@onreza/sqlx-js 0.5.0 → 0.7.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/README.md +99 -30
- package/ROADMAP.md +2 -2
- package/dist/bin/sqlx-js-diagnostics.d.ts +2 -0
- package/dist/bin/sqlx-js-diagnostics.js +96 -0
- package/dist/bin/sqlx-js.js +291 -92
- package/dist/src/cache.d.ts +1 -1
- package/dist/src/cache.js +1 -1
- package/dist/src/codegen.js +27 -14
- package/dist/src/commands/init.js +97 -3
- package/dist/src/commands/migrate.d.ts +2 -101
- package/dist/src/commands/migrate.js +6 -546
- package/dist/src/commands/prepare.d.ts +10 -2
- package/dist/src/commands/prepare.js +201 -33
- package/dist/src/commands/schema.js +1 -1
- package/dist/src/commands/watch.d.ts +14 -6
- package/dist/src/commands/watch.js +184 -21
- package/dist/src/config.d.ts +1 -0
- package/dist/src/config.js +8 -0
- package/dist/src/function-cache.d.ts +2 -0
- package/dist/src/function-cache.js +6 -3
- package/dist/src/index.d.ts +17 -1
- package/dist/src/index.js +3 -0
- package/dist/src/migration-core.d.ts +157 -0
- package/dist/src/migration-core.js +578 -0
- package/dist/src/pg/schema.d.ts +1 -0
- package/dist/src/pg/schema.js +42 -31
- package/dist/src/pg/wire.d.ts +1 -0
- package/dist/src/pg/wire.js +6 -0
- package/dist/src/postgres-runtime.d.ts +11 -1
- package/dist/src/postgres-runtime.js +22 -5
- package/dist/src/runtime.d.ts +5 -2
- package/dist/src/runtime.js +34 -13
- package/dist/src/scan/scanner.d.ts +1 -1
- package/dist/src/scan/scanner.js +84 -17
- package/dist/src/type-inspection.d.ts +1 -0
- package/dist/src/type-inspection.js +20 -0
- package/package.json +6 -2
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { mkdtempSync, rmSync } from "node:fs";
|
|
1
|
+
import { existsSync, mkdtempSync, readFileSync, rmSync } from "node:fs";
|
|
2
2
|
import { tmpdir } from "node:os";
|
|
3
|
-
import { join } from "node:path";
|
|
3
|
+
import { join, relative } from "node:path";
|
|
4
4
|
import { PgClient, parseDatabaseUrl, PgError } from "../pg/wire.js";
|
|
5
5
|
import { SchemaCache, compositeLiteral } from "../pg/schema.js";
|
|
6
6
|
import { analyzeQuery } from "../pg/analyze.js";
|
|
@@ -9,11 +9,12 @@ import { ScanError, scanProject } from "../scan/scanner.js";
|
|
|
9
9
|
import { assertCacheManifest, Cache, fingerprint, effectiveNullable, portableCacheOid, writeCacheManifest, } from "../cache.js";
|
|
10
10
|
import { emitDts } from "../codegen.js";
|
|
11
11
|
import { loadConfig, lookupJsonbType, prepareConfigHash } from "../config.js";
|
|
12
|
-
import { readFunctionCache, writeFunctionCache } from "../function-cache.js";
|
|
12
|
+
import { functionCacheExists, readFunctionCache, writeFunctionCache } from "../function-cache.js";
|
|
13
13
|
import { introspectFunctions } from "../pg/functions.js";
|
|
14
14
|
import { buildParamMap } from "../pg/param-map.js";
|
|
15
15
|
import { mergeExtensionTypes } from "../pg/extensions.js";
|
|
16
16
|
import { compareArtifacts } from "../artifacts.js";
|
|
17
|
+
import { containsUnknownType } from "../type-inspection.js";
|
|
17
18
|
const JSON_OIDS = new Set([114, 3802]);
|
|
18
19
|
const JSON_ARRAY_OIDS = new Set([199, 3807]);
|
|
19
20
|
const JSON_INPUT_VALUE = 'import("@onreza/sqlx-js").JsonInputValue';
|
|
@@ -70,7 +71,8 @@ function resolveParamTs(paramIndex, paramOid, paramMap, schema, cfg) {
|
|
|
70
71
|
const target = paramMap.get(paramIndex);
|
|
71
72
|
if (target) {
|
|
72
73
|
const column = resolveTargetColumn(target, schema);
|
|
73
|
-
const
|
|
74
|
+
const table = resolvedTargetTable(target, schema);
|
|
75
|
+
const decl = column && table ? lookupJsonbType(cfg, table.schema, table.name, column) : undefined;
|
|
74
76
|
if (decl)
|
|
75
77
|
return jsonParameter(decl);
|
|
76
78
|
}
|
|
@@ -80,7 +82,8 @@ function resolveParamTs(paramIndex, paramOid, paramMap, schema, cfg) {
|
|
|
80
82
|
const target = paramMap.get(paramIndex);
|
|
81
83
|
if (target) {
|
|
82
84
|
const column = resolveTargetColumn(target, schema);
|
|
83
|
-
const
|
|
85
|
+
const table = resolvedTargetTable(target, schema);
|
|
86
|
+
const decl = column && table ? lookupJsonbType(cfg, table.schema, table.name, column) : undefined;
|
|
84
87
|
if (decl)
|
|
85
88
|
return arrayParameter(jsonParameter(decl));
|
|
86
89
|
}
|
|
@@ -102,6 +105,10 @@ function resolveParamTs(paramIndex, paramOid, paramMap, schema, cfg) {
|
|
|
102
105
|
}
|
|
103
106
|
return resolveTs(paramOid, (oid) => schema.customType(oid));
|
|
104
107
|
}
|
|
108
|
+
function resolvedTargetTable(target, schema) {
|
|
109
|
+
const oid = schema.resolveTable(target.schema, target.table);
|
|
110
|
+
return oid === undefined ? undefined : schema.tableNameByOid(oid);
|
|
111
|
+
}
|
|
105
112
|
function resolveTargetColumn(target, schema) {
|
|
106
113
|
if (target.column)
|
|
107
114
|
return target.column;
|
|
@@ -148,6 +155,14 @@ function isAliasOrExpression(f, schema) {
|
|
|
148
155
|
const real = schema.columnNameByAttno(f.tableOid, f.columnAttr);
|
|
149
156
|
return real !== undefined && real !== f.name;
|
|
150
157
|
}
|
|
158
|
+
function duplicateOutputColumns(fields) {
|
|
159
|
+
const counts = new Map();
|
|
160
|
+
for (const field of fields) {
|
|
161
|
+
const name = parseColumnOverride(field.name).name;
|
|
162
|
+
counts.set(name, (counts.get(name) ?? 0) + 1);
|
|
163
|
+
}
|
|
164
|
+
return [...counts].filter(([, count]) => count > 1).map(([name]) => name).sort();
|
|
165
|
+
}
|
|
151
166
|
export class PrepareFatalError extends Error {
|
|
152
167
|
phase;
|
|
153
168
|
file;
|
|
@@ -187,6 +202,32 @@ function siteUsage(sites) {
|
|
|
187
202
|
...(filePaths.length > 0 ? { filePaths } : {}),
|
|
188
203
|
};
|
|
189
204
|
}
|
|
205
|
+
function inferenceIssues(entry) {
|
|
206
|
+
const issues = [];
|
|
207
|
+
if (entry.degraded)
|
|
208
|
+
issues.push(`nullability inference degraded: ${entry.degraded.reason}`);
|
|
209
|
+
entry.paramTsTypes.forEach((type, index) => {
|
|
210
|
+
if (containsUnknownType(type))
|
|
211
|
+
issues.push(`parameter $${index + 1} resolved to ${type}`);
|
|
212
|
+
});
|
|
213
|
+
for (const column of entry.columns) {
|
|
214
|
+
if (containsUnknownType(column.tsType)) {
|
|
215
|
+
issues.push(`result column ${JSON.stringify(column.name)} resolved to ${column.tsType}`);
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
return issues;
|
|
219
|
+
}
|
|
220
|
+
function inferenceDiagnostics(entry, site, strict) {
|
|
221
|
+
return inferenceIssues(entry).map((message) => ({
|
|
222
|
+
severity: strict ? "error" : "warning",
|
|
223
|
+
phase: "inference",
|
|
224
|
+
message,
|
|
225
|
+
file: site.file,
|
|
226
|
+
line: site.line,
|
|
227
|
+
column: site.column,
|
|
228
|
+
query: entry.query,
|
|
229
|
+
}));
|
|
230
|
+
}
|
|
190
231
|
export async function openSession(opts) {
|
|
191
232
|
let userCfg;
|
|
192
233
|
try {
|
|
@@ -266,17 +307,23 @@ export async function describeAll(cfg, sessionClient, queries, concurrency) {
|
|
|
266
307
|
}
|
|
267
308
|
return results;
|
|
268
309
|
}
|
|
269
|
-
export async function prepareOnce(opts, session, log = console.log, err = console.error, concurrency = defaultPrepareConcurrency()) {
|
|
310
|
+
export async function prepareOnce(opts, session, log = console.log, err = console.error, concurrency = defaultPrepareConcurrency(), input = {}) {
|
|
270
311
|
let sites;
|
|
271
|
-
|
|
272
|
-
sites =
|
|
312
|
+
if (input.sites) {
|
|
313
|
+
sites = input.sites;
|
|
273
314
|
}
|
|
274
|
-
|
|
275
|
-
|
|
315
|
+
else {
|
|
316
|
+
try {
|
|
317
|
+
sites = scanProject(opts.root, session.userCfg.scan);
|
|
318
|
+
}
|
|
319
|
+
catch (error) {
|
|
320
|
+
throw fatal("scan", error);
|
|
321
|
+
}
|
|
276
322
|
}
|
|
277
323
|
log(`scanned: found ${sites.length} sql() call site(s)`);
|
|
278
324
|
const diagnostics = [];
|
|
279
325
|
const cache = new Cache(opts.cacheDir);
|
|
326
|
+
let failures = 0;
|
|
280
327
|
const unique = new Map();
|
|
281
328
|
for (const s of sites) {
|
|
282
329
|
const fp = fingerprint(s.query);
|
|
@@ -287,14 +334,50 @@ export async function prepareOnce(opts, session, log = console.log, err = consol
|
|
|
287
334
|
unique.set(fp, { fp, query: s.query, sites: [s] });
|
|
288
335
|
}
|
|
289
336
|
const raw = [];
|
|
290
|
-
|
|
337
|
+
const reusedEntries = [];
|
|
338
|
+
const reusedGenerated = [];
|
|
291
339
|
const { client, schema, userCfg } = session;
|
|
292
|
-
const
|
|
340
|
+
const toPrepare = new Map();
|
|
341
|
+
for (const [fp, item] of unique) {
|
|
342
|
+
const cached = input.reuseCacheFps?.has(fp) ? cache.read(fp) : null;
|
|
343
|
+
if (!cached) {
|
|
344
|
+
toPrepare.set(fp, item);
|
|
345
|
+
continue;
|
|
346
|
+
}
|
|
347
|
+
const entry = { ...cached, ...siteUsage(item.sites) };
|
|
348
|
+
const entryDiagnostics = inferenceDiagnostics(entry, item.sites[0], opts.strictInference === true);
|
|
349
|
+
diagnostics.push(...entryDiagnostics);
|
|
350
|
+
if (opts.strictInference && entryDiagnostics.length > 0) {
|
|
351
|
+
failures++;
|
|
352
|
+
continue;
|
|
353
|
+
}
|
|
354
|
+
reusedEntries.push(entry);
|
|
355
|
+
reusedGenerated.push({ fp, entry });
|
|
356
|
+
log(` ↺ ${formatSite(item.sites[0])} → reused ${entry.paramOids.length} param(s), ${entry.columns.length} col(s)`);
|
|
357
|
+
}
|
|
358
|
+
const describeList = [...toPrepare.values()].map((u) => ({ fp: u.fp, query: u.query }));
|
|
293
359
|
const describeResults = await describeAll(parseDatabaseUrl(opts.databaseUrl), client, describeList, concurrency);
|
|
294
|
-
for (const { fp, query, sites: ss } of
|
|
360
|
+
for (const { fp, query, sites: ss } of toPrepare.values()) {
|
|
295
361
|
const site = ss[0];
|
|
296
362
|
const outcome = describeResults.get(fp);
|
|
297
363
|
if (outcome.ok) {
|
|
364
|
+
const duplicates = duplicateOutputColumns(outcome.fields);
|
|
365
|
+
if (duplicates.length > 0) {
|
|
366
|
+
failures++;
|
|
367
|
+
const message = `duplicate output column name(s): ${duplicates.join(", ")}. Alias each result column to a unique name`;
|
|
368
|
+
diagnostics.push({
|
|
369
|
+
severity: "error",
|
|
370
|
+
phase: "result-shape",
|
|
371
|
+
message,
|
|
372
|
+
file: site.file,
|
|
373
|
+
line: site.line,
|
|
374
|
+
column: site.column,
|
|
375
|
+
query,
|
|
376
|
+
});
|
|
377
|
+
err(` ✗ ${formatSite(site)} — ${message}`);
|
|
378
|
+
err(` query: ${snippet(query)}`);
|
|
379
|
+
continue;
|
|
380
|
+
}
|
|
298
381
|
raw.push({ fp, query, sites: ss, paramOids: outcome.paramOids, fields: outcome.fields });
|
|
299
382
|
continue;
|
|
300
383
|
}
|
|
@@ -403,8 +486,8 @@ export async function prepareOnce(opts, session, log = console.log, err = consol
|
|
|
403
486
|
for (const idx of pm.dmlBound) {
|
|
404
487
|
const t = pm.targets.get(idx);
|
|
405
488
|
if (t) {
|
|
406
|
-
const
|
|
407
|
-
dmlTablesToLoad.set(
|
|
489
|
+
const key = JSON.stringify([t.schema ?? null, t.table]);
|
|
490
|
+
dmlTablesToLoad.set(key, t.schema ? { schema: t.schema, name: t.table } : { name: t.table });
|
|
408
491
|
}
|
|
409
492
|
}
|
|
410
493
|
}
|
|
@@ -439,8 +522,8 @@ export async function prepareOnce(opts, session, log = console.log, err = consol
|
|
|
439
522
|
catch (error) {
|
|
440
523
|
throw fatal("introspect", error);
|
|
441
524
|
}
|
|
442
|
-
const entries = [];
|
|
443
|
-
const generated = [];
|
|
525
|
+
const entries = [...reusedEntries];
|
|
526
|
+
const generated = [...reusedGenerated];
|
|
444
527
|
for (const r of raw) {
|
|
445
528
|
if (failedFps.has(r.fp))
|
|
446
529
|
continue;
|
|
@@ -470,6 +553,18 @@ export async function prepareOnce(opts, session, log = console.log, err = consol
|
|
|
470
553
|
hasResultSet: r.fields.length > 0,
|
|
471
554
|
...(analysis.degraded ? { degraded: analysis.degraded } : {}),
|
|
472
555
|
};
|
|
556
|
+
const entryDiagnostics = inferenceDiagnostics(entry, r.sites[0], opts.strictInference === true);
|
|
557
|
+
diagnostics.push(...entryDiagnostics);
|
|
558
|
+
if (entryDiagnostics.length > 0) {
|
|
559
|
+
for (const diagnostic of entryDiagnostics) {
|
|
560
|
+
const label = diagnostic.severity === "error" ? "inference failed" : "inference warning";
|
|
561
|
+
err(` ${label}: ${formatSite(r.sites[0])} — ${diagnostic.message}`);
|
|
562
|
+
}
|
|
563
|
+
if (opts.strictInference) {
|
|
564
|
+
failures++;
|
|
565
|
+
continue;
|
|
566
|
+
}
|
|
567
|
+
}
|
|
473
568
|
entries.push(entry);
|
|
474
569
|
generated.push({ fp: r.fp, entry });
|
|
475
570
|
const nn = entry.columns.filter((c) => !effectiveNullable(c)).length;
|
|
@@ -480,11 +575,16 @@ export async function prepareOnce(opts, session, log = console.log, err = consol
|
|
|
480
575
|
return { sites: sites.length, entries: entries.length, failures, pruned: 0, functions: 0, diagnostics };
|
|
481
576
|
}
|
|
482
577
|
let functions;
|
|
483
|
-
|
|
484
|
-
functions =
|
|
578
|
+
if (input.reuseFunctions && functionCacheExists(opts.cacheDir)) {
|
|
579
|
+
functions = readFunctionCache(opts.cacheDir);
|
|
485
580
|
}
|
|
486
|
-
|
|
487
|
-
|
|
581
|
+
else {
|
|
582
|
+
try {
|
|
583
|
+
functions = await introspectFunctions(client, schema);
|
|
584
|
+
}
|
|
585
|
+
catch (error) {
|
|
586
|
+
throw fatal("introspect", error);
|
|
587
|
+
}
|
|
488
588
|
}
|
|
489
589
|
let pruned;
|
|
490
590
|
try {
|
|
@@ -516,7 +616,8 @@ export async function runPrepare(opts) {
|
|
|
516
616
|
process.exitCode = 1;
|
|
517
617
|
return;
|
|
518
618
|
}
|
|
519
|
-
if (opts.check) {
|
|
619
|
+
if (opts.check || opts.offline) {
|
|
620
|
+
const mode = opts.offline ? "offline" : "check";
|
|
520
621
|
let userCfg;
|
|
521
622
|
try {
|
|
522
623
|
userCfg = await loadConfig(opts.root);
|
|
@@ -573,9 +674,9 @@ export async function runPrepare(opts) {
|
|
|
573
674
|
console.log(JSON.stringify({
|
|
574
675
|
formatVersion: 1,
|
|
575
676
|
ok: false,
|
|
576
|
-
mode
|
|
677
|
+
mode,
|
|
577
678
|
sites: sites.length,
|
|
578
|
-
entries: unique.
|
|
679
|
+
entries: [...unique.keys()].filter((fp) => cache.has(fp)).length,
|
|
579
680
|
failures: diagnostics.length,
|
|
580
681
|
pruned: 0,
|
|
581
682
|
functions: 0,
|
|
@@ -583,20 +684,83 @@ export async function runPrepare(opts) {
|
|
|
583
684
|
}, null, 2));
|
|
584
685
|
}
|
|
585
686
|
else {
|
|
586
|
-
console.error(`\nsqlx-js prepare
|
|
687
|
+
console.error(`\nsqlx-js prepare --${mode}: ${diagnostics.length} stale/missing entries. Run \`sqlx-js prepare\` against a live DB.`);
|
|
587
688
|
}
|
|
588
689
|
process.exitCode = 1;
|
|
589
690
|
return;
|
|
590
691
|
}
|
|
591
|
-
|
|
692
|
+
const entries = [];
|
|
693
|
+
let inferenceFailures = 0;
|
|
592
694
|
let functions;
|
|
593
695
|
try {
|
|
594
|
-
|
|
696
|
+
for (const u of unique.values()) {
|
|
595
697
|
const entry = cache.read(u.fp);
|
|
596
|
-
|
|
597
|
-
|
|
698
|
+
if (!entry)
|
|
699
|
+
continue;
|
|
700
|
+
const current = { ...entry, ...siteUsage(u.sites) };
|
|
701
|
+
const entryDiagnostics = inferenceDiagnostics(current, u.sites[0], opts.strictInference === true);
|
|
702
|
+
diagnostics.push(...entryDiagnostics);
|
|
703
|
+
if (opts.strictInference && entryDiagnostics.length > 0) {
|
|
704
|
+
inferenceFailures++;
|
|
705
|
+
continue;
|
|
706
|
+
}
|
|
707
|
+
entries.push(current);
|
|
708
|
+
}
|
|
598
709
|
functions = readFunctionCache(opts.cacheDir);
|
|
599
|
-
|
|
710
|
+
if (!functionCacheExists(opts.cacheDir)) {
|
|
711
|
+
diagnostics.push({
|
|
712
|
+
severity: "error",
|
|
713
|
+
phase: "cache",
|
|
714
|
+
message: "function cache is missing",
|
|
715
|
+
});
|
|
716
|
+
inferenceFailures++;
|
|
717
|
+
}
|
|
718
|
+
if (opts.check && inferenceFailures === 0) {
|
|
719
|
+
const tmp = mkdtempSync(join(tmpdir(), "sqlx-js-check-"));
|
|
720
|
+
const generatedDts = join(tmp, "sqlx-js-env.d.ts");
|
|
721
|
+
try {
|
|
722
|
+
emitDts(generatedDts, entries, functions);
|
|
723
|
+
if (!existsSync(opts.dtsPath) || readFileSync(opts.dtsPath, "utf8") !== readFileSync(generatedDts, "utf8")) {
|
|
724
|
+
diagnostics.push({
|
|
725
|
+
severity: "error",
|
|
726
|
+
phase: "cache",
|
|
727
|
+
message: "generated declaration is stale or missing",
|
|
728
|
+
file: relative(opts.root, opts.dtsPath).replace(/\\/g, "/"),
|
|
729
|
+
});
|
|
730
|
+
inferenceFailures++;
|
|
731
|
+
}
|
|
732
|
+
}
|
|
733
|
+
finally {
|
|
734
|
+
rmSync(tmp, { recursive: true, force: true });
|
|
735
|
+
}
|
|
736
|
+
}
|
|
737
|
+
if (inferenceFailures > 0) {
|
|
738
|
+
if (opts.json) {
|
|
739
|
+
console.log(JSON.stringify({
|
|
740
|
+
formatVersion: 1,
|
|
741
|
+
ok: false,
|
|
742
|
+
mode,
|
|
743
|
+
sites: sites.length,
|
|
744
|
+
entries: entries.length,
|
|
745
|
+
failures: inferenceFailures,
|
|
746
|
+
pruned: 0,
|
|
747
|
+
functions: functions.length,
|
|
748
|
+
diagnostics,
|
|
749
|
+
}, null, 2));
|
|
750
|
+
}
|
|
751
|
+
else {
|
|
752
|
+
for (const diagnostic of diagnostics) {
|
|
753
|
+
const location = diagnostic.file
|
|
754
|
+
? `${diagnostic.file}${diagnostic.line ? `:${diagnostic.line}:${diagnostic.column ?? 1}` : ""} — `
|
|
755
|
+
: "";
|
|
756
|
+
console.error(`${diagnostic.phase} failed: ${location}${diagnostic.message}`);
|
|
757
|
+
}
|
|
758
|
+
}
|
|
759
|
+
process.exitCode = 1;
|
|
760
|
+
return;
|
|
761
|
+
}
|
|
762
|
+
if (opts.offline)
|
|
763
|
+
emitDts(opts.dtsPath, entries, functions);
|
|
600
764
|
}
|
|
601
765
|
catch (error) {
|
|
602
766
|
throw fatal("cache", error);
|
|
@@ -605,17 +769,21 @@ export async function runPrepare(opts) {
|
|
|
605
769
|
console.log(JSON.stringify({
|
|
606
770
|
formatVersion: 1,
|
|
607
771
|
ok: true,
|
|
608
|
-
mode
|
|
772
|
+
mode,
|
|
609
773
|
sites: sites.length,
|
|
610
774
|
entries: entries.length,
|
|
611
775
|
failures: 0,
|
|
612
776
|
pruned: 0,
|
|
613
777
|
functions: functions.length,
|
|
614
|
-
diagnostics
|
|
778
|
+
diagnostics,
|
|
615
779
|
}, null, 2));
|
|
616
780
|
}
|
|
617
781
|
else {
|
|
618
|
-
|
|
782
|
+
for (const diagnostic of diagnostics) {
|
|
783
|
+
console.error(`inference warning: ${diagnostic.file}:${diagnostic.line}:${diagnostic.column} — ${diagnostic.message}`);
|
|
784
|
+
}
|
|
785
|
+
const suffix = opts.offline ? ", types regenerated" : ", generated artifacts are current";
|
|
786
|
+
console.log(`ok — ${entries.length} unique queries, ${functions.length} function(s)${suffix}`);
|
|
619
787
|
}
|
|
620
788
|
return;
|
|
621
789
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { introspectDatabase, readSchemaSnapshot, schemaSnapshotEqual, schemaSnapshotExists, writeSchemaManifest, writeSchemaSnapshot } from "../schema-snapshot.js";
|
|
2
2
|
import { PgClient, parseDatabaseUrl } from "../pg/wire.js";
|
|
3
|
-
import { acquireMigrateLock, applyPending, DEFAULT_MIGRATE_LOCK_KEY, releaseMigrateLock } from "
|
|
3
|
+
import { acquireMigrateLock, applyPending, DEFAULT_MIGRATE_LOCK_KEY, releaseMigrateLock } from "../migration-core.js";
|
|
4
4
|
export async function applyShadowMigrations(databaseUrl, migrationsDir, log = console.log) {
|
|
5
5
|
const client = new PgClient(parseDatabaseUrl(databaseUrl));
|
|
6
6
|
await client.connect();
|
|
@@ -1,22 +1,30 @@
|
|
|
1
|
-
import { openSession, prepareOnce, type PrepareOptions, type PrepareSession } from "./prepare.js";
|
|
1
|
+
import { openSession, prepareOnce, type PrepareOptions, type PrepareResult, type PrepareSession } from "./prepare.js";
|
|
2
|
+
import { loadConfig } from "../config.js";
|
|
3
|
+
import { findSourceFiles, scanFile, scanProject, type QueryCallSite } from "../scan/scanner.js";
|
|
2
4
|
export declare function shouldWatchFile(filename: string): boolean;
|
|
3
5
|
export type WatchPrepareHookResult = {
|
|
4
6
|
resetSession?: boolean;
|
|
5
7
|
};
|
|
6
8
|
export type WatchOptions = PrepareOptions & {
|
|
7
9
|
beforePrepare?: () => Promise<WatchPrepareHookResult | void>;
|
|
10
|
+
jsonl?: boolean;
|
|
8
11
|
};
|
|
9
12
|
export type WatchState = {
|
|
10
13
|
session: PrepareSession | null;
|
|
14
|
+
sitesByFile?: Map<string, QueryCallSite[]>;
|
|
15
|
+
dirtyFiles?: Set<string>;
|
|
16
|
+
dirtyFps?: Set<string>;
|
|
11
17
|
};
|
|
18
|
+
export declare function formatWatchEvent(name: string, data?: Record<string, unknown>, timestamp?: string): string;
|
|
19
|
+
export declare function watchErrorData(error: unknown): Record<string, unknown>;
|
|
12
20
|
type WatchDeps = {
|
|
13
21
|
openSession: typeof openSession;
|
|
14
22
|
prepareOnce: typeof prepareOnce;
|
|
23
|
+
loadConfig: typeof loadConfig;
|
|
24
|
+
scanProject: typeof scanProject;
|
|
25
|
+
scanFile: typeof scanFile;
|
|
26
|
+
findSourceFiles: typeof findSourceFiles;
|
|
15
27
|
};
|
|
16
|
-
export declare function prepareWatchedOnce(opts: WatchOptions, state: WatchState, log: (msg: string) => void, err: (msg: string) => void, deps?: WatchDeps): Promise<
|
|
17
|
-
entries: number;
|
|
18
|
-
failures: number;
|
|
19
|
-
pruned: number;
|
|
20
|
-
}>;
|
|
28
|
+
export declare function prepareWatchedOnce(opts: WatchOptions, state: WatchState, log: (msg: string) => void, err: (msg: string) => void, deps?: Partial<WatchDeps>, changedFiles?: readonly string[]): Promise<PrepareResult>;
|
|
21
29
|
export declare function runWatch(opts: WatchOptions): Promise<void>;
|
|
22
30
|
export {};
|