@b9g/zen 0.1.2 → 0.1.3

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/CHANGELOG.md CHANGED
@@ -5,6 +5,28 @@ All notable changes to this project will be documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## [0.1.3] - 2025-12-22
9
+
10
+ ### Added
11
+
12
+ - Validation that compound constraints (`indexes`, `unique`, `references` options) have 2+ fields
13
+ - Single-field constraints now throw `TableDefinitionError` with helpful message pointing to field-level API
14
+
15
+ ### Fixed
16
+
17
+ - **TypeScript types now work in published package** - Updated libuild to fix module augmentation and `.d.ts` path resolution
18
+
19
+ ### Changed
20
+
21
+ - New tagline: "Define Zod tables. Write raw SQL. Get typed objects."
22
+
23
+ ### Documentation
24
+
25
+ - Added `.db.inserted()`, `.db.updated()`, `.db.upserted()` documentation with examples
26
+ - Added compound unique constraints example
27
+ - Fixed table naming consistency (all plural)
28
+ - Various README cleanups and improvements
29
+
8
30
  ## [0.1.2] - 2025-12-22
9
31
 
10
32
  ### Added
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # ZenDB
2
2
 
3
- The simple database client. Define tables. Write SQL. Get objects.
3
+ Define Zod tables. Write raw SQL. Get typed objects.
4
4
 
5
5
  [Website](https://zendb.org) · [GitHub](https://github.com/bikeshaving/zen) · [npm](https://www.npmjs.com/package/@b9g/zen)
6
6
 
@@ -47,7 +47,7 @@ import SQLiteDriver from "@b9g/zen/sqlite";
47
47
  const driver = new SQLiteDriver("file:app.db");
48
48
 
49
49
  // 1. Define tables
50
- const Users = table("users", {
50
+ let Users = table("users", {
51
51
  id: z.string().uuid().db.primary().db.auto(),
52
52
  email: z.string().email().db.unique(),
53
53
  name: z.string(),
@@ -73,14 +73,14 @@ db.addEventListener("upgradeneeded", (e) => {
73
73
  }
74
74
  if (e.oldVersion < 2) {
75
75
  // Evolve schema: add avatar column (safe, additive)
76
- const UsersV2 = table("users", {
76
+ Users = table("users", {
77
77
  id: z.string().uuid().db.primary().db.auto(),
78
78
  email: z.string().email().db.unique(),
79
79
  name: z.string(),
80
- avatar: z.string().optional(),
80
+ avatar: z.string().optional(), // new field
81
81
  });
82
- await db.ensureTable(UsersV2); // adds missing columns/indexes
83
- await db.ensureConstraints(UsersV2); // applies new constraints on existing data
82
+ await db.ensureTable(Users); // adds missing columns/indexes
83
+ await db.ensureConstraints(Users); // applies new constraints on existing data
84
84
  }
85
85
  })());
86
86
  });
@@ -115,14 +115,8 @@ await db.update(Users, {name: "Alice Smith"}, user.id);
115
115
  Zen is the missing link between SQL and typed data. By writing tables with Zod schema, you get idempotent migration helpers, typed CRUD, normalized object references, and many features other database clients cannot provide.
116
116
 
117
117
  ### What Zen is not:
118
- - **Zen is not a query builder** — Rather than using a fluent query builder interface (`.where().orderBy().limit()`), Zen uses explicit SQL tagged template functions instead
119
- ```
120
- db.get(Posts)`
121
- WHERE ${Posts.cols.published} = ${true}
122
- ORDER BY ${Posts.cols.publishDate}
123
- DESC LIMIT 20
124
- ```.
125
- - **Zen is not an ORM** — Tables are not classes, they are Zod-powered singletons which provide schema-aware SQL-fragment helpers. These tables can be passed to CRUD helpers to validate writes, generate DDL, and normalize joined data into an object graph.
118
+ - **Zen is not a query builder** — Rather than building SQL with fluent chains `.where().orderBy().limit()`, you write it directly with templates: `` db.all(Posts)`WHERE published = ${true} ORDER BY created_at DESC LIMIT 20` `` Helper functions help you write the tedious parts of SQL without hiding it or limiting your queries.
119
+ - **Zen is not an ORM** — Tables are not classes. They are Zod-powered singletons which provide schema-aware utilities. These tables can be used to validate writes, generate DDL, and deduplicate joined data.
126
120
  - **Zen is not a startup** — Zen is an open-source library, not a venture-backed SaaS. There will never be a managed “ZenDB” instance or a “Zen Studio.” The library is a thin wrapper around Zod and JavaScript SQL drivers, with a focus on runtime abstractions rather than complicated tooling.
127
121
 
128
122
  ### Safety
@@ -133,9 +127,6 @@ Zen is the missing link between SQL and typed data. By writing tables with Zod s
133
127
  - **No destructive helpers** — No `dropColumn()`, `dropTable()`, `renameColumn()`
134
128
  - **No automatic migrations** — Schema changes are explicit in upgrade events
135
129
 
136
- Migrations are **additive and idempotent** by design. Use `ensureColumn()`, `ensureIndex()`, `copyColumn()` for safe schema evolution. Breaking changes require multi-step migrations. Rollbacks are new forward migrations.
137
-
138
-
139
130
  ## Table Definitions
140
131
 
141
132
  ```typescript
@@ -214,10 +205,37 @@ const Users = table("users", {
214
205
 
215
206
  // id and createdAt are optional - auto-generated if not provided
216
207
  const user = await db.insert(Users, {name: "Alice"});
217
- user.id; // "550e8400-e29b-41d4-a716-446655440000"
208
+ user.id; // "550e8400-e29b-41d4-a716-446655440000"
218
209
  user.createdAt; // 2024-01-15T10:30:00.000Z
219
210
  ```
220
211
 
212
+ **Default values with `.db.inserted()`, `.db.updated()`, `.db.upserted()`:**
213
+
214
+ These methods set default values for write operations. They accept JS functions or SQL builtins (`NOW`, `TODAY`, `CURRENT_TIMESTAMP`, `CURRENT_DATE`, `CURRENT_TIME`):
215
+
216
+ ```typescript
217
+ import {z, table, NOW} from "@b9g/zen";
218
+
219
+ const Posts = table("posts", {
220
+ id: z.string().uuid().db.primary().db.auto(),
221
+ title: z.string(),
222
+ // JS function — runs client-side
223
+ slug: z.string().db.inserted(() => generateSlug()),
224
+ // SQL builtin — runs database-side
225
+ createdAt: z.date().db.inserted(NOW),
226
+ updatedAt: z.date().db.upserted(NOW), // set on insert AND update
227
+ viewCount: z.number().db.inserted(() => 0).db.updated(() => 0), // reset on update
228
+ });
229
+ ```
230
+
231
+ | Method | When applied | Field becomes optional for |
232
+ |--------|--------------|---------------------------|
233
+ | `.db.inserted(value)` | INSERT only | insert |
234
+ | `.db.updated(value)` | UPDATE only | update |
235
+ | `.db.upserted(value)` | INSERT and UPDATE | insert and update |
236
+
237
+ **Why not Zod's `.default()`?** Zod's `.default()` applies at *parse time*, not *write time*. This means defaults would be applied when reading data, not when inserting. Zen throws an error if you use `.default()` — use `.db.inserted()` instead.
238
+
221
239
  **Automatic JSON encoding/decoding:**
222
240
 
223
241
  Objects (`z.object()`) and arrays (`z.array()`) are automatically serialized to JSON when stored and parsed back when read:
@@ -238,7 +256,7 @@ const settings = await db.insert(Settings, {
238
256
 
239
257
  // On read: JSON strings are parsed back to objects/arrays
240
258
  settings.config.theme; // "dark" (object, not string)
241
- settings.tags[0]; // "admin" (array, not string)
259
+ settings.tags[0]; // "admin" (array, not string)
242
260
  ```
243
261
 
244
262
  **Custom encoding/decoding:**
@@ -246,7 +264,7 @@ settings.tags[0]; // "admin" (array, not string)
246
264
  Override automatic JSON encoding with custom transformations:
247
265
 
248
266
  ```typescript
249
- const Custom = table("custom", {
267
+ const Articles = table("articles", {
250
268
  id: z.string().db.primary(),
251
269
  // Store array as CSV instead of JSON
252
270
  tags: z.array(z.string())
@@ -255,8 +273,8 @@ const Custom = table("custom", {
255
273
  .db.type("TEXT"), // Required: explicit column type for DDL
256
274
  });
257
275
 
258
- await db.insert(Custom, {id: "c1", tags: ["a", "b", "c"]});
259
- // Stored as: tags='a,b,c' (not '["a","b","c"]')
276
+ await db.insert(Articles, {id: "a1", tags: ["news", "tech", "featured"]});
277
+ // Stored as: tags='news,tech,featured' (not '["news","tech","featured"]')
260
278
  ```
261
279
 
262
280
  **Explicit column types:**
@@ -301,14 +319,16 @@ const posts = await db.all([Posts, Users.active])`
301
319
  `;
302
320
  ```
303
321
 
304
- **Compound indexes** via table options:
322
+ **Compound indexes and unique constraints** via table options:
305
323
  ```typescript
306
324
  const Posts = table("posts", {
307
325
  id: z.string().db.primary(),
308
326
  authorId: z.string(),
327
+ slug: z.string(),
309
328
  createdAt: z.date(),
310
329
  }, {
311
330
  indexes: [["authorId", "createdAt"]],
331
+ unique: [["authorId", "slug"]], // unique together
312
332
  });
313
333
  ```
314
334
 
@@ -355,16 +375,16 @@ type Post = Row<typeof Posts>;
355
375
  // Post includes: id, title, authorId, titleUpper, tags
356
376
 
357
377
  const posts = await db.all([Posts, Users, PostTags, Tags])`
358
- JOIN "users" ON ${Users.on(Posts)}
359
- LEFT JOIN "post_tags" ON ${PostTags.cols.postId} = ${Posts.cols.id}
360
- LEFT JOIN "tags" ON ${Tags.on(PostTags)}
378
+ JOIN ${Users} ON ${Users.on(Posts)}
379
+ LEFT JOIN ${PostTags} ON ${PostTags.cols.postId} = ${Posts.cols.id}
380
+ LEFT JOIN ${Tags} ON ${Tags.on(PostTags)}
361
381
  `;
362
382
 
363
383
  const post = posts[0];
364
384
  post.titleUpper; // "HELLO WORLD" — typed as string
365
- post.tags; // ["javascript", "typescript"] — traverses relationships
366
- Object.keys(post); // ["id", "title", "authorId", "author"] (no derived props)
367
- JSON.stringify(post); // Excludes derived properties (non-enumerable)
385
+ post.tags; // ["javascript", "typescript"] — traverses relationships
386
+ Object.keys(post); // ["id", "title", "authorId", "author"] (no derived props)
387
+ JSON.stringify(post); // Excludes derived properties (non-enumerable)
368
388
  ```
369
389
 
370
390
  Derived properties:
@@ -376,9 +396,9 @@ Derived properties:
376
396
 
377
397
  **Partial selects** with `pick()`:
378
398
  ```typescript
379
- const UserSummary = Users.pick("id", "name");
380
- const posts = await db.all([Posts, UserSummary])`
381
- JOIN "users" ON ${UserSummary.on(Posts)}
399
+ const UserSummaries = Users.pick("id", "name");
400
+ const posts = await db.all([Posts, UserSummaries])`
401
+ JOIN ${UserSummaries} ON ${UserSummaries.on(Posts)}
382
402
  `;
383
403
  // posts[0].author has only id and name
384
404
  ```
@@ -470,6 +490,29 @@ await db.exec`CREATE INDEX idx_posts_author ON ${Posts}(${Posts.cols.authorId})`
470
490
  const count = await db.val<number>`SELECT COUNT(*) FROM ${Posts}`;
471
491
  ```
472
492
 
493
+ ## CRUD Helpers
494
+ ```typescript
495
+ // Insert with Zod validation (uses RETURNING to get actual row)
496
+ const user = await db.insert(Users, {
497
+ email: "alice@example.com",
498
+ name: "Alice",
499
+ });
500
+ // Returns actual row from DB, including auto-generated id and DB-computed defaults
501
+ const userId = user.id;
502
+
503
+ // Update by primary key (uses RETURNING)
504
+ const updated = await db.update(Users, {name: "Bob"}, userId);
505
+
506
+ // Delete by primary key
507
+ await db.delete(Users, userId);
508
+
509
+ // Soft delete (sets deletedAt timestamp, requires softDelete() field)
510
+ await db.softDelete(Users, userId);
511
+ ```
512
+
513
+ **RETURNING support:** `insert()` and `update()` use `RETURNING *` on SQLite and PostgreSQL to return the actual row from the database, including DB-computed defaults and triggers. MySQL falls back to a separate SELECT.
514
+
515
+
473
516
  ## Fragment Helpers
474
517
 
475
518
  Type-safe SQL fragments as methods on Table objects:
@@ -519,29 +562,6 @@ const posts = await db.all(Posts)`WHERE ${Posts.in("id", [])}`;
519
562
  // → WHERE 1 = 0
520
563
  ```
521
564
 
522
- ## CRUD Helpers
523
-
524
- ```typescript
525
- // Insert with Zod validation (uses RETURNING to get actual row)
526
- const user = await db.insert(Users, {
527
- email: "alice@example.com",
528
- name: "Alice",
529
- });
530
- // Returns actual row from DB, including auto-generated id and DB-computed defaults
531
- const userId = user.id;
532
-
533
- // Update by primary key (uses RETURNING)
534
- const updated = await db.update(Users, {name: "Bob"}, userId);
535
-
536
- // Delete by primary key
537
- await db.delete(Users, userId);
538
-
539
- // Soft delete (sets deletedAt timestamp, requires softDelete() field)
540
- await db.softDelete(Users, userId);
541
- ```
542
-
543
- **RETURNING support:** `insert()` and `update()` use `RETURNING *` on SQLite and PostgreSQL to return the actual row from the database, including DB-computed defaults and triggers. MySQL falls back to a separate SELECT.
544
-
545
565
  ## Transactions
546
566
 
547
567
  ```typescript
@@ -818,6 +838,7 @@ const refs = Posts.references(); // [{fieldName: "authorId", table: Users,
818
838
  - Tagged template queries are cached by template object identity (compiled once per call site)
819
839
  - Normalization cost is O(rows) with hash maps per table
820
840
  - Reference resolution is zero-cost after deduplication
841
+ - Zod validation happens on writes, never on reads.
821
842
 
822
843
  ## Driver Interface
823
844
 
@@ -970,41 +991,41 @@ Override with `.db.type("CUSTOM")` when using custom encode/decode.
970
991
  ```typescript
971
992
  import {
972
993
  // Zod (extended with .db namespace)
973
- z, // Re-exported Zod with .db already available
994
+ z, // Re-exported Zod with .db already available
995
+ extendZod, // Extend a separate Zod instance (advanced)
974
996
 
975
997
  // Table and view definition
976
- table, // Create a table definition from Zod schema
977
- view, // Create a read-only view from a table
978
- isTable, // Type guard for Table objects
979
- isView, // Type guard for View objects
980
- extendZod, // Extend a separate Zod instance (advanced)
998
+ table, // Create a table definition from Zod schema
999
+ view, // Create a read-only view from a table
1000
+ isTable, // Type guard for Table objects
1001
+ isView, // Type guard for View objects
981
1002
 
982
1003
  // Database
983
- Database, // Main database class
984
- Transaction, // Transaction context (passed to transaction callbacks)
985
- DatabaseUpgradeEvent, // Event object for "upgradeneeded" handler
1004
+ Database, // Main database class
1005
+ Transaction, // Transaction context (passed to transaction callbacks)
1006
+ DatabaseUpgradeEvent, // Event object for "upgradeneeded" handler
986
1007
 
987
1008
  // SQL builtins (for .db.inserted() / .db.updated())
988
- NOW, // CURRENT_TIMESTAMP alias
989
- TODAY, // CURRENT_DATE alias
990
- CURRENT_TIMESTAMP, // SQL CURRENT_TIMESTAMP
991
- CURRENT_DATE, // SQL CURRENT_DATE
992
- CURRENT_TIME, // SQL CURRENT_TIME
1009
+ NOW, // CURRENT_TIMESTAMP alias
1010
+ TODAY, // CURRENT_DATE alias
1011
+ CURRENT_TIMESTAMP, // SQL CURRENT_TIMESTAMP
1012
+ CURRENT_DATE, // SQL CURRENT_DATE
1013
+ CURRENT_TIME, // SQL CURRENT_TIME
993
1014
 
994
1015
  // Errors
995
- DatabaseError, // Base error class
996
- ValidationError, // Schema validation failed
997
- TableDefinitionError, // Invalid table definition
998
- MigrationError, // Migration failed
999
- MigrationLockError, // Failed to acquire migration lock
1000
- QueryError, // SQL execution failed
1001
- NotFoundError, // Entity not found
1002
- AlreadyExistsError, // Unique constraint violated
1016
+ DatabaseError, // Base error class
1017
+ ValidationError, // Schema validation failed
1018
+ TableDefinitionError, // Invalid table definition
1019
+ MigrationError, // Migration failed
1020
+ MigrationLockError, // Failed to acquire migration lock
1021
+ QueryError, // SQL execution failed
1022
+ NotFoundError, // Entity not found
1023
+ AlreadyExistsError, // Unique constraint violated
1003
1024
  ConstraintViolationError, // Database constraint violated
1004
- ConnectionError, // Connection failed
1005
- TransactionError, // Transaction failed
1006
- isDatabaseError, // Type guard for DatabaseError
1007
- hasErrorCode, // Check error code
1025
+ ConnectionError, // Connection failed
1026
+ TransactionError, // Transaction failed
1027
+ isDatabaseError, // Type guard for DatabaseError
1028
+ hasErrorCode, // Check error code
1008
1029
  } from "@b9g/zen";
1009
1030
  ```
1010
1031
 
@@ -1013,34 +1034,34 @@ import {
1013
1034
  ```typescript
1014
1035
  import type {
1015
1036
  // Table types
1016
- Table, // Table definition object
1017
- PartialTable, // Table created via .pick()
1018
- DerivedTable, // Table with derived fields via .derive()
1019
- TableOptions, // Options for table()
1020
- ReferenceInfo, // Foreign key reference metadata
1021
- CompoundReference, // Compound foreign key reference
1037
+ Table, // Table definition object
1038
+ PartialTable, // Table created via .pick()
1039
+ DerivedTable, // Table with derived fields via .derive()
1040
+ TableOptions, // Options for table()
1041
+ ReferenceInfo, // Foreign key reference metadata
1042
+ CompoundReference, // Compound foreign key reference
1022
1043
 
1023
1044
  // Field types
1024
- FieldMeta, // Field metadata for form generation
1025
- FieldType, // Field type enum
1026
- FieldDBMeta, // Database-specific field metadata
1045
+ FieldMeta, // Field metadata for form generation
1046
+ FieldType, // Field type enum
1047
+ FieldDBMeta, // Database-specific field metadata
1027
1048
 
1028
1049
  // Type inference
1029
- Row, // Infer row type from Table (after read)
1030
- Insert, // Infer insert type from Table (respects defaults/.db.auto())
1031
- Update, // Infer update type from Table (all fields optional)
1050
+ Row, // Infer row type from Table (after read)
1051
+ Insert, // Infer insert type from Table (respects defaults/.db.auto())
1052
+ Update, // Infer update type from Table (all fields optional)
1032
1053
 
1033
1054
  // Fragment types
1034
- SetValues, // Values accepted by Table.set()
1035
- SQLTemplate, // SQL template object (return type of set(), on(), etc.)
1036
- SQLDialect, // "sqlite" | "postgresql" | "mysql"
1055
+ SetValues, // Values accepted by Table.set()
1056
+ SQLTemplate, // SQL template object (return type of set(), on(), etc.)
1057
+ SQLDialect, // "sqlite" | "postgresql" | "mysql"
1037
1058
 
1038
1059
  // Driver types
1039
- Driver, // Driver interface for adapters
1040
- TaggedQuery, // Tagged template query function
1060
+ Driver, // Driver interface for adapters
1061
+ TaggedQuery, // Tagged template query function
1041
1062
 
1042
1063
  // Error types
1043
- DatabaseErrorCode, // Error code string literals
1064
+ DatabaseErrorCode, // Error code string literals
1044
1065
  } from "@b9g/zen";
1045
1066
  ```
1046
1067
 
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@b9g/zen",
3
- "version": "0.1.2",
4
- "description": "The simple database client. Define tables. Write SQL. Get objects.",
3
+ "version": "0.1.3",
4
+ "description": "Define Zod tables. Write raw SQL. Get typed objects.",
5
5
  "keywords": [
6
6
  "database",
7
7
  "sql",
@@ -26,7 +26,7 @@
26
26
  "zod": "^4.0.0"
27
27
  },
28
28
  "devDependencies": {
29
- "@b9g/libuild": "^0.1.20",
29
+ "@b9g/libuild": "^0.1.21",
30
30
  "@eslint/js": "^9.39.2",
31
31
  "@types/better-sqlite3": "^7.6.0",
32
32
  "@types/bun": "^1.3.4",
@@ -2,7 +2,7 @@ import {
2
2
  isSQLBuiltin,
3
3
  isSQLIdentifier,
4
4
  resolveSQLBuiltin
5
- } from "./chunk-BEX6VPES.js";
5
+ } from "./chunk-DKLSJISE.js";
6
6
 
7
7
  // src/impl/sql.ts
8
8
  function quoteIdent(name, dialect) {
@@ -4,7 +4,7 @@ import {
4
4
  getViewMeta,
5
5
  ident,
6
6
  makeTemplate
7
- } from "./chunk-BEX6VPES.js";
7
+ } from "./chunk-DKLSJISE.js";
8
8
 
9
9
  // src/impl/ddl.ts
10
10
  import { z } from "zod";
@@ -793,6 +793,30 @@ function table(name, shape, options = {}) {
793
793
  name
794
794
  );
795
795
  }
796
+ for (const idx of options.indexes ?? []) {
797
+ if (idx.length < 2) {
798
+ throw new TableDefinitionError(
799
+ `Compound index in table "${name}" must have at least 2 fields. Use .db.index() for single-field indexes.`,
800
+ name
801
+ );
802
+ }
803
+ }
804
+ for (const u of options.unique ?? []) {
805
+ if (u.length < 2) {
806
+ throw new TableDefinitionError(
807
+ `Compound unique constraint in table "${name}" must have at least 2 fields. Use .db.unique() for single-field constraints.`,
808
+ name
809
+ );
810
+ }
811
+ }
812
+ for (const ref of options.references ?? []) {
813
+ if (ref.fields.length < 2) {
814
+ throw new TableDefinitionError(
815
+ `Compound foreign key in table "${name}" must have at least 2 fields. Use .db.references() for single-field foreign keys.`,
816
+ name
817
+ );
818
+ }
819
+ }
796
820
  const zodShape = {};
797
821
  const meta = {
798
822
  primary: null,
@@ -2,8 +2,8 @@ import {
2
2
  generateColumnDDL,
3
3
  generateDDL,
4
4
  generateViewDDL
5
- } from "./chunk-ARUUB3H4.js";
6
- import "./chunk-BEX6VPES.js";
5
+ } from "./chunk-2R6FDKLS.js";
6
+ import "./chunk-DKLSJISE.js";
7
7
  export {
8
8
  generateColumnDDL,
9
9
  generateDDL,
package/src/bun.js CHANGED
@@ -3,15 +3,15 @@ import {
3
3
  placeholder,
4
4
  quoteIdent,
5
5
  renderDDL
6
- } from "../chunk-NBXBBEMA.js";
6
+ } from "./_chunks/chunk-2C6KOX4F.js";
7
7
  import {
8
8
  generateDDL,
9
9
  generateViewDDL
10
- } from "../chunk-ARUUB3H4.js";
10
+ } from "./_chunks/chunk-2R6FDKLS.js";
11
11
  import {
12
12
  getTableMeta,
13
13
  resolveSQLBuiltin
14
- } from "../chunk-BEX6VPES.js";
14
+ } from "./_chunks/chunk-DKLSJISE.js";
15
15
 
16
16
  // src/bun.ts
17
17
  import { SQL } from "bun";
@@ -742,7 +742,7 @@ var BunDriver = class {
742
742
  return applied;
743
743
  }
744
744
  async #addColumn(table, fieldName) {
745
- const { generateColumnDDL } = await import("../ddl-OT6HPLQY.js");
745
+ const { generateColumnDDL } = await import("./_chunks/ddl-32B7E53E.js");
746
746
  const zodType = table.schema.shape[fieldName];
747
747
  const fieldMeta = table.meta.fields[fieldName] || {};
748
748
  const colTemplate = generateColumnDDL(
@@ -0,0 +1,52 @@
1
+ /**
2
+ * SQL Builtins - SQL-native values with no JavaScript equivalent.
3
+ *
4
+ * These symbols represent database functions that are evaluated at query time,
5
+ * not in JavaScript. They're used for default values and expressions.
6
+ */
7
+ /**
8
+ * Current timestamp - resolves to CURRENT_TIMESTAMP (standard SQL).
9
+ *
10
+ * @example
11
+ * createdAt: z.date().db.inserted(CURRENT_TIMESTAMP)
12
+ * updatedAt: z.date().db.updated(NOW)
13
+ */
14
+ export declare const CURRENT_TIMESTAMP: unique symbol;
15
+ /**
16
+ * Current date - resolves to CURRENT_DATE (standard SQL).
17
+ *
18
+ * @example
19
+ * dateOnly: z.date().db.inserted(CURRENT_DATE)
20
+ */
21
+ export declare const CURRENT_DATE: unique symbol;
22
+ /**
23
+ * Current time - resolves to CURRENT_TIME (standard SQL).
24
+ *
25
+ * @example
26
+ * timeOnly: z.string().db.inserted(CURRENT_TIME)
27
+ */
28
+ export declare const CURRENT_TIME: unique symbol;
29
+ /**
30
+ * Ergonomic alias for CURRENT_TIMESTAMP.
31
+ *
32
+ * @example
33
+ * createdAt: z.date().db.inserted(NOW)
34
+ */
35
+ export declare const NOW: typeof CURRENT_TIMESTAMP;
36
+ /**
37
+ * Ergonomic alias for CURRENT_DATE.
38
+ *
39
+ * @example
40
+ * dateOnly: z.date().db.inserted(TODAY)
41
+ */
42
+ export declare const TODAY: typeof CURRENT_DATE;
43
+ /** SQL builtins - SQL-native values with no JavaScript representation */
44
+ export type SQLBuiltin = typeof CURRENT_TIMESTAMP | typeof CURRENT_DATE | typeof CURRENT_TIME;
45
+ /**
46
+ * Check if a value is a known SQL builtin.
47
+ */
48
+ export declare function isSQLBuiltin(value: unknown): value is SQLBuiltin;
49
+ /**
50
+ * Resolve a SQL builtin symbol to its SQL representation.
51
+ */
52
+ export declare function resolveSQLBuiltin(sym: symbol): string;