@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.
Files changed (291) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +111 -0
  3. package/package.json +101 -0
  4. package/src/assets/logo.svg +6 -0
  5. package/src/auth/SessionAuthAdapter.ts +459 -0
  6. package/src/auth/index.ts +15 -0
  7. package/src/chain/ActiveStack.ts +154 -0
  8. package/src/chain/StackHydrator.ts +292 -0
  9. package/src/chain/index.ts +25 -0
  10. package/src/chain/useActiveStack.ts +120 -0
  11. package/src/chain/useStackHydrator.ts +155 -0
  12. package/src/components/BoolCell.vue +34 -0
  13. package/src/components/InfoBanner.vue +73 -0
  14. package/src/components/QdadmRoot.vue +52 -0
  15. package/src/components/SeverityTag.vue +86 -0
  16. package/src/components/dialogs/BulkStatusDialog.vue +60 -0
  17. package/src/components/dialogs/MultiStepDialog.vue +331 -0
  18. package/src/components/dialogs/SimpleDialog.vue +122 -0
  19. package/src/components/dialogs/UnsavedChangesDialog.vue +80 -0
  20. package/src/components/display/BannerZone.vue +65 -0
  21. package/src/components/display/CardsGrid.vue +72 -0
  22. package/src/components/display/CopyableId.vue +84 -0
  23. package/src/components/display/EmptyState.vue +62 -0
  24. package/src/components/display/IntensityBar.vue +190 -0
  25. package/src/components/display/RichCardsGrid.vue +101 -0
  26. package/src/components/edit/FormActions.vue +78 -0
  27. package/src/components/edit/FormField.vue +82 -0
  28. package/src/components/edit/FormInput.vue +158 -0
  29. package/src/components/edit/FormPage.vue +260 -0
  30. package/src/components/edit/FormTab.vue +217 -0
  31. package/src/components/edit/FormTabs.vue +120 -0
  32. package/src/components/edit/LookupField.vue +406 -0
  33. package/src/components/edit/LookupPickerDialog.vue +230 -0
  34. package/src/components/editors/JsonEditorFoldable.vue +470 -0
  35. package/src/components/editors/JsonStructuredField.vue +264 -0
  36. package/src/components/editors/JsonViewer.vue +51 -0
  37. package/src/components/editors/KeyValueEditor.vue +314 -0
  38. package/src/components/editors/LanguageEditor.vue +259 -0
  39. package/src/components/editors/PermissionEditor.vue +558 -0
  40. package/src/components/editors/ScopeEditor.vue +372 -0
  41. package/src/components/editors/VanillaJsonEditor.vue +183 -0
  42. package/src/components/index.ts +83 -0
  43. package/src/components/item/FieldGroups.vue +392 -0
  44. package/src/components/layout/AppLayout.vue +1032 -0
  45. package/src/components/layout/BaseLayout.vue +190 -0
  46. package/src/components/layout/Breadcrumb.vue +55 -0
  47. package/src/components/layout/DashboardLayout.vue +104 -0
  48. package/src/components/layout/FormLayout.vue +256 -0
  49. package/src/components/layout/ListLayout.vue +278 -0
  50. package/src/components/layout/PageHeader.vue +156 -0
  51. package/src/components/layout/PageLayout.vue +126 -0
  52. package/src/components/layout/PageNav.vue +192 -0
  53. package/src/components/layout/SidebarBox.vue +87 -0
  54. package/src/components/layout/Zone.vue +182 -0
  55. package/src/components/layout/defaults/DefaultBreadcrumb.vue +149 -0
  56. package/src/components/layout/defaults/DefaultFooter.vue +89 -0
  57. package/src/components/layout/defaults/DefaultFormActions.vue +67 -0
  58. package/src/components/layout/defaults/DefaultHeader.vue +78 -0
  59. package/src/components/layout/defaults/DefaultMenu.vue +188 -0
  60. package/src/components/layout/defaults/DefaultPagination.vue +75 -0
  61. package/src/components/layout/defaults/DefaultTable.vue +137 -0
  62. package/src/components/layout/defaults/DefaultUserInfo.vue +111 -0
  63. package/src/components/layout/defaults/index.ts +16 -0
  64. package/src/components/lists/ActionButtons.vue +49 -0
  65. package/src/components/lists/ActionColumn.vue +40 -0
  66. package/src/components/lists/FilterBar.vue +54 -0
  67. package/src/components/lists/ListPage.vue +467 -0
  68. package/src/components/pages/LoginPage.vue +334 -0
  69. package/src/components/pages/NotFoundPage.vue +98 -0
  70. package/src/components/show/ShowDisplay.vue +343 -0
  71. package/src/components/show/ShowField.vue +67 -0
  72. package/src/components/show/ShowPage.vue +431 -0
  73. package/src/composables/index.ts +155 -0
  74. package/src/composables/useApp.ts +67 -0
  75. package/src/composables/useAuth.ts +98 -0
  76. package/src/composables/useBareForm.ts +319 -0
  77. package/src/composables/useBreadcrumb.ts +252 -0
  78. package/src/composables/useChildPage.ts +113 -0
  79. package/src/composables/useCurrentEntity.ts +60 -0
  80. package/src/composables/useDeferred.ts +94 -0
  81. package/src/composables/useDirtyState.ts +138 -0
  82. package/src/composables/useEntityItemFormPage.ts +942 -0
  83. package/src/composables/useEntityItemFormPage.types.ts +451 -0
  84. package/src/composables/useEntityItemPage.ts +438 -0
  85. package/src/composables/useEntityItemShowPage.ts +722 -0
  86. package/src/composables/useFieldManager.ts +692 -0
  87. package/src/composables/useForm.ts +544 -0
  88. package/src/composables/useGuardStore.ts +53 -0
  89. package/src/composables/useHooks.ts +56 -0
  90. package/src/composables/useInfoBanner.ts +217 -0
  91. package/src/composables/useJsonSyntax.ts +122 -0
  92. package/src/composables/useLayoutResolver.ts +329 -0
  93. package/src/composables/useListPage.ts +1535 -0
  94. package/src/composables/useListPage.types.ts +437 -0
  95. package/src/composables/useListPage.utils.ts +101 -0
  96. package/src/composables/useNavContext.ts +439 -0
  97. package/src/composables/useNavigation.ts +216 -0
  98. package/src/composables/useOptionsLookup.ts +323 -0
  99. package/src/composables/usePageTitle.ts +84 -0
  100. package/src/composables/useSSEBridge.ts +142 -0
  101. package/src/composables/useSemanticBreadcrumb.ts +222 -0
  102. package/src/composables/useSidebarState.ts +24 -0
  103. package/src/composables/useSignals.ts +52 -0
  104. package/src/composables/useUnsavedChangesGuard.ts +155 -0
  105. package/src/composables/useUserImpersonator.ts +317 -0
  106. package/src/composables/useZoneRegistry.ts +252 -0
  107. package/src/core/bundles.ts +558 -0
  108. package/src/core/decorator.ts +420 -0
  109. package/src/core/extension.ts +470 -0
  110. package/src/core/index.ts +59 -0
  111. package/src/deferred/DeferredRegistry.ts +353 -0
  112. package/src/deferred/index.ts +15 -0
  113. package/src/editors/index.ts +12 -0
  114. package/src/entity/EntityManager.cache.ts +530 -0
  115. package/src/entity/EntityManager.crud.ts +615 -0
  116. package/src/entity/EntityManager.interface.ts +78 -0
  117. package/src/entity/EntityManager.query.ts +221 -0
  118. package/src/entity/EntityManager.relations.ts +151 -0
  119. package/src/entity/EntityManager.ts +944 -0
  120. package/src/entity/EntityManager.types.ts +288 -0
  121. package/src/entity/auth/CompositeAuthAdapter.ts +194 -0
  122. package/src/entity/auth/EntityAuthAdapter.ts +119 -0
  123. package/src/entity/auth/PermissiveAdapter.ts +43 -0
  124. package/src/entity/auth/RoleHierarchy.ts +128 -0
  125. package/src/entity/auth/SecurityChecker.ts +202 -0
  126. package/src/entity/auth/factory.ts +203 -0
  127. package/src/entity/auth/index.ts +47 -0
  128. package/src/entity/factory.test.js +189 -0
  129. package/src/entity/factory.ts +146 -0
  130. package/src/entity/index.ts +49 -0
  131. package/src/entity/storage/ApiStorage.ts +228 -0
  132. package/src/entity/storage/IStorage.ts +100 -0
  133. package/src/entity/storage/LocalStorage.ts +200 -0
  134. package/src/entity/storage/MemoryStorage.ts +184 -0
  135. package/src/entity/storage/MockApiStorage.ts +318 -0
  136. package/src/entity/storage/SdkStorage.ts +377 -0
  137. package/src/entity/storage/factory.test.js +159 -0
  138. package/src/entity/storage/factory.ts +209 -0
  139. package/src/entity/storage/index.ts +75 -0
  140. package/src/gen/FieldMapper.ts +122 -0
  141. package/src/gen/StorageProfileFactory.ts +93 -0
  142. package/src/gen/connectors/BaseConnector.ts +150 -0
  143. package/src/gen/connectors/ManualConnector.test.js +499 -0
  144. package/src/gen/connectors/ManualConnector.ts +414 -0
  145. package/src/gen/connectors/OpenAPIConnector.test.js +836 -0
  146. package/src/gen/connectors/OpenAPIConnector.ts +693 -0
  147. package/src/gen/connectors/__fixtures__/sample-openapi.json +311 -0
  148. package/src/gen/connectors/index.ts +27 -0
  149. package/src/gen/createManagers.ts +245 -0
  150. package/src/gen/decorators.ts +134 -0
  151. package/src/gen/generateManagers.test.js +540 -0
  152. package/src/gen/generateManagers.ts +398 -0
  153. package/src/gen/index.ts +66 -0
  154. package/src/gen/schema.ts +248 -0
  155. package/src/gen/vite-plugin.ts +114 -0
  156. package/src/generated/managers/testManager.js +45 -0
  157. package/src/generated/managers/testManager.ts +46 -0
  158. package/src/hooks/HookRegistry.ts +16 -0
  159. package/src/hooks/index.ts +15 -0
  160. package/src/i18n/I18n.ts +344 -0
  161. package/src/i18n/IncrementalDomainProvider.ts +153 -0
  162. package/src/i18n/InlineTranslationProvider.ts +4 -0
  163. package/src/i18n/LazyTranslationProvider.ts +102 -0
  164. package/src/i18n/MessagesRegistry.ts +4 -0
  165. package/src/i18n/Resolver.ts +4 -0
  166. package/src/i18n/__tests__/I18n.test.ts +169 -0
  167. package/src/i18n/__tests__/IncrementalDomainProvider.test.ts +146 -0
  168. package/src/i18n/__tests__/LazyTranslationProvider.test.ts +100 -0
  169. package/src/i18n/__tests__/Resolver.test.ts +271 -0
  170. package/src/i18n/defaults/DefaultCoreProvider.ts +28 -0
  171. package/src/i18n/defaults/core.en.yml +55 -0
  172. package/src/i18n/defaults/core.fr.yml +55 -0
  173. package/src/i18n/index.ts +55 -0
  174. package/src/i18n/loaders/raw-modules.d.ts +15 -0
  175. package/src/i18n/loaders/yaml.ts +35 -0
  176. package/src/i18n/strategies.ts +4 -0
  177. package/src/i18n/types.ts +34 -0
  178. package/src/i18n/useI18n.ts +34 -0
  179. package/src/index.ts +453 -0
  180. package/src/kernel/EventRouter.ts +23 -0
  181. package/src/kernel/Kernel.api.ts +79 -0
  182. package/src/kernel/Kernel.auth.ts +120 -0
  183. package/src/kernel/Kernel.i18n.ts +29 -0
  184. package/src/kernel/Kernel.modules.ts +170 -0
  185. package/src/kernel/Kernel.registries.ts +237 -0
  186. package/src/kernel/Kernel.routing.ts +334 -0
  187. package/src/kernel/Kernel.ts +460 -0
  188. package/src/kernel/Kernel.types.ts +263 -0
  189. package/src/kernel/Kernel.vue.ts +304 -0
  190. package/src/kernel/KernelContext.entities.ts +80 -0
  191. package/src/kernel/KernelContext.events.ts +57 -0
  192. package/src/kernel/KernelContext.i18n.ts +37 -0
  193. package/src/kernel/KernelContext.permissions.ts +38 -0
  194. package/src/kernel/KernelContext.routing.ts +280 -0
  195. package/src/kernel/KernelContext.ts +252 -0
  196. package/src/kernel/KernelContext.types.ts +173 -0
  197. package/src/kernel/KernelContext.zones.ts +54 -0
  198. package/src/kernel/Module.ts +169 -0
  199. package/src/kernel/ModuleLoader.ts +645 -0
  200. package/src/kernel/SSEBridge.ts +11 -0
  201. package/src/kernel/SignalBus.ts +48 -0
  202. package/src/kernel/index.ts +56 -0
  203. package/src/module/index.ts +33 -0
  204. package/src/module/moduleRegistry.ts +492 -0
  205. package/src/modules/debug/AuthCollector.ts +501 -0
  206. package/src/modules/debug/Collector.ts +20 -0
  207. package/src/modules/debug/DebugBridge.ts +14 -0
  208. package/src/modules/debug/DebugModule.ts +220 -0
  209. package/src/modules/debug/EntitiesCollector.ts +839 -0
  210. package/src/modules/debug/ErrorCollector.ts +4 -0
  211. package/src/modules/debug/I18nCollector.ts +9 -0
  212. package/src/modules/debug/LocalStorageAdapter.ts +7 -0
  213. package/src/modules/debug/RouterCollector.ts +449 -0
  214. package/src/modules/debug/SignalCollector.ts +4 -0
  215. package/src/modules/debug/ToastCollector.ts +4 -0
  216. package/src/modules/debug/ZonesCollector.ts +447 -0
  217. package/src/modules/debug/components/DebugBar.vue +31 -0
  218. package/src/modules/debug/components/adminPanelsConfig.ts +42 -0
  219. package/src/modules/debug/components/index.ts +9 -0
  220. package/src/modules/debug/components/panels/AuthPanel.vue +267 -0
  221. package/src/modules/debug/components/panels/EntitiesPanel.vue +572 -0
  222. package/src/modules/debug/components/panels/I18nPanel.vue +738 -0
  223. package/src/modules/debug/components/panels/RouterPanel.vue +440 -0
  224. package/src/modules/debug/components/panels/ZonesPanel.vue +133 -0
  225. package/src/modules/debug/components/panels/index.ts +16 -0
  226. package/src/modules/debug/index.ts +58 -0
  227. package/src/modules/debug/styles.scss +2671 -0
  228. package/src/notifications/NotificationBadge.vue +35 -0
  229. package/src/notifications/NotificationListener.vue +71 -0
  230. package/src/notifications/NotificationModule.ts +76 -0
  231. package/src/notifications/NotificationPanel.vue +478 -0
  232. package/src/notifications/NotificationStore.ts +288 -0
  233. package/src/notifications/index.ts +42 -0
  234. package/src/notifications/styles.scss +32 -0
  235. package/src/orchestrator/Orchestrator.ts +427 -0
  236. package/src/orchestrator/index.ts +8 -0
  237. package/src/orchestrator/useOrchestrator.ts +80 -0
  238. package/src/plugin.ts +251 -0
  239. package/src/query/FilterQuery.ts +306 -0
  240. package/src/query/QueryExecutor.ts +341 -0
  241. package/src/query/index.ts +16 -0
  242. package/src/security/EntityRolesProvider.ts +385 -0
  243. package/src/security/PermissionMatcher.ts +152 -0
  244. package/src/security/PermissionRegistry.ts +273 -0
  245. package/src/security/PersistableRolesProvider.ts +584 -0
  246. package/src/security/RolesManager.ts +136 -0
  247. package/src/security/RolesProvider.ts +167 -0
  248. package/src/security/RolesProviderStorage.ts +211 -0
  249. package/src/security/SecurityModule.ts +94 -0
  250. package/src/security/StaticRolesProvider.ts +117 -0
  251. package/src/security/UsersManager.ts +163 -0
  252. package/src/security/index.ts +77 -0
  253. package/src/security/pages/RoleForm.vue +276 -0
  254. package/src/security/pages/RoleList.vue +123 -0
  255. package/src/styles/_alerts.scss +95 -0
  256. package/src/styles/_buttons.scss +391 -0
  257. package/src/styles/_cards.scss +241 -0
  258. package/src/styles/_code.scss +78 -0
  259. package/src/styles/_dialogs.scss +55 -0
  260. package/src/styles/_filter-bar.scss +70 -0
  261. package/src/styles/_forms.scss +434 -0
  262. package/src/styles/_helpers.scss +153 -0
  263. package/src/styles/_lists.scss +225 -0
  264. package/src/styles/_main.scss +356 -0
  265. package/src/styles/_markdown.scss +88 -0
  266. package/src/styles/_responsive.scss +255 -0
  267. package/src/styles/_show-pages.scss +186 -0
  268. package/src/styles/_sidebar.scss +380 -0
  269. package/src/styles/_states.scss +115 -0
  270. package/src/styles/_stats.scss +47 -0
  271. package/src/styles/_variables.scss +224 -0
  272. package/src/styles/index.scss +38 -0
  273. package/src/styles/theme/_components.scss +331 -0
  274. package/src/styles/theme/_index.scss +10 -0
  275. package/src/styles/theme/_tokens.scss +147 -0
  276. package/src/styles/theme/_utilities.scss +175 -0
  277. package/src/toast/ToastBridgeModule.ts +68 -0
  278. package/src/toast/ToastListener.vue +55 -0
  279. package/src/toast/index.ts +26 -0
  280. package/src/toast/useSignalToast.ts +154 -0
  281. package/src/types/index.ts +285 -0
  282. package/src/types/pluralize.d.ts +19 -0
  283. package/src/types/quarkernel.d.ts +50 -0
  284. package/src/utils/formatters.ts +174 -0
  285. package/src/utils/index.ts +35 -0
  286. package/src/utils/transformers.ts +131 -0
  287. package/src/vite/qdadmDebugPlugin.ts +401 -0
  288. package/src/vite-env.d.ts +50 -0
  289. package/src/zones/ZoneRegistry.ts +934 -0
  290. package/src/zones/index.ts +29 -0
  291. 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
+ }