@c9up/atlas 0.2.5 → 0.2.6
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/db.win32-x64-msvc.node +0 -0
- package/dist/BaseEntity.d.ts +40 -27
- package/dist/BaseEntity.d.ts.map +1 -1
- package/dist/BaseEntity.js +82 -81
- package/dist/BaseEntity.js.map +1 -1
- package/dist/BaseModel.d.ts +10 -0
- package/dist/BaseModel.d.ts.map +1 -1
- package/dist/BaseModel.js +10 -0
- package/dist/BaseModel.js.map +1 -1
- package/dist/BaseRepository.d.ts.map +1 -1
- package/dist/BaseRepository.js +31 -5
- package/dist/BaseRepository.js.map +1 -1
- package/dist/ConnectionManager.d.ts.map +1 -1
- package/dist/ConnectionManager.js +22 -1
- package/dist/ConnectionManager.js.map +1 -1
- package/dist/ModelQuery.d.ts +22 -1
- package/dist/ModelQuery.d.ts.map +1 -1
- package/dist/ModelQuery.js +43 -20
- package/dist/ModelQuery.js.map +1 -1
- package/dist/Transaction.d.ts +9 -0
- package/dist/Transaction.d.ts.map +1 -1
- package/dist/Transaction.js +14 -0
- package/dist/Transaction.js.map +1 -1
- package/dist/adapters/NapiDbAdapter.d.ts.map +1 -1
- package/dist/adapters/NapiDbAdapter.js +7 -0
- package/dist/adapters/NapiDbAdapter.js.map +1 -1
- package/dist/decorators/entity.d.ts +4 -0
- package/dist/decorators/entity.d.ts.map +1 -1
- package/dist/decorators/entity.js +9 -1
- package/dist/decorators/entity.js.map +1 -1
- package/dist/decorators/hooks.d.ts +28 -0
- package/dist/decorators/hooks.d.ts.map +1 -1
- package/dist/decorators/hooks.js +43 -0
- package/dist/decorators/hooks.js.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -2
- package/dist/index.js.map +1 -1
- package/dist/query/DatabaseQueryBuilder.d.ts +24 -0
- package/dist/query/DatabaseQueryBuilder.d.ts.map +1 -1
- package/dist/query/DatabaseQueryBuilder.js +98 -3
- package/dist/query/DatabaseQueryBuilder.js.map +1 -1
- package/dist/schema/SchemaBuilder.d.ts +2 -1
- package/dist/schema/SchemaBuilder.d.ts.map +1 -1
- package/dist/schema/SchemaBuilder.js +2 -1
- package/dist/schema/SchemaBuilder.js.map +1 -1
- package/dist/schema/TableBuilder.d.ts +140 -132
- package/dist/schema/TableBuilder.d.ts.map +1 -1
- package/dist/schema/TableBuilder.js +232 -231
- package/dist/schema/TableBuilder.js.map +1 -1
- package/dist/services/db.d.ts +7 -0
- package/dist/services/db.d.ts.map +1 -1
- package/dist/services/db.js.map +1 -1
- package/index.darwin-arm64.node +0 -0
- package/index.darwin-x64.node +0 -0
- package/index.linux-arm64-gnu.node +0 -0
- package/index.linux-x64-gnu.node +0 -0
- package/index.win32-x64-msvc.node +0 -0
- package/package.json +3 -3
- package/src/BaseEntity.ts +115 -85
- package/src/BaseModel.ts +10 -0
- package/src/BaseRepository.ts +36 -4
- package/src/ConnectionManager.ts +26 -1
- package/src/ModelQuery.ts +73 -23
- package/src/Transaction.ts +23 -0
- package/src/adapters/NapiDbAdapter.ts +7 -0
- package/src/decorators/entity.ts +13 -1
- package/src/decorators/hooks.ts +67 -0
- package/src/index.ts +8 -1
- package/src/query/DatabaseQueryBuilder.ts +118 -7
- package/src/schema/SchemaBuilder.ts +2 -1
- package/src/schema/TableBuilder.ts +331 -303
- package/src/services/db.ts +7 -0
|
@@ -71,6 +71,255 @@ export class ForeignKeyBuilder {
|
|
|
71
71
|
}
|
|
72
72
|
}
|
|
73
73
|
|
|
74
|
+
/**
|
|
75
|
+
* The chainable a column-type method hands back — Knex's `ColumnBuilder`.
|
|
76
|
+
*
|
|
77
|
+
* It is bound to ITS OWN column, which is what lets `table.comment()` mean the
|
|
78
|
+
* table comment and `table.string('x').comment()` the column one. A builder
|
|
79
|
+
* flattened onto the table cannot tell those apart, and Knex has both.
|
|
80
|
+
*/
|
|
81
|
+
export class ColumnBuilder {
|
|
82
|
+
readonly #table: TableBuilder;
|
|
83
|
+
readonly #column: ColumnDefinition;
|
|
84
|
+
|
|
85
|
+
constructor(table: TableBuilder, column: ColumnDefinition) {
|
|
86
|
+
this.#table = table;
|
|
87
|
+
this.#column = column;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
notNullable(): this {
|
|
91
|
+
this.#column.nullable = false;
|
|
92
|
+
this.#table.markNullabilityTouched();
|
|
93
|
+
return this;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
nullable(): this {
|
|
97
|
+
this.#column.nullable = true;
|
|
98
|
+
this.#table.markNullabilityTouched();
|
|
99
|
+
return this;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* Set a column default. JS literals are quoted/escaped (`'x'`, `123`,
|
|
104
|
+
* `true` — Lucid/Knex semantics); wrap SQL expressions in {@link raw} (or
|
|
105
|
+
* use `Migration.now()`) to emit them verbatim.
|
|
106
|
+
*/
|
|
107
|
+
defaultTo(value: DefaultValue): this {
|
|
108
|
+
this.#column.defaultValue = renderDefaultValue(value);
|
|
109
|
+
return this;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
/** MySQL `UNSIGNED` numeric modifier (Lucid `unsigned()`). No-op on pg/sqlite. */
|
|
113
|
+
unsigned(): this {
|
|
114
|
+
this.#column.unsigned = true;
|
|
115
|
+
return this;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
* Declare the current column a foreign key.
|
|
120
|
+
*
|
|
121
|
+
* - `references('users', 'id')` — atlas form `(table, column='id')`.
|
|
122
|
+
* - `references('users.id')` — Lucid/Knex dotted `'table.column'` shorthand, so
|
|
123
|
+
* a migration copied from Lucid resolves the target the same way. A single
|
|
124
|
+
* argument without a dot is treated as the table name (column defaults to
|
|
125
|
+
* `id`), preserving the atlas one-arg behaviour.
|
|
126
|
+
*/
|
|
127
|
+
references(tableOrPath: string, column?: string): this {
|
|
128
|
+
let table = tableOrPath;
|
|
129
|
+
let col = column ?? "id";
|
|
130
|
+
const dot = tableOrPath.indexOf(".");
|
|
131
|
+
// Dotted shorthand only when no explicit column was passed — an explicit
|
|
132
|
+
// second arg always wins, so `references('a.b', 'c')` stays (table 'a.b').
|
|
133
|
+
if (dot !== -1 && column === undefined) {
|
|
134
|
+
table = tableOrPath.slice(0, dot);
|
|
135
|
+
col = tableOrPath.slice(dot + 1);
|
|
136
|
+
}
|
|
137
|
+
this.#column.references = { table, column: col };
|
|
138
|
+
return this;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
/**
|
|
142
|
+
* Referential action for the current column's foreign key `ON DELETE`
|
|
143
|
+
* (Lucid parity). Must follow {@link references}.
|
|
144
|
+
*/
|
|
145
|
+
onDelete(action: ReferentialAction): this {
|
|
146
|
+
if (this.#column.references) {
|
|
147
|
+
this.#column.references.onDelete = action;
|
|
148
|
+
}
|
|
149
|
+
return this;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
/** Referential action for the current column's foreign key `ON UPDATE`. Must follow {@link references}. */
|
|
153
|
+
onUpdate(action: ReferentialAction): this {
|
|
154
|
+
if (this.#column.references) {
|
|
155
|
+
this.#column.references.onUpdate = action;
|
|
156
|
+
}
|
|
157
|
+
return this;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
/**
|
|
161
|
+
* Comment this column (Lucid/Knex column `comment()`). Inline on MySQL, a
|
|
162
|
+
* separate `COMMENT ON COLUMN` on Postgres, dropped on SQLite. The TABLE
|
|
163
|
+
* comment is `table.comment()` — the receiver tells them apart, as in Knex.
|
|
164
|
+
*/
|
|
165
|
+
comment(text: string): this {
|
|
166
|
+
this.#column.comment = text;
|
|
167
|
+
return this;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
/** Collate this column (Lucid/Knex column `collate()`). The table collation is `table.collate()`. */
|
|
171
|
+
collate(collation: string): this {
|
|
172
|
+
this.#column.collate = collation;
|
|
173
|
+
return this;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
/**
|
|
177
|
+
* Place an added column first (Lucid/Knex `first()`). MySQL-only —
|
|
178
|
+
* Postgres and SQLite always append, and the Rust compiler raises
|
|
179
|
+
* `E_UNSUPPORTED` rather than dropping the instruction silently.
|
|
180
|
+
*/
|
|
181
|
+
first(): this {
|
|
182
|
+
this.#column.position = { at: "first" };
|
|
183
|
+
return this;
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
/** Place an added column after `column` (Lucid/Knex `after()`). MySQL-only — see {@link first}. */
|
|
187
|
+
after(column: string): this {
|
|
188
|
+
this.#column.position = { at: "after", column };
|
|
189
|
+
return this;
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
// ─── CHECK constraints ────────────────────────────────────
|
|
193
|
+
|
|
194
|
+
/** `CHECK (col > 0)` on this column (Lucid/Knex `checkPositive`). */
|
|
195
|
+
checkPositive(constraintName?: string): this {
|
|
196
|
+
this.#table.addColumnCheck(
|
|
197
|
+
this.#column.name,
|
|
198
|
+
(column) => ({ check: "positive", column }),
|
|
199
|
+
constraintName,
|
|
200
|
+
);
|
|
201
|
+
return this;
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
/** `CHECK (col < 0)` on this column (Lucid/Knex `checkNegative`). */
|
|
205
|
+
checkNegative(constraintName?: string): this {
|
|
206
|
+
this.#table.addColumnCheck(
|
|
207
|
+
this.#column.name,
|
|
208
|
+
(column) => ({ check: "negative", column }),
|
|
209
|
+
constraintName,
|
|
210
|
+
);
|
|
211
|
+
return this;
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
/** `CHECK (col IN (…))` on this column (Lucid/Knex `checkIn`). Values are quoted, never interpolated raw. */
|
|
215
|
+
checkIn(values: readonly CheckValue[], constraintName?: string): this {
|
|
216
|
+
this.#table.addColumnCheck(
|
|
217
|
+
this.#column.name,
|
|
218
|
+
(column) => ({ check: "in", column, values: [...values] }),
|
|
219
|
+
constraintName,
|
|
220
|
+
);
|
|
221
|
+
return this;
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
/** `CHECK (col NOT IN (…))` on this column (Lucid/Knex `checkNotIn`). */
|
|
225
|
+
checkNotIn(values: readonly CheckValue[], constraintName?: string): this {
|
|
226
|
+
this.#table.addColumnCheck(
|
|
227
|
+
this.#column.name,
|
|
228
|
+
(column) => ({ check: "notIn", column, values: [...values] }),
|
|
229
|
+
constraintName,
|
|
230
|
+
);
|
|
231
|
+
return this;
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
/**
|
|
235
|
+
* `CHECK (col BETWEEN lo AND hi)` on this column (Lucid/Knex
|
|
236
|
+
* `checkBetween`). Accepts one `[min, max]` interval or a list of them —
|
|
237
|
+
* several intervals are OR'd together, as in Knex.
|
|
238
|
+
*/
|
|
239
|
+
checkBetween(
|
|
240
|
+
range: readonly CheckValue[] | readonly (readonly CheckValue[])[],
|
|
241
|
+
constraintName?: string,
|
|
242
|
+
): this {
|
|
243
|
+
// A single [min, max] vs a list of intervals: the first element of a
|
|
244
|
+
// list-of-intervals is itself an array.
|
|
245
|
+
const ranges = Array.isArray(range[0])
|
|
246
|
+
? (range as readonly (readonly CheckValue[])[]).map((r) => [...r])
|
|
247
|
+
: [[...(range as readonly CheckValue[])]];
|
|
248
|
+
this.#table.addColumnCheck(
|
|
249
|
+
this.#column.name,
|
|
250
|
+
(column) => ({ check: "between", column, ranges }),
|
|
251
|
+
constraintName,
|
|
252
|
+
);
|
|
253
|
+
return this;
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
/** `CHECK (LENGTH(col) <op> n)` on this column (Lucid/Knex `checkLength`). The operator is allow-listed by the Rust compiler. */
|
|
257
|
+
checkLength(
|
|
258
|
+
operator: CheckOperator,
|
|
259
|
+
length: number,
|
|
260
|
+
constraintName?: string,
|
|
261
|
+
): this {
|
|
262
|
+
this.#table.addColumnCheck(
|
|
263
|
+
this.#column.name,
|
|
264
|
+
(column) => ({ check: "length", column, operator, length }),
|
|
265
|
+
constraintName,
|
|
266
|
+
);
|
|
267
|
+
return this;
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
/**
|
|
271
|
+
* `CHECK (col ~ 'pattern')` on this column (Lucid/Knex `checkRegex`).
|
|
272
|
+
* Postgres spells it `~`; MySQL and SQLite use `REGEXP`.
|
|
273
|
+
*
|
|
274
|
+
* SQLite parses `REGEXP` but ships no implementation — the constraint only
|
|
275
|
+
* works if the connection registers a `regexp` function. Knex behaves the
|
|
276
|
+
* same way, so this is parity rather than a new trap, but it is worth
|
|
277
|
+
* knowing before you rely on it there.
|
|
278
|
+
*/
|
|
279
|
+
checkRegex(pattern: string, constraintName?: string): this {
|
|
280
|
+
this.#table.addColumnCheck(
|
|
281
|
+
this.#column.name,
|
|
282
|
+
(column) => ({ check: "regex", column, pattern }),
|
|
283
|
+
constraintName,
|
|
284
|
+
);
|
|
285
|
+
return this;
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
/** Mark this column the primary key (Lucid/Knex column `primary()`). */
|
|
289
|
+
primary(): this {
|
|
290
|
+
this.#column.primary = true;
|
|
291
|
+
return this;
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
/** Mark this column `UNIQUE` (Lucid/Knex column `unique()`). */
|
|
295
|
+
unique(): this {
|
|
296
|
+
this.#column.unique = true;
|
|
297
|
+
return this;
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
/** Index this column (Lucid/Knex column `index()`). */
|
|
301
|
+
index(name?: string): this {
|
|
302
|
+
this.#table.index(this.#column.name, name);
|
|
303
|
+
return this;
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
/**
|
|
307
|
+
* Apply this definition as a type change instead of an `ADD COLUMN`
|
|
308
|
+
* (Lucid/Knex `alter()`).
|
|
309
|
+
*
|
|
310
|
+
* Nullability moves only if `.nullable()` / `.notNullable()` was called
|
|
311
|
+
* before this — a bare `t.string('x').alter()` changes the type and leaves
|
|
312
|
+
* the NOT NULL constraint exactly as it is.
|
|
313
|
+
*
|
|
314
|
+
* SQLite cannot alter a column in place; the Rust compiler rejects it with
|
|
315
|
+
* `E_UNSUPPORTED` rather than emitting a table rebuild behind your back.
|
|
316
|
+
*/
|
|
317
|
+
alter(): this {
|
|
318
|
+
this.#table.alterPendingColumn();
|
|
319
|
+
return this;
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
|
|
74
323
|
/**
|
|
75
324
|
* Whether the builder is filling a `CREATE TABLE` or an `ALTER TABLE`. In
|
|
76
325
|
* `alter` mode a column-type method (`t.string('x')`) becomes `ADD COLUMN`,
|
|
@@ -107,7 +356,7 @@ export class TableBuilder {
|
|
|
107
356
|
|
|
108
357
|
// ─── Column types ─────────────────────────────────────────
|
|
109
358
|
|
|
110
|
-
uuid(name: string):
|
|
359
|
+
uuid(name: string): ColumnBuilder {
|
|
111
360
|
return this.#addColumn(name, "uuid");
|
|
112
361
|
}
|
|
113
362
|
|
|
@@ -117,19 +366,19 @@ export class TableBuilder {
|
|
|
117
366
|
* `AUTOINCREMENT`, Postgres `GENERATED ... AS IDENTITY`, MySQL
|
|
118
367
|
* `AUTO_INCREMENT`). For a 64-bit key use `bigIncrements()`.
|
|
119
368
|
*/
|
|
120
|
-
increments(name = "id"):
|
|
369
|
+
increments(name = "id"): ColumnBuilder {
|
|
121
370
|
return this.#addIncrements(name, "integer");
|
|
122
371
|
}
|
|
123
372
|
|
|
124
373
|
/** Auto-incrementing 64-bit primary key (Lucid `bigIncrements()`). */
|
|
125
|
-
bigIncrements(name = "id"):
|
|
374
|
+
bigIncrements(name = "id"): ColumnBuilder {
|
|
126
375
|
return this.#addIncrements(name, "bigInteger");
|
|
127
376
|
}
|
|
128
377
|
|
|
129
|
-
string(name: string, length = 255):
|
|
130
|
-
this.#addColumn(name, "string");
|
|
378
|
+
string(name: string, length = 255): ColumnBuilder {
|
|
379
|
+
const column = this.#addColumn(name, "string");
|
|
131
380
|
if (this.#currentColumn) this.#currentColumn.length = length;
|
|
132
|
-
return
|
|
381
|
+
return column;
|
|
133
382
|
}
|
|
134
383
|
|
|
135
384
|
/**
|
|
@@ -137,35 +386,35 @@ export class TableBuilder {
|
|
|
137
386
|
* MySQL type (`MEDIUMTEXT` / `LONGTEXT`); Postgres and SQLite have a single
|
|
138
387
|
* unbounded `TEXT` and ignore it.
|
|
139
388
|
*/
|
|
140
|
-
text(name: string, textType: TextVariant = "text"):
|
|
389
|
+
text(name: string, textType: TextVariant = "text"): ColumnBuilder {
|
|
141
390
|
return this.#addColumn(name, textType);
|
|
142
391
|
}
|
|
143
|
-
integer(name: string):
|
|
392
|
+
integer(name: string): ColumnBuilder {
|
|
144
393
|
return this.#addColumn(name, "integer");
|
|
145
394
|
}
|
|
146
395
|
/** 24-bit integer (Lucid/Knex `mediumint`). MySQL `MEDIUMINT`; pg/SQLite widen to `INTEGER`. */
|
|
147
|
-
mediumint(name: string):
|
|
396
|
+
mediumint(name: string): ColumnBuilder {
|
|
148
397
|
return this.#addColumn(name, "mediumint");
|
|
149
398
|
}
|
|
150
399
|
/** 8-bit integer (Lucid `tinyint`). MySQL `TINYINT`; Postgres widens to `SMALLINT`; SQLite `INTEGER`. */
|
|
151
|
-
tinyint(name: string):
|
|
400
|
+
tinyint(name: string): ColumnBuilder {
|
|
152
401
|
return this.#addColumn(name, "tinyint");
|
|
153
402
|
}
|
|
154
403
|
/** 16-bit integer (Lucid `smallint`). `SMALLINT` on pg/mysql, `INTEGER` on SQLite. */
|
|
155
|
-
smallint(name: string):
|
|
404
|
+
smallint(name: string): ColumnBuilder {
|
|
156
405
|
return this.#addColumn(name, "smallint");
|
|
157
406
|
}
|
|
158
|
-
bigInteger(name: string):
|
|
407
|
+
bigInteger(name: string): ColumnBuilder {
|
|
159
408
|
return this.#addColumn(name, "bigInteger");
|
|
160
409
|
}
|
|
161
410
|
|
|
162
|
-
decimal(name: string, precision = 10, scale = 2):
|
|
163
|
-
this.#addColumn(name, "decimal");
|
|
411
|
+
decimal(name: string, precision = 10, scale = 2): ColumnBuilder {
|
|
412
|
+
const column = this.#addColumn(name, "decimal");
|
|
164
413
|
if (this.#currentColumn) {
|
|
165
414
|
this.#currentColumn.precision = precision;
|
|
166
415
|
this.#currentColumn.scale = scale;
|
|
167
416
|
}
|
|
168
|
-
return
|
|
417
|
+
return column;
|
|
169
418
|
}
|
|
170
419
|
|
|
171
420
|
/**
|
|
@@ -173,18 +422,18 @@ export class TableBuilder {
|
|
|
173
422
|
* MySQL. `precision`/`scale` render `FLOAT(p, s)` on MySQL only — pg and
|
|
174
423
|
* SQLite have fixed-width floats and ignore them.
|
|
175
424
|
*/
|
|
176
|
-
float(name: string, precision?: number, scale?: number):
|
|
425
|
+
float(name: string, precision?: number, scale?: number): ColumnBuilder {
|
|
177
426
|
return this.#addFloat(name, "float", precision, scale);
|
|
178
427
|
}
|
|
179
428
|
/** Double-precision float (Lucid `double`). `DOUBLE PRECISION` on pg, `REAL` on SQLite, `DOUBLE` on MySQL. See {@link float} for precision/scale. */
|
|
180
|
-
double(name: string, precision?: number, scale?: number):
|
|
429
|
+
double(name: string, precision?: number, scale?: number): ColumnBuilder {
|
|
181
430
|
return this.#addFloat(name, "double", precision, scale);
|
|
182
431
|
}
|
|
183
432
|
|
|
184
|
-
boolean(name: string):
|
|
433
|
+
boolean(name: string): ColumnBuilder {
|
|
185
434
|
return this.#addColumn(name, "boolean");
|
|
186
435
|
}
|
|
187
|
-
date(name: string):
|
|
436
|
+
date(name: string): ColumnBuilder {
|
|
188
437
|
return this.#addColumn(name, "date");
|
|
189
438
|
}
|
|
190
439
|
/**
|
|
@@ -192,10 +441,10 @@ export class TableBuilder {
|
|
|
192
441
|
* `precision` renders `TIME(p)` fractional seconds (ignored on SQLite,
|
|
193
442
|
* which has no time type to carry it).
|
|
194
443
|
*/
|
|
195
|
-
time(name: string, precision?: number):
|
|
196
|
-
this.#addColumn(name, "time");
|
|
444
|
+
time(name: string, precision?: number): ColumnBuilder {
|
|
445
|
+
const column = this.#addColumn(name, "time");
|
|
197
446
|
if (this.#currentColumn) this.#currentColumn.precision = precision;
|
|
198
|
-
return
|
|
447
|
+
return column;
|
|
199
448
|
}
|
|
200
449
|
/**
|
|
201
450
|
* Timestamp column (Lucid `timestamp(name, options)`).
|
|
@@ -208,16 +457,19 @@ export class TableBuilder {
|
|
|
208
457
|
timestamp(
|
|
209
458
|
name: string,
|
|
210
459
|
options: { useTz?: boolean; precision?: number } = {},
|
|
211
|
-
):
|
|
212
|
-
this.#addColumn(
|
|
460
|
+
): ColumnBuilder {
|
|
461
|
+
const column = this.#addColumn(
|
|
462
|
+
name,
|
|
463
|
+
options.useTz ? "timestamptz" : "timestamp",
|
|
464
|
+
);
|
|
213
465
|
if (this.#currentColumn) this.#currentColumn.precision = options.precision;
|
|
214
|
-
return
|
|
466
|
+
return column;
|
|
215
467
|
}
|
|
216
468
|
/** Alias of {@link timestamp} (Lucid `dateTime`). Use `{ useTz: true }` or {@link timestamptz} for a tz-aware column. */
|
|
217
469
|
dateTime(
|
|
218
470
|
name: string,
|
|
219
471
|
options: { useTz?: boolean; precision?: number } = {},
|
|
220
|
-
):
|
|
472
|
+
): ColumnBuilder {
|
|
221
473
|
return this.timestamp(name, options);
|
|
222
474
|
}
|
|
223
475
|
/**
|
|
@@ -229,33 +481,27 @@ export class TableBuilder {
|
|
|
229
481
|
* from the SQL type). On MySQL/SQLite (no real tz type) it degrades to the
|
|
230
482
|
* plain timestamp mapping.
|
|
231
483
|
*/
|
|
232
|
-
timestamptz(name: string):
|
|
484
|
+
timestamptz(name: string): ColumnBuilder {
|
|
233
485
|
return this.#addColumn(name, "timestamptz");
|
|
234
486
|
}
|
|
235
|
-
json(name: string):
|
|
487
|
+
json(name: string): ColumnBuilder {
|
|
236
488
|
return this.#addColumn(name, "json");
|
|
237
489
|
}
|
|
238
490
|
/**
|
|
239
491
|
* Binary JSON (Lucid/Knex `jsonb`). `JSONB` on pg, `JSON` on MySQL, `TEXT`
|
|
240
492
|
* on SQLite.
|
|
241
|
-
*
|
|
242
|
-
* Deviation, named: atlas's {@link json} already maps to `JSONB` on
|
|
243
|
-
* Postgres (it predates this method), where Lucid's `json()` maps to
|
|
244
|
-
* `json`. Leaving `json()` alone avoids silently rewriting the physical
|
|
245
|
-
* type of existing columns and desyncing `SchemaCheck`, so on Postgres the
|
|
246
|
-
* two spellings coincide.
|
|
247
493
|
*/
|
|
248
|
-
jsonb(name: string):
|
|
494
|
+
jsonb(name: string): ColumnBuilder {
|
|
249
495
|
return this.#addColumn(name, "jsonb");
|
|
250
496
|
}
|
|
251
497
|
/**
|
|
252
498
|
* Binary blob (Lucid/Knex `binary(name, length)`). `BYTEA` on pg, `BLOB` on
|
|
253
499
|
* SQLite; on MySQL `length` selects `VARBINARY(n)` over `BLOB`.
|
|
254
500
|
*/
|
|
255
|
-
binary(name: string, length?: number):
|
|
256
|
-
this.#addColumn(name, "binary");
|
|
501
|
+
binary(name: string, length?: number): ColumnBuilder {
|
|
502
|
+
const column = this.#addColumn(name, "binary");
|
|
257
503
|
if (this.#currentColumn) this.#currentColumn.length = length;
|
|
258
|
-
return
|
|
504
|
+
return column;
|
|
259
505
|
}
|
|
260
506
|
|
|
261
507
|
/**
|
|
@@ -268,10 +514,10 @@ export class TableBuilder {
|
|
|
268
514
|
* narrow grammar (letters, digits, spaces, `_`, and one parenthesised
|
|
269
515
|
* argument list) and rejects anything else with `E_UNSAFE_SQL`.
|
|
270
516
|
*/
|
|
271
|
-
specificType(name: string, type: string):
|
|
272
|
-
this.#addColumn(name, "specificType");
|
|
517
|
+
specificType(name: string, type: string): ColumnBuilder {
|
|
518
|
+
const column = this.#addColumn(name, "specificType");
|
|
273
519
|
if (this.#currentColumn) this.#currentColumn.rawType = type;
|
|
274
|
-
return
|
|
520
|
+
return column;
|
|
275
521
|
}
|
|
276
522
|
|
|
277
523
|
/**
|
|
@@ -279,10 +525,10 @@ export class TableBuilder {
|
|
|
279
525
|
* Postgres and SQLite render `TEXT` plus a `CHECK (col IN (...))` that pins the
|
|
280
526
|
* value set. At least one value is required.
|
|
281
527
|
*/
|
|
282
|
-
enum(name: string, values: string[]):
|
|
283
|
-
this.#addColumn(name, "enum");
|
|
528
|
+
enum(name: string, values: string[]): ColumnBuilder {
|
|
529
|
+
const column = this.#addColumn(name, "enum");
|
|
284
530
|
if (this.#currentColumn) this.#currentColumn.values = values;
|
|
285
|
-
return
|
|
531
|
+
return column;
|
|
286
532
|
}
|
|
287
533
|
|
|
288
534
|
// ─── Shortcuts ────────────────────────────────────────────
|
|
@@ -307,7 +553,7 @@ export class TableBuilder {
|
|
|
307
553
|
* (A dialect-aware escape hatch can be added later if a future story needs
|
|
308
554
|
* per-dialect PK defaults.)
|
|
309
555
|
*/
|
|
310
|
-
id():
|
|
556
|
+
id(): ColumnBuilder {
|
|
311
557
|
return this.uuid("id").primary().defaultTo(new RawSql("gen_random_uuid()"));
|
|
312
558
|
}
|
|
313
559
|
|
|
@@ -347,10 +593,9 @@ export class TableBuilder {
|
|
|
347
593
|
*/
|
|
348
594
|
timestamps(useTimestamps = true, defaultToNow = true): this {
|
|
349
595
|
const add = (name: string): void => {
|
|
350
|
-
|
|
351
|
-
else this.dateTime(name);
|
|
596
|
+
const column = useTimestamps ? this.timestamp(name) : this.dateTime(name);
|
|
352
597
|
if (defaultToNow) {
|
|
353
|
-
|
|
598
|
+
column.notNullable().defaultTo(new RawSql("CURRENT_TIMESTAMP"));
|
|
354
599
|
}
|
|
355
600
|
};
|
|
356
601
|
add("created_at");
|
|
@@ -358,209 +603,13 @@ export class TableBuilder {
|
|
|
358
603
|
return this;
|
|
359
604
|
}
|
|
360
605
|
|
|
361
|
-
// ─── Column modifiers ─────────────────────────────────────
|
|
362
|
-
|
|
363
|
-
notNullable(): this {
|
|
364
|
-
if (this.#currentColumn) this.#currentColumn.nullable = false;
|
|
365
|
-
this.#nullabilityTouched = true;
|
|
366
|
-
return this;
|
|
367
|
-
}
|
|
368
|
-
|
|
369
|
-
nullable(): this {
|
|
370
|
-
if (this.#currentColumn) this.#currentColumn.nullable = true;
|
|
371
|
-
this.#nullabilityTouched = true;
|
|
372
|
-
return this;
|
|
373
|
-
}
|
|
374
|
-
|
|
375
|
-
/**
|
|
376
|
-
* Set a column default. JS literals are quoted/escaped (`'x'`, `123`,
|
|
377
|
-
* `true` — Lucid/Knex semantics); wrap SQL expressions in {@link raw} (or
|
|
378
|
-
* use `Migration.now()`) to emit them verbatim.
|
|
379
|
-
*/
|
|
380
|
-
defaultTo(value: DefaultValue): this {
|
|
381
|
-
if (this.#currentColumn) {
|
|
382
|
-
this.#currentColumn.defaultValue = renderDefaultValue(value);
|
|
383
|
-
}
|
|
384
|
-
return this;
|
|
385
|
-
}
|
|
386
|
-
|
|
387
|
-
/** MySQL `UNSIGNED` numeric modifier (Lucid `unsigned()`). No-op on pg/sqlite. */
|
|
388
|
-
unsigned(): this {
|
|
389
|
-
if (this.#currentColumn) this.#currentColumn.unsigned = true;
|
|
390
|
-
return this;
|
|
391
|
-
}
|
|
392
|
-
|
|
393
|
-
/**
|
|
394
|
-
* Declare the current column a foreign key.
|
|
395
|
-
*
|
|
396
|
-
* - `references('users', 'id')` — atlas form `(table, column='id')`.
|
|
397
|
-
* - `references('users.id')` — Lucid/Knex dotted `'table.column'` shorthand, so
|
|
398
|
-
* a migration copied from Lucid resolves the target the same way. A single
|
|
399
|
-
* argument without a dot is treated as the table name (column defaults to
|
|
400
|
-
* `id`), preserving the atlas one-arg behaviour.
|
|
401
|
-
*/
|
|
402
|
-
references(tableOrPath: string, column?: string): this {
|
|
403
|
-
let table = tableOrPath;
|
|
404
|
-
let col = column ?? "id";
|
|
405
|
-
const dot = tableOrPath.indexOf(".");
|
|
406
|
-
// Dotted shorthand only when no explicit column was passed — an explicit
|
|
407
|
-
// second arg always wins, so `references('a.b', 'c')` stays (table 'a.b').
|
|
408
|
-
if (dot !== -1 && column === undefined) {
|
|
409
|
-
table = tableOrPath.slice(0, dot);
|
|
410
|
-
col = tableOrPath.slice(dot + 1);
|
|
411
|
-
}
|
|
412
|
-
if (this.#currentColumn) {
|
|
413
|
-
this.#currentColumn.references = { table, column: col };
|
|
414
|
-
}
|
|
415
|
-
return this;
|
|
416
|
-
}
|
|
417
|
-
|
|
418
|
-
/**
|
|
419
|
-
* Referential action for the current column's foreign key `ON DELETE`
|
|
420
|
-
* (Lucid parity). Must follow {@link references}.
|
|
421
|
-
*/
|
|
422
|
-
onDelete(action: ReferentialAction): this {
|
|
423
|
-
if (this.#currentColumn?.references) {
|
|
424
|
-
this.#currentColumn.references.onDelete = action;
|
|
425
|
-
}
|
|
426
|
-
return this;
|
|
427
|
-
}
|
|
428
|
-
|
|
429
|
-
/** Referential action for the current column's foreign key `ON UPDATE`. Must follow {@link references}. */
|
|
430
|
-
onUpdate(action: ReferentialAction): this {
|
|
431
|
-
if (this.#currentColumn?.references) {
|
|
432
|
-
this.#currentColumn.references.onUpdate = action;
|
|
433
|
-
}
|
|
434
|
-
return this;
|
|
435
|
-
}
|
|
436
|
-
|
|
437
|
-
/**
|
|
438
|
-
* Comment the current **column** (Lucid/Knex column `comment()`). Inline on
|
|
439
|
-
* MySQL, a separate `COMMENT ON COLUMN` on Postgres, dropped on SQLite.
|
|
440
|
-
*
|
|
441
|
-
* Deviation, named: Knex's `table.comment()` is the TABLE comment, because
|
|
442
|
-
* its column methods return a separate column builder. Atlas flattens the
|
|
443
|
-
* column modifiers onto the table builder (`.notNullable()`, `.unique()`,
|
|
444
|
-
* `.defaultTo()` all work this way), so `comment()` follows that same rule
|
|
445
|
-
* and the table comment is {@link tableComment}. Resolving it by "is a
|
|
446
|
-
* column pending?" would be exactly the kind of guessing that bites later.
|
|
447
|
-
*/
|
|
448
|
-
comment(text: string): this {
|
|
449
|
-
if (this.#currentColumn) this.#currentColumn.comment = text;
|
|
450
|
-
return this;
|
|
451
|
-
}
|
|
452
|
-
|
|
453
|
-
/** Collate the current **column** (Lucid/Knex column `collate()`). See {@link comment} for why the table form is {@link tableCollate}. */
|
|
454
|
-
collate(collation: string): this {
|
|
455
|
-
if (this.#currentColumn) this.#currentColumn.collate = collation;
|
|
456
|
-
return this;
|
|
457
|
-
}
|
|
458
|
-
|
|
459
|
-
/**
|
|
460
|
-
* Place an added column first (Lucid/Knex `first()`). MySQL-only —
|
|
461
|
-
* Postgres and SQLite always append, and the Rust compiler raises
|
|
462
|
-
* `E_UNSUPPORTED` rather than dropping the instruction silently.
|
|
463
|
-
*/
|
|
464
|
-
first(): this {
|
|
465
|
-
if (this.#currentColumn) this.#currentColumn.position = { at: "first" };
|
|
466
|
-
return this;
|
|
467
|
-
}
|
|
468
|
-
|
|
469
|
-
/** Place an added column after `column` (Lucid/Knex `after()`). MySQL-only — see {@link first}. */
|
|
470
|
-
after(column: string): this {
|
|
471
|
-
if (this.#currentColumn) {
|
|
472
|
-
this.#currentColumn.position = { at: "after", column };
|
|
473
|
-
}
|
|
474
|
-
return this;
|
|
475
|
-
}
|
|
476
|
-
|
|
477
606
|
// ─── CHECK constraints ────────────────────────────────────
|
|
478
607
|
|
|
479
|
-
/** `CHECK (col > 0)` on the current column (Lucid/Knex `checkPositive`). */
|
|
480
|
-
checkPositive(constraintName?: string): this {
|
|
481
|
-
return this.#addCheck(
|
|
482
|
-
(column) => ({ check: "positive", column }),
|
|
483
|
-
constraintName,
|
|
484
|
-
);
|
|
485
|
-
}
|
|
486
|
-
|
|
487
|
-
/** `CHECK (col < 0)` on the current column (Lucid/Knex `checkNegative`). */
|
|
488
|
-
checkNegative(constraintName?: string): this {
|
|
489
|
-
return this.#addCheck(
|
|
490
|
-
(column) => ({ check: "negative", column }),
|
|
491
|
-
constraintName,
|
|
492
|
-
);
|
|
493
|
-
}
|
|
494
|
-
|
|
495
|
-
/** `CHECK (col IN (…))` on the current column (Lucid/Knex `checkIn`). Values are quoted, never interpolated raw. */
|
|
496
|
-
checkIn(values: readonly CheckValue[], constraintName?: string): this {
|
|
497
|
-
return this.#addCheck(
|
|
498
|
-
(column) => ({ check: "in", column, values: [...values] }),
|
|
499
|
-
constraintName,
|
|
500
|
-
);
|
|
501
|
-
}
|
|
502
|
-
|
|
503
|
-
/** `CHECK (col NOT IN (…))` on the current column (Lucid/Knex `checkNotIn`). */
|
|
504
|
-
checkNotIn(values: readonly CheckValue[], constraintName?: string): this {
|
|
505
|
-
return this.#addCheck(
|
|
506
|
-
(column) => ({ check: "notIn", column, values: [...values] }),
|
|
507
|
-
constraintName,
|
|
508
|
-
);
|
|
509
|
-
}
|
|
510
|
-
|
|
511
|
-
/**
|
|
512
|
-
* `CHECK (col BETWEEN lo AND hi)` on the current column (Lucid/Knex
|
|
513
|
-
* `checkBetween`). Accepts one `[min, max]` interval or a list of them —
|
|
514
|
-
* several intervals are OR'd together, as in Knex.
|
|
515
|
-
*/
|
|
516
|
-
checkBetween(
|
|
517
|
-
range: readonly CheckValue[] | readonly (readonly CheckValue[])[],
|
|
518
|
-
constraintName?: string,
|
|
519
|
-
): this {
|
|
520
|
-
// A single [min, max] vs a list of intervals: the first element of a
|
|
521
|
-
// list-of-intervals is itself an array.
|
|
522
|
-
const ranges = Array.isArray(range[0])
|
|
523
|
-
? (range as readonly (readonly CheckValue[])[]).map((r) => [...r])
|
|
524
|
-
: [[...(range as readonly CheckValue[])]];
|
|
525
|
-
return this.#addCheck(
|
|
526
|
-
(column) => ({ check: "between", column, ranges }),
|
|
527
|
-
constraintName,
|
|
528
|
-
);
|
|
529
|
-
}
|
|
530
|
-
|
|
531
|
-
/** `CHECK (LENGTH(col) <op> n)` on the current column (Lucid/Knex `checkLength`). The operator is allow-listed by the Rust compiler. */
|
|
532
|
-
checkLength(
|
|
533
|
-
operator: CheckOperator,
|
|
534
|
-
length: number,
|
|
535
|
-
constraintName?: string,
|
|
536
|
-
): this {
|
|
537
|
-
return this.#addCheck(
|
|
538
|
-
(column) => ({ check: "length", column, operator, length }),
|
|
539
|
-
constraintName,
|
|
540
|
-
);
|
|
541
|
-
}
|
|
542
|
-
|
|
543
|
-
/**
|
|
544
|
-
* `CHECK (col ~ 'pattern')` on the current column (Lucid/Knex `checkRegex`).
|
|
545
|
-
* Postgres spells it `~`; MySQL and SQLite use `REGEXP`.
|
|
546
|
-
*
|
|
547
|
-
* SQLite parses `REGEXP` but ships no implementation — the constraint only
|
|
548
|
-
* works if the connection registers a `regexp` function. Knex behaves the
|
|
549
|
-
* same way, so this is parity rather than a new trap, but it is worth
|
|
550
|
-
* knowing before you rely on it there.
|
|
551
|
-
*/
|
|
552
|
-
checkRegex(pattern: string, constraintName?: string): this {
|
|
553
|
-
return this.#addCheck(
|
|
554
|
-
(column) => ({ check: "regex", column, pattern }),
|
|
555
|
-
constraintName,
|
|
556
|
-
);
|
|
557
|
-
}
|
|
558
|
-
|
|
559
608
|
/**
|
|
560
609
|
* A free-form `CHECK (predicate)` (Lucid/Knex `check`). The predicate is
|
|
561
610
|
* emitted verbatim — exactly as trusted as {@link Schema.raw}, so never
|
|
562
|
-
* build it from user input. Prefer the typed `check*` helpers
|
|
563
|
-
* safe by construction.
|
|
611
|
+
* build it from user input. Prefer the typed `check*` helpers on the column
|
|
612
|
+
* builder, which are safe by construction.
|
|
564
613
|
*/
|
|
565
614
|
check(predicate: string, constraintName?: string): this {
|
|
566
615
|
this.#pushConstraint({
|
|
@@ -582,16 +631,8 @@ export class TableBuilder {
|
|
|
582
631
|
|
|
583
632
|
// ─── Table-level constraints ──────────────────────────────
|
|
584
633
|
|
|
585
|
-
/**
|
|
586
|
-
|
|
587
|
-
* existing column modifier). With a column list, declare a composite
|
|
588
|
-
* `PRIMARY KEY (…)` table constraint (Lucid/Knex `primary([...])`).
|
|
589
|
-
*/
|
|
590
|
-
primary(columns?: readonly string[], constraintName?: string): this {
|
|
591
|
-
if (columns === undefined) {
|
|
592
|
-
if (this.#currentColumn) this.#currentColumn.primary = true;
|
|
593
|
-
return this;
|
|
594
|
-
}
|
|
634
|
+
/** Composite `PRIMARY KEY (…)` table constraint (Lucid/Knex `primary([...])`). */
|
|
635
|
+
primary(columns: readonly string[], constraintName?: string): this {
|
|
595
636
|
this.#pushConstraint({
|
|
596
637
|
constraint: "primary",
|
|
597
638
|
name: constraintName,
|
|
@@ -601,18 +642,12 @@ export class TableBuilder {
|
|
|
601
642
|
}
|
|
602
643
|
|
|
603
644
|
/**
|
|
604
|
-
*
|
|
605
|
-
* modifier). With a column list, declare a composite `UNIQUE (…)` table
|
|
606
|
-
* constraint (Lucid/Knex `unique([...])`).
|
|
645
|
+
* Composite `UNIQUE (…)` table constraint (Lucid/Knex `unique([...])`).
|
|
607
646
|
*
|
|
608
647
|
* Note this is a real constraint, unlike {@link uniqueIndex}, which creates
|
|
609
648
|
* a separate `CREATE UNIQUE INDEX`.
|
|
610
649
|
*/
|
|
611
|
-
unique(columns
|
|
612
|
-
if (columns === undefined) {
|
|
613
|
-
if (this.#currentColumn) this.#currentColumn.unique = true;
|
|
614
|
-
return this;
|
|
615
|
-
}
|
|
650
|
+
unique(columns: readonly string[], constraintName?: string): this {
|
|
616
651
|
this.#pushConstraint({
|
|
617
652
|
constraint: "unique",
|
|
618
653
|
name: constraintName ?? this.#constraintName(columns, "unique"),
|
|
@@ -698,14 +733,14 @@ export class TableBuilder {
|
|
|
698
733
|
return this;
|
|
699
734
|
}
|
|
700
735
|
|
|
701
|
-
/** MySQL default collation for the table
|
|
702
|
-
|
|
736
|
+
/** MySQL default collation for the table (Lucid/Knex `collate`). The column form is `table.<type>(…).collate()`. */
|
|
737
|
+
collate(name: string): this {
|
|
703
738
|
this.#options.collate = name;
|
|
704
739
|
return this;
|
|
705
740
|
}
|
|
706
741
|
|
|
707
|
-
/** Table comment
|
|
708
|
-
|
|
742
|
+
/** Table comment (Lucid/Knex `comment`). The column form is `table.<type>(…).comment()`. */
|
|
743
|
+
comment(text: string): this {
|
|
709
744
|
this.#options.comment = text;
|
|
710
745
|
return this;
|
|
711
746
|
}
|
|
@@ -736,16 +771,9 @@ export class TableBuilder {
|
|
|
736
771
|
|
|
737
772
|
/**
|
|
738
773
|
* Apply the pending column definition as a type change instead of an
|
|
739
|
-
*
|
|
740
|
-
*
|
|
741
|
-
* Nullability moves only if `.nullable()` / `.notNullable()` was called
|
|
742
|
-
* before this — a bare `t.string('x').alter()` changes the type and leaves
|
|
743
|
-
* the NOT NULL constraint exactly as it is.
|
|
744
|
-
*
|
|
745
|
-
* SQLite cannot alter a column in place; the Rust compiler rejects it with
|
|
746
|
-
* `E_UNSUPPORTED` rather than emitting a table rebuild behind your back.
|
|
774
|
+
* @internal Backs `ColumnBuilder.alter()`.
|
|
747
775
|
*/
|
|
748
|
-
|
|
776
|
+
alterPendingColumn(): void {
|
|
749
777
|
this.#assertAlterMode("alter()");
|
|
750
778
|
const pending = this.#currentOp;
|
|
751
779
|
if (!pending) {
|
|
@@ -764,7 +792,24 @@ export class TableBuilder {
|
|
|
764
792
|
this.#operations[this.#operations.indexOf(pending)] = converted;
|
|
765
793
|
this.#currentOp = converted;
|
|
766
794
|
}
|
|
767
|
-
|
|
795
|
+
}
|
|
796
|
+
|
|
797
|
+
/** @internal Backs `ColumnBuilder.nullable()` / `.notNullable()`. */
|
|
798
|
+
markNullabilityTouched(): void {
|
|
799
|
+
this.#nullabilityTouched = true;
|
|
800
|
+
}
|
|
801
|
+
|
|
802
|
+
/** @internal Backs the `ColumnBuilder.check*()` helpers, for a named column. */
|
|
803
|
+
addColumnCheck(
|
|
804
|
+
column: string,
|
|
805
|
+
build: (column: string) => CheckExpression,
|
|
806
|
+
constraintName?: string,
|
|
807
|
+
): void {
|
|
808
|
+
this.#pushConstraint({
|
|
809
|
+
constraint: "check",
|
|
810
|
+
name: constraintName,
|
|
811
|
+
expr: build(column),
|
|
812
|
+
});
|
|
768
813
|
}
|
|
769
814
|
|
|
770
815
|
/** Drop a column (Lucid/Knex `dropColumn`). */
|
|
@@ -920,23 +965,6 @@ export class TableBuilder {
|
|
|
920
965
|
}
|
|
921
966
|
|
|
922
967
|
/** Build a CHECK against the pending column. */
|
|
923
|
-
#addCheck(
|
|
924
|
-
build: (column: string) => CheckExpression,
|
|
925
|
-
constraintName?: string,
|
|
926
|
-
): this {
|
|
927
|
-
const column = this.#currentColumn?.name;
|
|
928
|
-
if (!column) {
|
|
929
|
-
throw new Error(
|
|
930
|
-
"E_CHECK_MISUSE: a check* helper must follow a column definition, e.g. table.integer('qty').checkPositive()",
|
|
931
|
-
);
|
|
932
|
-
}
|
|
933
|
-
this.#pushConstraint({
|
|
934
|
-
constraint: "check",
|
|
935
|
-
name: constraintName,
|
|
936
|
-
expr: build(column),
|
|
937
|
-
});
|
|
938
|
-
return this;
|
|
939
|
-
}
|
|
940
968
|
|
|
941
969
|
/**
|
|
942
970
|
* Default constraint name, following Knex's `<table>_<columns>_<suffix>`
|
|
@@ -968,7 +996,7 @@ export class TableBuilder {
|
|
|
968
996
|
this.#nullabilityTouched = false;
|
|
969
997
|
}
|
|
970
998
|
|
|
971
|
-
#addColumn(name: string, type: ColumnType):
|
|
999
|
+
#addColumn(name: string, type: ColumnType): ColumnBuilder {
|
|
972
1000
|
const col: ColumnDefinition = {
|
|
973
1001
|
name,
|
|
974
1002
|
type,
|
|
@@ -987,7 +1015,7 @@ export class TableBuilder {
|
|
|
987
1015
|
this.#operations.push(op);
|
|
988
1016
|
this.#currentOp = op;
|
|
989
1017
|
}
|
|
990
|
-
return this;
|
|
1018
|
+
return new ColumnBuilder(this, col);
|
|
991
1019
|
}
|
|
992
1020
|
|
|
993
1021
|
#addFloat(
|
|
@@ -995,22 +1023,22 @@ export class TableBuilder {
|
|
|
995
1023
|
type: "float" | "double",
|
|
996
1024
|
precision?: number,
|
|
997
1025
|
scale?: number,
|
|
998
|
-
):
|
|
999
|
-
this.#addColumn(name, type);
|
|
1026
|
+
): ColumnBuilder {
|
|
1027
|
+
const column = this.#addColumn(name, type);
|
|
1000
1028
|
if (this.#currentColumn) {
|
|
1001
1029
|
this.#currentColumn.precision = precision;
|
|
1002
1030
|
this.#currentColumn.scale = scale;
|
|
1003
1031
|
}
|
|
1004
|
-
return
|
|
1032
|
+
return column;
|
|
1005
1033
|
}
|
|
1006
1034
|
|
|
1007
|
-
#addIncrements(name: string, type: "integer" | "bigInteger"):
|
|
1008
|
-
this.#addColumn(name, type);
|
|
1035
|
+
#addIncrements(name: string, type: "integer" | "bigInteger"): ColumnBuilder {
|
|
1036
|
+
const column = this.#addColumn(name, type);
|
|
1009
1037
|
if (this.#currentColumn) {
|
|
1010
1038
|
this.#currentColumn.autoIncrement = true;
|
|
1011
1039
|
this.#currentColumn.primary = true;
|
|
1012
1040
|
this.#currentColumn.nullable = false;
|
|
1013
1041
|
}
|
|
1014
|
-
return
|
|
1042
|
+
return column;
|
|
1015
1043
|
}
|
|
1016
1044
|
}
|