@onreza/sqlx-js 0.6.0 → 0.8.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 +69 -15
- package/ROADMAP.md +4 -3
- package/dist/bin/sqlx-js.js +118 -23
- package/dist/src/cache.d.ts +3 -2
- package/dist/src/cache.js +26 -74
- package/dist/src/codegen.js +30 -15
- package/dist/src/commands/ci.d.ts +28 -0
- package/dist/src/commands/ci.js +103 -0
- package/dist/src/commands/init.js +14 -3
- package/dist/src/commands/prepare.d.ts +8 -1
- package/dist/src/commands/prepare.js +122 -48
- package/dist/src/commands/watch.d.ts +14 -6
- package/dist/src/commands/watch.js +184 -21
- 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/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 +41 -14
- package/dist/src/scan/scanner.js +101 -13
- package/dist/src/sql-lex.d.ts +7 -0
- package/dist/src/sql-lex.js +76 -0
- package/dist/src/sql-params.d.ts +11 -0
- package/dist/src/sql-params.js +101 -0
- package/dist/src/typed.d.ts +2 -2
- package/package.json +6 -1
package/dist/src/cache.js
CHANGED
|
@@ -2,8 +2,10 @@ import { createHash, randomBytes } from "node:crypto";
|
|
|
2
2
|
import { existsSync, mkdirSync, readdirSync, readFileSync, writeFileSync, unlinkSync, renameSync } from "node:fs";
|
|
3
3
|
import { join } from "node:path";
|
|
4
4
|
import { isBuiltinOid } from "./pg/oids.js";
|
|
5
|
-
|
|
6
|
-
|
|
5
|
+
import { isEscapeStringPrefix, isIdentifierContinuation, readBlockComment, readDollarQuoted, readLineComment, readQuotedIdentifier, readSingleQuoted, } from "./sql-lex.js";
|
|
6
|
+
import { rewriteNamedParameters } from "./sql-params.js";
|
|
7
|
+
export const CACHE_FORMAT_VERSION = 3;
|
|
8
|
+
export const GENERATOR_REVISION = 5;
|
|
7
9
|
export const CACHE_MANIFEST_FILE = "cache-manifest.json";
|
|
8
10
|
export function portableCacheOid(oid) {
|
|
9
11
|
return isBuiltinOid(oid) ? oid : 0;
|
|
@@ -56,7 +58,7 @@ function normalizeForFingerprint(query) {
|
|
|
56
58
|
continue;
|
|
57
59
|
}
|
|
58
60
|
if (ch === "$") {
|
|
59
|
-
const next = readDollarQuoted(query, i);
|
|
61
|
+
const next = i === 0 || !isIdentifierContinuation(query[i - 1]) ? readDollarQuoted(query, i) : null;
|
|
60
62
|
if (next !== null) {
|
|
61
63
|
emit(query.slice(i, next));
|
|
62
64
|
i = next;
|
|
@@ -68,77 +70,6 @@ function normalizeForFingerprint(query) {
|
|
|
68
70
|
}
|
|
69
71
|
return out;
|
|
70
72
|
}
|
|
71
|
-
function readSingleQuoted(query, start, escapeBackslash) {
|
|
72
|
-
let i = start + 1;
|
|
73
|
-
while (i < query.length) {
|
|
74
|
-
const ch = query[i];
|
|
75
|
-
if (escapeBackslash && ch === "\\") {
|
|
76
|
-
i += 2;
|
|
77
|
-
continue;
|
|
78
|
-
}
|
|
79
|
-
if (ch === "'") {
|
|
80
|
-
if (query[i + 1] === "'") {
|
|
81
|
-
i += 2;
|
|
82
|
-
continue;
|
|
83
|
-
}
|
|
84
|
-
return i + 1;
|
|
85
|
-
}
|
|
86
|
-
i++;
|
|
87
|
-
}
|
|
88
|
-
return query.length;
|
|
89
|
-
}
|
|
90
|
-
function readQuotedIdentifier(query, start) {
|
|
91
|
-
let i = start + 1;
|
|
92
|
-
while (i < query.length) {
|
|
93
|
-
if (query[i] === "\"") {
|
|
94
|
-
if (query[i + 1] === "\"") {
|
|
95
|
-
i += 2;
|
|
96
|
-
continue;
|
|
97
|
-
}
|
|
98
|
-
return i + 1;
|
|
99
|
-
}
|
|
100
|
-
i++;
|
|
101
|
-
}
|
|
102
|
-
return query.length;
|
|
103
|
-
}
|
|
104
|
-
function readDollarQuoted(query, start) {
|
|
105
|
-
let tagEnd = start + 1;
|
|
106
|
-
while (tagEnd < query.length && /[A-Za-z0-9_]/.test(query[tagEnd]))
|
|
107
|
-
tagEnd++;
|
|
108
|
-
if (query[tagEnd] !== "$")
|
|
109
|
-
return null;
|
|
110
|
-
const tag = query.slice(start, tagEnd + 1);
|
|
111
|
-
const end = query.indexOf(tag, tagEnd + 1);
|
|
112
|
-
return end === -1 ? query.length : end + tag.length;
|
|
113
|
-
}
|
|
114
|
-
function readLineComment(query, start) {
|
|
115
|
-
const end = query.indexOf("\n", start + 2);
|
|
116
|
-
return end === -1 ? query.length : end + 1;
|
|
117
|
-
}
|
|
118
|
-
function readBlockComment(query, start) {
|
|
119
|
-
let depth = 1;
|
|
120
|
-
let i = start + 2;
|
|
121
|
-
while (i < query.length && depth > 0) {
|
|
122
|
-
if (query[i] === "/" && query[i + 1] === "*") {
|
|
123
|
-
depth++;
|
|
124
|
-
i += 2;
|
|
125
|
-
continue;
|
|
126
|
-
}
|
|
127
|
-
if (query[i] === "*" && query[i + 1] === "/") {
|
|
128
|
-
depth--;
|
|
129
|
-
i += 2;
|
|
130
|
-
continue;
|
|
131
|
-
}
|
|
132
|
-
i++;
|
|
133
|
-
}
|
|
134
|
-
return i;
|
|
135
|
-
}
|
|
136
|
-
function isEscapeStringPrefix(query, quoteIndex) {
|
|
137
|
-
if (quoteIndex === 0 || query[quoteIndex - 1]?.toLowerCase() !== "e")
|
|
138
|
-
return false;
|
|
139
|
-
const beforePrefix = query[quoteIndex - 2];
|
|
140
|
-
return beforePrefix === undefined || !/[A-Za-z0-9_$]/.test(beforePrefix);
|
|
141
|
-
}
|
|
142
73
|
export function effectiveNullable(c) {
|
|
143
74
|
if (c.override === "non-null")
|
|
144
75
|
return false;
|
|
@@ -166,6 +97,27 @@ function assertEntryShape(fp, raw) {
|
|
|
166
97
|
throw new Error(`sqlx-js: cache entry ${fp}.json is malformed`);
|
|
167
98
|
}
|
|
168
99
|
const cols = raw.columns;
|
|
100
|
+
const entry = raw;
|
|
101
|
+
let expectedNames;
|
|
102
|
+
try {
|
|
103
|
+
if (typeof entry.query !== "string")
|
|
104
|
+
throw new Error("query must be a string");
|
|
105
|
+
expectedNames = rewriteNamedParameters(entry.query).names;
|
|
106
|
+
}
|
|
107
|
+
catch {
|
|
108
|
+
throw new Error(`sqlx-js: cache entry ${fp}.json has malformed named parameter metadata. Run \`sqlx-js prepare\`.`);
|
|
109
|
+
}
|
|
110
|
+
if (entry.paramNames !== undefined || expectedNames.length > 0) {
|
|
111
|
+
if (!Array.isArray(entry.paramNames) ||
|
|
112
|
+
!entry.paramNames.every((name) => typeof name === "string") ||
|
|
113
|
+
!Array.isArray(entry.paramTsTypes) ||
|
|
114
|
+
entry.paramNames.length !== entry.paramTsTypes.length ||
|
|
115
|
+
new Set(entry.paramNames).size !== entry.paramNames.length ||
|
|
116
|
+
entry.paramNames.length !== expectedNames.length ||
|
|
117
|
+
entry.paramNames.some((name, index) => name !== expectedNames[index])) {
|
|
118
|
+
throw new Error(`sqlx-js: cache entry ${fp}.json has malformed named parameter metadata. Run \`sqlx-js prepare\`.`);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
169
121
|
if (cols.length > 0) {
|
|
170
122
|
const c = cols[0];
|
|
171
123
|
if ("forceNonNull" in c || "forceNullable" in c) {
|
package/dist/src/codegen.js
CHANGED
|
@@ -7,7 +7,9 @@ function entrySignature(e) {
|
|
|
7
7
|
const nullable = e.paramNullable?.[i] === true;
|
|
8
8
|
return nullable ? `${t} | null` : t;
|
|
9
9
|
});
|
|
10
|
-
const params =
|
|
10
|
+
const params = e.paramNames && e.paramNames.length > 0
|
|
11
|
+
? `{ ${e.paramNames.map((name, index) => `${JSON.stringify(name)}: ${paramTypes[index]}`).join("; ")} }`
|
|
12
|
+
: paramTypes.length === 0 ? "[]" : `[${paramTypes.join(", ")}]`;
|
|
11
13
|
if (!e.hasResultSet)
|
|
12
14
|
return { params, row: "never" };
|
|
13
15
|
const cols = e.columns.map((c) => {
|
|
@@ -23,7 +25,9 @@ export function emitDts(outPath, entries, functions = []) {
|
|
|
23
25
|
lines.push("// AUTO-GENERATED by sqlx-js. Do not edit.");
|
|
24
26
|
lines.push("// Run `sqlx-js prepare` to regenerate.");
|
|
25
27
|
lines.push("");
|
|
26
|
-
|
|
28
|
+
emitRegistry(lines, entries, functions);
|
|
29
|
+
lines.push("");
|
|
30
|
+
emitModuleAugmentation(lines, "@onreza/sqlx-js");
|
|
27
31
|
lines.push("");
|
|
28
32
|
lines.push("export {};");
|
|
29
33
|
const tmp = `${outPath}.tmp-${randomBytes(4).toString("hex")}`;
|
|
@@ -39,9 +43,8 @@ export function emitDts(outPath, entries, functions = []) {
|
|
|
39
43
|
throw err;
|
|
40
44
|
}
|
|
41
45
|
}
|
|
42
|
-
function
|
|
43
|
-
lines.push(
|
|
44
|
-
lines.push(" interface KnownQueries {");
|
|
46
|
+
function emitRegistry(lines, entries, functions) {
|
|
47
|
+
lines.push("export interface SqlxJsGeneratedQueries {");
|
|
45
48
|
const inlineSeen = new Set();
|
|
46
49
|
const inlinePairs = [];
|
|
47
50
|
for (const e of entries) {
|
|
@@ -58,12 +61,12 @@ function emitModule(lines, moduleName, entries, functions) {
|
|
|
58
61
|
inlineSeen.add(query);
|
|
59
62
|
const { params, row } = entrySignature(entry);
|
|
60
63
|
if (entry.degraded)
|
|
61
|
-
lines.push(`
|
|
62
|
-
lines.push(`
|
|
64
|
+
lines.push(` /** Nullability inference degraded: ${entry.degraded.reason}. All result columns conservatively typed as nullable. */`);
|
|
65
|
+
lines.push(` ${JSON.stringify(query)}: { params: ${params}; row: ${row} };`);
|
|
63
66
|
}
|
|
64
|
-
lines.push("
|
|
67
|
+
lines.push("}");
|
|
65
68
|
lines.push("");
|
|
66
|
-
lines.push("
|
|
69
|
+
lines.push("export interface SqlxJsGeneratedFileQueries {");
|
|
67
70
|
const filePairs = [];
|
|
68
71
|
for (const e of entries) {
|
|
69
72
|
if (!e.filePaths || e.filePaths.length === 0)
|
|
@@ -78,21 +81,33 @@ function emitModule(lines, moduleName, entries, functions) {
|
|
|
78
81
|
filePathsSeen.add(path);
|
|
79
82
|
const { params, row } = entrySignature(entry);
|
|
80
83
|
if (entry.degraded)
|
|
81
|
-
lines.push(`
|
|
82
|
-
lines.push(`
|
|
84
|
+
lines.push(` /** Nullability inference degraded: ${entry.degraded.reason}. */`);
|
|
85
|
+
lines.push(` ${JSON.stringify(path)}: { params: ${params}; row: ${row} };`);
|
|
83
86
|
}
|
|
84
|
-
lines.push("
|
|
87
|
+
lines.push("}");
|
|
85
88
|
lines.push("");
|
|
86
|
-
lines.push("
|
|
89
|
+
lines.push("export interface SqlxJsGeneratedFunctions {");
|
|
87
90
|
const functionSeen = new Set();
|
|
88
91
|
for (const fn of functions.slice().sort((a, b) => a.signature.localeCompare(b.signature))) {
|
|
89
92
|
if (functionSeen.has(fn.signature))
|
|
90
93
|
continue;
|
|
91
94
|
functionSeen.add(fn.signature);
|
|
92
95
|
const params = inputParams(fn);
|
|
93
|
-
lines.push(`
|
|
96
|
+
lines.push(` ${JSON.stringify(fn.signature)}: { kind: ${JSON.stringify(fn.kind)}; params: ${params}; returns: ${fn.returns}; returnsSet: ${fn.returnsSet} };`);
|
|
94
97
|
}
|
|
95
|
-
lines.push("
|
|
98
|
+
lines.push("}");
|
|
99
|
+
lines.push("");
|
|
100
|
+
lines.push("export interface SqlxJsGeneratedRegistry {");
|
|
101
|
+
lines.push(" queries: SqlxJsGeneratedQueries;");
|
|
102
|
+
lines.push(" fileQueries: SqlxJsGeneratedFileQueries;");
|
|
103
|
+
lines.push(" functions: SqlxJsGeneratedFunctions;");
|
|
104
|
+
lines.push("}");
|
|
105
|
+
}
|
|
106
|
+
function emitModuleAugmentation(lines, moduleName) {
|
|
107
|
+
lines.push(`declare module ${JSON.stringify(moduleName)} {`);
|
|
108
|
+
lines.push(" interface KnownQueries extends SqlxJsGeneratedQueries {}");
|
|
109
|
+
lines.push(" interface KnownFileQueries extends SqlxJsGeneratedFileQueries {}");
|
|
110
|
+
lines.push(" interface KnownFunctions extends SqlxJsGeneratedFunctions {}");
|
|
96
111
|
lines.push("}");
|
|
97
112
|
}
|
|
98
113
|
function inputParams(fn) {
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import type { SqlxJsConfig } from "../config.js";
|
|
2
|
+
export type CiStep = {
|
|
3
|
+
name: string;
|
|
4
|
+
args: string[];
|
|
5
|
+
check?: "pgschema-plan";
|
|
6
|
+
};
|
|
7
|
+
export type CiStepResult = {
|
|
8
|
+
name: string;
|
|
9
|
+
ok: boolean;
|
|
10
|
+
durationMs: number;
|
|
11
|
+
exitCode: number;
|
|
12
|
+
stderr?: string;
|
|
13
|
+
};
|
|
14
|
+
export type CiOptions = {
|
|
15
|
+
executable: string;
|
|
16
|
+
cliPath: string;
|
|
17
|
+
root: string;
|
|
18
|
+
config: SqlxJsConfig;
|
|
19
|
+
schemaPath: string;
|
|
20
|
+
json?: boolean;
|
|
21
|
+
shadowUrl?: string;
|
|
22
|
+
shadowAdminUrl?: string;
|
|
23
|
+
migrationsDir?: string;
|
|
24
|
+
dtsPath?: string;
|
|
25
|
+
};
|
|
26
|
+
export declare function buildCiSteps(opts: Pick<CiOptions, "config" | "root" | "schemaPath" | "shadowUrl" | "shadowAdminUrl" | "migrationsDir" | "dtsPath">): CiStep[];
|
|
27
|
+
export declare function assertPgschemaPlanClean(path: string): void;
|
|
28
|
+
export declare function runCi(opts: CiOptions): void;
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
import { existsSync, mkdtempSync, readFileSync, rmSync } from "node:fs";
|
|
2
|
+
import { spawnSync } from "node:child_process";
|
|
3
|
+
import { tmpdir } from "node:os";
|
|
4
|
+
import { join } from "node:path";
|
|
5
|
+
const PLAN_PATH = "{sqlx-js-ci-plan}";
|
|
6
|
+
export function buildCiSteps(opts) {
|
|
7
|
+
const root = ["--root", opts.root];
|
|
8
|
+
const shadow = opts.shadowUrl ? ["--shadow-url", opts.shadowUrl] : [];
|
|
9
|
+
const shadowAdmin = opts.shadowAdminUrl ? ["--shadow-admin-url", opts.shadowAdminUrl] : [];
|
|
10
|
+
const migrations = opts.migrationsDir ? ["--migrations", opts.migrationsDir] : [];
|
|
11
|
+
const dts = opts.dtsPath ? ["--dts", opts.dtsPath] : [];
|
|
12
|
+
const steps = opts.config.schema?.provider === "pgschema"
|
|
13
|
+
? [
|
|
14
|
+
{ name: "pgschema", args: ["db", "check", ...root] },
|
|
15
|
+
{
|
|
16
|
+
name: "pgschema-plan",
|
|
17
|
+
args: ["db", "plan", ...root, "--", "--output-json", PLAN_PATH, "--no-color"],
|
|
18
|
+
check: "pgschema-plan",
|
|
19
|
+
},
|
|
20
|
+
{ name: "prepare-live", args: ["prepare", "--verify", "--strict-inference", ...shadow, ...dts, ...root] },
|
|
21
|
+
]
|
|
22
|
+
: [{
|
|
23
|
+
name: "migrations",
|
|
24
|
+
args: ["migrate", "verify", "--strict-inference", ...shadow, ...shadowAdmin, ...migrations, ...dts, ...root],
|
|
25
|
+
}];
|
|
26
|
+
steps.push({ name: "prepare-offline", args: ["prepare", "--check", "--strict-inference", ...dts, ...root] });
|
|
27
|
+
if (existsSync(opts.schemaPath)) {
|
|
28
|
+
steps.push({ name: "schema", args: ["schema", "check", ...shadow, "--schema", opts.schemaPath, ...migrations, ...root] });
|
|
29
|
+
}
|
|
30
|
+
return steps;
|
|
31
|
+
}
|
|
32
|
+
export function assertPgschemaPlanClean(path) {
|
|
33
|
+
const plan = JSON.parse(readFileSync(path, "utf8"));
|
|
34
|
+
if (plan.groups === null)
|
|
35
|
+
return;
|
|
36
|
+
if (!Array.isArray(plan.groups))
|
|
37
|
+
throw new Error("plan JSON does not contain groups as an array or null");
|
|
38
|
+
if (plan.groups.length > 0)
|
|
39
|
+
throw new Error(`pgschema plan contains ${plan.groups.length} unapplied change group(s)`);
|
|
40
|
+
}
|
|
41
|
+
export function runCi(opts) {
|
|
42
|
+
const results = [];
|
|
43
|
+
const temp = mkdtempSync(join(tmpdir(), "sqlx-js-ci-"));
|
|
44
|
+
try {
|
|
45
|
+
for (const step of buildCiSteps(opts)) {
|
|
46
|
+
if (!opts.json)
|
|
47
|
+
console.log(`ci: ${step.name}`);
|
|
48
|
+
const started = performance.now();
|
|
49
|
+
const planPath = join(temp, "pgschema-plan.json");
|
|
50
|
+
const args = step.args.map((arg) => arg === PLAN_PATH ? planPath : arg);
|
|
51
|
+
const result = spawnSync(opts.executable, [opts.cliPath, ...args], {
|
|
52
|
+
encoding: "utf8",
|
|
53
|
+
env: process.env,
|
|
54
|
+
stdio: opts.json ? ["ignore", "ignore", "pipe"] : "inherit",
|
|
55
|
+
maxBuffer: 4 * 1024 * 1024,
|
|
56
|
+
});
|
|
57
|
+
let exitCode = result.status ?? 1;
|
|
58
|
+
let checkError;
|
|
59
|
+
if (exitCode === 0 && step.check === "pgschema-plan") {
|
|
60
|
+
try {
|
|
61
|
+
assertPgschemaPlanClean(planPath);
|
|
62
|
+
}
|
|
63
|
+
catch (error) {
|
|
64
|
+
checkError = error.message.startsWith("pgschema plan contains")
|
|
65
|
+
? error.message
|
|
66
|
+
: `cannot verify pgschema plan: ${error.message}`;
|
|
67
|
+
exitCode = 1;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
if (result.error) {
|
|
71
|
+
checkError = result.error.message;
|
|
72
|
+
exitCode = 1;
|
|
73
|
+
}
|
|
74
|
+
else if (result.signal) {
|
|
75
|
+
checkError = `terminated by signal ${result.signal}`;
|
|
76
|
+
exitCode = 1;
|
|
77
|
+
}
|
|
78
|
+
if (checkError && !opts.json)
|
|
79
|
+
console.error(`ci: ${step.name}: ${checkError}`);
|
|
80
|
+
results.push({
|
|
81
|
+
name: step.name,
|
|
82
|
+
ok: exitCode === 0,
|
|
83
|
+
durationMs: Math.round(performance.now() - started),
|
|
84
|
+
exitCode,
|
|
85
|
+
...(opts.json && exitCode !== 0 && (checkError || result.stderr)
|
|
86
|
+
? { stderr: [result.stderr?.trim(), checkError].filter(Boolean).join("\n") }
|
|
87
|
+
: {}),
|
|
88
|
+
});
|
|
89
|
+
if (exitCode !== 0)
|
|
90
|
+
break;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
finally {
|
|
94
|
+
rmSync(temp, { recursive: true, force: true });
|
|
95
|
+
}
|
|
96
|
+
const ok = results.length > 0 && results.every((result) => result.ok);
|
|
97
|
+
if (opts.json)
|
|
98
|
+
console.log(JSON.stringify({ formatVersion: 1, ok, results }, null, 2));
|
|
99
|
+
else if (ok)
|
|
100
|
+
console.log(`ci: ok — ${results.length} check(s) passed`);
|
|
101
|
+
if (!ok)
|
|
102
|
+
process.exitCode = 1;
|
|
103
|
+
}
|
|
@@ -36,10 +36,19 @@ const PGSCHEMA_TEMPLATE = `-- Desired PostgreSQL schema managed by pgschema.
|
|
|
36
36
|
const DTS_TEMPLATE = `// AUTO-GENERATED by sqlx-js. Do not edit.
|
|
37
37
|
// Run \`sqlx-js prepare\` to regenerate.
|
|
38
38
|
|
|
39
|
+
export interface SqlxJsGeneratedQueries {}
|
|
40
|
+
export interface SqlxJsGeneratedFileQueries {}
|
|
41
|
+
export interface SqlxJsGeneratedFunctions {}
|
|
42
|
+
export interface SqlxJsGeneratedRegistry {
|
|
43
|
+
queries: SqlxJsGeneratedQueries;
|
|
44
|
+
fileQueries: SqlxJsGeneratedFileQueries;
|
|
45
|
+
functions: SqlxJsGeneratedFunctions;
|
|
46
|
+
}
|
|
47
|
+
|
|
39
48
|
declare module "@onreza/sqlx-js" {
|
|
40
|
-
interface KnownQueries {}
|
|
41
|
-
interface KnownFileQueries {}
|
|
42
|
-
interface KnownFunctions {}
|
|
49
|
+
interface KnownQueries extends SqlxJsGeneratedQueries {}
|
|
50
|
+
interface KnownFileQueries extends SqlxJsGeneratedFileQueries {}
|
|
51
|
+
interface KnownFunctions extends SqlxJsGeneratedFunctions {}
|
|
43
52
|
}
|
|
44
53
|
|
|
45
54
|
export {};
|
|
@@ -132,7 +141,9 @@ export function runInit(opts) {
|
|
|
132
141
|
const defaults = {
|
|
133
142
|
"sqlx:prepare": "sqlx-js prepare",
|
|
134
143
|
"sqlx:check": "sqlx-js prepare --check",
|
|
144
|
+
"sqlx:offline": "sqlx-js prepare --offline",
|
|
135
145
|
"sqlx:verify": "sqlx-js prepare --verify --strict-inference",
|
|
146
|
+
"sqlx:ci": "sqlx-js ci",
|
|
136
147
|
};
|
|
137
148
|
let changed = false;
|
|
138
149
|
for (const [name, command] of Object.entries(defaults)) {
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { PgClient, type ConnConfig, type FieldDescription } from "../pg/wire.js";
|
|
2
2
|
import { SchemaCache } from "../pg/schema.js";
|
|
3
|
+
import { type QueryCallSite } from "../scan/scanner.js";
|
|
3
4
|
import { type SqlxJsConfig } from "../config.js";
|
|
4
5
|
export type PrepareOptions = {
|
|
5
6
|
root: string;
|
|
@@ -7,6 +8,7 @@ export type PrepareOptions = {
|
|
|
7
8
|
cacheDir: string;
|
|
8
9
|
dtsPath: string;
|
|
9
10
|
check: boolean;
|
|
11
|
+
offline?: boolean;
|
|
10
12
|
verify?: boolean;
|
|
11
13
|
json?: boolean;
|
|
12
14
|
prune?: boolean;
|
|
@@ -49,6 +51,11 @@ export type PrepareSession = {
|
|
|
49
51
|
schema: SchemaCache;
|
|
50
52
|
userCfg: SqlxJsConfig;
|
|
51
53
|
};
|
|
54
|
+
export type PrepareIncrementalInput = {
|
|
55
|
+
sites?: QueryCallSite[];
|
|
56
|
+
reuseCacheFps?: ReadonlySet<string>;
|
|
57
|
+
reuseFunctions?: boolean;
|
|
58
|
+
};
|
|
52
59
|
export declare function openSession(opts: PrepareOptions): Promise<PrepareSession>;
|
|
53
60
|
type DescribeOutcome = {
|
|
54
61
|
ok: true;
|
|
@@ -63,7 +70,7 @@ export declare function describeAll(cfg: ConnConfig, sessionClient: PgClient, qu
|
|
|
63
70
|
fp: string;
|
|
64
71
|
query: string;
|
|
65
72
|
}[], concurrency: number): Promise<Map<string, DescribeOutcome>>;
|
|
66
|
-
export declare function prepareOnce(opts: PrepareOptions, session: PrepareSession, log?: (msg: string) => void, err?: (msg: string) => void, concurrency?: number): Promise<PrepareResult>;
|
|
73
|
+
export declare function prepareOnce(opts: PrepareOptions, session: PrepareSession, log?: (msg: string) => void, err?: (msg: string) => void, concurrency?: number, input?: PrepareIncrementalInput): Promise<PrepareResult>;
|
|
67
74
|
export declare function runPrepare(opts: PrepareOptions): Promise<void>;
|
|
68
75
|
export declare function verifyPrepareArtifacts(opts: PrepareOptions, log?: (msg: string) => void, err?: (msg: string) => void): Promise<{
|
|
69
76
|
ok: boolean;
|