@acorex/platform 20.0.6 → 20.0.8

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 (83) hide show
  1. package/auth/index.d.ts +37 -32
  2. package/common/index.d.ts +2 -2
  3. package/core/index.d.ts +4 -0
  4. package/domain/index.d.ts +2034 -2
  5. package/fesm2022/acorex-platform-auth.mjs +57 -21
  6. package/fesm2022/acorex-platform-auth.mjs.map +1 -1
  7. package/fesm2022/acorex-platform-common.mjs +92 -92
  8. package/fesm2022/acorex-platform-common.mjs.map +1 -1
  9. package/fesm2022/acorex-platform-core.mjs +54 -42
  10. package/fesm2022/acorex-platform-core.mjs.map +1 -1
  11. package/fesm2022/acorex-platform-domain.mjs +3320 -7
  12. package/fesm2022/acorex-platform-domain.mjs.map +1 -1
  13. package/fesm2022/acorex-platform-layout-builder.mjs +172 -168
  14. package/fesm2022/acorex-platform-layout-builder.mjs.map +1 -1
  15. package/fesm2022/acorex-platform-layout-components.mjs +103 -83
  16. package/fesm2022/acorex-platform-layout-components.mjs.map +1 -1
  17. package/fesm2022/acorex-platform-layout-designer.mjs +72 -72
  18. package/fesm2022/acorex-platform-layout-designer.mjs.map +1 -1
  19. package/fesm2022/acorex-platform-layout-entity.mjs +94 -96
  20. package/fesm2022/acorex-platform-layout-entity.mjs.map +1 -1
  21. package/fesm2022/acorex-platform-layout-views.mjs +340 -104
  22. package/fesm2022/acorex-platform-layout-views.mjs.map +1 -1
  23. package/fesm2022/acorex-platform-native.mjs +7 -7
  24. package/fesm2022/acorex-platform-native.mjs.map +1 -1
  25. package/fesm2022/acorex-platform-runtime.mjs +45 -43
  26. package/fesm2022/acorex-platform-runtime.mjs.map +1 -1
  27. package/fesm2022/{acorex-platform-themes-default-create-entity-view.component-BxYe1IlE.mjs → acorex-platform-themes-default-create-entity-view.component-DyVB3PZT.mjs} +4 -4
  28. package/fesm2022/{acorex-platform-themes-default-create-entity-view.component-BxYe1IlE.mjs.map → acorex-platform-themes-default-create-entity-view.component-DyVB3PZT.mjs.map} +1 -1
  29. package/fesm2022/{acorex-platform-themes-default-entity-master-create-view.component-CzSqhYfE.mjs → acorex-platform-themes-default-entity-master-create-view.component-CsWVOu-r.mjs} +4 -4
  30. package/fesm2022/{acorex-platform-themes-default-entity-master-create-view.component-CzSqhYfE.mjs.map → acorex-platform-themes-default-entity-master-create-view.component-CsWVOu-r.mjs.map} +1 -1
  31. package/fesm2022/{acorex-platform-themes-default-entity-master-list-view.component-BxdQ5JWS.mjs → acorex-platform-themes-default-entity-master-list-view.component-DgyzWR29.mjs} +20 -20
  32. package/fesm2022/acorex-platform-themes-default-entity-master-list-view.component-DgyzWR29.mjs.map +1 -0
  33. package/fesm2022/{acorex-platform-themes-default-entity-master-modify-view.component-12xcM8FJ.mjs → acorex-platform-themes-default-entity-master-modify-view.component-gJap_TBH.mjs} +4 -4
  34. package/fesm2022/{acorex-platform-themes-default-entity-master-modify-view.component-12xcM8FJ.mjs.map → acorex-platform-themes-default-entity-master-modify-view.component-gJap_TBH.mjs.map} +1 -1
  35. package/fesm2022/{acorex-platform-themes-default-entity-master-single-view.component--tn_1mKA.mjs → acorex-platform-themes-default-entity-master-single-view.component-BUNm9JV5.mjs} +7 -7
  36. package/fesm2022/{acorex-platform-themes-default-entity-master-single-view.component--tn_1mKA.mjs.map → acorex-platform-themes-default-entity-master-single-view.component-BUNm9JV5.mjs.map} +1 -1
  37. package/fesm2022/{acorex-platform-themes-default-error-401.component-8QfQ3hNo.mjs → acorex-platform-themes-default-error-401.component-DP3msj3d.mjs} +4 -4
  38. package/fesm2022/{acorex-platform-themes-default-error-401.component-8QfQ3hNo.mjs.map → acorex-platform-themes-default-error-401.component-DP3msj3d.mjs.map} +1 -1
  39. package/fesm2022/{acorex-platform-themes-default-error-404.component-D9npA9_W.mjs → acorex-platform-themes-default-error-404.component-uvBHGbHY.mjs} +4 -4
  40. package/fesm2022/{acorex-platform-themes-default-error-404.component-D9npA9_W.mjs.map → acorex-platform-themes-default-error-404.component-uvBHGbHY.mjs.map} +1 -1
  41. package/fesm2022/{acorex-platform-themes-default-error-offline.component-BQpVnLzt.mjs → acorex-platform-themes-default-error-offline.component-CdXIik4U.mjs} +4 -4
  42. package/fesm2022/{acorex-platform-themes-default-error-offline.component-BQpVnLzt.mjs.map → acorex-platform-themes-default-error-offline.component-CdXIik4U.mjs.map} +1 -1
  43. package/fesm2022/acorex-platform-themes-default.mjs +469 -51
  44. package/fesm2022/acorex-platform-themes-default.mjs.map +1 -1
  45. package/fesm2022/acorex-platform-themes-shared.mjs +22 -23
  46. package/fesm2022/acorex-platform-themes-shared.mjs.map +1 -1
  47. package/fesm2022/{acorex-platform-widgets-button-widget-designer.component-BIZkWv8q.mjs → acorex-platform-widgets-button-widget-designer.component-CgUkYMwV.mjs} +4 -4
  48. package/fesm2022/{acorex-platform-widgets-button-widget-designer.component-BIZkWv8q.mjs.map → acorex-platform-widgets-button-widget-designer.component-CgUkYMwV.mjs.map} +1 -1
  49. package/fesm2022/{acorex-platform-widgets-checkbox-widget-column.component-MjSzOXIJ.mjs → acorex-platform-widgets-checkbox-widget-column.component-Dn0U56O7.mjs} +4 -4
  50. package/fesm2022/{acorex-platform-widgets-checkbox-widget-column.component-MjSzOXIJ.mjs.map → acorex-platform-widgets-checkbox-widget-column.component-Dn0U56O7.mjs.map} +1 -1
  51. package/fesm2022/{acorex-platform-widgets-checkbox-widget-designer.component-BuU7nJ6u.mjs → acorex-platform-widgets-checkbox-widget-designer.component-BD0-kCi0.mjs} +4 -4
  52. package/fesm2022/{acorex-platform-widgets-checkbox-widget-designer.component-BuU7nJ6u.mjs.map → acorex-platform-widgets-checkbox-widget-designer.component-BD0-kCi0.mjs.map} +1 -1
  53. package/fesm2022/{acorex-platform-widgets-checkbox-widget-view.component-BgrIeNW0.mjs → acorex-platform-widgets-checkbox-widget-view.component-CzCWGDil.mjs} +4 -4
  54. package/fesm2022/{acorex-platform-widgets-checkbox-widget-view.component-BgrIeNW0.mjs.map → acorex-platform-widgets-checkbox-widget-view.component-CzCWGDil.mjs.map} +1 -1
  55. package/fesm2022/{acorex-platform-widgets-color-box-widget-designer.component-BTxAgvMQ.mjs → acorex-platform-widgets-color-box-widget-designer.component-BSRAHIPQ.mjs} +4 -4
  56. package/fesm2022/{acorex-platform-widgets-color-box-widget-designer.component-BTxAgvMQ.mjs.map → acorex-platform-widgets-color-box-widget-designer.component-BSRAHIPQ.mjs.map} +1 -1
  57. package/fesm2022/{acorex-platform-widgets-contact-widget-filter.component-DCUfKMJ6.mjs → acorex-platform-widgets-contact-widget-filter.component-CtCAgeH9.mjs} +4 -4
  58. package/fesm2022/{acorex-platform-widgets-contact-widget-filter.component-DCUfKMJ6.mjs.map → acorex-platform-widgets-contact-widget-filter.component-CtCAgeH9.mjs.map} +1 -1
  59. package/fesm2022/{acorex-platform-widgets-file-list-popup.component-yqqPJMg2.mjs → acorex-platform-widgets-file-list-popup.component-hyJf0xT2.mjs} +4 -4
  60. package/fesm2022/{acorex-platform-widgets-file-list-popup.component-yqqPJMg2.mjs.map → acorex-platform-widgets-file-list-popup.component-hyJf0xT2.mjs.map} +1 -1
  61. package/fesm2022/acorex-platform-widgets-file-rename-popup.component-BSm6Qew2.mjs +211 -0
  62. package/fesm2022/acorex-platform-widgets-file-rename-popup.component-BSm6Qew2.mjs.map +1 -0
  63. package/fesm2022/{acorex-platform-widgets-page-widget-designer.component-Dwts3at7.mjs → acorex-platform-widgets-page-widget-designer.component-Dlu4Tkou.mjs} +4 -4
  64. package/fesm2022/{acorex-platform-widgets-page-widget-designer.component-Dwts3at7.mjs.map → acorex-platform-widgets-page-widget-designer.component-Dlu4Tkou.mjs.map} +1 -1
  65. package/fesm2022/{acorex-platform-widgets-rich-text-popup.component-Bk20MsqK.mjs → acorex-platform-widgets-rich-text-popup.component-DB2IMaLw.mjs} +4 -4
  66. package/fesm2022/{acorex-platform-widgets-rich-text-popup.component-Bk20MsqK.mjs.map → acorex-platform-widgets-rich-text-popup.component-DB2IMaLw.mjs.map} +1 -1
  67. package/fesm2022/{acorex-platform-widgets-tabular-data-edit-popup.component-2srL34Aq.mjs → acorex-platform-widgets-tabular-data-edit-popup.component-CBOUSkL4.mjs} +4 -4
  68. package/fesm2022/{acorex-platform-widgets-tabular-data-edit-popup.component-2srL34Aq.mjs.map → acorex-platform-widgets-tabular-data-edit-popup.component-CBOUSkL4.mjs.map} +1 -1
  69. package/fesm2022/{acorex-platform-widgets-tabular-data-view-popup.component-D9654sA3.mjs → acorex-platform-widgets-tabular-data-view-popup.component-Dl5U2HFR.mjs} +4 -4
  70. package/fesm2022/{acorex-platform-widgets-tabular-data-view-popup.component-D9654sA3.mjs.map → acorex-platform-widgets-tabular-data-view-popup.component-Dl5U2HFR.mjs.map} +1 -1
  71. package/fesm2022/{acorex-platform-widgets-text-block-widget-designer.component-C1VgsL1j.mjs → acorex-platform-widgets-text-block-widget-designer.component-CG_2APU3.mjs} +4 -4
  72. package/fesm2022/{acorex-platform-widgets-text-block-widget-designer.component-C1VgsL1j.mjs.map → acorex-platform-widgets-text-block-widget-designer.component-CG_2APU3.mjs.map} +1 -1
  73. package/fesm2022/acorex-platform-widgets.mjs +884 -677
  74. package/fesm2022/acorex-platform-widgets.mjs.map +1 -1
  75. package/fesm2022/acorex-platform-workflow.mjs +25 -25
  76. package/fesm2022/acorex-platform-workflow.mjs.map +1 -1
  77. package/layout/builder/index.d.ts +17 -10
  78. package/layout/components/index.d.ts +3 -0
  79. package/layout/views/index.d.ts +83 -24
  80. package/package.json +1 -1
  81. package/widgets/index.d.ts +15 -7
  82. package/domain/README.md +0 -3
  83. package/fesm2022/acorex-platform-themes-default-entity-master-list-view.component-BxdQ5JWS.mjs.map +0 -1
@@ -1,5 +1,5 @@
1
1
  import * as i0 from '@angular/core';
2
- import { InjectionToken, makeEnvironmentProviders, inject, NgModule } from '@angular/core';
2
+ import { InjectionToken, makeEnvironmentProviders, inject, NgModule, Injectable } from '@angular/core';
3
3
  import { AXMEntityCrudServiceImpl } from '@acorex/platform/layout/entity';
4
4
  import { AXPCommandRegistry, AXPQueryRegistry, AXPRuntimeModule } from '@acorex/platform/runtime';
5
5
  import { AXP_PERMISSION_DEFINITION_PROVIDER } from '@acorex/platform/auth';
@@ -79,15 +79,105 @@ function provideEntity(entityKeys) {
79
79
  ]);
80
80
  }
81
81
 
82
+ //#region ---- Dependency Injection Tokens ----
83
+ /**
84
+ * Injection token for schema-specific middleware extensions.
85
+ *
86
+ * Used for targeted middleware that applies only to schemas matching
87
+ * specific patterns (name or regex). This enables fine-grained control
88
+ * over which schemas receive which middleware.
89
+ */
90
+ const AXP_SCHEMA_EXTENSION = new InjectionToken('AXP_SCHEMA_EXTENSION');
91
+ /**
92
+ * Injection token for schema setup initialization.
93
+ *
94
+ * Used during application bootstrap to register schemas that are
95
+ * known at build time. Multiple providers can use this token to
96
+ * contribute schemas to the registry.
97
+ */
98
+ const AXP_SCHEMA_SETUP = new InjectionToken('AXP_SCHEMA_SETUP');
99
+ /**
100
+ * Injection token for schema middleware setup initialization.
101
+ *
102
+ * Used during application bootstrap to register global middleware
103
+ * that applies to all schema resolutions. This enables centralized
104
+ * schema processing logic.
105
+ */
106
+ const AXP_SCHEMA_MIDDLEWARE_SETUP = new InjectionToken('AXP_SCHEMA_MIDDLEWARE_SETUP');
107
+ /**
108
+ * Injection token for schema loader setup initialization.
109
+ *
110
+ * Used during application bootstrap to register schema loaders
111
+ * that can provide schemas on-demand when they're not found in
112
+ * the registry.
113
+ */
114
+ const AXP_SCHEMA_LOADER_SETUP = new InjectionToken('AXP_SCHEMA_LOADER_SETUP');
115
+ //#endregion
116
+
117
+ //#region ---- Dependency Injection Tokens ----
118
+ /**
119
+ * Injection token for schema-specific middleware extensions.
120
+ *
121
+ * Used for targeted middleware that applies only to schemas matching
122
+ * specific patterns (name or regex). This enables fine-grained control
123
+ * over which schemas receive which middleware.
124
+ */
125
+ const AXP_DOMAIN_EXTENSION = new InjectionToken('AXP_DOMAIN_EXTENSION');
126
+ /**
127
+ * Injection token for schema setup initialization.
128
+ *
129
+ * Used during application bootstrap to register schemas that are
130
+ * known at build time. Multiple providers can use this token to
131
+ * contribute schemas to the registry.
132
+ */
133
+ const AXP_DOMAIN_SETUP = new InjectionToken('AXP_DOMAIN_SETUP');
134
+ /**
135
+ * Injection token for schema middleware setup initialization.
136
+ *
137
+ * Used during application bootstrap to register global middleware
138
+ * that applies to all schema resolutions. This enables centralized
139
+ * schema processing logic.
140
+ */
141
+ const AXP_DOMAIN_MIDDLEWARE_SETUP = new InjectionToken('AXP_DOMAIN_MIDDLEWARE_SETUP');
142
+ /**
143
+ * Injection token for schema loader setup initialization.
144
+ *
145
+ * Used during application bootstrap to register schema loaders
146
+ * that can provide schemas on-demand when they're not found in
147
+ * the registry.
148
+ */
149
+ const AXP_DOMAIN_LOADER_SETUP = new InjectionToken('AXP_DOMAIN_LOADER_SETUP');
150
+ //#endregion
151
+
82
152
  class AXPDomainModule {
83
153
  constructor() {
84
154
  this._commandSetup = inject(AXP_ENTITY_CRUD_SETUP, { optional: true });
155
+ /**
156
+ * Injection token for schema setup initialization.
157
+ *
158
+ * Used during application bootstrap to register global middleware
159
+ * that applies to all schema resolutions. This enables centralized
160
+ * schema processing logic.
161
+ */
162
+ this._schemaSetup = inject(AXP_SCHEMA_SETUP, { optional: true });
163
+ this._schemaMiddlewareSetup = inject(AXP_SCHEMA_MIDDLEWARE_SETUP, { optional: true });
164
+ this._schemaLoaderSetup = inject(AXP_SCHEMA_LOADER_SETUP, { optional: true });
165
+ /**
166
+ * Injection token for domain loader setup initialization.
167
+ *
168
+ * Used during application bootstrap to register domain loaders
169
+ * that can provide domain definitions on-demand when they're not found in
170
+ * the registry.
171
+ */
172
+ this._domainLoaderSetup = inject(AXP_DOMAIN_LOADER_SETUP, { optional: true });
173
+ this._domainMiddlewareSetup = inject(AXP_DOMAIN_MIDDLEWARE_SETUP, { optional: true });
174
+ this._domainSetup = inject(AXP_DOMAIN_SETUP, { optional: true });
85
175
  }
86
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.0.4", ngImport: i0, type: AXPDomainModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
87
- static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "20.0.4", ngImport: i0, type: AXPDomainModule, imports: [AXPRuntimeModule] }); }
88
- static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "20.0.4", ngImport: i0, type: AXPDomainModule, imports: [AXPRuntimeModule] }); }
176
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.0.6", ngImport: i0, type: AXPDomainModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
177
+ static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "20.0.6", ngImport: i0, type: AXPDomainModule, imports: [AXPRuntimeModule] }); }
178
+ static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "20.0.6", ngImport: i0, type: AXPDomainModule, imports: [AXPRuntimeModule] }); }
89
179
  }
90
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.4", ngImport: i0, type: AXPDomainModule, decorators: [{
180
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.6", ngImport: i0, type: AXPDomainModule, decorators: [{
91
181
  type: NgModule,
92
182
  args: [{
93
183
  imports: [
@@ -96,11 +186,3234 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.4", ngImpor
96
186
  }]
97
187
  }] });
98
188
 
99
- //export * from './lib/definitions.types';
189
+ var AXPEntityCommandScope;
190
+ (function (AXPEntityCommandScope) {
191
+ AXPEntityCommandScope["TypeLevel"] = "typeLevel";
192
+ AXPEntityCommandScope["Selected"] = "selected";
193
+ AXPEntityCommandScope["Individual"] = "individual";
194
+ AXPEntityCommandScope["Section"] = "section";
195
+ })(AXPEntityCommandScope || (AXPEntityCommandScope = {}));
196
+
197
+ //#endregion
198
+
199
+ var AXPEntityType;
200
+ (function (AXPEntityType) {
201
+ AXPEntityType[AXPEntityType["Entity"] = 0] = "Entity";
202
+ AXPEntityType[AXPEntityType["AggregateRoot"] = 1] = "AggregateRoot";
203
+ AXPEntityType[AXPEntityType["ValueObject"] = 2] = "ValueObject";
204
+ })(AXPEntityType || (AXPEntityType = {}));
205
+
206
+ var AXPRelationshipKind;
207
+ (function (AXPRelationshipKind) {
208
+ AXPRelationshipKind[AXPRelationshipKind["Association"] = 0] = "Association";
209
+ AXPRelationshipKind[AXPRelationshipKind["Composition"] = 1] = "Composition";
210
+ AXPRelationshipKind[AXPRelationshipKind["Aggregation"] = 2] = "Aggregation";
211
+ })(AXPRelationshipKind || (AXPRelationshipKind = {}));
212
+ var AXPRelationshipCardinality;
213
+ (function (AXPRelationshipCardinality) {
214
+ AXPRelationshipCardinality[AXPRelationshipCardinality["OneToOne"] = 0] = "OneToOne";
215
+ AXPRelationshipCardinality[AXPRelationshipCardinality["OneToMany"] = 1] = "OneToMany";
216
+ AXPRelationshipCardinality[AXPRelationshipCardinality["ManyToMany"] = 2] = "ManyToMany";
217
+ })(AXPRelationshipCardinality || (AXPRelationshipCardinality = {}));
218
+
219
+ //#region ---- AXPRelationModel ----
220
+ /**
221
+ * Runtime model for relation definitions with parent references and helper methods
222
+ */
223
+ class AXPRelationModel {
224
+ constructor(definition, parent) {
225
+ console.log('Relation Model Constructor', definition, parent);
226
+ this.type = definition.type;
227
+ this.kind = definition.kind;
228
+ this.target = { ...definition.target };
229
+ this.source = { ...definition.source };
230
+ this.isRequired = definition.isRequired;
231
+ this.parent = parent;
232
+ }
233
+ //#endregion
234
+ //#region ---- Cardinality Methods ----
235
+ /**
236
+ * Check if relation is one-to-one
237
+ */
238
+ isOneToOne() {
239
+ return this.type === AXPRelationshipCardinality.OneToOne;
240
+ }
241
+ /**
242
+ * Check if relation is one-to-many
243
+ */
244
+ isOneToMany() {
245
+ return this.type === AXPRelationshipCardinality.OneToMany;
246
+ }
247
+ /**
248
+ * Check if relation is many-to-many
249
+ */
250
+ isManyToMany() {
251
+ return this.type === AXPRelationshipCardinality.ManyToMany;
252
+ }
253
+ //#endregion
254
+ //#region ---- Kind Methods ----
255
+ /**
256
+ * Check if relation is association
257
+ */
258
+ isAssociation() {
259
+ return this.kind === AXPRelationshipKind.Association;
260
+ }
261
+ /**
262
+ * Check if relation is composition
263
+ */
264
+ isComposition() {
265
+ return this.kind === AXPRelationshipKind.Composition;
266
+ }
267
+ /**
268
+ * Check if relation is aggregation
269
+ */
270
+ isAggregation() {
271
+ return this.kind === AXPRelationshipKind.Aggregation;
272
+ }
273
+ //#endregion
274
+ //#region ---- Navigation Methods ----
275
+ /**
276
+ * Get parent aggregate
277
+ */
278
+ getAggregate() {
279
+ return this.parent;
280
+ }
281
+ /**
282
+ * Get parent module
283
+ */
284
+ getModule() {
285
+ return this.parent?.parent;
286
+ }
287
+ /**
288
+ * Get full path (module.aggregate.relation)
289
+ */
290
+ getPath() {
291
+ return `${this.parent.parent.name}.${this.parent.name}.${this.source.entity}->${this.target.entity}`;
292
+ }
293
+ //#endregion
294
+ //#region ---- Query Methods ----
295
+ /**
296
+ * Get relation description
297
+ */
298
+ getDescription() {
299
+ const cardinalityDesc = this.getCardinalityDescription();
300
+ const kindDesc = this.getKindDescription();
301
+ const requiredDesc = this.isRequired ? 'required' : 'optional';
302
+ return `${cardinalityDesc} ${kindDesc} (${requiredDesc})`;
303
+ }
304
+ /**
305
+ * Get cardinality description
306
+ */
307
+ getCardinalityDescription() {
308
+ switch (this.type) {
309
+ case AXPRelationshipCardinality.OneToOne:
310
+ return 'one-to-one';
311
+ case AXPRelationshipCardinality.OneToMany:
312
+ return 'one-to-many';
313
+ case AXPRelationshipCardinality.ManyToMany:
314
+ return 'many-to-many';
315
+ default:
316
+ return 'unknown';
317
+ }
318
+ }
319
+ /**
320
+ * Get kind description
321
+ */
322
+ getKindDescription() {
323
+ switch (this.kind) {
324
+ case AXPRelationshipKind.Association:
325
+ return 'association';
326
+ case AXPRelationshipKind.Composition:
327
+ return 'composition';
328
+ case AXPRelationshipKind.Aggregation:
329
+ return 'aggregation';
330
+ default:
331
+ return 'unknown';
332
+ }
333
+ }
334
+ /**
335
+ * Get relation summary
336
+ */
337
+ getSummary() {
338
+ return `${this.source.entity}.${this.source.key} -> ${this.target.aggregate}.${this.target.entity}.${this.target.key}`;
339
+ }
340
+ //#endregion
341
+ //#region ---- Validation Methods ----
342
+ /**
343
+ * Validate the relation structure
344
+ */
345
+ validate() {
346
+ const errors = [];
347
+ // Validate source
348
+ if (!this.source.entity)
349
+ errors.push('Source entity is required');
350
+ if (!this.source.key)
351
+ errors.push('Source key is required');
352
+ // Validate target
353
+ if (!this.target.aggregate)
354
+ errors.push('Target aggregate is required');
355
+ if (!this.target.entity)
356
+ errors.push('Target entity is required');
357
+ if (!this.target.key)
358
+ errors.push('Target key is required');
359
+ return errors;
360
+ }
361
+ //#endregion
362
+ //#region ---- Utility Methods ----
363
+ /**
364
+ * Get relation characteristics
365
+ */
366
+ getCharacteristics() {
367
+ return {
368
+ type: this.getCardinalityDescription(),
369
+ kind: this.getKindDescription(),
370
+ required: this.isRequired,
371
+ isOwning: this.isComposition(),
372
+ isNavigable: !this.isComposition() || this.isOneToOne()
373
+ };
374
+ }
375
+ /**
376
+ * Check if relation involves entity
377
+ */
378
+ involvesEntity(entityName) {
379
+ return this.source.entity === entityName || this.target.entity === entityName;
380
+ }
381
+ /**
382
+ * Check if relation targets aggregate
383
+ */
384
+ targetsAggregate(aggregateName) {
385
+ return this.target.aggregate === aggregateName;
386
+ }
387
+ /**
388
+ * Get the other entity in the relation
389
+ */
390
+ getOtherEntity(entityName) {
391
+ if (this.source.entity === entityName) {
392
+ return this.target.entity;
393
+ }
394
+ else if (this.target.entity === entityName) {
395
+ return this.source.entity;
396
+ }
397
+ return null;
398
+ }
399
+ /**
400
+ * Convert back to interface definition
401
+ */
402
+ toDefinition() {
403
+ return {
404
+ type: this.type,
405
+ kind: this.kind,
406
+ target: { ...this.target },
407
+ source: { ...this.source },
408
+ isRequired: this.isRequired
409
+ };
410
+ }
411
+ }
412
+
413
+ //#region ---- AXPAggregateModel ----
414
+ /**
415
+ * Simple runtime model for aggregate definitions with parent references and navigation helpers.
416
+ *
417
+ * This model is a pure data structure that provides:
418
+ * - Access to aggregate properties and metadata
419
+ * - Navigation helpers for finding relations and entity references
420
+ * - Parent module reference for hierarchy navigation
421
+ *
422
+ * All loading and resolution logic has been moved to AXPDomainRegistry.
423
+ */
424
+ class AXPAggregateModel {
425
+ constructor(definition, parent) {
426
+ this.relations = [];
427
+ this.name = definition.name;
428
+ this.title = definition.title;
429
+ this.validations = definition.validations || [];
430
+ this.actions = definition.actions || [];
431
+ this.parent = parent;
432
+ // Initialize relations with parent reference
433
+ this.relations = (definition.relations || []).map(relationDef => new AXPRelationModel(relationDef, this));
434
+ // Extract entity references - convert all formats to simple string map
435
+ this.entityReferences = this.extractEntityReferences(definition.entities);
436
+ }
437
+ //#endregion
438
+ //#region ---- Entity Reference Extraction ----
439
+ /**
440
+ * Extract entity references from various entity definition formats
441
+ * and convert to simple string map
442
+ */
443
+ extractEntityReferences(entities) {
444
+ if (!entities) {
445
+ return {};
446
+ }
447
+ if (Array.isArray(entities)) {
448
+ // Format 1: Array of entity definitions - convert to self-references
449
+ const references = {};
450
+ for (const entity of entities) {
451
+ if (entity.name) {
452
+ // Self-reference format: module.aggregate.entity
453
+ references[entity.name] = `${this.parent.name}.${this.name}.${entity.name}`;
454
+ }
455
+ }
456
+ return references;
457
+ }
458
+ if (typeof entities === 'object') {
459
+ // Format 2: Object with string references - use as-is
460
+ return { ...entities };
461
+ }
462
+ return {};
463
+ }
464
+ //#endregion
465
+ //#region ---- Navigation Helpers ----
466
+ /**
467
+ * Get entity reference by name
468
+ *
469
+ * @param entityName Name of the entity
470
+ * @returns Entity reference string or undefined if not found
471
+ */
472
+ getEntityReference(entityName) {
473
+ return this.entityReferences[entityName];
474
+ }
475
+ /**
476
+ * Get full path for an entity in this aggregate
477
+ *
478
+ * @param entityName Name of the entity
479
+ * @returns Full entity path
480
+ */
481
+ getEntityPath(entityName) {
482
+ return `${this.parent.name}.${this.name}.${entityName}`;
483
+ }
484
+ /**
485
+ * Get all available entity names
486
+ *
487
+ * @returns Array of entity names
488
+ */
489
+ getEntityNames() {
490
+ return Object.keys(this.entityReferences);
491
+ }
492
+ /**
493
+ * Check if entity exists in this aggregate
494
+ *
495
+ * @param entityName Name of the entity
496
+ * @returns True if entity exists
497
+ */
498
+ hasEntity(entityName) {
499
+ return entityName in this.entityReferences;
500
+ }
501
+ /**
502
+ * Find relation by source and target entities
503
+ *
504
+ * @param sourceEntity Source entity name
505
+ * @param targetEntity Target entity name
506
+ * @returns Relation model or undefined if not found
507
+ */
508
+ findRelation(sourceEntity, targetEntity) {
509
+ return this.relations.find(relation => relation.source.entity === sourceEntity &&
510
+ relation.target.entity === targetEntity);
511
+ }
512
+ /**
513
+ * Get all relations for a specific entity
514
+ *
515
+ * @param entityName Entity name
516
+ * @returns Array of relations involving the entity
517
+ */
518
+ getEntityRelations(entityName) {
519
+ return this.relations.filter(relation => relation.source.entity === entityName ||
520
+ relation.target.entity === entityName);
521
+ }
522
+ //#endregion
523
+ //#region ---- Parent Navigation ----
524
+ /**
525
+ * Get parent module
526
+ *
527
+ * @returns Parent module model
528
+ */
529
+ getModule() {
530
+ return this.parent;
531
+ }
532
+ /**
533
+ * Get full aggregate path (module.aggregate)
534
+ *
535
+ * @returns Full path string
536
+ */
537
+ getPath() {
538
+ return `${this.parent.name}.${this.name}`;
539
+ }
540
+ //#endregion
541
+ //#region ---- Utility Methods ----
542
+ /**
543
+ * Get aggregate statistics
544
+ *
545
+ * @returns Statistics object
546
+ */
547
+ getStatistics() {
548
+ return {
549
+ entityCount: Object.keys(this.entityReferences).length,
550
+ relationCount: this.relations.length,
551
+ actionCount: this.actions.length,
552
+ validationCount: this.validations.length
553
+ };
554
+ }
555
+ /**
556
+ * Convert back to interface definition
557
+ *
558
+ * @returns Aggregate definition
559
+ */
560
+ toDefinition() {
561
+ return {
562
+ name: this.name,
563
+ title: this.title,
564
+ entities: this.entityReferences, // Return as reference map
565
+ relations: this.relations.map(relation => relation.toDefinition()),
566
+ validations: this.validations,
567
+ actions: this.actions
568
+ };
569
+ }
570
+ //#endregion
571
+ //#region ---- Validation Methods ----
572
+ /**
573
+ * Validate the aggregate structure (synchronous validation only)
574
+ *
575
+ * @returns Array of validation errors
576
+ */
577
+ validate() {
578
+ const errors = [];
579
+ // Validate aggregate structure
580
+ if (!this.name)
581
+ errors.push('Aggregate name is required');
582
+ if (!this.title)
583
+ errors.push('Aggregate title is required');
584
+ // Validate relations
585
+ this.relations.forEach(relation => {
586
+ const relationErrors = relation.validate();
587
+ if (relationErrors.length > 0) {
588
+ errors.push(...relationErrors.map(err => `Relation: ${err}`));
589
+ }
590
+ });
591
+ // Validate entity references
592
+ for (const [entityName, entityRef] of Object.entries(this.entityReferences)) {
593
+ if (!entityRef || typeof entityRef !== 'string') {
594
+ errors.push(`Invalid entity reference for '${entityName}': must be a non-empty string`);
595
+ }
596
+ }
597
+ return errors;
598
+ }
599
+ }
600
+ //#endregion
601
+
602
+ //#region ---- AXPModuleModel ----
603
+ /**
604
+ * Simple runtime model for module definitions with navigation helpers.
605
+ *
606
+ * This model is a pure data structure that provides:
607
+ * - Access to module properties and metadata
608
+ * - Navigation helpers for finding aggregates
609
+ * - Hierarchy navigation and path generation
610
+ *
611
+ * All loading and resolution logic has been moved to AXPDomainRegistry.
612
+ */
613
+ class AXPModuleModel {
614
+ constructor(definition) {
615
+ this.aggregates = [];
616
+ this.name = definition.name;
617
+ this.title = definition.title;
618
+ // Initialize aggregates with parent reference (simplified constructor)
619
+ this.aggregates = (definition.aggregates || []).map(aggDef => new AXPAggregateModel(aggDef, this));
620
+ }
621
+ //#endregion
622
+ //#region ---- Navigation Helpers ----
623
+ /**
624
+ * Find aggregate by name
625
+ *
626
+ * @param name Aggregate name
627
+ * @returns Aggregate model or undefined if not found
628
+ */
629
+ findAggregate(name) {
630
+ return this.aggregates.find(agg => agg.name === name);
631
+ }
632
+ /**
633
+ * Get all aggregates
634
+ *
635
+ * @returns Array of all aggregate models
636
+ */
637
+ getAllAggregates() {
638
+ return [...this.aggregates];
639
+ }
640
+ /**
641
+ * Check if aggregate exists in this module
642
+ *
643
+ * @param name Aggregate name
644
+ * @returns True if aggregate exists
645
+ */
646
+ hasAggregate(name) {
647
+ return this.aggregates.some(agg => agg.name === name);
648
+ }
649
+ /**
650
+ * Get all aggregate names
651
+ *
652
+ * @returns Array of aggregate names
653
+ */
654
+ getAggregateNames() {
655
+ return this.aggregates.map(agg => agg.name);
656
+ }
657
+ /**
658
+ * Find entity reference across all aggregates
659
+ *
660
+ * @param entityName Entity name to search for
661
+ * @returns Object with aggregate and entity reference, or undefined if not found
662
+ */
663
+ findEntityReference(entityName) {
664
+ for (const aggregate of this.aggregates) {
665
+ const entityReference = aggregate.getEntityReference(entityName);
666
+ if (entityReference) {
667
+ return { aggregate, entityReference };
668
+ }
669
+ }
670
+ return undefined;
671
+ }
672
+ /**
673
+ * Get entity path for a specific entity in a specific aggregate
674
+ *
675
+ * @param aggregateName Aggregate name
676
+ * @param entityName Entity name
677
+ * @returns Full entity path
678
+ */
679
+ getEntityPath(aggregateName, entityName) {
680
+ return `${this.name}.${aggregateName}.${entityName}`;
681
+ }
682
+ /**
683
+ * Get aggregate path
684
+ *
685
+ * @param aggregateName Aggregate name
686
+ * @returns Full aggregate path
687
+ */
688
+ getAggregatePath(aggregateName) {
689
+ return `${this.name}.${aggregateName}`;
690
+ }
691
+ //#endregion
692
+ //#region ---- Query Methods ----
693
+ /**
694
+ * Get all entity references across all aggregates
695
+ *
696
+ * @returns Map of entity name to full path
697
+ */
698
+ getAllEntityReferences() {
699
+ const allReferences = {};
700
+ for (const aggregate of this.aggregates) {
701
+ const aggregateReferences = aggregate.entityReferences;
702
+ for (const [entityName, entityRef] of Object.entries(aggregateReferences)) {
703
+ // Use full path as key to avoid conflicts
704
+ const fullKey = `${aggregate.name}.${entityName}`;
705
+ allReferences[fullKey] = entityRef;
706
+ }
707
+ }
708
+ return allReferences;
709
+ }
710
+ /**
711
+ * Get all relations across all aggregates
712
+ *
713
+ * @returns Array of all relation models
714
+ */
715
+ getAllRelations() {
716
+ const allRelations = [];
717
+ for (const aggregate of this.aggregates) {
718
+ for (const relation of aggregate.relations) {
719
+ allRelations.push({ aggregate, relation });
720
+ }
721
+ }
722
+ return allRelations;
723
+ }
724
+ //#endregion
725
+ //#region ---- Validation Methods ----
726
+ /**
727
+ * Validate the module structure (synchronous validation only)
728
+ *
729
+ * @returns Array of validation errors
730
+ */
731
+ validate() {
732
+ const errors = [];
733
+ // Validate module structure
734
+ if (!this.name)
735
+ errors.push('Module name is required');
736
+ if (!this.title)
737
+ errors.push('Module title is required');
738
+ // Check for duplicate aggregate names
739
+ const aggregateNames = this.aggregates.map(agg => agg.name);
740
+ const duplicateNames = aggregateNames.filter((name, index) => aggregateNames.indexOf(name) !== index);
741
+ if (duplicateNames.length > 0) {
742
+ errors.push(`Duplicate aggregate names: ${duplicateNames.join(', ')}`);
743
+ }
744
+ // Validate aggregates
745
+ for (const aggregate of this.aggregates) {
746
+ const aggErrors = aggregate.validate();
747
+ if (aggErrors.length > 0) {
748
+ errors.push(...aggErrors.map((err) => `${aggregate.name}: ${err}`));
749
+ }
750
+ }
751
+ return errors;
752
+ }
753
+ //#endregion
754
+ //#region ---- Utility Methods ----
755
+ /**
756
+ * Get module statistics
757
+ *
758
+ * @returns Statistics object
759
+ */
760
+ getStatistics() {
761
+ const aggregateStats = this.aggregates.map(agg => agg.getStatistics());
762
+ return {
763
+ aggregateCount: this.aggregates.length,
764
+ entityCount: aggregateStats.reduce((sum, stat) => sum + stat.entityCount, 0),
765
+ relationCount: aggregateStats.reduce((sum, stat) => sum + stat.relationCount, 0),
766
+ actionCount: aggregateStats.reduce((sum, stat) => sum + stat.actionCount, 0),
767
+ validationCount: aggregateStats.reduce((sum, stat) => sum + stat.validationCount, 0)
768
+ };
769
+ }
770
+ /**
771
+ * Convert back to interface definition
772
+ *
773
+ * @returns Module definition
774
+ */
775
+ toDefinition() {
776
+ return {
777
+ name: this.name,
778
+ title: this.title,
779
+ aggregates: this.aggregates.map(agg => agg.toDefinition())
780
+ };
781
+ }
782
+ }
783
+ //#endregion
784
+
785
+ //#region ---- AXPEntityFieldModel ----
786
+ /**
787
+ * Runtime model for entity field definitions with parent references and helper methods
788
+ */
789
+ class AXPEntityFieldModel {
790
+ constructor(definition, parent, schemaService) {
791
+ this.name = definition.name;
792
+ this.title = definition.title;
793
+ this.description = definition.description;
794
+ this.validations = definition.validations;
795
+ this.actions = definition.actions;
796
+ this.features = definition.features;
797
+ this.defaultValue = definition.defaultValue;
798
+ this.parent = parent;
799
+ this.schemaService = schemaService;
800
+ // Store schema name for toDefinition
801
+ this.schemaName = definition.schema;
802
+ // Resolve schema by name from schema service
803
+ this.schema = schemaService.resolveSync(definition.schema);
804
+ }
805
+ //#endregion
806
+ //#region ---- Feature Check Methods ----
807
+ /**
808
+ * Check if field is nullable
809
+ */
810
+ isNullable() {
811
+ return this.features?.nullable ?? false;
812
+ }
813
+ /**
814
+ * Check if field is readonly
815
+ */
816
+ isReadonly() {
817
+ return this.features?.readOnly ?? false;
818
+ }
819
+ /**
820
+ * Check if field is required (has required validation)
821
+ */
822
+ isRequired() {
823
+ return this.validations?.some(validation => validation.rule === 'required') ?? false;
824
+ }
825
+ /**
826
+ * Check if field is searchable
827
+ */
828
+ isSearchable() {
829
+ return this.schema.features?.searchable?.enabled ?? false;
830
+ }
831
+ /**
832
+ * Check if field supports full text search
833
+ */
834
+ isFullTextSearchable() {
835
+ return this.schema.features?.searchable?.fullText ?? false;
836
+ }
837
+ /**
838
+ * Check if field is filterable
839
+ */
840
+ isFilterable() {
841
+ return this.schema.features?.filterable?.enabled ?? false;
842
+ }
843
+ /**
844
+ * Check if field has inline filtering
845
+ */
846
+ hasInlineFiltering() {
847
+ return this.schema.features?.filterable?.inline ?? false;
848
+ }
849
+ /**
850
+ * Check if field is sortable
851
+ */
852
+ isSortable() {
853
+ return this.schema.features?.sortable?.enabled ?? false;
854
+ }
855
+ /**
856
+ * Check if field is auditable
857
+ */
858
+ isAuditable() {
859
+ return this.schema.features?.auditable?.enabled ?? false;
860
+ }
861
+ //#endregion
862
+ //#region ---- Schema Methods ----
863
+ /**
864
+ * Get the schema name
865
+ */
866
+ getSchemaName() {
867
+ return this.schemaName;
868
+ }
869
+ /**
870
+ * Get schema info from registry
871
+ */
872
+ getSchemaInfo() {
873
+ return this.schemaService.getSchemaInfo(this.schemaName);
874
+ }
875
+ /**
876
+ * Re-resolve schema from registry (useful after schema updates)
877
+ */
878
+ refreshSchema() {
879
+ const newSchema = this.schemaService.resolveSync(this.schemaName);
880
+ this.schema = newSchema;
881
+ this.schema.parent = this;
882
+ }
883
+ //#endregion
884
+ //#region ---- Navigation Methods ----
885
+ /**
886
+ * Get parent entity
887
+ */
888
+ getEntity() {
889
+ return this.parent;
890
+ }
891
+ /**
892
+ * Get parent aggregate
893
+ */
894
+ getAggregate() {
895
+ return this.parent?.parent;
896
+ }
897
+ /**
898
+ * Get parent module
899
+ */
900
+ getModule() {
901
+ return this.parent?.parent?.parent;
902
+ }
903
+ /**
904
+ * Get full path (module.aggregate.entity.field)
905
+ */
906
+ getPath() {
907
+ return `${this.parent.parent.parent.name}.${this.parent.parent.name}.${this.parent.name}.${this.name}`;
908
+ }
909
+ //#endregion
910
+ //#region ---- Validation Methods ----
911
+ /**
912
+ * Validate the field structure
913
+ */
914
+ async validate() {
915
+ const errors = [];
916
+ // Validate field structure
917
+ if (!this.name)
918
+ errors.push('Field name is required');
919
+ if (!this.title)
920
+ errors.push('Field title is required');
921
+ // Validate schema name
922
+ if (!this.schemaName) {
923
+ errors.push('Schema name is required');
924
+ }
925
+ else {
926
+ if (!this.schemaService.isRegistered(this.schemaName)) {
927
+ errors.push(`Schema '${this.schemaName}' is not registered`);
928
+ }
929
+ }
930
+ // Validate schema if it exists
931
+ if (this.schema) {
932
+ const schemaErrors = await this.schema.validate();
933
+ if (schemaErrors.length > 0) {
934
+ errors.push(...schemaErrors.map(err => `Schema: ${err}`));
935
+ }
936
+ }
937
+ return errors;
938
+ }
939
+ //#endregion
940
+ //#region ---- Utility Methods ----
941
+ /**
942
+ * Get field statistics
943
+ */
944
+ getStatistics() {
945
+ return {
946
+ hasValidations: !!this.validations && this.validations.length > 0,
947
+ hasActions: !!this.actions && this.actions.length > 0,
948
+ hasFeatures: !!this.features,
949
+ hasDefaultValue: this.defaultValue !== undefined,
950
+ validationCount: this.validations?.length ?? 0,
951
+ actionCount: this.actions?.length ?? 0
952
+ };
953
+ }
954
+ /**
955
+ * Get field capabilities
956
+ */
957
+ getCapabilities() {
958
+ return {
959
+ searchable: this.isSearchable(),
960
+ filterable: this.isFilterable(),
961
+ sortable: this.isSortable(),
962
+ auditable: this.isAuditable(),
963
+ nullable: this.isNullable(),
964
+ readonly: this.isReadonly(),
965
+ required: this.isRequired()
966
+ };
967
+ }
968
+ /**
969
+ * Convert back to interface definition
970
+ */
971
+ toDefinition() {
972
+ return {
973
+ name: this.name,
974
+ title: this.title,
975
+ description: this.description,
976
+ validations: this.validations,
977
+ actions: this.actions,
978
+ features: this.features,
979
+ defaultValue: this.defaultValue,
980
+ schema: this.schemaName
981
+ };
982
+ }
983
+ }
984
+
985
+ //#region ---- AXPEntityModel ----
986
+ /**
987
+ * Runtime model for entity definitions with parent references and helper methods
988
+ */
989
+ class AXPEntityModel {
990
+ constructor(definition, parent, schemaService) {
991
+ this.fields = [];
992
+ this.name = definition.name;
993
+ this.title = definition.title;
994
+ this.type = definition.type;
995
+ this.parent = parent;
996
+ this.schemaService = schemaService;
997
+ // Initialize fields with parent reference and schema service
998
+ this.fields = definition.fields.map(fieldDef => new AXPEntityFieldModel(fieldDef, this, schemaService));
999
+ }
1000
+ //#endregion
1001
+ //#region ---- Query Methods ----
1002
+ /**
1003
+ * Find field by name
1004
+ */
1005
+ findField(name) {
1006
+ return this.fields.find(field => field.name === name);
1007
+ }
1008
+ /**
1009
+ * Get all fields
1010
+ */
1011
+ getAllFields() {
1012
+ return [...this.fields];
1013
+ }
1014
+ /**
1015
+ * Get fields by data type
1016
+ */
1017
+ getFieldsByType(dataType) {
1018
+ return this.fields.filter(field => field.schema.dataType === dataType);
1019
+ }
1020
+ /**
1021
+ * Get required fields
1022
+ */
1023
+ getRequiredFields() {
1024
+ return this.fields.filter(field => field.isRequired());
1025
+ }
1026
+ /**
1027
+ * Get readonly fields
1028
+ */
1029
+ getReadonlyFields() {
1030
+ return this.fields.filter(field => field.isReadonly());
1031
+ }
1032
+ /**
1033
+ * Get searchable fields
1034
+ */
1035
+ getSearchableFields() {
1036
+ return this.fields.filter(field => field.isSearchable());
1037
+ }
1038
+ /**
1039
+ * Get filterable fields
1040
+ */
1041
+ getFilterableFields() {
1042
+ return this.fields.filter(field => field.isFilterable());
1043
+ }
1044
+ /**
1045
+ * Get sortable fields
1046
+ */
1047
+ getSortableFields() {
1048
+ return this.fields.filter(field => field.isSortable());
1049
+ }
1050
+ //#endregion
1051
+ //#region ---- Type Checking Methods ----
1052
+ /**
1053
+ * Check if this entity is an aggregate root
1054
+ */
1055
+ isAggregateRoot() {
1056
+ return this.type === AXPEntityType.AggregateRoot;
1057
+ }
1058
+ /**
1059
+ * Check if this entity is a regular entity
1060
+ */
1061
+ isEntity() {
1062
+ return this.type === AXPEntityType.Entity;
1063
+ }
1064
+ /**
1065
+ * Check if this entity is a value object
1066
+ */
1067
+ isValueObject() {
1068
+ return this.type === AXPEntityType.ValueObject;
1069
+ }
1070
+ //#endregion
1071
+ //#region ---- Navigation Methods ----
1072
+ /**
1073
+ * Get parent aggregate
1074
+ */
1075
+ getAggregate() {
1076
+ return this.parent;
1077
+ }
1078
+ /**
1079
+ * Get parent module
1080
+ */
1081
+ getModule() {
1082
+ return this.parent?.parent;
1083
+ }
1084
+ /**
1085
+ * Get full path (module.aggregate.entity)
1086
+ */
1087
+ getPath() {
1088
+ return `${this.parent.parent.name}.${this.parent.name}.${this.name}`;
1089
+ }
1090
+ //#endregion
1091
+ //#region ---- Validation Methods ----
1092
+ /**
1093
+ * Validate the entity structure
1094
+ */
1095
+ async validate() {
1096
+ const errors = [];
1097
+ // Validate entity structure
1098
+ if (!this.name)
1099
+ errors.push('Entity name is required');
1100
+ if (!this.title)
1101
+ errors.push('Entity title is required');
1102
+ // Validate fields
1103
+ for (const field of this.fields) {
1104
+ const fieldErrors = await field.validate();
1105
+ if (fieldErrors.length > 0) {
1106
+ errors.push(...fieldErrors.map(err => `${field.name}: ${err}`));
1107
+ }
1108
+ }
1109
+ return errors;
1110
+ }
1111
+ //#endregion
1112
+ //#region ---- Utility Methods ----
1113
+ /**
1114
+ * Get entity statistics
1115
+ */
1116
+ getStatistics() {
1117
+ return {
1118
+ fieldCount: this.fields.length,
1119
+ requiredFieldCount: this.getRequiredFields().length,
1120
+ readonlyFieldCount: this.getReadonlyFields().length,
1121
+ searchableFieldCount: this.getSearchableFields().length,
1122
+ filterableFieldCount: this.getFilterableFields().length,
1123
+ sortableFieldCount: this.getSortableFields().length
1124
+ };
1125
+ }
1126
+ /**
1127
+ * Convert back to interface definition
1128
+ */
1129
+ toDefinition() {
1130
+ return {
1131
+ name: this.name,
1132
+ title: this.title,
1133
+ fields: this.fields.map(field => field.toDefinition()),
1134
+ type: this.type
1135
+ };
1136
+ }
1137
+ }
1138
+
1139
+ //#region ---- AXPSchemaModel ----
1140
+ /**
1141
+ * Runtime model for schema definitions with helper methods
1142
+ */
1143
+ class AXPSchemaModel {
1144
+ constructor(definition) {
1145
+ this.name = definition.name;
1146
+ this.dataType = definition.dataType;
1147
+ this.interface = definition.interface;
1148
+ this.validations = definition.validations ?? [];
1149
+ this.features = definition.features ?? {};
1150
+ this.metadata = definition.metadata;
1151
+ }
1152
+ //#endregion
1153
+ //#region ---- Data Type Methods ----
1154
+ /**
1155
+ * Check if schema is for string data
1156
+ */
1157
+ isString() {
1158
+ return this.dataType === 'string';
1159
+ }
1160
+ /**
1161
+ * Check if schema is for number data
1162
+ */
1163
+ isNumber() {
1164
+ return this.dataType === 'number';
1165
+ }
1166
+ /**
1167
+ * Check if schema is for boolean data
1168
+ */
1169
+ isBoolean() {
1170
+ return this.dataType === 'boolean';
1171
+ }
1172
+ /**
1173
+ * Check if schema is for date data
1174
+ */
1175
+ isDate() {
1176
+ return this.dataType === 'date';
1177
+ }
1178
+ /**
1179
+ * Check if schema is for object data
1180
+ */
1181
+ isObject() {
1182
+ return this.dataType === 'object';
1183
+ }
1184
+ /**
1185
+ * Check if schema is for array data
1186
+ */
1187
+ isArray() {
1188
+ return this.dataType === 'array';
1189
+ }
1190
+ /**
1191
+ * Check if schema is for blob data
1192
+ */
1193
+ isBlob() {
1194
+ return this.dataType === 'blob';
1195
+ }
1196
+ //#endregion
1197
+ //#region ---- Interface Methods ----
1198
+ /**
1199
+ * Get widget type
1200
+ */
1201
+ getWidgetType() {
1202
+ return this.interface.widget;
1203
+ }
1204
+ /**
1205
+ * Get widget options
1206
+ */
1207
+ getWidgetOptions() {
1208
+ return this.interface.options;
1209
+ }
1210
+ /**
1211
+ * Check if interface is disabled
1212
+ */
1213
+ isDisabled() {
1214
+ return this.interface.disabled ?? false;
1215
+ }
1216
+ //#endregion
1217
+ //#region ---- Feature Methods ----
1218
+ /**
1219
+ * Check if searchable
1220
+ */
1221
+ isSearchable() {
1222
+ return this.features.searchable?.enabled ?? false;
1223
+ }
1224
+ /**
1225
+ * Check if full text searchable
1226
+ */
1227
+ isFullTextSearchable() {
1228
+ return this.features.searchable?.fullText ?? false;
1229
+ }
1230
+ /**
1231
+ * Check if filterable
1232
+ */
1233
+ isFilterable() {
1234
+ return this.features.filterable?.enabled ?? false;
1235
+ }
1236
+ /**
1237
+ * Check if inline filterable
1238
+ */
1239
+ isInlineFilterable() {
1240
+ return this.features.filterable?.inline ?? false;
1241
+ }
1242
+ /**
1243
+ * Check if sortable
1244
+ */
1245
+ isSortable() {
1246
+ return this.features.sortable?.enabled ?? false;
1247
+ }
1248
+ /**
1249
+ * Check if auditable
1250
+ */
1251
+ isAuditable() {
1252
+ return this.features.auditable?.enabled ?? false;
1253
+ }
1254
+ //#endregion
1255
+ //#region ---- Validation Methods ----
1256
+ /**
1257
+ * Validate the schema structure
1258
+ */
1259
+ async validate() {
1260
+ const errors = [];
1261
+ // Validate data type
1262
+ const validDataTypes = ['string', 'number', 'boolean', 'date', 'object', 'array', 'blob'];
1263
+ if (!validDataTypes.includes(this.dataType)) {
1264
+ errors.push(`Invalid data type: ${this.dataType}`);
1265
+ }
1266
+ // Validate interface
1267
+ if (!this.interface.widget) {
1268
+ errors.push('Widget type is required');
1269
+ }
1270
+ return errors;
1271
+ }
1272
+ //#endregion
1273
+ //#region ---- Utility Methods ----
1274
+ /**
1275
+ * Get schema capabilities
1276
+ */
1277
+ getCapabilities() {
1278
+ return {
1279
+ searchable: this.isSearchable(),
1280
+ fullTextSearchable: this.isFullTextSearchable(),
1281
+ filterable: this.isFilterable(),
1282
+ inlineFilterable: this.isInlineFilterable(),
1283
+ sortable: this.isSortable(),
1284
+ auditable: this.isAuditable(),
1285
+ disabled: this.isDisabled()
1286
+ };
1287
+ }
1288
+ /**
1289
+ * Get schema summary
1290
+ */
1291
+ getSummary() {
1292
+ const capabilities = this.getCapabilities();
1293
+ const capabilityCount = Object.values(capabilities).filter(Boolean).length;
1294
+ return {
1295
+ dataType: this.dataType,
1296
+ widget: this.getWidgetType(),
1297
+ hasOptions: !!this.interface.options,
1298
+ hasMetadata: !!this.metadata,
1299
+ hasValidations: !!this.validations && this.validations.length > 0,
1300
+ capabilityCount
1301
+ };
1302
+ }
1303
+ /**
1304
+ * Convert back to interface definition
1305
+ */
1306
+ toDefinition() {
1307
+ return {
1308
+ name: this.name,
1309
+ dataType: this.dataType,
1310
+ interface: this.interface,
1311
+ validations: this.validations,
1312
+ features: this.features,
1313
+ metadata: this.metadata
1314
+ };
1315
+ }
1316
+ }
1317
+
1318
+ //#region ---- AXPModuleHelper ----
1319
+ /**
1320
+ * Helper utility class for working with module models
1321
+ *
1322
+ * @deprecated This helper class is deprecated and will be updated to work with the new domain registry system.
1323
+ * Use AXPDomainService for domain operations instead.
1324
+ *
1325
+ * TODO: Update this helper to work with the new simplified models and domain registry system.
1326
+ */
1327
+ class AXPModuleHelper {
1328
+ //#endregion
1329
+ //#region ---- Deprecated Methods - To Be Updated ----
1330
+ /**
1331
+ * @deprecated Use AXPDomainService.findEntitiesByName() instead
1332
+ */
1333
+ static findEntitiesByName(module, name) {
1334
+ console.warn('AXPModuleHelper.findEntitiesByName is deprecated. Use AXPDomainService instead.');
1335
+ return [];
1336
+ }
1337
+ /**
1338
+ * @deprecated Use AXPDomainService with entity field queries instead
1339
+ */
1340
+ static findFieldsByName(module, fieldName) {
1341
+ console.warn('AXPModuleHelper.findFieldsByName is deprecated. Use AXPDomainService instead.');
1342
+ return [];
1343
+ }
1344
+ /**
1345
+ * @deprecated Use AXPDomainService with entity type queries instead
1346
+ */
1347
+ static findEntitiesByType(module, type) {
1348
+ console.warn('AXPModuleHelper.findEntitiesByType is deprecated. Use AXPDomainService instead.');
1349
+ return [];
1350
+ }
1351
+ /**
1352
+ * @deprecated Use AXPDomainService with field validation queries instead
1353
+ */
1354
+ static findFieldsWithValidation(module, validationRule) {
1355
+ console.warn('AXPModuleHelper.findFieldsWithValidation is deprecated. Use AXPDomainService instead.');
1356
+ return [];
1357
+ }
1358
+ /**
1359
+ * @deprecated Use AXPDomainService with field queries instead
1360
+ */
1361
+ static findFieldsByDataType(module, dataType) {
1362
+ console.warn('AXPModuleHelper.findFieldsByDataType is deprecated. Use AXPDomainService instead.');
1363
+ return [];
1364
+ }
1365
+ /**
1366
+ * @deprecated Use AXPDomainService with required field queries instead
1367
+ */
1368
+ static findRequiredFields(module) {
1369
+ console.warn('AXPModuleHelper.findRequiredFields is deprecated. Use AXPDomainService instead.');
1370
+ return [];
1371
+ }
1372
+ /**
1373
+ * @deprecated Use AXPDomainService with nullable field queries instead
1374
+ */
1375
+ static findNullableFields(module) {
1376
+ console.warn('AXPModuleHelper.findNullableFields is deprecated. Use AXPDomainService instead.');
1377
+ return [];
1378
+ }
1379
+ /**
1380
+ * @deprecated Use AXPDomainService with default value queries instead
1381
+ */
1382
+ static findFieldsWithDefaultValues(module) {
1383
+ console.warn('AXPModuleHelper.findFieldsWithDefaultValues is deprecated. Use AXPDomainService instead.');
1384
+ return [];
1385
+ }
1386
+ /**
1387
+ * @deprecated Use AXPDomainService with field schema queries instead
1388
+ */
1389
+ static findFieldsBySchema(module, schemaName) {
1390
+ console.warn('AXPModuleHelper.findFieldsBySchema is deprecated. Use AXPDomainService instead.');
1391
+ return [];
1392
+ }
1393
+ /**
1394
+ * @deprecated Use module.validate() method instead
1395
+ */
1396
+ static validateModule(module) {
1397
+ return module.validate();
1398
+ }
1399
+ /**
1400
+ * @deprecated Use aggregate relation queries instead
1401
+ */
1402
+ static findRelationsByType(module, relationType) {
1403
+ console.warn('AXPModuleHelper.findRelationsByType is deprecated. Use relation queries instead.');
1404
+ return [];
1405
+ }
1406
+ /**
1407
+ * @deprecated Use AXPDomainService with entity dependency queries instead
1408
+ */
1409
+ static findEntityDependencies(module, entityName) {
1410
+ console.warn('AXPModuleHelper.findEntityDependencies is deprecated. Use AXPDomainService instead.');
1411
+ return [];
1412
+ }
1413
+ /**
1414
+ * @deprecated Use module.getStatistics() method instead
1415
+ */
1416
+ static getModuleStatistics(module) {
1417
+ return module.getStatistics();
1418
+ }
1419
+ /**
1420
+ * @deprecated Use AXPDomainService with entity queries instead
1421
+ */
1422
+ static getAllEntities(module) {
1423
+ console.warn('AXPModuleHelper.getAllEntities is deprecated. Use AXPDomainService instead.');
1424
+ return [];
1425
+ }
1426
+ /**
1427
+ * @deprecated Use AXPDomainService with field queries instead
1428
+ */
1429
+ static getAllFields(module) {
1430
+ console.warn('AXPModuleHelper.getAllFields is deprecated. Use AXPDomainService instead.');
1431
+ return [];
1432
+ }
1433
+ }
1434
+
1435
+ //#region ---- Schema Middleware Context ----
1436
+ /**
1437
+ * Context class for schema middleware operations providing a fluent API for schema manipulation.
1438
+ *
1439
+ * This class serves as the interface between middleware functions and schema definitions,
1440
+ * offering methods to modify various aspects of a schema including:
1441
+ * - Widget configuration and options
1442
+ * - Validation rules
1443
+ * - Feature flags (searchable, filterable, sortable)
1444
+ * - Metadata and custom properties
1445
+ * - UI behavior (visibility, readonly state)
1446
+ *
1447
+ * All methods return `this` to enable fluent method chaining.
1448
+ *
1449
+ * @example
1450
+ * ```typescript
1451
+ * // Example middleware using the context
1452
+ * (context) => {
1453
+ * context
1454
+ * .addValidation({ rule: 'required' })
1455
+ * .searchable(true)
1456
+ * .withDefaultValue('default text')
1457
+ * .readonly(false);
1458
+ * }
1459
+ * ```
1460
+ */
1461
+ class AXPSchemaMiddlewareContext {
1462
+ constructor(schema) {
1463
+ // Deep clone to avoid mutating the original schema
1464
+ this._schema = JSON.parse(JSON.stringify(schema));
1465
+ }
1466
+ //#region ---- Schema Access Properties ----
1467
+ /**
1468
+ * Get the current schema definition (readonly access)
1469
+ */
1470
+ get schema() {
1471
+ return this._schema;
1472
+ }
1473
+ /**
1474
+ * Get the schema name for conditional logic
1475
+ */
1476
+ get name() {
1477
+ return this._schema.name;
1478
+ }
1479
+ //#endregion
1480
+ //#region ---- Default Value Management ----
1481
+ /**
1482
+ * Set a default value for the widget
1483
+ * @param defaultValue The default value to set
1484
+ */
1485
+ withDefaultValue(defaultValue) {
1486
+ if (!this._schema.interface.options) {
1487
+ this._schema.interface.options = {};
1488
+ }
1489
+ this._schema.interface.options['defaultValue'] = defaultValue;
1490
+ return this;
1491
+ }
1492
+ /**
1493
+ * Remove the default value from the widget
1494
+ */
1495
+ removeDefaultValue() {
1496
+ if (this._schema.interface.options) {
1497
+ delete this._schema.interface.options['defaultValue'];
1498
+ }
1499
+ return this;
1500
+ }
1501
+ //#endregion
1502
+ //#region ---- Validation Management ----
1503
+ /**
1504
+ * Add multiple validation rules to the schema
1505
+ * @param rules Array of validation rules to add
1506
+ */
1507
+ withValidation(rules) {
1508
+ if (!this._schema.validations) {
1509
+ this._schema.validations = [];
1510
+ }
1511
+ this._schema.validations.push(...rules);
1512
+ return this;
1513
+ }
1514
+ /**
1515
+ * Add a single validation rule to the schema
1516
+ * @param rule The validation rule to add
1517
+ */
1518
+ addValidation(rule) {
1519
+ if (!this._schema.validations) {
1520
+ this._schema.validations = [];
1521
+ }
1522
+ this._schema.validations.push(rule);
1523
+ return this;
1524
+ }
1525
+ /**
1526
+ * Add a single validation rule (alias for addValidation for backward compatibility)
1527
+ * @param rule The validation rule to add
1528
+ */
1529
+ withValidationRule(rule) {
1530
+ return this.addValidation(rule);
1531
+ }
1532
+ /**
1533
+ * Remove all validation rules from the schema
1534
+ */
1535
+ clearValidations() {
1536
+ this._schema.validations = [];
1537
+ return this;
1538
+ }
1539
+ /**
1540
+ * Remove a specific validation rule by its rule name
1541
+ * @param ruleName The name of the rule to remove (e.g., 'required', 'email')
1542
+ */
1543
+ removeValidation(ruleName) {
1544
+ if (this._schema.validations) {
1545
+ this._schema.validations = this._schema.validations.filter(v => v.rule !== ruleName);
1546
+ }
1547
+ return this;
1548
+ }
1549
+ //#endregion
1550
+ //#region ---- Widget Configuration ----
1551
+ /**
1552
+ * Set or merge widget options
1553
+ * @param options Object containing widget-specific options to merge
1554
+ */
1555
+ withWidgetOptions(options) {
1556
+ this._schema.interface.options = {
1557
+ ...this._schema.interface.options,
1558
+ ...options
1559
+ };
1560
+ return this;
1561
+ }
1562
+ /**
1563
+ * Remove a specific widget option by key
1564
+ * @param optionKey The key of the option to remove
1565
+ */
1566
+ removeWidgetOption(optionKey) {
1567
+ if (this._schema.interface.options) {
1568
+ delete this._schema.interface.options[optionKey];
1569
+ }
1570
+ return this;
1571
+ }
1572
+ /**
1573
+ * Change the widget type for this schema
1574
+ * @param widgetType The new widget type identifier
1575
+ */
1576
+ withWidgetType(widgetType) {
1577
+ this._schema.interface.widget = widgetType;
1578
+ return this;
1579
+ }
1580
+ //#endregion
1581
+ //#region ---- Feature Configuration ----
1582
+ /**
1583
+ * Configure general features using an object
1584
+ * @param features Object containing feature configurations to merge
1585
+ */
1586
+ withFeatures(features) {
1587
+ this._schema.features = {
1588
+ ...this._schema.features,
1589
+ ...features
1590
+ };
1591
+ return this;
1592
+ }
1593
+ /**
1594
+ * Configure searchable feature with fine-grained control
1595
+ * @param enabled Whether searching is enabled
1596
+ * @param fullText Whether full-text search is enabled
1597
+ */
1598
+ searchable(enabled = true, fullText = false) {
1599
+ if (!this._schema.features) {
1600
+ this._schema.features = {};
1601
+ }
1602
+ this._schema.features.searchable = { enabled, fullText };
1603
+ return this;
1604
+ }
1605
+ /**
1606
+ * Configure filterable feature with inline filter support
1607
+ * @param enabled Whether filtering is enabled
1608
+ * @param inline Whether inline filtering is supported
1609
+ */
1610
+ filterable(enabled = true, inline = false) {
1611
+ if (!this._schema.features) {
1612
+ this._schema.features = {};
1613
+ }
1614
+ this._schema.features.filterable = { enabled, inline };
1615
+ return this;
1616
+ }
1617
+ /**
1618
+ * Configure sortable feature
1619
+ * @param enabled Whether sorting is enabled
1620
+ */
1621
+ sortable(enabled = true) {
1622
+ if (!this._schema.features) {
1623
+ this._schema.features = {};
1624
+ }
1625
+ this._schema.features.sortable = { enabled };
1626
+ return this;
1627
+ }
1628
+ //#endregion
1629
+ //#region ---- Metadata Management ----
1630
+ /**
1631
+ * Add or merge metadata to the schema
1632
+ * @param metadata Object containing metadata to merge
1633
+ */
1634
+ withMetadata(metadata) {
1635
+ this._schema.metadata = {
1636
+ ...this._schema.metadata,
1637
+ ...metadata
1638
+ };
1639
+ return this;
1640
+ }
1641
+ /**
1642
+ * Remove a specific metadata property by key
1643
+ * @param key The metadata key to remove
1644
+ */
1645
+ removeMetadata(key) {
1646
+ if (this._schema.metadata) {
1647
+ delete this._schema.metadata[key];
1648
+ }
1649
+ return this;
1650
+ }
1651
+ //#endregion
1652
+ //#region ---- Schema Properties ----
1653
+ /**
1654
+ * Set the data type for this schema
1655
+ * @param dataType The new data type (string, number, boolean, etc.)
1656
+ */
1657
+ withDataType(dataType) {
1658
+ this._schema.dataType = dataType;
1659
+ return this;
1660
+ }
1661
+ //#endregion
1662
+ //#region ---- UI State Management ----
1663
+ /**
1664
+ * Set the disabled state of the widget
1665
+ * @param isDisabled Whether the widget should be disabled
1666
+ */
1667
+ disabled(isDisabled = true) {
1668
+ this._schema.interface.disabled = isDisabled;
1669
+ return this;
1670
+ }
1671
+ /**
1672
+ * Set the visibility of the widget
1673
+ * @param visible Whether the widget should be visible
1674
+ */
1675
+ withVisibility(visible) {
1676
+ if (!this._schema.interface.options) {
1677
+ this._schema.interface.options = {};
1678
+ }
1679
+ this._schema.interface.options['visible'] = visible;
1680
+ return this;
1681
+ }
1682
+ /**
1683
+ * Set the readonly state of the widget
1684
+ * @param isReadonly Whether the widget should be readonly
1685
+ */
1686
+ readonly(isReadonly = true) {
1687
+ if (!this._schema.interface.options) {
1688
+ this._schema.interface.options = {};
1689
+ }
1690
+ this._schema.interface.options['readonly'] = isReadonly;
1691
+ return this;
1692
+ }
1693
+ }
1694
+ //#endregion
1695
+ //#region ---- Builder-Based Middleware Types ----
1696
+
1697
+ //#endregion
1698
+ //#region ---- Schema Registry Service ----
1699
+ /**
1700
+ * Central registry for managing schema definitions, middleware, and dynamic loading.
1701
+ *
1702
+ * Provides:
1703
+ * - Schema registration and retrieval
1704
+ * - Middleware processing pipeline
1705
+ * - On-demand schema loading
1706
+ * - Caching and performance optimization
1707
+ */
1708
+ class AXPSchemaRegistry {
1709
+ constructor() {
1710
+ this._schemas = new Map();
1711
+ this._globalMiddleware = [];
1712
+ this._modelCache = new Map();
1713
+ this._loaders = null;
1714
+ }
1715
+ //#region ---- Registration Methods ----
1716
+ /**
1717
+ * Register a schema definition with optional metadata and middleware
1718
+ */
1719
+ register(definition, options = {}) {
1720
+ if (!definition.name || definition.name.trim() === '') {
1721
+ throw new Error('Schema name is required and cannot be empty');
1722
+ }
1723
+ const registered = {
1724
+ name: definition.name,
1725
+ definition,
1726
+ options,
1727
+ registeredAt: new Date()
1728
+ };
1729
+ this._schemas.set(definition.name, registered);
1730
+ this.invalidateCache(definition.name);
1731
+ console.log(`Schema '${definition.name}' registered successfully`);
1732
+ }
1733
+ /**
1734
+ * Register multiple schemas at once for batch operations
1735
+ */
1736
+ registerBatch(schemas) {
1737
+ for (const schema of schemas) {
1738
+ this.register(schema.definition, schema.options || {});
1739
+ }
1740
+ }
1741
+ /**
1742
+ * Remove a schema from the registry
1743
+ */
1744
+ unregister(name) {
1745
+ const removed = this._schemas.delete(name);
1746
+ if (removed) {
1747
+ this.invalidateCache(name);
1748
+ }
1749
+ return removed;
1750
+ }
1751
+ /**
1752
+ * Check if a schema is currently registered
1753
+ */
1754
+ isRegistered(name) {
1755
+ return this._schemas.has(name);
1756
+ }
1757
+ //#endregion
1758
+ //#region ---- Resolution Methods ----
1759
+ /**
1760
+ * Resolve a schema by name with full middleware processing and caching.
1761
+ * Supports on-demand loading if schema is not registered.
1762
+ */
1763
+ async resolve(name) {
1764
+ // Check cache first for performance
1765
+ if (this._modelCache.has(name)) {
1766
+ return this._modelCache.get(name);
1767
+ }
1768
+ // Try to get from registered schemas first
1769
+ let registered = this._schemas.get(name);
1770
+ // If not found, attempt on-demand loading
1771
+ if (!registered) {
1772
+ const definition = await this.loadFromLoaders(name);
1773
+ if (definition) {
1774
+ registered = {
1775
+ name,
1776
+ definition,
1777
+ options: {},
1778
+ registeredAt: new Date()
1779
+ };
1780
+ this._schemas.set(name, registered);
1781
+ }
1782
+ else {
1783
+ throw new Error(`Schema '${name}' is not registered and no loader can provide it`);
1784
+ }
1785
+ }
1786
+ // Clone and process through middleware pipeline
1787
+ const schema = this.cloneDefinition(registered.definition);
1788
+ const context = new AXPSchemaMiddlewareContext(schema);
1789
+ // Apply global middleware first
1790
+ for (const middleware of this._globalMiddleware) {
1791
+ await middleware(context);
1792
+ }
1793
+ // Apply schema-specific middleware
1794
+ if (registered.options.middleware) {
1795
+ for (const middleware of registered.options.middleware) {
1796
+ await middleware(context);
1797
+ }
1798
+ }
1799
+ // Create final model and cache it
1800
+ const model = new AXPSchemaModel(context.schema);
1801
+ this._modelCache.set(name, model);
1802
+ return model;
1803
+ }
1804
+ /**
1805
+ * Synchronous resolution without middleware processing.
1806
+ * Use only when middleware is not needed for performance.
1807
+ */
1808
+ resolveSync(name) {
1809
+ const registered = this._schemas.get(name);
1810
+ if (!registered) {
1811
+ throw new Error(`Schema '${name}' is not registered`);
1812
+ }
1813
+ return new AXPSchemaModel(this.cloneDefinition(registered.definition));
1814
+ }
1815
+ //#endregion
1816
+ //#region ---- Middleware Management ----
1817
+ /**
1818
+ * Add global middleware that applies to all schema resolutions
1819
+ */
1820
+ addGlobalMiddleware(middleware) {
1821
+ if (typeof middleware !== 'function') {
1822
+ throw new Error('Middleware must be a function');
1823
+ }
1824
+ this._globalMiddleware.push(middleware);
1825
+ }
1826
+ /**
1827
+ * Remove specific global middleware
1828
+ */
1829
+ removeGlobalMiddleware(middleware) {
1830
+ const index = this._globalMiddleware.indexOf(middleware);
1831
+ if (index > -1) {
1832
+ this._globalMiddleware.splice(index, 1);
1833
+ return true;
1834
+ }
1835
+ return false;
1836
+ }
1837
+ /**
1838
+ * Clear all global middleware
1839
+ */
1840
+ clearGlobalMiddleware() {
1841
+ this._globalMiddleware.length = 0;
1842
+ }
1843
+ //#endregion
1844
+ //#region ---- Loader Management ----
1845
+ /**
1846
+ * Add a schema loader for on-demand loading
1847
+ */
1848
+ addLoader(loader) {
1849
+ if (this._loaders === null) {
1850
+ this._loaders = [];
1851
+ }
1852
+ this._loaders.push(new loader());
1853
+ }
1854
+ //#endregion
1855
+ //#region ---- Query Methods ----
1856
+ /**
1857
+ * Get all registered schema names
1858
+ */
1859
+ getRegisteredNames() {
1860
+ return Array.from(this._schemas.keys());
1861
+ }
1862
+ /**
1863
+ * Get detailed registration information for a schema
1864
+ */
1865
+ getSchemaInfo(name) {
1866
+ return this._schemas.get(name);
1867
+ }
1868
+ /**
1869
+ * Get all registered schemas with their metadata
1870
+ */
1871
+ getAllSchemas() {
1872
+ return Array.from(this._schemas.values());
1873
+ }
1874
+ /**
1875
+ * Find schemas by tag for categorization
1876
+ */
1877
+ findByTag(tag) {
1878
+ return Array.from(this._schemas.values()).filter(schema => schema.options.tags?.includes(tag));
1879
+ }
1880
+ /**
1881
+ * Find schemas by widget type for widget-specific operations
1882
+ */
1883
+ findByWidget(widgetType) {
1884
+ return Array.from(this._schemas.values()).filter(schema => schema.definition.interface.widget === widgetType);
1885
+ }
1886
+ /**
1887
+ * Get comprehensive registry statistics
1888
+ */
1889
+ getStatistics() {
1890
+ const schemasByWidget = {};
1891
+ const schemasByTag = {};
1892
+ for (const schema of this._schemas.values()) {
1893
+ const widget = schema.definition.interface.widget;
1894
+ schemasByWidget[widget] = (schemasByWidget[widget] || 0) + 1;
1895
+ if (schema.options.tags) {
1896
+ for (const tag of schema.options.tags) {
1897
+ schemasByTag[tag] = (schemasByTag[tag] || 0) + 1;
1898
+ }
1899
+ }
1900
+ }
1901
+ return {
1902
+ schemaCount: this._schemas.size,
1903
+ globalMiddlewareCount: this._globalMiddleware.length,
1904
+ schemasByWidget,
1905
+ schemasByTag
1906
+ };
1907
+ }
1908
+ //#endregion
1909
+ //#region ---- Cache Management ----
1910
+ /**
1911
+ * Clear all cached models (useful when schemas need to be reloaded)
1912
+ */
1913
+ clearCache() {
1914
+ this._modelCache.clear();
1915
+ }
1916
+ /**
1917
+ * Invalidate cache for a specific schema
1918
+ */
1919
+ invalidateCache(name) {
1920
+ this._modelCache.delete(name);
1921
+ }
1922
+ /**
1923
+ * Clear all registered schemas, middleware, and cached models
1924
+ */
1925
+ clear() {
1926
+ this._schemas.clear();
1927
+ this._globalMiddleware.length = 0;
1928
+ this._modelCache.clear();
1929
+ this._loaders = null;
1930
+ }
1931
+ //#endregion
1932
+ //#region ---- Private Helper Methods ----
1933
+ /**
1934
+ * Attempt to load schema from registered loaders
1935
+ */
1936
+ async loadFromLoaders(name) {
1937
+ const loaders = this.getLoaders();
1938
+ for (const loader of loaders) {
1939
+ if (loader.canLoad(name)) {
1940
+ try {
1941
+ const definition = await loader.load(name);
1942
+ if (definition) {
1943
+ console.log(`Schema '${name}' loaded from ${loader.constructor.name}`);
1944
+ return definition;
1945
+ }
1946
+ }
1947
+ catch (error) {
1948
+ console.warn(`Loader ${loader.constructor.name} failed to load '${name}':`, error);
1949
+ }
1950
+ }
1951
+ }
1952
+ return null;
1953
+ }
1954
+ /**
1955
+ * Get loaders sorted by priority (lazy initialization)
1956
+ */
1957
+ getLoaders() {
1958
+ if (this._loaders === null) {
1959
+ try {
1960
+ this._loaders = [];
1961
+ // Sort by priority (higher priority first)
1962
+ this._loaders.sort((a, b) => {
1963
+ const priorityA = a.priority ?? 0;
1964
+ const priorityB = b.priority ?? 0;
1965
+ return priorityB - priorityA;
1966
+ });
1967
+ }
1968
+ catch (error) {
1969
+ console.warn('Failed to initialize schema loaders:', error);
1970
+ this._loaders = [];
1971
+ }
1972
+ }
1973
+ return this._loaders;
1974
+ }
1975
+ /**
1976
+ * Create a deep clone of a schema definition to prevent mutations
1977
+ */
1978
+ cloneDefinition(definition) {
1979
+ return JSON.parse(JSON.stringify(definition));
1980
+ }
1981
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.0.6", ngImport: i0, type: AXPSchemaRegistry, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
1982
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.0.6", ngImport: i0, type: AXPSchemaRegistry, providedIn: 'root' }); }
1983
+ }
1984
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.6", ngImport: i0, type: AXPSchemaRegistry, decorators: [{
1985
+ type: Injectable,
1986
+ args: [{ providedIn: 'root' }]
1987
+ }], ctorParameters: () => [] });
1988
+
1989
+ //#region ---- Schema Service ----
1990
+ /**
1991
+ * High-level facade service for schema operations.
1992
+ *
1993
+ * Provides a simplified interface to the schema registry with additional
1994
+ * business logic and convenience methods for common operations.
1995
+ */
1996
+ class AXPSchemaService {
1997
+ constructor() {
1998
+ this.registry = inject(AXPSchemaRegistry);
1999
+ }
2000
+ //#region ---- Core Schema Management ----
2001
+ /**
2002
+ * Register a schema with optional configuration
2003
+ */
2004
+ register(definition, options) {
2005
+ this.registry.register(definition, options);
2006
+ }
2007
+ /**
2008
+ * Register multiple schemas at once
2009
+ */
2010
+ registerBatch(schemas) {
2011
+ this.registry.registerBatch(schemas);
2012
+ }
2013
+ /**
2014
+ * Remove a schema from the registry
2015
+ */
2016
+ unregister(name) {
2017
+ return this.registry.unregister(name);
2018
+ }
2019
+ /**
2020
+ * Check if a schema is registered
2021
+ */
2022
+ isRegistered(name) {
2023
+ return this.registry.isRegistered(name);
2024
+ }
2025
+ /**
2026
+ * Get all registered schema names
2027
+ */
2028
+ getRegisteredNames() {
2029
+ return this.registry.getRegisteredNames();
2030
+ }
2031
+ /**
2032
+ * Clear all schemas and reset the registry
2033
+ */
2034
+ clear() {
2035
+ this.registry.clear();
2036
+ }
2037
+ //#endregion
2038
+ //#region ---- Schema Resolution ----
2039
+ /**
2040
+ * Resolve a schema with full middleware processing
2041
+ */
2042
+ async resolve(name) {
2043
+ return this.registry.resolve(name);
2044
+ }
2045
+ /**
2046
+ * Resolve schema synchronously without middleware (for performance)
2047
+ */
2048
+ resolveSync(name) {
2049
+ return this.registry.resolveSync(name);
2050
+ }
2051
+ /**
2052
+ * Resolve multiple schemas for form building and batch operations
2053
+ */
2054
+ async resolveMultiple(fieldConfigs) {
2055
+ const resolvedFields = await Promise.all(fieldConfigs.map(async (config) => ({
2056
+ name: config.name,
2057
+ schema: await this.resolve(config.schemaName)
2058
+ })));
2059
+ return resolvedFields;
2060
+ }
2061
+ //#endregion
2062
+ //#region ---- Middleware Management ----
2063
+ /**
2064
+ * Add global middleware that applies to all schema resolutions
2065
+ */
2066
+ addGlobalMiddleware(middleware) {
2067
+ this.registry.addGlobalMiddleware(middleware);
2068
+ }
2069
+ /**
2070
+ * Remove specific global middleware
2071
+ */
2072
+ removeGlobalMiddleware(middleware) {
2073
+ return this.registry.removeGlobalMiddleware(middleware);
2074
+ }
2075
+ /**
2076
+ * Clear all global middleware
2077
+ */
2078
+ clearGlobalMiddleware() {
2079
+ this.registry.clearGlobalMiddleware();
2080
+ }
2081
+ //#endregion
2082
+ //#region ---- Query and Discovery ----
2083
+ /**
2084
+ * Get detailed information about a registered schema
2085
+ */
2086
+ getSchemaInfo(name) {
2087
+ return this.registry.getSchemaInfo(name);
2088
+ }
2089
+ /**
2090
+ * Get all registered schemas with their metadata
2091
+ */
2092
+ getAllSchemas() {
2093
+ return this.registry.getAllSchemas();
2094
+ }
2095
+ /**
2096
+ * Find schemas by tag for categorization and grouping
2097
+ */
2098
+ findByTag(tag) {
2099
+ return this.registry.findByTag(tag);
2100
+ }
2101
+ /**
2102
+ * Find schemas by widget type for widget-specific operations
2103
+ */
2104
+ findByWidget(widgetType) {
2105
+ return this.registry.findByWidget(widgetType);
2106
+ }
2107
+ /**
2108
+ * Get comprehensive registry statistics and analytics
2109
+ */
2110
+ getStatistics() {
2111
+ const stats = this.registry.getStatistics();
2112
+ // Enhance with top-used analytics
2113
+ const mostUsedWidgets = Object.entries(stats.schemasByWidget)
2114
+ .sort(([, a], [, b]) => b - a)
2115
+ .slice(0, 5)
2116
+ .map(([widget]) => widget);
2117
+ const mostUsedTags = Object.entries(stats.schemasByTag)
2118
+ .sort(([, a], [, b]) => b - a)
2119
+ .slice(0, 5)
2120
+ .map(([tag]) => tag);
2121
+ return {
2122
+ ...stats,
2123
+ mostUsedWidgets,
2124
+ mostUsedTags
2125
+ };
2126
+ }
2127
+ //#endregion
2128
+ //#region ---- Validation and Analysis ----
2129
+ /**
2130
+ * Validate that all referenced schemas exist in the registry
2131
+ */
2132
+ validateSchemaReferences(schemaNames) {
2133
+ const missingSchemas = [];
2134
+ for (const schemaName of schemaNames) {
2135
+ if (!this.isRegistered(schemaName)) {
2136
+ missingSchemas.push(schemaName);
2137
+ }
2138
+ }
2139
+ return {
2140
+ valid: missingSchemas.length === 0,
2141
+ missingSchemas
2142
+ };
2143
+ }
2144
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.0.6", ngImport: i0, type: AXPSchemaService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
2145
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.0.6", ngImport: i0, type: AXPSchemaService, providedIn: 'root' }); }
2146
+ }
2147
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.6", ngImport: i0, type: AXPSchemaService, decorators: [{
2148
+ type: Injectable,
2149
+ args: [{ providedIn: 'root' }]
2150
+ }] });
2151
+
2152
+ //#endregion
2153
+
2154
+ //#endregion
2155
+ //#region ---- Provider Functions ----
2156
+ /**
2157
+ * Provide schema loaders for on-demand schema loading.
2158
+ *
2159
+ * Schema loaders enable the registry to load schemas that are not registered
2160
+ * at build time. This is useful for:
2161
+ * - Loading schemas from external APIs
2162
+ * - Dynamic schema generation
2163
+ * - Lazy loading of large schema sets
2164
+ * - Development-time schema hot-reloading
2165
+ *
2166
+ * @param loaders Array of loader classes or loader configurations
2167
+ * @returns Environment providers for dependency injection
2168
+ *
2169
+ * @example
2170
+ * ```typescript
2171
+ * // Simple loader registration
2172
+ * provideSchemaLoaders([
2173
+ * HttpSchemaLoader,
2174
+ * FileSystemSchemaLoader
2175
+ * ])
2176
+ *
2177
+ * // With priority configuration
2178
+ * provideSchemaLoaders([
2179
+ * { loader: HttpSchemaLoader, priority: 10 },
2180
+ * { loader: FileSystemSchemaLoader, priority: 5 }
2181
+ * ])
2182
+ * ```
2183
+ */
2184
+ function provideSchemaLoaders(loaders) {
2185
+ return makeEnvironmentProviders([
2186
+ {
2187
+ provide: AXP_SCHEMA_LOADER_SETUP,
2188
+ useFactory: async () => {
2189
+ const registry = inject(AXPSchemaRegistry);
2190
+ // Register each loader with the registry
2191
+ for (const loader of loaders) {
2192
+ const loaderClass = typeof loader === 'function' ? loader : loader.loader;
2193
+ registry.addLoader(loaderClass);
2194
+ }
2195
+ return true;
2196
+ },
2197
+ multi: true
2198
+ }
2199
+ ]);
2200
+ }
2201
+ //#endregion
2202
+
2203
+ //#endregion
2204
+ //#region ---- Provider Functions ----
2205
+ /**
2206
+ * Provide schema setups for registration during application bootstrap.
2207
+ *
2208
+ * This is the primary way to register schemas that are known at build time.
2209
+ * Schemas registered this way are immediately available in the registry.
2210
+ *
2211
+ * @param schemas Array of schema entries to register
2212
+ * @returns Environment providers for dependency injection
2213
+ *
2214
+ * @example
2215
+ * ```typescript
2216
+ * provideSchemaSetups([
2217
+ * {
2218
+ * definition: emailSchema,
2219
+ * options: {
2220
+ * tags: ['user', 'contact'],
2221
+ * description: 'Email field schema'
2222
+ * }
2223
+ * },
2224
+ * {
2225
+ * definition: phoneSchema,
2226
+ * options: { tags: ['contact'] }
2227
+ * }
2228
+ * ])
2229
+ * ```
2230
+ */
2231
+ function provideSchemaSetups(schemas) {
2232
+ return makeEnvironmentProviders([
2233
+ {
2234
+ provide: AXP_SCHEMA_SETUP,
2235
+ useFactory: () => {
2236
+ const registry = inject(AXPSchemaRegistry);
2237
+ // Register all schemas with their options
2238
+ for (const schema of schemas) {
2239
+ registry.register(schema.definition, schema.options);
2240
+ }
2241
+ return true;
2242
+ },
2243
+ multi: true
2244
+ }
2245
+ ]);
2246
+ }
2247
+ /**
2248
+ * Convenience function to provide a single schema setup.
2249
+ *
2250
+ * Useful when you need to register just one schema or want to keep
2251
+ * schema registrations separate for organizational purposes.
2252
+ *
2253
+ * @param definition The schema definition to register
2254
+ * @param options Optional registration options and metadata
2255
+ * @returns Environment providers for dependency injection
2256
+ *
2257
+ * @example
2258
+ * ```typescript
2259
+ * provideSchema(emailSchema, {
2260
+ * tags: ['user', 'contact'],
2261
+ * description: 'User email field'
2262
+ * })
2263
+ * ```
2264
+ */
2265
+ function provideSchema(definition, options) {
2266
+ return provideSchemaSetups([{ definition, options }]);
2267
+ }
2268
+ /**
2269
+ * Provide schema setups from a factory function for dynamic registration.
2270
+ *
2271
+ * Useful when schemas need to be generated at runtime, loaded from external
2272
+ * sources, or depend on configuration that's not available at build time.
2273
+ *
2274
+ * @param schemaFactory Factory function that returns schema entries
2275
+ * @returns Environment providers for dependency injection
2276
+ *
2277
+ * @example
2278
+ * ```typescript
2279
+ * provideSchemasFromFactory(async () => {
2280
+ * const config = await loadConfiguration();
2281
+ * return config.schemas.map(schema => ({
2282
+ * definition: schema,
2283
+ * options: { tags: ['dynamic'] }
2284
+ * }));
2285
+ * })
2286
+ * ```
2287
+ */
2288
+ function provideSchemasFromFactory(schemaFactory) {
2289
+ return makeEnvironmentProviders([
2290
+ {
2291
+ provide: AXP_SCHEMA_SETUP,
2292
+ useFactory: async () => {
2293
+ const registry = inject(AXPSchemaRegistry);
2294
+ const schemas = await schemaFactory();
2295
+ // Register all factory-generated schemas
2296
+ for (const schema of schemas) {
2297
+ registry.register(schema.definition, schema.options);
2298
+ }
2299
+ return true;
2300
+ },
2301
+ multi: true
2302
+ }
2303
+ ]);
2304
+ }
2305
+ //#endregion
2306
+
2307
+ //#endregion
2308
+ //#region ---- Provider Functions ----
2309
+ /**
2310
+ * Provide schema middleware for registration in the application.
2311
+ *
2312
+ * Supports both global middleware (applies to all schemas) and targeted middleware
2313
+ * (applies only to schemas matching specific patterns).
2314
+ *
2315
+ * @param middleware Array of middleware entries to register
2316
+ * @returns Environment providers for dependency injection
2317
+ *
2318
+ * @example
2319
+ * ```typescript
2320
+ * // Global middleware
2321
+ * provideSchemaMiddleware([
2322
+ * (context) => {
2323
+ * if (context.schema.dataType === 'string') {
2324
+ * context.searchable(true);
2325
+ * }
2326
+ * }
2327
+ * ])
2328
+ *
2329
+ * // Targeted middleware
2330
+ * provideSchemaMiddleware([
2331
+ * {
2332
+ * target: /^user_/,
2333
+ * middleware: (context) => context.withMetadata({ category: 'user' })
2334
+ * }
2335
+ * ])
2336
+ * ```
2337
+ */
2338
+ function provideSchemaMiddleware(middleware) {
2339
+ const global = [];
2340
+ const targeted = [];
2341
+ // Separate global and targeted middleware for different processing
2342
+ for (const entry of middleware) {
2343
+ if (typeof entry === 'function') {
2344
+ global.push(entry);
2345
+ }
2346
+ else {
2347
+ targeted.push(entry);
2348
+ }
2349
+ }
2350
+ return makeEnvironmentProviders([
2351
+ // Setup global middleware that applies to all schemas
2352
+ ...(global.length > 0 ? [{
2353
+ provide: AXP_SCHEMA_MIDDLEWARE_SETUP,
2354
+ useFactory: () => {
2355
+ const registry = inject(AXPSchemaRegistry);
2356
+ for (const mw of global) {
2357
+ registry.addGlobalMiddleware(mw);
2358
+ }
2359
+ return true;
2360
+ },
2361
+ multi: true
2362
+ }] : []),
2363
+ // Register targeted middleware entries for future extension support
2364
+ ...targeted.map(entry => ({
2365
+ provide: AXP_SCHEMA_EXTENSION,
2366
+ useValue: entry,
2367
+ multi: true
2368
+ }))
2369
+ ]);
2370
+ }
2371
+ //#endregion
2372
+
2373
+ //#region ---- Core Schema Registry ----
2374
+ // Core registry and service classes
2375
+ //#endregion
2376
+
2377
+ //#region ---- Domain Middleware Context ----
2378
+ /**
2379
+ * Context class for domain middleware operations providing a fluent API for domain definition manipulation.
2380
+ *
2381
+ * This class serves as the interface between middleware functions and domain definitions,
2382
+ * offering methods to modify various aspects of a domain definition including:
2383
+ * - Metadata and custom properties
2384
+ * - Validation rules
2385
+ * - Feature flags and configuration
2386
+ * - Transformations and augmentations
2387
+ *
2388
+ * All methods return `this` to enable fluent method chaining.
2389
+ */
2390
+ class AXPDomainMiddlewareContext {
2391
+ constructor(definition, type) {
2392
+ // Deep clone to avoid mutating the original definition
2393
+ this._definition = JSON.parse(JSON.stringify(definition));
2394
+ this._type = type;
2395
+ }
2396
+ /**
2397
+ * Get the current definition (read-only access)
2398
+ */
2399
+ get definition() {
2400
+ return this._definition;
2401
+ }
2402
+ /**
2403
+ * Get the type of domain object being processed
2404
+ */
2405
+ get type() {
2406
+ return this._type;
2407
+ }
2408
+ /**
2409
+ * Set metadata for the domain definition
2410
+ */
2411
+ setMetadata(key, value) {
2412
+ const def = this._definition;
2413
+ if (!def.metadata) {
2414
+ def.metadata = {};
2415
+ }
2416
+ def.metadata[key] = value;
2417
+ return this;
2418
+ }
2419
+ /**
2420
+ * Get metadata value
2421
+ */
2422
+ getMetadata(key) {
2423
+ const def = this._definition;
2424
+ return def.metadata?.[key];
2425
+ }
2426
+ /**
2427
+ * Add validation rule to the definition (for entities and aggregates)
2428
+ */
2429
+ addValidation(rule) {
2430
+ if ('validations' in this._definition) {
2431
+ this._definition.validations = this._definition.validations || [];
2432
+ this._definition.validations.push(rule);
2433
+ }
2434
+ return this;
2435
+ }
2436
+ /**
2437
+ * Transform fields (for entities)
2438
+ */
2439
+ transformFields(transformer) {
2440
+ if ('fields' in this._definition && this._definition.fields) {
2441
+ this._definition.fields = this._definition.fields.map(transformer);
2442
+ }
2443
+ return this;
2444
+ }
2445
+ /**
2446
+ * Add field to entity definition
2447
+ */
2448
+ addField(field) {
2449
+ if ('fields' in this._definition) {
2450
+ this._definition.fields = this._definition.fields || [];
2451
+ this._definition.fields.push(field);
2452
+ }
2453
+ return this;
2454
+ }
2455
+ /**
2456
+ * Set title with transformation
2457
+ */
2458
+ setTitle(title) {
2459
+ this._definition.title = title;
2460
+ return this;
2461
+ }
2462
+ /**
2463
+ * Apply conditional logic
2464
+ */
2465
+ when(condition, callback) {
2466
+ if (condition) {
2467
+ callback(this);
2468
+ }
2469
+ return this;
2470
+ }
2471
+ /**
2472
+ * Replace the entire definition
2473
+ */
2474
+ replaceDefinition(newDefinition) {
2475
+ this._definition = JSON.parse(JSON.stringify(newDefinition));
2476
+ return this;
2477
+ }
2478
+ }
2479
+ //#endregion
2480
+
2481
+ //#region ---- Domain Registry Service ----
2482
+ /**
2483
+ * Central registry for managing domain definitions, middleware, and dynamic loading.
2484
+ *
2485
+ * Provides:
2486
+ * - Path-based domain resolution (module.aggregate.entity)
2487
+ * - Definition-level caching with fresh model creation
2488
+ * - Type-specific middleware processing
2489
+ * - On-demand domain loading with first-wins strategy
2490
+ * - Model creation and dependency injection
2491
+ */
2492
+ class AXPDomainRegistry {
2493
+ constructor() {
2494
+ // Cache definitions (before middleware), not models
2495
+ this._definitionCache = new Map();
2496
+ // Type-specific middleware collections
2497
+ this._moduleMiddleware = [];
2498
+ this._aggregateMiddleware = [];
2499
+ this._entityMiddleware = [];
2500
+ // Registered loaders for on-demand loading
2501
+ this._loaders = [];
2502
+ // Injected dependencies
2503
+ this.schemaService = inject(AXPSchemaService);
2504
+ }
2505
+ //#region ---- Main Resolution Method ----
2506
+ /**
2507
+ * Resolve a domain object by path with full middleware processing.
2508
+ * Supports definition-level caching with fresh model creation.
2509
+ *
2510
+ * @param path Domain path (e.g., "user-management.user-aggregate.user")
2511
+ * @returns Promise that resolves to the domain model
2512
+ */
2513
+ async resolve(path) {
2514
+ const pathInfo = this.parsePath(path);
2515
+ // Check definition cache first
2516
+ let definition = this._definitionCache.get(path);
2517
+ if (!definition) {
2518
+ // Load from first available loader
2519
+ definition = await this.loadFromLoaders(path, pathInfo.type);
2520
+ if (!definition) {
2521
+ throw new Error(`Cannot resolve domain path: ${path}`);
2522
+ }
2523
+ // Cache the raw definition
2524
+ this._definitionCache.set(path, definition);
2525
+ }
2526
+ // Apply type-specific middleware (creates new processed definition)
2527
+ const processedDefinition = await this.applyTypeMiddleware(definition, pathInfo.type, path);
2528
+ // Create and return fresh model instance (not cached)
2529
+ return this.createModel(processedDefinition, pathInfo);
2530
+ }
2531
+ //#endregion
2532
+ //#region ---- Path Parsing ----
2533
+ /**
2534
+ * Parse domain path string into structured information
2535
+ *
2536
+ * @param path Domain path to parse
2537
+ * @returns Parsed path information
2538
+ */
2539
+ parsePath(path) {
2540
+ const parts = path.split('.');
2541
+ if (parts.length === 1) {
2542
+ return {
2543
+ module: parts[0],
2544
+ type: 'module',
2545
+ fullPath: path
2546
+ };
2547
+ }
2548
+ else if (parts.length === 2) {
2549
+ return {
2550
+ module: parts[0],
2551
+ aggregate: parts[1],
2552
+ type: 'aggregate',
2553
+ fullPath: path
2554
+ };
2555
+ }
2556
+ else if (parts.length === 3) {
2557
+ return {
2558
+ module: parts[0],
2559
+ aggregate: parts[1],
2560
+ entity: parts[2],
2561
+ type: 'entity',
2562
+ fullPath: path
2563
+ };
2564
+ }
2565
+ throw new Error(`Invalid domain path format: ${path}. Expected: module, module.aggregate, or module.aggregate.entity`);
2566
+ }
2567
+ //#endregion
2568
+ //#region ---- Loader Management ----
2569
+ /**
2570
+ * Register a domain loader for on-demand loading
2571
+ *
2572
+ * @param loader The loader instance to register
2573
+ */
2574
+ addLoader(loader) {
2575
+ this._loaders.push(loader);
2576
+ // Sort by priority (highest first) after adding
2577
+ this._loaders.sort((a, b) => (b.priority ?? 0) - (a.priority ?? 0));
2578
+ }
2579
+ /**
2580
+ * Load definition from registered loaders using first-wins strategy
2581
+ *
2582
+ * @param path Domain path to load
2583
+ * @param type Type of domain object
2584
+ * @returns Promise that resolves to definition or undefined
2585
+ */
2586
+ async loadFromLoaders(path, type) {
2587
+ for (const loader of this._loaders) {
2588
+ if (loader.canLoad(path, type)) {
2589
+ try {
2590
+ const definition = await loader.load(path, type);
2591
+ if (definition) {
2592
+ console.log(`✓ Loaded ${path} from ${loader.constructor.name}`);
2593
+ return definition; // Return first successful result
2594
+ }
2595
+ }
2596
+ catch (error) {
2597
+ console.warn(`⚠ Loader ${loader.constructor.name} failed for ${path}:`, error);
2598
+ // Continue to next loader instead of throwing
2599
+ }
2600
+ }
2601
+ }
2602
+ return undefined; // No loader could provide the definition
2603
+ }
2604
+ //#endregion
2605
+ //#region ---- Middleware Management ----
2606
+ /**
2607
+ * Add middleware for module processing
2608
+ */
2609
+ addModuleMiddleware(middleware) {
2610
+ this._moduleMiddleware.push(middleware);
2611
+ }
2612
+ /**
2613
+ * Add middleware for aggregate processing
2614
+ */
2615
+ addAggregateMiddleware(middleware) {
2616
+ this._aggregateMiddleware.push(middleware);
2617
+ }
2618
+ /**
2619
+ * Add middleware for entity processing
2620
+ */
2621
+ addEntityMiddleware(middleware) {
2622
+ this._entityMiddleware.push(middleware);
2623
+ }
2624
+ /**
2625
+ * Apply type-specific middleware to definition
2626
+ *
2627
+ * @param definition Raw definition from cache or loader
2628
+ * @param type Type of domain object
2629
+ * @param path Original path for context
2630
+ * @returns Processed definition
2631
+ */
2632
+ async applyTypeMiddleware(definition, type, path) {
2633
+ const middleware = this.getMiddlewareForType(type);
2634
+ if (middleware.length === 0) {
2635
+ return definition; // No middleware to apply
2636
+ }
2637
+ const context = new AXPDomainMiddlewareContext(definition, type);
2638
+ // Apply all middleware for this type
2639
+ for (const mw of middleware) {
2640
+ await mw(context);
2641
+ }
2642
+ return context.definition;
2643
+ }
2644
+ /**
2645
+ * Get middleware collection for specific type
2646
+ *
2647
+ * @param type Domain object type
2648
+ * @returns Array of middleware functions
2649
+ */
2650
+ getMiddlewareForType(type) {
2651
+ switch (type) {
2652
+ case 'module': return this._moduleMiddleware;
2653
+ case 'aggregate': return this._aggregateMiddleware;
2654
+ case 'entity': return this._entityMiddleware;
2655
+ default: return [];
2656
+ }
2657
+ }
2658
+ //#endregion
2659
+ //#region ---- Model Creation ----
2660
+ /**
2661
+ * Create domain model from processed definition
2662
+ *
2663
+ * @param definition Processed definition (after middleware)
2664
+ * @param pathInfo Parsed path information
2665
+ * @returns Created domain model
2666
+ */
2667
+ createModel(definition, pathInfo) {
2668
+ switch (pathInfo.type) {
2669
+ case 'module':
2670
+ return new AXPModuleModel(definition);
2671
+ case 'aggregate':
2672
+ // For aggregate, we need to resolve parent module first
2673
+ // This will be simplified when we refactor the models
2674
+ const moduleDefinition = {
2675
+ name: pathInfo.module,
2676
+ title: pathInfo.module,
2677
+ aggregates: [definition]
2678
+ };
2679
+ const parentModule = new AXPModuleModel(moduleDefinition);
2680
+ return new AXPAggregateModel(definition, parentModule);
2681
+ case 'entity':
2682
+ // For entity, we need both module and aggregate parents
2683
+ // This will be simplified when we refactor the models
2684
+ const entityAggregateDefinition = {
2685
+ name: pathInfo.aggregate,
2686
+ title: pathInfo.aggregate || '',
2687
+ entities: [definition],
2688
+ relations: [],
2689
+ validations: [],
2690
+ actions: []
2691
+ };
2692
+ const entityModuleDefinition = {
2693
+ name: pathInfo.module,
2694
+ title: pathInfo.module,
2695
+ aggregates: [entityAggregateDefinition]
2696
+ };
2697
+ const entityModule = new AXPModuleModel(entityModuleDefinition);
2698
+ const entityAggregate = new AXPAggregateModel(entityAggregateDefinition, entityModule);
2699
+ return new AXPEntityModel(definition, entityAggregate, this.schemaService);
2700
+ default:
2701
+ throw new Error(`Unknown domain type: ${pathInfo.type}`);
2702
+ }
2703
+ }
2704
+ //#endregion
2705
+ //#region ---- Cache Management ----
2706
+ /**
2707
+ * Clear definition cache for a specific path
2708
+ *
2709
+ * @param path Path to clear from cache
2710
+ */
2711
+ invalidateCache(path) {
2712
+ this._definitionCache.delete(path);
2713
+ }
2714
+ /**
2715
+ * Clear all cached definitions
2716
+ */
2717
+ clearCache() {
2718
+ this._definitionCache.clear();
2719
+ }
2720
+ /**
2721
+ * Get cache statistics
2722
+ */
2723
+ getCacheStats() {
2724
+ return {
2725
+ size: this._definitionCache.size,
2726
+ paths: Array.from(this._definitionCache.keys())
2727
+ };
2728
+ }
2729
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.0.6", ngImport: i0, type: AXPDomainRegistry, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
2730
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.0.6", ngImport: i0, type: AXPDomainRegistry, providedIn: 'root' }); }
2731
+ }
2732
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.6", ngImport: i0, type: AXPDomainRegistry, decorators: [{
2733
+ type: Injectable,
2734
+ args: [{ providedIn: 'root' }]
2735
+ }] });
2736
+
2737
+ //#region ---- Domain Service ----
2738
+ /**
2739
+ * High-level facade service for domain operations.
2740
+ *
2741
+ * Provides simplified interfaces to the domain registry with additional
2742
+ * business logic and convenience methods for common operations.
2743
+ *
2744
+ * This service acts as the main entry point for domain model resolution
2745
+ * and provides a clean API for consuming applications.
2746
+ */
2747
+ class AXPDomainService {
2748
+ constructor() {
2749
+ // Injected dependencies
2750
+ this.registry = inject(AXPDomainRegistry);
2751
+ }
2752
+ //#region ---- Module Operations ----
2753
+ /**
2754
+ * Get module by name
2755
+ *
2756
+ * @param name Module name
2757
+ * @returns Promise that resolves to module model
2758
+ */
2759
+ async getModule(name) {
2760
+ return this.registry.resolve(name);
2761
+ }
2762
+ /**
2763
+ * Check if module exists
2764
+ *
2765
+ * @param name Module name
2766
+ * @returns Promise that resolves to boolean
2767
+ */
2768
+ async moduleExists(name) {
2769
+ try {
2770
+ await this.getModule(name);
2771
+ return true;
2772
+ }
2773
+ catch {
2774
+ return false;
2775
+ }
2776
+ }
2777
+ //#endregion
2778
+ //#region ---- Aggregate Operations ----
2779
+ /**
2780
+ * Get aggregate by module and aggregate names
2781
+ *
2782
+ * @param moduleName Module name
2783
+ * @param aggregateName Aggregate name
2784
+ * @returns Promise that resolves to aggregate model
2785
+ */
2786
+ async getAggregate(moduleName, aggregateName) {
2787
+ const path = `${moduleName}.${aggregateName}`;
2788
+ return this.registry.resolve(path);
2789
+ }
2790
+ /**
2791
+ * Get aggregate by path
2792
+ *
2793
+ * @param path Aggregate path (module.aggregate)
2794
+ * @returns Promise that resolves to aggregate model
2795
+ */
2796
+ async getAggregateByPath(path) {
2797
+ return this.registry.resolve(path);
2798
+ }
2799
+ /**
2800
+ * Check if aggregate exists
2801
+ *
2802
+ * @param moduleName Module name
2803
+ * @param aggregateName Aggregate name
2804
+ * @returns Promise that resolves to boolean
2805
+ */
2806
+ async aggregateExists(moduleName, aggregateName) {
2807
+ try {
2808
+ await this.getAggregate(moduleName, aggregateName);
2809
+ return true;
2810
+ }
2811
+ catch {
2812
+ return false;
2813
+ }
2814
+ }
2815
+ //#endregion
2816
+ //#region ---- Entity Operations ----
2817
+ /**
2818
+ * Get entity by full path
2819
+ *
2820
+ * @param path Full entity path (module.aggregate.entity)
2821
+ * @returns Promise that resolves to entity model
2822
+ */
2823
+ async getEntity(path) {
2824
+ return this.registry.resolve(path);
2825
+ }
2826
+ /**
2827
+ * Get entity by component parts
2828
+ *
2829
+ * @param moduleName Module name
2830
+ * @param aggregateName Aggregate name
2831
+ * @param entityName Entity name
2832
+ * @returns Promise that resolves to entity model
2833
+ */
2834
+ async getEntityByParts(moduleName, aggregateName, entityName) {
2835
+ const path = `${moduleName}.${aggregateName}.${entityName}`;
2836
+ return this.getEntity(path);
2837
+ }
2838
+ /**
2839
+ * Check if entity exists
2840
+ *
2841
+ * @param path Full entity path
2842
+ * @returns Promise that resolves to boolean
2843
+ */
2844
+ async entityExists(path) {
2845
+ try {
2846
+ await this.getEntity(path);
2847
+ return true;
2848
+ }
2849
+ catch {
2850
+ return false;
2851
+ }
2852
+ }
2853
+ //#endregion
2854
+ //#region ---- Batch Operations ----
2855
+ /**
2856
+ * Get multiple modules in parallel
2857
+ *
2858
+ * @param moduleNames Array of module names
2859
+ * @returns Promise that resolves to array of module models
2860
+ */
2861
+ async getModules(moduleNames) {
2862
+ return Promise.all(moduleNames.map(name => this.getModule(name)));
2863
+ }
2864
+ /**
2865
+ * Get multiple aggregates in parallel
2866
+ *
2867
+ * @param aggregatePaths Array of aggregate paths
2868
+ * @returns Promise that resolves to array of aggregate models
2869
+ */
2870
+ async getAggregates(aggregatePaths) {
2871
+ return Promise.all(aggregatePaths.map(path => this.getAggregateByPath(path)));
2872
+ }
2873
+ /**
2874
+ * Get multiple entities in parallel
2875
+ *
2876
+ * @param entityPaths Array of entity paths
2877
+ * @returns Promise that resolves to array of entity models
2878
+ */
2879
+ async getEntities(entityPaths) {
2880
+ return Promise.all(entityPaths.map(path => this.getEntity(path)));
2881
+ }
2882
+ //#endregion
2883
+ //#region ---- Search and Discovery ----
2884
+ /**
2885
+ * Find entities by name across all loaded modules
2886
+ *
2887
+ * @param entityName Entity name to search for
2888
+ * @returns Promise that resolves to array of matching entity paths
2889
+ */
2890
+ async findEntitiesByName(entityName) {
2891
+ // This would require additional registry functionality
2892
+ // For now, return empty array as placeholder
2893
+ return [];
2894
+ }
2895
+ /**
2896
+ * Get all aggregates for a module
2897
+ *
2898
+ * @param moduleName Module name
2899
+ * @returns Promise that resolves to array of aggregate models
2900
+ */
2901
+ async getModuleAggregates(moduleName) {
2902
+ const module = await this.getModule(moduleName);
2903
+ return module.getAllAggregates();
2904
+ }
2905
+ /**
2906
+ * Get all entity references for an aggregate
2907
+ *
2908
+ * @param moduleName Module name
2909
+ * @param aggregateName Aggregate name
2910
+ * @returns Promise that resolves to entity references map
2911
+ */
2912
+ async getAggregateEntityReferences(moduleName, aggregateName) {
2913
+ const aggregate = await this.getAggregate(moduleName, aggregateName);
2914
+ return aggregate.entityReferences;
2915
+ }
2916
+ //#endregion
2917
+ //#region ---- Validation Operations ----
2918
+ /**
2919
+ * Validate module and all its components
2920
+ *
2921
+ * @param moduleName Module name
2922
+ * @returns Promise that resolves to validation errors array
2923
+ */
2924
+ async validateModule(moduleName) {
2925
+ try {
2926
+ const module = await this.getModule(moduleName);
2927
+ return module.validate();
2928
+ }
2929
+ catch (error) {
2930
+ return [`Failed to load module '${moduleName}': ${error instanceof Error ? error.message : 'Unknown error'}`];
2931
+ }
2932
+ }
2933
+ /**
2934
+ * Validate aggregate and its components
2935
+ *
2936
+ * @param moduleName Module name
2937
+ * @param aggregateName Aggregate name
2938
+ * @returns Promise that resolves to validation errors array
2939
+ */
2940
+ async validateAggregate(moduleName, aggregateName) {
2941
+ try {
2942
+ const aggregate = await this.getAggregate(moduleName, aggregateName);
2943
+ return aggregate.validate();
2944
+ }
2945
+ catch (error) {
2946
+ return [`Failed to load aggregate '${moduleName}.${aggregateName}': ${error instanceof Error ? error.message : 'Unknown error'}`];
2947
+ }
2948
+ }
2949
+ //#endregion
2950
+ //#region ---- Utility Operations ----
2951
+ /**
2952
+ * Get statistics for a module
2953
+ *
2954
+ * @param moduleName Module name
2955
+ * @returns Promise that resolves to module statistics
2956
+ */
2957
+ async getModuleStatistics(moduleName) {
2958
+ const module = await this.getModule(moduleName);
2959
+ return module.getStatistics();
2960
+ }
2961
+ /**
2962
+ * Get statistics for an aggregate
2963
+ *
2964
+ * @param moduleName Module name
2965
+ * @param aggregateName Aggregate name
2966
+ * @returns Promise that resolves to aggregate statistics
2967
+ */
2968
+ async getAggregateStatistics(moduleName, aggregateName) {
2969
+ const aggregate = await this.getAggregate(moduleName, aggregateName);
2970
+ return aggregate.getStatistics();
2971
+ }
2972
+ /**
2973
+ * Clear registry cache
2974
+ */
2975
+ clearCache() {
2976
+ this.registry.clearCache();
2977
+ }
2978
+ /**
2979
+ * Get cache statistics
2980
+ *
2981
+ * @returns Cache statistics object
2982
+ */
2983
+ getCacheStatistics() {
2984
+ return this.registry.getCacheStats();
2985
+ }
2986
+ /**
2987
+ * Invalidate cache for specific path
2988
+ *
2989
+ * @param path Domain path to invalidate
2990
+ */
2991
+ invalidateCache(path) {
2992
+ this.registry.invalidateCache(path);
2993
+ }
2994
+ //#endregion
2995
+ //#region ---- Helper Methods ----
2996
+ /**
2997
+ * Parse domain path into components
2998
+ *
2999
+ * @param path Domain path to parse
3000
+ * @returns Parsed path components
3001
+ */
3002
+ parsePath(path) {
3003
+ const parts = path.split('.');
3004
+ if (parts.length === 1) {
3005
+ return { module: parts[0], type: 'module' };
3006
+ }
3007
+ else if (parts.length === 2) {
3008
+ return { module: parts[0], aggregate: parts[1], type: 'aggregate' };
3009
+ }
3010
+ else if (parts.length === 3) {
3011
+ return { module: parts[0], aggregate: parts[1], entity: parts[2], type: 'entity' };
3012
+ }
3013
+ throw new Error(`Invalid domain path format: ${path}`);
3014
+ }
3015
+ /**
3016
+ * Build path from components
3017
+ *
3018
+ * @param module Module name
3019
+ * @param aggregate Aggregate name (optional)
3020
+ * @param entity Entity name (optional)
3021
+ * @returns Built path string
3022
+ */
3023
+ buildPath(module, aggregate, entity) {
3024
+ if (entity && aggregate) {
3025
+ return `${module}.${aggregate}.${entity}`;
3026
+ }
3027
+ else if (aggregate) {
3028
+ return `${module}.${aggregate}`;
3029
+ }
3030
+ else {
3031
+ return module;
3032
+ }
3033
+ }
3034
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.0.6", ngImport: i0, type: AXPDomainService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
3035
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.0.6", ngImport: i0, type: AXPDomainService, providedIn: 'root' }); }
3036
+ }
3037
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.6", ngImport: i0, type: AXPDomainService, decorators: [{
3038
+ type: Injectable,
3039
+ args: [{ providedIn: 'root' }]
3040
+ }] });
3041
+
3042
+ //#endregion
3043
+
3044
+ //#endregion
3045
+ //#region ---- Provider Functions ----
3046
+ /**
3047
+ * Provide domain loaders for on-demand domain loading.
3048
+ *
3049
+ * Domain loaders enable the registry to load domain definitions that are not registered
3050
+ * at build time. This is useful for:
3051
+ * - Loading domain definitions from external APIs
3052
+ * - Dynamic domain generation
3053
+ * - Lazy loading of large domain sets
3054
+ * - Development-time domain hot-reloading
3055
+ *
3056
+ * @param loaders Array of loader classes, instances, or loader configurations
3057
+ * @returns Environment providers for dependency injection
3058
+ *
3059
+ * @example
3060
+ * ```typescript
3061
+ * // Simple loader registration
3062
+ * provideDomainLoaders([
3063
+ * HttpDomainLoader,
3064
+ * FileSystemDomainLoader,
3065
+ * new MemoryDomainLoader()
3066
+ * ])
3067
+ *
3068
+ * // With priority configuration
3069
+ * provideDomainLoaders([
3070
+ * { loader: HttpDomainLoader, priority: 10 },
3071
+ * { loader: FileSystemDomainLoader, priority: 5 },
3072
+ * { loader: new MemoryDomainLoader(), priority: 15 }
3073
+ * ])
3074
+ * ```
3075
+ */
3076
+ function provideDomainLoaders(loaders) {
3077
+ return makeEnvironmentProviders([
3078
+ {
3079
+ provide: AXP_DOMAIN_LOADER_SETUP,
3080
+ useFactory: async () => {
3081
+ const registry = inject(AXPDomainRegistry);
3082
+ if (!registry) {
3083
+ console.warn('Domain registry not available during loader setup');
3084
+ return false;
3085
+ }
3086
+ // Register each loader with the registry
3087
+ for (const loaderConfig of loaders) {
3088
+ try {
3089
+ let loaderInstance;
3090
+ let priority;
3091
+ if (typeof loaderConfig === 'function') {
3092
+ // Type<AXPDomainLoader>
3093
+ loaderInstance = new loaderConfig();
3094
+ priority = loaderInstance.priority;
3095
+ }
3096
+ else if (typeof loaderConfig === 'object' && 'canLoad' in loaderConfig) {
3097
+ // AXPDomainLoader instance
3098
+ loaderInstance = loaderConfig;
3099
+ priority = loaderInstance.priority;
3100
+ }
3101
+ else if (typeof loaderConfig === 'object' && 'loader' in loaderConfig) {
3102
+ // AXPDomainLoaderConfig
3103
+ if (typeof loaderConfig.loader === 'function') {
3104
+ loaderInstance = new loaderConfig.loader();
3105
+ }
3106
+ else {
3107
+ loaderInstance = loaderConfig.loader;
3108
+ }
3109
+ priority = loaderConfig.priority ?? loaderInstance.priority;
3110
+ }
3111
+ else {
3112
+ console.warn('Invalid loader configuration:', loaderConfig);
3113
+ continue;
3114
+ }
3115
+ // Apply custom priority if specified
3116
+ if (priority !== undefined && priority !== loaderInstance.priority) {
3117
+ loaderInstance.priority = priority;
3118
+ }
3119
+ registry.addLoader(loaderInstance);
3120
+ console.log(`✓ Registered domain loader: ${loaderInstance.constructor.name} (priority: ${loaderInstance.priority ?? 0})`);
3121
+ }
3122
+ catch (error) {
3123
+ console.error('Failed to register domain loader:', error);
3124
+ }
3125
+ }
3126
+ return true;
3127
+ },
3128
+ multi: true
3129
+ }
3130
+ ]);
3131
+ }
3132
+ /**
3133
+ * Provide a single domain loader for convenience
3134
+ *
3135
+ * @param loader Loader class, instance, or configuration
3136
+ * @returns Environment providers for dependency injection
3137
+ */
3138
+ function provideDomainLoader(loader) {
3139
+ return provideDomainLoaders([loader]);
3140
+ }
3141
+ //#endregion
3142
+
3143
+ //#region ---- Injection Tokens ----
3144
+ /**
3145
+ * Injection tokens for type-specific middleware setup
3146
+ */
3147
+ const AXP_MODULE_MIDDLEWARE_SETUP = 'AXP_MODULE_MIDDLEWARE_SETUP';
3148
+ const AXP_AGGREGATE_MIDDLEWARE_SETUP = 'AXP_AGGREGATE_MIDDLEWARE_SETUP';
3149
+ const AXP_ENTITY_MIDDLEWARE_SETUP = 'AXP_ENTITY_MIDDLEWARE_SETUP';
3150
+ //#endregion
3151
+ //#region ---- Provider Functions ----
3152
+ /**
3153
+ * Provide middleware for module processing.
3154
+ *
3155
+ * Module middleware is applied when resolving module definitions and can:
3156
+ * - Add metadata and custom properties
3157
+ * - Validate module structure
3158
+ * - Transform module definitions
3159
+ * - Add computed properties
3160
+ *
3161
+ * @param middleware Array of middleware functions to register
3162
+ * @returns Environment providers for dependency injection
3163
+ *
3164
+ * @example
3165
+ * ```typescript
3166
+ * provideModuleMiddleware([
3167
+ * (context) => {
3168
+ * // Add common module metadata
3169
+ * context.setMetadata('loadedAt', new Date());
3170
+ * context.setMetadata('version', '1.0.0');
3171
+ * },
3172
+ * (context) => {
3173
+ * // Add namespace prefix if not present
3174
+ * if (!context.definition.name.includes('.')) {
3175
+ * context.definition.name = `app.${context.definition.name}`;
3176
+ * }
3177
+ * }
3178
+ * ])
3179
+ * ```
3180
+ */
3181
+ function provideModuleMiddleware(middleware) {
3182
+ return makeEnvironmentProviders([
3183
+ {
3184
+ provide: AXP_MODULE_MIDDLEWARE_SETUP,
3185
+ useFactory: () => {
3186
+ // Access registry through DI when available
3187
+ const registry = globalThis.__domainRegistry__;
3188
+ if (!registry) {
3189
+ console.warn('Domain registry not available during module middleware setup');
3190
+ return false;
3191
+ }
3192
+ // Register all module middleware
3193
+ for (const mw of middleware) {
3194
+ registry.addModuleMiddleware(mw);
3195
+ }
3196
+ console.log(`✓ Registered ${middleware.length} module middleware functions`);
3197
+ return true;
3198
+ },
3199
+ multi: true
3200
+ }
3201
+ ]);
3202
+ }
3203
+ /**
3204
+ * Provide middleware for aggregate processing.
3205
+ *
3206
+ * Aggregate middleware is applied when resolving aggregate definitions and can:
3207
+ * - Add metadata and custom properties
3208
+ * - Validate aggregate structure
3209
+ * - Transform entity references
3210
+ * - Add computed relations
3211
+ *
3212
+ * @param middleware Array of middleware functions to register
3213
+ * @returns Environment providers for dependency injection
3214
+ *
3215
+ * @example
3216
+ * ```typescript
3217
+ * provideAggregateMiddleware([
3218
+ * (context) => {
3219
+ * // Add aggregate metadata
3220
+ * context.setMetadata('type', 'business-aggregate');
3221
+ * },
3222
+ * (context) => {
3223
+ * // Validate entity references
3224
+ * const entities = context.definition.entities;
3225
+ * if (Object.keys(entities).length === 0) {
3226
+ * throw new Error('Aggregate must have at least one entity');
3227
+ * }
3228
+ * }
3229
+ * ])
3230
+ * ```
3231
+ */
3232
+ function provideAggregateMiddleware(middleware) {
3233
+ return makeEnvironmentProviders([
3234
+ {
3235
+ provide: AXP_AGGREGATE_MIDDLEWARE_SETUP,
3236
+ useFactory: () => {
3237
+ // Access registry through DI when available
3238
+ const registry = globalThis.__domainRegistry__;
3239
+ if (!registry) {
3240
+ console.warn('Domain registry not available during aggregate middleware setup');
3241
+ return false;
3242
+ }
3243
+ // Register all aggregate middleware
3244
+ for (const mw of middleware) {
3245
+ registry.addAggregateMiddleware(mw);
3246
+ }
3247
+ console.log(`✓ Registered ${middleware.length} aggregate middleware functions`);
3248
+ return true;
3249
+ },
3250
+ multi: true
3251
+ }
3252
+ ]);
3253
+ }
3254
+ /**
3255
+ * Provide middleware for entity processing.
3256
+ *
3257
+ * Entity middleware is applied when resolving entity definitions and can:
3258
+ * - Add auto-generated fields (id, timestamps)
3259
+ * - Apply field transformations
3260
+ * - Add validation rules
3261
+ * - Set default values
3262
+ *
3263
+ * @param middleware Array of middleware functions to register
3264
+ * @returns Environment providers for dependency injection
3265
+ *
3266
+ * @example
3267
+ * ```typescript
3268
+ * provideEntityMiddleware([
3269
+ * (context) => {
3270
+ * // Add auto-generated ID field if not present
3271
+ * if (!context.definition.fields.some(f => f.name === 'id')) {
3272
+ * context.addField({
3273
+ * name: 'id',
3274
+ * type: 'uuid',
3275
+ * required: true,
3276
+ * generated: true
3277
+ * });
3278
+ * }
3279
+ * },
3280
+ * (context) => {
3281
+ * // Add timestamp fields
3282
+ * context.addField({
3283
+ * name: 'createdAt',
3284
+ * type: 'datetime',
3285
+ * required: true,
3286
+ * generated: true
3287
+ * });
3288
+ * context.addField({
3289
+ * name: 'updatedAt',
3290
+ * type: 'datetime',
3291
+ * required: true,
3292
+ * generated: true
3293
+ * });
3294
+ * }
3295
+ * ])
3296
+ * ```
3297
+ */
3298
+ function provideEntityMiddleware(middleware) {
3299
+ return makeEnvironmentProviders([
3300
+ {
3301
+ provide: AXP_ENTITY_MIDDLEWARE_SETUP,
3302
+ useFactory: () => {
3303
+ // Access registry through DI when available
3304
+ const registry = globalThis.__domainRegistry__;
3305
+ if (!registry) {
3306
+ console.warn('Domain registry not available during entity middleware setup');
3307
+ return false;
3308
+ }
3309
+ // Register all entity middleware
3310
+ for (const mw of middleware) {
3311
+ registry.addEntityMiddleware(mw);
3312
+ }
3313
+ console.log(`✓ Registered ${middleware.length} entity middleware functions`);
3314
+ return true;
3315
+ },
3316
+ multi: true
3317
+ }
3318
+ ]);
3319
+ }
3320
+ /**
3321
+ * Provide combined middleware for all domain types.
3322
+ *
3323
+ * This is a convenience function that allows registering middleware for multiple
3324
+ * domain types in a single call.
3325
+ *
3326
+ * @param config Configuration object with middleware for each type
3327
+ * @returns Environment providers for dependency injection
3328
+ *
3329
+ * @example
3330
+ * ```typescript
3331
+ * provideDomainMiddleware({
3332
+ * modules: [
3333
+ * (context) => context.setMetadata('loadedAt', new Date())
3334
+ * ],
3335
+ * aggregates: [
3336
+ * (context) => context.setMetadata('type', 'business-aggregate')
3337
+ * ],
3338
+ * entities: [
3339
+ * (context) => {
3340
+ * if (!context.definition.fields.some(f => f.name === 'id')) {
3341
+ * context.addField({ name: 'id', type: 'uuid', required: true });
3342
+ * }
3343
+ * }
3344
+ * ]
3345
+ * })
3346
+ * ```
3347
+ */
3348
+ function provideDomainMiddleware(config) {
3349
+ const allProviders = [];
3350
+ // Add module middleware providers
3351
+ if (config.modules && config.modules.length > 0) {
3352
+ allProviders.push({
3353
+ provide: AXP_MODULE_MIDDLEWARE_SETUP,
3354
+ useFactory: () => {
3355
+ const registry = globalThis.__domainRegistry__;
3356
+ if (!registry) {
3357
+ console.warn('Domain registry not available during module middleware setup');
3358
+ return false;
3359
+ }
3360
+ for (const mw of config.modules) {
3361
+ registry.addModuleMiddleware(mw);
3362
+ }
3363
+ return true;
3364
+ },
3365
+ multi: true
3366
+ });
3367
+ }
3368
+ // Add aggregate middleware providers
3369
+ if (config.aggregates && config.aggregates.length > 0) {
3370
+ allProviders.push({
3371
+ provide: AXP_AGGREGATE_MIDDLEWARE_SETUP,
3372
+ useFactory: () => {
3373
+ const registry = globalThis.__domainRegistry__;
3374
+ if (!registry) {
3375
+ console.warn('Domain registry not available during aggregate middleware setup');
3376
+ return false;
3377
+ }
3378
+ for (const mw of config.aggregates) {
3379
+ registry.addAggregateMiddleware(mw);
3380
+ }
3381
+ return true;
3382
+ },
3383
+ multi: true
3384
+ });
3385
+ }
3386
+ // Add entity middleware providers
3387
+ if (config.entities && config.entities.length > 0) {
3388
+ allProviders.push({
3389
+ provide: AXP_ENTITY_MIDDLEWARE_SETUP,
3390
+ useFactory: () => {
3391
+ const registry = globalThis.__domainRegistry__;
3392
+ if (!registry) {
3393
+ console.warn('Domain registry not available during entity middleware setup');
3394
+ return false;
3395
+ }
3396
+ for (const mw of config.entities) {
3397
+ registry.addEntityMiddleware(mw);
3398
+ }
3399
+ return true;
3400
+ },
3401
+ multi: true
3402
+ });
3403
+ }
3404
+ return makeEnvironmentProviders(allProviders);
3405
+ }
3406
+ //#endregion
3407
+
3408
+ //#region ---- Core Registry System ----
3409
+ // Main registry and service
3410
+ //#endregion
3411
+
3412
+ //#endregion
100
3413
 
101
3414
  /**
102
3415
  * Generated bundle index. Do not edit.
103
3416
  */
104
3417
 
105
- export { AXPDomainModule, AXP_ENTITY_CRUD_SETUP, provideEntity };
3418
+ export { AXPAggregateModel, AXPDomainMiddlewareContext, AXPDomainModule, AXPDomainRegistry, AXPDomainService, AXPEntityCommandScope, AXPEntityFieldModel, AXPEntityModel, AXPEntityType, AXPModuleHelper, AXPModuleModel, AXPRelationModel, AXPRelationshipCardinality, AXPRelationshipKind, AXPSchemaMiddlewareContext, AXPSchemaModel, AXPSchemaRegistry, AXPSchemaService, AXP_AGGREGATE_MIDDLEWARE_SETUP, AXP_ENTITY_CRUD_SETUP, AXP_ENTITY_MIDDLEWARE_SETUP, AXP_MODULE_MIDDLEWARE_SETUP, AXP_SCHEMA_EXTENSION, AXP_SCHEMA_LOADER_SETUP, AXP_SCHEMA_MIDDLEWARE_SETUP, AXP_SCHEMA_SETUP, provideAggregateMiddleware, provideDomainLoader, provideDomainLoaders, provideDomainMiddleware, provideEntity, provideEntityMiddleware, provideModuleMiddleware, provideSchema, provideSchemaLoaders, provideSchemaMiddleware, provideSchemaSetups, provideSchemasFromFactory };
106
3419
  //# sourceMappingURL=acorex-platform-domain.mjs.map