@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.
@@ -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";