@storyshelf/db-sqlite 0.10.0-next-23b15fb → 0.10.0-next-864c1ce

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.
@@ -37,7 +37,7 @@ function createBetterSqlite3Database(options) {
37
37
  const adapter = createDrizzleAdapter(db, {
38
38
  metadata: {
39
39
  name: "better-sqlite3",
40
- version: "0.10.0-next-23b15fb",
40
+ version: "0.10.0-next-864c1ce",
41
41
  description: "better-sqlite3 database adapter (native + Drizzle)",
42
42
  kind: "better-sqlite3",
43
43
  category: "database"
@@ -37,7 +37,7 @@ function createBunSqliteDatabase(options) {
37
37
  const adapter = createDrizzleAdapter(db, {
38
38
  metadata: {
39
39
  name: "Bun SQLite",
40
- version: "0.10.0-next-23b15fb",
40
+ version: "0.10.0-next-864c1ce",
41
41
  description: "Bun SQLite database adapter (bun:sqlite + Drizzle)",
42
42
  kind: "bun-sqlite",
43
43
  category: "database"
package/dist/d1.mjs CHANGED
@@ -22,7 +22,7 @@ function createD1Database(options) {
22
22
  return createDrizzleAdapter(db, {
23
23
  metadata: {
24
24
  name: "Cloudflare D1",
25
- version: "0.10.0-next-23b15fb",
25
+ version: "0.10.0-next-864c1ce",
26
26
  description: "Cloudflare D1 database adapter (D1 binding + Drizzle)",
27
27
  kind: "d1",
28
28
  category: "database",
@@ -41,30 +41,34 @@ function withManualTransactions(adapter, exec) {
41
41
  }
42
42
  };
43
43
  }
44
+ /** Setup, teardown (once) and health for the adapter; teardown closes the driver a single time. */
45
+ function buildLifecycle(options) {
46
+ let closed = false;
47
+ return {
48
+ setup: async () => {
49
+ await options.migrate();
50
+ },
51
+ teardown: async () => {
52
+ if (closed) return;
53
+ closed = true;
54
+ await options.close();
55
+ },
56
+ health: async () => {
57
+ if (closed) return {
58
+ ok: false,
59
+ detail: "database closed"
60
+ };
61
+ if (options.ping) await options.ping();
62
+ return { ok: true };
63
+ }
64
+ };
65
+ }
44
66
  function createDrizzleAdapter(db, options) {
45
67
  const drizzle = db;
46
- let closed = false;
47
68
  return {
48
69
  metadata: options.metadata,
49
70
  tables: options.tables,
50
- lifecycle: {
51
- setup: async () => {
52
- await options.migrate();
53
- },
54
- teardown: async () => {
55
- if (closed) return;
56
- closed = true;
57
- await options.close();
58
- },
59
- health: async () => {
60
- if (closed) return {
61
- ok: false,
62
- detail: "database closed"
63
- };
64
- if (options.ping) await options.ping();
65
- return { ok: true };
66
- }
67
- },
71
+ lifecycle: buildLifecycle(options),
68
72
  insert: async (table, values) => await insertOne(drizzle, table, values),
69
73
  update: async (table, id, values) => await updateOne(drizzle, table, id, values),
70
74
  updateWhere: async (table, id, values, where) => await updateWhereOne(drizzle, table, id, values, where),
@@ -94,12 +98,16 @@ async function removeOne(drizzle, table, id) {
94
98
  await drizzle.delete(table).where(eq(idOf(table), id)).run();
95
99
  }
96
100
  async function listMany(drizzle, table, opts = {}) {
97
- let query = drizzle.select().from(table);
98
- if (opts.where) query = query.where(opts.where);
99
- if (opts.orderBy) query = query.orderBy(opts.orderBy);
100
- if (opts.limit !== void 0) query = query.limit(opts.limit);
101
- if (opts.offset !== void 0) query = query.offset(opts.offset);
102
- return await query.all();
101
+ return await applyListOptions(drizzle.select().from(table), opts).all();
102
+ }
103
+ /** The `where`, `orderBy`, `limit` and `offset` the caller asked for, in that order. */
104
+ function applyListOptions(query, opts) {
105
+ let next = query;
106
+ if (opts.where) next = next.where(opts.where);
107
+ if (opts.orderBy) next = next.orderBy(opts.orderBy);
108
+ if (opts.limit !== void 0) next = next.limit(opts.limit);
109
+ if (opts.offset !== void 0) next = next.offset(opts.offset);
110
+ return next;
103
111
  }
104
112
  /** CRUD subset bound to a transaction handle. */
105
113
  function buildTxStore(drizzle) {
@@ -1 +1 @@
1
- {"version":3,"file":"drizzle-factory.mjs","names":[],"sources":["../src/drizzle-factory.ts"],"sourcesContent":["/**\n * SQLite Drizzle adapter factory.\n *\n * Builds a {@link DatabaseAdapter} over any SQLite-compatible Drizzle dialect.\n */\n\nimport type {\n DatabaseAdapter,\n DrizzleAdapterOptions,\n ListOptions,\n TxStore,\n} from \"@storyshelf/core/adapter/database\";\nimport type { SQL, Table } from \"drizzle-orm\";\nimport { and, eq, getTableColumns } from \"drizzle-orm\";\nimport type { AnySQLiteTable, SQLiteColumn } from \"drizzle-orm/sqlite-core\";\n\n/**\n * Wrap an adapter with manual BEGIN/COMMIT transactions for synchronous\n * SQLite drivers (better-sqlite3, `bun:sqlite`), whose `transaction()`\n * rejects async callbacks. Statements run on the adapter's own connection,\n * so the open transaction covers them; rollback runs on throw.\n *\n * @param adapter - Adapter built by {@link createDrizzleAdapter}.\n * @param exec - Synchronous statement runner on the same connection.\n * @returns The adapter with `transact` replaced.\n */\nexport function withManualTransactions(\n adapter: DatabaseAdapter,\n exec: (sql: string) => void,\n): DatabaseAdapter {\n return {\n ...adapter,\n transact: async <R>(fn: (tx: TxStore) => Promise<R>): Promise<R> => {\n const tx: TxStore = {\n insert: async (table, values) => await adapter.insert(table, values),\n update: async (table, id, values) => await adapter.update(table, id, values),\n get: async (table, id) => await adapter.get(table, id),\n remove: async (table, id) => {\n await adapter.remove(table, id);\n },\n list: async (table, opts) => await adapter.list(table, opts),\n count: async (table, where) => await adapter.count(table, where),\n };\n exec(\"BEGIN\");\n try {\n const result = await fn(tx);\n exec(\"COMMIT\");\n return result;\n } catch (error) {\n try {\n exec(\"ROLLBACK\");\n } catch {\n // already rolled back (e.g. constraint abort) — report the cause\n }\n throw error;\n }\n },\n };\n}\nexport function createDrizzleAdapter(db: unknown, options: DrizzleAdapterOptions): DatabaseAdapter {\n const drizzle = db as DrizzleLike;\n let closed = false;\n return {\n metadata: options.metadata,\n tables: options.tables,\n lifecycle: {\n setup: async () => {\n await options.migrate();\n },\n teardown: async () => {\n if (closed) {\n return;\n }\n closed = true;\n await options.close();\n },\n health: async () => {\n if (closed) {\n return { ok: false, detail: \"database closed\" };\n }\n if (options.ping) {\n await options.ping();\n }\n return { ok: true };\n },\n },\n insert: async <T extends AnySQLiteTable>(\n table: T,\n values: T[\"$inferInsert\"],\n ): Promise<T[\"$inferSelect\"]> => await insertOne(drizzle, table, values),\n update: async <T extends AnySQLiteTable>(\n table: T,\n id: string,\n // Homomorphic equivalent of Partial<T[\"$inferInsert\"]>; written out so\n // the type stays deferred instead of resolving to `{}` under generics.\n values: { [K in keyof T[\"$inferInsert\"]]?: T[\"$inferInsert\"][K] },\n ): Promise<T[\"$inferSelect\"]> => await updateOne(drizzle, table, id, values),\n updateWhere: async <T extends AnySQLiteTable>(\n table: T,\n id: string,\n values: { [K in keyof T[\"$inferInsert\"]]?: T[\"$inferInsert\"][K] },\n where: SQL,\n ): Promise<T[\"$inferSelect\"] | null> => await updateWhereOne(drizzle, table, id, values, where),\n get: async <T extends AnySQLiteTable>(\n table: T,\n id: string,\n ): Promise<T[\"$inferSelect\"] | null> => await getOne(drizzle, table, id),\n remove: async (table: AnySQLiteTable, id: string): Promise<void> => {\n await removeOne(drizzle, table, id);\n },\n list: async <T extends AnySQLiteTable>(\n table: T,\n opts: ListOptions = {},\n ): Promise<T[\"$inferSelect\"][]> => await listMany(drizzle, table, opts),\n count: async (table: AnySQLiteTable, where?: SQL): Promise<number> =>\n await drizzle.$count(table, where),\n all: async <T>(query: SQL): Promise<T[]> => await drizzle.all(query),\n transact: async <R>(fn: (tx: TxStore) => Promise<R>): Promise<R> =>\n await drizzle.transaction(async (tx) => await fn(buildTxStore(tx as DrizzleLike))),\n };\n}\n\nasync function updateWhereOne<T extends AnySQLiteTable>(\n drizzle: DrizzleLike,\n table: T,\n id: string,\n values: { [K in keyof T[\"$inferInsert\"]]?: T[\"$inferInsert\"][K] },\n where: SQL,\n): Promise<T[\"$inferSelect\"] | null> {\n const updated = (await drizzle\n .update(table)\n .set(values)\n .where(and(eq(idOf(table), id), where) ?? where)\n .returning()\n .get()) as T[\"$inferSelect\"] | undefined;\n return updated ?? (await getOne(drizzle, table, id));\n}\n\nasync function insertOne<T extends Table>(\n drizzle: DrizzleLike,\n table: T,\n values: T[\"$inferInsert\"],\n): Promise<T[\"$inferSelect\"]> {\n return (await drizzle\n .insert(table as AnySQLiteTable)\n .values(values)\n .returning()\n .get()) as T[\"$inferSelect\"];\n}\n\nasync function updateOne<T extends Table>(\n drizzle: DrizzleLike,\n table: T,\n id: string,\n values: Partial<T[\"$inferInsert\"]>,\n): Promise<T[\"$inferSelect\"]> {\n return (await drizzle\n .update(table as AnySQLiteTable)\n .set(values)\n .where(eq(idOf(table as AnySQLiteTable), id))\n .returning()\n .get()) as T[\"$inferSelect\"];\n}\n\nasync function getOne<T extends Table>(\n drizzle: DrizzleLike,\n table: T,\n id: string,\n): Promise<T[\"$inferSelect\"] | null> {\n return (\n ((await drizzle\n .select()\n .from(table as AnySQLiteTable)\n .where(eq(idOf(table as AnySQLiteTable), id))\n .limit(1)\n .get()) as T[\"$inferSelect\"] | undefined) ?? null\n );\n}\n\nasync function removeOne(drizzle: DrizzleLike, table: Table, id: string): Promise<void> {\n await drizzle\n .delete(table as AnySQLiteTable)\n .where(eq(idOf(table as AnySQLiteTable), id))\n .run();\n}\n\nasync function listMany<T extends Table>(\n drizzle: DrizzleLike,\n table: T,\n opts: ListOptions = {},\n): Promise<T[\"$inferSelect\"][]> {\n let query = drizzle.select().from(table as AnySQLiteTable) as DrizzleSelectChain;\n if (opts.where) {\n query = query.where(opts.where);\n }\n if (opts.orderBy) {\n query = query.orderBy(opts.orderBy);\n }\n if (opts.limit !== undefined) {\n query = query.limit(opts.limit);\n }\n if (opts.offset !== undefined) {\n query = query.offset(opts.offset);\n }\n const rows: unknown = await query.all();\n return rows as T[\"$inferSelect\"][];\n}\n\n/** CRUD subset bound to a transaction handle. */\nfunction buildTxStore(drizzle: DrizzleLike): TxStore {\n return {\n insert: async (table, values) => await insertOne(drizzle, table, values as never),\n update: async (table, id, values) => await updateOne(drizzle, table, id, values as never),\n get: async (table, id) => await getOne(drizzle, table, id),\n remove: async (table, id) => {\n await removeOne(drizzle, table, id);\n },\n list: async (table, opts) => await listMany(drizzle, table, opts),\n count: async (table, where) => await drizzle.$count(table as AnySQLiteTable, where),\n };\n}\n\n/** A value or a promise of one (sync node:sqlite vs async libSQL drivers). */\ntype MaybePromise<T> = T | Promise<T>;\n\n/** Chainable select surface shared by the sync and async Drizzle dialects. */\ninterface DrizzleSelectChain {\n where(where: SQL): DrizzleSelectChain;\n orderBy(order: SQL): DrizzleSelectChain;\n limit(n: number): DrizzleSelectChain;\n offset(n: number): DrizzleSelectChain;\n get(): MaybePromise<unknown>;\n all(): MaybePromise<unknown[]>;\n}\n\n/**\n * Minimal Drizzle surface consumed by {@link createDrizzleAdapter}. Drivers\n * pass their dialect instance as `unknown`; the cast lives here, once, so\n * driver packages stay fully typed. Covered by the adapter contract tests.\n */\ninterface DrizzleLike {\n insert(table: AnySQLiteTable): {\n values(values: unknown): { returning(): { get(): MaybePromise<unknown> } };\n };\n update(table: AnySQLiteTable): {\n set(values: unknown): { where(where: SQL): { returning(): { get(): MaybePromise<unknown> } } };\n };\n select(): { from(table: AnySQLiteTable): DrizzleSelectChain };\n delete(table: AnySQLiteTable): { where(where: SQL): { run(): MaybePromise<unknown> } };\n $count(table: AnySQLiteTable, where?: SQL): MaybePromise<number>;\n all<T>(query: SQL): MaybePromise<T[]>;\n transaction<R>(fn: (tx: unknown) => Promise<R>): Promise<R>;\n}\n\nfunction idOf(table: AnySQLiteTable): SQLiteColumn {\n const id = getTableColumns(table)[\"id\"];\n if (!id) {\n throw new Error(\"Table has no id column\");\n }\n return id;\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"drizzle-factory.mjs","names":[],"sources":["../src/drizzle-factory.ts"],"sourcesContent":["/**\n * SQLite Drizzle adapter factory.\n *\n * Builds a {@link DatabaseAdapter} over any SQLite-compatible Drizzle dialect.\n */\n\nimport type {\n DatabaseAdapter,\n DrizzleAdapterOptions,\n ListOptions,\n TxStore,\n} from \"@storyshelf/core/adapter/database\";\nimport type { SQL, Table } from \"drizzle-orm\";\nimport { and, eq, getTableColumns } from \"drizzle-orm\";\nimport type { AnySQLiteTable, SQLiteColumn } from \"drizzle-orm/sqlite-core\";\n\n/**\n * Wrap an adapter with manual BEGIN/COMMIT transactions for synchronous\n * SQLite drivers (better-sqlite3, `bun:sqlite`), whose `transaction()`\n * rejects async callbacks. Statements run on the adapter's own connection,\n * so the open transaction covers them; rollback runs on throw.\n *\n * @param adapter - Adapter built by {@link createDrizzleAdapter}.\n * @param exec - Synchronous statement runner on the same connection.\n * @returns The adapter with `transact` replaced.\n */\nexport function withManualTransactions(\n adapter: DatabaseAdapter,\n exec: (sql: string) => void,\n): DatabaseAdapter {\n return {\n ...adapter,\n transact: async <R>(fn: (tx: TxStore) => Promise<R>): Promise<R> => {\n const tx: TxStore = {\n insert: async (table, values) => await adapter.insert(table, values),\n update: async (table, id, values) => await adapter.update(table, id, values),\n get: async (table, id) => await adapter.get(table, id),\n remove: async (table, id) => {\n await adapter.remove(table, id);\n },\n list: async (table, opts) => await adapter.list(table, opts),\n count: async (table, where) => await adapter.count(table, where),\n };\n exec(\"BEGIN\");\n try {\n const result = await fn(tx);\n exec(\"COMMIT\");\n return result;\n } catch (error) {\n try {\n exec(\"ROLLBACK\");\n } catch {\n // already rolled back (e.g. constraint abort) — report the cause\n }\n throw error;\n }\n },\n };\n}\n/** Setup, teardown (once) and health for the adapter; teardown closes the driver a single time. */\nfunction buildLifecycle(options: DrizzleAdapterOptions): NonNullable<DatabaseAdapter[\"lifecycle\"]> {\n let closed = false;\n return {\n setup: async () => {\n await options.migrate();\n },\n teardown: async () => {\n if (closed) {\n return;\n }\n closed = true;\n await options.close();\n },\n health: async () => {\n if (closed) {\n return { ok: false, detail: \"database closed\" };\n }\n if (options.ping) {\n await options.ping();\n }\n return { ok: true };\n },\n };\n}\n\nexport function createDrizzleAdapter(db: unknown, options: DrizzleAdapterOptions): DatabaseAdapter {\n const drizzle = db as DrizzleLike;\n return {\n metadata: options.metadata,\n tables: options.tables,\n lifecycle: buildLifecycle(options),\n insert: async <T extends AnySQLiteTable>(\n table: T,\n values: T[\"$inferInsert\"],\n ): Promise<T[\"$inferSelect\"]> => await insertOne(drizzle, table, values),\n update: async <T extends AnySQLiteTable>(\n table: T,\n id: string,\n // Homomorphic equivalent of Partial<T[\"$inferInsert\"]>; written out so\n // the type stays deferred instead of resolving to `{}` under generics.\n values: { [K in keyof T[\"$inferInsert\"]]?: T[\"$inferInsert\"][K] },\n ): Promise<T[\"$inferSelect\"]> => await updateOne(drizzle, table, id, values),\n updateWhere: async <T extends AnySQLiteTable>(\n table: T,\n id: string,\n values: { [K in keyof T[\"$inferInsert\"]]?: T[\"$inferInsert\"][K] },\n where: SQL,\n ): Promise<T[\"$inferSelect\"] | null> => await updateWhereOne(drizzle, table, id, values, where),\n get: async <T extends AnySQLiteTable>(\n table: T,\n id: string,\n ): Promise<T[\"$inferSelect\"] | null> => await getOne(drizzle, table, id),\n remove: async (table: AnySQLiteTable, id: string): Promise<void> => {\n await removeOne(drizzle, table, id);\n },\n list: async <T extends AnySQLiteTable>(\n table: T,\n opts: ListOptions = {},\n ): Promise<T[\"$inferSelect\"][]> => await listMany(drizzle, table, opts),\n count: async (table: AnySQLiteTable, where?: SQL): Promise<number> =>\n await drizzle.$count(table, where),\n all: async <T>(query: SQL): Promise<T[]> => await drizzle.all(query),\n transact: async <R>(fn: (tx: TxStore) => Promise<R>): Promise<R> =>\n await drizzle.transaction(async (tx) => await fn(buildTxStore(tx as DrizzleLike))),\n };\n}\n\nasync function updateWhereOne<T extends AnySQLiteTable>(\n drizzle: DrizzleLike,\n table: T,\n id: string,\n values: { [K in keyof T[\"$inferInsert\"]]?: T[\"$inferInsert\"][K] },\n where: SQL,\n): Promise<T[\"$inferSelect\"] | null> {\n const updated = (await drizzle\n .update(table)\n .set(values)\n .where(and(eq(idOf(table), id), where) ?? where)\n .returning()\n .get()) as T[\"$inferSelect\"] | undefined;\n return updated ?? (await getOne(drizzle, table, id));\n}\n\nasync function insertOne<T extends Table>(\n drizzle: DrizzleLike,\n table: T,\n values: T[\"$inferInsert\"],\n): Promise<T[\"$inferSelect\"]> {\n return (await drizzle.insert(table).values(values).returning().get()) as T[\"$inferSelect\"];\n}\n\nasync function updateOne<T extends Table>(\n drizzle: DrizzleLike,\n table: T,\n id: string,\n values: Partial<T[\"$inferInsert\"]>,\n): Promise<T[\"$inferSelect\"]> {\n return (await drizzle\n .update(table)\n .set(values)\n .where(eq(idOf(table as AnySQLiteTable), id))\n .returning()\n .get()) as T[\"$inferSelect\"];\n}\n\nasync function getOne<T extends Table>(\n drizzle: DrizzleLike,\n table: T,\n id: string,\n): Promise<T[\"$inferSelect\"] | null> {\n return (\n ((await drizzle\n .select()\n .from(table)\n .where(eq(idOf(table as AnySQLiteTable), id))\n .limit(1)\n .get()) as T[\"$inferSelect\"] | undefined) ?? null\n );\n}\n\nasync function removeOne(drizzle: DrizzleLike, table: Table, id: string): Promise<void> {\n await drizzle\n .delete(table)\n .where(eq(idOf(table as AnySQLiteTable), id))\n .run();\n}\n\nasync function listMany<T extends Table>(\n drizzle: DrizzleLike,\n table: T,\n opts: ListOptions = {},\n): Promise<T[\"$inferSelect\"][]> {\n const query = applyListOptions(drizzle.select().from(table), opts);\n const rows: unknown = await query.all();\n return rows as T[\"$inferSelect\"][];\n}\n\n/** The `where`, `orderBy`, `limit` and `offset` the caller asked for, in that order. */\nfunction applyListOptions(query: DrizzleSelectChain, opts: ListOptions): DrizzleSelectChain {\n let next = query;\n if (opts.where) {\n next = next.where(opts.where);\n }\n if (opts.orderBy) {\n next = next.orderBy(opts.orderBy);\n }\n if (opts.limit !== undefined) {\n next = next.limit(opts.limit);\n }\n if (opts.offset !== undefined) {\n next = next.offset(opts.offset);\n }\n return next;\n}\n\n/** CRUD subset bound to a transaction handle. */\nfunction buildTxStore(drizzle: DrizzleLike): TxStore {\n return {\n insert: async (table, values) => await insertOne(drizzle, table, values as never),\n update: async (table, id, values) => await updateOne(drizzle, table, id, values as never),\n get: async (table, id) => await getOne(drizzle, table, id),\n remove: async (table, id) => {\n await removeOne(drizzle, table, id);\n },\n list: async (table, opts) => await listMany(drizzle, table, opts),\n count: async (table, where) => await drizzle.$count(table as AnySQLiteTable, where),\n };\n}\n\n/** A value or a promise of one (sync node:sqlite vs async libSQL drivers). */\ntype MaybePromise<T> = T | Promise<T>;\n\n/** Chainable select surface shared by the sync and async Drizzle dialects. */\ninterface DrizzleSelectChain {\n where(where: SQL): DrizzleSelectChain;\n orderBy(order: SQL): DrizzleSelectChain;\n limit(n: number): DrizzleSelectChain;\n offset(n: number): DrizzleSelectChain;\n get(): MaybePromise<unknown>;\n all(): MaybePromise<unknown[]>;\n}\n\n/**\n * Minimal Drizzle surface consumed by {@link createDrizzleAdapter}. Drivers\n * pass their dialect instance as `unknown`; the cast lives here, once, so\n * driver packages stay fully typed. Covered by the adapter contract tests.\n */\ninterface DrizzleLike {\n insert(table: AnySQLiteTable): {\n values(values: unknown): { returning(): { get(): MaybePromise<unknown> } };\n };\n update(table: AnySQLiteTable): {\n set(values: unknown): { where(where: SQL): { returning(): { get(): MaybePromise<unknown> } } };\n };\n select(): { from(table: AnySQLiteTable): DrizzleSelectChain };\n delete(table: AnySQLiteTable): { where(where: SQL): { run(): MaybePromise<unknown> } };\n $count(table: AnySQLiteTable, where?: SQL): MaybePromise<number>;\n all<T>(query: SQL): MaybePromise<T[]>;\n transaction<R>(fn: (tx: unknown) => Promise<R>): Promise<R>;\n}\n\nfunction idOf(table: AnySQLiteTable): SQLiteColumn {\n const id = getTableColumns(table)[\"id\"];\n if (!id) {\n throw new Error(\"Table has no id column\");\n }\n return id;\n}\n"],"mappings":"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"}
package/dist/index.mjs CHANGED
@@ -29,7 +29,7 @@ function createSqliteDatabase(path) {
29
29
  const adapter = createDrizzleAdapter(db, {
30
30
  metadata: {
31
31
  name: "SQLite",
32
- version: "0.10.0-next-23b15fb",
32
+ version: "0.10.0-next-864c1ce",
33
33
  description: "SQLite database adapter (node:sqlite + Drizzle)",
34
34
  kind: "sqlite",
35
35
  category: "database"
package/dist/turso.mjs CHANGED
@@ -32,7 +32,7 @@ function createTursoDatabase(options) {
32
32
  return createDrizzleAdapter(db, {
33
33
  metadata: {
34
34
  name: "Turso",
35
- version: "0.10.0-next-23b15fb",
35
+ version: "0.10.0-next-864c1ce",
36
36
  description: "Turso/libSQL database adapter",
37
37
  kind: "turso",
38
38
  category: "database"
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@storyshelf/db-sqlite",
3
- "version": "0.10.0-next-23b15fb",
3
+ "version": "0.10.0-next-864c1ce",
4
4
  "description": "SQLite database adapter for StoryShelf (node:sqlite + Drizzle).",
5
5
  "keywords": [
6
6
  "database",
@@ -87,7 +87,7 @@
87
87
  "prepublishOnly": "nub run build"
88
88
  },
89
89
  "dependencies": {
90
- "@storyshelf/core": "0.10.0-next-23b15fb",
90
+ "@storyshelf/core": "0.10.0-next-864c1ce",
91
91
  "drizzle-orm": "^0.45.4"
92
92
  },
93
93
  "devDependencies": {