@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.
- package/README.md +16 -6
- package/dist/bootstrap/contracts.d.ts +2 -0
- package/dist/bootstrap/httpKernel.d.ts +1 -2
- package/dist/core/admin/registry.d.ts +1 -0
- package/dist/core/auth/membershipService.d.ts +5 -1
- package/dist/core/database/baseRepository.d.ts +6 -1
- package/dist/core/database/connectionContext.d.ts +2 -1
- package/dist/core/database/defaultConnection.d.ts +6 -0
- package/dist/core/database/queryProxy.d.ts +3 -0
- package/dist/core/database/repositoryConnection.d.ts +3 -3
- package/dist/core/jobs/dispatchWebhookJob.d.ts +0 -1
- package/dist/core/security/safeFetch.d.ts +2 -0
- package/dist/core/security/safeUrl.d.ts +16 -1
- package/dist/core/storage/storage.d.ts +6 -3
- package/dist/core/tenant/tenantDatabaseScope.d.ts +2 -1
- package/dist/db/connection/index.d.ts +1 -1
- package/dist/entries/auth/accessControl.js +1 -113
- package/dist/entries/auth/authContext.js +1 -15
- package/dist/entries/auth/guard.js +1 -3044
- package/dist/entries/auth/membershipContext.js +1 -276
- package/dist/entries/auth/membershipScope.js +1 -390
- package/dist/entries/auth/membershipService.js +1 -480
- package/dist/entries/auth/policy.js +1 -134
- package/dist/entries/database.js +1 -2398
- package/dist/entries/http/csrfToken.js +0 -6
- package/dist/entries/http/middleware.js +1 -68
- package/dist/entries/http/requestMetaContext.js +1 -18
- package/dist/entries/http/webErrorResponse.js +94 -563
- package/dist/entries/http/webFormRequest.js +0 -131
- package/dist/entries/http.js +1 -4091
- package/dist/entries/jobs/dispatchWebhookJob.js +109 -102
- package/dist/entries/queue/createAppQueue.js +111 -631
- package/dist/entries/queue/jobRunner.js +0 -3
- package/dist/entries/queue/publicQueue.js +45 -546
- package/dist/entries/queue/queueMetrics.js +111 -631
- package/dist/entries/security/safeUrl.js +29 -0
- package/dist/entries/security/securityEvents.js +1 -41
- package/dist/entries/storage/storage.js +14 -4
- package/dist/entries/tenant/tenantContext.js +1 -30
- package/dist/entries/tenant/tenantMiddleware.js +1 -312
- package/dist/entries/tracing/traceContext.js +1 -15
- package/dist/entries/view.js +94 -563
- package/dist/framework/public-api.d.ts +36 -4
- package/dist/index.js +2270 -1666
- package/dist/modules/user/repository.d.ts +1 -0
- package/package.json +6 -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/
|
|
729
|
-
|
|
730
|
-
|
|
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/
|
|
752
|
-
var
|
|
753
|
-
function
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
}
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
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/
|
|
767
|
-
var
|
|
678
|
+
// ../../src/core/database/defaultConnection.ts
|
|
679
|
+
var defaultPool = {
|
|
768
680
|
connection: null
|
|
769
681
|
};
|
|
770
|
-
|
|
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
|
|
803
|
-
|
|
685
|
+
function registerDefaultDatabasePool(connection) {
|
|
686
|
+
defaultPool.connection = connection;
|
|
687
|
+
defaultQuery.connection = createDatabaseQueryProxy(connection);
|
|
804
688
|
}
|
|
805
|
-
function
|
|
806
|
-
|
|
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() ??
|
|
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(
|
|
1829
|
+
async execute(db) {
|
|
2296
1830
|
for (const statement of this.#statements) {
|
|
2297
|
-
await
|
|
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
|
|