@cleverbrush/knex-schema 3.1.0 → 4.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,4 +1,31 @@
1
- import type { AnySchemaBuilder, ArraySchemaBuilder, BooleanSchemaBuilder, DateSchemaBuilder, FunctionSchemaBuilder, GenericSchemaBuilder, NumberSchemaBuilder, ObjectSchemaBuilder, SchemaBuilder, StringSchemaBuilder, UnionSchemaBuilder } from '@cleverbrush/schema';
1
+ import type { AnySchemaBuilder, ArraySchemaBuilder, BooleanSchemaBuilder, DateSchemaBuilder, FunctionSchemaBuilder, GenericSchemaBuilder, NumberSchemaBuilder, ObjectSchemaBuilder, PropertyDescriptor, PropertyDescriptorTree, SchemaBuilder, StringSchemaBuilder, UnionSchemaBuilder } from '@cleverbrush/schema';
2
+ import { EXTRA_TYPE_BRAND, METHOD_LITERAL_BRAND } from '@cleverbrush/schema';
3
+ import type { ResolvedVariantConfig, ResolvedVariantRelationSpec, VariantStorageType } from './types.js';
4
+ export { EXTRA_TYPE_BRAND, METHOD_LITERAL_BRAND } from '@cleverbrush/schema';
5
+ /**
6
+ * Phantom-type brand placed on a column schema by `.primaryKey()`.
7
+ * Carried on the property schema's type so that {@link PrimaryKeyOf} can
8
+ * locate primary-key columns at the type level.
9
+ *
10
+ * @public
11
+ */
12
+ export declare const PRIMARY_KEY_BRAND: unique symbol;
13
+ /**
14
+ * Phantom-type brand placed on an object schema by `.hasPrimaryKey([cols])`
15
+ * to record the composite primary-key column tuple at the type level.
16
+ *
17
+ * @public
18
+ */
19
+ export declare const COMPOSITE_PRIMARY_KEY_BRAND: unique symbol;
20
+ /**
21
+ * Phantom-type brand placed on an `ObjectSchemaBuilder` by `.withVariants()`.
22
+ * The brand carries the discriminated-union result type so that
23
+ * `query(db, polymorphicSchema)` automatically infers the correct union type
24
+ * without any extra type annotation.
25
+ *
26
+ * @public
27
+ */
28
+ export declare const POLYMORPHIC_TYPE_BRAND: unique symbol;
2
29
  /**
3
30
  * Schema extension that adds database-mapping metadata to schema builders.
4
31
  *
@@ -99,6 +126,342 @@ export declare const dbExtension: import("@cleverbrush/schema").ExtensionDescrip
99
126
  hasTableName(this: ObjectSchemaBuilder<any, any, any, any, any, any, any>, name: string): ObjectSchemaBuilder<any, any, any, any, any, any, any>;
100
127
  };
101
128
  }>;
129
+ type FKAction = 'CASCADE' | 'SET NULL' | 'RESTRICT' | 'NO ACTION';
130
+ /**
131
+ * DDL and ORM extension that adds database DDL metadata, relationship
132
+ * definitions, and ORM conveniences to schema builders.
133
+ *
134
+ * Column-level methods: `.primaryKey()`, `.references()`, `.unique()`,
135
+ * `.index()`, `.defaultTo()`, `.columnType()`, `.check()`, `.defaultToRaw()`.
136
+ *
137
+ * Object-level methods: `.hasIndex()`, `.hasUnique()`, `.hasCheck()`,
138
+ * `.hasPrimaryKey()`, `.hasRawColumn()`, `.hasRawIndex()`, `.hasMany()`,
139
+ * `.hasOne()`, `.belongsTo()`, `.belongsToMany()`, `.hasTimestamps()`,
140
+ * `.softDelete()`, `.scope()`, `.defaultScope()`, `.beforeInsert()`,
141
+ * `.afterInsert()`, `.beforeUpdate()`, `.beforeDelete()`.
142
+ */
143
+ export declare const ddlExtension: import("@cleverbrush/schema").ExtensionDescriptor<{
144
+ number: {
145
+ /** Add a foreign key reference to another table.
146
+ * @param table - The referenced table name.
147
+ * @param column - The referenced column (defaults to `'id'`).
148
+ */
149
+ references(this: NumberSchemaBuilder<any, any, any, any, any>, table: string, column?: string): NumberSchemaBuilder<any, any, any, any, any>;
150
+ /** Set the ON DELETE action for a foreign key. */
151
+ onDelete(this: NumberSchemaBuilder<any, any, any, any, any>, action: FKAction): NumberSchemaBuilder<any, any, any, any, any>;
152
+ /** Set the ON UPDATE action for a foreign key. */
153
+ onUpdate(this: NumberSchemaBuilder<any, any, any, any, any>, action: FKAction): NumberSchemaBuilder<any, any, any, any, any>;
154
+ /** Set a default value for this column. */
155
+ defaultTo(this: NumberSchemaBuilder<any, any, any, any, any>, value: number | "auto_increment"): NumberSchemaBuilder<any, any, any, any, any>;
156
+ /** Add an index on this column.
157
+ * @param name - Optional index name.
158
+ */
159
+ index(this: NumberSchemaBuilder<any, any, any, any, any>, name?: string): NumberSchemaBuilder<any, any, any, any, any>;
160
+ /** Add a unique constraint on this column.
161
+ * @param name - Optional constraint name.
162
+ */
163
+ unique(this: NumberSchemaBuilder<any, any, any, any, any>, name?: string): NumberSchemaBuilder<any, any, any, any, any>;
164
+ /** Override the SQL column type (e.g. `'bigint'`, `'smallint'`). */
165
+ columnType(this: NumberSchemaBuilder<any, any, any, any, any>, type: string): NumberSchemaBuilder<any, any, any, any, any>;
166
+ /** Shorthand for `.columnType('bigint')`. */
167
+ bigint(this: NumberSchemaBuilder<any, any, any, any, any>): NumberSchemaBuilder<any, any, any, any, any>;
168
+ /** Shorthand for `.columnType('smallint')`. */
169
+ smallint(this: NumberSchemaBuilder<any, any, any, any, any>): NumberSchemaBuilder<any, any, any, any, any>;
170
+ /** Shorthand for `.columnType('decimal(p,s)')` — exact numeric.
171
+ * @param precision - Total digits.
172
+ * @param scale - Digits after decimal point.
173
+ */
174
+ decimal(this: NumberSchemaBuilder<any, any, any, any, any>, precision: number, scale: number): NumberSchemaBuilder<any, any, any, any, any>;
175
+ /** Set a raw SQL default expression.
176
+ * @param expression - Raw SQL expression (e.g. `"nextval('my_seq')"`).
177
+ */
178
+ defaultToRaw(this: NumberSchemaBuilder<any, any, any, any, any>, expression: string): NumberSchemaBuilder<any, any, any, any, any>;
179
+ /**
180
+ * Mark this integer column as an optimistic-concurrency row-version
181
+ * token checked by the ORM on every UPDATE / DELETE.
182
+ *
183
+ * A mismatch between the stored value and the snapshot taken at read
184
+ * time throws `ConcurrencyError`.
185
+ *
186
+ * @param opts.strategy
187
+ * - `'increment'` (default) — ORM adds 1 on each UPDATE.
188
+ * - `'manual'` — caller supplies the new value.
189
+ */
190
+ rowVersion(this: NumberSchemaBuilder<any, any, any, any, any>, opts?: {
191
+ strategy?: "increment" | "manual";
192
+ }): NumberSchemaBuilder<any, any, any, any, any>;
193
+ };
194
+ string: {
195
+ /** Override the SQL column type (e.g. `'text'`, `'uuid'`, `'jsonb'`, `'citext'`). */
196
+ columnType(this: StringSchemaBuilder<any, any, any, any, any>, type: string): StringSchemaBuilder<any, any, any, any, any>;
197
+ /** Shorthand for `.columnType('text')` — unlimited-length text. */
198
+ text(this: StringSchemaBuilder<any, any, any, any, any>): StringSchemaBuilder<any, any, any, any, any>;
199
+ /** Shorthand for `.columnType('uuid')` — UUID column type.
200
+ * Note: this sets the *storage type* — for UUID format validation use
201
+ * the schema-level `.uuid()` validator instead.
202
+ */
203
+ asUuid(this: StringSchemaBuilder<any, any, any, any, any>): StringSchemaBuilder<any, any, any, any, any>;
204
+ /** Shorthand for `.columnType('citext')` — case-insensitive text (Postgres). */
205
+ citext(this: StringSchemaBuilder<any, any, any, any, any>): StringSchemaBuilder<any, any, any, any, any>;
206
+ /** Shorthand for `.columnType('jsonb')` — binary JSON (Postgres). */
207
+ jsonb(this: StringSchemaBuilder<any, any, any, any, any>): StringSchemaBuilder<any, any, any, any, any>;
208
+ /** Shorthand for `.columnType('tsvector')` — full-text search vector (Postgres). */
209
+ tsvector(this: StringSchemaBuilder<any, any, any, any, any>): StringSchemaBuilder<any, any, any, any, any>;
210
+ /** Add a foreign key reference to another table. */
211
+ references(this: StringSchemaBuilder<any, any, any, any, any>, table: string, column?: string): StringSchemaBuilder<any, any, any, any, any>;
212
+ /** Set the ON DELETE action for a foreign key. */
213
+ onDelete(this: StringSchemaBuilder<any, any, any, any, any>, action: FKAction): StringSchemaBuilder<any, any, any, any, any>;
214
+ /** Set the ON UPDATE action for a foreign key. */
215
+ onUpdate(this: StringSchemaBuilder<any, any, any, any, any>, action: FKAction): StringSchemaBuilder<any, any, any, any, any>;
216
+ /** Add a unique constraint on this column. */
217
+ unique(this: StringSchemaBuilder<any, any, any, any, any>, name?: string): StringSchemaBuilder<any, any, any, any, any>;
218
+ /** Add an index on this column. */
219
+ index(this: StringSchemaBuilder<any, any, any, any, any>, name?: string): StringSchemaBuilder<any, any, any, any, any>;
220
+ /** Set a default value for this column. */
221
+ defaultTo(this: StringSchemaBuilder<any, any, any, any, any>, value: string): StringSchemaBuilder<any, any, any, any, any>;
222
+ /** Add a CHECK constraint with raw SQL.
223
+ * @param sql - SQL expression for the check (e.g. `"role IN ('user','admin')"`).
224
+ */
225
+ check(this: StringSchemaBuilder<any, any, any, any, any>, sql: string): StringSchemaBuilder<any, any, any, any, any>;
226
+ /** Set a raw SQL default expression. */
227
+ defaultToRaw(this: StringSchemaBuilder<any, any, any, any, any>, expression: string): StringSchemaBuilder<any, any, any, any, any>;
228
+ /**
229
+ * Mark this string column as an optimistic-concurrency row-version
230
+ * token (e.g. a UUID or opaque hash). Strategy is always `'manual'`
231
+ * — the caller must supply a new value on each UPDATE.
232
+ */
233
+ rowVersion(this: StringSchemaBuilder<any, any, any, any, any>): StringSchemaBuilder<any, any, any, any, any>;
234
+ };
235
+ boolean: {
236
+ /** Set a default value for this column. */
237
+ defaultTo(this: BooleanSchemaBuilder<any, any, any, any, any, any, any>, value: boolean): BooleanSchemaBuilder<any, any, any, any, any, any, any>;
238
+ /** Override the SQL column type (e.g. `'smallint'`, `'integer'`). */
239
+ columnType(this: BooleanSchemaBuilder<any, any, any, any, any, any, any>, type: string): BooleanSchemaBuilder<any, any, any, any, any, any, any>;
240
+ /** Add an index on this column. */
241
+ index(this: BooleanSchemaBuilder<any, any, any, any, any, any, any>, name?: string): BooleanSchemaBuilder<any, any, any, any, any, any, any>;
242
+ /** Add a unique constraint on this column. */
243
+ unique(this: BooleanSchemaBuilder<any, any, any, any, any, any, any>, name?: string): BooleanSchemaBuilder<any, any, any, any, any, any, any>;
244
+ };
245
+ date: {
246
+ /** Set a default value (`'now'` for current timestamp). */
247
+ defaultTo(this: DateSchemaBuilder<any, any, any, any, any>, value: "now"): DateSchemaBuilder<any, any, any, any, any>;
248
+ /** Override the SQL column type
249
+ * (e.g. `'timestamptz'`, `'date'`, `'time'`).
250
+ */
251
+ columnType(this: DateSchemaBuilder<any, any, any, any, any>, type: string): DateSchemaBuilder<any, any, any, any, any>;
252
+ /** Add an index on this column. */
253
+ index(this: DateSchemaBuilder<any, any, any, any, any>, name?: string): DateSchemaBuilder<any, any, any, any, any>;
254
+ /** Set a raw SQL default expression. */
255
+ defaultToRaw(this: DateSchemaBuilder<any, any, any, any, any>, expression: string): DateSchemaBuilder<any, any, any, any, any>;
256
+ /** Shorthand for `.columnType('timestamptz')`. */
257
+ timestamptz(this: DateSchemaBuilder<any, any, any, any, any>): DateSchemaBuilder<any, any, any, any, any>;
258
+ /** Shorthand for `.columnType('date')` (date-only, no time). */
259
+ dateOnly(this: DateSchemaBuilder<any, any, any, any, any>): DateSchemaBuilder<any, any, any, any, any>;
260
+ /**
261
+ * Mark this date column as an optimistic-concurrency row-version
262
+ * token (timestamp-based). Strategy is always `'timestamp'` —
263
+ * the ORM sets the value to `new Date()` on each UPDATE.
264
+ */
265
+ rowVersion(this: DateSchemaBuilder<any, any, any, any, any>): DateSchemaBuilder<any, any, any, any, any>;
266
+ };
267
+ object: {
268
+ /** Override the SQL column type for an object property stored inline.
269
+ * Object-typed properties default to `jsonb` when used as columns in
270
+ * a parent schema's table.
271
+ */
272
+ columnType(this: ObjectSchemaBuilder<any, any, any, any, any, any, any>, type: string): ObjectSchemaBuilder<any, any, any, any, any, any, any>;
273
+ /** Shorthand for `.columnType('jsonb')` — store this nested object as
274
+ * a `jsonb` column (Postgres). Nested objects already default to
275
+ * `jsonb` in DDL; calling `.jsonb()` makes the intent explicit.
276
+ */
277
+ jsonb(this: ObjectSchemaBuilder<any, any, any, any, any, any, any>): ObjectSchemaBuilder<any, any, any, any, any, any, any>;
278
+ /** Shorthand for `.columnType('json')` — store this nested object as
279
+ * a plain `json` column (Postgres / MySQL).
280
+ */
281
+ json(this: ObjectSchemaBuilder<any, any, any, any, any, any, any>): ObjectSchemaBuilder<any, any, any, any, any, any, any>;
282
+ /** Add a composite index on multiple columns.
283
+ * @param columns - Column names to index.
284
+ * @param opts - Optional index name and unique flag.
285
+ */
286
+ hasIndex(this: ObjectSchemaBuilder<any, any, any, any, any, any, any>, columns: string[], opts?: {
287
+ name?: string;
288
+ unique?: boolean;
289
+ }): ObjectSchemaBuilder<any, any, any, any, any, any, any>;
290
+ /** Add a composite unique constraint.
291
+ * @param columns - Column names.
292
+ * @param name - Optional constraint name.
293
+ */
294
+ hasUnique(this: ObjectSchemaBuilder<any, any, any, any, any, any, any>, columns: string[], name?: string): ObjectSchemaBuilder<any, any, any, any, any, any, any>;
295
+ /** Add a table-level CHECK constraint.
296
+ * @param sql - Raw SQL expression for the check.
297
+ */
298
+ hasCheck(this: ObjectSchemaBuilder<any, any, any, any, any, any, any>, sql: string): ObjectSchemaBuilder<any, any, any, any, any, any, any>;
299
+ /** Add a raw SQL column definition not backed by a schema property.
300
+ * @param name - Column name.
301
+ * @param definition - SQL type and constraints (e.g. `"tsvector GENERATED ALWAYS AS (...) STORED"`).
302
+ */
303
+ hasRawColumn(this: ObjectSchemaBuilder<any, any, any, any, any, any, any>, name: string, definition: string): ObjectSchemaBuilder<any, any, any, any, any, any, any>;
304
+ /** Add a raw SQL index statement executed after table creation.
305
+ * @param sql - Full `CREATE INDEX` SQL statement.
306
+ */
307
+ hasRawIndex(this: ObjectSchemaBuilder<any, any, any, any, any, any, any>, sql: string): ObjectSchemaBuilder<any, any, any, any, any, any, any>;
308
+ /** Define a one-to-many relationship.
309
+ * @param name - Relation name used with `include()`.
310
+ * @param opts - `{ schema, foreignKey }` — `foreignKey` is a ColumnRef on the foreign schema.
311
+ */
312
+ hasMany(this: ObjectSchemaBuilder<any, any, any, any, any, any, any>, name: string, opts: {
313
+ schema: any;
314
+ foreignKey: any;
315
+ }): ObjectSchemaBuilder<any, any, any, any, any, any, any>;
316
+ /** Define a one-to-one relationship (FK on foreign table).
317
+ * @param name - Relation name used with `include()`.
318
+ * @param opts - `{ schema, foreignKey }` — `foreignKey` is a ColumnRef on the foreign schema.
319
+ */
320
+ hasOne(this: ObjectSchemaBuilder<any, any, any, any, any, any, any>, name: string, opts: {
321
+ schema: any;
322
+ foreignKey: any;
323
+ }): ObjectSchemaBuilder<any, any, any, any, any, any, any>;
324
+ /** Define a belongs-to relationship (FK on local table).
325
+ * @param name - Relation name used with `include()`.
326
+ * @param opts - `{ schema, foreignKey }` — `foreignKey` is a ColumnRef on the local schema.
327
+ */
328
+ belongsTo(this: ObjectSchemaBuilder<any, any, any, any, any, any, any>, name: string, opts: {
329
+ schema: any;
330
+ foreignKey: any;
331
+ }): ObjectSchemaBuilder<any, any, any, any, any, any, any>;
332
+ /** Define a many-to-many relationship through a pivot table.
333
+ * @param name - Relation name used with `include()`.
334
+ * @param opts - `{ schema, through: { table, localKey, foreignKey } }`.
335
+ */
336
+ belongsToMany(this: ObjectSchemaBuilder<any, any, any, any, any, any, any>, name: string, opts: {
337
+ schema: any;
338
+ through: {
339
+ table: string;
340
+ localKey: string;
341
+ foreignKey: string;
342
+ };
343
+ }): ObjectSchemaBuilder<any, any, any, any, any, any, any>;
344
+ /** Auto-add `created_at` and `updated_at` timestamp columns.
345
+ * @param opts - Optional custom column names.
346
+ */
347
+ hasTimestamps(this: ObjectSchemaBuilder<any, any, any, any, any, any, any>, opts?: {
348
+ createdAt?: string;
349
+ updatedAt?: string;
350
+ }): ObjectSchemaBuilder<any, any, any, any, any, any, any>;
351
+ /** Enable soft deletes (adds a `deleted_at` column, auto-filters queries).
352
+ * @param opts - Optional custom column name.
353
+ */
354
+ softDelete(this: ObjectSchemaBuilder<any, any, any, any, any, any, any>, opts?: {
355
+ column?: string;
356
+ }): ObjectSchemaBuilder<any, any, any, any, any, any, any>;
357
+ /** Register a named query scope.
358
+ * @param name - Scope name to use with `.scoped(name)`.
359
+ * @param fn - Function that receives a `SchemaQueryBuilder` and applies filters.
360
+ */
361
+ scope<N extends string>(this: ObjectSchemaBuilder<any, any, any, any, any, any, any>, name: N, fn: Function): ObjectSchemaBuilder<any, any, any, any, any, any, any> & {
362
+ readonly [METHOD_LITERAL_BRAND]?: N;
363
+ };
364
+ /**
365
+ * Register a **named projection** — a reusable column subset that can be
366
+ * applied at query time via `.projected(name)`.
367
+ *
368
+ * When a projection is applied the query builder:
369
+ * 1. Issues `SELECT <cols>` instead of `SELECT *`.
370
+ * 2. Narrows the TypeScript result row type to `Pick<Row, Keys>`.
371
+ *
372
+ * Columns are passed as **rest parameters**. Each argument can be either:
373
+ *
374
+ * - A **string** literal of a property name (autocompleted against the
375
+ * schema's properties):
376
+ * ```ts
377
+ * .projection('summary', 'id', 'title', 'completed')
378
+ * ```
379
+ * - An **accessor callback** (refactor-safe — renaming a property
380
+ * updates the projection automatically):
381
+ * ```ts
382
+ * .projection('listView', t => t.id, t => t.title, t => t.userId)
383
+ * ```
384
+ *
385
+ * The two forms can be mixed freely:
386
+ * ```ts
387
+ * .projection('mixed', 'id', t => t.title)
388
+ * ```
389
+ *
390
+ * The literal property keys flow through the type system, so
391
+ * `.projected('listView')` still narrows the result type to
392
+ * `Pick<Row, 'id' | 'title' | 'userId'>`.
393
+ *
394
+ * @param name - Unique projection name (used with `.projected()`).
395
+ * @param columns - One argument per column: either a property name
396
+ * string or a `t => t.propName` accessor callback.
397
+ *
398
+ * @example
399
+ * ```ts
400
+ * const PostSchema = object({ id: number(), title: string(), body: string() })
401
+ * .hasTableName('posts')
402
+ * .projection('summary', 'id', 'title')
403
+ * .projection('detail', t => t.id, t => t.title, t => t.body);
404
+ *
405
+ * // Later:
406
+ * const rows = await query(db, PostSchema).projected('summary');
407
+ * // rows: Array<Pick<Post, 'id' | 'title'>>
408
+ * ```
409
+ *
410
+ * @see {@link SchemaQueryBuilder.projected}
411
+ */
412
+ projection<TProperties extends Record<string, SchemaBuilder<any, any, any, any, any>>, const N extends string, const TKey extends keyof TProperties & string>(this: ObjectSchemaBuilder<TProperties, any, any, any, any, any, any>, name: N, ...columns: ReadonlyArray<TKey | ((t: PropertyDescriptorTree<ObjectSchemaBuilder<TProperties, any, any, any, any, any, any>, ObjectSchemaBuilder<TProperties, any, any, any, any, any, any>>) => PropertyDescriptor<any, any, any, TKey>)>): ObjectSchemaBuilder<TProperties, any, any, any, any, any, any> & {
413
+ readonly [EXTRA_TYPE_BRAND]?: { [P in N]: readonly TKey[]; };
414
+ };
415
+ /** Set a default scope applied to all queries unless `.unscoped()` is called.
416
+ * @param fn - Function that receives a `SchemaQueryBuilder` and applies filters.
417
+ */
418
+ defaultScope(this: ObjectSchemaBuilder<any, any, any, any, any, any, any>, fn: Function): ObjectSchemaBuilder<any, any, any, any, any, any, any>;
419
+ /** Register a before-insert lifecycle hook.
420
+ * @param fn - Async function `(data) => data` called before inserting.
421
+ */
422
+ beforeInsert(this: ObjectSchemaBuilder<any, any, any, any, any, any, any>, fn: Function): ObjectSchemaBuilder<any, any, any, any, any, any, any>;
423
+ /** Register an after-insert lifecycle hook.
424
+ * @param fn - Async function `(row)` called after inserting.
425
+ */
426
+ afterInsert(this: ObjectSchemaBuilder<any, any, any, any, any, any, any>, fn: Function): ObjectSchemaBuilder<any, any, any, any, any, any, any>;
427
+ /** Register a before-update lifecycle hook.
428
+ * @param fn - Async function `(data) => data` called before updating.
429
+ */
430
+ beforeUpdate(this: ObjectSchemaBuilder<any, any, any, any, any, any, any>, fn: Function): ObjectSchemaBuilder<any, any, any, any, any, any, any>;
431
+ /** Register a before-delete lifecycle hook.
432
+ * @param fn - Async function `(query)` called before deleting.
433
+ */
434
+ beforeDelete(this: ObjectSchemaBuilder<any, any, any, any, any, any, any>, fn: Function): ObjectSchemaBuilder<any, any, any, any, any, any, any>;
435
+ };
436
+ }>;
437
+ /**
438
+ * @internal Input to {@link applyVariantsToSchema}: a single resolved variant
439
+ * entry, as produced by `Entity.ctiVariant()` / `Entity.stiVariant()`.
440
+ */
441
+ export interface VariantInputForResolver {
442
+ /** CTI-only: FK column name on the variant table that joins back to base PK. */
443
+ foreignKeyColumn?: string;
444
+ /** Variant body schema (CTI table or STI extras). */
445
+ schema: ObjectSchemaBuilder<any, any, any, any, any, any, any>;
446
+ storage: VariantStorageType;
447
+ allowOrphan?: boolean;
448
+ enforceCheck?: boolean;
449
+ /**
450
+ * Variant-scoped relations (already resolved to FK column names). When
451
+ * the variant entry is sourced from another `Entity`, these are read
452
+ * from that entity's `'relations'` extension and passed in here.
453
+ */
454
+ relations?: ResolvedVariantRelationSpec[];
455
+ }
456
+ /**
457
+ * @internal Validate + apply a fully-resolved variant config to a base
458
+ * schema. Stores the `'variants'` and `'polymorphicVariants'` extensions
459
+ * read by {@link SchemaQueryBuilder}.
460
+ *
461
+ * Called by the {@link Entity} chain (`.discriminator().ctiVariant().stiVariant()`).
462
+ * Replaces the previous schema-level `.withVariants()` method.
463
+ */
464
+ export declare function applyVariantsToSchema(baseSchema: ObjectSchemaBuilder<any, any, any, any, any, any, any>, discriminatorKey: string, variants: Record<string, VariantInputForResolver>): ObjectSchemaBuilder<any, any, any, any, any, any, any>;
102
465
  export declare const string: {
103
466
  (): import("@cleverbrush/schema").CleanExtended<StringSchemaBuilder<string, true, false, false, {
104
467
  email(this: StringSchemaBuilder, errorMessage?: import("@cleverbrush/schema").ValidationErrorMessageProvider<StringSchemaBuilder>): StringSchemaBuilder<string, true, false, false, {}>;
@@ -124,6 +487,46 @@ export declare const string: {
124
487
  * @param name - The SQL column name.
125
488
  */
126
489
  hasColumnName(this: StringSchemaBuilder<any, any, any, any, any>, name: string): SchemaBuilder<any, any, any, false, {}>;
490
+ } & {
491
+ /** Override the SQL column type (e.g. `'text'`, `'uuid'`, `'jsonb'`, `'citext'`). */
492
+ columnType(this: StringSchemaBuilder<any, any, any, any, any>, type: string): StringSchemaBuilder<any, any, any, any, any>;
493
+ /** Shorthand for `.columnType('text')` — unlimited-length text. */
494
+ text(this: StringSchemaBuilder<any, any, any, any, any>): StringSchemaBuilder<any, any, any, any, any>;
495
+ /** Shorthand for `.columnType('uuid')` — UUID column type.
496
+ * Note: this sets the *storage type* — for UUID format validation use
497
+ * the schema-level `.uuid()` validator instead.
498
+ */
499
+ asUuid(this: StringSchemaBuilder<any, any, any, any, any>): StringSchemaBuilder<any, any, any, any, any>;
500
+ /** Shorthand for `.columnType('citext')` — case-insensitive text (Postgres). */
501
+ citext(this: StringSchemaBuilder<any, any, any, any, any>): StringSchemaBuilder<any, any, any, any, any>;
502
+ /** Shorthand for `.columnType('jsonb')` — binary JSON (Postgres). */
503
+ jsonb(this: StringSchemaBuilder<any, any, any, any, any>): StringSchemaBuilder<any, any, any, any, any>;
504
+ /** Shorthand for `.columnType('tsvector')` — full-text search vector (Postgres). */
505
+ tsvector(this: StringSchemaBuilder<any, any, any, any, any>): StringSchemaBuilder<any, any, any, any, any>;
506
+ /** Add a foreign key reference to another table. */
507
+ references(this: StringSchemaBuilder<any, any, any, any, any>, table: string, column?: string): StringSchemaBuilder<any, any, any, any, any>;
508
+ /** Set the ON DELETE action for a foreign key. */
509
+ onDelete(this: StringSchemaBuilder<any, any, any, any, any>, action: FKAction): StringSchemaBuilder<any, any, any, any, any>;
510
+ /** Set the ON UPDATE action for a foreign key. */
511
+ onUpdate(this: StringSchemaBuilder<any, any, any, any, any>, action: FKAction): StringSchemaBuilder<any, any, any, any, any>;
512
+ /** Add a unique constraint on this column. */
513
+ unique(this: StringSchemaBuilder<any, any, any, any, any>, name?: string): StringSchemaBuilder<any, any, any, any, any>;
514
+ /** Add an index on this column. */
515
+ index(this: StringSchemaBuilder<any, any, any, any, any>, name?: string): StringSchemaBuilder<any, any, any, any, any>;
516
+ /** Set a default value for this column. */
517
+ defaultTo(this: StringSchemaBuilder<any, any, any, any, any>, value: string): StringSchemaBuilder<any, any, any, any, any>;
518
+ /** Add a CHECK constraint with raw SQL.
519
+ * @param sql - SQL expression for the check (e.g. `"role IN ('user','admin')"`).
520
+ */
521
+ check(this: StringSchemaBuilder<any, any, any, any, any>, sql: string): StringSchemaBuilder<any, any, any, any, any>;
522
+ /** Set a raw SQL default expression. */
523
+ defaultToRaw(this: StringSchemaBuilder<any, any, any, any, any>, expression: string): StringSchemaBuilder<any, any, any, any, any>;
524
+ /**
525
+ * Mark this string column as an optimistic-concurrency row-version
526
+ * token (e.g. a UUID or opaque hash). Strategy is always `'manual'`
527
+ * — the caller must supply a new value on each UPDATE.
528
+ */
529
+ rowVersion(this: StringSchemaBuilder<any, any, any, any, any>): StringSchemaBuilder<any, any, any, any, any>;
127
530
  }>, {
128
531
  email(this: StringSchemaBuilder, errorMessage?: import("@cleverbrush/schema").ValidationErrorMessageProvider<StringSchemaBuilder>): StringSchemaBuilder<string, true, false, false, {}>;
129
532
  url(this: StringSchemaBuilder, optsOrError?: {
@@ -148,6 +551,46 @@ export declare const string: {
148
551
  * @param name - The SQL column name.
149
552
  */
150
553
  hasColumnName(this: StringSchemaBuilder<any, any, any, any, any>, name: string): SchemaBuilder<any, any, any, false, {}>;
554
+ } & {
555
+ /** Override the SQL column type (e.g. `'text'`, `'uuid'`, `'jsonb'`, `'citext'`). */
556
+ columnType(this: StringSchemaBuilder<any, any, any, any, any>, type: string): StringSchemaBuilder<any, any, any, any, any>;
557
+ /** Shorthand for `.columnType('text')` — unlimited-length text. */
558
+ text(this: StringSchemaBuilder<any, any, any, any, any>): StringSchemaBuilder<any, any, any, any, any>;
559
+ /** Shorthand for `.columnType('uuid')` — UUID column type.
560
+ * Note: this sets the *storage type* — for UUID format validation use
561
+ * the schema-level `.uuid()` validator instead.
562
+ */
563
+ asUuid(this: StringSchemaBuilder<any, any, any, any, any>): StringSchemaBuilder<any, any, any, any, any>;
564
+ /** Shorthand for `.columnType('citext')` — case-insensitive text (Postgres). */
565
+ citext(this: StringSchemaBuilder<any, any, any, any, any>): StringSchemaBuilder<any, any, any, any, any>;
566
+ /** Shorthand for `.columnType('jsonb')` — binary JSON (Postgres). */
567
+ jsonb(this: StringSchemaBuilder<any, any, any, any, any>): StringSchemaBuilder<any, any, any, any, any>;
568
+ /** Shorthand for `.columnType('tsvector')` — full-text search vector (Postgres). */
569
+ tsvector(this: StringSchemaBuilder<any, any, any, any, any>): StringSchemaBuilder<any, any, any, any, any>;
570
+ /** Add a foreign key reference to another table. */
571
+ references(this: StringSchemaBuilder<any, any, any, any, any>, table: string, column?: string): StringSchemaBuilder<any, any, any, any, any>;
572
+ /** Set the ON DELETE action for a foreign key. */
573
+ onDelete(this: StringSchemaBuilder<any, any, any, any, any>, action: FKAction): StringSchemaBuilder<any, any, any, any, any>;
574
+ /** Set the ON UPDATE action for a foreign key. */
575
+ onUpdate(this: StringSchemaBuilder<any, any, any, any, any>, action: FKAction): StringSchemaBuilder<any, any, any, any, any>;
576
+ /** Add a unique constraint on this column. */
577
+ unique(this: StringSchemaBuilder<any, any, any, any, any>, name?: string): StringSchemaBuilder<any, any, any, any, any>;
578
+ /** Add an index on this column. */
579
+ index(this: StringSchemaBuilder<any, any, any, any, any>, name?: string): StringSchemaBuilder<any, any, any, any, any>;
580
+ /** Set a default value for this column. */
581
+ defaultTo(this: StringSchemaBuilder<any, any, any, any, any>, value: string): StringSchemaBuilder<any, any, any, any, any>;
582
+ /** Add a CHECK constraint with raw SQL.
583
+ * @param sql - SQL expression for the check (e.g. `"role IN ('user','admin')"`).
584
+ */
585
+ check(this: StringSchemaBuilder<any, any, any, any, any>, sql: string): StringSchemaBuilder<any, any, any, any, any>;
586
+ /** Set a raw SQL default expression. */
587
+ defaultToRaw(this: StringSchemaBuilder<any, any, any, any, any>, expression: string): StringSchemaBuilder<any, any, any, any, any>;
588
+ /**
589
+ * Mark this string column as an optimistic-concurrency row-version
590
+ * token (e.g. a UUID or opaque hash). Strategy is always `'manual'`
591
+ * — the caller must supply a new value on each UPDATE.
592
+ */
593
+ rowVersion(this: StringSchemaBuilder<any, any, any, any, any>): StringSchemaBuilder<any, any, any, any, any>;
151
594
  }>;
152
595
  <T extends string>(equals: T): import("@cleverbrush/schema").CleanExtended<StringSchemaBuilder<T, true, false, false, {
153
596
  email(this: StringSchemaBuilder, errorMessage?: import("@cleverbrush/schema").ValidationErrorMessageProvider<StringSchemaBuilder>): StringSchemaBuilder<string, true, false, false, {}>;
@@ -173,6 +616,46 @@ export declare const string: {
173
616
  * @param name - The SQL column name.
174
617
  */
175
618
  hasColumnName(this: StringSchemaBuilder<any, any, any, any, any>, name: string): SchemaBuilder<any, any, any, false, {}>;
619
+ } & {
620
+ /** Override the SQL column type (e.g. `'text'`, `'uuid'`, `'jsonb'`, `'citext'`). */
621
+ columnType(this: StringSchemaBuilder<any, any, any, any, any>, type: string): StringSchemaBuilder<any, any, any, any, any>;
622
+ /** Shorthand for `.columnType('text')` — unlimited-length text. */
623
+ text(this: StringSchemaBuilder<any, any, any, any, any>): StringSchemaBuilder<any, any, any, any, any>;
624
+ /** Shorthand for `.columnType('uuid')` — UUID column type.
625
+ * Note: this sets the *storage type* — for UUID format validation use
626
+ * the schema-level `.uuid()` validator instead.
627
+ */
628
+ asUuid(this: StringSchemaBuilder<any, any, any, any, any>): StringSchemaBuilder<any, any, any, any, any>;
629
+ /** Shorthand for `.columnType('citext')` — case-insensitive text (Postgres). */
630
+ citext(this: StringSchemaBuilder<any, any, any, any, any>): StringSchemaBuilder<any, any, any, any, any>;
631
+ /** Shorthand for `.columnType('jsonb')` — binary JSON (Postgres). */
632
+ jsonb(this: StringSchemaBuilder<any, any, any, any, any>): StringSchemaBuilder<any, any, any, any, any>;
633
+ /** Shorthand for `.columnType('tsvector')` — full-text search vector (Postgres). */
634
+ tsvector(this: StringSchemaBuilder<any, any, any, any, any>): StringSchemaBuilder<any, any, any, any, any>;
635
+ /** Add a foreign key reference to another table. */
636
+ references(this: StringSchemaBuilder<any, any, any, any, any>, table: string, column?: string): StringSchemaBuilder<any, any, any, any, any>;
637
+ /** Set the ON DELETE action for a foreign key. */
638
+ onDelete(this: StringSchemaBuilder<any, any, any, any, any>, action: FKAction): StringSchemaBuilder<any, any, any, any, any>;
639
+ /** Set the ON UPDATE action for a foreign key. */
640
+ onUpdate(this: StringSchemaBuilder<any, any, any, any, any>, action: FKAction): StringSchemaBuilder<any, any, any, any, any>;
641
+ /** Add a unique constraint on this column. */
642
+ unique(this: StringSchemaBuilder<any, any, any, any, any>, name?: string): StringSchemaBuilder<any, any, any, any, any>;
643
+ /** Add an index on this column. */
644
+ index(this: StringSchemaBuilder<any, any, any, any, any>, name?: string): StringSchemaBuilder<any, any, any, any, any>;
645
+ /** Set a default value for this column. */
646
+ defaultTo(this: StringSchemaBuilder<any, any, any, any, any>, value: string): StringSchemaBuilder<any, any, any, any, any>;
647
+ /** Add a CHECK constraint with raw SQL.
648
+ * @param sql - SQL expression for the check (e.g. `"role IN ('user','admin')"`).
649
+ */
650
+ check(this: StringSchemaBuilder<any, any, any, any, any>, sql: string): StringSchemaBuilder<any, any, any, any, any>;
651
+ /** Set a raw SQL default expression. */
652
+ defaultToRaw(this: StringSchemaBuilder<any, any, any, any, any>, expression: string): StringSchemaBuilder<any, any, any, any, any>;
653
+ /**
654
+ * Mark this string column as an optimistic-concurrency row-version
655
+ * token (e.g. a UUID or opaque hash). Strategy is always `'manual'`
656
+ * — the caller must supply a new value on each UPDATE.
657
+ */
658
+ rowVersion(this: StringSchemaBuilder<any, any, any, any, any>): StringSchemaBuilder<any, any, any, any, any>;
176
659
  }>, {
177
660
  email(this: StringSchemaBuilder, errorMessage?: import("@cleverbrush/schema").ValidationErrorMessageProvider<StringSchemaBuilder>): StringSchemaBuilder<string, true, false, false, {}>;
178
661
  url(this: StringSchemaBuilder, optsOrError?: {
@@ -197,6 +680,46 @@ export declare const string: {
197
680
  * @param name - The SQL column name.
198
681
  */
199
682
  hasColumnName(this: StringSchemaBuilder<any, any, any, any, any>, name: string): SchemaBuilder<any, any, any, false, {}>;
683
+ } & {
684
+ /** Override the SQL column type (e.g. `'text'`, `'uuid'`, `'jsonb'`, `'citext'`). */
685
+ columnType(this: StringSchemaBuilder<any, any, any, any, any>, type: string): StringSchemaBuilder<any, any, any, any, any>;
686
+ /** Shorthand for `.columnType('text')` — unlimited-length text. */
687
+ text(this: StringSchemaBuilder<any, any, any, any, any>): StringSchemaBuilder<any, any, any, any, any>;
688
+ /** Shorthand for `.columnType('uuid')` — UUID column type.
689
+ * Note: this sets the *storage type* — for UUID format validation use
690
+ * the schema-level `.uuid()` validator instead.
691
+ */
692
+ asUuid(this: StringSchemaBuilder<any, any, any, any, any>): StringSchemaBuilder<any, any, any, any, any>;
693
+ /** Shorthand for `.columnType('citext')` — case-insensitive text (Postgres). */
694
+ citext(this: StringSchemaBuilder<any, any, any, any, any>): StringSchemaBuilder<any, any, any, any, any>;
695
+ /** Shorthand for `.columnType('jsonb')` — binary JSON (Postgres). */
696
+ jsonb(this: StringSchemaBuilder<any, any, any, any, any>): StringSchemaBuilder<any, any, any, any, any>;
697
+ /** Shorthand for `.columnType('tsvector')` — full-text search vector (Postgres). */
698
+ tsvector(this: StringSchemaBuilder<any, any, any, any, any>): StringSchemaBuilder<any, any, any, any, any>;
699
+ /** Add a foreign key reference to another table. */
700
+ references(this: StringSchemaBuilder<any, any, any, any, any>, table: string, column?: string): StringSchemaBuilder<any, any, any, any, any>;
701
+ /** Set the ON DELETE action for a foreign key. */
702
+ onDelete(this: StringSchemaBuilder<any, any, any, any, any>, action: FKAction): StringSchemaBuilder<any, any, any, any, any>;
703
+ /** Set the ON UPDATE action for a foreign key. */
704
+ onUpdate(this: StringSchemaBuilder<any, any, any, any, any>, action: FKAction): StringSchemaBuilder<any, any, any, any, any>;
705
+ /** Add a unique constraint on this column. */
706
+ unique(this: StringSchemaBuilder<any, any, any, any, any>, name?: string): StringSchemaBuilder<any, any, any, any, any>;
707
+ /** Add an index on this column. */
708
+ index(this: StringSchemaBuilder<any, any, any, any, any>, name?: string): StringSchemaBuilder<any, any, any, any, any>;
709
+ /** Set a default value for this column. */
710
+ defaultTo(this: StringSchemaBuilder<any, any, any, any, any>, value: string): StringSchemaBuilder<any, any, any, any, any>;
711
+ /** Add a CHECK constraint with raw SQL.
712
+ * @param sql - SQL expression for the check (e.g. `"role IN ('user','admin')"`).
713
+ */
714
+ check(this: StringSchemaBuilder<any, any, any, any, any>, sql: string): StringSchemaBuilder<any, any, any, any, any>;
715
+ /** Set a raw SQL default expression. */
716
+ defaultToRaw(this: StringSchemaBuilder<any, any, any, any, any>, expression: string): StringSchemaBuilder<any, any, any, any, any>;
717
+ /**
718
+ * Mark this string column as an optimistic-concurrency row-version
719
+ * token (e.g. a UUID or opaque hash). Strategy is always `'manual'`
720
+ * — the caller must supply a new value on each UPDATE.
721
+ */
722
+ rowVersion(this: StringSchemaBuilder<any, any, any, any, any>): StringSchemaBuilder<any, any, any, any, any>;
200
723
  }>;
201
724
  };
202
725
  export declare const number: {
@@ -212,6 +735,55 @@ export declare const number: {
212
735
  * @param name - The SQL column name.
213
736
  */
214
737
  hasColumnName(this: NumberSchemaBuilder<any, any, any, any, any>, name: string): SchemaBuilder<any, any, any, false, {}>;
738
+ } & {
739
+ /** Add a foreign key reference to another table.
740
+ * @param table - The referenced table name.
741
+ * @param column - The referenced column (defaults to `'id'`).
742
+ */
743
+ references(this: NumberSchemaBuilder<any, any, any, any, any>, table: string, column?: string): NumberSchemaBuilder<any, any, any, any, any>;
744
+ /** Set the ON DELETE action for a foreign key. */
745
+ onDelete(this: NumberSchemaBuilder<any, any, any, any, any>, action: FKAction): NumberSchemaBuilder<any, any, any, any, any>;
746
+ /** Set the ON UPDATE action for a foreign key. */
747
+ onUpdate(this: NumberSchemaBuilder<any, any, any, any, any>, action: FKAction): NumberSchemaBuilder<any, any, any, any, any>;
748
+ /** Set a default value for this column. */
749
+ defaultTo(this: NumberSchemaBuilder<any, any, any, any, any>, value: number | "auto_increment"): NumberSchemaBuilder<any, any, any, any, any>;
750
+ /** Add an index on this column.
751
+ * @param name - Optional index name.
752
+ */
753
+ index(this: NumberSchemaBuilder<any, any, any, any, any>, name?: string): NumberSchemaBuilder<any, any, any, any, any>;
754
+ /** Add a unique constraint on this column.
755
+ * @param name - Optional constraint name.
756
+ */
757
+ unique(this: NumberSchemaBuilder<any, any, any, any, any>, name?: string): NumberSchemaBuilder<any, any, any, any, any>;
758
+ /** Override the SQL column type (e.g. `'bigint'`, `'smallint'`). */
759
+ columnType(this: NumberSchemaBuilder<any, any, any, any, any>, type: string): NumberSchemaBuilder<any, any, any, any, any>;
760
+ /** Shorthand for `.columnType('bigint')`. */
761
+ bigint(this: NumberSchemaBuilder<any, any, any, any, any>): NumberSchemaBuilder<any, any, any, any, any>;
762
+ /** Shorthand for `.columnType('smallint')`. */
763
+ smallint(this: NumberSchemaBuilder<any, any, any, any, any>): NumberSchemaBuilder<any, any, any, any, any>;
764
+ /** Shorthand for `.columnType('decimal(p,s)')` — exact numeric.
765
+ * @param precision - Total digits.
766
+ * @param scale - Digits after decimal point.
767
+ */
768
+ decimal(this: NumberSchemaBuilder<any, any, any, any, any>, precision: number, scale: number): NumberSchemaBuilder<any, any, any, any, any>;
769
+ /** Set a raw SQL default expression.
770
+ * @param expression - Raw SQL expression (e.g. `"nextval('my_seq')"`).
771
+ */
772
+ defaultToRaw(this: NumberSchemaBuilder<any, any, any, any, any>, expression: string): NumberSchemaBuilder<any, any, any, any, any>;
773
+ /**
774
+ * Mark this integer column as an optimistic-concurrency row-version
775
+ * token checked by the ORM on every UPDATE / DELETE.
776
+ *
777
+ * A mismatch between the stored value and the snapshot taken at read
778
+ * time throws `ConcurrencyError`.
779
+ *
780
+ * @param opts.strategy
781
+ * - `'increment'` (default) — ORM adds 1 on each UPDATE.
782
+ * - `'manual'` — caller supplies the new value.
783
+ */
784
+ rowVersion(this: NumberSchemaBuilder<any, any, any, any, any>, opts?: {
785
+ strategy?: "increment" | "manual";
786
+ }): NumberSchemaBuilder<any, any, any, any, any>;
215
787
  }>, {
216
788
  positive(this: NumberSchemaBuilder, errorMessage?: import("@cleverbrush/schema").ValidationErrorMessageProvider<NumberSchemaBuilder>): NumberSchemaBuilder<number, true, false, false, {}>;
217
789
  negative(this: NumberSchemaBuilder, errorMessage?: import("@cleverbrush/schema").ValidationErrorMessageProvider<NumberSchemaBuilder>): NumberSchemaBuilder<number, true, false, false, {}>;
@@ -224,6 +796,55 @@ export declare const number: {
224
796
  * @param name - The SQL column name.
225
797
  */
226
798
  hasColumnName(this: NumberSchemaBuilder<any, any, any, any, any>, name: string): SchemaBuilder<any, any, any, false, {}>;
799
+ } & {
800
+ /** Add a foreign key reference to another table.
801
+ * @param table - The referenced table name.
802
+ * @param column - The referenced column (defaults to `'id'`).
803
+ */
804
+ references(this: NumberSchemaBuilder<any, any, any, any, any>, table: string, column?: string): NumberSchemaBuilder<any, any, any, any, any>;
805
+ /** Set the ON DELETE action for a foreign key. */
806
+ onDelete(this: NumberSchemaBuilder<any, any, any, any, any>, action: FKAction): NumberSchemaBuilder<any, any, any, any, any>;
807
+ /** Set the ON UPDATE action for a foreign key. */
808
+ onUpdate(this: NumberSchemaBuilder<any, any, any, any, any>, action: FKAction): NumberSchemaBuilder<any, any, any, any, any>;
809
+ /** Set a default value for this column. */
810
+ defaultTo(this: NumberSchemaBuilder<any, any, any, any, any>, value: number | "auto_increment"): NumberSchemaBuilder<any, any, any, any, any>;
811
+ /** Add an index on this column.
812
+ * @param name - Optional index name.
813
+ */
814
+ index(this: NumberSchemaBuilder<any, any, any, any, any>, name?: string): NumberSchemaBuilder<any, any, any, any, any>;
815
+ /** Add a unique constraint on this column.
816
+ * @param name - Optional constraint name.
817
+ */
818
+ unique(this: NumberSchemaBuilder<any, any, any, any, any>, name?: string): NumberSchemaBuilder<any, any, any, any, any>;
819
+ /** Override the SQL column type (e.g. `'bigint'`, `'smallint'`). */
820
+ columnType(this: NumberSchemaBuilder<any, any, any, any, any>, type: string): NumberSchemaBuilder<any, any, any, any, any>;
821
+ /** Shorthand for `.columnType('bigint')`. */
822
+ bigint(this: NumberSchemaBuilder<any, any, any, any, any>): NumberSchemaBuilder<any, any, any, any, any>;
823
+ /** Shorthand for `.columnType('smallint')`. */
824
+ smallint(this: NumberSchemaBuilder<any, any, any, any, any>): NumberSchemaBuilder<any, any, any, any, any>;
825
+ /** Shorthand for `.columnType('decimal(p,s)')` — exact numeric.
826
+ * @param precision - Total digits.
827
+ * @param scale - Digits after decimal point.
828
+ */
829
+ decimal(this: NumberSchemaBuilder<any, any, any, any, any>, precision: number, scale: number): NumberSchemaBuilder<any, any, any, any, any>;
830
+ /** Set a raw SQL default expression.
831
+ * @param expression - Raw SQL expression (e.g. `"nextval('my_seq')"`).
832
+ */
833
+ defaultToRaw(this: NumberSchemaBuilder<any, any, any, any, any>, expression: string): NumberSchemaBuilder<any, any, any, any, any>;
834
+ /**
835
+ * Mark this integer column as an optimistic-concurrency row-version
836
+ * token checked by the ORM on every UPDATE / DELETE.
837
+ *
838
+ * A mismatch between the stored value and the snapshot taken at read
839
+ * time throws `ConcurrencyError`.
840
+ *
841
+ * @param opts.strategy
842
+ * - `'increment'` (default) — ORM adds 1 on each UPDATE.
843
+ * - `'manual'` — caller supplies the new value.
844
+ */
845
+ rowVersion(this: NumberSchemaBuilder<any, any, any, any, any>, opts?: {
846
+ strategy?: "increment" | "manual";
847
+ }): NumberSchemaBuilder<any, any, any, any, any>;
227
848
  }>;
228
849
  <T extends number>(equals: T): import("@cleverbrush/schema").CleanExtended<NumberSchemaBuilder<T, true, false, false, {
229
850
  positive(this: NumberSchemaBuilder, errorMessage?: import("@cleverbrush/schema").ValidationErrorMessageProvider<NumberSchemaBuilder>): NumberSchemaBuilder<number, true, false, false, {}>;
@@ -237,6 +858,55 @@ export declare const number: {
237
858
  * @param name - The SQL column name.
238
859
  */
239
860
  hasColumnName(this: NumberSchemaBuilder<any, any, any, any, any>, name: string): SchemaBuilder<any, any, any, false, {}>;
861
+ } & {
862
+ /** Add a foreign key reference to another table.
863
+ * @param table - The referenced table name.
864
+ * @param column - The referenced column (defaults to `'id'`).
865
+ */
866
+ references(this: NumberSchemaBuilder<any, any, any, any, any>, table: string, column?: string): NumberSchemaBuilder<any, any, any, any, any>;
867
+ /** Set the ON DELETE action for a foreign key. */
868
+ onDelete(this: NumberSchemaBuilder<any, any, any, any, any>, action: FKAction): NumberSchemaBuilder<any, any, any, any, any>;
869
+ /** Set the ON UPDATE action for a foreign key. */
870
+ onUpdate(this: NumberSchemaBuilder<any, any, any, any, any>, action: FKAction): NumberSchemaBuilder<any, any, any, any, any>;
871
+ /** Set a default value for this column. */
872
+ defaultTo(this: NumberSchemaBuilder<any, any, any, any, any>, value: number | "auto_increment"): NumberSchemaBuilder<any, any, any, any, any>;
873
+ /** Add an index on this column.
874
+ * @param name - Optional index name.
875
+ */
876
+ index(this: NumberSchemaBuilder<any, any, any, any, any>, name?: string): NumberSchemaBuilder<any, any, any, any, any>;
877
+ /** Add a unique constraint on this column.
878
+ * @param name - Optional constraint name.
879
+ */
880
+ unique(this: NumberSchemaBuilder<any, any, any, any, any>, name?: string): NumberSchemaBuilder<any, any, any, any, any>;
881
+ /** Override the SQL column type (e.g. `'bigint'`, `'smallint'`). */
882
+ columnType(this: NumberSchemaBuilder<any, any, any, any, any>, type: string): NumberSchemaBuilder<any, any, any, any, any>;
883
+ /** Shorthand for `.columnType('bigint')`. */
884
+ bigint(this: NumberSchemaBuilder<any, any, any, any, any>): NumberSchemaBuilder<any, any, any, any, any>;
885
+ /** Shorthand for `.columnType('smallint')`. */
886
+ smallint(this: NumberSchemaBuilder<any, any, any, any, any>): NumberSchemaBuilder<any, any, any, any, any>;
887
+ /** Shorthand for `.columnType('decimal(p,s)')` — exact numeric.
888
+ * @param precision - Total digits.
889
+ * @param scale - Digits after decimal point.
890
+ */
891
+ decimal(this: NumberSchemaBuilder<any, any, any, any, any>, precision: number, scale: number): NumberSchemaBuilder<any, any, any, any, any>;
892
+ /** Set a raw SQL default expression.
893
+ * @param expression - Raw SQL expression (e.g. `"nextval('my_seq')"`).
894
+ */
895
+ defaultToRaw(this: NumberSchemaBuilder<any, any, any, any, any>, expression: string): NumberSchemaBuilder<any, any, any, any, any>;
896
+ /**
897
+ * Mark this integer column as an optimistic-concurrency row-version
898
+ * token checked by the ORM on every UPDATE / DELETE.
899
+ *
900
+ * A mismatch between the stored value and the snapshot taken at read
901
+ * time throws `ConcurrencyError`.
902
+ *
903
+ * @param opts.strategy
904
+ * - `'increment'` (default) — ORM adds 1 on each UPDATE.
905
+ * - `'manual'` — caller supplies the new value.
906
+ */
907
+ rowVersion(this: NumberSchemaBuilder<any, any, any, any, any>, opts?: {
908
+ strategy?: "increment" | "manual";
909
+ }): NumberSchemaBuilder<any, any, any, any, any>;
240
910
  }>, {
241
911
  positive(this: NumberSchemaBuilder, errorMessage?: import("@cleverbrush/schema").ValidationErrorMessageProvider<NumberSchemaBuilder>): NumberSchemaBuilder<number, true, false, false, {}>;
242
912
  negative(this: NumberSchemaBuilder, errorMessage?: import("@cleverbrush/schema").ValidationErrorMessageProvider<NumberSchemaBuilder>): NumberSchemaBuilder<number, true, false, false, {}>;
@@ -249,6 +919,55 @@ export declare const number: {
249
919
  * @param name - The SQL column name.
250
920
  */
251
921
  hasColumnName(this: NumberSchemaBuilder<any, any, any, any, any>, name: string): SchemaBuilder<any, any, any, false, {}>;
922
+ } & {
923
+ /** Add a foreign key reference to another table.
924
+ * @param table - The referenced table name.
925
+ * @param column - The referenced column (defaults to `'id'`).
926
+ */
927
+ references(this: NumberSchemaBuilder<any, any, any, any, any>, table: string, column?: string): NumberSchemaBuilder<any, any, any, any, any>;
928
+ /** Set the ON DELETE action for a foreign key. */
929
+ onDelete(this: NumberSchemaBuilder<any, any, any, any, any>, action: FKAction): NumberSchemaBuilder<any, any, any, any, any>;
930
+ /** Set the ON UPDATE action for a foreign key. */
931
+ onUpdate(this: NumberSchemaBuilder<any, any, any, any, any>, action: FKAction): NumberSchemaBuilder<any, any, any, any, any>;
932
+ /** Set a default value for this column. */
933
+ defaultTo(this: NumberSchemaBuilder<any, any, any, any, any>, value: number | "auto_increment"): NumberSchemaBuilder<any, any, any, any, any>;
934
+ /** Add an index on this column.
935
+ * @param name - Optional index name.
936
+ */
937
+ index(this: NumberSchemaBuilder<any, any, any, any, any>, name?: string): NumberSchemaBuilder<any, any, any, any, any>;
938
+ /** Add a unique constraint on this column.
939
+ * @param name - Optional constraint name.
940
+ */
941
+ unique(this: NumberSchemaBuilder<any, any, any, any, any>, name?: string): NumberSchemaBuilder<any, any, any, any, any>;
942
+ /** Override the SQL column type (e.g. `'bigint'`, `'smallint'`). */
943
+ columnType(this: NumberSchemaBuilder<any, any, any, any, any>, type: string): NumberSchemaBuilder<any, any, any, any, any>;
944
+ /** Shorthand for `.columnType('bigint')`. */
945
+ bigint(this: NumberSchemaBuilder<any, any, any, any, any>): NumberSchemaBuilder<any, any, any, any, any>;
946
+ /** Shorthand for `.columnType('smallint')`. */
947
+ smallint(this: NumberSchemaBuilder<any, any, any, any, any>): NumberSchemaBuilder<any, any, any, any, any>;
948
+ /** Shorthand for `.columnType('decimal(p,s)')` — exact numeric.
949
+ * @param precision - Total digits.
950
+ * @param scale - Digits after decimal point.
951
+ */
952
+ decimal(this: NumberSchemaBuilder<any, any, any, any, any>, precision: number, scale: number): NumberSchemaBuilder<any, any, any, any, any>;
953
+ /** Set a raw SQL default expression.
954
+ * @param expression - Raw SQL expression (e.g. `"nextval('my_seq')"`).
955
+ */
956
+ defaultToRaw(this: NumberSchemaBuilder<any, any, any, any, any>, expression: string): NumberSchemaBuilder<any, any, any, any, any>;
957
+ /**
958
+ * Mark this integer column as an optimistic-concurrency row-version
959
+ * token checked by the ORM on every UPDATE / DELETE.
960
+ *
961
+ * A mismatch between the stored value and the snapshot taken at read
962
+ * time throws `ConcurrencyError`.
963
+ *
964
+ * @param opts.strategy
965
+ * - `'increment'` (default) — ORM adds 1 on each UPDATE.
966
+ * - `'manual'` — caller supplies the new value.
967
+ */
968
+ rowVersion(this: NumberSchemaBuilder<any, any, any, any, any>, opts?: {
969
+ strategy?: "increment" | "manual";
970
+ }): NumberSchemaBuilder<any, any, any, any, any>;
252
971
  }>;
253
972
  };
254
973
  export declare const boolean: () => import("@cleverbrush/schema").CleanExtended<BooleanSchemaBuilder<boolean, true, false, undefined, false, {
@@ -257,12 +976,30 @@ export declare const boolean: () => import("@cleverbrush/schema").CleanExtended<
257
976
  * @param name - The SQL column name.
258
977
  */
259
978
  hasColumnName(this: BooleanSchemaBuilder<any, any, any, any, any, any, any>, name: string): SchemaBuilder<any, any, any, false, {}>;
979
+ } & {
980
+ /** Set a default value for this column. */
981
+ defaultTo(this: BooleanSchemaBuilder<any, any, any, any, any, any, any>, value: boolean): BooleanSchemaBuilder<any, any, any, any, any, any, any>;
982
+ /** Override the SQL column type (e.g. `'smallint'`, `'integer'`). */
983
+ columnType(this: BooleanSchemaBuilder<any, any, any, any, any, any, any>, type: string): BooleanSchemaBuilder<any, any, any, any, any, any, any>;
984
+ /** Add an index on this column. */
985
+ index(this: BooleanSchemaBuilder<any, any, any, any, any, any, any>, name?: string): BooleanSchemaBuilder<any, any, any, any, any, any, any>;
986
+ /** Add a unique constraint on this column. */
987
+ unique(this: BooleanSchemaBuilder<any, any, any, any, any, any, any>, name?: string): BooleanSchemaBuilder<any, any, any, any, any, any, any>;
260
988
  }, boolean>, {
261
989
  /**
262
990
  * Override the SQL column name for this property.
263
991
  * @param name - The SQL column name.
264
992
  */
265
993
  hasColumnName(this: BooleanSchemaBuilder<any, any, any, any, any, any, any>, name: string): SchemaBuilder<any, any, any, false, {}>;
994
+ } & {
995
+ /** Set a default value for this column. */
996
+ defaultTo(this: BooleanSchemaBuilder<any, any, any, any, any, any, any>, value: boolean): BooleanSchemaBuilder<any, any, any, any, any, any, any>;
997
+ /** Override the SQL column type (e.g. `'smallint'`, `'integer'`). */
998
+ columnType(this: BooleanSchemaBuilder<any, any, any, any, any, any, any>, type: string): BooleanSchemaBuilder<any, any, any, any, any, any, any>;
999
+ /** Add an index on this column. */
1000
+ index(this: BooleanSchemaBuilder<any, any, any, any, any, any, any>, name?: string): BooleanSchemaBuilder<any, any, any, any, any, any, any>;
1001
+ /** Add a unique constraint on this column. */
1002
+ unique(this: BooleanSchemaBuilder<any, any, any, any, any, any, any>, name?: string): BooleanSchemaBuilder<any, any, any, any, any, any, any>;
266
1003
  }>;
267
1004
  export declare const date: () => import("@cleverbrush/schema").CleanExtended<DateSchemaBuilder<Date, true, false, false, {
268
1005
  /**
@@ -270,12 +1007,54 @@ export declare const date: () => import("@cleverbrush/schema").CleanExtended<Dat
270
1007
  * @param name - The SQL column name.
271
1008
  */
272
1009
  hasColumnName(this: DateSchemaBuilder<any, any, any, any, any>, name: string): SchemaBuilder<any, any, any, false, {}>;
1010
+ } & {
1011
+ /** Set a default value (`'now'` for current timestamp). */
1012
+ defaultTo(this: DateSchemaBuilder<any, any, any, any, any>, value: "now"): DateSchemaBuilder<any, any, any, any, any>;
1013
+ /** Override the SQL column type
1014
+ * (e.g. `'timestamptz'`, `'date'`, `'time'`).
1015
+ */
1016
+ columnType(this: DateSchemaBuilder<any, any, any, any, any>, type: string): DateSchemaBuilder<any, any, any, any, any>;
1017
+ /** Add an index on this column. */
1018
+ index(this: DateSchemaBuilder<any, any, any, any, any>, name?: string): DateSchemaBuilder<any, any, any, any, any>;
1019
+ /** Set a raw SQL default expression. */
1020
+ defaultToRaw(this: DateSchemaBuilder<any, any, any, any, any>, expression: string): DateSchemaBuilder<any, any, any, any, any>;
1021
+ /** Shorthand for `.columnType('timestamptz')`. */
1022
+ timestamptz(this: DateSchemaBuilder<any, any, any, any, any>): DateSchemaBuilder<any, any, any, any, any>;
1023
+ /** Shorthand for `.columnType('date')` (date-only, no time). */
1024
+ dateOnly(this: DateSchemaBuilder<any, any, any, any, any>): DateSchemaBuilder<any, any, any, any, any>;
1025
+ /**
1026
+ * Mark this date column as an optimistic-concurrency row-version
1027
+ * token (timestamp-based). Strategy is always `'timestamp'` —
1028
+ * the ORM sets the value to `new Date()` on each UPDATE.
1029
+ */
1030
+ rowVersion(this: DateSchemaBuilder<any, any, any, any, any>): DateSchemaBuilder<any, any, any, any, any>;
273
1031
  }>, {
274
1032
  /**
275
1033
  * Override the SQL column name for this property.
276
1034
  * @param name - The SQL column name.
277
1035
  */
278
1036
  hasColumnName(this: DateSchemaBuilder<any, any, any, any, any>, name: string): SchemaBuilder<any, any, any, false, {}>;
1037
+ } & {
1038
+ /** Set a default value (`'now'` for current timestamp). */
1039
+ defaultTo(this: DateSchemaBuilder<any, any, any, any, any>, value: "now"): DateSchemaBuilder<any, any, any, any, any>;
1040
+ /** Override the SQL column type
1041
+ * (e.g. `'timestamptz'`, `'date'`, `'time'`).
1042
+ */
1043
+ columnType(this: DateSchemaBuilder<any, any, any, any, any>, type: string): DateSchemaBuilder<any, any, any, any, any>;
1044
+ /** Add an index on this column. */
1045
+ index(this: DateSchemaBuilder<any, any, any, any, any>, name?: string): DateSchemaBuilder<any, any, any, any, any>;
1046
+ /** Set a raw SQL default expression. */
1047
+ defaultToRaw(this: DateSchemaBuilder<any, any, any, any, any>, expression: string): DateSchemaBuilder<any, any, any, any, any>;
1048
+ /** Shorthand for `.columnType('timestamptz')`. */
1049
+ timestamptz(this: DateSchemaBuilder<any, any, any, any, any>): DateSchemaBuilder<any, any, any, any, any>;
1050
+ /** Shorthand for `.columnType('date')` (date-only, no time). */
1051
+ dateOnly(this: DateSchemaBuilder<any, any, any, any, any>): DateSchemaBuilder<any, any, any, any, any>;
1052
+ /**
1053
+ * Mark this date column as an optimistic-concurrency row-version
1054
+ * token (timestamp-based). Strategy is always `'timestamp'` —
1055
+ * the ORM sets the value to `new Date()` on each UPDATE.
1056
+ */
1057
+ rowVersion(this: DateSchemaBuilder<any, any, any, any, any>): DateSchemaBuilder<any, any, any, any, any>;
279
1058
  }>;
280
1059
  export declare const object: <P extends Record<string, SchemaBuilder<any, any, any, any, any>>>(properties?: P | undefined) => import("@cleverbrush/schema").CleanExtended<ObjectSchemaBuilder<P, true, false, undefined, false, {
281
1060
  /**
@@ -287,6 +1066,174 @@ export declare const object: <P extends Record<string, SchemaBuilder<any, any, a
287
1066
  * @param name - The SQL table name (e.g. `'users'`).
288
1067
  */
289
1068
  hasTableName(this: ObjectSchemaBuilder<any, any, any, any, any, any, any>, name: string): ObjectSchemaBuilder<any, any, any, any, any, any, any>;
1069
+ } & {
1070
+ /** Override the SQL column type for an object property stored inline.
1071
+ * Object-typed properties default to `jsonb` when used as columns in
1072
+ * a parent schema's table.
1073
+ */
1074
+ columnType(this: ObjectSchemaBuilder<any, any, any, any, any, any, any>, type: string): ObjectSchemaBuilder<any, any, any, any, any, any, any>;
1075
+ /** Shorthand for `.columnType('jsonb')` — store this nested object as
1076
+ * a `jsonb` column (Postgres). Nested objects already default to
1077
+ * `jsonb` in DDL; calling `.jsonb()` makes the intent explicit.
1078
+ */
1079
+ jsonb(this: ObjectSchemaBuilder<any, any, any, any, any, any, any>): ObjectSchemaBuilder<any, any, any, any, any, any, any>;
1080
+ /** Shorthand for `.columnType('json')` — store this nested object as
1081
+ * a plain `json` column (Postgres / MySQL).
1082
+ */
1083
+ json(this: ObjectSchemaBuilder<any, any, any, any, any, any, any>): ObjectSchemaBuilder<any, any, any, any, any, any, any>;
1084
+ /** Add a composite index on multiple columns.
1085
+ * @param columns - Column names to index.
1086
+ * @param opts - Optional index name and unique flag.
1087
+ */
1088
+ hasIndex(this: ObjectSchemaBuilder<any, any, any, any, any, any, any>, columns: string[], opts?: {
1089
+ name?: string;
1090
+ unique?: boolean;
1091
+ }): ObjectSchemaBuilder<any, any, any, any, any, any, any>;
1092
+ /** Add a composite unique constraint.
1093
+ * @param columns - Column names.
1094
+ * @param name - Optional constraint name.
1095
+ */
1096
+ hasUnique(this: ObjectSchemaBuilder<any, any, any, any, any, any, any>, columns: string[], name?: string): ObjectSchemaBuilder<any, any, any, any, any, any, any>;
1097
+ /** Add a table-level CHECK constraint.
1098
+ * @param sql - Raw SQL expression for the check.
1099
+ */
1100
+ hasCheck(this: ObjectSchemaBuilder<any, any, any, any, any, any, any>, sql: string): ObjectSchemaBuilder<any, any, any, any, any, any, any>;
1101
+ /** Add a raw SQL column definition not backed by a schema property.
1102
+ * @param name - Column name.
1103
+ * @param definition - SQL type and constraints (e.g. `"tsvector GENERATED ALWAYS AS (...) STORED"`).
1104
+ */
1105
+ hasRawColumn(this: ObjectSchemaBuilder<any, any, any, any, any, any, any>, name: string, definition: string): ObjectSchemaBuilder<any, any, any, any, any, any, any>;
1106
+ /** Add a raw SQL index statement executed after table creation.
1107
+ * @param sql - Full `CREATE INDEX` SQL statement.
1108
+ */
1109
+ hasRawIndex(this: ObjectSchemaBuilder<any, any, any, any, any, any, any>, sql: string): ObjectSchemaBuilder<any, any, any, any, any, any, any>;
1110
+ /** Define a one-to-many relationship.
1111
+ * @param name - Relation name used with `include()`.
1112
+ * @param opts - `{ schema, foreignKey }` — `foreignKey` is a ColumnRef on the foreign schema.
1113
+ */
1114
+ hasMany(this: ObjectSchemaBuilder<any, any, any, any, any, any, any>, name: string, opts: {
1115
+ schema: any;
1116
+ foreignKey: any;
1117
+ }): ObjectSchemaBuilder<any, any, any, any, any, any, any>;
1118
+ /** Define a one-to-one relationship (FK on foreign table).
1119
+ * @param name - Relation name used with `include()`.
1120
+ * @param opts - `{ schema, foreignKey }` — `foreignKey` is a ColumnRef on the foreign schema.
1121
+ */
1122
+ hasOne(this: ObjectSchemaBuilder<any, any, any, any, any, any, any>, name: string, opts: {
1123
+ schema: any;
1124
+ foreignKey: any;
1125
+ }): ObjectSchemaBuilder<any, any, any, any, any, any, any>;
1126
+ /** Define a belongs-to relationship (FK on local table).
1127
+ * @param name - Relation name used with `include()`.
1128
+ * @param opts - `{ schema, foreignKey }` — `foreignKey` is a ColumnRef on the local schema.
1129
+ */
1130
+ belongsTo(this: ObjectSchemaBuilder<any, any, any, any, any, any, any>, name: string, opts: {
1131
+ schema: any;
1132
+ foreignKey: any;
1133
+ }): ObjectSchemaBuilder<any, any, any, any, any, any, any>;
1134
+ /** Define a many-to-many relationship through a pivot table.
1135
+ * @param name - Relation name used with `include()`.
1136
+ * @param opts - `{ schema, through: { table, localKey, foreignKey } }`.
1137
+ */
1138
+ belongsToMany(this: ObjectSchemaBuilder<any, any, any, any, any, any, any>, name: string, opts: {
1139
+ schema: any;
1140
+ through: {
1141
+ table: string;
1142
+ localKey: string;
1143
+ foreignKey: string;
1144
+ };
1145
+ }): ObjectSchemaBuilder<any, any, any, any, any, any, any>;
1146
+ /** Auto-add `created_at` and `updated_at` timestamp columns.
1147
+ * @param opts - Optional custom column names.
1148
+ */
1149
+ hasTimestamps(this: ObjectSchemaBuilder<any, any, any, any, any, any, any>, opts?: {
1150
+ createdAt?: string;
1151
+ updatedAt?: string;
1152
+ }): ObjectSchemaBuilder<any, any, any, any, any, any, any>;
1153
+ /** Enable soft deletes (adds a `deleted_at` column, auto-filters queries).
1154
+ * @param opts - Optional custom column name.
1155
+ */
1156
+ softDelete(this: ObjectSchemaBuilder<any, any, any, any, any, any, any>, opts?: {
1157
+ column?: string;
1158
+ }): ObjectSchemaBuilder<any, any, any, any, any, any, any>;
1159
+ /** Register a named query scope.
1160
+ * @param name - Scope name to use with `.scoped(name)`.
1161
+ * @param fn - Function that receives a `SchemaQueryBuilder` and applies filters.
1162
+ */
1163
+ scope<N extends string>(this: ObjectSchemaBuilder<any, any, any, any, any, any, any>, name: N, fn: Function): ObjectSchemaBuilder<any, any, any, any, any, any, any> & {
1164
+ readonly [METHOD_LITERAL_BRAND]?: N;
1165
+ };
1166
+ /**
1167
+ * Register a **named projection** — a reusable column subset that can be
1168
+ * applied at query time via `.projected(name)`.
1169
+ *
1170
+ * When a projection is applied the query builder:
1171
+ * 1. Issues `SELECT <cols>` instead of `SELECT *`.
1172
+ * 2. Narrows the TypeScript result row type to `Pick<Row, Keys>`.
1173
+ *
1174
+ * Columns are passed as **rest parameters**. Each argument can be either:
1175
+ *
1176
+ * - A **string** literal of a property name (autocompleted against the
1177
+ * schema's properties):
1178
+ * ```ts
1179
+ * .projection('summary', 'id', 'title', 'completed')
1180
+ * ```
1181
+ * - An **accessor callback** (refactor-safe — renaming a property
1182
+ * updates the projection automatically):
1183
+ * ```ts
1184
+ * .projection('listView', t => t.id, t => t.title, t => t.userId)
1185
+ * ```
1186
+ *
1187
+ * The two forms can be mixed freely:
1188
+ * ```ts
1189
+ * .projection('mixed', 'id', t => t.title)
1190
+ * ```
1191
+ *
1192
+ * The literal property keys flow through the type system, so
1193
+ * `.projected('listView')` still narrows the result type to
1194
+ * `Pick<Row, 'id' | 'title' | 'userId'>`.
1195
+ *
1196
+ * @param name - Unique projection name (used with `.projected()`).
1197
+ * @param columns - One argument per column: either a property name
1198
+ * string or a `t => t.propName` accessor callback.
1199
+ *
1200
+ * @example
1201
+ * ```ts
1202
+ * const PostSchema = object({ id: number(), title: string(), body: string() })
1203
+ * .hasTableName('posts')
1204
+ * .projection('summary', 'id', 'title')
1205
+ * .projection('detail', t => t.id, t => t.title, t => t.body);
1206
+ *
1207
+ * // Later:
1208
+ * const rows = await query(db, PostSchema).projected('summary');
1209
+ * // rows: Array<Pick<Post, 'id' | 'title'>>
1210
+ * ```
1211
+ *
1212
+ * @see {@link SchemaQueryBuilder.projected}
1213
+ */
1214
+ projection<TProperties extends Record<string, SchemaBuilder<any, any, any, any, any>>, const N extends string, const TKey extends keyof TProperties & string>(this: ObjectSchemaBuilder<TProperties, any, any, any, any, any, any>, name: N, ...columns: ReadonlyArray<TKey | ((t: PropertyDescriptorTree<ObjectSchemaBuilder<TProperties, any, any, any, any, any, any>, ObjectSchemaBuilder<TProperties, any, any, any, any, any, any>>) => PropertyDescriptor<any, any, any, TKey>)>): ObjectSchemaBuilder<TProperties, any, any, any, any, any, any> & {
1215
+ readonly [EXTRA_TYPE_BRAND]?: { [P_1 in N]: readonly TKey[]; };
1216
+ };
1217
+ /** Set a default scope applied to all queries unless `.unscoped()` is called.
1218
+ * @param fn - Function that receives a `SchemaQueryBuilder` and applies filters.
1219
+ */
1220
+ defaultScope(this: ObjectSchemaBuilder<any, any, any, any, any, any, any>, fn: Function): ObjectSchemaBuilder<any, any, any, any, any, any, any>;
1221
+ /** Register a before-insert lifecycle hook.
1222
+ * @param fn - Async function `(data) => data` called before inserting.
1223
+ */
1224
+ beforeInsert(this: ObjectSchemaBuilder<any, any, any, any, any, any, any>, fn: Function): ObjectSchemaBuilder<any, any, any, any, any, any, any>;
1225
+ /** Register an after-insert lifecycle hook.
1226
+ * @param fn - Async function `(row)` called after inserting.
1227
+ */
1228
+ afterInsert(this: ObjectSchemaBuilder<any, any, any, any, any, any, any>, fn: Function): ObjectSchemaBuilder<any, any, any, any, any, any, any>;
1229
+ /** Register a before-update lifecycle hook.
1230
+ * @param fn - Async function `(data) => data` called before updating.
1231
+ */
1232
+ beforeUpdate(this: ObjectSchemaBuilder<any, any, any, any, any, any, any>, fn: Function): ObjectSchemaBuilder<any, any, any, any, any, any, any>;
1233
+ /** Register a before-delete lifecycle hook.
1234
+ * @param fn - Async function `(query)` called before deleting.
1235
+ */
1236
+ beforeDelete(this: ObjectSchemaBuilder<any, any, any, any, any, any, any>, fn: Function): ObjectSchemaBuilder<any, any, any, any, any, any, any>;
290
1237
  }, []>, {
291
1238
  /**
292
1239
  * Set the SQL table name for this object schema.
@@ -297,6 +1244,174 @@ export declare const object: <P extends Record<string, SchemaBuilder<any, any, a
297
1244
  * @param name - The SQL table name (e.g. `'users'`).
298
1245
  */
299
1246
  hasTableName(this: ObjectSchemaBuilder<any, any, any, any, any, any, any>, name: string): ObjectSchemaBuilder<any, any, any, any, any, any, any>;
1247
+ } & {
1248
+ /** Override the SQL column type for an object property stored inline.
1249
+ * Object-typed properties default to `jsonb` when used as columns in
1250
+ * a parent schema's table.
1251
+ */
1252
+ columnType(this: ObjectSchemaBuilder<any, any, any, any, any, any, any>, type: string): ObjectSchemaBuilder<any, any, any, any, any, any, any>;
1253
+ /** Shorthand for `.columnType('jsonb')` — store this nested object as
1254
+ * a `jsonb` column (Postgres). Nested objects already default to
1255
+ * `jsonb` in DDL; calling `.jsonb()` makes the intent explicit.
1256
+ */
1257
+ jsonb(this: ObjectSchemaBuilder<any, any, any, any, any, any, any>): ObjectSchemaBuilder<any, any, any, any, any, any, any>;
1258
+ /** Shorthand for `.columnType('json')` — store this nested object as
1259
+ * a plain `json` column (Postgres / MySQL).
1260
+ */
1261
+ json(this: ObjectSchemaBuilder<any, any, any, any, any, any, any>): ObjectSchemaBuilder<any, any, any, any, any, any, any>;
1262
+ /** Add a composite index on multiple columns.
1263
+ * @param columns - Column names to index.
1264
+ * @param opts - Optional index name and unique flag.
1265
+ */
1266
+ hasIndex(this: ObjectSchemaBuilder<any, any, any, any, any, any, any>, columns: string[], opts?: {
1267
+ name?: string;
1268
+ unique?: boolean;
1269
+ }): ObjectSchemaBuilder<any, any, any, any, any, any, any>;
1270
+ /** Add a composite unique constraint.
1271
+ * @param columns - Column names.
1272
+ * @param name - Optional constraint name.
1273
+ */
1274
+ hasUnique(this: ObjectSchemaBuilder<any, any, any, any, any, any, any>, columns: string[], name?: string): ObjectSchemaBuilder<any, any, any, any, any, any, any>;
1275
+ /** Add a table-level CHECK constraint.
1276
+ * @param sql - Raw SQL expression for the check.
1277
+ */
1278
+ hasCheck(this: ObjectSchemaBuilder<any, any, any, any, any, any, any>, sql: string): ObjectSchemaBuilder<any, any, any, any, any, any, any>;
1279
+ /** Add a raw SQL column definition not backed by a schema property.
1280
+ * @param name - Column name.
1281
+ * @param definition - SQL type and constraints (e.g. `"tsvector GENERATED ALWAYS AS (...) STORED"`).
1282
+ */
1283
+ hasRawColumn(this: ObjectSchemaBuilder<any, any, any, any, any, any, any>, name: string, definition: string): ObjectSchemaBuilder<any, any, any, any, any, any, any>;
1284
+ /** Add a raw SQL index statement executed after table creation.
1285
+ * @param sql - Full `CREATE INDEX` SQL statement.
1286
+ */
1287
+ hasRawIndex(this: ObjectSchemaBuilder<any, any, any, any, any, any, any>, sql: string): ObjectSchemaBuilder<any, any, any, any, any, any, any>;
1288
+ /** Define a one-to-many relationship.
1289
+ * @param name - Relation name used with `include()`.
1290
+ * @param opts - `{ schema, foreignKey }` — `foreignKey` is a ColumnRef on the foreign schema.
1291
+ */
1292
+ hasMany(this: ObjectSchemaBuilder<any, any, any, any, any, any, any>, name: string, opts: {
1293
+ schema: any;
1294
+ foreignKey: any;
1295
+ }): ObjectSchemaBuilder<any, any, any, any, any, any, any>;
1296
+ /** Define a one-to-one relationship (FK on foreign table).
1297
+ * @param name - Relation name used with `include()`.
1298
+ * @param opts - `{ schema, foreignKey }` — `foreignKey` is a ColumnRef on the foreign schema.
1299
+ */
1300
+ hasOne(this: ObjectSchemaBuilder<any, any, any, any, any, any, any>, name: string, opts: {
1301
+ schema: any;
1302
+ foreignKey: any;
1303
+ }): ObjectSchemaBuilder<any, any, any, any, any, any, any>;
1304
+ /** Define a belongs-to relationship (FK on local table).
1305
+ * @param name - Relation name used with `include()`.
1306
+ * @param opts - `{ schema, foreignKey }` — `foreignKey` is a ColumnRef on the local schema.
1307
+ */
1308
+ belongsTo(this: ObjectSchemaBuilder<any, any, any, any, any, any, any>, name: string, opts: {
1309
+ schema: any;
1310
+ foreignKey: any;
1311
+ }): ObjectSchemaBuilder<any, any, any, any, any, any, any>;
1312
+ /** Define a many-to-many relationship through a pivot table.
1313
+ * @param name - Relation name used with `include()`.
1314
+ * @param opts - `{ schema, through: { table, localKey, foreignKey } }`.
1315
+ */
1316
+ belongsToMany(this: ObjectSchemaBuilder<any, any, any, any, any, any, any>, name: string, opts: {
1317
+ schema: any;
1318
+ through: {
1319
+ table: string;
1320
+ localKey: string;
1321
+ foreignKey: string;
1322
+ };
1323
+ }): ObjectSchemaBuilder<any, any, any, any, any, any, any>;
1324
+ /** Auto-add `created_at` and `updated_at` timestamp columns.
1325
+ * @param opts - Optional custom column names.
1326
+ */
1327
+ hasTimestamps(this: ObjectSchemaBuilder<any, any, any, any, any, any, any>, opts?: {
1328
+ createdAt?: string;
1329
+ updatedAt?: string;
1330
+ }): ObjectSchemaBuilder<any, any, any, any, any, any, any>;
1331
+ /** Enable soft deletes (adds a `deleted_at` column, auto-filters queries).
1332
+ * @param opts - Optional custom column name.
1333
+ */
1334
+ softDelete(this: ObjectSchemaBuilder<any, any, any, any, any, any, any>, opts?: {
1335
+ column?: string;
1336
+ }): ObjectSchemaBuilder<any, any, any, any, any, any, any>;
1337
+ /** Register a named query scope.
1338
+ * @param name - Scope name to use with `.scoped(name)`.
1339
+ * @param fn - Function that receives a `SchemaQueryBuilder` and applies filters.
1340
+ */
1341
+ scope<N_1 extends string>(this: ObjectSchemaBuilder<any, any, any, any, any, any, any>, name: N_1, fn: Function): ObjectSchemaBuilder<any, any, any, any, any, any, any> & {
1342
+ readonly [METHOD_LITERAL_BRAND]?: N_1;
1343
+ };
1344
+ /**
1345
+ * Register a **named projection** — a reusable column subset that can be
1346
+ * applied at query time via `.projected(name)`.
1347
+ *
1348
+ * When a projection is applied the query builder:
1349
+ * 1. Issues `SELECT <cols>` instead of `SELECT *`.
1350
+ * 2. Narrows the TypeScript result row type to `Pick<Row, Keys>`.
1351
+ *
1352
+ * Columns are passed as **rest parameters**. Each argument can be either:
1353
+ *
1354
+ * - A **string** literal of a property name (autocompleted against the
1355
+ * schema's properties):
1356
+ * ```ts
1357
+ * .projection('summary', 'id', 'title', 'completed')
1358
+ * ```
1359
+ * - An **accessor callback** (refactor-safe — renaming a property
1360
+ * updates the projection automatically):
1361
+ * ```ts
1362
+ * .projection('listView', t => t.id, t => t.title, t => t.userId)
1363
+ * ```
1364
+ *
1365
+ * The two forms can be mixed freely:
1366
+ * ```ts
1367
+ * .projection('mixed', 'id', t => t.title)
1368
+ * ```
1369
+ *
1370
+ * The literal property keys flow through the type system, so
1371
+ * `.projected('listView')` still narrows the result type to
1372
+ * `Pick<Row, 'id' | 'title' | 'userId'>`.
1373
+ *
1374
+ * @param name - Unique projection name (used with `.projected()`).
1375
+ * @param columns - One argument per column: either a property name
1376
+ * string or a `t => t.propName` accessor callback.
1377
+ *
1378
+ * @example
1379
+ * ```ts
1380
+ * const PostSchema = object({ id: number(), title: string(), body: string() })
1381
+ * .hasTableName('posts')
1382
+ * .projection('summary', 'id', 'title')
1383
+ * .projection('detail', t => t.id, t => t.title, t => t.body);
1384
+ *
1385
+ * // Later:
1386
+ * const rows = await query(db, PostSchema).projected('summary');
1387
+ * // rows: Array<Pick<Post, 'id' | 'title'>>
1388
+ * ```
1389
+ *
1390
+ * @see {@link SchemaQueryBuilder.projected}
1391
+ */
1392
+ projection<TProperties extends Record<string, SchemaBuilder<any, any, any, any, any>>, const N extends string, const TKey extends keyof TProperties & string>(this: ObjectSchemaBuilder<TProperties, any, any, any, any, any, any>, name: N, ...columns: ReadonlyArray<TKey | ((t: PropertyDescriptorTree<ObjectSchemaBuilder<TProperties, any, any, any, any, any, any>, ObjectSchemaBuilder<TProperties, any, any, any, any, any, any>>) => PropertyDescriptor<any, any, any, TKey>)>): ObjectSchemaBuilder<TProperties, any, any, any, any, any, any> & {
1393
+ readonly [EXTRA_TYPE_BRAND]?: { [P_1 in N]: readonly TKey[]; };
1394
+ };
1395
+ /** Set a default scope applied to all queries unless `.unscoped()` is called.
1396
+ * @param fn - Function that receives a `SchemaQueryBuilder` and applies filters.
1397
+ */
1398
+ defaultScope(this: ObjectSchemaBuilder<any, any, any, any, any, any, any>, fn: Function): ObjectSchemaBuilder<any, any, any, any, any, any, any>;
1399
+ /** Register a before-insert lifecycle hook.
1400
+ * @param fn - Async function `(data) => data` called before inserting.
1401
+ */
1402
+ beforeInsert(this: ObjectSchemaBuilder<any, any, any, any, any, any, any>, fn: Function): ObjectSchemaBuilder<any, any, any, any, any, any, any>;
1403
+ /** Register an after-insert lifecycle hook.
1404
+ * @param fn - Async function `(row)` called after inserting.
1405
+ */
1406
+ afterInsert(this: ObjectSchemaBuilder<any, any, any, any, any, any, any>, fn: Function): ObjectSchemaBuilder<any, any, any, any, any, any, any>;
1407
+ /** Register a before-update lifecycle hook.
1408
+ * @param fn - Async function `(data) => data` called before updating.
1409
+ */
1410
+ beforeUpdate(this: ObjectSchemaBuilder<any, any, any, any, any, any, any>, fn: Function): ObjectSchemaBuilder<any, any, any, any, any, any, any>;
1411
+ /** Register a before-delete lifecycle hook.
1412
+ * @param fn - Async function `(query)` called before deleting.
1413
+ */
1414
+ beforeDelete(this: ObjectSchemaBuilder<any, any, any, any, any, any, any>, fn: Function): ObjectSchemaBuilder<any, any, any, any, any, any, any>;
300
1415
  }>;
301
1416
  export declare const array: <TElementSchema extends SchemaBuilder<any, any, any, any, any>>(elementSchema?: TElementSchema | undefined) => import("@cleverbrush/schema").CleanExtended<ArraySchemaBuilder<TElementSchema, true, false, undefined, false, {
302
1417
  nonempty(this: ArraySchemaBuilder<any>, errorMessage?: import("@cleverbrush/schema").ValidationErrorMessageProvider<ArraySchemaBuilder<any>>): ArraySchemaBuilder<any, true, false, undefined, false, {}, any[] | unknown[]>;
@@ -356,6 +1471,33 @@ export declare const any: () => import("@cleverbrush/schema").CleanExtended<AnyS
356
1471
  */
357
1472
  hasColumnName(this: AnySchemaBuilder<any, any, any, any, any, any>, name: string): SchemaBuilder<any, any, any, false, {}>;
358
1473
  }>;
1474
+ declare module '@cleverbrush/schema' {
1475
+ interface NumberSchemaBuilder<TResult, TRequired extends boolean, TNullable extends boolean, THasDefault extends boolean, TExtensions> {
1476
+ /** Mark this column as a primary key.
1477
+ * @param opts - Options. `autoIncrement` defaults to `true`.
1478
+ */
1479
+ primaryKey(opts?: {
1480
+ autoIncrement?: boolean;
1481
+ }): this & {
1482
+ readonly [PRIMARY_KEY_BRAND]?: true;
1483
+ };
1484
+ }
1485
+ interface StringSchemaBuilder<TResult, TRequired extends boolean, TNullable extends boolean, THasDefault extends boolean, TExtensions> {
1486
+ /** Mark this column as a primary key (non-auto-increment). */
1487
+ primaryKey(): this & {
1488
+ readonly [PRIMARY_KEY_BRAND]?: true;
1489
+ };
1490
+ }
1491
+ interface ObjectSchemaBuilder<TProperties extends Record<string, SchemaBuilder<any, any, any, any, any>>, TRequired extends boolean, TNullable extends boolean, TExplicitType, THasDefault extends boolean, TExtensions, TConstructorSchemas> {
1492
+ /** Set a composite primary key.
1493
+ * @param columns - Column names (or property keys) forming the primary key,
1494
+ * in declaration order. Use `as const` to preserve ordering at the type level.
1495
+ */
1496
+ hasPrimaryKey<const TCols extends readonly string[]>(columns: TCols): this & {
1497
+ readonly [COMPOSITE_PRIMARY_KEY_BRAND]?: TCols;
1498
+ };
1499
+ }
1500
+ }
359
1501
  /**
360
1502
  * Get the SQL column name for a schema property.
361
1503
  * Returns the `hasColumnName()` value if set, otherwise falls back to `propertyKey`.
@@ -366,3 +1508,36 @@ export declare function getColumnName(schema: SchemaBuilder<any, any, any>, prop
366
1508
  * Throws if `hasTableName()` was never called.
367
1509
  */
368
1510
  export declare function getTableName(schema: ObjectSchemaBuilder<any, any, any, any, any, any, any>): string;
1511
+ /**
1512
+ * Retrieve the named projections registered on a schema via
1513
+ * `.projection(name, columns)`.
1514
+ *
1515
+ * Returns a map of `{ [name]: { keys: readonly string[] } }` where each
1516
+ * entry's `keys` array contains the **property keys** (not SQL column names)
1517
+ * for that projection. Returns an empty object when no projections are
1518
+ * defined.
1519
+ *
1520
+ * @example
1521
+ * ```ts
1522
+ * const projs = getProjections(PostSchema);
1523
+ * // { summary: { keys: ['id', 'title'] } }
1524
+ * ```
1525
+ */
1526
+ export declare function getProjections(schema: ObjectSchemaBuilder<any, any, any, any, any, any, any>): Record<string, {
1527
+ keys: readonly string[];
1528
+ }>;
1529
+ /**
1530
+ * Retrieve the resolved variant configuration stored by `.withVariants()`.
1531
+ * Returns `null` when the schema is not polymorphic.
1532
+ *
1533
+ * @internal — used by {@link SchemaQueryBuilder}.
1534
+ */
1535
+ export declare function getVariants(schema: ObjectSchemaBuilder<any, any, any, any, any, any, any>): Omit<ResolvedVariantConfig, 'discriminatorColumn'> | null;
1536
+ /**
1537
+ * Retrieve the array of variant `ObjectSchemaBuilder` instances stored by
1538
+ * `.withVariants()`. Used by migration / DDL tools to discover variant
1539
+ * tables without walking the full schema tree.
1540
+ *
1541
+ * @internal
1542
+ */
1543
+ export declare function getPolymorphicVariantSchemas(schema: ObjectSchemaBuilder<any, any, any, any, any, any, any>): ObjectSchemaBuilder<any, any, any, any, any, any, any>[];