@onreza/sqlx-js 0.0.0 → 0.2.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 +111 -22
- package/ROADMAP.md +2 -3
- package/dist/bin/sqlx-js.js +94 -11
- package/dist/src/codegen.js +0 -2
- package/dist/src/commands/init.d.ts +5 -0
- package/dist/src/commands/init.js +57 -0
- package/dist/src/commands/migrate.d.ts +190 -3
- package/dist/src/commands/migrate.js +1383 -46
- package/dist/src/commands/prepare.d.ts +16 -2
- package/dist/src/commands/prepare.js +81 -23
- package/dist/src/commands/schema.js +4 -0
- package/dist/src/commands/watch.js +1 -1
- package/dist/src/index.d.ts +2 -2
- package/dist/src/pg/narrow.js +8 -0
- package/dist/src/pg/schema.d.ts +17 -1
- package/dist/src/pg/schema.js +48 -2
- package/dist/src/pg/wire.d.ts +14 -1
- package/dist/src/pg/wire.js +81 -3
- package/dist/src/postgres-runtime.d.ts +9 -2
- package/dist/src/postgres-runtime.js +20 -5
- package/dist/src/runtime.d.ts +12 -0
- package/dist/src/runtime.js +83 -3
- package/dist/src/scan/scanner.js +1 -1
- package/package.json +6 -9
- package/dist/src/bun-runtime.d.ts +0 -7
- package/dist/src/bun-runtime.js +0 -45
- package/dist/src/bun.d.ts +0 -22
- package/dist/src/bun.js +0 -9
package/dist/src/runtime.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { existsSync, readFileSync, statSync } from "node:fs";
|
|
2
2
|
import { resolve } from "node:path";
|
|
3
|
-
import { PgClient, parseDatabaseUrl } from "./pg/wire.js";
|
|
3
|
+
import { PgClient, parseDatabaseUrl, PgError } from "./pg/wire.js";
|
|
4
4
|
import { applyPending, acquireMigrateLock, releaseMigrateLock, DEFAULT_MIGRATE_LOCK_KEY } from "./commands/migrate.js";
|
|
5
5
|
const SUFFIX = /[!?]$/;
|
|
6
6
|
function renameRows(rows) {
|
|
@@ -148,6 +148,63 @@ export class TooManyRowsError extends Error {
|
|
|
148
148
|
this.actual = actual;
|
|
149
149
|
}
|
|
150
150
|
}
|
|
151
|
+
// SQLSTATE is exactly five characters from [0-9A-Z]; lowercase or other shapes
|
|
152
|
+
// are never valid, so transport codes like "EPIPE" must not match on shape alone.
|
|
153
|
+
const SQLSTATE = /^[0-9A-Z]{5}$/;
|
|
154
|
+
function firstString(...candidates) {
|
|
155
|
+
for (const value of candidates) {
|
|
156
|
+
if (typeof value === "string" && value.length > 0)
|
|
157
|
+
return value;
|
|
158
|
+
}
|
|
159
|
+
return undefined;
|
|
160
|
+
}
|
|
161
|
+
export function toPgError(e) {
|
|
162
|
+
if (e instanceof PgError)
|
|
163
|
+
return e;
|
|
164
|
+
if (e === null || typeof e !== "object")
|
|
165
|
+
return null;
|
|
166
|
+
const o = e;
|
|
167
|
+
const code = typeof o.code === "string" ? o.code : undefined;
|
|
168
|
+
// `_name` variants are postgres.js; bare forms are node-postgres. Bare
|
|
169
|
+
// `column`/`schema`/`table` can also collide with runtime-added Error
|
|
170
|
+
// properties, so we read namespaced variants first and only accept strings.
|
|
171
|
+
const severity = firstString(o.severity, o.severity_local);
|
|
172
|
+
// A genuine database error is identified by the driver's branded name
|
|
173
|
+
// (Postgres.js) or by a SQLSTATE-shaped code paired with a severity. Transport
|
|
174
|
+
// and system errors (EPIPE, ECONNREFUSED, CONNECTION_ENDED) carry neither, so
|
|
175
|
+
// they pass through untouched instead of masquerading as a PgError.
|
|
176
|
+
const isDatabaseError = o.name === "PostgresError" ||
|
|
177
|
+
(code !== undefined && SQLSTATE.test(code) && severity !== undefined);
|
|
178
|
+
if (!isDatabaseError)
|
|
179
|
+
return null;
|
|
180
|
+
const fields = {};
|
|
181
|
+
if (typeof o.message === "string" && o.message.length > 0)
|
|
182
|
+
fields.M = o.message;
|
|
183
|
+
if (code)
|
|
184
|
+
fields.C = code;
|
|
185
|
+
if (typeof o.detail === "string" && o.detail.length > 0)
|
|
186
|
+
fields.D = o.detail;
|
|
187
|
+
if (typeof o.hint === "string" && o.hint.length > 0)
|
|
188
|
+
fields.H = o.hint;
|
|
189
|
+
const position = firstString(o.position) ?? (typeof o.position === "number" && Number.isFinite(o.position) ? String(o.position) : undefined);
|
|
190
|
+
if (position)
|
|
191
|
+
fields.P = position;
|
|
192
|
+
if (severity)
|
|
193
|
+
fields.S = severity;
|
|
194
|
+
const table = firstString(o.table_name, o.table);
|
|
195
|
+
if (table)
|
|
196
|
+
fields.t = table;
|
|
197
|
+
const column = firstString(o.column_name, o.column);
|
|
198
|
+
if (column)
|
|
199
|
+
fields.c = column;
|
|
200
|
+
const constraint = firstString(o.constraint_name, o.constraint);
|
|
201
|
+
if (constraint)
|
|
202
|
+
fields.n = constraint;
|
|
203
|
+
const schema = firstString(o.schema_name, o.schema);
|
|
204
|
+
if (schema)
|
|
205
|
+
fields.s = schema;
|
|
206
|
+
return new PgError(fields, { cause: e });
|
|
207
|
+
}
|
|
151
208
|
export const _internal = {
|
|
152
209
|
renameRows,
|
|
153
210
|
encodeParam,
|
|
@@ -156,13 +213,32 @@ export const _internal = {
|
|
|
156
213
|
loadSqlFile,
|
|
157
214
|
buildSetTransaction,
|
|
158
215
|
clearIdentifierCache,
|
|
216
|
+
toPgError,
|
|
159
217
|
};
|
|
160
218
|
async function runQuery(client, query, params) {
|
|
161
219
|
const encoded = params.length === 0
|
|
162
220
|
? params
|
|
163
221
|
: params.map((p) => client.transformParam ? client.transformParam(p) : encodeParam(p));
|
|
164
|
-
const
|
|
165
|
-
|
|
222
|
+
const onQuery = client.onQuery;
|
|
223
|
+
if (!onQuery) {
|
|
224
|
+
try {
|
|
225
|
+
return renameRows(await client.query(query, encoded));
|
|
226
|
+
}
|
|
227
|
+
catch (e) {
|
|
228
|
+
throw toPgError(e) ?? e;
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
const start = performance.now();
|
|
232
|
+
try {
|
|
233
|
+
const rows = await client.query(query, encoded);
|
|
234
|
+
onQuery({ query, params, durationMs: performance.now() - start, rowCount: rows.length });
|
|
235
|
+
return renameRows(rows);
|
|
236
|
+
}
|
|
237
|
+
catch (e) {
|
|
238
|
+
const error = toPgError(e) ?? e;
|
|
239
|
+
onQuery({ query, params, durationMs: performance.now() - start, error });
|
|
240
|
+
throw error;
|
|
241
|
+
}
|
|
166
242
|
}
|
|
167
243
|
async function runOne(client, query, params) {
|
|
168
244
|
const rows = await runQuery(client, query, params);
|
|
@@ -422,6 +498,10 @@ export async function migrate(opts = {}) {
|
|
|
422
498
|
log(`migrate: applied ${String(e.version).padStart(4, "0")}_${e.name}`);
|
|
423
499
|
appliedAny = true;
|
|
424
500
|
}
|
|
501
|
+
else if (e.kind === "adopted") {
|
|
502
|
+
log(`migrate: adopted ${String(e.version).padStart(4, "0")}_${e.name} (${e.replaced} replaced)`);
|
|
503
|
+
appliedAny = true;
|
|
504
|
+
}
|
|
425
505
|
else if (e.kind === "tampered") {
|
|
426
506
|
throw new Error(`sqlx-js.migrate: ${e.version}_${e.name} hash mismatch (applied ${e.applied.slice(0, 16)}… vs current ${e.current.slice(0, 16)}…)`);
|
|
427
507
|
}
|
package/dist/src/scan/scanner.js
CHANGED
|
@@ -2,7 +2,7 @@ import ts from "typescript";
|
|
|
2
2
|
import { existsSync, readFileSync, readdirSync, statSync } from "node:fs";
|
|
3
3
|
import { dirname, join, relative, resolve } from "node:path";
|
|
4
4
|
const EXCLUDE_DIRS = new Set(["node_modules", ".git", ".sqlx-js", "dist", "build", ".next"]);
|
|
5
|
-
const SQLX_MODULES = new Set(["@onreza/sqlx-js"
|
|
5
|
+
const SQLX_MODULES = new Set(["@onreza/sqlx-js"]);
|
|
6
6
|
const EXT = /\.(ts|tsx|mts|cts)$/;
|
|
7
7
|
function walk(dir, out) {
|
|
8
8
|
for (const name of readdirSync(dir)) {
|
package/package.json
CHANGED
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@onreza/sqlx-js",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"description": "Compile-time-checked raw SQL for TypeScript + PostgreSQL. Inspired by sqlx.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
7
|
+
"engines": {
|
|
8
|
+
"node": ">=18"
|
|
9
|
+
},
|
|
7
10
|
"sideEffects": false,
|
|
8
11
|
"main": "./dist/src/index.js",
|
|
9
12
|
"types": "./dist/src/index.d.ts",
|
|
@@ -12,16 +15,10 @@
|
|
|
12
15
|
"types": "./dist/src/index.d.ts",
|
|
13
16
|
"import": "./dist/src/index.js",
|
|
14
17
|
"default": "./dist/src/index.js"
|
|
15
|
-
},
|
|
16
|
-
"./bun": {
|
|
17
|
-
"types": "./dist/src/bun.d.ts",
|
|
18
|
-
"bun": "./dist/src/bun.js",
|
|
19
|
-
"import": "./dist/src/bun.js",
|
|
20
|
-
"default": "./dist/src/bun.js"
|
|
21
18
|
}
|
|
22
19
|
},
|
|
23
20
|
"bin": {
|
|
24
|
-
"sqlx-js": "
|
|
21
|
+
"sqlx-js": "dist/bin/sqlx-js.js"
|
|
25
22
|
},
|
|
26
23
|
"files": [
|
|
27
24
|
"dist",
|
|
@@ -52,7 +49,7 @@
|
|
|
52
49
|
"migrations"
|
|
53
50
|
],
|
|
54
51
|
"scripts": {
|
|
55
|
-
"prepare": "[ -d .git ]
|
|
52
|
+
"prepare": "(test -f dist/bin/sqlx-js.js || bun run build) && ([ ! -d .git ] || lefthook install >/dev/null 2>&1 || true)",
|
|
56
53
|
"test": "bun test tests",
|
|
57
54
|
"test:typecheck": "tsc --noEmit",
|
|
58
55
|
"test:example": "bunx tsc -p example --noEmit",
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
import { SQL } from "bun";
|
|
2
|
-
export type BunClient = SQL;
|
|
3
|
-
export declare function getClient(): BunClient;
|
|
4
|
-
export declare function setClient(client: BunClient): void;
|
|
5
|
-
export declare function close(): Promise<void>;
|
|
6
|
-
export declare const sql: import("./runtime.js").SqlRoot;
|
|
7
|
-
export declare const unsafe: (query: string, ...params: unknown[]) => Promise<Record<string, unknown>[]>;
|
package/dist/src/bun-runtime.js
DELETED
|
@@ -1,45 +0,0 @@
|
|
|
1
|
-
import { SQL } from "bun";
|
|
2
|
-
import { createSqlRuntime } from "./runtime.js";
|
|
3
|
-
class BunRuntimeClient {
|
|
4
|
-
client;
|
|
5
|
-
constructor(client) {
|
|
6
|
-
this.client = client;
|
|
7
|
-
}
|
|
8
|
-
async query(query, params) {
|
|
9
|
-
return await this.client.unsafe(query, params);
|
|
10
|
-
}
|
|
11
|
-
async transaction(fn) {
|
|
12
|
-
return await this.client.begin(async (tx) => {
|
|
13
|
-
return await fn(new BunRuntimeClient(tx));
|
|
14
|
-
});
|
|
15
|
-
}
|
|
16
|
-
async close() {
|
|
17
|
-
await this.client.close();
|
|
18
|
-
}
|
|
19
|
-
}
|
|
20
|
-
let defaultClient = null;
|
|
21
|
-
function createDefaultClient() {
|
|
22
|
-
const url = process.env.DATABASE_URL;
|
|
23
|
-
if (!url)
|
|
24
|
-
throw new Error("sqlx-js: DATABASE_URL is not set");
|
|
25
|
-
return new BunRuntimeClient(new SQL({ url, bigint: true }));
|
|
26
|
-
}
|
|
27
|
-
function getRuntimeClient() {
|
|
28
|
-
defaultClient ??= createDefaultClient();
|
|
29
|
-
return defaultClient;
|
|
30
|
-
}
|
|
31
|
-
export function getClient() {
|
|
32
|
-
return getRuntimeClient().client;
|
|
33
|
-
}
|
|
34
|
-
export function setClient(client) {
|
|
35
|
-
defaultClient = new BunRuntimeClient(client);
|
|
36
|
-
}
|
|
37
|
-
export async function close() {
|
|
38
|
-
if (defaultClient) {
|
|
39
|
-
await defaultClient.close();
|
|
40
|
-
defaultClient = null;
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
const runtime = createSqlRuntime(getRuntimeClient);
|
|
44
|
-
export const sql = runtime.sql;
|
|
45
|
-
export const unsafe = runtime.unsafe;
|
package/dist/src/bun.d.ts
DELETED
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
import * as rt from "./bun-runtime.js";
|
|
2
|
-
import type { Typed as TypedFor, TypedFile as TypedFileFor, TypedSql as TypedSqlFor } from "./typed.js";
|
|
3
|
-
export interface KnownQueries {
|
|
4
|
-
}
|
|
5
|
-
export interface KnownFileQueries {
|
|
6
|
-
}
|
|
7
|
-
export type { SqlxJsConfig } from "./config.js";
|
|
8
|
-
export type { SslMode, ConnConfig } from "./pg/wire.js";
|
|
9
|
-
export { PgError, ConnectionLostError } from "./pg/wire.js";
|
|
10
|
-
export { NoRowsError, TooManyRowsError } from "./runtime.js";
|
|
11
|
-
export type { TransactionOptions, MigrateOptions } from "./runtime.js";
|
|
12
|
-
export type { BunClient } from "./bun-runtime.js";
|
|
13
|
-
export type TypedFile = TypedFileFor<KnownFileQueries>;
|
|
14
|
-
export type TypedSql = TypedSqlFor<KnownQueries, KnownFileQueries>;
|
|
15
|
-
export type Typed = TypedFor<KnownQueries, KnownFileQueries, import("./runtime.js").TransactionOptions>;
|
|
16
|
-
export declare const sql: Typed;
|
|
17
|
-
export type Unsafe = (query: string, ...params: unknown[]) => Promise<Record<string, unknown>[]>;
|
|
18
|
-
export declare const unsafe: Unsafe;
|
|
19
|
-
export declare const getClient: typeof rt.getClient;
|
|
20
|
-
export declare const setClient: typeof rt.setClient;
|
|
21
|
-
export declare const close: typeof rt.close;
|
|
22
|
-
export { migrate, clearSqlFileCache, encodePgArrayLiteral, id } from "./runtime.js";
|
package/dist/src/bun.js
DELETED
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
import * as rt from "./bun-runtime.js";
|
|
2
|
-
export { PgError, ConnectionLostError } from "./pg/wire.js";
|
|
3
|
-
export { NoRowsError, TooManyRowsError } from "./runtime.js";
|
|
4
|
-
export const sql = rt.sql;
|
|
5
|
-
export const unsafe = rt.unsafe;
|
|
6
|
-
export const getClient = rt.getClient;
|
|
7
|
-
export const setClient = rt.setClient;
|
|
8
|
-
export const close = rt.close;
|
|
9
|
-
export { migrate, clearSqlFileCache, encodePgArrayLiteral, id } from "./runtime.js";
|