durcno 1.0.0-alpha.11 → 1.0.0-alpha.13

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.
Files changed (58) hide show
  1. package/dist/bin.cjs +54 -5
  2. package/dist/src/columns/common.d.mts +66 -11
  3. package/dist/src/columns/common.mjs +81 -14
  4. package/dist/src/columns/enum.mjs +1 -1
  5. package/dist/src/constraints/check.d.mts +3 -3
  6. package/dist/src/constraints/check.mjs +16 -3
  7. package/dist/src/constraints/primary-key.d.mts +7 -4
  8. package/dist/src/constraints/primary-key.mjs +7 -4
  9. package/dist/src/constraints/unique.d.mts +9 -7
  10. package/dist/src/constraints/unique.mjs +7 -4
  11. package/dist/src/db.d.mts +2 -10
  12. package/dist/src/db.mjs +1 -11
  13. package/dist/src/enumtype.d.mts +13 -5
  14. package/dist/src/enumtype.mjs +18 -16
  15. package/dist/src/filters/array.d.mts +16 -16
  16. package/dist/src/filters/index.d.mts +25 -25
  17. package/dist/src/filters/postgis.d.mts +1 -2
  18. package/dist/src/filters/string.d.mts +1 -2
  19. package/dist/src/functions/aggregate.d.mts +7 -7
  20. package/dist/src/functions/index.d.mts +3 -3
  21. package/dist/src/functions/numeric.d.mts +11 -11
  22. package/dist/src/functions/string.d.mts +17 -17
  23. package/dist/src/index.d.mts +2 -2
  24. package/dist/src/index.mjs +2 -2
  25. package/dist/src/indexes.d.mts +5 -6
  26. package/dist/src/indexes.mjs +1 -1
  27. package/dist/src/migration/ddl/index.d.mts +2 -42
  28. package/dist/src/migration/ddl/index.mjs +1 -44
  29. package/dist/src/migration/ddl/sequence.d.mts +3 -3
  30. package/dist/src/migration/ddl/sequence.mjs +8 -4
  31. package/dist/src/migration/ddl/statement.d.mts +1 -4
  32. package/dist/src/migration/ddl/table.d.mts +5 -5
  33. package/dist/src/migration/ddl/table.mjs +28 -18
  34. package/dist/src/migration/ddl/types.d.mts +3 -3
  35. package/dist/src/migration/ddl/types.mjs +14 -6
  36. package/dist/src/migration/snapshot.d.mts +10 -9
  37. package/dist/src/migration/snapshot.mjs +39 -21
  38. package/dist/src/query-builders/first.mjs +2 -3
  39. package/dist/src/query-builders/insert.d.mts +5 -2
  40. package/dist/src/query-builders/insert.mjs +5 -5
  41. package/dist/src/query-builders/pre.d.mts +10 -3
  42. package/dist/src/query-builders/pre.mjs +11 -2
  43. package/dist/src/query-builders/rq.d.mts +39 -28
  44. package/dist/src/query-builders/rq.mjs +23 -16
  45. package/dist/src/query-builders/select.d.mts +4 -3
  46. package/dist/src/query-builders/select.mjs +16 -8
  47. package/dist/src/query-builders/update.mjs +2 -3
  48. package/dist/src/sequence.d.mts +13 -5
  49. package/dist/src/sequence.mjs +21 -19
  50. package/dist/src/table.d.mts +23 -16
  51. package/dist/src/table.mjs +5 -1
  52. package/dist/src/types.d.mts +7 -1
  53. package/dist/src/utils.mjs +8 -1
  54. package/package.json +2 -2
  55. package/dist/src/migration/ddl/enum.d.mts +0 -100
  56. package/dist/src/migration/ddl/enum.mjs +0 -138
  57. package/dist/src/query-builders/insert-returning.d.mts +0 -15
  58. package/dist/src/query-builders/insert-returning.mjs +0 -38
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 import_durcno4 = require("durcno");
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, import_durcno4.database)({ Migrations: import_durcno4.Migrations }, config);
10376
- const migrationsQuery = db.from(import_durcno4.Migrations).select();
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.10");
10454
+ program.version("1.0.0-alpha.12");
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").description("squash a range of migrations into a single migration").action(
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,7 @@
1
+ import { CheckExpression } from "../constraints/check.mjs";
1
2
  import { entityType } from "../symbols.mjs";
2
- import { Key } from "../types.mjs";
3
- import { StdTable, StdTableColumn, TableColumn } from "../table.mjs";
3
+ import { StdTable, StdTableColumn } from "../table.mjs";
4
+ import { AnyFilter } from "../filters/index.mjs";
4
5
  import { Arg } from "../query-builders/pre.mjs";
5
6
  import { Query, QueryContext } from "../query-builders/query.mjs";
6
7
  import { Sql } from "../sql.mjs";
@@ -10,19 +11,59 @@ import * as z from "zod";
10
11
  declare const notNull: true;
11
12
  declare const unique: true;
12
13
  declare const primaryKey: true;
14
+ /**
15
+ * Represents the dimension configuration for an array column.
16
+ */
17
+ declare class Dimension<TDims extends readonly (number | null)[]> {
18
+ /** The raw dimension tuple (first = innermost dimension). */
19
+ readonly dims: TDims;
20
+ constructor(dims: TDims);
21
+ /**
22
+ * Appends a variable-length (unbounded) outer dimension.
23
+ * SQL equivalent: `type[]`
24
+ */
25
+ array(): Dimension<readonly [...TDims, null]>;
26
+ /**
27
+ * Appends a fixed-length outer dimension of `size` elements.
28
+ * SQL equivalent: `type[N]`
29
+ */
30
+ tuple<const L extends number>(size: L): Dimension<readonly [...TDims, L]>;
31
+ }
32
+ /**
33
+ * Creates a variable-length (unbounded) 1D array dimension.
34
+ * SQL equivalent: `type[]`
35
+ *
36
+ * @example
37
+ * ```typescript
38
+ * tags: varchar({ length: 50, dimension: array() })
39
+ * ```
40
+ */
41
+ declare function array(): Dimension<readonly [null]>;
42
+ /**
43
+ * Creates a fixed-length 1D array dimension of `size` elements.
44
+ * SQL equivalent: `type[N]`
45
+ *
46
+ * @example
47
+ * ```typescript
48
+ * coordinates: integer({ dimension: tuple(3) })
49
+ * ```
50
+ */
51
+ declare function tuple<const L extends number>(size: L): Dimension<readonly [L]>;
13
52
  type Tuple<T, L extends number, Acc extends T[] = []> = Acc["length"] extends L ? Acc : Tuple<T, L, [...Acc, T]>;
14
53
  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
54
  type GetValueArray<T, TConfig> = TConfig extends {
16
- dimension: infer D;
17
- } ? D extends readonly (number | null)[] ? MultiDimValueArray<T, D> : T : T;
55
+ dimension: Dimension<infer Dims>;
56
+ } ? Dims extends readonly (number | null)[] ? MultiDimValueArray<T, Dims> : T : T;
18
57
  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
58
  type GetZodTypeArray<T extends z.ZodType, TConfig> = TConfig extends {
20
- dimension: infer D;
21
- } ? D extends readonly (number | null)[] ? MultiDimZodTypeArray<T, D> : T : T;
59
+ dimension: Dimension<infer Dims>;
60
+ } ? Dims extends readonly (number | null)[] ? MultiDimZodTypeArray<T, Dims> : T : T;
22
61
  interface TableLike {
23
62
  _: {
24
63
  schema: string;
25
64
  name: string;
65
+ schemaSql: string;
66
+ nameSql: string;
26
67
  };
27
68
  }
28
69
  declare const OnDeleteActions: readonly ["CASCADE", "SET NULL", "SET DEFAULT", "RESTRICT", "NO ACTION"];
@@ -42,8 +83,9 @@ type ColumnConfig = {
42
83
  notNull?: true;
43
84
  /**
44
85
  * The dimension of the array column.
86
+ * Use the `array()` or `tuple(size)` helpers to define dimensions.
45
87
  */
46
- dimension?: Readonly<[number | null, ...(number | null)[]]>;
88
+ dimension?: Dimension<readonly (number | null)[]>;
47
89
  };
48
90
  /**
49
91
  * Type that augments C with a `hasDefault` property set to true.
@@ -77,8 +119,8 @@ type HasUpdateFn<C> = C & {
77
119
  * Supports either a direct column resolver function or an object with
78
120
  * a resolver and optional `onDelete` action.
79
121
  */
80
- type BuildRef<ValType> = (() => TableColumn<string, string, Key, Column<any, ValType, any>>) | {
81
- column: () => TableColumn<string, string, Key, Column<any, ValType, any>>;
122
+ type BuildRef<ValType> = (() => StdTableColumn<Column<any, ValType>>) | {
123
+ column: () => StdTableColumn<Column<any, ValType>>;
82
124
  onDelete?: OnDeleteAction;
83
125
  };
84
126
  /**
@@ -104,7 +146,9 @@ declare abstract class Column<TConfig extends ColumnConfig, TColVal, TPgType ext
104
146
  readonly $: {
105
147
  /** Phantom discriminant id for this entity kind. */kind: "column"; /** The PostgreSQL type category for this column. */
106
148
  PgType: TPgType; /** The TypeScript type for this column's value. */
107
- TsType: TColVal;
149
+ TsType: TColVal; /** Phantom schema and table references for this column. */
150
+ schema: string | undefined;
151
+ table: string | undefined;
108
152
  HasValTypeOverridde: {};
109
153
  ValTypeOverride: {};
110
154
  };
@@ -151,6 +195,10 @@ declare abstract class Column<TConfig extends ColumnConfig, TColVal, TPgType ext
151
195
  get isNotNull(): TConfig extends {
152
196
  notNull: true;
153
197
  } ? true : false;
198
+ /**
199
+ * Returns the raw dimension tuple from the column config, or `undefined` if not set.
200
+ */
201
+ get dimensions(): Readonly<[number | null, ...(number | null)[]]> | undefined;
154
202
  abstract get sqlTypeScalar(): string;
155
203
  get sqlType(): string;
156
204
  /** Returns the PostgreSQL cast type for this column's scalar value, or `null` if no cast is needed. */
@@ -227,6 +275,13 @@ declare abstract class Column<TConfig extends ColumnConfig, TColVal, TPgType ext
227
275
  get hasReferences(): boolean;
228
276
  get getReferencesCol(): StdTableColumn | null;
229
277
  get getReferencesOnDelete(): OnDeleteAction | null;
278
+ /**
279
+ * Attaches a column-level CHECK constraint.
280
+ * SQL equivalent: `CONSTRAINT "{table}_{col}_check" CHECK (<expr>)`
281
+ * @param fn - Function receiving the column and returning a filter or SQL expression.
282
+ */
283
+ check(fn: (c: this) => CheckExpression<this>): this;
284
+ get getCheckFn(): ((c: StdTableColumn) => AnyFilter | Sql) | undefined;
230
285
  /**
231
286
  * Sets a function to be called during INSERT queries to generate a value.
232
287
  * @param fn - A function that returns the value to insert
@@ -255,4 +310,4 @@ declare abstract class Column<TConfig extends ColumnConfig, TColVal, TPgType ext
255
310
  arg(): Arg<this["ValType"]>;
256
311
  }
257
312
  //#endregion
258
- export { Column, ColumnConfig, GeneratedAlways, GeneratedByDefault, OnDeleteAction, notNull, primaryKey, unique };
313
+ 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;
@@ -26,6 +74,7 @@ var Column = class {
26
74
  #generated;
27
75
  #generatedAs;
28
76
  #references;
77
+ #check;
29
78
  #name;
30
79
  #nameSql;
31
80
  #table;
@@ -62,22 +111,28 @@ var Column = class {
62
111
  get isNotNull() {
63
112
  return this.#notNull;
64
113
  }
114
+ /**
115
+ * Returns the raw dimension tuple from the column config, or `undefined` if not set.
116
+ */
117
+ get dimensions() {
118
+ return this.config.dimension?.dims;
119
+ }
65
120
  get sqlType() {
66
121
  const base = this.sqlTypeScalar;
67
- if (!this.config.dimension) return base;
68
- return `${base}${this.config.dimension.map((d) => d === null ? "[]" : `[${d}]`).join("")}`;
122
+ if (!this.dimensions) return base;
123
+ return `${base}${this.dimensions.map((d) => d === null ? "[]" : `[${d}]`).join("")}`;
69
124
  }
70
125
  /** Returns the full PostgreSQL cast type including array dimensions, or `null` if no cast is needed. */
71
126
  get sqlCast() {
72
127
  const base = this.sqlCastScalar;
73
128
  if (base === null) return null;
74
- if (!this.config.dimension) return base;
75
- return `${base}${this.config.dimension.map((d) => d === null ? "[]" : `[${d}]`).join("")}`;
129
+ if (!this.dimensions) return base;
130
+ return `${base}${this.dimensions.map((d) => d === null ? "[]" : `[${d}]`).join("")}`;
76
131
  }
77
132
  get zodType() {
78
133
  let schema = this.zodTypeScaler;
79
- if (!this.config.dimension) return schema;
80
- for (const dim of this.config.dimension) if (typeof dim === "number") schema = z.tuple(Array.from({ length: dim }, () => schema));
134
+ if (!this.dimensions) return schema;
135
+ for (const dim of this.dimensions) if (typeof dim === "number") schema = z.tuple(Array.from({ length: dim }, () => schema));
81
136
  else schema = z.array(schema);
82
137
  return schema;
83
138
  }
@@ -86,7 +141,7 @@ var Column = class {
86
141
  * @returns string `"table"."column"`
87
142
  */
88
143
  get fullName() {
89
- return `"${this.table?._.name}"."${this.nameSql}"`;
144
+ return `"${this.table?._.nameSql}"."${this.nameSql}"`;
90
145
  }
91
146
  toQuery(query, ctx) {
92
147
  const alias = ctx?.tableAliases?.get(`${this.table?._.schema}.${this.table?._.name}`);
@@ -101,14 +156,14 @@ var Column = class {
101
156
  toDriver(value) {
102
157
  if (value === null) return null;
103
158
  if (value instanceof Sql) return value.string;
104
- if (!this.config.dimension) return this.toDriverScalar(value);
159
+ if (!this.dimensions) return this.toDriverScalar(value);
105
160
  return value.map((item) => this.#toDriverArrayElement(item, 0));
106
161
  }
107
162
  /**
108
163
  * Helper to recursively process multi-dimensional arrays for toDriver.
109
164
  */
110
165
  #toDriverArrayElement(value, dimIndex) {
111
- if (dimIndex >= this.config.dimension.length - 1) return this.toDriverScalar(value);
166
+ if (dimIndex >= this.dimensions.length - 1) return this.toDriverScalar(value);
112
167
  return value.map((item) => this.#toDriverArrayElement(item, dimIndex + 1));
113
168
  }
114
169
  /**
@@ -118,7 +173,7 @@ var Column = class {
118
173
  toSQL(value, options) {
119
174
  if (value === null) return "NULL";
120
175
  if (value instanceof Sql) return value.string;
121
- if (!this.config.dimension) {
176
+ if (!this.dimensions) {
122
177
  if (!options?.cast || !this.sqlCastScalar) return this.toSQLScalar(value);
123
178
  return `${this.toSQLScalar(value)}::${this.sqlCastScalar}`;
124
179
  }
@@ -128,7 +183,7 @@ var Column = class {
128
183
  * Helper to recursively process multi-dimensional arrays for toSQL.
129
184
  */
130
185
  #toSQLArray(arr, dimIndex, options) {
131
- const dimensions = this.config.dimension;
186
+ const dimensions = this.dimensions;
132
187
  if (arr.length === 0) return "'{}'";
133
188
  if (dimIndex >= dimensions.length - 1) return `ARRAY[${arr.map((item) => {
134
189
  if (!options?.cast || !this.sqlCastScalar) return this.toSQLScalar(item);
@@ -142,7 +197,7 @@ var Column = class {
142
197
  */
143
198
  fromDriver(value) {
144
199
  if (value === null) return null;
145
- if (!this.config.dimension) return this.fromDriverScalar(value);
200
+ if (!this.dimensions) return this.fromDriverScalar(value);
146
201
  let arr;
147
202
  if (typeof value === "string") arr = this.#parsePostgresArrayString(value);
148
203
  else arr = value;
@@ -191,7 +246,7 @@ var Column = class {
191
246
  * Helper to recursively process multi-dimensional arrays for fromDriver.
192
247
  */
193
248
  #fromDriverArray(arr, dimIndex) {
194
- if (dimIndex >= this.config.dimension.length - 1) return arr.map((item) => this.fromDriverScalar(item));
249
+ if (dimIndex >= this.dimensions.length - 1) return arr.map((item) => this.fromDriverScalar(item));
195
250
  return arr.map((item) => this.#fromDriverArray(item, dimIndex + 1));
196
251
  }
197
252
  /**
@@ -280,6 +335,18 @@ var Column = class {
280
335
  return this.#references ? this.#references.onDelete : null;
281
336
  }
282
337
  /**
338
+ * Attaches a column-level CHECK constraint.
339
+ * SQL equivalent: `CONSTRAINT "{table}_{col}_check" CHECK (<expr>)`
340
+ * @param fn - Function receiving the column and returning a filter or SQL expression.
341
+ */
342
+ check(fn) {
343
+ this.#check = fn;
344
+ return this;
345
+ }
346
+ get getCheckFn() {
347
+ return this.#check;
348
+ }
349
+ /**
283
350
  * Sets a function to be called during INSERT queries to generate a value.
284
351
  * @param fn - A function that returns the value to insert
285
352
  * @returns HasInsertFn<this>
@@ -325,4 +392,4 @@ var Column = class {
325
392
  }
326
393
  };
327
394
  //#endregion
328
- export { Column, identity, notNull, primaryKey, unique };
395
+ 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.schema}"."${this.#enum.name}"`;
13
+ return `"${this.#enum.schemaSql}"."${this.#enum.nameSql}"`;
14
14
  }
15
15
  get sqlCastScalar() {
16
16
  return this.sqlTypeScalar;
@@ -1,4 +1,4 @@
1
- import { TableAnyColumn } from "../table.mjs";
1
+ import { AnyColumn, TableAnyColumn } from "../table.mjs";
2
2
  import { AnyFilter, Filter } from "../filters/index.mjs";
3
3
  import { QueryContext } from "../query-builders/query.mjs";
4
4
  import { Sql } from "../sql.mjs";
@@ -8,12 +8,12 @@ import { Sql } from "../sql.mjs";
8
8
  * A check constraint expression that can be a filter condition or a raw SQL snippet.
9
9
  * Used in `checkConstraints` table extra to define `CHECK` constraints.
10
10
  */
11
- type CheckExpression<TScopeColumns extends TableAnyColumn> = Filter<TScopeColumns, false> | Sql;
11
+ type CheckExpression<TScopeColumns extends TableAnyColumn | AnyColumn> = Filter<TScopeColumns, false> | Sql;
12
12
  /** A CHECK constraint for a table, storing its name and filter/SQL expression. */
13
13
  declare class Check {
14
14
  #private;
15
15
  constructor(name: string, expr: AnyFilter | Sql);
16
- /** Returns the constraint name, appending `_check` suffix if not already present. */
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, appending `_check` suffix if not already present. */
12
+ /** Returns the constraint name as-is. */
13
13
  getName() {
14
- return this.#name.includes("check") ? this.#name : `${this.#name}_check`;
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
- /** Creates a {@link Check} constraint from a filter expression or raw SQL. */
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(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 { StdTable, StdTableColumn } from "../table.mjs";
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
- getName(table: StdTable): string;
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", "user_roles", { userId: bigint({}), roleId: bigint({}) }, {
22
+ * table("public", "userRoles", { userId: bigint({}), roleId: bigint({}) }, {
20
23
  * primaryKeyConstraint: (t, primaryKey) =>
21
- * primaryKey("pk", [t.userId, t.roleId]),
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
- getName(table) {
11
- return this.#name.startsWith(`${table._.name}_`) ? this.#name : `${table._.name}_${this.#name}`;
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", "user_roles", { userId: bigint({}), roleId: bigint({}) }, {
29
+ * table("public", "userRoles", { userId: bigint({}), roleId: bigint({}) }, {
27
30
  * primaryKeyConstraint: (t, primaryKey) =>
28
- * primaryKey("pk", [t.userId, t.roleId]),
31
+ * primaryKey("pk_user_roles", [t.userId, t.roleId]),
29
32
  * });
30
33
  * ```
31
34
  */
@@ -1,11 +1,11 @@
1
- import { Key } from "../types.mjs";
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: TableColumn<string, string, Key, AnyColumn>[]);
8
- getName(table: StdTable): string;
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", "user_roles", { userId: bigint({}), roleId: bigint({}) }, {
21
+ * table("public", "userRoles", { userId: bigint({}), roleId: bigint({}) }, {
20
22
  * uniqueConstraints: (t, unique) => [
21
- * unique("unique_user_role", [t.userId, t.roleId]),
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: [TableColumn<string, string, Key, AnyColumn>, TableColumn<string, string, Key, AnyColumn>, ...TableColumn<string, string, Key, AnyColumn>[]]): UniqueConstraint;
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
- getName(table) {
11
- return this.#name.startsWith(`${table._.name}_`) ? this.#name : `${table._.name}_${this.#name}`;
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", "user_roles", { userId: bigint({}), roleId: bigint({}) }, {
28
+ * table("public", "userRoles", { userId: bigint({}), roleId: bigint({}) }, {
26
29
  * uniqueConstraints: (t, unique) => [
27
- * unique("unique_user_role", [t.userId, t.roleId]),
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";
@@ -10,7 +10,6 @@ import { DistinctQuery } from "./query-builders/distinct.mjs";
10
10
  import { ExistsQuery } from "./query-builders/exists.mjs";
11
11
  import { FirstQuery } from "./query-builders/first.mjs";
12
12
  import { InsertBuilder } from "./query-builders/insert.mjs";
13
- import { InsertReturningQuery } from "./query-builders/insert-returning.mjs";
14
13
  import { RawQuery } from "./query-builders/raw.mjs";
15
14
  import { RelationQueryBuilder } from "./query-builders/rq.mjs";
16
15
  import { UpdateBuilder } from "./query-builders/update.mjs";
@@ -124,13 +123,6 @@ declare class Base<TTName extends string, TTables extends Record<TTName, TableWi
124
123
  */
125
124
  $distinct<TTable extends TTables[keyof TTables], TColumn extends Valueof<TTable["_"]["columns"]>>(table: TTable, column: TColumn): DistinctQuery<TTable, TColumn, TColumn["ValTypeSelect"][], TPrepare>;
126
125
  $distinct<TTable extends TTables[keyof TTables], TColumn extends Valueof<TTable["_"]["columns"]>, TWhere extends FilterExpression<Valueof<TTable["_"]["columns"]>, TPrepare>>(table: TTable, column: TColumn, where: TWhere): DistinctQuery<TTable, TColumn, TColumn["ValTypeSelect"][], TPrepare>;
127
- /**
128
- * Insert a row and return the inserted row with all columns.
129
- * @param table The table to insert into
130
- * @param values The values to insert
131
- * @returns Promise<T> - the inserted row with all columns including generated values
132
- */
133
- $insertReturning<TTable extends TTables[keyof TTables]>(table: TTable, values: { [colName in keyof TTable["_"]["columns"] as TTable["_"]["columns"][colName]["ValTypeInsert"] extends never ? never : undefined extends TTable["_"]["columns"][colName]["ValTypeInsert"] ? never : colName]: TTable["_"]["columns"][colName]["ValTypeInsert"] } & { [colName in keyof TTable["_"]["columns"] as TTable["_"]["columns"][colName]["ValTypeInsert"] extends never ? never : undefined extends TTable["_"]["columns"][colName]["ValTypeInsert"] ? colName : never]?: Exclude<TTable["_"]["columns"][colName]["ValTypeInsert"], undefined> }): InsertReturningQuery<TTable, { [ColName in keyof TTable["_"]["columns"]]: TTable["_"]["columns"][ColName]["ValTypeSelect"] }>;
134
126
  /**
135
127
  * Start building a relational query for the specified table.
136
128
  *
@@ -148,7 +140,7 @@ declare class Base<TTName extends string, TTables extends Record<TTName, TableWi
148
140
  * @param table The table to query — must have relations registered via `relations()`.
149
141
  * @returns A `RelationQueryBuilder` with `.findMany()` and `.findFirst()` methods.
150
142
  */
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>;
143
+ 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, TPrepare>;
152
144
  /**
153
145
  * Execute a raw SQL query with optional parameter binding and custom result handler.
154
146
  * @param query The raw SQL query string with $1, $2, etc. placeholders for parameters