shapecraft 1.0.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/CLAUDE.md +227 -0
- package/README.md +22 -0
- package/apps/cli/node_modules/.bin/prettier +21 -0
- package/apps/cli/node_modules/.bin/tsc +21 -0
- package/apps/cli/node_modules/.bin/tsserver +21 -0
- package/apps/cli/node_modules/.bin/tsx +21 -0
- package/apps/cli/node_modules/.bin/vitest +21 -0
- package/apps/cli/package.json +47 -0
- package/apps/cli/src/index.ts +98 -0
- package/apps/cli/tsconfig.cjs.json +10 -0
- package/apps/cli/tsconfig.esm.json +10 -0
- package/apps/cli/tsconfig.json +22 -0
- package/package.json +16 -0
- package/packages/core/node_modules/.bin/prettier +21 -0
- package/packages/core/node_modules/.bin/tsc +21 -0
- package/packages/core/node_modules/.bin/tsserver +21 -0
- package/packages/core/node_modules/.bin/tsx +21 -0
- package/packages/core/node_modules/.bin/vitest +21 -0
- package/packages/core/node_modules/.vite/vitest/da39a3ee5e6b4b0d3255bfef95601890afd80709/results.json +1 -0
- package/packages/core/package.json +44 -0
- package/packages/core/src/common/array.test.ts +19 -0
- package/packages/core/src/common/array.ts +15 -0
- package/packages/core/src/common/index.ts +5 -0
- package/packages/core/src/common/is.ts +23 -0
- package/packages/core/src/common/object.ts +35 -0
- package/packages/core/src/common/phantom.ts +1 -0
- package/packages/core/src/common/result.ts +43 -0
- package/packages/core/src/common/string.ts +28 -0
- package/packages/core/src/common/types.ts +34 -0
- package/packages/core/src/index.ts +1 -0
- package/packages/core/src/shape/annotate.ts +139 -0
- package/packages/core/src/shape/annotation.ts +47 -0
- package/packages/core/src/shape/base.ts +71 -0
- package/packages/core/src/shape/builder.test.ts +728 -0
- package/packages/core/src/shape/builder.ts +475 -0
- package/packages/core/src/shape/error.ts +4 -0
- package/packages/core/src/shape/index.ts +3 -0
- package/packages/core/src/shape/number.ts +118 -0
- package/packages/core/src/shape/shape.test.ts +792 -0
- package/packages/core/src/shape/shape.ts +377 -0
- package/packages/core/src/shape/tags.ts +14 -0
- package/packages/core/src/shape/transforms/index.ts +3 -0
- package/packages/core/src/shape/transforms/json-schema/index.ts +2 -0
- package/packages/core/src/shape/transforms/json-schema/transform.test.ts +850 -0
- package/packages/core/src/shape/transforms/json-schema/transform.ts +882 -0
- package/packages/core/src/shape/transforms/json-schema/types.ts +132 -0
- package/packages/core/src/shape/transforms/sql/dialects/dialect.ts +89 -0
- package/packages/core/src/shape/transforms/sql/dialects/index.ts +14 -0
- package/packages/core/src/shape/transforms/sql/dialects/postgres.ts +392 -0
- package/packages/core/src/shape/transforms/sql/dialects/sqlite.ts +333 -0
- package/packages/core/src/shape/transforms/sql/from-sql.test.ts +704 -0
- package/packages/core/src/shape/transforms/sql/from-sql.ts +210 -0
- package/packages/core/src/shape/transforms/sql/index.ts +3 -0
- package/packages/core/src/shape/transforms/sql/options.ts +6 -0
- package/packages/core/src/shape/transforms/sql/parser/check-decoder.ts +457 -0
- package/packages/core/src/shape/transforms/sql/parser/create-domain.ts +105 -0
- package/packages/core/src/shape/transforms/sql/parser/create-table.ts +809 -0
- package/packages/core/src/shape/transforms/sql/parser/create-type.ts +91 -0
- package/packages/core/src/shape/transforms/sql/parser/cursor.ts +179 -0
- package/packages/core/src/shape/transforms/sql/parser/default-decoder.ts +129 -0
- package/packages/core/src/shape/transforms/sql/parser/lexer.ts +289 -0
- package/packages/core/src/shape/transforms/sql/parser/pg-types.ts +247 -0
- package/packages/core/src/shape/transforms/sql/parser/sqlite-types.ts +103 -0
- package/packages/core/src/shape/transforms/sql/parser/statements.ts +127 -0
- package/packages/core/src/shape/transforms/sql/parser/type-spec.ts +159 -0
- package/packages/core/src/shape/transforms/sql/transform.sqlite.test.ts +448 -0
- package/packages/core/src/shape/transforms/sql/transform.test.ts +880 -0
- package/packages/core/src/shape/transforms/sql/transform.ts +295 -0
- package/packages/core/src/shape/transforms/typescript/index.ts +1 -0
- package/packages/core/src/shape/transforms/typescript/transform.ts +211 -0
- package/packages/core/src/shape/tuple.test.ts +171 -0
- package/packages/core/src/shape/validate.ts +413 -0
- package/packages/core/tsconfig.cjs.json +11 -0
- package/packages/core/tsconfig.esm.json +10 -0
- package/packages/core/tsconfig.json +23 -0
- package/packages/samples/node_modules/.bin/prettier +21 -0
- package/packages/samples/node_modules/.bin/tsc +21 -0
- package/packages/samples/node_modules/.bin/tsserver +21 -0
- package/packages/samples/node_modules/.bin/tsx +21 -0
- package/packages/samples/node_modules/.bin/vitest +21 -0
- package/packages/samples/package.json +47 -0
- package/packages/samples/src/blog.ts +49 -0
- package/packages/samples/src/config.ts +50 -0
- package/packages/samples/src/ecommerce.ts +65 -0
- package/packages/samples/src/embeddings.ts +43 -0
- package/packages/samples/src/events.ts +52 -0
- package/packages/samples/src/geometry.ts +62 -0
- package/packages/samples/src/index.ts +9 -0
- package/packages/samples/src/relational.ts +17 -0
- package/packages/samples/src/tuples.ts +67 -0
- package/packages/samples/src/user.ts +9 -0
- package/packages/samples/tsconfig.cjs.json +11 -0
- package/packages/samples/tsconfig.esm.json +10 -0
- package/packages/samples/tsconfig.json +23 -0
- package/pnpm-workspace.yaml +3 -0
- package/test-data/json-schema/address.json +35 -0
- package/test-data/json-schema/array-of-things.json +36 -0
- package/test-data/json-schema/basic.json +21 -0
- package/test-data/json-schema/blog-post.json +29 -0
- package/test-data/json-schema/calendar.json +48 -0
- package/test-data/json-schema/complex-object-with-nested-properties.json +41 -0
- package/test-data/json-schema/ecommerce-complex.json +344 -0
- package/test-data/json-schema/ecommerce-system.json +27 -0
- package/test-data/json-schema/enumerated-values.json +11 -0
- package/test-data/json-schema/fstab-entry.json +92 -0
- package/test-data/json-schema/geographical-location.json +20 -0
- package/test-data/json-schema/health-record.json +41 -0
- package/test-data/json-schema/job-posting.json +33 -0
- package/test-data/json-schema/movie.json +35 -0
- package/test-data/json-schema/regular-expression-pattern.json +12 -0
- package/test-data/json-schema/user-profile.json +33 -0
- package/test-data/sql/ecommerce.sql +641 -0
|
@@ -0,0 +1,333 @@
|
|
|
1
|
+
import { R } from "../../../../common/result";
|
|
2
|
+
import { shapes } from "../../../shape";
|
|
3
|
+
import { NumberTag } from "../../../tags";
|
|
4
|
+
import {
|
|
5
|
+
ColumnDef,
|
|
6
|
+
Dialect,
|
|
7
|
+
FormatDefault,
|
|
8
|
+
Prelude,
|
|
9
|
+
quoteIdent,
|
|
10
|
+
quoteLit,
|
|
11
|
+
TypeRendering,
|
|
12
|
+
} from "./dialect";
|
|
13
|
+
|
|
14
|
+
const INT_RANGES: Record<string, { minimum?: number; maximum?: number }> = {
|
|
15
|
+
int8: { minimum: -128, maximum: 127 },
|
|
16
|
+
uint8: { minimum: 0, maximum: 255 },
|
|
17
|
+
int16: { minimum: -32768, maximum: 32767 },
|
|
18
|
+
uint16: { minimum: 0, maximum: 65535 },
|
|
19
|
+
int32: { minimum: -2_147_483_648, maximum: 2_147_483_647 },
|
|
20
|
+
uint32: { minimum: 0, maximum: 4_294_967_295 },
|
|
21
|
+
uint64: { minimum: 0 },
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
const INT_TAGS = new Set([
|
|
25
|
+
"int",
|
|
26
|
+
"int8",
|
|
27
|
+
"uint8",
|
|
28
|
+
"int16",
|
|
29
|
+
"uint16",
|
|
30
|
+
"int32",
|
|
31
|
+
"uint32",
|
|
32
|
+
"int64",
|
|
33
|
+
"uint64",
|
|
34
|
+
]);
|
|
35
|
+
|
|
36
|
+
const isIntTag = (tag: NumberTag): boolean => INT_TAGS.has(tag);
|
|
37
|
+
|
|
38
|
+
// SQLite's INTEGER affinity stores values up to 8 bytes (signed 64-bit). We
|
|
39
|
+
// model its natural range so the int-tag-range intersection logic only emits
|
|
40
|
+
// CHECKs when the tag's range is tighter than SQLite's.
|
|
41
|
+
const SQLITE_INTEGER_MIN = -9_223_372_036_854_775_808;
|
|
42
|
+
const SQLITE_INTEGER_MAX = 9_223_372_036_854_775_807;
|
|
43
|
+
|
|
44
|
+
const formatNumberLit = (n: number): string => {
|
|
45
|
+
if (!isFinite(n)) return quoteLit(String(n));
|
|
46
|
+
return String(n);
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
const unionEnumValues = (u: shapes.ShapeUnion): string[] | null => {
|
|
50
|
+
const variants = Array.from(u.input) as shapes.Shape[];
|
|
51
|
+
if (variants.length === 0) return null;
|
|
52
|
+
const values: string[] = [];
|
|
53
|
+
for (const v of variants) {
|
|
54
|
+
if (v.type !== "string" || v.literal !== true) return null;
|
|
55
|
+
values.push(v.input as string);
|
|
56
|
+
}
|
|
57
|
+
return values;
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
const renderType = (
|
|
61
|
+
name: string,
|
|
62
|
+
shape: shapes.Shape,
|
|
63
|
+
): R.Result<TypeRendering, string[]> => {
|
|
64
|
+
const errors: string[] = [];
|
|
65
|
+
const prelude: Prelude[] = [];
|
|
66
|
+
const checks: string[] = [];
|
|
67
|
+
let sqlType: string | null = null;
|
|
68
|
+
|
|
69
|
+
const col = quoteIdent(name);
|
|
70
|
+
|
|
71
|
+
if (shape.type === "union") {
|
|
72
|
+
const values = unionEnumValues(shape);
|
|
73
|
+
if (values !== null) {
|
|
74
|
+
sqlType = "TEXT";
|
|
75
|
+
checks.push(`${col} IN (${values.map(quoteLit).join(", ")})`);
|
|
76
|
+
} else {
|
|
77
|
+
sqlType = "TEXT";
|
|
78
|
+
checks.push(`json_valid(${col})`);
|
|
79
|
+
}
|
|
80
|
+
} else {
|
|
81
|
+
switch (shape.type) {
|
|
82
|
+
case "string": {
|
|
83
|
+
sqlType = "TEXT";
|
|
84
|
+
if (shape.literal) {
|
|
85
|
+
checks.push(`${col} = ${quoteLit(shape.input as string)}`);
|
|
86
|
+
} else {
|
|
87
|
+
if (shape.anno.max !== undefined)
|
|
88
|
+
checks.push(`length(${col}) <= ${shape.anno.max}`);
|
|
89
|
+
if (shape.anno.min !== undefined)
|
|
90
|
+
checks.push(`length(${col}) >= ${shape.anno.min}`);
|
|
91
|
+
if (shape.anno.pattern !== undefined) {
|
|
92
|
+
const src =
|
|
93
|
+
shape.anno.pattern instanceof RegExp ?
|
|
94
|
+
shape.anno.pattern.source
|
|
95
|
+
: shape.anno.pattern;
|
|
96
|
+
checks.push(`${col} REGEXP ${quoteLit(src)}`);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
break;
|
|
100
|
+
}
|
|
101
|
+
case "boolean": {
|
|
102
|
+
sqlType = "INTEGER";
|
|
103
|
+
if (shape.literal) {
|
|
104
|
+
const v = shape.input as boolean;
|
|
105
|
+
checks.push(`${col} = ${v ? "1" : "0"}`);
|
|
106
|
+
} else {
|
|
107
|
+
checks.push(`${col} IN (0, 1)`);
|
|
108
|
+
}
|
|
109
|
+
break;
|
|
110
|
+
}
|
|
111
|
+
case "number": {
|
|
112
|
+
if (shape.literal) {
|
|
113
|
+
sqlType = isIntTag(shape.tag) ? "INTEGER" : "REAL";
|
|
114
|
+
checks.push(`${col} = ${formatNumberLit(shape.input as number)}`);
|
|
115
|
+
} else if (isIntTag(shape.tag)) {
|
|
116
|
+
sqlType = "INTEGER";
|
|
117
|
+
const natural = INT_RANGES[shape.tag];
|
|
118
|
+
let effMin: number | undefined = natural?.minimum;
|
|
119
|
+
let effMax: number | undefined = natural?.maximum;
|
|
120
|
+
if (shape.anno.min !== undefined) {
|
|
121
|
+
effMin =
|
|
122
|
+
effMin === undefined ?
|
|
123
|
+
shape.anno.min
|
|
124
|
+
: Math.max(effMin, shape.anno.min);
|
|
125
|
+
}
|
|
126
|
+
if (shape.anno.max !== undefined) {
|
|
127
|
+
effMax =
|
|
128
|
+
effMax === undefined ?
|
|
129
|
+
shape.anno.max
|
|
130
|
+
: Math.min(effMax, shape.anno.max);
|
|
131
|
+
}
|
|
132
|
+
if (effMin !== undefined && effMin > SQLITE_INTEGER_MIN) {
|
|
133
|
+
checks.push(`${col} >= ${effMin}`);
|
|
134
|
+
}
|
|
135
|
+
if (effMax !== undefined && effMax < SQLITE_INTEGER_MAX) {
|
|
136
|
+
checks.push(`${col} <= ${effMax}`);
|
|
137
|
+
}
|
|
138
|
+
} else {
|
|
139
|
+
sqlType = "REAL";
|
|
140
|
+
if (shape.anno.min !== undefined)
|
|
141
|
+
checks.push(`${col} >= ${shape.anno.min}`);
|
|
142
|
+
if (shape.anno.max !== undefined)
|
|
143
|
+
checks.push(`${col} <= ${shape.anno.max}`);
|
|
144
|
+
}
|
|
145
|
+
break;
|
|
146
|
+
}
|
|
147
|
+
case "date":
|
|
148
|
+
sqlType = "TEXT";
|
|
149
|
+
break;
|
|
150
|
+
case "binary":
|
|
151
|
+
sqlType = "BLOB";
|
|
152
|
+
break;
|
|
153
|
+
case "unknown":
|
|
154
|
+
sqlType = "TEXT";
|
|
155
|
+
checks.push(`json_valid(${col})`);
|
|
156
|
+
break;
|
|
157
|
+
case "nil":
|
|
158
|
+
errors.push(`field '${name}': nil cannot be a column`);
|
|
159
|
+
break;
|
|
160
|
+
case "undefined":
|
|
161
|
+
errors.push(`field '${name}': undefined cannot be a column`);
|
|
162
|
+
break;
|
|
163
|
+
case "array": {
|
|
164
|
+
sqlType = "TEXT";
|
|
165
|
+
checks.push(`json_valid(${col})`);
|
|
166
|
+
if (shape.anno.min !== undefined)
|
|
167
|
+
checks.push(`json_array_length(${col}) >= ${shape.anno.min}`);
|
|
168
|
+
if (shape.anno.max !== undefined)
|
|
169
|
+
checks.push(`json_array_length(${col}) <= ${shape.anno.max}`);
|
|
170
|
+
if (shape.anno.uniqueItems === true) {
|
|
171
|
+
checks.push(
|
|
172
|
+
`(SELECT COUNT(*) FROM json_each(${col})) = (SELECT COUNT(DISTINCT value) FROM json_each(${col}))`,
|
|
173
|
+
);
|
|
174
|
+
}
|
|
175
|
+
break;
|
|
176
|
+
}
|
|
177
|
+
case "vector": {
|
|
178
|
+
sqlType = "BLOB";
|
|
179
|
+
checks.push(`length(${col}) = ${shape.input.dims * 4}`);
|
|
180
|
+
break;
|
|
181
|
+
}
|
|
182
|
+
case "range": {
|
|
183
|
+
sqlType = "TEXT";
|
|
184
|
+
checks.push(`json_valid(${col})`);
|
|
185
|
+
break;
|
|
186
|
+
}
|
|
187
|
+
case "mapping":
|
|
188
|
+
case "record":
|
|
189
|
+
sqlType = "TEXT";
|
|
190
|
+
checks.push(`json_valid(${col})`);
|
|
191
|
+
break;
|
|
192
|
+
case "tuple": {
|
|
193
|
+
sqlType = "TEXT";
|
|
194
|
+
const len = shape.input.length;
|
|
195
|
+
checks.push(
|
|
196
|
+
`json_valid(${col}) AND json_array_length(${col}) = ${len}`,
|
|
197
|
+
);
|
|
198
|
+
break;
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
if (sqlType === null) {
|
|
204
|
+
return R.err(errors);
|
|
205
|
+
}
|
|
206
|
+
if (errors.length > 0) return R.err(errors);
|
|
207
|
+
|
|
208
|
+
return R.ok({ type: sqlType, checks, prelude });
|
|
209
|
+
};
|
|
210
|
+
|
|
211
|
+
const formatDefault = (v: unknown, _columnType: string): FormatDefault => {
|
|
212
|
+
if (v === null) return { ok: true, expr: "NULL" };
|
|
213
|
+
if (typeof v === "string") return { ok: true, expr: quoteLit(v) };
|
|
214
|
+
if (typeof v === "number") return { ok: true, expr: formatNumberLit(v) };
|
|
215
|
+
if (typeof v === "boolean") return { ok: true, expr: v ? "1" : "0" };
|
|
216
|
+
if (v instanceof Date) return { ok: true, expr: quoteLit(v.toISOString()) };
|
|
217
|
+
if (typeof v === "object") {
|
|
218
|
+
try {
|
|
219
|
+
return { ok: true, expr: quoteLit(JSON.stringify(v)) };
|
|
220
|
+
} catch {
|
|
221
|
+
return { ok: false, reason: "default value could not be JSON-encoded" };
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
return {
|
|
225
|
+
ok: false,
|
|
226
|
+
reason: `default value of type ${typeof v} is not supported`,
|
|
227
|
+
};
|
|
228
|
+
};
|
|
229
|
+
|
|
230
|
+
const applyAutoIncrement = (
|
|
231
|
+
name: string,
|
|
232
|
+
shape: shapes.Shape,
|
|
233
|
+
col: ColumnDef,
|
|
234
|
+
): string[] => {
|
|
235
|
+
if (shape.type !== "number" || !isIntTag(shape.tag)) {
|
|
236
|
+
return [`field '${name}': autoIncrement requires an integer type`];
|
|
237
|
+
}
|
|
238
|
+
if (shape.tag === "uint64") {
|
|
239
|
+
return [
|
|
240
|
+
`field '${name}': autoIncrement is not supported on uint64 in sqlite`,
|
|
241
|
+
];
|
|
242
|
+
}
|
|
243
|
+
// SQLite's AUTOINCREMENT only works with INTEGER PRIMARY KEY. Auto-promote
|
|
244
|
+
// to primary (per SQLite's INTEGER PRIMARY KEY auto-increment semantics)
|
|
245
|
+
// and force NOT NULL.
|
|
246
|
+
col.identity = true;
|
|
247
|
+
col.primary = true;
|
|
248
|
+
col.notNull = true;
|
|
249
|
+
return [];
|
|
250
|
+
};
|
|
251
|
+
|
|
252
|
+
const renderColumn = (c: ColumnDef): string => {
|
|
253
|
+
const parts: string[] = [quoteIdent(c.name)];
|
|
254
|
+
|
|
255
|
+
if (c.identity && c.primary) {
|
|
256
|
+
// INTEGER PRIMARY KEY AUTOINCREMENT must appear as a single contiguous
|
|
257
|
+
// column-level clause in SQLite. NOT NULL is implied; UNIQUE is implied.
|
|
258
|
+
parts.push("INTEGER", "PRIMARY", "KEY", "AUTOINCREMENT");
|
|
259
|
+
if (c.defaultExpr !== undefined) parts.push(`DEFAULT ${c.defaultExpr}`);
|
|
260
|
+
if (c.references !== undefined) parts.push(`REFERENCES ${c.references}`);
|
|
261
|
+
for (const chk of c.checks) parts.push(`CHECK (${chk})`);
|
|
262
|
+
return parts.join(" ");
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
parts.push(c.type);
|
|
266
|
+
|
|
267
|
+
if (c.generated !== undefined) {
|
|
268
|
+
parts.push(
|
|
269
|
+
`GENERATED ALWAYS AS (${c.generated.expression}) ${c.generated.stored ? "STORED" : "VIRTUAL"}`,
|
|
270
|
+
);
|
|
271
|
+
if (c.primary) parts.push("PRIMARY KEY");
|
|
272
|
+
if (c.unique) parts.push("UNIQUE");
|
|
273
|
+
if (c.references !== undefined) parts.push(`REFERENCES ${c.references}`);
|
|
274
|
+
for (const chk of c.checks) parts.push(`CHECK (${chk})`);
|
|
275
|
+
return parts.join(" ");
|
|
276
|
+
}
|
|
277
|
+
if (c.notNull) parts.push("NOT NULL");
|
|
278
|
+
if (c.primary) parts.push("PRIMARY KEY");
|
|
279
|
+
if (c.unique) parts.push("UNIQUE");
|
|
280
|
+
if (c.defaultExpr !== undefined) parts.push(`DEFAULT ${c.defaultExpr}`);
|
|
281
|
+
if (c.references !== undefined) parts.push(`REFERENCES ${c.references}`);
|
|
282
|
+
for (const chk of c.checks) parts.push(`CHECK (${chk})`);
|
|
283
|
+
return parts.join(" ");
|
|
284
|
+
};
|
|
285
|
+
|
|
286
|
+
const validateMappingAnno = (
|
|
287
|
+
anno: shapes.Shape["anno"],
|
|
288
|
+
title: string,
|
|
289
|
+
): string[] => {
|
|
290
|
+
const errors: string[] = [];
|
|
291
|
+
if (anno.schema !== undefined) {
|
|
292
|
+
errors.push(
|
|
293
|
+
`table '${title}': sqlite has no schemas; remove anno.schema or use dialect='postgres'`,
|
|
294
|
+
);
|
|
295
|
+
}
|
|
296
|
+
return errors;
|
|
297
|
+
};
|
|
298
|
+
|
|
299
|
+
const finalizeColumns = (cols: ColumnDef[]): string[] => {
|
|
300
|
+
const identityCols = cols.filter((c) => c.identity);
|
|
301
|
+
if (identityCols.length === 0) return [];
|
|
302
|
+
if (identityCols.length > 1) {
|
|
303
|
+
return [
|
|
304
|
+
`multiple autoIncrement columns are not supported in sqlite: ${identityCols
|
|
305
|
+
.map((c) => `'${c.name}'`)
|
|
306
|
+
.join(", ")}`,
|
|
307
|
+
];
|
|
308
|
+
}
|
|
309
|
+
const ai = identityCols[0]!;
|
|
310
|
+
const otherPrimaries = cols.filter((c) => c !== ai && c.primary);
|
|
311
|
+
if (otherPrimaries.length > 0) {
|
|
312
|
+
return [
|
|
313
|
+
`autoIncrement column '${ai.name}' must be the sole primary key in sqlite, but also: ${otherPrimaries
|
|
314
|
+
.map((c) => `'${c.name}'`)
|
|
315
|
+
.join(", ")}`,
|
|
316
|
+
];
|
|
317
|
+
}
|
|
318
|
+
return [];
|
|
319
|
+
};
|
|
320
|
+
|
|
321
|
+
export const sqliteDialect: Dialect = {
|
|
322
|
+
name: "sqlite",
|
|
323
|
+
supportsSchema: false,
|
|
324
|
+
tableTrailer: " STRICT",
|
|
325
|
+
renderType,
|
|
326
|
+
applyAutoIncrement,
|
|
327
|
+
formatDefault,
|
|
328
|
+
validateMappingAnno,
|
|
329
|
+
schemaPrelude: () => "",
|
|
330
|
+
qualifiedTable: (_schema, title) => quoteIdent(title),
|
|
331
|
+
renderColumn,
|
|
332
|
+
finalizeColumns,
|
|
333
|
+
};
|