@dudousxd/nestjs-durable-store-mikro-orm 0.23.0 → 0.24.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 +86 -22
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +13 -3
- package/dist/index.d.ts +13 -3
- package/dist/index.js +87 -23
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
package/dist/index.cjs
CHANGED
|
@@ -1071,20 +1071,47 @@ var MikroOrmStateStore = class _MikroOrmStateStore {
|
|
|
1071
1071
|
* applied by the QueryBuilder path in both callers. */
|
|
1072
1072
|
runWhere(query) {
|
|
1073
1073
|
const where = {};
|
|
1074
|
+
const and = [];
|
|
1074
1075
|
if (query.workflow) where.workflow = query.workflow;
|
|
1076
|
+
if (query.workflows) and.push({
|
|
1077
|
+
workflow: {
|
|
1078
|
+
$in: query.workflows
|
|
1079
|
+
}
|
|
1080
|
+
});
|
|
1075
1081
|
if (query.namespace !== void 0) where.namespace = query.namespace;
|
|
1082
|
+
if (query.namespaces) and.push({
|
|
1083
|
+
namespace: {
|
|
1084
|
+
$in: query.namespaces
|
|
1085
|
+
}
|
|
1086
|
+
});
|
|
1076
1087
|
if (query.origin !== void 0) where.origin = query.origin;
|
|
1088
|
+
if (query.origins) {
|
|
1089
|
+
const named = query.origins.filter((o) => o !== null);
|
|
1090
|
+
const branches = [];
|
|
1091
|
+
if (named.length) branches.push({
|
|
1092
|
+
origin: {
|
|
1093
|
+
$in: named
|
|
1094
|
+
}
|
|
1095
|
+
});
|
|
1096
|
+
if (query.origins.some((o) => o === null)) branches.push({
|
|
1097
|
+
origin: null
|
|
1098
|
+
});
|
|
1099
|
+
and.push(branches.length ? {
|
|
1100
|
+
$or: branches
|
|
1101
|
+
} : {
|
|
1102
|
+
origin: {
|
|
1103
|
+
$in: []
|
|
1104
|
+
}
|
|
1105
|
+
});
|
|
1106
|
+
}
|
|
1077
1107
|
if (query.status && query.statuses) {
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
status: {
|
|
1084
|
-
$in: query.statuses
|
|
1085
|
-
}
|
|
1108
|
+
and.push({
|
|
1109
|
+
status: query.status
|
|
1110
|
+
}, {
|
|
1111
|
+
status: {
|
|
1112
|
+
$in: query.statuses
|
|
1086
1113
|
}
|
|
1087
|
-
|
|
1114
|
+
});
|
|
1088
1115
|
} else if (query.status) {
|
|
1089
1116
|
where.status = query.status;
|
|
1090
1117
|
} else if (query.statuses) {
|
|
@@ -1092,6 +1119,7 @@ var MikroOrmStateStore = class _MikroOrmStateStore {
|
|
|
1092
1119
|
$in: query.statuses
|
|
1093
1120
|
};
|
|
1094
1121
|
}
|
|
1122
|
+
if (and.length) where.$and = and;
|
|
1095
1123
|
return where;
|
|
1096
1124
|
}
|
|
1097
1125
|
async listRuns(query) {
|
|
@@ -1100,7 +1128,7 @@ var MikroOrmStateStore = class _MikroOrmStateStore {
|
|
|
1100
1128
|
const orderBy = {
|
|
1101
1129
|
createdAt: "desc"
|
|
1102
1130
|
};
|
|
1103
|
-
if (query.tag || query.attributes?.length) {
|
|
1131
|
+
if (query.tag || query.tags || query.attributes?.length) {
|
|
1104
1132
|
const qb = this.runQueryBuilder(em, query, where).orderBy(orderBy);
|
|
1105
1133
|
if (query.limit != null) qb.limit(query.limit);
|
|
1106
1134
|
if (query.offset != null) qb.offset(query.offset);
|
|
@@ -1126,17 +1154,23 @@ var MikroOrmStateStore = class _MikroOrmStateStore {
|
|
|
1126
1154
|
const quote = this.idQuote(em);
|
|
1127
1155
|
const cols = this.attributeColumns(em);
|
|
1128
1156
|
const qb = em.createQueryBuilder(WorkflowRunEntity, "r").where(where);
|
|
1129
|
-
if (query.tag)
|
|
1130
|
-
|
|
1131
|
-
const
|
|
1132
|
-
|
|
1133
|
-
qb.andWhere(`${colExpr} LIKE '${pattern}'`);
|
|
1157
|
+
if (query.tag) qb.andWhere(this.tagLikeSql(em, query.tag, quote));
|
|
1158
|
+
if (query.tags) {
|
|
1159
|
+
const branches = query.tags.map((t) => this.tagLikeSql(em, t, quote));
|
|
1160
|
+
qb.andWhere(branches.length ? `(${branches.join(" OR ")})` : "1 = 0");
|
|
1134
1161
|
}
|
|
1135
1162
|
for (const f of query.attributes ?? []) {
|
|
1136
1163
|
qb.andWhere(this.attributeExistsSql(f, quote, "r", cols));
|
|
1137
1164
|
}
|
|
1138
1165
|
return qb;
|
|
1139
1166
|
}
|
|
1167
|
+
/** `tags LIKE '%"etl"%'` — the quoted token, so `etl` doesn't match `etl-foo`. See the note in
|
|
1168
|
+
* {@link listRuns} for why this is raw SQL rather than a MikroORM condition. */
|
|
1169
|
+
tagLikeSql(em, tag, quote) {
|
|
1170
|
+
const pattern = `%"${tag.replace(/'/g, "''")}"%`;
|
|
1171
|
+
const colExpr = this.jsonAsText(em, `${quote("r")}.${quote(this.tagsColumn(em))}`);
|
|
1172
|
+
return `${colExpr} LIKE '${pattern}'`;
|
|
1173
|
+
}
|
|
1140
1174
|
/** `GROUP BY status, origin` over the same predicates {@link listRuns} pages — one aggregate, so a
|
|
1141
1175
|
* console can show whole-set counts next to a bounded page instead of downloading every run to
|
|
1142
1176
|
* count them in the browser. */
|
|
@@ -1157,20 +1191,50 @@ var MikroOrmStateStore = class _MikroOrmStateStore {
|
|
|
1157
1191
|
count: Number(r.count)
|
|
1158
1192
|
})));
|
|
1159
1193
|
}
|
|
1194
|
+
/** Distinct values of one filter axis over the same predicates {@link listRuns} pages. A run-table
|
|
1195
|
+
* column is a `GROUP BY` like {@link runFacets}, exact over the whole matching set; the tag and
|
|
1196
|
+
* attribute axes live outside the row (json array / side table) and are counted from a bounded
|
|
1197
|
+
* page of runs instead — see {@link RunValueFacetOptions.scan}. */
|
|
1198
|
+
async runValueFacets(axis, query, opts) {
|
|
1199
|
+
if (!(0, import_nestjs_durable_core.axisIsRunColumn)(axis)) {
|
|
1200
|
+
const runs = await this.listRuns({
|
|
1201
|
+
...query,
|
|
1202
|
+
limit: opts?.scan ?? import_nestjs_durable_core.RUN_VALUE_FACET_SCAN
|
|
1203
|
+
});
|
|
1204
|
+
return (0, import_nestjs_durable_core.runValueFacetsFromRuns)(runs, axis, opts);
|
|
1205
|
+
}
|
|
1206
|
+
const em = this.fork();
|
|
1207
|
+
const meta = em.getMetadata().get(WorkflowRunEntity);
|
|
1208
|
+
const col = meta.properties[axis.field]?.fieldNames?.[0] ?? axis.field;
|
|
1209
|
+
const rows = await this.runQueryBuilder(em, query, this.runWhere(query)).select([
|
|
1210
|
+
`r.${col}`
|
|
1211
|
+
]).addSelect((0, import_core3.raw)("count(*) as count")).groupBy([
|
|
1212
|
+
`r.${col}`
|
|
1213
|
+
]).execute();
|
|
1214
|
+
return (0, import_nestjs_durable_core.mergeRunValueFacetRows)(rows.map((row) => ({
|
|
1215
|
+
value: row[axis.field] ?? null,
|
|
1216
|
+
count: Number(row.count)
|
|
1217
|
+
})), opts);
|
|
1218
|
+
}
|
|
1160
1219
|
/** One attribute predicate as a raw EXISTS subquery on the side-table, correlated to the outer run
|
|
1161
1220
|
* alias. `<>` (ne) also excludes runs where the attribute is absent (missing-key-never-matches):
|
|
1162
1221
|
* EXISTS already requires a present row, so EXISTS(... <> ...) is exactly ne-with-present. Numeric
|
|
1163
|
-
* operands compare the num column, everything else the str column.
|
|
1164
|
-
*
|
|
1222
|
+
* operands compare the num column, everything else the str column. `in` contributes one comparison
|
|
1223
|
+
* per member, ORed inside the single EXISTS — one subquery either way, and an `in` over no values
|
|
1224
|
+
* yields no comparison and so matches nothing. Identifiers are quoted per driver and operands are
|
|
1225
|
+
* inlined as literals (string operands are escaped by doubling quotes). */
|
|
1165
1226
|
attributeExistsSql(f, quote, alias, cols) {
|
|
1166
|
-
const
|
|
1167
|
-
|
|
1168
|
-
|
|
1169
|
-
|
|
1227
|
+
const comparisons = (0, import_nestjs_durable_core.attributePredicateOperands)(f).map(({ column, comparator, operand }) => {
|
|
1228
|
+
const col = column === "numValue" ? cols.numValue : cols.strValue;
|
|
1229
|
+
const literal = typeof operand === "number" ? String(operand) : `'${String(operand).replace(/'/g, "''")}'`;
|
|
1230
|
+
return `${quote("a")}.${quote(col)} ${comparator} ${literal}`;
|
|
1231
|
+
});
|
|
1232
|
+
if (comparisons.length === 0) return "1 = 0";
|
|
1170
1233
|
const a = quote(cols.table);
|
|
1171
1234
|
const sub = quote("a");
|
|
1172
1235
|
const outerId = `${quote(alias)}.${quote(cols.runPk)}`;
|
|
1173
|
-
|
|
1236
|
+
const match = comparisons.length === 1 ? comparisons[0] : `(${comparisons.join(" OR ")})`;
|
|
1237
|
+
return `EXISTS (SELECT 1 FROM ${a} ${sub} WHERE ${sub}.${quote(cols.runId)} = ${outerId} AND ${sub}.${quote(cols.key)} = '${f.key.replace(/'/g, "''")}' AND ${match})`;
|
|
1174
1238
|
}
|
|
1175
1239
|
/** Resolve the side-table's actual column names from MikroORM metadata, so the raw EXISTS matches
|
|
1176
1240
|
* the active naming strategy (underscore vs camelCase) rather than guessing. The run PK column is
|