@stndrds/schema 0.1.0-alpha.36 → 0.1.0-alpha.37
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{chunk-QZZ4SSHD.mjs → chunk-OXPVVEZS.mjs} +210 -57
- package/dist/{chunk-JHLPK3RO.js → chunk-TL7PFCPC.js} +277 -124
- package/dist/index.d.mts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +12 -6
- package/dist/index.mjs +7 -1
- package/dist/{runtime-BWBRGKY1.d.mts → runtime-Hwgvv9Bn.d.mts} +243 -32
- package/dist/{runtime-BWBRGKY1.d.ts → runtime-Hwgvv9Bn.d.ts} +243 -32
- package/dist/runtime.d.mts +1 -1
- package/dist/runtime.d.ts +1 -1
- package/dist/runtime.js +8 -2
- package/dist/runtime.mjs +7 -1
- package/package.json +2 -2
|
@@ -2,6 +2,93 @@
|
|
|
2
2
|
|
|
3
3
|
var _chunk3RG5ZIWIjs = require('./chunk-3RG5ZIWI.js');
|
|
4
4
|
|
|
5
|
+
// src/runtime/cache.ts
|
|
6
|
+
var cacheKeys = {
|
|
7
|
+
// -------------------------------------------------------------------------
|
|
8
|
+
// Schemas - TTL: 1 hour (rarely change)
|
|
9
|
+
// -------------------------------------------------------------------------
|
|
10
|
+
/** Object schema by ID */
|
|
11
|
+
objectSchema: (tenantId, objectId) => `schema:${tenantId}:obj:${objectId}`,
|
|
12
|
+
/** Object schema by name */
|
|
13
|
+
objectSchemaByName: (tenantId, name) => `schema:${tenantId}:name:${name}`,
|
|
14
|
+
/** List of all object schemas */
|
|
15
|
+
objectSchemaList: (tenantId) => `schema:${tenantId}:list`,
|
|
16
|
+
// -------------------------------------------------------------------------
|
|
17
|
+
// Attributes - TTL: 1 hour (rarely change)
|
|
18
|
+
// -------------------------------------------------------------------------
|
|
19
|
+
/** Attributes for an object */
|
|
20
|
+
objectAttributes: (tenantId, objectId) => `attrs:${tenantId}:${objectId}`,
|
|
21
|
+
// -------------------------------------------------------------------------
|
|
22
|
+
// Permissions - TTL: 15 minutes (medium volatility)
|
|
23
|
+
// -------------------------------------------------------------------------
|
|
24
|
+
/** Effective permissions for a user */
|
|
25
|
+
userPermissions: (tenantId, userId) => `perms:${tenantId}:user:${userId}`,
|
|
26
|
+
// -------------------------------------------------------------------------
|
|
27
|
+
// Relations - TTL: 5 minutes (medium volatility)
|
|
28
|
+
// -------------------------------------------------------------------------
|
|
29
|
+
/** Relation options for an attribute */
|
|
30
|
+
relationOptions: (tenantId, attrId, hash) => `rel:${tenantId}:${attrId}:${hash}`,
|
|
31
|
+
// -------------------------------------------------------------------------
|
|
32
|
+
// Rollups - TTL: 2 minutes (high volatility)
|
|
33
|
+
// -------------------------------------------------------------------------
|
|
34
|
+
/** Computed rollup value for a record */
|
|
35
|
+
rollupValue: (tenantId, recordId, attrName) => `rollup:${tenantId}:${recordId}:${attrName}`,
|
|
36
|
+
// -------------------------------------------------------------------------
|
|
37
|
+
// Invalidation Patterns
|
|
38
|
+
// -------------------------------------------------------------------------
|
|
39
|
+
/** All schema cache for a tenant */
|
|
40
|
+
allSchemas: (tenantId) => `schema:${tenantId}:*`,
|
|
41
|
+
/** All attribute cache for a tenant */
|
|
42
|
+
allAttributes: (tenantId) => `attrs:${tenantId}:*`,
|
|
43
|
+
/** All permission cache for a tenant */
|
|
44
|
+
allPermissions: (tenantId) => `perms:${tenantId}:*`,
|
|
45
|
+
/** All relation cache for a tenant */
|
|
46
|
+
allRelations: (tenantId) => `rel:${tenantId}:*`,
|
|
47
|
+
/** All rollup cache for a tenant */
|
|
48
|
+
allRollups: (tenantId) => `rollup:${tenantId}:*`,
|
|
49
|
+
/** All rollups for a specific record */
|
|
50
|
+
rollupsByRecord: (tenantId, recordId) => `rollup:${tenantId}:${recordId}:*`,
|
|
51
|
+
/** All cache for a tenant (nuclear option) */
|
|
52
|
+
allForTenant: (tenantId) => `*:${tenantId}:*`
|
|
53
|
+
};
|
|
54
|
+
var cacheTtl = {
|
|
55
|
+
/** Object schemas - rarely change (1 hour) */
|
|
56
|
+
schema: 60 * 60 * 1e3,
|
|
57
|
+
/** Schema list - new objects more frequent (5 minutes) */
|
|
58
|
+
schemaList: 5 * 60 * 1e3,
|
|
59
|
+
/** Object attributes - rarely change (1 hour) */
|
|
60
|
+
attributes: 60 * 60 * 1e3,
|
|
61
|
+
/** User permissions - medium volatility (15 minutes) */
|
|
62
|
+
permissions: 15 * 60 * 1e3,
|
|
63
|
+
/** Relation options - medium volatility (5 minutes) */
|
|
64
|
+
relations: 5 * 60 * 1e3,
|
|
65
|
+
/** Rollup values - high volatility (2 minutes) */
|
|
66
|
+
rollup: 2 * 60 * 1e3
|
|
67
|
+
};
|
|
68
|
+
var NoopCacheAdapter = class {
|
|
69
|
+
get() {
|
|
70
|
+
return Promise.resolve(null);
|
|
71
|
+
}
|
|
72
|
+
set() {
|
|
73
|
+
return Promise.resolve();
|
|
74
|
+
}
|
|
75
|
+
delete() {
|
|
76
|
+
return Promise.resolve();
|
|
77
|
+
}
|
|
78
|
+
deletePattern() {
|
|
79
|
+
return Promise.resolve();
|
|
80
|
+
}
|
|
81
|
+
has() {
|
|
82
|
+
return Promise.resolve(false);
|
|
83
|
+
}
|
|
84
|
+
clear() {
|
|
85
|
+
return Promise.resolve();
|
|
86
|
+
}
|
|
87
|
+
getOrSet(_key, fetcher) {
|
|
88
|
+
return fetcher();
|
|
89
|
+
}
|
|
90
|
+
};
|
|
91
|
+
|
|
5
92
|
// src/runtime/client/types.ts
|
|
6
93
|
function formatRecord(record) {
|
|
7
94
|
return {
|
|
@@ -6284,6 +6371,7 @@ var ObjectSchemaService = class extends TenantAwareService {
|
|
|
6284
6371
|
this.adapter = adapter;
|
|
6285
6372
|
this.nativeRegistry = nativeRegistry;
|
|
6286
6373
|
this.auditService = _optionalChain([options, 'optionalAccess', _147 => _147.auditService]);
|
|
6374
|
+
this.cache = _nullishCoalesce(_optionalChain([options, 'optionalAccess', _148 => _148.cache]), () => ( adapter.cache));
|
|
6287
6375
|
}
|
|
6288
6376
|
/**
|
|
6289
6377
|
* Create a new custom object.
|
|
@@ -6359,6 +6447,7 @@ var ObjectSchemaService = class extends TenantAwareService {
|
|
|
6359
6447
|
attributes: createdAttributes,
|
|
6360
6448
|
system: false
|
|
6361
6449
|
};
|
|
6450
|
+
await this.invalidateSchemaCache();
|
|
6362
6451
|
if (this.auditService && this.userId) {
|
|
6363
6452
|
await this.auditService.logSchemaAction({
|
|
6364
6453
|
action: "object.created",
|
|
@@ -6406,6 +6495,7 @@ var ObjectSchemaService = class extends TenantAwareService {
|
|
|
6406
6495
|
// Always false for attributes added via API
|
|
6407
6496
|
config
|
|
6408
6497
|
});
|
|
6498
|
+
await this.invalidateSchemaCache();
|
|
6409
6499
|
if (this.auditService && this.userId) {
|
|
6410
6500
|
await this.auditService.logSchemaAction({
|
|
6411
6501
|
action: "attribute.created",
|
|
@@ -6479,12 +6569,13 @@ var ObjectSchemaService = class extends TenantAwareService {
|
|
|
6479
6569
|
resourceType: "attribute",
|
|
6480
6570
|
resourceId: attributeId,
|
|
6481
6571
|
resourceLabel: updatedDbAttr.label,
|
|
6482
|
-
objectName: _optionalChain([dbObject, 'optionalAccess',
|
|
6572
|
+
objectName: _optionalChain([dbObject, 'optionalAccess', _149 => _149.name]),
|
|
6483
6573
|
objectId: dbAttr.objectId,
|
|
6484
6574
|
changes
|
|
6485
6575
|
});
|
|
6486
6576
|
}
|
|
6487
6577
|
}
|
|
6578
|
+
await this.invalidateSchemaCache();
|
|
6488
6579
|
if (updates.required !== void 0 && updates.required !== oldValues.required) {
|
|
6489
6580
|
const schema = await this.getObjectSchema(dbAttr.objectId);
|
|
6490
6581
|
await this.adapter.objectRecords.batchRefreshStatus(
|
|
@@ -6511,7 +6602,7 @@ var ObjectSchemaService = class extends TenantAwareService {
|
|
|
6511
6602
|
);
|
|
6512
6603
|
}
|
|
6513
6604
|
const dbObject = await this.adapter.objects.findById(dbAttr.objectId);
|
|
6514
|
-
if (_optionalChain([dbObject, 'optionalAccess',
|
|
6605
|
+
if (_optionalChain([dbObject, 'optionalAccess', _150 => _150.labelExpression])) {
|
|
6515
6606
|
const usedAttributes = extractAttributeNames(dbObject.labelExpression);
|
|
6516
6607
|
if (usedAttributes.includes(dbAttr.name)) {
|
|
6517
6608
|
throw new AttributeInUseError(dbAttr.name, "labelExpression");
|
|
@@ -6519,6 +6610,7 @@ var ObjectSchemaService = class extends TenantAwareService {
|
|
|
6519
6610
|
}
|
|
6520
6611
|
await this.adapter.attributes.delete(attributeId);
|
|
6521
6612
|
await this.adapter.objectRecords.removeAttributeData(dbAttr.objectId, dbAttr.name);
|
|
6613
|
+
await this.invalidateSchemaCache();
|
|
6522
6614
|
if (this.auditService && this.userId) {
|
|
6523
6615
|
await this.auditService.logSchemaAction({
|
|
6524
6616
|
action: "attribute.deleted",
|
|
@@ -6526,7 +6618,7 @@ var ObjectSchemaService = class extends TenantAwareService {
|
|
|
6526
6618
|
resourceType: "attribute",
|
|
6527
6619
|
resourceId: attributeId,
|
|
6528
6620
|
resourceLabel: dbAttr.label,
|
|
6529
|
-
objectName: _optionalChain([dbObject, 'optionalAccess',
|
|
6621
|
+
objectName: _optionalChain([dbObject, 'optionalAccess', _151 => _151.name]),
|
|
6530
6622
|
objectId: dbAttr.objectId
|
|
6531
6623
|
});
|
|
6532
6624
|
}
|
|
@@ -6541,9 +6633,9 @@ var ObjectSchemaService = class extends TenantAwareService {
|
|
|
6541
6633
|
async listAttributes(objectId, options) {
|
|
6542
6634
|
const dbAttributes = await this.adapter.attributes.findByObjectId(objectId);
|
|
6543
6635
|
let filtered = dbAttributes;
|
|
6544
|
-
if (_optionalChain([options, 'optionalAccess',
|
|
6636
|
+
if (_optionalChain([options, 'optionalAccess', _152 => _152.systemOnly])) {
|
|
6545
6637
|
filtered = dbAttributes.filter((attr) => attr.system);
|
|
6546
|
-
} else if (_optionalChain([options, 'optionalAccess',
|
|
6638
|
+
} else if (_optionalChain([options, 'optionalAccess', _153 => _153.customOnly])) {
|
|
6547
6639
|
filtered = dbAttributes.filter((attr) => !attr.system);
|
|
6548
6640
|
}
|
|
6549
6641
|
return filtered.map((attr) => this.convertDBAttributeToAttribute(attr));
|
|
@@ -6579,14 +6671,14 @@ var ObjectSchemaService = class extends TenantAwareService {
|
|
|
6579
6671
|
pluralLabel: dbObject.pluralLabel,
|
|
6580
6672
|
description: dbObject.description,
|
|
6581
6673
|
labelExpression: dbObject.labelExpression,
|
|
6582
|
-
icon: _optionalChain([dbObject, 'access',
|
|
6674
|
+
icon: _optionalChain([dbObject, 'access', _154 => _154.metadata, 'optionalAccess', _155 => _155.icon])
|
|
6583
6675
|
};
|
|
6584
6676
|
let metadata = dbObject.metadata;
|
|
6585
6677
|
if (updates.icon !== void 0 || updates.metadata !== void 0) {
|
|
6586
6678
|
metadata = {
|
|
6587
6679
|
...dbObject.metadata,
|
|
6588
6680
|
...updates.metadata,
|
|
6589
|
-
icon: _nullishCoalesce(updates.icon, () => ( _optionalChain([dbObject, 'access',
|
|
6681
|
+
icon: _nullishCoalesce(updates.icon, () => ( _optionalChain([dbObject, 'access', _156 => _156.metadata, 'optionalAccess', _157 => _157.icon])))
|
|
6590
6682
|
};
|
|
6591
6683
|
}
|
|
6592
6684
|
const updatedDbObject = await this.adapter.objects.update(objectId, {
|
|
@@ -6619,6 +6711,7 @@ var ObjectSchemaService = class extends TenantAwareService {
|
|
|
6619
6711
|
}
|
|
6620
6712
|
const dbAttributes = await this.adapter.attributes.findByObjectId(objectId);
|
|
6621
6713
|
const attributes = dbAttributes.map((attr) => this.convertDBAttributeToAttribute(attr));
|
|
6714
|
+
await this.invalidateSchemaCache();
|
|
6622
6715
|
if (updates.labelExpression !== void 0 && updates.labelExpression !== oldValues.labelExpression) {
|
|
6623
6716
|
const newExpression = updates.labelExpression;
|
|
6624
6717
|
await this.adapter.objectRecords.batchRefreshLabels(objectId, (values) => {
|
|
@@ -6656,6 +6749,7 @@ var ObjectSchemaService = class extends TenantAwareService {
|
|
|
6656
6749
|
throw new ObjectReferencedError(dbObject.name, referencingObjects);
|
|
6657
6750
|
}
|
|
6658
6751
|
await this.adapter.objects.delete(objectId);
|
|
6752
|
+
await this.invalidateSchemaCache();
|
|
6659
6753
|
if (this.auditService && this.userId) {
|
|
6660
6754
|
await this.auditService.logSchemaAction({
|
|
6661
6755
|
action: "object.deleted",
|
|
@@ -6699,10 +6793,26 @@ Reserved names: ${RESERVED_ATTRIBUTE_NAMES.join(", ")}`
|
|
|
6699
6793
|
* Get complete object schema (object attributes + system attributes)
|
|
6700
6794
|
* Includes system attributes (createdAt, updatedAt, createdBy, lastUpdatedBy)
|
|
6701
6795
|
*
|
|
6796
|
+
* Results are cached if a CacheAdapter is configured.
|
|
6797
|
+
*
|
|
6702
6798
|
* @param objectId - Object UUID from database
|
|
6703
6799
|
* @returns Complete ObjectDefinition with all attributes including system attributes
|
|
6704
6800
|
*/
|
|
6705
6801
|
async getObjectSchema(objectId) {
|
|
6802
|
+
if (this.cache) {
|
|
6803
|
+
const cacheKey = cacheKeys.objectSchema(this.tenantId, objectId);
|
|
6804
|
+
return this.cache.getOrSet(
|
|
6805
|
+
cacheKey,
|
|
6806
|
+
() => this.fetchObjectSchemaById(objectId),
|
|
6807
|
+
cacheTtl.schema
|
|
6808
|
+
);
|
|
6809
|
+
}
|
|
6810
|
+
return this.fetchObjectSchemaById(objectId);
|
|
6811
|
+
}
|
|
6812
|
+
/**
|
|
6813
|
+
* Internal method to fetch object schema by ID (no caching)
|
|
6814
|
+
*/
|
|
6815
|
+
async fetchObjectSchemaById(objectId) {
|
|
6706
6816
|
const dbObject = await this.adapter.objects.findById(objectId);
|
|
6707
6817
|
if (!dbObject) {
|
|
6708
6818
|
throw new Error(`Object with id "${objectId}" not found`);
|
|
@@ -6723,8 +6833,24 @@ Reserved names: ${RESERVED_ATTRIBUTE_NAMES.join(", ")}`
|
|
|
6723
6833
|
/**
|
|
6724
6834
|
* Get object schema by name (supports both native and custom objects).
|
|
6725
6835
|
* Automatically uses tenant context from AsyncLocalStorage.
|
|
6836
|
+
*
|
|
6837
|
+
* Results are cached if a CacheAdapter is configured.
|
|
6726
6838
|
*/
|
|
6727
6839
|
async getObjectSchemaByNameForTenant(name) {
|
|
6840
|
+
if (this.cache) {
|
|
6841
|
+
const cacheKey = cacheKeys.objectSchemaByName(this.tenantId, name);
|
|
6842
|
+
return this.cache.getOrSet(
|
|
6843
|
+
cacheKey,
|
|
6844
|
+
() => this.fetchObjectSchemaByName(name),
|
|
6845
|
+
cacheTtl.schema
|
|
6846
|
+
);
|
|
6847
|
+
}
|
|
6848
|
+
return this.fetchObjectSchemaByName(name);
|
|
6849
|
+
}
|
|
6850
|
+
/**
|
|
6851
|
+
* Internal method to fetch object schema by name (no caching)
|
|
6852
|
+
*/
|
|
6853
|
+
async fetchObjectSchemaByName(name) {
|
|
6728
6854
|
let dbObject = await this.adapter.objects.findByName(name);
|
|
6729
6855
|
if (!dbObject) {
|
|
6730
6856
|
dbObject = await this.adapter.objects.findSystemByName(name);
|
|
@@ -6737,11 +6863,32 @@ Reserved names: ${RESERVED_ATTRIBUTE_NAMES.join(", ")}`
|
|
|
6737
6863
|
/**
|
|
6738
6864
|
* List all object schemas.
|
|
6739
6865
|
* Automatically uses tenant context from AsyncLocalStorage.
|
|
6866
|
+
*
|
|
6867
|
+
* Results are cached if a CacheAdapter is configured.
|
|
6740
6868
|
*/
|
|
6741
6869
|
async listObjectSchemas() {
|
|
6870
|
+
if (this.cache) {
|
|
6871
|
+
const cacheKey = cacheKeys.objectSchemaList(this.tenantId);
|
|
6872
|
+
return this.cache.getOrSet(cacheKey, () => this.fetchObjectSchemaList(), cacheTtl.schemaList);
|
|
6873
|
+
}
|
|
6874
|
+
return this.fetchObjectSchemaList();
|
|
6875
|
+
}
|
|
6876
|
+
/**
|
|
6877
|
+
* Internal method to fetch all object schemas (no caching)
|
|
6878
|
+
*/
|
|
6879
|
+
async fetchObjectSchemaList() {
|
|
6742
6880
|
const dbObjects = await this.adapter.objects.list();
|
|
6743
6881
|
return Promise.all(dbObjects.map((dbObject) => this.buildObjectDefinition(dbObject)));
|
|
6744
6882
|
}
|
|
6883
|
+
/**
|
|
6884
|
+
* Invalidate all schema-related cache for the current tenant.
|
|
6885
|
+
* Called automatically after schema mutations.
|
|
6886
|
+
*/
|
|
6887
|
+
async invalidateSchemaCache() {
|
|
6888
|
+
if (!this.cache) return;
|
|
6889
|
+
await this.cache.deletePattern(cacheKeys.allSchemas(this.tenantId));
|
|
6890
|
+
await this.cache.deletePattern(cacheKeys.allAttributes(this.tenantId));
|
|
6891
|
+
}
|
|
6745
6892
|
// ============================================================================
|
|
6746
6893
|
// PRIVATE HELPERS - SCHEMA BUILDING
|
|
6747
6894
|
// ============================================================================
|
|
@@ -6819,7 +6966,7 @@ Reserved names: ${RESERVED_ATTRIBUTE_NAMES.join(", ")}`
|
|
|
6819
6966
|
label: dbObject.label,
|
|
6820
6967
|
pluralLabel: dbObject.pluralLabel,
|
|
6821
6968
|
description: dbObject.description,
|
|
6822
|
-
icon: _optionalChain([dbObject, 'access',
|
|
6969
|
+
icon: _optionalChain([dbObject, 'access', _158 => _158.metadata, 'optionalAccess', _159 => _159.icon]),
|
|
6823
6970
|
labelExpression: dbObject.labelExpression,
|
|
6824
6971
|
attributes,
|
|
6825
6972
|
system: dbObject.system,
|
|
@@ -6919,7 +7066,7 @@ Reserved names: ${RESERVED_ATTRIBUTE_NAMES.join(", ")}`
|
|
|
6919
7066
|
const hasRelationToTarget = attrs.some((attr) => {
|
|
6920
7067
|
if (attr.type !== "relation") return false;
|
|
6921
7068
|
const config = attr.config;
|
|
6922
|
-
return _nullishCoalesce(_optionalChain([config, 'optionalAccess',
|
|
7069
|
+
return _nullishCoalesce(_optionalChain([config, 'optionalAccess', _160 => _160.targets, 'optionalAccess', _161 => _161.some, 'call', _162 => _162((t) => t.object === targetObjectName)]), () => ( false));
|
|
6923
7070
|
});
|
|
6924
7071
|
if (hasRelationToTarget) {
|
|
6925
7072
|
referencing.push(obj.name);
|
|
@@ -6951,17 +7098,13 @@ var PermissionService = class extends TenantAwareService {
|
|
|
6951
7098
|
constructor(adapter, options) {
|
|
6952
7099
|
super();
|
|
6953
7100
|
this.adapter = adapter;
|
|
6954
|
-
this.cache = /* @__PURE__ */ new Map();
|
|
6955
|
-
/** Track pending permission fetches to prevent duplicate concurrent requests */
|
|
6956
|
-
this.pendingFetches = /* @__PURE__ */ new Map();
|
|
6957
7101
|
if (!adapter.permissions) {
|
|
6958
7102
|
throw new Error(
|
|
6959
7103
|
"PermissionService requires a DatabaseAdapter with permissions repository. Make sure your adapter implements the permissions property."
|
|
6960
7104
|
);
|
|
6961
7105
|
}
|
|
6962
7106
|
this.permissionsRepo = adapter.permissions;
|
|
6963
|
-
this.
|
|
6964
|
-
this.maxCacheSize = _nullishCoalesce(_optionalChain([options, 'optionalAccess', _163 => _163.maxCacheSize]), () => ( 1e4));
|
|
7107
|
+
this.cache = _nullishCoalesce(_nullishCoalesce(_optionalChain([options, 'optionalAccess', _163 => _163.cache]), () => ( adapter.cache)), () => ( new NoopCacheAdapter()));
|
|
6965
7108
|
this.auditService = _optionalChain([options, 'optionalAccess', _164 => _164.auditService]);
|
|
6966
7109
|
}
|
|
6967
7110
|
// ============================================================================
|
|
@@ -7089,46 +7232,18 @@ var PermissionService = class extends TenantAwareService {
|
|
|
7089
7232
|
// ============================================================================
|
|
7090
7233
|
/**
|
|
7091
7234
|
* Get effective permissions for a user.
|
|
7092
|
-
* Results are cached with TTL
|
|
7235
|
+
* Results are cached using CacheAdapter with TTL.
|
|
7093
7236
|
*
|
|
7094
7237
|
* @param userProfileId - User profile ID
|
|
7095
7238
|
* @returns Merged permissions from all user's roles
|
|
7096
7239
|
*/
|
|
7097
7240
|
async getEffectivePermissions(userProfileId) {
|
|
7098
|
-
const cacheKey = this.
|
|
7099
|
-
|
|
7100
|
-
|
|
7101
|
-
|
|
7102
|
-
|
|
7103
|
-
|
|
7104
|
-
if (pendingFetch) {
|
|
7105
|
-
return pendingFetch;
|
|
7106
|
-
}
|
|
7107
|
-
const fetchPromise = this.fetchAndCachePermissions(userProfileId, cacheKey);
|
|
7108
|
-
this.pendingFetches.set(cacheKey, fetchPromise);
|
|
7109
|
-
try {
|
|
7110
|
-
return await fetchPromise;
|
|
7111
|
-
} finally {
|
|
7112
|
-
this.pendingFetches.delete(cacheKey);
|
|
7113
|
-
}
|
|
7114
|
-
}
|
|
7115
|
-
/**
|
|
7116
|
-
* Fetch permissions from database and cache the result
|
|
7117
|
-
* @internal
|
|
7118
|
-
*/
|
|
7119
|
-
async fetchAndCachePermissions(userProfileId, cacheKey) {
|
|
7120
|
-
const permissions = await this.permissionsRepo.getEffectivePermissions(userProfileId);
|
|
7121
|
-
if (this.cache.size >= this.maxCacheSize) {
|
|
7122
|
-
const firstKey = this.cache.keys().next().value;
|
|
7123
|
-
if (firstKey) {
|
|
7124
|
-
this.cache.delete(firstKey);
|
|
7125
|
-
}
|
|
7126
|
-
}
|
|
7127
|
-
this.cache.set(cacheKey, {
|
|
7128
|
-
permissions,
|
|
7129
|
-
expiresAt: Date.now() + this.cacheTtlMs
|
|
7130
|
-
});
|
|
7131
|
-
return permissions;
|
|
7241
|
+
const cacheKey = cacheKeys.userPermissions(this.tenantId, userProfileId);
|
|
7242
|
+
return this.cache.getOrSet(
|
|
7243
|
+
cacheKey,
|
|
7244
|
+
() => this.permissionsRepo.getEffectivePermissions(userProfileId),
|
|
7245
|
+
cacheTtl.permissions
|
|
7246
|
+
);
|
|
7132
7247
|
}
|
|
7133
7248
|
// ============================================================================
|
|
7134
7249
|
// CACHE MANAGEMENT
|
|
@@ -7137,24 +7252,15 @@ var PermissionService = class extends TenantAwareService {
|
|
|
7137
7252
|
* Invalidate cached permissions for a specific user.
|
|
7138
7253
|
* Call this after role/permission changes.
|
|
7139
7254
|
*/
|
|
7140
|
-
invalidateCache(userProfileId) {
|
|
7141
|
-
this.cache.delete(this.
|
|
7255
|
+
async invalidateCache(userProfileId) {
|
|
7256
|
+
await this.cache.delete(cacheKeys.userPermissions(this.tenantId, userProfileId));
|
|
7142
7257
|
}
|
|
7143
7258
|
/**
|
|
7144
|
-
* Invalidate all cached permissions.
|
|
7259
|
+
* Invalidate all cached permissions for the current tenant.
|
|
7145
7260
|
* Call this after bulk role/permission changes.
|
|
7146
7261
|
*/
|
|
7147
|
-
invalidateAllCache() {
|
|
7148
|
-
this.cache.
|
|
7149
|
-
}
|
|
7150
|
-
/**
|
|
7151
|
-
* Get current cache size (for monitoring).
|
|
7152
|
-
*/
|
|
7153
|
-
getCacheSize() {
|
|
7154
|
-
return this.cache.size;
|
|
7155
|
-
}
|
|
7156
|
-
getCacheKey(userProfileId) {
|
|
7157
|
-
return `${this.tenantId}:${userProfileId}`;
|
|
7262
|
+
async invalidateAllCache() {
|
|
7263
|
+
await this.cache.deletePattern(cacheKeys.allPermissions(this.tenantId));
|
|
7158
7264
|
}
|
|
7159
7265
|
// ============================================================================
|
|
7160
7266
|
// ROLE MANAGEMENT
|
|
@@ -7516,10 +7622,11 @@ var registry = new NativeObjectRegistryClass();
|
|
|
7516
7622
|
|
|
7517
7623
|
// src/runtime/services/relation.service.ts
|
|
7518
7624
|
var RelationService = class extends TenantAwareService {
|
|
7519
|
-
constructor(adapter, nativeRegistry) {
|
|
7625
|
+
constructor(adapter, nativeRegistry, options) {
|
|
7520
7626
|
super();
|
|
7521
7627
|
this.adapter = adapter;
|
|
7522
|
-
this.
|
|
7628
|
+
this.cache = _nullishCoalesce(_optionalChain([options, 'optionalAccess', _186 => _186.cache]), () => ( adapter.cache));
|
|
7629
|
+
this.schemaService = new ObjectSchemaService(adapter, nativeRegistry, { cache: this.cache });
|
|
7523
7630
|
}
|
|
7524
7631
|
/**
|
|
7525
7632
|
* Validate all relation attributes in the data
|
|
@@ -7570,7 +7677,7 @@ var RelationService = class extends TenantAwareService {
|
|
|
7570
7677
|
}
|
|
7571
7678
|
const isUniversal = attr.targets.length === 1 && attr.targets[0].object === RELATION_TARGET_ANY;
|
|
7572
7679
|
const validObjectIds = isUniversal ? null : await this.getValidObjectIds(attr.targets);
|
|
7573
|
-
if (!isUniversal && _optionalChain([validObjectIds, 'optionalAccess',
|
|
7680
|
+
if (!isUniversal && _optionalChain([validObjectIds, 'optionalAccess', _187 => _187.size]) === 0) {
|
|
7574
7681
|
errors.push({
|
|
7575
7682
|
attribute: attr.name,
|
|
7576
7683
|
message: `No valid target objects found for ${attr.label}`
|
|
@@ -7621,7 +7728,7 @@ var RelationService = class extends TenantAwareService {
|
|
|
7621
7728
|
for (const target of targets) {
|
|
7622
7729
|
try {
|
|
7623
7730
|
const objectSchema = await this.schemaService.getObjectSchemaByName(target.object);
|
|
7624
|
-
if (_optionalChain([objectSchema, 'optionalAccess',
|
|
7731
|
+
if (_optionalChain([objectSchema, 'optionalAccess', _188 => _188.id])) {
|
|
7625
7732
|
objectIds.add(objectSchema.id);
|
|
7626
7733
|
}
|
|
7627
7734
|
} catch (e7) {
|
|
@@ -7674,7 +7781,7 @@ var RelationService = class extends TenantAwareService {
|
|
|
7674
7781
|
const recordService = new RecordService(this.adapter);
|
|
7675
7782
|
for (const target of filteredTargets) {
|
|
7676
7783
|
const objectSchema = await this.schemaService.getObjectSchemaByName(target.object);
|
|
7677
|
-
if (!_optionalChain([objectSchema, 'optionalAccess',
|
|
7784
|
+
if (!_optionalChain([objectSchema, 'optionalAccess', _189 => _189.id])) {
|
|
7678
7785
|
continue;
|
|
7679
7786
|
}
|
|
7680
7787
|
const result = query ? await recordService.searchRecords(objectSchema.id, query, {
|
|
@@ -7744,9 +7851,9 @@ var RelationService = class extends TenantAwareService {
|
|
|
7744
7851
|
continue;
|
|
7745
7852
|
}
|
|
7746
7853
|
let template = objectSchema.labelExpression;
|
|
7747
|
-
if (_optionalChain([attribute, 'optionalAccess',
|
|
7854
|
+
if (_optionalChain([attribute, 'optionalAccess', _190 => _190.targets])) {
|
|
7748
7855
|
const targetConfig = attribute.targets.find((t) => t.object === objectSchema.name);
|
|
7749
|
-
if (_optionalChain([targetConfig, 'optionalAccess',
|
|
7856
|
+
if (_optionalChain([targetConfig, 'optionalAccess', _191 => _191.displayTemplate])) {
|
|
7750
7857
|
template = targetConfig.displayTemplate;
|
|
7751
7858
|
}
|
|
7752
7859
|
}
|
|
@@ -7786,12 +7893,15 @@ var RelationService = class extends TenantAwareService {
|
|
|
7786
7893
|
|
|
7787
7894
|
// src/runtime/services/rollup.service.ts
|
|
7788
7895
|
var RollupService = class {
|
|
7789
|
-
constructor(adapter) {
|
|
7896
|
+
constructor(adapter, options) {
|
|
7790
7897
|
this.adapter = adapter;
|
|
7898
|
+
this.cache = _nullishCoalesce(_optionalChain([options, 'optionalAccess', _192 => _192.cache]), () => ( adapter.cache));
|
|
7791
7899
|
}
|
|
7792
7900
|
/**
|
|
7793
7901
|
* Calculate a rollup value for a record
|
|
7794
7902
|
*
|
|
7903
|
+
* Results are cached if a CacheAdapter is configured.
|
|
7904
|
+
*
|
|
7795
7905
|
* @param recordId - ID of the parent record
|
|
7796
7906
|
* @param rollupAttr - Rollup attribute definition
|
|
7797
7907
|
* @param schema - Schema of the parent object
|
|
@@ -7815,6 +7925,21 @@ var RollupService = class {
|
|
|
7815
7925
|
* ```
|
|
7816
7926
|
*/
|
|
7817
7927
|
async calculate(recordId, rollupAttr, schema) {
|
|
7928
|
+
if (this.cache) {
|
|
7929
|
+
const tenantId = getTenantId();
|
|
7930
|
+
const cacheKey = cacheKeys.rollupValue(tenantId, recordId, rollupAttr.name);
|
|
7931
|
+
return this.cache.getOrSet(
|
|
7932
|
+
cacheKey,
|
|
7933
|
+
() => this.computeRollup(recordId, rollupAttr, schema),
|
|
7934
|
+
cacheTtl.rollup
|
|
7935
|
+
);
|
|
7936
|
+
}
|
|
7937
|
+
return this.computeRollup(recordId, rollupAttr, schema);
|
|
7938
|
+
}
|
|
7939
|
+
/**
|
|
7940
|
+
* Internal method to compute rollup value (no caching)
|
|
7941
|
+
*/
|
|
7942
|
+
async computeRollup(recordId, rollupAttr, schema) {
|
|
7818
7943
|
const relationAttr = schema.attributes.find(
|
|
7819
7944
|
(a) => a.type === "relation" && a.name === rollupAttr.relationAttribute
|
|
7820
7945
|
);
|
|
@@ -7866,7 +7991,7 @@ var RollupService = class {
|
|
|
7866
7991
|
const reverseRelationAttr = sourceAttributes.find((attr) => {
|
|
7867
7992
|
if (attr.type !== "relation") return false;
|
|
7868
7993
|
const relationConfig = attr.config;
|
|
7869
|
-
return _optionalChain([relationConfig, 'optionalAccess',
|
|
7994
|
+
return _optionalChain([relationConfig, 'optionalAccess', _193 => _193.targets, 'optionalAccess', _194 => _194.some, 'call', _195 => _195((t) => t.object === schema.name)]);
|
|
7870
7995
|
});
|
|
7871
7996
|
if (!reverseRelationAttr) {
|
|
7872
7997
|
return { value: null, recordCount: 0 };
|
|
@@ -8053,6 +8178,31 @@ var RollupService = class {
|
|
|
8053
8178
|
}
|
|
8054
8179
|
return [...new Set(affectedIds)];
|
|
8055
8180
|
}
|
|
8181
|
+
/**
|
|
8182
|
+
* Invalidate cached rollups for affected parent records.
|
|
8183
|
+
* Call this after a child record is created, updated, or deleted.
|
|
8184
|
+
*
|
|
8185
|
+
* @param affectedParentIds - Array of parent record IDs whose rollups need invalidation
|
|
8186
|
+
*/
|
|
8187
|
+
async invalidateAffectedRollups(affectedParentIds) {
|
|
8188
|
+
if (!this.cache || affectedParentIds.length === 0) return;
|
|
8189
|
+
const tenantId = getTenantId();
|
|
8190
|
+
const cache = this.cache;
|
|
8191
|
+
await Promise.all(
|
|
8192
|
+
affectedParentIds.map(
|
|
8193
|
+
(parentId) => cache.deletePattern(cacheKeys.rollupsByRecord(tenantId, parentId))
|
|
8194
|
+
)
|
|
8195
|
+
);
|
|
8196
|
+
}
|
|
8197
|
+
/**
|
|
8198
|
+
* Invalidate all cached rollups for the current tenant.
|
|
8199
|
+
* Use sparingly - prefer targeted invalidation.
|
|
8200
|
+
*/
|
|
8201
|
+
async invalidateAllRollups() {
|
|
8202
|
+
if (!this.cache) return;
|
|
8203
|
+
const tenantId = getTenantId();
|
|
8204
|
+
await this.cache.deletePattern(cacheKeys.allRollups(tenantId));
|
|
8205
|
+
}
|
|
8056
8206
|
/**
|
|
8057
8207
|
* Find records that have forward rollups pointing to the modified record.
|
|
8058
8208
|
*
|
|
@@ -8082,7 +8232,7 @@ var RollupService = class {
|
|
|
8082
8232
|
}
|
|
8083
8233
|
for (const rollupDbAttr of rollupAttrs) {
|
|
8084
8234
|
const rollupConfig = rollupDbAttr.config;
|
|
8085
|
-
if (!_optionalChain([rollupConfig, 'optionalAccess',
|
|
8235
|
+
if (!_optionalChain([rollupConfig, 'optionalAccess', _196 => _196.relationAttribute])) {
|
|
8086
8236
|
continue;
|
|
8087
8237
|
}
|
|
8088
8238
|
const relationAttr = attributes.find(
|
|
@@ -8092,7 +8242,7 @@ var RollupService = class {
|
|
|
8092
8242
|
continue;
|
|
8093
8243
|
}
|
|
8094
8244
|
const relationConfig = relationAttr.config;
|
|
8095
|
-
const targetsChangedObject = _optionalChain([relationConfig, 'optionalAccess',
|
|
8245
|
+
const targetsChangedObject = _optionalChain([relationConfig, 'optionalAccess', _197 => _197.targets, 'optionalAccess', _198 => _198.some, 'call', _199 => _199(
|
|
8096
8246
|
(t) => t.object === changedSchema.name
|
|
8097
8247
|
)]);
|
|
8098
8248
|
if (!targetsChangedObject) {
|
|
@@ -8195,7 +8345,7 @@ var UserService = class extends TenantAwareService {
|
|
|
8195
8345
|
if (roleErrors.length > 0) {
|
|
8196
8346
|
errors.push({
|
|
8197
8347
|
attribute: attr.name,
|
|
8198
|
-
message: `Users do not have required role for ${attr.label}. Allowed roles: ${_optionalChain([attr, 'access',
|
|
8348
|
+
message: `Users do not have required role for ${attr.label}. Allowed roles: ${_optionalChain([attr, 'access', _200 => _200.allowedRoles, 'optionalAccess', _201 => _201.join, 'call', _202 => _202(", ")])}`,
|
|
8199
8349
|
invalidIds: roleErrors
|
|
8200
8350
|
});
|
|
8201
8351
|
}
|
|
@@ -8249,15 +8399,15 @@ var RecordService = class extends TenantAwareService {
|
|
|
8249
8399
|
super();
|
|
8250
8400
|
this.adapter = adapter;
|
|
8251
8401
|
this.schemaService = new ObjectSchemaService(adapter, registry, {
|
|
8252
|
-
auditService: _optionalChain([options, 'optionalAccess',
|
|
8402
|
+
auditService: _optionalChain([options, 'optionalAccess', _203 => _203.auditService])
|
|
8253
8403
|
});
|
|
8254
8404
|
this.relationService = new RelationService(adapter, registry);
|
|
8255
8405
|
this.userService = new UserService(adapter);
|
|
8256
8406
|
this.rollupService = new RollupService(adapter);
|
|
8257
|
-
this.hookRegistry = _nullishCoalesce(_optionalChain([options, 'optionalAccess',
|
|
8258
|
-
this.permissionService = _optionalChain([options, 'optionalAccess',
|
|
8259
|
-
this.auditService = _nullishCoalesce(_optionalChain([options, 'optionalAccess',
|
|
8260
|
-
this.policyRegistry = _optionalChain([options, 'optionalAccess',
|
|
8407
|
+
this.hookRegistry = _nullishCoalesce(_optionalChain([options, 'optionalAccess', _204 => _204.hookRegistry]), () => ( new NoopHookRegistry()));
|
|
8408
|
+
this.permissionService = _optionalChain([options, 'optionalAccess', _205 => _205.permissionService]);
|
|
8409
|
+
this.auditService = _nullishCoalesce(_optionalChain([options, 'optionalAccess', _206 => _206.auditService]), () => ( (adapter.audit ? new AuditService(adapter) : void 0)));
|
|
8410
|
+
this.policyRegistry = _optionalChain([options, 'optionalAccess', _207 => _207.policyRegistry]) === null ? null : _nullishCoalesce(_optionalChain([options, 'optionalAccess', _208 => _208.policyRegistry]), () => ( defaultPolicyRegistry));
|
|
8261
8411
|
}
|
|
8262
8412
|
/**
|
|
8263
8413
|
* Check permission for an action on an object.
|
|
@@ -8441,20 +8591,20 @@ var RecordService = class extends TenantAwareService {
|
|
|
8441
8591
|
const schema = await this.schemaService.getObjectSchema(objectId);
|
|
8442
8592
|
const dataWithDefaults = applyDefaultValues(schema, data);
|
|
8443
8593
|
await this.checkPermission(schema.name, "create");
|
|
8444
|
-
const hookCtx = this.buildCreateHookContext(schema, dataWithDefaults, _optionalChain([options, 'optionalAccess',
|
|
8445
|
-
if (!_optionalChain([options, 'optionalAccess',
|
|
8594
|
+
const hookCtx = this.buildCreateHookContext(schema, dataWithDefaults, _optionalChain([options, 'optionalAccess', _209 => _209.hookMetadata]));
|
|
8595
|
+
if (!_optionalChain([options, 'optionalAccess', _210 => _210.skipHooks])) {
|
|
8446
8596
|
await this.hookRegistry.execute("beforeCreate", schema.name, hookCtx);
|
|
8447
8597
|
}
|
|
8448
|
-
if (_optionalChain([options, 'optionalAccess',
|
|
8449
|
-
if (_optionalChain([options, 'optionalAccess',
|
|
8598
|
+
if (_optionalChain([options, 'optionalAccess', _211 => _211.validate]) !== false) {
|
|
8599
|
+
if (_optionalChain([options, 'optionalAccess', _212 => _212.allowDraft])) {
|
|
8450
8600
|
validateDraftOrThrow(schema, dataWithDefaults);
|
|
8451
8601
|
} else {
|
|
8452
8602
|
validateObjectOrThrow(schema, dataWithDefaults);
|
|
8453
8603
|
}
|
|
8454
|
-
if (!_optionalChain([options, 'optionalAccess',
|
|
8604
|
+
if (!_optionalChain([options, 'optionalAccess', _213 => _213.skipRelationValidation])) {
|
|
8455
8605
|
await this.relationService.validateRelationsOrThrow(schema, dataWithDefaults);
|
|
8456
8606
|
}
|
|
8457
|
-
if (!_optionalChain([options, 'optionalAccess',
|
|
8607
|
+
if (!_optionalChain([options, 'optionalAccess', _214 => _214.skipUserValidation])) {
|
|
8458
8608
|
await this.userService.validateUsersOrThrow(schema, dataWithDefaults);
|
|
8459
8609
|
}
|
|
8460
8610
|
}
|
|
@@ -8465,10 +8615,10 @@ var RecordService = class extends TenantAwareService {
|
|
|
8465
8615
|
data: dataWithDefaults,
|
|
8466
8616
|
label,
|
|
8467
8617
|
completionStatus,
|
|
8468
|
-
metadata: _optionalChain([options, 'optionalAccess',
|
|
8618
|
+
metadata: _optionalChain([options, 'optionalAccess', _215 => _215.metadata]),
|
|
8469
8619
|
createdBy: this.userId
|
|
8470
8620
|
});
|
|
8471
|
-
if (!_optionalChain([options, 'optionalAccess',
|
|
8621
|
+
if (!_optionalChain([options, 'optionalAccess', _216 => _216.skipHooks])) {
|
|
8472
8622
|
const afterCtx = {
|
|
8473
8623
|
...hookCtx,
|
|
8474
8624
|
recordId: record.id,
|
|
@@ -8485,7 +8635,7 @@ var RecordService = class extends TenantAwareService {
|
|
|
8485
8635
|
objectId: schema.id,
|
|
8486
8636
|
recordId: record.id,
|
|
8487
8637
|
recordLabel: record.label,
|
|
8488
|
-
metadata: _optionalChain([options, 'optionalAccess',
|
|
8638
|
+
metadata: _optionalChain([options, 'optionalAccess', _217 => _217.hookMetadata])
|
|
8489
8639
|
});
|
|
8490
8640
|
}
|
|
8491
8641
|
return record;
|
|
@@ -8503,17 +8653,17 @@ var RecordService = class extends TenantAwareService {
|
|
|
8503
8653
|
return null;
|
|
8504
8654
|
}
|
|
8505
8655
|
const schema = await this.schemaService.getObjectSchema(record.objectId);
|
|
8506
|
-
if (!_optionalChain([options, 'optionalAccess',
|
|
8656
|
+
if (!_optionalChain([options, 'optionalAccess', _218 => _218.skipPolicyCheck])) {
|
|
8507
8657
|
const policy = this.getPolicy(schema.name);
|
|
8508
8658
|
if (policy && !this.checkRecordAccess(policy, record)) {
|
|
8509
8659
|
return null;
|
|
8510
8660
|
}
|
|
8511
8661
|
}
|
|
8512
8662
|
let enrichedRecord = record;
|
|
8513
|
-
if (!_optionalChain([options, 'optionalAccess',
|
|
8663
|
+
if (!_optionalChain([options, 'optionalAccess', _219 => _219.skipFormulas])) {
|
|
8514
8664
|
enrichedRecord = this.enrichWithFormulas(record, schema);
|
|
8515
8665
|
}
|
|
8516
|
-
if (_optionalChain([options, 'optionalAccess',
|
|
8666
|
+
if (_optionalChain([options, 'optionalAccess', _220 => _220.includeSchema])) {
|
|
8517
8667
|
const recordWithSchema = enrichedRecord;
|
|
8518
8668
|
recordWithSchema.schema = schema;
|
|
8519
8669
|
return recordWithSchema;
|
|
@@ -8572,9 +8722,9 @@ var RecordService = class extends TenantAwareService {
|
|
|
8572
8722
|
data,
|
|
8573
8723
|
mergedData,
|
|
8574
8724
|
changedAttributes,
|
|
8575
|
-
_optionalChain([options, 'optionalAccess',
|
|
8725
|
+
_optionalChain([options, 'optionalAccess', _221 => _221.hookMetadata])
|
|
8576
8726
|
);
|
|
8577
|
-
if (!_optionalChain([options, 'optionalAccess',
|
|
8727
|
+
if (!_optionalChain([options, 'optionalAccess', _222 => _222.skipHooks])) {
|
|
8578
8728
|
await this.hookRegistry.execute("beforeUpdate", schema.name, hookCtx);
|
|
8579
8729
|
}
|
|
8580
8730
|
const hookModifiedValues = {};
|
|
@@ -8583,19 +8733,19 @@ var RecordService = class extends TenantAwareService {
|
|
|
8583
8733
|
hookModifiedValues[key] = hookCtx.newValues[key];
|
|
8584
8734
|
}
|
|
8585
8735
|
}
|
|
8586
|
-
if (_optionalChain([options, 'optionalAccess',
|
|
8587
|
-
if (_optionalChain([options, 'optionalAccess',
|
|
8736
|
+
if (_optionalChain([options, 'optionalAccess', _223 => _223.validate]) !== false) {
|
|
8737
|
+
if (_optionalChain([options, 'optionalAccess', _224 => _224.partial])) {
|
|
8588
8738
|
validateDraftOrThrow(schema, mergedData);
|
|
8589
8739
|
} else {
|
|
8590
8740
|
validateObjectOrThrow(schema, mergedData);
|
|
8591
8741
|
}
|
|
8592
|
-
if (!_optionalChain([options, 'optionalAccess',
|
|
8742
|
+
if (!_optionalChain([options, 'optionalAccess', _225 => _225.skipRelationValidation])) {
|
|
8593
8743
|
await this.relationService.validateRelationsOrThrow(schema, {
|
|
8594
8744
|
...data,
|
|
8595
8745
|
...hookModifiedValues
|
|
8596
8746
|
});
|
|
8597
8747
|
}
|
|
8598
|
-
if (!_optionalChain([options, 'optionalAccess',
|
|
8748
|
+
if (!_optionalChain([options, 'optionalAccess', _226 => _226.skipUserValidation])) {
|
|
8599
8749
|
await this.userService.validateUsersOrThrow(schema, {
|
|
8600
8750
|
...data,
|
|
8601
8751
|
...hookModifiedValues
|
|
@@ -8611,7 +8761,7 @@ var RecordService = class extends TenantAwareService {
|
|
|
8611
8761
|
__label: label,
|
|
8612
8762
|
__lastUpdatedBy: this.userId
|
|
8613
8763
|
};
|
|
8614
|
-
if (_optionalChain([options, 'optionalAccess',
|
|
8764
|
+
if (_optionalChain([options, 'optionalAccess', _227 => _227.metadata]) !== void 0) {
|
|
8615
8765
|
const existingMetadata = _nullishCoalesce(existing.metadata, () => ( {}));
|
|
8616
8766
|
const mergedMetadata = { ...existingMetadata, ...options.metadata };
|
|
8617
8767
|
const cleanedMetadata = Object.fromEntries(
|
|
@@ -8620,7 +8770,7 @@ var RecordService = class extends TenantAwareService {
|
|
|
8620
8770
|
updatePayload.__metadata = cleanedMetadata;
|
|
8621
8771
|
}
|
|
8622
8772
|
const updated = await this.adapter.objectRecords.update(recordId, updatePayload);
|
|
8623
|
-
if (!_optionalChain([options, 'optionalAccess',
|
|
8773
|
+
if (!_optionalChain([options, 'optionalAccess', _228 => _228.skipHooks])) {
|
|
8624
8774
|
const afterCtx = {
|
|
8625
8775
|
...hookCtx,
|
|
8626
8776
|
record: updated
|
|
@@ -8635,7 +8785,7 @@ var RecordService = class extends TenantAwareService {
|
|
|
8635
8785
|
if (this.auditService && this.userId && allChangedAttributes.length > 0) {
|
|
8636
8786
|
const changes = allChangedAttributes.map((attr) => ({
|
|
8637
8787
|
field: attr,
|
|
8638
|
-
oldValue: _optionalChain([hookCtx, 'access',
|
|
8788
|
+
oldValue: _optionalChain([hookCtx, 'access', _229 => _229.oldValues, 'optionalAccess', _230 => _230[attr]]),
|
|
8639
8789
|
newValue: hookCtx.newValues[attr]
|
|
8640
8790
|
}));
|
|
8641
8791
|
await this.auditService.logRecordAction({
|
|
@@ -8646,7 +8796,7 @@ var RecordService = class extends TenantAwareService {
|
|
|
8646
8796
|
recordId: updated.id,
|
|
8647
8797
|
recordLabel: updated.label,
|
|
8648
8798
|
changes,
|
|
8649
|
-
metadata: _optionalChain([options, 'optionalAccess',
|
|
8799
|
+
metadata: _optionalChain([options, 'optionalAccess', _231 => _231.hookMetadata])
|
|
8650
8800
|
});
|
|
8651
8801
|
}
|
|
8652
8802
|
return updated;
|
|
@@ -8746,23 +8896,23 @@ var RecordService = class extends TenantAwareService {
|
|
|
8746
8896
|
if (policy) {
|
|
8747
8897
|
this.checkRecordDelete(policy, record);
|
|
8748
8898
|
}
|
|
8749
|
-
if (_optionalChain([options, 'optionalAccess',
|
|
8899
|
+
if (_optionalChain([options, 'optionalAccess', _232 => _232.checkSystem])) {
|
|
8750
8900
|
if (schema.system) {
|
|
8751
8901
|
throw new ProtectedResourceError("object", schema.name, "delete");
|
|
8752
8902
|
}
|
|
8753
8903
|
}
|
|
8754
|
-
if (!_optionalChain([options, 'optionalAccess',
|
|
8904
|
+
if (!_optionalChain([options, 'optionalAccess', _233 => _233.skipReferenceCheck])) {
|
|
8755
8905
|
const references = await this.adapter.objectRecords.countRecordsReferencingId(recordId);
|
|
8756
8906
|
if (references.length > 0) {
|
|
8757
8907
|
throw new RecordReferencedError(recordId, references);
|
|
8758
8908
|
}
|
|
8759
8909
|
}
|
|
8760
|
-
const hookCtx = this.buildDeleteHookContext(schema, record, _optionalChain([options, 'optionalAccess',
|
|
8761
|
-
if (!_optionalChain([options, 'optionalAccess',
|
|
8910
|
+
const hookCtx = this.buildDeleteHookContext(schema, record, _optionalChain([options, 'optionalAccess', _234 => _234.hookMetadata]));
|
|
8911
|
+
if (!_optionalChain([options, 'optionalAccess', _235 => _235.skipHooks])) {
|
|
8762
8912
|
await this.hookRegistry.execute("beforeDelete", schema.name, hookCtx);
|
|
8763
8913
|
}
|
|
8764
8914
|
await this.adapter.objectRecords.delete(recordId);
|
|
8765
|
-
if (!_optionalChain([options, 'optionalAccess',
|
|
8915
|
+
if (!_optionalChain([options, 'optionalAccess', _236 => _236.skipHooks])) {
|
|
8766
8916
|
await this.hookRegistry.execute("afterDelete", schema.name, hookCtx);
|
|
8767
8917
|
}
|
|
8768
8918
|
await this.recalculateParentRollups(record, schema);
|
|
@@ -8774,7 +8924,7 @@ var RecordService = class extends TenantAwareService {
|
|
|
8774
8924
|
objectId: schema.id,
|
|
8775
8925
|
recordId: record.id,
|
|
8776
8926
|
recordLabel: record.label,
|
|
8777
|
-
metadata: _optionalChain([options, 'optionalAccess',
|
|
8927
|
+
metadata: _optionalChain([options, 'optionalAccess', _237 => _237.hookMetadata])
|
|
8778
8928
|
});
|
|
8779
8929
|
}
|
|
8780
8930
|
}
|
|
@@ -8805,12 +8955,12 @@ var RecordService = class extends TenantAwareService {
|
|
|
8805
8955
|
}
|
|
8806
8956
|
const schema = await this.schemaService.getObjectSchema(record.objectId);
|
|
8807
8957
|
await this.checkPermission(schema.name, "update");
|
|
8808
|
-
const hookCtx = this.buildRestoreHookContext(schema, record, _optionalChain([options, 'optionalAccess',
|
|
8809
|
-
if (!_optionalChain([options, 'optionalAccess',
|
|
8958
|
+
const hookCtx = this.buildRestoreHookContext(schema, record, _optionalChain([options, 'optionalAccess', _238 => _238.hookMetadata]));
|
|
8959
|
+
if (!_optionalChain([options, 'optionalAccess', _239 => _239.skipHooks])) {
|
|
8810
8960
|
await this.hookRegistry.execute("beforeRestore", schema.name, hookCtx);
|
|
8811
8961
|
}
|
|
8812
8962
|
const restored = await this.adapter.objectRecords.restore(recordId);
|
|
8813
|
-
if (!_optionalChain([options, 'optionalAccess',
|
|
8963
|
+
if (!_optionalChain([options, 'optionalAccess', _240 => _240.skipHooks])) {
|
|
8814
8964
|
const afterCtx = {
|
|
8815
8965
|
...hookCtx,
|
|
8816
8966
|
record: restored
|
|
@@ -8825,7 +8975,7 @@ var RecordService = class extends TenantAwareService {
|
|
|
8825
8975
|
objectId: schema.id,
|
|
8826
8976
|
recordId: restored.id,
|
|
8827
8977
|
recordLabel: restored.label,
|
|
8828
|
-
metadata: _optionalChain([options, 'optionalAccess',
|
|
8978
|
+
metadata: _optionalChain([options, 'optionalAccess', _241 => _241.hookMetadata])
|
|
8829
8979
|
});
|
|
8830
8980
|
}
|
|
8831
8981
|
return restored;
|
|
@@ -8970,20 +9120,20 @@ var RecordService = class extends TenantAwareService {
|
|
|
8970
9120
|
if (this.permissionService && this.userId) {
|
|
8971
9121
|
await this.checkPermission(schema.name, "read");
|
|
8972
9122
|
}
|
|
8973
|
-
const policy = _optionalChain([options, 'optionalAccess',
|
|
9123
|
+
const policy = _optionalChain([options, 'optionalAccess', _242 => _242.skipPolicyFilter]) ? void 0 : this.getPolicy(schema.name);
|
|
8974
9124
|
let effectiveOptions = options;
|
|
8975
|
-
if (_optionalChain([policy, 'optionalAccess',
|
|
9125
|
+
if (_optionalChain([policy, 'optionalAccess', _243 => _243.applyListFilter])) {
|
|
8976
9126
|
effectiveOptions = policy.applyListFilter(this.buildPolicyContext(schema.name), options);
|
|
8977
9127
|
}
|
|
8978
9128
|
const result = await this.adapter.objectRecords.list(objectId, effectiveOptions);
|
|
8979
9129
|
let filteredRecords = result.records;
|
|
8980
9130
|
let effectiveTotal = result.total;
|
|
8981
|
-
if (_optionalChain([policy, 'optionalAccess',
|
|
9131
|
+
if (_optionalChain([policy, 'optionalAccess', _244 => _244.canAccessRecord])) {
|
|
8982
9132
|
const ctx = this.buildPolicyContext(schema.name);
|
|
8983
|
-
filteredRecords = result.records.filter((record) => _optionalChain([policy, 'access',
|
|
9133
|
+
filteredRecords = result.records.filter((record) => _optionalChain([policy, 'access', _245 => _245.canAccessRecord, 'optionalCall', _246 => _246(ctx, record)]));
|
|
8984
9134
|
effectiveTotal = filteredRecords.length;
|
|
8985
9135
|
}
|
|
8986
|
-
if (!_optionalChain([options, 'optionalAccess',
|
|
9136
|
+
if (!_optionalChain([options, 'optionalAccess', _247 => _247.skipFormulas])) {
|
|
8987
9137
|
return {
|
|
8988
9138
|
records: this.enrichRecordsWithFormulas(filteredRecords, schema),
|
|
8989
9139
|
total: effectiveTotal
|
|
@@ -9008,7 +9158,7 @@ var RecordService = class extends TenantAwareService {
|
|
|
9008
9158
|
await this.checkPermission(schema.name, "read");
|
|
9009
9159
|
}
|
|
9010
9160
|
const result = await this.adapter.objectRecords.search(objectId, query, options);
|
|
9011
|
-
if (!_optionalChain([options, 'optionalAccess',
|
|
9161
|
+
if (!_optionalChain([options, 'optionalAccess', _248 => _248.skipFormulas])) {
|
|
9012
9162
|
return {
|
|
9013
9163
|
records: this.enrichRecordsWithFormulas(result.records, schema),
|
|
9014
9164
|
total: result.total
|
|
@@ -9206,8 +9356,8 @@ var RollupScheduler = class {
|
|
|
9206
9356
|
this.getSchemaById = getSchemaById;
|
|
9207
9357
|
this.pending = /* @__PURE__ */ new Map();
|
|
9208
9358
|
this.rollupService = new RollupService(adapter);
|
|
9209
|
-
this.debounceMs = _nullishCoalesce(_optionalChain([options, 'optionalAccess',
|
|
9210
|
-
this.maxPending = _nullishCoalesce(_optionalChain([options, 'optionalAccess',
|
|
9359
|
+
this.debounceMs = _nullishCoalesce(_optionalChain([options, 'optionalAccess', _249 => _249.debounceMs]), () => ( 100));
|
|
9360
|
+
this.maxPending = _nullishCoalesce(_optionalChain([options, 'optionalAccess', _250 => _250.maxPending]), () => ( 100));
|
|
9211
9361
|
}
|
|
9212
9362
|
/**
|
|
9213
9363
|
* Schedule a rollup recalculation for a parent record.
|
|
@@ -9283,7 +9433,7 @@ var UserProfileService = class extends TenantAwareService {
|
|
|
9283
9433
|
constructor(adapter, options) {
|
|
9284
9434
|
super();
|
|
9285
9435
|
this.adapter = adapter;
|
|
9286
|
-
this.auditService = _optionalChain([options, 'optionalAccess',
|
|
9436
|
+
this.auditService = _optionalChain([options, 'optionalAccess', _251 => _251.auditService]);
|
|
9287
9437
|
}
|
|
9288
9438
|
/**
|
|
9289
9439
|
* Create a new user profile (typically after first auth).
|
|
@@ -9416,7 +9566,7 @@ var UserProfileService = class extends TenantAwareService {
|
|
|
9416
9566
|
*/
|
|
9417
9567
|
async deleteProfile(profileId, options) {
|
|
9418
9568
|
const profile = await this.getProfileOrThrow(profileId);
|
|
9419
|
-
if (_optionalChain([options, 'optionalAccess',
|
|
9569
|
+
if (_optionalChain([options, 'optionalAccess', _252 => _252.checkAdmin])) {
|
|
9420
9570
|
if (profile.role === "admin") {
|
|
9421
9571
|
const adminCount = await this.adapter.userProfiles.countByRole("admin");
|
|
9422
9572
|
if (adminCount <= 1) {
|
|
@@ -9485,7 +9635,7 @@ var UserProfileService = class extends TenantAwareService {
|
|
|
9485
9635
|
*/
|
|
9486
9636
|
async hasRole(profileId, role) {
|
|
9487
9637
|
const profile = await this.getProfile(profileId);
|
|
9488
|
-
return _optionalChain([profile, 'optionalAccess',
|
|
9638
|
+
return _optionalChain([profile, 'optionalAccess', _253 => _253.role]) === role;
|
|
9489
9639
|
}
|
|
9490
9640
|
/**
|
|
9491
9641
|
* Check if user is admin
|
|
@@ -10319,4 +10469,7 @@ var NoopGeocodingAdapter = class {
|
|
|
10319
10469
|
|
|
10320
10470
|
|
|
10321
10471
|
|
|
10322
|
-
|
|
10472
|
+
|
|
10473
|
+
|
|
10474
|
+
|
|
10475
|
+
exports.RELATION_TARGET_ANY = RELATION_TARGET_ANY; exports.isUniversalRelation = isUniversalRelation; exports.RecordReferencedError = RecordReferencedError; exports.AttributeInUseError = AttributeInUseError; exports.ObjectReferencedError = ObjectReferencedError; exports.NoopGeocodingAdapter = NoopGeocodingAdapter; exports.SYSTEM_FIELD_NAMES = SYSTEM_FIELD_NAMES; exports.RESERVED_ATTRIBUTE_NAMES = RESERVED_ATTRIBUTE_NAMES; exports.PolicyViolationError = PolicyViolationError; exports.SYSTEM_ATTRIBUTES = SYSTEM_ATTRIBUTES; exports.getSystemAttributeList = getSystemAttributeList; exports.isSystemAttribute = isSystemAttribute; exports.isSystemAttributeObject = isSystemAttributeObject; exports.asTenantId = asTenantId; exports.asUserId = asUserId; exports.generateId = generateId; exports.generatePrefixedId = generatePrefixedId; exports.EMPTY_VALUE_PLACEHOLDER = EMPTY_VALUE_PLACEHOLDER; exports.formatAttributeValue = formatAttributeValue; exports.SchemaErrorCode = SchemaErrorCode; exports.SchemaError = SchemaError; exports.NotFoundError = NotFoundError; exports.ObjectNotFoundError = ObjectNotFoundError; exports.AttributeNotFoundError = AttributeNotFoundError; exports.RecordNotFoundError = RecordNotFoundError; exports.UserProfileNotFoundError = UserProfileNotFoundError; exports.FileNotFoundError = FileNotFoundError; exports.ValidationError = ValidationError; exports.ProtectedResourceError = ProtectedResourceError; exports.SyncError = SyncError; exports.NotSystemObjectError = NotSystemObjectError; exports.DuplicateError = DuplicateError; exports.isSchemaError = isSchemaError; exports.isNotFoundError = isNotFoundError; exports.isValidationError = isValidationError; exports.isProtectedResourceError = isProtectedResourceError; exports.ForbiddenError = ForbiddenError; exports.ProtectedRoleError = ProtectedRoleError; exports.RoleNotFoundError = RoleNotFoundError; exports.isForbiddenError = isForbiddenError; exports.text = text; exports.textarea = textarea; exports.richtext = richtext; exports.number = number; exports.checkbox = checkbox; exports.date = date; exports.phone = phone; exports.currency = currency; exports.status = status; exports.select = select; exports.multiselect = multiselect; exports.location = location; exports.file = file; exports.user = user; exports.relation = relation; exports.rating = rating; exports.formula = formula; exports.rollup = rollup; exports.FlowRowBuilder = FlowRowBuilder; exports.FlowPageBuilder = FlowPageBuilder; exports.FlowBuilder = FlowBuilder; exports.flow = flow; exports.ObjectBuilder = ObjectBuilder; exports.object = object; exports.GroupBuilder = GroupBuilder; exports.DirectTableTabConfig = DirectTableTabConfig; exports.InverseTableTabConfig = InverseTableTabConfig; exports.CustomTabConfig = CustomTabConfig; exports.NotesTabConfig = NotesTabConfig; exports.ActivityTabConfig = ActivityTabConfig; exports.TabBuilder = TabBuilder; exports.ViewBuilder = ViewBuilder; exports.view = view; exports.group = group; exports.registry = registry; exports.DEFAULT_VALIDATION_MESSAGES = DEFAULT_VALIDATION_MESSAGES; exports.textConfigSchema = textConfigSchema; exports.textareaConfigSchema = textareaConfigSchema; exports.richtextConfigSchema = richtextConfigSchema; exports.numberConfigSchema = numberConfigSchema; exports.checkboxConfigSchema = checkboxConfigSchema; exports.dateConfigSchema = dateConfigSchema; exports.phoneConfigSchema = phoneConfigSchema; exports.currencyConfigSchema = currencyConfigSchema; exports.statusConfigSchema = statusConfigSchema; exports.locationConfigSchema = locationConfigSchema; exports.selectConfigSchema = selectConfigSchema; exports.multiselectConfigSchema = multiselectConfigSchema; exports.fileConfigSchema = fileConfigSchema; exports.userConfigSchema = userConfigSchema; exports.relationConfigSchema = relationConfigSchema; exports.ratingConfigSchema = ratingConfigSchema; exports.formulaConfigSchema = formulaConfigSchema; exports.rollupConfigSchema = rollupConfigSchema; exports.attributeConfigSchemas = attributeConfigSchemas; exports.getAttributeConfigSchema = getAttributeConfigSchema; exports.validateAttributeConfig = validateAttributeConfig; exports.parseAttributeConfig = parseAttributeConfig; exports.safeParseAttributeConfig = safeParseAttributeConfig; exports.createTextValidator = createTextValidator; exports.createNumberValidator = createNumberValidator; exports.createCheckboxValidator = createCheckboxValidator; exports.createDateValidator = createDateValidator; exports.createPhoneValidator = createPhoneValidator; exports.createCurrencyValidator = createCurrencyValidator; exports.createStatusValidator = createStatusValidator; exports.createSelectValidator = createSelectValidator; exports.createMultiselectValidator = createMultiselectValidator; exports.createLocationValidator = createLocationValidator; exports.createFileValidator = createFileValidator; exports.createUserValidator = createUserValidator; exports.createSingleRelationValidator = createSingleRelationValidator; exports.createMultiRelationValidator = createMultiRelationValidator; exports.createRelationValidator = createRelationValidator; exports.createRatingValidator = createRatingValidator; exports.createFormulaValidator = createFormulaValidator; exports.createRollupValidator = createRollupValidator; exports.createTextAreaValidator = createTextAreaValidator; exports.createRichtextValidator = createRichtextValidator; exports.createAttributeValidator = createAttributeValidator; exports.createFormAttributeValidator = createFormAttributeValidator; exports.createObjectValidator = createObjectValidator; exports.validateAttribute = validateAttribute; exports.validateObject = validateObject; exports.validateObjectOrThrow = validateObjectOrThrow; exports.createDraftValidator = createDraftValidator; exports.validateDraft = validateDraft; exports.validateDraftOrThrow = validateDraftOrThrow; exports.getMissingRequiredAttributes = getMissingRequiredAttributes; exports.isRecordComplete = isRecordComplete; exports.computeRecordStatus = computeRecordStatus; exports.cacheKeys = cacheKeys; exports.cacheTtl = cacheTtl; exports.NoopCacheAdapter = NoopCacheAdapter; exports.formatRecord = formatRecord; exports.formatRecords = formatRecords; exports.createDefaultState = createDefaultState; exports.SHORTCUT_TO_FILTER_OPERATOR = SHORTCUT_TO_FILTER_OPERATOR; exports.QueryNoResultError = QueryNoResultError; exports.QueryMultipleResultsError = QueryMultipleResultsError; exports.TenantContextError = TenantContextError; exports.getContext = getContext; exports.getTenantId = getTenantId; exports.getUserId = getUserId; exports.hasContext = hasContext; exports.runWithContext = runWithContext; exports.withTenantContext = withTenantContext; exports.QueryBuilder = QueryBuilder; exports.createQueryBuilder = createQueryBuilder; exports.evaluateFormula = evaluateFormula; exports.evaluateFormulaWithResult = evaluateFormulaWithResult; exports.formatFormulaResult = formatFormulaResult; exports.evaluateFormulaAttribute = evaluateFormulaAttribute; exports.validateFormulaExpression = validateFormulaExpression; exports.extractFormulaVariables = extractFormulaVariables; exports.extractRelationReferences = extractRelationReferences; exports.extractRelationNames = extractRelationNames; exports.hasRelationReferences = hasRelationReferences; exports.flattenRelationsForEval = flattenRelationsForEval; exports.evaluateFormulaWithRelations = evaluateFormulaWithRelations; exports.evaluateFormulaAttributeWithRelations = evaluateFormulaAttributeWithRelations; exports.InvalidPathError = InvalidPathError; exports.MaxDepthExceededError = MaxDepthExceededError; exports.parsePath = parsePath; exports.validatePath = validatePath; exports.pathHasManyCardinality = pathHasManyCardinality; exports.getPathDepth = getPathDepth; exports.getTargetAttributeName = getTargetAttributeName; exports.getRelationPath = getRelationPath; exports.traversePath = traversePath; exports.resolveSingleValue = resolveSingleValue; exports.resolveMultiplePaths = resolveMultiplePaths; exports.NoopHookRegistry = NoopHookRegistry; exports.DEFAULT_LABEL_FALLBACK = DEFAULT_LABEL_FALLBACK; exports.renderLabelExpression = renderLabelExpression; exports.isLabelExpression = isLabelExpression; exports.extractAttributeNames = extractAttributeNames; exports.enrichValuesWithSelectLabels = enrichValuesWithSelectLabels; exports.createMockAdapter = createMockAdapter; exports.PolicyRegistry = PolicyRegistry; exports.defaultPolicyRegistry = defaultPolicyRegistry; exports.notesPolicy = notesPolicy; exports.buildAuditChanges = buildAuditChanges; exports.TenantAwareService = TenantAwareService; exports.TenantAwareRepository = TenantAwareRepository; exports.AuditService = AuditService; exports.FileService = FileService; exports.FlowService = FlowService; exports.GeocodingService = GeocodingService; exports.GlobalSearchService = GlobalSearchService; exports.ObjectSchemaService = ObjectSchemaService; exports.PermissionService = PermissionService; exports.RelationService = RelationService; exports.RollupService = RollupService; exports.UserService = UserService; exports.RecordService = RecordService; exports.RelationResolverService = RelationResolverService; exports.RollupScheduler = RollupScheduler; exports.UserProfileService = UserProfileService; exports.ViewService = ViewService; exports.syncNativeViews = syncNativeViews; exports.verifyNativeViewsSync = verifyNativeViewsSync; exports.getViewSyncPreview = getViewSyncPreview; exports.syncNativeObjects = syncNativeObjects; exports.verifyNativeObjectsSync = verifyNativeObjectsSync; exports.getSyncPreview = getSyncPreview; exports.syncAll = syncAll;
|