@nsxbet/admin-sdk 0.7.1 → 0.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHECKLIST.md +48 -13
- package/README.md +24 -74
- package/dist/auth/client/bff.d.ts +38 -0
- package/dist/auth/client/bff.js +270 -0
- package/dist/auth/client/in-memory.d.ts +1 -1
- package/dist/auth/client/in-memory.js +2 -2
- package/dist/auth/client/index.d.ts +1 -1
- package/dist/auth/client/index.js +2 -2
- package/dist/auth/client/interface.d.ts +4 -4
- package/dist/auth/client/interface.js +1 -1
- package/dist/auth/components/LoginPage.d.ts +8 -0
- package/dist/auth/components/LoginPage.js +32 -0
- package/dist/auth/components/UserSelector.js +2 -2
- package/dist/auth/components/index.d.ts +2 -0
- package/dist/auth/components/index.js +1 -0
- package/dist/auth/index.d.ts +3 -2
- package/dist/auth/index.js +2 -2
- package/dist/components/AuthProvider.d.ts +3 -3
- package/dist/components/AuthProvider.js +25 -10
- package/dist/env.d.ts +17 -0
- package/dist/env.js +50 -0
- package/dist/hooks/useAuth.d.ts +3 -3
- package/dist/hooks/useAuth.js +1 -1
- package/dist/hooks/useFetch.js +6 -1
- package/dist/hooks/useI18n.js +2 -2
- package/dist/i18n/config.d.ts +2 -1
- package/dist/i18n/config.js +4 -3
- package/dist/i18n/index.d.ts +1 -1
- package/dist/i18n/index.js +1 -1
- package/dist/i18n/locales/en-US.json +7 -0
- package/dist/i18n/locales/es.json +7 -0
- package/dist/i18n/locales/pt-BR.json +7 -0
- package/dist/i18n/locales/ro.json +7 -0
- package/dist/index.d.ts +6 -5
- package/dist/index.js +5 -2
- package/dist/registry/client/http.js +6 -1
- package/dist/registry/client/in-memory.js +20 -5
- package/dist/registry/types/manifest.d.ts +5 -0
- package/dist/registry/types/manifest.js +4 -1
- package/dist/registry/types/module.d.ts +6 -2
- package/dist/sdk-version.d.ts +5 -0
- package/dist/sdk-version.js +5 -0
- package/dist/shell/AdminShell.d.ts +12 -9
- package/dist/shell/AdminShell.js +56 -70
- package/dist/shell/components/ModuleOverview.js +1 -5
- package/dist/shell/components/RegistryPage.js +1 -1
- package/dist/shell/components/TopBar.js +2 -2
- package/dist/shell/index.d.ts +1 -1
- package/dist/shell/polling-config.d.ts +4 -3
- package/dist/shell/polling-config.js +11 -9
- package/dist/shell/types.d.ts +3 -1
- package/dist/types/platform.d.ts +2 -11
- package/dist/vite/config.d.ts +4 -9
- package/dist/vite/config.js +85 -27
- package/dist/vite/index.d.ts +1 -1
- package/dist/vite/index.js +1 -1
- package/dist/vite/plugins.js +6 -1
- package/package.json +11 -5
- package/scripts/write-sdk-version.mjs +21 -0
- package/dist/auth/client/keycloak.d.ts +0 -18
- package/dist/auth/client/keycloak.js +0 -129
- package/dist/shell/BackofficeShell.d.ts +0 -37
- package/dist/shell/BackofficeShell.js +0 -339
- package/dist/types/keycloak.d.ts +0 -25
- package/dist/types/keycloak.js +0 -1
package/dist/vite/config.js
CHANGED
|
@@ -2,18 +2,96 @@ import { loadEnv } from "vite";
|
|
|
2
2
|
import { generateModuleManifestPlugin, serveDistPlugin } from "./plugins.js";
|
|
3
3
|
import { adminModuleI18nPlugin } from "./i18n-plugin.js";
|
|
4
4
|
import { getSharedExternals } from "./AdminShellSharedDeps.js";
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
* Default admin gateway URL (staging environment).
|
|
8
|
-
* Used by the env injection plugin when no explicit value is configured.
|
|
9
|
-
*/
|
|
10
|
-
export const ADMIN_GATEWAY_STAGING_URL = "https://admin-bff-stg.nsx.dev";
|
|
5
|
+
/** Default gateway when no env or option is set (internal to the plugin). */
|
|
6
|
+
const DEFAULT_GATEWAY_URL = "https://admin-bff-stg.nsx.dev";
|
|
11
7
|
/**
|
|
12
8
|
* Shared dependencies that are externalized in module builds.
|
|
13
9
|
* These are provided by the shell via import maps.
|
|
14
10
|
* Derived from SHARED_DEPS_CONFIG — the single source of truth.
|
|
15
11
|
*/
|
|
16
12
|
export const SHARED_EXTERNALS = getSharedExternals();
|
|
13
|
+
function buildEnvJs(mode, gatewayUrl) {
|
|
14
|
+
const loaded = loadEnv(mode, process.cwd(), "");
|
|
15
|
+
const fromEnv = process.env.ADMIN_GATEWAY_URL || loaded.ADMIN_GATEWAY_URL;
|
|
16
|
+
let adminGateway;
|
|
17
|
+
if (fromEnv) {
|
|
18
|
+
adminGateway = fromEnv;
|
|
19
|
+
}
|
|
20
|
+
else if (gatewayUrl !== undefined && gatewayUrl !== null) {
|
|
21
|
+
adminGateway = gatewayUrl;
|
|
22
|
+
}
|
|
23
|
+
else {
|
|
24
|
+
adminGateway = DEFAULT_GATEWAY_URL;
|
|
25
|
+
}
|
|
26
|
+
const entries = {
|
|
27
|
+
ADMIN_GATEWAY_URL: adminGateway,
|
|
28
|
+
};
|
|
29
|
+
const mockAuth = loaded.MOCK_AUTH ?? process.env.MOCK_AUTH;
|
|
30
|
+
if (mockAuth !== undefined && mockAuth !== "") {
|
|
31
|
+
entries.MOCK_AUTH = mockAuth;
|
|
32
|
+
}
|
|
33
|
+
const environment = loaded.ENVIRONMENT ?? process.env.ENVIRONMENT;
|
|
34
|
+
if (environment !== undefined && environment !== "") {
|
|
35
|
+
entries.ENVIRONMENT = environment;
|
|
36
|
+
}
|
|
37
|
+
const registryPollInterval = loaded.REGISTRY_POLL_INTERVAL ?? process.env.REGISTRY_POLL_INTERVAL;
|
|
38
|
+
if (registryPollInterval !== undefined && registryPollInterval !== "") {
|
|
39
|
+
entries.REGISTRY_POLL_INTERVAL = registryPollInterval;
|
|
40
|
+
}
|
|
41
|
+
const body = Object.entries(entries)
|
|
42
|
+
.map(([k, v]) => `${k}:${JSON.stringify(v)}`)
|
|
43
|
+
.join(",");
|
|
44
|
+
return `window.__ENV__={${body}};`;
|
|
45
|
+
}
|
|
46
|
+
function createAdminModuleEnvPlugin(gatewayUrl) {
|
|
47
|
+
return {
|
|
48
|
+
name: "admin-module-env",
|
|
49
|
+
configureServer(server) {
|
|
50
|
+
if (gatewayUrl === null)
|
|
51
|
+
return;
|
|
52
|
+
server.middlewares.use((req, res, next) => {
|
|
53
|
+
const url = req.url?.split("?")[0];
|
|
54
|
+
if (url === "/env.js") {
|
|
55
|
+
const mode = server.config.mode;
|
|
56
|
+
res.setHeader("Content-Type", "application/javascript");
|
|
57
|
+
res.setHeader("Cache-Control", "no-cache");
|
|
58
|
+
res.end(buildEnvJs(mode, gatewayUrl));
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
next();
|
|
62
|
+
});
|
|
63
|
+
},
|
|
64
|
+
configurePreviewServer(server) {
|
|
65
|
+
if (gatewayUrl === null)
|
|
66
|
+
return;
|
|
67
|
+
server.middlewares.use((req, res, next) => {
|
|
68
|
+
const url = req.url?.split("?")[0];
|
|
69
|
+
if (url === "/env.js") {
|
|
70
|
+
const mode = server.config.mode;
|
|
71
|
+
res.setHeader("Content-Type", "application/javascript");
|
|
72
|
+
res.setHeader("Cache-Control", "no-cache");
|
|
73
|
+
res.end(buildEnvJs(mode, gatewayUrl));
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
76
|
+
next();
|
|
77
|
+
});
|
|
78
|
+
},
|
|
79
|
+
transformIndexHtml: {
|
|
80
|
+
order: "pre",
|
|
81
|
+
handler(html) {
|
|
82
|
+
if (gatewayUrl === null)
|
|
83
|
+
return html;
|
|
84
|
+
if (html.includes('src="/env.js"') || html.includes("src='/env.js'")) {
|
|
85
|
+
return html;
|
|
86
|
+
}
|
|
87
|
+
if (html.includes("</head>")) {
|
|
88
|
+
return html.replace("</head>", ` <script src="/env.js"></script>\n </head>`);
|
|
89
|
+
}
|
|
90
|
+
return html;
|
|
91
|
+
},
|
|
92
|
+
},
|
|
93
|
+
};
|
|
94
|
+
}
|
|
17
95
|
/**
|
|
18
96
|
* Composable Vite plugin array for admin modules.
|
|
19
97
|
* Returns plugins that handle build-time lib config, dist serving, and manifest generation.
|
|
@@ -54,26 +132,6 @@ export function adminModule(options = {}) {
|
|
|
54
132
|
return true;
|
|
55
133
|
return process.env.ADMIN_MODULE === "true";
|
|
56
134
|
}
|
|
57
|
-
const envPlugin = {
|
|
58
|
-
name: "admin-module-env",
|
|
59
|
-
config(_config, { mode }) {
|
|
60
|
-
if (gatewayUrl === null)
|
|
61
|
-
return;
|
|
62
|
-
const env = loadEnv(mode, process.cwd(), "VITE_");
|
|
63
|
-
const fromEnv = process.env[ENV_KEY] || env[ENV_KEY];
|
|
64
|
-
if (fromEnv) {
|
|
65
|
-
console.log(`[admin-module-env] ${ENV_KEY} → ${fromEnv} (from env)`);
|
|
66
|
-
return;
|
|
67
|
-
}
|
|
68
|
-
const url = gatewayUrl ?? ADMIN_GATEWAY_STAGING_URL;
|
|
69
|
-
console.log(`[admin-module-env] ${ENV_KEY} → ${url} (auto-injected)`);
|
|
70
|
-
return {
|
|
71
|
-
define: {
|
|
72
|
-
[`import.meta.env.${ENV_KEY}`]: JSON.stringify(url),
|
|
73
|
-
},
|
|
74
|
-
};
|
|
75
|
-
},
|
|
76
|
-
};
|
|
77
135
|
const buildConfigPlugin = {
|
|
78
136
|
name: "admin-module-build-config",
|
|
79
137
|
config(_config, { command }) {
|
|
@@ -100,7 +158,7 @@ export function adminModule(options = {}) {
|
|
|
100
158
|
},
|
|
101
159
|
};
|
|
102
160
|
return [
|
|
103
|
-
|
|
161
|
+
createAdminModuleEnvPlugin(gatewayUrl),
|
|
104
162
|
adminModuleI18nPlugin(),
|
|
105
163
|
serveDistPlugin({ distDir: outDir }),
|
|
106
164
|
generateModuleManifestPlugin(),
|
package/dist/vite/index.d.ts
CHANGED
|
@@ -15,5 +15,5 @@
|
|
|
15
15
|
*/
|
|
16
16
|
export { generateModuleManifestPlugin, serveDistPlugin, type GenerateModuleManifestPluginOptions, type ServeDistPluginOptions, } from "./plugins.js";
|
|
17
17
|
export { adminModuleI18nPlugin, type AdminModuleI18nPluginOptions, } from "./i18n-plugin.js";
|
|
18
|
-
export { adminModule, defineModuleConfig, SHARED_EXTERNALS,
|
|
18
|
+
export { adminModule, defineModuleConfig, SHARED_EXTERNALS, type AdminModuleOptions, type ModuleConfigOptions, } from "./config.js";
|
|
19
19
|
export { AdminShellSharedDeps, SHARED_DEPS_CONFIG, getSharedExternals, type SharedDepConfig, } from "./AdminShellSharedDeps.js";
|
package/dist/vite/index.js
CHANGED
|
@@ -15,5 +15,5 @@
|
|
|
15
15
|
*/
|
|
16
16
|
export { generateModuleManifestPlugin, serveDistPlugin, } from "./plugins.js";
|
|
17
17
|
export { adminModuleI18nPlugin, } from "./i18n-plugin.js";
|
|
18
|
-
export { adminModule, defineModuleConfig, SHARED_EXTERNALS,
|
|
18
|
+
export { adminModule, defineModuleConfig, SHARED_EXTERNALS, } from "./config.js";
|
|
19
19
|
export { AdminShellSharedDeps, SHARED_DEPS_CONFIG, getSharedExternals, } from "./AdminShellSharedDeps.js";
|
package/dist/vite/plugins.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { readFileSync, writeFileSync, existsSync } from "fs";
|
|
2
2
|
import { resolve, join } from "path";
|
|
3
|
+
import { SDK_PACKAGE_VERSION } from "../sdk-version.js";
|
|
3
4
|
/**
|
|
4
5
|
* Vite plugin to generate module.manifest.json after build.
|
|
5
6
|
* Merges admin.module.json metadata with the build entry path.
|
|
@@ -22,7 +23,11 @@ export function generateModuleManifestPlugin(options = {}) {
|
|
|
22
23
|
if (!spaEntry)
|
|
23
24
|
return;
|
|
24
25
|
const metadata = JSON.parse(readFileSync(manifestPath, "utf-8"));
|
|
25
|
-
const manifest = {
|
|
26
|
+
const manifest = {
|
|
27
|
+
entry: spaEntry,
|
|
28
|
+
sdkVersion: SDK_PACKAGE_VERSION,
|
|
29
|
+
...metadata,
|
|
30
|
+
};
|
|
26
31
|
const outDir = outputOptions.dir || "dist";
|
|
27
32
|
const outputPath = join(outDir, "module.manifest.json");
|
|
28
33
|
writeFileSync(outputPath, JSON.stringify(manifest, null, 2));
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nsxbet/admin-sdk",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.8.0",
|
|
4
4
|
"description": "SDK for building NSX Admin modules with integrated shell",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -19,6 +19,12 @@
|
|
|
19
19
|
"import": "./dist/vite/index.js",
|
|
20
20
|
"default": "./dist/vite/index.js"
|
|
21
21
|
},
|
|
22
|
+
"./env": {
|
|
23
|
+
"source": "./src/env.ts",
|
|
24
|
+
"types": "./dist/env.d.ts",
|
|
25
|
+
"import": "./dist/env.js",
|
|
26
|
+
"default": "./dist/env.js"
|
|
27
|
+
},
|
|
22
28
|
"./tailwind": {
|
|
23
29
|
"source": "./src/tailwind/index.ts",
|
|
24
30
|
"types": "./dist/tailwind/index.d.ts",
|
|
@@ -34,9 +40,9 @@
|
|
|
34
40
|
],
|
|
35
41
|
"scripts": {
|
|
36
42
|
"postinstall": "node scripts/postinstall.js",
|
|
37
|
-
"build": "tsc",
|
|
38
|
-
"dev": "tsc --watch --preserveWatchOutput",
|
|
39
|
-
"type-check": "tsc --noEmit",
|
|
43
|
+
"build": "node scripts/write-sdk-version.mjs && tsc",
|
|
44
|
+
"dev": "node scripts/write-sdk-version.mjs && tsc --watch --preserveWatchOutput",
|
|
45
|
+
"type-check": "node scripts/write-sdk-version.mjs && tsc --noEmit",
|
|
40
46
|
"test": "vitest run --passWithNoTests",
|
|
41
47
|
"storybook": "storybook dev -p 6007 --host 0.0.0.0",
|
|
42
48
|
"build-storybook": "storybook build -o storybook-static"
|
|
@@ -63,7 +69,6 @@
|
|
|
63
69
|
}
|
|
64
70
|
},
|
|
65
71
|
"dependencies": {
|
|
66
|
-
"keycloak-js": "^23.0.0",
|
|
67
72
|
"lucide-react": "^0.460.0"
|
|
68
73
|
},
|
|
69
74
|
"devDependencies": {
|
|
@@ -71,6 +76,7 @@
|
|
|
71
76
|
"@storybook/react-vite": "^10.3.0",
|
|
72
77
|
"@testing-library/jest-dom": "^6.9.1",
|
|
73
78
|
"@testing-library/react": "^16.3.2",
|
|
79
|
+
"@types/node": "^20.3.1",
|
|
74
80
|
"@types/react": "^18.2.0",
|
|
75
81
|
"@types/react-dom": "^18.2.0",
|
|
76
82
|
"@vitejs/plugin-react": "^4.3.4",
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Writes src/sdk-version.ts from package.json version so tsc can use rootDir "./src"
|
|
3
|
+
* without importing files outside src/ (which breaks dist/ layout vs package exports).
|
|
4
|
+
*/
|
|
5
|
+
import { readFileSync, writeFileSync } from "node:fs";
|
|
6
|
+
import { dirname, join } from "node:path";
|
|
7
|
+
import { fileURLToPath } from "node:url";
|
|
8
|
+
|
|
9
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
10
|
+
const pkgPath = join(__dirname, "..", "package.json");
|
|
11
|
+
const outPath = join(__dirname, "..", "src", "sdk-version.ts");
|
|
12
|
+
const { version } = JSON.parse(readFileSync(pkgPath, "utf8"));
|
|
13
|
+
|
|
14
|
+
const contents = `/**
|
|
15
|
+
* Semver of @nsxbet/admin-sdk (synced from package.json by scripts/write-sdk-version.mjs).
|
|
16
|
+
* Do not edit manually — run \`node scripts/write-sdk-version.mjs\` after version bumps.
|
|
17
|
+
*/
|
|
18
|
+
export const SDK_PACKAGE_VERSION: string = ${JSON.stringify(version)};
|
|
19
|
+
`;
|
|
20
|
+
|
|
21
|
+
writeFileSync(outPath, contents, "utf8");
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Keycloak Auth Client
|
|
3
|
-
*
|
|
4
|
-
* Provides real authentication via Keycloak for production environments.
|
|
5
|
-
*/
|
|
6
|
-
import type { KeycloakConfig } from '../../types/keycloak';
|
|
7
|
-
import type { AuthClient } from './interface';
|
|
8
|
-
/**
|
|
9
|
-
* Options for creating a Keycloak auth client
|
|
10
|
-
*/
|
|
11
|
-
export interface KeycloakAuthClientOptions {
|
|
12
|
-
/** Keycloak configuration */
|
|
13
|
-
config: KeycloakConfig;
|
|
14
|
-
}
|
|
15
|
-
/**
|
|
16
|
-
* Create a Keycloak auth client for production
|
|
17
|
-
*/
|
|
18
|
-
export declare function createKeycloakAuthClient(options: KeycloakAuthClientOptions): AuthClient;
|
|
@@ -1,129 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Keycloak Auth Client
|
|
3
|
-
*
|
|
4
|
-
* Provides real authentication via Keycloak for production environments.
|
|
5
|
-
*/
|
|
6
|
-
import Keycloak from 'keycloak-js';
|
|
7
|
-
/**
|
|
8
|
-
* Create a Keycloak auth client for production
|
|
9
|
-
*/
|
|
10
|
-
export function createKeycloakAuthClient(options) {
|
|
11
|
-
const { config } = options;
|
|
12
|
-
let keycloak = null;
|
|
13
|
-
let currentUser = null;
|
|
14
|
-
let isInitialized = false;
|
|
15
|
-
const subscribers = new Set();
|
|
16
|
-
/**
|
|
17
|
-
* Parse user from Keycloak token
|
|
18
|
-
*/
|
|
19
|
-
function parseUser(tokenParsed) {
|
|
20
|
-
return {
|
|
21
|
-
id: tokenParsed.sub || '',
|
|
22
|
-
email: tokenParsed.email || '',
|
|
23
|
-
displayName: tokenParsed.name || tokenParsed.preferred_username || '',
|
|
24
|
-
roles: tokenParsed.realm_access?.roles ?? [],
|
|
25
|
-
};
|
|
26
|
-
}
|
|
27
|
-
/**
|
|
28
|
-
* Notify subscribers of state change
|
|
29
|
-
*/
|
|
30
|
-
function notifySubscribers() {
|
|
31
|
-
const state = {
|
|
32
|
-
isAuthenticated: currentUser !== null,
|
|
33
|
-
user: currentUser,
|
|
34
|
-
};
|
|
35
|
-
subscribers.forEach((callback) => callback(state));
|
|
36
|
-
}
|
|
37
|
-
const client = {
|
|
38
|
-
type: 'keycloak',
|
|
39
|
-
async initialize() {
|
|
40
|
-
if (keycloak) {
|
|
41
|
-
return keycloak.authenticated ?? false;
|
|
42
|
-
}
|
|
43
|
-
keycloak = new Keycloak({
|
|
44
|
-
url: config.url || 'http://localhost:8080',
|
|
45
|
-
realm: config.realm || 'admin',
|
|
46
|
-
clientId: config.clientId,
|
|
47
|
-
});
|
|
48
|
-
try {
|
|
49
|
-
const authenticated = await keycloak.init({
|
|
50
|
-
onLoad: 'login-required',
|
|
51
|
-
checkLoginIframe: false,
|
|
52
|
-
pkceMethod: 'S256',
|
|
53
|
-
});
|
|
54
|
-
if (authenticated && keycloak.tokenParsed) {
|
|
55
|
-
currentUser = parseUser(keycloak.tokenParsed);
|
|
56
|
-
}
|
|
57
|
-
isInitialized = true;
|
|
58
|
-
// Notify subscribers that auth is ready - this triggers React re-render
|
|
59
|
-
// which will re-evaluate permissions with the now-available token
|
|
60
|
-
notifySubscribers();
|
|
61
|
-
// Setup token refresh
|
|
62
|
-
keycloak.onTokenExpired = () => {
|
|
63
|
-
keycloak?.updateToken(30).catch(() => {
|
|
64
|
-
console.error('[AuthClient] Failed to refresh token');
|
|
65
|
-
client.logout();
|
|
66
|
-
});
|
|
67
|
-
};
|
|
68
|
-
// Setup auth state changes
|
|
69
|
-
keycloak.onAuthLogout = () => {
|
|
70
|
-
currentUser = null;
|
|
71
|
-
notifySubscribers();
|
|
72
|
-
};
|
|
73
|
-
keycloak.onAuthRefreshError = () => {
|
|
74
|
-
currentUser = null;
|
|
75
|
-
notifySubscribers();
|
|
76
|
-
};
|
|
77
|
-
return authenticated;
|
|
78
|
-
}
|
|
79
|
-
catch (error) {
|
|
80
|
-
console.error('[AuthClient] Keycloak initialization failed:', error);
|
|
81
|
-
throw error;
|
|
82
|
-
}
|
|
83
|
-
},
|
|
84
|
-
isAuthenticated() {
|
|
85
|
-
return keycloak?.authenticated ?? false;
|
|
86
|
-
},
|
|
87
|
-
getUser() {
|
|
88
|
-
return currentUser;
|
|
89
|
-
},
|
|
90
|
-
async getAccessToken() {
|
|
91
|
-
if (!keycloak) {
|
|
92
|
-
throw new Error('Keycloak not initialized');
|
|
93
|
-
}
|
|
94
|
-
try {
|
|
95
|
-
await keycloak.updateToken(5);
|
|
96
|
-
return keycloak.token || '';
|
|
97
|
-
}
|
|
98
|
-
catch (error) {
|
|
99
|
-
console.error('[AuthClient] Failed to refresh token');
|
|
100
|
-
client.logout();
|
|
101
|
-
throw error;
|
|
102
|
-
}
|
|
103
|
-
},
|
|
104
|
-
hasPermission(permission) {
|
|
105
|
-
// Deny-by-default: return false until Keycloak is fully initialized.
|
|
106
|
-
// This prevents a window where all actions appear permitted during auth init.
|
|
107
|
-
// AuthProvider gates rendering behind isAuthenticated, so modules won't
|
|
108
|
-
// render permission-gated UI until auth completes.
|
|
109
|
-
if (!isInitialized || !keycloak) {
|
|
110
|
-
return false;
|
|
111
|
-
}
|
|
112
|
-
return keycloak.hasRealmRole(permission);
|
|
113
|
-
},
|
|
114
|
-
logout() {
|
|
115
|
-
currentUser = null;
|
|
116
|
-
if (keycloak) {
|
|
117
|
-
keycloak.logout();
|
|
118
|
-
}
|
|
119
|
-
notifySubscribers();
|
|
120
|
-
},
|
|
121
|
-
subscribe(callback) {
|
|
122
|
-
subscribers.add(callback);
|
|
123
|
-
return () => {
|
|
124
|
-
subscribers.delete(callback);
|
|
125
|
-
};
|
|
126
|
-
},
|
|
127
|
-
};
|
|
128
|
-
return client;
|
|
129
|
-
}
|
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
import type { AuthClient } from "../auth/client/interface";
|
|
2
|
-
import type { AdminModuleManifest, RegistryClient } from "../registry";
|
|
3
|
-
export interface AdminShellProps {
|
|
4
|
-
/**
|
|
5
|
-
* Module manifests to load (used for standalone mode when no registryClient)
|
|
6
|
-
* In standalone mode, modules are rendered via children prop
|
|
7
|
-
*/
|
|
8
|
-
modules?: AdminModuleManifest[];
|
|
9
|
-
/**
|
|
10
|
-
* Content to render for standalone module development.
|
|
11
|
-
* Only used in standalone mode (when modules prop is provided)
|
|
12
|
-
*/
|
|
13
|
-
children?: React.ReactNode;
|
|
14
|
-
/**
|
|
15
|
-
* Keycloak configuration
|
|
16
|
-
* If not provided, uses in-memory (mock) authentication
|
|
17
|
-
*/
|
|
18
|
-
keycloak?: {
|
|
19
|
-
url: string;
|
|
20
|
-
realm: string;
|
|
21
|
-
clientId: string;
|
|
22
|
-
};
|
|
23
|
-
/**
|
|
24
|
-
* Auth client to use for authentication.
|
|
25
|
-
* If not provided, creates one based on keycloak prop or environment.
|
|
26
|
-
*/
|
|
27
|
-
authClient?: AuthClient;
|
|
28
|
-
/** Registry client for fetching modules from API */
|
|
29
|
-
registryClient?: RegistryClient;
|
|
30
|
-
/** API URL for registry management (e.g., "http://localhost:4000/api") */
|
|
31
|
-
apiUrl?: string;
|
|
32
|
-
/** Use in-memory registry (default: true, ignored if registryClient is provided) */
|
|
33
|
-
inMemoryRegistry?: boolean;
|
|
34
|
-
/** Environment (default: "local") */
|
|
35
|
-
environment?: string;
|
|
36
|
-
}
|
|
37
|
-
export declare function AdminShell({ modules: manifests, children, keycloak, authClient: providedAuthClient, registryClient, apiUrl, inMemoryRegistry, environment, }: AdminShellProps): import("react/jsx-runtime").JSX.Element;
|