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