@nsxbet/admin-sdk 0.1.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/README.md +680 -0
- package/dist/auth/client/in-memory.d.ts +27 -0
- package/dist/auth/client/in-memory.d.ts.map +1 -0
- package/dist/auth/client/in-memory.js +242 -0
- package/dist/auth/client/index.d.ts +7 -0
- package/dist/auth/client/index.d.ts.map +1 -0
- package/dist/auth/client/index.js +7 -0
- package/dist/auth/client/interface.d.ts +115 -0
- package/dist/auth/client/interface.d.ts.map +1 -0
- package/dist/auth/client/interface.js +7 -0
- package/dist/auth/client/keycloak.d.ts +19 -0
- package/dist/auth/client/keycloak.d.ts.map +1 -0
- package/dist/auth/client/keycloak.js +126 -0
- package/dist/auth/components/UserSelector.d.ts +19 -0
- package/dist/auth/components/UserSelector.d.ts.map +1 -0
- package/dist/auth/components/UserSelector.js +100 -0
- package/dist/auth/components/index.d.ts +5 -0
- package/dist/auth/components/index.d.ts.map +1 -0
- package/dist/auth/components/index.js +4 -0
- package/dist/auth/index.d.ts +7 -0
- package/dist/auth/index.d.ts.map +1 -0
- package/dist/auth/index.js +7 -0
- package/dist/components/AuthProvider.d.ts +48 -0
- package/dist/components/AuthProvider.d.ts.map +1 -0
- package/dist/components/AuthProvider.js +117 -0
- package/dist/hooks/useAuth.d.ts +21 -0
- package/dist/hooks/useAuth.d.ts.map +1 -0
- package/dist/hooks/useAuth.js +34 -0
- package/dist/hooks/useFetch.d.ts +8 -0
- package/dist/hooks/useFetch.d.ts.map +1 -0
- package/dist/hooks/useFetch.js +31 -0
- package/dist/hooks/useI18n.d.ts +46 -0
- package/dist/hooks/useI18n.d.ts.map +1 -0
- package/dist/hooks/useI18n.js +95 -0
- package/dist/hooks/usePlatformAPI.d.ts +12 -0
- package/dist/hooks/usePlatformAPI.d.ts.map +1 -0
- package/dist/hooks/usePlatformAPI.js +10 -0
- package/dist/hooks/useTelemetry.d.ts +17 -0
- package/dist/hooks/useTelemetry.d.ts.map +1 -0
- package/dist/hooks/useTelemetry.js +36 -0
- package/dist/i18n/config.d.ts +26 -0
- package/dist/i18n/config.d.ts.map +1 -0
- package/dist/i18n/config.js +92 -0
- package/dist/i18n/index.d.ts +6 -0
- package/dist/i18n/index.d.ts.map +1 -0
- package/dist/i18n/index.js +4 -0
- package/dist/i18n/locales/en-US.json +144 -0
- package/dist/i18n/locales/es.json +144 -0
- package/dist/i18n/locales/pt-BR.json +144 -0
- package/dist/i18n/locales/ro.json +144 -0
- package/dist/index.d.ts +27 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +30 -0
- package/dist/registry/AdminShellRegistry.d.ts +140 -0
- package/dist/registry/AdminShellRegistry.d.ts.map +1 -0
- package/dist/registry/AdminShellRegistry.js +237 -0
- package/dist/registry/client/http.d.ts +21 -0
- package/dist/registry/client/http.d.ts.map +1 -0
- package/dist/registry/client/http.js +107 -0
- package/dist/registry/client/in-memory.d.ts +36 -0
- package/dist/registry/client/in-memory.d.ts.map +1 -0
- package/dist/registry/client/in-memory.js +242 -0
- package/dist/registry/client/index.d.ts +7 -0
- package/dist/registry/client/index.d.ts.map +1 -0
- package/dist/registry/client/index.js +5 -0
- package/dist/registry/client/interface.d.ts +96 -0
- package/dist/registry/client/interface.d.ts.map +1 -0
- package/dist/registry/client/interface.js +7 -0
- package/dist/registry/index.d.ts +12 -0
- package/dist/registry/index.d.ts.map +1 -0
- package/dist/registry/index.js +8 -0
- package/dist/registry/types/index.d.ts +9 -0
- package/dist/registry/types/index.d.ts.map +1 -0
- package/dist/registry/types/index.js +6 -0
- package/dist/registry/types/manifest.d.ts +98 -0
- package/dist/registry/types/manifest.d.ts.map +1 -0
- package/dist/registry/types/manifest.js +81 -0
- package/dist/registry/types/module.d.ts +115 -0
- package/dist/registry/types/module.d.ts.map +1 -0
- package/dist/registry/types/module.js +6 -0
- package/dist/router/DynamicModule.d.ts +50 -0
- package/dist/router/DynamicModule.d.ts.map +1 -0
- package/dist/router/DynamicModule.js +141 -0
- package/dist/router/index.d.ts +2 -0
- package/dist/router/index.d.ts.map +1 -0
- package/dist/router/index.js +1 -0
- package/dist/shell/AdminShell.d.ts +38 -0
- package/dist/shell/AdminShell.d.ts.map +1 -0
- package/dist/shell/AdminShell.js +299 -0
- package/dist/shell/BackofficeShell.d.ts +38 -0
- package/dist/shell/BackofficeShell.d.ts.map +1 -0
- package/dist/shell/BackofficeShell.js +299 -0
- package/dist/shell/components/CommandPalette.d.ts +8 -0
- package/dist/shell/components/CommandPalette.d.ts.map +1 -0
- package/dist/shell/components/CommandPalette.js +197 -0
- package/dist/shell/components/HomePage.d.ts +2 -0
- package/dist/shell/components/HomePage.d.ts.map +1 -0
- package/dist/shell/components/HomePage.js +32 -0
- package/dist/shell/components/LeftNav.d.ts +7 -0
- package/dist/shell/components/LeftNav.d.ts.map +1 -0
- package/dist/shell/components/LeftNav.js +247 -0
- package/dist/shell/components/MainContent.d.ts +9 -0
- package/dist/shell/components/MainContent.d.ts.map +1 -0
- package/dist/shell/components/MainContent.js +88 -0
- package/dist/shell/components/ModuleOverview.d.ts +7 -0
- package/dist/shell/components/ModuleOverview.d.ts.map +1 -0
- package/dist/shell/components/ModuleOverview.js +40 -0
- package/dist/shell/components/ProfilePage.d.ts +2 -0
- package/dist/shell/components/ProfilePage.d.ts.map +1 -0
- package/dist/shell/components/ProfilePage.js +30 -0
- package/dist/shell/components/RegistryPage.d.ts +8 -0
- package/dist/shell/components/RegistryPage.d.ts.map +1 -0
- package/dist/shell/components/RegistryPage.js +129 -0
- package/dist/shell/components/SettingsPage.d.ts +2 -0
- package/dist/shell/components/SettingsPage.d.ts.map +1 -0
- package/dist/shell/components/SettingsPage.js +60 -0
- package/dist/shell/components/TopBar.d.ts +8 -0
- package/dist/shell/components/TopBar.d.ts.map +1 -0
- package/dist/shell/components/TopBar.js +61 -0
- package/dist/shell/components/index.d.ts +10 -0
- package/dist/shell/components/index.d.ts.map +1 -0
- package/dist/shell/components/index.js +7 -0
- package/dist/shell/components/theme-provider.d.ts +15 -0
- package/dist/shell/components/theme-provider.d.ts.map +1 -0
- package/dist/shell/components/theme-provider.js +39 -0
- package/dist/shell/index.d.ts +9 -0
- package/dist/shell/index.d.ts.map +1 -0
- package/dist/shell/index.js +8 -0
- package/dist/shell/search/fuzzy.d.ts +18 -0
- package/dist/shell/search/fuzzy.d.ts.map +1 -0
- package/dist/shell/search/fuzzy.js +121 -0
- package/dist/shell/search/index.d.ts +3 -0
- package/dist/shell/search/index.d.ts.map +1 -0
- package/dist/shell/search/index.js +1 -0
- package/dist/shell/telemetry.d.ts +7 -0
- package/dist/shell/telemetry.d.ts.map +1 -0
- package/dist/shell/telemetry.js +25 -0
- package/dist/shell/types.d.ts +110 -0
- package/dist/shell/types.d.ts.map +1 -0
- package/dist/shell/types.js +4 -0
- package/dist/tailwind/index.d.ts +20 -0
- package/dist/tailwind/index.d.ts.map +1 -0
- package/dist/tailwind/index.js +42 -0
- package/dist/types/keycloak.d.ts +26 -0
- package/dist/types/keycloak.d.ts.map +1 -0
- package/dist/types/keycloak.js +1 -0
- package/dist/types/platform.d.ts +83 -0
- package/dist/types/platform.d.ts.map +1 -0
- package/dist/types/platform.js +5 -0
- package/dist/vite/config.d.ts +71 -0
- package/dist/vite/config.d.ts.map +1 -0
- package/dist/vite/config.js +87 -0
- package/dist/vite/index.d.ts +18 -0
- package/dist/vite/index.d.ts.map +1 -0
- package/dist/vite/index.js +17 -0
- package/dist/vite/plugins.d.ts +44 -0
- package/dist/vite/plugins.d.ts.map +1 -0
- package/dist/vite/plugins.js +74 -0
- package/package.json +86 -0
|
@@ -0,0 +1,242 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* In-Memory Registry Client
|
|
3
|
+
*
|
|
4
|
+
* Implementation of RegistryClient that stores data in localStorage.
|
|
5
|
+
* Used for local development and testing without a backend.
|
|
6
|
+
*/
|
|
7
|
+
import { parseManifest } from '../types';
|
|
8
|
+
const DEFAULT_STORAGE_KEY = '@nsxbet/registry';
|
|
9
|
+
/**
|
|
10
|
+
* Create an in-memory registry client
|
|
11
|
+
*/
|
|
12
|
+
export function createInMemoryRegistryClient(options = {}) {
|
|
13
|
+
const storageKey = options.storageKey ?? DEFAULT_STORAGE_KEY;
|
|
14
|
+
// Initialize or load storage
|
|
15
|
+
let data = loadStorage(storageKey);
|
|
16
|
+
// Apply seed if provided and storage is empty
|
|
17
|
+
// Note: seed is for standalone mode where modules are imported directly (no baseUrl needed)
|
|
18
|
+
if (options.seed && data.modules.length === 0) {
|
|
19
|
+
const now = new Date().toISOString();
|
|
20
|
+
for (const manifest of options.seed) {
|
|
21
|
+
const validated = parseManifest(manifest);
|
|
22
|
+
data.modules.push({
|
|
23
|
+
id: ++data.autoIncrement,
|
|
24
|
+
moduleId: validated.id,
|
|
25
|
+
baseUrl: '',
|
|
26
|
+
manifest: validated,
|
|
27
|
+
navOrder: validated.navOrder ?? data.autoIncrement * 10,
|
|
28
|
+
enabled: true,
|
|
29
|
+
registeredAt: now,
|
|
30
|
+
updatedAt: now,
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
saveStorage(storageKey, data);
|
|
34
|
+
}
|
|
35
|
+
// Apply initialModules if provided and storage is empty
|
|
36
|
+
if (options.initialModules && data.modules.length === 0) {
|
|
37
|
+
const now = new Date().toISOString();
|
|
38
|
+
for (const moduleConfig of options.initialModules) {
|
|
39
|
+
const { baseUrl, ...manifestData } = moduleConfig;
|
|
40
|
+
const validated = parseManifest(manifestData);
|
|
41
|
+
data.modules.push({
|
|
42
|
+
id: ++data.autoIncrement,
|
|
43
|
+
moduleId: validated.id,
|
|
44
|
+
baseUrl,
|
|
45
|
+
manifest: validated,
|
|
46
|
+
navOrder: validated.navOrder ?? data.autoIncrement * 10,
|
|
47
|
+
enabled: true,
|
|
48
|
+
registeredAt: now,
|
|
49
|
+
updatedAt: now,
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
saveStorage(storageKey, data);
|
|
53
|
+
}
|
|
54
|
+
// Module operations
|
|
55
|
+
const modules = {
|
|
56
|
+
async findAll(filters) {
|
|
57
|
+
data = loadStorage(storageKey);
|
|
58
|
+
let result = [...data.modules];
|
|
59
|
+
if (filters?.enabled !== undefined) {
|
|
60
|
+
result = result.filter((m) => m.enabled === filters.enabled);
|
|
61
|
+
}
|
|
62
|
+
if (filters?.category) {
|
|
63
|
+
result = result.filter((m) => m.manifest.category === filters.category);
|
|
64
|
+
}
|
|
65
|
+
if (filters?.status) {
|
|
66
|
+
result = result.filter((m) => m.manifest.status === filters.status);
|
|
67
|
+
}
|
|
68
|
+
// Sort by navOrder
|
|
69
|
+
result.sort((a, b) => a.navOrder - b.navOrder);
|
|
70
|
+
return result;
|
|
71
|
+
},
|
|
72
|
+
async find(id) {
|
|
73
|
+
data = loadStorage(storageKey);
|
|
74
|
+
const module = data.modules.find((m) => m.id === id);
|
|
75
|
+
if (!module) {
|
|
76
|
+
throw new Error(`Module with id ${id} not found`);
|
|
77
|
+
}
|
|
78
|
+
return module;
|
|
79
|
+
},
|
|
80
|
+
async register(baseUrl) {
|
|
81
|
+
// Fetch module.manifest.json from URL to get metadata
|
|
82
|
+
// Note: entry is NOT stored - DynamicModule fetches it at runtime
|
|
83
|
+
const manifestUrl = baseUrl.endsWith('/')
|
|
84
|
+
? `${baseUrl}module.manifest.json`
|
|
85
|
+
: `${baseUrl}/module.manifest.json`;
|
|
86
|
+
const response = await fetch(manifestUrl);
|
|
87
|
+
if (!response.ok) {
|
|
88
|
+
throw new Error(`Failed to fetch manifest from ${manifestUrl}: ${response.status}`);
|
|
89
|
+
}
|
|
90
|
+
const manifestData = await response.json();
|
|
91
|
+
// Extract manifest without entry (entry is fetched by DynamicModule at runtime)
|
|
92
|
+
const { entry: _entry, ...manifest } = manifestData;
|
|
93
|
+
const validated = parseManifest(manifest);
|
|
94
|
+
return this.registerFromManifest(validated, baseUrl);
|
|
95
|
+
},
|
|
96
|
+
async registerFromManifest(manifest, baseUrl = '') {
|
|
97
|
+
data = loadStorage(storageKey);
|
|
98
|
+
// Validate manifest
|
|
99
|
+
const validated = parseManifest(manifest);
|
|
100
|
+
// Check for duplicate moduleId
|
|
101
|
+
if (data.modules.some((m) => m.moduleId === validated.id)) {
|
|
102
|
+
throw new Error(`Module with id ${validated.id} already exists`);
|
|
103
|
+
}
|
|
104
|
+
const now = new Date().toISOString();
|
|
105
|
+
const newModule = {
|
|
106
|
+
id: ++data.autoIncrement,
|
|
107
|
+
moduleId: validated.id,
|
|
108
|
+
baseUrl,
|
|
109
|
+
manifest: validated,
|
|
110
|
+
navOrder: validated.navOrder ?? data.autoIncrement * 10,
|
|
111
|
+
enabled: true,
|
|
112
|
+
registeredAt: now,
|
|
113
|
+
updatedAt: now,
|
|
114
|
+
};
|
|
115
|
+
data.modules.push(newModule);
|
|
116
|
+
saveStorage(storageKey, data);
|
|
117
|
+
return newModule;
|
|
118
|
+
},
|
|
119
|
+
async update(id, updateData) {
|
|
120
|
+
data = loadStorage(storageKey);
|
|
121
|
+
const index = data.modules.findIndex((m) => m.id === id);
|
|
122
|
+
if (index === -1) {
|
|
123
|
+
throw new Error(`Module with id ${id} not found`);
|
|
124
|
+
}
|
|
125
|
+
const module = data.modules[index];
|
|
126
|
+
const updated = {
|
|
127
|
+
...module,
|
|
128
|
+
...(updateData.navOrder !== undefined && { navOrder: updateData.navOrder }),
|
|
129
|
+
...(updateData.enabled !== undefined && { enabled: updateData.enabled }),
|
|
130
|
+
updatedAt: new Date().toISOString(),
|
|
131
|
+
};
|
|
132
|
+
data.modules[index] = updated;
|
|
133
|
+
saveStorage(storageKey, data);
|
|
134
|
+
return updated;
|
|
135
|
+
},
|
|
136
|
+
async delete(id) {
|
|
137
|
+
data = loadStorage(storageKey);
|
|
138
|
+
const index = data.modules.findIndex((m) => m.id === id);
|
|
139
|
+
if (index === -1) {
|
|
140
|
+
throw new Error(`Module with id ${id} not found`);
|
|
141
|
+
}
|
|
142
|
+
data.modules.splice(index, 1);
|
|
143
|
+
saveStorage(storageKey, data);
|
|
144
|
+
},
|
|
145
|
+
async reorder(order) {
|
|
146
|
+
data = loadStorage(storageKey);
|
|
147
|
+
const now = new Date().toISOString();
|
|
148
|
+
for (const { id, navOrder } of order) {
|
|
149
|
+
const module = data.modules.find((m) => m.id === id);
|
|
150
|
+
if (module) {
|
|
151
|
+
module.navOrder = navOrder;
|
|
152
|
+
module.updatedAt = now;
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
saveStorage(storageKey, data);
|
|
156
|
+
},
|
|
157
|
+
};
|
|
158
|
+
// Catalog operations
|
|
159
|
+
const catalog = {
|
|
160
|
+
async get() {
|
|
161
|
+
const allModules = await modules.findAll({ enabled: true });
|
|
162
|
+
const catalogModules = allModules.map((m) => ({
|
|
163
|
+
id: m.manifest.id,
|
|
164
|
+
title: m.manifest.title,
|
|
165
|
+
description: m.manifest.description ?? '',
|
|
166
|
+
category: m.manifest.category ?? 'General',
|
|
167
|
+
routeBase: m.manifest.routeBase,
|
|
168
|
+
baseUrl: m.baseUrl,
|
|
169
|
+
keywords: m.manifest.keywords ?? [],
|
|
170
|
+
permissions: {
|
|
171
|
+
view: m.manifest.permissions?.view ?? [],
|
|
172
|
+
dangerous: m.manifest.permissions?.dangerous,
|
|
173
|
+
},
|
|
174
|
+
owners: {
|
|
175
|
+
team: m.manifest.owners?.team ?? 'unknown',
|
|
176
|
+
supportChannel: m.manifest.owners?.supportChannel ?? '#general',
|
|
177
|
+
},
|
|
178
|
+
status: m.manifest.status ?? 'active',
|
|
179
|
+
navOrder: m.navOrder,
|
|
180
|
+
icon: m.manifest.icon,
|
|
181
|
+
commands: m.manifest.commands?.map((cmd) => ({
|
|
182
|
+
id: cmd.id,
|
|
183
|
+
title: cmd.title,
|
|
184
|
+
keywords: cmd.keywords,
|
|
185
|
+
route: cmd.route,
|
|
186
|
+
icon: cmd.icon,
|
|
187
|
+
})),
|
|
188
|
+
}));
|
|
189
|
+
return {
|
|
190
|
+
version: '1.0.0',
|
|
191
|
+
generatedAt: new Date().toISOString(),
|
|
192
|
+
modules: catalogModules,
|
|
193
|
+
};
|
|
194
|
+
},
|
|
195
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
196
|
+
async getImportMap(_environment) {
|
|
197
|
+
const allModules = await modules.findAll({ enabled: true });
|
|
198
|
+
const imports = {};
|
|
199
|
+
for (const m of allModules) {
|
|
200
|
+
if (m.baseUrl) {
|
|
201
|
+
// Note: This import map is deprecated - DynamicModule fetches manifest at runtime
|
|
202
|
+
const base = m.baseUrl.endsWith('/') ? m.baseUrl.slice(0, -1) : m.baseUrl;
|
|
203
|
+
imports[m.moduleId] = `${base}/module.manifest.json`;
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
return { imports };
|
|
207
|
+
},
|
|
208
|
+
};
|
|
209
|
+
return { modules, catalog };
|
|
210
|
+
}
|
|
211
|
+
/**
|
|
212
|
+
* Load storage data from localStorage
|
|
213
|
+
*/
|
|
214
|
+
function loadStorage(key) {
|
|
215
|
+
try {
|
|
216
|
+
const stored = localStorage.getItem(key);
|
|
217
|
+
if (stored) {
|
|
218
|
+
return JSON.parse(stored);
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
catch (error) {
|
|
222
|
+
console.error('[InMemoryRegistry] Failed to load storage:', error);
|
|
223
|
+
}
|
|
224
|
+
return { modules: [], autoIncrement: 0 };
|
|
225
|
+
}
|
|
226
|
+
/**
|
|
227
|
+
* Save storage data to localStorage
|
|
228
|
+
*/
|
|
229
|
+
function saveStorage(key, data) {
|
|
230
|
+
try {
|
|
231
|
+
localStorage.setItem(key, JSON.stringify(data));
|
|
232
|
+
}
|
|
233
|
+
catch (error) {
|
|
234
|
+
console.error('[InMemoryRegistry] Failed to save storage:', error);
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
/**
|
|
238
|
+
* Clear all registry data from localStorage
|
|
239
|
+
*/
|
|
240
|
+
export function clearInMemoryRegistry(storageKey = DEFAULT_STORAGE_KEY) {
|
|
241
|
+
localStorage.removeItem(storageKey);
|
|
242
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Registry Client Exports
|
|
3
|
+
*/
|
|
4
|
+
export type { RegistryClient, ModuleOperations, CatalogOperations } from './interface';
|
|
5
|
+
export { createInMemoryRegistryClient, clearInMemoryRegistry, type InMemoryRegistryOptions, type PreConfiguredModule, } from './in-memory';
|
|
6
|
+
export { createHttpRegistryClient, type HttpRegistryOptions, } from './http';
|
|
7
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/registry/client/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,YAAY,EAAE,cAAc,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAEvF,OAAO,EACL,4BAA4B,EAC5B,qBAAqB,EACrB,KAAK,uBAAuB,EAC5B,KAAK,mBAAmB,GACzB,MAAM,aAAa,CAAC;AAErB,OAAO,EACL,wBAAwB,EACxB,KAAK,mBAAmB,GACzB,MAAM,QAAQ,CAAC"}
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Registry Client Interface
|
|
3
|
+
*
|
|
4
|
+
* Defines the interface for registry operations.
|
|
5
|
+
* Can be implemented by in-memory (localStorage) or HTTP clients.
|
|
6
|
+
*/
|
|
7
|
+
import type { RegisteredModule, UpdateModuleDto, ReorderModuleDto, ModuleFilters, Catalog, ImportMap, AdminModuleManifest } from '../types';
|
|
8
|
+
/**
|
|
9
|
+
* Module operations interface
|
|
10
|
+
*/
|
|
11
|
+
export interface ModuleOperations {
|
|
12
|
+
/**
|
|
13
|
+
* List all registered modules
|
|
14
|
+
* @param filters Optional filters
|
|
15
|
+
*/
|
|
16
|
+
findAll(filters?: ModuleFilters): Promise<RegisteredModule[]>;
|
|
17
|
+
/**
|
|
18
|
+
* Get a single module by ID
|
|
19
|
+
* @param id Module ID
|
|
20
|
+
*/
|
|
21
|
+
find(id: number): Promise<RegisteredModule>;
|
|
22
|
+
/**
|
|
23
|
+
* Register a new module by URL (fetches admin.module.json)
|
|
24
|
+
* @param baseUrl Base URL of the module
|
|
25
|
+
*/
|
|
26
|
+
register(baseUrl: string): Promise<RegisteredModule>;
|
|
27
|
+
/**
|
|
28
|
+
* Register a new module from a manifest directly
|
|
29
|
+
* @param manifest The module manifest
|
|
30
|
+
* @param baseUrl Optional base URL
|
|
31
|
+
*/
|
|
32
|
+
registerFromManifest(manifest: AdminModuleManifest, baseUrl?: string): Promise<RegisteredModule>;
|
|
33
|
+
/**
|
|
34
|
+
* Update admin-controlled fields of a module
|
|
35
|
+
* @param id Module ID
|
|
36
|
+
* @param data Update data
|
|
37
|
+
*/
|
|
38
|
+
update(id: number, data: UpdateModuleDto): Promise<RegisteredModule>;
|
|
39
|
+
/**
|
|
40
|
+
* Delete a module
|
|
41
|
+
* @param id Module ID
|
|
42
|
+
*/
|
|
43
|
+
delete(id: number): Promise<void>;
|
|
44
|
+
/**
|
|
45
|
+
* Reorder modules (batch update navOrder)
|
|
46
|
+
* @param order Array of id and navOrder pairs
|
|
47
|
+
*/
|
|
48
|
+
reorder(order: ReorderModuleDto[]): Promise<void>;
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Catalog operations interface (read-only)
|
|
52
|
+
*/
|
|
53
|
+
export interface CatalogOperations {
|
|
54
|
+
/**
|
|
55
|
+
* Get the full catalog (denormalized for shell consumption)
|
|
56
|
+
*/
|
|
57
|
+
get(): Promise<Catalog>;
|
|
58
|
+
/**
|
|
59
|
+
* Get the import map for a specific environment
|
|
60
|
+
* @param environment Environment name (e.g., 'production', 'local')
|
|
61
|
+
*/
|
|
62
|
+
getImportMap(environment: string): Promise<ImportMap>;
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Registry Client Interface
|
|
66
|
+
*
|
|
67
|
+
* Usage:
|
|
68
|
+
* ```typescript
|
|
69
|
+
* const registry = createRegistryClient();
|
|
70
|
+
*
|
|
71
|
+
* // List modules
|
|
72
|
+
* const modules = await registry.modules.findAll();
|
|
73
|
+
*
|
|
74
|
+
* // Register by URL
|
|
75
|
+
* await registry.modules.register('https://my-module.com');
|
|
76
|
+
*
|
|
77
|
+
* // Update
|
|
78
|
+
* await registry.modules.update(1, { enabled: false });
|
|
79
|
+
*
|
|
80
|
+
* // Reorder
|
|
81
|
+
* await registry.modules.reorder([
|
|
82
|
+
* { id: 1, navOrder: 2 },
|
|
83
|
+
* { id: 2, navOrder: 1 },
|
|
84
|
+
* ]);
|
|
85
|
+
*
|
|
86
|
+
* // Get catalog
|
|
87
|
+
* const catalog = await registry.catalog.get();
|
|
88
|
+
* ```
|
|
89
|
+
*/
|
|
90
|
+
export interface RegistryClient {
|
|
91
|
+
/** Module operations */
|
|
92
|
+
modules: ModuleOperations;
|
|
93
|
+
/** Catalog operations (read-only) */
|
|
94
|
+
catalog: CatalogOperations;
|
|
95
|
+
}
|
|
96
|
+
//# sourceMappingURL=interface.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"interface.d.ts","sourceRoot":"","sources":["../../../src/registry/client/interface.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EACV,gBAAgB,EAChB,eAAe,EACf,gBAAgB,EAChB,aAAa,EACb,OAAO,EACP,SAAS,EACT,mBAAmB,EACpB,MAAM,UAAU,CAAC;AAElB;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B;;;OAGG;IACH,OAAO,CAAC,OAAO,CAAC,EAAE,aAAa,GAAG,OAAO,CAAC,gBAAgB,EAAE,CAAC,CAAC;IAE9D;;;OAGG;IACH,IAAI,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAAC;IAE5C;;;OAGG;IACH,QAAQ,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAAC;IAErD;;;;OAIG;IACH,oBAAoB,CAAC,QAAQ,EAAE,mBAAmB,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAAC;IAEjG;;;;OAIG;IACH,MAAM,CAAC,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,eAAe,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAAC;IAErE;;;OAGG;IACH,MAAM,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAElC;;;OAGG;IACH,OAAO,CAAC,KAAK,EAAE,gBAAgB,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACnD;AAED;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC;;OAEG;IACH,GAAG,IAAI,OAAO,CAAC,OAAO,CAAC,CAAC;IAExB;;;OAGG;IACH,YAAY,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,CAAC,CAAC;CACvD;AAED;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,MAAM,WAAW,cAAc;IAC7B,wBAAwB;IACxB,OAAO,EAAE,gBAAgB,CAAC;IAE1B,qCAAqC;IACrC,OAAO,EAAE,iBAAiB,CAAC;CAC5B"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Registry Module
|
|
3
|
+
*
|
|
4
|
+
* Provides types and clients for module registry management.
|
|
5
|
+
*/
|
|
6
|
+
export type { AdminModuleManifest, ModuleCommand, ModulePermissions, ModuleOwners, ModuleStatus, RegisteredModule, UpdateModuleDto, ReorderModuleDto, ModuleFilters, Catalog, CatalogModule, ImportMap, } from './types';
|
|
7
|
+
export { validateManifest, parseManifest } from './types';
|
|
8
|
+
export type { RegistryClient, ModuleOperations, CatalogOperations } from './client';
|
|
9
|
+
export { createInMemoryRegistryClient, clearInMemoryRegistry, createHttpRegistryClient, type InMemoryRegistryOptions, type PreConfiguredModule, type HttpRegistryOptions, } from './client';
|
|
10
|
+
export type { RegistryContextValue, AdminShellRegistryProps, } from './AdminShellRegistry';
|
|
11
|
+
export { AdminShellRegistry, useRegistry, useRegistryClient, } from './AdminShellRegistry';
|
|
12
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/registry/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,YAAY,EACV,mBAAmB,EACnB,aAAa,EACb,iBAAiB,EACjB,YAAY,EACZ,YAAY,EACZ,gBAAgB,EAChB,eAAe,EACf,gBAAgB,EAChB,aAAa,EACb,OAAO,EACP,aAAa,EACb,SAAS,GACV,MAAM,SAAS,CAAC;AAEjB,OAAO,EAAE,gBAAgB,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAG1D,YAAY,EAAE,cAAc,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,MAAM,UAAU,CAAC;AAEpF,OAAO,EACL,4BAA4B,EAC5B,qBAAqB,EACrB,wBAAwB,EACxB,KAAK,uBAAuB,EAC5B,KAAK,mBAAmB,EACxB,KAAK,mBAAmB,GACzB,MAAM,UAAU,CAAC;AAGlB,YAAY,EACV,oBAAoB,EACpB,uBAAuB,GACxB,MAAM,sBAAsB,CAAC;AAE9B,OAAO,EACL,kBAAkB,EAClB,WAAW,EACX,iBAAiB,GAClB,MAAM,sBAAsB,CAAC"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Registry Module
|
|
3
|
+
*
|
|
4
|
+
* Provides types and clients for module registry management.
|
|
5
|
+
*/
|
|
6
|
+
export { validateManifest, parseManifest } from './types';
|
|
7
|
+
export { createInMemoryRegistryClient, clearInMemoryRegistry, createHttpRegistryClient, } from './client';
|
|
8
|
+
export { AdminShellRegistry, useRegistry, useRegistryClient, } from './AdminShellRegistry';
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Registry Types
|
|
3
|
+
*
|
|
4
|
+
* Re-exports all registry-related types.
|
|
5
|
+
*/
|
|
6
|
+
export type { AdminModuleManifest, ModuleCommand, ModulePermissions, ModuleOwners, ModuleStatus, } from './manifest';
|
|
7
|
+
export { validateManifest, parseManifest } from './manifest';
|
|
8
|
+
export type { RegisteredModule, UpdateModuleDto, ReorderModuleDto, ModuleFilters, Catalog, CatalogModule, ImportMap, } from './module';
|
|
9
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/registry/types/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,YAAY,EACV,mBAAmB,EACnB,aAAa,EACb,iBAAiB,EACjB,YAAY,EACZ,YAAY,GACb,MAAM,YAAY,CAAC;AAEpB,OAAO,EAAE,gBAAgB,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAE7D,YAAY,EACV,gBAAgB,EAChB,eAAe,EACf,gBAAgB,EAChB,aAAa,EACb,OAAO,EACP,aAAa,EACb,SAAS,GACV,MAAM,UAAU,CAAC"}
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Admin Module Manifest Schema
|
|
3
|
+
*
|
|
4
|
+
* This interface defines the structure of admin.module.json files
|
|
5
|
+
* that module developers create to register their modules.
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* Command within a module that can be searched and invoked
|
|
9
|
+
*/
|
|
10
|
+
export interface ModuleCommand {
|
|
11
|
+
/** Unique identifier for the command within the module */
|
|
12
|
+
id: string;
|
|
13
|
+
/** Human-readable title */
|
|
14
|
+
title: string;
|
|
15
|
+
/** i18n key for the title (for translation) */
|
|
16
|
+
titleKey?: string;
|
|
17
|
+
/** Route path for this command */
|
|
18
|
+
route: string;
|
|
19
|
+
/** Optional Lucide icon name in kebab-case (e.g., "clipboard-list", "file-text") */
|
|
20
|
+
icon?: string;
|
|
21
|
+
/** Keywords for search */
|
|
22
|
+
keywords?: string[];
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Permission configuration for a module
|
|
26
|
+
*/
|
|
27
|
+
export interface ModulePermissions {
|
|
28
|
+
/** Permissions required to view the module */
|
|
29
|
+
view?: string[];
|
|
30
|
+
/** Permissions required to edit within the module */
|
|
31
|
+
edit?: string[];
|
|
32
|
+
/** Permissions required to delete within the module */
|
|
33
|
+
delete?: string[];
|
|
34
|
+
/** Dangerous permissions that require extra confirmation */
|
|
35
|
+
dangerous?: string[];
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Module ownership information
|
|
39
|
+
*/
|
|
40
|
+
export interface ModuleOwners {
|
|
41
|
+
/** Team responsible for the module */
|
|
42
|
+
team?: string;
|
|
43
|
+
/** Support channel (e.g., Slack channel) */
|
|
44
|
+
supportChannel?: string;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Module status
|
|
48
|
+
*/
|
|
49
|
+
export type ModuleStatus = 'active' | 'deprecated' | 'disabled';
|
|
50
|
+
/**
|
|
51
|
+
* Admin Module Manifest
|
|
52
|
+
*
|
|
53
|
+
* The structure of admin.module.json files that define a module's metadata.
|
|
54
|
+
*/
|
|
55
|
+
export interface AdminModuleManifest {
|
|
56
|
+
/** Unique identifier for the module (e.g., "@admin/tasks") */
|
|
57
|
+
id: string;
|
|
58
|
+
/** Human-readable title */
|
|
59
|
+
title: string;
|
|
60
|
+
/** Base route where module is mounted (e.g., "/admin/tasks") */
|
|
61
|
+
routeBase: string;
|
|
62
|
+
/** i18n key for the title (for translation) */
|
|
63
|
+
titleKey?: string;
|
|
64
|
+
/** URL slug (derived from id if not provided) */
|
|
65
|
+
slug?: string;
|
|
66
|
+
/** Description of what the module does */
|
|
67
|
+
description?: string;
|
|
68
|
+
/** i18n key for the description (for translation) */
|
|
69
|
+
descriptionKey?: string;
|
|
70
|
+
/** Category for navigation grouping (e.g., "Tools", "Customer") */
|
|
71
|
+
category?: string;
|
|
72
|
+
/** Semantic version */
|
|
73
|
+
version?: string;
|
|
74
|
+
/** Lucide icon name in kebab-case (e.g., "users", "clipboard-list") */
|
|
75
|
+
icon?: string;
|
|
76
|
+
/** Keywords for search */
|
|
77
|
+
keywords?: string[];
|
|
78
|
+
/** Navigation order (lower = higher priority) */
|
|
79
|
+
navOrder?: number;
|
|
80
|
+
/** Module status */
|
|
81
|
+
status?: ModuleStatus;
|
|
82
|
+
/** Commands/actions available in this module */
|
|
83
|
+
commands?: ModuleCommand[];
|
|
84
|
+
/** Permission configuration */
|
|
85
|
+
permissions?: ModulePermissions;
|
|
86
|
+
/** Module ownership info */
|
|
87
|
+
owners?: ModuleOwners;
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Validates that an object is a valid AdminModuleManifest
|
|
91
|
+
*/
|
|
92
|
+
export declare function validateManifest(value: unknown): value is AdminModuleManifest;
|
|
93
|
+
/**
|
|
94
|
+
* Parse and validate a manifest from unknown input
|
|
95
|
+
* @throws Error if validation fails
|
|
96
|
+
*/
|
|
97
|
+
export declare function parseManifest(value: unknown): AdminModuleManifest;
|
|
98
|
+
//# sourceMappingURL=manifest.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"manifest.d.ts","sourceRoot":"","sources":["../../../src/registry/types/manifest.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,0DAA0D;IAC1D,EAAE,EAAE,MAAM,CAAC;IACX,2BAA2B;IAC3B,KAAK,EAAE,MAAM,CAAC;IACd,+CAA+C;IAC/C,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,kCAAkC;IAClC,KAAK,EAAE,MAAM,CAAC;IACd,oFAAoF;IACpF,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,0BAA0B;IAC1B,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;CACrB;AAED;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC,8CAA8C;IAC9C,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,qDAAqD;IACrD,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,uDAAuD;IACvD,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAClB,4DAA4D;IAC5D,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;CACtB;AAED;;GAEG;AACH,MAAM,WAAW,YAAY;IAC3B,sCAAsC;IACtC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,4CAA4C;IAC5C,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED;;GAEG;AACH,MAAM,MAAM,YAAY,GAAG,QAAQ,GAAG,YAAY,GAAG,UAAU,CAAC;AAEhE;;;;GAIG;AACH,MAAM,WAAW,mBAAmB;IAElC,8DAA8D;IAC9D,EAAE,EAAE,MAAM,CAAC;IACX,2BAA2B;IAC3B,KAAK,EAAE,MAAM,CAAC;IACd,gEAAgE;IAChE,SAAS,EAAE,MAAM,CAAC;IAGlB,+CAA+C;IAC/C,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,iDAAiD;IACjD,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,0CAA0C;IAC1C,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,qDAAqD;IACrD,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,mEAAmE;IACnE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,uBAAuB;IACvB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,uEAAuE;IACvE,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,0BAA0B;IAC1B,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;IACpB,iDAAiD;IACjD,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,oBAAoB;IACpB,MAAM,CAAC,EAAE,YAAY,CAAC;IAGtB,gDAAgD;IAChD,QAAQ,CAAC,EAAE,aAAa,EAAE,CAAC;IAG3B,+BAA+B;IAC/B,WAAW,CAAC,EAAE,iBAAiB,CAAC;IAGhC,4BAA4B;IAC5B,MAAM,CAAC,EAAE,YAAY,CAAC;CACvB;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,mBAAmB,CA4D7E;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,OAAO,GAAG,mBAAmB,CAKjE"}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Admin Module Manifest Schema
|
|
3
|
+
*
|
|
4
|
+
* This interface defines the structure of admin.module.json files
|
|
5
|
+
* that module developers create to register their modules.
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* Validates that an object is a valid AdminModuleManifest
|
|
9
|
+
*/
|
|
10
|
+
export function validateManifest(value) {
|
|
11
|
+
if (typeof value !== 'object' || value === null) {
|
|
12
|
+
return false;
|
|
13
|
+
}
|
|
14
|
+
const obj = value;
|
|
15
|
+
// Required fields
|
|
16
|
+
if (typeof obj.id !== 'string' || obj.id.trim() === '') {
|
|
17
|
+
return false;
|
|
18
|
+
}
|
|
19
|
+
if (typeof obj.title !== 'string' || obj.title.trim() === '') {
|
|
20
|
+
return false;
|
|
21
|
+
}
|
|
22
|
+
if (typeof obj.routeBase !== 'string' || !obj.routeBase.startsWith('/')) {
|
|
23
|
+
return false;
|
|
24
|
+
}
|
|
25
|
+
// Optional field validations
|
|
26
|
+
if (obj.slug !== undefined && typeof obj.slug !== 'string') {
|
|
27
|
+
return false;
|
|
28
|
+
}
|
|
29
|
+
if (obj.description !== undefined && typeof obj.description !== 'string') {
|
|
30
|
+
return false;
|
|
31
|
+
}
|
|
32
|
+
if (obj.category !== undefined && typeof obj.category !== 'string') {
|
|
33
|
+
return false;
|
|
34
|
+
}
|
|
35
|
+
if (obj.version !== undefined && typeof obj.version !== 'string') {
|
|
36
|
+
return false;
|
|
37
|
+
}
|
|
38
|
+
if (obj.icon !== undefined && typeof obj.icon !== 'string') {
|
|
39
|
+
return false;
|
|
40
|
+
}
|
|
41
|
+
if (obj.navOrder !== undefined && typeof obj.navOrder !== 'number') {
|
|
42
|
+
return false;
|
|
43
|
+
}
|
|
44
|
+
if (obj.status !== undefined &&
|
|
45
|
+
obj.status !== 'active' &&
|
|
46
|
+
obj.status !== 'deprecated' &&
|
|
47
|
+
obj.status !== 'disabled') {
|
|
48
|
+
return false;
|
|
49
|
+
}
|
|
50
|
+
if (obj.keywords !== undefined) {
|
|
51
|
+
if (!Array.isArray(obj.keywords))
|
|
52
|
+
return false;
|
|
53
|
+
if (!obj.keywords.every((k) => typeof k === 'string'))
|
|
54
|
+
return false;
|
|
55
|
+
}
|
|
56
|
+
if (obj.commands !== undefined) {
|
|
57
|
+
if (!Array.isArray(obj.commands))
|
|
58
|
+
return false;
|
|
59
|
+
for (const cmd of obj.commands) {
|
|
60
|
+
if (typeof cmd !== 'object' || cmd === null)
|
|
61
|
+
return false;
|
|
62
|
+
if (typeof cmd.id !== 'string')
|
|
63
|
+
return false;
|
|
64
|
+
if (typeof cmd.title !== 'string')
|
|
65
|
+
return false;
|
|
66
|
+
if (typeof cmd.route !== 'string')
|
|
67
|
+
return false;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
return true;
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Parse and validate a manifest from unknown input
|
|
74
|
+
* @throws Error if validation fails
|
|
75
|
+
*/
|
|
76
|
+
export function parseManifest(value) {
|
|
77
|
+
if (!validateManifest(value)) {
|
|
78
|
+
throw new Error('Invalid manifest: must have id, title, and routeBase (starting with /)');
|
|
79
|
+
}
|
|
80
|
+
return value;
|
|
81
|
+
}
|