mirror of
https://github.com/MAKS-IT-COM/maksit-webui.git
synced 2026-08-15 09:58:09 +02:00
(feature): release as unified npm package @maks-it.com/webui, deepDelta fixes
Some checks failed
Storybook tests / storybook-tests (push) Has been cancelled
Some checks failed
Storybook tests / storybook-tests (push) Has been cancelled
This commit is contained in:
parent
b74e9250a7
commit
25ae18bab6
@ -2,6 +2,7 @@
|
||||
"$schema": "homelab-maksit-skills-manifest-v1",
|
||||
"skillsRoot": "E:\\Users\\maksym\\source\\repos\\private\\homelab\\ai\\skills",
|
||||
"skills": [
|
||||
"common/maksit-webui",
|
||||
"common/react-typescript",
|
||||
"common/maksit-repo-maintenance",
|
||||
"local-ollama"
|
||||
|
||||
@ -6,8 +6,13 @@ alwaysApply: true
|
||||
|
||||
# MaksIT skills (maksit-webui)
|
||||
|
||||
1. `E:\Users\maksym\source\repos\private\homelab\ai\skills\common\react-typescript\SKILL.md`
|
||||
2. `E:\Users\maksym\source\repos\private\homelab\ai\skills\common\maksit-repo-maintenance\SKILL.md`
|
||||
3. `E:\Users\maksym\source\repos\private\homelab\ai\skills\local-ollama\SKILL.md` — local Ollama offload (`@local-ollama`)
|
||||
1. `E:\Users\maksym\source\repos\private\homelab\ai\skills\common\maksit-webui\SKILL.md` — `@maks-it.com/webui` ↔ **MaksIT.Core** + **maksit-identity-hub** + product backends (PATCH, OAuth, ACL)
|
||||
2. `E:\Users\maksym\source\repos\private\homelab\ai\skills\common\react-typescript\SKILL.md`
|
||||
3. `E:\Users\maksym\source\repos\private\homelab\ai\skills\common\maksit-repo-maintenance\SKILL.md`
|
||||
4. `E:\Users\maksym\source\repos\private\homelab\ai\skills\local-ollama\SKILL.md` — `@local-ollama`
|
||||
|
||||
Before changing `src/` library source: read **maksit-webui** skill; grep **maksit-core** and **maksit-identity-hub** as needed. Run `npm run build` in `src/` after source changes.
|
||||
|
||||
Shortcuts: `c:\Users\maksym\Desktop\maksit-core.lnk`, `c:\Users\maksym\Desktop\maksit-identity-hub.lnk`
|
||||
|
||||
Manifest: `.cursor/maksit-skills.json`.
|
||||
2
.gitignore
vendored
2
.gitignore
vendored
@ -267,6 +267,8 @@ __pycache__/
|
||||
node_modules/
|
||||
dist/
|
||||
coverage/
|
||||
src/coverage/
|
||||
src/dist-test-dts/
|
||||
storybook-static/
|
||||
*.tsbuildinfo
|
||||
.DS_Store
|
||||
|
||||
4
.vscode/settings.json
vendored
4
.vscode/settings.json
vendored
@ -1,4 +1,6 @@
|
||||
{
|
||||
"typescript.tsdk": "src/node_modules/typescript/lib",
|
||||
"typescript.enablePromptUseWorkspaceTsdk": true
|
||||
"typescript.enablePromptUseWorkspaceTsdk": true,
|
||||
"terminal.integrated.cwd": "${workspaceFolder}/src",
|
||||
"npm.packageManager": "npm"
|
||||
}
|
||||
|
||||
@ -1,12 +1,18 @@
|
||||
# Agent instructions (maksit-webui)
|
||||
|
||||
Read **[maksit-webui](E:\Users\maksym\source\repos\private\homelab\ai\skills\common\maksit-webui\SKILL.md)** before changing `src/` library source or shared npm packages. It covers alignment with **MaksIT.Core**, **maksit-identity-hub**, **maksit-results**, and product backends.
|
||||
|
||||
Complementary skills (no precedence):
|
||||
|
||||
| Skill | Path |
|
||||
|-------|------|
|
||||
| maksit-webui | [SKILL.md](E:\Users\maksym\source\repos\private\homelab\ai\skills\common\maksit-webui\SKILL.md) |
|
||||
| react-typescript | [SKILL.md](E:\Users\maksym\source\repos\private\homelab\ai\skills\common\react-typescript\SKILL.md) |
|
||||
| maksit-repo-maintenance | [SKILL.md](E:\Users\maksym\source\repos\private\homelab\ai\skills\common\maksit-repo-maintenance\SKILL.md) |
|
||||
(E:\Users\maksym\source\repos\private\homelab\ai\skills\common\maksit-repo-maintenance\SKILL.md) |
|
||||
| local-ollama | [SKILL.md](E:\Users\maksym\source\repos\private\homelab\ai\skills\local-ollama\SKILL.md) |
|
||||
|
||||
Manifest: `.cursor/maksit-skills.json`.
|
||||
|
||||
**Shortcuts:** `c:\Users\maksym\Desktop\maksit-core.lnk`, `c:\Users\maksym\Desktop\maksit-identity-hub.lnk`
|
||||
|
||||
**Build rule:** after editing `src/` library source (`contracts/`, `core/`, `components/`), run `npm run build` in `src/` before typechecking consumers.
|
||||
|
||||
24
CHANGELOG.md
24
CHANGELOG.md
@ -4,6 +4,30 @@ All notable changes to this project will be documented in this file.
|
||||
|
||||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||
|
||||
## [0.4.0] - 2026-07-07
|
||||
|
||||
### Changed
|
||||
|
||||
- **Breaking:** merged `@maks-it.com/webui-contracts`, `@maks-it.com/webui-core`, and `@maks-it.com/webui-components` into a single published package **`@maks-it.com/webui`**. Host apps install one package and import everything from `@maks-it.com/webui` (see `assets/docs/NPM_CONSUMPTION.md` migration notes).
|
||||
- **Breaking:** `src/` is now the npm package root — `src/package.json` publishes as `@maks-it.com/webui`; npm workspaces and `src/packages/*` nesting removed.
|
||||
- Source layout: `contracts/`, `core/`, and `components/` live directly under `src/` (internal organization only; no subpath exports).
|
||||
- Release pipeline (`utils/engines/release/scriptSettings.json`) publishes one package; `NpmReleaseVersion.syncWorkspaceVersions` disabled.
|
||||
- Jest, Vitest, and Storybook configs updated for the flat `src/` layout (`@webui/*` aliases point at `src/{contracts,core,components}`).
|
||||
- VS Code/Cursor: TypeScript SDK and integrated terminal default to `src/`.
|
||||
- `src/coverage/` explicitly gitignored; generated coverage is no longer tracked (README badges remain under `assets/badges/`).
|
||||
|
||||
### Removed
|
||||
|
||||
- `@maks-it.com/webui-contracts`, `@maks-it.com/webui-core`, and `@maks-it.com/webui-components` as separate npm packages (superseded by `@maks-it.com/webui`).
|
||||
- `src/packages/` workspace layout and per-package `package.json` files.
|
||||
- Repo-root `tsconfig.json` and stray `node_modules/` (tooling and dependencies live under `src/` only).
|
||||
|
||||
## [0.3.5] - 2026-07-06
|
||||
|
||||
### Fixed
|
||||
|
||||
- `ENTITY_SCOPES_ARRAY_POLICY`: synthetic identity is now `{entityId}-{entityType}` (not including `scope`), so adding an application scope alongside an existing organization scope produces a correct `AddToCollection` delta, and permission changes on id-less rows update in place via `_deltaId`.
|
||||
|
||||
## [0.3.4] - 2026-07-06
|
||||
|
||||
### Added
|
||||
|
||||
18
README.md
18
README.md
@ -4,15 +4,13 @@
|
||||
|
||||
Shared React UI library for **maksit-certs-ui** and **maksit-vault** WebUI apps.
|
||||
|
||||
## Packages
|
||||
## Package
|
||||
|
||||
| npm package | Description |
|
||||
|-------------|-------------|
|
||||
| `@maks-it.com/webui-contracts` | Shared TypeScript contracts (paging, gallery types, patch ops, scopes) |
|
||||
| `@maks-it.com/webui-core` | Utilities (`deepDelta`, enum helpers, ACL parsers) and `useFormState` |
|
||||
| `@maks-it.com/webui-components` | React components, layout, editors, DataTable, auth shell |
|
||||
| `@maks-it.com/webui` | Contracts, utilities (`deepDelta`, hooks, HTTP, SignalR), and React components |
|
||||
|
||||
Source lives under `src/` (npm workspaces). Release automation lives under `utils/` (from [maksit-repoutils](https://github.com/MAKS-IT-COM/maksit-repoutils)).
|
||||
Source lives under `src/` (`@maks-it.com/webui` — `contracts/`, `core/`, `components/`). Release automation lives under `utils/`.
|
||||
|
||||
## Local development
|
||||
|
||||
@ -24,7 +22,7 @@ npm test
|
||||
npm run storybook
|
||||
```
|
||||
|
||||
**Storybook** (`npm run storybook`) runs a local catalog of `@maks-it.com/webui-components` with Tailwind, React Router, autodocs, a11y checks, and **Vitest component tests** (testing widget + `npm run test-storybook`). Stories live under `src/stories/components/` (mirroring component folders); see `src/stories/README.md` for story conventions and testing.
|
||||
**Storybook** (`npm run storybook`) runs a local component catalog with Tailwind, React Router, autodocs, a11y checks, and **Vitest component tests** (testing widget + `npm run test-storybook`). Stories live under `src/stories/components/`; see `src/stories/README.md`.
|
||||
|
||||
Tests and coverage badges: **`utils\Invoke-TestEngine.bat`** (plugin config in `utils\engines\test\scriptSettings.json`; uses `NpmJestTest`).
|
||||
|
||||
@ -38,21 +36,21 @@ Configured plugins (see `utils\engines\release\scriptSettings.json`):
|
||||
|
||||
| Plugin | Role |
|
||||
|--------|------|
|
||||
| `NpmReleaseVersion` | Read semver from `src/package.json`; sync `packages/*/package.json` |
|
||||
| `NpmReleaseVersion` | Read semver from `src/package.json` |
|
||||
| `NpmBuild` | `npm ci` + `npm run build` |
|
||||
| `ReleasePublishGuard` | Branch/tag checks before publish |
|
||||
| `GitHub` | GitHub release (optional; set `GitHub` env var) |
|
||||
| `NpmPublish` | Publish workspace packages in dependency order |
|
||||
| `NpmPublish` | Publish `@maks-it.com/webui` |
|
||||
|
||||
Refresh shared utils from repoutils: **`utils\Update-RepoUtils.bat`**.
|
||||
|
||||
## Consume in product repos
|
||||
|
||||
```bash
|
||||
npm install @maks-it.com/webui-contracts @maks-it.com/webui-core @maks-it.com/webui-components
|
||||
npm install @maks-it.com/webui
|
||||
```
|
||||
|
||||
Wrap the app with `WebUiProvider` and pass axios/redux adapters — see [assets/docs/NPM_CONSUMPTION.md](assets/docs/NPM_CONSUMPTION.md).
|
||||
See [assets/docs/NPM_CONSUMPTION.md](assets/docs/NPM_CONSUMPTION.md).
|
||||
|
||||
## License
|
||||
|
||||
|
||||
@ -1,21 +1,21 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="147.5" height="20" role="img" aria-label="Branch Coverage: 78%">
|
||||
<title>Branch Coverage: 78%</title>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="150" height="20" role="img" aria-label="Branch Coverage: 78.2%">
|
||||
<title>Branch Coverage: 78.2%</title>
|
||||
<linearGradient id="s" x2="0" y2="100%">
|
||||
<stop offset="0" stop-color="#bbb" stop-opacity=".1"/>
|
||||
<stop offset="1" stop-opacity=".1"/>
|
||||
</linearGradient>
|
||||
<clipPath id="r">
|
||||
<rect width="147.5" height="20" rx="3" fill="#fff"/>
|
||||
<rect width="150" height="20" rx="3" fill="#fff"/>
|
||||
</clipPath>
|
||||
<g clip-path="url(#r)">
|
||||
<rect width="107.5" height="20" fill="#555"/>
|
||||
<rect x="107.5" width="40" height="20" fill="#97ca00"/>
|
||||
<rect width="147.5" height="20" fill="url(#s)"/>
|
||||
<rect x="107.5" width="42.5" height="20" fill="#97ca00"/>
|
||||
<rect width="150" height="20" fill="url(#s)"/>
|
||||
</g>
|
||||
<g fill="#fff" text-anchor="middle" font-family="Verdana,Geneva,DejaVu Sans,sans-serif" text-rendering="geometricPrecision" font-size="11">
|
||||
<text aria-hidden="true" x="53.75" y="15" fill="#010101" fill-opacity=".3">Branch Coverage</text>
|
||||
<text x="53.75" y="14" fill="#fff">Branch Coverage</text>
|
||||
<text aria-hidden="true" x="127.5" y="15" fill="#010101" fill-opacity=".3">78%</text>
|
||||
<text x="127.5" y="14" fill="#fff">78%</text>
|
||||
<text aria-hidden="true" x="128.75" y="15" fill="#010101" fill-opacity=".3">78.2%</text>
|
||||
<text x="128.75" y="14" fill="#fff">78.2%</text>
|
||||
</g>
|
||||
</svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 1.0 KiB After Width: | Height: | Size: 1.0 KiB |
@ -1,5 +1,5 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="137" height="20" role="img" aria-label="Line Coverage: 82.2%">
|
||||
<title>Line Coverage: 82.2%</title>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="137" height="20" role="img" aria-label="Line Coverage: 82.5%">
|
||||
<title>Line Coverage: 82.5%</title>
|
||||
<linearGradient id="s" x2="0" y2="100%">
|
||||
<stop offset="0" stop-color="#bbb" stop-opacity=".1"/>
|
||||
<stop offset="1" stop-opacity=".1"/>
|
||||
@ -15,7 +15,7 @@
|
||||
<g fill="#fff" text-anchor="middle" font-family="Verdana,Geneva,DejaVu Sans,sans-serif" text-rendering="geometricPrecision" font-size="11">
|
||||
<text aria-hidden="true" x="47.25" y="15" fill="#010101" fill-opacity=".3">Line Coverage</text>
|
||||
<text x="47.25" y="14" fill="#fff">Line Coverage</text>
|
||||
<text aria-hidden="true" x="115.75" y="15" fill="#010101" fill-opacity=".3">82.2%</text>
|
||||
<text x="115.75" y="14" fill="#fff">82.2%</text>
|
||||
<text aria-hidden="true" x="115.75" y="15" fill="#010101" fill-opacity=".3">82.5%</text>
|
||||
<text x="115.75" y="14" fill="#fff">82.5%</text>
|
||||
</g>
|
||||
</svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 1.0 KiB After Width: | Height: | Size: 1.0 KiB |
@ -1,5 +1,5 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="150" height="20" role="img" aria-label="Method Coverage: 62.4%">
|
||||
<title>Method Coverage: 62.4%</title>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="150" height="20" role="img" aria-label="Method Coverage: 58.2%">
|
||||
<title>Method Coverage: 58.2%</title>
|
||||
<linearGradient id="s" x2="0" y2="100%">
|
||||
<stop offset="0" stop-color="#bbb" stop-opacity=".1"/>
|
||||
<stop offset="1" stop-opacity=".1"/>
|
||||
@ -9,13 +9,13 @@
|
||||
</clipPath>
|
||||
<g clip-path="url(#r)">
|
||||
<rect width="107.5" height="20" fill="#555"/>
|
||||
<rect x="107.5" width="42.5" height="20" fill="#97ca00"/>
|
||||
<rect x="107.5" width="42.5" height="20" fill="#a4a61d"/>
|
||||
<rect width="150" height="20" fill="url(#s)"/>
|
||||
</g>
|
||||
<g fill="#fff" text-anchor="middle" font-family="Verdana,Geneva,DejaVu Sans,sans-serif" text-rendering="geometricPrecision" font-size="11">
|
||||
<text aria-hidden="true" x="53.75" y="15" fill="#010101" fill-opacity=".3">Method Coverage</text>
|
||||
<text x="53.75" y="14" fill="#fff">Method Coverage</text>
|
||||
<text aria-hidden="true" x="128.75" y="15" fill="#010101" fill-opacity=".3">62.4%</text>
|
||||
<text x="128.75" y="14" fill="#fff">62.4%</text>
|
||||
<text aria-hidden="true" x="128.75" y="15" fill="#010101" fill-opacity=".3">58.2%</text>
|
||||
<text x="128.75" y="14" fill="#fff">58.2%</text>
|
||||
</g>
|
||||
</svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 1.0 KiB After Width: | Height: | Size: 1.0 KiB |
@ -1,16 +1,29 @@
|
||||
# Consuming @maks-it.com/webui-* in Certs UI / Vault
|
||||
# Consuming `@maks-it.com/webui` in Certs UI / Vault
|
||||
|
||||
Install:
|
||||
|
||||
```bash
|
||||
npm install @maks-it.com/webui-contracts @maks-it.com/webui-core @maks-it.com/webui-components
|
||||
npm install @maks-it.com/webui
|
||||
npm install react react-dom react-router-dom lucide-react @tanstack/react-table react-virtualized axios @microsoft/signalr zod
|
||||
```
|
||||
|
||||
Example imports:
|
||||
|
||||
```tsx
|
||||
import {
|
||||
WebUiProvider,
|
||||
Loader,
|
||||
Authorization,
|
||||
DataTable,
|
||||
createColumns,
|
||||
deepDelta,
|
||||
PatchOperation,
|
||||
} from '@maks-it.com/webui'
|
||||
```
|
||||
|
||||
Wrap the app:
|
||||
|
||||
```tsx
|
||||
import { WebUiProvider, Loader, Authorization } from '@maks-it.com/webui-components'
|
||||
|
||||
<WebUiProvider
|
||||
api={{
|
||||
getData: (url) => getData(url),
|
||||
@ -39,9 +52,27 @@ import { WebUiProvider, Loader, Authorization } from '@maks-it.com/webui-compone
|
||||
</WebUiProvider>
|
||||
```
|
||||
|
||||
## API differences vs copied local folders
|
||||
## Migration from `@maks-it.com/webui-*`
|
||||
|
||||
Replace three package installs with one:
|
||||
|
||||
```diff
|
||||
- npm install @maks-it.com/webui-contracts @maks-it.com/webui-core @maks-it.com/webui-components
|
||||
+ npm install @maks-it.com/webui
|
||||
```
|
||||
|
||||
Update imports:
|
||||
|
||||
```diff
|
||||
- import { PatchOperation } from '@maks-it.com/webui-contracts'
|
||||
- import { deepDelta } from '@maks-it.com/webui-core'
|
||||
- import { DataTable } from '@maks-it.com/webui-components'
|
||||
+ import { PatchOperation, deepDelta, DataTable } from '@maks-it.com/webui'
|
||||
```
|
||||
|
||||
## API notes
|
||||
|
||||
- `RemoteSelectBoxComponent`: use `searchRoute` (absolute API path string) instead of `apiRoute: ApiRoutes`.
|
||||
- `SecretComponent`: pass `generateSecretRoute` when `enableGenerate` is true.
|
||||
- ACL: generic `parseAclEntry` / `parseAclEntries` from `@maks-it.com/webui-core`; per-app entity maps and `parse*AclEntries` live in each WebUI project (`models/acl.ts`).
|
||||
- Identity request types and Zod schemas (`LoginRequest` + `LoginRequestSchema`, `LogoutRequest` + `LogoutRequestSchema`, `RefreshTokenRequest` + `RefreshTokenRequestSchema`) live in `@maks-it.com/webui-contracts`.
|
||||
- ACL: generic `parseAclEntry` / `parseAclEntries` from `@maks-it.com/webui`; per-app entity maps and `parse*AclEntries` live in each WebUI project (`models/acl.ts`).
|
||||
- Identity request types and Zod schemas (`LoginRequest` + `LoginRequestSchema`, `LogoutRequest` + `LogoutRequestSchema`, `RefreshTokenRequest` + `RefreshTokenRequestSchema`) are exported from `@maks-it.com/webui`.
|
||||
|
||||
@ -1,19 +1,19 @@
|
||||
# Publishing `@maks-it.com/webui-*` to npm
|
||||
# Publishing `@maks-it.com/webui` to npm
|
||||
|
||||
Packages are published under the **`@maks-it.com` scope** to [registry.npmjs.org](https://registry.npmjs.org), managed from the [maks-it.com npm org](https://www.npmjs.com/settings/maks-it.com/packages).
|
||||
The library is published under the **`@maks-it.com` scope** to [registry.npmjs.org](https://registry.npmjs.org), managed from the [maks-it.com npm org](https://www.npmjs.com/settings/maks-it.com/packages).
|
||||
|
||||
Published packages:
|
||||
Published package:
|
||||
|
||||
| Package | npm |
|
||||
|---------|-----|
|
||||
| `@maks-it.com/webui-contracts` | https://www.npmjs.com/package/@maks-it.com/webui-contracts |
|
||||
| `@maks-it.com/webui-core` | https://www.npmjs.com/package/@maks-it.com/webui-core |
|
||||
| `@maks-it.com/webui-components` | https://www.npmjs.com/package/@maks-it.com/webui-components |
|
||||
| `@maks-it.com/webui` | https://www.npmjs.com/package/@maks-it.com/webui |
|
||||
|
||||
> **Note:** `@maks-it.com/webui-contracts`, `@maks-it.com/webui-core`, and `@maks-it.com/webui-components` were merged into `@maks-it.com/webui` starting at **0.4.0**. Migrate host apps to the single package.
|
||||
|
||||
## One-time npm setup
|
||||
|
||||
1. Sign in at https://www.npmjs.com/ with the **maks-it.com** org account.
|
||||
2. Confirm the **`@maks-it.com` scope** exists under [Packages](https://www.npmjs.com/settings/maks-it.com/packages). The org name `maks-it.com` is the npm scope for scoped packages.
|
||||
2. Confirm the **`@maks-it.com` scope** exists under [Packages](https://www.npmjs.com/settings/maks-it.com/packages).
|
||||
3. Create an **Automation** token (recommended) or Granular Access token with **Publish** on `@maks-it.com/*`:
|
||||
- https://www.npmjs.com/settings/maks-it.com/tokens
|
||||
4. Store the token for release tooling:
|
||||
@ -23,9 +23,9 @@ Published packages:
|
||||
//registry.npmjs.org/:_authToken=YOUR_TOKEN
|
||||
```
|
||||
|
||||
Scoped packages must use **`--access public`** (already configured in each package `publishConfig`).
|
||||
Scoped packages must use **`--access public`** (already configured in package `publishConfig`).
|
||||
|
||||
## Manual first publish (0.1.0)
|
||||
## Manual publish
|
||||
|
||||
From the repo root:
|
||||
|
||||
@ -33,19 +33,13 @@ From the repo root:
|
||||
cd src
|
||||
npm ci
|
||||
npm run build
|
||||
npm publish -w @maks-it.com/webui-contracts --access public
|
||||
npm publish -w @maks-it.com/webui-core --access public
|
||||
npm publish -w @maks-it.com/webui-components --access public
|
||||
npm publish -w @maks-it.com/webui --access public
|
||||
```
|
||||
|
||||
Order matters: **contracts → core → components**.
|
||||
|
||||
Verify:
|
||||
|
||||
```powershell
|
||||
npm view @maks-it.com/webui-contracts version
|
||||
npm view @maks-it.com/webui-core version
|
||||
npm view @maks-it.com/webui-components version
|
||||
npm view @maks-it.com/webui version
|
||||
```
|
||||
|
||||
## Release pipeline (recommended)
|
||||
@ -53,19 +47,17 @@ npm view @maks-it.com/webui-components version
|
||||
Use **`utils\Invoke-ReleasePackage-Single.bat`** (or `pwsh utils\engines\release\Invoke-ReleasePackage.ps1`):
|
||||
|
||||
1. Bump version in `src/package.json` (or tag drives `NpmReleaseVersion`).
|
||||
2. Tag `HEAD` with exact semver, e.g. `git tag v0.2.0 && git push origin v0.2.0`.
|
||||
2. Tag `HEAD` with exact semver, e.g. `git tag v0.4.0 && git push origin v0.4.0`.
|
||||
3. Set `$env:Npm` and run the release engine.
|
||||
|
||||
`utils\engines\release\scriptSettings.json` runs `NpmReleaseVersion`, `NpmBuild`, `ReleasePublishGuard`, optional `GitHub`, then `NpmPublish` in dependency order.
|
||||
`utils\engines\release\scriptSettings.json` runs `NpmReleaseVersion`, `NpmBuild`, `ReleasePublishGuard`, optional `GitHub`, then `NpmPublish`.
|
||||
|
||||
## After publish — Certs UI / Vault
|
||||
|
||||
In each WebUI app (`MaksIT.WebUI/package.json`):
|
||||
|
||||
```json
|
||||
"@maks-it.com/webui-contracts": "^0.1.0",
|
||||
"@maks-it.com/webui-core": "^0.1.0",
|
||||
"@maks-it.com/webui-components": "^0.1.0"
|
||||
"@maks-it.com/webui": "^0.4.0"
|
||||
```
|
||||
|
||||
Then refresh the lockfile:
|
||||
|
||||
6
src/.gitignore
vendored
Normal file
6
src/.gitignore
vendored
Normal file
@ -0,0 +1,6 @@
|
||||
coverage/
|
||||
dist/
|
||||
dist-test-dts/
|
||||
storybook-static/
|
||||
*.tsbuildinfo
|
||||
*.tgz
|
||||
@ -9,6 +9,12 @@ const srcDir = join(storybookDir, '..')
|
||||
const config: StorybookConfig = {
|
||||
stories: ['../stories/**/*.stories.@(ts|tsx)'],
|
||||
staticDirs: ['../public'],
|
||||
typescript: {
|
||||
reactDocgen: 'react-docgen-typescript',
|
||||
reactDocgenTypescriptOptions: {
|
||||
tsconfigPath: join(srcDir, 'tsconfig.json'),
|
||||
},
|
||||
},
|
||||
addons: [
|
||||
getAbsolutePath("@storybook/addon-docs"),
|
||||
getAbsolutePath("@storybook/addon-a11y"),
|
||||
@ -29,9 +35,9 @@ const config: StorybookConfig = {
|
||||
...config.resolve,
|
||||
alias: {
|
||||
...(config.resolve?.alias as Record<string, string> | undefined),
|
||||
'@webui/components': join(srcDir, 'packages/components/src'),
|
||||
'@webui/contracts': join(srcDir, 'packages/contracts/src'),
|
||||
'@webui/core': join(srcDir, 'packages/core/src'),
|
||||
'@webui/components': join(srcDir, 'components'),
|
||||
'@webui/contracts': join(srcDir, 'contracts'),
|
||||
'@webui/core': join(srcDir, 'core'),
|
||||
},
|
||||
}
|
||||
return config
|
||||
|
||||
@ -1,21 +0,0 @@
|
||||
{
|
||||
"extends": "../tsconfig.base.json",
|
||||
"compilerOptions": {
|
||||
"noEmit": true,
|
||||
"declaration": false,
|
||||
"declarationMap": false,
|
||||
"rootDir": "..",
|
||||
"paths": {
|
||||
"@webui/components": ["../packages/components/src"],
|
||||
"@webui/contracts": ["../packages/contracts/src"],
|
||||
"@webui/core": ["../packages/core/src"],
|
||||
"@webui/components/*": ["../packages/components/src/*"],
|
||||
"@webui/contracts/*": ["../packages/contracts/src/*"],
|
||||
"@webui/core/*": ["../packages/core/src/*"]
|
||||
}
|
||||
},
|
||||
"include": [
|
||||
"./**/*",
|
||||
"../stories/**/*"
|
||||
]
|
||||
}
|
||||
54
src/README.md
Normal file
54
src/README.md
Normal file
@ -0,0 +1,54 @@
|
||||
# @maks-it.com/webui
|
||||
|
||||
Shared TypeScript contracts, utilities, hooks, and React components for MaksIT WebUI apps (Certs UI, Vault WebUI, CICD, and related products).
|
||||
|
||||
## Install
|
||||
|
||||
```bash
|
||||
npm install @maks-it.com/webui
|
||||
npm install react react-dom react-router-dom lucide-react @tanstack/react-table react-virtualized axios @microsoft/signalr zod
|
||||
```
|
||||
|
||||
Peer dependencies must be installed in the host app.
|
||||
|
||||
## Contents
|
||||
|
||||
| Area | Examples |
|
||||
|------|----------|
|
||||
| Contracts | `PagedRequest`, `PatchOperation`, `LoginRequestSchema`, OAuth DTOs |
|
||||
| Core | `deepDelta`, `useFormState`, `createWebUiHttpClient`, `useWebUiHub`, ACL parsers |
|
||||
| Components | `DataTable`, `Layout`, editors, `ExternalLoginButtons`, `IdpLoginCallbackHandler` |
|
||||
|
||||
## Example — imports
|
||||
|
||||
```tsx
|
||||
import {
|
||||
PatchOperation,
|
||||
deepDelta,
|
||||
deltaHasOperations,
|
||||
useFormState,
|
||||
DataTable,
|
||||
createColumns,
|
||||
} from '@maks-it.com/webui'
|
||||
```
|
||||
|
||||
## Example — PATCH delta
|
||||
|
||||
```ts
|
||||
import { deepDelta, deltaHasOperations, ENTITY_SCOPES_ARRAY_POLICY } from '@maks-it.com/webui'
|
||||
|
||||
const delta = deepDelta(formState, backupState, {
|
||||
arrays: { entityScopes: ENTITY_SCOPES_ARRAY_POLICY },
|
||||
})
|
||||
if (deltaHasOperations(delta)) {
|
||||
await api.patch('/resource', delta)
|
||||
}
|
||||
```
|
||||
|
||||
## Repository
|
||||
|
||||
[github.com/MAKS-IT-COM/maksit-webui](https://github.com/MAKS-IT-COM/maksit-webui) — `src/`
|
||||
|
||||
## License
|
||||
|
||||
MIT
|
||||
@ -1,7 +1,7 @@
|
||||
import React, { useState, useMemo, useRef, useEffect } from 'react'
|
||||
import { AutoSizer, MultiGrid, GridCellProps } from 'react-virtualized'
|
||||
|
||||
import { mapPagedToDataTable, type DataTablePageView, type PagedResponse } from '@maks-it.com/webui-core'
|
||||
import { mapPagedToDataTable, type DataTablePageView, type PagedResponse } from '@webui/core'
|
||||
import { Plus, Trash2, Edit } from 'lucide-react'
|
||||
import { debounce, colSpanClass, type GridColSpan } from '../../functions'
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
import { useEffect, useMemo, useState } from 'react'
|
||||
import { formatISODateString } from '@maks-it.com/webui-core'
|
||||
import { formatISODateString } from '@webui/core'
|
||||
|
||||
interface NormalLabelProps {
|
||||
type: 'normal'
|
||||
@ -1,4 +1,4 @@
|
||||
import type { SearchEntityScopeEntry } from '@maks-it.com/webui-contracts'
|
||||
import type { SearchEntityScopeEntry } from '@webui/contracts'
|
||||
|
||||
export interface EntityScopesSummaryProps<TScopeEntityType extends number = number> {
|
||||
entries: SearchEntityScopeEntry<TScopeEntityType>[]
|
||||
@ -6,7 +6,7 @@ import {
|
||||
getDaysInMonth,
|
||||
addMonths,
|
||||
subMonths,
|
||||
} from '@maks-it.com/webui-core'
|
||||
} from '@webui/core'
|
||||
import { CircleX } from 'lucide-react'
|
||||
import { ButtonComponent } from './ButtonComponent'
|
||||
import { TextBoxComponent } from './TextBoxComponent'
|
||||
@ -1,7 +1,7 @@
|
||||
import { useState, useCallback, ChangeEvent, useEffect, useRef } from 'react'
|
||||
import type { PagedRequest } from '@maks-it.com/webui-contracts'
|
||||
import type { SearchResponseBase } from '@maks-it.com/webui-contracts'
|
||||
import { deepEqual } from '@maks-it.com/webui-core'
|
||||
import type { PagedRequest } from '@webui/contracts'
|
||||
import type { SearchResponseBase } from '@webui/contracts'
|
||||
import { deepEqual } from '@webui/core'
|
||||
import type { GridColSpan } from '../../functions'
|
||||
import { SelectBoxComponent } from './SelectBoxComponent'
|
||||
|
||||
59
src/components/oauth/ExternalLoginButtons.tsx
Normal file
59
src/components/oauth/ExternalLoginButtons.tsx
Normal file
@ -0,0 +1,59 @@
|
||||
import type { FC, ReactNode } from 'react'
|
||||
import { LoginProviderExternal } from '@webui/contracts'
|
||||
|
||||
export interface ExternalLoginProviderConfig {
|
||||
provider: LoginProviderExternal
|
||||
label: string
|
||||
iconSrc?: string
|
||||
}
|
||||
|
||||
export interface ExternalLoginButtonsProps {
|
||||
providers: ExternalLoginProviderConfig[]
|
||||
onSelect: (provider: LoginProviderExternal) => void
|
||||
className?: string
|
||||
renderButton?: (props: {
|
||||
provider: LoginProviderExternal
|
||||
label: string
|
||||
iconSrc?: string
|
||||
onClick: () => void
|
||||
}) => ReactNode
|
||||
}
|
||||
|
||||
const defaultRenderButton = ({
|
||||
label,
|
||||
iconSrc,
|
||||
onClick,
|
||||
}: {
|
||||
label: string
|
||||
iconSrc?: string
|
||||
onClick: () => void
|
||||
}) => (
|
||||
<button
|
||||
type="button"
|
||||
className="w-full flex items-center justify-center gap-2 rounded border border-gray-300 bg-white px-4 py-2 text-sm hover:bg-gray-50"
|
||||
onClick={onClick}
|
||||
>
|
||||
{iconSrc && <img src={iconSrc} alt="" className="h-5 w-5" />}
|
||||
<span>{label}</span>
|
||||
</button>
|
||||
)
|
||||
|
||||
const ExternalLoginButtons: FC<ExternalLoginButtonsProps> = ({
|
||||
providers,
|
||||
onSelect,
|
||||
className,
|
||||
renderButton = defaultRenderButton,
|
||||
}) => (
|
||||
<div className={className ?? 'flex flex-col gap-2'}>
|
||||
{providers.map(({ provider, label, iconSrc }) =>
|
||||
renderButton({
|
||||
provider,
|
||||
label,
|
||||
iconSrc,
|
||||
onClick: () => onSelect(provider),
|
||||
}),
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
|
||||
export { ExternalLoginButtons }
|
||||
14
src/components/oauth/IdpLoginCallbackHandler.tsx
Normal file
14
src/components/oauth/IdpLoginCallbackHandler.tsx
Normal file
@ -0,0 +1,14 @@
|
||||
import type { FC } from 'react'
|
||||
import { useIdpLoginCallback, type UseIdpLoginCallbackOptions } from '@webui/core'
|
||||
|
||||
export type IdpLoginCallbackHandlerProps = UseIdpLoginCallbackOptions
|
||||
|
||||
const IdpLoginCallbackHandler: FC<IdpLoginCallbackHandlerProps> = (props) => {
|
||||
useIdpLoginCallback(props)
|
||||
return null
|
||||
}
|
||||
|
||||
export { IdpLoginCallbackHandler }
|
||||
export type { LoginExternalExchangeResponse } from '@webui/contracts'
|
||||
/** @deprecated Use `LoginExternalExchangeResponse`. */
|
||||
export type { IdpRedeemLoginResponse } from '@webui/contracts'
|
||||
11
src/components/oauth/MailboxOAuthReturnHandler.tsx
Normal file
11
src/components/oauth/MailboxOAuthReturnHandler.tsx
Normal file
@ -0,0 +1,11 @@
|
||||
import type { FC } from 'react'
|
||||
import { useMailboxOAuthReturn, type UseMailboxOAuthReturnOptions } from '@webui/core'
|
||||
|
||||
export type MailboxOAuthReturnHandlerProps = UseMailboxOAuthReturnOptions
|
||||
|
||||
const MailboxOAuthReturnHandler: FC<MailboxOAuthReturnHandlerProps> = (props) => {
|
||||
useMailboxOAuthReturn(props)
|
||||
return null
|
||||
}
|
||||
|
||||
export { MailboxOAuthReturnHandler }
|
||||
15
src/components/oauth/index.ts
Normal file
15
src/components/oauth/index.ts
Normal file
@ -0,0 +1,15 @@
|
||||
export {
|
||||
ExternalLoginButtons,
|
||||
type ExternalLoginButtonsProps,
|
||||
type ExternalLoginProviderConfig,
|
||||
} from './ExternalLoginButtons'
|
||||
|
||||
export {
|
||||
IdpLoginCallbackHandler,
|
||||
type IdpLoginCallbackHandlerProps,
|
||||
} from './IdpLoginCallbackHandler'
|
||||
|
||||
export {
|
||||
MailboxOAuthReturnHandler,
|
||||
type MailboxOAuthReturnHandlerProps,
|
||||
} from './MailboxOAuthReturnHandler'
|
||||
@ -1,12 +1,12 @@
|
||||
import { boolean, intersection, number, object, record, string, type ZodType } from 'zod'
|
||||
import { boolean, intersection, number, object, string, type ZodType } from 'zod'
|
||||
import type { RequestModelBase } from './RequestModelBase'
|
||||
import { RequestModelBaseSchema } from './RequestModelBase'
|
||||
|
||||
/** Matches server `MaksIT.Core.Webapi.Models.PagedRequest` (camelCase JSON). */
|
||||
export interface PagedRequest extends RequestModelBase {
|
||||
pageSize?: number
|
||||
pageNumber?: number
|
||||
filters?: string
|
||||
collectionFilters?: Record<string, string>
|
||||
sortBy?: string
|
||||
isAscending?: boolean
|
||||
}
|
||||
@ -17,7 +17,6 @@ export const PagedRequestSchema: ZodType<PagedRequest> = intersection(
|
||||
pageSize: number().optional(),
|
||||
pageNumber: number().optional(),
|
||||
filters: string().optional(),
|
||||
collectionFilters: record(string(), string()).optional(),
|
||||
sortBy: string().optional(),
|
||||
isAscending: boolean().optional(),
|
||||
})
|
||||
11
src/contracts/SearchResponseBase.ts
Normal file
11
src/contracts/SearchResponseBase.ts
Normal file
@ -0,0 +1,11 @@
|
||||
import type { ResponseModelBase } from './ResponseModelBase'
|
||||
|
||||
/**
|
||||
* Minimal id + display label for remote select / paged search helpers.
|
||||
* Not a MaksIT.Core type — product `Search*Response` models add domain fields
|
||||
* (e.g. `username` on users, `description` on API keys). Map to `name` in the UI layer.
|
||||
*/
|
||||
export interface SearchResponseBase extends ResponseModelBase {
|
||||
id: string
|
||||
name: string
|
||||
}
|
||||
6
src/contracts/TrngResponse.ts
Normal file
6
src/contracts/TrngResponse.ts
Normal file
@ -0,0 +1,6 @@
|
||||
import type { ResponseModelBase } from './ResponseModelBase'
|
||||
|
||||
/** Matches `GET api/secret/generatesecret` anonymous response `{ secret }` (e.g. MaksIT.Vault). */
|
||||
export interface TrngResponse extends ResponseModelBase {
|
||||
secret: string
|
||||
}
|
||||
14
src/contracts/identity/logout/LogoutRequest.ts
Normal file
14
src/contracts/identity/logout/LogoutRequest.ts
Normal file
@ -0,0 +1,14 @@
|
||||
import { boolean, object, type ZodType } from 'zod'
|
||||
import type { RequestModelBase } from '../../RequestModelBase'
|
||||
import { RequestModelBaseSchema } from '../../RequestModelBase'
|
||||
|
||||
/** Matches product `Models/Identity/Logout/LogoutRequest` (e.g. MaksIT.CertsUI). */
|
||||
export interface LogoutRequest extends RequestModelBase {
|
||||
logoutFromAllDevices?: boolean
|
||||
}
|
||||
|
||||
export const LogoutRequestSchema: ZodType<LogoutRequest> = RequestModelBaseSchema.and(
|
||||
object({
|
||||
logoutFromAllDevices: boolean().optional(),
|
||||
})
|
||||
)
|
||||
9
src/contracts/oauth/EmailProtocol.ts
Normal file
9
src/contracts/oauth/EmailProtocol.ts
Normal file
@ -0,0 +1,9 @@
|
||||
/**
|
||||
* Mailbox email protocol flags for multi-step OAuth UI.
|
||||
* FiPlan/legacy FE shape — not in MaksIT.IdentityHub.Contracts.
|
||||
*/
|
||||
export enum EmailProtocol {
|
||||
Smtp = 0,
|
||||
Pop3 = 1,
|
||||
Imap = 2,
|
||||
}
|
||||
6
src/contracts/oauth/IdpRedeemLoginResponse.ts
Normal file
6
src/contracts/oauth/IdpRedeemLoginResponse.ts
Normal file
@ -0,0 +1,6 @@
|
||||
import type { LoginExternalExchangeResponse } from './LoginExternalExchangeResponse'
|
||||
|
||||
/**
|
||||
* @deprecated Use {@link LoginExternalExchangeResponse}. Legacy FiPlan.Auth snake_case shape removed.
|
||||
*/
|
||||
export type IdpRedeemLoginResponse = LoginExternalExchangeResponse
|
||||
16
src/contracts/oauth/LoginExternalExchangeResponse.ts
Normal file
16
src/contracts/oauth/LoginExternalExchangeResponse.ts
Normal file
@ -0,0 +1,16 @@
|
||||
import type { ResponseModelBase } from '../ResponseModelBase'
|
||||
|
||||
/**
|
||||
* Response from Identity Hub `POST login-external/redeem`.
|
||||
* Align with `MaksIT.IdentityHub.Contracts.LoginExternalExchangeResponse`.
|
||||
*/
|
||||
export interface LoginExternalExchangeResponse extends ResponseModelBase {
|
||||
provider: string
|
||||
subject: string
|
||||
email: string
|
||||
idToken: string
|
||||
accessToken: string
|
||||
refreshToken?: string
|
||||
expiresAt?: string
|
||||
postLogin?: string
|
||||
}
|
||||
23
src/contracts/oauth/LoginProviderExternal.ts
Normal file
23
src/contracts/oauth/LoginProviderExternal.ts
Normal file
@ -0,0 +1,23 @@
|
||||
/**
|
||||
* External identity provider for Identity Hub login (`login-external/challenge`).
|
||||
* Values match `MaksIT.IdentityHub.Engine.LoginProviderExternal` names (`Microsoft`, `Google`).
|
||||
*/
|
||||
export enum LoginProviderExternal {
|
||||
Microsoft = 'Microsoft',
|
||||
Google = 'Google',
|
||||
}
|
||||
|
||||
export const toAuthProviderName = (provider: LoginProviderExternal): string => provider
|
||||
|
||||
export const tryParseLoginProviderExternal = (
|
||||
value: string | null | undefined,
|
||||
): LoginProviderExternal | undefined => {
|
||||
if (!value)
|
||||
return undefined
|
||||
|
||||
const normalized = value.trim()
|
||||
if (normalized === LoginProviderExternal.Google || normalized === LoginProviderExternal.Microsoft)
|
||||
return normalized
|
||||
|
||||
return undefined
|
||||
}
|
||||
8
src/contracts/oauth/MailboxOAuthPending.ts
Normal file
8
src/contracts/oauth/MailboxOAuthPending.ts
Normal file
@ -0,0 +1,8 @@
|
||||
import type { EmailProtocol } from './EmailProtocol'
|
||||
|
||||
/** sessionStorage payload during multi-protocol mailbox OAuth (FE-only). */
|
||||
export interface MailboxOAuthPending {
|
||||
mailboxId: number
|
||||
protocols: EmailProtocol[]
|
||||
returnPath: string
|
||||
}
|
||||
7
src/contracts/oauth/MsalViewModel.ts
Normal file
7
src/contracts/oauth/MsalViewModel.ts
Normal file
@ -0,0 +1,7 @@
|
||||
import type { EmailProtocol } from './EmailProtocol'
|
||||
|
||||
/** FiPlan/legacy mailbox redeem payload — not Identity Hub `LoginExternalExchangeResponse`. */
|
||||
export interface MsalViewModel {
|
||||
code: string
|
||||
emailProtocol: EmailProtocol
|
||||
}
|
||||
18
src/contracts/oauth/RedeemLoginExternalRequest.ts
Normal file
18
src/contracts/oauth/RedeemLoginExternalRequest.ts
Normal file
@ -0,0 +1,18 @@
|
||||
import { object, string, type ZodType } from 'zod'
|
||||
import type { RequestModelBase } from '../RequestModelBase'
|
||||
import { RequestModelBaseSchema } from '../RequestModelBase'
|
||||
|
||||
/**
|
||||
* Body for Identity Hub `POST login-external/redeem`.
|
||||
* Align with `MaksIT.IdentityHub.Contracts.RedeemLoginExternalRequest`.
|
||||
*/
|
||||
export interface RedeemLoginExternalRequest extends RequestModelBase {
|
||||
code: string
|
||||
}
|
||||
|
||||
export const RedeemLoginExternalRequestSchema: ZodType<RedeemLoginExternalRequest> =
|
||||
RequestModelBaseSchema.and(
|
||||
object({
|
||||
code: string().min(1),
|
||||
}),
|
||||
)
|
||||
20
src/contracts/oauth/RefreshMailboxAccessTokenRequest.ts
Normal file
20
src/contracts/oauth/RefreshMailboxAccessTokenRequest.ts
Normal file
@ -0,0 +1,20 @@
|
||||
import { object, string, type ZodType } from 'zod'
|
||||
import type { RequestModelBase } from '../RequestModelBase'
|
||||
import { RequestModelBaseSchema } from '../RequestModelBase'
|
||||
|
||||
/**
|
||||
* Body for Identity Hub `POST login-external/refresh-mailbox`.
|
||||
* Align with `MaksIT.IdentityHub.Contracts.RefreshMailboxAccessTokenRequest`.
|
||||
*/
|
||||
export interface RefreshMailboxAccessTokenRequest extends RequestModelBase {
|
||||
provider: string
|
||||
refreshToken: string
|
||||
}
|
||||
|
||||
export const RefreshMailboxAccessTokenRequestSchema: ZodType<RefreshMailboxAccessTokenRequest> =
|
||||
RequestModelBaseSchema.and(
|
||||
object({
|
||||
provider: string().min(1),
|
||||
refreshToken: string().min(1),
|
||||
}),
|
||||
)
|
||||
9
src/contracts/oauth/RefreshMailboxAccessTokenResponse.ts
Normal file
9
src/contracts/oauth/RefreshMailboxAccessTokenResponse.ts
Normal file
@ -0,0 +1,9 @@
|
||||
import type { ResponseModelBase } from '../ResponseModelBase'
|
||||
|
||||
/**
|
||||
* Response from Identity Hub `POST login-external/refresh-mailbox`.
|
||||
* Align with `MaksIT.IdentityHub.Contracts.RefreshMailboxAccessTokenResponse`.
|
||||
*/
|
||||
export interface RefreshMailboxAccessTokenResponse extends ResponseModelBase {
|
||||
accessToken: string
|
||||
}
|
||||
9
src/contracts/oauth/ServerAuthenticationMethod.ts
Normal file
9
src/contracts/oauth/ServerAuthenticationMethod.ts
Normal file
@ -0,0 +1,9 @@
|
||||
/**
|
||||
* Mailbox server authentication method (OAuth2 vs login).
|
||||
* FiPlan/legacy FE shape — not in MaksIT.IdentityHub.Contracts.
|
||||
*/
|
||||
export enum ServerAuthenticationMethod {
|
||||
Default = 0,
|
||||
Login = 1,
|
||||
OAuth2 = 6,
|
||||
}
|
||||
37
src/contracts/oauth/index.ts
Normal file
37
src/contracts/oauth/index.ts
Normal file
@ -0,0 +1,37 @@
|
||||
export {
|
||||
LoginProviderExternal,
|
||||
toAuthProviderName,
|
||||
tryParseLoginProviderExternal,
|
||||
} from './LoginProviderExternal'
|
||||
|
||||
export { EmailProtocol } from './EmailProtocol'
|
||||
|
||||
export { ServerAuthenticationMethod } from './ServerAuthenticationMethod'
|
||||
|
||||
export type { MsalViewModel } from './MsalViewModel'
|
||||
|
||||
export type { LoginExternalExchangeResponse } from './LoginExternalExchangeResponse'
|
||||
|
||||
export type { RedeemLoginExternalRequest } from './RedeemLoginExternalRequest'
|
||||
export { RedeemLoginExternalRequestSchema } from './RedeemLoginExternalRequest'
|
||||
|
||||
export type { RefreshMailboxAccessTokenRequest } from './RefreshMailboxAccessTokenRequest'
|
||||
export { RefreshMailboxAccessTokenRequestSchema } from './RefreshMailboxAccessTokenRequest'
|
||||
|
||||
export type { RefreshMailboxAccessTokenResponse } from './RefreshMailboxAccessTokenResponse'
|
||||
|
||||
/** @deprecated Use `LoginExternalExchangeResponse`. */
|
||||
export type { IdpRedeemLoginResponse } from './IdpRedeemLoginResponse'
|
||||
|
||||
export type { MailboxOAuthPending } from './MailboxOAuthPending'
|
||||
|
||||
export {
|
||||
MAILBOX_OAUTH_STORAGE_KEY,
|
||||
MAILBOX_OAUTH_QUERY_FLAG,
|
||||
MAILBOX_OAUTH_PROCESSING_KEY_PREFIX,
|
||||
IDP_PROVIDER_STORAGE_KEY,
|
||||
IDENTITY_HUB_ROUTE_CHALLENGE,
|
||||
IDENTITY_HUB_ROUTE_REDEEM,
|
||||
IDENTITY_HUB_ROUTE_REFRESH_MAILBOX,
|
||||
IDENTITY_HUB_MAILBOX_PURPOSE,
|
||||
} from './oauthConstants'
|
||||
19
src/contracts/oauth/oauthConstants.ts
Normal file
19
src/contracts/oauth/oauthConstants.ts
Normal file
@ -0,0 +1,19 @@
|
||||
/** sessionStorage key while a multi-protocol mailbox OAuth flow is in progress. */
|
||||
export const MAILBOX_OAUTH_STORAGE_KEY = 'mailboxOAuth_pending'
|
||||
|
||||
/** Query flag on the OAuth redirect landing URL (`?mailboxOAuth=1`). */
|
||||
export const MAILBOX_OAUTH_QUERY_FLAG = 'mailboxOAuth'
|
||||
|
||||
/** sessionStorage prefix to dedupe concurrent code redemption for the same authorization code. */
|
||||
export const MAILBOX_OAUTH_PROCESSING_KEY_PREFIX = 'mailboxOAuth_processing_'
|
||||
|
||||
/** sessionStorage key for the last external login provider (optional diagnostics). */
|
||||
export const IDP_PROVIDER_STORAGE_KEY = 'ext_provider'
|
||||
|
||||
/** Identity Hub route segments (append to hub base URL). */
|
||||
export const IDENTITY_HUB_ROUTE_CHALLENGE = 'login-external/challenge'
|
||||
export const IDENTITY_HUB_ROUTE_REDEEM = 'login-external/redeem'
|
||||
export const IDENTITY_HUB_ROUTE_REFRESH_MAILBOX = 'login-external/refresh-mailbox'
|
||||
|
||||
/** Query value for mailbox OAuth challenge (`?purpose=mailbox`). Matches `HttpExternalLoginSessionContext`. */
|
||||
export const IDENTITY_HUB_MAILBOX_PURPOSE = 'mailbox'
|
||||
@ -1,4 +1,7 @@
|
||||
/** One entity scope line in search results (entity + CRUD permission flags). */
|
||||
/**
|
||||
* One entity scope line in search results (entity + CRUD permission flags).
|
||||
* Align with product `Models/Shared/Search/SearchEntityScopeEntry.cs` (certs-ui, vault).
|
||||
*/
|
||||
export interface SearchEntityScopeEntry<TScopeEntityType = number> {
|
||||
scopeEntityType: TScopeEntityType
|
||||
entityId: string
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user