@gobing-ai/ts-db 0.2.8 → 0.2.9

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 (48) hide show
  1. package/README.md +52 -1
  2. package/dist/drizzle-builders.d.ts +96 -0
  3. package/dist/drizzle-builders.d.ts.map +1 -0
  4. package/dist/drizzle-builders.js +17 -0
  5. package/dist/embedded-migrations.d.ts.map +1 -1
  6. package/dist/embedded-migrations.js +10 -0
  7. package/dist/entity-dao.d.ts.map +1 -1
  8. package/dist/inbox-message-dao.d.ts +19 -0
  9. package/dist/inbox-message-dao.d.ts.map +1 -0
  10. package/dist/inbox-message-dao.js +75 -0
  11. package/dist/inbox.d.ts +3 -0
  12. package/dist/inbox.d.ts.map +1 -0
  13. package/dist/inbox.js +2 -0
  14. package/dist/index.d.ts +3 -1
  15. package/dist/index.d.ts.map +1 -1
  16. package/dist/index.js +2 -0
  17. package/dist/migrate.d.ts +12 -5
  18. package/dist/migrate.d.ts.map +1 -1
  19. package/dist/migrate.js +19 -25
  20. package/dist/queue-job-dao.d.ts.map +1 -1
  21. package/dist/schema/ddl.d.ts.map +1 -1
  22. package/dist/schema/ddl.js +4 -36
  23. package/dist/schema/drizzle-internals.d.ts +25 -0
  24. package/dist/schema/drizzle-internals.d.ts.map +1 -0
  25. package/dist/schema/drizzle-internals.js +47 -0
  26. package/dist/schema/inbox-messages.d.ts +212 -0
  27. package/dist/schema/inbox-messages.d.ts.map +1 -0
  28. package/dist/schema/inbox-messages.js +17 -0
  29. package/dist/schema/index.d.ts +1 -0
  30. package/dist/schema/index.d.ts.map +1 -1
  31. package/dist/schema/index.js +1 -0
  32. package/dist/schema/runtime.d.ts +1 -0
  33. package/dist/schema/runtime.d.ts.map +1 -1
  34. package/dist/schema/runtime.js +1 -0
  35. package/package.json +7 -2
  36. package/src/drizzle-builders.ts +98 -0
  37. package/src/embedded-migrations.ts +10 -0
  38. package/src/entity-dao.ts +2 -21
  39. package/src/inbox-message-dao.ts +91 -0
  40. package/src/inbox.ts +2 -0
  41. package/src/index.ts +3 -1
  42. package/src/migrate.ts +34 -22
  43. package/src/queue-job-dao.ts +14 -59
  44. package/src/schema/ddl.ts +4 -40
  45. package/src/schema/drizzle-internals.ts +55 -0
  46. package/src/schema/inbox-messages.ts +22 -0
  47. package/src/schema/index.ts +1 -0
  48. package/src/schema/runtime.ts +1 -0
package/README.md CHANGED
@@ -22,6 +22,7 @@ Application code imports only `@gobing-ai/ts-db` — never `drizzle-orm`. drizzl
22
22
  | `defineTable` | Single source of truth — one table → drizzle table + derived zod insert/select schemas (optional peers) |
23
23
  | `Predicate` / `ListSpec` / `OrderTerm` | The drizzle-free query vocabulary |
24
24
  | `QueueJobDao` | Job queue persistence — `enqueue`, `claimReady`, `markCompleted`, `failExpiredJobs` |
25
+ | `InboxMessageDao` | Durable inter-agent message persistence (`@gobing-ai/ts-db/inbox`) |
25
26
  | `applyMigrations` | Drizzle migration runner (file-based + embedded fallback) |
26
27
  | `schema` helpers | `standardColumns`, `appendOnlyColumns`, soft-delete columns |
27
28
  | `SpanContext` | Re-exported from `@gobing-ai/ts-runtime` for telemetry |
@@ -102,6 +103,15 @@ classDiagram
102
103
  +getStats() QueueStats
103
104
  }
104
105
 
106
+ class InboxMessageDao {
107
+ +enqueue(fromId, toId, body, inReplyTo?) string
108
+ +drainPending(toId) InboxMessage[]
109
+ +markDelivered(msgId) void
110
+ +markFailed(msgId, error) void
111
+ +inbox(toId, limit?, offset?) InboxMessage[]
112
+ +countPending(toId) number
113
+ }
114
+
105
115
  class ColumnHelpers {
106
116
  +standardColumns
107
117
  +standardColumnsWithSoftDelete
@@ -112,6 +122,10 @@ classDiagram
112
122
  +queueJobs
113
123
  }
114
124
 
125
+ class InboxMessagesTable {
126
+ +inboxMessages
127
+ }
128
+
115
129
  class MigrationRunner {
116
130
  +applyMigrations(adapter, opts?) void
117
131
  }
@@ -124,7 +138,9 @@ classDiagram
124
138
  DbAdapter <|.. D1Adapter : implements
125
139
  BaseDao <|-- EntityDao : extends
126
140
  EntityDao <|-- QueueJobDao : extends
141
+ EntityDao <|-- InboxMessageDao : extends
127
142
  QueueJobDao --> QueueJobsTable : "uses"
143
+ InboxMessageDao --> InboxMessagesTable : "uses"
128
144
  MigrationRunner --> EmbeddedMigrations : "uses"
129
145
  MigrationRunner --> BunSqliteAdapter : "requires"
130
146
  ```
@@ -233,6 +249,39 @@ const stats = await queue.getStats();
233
249
  // → { pending: 5, processing: 2, completed: 100, failed: 3 }
234
250
  ```
235
251
 
252
+ ### InboxMessageDao — durable inter-agent messages
253
+
254
+ `InboxMessageDao` persists directed messages for team-mode or multi-agent workflows. It lives on the
255
+ `@gobing-ai/ts-db/inbox` subpath so consumers can depend on the inbox surface without pulling schema
256
+ helpers.
257
+
258
+ ```ts
259
+ import { InboxMessageDao } from '@gobing-ai/ts-db/inbox';
260
+
261
+ const inbox = new InboxMessageDao(adapter);
262
+
263
+ // Operator sends a task to an agent.
264
+ const msgId = await inbox.enqueue(null, 'coder', 'Please inspect packages/db');
265
+
266
+ // Agent process startup/live-injection path atomically drains queued work.
267
+ const pending = await inbox.drainPending('coder');
268
+ for (const msg of pending) {
269
+ try {
270
+ await injectIntoAgentStdin(`[task from=${msg.fromId ?? 'operator'} id=${msg.id}] ${msg.body}`);
271
+ await inbox.markDelivered(msg.id);
272
+ } catch (error) {
273
+ await inbox.markFailed(msg.id, String(error));
274
+ }
275
+ }
276
+
277
+ const history = await inbox.inbox('coder', 20);
278
+ const queued = await inbox.countPending('coder');
279
+ ```
280
+
281
+ The `inbox_messages` table is additive and included in embedded migrations. It stores `from_id`,
282
+ `to_id`, `body`, `status`, optional reply linkage, delivery timestamp, injection attempts, and the
283
+ last injection error. The indexed access path is `(to_id, status)` for efficient pending drains.
284
+
236
285
  ### Migrations
237
286
 
238
287
  ```ts
@@ -252,7 +301,7 @@ await applyMigrations(adapter);
252
301
 
253
302
  ```ts
254
303
  import { sqliteTable, text } from 'drizzle-orm/sqlite-core';
255
- import { standardColumns, standardColumnsWithSoftDelete, queueJobs } from '@gobing-ai/ts-db';
304
+ import { standardColumns, standardColumnsWithSoftDelete, queueJobs, inboxMessages } from '@gobing-ai/ts-db';
256
305
 
257
306
  // Standard columns (createdAt, updatedAt)
258
307
  const docs = sqliteTable('docs', {
@@ -269,6 +318,8 @@ const projects = sqliteTable('projects', {
269
318
  });
270
319
 
271
320
  // queue_jobs table is pre-built for use with QueueJobDao
321
+
322
+ // inbox_messages table is pre-built for use with InboxMessageDao
272
323
  ```
273
324
 
274
325
  ## Usage
@@ -0,0 +1,96 @@
1
+ /**
2
+ * Shared structural types for drizzle's fluent query builders.
3
+ *
4
+ * `InternalDb` is typed as the bare drizzle union (ADR-005 keeps drizzle internal),
5
+ * so its fluent builders (`insert().values().returning()`, `update().set().where()`,
6
+ * `select(proj).from()...`) are not surfaced as call-shapes. Each DAO previously
7
+ * re-declared these narrowings inline — three files independently describing the
8
+ * same `update → set → where → returning` chain. Centralising them here means the
9
+ * cast shape lives in one place: when drizzle's builder surface shifts, this file
10
+ * changes, not every DAO.
11
+ *
12
+ * These are deliberately minimal — each type narrows only the chain a DAO actually
13
+ * invokes. Table-specific projections (`select({ status, count })`) stay local to
14
+ * their DAO; only the recurring chain skeletons live here.
15
+ *
16
+ * @internal
17
+ */
18
+ /** Terminal `.returning()` returning the written rows. */
19
+ export interface ReturningRows {
20
+ returning: () => Promise<unknown[]>;
21
+ }
22
+ /** `insert(table).values(record)` → returning, with optional upsert. */
23
+ export interface InsertBuilder {
24
+ values: (record: unknown) => ReturningRows & {
25
+ onConflictDoUpdate: (cfg: {
26
+ target: unknown;
27
+ set: unknown;
28
+ }) => ReturningRows;
29
+ };
30
+ }
31
+ /** `update(table).set(data).where(cond)` → `.returning()` rows. */
32
+ export interface UpdateReturningDb {
33
+ update: (table: unknown) => {
34
+ set: (data: unknown) => {
35
+ where: (cond: unknown) => ReturningRows;
36
+ };
37
+ };
38
+ }
39
+ /** `update(table).set(data).where(cond)` → void (no rows). */
40
+ export interface UpdateVoidDb {
41
+ update: (table: unknown) => {
42
+ set: (data: unknown) => {
43
+ where: (cond: unknown) => Promise<unknown>;
44
+ };
45
+ };
46
+ }
47
+ /** `update(table).set(data).where(cond)` → `{ changes }` (affected-row count). */
48
+ export interface UpdateChangesDb {
49
+ update: (table: unknown) => {
50
+ set: (data: unknown) => {
51
+ where: (cond: unknown) => Promise<{
52
+ changes: number;
53
+ }>;
54
+ };
55
+ };
56
+ }
57
+ /** `update(table).set(data).where(cond)` → arbitrary single condition (no projection). */
58
+ export interface SimpleUpdateDb {
59
+ update: (table: unknown) => {
60
+ set: (data: unknown) => {
61
+ where: (cond: unknown) => ReturningRows;
62
+ };
63
+ };
64
+ }
65
+ /** `select(projection).from(table)` exposing `.where(...)` and `.groupBy(...)` terminals. */
66
+ export interface SelectProjectionDb {
67
+ select: (projection: unknown) => {
68
+ from: (table: unknown) => {
69
+ where: (cond: unknown) => Promise<unknown[]>;
70
+ groupBy: (group: unknown) => Promise<unknown[]>;
71
+ };
72
+ };
73
+ }
74
+ /** `select().from(table).where(cond).orderBy(o).limit(n)` — the ready-rows read chain. */
75
+ export interface SelectOrderedLimitDb {
76
+ select: () => {
77
+ from: (table: unknown) => {
78
+ where: (cond: unknown) => {
79
+ orderBy: (order: unknown) => {
80
+ limit: (limit: number) => Promise<unknown[]>;
81
+ };
82
+ };
83
+ };
84
+ };
85
+ }
86
+ /** `select(count).from(table)` that is awaitable and chainable with `.where(...)`. */
87
+ export type CountQuery = Promise<unknown[]> & {
88
+ where: (condition: unknown) => Promise<unknown[]>;
89
+ };
90
+ /** `select({ value: count() }).from(table)` → awaitable count, optionally filtered. */
91
+ export interface CountSelectDb {
92
+ select: (projection: unknown) => {
93
+ from: (table: unknown) => CountQuery;
94
+ };
95
+ }
96
+ //# sourceMappingURL=drizzle-builders.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"drizzle-builders.d.ts","sourceRoot":"","sources":["../src/drizzle-builders.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Shared structural types for drizzle's fluent query builders.
3
+ *
4
+ * `InternalDb` is typed as the bare drizzle union (ADR-005 keeps drizzle internal),
5
+ * so its fluent builders (`insert().values().returning()`, `update().set().where()`,
6
+ * `select(proj).from()...`) are not surfaced as call-shapes. Each DAO previously
7
+ * re-declared these narrowings inline — three files independently describing the
8
+ * same `update → set → where → returning` chain. Centralising them here means the
9
+ * cast shape lives in one place: when drizzle's builder surface shifts, this file
10
+ * changes, not every DAO.
11
+ *
12
+ * These are deliberately minimal — each type narrows only the chain a DAO actually
13
+ * invokes. Table-specific projections (`select({ status, count })`) stay local to
14
+ * their DAO; only the recurring chain skeletons live here.
15
+ *
16
+ * @internal
17
+ */
@@ -1 +1 @@
1
- {"version":3,"file":"embedded-migrations.d.ts","sourceRoot":"","sources":["../src/embedded-migrations.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,MAAM,WAAW,iBAAiB;IAC9B,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;CAChB;AAED,eAAO,MAAM,kBAAkB,EAAE,iBAAiB,EAgBjD,CAAC"}
1
+ {"version":3,"file":"embedded-migrations.d.ts","sourceRoot":"","sources":["../src/embedded-migrations.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,MAAM,WAAW,iBAAiB;IAC9B,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;CAChB;AAED,eAAO,MAAM,kBAAkB,EAAE,iBAAiB,EA0BjD,CAAC"}
@@ -22,4 +22,14 @@ export const embeddedMigrations = [
22
22
  sql: 'ALTER TABLE `queue_jobs` ADD `expires_at` integer;',
23
23
  hash: '7380f8c162352a61b15205af5a87e0e7313a499203dae98fe62151a1dc7fec0e',
24
24
  },
25
+ {
26
+ tag: '0003_inbox_messages',
27
+ sql: "CREATE TABLE `inbox_messages` (\n\t`id` text PRIMARY KEY NOT NULL,\n\t`from_id` text,\n\t`to_id` text NOT NULL,\n\t`body` text NOT NULL,\n\t`status` text DEFAULT 'queued' NOT NULL,\n\t`in_reply_to` text,\n\t`created_at` integer NOT NULL,\n\t`updated_at` integer NOT NULL,\n\t`delivered_at` integer,\n\t`inject_attempts` integer DEFAULT 0 NOT NULL,\n\t`inject_error` text\n);",
28
+ hash: 'c4ba569172d1be276c42b5c164c668404e6229dcf48b41d7fb2bc93e8d29d11b',
29
+ },
30
+ {
31
+ tag: '0004_inbox_messages_to_status_idx',
32
+ sql: 'CREATE INDEX `idx_inbox_messages_to_status` ON `inbox_messages` (`to_id`,`status`);',
33
+ hash: '3c00f1bce4f569e442f3142df31ff478d6c9b3d460824d46575f50a324bfae61',
34
+ },
25
35
  ];
@@ -1 +1 @@
1
- {"version":3,"file":"entity-dao.d.ts","sourceRoot":"","sources":["../src/entity-dao.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"entity-dao.d.ts","sourceRoot":"","sources":["../src/entity-dao.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,19 @@
1
+ import type { DbAdapter } from './adapter';
2
+ import { EntityDao } from './entity-dao';
3
+ import { inboxMessages } from './schema/inbox-messages';
4
+ /** Row type inferred from the inbox_messages Drizzle schema. */
5
+ export type InboxMessage = typeof inboxMessages.$inferSelect;
6
+ /**
7
+ * DAO for durable inter-agent inbox messages.
8
+ */
9
+ export declare class InboxMessageDao extends EntityDao<typeof inboxMessages, typeof inboxMessages.id> {
10
+ constructor(adapter: DbAdapter);
11
+ enqueue(fromId: string | null, toId: string, body: string, inReplyTo?: string): Promise<string>;
12
+ drainPending(toId: string): Promise<InboxMessage[]>;
13
+ markDelivered(msgId: string): Promise<void>;
14
+ markFailed(msgId: string, error: string): Promise<void>;
15
+ inbox(toId: string, limit?: number, offset?: number): Promise<InboxMessage[]>;
16
+ countPending(toId: string): Promise<number>;
17
+ getById(id: string): Promise<InboxMessage | undefined>;
18
+ }
19
+ //# sourceMappingURL=inbox-message-dao.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"inbox-message-dao.d.ts","sourceRoot":"","sources":["../src/inbox-message-dao.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAE3C,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AACzC,OAAO,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAC;AAExD,gEAAgE;AAChE,MAAM,MAAM,YAAY,GAAG,OAAO,aAAa,CAAC,YAAY,CAAC;AAE7D;;GAEG;AACH,qBAAa,eAAgB,SAAQ,SAAS,CAAC,OAAO,aAAa,EAAE,OAAO,aAAa,CAAC,EAAE,CAAC;gBAC7E,OAAO,EAAE,SAAS;IAIxB,OAAO,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAc/F,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC;IAwBnD,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAO3C,UAAU,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAOvD,KAAK,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC;IAS7E,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAS3C,OAAO,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,GAAG,SAAS,CAAC;CAG/D"}
@@ -0,0 +1,75 @@
1
+ import { sql } from 'drizzle-orm';
2
+ import { EntityDao } from './entity-dao.js';
3
+ import { inboxMessages } from './schema/inbox-messages.js';
4
+ /**
5
+ * DAO for durable inter-agent inbox messages.
6
+ */
7
+ export class InboxMessageDao extends EntityDao {
8
+ constructor(adapter) {
9
+ super(adapter, inboxMessages, [inboxMessages.id], 'inbox_messages');
10
+ }
11
+ async enqueue(fromId, toId, body, inReplyTo) {
12
+ const id = crypto.randomUUID();
13
+ await this.create({
14
+ id,
15
+ fromId,
16
+ toId,
17
+ body,
18
+ status: 'queued',
19
+ injectAttempts: 0,
20
+ ...(inReplyTo !== undefined ? { inReplyTo } : {}),
21
+ });
22
+ return id;
23
+ }
24
+ async drainPending(toId) {
25
+ const now = this.now();
26
+ const rows = await this.db
27
+ .update(inboxMessages)
28
+ .set({
29
+ status: 'injected',
30
+ injectAttempts: sql `${inboxMessages.injectAttempts} + 1`,
31
+ updatedAt: now,
32
+ })
33
+ .where(sql `${inboxMessages.id} IN (
34
+ SELECT id
35
+ FROM ${inboxMessages}
36
+ WHERE to_id = ${toId}
37
+ AND status = 'queued'
38
+ ORDER BY created_at
39
+ )
40
+ AND ${inboxMessages.status} = 'queued'`)
41
+ .returning();
42
+ return rows;
43
+ }
44
+ async markDelivered(msgId) {
45
+ await this.update(msgId, {
46
+ status: 'delivered',
47
+ deliveredAt: this.now(),
48
+ });
49
+ }
50
+ async markFailed(msgId, error) {
51
+ await this.update(msgId, {
52
+ status: 'failed',
53
+ injectError: error,
54
+ });
55
+ }
56
+ async inbox(toId, limit, offset) {
57
+ return this.list({
58
+ where: { col: inboxMessages.toId, op: 'eq', value: toId },
59
+ orderBy: [{ col: inboxMessages.createdAt, dir: 'desc' }],
60
+ ...(limit !== undefined ? { limit } : {}),
61
+ ...(offset !== undefined ? { offset } : {}),
62
+ });
63
+ }
64
+ async countPending(toId) {
65
+ return this.count({
66
+ and: [
67
+ { col: inboxMessages.toId, op: 'eq', value: toId },
68
+ { col: inboxMessages.status, op: 'eq', value: 'queued' },
69
+ ],
70
+ });
71
+ }
72
+ async getById(id) {
73
+ return this.findBy(inboxMessages.id, id);
74
+ }
75
+ }
@@ -0,0 +1,3 @@
1
+ export { type InboxMessage, InboxMessageDao } from './inbox-message-dao';
2
+ export { inboxMessages } from './schema/inbox-messages';
3
+ //# sourceMappingURL=inbox.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"inbox.d.ts","sourceRoot":"","sources":["../src/inbox.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,YAAY,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AACzE,OAAO,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAC"}
package/dist/inbox.js ADDED
@@ -0,0 +1,2 @@
1
+ export { InboxMessageDao } from './inbox-message-dao.js';
2
+ export { inboxMessages } from './schema/inbox-messages.js';
package/dist/index.d.ts CHANGED
@@ -3,10 +3,12 @@ export { D1Adapter } from './adapters/d1';
3
3
  export { BaseDao, type TxHandle } from './base-dao';
4
4
  export { type EmbeddedMigration, embeddedMigrations } from './embedded-migrations';
5
5
  export { type CursorListSpec, type DaoValidator, EntityDao, type EntityDaoOptions, type EntityListSpec, type EntityTable, type PKColumn, type PKValue, type SoftDeletableTable, } from './entity-dao';
6
- export { applyMigrations, type MigrationOptions } from './migrate';
6
+ export { type InboxMessage, InboxMessageDao } from './inbox-message-dao';
7
+ export { applyMigrations, type MigrationLogger, type MigrationOptions } from './migrate';
7
8
  export { type ColRef, type ComparisonOp, compileOrderBy, compilePredicate, type ListSpec, type OrderTerm, type Predicate, } from './query-spec';
8
9
  export { QueueJobDao, type QueueJobRecord, type QueueStats } from './queue-job-dao';
9
10
  export { appendOnlyColumns, buildAppendOnlyColumns, buildStandardColumns, buildStandardColumnsWithSoftDelete, nowTimestamp, standardColumns, standardColumnsWithSoftDelete, } from './schema/common';
11
+ export { inboxMessages } from './schema/inbox-messages';
10
12
  export { queueJobs } from './schema/queue-jobs';
11
13
  export type { SpanContext } from './span-context';
12
14
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,KAAK,SAAS,EAAE,KAAK,eAAe,EAAE,KAAK,UAAU,EAAE,MAAM,WAAW,CAAC;AACnG,OAAO,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAC1C,OAAO,EAAE,OAAO,EAAE,KAAK,QAAQ,EAAE,MAAM,YAAY,CAAC;AAEpD,OAAO,EAAE,KAAK,iBAAiB,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AACnF,OAAO,EACH,KAAK,cAAc,EACnB,KAAK,YAAY,EACjB,SAAS,EACT,KAAK,gBAAgB,EACrB,KAAK,cAAc,EACnB,KAAK,WAAW,EAChB,KAAK,QAAQ,EACb,KAAK,OAAO,EACZ,KAAK,kBAAkB,GAC1B,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,eAAe,EAAE,KAAK,gBAAgB,EAAE,MAAM,WAAW,CAAC;AACnE,OAAO,EACH,KAAK,MAAM,EACX,KAAK,YAAY,EACjB,cAAc,EACd,gBAAgB,EAChB,KAAK,QAAQ,EACb,KAAK,SAAS,EACd,KAAK,SAAS,GACjB,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,WAAW,EAAE,KAAK,cAAc,EAAE,KAAK,UAAU,EAAE,MAAM,iBAAiB,CAAC;AACpF,OAAO,EACH,iBAAiB,EACjB,sBAAsB,EACtB,oBAAoB,EACpB,kCAAkC,EAClC,YAAY,EACZ,eAAe,EACf,6BAA6B,GAChC,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAChD,YAAY,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,KAAK,SAAS,EAAE,KAAK,eAAe,EAAE,KAAK,UAAU,EAAE,MAAM,WAAW,CAAC;AACnG,OAAO,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAC1C,OAAO,EAAE,OAAO,EAAE,KAAK,QAAQ,EAAE,MAAM,YAAY,CAAC;AAEpD,OAAO,EAAE,KAAK,iBAAiB,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AACnF,OAAO,EACH,KAAK,cAAc,EACnB,KAAK,YAAY,EACjB,SAAS,EACT,KAAK,gBAAgB,EACrB,KAAK,cAAc,EACnB,KAAK,WAAW,EAChB,KAAK,QAAQ,EACb,KAAK,OAAO,EACZ,KAAK,kBAAkB,GAC1B,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,KAAK,YAAY,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AACzE,OAAO,EAAE,eAAe,EAAE,KAAK,eAAe,EAAE,KAAK,gBAAgB,EAAE,MAAM,WAAW,CAAC;AACzF,OAAO,EACH,KAAK,MAAM,EACX,KAAK,YAAY,EACjB,cAAc,EACd,gBAAgB,EAChB,KAAK,QAAQ,EACb,KAAK,SAAS,EACd,KAAK,SAAS,GACjB,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,WAAW,EAAE,KAAK,cAAc,EAAE,KAAK,UAAU,EAAE,MAAM,iBAAiB,CAAC;AACpF,OAAO,EACH,iBAAiB,EACjB,sBAAsB,EACtB,oBAAoB,EACpB,kCAAkC,EAClC,YAAY,EACZ,eAAe,EACf,6BAA6B,GAChC,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAC;AACxD,OAAO,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAChD,YAAY,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC"}
package/dist/index.js CHANGED
@@ -3,8 +3,10 @@ export { D1Adapter } from './adapters/d1.js';
3
3
  export { BaseDao } from './base-dao.js';
4
4
  export { embeddedMigrations } from './embedded-migrations.js';
5
5
  export { EntityDao, } from './entity-dao.js';
6
+ export { InboxMessageDao } from './inbox-message-dao.js';
6
7
  export { applyMigrations } from './migrate.js';
7
8
  export { compileOrderBy, compilePredicate, } from './query-spec.js';
8
9
  export { QueueJobDao } from './queue-job-dao.js';
9
10
  export { appendOnlyColumns, buildAppendOnlyColumns, buildStandardColumns, buildStandardColumnsWithSoftDelete, nowTimestamp, standardColumns, standardColumnsWithSoftDelete, } from './schema/common.js';
11
+ export { inboxMessages } from './schema/inbox-messages.js';
10
12
  export { queueJobs } from './schema/queue-jobs.js';
package/dist/migrate.d.ts CHANGED
@@ -1,12 +1,17 @@
1
1
  import type { FileSystem } from '@gobing-ai/ts-runtime';
2
2
  import type { DbAdapter } from './adapter';
3
3
  /**
4
- * Find project root by walking up looking for bun.lock.
5
- * @deprecated Use `FileSystem.getProjectRoot()` instead.
6
- * @internal only used for backward compatibility.
4
+ * Minimal structural logger for migration progress.
5
+ *
6
+ * Structurally compatible with `@gobing-ai/ts-infra`'s `Logger` so consumers can
7
+ * pass theirs directly — ts-db never imports ts-infra (keeps the package
8
+ * boundary). Defaults to `console` when absent.
7
9
  */
8
- /** @internal */
9
- export declare function findProjectRoot(_startDir: string): string;
10
+ export interface MigrationLogger {
11
+ info(msg: string): void;
12
+ warn(msg: string): void;
13
+ error(msg: string): void;
14
+ }
10
15
  /**
11
16
  * Options for configuring migration behaviour (folder path, table name).
12
17
  */
@@ -17,6 +22,8 @@ export interface MigrationOptions {
17
22
  migrationsTable?: string;
18
23
  /** File system abstraction for path resolution. */
19
24
  fs?: FileSystem;
25
+ /** Logger for migration progress. Default: `console`. */
26
+ logger?: MigrationLogger;
20
27
  }
21
28
  /**
22
29
  * Apply pending migrations using drizzle-orm's built-in migrator.
@@ -1 +1 @@
1
- {"version":3,"file":"migrate.d.ts","sourceRoot":"","sources":["../src/migrate.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AAExD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAG3C;;;;GAIG;AACH,gBAAgB;AAChB,wBAAgB,eAAe,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAEzD;AAED;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC7B,oEAAoE;IACpE,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,6EAA6E;IAC7E,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,mDAAmD;IACnD,EAAE,CAAC,EAAE,UAAU,CAAC;CACnB;AA0ED;;;;;;;;;;;;;;;GAeG;AACH,wBAAsB,eAAe,CAAC,OAAO,EAAE,SAAS,EAAE,OAAO,CAAC,EAAE,gBAAgB,GAAG,OAAO,CAAC,IAAI,CAAC,CA8CnG"}
1
+ {"version":3,"file":"migrate.d.ts","sourceRoot":"","sources":["../src/migrate.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AAExD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAG3C;;;;;;GAMG;AACH,MAAM,WAAW,eAAe;IAC5B,IAAI,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,IAAI,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,KAAK,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;CAC5B;AAED;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC7B,oEAAoE;IACpE,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,6EAA6E;IAC7E,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,mDAAmD;IACnD,EAAE,CAAC,EAAE,UAAU,CAAC;IAChB,yDAAyD;IACzD,MAAM,CAAC,EAAE,eAAe,CAAC;CAC5B;AA8ED;;;;;;;;;;;;;;;GAeG;AACH,wBAAsB,eAAe,CAAC,OAAO,EAAE,SAAS,EAAE,OAAO,CAAC,EAAE,gBAAgB,GAAG,OAAO,CAAC,IAAI,CAAC,CAiDnG"}
package/dist/migrate.js CHANGED
@@ -1,14 +1,5 @@
1
1
  import { resolve } from 'node:path';
2
2
  import { embeddedMigrations } from './embedded-migrations.js';
3
- /**
4
- * Find project root by walking up looking for bun.lock.
5
- * @deprecated Use `FileSystem.getProjectRoot()` instead.
6
- * @internal — only used for backward compatibility.
7
- */
8
- /** @internal */
9
- export function findProjectRoot(_startDir) {
10
- return process.cwd();
11
- }
12
3
  /**
13
4
  * Ensure the migration tracking table exists with proper SQLite types.
14
5
  *
@@ -35,7 +26,7 @@ function validateMigrationTableName(table) {
35
26
  * Checks the journal table and applies only migrations that haven't run yet.
36
27
  * Each migration is executed with adapter.exec() for file-based or adapter.run() for journal tracking.
37
28
  */
38
- async function applyEmbeddedMigrations(adapter, journalTable) {
29
+ async function applyEmbeddedMigrations(adapter, journalTable, logger) {
39
30
  // Validate journal table name — this is an internal constant, never user input.
40
31
  if (!/^__[a-z_]+$/.test(journalTable)) {
41
32
  throw new Error(`Invalid migration journal table name: ${journalTable}`);
@@ -55,7 +46,7 @@ async function applyEmbeddedMigrations(adapter, journalTable) {
55
46
  for (const migration of embeddedMigrations) {
56
47
  if (appliedHashes.has(migration.hash))
57
48
  continue;
58
- console.info(`Applying embedded migration: ${migration.tag}`);
49
+ logger.info(`Applying embedded migration: ${migration.tag}`);
59
50
  // Split on semicolons and execute each non-empty statement
60
51
  const statements = migration.sql
61
52
  .split(';')
@@ -69,7 +60,7 @@ async function applyEmbeddedMigrations(adapter, journalTable) {
69
60
  applied++;
70
61
  }
71
62
  if (applied > 0) {
72
- console.info(`Applied ${applied} embedded migration(s)`);
63
+ logger.info(`Applied ${applied} embedded migration(s)`);
73
64
  }
74
65
  }
75
66
  /**
@@ -89,43 +80,46 @@ async function applyEmbeddedMigrations(adapter, journalTable) {
89
80
  * @param options - Optional migration folder and table name overrides.
90
81
  */
91
82
  export async function applyMigrations(adapter, options) {
83
+ const logger = options?.logger ?? console;
92
84
  const { BunSqliteAdapter } = await import('./adapters/bun-sqlite.js');
93
85
  if (!(adapter instanceof BunSqliteAdapter)) {
94
- console.warn('Skipping in-app migrations: only supported for bun-sqlite adapter');
86
+ logger.warn('Skipping in-app migrations: only supported for bun-sqlite adapter');
95
87
  return;
96
88
  }
97
89
  const table = validateMigrationTableName(options?.migrationsTable ?? '__drizzle_migrations');
98
90
  await ensureJournalTable(adapter, table);
99
- const folder = options?.migrationsFolder ?? resolve(findProjectRoot(process.cwd()), 'drizzle');
100
- // File-based migrations: attempt if drizzle/ folder is accessible.
101
- // Use FileSystem.exists when available, otherwise try and fall back to embedded.
91
+ const folder = options?.migrationsFolder ?? resolve(process.cwd(), 'drizzle');
92
+ // File-based migrations: attempt only if the drizzle/ folder is present.
93
+ // With an injected fs we get a definitive answer (await the Promise — a bare
94
+ // `fs.exists(...)` is always truthy and silently disables the check); without
95
+ // one we attempt optimistically and fall back on the migrator's own error.
102
96
  const fs = options?.fs;
103
- const tryFileBased = fs?.exists(folder) ?? true; // optimistic when no fs
97
+ const tryFileBased = fs ? await fs.exists(folder) : true;
104
98
  if (tryFileBased) {
105
99
  try {
106
100
  const { migrate: drizzleMigrate } = await import('drizzle-orm/bun-sqlite/migrator');
107
- console.info(`Applying database migrations from ${folder}`);
101
+ logger.info(`Applying database migrations from ${folder}`);
108
102
  await drizzleMigrate(adapter.getDrizzleDb(), {
109
103
  migrationsFolder: folder,
110
104
  ...(options?.migrationsTable !== undefined ? { migrationsTable: options.migrationsTable } : {}),
111
105
  });
112
- console.info('Database migrations complete');
106
+ logger.info('Database migrations complete');
113
107
  return;
114
108
  }
115
109
  catch (error) {
116
- // If folder doesn't exist, fall through to embedded migrations.
117
- // Any other error should be thrown.
110
+ // A missing/empty migrations folder is expected in compiled binaries
111
+ // fall through to embedded. Any other failure is real; rethrow it.
118
112
  const message = error instanceof Error ? error.message : String(error);
119
113
  if (message.includes('journal') || message.includes('ENOENT') || message.includes('meta')) {
120
- console.info(`File-based migrations unavailable, using embedded: ${message}`);
114
+ logger.info(`File-based migrations unavailable, using embedded: ${message}`);
121
115
  }
122
116
  else {
123
- console.error(`[MIGRATE] drizzleMigrate failed: ${message}`);
117
+ logger.error(`[MIGRATE] drizzleMigrate failed: ${message}`);
124
118
  throw error;
125
119
  }
126
120
  }
127
121
  }
128
122
  // Fallback: embedded migrations (for compiled binaries)
129
- console.info('No drizzle/ folder found — applying embedded migrations');
130
- await applyEmbeddedMigrations(adapter, table);
123
+ logger.info('No drizzle/ folder found — applying embedded migrations');
124
+ await applyEmbeddedMigrations(adapter, table, logger);
131
125
  }
@@ -1 +1 @@
1
- {"version":3,"file":"queue-job-dao.d.ts","sourceRoot":"","sources":["../src/queue-job-dao.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAC3C,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AACzC,OAAO,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAsDhD;;GAEG;AACH,MAAM,WAAW,UAAU;IACvB,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;CAClB;AAED;;GAEG;AACH,MAAM,MAAM,cAAc,GAAG,OAAO,SAAS,CAAC,YAAY,CAAC;AAE3D;;;;;GAKG;AACH,qBAAa,WAAY,SAAQ,SAAS,CAAC,OAAO,SAAS,EAAE,OAAO,SAAS,CAAC,EAAE,CAAC;gBACjE,OAAO,EAAE,SAAS;IAI9B;;OAEG;IACG,OAAO,CACT,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,OAAO,EAChB,OAAO,CAAC,EAAE;QAAE,UAAU,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,GAClE,OAAO,CAAC,MAAM,CAAC;IAkBlB;;OAEG;IACG,YAAY,CACd,IAAI,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,OAAO,CAAA;KAAE,GAAG;QAAE,UAAU,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,GAC1G,OAAO,CAAC,MAAM,EAAE,CAAC;IA+BpB;;OAEG;IACG,OAAO,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,GAAG,SAAS,CAAC;IAI9D;;OAEG;IACG,QAAQ,IAAI,OAAO,CAAC,UAAU,CAAC;IAoBrC;;OAEG;IACG,aAAa,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IASpD;;OAEG;IACG,WAAW,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,EAAE,CAAC;IAe/D;;;;;OAKG;IACG,UAAU,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,EAAE,CAAC;IAyB9D;;OAEG;IACG,cAAc,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAWlD;;OAEG;IACG,aAAa,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAO9C;;OAEG;IACG,UAAU,CAAC,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAS5E;;OAEG;IACG,YAAY,CAAC,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAU1G;;OAEG;IACG,cAAc,CAAC,iBAAiB,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAahE;;;;;OAKG;IACG,eAAe,IAAI,OAAO,CAAC,MAAM,CAAC;CAkB3C"}
1
+ {"version":3,"file":"queue-job-dao.d.ts","sourceRoot":"","sources":["../src/queue-job-dao.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAQ3C,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AACzC,OAAO,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAEhD;;GAEG;AACH,MAAM,WAAW,UAAU;IACvB,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;CAClB;AAED;;GAEG;AACH,MAAM,MAAM,cAAc,GAAG,OAAO,SAAS,CAAC,YAAY,CAAC;AAE3D;;;;;GAKG;AACH,qBAAa,WAAY,SAAQ,SAAS,CAAC,OAAO,SAAS,EAAE,OAAO,SAAS,CAAC,EAAE,CAAC;gBACjE,OAAO,EAAE,SAAS;IAI9B;;OAEG;IACG,OAAO,CACT,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,OAAO,EAChB,OAAO,CAAC,EAAE;QAAE,UAAU,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,GAClE,OAAO,CAAC,MAAM,CAAC;IAkBlB;;OAEG;IACG,YAAY,CACd,IAAI,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,OAAO,CAAA;KAAE,GAAG;QAAE,UAAU,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,GAC1G,OAAO,CAAC,MAAM,EAAE,CAAC;IA+BpB;;OAEG;IACG,OAAO,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,GAAG,SAAS,CAAC;IAI9D;;OAEG;IACG,QAAQ,IAAI,OAAO,CAAC,UAAU,CAAC;IAoBrC;;OAEG;IACG,aAAa,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IASpD;;OAEG;IACG,WAAW,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,EAAE,CAAC;IAe/D;;;;;OAKG;IACG,UAAU,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,EAAE,CAAC;IAyB9D;;OAEG;IACG,cAAc,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAWlD;;OAEG;IACG,aAAa,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAO9C;;OAEG;IACG,UAAU,CAAC,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAS5E;;OAEG;IACG,YAAY,CAAC,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAU1G;;OAEG;IACG,cAAc,CAAC,iBAAiB,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAahE;;;;;OAKG;IACG,eAAe,IAAI,OAAO,CAAC,MAAM,CAAC;CAkB3C"}
@@ -1 +1 @@
1
- {"version":3,"file":"ddl.d.ts","sourceRoot":"","sources":["../../src/schema/ddl.ts"],"names":[],"mappings":"AAAA,OAAO,EAAkB,KAAK,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAuE3E;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,WAAW,GAAG,MAAM,CAsFjE"}
1
+ {"version":3,"file":"ddl.d.ts","sourceRoot":"","sources":["../../src/schema/ddl.ts"],"names":[],"mappings":"AAAA,OAAO,EAAkB,KAAK,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAmC3E;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,WAAW,GAAG,MAAM,CAsFjE"}
@@ -1,29 +1,11 @@
1
1
  import { getTableConfig } from 'drizzle-orm/sqlite-core';
2
+ import { getDrizzleTableName, sqlExpressionToText } from './drizzle-internals.js';
2
3
  /**
3
4
  * Quote an identifier for use in SQL (double-quoted for SQLite compatibility).
4
5
  */
5
6
  function quoteIdent(name) {
6
7
  return `"${name.replace(/"/g, '""')}"`;
7
8
  }
8
- /**
9
- * Extract the SQL string from a drizzle-orm SQL expression by walking its
10
- * internal `queryChunks` — StringChunk values plus Param placeholders.
11
- */
12
- function sqlToString(chunks) {
13
- return chunks
14
- .map((chunk) => {
15
- // StringChunk — the literal SQL fragment
16
- if ('value' in chunk && typeof chunk.value === 'string') {
17
- return chunk.value;
18
- }
19
- // Param — use the input value if available
20
- if ('input' in chunk && chunk.input !== undefined) {
21
- return String(chunk.input);
22
- }
23
- return String(chunk.value ?? '?');
24
- })
25
- .join('');
26
- }
27
9
  /**
28
10
  * Map a column default value to its SQL literal representation.
29
11
  *
@@ -45,22 +27,8 @@ function defaultToSql(value) {
45
27
  if (typeof value === 'boolean') {
46
28
  return value ? '1' : '0';
47
29
  }
48
- // drizzle-orm SQL expression (has queryChunks)
49
- if (typeof value === 'object' && value !== null && 'queryChunks' in value) {
50
- const chunks = value.queryChunks;
51
- if (chunks) {
52
- return sqlToString(chunks);
53
- }
54
- }
55
- return String(value);
56
- }
57
- /**
58
- * Resolve a drizzle table object to its string name.
59
- */
60
- function getTableName(table) {
61
- // Drizzle tables store name at Symbol.for('drizzle:Name')
62
- const nameSym = Symbol.for('drizzle:Name');
63
- return String(table[nameSym]);
30
+ // drizzle-orm SQL expression (sql`...`) — rendered via the internals quarantine.
31
+ return sqlExpressionToText(value) ?? String(value);
64
32
  }
65
33
  /**
66
34
  * Generate a `CREATE TABLE IF NOT EXISTS` DDL statement from a Drizzle SQLite table.
@@ -141,7 +109,7 @@ export function generateCreateTableSql(table) {
141
109
  const ref = fk.reference();
142
110
  const localCols = ref.columns.map((c) => quoteIdent(c.name)).join(', ');
143
111
  const foreignCols = ref.foreignColumns.map((c) => quoteIdent(c.name)).join(', ');
144
- const foreignTableName = getTableName(ref.foreignTable);
112
+ const foreignTableName = getDrizzleTableName(ref.foreignTable);
145
113
  let constraint = `FOREIGN KEY (${localCols}) REFERENCES ${quoteIdent(foreignTableName)} (${foreignCols})`;
146
114
  if (fk.onDelete) {
147
115
  constraint += ` ON DELETE ${fk.onDelete}`;