@dudousxd/nestjs-durable-store-mikro-orm 0.17.0 → 0.18.0
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/index.cjs +70 -26
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +33 -10
- package/dist/index.d.ts +33 -10
- package/dist/index.js +70 -26
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.cjs
CHANGED
|
@@ -116,11 +116,28 @@ var BufferedSignalEntity = class {
|
|
|
116
116
|
token;
|
|
117
117
|
payload;
|
|
118
118
|
};
|
|
119
|
+
function namespaceFilterCond(args) {
|
|
120
|
+
if (args.namespace === void 0) return {};
|
|
121
|
+
return {
|
|
122
|
+
namespace: args.namespace
|
|
123
|
+
};
|
|
124
|
+
}
|
|
125
|
+
__name(namespaceFilterCond, "namespaceFilterCond");
|
|
119
126
|
function durableEntities(options = {}) {
|
|
120
127
|
const col = columnNamer(options.naming ?? "snake_case");
|
|
121
128
|
const workflowRuns = new import_core.EntitySchema({
|
|
122
129
|
class: WorkflowRunEntity,
|
|
123
130
|
tableName: "durable_workflow_runs",
|
|
131
|
+
// Global filter: confines every read to the tenant's namespace when the store is scoped.
|
|
132
|
+
// The `cond` returns `{}` (no-op) when the `namespace` arg is `undefined`, so an unscoped
|
|
133
|
+
// (operator / control-plane) store sees all rows unchanged — existing behaviour is preserved.
|
|
134
|
+
filters: {
|
|
135
|
+
namespace: {
|
|
136
|
+
name: "namespace",
|
|
137
|
+
cond: namespaceFilterCond,
|
|
138
|
+
default: true
|
|
139
|
+
}
|
|
140
|
+
},
|
|
124
141
|
// Indexes mirror the Prisma adapter so a store swap keeps the same plan. The poller hits these
|
|
125
142
|
// every tick: `(status, wakeAt)` serves both the due-timer scan (status='suspended' AND wakeAt<=now)
|
|
126
143
|
// and, via its `status` prefix, the pending/incomplete status lookups; `(workflow, status)` serves
|
|
@@ -646,25 +663,51 @@ async function alignDurableCollation(orm) {
|
|
|
646
663
|
__name(alignDurableCollation, "alignDurableCollation");
|
|
647
664
|
|
|
648
665
|
// src/mikro-orm-state-store.ts
|
|
649
|
-
var MikroOrmStateStore = class {
|
|
666
|
+
var MikroOrmStateStore = class _MikroOrmStateStore {
|
|
650
667
|
static {
|
|
651
668
|
__name(this, "MikroOrmStateStore");
|
|
652
669
|
}
|
|
653
670
|
orm;
|
|
654
|
-
|
|
671
|
+
scopeNamespace;
|
|
672
|
+
constructor(orm, opts) {
|
|
655
673
|
this.orm = orm;
|
|
674
|
+
this.scopeNamespace = opts?.scope?.namespace;
|
|
675
|
+
}
|
|
676
|
+
/**
|
|
677
|
+
* Derive a store confined to a single tenant `scope.namespace`, sharing this store's ORM (no new
|
|
678
|
+
* connection). Turns the operator (unscoped) store into a tenant-boundary view at wiring time —
|
|
679
|
+
* used by the NestJS module's `scopeReads` option, which receives a pre-built store and can't
|
|
680
|
+
* reconstruct it. Pass `{ namespace: undefined }` for the unscoped operator view.
|
|
681
|
+
*/
|
|
682
|
+
withScope(scope) {
|
|
683
|
+
return new _MikroOrmStateStore(this.orm, {
|
|
684
|
+
scope
|
|
685
|
+
});
|
|
686
|
+
}
|
|
687
|
+
/**
|
|
688
|
+
* Create a forked EntityManager and activate the `namespace` global filter with the store's
|
|
689
|
+
* scope (if any). All read operations go through this so the tenant boundary is applied
|
|
690
|
+
* uniformly. Write operations (nativeDelete, nativeUpdate, upsert, insertMany) bypass global
|
|
691
|
+
* filters in MikroORM and are unaffected.
|
|
692
|
+
*/
|
|
693
|
+
fork() {
|
|
694
|
+
const em = this.orm.em.fork();
|
|
695
|
+
em.setFilterParams("namespace", {
|
|
696
|
+
namespace: this.scopeNamespace
|
|
697
|
+
});
|
|
698
|
+
return em;
|
|
656
699
|
}
|
|
657
700
|
async ensureSchema() {
|
|
658
701
|
await ensureMikroOrmDurableSchema(this.orm);
|
|
659
702
|
}
|
|
660
703
|
async createRun(run) {
|
|
661
|
-
const em = this.
|
|
704
|
+
const em = this.fork();
|
|
662
705
|
em.create(WorkflowRunEntity, toRunEntity(run));
|
|
663
706
|
await em.flush();
|
|
664
707
|
await this.reindexAttributes(run.id, run.searchAttributes);
|
|
665
708
|
}
|
|
666
709
|
async updateRun(runId, patch) {
|
|
667
|
-
const em = this.
|
|
710
|
+
const em = this.fork();
|
|
668
711
|
const entity = await em.findOneOrFail(WorkflowRunEntity, {
|
|
669
712
|
id: runId
|
|
670
713
|
});
|
|
@@ -678,7 +721,7 @@ var MikroOrmStateStore = class {
|
|
|
678
721
|
/** Rewrite a run's normalized attribute rows: delete the old set, insert the current one. Mirrors
|
|
679
722
|
* the in-memory store's reindex so the side-table always reflects the run's live searchAttributes. */
|
|
680
723
|
async reindexAttributes(runId, attributes, forked) {
|
|
681
|
-
const em = forked ?? this.
|
|
724
|
+
const em = forked ?? this.fork();
|
|
682
725
|
await em.nativeDelete(RunAttributeEntity, {
|
|
683
726
|
runId
|
|
684
727
|
});
|
|
@@ -686,14 +729,14 @@ var MikroOrmStateStore = class {
|
|
|
686
729
|
if (rows.length) await em.insertMany(RunAttributeEntity, rows);
|
|
687
730
|
}
|
|
688
731
|
async getRun(runId) {
|
|
689
|
-
const em = this.
|
|
732
|
+
const em = this.fork();
|
|
690
733
|
const entity = await em.findOne(WorkflowRunEntity, {
|
|
691
734
|
id: runId
|
|
692
735
|
});
|
|
693
736
|
return entity ? fromRunEntity(entity) : null;
|
|
694
737
|
}
|
|
695
738
|
async deleteRun(runId) {
|
|
696
|
-
const em = this.
|
|
739
|
+
const em = this.fork();
|
|
697
740
|
await em.nativeDelete(StepCheckpointEntity, {
|
|
698
741
|
runId
|
|
699
742
|
});
|
|
@@ -709,7 +752,7 @@ var MikroOrmStateStore = class {
|
|
|
709
752
|
}
|
|
710
753
|
async pruneTerminalRuns(policy, nowMs, limit) {
|
|
711
754
|
if (policy.statuses.length === 0 || limit <= 0) return 0;
|
|
712
|
-
const em = this.
|
|
755
|
+
const em = this.fork();
|
|
713
756
|
const status = {
|
|
714
757
|
$in: policy.statuses
|
|
715
758
|
};
|
|
@@ -775,7 +818,7 @@ var MikroOrmStateStore = class {
|
|
|
775
818
|
return idList.length;
|
|
776
819
|
}
|
|
777
820
|
async getCheckpoint(runId, seq) {
|
|
778
|
-
const em = this.
|
|
821
|
+
const em = this.fork();
|
|
779
822
|
const entity = await em.findOne(StepCheckpointEntity, {
|
|
780
823
|
runId,
|
|
781
824
|
seq
|
|
@@ -783,12 +826,12 @@ var MikroOrmStateStore = class {
|
|
|
783
826
|
return entity ? fromCheckpointEntity(entity) : null;
|
|
784
827
|
}
|
|
785
828
|
async saveCheckpoint(checkpoint) {
|
|
786
|
-
const em = this.
|
|
829
|
+
const em = this.fork();
|
|
787
830
|
await em.upsert(StepCheckpointEntity, toCheckpointEntity(checkpoint));
|
|
788
831
|
await em.flush();
|
|
789
832
|
}
|
|
790
833
|
async transaction(work) {
|
|
791
|
-
return this.
|
|
834
|
+
return this.fork().transactional(async (em) => work({
|
|
792
835
|
raw: em,
|
|
793
836
|
saveCheckpoint: /* @__PURE__ */ __name(async (cp) => {
|
|
794
837
|
await em.upsert(StepCheckpointEntity, toCheckpointEntity(cp));
|
|
@@ -796,7 +839,7 @@ var MikroOrmStateStore = class {
|
|
|
796
839
|
}));
|
|
797
840
|
}
|
|
798
841
|
async listIncompleteRuns(namespace) {
|
|
799
|
-
const em = this.
|
|
842
|
+
const em = this.fork();
|
|
800
843
|
const rows = await em.find(WorkflowRunEntity, {
|
|
801
844
|
status: {
|
|
802
845
|
$in: [
|
|
@@ -811,7 +854,7 @@ var MikroOrmStateStore = class {
|
|
|
811
854
|
return rows.map(fromRunEntity);
|
|
812
855
|
}
|
|
813
856
|
async listPendingRuns(limit, namespace) {
|
|
814
|
-
const em = this.
|
|
857
|
+
const em = this.fork();
|
|
815
858
|
const rows = await em.find(WorkflowRunEntity, {
|
|
816
859
|
status: "pending",
|
|
817
860
|
...namespace !== void 0 ? {
|
|
@@ -826,7 +869,7 @@ var MikroOrmStateStore = class {
|
|
|
826
869
|
return rows.map(fromRunEntity);
|
|
827
870
|
}
|
|
828
871
|
async listDueTimers(nowMs, namespace) {
|
|
829
|
-
const em = this.
|
|
872
|
+
const em = this.fork();
|
|
830
873
|
const rows = await em.find(WorkflowRunEntity, {
|
|
831
874
|
status: "suspended",
|
|
832
875
|
wakeAt: {
|
|
@@ -840,7 +883,7 @@ var MikroOrmStateStore = class {
|
|
|
840
883
|
return rows.map(fromRunEntity);
|
|
841
884
|
}
|
|
842
885
|
async tryLockRun(runId, owner, leaseUntilMs, nowMs) {
|
|
843
|
-
const em = this.
|
|
886
|
+
const em = this.fork();
|
|
844
887
|
const affected = await em.nativeUpdate(WorkflowRunEntity, {
|
|
845
888
|
id: runId,
|
|
846
889
|
$or: [
|
|
@@ -860,7 +903,7 @@ var MikroOrmStateStore = class {
|
|
|
860
903
|
return affected === 1;
|
|
861
904
|
}
|
|
862
905
|
async releaseRunLock(runId) {
|
|
863
|
-
const em = this.
|
|
906
|
+
const em = this.fork();
|
|
864
907
|
await em.nativeUpdate(WorkflowRunEntity, {
|
|
865
908
|
id: runId
|
|
866
909
|
}, {
|
|
@@ -869,7 +912,7 @@ var MikroOrmStateStore = class {
|
|
|
869
912
|
});
|
|
870
913
|
}
|
|
871
914
|
async renewRunLock(runId, owner, leaseUntilMs) {
|
|
872
|
-
const em = this.
|
|
915
|
+
const em = this.fork();
|
|
873
916
|
const affected = await em.nativeUpdate(WorkflowRunEntity, {
|
|
874
917
|
id: runId,
|
|
875
918
|
lockedBy: owner
|
|
@@ -879,7 +922,7 @@ var MikroOrmStateStore = class {
|
|
|
879
922
|
return affected === 1;
|
|
880
923
|
}
|
|
881
924
|
async listRuns(query) {
|
|
882
|
-
const em = this.
|
|
925
|
+
const em = this.fork();
|
|
883
926
|
const where = {};
|
|
884
927
|
if (query.workflow) where.workflow = query.workflow;
|
|
885
928
|
if (query.namespace !== void 0) where.namespace = query.namespace;
|
|
@@ -905,6 +948,7 @@ var MikroOrmStateStore = class {
|
|
|
905
948
|
createdAt: "desc"
|
|
906
949
|
};
|
|
907
950
|
if (query.tag || query.attributes?.length) {
|
|
951
|
+
if (this.scopeNamespace !== void 0) where.namespace = this.scopeNamespace;
|
|
908
952
|
const quote = this.idQuote(em);
|
|
909
953
|
const cols = this.attributeColumns(em);
|
|
910
954
|
const qb = em.createQueryBuilder(WorkflowRunEntity, "r").where(where).orderBy(orderBy);
|
|
@@ -987,7 +1031,7 @@ var MikroOrmStateStore = class {
|
|
|
987
1031
|
return (id) => `${ch}${id}${ch}`;
|
|
988
1032
|
}
|
|
989
1033
|
async listCheckpoints(runId) {
|
|
990
|
-
const em = this.
|
|
1034
|
+
const em = this.fork();
|
|
991
1035
|
const rows = await em.find(StepCheckpointEntity, {
|
|
992
1036
|
runId
|
|
993
1037
|
}, {
|
|
@@ -998,7 +1042,7 @@ var MikroOrmStateStore = class {
|
|
|
998
1042
|
return rows.map(fromCheckpointEntity);
|
|
999
1043
|
}
|
|
1000
1044
|
async getLatestCheckpointByName(runId, name) {
|
|
1001
|
-
const em = this.
|
|
1045
|
+
const em = this.fork();
|
|
1002
1046
|
const entity = await em.findOne(StepCheckpointEntity, {
|
|
1003
1047
|
runId,
|
|
1004
1048
|
name
|
|
@@ -1011,7 +1055,7 @@ var MikroOrmStateStore = class {
|
|
|
1011
1055
|
}
|
|
1012
1056
|
async listCheckpointsByNamePrefix(runId, prefixes) {
|
|
1013
1057
|
if (prefixes.length === 0) return [];
|
|
1014
|
-
const em = this.
|
|
1058
|
+
const em = this.fork();
|
|
1015
1059
|
const rows = await em.find(StepCheckpointEntity, {
|
|
1016
1060
|
runId,
|
|
1017
1061
|
$or: prefixes.map((p) => ({
|
|
@@ -1027,7 +1071,7 @@ var MikroOrmStateStore = class {
|
|
|
1027
1071
|
return rows.map(fromCheckpointEntity);
|
|
1028
1072
|
}
|
|
1029
1073
|
async putSignalWaiter(waiter) {
|
|
1030
|
-
const em = this.
|
|
1074
|
+
const em = this.fork();
|
|
1031
1075
|
await em.upsert(SignalWaiterEntity, {
|
|
1032
1076
|
token: waiter.token,
|
|
1033
1077
|
runId: waiter.runId,
|
|
@@ -1037,7 +1081,7 @@ var MikroOrmStateStore = class {
|
|
|
1037
1081
|
await em.flush();
|
|
1038
1082
|
}
|
|
1039
1083
|
async takeSignalWaiter(token) {
|
|
1040
|
-
const em = this.
|
|
1084
|
+
const em = this.fork();
|
|
1041
1085
|
const entity = await em.findOne(SignalWaiterEntity, {
|
|
1042
1086
|
token
|
|
1043
1087
|
});
|
|
@@ -1052,7 +1096,7 @@ var MikroOrmStateStore = class {
|
|
|
1052
1096
|
return waiter;
|
|
1053
1097
|
}
|
|
1054
1098
|
async listSignalWaiters(prefix) {
|
|
1055
|
-
const em = this.
|
|
1099
|
+
const em = this.fork();
|
|
1056
1100
|
const rows = await em.find(SignalWaiterEntity, {
|
|
1057
1101
|
token: {
|
|
1058
1102
|
$like: `${prefix}%`
|
|
@@ -1066,7 +1110,7 @@ var MikroOrmStateStore = class {
|
|
|
1066
1110
|
}));
|
|
1067
1111
|
}
|
|
1068
1112
|
async bufferSignal(token, payload) {
|
|
1069
|
-
const em = this.
|
|
1113
|
+
const em = this.fork();
|
|
1070
1114
|
const e = new BufferedSignalEntity();
|
|
1071
1115
|
e.token = token;
|
|
1072
1116
|
e.payload = payload ?? null;
|
|
@@ -1074,7 +1118,7 @@ var MikroOrmStateStore = class {
|
|
|
1074
1118
|
await em.flush();
|
|
1075
1119
|
}
|
|
1076
1120
|
async takeBufferedSignal(token) {
|
|
1077
|
-
const em = this.
|
|
1121
|
+
const em = this.fork();
|
|
1078
1122
|
const entity = await em.findOne(BufferedSignalEntity, {
|
|
1079
1123
|
token
|
|
1080
1124
|
}, {
|