@firtoz/drizzle-utils 0.1.0

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 ADDED
@@ -0,0 +1,82 @@
1
+ # @firtoz/drizzle-utils
2
+
3
+ ## 0.1.0
4
+
5
+ ### Minor Changes
6
+
7
+ - [#22](https://github.com/firtoz/fullstack-toolkit/pull/22) [`05e88e7`](https://github.com/firtoz/fullstack-toolkit/commit/05e88e775f262488d1da2b579eadd560cee2eba9) Thanks [@firtoz](https://github.com/firtoz)! - Initial release of `@firtoz/drizzle-utils` - Shared utilities and types for Drizzle ORM-based packages.
8
+
9
+ > **⚠️ Early WIP Notice:** This package is in very early development and is **not production-ready**. It is TypeScript-only and may have breaking changes. While I (the maintainer) have limited time, I'm open to PRs for features, bug fixes, or additional support (like JS builds). Please feel free to try it out and contribute! See [CONTRIBUTING.md](../../CONTRIBUTING.md) for details.
10
+
11
+ ## Features
12
+
13
+ ### Syncable Table Builder
14
+
15
+ - **`syncableTable`** - Creates SQLite tables with automatic timestamp tracking
16
+ - Auto-generates UUID primary keys with type branding
17
+ - Includes `id`, `createdAt`, `updatedAt`, and `deletedAt` columns
18
+ - Validates that default values are compatible with IndexedDB (no SQL expressions)
19
+ - Full TypeScript type safety with branded IDs
20
+
21
+ ### Column Helpers
22
+
23
+ - **`idColumn`** - Branded text primary key column
24
+ - **`createdAtColumn`** - Integer timestamp with automatic default (now)
25
+ - **`updatedAtColumn`** - Integer timestamp with automatic default (now)
26
+ - **`deletedAtColumn`** - Nullable integer timestamp for soft deletes
27
+
28
+ ### Type Utilities
29
+
30
+ - **Branded IDs** - Type-safe string IDs with table-specific branding
31
+ - `TableId<TTableName>` - Table-specific branded ID type
32
+ - `IdOf<TTable>` - Extract ID type from a table
33
+ - `makeId()` - Safely create branded IDs
34
+ - **Schema Helpers** - Type-safe Valibot schema inference
35
+ - `SelectSchema<TTable>` - Infer select schema from table
36
+ - `InsertSchema<TTable>` - Infer insert schema from table
37
+
38
+ ### Migration Types
39
+
40
+ Shared TypeScript types for Drizzle migrations across different database backends:
41
+
42
+ - **Journal Types** - `Journal`, `JournalEntry`
43
+ - **Schema Definition Types** - `TableDefinition`, `ColumnDefinition`, `IndexDefinition`, `ForeignKeyDefinition`, `ViewDefinition`, `EnumDefinition`, etc.
44
+ - **Snapshot Types** - `Snapshot`, `SnapshotMeta`, `SnapshotInternal`
45
+
46
+ These types enable consistent migration handling in both IndexedDB and SQLite WASM packages.
47
+
48
+ ## Example
49
+
50
+ ```typescript
51
+ import { syncableTable, idColumn } from "@firtoz/drizzle-utils";
52
+ import { text } from "drizzle-orm/sqlite-core";
53
+
54
+ // Create a table with automatic timestamp tracking
55
+ const todoTable = syncableTable("todos", {
56
+ title: text("title").notNull(),
57
+ completed: integer("completed", { mode: "boolean" })
58
+ .notNull()
59
+ .default(false),
60
+ });
61
+
62
+ // The table automatically includes:
63
+ // - id: TableId<"todos"> (UUID primary key)
64
+ // - createdAt: Date (auto-set on insert)
65
+ // - updatedAt: Date (auto-set on insert/update)
66
+ // - deletedAt: Date | null (for soft deletes)
67
+
68
+ type Todo = typeof todoTable.$inferSelect;
69
+ // {
70
+ // id: TableId<"todos">;
71
+ // title: string;
72
+ // completed: boolean;
73
+ // createdAt: Date;
74
+ // updatedAt: Date;
75
+ // deletedAt: Date | null;
76
+ // }
77
+ ```
78
+
79
+ ## Dependencies
80
+
81
+ - `drizzle-orm` (peer dependency)
82
+ - `drizzle-valibot` (peer dependency)
package/README.md ADDED
@@ -0,0 +1,270 @@
1
+ # @firtoz/drizzle-utils
2
+
3
+ Shared utilities and types for Drizzle ORM-based packages. Provides type-safe table builders with automatic timestamp tracking, branded IDs, and common migration types.
4
+
5
+ > **⚠️ Early WIP Notice:** This package is in very early development and is **not production-ready**. It is TypeScript-only and may have breaking changes. While I (the maintainer) have limited time, I'm open to PRs for features, bug fixes, or additional support (like JS builds). Please feel free to try it out and contribute! See [CONTRIBUTING.md](../../CONTRIBUTING.md) for details.
6
+
7
+ ## Installation
8
+
9
+ ```bash
10
+ npm install @firtoz/drizzle-utils drizzle-orm drizzle-valibot
11
+ ```
12
+
13
+ ## Features
14
+
15
+ ### 🏗️ Syncable Table Builder
16
+
17
+ Create SQLite tables with automatic timestamp tracking and UUID primary keys:
18
+
19
+ ```typescript
20
+ import { syncableTable } from "@firtoz/drizzle-utils";
21
+ import { text, integer } from "drizzle-orm/sqlite-core";
22
+
23
+ const todoTable = syncableTable("todos", {
24
+ title: text("title").notNull(),
25
+ completed: integer("completed", { mode: "boolean" }).notNull().default(false),
26
+ description: text("description"),
27
+ });
28
+
29
+ // Automatically includes:
30
+ // - id: TableId<"todos"> (UUID primary key)
31
+ // - createdAt: Date (auto-set on insert)
32
+ // - updatedAt: Date (auto-set on update)
33
+ // - deletedAt: Date | null (for soft deletes)
34
+
35
+ type Todo = typeof todoTable.$inferSelect;
36
+ // {
37
+ // id: TableId<"todos">;
38
+ // title: string;
39
+ // completed: boolean;
40
+ // description: string | null;
41
+ // createdAt: Date;
42
+ // updatedAt: Date;
43
+ // deletedAt: Date | null;
44
+ // }
45
+ ```
46
+
47
+ ### 🏷️ Branded ID Types
48
+
49
+ Type-safe IDs with table-specific branding prevent mixing IDs from different tables:
50
+
51
+ ```typescript
52
+ import { makeId, type IdOf } from "@firtoz/drizzle-utils";
53
+
54
+ const todoId = makeId(todoTable, "123e4567-e89b-12d3-a456-426614174000");
55
+ const userId = makeId(userTable, "123e4567-e89b-12d3-a456-426614174000");
56
+
57
+ // TypeScript prevents mixing different table IDs
58
+ function getTodo(id: IdOf<typeof todoTable>) { /* ... */ }
59
+
60
+ getTodo(todoId); // ✅ OK
61
+ getTodo(userId); // ❌ Type error - wrong table!
62
+ ```
63
+
64
+ ### 📋 Column Helpers
65
+
66
+ Individual column builders for custom table definitions:
67
+
68
+ ```typescript
69
+ import {
70
+ idColumn,
71
+ createdAtColumn,
72
+ updatedAtColumn,
73
+ deletedAtColumn
74
+ } from "@firtoz/drizzle-utils";
75
+
76
+ // Use in custom table definitions
77
+ const customTable = sqliteTable("custom", {
78
+ id: idColumn,
79
+ name: text("name").notNull(),
80
+ createdAt: createdAtColumn,
81
+ updatedAt: updatedAtColumn,
82
+ deletedAt: deletedAtColumn,
83
+ });
84
+ ```
85
+
86
+ ### 🔄 Migration Types
87
+
88
+ Shared TypeScript types for Drizzle migrations across IndexedDB and SQLite:
89
+
90
+ ```typescript
91
+ import type {
92
+ Journal,
93
+ JournalEntry,
94
+ Snapshot,
95
+ TableDefinition,
96
+ ColumnDefinition,
97
+ IndexDefinition
98
+ } from "@firtoz/drizzle-utils";
99
+
100
+ // Use these types for custom migration logic
101
+ function applyMigration(snapshot: Snapshot) {
102
+ for (const [tableName, table] of Object.entries(snapshot.tables)) {
103
+ const tableDef: TableDefinition = table;
104
+ // ... migration logic
105
+ }
106
+ }
107
+ ```
108
+
109
+ ### 📝 Schema Type Helpers
110
+
111
+ Type-safe Valibot schema inference:
112
+
113
+ ```typescript
114
+ import { type SelectSchema, type InsertSchema } from "@firtoz/drizzle-utils";
115
+
116
+ type TodoSelect = SelectSchema<typeof todoTable>;
117
+ type TodoInsert = InsertSchema<typeof todoTable>;
118
+
119
+ // Use with Valibot for runtime validation
120
+ import { parse } from "valibot";
121
+ import { createSelectSchema, createInsertSchema } from "drizzle-valibot";
122
+
123
+ const selectSchema = createSelectSchema(todoTable);
124
+ const insertSchema = createInsertSchema(todoTable);
125
+
126
+ const validTodo = parse(selectSchema, data);
127
+ ```
128
+
129
+ ## API Reference
130
+
131
+ ### Table Builders
132
+
133
+ #### `syncableTable(name, columns, extraConfig?)`
134
+
135
+ Creates a SQLite table with automatic timestamp tracking.
136
+
137
+ **Parameters:**
138
+ - `name: string` - Table name
139
+ - `columns: Record<string, SQLiteColumnBuilder>` - Column definitions (cannot use `id`, `createdAt`, `updatedAt`, or `deletedAt` as keys)
140
+ - `extraConfig?: (self) => SQLiteTableExtraConfigValue[]` - Optional indexes and constraints
141
+
142
+ **Returns:** SQLite table with id, createdAt, updatedAt, deletedAt columns
143
+
144
+ **Validation:**
145
+ - Ensures default values are compatible with IndexedDB (no SQL expressions)
146
+ - Throws error if SQL expressions are used as default values
147
+
148
+ ### Column Helpers
149
+
150
+ #### `idColumn`
151
+
152
+ Text column configured as primary key with branded UUID type.
153
+
154
+ #### `createdAtColumn`
155
+
156
+ Integer timestamp column (mode: "timestamp") with automatic default (current date).
157
+
158
+ #### `updatedAtColumn`
159
+
160
+ Integer timestamp column (mode: "timestamp") with automatic default (current date).
161
+
162
+ #### `deletedAtColumn`
163
+
164
+ Nullable integer timestamp column (mode: "timestamp") for soft deletes.
165
+
166
+ ### Type Utilities
167
+
168
+ #### `Branded<T, Brand>`
169
+
170
+ Creates a branded type for better type safety.
171
+
172
+ #### `TableId<TTableName>`
173
+
174
+ Table-specific branded ID type with table name in the brand.
175
+
176
+ #### `IdOf<TTable>`
177
+
178
+ Extracts the ID type from a Drizzle table.
179
+
180
+ #### `makeId<TTable>(table, value)`
181
+
182
+ Safely creates a branded ID for a specific table.
183
+
184
+ #### `SelectSchema<TTable>`
185
+
186
+ Infers the Valibot select schema type from a Drizzle table.
187
+
188
+ #### `InsertSchema<TTable>`
189
+
190
+ Infers the Valibot insert schema type from a Drizzle table.
191
+
192
+ ### Migration Types
193
+
194
+ Comprehensive types for database migrations:
195
+
196
+ - `Journal` - Migration journal with version and entries
197
+ - `JournalEntry` - Individual migration record
198
+ - `Snapshot` - Complete database schema snapshot
199
+ - `TableDefinition` - Table structure definition
200
+ - `ColumnDefinition` - Column configuration
201
+ - `IndexDefinition` - Index configuration
202
+ - `ForeignKeyDefinition` - Foreign key constraint
203
+ - `ViewDefinition` - Database view definition
204
+ - `EnumDefinition` - Enum type definition
205
+
206
+ ## Best Practices
207
+
208
+ ### 1. Use syncableTable for Data Tables
209
+
210
+ Always use `syncableTable` for tables that need timestamp tracking:
211
+
212
+ ```typescript
213
+ // ✅ Good - automatic timestamps
214
+ const todoTable = syncableTable("todos", {
215
+ title: text("title").notNull(),
216
+ });
217
+
218
+ // ❌ Bad - manual timestamp management
219
+ const todoTable = sqliteTable("todos", {
220
+ id: text("id").primaryKey(),
221
+ title: text("title").notNull(),
222
+ createdAt: integer("createdAt", { mode: "timestamp" }),
223
+ // ... repetitive boilerplate
224
+ });
225
+ ```
226
+
227
+ ### 2. Leverage Branded IDs
228
+
229
+ Use branded IDs to prevent mixing IDs from different tables:
230
+
231
+ ```typescript
232
+ type TodoId = IdOf<typeof todoTable>;
233
+ type UserId = IdOf<typeof userTable>;
234
+
235
+ function assignTodo(todoId: TodoId, userId: UserId) {
236
+ // Type safety ensures correct ID types are used
237
+ }
238
+ ```
239
+
240
+ ### 3. Avoid SQL Expressions in Defaults
241
+
242
+ The `syncableTable` validates that default values work with IndexedDB:
243
+
244
+ ```typescript
245
+ // ✅ Good - JavaScript default
246
+ const table = syncableTable("table", {
247
+ status: text("status").default("pending"),
248
+ count: integer("count").default(0),
249
+ });
250
+
251
+ // ❌ Bad - SQL expression (will throw error)
252
+ const table = syncableTable("table", {
253
+ status: text("status").default(sql`'pending'`), // Error!
254
+ });
255
+ ```
256
+
257
+ ## Integration
258
+
259
+ This package is used by:
260
+ - `@firtoz/drizzle-indexeddb` - IndexedDB migrations
261
+ - `@firtoz/drizzle-sqlite-wasm` - SQLite WASM integration
262
+
263
+ ## License
264
+
265
+ MIT
266
+
267
+ ## Author
268
+
269
+ Firtina Ozbalikchi <firtoz@github.com>
270
+
package/package.json ADDED
@@ -0,0 +1,67 @@
1
+ {
2
+ "name": "@firtoz/drizzle-utils",
3
+ "version": "0.1.0",
4
+ "description": "Shared utilities and types for Drizzle-based packages",
5
+ "main": "./src/index.ts",
6
+ "module": "./src/index.ts",
7
+ "types": "./src/index.ts",
8
+ "type": "module",
9
+ "exports": {
10
+ ".": {
11
+ "types": "./src/index.ts",
12
+ "import": "./src/index.ts",
13
+ "require": "./src/index.ts"
14
+ },
15
+ "./*": {
16
+ "types": "./src/*.ts",
17
+ "import": "./src/*.ts",
18
+ "require": "./src/*.ts"
19
+ }
20
+ },
21
+ "files": [
22
+ "src/**/*.ts",
23
+ "!src/**/*.test.ts",
24
+ "README.md",
25
+ "CHANGELOG.md"
26
+ ],
27
+ "scripts": {
28
+ "typecheck": "tsc --noEmit -p ./tsconfig.json",
29
+ "lint": "biome check --write src",
30
+ "lint:ci": "biome ci src",
31
+ "format": "biome format src --write",
32
+ "test": "bun test --pass-with-no-tests",
33
+ "test:watch": "bun test --watch"
34
+ },
35
+ "keywords": [
36
+ "typescript",
37
+ "drizzle",
38
+ "utils"
39
+ ],
40
+ "author": "Firtina Ozbalikchi <firtoz@github.com>",
41
+ "license": "MIT",
42
+ "homepage": "https://github.com/firtoz/fullstack-toolkit#readme",
43
+ "repository": {
44
+ "type": "git",
45
+ "url": "https://github.com/firtoz/fullstack-toolkit.git",
46
+ "directory": "packages/drizzle-utils"
47
+ },
48
+ "bugs": {
49
+ "url": "https://github.com/firtoz/fullstack-toolkit/issues"
50
+ },
51
+ "engines": {
52
+ "node": ">=18.0.0"
53
+ },
54
+ "publishConfig": {
55
+ "access": "public"
56
+ },
57
+ "peerDependencies": {
58
+ "@tanstack/db": "^0.5.0",
59
+ "drizzle-orm": "^0.44.7",
60
+ "drizzle-valibot": "^0.4.2"
61
+ },
62
+ "devDependencies": {
63
+ "@tanstack/db": "^0.5.0",
64
+ "drizzle-orm": "^0.44.7",
65
+ "drizzle-valibot": "^0.4.2"
66
+ }
67
+ }
@@ -0,0 +1,76 @@
1
+ import type { Table } from "drizzle-orm";
2
+ import type { BuildSchema } from "drizzle-valibot";
3
+ import type { Collection, UtilsRecord } from "@tanstack/db";
4
+
5
+ /**
6
+ * Utility type for branded IDs
7
+ */
8
+ export type Branded<T, Brand> = T & { __brand: Brand };
9
+
10
+ export type TableId<TTableName extends string> = Branded<
11
+ string,
12
+ `${TTableName}_id`
13
+ >;
14
+
15
+ /**
16
+ * Utility type to extract the ID type from a table
17
+ */
18
+ export type IdOf<TTable extends Table> = TTable extends {
19
+ $inferSelect: { id: infer TId extends string | number };
20
+ }
21
+ ? TId
22
+ : string | number;
23
+
24
+ /**
25
+ * Utility function to safely create branded IDs
26
+ */
27
+ export function makeId<TTable extends Table>(
28
+ _table: TTable,
29
+ value: string,
30
+ ): IdOf<TTable> {
31
+ return value as IdOf<TTable>;
32
+ }
33
+
34
+ /**
35
+ * Select schema type helper
36
+ */
37
+ export type SelectSchema<TTable extends Table> = BuildSchema<
38
+ "select",
39
+ TTable["_"]["columns"],
40
+ undefined
41
+ >;
42
+
43
+ /**
44
+ * Insert schema type helper
45
+ */
46
+ export type InsertSchema<TTable extends Table> = BuildSchema<
47
+ "insert",
48
+ TTable["_"]["columns"],
49
+ undefined
50
+ >;
51
+
52
+ /**
53
+ * Helper type to get the table from schema by name
54
+ */
55
+ export type GetTableFromSchema<
56
+ TSchema extends Record<string, unknown>,
57
+ TTableName extends keyof TSchema,
58
+ > = TSchema[TTableName] extends Table ? TSchema[TTableName] : never;
59
+
60
+ /**
61
+ * Helper type to infer the collection type from table
62
+ * This provides proper typing for Collection insert/update operations
63
+ */
64
+ export type InferCollectionFromTable<TTable extends Table> = Collection<
65
+ TTable["$inferSelect"],
66
+ IdOf<TTable>,
67
+ UtilsRecord,
68
+ SelectSchema<TTable>,
69
+ Omit<
70
+ TTable["$inferInsert"],
71
+ "id"
72
+ // "createdAt" | "updatedAt" | "deletedAt" | "id"
73
+ > & {
74
+ id?: IdOf<TTable>;
75
+ }
76
+ >;
package/src/index.ts ADDED
@@ -0,0 +1,38 @@
1
+ export type {
2
+ JournalEntry,
3
+ Journal,
4
+ SqliteColumnType,
5
+ ColumnDefinition,
6
+ IndexDefinition,
7
+ ForeignKeyDefinition,
8
+ CompositePrimaryKeyDefinition,
9
+ UniqueConstraintDefinition,
10
+ CheckConstraintDefinition,
11
+ TableDefinition,
12
+ ViewDefinition,
13
+ EnumDefinition,
14
+ SnapshotMeta,
15
+ SnapshotInternal,
16
+ Snapshot,
17
+ } from "./types";
18
+
19
+ export type {
20
+ Branded,
21
+ TableId,
22
+ IdOf,
23
+ SelectSchema,
24
+ InsertSchema,
25
+ GetTableFromSchema,
26
+ InferCollectionFromTable,
27
+ } from "./collection-utils";
28
+
29
+ export { makeId } from "./collection-utils";
30
+
31
+ export {
32
+ createdAtColumn,
33
+ updatedAtColumn,
34
+ deletedAtColumn,
35
+ syncableTable,
36
+ } from "./syncableTable";
37
+
38
+ export type { TableWithRequiredFields } from "./syncableTable";
@@ -0,0 +1,108 @@
1
+ import {
2
+ integer,
3
+ text,
4
+ sqliteTable,
5
+ type SQLiteColumnBuilderBase,
6
+ type TableConfig,
7
+ type SQLiteTableExtraConfigValue,
8
+ type SQLiteTableWithColumns,
9
+ } from "drizzle-orm/sqlite-core";
10
+ import { type BuildColumns, getTableColumns, SQL } from "drizzle-orm";
11
+ import type { TableId } from "./collection-utils";
12
+
13
+ const createTableIdColumn = <TTableName extends string>() =>
14
+ text("id")
15
+ .primaryKey()
16
+ .$type<TableId<TTableName>>()
17
+ .$defaultFn(() => {
18
+ return crypto.randomUUID() as TableId<TTableName>;
19
+ });
20
+
21
+ // Use unixepoch with 'subsec' modifier for millisecond precision timestamps
22
+ export const createdAtColumn = integer("createdAt", { mode: "timestamp_ms" })
23
+ .$defaultFn(() => new Date())
24
+ .notNull();
25
+
26
+ export const updatedAtColumn = integer("updatedAt", { mode: "timestamp_ms" })
27
+ .$defaultFn(() => new Date())
28
+ .notNull();
29
+
30
+ export const deletedAtColumn = integer("deletedAt", {
31
+ mode: "timestamp_ms",
32
+ });
33
+
34
+ export const syncableTable = <
35
+ TTableName extends string,
36
+ TColumns extends Record<string, SQLiteColumnBuilderBase> & {
37
+ id?: never;
38
+ createdAt?: never;
39
+ updatedAt?: never;
40
+ deletedAt?: never;
41
+ },
42
+ >(
43
+ tableName: TTableName,
44
+ columns: TColumns,
45
+ extraConfig?: (
46
+ self: BuildColumns<
47
+ TTableName,
48
+ Omit<TColumns, "id" | "createdAt" | "updatedAt" | "deletedAt"> & {
49
+ id: ReturnType<typeof createTableIdColumn<TTableName>>;
50
+ createdAt: typeof createdAtColumn;
51
+ updatedAt: typeof updatedAtColumn;
52
+ deletedAt: typeof deletedAtColumn;
53
+ },
54
+ "sqlite"
55
+ >,
56
+ ) => SQLiteTableExtraConfigValue[],
57
+ ) => {
58
+ const tableIdColumn = createTableIdColumn<TTableName>();
59
+ const table = sqliteTable(
60
+ tableName,
61
+ {
62
+ id: tableIdColumn,
63
+ createdAt: createdAtColumn,
64
+ updatedAt: updatedAtColumn,
65
+ deletedAt: deletedAtColumn,
66
+ ...columns,
67
+ },
68
+ extraConfig,
69
+ );
70
+
71
+ const tableColumns = getTableColumns(table);
72
+
73
+ // console.log("table:", table);
74
+
75
+ for (const columnName in tableColumns) {
76
+ const column = tableColumns[columnName];
77
+
78
+ let defaultValue: unknown | undefined;
79
+ if (column.defaultFn) {
80
+ defaultValue = column.defaultFn();
81
+ } else if (column.default !== undefined) {
82
+ defaultValue = column.default;
83
+ }
84
+
85
+ if (defaultValue instanceof SQL) {
86
+ throw new Error(
87
+ `Default value for column ${tableName}.${columnName} is a SQL expression, which is not supported for IndexedDB.\n\nYou can use a default value or a default function instead.`,
88
+ );
89
+ }
90
+ }
91
+
92
+ return table;
93
+ };
94
+
95
+ export type TableWithRequiredFields = SQLiteTableWithColumns<
96
+ Pick<TableConfig, "name" | "schema" | "dialect"> & {
97
+ columns: BuildColumns<
98
+ string,
99
+ {
100
+ id: ReturnType<typeof createTableIdColumn<string>>;
101
+ createdAt: typeof createdAtColumn;
102
+ updatedAt: typeof updatedAtColumn;
103
+ deletedAt: typeof deletedAtColumn;
104
+ },
105
+ "sqlite"
106
+ >;
107
+ }
108
+ >;
package/src/types.ts ADDED
@@ -0,0 +1,108 @@
1
+ // Shared types for Drizzle migrations across different database backends
2
+
3
+ // ============================================================================
4
+ // Journal Types
5
+ // ============================================================================
6
+
7
+ export interface JournalEntry {
8
+ idx: number;
9
+ version: string;
10
+ when: number;
11
+ tag: string;
12
+ breakpoints: boolean;
13
+ }
14
+
15
+ export interface Journal {
16
+ version: string;
17
+ dialect: string;
18
+ entries: JournalEntry[];
19
+ }
20
+
21
+ // ============================================================================
22
+ // Schema Definition Types
23
+ // ============================================================================
24
+
25
+ export type SqliteColumnType = "text" | "integer" | "real" | "blob" | "numeric";
26
+
27
+ export interface ColumnDefinition {
28
+ name: string;
29
+ type: SqliteColumnType | string;
30
+ primaryKey: boolean;
31
+ notNull: boolean;
32
+ autoincrement: boolean;
33
+ default?: string | number | boolean | null;
34
+ }
35
+
36
+ export interface IndexDefinition {
37
+ name: string;
38
+ columns: string[];
39
+ isUnique: boolean;
40
+ }
41
+
42
+ export interface ForeignKeyDefinition {
43
+ name: string;
44
+ tableFrom: string;
45
+ tableTo: string;
46
+ columnsFrom: string[];
47
+ columnsTo: string[];
48
+ onDelete?: "cascade" | "set null" | "set default" | "restrict" | "no action";
49
+ onUpdate?: "cascade" | "set null" | "set default" | "restrict" | "no action";
50
+ }
51
+
52
+ export interface CompositePrimaryKeyDefinition {
53
+ name: string;
54
+ columns: string[];
55
+ }
56
+
57
+ export interface UniqueConstraintDefinition {
58
+ name: string;
59
+ columns: string[];
60
+ }
61
+
62
+ export interface CheckConstraintDefinition {
63
+ name: string;
64
+ value: string;
65
+ }
66
+
67
+ export interface TableDefinition {
68
+ name: string;
69
+ columns: Record<string, ColumnDefinition>;
70
+ indexes: Record<string, IndexDefinition>;
71
+ foreignKeys: Record<string, ForeignKeyDefinition>;
72
+ compositePrimaryKeys: Record<string, CompositePrimaryKeyDefinition>;
73
+ uniqueConstraints: Record<string, UniqueConstraintDefinition>;
74
+ checkConstraints: Record<string, CheckConstraintDefinition>;
75
+ }
76
+
77
+ export interface ViewDefinition {
78
+ name: string;
79
+ query: string;
80
+ columns: Record<string, { name: string; type: string }>;
81
+ }
82
+
83
+ export interface EnumDefinition {
84
+ name: string;
85
+ values: string[];
86
+ }
87
+
88
+ export interface SnapshotMeta {
89
+ schemas: Record<string, unknown>;
90
+ tables: Record<string, unknown>;
91
+ columns: Record<string, string>; // Old column name -> new column name
92
+ }
93
+
94
+ export interface SnapshotInternal {
95
+ indexes: Record<string, unknown>;
96
+ }
97
+
98
+ export interface Snapshot {
99
+ version: string;
100
+ dialect: string;
101
+ id: string;
102
+ prevId: string;
103
+ tables: Record<string, TableDefinition>;
104
+ views: Record<string, ViewDefinition>;
105
+ enums: Record<string, EnumDefinition>;
106
+ _meta: SnapshotMeta;
107
+ internal: SnapshotInternal;
108
+ }