@acorex/platform 20.8.12 → 20.8.14

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 (123) hide show
  1. package/{types/acorex-platform-auth.d.ts → auth/index.d.ts} +2 -14
  2. package/{types/acorex-platform-common.d.ts → common/index.d.ts} +30 -302
  3. package/{types/acorex-platform-core.d.ts → core/index.d.ts} +44 -188
  4. package/{types/acorex-platform-domain.d.ts → domain/index.d.ts} +412 -744
  5. package/fesm2022/acorex-platform-auth.mjs +27 -125
  6. package/fesm2022/acorex-platform-auth.mjs.map +1 -1
  7. package/fesm2022/{acorex-platform-common-common-settings.provider-Bi1RYif5.mjs → acorex-platform-common-common-settings.provider-DVvuLUfF.mjs} +32 -30
  8. package/fesm2022/acorex-platform-common-common-settings.provider-DVvuLUfF.mjs.map +1 -0
  9. package/fesm2022/acorex-platform-common.mjs +205 -711
  10. package/fesm2022/acorex-platform-common.mjs.map +1 -1
  11. package/fesm2022/acorex-platform-core.mjs +127 -420
  12. package/fesm2022/acorex-platform-core.mjs.map +1 -1
  13. package/fesm2022/acorex-platform-domain.mjs +830 -561
  14. package/fesm2022/acorex-platform-domain.mjs.map +1 -1
  15. package/fesm2022/acorex-platform-layout-builder.mjs +114 -634
  16. package/fesm2022/acorex-platform-layout-builder.mjs.map +1 -1
  17. package/fesm2022/{acorex-platform-layout-components-binding-expression-editor-popup.component-CXEdvDTf.mjs → acorex-platform-layout-components-binding-expression-editor-popup.component-CSxCnzwU.mjs} +9 -9
  18. package/fesm2022/acorex-platform-layout-components-binding-expression-editor-popup.component-CSxCnzwU.mjs.map +1 -0
  19. package/fesm2022/acorex-platform-layout-components.mjs +877 -3362
  20. package/fesm2022/acorex-platform-layout-components.mjs.map +1 -1
  21. package/fesm2022/acorex-platform-layout-designer.mjs +204 -456
  22. package/fesm2022/acorex-platform-layout-designer.mjs.map +1 -1
  23. package/fesm2022/acorex-platform-layout-entity.mjs +10062 -14672
  24. package/fesm2022/acorex-platform-layout-entity.mjs.map +1 -1
  25. package/fesm2022/acorex-platform-layout-views.mjs +171 -413
  26. package/fesm2022/acorex-platform-layout-views.mjs.map +1 -1
  27. package/fesm2022/acorex-platform-layout-widget-core.mjs +441 -507
  28. package/fesm2022/acorex-platform-layout-widget-core.mjs.map +1 -1
  29. package/fesm2022/{acorex-platform-layout-widgets-button-widget-designer.component-Dy7jF-oD.mjs → acorex-platform-layout-widgets-button-widget-designer.component-CPBzE96V.mjs} +10 -10
  30. package/fesm2022/acorex-platform-layout-widgets-button-widget-designer.component-CPBzE96V.mjs.map +1 -0
  31. package/fesm2022/{acorex-platform-layout-widgets-file-list-popup.component-CDYAGBku.mjs → acorex-platform-layout-widgets-file-list-popup.component-Dtv6U3df.mjs} +76 -21
  32. package/fesm2022/acorex-platform-layout-widgets-file-list-popup.component-Dtv6U3df.mjs.map +1 -0
  33. package/fesm2022/{acorex-platform-layout-widgets-image-preview.popup-C_EPAvCU.mjs → acorex-platform-layout-widgets-image-preview.popup-QxJfswhK.mjs} +7 -6
  34. package/fesm2022/acorex-platform-layout-widgets-image-preview.popup-QxJfswhK.mjs.map +1 -0
  35. package/fesm2022/{acorex-platform-layout-widgets-page-widget-designer.component-D10yO28c.mjs → acorex-platform-layout-widgets-page-widget-designer.component-CVdssZBD.mjs} +12 -12
  36. package/fesm2022/acorex-platform-layout-widgets-page-widget-designer.component-CVdssZBD.mjs.map +1 -0
  37. package/fesm2022/acorex-platform-layout-widgets-repeater-widget-column.component-BCxE0RTB.mjs +111 -0
  38. package/fesm2022/acorex-platform-layout-widgets-repeater-widget-column.component-BCxE0RTB.mjs.map +1 -0
  39. package/fesm2022/{acorex-platform-layout-widgets-tabular-data-edit-popup.component-DmzNTYiS.mjs → acorex-platform-layout-widgets-tabular-data-edit-popup.component-DVaZN9QN.mjs} +5 -5
  40. package/fesm2022/acorex-platform-layout-widgets-tabular-data-edit-popup.component-DVaZN9QN.mjs.map +1 -0
  41. package/fesm2022/{acorex-platform-layout-widgets-tabular-data-view-popup.component-BNG_588B.mjs → acorex-platform-layout-widgets-tabular-data-view-popup.component-DPGHgXa6.mjs} +4 -4
  42. package/fesm2022/acorex-platform-layout-widgets-tabular-data-view-popup.component-DPGHgXa6.mjs.map +1 -0
  43. package/fesm2022/{acorex-platform-layout-widgets-text-block-widget-designer.component-Vo4fWHtX.mjs → acorex-platform-layout-widgets-text-block-widget-designer.component-CdiNW691.mjs} +6 -6
  44. package/fesm2022/acorex-platform-layout-widgets-text-block-widget-designer.component-CdiNW691.mjs.map +1 -0
  45. package/fesm2022/acorex-platform-layout-widgets.mjs +3408 -5611
  46. package/fesm2022/acorex-platform-layout-widgets.mjs.map +1 -1
  47. package/fesm2022/acorex-platform-native.mjs +7 -8
  48. package/fesm2022/acorex-platform-native.mjs.map +1 -1
  49. package/fesm2022/acorex-platform-runtime.mjs +166 -391
  50. package/fesm2022/acorex-platform-runtime.mjs.map +1 -1
  51. package/fesm2022/acorex-platform-themes-default-entity-master-create-view.component-D4hU2SCE.mjs +160 -0
  52. package/fesm2022/acorex-platform-themes-default-entity-master-create-view.component-D4hU2SCE.mjs.map +1 -0
  53. package/fesm2022/acorex-platform-themes-default-entity-master-list-view.component-D2CtNrSn.mjs +1716 -0
  54. package/fesm2022/acorex-platform-themes-default-entity-master-list-view.component-D2CtNrSn.mjs.map +1 -0
  55. package/fesm2022/acorex-platform-themes-default-entity-master-modify-view.component-BVTklnzs.mjs +120 -0
  56. package/fesm2022/acorex-platform-themes-default-entity-master-modify-view.component-BVTklnzs.mjs.map +1 -0
  57. package/fesm2022/{acorex-platform-themes-default-entity-master-single-view.component-BfCeUU5F.mjs → acorex-platform-themes-default-entity-master-single-view.component-rGsMVAZj.mjs} +23 -16
  58. package/fesm2022/acorex-platform-themes-default-entity-master-single-view.component-rGsMVAZj.mjs.map +1 -0
  59. package/fesm2022/{acorex-platform-themes-default-error-401.component-C7EYJzSr.mjs → acorex-platform-themes-default-error-401.component-53VB-PS_.mjs} +4 -4
  60. package/fesm2022/acorex-platform-themes-default-error-401.component-53VB-PS_.mjs.map +1 -0
  61. package/fesm2022/{acorex-platform-themes-default-error-404.component-7MVLMwIa.mjs → acorex-platform-themes-default-error-404.component-DVF9soT5.mjs} +4 -4
  62. package/fesm2022/acorex-platform-themes-default-error-404.component-DVF9soT5.mjs.map +1 -0
  63. package/fesm2022/acorex-platform-themes-default-error-offline.component-CwNNHzZn.mjs +19 -0
  64. package/fesm2022/acorex-platform-themes-default-error-offline.component-CwNNHzZn.mjs.map +1 -0
  65. package/fesm2022/acorex-platform-themes-default.mjs +61 -1784
  66. package/fesm2022/acorex-platform-themes-default.mjs.map +1 -1
  67. package/fesm2022/{acorex-platform-themes-shared-icon-chooser-column.component-CqkWJYdv.mjs → acorex-platform-themes-shared-icon-chooser-column.component-TJ9PWHMY.mjs} +6 -6
  68. package/fesm2022/acorex-platform-themes-shared-icon-chooser-column.component-TJ9PWHMY.mjs.map +1 -0
  69. package/fesm2022/{acorex-platform-themes-shared-icon-chooser-view.component-BOTuLdWN.mjs → acorex-platform-themes-shared-icon-chooser-view.component-BHcKkIx0.mjs} +6 -6
  70. package/fesm2022/acorex-platform-themes-shared-icon-chooser-view.component-BHcKkIx0.mjs.map +1 -0
  71. package/fesm2022/{acorex-platform-themes-shared-settings.provider-DK6R87Lf.mjs → acorex-platform-themes-shared-settings.provider-DSs1o1M6.mjs} +25 -24
  72. package/fesm2022/acorex-platform-themes-shared-settings.provider-DSs1o1M6.mjs.map +1 -0
  73. package/fesm2022/acorex-platform-themes-shared-theme-color-chooser-column.component-BUPs84MI.mjs +65 -0
  74. package/fesm2022/acorex-platform-themes-shared-theme-color-chooser-column.component-BUPs84MI.mjs.map +1 -0
  75. package/fesm2022/acorex-platform-themes-shared-theme-color-chooser-view.component-BotknoHn.mjs +64 -0
  76. package/fesm2022/acorex-platform-themes-shared-theme-color-chooser-view.component-BotknoHn.mjs.map +1 -0
  77. package/fesm2022/acorex-platform-themes-shared.mjs +305 -408
  78. package/fesm2022/acorex-platform-themes-shared.mjs.map +1 -1
  79. package/fesm2022/acorex-platform-workflow.mjs +100 -359
  80. package/fesm2022/acorex-platform-workflow.mjs.map +1 -1
  81. package/fesm2022/acorex-platform.mjs.map +1 -1
  82. package/{types/acorex-platform-layout-builder.d.ts → layout/builder/index.d.ts} +38 -160
  83. package/{types/acorex-platform-layout-components.d.ts → layout/components/index.d.ts} +125 -854
  84. package/{types/acorex-platform-layout-designer.d.ts → layout/designer/index.d.ts} +18 -96
  85. package/{types/acorex-platform-layout-entity.d.ts → layout/entity/index.d.ts} +65 -848
  86. package/{types/acorex-platform-layout-views.d.ts → layout/views/index.d.ts} +47 -80
  87. package/{types/acorex-platform-layout-widget-core.d.ts → layout/widget-core/index.d.ts} +197 -274
  88. package/{types/acorex-platform-layout-widgets.d.ts → layout/widgets/index.d.ts} +124 -608
  89. package/{types/acorex-platform-native.d.ts → native/index.d.ts} +7 -0
  90. package/package.json +36 -36
  91. package/runtime/index.d.ts +307 -0
  92. package/{types/acorex-platform-themes-default.d.ts → themes/default/index.d.ts} +4 -113
  93. package/{types/acorex-platform-themes-shared.d.ts → themes/shared/index.d.ts} +4 -5
  94. package/{types/acorex-platform-workflow.d.ts → workflow/index.d.ts} +81 -162
  95. package/fesm2022/acorex-platform-common-common-settings.provider-Bi1RYif5.mjs.map +0 -1
  96. package/fesm2022/acorex-platform-layout-components-binding-expression-editor-popup.component-CXEdvDTf.mjs.map +0 -1
  97. package/fesm2022/acorex-platform-layout-widgets-button-widget-designer.component-Dy7jF-oD.mjs.map +0 -1
  98. package/fesm2022/acorex-platform-layout-widgets-file-list-popup.component-CDYAGBku.mjs.map +0 -1
  99. package/fesm2022/acorex-platform-layout-widgets-image-preview.popup-C_EPAvCU.mjs.map +0 -1
  100. package/fesm2022/acorex-platform-layout-widgets-page-widget-designer.component-D10yO28c.mjs.map +0 -1
  101. package/fesm2022/acorex-platform-layout-widgets-repeater-widget-column.component-BGO75IMz.mjs +0 -116
  102. package/fesm2022/acorex-platform-layout-widgets-repeater-widget-column.component-BGO75IMz.mjs.map +0 -1
  103. package/fesm2022/acorex-platform-layout-widgets-tabular-data-edit-popup.component-DmzNTYiS.mjs.map +0 -1
  104. package/fesm2022/acorex-platform-layout-widgets-tabular-data-view-popup.component-BNG_588B.mjs.map +0 -1
  105. package/fesm2022/acorex-platform-layout-widgets-text-block-widget-designer.component-Vo4fWHtX.mjs.map +0 -1
  106. package/fesm2022/acorex-platform-themes-default-entity-master-create-view.component-Cx1lLUaR.mjs +0 -160
  107. package/fesm2022/acorex-platform-themes-default-entity-master-create-view.component-Cx1lLUaR.mjs.map +0 -1
  108. package/fesm2022/acorex-platform-themes-default-entity-master-modify-view.component-AOrcgjDF.mjs +0 -120
  109. package/fesm2022/acorex-platform-themes-default-entity-master-modify-view.component-AOrcgjDF.mjs.map +0 -1
  110. package/fesm2022/acorex-platform-themes-default-entity-master-single-view.component-BfCeUU5F.mjs.map +0 -1
  111. package/fesm2022/acorex-platform-themes-default-error-401.component-C7EYJzSr.mjs.map +0 -1
  112. package/fesm2022/acorex-platform-themes-default-error-404.component-7MVLMwIa.mjs.map +0 -1
  113. package/fesm2022/acorex-platform-themes-default-error-offline.component-DR6G8gPC.mjs +0 -19
  114. package/fesm2022/acorex-platform-themes-default-error-offline.component-DR6G8gPC.mjs.map +0 -1
  115. package/fesm2022/acorex-platform-themes-shared-icon-chooser-column.component-CqkWJYdv.mjs.map +0 -1
  116. package/fesm2022/acorex-platform-themes-shared-icon-chooser-view.component-BOTuLdWN.mjs.map +0 -1
  117. package/fesm2022/acorex-platform-themes-shared-settings.provider-DK6R87Lf.mjs.map +0 -1
  118. package/fesm2022/acorex-platform-themes-shared-theme-color-chooser-column.component-D566Kdvy.mjs +0 -94
  119. package/fesm2022/acorex-platform-themes-shared-theme-color-chooser-column.component-D566Kdvy.mjs.map +0 -1
  120. package/fesm2022/acorex-platform-themes-shared-theme-color-chooser-view.component-D7-rCGl7.mjs +0 -86
  121. package/fesm2022/acorex-platform-themes-shared-theme-color-chooser-view.component-D7-rCGl7.mjs.map +0 -1
  122. package/types/acorex-platform-runtime.d.ts +0 -571
  123. /package/{types/acorex-platform.d.ts → index.d.ts} +0 -0
@@ -1,39 +1,204 @@
1
1
  import * as i0 from '@angular/core';
2
- import { InjectionToken, inject, NgModule, Injectable, makeEnvironmentProviders } from '@angular/core';
3
- import { AXPRuntimeModule } from '@acorex/platform/runtime';
2
+ import { InjectionToken, makeEnvironmentProviders, inject, NgModule, Injectable } from '@angular/core';
3
+ import { AXPEntityService } from '@acorex/platform/layout/entity';
4
+ import { AXPCommandRegistry, AXPQueryRegistry, AXPRuntimeModule } from '@acorex/platform/runtime';
4
5
 
5
- /**
6
- * Token for entity CRUD setup. Consumed by AXPDomainModule.
7
- * The actual provider is provideEntity() from @acorex/platform/layout/entity
8
- * to avoid circular dependency (domain must not depend on layout/entity).
9
- */
10
6
  const AXP_ENTITY_CRUD_SETUP = new InjectionToken('AXP_ENTITY_CRUD_SETUP');
11
-
12
- //#endregion
13
- //#region ---- Injection Token ----
14
- const AXP_ENTITY_DEFINITION_CRUD_SERVICE = new InjectionToken('AXP_ENTITY_DEFINITION_CRUD_SERVICE', {
15
- providedIn: null,
16
- factory: () => null,
17
- });
18
- //#endregion
7
+ function provideEntity(entityKeys) {
8
+ return makeEnvironmentProviders([
9
+ {
10
+ provide: AXP_ENTITY_CRUD_SETUP,
11
+ multi: true,
12
+ useFactory: () => {
13
+ const commandRegistry = inject(AXPCommandRegistry);
14
+ const queryRegistry = inject(AXPQueryRegistry);
15
+ const entityService = inject(AXPEntityService);
16
+ for (const entityKey of entityKeys) {
17
+ const dataAccessor = entityService.withEntity(entityKey).data();
18
+ // Register Commands
19
+ commandRegistry.register(`${entityKey}:Create`, async () => ({
20
+ execute: async (input) => {
21
+ try {
22
+ const id = await dataAccessor.create(input);
23
+ const entity = await dataAccessor.byKey(id);
24
+ if (!entity) {
25
+ throw new Error('Entity not found after creation');
26
+ }
27
+ return {
28
+ success: true,
29
+ data: entity,
30
+ };
31
+ }
32
+ catch (error) {
33
+ return {
34
+ success: false,
35
+ message: {
36
+ text: error instanceof Error ? error.message : 'Failed to create entity',
37
+ },
38
+ };
39
+ }
40
+ }
41
+ }));
42
+ commandRegistry.register(`${entityKey}:Update`, async () => ({
43
+ execute: async ({ id, ...rest }) => {
44
+ try {
45
+ const updated = await dataAccessor.update(id, rest);
46
+ return {
47
+ success: true,
48
+ data: updated,
49
+ };
50
+ }
51
+ catch (error) {
52
+ return {
53
+ success: false,
54
+ message: {
55
+ text: error instanceof Error ? error.message : 'Failed to update entity',
56
+ },
57
+ };
58
+ }
59
+ }
60
+ }));
61
+ commandRegistry.register(`${entityKey}:Delete`, async () => ({
62
+ execute: async (id) => {
63
+ try {
64
+ await dataAccessor.delete(id);
65
+ return {
66
+ success: true,
67
+ };
68
+ }
69
+ catch (error) {
70
+ return {
71
+ success: false,
72
+ message: {
73
+ text: error instanceof Error ? error.message : 'Failed to delete entity',
74
+ },
75
+ };
76
+ }
77
+ }
78
+ }));
79
+ // Register Queries
80
+ queryRegistry.register(`${entityKey}:GetById`, async () => ({
81
+ fetch: (id) => dataAccessor.byKey(id)
82
+ }));
83
+ queryRegistry.register(`${entityKey}:GetList`, async () => ({
84
+ fetch: (request) => dataAccessor.query(request)
85
+ }));
86
+ // Implement getRoots, getChildren, and getByCategory using query with appropriate filters
87
+ queryRegistry.register(`${entityKey}:GetRoots`, async () => ({
88
+ fetch: async (request) => {
89
+ return await dataAccessor.query({
90
+ skip: 0,
91
+ take: 1000,
92
+ filter: {
93
+ field: 'parentId',
94
+ operator: {
95
+ type: 'isEmpty',
96
+ },
97
+ value: true,
98
+ },
99
+ });
100
+ }
101
+ }));
102
+ queryRegistry.register(`${entityKey}:GetChildren`, async () => ({
103
+ fetch: async (request) => {
104
+ const parentKey = request.parentKey ?? 'parentId';
105
+ return await dataAccessor.query({
106
+ skip: 0,
107
+ take: 1000,
108
+ filter: {
109
+ field: parentKey,
110
+ operator: {
111
+ type: 'equal',
112
+ },
113
+ value: request.parentId,
114
+ },
115
+ });
116
+ }
117
+ }));
118
+ queryRegistry.register(`${entityKey}:GetByCategory`, async () => ({
119
+ fetch: async (request) => {
120
+ const categoryKey = request.categoryKey ?? 'categoryIds';
121
+ return await dataAccessor.query({
122
+ skip: 0,
123
+ take: 1000,
124
+ filter: {
125
+ field: categoryKey,
126
+ operator: {
127
+ type: 'contains',
128
+ },
129
+ value: request.categoryId,
130
+ },
131
+ });
132
+ }
133
+ }));
134
+ }
135
+ return true;
136
+ }
137
+ },
138
+ // {
139
+ // provide: AXP_PERMISSION_DEFINITION_PROVIDER,
140
+ // multi: true,
141
+ // useFactory: () => {
142
+ // const provider: AXPPermissionDefinitionProvider = {
143
+ // define: async (context) => {
144
+ // for (const entityKey of entityKeys) {
145
+ // const group = entityKey.split('.')[0];
146
+ // context.addGroup(group, group)
147
+ // .addPermission(entityKey, entityKey)
148
+ // .addChild(`${entityKey}:Create`, `${entityKey}:Create`)
149
+ // .addChild(`${entityKey}:Update`, `${entityKey}:Update`)
150
+ // .addChild(`${entityKey}:Delete`, `${entityKey}:Delete`)
151
+ // .endPermission()
152
+ // .endGroup();
153
+ // }
154
+ // }
155
+ // }
156
+ // return provider;
157
+ // }
158
+ // },
159
+ // {
160
+ // provide: AXP_ENTITY_CRUD_SETUP,
161
+ // multi: true,
162
+ // useFactory: () => {
163
+ // return true;
164
+ // }
165
+ // }
166
+ ]);
167
+ }
19
168
 
20
169
  //#region ---- Dependency Injection Tokens ----
21
170
  /**
22
- * Targeted middleware extension (name or regex) for property resolution.
171
+ * Injection token for schema-specific middleware extensions.
172
+ *
173
+ * Used for targeted middleware that applies only to schemas matching
174
+ * specific patterns (name or regex). This enables fine-grained control
175
+ * over which schemas receive which middleware.
23
176
  */
24
- const AXP_PROPERTY_EXTENSION = new InjectionToken('AXP_PROPERTY_EXTENSION');
177
+ const AXP_SCHEMA_EXTENSION = new InjectionToken('AXP_SCHEMA_EXTENSION');
25
178
  /**
26
- * Bootstrap hook: register property definitions known at build time.
179
+ * Injection token for schema setup initialization.
180
+ *
181
+ * Used during application bootstrap to register schemas that are
182
+ * known at build time. Multiple providers can use this token to
183
+ * contribute schemas to the registry.
27
184
  */
28
- const AXP_PROPERTY_SETUP = new InjectionToken('AXP_PROPERTY_SETUP');
185
+ const AXP_SCHEMA_SETUP = new InjectionToken('AXP_SCHEMA_SETUP');
29
186
  /**
30
- * Bootstrap hook: register global middleware for every property resolution.
187
+ * Injection token for schema middleware setup initialization.
188
+ *
189
+ * Used during application bootstrap to register global middleware
190
+ * that applies to all schema resolutions. This enables centralized
191
+ * schema processing logic.
31
192
  */
32
- const AXP_PROPERTY_MIDDLEWARE_SETUP = new InjectionToken('AXP_PROPERTY_MIDDLEWARE_SETUP');
193
+ const AXP_SCHEMA_MIDDLEWARE_SETUP = new InjectionToken('AXP_SCHEMA_MIDDLEWARE_SETUP');
33
194
  /**
34
- * Bootstrap hook: register on-demand property loaders.
195
+ * Injection token for schema loader setup initialization.
196
+ *
197
+ * Used during application bootstrap to register schema loaders
198
+ * that can provide schemas on-demand when they're not found in
199
+ * the registry.
35
200
  */
36
- const AXP_PROPERTY_LOADER_SETUP = new InjectionToken('AXP_PROPERTY_LOADER_SETUP');
201
+ const AXP_SCHEMA_LOADER_SETUP = new InjectionToken('AXP_SCHEMA_LOADER_SETUP');
37
202
  //#endregion
38
203
 
39
204
  //#region ---- Dependency Injection Tokens ----
@@ -75,11 +240,15 @@ class AXPDomainModule {
75
240
  constructor() {
76
241
  this._commandSetup = inject(AXP_ENTITY_CRUD_SETUP, { optional: true });
77
242
  /**
78
- * Optional bootstrap hooks for registered property definitions (see {@link AXP_PROPERTY_SETUP} and related tokens).
243
+ * Injection token for schema setup initialization.
244
+ *
245
+ * Used during application bootstrap to register global middleware
246
+ * that applies to all schema resolutions. This enables centralized
247
+ * schema processing logic.
79
248
  */
80
- this._propertySetup = inject(AXP_PROPERTY_SETUP, { optional: true });
81
- this._propertyMiddlewareSetup = inject(AXP_PROPERTY_MIDDLEWARE_SETUP, { optional: true });
82
- this._propertyLoaderSetup = inject(AXP_PROPERTY_LOADER_SETUP, { optional: true });
249
+ this._schemaSetup = inject(AXP_SCHEMA_SETUP, { optional: true });
250
+ this._schemaMiddlewareSetup = inject(AXP_SCHEMA_MIDDLEWARE_SETUP, { optional: true });
251
+ this._schemaLoaderSetup = inject(AXP_SCHEMA_LOADER_SETUP, { optional: true });
83
252
  /**
84
253
  * Injection token for domain loader setup initialization.
85
254
  *
@@ -91,11 +260,11 @@ class AXPDomainModule {
91
260
  this._domainMiddlewareSetup = inject(AXP_DOMAIN_MIDDLEWARE_SETUP, { optional: true });
92
261
  this._domainSetup = inject(AXP_DOMAIN_SETUP, { optional: true });
93
262
  }
94
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPDomainModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
95
- static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "21.2.9", ngImport: i0, type: AXPDomainModule, imports: [AXPRuntimeModule] }); }
96
- static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPDomainModule, imports: [AXPRuntimeModule] }); }
263
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: AXPDomainModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
264
+ static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "20.3.19", ngImport: i0, type: AXPDomainModule, imports: [AXPRuntimeModule] }); }
265
+ static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: AXPDomainModule, imports: [AXPRuntimeModule] }); }
97
266
  }
98
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPDomainModule, decorators: [{
267
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: AXPDomainModule, decorators: [{
99
268
  type: NgModule,
100
269
  args: [{
101
270
  imports: [
@@ -104,12 +273,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
104
273
  }]
105
274
  }] });
106
275
 
107
- var AXPDomainActionSide;
108
- (function (AXPDomainActionSide) {
109
- AXPDomainActionSide["Client"] = "client";
110
- AXPDomainActionSide["Server"] = "server";
111
- AXPDomainActionSide["Both"] = "both";
112
- })(AXPDomainActionSide || (AXPDomainActionSide = {}));
113
276
  var AXPEntityCommandScope;
114
277
  (function (AXPEntityCommandScope) {
115
278
  AXPEntityCommandScope["TypeLevel"] = "typeLevel";
@@ -140,31 +303,221 @@ var AXPRelationshipCardinality;
140
303
  AXPRelationshipCardinality[AXPRelationshipCardinality["ManyToMany"] = 2] = "ManyToMany";
141
304
  })(AXPRelationshipCardinality || (AXPRelationshipCardinality = {}));
142
305
 
143
- //#region ---- Serializable menu definition (storage / CRUD contract) ----
144
- //#endregion
145
-
146
- //#region ---- Serializable permission definition (storage / CRUD contract) ----
147
- //#endregion
148
-
149
- //#endregion
150
-
151
- //#endregion
152
-
153
- //#region ---- Widget catalog persisted record ----
154
- //#endregion
306
+ //#region ---- AXPRelationModel ----
307
+ /**
308
+ * Runtime model for relation definitions with parent references and helper methods
309
+ */
310
+ class AXPRelationModel {
311
+ constructor(definition, parent) {
312
+ console.log('Relation Model Constructor', definition, parent);
313
+ this.type = definition.type;
314
+ this.kind = definition.kind;
315
+ this.target = { ...definition.target };
316
+ this.source = { ...definition.source };
317
+ this.isRequired = definition.isRequired;
318
+ this.parent = parent;
319
+ }
320
+ //#endregion
321
+ //#region ---- Cardinality Methods ----
322
+ /**
323
+ * Check if relation is one-to-one
324
+ */
325
+ isOneToOne() {
326
+ return this.type === AXPRelationshipCardinality.OneToOne;
327
+ }
328
+ /**
329
+ * Check if relation is one-to-many
330
+ */
331
+ isOneToMany() {
332
+ return this.type === AXPRelationshipCardinality.OneToMany;
333
+ }
334
+ /**
335
+ * Check if relation is many-to-many
336
+ */
337
+ isManyToMany() {
338
+ return this.type === AXPRelationshipCardinality.ManyToMany;
339
+ }
340
+ //#endregion
341
+ //#region ---- Kind Methods ----
342
+ /**
343
+ * Check if relation is association
344
+ */
345
+ isAssociation() {
346
+ return this.kind === AXPRelationshipKind.Association;
347
+ }
348
+ /**
349
+ * Check if relation is composition
350
+ */
351
+ isComposition() {
352
+ return this.kind === AXPRelationshipKind.Composition;
353
+ }
354
+ /**
355
+ * Check if relation is aggregation
356
+ */
357
+ isAggregation() {
358
+ return this.kind === AXPRelationshipKind.Aggregation;
359
+ }
360
+ //#endregion
361
+ //#region ---- Navigation Methods ----
362
+ /**
363
+ * Get parent aggregate
364
+ */
365
+ getAggregate() {
366
+ return this.parent;
367
+ }
368
+ /**
369
+ * Get parent module
370
+ */
371
+ getModule() {
372
+ return this.parent?.parent;
373
+ }
374
+ /**
375
+ * Get full path (module.aggregate.relation)
376
+ */
377
+ getPath() {
378
+ return `${this.parent.parent.name}.${this.parent.name}.${this.source.entity}->${this.target.entity}`;
379
+ }
380
+ //#endregion
381
+ //#region ---- Query Methods ----
382
+ /**
383
+ * Get relation description
384
+ */
385
+ getDescription() {
386
+ const cardinalityDesc = this.getCardinalityDescription();
387
+ const kindDesc = this.getKindDescription();
388
+ const requiredDesc = this.isRequired ? 'required' : 'optional';
389
+ return `${cardinalityDesc} ${kindDesc} (${requiredDesc})`;
390
+ }
391
+ /**
392
+ * Get cardinality description
393
+ */
394
+ getCardinalityDescription() {
395
+ switch (this.type) {
396
+ case AXPRelationshipCardinality.OneToOne:
397
+ return 'one-to-one';
398
+ case AXPRelationshipCardinality.OneToMany:
399
+ return 'one-to-many';
400
+ case AXPRelationshipCardinality.ManyToMany:
401
+ return 'many-to-many';
402
+ default:
403
+ return 'unknown';
404
+ }
405
+ }
406
+ /**
407
+ * Get kind description
408
+ */
409
+ getKindDescription() {
410
+ switch (this.kind) {
411
+ case AXPRelationshipKind.Association:
412
+ return 'association';
413
+ case AXPRelationshipKind.Composition:
414
+ return 'composition';
415
+ case AXPRelationshipKind.Aggregation:
416
+ return 'aggregation';
417
+ default:
418
+ return 'unknown';
419
+ }
420
+ }
421
+ /**
422
+ * Get relation summary
423
+ */
424
+ getSummary() {
425
+ return `${this.source.entity}.${this.source.key} -> ${this.target.aggregate}.${this.target.entity}.${this.target.key}`;
426
+ }
427
+ //#endregion
428
+ //#region ---- Validation Methods ----
429
+ /**
430
+ * Validate the relation structure
431
+ */
432
+ validate() {
433
+ const errors = [];
434
+ // Validate source
435
+ if (!this.source.entity)
436
+ errors.push('Source entity is required');
437
+ if (!this.source.key)
438
+ errors.push('Source key is required');
439
+ // Validate target
440
+ if (!this.target.aggregate)
441
+ errors.push('Target aggregate is required');
442
+ if (!this.target.entity)
443
+ errors.push('Target entity is required');
444
+ if (!this.target.key)
445
+ errors.push('Target key is required');
446
+ return errors;
447
+ }
448
+ //#endregion
449
+ //#region ---- Utility Methods ----
450
+ /**
451
+ * Get relation characteristics
452
+ */
453
+ getCharacteristics() {
454
+ return {
455
+ type: this.getCardinalityDescription(),
456
+ kind: this.getKindDescription(),
457
+ required: this.isRequired,
458
+ isOwning: this.isComposition(),
459
+ isNavigable: !this.isComposition() || this.isOneToOne()
460
+ };
461
+ }
462
+ /**
463
+ * Check if relation involves entity
464
+ */
465
+ involvesEntity(entityName) {
466
+ return this.source.entity === entityName || this.target.entity === entityName;
467
+ }
468
+ /**
469
+ * Check if relation targets aggregate
470
+ */
471
+ targetsAggregate(aggregateName) {
472
+ return this.target.aggregate === aggregateName;
473
+ }
474
+ /**
475
+ * Get the other entity in the relation
476
+ */
477
+ getOtherEntity(entityName) {
478
+ if (this.source.entity === entityName) {
479
+ return this.target.entity;
480
+ }
481
+ else if (this.target.entity === entityName) {
482
+ return this.source.entity;
483
+ }
484
+ return null;
485
+ }
486
+ /**
487
+ * Convert back to interface definition
488
+ */
489
+ toDefinition() {
490
+ return {
491
+ type: this.type,
492
+ kind: this.kind,
493
+ target: { ...this.target },
494
+ source: { ...this.source },
495
+ isRequired: this.isRequired
496
+ };
497
+ }
498
+ }
155
499
 
156
500
  //#region ---- AXPAggregateModel ----
157
501
  /**
158
502
  * Simple runtime model for aggregate definitions with parent references and navigation helpers.
159
- * Relations are stored in a separate collection; join when needed.
503
+ *
504
+ * This model is a pure data structure that provides:
505
+ * - Access to aggregate properties and metadata
506
+ * - Navigation helpers for finding relations and entity references
507
+ * - Parent module reference for hierarchy navigation
508
+ *
509
+ * All loading and resolution logic has been moved to AXPDomainRegistry.
160
510
  */
161
511
  class AXPAggregateModel {
162
512
  constructor(definition, parent) {
513
+ this.relations = [];
163
514
  this.name = definition.name;
164
515
  this.title = definition.title;
165
516
  this.validations = definition.validations || [];
166
517
  this.actions = definition.actions || [];
167
518
  this.parent = parent;
519
+ // Initialize relations with parent reference
520
+ this.relations = (definition.relations || []).map(relationDef => new AXPRelationModel(relationDef, this));
168
521
  // Extract entity references - convert all formats to simple string map
169
522
  this.entityReferences = this.extractEntityReferences(definition.entities);
170
523
  }
@@ -232,6 +585,27 @@ class AXPAggregateModel {
232
585
  hasEntity(entityName) {
233
586
  return entityName in this.entityReferences;
234
587
  }
588
+ /**
589
+ * Find relation by source and target entities
590
+ *
591
+ * @param sourceEntity Source entity name
592
+ * @param targetEntity Target entity name
593
+ * @returns Relation model or undefined if not found
594
+ */
595
+ findRelation(sourceEntity, targetEntity) {
596
+ return this.relations.find(relation => relation.source.entity === sourceEntity &&
597
+ relation.target.entity === targetEntity);
598
+ }
599
+ /**
600
+ * Get all relations for a specific entity
601
+ *
602
+ * @param entityName Entity name
603
+ * @returns Array of relations involving the entity
604
+ */
605
+ getEntityRelations(entityName) {
606
+ return this.relations.filter(relation => relation.source.entity === entityName ||
607
+ relation.target.entity === entityName);
608
+ }
235
609
  //#endregion
236
610
  //#region ---- Parent Navigation ----
237
611
  /**
@@ -260,6 +634,7 @@ class AXPAggregateModel {
260
634
  getStatistics() {
261
635
  return {
262
636
  entityCount: Object.keys(this.entityReferences).length,
637
+ relationCount: this.relations.length,
263
638
  actionCount: this.actions.length,
264
639
  validationCount: this.validations.length
265
640
  };
@@ -274,6 +649,7 @@ class AXPAggregateModel {
274
649
  name: this.name,
275
650
  title: this.title,
276
651
  entities: this.entityReferences, // Return as reference map
652
+ relations: this.relations.map(relation => relation.toDefinition()),
277
653
  validations: this.validations,
278
654
  actions: this.actions
279
655
  };
@@ -292,6 +668,13 @@ class AXPAggregateModel {
292
668
  errors.push('Aggregate name is required');
293
669
  if (!this.title)
294
670
  errors.push('Aggregate title is required');
671
+ // Validate relations
672
+ this.relations.forEach(relation => {
673
+ const relationErrors = relation.validate();
674
+ if (relationErrors.length > 0) {
675
+ errors.push(...relationErrors.map(err => `Relation: ${err}`));
676
+ }
677
+ });
295
678
  // Validate entity references
296
679
  for (const [entityName, entityRef] of Object.entries(this.entityReferences)) {
297
680
  if (!entityRef || typeof entityRef !== 'string') {
@@ -412,11 +795,18 @@ class AXPModuleModel {
412
795
  return allReferences;
413
796
  }
414
797
  /**
415
- * Relations are stored in a separate collection. Use relation queries for join when needed.
416
- * @deprecated Relations are no longer nested in aggregates.
798
+ * Get all relations across all aggregates
799
+ *
800
+ * @returns Array of all relation models
417
801
  */
418
802
  getAllRelations() {
419
- return [];
803
+ const allRelations = [];
804
+ for (const aggregate of this.aggregates) {
805
+ for (const relation of aggregate.relations) {
806
+ allRelations.push({ aggregate, relation });
807
+ }
808
+ }
809
+ return allRelations;
420
810
  }
421
811
  //#endregion
422
812
  //#region ---- Validation Methods ----
@@ -442,279 +832,140 @@ class AXPModuleModel {
442
832
  for (const aggregate of this.aggregates) {
443
833
  const aggErrors = aggregate.validate();
444
834
  if (aggErrors.length > 0) {
445
- errors.push(...aggErrors.map((err) => `${aggregate.name}: ${err}`));
446
- }
447
- }
448
- return errors;
449
- }
450
- //#endregion
451
- //#region ---- Utility Methods ----
452
- /**
453
- * Get module statistics
454
- *
455
- * @returns Statistics object
456
- */
457
- getStatistics() {
458
- const aggregateStats = this.aggregates.map(agg => agg.getStatistics());
459
- return {
460
- aggregateCount: this.aggregates.length,
461
- entityCount: aggregateStats.reduce((sum, stat) => sum + stat.entityCount, 0),
462
- actionCount: aggregateStats.reduce((sum, stat) => sum + stat.actionCount, 0),
463
- validationCount: aggregateStats.reduce((sum, stat) => sum + stat.validationCount, 0)
464
- };
465
- }
466
- /**
467
- * Convert back to interface definition
468
- *
469
- * @returns Module definition
470
- */
471
- toDefinition() {
472
- return {
473
- name: this.name,
474
- title: this.title,
475
- aggregates: this.aggregates.map(agg => agg.toDefinition())
476
- };
477
- }
478
- }
479
- //#endregion
480
-
481
- //#region ---- AXPPropertyModel ----
482
- /**
483
- * Runtime model for a {@link AXPPropertyDefinition} with helper methods.
484
- */
485
- class AXPPropertyModel {
486
- constructor(definition) {
487
- this.name = definition.name;
488
- this.title = definition.title;
489
- this.interface = definition.interface;
490
- this.disabled = definition.disabled;
491
- this.dataType = definition.dataType ?? 'string';
492
- this.validations = definition.validations ?? [];
493
- this.features = definition.features ?? {};
494
- this.metadata = definition.metadata;
495
- this.description = definition.description;
496
- this.icon = definition.icon;
497
- this.defaultValue = definition.defaultValue;
498
- }
499
- //#endregion
500
- /**
501
- * Get widget options
502
- */
503
- getWidgetOptions() {
504
- return this.interface.options;
505
- }
506
- /**
507
- * Check if the property is disabled
508
- */
509
- isDisabled() {
510
- return this.disabled ?? false;
511
- }
512
- //#endregion
513
- //#region ---- Feature Methods ----
514
- /**
515
- * Check if searchable
516
- */
517
- isSearchable() {
518
- return this.features.searchable?.enabled ?? false;
519
- }
520
- /**
521
- * Check if full text searchable
522
- */
523
- isFullTextSearchable() {
524
- return this.features.searchable?.fullText ?? false;
525
- }
526
- /**
527
- * Check if filterable
528
- */
529
- isFilterable() {
530
- return this.features.filterable?.enabled ?? false;
531
- }
532
- /**
533
- * Check if inline filterable
534
- */
535
- isInlineFilterable() {
536
- return this.features.filterable?.inline ?? false;
537
- }
538
- /**
539
- * Check if sortable
540
- */
541
- isSortable() {
542
- return this.features.sortable?.enabled ?? false;
543
- }
544
- /**
545
- * Check if auditable
546
- */
547
- isAuditable() {
548
- return this.features.auditable?.enabled ?? false;
549
- }
550
- //#endregion
551
- //#region ---- Validation Methods ----
552
- /**
553
- * Validate the property definition structure
554
- */
555
- async validate() {
556
- const errors = [];
557
- // Validate interface
558
- if (!this.interface.name) {
559
- errors.push('Widget type is required');
560
- }
561
- return errors;
562
- }
563
- //#endregion
564
- //#region ---- Utility Methods ----
565
- /**
566
- * Get property capabilities
567
- */
568
- getCapabilities() {
569
- return {
570
- searchable: this.isSearchable(),
571
- fullTextSearchable: this.isFullTextSearchable(),
572
- filterable: this.isFilterable(),
573
- inlineFilterable: this.isInlineFilterable(),
574
- sortable: this.isSortable(),
575
- auditable: this.isAuditable(),
576
- disabled: this.isDisabled()
577
- };
835
+ errors.push(...aggErrors.map((err) => `${aggregate.name}: ${err}`));
836
+ }
837
+ }
838
+ return errors;
578
839
  }
840
+ //#endregion
841
+ //#region ---- Utility Methods ----
579
842
  /**
580
- * Get property summary
843
+ * Get module statistics
844
+ *
845
+ * @returns Statistics object
581
846
  */
582
- getSummary() {
583
- const capabilities = this.getCapabilities();
584
- const capabilityCount = Object.values(capabilities).filter(Boolean).length;
847
+ getStatistics() {
848
+ const aggregateStats = this.aggregates.map(agg => agg.getStatistics());
585
849
  return {
586
- widget: this.interface.name,
587
- hasOptions: !!this.interface.options,
588
- hasMetadata: !!this.metadata,
589
- hasValidations: !!this.validations && this.validations.length > 0,
590
- capabilityCount
850
+ aggregateCount: this.aggregates.length,
851
+ entityCount: aggregateStats.reduce((sum, stat) => sum + stat.entityCount, 0),
852
+ relationCount: aggregateStats.reduce((sum, stat) => sum + stat.relationCount, 0),
853
+ actionCount: aggregateStats.reduce((sum, stat) => sum + stat.actionCount, 0),
854
+ validationCount: aggregateStats.reduce((sum, stat) => sum + stat.validationCount, 0)
591
855
  };
592
856
  }
593
857
  /**
594
858
  * Convert back to interface definition
859
+ *
860
+ * @returns Module definition
595
861
  */
596
862
  toDefinition() {
597
863
  return {
598
864
  name: this.name,
599
865
  title: this.title,
600
- description: this.description,
601
- icon: this.icon,
602
- dataType: this.dataType,
603
- defaultValue: this.defaultValue,
604
- disabled: this.disabled,
605
- interface: this.interface,
606
- validations: this.validations,
607
- features: this.features,
608
- metadata: this.metadata
866
+ aggregates: this.aggregates.map(agg => agg.toDefinition())
609
867
  };
610
868
  }
611
869
  }
612
-
613
- //#region ---- Property definition helpers ----
614
- /**
615
- * Strips entity-only fields so the payload matches {@link AXPPropertyDefinition}.
616
- */
617
- function toPropertyDefinition(def) {
618
- const { actions, fieldFeatures, ...propertyDefinition } = def;
619
- return propertyDefinition;
620
- }
621
870
  //#endregion
871
+
622
872
  //#region ---- AXPEntityFieldModel ----
623
873
  /**
624
874
  * Runtime model for entity field definitions with parent references and helper methods
625
875
  */
626
876
  class AXPEntityFieldModel {
627
- constructor(definition, parent, propertyService) {
628
- this.entityPropertyDefinition = definition;
877
+ constructor(definition, parent, schemaService) {
629
878
  this.name = definition.name;
630
879
  this.title = definition.title;
631
880
  this.description = definition.description;
632
881
  this.validations = definition.validations;
633
882
  this.actions = definition.actions;
634
- this.fieldFeatures = definition.fieldFeatures;
883
+ this.features = definition.features;
635
884
  this.defaultValue = definition.defaultValue;
636
885
  this.parent = parent;
637
- this.propertyService = propertyService;
638
- this.property = new AXPPropertyModel(toPropertyDefinition(definition));
639
- this.propertyName = definition.name;
886
+ this.schemaService = schemaService;
887
+ // Store schema name for toDefinition
888
+ this.schemaName = definition.schema;
889
+ // Resolve schema by name from schema service
890
+ this.schema = schemaService.resolveSync(definition.schema);
640
891
  }
892
+ //#endregion
641
893
  //#region ---- Feature Check Methods ----
642
894
  /**
643
895
  * Check if field is nullable
644
896
  */
645
897
  isNullable() {
646
- return this.fieldFeatures?.nullable ?? false;
898
+ return this.features?.nullable ?? false;
647
899
  }
648
900
  /**
649
901
  * Check if field is readonly
650
902
  */
651
903
  isReadonly() {
652
- return this.fieldFeatures?.readOnly ?? false;
904
+ return this.features?.readOnly ?? false;
653
905
  }
654
906
  /**
655
907
  * Check if field is required (has required validation)
656
908
  */
657
909
  isRequired() {
658
- return this.validations?.some((validation) => validation.rule === "required") ?? false;
910
+ return this.validations?.some(validation => validation.rule === 'required') ?? false;
659
911
  }
660
912
  /**
661
913
  * Check if field is searchable
662
914
  */
663
915
  isSearchable() {
664
- return this.property.features?.searchable?.enabled ?? false;
916
+ return this.schema.features?.searchable?.enabled ?? false;
665
917
  }
666
918
  /**
667
919
  * Check if field supports full text search
668
920
  */
669
921
  isFullTextSearchable() {
670
- return this.property.features?.searchable?.fullText ?? false;
922
+ return this.schema.features?.searchable?.fullText ?? false;
671
923
  }
672
924
  /**
673
925
  * Check if field is filterable
674
926
  */
675
927
  isFilterable() {
676
- return this.property.features?.filterable?.enabled ?? false;
928
+ return this.schema.features?.filterable?.enabled ?? false;
677
929
  }
678
930
  /**
679
931
  * Check if field has inline filtering
680
932
  */
681
933
  hasInlineFiltering() {
682
- return this.property.features?.filterable?.inline ?? false;
934
+ return this.schema.features?.filterable?.inline ?? false;
683
935
  }
684
936
  /**
685
937
  * Check if field is sortable
686
938
  */
687
939
  isSortable() {
688
- return this.property.features?.sortable?.enabled ?? false;
940
+ return this.schema.features?.sortable?.enabled ?? false;
689
941
  }
690
942
  /**
691
943
  * Check if field is auditable
692
944
  */
693
945
  isAuditable() {
694
- return this.property.features?.auditable?.enabled ?? false;
946
+ return this.schema.features?.auditable?.enabled ?? false;
695
947
  }
696
948
  //#endregion
697
- //#region ---- Property info ----
949
+ //#region ---- Schema Methods ----
698
950
  /**
699
- * Registered property name (same as entity field name in the embedded model).
951
+ * Get the schema name
700
952
  */
701
- getPropertyName() {
702
- return this.propertyName;
953
+ getSchemaName() {
954
+ return this.schemaName;
703
955
  }
704
956
  /**
705
- * Registration metadata when this field's definition name is registered; otherwise embedded summary.
957
+ * Get schema info from registry
706
958
  */
707
- getPropertyInfo() {
708
- if (this.propertyService.isRegistered(this.property.name)) {
709
- return this.propertyService.getRegisteredProperty(this.property.name);
710
- }
711
- return this.property.getSummary();
959
+ getSchemaInfo() {
960
+ return this.schemaService.getSchemaInfo(this.schemaName);
712
961
  }
713
962
  /**
714
- * Rebuild the property model from embedded definition (e.g. after definition updates).
963
+ * Re-resolve schema from registry (useful after schema updates)
715
964
  */
716
- refreshProperty() {
717
- this.property = new AXPPropertyModel(toPropertyDefinition(this.entityPropertyDefinition));
965
+ refreshSchema() {
966
+ const newSchema = this.schemaService.resolveSync(this.schemaName);
967
+ this.schema = newSchema;
968
+ this.schema.parent = this;
718
969
  }
719
970
  //#endregion
720
971
  //#region ---- Navigation Methods ----
@@ -749,17 +1000,25 @@ class AXPEntityFieldModel {
749
1000
  */
750
1001
  async validate() {
751
1002
  const errors = [];
1003
+ // Validate field structure
752
1004
  if (!this.name)
753
- errors.push("Field name is required");
1005
+ errors.push('Field name is required');
754
1006
  if (!this.title)
755
- errors.push("Field title is required");
756
- if (!this.property.interface?.name) {
757
- errors.push("Widget type (interface.name) is required");
758
- }
759
- if (this.property) {
760
- const propertyErrors = await this.property.validate();
761
- if (propertyErrors.length > 0) {
762
- errors.push(...propertyErrors.map((err) => `Property: ${err}`));
1007
+ errors.push('Field title is required');
1008
+ // Validate schema name
1009
+ if (!this.schemaName) {
1010
+ errors.push('Schema name is required');
1011
+ }
1012
+ else {
1013
+ if (!this.schemaService.isRegistered(this.schemaName)) {
1014
+ errors.push(`Schema '${this.schemaName}' is not registered`);
1015
+ }
1016
+ }
1017
+ // Validate schema if it exists
1018
+ if (this.schema) {
1019
+ const schemaErrors = await this.schema.validate();
1020
+ if (schemaErrors.length > 0) {
1021
+ errors.push(...schemaErrors.map(err => `Schema: ${err}`));
763
1022
  }
764
1023
  }
765
1024
  return errors;
@@ -773,10 +1032,10 @@ class AXPEntityFieldModel {
773
1032
  return {
774
1033
  hasValidations: !!this.validations && this.validations.length > 0,
775
1034
  hasActions: !!this.actions && this.actions.length > 0,
776
- hasFieldFeatures: !!this.fieldFeatures,
1035
+ hasFeatures: !!this.features,
777
1036
  hasDefaultValue: this.defaultValue !== undefined,
778
1037
  validationCount: this.validations?.length ?? 0,
779
- actionCount: this.actions?.length ?? 0,
1038
+ actionCount: this.actions?.length ?? 0
780
1039
  };
781
1040
  }
782
1041
  /**
@@ -790,7 +1049,7 @@ class AXPEntityFieldModel {
790
1049
  auditable: this.isAuditable(),
791
1050
  nullable: this.isNullable(),
792
1051
  readonly: this.isReadonly(),
793
- required: this.isRequired(),
1052
+ required: this.isRequired()
794
1053
  };
795
1054
  }
796
1055
  /**
@@ -798,28 +1057,32 @@ class AXPEntityFieldModel {
798
1057
  */
799
1058
  toDefinition() {
800
1059
  return {
801
- ...this.property.toDefinition(),
1060
+ name: this.name,
1061
+ title: this.title,
1062
+ description: this.description,
1063
+ validations: this.validations,
802
1064
  actions: this.actions,
803
- fieldFeatures: this.fieldFeatures,
1065
+ features: this.features,
1066
+ defaultValue: this.defaultValue,
1067
+ schema: this.schemaName
804
1068
  };
805
1069
  }
806
1070
  }
807
- //#endregion
808
1071
 
809
1072
  //#region ---- AXPEntityModel ----
810
1073
  /**
811
1074
  * Runtime model for entity definitions with parent references and helper methods
812
1075
  */
813
1076
  class AXPEntityModel {
814
- constructor(definition, parent, propertyService) {
1077
+ constructor(definition, parent, schemaService) {
815
1078
  this.fields = [];
816
1079
  this.name = definition.name;
817
1080
  this.title = definition.title;
818
1081
  this.type = definition.type;
819
1082
  this.parent = parent;
820
- this.propertyService = propertyService;
821
- // Initialize fields with parent reference and property service
822
- this.fields = definition.fields.map(fieldDef => new AXPEntityFieldModel(fieldDef, this, propertyService));
1083
+ this.schemaService = schemaService;
1084
+ // Initialize fields with parent reference and schema service
1085
+ this.fields = definition.fields.map(fieldDef => new AXPEntityFieldModel(fieldDef, this, schemaService));
823
1086
  }
824
1087
  //#endregion
825
1088
  //#region ---- Query Methods ----
@@ -835,6 +1098,12 @@ class AXPEntityModel {
835
1098
  getAllFields() {
836
1099
  return [...this.fields];
837
1100
  }
1101
+ /**
1102
+ * Get fields by data type
1103
+ */
1104
+ getFieldsByType(dataType) {
1105
+ return this.fields.filter(field => field.schema.dataType === dataType);
1106
+ }
838
1107
  /**
839
1108
  * Get required fields
840
1109
  */
@@ -954,196 +1223,181 @@ class AXPEntityModel {
954
1223
  }
955
1224
  }
956
1225
 
957
- //#region ---- AXPRelationModel ----
1226
+ //#region ---- AXPSchemaModel ----
958
1227
  /**
959
- * Runtime model for standalone relation definitions.
960
- * Relations live in their own collection; join when needed.
1228
+ * Runtime model for schema definitions with helper methods
961
1229
  */
962
- class AXPRelationModel {
963
- constructor(definition, parent) {
964
- this.type = definition.type;
965
- this.kind = definition.kind;
966
- this.target = { ...definition.target };
967
- this.source = { ...definition.source };
968
- this.isRequired = definition.isRequired;
969
- this.parent = parent;
1230
+ class AXPSchemaModel {
1231
+ constructor(definition) {
1232
+ this.name = definition.name;
1233
+ this.dataType = definition.dataType;
1234
+ this.interface = definition.interface;
1235
+ this.validations = definition.validations ?? [];
1236
+ this.features = definition.features ?? {};
1237
+ this.metadata = definition.metadata;
970
1238
  }
971
1239
  //#endregion
972
- //#region ---- Cardinality Methods ----
1240
+ //#region ---- Data Type Methods ----
973
1241
  /**
974
- * Check if relation is one-to-one
1242
+ * Check if schema is for string data
975
1243
  */
976
- isOneToOne() {
977
- return this.type === AXPRelationshipCardinality.OneToOne;
1244
+ isString() {
1245
+ return this.dataType === 'string';
978
1246
  }
979
1247
  /**
980
- * Check if relation is one-to-many
1248
+ * Check if schema is for number data
981
1249
  */
982
- isOneToMany() {
983
- return this.type === AXPRelationshipCardinality.OneToMany;
1250
+ isNumber() {
1251
+ return this.dataType === 'number';
984
1252
  }
985
1253
  /**
986
- * Check if relation is many-to-many
1254
+ * Check if schema is for boolean data
987
1255
  */
988
- isManyToMany() {
989
- return this.type === AXPRelationshipCardinality.ManyToMany;
1256
+ isBoolean() {
1257
+ return this.dataType === 'boolean';
990
1258
  }
991
- //#endregion
992
- //#region ---- Kind Methods ----
993
1259
  /**
994
- * Check if relation is association
1260
+ * Check if schema is for date data
995
1261
  */
996
- isAssociation() {
997
- return this.kind === AXPRelationshipKind.Association;
1262
+ isDate() {
1263
+ return this.dataType === 'date';
998
1264
  }
999
1265
  /**
1000
- * Check if relation is composition
1266
+ * Check if schema is for object data
1001
1267
  */
1002
- isComposition() {
1003
- return this.kind === AXPRelationshipKind.Composition;
1268
+ isObject() {
1269
+ return this.dataType === 'object';
1004
1270
  }
1005
1271
  /**
1006
- * Check if relation is aggregation
1272
+ * Check if schema is for array data
1007
1273
  */
1008
- isAggregation() {
1009
- return this.kind === AXPRelationshipKind.Aggregation;
1274
+ isArray() {
1275
+ return this.dataType === 'array';
1276
+ }
1277
+ /**
1278
+ * Check if schema is for blob data
1279
+ */
1280
+ isBlob() {
1281
+ return this.dataType === 'blob';
1010
1282
  }
1011
1283
  //#endregion
1012
- //#region ---- Navigation Methods ----
1284
+ //#region ---- Interface Methods ----
1013
1285
  /**
1014
- * Get parent aggregate
1286
+ * Get widget type
1015
1287
  */
1016
- getAggregate() {
1017
- return this.parent;
1288
+ getWidgetType() {
1289
+ return this.interface.widget;
1018
1290
  }
1019
1291
  /**
1020
- * Get parent module
1292
+ * Get widget options
1021
1293
  */
1022
- getModule() {
1023
- return this.parent?.parent;
1294
+ getWidgetOptions() {
1295
+ return this.interface.options;
1024
1296
  }
1025
1297
  /**
1026
- * Get full path (module.aggregate.relation)
1298
+ * Check if interface is disabled
1027
1299
  */
1028
- getPath() {
1029
- return `${this.parent.parent.name}.${this.parent.name}.${this.source.entity}->${this.target.entity}`;
1300
+ isDisabled() {
1301
+ return this.interface.disabled ?? false;
1030
1302
  }
1031
1303
  //#endregion
1032
- //#region ---- Query Methods ----
1304
+ //#region ---- Feature Methods ----
1033
1305
  /**
1034
- * Get relation description
1306
+ * Check if searchable
1035
1307
  */
1036
- getDescription() {
1037
- const cardinalityDesc = this.getCardinalityDescription();
1038
- const kindDesc = this.getKindDescription();
1039
- const requiredDesc = this.isRequired ? 'required' : 'optional';
1040
- return `${cardinalityDesc} ${kindDesc} (${requiredDesc})`;
1308
+ isSearchable() {
1309
+ return this.features.searchable?.enabled ?? false;
1041
1310
  }
1042
1311
  /**
1043
- * Get cardinality description
1312
+ * Check if full text searchable
1044
1313
  */
1045
- getCardinalityDescription() {
1046
- switch (this.type) {
1047
- case AXPRelationshipCardinality.OneToOne:
1048
- return 'one-to-one';
1049
- case AXPRelationshipCardinality.OneToMany:
1050
- return 'one-to-many';
1051
- case AXPRelationshipCardinality.ManyToMany:
1052
- return 'many-to-many';
1053
- default:
1054
- return 'unknown';
1055
- }
1314
+ isFullTextSearchable() {
1315
+ return this.features.searchable?.fullText ?? false;
1056
1316
  }
1057
1317
  /**
1058
- * Get kind description
1318
+ * Check if filterable
1059
1319
  */
1060
- getKindDescription() {
1061
- switch (this.kind) {
1062
- case AXPRelationshipKind.Association:
1063
- return 'association';
1064
- case AXPRelationshipKind.Composition:
1065
- return 'composition';
1066
- case AXPRelationshipKind.Aggregation:
1067
- return 'aggregation';
1068
- default:
1069
- return 'unknown';
1070
- }
1320
+ isFilterable() {
1321
+ return this.features.filterable?.enabled ?? false;
1071
1322
  }
1072
1323
  /**
1073
- * Get relation summary
1324
+ * Check if inline filterable
1074
1325
  */
1075
- getSummary() {
1076
- return `${this.source.entity}.${this.source.key} -> ${this.target.aggregate}.${this.target.entity}.${this.target.key}`;
1326
+ isInlineFilterable() {
1327
+ return this.features.filterable?.inline ?? false;
1328
+ }
1329
+ /**
1330
+ * Check if sortable
1331
+ */
1332
+ isSortable() {
1333
+ return this.features.sortable?.enabled ?? false;
1334
+ }
1335
+ /**
1336
+ * Check if auditable
1337
+ */
1338
+ isAuditable() {
1339
+ return this.features.auditable?.enabled ?? false;
1077
1340
  }
1078
1341
  //#endregion
1079
1342
  //#region ---- Validation Methods ----
1080
1343
  /**
1081
- * Validate the relation structure
1344
+ * Validate the schema structure
1082
1345
  */
1083
- validate() {
1346
+ async validate() {
1084
1347
  const errors = [];
1085
- // Validate source
1086
- if (!this.source.entity)
1087
- errors.push('Source entity is required');
1088
- if (!this.source.key)
1089
- errors.push('Source key is required');
1090
- // Validate target
1091
- if (!this.target.aggregate)
1092
- errors.push('Target aggregate is required');
1093
- if (!this.target.entity)
1094
- errors.push('Target entity is required');
1095
- if (!this.target.key)
1096
- errors.push('Target key is required');
1348
+ // Validate data type
1349
+ const validDataTypes = ['string', 'number', 'boolean', 'date', 'object', 'array', 'blob'];
1350
+ if (!validDataTypes.includes(this.dataType)) {
1351
+ errors.push(`Invalid data type: ${this.dataType}`);
1352
+ }
1353
+ // Validate interface
1354
+ if (!this.interface.widget) {
1355
+ errors.push('Widget type is required');
1356
+ }
1097
1357
  return errors;
1098
1358
  }
1099
1359
  //#endregion
1100
1360
  //#region ---- Utility Methods ----
1101
1361
  /**
1102
- * Get relation characteristics
1362
+ * Get schema capabilities
1103
1363
  */
1104
- getCharacteristics() {
1364
+ getCapabilities() {
1105
1365
  return {
1106
- type: this.getCardinalityDescription(),
1107
- kind: this.getKindDescription(),
1108
- required: this.isRequired,
1109
- isOwning: this.isComposition(),
1110
- isNavigable: !this.isComposition() || this.isOneToOne()
1366
+ searchable: this.isSearchable(),
1367
+ fullTextSearchable: this.isFullTextSearchable(),
1368
+ filterable: this.isFilterable(),
1369
+ inlineFilterable: this.isInlineFilterable(),
1370
+ sortable: this.isSortable(),
1371
+ auditable: this.isAuditable(),
1372
+ disabled: this.isDisabled()
1111
1373
  };
1112
1374
  }
1113
1375
  /**
1114
- * Check if relation involves entity
1115
- */
1116
- involvesEntity(entityName) {
1117
- return this.source.entity === entityName || this.target.entity === entityName;
1118
- }
1119
- /**
1120
- * Check if relation targets aggregate
1121
- */
1122
- targetsAggregate(aggregateName) {
1123
- return this.target.aggregate === aggregateName;
1124
- }
1125
- /**
1126
- * Get the other entity in the relation
1376
+ * Get schema summary
1127
1377
  */
1128
- getOtherEntity(entityName) {
1129
- if (this.source.entity === entityName) {
1130
- return this.target.entity;
1131
- }
1132
- else if (this.target.entity === entityName) {
1133
- return this.source.entity;
1134
- }
1135
- return null;
1378
+ getSummary() {
1379
+ const capabilities = this.getCapabilities();
1380
+ const capabilityCount = Object.values(capabilities).filter(Boolean).length;
1381
+ return {
1382
+ dataType: this.dataType,
1383
+ widget: this.getWidgetType(),
1384
+ hasOptions: !!this.interface.options,
1385
+ hasMetadata: !!this.metadata,
1386
+ hasValidations: !!this.validations && this.validations.length > 0,
1387
+ capabilityCount
1388
+ };
1136
1389
  }
1137
1390
  /**
1138
- * Convert back to interface definition (AXPRelationDefinition with full source/target)
1391
+ * Convert back to interface definition
1139
1392
  */
1140
1393
  toDefinition() {
1141
1394
  return {
1142
- type: this.type,
1143
- kind: this.kind,
1144
- target: { ...this.target },
1145
- source: { ...this.source },
1146
- isRequired: this.isRequired
1395
+ name: this.name,
1396
+ dataType: this.dataType,
1397
+ interface: this.interface,
1398
+ validations: this.validations,
1399
+ features: this.features,
1400
+ metadata: this.metadata
1147
1401
  };
1148
1402
  }
1149
1403
  }
@@ -1217,10 +1471,10 @@ class AXPModuleHelper {
1217
1471
  return [];
1218
1472
  }
1219
1473
  /**
1220
- * @deprecated Use AXPDomainService with registered property name queries instead
1474
+ * @deprecated Use AXPDomainService with field schema queries instead
1221
1475
  */
1222
- static findFieldsByRegisteredPropertyName(module, propertyName) {
1223
- console.warn('AXPModuleHelper.findFieldsByRegisteredPropertyName is deprecated. Use AXPDomainService instead.');
1476
+ static findFieldsBySchema(module, schemaName) {
1477
+ console.warn('AXPModuleHelper.findFieldsBySchema is deprecated. Use AXPDomainService instead.');
1224
1478
  return [];
1225
1479
  }
1226
1480
  /**
@@ -1291,23 +1545,23 @@ class AXPModuleHelper {
1291
1545
  * }
1292
1546
  * ```
1293
1547
  */
1294
- class AXPPropertyMiddlewareContext {
1295
- constructor(definition) {
1296
- // Deep clone to avoid mutating the original definition
1297
- this._definition = JSON.parse(JSON.stringify(definition));
1548
+ class AXPSchemaMiddlewareContext {
1549
+ constructor(schema) {
1550
+ // Deep clone to avoid mutating the original schema
1551
+ this._schema = JSON.parse(JSON.stringify(schema));
1298
1552
  }
1299
1553
  //#region ---- Schema Access Properties ----
1300
1554
  /**
1301
1555
  * Get the current schema definition (readonly access)
1302
1556
  */
1303
- get definition() {
1304
- return this._definition;
1557
+ get schema() {
1558
+ return this._schema;
1305
1559
  }
1306
1560
  /**
1307
1561
  * Get the schema name for conditional logic
1308
1562
  */
1309
1563
  get name() {
1310
- return this._definition.name;
1564
+ return this._schema.name;
1311
1565
  }
1312
1566
  //#endregion
1313
1567
  //#region ---- Default Value Management ----
@@ -1316,18 +1570,18 @@ class AXPPropertyMiddlewareContext {
1316
1570
  * @param defaultValue The default value to set
1317
1571
  */
1318
1572
  withDefaultValue(defaultValue) {
1319
- if (!this._definition.interface.options) {
1320
- this._definition.interface.options = {};
1573
+ if (!this._schema.interface.options) {
1574
+ this._schema.interface.options = {};
1321
1575
  }
1322
- this._definition.interface.options['defaultValue'] = defaultValue;
1576
+ this._schema.interface.options['defaultValue'] = defaultValue;
1323
1577
  return this;
1324
1578
  }
1325
1579
  /**
1326
1580
  * Remove the default value from the widget
1327
1581
  */
1328
1582
  removeDefaultValue() {
1329
- if (this._definition.interface.options) {
1330
- delete this._definition.interface.options['defaultValue'];
1583
+ if (this._schema.interface.options) {
1584
+ delete this._schema.interface.options['defaultValue'];
1331
1585
  }
1332
1586
  return this;
1333
1587
  }
@@ -1338,10 +1592,10 @@ class AXPPropertyMiddlewareContext {
1338
1592
  * @param rules Array of validation rules to add
1339
1593
  */
1340
1594
  withValidation(rules) {
1341
- if (!this._definition.validations) {
1342
- this._definition.validations = [];
1595
+ if (!this._schema.validations) {
1596
+ this._schema.validations = [];
1343
1597
  }
1344
- this._definition.validations.push(...rules);
1598
+ this._schema.validations.push(...rules);
1345
1599
  return this;
1346
1600
  }
1347
1601
  /**
@@ -1349,10 +1603,10 @@ class AXPPropertyMiddlewareContext {
1349
1603
  * @param rule The validation rule to add
1350
1604
  */
1351
1605
  addValidation(rule) {
1352
- if (!this._definition.validations) {
1353
- this._definition.validations = [];
1606
+ if (!this._schema.validations) {
1607
+ this._schema.validations = [];
1354
1608
  }
1355
- this._definition.validations.push(rule);
1609
+ this._schema.validations.push(rule);
1356
1610
  return this;
1357
1611
  }
1358
1612
  /**
@@ -1366,7 +1620,7 @@ class AXPPropertyMiddlewareContext {
1366
1620
  * Remove all validation rules from the schema
1367
1621
  */
1368
1622
  clearValidations() {
1369
- this._definition.validations = [];
1623
+ this._schema.validations = [];
1370
1624
  return this;
1371
1625
  }
1372
1626
  /**
@@ -1374,8 +1628,8 @@ class AXPPropertyMiddlewareContext {
1374
1628
  * @param ruleName The name of the rule to remove (e.g., 'required', 'email')
1375
1629
  */
1376
1630
  removeValidation(ruleName) {
1377
- if (this._definition.validations) {
1378
- this._definition.validations = this._definition.validations.filter((v) => v.rule !== ruleName);
1631
+ if (this._schema.validations) {
1632
+ this._schema.validations = this._schema.validations.filter(v => v.rule !== ruleName);
1379
1633
  }
1380
1634
  return this;
1381
1635
  }
@@ -1386,9 +1640,8 @@ class AXPPropertyMiddlewareContext {
1386
1640
  * @param options Object containing widget-specific options to merge
1387
1641
  */
1388
1642
  withWidgetOptions(options) {
1389
- const current = this._definition.interface.options ?? {};
1390
- this._definition.interface.options = {
1391
- ...current,
1643
+ this._schema.interface.options = {
1644
+ ...this._schema.interface.options,
1392
1645
  ...options
1393
1646
  };
1394
1647
  return this;
@@ -1398,8 +1651,8 @@ class AXPPropertyMiddlewareContext {
1398
1651
  * @param optionKey The key of the option to remove
1399
1652
  */
1400
1653
  removeWidgetOption(optionKey) {
1401
- if (this._definition.interface.options) {
1402
- delete this._definition.interface.options[optionKey];
1654
+ if (this._schema.interface.options) {
1655
+ delete this._schema.interface.options[optionKey];
1403
1656
  }
1404
1657
  return this;
1405
1658
  }
@@ -1408,7 +1661,7 @@ class AXPPropertyMiddlewareContext {
1408
1661
  * @param widgetType The new widget type identifier
1409
1662
  */
1410
1663
  withWidgetType(widgetType) {
1411
- this._definition.interface.name = widgetType;
1664
+ this._schema.interface.widget = widgetType;
1412
1665
  return this;
1413
1666
  }
1414
1667
  //#endregion
@@ -1418,8 +1671,8 @@ class AXPPropertyMiddlewareContext {
1418
1671
  * @param features Object containing feature configurations to merge
1419
1672
  */
1420
1673
  withFeatures(features) {
1421
- this._definition.features = {
1422
- ...this._definition.features,
1674
+ this._schema.features = {
1675
+ ...this._schema.features,
1423
1676
  ...features
1424
1677
  };
1425
1678
  return this;
@@ -1430,10 +1683,10 @@ class AXPPropertyMiddlewareContext {
1430
1683
  * @param fullText Whether full-text search is enabled
1431
1684
  */
1432
1685
  searchable(enabled = true, fullText = false) {
1433
- if (!this._definition.features) {
1434
- this._definition.features = {};
1686
+ if (!this._schema.features) {
1687
+ this._schema.features = {};
1435
1688
  }
1436
- this._definition.features.searchable = { enabled, fullText };
1689
+ this._schema.features.searchable = { enabled, fullText };
1437
1690
  return this;
1438
1691
  }
1439
1692
  /**
@@ -1442,10 +1695,10 @@ class AXPPropertyMiddlewareContext {
1442
1695
  * @param inline Whether inline filtering is supported
1443
1696
  */
1444
1697
  filterable(enabled = true, inline = false) {
1445
- if (!this._definition.features) {
1446
- this._definition.features = {};
1698
+ if (!this._schema.features) {
1699
+ this._schema.features = {};
1447
1700
  }
1448
- this._definition.features.filterable = { enabled, inline };
1701
+ this._schema.features.filterable = { enabled, inline };
1449
1702
  return this;
1450
1703
  }
1451
1704
  /**
@@ -1453,10 +1706,10 @@ class AXPPropertyMiddlewareContext {
1453
1706
  * @param enabled Whether sorting is enabled
1454
1707
  */
1455
1708
  sortable(enabled = true) {
1456
- if (!this._definition.features) {
1457
- this._definition.features = {};
1709
+ if (!this._schema.features) {
1710
+ this._schema.features = {};
1458
1711
  }
1459
- this._definition.features.sortable = { enabled };
1712
+ this._schema.features.sortable = { enabled };
1460
1713
  return this;
1461
1714
  }
1462
1715
  //#endregion
@@ -1466,8 +1719,8 @@ class AXPPropertyMiddlewareContext {
1466
1719
  * @param metadata Object containing metadata to merge
1467
1720
  */
1468
1721
  withMetadata(metadata) {
1469
- this._definition.metadata = {
1470
- ...this._definition.metadata,
1722
+ this._schema.metadata = {
1723
+ ...this._schema.metadata,
1471
1724
  ...metadata
1472
1725
  };
1473
1726
  return this;
@@ -1477,19 +1730,29 @@ class AXPPropertyMiddlewareContext {
1477
1730
  * @param key The metadata key to remove
1478
1731
  */
1479
1732
  removeMetadata(key) {
1480
- if (this._definition.metadata) {
1481
- delete this._definition.metadata[key];
1733
+ if (this._schema.metadata) {
1734
+ delete this._schema.metadata[key];
1482
1735
  }
1483
1736
  return this;
1484
1737
  }
1485
1738
  //#endregion
1739
+ //#region ---- Schema Properties ----
1740
+ /**
1741
+ * Set the data type for this schema
1742
+ * @param dataType The new data type (string, number, boolean, etc.)
1743
+ */
1744
+ withDataType(dataType) {
1745
+ this._schema.dataType = dataType;
1746
+ return this;
1747
+ }
1748
+ //#endregion
1486
1749
  //#region ---- UI State Management ----
1487
1750
  /**
1488
1751
  * Set the disabled state of the widget
1489
1752
  * @param isDisabled Whether the widget should be disabled
1490
1753
  */
1491
1754
  disabled(isDisabled = true) {
1492
- this._definition.disabled = isDisabled;
1755
+ this._schema.interface.disabled = isDisabled;
1493
1756
  return this;
1494
1757
  }
1495
1758
  /**
@@ -1497,10 +1760,10 @@ class AXPPropertyMiddlewareContext {
1497
1760
  * @param visible Whether the widget should be visible
1498
1761
  */
1499
1762
  withVisibility(visible) {
1500
- if (!this._definition.interface.options) {
1501
- this._definition.interface.options = {};
1763
+ if (!this._schema.interface.options) {
1764
+ this._schema.interface.options = {};
1502
1765
  }
1503
- this._definition.interface.options['visible'] = visible;
1766
+ this._schema.interface.options['visible'] = visible;
1504
1767
  return this;
1505
1768
  }
1506
1769
  /**
@@ -1508,10 +1771,10 @@ class AXPPropertyMiddlewareContext {
1508
1771
  * @param isReadonly Whether the widget should be readonly
1509
1772
  */
1510
1773
  readonly(isReadonly = true) {
1511
- if (!this._definition.interface.options) {
1512
- this._definition.interface.options = {};
1774
+ if (!this._schema.interface.options) {
1775
+ this._schema.interface.options = {};
1513
1776
  }
1514
- this._definition.interface.options['readonly'] = isReadonly;
1777
+ this._schema.interface.options['readonly'] = isReadonly;
1515
1778
  return this;
1516
1779
  }
1517
1780
  }
@@ -1529,9 +1792,9 @@ class AXPPropertyMiddlewareContext {
1529
1792
  * - On-demand schema loading
1530
1793
  * - Caching and performance optimization
1531
1794
  */
1532
- class AXPPropertyRegistry {
1795
+ class AXPSchemaRegistry {
1533
1796
  constructor() {
1534
- this._registrations = new Map();
1797
+ this._schemas = new Map();
1535
1798
  this._globalMiddleware = [];
1536
1799
  this._modelCache = new Map();
1537
1800
  this._loaders = null;
@@ -1542,7 +1805,7 @@ class AXPPropertyRegistry {
1542
1805
  */
1543
1806
  register(definition, options = {}) {
1544
1807
  if (!definition.name || definition.name.trim() === '') {
1545
- throw new Error('Property name is required and cannot be empty');
1808
+ throw new Error('Schema name is required and cannot be empty');
1546
1809
  }
1547
1810
  const registered = {
1548
1811
  name: definition.name,
@@ -1550,22 +1813,23 @@ class AXPPropertyRegistry {
1550
1813
  options,
1551
1814
  registeredAt: new Date()
1552
1815
  };
1553
- this._registrations.set(definition.name, registered);
1816
+ this._schemas.set(definition.name, registered);
1554
1817
  this.invalidateCache(definition.name);
1818
+ console.log(`Schema '${definition.name}' registered successfully`);
1555
1819
  }
1556
1820
  /**
1557
1821
  * Register multiple schemas at once for batch operations
1558
1822
  */
1559
- registerBatch(entries) {
1560
- for (const entry of entries) {
1561
- this.register(entry.definition, entry.options || {});
1823
+ registerBatch(schemas) {
1824
+ for (const schema of schemas) {
1825
+ this.register(schema.definition, schema.options || {});
1562
1826
  }
1563
1827
  }
1564
1828
  /**
1565
1829
  * Remove a schema from the registry
1566
1830
  */
1567
1831
  unregister(name) {
1568
- const removed = this._registrations.delete(name);
1832
+ const removed = this._schemas.delete(name);
1569
1833
  if (removed) {
1570
1834
  this.invalidateCache(name);
1571
1835
  }
@@ -1575,7 +1839,7 @@ class AXPPropertyRegistry {
1575
1839
  * Check if a schema is currently registered
1576
1840
  */
1577
1841
  isRegistered(name) {
1578
- return this._registrations.has(name);
1842
+ return this._schemas.has(name);
1579
1843
  }
1580
1844
  //#endregion
1581
1845
  //#region ---- Resolution Methods ----
@@ -1589,7 +1853,7 @@ class AXPPropertyRegistry {
1589
1853
  return this._modelCache.get(name);
1590
1854
  }
1591
1855
  // Try to get from registered schemas first
1592
- let registered = this._registrations.get(name);
1856
+ let registered = this._schemas.get(name);
1593
1857
  // If not found, attempt on-demand loading
1594
1858
  if (!registered) {
1595
1859
  const definition = await this.loadFromLoaders(name);
@@ -1600,27 +1864,27 @@ class AXPPropertyRegistry {
1600
1864
  options: {},
1601
1865
  registeredAt: new Date()
1602
1866
  };
1603
- this._registrations.set(name, registered);
1867
+ this._schemas.set(name, registered);
1604
1868
  }
1605
1869
  else {
1606
- throw new Error(`Property '${name}' is not registered and no loader can provide it`);
1870
+ throw new Error(`Schema '${name}' is not registered and no loader can provide it`);
1607
1871
  }
1608
1872
  }
1609
1873
  // Clone and process through middleware pipeline
1610
- const definition = this.cloneDefinition(registered.definition);
1611
- const context = new AXPPropertyMiddlewareContext(definition);
1874
+ const schema = this.cloneDefinition(registered.definition);
1875
+ const context = new AXPSchemaMiddlewareContext(schema);
1612
1876
  // Apply global middleware first
1613
1877
  for (const middleware of this._globalMiddleware) {
1614
1878
  await middleware(context);
1615
1879
  }
1616
- // Apply registration-specific middleware
1880
+ // Apply schema-specific middleware
1617
1881
  if (registered.options.middleware) {
1618
1882
  for (const middleware of registered.options.middleware) {
1619
1883
  await middleware(context);
1620
1884
  }
1621
1885
  }
1622
1886
  // Create final model and cache it
1623
- const model = new AXPPropertyModel(context.definition);
1887
+ const model = new AXPSchemaModel(context.schema);
1624
1888
  this._modelCache.set(name, model);
1625
1889
  return model;
1626
1890
  }
@@ -1629,11 +1893,11 @@ class AXPPropertyRegistry {
1629
1893
  * Use only when middleware is not needed for performance.
1630
1894
  */
1631
1895
  resolveSync(name) {
1632
- const registered = this._registrations.get(name);
1896
+ const registered = this._schemas.get(name);
1633
1897
  if (!registered) {
1634
- throw new Error(`Property '${name}' is not registered`);
1898
+ throw new Error(`Schema '${name}' is not registered`);
1635
1899
  }
1636
- return new AXPPropertyModel(this.cloneDefinition(registered.definition));
1900
+ return new AXPSchemaModel(this.cloneDefinition(registered.definition));
1637
1901
  }
1638
1902
  //#endregion
1639
1903
  //#region ---- Middleware Management ----
@@ -1680,52 +1944,52 @@ class AXPPropertyRegistry {
1680
1944
  * Get all registered schema names
1681
1945
  */
1682
1946
  getRegisteredNames() {
1683
- return Array.from(this._registrations.keys());
1947
+ return Array.from(this._schemas.keys());
1684
1948
  }
1685
1949
  /**
1686
1950
  * Get detailed registration information for a schema
1687
1951
  */
1688
- getRegisteredProperty(name) {
1689
- return this._registrations.get(name);
1952
+ getSchemaInfo(name) {
1953
+ return this._schemas.get(name);
1690
1954
  }
1691
1955
  /**
1692
- * Get all registered properties with their metadata
1956
+ * Get all registered schemas with their metadata
1693
1957
  */
1694
- getAllRegisteredProperties() {
1695
- return Array.from(this._registrations.values());
1958
+ getAllSchemas() {
1959
+ return Array.from(this._schemas.values());
1696
1960
  }
1697
1961
  /**
1698
- * Find registered properties by tag for categorization
1962
+ * Find schemas by tag for categorization
1699
1963
  */
1700
1964
  findByTag(tag) {
1701
- return Array.from(this._registrations.values()).filter((registration) => registration.options.tags?.includes(tag));
1965
+ return Array.from(this._schemas.values()).filter(schema => schema.options.tags?.includes(tag));
1702
1966
  }
1703
1967
  /**
1704
- * Find registered properties by widget type for widget-specific operations
1968
+ * Find schemas by widget type for widget-specific operations
1705
1969
  */
1706
1970
  findByWidget(widgetType) {
1707
- return Array.from(this._registrations.values()).filter((registration) => registration.definition.interface.name === widgetType);
1971
+ return Array.from(this._schemas.values()).filter(schema => schema.definition.interface.widget === widgetType);
1708
1972
  }
1709
1973
  /**
1710
1974
  * Get comprehensive registry statistics
1711
1975
  */
1712
1976
  getStatistics() {
1713
- const propertiesByWidget = {};
1714
- const propertiesByTag = {};
1715
- for (const registration of this._registrations.values()) {
1716
- const widget = registration.definition.interface.name;
1717
- propertiesByWidget[widget] = (propertiesByWidget[widget] || 0) + 1;
1718
- if (registration.options.tags) {
1719
- for (const tag of registration.options.tags) {
1720
- propertiesByTag[tag] = (propertiesByTag[tag] || 0) + 1;
1977
+ const schemasByWidget = {};
1978
+ const schemasByTag = {};
1979
+ for (const schema of this._schemas.values()) {
1980
+ const widget = schema.definition.interface.widget;
1981
+ schemasByWidget[widget] = (schemasByWidget[widget] || 0) + 1;
1982
+ if (schema.options.tags) {
1983
+ for (const tag of schema.options.tags) {
1984
+ schemasByTag[tag] = (schemasByTag[tag] || 0) + 1;
1721
1985
  }
1722
1986
  }
1723
1987
  }
1724
1988
  return {
1725
- propertyCount: this._registrations.size,
1989
+ schemaCount: this._schemas.size,
1726
1990
  globalMiddlewareCount: this._globalMiddleware.length,
1727
- propertiesByWidget,
1728
- propertiesByTag
1991
+ schemasByWidget,
1992
+ schemasByTag
1729
1993
  };
1730
1994
  }
1731
1995
  //#endregion
@@ -1746,7 +2010,7 @@ class AXPPropertyRegistry {
1746
2010
  * Clear all registered schemas, middleware, and cached models
1747
2011
  */
1748
2012
  clear() {
1749
- this._registrations.clear();
2013
+ this._schemas.clear();
1750
2014
  this._globalMiddleware.length = 0;
1751
2015
  this._modelCache.clear();
1752
2016
  this._loaders = null;
@@ -1763,7 +2027,7 @@ class AXPPropertyRegistry {
1763
2027
  try {
1764
2028
  const definition = await loader.load(name);
1765
2029
  if (definition) {
1766
- console.log(`Property '${name}' loaded from ${loader.constructor.name}`);
2030
+ console.log(`Schema '${name}' loaded from ${loader.constructor.name}`);
1767
2031
  return definition;
1768
2032
  }
1769
2033
  }
@@ -1789,7 +2053,7 @@ class AXPPropertyRegistry {
1789
2053
  });
1790
2054
  }
1791
2055
  catch (error) {
1792
- console.warn('Failed to initialize property loaders:', error);
2056
+ console.warn('Failed to initialize schema loaders:', error);
1793
2057
  this._loaders = [];
1794
2058
  }
1795
2059
  }
@@ -1801,89 +2065,90 @@ class AXPPropertyRegistry {
1801
2065
  cloneDefinition(definition) {
1802
2066
  return JSON.parse(JSON.stringify(definition));
1803
2067
  }
1804
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPPropertyRegistry, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
1805
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPPropertyRegistry, providedIn: 'root' }); }
2068
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: AXPSchemaRegistry, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
2069
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: AXPSchemaRegistry, providedIn: 'root' }); }
1806
2070
  }
1807
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPPropertyRegistry, decorators: [{
2071
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: AXPSchemaRegistry, decorators: [{
1808
2072
  type: Injectable,
1809
2073
  args: [{ providedIn: 'root' }]
1810
2074
  }], ctorParameters: () => [] });
1811
2075
 
1812
- //#region ---- Property Service ----
2076
+ //#region ---- Schema Service ----
1813
2077
  /**
1814
- * High-level facade for registered property definitions ({@link AXPPropertyDefinition}).
2078
+ * High-level facade service for schema operations.
1815
2079
  *
1816
- * Wraps {@link AXPPropertyRegistry} with convenience methods for resolution and discovery.
2080
+ * Provides a simplified interface to the schema registry with additional
2081
+ * business logic and convenience methods for common operations.
1817
2082
  */
1818
- class AXPPropertyService {
2083
+ class AXPSchemaService {
1819
2084
  constructor() {
1820
- this.registry = inject(AXPPropertyRegistry);
2085
+ this.registry = inject(AXPSchemaRegistry);
1821
2086
  }
1822
- //#region ---- Registration ----
2087
+ //#region ---- Core Schema Management ----
1823
2088
  /**
1824
- * Register a property definition with optional configuration
2089
+ * Register a schema with optional configuration
1825
2090
  */
1826
2091
  register(definition, options) {
1827
2092
  this.registry.register(definition, options);
1828
2093
  }
1829
2094
  /**
1830
- * Register multiple property definitions at once
2095
+ * Register multiple schemas at once
1831
2096
  */
1832
- registerBatch(entries) {
1833
- this.registry.registerBatch(entries);
2097
+ registerBatch(schemas) {
2098
+ this.registry.registerBatch(schemas);
1834
2099
  }
1835
2100
  /**
1836
- * Remove a property definition from the registry
2101
+ * Remove a schema from the registry
1837
2102
  */
1838
2103
  unregister(name) {
1839
2104
  return this.registry.unregister(name);
1840
2105
  }
1841
2106
  /**
1842
- * Check if a property definition is registered by name
2107
+ * Check if a schema is registered
1843
2108
  */
1844
2109
  isRegistered(name) {
1845
2110
  return this.registry.isRegistered(name);
1846
2111
  }
1847
2112
  /**
1848
- * Get all registered property names
2113
+ * Get all registered schema names
1849
2114
  */
1850
2115
  getRegisteredNames() {
1851
2116
  return this.registry.getRegisteredNames();
1852
2117
  }
1853
2118
  /**
1854
- * Clear all registrations and reset the registry
2119
+ * Clear all schemas and reset the registry
1855
2120
  */
1856
2121
  clear() {
1857
2122
  this.registry.clear();
1858
2123
  }
1859
2124
  //#endregion
1860
- //#region ---- Resolution ----
2125
+ //#region ---- Schema Resolution ----
1861
2126
  /**
1862
- * Resolve a registered property by name with full middleware processing
2127
+ * Resolve a schema with full middleware processing
1863
2128
  */
1864
2129
  async resolve(name) {
1865
2130
  return this.registry.resolve(name);
1866
2131
  }
1867
2132
  /**
1868
- * Resolve synchronously without middleware (for performance)
2133
+ * Resolve schema synchronously without middleware (for performance)
1869
2134
  */
1870
2135
  resolveSync(name) {
1871
2136
  return this.registry.resolveSync(name);
1872
2137
  }
1873
2138
  /**
1874
- * Resolve multiple registered properties for form building and batch operations
2139
+ * Resolve multiple schemas for form building and batch operations
1875
2140
  */
1876
2141
  async resolveMultiple(fieldConfigs) {
1877
2142
  const resolvedFields = await Promise.all(fieldConfigs.map(async (config) => ({
1878
2143
  name: config.name,
1879
- property: await this.resolve(config.propertyName),
2144
+ schema: await this.resolve(config.schemaName)
1880
2145
  })));
1881
2146
  return resolvedFields;
1882
2147
  }
1883
2148
  //#endregion
1884
2149
  //#region ---- Middleware Management ----
1885
2150
  /**
1886
- * Add global middleware that applies to all property resolutions
2151
+ * Add global middleware that applies to all schema resolutions
1887
2152
  */
1888
2153
  addGlobalMiddleware(middleware) {
1889
2154
  this.registry.addGlobalMiddleware(middleware);
@@ -1903,25 +2168,25 @@ class AXPPropertyService {
1903
2168
  //#endregion
1904
2169
  //#region ---- Query and Discovery ----
1905
2170
  /**
1906
- * Get detailed information about a registered property definition
2171
+ * Get detailed information about a registered schema
1907
2172
  */
1908
- getRegisteredProperty(name) {
1909
- return this.registry.getRegisteredProperty(name);
2173
+ getSchemaInfo(name) {
2174
+ return this.registry.getSchemaInfo(name);
1910
2175
  }
1911
2176
  /**
1912
- * Get all registered property definitions with their metadata
2177
+ * Get all registered schemas with their metadata
1913
2178
  */
1914
- getAllRegisteredProperties() {
1915
- return this.registry.getAllRegisteredProperties();
2179
+ getAllSchemas() {
2180
+ return this.registry.getAllSchemas();
1916
2181
  }
1917
2182
  /**
1918
- * Find registered properties by tag for categorization and grouping
2183
+ * Find schemas by tag for categorization and grouping
1919
2184
  */
1920
2185
  findByTag(tag) {
1921
2186
  return this.registry.findByTag(tag);
1922
2187
  }
1923
2188
  /**
1924
- * Find registered properties by widget type for widget-specific operations
2189
+ * Find schemas by widget type for widget-specific operations
1925
2190
  */
1926
2191
  findByWidget(widgetType) {
1927
2192
  return this.registry.findByWidget(widgetType);
@@ -1932,11 +2197,11 @@ class AXPPropertyService {
1932
2197
  getStatistics() {
1933
2198
  const stats = this.registry.getStatistics();
1934
2199
  // Enhance with top-used analytics
1935
- const mostUsedWidgets = Object.entries(stats.propertiesByWidget)
2200
+ const mostUsedWidgets = Object.entries(stats.schemasByWidget)
1936
2201
  .sort(([, a], [, b]) => b - a)
1937
2202
  .slice(0, 5)
1938
2203
  .map(([widget]) => widget);
1939
- const mostUsedTags = Object.entries(stats.propertiesByTag)
2204
+ const mostUsedTags = Object.entries(stats.schemasByTag)
1940
2205
  .sort(([, a], [, b]) => b - a)
1941
2206
  .slice(0, 5)
1942
2207
  .map(([tag]) => tag);
@@ -1949,24 +2214,24 @@ class AXPPropertyService {
1949
2214
  //#endregion
1950
2215
  //#region ---- Validation and Analysis ----
1951
2216
  /**
1952
- * Validate that all referenced property names exist in the registry
2217
+ * Validate that all referenced schemas exist in the registry
1953
2218
  */
1954
- validatePropertyReferences(propertyNames) {
1955
- const missingPropertyNames = [];
1956
- for (const propertyName of propertyNames) {
1957
- if (!this.isRegistered(propertyName)) {
1958
- missingPropertyNames.push(propertyName);
2219
+ validateSchemaReferences(schemaNames) {
2220
+ const missingSchemas = [];
2221
+ for (const schemaName of schemaNames) {
2222
+ if (!this.isRegistered(schemaName)) {
2223
+ missingSchemas.push(schemaName);
1959
2224
  }
1960
2225
  }
1961
2226
  return {
1962
- valid: missingPropertyNames.length === 0,
1963
- missingPropertyNames,
2227
+ valid: missingSchemas.length === 0,
2228
+ missingSchemas
1964
2229
  };
1965
2230
  }
1966
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPPropertyService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
1967
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPPropertyService, providedIn: 'root' }); }
2231
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: AXPSchemaService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
2232
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: AXPSchemaService, providedIn: 'root' }); }
1968
2233
  }
1969
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPPropertyService, decorators: [{
2234
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: AXPSchemaService, decorators: [{
1970
2235
  type: Injectable,
1971
2236
  args: [{ providedIn: 'root' }]
1972
2237
  }] });
@@ -1991,24 +2256,24 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
1991
2256
  * @example
1992
2257
  * ```typescript
1993
2258
  * // Simple loader registration
1994
- * providePropertyLoaders([
2259
+ * provideSchemaLoaders([
1995
2260
  * HttpSchemaLoader,
1996
2261
  * FileSystemSchemaLoader
1997
2262
  * ])
1998
2263
  *
1999
2264
  * // With priority configuration
2000
- * providePropertyLoaders([
2265
+ * provideSchemaLoaders([
2001
2266
  * { loader: HttpSchemaLoader, priority: 10 },
2002
2267
  * { loader: FileSystemSchemaLoader, priority: 5 }
2003
2268
  * ])
2004
2269
  * ```
2005
2270
  */
2006
- function providePropertyLoaders(loaders) {
2271
+ function provideSchemaLoaders(loaders) {
2007
2272
  return makeEnvironmentProviders([
2008
2273
  {
2009
- provide: AXP_PROPERTY_LOADER_SETUP,
2274
+ provide: AXP_SCHEMA_LOADER_SETUP,
2010
2275
  useFactory: async () => {
2011
- const registry = inject(AXPPropertyRegistry);
2276
+ const registry = inject(AXPSchemaRegistry);
2012
2277
  // Register each loader with the registry
2013
2278
  for (const loader of loaders) {
2014
2279
  const loaderClass = typeof loader === 'function' ? loader : loader.loader;
@@ -2035,7 +2300,7 @@ function providePropertyLoaders(loaders) {
2035
2300
  *
2036
2301
  * @example
2037
2302
  * ```typescript
2038
- * providePropertySetups([
2303
+ * provideSchemaSetups([
2039
2304
  * {
2040
2305
  * definition: emailSchema,
2041
2306
  * options: {
@@ -2050,14 +2315,15 @@ function providePropertyLoaders(loaders) {
2050
2315
  * ])
2051
2316
  * ```
2052
2317
  */
2053
- function providePropertySetups(entries) {
2318
+ function provideSchemaSetups(schemas) {
2054
2319
  return makeEnvironmentProviders([
2055
2320
  {
2056
- provide: AXP_PROPERTY_SETUP,
2321
+ provide: AXP_SCHEMA_SETUP,
2057
2322
  useFactory: () => {
2058
- const registry = inject(AXPPropertyRegistry);
2059
- for (const entry of entries) {
2060
- registry.register(entry.definition, entry.options);
2323
+ const registry = inject(AXPSchemaRegistry);
2324
+ // Register all schemas with their options
2325
+ for (const schema of schemas) {
2326
+ registry.register(schema.definition, schema.options);
2061
2327
  }
2062
2328
  return true;
2063
2329
  },
@@ -2077,14 +2343,14 @@ function providePropertySetups(entries) {
2077
2343
  *
2078
2344
  * @example
2079
2345
  * ```typescript
2080
- * provideProperty(emailSchema, {
2346
+ * provideSchema(emailSchema, {
2081
2347
  * tags: ['user', 'contact'],
2082
2348
  * description: 'User email field'
2083
2349
  * })
2084
2350
  * ```
2085
2351
  */
2086
- function provideProperty(definition, options) {
2087
- return providePropertySetups([{ definition, options }]);
2352
+ function provideSchema(definition, options) {
2353
+ return provideSchemaSetups([{ definition, options }]);
2088
2354
  }
2089
2355
  /**
2090
2356
  * Provide schema setups from a factory function for dynamic registration.
@@ -2097,7 +2363,7 @@ function provideProperty(definition, options) {
2097
2363
  *
2098
2364
  * @example
2099
2365
  * ```typescript
2100
- * providePropertiesFromFactory(async () => {
2366
+ * provideSchemasFromFactory(async () => {
2101
2367
  * const config = await loadConfiguration();
2102
2368
  * return config.schemas.map(schema => ({
2103
2369
  * definition: schema,
@@ -2106,15 +2372,16 @@ function provideProperty(definition, options) {
2106
2372
  * })
2107
2373
  * ```
2108
2374
  */
2109
- function providePropertiesFromFactory(factory) {
2375
+ function provideSchemasFromFactory(schemaFactory) {
2110
2376
  return makeEnvironmentProviders([
2111
2377
  {
2112
- provide: AXP_PROPERTY_SETUP,
2378
+ provide: AXP_SCHEMA_SETUP,
2113
2379
  useFactory: async () => {
2114
- const registry = inject(AXPPropertyRegistry);
2115
- const entries = await factory();
2116
- for (const entry of entries) {
2117
- registry.register(entry.definition, entry.options);
2380
+ const registry = inject(AXPSchemaRegistry);
2381
+ const schemas = await schemaFactory();
2382
+ // Register all factory-generated schemas
2383
+ for (const schema of schemas) {
2384
+ registry.register(schema.definition, schema.options);
2118
2385
  }
2119
2386
  return true;
2120
2387
  },
@@ -2138,16 +2405,16 @@ function providePropertiesFromFactory(factory) {
2138
2405
  * @example
2139
2406
  * ```typescript
2140
2407
  * // Global middleware
2141
- * providePropertyMiddleware([
2408
+ * provideSchemaMiddleware([
2142
2409
  * (context) => {
2143
- * if (context.definition.dataType === 'string') {
2410
+ * if (context.schema.dataType === 'string') {
2144
2411
  * context.searchable(true);
2145
2412
  * }
2146
2413
  * }
2147
2414
  * ])
2148
2415
  *
2149
2416
  * // Targeted middleware
2150
- * providePropertyMiddleware([
2417
+ * provideSchemaMiddleware([
2151
2418
  * {
2152
2419
  * target: /^user_/,
2153
2420
  * middleware: (context) => context.withMetadata({ category: 'user' })
@@ -2155,7 +2422,7 @@ function providePropertiesFromFactory(factory) {
2155
2422
  * ])
2156
2423
  * ```
2157
2424
  */
2158
- function providePropertyMiddleware(middleware) {
2425
+ function provideSchemaMiddleware(middleware) {
2159
2426
  const global = [];
2160
2427
  const targeted = [];
2161
2428
  // Separate global and targeted middleware for different processing
@@ -2170,9 +2437,9 @@ function providePropertyMiddleware(middleware) {
2170
2437
  return makeEnvironmentProviders([
2171
2438
  // Setup global middleware that applies to all schemas
2172
2439
  ...(global.length > 0 ? [{
2173
- provide: AXP_PROPERTY_MIDDLEWARE_SETUP,
2440
+ provide: AXP_SCHEMA_MIDDLEWARE_SETUP,
2174
2441
  useFactory: () => {
2175
- const registry = inject(AXPPropertyRegistry);
2442
+ const registry = inject(AXPSchemaRegistry);
2176
2443
  for (const mw of global) {
2177
2444
  registry.addGlobalMiddleware(mw);
2178
2445
  }
@@ -2182,7 +2449,7 @@ function providePropertyMiddleware(middleware) {
2182
2449
  }] : []),
2183
2450
  // Register targeted middleware entries for future extension support
2184
2451
  ...targeted.map(entry => ({
2185
- provide: AXP_PROPERTY_EXTENSION,
2452
+ provide: AXP_SCHEMA_EXTENSION,
2186
2453
  useValue: entry,
2187
2454
  multi: true
2188
2455
  }))
@@ -2190,7 +2457,8 @@ function providePropertyMiddleware(middleware) {
2190
2457
  }
2191
2458
  //#endregion
2192
2459
 
2193
- //#region ---- Property registry core ----
2460
+ //#region ---- Core Schema Registry ----
2461
+ // Core registry and service classes
2194
2462
  //#endregion
2195
2463
 
2196
2464
  //#region ---- Domain Middleware Context ----
@@ -2319,7 +2587,7 @@ class AXPDomainRegistry {
2319
2587
  // Registered loaders for on-demand loading
2320
2588
  this._loaders = [];
2321
2589
  // Injected dependencies
2322
- this.propertyService = inject(AXPPropertyService);
2590
+ this.schemaService = inject(AXPSchemaService);
2323
2591
  }
2324
2592
  //#region ---- Main Resolution Method ----
2325
2593
  /**
@@ -2504,6 +2772,7 @@ class AXPDomainRegistry {
2504
2772
  name: pathInfo.aggregate,
2505
2773
  title: pathInfo.aggregate || '',
2506
2774
  entities: [definition],
2775
+ relations: [],
2507
2776
  validations: [],
2508
2777
  actions: []
2509
2778
  };
@@ -2514,7 +2783,7 @@ class AXPDomainRegistry {
2514
2783
  };
2515
2784
  const entityModule = new AXPModuleModel(entityModuleDefinition);
2516
2785
  const entityAggregate = new AXPAggregateModel(entityAggregateDefinition, entityModule);
2517
- return new AXPEntityModel(definition, entityAggregate, this.propertyService);
2786
+ return new AXPEntityModel(definition, entityAggregate, this.schemaService);
2518
2787
  default:
2519
2788
  throw new Error(`Unknown domain type: ${pathInfo.type}`);
2520
2789
  }
@@ -2544,10 +2813,10 @@ class AXPDomainRegistry {
2544
2813
  paths: Array.from(this._definitionCache.keys())
2545
2814
  };
2546
2815
  }
2547
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPDomainRegistry, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
2548
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPDomainRegistry, providedIn: 'root' }); }
2816
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: AXPDomainRegistry, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
2817
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: AXPDomainRegistry, providedIn: 'root' }); }
2549
2818
  }
2550
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPDomainRegistry, decorators: [{
2819
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: AXPDomainRegistry, decorators: [{
2551
2820
  type: Injectable,
2552
2821
  args: [{ providedIn: 'root' }]
2553
2822
  }] });
@@ -2849,10 +3118,10 @@ class AXPDomainService {
2849
3118
  return module;
2850
3119
  }
2851
3120
  }
2852
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPDomainService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
2853
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPDomainService, providedIn: 'root' }); }
3121
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: AXPDomainService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
3122
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: AXPDomainService, providedIn: 'root' }); }
2854
3123
  }
2855
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPDomainService, decorators: [{
3124
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: AXPDomainService, decorators: [{
2856
3125
  type: Injectable,
2857
3126
  args: [{ providedIn: 'root' }]
2858
3127
  }] });
@@ -3233,5 +3502,5 @@ function provideDomainMiddleware(config) {
3233
3502
  * Generated bundle index. Do not edit.
3234
3503
  */
3235
3504
 
3236
- export { AXPAggregateModel, AXPDomainActionSide, AXPDomainMiddlewareContext, AXPDomainModule, AXPDomainRegistry, AXPDomainService, AXPEntityCommandScope, AXPEntityFieldModel, AXPEntityModel, AXPEntityType, AXPModuleHelper, AXPModuleModel, AXPPropertyMiddlewareContext, AXPPropertyModel, AXPPropertyRegistry, AXPPropertyService, AXPRelationModel, AXPRelationshipCardinality, AXPRelationshipKind, AXP_AGGREGATE_MIDDLEWARE_SETUP, AXP_ENTITY_CRUD_SETUP, AXP_ENTITY_DEFINITION_CRUD_SERVICE, AXP_ENTITY_MIDDLEWARE_SETUP, AXP_MODULE_MIDDLEWARE_SETUP, AXP_PROPERTY_EXTENSION, AXP_PROPERTY_LOADER_SETUP, AXP_PROPERTY_MIDDLEWARE_SETUP, AXP_PROPERTY_SETUP, provideAggregateMiddleware, provideDomainLoader, provideDomainLoaders, provideDomainMiddleware, provideEntityMiddleware, provideModuleMiddleware, providePropertiesFromFactory, provideProperty, providePropertyLoaders, providePropertyMiddleware, providePropertySetups, toPropertyDefinition };
3505
+ 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 };
3237
3506
  //# sourceMappingURL=acorex-platform-domain.mjs.map