durcno 1.0.0-alpha.11 → 1.0.0-alpha.12
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/bin.cjs +54 -5
- package/dist/src/columns/common.d.mts +57 -11
- package/dist/src/columns/common.mjs +68 -14
- package/dist/src/columns/enum.mjs +1 -1
- package/dist/src/constraints/check.d.mts +1 -1
- package/dist/src/constraints/check.mjs +16 -3
- package/dist/src/constraints/primary-key.d.mts +7 -4
- package/dist/src/constraints/primary-key.mjs +7 -4
- package/dist/src/constraints/unique.d.mts +9 -7
- package/dist/src/constraints/unique.mjs +7 -4
- package/dist/src/db.d.mts +2 -2
- package/dist/src/enumtype.d.mts +13 -5
- package/dist/src/enumtype.mjs +18 -16
- package/dist/src/filters/postgis.d.mts +2 -2
- package/dist/src/filters/string.d.mts +2 -2
- package/dist/src/index.d.mts +2 -2
- package/dist/src/index.mjs +2 -2
- package/dist/src/indexes.d.mts +5 -6
- package/dist/src/indexes.mjs +1 -1
- package/dist/src/migration/ddl/enum.d.mts +4 -4
- package/dist/src/migration/ddl/enum.mjs +16 -6
- package/dist/src/migration/ddl/index.d.mts +1 -1
- package/dist/src/migration/ddl/sequence.d.mts +3 -3
- package/dist/src/migration/ddl/sequence.mjs +8 -4
- package/dist/src/migration/ddl/table.d.mts +5 -5
- package/dist/src/migration/ddl/table.mjs +28 -18
- package/dist/src/migration/ddl/types.d.mts +3 -3
- package/dist/src/migration/ddl/types.mjs +14 -6
- package/dist/src/migration/snapshot.d.mts +10 -9
- package/dist/src/migration/snapshot.mjs +21 -21
- package/dist/src/query-builders/first.mjs +2 -3
- package/dist/src/query-builders/insert-returning.mjs +2 -3
- package/dist/src/query-builders/insert.mjs +2 -3
- package/dist/src/query-builders/rq.mjs +6 -7
- package/dist/src/query-builders/select.mjs +4 -6
- package/dist/src/query-builders/update.mjs +2 -3
- package/dist/src/sequence.d.mts +13 -5
- package/dist/src/sequence.mjs +21 -19
- package/dist/src/table.d.mts +21 -14
- package/dist/src/table.mjs +5 -1
- package/dist/src/types.d.mts +7 -1
- package/dist/src/utils.mjs +8 -1
- package/package.json +1 -1
package/dist/bin.cjs
CHANGED
|
@@ -10247,6 +10247,7 @@ function formatValue(value) {
|
|
|
10247
10247
|
// src/cli/commands/squash.ts
|
|
10248
10248
|
var import_node_fs4 = require("node:fs");
|
|
10249
10249
|
var import_node_path7 = require("node:path");
|
|
10250
|
+
var import_durcno4 = require("durcno");
|
|
10250
10251
|
var import_migration3 = require("durcno/migration");
|
|
10251
10252
|
var { bgGreen: bgGreen4, bgRed: bgRed2, yellow: yellow7, red: red5, green: green4, cyan: cyan7, gray: gray6 } = source_default;
|
|
10252
10253
|
async function squash(start, end, options) {
|
|
@@ -10286,6 +10287,35 @@ async function squash(start, end, options) {
|
|
|
10286
10287
|
console.log(yellow7("Only one migration in range. Nothing to squash."));
|
|
10287
10288
|
process.exit(0);
|
|
10288
10289
|
}
|
|
10290
|
+
let client = null;
|
|
10291
|
+
let rangeAllApplied = false;
|
|
10292
|
+
if (!options.skipDb) {
|
|
10293
|
+
client = config.connector.getClient();
|
|
10294
|
+
await client.connect();
|
|
10295
|
+
if (await migrationsTableExists(client)) {
|
|
10296
|
+
config.connector.options.pool = {
|
|
10297
|
+
...config.connector.options.pool,
|
|
10298
|
+
max: 1
|
|
10299
|
+
};
|
|
10300
|
+
config.connector.options.logger = void 0;
|
|
10301
|
+
const db = (0, import_durcno4.database)({ Migrations: import_durcno4.Migrations }, config);
|
|
10302
|
+
const records = await db.from(import_durcno4.Migrations).select();
|
|
10303
|
+
await db.close();
|
|
10304
|
+
const appliedNames = new Set(records.map((r) => r.name));
|
|
10305
|
+
const appliedInRange = range.filter((m) => appliedNames.has(m));
|
|
10306
|
+
const unappliedInRange = range.filter((m) => !appliedNames.has(m));
|
|
10307
|
+
if (appliedInRange.length > 0 && unappliedInRange.length > 0) {
|
|
10308
|
+
await client.close();
|
|
10309
|
+
console.error(
|
|
10310
|
+
bgRed2.white("[ERROR]") + " " + red5("Cannot squash a mix of applied and unapplied migrations.") + gray6(`
|
|
10311
|
+
Applied in range: ${appliedInRange.join(", ")}`) + gray6(`
|
|
10312
|
+
Unapplied in range: ${unappliedInRange.join(", ")}`)
|
|
10313
|
+
);
|
|
10314
|
+
process.exit(1);
|
|
10315
|
+
}
|
|
10316
|
+
rangeAllApplied = unappliedInRange.length === 0;
|
|
10317
|
+
}
|
|
10318
|
+
}
|
|
10289
10319
|
let hasCustomStatements = false;
|
|
10290
10320
|
for (const migrationDirName of range) {
|
|
10291
10321
|
const upPath = (0, import_node_path7.join)(migrationsDir, migrationDirName, "up.ts");
|
|
@@ -10346,6 +10376,22 @@ async function squash(start, end, options) {
|
|
|
10346
10376
|
(0, import_node_fs4.mkdirSync)(squashedDir, { recursive: true });
|
|
10347
10377
|
(0, import_node_fs4.writeFileSync)((0, import_node_path7.join)(squashedDir, "up.ts"), squashedUpTs);
|
|
10348
10378
|
(0, import_node_fs4.writeFileSync)((0, import_node_path7.join)(squashedDir, "down.ts"), squashedDownTs);
|
|
10379
|
+
if (client !== null && rangeAllApplied) {
|
|
10380
|
+
config.connector.options.pool = {
|
|
10381
|
+
...config.connector.options.pool,
|
|
10382
|
+
max: 1
|
|
10383
|
+
};
|
|
10384
|
+
config.connector.options.logger = void 0;
|
|
10385
|
+
const db = (0, import_durcno4.database)({ Migrations: import_durcno4.Migrations }, config);
|
|
10386
|
+
for (const migrationName of range) {
|
|
10387
|
+
await db.delete(import_durcno4.Migrations).where((0, import_durcno4.eq)(import_durcno4.Migrations.name, migrationName));
|
|
10388
|
+
}
|
|
10389
|
+
await db.insert(import_durcno4.Migrations).values({ name: start, createdAt: /* @__PURE__ */ new Date() });
|
|
10390
|
+
await db.close();
|
|
10391
|
+
}
|
|
10392
|
+
if (client !== null) {
|
|
10393
|
+
await client.close();
|
|
10394
|
+
}
|
|
10349
10395
|
console.log(
|
|
10350
10396
|
bgGreen4.white.bold("[SQUASHED]") + " " + green4(`${cyan7(String(range.length))} migrations into ${cyan7(start)}.`)
|
|
10351
10397
|
);
|
|
@@ -10354,7 +10400,7 @@ async function squash(start, end, options) {
|
|
|
10354
10400
|
|
|
10355
10401
|
// src/cli/commands/status.ts
|
|
10356
10402
|
var import_node_path8 = require("node:path");
|
|
10357
|
-
var
|
|
10403
|
+
var import_durcno5 = require("durcno");
|
|
10358
10404
|
var { dim: dim4, cyan: cyan8, yellow: yellow8, green: green5 } = source_default;
|
|
10359
10405
|
async function status(options) {
|
|
10360
10406
|
const configPath = resolveConfigPath(options.config);
|
|
@@ -10372,8 +10418,8 @@ async function status(options) {
|
|
|
10372
10418
|
}
|
|
10373
10419
|
connector.options.pool = { ...connector.options.pool, max: 1 };
|
|
10374
10420
|
connector.options.logger = void 0;
|
|
10375
|
-
const db = (0,
|
|
10376
|
-
const migrationsQuery = db.from(
|
|
10421
|
+
const db = (0, import_durcno5.database)({ Migrations: import_durcno5.Migrations }, config);
|
|
10422
|
+
const migrationsQuery = db.from(import_durcno5.Migrations).select();
|
|
10377
10423
|
let migrations;
|
|
10378
10424
|
const client = connector.getClient();
|
|
10379
10425
|
await client.connect();
|
|
@@ -10405,7 +10451,7 @@ async function status(options) {
|
|
|
10405
10451
|
}
|
|
10406
10452
|
|
|
10407
10453
|
// src/cli/index.ts
|
|
10408
|
-
program.version("1.0.0-alpha.
|
|
10454
|
+
program.version("1.0.0-alpha.11");
|
|
10409
10455
|
var Options = {
|
|
10410
10456
|
config: ["--config <path>", "Path to the config file"]
|
|
10411
10457
|
};
|
|
@@ -10430,7 +10476,10 @@ program.command("status").alias("stat").option(...Options.config).description("s
|
|
|
10430
10476
|
program.command("down <migration>").option(...Options.config).description("down a specific migration").action(async (migration, opts) => {
|
|
10431
10477
|
await down(migration, opts);
|
|
10432
10478
|
});
|
|
10433
|
-
program.command("squash <start> <end>").option(...Options.config).option("--force", "Squash even if custom statements exist").
|
|
10479
|
+
program.command("squash <start> <end>").option(...Options.config).option("--force", "Squash even if custom statements exist").option(
|
|
10480
|
+
"--skip-db",
|
|
10481
|
+
"Skip all database interaction (no validation, no tracking update)"
|
|
10482
|
+
).description("squash a range of migrations into a single migration").action(
|
|
10434
10483
|
async (start, end, opts) => {
|
|
10435
10484
|
await squash(start, end, opts);
|
|
10436
10485
|
}
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { entityType } from "../symbols.mjs";
|
|
2
|
-
import {
|
|
3
|
-
import { StdTable, StdTableColumn, TableColumn } from "../table.mjs";
|
|
2
|
+
import { StdTable, StdTableColumn } from "../table.mjs";
|
|
4
3
|
import { Arg } from "../query-builders/pre.mjs";
|
|
5
4
|
import { Query, QueryContext } from "../query-builders/query.mjs";
|
|
6
5
|
import { Sql } from "../sql.mjs";
|
|
@@ -10,19 +9,59 @@ import * as z from "zod";
|
|
|
10
9
|
declare const notNull: true;
|
|
11
10
|
declare const unique: true;
|
|
12
11
|
declare const primaryKey: true;
|
|
12
|
+
/**
|
|
13
|
+
* Represents the dimension configuration for an array column.
|
|
14
|
+
*/
|
|
15
|
+
declare class Dimension<TDims extends readonly (number | null)[]> {
|
|
16
|
+
/** The raw dimension tuple (first = innermost dimension). */
|
|
17
|
+
readonly dims: TDims;
|
|
18
|
+
constructor(dims: TDims);
|
|
19
|
+
/**
|
|
20
|
+
* Appends a variable-length (unbounded) outer dimension.
|
|
21
|
+
* SQL equivalent: `type[]`
|
|
22
|
+
*/
|
|
23
|
+
array(): Dimension<readonly [...TDims, null]>;
|
|
24
|
+
/**
|
|
25
|
+
* Appends a fixed-length outer dimension of `size` elements.
|
|
26
|
+
* SQL equivalent: `type[N]`
|
|
27
|
+
*/
|
|
28
|
+
tuple<const L extends number>(size: L): Dimension<readonly [...TDims, L]>;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Creates a variable-length (unbounded) 1D array dimension.
|
|
32
|
+
* SQL equivalent: `type[]`
|
|
33
|
+
*
|
|
34
|
+
* @example
|
|
35
|
+
* ```typescript
|
|
36
|
+
* tags: varchar({ length: 50, dimension: array() })
|
|
37
|
+
* ```
|
|
38
|
+
*/
|
|
39
|
+
declare function array(): Dimension<readonly [null]>;
|
|
40
|
+
/**
|
|
41
|
+
* Creates a fixed-length 1D array dimension of `size` elements.
|
|
42
|
+
* SQL equivalent: `type[N]`
|
|
43
|
+
*
|
|
44
|
+
* @example
|
|
45
|
+
* ```typescript
|
|
46
|
+
* coordinates: integer({ dimension: tuple(3) })
|
|
47
|
+
* ```
|
|
48
|
+
*/
|
|
49
|
+
declare function tuple<const L extends number>(size: L): Dimension<readonly [L]>;
|
|
13
50
|
type Tuple<T, L extends number, Acc extends T[] = []> = Acc["length"] extends L ? Acc : Tuple<T, L, [...Acc, T]>;
|
|
14
51
|
type MultiDimValueArray<T, D extends readonly (number | null)[]> = D extends readonly [infer First, ...infer Rest] ? First extends number ? Rest extends readonly (number | null)[] ? MultiDimValueArray<Tuple<T, First>, Rest> : never : First extends null ? Rest extends readonly (number | null)[] ? MultiDimValueArray<T[], Rest> : never : never : T;
|
|
15
52
|
type GetValueArray<T, TConfig> = TConfig extends {
|
|
16
|
-
dimension: infer
|
|
17
|
-
} ?
|
|
53
|
+
dimension: Dimension<infer Dims>;
|
|
54
|
+
} ? Dims extends readonly (number | null)[] ? MultiDimValueArray<T, Dims> : T : T;
|
|
18
55
|
type MultiDimZodTypeArray<T extends z.ZodType, D extends readonly (number | null)[]> = D extends readonly [infer First, ...infer Rest] ? First extends number ? Rest extends readonly (number | null)[] ? MultiDimZodTypeArray<z.ZodTuple<Tuple<T, First>, null>, Rest> : never : First extends null ? Rest extends readonly (number | null)[] ? MultiDimZodTypeArray<z.ZodArray<T>, Rest> : never : never : T;
|
|
19
56
|
type GetZodTypeArray<T extends z.ZodType, TConfig> = TConfig extends {
|
|
20
|
-
dimension: infer
|
|
21
|
-
} ?
|
|
57
|
+
dimension: Dimension<infer Dims>;
|
|
58
|
+
} ? Dims extends readonly (number | null)[] ? MultiDimZodTypeArray<T, Dims> : T : T;
|
|
22
59
|
interface TableLike {
|
|
23
60
|
_: {
|
|
24
61
|
schema: string;
|
|
25
62
|
name: string;
|
|
63
|
+
schemaSql: string;
|
|
64
|
+
nameSql: string;
|
|
26
65
|
};
|
|
27
66
|
}
|
|
28
67
|
declare const OnDeleteActions: readonly ["CASCADE", "SET NULL", "SET DEFAULT", "RESTRICT", "NO ACTION"];
|
|
@@ -42,8 +81,9 @@ type ColumnConfig = {
|
|
|
42
81
|
notNull?: true;
|
|
43
82
|
/**
|
|
44
83
|
* The dimension of the array column.
|
|
84
|
+
* Use the `array()` or `tuple(size)` helpers to define dimensions.
|
|
45
85
|
*/
|
|
46
|
-
dimension?:
|
|
86
|
+
dimension?: Dimension<readonly (number | null)[]>;
|
|
47
87
|
};
|
|
48
88
|
/**
|
|
49
89
|
* Type that augments C with a `hasDefault` property set to true.
|
|
@@ -77,8 +117,8 @@ type HasUpdateFn<C> = C & {
|
|
|
77
117
|
* Supports either a direct column resolver function or an object with
|
|
78
118
|
* a resolver and optional `onDelete` action.
|
|
79
119
|
*/
|
|
80
|
-
type BuildRef<ValType> = (() =>
|
|
81
|
-
column: () =>
|
|
120
|
+
type BuildRef<ValType> = (() => StdTableColumn<Column<any, ValType>>) | {
|
|
121
|
+
column: () => StdTableColumn<Column<any, ValType>>;
|
|
82
122
|
onDelete?: OnDeleteAction;
|
|
83
123
|
};
|
|
84
124
|
/**
|
|
@@ -104,7 +144,9 @@ declare abstract class Column<TConfig extends ColumnConfig, TColVal, TPgType ext
|
|
|
104
144
|
readonly $: {
|
|
105
145
|
/** Phantom discriminant id for this entity kind. */kind: "column"; /** The PostgreSQL type category for this column. */
|
|
106
146
|
PgType: TPgType; /** The TypeScript type for this column's value. */
|
|
107
|
-
TsType: TColVal;
|
|
147
|
+
TsType: TColVal; /** Phantom schema and table references for this column. */
|
|
148
|
+
schema: string | undefined;
|
|
149
|
+
table: string | undefined;
|
|
108
150
|
HasValTypeOverridde: {};
|
|
109
151
|
ValTypeOverride: {};
|
|
110
152
|
};
|
|
@@ -151,6 +193,10 @@ declare abstract class Column<TConfig extends ColumnConfig, TColVal, TPgType ext
|
|
|
151
193
|
get isNotNull(): TConfig extends {
|
|
152
194
|
notNull: true;
|
|
153
195
|
} ? true : false;
|
|
196
|
+
/**
|
|
197
|
+
* Returns the raw dimension tuple from the column config, or `undefined` if not set.
|
|
198
|
+
*/
|
|
199
|
+
get dimensions(): Readonly<[number | null, ...(number | null)[]]> | undefined;
|
|
154
200
|
abstract get sqlTypeScalar(): string;
|
|
155
201
|
get sqlType(): string;
|
|
156
202
|
/** Returns the PostgreSQL cast type for this column's scalar value, or `null` if no cast is needed. */
|
|
@@ -255,4 +301,4 @@ declare abstract class Column<TConfig extends ColumnConfig, TColVal, TPgType ext
|
|
|
255
301
|
arg(): Arg<this["ValType"]>;
|
|
256
302
|
}
|
|
257
303
|
//#endregion
|
|
258
|
-
export { Column, ColumnConfig, GeneratedAlways, GeneratedByDefault, OnDeleteAction, notNull, primaryKey, unique };
|
|
304
|
+
export { Column, ColumnConfig, Dimension, GeneratedAlways, GeneratedByDefault, OnDeleteAction, array, notNull, primaryKey, tuple, unique };
|
|
@@ -9,6 +9,54 @@ const notNull = true;
|
|
|
9
9
|
const unique = true;
|
|
10
10
|
const primaryKey = true;
|
|
11
11
|
const identity = "IDENTITY";
|
|
12
|
+
/**
|
|
13
|
+
* Represents the dimension configuration for an array column.
|
|
14
|
+
*/
|
|
15
|
+
var Dimension = class Dimension {
|
|
16
|
+
/** The raw dimension tuple (first = innermost dimension). */
|
|
17
|
+
dims;
|
|
18
|
+
constructor(dims) {
|
|
19
|
+
this.dims = dims;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Appends a variable-length (unbounded) outer dimension.
|
|
23
|
+
* SQL equivalent: `type[]`
|
|
24
|
+
*/
|
|
25
|
+
array() {
|
|
26
|
+
return new Dimension([...this.dims, null]);
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Appends a fixed-length outer dimension of `size` elements.
|
|
30
|
+
* SQL equivalent: `type[N]`
|
|
31
|
+
*/
|
|
32
|
+
tuple(size) {
|
|
33
|
+
return new Dimension([...this.dims, size]);
|
|
34
|
+
}
|
|
35
|
+
};
|
|
36
|
+
/**
|
|
37
|
+
* Creates a variable-length (unbounded) 1D array dimension.
|
|
38
|
+
* SQL equivalent: `type[]`
|
|
39
|
+
*
|
|
40
|
+
* @example
|
|
41
|
+
* ```typescript
|
|
42
|
+
* tags: varchar({ length: 50, dimension: array() })
|
|
43
|
+
* ```
|
|
44
|
+
*/
|
|
45
|
+
function array() {
|
|
46
|
+
return new Dimension([null]);
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Creates a fixed-length 1D array dimension of `size` elements.
|
|
50
|
+
* SQL equivalent: `type[N]`
|
|
51
|
+
*
|
|
52
|
+
* @example
|
|
53
|
+
* ```typescript
|
|
54
|
+
* coordinates: integer({ dimension: tuple(3) })
|
|
55
|
+
* ```
|
|
56
|
+
*/
|
|
57
|
+
function tuple(size) {
|
|
58
|
+
return new Dimension([size]);
|
|
59
|
+
}
|
|
12
60
|
var Column = class {
|
|
13
61
|
static [entityType] = "Column";
|
|
14
62
|
config;
|
|
@@ -62,22 +110,28 @@ var Column = class {
|
|
|
62
110
|
get isNotNull() {
|
|
63
111
|
return this.#notNull;
|
|
64
112
|
}
|
|
113
|
+
/**
|
|
114
|
+
* Returns the raw dimension tuple from the column config, or `undefined` if not set.
|
|
115
|
+
*/
|
|
116
|
+
get dimensions() {
|
|
117
|
+
return this.config.dimension?.dims;
|
|
118
|
+
}
|
|
65
119
|
get sqlType() {
|
|
66
120
|
const base = this.sqlTypeScalar;
|
|
67
|
-
if (!this.
|
|
68
|
-
return `${base}${this.
|
|
121
|
+
if (!this.dimensions) return base;
|
|
122
|
+
return `${base}${this.dimensions.map((d) => d === null ? "[]" : `[${d}]`).join("")}`;
|
|
69
123
|
}
|
|
70
124
|
/** Returns the full PostgreSQL cast type including array dimensions, or `null` if no cast is needed. */
|
|
71
125
|
get sqlCast() {
|
|
72
126
|
const base = this.sqlCastScalar;
|
|
73
127
|
if (base === null) return null;
|
|
74
|
-
if (!this.
|
|
75
|
-
return `${base}${this.
|
|
128
|
+
if (!this.dimensions) return base;
|
|
129
|
+
return `${base}${this.dimensions.map((d) => d === null ? "[]" : `[${d}]`).join("")}`;
|
|
76
130
|
}
|
|
77
131
|
get zodType() {
|
|
78
132
|
let schema = this.zodTypeScaler;
|
|
79
|
-
if (!this.
|
|
80
|
-
for (const dim of this.
|
|
133
|
+
if (!this.dimensions) return schema;
|
|
134
|
+
for (const dim of this.dimensions) if (typeof dim === "number") schema = z.tuple(Array.from({ length: dim }, () => schema));
|
|
81
135
|
else schema = z.array(schema);
|
|
82
136
|
return schema;
|
|
83
137
|
}
|
|
@@ -86,7 +140,7 @@ var Column = class {
|
|
|
86
140
|
* @returns string `"table"."column"`
|
|
87
141
|
*/
|
|
88
142
|
get fullName() {
|
|
89
|
-
return `"${this.table?._.
|
|
143
|
+
return `"${this.table?._.nameSql}"."${this.nameSql}"`;
|
|
90
144
|
}
|
|
91
145
|
toQuery(query, ctx) {
|
|
92
146
|
const alias = ctx?.tableAliases?.get(`${this.table?._.schema}.${this.table?._.name}`);
|
|
@@ -101,14 +155,14 @@ var Column = class {
|
|
|
101
155
|
toDriver(value) {
|
|
102
156
|
if (value === null) return null;
|
|
103
157
|
if (value instanceof Sql) return value.string;
|
|
104
|
-
if (!this.
|
|
158
|
+
if (!this.dimensions) return this.toDriverScalar(value);
|
|
105
159
|
return value.map((item) => this.#toDriverArrayElement(item, 0));
|
|
106
160
|
}
|
|
107
161
|
/**
|
|
108
162
|
* Helper to recursively process multi-dimensional arrays for toDriver.
|
|
109
163
|
*/
|
|
110
164
|
#toDriverArrayElement(value, dimIndex) {
|
|
111
|
-
if (dimIndex >= this.
|
|
165
|
+
if (dimIndex >= this.dimensions.length - 1) return this.toDriverScalar(value);
|
|
112
166
|
return value.map((item) => this.#toDriverArrayElement(item, dimIndex + 1));
|
|
113
167
|
}
|
|
114
168
|
/**
|
|
@@ -118,7 +172,7 @@ var Column = class {
|
|
|
118
172
|
toSQL(value, options) {
|
|
119
173
|
if (value === null) return "NULL";
|
|
120
174
|
if (value instanceof Sql) return value.string;
|
|
121
|
-
if (!this.
|
|
175
|
+
if (!this.dimensions) {
|
|
122
176
|
if (!options?.cast || !this.sqlCastScalar) return this.toSQLScalar(value);
|
|
123
177
|
return `${this.toSQLScalar(value)}::${this.sqlCastScalar}`;
|
|
124
178
|
}
|
|
@@ -128,7 +182,7 @@ var Column = class {
|
|
|
128
182
|
* Helper to recursively process multi-dimensional arrays for toSQL.
|
|
129
183
|
*/
|
|
130
184
|
#toSQLArray(arr, dimIndex, options) {
|
|
131
|
-
const dimensions = this.
|
|
185
|
+
const dimensions = this.dimensions;
|
|
132
186
|
if (arr.length === 0) return "'{}'";
|
|
133
187
|
if (dimIndex >= dimensions.length - 1) return `ARRAY[${arr.map((item) => {
|
|
134
188
|
if (!options?.cast || !this.sqlCastScalar) return this.toSQLScalar(item);
|
|
@@ -142,7 +196,7 @@ var Column = class {
|
|
|
142
196
|
*/
|
|
143
197
|
fromDriver(value) {
|
|
144
198
|
if (value === null) return null;
|
|
145
|
-
if (!this.
|
|
199
|
+
if (!this.dimensions) return this.fromDriverScalar(value);
|
|
146
200
|
let arr;
|
|
147
201
|
if (typeof value === "string") arr = this.#parsePostgresArrayString(value);
|
|
148
202
|
else arr = value;
|
|
@@ -191,7 +245,7 @@ var Column = class {
|
|
|
191
245
|
* Helper to recursively process multi-dimensional arrays for fromDriver.
|
|
192
246
|
*/
|
|
193
247
|
#fromDriverArray(arr, dimIndex) {
|
|
194
|
-
if (dimIndex >= this.
|
|
248
|
+
if (dimIndex >= this.dimensions.length - 1) return arr.map((item) => this.fromDriverScalar(item));
|
|
195
249
|
return arr.map((item) => this.#fromDriverArray(item, dimIndex + 1));
|
|
196
250
|
}
|
|
197
251
|
/**
|
|
@@ -325,4 +379,4 @@ var Column = class {
|
|
|
325
379
|
}
|
|
326
380
|
};
|
|
327
381
|
//#endregion
|
|
328
|
-
export { Column, identity, notNull, primaryKey, unique };
|
|
382
|
+
export { Column, Dimension, array, identity, notNull, primaryKey, tuple, unique };
|
|
@@ -10,7 +10,7 @@ var EnumedColumn = class extends Column {
|
|
|
10
10
|
this.#enum = enm;
|
|
11
11
|
}
|
|
12
12
|
get sqlTypeScalar() {
|
|
13
|
-
return `"${this.#enum.
|
|
13
|
+
return `"${this.#enum.schemaSql}"."${this.#enum.nameSql}"`;
|
|
14
14
|
}
|
|
15
15
|
get sqlCastScalar() {
|
|
16
16
|
return this.sqlTypeScalar;
|
|
@@ -13,7 +13,7 @@ type CheckExpression<TScopeColumns extends TableAnyColumn> = Filter<TScopeColumn
|
|
|
13
13
|
declare class Check {
|
|
14
14
|
#private;
|
|
15
15
|
constructor(name: string, expr: AnyFilter | Sql);
|
|
16
|
-
/** Returns the constraint name
|
|
16
|
+
/** Returns the constraint name as-is. */
|
|
17
17
|
getName(): string;
|
|
18
18
|
/**
|
|
19
19
|
* Renders the constraint expression to a SQL string.
|
|
@@ -9,9 +9,9 @@ var Check = class {
|
|
|
9
9
|
this.#name = name;
|
|
10
10
|
this.#expr = expr;
|
|
11
11
|
}
|
|
12
|
-
/** Returns the constraint name
|
|
12
|
+
/** Returns the constraint name as-is. */
|
|
13
13
|
getName() {
|
|
14
|
-
return this.#name
|
|
14
|
+
return this.#name;
|
|
15
15
|
}
|
|
16
16
|
/**
|
|
17
17
|
* Renders the constraint expression to a SQL string.
|
|
@@ -25,7 +25,20 @@ var Check = class {
|
|
|
25
25
|
return query.sql;
|
|
26
26
|
}
|
|
27
27
|
};
|
|
28
|
-
/**
|
|
28
|
+
/**
|
|
29
|
+
* Creates a {@link Check} constraint from a filter expression or raw SQL.
|
|
30
|
+
*
|
|
31
|
+
* Convention: `check_<table>_<col>[_and_<col>]*[_<suffix>]?`
|
|
32
|
+
*
|
|
33
|
+
* @example
|
|
34
|
+
* ```ts
|
|
35
|
+
* table("public", "projects", { name: varchar({ length: 255 }) }, {
|
|
36
|
+
* checkConstraints: (t, check) => [
|
|
37
|
+
* check("check_projects_name_length", gte(sql`char_length(${t.name})`, 1)),
|
|
38
|
+
* ],
|
|
39
|
+
* });
|
|
40
|
+
* ```
|
|
41
|
+
*/
|
|
29
42
|
function check(name, expr) {
|
|
30
43
|
return new Check(name, expr);
|
|
31
44
|
}
|
|
@@ -1,10 +1,11 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { StdTableColumn } from "../table.mjs";
|
|
2
2
|
|
|
3
3
|
//#region src/constraints/primary-key.d.ts
|
|
4
4
|
declare class PrimaryKeyConstraint {
|
|
5
5
|
#private;
|
|
6
6
|
constructor(name: string, columns: StdTableColumn[]);
|
|
7
|
-
|
|
7
|
+
/** Returns the constraint name as-is. */
|
|
8
|
+
getName(): string;
|
|
8
9
|
getColumns(): string[];
|
|
9
10
|
}
|
|
10
11
|
/**
|
|
@@ -14,11 +15,13 @@ declare class PrimaryKeyConstraint {
|
|
|
14
15
|
*
|
|
15
16
|
* This function is passed as the second parameter to the `primaryKeyConstraint` callback.
|
|
16
17
|
*
|
|
18
|
+
* Convention: `pk_<table>`
|
|
19
|
+
*
|
|
17
20
|
* @example
|
|
18
21
|
* ```ts
|
|
19
|
-
* table("public", "
|
|
22
|
+
* table("public", "userRoles", { userId: bigint({}), roleId: bigint({}) }, {
|
|
20
23
|
* primaryKeyConstraint: (t, primaryKey) =>
|
|
21
|
-
* primaryKey("
|
|
24
|
+
* primaryKey("pk_user_roles", [t.userId, t.roleId]),
|
|
22
25
|
* });
|
|
23
26
|
* ```
|
|
24
27
|
*/
|
|
@@ -7,8 +7,9 @@ var PrimaryKeyConstraint = class {
|
|
|
7
7
|
this.#name = name;
|
|
8
8
|
this.#columns = columns;
|
|
9
9
|
}
|
|
10
|
-
|
|
11
|
-
|
|
10
|
+
/** Returns the constraint name as-is. */
|
|
11
|
+
getName() {
|
|
12
|
+
return this.#name;
|
|
12
13
|
}
|
|
13
14
|
getColumns() {
|
|
14
15
|
return this.#columns.map((col) => col.nameSql);
|
|
@@ -21,11 +22,13 @@ var PrimaryKeyConstraint = class {
|
|
|
21
22
|
*
|
|
22
23
|
* This function is passed as the second parameter to the `primaryKeyConstraint` callback.
|
|
23
24
|
*
|
|
25
|
+
* Convention: `pk_<table>`
|
|
26
|
+
*
|
|
24
27
|
* @example
|
|
25
28
|
* ```ts
|
|
26
|
-
* table("public", "
|
|
29
|
+
* table("public", "userRoles", { userId: bigint({}), roleId: bigint({}) }, {
|
|
27
30
|
* primaryKeyConstraint: (t, primaryKey) =>
|
|
28
|
-
* primaryKey("
|
|
31
|
+
* primaryKey("pk_user_roles", [t.userId, t.roleId]),
|
|
29
32
|
* });
|
|
30
33
|
* ```
|
|
31
34
|
*/
|
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { AnyColumn, StdTable, TableColumn } from "../table.mjs";
|
|
1
|
+
import { StdTableColumn } from "../table.mjs";
|
|
3
2
|
|
|
4
3
|
//#region src/constraints/unique.d.ts
|
|
5
4
|
declare class UniqueConstraint {
|
|
6
5
|
#private;
|
|
7
|
-
constructor(name: string, columns:
|
|
8
|
-
|
|
6
|
+
constructor(name: string, columns: StdTableColumn[]);
|
|
7
|
+
/** Returns the constraint name as-is. */
|
|
8
|
+
getName(): string;
|
|
9
9
|
getColumns(): string[];
|
|
10
10
|
}
|
|
11
11
|
/**
|
|
@@ -14,16 +14,18 @@ declare class UniqueConstraint {
|
|
|
14
14
|
*
|
|
15
15
|
* This function is passed as the second parameter to the `uniqueConstraints` callback.
|
|
16
16
|
*
|
|
17
|
+
* Convention: `unique_<table>_<col1>[_and_<col2>]*`
|
|
18
|
+
*
|
|
17
19
|
* @example
|
|
18
20
|
* ```ts
|
|
19
|
-
* table("public", "
|
|
21
|
+
* table("public", "userRoles", { userId: bigint({}), roleId: bigint({}) }, {
|
|
20
22
|
* uniqueConstraints: (t, unique) => [
|
|
21
|
-
* unique("
|
|
23
|
+
* unique("unique_user_roles_user_id_and_role_id", [t.userId, t.roleId]),
|
|
22
24
|
* ],
|
|
23
25
|
* });
|
|
24
26
|
* ```
|
|
25
27
|
*/
|
|
26
|
-
declare function uniqueConstraint(name: string, columns: [
|
|
28
|
+
declare function uniqueConstraint(name: string, columns: [StdTableColumn, StdTableColumn, ...StdTableColumn[]]): UniqueConstraint;
|
|
27
29
|
type UniqueConstraintFn = typeof uniqueConstraint;
|
|
28
30
|
//#endregion
|
|
29
31
|
export { UniqueConstraint, UniqueConstraintFn, uniqueConstraint };
|
|
@@ -7,8 +7,9 @@ var UniqueConstraint = class {
|
|
|
7
7
|
this.#name = name;
|
|
8
8
|
this.#columns = columns;
|
|
9
9
|
}
|
|
10
|
-
|
|
11
|
-
|
|
10
|
+
/** Returns the constraint name as-is. */
|
|
11
|
+
getName() {
|
|
12
|
+
return this.#name;
|
|
12
13
|
}
|
|
13
14
|
getColumns() {
|
|
14
15
|
return this.#columns.map((col) => col.nameSql);
|
|
@@ -20,11 +21,13 @@ var UniqueConstraint = class {
|
|
|
20
21
|
*
|
|
21
22
|
* This function is passed as the second parameter to the `uniqueConstraints` callback.
|
|
22
23
|
*
|
|
24
|
+
* Convention: `unique_<table>_<col1>[_and_<col2>]*`
|
|
25
|
+
*
|
|
23
26
|
* @example
|
|
24
27
|
* ```ts
|
|
25
|
-
* table("public", "
|
|
28
|
+
* table("public", "userRoles", { userId: bigint({}), roleId: bigint({}) }, {
|
|
26
29
|
* uniqueConstraints: (t, unique) => [
|
|
27
|
-
* unique("
|
|
30
|
+
* unique("unique_user_roles_user_id_and_role_id", [t.userId, t.roleId]),
|
|
28
31
|
* ],
|
|
29
32
|
* });
|
|
30
33
|
* ```
|
package/dist/src/db.d.mts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Valueof } from "./types.mjs";
|
|
1
|
+
import { CamelToSnake, Valueof } from "./types.mjs";
|
|
2
2
|
import { AnyColumn, AnyRelations, IsTableWC, Relations, TableWCorNever, TableWithColumns } from "./table.mjs";
|
|
3
3
|
import { SelectBuilder } from "./query-builders/select.mjs";
|
|
4
4
|
import { FilterExpression } from "./filters/index.mjs";
|
|
@@ -148,7 +148,7 @@ declare class Base<TTName extends string, TTables extends Record<TTName, TableWi
|
|
|
148
148
|
* @param table The table to query — must have relations registered via `relations()`.
|
|
149
149
|
* @returns A `RelationQueryBuilder` with `.findMany()` and `.findFirst()` methods.
|
|
150
150
|
*/
|
|
151
|
-
query<UTSchema extends string, UTName extends string, TColumns extends Record<string, AnyColumn>>(table: TableWithColumns<UTSchema, UTName, TColumns>): RelationQueryBuilder<UTSchema, UTName, TColumns, TAllRelations[`"${UTSchema}"."${UTName}"`], TAllRelations>;
|
|
151
|
+
query<UTSchema extends string, UTName extends string, TColumns extends Record<string, AnyColumn>>(table: TableWithColumns<UTSchema, UTName, TColumns>): RelationQueryBuilder<UTSchema, UTName, TColumns, TAllRelations[`"${CamelToSnake<UTSchema>}"."${CamelToSnake<UTName>}"`], TAllRelations>;
|
|
152
152
|
/**
|
|
153
153
|
* Execute a raw SQL query with optional parameter binding and custom result handler.
|
|
154
154
|
* @param query The raw SQL query string with $1, $2, etc. placeholders for parameters
|
package/dist/src/enumtype.d.mts
CHANGED
|
@@ -1,15 +1,23 @@
|
|
|
1
|
+
import { SnakeCase } from "./types.mjs";
|
|
1
2
|
import { entityType } from "./symbols.mjs";
|
|
2
3
|
import { EnumedColumn, EnumedConfig } from "./columns/enum.mjs";
|
|
3
4
|
|
|
4
5
|
//#region src/enumtype.d.ts
|
|
6
|
+
/** Represents a PostgreSQL enum type definition. */
|
|
5
7
|
declare class Enum<U extends string = string, TValues extends Readonly<[U, ...U[]]> = Readonly<[U, ...U[]]>> {
|
|
6
|
-
#private;
|
|
7
8
|
static readonly [entityType] = "Enum";
|
|
8
9
|
readonly TValue: TValues[number];
|
|
10
|
+
/** The raw schema identifier as provided by the user (may be camelCase). */
|
|
11
|
+
readonly schema: string;
|
|
12
|
+
/** The snake_case version of {@link schema} used in generated SQL. */
|
|
13
|
+
readonly schemaSql: SnakeCase;
|
|
14
|
+
/** The raw enum name as provided by the user (may be camelCase). */
|
|
15
|
+
readonly name: string;
|
|
16
|
+
/** The snake_case version of {@link name} used in generated SQL. */
|
|
17
|
+
readonly nameSql: SnakeCase;
|
|
18
|
+
/** The ordered list of allowed enum values. */
|
|
19
|
+
readonly values: TValues;
|
|
9
20
|
constructor(schema: string, name: string, values: TValues);
|
|
10
|
-
get schema(): string;
|
|
11
|
-
get name(): string;
|
|
12
|
-
get values(): TValues;
|
|
13
21
|
enumed<TConfig extends EnumedConfig>(config: TConfig): EnumedColumn<TValues[number], TConfig>;
|
|
14
22
|
}
|
|
15
23
|
/**
|
|
@@ -19,7 +27,7 @@ declare class Enum<U extends string = string, TValues extends Readonly<[U, ...U[
|
|
|
19
27
|
* ```ts
|
|
20
28
|
* import { enumtype } from "durcno";
|
|
21
29
|
*
|
|
22
|
-
* export const UserTypeEnm = enumtype("public", "
|
|
30
|
+
* export const UserTypeEnm = enumtype("public", "userType", ["admin", "user"]);
|
|
23
31
|
* ```
|
|
24
32
|
*/
|
|
25
33
|
declare function enumtype<U extends string, TValues extends Readonly<[U, ...U[]]>>(schema: string, name: string, values: TValues): Enum<string, TValues>;
|
package/dist/src/enumtype.mjs
CHANGED
|
@@ -1,25 +1,27 @@
|
|
|
1
1
|
import { entityType } from "./symbols.mjs";
|
|
2
|
+
import { camelToSnake } from "./utils.mjs";
|
|
2
3
|
import { enumed } from "./columns/enum.mjs";
|
|
3
4
|
//#region src/enumtype.ts
|
|
5
|
+
/** Represents a PostgreSQL enum type definition. */
|
|
4
6
|
var Enum = class {
|
|
5
7
|
static [entityType] = "Enum";
|
|
6
8
|
TValue;
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
9
|
+
/** The raw schema identifier as provided by the user (may be camelCase). */
|
|
10
|
+
schema;
|
|
11
|
+
/** The snake_case version of {@link schema} used in generated SQL. */
|
|
12
|
+
schemaSql;
|
|
13
|
+
/** The raw enum name as provided by the user (may be camelCase). */
|
|
14
|
+
name;
|
|
15
|
+
/** The snake_case version of {@link name} used in generated SQL. */
|
|
16
|
+
nameSql;
|
|
17
|
+
/** The ordered list of allowed enum values. */
|
|
18
|
+
values;
|
|
10
19
|
constructor(schema, name, values) {
|
|
11
|
-
this
|
|
12
|
-
this
|
|
13
|
-
this
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
return this.#schema;
|
|
17
|
-
}
|
|
18
|
-
get name() {
|
|
19
|
-
return this.#name;
|
|
20
|
-
}
|
|
21
|
-
get values() {
|
|
22
|
-
return this.#values;
|
|
20
|
+
this.schema = schema;
|
|
21
|
+
this.schemaSql = camelToSnake(schema);
|
|
22
|
+
this.name = name;
|
|
23
|
+
this.nameSql = camelToSnake(name);
|
|
24
|
+
this.values = values;
|
|
23
25
|
}
|
|
24
26
|
enumed(config) {
|
|
25
27
|
return enumed(this, config);
|
|
@@ -32,7 +34,7 @@ var Enum = class {
|
|
|
32
34
|
* ```ts
|
|
33
35
|
* import { enumtype } from "durcno";
|
|
34
36
|
*
|
|
35
|
-
* export const UserTypeEnm = enumtype("public", "
|
|
37
|
+
* export const UserTypeEnm = enumtype("public", "userType", ["admin", "user"]);
|
|
36
38
|
* ```
|
|
37
39
|
*/
|
|
38
40
|
function enumtype(schema, name, values) {
|