@quazardous/qdadm 1.19.3
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/LICENSE +21 -0
- package/README.md +111 -0
- package/package.json +101 -0
- package/src/assets/logo.svg +6 -0
- package/src/auth/SessionAuthAdapter.ts +459 -0
- package/src/auth/index.ts +15 -0
- package/src/chain/ActiveStack.ts +154 -0
- package/src/chain/StackHydrator.ts +292 -0
- package/src/chain/index.ts +25 -0
- package/src/chain/useActiveStack.ts +120 -0
- package/src/chain/useStackHydrator.ts +155 -0
- package/src/components/BoolCell.vue +34 -0
- package/src/components/InfoBanner.vue +73 -0
- package/src/components/QdadmRoot.vue +52 -0
- package/src/components/SeverityTag.vue +86 -0
- package/src/components/dialogs/BulkStatusDialog.vue +60 -0
- package/src/components/dialogs/MultiStepDialog.vue +331 -0
- package/src/components/dialogs/SimpleDialog.vue +122 -0
- package/src/components/dialogs/UnsavedChangesDialog.vue +80 -0
- package/src/components/display/BannerZone.vue +65 -0
- package/src/components/display/CardsGrid.vue +72 -0
- package/src/components/display/CopyableId.vue +84 -0
- package/src/components/display/EmptyState.vue +62 -0
- package/src/components/display/IntensityBar.vue +190 -0
- package/src/components/display/RichCardsGrid.vue +101 -0
- package/src/components/edit/FormActions.vue +78 -0
- package/src/components/edit/FormField.vue +82 -0
- package/src/components/edit/FormInput.vue +158 -0
- package/src/components/edit/FormPage.vue +260 -0
- package/src/components/edit/FormTab.vue +217 -0
- package/src/components/edit/FormTabs.vue +120 -0
- package/src/components/edit/LookupField.vue +406 -0
- package/src/components/edit/LookupPickerDialog.vue +230 -0
- package/src/components/editors/JsonEditorFoldable.vue +470 -0
- package/src/components/editors/JsonStructuredField.vue +264 -0
- package/src/components/editors/JsonViewer.vue +51 -0
- package/src/components/editors/KeyValueEditor.vue +314 -0
- package/src/components/editors/LanguageEditor.vue +259 -0
- package/src/components/editors/PermissionEditor.vue +558 -0
- package/src/components/editors/ScopeEditor.vue +372 -0
- package/src/components/editors/VanillaJsonEditor.vue +183 -0
- package/src/components/index.ts +83 -0
- package/src/components/item/FieldGroups.vue +392 -0
- package/src/components/layout/AppLayout.vue +1032 -0
- package/src/components/layout/BaseLayout.vue +190 -0
- package/src/components/layout/Breadcrumb.vue +55 -0
- package/src/components/layout/DashboardLayout.vue +104 -0
- package/src/components/layout/FormLayout.vue +256 -0
- package/src/components/layout/ListLayout.vue +278 -0
- package/src/components/layout/PageHeader.vue +156 -0
- package/src/components/layout/PageLayout.vue +126 -0
- package/src/components/layout/PageNav.vue +192 -0
- package/src/components/layout/SidebarBox.vue +87 -0
- package/src/components/layout/Zone.vue +182 -0
- package/src/components/layout/defaults/DefaultBreadcrumb.vue +149 -0
- package/src/components/layout/defaults/DefaultFooter.vue +89 -0
- package/src/components/layout/defaults/DefaultFormActions.vue +67 -0
- package/src/components/layout/defaults/DefaultHeader.vue +78 -0
- package/src/components/layout/defaults/DefaultMenu.vue +188 -0
- package/src/components/layout/defaults/DefaultPagination.vue +75 -0
- package/src/components/layout/defaults/DefaultTable.vue +137 -0
- package/src/components/layout/defaults/DefaultUserInfo.vue +111 -0
- package/src/components/layout/defaults/index.ts +16 -0
- package/src/components/lists/ActionButtons.vue +49 -0
- package/src/components/lists/ActionColumn.vue +40 -0
- package/src/components/lists/FilterBar.vue +54 -0
- package/src/components/lists/ListPage.vue +467 -0
- package/src/components/pages/LoginPage.vue +334 -0
- package/src/components/pages/NotFoundPage.vue +98 -0
- package/src/components/show/ShowDisplay.vue +343 -0
- package/src/components/show/ShowField.vue +67 -0
- package/src/components/show/ShowPage.vue +431 -0
- package/src/composables/index.ts +155 -0
- package/src/composables/useApp.ts +67 -0
- package/src/composables/useAuth.ts +98 -0
- package/src/composables/useBareForm.ts +319 -0
- package/src/composables/useBreadcrumb.ts +252 -0
- package/src/composables/useChildPage.ts +113 -0
- package/src/composables/useCurrentEntity.ts +60 -0
- package/src/composables/useDeferred.ts +94 -0
- package/src/composables/useDirtyState.ts +138 -0
- package/src/composables/useEntityItemFormPage.ts +942 -0
- package/src/composables/useEntityItemFormPage.types.ts +451 -0
- package/src/composables/useEntityItemPage.ts +438 -0
- package/src/composables/useEntityItemShowPage.ts +722 -0
- package/src/composables/useFieldManager.ts +692 -0
- package/src/composables/useForm.ts +544 -0
- package/src/composables/useGuardStore.ts +53 -0
- package/src/composables/useHooks.ts +56 -0
- package/src/composables/useInfoBanner.ts +217 -0
- package/src/composables/useJsonSyntax.ts +122 -0
- package/src/composables/useLayoutResolver.ts +329 -0
- package/src/composables/useListPage.ts +1535 -0
- package/src/composables/useListPage.types.ts +437 -0
- package/src/composables/useListPage.utils.ts +101 -0
- package/src/composables/useNavContext.ts +439 -0
- package/src/composables/useNavigation.ts +216 -0
- package/src/composables/useOptionsLookup.ts +323 -0
- package/src/composables/usePageTitle.ts +84 -0
- package/src/composables/useSSEBridge.ts +142 -0
- package/src/composables/useSemanticBreadcrumb.ts +222 -0
- package/src/composables/useSidebarState.ts +24 -0
- package/src/composables/useSignals.ts +52 -0
- package/src/composables/useUnsavedChangesGuard.ts +155 -0
- package/src/composables/useUserImpersonator.ts +317 -0
- package/src/composables/useZoneRegistry.ts +252 -0
- package/src/core/bundles.ts +558 -0
- package/src/core/decorator.ts +420 -0
- package/src/core/extension.ts +470 -0
- package/src/core/index.ts +59 -0
- package/src/deferred/DeferredRegistry.ts +353 -0
- package/src/deferred/index.ts +15 -0
- package/src/editors/index.ts +12 -0
- package/src/entity/EntityManager.cache.ts +530 -0
- package/src/entity/EntityManager.crud.ts +615 -0
- package/src/entity/EntityManager.interface.ts +78 -0
- package/src/entity/EntityManager.query.ts +221 -0
- package/src/entity/EntityManager.relations.ts +151 -0
- package/src/entity/EntityManager.ts +944 -0
- package/src/entity/EntityManager.types.ts +288 -0
- package/src/entity/auth/CompositeAuthAdapter.ts +194 -0
- package/src/entity/auth/EntityAuthAdapter.ts +119 -0
- package/src/entity/auth/PermissiveAdapter.ts +43 -0
- package/src/entity/auth/RoleHierarchy.ts +128 -0
- package/src/entity/auth/SecurityChecker.ts +202 -0
- package/src/entity/auth/factory.ts +203 -0
- package/src/entity/auth/index.ts +47 -0
- package/src/entity/factory.test.js +189 -0
- package/src/entity/factory.ts +146 -0
- package/src/entity/index.ts +49 -0
- package/src/entity/storage/ApiStorage.ts +228 -0
- package/src/entity/storage/IStorage.ts +100 -0
- package/src/entity/storage/LocalStorage.ts +200 -0
- package/src/entity/storage/MemoryStorage.ts +184 -0
- package/src/entity/storage/MockApiStorage.ts +318 -0
- package/src/entity/storage/SdkStorage.ts +377 -0
- package/src/entity/storage/factory.test.js +159 -0
- package/src/entity/storage/factory.ts +209 -0
- package/src/entity/storage/index.ts +75 -0
- package/src/gen/FieldMapper.ts +122 -0
- package/src/gen/StorageProfileFactory.ts +93 -0
- package/src/gen/connectors/BaseConnector.ts +150 -0
- package/src/gen/connectors/ManualConnector.test.js +499 -0
- package/src/gen/connectors/ManualConnector.ts +414 -0
- package/src/gen/connectors/OpenAPIConnector.test.js +836 -0
- package/src/gen/connectors/OpenAPIConnector.ts +693 -0
- package/src/gen/connectors/__fixtures__/sample-openapi.json +311 -0
- package/src/gen/connectors/index.ts +27 -0
- package/src/gen/createManagers.ts +245 -0
- package/src/gen/decorators.ts +134 -0
- package/src/gen/generateManagers.test.js +540 -0
- package/src/gen/generateManagers.ts +398 -0
- package/src/gen/index.ts +66 -0
- package/src/gen/schema.ts +248 -0
- package/src/gen/vite-plugin.ts +114 -0
- package/src/generated/managers/testManager.js +45 -0
- package/src/generated/managers/testManager.ts +46 -0
- package/src/hooks/HookRegistry.ts +16 -0
- package/src/hooks/index.ts +15 -0
- package/src/i18n/I18n.ts +344 -0
- package/src/i18n/IncrementalDomainProvider.ts +153 -0
- package/src/i18n/InlineTranslationProvider.ts +4 -0
- package/src/i18n/LazyTranslationProvider.ts +102 -0
- package/src/i18n/MessagesRegistry.ts +4 -0
- package/src/i18n/Resolver.ts +4 -0
- package/src/i18n/__tests__/I18n.test.ts +169 -0
- package/src/i18n/__tests__/IncrementalDomainProvider.test.ts +146 -0
- package/src/i18n/__tests__/LazyTranslationProvider.test.ts +100 -0
- package/src/i18n/__tests__/Resolver.test.ts +271 -0
- package/src/i18n/defaults/DefaultCoreProvider.ts +28 -0
- package/src/i18n/defaults/core.en.yml +55 -0
- package/src/i18n/defaults/core.fr.yml +55 -0
- package/src/i18n/index.ts +55 -0
- package/src/i18n/loaders/raw-modules.d.ts +15 -0
- package/src/i18n/loaders/yaml.ts +35 -0
- package/src/i18n/strategies.ts +4 -0
- package/src/i18n/types.ts +34 -0
- package/src/i18n/useI18n.ts +34 -0
- package/src/index.ts +453 -0
- package/src/kernel/EventRouter.ts +23 -0
- package/src/kernel/Kernel.api.ts +79 -0
- package/src/kernel/Kernel.auth.ts +120 -0
- package/src/kernel/Kernel.i18n.ts +29 -0
- package/src/kernel/Kernel.modules.ts +170 -0
- package/src/kernel/Kernel.registries.ts +237 -0
- package/src/kernel/Kernel.routing.ts +334 -0
- package/src/kernel/Kernel.ts +460 -0
- package/src/kernel/Kernel.types.ts +263 -0
- package/src/kernel/Kernel.vue.ts +304 -0
- package/src/kernel/KernelContext.entities.ts +80 -0
- package/src/kernel/KernelContext.events.ts +57 -0
- package/src/kernel/KernelContext.i18n.ts +37 -0
- package/src/kernel/KernelContext.permissions.ts +38 -0
- package/src/kernel/KernelContext.routing.ts +280 -0
- package/src/kernel/KernelContext.ts +252 -0
- package/src/kernel/KernelContext.types.ts +173 -0
- package/src/kernel/KernelContext.zones.ts +54 -0
- package/src/kernel/Module.ts +169 -0
- package/src/kernel/ModuleLoader.ts +645 -0
- package/src/kernel/SSEBridge.ts +11 -0
- package/src/kernel/SignalBus.ts +48 -0
- package/src/kernel/index.ts +56 -0
- package/src/module/index.ts +33 -0
- package/src/module/moduleRegistry.ts +492 -0
- package/src/modules/debug/AuthCollector.ts +501 -0
- package/src/modules/debug/Collector.ts +20 -0
- package/src/modules/debug/DebugBridge.ts +14 -0
- package/src/modules/debug/DebugModule.ts +220 -0
- package/src/modules/debug/EntitiesCollector.ts +839 -0
- package/src/modules/debug/ErrorCollector.ts +4 -0
- package/src/modules/debug/I18nCollector.ts +9 -0
- package/src/modules/debug/LocalStorageAdapter.ts +7 -0
- package/src/modules/debug/RouterCollector.ts +449 -0
- package/src/modules/debug/SignalCollector.ts +4 -0
- package/src/modules/debug/ToastCollector.ts +4 -0
- package/src/modules/debug/ZonesCollector.ts +447 -0
- package/src/modules/debug/components/DebugBar.vue +31 -0
- package/src/modules/debug/components/adminPanelsConfig.ts +42 -0
- package/src/modules/debug/components/index.ts +9 -0
- package/src/modules/debug/components/panels/AuthPanel.vue +267 -0
- package/src/modules/debug/components/panels/EntitiesPanel.vue +572 -0
- package/src/modules/debug/components/panels/I18nPanel.vue +738 -0
- package/src/modules/debug/components/panels/RouterPanel.vue +440 -0
- package/src/modules/debug/components/panels/ZonesPanel.vue +133 -0
- package/src/modules/debug/components/panels/index.ts +16 -0
- package/src/modules/debug/index.ts +58 -0
- package/src/modules/debug/styles.scss +2671 -0
- package/src/notifications/NotificationBadge.vue +35 -0
- package/src/notifications/NotificationListener.vue +71 -0
- package/src/notifications/NotificationModule.ts +76 -0
- package/src/notifications/NotificationPanel.vue +478 -0
- package/src/notifications/NotificationStore.ts +288 -0
- package/src/notifications/index.ts +42 -0
- package/src/notifications/styles.scss +32 -0
- package/src/orchestrator/Orchestrator.ts +427 -0
- package/src/orchestrator/index.ts +8 -0
- package/src/orchestrator/useOrchestrator.ts +80 -0
- package/src/plugin.ts +251 -0
- package/src/query/FilterQuery.ts +306 -0
- package/src/query/QueryExecutor.ts +341 -0
- package/src/query/index.ts +16 -0
- package/src/security/EntityRolesProvider.ts +385 -0
- package/src/security/PermissionMatcher.ts +152 -0
- package/src/security/PermissionRegistry.ts +273 -0
- package/src/security/PersistableRolesProvider.ts +584 -0
- package/src/security/RolesManager.ts +136 -0
- package/src/security/RolesProvider.ts +167 -0
- package/src/security/RolesProviderStorage.ts +211 -0
- package/src/security/SecurityModule.ts +94 -0
- package/src/security/StaticRolesProvider.ts +117 -0
- package/src/security/UsersManager.ts +163 -0
- package/src/security/index.ts +77 -0
- package/src/security/pages/RoleForm.vue +276 -0
- package/src/security/pages/RoleList.vue +123 -0
- package/src/styles/_alerts.scss +95 -0
- package/src/styles/_buttons.scss +391 -0
- package/src/styles/_cards.scss +241 -0
- package/src/styles/_code.scss +78 -0
- package/src/styles/_dialogs.scss +55 -0
- package/src/styles/_filter-bar.scss +70 -0
- package/src/styles/_forms.scss +434 -0
- package/src/styles/_helpers.scss +153 -0
- package/src/styles/_lists.scss +225 -0
- package/src/styles/_main.scss +356 -0
- package/src/styles/_markdown.scss +88 -0
- package/src/styles/_responsive.scss +255 -0
- package/src/styles/_show-pages.scss +186 -0
- package/src/styles/_sidebar.scss +380 -0
- package/src/styles/_states.scss +115 -0
- package/src/styles/_stats.scss +47 -0
- package/src/styles/_variables.scss +224 -0
- package/src/styles/index.scss +38 -0
- package/src/styles/theme/_components.scss +331 -0
- package/src/styles/theme/_index.scss +10 -0
- package/src/styles/theme/_tokens.scss +147 -0
- package/src/styles/theme/_utilities.scss +175 -0
- package/src/toast/ToastBridgeModule.ts +68 -0
- package/src/toast/ToastListener.vue +55 -0
- package/src/toast/index.ts +26 -0
- package/src/toast/useSignalToast.ts +154 -0
- package/src/types/index.ts +285 -0
- package/src/types/pluralize.d.ts +19 -0
- package/src/types/quarkernel.d.ts +50 -0
- package/src/utils/formatters.ts +174 -0
- package/src/utils/index.ts +35 -0
- package/src/utils/transformers.ts +131 -0
- package/src/vite/qdadmDebugPlugin.ts +401 -0
- package/src/vite-env.d.ts +50 -0
- package/src/zones/ZoneRegistry.ts +934 -0
- package/src/zones/index.ts +29 -0
- package/src/zones/zones.ts +191 -0
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Patch Kernel prototype with i18n-related methods.
|
|
3
|
+
*
|
|
4
|
+
* Adds:
|
|
5
|
+
* - kernel.i18n : I18n instance
|
|
6
|
+
* - _createI18n() : init step
|
|
7
|
+
* - _bootstrapI18n() : warmup step (loads default + fallback locales)
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import { I18n } from '../i18n/I18n'
|
|
11
|
+
import type { I18nOptions } from '../i18n/types'
|
|
12
|
+
|
|
13
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
14
|
+
type Self = any
|
|
15
|
+
|
|
16
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
17
|
+
export function applyI18nMethods(KernelClass: { prototype: any }): void {
|
|
18
|
+
const proto = KernelClass.prototype as Self
|
|
19
|
+
|
|
20
|
+
proto._createI18n = function (this: Self): void {
|
|
21
|
+
const opts = (this.options.i18n as I18nOptions | undefined) ?? {}
|
|
22
|
+
this.i18nInstance = new I18n(opts, { signals: this.signals })
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
proto._bootstrapI18n = function (this: Self): Promise<void> {
|
|
26
|
+
if (!this.i18nInstance) return Promise.resolve()
|
|
27
|
+
return this.i18nInstance.bootstrap()
|
|
28
|
+
}
|
|
29
|
+
}
|
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
import { initModules, setSectionOrder } from '../module/moduleRegistry'
|
|
2
|
+
import { createModuleLoader, type ModuleLike } from './ModuleLoader'
|
|
3
|
+
import { createKernelContext, type KernelContext } from './KernelContext'
|
|
4
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
5
|
+
type Self = any
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Patch Kernel prototype with module-related methods.
|
|
9
|
+
*/
|
|
10
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
11
|
+
export function applyModuleMethods(KernelClass: { prototype: any }): void {
|
|
12
|
+
const proto = KernelClass.prototype as Self
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Fire entity cache warmups
|
|
16
|
+
*/
|
|
17
|
+
proto._fireWarmups = function (this: Self): void {
|
|
18
|
+
if (this.i18nInstance) {
|
|
19
|
+
// Fire-and-forget bootstrap; locale-sensitive pages await
|
|
20
|
+
// 'i18n:locale:{loc}:ready' via DeferredRegistry if needed.
|
|
21
|
+
void this._bootstrapI18n()
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
const warmup = this.options.warmup ?? true
|
|
25
|
+
if (!warmup) return
|
|
26
|
+
|
|
27
|
+
this.orchestrator!.fireWarmups()
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Initialize legacy modules from glob import
|
|
32
|
+
*/
|
|
33
|
+
proto._initModules = function (this: Self): void {
|
|
34
|
+
if (this.options.sectionOrder) {
|
|
35
|
+
setSectionOrder(this.options.sectionOrder)
|
|
36
|
+
}
|
|
37
|
+
if (this.options.modules) {
|
|
38
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
39
|
+
initModules(this.options.modules as any, {
|
|
40
|
+
...this.options.modulesOptions,
|
|
41
|
+
zones: this.zoneRegistry,
|
|
42
|
+
signals: this.signals,
|
|
43
|
+
hooks: this.hookRegistry,
|
|
44
|
+
deferred: this.deferred,
|
|
45
|
+
} as any)
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Create KernelContext for module connection
|
|
51
|
+
*/
|
|
52
|
+
proto._createModuleContext = function (this: Self, module: ModuleLike): KernelContext {
|
|
53
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
54
|
+
return createKernelContext(this as any, module as any)
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Load new-style modules synchronously
|
|
59
|
+
*/
|
|
60
|
+
proto._loadModulesSync = function (this: Self): void {
|
|
61
|
+
const { moduleDefs } = this.options
|
|
62
|
+
if (!moduleDefs?.length) return
|
|
63
|
+
|
|
64
|
+
this.moduleLoader = createModuleLoader()
|
|
65
|
+
|
|
66
|
+
for (const mod of moduleDefs) {
|
|
67
|
+
this.moduleLoader.add(mod as ModuleLike)
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
// Access private method for sorting
|
|
71
|
+
const sorted = (this.moduleLoader as unknown as { _topologicalSort(): string[] })._topologicalSort()
|
|
72
|
+
const registered = (this.moduleLoader as unknown as { _registered: Map<string, ModuleLike> })._registered
|
|
73
|
+
const loaded = (this.moduleLoader as unknown as { _loaded: Map<string, ModuleLike> })._loaded
|
|
74
|
+
const loadOrder = (this.moduleLoader as unknown as { _loadOrder: string[] })._loadOrder
|
|
75
|
+
|
|
76
|
+
for (const name of sorted) {
|
|
77
|
+
const module = registered.get(name)
|
|
78
|
+
if (!module) continue
|
|
79
|
+
|
|
80
|
+
const ctx = this._createModuleContext(module)
|
|
81
|
+
|
|
82
|
+
if (!module.enabled(ctx as unknown as Parameters<typeof module.enabled>[0])) {
|
|
83
|
+
continue
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
if (typeof module.loadStyles === 'function') {
|
|
87
|
+
const styleResult = module.loadStyles()
|
|
88
|
+
if (styleResult instanceof Promise) {
|
|
89
|
+
styleResult.catch((err) => {
|
|
90
|
+
console.warn(`[Kernel] Module '${name}' styles failed:`, err)
|
|
91
|
+
})
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
const result = module.connect(ctx as unknown as Parameters<typeof module.connect>[0])
|
|
96
|
+
|
|
97
|
+
if (result instanceof Promise) {
|
|
98
|
+
result.catch((err) => {
|
|
99
|
+
console.error(`[Kernel] Async module '${name}' failed:`, err)
|
|
100
|
+
})
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
loaded.set(name, module)
|
|
104
|
+
loadOrder.push(name)
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* Load new-style modules asynchronously
|
|
110
|
+
*/
|
|
111
|
+
proto._loadModules = async function (this: Self): Promise<void> {
|
|
112
|
+
const { moduleDefs } = this.options
|
|
113
|
+
if (!moduleDefs?.length) return
|
|
114
|
+
|
|
115
|
+
this.moduleLoader = createModuleLoader()
|
|
116
|
+
|
|
117
|
+
for (const mod of moduleDefs) {
|
|
118
|
+
this.moduleLoader.add(mod as ModuleLike)
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
const sorted = (this.moduleLoader as unknown as { _topologicalSort(): string[] })._topologicalSort()
|
|
122
|
+
const registered = (this.moduleLoader as unknown as { _registered: Map<string, ModuleLike> })._registered
|
|
123
|
+
const loaded = (this.moduleLoader as unknown as { _loaded: Map<string, ModuleLike> })._loaded
|
|
124
|
+
const loadOrder = (this.moduleLoader as unknown as { _loadOrder: string[] })._loadOrder
|
|
125
|
+
|
|
126
|
+
for (const name of sorted) {
|
|
127
|
+
const module = registered.get(name)
|
|
128
|
+
if (!module) continue
|
|
129
|
+
|
|
130
|
+
const ctx = this._createModuleContext(module)
|
|
131
|
+
|
|
132
|
+
if (!module.enabled(ctx as unknown as Parameters<typeof module.enabled>[0])) {
|
|
133
|
+
continue
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
if (typeof module.loadStyles === 'function') {
|
|
137
|
+
await module.loadStyles()
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
await module.connect(ctx as unknown as Parameters<typeof module.connect>[0])
|
|
141
|
+
|
|
142
|
+
loaded.set(name, module)
|
|
143
|
+
loadOrder.push(name)
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
/**
|
|
148
|
+
* Wire modules that need orchestrator (phase 2)
|
|
149
|
+
*/
|
|
150
|
+
proto._wireModules = function (this: Self): void {
|
|
151
|
+
if (!this.moduleLoader) return
|
|
152
|
+
|
|
153
|
+
const result = this.signals!.emit('kernel:ready', { ready: true })
|
|
154
|
+
|
|
155
|
+
if (result instanceof Promise) {
|
|
156
|
+
result.catch((err) => {
|
|
157
|
+
console.error('[Kernel] kernel:ready handler failed:', err)
|
|
158
|
+
})
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
/**
|
|
163
|
+
* Wire modules that need orchestrator (phase 2) - async version
|
|
164
|
+
*/
|
|
165
|
+
proto._wireModulesAsync = async function (this: Self): Promise<void> {
|
|
166
|
+
if (!this.moduleLoader) return
|
|
167
|
+
|
|
168
|
+
await this.signals!.emit('kernel:ready', { ready: true })
|
|
169
|
+
}
|
|
170
|
+
}
|
|
@@ -0,0 +1,237 @@
|
|
|
1
|
+
import { createSignalBus } from './SignalBus'
|
|
2
|
+
import { createZoneRegistry } from '../zones/ZoneRegistry'
|
|
3
|
+
import { createHookRegistry } from '../hooks/HookRegistry'
|
|
4
|
+
import { createSecurityChecker } from '../entity/auth/SecurityChecker'
|
|
5
|
+
import { PermissionRegistry } from '../security/PermissionRegistry'
|
|
6
|
+
import { StaticRoleProvider } from '../security/StaticRolesProvider'
|
|
7
|
+
import { createManagers, type ManagerFactoryContext } from '../entity/factory.js'
|
|
8
|
+
import { defaultStorageResolver } from '../entity/storage/factory'
|
|
9
|
+
import { createDeferredRegistry } from '../deferred/DeferredRegistry.js'
|
|
10
|
+
import { createEventRouter } from './EventRouter'
|
|
11
|
+
import { createSSEBridge } from './SSEBridge'
|
|
12
|
+
import { ActiveStack } from '../chain/ActiveStack.js'
|
|
13
|
+
import { StackHydrator } from '../chain/StackHydrator.js'
|
|
14
|
+
import { Orchestrator } from '../orchestrator/Orchestrator'
|
|
15
|
+
import type { EntityAuthAdapter } from '../entity/auth/EntityAuthAdapter'
|
|
16
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
17
|
+
type Self = any
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Patch Kernel prototype with registry-related methods.
|
|
21
|
+
*/
|
|
22
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
23
|
+
export function applyRegistryMethods(KernelClass: { prototype: any }): void {
|
|
24
|
+
const proto = KernelClass.prototype as Self
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Create signal bus for event-driven communication.
|
|
28
|
+
*
|
|
29
|
+
* When `options.existingSignals` is provided (host shell already
|
|
30
|
+
* owns a bus), reuse it instead of spinning up a fresh one. This
|
|
31
|
+
* is what lets qdcms and qdadm share entity events when they're
|
|
32
|
+
* mounted on the same Vue app.
|
|
33
|
+
*/
|
|
34
|
+
proto._createSignalBus = function (this: Self): void {
|
|
35
|
+
if (this.options.existingSignals) {
|
|
36
|
+
this.signals = this.options.existingSignals
|
|
37
|
+
return
|
|
38
|
+
}
|
|
39
|
+
const debug = this.options.debug ?? false
|
|
40
|
+
this.signals = createSignalBus({ debug })
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Create hook registry for Drupal-inspired extensibility
|
|
45
|
+
*/
|
|
46
|
+
proto._createHookRegistry = function (this: Self): void {
|
|
47
|
+
const debug = this.options.debug ?? false
|
|
48
|
+
this.hookRegistry = createHookRegistry({
|
|
49
|
+
kernel: this.signals!.getKernel(),
|
|
50
|
+
debug,
|
|
51
|
+
})
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Create orchestrator with managers and signal bus
|
|
56
|
+
*/
|
|
57
|
+
proto._createOrchestrator = function (this: Self): void {
|
|
58
|
+
const factoryContext = {
|
|
59
|
+
storageResolver: this.options.storageResolver || defaultStorageResolver,
|
|
60
|
+
managerResolver: this.options.managerResolver,
|
|
61
|
+
managerRegistry: this.options.managerRegistry || {},
|
|
62
|
+
} as ManagerFactoryContext
|
|
63
|
+
|
|
64
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
65
|
+
const managers = createManagers((this.options.managers || {}) as any, factoryContext)
|
|
66
|
+
|
|
67
|
+
this.orchestrator = new Orchestrator({
|
|
68
|
+
managers,
|
|
69
|
+
signals: this.signals,
|
|
70
|
+
hooks: this.hookRegistry,
|
|
71
|
+
deferred: this.deferred,
|
|
72
|
+
entityAuthAdapter: (this.options.entityAuthAdapter as EntityAuthAdapter) || null,
|
|
73
|
+
})
|
|
74
|
+
|
|
75
|
+
// Pass kernel options to orchestrator (avoid circular reference for Vue reactivity)
|
|
76
|
+
this.orchestrator.kernelOptions = {
|
|
77
|
+
defaultEntityCacheTtlMs: this.options.defaultEntityCacheTtlMs,
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
if (this.options.toast) {
|
|
81
|
+
this.orchestrator.setToastConfig(this.options.toast)
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* Create PermissionRegistry early so modules can register permissions
|
|
87
|
+
*/
|
|
88
|
+
proto._createPermissionRegistry = function (this: Self): void {
|
|
89
|
+
this.permissionRegistry = new PermissionRegistry()
|
|
90
|
+
this._registerCorePermissions()
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* Register core system permissions provided by the framework
|
|
95
|
+
*/
|
|
96
|
+
proto._registerCorePermissions = function (this: Self): void {
|
|
97
|
+
this.permissionRegistry!.register('auth', {
|
|
98
|
+
impersonate: 'Impersonate other users',
|
|
99
|
+
manage: 'Manage authentication settings',
|
|
100
|
+
})
|
|
101
|
+
|
|
102
|
+
this.permissionRegistry!.register('admin', {
|
|
103
|
+
access: 'Access admin panel',
|
|
104
|
+
config: 'Edit system configuration',
|
|
105
|
+
})
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* Setup security layer (role hierarchy, permissions)
|
|
110
|
+
*/
|
|
111
|
+
proto._setupSecurity = function (this: Self): void {
|
|
112
|
+
const { security, entityAuthAdapter } = this.options
|
|
113
|
+
|
|
114
|
+
if (!this.permissionRegistry) {
|
|
115
|
+
this.permissionRegistry = new PermissionRegistry()
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
if (!security) return
|
|
119
|
+
|
|
120
|
+
let rolesProvider = security.rolesProvider
|
|
121
|
+
if (!rolesProvider && (security.role_permissions || security.role_hierarchy)) {
|
|
122
|
+
rolesProvider = new StaticRoleProvider({
|
|
123
|
+
role_hierarchy: security.role_hierarchy || {},
|
|
124
|
+
role_permissions: security.role_permissions || {},
|
|
125
|
+
role_labels: security.role_labels || {},
|
|
126
|
+
})
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
this.securityChecker = createSecurityChecker({
|
|
130
|
+
rolesProvider: rolesProvider || undefined,
|
|
131
|
+
getCurrentUser: () =>
|
|
132
|
+
(entityAuthAdapter as EntityAuthAdapter | null)?.getCurrentUser?.() || null,
|
|
133
|
+
})
|
|
134
|
+
|
|
135
|
+
// Store entity_permissions config (augment securityChecker for EntityManager to use)
|
|
136
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
137
|
+
;(this.securityChecker as any).entityPermissions = security.entity_permissions ?? false
|
|
138
|
+
|
|
139
|
+
const adapter = entityAuthAdapter as EntityAuthAdapter | null
|
|
140
|
+
if (adapter?.setSecurityChecker) {
|
|
141
|
+
adapter.setSecurityChecker(this.securityChecker)
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
if (rolesProvider?.install) {
|
|
145
|
+
const ctx = {
|
|
146
|
+
orchestrator: this.orchestrator,
|
|
147
|
+
signals: this.signals,
|
|
148
|
+
}
|
|
149
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
150
|
+
rolesProvider.install(ctx as any)
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
/**
|
|
155
|
+
* Create zone registry for extensible UI composition
|
|
156
|
+
*/
|
|
157
|
+
proto._createZoneRegistry = function (this: Self): void {
|
|
158
|
+
const debug = this.options.debug ?? false
|
|
159
|
+
this.zoneRegistry = createZoneRegistry({ debug })
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
/**
|
|
163
|
+
* Create active stack for navigation state
|
|
164
|
+
*/
|
|
165
|
+
proto._createActiveStack = function (this: Self): void {
|
|
166
|
+
this.activeStack = new ActiveStack(this.signals!)
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
/**
|
|
170
|
+
* Create stack hydrator for async data loading
|
|
171
|
+
*/
|
|
172
|
+
proto._createStackHydrator = function (this: Self): void {
|
|
173
|
+
this.stackHydrator = new StackHydrator(
|
|
174
|
+
this.activeStack!,
|
|
175
|
+
this.orchestrator!,
|
|
176
|
+
this.signals!
|
|
177
|
+
)
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
/**
|
|
181
|
+
* Create deferred registry for async service loading
|
|
182
|
+
*/
|
|
183
|
+
proto._createDeferredRegistry = function (this: Self): void {
|
|
184
|
+
const debug = this.options.debug ?? false
|
|
185
|
+
this.deferred = createDeferredRegistry({
|
|
186
|
+
kernel: this.signals?.getKernel() || null,
|
|
187
|
+
debug,
|
|
188
|
+
})
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
/**
|
|
192
|
+
* Create EventRouter for declarative signal routing
|
|
193
|
+
*/
|
|
194
|
+
proto._createEventRouter = function (this: Self): void {
|
|
195
|
+
const { eventRouter: routes } = this.options
|
|
196
|
+
if (!routes || Object.keys(routes).length === 0) return
|
|
197
|
+
|
|
198
|
+
const debug = this.options.debug ?? false
|
|
199
|
+
this.eventRouter = createEventRouter({
|
|
200
|
+
signals: this.signals!,
|
|
201
|
+
routes,
|
|
202
|
+
debug,
|
|
203
|
+
})
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
/**
|
|
207
|
+
* Create SSEBridge for Server-Sent Events to SignalBus integration
|
|
208
|
+
*/
|
|
209
|
+
proto._createSSEBridge = function (this: Self): void {
|
|
210
|
+
const { sse, authAdapter } = this.options
|
|
211
|
+
if (!sse?.url) return
|
|
212
|
+
|
|
213
|
+
const debug = this.options.debug ?? false
|
|
214
|
+
|
|
215
|
+
const getToken = authAdapter?.getToken
|
|
216
|
+
? () => authAdapter.getToken!()
|
|
217
|
+
: () => localStorage.getItem('auth_token')
|
|
218
|
+
|
|
219
|
+
this.sseBridge = createSSEBridge({
|
|
220
|
+
signals: this.signals!,
|
|
221
|
+
url: sse.url,
|
|
222
|
+
reconnectDelay: sse.reconnectDelay ?? 5000,
|
|
223
|
+
signalPrefix: sse.signalPrefix ?? 'sse',
|
|
224
|
+
autoConnect: sse.autoConnect ?? false,
|
|
225
|
+
withCredentials: sse.withCredentials ?? false,
|
|
226
|
+
tokenParam: sse.tokenParam ?? 'token',
|
|
227
|
+
getToken,
|
|
228
|
+
debug,
|
|
229
|
+
})
|
|
230
|
+
|
|
231
|
+
if (sse.events?.length) {
|
|
232
|
+
this.signals!.once('sse:connected', () => {
|
|
233
|
+
this.sseBridge!.registerEvents(sse.events!)
|
|
234
|
+
})
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
}
|