@acorex/platform 20.8.13 → 20.8.15
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/{types/acorex-platform-auth.d.ts → auth/index.d.ts} +2 -14
- package/{types/acorex-platform-common.d.ts → common/index.d.ts} +30 -302
- package/{types/acorex-platform-core.d.ts → core/index.d.ts} +44 -188
- package/{types/acorex-platform-domain.d.ts → domain/index.d.ts} +412 -744
- package/fesm2022/acorex-platform-auth.mjs +27 -125
- package/fesm2022/acorex-platform-auth.mjs.map +1 -1
- package/fesm2022/{acorex-platform-common-common-settings.provider-Bi1RYif5.mjs → acorex-platform-common-common-settings.provider-DVvuLUfF.mjs} +32 -30
- package/fesm2022/acorex-platform-common-common-settings.provider-DVvuLUfF.mjs.map +1 -0
- package/fesm2022/acorex-platform-common.mjs +205 -711
- package/fesm2022/acorex-platform-common.mjs.map +1 -1
- package/fesm2022/acorex-platform-core.mjs +127 -420
- package/fesm2022/acorex-platform-core.mjs.map +1 -1
- package/fesm2022/acorex-platform-domain.mjs +830 -561
- package/fesm2022/acorex-platform-domain.mjs.map +1 -1
- package/fesm2022/acorex-platform-layout-builder.mjs +114 -634
- package/fesm2022/acorex-platform-layout-builder.mjs.map +1 -1
- 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
- package/fesm2022/acorex-platform-layout-components-binding-expression-editor-popup.component-CSxCnzwU.mjs.map +1 -0
- package/fesm2022/acorex-platform-layout-components.mjs +877 -3362
- package/fesm2022/acorex-platform-layout-components.mjs.map +1 -1
- package/fesm2022/acorex-platform-layout-designer.mjs +204 -456
- package/fesm2022/acorex-platform-layout-designer.mjs.map +1 -1
- package/fesm2022/acorex-platform-layout-entity.mjs +10062 -14672
- package/fesm2022/acorex-platform-layout-entity.mjs.map +1 -1
- package/fesm2022/acorex-platform-layout-views.mjs +171 -413
- package/fesm2022/acorex-platform-layout-views.mjs.map +1 -1
- package/fesm2022/acorex-platform-layout-widget-core.mjs +441 -507
- package/fesm2022/acorex-platform-layout-widget-core.mjs.map +1 -1
- 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
- package/fesm2022/acorex-platform-layout-widgets-button-widget-designer.component-CPBzE96V.mjs.map +1 -0
- package/fesm2022/{acorex-platform-layout-widgets-file-list-popup.component-CDYAGBku.mjs → acorex-platform-layout-widgets-file-list-popup.component-Dtv6U3df.mjs} +76 -21
- package/fesm2022/acorex-platform-layout-widgets-file-list-popup.component-Dtv6U3df.mjs.map +1 -0
- package/fesm2022/{acorex-platform-layout-widgets-image-preview.popup-C_EPAvCU.mjs → acorex-platform-layout-widgets-image-preview.popup-QxJfswhK.mjs} +7 -6
- package/fesm2022/acorex-platform-layout-widgets-image-preview.popup-QxJfswhK.mjs.map +1 -0
- package/fesm2022/{acorex-platform-layout-widgets-page-widget-designer.component-D10yO28c.mjs → acorex-platform-layout-widgets-page-widget-designer.component-CVdssZBD.mjs} +12 -12
- package/fesm2022/acorex-platform-layout-widgets-page-widget-designer.component-CVdssZBD.mjs.map +1 -0
- package/fesm2022/acorex-platform-layout-widgets-repeater-widget-column.component-BCxE0RTB.mjs +111 -0
- package/fesm2022/acorex-platform-layout-widgets-repeater-widget-column.component-BCxE0RTB.mjs.map +1 -0
- 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
- package/fesm2022/acorex-platform-layout-widgets-tabular-data-edit-popup.component-DVaZN9QN.mjs.map +1 -0
- 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
- package/fesm2022/acorex-platform-layout-widgets-tabular-data-view-popup.component-DPGHgXa6.mjs.map +1 -0
- 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
- package/fesm2022/acorex-platform-layout-widgets-text-block-widget-designer.component-CdiNW691.mjs.map +1 -0
- package/fesm2022/acorex-platform-layout-widgets.mjs +3429 -5632
- package/fesm2022/acorex-platform-layout-widgets.mjs.map +1 -1
- package/fesm2022/acorex-platform-native.mjs +7 -8
- package/fesm2022/acorex-platform-native.mjs.map +1 -1
- package/fesm2022/acorex-platform-runtime.mjs +166 -391
- package/fesm2022/acorex-platform-runtime.mjs.map +1 -1
- package/fesm2022/acorex-platform-themes-default-entity-master-create-view.component-D4hU2SCE.mjs +160 -0
- package/fesm2022/acorex-platform-themes-default-entity-master-create-view.component-D4hU2SCE.mjs.map +1 -0
- package/fesm2022/acorex-platform-themes-default-entity-master-list-view.component-D2CtNrSn.mjs +1716 -0
- package/fesm2022/acorex-platform-themes-default-entity-master-list-view.component-D2CtNrSn.mjs.map +1 -0
- package/fesm2022/acorex-platform-themes-default-entity-master-modify-view.component-BVTklnzs.mjs +120 -0
- package/fesm2022/acorex-platform-themes-default-entity-master-modify-view.component-BVTklnzs.mjs.map +1 -0
- 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
- package/fesm2022/acorex-platform-themes-default-entity-master-single-view.component-rGsMVAZj.mjs.map +1 -0
- package/fesm2022/{acorex-platform-themes-default-error-401.component-C7EYJzSr.mjs → acorex-platform-themes-default-error-401.component-53VB-PS_.mjs} +4 -4
- package/fesm2022/acorex-platform-themes-default-error-401.component-53VB-PS_.mjs.map +1 -0
- package/fesm2022/{acorex-platform-themes-default-error-404.component-7MVLMwIa.mjs → acorex-platform-themes-default-error-404.component-DVF9soT5.mjs} +4 -4
- package/fesm2022/acorex-platform-themes-default-error-404.component-DVF9soT5.mjs.map +1 -0
- package/fesm2022/acorex-platform-themes-default-error-offline.component-CwNNHzZn.mjs +19 -0
- package/fesm2022/acorex-platform-themes-default-error-offline.component-CwNNHzZn.mjs.map +1 -0
- package/fesm2022/acorex-platform-themes-default.mjs +61 -1784
- package/fesm2022/acorex-platform-themes-default.mjs.map +1 -1
- package/fesm2022/{acorex-platform-themes-shared-icon-chooser-column.component-CqkWJYdv.mjs → acorex-platform-themes-shared-icon-chooser-column.component-TJ9PWHMY.mjs} +6 -6
- package/fesm2022/acorex-platform-themes-shared-icon-chooser-column.component-TJ9PWHMY.mjs.map +1 -0
- package/fesm2022/{acorex-platform-themes-shared-icon-chooser-view.component-BOTuLdWN.mjs → acorex-platform-themes-shared-icon-chooser-view.component-BHcKkIx0.mjs} +6 -6
- package/fesm2022/acorex-platform-themes-shared-icon-chooser-view.component-BHcKkIx0.mjs.map +1 -0
- package/fesm2022/{acorex-platform-themes-shared-settings.provider-DK6R87Lf.mjs → acorex-platform-themes-shared-settings.provider-DSs1o1M6.mjs} +25 -24
- package/fesm2022/acorex-platform-themes-shared-settings.provider-DSs1o1M6.mjs.map +1 -0
- package/fesm2022/acorex-platform-themes-shared-theme-color-chooser-column.component-BUPs84MI.mjs +65 -0
- package/fesm2022/acorex-platform-themes-shared-theme-color-chooser-column.component-BUPs84MI.mjs.map +1 -0
- package/fesm2022/acorex-platform-themes-shared-theme-color-chooser-view.component-BotknoHn.mjs +64 -0
- package/fesm2022/acorex-platform-themes-shared-theme-color-chooser-view.component-BotknoHn.mjs.map +1 -0
- package/fesm2022/acorex-platform-themes-shared.mjs +305 -408
- package/fesm2022/acorex-platform-themes-shared.mjs.map +1 -1
- package/fesm2022/acorex-platform-workflow.mjs +100 -359
- package/fesm2022/acorex-platform-workflow.mjs.map +1 -1
- package/fesm2022/acorex-platform.mjs.map +1 -1
- package/{types/acorex-platform-layout-builder.d.ts → layout/builder/index.d.ts} +38 -160
- package/{types/acorex-platform-layout-components.d.ts → layout/components/index.d.ts} +125 -854
- package/{types/acorex-platform-layout-designer.d.ts → layout/designer/index.d.ts} +18 -96
- package/{types/acorex-platform-layout-entity.d.ts → layout/entity/index.d.ts} +65 -848
- package/{types/acorex-platform-layout-views.d.ts → layout/views/index.d.ts} +47 -80
- package/{types/acorex-platform-layout-widget-core.d.ts → layout/widget-core/index.d.ts} +197 -274
- package/{types/acorex-platform-layout-widgets.d.ts → layout/widgets/index.d.ts} +124 -608
- package/{types/acorex-platform-native.d.ts → native/index.d.ts} +7 -0
- package/package.json +33 -33
- package/runtime/index.d.ts +307 -0
- package/{types/acorex-platform-themes-default.d.ts → themes/default/index.d.ts} +4 -113
- package/{types/acorex-platform-themes-shared.d.ts → themes/shared/index.d.ts} +4 -5
- package/{types/acorex-platform-workflow.d.ts → workflow/index.d.ts} +81 -162
- package/fesm2022/acorex-platform-common-common-settings.provider-Bi1RYif5.mjs.map +0 -1
- package/fesm2022/acorex-platform-layout-components-binding-expression-editor-popup.component-CXEdvDTf.mjs.map +0 -1
- package/fesm2022/acorex-platform-layout-widgets-button-widget-designer.component-Dy7jF-oD.mjs.map +0 -1
- package/fesm2022/acorex-platform-layout-widgets-file-list-popup.component-CDYAGBku.mjs.map +0 -1
- package/fesm2022/acorex-platform-layout-widgets-image-preview.popup-C_EPAvCU.mjs.map +0 -1
- package/fesm2022/acorex-platform-layout-widgets-page-widget-designer.component-D10yO28c.mjs.map +0 -1
- package/fesm2022/acorex-platform-layout-widgets-repeater-widget-column.component-BGO75IMz.mjs +0 -116
- package/fesm2022/acorex-platform-layout-widgets-repeater-widget-column.component-BGO75IMz.mjs.map +0 -1
- package/fesm2022/acorex-platform-layout-widgets-tabular-data-edit-popup.component-DmzNTYiS.mjs.map +0 -1
- package/fesm2022/acorex-platform-layout-widgets-tabular-data-view-popup.component-BNG_588B.mjs.map +0 -1
- package/fesm2022/acorex-platform-layout-widgets-text-block-widget-designer.component-Vo4fWHtX.mjs.map +0 -1
- package/fesm2022/acorex-platform-themes-default-entity-master-create-view.component-Cx1lLUaR.mjs +0 -160
- package/fesm2022/acorex-platform-themes-default-entity-master-create-view.component-Cx1lLUaR.mjs.map +0 -1
- package/fesm2022/acorex-platform-themes-default-entity-master-modify-view.component-AOrcgjDF.mjs +0 -120
- package/fesm2022/acorex-platform-themes-default-entity-master-modify-view.component-AOrcgjDF.mjs.map +0 -1
- package/fesm2022/acorex-platform-themes-default-entity-master-single-view.component-BfCeUU5F.mjs.map +0 -1
- package/fesm2022/acorex-platform-themes-default-error-401.component-C7EYJzSr.mjs.map +0 -1
- package/fesm2022/acorex-platform-themes-default-error-404.component-7MVLMwIa.mjs.map +0 -1
- package/fesm2022/acorex-platform-themes-default-error-offline.component-DR6G8gPC.mjs +0 -19
- package/fesm2022/acorex-platform-themes-default-error-offline.component-DR6G8gPC.mjs.map +0 -1
- package/fesm2022/acorex-platform-themes-shared-icon-chooser-column.component-CqkWJYdv.mjs.map +0 -1
- package/fesm2022/acorex-platform-themes-shared-icon-chooser-view.component-BOTuLdWN.mjs.map +0 -1
- package/fesm2022/acorex-platform-themes-shared-settings.provider-DK6R87Lf.mjs.map +0 -1
- package/fesm2022/acorex-platform-themes-shared-theme-color-chooser-column.component-D566Kdvy.mjs +0 -94
- package/fesm2022/acorex-platform-themes-shared-theme-color-chooser-column.component-D566Kdvy.mjs.map +0 -1
- package/fesm2022/acorex-platform-themes-shared-theme-color-chooser-view.component-D7-rCGl7.mjs +0 -86
- package/fesm2022/acorex-platform-themes-shared-theme-color-chooser-view.component-D7-rCGl7.mjs.map +0 -1
- package/types/acorex-platform-runtime.d.ts +0 -571
- /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
|
|
3
|
-
import {
|
|
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
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
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
|
-
*
|
|
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
|
|
177
|
+
const AXP_SCHEMA_EXTENSION = new InjectionToken('AXP_SCHEMA_EXTENSION');
|
|
25
178
|
/**
|
|
26
|
-
*
|
|
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
|
|
185
|
+
const AXP_SCHEMA_SETUP = new InjectionToken('AXP_SCHEMA_SETUP');
|
|
29
186
|
/**
|
|
30
|
-
*
|
|
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
|
|
193
|
+
const AXP_SCHEMA_MIDDLEWARE_SETUP = new InjectionToken('AXP_SCHEMA_MIDDLEWARE_SETUP');
|
|
33
194
|
/**
|
|
34
|
-
*
|
|
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
|
|
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
|
-
*
|
|
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.
|
|
81
|
-
this.
|
|
82
|
-
this.
|
|
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: "
|
|
95
|
-
static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "
|
|
96
|
-
static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "
|
|
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: "
|
|
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 ----
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
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
|
-
*
|
|
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
|
-
*
|
|
416
|
-
*
|
|
798
|
+
* Get all relations across all aggregates
|
|
799
|
+
*
|
|
800
|
+
* @returns Array of all relation models
|
|
417
801
|
*/
|
|
418
802
|
getAllRelations() {
|
|
419
|
-
|
|
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
|
|
843
|
+
* Get module statistics
|
|
844
|
+
*
|
|
845
|
+
* @returns Statistics object
|
|
581
846
|
*/
|
|
582
|
-
|
|
583
|
-
const
|
|
584
|
-
const capabilityCount = Object.values(capabilities).filter(Boolean).length;
|
|
847
|
+
getStatistics() {
|
|
848
|
+
const aggregateStats = this.aggregates.map(agg => agg.getStatistics());
|
|
585
849
|
return {
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
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
|
-
|
|
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,
|
|
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.
|
|
883
|
+
this.features = definition.features;
|
|
635
884
|
this.defaultValue = definition.defaultValue;
|
|
636
885
|
this.parent = parent;
|
|
637
|
-
this.
|
|
638
|
-
|
|
639
|
-
this.
|
|
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.
|
|
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.
|
|
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(
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
946
|
+
return this.schema.features?.auditable?.enabled ?? false;
|
|
695
947
|
}
|
|
696
948
|
//#endregion
|
|
697
|
-
//#region ----
|
|
949
|
+
//#region ---- Schema Methods ----
|
|
698
950
|
/**
|
|
699
|
-
*
|
|
951
|
+
* Get the schema name
|
|
700
952
|
*/
|
|
701
|
-
|
|
702
|
-
return this.
|
|
953
|
+
getSchemaName() {
|
|
954
|
+
return this.schemaName;
|
|
703
955
|
}
|
|
704
956
|
/**
|
|
705
|
-
*
|
|
957
|
+
* Get schema info from registry
|
|
706
958
|
*/
|
|
707
|
-
|
|
708
|
-
|
|
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
|
-
*
|
|
963
|
+
* Re-resolve schema from registry (useful after schema updates)
|
|
715
964
|
*/
|
|
716
|
-
|
|
717
|
-
|
|
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(
|
|
1005
|
+
errors.push('Field name is required');
|
|
754
1006
|
if (!this.title)
|
|
755
|
-
errors.push(
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
if (
|
|
762
|
-
errors.push(
|
|
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
|
-
|
|
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
|
-
|
|
1060
|
+
name: this.name,
|
|
1061
|
+
title: this.title,
|
|
1062
|
+
description: this.description,
|
|
1063
|
+
validations: this.validations,
|
|
802
1064
|
actions: this.actions,
|
|
803
|
-
|
|
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,
|
|
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.
|
|
821
|
-
// Initialize fields with parent reference and
|
|
822
|
-
this.fields = definition.fields.map(fieldDef => new AXPEntityFieldModel(fieldDef, this,
|
|
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 ----
|
|
1226
|
+
//#region ---- AXPSchemaModel ----
|
|
958
1227
|
/**
|
|
959
|
-
* Runtime model for
|
|
960
|
-
* Relations live in their own collection; join when needed.
|
|
1228
|
+
* Runtime model for schema definitions with helper methods
|
|
961
1229
|
*/
|
|
962
|
-
class
|
|
963
|
-
constructor(definition
|
|
964
|
-
this.
|
|
965
|
-
this.
|
|
966
|
-
this.
|
|
967
|
-
this.
|
|
968
|
-
this.
|
|
969
|
-
this.
|
|
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 ----
|
|
1240
|
+
//#region ---- Data Type Methods ----
|
|
973
1241
|
/**
|
|
974
|
-
* Check if
|
|
1242
|
+
* Check if schema is for string data
|
|
975
1243
|
*/
|
|
976
|
-
|
|
977
|
-
return this.
|
|
1244
|
+
isString() {
|
|
1245
|
+
return this.dataType === 'string';
|
|
978
1246
|
}
|
|
979
1247
|
/**
|
|
980
|
-
* Check if
|
|
1248
|
+
* Check if schema is for number data
|
|
981
1249
|
*/
|
|
982
|
-
|
|
983
|
-
return this.
|
|
1250
|
+
isNumber() {
|
|
1251
|
+
return this.dataType === 'number';
|
|
984
1252
|
}
|
|
985
1253
|
/**
|
|
986
|
-
* Check if
|
|
1254
|
+
* Check if schema is for boolean data
|
|
987
1255
|
*/
|
|
988
|
-
|
|
989
|
-
return this.
|
|
1256
|
+
isBoolean() {
|
|
1257
|
+
return this.dataType === 'boolean';
|
|
990
1258
|
}
|
|
991
|
-
//#endregion
|
|
992
|
-
//#region ---- Kind Methods ----
|
|
993
1259
|
/**
|
|
994
|
-
* Check if
|
|
1260
|
+
* Check if schema is for date data
|
|
995
1261
|
*/
|
|
996
|
-
|
|
997
|
-
return this.
|
|
1262
|
+
isDate() {
|
|
1263
|
+
return this.dataType === 'date';
|
|
998
1264
|
}
|
|
999
1265
|
/**
|
|
1000
|
-
* Check if
|
|
1266
|
+
* Check if schema is for object data
|
|
1001
1267
|
*/
|
|
1002
|
-
|
|
1003
|
-
return this.
|
|
1268
|
+
isObject() {
|
|
1269
|
+
return this.dataType === 'object';
|
|
1004
1270
|
}
|
|
1005
1271
|
/**
|
|
1006
|
-
* Check if
|
|
1272
|
+
* Check if schema is for array data
|
|
1007
1273
|
*/
|
|
1008
|
-
|
|
1009
|
-
return this.
|
|
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 ----
|
|
1284
|
+
//#region ---- Interface Methods ----
|
|
1013
1285
|
/**
|
|
1014
|
-
* Get
|
|
1286
|
+
* Get widget type
|
|
1015
1287
|
*/
|
|
1016
|
-
|
|
1017
|
-
return this.
|
|
1288
|
+
getWidgetType() {
|
|
1289
|
+
return this.interface.widget;
|
|
1018
1290
|
}
|
|
1019
1291
|
/**
|
|
1020
|
-
* Get
|
|
1292
|
+
* Get widget options
|
|
1021
1293
|
*/
|
|
1022
|
-
|
|
1023
|
-
return this.
|
|
1294
|
+
getWidgetOptions() {
|
|
1295
|
+
return this.interface.options;
|
|
1024
1296
|
}
|
|
1025
1297
|
/**
|
|
1026
|
-
*
|
|
1298
|
+
* Check if interface is disabled
|
|
1027
1299
|
*/
|
|
1028
|
-
|
|
1029
|
-
return
|
|
1300
|
+
isDisabled() {
|
|
1301
|
+
return this.interface.disabled ?? false;
|
|
1030
1302
|
}
|
|
1031
1303
|
//#endregion
|
|
1032
|
-
//#region ----
|
|
1304
|
+
//#region ---- Feature Methods ----
|
|
1033
1305
|
/**
|
|
1034
|
-
*
|
|
1306
|
+
* Check if searchable
|
|
1035
1307
|
*/
|
|
1036
|
-
|
|
1037
|
-
|
|
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
|
-
*
|
|
1312
|
+
* Check if full text searchable
|
|
1044
1313
|
*/
|
|
1045
|
-
|
|
1046
|
-
|
|
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
|
-
*
|
|
1318
|
+
* Check if filterable
|
|
1059
1319
|
*/
|
|
1060
|
-
|
|
1061
|
-
|
|
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
|
-
*
|
|
1324
|
+
* Check if inline filterable
|
|
1074
1325
|
*/
|
|
1075
|
-
|
|
1076
|
-
return
|
|
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
|
|
1344
|
+
* Validate the schema structure
|
|
1082
1345
|
*/
|
|
1083
|
-
validate() {
|
|
1346
|
+
async validate() {
|
|
1084
1347
|
const errors = [];
|
|
1085
|
-
// Validate
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
// Validate
|
|
1091
|
-
if (!this.
|
|
1092
|
-
errors.push('
|
|
1093
|
-
|
|
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
|
|
1362
|
+
* Get schema capabilities
|
|
1103
1363
|
*/
|
|
1104
|
-
|
|
1364
|
+
getCapabilities() {
|
|
1105
1365
|
return {
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
|
|
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
|
-
*
|
|
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
|
-
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
|
|
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
|
|
1391
|
+
* Convert back to interface definition
|
|
1139
1392
|
*/
|
|
1140
1393
|
toDefinition() {
|
|
1141
1394
|
return {
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
|
|
1145
|
-
|
|
1146
|
-
|
|
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
|
|
1474
|
+
* @deprecated Use AXPDomainService with field schema queries instead
|
|
1221
1475
|
*/
|
|
1222
|
-
static
|
|
1223
|
-
console.warn('AXPModuleHelper.
|
|
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
|
|
1295
|
-
constructor(
|
|
1296
|
-
// Deep clone to avoid mutating the original
|
|
1297
|
-
this.
|
|
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
|
|
1304
|
-
return this.
|
|
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.
|
|
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.
|
|
1320
|
-
this.
|
|
1573
|
+
if (!this._schema.interface.options) {
|
|
1574
|
+
this._schema.interface.options = {};
|
|
1321
1575
|
}
|
|
1322
|
-
this.
|
|
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.
|
|
1330
|
-
delete this.
|
|
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.
|
|
1342
|
-
this.
|
|
1595
|
+
if (!this._schema.validations) {
|
|
1596
|
+
this._schema.validations = [];
|
|
1343
1597
|
}
|
|
1344
|
-
this.
|
|
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.
|
|
1353
|
-
this.
|
|
1606
|
+
if (!this._schema.validations) {
|
|
1607
|
+
this._schema.validations = [];
|
|
1354
1608
|
}
|
|
1355
|
-
this.
|
|
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.
|
|
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.
|
|
1378
|
-
this.
|
|
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
|
-
|
|
1390
|
-
|
|
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.
|
|
1402
|
-
delete this.
|
|
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.
|
|
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.
|
|
1422
|
-
...this.
|
|
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.
|
|
1434
|
-
this.
|
|
1686
|
+
if (!this._schema.features) {
|
|
1687
|
+
this._schema.features = {};
|
|
1435
1688
|
}
|
|
1436
|
-
this.
|
|
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.
|
|
1446
|
-
this.
|
|
1698
|
+
if (!this._schema.features) {
|
|
1699
|
+
this._schema.features = {};
|
|
1447
1700
|
}
|
|
1448
|
-
this.
|
|
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.
|
|
1457
|
-
this.
|
|
1709
|
+
if (!this._schema.features) {
|
|
1710
|
+
this._schema.features = {};
|
|
1458
1711
|
}
|
|
1459
|
-
this.
|
|
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.
|
|
1470
|
-
...this.
|
|
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.
|
|
1481
|
-
delete this.
|
|
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.
|
|
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.
|
|
1501
|
-
this.
|
|
1763
|
+
if (!this._schema.interface.options) {
|
|
1764
|
+
this._schema.interface.options = {};
|
|
1502
1765
|
}
|
|
1503
|
-
this.
|
|
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.
|
|
1512
|
-
this.
|
|
1774
|
+
if (!this._schema.interface.options) {
|
|
1775
|
+
this._schema.interface.options = {};
|
|
1513
1776
|
}
|
|
1514
|
-
this.
|
|
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
|
|
1795
|
+
class AXPSchemaRegistry {
|
|
1533
1796
|
constructor() {
|
|
1534
|
-
this.
|
|
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('
|
|
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.
|
|
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(
|
|
1560
|
-
for (const
|
|
1561
|
-
this.register(
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
1867
|
+
this._schemas.set(name, registered);
|
|
1604
1868
|
}
|
|
1605
1869
|
else {
|
|
1606
|
-
throw new Error(`
|
|
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
|
|
1611
|
-
const context = new
|
|
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
|
|
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
|
|
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.
|
|
1896
|
+
const registered = this._schemas.get(name);
|
|
1633
1897
|
if (!registered) {
|
|
1634
|
-
throw new Error(`
|
|
1898
|
+
throw new Error(`Schema '${name}' is not registered`);
|
|
1635
1899
|
}
|
|
1636
|
-
return new
|
|
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.
|
|
1947
|
+
return Array.from(this._schemas.keys());
|
|
1684
1948
|
}
|
|
1685
1949
|
/**
|
|
1686
1950
|
* Get detailed registration information for a schema
|
|
1687
1951
|
*/
|
|
1688
|
-
|
|
1689
|
-
return this.
|
|
1952
|
+
getSchemaInfo(name) {
|
|
1953
|
+
return this._schemas.get(name);
|
|
1690
1954
|
}
|
|
1691
1955
|
/**
|
|
1692
|
-
* Get all registered
|
|
1956
|
+
* Get all registered schemas with their metadata
|
|
1693
1957
|
*/
|
|
1694
|
-
|
|
1695
|
-
return Array.from(this.
|
|
1958
|
+
getAllSchemas() {
|
|
1959
|
+
return Array.from(this._schemas.values());
|
|
1696
1960
|
}
|
|
1697
1961
|
/**
|
|
1698
|
-
* Find
|
|
1962
|
+
* Find schemas by tag for categorization
|
|
1699
1963
|
*/
|
|
1700
1964
|
findByTag(tag) {
|
|
1701
|
-
return Array.from(this.
|
|
1965
|
+
return Array.from(this._schemas.values()).filter(schema => schema.options.tags?.includes(tag));
|
|
1702
1966
|
}
|
|
1703
1967
|
/**
|
|
1704
|
-
* Find
|
|
1968
|
+
* Find schemas by widget type for widget-specific operations
|
|
1705
1969
|
*/
|
|
1706
1970
|
findByWidget(widgetType) {
|
|
1707
|
-
return Array.from(this.
|
|
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
|
|
1714
|
-
const
|
|
1715
|
-
for (const
|
|
1716
|
-
const widget =
|
|
1717
|
-
|
|
1718
|
-
if (
|
|
1719
|
-
for (const tag of
|
|
1720
|
-
|
|
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
|
-
|
|
1989
|
+
schemaCount: this._schemas.size,
|
|
1726
1990
|
globalMiddlewareCount: this._globalMiddleware.length,
|
|
1727
|
-
|
|
1728
|
-
|
|
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.
|
|
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(`
|
|
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
|
|
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: "
|
|
1805
|
-
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "
|
|
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: "
|
|
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 ----
|
|
2076
|
+
//#region ---- Schema Service ----
|
|
1813
2077
|
/**
|
|
1814
|
-
* High-level facade for
|
|
2078
|
+
* High-level facade service for schema operations.
|
|
1815
2079
|
*
|
|
1816
|
-
*
|
|
2080
|
+
* Provides a simplified interface to the schema registry with additional
|
|
2081
|
+
* business logic and convenience methods for common operations.
|
|
1817
2082
|
*/
|
|
1818
|
-
class
|
|
2083
|
+
class AXPSchemaService {
|
|
1819
2084
|
constructor() {
|
|
1820
|
-
this.registry = inject(
|
|
2085
|
+
this.registry = inject(AXPSchemaRegistry);
|
|
1821
2086
|
}
|
|
1822
|
-
//#region ----
|
|
2087
|
+
//#region ---- Core Schema Management ----
|
|
1823
2088
|
/**
|
|
1824
|
-
* Register a
|
|
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
|
|
2095
|
+
* Register multiple schemas at once
|
|
1831
2096
|
*/
|
|
1832
|
-
registerBatch(
|
|
1833
|
-
this.registry.registerBatch(
|
|
2097
|
+
registerBatch(schemas) {
|
|
2098
|
+
this.registry.registerBatch(schemas);
|
|
1834
2099
|
}
|
|
1835
2100
|
/**
|
|
1836
|
-
* Remove a
|
|
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
|
|
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
|
|
2113
|
+
* Get all registered schema names
|
|
1849
2114
|
*/
|
|
1850
2115
|
getRegisteredNames() {
|
|
1851
2116
|
return this.registry.getRegisteredNames();
|
|
1852
2117
|
}
|
|
1853
2118
|
/**
|
|
1854
|
-
* Clear all
|
|
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
|
|
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
|
|
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
|
-
|
|
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
|
|
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
|
|
2171
|
+
* Get detailed information about a registered schema
|
|
1907
2172
|
*/
|
|
1908
|
-
|
|
1909
|
-
return this.registry.
|
|
2173
|
+
getSchemaInfo(name) {
|
|
2174
|
+
return this.registry.getSchemaInfo(name);
|
|
1910
2175
|
}
|
|
1911
2176
|
/**
|
|
1912
|
-
* Get all registered
|
|
2177
|
+
* Get all registered schemas with their metadata
|
|
1913
2178
|
*/
|
|
1914
|
-
|
|
1915
|
-
return this.registry.
|
|
2179
|
+
getAllSchemas() {
|
|
2180
|
+
return this.registry.getAllSchemas();
|
|
1916
2181
|
}
|
|
1917
2182
|
/**
|
|
1918
|
-
* Find
|
|
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
|
|
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.
|
|
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.
|
|
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
|
|
2217
|
+
* Validate that all referenced schemas exist in the registry
|
|
1953
2218
|
*/
|
|
1954
|
-
|
|
1955
|
-
const
|
|
1956
|
-
for (const
|
|
1957
|
-
if (!this.isRegistered(
|
|
1958
|
-
|
|
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:
|
|
1963
|
-
|
|
2227
|
+
valid: missingSchemas.length === 0,
|
|
2228
|
+
missingSchemas
|
|
1964
2229
|
};
|
|
1965
2230
|
}
|
|
1966
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
1967
|
-
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "
|
|
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: "
|
|
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
|
-
*
|
|
2259
|
+
* provideSchemaLoaders([
|
|
1995
2260
|
* HttpSchemaLoader,
|
|
1996
2261
|
* FileSystemSchemaLoader
|
|
1997
2262
|
* ])
|
|
1998
2263
|
*
|
|
1999
2264
|
* // With priority configuration
|
|
2000
|
-
*
|
|
2265
|
+
* provideSchemaLoaders([
|
|
2001
2266
|
* { loader: HttpSchemaLoader, priority: 10 },
|
|
2002
2267
|
* { loader: FileSystemSchemaLoader, priority: 5 }
|
|
2003
2268
|
* ])
|
|
2004
2269
|
* ```
|
|
2005
2270
|
*/
|
|
2006
|
-
function
|
|
2271
|
+
function provideSchemaLoaders(loaders) {
|
|
2007
2272
|
return makeEnvironmentProviders([
|
|
2008
2273
|
{
|
|
2009
|
-
provide:
|
|
2274
|
+
provide: AXP_SCHEMA_LOADER_SETUP,
|
|
2010
2275
|
useFactory: async () => {
|
|
2011
|
-
const registry = inject(
|
|
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
|
-
*
|
|
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
|
|
2318
|
+
function provideSchemaSetups(schemas) {
|
|
2054
2319
|
return makeEnvironmentProviders([
|
|
2055
2320
|
{
|
|
2056
|
-
provide:
|
|
2321
|
+
provide: AXP_SCHEMA_SETUP,
|
|
2057
2322
|
useFactory: () => {
|
|
2058
|
-
const registry = inject(
|
|
2059
|
-
|
|
2060
|
-
|
|
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
|
-
*
|
|
2346
|
+
* provideSchema(emailSchema, {
|
|
2081
2347
|
* tags: ['user', 'contact'],
|
|
2082
2348
|
* description: 'User email field'
|
|
2083
2349
|
* })
|
|
2084
2350
|
* ```
|
|
2085
2351
|
*/
|
|
2086
|
-
function
|
|
2087
|
-
return
|
|
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
|
-
*
|
|
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
|
|
2375
|
+
function provideSchemasFromFactory(schemaFactory) {
|
|
2110
2376
|
return makeEnvironmentProviders([
|
|
2111
2377
|
{
|
|
2112
|
-
provide:
|
|
2378
|
+
provide: AXP_SCHEMA_SETUP,
|
|
2113
2379
|
useFactory: async () => {
|
|
2114
|
-
const registry = inject(
|
|
2115
|
-
const
|
|
2116
|
-
|
|
2117
|
-
|
|
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
|
-
*
|
|
2408
|
+
* provideSchemaMiddleware([
|
|
2142
2409
|
* (context) => {
|
|
2143
|
-
* if (context.
|
|
2410
|
+
* if (context.schema.dataType === 'string') {
|
|
2144
2411
|
* context.searchable(true);
|
|
2145
2412
|
* }
|
|
2146
2413
|
* }
|
|
2147
2414
|
* ])
|
|
2148
2415
|
*
|
|
2149
2416
|
* // Targeted middleware
|
|
2150
|
-
*
|
|
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
|
|
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:
|
|
2440
|
+
provide: AXP_SCHEMA_MIDDLEWARE_SETUP,
|
|
2174
2441
|
useFactory: () => {
|
|
2175
|
-
const registry = inject(
|
|
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:
|
|
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 ----
|
|
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.
|
|
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.
|
|
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: "
|
|
2548
|
-
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "
|
|
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: "
|
|
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: "
|
|
2853
|
-
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "
|
|
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: "
|
|
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,
|
|
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
|