@getstrata/core 0.5.13 → 0.5.15

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 (46) hide show
  1. package/README.md +16 -6
  2. package/dist/bootstrap/contracts.d.ts +2 -0
  3. package/dist/bootstrap/httpKernel.d.ts +1 -2
  4. package/dist/core/admin/registry.d.ts +1 -0
  5. package/dist/core/auth/membershipService.d.ts +5 -1
  6. package/dist/core/database/baseRepository.d.ts +6 -1
  7. package/dist/core/database/connectionContext.d.ts +2 -1
  8. package/dist/core/database/defaultConnection.d.ts +6 -0
  9. package/dist/core/database/queryProxy.d.ts +3 -0
  10. package/dist/core/database/repositoryConnection.d.ts +3 -3
  11. package/dist/core/jobs/dispatchWebhookJob.d.ts +0 -1
  12. package/dist/core/security/safeFetch.d.ts +2 -0
  13. package/dist/core/security/safeUrl.d.ts +16 -1
  14. package/dist/core/storage/storage.d.ts +6 -3
  15. package/dist/core/tenant/tenantDatabaseScope.d.ts +2 -1
  16. package/dist/db/connection/index.d.ts +1 -1
  17. package/dist/entries/auth/accessControl.js +1 -113
  18. package/dist/entries/auth/authContext.js +1 -15
  19. package/dist/entries/auth/guard.js +1 -3044
  20. package/dist/entries/auth/membershipContext.js +1 -276
  21. package/dist/entries/auth/membershipScope.js +1 -390
  22. package/dist/entries/auth/membershipService.js +1 -480
  23. package/dist/entries/auth/policy.js +1 -134
  24. package/dist/entries/database.js +1 -2398
  25. package/dist/entries/http/csrfToken.js +0 -6
  26. package/dist/entries/http/middleware.js +1 -68
  27. package/dist/entries/http/requestMetaContext.js +1 -18
  28. package/dist/entries/http/webErrorResponse.js +94 -563
  29. package/dist/entries/http/webFormRequest.js +0 -131
  30. package/dist/entries/http.js +1 -4091
  31. package/dist/entries/jobs/dispatchWebhookJob.js +109 -102
  32. package/dist/entries/queue/createAppQueue.js +111 -631
  33. package/dist/entries/queue/jobRunner.js +0 -3
  34. package/dist/entries/queue/publicQueue.js +45 -546
  35. package/dist/entries/queue/queueMetrics.js +111 -631
  36. package/dist/entries/security/safeUrl.js +29 -0
  37. package/dist/entries/security/securityEvents.js +1 -41
  38. package/dist/entries/storage/storage.js +14 -4
  39. package/dist/entries/tenant/tenantContext.js +1 -30
  40. package/dist/entries/tenant/tenantMiddleware.js +1 -312
  41. package/dist/entries/tracing/traceContext.js +1 -15
  42. package/dist/entries/view.js +94 -563
  43. package/dist/framework/public-api.d.ts +36 -4
  44. package/dist/index.js +2270 -1666
  45. package/dist/modules/user/repository.d.ts +1 -0
  46. package/package.json +6 -5
@@ -1,8 +1,5 @@
1
1
  // @bun
2
2
  // ../../src/bootstrap/config.ts
3
- var CORE_QUEUE_TOKEN = "core.queue";
4
- var CORE_POLICY_GATE_TOKEN = "core.policyGate";
5
- var CORE_AUTH_TOKEN = "core.auth";
6
3
  var CORE_TOKEN_SERVICE_TOKEN = "core.tokenService";
7
4
  var DEFAULT_QUEUE_DRIVER = "sync";
8
5
 
@@ -270,14 +270,6 @@ function appendWhereParts(tableName, where, params) {
270
270
  }
271
271
  return clauses.join(" AND ");
272
272
  }
273
- function buildWhereClause(tableName, where = {}) {
274
- const params = [];
275
- const body = appendWhereParts(tableName, where, params);
276
- return {
277
- clause: body.length > 0 ? ` WHERE ${body}` : "",
278
- params
279
- };
280
- }
281
273
  function buildWhereNodeClause(tableName, node, params) {
282
274
  if ("where" in node) {
283
275
  return appendWhereParts(tableName, node.where, params);
@@ -580,30 +572,6 @@ function buildDeleteByIdQuery(table, id) {
580
572
  }
581
573
 
582
574
  // ../../src/core/database/relationships.ts
583
- function hasMany(definition) {
584
- return {
585
- type: "hasMany",
586
- ...definition
587
- };
588
- }
589
- function hasOne(definition) {
590
- return {
591
- type: "hasOne",
592
- ...definition
593
- };
594
- }
595
- function belongsTo(definition) {
596
- return {
597
- type: "belongsTo",
598
- ...definition
599
- };
600
- }
601
- function belongsToMany(definition) {
602
- return {
603
- type: "belongsToMany",
604
- ...definition
605
- };
606
- }
607
575
  function indexHasManyRelation(parents, children, relation) {
608
576
  const groups = new Map;
609
577
  for (const parent of parents) {
@@ -619,15 +587,6 @@ function indexHasManyRelation(parents, children, relation) {
619
587
  }
620
588
  return groups;
621
589
  }
622
- function indexHasOneRelation(parents, children, relation) {
623
- const grouped = indexHasManyRelation(parents, children, relation);
624
- const result = new Map;
625
- for (const parent of parents) {
626
- const matches = grouped.get(parent[relation.localKey]) ?? [];
627
- result.set(parent[relation.localKey], matches[0]);
628
- }
629
- return result;
630
- }
631
590
  function indexBelongsToRelation(children, parents, relation) {
632
591
  const parentsById = new Map;
633
592
  for (const parent of parents) {
@@ -643,45 +602,6 @@ function indexBelongsToRelation(children, parents, relation) {
643
602
  }
644
603
  return result;
645
604
  }
646
- function indexBelongsToManyRelation(parents, pivotRows, relatedRows, relation) {
647
- const relatedById = new Map;
648
- for (const related of relatedRows) {
649
- relatedById.set(related[relation.relatedKey], related);
650
- }
651
- const groups = new Map;
652
- for (const parent of parents) {
653
- groups.set(parent[relation.parentKey], []);
654
- }
655
- for (const pivot of pivotRows) {
656
- const parentId = pivot[relation.foreignPivotKey];
657
- const relatedId = pivot[relation.relatedPivotKey];
658
- const group = groups.get(parentId);
659
- const related = relatedById.get(relatedId);
660
- if (!group || !related) {
661
- continue;
662
- }
663
- group.push(related);
664
- }
665
- return groups;
666
- }
667
- function morphMany(definition) {
668
- return {
669
- type: "morphMany",
670
- ...definition
671
- };
672
- }
673
- function morphOne(definition) {
674
- return {
675
- type: "morphOne",
676
- ...definition
677
- };
678
- }
679
- function morphTo(definition) {
680
- return {
681
- type: "morphTo",
682
- ...definition
683
- };
684
- }
685
605
  function indexMorphManyRelation(parents, children, relation) {
686
606
  const groups = new Map;
687
607
  for (const parent of parents) {
@@ -700,15 +620,6 @@ function indexMorphManyRelation(parents, children, relation) {
700
620
  }
701
621
  return groups;
702
622
  }
703
- function indexMorphOneRelation(parents, children, relation) {
704
- const grouped = indexMorphManyRelation(parents, children, relation);
705
- const result = new Map;
706
- for (const parent of parents) {
707
- const matches = grouped.get(parent[relation.localKey]) ?? [];
708
- result.set(parent[relation.localKey], matches[0]);
709
- }
710
- return result;
711
- }
712
623
  function indexMorphToRelation(children, parentsByType, relation) {
713
624
  const result = new Map;
714
625
  for (const child of children) {
@@ -725,92 +636,71 @@ function indexMorphToRelation(children, parentsByType, relation) {
725
636
  return result;
726
637
  }
727
638
 
728
- // ../../src/config/database.ts
729
- function readInteger(name, fallback) {
730
- const parsed = Number.parseInt(process.env[name] ?? String(fallback), 10);
731
- return Number.isInteger(parsed) && parsed >= 0 ? parsed : fallback;
732
- }
733
- var databaseConfig = {
734
- url: process.env.DATABASE_URL ?? "",
735
- poolMax: readInteger("DB_POOL_MAX", 10),
736
- idleTimeoutSeconds: readInteger("DB_POOL_IDLE_TIMEOUT", 30),
737
- maxLifetimeSeconds: readInteger("DB_POOL_MAX_LIFETIME", 3600),
738
- connectionTimeoutSeconds: readInteger("DB_CONNECTION_TIMEOUT", 10)
639
+ // ../../src/core/database/boundConnection.ts
640
+ var boundConnectionHolder = {
641
+ connection: null
739
642
  };
643
+ function getBoundDatabaseConnection() {
644
+ return boundConnectionHolder.connection;
645
+ }
740
646
 
741
647
  // ../../src/core/database/connectionContext.ts
742
648
  import { AsyncLocalStorage } from "async_hooks";
743
649
  var activeConnection = new AsyncLocalStorage;
744
- function runWithDatabaseConnection(connection, callback) {
745
- return activeConnection.run(connection, callback);
746
- }
747
650
  function getActiveDatabaseConnection(fallback) {
748
651
  return activeConnection.getStore() ?? fallback;
749
652
  }
750
653
 
751
- // ../../src/db/connection/createConnection.ts
752
- var {SQL } = globalThis.Bun;
753
- function createDatabaseConnection(config) {
754
- if (!config.url) {
755
- throw new Error("DATABASE_URL is not configured. Set DATABASE_URL before starting the app or running integration tests.");
756
- }
757
- return new SQL({
758
- url: config.url,
759
- max: config.poolMax,
760
- idleTimeout: config.idleTimeoutSeconds,
761
- maxLifetime: config.maxLifetimeSeconds,
762
- connectionTimeout: config.connectionTimeoutSeconds
654
+ // ../../src/core/database/queryProxy.ts
655
+ var POOL_CONNECTION_METHODS = new Set(["begin", "close", "connect"]);
656
+ function createDatabaseQueryProxy(pool) {
657
+ function resolveDatabase() {
658
+ return getActiveDatabaseConnection(pool);
659
+ }
660
+ function resolveDatabaseForProperty(property) {
661
+ if (typeof property === "string" && POOL_CONNECTION_METHODS.has(property)) {
662
+ return pool;
663
+ }
664
+ return resolveDatabase();
665
+ }
666
+ return new Proxy(function database() {}, {
667
+ apply(_target, _thisArg, args) {
668
+ return resolveDatabase()(...args);
669
+ },
670
+ get(_target, property) {
671
+ const connection = resolveDatabaseForProperty(property);
672
+ const value = connection[property];
673
+ return typeof value === "function" ? value.bind(connection) : value;
674
+ }
763
675
  });
764
676
  }
765
677
 
766
- // ../../src/db/connection/index.ts
767
- var connectionHolder = {
678
+ // ../../src/core/database/defaultConnection.ts
679
+ var defaultPool = {
768
680
  connection: null
769
681
  };
770
- function getDatabase() {
771
- if (!connectionHolder.connection) {
772
- connectionHolder.connection = createDatabaseConnection(databaseConfig);
773
- }
774
- return connectionHolder.connection;
775
- }
776
- var POOL_CONNECTION_METHODS = new Set(["begin", "close", "connect"]);
777
- function resolveDatabase() {
778
- return getActiveDatabaseConnection(getDatabase());
779
- }
780
- function resolveDatabaseForProperty(property) {
781
- if (typeof property === "string" && POOL_CONNECTION_METHODS.has(property)) {
782
- return getDatabase();
783
- }
784
- return resolveDatabase();
785
- }
786
- var db = new Proxy(function database() {}, {
787
- apply(_target, _thisArg, args) {
788
- return resolveDatabase()(...args);
789
- },
790
- get(_target, property) {
791
- const connection = resolveDatabaseForProperty(property);
792
- const value = connection[property];
793
- return typeof value === "function" ? value.bind(connection) : value;
794
- }
795
- });
796
- var connection_default = db;
797
-
798
- // ../../src/core/database/boundConnection.ts
799
- var boundConnectionHolder = {
682
+ var defaultQuery = {
800
683
  connection: null
801
684
  };
802
- function bindDatabaseConnection(connection) {
803
- boundConnectionHolder.connection = connection;
685
+ function registerDefaultDatabasePool(connection) {
686
+ defaultPool.connection = connection;
687
+ defaultQuery.connection = createDatabaseQueryProxy(connection);
804
688
  }
805
- function getBoundDatabaseConnection() {
806
- return boundConnectionHolder.connection;
689
+ function getDefaultDatabaseQuery() {
690
+ if (!defaultQuery.connection) {
691
+ throw new Error("Default database query handle is not registered. Call registerDefaultDatabasePool() during app bootstrap.");
692
+ }
693
+ return defaultQuery.connection;
807
694
  }
808
695
 
809
696
  // ../../src/core/database/repositoryConnection.ts
810
697
  function resolveRepositoryConnection() {
811
- return getBoundDatabaseConnection() ?? connection_default;
698
+ return getBoundDatabaseConnection() ?? getDefaultDatabaseQuery();
812
699
  }
813
- var repositoryConnection = new Proxy({}, {
700
+ var repositoryConnection = new Proxy(function repositoryConnection2() {}, {
701
+ apply(_target, _thisArg, args) {
702
+ return resolveRepositoryConnection()(...args);
703
+ },
814
704
  get(_target, property) {
815
705
  const connection = resolveRepositoryConnection();
816
706
  const value = connection[property];
@@ -1373,327 +1263,10 @@ class BaseRepository {
1373
1263
  }
1374
1264
  }
1375
1265
  var baseRepository_default = BaseRepository;
1376
- // ../../src/core/database/connection.ts
1377
- function createDatabaseConnection2(source) {
1378
- return {
1379
- async unsafe(query, params = []) {
1380
- return await source.unsafe(query, params);
1381
- }
1382
- };
1383
- }
1384
1266
  // ../../src/core/database/model.ts
1385
1267
  var modelRepositories = new WeakMap;
1386
1268
  var modelGlobalScopes = new WeakMap;
1387
1269
  var modelBooted = new WeakSet;
1388
- function resolveModelRepository(model) {
1389
- const repository = modelRepositories.get(model);
1390
- if (!repository) {
1391
- throw new Error(`${model.name}.repository() is not implemented.`);
1392
- }
1393
- return repository;
1394
- }
1395
- function modelStatics(model) {
1396
- return model;
1397
- }
1398
- function ensureBooted(model) {
1399
- if (modelBooted.has(model)) {
1400
- return;
1401
- }
1402
- modelBooted.add(model);
1403
- const boot = model.boot;
1404
- if (typeof boot === "function") {
1405
- boot.call(model);
1406
- }
1407
- }
1408
- function getGlobalScopes(model) {
1409
- return modelGlobalScopes.get(model) ?? [];
1410
- }
1411
- function hydrateValue(value, cast) {
1412
- if (value === null || value === undefined) {
1413
- return value;
1414
- }
1415
- switch (cast) {
1416
- case "date":
1417
- case "datetime":
1418
- return value instanceof Date ? value : new Date(String(value));
1419
- case "json":
1420
- return typeof value === "string" ? JSON.parse(value) : value;
1421
- case "bool":
1422
- case "boolean":
1423
- return value === true || value === 1 || value === "1" || value === "true";
1424
- default:
1425
- return value;
1426
- }
1427
- }
1428
- function dehydrateValue(value, cast) {
1429
- if (value === null || value === undefined) {
1430
- return value;
1431
- }
1432
- switch (cast) {
1433
- case "date":
1434
- case "datetime":
1435
- return value instanceof Date ? value : new Date(String(value));
1436
- case "json":
1437
- return typeof value === "string" ? value : JSON.stringify(value);
1438
- case "bool":
1439
- case "boolean":
1440
- return Boolean(value);
1441
- default:
1442
- return value;
1443
- }
1444
- }
1445
- function filterMassAssignable(fillable, guarded, input) {
1446
- const resolvedGuarded = guarded ?? true;
1447
- if (fillable && fillable.length > 0) {
1448
- const allowed = new Set(fillable);
1449
- return Object.fromEntries(Object.entries(input).filter(([key]) => allowed.has(key)));
1450
- }
1451
- if (resolvedGuarded === true || resolvedGuarded.includes("*")) {
1452
- return {};
1453
- }
1454
- const blocked = new Set(resolvedGuarded);
1455
- return Object.fromEntries(Object.entries(input).filter(([key]) => !blocked.has(key)));
1456
- }
1457
- function applyCasts(values, casts, direction) {
1458
- if (Object.keys(casts).length === 0) {
1459
- return values;
1460
- }
1461
- const result = { ...values };
1462
- const castFn = direction === "hydrate" ? hydrateValue : dehydrateValue;
1463
- for (const [key, cast] of Object.entries(casts)) {
1464
- if (key in result && cast) {
1465
- result[key] = castFn(result[key], cast);
1466
- }
1467
- }
1468
- return result;
1469
- }
1470
- function applyTimestampsOnCreate(columns, values, enabled) {
1471
- if (!enabled) {
1472
- return values;
1473
- }
1474
- const now = new Date;
1475
- const result = { ...values };
1476
- if (columns.includes("created_at")) {
1477
- result.created_at = now;
1478
- }
1479
- if (columns.includes("updated_at")) {
1480
- result.updated_at = now;
1481
- }
1482
- return result;
1483
- }
1484
- function applyTimestampsOnUpdate(columns, values, enabled) {
1485
- if (!enabled) {
1486
- return values;
1487
- }
1488
- const result = { ...values };
1489
- if (columns.includes("updated_at")) {
1490
- result.updated_at = new Date;
1491
- }
1492
- return result;
1493
- }
1494
-
1495
- class Model {
1496
- attributes;
1497
- repository;
1498
- static $fillable;
1499
- static $guarded;
1500
- static $casts = {};
1501
- static $timestamps = true;
1502
- _exists;
1503
- constructor(attributes, repository, exists = true) {
1504
- this.attributes = attributes;
1505
- this.repository = repository;
1506
- this._exists = exists;
1507
- }
1508
- get $exists() {
1509
- return this._exists;
1510
- }
1511
- get(key) {
1512
- return this.attributes[key];
1513
- }
1514
- get id() {
1515
- return this.attributes[this.primaryKey()];
1516
- }
1517
- toObject() {
1518
- return { ...this.attributes };
1519
- }
1520
- primaryKey() {
1521
- throw new Error(`${this.constructor.name}.primaryKey() is not implemented.`);
1522
- }
1523
- static primaryKeyField() {
1524
- return resolveModelRepository(this).getTable().primaryKey;
1525
- }
1526
- static hydrateAttributes(attributes) {
1527
- const casts = modelStatics(this).$casts ?? {};
1528
- return applyCasts(attributes, casts, "hydrate");
1529
- }
1530
- static dehydrateAttributes(attributes) {
1531
- const casts = modelStatics(this).$casts ?? {};
1532
- return applyCasts(attributes, casts, "dehydrate");
1533
- }
1534
- static fromRecord(record, repository, exists = true) {
1535
- const statics = modelStatics(this);
1536
- const hydrated = statics.hydrateAttributes(record);
1537
- return new statics(hydrated, repository, exists);
1538
- }
1539
- static boot() {}
1540
- static addGlobalScope(_name, scope) {
1541
- ensureBooted(this);
1542
- const existing = modelGlobalScopes.get(this) ?? [];
1543
- modelGlobalScopes.set(this, [
1544
- ...existing,
1545
- scope
1546
- ]);
1547
- }
1548
- static repository() {
1549
- return resolveModelRepository(this);
1550
- }
1551
- static query() {
1552
- ensureBooted(this);
1553
- const repository = resolveModelRepository(this);
1554
- let query = repository.query();
1555
- for (const scope of getGlobalScopes(this)) {
1556
- query = scope(query);
1557
- }
1558
- return query;
1559
- }
1560
- static async create(attributes) {
1561
- const statics = modelStatics(this);
1562
- ensureBooted(this);
1563
- const repository = resolveModelRepository(this);
1564
- const table = repository.getTable();
1565
- const timestamps = statics.$timestamps ?? true;
1566
- const assignable = filterMassAssignable(statics.$fillable, statics.$guarded, attributes);
1567
- const withTimestamps = applyTimestampsOnCreate(table.columns, assignable, timestamps);
1568
- const payload = statics.dehydrateAttributes(withTimestamps);
1569
- const record = await repository.create(payload);
1570
- return statics.fromRecord(record, repository, true);
1571
- }
1572
- static async find(id) {
1573
- const statics = modelStatics(this);
1574
- const repository = resolveModelRepository(this);
1575
- const primaryKey = repository.getTable().primaryKey;
1576
- const record = await Model.query.call(this).where({ [primaryKey]: id }).first();
1577
- return record ? statics.fromRecord(record, repository, true) : null;
1578
- }
1579
- static async findOrFail(id, errorFactory) {
1580
- const model = await Model.find.call(this, id);
1581
- if (model) {
1582
- return model;
1583
- }
1584
- throw errorFactory?.(id) ?? new NotFoundError(`${this.name} ${String(id)} not found.`);
1585
- }
1586
- static async all(options = {}) {
1587
- const statics = modelStatics(this);
1588
- const repository = resolveModelRepository(this);
1589
- let query = Model.query.call(this);
1590
- if (options.orderBy) {
1591
- query = query.orderBy(options.orderBy);
1592
- }
1593
- if (options.limit !== undefined) {
1594
- query = query.limit(options.limit);
1595
- }
1596
- const rows = await query.get();
1597
- return rows.map((row) => statics.fromRecord(row, repository, true));
1598
- }
1599
- static async firstWhere(where, options = {}) {
1600
- const statics = modelStatics(this);
1601
- const repository = resolveModelRepository(this);
1602
- let query = Model.query.call(this).where(where);
1603
- if (options.orderBy) {
1604
- query = query.orderBy(options.orderBy);
1605
- }
1606
- const record = await query.first();
1607
- return record ? statics.fromRecord(record, repository, true) : null;
1608
- }
1609
- async save() {
1610
- const ModelClass = modelStatics(this.constructor);
1611
- const timestamps = ModelClass.$timestamps ?? true;
1612
- const casts = ModelClass.$casts ?? {};
1613
- const table = this.repository.getTable();
1614
- if (this.$exists) {
1615
- const changes = applyTimestampsOnUpdate(table.columns, applyCasts(this.attributes, casts, "dehydrate"), timestamps);
1616
- const record2 = await this.repository.updateByIdOrThrow(this.id, changes);
1617
- this.attributes = ModelClass.hydrateAttributes(record2);
1618
- return this;
1619
- }
1620
- const assignable = filterMassAssignable(ModelClass.$fillable, ModelClass.$guarded, this.attributes);
1621
- const withTimestamps = applyTimestampsOnCreate(table.columns, assignable, timestamps);
1622
- const payload = ModelClass.dehydrateAttributes(withTimestamps);
1623
- const record = await this.repository.create(payload);
1624
- this.attributes = ModelClass.hydrateAttributes(record);
1625
- this._exists = true;
1626
- return this;
1627
- }
1628
- async update(changes) {
1629
- const ModelClass = modelStatics(this.constructor);
1630
- const assignable = filterMassAssignable(ModelClass.$fillable, ModelClass.$guarded, changes);
1631
- Object.assign(this.attributes, assignable);
1632
- return await this.save();
1633
- }
1634
- async delete() {
1635
- if (resolveSoftDeleteColumn(this.repository.getTable())) {
1636
- return await this.repository.deleteById(this.id);
1637
- }
1638
- return await this.repository.forceDeleteById(this.id);
1639
- }
1640
- async forceDelete() {
1641
- return await this.repository.forceDeleteById(this.id);
1642
- }
1643
- async restore() {
1644
- const ModelClass = modelStatics(this.constructor);
1645
- const record = await this.repository.restoreById(this.id);
1646
- if (!record) {
1647
- return null;
1648
- }
1649
- this.attributes = ModelClass.hydrateAttributes(record);
1650
- return this;
1651
- }
1652
- async loadHasMany(as, relation, childRepository, options = {}) {
1653
- const grouped = await childRepository.withConnection(this.repository.getConnection()).loadHasManyForParents([this.attributes], relation, options);
1654
- const loaded = grouped.get(this.attributes[relation.localKey]) ?? [];
1655
- return Object.assign(this, { [as]: loaded });
1656
- }
1657
- async loadHasOne(as, relation, childRepository, options = {}) {
1658
- const loaded = await this.loadHasMany(as, relation, childRepository, { ...options, limit: 1 });
1659
- const value = loaded[as]?.[0];
1660
- return Object.assign(this, { [as]: value });
1661
- }
1662
- async loadBelongsTo(as, relation, parentRepository, options = {}) {
1663
- const grouped = await this.repository.loadBelongsToForParents([this.attributes], relation, parentRepository, options);
1664
- const loaded = grouped.get(this.attributes[relation.foreignKey]);
1665
- return Object.assign(this, { [as]: loaded });
1666
- }
1667
- async loadBelongsToMany(as, relation, relatedRepository, options = {}) {
1668
- const connection = this.repository.getConnection();
1669
- const parentId = this.attributes[relation.parentKey];
1670
- const pivotRows = await connection.unsafe(`SELECT * FROM ${relation.pivotTable} WHERE ${String(relation.foreignPivotKey)} = $1`, [parentId]);
1671
- if (pivotRows.length === 0) {
1672
- return Object.assign(this, { [as]: [] });
1673
- }
1674
- const relatedIds = [
1675
- ...new Set(pivotRows.map((row) => row[relation.relatedPivotKey]))
1676
- ];
1677
- const relatedRows = await relatedRepository.withConnection(connection).findAll({
1678
- ...options,
1679
- where: {
1680
- [relation.relatedKey]: relatedIds
1681
- }
1682
- });
1683
- const grouped = indexBelongsToManyRelation([this.attributes], pivotRows, relatedRows, relation);
1684
- const loaded = grouped.get(parentId) ?? [];
1685
- return Object.assign(this, { [as]: loaded });
1686
- }
1687
- mergeAttributes(patch) {
1688
- Object.assign(this.attributes, patch);
1689
- return this;
1690
- }
1691
- }
1692
- function registerModelRepository(model, repository) {
1693
- modelRepositories.set(model, repository);
1694
- ensureBooted(model);
1695
- return model;
1696
- }
1697
1270
  // ../../src/core/database/schema/columnDefinition.ts
1698
1271
  class ColumnDefinition {
1699
1272
  name;
@@ -1915,45 +1488,6 @@ class Blueprint {
1915
1488
  });
1916
1489
  }
1917
1490
  }
1918
- // ../../src/core/database/schema/driver.ts
1919
- function normalizeConnectionName(connection) {
1920
- const normalized = connection.trim().toLowerCase();
1921
- if (normalized === "pgsql" || normalized === "postgres" || normalized === "postgresql") {
1922
- return "pgsql";
1923
- }
1924
- if (normalized === "mysql" || normalized === "mariadb") {
1925
- return "mysql";
1926
- }
1927
- if (normalized === "sqlite") {
1928
- return "sqlite";
1929
- }
1930
- throw new Error(`Unsupported DB_CONNECTION: ${connection}`);
1931
- }
1932
- function resolveDriverFromUrl(url) {
1933
- const normalized = url.trim().toLowerCase();
1934
- if (normalized.startsWith("postgres://") || normalized.startsWith("postgresql://") || normalized.startsWith("postgres:")) {
1935
- return "pgsql";
1936
- }
1937
- if (normalized.startsWith("mysql://") || normalized.startsWith("mysql:")) {
1938
- return "mysql";
1939
- }
1940
- if (normalized.startsWith("sqlite:")) {
1941
- return "sqlite";
1942
- }
1943
- return null;
1944
- }
1945
- function resolveDatabaseDriver(options = {}) {
1946
- const connection = options.connection ?? process.env.DB_CONNECTION;
1947
- if (connection) {
1948
- return normalizeConnectionName(connection);
1949
- }
1950
- const url = options.url ?? process.env.DATABASE_URL ?? "";
1951
- const fromUrl = resolveDriverFromUrl(url);
1952
- if (fromUrl) {
1953
- return fromUrl;
1954
- }
1955
- return "pgsql";
1956
- }
1957
1491
  // ../../src/core/database/schema/errors.ts
1958
1492
  class UnsupportedSchemaFeatureError extends Error {
1959
1493
  constructor(feature, driver) {
@@ -2292,48 +1826,16 @@ class SchemaBuilder {
2292
1826
  toSql() {
2293
1827
  return [...this.#statements];
2294
1828
  }
2295
- async execute(db2) {
1829
+ async execute(db) {
2296
1830
  for (const statement of this.#statements) {
2297
- await db2.unsafe(statement);
1831
+ await db.unsafe(statement);
2298
1832
  }
2299
1833
  }
2300
1834
  }
2301
-
2302
- class Schema {
2303
- static builder(driver) {
2304
- return new SchemaBuilder(driver ?? resolveDatabaseDriver());
2305
- }
2306
- static async run(db2, driver, callback) {
2307
- const schema = Schema.builder(driver);
2308
- await callback(schema);
2309
- await schema.execute(db2);
2310
- }
2311
- }
2312
- function createSchemaBuilder(db2, driver) {
2313
- const builder = Schema.builder(driver);
2314
- return Object.assign(builder, {
2315
- async commit() {
2316
- await builder.execute(db2);
2317
- }
2318
- });
2319
- }
2320
1835
  // ../../src/core/database/table.ts
2321
1836
  function defineTable(definition) {
2322
1837
  return definition;
2323
1838
  }
2324
- // ../../src/core/database/transaction.ts
2325
- function supportsTransactions(connection) {
2326
- return typeof connection.begin === "function";
2327
- }
2328
- async function runInTransaction(operation) {
2329
- const pool = resolveRepositoryConnection();
2330
- if (!supportsTransactions(pool)) {
2331
- throw new Error("Active database connection does not support transactions. Bind a client with begin() via bindDatabaseConnection.");
2332
- }
2333
- return await pool.begin(async (transaction) => {
2334
- return await operation(createDatabaseConnection2(transaction));
2335
- });
2336
- }
2337
1839
  // ../../src/core/queue/failedJobTable.ts
2338
1840
  var failedJobTable = defineTable({
2339
1841
  name: "failed_job",
@@ -2423,9 +1925,6 @@ class JobRegistry {
2423
1925
  var jobRegistry = new JobRegistry;
2424
1926
 
2425
1927
  // ../../src/bootstrap/config.ts
2426
- var CORE_QUEUE_TOKEN = "core.queue";
2427
- var CORE_POLICY_GATE_TOKEN = "core.policyGate";
2428
- var CORE_AUTH_TOKEN = "core.auth";
2429
1928
  var CORE_TOKEN_SERVICE_TOKEN = "core.tokenService";
2430
1929
  var DEFAULT_QUEUE_DRIVER = "sync";
2431
1930