Skip to content

Commit 579d17f

Browse files
brainkimclaude
andcommitted
docs: improve README based on review feedback
- Fix stale db.now()/db.json() reference (now NOW/TODAY/CURRENT_*) - Add connection pooling note to Driver Interface section - Add relationship-traversing derive example (tags from postTags) - Document compound foreign keys with example 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <[email protected]>
1 parent 96a7434 commit 579d17f

File tree

1 file changed

+38
-12
lines changed

1 file changed

+38
-12
lines changed

README.md

Lines changed: 38 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -313,6 +313,28 @@ const Posts = table("posts", {
313313
});
314314
```
315315

316+
**Compound foreign keys** for composite primary keys:
317+
```typescript
318+
const OrderProducts = table("order_products", {
319+
orderId: z.string().uuid(),
320+
productId: z.string().uuid(),
321+
// ... compound primary key
322+
});
323+
324+
const OrderItems = table("order_items", {
325+
id: z.string().uuid().db.primary(),
326+
orderId: z.string().uuid(),
327+
productId: z.string().uuid(),
328+
quantity: z.number(),
329+
}, {
330+
references: [{
331+
fields: ["orderId", "productId"],
332+
table: OrderProducts,
333+
as: "orderProduct",
334+
}],
335+
});
336+
```
337+
316338
**Derived properties** for client-side transformations:
317339
```typescript
318340
const Posts = table("posts", {
@@ -325,20 +347,23 @@ const Posts = table("posts", {
325347
derive: {
326348
// Pure functions only (no I/O, no side effects)
327349
titleUpper: (post) => post.title.toUpperCase(),
328-
wordCount: (post) => post.title.split(" ").length,
350+
// Traverse relationships (requires JOIN in query)
351+
tags: (post) => post.postTags?.map(pt => pt.tag?.name) ?? [],
329352
}
330353
});
331354

332355
type Post = Row<typeof Posts>;
333-
// Post includes: id, title, authorId, titleUpper, wordCount
356+
// Post includes: id, title, authorId, titleUpper, tags
334357

335-
const posts = await db.all([Posts, Users])`
358+
const posts = await db.all([Posts, Users, PostTags, Tags])`
336359
JOIN "users" ON ${Users.on(Posts)}
360+
LEFT JOIN "post_tags" ON ${PostTags.cols.postId} = ${Posts.cols.id}
361+
LEFT JOIN "tags" ON ${Tags.on(PostTags)}
337362
`;
338363

339364
const post = posts[0];
340365
post.titleUpper; // "HELLO WORLD" — typed as string
341-
post.wordCount; // 2 — typed as number
366+
post.tags; // ["javascript", "typescript"] — traverses relationships
342367
Object.keys(post); // ["id", "title", "authorId", "author"] (no derived props)
343368
JSON.stringify(post); // Excludes derived properties (non-enumerable)
344369
```
@@ -347,7 +372,7 @@ Derived properties:
347372
- Are lazy getters (computed on access, not stored)
348373
- Are non-enumerable (hidden from `Object.keys()` and `JSON.stringify()`)
349374
- Must be pure functions (no I/O, no database queries)
350-
- Only transform data already in the entity
375+
- Can traverse resolved relationships from the same query
351376
- Are fully typed via `Row<T>` inference
352377

353378
**Partial selects** with `pick()`:
@@ -776,6 +801,8 @@ interface Driver {
776801

777802
**Migration locking**: If the driver provides `withMigrationLock()`, migrations run atomically (PostgreSQL uses advisory locks, MySQL uses `GET_LOCK`, SQLite uses exclusive transactions).
778803

804+
**Connection pooling**: Handled by the underlying driver. `postgres.js` and `mysql2` pool automatically; `better-sqlite3` uses a single connection (SQLite is single-writer anyway).
805+
779806
## Error Handling
780807

781808
All errors extend `DatabaseError` with typed error codes:
@@ -905,13 +932,12 @@ import {
905932
Transaction, // Transaction context (passed to transaction callbacks)
906933
DatabaseUpgradeEvent, // Event object for "upgradeneeded" handler
907934

908-
// DB expressions
909-
db, // Runtime DB expressions (db.now(), db.json(), etc.)
910-
isDBExpression, // Type guard for DBExpression objects
911-
912-
// Custom field helpers
913-
setDBMeta, // Set database metadata on a Zod schema
914-
getDBMeta, // Get database metadata from a Zod schema
935+
// SQL builtins (for .db.inserted() / .db.updated())
936+
NOW, // CURRENT_TIMESTAMP alias
937+
TODAY, // CURRENT_DATE alias
938+
CURRENT_TIMESTAMP, // SQL CURRENT_TIMESTAMP
939+
CURRENT_DATE, // SQL CURRENT_DATE
940+
CURRENT_TIME, // SQL CURRENT_TIME
915941

916942
// Errors
917943
DatabaseError, // Base error class

0 commit comments

Comments
 (0)