@sedrino/db-schema 0.1.1
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/README.md +69 -0
- package/dist/index.d.ts +1222 -0
- package/dist/index.js +1456 -0
- package/dist/index.js.map +1 -0
- package/docs/cli.md +70 -0
- package/docs/index.md +11 -0
- package/docs/migrations.md +65 -0
- package/docs/schema-document.md +48 -0
- package/package.json +41 -0
- package/src/apply.ts +234 -0
- package/src/cli.ts +209 -0
- package/src/drizzle.ts +178 -0
- package/src/index.ts +62 -0
- package/src/migration.ts +456 -0
- package/src/planner.ts +247 -0
- package/src/project.ts +79 -0
- package/src/schema.ts +53 -0
- package/src/sqlite.ts +172 -0
- package/src/types.ts +145 -0
- package/src/utils.ts +286 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/types.ts","../src/utils.ts","../src/migration.ts","../src/schema.ts","../src/sqlite.ts","../src/planner.ts","../src/drizzle.ts","../src/apply.ts","../src/project.ts"],"sourcesContent":["import { z } from \"zod\";\n\nexport const foreignKeyActionSchema = z.enum([\n \"cascade\",\n \"restrict\",\n \"set null\",\n \"set default\",\n \"no action\",\n]);\n\nexport const fieldReferenceSpecSchema = z.object({\n table: z.string().min(1),\n field: z.string().min(1),\n onDelete: foreignKeyActionSchema.optional(),\n onUpdate: foreignKeyActionSchema.optional(),\n});\n\nexport const logicalTypeSpecSchema = z.discriminatedUnion(\"kind\", [\n z.object({\n kind: z.literal(\"id\"),\n prefix: z.string().min(1),\n }),\n z.object({\n kind: z.literal(\"string\"),\n format: z.enum([\"email\", \"url\", \"slug\"]).optional(),\n }),\n z.object({\n kind: z.literal(\"text\"),\n }),\n z.object({\n kind: z.literal(\"boolean\"),\n }),\n z.object({\n kind: z.literal(\"integer\"),\n }),\n z.object({\n kind: z.literal(\"number\"),\n }),\n z.object({\n kind: z.literal(\"enum\"),\n values: z.array(z.string()).min(1),\n }),\n z.object({\n kind: z.literal(\"json\"),\n tsType: z.string().min(1),\n }),\n z.object({\n kind: z.literal(\"temporal.instant\"),\n }),\n z.object({\n kind: z.literal(\"temporal.plainDate\"),\n }),\n]);\n\nexport const storageSpecSchema = z.discriminatedUnion(\"strategy\", [\n z.object({\n strategy: z.literal(\"sqlite.text\"),\n column: z.string().min(1),\n }),\n z.object({\n strategy: z.literal(\"sqlite.integer\"),\n column: z.string().min(1),\n }),\n z.object({\n strategy: z.literal(\"sqlite.real\"),\n column: z.string().min(1),\n }),\n z.object({\n strategy: z.literal(\"sqlite.temporalInstantEpochMs\"),\n column: z.string().min(1),\n }),\n z.object({\n strategy: z.literal(\"sqlite.temporalPlainDateText\"),\n column: z.string().min(1),\n }),\n]);\n\nexport const defaultSpecSchema = z.discriminatedUnion(\"kind\", [\n z.object({\n kind: z.literal(\"literal\"),\n value: z.union([z.string(), z.number(), z.boolean(), z.null()]),\n }),\n z.object({\n kind: z.literal(\"now\"),\n }),\n z.object({\n kind: z.literal(\"generatedId\"),\n prefix: z.string().min(1),\n }),\n]);\n\nexport const fieldSpecSchema = z.object({\n id: z.string().min(1),\n name: z.string().min(1),\n logical: logicalTypeSpecSchema,\n storage: storageSpecSchema,\n nullable: z.boolean().default(true),\n default: defaultSpecSchema.optional(),\n primaryKey: z.boolean().default(false),\n unique: z.boolean().default(false),\n description: z.string().min(1).optional(),\n references: fieldReferenceSpecSchema.optional(),\n});\n\nexport const indexSpecSchema = z.object({\n name: z.string().min(1).optional(),\n fields: z.array(z.string().min(1)).min(1),\n});\n\nexport const uniqueSpecSchema = z.object({\n name: z.string().min(1).optional(),\n fields: z.array(z.string().min(1)).min(1),\n});\n\nexport const tableSpecSchema = z.object({\n id: z.string().min(1),\n name: z.string().min(1),\n description: z.string().min(1).optional(),\n fields: z.array(fieldSpecSchema).default([]),\n indexes: z.array(indexSpecSchema).default([]),\n uniques: z.array(uniqueSpecSchema).default([]),\n});\n\nexport const schemaDocumentSchema = z.object({\n version: z.literal(1),\n dialect: z.literal(\"sqlite\"),\n schemaId: z.string().min(1),\n tables: z.array(tableSpecSchema).default([]),\n});\n\nexport type ForeignKeyAction = z.infer<typeof foreignKeyActionSchema>;\nexport type FieldReferenceSpec = z.infer<typeof fieldReferenceSpecSchema>;\nexport type LogicalTypeSpec = z.infer<typeof logicalTypeSpecSchema>;\nexport type StorageSpec = z.infer<typeof storageSpecSchema>;\nexport type DefaultSpec = z.infer<typeof defaultSpecSchema>;\nexport type FieldSpec = z.infer<typeof fieldSpecSchema>;\nexport type IndexSpec = z.infer<typeof indexSpecSchema>;\nexport type UniqueSpec = z.infer<typeof uniqueSpecSchema>;\nexport type TableSpec = z.infer<typeof tableSpecSchema>;\nexport type DatabaseSchemaDocument = z.infer<typeof schemaDocumentSchema>;\n\nexport type SchemaValidationIssue = {\n path: string;\n message: string;\n};\n","import type {\n DatabaseSchemaDocument,\n DefaultSpec,\n FieldSpec,\n LogicalTypeSpec,\n SchemaValidationIssue,\n StorageSpec,\n} from \"./types\";\n\nconst SQLITE_EPOCH_MS_NOW =\n \"CAST(strftime('%s','now') AS integer) * 1000 + CAST((strftime('%f','now') - strftime('%S','now')) * 1000 AS integer)\";\n\nexport function sqliteEpochMsNowSql() {\n return SQLITE_EPOCH_MS_NOW;\n}\n\nexport function toSnakeCase(value: string) {\n return value\n .replace(/-/g, \"_\")\n .replace(/([a-z0-9])([A-Z])/g, \"$1_$2\")\n .replace(/([A-Z]+)([A-Z][a-z0-9]+)/g, \"$1_$2\")\n .toLowerCase();\n}\n\nexport function toPascalCase(value: string) {\n return value\n .replace(/[_-]+/g, \" \")\n .replace(/([a-z0-9])([A-Z])/g, \"$1 $2\")\n .split(/\\s+/)\n .filter(Boolean)\n .map((part) => `${part[0]!.toUpperCase()}${part.slice(1)}`)\n .join(\"\");\n}\n\nexport function quoteIdentifier(value: string) {\n return `\"${value.replace(/\"/g, '\"\"')}\"`;\n}\n\nexport function tableVariableName(tableName: string) {\n return `table${toPascalCase(tableName)}`;\n}\n\nexport function fieldAutoId(tableName: string, fieldName: string) {\n return `fld_${toSnakeCase(tableName)}_${toSnakeCase(fieldName)}`;\n}\n\nexport function tableAutoId(tableName: string) {\n return `tbl_${toSnakeCase(tableName)}`;\n}\n\nexport function defaultStorageForLogical(logical: LogicalTypeSpec, column: string): StorageSpec {\n switch (logical.kind) {\n case \"id\":\n case \"string\":\n case \"text\":\n case \"enum\":\n case \"json\":\n return { strategy: \"sqlite.text\", column };\n case \"boolean\":\n case \"integer\":\n return { strategy: \"sqlite.integer\", column };\n case \"number\":\n return { strategy: \"sqlite.real\", column };\n case \"temporal.instant\":\n return { strategy: \"sqlite.temporalInstantEpochMs\", column };\n case \"temporal.plainDate\":\n return { strategy: \"sqlite.temporalPlainDateText\", column };\n }\n}\n\nexport function validateLogicalAndStorageCompatibility(\n logical: LogicalTypeSpec,\n storage: StorageSpec,\n): string | null {\n switch (storage.strategy) {\n case \"sqlite.temporalInstantEpochMs\":\n return logical.kind === \"temporal.instant\"\n ? null\n : \"sqlite.temporalInstantEpochMs storage requires logical kind temporal.instant\";\n case \"sqlite.temporalPlainDateText\":\n return logical.kind === \"temporal.plainDate\"\n ? null\n : \"sqlite.temporalPlainDateText storage requires logical kind temporal.plainDate\";\n case \"sqlite.integer\":\n return logical.kind === \"boolean\" || logical.kind === \"integer\"\n ? null\n : \"sqlite.integer storage requires logical kind boolean or integer\";\n case \"sqlite.real\":\n return logical.kind === \"number\" ? null : \"sqlite.real storage requires logical kind number\";\n case \"sqlite.text\":\n return logical.kind === \"id\" ||\n logical.kind === \"string\" ||\n logical.kind === \"text\" ||\n logical.kind === \"enum\" ||\n logical.kind === \"json\"\n ? null\n : \"sqlite.text storage requires logical kind id, string, text, enum, or json\";\n }\n}\n\nexport function validateDefaultCompatibility(\n field: FieldSpec,\n defaultValue: DefaultSpec,\n): string | null {\n if (defaultValue.kind === \"generatedId\") {\n return field.logical.kind === \"id\" ? null : \"generatedId default requires logical kind id\";\n }\n\n if (defaultValue.kind === \"now\") {\n return field.logical.kind === \"temporal.instant\"\n ? null\n : \"now default requires logical kind temporal.instant\";\n }\n\n if (field.logical.kind === \"boolean\" && typeof defaultValue.value !== \"boolean\") {\n return \"boolean fields require boolean literal defaults\";\n }\n\n if (field.logical.kind === \"integer\" && !Number.isInteger(defaultValue.value)) {\n return \"integer fields require integer literal defaults\";\n }\n\n if (field.logical.kind === \"number\" && typeof defaultValue.value !== \"number\") {\n return \"number fields require numeric literal defaults\";\n }\n\n return null;\n}\n\nexport function validateSchemaDocumentCompatibility(\n schema: DatabaseSchemaDocument,\n): SchemaValidationIssue[] {\n const issues: SchemaValidationIssue[] = [];\n const tableNames = new Set<string>();\n\n for (const table of schema.tables) {\n if (tableNames.has(table.name)) {\n issues.push({\n path: `tables.${table.name}`,\n message: `Duplicate table name ${table.name}`,\n });\n }\n tableNames.add(table.name);\n\n const fieldNames = new Set<string>();\n let primaryKeyCount = 0;\n\n for (const field of table.fields) {\n if (fieldNames.has(field.name)) {\n issues.push({\n path: `tables.${table.name}.fields.${field.name}`,\n message: `Duplicate field name ${field.name}`,\n });\n }\n fieldNames.add(field.name);\n\n if (field.primaryKey) primaryKeyCount += 1;\n if (field.primaryKey && field.nullable) {\n issues.push({\n path: `tables.${table.name}.fields.${field.name}`,\n message: \"Primary key fields cannot be nullable\",\n });\n }\n\n const storageIssue = validateLogicalAndStorageCompatibility(field.logical, field.storage);\n if (storageIssue) {\n issues.push({\n path: `tables.${table.name}.fields.${field.name}`,\n message: storageIssue,\n });\n }\n\n if (field.default) {\n const defaultIssue = validateDefaultCompatibility(field, field.default);\n if (defaultIssue) {\n issues.push({\n path: `tables.${table.name}.fields.${field.name}`,\n message: defaultIssue,\n });\n }\n }\n\n if (field.references && !tableNames.has(field.references.table)) {\n const targetTableExists = schema.tables.some(\n (candidate) => candidate.name === field.references!.table,\n );\n if (!targetTableExists) {\n issues.push({\n path: `tables.${table.name}.fields.${field.name}`,\n message: `Referenced table ${field.references.table} does not exist`,\n });\n }\n }\n\n if (field.references) {\n const targetTable = schema.tables.find(\n (candidate) => candidate.name === field.references!.table,\n );\n const targetFieldExists = targetTable?.fields.some(\n (candidate) => candidate.name === field.references!.field,\n );\n\n if (targetTable && !targetFieldExists) {\n issues.push({\n path: `tables.${table.name}.fields.${field.name}`,\n message: `Referenced field ${field.references.field} does not exist on table ${field.references.table}`,\n });\n }\n }\n }\n\n if (primaryKeyCount > 1) {\n issues.push({\n path: `tables.${table.name}`,\n message: \"Composite primary keys are not supported in v1\",\n });\n }\n\n for (const index of table.indexes) {\n for (const fieldName of index.fields) {\n if (!fieldNames.has(fieldName)) {\n issues.push({\n path: `tables.${table.name}.indexes.${index.name ?? fieldName}`,\n message: `Index references missing field ${fieldName}`,\n });\n }\n }\n }\n\n for (const unique of table.uniques) {\n for (const fieldName of unique.fields) {\n if (!fieldNames.has(fieldName)) {\n issues.push({\n path: `tables.${table.name}.uniques.${unique.name ?? fieldName}`,\n message: `Unique constraint references missing field ${fieldName}`,\n });\n }\n }\n }\n }\n\n return issues;\n}\n\nexport function stableStringify(value: unknown): string {\n return JSON.stringify(sortValue(value));\n}\n\nfunction sortValue(value: unknown): unknown {\n if (Array.isArray(value)) {\n return value.map((entry) => sortValue(entry));\n }\n\n if (value && typeof value === \"object\") {\n const entries = Object.entries(value as Record<string, unknown>)\n .sort(([left], [right]) => left.localeCompare(right))\n .map(([key, innerValue]) => [key, sortValue(innerValue)]);\n return Object.fromEntries(entries);\n }\n\n return value;\n}\n\nexport function createSchemaHash(schema: DatabaseSchemaDocument) {\n const text = stableStringify(schema);\n let hash = 2166136261;\n\n for (let index = 0; index < text.length; index += 1) {\n hash ^= text.charCodeAt(index);\n hash = Math.imul(hash, 16777619);\n }\n\n return `schema_${(hash >>> 0).toString(16).padStart(8, \"0\")}`;\n}\n\nexport function cloneSchema<T>(value: T): T {\n return structuredClone(value);\n}\n\nexport function renameStorageColumn(field: FieldSpec, newFieldName: string): FieldSpec {\n const next = cloneSchema(field);\n const column = toSnakeCase(newFieldName);\n next.name = newFieldName;\n next.storage = { ...next.storage, column };\n return next;\n}\n","import type {\n DefaultSpec,\n FieldReferenceSpec,\n FieldSpec,\n IndexSpec,\n LogicalTypeSpec,\n StorageSpec,\n TableSpec,\n UniqueSpec,\n} from \"./types\";\nimport {\n defaultStorageForLogical,\n fieldAutoId,\n tableAutoId,\n toSnakeCase,\n validateDefaultCompatibility,\n validateLogicalAndStorageCompatibility,\n} from \"./utils\";\n\nexport type MigrationMeta = {\n id: string;\n name: string;\n description?: string;\n};\n\nexport type MigrationOperation =\n | { kind: \"createTable\"; table: TableSpec }\n | { kind: \"dropTable\"; tableName: string }\n | { kind: \"renameTable\"; from: string; to: string }\n | { kind: \"addField\"; tableName: string; field: FieldSpec }\n | { kind: \"dropField\"; tableName: string; fieldName: string }\n | { kind: \"renameField\"; tableName: string; from: string; to: string }\n | { kind: \"addIndex\"; tableName: string; index: IndexSpec }\n | { kind: \"dropIndex\"; tableName: string; indexName: string }\n | { kind: \"addUnique\"; tableName: string; unique: UniqueSpec }\n | { kind: \"dropUnique\"; tableName: string; uniqueName: string };\n\nexport type MigrationDefinition = {\n meta: MigrationMeta;\n buildOperations(): MigrationOperation[];\n};\n\ntype FieldOptions = {\n column?: string;\n description?: string;\n storage?: StorageSpec;\n references?: FieldReferenceSpec;\n};\n\nclass MutableFieldBuilder {\n constructor(private field: FieldSpec) {}\n\n required() {\n this.field.nullable = false;\n return this;\n }\n\n nullable() {\n this.field.nullable = true;\n return this;\n }\n\n unique() {\n this.field.unique = true;\n return this;\n }\n\n default(value: string | number | boolean | null) {\n const nextDefault: DefaultSpec = {\n kind: \"literal\",\n value,\n };\n const issue = validateDefaultCompatibility(this.field, nextDefault);\n if (issue) throw new Error(issue);\n this.field.default = nextDefault;\n return this;\n }\n\n defaultNow() {\n const nextDefault: DefaultSpec = {\n kind: \"now\",\n };\n const issue = validateDefaultCompatibility(this.field, nextDefault);\n if (issue) throw new Error(issue);\n this.field.default = nextDefault;\n return this;\n }\n\n references(reference: FieldReferenceSpec) {\n this.field.references = reference;\n return this;\n }\n\n description(description: string) {\n this.field.description = description;\n return this;\n }\n\n column(column: string) {\n this.field.storage = {\n ...this.field.storage,\n column,\n };\n return this;\n }\n\n build() {\n return this.field;\n }\n}\n\nfunction createFieldSpec(\n tableName: string,\n fieldName: string,\n logical: LogicalTypeSpec,\n options: FieldOptions = {},\n): FieldSpec {\n const column = options.column ?? toSnakeCase(fieldName);\n const storage = options.storage ?? defaultStorageForLogical(logical, column);\n const storageIssue = validateLogicalAndStorageCompatibility(logical, storage);\n if (storageIssue) throw new Error(storageIssue);\n\n const field: FieldSpec = {\n id: fieldAutoId(tableName, fieldName),\n name: fieldName,\n logical,\n storage,\n nullable: true,\n primaryKey: false,\n unique: false,\n description: options.description,\n references: options.references,\n };\n\n if (logical.kind === \"id\") {\n field.primaryKey = true;\n field.nullable = false;\n field.default = {\n kind: \"generatedId\",\n prefix: logical.prefix,\n };\n }\n\n return field;\n}\n\nclass TableCreateBuilder {\n private readonly fields: FieldSpec[] = [];\n private readonly indexes: IndexSpec[] = [];\n private readonly uniques: UniqueSpec[] = [];\n private descriptionText?: string;\n\n constructor(private readonly tableName: string) {}\n\n description(text: string) {\n this.descriptionText = text;\n return this;\n }\n\n private addField(field: FieldSpec) {\n this.fields.push(field);\n return new MutableFieldBuilder(field);\n }\n\n id(fieldName: string, options: Omit<FieldOptions, \"storage\"> & { prefix: string }) {\n return this.addField(\n createFieldSpec(this.tableName, fieldName, { kind: \"id\", prefix: options.prefix }, options),\n );\n }\n\n string(fieldName: string, options: FieldOptions & { format?: \"email\" | \"url\" | \"slug\" } = {}) {\n return this.addField(\n createFieldSpec(\n this.tableName,\n fieldName,\n { kind: \"string\", format: options.format },\n options,\n ),\n );\n }\n\n text(fieldName: string, options: FieldOptions = {}) {\n return this.addField(createFieldSpec(this.tableName, fieldName, { kind: \"text\" }, options));\n }\n\n boolean(fieldName: string, options: FieldOptions = {}) {\n return this.addField(createFieldSpec(this.tableName, fieldName, { kind: \"boolean\" }, options));\n }\n\n integer(fieldName: string, options: FieldOptions = {}) {\n return this.addField(createFieldSpec(this.tableName, fieldName, { kind: \"integer\" }, options));\n }\n\n number(fieldName: string, options: FieldOptions = {}) {\n return this.addField(createFieldSpec(this.tableName, fieldName, { kind: \"number\" }, options));\n }\n\n enum(fieldName: string, values: string[], options: FieldOptions = {}) {\n return this.addField(\n createFieldSpec(this.tableName, fieldName, { kind: \"enum\", values }, options),\n );\n }\n\n json(fieldName: string, tsType: string, options: FieldOptions = {}) {\n return this.addField(\n createFieldSpec(this.tableName, fieldName, { kind: \"json\", tsType }, options),\n );\n }\n\n temporalInstant(fieldName: string, options: FieldOptions = {}) {\n return this.addField(\n createFieldSpec(this.tableName, fieldName, { kind: \"temporal.instant\" }, options),\n );\n }\n\n temporalPlainDate(fieldName: string, options: FieldOptions = {}) {\n return this.addField(\n createFieldSpec(this.tableName, fieldName, { kind: \"temporal.plainDate\" }, options),\n );\n }\n\n reference(\n fieldName: string,\n options: Omit<FieldOptions, \"references\"> & { references: FieldReferenceSpec },\n ) {\n return this.addField(\n createFieldSpec(\n this.tableName,\n fieldName,\n { kind: \"string\" },\n { ...options, references: options.references },\n ),\n );\n }\n\n index(fields: string[], options: { name?: string } = {}) {\n this.indexes.push({\n fields,\n name: options.name,\n });\n return this;\n }\n\n unique(fields: string[], options: { name?: string } = {}) {\n this.uniques.push({\n fields,\n name: options.name,\n });\n return this;\n }\n\n build(): TableSpec {\n return {\n id: tableAutoId(this.tableName),\n name: this.tableName,\n description: this.descriptionText,\n fields: this.fields,\n indexes: this.indexes,\n uniques: this.uniques,\n };\n }\n}\n\nclass TableAlterBuilder {\n readonly operations: MigrationOperation[] = [];\n\n constructor(private readonly tableName: string) {}\n\n private addField(field: FieldSpec) {\n const operation: MigrationOperation = {\n kind: \"addField\",\n tableName: this.tableName,\n field,\n };\n this.operations.push(operation);\n return new MutableFieldBuilder(field);\n }\n\n string(fieldName: string, options: FieldOptions & { format?: \"email\" | \"url\" | \"slug\" } = {}) {\n return this.addField(\n createFieldSpec(\n this.tableName,\n fieldName,\n { kind: \"string\", format: options.format },\n options,\n ),\n );\n }\n\n text(fieldName: string, options: FieldOptions = {}) {\n return this.addField(createFieldSpec(this.tableName, fieldName, { kind: \"text\" }, options));\n }\n\n boolean(fieldName: string, options: FieldOptions = {}) {\n return this.addField(createFieldSpec(this.tableName, fieldName, { kind: \"boolean\" }, options));\n }\n\n integer(fieldName: string, options: FieldOptions = {}) {\n return this.addField(createFieldSpec(this.tableName, fieldName, { kind: \"integer\" }, options));\n }\n\n number(fieldName: string, options: FieldOptions = {}) {\n return this.addField(createFieldSpec(this.tableName, fieldName, { kind: \"number\" }, options));\n }\n\n enum(fieldName: string, values: string[], options: FieldOptions = {}) {\n return this.addField(\n createFieldSpec(this.tableName, fieldName, { kind: \"enum\", values }, options),\n );\n }\n\n json(fieldName: string, tsType: string, options: FieldOptions = {}) {\n return this.addField(\n createFieldSpec(this.tableName, fieldName, { kind: \"json\", tsType }, options),\n );\n }\n\n temporalInstant(fieldName: string, options: FieldOptions = {}) {\n return this.addField(\n createFieldSpec(this.tableName, fieldName, { kind: \"temporal.instant\" }, options),\n );\n }\n\n temporalPlainDate(fieldName: string, options: FieldOptions = {}) {\n return this.addField(\n createFieldSpec(this.tableName, fieldName, { kind: \"temporal.plainDate\" }, options),\n );\n }\n\n reference(\n fieldName: string,\n options: Omit<FieldOptions, \"references\"> & { references: FieldReferenceSpec },\n ) {\n return this.addField(\n createFieldSpec(\n this.tableName,\n fieldName,\n { kind: \"string\" },\n { ...options, references: options.references },\n ),\n );\n }\n\n dropField(fieldName: string) {\n this.operations.push({\n kind: \"dropField\",\n tableName: this.tableName,\n fieldName,\n });\n return this;\n }\n\n renameField(from: string, to: string) {\n this.operations.push({\n kind: \"renameField\",\n tableName: this.tableName,\n from,\n to,\n });\n return this;\n }\n\n addIndex(fields: string[], options: { name?: string } = {}) {\n this.operations.push({\n kind: \"addIndex\",\n tableName: this.tableName,\n index: {\n fields,\n name: options.name,\n },\n });\n return this;\n }\n\n dropIndex(indexName: string) {\n this.operations.push({\n kind: \"dropIndex\",\n tableName: this.tableName,\n indexName,\n });\n return this;\n }\n\n addUnique(fields: string[], options: { name?: string } = {}) {\n this.operations.push({\n kind: \"addUnique\",\n tableName: this.tableName,\n unique: {\n fields,\n name: options.name,\n },\n });\n return this;\n }\n\n dropUnique(uniqueName: string) {\n this.operations.push({\n kind: \"dropUnique\",\n tableName: this.tableName,\n uniqueName,\n });\n return this;\n }\n}\n\nclass MigrationBuilderImpl {\n readonly operations: MigrationOperation[] = [];\n\n createTable(name: string, callback: (table: TableCreateBuilder) => void) {\n const table = new TableCreateBuilder(name);\n callback(table);\n this.operations.push({\n kind: \"createTable\",\n table: table.build(),\n });\n return this;\n }\n\n dropTable(tableName: string) {\n this.operations.push({\n kind: \"dropTable\",\n tableName,\n });\n return this;\n }\n\n renameTable(from: string, to: string) {\n this.operations.push({\n kind: \"renameTable\",\n from,\n to,\n });\n return this;\n }\n\n alterTable(tableName: string, callback: (table: TableAlterBuilder) => void) {\n const table = new TableAlterBuilder(tableName);\n callback(table);\n this.operations.push(...table.operations);\n return this;\n }\n}\n\nexport function createMigration(\n meta: MigrationMeta,\n callback: (migration: MigrationBuilderImpl) => void,\n): MigrationDefinition {\n return {\n meta,\n buildOperations() {\n const builder = new MigrationBuilderImpl();\n callback(builder);\n return builder.operations;\n },\n };\n}\n","import {\n type DatabaseSchemaDocument,\n type FieldSpec,\n type SchemaValidationIssue,\n schemaDocumentSchema,\n} from \"./types\";\nimport { createSchemaHash, validateSchemaDocumentCompatibility } from \"./utils\";\n\nexport function createEmptySchema(schemaId = \"schema\") {\n return schemaDocumentSchema.parse({\n version: 1,\n dialect: \"sqlite\",\n schemaId,\n tables: [],\n });\n}\n\nexport function parseSchemaDocument(input: unknown): DatabaseSchemaDocument {\n return schemaDocumentSchema.parse(input);\n}\n\nexport function validateSchemaDocument(input: unknown): {\n schema: DatabaseSchemaDocument;\n issues: SchemaValidationIssue[];\n} {\n const schema = parseSchemaDocument(input);\n return {\n schema,\n issues: validateSchemaDocumentCompatibility(schema),\n };\n}\n\nexport function assertValidSchemaDocument(input: unknown): DatabaseSchemaDocument {\n const { schema, issues } = validateSchemaDocument(input);\n if (issues.length > 0) {\n throw new Error(\n `Schema validation failed:\\n${issues.map((issue) => `- ${issue.path}: ${issue.message}`).join(\"\\n\")}`,\n );\n }\n return schema;\n}\n\nexport function schemaHash(input: DatabaseSchemaDocument) {\n return createSchemaHash(input);\n}\n\nexport function findTable(schema: DatabaseSchemaDocument, tableName: string) {\n return schema.tables.find((table) => table.name === tableName) ?? null;\n}\n\nexport function findField(table: { fields: FieldSpec[] }, fieldName: string) {\n return table.fields.find((field) => field.name === fieldName) ?? null;\n}\n","import type {\n DatabaseSchemaDocument,\n DefaultSpec,\n FieldSpec,\n IndexSpec,\n StorageSpec,\n TableSpec,\n UniqueSpec,\n} from \"./types\";\nimport type { MigrationOperation } from \"./migration\";\nimport { quoteIdentifier, sqliteEpochMsNowSql, toSnakeCase } from \"./utils\";\n\nexport function compileSchemaToSqlite(schema: DatabaseSchemaDocument) {\n const statements: string[] = [];\n\n for (const table of schema.tables) {\n statements.push(renderCreateTableStatement(table));\n statements.push(...renderCreateIndexStatements(table));\n }\n\n return `${statements.join(\"\\n\\n\")}\\n`;\n}\n\nexport function renderSqliteMigration(operations: MigrationOperation[]) {\n const statements: string[] = [];\n const warnings: string[] = [];\n\n for (const operation of operations) {\n switch (operation.kind) {\n case \"createTable\":\n statements.push(renderCreateTableStatement(operation.table));\n statements.push(...renderCreateIndexStatements(operation.table));\n break;\n case \"dropTable\":\n statements.push(`DROP TABLE ${quoteIdentifier(operation.tableName)};`);\n break;\n case \"renameTable\":\n statements.push(\n `ALTER TABLE ${quoteIdentifier(operation.from)} RENAME TO ${quoteIdentifier(operation.to)};`,\n );\n break;\n case \"addField\":\n statements.push(\n `ALTER TABLE ${quoteIdentifier(operation.tableName)} ADD COLUMN ${renderColumnDefinition(operation.field)};`,\n );\n break;\n case \"renameField\":\n statements.push(\n `ALTER TABLE ${quoteIdentifier(operation.tableName)} RENAME COLUMN ${quoteIdentifier(toSnakeCase(operation.from))} TO ${quoteIdentifier(toSnakeCase(operation.to))};`,\n );\n break;\n case \"addIndex\":\n statements.push(renderCreateIndexStatement(operation.tableName, operation.index));\n break;\n case \"dropIndex\":\n statements.push(`DROP INDEX ${quoteIdentifier(operation.indexName)};`);\n break;\n case \"addUnique\":\n statements.push(renderCreateUniqueStatement(operation.tableName, operation.unique));\n break;\n case \"dropUnique\":\n statements.push(`DROP INDEX ${quoteIdentifier(operation.uniqueName)};`);\n break;\n case \"dropField\":\n warnings.push(\n `dropField ${operation.tableName}.${operation.fieldName} requires a table rebuild and is not emitted in v1`,\n );\n break;\n }\n }\n\n return {\n statements,\n warnings,\n };\n}\n\nexport function renderCreateTableStatement(table: TableSpec) {\n const columnLines = table.fields.map((field) => ` ${renderColumnDefinition(field)}`);\n return `CREATE TABLE ${quoteIdentifier(table.name)} (\\n${columnLines.join(\",\\n\")}\\n);`;\n}\n\nexport function renderCreateIndexStatements(table: TableSpec) {\n const statements = table.indexes.map((index) =>\n renderCreateIndexStatement(table.name, index, table),\n );\n statements.push(\n ...table.uniques.map((unique) => renderCreateUniqueStatement(table.name, unique, table)),\n );\n return statements;\n}\n\nfunction renderCreateIndexStatement(tableName: string, index: IndexSpec, table?: TableSpec) {\n const name = index.name ?? `${tableName}_${index.fields.join(\"_\")}_idx`;\n return `CREATE INDEX ${quoteIdentifier(name)} ON ${quoteIdentifier(tableName)} (${index.fields\n .map((field) => quoteIdentifier(resolveColumnName(table, field)))\n .join(\", \")});`;\n}\n\nfunction renderCreateUniqueStatement(tableName: string, unique: UniqueSpec, table?: TableSpec) {\n const name = unique.name ?? `${tableName}_${unique.fields.join(\"_\")}_unique`;\n return `CREATE UNIQUE INDEX ${quoteIdentifier(name)} ON ${quoteIdentifier(tableName)} (${unique.fields\n .map((field) => quoteIdentifier(resolveColumnName(table, field)))\n .join(\", \")});`;\n}\n\nfunction renderColumnDefinition(field: FieldSpec) {\n const parts = [quoteIdentifier(field.storage.column), renderSqlType(field.storage)];\n\n if (field.primaryKey) parts.push(\"PRIMARY KEY\");\n if (!field.nullable) parts.push(\"NOT NULL\");\n if (field.unique && !field.primaryKey) parts.push(\"UNIQUE\");\n\n const defaultSql = renderSqlDefault(field.default, field);\n if (defaultSql) parts.push(`DEFAULT ${defaultSql}`);\n\n if (field.references) {\n parts.push(\n `REFERENCES ${quoteIdentifier(field.references.table)}(${quoteIdentifier(toSnakeCase(field.references.field))})`,\n );\n if (field.references.onDelete)\n parts.push(`ON DELETE ${field.references.onDelete.toUpperCase()}`);\n if (field.references.onUpdate)\n parts.push(`ON UPDATE ${field.references.onUpdate.toUpperCase()}`);\n }\n\n return parts.join(\" \");\n}\n\nfunction renderSqlType(storage: StorageSpec) {\n switch (storage.strategy) {\n case \"sqlite.text\":\n case \"sqlite.temporalPlainDateText\":\n return \"TEXT\";\n case \"sqlite.integer\":\n case \"sqlite.temporalInstantEpochMs\":\n return \"INTEGER\";\n case \"sqlite.real\":\n return \"REAL\";\n }\n}\n\nfunction renderSqlDefault(defaultValue: DefaultSpec | undefined, field: FieldSpec) {\n if (!defaultValue) return null;\n\n switch (defaultValue.kind) {\n case \"generatedId\":\n return null;\n case \"now\":\n return `(${sqliteEpochMsNowSql()})`;\n case \"literal\":\n if (defaultValue.value === null) return \"NULL\";\n if (typeof defaultValue.value === \"string\") {\n return `'${defaultValue.value.replace(/'/g, \"''\")}'`;\n }\n if (typeof defaultValue.value === \"boolean\") {\n return field.storage.strategy === \"sqlite.integer\"\n ? defaultValue.value\n ? \"1\"\n : \"0\"\n : defaultValue.value\n ? \"TRUE\"\n : \"FALSE\";\n }\n return `${defaultValue.value}`;\n }\n}\n\nfunction resolveColumnName(table: TableSpec | undefined, fieldName: string) {\n const field = table?.fields.find((candidate) => candidate.name === fieldName);\n return field?.storage.column ?? toSnakeCase(fieldName);\n}\n","import type { DatabaseSchemaDocument, IndexSpec, TableSpec, UniqueSpec } from \"./types\";\nimport { type MigrationDefinition, type MigrationOperation } from \"./migration\";\nimport { assertValidSchemaDocument, createEmptySchema, findField, findTable } from \"./schema\";\nimport { renderSqliteMigration } from \"./sqlite\";\nimport { cloneSchema, createSchemaHash, renameStorageColumn } from \"./utils\";\n\nexport type PlannedMigration = {\n migrationId: string;\n migrationName: string;\n fromSchemaHash: string;\n toSchemaHash: string;\n operations: MigrationOperation[];\n nextSchema: DatabaseSchemaDocument;\n sql: {\n statements: string[];\n warnings: string[];\n };\n};\n\nexport function planMigration(args: {\n currentSchema?: DatabaseSchemaDocument;\n migration: MigrationDefinition;\n}): PlannedMigration {\n const currentSchema = args.currentSchema\n ? assertValidSchemaDocument(args.currentSchema)\n : createEmptySchema(args.migration.meta.id);\n const operations = args.migration.buildOperations();\n const nextSchema = applyOperationsToSchema(currentSchema, operations);\n\n return {\n migrationId: args.migration.meta.id,\n migrationName: args.migration.meta.name,\n fromSchemaHash: createSchemaHash(currentSchema),\n toSchemaHash: createSchemaHash(nextSchema),\n operations,\n nextSchema,\n sql: renderSqliteMigration(operations),\n };\n}\n\nexport function materializeSchema(args: {\n baseSchema?: DatabaseSchemaDocument;\n migrations: MigrationDefinition[];\n}) {\n let schema = args.baseSchema ? assertValidSchemaDocument(args.baseSchema) : createEmptySchema();\n const plans: PlannedMigration[] = [];\n\n for (const migration of args.migrations) {\n const plan = planMigration({\n currentSchema: schema,\n migration,\n });\n plans.push(plan);\n schema = plan.nextSchema;\n }\n\n return {\n schema,\n plans,\n };\n}\n\nexport function applyOperationsToSchema(\n schemaInput: DatabaseSchemaDocument,\n operations: MigrationOperation[],\n) {\n const schema = cloneSchema(schemaInput);\n\n for (const operation of operations) {\n switch (operation.kind) {\n case \"createTable\":\n if (findTable(schema, operation.table.name)) {\n throw new Error(`Table ${operation.table.name} already exists`);\n }\n schema.tables.push(cloneSchema(operation.table));\n break;\n case \"dropTable\": {\n const referencedBy = schema.tables.flatMap((table) =>\n table.fields\n .filter((field) => field.references?.table === operation.tableName)\n .map((field) => `${table.name}.${field.name}`),\n );\n\n if (referencedBy.length > 0) {\n throw new Error(\n `Cannot drop table ${operation.tableName}; still referenced by ${referencedBy.join(\", \")}`,\n );\n }\n\n const index = schema.tables.findIndex((table) => table.name === operation.tableName);\n if (index < 0) throw new Error(`Table ${operation.tableName} does not exist`);\n schema.tables.splice(index, 1);\n break;\n }\n case \"renameTable\": {\n const table = findTable(schema, operation.from);\n if (!table) throw new Error(`Table ${operation.from} does not exist`);\n if (findTable(schema, operation.to)) {\n throw new Error(`Table ${operation.to} already exists`);\n }\n\n table.name = operation.to;\n for (const candidateTable of schema.tables) {\n for (const field of candidateTable.fields) {\n if (field.references?.table === operation.from) {\n field.references = {\n ...field.references,\n table: operation.to,\n };\n }\n }\n }\n break;\n }\n case \"addField\": {\n const table = findTable(schema, operation.tableName);\n if (!table) throw new Error(`Table ${operation.tableName} does not exist`);\n if (findField(table, operation.field.name)) {\n throw new Error(`Field ${operation.tableName}.${operation.field.name} already exists`);\n }\n table.fields.push(cloneSchema(operation.field));\n break;\n }\n case \"dropField\": {\n const table = findTable(schema, operation.tableName);\n if (!table) throw new Error(`Table ${operation.tableName} does not exist`);\n const fieldIndex = table.fields.findIndex((field) => field.name === operation.fieldName);\n if (fieldIndex < 0) {\n throw new Error(`Field ${operation.tableName}.${operation.fieldName} does not exist`);\n }\n const referencedBy = schema.tables.flatMap((candidateTable) =>\n candidateTable.fields\n .filter(\n (field) =>\n field.references?.table === operation.tableName &&\n field.references.field === operation.fieldName,\n )\n .map((field) => `${candidateTable.name}.${field.name}`),\n );\n if (referencedBy.length > 0) {\n throw new Error(\n `Cannot drop field ${operation.tableName}.${operation.fieldName}; still referenced by ${referencedBy.join(\", \")}`,\n );\n }\n table.fields.splice(fieldIndex, 1);\n table.indexes = table.indexes.filter(\n (index) => !index.fields.includes(operation.fieldName),\n );\n table.uniques = table.uniques.filter(\n (unique) => !unique.fields.includes(operation.fieldName),\n );\n break;\n }\n case \"renameField\": {\n const table = findTable(schema, operation.tableName);\n if (!table) throw new Error(`Table ${operation.tableName} does not exist`);\n const field = findField(table, operation.from);\n if (!field)\n throw new Error(`Field ${operation.tableName}.${operation.from} does not exist`);\n if (findField(table, operation.to)) {\n throw new Error(`Field ${operation.tableName}.${operation.to} already exists`);\n }\n\n const renamed = renameStorageColumn(field, operation.to);\n const index = table.fields.findIndex((candidate) => candidate.id === field.id);\n table.fields[index] = renamed;\n table.indexes = renameFieldInIndexes(table.indexes, operation.from, operation.to);\n table.uniques = renameFieldInUniques(table.uniques, operation.from, operation.to);\n\n for (const candidateTable of schema.tables) {\n for (const candidateField of candidateTable.fields) {\n if (\n candidateField.references?.table === table.name &&\n candidateField.references.field === operation.from\n ) {\n candidateField.references = {\n ...candidateField.references,\n field: operation.to,\n };\n }\n }\n }\n break;\n }\n case \"addIndex\": {\n const table = findTable(schema, operation.tableName);\n if (!table) throw new Error(`Table ${operation.tableName} does not exist`);\n table.indexes.push(cloneSchema(operation.index));\n break;\n }\n case \"dropIndex\": {\n const table = findTable(schema, operation.tableName);\n if (!table) throw new Error(`Table ${operation.tableName} does not exist`);\n const nextIndexes = table.indexes.filter(\n (index) => resolveIndexName(table.name, index) !== operation.indexName,\n );\n if (nextIndexes.length === table.indexes.length) {\n throw new Error(`Index ${operation.indexName} does not exist on ${table.name}`);\n }\n table.indexes = nextIndexes;\n break;\n }\n case \"addUnique\": {\n const table = findTable(schema, operation.tableName);\n if (!table) throw new Error(`Table ${operation.tableName} does not exist`);\n table.uniques.push(cloneSchema(operation.unique));\n break;\n }\n case \"dropUnique\": {\n const table = findTable(schema, operation.tableName);\n if (!table) throw new Error(`Table ${operation.tableName} does not exist`);\n const nextUniques = table.uniques.filter(\n (unique) => resolveUniqueName(table.name, unique) !== operation.uniqueName,\n );\n if (nextUniques.length === table.uniques.length) {\n throw new Error(`Unique ${operation.uniqueName} does not exist on ${table.name}`);\n }\n table.uniques = nextUniques;\n break;\n }\n }\n }\n\n return assertValidSchemaDocument(schema);\n}\n\nfunction renameFieldInIndexes(indexes: IndexSpec[], from: string, to: string): IndexSpec[] {\n return indexes.map((index) => ({\n ...index,\n fields: index.fields.map((field) => (field === from ? to : field)),\n }));\n}\n\nfunction renameFieldInUniques(uniques: UniqueSpec[], from: string, to: string): UniqueSpec[] {\n return uniques.map((unique) => ({\n ...unique,\n fields: unique.fields.map((field) => (field === from ? to : field)),\n }));\n}\n\nfunction resolveIndexName(tableName: string, index: IndexSpec) {\n return index.name ?? `${tableName}_${index.fields.join(\"_\")}_idx`;\n}\n\nfunction resolveUniqueName(tableName: string, unique: UniqueSpec) {\n return unique.name ?? `${tableName}_${unique.fields.join(\"_\")}_unique`;\n}\n","import type {\n DatabaseSchemaDocument,\n DefaultSpec,\n FieldSpec,\n IndexSpec,\n TableSpec,\n UniqueSpec,\n} from \"./types\";\nimport { tableVariableName, toPascalCase } from \"./utils\";\n\nexport function compileSchemaToDrizzle(schema: DatabaseSchemaDocument) {\n const sqliteImports = new Set([\"sqliteTable\"]);\n const toolkitImports = new Set<string>();\n let needsUlid = false;\n\n for (const table of schema.tables) {\n for (const field of table.fields) {\n switch (field.logical.kind) {\n case \"id\":\n case \"string\":\n case \"text\":\n case \"enum\":\n case \"json\":\n sqliteImports.add(\"text\");\n break;\n case \"boolean\":\n case \"integer\":\n sqliteImports.add(\"integer\");\n break;\n case \"number\":\n sqliteImports.add(\"real\");\n break;\n case \"temporal.instant\":\n toolkitImports.add(\"temporalInstantEpochMs\");\n break;\n case \"temporal.plainDate\":\n toolkitImports.add(\"temporalPlainDateText\");\n break;\n }\n\n if (field.default?.kind === \"generatedId\") needsUlid = true;\n if (field.default?.kind === \"now\") toolkitImports.add(\"epochMsNow\");\n }\n\n if (table.indexes.length > 0) sqliteImports.add(\"index\");\n if (table.uniques.length > 0) sqliteImports.add(\"uniqueIndex\");\n }\n\n const lines: string[] = [];\n lines.push(\n `import { ${Array.from(sqliteImports).sort().join(\", \")} } from \"drizzle-orm/sqlite-core\";`,\n );\n if (toolkitImports.size > 0) {\n lines.push(\n `import { ${Array.from(toolkitImports).sort().join(\", \")} } from \"@sedrino/toolkit/drizzle/sqlite\";`,\n );\n }\n if (needsUlid) {\n lines.push(`import { ulid } from \"ulid\";`);\n }\n lines.push(\"\");\n\n for (const table of schema.tables) {\n lines.push(renderTable(table));\n lines.push(\"\");\n }\n\n return lines.join(\"\\n\").trimEnd() + \"\\n\";\n}\n\nfunction renderTable(table: TableSpec) {\n const variableName = tableVariableName(table.name);\n const fieldLines = table.fields.map((field) => ` ${field.name}: ${renderField(field)},`);\n const tableConfig = renderTableConfig(table);\n\n if (!tableConfig) {\n return `export const ${variableName} = sqliteTable(\"${table.name}\", {\\n${fieldLines.join(\"\\n\")}\\n});`;\n }\n\n return `export const ${variableName} = sqliteTable(\"${table.name}\", {\\n${fieldLines.join(\n \"\\n\",\n )}\\n}, (table) => [\\n${tableConfig}\\n]);`;\n}\n\nfunction renderTableConfig(table: TableSpec) {\n const lines: string[] = [];\n\n for (const index of table.indexes) {\n lines.push(` ${renderIndex(table.name, index)},`);\n }\n\n for (const unique of table.uniques) {\n lines.push(` ${renderUnique(table.name, unique)},`);\n }\n\n return lines.length > 0 ? lines.join(\"\\n\") : null;\n}\n\nfunction renderIndex(tableName: string, index: IndexSpec) {\n const name = index.name ?? `${tableName}_${index.fields.join(\"_\")}_idx`;\n return `index(\"${name}\").on(${index.fields.map((field) => `table.${field}`).join(\", \")})`;\n}\n\nfunction renderUnique(tableName: string, unique: UniqueSpec) {\n const name = unique.name ?? `${tableName}_${unique.fields.join(\"_\")}_unique`;\n return `uniqueIndex(\"${name}\").on(${unique.fields.map((field) => `table.${field}`).join(\", \")})`;\n}\n\nfunction renderField(field: FieldSpec) {\n let expression = renderBaseColumn(field);\n\n if (field.logical.kind === \"json\") {\n expression += `.$type<${field.logical.tsType}>()`;\n }\n\n if (field.primaryKey) expression += \".primaryKey()\";\n if (!field.nullable) expression += \".notNull()\";\n if (field.unique && !field.primaryKey) expression += \".unique()\";\n\n const defaultExpression = renderDrizzleDefault(field.default);\n if (defaultExpression) expression += `.default(${defaultExpression})`;\n\n if (field.default?.kind === \"generatedId\") {\n expression += `.$default(() => \\`${field.default.prefix}-\\${ulid()}\\`)`;\n }\n\n if (field.references) {\n const targetTable = tableVariableName(field.references.table);\n const referenceParts = [`() => ${targetTable}.${field.references.field}`];\n const options: string[] = [];\n if (field.references.onDelete) options.push(`onDelete: \"${field.references.onDelete}\"`);\n if (field.references.onUpdate) options.push(`onUpdate: \"${field.references.onUpdate}\"`);\n if (options.length > 0) {\n referenceParts.push(`{ ${options.join(\", \")} }`);\n }\n expression += `.references(${referenceParts.join(\", \")})`;\n }\n\n return expression;\n}\n\nfunction renderBaseColumn(field: FieldSpec) {\n switch (field.logical.kind) {\n case \"id\":\n case \"string\":\n case \"text\":\n return `text(\"${field.storage.column}\")`;\n case \"enum\":\n return `text(\"${field.storage.column}\", { enum: [${field.logical.values\n .map((value) => JSON.stringify(value))\n .join(\", \")}] })`;\n case \"json\":\n return `text(\"${field.storage.column}\", { mode: \"json\" })`;\n case \"boolean\":\n return `integer(\"${field.storage.column}\", { mode: \"boolean\" })`;\n case \"integer\":\n return `integer(\"${field.storage.column}\", { mode: \"number\" })`;\n case \"number\":\n return `real(\"${field.storage.column}\")`;\n case \"temporal.instant\":\n return `temporalInstantEpochMs(\"${field.storage.column}\")`;\n case \"temporal.plainDate\":\n return `temporalPlainDateText(\"${field.storage.column}\")`;\n }\n}\n\nfunction renderDrizzleDefault(defaultValue: DefaultSpec | undefined) {\n if (!defaultValue) return null;\n\n switch (defaultValue.kind) {\n case \"generatedId\":\n return null;\n case \"now\":\n return \"epochMsNow()\";\n case \"literal\":\n return JSON.stringify(defaultValue.value);\n }\n}\n","import { createClient, type Client } from \"@libsql/client\";\nimport type { DatabaseSchemaDocument } from \"./types\";\nimport type { MigrationDefinition } from \"./migration\";\nimport { materializeSchema, planMigration, type PlannedMigration } from \"./planner\";\nimport { schemaHash } from \"./schema\";\n\nconst MIGRATIONS_TABLE = \"_sedrino_schema_migrations\";\nconst STATE_TABLE = \"_sedrino_schema_state\";\n\ntype SqlValue = string | number | null;\n\ntype SchemaStateRow = {\n schemaHash: string;\n schemaJson: string;\n};\n\nexport type ApplyMigrationsResult = {\n appliedPlans: PlannedMigration[];\n skippedMigrationIds: string[];\n currentSchema: DatabaseSchemaDocument;\n currentSchemaHash: string;\n};\n\nexport type LibsqlConnectionOptions = {\n url: string;\n authToken?: string;\n};\n\nexport function createLibsqlClient(options: LibsqlConnectionOptions) {\n return createClient({\n url: options.url,\n authToken: options.authToken,\n concurrency: 0,\n });\n}\n\nexport async function applyMigrations(args: {\n client?: Client;\n connection?: LibsqlConnectionOptions;\n migrations: MigrationDefinition[];\n baseSchema?: DatabaseSchemaDocument;\n}) {\n const client = args.client ?? createLibsqlClient(assertConnection(args.connection));\n\n await ensureMetadataTables(client);\n\n const appliedRows = await listAppliedMigrations(client);\n const appliedIds = new Set(appliedRows.map((row) => row.migrationId));\n const migrationMap = new Map(args.migrations.map((migration) => [migration.meta.id, migration]));\n\n for (const applied of appliedRows) {\n if (!migrationMap.has(applied.migrationId)) {\n throw new Error(\n `Database contains applied migration ${applied.migrationId}, but it is not present locally`,\n );\n }\n }\n\n const appliedLocalMigrations = args.migrations.filter((migration) =>\n appliedIds.has(migration.meta.id),\n );\n const expectedCurrent = materializeSchema({\n baseSchema: args.baseSchema,\n migrations: appliedLocalMigrations,\n }).schema;\n const expectedHash = schemaHash(expectedCurrent);\n const currentState = await getSchemaState(client);\n\n if (currentState) {\n if (currentState.schemaHash !== expectedHash) {\n throw new Error(\n `Schema drift detected. Database hash ${currentState.schemaHash} does not match expected local hash ${expectedHash}`,\n );\n }\n } else if (appliedRows.length > 0) {\n throw new Error(\n `Database has applied migrations recorded in ${MIGRATIONS_TABLE} but is missing ${STATE_TABLE}`,\n );\n }\n\n const pendingMigrations = args.migrations.filter(\n (migration) => !appliedIds.has(migration.meta.id),\n );\n const appliedPlans: PlannedMigration[] = [];\n let currentSchema = expectedCurrent;\n\n for (const migration of pendingMigrations) {\n const plan = planMigration({\n currentSchema,\n migration,\n });\n\n if (plan.sql.warnings.length > 0) {\n throw new Error(\n `Migration ${plan.migrationId} cannot be applied safely:\\n${plan.sql.warnings\n .map((warning) => `- ${warning}`)\n .join(\"\\n\")}`,\n );\n }\n\n await executePlan(client, plan);\n currentSchema = plan.nextSchema;\n appliedPlans.push(plan);\n }\n\n return {\n appliedPlans,\n skippedMigrationIds: appliedLocalMigrations.map((migration) => migration.meta.id),\n currentSchema,\n currentSchemaHash: schemaHash(currentSchema),\n } satisfies ApplyMigrationsResult;\n}\n\nexport async function listAppliedMigrations(client: Client) {\n const result = await client.execute(\n `SELECT migration_id, migration_name, schema_hash, applied_at\n FROM ${MIGRATIONS_TABLE}\n ORDER BY applied_at ASC, migration_id ASC`,\n );\n\n return (result.rows as Array<Record<string, unknown>>).map((row) => ({\n migrationId: getString(row.migration_id) ?? \"\",\n migrationName: getString(row.migration_name) ?? \"\",\n schemaHash: getString(row.schema_hash) ?? \"\",\n appliedAt: getNumber(row.applied_at) ?? 0,\n }));\n}\n\nexport async function getSchemaState(client: Client): Promise<SchemaStateRow | null> {\n const result = await client.execute(\n `SELECT schema_hash, schema_json\n FROM ${STATE_TABLE}\n WHERE singleton_id = 1`,\n );\n\n const row = (result.rows as Array<Record<string, unknown>>)[0];\n if (!row) return null;\n\n const schemaHashValue = getString(row.schema_hash);\n const schemaJsonValue = getString(row.schema_json);\n if (!schemaHashValue || !schemaJsonValue) return null;\n\n return {\n schemaHash: schemaHashValue,\n schemaJson: schemaJsonValue,\n };\n}\n\nasync function ensureMetadataTables(client: Client) {\n await client.batch(\n [\n \"PRAGMA foreign_keys = ON\",\n `\n CREATE TABLE IF NOT EXISTS ${MIGRATIONS_TABLE} (\n migration_id TEXT PRIMARY KEY,\n migration_name TEXT NOT NULL,\n schema_hash TEXT NOT NULL,\n applied_at INTEGER NOT NULL,\n sql_statements_json TEXT NOT NULL\n )\n `,\n `\n CREATE TABLE IF NOT EXISTS ${STATE_TABLE} (\n singleton_id INTEGER PRIMARY KEY CHECK (singleton_id = 1),\n schema_hash TEXT NOT NULL,\n schema_json TEXT NOT NULL,\n updated_at INTEGER NOT NULL\n )\n `,\n ],\n \"write\",\n );\n}\n\nasync function executePlan(client: Client, plan: PlannedMigration) {\n const appliedAt = Date.now();\n const statements: Array<string | { sql: string; args: SqlValue[] }> = [\n ...plan.sql.statements,\n {\n sql: `INSERT INTO ${MIGRATIONS_TABLE} (\n migration_id,\n migration_name,\n schema_hash,\n applied_at,\n sql_statements_json\n ) VALUES (?, ?, ?, ?, ?)`,\n args: [\n plan.migrationId,\n plan.migrationName,\n plan.toSchemaHash,\n appliedAt,\n JSON.stringify(plan.sql.statements),\n ],\n },\n {\n sql: `INSERT INTO ${STATE_TABLE} (\n singleton_id,\n schema_hash,\n schema_json,\n updated_at\n ) VALUES (1, ?, ?, ?)\n ON CONFLICT(singleton_id) DO UPDATE SET\n schema_hash = excluded.schema_hash,\n schema_json = excluded.schema_json,\n updated_at = excluded.updated_at`,\n args: [plan.toSchemaHash, JSON.stringify(plan.nextSchema), appliedAt],\n },\n ];\n\n await client.batch(statements, \"write\");\n}\n\nfunction assertConnection(\n connection: LibsqlConnectionOptions | undefined,\n): LibsqlConnectionOptions {\n if (!connection?.url) {\n throw new Error(\"Missing database connection. Provide --url or pass a connection object.\");\n }\n return connection;\n}\n\nfunction getString(value: unknown) {\n return typeof value === \"string\" && value.trim().length > 0 ? value : null;\n}\n\nfunction getNumber(value: unknown) {\n if (typeof value === \"number\" && Number.isFinite(value)) return value;\n if (typeof value === \"bigint\") return Number(value);\n if (typeof value === \"string\" && value.trim().length > 0) {\n const parsed = Number(value);\n return Number.isFinite(parsed) ? parsed : null;\n }\n return null;\n}\n","import { mkdir, readdir, writeFile } from \"node:fs/promises\";\nimport path from \"node:path\";\nimport { pathToFileURL } from \"node:url\";\nimport type { DatabaseSchemaDocument } from \"./types\";\nimport type { MigrationDefinition } from \"./migration\";\nimport { compileSchemaToDrizzle } from \"./drizzle\";\nimport { materializeSchema } from \"./planner\";\n\nconst MIGRATION_EXTENSIONS = new Set([\".ts\", \".mts\", \".js\", \".mjs\"]);\n\nexport type DbProjectLayout = {\n dbDir: string;\n migrationsDir: string;\n schemaDir: string;\n snapshotPath: string;\n drizzlePath: string;\n};\n\nexport function resolveDbProjectLayout(dbDir = \"db\"): DbProjectLayout {\n const absoluteDbDir = path.resolve(dbDir);\n return {\n dbDir: absoluteDbDir,\n migrationsDir: path.join(absoluteDbDir, \"migrations\"),\n schemaDir: path.join(absoluteDbDir, \"schema\"),\n snapshotPath: path.join(absoluteDbDir, \"schema\", \"schema.snapshot.json\"),\n drizzlePath: path.join(absoluteDbDir, \"schema\", \"schema.generated.ts\"),\n };\n}\n\nexport async function loadMigrationDefinitionsFromDirectory(\n migrationsDir: string,\n): Promise<MigrationDefinition[]> {\n const files = await readdir(migrationsDir, { withFileTypes: true });\n const migrationFiles = files\n .filter((entry) => entry.isFile())\n .map((entry) => path.join(migrationsDir, entry.name))\n .filter((filePath) => MIGRATION_EXTENSIONS.has(path.extname(filePath)))\n .sort((left, right) => path.basename(left).localeCompare(path.basename(right)));\n\n const migrations: MigrationDefinition[] = [];\n\n for (const filePath of migrationFiles) {\n const imported = await import(pathToFileURL(filePath).href);\n const definition = imported.default as Partial<MigrationDefinition> | undefined;\n\n if (\n !definition ||\n !definition.meta ||\n typeof definition.meta.id !== \"string\" ||\n typeof definition.meta.name !== \"string\" ||\n typeof definition.buildOperations !== \"function\"\n ) {\n throw new Error(`Migration file ${filePath} does not export a valid default migration`);\n }\n\n migrations.push(definition as MigrationDefinition);\n }\n\n return migrations;\n}\n\nexport async function materializeProjectMigrations(layout: DbProjectLayout) {\n const migrations = await loadMigrationDefinitionsFromDirectory(layout.migrationsDir);\n const materialized = materializeSchema({ migrations });\n return {\n ...materialized,\n migrations,\n };\n}\n\nexport async function writeSchemaSnapshot(schema: DatabaseSchemaDocument, snapshotPath: string) {\n await mkdir(path.dirname(snapshotPath), { recursive: true });\n await writeFile(snapshotPath, `${JSON.stringify(schema, null, 2)}\\n`, \"utf8\");\n}\n\nexport async function writeDrizzleSchema(schema: DatabaseSchemaDocument, drizzlePath: string) {\n await mkdir(path.dirname(drizzlePath), { recursive: true });\n await writeFile(drizzlePath, compileSchemaToDrizzle(schema), \"utf8\");\n}\n"],"mappings":"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","names":[]}
|
package/docs/cli.md
ADDED
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
# CLI
|
|
2
|
+
|
|
3
|
+
The package ships a Bun-first CLI named `sedrino-db`.
|
|
4
|
+
|
|
5
|
+
## Default project layout
|
|
6
|
+
|
|
7
|
+
```text
|
|
8
|
+
db/
|
|
9
|
+
migrations/
|
|
10
|
+
schema/
|
|
11
|
+
schema.snapshot.json
|
|
12
|
+
schema.generated.ts
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
## Commands
|
|
16
|
+
|
|
17
|
+
### Plan
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
sedrino-db migrate plan --dir db
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
This:
|
|
24
|
+
|
|
25
|
+
- loads and sorts migrations from `db/migrations`
|
|
26
|
+
- materializes the current schema snapshot
|
|
27
|
+
- writes `db/schema/schema.snapshot.json`
|
|
28
|
+
- writes `db/schema/schema.generated.ts`
|
|
29
|
+
|
|
30
|
+
Add `--sql` to print the SQLite statements per migration.
|
|
31
|
+
|
|
32
|
+
### Apply
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
sedrino-db migrate apply --dir db --url libsql://...
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
This:
|
|
39
|
+
|
|
40
|
+
- reads local migrations
|
|
41
|
+
- compares them with applied migrations recorded in the database
|
|
42
|
+
- applies pending migrations
|
|
43
|
+
- updates the stored schema metadata tables
|
|
44
|
+
- writes the local snapshot and generated Drizzle file
|
|
45
|
+
|
|
46
|
+
Auth token resolution order:
|
|
47
|
+
|
|
48
|
+
- `--auth-token`
|
|
49
|
+
- `LIBSQL_AUTH_TOKEN`
|
|
50
|
+
|
|
51
|
+
URL resolution order:
|
|
52
|
+
|
|
53
|
+
- `--url`
|
|
54
|
+
- `LIBSQL_URL`
|
|
55
|
+
|
|
56
|
+
### Print schema
|
|
57
|
+
|
|
58
|
+
```bash
|
|
59
|
+
sedrino-db schema print --dir db
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
Prints the materialized schema snapshot JSON to stdout.
|
|
63
|
+
|
|
64
|
+
### Emit Drizzle
|
|
65
|
+
|
|
66
|
+
```bash
|
|
67
|
+
sedrino-db schema drizzle --dir db --out db/schema/schema.generated.ts
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
Prints generated Drizzle source to stdout unless `--out` is provided.
|
package/docs/index.md
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
# @sedrino/db-schema docs
|
|
2
|
+
|
|
3
|
+
Reference index for the migration-first schema planning package.
|
|
4
|
+
|
|
5
|
+
## Guides
|
|
6
|
+
|
|
7
|
+
| Topic | File |
|
|
8
|
+
| --- | --- |
|
|
9
|
+
| Schema document model | [`schema-document.md`](./schema-document.md) |
|
|
10
|
+
| Migration DSL and planning flow | [`migrations.md`](./migrations.md) |
|
|
11
|
+
| CLI commands | [`cli.md`](./cli.md) |
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
# Migrations
|
|
2
|
+
|
|
3
|
+
The library is migration-first.
|
|
4
|
+
|
|
5
|
+
Humans or AI author migration files in a deterministic builder DSL, and the planner materializes the resulting schema snapshot.
|
|
6
|
+
|
|
7
|
+
## Example
|
|
8
|
+
|
|
9
|
+
```ts
|
|
10
|
+
import { createMigration } from "@sedrino/db-schema";
|
|
11
|
+
|
|
12
|
+
export default createMigration(
|
|
13
|
+
{
|
|
14
|
+
id: "2026-04-08-001-create-crm-core",
|
|
15
|
+
name: "Create CRM core tables",
|
|
16
|
+
},
|
|
17
|
+
(m) => {
|
|
18
|
+
m.createTable("account", (t) => {
|
|
19
|
+
t.id("accountId", { prefix: "acct" });
|
|
20
|
+
t.string("name").required();
|
|
21
|
+
t.temporalInstant("createdAt").required().defaultNow();
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
m.createTable("contact", (t) => {
|
|
25
|
+
t.id("contactId", { prefix: "ct" });
|
|
26
|
+
t.reference("accountId", {
|
|
27
|
+
references: {
|
|
28
|
+
table: "account",
|
|
29
|
+
field: "accountId",
|
|
30
|
+
onDelete: "cascade",
|
|
31
|
+
},
|
|
32
|
+
}).required();
|
|
33
|
+
t.string("email", { format: "email" }).required();
|
|
34
|
+
});
|
|
35
|
+
},
|
|
36
|
+
);
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
## Planning flow
|
|
40
|
+
|
|
41
|
+
```ts
|
|
42
|
+
const plan = planMigration({
|
|
43
|
+
currentSchema,
|
|
44
|
+
migration,
|
|
45
|
+
});
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
The result includes:
|
|
49
|
+
|
|
50
|
+
- ordered semantic operations
|
|
51
|
+
- next schema snapshot JSON
|
|
52
|
+
- SQLite migration statements where v1 can emit them safely
|
|
53
|
+
- warnings for operations that still need rebuild-aware emitters
|
|
54
|
+
|
|
55
|
+
For project-style usage, the CLI wraps this flow:
|
|
56
|
+
|
|
57
|
+
```bash
|
|
58
|
+
sedrino-db migrate plan --dir db
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
## Current v1 limits
|
|
62
|
+
|
|
63
|
+
- no rebuild-aware SQL emission for destructive field changes
|
|
64
|
+
- no composite primary keys
|
|
65
|
+
- SQLite-only
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
# Schema Document
|
|
2
|
+
|
|
3
|
+
`@sedrino/db-schema` separates:
|
|
4
|
+
|
|
5
|
+
- logical/runtime field meaning
|
|
6
|
+
- physical SQLite storage strategy
|
|
7
|
+
|
|
8
|
+
That means a field can be modeled as `Temporal.Instant` in the schema document while still compiling to integer storage and Temporal-aware Drizzle helpers.
|
|
9
|
+
|
|
10
|
+
## Core shape
|
|
11
|
+
|
|
12
|
+
```ts
|
|
13
|
+
type DatabaseSchemaDocument = {
|
|
14
|
+
version: 1;
|
|
15
|
+
dialect: "sqlite";
|
|
16
|
+
schemaId: string;
|
|
17
|
+
tables: TableSpec[];
|
|
18
|
+
};
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
## Important v1 ideas
|
|
22
|
+
|
|
23
|
+
- The schema document is the materialized current-state snapshot.
|
|
24
|
+
- Migrations are still the authored change history.
|
|
25
|
+
- Logical types are higher-level than physical column types.
|
|
26
|
+
- Storage strategies make the SQLite representation explicit.
|
|
27
|
+
|
|
28
|
+
## Example
|
|
29
|
+
|
|
30
|
+
```ts
|
|
31
|
+
{
|
|
32
|
+
id: "fld_account_created_at",
|
|
33
|
+
name: "createdAt",
|
|
34
|
+
logical: { kind: "temporal.instant" },
|
|
35
|
+
storage: {
|
|
36
|
+
strategy: "sqlite.temporalInstantEpochMs",
|
|
37
|
+
column: "created_at",
|
|
38
|
+
},
|
|
39
|
+
nullable: false,
|
|
40
|
+
default: { kind: "now" },
|
|
41
|
+
}
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
That compiles to:
|
|
45
|
+
|
|
46
|
+
- runtime semantics: `Temporal.Instant`
|
|
47
|
+
- physical storage: `INTEGER`
|
|
48
|
+
- Drizzle helper: `temporalInstantEpochMs("created_at")`
|
package/package.json
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@sedrino/db-schema",
|
|
3
|
+
"version": "0.1.1",
|
|
4
|
+
"publishConfig": {
|
|
5
|
+
"access": "public"
|
|
6
|
+
},
|
|
7
|
+
"type": "module",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"types": "./dist/index.d.ts",
|
|
11
|
+
"import": "./dist/index.js",
|
|
12
|
+
"default": "./dist/index.js"
|
|
13
|
+
},
|
|
14
|
+
"./package.json": "./package.json"
|
|
15
|
+
},
|
|
16
|
+
"bin": {
|
|
17
|
+
"sedrino-db": "./src/cli.ts"
|
|
18
|
+
},
|
|
19
|
+
"files": [
|
|
20
|
+
"dist",
|
|
21
|
+
"src",
|
|
22
|
+
"docs",
|
|
23
|
+
"README.md"
|
|
24
|
+
],
|
|
25
|
+
"scripts": {
|
|
26
|
+
"clean": "rm -rf dist",
|
|
27
|
+
"build": "bun run clean && tsup",
|
|
28
|
+
"test": "bun test",
|
|
29
|
+
"typecheck": "bunx -p @typescript/native-preview tsc --noEmit",
|
|
30
|
+
"test:all": "bun test && bunx -p @typescript/native-preview tsc --noEmit"
|
|
31
|
+
},
|
|
32
|
+
"dependencies": {
|
|
33
|
+
"@libsql/client": "^0.15.15",
|
|
34
|
+
"zod": "^4.3.6"
|
|
35
|
+
},
|
|
36
|
+
"devDependencies": {
|
|
37
|
+
"@types/bun": "^1.3.9",
|
|
38
|
+
"tsup": "^8.5.1",
|
|
39
|
+
"typescript": "^5.9.3"
|
|
40
|
+
}
|
|
41
|
+
}
|