zod-sqlite 1.0.2 → 1.0.3
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/LICENSE +21 -0
- package/README.md +226 -185
- package/dist/index.d.mts +461 -0
- package/dist/index.mjs +287 -0
- package/package.json +38 -55
- package/dist/index.cjs +0 -255
- package/dist/index.cjs.map +0 -1
- package/dist/index.d.cts +0 -478
- package/dist/index.d.ts +0 -478
- package/dist/index.js +0 -253
- package/dist/index.js.map +0 -1
package/dist/index.mjs
ADDED
|
@@ -0,0 +1,287 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
//#region src/utils/format-check-constraint.ts
|
|
3
|
+
/**
|
|
4
|
+
* Generates formatted CHECK constraints for validatable columns.
|
|
5
|
+
*
|
|
6
|
+
* Supports:
|
|
7
|
+
* - `z.enum()`: CHECK(col IN ('a', 'b'))
|
|
8
|
+
* - `z.literal()`: CHECK(col = 'val')
|
|
9
|
+
* - `z.number().min/max()`: CHECK(col >= min AND col <= max)
|
|
10
|
+
* - `z.string().min/max()`: CHECK(length(col) >= min)
|
|
11
|
+
* @param name Column name
|
|
12
|
+
* @param schema Zod schema
|
|
13
|
+
* @returns SQL CHECK constraint string or null
|
|
14
|
+
*/
|
|
15
|
+
function formatCheckConstraint(name, schema) {
|
|
16
|
+
let currentSchema = schema;
|
|
17
|
+
while (true) {
|
|
18
|
+
const def = currentSchema._zod.def;
|
|
19
|
+
if (def.type === "nullable" || def.type === "optional" || def.type === "default") currentSchema = def.innerType;
|
|
20
|
+
else break;
|
|
21
|
+
}
|
|
22
|
+
const definition = currentSchema._zod.def;
|
|
23
|
+
switch (definition.type) {
|
|
24
|
+
case "enum": {
|
|
25
|
+
const entries = definition.entries;
|
|
26
|
+
return `CHECK(${name} IN (${Object.values(entries).map((value) => `'${String(value).replaceAll("'", "''")}'`).join(", ")}))`;
|
|
27
|
+
}
|
|
28
|
+
case "literal": {
|
|
29
|
+
const values = definition.values;
|
|
30
|
+
if (values.length === 1) {
|
|
31
|
+
const value = values[0];
|
|
32
|
+
if (typeof value === "string") return `CHECK(${name} = '${value.replaceAll("'", "''")}')`;
|
|
33
|
+
return `CHECK(${name} = ${value})`;
|
|
34
|
+
}
|
|
35
|
+
return `CHECK(${name} IN (${values.map((value) => {
|
|
36
|
+
if (typeof value === "string") return `'${value.replaceAll("'", "''")}'`;
|
|
37
|
+
return String(value);
|
|
38
|
+
}).join(", ")}))`;
|
|
39
|
+
}
|
|
40
|
+
case "number": {
|
|
41
|
+
const checks = definition.checks;
|
|
42
|
+
const constraints = [];
|
|
43
|
+
if (!checks) return;
|
|
44
|
+
for (const check of checks) {
|
|
45
|
+
const checkParameters = check._zod.def.check;
|
|
46
|
+
const checkValue = check._zod.def.value;
|
|
47
|
+
switch (checkParameters) {
|
|
48
|
+
case "greater_than":
|
|
49
|
+
constraints.push(`${name} >= ${checkValue}`);
|
|
50
|
+
break;
|
|
51
|
+
case "less_than":
|
|
52
|
+
constraints.push(`${name} <= ${checkValue}`);
|
|
53
|
+
break;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
return constraints.length > 0 ? `CHECK(${constraints.join(" AND ")})` : void 0;
|
|
57
|
+
}
|
|
58
|
+
case "string": {
|
|
59
|
+
const checks = definition.checks;
|
|
60
|
+
const constraints = [];
|
|
61
|
+
if (!checks) return;
|
|
62
|
+
for (const check of checks) {
|
|
63
|
+
const checkParameters = check._zod.def.check;
|
|
64
|
+
const checkDefinition = check._zod.def;
|
|
65
|
+
switch (checkParameters) {
|
|
66
|
+
case "length_equals":
|
|
67
|
+
constraints.push(`length(${name}) = ${checkDefinition.length}`);
|
|
68
|
+
break;
|
|
69
|
+
case "max_length":
|
|
70
|
+
constraints.push(`length(${name}) <= ${checkDefinition.maximum}`);
|
|
71
|
+
break;
|
|
72
|
+
case "min_length":
|
|
73
|
+
constraints.push(`length(${name}) >= ${checkDefinition.minimum}`);
|
|
74
|
+
break;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
return constraints.length > 0 ? `CHECK(${constraints.join(" AND ")})` : void 0;
|
|
78
|
+
}
|
|
79
|
+
case "union": {
|
|
80
|
+
const options = definition.options;
|
|
81
|
+
if (!options.every((option) => option._zod.def.type === "literal")) return;
|
|
82
|
+
const values = [];
|
|
83
|
+
for (const option of options) values.push(...option._zod.def.values);
|
|
84
|
+
return `CHECK(${name} IN (${values.map((value) => {
|
|
85
|
+
if (typeof value === "string") return `'${value.replaceAll("'", "''")}'`;
|
|
86
|
+
return String(value);
|
|
87
|
+
}).join(", ")}))`;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
//#endregion
|
|
92
|
+
//#region src/utils/format-default-value.ts
|
|
93
|
+
/**
|
|
94
|
+
* Formats a default value for SQL.
|
|
95
|
+
*
|
|
96
|
+
* Handles string quoting and type conversions for DEFAULT clauses.
|
|
97
|
+
* @param value The default value
|
|
98
|
+
* @param SQLiteType Target column type
|
|
99
|
+
* @returns Formatted SQL default string (e.g., "DEFAULT 'val'", "DEFAULT 42")
|
|
100
|
+
*/
|
|
101
|
+
function formatDefaultValue(value, SQLiteType) {
|
|
102
|
+
switch (SQLiteType) {
|
|
103
|
+
case "TEXT": return `DEFAULT '${String(value).replaceAll("'", "''")}'`;
|
|
104
|
+
case "INTEGER":
|
|
105
|
+
case "REAL": return `DEFAULT ${Number(value)}`;
|
|
106
|
+
case "BOOLEAN": return `DEFAULT ${value ? 1 : 0}`;
|
|
107
|
+
case "NULL": return "DEFAULT NULL";
|
|
108
|
+
default: return `DEFAULT '${value}'`;
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
//#endregion
|
|
112
|
+
//#region src/utils/map-zod-type-to-sqlite.ts
|
|
113
|
+
/**
|
|
114
|
+
* Maps a Zod type to an SQLite column type.
|
|
115
|
+
*
|
|
116
|
+
* analyzes the Zod schema type and optionally its format (e.g., z.email())
|
|
117
|
+
* to determine the most appropriate SQLite storage class or supported type.
|
|
118
|
+
* @param zodType Zod type string (e.g., 'string', 'number')
|
|
119
|
+
* @param schema The actual Zod schema instance
|
|
120
|
+
* @returns SQLite column type
|
|
121
|
+
*/
|
|
122
|
+
function mapZodTypeToSQLite(zodType, schema) {
|
|
123
|
+
switch (zodType) {
|
|
124
|
+
case "string": switch (schema._zod.def.format) {
|
|
125
|
+
case "date": return "DATE";
|
|
126
|
+
case "datetime": return "DATETIME";
|
|
127
|
+
case "duration": return "INTEGER";
|
|
128
|
+
default: return "TEXT";
|
|
129
|
+
}
|
|
130
|
+
case "enum":
|
|
131
|
+
case "literal":
|
|
132
|
+
case "array":
|
|
133
|
+
case "template_literal":
|
|
134
|
+
case "object": return "TEXT";
|
|
135
|
+
case "date": return "DATE";
|
|
136
|
+
case "number": switch (schema._zod.def.format) {
|
|
137
|
+
case "safeint":
|
|
138
|
+
case "uint32":
|
|
139
|
+
case "int32": return "INTEGER";
|
|
140
|
+
case "float32":
|
|
141
|
+
case "float64": return "FLOAT";
|
|
142
|
+
default: return "REAL";
|
|
143
|
+
}
|
|
144
|
+
case "boolean": return "BOOLEAN";
|
|
145
|
+
case "bigint": return "BIGINT";
|
|
146
|
+
case "null":
|
|
147
|
+
case "undefined": return "NULL";
|
|
148
|
+
case "file": return "BLOB";
|
|
149
|
+
default: return "TEXT";
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
//#endregion
|
|
153
|
+
//#region src/utils/zod-to-sqlite.ts
|
|
154
|
+
/**
|
|
155
|
+
* Analyzes a Zod schema to extract SQLite metadata.
|
|
156
|
+
*
|
|
157
|
+
* Unwraps optional/nullable/default layers to find the underlying core type
|
|
158
|
+
* and extracts metadata like nullability and default values.
|
|
159
|
+
* @param schema Zod schema to analyze
|
|
160
|
+
* @returns Object containing SQLite type, nullability, default value, and inner schema
|
|
161
|
+
*/
|
|
162
|
+
function zodToSQLite(schema) {
|
|
163
|
+
let nullable = false;
|
|
164
|
+
let defaultValue;
|
|
165
|
+
let currentSchema = schema;
|
|
166
|
+
while (true) {
|
|
167
|
+
const definition = currentSchema._zod.def;
|
|
168
|
+
const zodType = definition.type;
|
|
169
|
+
if (zodType === "nullable" || zodType === "optional") {
|
|
170
|
+
nullable = true;
|
|
171
|
+
currentSchema = definition.innerType;
|
|
172
|
+
} else if (zodType === "default") {
|
|
173
|
+
defaultValue = typeof definition.defaultValue === "function" ? definition.defaultValue() : definition.defaultValue;
|
|
174
|
+
currentSchema = definition.innerType;
|
|
175
|
+
} else break;
|
|
176
|
+
}
|
|
177
|
+
const mainType = currentSchema._zod.def.type;
|
|
178
|
+
const SQLiteType = mapZodTypeToSQLite(mainType, currentSchema);
|
|
179
|
+
return {
|
|
180
|
+
defaultValue,
|
|
181
|
+
nullable,
|
|
182
|
+
schema,
|
|
183
|
+
SQLiteType
|
|
184
|
+
};
|
|
185
|
+
}
|
|
186
|
+
//#endregion
|
|
187
|
+
//#region src/column-definitions.ts
|
|
188
|
+
/**
|
|
189
|
+
* Builds the SQL definition for a single column.
|
|
190
|
+
*
|
|
191
|
+
* Combines name, type, and constraints into a valid SQL column string.
|
|
192
|
+
* @param column Column configuration object
|
|
193
|
+
* @returns Complete column definition string (e.g., "id INTEGER NOT NULL")
|
|
194
|
+
*/
|
|
195
|
+
function buildColumnDefinition(column) {
|
|
196
|
+
const { name, references, schema, unique } = column;
|
|
197
|
+
const { defaultValue, nullable, SQLiteType } = zodToSQLite(schema);
|
|
198
|
+
const parts = [name, SQLiteType];
|
|
199
|
+
if (!nullable) parts.push("NOT NULL");
|
|
200
|
+
if (defaultValue !== void 0) parts.push(formatDefaultValue(defaultValue, SQLiteType));
|
|
201
|
+
if (unique) parts.push("UNIQUE");
|
|
202
|
+
const checkConstraint = formatCheckConstraint(name, schema);
|
|
203
|
+
if (checkConstraint) parts.push(checkConstraint);
|
|
204
|
+
if (references) {
|
|
205
|
+
const { column: refColumn, onDelete, onUpdate, table } = references;
|
|
206
|
+
parts.push(`REFERENCES ${table}(${refColumn})`);
|
|
207
|
+
if (onDelete) parts.push(`ON DELETE ${onDelete}`);
|
|
208
|
+
if (onUpdate) parts.push(`ON UPDATE ${onUpdate}`);
|
|
209
|
+
}
|
|
210
|
+
return parts.join(" ");
|
|
211
|
+
}
|
|
212
|
+
//#endregion
|
|
213
|
+
//#region src/index-statements.ts
|
|
214
|
+
/**
|
|
215
|
+
* Generates SQL statements for table indexes.
|
|
216
|
+
*
|
|
217
|
+
* Creates standard, unique, and partial indexes based on configuration.
|
|
218
|
+
* @param tableName Name of the table
|
|
219
|
+
* @param indexes Array of index configurations
|
|
220
|
+
* @returns Array of CREATE INDEX SQL statements
|
|
221
|
+
*/
|
|
222
|
+
function buildIndexStatements(tableName, indexes) {
|
|
223
|
+
if (!indexes || indexes.length === 0) return [];
|
|
224
|
+
return indexes.map((index) => {
|
|
225
|
+
const uniqueClause = index.unique ? "UNIQUE " : "";
|
|
226
|
+
const whereClause = index.where ? ` WHERE ${index.where}` : "";
|
|
227
|
+
return `CREATE ${uniqueClause}INDEX ${index.name} ON ${tableName} (${index.columns.join(", ")})${whereClause};`;
|
|
228
|
+
});
|
|
229
|
+
}
|
|
230
|
+
//#endregion
|
|
231
|
+
//#region src/primary-key-constraint.ts
|
|
232
|
+
/**
|
|
233
|
+
* Builds the PRIMARY KEY constraint string.
|
|
234
|
+
*
|
|
235
|
+
* Handles both single-column and composite primary keys.
|
|
236
|
+
* @param primaryKeys Array of column names forming the primary key
|
|
237
|
+
* @returns SQL constraint string (e.g., "PRIMARY KEY (id, email)")
|
|
238
|
+
*/
|
|
239
|
+
function buildPrimaryKeyConstraint(primaryKeys) {
|
|
240
|
+
if (primaryKeys.length === 0) return "";
|
|
241
|
+
return `PRIMARY KEY (${primaryKeys.join(", ")})`;
|
|
242
|
+
}
|
|
243
|
+
//#endregion
|
|
244
|
+
//#region src/zod-schema.ts
|
|
245
|
+
/**
|
|
246
|
+
* Builds a Zod schema from column definitions.
|
|
247
|
+
*
|
|
248
|
+
* Creates a Zod object schema where keys are column names and values are
|
|
249
|
+
* the corresponding Zod schemas from the column configuration.
|
|
250
|
+
* @template TColumns - Array of column configurations
|
|
251
|
+
* @param columns Array of column configurations
|
|
252
|
+
* @returns Zod object schema
|
|
253
|
+
*/
|
|
254
|
+
function buildZodSchema(columns) {
|
|
255
|
+
const schemaShape = {};
|
|
256
|
+
for (const column of columns) schemaShape[column.name] = column.schema;
|
|
257
|
+
return z.object(schemaShape);
|
|
258
|
+
}
|
|
259
|
+
//#endregion
|
|
260
|
+
//#region src/table.ts
|
|
261
|
+
/**
|
|
262
|
+
* Creates a table definition and Zod schema.
|
|
263
|
+
*
|
|
264
|
+
* This function is the main entry point for defining a table. It takes a configuration object
|
|
265
|
+
* and returns:
|
|
266
|
+
* 1. `table`: SQL CREATE TABLE statement
|
|
267
|
+
* 2. `indexes`: Array of SQL CREATE INDEX statements
|
|
268
|
+
* 3. `schema`: Zod object schema matching the table structure
|
|
269
|
+
* @template TColumns - Array of column configurations
|
|
270
|
+
* @param config Table configuration object
|
|
271
|
+
* @returns Object containing SQL statements and Zod schema
|
|
272
|
+
*/
|
|
273
|
+
function createTable(config) {
|
|
274
|
+
const { columns, indexes, name, primaryKeys } = config;
|
|
275
|
+
const columnDefs = columns.map((column) => buildColumnDefinition(column));
|
|
276
|
+
const primaryKeyConstraint = buildPrimaryKeyConstraint(primaryKeys);
|
|
277
|
+
const createTableSQL = `CREATE TABLE ${name} (
|
|
278
|
+
${[...columnDefs, primaryKeyConstraint].filter(Boolean).join(",\n ")}
|
|
279
|
+
);`;
|
|
280
|
+
return {
|
|
281
|
+
indexes: buildIndexStatements(name, indexes),
|
|
282
|
+
schema: buildZodSchema(columns),
|
|
283
|
+
table: createTableSQL
|
|
284
|
+
};
|
|
285
|
+
}
|
|
286
|
+
//#endregion
|
|
287
|
+
export { createTable };
|
package/package.json
CHANGED
|
@@ -1,14 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "zod-sqlite",
|
|
3
|
-
"
|
|
4
|
-
"
|
|
3
|
+
"type": "module",
|
|
4
|
+
"version": "1.0.3",
|
|
5
5
|
"private": false,
|
|
6
|
-
"
|
|
7
|
-
|
|
8
|
-
"email": "favor.emeka@minibase.com",
|
|
9
|
-
"url": "https://github.com/favorodera"
|
|
10
|
-
},
|
|
6
|
+
"description": "Generate type-safe SQLite table schemas from Zod validation schemas.",
|
|
7
|
+
"author": "Favour Emeka <favorodera@gmail.com>",
|
|
11
8
|
"license": "MIT",
|
|
9
|
+
"funding": "https://github.com/sponsors/favorodera",
|
|
10
|
+
"homepage": "https://github.com/favorodera/zod-sqlite#readme",
|
|
12
11
|
"repository": {
|
|
13
12
|
"type": "git",
|
|
14
13
|
"url": "git+https://github.com/favorodera/zod-sqlite.git"
|
|
@@ -16,67 +15,51 @@
|
|
|
16
15
|
"bugs": {
|
|
17
16
|
"url": "https://github.com/favorodera/zod-sqlite/issues"
|
|
18
17
|
},
|
|
19
|
-
"
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
18
|
+
"keywords": [
|
|
19
|
+
"zod",
|
|
20
|
+
"sqlite",
|
|
21
|
+
"database",
|
|
22
|
+
"schema",
|
|
23
|
+
"validation",
|
|
24
|
+
"zod-to-sqlite"
|
|
25
|
+
],
|
|
26
|
+
"sideEffects": false,
|
|
24
27
|
"exports": {
|
|
25
|
-
".":
|
|
26
|
-
"import": {
|
|
27
|
-
"types": "./dist/index.d.ts",
|
|
28
|
-
"default": "./dist/index.js"
|
|
29
|
-
},
|
|
30
|
-
"require": {
|
|
31
|
-
"types": "./dist/index.d.cts",
|
|
32
|
-
"default": "./dist/index.cjs"
|
|
33
|
-
}
|
|
34
|
-
},
|
|
28
|
+
".": "./dist/index.mjs",
|
|
35
29
|
"./package.json": "./package.json"
|
|
36
30
|
},
|
|
37
31
|
"files": [
|
|
38
|
-
"dist"
|
|
39
|
-
"README.md",
|
|
40
|
-
"LICENSE"
|
|
32
|
+
"dist"
|
|
41
33
|
],
|
|
42
|
-
"sideEffects": false,
|
|
43
|
-
"devDependencies": {
|
|
44
|
-
"@changesets/cli": "^2.29.8",
|
|
45
|
-
"@stylistic/eslint-plugin": "^5.6.1",
|
|
46
|
-
"@typescript-eslint/eslint-plugin": "^8.51.0",
|
|
47
|
-
"@typescript-eslint/parser": "^8.51.0",
|
|
48
|
-
"@vitest/ui": "^4.0.16",
|
|
49
|
-
"db0": "^0.3.4",
|
|
50
|
-
"eslint": "^9.39.2",
|
|
51
|
-
"tsup": "^8.5.1",
|
|
52
|
-
"typescript": "^5.9.3",
|
|
53
|
-
"vitest": "^4.0.16"
|
|
54
|
-
},
|
|
55
34
|
"publishConfig": {
|
|
56
35
|
"access": "public"
|
|
57
36
|
},
|
|
58
37
|
"engines": {
|
|
59
|
-
"node": ">=
|
|
38
|
+
"node": ">=22.0.0",
|
|
39
|
+
"pnpm": ">=11.0.0"
|
|
60
40
|
},
|
|
61
41
|
"dependencies": {
|
|
62
|
-
"zod": "^4.3
|
|
42
|
+
"zod": "^4.4.3"
|
|
43
|
+
},
|
|
44
|
+
"devDependencies": {
|
|
45
|
+
"@favorodera/eslint-config": "^1.0.0",
|
|
46
|
+
"@types/node": "^25.6.2",
|
|
47
|
+
"@typescript/native-preview": "7.0.0-dev.20260509.2",
|
|
48
|
+
"@vitest/ui": "4.1.8",
|
|
49
|
+
"db0": "^0.3.4",
|
|
50
|
+
"eslint": "^10.4.1",
|
|
51
|
+
"relizy": "^1.4.9",
|
|
52
|
+
"tsdown": "^0.22.0",
|
|
53
|
+
"typescript": "^6.0.3",
|
|
54
|
+
"vitest": "^4.1.5"
|
|
63
55
|
},
|
|
64
|
-
"keywords": [
|
|
65
|
-
"zod",
|
|
66
|
-
"sqlite",
|
|
67
|
-
"database",
|
|
68
|
-
"schema",
|
|
69
|
-
"validation",
|
|
70
|
-
"zod-to-sqlite"
|
|
71
|
-
],
|
|
72
56
|
"scripts": {
|
|
73
|
-
"build": "
|
|
74
|
-
"dev": "
|
|
75
|
-
"test": "vitest",
|
|
57
|
+
"build": "tsdown",
|
|
58
|
+
"dev": "tsdown --watch",
|
|
59
|
+
"test": "vitest run",
|
|
60
|
+
"test:watch": "vitest --watch --ui",
|
|
76
61
|
"typecheck": "tsc --noEmit",
|
|
77
|
-
"lint": "eslint
|
|
78
|
-
"
|
|
79
|
-
"ci:release": "pnpm build && pnpm dlx @changesets/cli publish",
|
|
80
|
-
"ci:version": "pnpm dlx @changesets/cli version && pnpm install --no-frozen-lockfile"
|
|
62
|
+
"lint": "eslint . --fix",
|
|
63
|
+
"ready": "pnpm install && pnpm build && pnpm lint && pnpm typecheck && pnpm test"
|
|
81
64
|
}
|
|
82
65
|
}
|
package/dist/index.cjs
DELETED
|
@@ -1,255 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
require('zod/v4/core');
|
|
4
|
-
var zod = require('zod');
|
|
5
|
-
|
|
6
|
-
// src/utils/format-check-constraint.ts
|
|
7
|
-
function formatCheckConstraint(name, schema) {
|
|
8
|
-
let currentSchema = schema;
|
|
9
|
-
while (true) {
|
|
10
|
-
const def = currentSchema._zod.def;
|
|
11
|
-
if (def.type === "nullable" || def.type === "optional" || def.type === "default") {
|
|
12
|
-
currentSchema = def.innerType;
|
|
13
|
-
} else {
|
|
14
|
-
break;
|
|
15
|
-
}
|
|
16
|
-
}
|
|
17
|
-
const definition = currentSchema._zod.def;
|
|
18
|
-
const zodType = definition.type;
|
|
19
|
-
switch (zodType) {
|
|
20
|
-
case "enum": {
|
|
21
|
-
const entries = definition.entries;
|
|
22
|
-
const values = Object.values(entries);
|
|
23
|
-
const quotedValues = values.map((value) => `'${String(value).replace(/'/g, "''")}'`).join(", ");
|
|
24
|
-
return `CHECK(${name} IN (${quotedValues}))`;
|
|
25
|
-
}
|
|
26
|
-
case "literal": {
|
|
27
|
-
const values = definition.values;
|
|
28
|
-
if (values.length === 1) {
|
|
29
|
-
const value = values[0];
|
|
30
|
-
if (typeof value === "string") {
|
|
31
|
-
return `CHECK(${name} = '${value.replace(/'/g, "''")}')`;
|
|
32
|
-
}
|
|
33
|
-
return `CHECK(${name} = ${value})`;
|
|
34
|
-
}
|
|
35
|
-
const quotedValues = values.map((value) => {
|
|
36
|
-
if (typeof value === "string") {
|
|
37
|
-
return `'${value.replace(/'/g, "''")}'`;
|
|
38
|
-
}
|
|
39
|
-
return String(value);
|
|
40
|
-
}).join(", ");
|
|
41
|
-
return `CHECK(${name} IN (${quotedValues}))`;
|
|
42
|
-
}
|
|
43
|
-
case "union": {
|
|
44
|
-
const options = definition.options;
|
|
45
|
-
const allAreLiterals = options.every((option) => option._zod.def.type === "literal");
|
|
46
|
-
if (!allAreLiterals) return null;
|
|
47
|
-
const values = [];
|
|
48
|
-
for (const option of options) {
|
|
49
|
-
values.push(...option._zod.def.values);
|
|
50
|
-
}
|
|
51
|
-
const quotedValues = values.map((value) => {
|
|
52
|
-
if (typeof value === "string") {
|
|
53
|
-
return `'${value.replace(/'/g, "''")}'`;
|
|
54
|
-
}
|
|
55
|
-
return String(value);
|
|
56
|
-
}).join(", ");
|
|
57
|
-
return `CHECK(${name} IN (${quotedValues}))`;
|
|
58
|
-
}
|
|
59
|
-
case "number": {
|
|
60
|
-
const checks = definition.checks;
|
|
61
|
-
const constraints = [];
|
|
62
|
-
if (!checks) return null;
|
|
63
|
-
for (const check of checks) {
|
|
64
|
-
const checkParameters = check._zod.def.check;
|
|
65
|
-
const checkValue = check._zod.def.value;
|
|
66
|
-
switch (checkParameters) {
|
|
67
|
-
case "greater_than":
|
|
68
|
-
constraints.push(`${name} >= ${checkValue}`);
|
|
69
|
-
break;
|
|
70
|
-
case "less_than":
|
|
71
|
-
constraints.push(`${name} <= ${checkValue}`);
|
|
72
|
-
break;
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
return constraints.length > 0 ? `CHECK(${constraints.join(" AND ")})` : null;
|
|
76
|
-
}
|
|
77
|
-
case "string": {
|
|
78
|
-
const checks = definition.checks;
|
|
79
|
-
const constraints = [];
|
|
80
|
-
if (!checks) return null;
|
|
81
|
-
for (const check of checks) {
|
|
82
|
-
const checkParameters = check._zod.def.check;
|
|
83
|
-
const checkDefinition = check._zod.def;
|
|
84
|
-
switch (checkParameters) {
|
|
85
|
-
case "min_length":
|
|
86
|
-
constraints.push(`length(${name}) >= ${checkDefinition.minimum}`);
|
|
87
|
-
break;
|
|
88
|
-
case "max_length":
|
|
89
|
-
constraints.push(`length(${name}) <= ${checkDefinition.maximum}`);
|
|
90
|
-
break;
|
|
91
|
-
case "length_equals":
|
|
92
|
-
constraints.push(`length(${name}) = ${checkDefinition.length}`);
|
|
93
|
-
break;
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
|
-
return constraints.length > 0 ? `CHECK(${constraints.join(" AND ")})` : null;
|
|
97
|
-
}
|
|
98
|
-
default:
|
|
99
|
-
return null;
|
|
100
|
-
}
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
// src/utils/format-default-value.ts
|
|
104
|
-
function formatDefaultValue(value, SQLiteType) {
|
|
105
|
-
switch (SQLiteType) {
|
|
106
|
-
case "TEXT":
|
|
107
|
-
return `DEFAULT '${String(value).replace(/'/g, "''")}'`;
|
|
108
|
-
case "INTEGER":
|
|
109
|
-
case "REAL":
|
|
110
|
-
return `DEFAULT ${Number(value)}`;
|
|
111
|
-
case "BOOLEAN":
|
|
112
|
-
return `DEFAULT ${Boolean(value) ? 1 : 0}`;
|
|
113
|
-
case "NULL":
|
|
114
|
-
return "DEFAULT NULL";
|
|
115
|
-
default:
|
|
116
|
-
return `DEFAULT '${value}'`;
|
|
117
|
-
}
|
|
118
|
-
}
|
|
119
|
-
function mapZodTypeToSQLite(zodType, schema) {
|
|
120
|
-
switch (zodType) {
|
|
121
|
-
case "string": {
|
|
122
|
-
const format = schema._zod.def.format;
|
|
123
|
-
switch (format) {
|
|
124
|
-
case "date":
|
|
125
|
-
return "DATE";
|
|
126
|
-
case "datetime":
|
|
127
|
-
return "DATETIME";
|
|
128
|
-
case "duration":
|
|
129
|
-
return "INTEGER";
|
|
130
|
-
default:
|
|
131
|
-
return "TEXT";
|
|
132
|
-
}
|
|
133
|
-
}
|
|
134
|
-
case "date":
|
|
135
|
-
return "DATE";
|
|
136
|
-
case "enum":
|
|
137
|
-
case "literal":
|
|
138
|
-
case "template_literal":
|
|
139
|
-
case "array":
|
|
140
|
-
case "object":
|
|
141
|
-
return "TEXT";
|
|
142
|
-
case "number": {
|
|
143
|
-
const format = schema._zod.def.format;
|
|
144
|
-
switch (format) {
|
|
145
|
-
case "safeint":
|
|
146
|
-
case "uint32":
|
|
147
|
-
case "int32":
|
|
148
|
-
return "INTEGER";
|
|
149
|
-
case "float32":
|
|
150
|
-
case "float64":
|
|
151
|
-
return "FLOAT";
|
|
152
|
-
default:
|
|
153
|
-
return "REAL";
|
|
154
|
-
}
|
|
155
|
-
}
|
|
156
|
-
case "boolean":
|
|
157
|
-
return "BOOLEAN";
|
|
158
|
-
case "bigint":
|
|
159
|
-
return "BIGINT";
|
|
160
|
-
case "null":
|
|
161
|
-
case "undefined":
|
|
162
|
-
return "NULL";
|
|
163
|
-
case "file":
|
|
164
|
-
return "BLOB";
|
|
165
|
-
default:
|
|
166
|
-
return "TEXT";
|
|
167
|
-
}
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
// src/utils/zod-to-sqlite.ts
|
|
171
|
-
function zodToSQLite(schema) {
|
|
172
|
-
let nullable = false;
|
|
173
|
-
let defaultValue = void 0;
|
|
174
|
-
let currentSchema = schema;
|
|
175
|
-
while (true) {
|
|
176
|
-
const definition = currentSchema._zod.def;
|
|
177
|
-
const zodType = definition.type;
|
|
178
|
-
if (zodType === "nullable" || zodType === "optional") {
|
|
179
|
-
nullable = true;
|
|
180
|
-
currentSchema = definition.innerType;
|
|
181
|
-
} else if (zodType === "default") {
|
|
182
|
-
defaultValue = typeof definition.defaultValue === "function" ? definition.defaultValue() : definition.defaultValue;
|
|
183
|
-
currentSchema = definition.innerType;
|
|
184
|
-
} else {
|
|
185
|
-
break;
|
|
186
|
-
}
|
|
187
|
-
}
|
|
188
|
-
const mainType = currentSchema._zod.def.type;
|
|
189
|
-
const SQLiteType = mapZodTypeToSQLite(mainType, currentSchema);
|
|
190
|
-
return { SQLiteType, nullable, defaultValue, schema };
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
// src/core/column-definitions.ts
|
|
194
|
-
function buildColumnDefinition(column) {
|
|
195
|
-
const { name, schema, unique, references } = column;
|
|
196
|
-
const { SQLiteType, nullable, defaultValue } = zodToSQLite(schema);
|
|
197
|
-
const parts = [name, SQLiteType];
|
|
198
|
-
if (!nullable) parts.push("NOT NULL");
|
|
199
|
-
if (defaultValue !== void 0) parts.push(formatDefaultValue(defaultValue, SQLiteType));
|
|
200
|
-
if (unique) parts.push("UNIQUE");
|
|
201
|
-
const checkConstraint = formatCheckConstraint(name, schema);
|
|
202
|
-
if (checkConstraint) parts.push(checkConstraint);
|
|
203
|
-
if (references) {
|
|
204
|
-
const { table, column: refColumn, onDelete, onUpdate } = references;
|
|
205
|
-
parts.push(`REFERENCES ${table}(${refColumn})`);
|
|
206
|
-
if (onDelete) parts.push(`ON DELETE ${onDelete}`);
|
|
207
|
-
if (onUpdate) parts.push(`ON UPDATE ${onUpdate}`);
|
|
208
|
-
}
|
|
209
|
-
return parts.join(" ");
|
|
210
|
-
}
|
|
211
|
-
|
|
212
|
-
// src/core/index-statements.ts
|
|
213
|
-
function buildIndexStatements(tableName, indexes) {
|
|
214
|
-
if (!indexes || indexes.length === 0) return [];
|
|
215
|
-
return indexes.map((index) => {
|
|
216
|
-
const uniqueClause = index.unique ? "UNIQUE " : "";
|
|
217
|
-
const whereClause = index.where ? ` WHERE ${index.where}` : "";
|
|
218
|
-
return `CREATE ${uniqueClause}INDEX ${index.name} ON ${tableName} (${index.columns.join(", ")})${whereClause};`;
|
|
219
|
-
});
|
|
220
|
-
}
|
|
221
|
-
|
|
222
|
-
// src/core/primary-key-constraint.ts
|
|
223
|
-
function buildPrimaryKeyConstraint(primaryKeys) {
|
|
224
|
-
if (primaryKeys.length === 0) return "";
|
|
225
|
-
return `PRIMARY KEY (${primaryKeys.join(", ")})`;
|
|
226
|
-
}
|
|
227
|
-
function buildZodSchema(columns) {
|
|
228
|
-
const schemaShape = {};
|
|
229
|
-
for (const column of columns) {
|
|
230
|
-
schemaShape[column.name] = column.schema;
|
|
231
|
-
}
|
|
232
|
-
return zod.z.object(schemaShape);
|
|
233
|
-
}
|
|
234
|
-
|
|
235
|
-
// src/core/table.ts
|
|
236
|
-
function createTable(config) {
|
|
237
|
-
const { name, columns, primaryKeys, indexes } = config;
|
|
238
|
-
const columnDefs = columns.map(buildColumnDefinition);
|
|
239
|
-
const primaryKeyConstraint = buildPrimaryKeyConstraint(primaryKeys);
|
|
240
|
-
const tableElements = [...columnDefs, primaryKeyConstraint].filter(Boolean);
|
|
241
|
-
const createTableSQL = `CREATE TABLE ${name} (
|
|
242
|
-
${tableElements.join(",\n ")}
|
|
243
|
-
);`;
|
|
244
|
-
const createIndexesSQL = buildIndexStatements(name, indexes);
|
|
245
|
-
const zodSchema = buildZodSchema(columns);
|
|
246
|
-
return {
|
|
247
|
-
table: createTableSQL,
|
|
248
|
-
indexes: createIndexesSQL,
|
|
249
|
-
schema: zodSchema
|
|
250
|
-
};
|
|
251
|
-
}
|
|
252
|
-
|
|
253
|
-
exports.createTable = createTable;
|
|
254
|
-
//# sourceMappingURL=index.cjs.map
|
|
255
|
-
//# sourceMappingURL=index.cjs.map
|