@acorex/platform 21.0.0-next.85 → 21.0.0-next.88

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (74) hide show
  1. package/fesm2022/acorex-platform-auth.mjs +1 -1
  2. package/fesm2022/acorex-platform-auth.mjs.map +1 -1
  3. package/fesm2022/{acorex-platform-common-common-settings.provider-Ytey9uhY.mjs → acorex-platform-common-common-settings.provider-VfmZct9H.mjs} +43 -3
  4. package/fesm2022/acorex-platform-common-common-settings.provider-VfmZct9H.mjs.map +1 -0
  5. package/fesm2022/acorex-platform-common.mjs +1709 -870
  6. package/fesm2022/acorex-platform-common.mjs.map +1 -1
  7. package/fesm2022/acorex-platform-contracts.mjs +1160 -9
  8. package/fesm2022/acorex-platform-contracts.mjs.map +1 -1
  9. package/fesm2022/acorex-platform-core.mjs +210 -131
  10. package/fesm2022/acorex-platform-core.mjs.map +1 -1
  11. package/fesm2022/acorex-platform-domain-contracts.mjs +58 -0
  12. package/fesm2022/acorex-platform-domain-contracts.mjs.map +1 -0
  13. package/fesm2022/acorex-platform-domain.mjs +2 -50
  14. package/fesm2022/acorex-platform-domain.mjs.map +1 -1
  15. package/fesm2022/acorex-platform-layout-builder.mjs.map +1 -1
  16. package/fesm2022/acorex-platform-layout-components.mjs +59 -23
  17. package/fesm2022/acorex-platform-layout-components.mjs.map +1 -1
  18. package/fesm2022/acorex-platform-layout-designer.mjs +3 -2
  19. package/fesm2022/acorex-platform-layout-designer.mjs.map +1 -1
  20. package/fesm2022/acorex-platform-layout-entity-attachments-page.component-CwG6n_Yb.mjs.map +1 -1
  21. package/fesm2022/acorex-platform-layout-entity-contracts.mjs +1114 -0
  22. package/fesm2022/acorex-platform-layout-entity-contracts.mjs.map +1 -0
  23. package/fesm2022/acorex-platform-layout-entity-file-list-popup.component--IeMZLIr.mjs.map +1 -1
  24. package/fesm2022/acorex-platform-layout-entity.mjs +661 -742
  25. package/fesm2022/acorex-platform-layout-entity.mjs.map +1 -1
  26. package/fesm2022/acorex-platform-layout-views.mjs +333 -119
  27. package/fesm2022/acorex-platform-layout-views.mjs.map +1 -1
  28. package/fesm2022/acorex-platform-layout-widget-core.mjs +11 -105
  29. package/fesm2022/acorex-platform-layout-widget-core.mjs.map +1 -1
  30. package/fesm2022/acorex-platform-layout-widgets-repeater-widget-column.component-CFyfix31.mjs +513 -0
  31. package/fesm2022/acorex-platform-layout-widgets-repeater-widget-column.component-CFyfix31.mjs.map +1 -0
  32. package/fesm2022/{acorex-platform-layout-widgets-tabular-data-edit-popup.component-DjpZU6gz.mjs → acorex-platform-layout-widgets-tabular-data-edit-popup.component-D4MOHEpI.mjs} +4 -4
  33. package/fesm2022/acorex-platform-layout-widgets-tabular-data-edit-popup.component-D4MOHEpI.mjs.map +1 -0
  34. package/fesm2022/acorex-platform-layout-widgets.mjs +868 -57
  35. package/fesm2022/acorex-platform-layout-widgets.mjs.map +1 -1
  36. package/fesm2022/acorex-platform-runtime.mjs.map +1 -1
  37. package/fesm2022/{acorex-platform-themes-default-entity-master-single-view.component-Br9p5aXT.mjs → acorex-platform-themes-default-entity-master-single-view.component-DrUwqKKA.mjs} +2 -3
  38. package/fesm2022/acorex-platform-themes-default-entity-master-single-view.component-DrUwqKKA.mjs.map +1 -0
  39. package/fesm2022/acorex-platform-themes-default.mjs +740 -96
  40. package/fesm2022/acorex-platform-themes-default.mjs.map +1 -1
  41. package/fesm2022/{acorex-platform-themes-shared-settings.provider-BjuzSe0T.mjs → acorex-platform-themes-shared-settings.provider-BUwPqwUS.mjs} +3 -3
  42. package/fesm2022/acorex-platform-themes-shared-settings.provider-BUwPqwUS.mjs.map +1 -0
  43. package/fesm2022/acorex-platform-themes-shared.mjs +4 -3
  44. package/fesm2022/acorex-platform-themes-shared.mjs.map +1 -1
  45. package/fesm2022/acorex-platform-workflow.mjs +6 -8
  46. package/fesm2022/acorex-platform-workflow.mjs.map +1 -1
  47. package/package.json +9 -5
  48. package/types/acorex-platform-auth.d.ts +2 -1
  49. package/types/acorex-platform-common.d.ts +419 -1083
  50. package/types/acorex-platform-contracts.d.ts +1791 -260
  51. package/types/acorex-platform-core.d.ts +2153 -2806
  52. package/types/acorex-platform-domain-contracts.d.ts +416 -0
  53. package/types/acorex-platform-domain.d.ts +4 -415
  54. package/types/acorex-platform-layout-builder.d.ts +2 -1
  55. package/types/acorex-platform-layout-components.d.ts +15 -4
  56. package/types/acorex-platform-layout-designer.d.ts +2 -1
  57. package/types/acorex-platform-layout-entity-contracts.d.ts +864 -0
  58. package/types/acorex-platform-layout-entity.d.ts +88 -269
  59. package/types/acorex-platform-layout-views.d.ts +48 -14
  60. package/types/acorex-platform-layout-widget-core.d.ts +9 -5
  61. package/types/acorex-platform-layout-widgets.d.ts +89 -13
  62. package/types/acorex-platform-runtime.d.ts +1 -1
  63. package/types/acorex-platform-themes-default.d.ts +173 -70
  64. package/types/acorex-platform-workflow.d.ts +5 -18
  65. package/fesm2022/acorex-platform-common-common-settings.provider-Ytey9uhY.mjs.map +0 -1
  66. package/fesm2022/acorex-platform-layout-widgets-repeater-widget-column.component-J0zcGKBX.mjs +0 -116
  67. package/fesm2022/acorex-platform-layout-widgets-repeater-widget-column.component-J0zcGKBX.mjs.map +0 -1
  68. package/fesm2022/acorex-platform-layout-widgets-tabular-data-edit-popup.component-DjpZU6gz.mjs.map +0 -1
  69. package/fesm2022/acorex-platform-native.mjs +0 -155
  70. package/fesm2022/acorex-platform-native.mjs.map +0 -1
  71. package/fesm2022/acorex-platform-themes-default-entity-master-single-view.component-Br9p5aXT.mjs.map +0 -1
  72. package/fesm2022/acorex-platform-themes-shared-settings.provider-BjuzSe0T.mjs.map +0 -1
  73. package/native/README.md +0 -4
  74. package/types/acorex-platform-native.d.ts +0 -28
@@ -0,0 +1,1114 @@
1
+ import { AXPSystemActionType } from '@acorex/platform/contracts';
2
+ import { omit } from 'lodash-es';
3
+
4
+ //#region ---- Entity actions ----
5
+ var AXPEntityCommandScope;
6
+ (function (AXPEntityCommandScope) {
7
+ AXPEntityCommandScope["TypeLevel"] = "typeLevel";
8
+ AXPEntityCommandScope["Selected"] = "selected";
9
+ AXPEntityCommandScope["Individual"] = "individual";
10
+ AXPEntityCommandScope["Section"] = "section";
11
+ })(AXPEntityCommandScope || (AXPEntityCommandScope = {}));
12
+ var AXPEntityQueryType;
13
+ (function (AXPEntityQueryType) {
14
+ AXPEntityQueryType["Single"] = "single";
15
+ AXPEntityQueryType["List"] = "list";
16
+ })(AXPEntityQueryType || (AXPEntityQueryType = {}));
17
+ //#endregion
18
+
19
+ //#region ---- Entity properties ----
20
+ //#endregion
21
+
22
+ //#region ---- Entity definition ----
23
+ var AXPRelationshipKind;
24
+ (function (AXPRelationshipKind) {
25
+ AXPRelationshipKind[AXPRelationshipKind["Association"] = 0] = "Association";
26
+ AXPRelationshipKind[AXPRelationshipKind["Composition"] = 1] = "Composition";
27
+ AXPRelationshipKind[AXPRelationshipKind["Aggregation"] = 2] = "Aggregation";
28
+ })(AXPRelationshipKind || (AXPRelationshipKind = {}));
29
+ var AXPRelationshipCardinality;
30
+ (function (AXPRelationshipCardinality) {
31
+ AXPRelationshipCardinality[AXPRelationshipCardinality["OneToOne"] = 0] = "OneToOne";
32
+ AXPRelationshipCardinality[AXPRelationshipCardinality["OneToMany"] = 1] = "OneToMany";
33
+ AXPRelationshipCardinality[AXPRelationshipCardinality["ManyToMany"] = 2] = "ManyToMany";
34
+ })(AXPRelationshipCardinality || (AXPRelationshipCardinality = {}));
35
+ function kebabCase(value) {
36
+ return value
37
+ .replace(/([a-z0-9])([A-Z])/g, '$1-$2')
38
+ .replace(/([A-Z])([A-Z][a-z])/g, '$1-$2')
39
+ .replace(/[\s_]+/g, '-')
40
+ .replace(/-+/g, '-')
41
+ .toLowerCase();
42
+ }
43
+ function getEntityInfo(entity) {
44
+ return {
45
+ source: `${entity.module}.${entity.name}`,
46
+ module: {
47
+ route: kebabCase(entity.module),
48
+ },
49
+ entity: {
50
+ route: kebabCase(entity.name),
51
+ },
52
+ };
53
+ }
54
+ var AXPEntityType;
55
+ (function (AXPEntityType) {
56
+ AXPEntityType[AXPEntityType["Entity"] = 0] = "Entity";
57
+ AXPEntityType[AXPEntityType["AggregateRoot"] = 1] = "AggregateRoot";
58
+ AXPEntityType[AXPEntityType["ValueObject"] = 2] = "ValueObject";
59
+ })(AXPEntityType || (AXPEntityType = {}));
60
+ //#endregion
61
+
62
+ //#region ---- Entity model & DTO types ----
63
+ //#endregion
64
+
65
+ //#endregion
66
+
67
+ //#region ---- Entity formats ----
68
+ //#endregion
69
+
70
+ //#region ---- Entity property list options ----
71
+ //#endregion
72
+
73
+ //#region ---- Entity display fields ----
74
+ //#endregion
75
+
76
+ //#region ---- Entity card fields ----
77
+ /** Whether the card field is shown as a header badge (not in the card body). */
78
+ function isCardFieldBadgeDisplay(display) {
79
+ if (display === 'badge') {
80
+ return true;
81
+ }
82
+ return typeof display === 'object' && display !== null && display.type === 'badge';
83
+ }
84
+ /** Resolves static badge color config from {@link AXPCardField.display} and legacy {@link AXPCardField.badgeColor}. */
85
+ function resolveCardFieldBadgeColor(field) {
86
+ if (typeof field.display === 'object' && field.display.type === 'badge') {
87
+ return field.display.options?.color ?? field.badgeColor;
88
+ }
89
+ if (field.display === 'badge') {
90
+ return field.badgeColor;
91
+ }
92
+ return undefined;
93
+ }
94
+ //#endregion
95
+
96
+ //#region ---- Entity query views ----
97
+ function createQueryView(name, title, fixed, params = {
98
+ columns: [],
99
+ conditions: [],
100
+ sorts: [],
101
+ }) {
102
+ params = Object.assign({ columns: [], sorts: [], conditions: [] }, params);
103
+ return {
104
+ name,
105
+ title,
106
+ fixed,
107
+ columns: params.columns ?? [],
108
+ conditions: params.conditions ?? [],
109
+ sorts: params.sorts ?? [],
110
+ };
111
+ }
112
+ function createAllQueryView(params = {
113
+ columns: [],
114
+ sorts: [],
115
+ conditions: [],
116
+ }) {
117
+ params = Object.assign({ columns: [], sorts: [], conditions: [] }, params);
118
+ return createQueryView('all', '@general:terms.interface.selection.all-items', true, {
119
+ columns: params.columns ?? [],
120
+ conditions: params.conditions ?? [],
121
+ sorts: params.sorts ?? [],
122
+ });
123
+ }
124
+ //#endregion
125
+
126
+ //#region ---- Entity master list views ----
127
+ /** Resolves master list layouts that are currently enabled. */
128
+ function resolveEnabledMasterListLayouts(layouts) {
129
+ if (!layouts) {
130
+ return ['table'];
131
+ }
132
+ const enabled = [];
133
+ if (layouts.table?.enabled !== false) {
134
+ enabled.push('table');
135
+ }
136
+ if (layouts.card && layouts.card.enabled !== false) {
137
+ enabled.push('card');
138
+ }
139
+ return enabled.length > 0 ? enabled : ['table'];
140
+ }
141
+ /** First enabled layout; used as the default when no user preference is stored. */
142
+ function resolveDefaultMasterListLayout(layouts) {
143
+ return resolveEnabledMasterListLayouts(layouts)[0];
144
+ }
145
+ //#endregion
146
+
147
+ //#region ---- Entity detail list views ----
148
+ //#endregion
149
+
150
+ //#region ---- Entity layout views ----
151
+ //#endregion
152
+
153
+ //#region ---- Related entity layout ----
154
+ //#endregion
155
+
156
+ //#region ---- Entity list filters ----
157
+ /** Encodes a dotted storage path as a flat filter context key (e.g. `person.lastName` → `person__lastName`). */
158
+ function encodeEntityListFilterContextField(queryField) {
159
+ return queryField.replace(/\./g, '__');
160
+ }
161
+ /**
162
+ * Resolves the flat context key used by query-filters / widget binding for a filter definition.
163
+ */
164
+ function resolveEntityListFilterContextField(filter) {
165
+ const explicit = filter.contextField?.trim();
166
+ if (explicit) {
167
+ return explicit;
168
+ }
169
+ const field = filter.field?.trim();
170
+ if (!field) {
171
+ return '';
172
+ }
173
+ return field.includes('.') ? encodeEntityListFilterContextField(field) : field;
174
+ }
175
+ /**
176
+ * Maps an entity list filter definition to the storage query field.
177
+ * Inline `contains` filters on lookup/select use `inlineQueryField` (display text path).
178
+ */
179
+ function resolveEntityListFilterQueryField(filter, operator) {
180
+ const operatorType = operator?.type ?? filter.operator?.type;
181
+ if (operatorType === 'contains' && filter.inlineQueryField) {
182
+ return filter.inlineQueryField;
183
+ }
184
+ return filter.field;
185
+ }
186
+ //#endregion
187
+
188
+ //#region ---- Types barrel ----
189
+ //#endregion
190
+
191
+ //#region ---- Entity action helpers (pure data, no Angular) ----
192
+ //#region Master
193
+ function entityMasterCreateAction() {
194
+ return {
195
+ title: '@general:actions.create.title',
196
+ command: {
197
+ name: 'Entity:Create',
198
+ },
199
+ priority: 'primary',
200
+ type: AXPSystemActionType.Create,
201
+ scope: AXPEntityCommandScope.TypeLevel,
202
+ };
203
+ }
204
+ function entityMasterEditAction() {
205
+ return {
206
+ title: '@general:actions.edit.title',
207
+ command: 'Entity:Update',
208
+ priority: 'secondary',
209
+ type: AXPSystemActionType.Update,
210
+ scope: AXPEntityCommandScope.Individual,
211
+ default: true,
212
+ };
213
+ }
214
+ function entityMasterBulkDeleteAction() {
215
+ return {
216
+ title: '@general:actions.delete-items.title',
217
+ command: 'delete-entity',
218
+ priority: 'primary',
219
+ type: AXPSystemActionType.Delete,
220
+ scope: AXPEntityCommandScope.Selected,
221
+ order: 100,
222
+ };
223
+ }
224
+ function entityMasterViewAction() {
225
+ return {
226
+ title: '@general:actions.view.title',
227
+ command: 'open-entity',
228
+ priority: 'secondary',
229
+ type: AXPSystemActionType.View,
230
+ scope: AXPEntityCommandScope.Individual,
231
+ default: true,
232
+ };
233
+ }
234
+ function entityMasterDeleteAction() {
235
+ return {
236
+ title: '@general:actions.delete.title',
237
+ command: 'delete-entity',
238
+ priority: 'secondary',
239
+ type: AXPSystemActionType.Delete,
240
+ scope: AXPEntityCommandScope.Individual,
241
+ order: 100,
242
+ shortcuts: ['ctrl+shift+delete'],
243
+ };
244
+ }
245
+ function entityMasterCrudActions(options) {
246
+ const opts = {
247
+ create: true,
248
+ delete: true,
249
+ view: true,
250
+ edit: false,
251
+ ...options,
252
+ };
253
+ const actions = [];
254
+ if (opts.create) {
255
+ actions.push(entityMasterCreateAction());
256
+ }
257
+ if (opts.delete) {
258
+ actions.push(entityMasterBulkDeleteAction());
259
+ actions.push(entityMasterDeleteAction());
260
+ }
261
+ if (opts.view) {
262
+ actions.push(entityMasterViewAction());
263
+ }
264
+ if (opts.edit) {
265
+ actions.push(entityMasterEditAction());
266
+ }
267
+ return actions;
268
+ }
269
+ function entityMasterRecordActions() {
270
+ return [entityMasterDeleteAction()];
271
+ }
272
+ //#endregion
273
+ //#region Details
274
+ function entityDetailsCreateActions(parentId) {
275
+ return {
276
+ title: '@general:actions.create.title',
277
+ command: {
278
+ name: 'Entity:Create',
279
+ options: {
280
+ process: {
281
+ redirect: false,
282
+ canCreateNewOne: true,
283
+ data: {
284
+ [parentId]: '{{context.eval("id")}}',
285
+ },
286
+ },
287
+ },
288
+ },
289
+ priority: 'primary',
290
+ type: AXPSystemActionType.Create,
291
+ scope: AXPEntityCommandScope.TypeLevel,
292
+ };
293
+ }
294
+ function entityDetailsCreateActionsDeferredParent() {
295
+ return {
296
+ title: '@general:actions.create.title',
297
+ command: {
298
+ name: 'Entity:Create',
299
+ options: {
300
+ process: {
301
+ redirect: false,
302
+ canCreateNewOne: true,
303
+ data: {},
304
+ },
305
+ },
306
+ },
307
+ priority: 'primary',
308
+ type: AXPSystemActionType.Create,
309
+ scope: AXPEntityCommandScope.TypeLevel,
310
+ };
311
+ }
312
+ function mergeForeignKeyFieldIntoCreateActions(foreignKeyField, actions) {
313
+ if (!foreignKeyField || !actions?.length) {
314
+ return actions ?? [];
315
+ }
316
+ return actions.map((a) => {
317
+ const cmd = a.command;
318
+ if (typeof cmd !== 'object' ||
319
+ !cmd ||
320
+ cmd.name !== 'Entity:Create' ||
321
+ a.scope !== AXPEntityCommandScope.TypeLevel) {
322
+ return a;
323
+ }
324
+ const opts = (cmd.options ?? {});
325
+ const proc = (opts['process'] ?? {});
326
+ const data = { ...(proc['data'] ?? {}) };
327
+ if (data[foreignKeyField] === undefined || data[foreignKeyField] === null || data[foreignKeyField] === '') {
328
+ data[foreignKeyField] = '{{ context.eval("id") }}';
329
+ }
330
+ return {
331
+ ...a,
332
+ command: {
333
+ ...cmd,
334
+ options: { ...opts, process: { ...proc, data } },
335
+ },
336
+ };
337
+ });
338
+ }
339
+ function collectNestedCreateHiddenProperties(relatedEntity) {
340
+ const fk = relatedEntity.persistence?.foreignKeyField;
341
+ const merged = [...(relatedEntity.excludeProperties ?? [])];
342
+ if (fk) {
343
+ merged.push(fk);
344
+ }
345
+ const unique = [...new Set(merged)];
346
+ return unique.length ? unique : undefined;
347
+ }
348
+ function entityDetailsSimpleCondition(fk) {
349
+ return {
350
+ name: fk,
351
+ operator: { type: 'equal' },
352
+ value: '{{context.eval("id")}}',
353
+ };
354
+ }
355
+ function entityDetailsReferenceCondition(type) {
356
+ return [
357
+ {
358
+ name: 'reference.id',
359
+ operator: { type: 'equal' },
360
+ value: '{{context.eval("id")}}',
361
+ },
362
+ {
363
+ name: 'reference.type',
364
+ operator: { type: 'equal' },
365
+ value: type,
366
+ },
367
+ ];
368
+ }
369
+ function entityDetailsEditAction() {
370
+ return {
371
+ title: '@general:actions.edit.title',
372
+ command: 'Entity:Update',
373
+ priority: 'secondary',
374
+ type: AXPSystemActionType.Update,
375
+ default: true,
376
+ scope: AXPEntityCommandScope.Individual,
377
+ };
378
+ }
379
+ function entityDetailsNewEditAction() {
380
+ return {
381
+ title: 'New Edit',
382
+ command: {
383
+ name: 'Entity:Update',
384
+ },
385
+ priority: 'secondary',
386
+ type: AXPSystemActionType.Update,
387
+ default: true,
388
+ scope: AXPEntityCommandScope.Individual,
389
+ };
390
+ }
391
+ function entityOverrideDetailsViewAction() {
392
+ return {
393
+ title: '@general:actions.view.title',
394
+ command: 'open-entity',
395
+ priority: 'secondary',
396
+ hidden: true,
397
+ type: AXPSystemActionType.View,
398
+ scope: AXPEntityCommandScope.Individual,
399
+ };
400
+ }
401
+ function entityDetailsCrudActions(parentId, options) {
402
+ const opts = {
403
+ create: true,
404
+ delete: true,
405
+ view: true,
406
+ edit: true,
407
+ ...options,
408
+ };
409
+ const actions = [];
410
+ if (opts.create) {
411
+ if (parentId) {
412
+ actions.push(entityDetailsCreateActions(parentId));
413
+ }
414
+ else {
415
+ actions.push(entityDetailsCreateActionsDeferredParent());
416
+ }
417
+ }
418
+ if (opts.edit) {
419
+ actions.push(entityDetailsEditAction());
420
+ }
421
+ if (opts.view) {
422
+ actions.push(entityOverrideDetailsViewAction());
423
+ }
424
+ return actions;
425
+ }
426
+ function entityDetailsReferenceCreateActions(type) {
427
+ return [
428
+ {
429
+ title: '@general:actions.create.title',
430
+ command: {
431
+ name: 'Entity:Create',
432
+ options: {
433
+ process: {
434
+ redirect: false,
435
+ canCreateNewOne: true,
436
+ data: {
437
+ reference: {
438
+ id: '{{context.eval("id")}}',
439
+ type: type,
440
+ },
441
+ },
442
+ },
443
+ },
444
+ },
445
+ priority: 'primary',
446
+ type: AXPSystemActionType.Create,
447
+ scope: AXPEntityCommandScope.TypeLevel,
448
+ },
449
+ entityDetailsEditAction(),
450
+ entityOverrideDetailsViewAction(),
451
+ ];
452
+ }
453
+ //#endregion
454
+
455
+ //#region ---- Helpers barrel ----
456
+ //#endregion
457
+
458
+ //#region ---- Template normalization ----
459
+ /**
460
+ * Normalizes display templates before expression evaluation.
461
+ * Converts simple dot paths (e.g. `{{ position.title }}`) to `context.eval("position.title")`.
462
+ */
463
+ function normalizeExpressionTemplate(template) {
464
+ let normalized = template.replace(/\{\{\s*context\.eval\(['"]([^'"]+)['"]\)\s*\}\}/g, '{{ context.eval("$1") }}');
465
+ if (!normalized.includes('{{')) {
466
+ normalized = normalized.replace(/\{/g, '{{').replace(/\}/g, '}}');
467
+ }
468
+ return normalized.replace(/\{\{\s*(?!context\.)([\w]+(?:\.[\w]+)*)\s*\}\}/g, '{{ context.eval("$1") }}');
469
+ }
470
+ /** @see normalizeExpressionTemplate */
471
+ const normalizeEntityDisplayTemplate = normalizeExpressionTemplate;
472
+ /** True when formatted text still contains unresolved template markers. */
473
+ function isUnresolvedEntityDisplayTemplate(value) {
474
+ return /\{\{/.test(value) || /context\.eval\s*\(/.test(value) || value === '[object Object]';
475
+ }
476
+ /**
477
+ * Strips literal `undefined` / `null` tokens produced when expression segments are missing.
478
+ */
479
+ function sanitizeResolvedEntityDisplayTitle(value) {
480
+ const trimmed = value.trim();
481
+ if (!trimmed) {
482
+ return '';
483
+ }
484
+ const withoutLiterals = trimmed
485
+ .replace(/\bundefined\b/gi, ' ')
486
+ .replace(/\bnull\b/gi, ' ')
487
+ .replace(/\s+/g, ' ')
488
+ .trim();
489
+ return withoutLiterals
490
+ .replace(/^[\s\-–—·|/,()+]+|[\s\-–—·|/,()+]+$/g, '')
491
+ .trim();
492
+ }
493
+ /** True when a resolved title is non-empty and safe to show in search or entity chrome. */
494
+ function isMeaningfulEntityDisplayTitle(value) {
495
+ const sanitized = sanitizeResolvedEntityDisplayTitle(value);
496
+ return sanitized.length > 0 && !isUnresolvedEntityDisplayTemplate(sanitized);
497
+ }
498
+ function isRowBoundEntityDisplayTemplate(template) {
499
+ const trimmed = template.trim();
500
+ if (!trimmed || trimmed.startsWith('@')) {
501
+ return false;
502
+ }
503
+ return trimmed.includes('{{') || trimmed.includes('{');
504
+ }
505
+ //#endregion
506
+
507
+ //#endregion
508
+ //#region ---- Expose parsing ----
509
+ /**
510
+ * Parses lookup/select `expose` entries from a property interface options object.
511
+ */
512
+ function parsePropertyExposeEntries(options) {
513
+ const expose = options?.['expose'];
514
+ if (!Array.isArray(expose)) {
515
+ return [];
516
+ }
517
+ return expose.filter((row) => row != null &&
518
+ typeof row === 'object' &&
519
+ typeof row.source === 'string' &&
520
+ typeof row.target === 'string');
521
+ }
522
+ /**
523
+ * Collects all non-empty `expose[].target` paths from a property.
524
+ */
525
+ function collectPropertyExposeTargetPaths(property) {
526
+ const opts = property.schema?.interface?.options;
527
+ if (!opts || typeof opts !== 'object') {
528
+ return [];
529
+ }
530
+ const paths = new Set();
531
+ for (const entry of parsePropertyExposeEntries(opts)) {
532
+ const target = entry.target.trim();
533
+ if (target) {
534
+ paths.add(target);
535
+ }
536
+ }
537
+ return [...paths];
538
+ }
539
+ /**
540
+ * Resolves list column `options.dataPath` for a property when explicitly set.
541
+ */
542
+ function resolveEntityColumnDataPath(entity, propertyName) {
543
+ const column = entity?.columns?.find((c) => c.name === propertyName);
544
+ const rawDataPath = column?.options?.['dataPath'];
545
+ if (typeof rawDataPath !== 'string') {
546
+ return undefined;
547
+ }
548
+ const dataPath = rawDataPath.trim();
549
+ if (!dataPath || dataPath === propertyName) {
550
+ return undefined;
551
+ }
552
+ return dataPath;
553
+ }
554
+ /**
555
+ * Resolves the lodash-get path for lookup/select display text from expose metadata.
556
+ */
557
+ function resolvePropertyExposeDisplayTarget(options) {
558
+ if (!options) {
559
+ return undefined;
560
+ }
561
+ const textField = typeof options['textField'] === 'string' ? options['textField'].trim() : '';
562
+ const valueField = typeof options['valueField'] === 'string' ? options['valueField'].trim() : 'id';
563
+ const entries = parsePropertyExposeEntries(options);
564
+ if (textField) {
565
+ const match = entries.find((entry) => entry.source === textField);
566
+ if (match?.target.trim()) {
567
+ return match.target.trim();
568
+ }
569
+ }
570
+ const displayEntry = entries.find((entry) => entry.source !== valueField && entry.source !== 'id' && entry.target.trim());
571
+ return displayEntry?.target.trim();
572
+ }
573
+ /**
574
+ * Resolves the lodash-get path used for inline `contains` filters on lookup/select properties.
575
+ * Prefers list column `dataPath`, then lookup `expose` target for `textField` (or first non-id expose).
576
+ * Returns `undefined` when the property name should be used as-is (e.g. plain text fields).
577
+ */
578
+ function resolveEntityPropertyInlineFilterField(entity, property) {
579
+ if (!entity || !property?.name) {
580
+ return undefined;
581
+ }
582
+ const dataPath = resolveEntityColumnDataPath(entity, property.name);
583
+ if (dataPath) {
584
+ return dataPath;
585
+ }
586
+ const opts = property.schema?.interface?.options;
587
+ if (!opts || typeof opts !== 'object') {
588
+ return undefined;
589
+ }
590
+ return resolvePropertyExposeDisplayTarget(opts);
591
+ }
592
+ //#endregion
593
+
594
+ //#endregion
595
+ //#region ---- Entity metadata ----
596
+ const DEFAULT_DISPLAY_FIELD_CANDIDATES = [
597
+ 'title',
598
+ 'name',
599
+ 'code',
600
+ 'fullName',
601
+ 'displayName',
602
+ 'subject',
603
+ 'description',
604
+ ];
605
+ function entityHasProperty(entity, path) {
606
+ const root = path.split('.')[0];
607
+ return entity.properties?.some((property) => property.name === root) ?? false;
608
+ }
609
+ function resolveEntityDisplayPropertyPaths(entity) {
610
+ const paths = [];
611
+ const add = (path) => {
612
+ const trimmed = path?.trim();
613
+ if (!trimmed || trimmed.includes('{') || paths.includes(trimmed)) {
614
+ return;
615
+ }
616
+ if (entityHasProperty(entity, trimmed)) {
617
+ paths.push(trimmed);
618
+ }
619
+ };
620
+ const lookupFormat = entity.formats?.lookup?.trim();
621
+ if (lookupFormat && !lookupFormat.includes('{')) {
622
+ add(lookupFormat);
623
+ }
624
+ for (const candidate of DEFAULT_DISPLAY_FIELD_CANDIDATES) {
625
+ add(candidate);
626
+ }
627
+ const identifierPlugin = entity.plugins?.find((plugin) => plugin.name === 'identifier');
628
+ const identifierField = identifierPlugin?.options?.['field'];
629
+ if (typeof identifierField === 'string') {
630
+ add(identifierField);
631
+ }
632
+ if (paths.length === 0) {
633
+ const firstStringProperty = entity.properties?.find((property) => property.schema?.dataType === 'string' && property.name !== 'id');
634
+ add(firstStringProperty?.name);
635
+ }
636
+ return paths;
637
+ }
638
+ /**
639
+ * Builds entity-scoped fallback metadata for global search (registered on each entity search definition).
640
+ */
641
+ function buildEntitySearchTitleContext(entity, primaryTemplate) {
642
+ const fallbackTemplates = [];
643
+ const normalizedPrimary = primaryTemplate?.trim()
644
+ ? normalizeEntityDisplayTemplate(primaryTemplate.trim())
645
+ : undefined;
646
+ const addTemplate = (raw) => {
647
+ const trimmed = raw?.trim();
648
+ if (!trimmed || !isRowBoundEntityDisplayTemplate(trimmed)) {
649
+ return;
650
+ }
651
+ const normalized = normalizeEntityDisplayTemplate(trimmed);
652
+ if (!normalized || normalized === normalizedPrimary || fallbackTemplates.includes(normalized)) {
653
+ return;
654
+ }
655
+ fallbackTemplates.push(normalized);
656
+ };
657
+ addTemplate(entity.interfaces?.master?.single?.title);
658
+ addTemplate(entity.formats?.lookup);
659
+ addTemplate(entity.formats?.individual);
660
+ return {
661
+ fallbackTemplates,
662
+ fallbackFields: resolveEntityDisplayPropertyPaths(entity),
663
+ };
664
+ }
665
+ /**
666
+ * Row title template chain aligned with entity layouts.
667
+ * Priority: `interfaces.master.single.title` → `formats.searchResult.title` → `formats.individual`.
668
+ */
669
+ function resolveEntityRowTitleTemplate(entity) {
670
+ if (!entity) {
671
+ return undefined;
672
+ }
673
+ const singleTitle = entity.interfaces?.master?.single?.title?.trim();
674
+ if (singleTitle && isRowBoundEntityDisplayTemplate(singleTitle)) {
675
+ return normalizeEntityDisplayTemplate(singleTitle);
676
+ }
677
+ const searchTitle = entity.formats?.searchResult?.title?.trim();
678
+ if (searchTitle && isRowBoundEntityDisplayTemplate(searchTitle)) {
679
+ return normalizeEntityDisplayTemplate(searchTitle);
680
+ }
681
+ const lookupFormat = entity.formats?.lookup?.trim();
682
+ if (lookupFormat && isRowBoundEntityDisplayTemplate(lookupFormat)) {
683
+ return normalizeEntityDisplayTemplate(lookupFormat);
684
+ }
685
+ const individual = entity.formats?.individual?.trim();
686
+ if (individual && isRowBoundEntityDisplayTemplate(individual)) {
687
+ return normalizeEntityDisplayTemplate(individual);
688
+ }
689
+ return undefined;
690
+ }
691
+ /**
692
+ * Record title template for modify popups: `interfaces.master.update.title` → `single.title`.
693
+ */
694
+ function resolveEntityModifyRecordTitleTemplate(entity) {
695
+ if (!entity) {
696
+ return undefined;
697
+ }
698
+ const updateTitle = entity.interfaces?.master?.update?.title?.trim();
699
+ if (updateTitle && isRowBoundEntityDisplayTemplate(updateTitle)) {
700
+ return normalizeEntityDisplayTemplate(updateTitle);
701
+ }
702
+ const singleTitle = entity.interfaces?.master?.single?.title?.trim();
703
+ if (singleTitle && isRowBoundEntityDisplayTemplate(singleTitle)) {
704
+ return normalizeEntityDisplayTemplate(singleTitle);
705
+ }
706
+ return undefined;
707
+ }
708
+ //#endregion
709
+
710
+ //#endregion
711
+ //#region ---- Quick search: schema-driven field paths ----
712
+ const NON_TEXT_DATATYPES = new Set([
713
+ 'number',
714
+ 'integer',
715
+ 'int',
716
+ 'long',
717
+ 'float',
718
+ 'double',
719
+ 'decimal',
720
+ 'money',
721
+ 'currency',
722
+ 'boolean',
723
+ 'bool',
724
+ 'date',
725
+ 'datetime',
726
+ 'time',
727
+ 'object',
728
+ 'array',
729
+ 'json',
730
+ 'image',
731
+ 'file',
732
+ 'binary',
733
+ ]);
734
+ /**
735
+ * Whether an entity property likely stores free text worth a `contains` quick-search clause.
736
+ */
737
+ function isTextLikeDataType(dataType) {
738
+ const dt = (dataType ?? 'string').toLowerCase().trim();
739
+ if (!dt || NON_TEXT_DATATYPES.has(dt)) {
740
+ return false;
741
+ }
742
+ return true;
743
+ }
744
+ /**
745
+ * Lodash-get paths for quick search from a single entity definition: string-like property names
746
+ * plus lookup `expose[].target` paths (e.g. `brand.title`).
747
+ */
748
+ function collectQuickSearchPathsFromSingleEntityDefinition(entity) {
749
+ if (!entity?.properties?.length) {
750
+ return [];
751
+ }
752
+ const paths = new Set();
753
+ for (const property of entity.properties) {
754
+ if (isTextLikeDataType(property.schema?.dataType)) {
755
+ paths.add(property.name);
756
+ }
757
+ for (const target of collectPropertyExposeTargetPaths(property)) {
758
+ paths.add(target);
759
+ }
760
+ }
761
+ return [...paths];
762
+ }
763
+ //#endregion
764
+ //#region ---- Column-derived nested paths ----
765
+ /**
766
+ * Adds dotted paths from master columns (`name` or `options.dataPath`), e.g. `person.fullName`, `jobDefinition.title`.
767
+ */
768
+ function collectNestedFieldPathsFromEntityColumns(entity) {
769
+ if (!entity?.columns?.length) {
770
+ return [];
771
+ }
772
+ const paths = new Set();
773
+ for (const col of entity.columns) {
774
+ const name = col.name.trim();
775
+ if (name.includes('.')) {
776
+ paths.add(name);
777
+ }
778
+ const rawDp = col.options?.['dataPath'];
779
+ if (typeof rawDp === 'string') {
780
+ const dp = rawDp.trim();
781
+ if (dp.includes('.')) {
782
+ paths.add(dp);
783
+ }
784
+ }
785
+ }
786
+ return [...paths];
787
+ }
788
+ //#endregion
789
+ //#region ---- Related merge-detail paths ----
790
+ function parseRelatedEntityFullName$1(fullName) {
791
+ const t = fullName.trim();
792
+ const idx = t.indexOf('.');
793
+ if (idx <= 0 || idx >= t.length - 1) {
794
+ return null;
795
+ }
796
+ return {
797
+ moduleName: t.slice(0, idx),
798
+ entityName: t.slice(idx + 1),
799
+ };
800
+ }
801
+ //#endregion
802
+ //#region ---- Public API ----
803
+ /**
804
+ * Collects lodash-get field paths used for mock/API quick search (`contains` / OR filters):
805
+ * host properties and lookup expose targets, dotted column paths, and merge-detail related entities
806
+ * prefixed with the related entity merge `persistence.dataPath` (e.g. `person.firstName`).
807
+ */
808
+ async function collectEntityQuickSearchFieldPaths(entity, resolveRelatedDefinition) {
809
+ if (!entity) {
810
+ return [];
811
+ }
812
+ const paths = new Set();
813
+ for (const p of collectQuickSearchPathsFromSingleEntityDefinition(entity)) {
814
+ paths.add(p);
815
+ }
816
+ for (const p of collectNestedFieldPathsFromEntityColumns(entity)) {
817
+ paths.add(p);
818
+ }
819
+ const related = entity.relatedEntities ?? [];
820
+ for (const rel of related) {
821
+ const dataPath = rel.persistence?.dataPath?.trim();
822
+ if (!dataPath || rel.layout?.type !== 'merge-detail') {
823
+ continue;
824
+ }
825
+ const parsed = rel.entity ? parseRelatedEntityFullName$1(rel.entity) : null;
826
+ if (!parsed) {
827
+ continue;
828
+ }
829
+ const relatedDef = await resolveRelatedDefinition(parsed.moduleName, parsed.entityName);
830
+ if (!relatedDef) {
831
+ continue;
832
+ }
833
+ for (const p of collectQuickSearchPathsFromSingleEntityDefinition(relatedDef)) {
834
+ paths.add(`${dataPath}.${p}`);
835
+ }
836
+ for (const p of collectNestedFieldPathsFromEntityColumns(relatedDef)) {
837
+ paths.add(`${dataPath}.${p}`);
838
+ }
839
+ }
840
+ return [...paths];
841
+ }
842
+ //#endregion
843
+
844
+ //#endregion
845
+ //#region ---- Property filter helpers ----
846
+ function isPropertyFilterEnabled(property) {
847
+ const filter = property.options?.filter;
848
+ return !!(filter?.advance?.enabled ||
849
+ filter?.inline?.enabled ||
850
+ filter?.preload?.enabled);
851
+ }
852
+ function parseRelatedEntityFullName(fullName) {
853
+ const trimmed = fullName.trim();
854
+ const idx = trimmed.indexOf('.');
855
+ if (idx <= 0 || idx >= trimmed.length - 1) {
856
+ return null;
857
+ }
858
+ return {
859
+ moduleName: trimmed.slice(0, idx),
860
+ entityName: trimmed.slice(idx + 1),
861
+ };
862
+ }
863
+ //#endregion
864
+ //#region ---- Merge-detail property discovery ----
865
+ /**
866
+ * Resolves related property names eligible for host list filters:
867
+ * host columns under `dataPath`, optional `related.properties` allowlist, minus `excludeProperties`.
868
+ */
869
+ function collectMergeDetailFilterPropertyNames(hostEntity, dataPath, relatedEntity) {
870
+ const names = new Set();
871
+ const prefix = `${dataPath}.`;
872
+ if (relatedEntity.properties?.length) {
873
+ for (const name of relatedEntity.properties) {
874
+ const trimmed = name.trim();
875
+ if (trimmed) {
876
+ names.add(trimmed);
877
+ }
878
+ }
879
+ }
880
+ for (const column of hostEntity.columns ?? []) {
881
+ const columnName = column.name.trim();
882
+ if (columnName.startsWith(prefix)) {
883
+ const tail = columnName.slice(prefix.length);
884
+ const leaf = tail.split('.')[0]?.trim();
885
+ if (leaf) {
886
+ names.add(leaf);
887
+ }
888
+ }
889
+ const rawDataPath = column.options?.['dataPath'];
890
+ if (typeof rawDataPath === 'string') {
891
+ const dp = rawDataPath.trim();
892
+ if (dp.startsWith(prefix)) {
893
+ const tail = dp.slice(prefix.length);
894
+ const leaf = tail.split('.')[0]?.trim();
895
+ if (leaf) {
896
+ names.add(leaf);
897
+ }
898
+ }
899
+ }
900
+ }
901
+ const excluded = new Set((relatedEntity.excludeProperties ?? []).map((n) => n.trim()).filter(Boolean));
902
+ for (const name of excluded) {
903
+ names.delete(name);
904
+ }
905
+ return names;
906
+ }
907
+ function resolveMergedRelatedInlineFilterField(dataPath, relatedEntityDef, property) {
908
+ const columnDataPath = resolveEntityColumnDataPath(relatedEntityDef, property.name);
909
+ if (columnDataPath) {
910
+ return `${dataPath}.${columnDataPath}`;
911
+ }
912
+ const exposeTarget = resolvePropertyExposeDisplayTarget(property.schema?.interface?.options);
913
+ if (exposeTarget) {
914
+ return `${dataPath}.${exposeTarget}`;
915
+ }
916
+ return undefined;
917
+ }
918
+ //#endregion
919
+ //#region ---- Filter definition builder ----
920
+ function buildFilterDefinitionFromProperty(hostEntity, property, options, deps) {
921
+ if (!isPropertyFilterEnabled(property)) {
922
+ return null;
923
+ }
924
+ const iface = property.schema.interface ?? {};
925
+ const interfaceType = iface.type;
926
+ const widgetConfig = interfaceType ? deps?.resolveWidget?.(interfaceType) : undefined;
927
+ const type = (property.options?.filter?.advance?.widgetType ||
928
+ widgetConfig?.defaultFilterWidgetName ||
929
+ interfaceType);
930
+ const inlineQueryField = options.inlineQueryField ??
931
+ resolveEntityPropertyInlineFilterField(hostEntity, property);
932
+ const preloadRequired = property.options?.filter?.preload?.required;
933
+ const validations = preloadRequired
934
+ ? [
935
+ {
936
+ rule: 'required',
937
+ message: 'This field is required',
938
+ options: {},
939
+ },
940
+ ]
941
+ : [];
942
+ const widgetOptions = {
943
+ ...(iface.options ?? {}),
944
+ ...(validations.length ? { validations } : {}),
945
+ };
946
+ const contextField = options.field.includes('.')
947
+ ? encodeEntityListFilterContextField(options.field)
948
+ : undefined;
949
+ return {
950
+ title: property.title,
951
+ field: options.field,
952
+ ...(contextField ? { contextField } : {}),
953
+ ...(inlineQueryField && inlineQueryField !== options.field ? { inlineQueryField } : {}),
954
+ operator: {
955
+ type: 'contains',
956
+ },
957
+ widget: {
958
+ ...omit(iface, 'triggers'),
959
+ path: contextField ?? options.field,
960
+ type,
961
+ options: widgetOptions,
962
+ },
963
+ filters: [],
964
+ isParametric: false,
965
+ icon: widgetConfig?.icon,
966
+ filterType: {
967
+ advance: property.options?.filter?.advance?.enabled ?? false,
968
+ inline: property.options?.filter?.inline?.enabled ?? false,
969
+ preload: property.options?.filter?.preload,
970
+ },
971
+ triggers: iface.triggers,
972
+ };
973
+ }
974
+ async function collectHostPropertyFilterDefinitions(entity, deps) {
975
+ const definitions = [];
976
+ for (const property of entity.properties ?? []) {
977
+ const definition = buildFilterDefinitionFromProperty(entity, property, { field: property.name }, deps);
978
+ if (definition) {
979
+ definitions.push(definition);
980
+ }
981
+ }
982
+ return definitions;
983
+ }
984
+ async function collectMergeDetailFilterDefinitions(hostEntity, resolveRelatedDefinition, deps) {
985
+ const definitions = [];
986
+ for (const related of hostEntity.relatedEntities ?? []) {
987
+ if (related.layout?.type !== 'merge-detail') {
988
+ continue;
989
+ }
990
+ if (related.filter?.enabled === false) {
991
+ continue;
992
+ }
993
+ const dataPath = related.persistence?.dataPath?.trim();
994
+ if (!dataPath) {
995
+ continue;
996
+ }
997
+ const parsed = related.entity ? parseRelatedEntityFullName(related.entity) : null;
998
+ if (!parsed) {
999
+ continue;
1000
+ }
1001
+ const relatedDef = await resolveRelatedDefinition(parsed.moduleName, parsed.entityName);
1002
+ if (!relatedDef) {
1003
+ continue;
1004
+ }
1005
+ const propertyNames = collectMergeDetailFilterPropertyNames(hostEntity, dataPath, related);
1006
+ if (propertyNames.size === 0) {
1007
+ continue;
1008
+ }
1009
+ for (const propertyName of propertyNames) {
1010
+ const property = relatedDef.properties?.find((p) => p.name === propertyName);
1011
+ if (!property) {
1012
+ continue;
1013
+ }
1014
+ const queryField = `${dataPath}.${propertyName}`;
1015
+ const inlineQueryField = resolveMergedRelatedInlineFilterField(dataPath, relatedDef, property);
1016
+ const definition = buildFilterDefinitionFromProperty(hostEntity, property, {
1017
+ field: queryField,
1018
+ inlineQueryField,
1019
+ }, deps);
1020
+ if (definition) {
1021
+ definitions.push(definition);
1022
+ }
1023
+ }
1024
+ }
1025
+ return definitions;
1026
+ }
1027
+ //#endregion
1028
+ //#region ---- Public API ----
1029
+ /**
1030
+ * Builds master-list filter definitions from host properties and merge-detail related entities.
1031
+ * Related filters use `{dataPath}.{property}` query fields (e.g. `person.firstName`).
1032
+ */
1033
+ async function collectEntityListFilterDefinitions(entity, resolveRelatedDefinition, deps) {
1034
+ if (!entity) {
1035
+ return [];
1036
+ }
1037
+ const hostDefinitions = await collectHostPropertyFilterDefinitions(entity, deps);
1038
+ const relatedDefinitions = await collectMergeDetailFilterDefinitions(entity, resolveRelatedDefinition, deps);
1039
+ return [...hostDefinitions, ...relatedDefinitions];
1040
+ }
1041
+ //#endregion
1042
+
1043
+ //#region ---- Workflow record helpers ----
1044
+ /** Entity query filter field for {@link AXPRecordWorkflowInfo.instanceId}. */
1045
+ const AXP_RECORD_WORKFLOW_INFO_INSTANCE_ID_FIELD = 'workflowInfo.instanceId';
1046
+ /** Entity query filter field for {@link AXPRecordWorkflowInfo.correlationId}. */
1047
+ const AXP_RECORD_WORKFLOW_INFO_CORRELATION_ID_FIELD = 'workflowInfo.correlationId';
1048
+ /** Entity query filter field for {@link AXPRecordWorkflowInfo.definitionId}. */
1049
+ const AXP_RECORD_WORKFLOW_INFO_DEFINITION_ID_FIELD = 'workflowInfo.definitionId';
1050
+ /** Returns a trimmed workflow instance id from a record, if present. */
1051
+ function getRecordWorkflowInstanceId(record) {
1052
+ const id = record?.workflowInfo?.instanceId?.trim();
1053
+ return id && id.length > 0 ? id : null;
1054
+ }
1055
+ /** Returns a trimmed workflow correlation id from a record, if present. */
1056
+ function getRecordWorkflowCorrelationId(record) {
1057
+ const id = record?.workflowInfo?.correlationId?.trim();
1058
+ return id && id.length > 0 ? id : null;
1059
+ }
1060
+ /** Builds canonical workflow metadata for a domain record (engine / middleware). */
1061
+ function buildAXPRecordWorkflowInfo(params) {
1062
+ const instanceId = params.instanceId?.trim();
1063
+ if (!instanceId) {
1064
+ return {};
1065
+ }
1066
+ const definitionId = params.definitionId?.trim();
1067
+ const correlationId = params.correlationId?.trim();
1068
+ return {
1069
+ instanceId,
1070
+ ...(definitionId ? { definitionId } : { definitionId: null }),
1071
+ ...(correlationId ? { correlationId } : { correlationId: null }),
1072
+ ...(params.pinnedVersion != null ? { pinnedVersion: params.pinnedVersion } : {}),
1073
+ };
1074
+ }
1075
+ //#endregion
1076
+
1077
+ //#region ---- Utils barrel ----
1078
+ //#endregion
1079
+
1080
+ //#region ---- Entity display constants ----
1081
+ /** Row path used when context carries a nested entity layout title. */
1082
+ const ENTITY_LAYOUT_SINGLE_TITLE_PATH = 'entity.layout.single.title';
1083
+ /** Widget option for a pre-evaluated or template entity row title (entity list column mappers). */
1084
+ const ENTITY_ROW_POPUP_TITLE_OPTION = 'popupTitle';
1085
+ /** Widget option alias for entity row title templates in view/edit forms. */
1086
+ const ENTITY_ROW_TITLE_TEMPLATE_OPTION = 'titleTemplate';
1087
+ //#endregion
1088
+
1089
+ //#region ---- Entity datasource keys ----
1090
+ /** Platform entity layout datasource registry names. */
1091
+ const AXPEntityDataSourceKeys = {
1092
+ Entities: 'entities',
1093
+ };
1094
+ //#endregion
1095
+
1096
+ //#region ---- Entity events ----
1097
+ const AXPEntityEventsKeys = {
1098
+ REFRESH_LAYOUT: 'entity:refresh-layout',
1099
+ REFRESH_DATA: 'entity:refresh-data',
1100
+ };
1101
+ //#endregion
1102
+
1103
+ //#region ---- Constants barrel ----
1104
+ //#endregion
1105
+
1106
+ //#region ---- Barrel ----
1107
+ //#endregion
1108
+
1109
+ /**
1110
+ * Generated bundle index. Do not edit.
1111
+ */
1112
+
1113
+ export { AXPEntityCommandScope, AXPEntityDataSourceKeys, AXPEntityEventsKeys, AXPEntityQueryType, AXPEntityType, AXPRelationshipCardinality, AXPRelationshipKind, AXP_RECORD_WORKFLOW_INFO_CORRELATION_ID_FIELD, AXP_RECORD_WORKFLOW_INFO_DEFINITION_ID_FIELD, AXP_RECORD_WORKFLOW_INFO_INSTANCE_ID_FIELD, ENTITY_LAYOUT_SINGLE_TITLE_PATH, ENTITY_ROW_POPUP_TITLE_OPTION, ENTITY_ROW_TITLE_TEMPLATE_OPTION, buildAXPRecordWorkflowInfo, buildEntitySearchTitleContext, collectEntityListFilterDefinitions, collectEntityQuickSearchFieldPaths, collectNestedCreateHiddenProperties, collectNestedFieldPathsFromEntityColumns, collectPropertyExposeTargetPaths, collectQuickSearchPathsFromSingleEntityDefinition, createAllQueryView, createQueryView, encodeEntityListFilterContextField, entityDetailsCreateActions, entityDetailsCreateActionsDeferredParent, entityDetailsCrudActions, entityDetailsEditAction, entityDetailsNewEditAction, entityDetailsReferenceCondition, entityDetailsReferenceCreateActions, entityDetailsSimpleCondition, entityMasterBulkDeleteAction, entityMasterCreateAction, entityMasterCrudActions, entityMasterDeleteAction, entityMasterEditAction, entityMasterRecordActions, entityMasterViewAction, entityOverrideDetailsViewAction, getEntityInfo, getRecordWorkflowCorrelationId, getRecordWorkflowInstanceId, isCardFieldBadgeDisplay, isMeaningfulEntityDisplayTitle, isRowBoundEntityDisplayTemplate, isUnresolvedEntityDisplayTemplate, mergeForeignKeyFieldIntoCreateActions, normalizeEntityDisplayTemplate, normalizeExpressionTemplate, parsePropertyExposeEntries, resolveCardFieldBadgeColor, resolveDefaultMasterListLayout, resolveEnabledMasterListLayouts, resolveEntityColumnDataPath, resolveEntityListFilterContextField, resolveEntityListFilterQueryField, resolveEntityModifyRecordTitleTemplate, resolveEntityPropertyInlineFilterField, resolveEntityRowTitleTemplate, resolvePropertyExposeDisplayTarget, sanitizeResolvedEntityDisplayTitle };
1114
+ //# sourceMappingURL=acorex-platform-layout-entity-contracts.mjs.map