@acorex/platform 21.0.0-next.3 → 21.0.0-next.33
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 +295 -45
- package/fesm2022/acorex-platform-auth.mjs.map +1 -1
- package/fesm2022/{acorex-platform-common-common-settings.provider-zhqNP3xb.mjs → acorex-platform-common-common-settings.provider-G9XcXXOG.mjs} +60 -4
- package/fesm2022/acorex-platform-common-common-settings.provider-G9XcXXOG.mjs.map +1 -0
- package/fesm2022/acorex-platform-common.mjs +960 -319
- package/fesm2022/acorex-platform-common.mjs.map +1 -1
- package/fesm2022/acorex-platform-core.mjs +1352 -832
- package/fesm2022/acorex-platform-core.mjs.map +1 -1
- package/fesm2022/acorex-platform-domain.mjs +554 -826
- package/fesm2022/acorex-platform-domain.mjs.map +1 -1
- package/fesm2022/acorex-platform-layout-builder.mjs +530 -154
- 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 +5969 -2347
- package/fesm2022/acorex-platform-layout-components.mjs.map +1 -1
- package/fesm2022/acorex-platform-layout-designer.mjs +169 -154
- package/fesm2022/acorex-platform-layout-designer.mjs.map +1 -1
- package/fesm2022/acorex-platform-layout-entity.mjs +15380 -9274
- package/fesm2022/acorex-platform-layout-entity.mjs.map +1 -1
- package/fesm2022/acorex-platform-layout-views.mjs +393 -110
- package/fesm2022/acorex-platform-layout-views.mjs.map +1 -1
- package/fesm2022/acorex-platform-layout-widget-core.mjs +511 -450
- 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-CxrsI6Hn.mjs → acorex-platform-layout-widgets-file-list-popup.component-9uCkMxcc.mjs} +39 -16
- package/fesm2022/acorex-platform-layout-widgets-file-list-popup.component-9uCkMxcc.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-BGQqY5Mw.mjs +111 -0
- package/fesm2022/acorex-platform-layout-widgets-repeater-widget-column.component-BGQqY5Mw.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 +7865 -4026
- 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 +220 -169
- package/fesm2022/acorex-platform-runtime.mjs.map +1 -1
- package/fesm2022/acorex-platform-themes-default-entity-master-create-view.component-Cvvr4HnL.mjs +160 -0
- package/fesm2022/acorex-platform-themes-default-entity-master-create-view.component-Cvvr4HnL.mjs.map +1 -0
- package/fesm2022/acorex-platform-themes-default-entity-master-modify-view.component-TYoLN1Jq.mjs +120 -0
- package/fesm2022/acorex-platform-themes-default-entity-master-modify-view.component-TYoLN1Jq.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-C2z5Lq9y.mjs} +18 -25
- package/fesm2022/acorex-platform-themes-default-entity-master-single-view.component-C2z5Lq9y.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 +1717 -66
- 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.map +1 -1
- package/fesm2022/{acorex-platform-themes-shared-theme-color-chooser-column.component-DTnfRy5f.mjs → acorex-platform-themes-shared-theme-color-chooser-column.component-CHfrTtol.mjs} +11 -11
- package/fesm2022/acorex-platform-themes-shared-theme-color-chooser-column.component-CHfrTtol.mjs.map +1 -0
- package/fesm2022/{acorex-platform-themes-shared-theme-color-chooser-view.component-DY0JtT1v.mjs → acorex-platform-themes-shared-theme-color-chooser-view.component-BSmvnUVq.mjs} +9 -9
- package/fesm2022/acorex-platform-themes-shared-theme-color-chooser-view.component-BSmvnUVq.mjs.map +1 -0
- package/fesm2022/acorex-platform-themes-shared.mjs +563 -561
- package/fesm2022/acorex-platform-themes-shared.mjs.map +1 -1
- package/fesm2022/acorex-platform-workflow.mjs +1735 -1750
- package/fesm2022/acorex-platform-workflow.mjs.map +1 -1
- package/fesm2022/acorex-platform.mjs.map +1 -1
- package/package.json +31 -31
- package/{auth/index.d.ts → types/acorex-platform-auth.d.ts} +247 -10
- package/{common/index.d.ts → types/acorex-platform-common.d.ts} +492 -31
- package/{core/index.d.ts → types/acorex-platform-core.d.ts} +606 -392
- package/{domain/index.d.ts → types/acorex-platform-domain.d.ts} +719 -413
- package/{layout/builder/index.d.ts → types/acorex-platform-layout-builder.d.ts} +128 -56
- package/types/acorex-platform-layout-components.d.ts +2927 -0
- package/{layout/designer/index.d.ts → types/acorex-platform-layout-designer.d.ts} +9 -3
- package/{layout/entity/index.d.ts → types/acorex-platform-layout-entity.d.ts} +1133 -237
- package/{layout/views/index.d.ts → types/acorex-platform-layout-views.d.ts} +90 -31
- package/{layout/widget-core/index.d.ts → types/acorex-platform-layout-widget-core.d.ts} +206 -102
- package/{layout/widgets/index.d.ts → types/acorex-platform-layout-widgets.d.ts} +942 -137
- package/{native/index.d.ts → types/acorex-platform-native.d.ts} +0 -7
- package/{runtime/index.d.ts → types/acorex-platform-runtime.d.ts} +237 -74
- package/{themes/default/index.d.ts → types/acorex-platform-themes-default.d.ts} +113 -5
- package/{themes/shared/index.d.ts → types/acorex-platform-themes-shared.d.ts} +1 -1
- package/types/acorex-platform-workflow.d.ts +1806 -0
- 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.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-theme-color-chooser-column.component-DTnfRy5f.mjs.map +0 -1
- 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/workflow/index.d.ts +0 -2443
- /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,28 @@ 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
|
-
this.target = { ...definition.target };
|
|
316
|
-
this.source = { ...definition.source };
|
|
317
|
-
this.isRequired = definition.isRequired;
|
|
318
|
-
this.parent = parent;
|
|
319
|
-
}
|
|
320
|
-
//#endregion
|
|
321
|
-
//#region ---- Cardinality Methods ----
|
|
322
|
-
/**
|
|
323
|
-
* Check if relation is one-to-one
|
|
324
|
-
*/
|
|
325
|
-
isOneToOne() {
|
|
326
|
-
return this.type === AXPRelationshipCardinality.OneToOne;
|
|
327
|
-
}
|
|
328
|
-
/**
|
|
329
|
-
* Check if relation is one-to-many
|
|
330
|
-
*/
|
|
331
|
-
isOneToMany() {
|
|
332
|
-
return this.type === AXPRelationshipCardinality.OneToMany;
|
|
333
|
-
}
|
|
334
|
-
/**
|
|
335
|
-
* Check if relation is many-to-many
|
|
336
|
-
*/
|
|
337
|
-
isManyToMany() {
|
|
338
|
-
return this.type === AXPRelationshipCardinality.ManyToMany;
|
|
339
|
-
}
|
|
340
|
-
//#endregion
|
|
341
|
-
//#region ---- Kind Methods ----
|
|
342
|
-
/**
|
|
343
|
-
* Check if relation is association
|
|
344
|
-
*/
|
|
345
|
-
isAssociation() {
|
|
346
|
-
return this.kind === AXPRelationshipKind.Association;
|
|
347
|
-
}
|
|
348
|
-
/**
|
|
349
|
-
* Check if relation is composition
|
|
350
|
-
*/
|
|
351
|
-
isComposition() {
|
|
352
|
-
return this.kind === AXPRelationshipKind.Composition;
|
|
353
|
-
}
|
|
354
|
-
/**
|
|
355
|
-
* Check if relation is aggregation
|
|
356
|
-
*/
|
|
357
|
-
isAggregation() {
|
|
358
|
-
return this.kind === AXPRelationshipKind.Aggregation;
|
|
359
|
-
}
|
|
360
|
-
//#endregion
|
|
361
|
-
//#region ---- Navigation Methods ----
|
|
362
|
-
/**
|
|
363
|
-
* Get parent aggregate
|
|
364
|
-
*/
|
|
365
|
-
getAggregate() {
|
|
366
|
-
return this.parent;
|
|
367
|
-
}
|
|
368
|
-
/**
|
|
369
|
-
* Get parent module
|
|
370
|
-
*/
|
|
371
|
-
getModule() {
|
|
372
|
-
return this.parent?.parent;
|
|
373
|
-
}
|
|
374
|
-
/**
|
|
375
|
-
* Get full path (module.aggregate.relation)
|
|
376
|
-
*/
|
|
377
|
-
getPath() {
|
|
378
|
-
return `${this.parent.parent.name}.${this.parent.name}.${this.source.entity}->${this.target.entity}`;
|
|
379
|
-
}
|
|
380
|
-
//#endregion
|
|
381
|
-
//#region ---- Query Methods ----
|
|
382
|
-
/**
|
|
383
|
-
* Get relation description
|
|
384
|
-
*/
|
|
385
|
-
getDescription() {
|
|
386
|
-
const cardinalityDesc = this.getCardinalityDescription();
|
|
387
|
-
const kindDesc = this.getKindDescription();
|
|
388
|
-
const requiredDesc = this.isRequired ? 'required' : 'optional';
|
|
389
|
-
return `${cardinalityDesc} ${kindDesc} (${requiredDesc})`;
|
|
390
|
-
}
|
|
391
|
-
/**
|
|
392
|
-
* Get cardinality description
|
|
393
|
-
*/
|
|
394
|
-
getCardinalityDescription() {
|
|
395
|
-
switch (this.type) {
|
|
396
|
-
case AXPRelationshipCardinality.OneToOne:
|
|
397
|
-
return 'one-to-one';
|
|
398
|
-
case AXPRelationshipCardinality.OneToMany:
|
|
399
|
-
return 'one-to-many';
|
|
400
|
-
case AXPRelationshipCardinality.ManyToMany:
|
|
401
|
-
return 'many-to-many';
|
|
402
|
-
default:
|
|
403
|
-
return 'unknown';
|
|
404
|
-
}
|
|
405
|
-
}
|
|
406
|
-
/**
|
|
407
|
-
* Get kind description
|
|
408
|
-
*/
|
|
409
|
-
getKindDescription() {
|
|
410
|
-
switch (this.kind) {
|
|
411
|
-
case AXPRelationshipKind.Association:
|
|
412
|
-
return 'association';
|
|
413
|
-
case AXPRelationshipKind.Composition:
|
|
414
|
-
return 'composition';
|
|
415
|
-
case AXPRelationshipKind.Aggregation:
|
|
416
|
-
return 'aggregation';
|
|
417
|
-
default:
|
|
418
|
-
return 'unknown';
|
|
419
|
-
}
|
|
420
|
-
}
|
|
421
|
-
/**
|
|
422
|
-
* Get relation summary
|
|
423
|
-
*/
|
|
424
|
-
getSummary() {
|
|
425
|
-
return `${this.source.entity}.${this.source.key} -> ${this.target.aggregate}.${this.target.entity}.${this.target.key}`;
|
|
426
|
-
}
|
|
427
|
-
//#endregion
|
|
428
|
-
//#region ---- Validation Methods ----
|
|
429
|
-
/**
|
|
430
|
-
* Validate the relation structure
|
|
431
|
-
*/
|
|
432
|
-
validate() {
|
|
433
|
-
const errors = [];
|
|
434
|
-
// Validate source
|
|
435
|
-
if (!this.source.entity)
|
|
436
|
-
errors.push('Source entity is required');
|
|
437
|
-
if (!this.source.key)
|
|
438
|
-
errors.push('Source key is required');
|
|
439
|
-
// Validate target
|
|
440
|
-
if (!this.target.aggregate)
|
|
441
|
-
errors.push('Target aggregate is required');
|
|
442
|
-
if (!this.target.entity)
|
|
443
|
-
errors.push('Target entity is required');
|
|
444
|
-
if (!this.target.key)
|
|
445
|
-
errors.push('Target key is required');
|
|
446
|
-
return errors;
|
|
447
|
-
}
|
|
448
|
-
//#endregion
|
|
449
|
-
//#region ---- Utility Methods ----
|
|
450
|
-
/**
|
|
451
|
-
* Get relation characteristics
|
|
452
|
-
*/
|
|
453
|
-
getCharacteristics() {
|
|
454
|
-
return {
|
|
455
|
-
type: this.getCardinalityDescription(),
|
|
456
|
-
kind: this.getKindDescription(),
|
|
457
|
-
required: this.isRequired,
|
|
458
|
-
isOwning: this.isComposition(),
|
|
459
|
-
isNavigable: !this.isComposition() || this.isOneToOne()
|
|
460
|
-
};
|
|
461
|
-
}
|
|
462
|
-
/**
|
|
463
|
-
* Check if relation involves entity
|
|
464
|
-
*/
|
|
465
|
-
involvesEntity(entityName) {
|
|
466
|
-
return this.source.entity === entityName || this.target.entity === entityName;
|
|
467
|
-
}
|
|
468
|
-
/**
|
|
469
|
-
* Check if relation targets aggregate
|
|
470
|
-
*/
|
|
471
|
-
targetsAggregate(aggregateName) {
|
|
472
|
-
return this.target.aggregate === aggregateName;
|
|
473
|
-
}
|
|
474
|
-
/**
|
|
475
|
-
* Get the other entity in the relation
|
|
476
|
-
*/
|
|
477
|
-
getOtherEntity(entityName) {
|
|
478
|
-
if (this.source.entity === entityName) {
|
|
479
|
-
return this.target.entity;
|
|
480
|
-
}
|
|
481
|
-
else if (this.target.entity === entityName) {
|
|
482
|
-
return this.source.entity;
|
|
483
|
-
}
|
|
484
|
-
return null;
|
|
485
|
-
}
|
|
486
|
-
/**
|
|
487
|
-
* Convert back to interface definition
|
|
488
|
-
*/
|
|
489
|
-
toDefinition() {
|
|
490
|
-
return {
|
|
491
|
-
type: this.type,
|
|
492
|
-
kind: this.kind,
|
|
493
|
-
target: { ...this.target },
|
|
494
|
-
source: { ...this.source },
|
|
495
|
-
isRequired: this.isRequired
|
|
496
|
-
};
|
|
497
|
-
}
|
|
498
|
-
}
|
|
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
|
|
499
152
|
|
|
500
153
|
//#region ---- AXPAggregateModel ----
|
|
501
154
|
/**
|
|
502
155
|
* 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.
|
|
156
|
+
* Relations are stored in a separate collection; join when needed.
|
|
510
157
|
*/
|
|
511
158
|
class AXPAggregateModel {
|
|
512
159
|
constructor(definition, parent) {
|
|
513
|
-
this.relations = [];
|
|
514
160
|
this.name = definition.name;
|
|
515
161
|
this.title = definition.title;
|
|
516
162
|
this.validations = definition.validations || [];
|
|
517
163
|
this.actions = definition.actions || [];
|
|
518
164
|
this.parent = parent;
|
|
519
|
-
// Initialize relations with parent reference
|
|
520
|
-
this.relations = (definition.relations || []).map(relationDef => new AXPRelationModel(relationDef, this));
|
|
521
165
|
// Extract entity references - convert all formats to simple string map
|
|
522
166
|
this.entityReferences = this.extractEntityReferences(definition.entities);
|
|
523
167
|
}
|
|
@@ -585,27 +229,6 @@ class AXPAggregateModel {
|
|
|
585
229
|
hasEntity(entityName) {
|
|
586
230
|
return entityName in this.entityReferences;
|
|
587
231
|
}
|
|
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
232
|
//#endregion
|
|
610
233
|
//#region ---- Parent Navigation ----
|
|
611
234
|
/**
|
|
@@ -634,7 +257,6 @@ class AXPAggregateModel {
|
|
|
634
257
|
getStatistics() {
|
|
635
258
|
return {
|
|
636
259
|
entityCount: Object.keys(this.entityReferences).length,
|
|
637
|
-
relationCount: this.relations.length,
|
|
638
260
|
actionCount: this.actions.length,
|
|
639
261
|
validationCount: this.validations.length
|
|
640
262
|
};
|
|
@@ -649,7 +271,6 @@ class AXPAggregateModel {
|
|
|
649
271
|
name: this.name,
|
|
650
272
|
title: this.title,
|
|
651
273
|
entities: this.entityReferences, // Return as reference map
|
|
652
|
-
relations: this.relations.map(relation => relation.toDefinition()),
|
|
653
274
|
validations: this.validations,
|
|
654
275
|
actions: this.actions
|
|
655
276
|
};
|
|
@@ -668,13 +289,6 @@ class AXPAggregateModel {
|
|
|
668
289
|
errors.push('Aggregate name is required');
|
|
669
290
|
if (!this.title)
|
|
670
291
|
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
292
|
// Validate entity references
|
|
679
293
|
for (const [entityName, entityRef] of Object.entries(this.entityReferences)) {
|
|
680
294
|
if (!entityRef || typeof entityRef !== 'string') {
|
|
@@ -795,18 +409,11 @@ class AXPModuleModel {
|
|
|
795
409
|
return allReferences;
|
|
796
410
|
}
|
|
797
411
|
/**
|
|
798
|
-
*
|
|
799
|
-
*
|
|
800
|
-
* @returns Array of all relation models
|
|
412
|
+
* Relations are stored in a separate collection. Use relation queries for join when needed.
|
|
413
|
+
* @deprecated Relations are no longer nested in aggregates.
|
|
801
414
|
*/
|
|
802
415
|
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;
|
|
416
|
+
return [];
|
|
810
417
|
}
|
|
811
418
|
//#endregion
|
|
812
419
|
//#region ---- Validation Methods ----
|
|
@@ -837,135 +444,274 @@ class AXPModuleModel {
|
|
|
837
444
|
}
|
|
838
445
|
return errors;
|
|
839
446
|
}
|
|
840
|
-
//#endregion
|
|
841
|
-
//#region ---- Utility Methods ----
|
|
447
|
+
//#endregion
|
|
448
|
+
//#region ---- Utility Methods ----
|
|
449
|
+
/**
|
|
450
|
+
* Get module statistics
|
|
451
|
+
*
|
|
452
|
+
* @returns Statistics object
|
|
453
|
+
*/
|
|
454
|
+
getStatistics() {
|
|
455
|
+
const aggregateStats = this.aggregates.map(agg => agg.getStatistics());
|
|
456
|
+
return {
|
|
457
|
+
aggregateCount: this.aggregates.length,
|
|
458
|
+
entityCount: aggregateStats.reduce((sum, stat) => sum + stat.entityCount, 0),
|
|
459
|
+
actionCount: aggregateStats.reduce((sum, stat) => sum + stat.actionCount, 0),
|
|
460
|
+
validationCount: aggregateStats.reduce((sum, stat) => sum + stat.validationCount, 0)
|
|
461
|
+
};
|
|
462
|
+
}
|
|
463
|
+
/**
|
|
464
|
+
* Convert back to interface definition
|
|
465
|
+
*
|
|
466
|
+
* @returns Module definition
|
|
467
|
+
*/
|
|
468
|
+
toDefinition() {
|
|
469
|
+
return {
|
|
470
|
+
name: this.name,
|
|
471
|
+
title: this.title,
|
|
472
|
+
aggregates: this.aggregates.map(agg => agg.toDefinition())
|
|
473
|
+
};
|
|
474
|
+
}
|
|
475
|
+
}
|
|
476
|
+
//#endregion
|
|
477
|
+
|
|
478
|
+
//#region ---- AXPPropertyModel ----
|
|
479
|
+
/**
|
|
480
|
+
* Runtime model for a {@link AXPPropertyDefinition} with helper methods.
|
|
481
|
+
*/
|
|
482
|
+
class AXPPropertyModel {
|
|
483
|
+
constructor(definition) {
|
|
484
|
+
this.name = definition.name;
|
|
485
|
+
this.title = definition.title;
|
|
486
|
+
this.interface = definition.interface;
|
|
487
|
+
this.disabled = definition.disabled;
|
|
488
|
+
this.dataType = definition.dataType ?? 'string';
|
|
489
|
+
this.validations = definition.validations ?? [];
|
|
490
|
+
this.features = definition.features ?? {};
|
|
491
|
+
this.metadata = definition.metadata;
|
|
492
|
+
this.description = definition.description;
|
|
493
|
+
this.icon = definition.icon;
|
|
494
|
+
this.defaultValue = definition.defaultValue;
|
|
495
|
+
}
|
|
496
|
+
//#endregion
|
|
497
|
+
/**
|
|
498
|
+
* Get widget options
|
|
499
|
+
*/
|
|
500
|
+
getWidgetOptions() {
|
|
501
|
+
return this.interface.options;
|
|
502
|
+
}
|
|
503
|
+
/**
|
|
504
|
+
* Check if the property is disabled
|
|
505
|
+
*/
|
|
506
|
+
isDisabled() {
|
|
507
|
+
return this.disabled ?? false;
|
|
508
|
+
}
|
|
509
|
+
//#endregion
|
|
510
|
+
//#region ---- Feature Methods ----
|
|
511
|
+
/**
|
|
512
|
+
* Check if searchable
|
|
513
|
+
*/
|
|
514
|
+
isSearchable() {
|
|
515
|
+
return this.features.searchable?.enabled ?? false;
|
|
516
|
+
}
|
|
517
|
+
/**
|
|
518
|
+
* Check if full text searchable
|
|
519
|
+
*/
|
|
520
|
+
isFullTextSearchable() {
|
|
521
|
+
return this.features.searchable?.fullText ?? false;
|
|
522
|
+
}
|
|
523
|
+
/**
|
|
524
|
+
* Check if filterable
|
|
525
|
+
*/
|
|
526
|
+
isFilterable() {
|
|
527
|
+
return this.features.filterable?.enabled ?? false;
|
|
528
|
+
}
|
|
529
|
+
/**
|
|
530
|
+
* Check if inline filterable
|
|
531
|
+
*/
|
|
532
|
+
isInlineFilterable() {
|
|
533
|
+
return this.features.filterable?.inline ?? false;
|
|
534
|
+
}
|
|
535
|
+
/**
|
|
536
|
+
* Check if sortable
|
|
537
|
+
*/
|
|
538
|
+
isSortable() {
|
|
539
|
+
return this.features.sortable?.enabled ?? false;
|
|
540
|
+
}
|
|
541
|
+
/**
|
|
542
|
+
* Check if auditable
|
|
543
|
+
*/
|
|
544
|
+
isAuditable() {
|
|
545
|
+
return this.features.auditable?.enabled ?? false;
|
|
546
|
+
}
|
|
547
|
+
//#endregion
|
|
548
|
+
//#region ---- Validation Methods ----
|
|
549
|
+
/**
|
|
550
|
+
* Validate the property definition structure
|
|
551
|
+
*/
|
|
552
|
+
async validate() {
|
|
553
|
+
const errors = [];
|
|
554
|
+
// Validate interface
|
|
555
|
+
if (!this.interface.name) {
|
|
556
|
+
errors.push('Widget type is required');
|
|
557
|
+
}
|
|
558
|
+
return errors;
|
|
559
|
+
}
|
|
560
|
+
//#endregion
|
|
561
|
+
//#region ---- Utility Methods ----
|
|
562
|
+
/**
|
|
563
|
+
* Get property capabilities
|
|
564
|
+
*/
|
|
565
|
+
getCapabilities() {
|
|
566
|
+
return {
|
|
567
|
+
searchable: this.isSearchable(),
|
|
568
|
+
fullTextSearchable: this.isFullTextSearchable(),
|
|
569
|
+
filterable: this.isFilterable(),
|
|
570
|
+
inlineFilterable: this.isInlineFilterable(),
|
|
571
|
+
sortable: this.isSortable(),
|
|
572
|
+
auditable: this.isAuditable(),
|
|
573
|
+
disabled: this.isDisabled()
|
|
574
|
+
};
|
|
575
|
+
}
|
|
842
576
|
/**
|
|
843
|
-
* Get
|
|
844
|
-
*
|
|
845
|
-
* @returns Statistics object
|
|
577
|
+
* Get property summary
|
|
846
578
|
*/
|
|
847
|
-
|
|
848
|
-
const
|
|
579
|
+
getSummary() {
|
|
580
|
+
const capabilities = this.getCapabilities();
|
|
581
|
+
const capabilityCount = Object.values(capabilities).filter(Boolean).length;
|
|
849
582
|
return {
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
583
|
+
widget: this.interface.name,
|
|
584
|
+
hasOptions: !!this.interface.options,
|
|
585
|
+
hasMetadata: !!this.metadata,
|
|
586
|
+
hasValidations: !!this.validations && this.validations.length > 0,
|
|
587
|
+
capabilityCount
|
|
855
588
|
};
|
|
856
589
|
}
|
|
857
590
|
/**
|
|
858
591
|
* Convert back to interface definition
|
|
859
|
-
*
|
|
860
|
-
* @returns Module definition
|
|
861
592
|
*/
|
|
862
593
|
toDefinition() {
|
|
863
594
|
return {
|
|
864
595
|
name: this.name,
|
|
865
596
|
title: this.title,
|
|
866
|
-
|
|
597
|
+
description: this.description,
|
|
598
|
+
icon: this.icon,
|
|
599
|
+
dataType: this.dataType,
|
|
600
|
+
defaultValue: this.defaultValue,
|
|
601
|
+
disabled: this.disabled,
|
|
602
|
+
interface: this.interface,
|
|
603
|
+
validations: this.validations,
|
|
604
|
+
features: this.features,
|
|
605
|
+
metadata: this.metadata
|
|
867
606
|
};
|
|
868
607
|
}
|
|
869
608
|
}
|
|
870
|
-
//#endregion
|
|
871
609
|
|
|
610
|
+
//#region ---- Property definition helpers ----
|
|
611
|
+
/**
|
|
612
|
+
* Strips entity-only fields so the payload matches {@link AXPPropertyDefinition}.
|
|
613
|
+
*/
|
|
614
|
+
function toPropertyDefinition(def) {
|
|
615
|
+
const { actions, fieldFeatures, ...propertyDefinition } = def;
|
|
616
|
+
return propertyDefinition;
|
|
617
|
+
}
|
|
618
|
+
//#endregion
|
|
872
619
|
//#region ---- AXPEntityFieldModel ----
|
|
873
620
|
/**
|
|
874
621
|
* Runtime model for entity field definitions with parent references and helper methods
|
|
875
622
|
*/
|
|
876
623
|
class AXPEntityFieldModel {
|
|
877
|
-
constructor(definition, parent,
|
|
624
|
+
constructor(definition, parent, propertyService) {
|
|
625
|
+
this.entityPropertyDefinition = definition;
|
|
878
626
|
this.name = definition.name;
|
|
879
627
|
this.title = definition.title;
|
|
880
628
|
this.description = definition.description;
|
|
881
629
|
this.validations = definition.validations;
|
|
882
630
|
this.actions = definition.actions;
|
|
883
|
-
this.
|
|
631
|
+
this.fieldFeatures = definition.fieldFeatures;
|
|
884
632
|
this.defaultValue = definition.defaultValue;
|
|
885
633
|
this.parent = parent;
|
|
886
|
-
this.
|
|
887
|
-
|
|
888
|
-
this.
|
|
889
|
-
// Resolve schema by name from schema service
|
|
890
|
-
this.schema = schemaService.resolveSync(definition.schema);
|
|
634
|
+
this.propertyService = propertyService;
|
|
635
|
+
this.property = new AXPPropertyModel(toPropertyDefinition(definition));
|
|
636
|
+
this.propertyName = definition.name;
|
|
891
637
|
}
|
|
892
|
-
//#endregion
|
|
893
638
|
//#region ---- Feature Check Methods ----
|
|
894
639
|
/**
|
|
895
640
|
* Check if field is nullable
|
|
896
641
|
*/
|
|
897
642
|
isNullable() {
|
|
898
|
-
return this.
|
|
643
|
+
return this.fieldFeatures?.nullable ?? false;
|
|
899
644
|
}
|
|
900
645
|
/**
|
|
901
646
|
* Check if field is readonly
|
|
902
647
|
*/
|
|
903
648
|
isReadonly() {
|
|
904
|
-
return this.
|
|
649
|
+
return this.fieldFeatures?.readOnly ?? false;
|
|
905
650
|
}
|
|
906
651
|
/**
|
|
907
652
|
* Check if field is required (has required validation)
|
|
908
653
|
*/
|
|
909
654
|
isRequired() {
|
|
910
|
-
return this.validations?.some(validation => validation.rule ===
|
|
655
|
+
return this.validations?.some((validation) => validation.rule === "required") ?? false;
|
|
911
656
|
}
|
|
912
657
|
/**
|
|
913
658
|
* Check if field is searchable
|
|
914
659
|
*/
|
|
915
660
|
isSearchable() {
|
|
916
|
-
return this.
|
|
661
|
+
return this.property.features?.searchable?.enabled ?? false;
|
|
917
662
|
}
|
|
918
663
|
/**
|
|
919
664
|
* Check if field supports full text search
|
|
920
665
|
*/
|
|
921
666
|
isFullTextSearchable() {
|
|
922
|
-
return this.
|
|
667
|
+
return this.property.features?.searchable?.fullText ?? false;
|
|
923
668
|
}
|
|
924
669
|
/**
|
|
925
670
|
* Check if field is filterable
|
|
926
671
|
*/
|
|
927
672
|
isFilterable() {
|
|
928
|
-
return this.
|
|
673
|
+
return this.property.features?.filterable?.enabled ?? false;
|
|
929
674
|
}
|
|
930
675
|
/**
|
|
931
676
|
* Check if field has inline filtering
|
|
932
677
|
*/
|
|
933
678
|
hasInlineFiltering() {
|
|
934
|
-
return this.
|
|
679
|
+
return this.property.features?.filterable?.inline ?? false;
|
|
935
680
|
}
|
|
936
681
|
/**
|
|
937
682
|
* Check if field is sortable
|
|
938
683
|
*/
|
|
939
684
|
isSortable() {
|
|
940
|
-
return this.
|
|
685
|
+
return this.property.features?.sortable?.enabled ?? false;
|
|
941
686
|
}
|
|
942
687
|
/**
|
|
943
688
|
* Check if field is auditable
|
|
944
689
|
*/
|
|
945
690
|
isAuditable() {
|
|
946
|
-
return this.
|
|
691
|
+
return this.property.features?.auditable?.enabled ?? false;
|
|
947
692
|
}
|
|
948
693
|
//#endregion
|
|
949
|
-
//#region ----
|
|
694
|
+
//#region ---- Property info ----
|
|
950
695
|
/**
|
|
951
|
-
*
|
|
696
|
+
* Registered property name (same as entity field name in the embedded model).
|
|
952
697
|
*/
|
|
953
|
-
|
|
954
|
-
return this.
|
|
698
|
+
getPropertyName() {
|
|
699
|
+
return this.propertyName;
|
|
955
700
|
}
|
|
956
701
|
/**
|
|
957
|
-
*
|
|
702
|
+
* Registration metadata when this field's definition name is registered; otherwise embedded summary.
|
|
958
703
|
*/
|
|
959
|
-
|
|
960
|
-
|
|
704
|
+
getPropertyInfo() {
|
|
705
|
+
if (this.propertyService.isRegistered(this.property.name)) {
|
|
706
|
+
return this.propertyService.getRegisteredProperty(this.property.name);
|
|
707
|
+
}
|
|
708
|
+
return this.property.getSummary();
|
|
961
709
|
}
|
|
962
710
|
/**
|
|
963
|
-
*
|
|
711
|
+
* Rebuild the property model from embedded definition (e.g. after definition updates).
|
|
964
712
|
*/
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
this.schema = newSchema;
|
|
968
|
-
this.schema.parent = this;
|
|
713
|
+
refreshProperty() {
|
|
714
|
+
this.property = new AXPPropertyModel(toPropertyDefinition(this.entityPropertyDefinition));
|
|
969
715
|
}
|
|
970
716
|
//#endregion
|
|
971
717
|
//#region ---- Navigation Methods ----
|
|
@@ -1000,25 +746,17 @@ class AXPEntityFieldModel {
|
|
|
1000
746
|
*/
|
|
1001
747
|
async validate() {
|
|
1002
748
|
const errors = [];
|
|
1003
|
-
// Validate field structure
|
|
1004
749
|
if (!this.name)
|
|
1005
|
-
errors.push(
|
|
750
|
+
errors.push("Field name is required");
|
|
1006
751
|
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}`));
|
|
752
|
+
errors.push("Field title is required");
|
|
753
|
+
if (!this.property.interface?.name) {
|
|
754
|
+
errors.push("Widget type (interface.name) is required");
|
|
755
|
+
}
|
|
756
|
+
if (this.property) {
|
|
757
|
+
const propertyErrors = await this.property.validate();
|
|
758
|
+
if (propertyErrors.length > 0) {
|
|
759
|
+
errors.push(...propertyErrors.map((err) => `Property: ${err}`));
|
|
1022
760
|
}
|
|
1023
761
|
}
|
|
1024
762
|
return errors;
|
|
@@ -1032,10 +770,10 @@ class AXPEntityFieldModel {
|
|
|
1032
770
|
return {
|
|
1033
771
|
hasValidations: !!this.validations && this.validations.length > 0,
|
|
1034
772
|
hasActions: !!this.actions && this.actions.length > 0,
|
|
1035
|
-
|
|
773
|
+
hasFieldFeatures: !!this.fieldFeatures,
|
|
1036
774
|
hasDefaultValue: this.defaultValue !== undefined,
|
|
1037
775
|
validationCount: this.validations?.length ?? 0,
|
|
1038
|
-
actionCount: this.actions?.length ?? 0
|
|
776
|
+
actionCount: this.actions?.length ?? 0,
|
|
1039
777
|
};
|
|
1040
778
|
}
|
|
1041
779
|
/**
|
|
@@ -1049,7 +787,7 @@ class AXPEntityFieldModel {
|
|
|
1049
787
|
auditable: this.isAuditable(),
|
|
1050
788
|
nullable: this.isNullable(),
|
|
1051
789
|
readonly: this.isReadonly(),
|
|
1052
|
-
required: this.isRequired()
|
|
790
|
+
required: this.isRequired(),
|
|
1053
791
|
};
|
|
1054
792
|
}
|
|
1055
793
|
/**
|
|
@@ -1057,32 +795,28 @@ class AXPEntityFieldModel {
|
|
|
1057
795
|
*/
|
|
1058
796
|
toDefinition() {
|
|
1059
797
|
return {
|
|
1060
|
-
|
|
1061
|
-
title: this.title,
|
|
1062
|
-
description: this.description,
|
|
1063
|
-
validations: this.validations,
|
|
798
|
+
...this.property.toDefinition(),
|
|
1064
799
|
actions: this.actions,
|
|
1065
|
-
|
|
1066
|
-
defaultValue: this.defaultValue,
|
|
1067
|
-
schema: this.schemaName
|
|
800
|
+
fieldFeatures: this.fieldFeatures,
|
|
1068
801
|
};
|
|
1069
802
|
}
|
|
1070
803
|
}
|
|
804
|
+
//#endregion
|
|
1071
805
|
|
|
1072
806
|
//#region ---- AXPEntityModel ----
|
|
1073
807
|
/**
|
|
1074
808
|
* Runtime model for entity definitions with parent references and helper methods
|
|
1075
809
|
*/
|
|
1076
810
|
class AXPEntityModel {
|
|
1077
|
-
constructor(definition, parent,
|
|
811
|
+
constructor(definition, parent, propertyService) {
|
|
1078
812
|
this.fields = [];
|
|
1079
813
|
this.name = definition.name;
|
|
1080
814
|
this.title = definition.title;
|
|
1081
815
|
this.type = definition.type;
|
|
1082
816
|
this.parent = parent;
|
|
1083
|
-
this.
|
|
1084
|
-
// Initialize fields with parent reference and
|
|
1085
|
-
this.fields = definition.fields.map(fieldDef => new AXPEntityFieldModel(fieldDef, this,
|
|
817
|
+
this.propertyService = propertyService;
|
|
818
|
+
// Initialize fields with parent reference and property service
|
|
819
|
+
this.fields = definition.fields.map(fieldDef => new AXPEntityFieldModel(fieldDef, this, propertyService));
|
|
1086
820
|
}
|
|
1087
821
|
//#endregion
|
|
1088
822
|
//#region ---- Query Methods ----
|
|
@@ -1098,12 +832,6 @@ class AXPEntityModel {
|
|
|
1098
832
|
getAllFields() {
|
|
1099
833
|
return [...this.fields];
|
|
1100
834
|
}
|
|
1101
|
-
/**
|
|
1102
|
-
* Get fields by data type
|
|
1103
|
-
*/
|
|
1104
|
-
getFieldsByType(dataType) {
|
|
1105
|
-
return this.fields.filter(field => field.schema.dataType === dataType);
|
|
1106
|
-
}
|
|
1107
835
|
/**
|
|
1108
836
|
* Get required fields
|
|
1109
837
|
*/
|
|
@@ -1223,181 +951,196 @@ class AXPEntityModel {
|
|
|
1223
951
|
}
|
|
1224
952
|
}
|
|
1225
953
|
|
|
1226
|
-
//#region ----
|
|
954
|
+
//#region ---- AXPRelationModel ----
|
|
1227
955
|
/**
|
|
1228
|
-
* Runtime model for
|
|
956
|
+
* Runtime model for standalone relation definitions.
|
|
957
|
+
* Relations live in their own collection; join when needed.
|
|
1229
958
|
*/
|
|
1230
|
-
class
|
|
1231
|
-
constructor(definition) {
|
|
1232
|
-
this.
|
|
1233
|
-
this.
|
|
1234
|
-
this.
|
|
1235
|
-
this.
|
|
1236
|
-
this.
|
|
1237
|
-
this.
|
|
959
|
+
class AXPRelationModel {
|
|
960
|
+
constructor(definition, parent) {
|
|
961
|
+
this.type = definition.type;
|
|
962
|
+
this.kind = definition.kind;
|
|
963
|
+
this.target = { ...definition.target };
|
|
964
|
+
this.source = { ...definition.source };
|
|
965
|
+
this.isRequired = definition.isRequired;
|
|
966
|
+
this.parent = parent;
|
|
1238
967
|
}
|
|
1239
968
|
//#endregion
|
|
1240
|
-
//#region ----
|
|
1241
|
-
/**
|
|
1242
|
-
* Check if schema is for string data
|
|
1243
|
-
*/
|
|
1244
|
-
isString() {
|
|
1245
|
-
return this.dataType === 'string';
|
|
1246
|
-
}
|
|
969
|
+
//#region ---- Cardinality Methods ----
|
|
1247
970
|
/**
|
|
1248
|
-
* Check if
|
|
971
|
+
* Check if relation is one-to-one
|
|
1249
972
|
*/
|
|
1250
|
-
|
|
1251
|
-
return this.
|
|
973
|
+
isOneToOne() {
|
|
974
|
+
return this.type === AXPRelationshipCardinality.OneToOne;
|
|
1252
975
|
}
|
|
1253
976
|
/**
|
|
1254
|
-
* Check if
|
|
977
|
+
* Check if relation is one-to-many
|
|
1255
978
|
*/
|
|
1256
|
-
|
|
1257
|
-
return this.
|
|
979
|
+
isOneToMany() {
|
|
980
|
+
return this.type === AXPRelationshipCardinality.OneToMany;
|
|
1258
981
|
}
|
|
1259
982
|
/**
|
|
1260
|
-
* Check if
|
|
983
|
+
* Check if relation is many-to-many
|
|
1261
984
|
*/
|
|
1262
|
-
|
|
1263
|
-
return this.
|
|
985
|
+
isManyToMany() {
|
|
986
|
+
return this.type === AXPRelationshipCardinality.ManyToMany;
|
|
1264
987
|
}
|
|
988
|
+
//#endregion
|
|
989
|
+
//#region ---- Kind Methods ----
|
|
1265
990
|
/**
|
|
1266
|
-
* Check if
|
|
991
|
+
* Check if relation is association
|
|
1267
992
|
*/
|
|
1268
|
-
|
|
1269
|
-
return this.
|
|
993
|
+
isAssociation() {
|
|
994
|
+
return this.kind === AXPRelationshipKind.Association;
|
|
1270
995
|
}
|
|
1271
996
|
/**
|
|
1272
|
-
* Check if
|
|
997
|
+
* Check if relation is composition
|
|
1273
998
|
*/
|
|
1274
|
-
|
|
1275
|
-
return this.
|
|
999
|
+
isComposition() {
|
|
1000
|
+
return this.kind === AXPRelationshipKind.Composition;
|
|
1276
1001
|
}
|
|
1277
1002
|
/**
|
|
1278
|
-
* Check if
|
|
1003
|
+
* Check if relation is aggregation
|
|
1279
1004
|
*/
|
|
1280
|
-
|
|
1281
|
-
return this.
|
|
1005
|
+
isAggregation() {
|
|
1006
|
+
return this.kind === AXPRelationshipKind.Aggregation;
|
|
1282
1007
|
}
|
|
1283
1008
|
//#endregion
|
|
1284
|
-
//#region ----
|
|
1009
|
+
//#region ---- Navigation Methods ----
|
|
1285
1010
|
/**
|
|
1286
|
-
* Get
|
|
1011
|
+
* Get parent aggregate
|
|
1287
1012
|
*/
|
|
1288
|
-
|
|
1289
|
-
return this.
|
|
1013
|
+
getAggregate() {
|
|
1014
|
+
return this.parent;
|
|
1290
1015
|
}
|
|
1291
1016
|
/**
|
|
1292
|
-
* Get
|
|
1017
|
+
* Get parent module
|
|
1293
1018
|
*/
|
|
1294
|
-
|
|
1295
|
-
return this.
|
|
1019
|
+
getModule() {
|
|
1020
|
+
return this.parent?.parent;
|
|
1296
1021
|
}
|
|
1297
1022
|
/**
|
|
1298
|
-
*
|
|
1023
|
+
* Get full path (module.aggregate.relation)
|
|
1299
1024
|
*/
|
|
1300
|
-
|
|
1301
|
-
return this.
|
|
1025
|
+
getPath() {
|
|
1026
|
+
return `${this.parent.parent.name}.${this.parent.name}.${this.source.entity}->${this.target.entity}`;
|
|
1302
1027
|
}
|
|
1303
1028
|
//#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
|
-
}
|
|
1029
|
+
//#region ---- Query Methods ----
|
|
1317
1030
|
/**
|
|
1318
|
-
*
|
|
1031
|
+
* Get relation description
|
|
1319
1032
|
*/
|
|
1320
|
-
|
|
1321
|
-
|
|
1033
|
+
getDescription() {
|
|
1034
|
+
const cardinalityDesc = this.getCardinalityDescription();
|
|
1035
|
+
const kindDesc = this.getKindDescription();
|
|
1036
|
+
const requiredDesc = this.isRequired ? 'required' : 'optional';
|
|
1037
|
+
return `${cardinalityDesc} ${kindDesc} (${requiredDesc})`;
|
|
1322
1038
|
}
|
|
1323
1039
|
/**
|
|
1324
|
-
*
|
|
1040
|
+
* Get cardinality description
|
|
1325
1041
|
*/
|
|
1326
|
-
|
|
1327
|
-
|
|
1042
|
+
getCardinalityDescription() {
|
|
1043
|
+
switch (this.type) {
|
|
1044
|
+
case AXPRelationshipCardinality.OneToOne:
|
|
1045
|
+
return 'one-to-one';
|
|
1046
|
+
case AXPRelationshipCardinality.OneToMany:
|
|
1047
|
+
return 'one-to-many';
|
|
1048
|
+
case AXPRelationshipCardinality.ManyToMany:
|
|
1049
|
+
return 'many-to-many';
|
|
1050
|
+
default:
|
|
1051
|
+
return 'unknown';
|
|
1052
|
+
}
|
|
1328
1053
|
}
|
|
1329
1054
|
/**
|
|
1330
|
-
*
|
|
1055
|
+
* Get kind description
|
|
1331
1056
|
*/
|
|
1332
|
-
|
|
1333
|
-
|
|
1057
|
+
getKindDescription() {
|
|
1058
|
+
switch (this.kind) {
|
|
1059
|
+
case AXPRelationshipKind.Association:
|
|
1060
|
+
return 'association';
|
|
1061
|
+
case AXPRelationshipKind.Composition:
|
|
1062
|
+
return 'composition';
|
|
1063
|
+
case AXPRelationshipKind.Aggregation:
|
|
1064
|
+
return 'aggregation';
|
|
1065
|
+
default:
|
|
1066
|
+
return 'unknown';
|
|
1067
|
+
}
|
|
1334
1068
|
}
|
|
1335
1069
|
/**
|
|
1336
|
-
*
|
|
1070
|
+
* Get relation summary
|
|
1337
1071
|
*/
|
|
1338
|
-
|
|
1339
|
-
return this.
|
|
1072
|
+
getSummary() {
|
|
1073
|
+
return `${this.source.entity}.${this.source.key} -> ${this.target.aggregate}.${this.target.entity}.${this.target.key}`;
|
|
1340
1074
|
}
|
|
1341
1075
|
//#endregion
|
|
1342
1076
|
//#region ---- Validation Methods ----
|
|
1343
1077
|
/**
|
|
1344
|
-
* Validate the
|
|
1078
|
+
* Validate the relation structure
|
|
1345
1079
|
*/
|
|
1346
|
-
|
|
1080
|
+
validate() {
|
|
1347
1081
|
const errors = [];
|
|
1348
|
-
// Validate
|
|
1349
|
-
|
|
1350
|
-
|
|
1351
|
-
|
|
1352
|
-
|
|
1353
|
-
// Validate
|
|
1354
|
-
if (!this.
|
|
1355
|
-
errors.push('
|
|
1356
|
-
|
|
1082
|
+
// Validate source
|
|
1083
|
+
if (!this.source.entity)
|
|
1084
|
+
errors.push('Source entity is required');
|
|
1085
|
+
if (!this.source.key)
|
|
1086
|
+
errors.push('Source key is required');
|
|
1087
|
+
// Validate target
|
|
1088
|
+
if (!this.target.aggregate)
|
|
1089
|
+
errors.push('Target aggregate is required');
|
|
1090
|
+
if (!this.target.entity)
|
|
1091
|
+
errors.push('Target entity is required');
|
|
1092
|
+
if (!this.target.key)
|
|
1093
|
+
errors.push('Target key is required');
|
|
1357
1094
|
return errors;
|
|
1358
1095
|
}
|
|
1359
1096
|
//#endregion
|
|
1360
1097
|
//#region ---- Utility Methods ----
|
|
1361
1098
|
/**
|
|
1362
|
-
* Get
|
|
1099
|
+
* Get relation characteristics
|
|
1363
1100
|
*/
|
|
1364
|
-
|
|
1101
|
+
getCharacteristics() {
|
|
1365
1102
|
return {
|
|
1366
|
-
|
|
1367
|
-
|
|
1368
|
-
|
|
1369
|
-
|
|
1370
|
-
|
|
1371
|
-
auditable: this.isAuditable(),
|
|
1372
|
-
disabled: this.isDisabled()
|
|
1103
|
+
type: this.getCardinalityDescription(),
|
|
1104
|
+
kind: this.getKindDescription(),
|
|
1105
|
+
required: this.isRequired,
|
|
1106
|
+
isOwning: this.isComposition(),
|
|
1107
|
+
isNavigable: !this.isComposition() || this.isOneToOne()
|
|
1373
1108
|
};
|
|
1374
1109
|
}
|
|
1375
1110
|
/**
|
|
1376
|
-
*
|
|
1111
|
+
* Check if relation involves entity
|
|
1377
1112
|
*/
|
|
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
|
-
};
|
|
1113
|
+
involvesEntity(entityName) {
|
|
1114
|
+
return this.source.entity === entityName || this.target.entity === entityName;
|
|
1389
1115
|
}
|
|
1390
1116
|
/**
|
|
1391
|
-
*
|
|
1117
|
+
* Check if relation targets aggregate
|
|
1118
|
+
*/
|
|
1119
|
+
targetsAggregate(aggregateName) {
|
|
1120
|
+
return this.target.aggregate === aggregateName;
|
|
1121
|
+
}
|
|
1122
|
+
/**
|
|
1123
|
+
* Get the other entity in the relation
|
|
1124
|
+
*/
|
|
1125
|
+
getOtherEntity(entityName) {
|
|
1126
|
+
if (this.source.entity === entityName) {
|
|
1127
|
+
return this.target.entity;
|
|
1128
|
+
}
|
|
1129
|
+
else if (this.target.entity === entityName) {
|
|
1130
|
+
return this.source.entity;
|
|
1131
|
+
}
|
|
1132
|
+
return null;
|
|
1133
|
+
}
|
|
1134
|
+
/**
|
|
1135
|
+
* Convert back to interface definition (AXPRelationDefinition with full source/target)
|
|
1392
1136
|
*/
|
|
1393
1137
|
toDefinition() {
|
|
1394
1138
|
return {
|
|
1395
|
-
|
|
1396
|
-
|
|
1397
|
-
|
|
1398
|
-
|
|
1399
|
-
|
|
1400
|
-
metadata: this.metadata
|
|
1139
|
+
type: this.type,
|
|
1140
|
+
kind: this.kind,
|
|
1141
|
+
target: { ...this.target },
|
|
1142
|
+
source: { ...this.source },
|
|
1143
|
+
isRequired: this.isRequired
|
|
1401
1144
|
};
|
|
1402
1145
|
}
|
|
1403
1146
|
}
|
|
@@ -1471,10 +1214,10 @@ class AXPModuleHelper {
|
|
|
1471
1214
|
return [];
|
|
1472
1215
|
}
|
|
1473
1216
|
/**
|
|
1474
|
-
* @deprecated Use AXPDomainService with
|
|
1217
|
+
* @deprecated Use AXPDomainService with registered property name queries instead
|
|
1475
1218
|
*/
|
|
1476
|
-
static
|
|
1477
|
-
console.warn('AXPModuleHelper.
|
|
1219
|
+
static findFieldsByRegisteredPropertyName(module, propertyName) {
|
|
1220
|
+
console.warn('AXPModuleHelper.findFieldsByRegisteredPropertyName is deprecated. Use AXPDomainService instead.');
|
|
1478
1221
|
return [];
|
|
1479
1222
|
}
|
|
1480
1223
|
/**
|
|
@@ -1545,23 +1288,23 @@ class AXPModuleHelper {
|
|
|
1545
1288
|
* }
|
|
1546
1289
|
* ```
|
|
1547
1290
|
*/
|
|
1548
|
-
class
|
|
1549
|
-
constructor(
|
|
1550
|
-
// Deep clone to avoid mutating the original
|
|
1551
|
-
this.
|
|
1291
|
+
class AXPPropertyMiddlewareContext {
|
|
1292
|
+
constructor(definition) {
|
|
1293
|
+
// Deep clone to avoid mutating the original definition
|
|
1294
|
+
this._definition = JSON.parse(JSON.stringify(definition));
|
|
1552
1295
|
}
|
|
1553
1296
|
//#region ---- Schema Access Properties ----
|
|
1554
1297
|
/**
|
|
1555
1298
|
* Get the current schema definition (readonly access)
|
|
1556
1299
|
*/
|
|
1557
|
-
get
|
|
1558
|
-
return this.
|
|
1300
|
+
get definition() {
|
|
1301
|
+
return this._definition;
|
|
1559
1302
|
}
|
|
1560
1303
|
/**
|
|
1561
1304
|
* Get the schema name for conditional logic
|
|
1562
1305
|
*/
|
|
1563
1306
|
get name() {
|
|
1564
|
-
return this.
|
|
1307
|
+
return this._definition.name;
|
|
1565
1308
|
}
|
|
1566
1309
|
//#endregion
|
|
1567
1310
|
//#region ---- Default Value Management ----
|
|
@@ -1570,18 +1313,18 @@ class AXPSchemaMiddlewareContext {
|
|
|
1570
1313
|
* @param defaultValue The default value to set
|
|
1571
1314
|
*/
|
|
1572
1315
|
withDefaultValue(defaultValue) {
|
|
1573
|
-
if (!this.
|
|
1574
|
-
this.
|
|
1316
|
+
if (!this._definition.interface.options) {
|
|
1317
|
+
this._definition.interface.options = {};
|
|
1575
1318
|
}
|
|
1576
|
-
this.
|
|
1319
|
+
this._definition.interface.options['defaultValue'] = defaultValue;
|
|
1577
1320
|
return this;
|
|
1578
1321
|
}
|
|
1579
1322
|
/**
|
|
1580
1323
|
* Remove the default value from the widget
|
|
1581
1324
|
*/
|
|
1582
1325
|
removeDefaultValue() {
|
|
1583
|
-
if (this.
|
|
1584
|
-
delete this.
|
|
1326
|
+
if (this._definition.interface.options) {
|
|
1327
|
+
delete this._definition.interface.options['defaultValue'];
|
|
1585
1328
|
}
|
|
1586
1329
|
return this;
|
|
1587
1330
|
}
|
|
@@ -1592,10 +1335,10 @@ class AXPSchemaMiddlewareContext {
|
|
|
1592
1335
|
* @param rules Array of validation rules to add
|
|
1593
1336
|
*/
|
|
1594
1337
|
withValidation(rules) {
|
|
1595
|
-
if (!this.
|
|
1596
|
-
this.
|
|
1338
|
+
if (!this._definition.validations) {
|
|
1339
|
+
this._definition.validations = [];
|
|
1597
1340
|
}
|
|
1598
|
-
this.
|
|
1341
|
+
this._definition.validations.push(...rules);
|
|
1599
1342
|
return this;
|
|
1600
1343
|
}
|
|
1601
1344
|
/**
|
|
@@ -1603,10 +1346,10 @@ class AXPSchemaMiddlewareContext {
|
|
|
1603
1346
|
* @param rule The validation rule to add
|
|
1604
1347
|
*/
|
|
1605
1348
|
addValidation(rule) {
|
|
1606
|
-
if (!this.
|
|
1607
|
-
this.
|
|
1349
|
+
if (!this._definition.validations) {
|
|
1350
|
+
this._definition.validations = [];
|
|
1608
1351
|
}
|
|
1609
|
-
this.
|
|
1352
|
+
this._definition.validations.push(rule);
|
|
1610
1353
|
return this;
|
|
1611
1354
|
}
|
|
1612
1355
|
/**
|
|
@@ -1620,7 +1363,7 @@ class AXPSchemaMiddlewareContext {
|
|
|
1620
1363
|
* Remove all validation rules from the schema
|
|
1621
1364
|
*/
|
|
1622
1365
|
clearValidations() {
|
|
1623
|
-
this.
|
|
1366
|
+
this._definition.validations = [];
|
|
1624
1367
|
return this;
|
|
1625
1368
|
}
|
|
1626
1369
|
/**
|
|
@@ -1628,8 +1371,8 @@ class AXPSchemaMiddlewareContext {
|
|
|
1628
1371
|
* @param ruleName The name of the rule to remove (e.g., 'required', 'email')
|
|
1629
1372
|
*/
|
|
1630
1373
|
removeValidation(ruleName) {
|
|
1631
|
-
if (this.
|
|
1632
|
-
this.
|
|
1374
|
+
if (this._definition.validations) {
|
|
1375
|
+
this._definition.validations = this._definition.validations.filter((v) => v.rule !== ruleName);
|
|
1633
1376
|
}
|
|
1634
1377
|
return this;
|
|
1635
1378
|
}
|
|
@@ -1640,8 +1383,9 @@ class AXPSchemaMiddlewareContext {
|
|
|
1640
1383
|
* @param options Object containing widget-specific options to merge
|
|
1641
1384
|
*/
|
|
1642
1385
|
withWidgetOptions(options) {
|
|
1643
|
-
this.
|
|
1644
|
-
|
|
1386
|
+
const current = this._definition.interface.options ?? {};
|
|
1387
|
+
this._definition.interface.options = {
|
|
1388
|
+
...current,
|
|
1645
1389
|
...options
|
|
1646
1390
|
};
|
|
1647
1391
|
return this;
|
|
@@ -1651,8 +1395,8 @@ class AXPSchemaMiddlewareContext {
|
|
|
1651
1395
|
* @param optionKey The key of the option to remove
|
|
1652
1396
|
*/
|
|
1653
1397
|
removeWidgetOption(optionKey) {
|
|
1654
|
-
if (this.
|
|
1655
|
-
delete this.
|
|
1398
|
+
if (this._definition.interface.options) {
|
|
1399
|
+
delete this._definition.interface.options[optionKey];
|
|
1656
1400
|
}
|
|
1657
1401
|
return this;
|
|
1658
1402
|
}
|
|
@@ -1661,7 +1405,7 @@ class AXPSchemaMiddlewareContext {
|
|
|
1661
1405
|
* @param widgetType The new widget type identifier
|
|
1662
1406
|
*/
|
|
1663
1407
|
withWidgetType(widgetType) {
|
|
1664
|
-
this.
|
|
1408
|
+
this._definition.interface.name = widgetType;
|
|
1665
1409
|
return this;
|
|
1666
1410
|
}
|
|
1667
1411
|
//#endregion
|
|
@@ -1671,8 +1415,8 @@ class AXPSchemaMiddlewareContext {
|
|
|
1671
1415
|
* @param features Object containing feature configurations to merge
|
|
1672
1416
|
*/
|
|
1673
1417
|
withFeatures(features) {
|
|
1674
|
-
this.
|
|
1675
|
-
...this.
|
|
1418
|
+
this._definition.features = {
|
|
1419
|
+
...this._definition.features,
|
|
1676
1420
|
...features
|
|
1677
1421
|
};
|
|
1678
1422
|
return this;
|
|
@@ -1683,10 +1427,10 @@ class AXPSchemaMiddlewareContext {
|
|
|
1683
1427
|
* @param fullText Whether full-text search is enabled
|
|
1684
1428
|
*/
|
|
1685
1429
|
searchable(enabled = true, fullText = false) {
|
|
1686
|
-
if (!this.
|
|
1687
|
-
this.
|
|
1430
|
+
if (!this._definition.features) {
|
|
1431
|
+
this._definition.features = {};
|
|
1688
1432
|
}
|
|
1689
|
-
this.
|
|
1433
|
+
this._definition.features.searchable = { enabled, fullText };
|
|
1690
1434
|
return this;
|
|
1691
1435
|
}
|
|
1692
1436
|
/**
|
|
@@ -1695,10 +1439,10 @@ class AXPSchemaMiddlewareContext {
|
|
|
1695
1439
|
* @param inline Whether inline filtering is supported
|
|
1696
1440
|
*/
|
|
1697
1441
|
filterable(enabled = true, inline = false) {
|
|
1698
|
-
if (!this.
|
|
1699
|
-
this.
|
|
1442
|
+
if (!this._definition.features) {
|
|
1443
|
+
this._definition.features = {};
|
|
1700
1444
|
}
|
|
1701
|
-
this.
|
|
1445
|
+
this._definition.features.filterable = { enabled, inline };
|
|
1702
1446
|
return this;
|
|
1703
1447
|
}
|
|
1704
1448
|
/**
|
|
@@ -1706,10 +1450,10 @@ class AXPSchemaMiddlewareContext {
|
|
|
1706
1450
|
* @param enabled Whether sorting is enabled
|
|
1707
1451
|
*/
|
|
1708
1452
|
sortable(enabled = true) {
|
|
1709
|
-
if (!this.
|
|
1710
|
-
this.
|
|
1453
|
+
if (!this._definition.features) {
|
|
1454
|
+
this._definition.features = {};
|
|
1711
1455
|
}
|
|
1712
|
-
this.
|
|
1456
|
+
this._definition.features.sortable = { enabled };
|
|
1713
1457
|
return this;
|
|
1714
1458
|
}
|
|
1715
1459
|
//#endregion
|
|
@@ -1719,8 +1463,8 @@ class AXPSchemaMiddlewareContext {
|
|
|
1719
1463
|
* @param metadata Object containing metadata to merge
|
|
1720
1464
|
*/
|
|
1721
1465
|
withMetadata(metadata) {
|
|
1722
|
-
this.
|
|
1723
|
-
...this.
|
|
1466
|
+
this._definition.metadata = {
|
|
1467
|
+
...this._definition.metadata,
|
|
1724
1468
|
...metadata
|
|
1725
1469
|
};
|
|
1726
1470
|
return this;
|
|
@@ -1730,29 +1474,19 @@ class AXPSchemaMiddlewareContext {
|
|
|
1730
1474
|
* @param key The metadata key to remove
|
|
1731
1475
|
*/
|
|
1732
1476
|
removeMetadata(key) {
|
|
1733
|
-
if (this.
|
|
1734
|
-
delete this.
|
|
1477
|
+
if (this._definition.metadata) {
|
|
1478
|
+
delete this._definition.metadata[key];
|
|
1735
1479
|
}
|
|
1736
1480
|
return this;
|
|
1737
1481
|
}
|
|
1738
1482
|
//#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
1483
|
//#region ---- UI State Management ----
|
|
1750
1484
|
/**
|
|
1751
1485
|
* Set the disabled state of the widget
|
|
1752
1486
|
* @param isDisabled Whether the widget should be disabled
|
|
1753
1487
|
*/
|
|
1754
1488
|
disabled(isDisabled = true) {
|
|
1755
|
-
this.
|
|
1489
|
+
this._definition.disabled = isDisabled;
|
|
1756
1490
|
return this;
|
|
1757
1491
|
}
|
|
1758
1492
|
/**
|
|
@@ -1760,10 +1494,10 @@ class AXPSchemaMiddlewareContext {
|
|
|
1760
1494
|
* @param visible Whether the widget should be visible
|
|
1761
1495
|
*/
|
|
1762
1496
|
withVisibility(visible) {
|
|
1763
|
-
if (!this.
|
|
1764
|
-
this.
|
|
1497
|
+
if (!this._definition.interface.options) {
|
|
1498
|
+
this._definition.interface.options = {};
|
|
1765
1499
|
}
|
|
1766
|
-
this.
|
|
1500
|
+
this._definition.interface.options['visible'] = visible;
|
|
1767
1501
|
return this;
|
|
1768
1502
|
}
|
|
1769
1503
|
/**
|
|
@@ -1771,10 +1505,10 @@ class AXPSchemaMiddlewareContext {
|
|
|
1771
1505
|
* @param isReadonly Whether the widget should be readonly
|
|
1772
1506
|
*/
|
|
1773
1507
|
readonly(isReadonly = true) {
|
|
1774
|
-
if (!this.
|
|
1775
|
-
this.
|
|
1508
|
+
if (!this._definition.interface.options) {
|
|
1509
|
+
this._definition.interface.options = {};
|
|
1776
1510
|
}
|
|
1777
|
-
this.
|
|
1511
|
+
this._definition.interface.options['readonly'] = isReadonly;
|
|
1778
1512
|
return this;
|
|
1779
1513
|
}
|
|
1780
1514
|
}
|
|
@@ -1792,9 +1526,9 @@ class AXPSchemaMiddlewareContext {
|
|
|
1792
1526
|
* - On-demand schema loading
|
|
1793
1527
|
* - Caching and performance optimization
|
|
1794
1528
|
*/
|
|
1795
|
-
class
|
|
1529
|
+
class AXPPropertyRegistry {
|
|
1796
1530
|
constructor() {
|
|
1797
|
-
this.
|
|
1531
|
+
this._registrations = new Map();
|
|
1798
1532
|
this._globalMiddleware = [];
|
|
1799
1533
|
this._modelCache = new Map();
|
|
1800
1534
|
this._loaders = null;
|
|
@@ -1805,7 +1539,7 @@ class AXPSchemaRegistry {
|
|
|
1805
1539
|
*/
|
|
1806
1540
|
register(definition, options = {}) {
|
|
1807
1541
|
if (!definition.name || definition.name.trim() === '') {
|
|
1808
|
-
throw new Error('
|
|
1542
|
+
throw new Error('Property name is required and cannot be empty');
|
|
1809
1543
|
}
|
|
1810
1544
|
const registered = {
|
|
1811
1545
|
name: definition.name,
|
|
@@ -1813,23 +1547,22 @@ class AXPSchemaRegistry {
|
|
|
1813
1547
|
options,
|
|
1814
1548
|
registeredAt: new Date()
|
|
1815
1549
|
};
|
|
1816
|
-
this.
|
|
1550
|
+
this._registrations.set(definition.name, registered);
|
|
1817
1551
|
this.invalidateCache(definition.name);
|
|
1818
|
-
console.log(`Schema '${definition.name}' registered successfully`);
|
|
1819
1552
|
}
|
|
1820
1553
|
/**
|
|
1821
1554
|
* Register multiple schemas at once for batch operations
|
|
1822
1555
|
*/
|
|
1823
|
-
registerBatch(
|
|
1824
|
-
for (const
|
|
1825
|
-
this.register(
|
|
1556
|
+
registerBatch(entries) {
|
|
1557
|
+
for (const entry of entries) {
|
|
1558
|
+
this.register(entry.definition, entry.options || {});
|
|
1826
1559
|
}
|
|
1827
1560
|
}
|
|
1828
1561
|
/**
|
|
1829
1562
|
* Remove a schema from the registry
|
|
1830
1563
|
*/
|
|
1831
1564
|
unregister(name) {
|
|
1832
|
-
const removed = this.
|
|
1565
|
+
const removed = this._registrations.delete(name);
|
|
1833
1566
|
if (removed) {
|
|
1834
1567
|
this.invalidateCache(name);
|
|
1835
1568
|
}
|
|
@@ -1839,7 +1572,7 @@ class AXPSchemaRegistry {
|
|
|
1839
1572
|
* Check if a schema is currently registered
|
|
1840
1573
|
*/
|
|
1841
1574
|
isRegistered(name) {
|
|
1842
|
-
return this.
|
|
1575
|
+
return this._registrations.has(name);
|
|
1843
1576
|
}
|
|
1844
1577
|
//#endregion
|
|
1845
1578
|
//#region ---- Resolution Methods ----
|
|
@@ -1853,7 +1586,7 @@ class AXPSchemaRegistry {
|
|
|
1853
1586
|
return this._modelCache.get(name);
|
|
1854
1587
|
}
|
|
1855
1588
|
// Try to get from registered schemas first
|
|
1856
|
-
let registered = this.
|
|
1589
|
+
let registered = this._registrations.get(name);
|
|
1857
1590
|
// If not found, attempt on-demand loading
|
|
1858
1591
|
if (!registered) {
|
|
1859
1592
|
const definition = await this.loadFromLoaders(name);
|
|
@@ -1864,27 +1597,27 @@ class AXPSchemaRegistry {
|
|
|
1864
1597
|
options: {},
|
|
1865
1598
|
registeredAt: new Date()
|
|
1866
1599
|
};
|
|
1867
|
-
this.
|
|
1600
|
+
this._registrations.set(name, registered);
|
|
1868
1601
|
}
|
|
1869
1602
|
else {
|
|
1870
|
-
throw new Error(`
|
|
1603
|
+
throw new Error(`Property '${name}' is not registered and no loader can provide it`);
|
|
1871
1604
|
}
|
|
1872
1605
|
}
|
|
1873
1606
|
// Clone and process through middleware pipeline
|
|
1874
|
-
const
|
|
1875
|
-
const context = new
|
|
1607
|
+
const definition = this.cloneDefinition(registered.definition);
|
|
1608
|
+
const context = new AXPPropertyMiddlewareContext(definition);
|
|
1876
1609
|
// Apply global middleware first
|
|
1877
1610
|
for (const middleware of this._globalMiddleware) {
|
|
1878
1611
|
await middleware(context);
|
|
1879
1612
|
}
|
|
1880
|
-
// Apply
|
|
1613
|
+
// Apply registration-specific middleware
|
|
1881
1614
|
if (registered.options.middleware) {
|
|
1882
1615
|
for (const middleware of registered.options.middleware) {
|
|
1883
1616
|
await middleware(context);
|
|
1884
1617
|
}
|
|
1885
1618
|
}
|
|
1886
1619
|
// Create final model and cache it
|
|
1887
|
-
const model = new
|
|
1620
|
+
const model = new AXPPropertyModel(context.definition);
|
|
1888
1621
|
this._modelCache.set(name, model);
|
|
1889
1622
|
return model;
|
|
1890
1623
|
}
|
|
@@ -1893,11 +1626,11 @@ class AXPSchemaRegistry {
|
|
|
1893
1626
|
* Use only when middleware is not needed for performance.
|
|
1894
1627
|
*/
|
|
1895
1628
|
resolveSync(name) {
|
|
1896
|
-
const registered = this.
|
|
1629
|
+
const registered = this._registrations.get(name);
|
|
1897
1630
|
if (!registered) {
|
|
1898
|
-
throw new Error(`
|
|
1631
|
+
throw new Error(`Property '${name}' is not registered`);
|
|
1899
1632
|
}
|
|
1900
|
-
return new
|
|
1633
|
+
return new AXPPropertyModel(this.cloneDefinition(registered.definition));
|
|
1901
1634
|
}
|
|
1902
1635
|
//#endregion
|
|
1903
1636
|
//#region ---- Middleware Management ----
|
|
@@ -1944,52 +1677,52 @@ class AXPSchemaRegistry {
|
|
|
1944
1677
|
* Get all registered schema names
|
|
1945
1678
|
*/
|
|
1946
1679
|
getRegisteredNames() {
|
|
1947
|
-
return Array.from(this.
|
|
1680
|
+
return Array.from(this._registrations.keys());
|
|
1948
1681
|
}
|
|
1949
1682
|
/**
|
|
1950
1683
|
* Get detailed registration information for a schema
|
|
1951
1684
|
*/
|
|
1952
|
-
|
|
1953
|
-
return this.
|
|
1685
|
+
getRegisteredProperty(name) {
|
|
1686
|
+
return this._registrations.get(name);
|
|
1954
1687
|
}
|
|
1955
1688
|
/**
|
|
1956
|
-
* Get all registered
|
|
1689
|
+
* Get all registered properties with their metadata
|
|
1957
1690
|
*/
|
|
1958
|
-
|
|
1959
|
-
return Array.from(this.
|
|
1691
|
+
getAllRegisteredProperties() {
|
|
1692
|
+
return Array.from(this._registrations.values());
|
|
1960
1693
|
}
|
|
1961
1694
|
/**
|
|
1962
|
-
* Find
|
|
1695
|
+
* Find registered properties by tag for categorization
|
|
1963
1696
|
*/
|
|
1964
1697
|
findByTag(tag) {
|
|
1965
|
-
return Array.from(this.
|
|
1698
|
+
return Array.from(this._registrations.values()).filter((registration) => registration.options.tags?.includes(tag));
|
|
1966
1699
|
}
|
|
1967
1700
|
/**
|
|
1968
|
-
* Find
|
|
1701
|
+
* Find registered properties by widget type for widget-specific operations
|
|
1969
1702
|
*/
|
|
1970
1703
|
findByWidget(widgetType) {
|
|
1971
|
-
return Array.from(this.
|
|
1704
|
+
return Array.from(this._registrations.values()).filter((registration) => registration.definition.interface.name === widgetType);
|
|
1972
1705
|
}
|
|
1973
1706
|
/**
|
|
1974
1707
|
* Get comprehensive registry statistics
|
|
1975
1708
|
*/
|
|
1976
1709
|
getStatistics() {
|
|
1977
|
-
const
|
|
1978
|
-
const
|
|
1979
|
-
for (const
|
|
1980
|
-
const widget =
|
|
1981
|
-
|
|
1982
|
-
if (
|
|
1983
|
-
for (const tag of
|
|
1984
|
-
|
|
1710
|
+
const propertiesByWidget = {};
|
|
1711
|
+
const propertiesByTag = {};
|
|
1712
|
+
for (const registration of this._registrations.values()) {
|
|
1713
|
+
const widget = registration.definition.interface.name;
|
|
1714
|
+
propertiesByWidget[widget] = (propertiesByWidget[widget] || 0) + 1;
|
|
1715
|
+
if (registration.options.tags) {
|
|
1716
|
+
for (const tag of registration.options.tags) {
|
|
1717
|
+
propertiesByTag[tag] = (propertiesByTag[tag] || 0) + 1;
|
|
1985
1718
|
}
|
|
1986
1719
|
}
|
|
1987
1720
|
}
|
|
1988
1721
|
return {
|
|
1989
|
-
|
|
1722
|
+
propertyCount: this._registrations.size,
|
|
1990
1723
|
globalMiddlewareCount: this._globalMiddleware.length,
|
|
1991
|
-
|
|
1992
|
-
|
|
1724
|
+
propertiesByWidget,
|
|
1725
|
+
propertiesByTag
|
|
1993
1726
|
};
|
|
1994
1727
|
}
|
|
1995
1728
|
//#endregion
|
|
@@ -2010,7 +1743,7 @@ class AXPSchemaRegistry {
|
|
|
2010
1743
|
* Clear all registered schemas, middleware, and cached models
|
|
2011
1744
|
*/
|
|
2012
1745
|
clear() {
|
|
2013
|
-
this.
|
|
1746
|
+
this._registrations.clear();
|
|
2014
1747
|
this._globalMiddleware.length = 0;
|
|
2015
1748
|
this._modelCache.clear();
|
|
2016
1749
|
this._loaders = null;
|
|
@@ -2027,7 +1760,7 @@ class AXPSchemaRegistry {
|
|
|
2027
1760
|
try {
|
|
2028
1761
|
const definition = await loader.load(name);
|
|
2029
1762
|
if (definition) {
|
|
2030
|
-
console.log(`
|
|
1763
|
+
console.log(`Property '${name}' loaded from ${loader.constructor.name}`);
|
|
2031
1764
|
return definition;
|
|
2032
1765
|
}
|
|
2033
1766
|
}
|
|
@@ -2053,7 +1786,7 @@ class AXPSchemaRegistry {
|
|
|
2053
1786
|
});
|
|
2054
1787
|
}
|
|
2055
1788
|
catch (error) {
|
|
2056
|
-
console.warn('Failed to initialize
|
|
1789
|
+
console.warn('Failed to initialize property loaders:', error);
|
|
2057
1790
|
this._loaders = [];
|
|
2058
1791
|
}
|
|
2059
1792
|
}
|
|
@@ -2065,90 +1798,89 @@ class AXPSchemaRegistry {
|
|
|
2065
1798
|
cloneDefinition(definition) {
|
|
2066
1799
|
return JSON.parse(JSON.stringify(definition));
|
|
2067
1800
|
}
|
|
2068
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
2069
|
-
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "
|
|
1801
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPPropertyRegistry, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
1802
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPPropertyRegistry, providedIn: 'root' }); }
|
|
2070
1803
|
}
|
|
2071
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
1804
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPPropertyRegistry, decorators: [{
|
|
2072
1805
|
type: Injectable,
|
|
2073
1806
|
args: [{ providedIn: 'root' }]
|
|
2074
1807
|
}], ctorParameters: () => [] });
|
|
2075
1808
|
|
|
2076
|
-
//#region ----
|
|
1809
|
+
//#region ---- Property Service ----
|
|
2077
1810
|
/**
|
|
2078
|
-
* High-level facade
|
|
1811
|
+
* High-level facade for registered property definitions ({@link AXPPropertyDefinition}).
|
|
2079
1812
|
*
|
|
2080
|
-
*
|
|
2081
|
-
* business logic and convenience methods for common operations.
|
|
1813
|
+
* Wraps {@link AXPPropertyRegistry} with convenience methods for resolution and discovery.
|
|
2082
1814
|
*/
|
|
2083
|
-
class
|
|
1815
|
+
class AXPPropertyService {
|
|
2084
1816
|
constructor() {
|
|
2085
|
-
this.registry = inject(
|
|
1817
|
+
this.registry = inject(AXPPropertyRegistry);
|
|
2086
1818
|
}
|
|
2087
|
-
//#region ----
|
|
1819
|
+
//#region ---- Registration ----
|
|
2088
1820
|
/**
|
|
2089
|
-
* Register a
|
|
1821
|
+
* Register a property definition with optional configuration
|
|
2090
1822
|
*/
|
|
2091
1823
|
register(definition, options) {
|
|
2092
1824
|
this.registry.register(definition, options);
|
|
2093
1825
|
}
|
|
2094
1826
|
/**
|
|
2095
|
-
* Register multiple
|
|
1827
|
+
* Register multiple property definitions at once
|
|
2096
1828
|
*/
|
|
2097
|
-
registerBatch(
|
|
2098
|
-
this.registry.registerBatch(
|
|
1829
|
+
registerBatch(entries) {
|
|
1830
|
+
this.registry.registerBatch(entries);
|
|
2099
1831
|
}
|
|
2100
1832
|
/**
|
|
2101
|
-
* Remove a
|
|
1833
|
+
* Remove a property definition from the registry
|
|
2102
1834
|
*/
|
|
2103
1835
|
unregister(name) {
|
|
2104
1836
|
return this.registry.unregister(name);
|
|
2105
1837
|
}
|
|
2106
1838
|
/**
|
|
2107
|
-
* Check if a
|
|
1839
|
+
* Check if a property definition is registered by name
|
|
2108
1840
|
*/
|
|
2109
1841
|
isRegistered(name) {
|
|
2110
1842
|
return this.registry.isRegistered(name);
|
|
2111
1843
|
}
|
|
2112
1844
|
/**
|
|
2113
|
-
* Get all registered
|
|
1845
|
+
* Get all registered property names
|
|
2114
1846
|
*/
|
|
2115
1847
|
getRegisteredNames() {
|
|
2116
1848
|
return this.registry.getRegisteredNames();
|
|
2117
1849
|
}
|
|
2118
1850
|
/**
|
|
2119
|
-
* Clear all
|
|
1851
|
+
* Clear all registrations and reset the registry
|
|
2120
1852
|
*/
|
|
2121
1853
|
clear() {
|
|
2122
1854
|
this.registry.clear();
|
|
2123
1855
|
}
|
|
2124
1856
|
//#endregion
|
|
2125
|
-
//#region ----
|
|
1857
|
+
//#region ---- Resolution ----
|
|
2126
1858
|
/**
|
|
2127
|
-
* Resolve a
|
|
1859
|
+
* Resolve a registered property by name with full middleware processing
|
|
2128
1860
|
*/
|
|
2129
1861
|
async resolve(name) {
|
|
2130
1862
|
return this.registry.resolve(name);
|
|
2131
1863
|
}
|
|
2132
1864
|
/**
|
|
2133
|
-
* Resolve
|
|
1865
|
+
* Resolve synchronously without middleware (for performance)
|
|
2134
1866
|
*/
|
|
2135
1867
|
resolveSync(name) {
|
|
2136
1868
|
return this.registry.resolveSync(name);
|
|
2137
1869
|
}
|
|
2138
1870
|
/**
|
|
2139
|
-
* Resolve multiple
|
|
1871
|
+
* Resolve multiple registered properties for form building and batch operations
|
|
2140
1872
|
*/
|
|
2141
1873
|
async resolveMultiple(fieldConfigs) {
|
|
2142
1874
|
const resolvedFields = await Promise.all(fieldConfigs.map(async (config) => ({
|
|
2143
1875
|
name: config.name,
|
|
2144
|
-
|
|
1876
|
+
property: await this.resolve(config.propertyName),
|
|
2145
1877
|
})));
|
|
2146
1878
|
return resolvedFields;
|
|
2147
1879
|
}
|
|
2148
1880
|
//#endregion
|
|
2149
1881
|
//#region ---- Middleware Management ----
|
|
2150
1882
|
/**
|
|
2151
|
-
* Add global middleware that applies to all
|
|
1883
|
+
* Add global middleware that applies to all property resolutions
|
|
2152
1884
|
*/
|
|
2153
1885
|
addGlobalMiddleware(middleware) {
|
|
2154
1886
|
this.registry.addGlobalMiddleware(middleware);
|
|
@@ -2168,25 +1900,25 @@ class AXPSchemaService {
|
|
|
2168
1900
|
//#endregion
|
|
2169
1901
|
//#region ---- Query and Discovery ----
|
|
2170
1902
|
/**
|
|
2171
|
-
* Get detailed information about a registered
|
|
1903
|
+
* Get detailed information about a registered property definition
|
|
2172
1904
|
*/
|
|
2173
|
-
|
|
2174
|
-
return this.registry.
|
|
1905
|
+
getRegisteredProperty(name) {
|
|
1906
|
+
return this.registry.getRegisteredProperty(name);
|
|
2175
1907
|
}
|
|
2176
1908
|
/**
|
|
2177
|
-
* Get all registered
|
|
1909
|
+
* Get all registered property definitions with their metadata
|
|
2178
1910
|
*/
|
|
2179
|
-
|
|
2180
|
-
return this.registry.
|
|
1911
|
+
getAllRegisteredProperties() {
|
|
1912
|
+
return this.registry.getAllRegisteredProperties();
|
|
2181
1913
|
}
|
|
2182
1914
|
/**
|
|
2183
|
-
* Find
|
|
1915
|
+
* Find registered properties by tag for categorization and grouping
|
|
2184
1916
|
*/
|
|
2185
1917
|
findByTag(tag) {
|
|
2186
1918
|
return this.registry.findByTag(tag);
|
|
2187
1919
|
}
|
|
2188
1920
|
/**
|
|
2189
|
-
* Find
|
|
1921
|
+
* Find registered properties by widget type for widget-specific operations
|
|
2190
1922
|
*/
|
|
2191
1923
|
findByWidget(widgetType) {
|
|
2192
1924
|
return this.registry.findByWidget(widgetType);
|
|
@@ -2197,11 +1929,11 @@ class AXPSchemaService {
|
|
|
2197
1929
|
getStatistics() {
|
|
2198
1930
|
const stats = this.registry.getStatistics();
|
|
2199
1931
|
// Enhance with top-used analytics
|
|
2200
|
-
const mostUsedWidgets = Object.entries(stats.
|
|
1932
|
+
const mostUsedWidgets = Object.entries(stats.propertiesByWidget)
|
|
2201
1933
|
.sort(([, a], [, b]) => b - a)
|
|
2202
1934
|
.slice(0, 5)
|
|
2203
1935
|
.map(([widget]) => widget);
|
|
2204
|
-
const mostUsedTags = Object.entries(stats.
|
|
1936
|
+
const mostUsedTags = Object.entries(stats.propertiesByTag)
|
|
2205
1937
|
.sort(([, a], [, b]) => b - a)
|
|
2206
1938
|
.slice(0, 5)
|
|
2207
1939
|
.map(([tag]) => tag);
|
|
@@ -2214,24 +1946,24 @@ class AXPSchemaService {
|
|
|
2214
1946
|
//#endregion
|
|
2215
1947
|
//#region ---- Validation and Analysis ----
|
|
2216
1948
|
/**
|
|
2217
|
-
* Validate that all referenced
|
|
1949
|
+
* Validate that all referenced property names exist in the registry
|
|
2218
1950
|
*/
|
|
2219
|
-
|
|
2220
|
-
const
|
|
2221
|
-
for (const
|
|
2222
|
-
if (!this.isRegistered(
|
|
2223
|
-
|
|
1951
|
+
validatePropertyReferences(propertyNames) {
|
|
1952
|
+
const missingPropertyNames = [];
|
|
1953
|
+
for (const propertyName of propertyNames) {
|
|
1954
|
+
if (!this.isRegistered(propertyName)) {
|
|
1955
|
+
missingPropertyNames.push(propertyName);
|
|
2224
1956
|
}
|
|
2225
1957
|
}
|
|
2226
1958
|
return {
|
|
2227
|
-
valid:
|
|
2228
|
-
|
|
1959
|
+
valid: missingPropertyNames.length === 0,
|
|
1960
|
+
missingPropertyNames,
|
|
2229
1961
|
};
|
|
2230
1962
|
}
|
|
2231
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
2232
|
-
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "
|
|
1963
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPPropertyService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
1964
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPPropertyService, providedIn: 'root' }); }
|
|
2233
1965
|
}
|
|
2234
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
1966
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPPropertyService, decorators: [{
|
|
2235
1967
|
type: Injectable,
|
|
2236
1968
|
args: [{ providedIn: 'root' }]
|
|
2237
1969
|
}] });
|
|
@@ -2256,24 +1988,24 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.12", ngImpo
|
|
|
2256
1988
|
* @example
|
|
2257
1989
|
* ```typescript
|
|
2258
1990
|
* // Simple loader registration
|
|
2259
|
-
*
|
|
1991
|
+
* providePropertyLoaders([
|
|
2260
1992
|
* HttpSchemaLoader,
|
|
2261
1993
|
* FileSystemSchemaLoader
|
|
2262
1994
|
* ])
|
|
2263
1995
|
*
|
|
2264
1996
|
* // With priority configuration
|
|
2265
|
-
*
|
|
1997
|
+
* providePropertyLoaders([
|
|
2266
1998
|
* { loader: HttpSchemaLoader, priority: 10 },
|
|
2267
1999
|
* { loader: FileSystemSchemaLoader, priority: 5 }
|
|
2268
2000
|
* ])
|
|
2269
2001
|
* ```
|
|
2270
2002
|
*/
|
|
2271
|
-
function
|
|
2003
|
+
function providePropertyLoaders(loaders) {
|
|
2272
2004
|
return makeEnvironmentProviders([
|
|
2273
2005
|
{
|
|
2274
|
-
provide:
|
|
2006
|
+
provide: AXP_PROPERTY_LOADER_SETUP,
|
|
2275
2007
|
useFactory: async () => {
|
|
2276
|
-
const registry = inject(
|
|
2008
|
+
const registry = inject(AXPPropertyRegistry);
|
|
2277
2009
|
// Register each loader with the registry
|
|
2278
2010
|
for (const loader of loaders) {
|
|
2279
2011
|
const loaderClass = typeof loader === 'function' ? loader : loader.loader;
|
|
@@ -2300,7 +2032,7 @@ function provideSchemaLoaders(loaders) {
|
|
|
2300
2032
|
*
|
|
2301
2033
|
* @example
|
|
2302
2034
|
* ```typescript
|
|
2303
|
-
*
|
|
2035
|
+
* providePropertySetups([
|
|
2304
2036
|
* {
|
|
2305
2037
|
* definition: emailSchema,
|
|
2306
2038
|
* options: {
|
|
@@ -2315,15 +2047,14 @@ function provideSchemaLoaders(loaders) {
|
|
|
2315
2047
|
* ])
|
|
2316
2048
|
* ```
|
|
2317
2049
|
*/
|
|
2318
|
-
function
|
|
2050
|
+
function providePropertySetups(entries) {
|
|
2319
2051
|
return makeEnvironmentProviders([
|
|
2320
2052
|
{
|
|
2321
|
-
provide:
|
|
2053
|
+
provide: AXP_PROPERTY_SETUP,
|
|
2322
2054
|
useFactory: () => {
|
|
2323
|
-
const registry = inject(
|
|
2324
|
-
|
|
2325
|
-
|
|
2326
|
-
registry.register(schema.definition, schema.options);
|
|
2055
|
+
const registry = inject(AXPPropertyRegistry);
|
|
2056
|
+
for (const entry of entries) {
|
|
2057
|
+
registry.register(entry.definition, entry.options);
|
|
2327
2058
|
}
|
|
2328
2059
|
return true;
|
|
2329
2060
|
},
|
|
@@ -2343,14 +2074,14 @@ function provideSchemaSetups(schemas) {
|
|
|
2343
2074
|
*
|
|
2344
2075
|
* @example
|
|
2345
2076
|
* ```typescript
|
|
2346
|
-
*
|
|
2077
|
+
* provideProperty(emailSchema, {
|
|
2347
2078
|
* tags: ['user', 'contact'],
|
|
2348
2079
|
* description: 'User email field'
|
|
2349
2080
|
* })
|
|
2350
2081
|
* ```
|
|
2351
2082
|
*/
|
|
2352
|
-
function
|
|
2353
|
-
return
|
|
2083
|
+
function provideProperty(definition, options) {
|
|
2084
|
+
return providePropertySetups([{ definition, options }]);
|
|
2354
2085
|
}
|
|
2355
2086
|
/**
|
|
2356
2087
|
* Provide schema setups from a factory function for dynamic registration.
|
|
@@ -2363,7 +2094,7 @@ function provideSchema(definition, options) {
|
|
|
2363
2094
|
*
|
|
2364
2095
|
* @example
|
|
2365
2096
|
* ```typescript
|
|
2366
|
-
*
|
|
2097
|
+
* providePropertiesFromFactory(async () => {
|
|
2367
2098
|
* const config = await loadConfiguration();
|
|
2368
2099
|
* return config.schemas.map(schema => ({
|
|
2369
2100
|
* definition: schema,
|
|
@@ -2372,16 +2103,15 @@ function provideSchema(definition, options) {
|
|
|
2372
2103
|
* })
|
|
2373
2104
|
* ```
|
|
2374
2105
|
*/
|
|
2375
|
-
function
|
|
2106
|
+
function providePropertiesFromFactory(factory) {
|
|
2376
2107
|
return makeEnvironmentProviders([
|
|
2377
2108
|
{
|
|
2378
|
-
provide:
|
|
2109
|
+
provide: AXP_PROPERTY_SETUP,
|
|
2379
2110
|
useFactory: async () => {
|
|
2380
|
-
const registry = inject(
|
|
2381
|
-
const
|
|
2382
|
-
|
|
2383
|
-
|
|
2384
|
-
registry.register(schema.definition, schema.options);
|
|
2111
|
+
const registry = inject(AXPPropertyRegistry);
|
|
2112
|
+
const entries = await factory();
|
|
2113
|
+
for (const entry of entries) {
|
|
2114
|
+
registry.register(entry.definition, entry.options);
|
|
2385
2115
|
}
|
|
2386
2116
|
return true;
|
|
2387
2117
|
},
|
|
@@ -2405,16 +2135,16 @@ function provideSchemasFromFactory(schemaFactory) {
|
|
|
2405
2135
|
* @example
|
|
2406
2136
|
* ```typescript
|
|
2407
2137
|
* // Global middleware
|
|
2408
|
-
*
|
|
2138
|
+
* providePropertyMiddleware([
|
|
2409
2139
|
* (context) => {
|
|
2410
|
-
* if (context.
|
|
2140
|
+
* if (context.definition.dataType === 'string') {
|
|
2411
2141
|
* context.searchable(true);
|
|
2412
2142
|
* }
|
|
2413
2143
|
* }
|
|
2414
2144
|
* ])
|
|
2415
2145
|
*
|
|
2416
2146
|
* // Targeted middleware
|
|
2417
|
-
*
|
|
2147
|
+
* providePropertyMiddleware([
|
|
2418
2148
|
* {
|
|
2419
2149
|
* target: /^user_/,
|
|
2420
2150
|
* middleware: (context) => context.withMetadata({ category: 'user' })
|
|
@@ -2422,7 +2152,7 @@ function provideSchemasFromFactory(schemaFactory) {
|
|
|
2422
2152
|
* ])
|
|
2423
2153
|
* ```
|
|
2424
2154
|
*/
|
|
2425
|
-
function
|
|
2155
|
+
function providePropertyMiddleware(middleware) {
|
|
2426
2156
|
const global = [];
|
|
2427
2157
|
const targeted = [];
|
|
2428
2158
|
// Separate global and targeted middleware for different processing
|
|
@@ -2437,9 +2167,9 @@ function provideSchemaMiddleware(middleware) {
|
|
|
2437
2167
|
return makeEnvironmentProviders([
|
|
2438
2168
|
// Setup global middleware that applies to all schemas
|
|
2439
2169
|
...(global.length > 0 ? [{
|
|
2440
|
-
provide:
|
|
2170
|
+
provide: AXP_PROPERTY_MIDDLEWARE_SETUP,
|
|
2441
2171
|
useFactory: () => {
|
|
2442
|
-
const registry = inject(
|
|
2172
|
+
const registry = inject(AXPPropertyRegistry);
|
|
2443
2173
|
for (const mw of global) {
|
|
2444
2174
|
registry.addGlobalMiddleware(mw);
|
|
2445
2175
|
}
|
|
@@ -2449,7 +2179,7 @@ function provideSchemaMiddleware(middleware) {
|
|
|
2449
2179
|
}] : []),
|
|
2450
2180
|
// Register targeted middleware entries for future extension support
|
|
2451
2181
|
...targeted.map(entry => ({
|
|
2452
|
-
provide:
|
|
2182
|
+
provide: AXP_PROPERTY_EXTENSION,
|
|
2453
2183
|
useValue: entry,
|
|
2454
2184
|
multi: true
|
|
2455
2185
|
}))
|
|
@@ -2457,8 +2187,7 @@ function provideSchemaMiddleware(middleware) {
|
|
|
2457
2187
|
}
|
|
2458
2188
|
//#endregion
|
|
2459
2189
|
|
|
2460
|
-
//#region ----
|
|
2461
|
-
// Core registry and service classes
|
|
2190
|
+
//#region ---- Property registry core ----
|
|
2462
2191
|
//#endregion
|
|
2463
2192
|
|
|
2464
2193
|
//#region ---- Domain Middleware Context ----
|
|
@@ -2587,7 +2316,7 @@ class AXPDomainRegistry {
|
|
|
2587
2316
|
// Registered loaders for on-demand loading
|
|
2588
2317
|
this._loaders = [];
|
|
2589
2318
|
// Injected dependencies
|
|
2590
|
-
this.
|
|
2319
|
+
this.propertyService = inject(AXPPropertyService);
|
|
2591
2320
|
}
|
|
2592
2321
|
//#region ---- Main Resolution Method ----
|
|
2593
2322
|
/**
|
|
@@ -2772,7 +2501,6 @@ class AXPDomainRegistry {
|
|
|
2772
2501
|
name: pathInfo.aggregate,
|
|
2773
2502
|
title: pathInfo.aggregate || '',
|
|
2774
2503
|
entities: [definition],
|
|
2775
|
-
relations: [],
|
|
2776
2504
|
validations: [],
|
|
2777
2505
|
actions: []
|
|
2778
2506
|
};
|
|
@@ -2783,7 +2511,7 @@ class AXPDomainRegistry {
|
|
|
2783
2511
|
};
|
|
2784
2512
|
const entityModule = new AXPModuleModel(entityModuleDefinition);
|
|
2785
2513
|
const entityAggregate = new AXPAggregateModel(entityAggregateDefinition, entityModule);
|
|
2786
|
-
return new AXPEntityModel(definition, entityAggregate, this.
|
|
2514
|
+
return new AXPEntityModel(definition, entityAggregate, this.propertyService);
|
|
2787
2515
|
default:
|
|
2788
2516
|
throw new Error(`Unknown domain type: ${pathInfo.type}`);
|
|
2789
2517
|
}
|
|
@@ -2813,10 +2541,10 @@ class AXPDomainRegistry {
|
|
|
2813
2541
|
paths: Array.from(this._definitionCache.keys())
|
|
2814
2542
|
};
|
|
2815
2543
|
}
|
|
2816
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
2817
|
-
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "
|
|
2544
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPDomainRegistry, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
2545
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPDomainRegistry, providedIn: 'root' }); }
|
|
2818
2546
|
}
|
|
2819
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
2547
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPDomainRegistry, decorators: [{
|
|
2820
2548
|
type: Injectable,
|
|
2821
2549
|
args: [{ providedIn: 'root' }]
|
|
2822
2550
|
}] });
|
|
@@ -3118,10 +2846,10 @@ class AXPDomainService {
|
|
|
3118
2846
|
return module;
|
|
3119
2847
|
}
|
|
3120
2848
|
}
|
|
3121
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
3122
|
-
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "
|
|
2849
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPDomainService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
2850
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPDomainService, providedIn: 'root' }); }
|
|
3123
2851
|
}
|
|
3124
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
2852
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPDomainService, decorators: [{
|
|
3125
2853
|
type: Injectable,
|
|
3126
2854
|
args: [{ providedIn: 'root' }]
|
|
3127
2855
|
}] });
|
|
@@ -3502,5 +3230,5 @@ function provideDomainMiddleware(config) {
|
|
|
3502
3230
|
* Generated bundle index. Do not edit.
|
|
3503
3231
|
*/
|
|
3504
3232
|
|
|
3505
|
-
export { AXPAggregateModel, AXPDomainMiddlewareContext, AXPDomainModule, AXPDomainRegistry, AXPDomainService, AXPEntityCommandScope, AXPEntityFieldModel, AXPEntityModel, AXPEntityType, AXPModuleHelper, AXPModuleModel,
|
|
3233
|
+
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
3234
|
//# sourceMappingURL=acorex-platform-domain.mjs.map
|