@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,311 @@
|
|
|
1
|
+
{
|
|
2
|
+
"openapi": "3.0.0",
|
|
3
|
+
"info": {
|
|
4
|
+
"title": "Sample API",
|
|
5
|
+
"version": "1.0.0"
|
|
6
|
+
},
|
|
7
|
+
"paths": {
|
|
8
|
+
"/api/users": {
|
|
9
|
+
"get": {
|
|
10
|
+
"summary": "List users",
|
|
11
|
+
"responses": {
|
|
12
|
+
"200": {
|
|
13
|
+
"description": "Success",
|
|
14
|
+
"content": {
|
|
15
|
+
"application/json": {
|
|
16
|
+
"schema": {
|
|
17
|
+
"type": "object",
|
|
18
|
+
"properties": {
|
|
19
|
+
"data": {
|
|
20
|
+
"type": "array",
|
|
21
|
+
"items": {
|
|
22
|
+
"$ref": "#/components/schemas/User"
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
},
|
|
32
|
+
"post": {
|
|
33
|
+
"summary": "Create user",
|
|
34
|
+
"requestBody": {
|
|
35
|
+
"content": {
|
|
36
|
+
"application/json": {
|
|
37
|
+
"schema": {
|
|
38
|
+
"$ref": "#/components/schemas/CreateUserRequest"
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
},
|
|
43
|
+
"responses": {
|
|
44
|
+
"201": {
|
|
45
|
+
"description": "Created",
|
|
46
|
+
"content": {
|
|
47
|
+
"application/json": {
|
|
48
|
+
"schema": {
|
|
49
|
+
"type": "object",
|
|
50
|
+
"properties": {
|
|
51
|
+
"data": {
|
|
52
|
+
"$ref": "#/components/schemas/User"
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
},
|
|
62
|
+
"/api/users/{id}": {
|
|
63
|
+
"get": {
|
|
64
|
+
"summary": "Get user by ID",
|
|
65
|
+
"responses": {
|
|
66
|
+
"200": {
|
|
67
|
+
"description": "Success",
|
|
68
|
+
"content": {
|
|
69
|
+
"application/json": {
|
|
70
|
+
"schema": {
|
|
71
|
+
"type": "object",
|
|
72
|
+
"properties": {
|
|
73
|
+
"data": {
|
|
74
|
+
"$ref": "#/components/schemas/User"
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
},
|
|
84
|
+
"/api/posts": {
|
|
85
|
+
"get": {
|
|
86
|
+
"summary": "List posts",
|
|
87
|
+
"responses": {
|
|
88
|
+
"200": {
|
|
89
|
+
"description": "Success",
|
|
90
|
+
"content": {
|
|
91
|
+
"application/json": {
|
|
92
|
+
"schema": {
|
|
93
|
+
"type": "object",
|
|
94
|
+
"properties": {
|
|
95
|
+
"data": {
|
|
96
|
+
"type": "array",
|
|
97
|
+
"items": {
|
|
98
|
+
"$ref": "#/components/schemas/Post"
|
|
99
|
+
}
|
|
100
|
+
},
|
|
101
|
+
"pagination": {
|
|
102
|
+
"type": "object",
|
|
103
|
+
"properties": {
|
|
104
|
+
"page": { "type": "integer" },
|
|
105
|
+
"total": { "type": "integer" }
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
},
|
|
116
|
+
"/api/posts/{id}": {
|
|
117
|
+
"get": {
|
|
118
|
+
"summary": "Get post by ID",
|
|
119
|
+
"responses": {
|
|
120
|
+
"200": {
|
|
121
|
+
"description": "Success",
|
|
122
|
+
"content": {
|
|
123
|
+
"application/json": {
|
|
124
|
+
"schema": {
|
|
125
|
+
"type": "object",
|
|
126
|
+
"properties": {
|
|
127
|
+
"data": {
|
|
128
|
+
"$ref": "#/components/schemas/Post"
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
},
|
|
138
|
+
"/api/categories": {
|
|
139
|
+
"get": {
|
|
140
|
+
"summary": "List categories",
|
|
141
|
+
"responses": {
|
|
142
|
+
"200": {
|
|
143
|
+
"description": "Success",
|
|
144
|
+
"content": {
|
|
145
|
+
"application/json": {
|
|
146
|
+
"schema": {
|
|
147
|
+
"type": "object",
|
|
148
|
+
"properties": {
|
|
149
|
+
"data": {
|
|
150
|
+
"type": "array",
|
|
151
|
+
"items": {
|
|
152
|
+
"$ref": "#/components/schemas/Category"
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
},
|
|
163
|
+
"/internal/metrics": {
|
|
164
|
+
"get": {
|
|
165
|
+
"summary": "Internal metrics",
|
|
166
|
+
"tags": ["internal"],
|
|
167
|
+
"responses": {
|
|
168
|
+
"200": {
|
|
169
|
+
"description": "Success",
|
|
170
|
+
"content": {
|
|
171
|
+
"application/json": {
|
|
172
|
+
"schema": {
|
|
173
|
+
"type": "object"
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
},
|
|
182
|
+
"components": {
|
|
183
|
+
"schemas": {
|
|
184
|
+
"User": {
|
|
185
|
+
"type": "object",
|
|
186
|
+
"required": ["email"],
|
|
187
|
+
"properties": {
|
|
188
|
+
"id": {
|
|
189
|
+
"type": "integer",
|
|
190
|
+
"readOnly": true,
|
|
191
|
+
"description": "User ID"
|
|
192
|
+
},
|
|
193
|
+
"email": {
|
|
194
|
+
"type": "string",
|
|
195
|
+
"format": "email",
|
|
196
|
+
"description": "Email address"
|
|
197
|
+
},
|
|
198
|
+
"name": {
|
|
199
|
+
"type": "string",
|
|
200
|
+
"description": "Full name"
|
|
201
|
+
},
|
|
202
|
+
"created_at": {
|
|
203
|
+
"type": "string",
|
|
204
|
+
"format": "date-time",
|
|
205
|
+
"readOnly": true,
|
|
206
|
+
"description": "Creation date"
|
|
207
|
+
},
|
|
208
|
+
"website": {
|
|
209
|
+
"type": "string",
|
|
210
|
+
"format": "uri",
|
|
211
|
+
"description": "Personal website"
|
|
212
|
+
},
|
|
213
|
+
"uuid": {
|
|
214
|
+
"type": "string",
|
|
215
|
+
"format": "uuid",
|
|
216
|
+
"description": "Unique identifier"
|
|
217
|
+
},
|
|
218
|
+
"active": {
|
|
219
|
+
"type": "boolean",
|
|
220
|
+
"default": true,
|
|
221
|
+
"description": "Is active"
|
|
222
|
+
},
|
|
223
|
+
"role": {
|
|
224
|
+
"type": "string",
|
|
225
|
+
"enum": ["admin", "user", "guest"],
|
|
226
|
+
"default": "user",
|
|
227
|
+
"description": "User role"
|
|
228
|
+
},
|
|
229
|
+
"tags": {
|
|
230
|
+
"type": "array",
|
|
231
|
+
"items": { "type": "string" },
|
|
232
|
+
"description": "User tags"
|
|
233
|
+
},
|
|
234
|
+
"metadata": {
|
|
235
|
+
"type": "object",
|
|
236
|
+
"description": "Extra metadata"
|
|
237
|
+
},
|
|
238
|
+
"profile": {
|
|
239
|
+
"type": "object",
|
|
240
|
+
"properties": {
|
|
241
|
+
"bio": { "type": "string" },
|
|
242
|
+
"avatar": { "type": "string", "format": "uri" }
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
},
|
|
247
|
+
"CreateUserRequest": {
|
|
248
|
+
"type": "object",
|
|
249
|
+
"required": ["email", "name"],
|
|
250
|
+
"properties": {
|
|
251
|
+
"email": {
|
|
252
|
+
"type": "string",
|
|
253
|
+
"format": "email"
|
|
254
|
+
},
|
|
255
|
+
"name": {
|
|
256
|
+
"type": "string"
|
|
257
|
+
},
|
|
258
|
+
"password": {
|
|
259
|
+
"type": "string",
|
|
260
|
+
"format": "password"
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
},
|
|
264
|
+
"Post": {
|
|
265
|
+
"type": "object",
|
|
266
|
+
"required": ["title"],
|
|
267
|
+
"properties": {
|
|
268
|
+
"id": {
|
|
269
|
+
"type": "integer",
|
|
270
|
+
"readOnly": true
|
|
271
|
+
},
|
|
272
|
+
"title": {
|
|
273
|
+
"type": "string",
|
|
274
|
+
"description": "Post title"
|
|
275
|
+
},
|
|
276
|
+
"content": {
|
|
277
|
+
"type": "string"
|
|
278
|
+
},
|
|
279
|
+
"author_id": {
|
|
280
|
+
"type": "integer",
|
|
281
|
+
"description": "Author reference"
|
|
282
|
+
},
|
|
283
|
+
"published_at": {
|
|
284
|
+
"type": "string",
|
|
285
|
+
"format": "date"
|
|
286
|
+
},
|
|
287
|
+
"status": {
|
|
288
|
+
"type": "string",
|
|
289
|
+
"enum": ["draft", "published", "archived"],
|
|
290
|
+
"default": "draft"
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
},
|
|
294
|
+
"Category": {
|
|
295
|
+
"type": "object",
|
|
296
|
+
"properties": {
|
|
297
|
+
"id": {
|
|
298
|
+
"type": "integer",
|
|
299
|
+
"readOnly": true
|
|
300
|
+
},
|
|
301
|
+
"name": {
|
|
302
|
+
"type": "string"
|
|
303
|
+
},
|
|
304
|
+
"slug": {
|
|
305
|
+
"type": "string"
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Schema Connectors
|
|
3
|
+
*
|
|
4
|
+
* Pluggable connectors that parse various schema sources into UnifiedEntitySchema format.
|
|
5
|
+
*
|
|
6
|
+
* @module gen/connectors
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
export {
|
|
10
|
+
BaseConnector,
|
|
11
|
+
type ConnectorOptions,
|
|
12
|
+
type ParseWarning,
|
|
13
|
+
type ParseResult,
|
|
14
|
+
} from './BaseConnector'
|
|
15
|
+
|
|
16
|
+
export {
|
|
17
|
+
ManualConnector,
|
|
18
|
+
type ManualEntityInput,
|
|
19
|
+
type ManualFieldInput,
|
|
20
|
+
type ManualSourceInput,
|
|
21
|
+
} from './ManualConnector'
|
|
22
|
+
|
|
23
|
+
export {
|
|
24
|
+
OpenAPIConnector,
|
|
25
|
+
type OpenAPIConnectorOptions,
|
|
26
|
+
type OperationFilter,
|
|
27
|
+
} from './OpenAPIConnector'
|
|
@@ -0,0 +1,245 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Runtime Factory for EntityManager Creation
|
|
3
|
+
*
|
|
4
|
+
* Creates EntityManager instances on-the-fly from configuration.
|
|
5
|
+
* This is the core factory function that wires schemas, storage profiles,
|
|
6
|
+
* and decorators together at runtime.
|
|
7
|
+
*
|
|
8
|
+
* @module gen/createManagers
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import { EntityManager } from '../entity/EntityManager'
|
|
12
|
+
import { applyDecorators, type EntityDecorator } from './decorators'
|
|
13
|
+
import type { UnifiedEntitySchema } from './schema'
|
|
14
|
+
import type { StorageProfileFactory, StorageProfileOptions } from './StorageProfileFactory'
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Entity configuration in the config.entities map
|
|
18
|
+
*/
|
|
19
|
+
export interface EntityConfig {
|
|
20
|
+
/** Schema source name (key in config.schemas) */
|
|
21
|
+
schema: string
|
|
22
|
+
/** Storage profile name (key in config.storages) */
|
|
23
|
+
storage: string
|
|
24
|
+
/** API endpoint path (e.g., '/users') */
|
|
25
|
+
endpoint: string
|
|
26
|
+
/** Per-entity storage options */
|
|
27
|
+
options?: StorageProfileOptions
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Configuration for createManagers factory
|
|
32
|
+
*/
|
|
33
|
+
export interface CreateManagersConfig {
|
|
34
|
+
/** Schema sources (connector results) keyed by name */
|
|
35
|
+
schemas: Record<string, UnifiedEntitySchema[]>
|
|
36
|
+
/** Storage profile factories keyed by name */
|
|
37
|
+
storages: Record<string, StorageProfileFactory>
|
|
38
|
+
/** Entity configurations keyed by entity name */
|
|
39
|
+
entities: Record<string, EntityConfig>
|
|
40
|
+
/** Per-entity decorators (fields, labels, permissions) */
|
|
41
|
+
decorators?: Record<string, EntityDecorator>
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Validate config structure early with clear error messages
|
|
46
|
+
*
|
|
47
|
+
* @param config - Configuration to validate
|
|
48
|
+
* @throws If config is invalid
|
|
49
|
+
*/
|
|
50
|
+
function validateConfig(config: CreateManagersConfig): void {
|
|
51
|
+
if (!config || typeof config !== 'object') {
|
|
52
|
+
throw new Error('createManagers: config is required and must be an object')
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
if (!config.schemas || typeof config.schemas !== 'object') {
|
|
56
|
+
throw new Error('createManagers: config.schemas is required and must be an object')
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
if (!config.storages || typeof config.storages !== 'object') {
|
|
60
|
+
throw new Error('createManagers: config.storages is required and must be an object')
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
if (!config.entities || typeof config.entities !== 'object') {
|
|
64
|
+
throw new Error('createManagers: config.entities is required and must be an object')
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
// Validate each entity config
|
|
68
|
+
for (const [entityName, entityConfig] of Object.entries(config.entities)) {
|
|
69
|
+
if (!entityConfig || typeof entityConfig !== 'object') {
|
|
70
|
+
throw new Error(`createManagers: entity '${entityName}' config must be an object`)
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
if (!entityConfig.schema || typeof entityConfig.schema !== 'string') {
|
|
74
|
+
throw new Error(`createManagers: entity '${entityName}' requires 'schema' property`)
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
if (!entityConfig.storage || typeof entityConfig.storage !== 'string') {
|
|
78
|
+
throw new Error(`createManagers: entity '${entityName}' requires 'storage' property`)
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
if (!entityConfig.endpoint || typeof entityConfig.endpoint !== 'string') {
|
|
82
|
+
throw new Error(`createManagers: entity '${entityName}' requires 'endpoint' property`)
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
// Validate references exist
|
|
86
|
+
if (!(entityConfig.schema in config.schemas)) {
|
|
87
|
+
throw new Error(
|
|
88
|
+
`createManagers: entity '${entityName}' references unknown schema '${entityConfig.schema}'`
|
|
89
|
+
)
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
if (!(entityConfig.storage in config.storages)) {
|
|
93
|
+
throw new Error(
|
|
94
|
+
`createManagers: entity '${entityName}' references unknown storage '${entityConfig.storage}'`
|
|
95
|
+
)
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* Find schema for entity from connector result
|
|
102
|
+
*
|
|
103
|
+
* Connector results are arrays of UnifiedEntitySchema. This finds the schema
|
|
104
|
+
* matching the entity name, or uses the first schema if none matches.
|
|
105
|
+
*
|
|
106
|
+
* @param schemas - Connector result (array of schemas)
|
|
107
|
+
* @param entityName - Entity name to find
|
|
108
|
+
* @param schemaSourceName - Schema source name for error messages
|
|
109
|
+
* @returns Found schema
|
|
110
|
+
* @throws If schema not found
|
|
111
|
+
*/
|
|
112
|
+
function findSchemaForEntity(
|
|
113
|
+
schemas: UnifiedEntitySchema[],
|
|
114
|
+
entityName: string,
|
|
115
|
+
schemaSourceName: string
|
|
116
|
+
): UnifiedEntitySchema {
|
|
117
|
+
if (!Array.isArray(schemas)) {
|
|
118
|
+
throw new Error(
|
|
119
|
+
`createManagers: schema source '${schemaSourceName}' must be an array of UnifiedEntitySchema`
|
|
120
|
+
)
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
if (schemas.length === 0) {
|
|
124
|
+
throw new Error(`createManagers: schema source '${schemaSourceName}' is empty`)
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
// Find by entity name
|
|
128
|
+
const schema = schemas.find((s) => s.name === entityName)
|
|
129
|
+
if (schema) {
|
|
130
|
+
return schema
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
// If only one schema in source, use it (common for single-entity sources)
|
|
134
|
+
if (schemas.length === 1) {
|
|
135
|
+
return schemas[0]!
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
// Multiple schemas but none match
|
|
139
|
+
const available = schemas.map((s) => s.name).join(', ')
|
|
140
|
+
throw new Error(
|
|
141
|
+
`createManagers: entity '${entityName}' not found in schema source '${schemaSourceName}'. Available: ${available}`
|
|
142
|
+
)
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
/**
|
|
146
|
+
* Create EntityManager instances from configuration
|
|
147
|
+
*
|
|
148
|
+
* This is the runtime factory that wires schemas, storage profiles, and
|
|
149
|
+
* decorators together at runtime without code generation.
|
|
150
|
+
*
|
|
151
|
+
* @param config - Configuration object
|
|
152
|
+
* @returns Map of entity name to EntityManager instance
|
|
153
|
+
* @throws If config is invalid or references missing schemas/storages
|
|
154
|
+
*
|
|
155
|
+
* @example
|
|
156
|
+
* ```ts
|
|
157
|
+
* import { createManagers } from '@quazardous/qdadm/gen'
|
|
158
|
+
* import { ManualConnector } from '@quazardous/qdadm/gen'
|
|
159
|
+
* import { ApiStorage } from '@quazardous/qdadm'
|
|
160
|
+
* import axios from 'axios'
|
|
161
|
+
*
|
|
162
|
+
* // Define schemas using connectors
|
|
163
|
+
* const connector = new ManualConnector()
|
|
164
|
+
* const schemas = connector.parse([
|
|
165
|
+
* {
|
|
166
|
+
* name: 'users',
|
|
167
|
+
* endpoint: '/users',
|
|
168
|
+
* fields: {
|
|
169
|
+
* id: { name: 'id', type: 'number', readOnly: true },
|
|
170
|
+
* email: { name: 'email', type: 'email', required: true }
|
|
171
|
+
* }
|
|
172
|
+
* }
|
|
173
|
+
* ])
|
|
174
|
+
*
|
|
175
|
+
* // Define storage profile factory
|
|
176
|
+
* const apiClient = axios.create({ baseURL: 'https://api.example.com' })
|
|
177
|
+
* const apiProfile = (endpoint, options) => new ApiStorage({
|
|
178
|
+
* endpoint,
|
|
179
|
+
* client: apiClient,
|
|
180
|
+
* ...options
|
|
181
|
+
* })
|
|
182
|
+
*
|
|
183
|
+
* // Create managers
|
|
184
|
+
* const managers = createManagers({
|
|
185
|
+
* schemas: { api: schemas },
|
|
186
|
+
* storages: { jsonplaceholder: apiProfile },
|
|
187
|
+
* entities: {
|
|
188
|
+
* users: { schema: 'api', storage: 'jsonplaceholder', endpoint: '/users' }
|
|
189
|
+
* },
|
|
190
|
+
* decorators: {
|
|
191
|
+
* users: { fields: { email: { hidden: true } } }
|
|
192
|
+
* }
|
|
193
|
+
* })
|
|
194
|
+
*
|
|
195
|
+
* const usersManager = managers.get('users')
|
|
196
|
+
* const users = await usersManager.list()
|
|
197
|
+
* ```
|
|
198
|
+
*/
|
|
199
|
+
export function createManagers(config: CreateManagersConfig): Map<string, EntityManager> {
|
|
200
|
+
// Validate config structure early
|
|
201
|
+
validateConfig(config)
|
|
202
|
+
|
|
203
|
+
const managers: Map<string, EntityManager> = new Map()
|
|
204
|
+
|
|
205
|
+
// Process each entity configuration
|
|
206
|
+
for (const [entityName, entityConfig] of Object.entries(config.entities)) {
|
|
207
|
+
// 1. Get schema from connector result (validated in validateConfig)
|
|
208
|
+
const schemaSource = config.schemas[entityConfig.schema]!
|
|
209
|
+
let schema = findSchemaForEntity(schemaSource, entityName, entityConfig.schema)
|
|
210
|
+
|
|
211
|
+
// 2. Apply decorators if defined
|
|
212
|
+
const decorator = config.decorators?.[entityName]
|
|
213
|
+
schema = applyDecorators(schema, decorator)
|
|
214
|
+
|
|
215
|
+
// 3. Get storage factory and create storage instance
|
|
216
|
+
const storageFactory = config.storages[entityConfig.storage]
|
|
217
|
+
if (typeof storageFactory !== 'function') {
|
|
218
|
+
throw new Error(`createManagers: storage '${entityConfig.storage}' must be a factory function`)
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
const storageOptions: StorageProfileOptions = {
|
|
222
|
+
entity: entityName,
|
|
223
|
+
...entityConfig.options,
|
|
224
|
+
}
|
|
225
|
+
const storage = storageFactory(entityConfig.endpoint, storageOptions)
|
|
226
|
+
|
|
227
|
+
// 4. Create EntityManager with schema + storage
|
|
228
|
+
const manager = new EntityManager({
|
|
229
|
+
name: schema.name,
|
|
230
|
+
storage,
|
|
231
|
+
idField: schema.idField || 'id',
|
|
232
|
+
label: schema.label,
|
|
233
|
+
labelPlural: schema.labelPlural,
|
|
234
|
+
labelField: schema.labelField,
|
|
235
|
+
routePrefix: schema.routePrefix,
|
|
236
|
+
readOnly: schema.readOnly,
|
|
237
|
+
fields: schema.fields,
|
|
238
|
+
})
|
|
239
|
+
|
|
240
|
+
// 5. Store in result Map
|
|
241
|
+
managers.set(entityName, manager)
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
return managers
|
|
245
|
+
}
|