alepha 0.10.7 → 0.11.1

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/postgres.d.ts CHANGED
@@ -1,80 +1,23 @@
1
1
  import * as _alepha_core1 from "alepha";
2
- import { Alepha, AlephaError, Descriptor, KIND, Service, Static, TArray, TBigInt, TBoolean, TInteger, TNull, TNumber, TNumberOptions, TObject, TObjectOptions, TOptional, TOptionalAdd, TRecord, TSchema as TSchema$1, TString, TStringOptions, TUnion } from "alepha";
3
- import * as drizzle_orm6 from "drizzle-orm";
4
- import { BuildColumns, BuildExtraConfigColumns, SQL, SQLWrapper, TableConfig, sql } from "drizzle-orm";
5
- import * as pg$1 from "drizzle-orm/pg-core";
6
- import { AnyPgColumn, AnyPgTable, LockConfig, LockStrength, PgColumn, PgColumnBuilderBase, PgDatabase, PgInsertValue, PgSelectBase, PgSequenceOptions, PgTableExtraConfigValue, PgTableWithColumns, PgTransaction, PgTransactionConfig, TableConfig as TableConfig$1, UpdateDeleteAction } from "drizzle-orm/pg-core";
2
+ import { Alepha, AlephaError, Descriptor, DescriptorArgs, KIND, Static, StaticEncode, TArray, TBigInt, TBoolean, TInteger, TNull, TNumber, TNumberOptions, TObject, TObjectOptions, TOptional, TOptionalAdd, TRecord, TSchema, TString, TStringOptions, TUnion, TUnsafe } from "alepha";
7
3
  import { DateTime, DateTimeProvider } from "alepha/datetime";
8
- import * as _alepha_logger1 from "alepha/logger";
4
+ import * as _alepha_logger0 from "alepha/logger";
9
5
  import * as _alepha_lock0 from "alepha/lock";
10
- import { PostgresJsDatabase } from "drizzle-orm/postgres-js";
11
- import postgres from "postgres";
12
6
  import * as _alepha_retry0 from "alepha/retry";
13
- import * as typebox0 from "typebox";
7
+ import * as drizzle_orm0 from "drizzle-orm";
8
+ import { BuildExtraConfigColumns, SQL, SQLWrapper, sql } from "drizzle-orm";
9
+ import * as drizzle_orm_pg_core0 from "drizzle-orm/pg-core";
10
+ import { LockConfig, LockStrength, PgColumn, PgColumnBuilderBase, PgDatabase, PgInsertValue, PgSchema, PgSelectBase, PgSequenceOptions, PgTableExtraConfigValue, PgTableWithColumns, PgTransaction, PgTransactionConfig, UpdateDeleteAction } from "drizzle-orm/pg-core";
11
+ import * as typebox4 from "typebox";
14
12
  import { PgTransactionConfig as PgTransactionConfig$1 } from "drizzle-orm/pg-core/session";
15
13
  import * as DrizzleKit from "drizzle-kit/api";
16
14
  import { MigrationConfig } from "drizzle-orm/migrator";
15
+ import { PostgresJsDatabase } from "drizzle-orm/postgres-js";
16
+ import postgres from "postgres";
17
+ import * as dayjs0 from "dayjs";
17
18
  import { UpdateDeleteAction as UpdateDeleteAction$1 } from "drizzle-orm/pg-core/foreign-keys";
18
19
  export * from "drizzle-orm/pg-core";
19
20
 
20
- //#region src/constants/PG_SCHEMA.d.ts
21
- declare const PG_SCHEMA: unique symbol;
22
- //#endregion
23
- //#region src/constants/PG_SYMBOLS.d.ts
24
- declare const PG_DEFAULT: unique symbol;
25
- declare const PG_PRIMARY_KEY: unique symbol;
26
- declare const PG_CREATED_AT: unique symbol;
27
- declare const PG_UPDATED_AT: unique symbol;
28
- declare const PG_DELETED_AT: unique symbol;
29
- declare const PG_VERSION: unique symbol;
30
- declare const PG_IDENTITY: unique symbol;
31
- declare const PG_MANY: unique symbol;
32
- declare const PG_ONE: unique symbol;
33
- declare const PG_REF: unique symbol;
34
- /**
35
- * @deprecated Use `PG_IDENTITY` instead.
36
- */
37
- declare const PG_SERIAL: unique symbol;
38
- type PgDefault = typeof PG_DEFAULT;
39
- type PgMany = typeof PG_MANY;
40
- type PgOne = typeof PG_ONE;
41
- type PgRef = typeof PG_REF;
42
- type PgPrimaryKey = typeof PG_PRIMARY_KEY;
43
- type PgSymbols = {
44
- [PG_DEFAULT]: {};
45
- [PG_PRIMARY_KEY]: {};
46
- [PG_CREATED_AT]: {};
47
- [PG_UPDATED_AT]: {};
48
- [PG_DELETED_AT]: {};
49
- [PG_VERSION]: {};
50
- [PG_IDENTITY]: PgIdentityOptions;
51
- [PG_MANY]: PgManyOptions;
52
- [PG_ONE]: PgManyOptions;
53
- [PG_REF]: PgRefOptions;
54
- /**
55
- * @deprecated Use `PG_IDENTITY` instead.
56
- */
57
- [PG_SERIAL]: {};
58
- };
59
- type PgSymbolKeys = keyof PgSymbols;
60
- type PgIdentityOptions = {
61
- mode: "always" | "byDefault";
62
- } & PgSequenceOptions & {
63
- name?: string;
64
- };
65
- interface PgManyOptions {
66
- table: AnyPgTable;
67
- schema: TObject;
68
- foreignKey: string;
69
- }
70
- interface PgRefOptions {
71
- ref: () => AnyPgColumn;
72
- actions?: {
73
- onUpdate?: UpdateDeleteAction;
74
- onDelete?: UpdateDeleteAction;
75
- };
76
- }
77
- //#endregion
78
21
  //#region src/schemas/insertSchema.d.ts
79
22
  /**
80
23
  * Transforms a TObject schema for insert operations.
@@ -84,11 +27,11 @@ interface PgRefOptions {
84
27
  * Before: { name: string; age: number(default=0); }
85
28
  * After: { name: string; age?: number; }
86
29
  */
87
- type TObjectInsert<T$1 extends TObject> = TObject<{ [K in keyof T$1["properties"]]: T$1["properties"][K] extends {
30
+ type TObjectInsert<T extends TObject> = TObject<{ [K in keyof T["properties"]]: T["properties"][K] extends {
88
31
  [PG_DEFAULT]: any;
89
32
  } | {
90
33
  "~optional": true;
91
- } ? TOptional<T$1["properties"][K]> : T$1["properties"][K] }>;
34
+ } ? TOptional<T["properties"][K]> : T["properties"][K] }>;
92
35
  declare const insertSchema: <T extends TObject>(obj: T) => TObjectInsert<T>;
93
36
  //#endregion
94
37
  //#region src/schemas/updateSchema.d.ts
@@ -101,401 +44,42 @@ declare const insertSchema: <T extends TObject>(obj: T) => TObjectInsert<T>;
101
44
  * Before: { name?: string; age: number; }
102
45
  * After: { name?: string | null; age: number; }
103
46
  */
104
- type TObjectUpdate<T$1 extends TObject> = TObject<{ [K in keyof T$1["properties"]]: T$1["properties"][K] extends TOptional<infer U> ? TOptional<TUnion<[U, TNull]>> : T$1["properties"][K] }>;
47
+ type TObjectUpdate<T extends TObject> = TObject<{ [K in keyof T["properties"]]: T["properties"][K] extends TOptional<infer U> ? TOptional<TUnion<[U, TNull]>> : T["properties"][K] }>;
105
48
  declare const updateSchema: <T extends TObject>(schema: T) => TObjectUpdate<T>;
106
49
  //#endregion
107
- //#region src/helpers/schemaToPgColumns.d.ts
108
- /**
109
- * Convert a Typebox Schema to Drizzle ORM Postgres columns
110
- */
111
- declare const schemaToPgColumns: <T extends TObject>(schema: T) => FromSchema<T>;
112
- /**
113
- * Map a Typebox field to a PG column.
114
- *
115
- * @param name The key of the field.
116
- * @param value The value of the field.
117
- * @returns The PG column.
118
- */
119
- declare const mapFieldToColumn: (name: string, value: TSchema$1) => pg$1.PgSerialBuilderInitial<string> | pg$1.PgIntegerBuilderInitial<string> | drizzle_orm6.IsIdentity<pg$1.PgBigInt64BuilderInitial<"">, "byDefault"> | drizzle_orm6.IsIdentity<pg$1.PgBigInt64BuilderInitial<"">, "always"> | pg$1.PgBigInt53BuilderInitial<string> | pg$1.PgNumericBuilderInitial<string> | pg$1.PgDateStringBuilderInitial<string> | pg$1.PgUUIDBuilderInitial<string> | pg$1.PgCustomColumnBuilder<{
120
- name: string;
121
- dataType: "custom";
122
- columnType: "PgCustomColumn";
123
- data: Buffer<ArrayBufferLike>;
124
- driverParam: unknown;
125
- enumValues: undefined;
126
- }> | pg$1.PgTimestampStringBuilderInitial<string> | pg$1.PgTextBuilderInitial<string, [string, ...string[]]> | pg$1.PgBooleanBuilderInitial<string> | drizzle_orm6.$Type<pg$1.PgCustomColumnBuilder<{
127
- name: string;
128
- dataType: "custom";
129
- columnType: "PgCustomColumn";
130
- data: {
131
- [x: string]: unknown;
132
- [x: number]: unknown;
133
- [x: symbol]: unknown;
134
- };
135
- driverParam: string;
136
- enumValues: undefined;
137
- }>, {
138
- [x: string]: unknown;
139
- [x: number]: unknown;
140
- [x: symbol]: unknown;
141
- }> | drizzle_orm6.$Type<pg$1.PgCustomColumnBuilder<{
142
- name: string;
143
- dataType: "custom";
144
- columnType: "PgCustomColumn";
145
- data: Record<string, unknown>;
146
- driverParam: string;
147
- enumValues: undefined;
148
- }>, Record<string, unknown>> | drizzle_orm6.$Type<pg$1.PgCustomColumnBuilder<{
149
- name: string;
150
- dataType: "custom";
151
- columnType: "PgCustomColumn";
152
- data: unknown[];
153
- driverParam: string;
154
- enumValues: undefined;
155
- }>, unknown[]> | pg$1.PgArrayBuilder<{
156
- name: string;
157
- dataType: "array";
158
- columnType: "PgArray";
159
- data: string[];
160
- driverParam: string | string[];
161
- enumValues: [string, ...string[]];
162
- size: undefined;
163
- baseBuilder: {
164
- name: string;
165
- dataType: "string";
166
- columnType: "PgText";
167
- data: string;
168
- enumValues: [string, ...string[]];
169
- driverParam: string;
170
- };
171
- }, {
172
- name: string;
173
- dataType: "string";
174
- columnType: "PgText";
175
- data: string;
176
- enumValues: [string, ...string[]];
177
- driverParam: string;
178
- }> | pg$1.PgArrayBuilder<{
179
- name: string;
180
- dataType: "array";
181
- columnType: "PgArray";
182
- data: number[];
183
- driverParam: string | (string | number)[];
184
- enumValues: undefined;
185
- size: undefined;
186
- baseBuilder: {
187
- name: string;
188
- dataType: "number";
189
- columnType: "PgInteger";
190
- data: number;
191
- driverParam: number | string;
192
- enumValues: undefined;
193
- };
194
- }, {
195
- name: string;
196
- dataType: "number";
197
- columnType: "PgInteger";
198
- data: number;
199
- driverParam: number | string;
200
- enumValues: undefined;
201
- }> | pg$1.PgArrayBuilder<{
202
- name: string;
203
- dataType: "array";
204
- columnType: "PgArray";
205
- data: string[];
206
- driverParam: string | string[];
207
- enumValues: undefined;
208
- size: undefined;
209
- baseBuilder: {
210
- name: string;
211
- dataType: "string";
212
- columnType: "PgNumeric";
213
- data: string;
214
- driverParam: string;
215
- enumValues: undefined;
216
- };
217
- }, {
218
- name: string;
219
- dataType: "string";
220
- columnType: "PgNumeric";
221
- data: string;
222
- driverParam: string;
223
- enumValues: undefined;
224
- }> | pg$1.PgArrayBuilder<{
225
- name: string;
226
- dataType: "array";
227
- columnType: "PgArray";
228
- data: boolean[];
229
- driverParam: string | boolean[];
230
- enumValues: undefined;
231
- size: undefined;
232
- baseBuilder: {
233
- name: string;
234
- dataType: "boolean";
235
- columnType: "PgBoolean";
236
- data: boolean;
237
- driverParam: boolean;
238
- enumValues: undefined;
239
- };
240
- }, {
241
- name: string;
242
- dataType: "boolean";
243
- columnType: "PgBoolean";
244
- data: boolean;
245
- driverParam: boolean;
246
- enumValues: undefined;
247
- }>;
248
- /**
249
- * Map a string to a PG column.
250
- *
251
- * @param key The key of the field.
252
- * @param value The value of the field.
253
- */
254
- declare const mapStringToColumn: (key: string, value: TSchema$1) => pg$1.PgDateStringBuilderInitial<string> | pg$1.PgUUIDBuilderInitial<string> | pg$1.PgCustomColumnBuilder<{
255
- name: string;
256
- dataType: "custom";
257
- columnType: "PgCustomColumn";
258
- data: Buffer<ArrayBufferLike>;
259
- driverParam: unknown;
260
- enumValues: undefined;
261
- }> | pg$1.PgTimestampStringBuilderInitial<string> | pg$1.PgTextBuilderInitial<string, [string, ...string[]]>;
262
- declare const camelToSnakeCase: (str: string) => string;
263
- /**
264
- * Convert a schema to columns.
265
- */
266
- type FromSchema<T$1 extends TObject> = { [key in keyof T$1["properties"]]: PgColumnBuilderBase };
267
- /**
268
- * A table with columns and schema.
269
- */
270
- type PgTableWithColumnsAndSchema<T$1 extends TableConfig, R$1 extends TObject> = PgTableWithColumns<T$1> & {
271
- get $table(): PgTableWithColumns<T$1>;
272
- get $schema(): R$1;
273
- get $insertSchema(): TObjectInsert<R$1>;
274
- get $updateSchema(): TObjectUpdate<R$1>;
275
- alias: (alias: string) => PgTableWithColumnsAndSchema<T$1, R$1>;
276
- };
277
- //#endregion
278
50
  //#region src/descriptors/$entity.d.ts
279
51
  /**
280
52
  * Creates a database entity descriptor that defines table structure using TypeBox schemas.
281
53
  *
282
- * This descriptor provides a type-safe way to define database tables using JSON Schema
283
- * syntax while generating the necessary database metadata for migrations and operations.
284
- * It integrates with Drizzle ORM under the hood and works seamlessly with the $repository
285
- * descriptor for complete database functionality.
286
- *
287
- * **Key Features**
288
- *
289
- * - **Type-Safe Schema Definition**: Uses TypeBox for full TypeScript type inference
290
- * - **Automatic Table Generation**: Creates Drizzle ORM table structures automatically
291
- * - **Index Management**: Supports single-column, multi-column, and unique indexes
292
- * - **Constraint Support**: Foreign keys, unique constraints, and check constraints
293
- * - **Audit Fields**: Built-in support for created_at, updated_at, deleted_at, and version fields
294
- * - **Schema Validation**: Automatic insert/update schema generation with validation
295
- *
296
- * **Important Note**:
297
- * This descriptor only defines the table structure - it does not create the physical
298
- * database table. Use it with $repository to perform actual database operations,
299
- * and run migrations to create the tables in your database.
300
- *
301
- * **Use Cases**
302
- *
303
- * Essential for defining database schema in type-safe applications:
304
- * - User management and authentication tables
305
- * - Business domain entities (products, orders, customers)
306
- * - Audit and logging tables
307
- * - Junction tables for many-to-many relationships
308
- * - Configuration and settings tables
309
- *
310
54
  * @example
311
- * **Basic entity with indexes:**
312
55
  * ```ts
56
+ * import { t } from "alepha";
313
57
  * import { $entity } from "alepha/postgres";
314
- * import { pg, t } from "alepha";
315
58
  *
316
- * const User = $entity({
59
+ * const userEntity = $entity({
317
60
  * name: "users",
318
61
  * schema: t.object({
319
- * id: pg.primaryKey(t.uuid()),
320
- * email: t.text({ format: "email" }),
321
- * username: t.text({ minLength: 3, maxLength: 30 }),
322
- * firstName: t.text(),
323
- * lastName: t.text(),
324
- * isActive: t.boolean({ default: true }),
325
- * createdAt: pg.createdAt(),
326
- * updatedAt: pg.updatedAt(),
327
- * deletedAt: pg.deletedAt()
328
- * }),
329
- * indexes: [
330
- * "email", // Simple index on email
331
- * "username", // Simple index on username
332
- * { column: "email", unique: true }, // Unique constraint on email
333
- * { columns: ["firstName", "lastName"] } // Composite index
334
- * ]
335
- * });
336
- * ```
337
- *
338
- * @example
339
- * **E-commerce product entity with relationships:**
340
- * ```ts
341
- * const Product = $entity({
342
- * name: "products",
343
- * schema: t.object({
344
- * id: pg.primaryKey(t.uuid()),
345
- * sku: t.text({ minLength: 3 }),
346
- * name: t.text({ minLength: 1, maxLength: 200 }),
347
- * description: t.optional(t.text()),
348
- * price: t.number({ minimum: 0 }),
349
- * categoryId: t.text({ format: "uuid" }),
350
- * inStock: t.boolean({ default: true }),
351
- * stockQuantity: t.integer({ minimum: 0, default: 0 }),
352
- * tags: t.optional(t.array(t.text())), // PostgreSQL array column
353
- * metadata: t.optional(t.record(t.text(), t.any())), // JSONB column
354
- * version: pg.version(),
355
- * createdAt: pg.createdAt(),
356
- * updatedAt: pg.updatedAt()
357
- * }),
358
- * indexes: [
359
- * { column: "sku", unique: true }, // Unique SKU
360
- * "categoryId", // Foreign key index
361
- * "inStock", // Filter frequently by stock status
362
- * { columns: ["categoryId", "inStock"] }, // Composite for category + stock queries
363
- * "createdAt" // For date-based queries
364
- * ],
365
- * foreignKeys: [
366
- * {
367
- * name: "fk_product_category",
368
- * columns: ["categoryId"],
369
- * foreignColumns: [Category.id] // Reference to Category entity
370
- * }
371
- * ]
372
- * });
373
- * ```
374
- *
375
- * @example
376
- * **Audit log entity with constraints:**
377
- * ```ts
378
- * const AuditLog = $entity({
379
- * name: "audit_logs",
380
- * schema: t.object({
381
- * id: pg.primaryKey(t.uuid()),
382
- * tableName: t.text(),
383
- * recordId: t.text(),
384
- * action: t.enum(["CREATE", "UPDATE", "DELETE"]),
385
- * userId: t.optional(t.text({ format: "uuid" })),
386
- * oldValues: t.optional(t.record(t.text(), t.any())),
387
- * newValues: t.optional(t.record(t.text(), t.any())),
388
- * timestamp: pg.createdAt(),
389
- * ipAddress: t.optional(t.text()),
390
- * userAgent: t.optional(t.text())
391
- * }),
392
- * indexes: [
393
- * "tableName",
394
- * "recordId",
395
- * "userId",
396
- * "action",
397
- * { columns: ["tableName", "recordId"] }, // Find all changes to a record
398
- * { columns: ["userId", "timestamp"] }, // User activity timeline
399
- * "timestamp" // Time-based queries
400
- * ],
401
- * constraints: [
402
- * {
403
- * name: "valid_action_values",
404
- * columns: ["action"],
405
- * check: sql`action IN ('CREATE', 'UPDATE', 'DELETE')`
406
- * }
407
- * ]
408
- * });
409
- * ```
410
- *
411
- * @example
412
- * **Many-to-many junction table:**
413
- * ```ts
414
- * const UserRole = $entity({
415
- * name: "user_roles",
416
- * schema: t.object({
417
- * id: pg.primaryKey(t.uuid()),
418
- * userId: t.text({ format: "uuid" }),
419
- * roleId: t.text({ format: "uuid" }),
420
- * assignedBy: t.text({ format: "uuid" }),
421
- * assignedAt: pg.createdAt(),
422
- * expiresAt: t.optional(t.datetime())
423
- * }),
424
- * indexes: [
425
- * "userId",
426
- * "roleId",
427
- * "assignedBy",
428
- * { columns: ["userId", "roleId"], unique: true }, // Prevent duplicate assignments
429
- * "expiresAt" // For cleanup of expired roles
430
- * ],
431
- * foreignKeys: [
432
- * {
433
- * columns: ["userId"],
434
- * foreignColumns: [User.id]
435
- * },
436
- * {
437
- * columns: ["roleId"],
438
- * foreignColumns: [Role.id]
439
- * },
440
- * {
441
- * columns: ["assignedBy"],
442
- * foreignColumns: [User.id]
443
- * }
444
- * ]
445
- * });
446
- * ```
447
- *
448
- * @example
449
- * **Entity with custom Drizzle configuration:**
450
- * ```ts
451
- * const Order = $entity({
452
- * name: "orders",
453
- * schema: t.object({
454
- * id: pg.primaryKey(t.uuid()),
455
- * orderNumber: t.text(),
456
- * customerId: t.text({ format: "uuid" }),
457
- * status: t.enum(["pending", "processing", "shipped", "delivered"]),
458
- * totalAmount: t.number({ minimum: 0 }),
459
- * currency: t.text({ default: "USD" }),
460
- * notes: t.optional(t.text()),
461
- * createdAt: pg.createdAt(),
462
- * updatedAt: pg.updatedAt(),
463
- * version: pg.version()
62
+ * id: pg.primaryKey(),
63
+ * name: t.text(),
64
+ * email: t.email(),
464
65
  * }),
465
- * indexes: [
466
- * { column: "orderNumber", unique: true },
467
- * "customerId",
468
- * "status",
469
- * "createdAt",
470
- * { columns: ["customerId", "status"] }
471
- * ],
472
- * // Advanced Drizzle ORM configuration
473
- * config: (table) => [
474
- * // Custom index with specific options
475
- * index("idx_orders_amount_status")
476
- * .on(table.totalAmount, table.status)
477
- * .where(sql`status != 'cancelled'`), // Partial index
478
- *
479
- * // Full-text search index (PostgreSQL specific)
480
- * index("idx_orders_search")
481
- * .using("gin", table.notes)
482
- * ]
483
66
  * });
484
67
  * ```
485
68
  */
486
69
  declare const $entity: {
487
- <TTableName extends string, TSchema extends TObject, TColumnsMap extends FromSchema<TSchema>>(options: EntityDescriptorOptions<TTableName, TSchema>): PgTableWithColumnsAndSchema<PgTableConfig<TTableName, TSchema, TColumnsMap>, TSchema>;
488
- [KIND]: string;
70
+ <TSchema$1 extends TObject>(options: EntityDescriptorOptions<TSchema$1>): EntityDescriptor<TSchema$1>;
71
+ [KIND]: typeof EntityDescriptor;
489
72
  };
490
- interface EntityDescriptorOptions<TTableName$1 extends string, T$1 extends TObject, Keys = keyof Static<T$1>> {
73
+ interface EntityDescriptorOptions<T extends TObject, Keys = keyof Static<T>> {
491
74
  /**
492
75
  * The database table name that will be created for this entity.
76
+ * If not provided, name will be inferred from the $repository variable name.
493
77
  */
494
- name: TTableName$1;
78
+ name: string;
495
79
  /**
496
80
  * TypeBox schema defining the table structure and column types.
497
81
  */
498
- schema: T$1;
82
+ schema: T;
499
83
  /**
500
84
  * Database indexes to create for query optimization.
501
85
  */
@@ -537,11 +121,12 @@ interface EntityDescriptorOptions<TTableName$1 extends string, T$1 extends TObje
537
121
  /**
538
122
  * Local columns that reference the foreign table.
539
123
  */
540
- columns: Array<keyof Static<T$1>>;
124
+ columns: Array<keyof Static<T>>;
541
125
  /**
542
126
  * Referenced columns in the foreign table.
127
+ * Must be EntityColumn references from other entities.
543
128
  */
544
- foreignColumns: Array<AnyPgColumn>;
129
+ foreignColumns: Array<() => EntityColumn<any>>;
545
130
  }>;
546
131
  /**
547
132
  * Additional table constraints for data validation.
@@ -553,12 +138,6 @@ interface EntityDescriptorOptions<TTableName$1 extends string, T$1 extends TObje
553
138
  * - **Unique constraints**: Prevent duplicate values across columns
554
139
  * - **Check constraints**: Enforce custom validation rules with SQL expressions
555
140
  *
556
- * **Use Cases**:
557
- * - Enforce unique combinations of columns
558
- * - Validate value ranges or patterns
559
- * - Ensure consistent data states
560
- * - Implement business rule validation
561
- *
562
141
  * @example
563
142
  * ```ts
564
143
  * constraints: [
@@ -584,7 +163,7 @@ interface EntityDescriptorOptions<TTableName$1 extends string, T$1 extends TObje
584
163
  /**
585
164
  * Columns involved in this constraint.
586
165
  */
587
- columns: Array<keyof Static<T$1>>;
166
+ columns: Array<keyof Static<T>>;
588
167
  /**
589
168
  * Optional name for the constraint.
590
169
  */
@@ -600,52 +179,86 @@ interface EntityDescriptorOptions<TTableName$1 extends string, T$1 extends TObje
600
179
  }>;
601
180
  /**
602
181
  * Advanced Drizzle ORM configuration for complex table setups.
603
- *
604
- * This allows you to use advanced Drizzle ORM features that aren't covered
605
- * by the simplified options above. Use this for:
606
- * - Custom index types (GIN, GIST, etc.)
607
- * - Partial indexes with WHERE clauses
608
- * - Advanced constraint configurations
609
- * - PostgreSQL-specific features
610
- *
611
- * **When to Use**:
612
- * - Need PostgreSQL-specific index types
613
- * - Require partial indexes for performance
614
- * - Want fine-grained control over table creation
615
- * - Using advanced PostgreSQL features
616
- *
617
- * See Drizzle ORM documentation for complete configuration options.
618
- *
619
- * @param self - The table columns available for configuration
620
- * @returns Array of Drizzle table configuration objects
621
- *
622
- * @example
623
- * ```ts
624
- * config: (table) => [
625
- * // Partial index for active users only
626
- * index("idx_active_users_email")
627
- * .on(table.email)
628
- * .where(sql`is_active = true`),
629
- *
630
- * // GIN index for full-text search
631
- * index("idx_content_search")
632
- * .using("gin", table.searchVector),
633
- *
634
- * // Unique constraint with custom options
635
- * uniqueIndex("idx_unique_slug_per_tenant")
636
- * .on(table.tenantId, table.slug)
637
- * ]
638
- * ```
639
182
  */
640
- config?: (self: BuildExtraConfigColumns<string, FromSchema<T$1>, "pg">) => PgTableExtraConfigValue[];
183
+ config?: (self: BuildExtraConfigColumns<string, FromSchema<T>, "pg">) => PgTableExtraConfigValue[];
641
184
  }
642
- type Entity<T$1 extends TObject> = PgTableWithColumnsAndSchema<PgTableConfig<string, T$1, FromSchema<T$1>>, T$1>;
643
- type PgTableConfig<TTableName$1 extends string, TSchema$2 extends TObject, TColumnsMap$1 extends FromSchema<TSchema$2>> = {
644
- name: TTableName$1;
645
- schema: any;
646
- columns: BuildColumns<TTableName$1, TColumnsMap$1, "pg">;
647
- dialect: "pg";
185
+ declare class EntityDescriptor<T extends TObject = TObject> {
186
+ readonly options: EntityDescriptorOptions<T>;
187
+ constructor(options: EntityDescriptorOptions<T>);
188
+ alias(alias: string): this;
189
+ get cols(): EntityColumns<T>;
190
+ get name(): string;
191
+ get schema(): T;
192
+ get insertSchema(): TObjectInsert<T>;
193
+ get updateSchema(): TObjectUpdate<T>;
194
+ }
195
+ /**
196
+ * Convert a schema to columns.
197
+ */
198
+ type FromSchema<T extends TObject> = { [key in keyof T["properties"]]: PgColumnBuilderBase };
199
+ type SchemaToTableConfig<T extends TObject> = {
200
+ name: string;
201
+ schema: string | undefined;
202
+ columns: { [key in keyof T["properties"]]: PgColumn };
203
+ dialect: string;
204
+ };
205
+ type EntityColumn<T extends TObject> = {
206
+ name: string;
207
+ entity: EntityDescriptor<T>;
208
+ };
209
+ type EntityColumns<T extends TObject> = { [key in keyof T["properties"]]: EntityColumn<T> };
210
+ //#endregion
211
+ //#region src/constants/PG_SYMBOLS.d.ts
212
+ declare const PG_DEFAULT: unique symbol;
213
+ declare const PG_PRIMARY_KEY: unique symbol;
214
+ declare const PG_CREATED_AT: unique symbol;
215
+ declare const PG_UPDATED_AT: unique symbol;
216
+ declare const PG_DELETED_AT: unique symbol;
217
+ declare const PG_VERSION: unique symbol;
218
+ declare const PG_IDENTITY: unique symbol;
219
+ declare const PG_ENUM: unique symbol;
220
+ declare const PG_REF: unique symbol;
221
+ /**
222
+ * @deprecated Use `PG_IDENTITY` instead.
223
+ */
224
+ declare const PG_SERIAL: unique symbol;
225
+ type PgDefault = typeof PG_DEFAULT;
226
+ type PgRef = typeof PG_REF;
227
+ type PgPrimaryKey = typeof PG_PRIMARY_KEY;
228
+ type PgSymbols = {
229
+ [PG_DEFAULT]: {};
230
+ [PG_PRIMARY_KEY]: {};
231
+ [PG_CREATED_AT]: {};
232
+ [PG_UPDATED_AT]: {};
233
+ [PG_DELETED_AT]: {};
234
+ [PG_VERSION]: {};
235
+ [PG_IDENTITY]: PgIdentityOptions;
236
+ [PG_REF]: PgRefOptions;
237
+ [PG_ENUM]: PgEnumOptions;
238
+ /**
239
+ * @deprecated Use `PG_IDENTITY` instead.
240
+ */
241
+ [PG_SERIAL]: {};
242
+ };
243
+ type PgSymbolKeys = keyof PgSymbols;
244
+ type PgIdentityOptions = {
245
+ mode: "always" | "byDefault";
246
+ } & PgSequenceOptions & {
247
+ name?: string;
648
248
  };
249
+ interface PgEnumOptions {
250
+ name?: string;
251
+ }
252
+ interface PgRefOptions {
253
+ ref: () => {
254
+ name: string;
255
+ entity: EntityDescriptor;
256
+ };
257
+ actions?: {
258
+ onUpdate?: UpdateDeleteAction;
259
+ onDelete?: UpdateDeleteAction;
260
+ };
261
+ }
649
262
  //#endregion
650
263
  //#region src/errors/PgError.d.ts
651
264
  declare class PgError extends AlephaError {
@@ -653,6 +266,39 @@ declare class PgError extends AlephaError {
653
266
  constructor(message: string, cause?: unknown);
654
267
  }
655
268
  //#endregion
269
+ //#region src/helpers/pgAttr.d.ts
270
+ /**
271
+ * Decorates a typebox schema with a Postgres attribute.
272
+ *
273
+ * > It's just a fancy way to add Symbols to a field.
274
+ *
275
+ * @example
276
+ * ```ts
277
+ * import { t } from "alepha";
278
+ * import { PG_UPDATED_AT } from "../constants/PG_SYMBOLS";
279
+ *
280
+ * export const updatedAtSchema = pgAttr(
281
+ * t.datetime(), PG_UPDATED_AT,
282
+ * );
283
+ * ```
284
+ */
285
+ declare const pgAttr: <T extends TSchema, Attr extends PgSymbolKeys>(type: T, attr: Attr, value?: PgSymbols[Attr]) => PgAttr<T, Attr>;
286
+ /**
287
+ * Retrieves the fields of a schema that have a specific attribute.
288
+ */
289
+ declare const getAttrFields: (schema: TObject, name: PgSymbolKeys) => PgAttrField[];
290
+ /**
291
+ * Type representation.
292
+ */
293
+ type PgAttr<T extends TSchema, TAttr extends PgSymbolKeys> = T & { [K in TAttr]: PgSymbols[K] };
294
+ interface PgAttrField {
295
+ key: string;
296
+ type: TSchema;
297
+ data: any;
298
+ nested?: any[];
299
+ one?: boolean;
300
+ }
301
+ //#endregion
656
302
  //#region src/interfaces/FilterOperators.d.ts
657
303
  interface FilterOperators<TValue> {
658
304
  /**
@@ -1009,55 +655,11 @@ interface FilterOperators<TValue> {
1009
655
  arrayOverlaps?: TValue;
1010
656
  }
1011
657
  //#endregion
1012
- //#region src/interfaces/PgQuery.d.ts
1013
- /**
1014
- * Order direction for sorting
1015
- */
1016
- type OrderDirection = "asc" | "desc";
1017
- /**
1018
- * Single order by clause with column and direction
1019
- */
1020
- interface OrderByClause<T$1> {
1021
- column: keyof T$1;
1022
- direction?: OrderDirection;
1023
- }
1024
- /**
1025
- * Order by parameter - supports 3 modes:
1026
- * 1. String: orderBy: "name" (defaults to ASC)
1027
- * 2. Single object: orderBy: { column: "name", direction: "desc" }
1028
- * 3. Array: orderBy: [{ column: "name", direction: "asc" }, { column: "age", direction: "desc" }]
1029
- */
1030
- type OrderBy<T$1> = keyof T$1 | OrderByClause<T$1> | Array<OrderByClause<T$1>>;
1031
- /**
1032
- * Generic query interface for PostgreSQL entities
1033
- */
1034
- interface PgQuery<T$1 extends TObject = TObject> {
1035
- distinct?: (keyof Static<T$1>)[];
1036
- columns?: (keyof Static<T$1>)[];
1037
- where?: PgQueryWhereOrSQL<T$1>;
1038
- limit?: number;
1039
- offset?: number;
1040
- orderBy?: OrderBy<Static<T$1>>;
1041
- groupBy?: (keyof Static<T$1>)[];
1042
- }
1043
- type PgStatic<T$1 extends TObject, Relations extends PgRelationMap<T$1>> = Static<T$1> & { [K in keyof Relations]: Static<Relations[K]["join"]["$schema"]> & (Relations[K]["with"] extends PgRelationMap<TObject> ? PgStatic<Relations[K]["join"]["$schema"], Relations[K]["with"]> : {}) };
1044
- interface PgQueryRelations<T$1 extends TObject = TObject, Relations extends PgRelationMap<T$1> | undefined = undefined> extends PgQuery<T$1> {
1045
- with?: Relations;
1046
- where?: PgQueryWhereOrSQL<T$1, Relations>;
1047
- }
1048
- type PgRelationMap<Base extends TObject> = Record<string, PgRelation<Base>>;
1049
- type PgRelation<Base extends TObject> = {
1050
- type?: "left" | "inner" | "right";
1051
- join: PgTableWithColumnsAndSchema<any, TObject>;
1052
- on: SQLWrapper | [keyof Static<Base>, PgColumn];
1053
- with?: PgRelationMap<TObject>;
1054
- };
1055
- //#endregion
1056
658
  //#region src/interfaces/PgQueryWhere.d.ts
1057
- type PgQueryWhere<T$1 extends TObject, Relations extends PgRelationMap<TObject> | undefined = undefined> = (PgQueryWhereOperators<T$1> & PgQueryWhereConditions<T$1>) | (PgQueryWhereRelations<Relations> & PgQueryWhereOperators<T$1> & PgQueryWhereConditions<T$1, Relations>);
1058
- type PgQueryWhereOrSQL<T$1 extends TObject, Relations extends PgRelationMap<TObject> | undefined = undefined> = SQLWrapper | PgQueryWhere<T$1, Relations>;
1059
- type PgQueryWhereOperators<T$1 extends TObject> = { [Key in keyof Static<T$1>]?: FilterOperators<Static<T$1>[Key]> | Static<T$1>[Key] | (Static<T$1>[Key] extends object ? NestedJsonbQuery<Static<T$1>[Key]> : never) };
1060
- type PgQueryWhereConditions<T$1 extends TObject, Relations extends PgRelationMap<TObject> | undefined = undefined> = {
659
+ type PgQueryWhere<T extends TObject, Relations extends PgRelationMap<TObject> | undefined = undefined> = (PgQueryWhereOperators<T> & PgQueryWhereConditions<T>) | (PgQueryWhereRelations<Relations> & PgQueryWhereOperators<T> & PgQueryWhereConditions<T, Relations>);
660
+ type PgQueryWhereOrSQL<T extends TObject, Relations extends PgRelationMap<TObject> | undefined = undefined> = SQLWrapper | PgQueryWhere<T, Relations>;
661
+ type PgQueryWhereOperators<T extends TObject> = { [Key in keyof Static<T>]?: FilterOperators<Static<T>[Key]> | Static<T>[Key] | (Static<T>[Key] extends object ? NestedJsonbQuery<Static<T>[Key]> : never) };
662
+ type PgQueryWhereConditions<T extends TObject, Relations extends PgRelationMap<TObject> | undefined = undefined> = {
1061
663
  /**
1062
664
  * Combine a list of conditions with the `and` operator. Conditions
1063
665
  * that are equal `undefined` are automatically ignored.
@@ -1074,7 +676,7 @@ type PgQueryWhereConditions<T$1 extends TObject, Relations extends PgRelationMap
1074
676
  * )
1075
677
  * ```
1076
678
  */
1077
- and?: Array<PgQueryWhereOrSQL<T$1, Relations>>;
679
+ and?: Array<PgQueryWhereOrSQL<T, Relations>>;
1078
680
  /**
1079
681
  * Combine a list of conditions with the `or` operator. Conditions
1080
682
  * that are equal `undefined` are automatically ignored.
@@ -1091,7 +693,7 @@ type PgQueryWhereConditions<T$1 extends TObject, Relations extends PgRelationMap
1091
693
  * )
1092
694
  * ```
1093
695
  */
1094
- or?: Array<PgQueryWhereOrSQL<T$1, Relations>>;
696
+ or?: Array<PgQueryWhereOrSQL<T, Relations>>;
1095
697
  /**
1096
698
  * Negate the meaning of an expression using the `not` keyword.
1097
699
  *
@@ -1103,7 +705,7 @@ type PgQueryWhereConditions<T$1 extends TObject, Relations extends PgRelationMap
1103
705
  * .where(not(inArray(cars.make, ['GM', 'Ford'])))
1104
706
  * ```
1105
707
  */
1106
- not?: PgQueryWhereOrSQL<T$1, Relations>;
708
+ not?: PgQueryWhereOrSQL<T, Relations>;
1107
709
  /**
1108
710
  * Test whether a subquery evaluates to have any rows.
1109
711
  *
@@ -1126,11 +728,167 @@ type PgQueryWhereConditions<T$1 extends TObject, Relations extends PgRelationMap
1126
728
  */
1127
729
  exists?: SQLWrapper;
1128
730
  };
1129
- type PgQueryWhereRelations<Relations extends PgRelationMap<TObject> | undefined = undefined> = Relations extends PgRelationMap<TObject> ? { [K in keyof Relations]?: PgQueryWhere<Relations[K]["join"]["$schema"], Relations[K]["with"]> } : {};
731
+ type PgQueryWhereRelations<Relations extends PgRelationMap<TObject> | undefined = undefined> = Relations extends PgRelationMap<TObject> ? { [K in keyof Relations]?: PgQueryWhere<Relations[K]["join"]["schema"], Relations[K]["with"]> } : {};
732
+ /**
733
+ * Recursively allow nested queries for JSONB object/array types
734
+ */
735
+ type NestedJsonbQuery<T> = T extends object ? T extends Array<infer U> ? U extends object ? { [K in keyof U]?: FilterOperators<U[K]> | U[K] } : FilterOperators<U> | U : { [K in keyof T]?: FilterOperators<T[K]> | T[K] | (T[K] extends object ? NestedJsonbQuery<T[K]> : never) } : FilterOperators<T> | T;
736
+ //#endregion
737
+ //#region src/interfaces/PgQuery.d.ts
738
+ /**
739
+ * Order direction for sorting
740
+ */
741
+ type OrderDirection = "asc" | "desc";
742
+ /**
743
+ * Single order by clause with column and direction
744
+ */
745
+ interface OrderByClause<T> {
746
+ column: keyof T;
747
+ direction?: OrderDirection;
748
+ }
749
+ /**
750
+ * Order by parameter - supports 3 modes:
751
+ * 1. String: orderBy: "name" (defaults to ASC)
752
+ * 2. Single object: orderBy: { column: "name", direction: "desc" }
753
+ * 3. Array: orderBy: [{ column: "name", direction: "asc" }, { column: "age", direction: "desc" }]
754
+ */
755
+ type OrderBy<T> = keyof T | OrderByClause<T> | Array<OrderByClause<T>>;
756
+ /**
757
+ * Generic query interface for PostgreSQL entities
758
+ */
759
+ interface PgQuery<T extends TObject = TObject> {
760
+ distinct?: (keyof Static<T>)[];
761
+ columns?: (keyof Static<T>)[];
762
+ where?: PgQueryWhereOrSQL<T>;
763
+ limit?: number;
764
+ offset?: number;
765
+ orderBy?: OrderBy<Static<T>>;
766
+ groupBy?: (keyof Static<T>)[];
767
+ }
768
+ type PgStatic<T extends TObject, Relations extends PgRelationMap<T>> = Static<T> & { [K in keyof Relations]: Static<Relations[K]["join"]["schema"]> & (Relations[K]["with"] extends PgRelationMap<TObject> ? PgStatic<Relations[K]["join"]["schema"], Relations[K]["with"]> : {}) };
769
+ interface PgQueryRelations<T extends TObject = TObject, Relations extends PgRelationMap<T> | undefined = undefined> extends PgQuery<T> {
770
+ with?: Relations;
771
+ where?: PgQueryWhereOrSQL<T, Relations>;
772
+ }
773
+ type PgRelationMap<Base extends TObject> = Record<string, PgRelation<Base>>;
774
+ type PgRelation<Base extends TObject> = {
775
+ type?: "left" | "inner" | "right";
776
+ join: {
777
+ schema: TObject;
778
+ name: string;
779
+ };
780
+ on: SQLWrapper | [keyof Static<Base>, {
781
+ name: string;
782
+ }];
783
+ with?: PgRelationMap<TObject>;
784
+ };
785
+ //#endregion
786
+ //#region src/descriptors/$sequence.d.ts
787
+ /**
788
+ * Creates a PostgreSQL sequence descriptor for generating unique numeric values.
789
+ */
790
+ declare const $sequence: {
791
+ (options?: SequenceDescriptorOptions): SequenceDescriptor;
792
+ [KIND]: typeof SequenceDescriptor;
793
+ };
794
+ interface SequenceDescriptorOptions extends PgSequenceOptions {
795
+ /**
796
+ * The name of the sequence. If not provided, the property key will be used.
797
+ */
798
+ name?: string;
799
+ provider?: DatabaseProvider;
800
+ }
801
+ declare class SequenceDescriptor extends Descriptor<SequenceDescriptorOptions> {
802
+ readonly provider: DatabaseProvider;
803
+ onInit(): void;
804
+ get name(): string;
805
+ next(): Promise<number>;
806
+ current(): Promise<number>;
807
+ protected $provider(): DatabaseProvider;
808
+ }
809
+ //#endregion
810
+ //#region src/services/ModelBuilder.d.ts
1130
811
  /**
1131
- * Recursively allow nested queries for JSONB object/array types
812
+ * Database-specific table configuration functions
813
+ */
814
+ interface TableConfigBuilders<TConfig> {
815
+ index: (name: string) => {
816
+ on: (...columns: any[]) => TConfig;
817
+ };
818
+ uniqueIndex: (name: string) => {
819
+ on: (...columns: any[]) => TConfig;
820
+ };
821
+ unique: (name: string) => {
822
+ on: (...columns: any[]) => TConfig;
823
+ };
824
+ check: (name: string, sql: SQL) => TConfig;
825
+ foreignKey: (config: {
826
+ name: string;
827
+ columns: any[];
828
+ foreignColumns: any[];
829
+ }) => TConfig;
830
+ }
831
+ /**
832
+ * Abstract base class for transforming Alepha Descriptors (Entity, Sequence, etc...)
833
+ * into drizzle models (tables, enums, sequences, etc...).
1132
834
  */
1133
- type NestedJsonbQuery<T$1> = T$1 extends object ? T$1 extends Array<infer U> ? U extends object ? { [K in keyof U]?: FilterOperators<U[K]> | U[K] } : FilterOperators<U> | U : { [K in keyof T$1]?: FilterOperators<T$1[K]> | T$1[K] | (T$1[K] extends object ? NestedJsonbQuery<T$1[K]> : never) } : FilterOperators<T$1> | T$1;
835
+ declare abstract class ModelBuilder {
836
+ /**
837
+ * Build a table from an entity descriptor.
838
+ */
839
+ abstract buildTable(entity: EntityDescriptor, options: {
840
+ tables: Map<string, unknown>;
841
+ enums: Map<string, unknown>;
842
+ schema: string;
843
+ }): void;
844
+ /**
845
+ * Build a sequence from a sequence descriptor.
846
+ */
847
+ abstract buildSequence(sequence: SequenceDescriptor, options: {
848
+ sequences: Map<string, unknown>;
849
+ schema: string;
850
+ }): void;
851
+ /**
852
+ * Convert camelCase to snake_case for column names.
853
+ */
854
+ protected toColumnName(str: string): string;
855
+ /**
856
+ * Build the table configuration function for any database.
857
+ * This includes indexes, foreign keys, constraints, and custom config.
858
+ *
859
+ * @param entity - The entity descriptor
860
+ * @param builders - Database-specific builder functions
861
+ * @param tableResolver - Function to resolve entity references to table columns
862
+ * @param customConfigHandler - Optional handler for custom config
863
+ */
864
+ protected buildTableConfig<TConfig, TSelf>(entity: EntityDescriptor, builders: TableConfigBuilders<TConfig>, tableResolver?: (entityName: string) => any, customConfigHandler?: (config: any, self: TSelf) => TConfig[]): ((self: TSelf) => TConfig[]) | undefined;
865
+ }
866
+ //#endregion
867
+ //#region src/providers/drivers/DatabaseProvider.d.ts
868
+ type SQLLike = SQLWrapper | string;
869
+ declare abstract class DatabaseProvider {
870
+ protected readonly alepha: Alepha;
871
+ protected abstract readonly builder: ModelBuilder;
872
+ abstract readonly db: PgDatabase<any>;
873
+ abstract readonly dialect: "postgres" | "sqlite";
874
+ readonly enums: Map<string, unknown>;
875
+ readonly tables: Map<string, unknown>;
876
+ readonly sequences: Map<string, unknown>;
877
+ table<T extends TObject>(entity: EntityDescriptor<T>): PgTableWithColumns<SchemaToTableConfig<T>>;
878
+ get schema(): string;
879
+ registerEntity(entity: EntityDescriptor): void;
880
+ registerSequence(sequence: SequenceDescriptor): void;
881
+ abstract execute(statement: SQLLike): Promise<Record<string, unknown>[]>;
882
+ run<T extends TObject>(statement: SQLLike, schema: T): Promise<Array<Static<T>>>;
883
+ }
884
+ //#endregion
885
+ //#region src/schemas/pageQuerySchema.d.ts
886
+ declare const pageQuerySchema: typebox4.TObject<{
887
+ page: typebox4.TOptional<typebox4.TInteger>;
888
+ size: typebox4.TOptional<typebox4.TInteger>;
889
+ sort: typebox4.TOptional<typebox4.TString>;
890
+ }>;
891
+ type PageQuery = Static<typeof pageQuerySchema>;
1134
892
  //#endregion
1135
893
  //#region src/schemas/pageSchema.d.ts
1136
894
  /**
@@ -1147,8 +905,8 @@ type NestedJsonbQuery<T$1> = T$1 extends object ? T$1 extends Array<infer U> ? U
1147
905
  * @see {@link $repository#paginate}
1148
906
  */
1149
907
  declare const pageSchema: <T extends TObject | TRecord>(objectSchema: T, options?: TObjectOptions) => TPage<T>;
1150
- type TPage<T$1 extends TObject | TRecord> = TObject<{
1151
- content: TArray<T$1>;
908
+ type TPage<T extends TObject | TRecord> = TObject<{
909
+ content: TArray<T>;
1152
910
  can: TObject<{
1153
911
  next: TBoolean;
1154
912
  previous: TBoolean;
@@ -1178,11 +936,11 @@ type TPage<T$1 extends TObject | TRecord> = TObject<{
1178
936
  * }
1179
937
  * ```
1180
938
  */
1181
- type Page<T$1> = {
939
+ type Page<T> = {
1182
940
  /**
1183
941
  * Array of items on the current page.
1184
942
  */
1185
- content: T$1[];
943
+ content: T[];
1186
944
  can: {
1187
945
  /**
1188
946
  * Indicates if there is a next page.
@@ -1209,7 +967,7 @@ type Page<T$1> = {
1209
967
  };
1210
968
  };
1211
969
  //#endregion
1212
- //#region src/helpers/PgJsonQueryManager.d.ts
970
+ //#region src/services/PgJsonQueryManager.d.ts
1213
971
  /**
1214
972
  * Manages JSONB query generation for nested object and array queries in PostgreSQL.
1215
973
  * This class handles complex nested queries using PostgreSQL's JSONB operators.
@@ -1266,9 +1024,10 @@ declare class PgJsonQueryManager {
1266
1024
  isArrayProperty(schema: TObject, path: string[]): boolean;
1267
1025
  }
1268
1026
  //#endregion
1269
- //#region src/helpers/PgQueryManager.d.ts
1027
+ //#region src/services/PgQueryManager.d.ts
1270
1028
  declare class PgQueryManager {
1271
1029
  protected readonly jsonQueryManager: PgJsonQueryManager;
1030
+ protected readonly alepha: Alepha;
1272
1031
  /**
1273
1032
  * Convert a query object to a SQL query.
1274
1033
  */
@@ -1281,10 +1040,14 @@ declare class PgQueryManager {
1281
1040
  * Build a JSONB query for nested object/array queries.
1282
1041
  */
1283
1042
  protected buildJsonbQuery(column: PgColumn, nestedQuery: any, schema: TObject, columnName: string): SQL | undefined;
1043
+ /**
1044
+ * Check if an object has any filter operator properties.
1045
+ */
1046
+ protected hasFilterOperatorProperties(obj: any): boolean;
1284
1047
  /**
1285
1048
  * Map a filter operator to a SQL query.
1286
1049
  */
1287
- mapOperatorToSql(operator: FilterOperators<any> | any, column: PgColumn): SQL | undefined;
1050
+ mapOperatorToSql(operator: FilterOperators<any> | any, column: PgColumn, columnSchema?: TObject, columnName?: string): SQL | undefined;
1288
1051
  /**
1289
1052
  * Parse pagination sort string to orderBy format.
1290
1053
  * Format: "firstName,-lastName" -> [{ column: "firstName", direction: "asc" }, { column: "lastName", direction: "desc" }]
@@ -1332,68 +1095,26 @@ interface PgJoin {
1332
1095
  parent?: string;
1333
1096
  }
1334
1097
  //#endregion
1335
- //#region src/helpers/PgRelationManager.d.ts
1098
+ //#region src/services/PgRelationManager.d.ts
1336
1099
  declare class PgRelationManager {
1337
- buildJoins(builder: PgSelectBase<any, any, any>, joins: Array<PgJoin>, withRelations: PgRelationMap<TObject>, table: PgTableWithColumnsAndSchema<any, any>, parentKey?: string): void;
1100
+ /**
1101
+ * Recursively build joins for the query builder based on the relations map
1102
+ */
1103
+ buildJoins(provider: DatabaseProvider, builder: PgSelectBase<any, any, any>, joins: Array<PgJoin>, withRelations: PgRelationMap<TObject>, table: PgTableWithColumns<any>, parentKey?: string): void;
1104
+ /**
1105
+ * Map a row with its joined relations based on the joins definition
1106
+ */
1338
1107
  mapRowWithJoins(record: Record<string, unknown>, row: Record<string, unknown>, schema: TObject, joins: PgJoin[], parentKey?: string): Record<string, unknown>;
1339
1108
  /**
1340
1109
  * Check if all values in an object are null (indicates a left join with no match)
1341
1110
  */
1342
1111
  private isAllNull;
1112
+ /**
1113
+ * Build a schema that includes all join properties recursively
1114
+ */
1115
+ buildSchemaWithJoins(baseSchema: TObject, joins: PgJoin[], parentPath?: string): TObject;
1343
1116
  }
1344
1117
  //#endregion
1345
- //#region src/helpers/pgAttr.d.ts
1346
- /**
1347
- * Decorates a typebox schema with a Postgres attribute.
1348
- *
1349
- * > It's just a fancy way to add Symbols to a field.
1350
- *
1351
- * @example
1352
- * ```ts
1353
- * import { t } from "alepha";
1354
- * import { PG_UPDATED_AT } from "../constants/PG_SYMBOLS";
1355
- *
1356
- * export const updatedAtSchema = pgAttr(
1357
- * t.datetime(), PG_UPDATED_AT,
1358
- * );
1359
- * ```
1360
- */
1361
- declare const pgAttr: <T extends TSchema$1, Attr extends PgSymbolKeys>(type: T, attr: Attr, value?: PgSymbols[Attr]) => PgAttr<T, Attr>;
1362
- /**
1363
- * Retrieves the fields of a schema that have a specific attribute.
1364
- */
1365
- declare const getAttrFields: (schema: TObject, name: PgSymbolKeys) => PgAttrField[];
1366
- /**
1367
- * Type representation.
1368
- */
1369
- type PgAttr<T$1 extends TSchema$1, TAttr extends PgSymbolKeys> = T$1 & { [K in TAttr]: PgSymbols[K] };
1370
- interface PgAttrField {
1371
- key: string;
1372
- type: TSchema$1;
1373
- data: any;
1374
- nested?: any[];
1375
- one?: boolean;
1376
- }
1377
- //#endregion
1378
- //#region src/providers/drivers/PostgresProvider.d.ts
1379
- type SQLLike = SQLWrapper | string;
1380
- declare abstract class PostgresProvider {
1381
- protected readonly alepha: Alepha;
1382
- abstract get db(): PgDatabase<any>;
1383
- readonly dialect: "postgres" | "sqlite";
1384
- get schema(): string;
1385
- execute<T extends TObject | undefined>(query: SQLLike, schema?: T): Promise<Array<T extends TObject ? Static<T> : any>>;
1386
- protected mapResult<T extends TObject = any>(result: Array<any>, schema?: T): Array<T extends TObject ? Static<T> : any>;
1387
- }
1388
- //#endregion
1389
- //#region src/schemas/pageQuerySchema.d.ts
1390
- declare const pageQuerySchema: typebox0.TObject<{
1391
- page: typebox0.TOptional<typebox0.TInteger>;
1392
- size: typebox0.TOptional<typebox0.TInteger>;
1393
- sort: typebox0.TOptional<typebox0.TString>;
1394
- }>;
1395
- type PageQuery = Static<typeof pageQuerySchema>;
1396
- //#endregion
1397
1118
  //#region src/descriptors/$repository.d.ts
1398
1119
  /**
1399
1120
  * Creates a repository for database operations on a defined entity.
@@ -1402,75 +1123,12 @@ type PageQuery = Static<typeof pageQuerySchema>;
1402
1123
  * database operations on entities defined with $entity. It offers a rich set of
1403
1124
  * CRUD operations, advanced querying capabilities, pagination, transactions, and
1404
1125
  * built-in support for audit trails and soft deletes.
1405
- *
1406
- * **Key Features**
1407
- *
1408
- * - **Complete CRUD Operations**: Create, read, update, delete with full type safety
1409
- * - **Advanced Querying**: Complex WHERE conditions, sorting, pagination, and aggregations
1410
- * - **Transaction Support**: Database transactions for consistency and atomicity
1411
- * - **Soft Delete Support**: Built-in soft delete functionality with `pg.deletedAt()` fields
1412
- * - **Optimistic Locking**: Version-based conflict resolution with `pg.version()` fields
1413
- * - **Audit Trail Integration**: Automatic handling of `createdAt`, `updatedAt` timestamps
1414
- * - **Raw SQL Support**: Execute custom SQL queries when needed
1415
- * - **Pagination**: Built-in pagination with metadata and navigation
1416
- *
1417
- * **Important Requirements**
1418
- * - Must be used with an entity created by $entity
1419
- * - Entity schema must include exactly one primary key field
1420
- * - Database tables must be created via migrations before use
1421
- *
1422
- * @example
1423
- * **Basic repository with CRUD operations:**
1424
- * ```ts
1425
- * import { $entity, $repository } from "alepha/postgres";
1426
- * import { pg, t } from "alepha";
1427
- *
1428
- * // First, define the entity
1429
- * const users = $entity({
1430
- * name: "users",
1431
- * schema: t.object({
1432
- * id: pg.primaryKey(t.uuid()),
1433
- * email: t.text({ format: "email" }),
1434
- * firstName: t.text(),
1435
- * lastName: t.text(),
1436
- * isActive: pg.default(t.boolean(), true),
1437
- * createdAt: pg.createdAt(),
1438
- * updatedAt: pg.updatedAt()
1439
- * }),
1440
- * indexes: [{ column: "email", unique: true }]
1441
- * });
1442
- *
1443
- * class UserService {
1444
- * users = $repository(users);
1445
- *
1446
- * async createUser(userData: { email: string; firstName: string; lastName: string }) {
1447
- * return await this.users.create({
1448
- * id: generateUUID(),
1449
- * email: userData.email,
1450
- * firstName: userData.firstName,
1451
- * lastName: userData.lastName
1452
- * });
1453
- * }
1454
- *
1455
- * async getUserByEmail(email: string) {
1456
- * return await this.users.findOne({ email });
1457
- * }
1458
- *
1459
- * async updateUser(id: string, updates: { firstName?: string; lastName?: string }) {
1460
- * return await this.users.updateById(id, updates);
1461
- * }
1462
- *
1463
- * async deactivateUser(id: string) {
1464
- * return await this.users.updateById(id, { isActive: false });
1465
- * }
1466
- * }
1467
- * ```
1468
1126
  */
1469
1127
  declare const $repository: {
1470
- <EntityTableConfig extends TableConfig, EntitySchema extends TObject>(optionsOrTable: RepositoryDescriptorOptions<EntityTableConfig, EntitySchema> | PgTableWithColumnsAndSchema<EntityTableConfig, EntitySchema>): RepositoryDescriptor<EntityTableConfig, EntitySchema>;
1128
+ <T extends TObject>(optionsOrEntity: EntityDescriptor<T> | EntityDescriptorOptions<T> | RepositoryDescriptorOptions<T>): RepositoryDescriptor<T>;
1471
1129
  [KIND]: typeof RepositoryDescriptor;
1472
1130
  };
1473
- interface RepositoryDescriptorOptions<EntityTableConfig$1 extends TableConfig, EntitySchema$1 extends TObject> {
1131
+ interface RepositoryDescriptorOptions<T extends TObject> {
1474
1132
  /**
1475
1133
  * The entity table definition created with $entity.
1476
1134
  *
@@ -1505,7 +1163,7 @@ interface RepositoryDescriptorOptions<EntityTableConfig$1 extends TableConfig, E
1505
1163
  * const userRepository = $repository({ table: User });
1506
1164
  * ```
1507
1165
  */
1508
- table: PgTableWithColumnsAndSchema<EntityTableConfig$1, EntitySchema$1>;
1166
+ entity: EntityDescriptor<T>;
1509
1167
  /**
1510
1168
  * Override the default PostgreSQL database provider.
1511
1169
  *
@@ -1528,16 +1186,16 @@ interface RepositoryDescriptorOptions<EntityTableConfig$1 extends TableConfig, E
1528
1186
  * @example TenantSpecificPostgresProvider
1529
1187
  * @example TestDatabaseProvider
1530
1188
  */
1531
- provider?: Service<PostgresProvider>;
1189
+ provider?: DatabaseProvider;
1190
+ name?: string;
1532
1191
  }
1533
- declare class RepositoryDescriptor<EntityTableConfig$1 extends TableConfig, EntitySchema$1 extends TObject> extends Descriptor<RepositoryDescriptorOptions<EntityTableConfig$1, EntitySchema$1>> {
1534
- protected readonly pgRelationManager: PgRelationManager;
1535
- protected readonly pgQueryManager: PgQueryManager;
1192
+ declare class RepositoryDescriptor<T extends TObject = TObject> extends Descriptor<RepositoryDescriptorOptions<T>> {
1193
+ protected readonly relationManager: PgRelationManager;
1194
+ protected readonly queryManager: PgQueryManager;
1536
1195
  protected readonly dateTimeProvider: DateTimeProvider;
1537
1196
  protected readonly alepha: Alepha;
1538
- readonly provider: PostgresProvider;
1539
- readonly schema: EntitySchema$1;
1540
- readonly schemaInsert: TObjectInsert<EntitySchema$1>;
1197
+ readonly provider: DatabaseProvider;
1198
+ constructor(args: DescriptorArgs<RepositoryDescriptorOptions<T>>);
1541
1199
  /**
1542
1200
  * Represents the primary key of the table.
1543
1201
  * - Key is the name of the primary key column.
@@ -1545,15 +1203,15 @@ declare class RepositoryDescriptor<EntityTableConfig$1 extends TableConfig, Enti
1545
1203
  *
1546
1204
  * ID is mandatory. If the table does not have a primary key, it will throw an error.
1547
1205
  */
1548
- readonly id: {
1549
- type: TSchema$1;
1550
- key: keyof EntitySchema$1["properties"];
1206
+ get id(): {
1207
+ type: TSchema;
1208
+ key: keyof T["properties"];
1551
1209
  col: PgColumn;
1552
1210
  };
1553
1211
  /**
1554
1212
  * Get Drizzle table object.
1555
1213
  */
1556
- get table(): PgTableWithColumns<EntityTableConfig$1>;
1214
+ get table(): PgTableWithColumns<SchemaToTableConfig<T>>;
1557
1215
  /**
1558
1216
  * Get SQL table name. (from Drizzle table object)
1559
1217
  */
@@ -1561,7 +1219,7 @@ declare class RepositoryDescriptor<EntityTableConfig$1 extends TableConfig, Enti
1561
1219
  /**
1562
1220
  * Getter for the database connection from the database provider.
1563
1221
  */
1564
- protected get db(): PgDatabase<any, Record<string, never>, drizzle_orm6.ExtractTablesWithRelations<Record<string, never>>>;
1222
+ protected get db(): PgDatabase<any>;
1565
1223
  /**
1566
1224
  * Execute a SQL query.
1567
1225
  *
@@ -1572,11 +1230,18 @@ declare class RepositoryDescriptor<EntityTableConfig$1 extends TableConfig, Enti
1572
1230
  *
1573
1231
  * @example
1574
1232
  * ```ts
1575
- * const users = $entity({ ... });
1576
- * const result = await repository.query(sql`SELECT * FROM ${users} WHERE ${users.age} > ${18}`, users.$schema);
1233
+ * class App {
1234
+ * repository = $repository({ ... });
1235
+ * async getAdults() {
1236
+ * const users = repository.table; // Drizzle table object
1237
+ * await repository.query(sql`SELECT * FROM ${users} WHERE ${users.age} > ${18}`);
1238
+ * // or better
1239
+ * await repository.query((users) => sql`SELECT * FROM ${users} WHERE ${users.age} > ${18}`);
1240
+ * }
1241
+ * }
1577
1242
  * ```
1578
1243
  */
1579
- query<T extends TObject = EntitySchema$1>(query: SQLLike | ((table: PgTableWithColumns<EntityTableConfig$1>, db: PgDatabase<any>) => SQLLike), schema?: T): Promise<Static<T>[]>;
1244
+ query<R extends TObject = T>(query: SQLLike | ((table: PgTableWithColumns<SchemaToTableConfig<T>>, db: PgDatabase<any>) => SQLLike), schema?: R): Promise<Static<R>[]>;
1580
1245
  /**
1581
1246
  * Map raw database fields to entity fields. (handles column name differences)
1582
1247
  */
@@ -1584,7 +1249,7 @@ declare class RepositoryDescriptor<EntityTableConfig$1 extends TableConfig, Enti
1584
1249
  /**
1585
1250
  * Get a Drizzle column from the table by his name.
1586
1251
  */
1587
- protected col(name: keyof PgTableWithColumns<EntityTableConfig$1>["_"]["columns"]): PgColumn;
1252
+ protected col(name: keyof StaticEncode<T>): PgColumn;
1588
1253
  /**
1589
1254
  * Run a transaction.
1590
1255
  */
@@ -1592,15 +1257,15 @@ declare class RepositoryDescriptor<EntityTableConfig$1 extends TableConfig, Enti
1592
1257
  /**
1593
1258
  * Start a SELECT query on the table.
1594
1259
  */
1595
- protected select(opts?: StatementOptions): pg$1.PgSelectBase<string, Record<string, PgColumn<drizzle_orm6.ColumnBaseConfig<drizzle_orm6.ColumnDataType, string>, {}, {}>>, "single", Record<string, "not-null">, false, never, {
1260
+ protected select(opts?: StatementOptions): drizzle_orm_pg_core0.PgSelectBase<string, Record<string, PgColumn<drizzle_orm0.ColumnBaseConfig<drizzle_orm0.ColumnDataType, string>, {}, {}>>, "single", Record<string, "not-null">, false, never, {
1596
1261
  [x: string]: unknown;
1597
1262
  }[], {
1598
- [x: string]: PgColumn<drizzle_orm6.ColumnBaseConfig<drizzle_orm6.ColumnDataType, string>, {}, {}>;
1263
+ [x: string]: PgColumn<drizzle_orm0.ColumnBaseConfig<drizzle_orm0.ColumnDataType, string>, {}, {}>;
1599
1264
  }>;
1600
1265
  /**
1601
1266
  * Start a SELECT DISTINCT query on the table.
1602
1267
  */
1603
- protected selectDistinct(opts?: StatementOptions, columns?: (keyof Static<EntitySchema$1>)[]): pg$1.PgSelectBase<string, Record<string, any>, "partial", Record<string, "not-null">, false, never, {
1268
+ protected selectDistinct(opts?: StatementOptions, columns?: (keyof Static<T>)[]): drizzle_orm_pg_core0.PgSelectBase<string, Record<string, any>, "partial", Record<string, "not-null">, false, never, {
1604
1269
  [x: string]: any;
1605
1270
  }[], {
1606
1271
  [x: string]: any;
@@ -1608,25 +1273,25 @@ declare class RepositoryDescriptor<EntityTableConfig$1 extends TableConfig, Enti
1608
1273
  /**
1609
1274
  * Start an INSERT query on the table.
1610
1275
  */
1611
- protected insert(opts?: StatementOptions): pg$1.PgInsertBuilder<PgTableWithColumns<EntityTableConfig$1>, any, false>;
1276
+ protected insert(opts?: StatementOptions): drizzle_orm_pg_core0.PgInsertBuilder<PgTableWithColumns<SchemaToTableConfig<T>>, any, false>;
1612
1277
  /**
1613
1278
  * Start an UPDATE query on the table.
1614
1279
  */
1615
- protected update(opts?: StatementOptions): pg$1.PgUpdateBuilder<PgTableWithColumns<EntityTableConfig$1>, any>;
1280
+ protected update(opts?: StatementOptions): drizzle_orm_pg_core0.PgUpdateBuilder<PgTableWithColumns<SchemaToTableConfig<T>>, any>;
1616
1281
  /**
1617
1282
  * Start a DELETE query on the table.
1618
1283
  */
1619
- protected delete(opts?: StatementOptions): pg$1.PgDeleteBase<PgTableWithColumns<EntityTableConfig$1>, any, undefined, undefined, false, never>;
1284
+ protected delete(opts?: StatementOptions): drizzle_orm_pg_core0.PgDeleteBase<PgTableWithColumns<SchemaToTableConfig<T>>, any, undefined, undefined, false, never>;
1620
1285
  /**
1621
1286
  * Create a Drizzle `select` query based on a JSON query object.
1622
1287
  *
1623
1288
  * > This method is the base for `find`, `findOne`, `findById`, and `paginate`.
1624
1289
  */
1625
- find<R extends PgRelationMap<EntitySchema$1>>(query?: PgQueryRelations<EntitySchema$1, R>, opts?: StatementOptions): Promise<PgStatic<EntitySchema$1, R>[]>;
1290
+ find<R extends PgRelationMap<T>>(query?: PgQueryRelations<T, R>, opts?: StatementOptions): Promise<PgStatic<T, R>[]>;
1626
1291
  /**
1627
1292
  * Find a single entity.
1628
1293
  */
1629
- findOne<R extends PgRelationMap<EntitySchema$1>>(query: Pick<PgQueryRelations<EntitySchema$1, R>, "with" | "where">, opts?: StatementOptions): Promise<PgStatic<EntitySchema$1, R>>;
1294
+ findOne<R extends PgRelationMap<T>>(query: Pick<PgQueryRelations<T, R>, "with" | "where">, opts?: StatementOptions): Promise<PgStatic<T, R>>;
1630
1295
  /**
1631
1296
  * Find entities with pagination.
1632
1297
  *
@@ -1634,24 +1299,24 @@ declare class RepositoryDescriptor<EntityTableConfig$1 extends TableConfig, Enti
1634
1299
  *
1635
1300
  * > Pagination CAN also do a count query to get the total number of elements.
1636
1301
  */
1637
- paginate<R extends PgRelationMap<EntitySchema$1>>(pagination?: PageQuery, query?: PgQueryRelations<EntitySchema$1, R>, opts?: StatementOptions & {
1302
+ paginate<R extends PgRelationMap<T>>(pagination?: PageQuery, query?: PgQueryRelations<T, R>, opts?: StatementOptions & {
1638
1303
  count?: boolean;
1639
- }): Promise<Page<PgStatic<EntitySchema$1, R>>>;
1304
+ }): Promise<Page<PgStatic<T, R>>>;
1640
1305
  /**
1641
1306
  * Find an entity by ID.
1642
1307
  *
1643
1308
  * This is a convenience method for `findOne` with a where clause on the primary key.
1644
1309
  * If you need more complex queries, use `findOne` instead.
1645
1310
  */
1646
- findById(id: string | number, opts?: StatementOptions): Promise<Static<EntitySchema$1>>;
1311
+ findById(id: string | number, opts?: StatementOptions): Promise<Static<T>>;
1647
1312
  /**
1648
1313
  * Helper to create a type-safe query object.
1649
1314
  */
1650
- createQuery(): PgQuery<EntitySchema$1>;
1315
+ createQuery(): PgQuery<T>;
1651
1316
  /**
1652
1317
  * Helper to create a type-safe where clause.
1653
1318
  */
1654
- createQueryWhere(): PgQueryWhere<EntitySchema$1>;
1319
+ createQueryWhere(): PgQueryWhere<T>;
1655
1320
  /**
1656
1321
  * Create an entity.
1657
1322
  *
@@ -1659,7 +1324,7 @@ declare class RepositoryDescriptor<EntityTableConfig$1 extends TableConfig, Enti
1659
1324
  * @param opts The options for creating the entity.
1660
1325
  * @returns The ID of the created entity.
1661
1326
  */
1662
- create(data: Static<TObjectInsert<EntitySchema$1>>, opts?: StatementOptions): Promise<Static<EntitySchema$1>>;
1327
+ create(data: Static<TObjectInsert<T>>, opts?: StatementOptions): Promise<Static<T>>;
1663
1328
  /**
1664
1329
  * Create many entities.
1665
1330
  *
@@ -1667,11 +1332,11 @@ declare class RepositoryDescriptor<EntityTableConfig$1 extends TableConfig, Enti
1667
1332
  * @param opts The statement options.
1668
1333
  * @returns The created entities.
1669
1334
  */
1670
- createMany(values: Array<Static<TObjectInsert<EntitySchema$1>>>, opts?: StatementOptions): Promise<Static<EntitySchema$1>[]>;
1335
+ createMany(values: Array<Static<TObjectInsert<T>>>, opts?: StatementOptions): Promise<Static<T>[]>;
1671
1336
  /**
1672
1337
  * Find an entity and update it.
1673
1338
  */
1674
- updateOne(where: PgQueryWhereOrSQL<EntitySchema$1>, data: Partial<Static<TObjectUpdate<EntitySchema$1>>>, opts?: StatementOptions): Promise<Static<EntitySchema$1>>;
1339
+ updateOne(where: PgQueryWhereOrSQL<T>, data: Partial<Static<TObjectUpdate<T>>>, opts?: StatementOptions): Promise<Static<T>>;
1675
1340
  /**
1676
1341
  * Save a given entity.
1677
1342
  *
@@ -1693,51 +1358,57 @@ declare class RepositoryDescriptor<EntityTableConfig$1 extends TableConfig, Enti
1693
1358
  * @see {@link PostgresTypeProvider#version}
1694
1359
  * @see {@link PgVersionMismatchError}
1695
1360
  */
1696
- save(entity: Static<EntitySchema$1>, opts?: StatementOptions): Promise<Static<EntitySchema$1>>;
1361
+ save(entity: Static<T>, opts?: StatementOptions): Promise<void>;
1697
1362
  /**
1698
1363
  * Find an entity by ID and update it.
1699
1364
  */
1700
- updateById(id: string | number, data: Partial<Static<TObjectUpdate<EntitySchema$1>>>, opts?: StatementOptions): Promise<Static<EntitySchema$1>>;
1365
+ updateById(id: string | number, data: Partial<Static<TObjectUpdate<T>>>, opts?: StatementOptions): Promise<Static<T>>;
1701
1366
  /**
1702
1367
  * Find many entities and update all of them.
1703
1368
  */
1704
- updateMany(where: PgQueryWhereOrSQL<EntitySchema$1>, data: Partial<Static<TObjectUpdate<EntitySchema$1>>>, opts?: StatementOptions): Promise<void>;
1369
+ updateMany(where: PgQueryWhereOrSQL<T>, data: Partial<Static<TObjectUpdate<T>>>, opts?: StatementOptions): Promise<Array<number | string>>;
1705
1370
  /**
1706
1371
  * Find many and delete all of them.
1372
+ * @returns Array of deleted entity IDs
1707
1373
  */
1708
- deleteMany(where?: PgQueryWhereOrSQL<EntitySchema$1>, opts?: StatementOptions): Promise<void>;
1374
+ deleteMany(where?: PgQueryWhereOrSQL<T>, opts?: StatementOptions): Promise<Array<number | string>>;
1709
1375
  /**
1710
1376
  * Delete all entities.
1377
+ * @returns Array of deleted entity IDs
1711
1378
  */
1712
- clear(opts?: StatementOptions): Promise<void>;
1379
+ clear(opts?: StatementOptions): Promise<Array<number | string>>;
1713
1380
  /**
1714
1381
  * Delete the given entity.
1715
1382
  *
1716
1383
  * You must fetch the entity first in order to delete it.
1384
+ * @returns Array containing the deleted entity ID
1717
1385
  */
1718
- destroy(entity: Static<EntitySchema$1>, opts?: StatementOptions): Promise<void>;
1386
+ destroy(entity: Static<T>, opts?: StatementOptions): Promise<Array<number | string>>;
1719
1387
  /**
1720
1388
  * Find an entity and delete it.
1389
+ * @returns Array of deleted entity IDs (should contain at most one ID)
1721
1390
  */
1722
- deleteOne(where?: PgQueryWhereOrSQL<EntitySchema$1>, opts?: StatementOptions): Promise<void>;
1391
+ deleteOne(where?: PgQueryWhereOrSQL<T>, opts?: StatementOptions): Promise<Array<number | string>>;
1723
1392
  /**
1724
1393
  * Find an entity by ID and delete it.
1394
+ * @returns Array containing the deleted entity ID
1395
+ * @throws PgEntityNotFoundError if the entity is not found
1725
1396
  */
1726
- deleteById(id: string | number, opts?: StatementOptions): Promise<void>;
1397
+ deleteById(id: string | number, opts?: StatementOptions): Promise<Array<number | string>>;
1727
1398
  /**
1728
1399
  * Count entities.
1729
1400
  */
1730
- count(where?: PgQueryWhereOrSQL<EntitySchema$1>, opts?: StatementOptions): Promise<number>;
1401
+ count(where?: PgQueryWhereOrSQL<T>, opts?: StatementOptions): Promise<number>;
1731
1402
  protected conflictMessagePattern: string;
1732
1403
  protected handleError(error: unknown, message: string): PgError;
1733
- protected withDeletedAt(where: PgQueryWhereOrSQL<EntitySchema$1>, opts?: {
1404
+ protected withDeletedAt(where: PgQueryWhereOrSQL<T>, opts?: {
1734
1405
  force?: boolean;
1735
- }): PgQueryWhereOrSQL<EntitySchema$1>;
1406
+ }): PgQueryWhereOrSQL<T>;
1736
1407
  protected deletedAt(): PgAttrField | undefined;
1737
1408
  /**
1738
1409
  * Convert something to valid Pg Insert Value.
1739
1410
  */
1740
- protected cast(data: any, insert: boolean): PgInsertValue<PgTableWithColumns<EntityTableConfig$1>>;
1411
+ protected cast(data: any, insert: boolean): PgInsertValue<PgTableWithColumns<SchemaToTableConfig<T>>>;
1741
1412
  /**
1742
1413
  * Transform a row from the database into a clean entity.
1743
1414
  *
@@ -1746,37 +1417,31 @@ declare class RepositoryDescriptor<EntityTableConfig$1 extends TableConfig, Enti
1746
1417
  * - Fix date-time and date fields to ISO strings
1747
1418
  * - Cast BigInt to string
1748
1419
  */
1749
- protected clean<T extends TObject = EntitySchema$1>(row: Record<string, unknown>, schema?: T): Static<T>;
1420
+ protected clean<T extends TObject>(row: Record<string, unknown>, schema: T): Static<T>;
1750
1421
  /**
1751
1422
  * Clean a row with joins recursively
1752
1423
  */
1753
- protected cleanWithJoins<T extends TObject = EntitySchema$1>(row: Record<string, unknown>, schema: T, joins: PgJoin[], parentPath?: string): Static<T>;
1754
- /**
1755
- * Build a schema that includes all join properties recursively
1756
- */
1757
- protected buildSchemaWithJoins(baseSchema: TObject, joins: PgJoin[], parentPath?: string): TObject;
1424
+ protected cleanWithJoins<T extends TObject>(row: Record<string, unknown>, schema: T, joins: PgJoin[], parentPath?: string): Static<T>;
1758
1425
  /**
1759
1426
  * Convert a where clause to SQL.
1760
1427
  */
1761
- protected toSQL(where: PgQueryWhereOrSQL<EntitySchema$1>, joins?: PgJoin[]): SQL | undefined;
1428
+ protected toSQL(where: PgQueryWhereOrSQL<T>, joins?: PgJoin[]): SQL | undefined;
1762
1429
  /**
1763
1430
  * Get the where clause for an ID.
1764
1431
  *
1765
1432
  * @param id The ID to get the where clause for.
1766
1433
  * @returns The where clause for the ID.
1767
1434
  */
1768
- protected getWhereId(id: string | number): PgQueryWhere<EntitySchema$1>;
1435
+ protected getWhereId(id: string | number): PgQueryWhere<T>;
1769
1436
  /**
1770
1437
  * Find a primary key in the schema.
1771
- *
1772
- * @param schema
1773
- * @protected
1774
1438
  */
1775
1439
  protected getPrimaryKey(schema: TObject): {
1776
1440
  key: string;
1777
- col: PgColumn<drizzle_orm6.ColumnBaseConfig<drizzle_orm6.ColumnDataType, string>, {}, {}>;
1778
- type: TSchema$1;
1441
+ col: PgColumn<drizzle_orm0.ColumnBaseConfig<drizzle_orm0.ColumnDataType, string>, {}, {}>;
1442
+ type: TSchema;
1779
1443
  };
1444
+ protected $provider(): DatabaseProvider;
1780
1445
  }
1781
1446
  /**
1782
1447
  * The options for a statement.
@@ -1803,374 +1468,6 @@ interface StatementOptions {
1803
1468
  now?: DateTime;
1804
1469
  }
1805
1470
  //#endregion
1806
- //#region src/descriptors/$sequence.d.ts
1807
- /**
1808
- * Creates a PostgreSQL sequence descriptor for generating unique numeric values.
1809
- *
1810
- * This descriptor provides a type-safe interface to PostgreSQL sequences, which are
1811
- * database objects that generate unique numeric identifiers. Sequences are commonly
1812
- * used for primary keys, order numbers, invoice numbers, and other cases where
1813
- * guaranteed unique, incrementing values are needed across concurrent operations.
1814
- *
1815
- * **Key Features**
1816
- *
1817
- * - **Thread-Safe**: PostgreSQL sequences are inherently thread-safe and handle concurrency
1818
- * - **Configurable Parameters**: Start value, increment, min/max bounds, and cycling behavior
1819
- * - **Automatic Creation**: Sequences are created automatically when first used
1820
- * - **Type Safety**: Full TypeScript support with numeric return types
1821
- * - **Performance**: Optimized for high-throughput ID generation
1822
- * - **Schema Support**: Works with PostgreSQL schemas for organization
1823
- *
1824
- * **Use Cases**
1825
- *
1826
- * Perfect for generating unique identifiers in concurrent environments:
1827
- * - Primary key generation (alternative to UUIDs)
1828
- * - Order numbers and invoice sequences
1829
- * - Ticket numbers and reference IDs
1830
- * - Version numbers and revision tracking
1831
- * - Batch numbers for processing workflows
1832
- * - Any scenario requiring guaranteed unique incrementing numbers
1833
- *
1834
- * @example
1835
- * **Basic sequence for order numbers:**
1836
- * ```ts
1837
- * import { $sequence } from "alepha/postgres";
1838
- *
1839
- * class OrderService {
1840
- * orderNumbers = $sequence({
1841
- * name: "order_numbers",
1842
- * start: 1000, // Start from order #1000
1843
- * increment: 1 // Increment by 1 each time
1844
- * });
1845
- *
1846
- * async createOrder(orderData: OrderData) {
1847
- * const orderNumber = await this.orderNumbers.next();
1848
- *
1849
- * return await this.orders.create({
1850
- * id: generateUUID(),
1851
- * orderNumber,
1852
- * ...orderData
1853
- * });
1854
- * }
1855
- *
1856
- * async getCurrentOrderNumber() {
1857
- * // Get the last generated number without incrementing
1858
- * return await this.orderNumbers.current();
1859
- * }
1860
- * }
1861
- * ```
1862
- *
1863
- * @example
1864
- * **Invoice numbering with yearly reset:**
1865
- * ```ts
1866
- * class InvoiceService {
1867
- * // Separate sequence for each year
1868
- * getInvoiceSequence(year: number) {
1869
- * return $sequence({
1870
- * name: `invoice_numbers_${year}`,
1871
- * start: 1,
1872
- * increment: 1
1873
- * });
1874
- * }
1875
- *
1876
- * async generateInvoiceNumber(): Promise<string> {
1877
- * const year = new Date().getFullYear();
1878
- * const sequence = this.getInvoiceSequence(year);
1879
- * const number = await sequence.next();
1880
- *
1881
- * // Format as INV-2024-001, INV-2024-002, etc.
1882
- * return `INV-${year}-${number.toString().padStart(3, '0')}`;
1883
- * }
1884
- * }
1885
- * ```
1886
- *
1887
- * @example
1888
- * **High-performance ID generation with custom increments:**
1889
- * ```ts
1890
- * class TicketService {
1891
- * // Generate ticket numbers in increments of 10 for better distribution
1892
- * ticketSequence = $sequence({
1893
- * name: "ticket_numbers",
1894
- * start: 1000,
1895
- * increment: 10,
1896
- * min: 1000,
1897
- * max: 999999,
1898
- * cycle: false // Don't cycle when max is reached
1899
- * });
1900
- *
1901
- * priorityTicketSequence = $sequence({
1902
- * name: "priority_ticket_numbers",
1903
- * start: 1,
1904
- * increment: 1,
1905
- * min: 1,
1906
- * max: 999,
1907
- * cycle: true // Cycle when reaching max
1908
- * });
1909
- *
1910
- * async generateTicketNumber(isPriority: boolean = false): Promise<number> {
1911
- * if (isPriority) {
1912
- * return await this.priorityTicketSequence.next();
1913
- * }
1914
- * return await this.ticketSequence.next();
1915
- * }
1916
- *
1917
- * async getSequenceStatus() {
1918
- * return {
1919
- * currentTicketNumber: await this.ticketSequence.current(),
1920
- * currentPriorityNumber: await this.priorityTicketSequence.current()
1921
- * };
1922
- * }
1923
- * }
1924
- * ```
1925
- *
1926
- * @example
1927
- * **Batch processing with sequence-based coordination:**
1928
- * ```ts
1929
- * class BatchProcessor {
1930
- * batchSequence = $sequence({
1931
- * name: "batch_numbers",
1932
- * start: 1,
1933
- * increment: 1
1934
- * });
1935
- *
1936
- * async processBatch(items: any[]) {
1937
- * const batchNumber = await this.batchSequence.next();
1938
- *
1939
- * console.log(`Starting batch processing #${batchNumber} with ${items.length} items`);
1940
- *
1941
- * try {
1942
- * // Process items with batch number for tracking
1943
- * for (const item of items) {
1944
- * await this.processItem(item, batchNumber);
1945
- * }
1946
- *
1947
- * await this.auditLogger.log({
1948
- * event: 'batch_completed',
1949
- * batchNumber,
1950
- * itemCount: items.length,
1951
- * timestamp: new Date()
1952
- * });
1953
- *
1954
- * return { batchNumber, processedCount: items.length };
1955
- *
1956
- * } catch (error) {
1957
- * await this.auditLogger.log({
1958
- * event: 'batch_failed',
1959
- * batchNumber,
1960
- * error: error.message,
1961
- * timestamp: new Date()
1962
- * });
1963
- * throw error;
1964
- * }
1965
- * }
1966
- *
1967
- * async processItem(item: any, batchNumber: number) {
1968
- * // Associate item processing with batch number
1969
- * await this.items.update(item.id, {
1970
- * ...item.updates,
1971
- * batchNumber,
1972
- * processedAt: new Date()
1973
- * });
1974
- * }
1975
- * }
1976
- * ```
1977
- *
1978
- * @example
1979
- * **Multi-tenant sequence management:**
1980
- * ```ts
1981
- * class TenantSequenceService {
1982
- * // Create tenant-specific sequences
1983
- * getTenantSequence(tenantId: string, sequenceType: string) {
1984
- * return $sequence({
1985
- * name: `${tenantId}_${sequenceType}_seq`,
1986
- * start: 1,
1987
- * increment: 1
1988
- * });
1989
- * }
1990
- *
1991
- * async generateTenantOrderNumber(tenantId: string): Promise<string> {
1992
- * const sequence = this.getTenantSequence(tenantId, 'orders');
1993
- * const number = await sequence.next();
1994
- *
1995
- * return `${tenantId.toUpperCase()}-ORD-${number.toString().padStart(6, '0')}`;
1996
- * }
1997
- *
1998
- * async generateTenantInvoiceNumber(tenantId: string): Promise<string> {
1999
- * const sequence = this.getTenantSequence(tenantId, 'invoices');
2000
- * const number = await sequence.next();
2001
- *
2002
- * return `${tenantId.toUpperCase()}-INV-${number.toString().padStart(6, '0')}`;
2003
- * }
2004
- *
2005
- * async getTenantSequenceStatus(tenantId: string) {
2006
- * const orderSeq = this.getTenantSequence(tenantId, 'orders');
2007
- * const invoiceSeq = this.getTenantSequence(tenantId, 'invoices');
2008
- *
2009
- * return {
2010
- * tenant: tenantId,
2011
- * sequences: {
2012
- * orders: {
2013
- * current: await orderSeq.current(),
2014
- * next: await orderSeq.next()
2015
- * },
2016
- * invoices: {
2017
- * current: await invoiceSeq.current()
2018
- * }
2019
- * }
2020
- * };
2021
- * }
2022
- * }
2023
- * ```
2024
- *
2025
- * **Important Notes**:
2026
- * - Sequences are created automatically when first used
2027
- * - PostgreSQL sequences are atomic and handle high concurrency
2028
- * - Sequence values are not rolled back in failed transactions
2029
- * - Consider the impact of max values and cycling behavior
2030
- * - Sequences are schema-scoped in PostgreSQL
2031
- *
2032
- * @stability 1
2033
- */
2034
- declare const $sequence: {
2035
- (options?: SequenceDescriptorOptions): SequenceDescriptor;
2036
- [KIND]: typeof SequenceDescriptor;
2037
- };
2038
- interface SequenceDescriptorOptions {
2039
- /**
2040
- * Name of the PostgreSQL sequence to create.
2041
- *
2042
- * This name:
2043
- * - Must be unique within the database schema
2044
- * - Should follow PostgreSQL identifier conventions
2045
- * - Will be used in generated SQL for sequence operations
2046
- * - Should be descriptive of the sequence's purpose
2047
- *
2048
- * If not provided, defaults to the property key where the sequence is declared.
2049
- *
2050
- * **Naming Guidelines**:
2051
- * - Use descriptive names like "order_numbers", "invoice_seq"
2052
- * - Include the purpose or entity type in the name
2053
- * - Consider adding "_seq" suffix for clarity
2054
- * - Use snake_case for consistency with PostgreSQL conventions
2055
- *
2056
- * @example "order_numbers"
2057
- * @example "invoice_sequence"
2058
- * @example "ticket_numbers_seq"
2059
- */
2060
- name?: string;
2061
- /**
2062
- * The starting value for the sequence.
2063
- *
2064
- * This value:
2065
- * - Determines the first number that will be generated
2066
- * - Can be any integer within the sequence's range
2067
- * - Is useful for avoiding conflicts with existing data
2068
- * - Can be set higher for business reasons (e.g., starting invoices at 1000)
2069
- *
2070
- * **Common Patterns**:
2071
- * - Start at 1 for simple counters
2072
- * - Start at 1000+ for professional-looking numbers
2073
- * - Start at current max + 1 when migrating existing data
2074
- *
2075
- * @default 1
2076
- * @example 1 // Simple counter starting at 1
2077
- * @example 1000 // Professional numbering starting at 1000
2078
- * @example 10000 // Large starting number for established businesses
2079
- */
2080
- start?: number;
2081
- /**
2082
- * The increment value for each call to next().
2083
- *
2084
- * This value:
2085
- * - Determines how much the sequence increases each time
2086
- * - Can be any positive or negative integer
2087
- * - Affects the gaps between generated numbers
2088
- * - Can be used for number distribution strategies
2089
- *
2090
- * **Use Cases**:
2091
- * - increment: 1 for consecutive numbering
2092
- * - increment: 10 for distributed numbering (leaves gaps for manual entries)
2093
- * - increment: -1 for countdown sequences
2094
- *
2095
- * @default 1
2096
- * @example 1 // Standard consecutive numbering
2097
- * @example 10 // Leave gaps between numbers
2098
- * @example 100 // Large gaps for special numbering schemes
2099
- */
2100
- increment?: number;
2101
- /**
2102
- * The minimum value the sequence can generate.
2103
- *
2104
- * When the sequence reaches this value:
2105
- * - It cannot generate values below this minimum
2106
- * - Helps prevent negative numbers in contexts where they don't make sense
2107
- * - Works with cycling behavior to define the lower bound
2108
- *
2109
- * **Considerations**:
2110
- * - Set to 1 for positive-only sequences
2111
- * - Set to 0 if zero values are acceptable
2112
- * - Consider business rules about minimum valid numbers
2113
- *
2114
- * @example 1 // No zero or negative values
2115
- * @example 0 // Allow zero values
2116
- * @example 1000 // Maintain minimum professional appearance
2117
- */
2118
- min?: number;
2119
- /**
2120
- * The maximum value the sequence can generate.
2121
- *
2122
- * When the sequence reaches this value:
2123
- * - It cannot generate values above this maximum
2124
- * - Behavior depends on the cycle option
2125
- * - Useful for preventing overflow or limiting number ranges
2126
- *
2127
- * **Planning Considerations**:
2128
- * - Consider the expected volume of your application
2129
- * - Account for business growth over time
2130
- * - Factor in any formatting constraints (e.g., fixed-width displays)
2131
- * - Remember that PostgreSQL sequences can handle very large numbers
2132
- *
2133
- * @example 999999 // Six-digit limit
2134
- * @example 2147483647 // Maximum 32-bit signed integer
2135
- * @example 9999 // Four-digit limit for display purposes
2136
- */
2137
- max?: number;
2138
- /**
2139
- * Whether the sequence should cycle back to the minimum when it reaches the maximum.
2140
- *
2141
- * **cycle: true**:
2142
- * - When max is reached, next value will be the minimum value
2143
- * - Useful for scenarios where number reuse is acceptable
2144
- * - Common for temporary identifiers or rotating references
2145
- *
2146
- * **cycle: false (default)**:
2147
- * - When max is reached, further calls will fail with an error
2148
- * - Prevents unexpected number reuse
2149
- * - Better for permanent identifiers where uniqueness is critical
2150
- *
2151
- * **Use Cases for Cycling**:
2152
- * - Temporary ticket numbers that can be reused
2153
- * - Session IDs with limited lifetime
2154
- * - Batch numbers in rotating systems
2155
- *
2156
- * **Avoid Cycling For**:
2157
- * - Primary keys and permanent identifiers
2158
- * - Invoice numbers and financial references
2159
- * - Audit logs and compliance records
2160
- *
2161
- * @default false
2162
- */
2163
- cycle?: boolean;
2164
- }
2165
- declare class SequenceDescriptor extends Descriptor<SequenceDescriptorOptions> {
2166
- protected readonly provider: PostgresProvider;
2167
- protected created: boolean;
2168
- get name(): string;
2169
- protected create(): Promise<void>;
2170
- next(): Promise<number>;
2171
- current(): Promise<number>;
2172
- }
2173
- //#endregion
2174
1471
  //#region src/descriptors/$transaction.d.ts
2175
1472
  /**
2176
1473
  * Creates a transaction descriptor for database operations requiring atomicity and consistency.
@@ -2188,7 +1485,7 @@ declare class SequenceDescriptor extends Descriptor<SequenceDescriptorOptions> {
2188
1485
  * - Use appropriate isolation levels based on your consistency requirements
2189
1486
  */
2190
1487
  declare const $transaction: <T extends any[], R>(opts: TransactionDescriptorOptions<T, R>) => _alepha_retry0.RetryDescriptorFn<(...args: T) => Promise<R>>;
2191
- interface TransactionDescriptorOptions<T$1 extends any[], R$1> {
1488
+ interface TransactionDescriptorOptions<T extends any[], R> {
2192
1489
  /**
2193
1490
  * Transaction handler function that contains all database operations to be executed atomically.
2194
1491
  *
@@ -2248,7 +1545,7 @@ interface TransactionDescriptorOptions<T$1 extends any[], R$1> {
2248
1545
  * }
2249
1546
  * ```
2250
1547
  */
2251
- handler: (tx: PgTransaction<any, any, any>, ...args: T$1) => Promise<R$1>;
1548
+ handler: (tx: PgTransaction<any, any, any>, ...args: T) => Promise<R>;
2252
1549
  /**
2253
1550
  * PostgreSQL transaction configuration options.
2254
1551
  *
@@ -2322,66 +1619,85 @@ declare class PgVersionMismatchError extends PgError {
2322
1619
  constructor(table: string, id: any);
2323
1620
  }
2324
1621
  //#endregion
2325
- //#region src/providers/RepositoryProvider.d.ts
2326
- declare class RepositoryProvider {
2327
- protected readonly log: _alepha_logger1.Logger;
1622
+ //#region src/providers/DrizzleKitProvider.d.ts
1623
+ declare class DrizzleKitProvider {
1624
+ protected readonly log: _alepha_logger0.Logger;
2328
1625
  protected readonly alepha: Alepha;
2329
- protected get repositories(): RepositoryDescriptor<TableConfig$1, TObject>[];
2330
1626
  /**
2331
- * Get all repositories.
1627
+ * Synchronize database with current schema definitions.
2332
1628
  *
2333
- * @param provider - Filter by provider.
2334
- */
2335
- getRepositories(provider?: PostgresProvider): RepositoryDescriptor<TableConfig$1, TObject>[];
2336
- /**
2337
- * Get all tables from the repositories.
1629
+ * In development mode, it will generate and execute migrations based on the current state.
1630
+ * In testing mode, it will generate migrations from scratch without applying them.
2338
1631
  *
2339
- * @param provider
1632
+ * Does nothing in production mode, you must handle migrations manually.
2340
1633
  */
2341
- getTables(provider?: PostgresProvider): pg$1.PgTableWithColumns<TableConfig$1>[];
1634
+ synchronize(provider: DatabaseProvider): Promise<void>;
2342
1635
  /**
2343
- * Get all pg providers from the repositories.
1636
+ * Mostly used for testing purposes. You can generate SQL migration statements without executing them.
2344
1637
  */
2345
- getProviders(): PostgresProvider[];
2346
- }
2347
- //#endregion
2348
- //#region src/providers/DrizzleKitProvider.d.ts
2349
- declare class DrizzleKitProvider {
2350
- protected readonly log: _alepha_logger1.Logger;
2351
- protected readonly alepha: Alepha;
2352
- protected readonly repositoryProvider: RepositoryProvider;
2353
- push(provider: PostgresProvider, schema?: string): Promise<void>;
2354
- setPgSchema(provider: PostgresProvider): Promise<void>;
1638
+ generateMigration(provider: DatabaseProvider, prevSnapshot?: any): Promise<{
1639
+ statements: string[];
1640
+ models: Record<string, unknown>;
1641
+ snapshot?: any;
1642
+ }>;
2355
1643
  /**
2356
- * Try to generate migrations from scratch based on the models.
2357
- * Then, execute the migrations.
2358
- *
2359
- * This is useful for testing or development purposes.
2360
- *
2361
- * Do not use in production.
2362
- *
2363
- * @param provider - The Postgres provider to use.
2364
- * @param schema - The schema to use.
2365
- * @returns A promise that resolves once the migrations have been executed.
1644
+ * Load all tables, enums, sequences, etc. from the provider's repositories.
2366
1645
  */
2367
- synchronize(provider: PostgresProvider, schema?: string): Promise<void>;
1646
+ getModels(provider: DatabaseProvider): Record<string, unknown>;
2368
1647
  /**
2369
- * Get all tables from the provider's repositories.
1648
+ * Load the migration snapshot from the database.
2370
1649
  */
2371
- protected getTables(provider: PostgresProvider, schema?: string): Promise<Record<string, any>>;
2372
- protected loadMigrationSnapshot(provider: PostgresProvider): Promise<any>;
2373
- protected saveMigrationSnapshot(provider: PostgresProvider, curr: Record<string, any>, entry?: {
2374
- id: number;
2375
- snapshot: string;
2376
- }): Promise<void>;
2377
- protected executeStatements(statements: string[], provider: PostgresProvider, _schema?: string, catchErrors?: boolean): Promise<void>;
2378
- protected prepareSchema(schemaName: string, provider: PostgresProvider, repositories: any[]): Promise<void>;
1650
+ protected loadDevMigrations(provider: DatabaseProvider): Promise<DevMigrations | undefined>;
1651
+ protected saveDevMigrations(provider: DatabaseProvider, curr: Record<string, any>, devMigrations?: DevMigrations): Promise<void>;
1652
+ protected executeStatements(statements: string[], provider: DatabaseProvider, catchErrors?: boolean): Promise<void>;
1653
+ protected createSchemaIfNotExists(provider: DatabaseProvider, schemaName: string): Promise<void>;
2379
1654
  /**
2380
1655
  * Try to load the official Drizzle Kit API.
2381
1656
  * If not available, fallback to the local kit import.
2382
1657
  */
2383
1658
  protected importDrizzleKit(): typeof DrizzleKit;
2384
- synchronizeSqlite(provider: PostgresProvider): Promise<void>;
1659
+ }
1660
+ declare const devMigrationsSchema: typebox4.TObject<{
1661
+ id: typebox4.TNumber;
1662
+ name: typebox4.TString;
1663
+ snapshot: typebox4.TString;
1664
+ created_at: typebox4.TString;
1665
+ }>;
1666
+ type DevMigrations = Static<typeof devMigrationsSchema>;
1667
+ //#endregion
1668
+ //#region src/services/PostgresModelBuilder.d.ts
1669
+ declare class PostgresModelBuilder extends ModelBuilder {
1670
+ protected schemas: Map<string, drizzle_orm_pg_core0.PgSchema<string>>;
1671
+ protected getPgSchema(name: string): any;
1672
+ buildTable(entity: EntityDescriptor<any>, options: {
1673
+ tables: Map<string, unknown>;
1674
+ enums: Map<string, unknown>;
1675
+ schema: string;
1676
+ }): void;
1677
+ buildSequence(sequence: SequenceDescriptor, options: {
1678
+ sequences: Map<string, unknown>;
1679
+ schema: string;
1680
+ }): void;
1681
+ /**
1682
+ * Get PostgreSQL-specific config builder for the table.
1683
+ */
1684
+ protected getTableConfig(entity: EntityDescriptor, tables: Map<string, unknown>): ((self: BuildExtraConfigColumns<string, any, "pg">) => PgTableExtraConfigValue[]) | undefined;
1685
+ schemaToPgColumns: <T extends TObject>(tableName: string, schema: T, nsp: PgSchema, enums: Map<string, unknown>, tables: Map<string, unknown>) => FromSchema<T>;
1686
+ mapFieldToColumn: (tableName: string, fieldName: string, value: TSchema, nsp: PgSchema, enums: Map<string, any>) => any;
1687
+ /**
1688
+ * Map a string to a PG column.
1689
+ *
1690
+ * @param key The key of the field.
1691
+ * @param value The value of the field.
1692
+ */
1693
+ mapStringToColumn: (key: string, value: TSchema) => drizzle_orm_pg_core0.PgUUIDBuilderInitial<string> | drizzle_orm_pg_core0.PgCustomColumnBuilder<{
1694
+ name: string;
1695
+ dataType: "custom";
1696
+ columnType: "PgCustomColumn";
1697
+ data: Buffer<ArrayBufferLike>;
1698
+ driverParam: unknown;
1699
+ enumValues: undefined;
1700
+ }> | drizzle_orm_pg_core0.PgTimestampStringBuilderInitial<string> | drizzle_orm_pg_core0.PgDateStringBuilderInitial<string> | drizzle_orm_pg_core0.PgTextBuilderInitial<string, [string, ...string[]]>;
2385
1701
  }
2386
1702
  //#endregion
2387
1703
  //#region src/providers/drivers/NodePostgresProvider.d.ts
@@ -2409,42 +1725,33 @@ declare const envSchema: _alepha_core1.TObject<{
2409
1725
  * It will generate the migration script and save it to the DB.
2410
1726
  *
2411
1727
  * This is recommended for development and testing purposes only.
2412
- *
2413
- * @default false
2414
1728
  */
2415
1729
  POSTGRES_SYNCHRONIZE: _alepha_core1.TOptional<_alepha_core1.TBoolean>;
2416
- /**
2417
- * Push the schema to the database.
2418
- * It's like `drizzle-kit push` command.
2419
- * It will introspect the models from DB and generate the SQL statements to create or update the tables.
2420
- *
2421
- * @default false
2422
- */
2423
- POSTGRES_PUSH: _alepha_core1.TOptional<_alepha_core1.TBoolean>;
2424
1730
  }>;
2425
1731
  interface NodePostgresProviderOptions {
2426
1732
  migrations: MigrationConfig;
2427
1733
  connection: postgres.Options<any>;
2428
1734
  }
2429
- declare class NodePostgresProvider extends PostgresProvider {
1735
+ declare class NodePostgresProvider extends DatabaseProvider {
1736
+ static readonly SSL_MODES: readonly ["require", "allow", "prefer", "verify-full"];
2430
1737
  readonly dialect = "postgres";
2431
- protected readonly sslModes: readonly ["require", "allow", "prefer", "verify-full"];
2432
- protected readonly log: _alepha_logger1.Logger;
1738
+ protected readonly log: _alepha_logger0.Logger;
2433
1739
  protected readonly env: {
2434
1740
  DATABASE_URL?: string | undefined;
2435
1741
  POSTGRES_SCHEMA?: string | undefined;
2436
1742
  POSTGRES_SYNCHRONIZE?: boolean | undefined;
2437
- POSTGRES_PUSH?: boolean | undefined;
2438
1743
  };
2439
1744
  protected readonly alepha: Alepha;
2440
1745
  protected readonly kit: DrizzleKitProvider;
1746
+ protected readonly builder: PostgresModelBuilder;
2441
1747
  protected client?: postgres.Sql;
2442
1748
  protected pg?: PostgresJsDatabase;
2443
1749
  readonly options: NodePostgresProviderOptions;
2444
1750
  /**
2445
1751
  * In testing mode, the schema name will be generated and deleted after the test.
2446
1752
  */
2447
- protected schemaForTesting?: string;
1753
+ protected schemaForTesting: string | undefined;
1754
+ execute(statement: SQLLike): Promise<Array<Record<string, unknown>>>;
2448
1755
  /**
2449
1756
  * Get Postgres schema.
2450
1757
  */
@@ -2474,7 +1781,7 @@ declare class NodePostgresProvider extends PostgresProvider {
2474
1781
  //#endregion
2475
1782
  //#region src/providers/PostgresTypeProvider.d.ts
2476
1783
  declare class PostgresTypeProvider {
2477
- readonly attr: <T extends TSchema$1, Attr extends PgSymbolKeys>(type: T, attr: Attr, value?: PgSymbols[Attr]) => PgAttr<T, Attr>;
1784
+ readonly attr: <T extends TSchema, Attr extends PgSymbolKeys>(type: T, attr: Attr, value?: PgSymbols[Attr]) => PgAttr<T, Attr>;
2478
1785
  /**
2479
1786
  * Creates a primary key with an identity column.
2480
1787
  */
@@ -2502,7 +1809,7 @@ declare class PostgresTypeProvider {
2502
1809
  * Wrap a schema with "default" attribute.
2503
1810
  * This is used to set a default value for a column in the database.
2504
1811
  */
2505
- readonly default: <T extends TSchema$1>(type: T, value?: Static<T>) => PgAttr<T, PgDefault>;
1812
+ readonly default: <T extends TSchema>(type: T, value?: Static<T>) => PgAttr<T, PgDefault>;
2506
1813
  /**
2507
1814
  * Creates a column 'version'.
2508
1815
  *
@@ -2517,21 +1824,33 @@ declare class PostgresTypeProvider {
2517
1824
  /**
2518
1825
  * Creates a column Created At. So just a datetime column with a default value of the current timestamp.
2519
1826
  */
2520
- readonly createdAt: (options?: TStringOptions) => PgAttr<PgAttr<TString, typeof PG_CREATED_AT>, typeof PG_DEFAULT>;
1827
+ readonly createdAt: (options?: TStringOptions) => PgAttr<PgAttr<typebox4.TCodec<TString, dayjs0.Dayjs>, typeof PG_CREATED_AT>, typeof PG_DEFAULT>;
2521
1828
  /**
2522
1829
  * Creates a column Updated At. Like createdAt, but it is updated on every update of the row.
2523
1830
  */
2524
- readonly updatedAt: (options?: TStringOptions) => PgAttr<PgAttr<TString, typeof PG_UPDATED_AT>, typeof PG_DEFAULT>;
1831
+ readonly updatedAt: (options?: TStringOptions) => PgAttr<PgAttr<typebox4.TCodec<TString, dayjs0.Dayjs>, typeof PG_UPDATED_AT>, typeof PG_DEFAULT>;
2525
1832
  /**
2526
1833
  * Creates a column Deleted At for soft delete functionality.
2527
1834
  * This is used to mark rows as deleted without actually removing them from the database.
2528
1835
  * The column is nullable - NULL means not deleted, timestamp means deleted.
2529
1836
  */
2530
- readonly deletedAt: (options?: TStringOptions) => PgAttr<typebox0.TOptional<TString>, typeof PG_DELETED_AT>;
1837
+ readonly deletedAt: (options?: TStringOptions) => PgAttr<typebox4.TOptional<typebox4.TCodec<TString, dayjs0.Dayjs>>, typeof PG_DELETED_AT>;
1838
+ /**
1839
+ * Creates a Postgres ENUM type.
1840
+ *
1841
+ * > By default, `t.enum()` is mapped to a TEXT column in Postgres.
1842
+ * > Using this method, you can create a real ENUM type in the database.
1843
+ *
1844
+ * @example
1845
+ * ```ts
1846
+ * const statusEnum = pg.enum(["pending", "active", "archived"], { name: "status_enum" });
1847
+ * ```
1848
+ */
1849
+ readonly enum: <T extends string[]>(values: [...T], pgEnumOptions?: PgEnumOptions, typeOptions?: TStringOptions) => PgAttr<TUnsafe<T[number]>, typeof PG_ENUM>;
2531
1850
  /**
2532
1851
  * Creates a reference to another table or schema. Basically a foreign key.
2533
1852
  */
2534
- readonly ref: <T extends TSchema$1>(type: T, ref: () => any, actions?: {
1853
+ readonly ref: <T extends TSchema>(type: T, ref: () => any, actions?: {
2535
1854
  onUpdate?: UpdateDeleteAction$1;
2536
1855
  onDelete?: UpdateDeleteAction$1;
2537
1856
  }) => PgAttr<T, PgRef>;
@@ -2540,8 +1859,6 @@ declare class PostgresTypeProvider {
2540
1859
  * It's used by {@link RepositoryDescriptor#paginate} method.
2541
1860
  */
2542
1861
  readonly page: <T extends TObject>(resource: T, options?: TObjectOptions) => TPage<T>;
2543
- readonly many: <T extends TObject, Config extends TableConfig>(table: PgTableWithColumnsAndSchema<Config, T>, foreignKey: keyof T["properties"]) => TOptionalAdd<PgAttr<PgAttr<TArray<T>, PgMany>, PgDefault>>;
2544
- readonly one: <T extends TObject, Config extends TableConfig>(table: PgTableWithColumnsAndSchema<Config, T>, foreignKey: keyof T["properties"]) => PgAttr<PgAttr<TOptionalAdd<T>, PgOne>, PgDefault>;
2545
1862
  }
2546
1863
  declare const pg: PostgresTypeProvider;
2547
1864
  //#endregion
@@ -2549,13 +1866,13 @@ declare const pg: PostgresTypeProvider;
2549
1866
  /**
2550
1867
  * @deprecated Use `pg.primaryKey()` instead.
2551
1868
  */
2552
- declare const legacyIdSchema: PgAttr<PgAttr<PgAttr<typebox0.TInteger, typeof PG_PRIMARY_KEY>, typeof PG_SERIAL>, typeof PG_DEFAULT>;
1869
+ declare const legacyIdSchema: PgAttr<PgAttr<PgAttr<typebox4.TInteger, typeof PG_PRIMARY_KEY>, typeof PG_SERIAL>, typeof PG_DEFAULT>;
2553
1870
  //#endregion
2554
1871
  //#region src/types/schema.d.ts
2555
1872
  /**
2556
1873
  * Postgres schema type.
2557
1874
  */
2558
- declare const schema: <TDocument extends TSchema$1>(name: string, document: TDocument) => drizzle_orm6.$Type<pg$1.PgCustomColumnBuilder<{
1875
+ declare const schema: <TDocument extends TSchema>(name: string, document: TDocument) => drizzle_orm0.$Type<drizzle_orm_pg_core0.PgCustomColumnBuilder<{
2559
1876
  name: string;
2560
1877
  dataType: "custom";
2561
1878
  columnType: "PgCustomColumn";
@@ -2598,14 +1915,13 @@ declare const schema: <TDocument extends TSchema$1>(name: string, document: TDoc
2598
1915
  *
2599
1916
  * Migrations are supported via Drizzle ORM, you need to use the `drizzle-kit` CLI tool to generate and run migrations.
2600
1917
  *
2601
- * Relations are **NOT SUPPORTED** yet. If you need relations, please use the `drizzle-orm` package directly.
2602
- *
2603
1918
  * @see {@link $entity}
1919
+ * @see {@link $sequence}
2604
1920
  * @see {@link $repository}
2605
1921
  * @see {@link $transaction}
2606
1922
  * @module alepha.postgres
2607
1923
  */
2608
1924
  declare const AlephaPostgres: _alepha_core1.Service<_alepha_core1.Module<{}>>;
2609
1925
  //#endregion
2610
- export { $entity, $repository, $sequence, $transaction, AlephaPostgres, DrizzleKitProvider, Entity, EntityDescriptorOptions, FilterOperators, FromSchema, NodePostgresProvider, NodePostgresProviderOptions, OrderBy, OrderByClause, OrderDirection, PG_CREATED_AT, PG_DEFAULT, PG_DELETED_AT, PG_IDENTITY, PG_MANY, PG_ONE, PG_PRIMARY_KEY, PG_REF, PG_SCHEMA, PG_SERIAL, PG_UPDATED_AT, PG_VERSION, Page, PageQuery, PgAttr, PgAttrField, PgConflictError, PgDefault, PgEntityNotFoundError, PgError, PgIdentityOptions, PgMany, PgManyOptions, PgMigrationError, PgOne, PgPrimaryKey, PgQuery, PgQueryRelations, PgQueryWhere, PgQueryWhereOrSQL, PgRef, PgRefOptions, PgRelation, PgRelationMap, PgStatic, PgSymbolKeys, PgSymbols, PgTableConfig, PgTableWithColumnsAndSchema, PgVersionMismatchError, PostgresProvider, PostgresTypeProvider, RepositoryDescriptor, RepositoryDescriptorOptions, RepositoryProvider, SQLLike, SequenceDescriptor, SequenceDescriptorOptions, StatementOptions, TObjectInsert, TObjectUpdate, TPage, TransactionContext, TransactionDescriptorOptions, camelToSnakeCase, drizzle_orm6 as drizzle, getAttrFields, insertSchema, legacyIdSchema, mapFieldToColumn, mapStringToColumn, pageQuerySchema, pageSchema, pg, pgAttr, schema, schemaToPgColumns, sql, updateSchema };
1926
+ export { $entity, $repository, $sequence, $transaction, AlephaPostgres, DatabaseProvider, DrizzleKitProvider, EntityColumn, EntityColumns, EntityDescriptor, EntityDescriptorOptions, FilterOperators, FromSchema, NodePostgresProvider, NodePostgresProviderOptions, OrderBy, OrderByClause, OrderDirection, PG_CREATED_AT, PG_DEFAULT, PG_DELETED_AT, PG_ENUM, PG_IDENTITY, PG_PRIMARY_KEY, PG_REF, PG_SERIAL, PG_UPDATED_AT, PG_VERSION, Page, PageQuery, PgAttr, PgAttrField, PgConflictError, PgDefault, PgEntityNotFoundError, PgEnumOptions, PgError, PgIdentityOptions, PgMigrationError, PgPrimaryKey, PgQuery, PgQueryRelations, PgQueryWhere, PgQueryWhereOrSQL, PgRef, PgRefOptions, PgRelation, PgRelationMap, PgStatic, PgSymbolKeys, PgSymbols, PgVersionMismatchError, PostgresTypeProvider, RepositoryDescriptor, RepositoryDescriptorOptions, SQLLike, SchemaToTableConfig, SequenceDescriptor, SequenceDescriptorOptions, StatementOptions, TObjectInsert, TObjectUpdate, TPage, TransactionContext, TransactionDescriptorOptions, drizzle_orm0 as drizzle, getAttrFields, insertSchema, legacyIdSchema, pageQuerySchema, pageSchema, pg, pgAttr, schema, sql, updateSchema };
2611
1927
  //# sourceMappingURL=index.d.ts.map