@geekmidas/db 10.0.0-alpha.12 → 10.0.0-alpha.14
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/errors.cjs +72 -5
- package/dist/errors.cjs.map +1 -0
- package/dist/errors.d.cts +4 -6
- package/dist/errors.d.cts.map +1 -1
- package/dist/errors.d.mts +4 -6
- package/dist/errors.d.mts.map +1 -1
- package/dist/errors.mjs +68 -2
- package/dist/errors.mjs.map +1 -0
- package/dist/kysely/pagination.cjs +7 -9
- package/dist/kysely/pagination.cjs.map +1 -1
- package/dist/kysely/pagination.d.cts +4 -14
- package/dist/kysely/pagination.d.cts.map +1 -1
- package/dist/kysely/pagination.d.mts +4 -14
- package/dist/kysely/pagination.d.mts.map +1 -1
- package/dist/kysely/pagination.mjs +6 -9
- package/dist/kysely/pagination.mjs.map +1 -1
- package/dist/kysely.cjs +11 -2
- package/dist/kysely.cjs.map +1 -0
- package/dist/kysely.d.cts +9 -2
- package/dist/kysely.d.cts.map +1 -0
- package/dist/kysely.d.mts +9 -2
- package/dist/kysely.d.mts.map +1 -0
- package/dist/kysely.mjs +10 -2
- package/dist/kysely.mjs.map +1 -0
- package/dist/objection/pagination.cjs +6 -7
- package/dist/objection/pagination.cjs.map +1 -1
- package/dist/objection/pagination.d.cts +4 -14
- package/dist/objection/pagination.d.cts.map +1 -1
- package/dist/objection/pagination.d.mts +4 -14
- package/dist/objection/pagination.d.mts.map +1 -1
- package/dist/objection/pagination.mjs +5 -7
- package/dist/objection/pagination.mjs.map +1 -1
- package/dist/pagination.cjs +39 -4
- package/dist/pagination.cjs.map +1 -0
- package/dist/pagination.d.cts +30 -2
- package/dist/pagination.d.cts.map +1 -0
- package/dist/pagination.d.mts +30 -2
- package/dist/pagination.d.mts.map +1 -0
- package/dist/pagination.mjs +36 -2
- package/dist/pagination.mjs.map +1 -0
- package/dist/pg/roles.cjs +3 -2
- package/dist/pg/roles.cjs.map +1 -1
- package/dist/pg/roles.d.cts +6 -8
- package/dist/pg/roles.d.cts.map +1 -1
- package/dist/pg/roles.d.mts +6 -8
- package/dist/pg/roles.d.mts.map +1 -1
- package/dist/pg/roles.mjs +2 -1
- package/dist/pg/roles.mjs.map +1 -1
- package/dist/pg/url.cjs +18 -3
- package/dist/pg/url.cjs.map +1 -1
- package/dist/pg/url.d.cts +2 -4
- package/dist/pg/url.d.cts.map +1 -1
- package/dist/pg/url.d.mts +2 -4
- package/dist/pg/url.d.mts.map +1 -1
- package/dist/pg/url.mjs +17 -3
- package/dist/pg/url.mjs.map +1 -1
- package/dist/rls.cjs +5 -29
- package/dist/rls.cjs.map +1 -1
- package/dist/rls.d.cts +6 -10
- package/dist/rls.d.cts.map +1 -1
- package/dist/rls.d.mts +6 -10
- package/dist/rls.d.mts.map +1 -1
- package/dist/rls.mjs +3 -5
- package/dist/rls.mjs.map +1 -1
- package/package.json +2 -2
- package/dist/errors-CfFCan-X.mjs +0 -69
- package/dist/errors-CfFCan-X.mjs.map +0 -1
- package/dist/errors-Cs5jlAv-.cjs +0 -93
- package/dist/errors-Cs5jlAv-.cjs.map +0 -1
- package/dist/kysely-BAedYsvn.d.mts +0 -13
- package/dist/kysely-BAedYsvn.d.mts.map +0 -1
- package/dist/kysely-Bo_Zg-D3.mjs +0 -11
- package/dist/kysely-Bo_Zg-D3.mjs.map +0 -1
- package/dist/kysely-D3eeuId4.d.cts +0 -13
- package/dist/kysely-D3eeuId4.d.cts.map +0 -1
- package/dist/kysely-LWvS2ekY.cjs +0 -17
- package/dist/kysely-LWvS2ekY.cjs.map +0 -1
- package/dist/pagination-BAFX7C1I.d.cts +0 -32
- package/dist/pagination-BAFX7C1I.d.cts.map +0 -1
- package/dist/pagination-Bu1dqOy0.cjs +0 -55
- package/dist/pagination-Bu1dqOy0.cjs.map +0 -1
- package/dist/pagination-CQ8QHXaL.mjs +0 -37
- package/dist/pagination-CQ8QHXaL.mjs.map +0 -1
- package/dist/pagination-kv-KWS-7.d.mts +0 -32
- package/dist/pagination-kv-KWS-7.d.mts.map +0 -1
package/dist/pg/url.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"url.cjs","names":["
|
|
1
|
+
{"version":3,"file":"url.cjs","names":["MissingDatabaseHost","MissingDatabaseName"],"sources":["../../src/pg/url.ts"],"sourcesContent":["/**\n * Composing a `postgres://` connection string.\n *\n * One direction only. Parsing exists in `pg` already — every consumer hands the\n * string straight to `new Pool({ connectionString })` — so a parser here would\n * be surface whose only caller is its own round-trip test.\n *\n * What is *not* already solved is composition: a provisioned instance exposes\n * host, port, database, username, and password as five separate values, and the\n * construct reads one URL. Doing that join by hand is where `search_path`\n * quietly goes missing.\n *\n * A URL built here is a secret — it carries the role's password. See\n * {@link redactDatabaseUrl} before writing one anywhere.\n */\n\nimport { MissingDatabaseHost, MissingDatabaseName } from '../errors';\n\n/** What a Postgres connection string addresses. */\nexport interface PostgresAddress {\n\thost: string;\n\tport?: number;\n\t/** The logical database. */\n\tdatabase: string;\n\t/** The role connecting — which is what decides DDL versus DML. */\n\tusername?: string;\n\tpassword?: string;\n\t/**\n\t * The schema to resolve unqualified names against.\n\t *\n\t * Normally pinned on the *role* instead (`ALTER ROLE … SET search_path`), so\n\t * it does not appear in the URL at all. It is carried here for the one case\n\t * with no role of its own to pin — connecting as the cluster master under\n\t * `roles: false` — where without it every query looks in `public`.\n\t *\n\t * Postgres-specific by nature, not just by spelling: it becomes a libpq\n\t * connection option, and no other engine accepts one. MySQL has no schemas\n\t * distinct from databases at all.\n\t */\n\tsearchPath?: string;\n\t/** Off only for local development, where there is no certificate to verify. */\n\tssl?: boolean;\n}\n\nconst SCHEME = 'postgres:';\n\nconst DEFAULT_PORT = 5432;\n\n/**\n * `search_path` travels as a libpq connection option, not a query parameter.\n * The server reads `options`; a plain `?search_path=app` is accepted by the URL\n * parser, ignored by the server, and produces a database that looks empty.\n * The `-c` prefix is what makes it a runtime configuration setting.\n */\nfunction searchPathOption(schema: string): string {\n\treturn `-c search_path=${schema}`;\n}\n\n/** Compose an address into a connection string. */\nexport function build(address: PostgresAddress): string {\n\tconst { host, port, database, username, password, searchPath, ssl } = address;\n\n\tif (!host) throw new MissingDatabaseHost();\n\tif (!database) throw new MissingDatabaseName();\n\n\tconst url = new URL(`${SCHEME}//`);\n\turl.hostname = host;\n\tif (port && port !== DEFAULT_PORT) url.port = String(port);\n\t// Username before password: WHATWG URL drops a password set without one.\n\tif (username) url.username = encodeURIComponent(username);\n\tif (password) url.password = encodeURIComponent(password);\n\turl.pathname = `/${database}`;\n\n\tif (searchPath) url.searchParams.set('options', searchPathOption(searchPath));\n\tif (ssl === false) url.searchParams.set('sslmode', 'disable');\n\n\treturn url.toString();\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AA4CA,MAAM,SAAS;AAEf,MAAM,eAAe;;;;;;;AAQrB,SAAS,iBAAiB,QAAwB;CACjD,OAAO,kBAAkB;AAC1B;;AAGA,SAAgB,MAAM,SAAkC;CACvD,MAAM,EAAE,MAAM,MAAM,UAAU,UAAU,UAAU,YAAY,QAAQ;CAEtE,IAAI,CAAC,MAAM,MAAM,IAAIA,eAAAA,oBAAoB;CACzC,IAAI,CAAC,UAAU,MAAM,IAAIC,eAAAA,oBAAoB;CAE7C,MAAM,MAAM,IAAI,IAAI,GAAG,OAAO,GAAG;CACjC,IAAI,WAAW;CACf,IAAI,QAAQ,SAAS,cAAc,IAAI,OAAO,OAAO,IAAI;CAEzD,IAAI,UAAU,IAAI,WAAW,mBAAmB,QAAQ;CACxD,IAAI,UAAU,IAAI,WAAW,mBAAmB,QAAQ;CACxD,IAAI,WAAW,IAAI;CAEnB,IAAI,YAAY,IAAI,aAAa,IAAI,WAAW,iBAAiB,UAAU,CAAC;CAC5E,IAAI,QAAQ,OAAO,IAAI,aAAa,IAAI,WAAW,SAAS;CAE5D,OAAO,IAAI,SAAS;AACrB"}
|
package/dist/pg/url.d.cts
CHANGED
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
* {@link redactDatabaseUrl} before writing one anywhere.
|
|
16
16
|
*/
|
|
17
17
|
/** What a Postgres connection string addresses. */
|
|
18
|
-
interface PostgresAddress {
|
|
18
|
+
export interface PostgresAddress {
|
|
19
19
|
host: string;
|
|
20
20
|
port?: number;
|
|
21
21
|
/** The logical database. */
|
|
@@ -40,8 +40,6 @@ interface PostgresAddress {
|
|
|
40
40
|
ssl?: boolean;
|
|
41
41
|
}
|
|
42
42
|
/** Compose an address into a connection string. */
|
|
43
|
-
declare function build(address: PostgresAddress): string;
|
|
44
|
-
//# sourceMappingURL=url.d.ts.map
|
|
43
|
+
export declare function build(address: PostgresAddress): string;
|
|
45
44
|
//#endregion
|
|
46
|
-
export { PostgresAddress, build };
|
|
47
45
|
//# sourceMappingURL=url.d.cts.map
|
package/dist/pg/url.d.cts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"url.d.cts","names":[],"sources":["../../src/pg/url.ts"],"
|
|
1
|
+
{"version":3,"file":"url.d.cts","names":[],"sources":["../../src/pg/url.ts"],"mappings":";;;;;;;;;;;;;;;;;iBAmBiB;EAChB;EACA;;EAEA;;EAEA;EACA;;;;;;;;;;;;;EAaA;;EAEA;;;wBAkBe,MAAM,SAAS"}
|
package/dist/pg/url.d.mts
CHANGED
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
* {@link redactDatabaseUrl} before writing one anywhere.
|
|
16
16
|
*/
|
|
17
17
|
/** What a Postgres connection string addresses. */
|
|
18
|
-
interface PostgresAddress {
|
|
18
|
+
export interface PostgresAddress {
|
|
19
19
|
host: string;
|
|
20
20
|
port?: number;
|
|
21
21
|
/** The logical database. */
|
|
@@ -40,8 +40,6 @@ interface PostgresAddress {
|
|
|
40
40
|
ssl?: boolean;
|
|
41
41
|
}
|
|
42
42
|
/** Compose an address into a connection string. */
|
|
43
|
-
declare function build(address: PostgresAddress): string;
|
|
44
|
-
//# sourceMappingURL=url.d.ts.map
|
|
43
|
+
export declare function build(address: PostgresAddress): string;
|
|
45
44
|
//#endregion
|
|
46
|
-
export { PostgresAddress, build };
|
|
47
45
|
//# sourceMappingURL=url.d.mts.map
|
package/dist/pg/url.d.mts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"url.d.mts","names":[],"sources":["../../src/pg/url.ts"],"
|
|
1
|
+
{"version":3,"file":"url.d.mts","names":[],"sources":["../../src/pg/url.ts"],"mappings":";;;;;;;;;;;;;;;;;iBAmBiB;EAChB;EACA;;EAEA;;EAEA;EACA;;;;;;;;;;;;;EAaA;;EAEA;;;wBAkBe,MAAM,SAAS"}
|
package/dist/pg/url.mjs
CHANGED
|
@@ -1,6 +1,20 @@
|
|
|
1
|
-
import { MissingDatabaseHost, MissingDatabaseName } from "../errors
|
|
2
|
-
|
|
1
|
+
import { MissingDatabaseHost, MissingDatabaseName } from "../errors.mjs";
|
|
3
2
|
//#region src/pg/url.ts
|
|
3
|
+
/**
|
|
4
|
+
* Composing a `postgres://` connection string.
|
|
5
|
+
*
|
|
6
|
+
* One direction only. Parsing exists in `pg` already — every consumer hands the
|
|
7
|
+
* string straight to `new Pool({ connectionString })` — so a parser here would
|
|
8
|
+
* be surface whose only caller is its own round-trip test.
|
|
9
|
+
*
|
|
10
|
+
* What is *not* already solved is composition: a provisioned instance exposes
|
|
11
|
+
* host, port, database, username, and password as five separate values, and the
|
|
12
|
+
* construct reads one URL. Doing that join by hand is where `search_path`
|
|
13
|
+
* quietly goes missing.
|
|
14
|
+
*
|
|
15
|
+
* A URL built here is a secret — it carries the role's password. See
|
|
16
|
+
* {@link redactDatabaseUrl} before writing one anywhere.
|
|
17
|
+
*/
|
|
4
18
|
const SCHEME = "postgres:";
|
|
5
19
|
const DEFAULT_PORT = 5432;
|
|
6
20
|
/**
|
|
@@ -27,7 +41,7 @@ function build(address) {
|
|
|
27
41
|
if (ssl === false) url.searchParams.set("sslmode", "disable");
|
|
28
42
|
return url.toString();
|
|
29
43
|
}
|
|
30
|
-
|
|
31
44
|
//#endregion
|
|
32
45
|
export { build };
|
|
46
|
+
|
|
33
47
|
//# sourceMappingURL=url.mjs.map
|
package/dist/pg/url.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"url.mjs","names":[
|
|
1
|
+
{"version":3,"file":"url.mjs","names":[],"sources":["../../src/pg/url.ts"],"sourcesContent":["/**\n * Composing a `postgres://` connection string.\n *\n * One direction only. Parsing exists in `pg` already — every consumer hands the\n * string straight to `new Pool({ connectionString })` — so a parser here would\n * be surface whose only caller is its own round-trip test.\n *\n * What is *not* already solved is composition: a provisioned instance exposes\n * host, port, database, username, and password as five separate values, and the\n * construct reads one URL. Doing that join by hand is where `search_path`\n * quietly goes missing.\n *\n * A URL built here is a secret — it carries the role's password. See\n * {@link redactDatabaseUrl} before writing one anywhere.\n */\n\nimport { MissingDatabaseHost, MissingDatabaseName } from '../errors';\n\n/** What a Postgres connection string addresses. */\nexport interface PostgresAddress {\n\thost: string;\n\tport?: number;\n\t/** The logical database. */\n\tdatabase: string;\n\t/** The role connecting — which is what decides DDL versus DML. */\n\tusername?: string;\n\tpassword?: string;\n\t/**\n\t * The schema to resolve unqualified names against.\n\t *\n\t * Normally pinned on the *role* instead (`ALTER ROLE … SET search_path`), so\n\t * it does not appear in the URL at all. It is carried here for the one case\n\t * with no role of its own to pin — connecting as the cluster master under\n\t * `roles: false` — where without it every query looks in `public`.\n\t *\n\t * Postgres-specific by nature, not just by spelling: it becomes a libpq\n\t * connection option, and no other engine accepts one. MySQL has no schemas\n\t * distinct from databases at all.\n\t */\n\tsearchPath?: string;\n\t/** Off only for local development, where there is no certificate to verify. */\n\tssl?: boolean;\n}\n\nconst SCHEME = 'postgres:';\n\nconst DEFAULT_PORT = 5432;\n\n/**\n * `search_path` travels as a libpq connection option, not a query parameter.\n * The server reads `options`; a plain `?search_path=app` is accepted by the URL\n * parser, ignored by the server, and produces a database that looks empty.\n * The `-c` prefix is what makes it a runtime configuration setting.\n */\nfunction searchPathOption(schema: string): string {\n\treturn `-c search_path=${schema}`;\n}\n\n/** Compose an address into a connection string. */\nexport function build(address: PostgresAddress): string {\n\tconst { host, port, database, username, password, searchPath, ssl } = address;\n\n\tif (!host) throw new MissingDatabaseHost();\n\tif (!database) throw new MissingDatabaseName();\n\n\tconst url = new URL(`${SCHEME}//`);\n\turl.hostname = host;\n\tif (port && port !== DEFAULT_PORT) url.port = String(port);\n\t// Username before password: WHATWG URL drops a password set without one.\n\tif (username) url.username = encodeURIComponent(username);\n\tif (password) url.password = encodeURIComponent(password);\n\turl.pathname = `/${database}`;\n\n\tif (searchPath) url.searchParams.set('options', searchPathOption(searchPath));\n\tif (ssl === false) url.searchParams.set('sslmode', 'disable');\n\n\treturn url.toString();\n}\n"],"mappings":";;;;;;;;;;;;;;;;;AA4CA,MAAM,SAAS;AAEf,MAAM,eAAe;;;;;;;AAQrB,SAAS,iBAAiB,QAAwB;CACjD,OAAO,kBAAkB;AAC1B;;AAGA,SAAgB,MAAM,SAAkC;CACvD,MAAM,EAAE,MAAM,MAAM,UAAU,UAAU,UAAU,YAAY,QAAQ;CAEtE,IAAI,CAAC,MAAM,MAAM,IAAI,oBAAoB;CACzC,IAAI,CAAC,UAAU,MAAM,IAAI,oBAAoB;CAE7C,MAAM,MAAM,IAAI,IAAI,GAAG,OAAO,GAAG;CACjC,IAAI,WAAW;CACf,IAAI,QAAQ,SAAS,cAAc,IAAI,OAAO,OAAO,IAAI;CAEzD,IAAI,UAAU,IAAI,WAAW,mBAAmB,QAAQ;CACxD,IAAI,UAAU,IAAI,WAAW,mBAAmB,QAAQ;CACxD,IAAI,WAAW,IAAI;CAEnB,IAAI,YAAY,IAAI,aAAa,IAAI,WAAW,iBAAiB,UAAU,CAAC;CAC5E,IAAI,QAAQ,OAAO,IAAI,aAAa,IAAI,WAAW,SAAS;CAE5D,OAAO,IAAI,SAAS;AACrB"}
|
package/dist/rls.cjs
CHANGED
|
@@ -1,29 +1,6 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
-
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
-
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
-
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
-
var __copyProps = (to, from, except, desc) => {
|
|
9
|
-
if (from && typeof from === "object" || typeof from === "function") for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
|
|
10
|
-
key = keys[i];
|
|
11
|
-
if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, {
|
|
12
|
-
get: ((k) => from[k]).bind(null, key),
|
|
13
|
-
enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
|
|
14
|
-
});
|
|
15
|
-
}
|
|
16
|
-
return to;
|
|
17
|
-
};
|
|
18
|
-
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", {
|
|
19
|
-
value: mod,
|
|
20
|
-
enumerable: true
|
|
21
|
-
}) : target, mod));
|
|
22
|
-
|
|
23
|
-
//#endregion
|
|
24
|
-
const require_kysely = require('./kysely-LWvS2ekY.cjs');
|
|
25
|
-
const kysely = __toESM(require("kysely"));
|
|
26
|
-
|
|
1
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
+
const require_kysely = require("./kysely.cjs");
|
|
3
|
+
let kysely = require("kysely");
|
|
27
4
|
//#region src/rls.ts
|
|
28
5
|
/**
|
|
29
6
|
* Execute a callback within a transaction with RLS context variables set.
|
|
@@ -55,8 +32,7 @@ async function withRlsContext(db, context, callback, options) {
|
|
|
55
32
|
for (const [key, value] of Object.entries(context)) {
|
|
56
33
|
if (value === null || value === void 0) continue;
|
|
57
34
|
const settingName = `${prefix}.${key}`;
|
|
58
|
-
|
|
59
|
-
await kysely.sql`SELECT set_config(${settingName}, ${settingValue}, true)`.execute(trx);
|
|
35
|
+
await kysely.sql`SELECT set_config(${settingName}, ${String(value)}, true)`.execute(trx);
|
|
60
36
|
}
|
|
61
37
|
return callback(trx);
|
|
62
38
|
}, options?.settings);
|
|
@@ -65,8 +41,8 @@ async function withRlsContext(db, context, callback, options) {
|
|
|
65
41
|
* Bypass marker symbol for explicitly skipping RLS context.
|
|
66
42
|
*/
|
|
67
43
|
const RLS_BYPASS = Symbol.for("geekmidas.rls.bypass");
|
|
68
|
-
|
|
69
44
|
//#endregion
|
|
70
45
|
exports.RLS_BYPASS = RLS_BYPASS;
|
|
71
46
|
exports.withRlsContext = withRlsContext;
|
|
47
|
+
|
|
72
48
|
//# sourceMappingURL=rls.cjs.map
|
package/dist/rls.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rls.cjs","names":["
|
|
1
|
+
{"version":3,"file":"rls.cjs","names":["withTransaction"],"sources":["../src/rls.ts"],"sourcesContent":["import type { Transaction } from 'kysely';\nimport { sql } from 'kysely';\nimport {\n\ttype DatabaseConnection,\n\ttype TransactionSettings,\n\twithTransaction,\n} from './kysely';\n\n/**\n * RLS context - key-value pairs to set as PostgreSQL session variables.\n * Keys become `prefix.key` (e.g., `app.user_id`).\n */\nexport interface RlsContext {\n\t[key: string]: string | number | boolean | null | undefined;\n}\n\n/**\n * Options for withRlsContext function.\n */\nexport interface WithRlsContextOptions {\n\t/** Prefix for PostgreSQL session variables (default: 'app') */\n\tprefix?: string;\n\t/** Transaction settings (isolation level) */\n\tsettings?: TransactionSettings;\n}\n\n/**\n * Execute a callback within a transaction with RLS context variables set.\n *\n * Sets PostgreSQL session variables using `SET LOCAL` which scopes them to the\n * current transaction. Variables are automatically cleared when the transaction\n * ends (commit or rollback).\n *\n * @example\n * ```ts\n * await withRlsContext(\n * db,\n * { user_id: session.userId, tenant_id: session.tenantId },\n * async (trx) => {\n * // RLS policies can now use current_setting('app.user_id')\n * return trx.selectFrom('orders').selectAll().execute();\n * }\n * );\n * ```\n *\n * @param db - Database connection (Kysely, Transaction, or ControlledTransaction)\n * @param context - Key-value pairs to set as session variables\n * @param callback - Function to execute within the RLS context\n * @param options - Optional prefix and transaction settings\n */\nexport async function withRlsContext<DB, T>(\n\tdb: DatabaseConnection<DB>,\n\tcontext: RlsContext,\n\tcallback: (trx: Transaction<DB>) => Promise<T>,\n\toptions?: WithRlsContextOptions,\n): Promise<T> {\n\tconst prefix = options?.prefix ?? 'app';\n\n\treturn withTransaction(\n\t\tdb,\n\t\tasync (trx) => {\n\t\t\t// Set each context variable using SET LOCAL (scoped to transaction)\n\t\t\tfor (const [key, value] of Object.entries(context)) {\n\t\t\t\tif (value === null || value === undefined) continue;\n\n\t\t\t\tconst settingName = `${prefix}.${key}`;\n\t\t\t\tconst settingValue = String(value);\n\n\t\t\t\t// Use raw SQL for SET LOCAL with proper escaping\n\t\t\t\t// The setting name is an identifier, value is a string literal\n\t\t\t\tawait sql`SELECT set_config(${settingName}, ${settingValue}, true)`.execute(\n\t\t\t\t\ttrx,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\treturn callback(trx);\n\t\t},\n\t\toptions?.settings,\n\t);\n}\n\n/**\n * Bypass marker symbol for explicitly skipping RLS context.\n */\nexport const RLS_BYPASS = Symbol.for('geekmidas.rls.bypass');\n\n/**\n * Type for RLS bypass marker.\n */\nexport type RlsBypass = typeof RLS_BYPASS;\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAkDA,eAAsB,eACrB,IACA,SACA,UACA,SACa;CACb,MAAM,SAAS,SAAS,UAAU;CAElC,OAAOA,eAAAA,gBACN,IACA,OAAO,QAAQ;EAEd,KAAK,MAAM,CAAC,KAAK,UAAU,OAAO,QAAQ,OAAO,GAAG;GACnD,IAAI,UAAU,QAAQ,UAAU,KAAA,GAAW;GAE3C,MAAM,cAAc,GAAG,OAAO,GAAG;GAKjC,MAAM,OAAA,GAAG,qBAAqB,YAAY,IAJrB,OAAO,KAI6B,EAAE,SAAS,QACnE,GACD;EACD;EAEA,OAAO,SAAS,GAAG;CACpB,GACA,SAAS,QACV;AACD;;;;AAKA,MAAa,aAAa,OAAO,IAAI,sBAAsB"}
|
package/dist/rls.d.cts
CHANGED
|
@@ -1,19 +1,17 @@
|
|
|
1
|
-
import { DatabaseConnection, TransactionSettings } from "./kysely
|
|
1
|
+
import { DatabaseConnection, TransactionSettings } from "./kysely.cjs";
|
|
2
2
|
import { Transaction } from "kysely";
|
|
3
|
-
|
|
4
3
|
//#region src/rls.d.ts
|
|
5
|
-
|
|
6
4
|
/**
|
|
7
5
|
* RLS context - key-value pairs to set as PostgreSQL session variables.
|
|
8
6
|
* Keys become `prefix.key` (e.g., `app.user_id`).
|
|
9
7
|
*/
|
|
10
|
-
interface RlsContext {
|
|
8
|
+
export interface RlsContext {
|
|
11
9
|
[key: string]: string | number | boolean | null | undefined;
|
|
12
10
|
}
|
|
13
11
|
/**
|
|
14
12
|
* Options for withRlsContext function.
|
|
15
13
|
*/
|
|
16
|
-
interface WithRlsContextOptions {
|
|
14
|
+
export interface WithRlsContextOptions {
|
|
17
15
|
/** Prefix for PostgreSQL session variables (default: 'app') */
|
|
18
16
|
prefix?: string;
|
|
19
17
|
/** Transaction settings (isolation level) */
|
|
@@ -43,16 +41,14 @@ interface WithRlsContextOptions {
|
|
|
43
41
|
* @param callback - Function to execute within the RLS context
|
|
44
42
|
* @param options - Optional prefix and transaction settings
|
|
45
43
|
*/
|
|
46
|
-
declare function withRlsContext<DB, T>(db: DatabaseConnection<DB>, context: RlsContext, callback: (trx: Transaction<DB>) => Promise<T>, options?: WithRlsContextOptions): Promise<T>;
|
|
44
|
+
export declare function withRlsContext<DB, T>(db: DatabaseConnection<DB>, context: RlsContext, callback: (trx: Transaction<DB>) => Promise<T>, options?: WithRlsContextOptions): Promise<T>;
|
|
47
45
|
/**
|
|
48
46
|
* Bypass marker symbol for explicitly skipping RLS context.
|
|
49
47
|
*/
|
|
50
|
-
declare const RLS_BYPASS: unique symbol;
|
|
48
|
+
export declare const RLS_BYPASS: unique symbol;
|
|
51
49
|
/**
|
|
52
50
|
* Type for RLS bypass marker.
|
|
53
51
|
*/
|
|
54
|
-
type RlsBypass = typeof RLS_BYPASS;
|
|
55
|
-
//# sourceMappingURL=rls.d.ts.map
|
|
52
|
+
export type RlsBypass = typeof RLS_BYPASS;
|
|
56
53
|
//#endregion
|
|
57
|
-
export { RLS_BYPASS, RlsBypass, RlsContext, WithRlsContextOptions, withRlsContext };
|
|
58
54
|
//# sourceMappingURL=rls.d.cts.map
|
package/dist/rls.d.cts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rls.d.cts","names":[],"sources":["../src/rls.ts"],"
|
|
1
|
+
{"version":3,"file":"rls.d.cts","names":[],"sources":["../src/rls.ts"],"mappings":";;;;;;;iBAYiB;GACf;;;;;iBAMe;;EAEhB;;EAEA,WAAW;;;;;;;;;;;;;;;;;;;;;;;;;;wBA2BU,eAAe,IAAI,GACxC,IAAI,mBAAmB,KACvB,SAAS,YACT,WAAW,KAAK,YAAY,QAAQ,QAAQ,IAC5C,UAAU,wBACR,QAAQ;;;;qBA6BE;;;;YAKD,mBAAmB"}
|
package/dist/rls.d.mts
CHANGED
|
@@ -1,19 +1,17 @@
|
|
|
1
|
-
import { DatabaseConnection, TransactionSettings } from "./kysely
|
|
1
|
+
import { DatabaseConnection, TransactionSettings } from "./kysely.mjs";
|
|
2
2
|
import { Transaction } from "kysely";
|
|
3
|
-
|
|
4
3
|
//#region src/rls.d.ts
|
|
5
|
-
|
|
6
4
|
/**
|
|
7
5
|
* RLS context - key-value pairs to set as PostgreSQL session variables.
|
|
8
6
|
* Keys become `prefix.key` (e.g., `app.user_id`).
|
|
9
7
|
*/
|
|
10
|
-
interface RlsContext {
|
|
8
|
+
export interface RlsContext {
|
|
11
9
|
[key: string]: string | number | boolean | null | undefined;
|
|
12
10
|
}
|
|
13
11
|
/**
|
|
14
12
|
* Options for withRlsContext function.
|
|
15
13
|
*/
|
|
16
|
-
interface WithRlsContextOptions {
|
|
14
|
+
export interface WithRlsContextOptions {
|
|
17
15
|
/** Prefix for PostgreSQL session variables (default: 'app') */
|
|
18
16
|
prefix?: string;
|
|
19
17
|
/** Transaction settings (isolation level) */
|
|
@@ -43,16 +41,14 @@ interface WithRlsContextOptions {
|
|
|
43
41
|
* @param callback - Function to execute within the RLS context
|
|
44
42
|
* @param options - Optional prefix and transaction settings
|
|
45
43
|
*/
|
|
46
|
-
declare function withRlsContext<DB, T>(db: DatabaseConnection<DB>, context: RlsContext, callback: (trx: Transaction<DB>) => Promise<T>, options?: WithRlsContextOptions): Promise<T>;
|
|
44
|
+
export declare function withRlsContext<DB, T>(db: DatabaseConnection<DB>, context: RlsContext, callback: (trx: Transaction<DB>) => Promise<T>, options?: WithRlsContextOptions): Promise<T>;
|
|
47
45
|
/**
|
|
48
46
|
* Bypass marker symbol for explicitly skipping RLS context.
|
|
49
47
|
*/
|
|
50
|
-
declare const RLS_BYPASS: unique symbol;
|
|
48
|
+
export declare const RLS_BYPASS: unique symbol;
|
|
51
49
|
/**
|
|
52
50
|
* Type for RLS bypass marker.
|
|
53
51
|
*/
|
|
54
|
-
type RlsBypass = typeof RLS_BYPASS;
|
|
55
|
-
//# sourceMappingURL=rls.d.ts.map
|
|
52
|
+
export type RlsBypass = typeof RLS_BYPASS;
|
|
56
53
|
//#endregion
|
|
57
|
-
export { RLS_BYPASS, RlsBypass, RlsContext, WithRlsContextOptions, withRlsContext };
|
|
58
54
|
//# sourceMappingURL=rls.d.mts.map
|
package/dist/rls.d.mts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rls.d.mts","names":[],"sources":["../src/rls.ts"],"
|
|
1
|
+
{"version":3,"file":"rls.d.mts","names":[],"sources":["../src/rls.ts"],"mappings":";;;;;;;iBAYiB;GACf;;;;;iBAMe;;EAEhB;;EAEA,WAAW;;;;;;;;;;;;;;;;;;;;;;;;;;wBA2BU,eAAe,IAAI,GACxC,IAAI,mBAAmB,KACvB,SAAS,YACT,WAAW,KAAK,YAAY,QAAQ,QAAQ,IAC5C,UAAU,wBACR,QAAQ;;;;qBA6BE;;;;YAKD,mBAAmB"}
|
package/dist/rls.mjs
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
import { withTransaction } from "./kysely
|
|
1
|
+
import { withTransaction } from "./kysely.mjs";
|
|
2
2
|
import { sql } from "kysely";
|
|
3
|
-
|
|
4
3
|
//#region src/rls.ts
|
|
5
4
|
/**
|
|
6
5
|
* Execute a callback within a transaction with RLS context variables set.
|
|
@@ -32,8 +31,7 @@ async function withRlsContext(db, context, callback, options) {
|
|
|
32
31
|
for (const [key, value] of Object.entries(context)) {
|
|
33
32
|
if (value === null || value === void 0) continue;
|
|
34
33
|
const settingName = `${prefix}.${key}`;
|
|
35
|
-
|
|
36
|
-
await sql`SELECT set_config(${settingName}, ${settingValue}, true)`.execute(trx);
|
|
34
|
+
await sql`SELECT set_config(${settingName}, ${String(value)}, true)`.execute(trx);
|
|
37
35
|
}
|
|
38
36
|
return callback(trx);
|
|
39
37
|
}, options?.settings);
|
|
@@ -42,7 +40,7 @@ async function withRlsContext(db, context, callback, options) {
|
|
|
42
40
|
* Bypass marker symbol for explicitly skipping RLS context.
|
|
43
41
|
*/
|
|
44
42
|
const RLS_BYPASS = Symbol.for("geekmidas.rls.bypass");
|
|
45
|
-
|
|
46
43
|
//#endregion
|
|
47
44
|
export { RLS_BYPASS, withRlsContext };
|
|
45
|
+
|
|
48
46
|
//# sourceMappingURL=rls.mjs.map
|
package/dist/rls.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rls.mjs","names":[
|
|
1
|
+
{"version":3,"file":"rls.mjs","names":[],"sources":["../src/rls.ts"],"sourcesContent":["import type { Transaction } from 'kysely';\nimport { sql } from 'kysely';\nimport {\n\ttype DatabaseConnection,\n\ttype TransactionSettings,\n\twithTransaction,\n} from './kysely';\n\n/**\n * RLS context - key-value pairs to set as PostgreSQL session variables.\n * Keys become `prefix.key` (e.g., `app.user_id`).\n */\nexport interface RlsContext {\n\t[key: string]: string | number | boolean | null | undefined;\n}\n\n/**\n * Options for withRlsContext function.\n */\nexport interface WithRlsContextOptions {\n\t/** Prefix for PostgreSQL session variables (default: 'app') */\n\tprefix?: string;\n\t/** Transaction settings (isolation level) */\n\tsettings?: TransactionSettings;\n}\n\n/**\n * Execute a callback within a transaction with RLS context variables set.\n *\n * Sets PostgreSQL session variables using `SET LOCAL` which scopes them to the\n * current transaction. Variables are automatically cleared when the transaction\n * ends (commit or rollback).\n *\n * @example\n * ```ts\n * await withRlsContext(\n * db,\n * { user_id: session.userId, tenant_id: session.tenantId },\n * async (trx) => {\n * // RLS policies can now use current_setting('app.user_id')\n * return trx.selectFrom('orders').selectAll().execute();\n * }\n * );\n * ```\n *\n * @param db - Database connection (Kysely, Transaction, or ControlledTransaction)\n * @param context - Key-value pairs to set as session variables\n * @param callback - Function to execute within the RLS context\n * @param options - Optional prefix and transaction settings\n */\nexport async function withRlsContext<DB, T>(\n\tdb: DatabaseConnection<DB>,\n\tcontext: RlsContext,\n\tcallback: (trx: Transaction<DB>) => Promise<T>,\n\toptions?: WithRlsContextOptions,\n): Promise<T> {\n\tconst prefix = options?.prefix ?? 'app';\n\n\treturn withTransaction(\n\t\tdb,\n\t\tasync (trx) => {\n\t\t\t// Set each context variable using SET LOCAL (scoped to transaction)\n\t\t\tfor (const [key, value] of Object.entries(context)) {\n\t\t\t\tif (value === null || value === undefined) continue;\n\n\t\t\t\tconst settingName = `${prefix}.${key}`;\n\t\t\t\tconst settingValue = String(value);\n\n\t\t\t\t// Use raw SQL for SET LOCAL with proper escaping\n\t\t\t\t// The setting name is an identifier, value is a string literal\n\t\t\t\tawait sql`SELECT set_config(${settingName}, ${settingValue}, true)`.execute(\n\t\t\t\t\ttrx,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\treturn callback(trx);\n\t\t},\n\t\toptions?.settings,\n\t);\n}\n\n/**\n * Bypass marker symbol for explicitly skipping RLS context.\n */\nexport const RLS_BYPASS = Symbol.for('geekmidas.rls.bypass');\n\n/**\n * Type for RLS bypass marker.\n */\nexport type RlsBypass = typeof RLS_BYPASS;\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;AAkDA,eAAsB,eACrB,IACA,SACA,UACA,SACa;CACb,MAAM,SAAS,SAAS,UAAU;CAElC,OAAO,gBACN,IACA,OAAO,QAAQ;EAEd,KAAK,MAAM,CAAC,KAAK,UAAU,OAAO,QAAQ,OAAO,GAAG;GACnD,IAAI,UAAU,QAAQ,UAAU,KAAA,GAAW;GAE3C,MAAM,cAAc,GAAG,OAAO,GAAG;GAKjC,MAAM,GAAG,qBAAqB,YAAY,IAJrB,OAAO,KAI6B,EAAE,SAAS,QACnE,GACD;EACD;EAEA,OAAO,SAAS,GAAG;CACpB,GACA,SAAS,QACV;AACD;;;;AAKA,MAAa,aAAa,OAAO,IAAI,sBAAsB"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@geekmidas/db",
|
|
3
|
-
"version": "10.0.0-alpha.
|
|
3
|
+
"version": "10.0.0-alpha.14",
|
|
4
4
|
"private": false,
|
|
5
5
|
"type": "module",
|
|
6
6
|
"exports": {
|
|
@@ -108,7 +108,7 @@
|
|
|
108
108
|
"knex": ">=3.3.0",
|
|
109
109
|
"objection": ">=3.1.5",
|
|
110
110
|
"db-errors": "~0.2.3",
|
|
111
|
-
"vitest": "~
|
|
111
|
+
"vitest": "~5.0.2"
|
|
112
112
|
},
|
|
113
113
|
"scripts": {
|
|
114
114
|
"ts": "tsc --noEmit --skipLibCheck src/**/*.ts"
|
package/dist/errors-CfFCan-X.mjs
DELETED
|
@@ -1,69 +0,0 @@
|
|
|
1
|
-
//#region src/errors.ts
|
|
2
|
-
/**
|
|
3
|
-
* Database URL errors and redaction — engine-neutral.
|
|
4
|
-
*
|
|
5
|
-
* Nothing here is Postgres-specific: every engine addresses itself as a URL
|
|
6
|
-
* carrying a password, and "must name a host" holds for all of them. The parts
|
|
7
|
-
* that differ — libpq's `options=-c search_path=…`, which no other engine
|
|
8
|
-
* accepts — live under the driver they belong to.
|
|
9
|
-
*
|
|
10
|
-
* Messages state the rule, which is constant; the offending value is a field.
|
|
11
|
-
* An interpolated message cannot be matched on and carries user input into
|
|
12
|
-
* every log line that touches it.
|
|
13
|
-
*/
|
|
14
|
-
/**
|
|
15
|
-
* Replace the password in a connection string with `***`.
|
|
16
|
-
*
|
|
17
|
-
* A connection string is a secret, and the places it is most likely to be
|
|
18
|
-
* written down — a log line, an error, a crash report shipped to a third party
|
|
19
|
-
* — are the places nobody is reading carefully. This exists so that redacting
|
|
20
|
-
* is the easy thing to do at each of them.
|
|
21
|
-
*
|
|
22
|
-
* Safe on input that is not a URL: it returns a constant rather than throwing,
|
|
23
|
-
* because this runs on paths that must not fail. Anything unparseable is
|
|
24
|
-
* treated as potentially secret and withheld entirely rather than echoed.
|
|
25
|
-
*/
|
|
26
|
-
function redactDatabaseUrl(url) {
|
|
27
|
-
try {
|
|
28
|
-
const parsed = new URL(url);
|
|
29
|
-
if (!parsed.password) return url;
|
|
30
|
-
parsed.password = "***";
|
|
31
|
-
return parsed.toString();
|
|
32
|
-
} catch {
|
|
33
|
-
return "<unparseable url>";
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
|
-
/**
|
|
37
|
-
* Base for an address that cannot become a connection string.
|
|
38
|
-
*
|
|
39
|
-
* Deliberately carries no URL field: these are thrown while *composing* one, so
|
|
40
|
-
* there is no URL yet — only the parts, which include the password.
|
|
41
|
-
*/
|
|
42
|
-
var DatabaseAddressError = class extends Error {
|
|
43
|
-
constructor(message) {
|
|
44
|
-
super(message);
|
|
45
|
-
this.name = new.target.name;
|
|
46
|
-
}
|
|
47
|
-
};
|
|
48
|
-
/** An address with no host to connect to. */
|
|
49
|
-
var MissingDatabaseHost = class extends DatabaseAddressError {
|
|
50
|
-
constructor() {
|
|
51
|
-
super("A database address must name a host");
|
|
52
|
-
}
|
|
53
|
-
};
|
|
54
|
-
/**
|
|
55
|
-
* An address with no database name.
|
|
56
|
-
*
|
|
57
|
-
* Postgres silently falls back to the connecting role's name, so the app
|
|
58
|
-
* connects successfully to the wrong database and fails later with confusing
|
|
59
|
-
* "relation does not exist" errors. Rejecting it here is much cheaper.
|
|
60
|
-
*/
|
|
61
|
-
var MissingDatabaseName = class extends DatabaseAddressError {
|
|
62
|
-
constructor() {
|
|
63
|
-
super("A database address must name a database");
|
|
64
|
-
}
|
|
65
|
-
};
|
|
66
|
-
|
|
67
|
-
//#endregion
|
|
68
|
-
export { DatabaseAddressError, MissingDatabaseHost, MissingDatabaseName, redactDatabaseUrl };
|
|
69
|
-
//# sourceMappingURL=errors-CfFCan-X.mjs.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"errors-CfFCan-X.mjs","names":["url: string","message: string"],"sources":["../src/errors.ts"],"sourcesContent":["/**\n * Database URL errors and redaction — engine-neutral.\n *\n * Nothing here is Postgres-specific: every engine addresses itself as a URL\n * carrying a password, and \"must name a host\" holds for all of them. The parts\n * that differ — libpq's `options=-c search_path=…`, which no other engine\n * accepts — live under the driver they belong to.\n *\n * Messages state the rule, which is constant; the offending value is a field.\n * An interpolated message cannot be matched on and carries user input into\n * every log line that touches it.\n */\n\n/**\n * Replace the password in a connection string with `***`.\n *\n * A connection string is a secret, and the places it is most likely to be\n * written down — a log line, an error, a crash report shipped to a third party\n * — are the places nobody is reading carefully. This exists so that redacting\n * is the easy thing to do at each of them.\n *\n * Safe on input that is not a URL: it returns a constant rather than throwing,\n * because this runs on paths that must not fail. Anything unparseable is\n * treated as potentially secret and withheld entirely rather than echoed.\n */\nexport function redactDatabaseUrl(url: string): string {\n\ttry {\n\t\tconst parsed = new URL(url);\n\t\tif (!parsed.password) return url;\n\t\tparsed.password = '***';\n\t\treturn parsed.toString();\n\t} catch {\n\t\treturn '<unparseable url>';\n\t}\n}\n\n/**\n * Base for an address that cannot become a connection string.\n *\n * Deliberately carries no URL field: these are thrown while *composing* one, so\n * there is no URL yet — only the parts, which include the password.\n */\nexport abstract class DatabaseAddressError extends Error {\n\tconstructor(message: string) {\n\t\tsuper(message);\n\t\tthis.name = new.target.name;\n\t}\n}\n\n/** An address with no host to connect to. */\nexport class MissingDatabaseHost extends DatabaseAddressError {\n\tconstructor() {\n\t\tsuper('A database address must name a host');\n\t}\n}\n\n/**\n * An address with no database name.\n *\n * Postgres silently falls back to the connecting role's name, so the app\n * connects successfully to the wrong database and fails later with confusing\n * \"relation does not exist\" errors. Rejecting it here is much cheaper.\n */\nexport class MissingDatabaseName extends DatabaseAddressError {\n\tconstructor() {\n\t\tsuper('A database address must name a database');\n\t}\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;AAyBA,SAAgB,kBAAkBA,KAAqB;AACtD,KAAI;EACH,MAAM,SAAS,IAAI,IAAI;AACvB,OAAK,OAAO,SAAU,QAAO;AAC7B,SAAO,WAAW;AAClB,SAAO,OAAO,UAAU;CACxB,QAAO;AACP,SAAO;CACP;AACD;;;;;;;AAQD,IAAsB,uBAAtB,cAAmD,MAAM;CACxD,YAAYC,SAAiB;AAC5B,QAAM,QAAQ;AACd,OAAK,OAAO,IAAI,OAAO;CACvB;AACD;;AAGD,IAAa,sBAAb,cAAyC,qBAAqB;CAC7D,cAAc;AACb,QAAM,sCAAsC;CAC5C;AACD;;;;;;;;AASD,IAAa,sBAAb,cAAyC,qBAAqB;CAC7D,cAAc;AACb,QAAM,0CAA0C;CAChD;AACD"}
|
package/dist/errors-Cs5jlAv-.cjs
DELETED
|
@@ -1,93 +0,0 @@
|
|
|
1
|
-
|
|
2
|
-
//#region src/errors.ts
|
|
3
|
-
/**
|
|
4
|
-
* Database URL errors and redaction — engine-neutral.
|
|
5
|
-
*
|
|
6
|
-
* Nothing here is Postgres-specific: every engine addresses itself as a URL
|
|
7
|
-
* carrying a password, and "must name a host" holds for all of them. The parts
|
|
8
|
-
* that differ — libpq's `options=-c search_path=…`, which no other engine
|
|
9
|
-
* accepts — live under the driver they belong to.
|
|
10
|
-
*
|
|
11
|
-
* Messages state the rule, which is constant; the offending value is a field.
|
|
12
|
-
* An interpolated message cannot be matched on and carries user input into
|
|
13
|
-
* every log line that touches it.
|
|
14
|
-
*/
|
|
15
|
-
/**
|
|
16
|
-
* Replace the password in a connection string with `***`.
|
|
17
|
-
*
|
|
18
|
-
* A connection string is a secret, and the places it is most likely to be
|
|
19
|
-
* written down — a log line, an error, a crash report shipped to a third party
|
|
20
|
-
* — are the places nobody is reading carefully. This exists so that redacting
|
|
21
|
-
* is the easy thing to do at each of them.
|
|
22
|
-
*
|
|
23
|
-
* Safe on input that is not a URL: it returns a constant rather than throwing,
|
|
24
|
-
* because this runs on paths that must not fail. Anything unparseable is
|
|
25
|
-
* treated as potentially secret and withheld entirely rather than echoed.
|
|
26
|
-
*/
|
|
27
|
-
function redactDatabaseUrl(url) {
|
|
28
|
-
try {
|
|
29
|
-
const parsed = new URL(url);
|
|
30
|
-
if (!parsed.password) return url;
|
|
31
|
-
parsed.password = "***";
|
|
32
|
-
return parsed.toString();
|
|
33
|
-
} catch {
|
|
34
|
-
return "<unparseable url>";
|
|
35
|
-
}
|
|
36
|
-
}
|
|
37
|
-
/**
|
|
38
|
-
* Base for an address that cannot become a connection string.
|
|
39
|
-
*
|
|
40
|
-
* Deliberately carries no URL field: these are thrown while *composing* one, so
|
|
41
|
-
* there is no URL yet — only the parts, which include the password.
|
|
42
|
-
*/
|
|
43
|
-
var DatabaseAddressError = class extends Error {
|
|
44
|
-
constructor(message) {
|
|
45
|
-
super(message);
|
|
46
|
-
this.name = new.target.name;
|
|
47
|
-
}
|
|
48
|
-
};
|
|
49
|
-
/** An address with no host to connect to. */
|
|
50
|
-
var MissingDatabaseHost = class extends DatabaseAddressError {
|
|
51
|
-
constructor() {
|
|
52
|
-
super("A database address must name a host");
|
|
53
|
-
}
|
|
54
|
-
};
|
|
55
|
-
/**
|
|
56
|
-
* An address with no database name.
|
|
57
|
-
*
|
|
58
|
-
* Postgres silently falls back to the connecting role's name, so the app
|
|
59
|
-
* connects successfully to the wrong database and fails later with confusing
|
|
60
|
-
* "relation does not exist" errors. Rejecting it here is much cheaper.
|
|
61
|
-
*/
|
|
62
|
-
var MissingDatabaseName = class extends DatabaseAddressError {
|
|
63
|
-
constructor() {
|
|
64
|
-
super("A database address must name a database");
|
|
65
|
-
}
|
|
66
|
-
};
|
|
67
|
-
|
|
68
|
-
//#endregion
|
|
69
|
-
Object.defineProperty(exports, 'DatabaseAddressError', {
|
|
70
|
-
enumerable: true,
|
|
71
|
-
get: function () {
|
|
72
|
-
return DatabaseAddressError;
|
|
73
|
-
}
|
|
74
|
-
});
|
|
75
|
-
Object.defineProperty(exports, 'MissingDatabaseHost', {
|
|
76
|
-
enumerable: true,
|
|
77
|
-
get: function () {
|
|
78
|
-
return MissingDatabaseHost;
|
|
79
|
-
}
|
|
80
|
-
});
|
|
81
|
-
Object.defineProperty(exports, 'MissingDatabaseName', {
|
|
82
|
-
enumerable: true,
|
|
83
|
-
get: function () {
|
|
84
|
-
return MissingDatabaseName;
|
|
85
|
-
}
|
|
86
|
-
});
|
|
87
|
-
Object.defineProperty(exports, 'redactDatabaseUrl', {
|
|
88
|
-
enumerable: true,
|
|
89
|
-
get: function () {
|
|
90
|
-
return redactDatabaseUrl;
|
|
91
|
-
}
|
|
92
|
-
});
|
|
93
|
-
//# sourceMappingURL=errors-Cs5jlAv-.cjs.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"errors-Cs5jlAv-.cjs","names":["url: string","message: string"],"sources":["../src/errors.ts"],"sourcesContent":["/**\n * Database URL errors and redaction — engine-neutral.\n *\n * Nothing here is Postgres-specific: every engine addresses itself as a URL\n * carrying a password, and \"must name a host\" holds for all of them. The parts\n * that differ — libpq's `options=-c search_path=…`, which no other engine\n * accepts — live under the driver they belong to.\n *\n * Messages state the rule, which is constant; the offending value is a field.\n * An interpolated message cannot be matched on and carries user input into\n * every log line that touches it.\n */\n\n/**\n * Replace the password in a connection string with `***`.\n *\n * A connection string is a secret, and the places it is most likely to be\n * written down — a log line, an error, a crash report shipped to a third party\n * — are the places nobody is reading carefully. This exists so that redacting\n * is the easy thing to do at each of them.\n *\n * Safe on input that is not a URL: it returns a constant rather than throwing,\n * because this runs on paths that must not fail. Anything unparseable is\n * treated as potentially secret and withheld entirely rather than echoed.\n */\nexport function redactDatabaseUrl(url: string): string {\n\ttry {\n\t\tconst parsed = new URL(url);\n\t\tif (!parsed.password) return url;\n\t\tparsed.password = '***';\n\t\treturn parsed.toString();\n\t} catch {\n\t\treturn '<unparseable url>';\n\t}\n}\n\n/**\n * Base for an address that cannot become a connection string.\n *\n * Deliberately carries no URL field: these are thrown while *composing* one, so\n * there is no URL yet — only the parts, which include the password.\n */\nexport abstract class DatabaseAddressError extends Error {\n\tconstructor(message: string) {\n\t\tsuper(message);\n\t\tthis.name = new.target.name;\n\t}\n}\n\n/** An address with no host to connect to. */\nexport class MissingDatabaseHost extends DatabaseAddressError {\n\tconstructor() {\n\t\tsuper('A database address must name a host');\n\t}\n}\n\n/**\n * An address with no database name.\n *\n * Postgres silently falls back to the connecting role's name, so the app\n * connects successfully to the wrong database and fails later with confusing\n * \"relation does not exist\" errors. Rejecting it here is much cheaper.\n */\nexport class MissingDatabaseName extends DatabaseAddressError {\n\tconstructor() {\n\t\tsuper('A database address must name a database');\n\t}\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;AAyBA,SAAgB,kBAAkBA,KAAqB;AACtD,KAAI;EACH,MAAM,SAAS,IAAI,IAAI;AACvB,OAAK,OAAO,SAAU,QAAO;AAC7B,SAAO,WAAW;AAClB,SAAO,OAAO,UAAU;CACxB,QAAO;AACP,SAAO;CACP;AACD;;;;;;;AAQD,IAAsB,uBAAtB,cAAmD,MAAM;CACxD,YAAYC,SAAiB;AAC5B,QAAM,QAAQ;AACd,OAAK,OAAO,IAAI,OAAO;CACvB;AACD;;AAGD,IAAa,sBAAb,cAAyC,qBAAqB;CAC7D,cAAc;AACb,QAAM,sCAAsC;CAC5C;AACD;;;;;;;;AASD,IAAa,sBAAb,cAAyC,qBAAqB;CAC7D,cAAc;AACb,QAAM,0CAA0C;CAChD;AACD"}
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
import { ControlledTransaction, IsolationLevel, Kysely, Transaction } from "kysely";
|
|
2
|
-
|
|
3
|
-
//#region src/kysely.d.ts
|
|
4
|
-
interface TransactionSettings {
|
|
5
|
-
isolationLevel?: IsolationLevel;
|
|
6
|
-
}
|
|
7
|
-
declare function withTransaction<DB, T>(db: DatabaseConnection<DB>, cb: (trx: Transaction<DB>) => Promise<T>, settings?: TransactionSettings): Promise<T>;
|
|
8
|
-
type DatabaseConnection<T> = ControlledTransaction<T> | Kysely<T> | Transaction<T>;
|
|
9
|
-
//# sourceMappingURL=kysely.d.ts.map
|
|
10
|
-
|
|
11
|
-
//#endregion
|
|
12
|
-
export { DatabaseConnection, TransactionSettings, withTransaction };
|
|
13
|
-
//# sourceMappingURL=kysely-BAedYsvn.d.mts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"kysely-BAedYsvn.d.mts","names":[],"sources":["../src/kysely.ts"],"sourcesContent":[],"mappings":";;;UAOiB,mBAAA;mBACC;AADlB;AAIgB,iBAAA,eAAe,CAAA,EAAA,EAAA,CAAA,CAAA,CAAA,EAAA,EAC1B,kBAD0B,CACP,EADO,CAAA,EAAA,EAAA,EAAA,CAAA,GAAA,EAEpB,WAFoB,CAER,EAFQ,CAAA,EAAA,GAEA,OAFA,CAEQ,CAFR,CAAA,EAAA,QAAA,CAAA,EAGnB,mBAHmB,CAAA,EAI5B,OAJ4B,CAIpB,CAJoB,CAAA;AAAA,KAkBnB,kBAlBmB,CAAA,CAAA,CAAA,GAmB5B,qBAnB4B,CAmBN,CAnBM,CAAA,GAoB5B,MApB4B,CAoBrB,CApBqB,CAAA,GAqB5B,WArB4B,CAqBhB,CArBgB,CAAA"}
|
package/dist/kysely-Bo_Zg-D3.mjs
DELETED
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
//#region src/kysely.ts
|
|
2
|
-
function withTransaction(db, cb, settings) {
|
|
3
|
-
if (db.isTransaction) return cb(db);
|
|
4
|
-
const builder = db.transaction();
|
|
5
|
-
if (settings?.isolationLevel) return builder.setIsolationLevel(settings.isolationLevel).execute(cb);
|
|
6
|
-
return builder.execute(cb);
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
//#endregion
|
|
10
|
-
export { withTransaction };
|
|
11
|
-
//# sourceMappingURL=kysely-Bo_Zg-D3.mjs.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"kysely-Bo_Zg-D3.mjs","names":["db: DatabaseConnection<DB>","cb: (trx: Transaction<DB>) => Promise<T>","settings?: TransactionSettings"],"sources":["../src/kysely.ts"],"sourcesContent":["import type {\n\tControlledTransaction,\n\tIsolationLevel,\n\tKysely,\n\tTransaction,\n} from 'kysely';\n\nexport interface TransactionSettings {\n\tisolationLevel?: IsolationLevel;\n}\n\nexport function withTransaction<DB, T>(\n\tdb: DatabaseConnection<DB>,\n\tcb: (trx: Transaction<DB>) => Promise<T>,\n\tsettings?: TransactionSettings,\n): Promise<T> {\n\tif (db.isTransaction) {\n\t\treturn cb(db as Transaction<DB>);\n\t}\n\n\tconst builder = db.transaction();\n\n\tif (settings?.isolationLevel) {\n\t\treturn builder.setIsolationLevel(settings.isolationLevel).execute(cb);\n\t}\n\n\treturn builder.execute(cb);\n}\n\nexport type DatabaseConnection<T> =\n\t| ControlledTransaction<T>\n\t| Kysely<T>\n\t| Transaction<T>;\n"],"mappings":";AAWA,SAAgB,gBACfA,IACAC,IACAC,UACa;AACb,KAAI,GAAG,cACN,QAAO,GAAG,GAAsB;CAGjC,MAAM,UAAU,GAAG,aAAa;AAEhC,KAAI,UAAU,eACb,QAAO,QAAQ,kBAAkB,SAAS,eAAe,CAAC,QAAQ,GAAG;AAGtE,QAAO,QAAQ,QAAQ,GAAG;AAC1B"}
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
import { ControlledTransaction, IsolationLevel, Kysely, Transaction } from "kysely";
|
|
2
|
-
|
|
3
|
-
//#region src/kysely.d.ts
|
|
4
|
-
interface TransactionSettings {
|
|
5
|
-
isolationLevel?: IsolationLevel;
|
|
6
|
-
}
|
|
7
|
-
declare function withTransaction<DB, T>(db: DatabaseConnection<DB>, cb: (trx: Transaction<DB>) => Promise<T>, settings?: TransactionSettings): Promise<T>;
|
|
8
|
-
type DatabaseConnection<T> = ControlledTransaction<T> | Kysely<T> | Transaction<T>;
|
|
9
|
-
//# sourceMappingURL=kysely.d.ts.map
|
|
10
|
-
|
|
11
|
-
//#endregion
|
|
12
|
-
export { DatabaseConnection, TransactionSettings, withTransaction };
|
|
13
|
-
//# sourceMappingURL=kysely-D3eeuId4.d.cts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"kysely-D3eeuId4.d.cts","names":[],"sources":["../src/kysely.ts"],"sourcesContent":[],"mappings":";;;UAOiB,mBAAA;mBACC;AADlB;AAIgB,iBAAA,eAAe,CAAA,EAAA,EAAA,CAAA,CAAA,CAAA,EAAA,EAC1B,kBAD0B,CACP,EADO,CAAA,EAAA,EAAA,EAAA,CAAA,GAAA,EAEpB,WAFoB,CAER,EAFQ,CAAA,EAAA,GAEA,OAFA,CAEQ,CAFR,CAAA,EAAA,QAAA,CAAA,EAGnB,mBAHmB,CAAA,EAI5B,OAJ4B,CAIpB,CAJoB,CAAA;AAAA,KAkBnB,kBAlBmB,CAAA,CAAA,CAAA,GAmB5B,qBAnB4B,CAmBN,CAnBM,CAAA,GAoB5B,MApB4B,CAoBrB,CApBqB,CAAA,GAqB5B,WArB4B,CAqBhB,CArBgB,CAAA"}
|
package/dist/kysely-LWvS2ekY.cjs
DELETED
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
|
|
2
|
-
//#region src/kysely.ts
|
|
3
|
-
function withTransaction(db, cb, settings) {
|
|
4
|
-
if (db.isTransaction) return cb(db);
|
|
5
|
-
const builder = db.transaction();
|
|
6
|
-
if (settings?.isolationLevel) return builder.setIsolationLevel(settings.isolationLevel).execute(cb);
|
|
7
|
-
return builder.execute(cb);
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
//#endregion
|
|
11
|
-
Object.defineProperty(exports, 'withTransaction', {
|
|
12
|
-
enumerable: true,
|
|
13
|
-
get: function () {
|
|
14
|
-
return withTransaction;
|
|
15
|
-
}
|
|
16
|
-
});
|
|
17
|
-
//# sourceMappingURL=kysely-LWvS2ekY.cjs.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"kysely-LWvS2ekY.cjs","names":["db: DatabaseConnection<DB>","cb: (trx: Transaction<DB>) => Promise<T>","settings?: TransactionSettings"],"sources":["../src/kysely.ts"],"sourcesContent":["import type {\n\tControlledTransaction,\n\tIsolationLevel,\n\tKysely,\n\tTransaction,\n} from 'kysely';\n\nexport interface TransactionSettings {\n\tisolationLevel?: IsolationLevel;\n}\n\nexport function withTransaction<DB, T>(\n\tdb: DatabaseConnection<DB>,\n\tcb: (trx: Transaction<DB>) => Promise<T>,\n\tsettings?: TransactionSettings,\n): Promise<T> {\n\tif (db.isTransaction) {\n\t\treturn cb(db as Transaction<DB>);\n\t}\n\n\tconst builder = db.transaction();\n\n\tif (settings?.isolationLevel) {\n\t\treturn builder.setIsolationLevel(settings.isolationLevel).execute(cb);\n\t}\n\n\treturn builder.execute(cb);\n}\n\nexport type DatabaseConnection<T> =\n\t| ControlledTransaction<T>\n\t| Kysely<T>\n\t| Transaction<T>;\n"],"mappings":";;AAWA,SAAgB,gBACfA,IACAC,IACAC,UACa;AACb,KAAI,GAAG,cACN,QAAO,GAAG,GAAsB;CAGjC,MAAM,UAAU,GAAG,aAAa;AAEhC,KAAI,UAAU,eACb,QAAO,QAAQ,kBAAkB,SAAS,eAAe,CAAC,QAAQ,GAAG;AAGtE,QAAO,QAAQ,QAAQ,GAAG;AAC1B"}
|