@getstrata/core 0.5.10 → 0.5.13
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/core/admin/formatValue.d.ts +3 -0
- package/dist/core/admin/index.d.ts +3 -0
- package/dist/core/admin/registry.d.ts +10 -0
- package/dist/core/admin/types.d.ts +24 -0
- package/dist/core/database/baseRepository.d.ts +4 -1
- package/dist/core/database/index.d.ts +2 -2
- package/dist/core/database/relationships.d.ts +46 -2
- package/dist/core/database/repositoryQuery.d.ts +4 -1
- package/dist/core/mail/mailer.d.ts +3 -1
- package/dist/core/mail/markdownMail.d.ts +15 -0
- package/dist/core/mail/markdownMailable.d.ts +12 -0
- package/dist/core/notifications/dispatcher.d.ts +13 -0
- package/dist/core/notifications/index.d.ts +3 -0
- package/dist/core/notifications/notification.d.ts +7 -0
- package/dist/core/notifications/types.d.ts +25 -0
- package/dist/core/queue/failedJobService.d.ts +1 -0
- package/dist/core/queue/publicQueue.d.ts +2 -1
- package/dist/entries/auth/guard.js +168 -0
- package/dist/entries/database.js +174 -0
- package/dist/entries/http/webErrorResponse.js +168 -0
- package/dist/entries/http.js +168 -0
- package/dist/entries/queue/createAppQueue.js +175 -3
- package/dist/entries/queue/failedJobService.js +6 -0
- package/dist/entries/queue/publicQueue.js +176 -3
- package/dist/entries/queue/queueMetrics.js +175 -3
- package/dist/entries/view.js +168 -0
- package/dist/framework/public-api.d.ts +12 -4
- package/dist/index.js +421 -17
- package/package.json +1 -1
|
@@ -1132,6 +1132,66 @@ function indexBelongsToManyRelation(parents, pivotRows, relatedRows, relation) {
|
|
|
1132
1132
|
}
|
|
1133
1133
|
return groups;
|
|
1134
1134
|
}
|
|
1135
|
+
function morphMany(definition) {
|
|
1136
|
+
return {
|
|
1137
|
+
type: "morphMany",
|
|
1138
|
+
...definition
|
|
1139
|
+
};
|
|
1140
|
+
}
|
|
1141
|
+
function morphOne(definition) {
|
|
1142
|
+
return {
|
|
1143
|
+
type: "morphOne",
|
|
1144
|
+
...definition
|
|
1145
|
+
};
|
|
1146
|
+
}
|
|
1147
|
+
function morphTo(definition) {
|
|
1148
|
+
return {
|
|
1149
|
+
type: "morphTo",
|
|
1150
|
+
...definition
|
|
1151
|
+
};
|
|
1152
|
+
}
|
|
1153
|
+
function indexMorphManyRelation(parents, children, relation) {
|
|
1154
|
+
const groups = new Map;
|
|
1155
|
+
for (const parent of parents) {
|
|
1156
|
+
groups.set(parent[relation.localKey], []);
|
|
1157
|
+
}
|
|
1158
|
+
for (const child of children) {
|
|
1159
|
+
if (child[relation.morphTypeKey] !== relation.morphType) {
|
|
1160
|
+
continue;
|
|
1161
|
+
}
|
|
1162
|
+
const key = child[relation.morphIdKey];
|
|
1163
|
+
const group = groups.get(key);
|
|
1164
|
+
if (!group) {
|
|
1165
|
+
continue;
|
|
1166
|
+
}
|
|
1167
|
+
group.push(child);
|
|
1168
|
+
}
|
|
1169
|
+
return groups;
|
|
1170
|
+
}
|
|
1171
|
+
function indexMorphOneRelation(parents, children, relation) {
|
|
1172
|
+
const grouped = indexMorphManyRelation(parents, children, relation);
|
|
1173
|
+
const result = new Map;
|
|
1174
|
+
for (const parent of parents) {
|
|
1175
|
+
const matches = grouped.get(parent[relation.localKey]) ?? [];
|
|
1176
|
+
result.set(parent[relation.localKey], matches[0]);
|
|
1177
|
+
}
|
|
1178
|
+
return result;
|
|
1179
|
+
}
|
|
1180
|
+
function indexMorphToRelation(children, parentsByType, relation) {
|
|
1181
|
+
const result = new Map;
|
|
1182
|
+
for (const child of children) {
|
|
1183
|
+
const morphType = String(child[relation.morphTypeKey]);
|
|
1184
|
+
const parents = parentsByType.get(morphType);
|
|
1185
|
+
if (!parents) {
|
|
1186
|
+
continue;
|
|
1187
|
+
}
|
|
1188
|
+
const parent = parents.get(child[relation.morphIdKey]);
|
|
1189
|
+
if (parent) {
|
|
1190
|
+
result.set(child[relation.morphIdKey], parent);
|
|
1191
|
+
}
|
|
1192
|
+
}
|
|
1193
|
+
return result;
|
|
1194
|
+
}
|
|
1135
1195
|
|
|
1136
1196
|
// ../../src/core/database/boundConnection.ts
|
|
1137
1197
|
var boundConnectionHolder = {
|
|
@@ -1265,6 +1325,37 @@ class RepositoryQuery {
|
|
|
1265
1325
|
});
|
|
1266
1326
|
return this;
|
|
1267
1327
|
}
|
|
1328
|
+
withMorphMany(as, relation, childRepository, options = {}) {
|
|
1329
|
+
this.eagerLoads.push({
|
|
1330
|
+
kind: "morphMany",
|
|
1331
|
+
as,
|
|
1332
|
+
relation,
|
|
1333
|
+
repository: childRepository,
|
|
1334
|
+
options
|
|
1335
|
+
});
|
|
1336
|
+
return this;
|
|
1337
|
+
}
|
|
1338
|
+
withMorphOne(as, relation, childRepository, options = {}) {
|
|
1339
|
+
this.eagerLoads.push({
|
|
1340
|
+
kind: "morphOne",
|
|
1341
|
+
as,
|
|
1342
|
+
relation,
|
|
1343
|
+
repository: childRepository,
|
|
1344
|
+
options
|
|
1345
|
+
});
|
|
1346
|
+
return this;
|
|
1347
|
+
}
|
|
1348
|
+
withMorphTo(as, relation, repositoriesByType, options = {}) {
|
|
1349
|
+
this.eagerLoads.push({
|
|
1350
|
+
kind: "morphTo",
|
|
1351
|
+
as,
|
|
1352
|
+
relation,
|
|
1353
|
+
repository: this.repository,
|
|
1354
|
+
morphRepositories: repositoriesByType,
|
|
1355
|
+
options
|
|
1356
|
+
});
|
|
1357
|
+
return this;
|
|
1358
|
+
}
|
|
1268
1359
|
async get() {
|
|
1269
1360
|
const rows = await this.repository.findAll(this.buildOptions());
|
|
1270
1361
|
return await this.attach(rows);
|
|
@@ -1325,6 +1416,33 @@ class RepositoryQuery {
|
|
|
1325
1416
|
}));
|
|
1326
1417
|
continue;
|
|
1327
1418
|
}
|
|
1419
|
+
if (load.kind === "morphMany") {
|
|
1420
|
+
const relation2 = load.relation;
|
|
1421
|
+
const grouped2 = await load.repository.withConnection(this.repository.getConnection()).loadMorphManyForParents(rows, relation2, load.options);
|
|
1422
|
+
result = result.map((row) => ({
|
|
1423
|
+
...row,
|
|
1424
|
+
[load.as]: grouped2.get(row[relation2.localKey]) ?? []
|
|
1425
|
+
}));
|
|
1426
|
+
continue;
|
|
1427
|
+
}
|
|
1428
|
+
if (load.kind === "morphOne") {
|
|
1429
|
+
const relation2 = load.relation;
|
|
1430
|
+
const grouped2 = await load.repository.withConnection(this.repository.getConnection()).loadMorphOneForParents(rows, relation2, load.options);
|
|
1431
|
+
result = result.map((row) => ({
|
|
1432
|
+
...row,
|
|
1433
|
+
[load.as]: grouped2.get(row[relation2.localKey])
|
|
1434
|
+
}));
|
|
1435
|
+
continue;
|
|
1436
|
+
}
|
|
1437
|
+
if (load.kind === "morphTo") {
|
|
1438
|
+
const relation2 = load.relation;
|
|
1439
|
+
const grouped2 = await this.repository.loadMorphToForChildren(rows, relation2, load.morphRepositories ?? new Map, load.options);
|
|
1440
|
+
result = result.map((row) => ({
|
|
1441
|
+
...row,
|
|
1442
|
+
[load.as]: grouped2.get(row[relation2.morphIdKey])
|
|
1443
|
+
}));
|
|
1444
|
+
continue;
|
|
1445
|
+
}
|
|
1328
1446
|
const relation = load.relation;
|
|
1329
1447
|
const grouped = await this.repository.loadBelongsToForParents(rows, relation, load.repository, load.options);
|
|
1330
1448
|
result = result.map((row) => ({
|
|
@@ -1601,6 +1719,56 @@ class BaseRepository {
|
|
|
1601
1719
|
}, options);
|
|
1602
1720
|
return indexBelongsToRelation(children, parents, relation);
|
|
1603
1721
|
}
|
|
1722
|
+
async loadMorphManyForParents(parents, relation, options = {}) {
|
|
1723
|
+
if (parents.length === 0) {
|
|
1724
|
+
return indexMorphManyRelation(parents, [], relation);
|
|
1725
|
+
}
|
|
1726
|
+
const parentIds = [...new Set(parents.map((parent) => parent[relation.localKey]))];
|
|
1727
|
+
const children = await this.findWhere({
|
|
1728
|
+
[relation.morphTypeKey]: relation.morphType,
|
|
1729
|
+
[relation.morphIdKey]: parentIds
|
|
1730
|
+
}, options);
|
|
1731
|
+
return indexMorphManyRelation(parents, children, relation);
|
|
1732
|
+
}
|
|
1733
|
+
async loadMorphOneForParents(parents, relation, options = {}) {
|
|
1734
|
+
const grouped = await this.loadMorphManyForParents(parents, relation, options);
|
|
1735
|
+
const result = new Map;
|
|
1736
|
+
for (const parent of parents) {
|
|
1737
|
+
const matches = grouped.get(parent[relation.localKey]) ?? [];
|
|
1738
|
+
result.set(parent[relation.localKey], matches[0]);
|
|
1739
|
+
}
|
|
1740
|
+
return result;
|
|
1741
|
+
}
|
|
1742
|
+
async loadMorphToForChildren(children, relation, repositoriesByType, options = {}) {
|
|
1743
|
+
if (children.length === 0) {
|
|
1744
|
+
return new Map;
|
|
1745
|
+
}
|
|
1746
|
+
const idsByType = new Map;
|
|
1747
|
+
for (const child of children) {
|
|
1748
|
+
const morphType = String(child[relation.morphTypeKey]);
|
|
1749
|
+
const morphId = child[relation.morphIdKey];
|
|
1750
|
+
const ids = idsByType.get(morphType) ?? new Set;
|
|
1751
|
+
ids.add(morphId);
|
|
1752
|
+
idsByType.set(morphType, ids);
|
|
1753
|
+
}
|
|
1754
|
+
const parentsByType = new Map;
|
|
1755
|
+
for (const [morphType, ids] of idsByType) {
|
|
1756
|
+
const repository = repositoriesByType.get(morphType);
|
|
1757
|
+
if (!repository) {
|
|
1758
|
+
continue;
|
|
1759
|
+
}
|
|
1760
|
+
const ownerKey = repository.getTable().primaryKey;
|
|
1761
|
+
const parents = await repository.withConnection(this.connection).findWhere({
|
|
1762
|
+
[ownerKey]: [...ids]
|
|
1763
|
+
}, options);
|
|
1764
|
+
const indexed = new Map;
|
|
1765
|
+
for (const parent of parents) {
|
|
1766
|
+
indexed.set(parent[ownerKey], parent);
|
|
1767
|
+
}
|
|
1768
|
+
parentsByType.set(morphType, indexed);
|
|
1769
|
+
}
|
|
1770
|
+
return indexMorphToRelation(children, parentsByType, relation);
|
|
1771
|
+
}
|
|
1604
1772
|
}
|
|
1605
1773
|
var baseRepository_default = BaseRepository;
|
|
1606
1774
|
// ../../src/core/database/connection.ts
|
|
@@ -2605,6 +2773,12 @@ class FailedJobService {
|
|
|
2605
2773
|
await this.repository.deleteById(id);
|
|
2606
2774
|
return failedJob;
|
|
2607
2775
|
}
|
|
2776
|
+
async delete(id) {
|
|
2777
|
+
const deleted = await this.repository.deleteById(id);
|
|
2778
|
+
if (!deleted) {
|
|
2779
|
+
throw new Error(`Failed job ${id} not found.`);
|
|
2780
|
+
}
|
|
2781
|
+
}
|
|
2608
2782
|
async flush() {
|
|
2609
2783
|
const jobs = await this.repository.findAll();
|
|
2610
2784
|
let deleted = 0;
|
|
@@ -2618,9 +2792,6 @@ class FailedJobService {
|
|
|
2618
2792
|
}
|
|
2619
2793
|
var failedJobService_default = FailedJobService;
|
|
2620
2794
|
|
|
2621
|
-
// ../../src/core/queue/redisQueue.ts
|
|
2622
|
-
var {RedisClient } = globalThis.Bun;
|
|
2623
|
-
|
|
2624
2795
|
// ../../src/config/queue.ts
|
|
2625
2796
|
var queueConfig = {
|
|
2626
2797
|
driver: process.env.QUEUE_DRIVER === "redis" || process.env.QUEUE_DRIVER === "async" || process.env.QUEUE_DRIVER === "sync" ? process.env.QUEUE_DRIVER : DEFAULT_QUEUE_DRIVER,
|
|
@@ -2659,6 +2830,7 @@ async function runQueueJob(envelope, failedJobs) {
|
|
|
2659
2830
|
}
|
|
2660
2831
|
|
|
2661
2832
|
// ../../src/core/queue/redisQueue.ts
|
|
2833
|
+
var {RedisClient } = globalThis.Bun;
|
|
2662
2834
|
var QUEUE_LIST_KEY = "workhub:queue:default";
|
|
2663
2835
|
var QUEUE_HIGH_KEY = "workhub:queue:high";
|
|
2664
2836
|
var QUEUE_LOW_KEY = "workhub:queue:low";
|
|
@@ -24,6 +24,12 @@ class FailedJobService {
|
|
|
24
24
|
await this.repository.deleteById(id);
|
|
25
25
|
return failedJob;
|
|
26
26
|
}
|
|
27
|
+
async delete(id) {
|
|
28
|
+
const deleted = await this.repository.deleteById(id);
|
|
29
|
+
if (!deleted) {
|
|
30
|
+
throw new Error(`Failed job ${id} not found.`);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
27
33
|
async flush() {
|
|
28
34
|
const jobs = await this.repository.findAll();
|
|
29
35
|
let deleted = 0;
|
|
@@ -664,6 +664,66 @@ function indexBelongsToManyRelation(parents, pivotRows, relatedRows, relation) {
|
|
|
664
664
|
}
|
|
665
665
|
return groups;
|
|
666
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
|
+
function indexMorphManyRelation(parents, children, relation) {
|
|
686
|
+
const groups = new Map;
|
|
687
|
+
for (const parent of parents) {
|
|
688
|
+
groups.set(parent[relation.localKey], []);
|
|
689
|
+
}
|
|
690
|
+
for (const child of children) {
|
|
691
|
+
if (child[relation.morphTypeKey] !== relation.morphType) {
|
|
692
|
+
continue;
|
|
693
|
+
}
|
|
694
|
+
const key = child[relation.morphIdKey];
|
|
695
|
+
const group = groups.get(key);
|
|
696
|
+
if (!group) {
|
|
697
|
+
continue;
|
|
698
|
+
}
|
|
699
|
+
group.push(child);
|
|
700
|
+
}
|
|
701
|
+
return groups;
|
|
702
|
+
}
|
|
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
|
+
function indexMorphToRelation(children, parentsByType, relation) {
|
|
713
|
+
const result = new Map;
|
|
714
|
+
for (const child of children) {
|
|
715
|
+
const morphType = String(child[relation.morphTypeKey]);
|
|
716
|
+
const parents = parentsByType.get(morphType);
|
|
717
|
+
if (!parents) {
|
|
718
|
+
continue;
|
|
719
|
+
}
|
|
720
|
+
const parent = parents.get(child[relation.morphIdKey]);
|
|
721
|
+
if (parent) {
|
|
722
|
+
result.set(child[relation.morphIdKey], parent);
|
|
723
|
+
}
|
|
724
|
+
}
|
|
725
|
+
return result;
|
|
726
|
+
}
|
|
667
727
|
|
|
668
728
|
// ../../src/config/database.ts
|
|
669
729
|
function readInteger(name, fallback) {
|
|
@@ -867,6 +927,37 @@ class RepositoryQuery {
|
|
|
867
927
|
});
|
|
868
928
|
return this;
|
|
869
929
|
}
|
|
930
|
+
withMorphMany(as, relation, childRepository, options = {}) {
|
|
931
|
+
this.eagerLoads.push({
|
|
932
|
+
kind: "morphMany",
|
|
933
|
+
as,
|
|
934
|
+
relation,
|
|
935
|
+
repository: childRepository,
|
|
936
|
+
options
|
|
937
|
+
});
|
|
938
|
+
return this;
|
|
939
|
+
}
|
|
940
|
+
withMorphOne(as, relation, childRepository, options = {}) {
|
|
941
|
+
this.eagerLoads.push({
|
|
942
|
+
kind: "morphOne",
|
|
943
|
+
as,
|
|
944
|
+
relation,
|
|
945
|
+
repository: childRepository,
|
|
946
|
+
options
|
|
947
|
+
});
|
|
948
|
+
return this;
|
|
949
|
+
}
|
|
950
|
+
withMorphTo(as, relation, repositoriesByType, options = {}) {
|
|
951
|
+
this.eagerLoads.push({
|
|
952
|
+
kind: "morphTo",
|
|
953
|
+
as,
|
|
954
|
+
relation,
|
|
955
|
+
repository: this.repository,
|
|
956
|
+
morphRepositories: repositoriesByType,
|
|
957
|
+
options
|
|
958
|
+
});
|
|
959
|
+
return this;
|
|
960
|
+
}
|
|
870
961
|
async get() {
|
|
871
962
|
const rows = await this.repository.findAll(this.buildOptions());
|
|
872
963
|
return await this.attach(rows);
|
|
@@ -927,6 +1018,33 @@ class RepositoryQuery {
|
|
|
927
1018
|
}));
|
|
928
1019
|
continue;
|
|
929
1020
|
}
|
|
1021
|
+
if (load.kind === "morphMany") {
|
|
1022
|
+
const relation2 = load.relation;
|
|
1023
|
+
const grouped2 = await load.repository.withConnection(this.repository.getConnection()).loadMorphManyForParents(rows, relation2, load.options);
|
|
1024
|
+
result = result.map((row) => ({
|
|
1025
|
+
...row,
|
|
1026
|
+
[load.as]: grouped2.get(row[relation2.localKey]) ?? []
|
|
1027
|
+
}));
|
|
1028
|
+
continue;
|
|
1029
|
+
}
|
|
1030
|
+
if (load.kind === "morphOne") {
|
|
1031
|
+
const relation2 = load.relation;
|
|
1032
|
+
const grouped2 = await load.repository.withConnection(this.repository.getConnection()).loadMorphOneForParents(rows, relation2, load.options);
|
|
1033
|
+
result = result.map((row) => ({
|
|
1034
|
+
...row,
|
|
1035
|
+
[load.as]: grouped2.get(row[relation2.localKey])
|
|
1036
|
+
}));
|
|
1037
|
+
continue;
|
|
1038
|
+
}
|
|
1039
|
+
if (load.kind === "morphTo") {
|
|
1040
|
+
const relation2 = load.relation;
|
|
1041
|
+
const grouped2 = await this.repository.loadMorphToForChildren(rows, relation2, load.morphRepositories ?? new Map, load.options);
|
|
1042
|
+
result = result.map((row) => ({
|
|
1043
|
+
...row,
|
|
1044
|
+
[load.as]: grouped2.get(row[relation2.morphIdKey])
|
|
1045
|
+
}));
|
|
1046
|
+
continue;
|
|
1047
|
+
}
|
|
930
1048
|
const relation = load.relation;
|
|
931
1049
|
const grouped = await this.repository.loadBelongsToForParents(rows, relation, load.repository, load.options);
|
|
932
1050
|
result = result.map((row) => ({
|
|
@@ -1203,6 +1321,56 @@ class BaseRepository {
|
|
|
1203
1321
|
}, options);
|
|
1204
1322
|
return indexBelongsToRelation(children, parents, relation);
|
|
1205
1323
|
}
|
|
1324
|
+
async loadMorphManyForParents(parents, relation, options = {}) {
|
|
1325
|
+
if (parents.length === 0) {
|
|
1326
|
+
return indexMorphManyRelation(parents, [], relation);
|
|
1327
|
+
}
|
|
1328
|
+
const parentIds = [...new Set(parents.map((parent) => parent[relation.localKey]))];
|
|
1329
|
+
const children = await this.findWhere({
|
|
1330
|
+
[relation.morphTypeKey]: relation.morphType,
|
|
1331
|
+
[relation.morphIdKey]: parentIds
|
|
1332
|
+
}, options);
|
|
1333
|
+
return indexMorphManyRelation(parents, children, relation);
|
|
1334
|
+
}
|
|
1335
|
+
async loadMorphOneForParents(parents, relation, options = {}) {
|
|
1336
|
+
const grouped = await this.loadMorphManyForParents(parents, relation, options);
|
|
1337
|
+
const result = new Map;
|
|
1338
|
+
for (const parent of parents) {
|
|
1339
|
+
const matches = grouped.get(parent[relation.localKey]) ?? [];
|
|
1340
|
+
result.set(parent[relation.localKey], matches[0]);
|
|
1341
|
+
}
|
|
1342
|
+
return result;
|
|
1343
|
+
}
|
|
1344
|
+
async loadMorphToForChildren(children, relation, repositoriesByType, options = {}) {
|
|
1345
|
+
if (children.length === 0) {
|
|
1346
|
+
return new Map;
|
|
1347
|
+
}
|
|
1348
|
+
const idsByType = new Map;
|
|
1349
|
+
for (const child of children) {
|
|
1350
|
+
const morphType = String(child[relation.morphTypeKey]);
|
|
1351
|
+
const morphId = child[relation.morphIdKey];
|
|
1352
|
+
const ids = idsByType.get(morphType) ?? new Set;
|
|
1353
|
+
ids.add(morphId);
|
|
1354
|
+
idsByType.set(morphType, ids);
|
|
1355
|
+
}
|
|
1356
|
+
const parentsByType = new Map;
|
|
1357
|
+
for (const [morphType, ids] of idsByType) {
|
|
1358
|
+
const repository = repositoriesByType.get(morphType);
|
|
1359
|
+
if (!repository) {
|
|
1360
|
+
continue;
|
|
1361
|
+
}
|
|
1362
|
+
const ownerKey = repository.getTable().primaryKey;
|
|
1363
|
+
const parents = await repository.withConnection(this.connection).findWhere({
|
|
1364
|
+
[ownerKey]: [...ids]
|
|
1365
|
+
}, options);
|
|
1366
|
+
const indexed = new Map;
|
|
1367
|
+
for (const parent of parents) {
|
|
1368
|
+
indexed.set(parent[ownerKey], parent);
|
|
1369
|
+
}
|
|
1370
|
+
parentsByType.set(morphType, indexed);
|
|
1371
|
+
}
|
|
1372
|
+
return indexMorphToRelation(children, parentsByType, relation);
|
|
1373
|
+
}
|
|
1206
1374
|
}
|
|
1207
1375
|
var baseRepository_default = BaseRepository;
|
|
1208
1376
|
// ../../src/core/database/connection.ts
|
|
@@ -2207,6 +2375,12 @@ class FailedJobService {
|
|
|
2207
2375
|
await this.repository.deleteById(id);
|
|
2208
2376
|
return failedJob;
|
|
2209
2377
|
}
|
|
2378
|
+
async delete(id) {
|
|
2379
|
+
const deleted = await this.repository.deleteById(id);
|
|
2380
|
+
if (!deleted) {
|
|
2381
|
+
throw new Error(`Failed job ${id} not found.`);
|
|
2382
|
+
}
|
|
2383
|
+
}
|
|
2210
2384
|
async flush() {
|
|
2211
2385
|
const jobs = await this.repository.findAll();
|
|
2212
2386
|
let deleted = 0;
|
|
@@ -2248,9 +2422,6 @@ class JobRegistry {
|
|
|
2248
2422
|
}
|
|
2249
2423
|
var jobRegistry = new JobRegistry;
|
|
2250
2424
|
|
|
2251
|
-
// ../../src/core/queue/redisQueue.ts
|
|
2252
|
-
var {RedisClient } = globalThis.Bun;
|
|
2253
|
-
|
|
2254
2425
|
// ../../src/bootstrap/config.ts
|
|
2255
2426
|
var CORE_QUEUE_TOKEN = "core.queue";
|
|
2256
2427
|
var CORE_POLICY_GATE_TOKEN = "core.policyGate";
|
|
@@ -2296,6 +2467,7 @@ async function runQueueJob(envelope, failedJobs) {
|
|
|
2296
2467
|
}
|
|
2297
2468
|
|
|
2298
2469
|
// ../../src/core/queue/redisQueue.ts
|
|
2470
|
+
var {RedisClient } = globalThis.Bun;
|
|
2299
2471
|
var QUEUE_LIST_KEY = "workhub:queue:default";
|
|
2300
2472
|
var QUEUE_HIGH_KEY = "workhub:queue:high";
|
|
2301
2473
|
var QUEUE_LOW_KEY = "workhub:queue:low";
|
|
@@ -2469,6 +2641,7 @@ function createQueueWorker(redisUrl, failedJobs = createFailedJobService()) {
|
|
|
2469
2641
|
return new QueueWorker(redisUrl, failedJobs);
|
|
2470
2642
|
}
|
|
2471
2643
|
export {
|
|
2644
|
+
runQueueJob,
|
|
2472
2645
|
jobRegistry,
|
|
2473
2646
|
createTrackedJob,
|
|
2474
2647
|
createQueueWorker,
|
|
@@ -1142,6 +1142,66 @@ function indexBelongsToManyRelation(parents, pivotRows, relatedRows, relation) {
|
|
|
1142
1142
|
}
|
|
1143
1143
|
return groups;
|
|
1144
1144
|
}
|
|
1145
|
+
function morphMany(definition) {
|
|
1146
|
+
return {
|
|
1147
|
+
type: "morphMany",
|
|
1148
|
+
...definition
|
|
1149
|
+
};
|
|
1150
|
+
}
|
|
1151
|
+
function morphOne(definition) {
|
|
1152
|
+
return {
|
|
1153
|
+
type: "morphOne",
|
|
1154
|
+
...definition
|
|
1155
|
+
};
|
|
1156
|
+
}
|
|
1157
|
+
function morphTo(definition) {
|
|
1158
|
+
return {
|
|
1159
|
+
type: "morphTo",
|
|
1160
|
+
...definition
|
|
1161
|
+
};
|
|
1162
|
+
}
|
|
1163
|
+
function indexMorphManyRelation(parents, children, relation) {
|
|
1164
|
+
const groups = new Map;
|
|
1165
|
+
for (const parent of parents) {
|
|
1166
|
+
groups.set(parent[relation.localKey], []);
|
|
1167
|
+
}
|
|
1168
|
+
for (const child of children) {
|
|
1169
|
+
if (child[relation.morphTypeKey] !== relation.morphType) {
|
|
1170
|
+
continue;
|
|
1171
|
+
}
|
|
1172
|
+
const key = child[relation.morphIdKey];
|
|
1173
|
+
const group = groups.get(key);
|
|
1174
|
+
if (!group) {
|
|
1175
|
+
continue;
|
|
1176
|
+
}
|
|
1177
|
+
group.push(child);
|
|
1178
|
+
}
|
|
1179
|
+
return groups;
|
|
1180
|
+
}
|
|
1181
|
+
function indexMorphOneRelation(parents, children, relation) {
|
|
1182
|
+
const grouped = indexMorphManyRelation(parents, children, relation);
|
|
1183
|
+
const result = new Map;
|
|
1184
|
+
for (const parent of parents) {
|
|
1185
|
+
const matches = grouped.get(parent[relation.localKey]) ?? [];
|
|
1186
|
+
result.set(parent[relation.localKey], matches[0]);
|
|
1187
|
+
}
|
|
1188
|
+
return result;
|
|
1189
|
+
}
|
|
1190
|
+
function indexMorphToRelation(children, parentsByType, relation) {
|
|
1191
|
+
const result = new Map;
|
|
1192
|
+
for (const child of children) {
|
|
1193
|
+
const morphType = String(child[relation.morphTypeKey]);
|
|
1194
|
+
const parents = parentsByType.get(morphType);
|
|
1195
|
+
if (!parents) {
|
|
1196
|
+
continue;
|
|
1197
|
+
}
|
|
1198
|
+
const parent = parents.get(child[relation.morphIdKey]);
|
|
1199
|
+
if (parent) {
|
|
1200
|
+
result.set(child[relation.morphIdKey], parent);
|
|
1201
|
+
}
|
|
1202
|
+
}
|
|
1203
|
+
return result;
|
|
1204
|
+
}
|
|
1145
1205
|
|
|
1146
1206
|
// ../../src/core/database/boundConnection.ts
|
|
1147
1207
|
var boundConnectionHolder = {
|
|
@@ -1275,6 +1335,37 @@ class RepositoryQuery {
|
|
|
1275
1335
|
});
|
|
1276
1336
|
return this;
|
|
1277
1337
|
}
|
|
1338
|
+
withMorphMany(as, relation, childRepository, options = {}) {
|
|
1339
|
+
this.eagerLoads.push({
|
|
1340
|
+
kind: "morphMany",
|
|
1341
|
+
as,
|
|
1342
|
+
relation,
|
|
1343
|
+
repository: childRepository,
|
|
1344
|
+
options
|
|
1345
|
+
});
|
|
1346
|
+
return this;
|
|
1347
|
+
}
|
|
1348
|
+
withMorphOne(as, relation, childRepository, options = {}) {
|
|
1349
|
+
this.eagerLoads.push({
|
|
1350
|
+
kind: "morphOne",
|
|
1351
|
+
as,
|
|
1352
|
+
relation,
|
|
1353
|
+
repository: childRepository,
|
|
1354
|
+
options
|
|
1355
|
+
});
|
|
1356
|
+
return this;
|
|
1357
|
+
}
|
|
1358
|
+
withMorphTo(as, relation, repositoriesByType, options = {}) {
|
|
1359
|
+
this.eagerLoads.push({
|
|
1360
|
+
kind: "morphTo",
|
|
1361
|
+
as,
|
|
1362
|
+
relation,
|
|
1363
|
+
repository: this.repository,
|
|
1364
|
+
morphRepositories: repositoriesByType,
|
|
1365
|
+
options
|
|
1366
|
+
});
|
|
1367
|
+
return this;
|
|
1368
|
+
}
|
|
1278
1369
|
async get() {
|
|
1279
1370
|
const rows = await this.repository.findAll(this.buildOptions());
|
|
1280
1371
|
return await this.attach(rows);
|
|
@@ -1335,6 +1426,33 @@ class RepositoryQuery {
|
|
|
1335
1426
|
}));
|
|
1336
1427
|
continue;
|
|
1337
1428
|
}
|
|
1429
|
+
if (load.kind === "morphMany") {
|
|
1430
|
+
const relation2 = load.relation;
|
|
1431
|
+
const grouped2 = await load.repository.withConnection(this.repository.getConnection()).loadMorphManyForParents(rows, relation2, load.options);
|
|
1432
|
+
result = result.map((row) => ({
|
|
1433
|
+
...row,
|
|
1434
|
+
[load.as]: grouped2.get(row[relation2.localKey]) ?? []
|
|
1435
|
+
}));
|
|
1436
|
+
continue;
|
|
1437
|
+
}
|
|
1438
|
+
if (load.kind === "morphOne") {
|
|
1439
|
+
const relation2 = load.relation;
|
|
1440
|
+
const grouped2 = await load.repository.withConnection(this.repository.getConnection()).loadMorphOneForParents(rows, relation2, load.options);
|
|
1441
|
+
result = result.map((row) => ({
|
|
1442
|
+
...row,
|
|
1443
|
+
[load.as]: grouped2.get(row[relation2.localKey])
|
|
1444
|
+
}));
|
|
1445
|
+
continue;
|
|
1446
|
+
}
|
|
1447
|
+
if (load.kind === "morphTo") {
|
|
1448
|
+
const relation2 = load.relation;
|
|
1449
|
+
const grouped2 = await this.repository.loadMorphToForChildren(rows, relation2, load.morphRepositories ?? new Map, load.options);
|
|
1450
|
+
result = result.map((row) => ({
|
|
1451
|
+
...row,
|
|
1452
|
+
[load.as]: grouped2.get(row[relation2.morphIdKey])
|
|
1453
|
+
}));
|
|
1454
|
+
continue;
|
|
1455
|
+
}
|
|
1338
1456
|
const relation = load.relation;
|
|
1339
1457
|
const grouped = await this.repository.loadBelongsToForParents(rows, relation, load.repository, load.options);
|
|
1340
1458
|
result = result.map((row) => ({
|
|
@@ -1611,6 +1729,56 @@ class BaseRepository {
|
|
|
1611
1729
|
}, options);
|
|
1612
1730
|
return indexBelongsToRelation(children, parents, relation);
|
|
1613
1731
|
}
|
|
1732
|
+
async loadMorphManyForParents(parents, relation, options = {}) {
|
|
1733
|
+
if (parents.length === 0) {
|
|
1734
|
+
return indexMorphManyRelation(parents, [], relation);
|
|
1735
|
+
}
|
|
1736
|
+
const parentIds = [...new Set(parents.map((parent) => parent[relation.localKey]))];
|
|
1737
|
+
const children = await this.findWhere({
|
|
1738
|
+
[relation.morphTypeKey]: relation.morphType,
|
|
1739
|
+
[relation.morphIdKey]: parentIds
|
|
1740
|
+
}, options);
|
|
1741
|
+
return indexMorphManyRelation(parents, children, relation);
|
|
1742
|
+
}
|
|
1743
|
+
async loadMorphOneForParents(parents, relation, options = {}) {
|
|
1744
|
+
const grouped = await this.loadMorphManyForParents(parents, relation, options);
|
|
1745
|
+
const result = new Map;
|
|
1746
|
+
for (const parent of parents) {
|
|
1747
|
+
const matches = grouped.get(parent[relation.localKey]) ?? [];
|
|
1748
|
+
result.set(parent[relation.localKey], matches[0]);
|
|
1749
|
+
}
|
|
1750
|
+
return result;
|
|
1751
|
+
}
|
|
1752
|
+
async loadMorphToForChildren(children, relation, repositoriesByType, options = {}) {
|
|
1753
|
+
if (children.length === 0) {
|
|
1754
|
+
return new Map;
|
|
1755
|
+
}
|
|
1756
|
+
const idsByType = new Map;
|
|
1757
|
+
for (const child of children) {
|
|
1758
|
+
const morphType = String(child[relation.morphTypeKey]);
|
|
1759
|
+
const morphId = child[relation.morphIdKey];
|
|
1760
|
+
const ids = idsByType.get(morphType) ?? new Set;
|
|
1761
|
+
ids.add(morphId);
|
|
1762
|
+
idsByType.set(morphType, ids);
|
|
1763
|
+
}
|
|
1764
|
+
const parentsByType = new Map;
|
|
1765
|
+
for (const [morphType, ids] of idsByType) {
|
|
1766
|
+
const repository = repositoriesByType.get(morphType);
|
|
1767
|
+
if (!repository) {
|
|
1768
|
+
continue;
|
|
1769
|
+
}
|
|
1770
|
+
const ownerKey = repository.getTable().primaryKey;
|
|
1771
|
+
const parents = await repository.withConnection(this.connection).findWhere({
|
|
1772
|
+
[ownerKey]: [...ids]
|
|
1773
|
+
}, options);
|
|
1774
|
+
const indexed = new Map;
|
|
1775
|
+
for (const parent of parents) {
|
|
1776
|
+
indexed.set(parent[ownerKey], parent);
|
|
1777
|
+
}
|
|
1778
|
+
parentsByType.set(morphType, indexed);
|
|
1779
|
+
}
|
|
1780
|
+
return indexMorphToRelation(children, parentsByType, relation);
|
|
1781
|
+
}
|
|
1614
1782
|
}
|
|
1615
1783
|
var baseRepository_default = BaseRepository;
|
|
1616
1784
|
// ../../src/core/database/connection.ts
|
|
@@ -2615,6 +2783,12 @@ class FailedJobService {
|
|
|
2615
2783
|
await this.repository.deleteById(id);
|
|
2616
2784
|
return failedJob;
|
|
2617
2785
|
}
|
|
2786
|
+
async delete(id) {
|
|
2787
|
+
const deleted = await this.repository.deleteById(id);
|
|
2788
|
+
if (!deleted) {
|
|
2789
|
+
throw new Error(`Failed job ${id} not found.`);
|
|
2790
|
+
}
|
|
2791
|
+
}
|
|
2618
2792
|
async flush() {
|
|
2619
2793
|
const jobs = await this.repository.findAll();
|
|
2620
2794
|
let deleted = 0;
|
|
@@ -2628,9 +2802,6 @@ class FailedJobService {
|
|
|
2628
2802
|
}
|
|
2629
2803
|
var failedJobService_default = FailedJobService;
|
|
2630
2804
|
|
|
2631
|
-
// ../../src/core/queue/redisQueue.ts
|
|
2632
|
-
var {RedisClient } = globalThis.Bun;
|
|
2633
|
-
|
|
2634
2805
|
// ../../src/core/queue/jobRunner.ts
|
|
2635
2806
|
async function runQueueJob(envelope, failedJobs) {
|
|
2636
2807
|
const job = jobRegistry.create(envelope.name);
|
|
@@ -2662,6 +2833,7 @@ async function runQueueJob(envelope, failedJobs) {
|
|
|
2662
2833
|
}
|
|
2663
2834
|
|
|
2664
2835
|
// ../../src/core/queue/redisQueue.ts
|
|
2836
|
+
var {RedisClient } = globalThis.Bun;
|
|
2665
2837
|
var QUEUE_LIST_KEY = "workhub:queue:default";
|
|
2666
2838
|
var QUEUE_HIGH_KEY = "workhub:queue:high";
|
|
2667
2839
|
var QUEUE_LOW_KEY = "workhub:queue:low";
|