tempest-db-js 0.1.0 → 0.3.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/bin.cjs ADDED
@@ -0,0 +1,1191 @@
1
+ #!/usr/bin/env node
2
+ 'use strict';
3
+
4
+ var fs = require('fs');
5
+ var path = require('path');
6
+ var promises = require('readline/promises');
7
+ var url = require('url');
8
+
9
+ var _documentCurrentScript = typeof document !== 'undefined' ? document.currentScript : null;
10
+ // src/migrations/operations.ts
11
+ var IrreversibleMigration = class extends Error {
12
+ constructor(message) {
13
+ super(message);
14
+ this.name = "IrreversibleMigration";
15
+ }
16
+ };
17
+ function invert(op) {
18
+ switch (op.kind) {
19
+ case "create_table":
20
+ return { kind: "drop_table", table: op.table };
21
+ case "drop_table":
22
+ return { kind: "create_table", table: op.table };
23
+ case "rename_table":
24
+ return { kind: "rename_table", from: op.to, to: op.from };
25
+ case "add_column":
26
+ return { kind: "drop_column", table: op.table, column: op.column };
27
+ case "drop_column":
28
+ return { kind: "add_column", table: op.table, column: op.column };
29
+ case "alter_column":
30
+ return {
31
+ kind: "alter_column",
32
+ table: op.table,
33
+ name: op.name,
34
+ from: op.to,
35
+ to: op.from
36
+ };
37
+ case "rename_column":
38
+ return { kind: "rename_column", table: op.table, from: op.to, to: op.from };
39
+ case "recreate_table":
40
+ return { kind: "recreate_table", from: op.to, to: op.from };
41
+ case "execute":
42
+ if (op.down === null) {
43
+ throw new IrreversibleMigration("execute() operation has no down SQL");
44
+ }
45
+ return { kind: "execute", up: op.down, down: op.up };
46
+ }
47
+ }
48
+ function invertAll(ops) {
49
+ return [...ops].reverse().map(invert);
50
+ }
51
+
52
+ // src/migrations/codegen.ts
53
+ function renderOps(ops) {
54
+ if (ops.length === 0) return "[]";
55
+ const body = ops.map((op) => ` ${JSON.stringify(op)},`).join("\n");
56
+ return `[
57
+ ${body}
58
+ ]`;
59
+ }
60
+ function generateMigration(draft) {
61
+ let down;
62
+ try {
63
+ down = renderOps(invertAll(draft.operations));
64
+ } catch (error) {
65
+ down = `(() => { throw new Error(${JSON.stringify(
66
+ `irreversible migration: ${error.message}`
67
+ )}); })()`;
68
+ }
69
+ return `import type { Migration, Op } from "tempest-db-js/migrations";
70
+
71
+ export const revision = ${JSON.stringify(draft.revision)};
72
+ export const downRevision: string[] = ${JSON.stringify(draft.downRevision)};
73
+ export const label = ${JSON.stringify(draft.label)};
74
+
75
+ const upOps = ${renderOps(draft.operations)};
76
+
77
+ const downOps = ${down};
78
+
79
+ export const up = (op: Op): void => {
80
+ for (const operation of upOps) op.run(operation);
81
+ };
82
+
83
+ export const down = (op: Op): void => {
84
+ for (const operation of downOps) op.run(operation);
85
+ };
86
+
87
+ export default { revision, downRevision, label, up, down } satisfies Migration;
88
+ `;
89
+ }
90
+ function makeRevisionId(label, parents) {
91
+ let hash = 2166136261;
92
+ for (const ch of `${label}|${[...parents].sort().join(",")}`) {
93
+ hash ^= ch.charCodeAt(0);
94
+ hash = Math.imul(hash, 16777619) >>> 0;
95
+ }
96
+ return hash.toString(16).padStart(8, "0");
97
+ }
98
+
99
+ // src/migrations/ddl.ts
100
+ function quoteId(name, dialect) {
101
+ return dialect === "mysql" ? `\`${name.replace(/`/g, "``")}\`` : `"${name.replace(/"/g, '""')}"`;
102
+ }
103
+ function quoteLiteral(value) {
104
+ return `'${value.replace(/'/g, "''")}'`;
105
+ }
106
+ function renderColumnType(type, dialect) {
107
+ const { kind, meta } = type;
108
+ if (dialect === "sqlite") {
109
+ switch (kind) {
110
+ case "smallint":
111
+ case "integer":
112
+ case "bigint":
113
+ case "boolean":
114
+ return "INTEGER";
115
+ case "real":
116
+ case "double":
117
+ return "REAL";
118
+ case "numeric":
119
+ return "NUMERIC";
120
+ case "blob":
121
+ return "BLOB";
122
+ default:
123
+ return "TEXT";
124
+ }
125
+ }
126
+ if (dialect === "mysql") {
127
+ switch (kind) {
128
+ case "smallint":
129
+ return "SMALLINT";
130
+ case "integer":
131
+ return "INT";
132
+ case "bigint":
133
+ return "BIGINT";
134
+ case "numeric":
135
+ return meta.precision !== void 0 ? `DECIMAL(${meta.precision}${meta.scale !== void 0 ? `, ${meta.scale}` : ""})` : "DECIMAL";
136
+ case "real":
137
+ return "FLOAT";
138
+ case "double":
139
+ return "DOUBLE";
140
+ case "varchar":
141
+ return `VARCHAR(${meta.length ?? 255})`;
142
+ case "char":
143
+ return `CHAR(${meta.length ?? 255})`;
144
+ case "text":
145
+ return "TEXT";
146
+ case "boolean":
147
+ return "TINYINT(1)";
148
+ case "date":
149
+ return "DATE";
150
+ case "time":
151
+ return "TIME";
152
+ case "datetime":
153
+ case "timestamp":
154
+ return "DATETIME";
155
+ case "blob":
156
+ return "BLOB";
157
+ case "json":
158
+ return "JSON";
159
+ case "uuid":
160
+ return "CHAR(36)";
161
+ case "enum":
162
+ return `ENUM(${(meta.values ?? []).map(quoteLiteral).join(", ")})`;
163
+ }
164
+ }
165
+ switch (kind) {
166
+ case "smallint":
167
+ return "SMALLINT";
168
+ case "integer":
169
+ return "INTEGER";
170
+ case "bigint":
171
+ return "BIGINT";
172
+ case "numeric":
173
+ return meta.precision !== void 0 ? `NUMERIC(${meta.precision}${meta.scale !== void 0 ? `, ${meta.scale}` : ""})` : "NUMERIC";
174
+ case "real":
175
+ return "REAL";
176
+ case "double":
177
+ return "DOUBLE PRECISION";
178
+ case "varchar":
179
+ return meta.length !== void 0 ? `VARCHAR(${meta.length})` : "VARCHAR";
180
+ case "char":
181
+ return meta.length !== void 0 ? `CHAR(${meta.length})` : "CHAR";
182
+ case "text":
183
+ return "TEXT";
184
+ case "boolean":
185
+ return "BOOLEAN";
186
+ case "date":
187
+ return "DATE";
188
+ case "time":
189
+ return meta.withTimezone ? "TIME WITH TIME ZONE" : "TIME";
190
+ case "datetime":
191
+ case "timestamp":
192
+ return meta.withTimezone ? "TIMESTAMP WITH TIME ZONE" : "TIMESTAMP";
193
+ case "blob":
194
+ return "BYTEA";
195
+ case "json":
196
+ return meta.jsonb ? "JSONB" : "JSON";
197
+ case "uuid":
198
+ return "UUID";
199
+ case "enum":
200
+ return "TEXT";
201
+ }
202
+ }
203
+ function renderDefault(def, dialect) {
204
+ if (def.kind === "expression") {
205
+ const expr = def.expression;
206
+ if (typeof expr === "object") return expr.raw;
207
+ switch (expr) {
208
+ case "now":
209
+ return dialect === "postgresql" ? "now()" : "CURRENT_TIMESTAMP";
210
+ case "current_date":
211
+ return "CURRENT_DATE";
212
+ case "current_time":
213
+ return "CURRENT_TIME";
214
+ case "uuidv4":
215
+ if (dialect === "postgresql") return "gen_random_uuid()";
216
+ if (dialect === "mysql") return "(UUID())";
217
+ return "(lower(hex(randomblob(16))))";
218
+ }
219
+ }
220
+ const value = def.value;
221
+ if (value === null) return "NULL";
222
+ if (typeof value === "boolean") {
223
+ return dialect === "postgresql" ? value ? "TRUE" : "FALSE" : value ? "1" : "0";
224
+ }
225
+ if (typeof value === "number" || typeof value === "bigint") return String(value);
226
+ if (value instanceof Date) return quoteLiteral(value.toISOString());
227
+ if (typeof value === "object") return quoteLiteral(JSON.stringify(value));
228
+ return quoteLiteral(String(value));
229
+ }
230
+ function renderColumnDef(col, dialect) {
231
+ let sql = `${quoteId(col.name, dialect)} ${renderColumnType(col.type, dialect)}`;
232
+ if (col.notNull) sql += " NOT NULL";
233
+ if (col.default !== null) sql += ` DEFAULT ${renderDefault(col.default, dialect)}`;
234
+ return sql;
235
+ }
236
+ function enumTypeName(table, column) {
237
+ return `${table}_${column}`;
238
+ }
239
+ function isAutoIncrementPk(table, col) {
240
+ return table.primaryKey.length === 1 && table.primaryKey[0] === col.name && col.default === null && (col.type.kind === "smallint" || col.type.kind === "integer" || col.type.kind === "bigint");
241
+ }
242
+ function postgresSerialType(kind) {
243
+ if (kind === "bigint") return "BIGSERIAL";
244
+ if (kind === "smallint") return "SMALLSERIAL";
245
+ return "SERIAL";
246
+ }
247
+ function renderCreateTable(table, dialect) {
248
+ const typeStmts = [];
249
+ const cols = Object.values(table.columns).map((c) => {
250
+ if (dialect === "postgresql" && c.type.kind === "enum") {
251
+ const typeName = enumTypeName(table.name, c.name);
252
+ const values = (c.type.meta.values ?? []).map(quoteLiteral).join(", ");
253
+ typeStmts.push(`CREATE TYPE ${quoteId(typeName, dialect)} AS ENUM (${values})`);
254
+ let def = `${quoteId(c.name, dialect)} ${quoteId(typeName, dialect)}`;
255
+ if (c.notNull) def += " NOT NULL";
256
+ if (c.default !== null) def += ` DEFAULT ${renderDefault(c.default, dialect)}`;
257
+ return def;
258
+ }
259
+ if (dialect === "postgresql" && isAutoIncrementPk(table, c)) {
260
+ return `${quoteId(c.name, dialect)} ${postgresSerialType(c.type.kind)}`;
261
+ }
262
+ if (dialect === "mysql" && isAutoIncrementPk(table, c)) {
263
+ return `${quoteId(c.name, dialect)} ${renderColumnType(c.type, dialect)} NOT NULL AUTO_INCREMENT`;
264
+ }
265
+ return renderColumnDef(c, dialect);
266
+ });
267
+ if (table.primaryKey.length > 0) {
268
+ cols.push(
269
+ `PRIMARY KEY (${table.primaryKey.map((c) => quoteId(c, dialect)).join(", ")})`
270
+ );
271
+ }
272
+ return [
273
+ ...typeStmts,
274
+ `CREATE TABLE ${quoteId(table.name, dialect)} (
275
+ ${cols.join(",\n ")}
276
+ )`
277
+ ];
278
+ }
279
+ function renderOperation(op, dialect) {
280
+ switch (op.kind) {
281
+ case "create_table":
282
+ return renderCreateTable(op.table, dialect);
283
+ case "drop_table":
284
+ return [`DROP TABLE ${quoteId(op.table.name, dialect)}`];
285
+ case "rename_table":
286
+ return dialect === "mysql" ? [`RENAME TABLE ${quoteId(op.from, dialect)} TO ${quoteId(op.to, dialect)}`] : [
287
+ `ALTER TABLE ${quoteId(op.from, dialect)} RENAME TO ${quoteId(op.to, dialect)}`
288
+ ];
289
+ case "add_column":
290
+ return [
291
+ `ALTER TABLE ${quoteId(op.table, dialect)} ADD COLUMN ${renderColumnDef(op.column, dialect)}`
292
+ ];
293
+ case "drop_column":
294
+ return [
295
+ `ALTER TABLE ${quoteId(op.table, dialect)} DROP COLUMN ${quoteId(op.column.name, dialect)}`
296
+ ];
297
+ case "rename_column":
298
+ return [
299
+ `ALTER TABLE ${quoteId(op.table, dialect)} RENAME COLUMN ${quoteId(op.from, dialect)} TO ${quoteId(op.to, dialect)}`
300
+ ];
301
+ case "alter_column":
302
+ return renderAlterColumn(op.table, op.to, dialect);
303
+ case "recreate_table":
304
+ return dialect === "sqlite" ? renderSqliteRebuild(op.from, op.to) : renderTableDiff(op.from, op.to, dialect);
305
+ case "execute":
306
+ return [op.up];
307
+ }
308
+ }
309
+ function renderSqliteRebuild(from, to) {
310
+ const tmp = `__new_${to.name}`;
311
+ const common = Object.keys(to.columns).filter((c) => c in from.columns);
312
+ const cols = Object.values(to.columns).map((c) => renderColumnDef(c, "sqlite"));
313
+ if (to.primaryKey.length > 0) {
314
+ cols.push(
315
+ `PRIMARY KEY (${to.primaryKey.map((c) => quoteId(c, "sqlite")).join(", ")})`
316
+ );
317
+ }
318
+ const commonSql = common.map((c) => quoteId(c, "sqlite")).join(", ");
319
+ return [
320
+ "PRAGMA foreign_keys=off",
321
+ `CREATE TABLE ${quoteId(tmp, "sqlite")} (
322
+ ${cols.join(",\n ")}
323
+ )`,
324
+ common.length > 0 ? `INSERT INTO ${quoteId(tmp, "sqlite")} (${commonSql}) SELECT ${commonSql} FROM ${quoteId(from.name, "sqlite")}` : `-- no common columns to copy from ${from.name}`,
325
+ `DROP TABLE ${quoteId(from.name, "sqlite")}`,
326
+ `ALTER TABLE ${quoteId(tmp, "sqlite")} RENAME TO ${quoteId(to.name, "sqlite")}`,
327
+ "PRAGMA foreign_keys=on"
328
+ ];
329
+ }
330
+ function renderTableDiff(from, to, dialect) {
331
+ const stmts = [];
332
+ for (const [name, col] of Object.entries(to.columns)) {
333
+ if (!(name in from.columns)) {
334
+ stmts.push(
335
+ `ALTER TABLE ${quoteId(to.name, dialect)} ADD COLUMN ${renderColumnDef(col, dialect)}`
336
+ );
337
+ } else {
338
+ stmts.push(...renderAlterColumn(to.name, col, dialect));
339
+ }
340
+ }
341
+ for (const name of Object.keys(from.columns)) {
342
+ if (!(name in to.columns)) {
343
+ stmts.push(
344
+ `ALTER TABLE ${quoteId(to.name, dialect)} DROP COLUMN ${quoteId(name, dialect)}`
345
+ );
346
+ }
347
+ }
348
+ return stmts;
349
+ }
350
+ function renderAlterColumn(table, to, dialect) {
351
+ if (dialect === "sqlite") {
352
+ throw new Error(
353
+ `alter_column on SQLite needs a table-rebuild (recreate_table); column ${table}.${to.name}`
354
+ );
355
+ }
356
+ if (dialect === "mysql") {
357
+ return [
358
+ `ALTER TABLE ${quoteId(table, dialect)} MODIFY COLUMN ${renderColumnDef(to, dialect)}`
359
+ ];
360
+ }
361
+ const t = quoteId(table, dialect);
362
+ const c = quoteId(to.name, dialect);
363
+ const stmts = [
364
+ `ALTER TABLE ${t} ALTER COLUMN ${c} TYPE ${renderColumnType(to.type, dialect)}`
365
+ ];
366
+ stmts.push(
367
+ to.notNull ? `ALTER TABLE ${t} ALTER COLUMN ${c} SET NOT NULL` : `ALTER TABLE ${t} ALTER COLUMN ${c} DROP NOT NULL`
368
+ );
369
+ stmts.push(
370
+ to.default !== null ? `ALTER TABLE ${t} ALTER COLUMN ${c} SET DEFAULT ${renderDefault(to.default, dialect)}` : `ALTER TABLE ${t} ALTER COLUMN ${c} DROP DEFAULT`
371
+ );
372
+ return stmts;
373
+ }
374
+
375
+ // src/migrations/diff.ts
376
+ function columnSignature(col) {
377
+ return JSON.stringify({
378
+ type: col.type,
379
+ notNull: col.notNull,
380
+ primaryKey: col.primaryKey,
381
+ default: col.default
382
+ });
383
+ }
384
+ function diffSchema(current, target) {
385
+ const ops = [];
386
+ const drops = [];
387
+ for (const [name, targetTable] of Object.entries(target.tables)) {
388
+ const currentTable = current.tables[name];
389
+ if (!currentTable) {
390
+ ops.push({ kind: "create_table", table: targetTable });
391
+ continue;
392
+ }
393
+ for (const [colName, targetCol] of Object.entries(targetTable.columns)) {
394
+ const currentCol = currentTable.columns[colName];
395
+ if (!currentCol) {
396
+ ops.push({ kind: "add_column", table: name, column: targetCol });
397
+ } else if (columnSignature(currentCol) !== columnSignature(targetCol)) {
398
+ ops.push({
399
+ kind: "alter_column",
400
+ table: name,
401
+ name: colName,
402
+ from: currentCol,
403
+ to: targetCol
404
+ });
405
+ }
406
+ }
407
+ for (const [colName, currentCol] of Object.entries(currentTable.columns)) {
408
+ if (!targetTable.columns[colName]) {
409
+ ops.push({ kind: "drop_column", table: name, column: currentCol });
410
+ }
411
+ }
412
+ }
413
+ for (const [name, currentTable] of Object.entries(current.tables)) {
414
+ if (!target.tables[name]) {
415
+ drops.push({ kind: "drop_table", table: currentTable });
416
+ }
417
+ }
418
+ return [...ops, ...drops];
419
+ }
420
+
421
+ // src/migrations/graph.ts
422
+ var CyclicMigrationGraph = class extends Error {
423
+ constructor(remaining) {
424
+ super(`migration graph has a cycle among: ${remaining.join(", ")}`);
425
+ this.name = "CyclicMigrationGraph";
426
+ }
427
+ };
428
+ var UnknownRevision = class extends Error {
429
+ constructor(revision, parent) {
430
+ super(`revision ${revision} references unknown parent ${parent}`);
431
+ this.name = "UnknownRevision";
432
+ }
433
+ };
434
+ function topoOrder(migrations) {
435
+ const byId = /* @__PURE__ */ new Map();
436
+ for (const m of migrations) byId.set(m.revision, m);
437
+ const indegree = /* @__PURE__ */ new Map();
438
+ const children = /* @__PURE__ */ new Map();
439
+ for (const m of migrations) {
440
+ indegree.set(m.revision, m.downRevision.length);
441
+ for (const parent of m.downRevision) {
442
+ if (!byId.has(parent)) throw new UnknownRevision(m.revision, parent);
443
+ const list = children.get(parent) ?? [];
444
+ list.push(m.revision);
445
+ children.set(parent, list);
446
+ }
447
+ }
448
+ const ready = migrations.filter((m) => (indegree.get(m.revision) ?? 0) === 0).map((m) => m.revision).sort();
449
+ const ordered = [];
450
+ while (ready.length > 0) {
451
+ const id = ready.shift();
452
+ ordered.push(byId.get(id));
453
+ const next = (children.get(id) ?? []).sort();
454
+ for (const child of next) {
455
+ const deg = (indegree.get(child) ?? 0) - 1;
456
+ indegree.set(child, deg);
457
+ if (deg === 0) {
458
+ ready.push(child);
459
+ ready.sort();
460
+ }
461
+ }
462
+ }
463
+ if (ordered.length !== migrations.length) {
464
+ const remaining = migrations.map((m) => m.revision).filter((r) => !ordered.some((o) => o.revision === r));
465
+ throw new CyclicMigrationGraph(remaining);
466
+ }
467
+ return ordered;
468
+ }
469
+ function heads(migrations) {
470
+ const parents = /* @__PURE__ */ new Set();
471
+ for (const m of migrations) for (const p of m.downRevision) parents.add(p);
472
+ return migrations.map((m) => m.revision).filter((r) => !parents.has(r)).sort();
473
+ }
474
+
475
+ // src/index.ts
476
+ function isDefaultValue(value) {
477
+ return typeof value === "object" && value !== null && "kind" in value && (value.kind === "literal" || value.kind === "expression");
478
+ }
479
+ var Column = class _Column {
480
+ constructor(type, flags, defaultValue = null, onUpdateValue = null) {
481
+ this.type = type;
482
+ this.flags = flags;
483
+ this.defaultValue = defaultValue;
484
+ this.onUpdateValue = onUpdateValue;
485
+ }
486
+ type;
487
+ flags;
488
+ defaultValue;
489
+ onUpdateValue;
490
+ primaryKey() {
491
+ return new _Column(
492
+ this.type,
493
+ { ...this.flags, primaryKey: true, hasDefault: true },
494
+ this.defaultValue,
495
+ this.onUpdateValue
496
+ );
497
+ }
498
+ notNull() {
499
+ return new _Column(
500
+ this.type,
501
+ { ...this.flags, notNull: true },
502
+ this.defaultValue,
503
+ this.onUpdateValue
504
+ );
505
+ }
506
+ /**
507
+ * Set the insert-time default: a constant value of type `T`, or a portable
508
+ * server-side expression from {@link sql} (e.g. `sql.now()`, `sql.uuidv4()`).
509
+ */
510
+ default(value) {
511
+ const resolved = isDefaultValue(value) ? value : { kind: "literal", value };
512
+ return new _Column(
513
+ this.type,
514
+ { ...this.flags, hasDefault: true },
515
+ resolved,
516
+ this.onUpdateValue
517
+ );
518
+ }
519
+ /**
520
+ * Re-apply a value whenever the row is updated (e.g. an `updated_at` column
521
+ * with `sql.now()`). Mirrors SQLAlchemy's `onupdate`.
522
+ */
523
+ onUpdate(value) {
524
+ const resolved = isDefaultValue(value) ? value : { kind: "literal", value };
525
+ return new _Column(this.type, this.flags, this.defaultValue, resolved);
526
+ }
527
+ };
528
+ var columnsCache = /* @__PURE__ */ new WeakMap();
529
+ function columnsOf(model) {
530
+ const cached = columnsCache.get(model);
531
+ if (cached) return cached;
532
+ const instance = new model();
533
+ const out = {};
534
+ for (const [key, value] of Object.entries(instance)) {
535
+ if (value instanceof Column) {
536
+ out[key] = value;
537
+ }
538
+ }
539
+ columnsCache.set(model, out);
540
+ return out;
541
+ }
542
+
543
+ // src/migrations/ir.ts
544
+ function reflectTable(model) {
545
+ const columns = {};
546
+ const primaryKey = [];
547
+ for (const [name, col] of Object.entries(columnsOf(model))) {
548
+ const isPk = col.flags.primaryKey;
549
+ columns[name] = {
550
+ name,
551
+ type: col.type,
552
+ notNull: col.flags.notNull || isPk,
553
+ primaryKey: isPk,
554
+ default: col.defaultValue
555
+ };
556
+ if (isPk) primaryKey.push(name);
557
+ }
558
+ return { name: model.tablename, columns, primaryKey };
559
+ }
560
+ function reflectSchema(models) {
561
+ const tables = {};
562
+ for (const model of models) {
563
+ const table = reflectTable(model);
564
+ tables[table.name] = table;
565
+ }
566
+ return { tables };
567
+ }
568
+ function emptySchema() {
569
+ return { tables: {} };
570
+ }
571
+
572
+ // src/migrations/introspect.ts
573
+ function sqliteAffinity(declared) {
574
+ const t = declared.toUpperCase();
575
+ if (t.includes("INT")) return "INTEGER";
576
+ if (t.includes("CHAR") || t.includes("CLOB") || t.includes("TEXT")) return "TEXT";
577
+ if (t.includes("BLOB") || t === "") return "BLOB";
578
+ if (t.includes("REAL") || t.includes("FLOA") || t.includes("DOUB")) return "REAL";
579
+ return "NUMERIC";
580
+ }
581
+ function affinityToKind(affinity) {
582
+ switch (affinity) {
583
+ case "INTEGER":
584
+ return "integer";
585
+ case "REAL":
586
+ return "real";
587
+ case "BLOB":
588
+ return "blob";
589
+ case "NUMERIC":
590
+ return "numeric";
591
+ default:
592
+ return "text";
593
+ }
594
+ }
595
+ function introspectSqlite(driver) {
596
+ const tablesRows = driver.execute(
597
+ "SELECT name FROM sqlite_master WHERE type = 'table' AND name NOT LIKE 'sqlite_%' AND name != 'tempest_db_js_migrations'",
598
+ []
599
+ ).rows;
600
+ const tables = {};
601
+ for (const row of tablesRows) {
602
+ const tableName = String(row.name);
603
+ const info = driver.execute(`PRAGMA table_info(${JSON.stringify(tableName)})`, []).rows;
604
+ const columns = {};
605
+ const primaryKey = [];
606
+ for (const col of info) {
607
+ const isPk = Number(col.pk) > 0;
608
+ const affinity = sqliteAffinity(col.type);
609
+ columns[col.name] = {
610
+ name: col.name,
611
+ type: { kind: affinityToKind(affinity), meta: {} },
612
+ notNull: Number(col.notnull) === 1 || isPk,
613
+ primaryKey: isPk,
614
+ default: null
615
+ };
616
+ if (isPk) primaryKey.push(col.name);
617
+ }
618
+ tables[tableName] = { name: tableName, columns, primaryKey };
619
+ }
620
+ return { tables };
621
+ }
622
+ function checkDrift(driver, models) {
623
+ const actual = introspectSqlite(driver);
624
+ const expected = reflectSchema(models);
625
+ const issues = [];
626
+ for (const [tableName, expectedTable] of Object.entries(expected.tables)) {
627
+ const actualTable = actual.tables[tableName];
628
+ if (!actualTable) {
629
+ issues.push(`table "${tableName}" is missing from the database`);
630
+ continue;
631
+ }
632
+ for (const [colName, expectedCol] of Object.entries(expectedTable.columns)) {
633
+ const actualCol = actualTable.columns[colName];
634
+ if (!actualCol) {
635
+ issues.push(`column "${tableName}.${colName}" is missing from the database`);
636
+ continue;
637
+ }
638
+ const expAff = sqliteAffinity(renderColumnType(expectedCol.type, "sqlite"));
639
+ const actAff = sqliteAffinity(renderColumnType(actualCol.type, "sqlite"));
640
+ if (expAff !== actAff) {
641
+ issues.push(
642
+ `column "${tableName}.${colName}" affinity differs: model ${expAff}, db ${actAff}`
643
+ );
644
+ }
645
+ if (expectedCol.notNull !== actualCol.notNull) {
646
+ issues.push(`column "${tableName}.${colName}" nullability differs`);
647
+ }
648
+ if (expectedCol.primaryKey !== actualCol.primaryKey) {
649
+ issues.push(`column "${tableName}.${colName}" primary-key flag differs`);
650
+ }
651
+ }
652
+ for (const colName of Object.keys(actualTable.columns)) {
653
+ if (!expectedTable.columns[colName]) {
654
+ issues.push(
655
+ `column "${tableName}.${colName}" exists in the database but not in the model`
656
+ );
657
+ }
658
+ }
659
+ }
660
+ for (const tableName of Object.keys(actual.tables)) {
661
+ if (!expected.tables[tableName]) {
662
+ issues.push(`table "${tableName}" exists in the database but not in the models`);
663
+ }
664
+ }
665
+ return issues;
666
+ }
667
+
668
+ // src/migrations/renames.ts
669
+ function columnShape(col) {
670
+ return JSON.stringify({
671
+ type: col.type,
672
+ notNull: col.notNull,
673
+ primaryKey: col.primaryKey,
674
+ default: col.default
675
+ });
676
+ }
677
+ function tableShape(columns) {
678
+ return Object.entries(columns).map(([name, col]) => `${name}:${columnShape(col)}`).sort().join("|");
679
+ }
680
+ function detectRenames(ops) {
681
+ const candidates = [];
682
+ const creates = ops.filter((o) => o.kind === "create_table");
683
+ const tableDrops = ops.filter((o) => o.kind === "drop_table");
684
+ const takenCreate = /* @__PURE__ */ new Set();
685
+ const takenDrop = /* @__PURE__ */ new Set();
686
+ for (const create of creates) {
687
+ const createShape = tableShape(create.table.columns);
688
+ const matches = tableDrops.filter(
689
+ (d) => !takenDrop.has(d.table.name) && tableShape(d.table.columns) === createShape
690
+ );
691
+ const uniqueCreate = creates.filter(
692
+ (c) => !takenCreate.has(c.table.name) && tableShape(c.table.columns) === createShape
693
+ ).length === 1;
694
+ if (matches.length === 1 && uniqueCreate) {
695
+ const drop = matches[0];
696
+ if (drop.table.name !== create.table.name) {
697
+ candidates.push({ kind: "table", from: drop.table.name, to: create.table.name });
698
+ takenCreate.add(create.table.name);
699
+ takenDrop.add(drop.table.name);
700
+ }
701
+ }
702
+ }
703
+ const adds = ops.filter((o) => o.kind === "add_column");
704
+ const colDrops = ops.filter((o) => o.kind === "drop_column");
705
+ const tables = /* @__PURE__ */ new Set([...adds.map((o) => o.table), ...colDrops.map((o) => o.table)]);
706
+ for (const table of tables) {
707
+ const tableAdds = adds.filter((o) => o.table === table);
708
+ const tableColDrops = colDrops.filter((o) => o.table === table);
709
+ const takenAdd = /* @__PURE__ */ new Set();
710
+ const takenColDrop = /* @__PURE__ */ new Set();
711
+ for (const add of tableAdds) {
712
+ const shape = columnShape(add.column);
713
+ const dropMatches = tableColDrops.filter(
714
+ (d) => !takenColDrop.has(d.column.name) && columnShape(d.column) === shape
715
+ );
716
+ const addMatches = tableAdds.filter(
717
+ (a) => !takenAdd.has(a.column.name) && columnShape(a.column) === shape
718
+ );
719
+ if (dropMatches.length === 1 && addMatches.length === 1) {
720
+ const drop = dropMatches[0];
721
+ candidates.push({
722
+ kind: "column",
723
+ table,
724
+ from: drop.column.name,
725
+ to: add.column.name
726
+ });
727
+ takenAdd.add(add.column.name);
728
+ takenColDrop.add(drop.column.name);
729
+ }
730
+ }
731
+ }
732
+ return candidates;
733
+ }
734
+ function isTableRename(op, r) {
735
+ return op.kind === "create_table" && op.table.name === r.to || op.kind === "drop_table" && op.table.name === r.from;
736
+ }
737
+ function isColumnRename(op, r) {
738
+ return op.kind === "add_column" && op.table === r.table && op.column.name === r.to || op.kind === "drop_column" && op.table === r.table && op.column.name === r.from;
739
+ }
740
+ function applyRenames(ops, confirmed) {
741
+ const out = [];
742
+ const emitted = /* @__PURE__ */ new Set();
743
+ for (const op of ops) {
744
+ const match = confirmed.find(
745
+ (r) => r.kind === "table" ? isTableRename(op, r) : isColumnRename(op, r)
746
+ );
747
+ if (!match) {
748
+ out.push(op);
749
+ continue;
750
+ }
751
+ if (!emitted.has(match)) {
752
+ emitted.add(match);
753
+ out.push(
754
+ match.kind === "table" ? { kind: "rename_table", from: match.from, to: match.to } : { kind: "rename_column", table: match.table, from: match.from, to: match.to }
755
+ );
756
+ }
757
+ }
758
+ return out;
759
+ }
760
+
761
+ // src/migrations/runner.ts
762
+ var Op = class {
763
+ operations = [];
764
+ /** Record a raw operation (used by autogenerated migrations). */
765
+ run(operation) {
766
+ this.operations.push(operation);
767
+ }
768
+ createTable(table) {
769
+ this.run({ kind: "create_table", table });
770
+ }
771
+ dropTable(table) {
772
+ this.run({ kind: "drop_table", table });
773
+ }
774
+ renameTable(from, to) {
775
+ this.run({ kind: "rename_table", from, to });
776
+ }
777
+ addColumn(table, column) {
778
+ this.run({ kind: "add_column", table, column });
779
+ }
780
+ dropColumn(table, column) {
781
+ this.run({ kind: "drop_column", table, column });
782
+ }
783
+ alterColumn(table, name, from, to) {
784
+ this.run({ kind: "alter_column", table, name, from, to });
785
+ }
786
+ renameColumn(table, from, to) {
787
+ this.run({ kind: "rename_column", table, from, to });
788
+ }
789
+ /** Rebuild a table (SQLite batch-mode / PostgreSQL per-column alters). */
790
+ recreateTable(from, to) {
791
+ this.run({ kind: "recreate_table", from, to });
792
+ }
793
+ /** Raw SQL escape hatch (e.g. a data migration). `down` may be `null`. */
794
+ execute(up, down = null) {
795
+ this.run({ kind: "execute", up, down });
796
+ }
797
+ };
798
+ var VERSION_TABLE = "tempest_db_js_migrations";
799
+ var MigrationRunner = class {
800
+ constructor(driver, dialect) {
801
+ this.driver = driver;
802
+ this.dialect = dialect;
803
+ }
804
+ driver;
805
+ dialect;
806
+ /** Create the version-tracking table if it does not exist. */
807
+ ensureVersionTable() {
808
+ this.driver.execute(
809
+ `CREATE TABLE IF NOT EXISTS "${VERSION_TABLE}" (revision TEXT PRIMARY KEY, applied_at TEXT NOT NULL, down_revision TEXT NOT NULL)`,
810
+ []
811
+ );
812
+ }
813
+ /** The set of applied revision ids. */
814
+ applied() {
815
+ this.ensureVersionTable();
816
+ const { rows } = this.driver.execute(`SELECT revision FROM "${VERSION_TABLE}"`, []);
817
+ return new Set(rows.map((r) => String(r.revision)));
818
+ }
819
+ runOps(ops) {
820
+ for (const op of ops) {
821
+ for (const stmt of renderOperation(op, this.dialect)) {
822
+ const trimmed = stmt.trim();
823
+ if (trimmed.length === 0 || trimmed.startsWith("--")) continue;
824
+ this.driver.execute(stmt, []);
825
+ }
826
+ }
827
+ }
828
+ record(migration, appliedAt) {
829
+ this.driver.execute(
830
+ `INSERT INTO "${VERSION_TABLE}" (revision, applied_at, down_revision) VALUES (?, ?, ?)`,
831
+ [migration.revision, appliedAt, migration.downRevision.join(",")]
832
+ );
833
+ }
834
+ forget(revision) {
835
+ this.driver.execute(`DELETE FROM "${VERSION_TABLE}" WHERE revision = ?`, [revision]);
836
+ }
837
+ /**
838
+ * Apply all pending migrations up to the head(s), in DAG order.
839
+ *
840
+ * @param migrations All known migrations.
841
+ * @param appliedAt Timestamp string to stamp (pass one in — the runtime has no
842
+ * wall clock of its own here).
843
+ * @returns The revision ids that were applied this run.
844
+ */
845
+ upgrade(migrations, appliedAt) {
846
+ const done = this.applied();
847
+ const ordered = topoOrder(migrations);
848
+ const ran = [];
849
+ for (const migration of ordered) {
850
+ if (done.has(migration.revision)) continue;
851
+ const op = new Op();
852
+ migration.up(op);
853
+ this.runOps(op.operations);
854
+ this.record(migration, appliedAt);
855
+ ran.push(migration.revision);
856
+ }
857
+ return ran;
858
+ }
859
+ /**
860
+ * Revert the last `steps` applied migrations (default 1), newest first.
861
+ *
862
+ * @param migrations All known migrations.
863
+ * @param steps How many applied revisions to roll back.
864
+ * @returns The revision ids that were reverted.
865
+ */
866
+ downgrade(migrations, steps = 1) {
867
+ const done = this.applied();
868
+ const ordered = topoOrder(migrations).filter((m) => done.has(m.revision));
869
+ const toRevert = ordered.slice(-steps).reverse();
870
+ const reverted = [];
871
+ for (const migration of toRevert) {
872
+ const op = new Op();
873
+ if (migration.down.length >= 0) {
874
+ try {
875
+ migration.down(op);
876
+ } catch {
877
+ op.operations.length = 0;
878
+ }
879
+ }
880
+ if (op.operations.length === 0) {
881
+ const upOp = new Op();
882
+ migration.up(upOp);
883
+ op.operations.push(...invertAll(upOp.operations));
884
+ }
885
+ this.runOps(op.operations);
886
+ this.forget(migration.revision);
887
+ reverted.push(migration.revision);
888
+ }
889
+ return reverted;
890
+ }
891
+ };
892
+
893
+ // src/migrations/replay.ts
894
+ function applyOperation(schema, op) {
895
+ const tables = { ...schema.tables };
896
+ switch (op.kind) {
897
+ case "create_table":
898
+ tables[op.table.name] = op.table;
899
+ break;
900
+ case "drop_table":
901
+ delete tables[op.table.name];
902
+ break;
903
+ case "rename_table": {
904
+ const t = tables[op.from];
905
+ if (t) {
906
+ delete tables[op.from];
907
+ tables[op.to] = { ...t, name: op.to };
908
+ }
909
+ break;
910
+ }
911
+ case "recreate_table":
912
+ delete tables[op.from.name];
913
+ tables[op.to.name] = op.to;
914
+ break;
915
+ case "add_column": {
916
+ const t = tables[op.table];
917
+ if (t) {
918
+ tables[op.table] = {
919
+ ...t,
920
+ columns: { ...t.columns, [op.column.name]: op.column }
921
+ };
922
+ }
923
+ break;
924
+ }
925
+ case "drop_column": {
926
+ const t = tables[op.table];
927
+ if (t) {
928
+ const columns = { ...t.columns };
929
+ delete columns[op.column.name];
930
+ tables[op.table] = { ...t, columns };
931
+ }
932
+ break;
933
+ }
934
+ case "alter_column": {
935
+ const t = tables[op.table];
936
+ if (t) {
937
+ tables[op.table] = {
938
+ ...t,
939
+ columns: { ...t.columns, [op.name]: op.to }
940
+ };
941
+ }
942
+ break;
943
+ }
944
+ case "rename_column": {
945
+ const t = tables[op.table];
946
+ const col = t?.columns[op.from];
947
+ if (t && col) {
948
+ const columns = { ...t.columns };
949
+ delete columns[op.from];
950
+ columns[op.to] = { ...col, name: op.to };
951
+ tables[op.table] = { ...t, columns };
952
+ }
953
+ break;
954
+ }
955
+ }
956
+ return { tables };
957
+ }
958
+ function replaySchema(migrations) {
959
+ let schema = emptySchema();
960
+ for (const migration of topoOrder(migrations)) {
961
+ const op = new Op();
962
+ migration.up(op);
963
+ for (const operation of op.operations) {
964
+ schema = applyOperation(schema, operation);
965
+ }
966
+ }
967
+ return schema;
968
+ }
969
+
970
+ // src/migrations/cli.ts
971
+ function ok(lines) {
972
+ return { code: 0, lines };
973
+ }
974
+ function fail(lines) {
975
+ return { code: 1, lines };
976
+ }
977
+ function parseRenameFlags(rest) {
978
+ const out = [];
979
+ for (let i = 0; i < rest.length; i += 1) {
980
+ const arg = rest[i];
981
+ if (arg === "--rename-table") {
982
+ const [from, to] = (rest[i + 1] ?? "").split(":");
983
+ i += 1;
984
+ if (from && to) out.push({ kind: "table", from, to });
985
+ } else if (arg === "--rename-column") {
986
+ const [left, to] = (rest[i + 1] ?? "").split(":");
987
+ i += 1;
988
+ const dot = left?.lastIndexOf(".") ?? -1;
989
+ if (left && to && dot > 0) {
990
+ out.push({
991
+ kind: "column",
992
+ table: left.slice(0, dot),
993
+ from: left.slice(dot + 1),
994
+ to
995
+ });
996
+ }
997
+ }
998
+ }
999
+ return out;
1000
+ }
1001
+ function pending(config, runner) {
1002
+ const done = runner.applied();
1003
+ return topoOrder(config.migrations).filter((m) => !done.has(m.revision));
1004
+ }
1005
+ function runMigrationCli(argv, config) {
1006
+ const [command, ...rest] = argv;
1007
+ const runner = new MigrationRunner(config.driver, config.dialect);
1008
+ const appliedAt = config.appliedAt ?? "1970-01-01T00:00:00.000Z";
1009
+ switch (command) {
1010
+ case "current": {
1011
+ const applied = [...runner.applied()].sort();
1012
+ return ok(applied.length > 0 ? applied : ["(no migrations applied)"]);
1013
+ }
1014
+ case "heads":
1015
+ return ok(heads(config.migrations));
1016
+ case "history": {
1017
+ const done = runner.applied();
1018
+ return ok(
1019
+ topoOrder(config.migrations).map(
1020
+ (m) => `${done.has(m.revision) ? "\u2713" : "\xB7"} ${m.revision}${m.label ? ` \u2014 ${m.label}` : ""}`
1021
+ )
1022
+ );
1023
+ }
1024
+ case "upgrade": {
1025
+ if (rest.includes("--sql")) {
1026
+ const lines = [];
1027
+ for (const migration of pending(config, runner)) {
1028
+ const op = new Op();
1029
+ migration.up(op);
1030
+ lines.push(`-- ${migration.revision}`);
1031
+ for (const operation of op.operations) {
1032
+ for (const stmt of renderOperation(operation, config.dialect))
1033
+ lines.push(`${stmt};`);
1034
+ }
1035
+ }
1036
+ return ok(lines.length > 0 ? lines : ["-- nothing to upgrade"]);
1037
+ }
1038
+ const ran = runner.upgrade(config.migrations, appliedAt);
1039
+ return ok(ran.length > 0 ? ran.map((r) => `applied ${r}`) : ["nothing to upgrade"]);
1040
+ }
1041
+ case "downgrade": {
1042
+ const steps = rest[0] ? Number(rest[0]) : 1;
1043
+ const reverted = runner.downgrade(config.migrations, steps);
1044
+ return ok(
1045
+ reverted.length > 0 ? reverted.map((r) => `reverted ${r}`) : ["nothing to downgrade"]
1046
+ );
1047
+ }
1048
+ case "check": {
1049
+ if (!config.models) return fail(["check requires models in the config"]);
1050
+ const drift = config.dialect === "sqlite" ? checkDrift(config.driver, config.models) : [];
1051
+ const undiffed = diffSchema(
1052
+ replaySchema(config.migrations),
1053
+ reflectSchema(config.models)
1054
+ );
1055
+ const issues = [
1056
+ ...drift.map((d) => `drift: ${d}`),
1057
+ ...undiffed.map((o) => `uncaptured: ${o.kind}`)
1058
+ ];
1059
+ return issues.length > 0 ? fail(issues) : ok(["no drift; models match migrations"]);
1060
+ }
1061
+ case "revision": {
1062
+ if (!config.models)
1063
+ return fail(["revision --autogenerate requires models in the config"]);
1064
+ const msgIndex = rest.indexOf("-m");
1065
+ const label = msgIndex >= 0 ? rest[msgIndex + 1] ?? "revision" : "revision";
1066
+ const parents = heads(config.migrations);
1067
+ let ops = rest.includes("--autogenerate") ? diffSchema(replaySchema(config.migrations), reflectSchema(config.models)) : [];
1068
+ if (rest.includes("--autogenerate")) {
1069
+ const confirmed = rest.includes("--autorename") ? detectRenames(ops) : parseRenameFlags(rest);
1070
+ if (confirmed.length > 0) ops = applyRenames(ops, confirmed);
1071
+ }
1072
+ const source = generateMigration({
1073
+ revision: makeRevisionId(label, parents),
1074
+ downRevision: parents,
1075
+ label,
1076
+ operations: ops
1077
+ });
1078
+ return ok(source.split("\n"));
1079
+ }
1080
+ default:
1081
+ return fail([
1082
+ `unknown command ${JSON.stringify(command)}`,
1083
+ "commands: current | history | heads | upgrade [--sql] | downgrade [N] | check | revision -m <msg> [--autogenerate]"
1084
+ ]);
1085
+ }
1086
+ }
1087
+
1088
+ // src/bin.ts
1089
+ var DEFAULT_CONFIG_NAMES = [
1090
+ "tempest-db.config.mjs",
1091
+ "tempest-db.config.js",
1092
+ "tempest-db.config.cjs"
1093
+ ];
1094
+ function extractConfigFlag(argv) {
1095
+ const rest = [];
1096
+ let configPath = null;
1097
+ for (let i = 0; i < argv.length; i += 1) {
1098
+ const arg = argv[i];
1099
+ if (arg === "--config" || arg === "-c") {
1100
+ configPath = argv[i + 1] ?? null;
1101
+ i += 1;
1102
+ } else if (arg?.startsWith("--config=")) {
1103
+ configPath = arg.slice("--config=".length);
1104
+ } else if (arg !== void 0) {
1105
+ rest.push(arg);
1106
+ }
1107
+ }
1108
+ return { configPath, rest };
1109
+ }
1110
+ function resolveConfigPath(explicit) {
1111
+ if (explicit) return path.resolve(process.cwd(), explicit);
1112
+ for (const name of DEFAULT_CONFIG_NAMES) {
1113
+ const candidate = path.resolve(process.cwd(), name);
1114
+ if (fs.existsSync(candidate)) return candidate;
1115
+ }
1116
+ return null;
1117
+ }
1118
+ async function loadConfig(path) {
1119
+ const mod = await import(url.pathToFileURL(path).href);
1120
+ const config = mod.default ?? mod.config;
1121
+ if (!config) {
1122
+ throw new Error(
1123
+ `config at ${path} must default-export (or export \`config\`) a CliConfig`
1124
+ );
1125
+ }
1126
+ return config;
1127
+ }
1128
+ function renameToFlags(r) {
1129
+ return r.kind === "table" ? ["--rename-table", `${r.from}:${r.to}`] : ["--rename-column", `${r.table}.${r.from}:${r.to}`];
1130
+ }
1131
+ async function promptRenames(config, rest) {
1132
+ const decided = rest.includes("--autorename") || rest.includes("--rename-table") || rest.includes("--rename-column");
1133
+ if (rest[0] !== "revision" || !rest.includes("--autogenerate") || decided || !config.models || !process.stdin.isTTY) {
1134
+ return [];
1135
+ }
1136
+ const ops = diffSchema(replaySchema(config.migrations), reflectSchema(config.models));
1137
+ const candidates = detectRenames(ops);
1138
+ if (candidates.length === 0) return [];
1139
+ const rl = promises.createInterface({ input: process.stdin, output: process.stdout });
1140
+ const flags = [];
1141
+ try {
1142
+ for (const c of candidates) {
1143
+ const what = c.kind === "table" ? `table "${c.from}" \u2192 "${c.to}"` : `column "${c.table}.${c.from}" \u2192 "${c.table}.${c.to}"`;
1144
+ const answer = (await rl.question(`Rename ${what}? [y/N] `)).trim().toLowerCase();
1145
+ if (answer === "y" || answer === "yes") flags.push(...renameToFlags(c));
1146
+ }
1147
+ } finally {
1148
+ rl.close();
1149
+ }
1150
+ return flags;
1151
+ }
1152
+ async function main(argv) {
1153
+ const { configPath, rest } = extractConfigFlag(argv);
1154
+ const resolved = resolveConfigPath(configPath);
1155
+ if (!resolved) {
1156
+ process.stderr.write(
1157
+ `tempest-db: no config found. Create one of ${DEFAULT_CONFIG_NAMES.join(
1158
+ ", "
1159
+ )} or pass --config <path>.
1160
+ `
1161
+ );
1162
+ process.exitCode = 1;
1163
+ return;
1164
+ }
1165
+ let config;
1166
+ try {
1167
+ config = await loadConfig(resolved);
1168
+ } catch (error) {
1169
+ process.stderr.write(`tempest-db: ${error.message}
1170
+ `);
1171
+ process.exitCode = 1;
1172
+ return;
1173
+ }
1174
+ const withClock = {
1175
+ ...config,
1176
+ appliedAt: config.appliedAt ?? (/* @__PURE__ */ new Date()).toISOString()
1177
+ };
1178
+ const renameFlags = await promptRenames(withClock, rest);
1179
+ const result = runMigrationCli([...rest, ...renameFlags], withClock);
1180
+ const sink = result.code === 0 ? process.stdout : process.stderr;
1181
+ for (const line of result.lines) sink.write(`${line}
1182
+ `);
1183
+ process.exitCode = result.code;
1184
+ }
1185
+ if ((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('bin.cjs', document.baseURI).href)) === url.pathToFileURL(process.argv[1] ?? "").href) {
1186
+ void main(process.argv.slice(2));
1187
+ }
1188
+
1189
+ exports.main = main;
1190
+ //# sourceMappingURL=bin.cjs.map
1191
+ //# sourceMappingURL=bin.cjs.map