@acorex/connectivity 21.0.0-beta.7 → 21.0.0-beta.8

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 (19) hide show
  1. package/fesm2022/acorex-connectivity-api.mjs +89 -3
  2. package/fesm2022/acorex-connectivity-api.mjs.map +1 -1
  3. package/fesm2022/{acorex-connectivity-mock-acorex-connectivity-mock-BwFZQ1Xw.mjs → acorex-connectivity-mock-acorex-connectivity-mock-DGbHYfeu.mjs} +881 -209
  4. package/fesm2022/acorex-connectivity-mock-acorex-connectivity-mock-DGbHYfeu.mjs.map +1 -0
  5. package/fesm2022/{acorex-connectivity-mock-assign-to-manager.activity-BgaXGmcT.mjs → acorex-connectivity-mock-assign-to-manager.activity-B4WcK-sl.mjs} +2 -2
  6. package/fesm2022/{acorex-connectivity-mock-assign-to-manager.activity-BgaXGmcT.mjs.map → acorex-connectivity-mock-assign-to-manager.activity-B4WcK-sl.mjs.map} +1 -1
  7. package/fesm2022/{acorex-connectivity-mock-chat-generate-image.command-IUvQRJU0.mjs → acorex-connectivity-mock-chat-generate-image.command-iFiQ5rHd.mjs} +2 -2
  8. package/fesm2022/{acorex-connectivity-mock-chat-generate-image.command-IUvQRJU0.mjs.map → acorex-connectivity-mock-chat-generate-image.command-iFiQ5rHd.mjs.map} +1 -1
  9. package/fesm2022/{acorex-connectivity-mock-chat-synthesize-speech.command-DE8YU17E.mjs → acorex-connectivity-mock-chat-synthesize-speech.command-BTv6P2ez.mjs} +2 -2
  10. package/fesm2022/{acorex-connectivity-mock-chat-synthesize-speech.command-DE8YU17E.mjs.map → acorex-connectivity-mock-chat-synthesize-speech.command-BTv6P2ez.mjs.map} +1 -1
  11. package/fesm2022/{acorex-connectivity-mock-chat-transcribe-speech.command-Cr0QRiqr.mjs → acorex-connectivity-mock-chat-transcribe-speech.command-NxlEgtW-.mjs} +2 -2
  12. package/fesm2022/{acorex-connectivity-mock-chat-transcribe-speech.command-Cr0QRiqr.mjs.map → acorex-connectivity-mock-chat-transcribe-speech.command-NxlEgtW-.mjs.map} +1 -1
  13. package/fesm2022/{acorex-connectivity-mock-user-roles-for-list-column.query-DBhWkX3w.mjs → acorex-connectivity-mock-user-roles-for-list-column.query-DyGLxPvP.mjs} +2 -2
  14. package/fesm2022/{acorex-connectivity-mock-user-roles-for-list-column.query-DBhWkX3w.mjs.map → acorex-connectivity-mock-user-roles-for-list-column.query-DyGLxPvP.mjs.map} +1 -1
  15. package/fesm2022/acorex-connectivity-mock.mjs +1 -1
  16. package/package.json +2 -2
  17. package/types/acorex-connectivity-api.d.ts +12 -1
  18. package/types/acorex-connectivity-mock.d.ts +45 -6
  19. package/fesm2022/acorex-connectivity-mock-acorex-connectivity-mock-BwFZQ1Xw.mjs.map +0 -1
@@ -2,8 +2,8 @@ import { AXSafePipe } from '@acorex/core/pipes';
2
2
  import * as i2$2 from '@acorex/platform/auth';
3
3
  import { AXPSessionService, AXP_PERMISSION_DEFINITION_PROVIDER, AXP_APPLICATION_LOADER, AXP_FEATURE_LOADER, AXP_PERMISSION_LOADER, AXP_TENANT_LOADER, AXP_PERMISSION_CHECKER, AXP_FEATURE_CHECKER, AXPLoginChallengeComponentBase, AXPLoginChallengeProvider, AXPAuthStrategy, AXPAuthModule, AXP_LOGIN_CHALLENGE_PROVIDER } from '@acorex/platform/auth';
4
4
  import * as i1 from '@acorex/platform/core';
5
- import { applyFilterArray, applySortArray, AXPDataGenerator, AXPIconLogoConfig, AXPModuleManifestRegistry, AXPActivityLogProvider, AXP_ACTIVITY_LOG_PROVIDER, AXP_DATASOURCE_DEFINITION_PROVIDER, AXPDataSourceDefinitionProviderService, AXPPlatformScope, AXP_DISTRIBUTED_EVENT_LISTENER_PROVIDER, AXPExpressionEvaluatorService, provideLazyProvider } from '@acorex/platform/core';
6
- import { AXP_ENTITY_STORAGE_BACKEND, AXPEntityStorageService, isAXPMiddlewareAbortError, AXPEntityResolver, collectEntityQuickSearchFieldPaths, AXP_ENTITY_DEFINITION_CRUD_SERVICE, AXPEntityService, AXP_ENTITY_DEFINITION_LOADER, AXPMiddlewareAbortError, AXP_DATA_SEEDER_TOKEN, AXP_ENTITY_STORAGE_MIDDLEWARE, AXPEntityDefinitionRegistryService, eventDispatchMiddleware, AXPDataSeederService } from '@acorex/platform/layout/entity';
5
+ import { AXPDataGenerator, AXPIconLogoConfig, AXPModuleManifestRegistry, AXPActivityLogProvider, AXP_ACTIVITY_LOG_PROVIDER, AXP_DATASOURCE_DEFINITION_PROVIDER, AXPDataSourceDefinitionProviderService, AXPPlatformScope, AXPExpressionEvaluatorService, AXP_DISTRIBUTED_EVENT_LISTENER_PROVIDER, provideLazyProvider } from '@acorex/platform/core';
6
+ import { runEntityQuery, filterSortEntityRows, computeEntityAggregates, AXP_ENTITY_STORAGE_BACKEND, AXPEntityStorageService, isAXPMiddlewareAbortError, AXPEntityResolver, collectEntityQuickSearchFieldPaths, AXP_ENTITY_DEFINITION_CRUD_SERVICE, AXPEntityService, AXP_ENTITY_DEFINITION_LOADER, AXPMiddlewareAbortError, AXP_DATA_SEEDER_TOKEN, AXP_ENTITY_STORAGE_MIDDLEWARE, AXPEntityDefinitionRegistryService, eventDispatchMiddleware, AXPDataSeederService } from '@acorex/platform/layout/entity';
7
7
  import * as i0 from '@angular/core';
8
8
  import { InjectionToken, inject, Injectable, NgModule, isDevMode, Injector, Inject, signal, Component } from '@angular/core';
9
9
  import { AXP_MENU_PROVIDER, AXPFileStorageService, AXPSettingsService, AXPSystemStatusType, AXPAppVersionService, AXPFileStorageStatus, AXVChangeType as AXVChangeType$1, AXP_SEARCH_PROVIDER, AXPLockService, AXPVersioningService, AXPSystemStatuses, AXPStatusDefinitionProviderService } from '@acorex/platform/common';
@@ -23,13 +23,14 @@ import { AXMAssetManagementFeatureKeys, RootConfig as RootConfig$4, AXMAssetStat
23
23
  import { AXMAssessmentManagementFeatureKeys, RootConfig as RootConfig$3, AXMAssessmentManagementPermissionKeys } from '@acorex/modules/assessment-management';
24
24
  import { AXPCommonFeatureKeys, AXPWidgetsList } from '@acorex/modules/common';
25
25
  import { AXMDataManagementFeatureKeys, AXMPermissionsKeys as AXMPermissionsKeys$2, RootConfig as RootConfig$d, AXMQueryServiceImpl, ShowMetaDataFormPopupCommand, ShowMetaDataBuilderPopupCommand, AXMQueryService } from '@acorex/modules/data-management';
26
- import { AXPHumanCapitalManagementFeatureKeys, AXMPermissionsKeys as AXMPermissionsKeys$4, RootConfig as RootConfig$j, AXM_POSITION_ASSIGNMENT_OVERLAPPING_STATUS_IDS } from '@acorex/modules/human-capital-management';
26
+ import { AXPHumanCapitalManagementFeatureKeys, AXMPermissionsKeys as AXMPermissionsKeys$5, RootConfig as RootConfig$j, AXM_POSITION_ASSIGNMENT_OVERLAPPING_STATUS_IDS } from '@acorex/modules/human-capital-management';
27
27
  import { RootConfig as RootConfig$5 } from '@acorex/modules/locale-management';
28
28
  import { AXMPermissionsKeys as AXMPermissionsKeys$1, AXMSubscriptionManagementSubscriptionEntityService, AXMSubscriptionManagementSubscriptionPlanItemEntityService, RootConfig as RootConfig$w } from '@acorex/modules/subscription-management';
29
- import { AXPSecurityManagementPermissionKeys, AXMUserAccessState, resolveAXMUserEffectiveState, RootConfig as RootConfig$6, AXMUsersEntityService } from '@acorex/modules/security-management';
29
+ import { AXPSecurityManagementPermissionKeys, AXMUserAccessState, resolveAXMUserEffectiveState, RootConfig as RootConfig$6, AXMUsersEntityService, AXMPolicyService } from '@acorex/modules/security-management';
30
30
  import { AXMTenantManagementPermissionsKeys, AXMTenantService, AXMTenantManagementTenantUserEntityService, RootConfig as RootConfig$z } from '@acorex/modules/tenant-management';
31
- import { AXMPermissionsKeys as AXMPermissionsKeys$3, RootConfig as RootConfig$e, AXMDocumentTypeServiceImpl, AXPDocumentManagementService } from '@acorex/modules/document-management';
31
+ import { AXMPermissionsKeys as AXMPermissionsKeys$4, RootConfig as RootConfig$e, AXMDocumentTypeServiceImpl, AXPDocumentManagementService } from '@acorex/modules/document-management';
32
32
  import { AXMSettingsManagementPermissionKeys } from '@acorex/modules/settings-management';
33
+ import { AXMPermissionsKeys as AXMPermissionsKeys$3, RootConfig as RootConfig$y, AXPWorkflowTaskProvider } from '@acorex/modules/task-management';
33
34
  import { RootConfig as RootConfig$7 } from '@acorex/modules/business-core';
34
35
  import { RootConfig as RootConfig$8 } from '@acorex/modules/calendar-management';
35
36
  import { AXFileService } from '@acorex/core/file';
@@ -77,7 +78,6 @@ import { RootConfig as RootConfig$v } from '@acorex/modules/reservation-manageme
77
78
  import { AXMSessionStatusTypes, AXMDeviceSessionsServiceImpl, AXMDeviceSessionsService, AXM_AUTH_CONFIG_TOKEN } from '@acorex/modules/auth';
78
79
  import * as i1$3 from '@acorex/components/dialog';
79
80
  import { RootConfig as RootConfig$x } from '@acorex/modules/supplier-management';
80
- import { RootConfig as RootConfig$y, AXPWorkflowTaskProvider } from '@acorex/modules/task-management';
81
81
  import { AXPLayoutBuilderService } from '@acorex/platform/layout/builder';
82
82
  import { Router } from '@angular/router';
83
83
  import { AXPWorkflowManager, AXPWorkflowDefinitionService, AXPActivityDefinitionService, AXP_WORKFLOW_PROVIDER, WorkflowExpressionScopeService, AXP_WORKFLOW_ENGINE } from '@acorex/platform/workflow';
@@ -105,112 +105,8 @@ const AXC_FIRESTORE_CONFIG = new InjectionToken('AXC_FIRESTORE_CONFIG', {
105
105
  });
106
106
  //#endregion
107
107
 
108
- //#endregion
109
- //#region ---- Pure helpers ----
110
- /**
111
- * Fields where `contains` means hierarchical category membership (expand to descendants).
112
- * Excludes e.g. `roleIds`, which uses array membership only and must use normal filter logic.
113
- */
114
- function isCategoryContainsFieldName(field) {
115
- if (field === 'categoryIds') {
116
- return true;
117
- }
118
- if (typeof field === 'string' && field.endsWith('Ids') && field !== 'roleIds') {
119
- return true;
120
- }
121
- return false;
122
- }
123
- /**
124
- * Check if the entity is a category entity (ends with 'Category').
125
- */
126
- function isCategoryEntity(entityName) {
127
- return entityName.endsWith('Category');
128
- }
129
- /**
130
- * Check if the filter is a category filter (contains operator on categoryIds field).
131
- * Handles both simple filters and compound filters.
132
- */
133
- function isCategoryFilter(filter) {
134
- if (filter?.operator?.type === 'contains' && isCategoryContainsFieldName(filter.field)) {
135
- return true;
136
- }
137
- if (filter?.logic && filter?.filters && Array.isArray(filter.filters)) {
138
- return filter.filters.some((nestedFilter) => nestedFilter?.operator?.type === 'contains' && isCategoryContainsFieldName(nestedFilter.field));
139
- }
140
- return false;
141
- }
142
- //#endregion
143
- //#region ---- Query execution ----
144
- /**
145
- * Apply recursive category filtering: entities that belong to the category or any of its children.
146
- */
147
- async function applyRecursiveCategoryFilter(result, filter, entityName, getAllChildCategoryIds) {
148
- let categoryFilter = filter;
149
- let otherFilters = [];
150
- if (filter?.logic && filter?.filters && Array.isArray(filter.filters)) {
151
- const categoryFilterIndex = filter.filters.findIndex((f) => f?.operator?.type === 'contains' && isCategoryContainsFieldName(f.field));
152
- if (categoryFilterIndex !== -1) {
153
- categoryFilter = filter.filters[categoryFilterIndex];
154
- otherFilters = filter.filters.filter((_, index) => index !== categoryFilterIndex);
155
- }
156
- }
157
- if (!categoryFilter) {
158
- return applyFilterArray(result, [filter]);
159
- }
160
- const categoryId = categoryFilter.value;
161
- const categoryField = categoryFilter.field;
162
- const allCategoryIds = await getAllChildCategoryIds(categoryId, entityName);
163
- let filteredResult = result.filter((item) => {
164
- const categoryIds = item[categoryField];
165
- if (!categoryIds)
166
- return false;
167
- const itemCategoryIds = Array.isArray(categoryIds) ? categoryIds : [categoryIds];
168
- return itemCategoryIds.some((itemCategoryId) => allCategoryIds.includes(itemCategoryId));
169
- });
170
- if (otherFilters.length > 0) {
171
- filteredResult = applyFilterArray(filteredResult, otherFilters);
172
- }
173
- return filteredResult;
174
- }
175
- /**
176
- * Calculate childrenCount for each category entity when missing.
177
- */
178
- async function calculateChildrenCounts(items, entityName, getDirectChildCount) {
179
- return Promise.all(items.map(async (item) => {
180
- if (typeof item.childrenCount === 'number') {
181
- return { ...item };
182
- }
183
- const childrenCount = await getDirectChildCount(item.id, entityName);
184
- return { ...item, childrenCount };
185
- }));
186
- }
187
- /**
188
- * Shared entity query logic: sort, filter (including recursive category filter), childrenCount, pagination.
189
- * Used by both Dexie and Firestore backends.
190
- */
191
- async function runEntityQuery(entityName, request, adapters) {
192
- let result = await adapters.getRawAll(entityName);
193
- if (request.sort && request.sort.length) {
194
- result = applySortArray(result, request.sort);
195
- }
196
- if (request.filter && isCategoryFilter(request.filter)) {
197
- result = await applyRecursiveCategoryFilter(result, request.filter, entityName, adapters.getAllChildCategoryIds);
198
- }
199
- else {
200
- result = applyFilterArray(result, request.filter ? [request.filter] : []);
201
- }
202
- if (isCategoryEntity(entityName)) {
203
- result = await calculateChildrenCounts(result, entityName, adapters.getDirectChildCount);
204
- }
205
- const skip = request.skip ?? 0;
206
- const take = request.take ?? 0;
207
- return {
208
- total: result.length,
209
- items: result.slice(skip, skip + take),
210
- };
211
- }
212
- //#endregion
213
-
108
+ /** Rows loaded into memory for aggregation on mock backends (safety cap). */
109
+ const ENTITY_AGGREGATE_MAX_ROWS$1 = 500_000;
214
110
  class AXCDexieEntityStorageService extends Dexie {
215
111
  constructor() {
216
112
  super('ACoreXPlatform');
@@ -315,13 +211,61 @@ class AXCDexieEntityStorageService extends Dexie {
315
211
  return await this.table('entity-store').where({ entityName }).toArray();
316
212
  }
317
213
  async query(entityName, request) {
318
- return runEntityQuery(entityName, request, {
214
+ return runEntityQuery(entityName, request, this.createQueryAdapters());
215
+ }
216
+ async count(entityName, request) {
217
+ const rows = await filterSortEntityRows(entityName, request, this.createQueryAdapters());
218
+ return rows.length;
219
+ }
220
+ async queryAll(entityName, request, options) {
221
+ const rows = await filterSortEntityRows(entityName, request, this.createQueryAdapters());
222
+ const maxRows = options?.maxRows ?? Number.POSITIVE_INFINITY;
223
+ const capped = Number.isFinite(maxRows) ? rows.slice(0, maxRows) : rows;
224
+ const truncated = Number.isFinite(maxRows) && rows.length > maxRows;
225
+ return {
226
+ items: capped,
227
+ total: rows.length,
228
+ truncated,
229
+ };
230
+ }
231
+ async getMany(entityName, ids) {
232
+ return Promise.all(ids.map(async (id) => {
233
+ const row = await this.getOne(entityName, id);
234
+ return row ?? null;
235
+ }));
236
+ }
237
+ async exists(entityName, id) {
238
+ const row = await this.getOne(entityName, id);
239
+ return row != null;
240
+ }
241
+ async upsertOne(entityName, entity, options) {
242
+ const id = entity?.id;
243
+ if (id) {
244
+ const existing = await this.getOne(entityName, id);
245
+ if (existing != null) {
246
+ const merge = options?.merge !== false;
247
+ const next = merge ? { ...existing, ...entity } : { ...entity };
248
+ const { id: _omit, ...patch } = next;
249
+ await this.updateOne(entityName, id, patch);
250
+ return id;
251
+ }
252
+ }
253
+ return this.insertOne(entityName, entity);
254
+ }
255
+ async aggregate(entityName, request, options) {
256
+ const maxRows = options?.maxRows ?? ENTITY_AGGREGATE_MAX_ROWS$1;
257
+ const rows = await filterSortEntityRows(entityName, request, this.createQueryAdapters());
258
+ const slice = rows.slice(0, maxRows);
259
+ return { rows: computeEntityAggregates(slice, request) };
260
+ }
261
+ //#region ---- Private Helper Methods (used by runEntityQuery adapters) ----
262
+ createQueryAdapters() {
263
+ return {
319
264
  getRawAll: (name) => this.table('entity-store').where({ entityName: name }).toArray(),
320
265
  getDirectChildCount: (categoryId, name) => this.getDirectChildCount(categoryId, name),
321
266
  getAllChildCategoryIds: (categoryId, name) => this.getAllChildCategoryIds(categoryId, name),
322
- });
267
+ };
323
268
  }
324
- //#region ---- Private Helper Methods (used by runEntityQuery adapters) ----
325
269
  async getDirectChildCount(categoryId, entityName) {
326
270
  const children = await this.table('entity-store')
327
271
  .where({ entityName })
@@ -349,6 +293,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
349
293
  }], ctorParameters: () => [] });
350
294
 
351
295
  const ENTITY_STORE_COLLECTION = 'entity-store';
296
+ /** Rows loaded into memory for aggregation on mock backends (safety cap). */
297
+ const ENTITY_AGGREGATE_MAX_ROWS = 500_000;
352
298
  /** Firestore batch write/delete limit per commit. */
353
299
  const FIRESTORE_BATCH_MAX$1 = 500;
354
300
  /**
@@ -533,14 +479,64 @@ class AXCFirestoreEntityStorageService {
533
479
  return this.getRawAll(entityName);
534
480
  }
535
481
  async query(entityName, request) {
536
- return runEntityQuery(entityName, request, {
482
+ return runEntityQuery(entityName, request, this.createQueryAdapters());
483
+ }
484
+ async count(entityName, request) {
485
+ const rows = await filterSortEntityRows(entityName, request, this.createQueryAdapters());
486
+ return rows.length;
487
+ }
488
+ async queryAll(entityName, request, options) {
489
+ const rows = await filterSortEntityRows(entityName, request, this.createQueryAdapters());
490
+ const maxRows = options?.maxRows ?? Number.POSITIVE_INFINITY;
491
+ const capped = Number.isFinite(maxRows) ? rows.slice(0, maxRows) : rows;
492
+ const truncated = Number.isFinite(maxRows) && rows.length > maxRows;
493
+ return {
494
+ items: capped,
495
+ total: rows.length,
496
+ truncated,
497
+ };
498
+ }
499
+ async getMany(entityName, ids) {
500
+ return Promise.all(ids.map(async (id) => {
501
+ const row = await this.getOne(entityName, id);
502
+ return row ?? null;
503
+ }));
504
+ }
505
+ async exists(entityName, id) {
506
+ const row = await this.getOne(entityName, id);
507
+ return row != null;
508
+ }
509
+ async upsertOne(entityName, entity, options) {
510
+ const id = entity?.id;
511
+ if (id) {
512
+ const existing = await this.getOne(entityName, id);
513
+ if (existing != null) {
514
+ const merge = options?.merge !== false;
515
+ const next = merge
516
+ ? { ...existing, ...entity }
517
+ : { ...entity };
518
+ const { id: _omit, ...patch } = next;
519
+ await this.updateOne(entityName, id, patch);
520
+ return id;
521
+ }
522
+ }
523
+ return this.insertOne(entityName, entity);
524
+ }
525
+ async aggregate(entityName, request, options) {
526
+ const maxRows = options?.maxRows ?? ENTITY_AGGREGATE_MAX_ROWS;
527
+ const rows = await filterSortEntityRows(entityName, request, this.createQueryAdapters());
528
+ const slice = rows.slice(0, maxRows);
529
+ return { rows: computeEntityAggregates(slice, request) };
530
+ }
531
+ //#endregion
532
+ //#region ---- Adapters for runEntityQuery ----
533
+ createQueryAdapters() {
534
+ return {
537
535
  getRawAll: (name) => this.getRawAll(name),
538
536
  getDirectChildCount: (categoryId, name) => this.getDirectChildCount(categoryId, name),
539
537
  getAllChildCategoryIds: (categoryId, name) => this.getAllChildCategoryIds(categoryId, name),
540
- });
538
+ };
541
539
  }
542
- //#endregion
543
- //#region ---- Adapters for runEntityQuery ----
544
540
  /**
545
541
  * Load all documents for an entity (same approach as Dexie: load by entityName, filter in runEntityQuery).
546
542
  * Firestore and Dexie share the same runEntityQuery + applyFilterArray so behavior stays consistent.
@@ -813,6 +809,38 @@ function parseEntityStorageQueryRequest(raw) {
813
809
  };
814
810
  }
815
811
  //#endregion
812
+ //#region ---- Aggregate request parse ----
813
+ /**
814
+ * Parses optional aggregate payload (JSON object or string). Requires `groupBy` and `measures`.
815
+ */
816
+ function parseEntityStorageAggregateRequest(raw) {
817
+ if (raw == null || raw === '') {
818
+ return null;
819
+ }
820
+ let obj = raw;
821
+ if (typeof raw === 'string') {
822
+ try {
823
+ obj = JSON.parse(raw);
824
+ }
825
+ catch {
826
+ return null;
827
+ }
828
+ }
829
+ if (typeof obj !== 'object' || obj === null) {
830
+ return null;
831
+ }
832
+ const o = obj;
833
+ if (!Array.isArray(o['groupBy']) || !Array.isArray(o['measures'])) {
834
+ return null;
835
+ }
836
+ return {
837
+ groupBy: o['groupBy'],
838
+ measures: o['measures'],
839
+ filter: o['filter'],
840
+ sort: o['sort'],
841
+ };
842
+ }
843
+ //#endregion
816
844
  //#region ---- AI-friendly quick search → standard filter ----
817
845
  /** Fields commonly present across entities; always included for quickSearch. */
818
846
  const ENTITY_STORAGE_QUICK_SEARCH_BASE_FIELD_PATHS = ['id', 'code', 'title', 'name', 'shortName'];
@@ -863,6 +891,9 @@ function mergeQuickSearchIntoRequest(request, quickSearch, quickSearchExtraConta
863
891
  }
864
892
  //#endregion
865
893
 
894
+ //#region ---- Types ----
895
+ /** Default cap when draining rows (`resultMode: all`) or aggregating without `maxFetchRows`. */
896
+ const DEFAULT_MAX_FETCH_ROWS = 50_000;
866
897
  /**
867
898
  * Normalizes tool/AI payloads: string[] or JSON string array or comma-separated paths.
868
899
  */
@@ -891,10 +922,27 @@ function normalizeQuickSearchFieldPaths(raw) {
891
922
  }
892
923
  return [];
893
924
  }
925
+ function normalizeResultMode(raw) {
926
+ const s = typeof raw === 'string' ? raw.trim().toLowerCase() : raw;
927
+ if (s === 'count' || s === 'all') {
928
+ return s;
929
+ }
930
+ return 'page';
931
+ }
932
+ function normalizeMaxFetchRows(raw) {
933
+ if (raw == null || raw === '') {
934
+ return DEFAULT_MAX_FETCH_ROWS;
935
+ }
936
+ const n = typeof raw === 'number' ? raw : Number(String(raw).trim());
937
+ if (!Number.isFinite(n) || n <= 0) {
938
+ return DEFAULT_MAX_FETCH_ROWS;
939
+ }
940
+ return Math.floor(n);
941
+ }
894
942
  //#endregion
895
943
  //#region ---- Query ----
896
944
  /**
897
- * Runs {@link AXPEntityStorageService#query} against the active mock storage backend (Dexie or Firestore).
945
+ * Runs entity storage reads via {@link AXPEntityStorageService} (active connectivity backend).
898
946
  */
899
947
  class AXCEntityStorageQueryQuery {
900
948
  constructor() {
@@ -938,6 +986,46 @@ class AXCEntityStorageQueryQuery {
938
986
  const quickPaths = [...new Set([...fromSchema, ...explicit])];
939
987
  merged = mergeQuickSearchIntoRequest(request, input.quickSearch, quickPaths);
940
988
  }
989
+ const filterSort = { filter: merged.filter, sort: merged.sort };
990
+ const maxFetch = normalizeMaxFetchRows(input.maxFetchRows);
991
+ const aggregateReq = parseEntityStorageAggregateRequest(input.aggregate ?? null);
992
+ if (aggregateReq) {
993
+ const aggPayload = {
994
+ ...aggregateReq,
995
+ filter: aggregateReq.filter ?? merged.filter,
996
+ sort: aggregateReq.sort ?? merged.sort,
997
+ };
998
+ const agg = await this.entityStorage.aggregate(entity, aggPayload, {
999
+ maxRows: maxFetch,
1000
+ pageSize: 500,
1001
+ });
1002
+ return {
1003
+ success: true,
1004
+ total: agg.rows.length,
1005
+ aggregateRows: agg.rows,
1006
+ };
1007
+ }
1008
+ const mode = normalizeResultMode(input.resultMode);
1009
+ if (mode === 'count') {
1010
+ const total = await this.entityStorage.count(entity, filterSort);
1011
+ return {
1012
+ success: true,
1013
+ total,
1014
+ items: [],
1015
+ };
1016
+ }
1017
+ if (mode === 'all') {
1018
+ const all = await this.entityStorage.queryAll(entity, filterSort, {
1019
+ maxRows: maxFetch,
1020
+ pageSize: 500,
1021
+ });
1022
+ return {
1023
+ success: true,
1024
+ total: all.total,
1025
+ items: all.items,
1026
+ truncated: all.truncated,
1027
+ };
1028
+ }
941
1029
  const page = await this.entityStorage.query(entity, merged);
942
1030
  return {
943
1031
  success: true,
@@ -13908,8 +13996,8 @@ const AI_AGENT_MOCK = [
13908
13996
  'You are the platform entity specialist for ACoreX.',
13909
13997
  'Use PlatformManagement:ListRegisteredEntities to discover or validate Module.Entity keys and to inspect entity definitions (required fields, types).',
13910
13998
  'When explaining fields to end users in chat, mention **human-readable `title`** text from **`properties`**; use internal **`name`** only when the user wants technical/schema detail.',
13911
- 'Use ConnectivityMock:EntityStorage:Query to list or search stored rows once the entity key is known.',
13912
- 'If the query is paginated or totals/charts need **every** row, **fetch remaining pages** (next offset/cursor per schema) in further tool turns until complete — do not ask the user to approve each page.',
13999
+ 'Use ConnectivityMock:EntityStorage:Query to read stored rows once the entity key is known (data layer: same tool name). Prefer resultMode `all` with maxFetchRows for the full filtered set in one call, `count` for totals only, or `aggregate` (groupBy + measures) for grouped summaries before charts.',
14000
+ 'If you stay on default paging (`resultMode` page / skip–take) and totals require **every** row, fetch remaining pages in further tool turns until complete — do not ask the user to approve each page.',
13913
14001
  'Use Entity:Create and Entity:Update only with arguments that match each command schema; confirm outcomes from tool results and never fabricate success.',
13914
14002
  'Prefer read-only queries before mutations when you still need identifiers or schema details.',
13915
14003
  'When the user wants a **chart** from stored rows, finish accurate aggregation first, then let the supervisor route **widget-chart-layout**; keep your own prose minimal.',
@@ -19274,7 +19362,7 @@ class AXCAiManagementMockModule {
19274
19362
  provideCommandSetups([
19275
19363
  {
19276
19364
  key: 'AiManagement:ChatGenerateImage',
19277
- command: () => import('./acorex-connectivity-mock-chat-generate-image.command-IUvQRJU0.mjs').then((c) => c.AiManagementChatGenerateImageCommand),
19365
+ command: () => import('./acorex-connectivity-mock-chat-generate-image.command-iFiQ5rHd.mjs').then((c) => c.AiManagementChatGenerateImageCommand),
19278
19366
  },
19279
19367
  {
19280
19368
  key: 'AiManagement:ExtractDocumentText',
@@ -19286,11 +19374,11 @@ class AXCAiManagementMockModule {
19286
19374
  },
19287
19375
  {
19288
19376
  key: 'AiManagement:ChatTranscribeSpeech',
19289
- command: () => import('./acorex-connectivity-mock-chat-transcribe-speech.command-Cr0QRiqr.mjs').then((c) => c.AiManagementChatTranscribeSpeechCommand),
19377
+ command: () => import('./acorex-connectivity-mock-chat-transcribe-speech.command-NxlEgtW-.mjs').then((c) => c.AiManagementChatTranscribeSpeechCommand),
19290
19378
  },
19291
19379
  {
19292
19380
  key: 'AiManagement:ChatSynthesizeSpeech',
19293
- command: () => import('./acorex-connectivity-mock-chat-synthesize-speech.command-DE8YU17E.mjs').then((c) => c.AiManagementChatSynthesizeSpeechCommand),
19381
+ command: () => import('./acorex-connectivity-mock-chat-synthesize-speech.command-BTv6P2ez.mjs').then((c) => c.AiManagementChatSynthesizeSpeechCommand),
19294
19382
  },
19295
19383
  ]),
19296
19384
  ] }); }
@@ -19333,7 +19421,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
19333
19421
  provideCommandSetups([
19334
19422
  {
19335
19423
  key: 'AiManagement:ChatGenerateImage',
19336
- command: () => import('./acorex-connectivity-mock-chat-generate-image.command-IUvQRJU0.mjs').then((c) => c.AiManagementChatGenerateImageCommand),
19424
+ command: () => import('./acorex-connectivity-mock-chat-generate-image.command-iFiQ5rHd.mjs').then((c) => c.AiManagementChatGenerateImageCommand),
19337
19425
  },
19338
19426
  {
19339
19427
  key: 'AiManagement:ExtractDocumentText',
@@ -19345,11 +19433,11 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
19345
19433
  },
19346
19434
  {
19347
19435
  key: 'AiManagement:ChatTranscribeSpeech',
19348
- command: () => import('./acorex-connectivity-mock-chat-transcribe-speech.command-Cr0QRiqr.mjs').then((c) => c.AiManagementChatTranscribeSpeechCommand),
19436
+ command: () => import('./acorex-connectivity-mock-chat-transcribe-speech.command-NxlEgtW-.mjs').then((c) => c.AiManagementChatTranscribeSpeechCommand),
19349
19437
  },
19350
19438
  {
19351
19439
  key: 'AiManagement:ChatSynthesizeSpeech',
19352
- command: () => import('./acorex-connectivity-mock-chat-synthesize-speech.command-DE8YU17E.mjs').then((c) => c.AiManagementChatSynthesizeSpeechCommand),
19440
+ command: () => import('./acorex-connectivity-mock-chat-synthesize-speech.command-BTv6P2ez.mjs').then((c) => c.AiManagementChatSynthesizeSpeechCommand),
19353
19441
  },
19354
19442
  ]),
19355
19443
  ],
@@ -30225,6 +30313,8 @@ const mockRoleDefinitions = [
30225
30313
  AXMPermissionsKeys$2.DataManagement.DataSource.Management,
30226
30314
  AXMPermissionsKeys$2.DataManagement.MetaDataDefinition.Management,
30227
30315
  AXMPermissionsKeys$2.DataManagement.Tag.Management,
30316
+ //
30317
+ AXMPermissionsKeys$3.TaskManagement.Task.ViewAll,
30228
30318
  ],
30229
30319
  stateInfo: {
30230
30320
  isSystem: true,
@@ -30433,9 +30523,9 @@ const mockRoleDefinitions = [
30433
30523
  AXPSecurityManagementPermissionKeys.Role.Edit,
30434
30524
  AXPSecurityManagementPermissionKeys.Role.Delete,
30435
30525
  //
30436
- AXMPermissionsKeys$3.DocumentManagement.Management,
30437
- AXMPermissionsKeys$3.DocumentManagement.Driver.Management,
30438
- AXMPermissionsKeys$3.DocumentManagement.DocumentType.Management,
30526
+ AXMPermissionsKeys$4.DocumentManagement.Management,
30527
+ AXMPermissionsKeys$4.DocumentManagement.Driver.Management,
30528
+ AXMPermissionsKeys$4.DocumentManagement.DocumentType.Management,
30439
30529
  //
30440
30530
  AXMPermissionsKeys$2.DataManagement.MetaDataDefinition.Management,
30441
30531
  AXMPermissionsKeys$2.DataManagement.Tag.Management,
@@ -30443,9 +30533,9 @@ const mockRoleDefinitions = [
30443
30533
  AXMAssessmentManagementPermissionKeys.AssessmentManagement.Questionnaire.Management,
30444
30534
  AXMAssessmentManagementPermissionKeys.AssessmentManagement.QuestionBank,
30445
30535
  //
30446
- AXMPermissionsKeys$4.HumanCapitalManagement.Employee.Management,
30447
- AXMPermissionsKeys$4.HumanCapitalManagement.LeaveType.Management,
30448
- AXMPermissionsKeys$4.HumanCapitalManagement.LeaveRequest.Management,
30536
+ AXMPermissionsKeys$5.HumanCapitalManagement.Employee.Management,
30537
+ AXMPermissionsKeys$5.HumanCapitalManagement.LeaveType.Management,
30538
+ AXMPermissionsKeys$5.HumanCapitalManagement.LeaveRequest.Management,
30449
30539
  //
30450
30540
  AXMSettingsManagementPermissionKeys.TenantSettings.Management,
30451
30541
  ],
@@ -30559,8 +30649,8 @@ const rawMockUsers = [
30559
30649
  id: userIds.sarahJohnson,
30560
30650
  username: 'sarah.johnson',
30561
30651
  displayName: 'Sarah Johnson',
30562
- roleIds: [roleIdMap.admin],
30563
- roles: getRolesByIds([roleIdMap.admin]),
30652
+ roleIds: [roleIdMap.user],
30653
+ roles: getRolesByIds([roleIdMap.user]),
30564
30654
  password: '123',
30565
30655
  accountState: AXPSystemStatusType.Active,
30566
30656
  accessState: AXMUserAccessState.Allowed,
@@ -31102,6 +31192,7 @@ const personMock = [
31102
31192
  maritalStatus: maritalStatusRef(maritalStatusIds.married),
31103
31193
  educationLevelId: educationLevelIds.masters,
31104
31194
  educationLevel: educationLevelRef(educationLevelIds.masters),
31195
+ emails: [{ value: 'fatima.alzahra@example.com' }],
31105
31196
  },
31106
31197
  {
31107
31198
  id: personIds.jamesOConnor,
@@ -31710,22 +31801,32 @@ const toLocalized = (enUS, faIR) => ({
31710
31801
  });
31711
31802
  const getStatusTitle = (statusId) => {
31712
31803
  switch (statusId) {
31804
+ case AXMAssetStatus.Created:
31805
+ return toLocalized('Created', 'ایجاد شده');
31713
31806
  case AXMAssetStatus.Available:
31714
31807
  return toLocalized('Available', 'در دسترس');
31715
- case AXMAssetStatus.Archived:
31716
- return toLocalized('Archived', 'بایگانی‌شده');
31717
- case AXMAssetStatus.OutOfOrder:
31718
- return toLocalized('Out of Order', 'خارج از سرویس');
31808
+ case AXMAssetStatus.InStock:
31809
+ return toLocalized('In Stock', 'موجود در انبار');
31810
+ case AXMAssetStatus.Reserved:
31811
+ return toLocalized('Reserved', 'رزرو شده');
31812
+ case AXMAssetStatus.Assigned:
31813
+ return toLocalized('Assigned', 'تخصیص داده شده');
31814
+ case AXMAssetStatus.Installed:
31815
+ return toLocalized('Installed', 'نصب شده');
31816
+ case AXMAssetStatus.UnderInspection:
31817
+ return toLocalized('Under Inspection', 'تحت بازرسی');
31818
+ case AXMAssetStatus.UnderMaintenance:
31819
+ return toLocalized('Under Maintenance', 'تحت نگهداری');
31820
+ case AXMAssetStatus.OutOfService:
31821
+ return toLocalized('Out of Service', 'خارج از سرویس');
31719
31822
  case AXMAssetStatus.Retired:
31720
31823
  return toLocalized('Retired', 'بازنشسته');
31721
- case AXMAssetStatus.Suspended:
31722
- return toLocalized('Suspended', 'معلق');
31723
- case AXMAssetStatus.Transferring:
31724
- return toLocalized('Transferring', 'در حال انتقال');
31725
- case AXMAssetStatus.UnderRepair:
31726
- return toLocalized('Under Repair', 'در حال تعمیر');
31727
- case AXMAssetStatus.Inactive:
31728
- return toLocalized('Inactive', 'غیرفعال');
31824
+ case AXMAssetStatus.Disposed:
31825
+ return toLocalized('Disposed', 'امحا شده');
31826
+ case AXMAssetStatus.Lost:
31827
+ return toLocalized('Lost', 'مفقود');
31828
+ case AXMAssetStatus.ReturnedToSupplier:
31829
+ return toLocalized('Returned to Supplier', 'بازگشت به تامین کننده');
31729
31830
  default:
31730
31831
  return toLocalized(String(statusId ?? ''), String(statusId ?? ''));
31731
31832
  }
@@ -31849,7 +31950,7 @@ const assetEntries = [
31849
31950
  code: `ASST-${MOCK_ASSET_CODE_YYYYMM}-${MOCK_ASSET_CODE_SEQ(7)}`,
31850
31951
  title: 'Field Service Van 01',
31851
31952
  titleFa: 'ون خدمات میدانی ۰۱',
31852
- statusId: AXMAssetStatus.Inactive,
31953
+ statusId: AXMAssetStatus.Assigned,
31853
31954
  ownerEmployeeCode: EMPLOYEES_MOCK[0]?.employeeCode,
31854
31955
  assignedEmployeeCode: EMPLOYEES_MOCK[2]?.employeeCode ?? EMPLOYEES_MOCK[0]?.employeeCode,
31855
31956
  locationCode: 'LA-TH-001',
@@ -32534,18 +32635,17 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
32534
32635
  //#endregion
32535
32636
  //#region ---- Mock Permission Checker ----
32536
32637
  /**
32537
- * Mock permission checker that provides custom authorization logic.
32538
- * - Root user always has all permissions
32539
- * - Tenant account owner always has all permissions
32638
+ * Mock permission checker.
32639
+ * - `root`, `root2`, `super-root`: pass all permission checks (platform operators in demo).
32640
+ * - Everyone else: use role-granted permissions only (e.g. `Task.ViewAll` is not implied for `heidi.thonig`).
32540
32641
  */
32541
32642
  class MockPermissionChecker {
32643
+ static { this.platformRootUsernames = new Set(['root', 'root2', 'super-root']); }
32542
32644
  check(keys, context, baseResult) {
32543
- const user = context.user;
32544
- // Root user always has all permissions
32545
- if (user?.name === 'super-root' || user?.name === 'heidi.thonig' || user?.name === 'emily.rodriguez') {
32645
+ const username = context.user?.name;
32646
+ if (username != null && MockPermissionChecker.platformRootUsernames.has(username)) {
32546
32647
  return true;
32547
32648
  }
32548
- // Otherwise, use base result
32549
32649
  return baseResult;
32550
32650
  }
32551
32651
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: MockPermissionChecker, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
@@ -42970,9 +43070,10 @@ class AXCDocumentManagementService {
42970
43070
  return await this.getFolderPath(file.parentId, stopFolderId);
42971
43071
  }
42972
43072
  async searchFiles(searchTerm, rootFolderId, options) {
43073
+ console.log('options', options);
42973
43074
  const metadataFilters = options?.metadataFilters;
42974
43075
  const documentTypeIds = options?.documentTypeIds;
42975
- const hasMetadataFilters = metadataFilters != null && Object.keys(metadataFilters).length > 0;
43076
+ const hasMetadataFilters = metadataFilters != null && metadataFilters.length > 0;
42976
43077
  const hasDocTypeFilter = documentTypeIds != null && documentTypeIds.length > 0;
42977
43078
  if (hasMetadataFilters || hasDocTypeFilter) {
42978
43079
  const all = [];
@@ -43007,7 +43108,7 @@ class AXCDocumentManagementService {
43007
43108
  return v;
43008
43109
  }
43009
43110
  /**
43010
- * Reads a comparable value from a stored metaDataForm entry.
43111
+ * Reads a comparable value from a stored metaDataForm entry (select-like `{ value, text }` or plain scalars).
43011
43112
  */
43012
43113
  storedMetaEntryToComparable(raw) {
43013
43114
  if (raw != null && typeof raw === 'object' && !Array.isArray(raw) && 'value' in raw) {
@@ -43020,29 +43121,98 @@ class AXCDocumentManagementService {
43020
43121
  return filterKey.startsWith(prefix) ? filterKey.slice(prefix.length) : filterKey;
43021
43122
  }
43022
43123
  /**
43023
- * Whether the document's metaDataForm satisfies all metadata filter entries.
43124
+ * Whether the document's metaDataForm satisfies all metadata filter queries (AND), using operator semantics
43125
+ * aligned with the query filter panel ({@link AXPFilterQuery}).
43024
43126
  */
43025
- documentDtoMatchesMetadataFilters(file, metaFilters) {
43127
+ documentDtoMatchesMetadataFilters(file, queries) {
43128
+ return queries.every((q) => this.documentDtoMatchesOneMetadataQuery(file, q));
43129
+ }
43130
+ documentDtoMatchesOneMetadataQuery(file, query) {
43131
+ const field = query.field;
43132
+ if (!field) {
43133
+ return true;
43134
+ }
43135
+ const key = this.metaDataFormKeyForFilter(field);
43026
43136
  const form = file.metaDataForm;
43137
+ /** Runtime operator names from filter widgets may extend the CDK-typed union on {@link AXPFilterQuery}. */
43138
+ const opType = query.operator?.type;
43139
+ if (opType === 'isEmpty' || opType === 'isNull') {
43140
+ if (!form || typeof form !== 'object' || Array.isArray(form)) {
43141
+ return true;
43142
+ }
43143
+ const raw = form[key];
43144
+ const v = this.storedMetaEntryToComparable(raw);
43145
+ return v == null || v === '';
43146
+ }
43147
+ if (opType === 'isNotEmpty') {
43148
+ if (!form || typeof form !== 'object' || Array.isArray(form)) {
43149
+ return false;
43150
+ }
43151
+ const raw = form[key];
43152
+ const v = this.storedMetaEntryToComparable(raw);
43153
+ return v != null && v !== '';
43154
+ }
43027
43155
  if (!form || typeof form !== 'object' || Array.isArray(form)) {
43028
43156
  return false;
43029
43157
  }
43030
43158
  const record = form;
43031
- return Object.entries(metaFilters).every(([filterKey, filterRaw]) => {
43032
- const key = this.metaDataFormKeyForFilter(filterKey);
43033
- const filterValue = this.unwrapMetadataComparableValue(filterRaw);
43034
- if (filterValue == null || filterValue === '') {
43035
- return true;
43159
+ const metaValue = this.storedMetaEntryToComparable(record[key]);
43160
+ if (opType === 'between') {
43161
+ const betweenRaw = query.value;
43162
+ const fromN = betweenRaw?.from != null && betweenRaw.from !== '' ? Number(betweenRaw.from) : NaN;
43163
+ const toN = betweenRaw?.to != null && betweenRaw.to !== '' ? Number(betweenRaw.to) : NaN;
43164
+ const n = Number(metaValue);
43165
+ if (Number.isNaN(n)) {
43166
+ return false;
43036
43167
  }
43037
- const metaValue = this.storedMetaEntryToComparable(record[key]);
43038
- if (metaValue == null) {
43168
+ if (!Number.isNaN(fromN) && n < fromN) {
43039
43169
  return false;
43040
43170
  }
43041
- if (typeof filterValue === 'string') {
43042
- return String(metaValue).toLowerCase().includes(String(filterValue).toLowerCase());
43171
+ if (!Number.isNaN(toN) && n > toN) {
43172
+ return false;
43043
43173
  }
43044
- return metaValue === filterValue;
43045
- });
43174
+ return true;
43175
+ }
43176
+ const filterComparable = this.unwrapMetadataComparableValue(query.value);
43177
+ if (filterComparable == null || filterComparable === '') {
43178
+ return true;
43179
+ }
43180
+ if (metaValue == null) {
43181
+ return false;
43182
+ }
43183
+ const metaStr = String(metaValue);
43184
+ const filterStr = String(filterComparable);
43185
+ switch (opType) {
43186
+ case 'contains':
43187
+ return metaStr.toLowerCase().includes(filterStr.toLowerCase());
43188
+ case 'notContains':
43189
+ return !metaStr.toLowerCase().includes(filterStr.toLowerCase());
43190
+ case 'startsWith':
43191
+ return metaStr.toLowerCase().startsWith(filterStr.toLowerCase());
43192
+ case 'endsWith':
43193
+ return metaStr.toLowerCase().endsWith(filterStr.toLowerCase());
43194
+ case 'notEqual':
43195
+ return metaValue !== filterComparable && metaStr !== filterStr;
43196
+ case 'greaterThan':
43197
+ case 'gt':
43198
+ return Number(metaValue) > Number(filterComparable);
43199
+ case 'greaterThanOrEqual':
43200
+ case 'gte':
43201
+ return Number(metaValue) >= Number(filterComparable);
43202
+ case 'lessThan':
43203
+ case 'lt':
43204
+ return Number(metaValue) < Number(filterComparable);
43205
+ case 'lessThanOrEqual':
43206
+ case 'lte':
43207
+ return Number(metaValue) <= Number(filterComparable);
43208
+ case 'in': {
43209
+ const list = Array.isArray(filterComparable) ? filterComparable : [filterComparable];
43210
+ return list.some((x) => x === metaValue || String(x) === metaStr);
43211
+ }
43212
+ case 'equal':
43213
+ default:
43214
+ return metaValue === filterComparable || metaStr === filterStr;
43215
+ }
43046
43216
  }
43047
43217
  /**
43048
43218
  * Recursive collect of all files under a folder.
@@ -43656,6 +43826,12 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
43656
43826
  type: Injectable
43657
43827
  }] });
43658
43828
 
43829
+ /**
43830
+ * Drive mock tree: `parentId` is the source of truth for hierarchy. Each folder's `folders` and
43831
+ * `documents` arrays contain direct children only (no duplicate projection into ancestors).
43832
+ * `folderStorageMiddleware` updates embedded lists on the immediate parent only and skips
43833
+ * `stateInfo.isSystem` parents so platform root folders are not persisted on every deep create.
43834
+ */
43659
43835
  // Section: Constants and Initial Setup
43660
43836
  const checkbox = '{"type":"document-layout","children":[{"type":"page-layout","children":[{"type":"checkbox-editor","name":"checkbox-editor1","options":{"label":"i accept","readonly":false,"disabled":false},"defaultValue":false,"path":"accept-check-box"}],"name":"page-layout1"}],"name":"document"}';
43661
43837
  const allTypes = DOCUMENT_TYPES;
@@ -43743,7 +43919,7 @@ const rootTenantsFolder = {
43743
43919
  size: getRandomSize(),
43744
43920
  description: `Folder Of Tenants`,
43745
43921
  parentId: rootFolder.id,
43746
- stateInfo: { isSystem: false, isHidden: false },
43922
+ stateInfo: { isSystem: true, isHidden: false },
43747
43923
  auditInfo: {
43748
43924
  created: { at: new Date(), by: { id: 'system', type: 'user' } },
43749
43925
  updated: { at: new Date(), by: { id: 'system', type: 'user' } },
@@ -43769,9 +43945,9 @@ function getRandomMetadata() {
43769
43945
  const docNo = sampleDocNos[Math.floor(Math.random() * sampleDocNos.length)];
43770
43946
  const projectTypeKey = sampleProjectTypes[Math.floor(Math.random() * sampleProjectTypes.length)];
43771
43947
  return {
43772
- 'project-name': { value: projectName, title: 'Project Name', name: 'project-name' },
43773
- 'doc-no': { value: docNo, title: 'Doc No', name: 'doc-no' },
43774
- 'project-type': { value: projectTypeKey, title: 'Project Type', name: 'project-type' },
43948
+ 'project-name': { value: projectName, text: 'Project Name' },
43949
+ 'doc-no': { value: docNo, text: 'Doc No' },
43950
+ 'project-type': { value: projectTypeKey, text: sampleProjectTypeLabels[projectTypeKey] ?? projectTypeKey },
43775
43951
  };
43776
43952
  }
43777
43953
  // Section: Sample File Types
@@ -43899,7 +44075,7 @@ function createTenantFolderStructure(tenantId, tenantName) {
43899
44075
  size: getRandomSize(),
43900
44076
  description: `Folder Of Users`,
43901
44077
  parentId: mainTenantFolder.id,
43902
- stateInfo: { isSystem: false, isHidden: false },
44078
+ stateInfo: { isSystem: true, isHidden: false },
43903
44079
  auditInfo: {
43904
44080
  created: { at: new Date(), by: { id: 'system', type: 'user' } },
43905
44081
  updated: { at: new Date(), by: { id: 'system', type: 'user' } },
@@ -43925,7 +44101,7 @@ function createTenantFolderStructure(tenantId, tenantName) {
43925
44101
  size: getRandomSize(),
43926
44102
  description: `Folder of User : ${user.displayName}`,
43927
44103
  parentId: rootUsersFolder.id,
43928
- stateInfo: { isSystem: false, isHidden: false },
44104
+ stateInfo: { isSystem: true, isHidden: false },
43929
44105
  auditInfo: {
43930
44106
  created: { at: new Date(), by: { id: 'system', type: 'user' } },
43931
44107
  updated: { at: new Date(), by: { id: 'system', type: 'user' } },
@@ -43963,8 +44139,7 @@ function createTenantFolderStructure(tenantId, tenantName) {
43963
44139
  metaDataForm: {
43964
44140
  type: {
43965
44141
  value: extension == 'png' || extension == 'jpg' ? 'image' : extension,
43966
- name: 'type',
43967
- title: 'Type',
44142
+ text: 'Type',
43968
44143
  },
43969
44144
  ...getRandomMetadata(),
43970
44145
  },
@@ -44049,8 +44224,7 @@ function createTenantFolderStructure(tenantId, tenantName) {
44049
44224
  metaDataForm: {
44050
44225
  type: {
44051
44226
  value: fileType.ext == 'png' || fileType.ext == 'jpg' ? 'image' : fileType.ext,
44052
- title: 'Type',
44053
- name: 'title',
44227
+ text: 'Type',
44054
44228
  },
44055
44229
  ...getRandomMetadata(),
44056
44230
  },
@@ -44112,8 +44286,7 @@ function createTenantFolderStructure(tenantId, tenantName) {
44112
44286
  metaDataForm: {
44113
44287
  type: {
44114
44288
  value: extension == 'png' || extension == 'jpg' ? 'image' : extension,
44115
- title: 'Type',
44116
- name: 'title',
44289
+ text: 'Type',
44117
44290
  },
44118
44291
  ...getRandomMetadata(),
44119
44292
  },
@@ -44170,8 +44343,7 @@ function createTenantFolderStructure(tenantId, tenantName) {
44170
44343
  metaDataForm: {
44171
44344
  type: {
44172
44345
  value: fileType.ext == 'png' || fileType.ext == 'jpg' ? 'image' : fileType.ext,
44173
- title: 'Type',
44174
- name: 'title',
44346
+ text: 'Type',
44175
44347
  },
44176
44348
  ...getRandomMetadata(),
44177
44349
  },
@@ -44222,14 +44394,91 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
44222
44394
  }] });
44223
44395
 
44224
44396
  const FOLDER_ENTITY$1 = 'DocumentManagement.Folder';
44397
+ const DOCUMENT_ENTITY$2 = 'DocumentManagement.Document';
44398
+ function isSystemFolder(folder) {
44399
+ return Boolean(folder?.stateInfo?.isSystem);
44400
+ }
44401
+ function filterByParentIdEquals(parentId) {
44402
+ return {
44403
+ operator: null,
44404
+ logic: 'and',
44405
+ filters: [{ field: 'parentId', operator: { type: 'equal' }, value: parentId }],
44406
+ };
44407
+ }
44408
+ /**
44409
+ * Replaces each direct child folder with the persisted row from `getOne`.
44410
+ * Embedded snapshots in `parent.folders` stay stale after documents or nested folders are added;
44411
+ * only rows missing from the embed were previously re-fetched.
44412
+ */
44413
+ async function refreshDirectChildFolderSnapshotsFromStorage(backend, folderEntityName, folders) {
44414
+ const out = [];
44415
+ for (const f of folders) {
44416
+ if (!f?.id) {
44417
+ out.push(f);
44418
+ continue;
44419
+ }
44420
+ try {
44421
+ const fresh = (await backend.getOne(folderEntityName, f.id));
44422
+ out.push(fresh ?? f);
44423
+ }
44424
+ catch {
44425
+ out.push(f);
44426
+ }
44427
+ }
44428
+ return out;
44429
+ }
44430
+ /**
44431
+ * Appends direct child folders/documents discovered by `parentId` when they are missing from embedded arrays,
44432
+ * then refreshes every direct child folder from storage so embedded denormalized rows match persisted content.
44433
+ * Keeps drive listing and mock `searchFolders` / `searchFiles` (which walk `folders` from `getOne`) aligned with persisted rows.
44434
+ */
44435
+ async function mergeMissingDirectChildrenFromStorage(backend, folderEntityName, folder) {
44436
+ if (!folder.id)
44437
+ return;
44438
+ const parentFilter = filterByParentIdEquals(folder.id);
44439
+ const embeddedFolders = folder.folders ?? [];
44440
+ const folderIdSet = new Set(embeddedFolders.map((f) => f.id));
44441
+ const mergedFolders = [...embeddedFolders];
44442
+ const folderPage = await backend.query(folderEntityName, { skip: 0, take: 2000, filter: parentFilter });
44443
+ for (const row of folderPage.items) {
44444
+ if (!row?.id || folderIdSet.has(row.id))
44445
+ continue;
44446
+ folderIdSet.add(row.id);
44447
+ try {
44448
+ const full = (await backend.getOne(folderEntityName, row.id));
44449
+ mergedFolders.push(full ?? row);
44450
+ }
44451
+ catch {
44452
+ mergedFolders.push(row);
44453
+ }
44454
+ }
44455
+ folder.folders = await refreshDirectChildFolderSnapshotsFromStorage(backend, folderEntityName, mergedFolders);
44456
+ const embeddedDocs = (folder.documents ?? []);
44457
+ const docIdSet = new Set(embeddedDocs.map((d) => d.id).filter((id) => Boolean(id)));
44458
+ const mergedDocs = [...embeddedDocs];
44459
+ const docPage = await backend.query(DOCUMENT_ENTITY$2, { skip: 0, take: 2000, filter: parentFilter });
44460
+ for (const row of docPage.items) {
44461
+ if (!row?.id || docIdSet.has(row.id))
44462
+ continue;
44463
+ docIdSet.add(row.id);
44464
+ try {
44465
+ const full = await backend.getOne(DOCUMENT_ENTITY$2, row.id);
44466
+ mergedDocs.push(full != null ? full : row);
44467
+ }
44468
+ catch {
44469
+ mergedDocs.push(row);
44470
+ }
44471
+ }
44472
+ folder.documents = mergedDocs;
44473
+ }
44225
44474
  /**
44226
44475
  * Folder Storage Middleware
44227
44476
  *
44228
44477
  * Applies folder-specific behavior via storage layer (no service override):
44229
- * - create: enriches ownership from session, default inherit; after persist syncs parent.folders.
44230
- * - update: after persist, removes from old parent if parentId changed, syncs parent.folders.
44231
- * - delete: before delete loads folder, after delete removes from parent.folders.
44232
- * - getOne: enriches childrenCount/itemsCount and inherited properties (ownership, documentTypes).
44478
+ * - create: enriches ownership from session, default inherit; after persist syncs immediate parent.folders only.
44479
+ * - update: after persist, removes from old parent if parentId changed, syncs immediate parent.folders only.
44480
+ * - delete: before delete loads folder, after delete removes from parent.folders (immediate parent only).
44481
+ * - getOne: merges missing direct children from storage by `parentId`, refreshes each embedded child folder from storage, then enriches counts and inherited properties.
44233
44482
  */
44234
44483
  const folderStorageMiddleware = {
44235
44484
  target: {
@@ -44277,34 +44526,36 @@ const folderStorageMiddleware = {
44277
44526
  }
44278
44527
  await next();
44279
44528
  const backend = ctx.backend;
44280
- const updateParentFolders = async (folder) => {
44529
+ /**
44530
+ * Updates only the direct parent's embedded `folders` list (no ancestor walk).
44531
+ * Skips persistence when the parent is a system folder so mock roots are not mutated.
44532
+ */
44533
+ const syncImmediateParentFoldersList = async (folder) => {
44281
44534
  if (!folder.parentId)
44282
44535
  return;
44283
44536
  const parent = (await backend.getOne(ctx.entityName, folder.parentId));
44284
- if (!parent?.id)
44537
+ if (!parent?.id || isSystemFolder(parent))
44285
44538
  return;
44286
44539
  const folders = parent.folders ?? [];
44287
44540
  const idx = folders.findIndex((f) => f.id === folder.id);
44288
44541
  const nextFolders = idx === -1 ? [...folders, folder] : folders.map((f, i) => (i === idx ? folder : f));
44289
44542
  await backend.updateOne(ctx.entityName, parent.id, { folders: nextFolders });
44290
- await updateParentFolders(parent);
44291
44543
  };
44292
- const removeFromParent = async (folder) => {
44544
+ const removeFromImmediateParentFoldersList = async (folder) => {
44293
44545
  if (!folder.parentId)
44294
44546
  return;
44295
44547
  const parent = (await backend.getOne(ctx.entityName, folder.parentId));
44296
- if (!parent?.id || !parent.folders)
44548
+ if (!parent?.id || !parent.folders || isSystemFolder(parent))
44297
44549
  return;
44298
44550
  const nextFolders = parent.folders.filter((f) => f.id !== folder.id);
44299
44551
  await backend.updateOne(ctx.entityName, parent.id, { folders: nextFolders });
44300
- await updateParentFolders(parent);
44301
44552
  };
44302
- // ---- create: after insert, sync parent.folders ----
44553
+ // ---- create: after insert, sync immediate parent.folders ----
44303
44554
  if (ctx.op === 'create' && ctx.result) {
44304
44555
  const newId = ctx.result;
44305
44556
  const folderData = (await backend.getOne(ctx.entityName, newId));
44306
44557
  if (folderData) {
44307
- await updateParentFolders(folderData);
44558
+ await syncImmediateParentFoldersList(folderData);
44308
44559
  }
44309
44560
  }
44310
44561
  // ---- update: remove from old parent if parentId changed, then sync new parent ----
@@ -44312,17 +44563,18 @@ const folderStorageMiddleware = {
44312
44563
  const updated = ctx.result;
44313
44564
  const data = (ctx.data || {});
44314
44565
  if (data.parentId !== undefined && currentFolder.parentId !== data.parentId) {
44315
- await removeFromParent(currentFolder);
44566
+ await removeFromImmediateParentFoldersList(currentFolder);
44316
44567
  }
44317
- await updateParentFolders(updated);
44568
+ await syncImmediateParentFoldersList(updated);
44318
44569
  }
44319
44570
  // ---- delete: remove from parent after delete ----
44320
44571
  if (ctx.op === 'delete' && folderBeforeDelete) {
44321
- await removeFromParent(folderBeforeDelete);
44572
+ await removeFromImmediateParentFoldersList(folderBeforeDelete);
44322
44573
  }
44323
- // ---- getOne: enrich childrenCount, itemsCount, inherited props ----
44574
+ // ---- getOne: merge direct children by parentId, enrich counts, inherited props ----
44324
44575
  if (ctx.op === 'getOne' && ctx.result) {
44325
44576
  const folder = ctx.result;
44577
+ await mergeMissingDirectChildrenFromStorage(backend, ctx.entityName, folder);
44326
44578
  folder.childrenCount = folder.folders?.length ?? 0;
44327
44579
  folder.itemsCount = folder.documents?.length ?? 0;
44328
44580
  if (folder.folders) {
@@ -53068,6 +53320,45 @@ function defaultIdField(dataPath) {
53068
53320
  const leaf = (dataPath || '').split('.').filter(Boolean).pop() || 'related';
53069
53321
  return `${leaf}Id`;
53070
53322
  }
53323
+ /**
53324
+ * Reads merge-detail child data for referenced persistence: nested `dataPath` object and/or dotted keys
53325
+ * on the parent payload (`person.emails`, ...). Some clients send only flat dotted keys; without this,
53326
+ * `PersonCore.Person` is never updated and `getOne` hydrate keeps outdated contact fields on the host.
53327
+ */
53328
+ function readMergeDetailSubtree(parentData, dataPath) {
53329
+ if (!dataPath || parentData == null || typeof parentData !== 'object') {
53330
+ return undefined;
53331
+ }
53332
+ const root = get(parentData, dataPath);
53333
+ const prefix = `${dataPath}.`;
53334
+ const flatKeys = Object.keys(parentData).filter((k) => k.startsWith(prefix));
53335
+ const hasFlat = flatKeys.length > 0;
53336
+ if (root != null && typeof root === 'object' && !Array.isArray(root)) {
53337
+ const base = { ...root };
53338
+ if (hasFlat) {
53339
+ for (const key of flatKeys) {
53340
+ const tail = key.slice(prefix.length);
53341
+ if (!tail) {
53342
+ continue;
53343
+ }
53344
+ set(base, tail, get(parentData, key));
53345
+ }
53346
+ }
53347
+ return base;
53348
+ }
53349
+ if (!hasFlat) {
53350
+ return undefined;
53351
+ }
53352
+ const base = {};
53353
+ for (const key of flatKeys) {
53354
+ const tail = key.slice(prefix.length);
53355
+ if (!tail) {
53356
+ continue;
53357
+ }
53358
+ set(base, tail, get(parentData, key));
53359
+ }
53360
+ return base;
53361
+ }
53071
53362
  /** Only string/number ids are valid FK/PK for storage; ignore objects/arrays (bad form state). */
53072
53363
  function coerceRecordId(value) {
53073
53364
  if (value == null) {
@@ -53106,7 +53397,7 @@ const mergeDetailRelationMiddleware = {
53106
53397
  const idField = p.idField || defaultIdField(dp);
53107
53398
  const entries = Object.entries(p.map || {});
53108
53399
  const requiresChild = entries.some(([_, src]) => typeof src === 'string' && !src.startsWith('$parent.'));
53109
- const child = dp ? get(ctx.data, dp) : undefined;
53400
+ const child = dp ? readMergeDetailSubtree(ctx.data, dp) : undefined;
53110
53401
  if (requiresChild && (dp == null || child == null)) {
53111
53402
  // No available child object while mapping expects it
53112
53403
  continue;
@@ -53977,6 +54268,380 @@ async function resolveCategoriesWithAncestors(backend, categoryEntityName, categ
53977
54268
  return Array.from(collected.values());
53978
54269
  }
53979
54270
 
54271
+ /** Cache TTL in ms - policies rarely change during a session */
54272
+ const POLICY_CACHE_TTL_MS = 30_000;
54273
+ /** In-memory cache for policies - avoids N+1 Policy queries per page (one per entity operation) */
54274
+ let policyCache = null;
54275
+ /** In-flight promise for request deduplication - parallel entity ops share one Policy load */
54276
+ let policyLoadPromise = null;
54277
+ /**
54278
+ * resolve whether a policy matches current entity by wildcard (*) or exact name
54279
+ */
54280
+ function matchesEntity(target, entityName) {
54281
+ if (!target || target === '*')
54282
+ return true;
54283
+ return target === entityName;
54284
+ }
54285
+ /**
54286
+ * apply masking to a value using a simple standard mask
54287
+ */
54288
+ function maskValue(value) {
54289
+ if (value == null)
54290
+ return value;
54291
+ const str = String(value);
54292
+ if (str.length <= 4)
54293
+ return '****';
54294
+ return `${'*'.repeat(Math.max(0, str.length - 4))}${str.slice(-4)}`;
54295
+ }
54296
+ /**
54297
+ * remove fields from an object by dotted paths; supports single-level for now
54298
+ */
54299
+ function removeFields(obj, paths) {
54300
+ if (!obj || !paths?.length)
54301
+ return;
54302
+ // Helper: delete by dotted path (e.g., "a.b.c")
54303
+ const deleteByPath = (target, path) => {
54304
+ const parts = path.split('.');
54305
+ let cursor = target;
54306
+ for (let i = 0; i < parts.length - 1; i++) {
54307
+ const key = parts[i];
54308
+ if (cursor == null || typeof cursor !== 'object')
54309
+ return;
54310
+ cursor = cursor[key];
54311
+ }
54312
+ const lastKey = parts[parts.length - 1];
54313
+ if (cursor && typeof cursor === 'object' && Object.prototype.hasOwnProperty.call(cursor, lastKey)) {
54314
+ delete cursor[lastKey];
54315
+ }
54316
+ };
54317
+ // If wildcard present, remove all top-level fields
54318
+ if (paths.includes('*')) {
54319
+ for (const key of Object.keys(obj)) {
54320
+ delete obj[key];
54321
+ }
54322
+ }
54323
+ for (const p of paths) {
54324
+ if (!p || p === '*')
54325
+ continue;
54326
+ if (p.includes('.')) {
54327
+ deleteByPath(obj, p);
54328
+ }
54329
+ else if (Object.prototype.hasOwnProperty.call(obj, p)) {
54330
+ delete obj[p];
54331
+ }
54332
+ }
54333
+ }
54334
+ /**
54335
+ * set masked fields in object by dotted paths; supports single-level for now
54336
+ */
54337
+ function setMasked(obj, paths) {
54338
+ if (!obj || !paths?.length)
54339
+ return;
54340
+ // Helper: set mask by dotted path (e.g., "a.b.c")
54341
+ const maskByPath = (target, path) => {
54342
+ const parts = path.split('.');
54343
+ let cursor = target;
54344
+ for (let i = 0; i < parts.length - 1; i++) {
54345
+ const key = parts[i];
54346
+ if (cursor == null || typeof cursor !== 'object')
54347
+ return;
54348
+ cursor = cursor[key];
54349
+ }
54350
+ const lastKey = parts[parts.length - 1];
54351
+ if (cursor && typeof cursor === 'object' && Object.prototype.hasOwnProperty.call(cursor, lastKey)) {
54352
+ cursor[lastKey] = maskValue(cursor[lastKey]);
54353
+ }
54354
+ };
54355
+ // If wildcard present, mask all top-level primitive fields
54356
+ if (paths.includes('*')) {
54357
+ for (const key of Object.keys(obj)) {
54358
+ if (Object.prototype.hasOwnProperty.call(obj, key)) {
54359
+ const val = obj[key];
54360
+ if (val == null || typeof val !== 'object') {
54361
+ obj[key] = maskValue(val);
54362
+ }
54363
+ }
54364
+ }
54365
+ }
54366
+ for (const p of paths) {
54367
+ if (!p || p === '*')
54368
+ continue;
54369
+ if (p.includes('.')) {
54370
+ maskByPath(obj, p);
54371
+ }
54372
+ else if (Object.prototype.hasOwnProperty.call(obj, p)) {
54373
+ obj[p] = maskValue(obj[p]);
54374
+ }
54375
+ }
54376
+ }
54377
+ /**
54378
+ * collect effect targets from a list of rules filtered by effect name
54379
+ */
54380
+ function collectTargets(rules, effect) {
54381
+ return rules.filter(r => r.effect === effect).map(r => r.target).filter(Boolean);
54382
+ }
54383
+ /**
54384
+ * Evaluate a policy's rules against the provided scope
54385
+ */
54386
+ async function isRuleActive(conditions, evaluator, extraScope) {
54387
+ // Note: conditions is AXPExpression and may be a template string {{ ... }} or boolean
54388
+ const result = await evaluator.evaluate(conditions, extraScope);
54389
+ return Boolean(result);
54390
+ }
54391
+ const policyEnforceMiddleware = {
54392
+ target: { ops: ['create', 'update', 'delete', 'getOne', 'getAll', 'query'], order: 5 },
54393
+ execute: async (ctx, next) => {
54394
+ // try { console.warn('[policy] enter-middleware', ctx.op, ctx.entityName, ctx.id); } catch {}
54395
+ // Inject services at the top (before any await) to ensure injection context
54396
+ const policyService = inject(AXMPolicyService);
54397
+ const evaluator = inject(AXPExpressionEvaluatorService);
54398
+ const backend = inject(AXP_ENTITY_STORAGE_BACKEND);
54399
+ // Prevent recursion: skip enforcement when querying the Policy entity itself
54400
+ const policyEntityFullName = `${RootConfig$6.module.name}.${RootConfig$6.entities.policy.name}`;
54401
+ if (ctx.entityName === policyEntityFullName) {
54402
+ // Invalidate cache when Policy is modified so next entity op gets fresh policies
54403
+ if (ctx.op === 'create' || ctx.op === 'update' || ctx.op === 'delete') {
54404
+ policyCache = null;
54405
+ }
54406
+ await next();
54407
+ return;
54408
+ }
54409
+ // Load all policies (cached + request deduplication - parallel entity ops share one Policy load)
54410
+ let policies = [];
54411
+ const now = Date.now();
54412
+ if (policyCache && now - policyCache.timestamp < POLICY_CACHE_TTL_MS) {
54413
+ policies = policyCache.policies;
54414
+ }
54415
+ else {
54416
+ if (!policyLoadPromise) {
54417
+ policyLoadPromise = (async () => {
54418
+ try {
54419
+ const res = await policyService.query({ skip: 0, take: 1000 });
54420
+ const items = (res?.items ?? []);
54421
+ policyCache = { policies: items, timestamp: Date.now() };
54422
+ return items;
54423
+ }
54424
+ catch {
54425
+ return [];
54426
+ }
54427
+ finally {
54428
+ policyLoadPromise = null;
54429
+ }
54430
+ })();
54431
+ }
54432
+ policies = await policyLoadPromise;
54433
+ }
54434
+ const applicable = policies.filter(p => p?.resource?.type === 'entity' && matchesEntity(p.resource?.target, ctx.entityName));
54435
+ if (applicable.length === 0) {
54436
+ await next();
54437
+ return;
54438
+ }
54439
+ // Build evaluation scope per operation
54440
+ const buildScope = (overrides) => {
54441
+ const existing = overrides?.existing;
54442
+ const result = overrides?.result ?? ctx.result;
54443
+ return {
54444
+ // Additional scopes are provided via providers (session, permission). Here we add op-specific context.
54445
+ context: {
54446
+ op: ctx.op,
54447
+ entity: ctx.entityName,
54448
+ id: ctx.id,
54449
+ data: ctx.data,
54450
+ existing: existing,
54451
+ result: result,
54452
+ // Add eval function to access data fields
54453
+ eval: (key) => {
54454
+ // Helper function to get nested property
54455
+ const getNestedProperty = (obj, path) => {
54456
+ if (!obj || !path)
54457
+ return undefined;
54458
+ const parts = path.split('.');
54459
+ let current = obj;
54460
+ for (const part of parts) {
54461
+ if (current && typeof current === 'object' && part in current) {
54462
+ current = current[part];
54463
+ }
54464
+ else {
54465
+ return undefined;
54466
+ }
54467
+ }
54468
+ return current;
54469
+ };
54470
+ // For delete operations, use existing data
54471
+ if (ctx.op === 'delete' && existing) {
54472
+ return getNestedProperty(existing, key);
54473
+ }
54474
+ // For create/update operations, use data
54475
+ if (ctx.data) {
54476
+ const dataValue = getNestedProperty(ctx.data, key);
54477
+ if (dataValue !== undefined) {
54478
+ return dataValue;
54479
+ }
54480
+ }
54481
+ // Fallback to existing for update operations
54482
+ if (existing) {
54483
+ return getNestedProperty(existing, key);
54484
+ }
54485
+ return undefined;
54486
+ }
54487
+ }
54488
+ };
54489
+ };
54490
+ // Helper: evaluate active rules for a given scope
54491
+ const evaluateActiveRules = async (scope) => {
54492
+ const list = [];
54493
+ for (const pol of applicable) {
54494
+ for (const rule of pol.rules ?? []) {
54495
+ const active = await isRuleActive(rule.conditions, evaluator, scope);
54496
+ if (active) {
54497
+ for (const eff of rule.effects ?? []) {
54498
+ list.push(eff);
54499
+ }
54500
+ }
54501
+ }
54502
+ }
54503
+ return list;
54504
+ };
54505
+ // Resolve effects per operation following simple standard semantics
54506
+ const deriveTargets = (rules) => ({
54507
+ readonlyTargets: collectTargets(rules, 'readonly'),
54508
+ immutableTargets: collectTargets(rules, 'immutable'),
54509
+ hiddenTargets: collectTargets(rules, 'hidden'),
54510
+ maskedTargets: collectTargets(rules, 'masked'),
54511
+ editableTargets: collectTargets(rules, 'editable'),
54512
+ });
54513
+ let activeRules = [];
54514
+ let readonlyTargets = [];
54515
+ let immutableTargets = [];
54516
+ let hiddenTargets = [];
54517
+ let maskedTargets = [];
54518
+ let editableTargets = [];
54519
+ // Conflict resolution (standard): editable overrides readonly (not immutable), hidden beats everything in output, immutable strongest on write
54520
+ const isEditable = (t) => editableTargets.includes(t) || editableTargets.includes('*');
54521
+ // WRITE PATH
54522
+ if (ctx.op === 'create' || ctx.op === 'update') {
54523
+ // For update, load existing to allow conditions to reference current record state
54524
+ let existing;
54525
+ if (ctx.op === 'update' && ctx.id && backend?.getOne) {
54526
+ try {
54527
+ existing = await backend.getOne(ctx.entityName, ctx.id);
54528
+ }
54529
+ catch {
54530
+ existing = undefined;
54531
+ }
54532
+ }
54533
+ // Re-evaluate rules with existing in scope
54534
+ activeRules = await evaluateActiveRules(buildScope({ existing }));
54535
+ ({ readonlyTargets, immutableTargets, hiddenTargets, maskedTargets, editableTargets } = deriveTargets(activeRules));
54536
+ if (ctx.data && typeof ctx.data === 'object') {
54537
+ // Check if entire object is immutable
54538
+ const immutableAll = immutableTargets.includes('*');
54539
+ if (immutableAll) {
54540
+ throw new AXPMiddlewareAbortError('Update forbidden by policy: Record is marked as system and cannot be modified', {
54541
+ status: 409,
54542
+ code: 'POLICY_IMMUTABLE_RECORD',
54543
+ details: { entity: ctx.entityName, id: ctx.id },
54544
+ });
54545
+ }
54546
+ // For specific immutable/readonly fields, remove them from payload
54547
+ const forbiddenPaths = [];
54548
+ const addForbiddenFromTargets = (targets) => {
54549
+ for (const t of targets) {
54550
+ if (t === '*') {
54551
+ // This case is handled above
54552
+ continue;
54553
+ }
54554
+ else if (!isEditable(t)) {
54555
+ forbiddenPaths.push(t);
54556
+ }
54557
+ }
54558
+ };
54559
+ // readonly and immutable (excluding '*')
54560
+ addForbiddenFromTargets(readonlyTargets);
54561
+ addForbiddenFromTargets(immutableTargets);
54562
+ // Remove forbidden fields from payload
54563
+ const uniqueForbidden = Array.from(new Set(forbiddenPaths));
54564
+ if (uniqueForbidden.length > 0) {
54565
+ removeFields(ctx.data, uniqueForbidden);
54566
+ // Log which fields were removed
54567
+ // try {
54568
+ // console.warn('[policy] fields-removed', {
54569
+ // entity: ctx.entityName,
54570
+ // id: ctx.id,
54571
+ // removedFields: uniqueForbidden
54572
+ // });
54573
+ // } catch {}
54574
+ }
54575
+ }
54576
+ }
54577
+ // DELETE PATH
54578
+ if (ctx.op === 'delete') {
54579
+ // Load existing to evaluate conditions based on record's current state
54580
+ let existing;
54581
+ if (ctx.id && backend?.getOne) {
54582
+ try {
54583
+ existing = await backend.getOne(ctx.entityName, ctx.id);
54584
+ }
54585
+ catch {
54586
+ existing = undefined;
54587
+ }
54588
+ }
54589
+ activeRules = await evaluateActiveRules(buildScope({ existing }));
54590
+ ({ readonlyTargets, immutableTargets, hiddenTargets, maskedTargets, editableTargets } = deriveTargets(activeRules));
54591
+ // If immutable '*' exists, block delete by short-circuiting
54592
+ const immutableAll = immutableTargets.includes('*');
54593
+ // Temporary debug logs for troubleshooting policy delete enforcement
54594
+ try {
54595
+ // eslint-disable-next-line no-console
54596
+ console.warn('[policy] delete-check', {
54597
+ entity: ctx.entityName,
54598
+ id: ctx.id,
54599
+ existingIsSystem: existing?.control?.isSystem,
54600
+ immutableTargets,
54601
+ readonlyTargets,
54602
+ editableTargets,
54603
+ immutableAll,
54604
+ });
54605
+ }
54606
+ catch { }
54607
+ if (immutableAll) {
54608
+ // Block delete and throw error to notify frontend
54609
+ try {
54610
+ console.warn('[policy] delete-blocked', { entity: ctx.entityName, id: ctx.id });
54611
+ }
54612
+ catch { }
54613
+ throw new AXPMiddlewareAbortError('Delete forbidden by policy: Record is marked as system and cannot be deleted', {
54614
+ status: 409,
54615
+ code: 'POLICY_IMMUTABLE_RECORD',
54616
+ details: { entity: ctx.entityName, id: ctx.id },
54617
+ });
54618
+ }
54619
+ }
54620
+ await next();
54621
+ // try { console.warn('[policy] after-next', ctx.op, ctx.entityName); } catch {}
54622
+ // READ PATH (after next to transform response)
54623
+ if (ctx.op === 'getOne' || ctx.op === 'getAll' || ctx.op === 'query') {
54624
+ // Re-evaluate rules with result in scope (read conditions can depend on returned data)
54625
+ activeRules = await evaluateActiveRules(buildScope({ result: ctx.result }));
54626
+ ({ readonlyTargets, immutableTargets, hiddenTargets, maskedTargets, editableTargets } = deriveTargets(activeRules));
54627
+ const applyReadTransforms = (obj) => {
54628
+ if (!obj || typeof obj !== 'object')
54629
+ return;
54630
+ // hidden ⇒ remove field
54631
+ removeFields(obj, hiddenTargets);
54632
+ // masked ⇒ mask value
54633
+ setMasked(obj, maskedTargets);
54634
+ };
54635
+ if (Array.isArray(ctx.result)) {
54636
+ ctx.result.forEach(applyReadTransforms);
54637
+ }
54638
+ else {
54639
+ applyReadTransforms(ctx.result);
54640
+ }
54641
+ }
54642
+ },
54643
+ };
54644
+
53980
54645
  class AXCMiddlewaresModule {
53981
54646
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXCMiddlewaresModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
53982
54647
  static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "21.2.9", ngImport: i0, type: AXCMiddlewaresModule, imports: [AXCEntityStorageModule, AXCEntityDefinitionsModule] }); }
@@ -53984,7 +54649,7 @@ class AXCMiddlewaresModule {
53984
54649
  // Middlewares (ordered by execution priority)
53985
54650
  { provide: AXP_ENTITY_STORAGE_MIDDLEWARE, multi: true, useValue: statusDefaultMiddleware }, // order: 3 - backend: default status, security-sensitive defaults
53986
54651
  { provide: AXP_ENTITY_STORAGE_MIDDLEWARE, multi: true, useValue: entityValidationMiddleware }, // order: 5 - entity pre-save validation
53987
- // { provide: AXP_ENTITY_STORAGE_MIDDLEWARE, multi: true, useValue: policyEnforceMiddleware }, // order: 5 - Handles both isSystem and isImmutable
54652
+ { provide: AXP_ENTITY_STORAGE_MIDDLEWARE, multi: true, useValue: policyEnforceMiddleware }, // order: 5 - Handles both isSystem and isImmutable
53988
54653
  { provide: AXP_ENTITY_STORAGE_MIDDLEWARE, multi: true, useValue: lockGuardMiddleware }, // order: 10
53989
54654
  { provide: AXP_ENTITY_STORAGE_MIDDLEWARE, multi: true, useValue: historyMiddleware }, // order: 15 - audit + versioning
53990
54655
  { provide: AXP_ENTITY_STORAGE_MIDDLEWARE, multi: true, useValue: eventDispatchMiddleware },
@@ -54011,7 +54676,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
54011
54676
  // Middlewares (ordered by execution priority)
54012
54677
  { provide: AXP_ENTITY_STORAGE_MIDDLEWARE, multi: true, useValue: statusDefaultMiddleware }, // order: 3 - backend: default status, security-sensitive defaults
54013
54678
  { provide: AXP_ENTITY_STORAGE_MIDDLEWARE, multi: true, useValue: entityValidationMiddleware }, // order: 5 - entity pre-save validation
54014
- // { provide: AXP_ENTITY_STORAGE_MIDDLEWARE, multi: true, useValue: policyEnforceMiddleware }, // order: 5 - Handles both isSystem and isImmutable
54679
+ { provide: AXP_ENTITY_STORAGE_MIDDLEWARE, multi: true, useValue: policyEnforceMiddleware }, // order: 5 - Handles both isSystem and isImmutable
54015
54680
  { provide: AXP_ENTITY_STORAGE_MIDDLEWARE, multi: true, useValue: lockGuardMiddleware }, // order: 10
54016
54681
  { provide: AXP_ENTITY_STORAGE_MIDDLEWARE, multi: true, useValue: historyMiddleware }, // order: 15 - audit + versioning
54017
54682
  { provide: AXP_ENTITY_STORAGE_MIDDLEWARE, multi: true, useValue: eventDispatchMiddleware },
@@ -55525,6 +56190,9 @@ function composeOrgChartTreeForMode(workspace, mode, showVacantLeafSeats) {
55525
56190
  if (!pos) {
55526
56191
  continue;
55527
56192
  }
56193
+ const seatCapacity = typeof pos?.capacity === 'number' && Number.isFinite(pos.capacity) && pos.capacity >= 1
56194
+ ? Math.floor(pos.capacity)
56195
+ : 1;
55528
56196
  const list = byPosition.get(positionId) ?? [];
55529
56197
  const distinctAssignees = axcDistinctAssignmentsByEmployee(axcOrderAssignmentsForRepresentative(list));
55530
56198
  const hasAnyIncumbent = distinctAssignees.length > 0;
@@ -55552,6 +56220,8 @@ function composeOrgChartTreeForMode(workspace, mode, showVacantLeafSeats) {
55552
56220
  chartTemplate: 'position-ic',
55553
56221
  vacant: true,
55554
56222
  businessUnitId: String(bu.id),
56223
+ capacity: seatCapacity,
56224
+ activeAssignmentCount: 0,
55555
56225
  stats: { directReports: directReportsCount },
55556
56226
  },
55557
56227
  isExpanded: true,
@@ -55574,6 +56244,8 @@ function composeOrgChartTreeForMode(workspace, mode, showVacantLeafSeats) {
55574
56244
  const positionMetadata = {
55575
56245
  chartTemplate: 'merged-manager',
55576
56246
  businessUnitId: String(bu.id),
56247
+ capacity: seatCapacity,
56248
+ activeAssignmentCount: distinctAssignees.length,
55577
56249
  occupant: employeeName
55578
56250
  ? {
55579
56251
  displayName: employeeName,
@@ -62010,7 +62682,7 @@ class AXCSecurityManagementMockModule {
62010
62682
  provideQuerySetups([
62011
62683
  {
62012
62684
  key: 'SecurityManagement:User:RolesForListColumn',
62013
- loader: () => import('./acorex-connectivity-mock-user-roles-for-list-column.query-DBhWkX3w.mjs').then((m) => m.UserRolesForListColumnQuery),
62685
+ loader: () => import('./acorex-connectivity-mock-user-roles-for-list-column.query-DyGLxPvP.mjs').then((m) => m.UserRolesForListColumnQuery),
62014
62686
  },
62015
62687
  ]),
62016
62688
  ] }); }
@@ -62054,7 +62726,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
62054
62726
  provideQuerySetups([
62055
62727
  {
62056
62728
  key: 'SecurityManagement:User:RolesForListColumn',
62057
- loader: () => import('./acorex-connectivity-mock-user-roles-for-list-column.query-DBhWkX3w.mjs').then((m) => m.UserRolesForListColumnQuery),
62729
+ loader: () => import('./acorex-connectivity-mock-user-roles-for-list-column.query-DyGLxPvP.mjs').then((m) => m.UserRolesForListColumnQuery),
62058
62730
  },
62059
62731
  ]),
62060
62732
  ],
@@ -71779,7 +72451,7 @@ class AXCWorkflowManagementMockModule {
71779
72451
  provideCommandSetups([
71780
72452
  {
71781
72453
  key: 'workflow-activity:assign-to-manager',
71782
- command: () => import('./acorex-connectivity-mock-assign-to-manager.activity-BgaXGmcT.mjs').then((c) => c.AssignToManagerActivity),
72454
+ command: () => import('./acorex-connectivity-mock-assign-to-manager.activity-B4WcK-sl.mjs').then((c) => c.AssignToManagerActivity),
71783
72455
  },
71784
72456
  {
71785
72457
  key: 'workflow-activity:get-current-user-manager',
@@ -71890,7 +72562,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
71890
72562
  provideCommandSetups([
71891
72563
  {
71892
72564
  key: 'workflow-activity:assign-to-manager',
71893
- command: () => import('./acorex-connectivity-mock-assign-to-manager.activity-BgaXGmcT.mjs').then((c) => c.AssignToManagerActivity),
72565
+ command: () => import('./acorex-connectivity-mock-assign-to-manager.activity-B4WcK-sl.mjs').then((c) => c.AssignToManagerActivity),
71894
72566
  },
71895
72567
  {
71896
72568
  key: 'workflow-activity:get-current-user-manager',
@@ -76344,4 +77016,4 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
76344
77016
  */
76345
77017
 
76346
77018
  export { AXCFinancialCoreMockModule as $, AXCAiChatRouterService as A, AXCCalendarDataSeeder as B, AXCCalendarEventDataSeeder as C, AXCCalendarManagementMockModule as D, AXCCommandRegistryDataSeeder as E, AXCCommonMockModule as F, AXCContactCoreMockModule as G, AXCContentManagementMockModule as H, AXCConversationDataSeeder as I, AXCConversationMockConversationApi as J, AXCConversationMockMessageApi as K, AXCConversationMockModule as L, AXCConversationMockRealtimeApi as M, AXCConversationMockUserApi as N, AXCCustomerManagementMockModule as O, AXCDashboardManagementMockModule as P, AXCDataManagementMockModule as Q, AXCDexieEntityStorageService as R, AXCDocumentManagementMockModule as S, AXCEditionDataSeeder as T, AXCEntityDefinitionSeederService as U, AXCEntityDefinitionsModule as V, AXCEntityStorageInsertCommand as W, AXCEntityStorageModule as X, AXCEntityStorageQueryQuery as Y, AXCFileStorageServiceDexie as Z, AXCFileStorageServiceFirestore as _, AXMAiModelStableIds as a, AXMEmploymentTypeDataSeeder as a$, AXCFirestoreEntityStorageService as a0, AXCFormTemplateManagementMockModule as a1, AXCGoogleStrategyMock as a2, AXCHealthCoreMockModule as a3, AXCHelpDeskMockModule as a4, AXCHumanCapitalManagementMockModule as a5, AXCIdentifierManagementMockModule as a6, AXCImageCaptchaChallengeProviderMock as a7, AXCLearningManagementMockModule as a8, AXCLocaleManagementMockModule as a9, AXCTenantManagementMockModule as aA, AXCTenantSeeder as aB, AXCTextTemplateRenderBackend as aC, AXCTokensDataSeeder as aD, AXCUserPassStrategyMock as aE, AXCVersionDB as aF, AXCVersioningService as aG, AXCWidgetCatalogDataSeeder as aH, AXCWorkflowCategorySeeder as aI, AXCWorkflowDefinitionDataSeeder as aJ, AXCWorkflowEngine as aK, AXCWorkflowExecutionDB as aL, AXCWorkflowExecutionStoreDexie as aM, AXCWorkflowExecutionStoreFirestore as aN, AXCWorkflowInstanceCartableDemoSeeder as aO, AXCWorkflowManagementMockModule as aP, AXC_ENTITY_STORAGE_BACKEND_TYPE as aQ, AXC_FIRESTORE_CONFIG as aR, AXC_FIRESTORE_DB as aS, AXC_WORKFLOW_EXECUTION_STORE as aT, AXMAiDemisAssistantAssistId as aU, AXMAiPlatformAssistantAssistId as aV, AXMAutomationDataSeeder as aW, AXMBusinessUnitDataSeeder as aX, AXMCalendarEventTypeSeeder as aY, AXMDashboardChartDataSourceDefinition as aZ, AXMEmployeeDataSeeder as a_, AXCLocationManagementMockModule as aa, AXCLockService as ab, AXCMeasurementCoreMockModule as ac, AXCMeetingManagementMockModule as ad, AXCMetaDataDefinitionDataSeeder as ae, AXCMetadataCategorySeeder as af, AXCMiddlewaresModule as ag, AXCMockCaptchaChallengeComponent as ah, AXCMockEntityLogListener as ai, AXCMockModule as aj, AXCMockShowMetaDataFormPopupCommand as ak, AXCNotificationManagementMockModule as al, AXCOrderManagementMockModule as am, AXCOrganizationManagementMockModule as an, AXCPersonCoreMockModule as ao, AXCPlatformManagementMockModule as ap, AXCProcurementManagementMockModule as aq, AXCProductCatalogMockModule as ar, AXCProjectManagementMockModule as as, AXCQueryRegistryDataSeeder as at, AXCReportManagementMockModule as au, AXCSecurityManagementMockModule as av, AXCStoredEntityDefinitionLoader as aw, AXCSubscriptionManagementMockModule as ax, AXCSupplierManagementMockModule as ay, AXCTaskManagementMockModule as az, resolveDelegatedAssistOptionString as b, HW as b$, AXMFormDataSourcesProvider as b0, AXMJobDefinitionDataSeeder as b1, AXMJobLevelDataSeeder as b2, AXMLeaveRequestDataSeeder as b3, AXMMeetingDataSeeder as b4, AXMMeetingFilesDataSeeder as b5, AXMMeetingParticipantDataSeeder as b6, AXMMeetingRoleTypeDataSeeder as b7, AXMMeetingSessionDataSeeder as b8, AXMMeetingTypeDataSeeder as b9, AXPMockSequenceProvider as bA, AXPRoomDataSeeder as bB, AXPSecurityManagementRoleDataSeeder as bC, AXPSecurityManagementUserDataSeeder as bD, AXPTaskBoardPlatformManagementTaskProvider as bE, AXPTaskBoardProjectManagementTaskProvider as bF, AXVChangeType as bG, BCC as bH, BOC as bI, BUSINESS_UNITS_MOCK as bJ, CHAT_LAST_MESSAGE_IDS as bK, COSTMANAGER_ENTERPRISE as bL, COSTMANAGER_PROFESSIONAL as bM, COSTMANAGER_STANDARD as bN, CP as bO, CRM_ENTERPRISE as bP, DASHBOARDS as bQ, EDITIONS as bR, EMPLOYEES_MOCK as bS, EMPLOYMENT_TYPES_MOCK as bT, ENTITY_DEFINITION_MAP as bU, ENTITY_REGISTRY as bV, FINANCE_BASIC as bW, FINANCE_ENTERPRISE as bX, FINANCE_PRO as bY, G as bZ, HR_ENTERPRISE as b_, AXMMeetingTypeFileTemplateDataSeeder as ba, AXMPositionAssignmentDataSeeder as bb, AXMPositionDataSeeder as bc, AXMQuestionBankItemCategoryDataSeeder as bd, AXMQuestionBankItemDataSeeder as be, AXMQuestionnaireCalculationDataSeeder as bf, AXMQuestionnaireCategoryDataSeeder as bg, AXMQuestionnaireDataSeeder as bh, AXMResponsibilityDataSeeder as bi, AXMTagDataSeeder as bj, AXMTeamBusinessUnitDataSeeder as bk, AXMTeamDataSeeder as bl, AXMTeamMemberDataSeeder as bm, AXMTeamMemberRoleDataSeeder as bn, AXMWorkflowDashboardChartDataSourceDefinition as bo, AXM_AI_REGISTRY_COMMAND_NAME as bp, AXM_AI_REGISTRY_QUERY_NAME as bq, AXM_CORPORATE_BUSINESS_UNIT_ID as br, AXPDashboardDataSeeder as bs, AXPIdentifierDB as bt, AXPMessageDataSeeder as bu, AXPMockChecksumProvider as bv, AXPMockClockProvider as bw, AXPMockIdentifierService as bx, AXPMockLookupProvider as by, AXPMockPolicyProvider as bz, axcSyncSingleEmployeeDenormalizedOrgFields as c, awaitConversationMockSharedStorage as c$, JOB_DEFINITIONS_CATEGORY_MOCK as c0, JOB_DEFINITIONS_MOCK as c1, JOB_DEFINITION_CATEGORY_KEY_TO_ID as c2, JOB_LEVELS_MOCK as c3, LASER_PLUMBING_TENANT_ID as c4, LEAVE_REQUESTS_MOCK as c5, METADATA_CATEGORY_IDS as c6, METADATA_GENERAL_CATEGORY_REFS as c7, METADATA_SYSTEM_CATEGORY_REFS as c8, MLC as c9, SHOP_BASIC as cA, SHOP_ENTERPRISE as cB, SHOP_PRO as cC, TAGS_MOCK as cD, TASKS as cE, TASK_STATUSES as cF, TASK_TEMPLATES as cG, TASK_TYPES as cH, TEAMS_CATEGORY_MOCK as cI, TEAMS_MOCK as cJ, TEAM_BUSINESS_UNITS_MOCK as cK, TEAM_CATEGORY_KEY_TO_ID as cL, TEAM_MEMBERS_MOCK as cM, TEAM_MEMBER_ROLES_MOCK as cN, TIMEPLICITY_TENANT_ID as cO, TLA as cP, TOKENS as cQ, TPC as cR, VISIBILITY_FILTER_BYPASS as cS, WORKFLOW_CATEGORIES as cT, WS as cU, activityCategoryMocks as cV, activityDefinitionEntityMock as cW, applyEntityDefinitionFirestoreSnapshot as cX, automationCommandMiddleware as cY, automationMock as cZ, avatarInterface as c_, OHR as ca, ORDERING_BASIC as cb, ORDERING_ENTERPRISE as cc, ORDERING_STANDARD as cd, OWNERSHIP_FILTER_BYPASS as ce, PLATFORM_CONSOLE as cf, PLATFORM_TENANT_ID as cg, PM as ch, POSITIONS_CATEGORY_MOCK as ci, POSITIONS_MOCK as cj, POSITION_ASSIGNMENTS_MOCK as ck, QCP as cl, QGEN as cm, QHW as cn, QOHR as co, QPM as cp, QTLE as cq, QUESTIONNAIRE_CATEGORY_MOCK as cr, QUESTION_BANK_ITEM_CATEGORY_MOCK as cs, QWS as ct, RESPONSIBILITIES_CATEGORY_MOCK as cu, RESPONSIBILITIES_MOCK as cv, RESPONSIBILITY_CATEGORY_KEY_TO_ID as cw, SAFETYMINDER_BASIC as cx, SAFETYMINDER_ENTERPRISE as cy, SAFETYMINDER_PROFESSIONAL as cz, ACTIVITY_CATEGORIES as d, mockParticipantIndexForSecurityUserId as d$, axVersionDB as d0, axWorkflowExecutionDB as d1, axcPatchEmployeeActivePrimaryBusinessUnitRefsFromRows as d2, axcPatchEmployeeActivePrimaryPositionRefsFromRows as d3, axcPatchEmployeeManagerRefsFromRows as d4, axcResolveCommandRegistrySeedId as d5, axcResolveQueryRegistrySeedId as d6, axcResolveWidgetCatalogSeedId as d7, bankCategory as d8, buildEntityStorageQuickSearchFilter as d9, fileUploaderInterface as dA, finalizeActivityCategoryItemCounts as dB, findEmployeeById as dC, folderStorageMiddleware as dD, groupOrderItemCalculatorMiddleware as dE, historyMiddleware as dF, identifierCommitMiddleware as dG, imageInterface as dH, inspectionOkXNaInterface as dI, loadMockPropertyDefinitions as dJ, lockGuardMiddleware as dK, longTextAnswerInterface as dL, lookupInterface as dM, lookupResolverMiddleware as dN, mapInterface as dO, meetingFilesMock as dP, meetingIds as dQ, meetingMock as dR, meetingParticipantMock as dS, meetingRoleTypeMock as dT, meetingSessionMock as dU, meetingTimeSlotMock as dV, meetingTypeFileTemplateMock as dW, meetingTypeMock as dX, mergeDetailRelationMiddleware as dY, mergeQuickSearchIntoRequest as dZ, metadataCategoryMocks as d_, buildWorkflowInstanceCartableDemoRows as da, bypassAllFilters as db, bypassOwnershipFilter as dc, bypassVisibilityFilter as dd, calendarEventMock as de, calendarEventTypeMockData as df, calendarMock as dg, chatMessageMock as dh, chatMock as di, checkboxInterface as dj, childCountMiddleware as dk, clearEntityDefinitionFirestoreCollections as dl, colorInterface as dm, computeDiff as dn, contactInterface as dp, conversationDemoSeedUserIds as dq, createFileCastMiddleware as dr, createWidgetLayoutConfig as ds, dateInterface as dt, dateTimeInterface as du, descriptionInterface as dv, documentFolderSyncMiddleware as dw, emailInterface as dx, entityDefDb as dy, entityValidationMiddleware as dz, ACTIVITY_CATEGORY_ID_BY_KEY as e, mockQuestionBankItemByName as e0, mockRoleDefinitions as e1, multipleChoiceInterface as e2, multipleSelectInterface as e3, normalizeAnyFileArrayForView as e4, normalizeSnapshotFileFieldsForView as e5, numberInterface as e6, parseEntityStorageInsertData as e7, parseEntityStorageQueryRequest as e8, participantIds as e9, textInterface as eA, timeDurationInterface as eB, titleInterface as eC, toUiRows as eD, toggleInterface as eE, tokenCategoryIds as eF, tokenCategoryMocks as eG, urlInterface as eH, versionInterface as eI, visibilityFilterMiddleware as eJ, workflowDefinitionEntityMock as eK, workflowDefinitionIds as eL, workflowDefinitionMock as eM, yesNoInterface as eN, participantMock as ea, passwordInterface as eb, personIdentifierTypeMock as ec, personIds as ed, personLegalIds as ee, personMock as ef, personNaturalIds as eg, phoneInterface as eh, primaryMiddleware as ei, provideMockPropertySetups as ej, qrcodeInterface as ek, questionBankItemMock as el, questionnaireCalculationMock as em, questionnaireMock as en, ratingInterface as eo, richTextInterface as ep, scaleInterface as eq, selectInterface as er, selectionListInterface as es, sexAtBirthInterface as et, signatureInterface as eu, signatureLoaderMiddleware as ev, statusDefaultMiddleware as ew, tagInterface as ex, tenantMocks as ey, textAreaInterface as ez, ACTIVITY_DEFINITIONS as f, AI_ASSIST_MOCK as g, AI_MODEL_MOCK as h, APPLICATIONS as i, APPLICATION_CATEGORY_IDS as j, APPLICATION_CATEGORY_MOCKS as k, AXCActivityCategorySeeder as l, mockUsers as m, AXCActivityDefinitionSeeder as n, AXCAiAssistSeeder as o, AXCAiManagementMockModule as p, AXCAiModelSeeder as q, resolveDelegatedAssistOptionModel as r, AXCAppTermDataSeeder as s, AXCAppVersionDataSeeder as t, AXCApplicationCategoryDataSeeder as u, AXCApplicationDataSeeder as v, AXCApplicationManagementMockModule as w, AXCAssessmentManagementMockModule as x, AXCAssetManagementMockModule as y, AXCAuthMockModule as z };
76347
- //# sourceMappingURL=acorex-connectivity-mock-acorex-connectivity-mock-BwFZQ1Xw.mjs.map
77019
+ //# sourceMappingURL=acorex-connectivity-mock-acorex-connectivity-mock-DGbHYfeu.mjs.map