@stndrds/schema 0.1.0-alpha.40 → 0.1.0-alpha.41

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.
@@ -482,7 +482,7 @@ var TenantContextError = class _TenantContextError extends Error {
482
482
  }
483
483
  };
484
484
 
485
- // src/runtime/context/tenant-context.ts
485
+ // src/runtime/context/schema-context.ts
486
486
  var browserStub = {
487
487
  getStore: () => void 0,
488
488
  run: (_store, callback) => callback()
@@ -520,8 +520,102 @@ function getStorage() {
520
520
  storageInstance = browserStub;
521
521
  return storageInstance;
522
522
  }
523
- function getContext() {
523
+ function getSchemaFromContext(objectId) {
524
+ const ctx = getStorage().getStore();
525
+ return ctx?.objectsById.get(objectId);
526
+ }
527
+ function getSchemaByNameFromContext(objectName) {
528
+ const ctx = getStorage().getStore();
529
+ return ctx?.objectsByName.get(objectName);
530
+ }
531
+ function hasSchemaContext() {
532
+ return getStorage().getStore() !== void 0;
533
+ }
534
+ function getSchemaContext() {
535
+ return getStorage().getStore();
536
+ }
537
+ function addSchemaToContext(schema) {
524
538
  const ctx = getStorage().getStore();
539
+ if (!ctx) {
540
+ return;
541
+ }
542
+ if (schema.id) {
543
+ ctx.objectsById.set(schema.id, schema);
544
+ }
545
+ ctx.objectsByName.set(schema.name, schema);
546
+ }
547
+ function buildSchemaContext(schemas) {
548
+ const objectsById = /* @__PURE__ */ new Map();
549
+ const objectsByName = /* @__PURE__ */ new Map();
550
+ for (const schema of schemas) {
551
+ if (schema.id) {
552
+ objectsById.set(schema.id, schema);
553
+ }
554
+ objectsByName.set(schema.name, schema);
555
+ }
556
+ return { objectsById, objectsByName };
557
+ }
558
+ function runWithSchemaContext(schemas, fn) {
559
+ const context = buildSchemaContext(schemas);
560
+ return getStorage().run(context, fn);
561
+ }
562
+ function runWithMergedSchemaContext(schemas, fn) {
563
+ const existing = getStorage().getStore();
564
+ const objectsById = new Map(existing?.objectsById);
565
+ const objectsByName = new Map(existing?.objectsByName);
566
+ for (const schema of schemas) {
567
+ if (schema.id) {
568
+ objectsById.set(schema.id, schema);
569
+ }
570
+ objectsByName.set(schema.name, schema);
571
+ }
572
+ const context = {
573
+ objectsById,
574
+ objectsByName
575
+ };
576
+ return getStorage().run(context, fn);
577
+ }
578
+
579
+ // src/runtime/context/tenant-context.ts
580
+ var browserStub2 = {
581
+ getStore: () => void 0,
582
+ run: (_store, callback) => callback()
583
+ };
584
+ var AsyncLocalStorageClass2 = null;
585
+ if (typeof process !== "undefined" && process.versions?.node) {
586
+ try {
587
+ if (typeof __require !== "undefined") {
588
+ const asyncHooks = __require("async_hooks");
589
+ AsyncLocalStorageClass2 = asyncHooks.AsyncLocalStorage;
590
+ }
591
+ } catch {
592
+ try {
593
+ const dynamicRequire = new Function(
594
+ "m",
595
+ 'return typeof require!=="undefined"?require(m):null'
596
+ );
597
+ const asyncHooks = dynamicRequire("node:async_hooks");
598
+ if (asyncHooks) {
599
+ AsyncLocalStorageClass2 = asyncHooks.AsyncLocalStorage;
600
+ }
601
+ } catch {
602
+ }
603
+ }
604
+ }
605
+ var storageInstance2 = null;
606
+ function getStorage2() {
607
+ if (storageInstance2 !== null) {
608
+ return storageInstance2;
609
+ }
610
+ if (AsyncLocalStorageClass2) {
611
+ storageInstance2 = new AsyncLocalStorageClass2();
612
+ return storageInstance2;
613
+ }
614
+ storageInstance2 = browserStub2;
615
+ return storageInstance2;
616
+ }
617
+ function getContext() {
618
+ const ctx = getStorage2().getStore();
525
619
  if (!ctx) {
526
620
  throw new TenantContextError();
527
621
  }
@@ -534,11 +628,11 @@ function getUserId() {
534
628
  return getContext().userId;
535
629
  }
536
630
  function hasContext() {
537
- return getStorage().getStore() !== void 0;
631
+ return getStorage2().getStore() !== void 0;
538
632
  }
539
633
  function runWithContext(context, fn) {
540
634
  const frozenContext = Object.freeze({ ...context });
541
- return getStorage().run(frozenContext, fn);
635
+ return getStorage2().run(frozenContext, fn);
542
636
  }
543
637
  function withTenantContext(tenantId, fn, userId) {
544
638
  return runWithContext({ tenantId, userId }, fn);
@@ -2315,8 +2409,14 @@ function formatCheckbox(value) {
2315
2409
  function formatNumber(value, attribute) {
2316
2410
  if (typeof value !== "number") return String(value);
2317
2411
  const decimals = attribute.decimals;
2318
- if (attribute.unit === "percentage") {
2412
+ if (attribute.unit === "integer") {
2319
2413
  return value.toLocaleString(void 0, {
2414
+ minimumFractionDigits: 0,
2415
+ maximumFractionDigits: 0
2416
+ });
2417
+ }
2418
+ if (attribute.unit === "percentage") {
2419
+ return (value / 100).toLocaleString(void 0, {
2320
2420
  style: "percent",
2321
2421
  minimumFractionDigits: decimals,
2322
2422
  maximumFractionDigits: decimals
@@ -4122,6 +4222,20 @@ var TenantAwareRepository = class {
4122
4222
  return getUserId();
4123
4223
  }
4124
4224
  };
4225
+ var SchemaContextAwareRepository = class extends TenantAwareRepository {
4226
+ /**
4227
+ * Get an ObjectDefinition from context by its ID.
4228
+ */
4229
+ getSchemaFromContext(objectId) {
4230
+ return getSchemaFromContext(objectId);
4231
+ }
4232
+ /**
4233
+ * Get an ObjectDefinition from context by its name.
4234
+ */
4235
+ getSchemaByNameFromContext(objectName) {
4236
+ return getSchemaByNameFromContext(objectName);
4237
+ }
4238
+ };
4125
4239
 
4126
4240
  // src/runtime/services/audit.service.ts
4127
4241
  var SENSITIVE_PATTERNS = [
@@ -9349,6 +9463,8 @@ var RelationService = class extends TenantAwareService {
9349
9463
  }
9350
9464
  /**
9351
9465
  * Validate a single relation attribute value
9466
+ *
9467
+ * Uses batch fetching (findByIds) to avoid N+1 query pattern.
9352
9468
  */
9353
9469
  async validateRelationAttribute(attr, value) {
9354
9470
  const errors = [];
@@ -9365,9 +9481,11 @@ var RelationService = class extends TenantAwareService {
9365
9481
  });
9366
9482
  return errors;
9367
9483
  }
9484
+ const records = await this.adapter.objectRecords.findByIds(ids);
9485
+ const recordMap = new Map(records.map((r) => [r.id, r]));
9368
9486
  const invalidIds = [];
9369
9487
  for (const id of ids) {
9370
- const record = await this.adapter.objectRecords.findById(id);
9488
+ const record = recordMap.get(id);
9371
9489
  if (!record) {
9372
9490
  invalidIds.push(id);
9373
9491
  continue;
@@ -9681,22 +9799,37 @@ var RollupService = class {
9681
9799
  return { value: null, recordCount: 0 };
9682
9800
  }
9683
9801
  const sourceObjectName = rollupAttr.relationAttribute;
9684
- const sourceObject = await this.adapter.objects.findByName(sourceObjectName);
9685
- if (!sourceObject) {
9686
- return { value: null, recordCount: 0 };
9802
+ const sourceSchema = getSchemaByNameFromContext(sourceObjectName);
9803
+ let sourceObjectId;
9804
+ let reverseRelationAttrName;
9805
+ if (sourceSchema?.id) {
9806
+ sourceObjectId = sourceSchema.id;
9807
+ const reverseRelationAttr = sourceSchema.attributes.find((attr) => {
9808
+ if (attr.type !== "relation") return false;
9809
+ const relationConfig = attr;
9810
+ return relationConfig?.targets?.some((t) => t.object === schema.name);
9811
+ });
9812
+ reverseRelationAttrName = reverseRelationAttr?.name;
9813
+ } else {
9814
+ const sourceObject = await this.adapter.objects.findByName(sourceObjectName);
9815
+ if (!sourceObject) {
9816
+ return { value: null, recordCount: 0 };
9817
+ }
9818
+ sourceObjectId = sourceObject.id;
9819
+ const sourceAttributes = await this.adapter.attributes.findByObjectId(sourceObject.id);
9820
+ const reverseRelationAttr = sourceAttributes.find((attr) => {
9821
+ if (attr.type !== "relation") return false;
9822
+ const relationConfig = attr.config;
9823
+ return relationConfig?.targets?.some((t) => t.object === schema.name);
9824
+ });
9825
+ reverseRelationAttrName = reverseRelationAttr?.name;
9687
9826
  }
9688
- const sourceAttributes = await this.adapter.attributes.findByObjectId(sourceObject.id);
9689
- const reverseRelationAttr = sourceAttributes.find((attr) => {
9690
- if (attr.type !== "relation") return false;
9691
- const relationConfig = attr.config;
9692
- return relationConfig?.targets?.some((t) => t.object === schema.name);
9693
- });
9694
- if (!reverseRelationAttr) {
9827
+ if (!reverseRelationAttrName) {
9695
9828
  return { value: null, recordCount: 0 };
9696
9829
  }
9697
9830
  const relatedRecords = await this.adapter.objectRecords.findByRelation(
9698
- sourceObject.id,
9699
- reverseRelationAttr.name,
9831
+ sourceObjectId,
9832
+ reverseRelationAttrName,
9700
9833
  recordId
9701
9834
  );
9702
9835
  if (relatedRecords.length === 0) {
@@ -10823,7 +10956,10 @@ var RecordService = class extends TenantAwareService {
10823
10956
  if (policy?.applyListFilter) {
10824
10957
  effectiveOptions = policy.applyListFilter(this.buildPolicyContext(schema.name), options);
10825
10958
  }
10826
- const result = await this.adapter.objectRecords.list(objectId, effectiveOptions);
10959
+ const result = await runWithSchemaContext(
10960
+ [schema],
10961
+ () => this.adapter.objectRecords.list(objectId, effectiveOptions)
10962
+ );
10827
10963
  let filteredRecords = result.records;
10828
10964
  let effectiveTotal = result.total;
10829
10965
  if (policy?.canAccessRecord) {
@@ -10855,7 +10991,10 @@ var RecordService = class extends TenantAwareService {
10855
10991
  if (this.permissionService && this.userId) {
10856
10992
  await this.checkPermission(schema.name, "read");
10857
10993
  }
10858
- const result = await this.adapter.objectRecords.search(objectId, query, options);
10994
+ const result = await runWithSchemaContext(
10995
+ [schema],
10996
+ () => this.adapter.objectRecords.search(objectId, query, options)
10997
+ );
10859
10998
  if (!options?.skipFormulas) {
10860
10999
  return {
10861
11000
  records: this.enrichRecordsWithFormulas(result.records, schema),
@@ -13362,6 +13501,13 @@ export {
13362
13501
  QueryNoResultError,
13363
13502
  QueryMultipleResultsError,
13364
13503
  TenantContextError,
13504
+ getSchemaFromContext,
13505
+ getSchemaByNameFromContext,
13506
+ hasSchemaContext,
13507
+ getSchemaContext,
13508
+ addSchemaToContext,
13509
+ runWithSchemaContext,
13510
+ runWithMergedSchemaContext,
13365
13511
  getContext,
13366
13512
  getTenantId,
13367
13513
  getUserId,
@@ -13423,6 +13569,7 @@ export {
13423
13569
  buildAuditChanges,
13424
13570
  TenantAwareService,
13425
13571
  TenantAwareRepository,
13572
+ SchemaContextAwareRepository,
13426
13573
  AuditService,
13427
13574
  FileService,
13428
13575
  GeocodingService,