@dudousxd/nestjs-durable-store-drizzle 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 +2 -2
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +2 -2
- package/dist/index.js.map +1 -1
- package/dist/pg/index.cjs +105 -39
- package/dist/pg/index.cjs.map +1 -1
- package/dist/pg/index.d.cts +37 -3
- package/dist/pg/index.d.ts +37 -3
- package/dist/pg/index.js +104 -39
- package/dist/pg/index.js.map +1 -1
- package/package.json +3 -3
package/dist/pg/index.cjs
CHANGED
|
@@ -25,6 +25,7 @@ __export(pg_exports, {
|
|
|
25
25
|
DURABLE_PG_DDL: () => DURABLE_PG_DDL,
|
|
26
26
|
DrizzlePgStateStore: () => DrizzlePgStateStore,
|
|
27
27
|
drizzlePgExecutor: () => drizzlePgExecutor,
|
|
28
|
+
drizzlePgSchemaRepairWarning: () => drizzlePgSchemaRepairWarning,
|
|
28
29
|
durableBufferedEvents: () => durableBufferedEvents,
|
|
29
30
|
durableBufferedSignals: () => durableBufferedSignals,
|
|
30
31
|
durablePgManagedTables: () => durablePgManagedTables,
|
|
@@ -41,7 +42,41 @@ __export(pg_exports, {
|
|
|
41
42
|
module.exports = __toCommonJS(pg_exports);
|
|
42
43
|
|
|
43
44
|
// src/pg/ddl.ts
|
|
45
|
+
var import_drizzle_orm2 = require("drizzle-orm");
|
|
46
|
+
|
|
47
|
+
// src/pg/executor.ts
|
|
44
48
|
var import_drizzle_orm = require("drizzle-orm");
|
|
49
|
+
function toDrizzleSql(text2, params = []) {
|
|
50
|
+
const chunks = [];
|
|
51
|
+
let last = 0;
|
|
52
|
+
for (const match of text2.matchAll(/\$(\d+)/g)) {
|
|
53
|
+
const index2 = Number(match[1]) - 1;
|
|
54
|
+
if (index2 < 0 || index2 >= params.length) throw new Error(`placeholder ${match[0]} has no bound parameter`);
|
|
55
|
+
chunks.push(import_drizzle_orm.sql.raw(text2.slice(last, match.index)), import_drizzle_orm.sql`${params[index2]}`);
|
|
56
|
+
last = (match.index ?? 0) + match[0].length;
|
|
57
|
+
}
|
|
58
|
+
chunks.push(import_drizzle_orm.sql.raw(text2.slice(last)));
|
|
59
|
+
return import_drizzle_orm.sql.join(chunks);
|
|
60
|
+
}
|
|
61
|
+
__name(toDrizzleSql, "toDrizzleSql");
|
|
62
|
+
function rowsOf(result) {
|
|
63
|
+
if (Array.isArray(result)) return result;
|
|
64
|
+
return result?.rows ?? [];
|
|
65
|
+
}
|
|
66
|
+
__name(rowsOf, "rowsOf");
|
|
67
|
+
function drizzlePgExecutor(db) {
|
|
68
|
+
return {
|
|
69
|
+
dialect: "postgres",
|
|
70
|
+
escapeId: /* @__PURE__ */ __name((id) => `"${id.replace(/"/g, '""')}"`, "escapeId"),
|
|
71
|
+
query: /* @__PURE__ */ __name(async (text2, params) => rowsOf(await db.execute(toDrizzleSql(text2, params))), "query"),
|
|
72
|
+
transaction: /* @__PURE__ */ __name((fn) => db.transaction((tx) => fn({
|
|
73
|
+
query: /* @__PURE__ */ __name(async (text2, params) => rowsOf(await tx.execute(toDrizzleSql(text2, params))), "query")
|
|
74
|
+
})), "transaction")
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
__name(drizzlePgExecutor, "drizzlePgExecutor");
|
|
78
|
+
|
|
79
|
+
// src/pg/ddl.ts
|
|
45
80
|
var DURABLE_PG_DDL = [
|
|
46
81
|
`CREATE TABLE IF NOT EXISTS "durable_workflow_runs" (
|
|
47
82
|
"id" text PRIMARY KEY NOT NULL,
|
|
@@ -134,11 +169,71 @@ var DURABLE_PG_DDL = [
|
|
|
134
169
|
`CREATE INDEX IF NOT EXISTS "durable_schedules_due_idx" ON "durable_schedules" USING btree ("paused","next_fire_at")`
|
|
135
170
|
];
|
|
136
171
|
var SCHEMA_LOCK_KEY = "durable_schema";
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
172
|
+
function drizzlePgSchemaRepairWarning(repairs) {
|
|
173
|
+
return [
|
|
174
|
+
`[nestjs-durable] store-drizzle repaired the durable schema at boot: ${repairs.join("; ")}.`,
|
|
175
|
+
"The database had drifted from the schema this library version expects (it was created by an",
|
|
176
|
+
"older version, or a migration left these out), so they were applied at runtime and nothing",
|
|
177
|
+
"recorded them in your migration history. To make them permanent, generate a drizzle-kit",
|
|
178
|
+
"migration from `durablePgSchema` (or apply `DURABLE_PG_DDL` in a migration). This warning",
|
|
179
|
+
"appears only when a repair was applied; a schema that is already current logs nothing."
|
|
180
|
+
].join(" ");
|
|
181
|
+
}
|
|
182
|
+
__name(drizzlePgSchemaRepairWarning, "drizzlePgSchemaRepairWarning");
|
|
183
|
+
function ddlTarget(statement) {
|
|
184
|
+
const table = statement.match(/^CREATE TABLE IF NOT EXISTS "([^"]+)"/i);
|
|
185
|
+
if (table?.[1]) return {
|
|
186
|
+
kind: "table",
|
|
187
|
+
table: table[1]
|
|
188
|
+
};
|
|
189
|
+
const index2 = statement.match(/^CREATE (?:UNIQUE )?INDEX (?:CONCURRENTLY )?IF NOT EXISTS "([^"]+)" ON "([^"]+)"/i);
|
|
190
|
+
if (index2?.[1] && index2[2]) return {
|
|
191
|
+
kind: "index",
|
|
192
|
+
index: index2[1],
|
|
193
|
+
table: index2[2]
|
|
194
|
+
};
|
|
195
|
+
const column = statement.match(/^ALTER TABLE "([^"]+)" ADD COLUMN IF NOT EXISTS "([^"]+)"/i);
|
|
196
|
+
if (column?.[1] && column[2]) return {
|
|
197
|
+
kind: "column",
|
|
198
|
+
table: column[1],
|
|
199
|
+
column: column[2]
|
|
200
|
+
};
|
|
201
|
+
return void 0;
|
|
202
|
+
}
|
|
203
|
+
__name(ddlTarget, "ddlTarget");
|
|
204
|
+
async function ensureDrizzlePgDurableSchema(db, options = {}) {
|
|
205
|
+
const logger = options.logger ?? console;
|
|
206
|
+
const { repairs, freshInstall } = await db.transaction(async (tx) => {
|
|
207
|
+
await tx.execute(import_drizzle_orm2.sql`SELECT pg_advisory_xact_lock(hashtext(${SCHEMA_LOCK_KEY}))`);
|
|
208
|
+
const tables = new Set(rowsOf(await tx.execute(import_drizzle_orm2.sql.raw("SELECT tablename AS name FROM pg_tables WHERE schemaname = current_schema() AND left(tablename, 8) = 'durable_'"))).map((row) => row.name));
|
|
209
|
+
const indexes = new Set(rowsOf(await tx.execute(import_drizzle_orm2.sql.raw("SELECT indexname AS name FROM pg_indexes WHERE schemaname = current_schema() AND left(tablename, 8) = 'durable_'"))).map((row) => row.name));
|
|
210
|
+
const columns = new Set(rowsOf(await tx.execute(import_drizzle_orm2.sql.raw("SELECT table_name || '.' || column_name AS name FROM information_schema.columns WHERE table_schema = current_schema() AND left(table_name, 8) = 'durable_'"))).map((row) => row.name));
|
|
211
|
+
const created = /* @__PURE__ */ new Set();
|
|
212
|
+
const ddlTables = /* @__PURE__ */ new Set();
|
|
213
|
+
const applied = [];
|
|
214
|
+
for (const statement of DURABLE_PG_DDL) {
|
|
215
|
+
const target = ddlTarget(statement);
|
|
216
|
+
await tx.execute(import_drizzle_orm2.sql.raw(statement));
|
|
217
|
+
if (!target) continue;
|
|
218
|
+
if (target.kind === "table") {
|
|
219
|
+
ddlTables.add(target.table);
|
|
220
|
+
if (!tables.has(target.table)) {
|
|
221
|
+
created.add(target.table);
|
|
222
|
+
applied.push(`created table ${target.table}`);
|
|
223
|
+
}
|
|
224
|
+
} else if (created.has(target.table)) {
|
|
225
|
+
} else if (target.kind === "index" && !indexes.has(target.index)) {
|
|
226
|
+
applied.push(`created index ${target.index} on ${target.table}`);
|
|
227
|
+
} else if (target.kind === "column" && !columns.has(`${target.table}.${target.column}`)) {
|
|
228
|
+
applied.push(`added column ${target.table}.${target.column}`);
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
return {
|
|
232
|
+
repairs: applied,
|
|
233
|
+
freshInstall: created.size === ddlTables.size
|
|
234
|
+
};
|
|
141
235
|
});
|
|
236
|
+
if (repairs.length > 0 && !freshInstall) logger.warn(drizzlePgSchemaRepairWarning(repairs));
|
|
142
237
|
}
|
|
143
238
|
__name(ensureDrizzlePgDurableSchema, "ensureDrizzlePgDurableSchema");
|
|
144
239
|
|
|
@@ -146,38 +241,6 @@ __name(ensureDrizzlePgDurableSchema, "ensureDrizzlePgDurableSchema");
|
|
|
146
241
|
var import_nestjs_durable_core = require("@dudousxd/nestjs-durable-core");
|
|
147
242
|
var import_drizzle_orm4 = require("drizzle-orm");
|
|
148
243
|
|
|
149
|
-
// src/pg/executor.ts
|
|
150
|
-
var import_drizzle_orm2 = require("drizzle-orm");
|
|
151
|
-
function toDrizzleSql(text2, params = []) {
|
|
152
|
-
const chunks = [];
|
|
153
|
-
let last = 0;
|
|
154
|
-
for (const match of text2.matchAll(/\$(\d+)/g)) {
|
|
155
|
-
const index2 = Number(match[1]) - 1;
|
|
156
|
-
if (index2 < 0 || index2 >= params.length) throw new Error(`placeholder ${match[0]} has no bound parameter`);
|
|
157
|
-
chunks.push(import_drizzle_orm2.sql.raw(text2.slice(last, match.index)), import_drizzle_orm2.sql`${params[index2]}`);
|
|
158
|
-
last = (match.index ?? 0) + match[0].length;
|
|
159
|
-
}
|
|
160
|
-
chunks.push(import_drizzle_orm2.sql.raw(text2.slice(last)));
|
|
161
|
-
return import_drizzle_orm2.sql.join(chunks);
|
|
162
|
-
}
|
|
163
|
-
__name(toDrizzleSql, "toDrizzleSql");
|
|
164
|
-
function rowsOf(result) {
|
|
165
|
-
if (Array.isArray(result)) return result;
|
|
166
|
-
return result?.rows ?? [];
|
|
167
|
-
}
|
|
168
|
-
__name(rowsOf, "rowsOf");
|
|
169
|
-
function drizzlePgExecutor(db) {
|
|
170
|
-
return {
|
|
171
|
-
dialect: "postgres",
|
|
172
|
-
escapeId: /* @__PURE__ */ __name((id) => `"${id.replace(/"/g, '""')}"`, "escapeId"),
|
|
173
|
-
query: /* @__PURE__ */ __name(async (text2, params) => rowsOf(await db.execute(toDrizzleSql(text2, params))), "query"),
|
|
174
|
-
transaction: /* @__PURE__ */ __name((fn) => db.transaction((tx) => fn({
|
|
175
|
-
query: /* @__PURE__ */ __name(async (text2, params) => rowsOf(await tx.execute(toDrizzleSql(text2, params))), "query")
|
|
176
|
-
})), "transaction")
|
|
177
|
-
};
|
|
178
|
-
}
|
|
179
|
-
__name(drizzlePgExecutor, "drizzlePgExecutor");
|
|
180
|
-
|
|
181
244
|
// src/pg/schema.ts
|
|
182
245
|
var import_drizzle_orm3 = require("drizzle-orm");
|
|
183
246
|
var import_pg_core = require("drizzle-orm/pg-core");
|
|
@@ -390,7 +453,9 @@ var DrizzlePgStateStore = class _DrizzlePgStateStore {
|
|
|
390
453
|
/** Idempotent CREATE TABLE / INDEX IF NOT EXISTS under an advisory lock — called on boot when the
|
|
391
454
|
* module's `autoSchema` is on. Turn `autoSchema` off if drizzle-kit owns these tables. */
|
|
392
455
|
async ensureSchema() {
|
|
393
|
-
await ensureDrizzlePgDurableSchema(this.db
|
|
456
|
+
await ensureDrizzlePgDurableSchema(this.db, {
|
|
457
|
+
logger: this.options.schemaLogger
|
|
458
|
+
});
|
|
394
459
|
}
|
|
395
460
|
/** The read-scope predicate on the runs table (undefined when the store is unscoped). */
|
|
396
461
|
scope() {
|
|
@@ -588,11 +653,11 @@ var DrizzlePgStateStore = class _DrizzlePgStateStore {
|
|
|
588
653
|
});
|
|
589
654
|
return rows.length === 1;
|
|
590
655
|
}
|
|
591
|
-
async releaseRunLock(runId) {
|
|
656
|
+
async releaseRunLock(runId, owner) {
|
|
592
657
|
await this.db.update(durableWorkflowRuns).set({
|
|
593
658
|
lockedBy: null,
|
|
594
659
|
lockedUntil: null
|
|
595
|
-
}).where((0, import_drizzle_orm4.eq)(durableWorkflowRuns.id, runId));
|
|
660
|
+
}).where(owner === void 0 ? (0, import_drizzle_orm4.eq)(durableWorkflowRuns.id, runId) : (0, import_drizzle_orm4.and)((0, import_drizzle_orm4.eq)(durableWorkflowRuns.id, runId), (0, import_drizzle_orm4.eq)(durableWorkflowRuns.lockedBy, owner)));
|
|
596
661
|
}
|
|
597
662
|
async renewRunLock(runId, owner, leaseUntilMs) {
|
|
598
663
|
const rows = await this.db.update(durableWorkflowRuns).set({
|
|
@@ -1140,6 +1205,7 @@ __name(excludedSet, "excludedSet");
|
|
|
1140
1205
|
DURABLE_PG_DDL,
|
|
1141
1206
|
DrizzlePgStateStore,
|
|
1142
1207
|
drizzlePgExecutor,
|
|
1208
|
+
drizzlePgSchemaRepairWarning,
|
|
1143
1209
|
durableBufferedEvents,
|
|
1144
1210
|
durableBufferedSignals,
|
|
1145
1211
|
durablePgManagedTables,
|