zod-sqlite 1.0.3 → 1.0.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (4) hide show
  1. package/README.md +382 -379
  2. package/dist/index.d.mts +206 -212
  3. package/dist/index.mjs +4 -287
  4. package/package.json +13 -13
package/dist/index.d.mts CHANGED
@@ -1,23 +1,134 @@
1
1
  import * as zod from "zod/v4/core";
2
-
3
- //#region src/types.d.ts
4
2
  /**
5
- * SQLite native column types.
3
+ * Database column configuration.
6
4
  *
7
- * SQLite uses a dynamic type system with these five storage classes.
8
- * Column values are stored in one of these formats, and SQLite performs
9
- * type conversions as needed during operations.
10
- * @see https://www.sqlite.org/datatype3.html#storage_classes_and_datatypes
11
- */
12
- type SQLiteType = 'BLOB' | 'INTEGER' | 'NULL' | 'REAL' | 'TEXT';
13
- /**
14
- * SQLite supported column types.
5
+ * Defines a single column in a table, including its name, type (via Zod schema),
6
+ * validation rules, and optional constraints like uniqueness and foreign keys.
15
7
  *
16
- * These types are supported by SQLite but not as native storage classes.
17
- * They are often used as aliases for other types or for specific purposes.
18
- * @see https://www.sqlite.org/datatype3.html#type_affinity
8
+ * **Column definition workflow:**
9
+ * 1. Zod schema is analyzed to determine SQLite type (TEXT, INTEGER, etc.)
10
+ * 2. Zod schema provides TypeScript type safety and runtime validation
11
+ * 3. Constraints (unique, foreign key) are applied at the database level
12
+ * @template TName - Literal string type for the column name
13
+ * @template TSchema - Zod type for the column schema
14
+ * @example
15
+ * ```ts
16
+ * // Simple text column
17
+ * {
18
+ * name: 'email',
19
+ * schema: z.email()
20
+ * }
21
+ *
22
+ * // Unique column with validation
23
+ * {
24
+ * name: 'username',
25
+ * schema: z.string().min(3).max(20),
26
+ * unique: true
27
+ * }
28
+ *
29
+ * // Foreign key column
30
+ * {
31
+ * name: 'author_id',
32
+ * schema: z.int(),
33
+ * references: {
34
+ * table: 'users',
35
+ * column: 'id',
36
+ * onDelete: 'CASCADE'
37
+ * }
38
+ * }
39
+ *
40
+ * // Optional column with default
41
+ * {
42
+ * name: 'status',
43
+ * schema: z.enum(['draft', 'published']).default('draft')
44
+ * }
45
+ * ```
19
46
  */
20
- type SQLiteSupportType = 'BIGINT' | 'BOOLEAN' | 'DATE' | 'DATETIME' | 'FLOAT' | 'NUMERIC';
47
+ export interface ColumnConfig<TName extends string = string, TSchema extends zod.$ZodType = zod.$ZodType> {
48
+ /**
49
+ * Name of the column.
50
+ *
51
+ * Used in CREATE TABLE statement and all SQL queries.
52
+ * Should use snake_case by convention.
53
+ * @example 'user_id'
54
+ * @example 'created_at'
55
+ */
56
+ name: TName;
57
+ /**
58
+ * Foreign key reference configuration.
59
+ *
60
+ * Creates a constraint linking this column to a column in another table.
61
+ * Ensures referential integrity by preventing orphaned records.
62
+ *
63
+ * **Requirements:**
64
+ * - Referenced column should typically be a PRIMARY KEY or UNIQUE
65
+ * - Types must be compatible between the two columns
66
+ * - Foreign keys must be enabled: `PRAGMA foreign_keys = ON`
67
+ *
68
+ * **Composite foreign keys** (multiple columns referencing multiple columns)
69
+ * cannot be defined here - they must be defined at the table level as a
70
+ * separate constraint.
71
+ * @example
72
+ * ```ts
73
+ * {
74
+ * name: 'user_id',
75
+ * schema: z.int(),
76
+ * references: {
77
+ * table: 'users',
78
+ * column: 'id',
79
+ * onDelete: 'CASCADE'
80
+ * }
81
+ * }
82
+ * ```
83
+ */
84
+ references?: ForeignKeyReference;
85
+ /**
86
+ * Zod schema defining the column's type, validation, and constraints.
87
+ *
88
+ * The Zod schema serves dual purposes:
89
+ * 1. **Database level**: Mapped to SQLite type (TEXT, INTEGER, REAL, BLOB, NULL)
90
+ * 2. **Application level**: Provides TypeScript types and runtime validation
91
+ *
92
+ * **Zod to SQLite type mapping:**
93
+ * - `z.string()`, `z.enum()`, `z.literal()`, `z.date()` → TEXT
94
+ * - `z.number()` → REAL (or INTEGER if `.int()` is used)
95
+ * - `z.bigint()`, `z.boolean()` → INTEGER
96
+ * - `z.custom()` for file/blob → BLOB
97
+ * - `z.null()`, `z.undefined()` → NULL
98
+ *
99
+ * **Zod features mapped to SQL:**
100
+ * - `.optional()`, `.nullable()` → column allows NULL
101
+ * - `.default(value)` → DEFAULT clause in SQL
102
+ * - `.min()`, `.max()`, `.email()`, etc. → runtime validation only
103
+ * @example z.string() - TEXT column
104
+ * @example z.int() - INTEGER column
105
+ * @example z.string().nullable() - TEXT column that allows NULL
106
+ * @example z.boolean().default(false) - INTEGER with DEFAULT 0
107
+ */
108
+ schema: TSchema;
109
+ /**
110
+ * Whether column values must be unique across all rows.
111
+ *
112
+ * When true, adds a UNIQUE constraint to the column. Any attempt to
113
+ * INSERT or UPDATE a duplicate value will fail.
114
+ *
115
+ * **Note**: This is different from PRIMARY KEY:
116
+ * - UNIQUE columns can be NULL (unless also NOT NULL)
117
+ * - A table can have multiple UNIQUE columns
118
+ * - PRIMARY KEY implies UNIQUE + NOT NULL
119
+ * @default false
120
+ * @example
121
+ * ```ts
122
+ * // Unique email address
123
+ * {
124
+ * name: 'email',
125
+ * schema: z.email(),
126
+ * unique: true
127
+ * }
128
+ * ```
129
+ */
130
+ unique?: boolean;
131
+ }
21
132
  /**
22
133
  * Foreign key constraint actions for ON DELETE and ON UPDATE clauses.
23
134
  *
@@ -51,7 +162,7 @@ type SQLiteSupportType = 'BIGINT' | 'BOOLEAN' | 'DATE' | 'DATETIME' | 'FLOAT' |
51
162
  * }
52
163
  * ```
53
164
  */
54
- type ForeignKeyAction = 'CASCADE' | 'NO ACTION' | 'RESTRICT' | 'SET DEFAULT' | 'SET NULL';
165
+ export type ForeignKeyAction = 'CASCADE' | 'NO ACTION' | 'RESTRICT' | 'SET DEFAULT' | 'SET NULL';
55
166
  /**
56
167
  * Foreign key reference configuration.
57
168
  *
@@ -81,13 +192,7 @@ type ForeignKeyAction = 'CASCADE' | 'NO ACTION' | 'RESTRICT' | 'SET DEFAULT' | '
81
192
  * }
82
193
  * ```
83
194
  */
84
- interface ForeignKeyReference {
85
- /**
86
- * Name of the referenced table.
87
- *
88
- * This is the parent table that contains the column being referenced.
89
- */
90
- table: string;
195
+ export interface ForeignKeyReference {
91
196
  /**
92
197
  * Name of the referenced column in the parent table.
93
198
  *
@@ -110,6 +215,12 @@ interface ForeignKeyReference {
110
215
  * @default 'NO ACTION'
111
216
  */
112
217
  onUpdate?: ForeignKeyAction;
218
+ /**
219
+ * Name of the referenced table.
220
+ *
221
+ * This is the parent table that contains the column being referenced.
222
+ */
223
+ table: string;
113
224
  }
114
225
  /**
115
226
  * Database index configuration.
@@ -153,7 +264,16 @@ interface ForeignKeyReference {
153
264
  * }
154
265
  * ```
155
266
  */
156
- interface IndexConfig<TColumns extends ReadonlyArray<ColumnConfig<string, zod.$ZodType>> = ReadonlyArray<ColumnConfig<string, zod.$ZodType>>> {
267
+ export interface IndexConfig<TColumns extends readonly ColumnConfig<string, zod.$ZodType>[] = readonly ColumnConfig<string, zod.$ZodType>[]> {
268
+ /**
269
+ * Column names to include in the index.
270
+ *
271
+ * For composite indexes, the order matters: queries that filter on the
272
+ * first columns benefit most from the index.
273
+ * @example ['email'] - single column
274
+ * @example ['last_name', 'first_name'] - composite index
275
+ */
276
+ columns: readonly TColumns[number]['name'][];
157
277
  /**
158
278
  * Unique name for the index.
159
279
  *
@@ -163,15 +283,6 @@ interface IndexConfig<TColumns extends ReadonlyArray<ColumnConfig<string, zod.$Z
163
283
  * @example 'idx_posts_author_created'
164
284
  */
165
285
  name: string;
166
- /**
167
- * Column names to include in the index.
168
- *
169
- * For composite indexes, the order matters: queries that filter on the
170
- * first columns benefit most from the index.
171
- * @example ['email'] - single column
172
- * @example ['last_name', 'first_name'] - composite index
173
- */
174
- columns: ReadonlyArray<TColumns[number]['name']>;
175
286
  /**
176
287
  * Whether this is a unique index.
177
288
  *
@@ -196,155 +307,27 @@ interface IndexConfig<TColumns extends ReadonlyArray<ColumnConfig<string, zod.$Z
196
307
  where?: string;
197
308
  }
198
309
  /**
199
- * Database column configuration.
200
- *
201
- * Defines a single column in a table, including its name, type (via Zod schema),
202
- * validation rules, and optional constraints like uniqueness and foreign keys.
203
- *
204
- * **Column definition workflow:**
205
- * 1. Zod schema is analyzed to determine SQLite type (TEXT, INTEGER, etc.)
206
- * 2. Zod schema provides TypeScript type safety and runtime validation
207
- * 3. Constraints (unique, foreign key) are applied at the database level
208
- * @template TName - Literal string type for the column name
209
- * @template TSchema - Zod type for the column schema
210
- * @example
211
- * ```ts
212
- * // Simple text column
213
- * {
214
- * name: 'email',
215
- * schema: z.email()
216
- * }
217
- *
218
- * // Unique column with validation
219
- * {
220
- * name: 'username',
221
- * schema: z.string().min(3).max(20),
222
- * unique: true
223
- * }
310
+ * SQLite supported column types.
224
311
  *
225
- * // Foreign key column
226
- * {
227
- * name: 'author_id',
228
- * schema: z.int(),
229
- * references: {
230
- * table: 'users',
231
- * column: 'id',
232
- * onDelete: 'CASCADE'
233
- * }
234
- * }
312
+ * These types are supported by SQLite but not as native storage classes.
313
+ * They are often used as aliases for other types or for specific purposes.
314
+ * @see https://www.sqlite.org/datatype3.html#type_affinity
315
+ */
316
+ export type SQLiteSupportType = 'BIGINT' | 'BOOLEAN' | 'DATE' | 'DATETIME' | 'FLOAT' | 'NUMERIC';
317
+ /**
318
+ * SQLite native column types.
235
319
  *
236
- * // Optional column with default
237
- * {
238
- * name: 'status',
239
- * schema: z.enum(['draft', 'published']).default('draft')
240
- * }
241
- * ```
320
+ * SQLite uses a dynamic type system with these five storage classes.
321
+ * Column values are stored in one of these formats, and SQLite performs
322
+ * type conversions as needed during operations.
323
+ * @see https://www.sqlite.org/datatype3.html#storage_classes_and_datatypes
242
324
  */
243
- interface ColumnConfig<TName extends string = string, TSchema extends zod.$ZodType = zod.$ZodType> {
244
- /**
245
- * Name of the column.
246
- *
247
- * Used in CREATE TABLE statement and all SQL queries.
248
- * Should use snake_case by convention.
249
- * @example 'user_id'
250
- * @example 'created_at'
251
- */
252
- name: TName;
253
- /**
254
- * Zod schema defining the column's type, validation, and constraints.
255
- *
256
- * The Zod schema serves dual purposes:
257
- * 1. **Database level**: Mapped to SQLite type (TEXT, INTEGER, REAL, BLOB, NULL)
258
- * 2. **Application level**: Provides TypeScript types and runtime validation
259
- *
260
- * **Zod to SQLite type mapping:**
261
- * - `z.string()`, `z.enum()`, `z.literal()`, `z.date()` → TEXT
262
- * - `z.number()` → REAL (or INTEGER if `.int()` is used)
263
- * - `z.bigint()`, `z.boolean()` → INTEGER
264
- * - `z.custom()` for file/blob → BLOB
265
- * - `z.null()`, `z.undefined()` → NULL
266
- *
267
- * **Zod features mapped to SQL:**
268
- * - `.optional()`, `.nullable()` → column allows NULL
269
- * - `.default(value)` → DEFAULT clause in SQL
270
- * - `.min()`, `.max()`, `.email()`, etc. → runtime validation only
271
- * @example z.string() - TEXT column
272
- * @example z.int() - INTEGER column
273
- * @example z.string().nullable() - TEXT column that allows NULL
274
- * @example z.boolean().default(false) - INTEGER with DEFAULT 0
275
- */
276
- schema: TSchema;
277
- /**
278
- * Whether column values must be unique across all rows.
279
- *
280
- * When true, adds a UNIQUE constraint to the column. Any attempt to
281
- * INSERT or UPDATE a duplicate value will fail.
282
- *
283
- * **Note**: This is different from PRIMARY KEY:
284
- * - UNIQUE columns can be NULL (unless also NOT NULL)
285
- * - A table can have multiple UNIQUE columns
286
- * - PRIMARY KEY implies UNIQUE + NOT NULL
287
- * @default false
288
- * @example
289
- * ```ts
290
- * // Unique email address
291
- * {
292
- * name: 'email',
293
- * schema: z.email(),
294
- * unique: true
295
- * }
296
- * ```
297
- */
298
- unique?: boolean;
299
- /**
300
- * Foreign key reference configuration.
301
- *
302
- * Creates a constraint linking this column to a column in another table.
303
- * Ensures referential integrity by preventing orphaned records.
304
- *
305
- * **Requirements:**
306
- * - Referenced column should typically be a PRIMARY KEY or UNIQUE
307
- * - Types must be compatible between the two columns
308
- * - Foreign keys must be enabled: `PRAGMA foreign_keys = ON`
309
- *
310
- * **Composite foreign keys** (multiple columns referencing multiple columns)
311
- * cannot be defined here - they must be defined at the table level as a
312
- * separate constraint.
313
- * @example
314
- * ```ts
315
- * {
316
- * name: 'user_id',
317
- * schema: z.int(),
318
- * references: {
319
- * table: 'users',
320
- * column: 'id',
321
- * onDelete: 'CASCADE'
322
- * }
323
- * }
324
- * ```
325
- */
326
- references?: ForeignKeyReference;
327
- }
325
+ export type SQLiteType = 'BLOB' | 'INTEGER' | 'NULL' | 'REAL' | 'TEXT';
328
326
  /**
329
327
  * Complete database table configuration.
330
328
  * @template TColumns - An array of column configuration objects.
331
329
  */
332
- interface TableConfig<TColumns extends ReadonlyArray<ColumnConfig<string, zod.$ZodType>> = ReadonlyArray<ColumnConfig<string, zod.$ZodType>>> {
333
- /**
334
- * Name of the table.
335
- *
336
- * Used in CREATE TABLE statement and all SQL queries.
337
- * Should use snake_case by convention (e.g., 'user_profiles', 'order_items').
338
- *
339
- * **Naming conventions:**
340
- * - Use plural nouns for tables representing collections (e.g., 'users', 'posts')
341
- * - Use singular nouns for junction tables (e.g., 'user_role', 'post_tag')
342
- * - Avoid SQL reserved keywords (e.g., 'order' → 'orders' or 'user_order')
343
- * @example 'users'
344
- * @example 'blog_posts'
345
- * @example 'user_sessions'
346
- */
347
- name: string;
330
+ export interface TableConfig<TColumns extends readonly ColumnConfig<string, zod.$ZodType>[] = readonly ColumnConfig<string, zod.$ZodType>[]> {
348
331
  /**
349
332
  * Array of column configurations defining the table structure.
350
333
  *
@@ -367,35 +350,6 @@ interface TableConfig<TColumns extends ReadonlyArray<ColumnConfig<string, zod.$Z
367
350
  * ```
368
351
  */
369
352
  columns: TColumns;
370
- /**
371
- * Column name(s) that form the primary key.
372
- *
373
- * The primary key uniquely identifies each row in the table and cannot
374
- * contain NULL values. Always provided as an array, even for single-column
375
- * primary keys.
376
- *
377
- * **Single column primary key:**
378
- * - Use an array with one element (e.g., `['id']`)
379
- * - Typically an auto-incrementing integer
380
- * - Most common pattern for standard entity tables
381
- *
382
- * **Composite primary key:**
383
- * - Use an array with multiple elements (e.g., `['user_id', 'post_id']`)
384
- * - Common in junction tables for many-to-many relationships
385
- * - Order matters: most specific/selective column should come first
386
- * - The combination of all columns must be unique
387
- *
388
- * **Notes:**
389
- * - Every table should have a primary key
390
- * - Primary key columns are automatically indexed by SQLite
391
- * - Primary key implies UNIQUE + NOT NULL constraints on all columns
392
- * - Cannot be changed after table creation (requires table rebuild)
393
- * @example ['id'] - single column primary key
394
- * @example ['user_id', 'role_id'] - composite primary key for junction table
395
- * @example ['tenant_id', 'record_id'] - composite key for multi-tenant data
396
- * @example ['country_code', 'postal_code'] - composite key for location data
397
- */
398
- primaryKeys: ReadonlyArray<TColumns[number]['name']>;
399
353
  /**
400
354
  * Optional array of index configurations for query optimization.
401
355
  *
@@ -434,10 +388,52 @@ interface TableConfig<TColumns extends ReadonlyArray<ColumnConfig<string, zod.$Z
434
388
  * ]
435
389
  * ```
436
390
  */
437
- indexes?: Array<IndexConfig<TColumns>>;
391
+ indexes?: IndexConfig<TColumns>[];
392
+ /**
393
+ * Name of the table.
394
+ *
395
+ * Used in CREATE TABLE statement and all SQL queries.
396
+ * Should use snake_case by convention (e.g., 'user_profiles', 'order_items').
397
+ *
398
+ * **Naming conventions:**
399
+ * - Use plural nouns for tables representing collections (e.g., 'users', 'posts')
400
+ * - Use singular nouns for junction tables (e.g., 'user_role', 'post_tag')
401
+ * - Avoid SQL reserved keywords (e.g., 'order' → 'orders' or 'user_order')
402
+ * @example 'users'
403
+ * @example 'blog_posts'
404
+ * @example 'user_sessions'
405
+ */
406
+ name: string;
407
+ /**
408
+ * Column name(s) that form the primary key.
409
+ *
410
+ * The primary key uniquely identifies each row in the table and cannot
411
+ * contain NULL values. Always provided as an array, even for single-column
412
+ * primary keys.
413
+ *
414
+ * **Single column primary key:**
415
+ * - Use an array with one element (e.g., `['id']`)
416
+ * - Typically an auto-incrementing integer
417
+ * - Most common pattern for standard entity tables
418
+ *
419
+ * **Composite primary key:**
420
+ * - Use an array with multiple elements (e.g., `['user_id', 'post_id']`)
421
+ * - Common in junction tables for many-to-many relationships
422
+ * - Order matters: most specific/selective column should come first
423
+ * - The combination of all columns must be unique
424
+ *
425
+ * **Notes:**
426
+ * - Every table should have a primary key
427
+ * - Primary key columns are automatically indexed by SQLite
428
+ * - Primary key implies UNIQUE + NOT NULL constraints on all columns
429
+ * - Cannot be changed after table creation (requires table rebuild)
430
+ * @example ['id'] - single column primary key
431
+ * @example ['user_id', 'role_id'] - composite primary key for junction table
432
+ * @example ['tenant_id', 'record_id'] - composite key for multi-tenant data
433
+ * @example ['country_code', 'postal_code'] - composite key for location data
434
+ */
435
+ primaryKeys: readonly TColumns[number]['name'][];
438
436
  }
439
- //#endregion
440
- //#region src/table.d.ts
441
437
  /**
442
438
  * Creates a table definition and Zod schema.
443
439
  *
@@ -450,12 +446,10 @@ interface TableConfig<TColumns extends ReadonlyArray<ColumnConfig<string, zod.$Z
450
446
  * @param config Table configuration object
451
447
  * @returns Object containing SQL statements and Zod schema
452
448
  */
453
- declare function createTable<const TColumns extends ReadonlyArray<ColumnConfig<any, any>>>(config: TableConfig<TColumns>): {
449
+ export declare function createTable<const TColumns extends readonly ColumnConfig<any, any>[]>(config: TableConfig<TColumns>): {
454
450
  indexes: string[];
455
451
  schema: import("zod").ZodObject<{ [K in TColumns[number]["name"]]: Extract<TColumns[number], {
456
452
  name: K;
457
- }>["schema"] }, import("zod/v4/core").$strip>;
453
+ }>["schema"]; }, import("zod/v4/core").$strip>;
458
454
  table: string;
459
- };
460
- //#endregion
461
- export { ColumnConfig, ForeignKeyAction, ForeignKeyReference, IndexConfig, SQLiteSupportType, SQLiteType, TableConfig, createTable };
455
+ };