@zauso-ai/capstan-db 0.1.2
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/dist/client.d.ts +22 -0
- package/dist/client.d.ts.map +1 -0
- package/dist/client.js +30 -0
- package/dist/client.js.map +1 -0
- package/dist/crud.d.ts +27 -0
- package/dist/crud.d.ts.map +1 -0
- package/dist/crud.js +234 -0
- package/dist/crud.js.map +1 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +6 -0
- package/dist/index.js.map +1 -0
- package/dist/migrate.d.ts +29 -0
- package/dist/migrate.d.ts.map +1 -0
- package/dist/migrate.js +189 -0
- package/dist/migrate.js.map +1 -0
- package/dist/model.d.ts +64 -0
- package/dist/model.d.ts.map +1 -0
- package/dist/model.js +115 -0
- package/dist/model.js.map +1 -0
- package/dist/schema.d.ts +13 -0
- package/dist/schema.d.ts.map +1 -0
- package/dist/schema.js +148 -0
- package/dist/schema.js.map +1 -0
- package/dist/types.d.ts +39 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/package.json +45 -0
package/dist/client.d.ts
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { BetterSQLite3Database } from "drizzle-orm/better-sqlite3";
|
|
2
|
+
import type { DatabaseConfig } from "./types.js";
|
|
3
|
+
export interface DatabaseInstance {
|
|
4
|
+
/** The Drizzle ORM database instance. */
|
|
5
|
+
db: BetterSQLite3Database;
|
|
6
|
+
/** Close the underlying database connection. */
|
|
7
|
+
close: () => void;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Create a Drizzle database instance backed by better-sqlite3.
|
|
11
|
+
*
|
|
12
|
+
* @param config - Database configuration. Currently only `sqlite` provider is
|
|
13
|
+
* supported. The `url` field should be a file path (or `:memory:` for an
|
|
14
|
+
* in-memory database).
|
|
15
|
+
*
|
|
16
|
+
* @example
|
|
17
|
+
* const { db, close } = createDatabase({ provider: "sqlite", url: "./data.db" });
|
|
18
|
+
* // ... use db ...
|
|
19
|
+
* close();
|
|
20
|
+
*/
|
|
21
|
+
export declare function createDatabase(config: DatabaseConfig): DatabaseInstance;
|
|
22
|
+
//# sourceMappingURL=client.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,4BAA4B,CAAC;AAExE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAEjD,MAAM,WAAW,gBAAgB;IAC/B,yCAAyC;IACzC,EAAE,EAAE,qBAAqB,CAAC;IAC1B,gDAAgD;IAChD,KAAK,EAAE,MAAM,IAAI,CAAC;CACnB;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,cAAc,CAAC,MAAM,EAAE,cAAc,GAAG,gBAAgB,CAoBvE"}
|
package/dist/client.js
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { drizzle } from "drizzle-orm/better-sqlite3";
|
|
2
|
+
import Database from "better-sqlite3";
|
|
3
|
+
/**
|
|
4
|
+
* Create a Drizzle database instance backed by better-sqlite3.
|
|
5
|
+
*
|
|
6
|
+
* @param config - Database configuration. Currently only `sqlite` provider is
|
|
7
|
+
* supported. The `url` field should be a file path (or `:memory:` for an
|
|
8
|
+
* in-memory database).
|
|
9
|
+
*
|
|
10
|
+
* @example
|
|
11
|
+
* const { db, close } = createDatabase({ provider: "sqlite", url: "./data.db" });
|
|
12
|
+
* // ... use db ...
|
|
13
|
+
* close();
|
|
14
|
+
*/
|
|
15
|
+
export function createDatabase(config) {
|
|
16
|
+
if (config.provider !== "sqlite") {
|
|
17
|
+
throw new Error(`@zauso-ai/capstan-db: Unsupported database provider "${config.provider}". Only "sqlite" is currently supported.`);
|
|
18
|
+
}
|
|
19
|
+
const sqlite = new Database(config.url);
|
|
20
|
+
// Enable WAL mode for better concurrent read performance.
|
|
21
|
+
sqlite.pragma("journal_mode = WAL");
|
|
22
|
+
const db = drizzle({ client: sqlite });
|
|
23
|
+
return {
|
|
24
|
+
db,
|
|
25
|
+
close() {
|
|
26
|
+
sqlite.close();
|
|
27
|
+
},
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
//# sourceMappingURL=client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,4BAA4B,CAAC;AAErD,OAAO,QAAQ,MAAM,gBAAgB,CAAC;AAUtC;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,cAAc,CAAC,MAAsB;IACnD,IAAI,MAAM,CAAC,QAAQ,KAAK,QAAQ,EAAE,CAAC;QACjC,MAAM,IAAI,KAAK,CACb,wDAAwD,MAAM,CAAC,QAAQ,0CAA0C,CAClH,CAAC;IACJ,CAAC;IAED,MAAM,MAAM,GAAG,IAAI,QAAQ,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;IAExC,0DAA0D;IAC1D,MAAM,CAAC,MAAM,CAAC,oBAAoB,CAAC,CAAC;IAEpC,MAAM,EAAE,GAAG,OAAO,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;IAEvC,OAAO;QACL,EAAE;QACF,KAAK;YACH,MAAM,CAAC,KAAK,EAAE,CAAC;QACjB,CAAC;KACF,CAAC;AACJ,CAAC"}
|
package/dist/crud.d.ts
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import type { ModelDefinition } from "./types.js";
|
|
2
|
+
export interface CrudRouteFiles {
|
|
3
|
+
/** File path relative to app/routes/, e.g. "tickets/index.api.ts" */
|
|
4
|
+
path: string;
|
|
5
|
+
content: string;
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* Naive English pluraliser — sufficient for model-name pluralisation.
|
|
9
|
+
*
|
|
10
|
+
* ticket -> tickets
|
|
11
|
+
* company -> companies
|
|
12
|
+
* status -> statuses
|
|
13
|
+
* bus -> buses
|
|
14
|
+
*/
|
|
15
|
+
export declare function pluralize(word: string): string;
|
|
16
|
+
/**
|
|
17
|
+
* Generate CRUD API route handler files for a given model definition.
|
|
18
|
+
*
|
|
19
|
+
* Returns an array of `{ path, content }` objects where `path` is relative
|
|
20
|
+
* to the app's `app/routes/` directory.
|
|
21
|
+
*
|
|
22
|
+
* Two files are produced:
|
|
23
|
+
* 1. `<plural>/index.api.ts` — GET (list) + POST (create)
|
|
24
|
+
* 2. `<plural>/[id].api.ts` — GET (by id) + PUT (update) + DELETE
|
|
25
|
+
*/
|
|
26
|
+
export declare function generateCrudRoutes(model: ModelDefinition): CrudRouteFiles[];
|
|
27
|
+
//# sourceMappingURL=crud.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"crud.d.ts","sourceRoot":"","sources":["../src/crud.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAmB,MAAM,YAAY,CAAC;AAMnE,MAAM,WAAW,cAAc;IAC7B,qEAAqE;IACrE,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;CACjB;AAMD;;;;;;;GAOG;AACH,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CA0B9C;AAiHD;;;;;;;;;GASG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,eAAe,GAAG,cAAc,EAAE,CAsG3E"}
|
package/dist/crud.js
ADDED
|
@@ -0,0 +1,234 @@
|
|
|
1
|
+
// ---------------------------------------------------------------------------
|
|
2
|
+
// Pluralisation helper
|
|
3
|
+
// ---------------------------------------------------------------------------
|
|
4
|
+
/**
|
|
5
|
+
* Naive English pluraliser — sufficient for model-name pluralisation.
|
|
6
|
+
*
|
|
7
|
+
* ticket -> tickets
|
|
8
|
+
* company -> companies
|
|
9
|
+
* status -> statuses
|
|
10
|
+
* bus -> buses
|
|
11
|
+
*/
|
|
12
|
+
export function pluralize(word) {
|
|
13
|
+
if (word.length === 0)
|
|
14
|
+
return word;
|
|
15
|
+
const lower = word.toLowerCase();
|
|
16
|
+
// Words ending in consonant + y → ies
|
|
17
|
+
if (lower.endsWith("y") &&
|
|
18
|
+
lower.length > 1 &&
|
|
19
|
+
!"aeiou".includes(lower[lower.length - 2])) {
|
|
20
|
+
return word.slice(0, -1) + "ies";
|
|
21
|
+
}
|
|
22
|
+
// Words ending in s, sh, ch, x, z → es
|
|
23
|
+
if (lower.endsWith("s") ||
|
|
24
|
+
lower.endsWith("sh") ||
|
|
25
|
+
lower.endsWith("ch") ||
|
|
26
|
+
lower.endsWith("x") ||
|
|
27
|
+
lower.endsWith("z")) {
|
|
28
|
+
return word + "es";
|
|
29
|
+
}
|
|
30
|
+
return word + "s";
|
|
31
|
+
}
|
|
32
|
+
// ---------------------------------------------------------------------------
|
|
33
|
+
// Field → Zod mapping
|
|
34
|
+
// ---------------------------------------------------------------------------
|
|
35
|
+
/**
|
|
36
|
+
* Convert a FieldDefinition into a Zod expression string.
|
|
37
|
+
*/
|
|
38
|
+
function fieldToZod(field) {
|
|
39
|
+
let base;
|
|
40
|
+
// Enum takes precedence when values are supplied.
|
|
41
|
+
if (field.enum && field.enum.length > 0) {
|
|
42
|
+
const values = field.enum.map((v) => `"${v}"`).join(", ");
|
|
43
|
+
base = `z.enum([${values}])`;
|
|
44
|
+
}
|
|
45
|
+
else {
|
|
46
|
+
switch (field.type) {
|
|
47
|
+
case "string":
|
|
48
|
+
case "text":
|
|
49
|
+
case "date":
|
|
50
|
+
case "datetime":
|
|
51
|
+
base = "z.string()";
|
|
52
|
+
break;
|
|
53
|
+
case "integer":
|
|
54
|
+
base = "z.number().int()";
|
|
55
|
+
break;
|
|
56
|
+
case "number":
|
|
57
|
+
base = "z.number()";
|
|
58
|
+
break;
|
|
59
|
+
case "boolean":
|
|
60
|
+
base = "z.boolean()";
|
|
61
|
+
break;
|
|
62
|
+
case "json":
|
|
63
|
+
base = "z.unknown()";
|
|
64
|
+
break;
|
|
65
|
+
default:
|
|
66
|
+
base = "z.unknown()";
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
// Constraints (only meaningful for string and number types).
|
|
70
|
+
if (field.min !== undefined) {
|
|
71
|
+
if (field.type === "string" ||
|
|
72
|
+
field.type === "text") {
|
|
73
|
+
base += `.min(${field.min})`;
|
|
74
|
+
}
|
|
75
|
+
else if (field.type === "integer" ||
|
|
76
|
+
field.type === "number") {
|
|
77
|
+
base += `.min(${field.min})`;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
if (field.max !== undefined) {
|
|
81
|
+
if (field.type === "string" ||
|
|
82
|
+
field.type === "text") {
|
|
83
|
+
base += `.max(${field.max})`;
|
|
84
|
+
}
|
|
85
|
+
else if (field.type === "integer" ||
|
|
86
|
+
field.type === "number") {
|
|
87
|
+
base += `.max(${field.max})`;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
// Mark as optional when the field is not required.
|
|
91
|
+
if (!field.required) {
|
|
92
|
+
base += ".optional()";
|
|
93
|
+
}
|
|
94
|
+
return base;
|
|
95
|
+
}
|
|
96
|
+
// ---------------------------------------------------------------------------
|
|
97
|
+
// Schema generation helpers
|
|
98
|
+
// ---------------------------------------------------------------------------
|
|
99
|
+
/**
|
|
100
|
+
* Build a Zod object literal string from a set of fields, optionally
|
|
101
|
+
* excluding certain field names (e.g. auto-generated id).
|
|
102
|
+
*/
|
|
103
|
+
function buildZodObject(fields, options) {
|
|
104
|
+
const exclude = options?.exclude ?? new Set();
|
|
105
|
+
const allOptional = options?.allOptional ?? false;
|
|
106
|
+
const lines = [];
|
|
107
|
+
for (const [name, field] of Object.entries(fields)) {
|
|
108
|
+
if (exclude.has(name))
|
|
109
|
+
continue;
|
|
110
|
+
let zodExpr;
|
|
111
|
+
if (allOptional) {
|
|
112
|
+
// Strip existing .optional() to avoid duplicates, then add it.
|
|
113
|
+
zodExpr = fieldToZod({ ...field, required: true });
|
|
114
|
+
zodExpr += ".optional()";
|
|
115
|
+
}
|
|
116
|
+
else {
|
|
117
|
+
zodExpr = fieldToZod(field);
|
|
118
|
+
}
|
|
119
|
+
lines.push(` ${name}: ${zodExpr},`);
|
|
120
|
+
}
|
|
121
|
+
return `z.object({\n${lines.join("\n")}\n})`;
|
|
122
|
+
}
|
|
123
|
+
// ---------------------------------------------------------------------------
|
|
124
|
+
// Code generation
|
|
125
|
+
// ---------------------------------------------------------------------------
|
|
126
|
+
/**
|
|
127
|
+
* Generate CRUD API route handler files for a given model definition.
|
|
128
|
+
*
|
|
129
|
+
* Returns an array of `{ path, content }` objects where `path` is relative
|
|
130
|
+
* to the app's `app/routes/` directory.
|
|
131
|
+
*
|
|
132
|
+
* Two files are produced:
|
|
133
|
+
* 1. `<plural>/index.api.ts` — GET (list) + POST (create)
|
|
134
|
+
* 2. `<plural>/[id].api.ts` — GET (by id) + PUT (update) + DELETE
|
|
135
|
+
*/
|
|
136
|
+
export function generateCrudRoutes(model) {
|
|
137
|
+
const plural = pluralize(model.name.toLowerCase());
|
|
138
|
+
const resourceName = model.name;
|
|
139
|
+
// Determine which fields are auto-generated (id, updatedAt).
|
|
140
|
+
const autoFields = new Set();
|
|
141
|
+
for (const [name, field] of Object.entries(model.fields)) {
|
|
142
|
+
if (field.autoId)
|
|
143
|
+
autoFields.add(name);
|
|
144
|
+
if (field.updatedAt)
|
|
145
|
+
autoFields.add(name);
|
|
146
|
+
}
|
|
147
|
+
// ----- index.api.ts (list + create) -----
|
|
148
|
+
const createSchema = buildZodObject(model.fields, { exclude: autoFields });
|
|
149
|
+
const indexContent = `// Auto-generated CRUD routes for ${resourceName}
|
|
150
|
+
// This file was generated by @zauso-ai/capstan-db generateCrudRoutes().
|
|
151
|
+
|
|
152
|
+
import { defineAPI } from "@zauso-ai/capstan-core";
|
|
153
|
+
import { z } from "zod";
|
|
154
|
+
|
|
155
|
+
export const meta = { resource: "${resourceName}" };
|
|
156
|
+
|
|
157
|
+
const CreateInput = ${createSchema};
|
|
158
|
+
|
|
159
|
+
export const GET = defineAPI({
|
|
160
|
+
capability: "read",
|
|
161
|
+
resource: "${resourceName}",
|
|
162
|
+
description: "List all ${plural}",
|
|
163
|
+
handler: async ({ ctx }) => {
|
|
164
|
+
// TODO: replace with actual database query
|
|
165
|
+
return { data: [], total: 0 };
|
|
166
|
+
},
|
|
167
|
+
});
|
|
168
|
+
|
|
169
|
+
export const POST = defineAPI({
|
|
170
|
+
capability: "write",
|
|
171
|
+
resource: "${resourceName}",
|
|
172
|
+
description: "Create a new ${resourceName}",
|
|
173
|
+
policy: "requireAuth",
|
|
174
|
+
input: CreateInput,
|
|
175
|
+
handler: async ({ input, ctx }) => {
|
|
176
|
+
// TODO: replace with actual database insert
|
|
177
|
+
return { data: { id: "TODO", ...input }, created: true };
|
|
178
|
+
},
|
|
179
|
+
});
|
|
180
|
+
`;
|
|
181
|
+
// ----- [id].api.ts (get by id + update + delete) -----
|
|
182
|
+
const updateSchema = buildZodObject(model.fields, {
|
|
183
|
+
exclude: autoFields,
|
|
184
|
+
allOptional: true,
|
|
185
|
+
});
|
|
186
|
+
const idContent = `// Auto-generated CRUD routes for ${resourceName} (by id)
|
|
187
|
+
// This file was generated by @zauso-ai/capstan-db generateCrudRoutes().
|
|
188
|
+
|
|
189
|
+
import { defineAPI } from "@zauso-ai/capstan-core";
|
|
190
|
+
import { z } from "zod";
|
|
191
|
+
|
|
192
|
+
export const meta = { resource: "${resourceName}" };
|
|
193
|
+
|
|
194
|
+
const UpdateInput = ${updateSchema};
|
|
195
|
+
|
|
196
|
+
export const GET = defineAPI({
|
|
197
|
+
capability: "read",
|
|
198
|
+
resource: "${resourceName}",
|
|
199
|
+
description: "Get a ${resourceName} by id",
|
|
200
|
+
handler: async ({ input, ctx }) => {
|
|
201
|
+
// TODO: replace with actual database lookup
|
|
202
|
+
return { data: null };
|
|
203
|
+
},
|
|
204
|
+
});
|
|
205
|
+
|
|
206
|
+
export const PUT = defineAPI({
|
|
207
|
+
capability: "write",
|
|
208
|
+
resource: "${resourceName}",
|
|
209
|
+
description: "Update a ${resourceName}",
|
|
210
|
+
policy: "requireAuth",
|
|
211
|
+
input: UpdateInput,
|
|
212
|
+
handler: async ({ input, ctx }) => {
|
|
213
|
+
// TODO: replace with actual database update
|
|
214
|
+
return { data: { id: "TODO", ...input }, updated: true };
|
|
215
|
+
},
|
|
216
|
+
});
|
|
217
|
+
|
|
218
|
+
export const DELETE = defineAPI({
|
|
219
|
+
capability: "write",
|
|
220
|
+
resource: "${resourceName}",
|
|
221
|
+
description: "Delete a ${resourceName}",
|
|
222
|
+
policy: "requireAuth",
|
|
223
|
+
handler: async ({ ctx }) => {
|
|
224
|
+
// TODO: replace with actual database delete
|
|
225
|
+
return { deleted: true };
|
|
226
|
+
},
|
|
227
|
+
});
|
|
228
|
+
`;
|
|
229
|
+
return [
|
|
230
|
+
{ path: `${plural}/index.api.ts`, content: indexContent },
|
|
231
|
+
{ path: `${plural}/[id].api.ts`, content: idContent },
|
|
232
|
+
];
|
|
233
|
+
}
|
|
234
|
+
//# sourceMappingURL=crud.js.map
|
package/dist/crud.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"crud.js","sourceRoot":"","sources":["../src/crud.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export { defineModel, field, relation } from "./model.js";
|
|
2
|
+
export { generateDrizzleSchema } from "./schema.js";
|
|
3
|
+
export { createDatabase } from "./client.js";
|
|
4
|
+
export { generateMigration, applyMigration } from "./migrate.js";
|
|
5
|
+
export { generateCrudRoutes, pluralize } from "./crud.js";
|
|
6
|
+
export type { CrudRouteFiles } from "./crud.js";
|
|
7
|
+
export type { ModelDefinition, FieldDefinition, RelationDefinition, IndexDefinition, DatabaseConfig, ScalarType, } from "./types.js";
|
|
8
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAC1D,OAAO,EAAE,qBAAqB,EAAE,MAAM,aAAa,CAAC;AACpD,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAC7C,OAAO,EAAE,iBAAiB,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AACjE,OAAO,EAAE,kBAAkB,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAC1D,YAAY,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAChD,YAAY,EACV,eAAe,EACf,eAAe,EACf,kBAAkB,EAClB,eAAe,EACf,cAAc,EACd,UAAU,GACX,MAAM,YAAY,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export { defineModel, field, relation } from "./model.js";
|
|
2
|
+
export { generateDrizzleSchema } from "./schema.js";
|
|
3
|
+
export { createDatabase } from "./client.js";
|
|
4
|
+
export { generateMigration, applyMigration } from "./migrate.js";
|
|
5
|
+
export { generateCrudRoutes, pluralize } from "./crud.js";
|
|
6
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAC1D,OAAO,EAAE,qBAAqB,EAAE,MAAM,aAAa,CAAC;AACpD,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAC7C,OAAO,EAAE,iBAAiB,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AACjE,OAAO,EAAE,kBAAkB,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import type { ModelDefinition } from "./types.js";
|
|
2
|
+
/**
|
|
3
|
+
* Generate SQL migration statements that transform `fromModels` into
|
|
4
|
+
* `toModels`. This is a forward-only diff: it creates new tables, adds new
|
|
5
|
+
* columns, and creates indexes. It does NOT handle column drops, renames, or
|
|
6
|
+
* type changes (SQLite has limited ALTER TABLE support).
|
|
7
|
+
*
|
|
8
|
+
* @param fromModels - The previous set of model definitions (can be empty for
|
|
9
|
+
* initial migration).
|
|
10
|
+
* @param toModels - The target set of model definitions.
|
|
11
|
+
* @returns An array of SQL statements to execute.
|
|
12
|
+
*/
|
|
13
|
+
export declare function generateMigration(fromModels: ModelDefinition[], toModels: ModelDefinition[]): string[];
|
|
14
|
+
/**
|
|
15
|
+
* Execute an array of SQL migration statements against a database.
|
|
16
|
+
*
|
|
17
|
+
* The statements are run inside a transaction so that either all succeed or
|
|
18
|
+
* none are applied.
|
|
19
|
+
*
|
|
20
|
+
* @param db - A Drizzle `BetterSQLite3Database` instance (or any object whose
|
|
21
|
+
* `$client` property is a better-sqlite3 `Database`).
|
|
22
|
+
* @param sql - The SQL statements to execute.
|
|
23
|
+
*/
|
|
24
|
+
export declare function applyMigration(db: {
|
|
25
|
+
$client: {
|
|
26
|
+
exec: (sql: string) => void;
|
|
27
|
+
};
|
|
28
|
+
}, sql: string[]): void;
|
|
29
|
+
//# sourceMappingURL=migrate.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"migrate.d.ts","sourceRoot":"","sources":["../src/migrate.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAgD,MAAM,YAAY,CAAC;AAyHhG;;;;;;;;;;GAUG;AACH,wBAAgB,iBAAiB,CAC/B,UAAU,EAAE,eAAe,EAAE,EAC7B,QAAQ,EAAE,eAAe,EAAE,GAC1B,MAAM,EAAE,CA0DV;AAED;;;;;;;;;GASG;AACH,wBAAgB,cAAc,CAAC,EAAE,EAAE;IAAE,OAAO,EAAE;QAAE,IAAI,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAA;KAAE,CAAA;CAAE,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,IAAI,CAcpG"}
|
package/dist/migrate.js
ADDED
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
// ---------------------------------------------------------------------------
|
|
2
|
+
// Helpers
|
|
3
|
+
// ---------------------------------------------------------------------------
|
|
4
|
+
function toSnakeCase(str) {
|
|
5
|
+
return str.replace(/[A-Z]/g, (ch) => `_${ch.toLowerCase()}`);
|
|
6
|
+
}
|
|
7
|
+
function pluralise(name) {
|
|
8
|
+
const lower = name.charAt(0).toLowerCase() + name.slice(1);
|
|
9
|
+
if (lower.endsWith("y") && !/[aeiou]y$/i.test(lower)) {
|
|
10
|
+
return lower.slice(0, -1) + "ies";
|
|
11
|
+
}
|
|
12
|
+
if (lower.endsWith("s") || lower.endsWith("x") || lower.endsWith("sh") || lower.endsWith("ch")) {
|
|
13
|
+
return lower + "es";
|
|
14
|
+
}
|
|
15
|
+
return lower + "s";
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Map a Capstan scalar type to a SQLite column type.
|
|
19
|
+
*/
|
|
20
|
+
function sqliteType(type) {
|
|
21
|
+
switch (type) {
|
|
22
|
+
case "string":
|
|
23
|
+
case "text":
|
|
24
|
+
case "date":
|
|
25
|
+
case "datetime":
|
|
26
|
+
case "json":
|
|
27
|
+
return "TEXT";
|
|
28
|
+
case "integer":
|
|
29
|
+
case "boolean":
|
|
30
|
+
return "INTEGER";
|
|
31
|
+
case "number":
|
|
32
|
+
return "REAL";
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Generate the SQL default expression for a field.
|
|
37
|
+
*/
|
|
38
|
+
function sqlDefault(def) {
|
|
39
|
+
if (def.default === undefined)
|
|
40
|
+
return null;
|
|
41
|
+
if (def.default === "now")
|
|
42
|
+
return "DEFAULT (datetime('now'))";
|
|
43
|
+
if (typeof def.default === "string")
|
|
44
|
+
return `DEFAULT '${def.default.replace(/'/g, "''")}'`;
|
|
45
|
+
if (typeof def.default === "boolean")
|
|
46
|
+
return `DEFAULT ${def.default ? 1 : 0}`;
|
|
47
|
+
if (typeof def.default === "number")
|
|
48
|
+
return `DEFAULT ${def.default}`;
|
|
49
|
+
return null;
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Build a column definition clause for a CREATE TABLE statement.
|
|
53
|
+
*/
|
|
54
|
+
function columnDef(fieldName, def) {
|
|
55
|
+
const colName = toSnakeCase(fieldName);
|
|
56
|
+
const parts = [colName, sqliteType(def.type)];
|
|
57
|
+
if (def.autoId) {
|
|
58
|
+
parts.push("PRIMARY KEY");
|
|
59
|
+
}
|
|
60
|
+
if (def.required && !def.autoId) {
|
|
61
|
+
parts.push("NOT NULL");
|
|
62
|
+
}
|
|
63
|
+
if (def.unique && !def.autoId) {
|
|
64
|
+
parts.push("UNIQUE");
|
|
65
|
+
}
|
|
66
|
+
const defaultExpr = sqlDefault(def);
|
|
67
|
+
if (defaultExpr) {
|
|
68
|
+
parts.push(defaultExpr);
|
|
69
|
+
}
|
|
70
|
+
if (def.references) {
|
|
71
|
+
const refTable = pluralise(def.references);
|
|
72
|
+
parts.push(`REFERENCES ${refTable}(id)`);
|
|
73
|
+
}
|
|
74
|
+
return parts.join(" ");
|
|
75
|
+
}
|
|
76
|
+
function tableInfo(model) {
|
|
77
|
+
return { tableName: pluralise(model.name), model };
|
|
78
|
+
}
|
|
79
|
+
function createTableSQL(model) {
|
|
80
|
+
const tableName = pluralise(model.name);
|
|
81
|
+
const cols = Object.entries(model.fields).map(([name, def]) => ` ${columnDef(name, def)}`);
|
|
82
|
+
return `CREATE TABLE ${tableName} (\n${cols.join(",\n")}\n)`;
|
|
83
|
+
}
|
|
84
|
+
function dropTableSQL(tableName) {
|
|
85
|
+
return `DROP TABLE IF EXISTS ${tableName}`;
|
|
86
|
+
}
|
|
87
|
+
function addColumnSQL(tableName, fieldName, def) {
|
|
88
|
+
return `ALTER TABLE ${tableName} ADD COLUMN ${columnDef(fieldName, def)}`;
|
|
89
|
+
}
|
|
90
|
+
function createIndexSQL(tableName, idx, idxNum) {
|
|
91
|
+
const idxName = `idx_${tableName}_${idx.fields.map(toSnakeCase).join("_")}`;
|
|
92
|
+
const unique = idx.unique ? "UNIQUE " : "";
|
|
93
|
+
const cols = idx.fields.map((f) => {
|
|
94
|
+
const col = toSnakeCase(f);
|
|
95
|
+
return idx.order ? `${col} ${idx.order.toUpperCase()}` : col;
|
|
96
|
+
});
|
|
97
|
+
return `CREATE ${unique}INDEX IF NOT EXISTS ${idxName} ON ${tableName} (${cols.join(", ")})`;
|
|
98
|
+
}
|
|
99
|
+
// ---------------------------------------------------------------------------
|
|
100
|
+
// Public API
|
|
101
|
+
// ---------------------------------------------------------------------------
|
|
102
|
+
/**
|
|
103
|
+
* Generate SQL migration statements that transform `fromModels` into
|
|
104
|
+
* `toModels`. This is a forward-only diff: it creates new tables, adds new
|
|
105
|
+
* columns, and creates indexes. It does NOT handle column drops, renames, or
|
|
106
|
+
* type changes (SQLite has limited ALTER TABLE support).
|
|
107
|
+
*
|
|
108
|
+
* @param fromModels - The previous set of model definitions (can be empty for
|
|
109
|
+
* initial migration).
|
|
110
|
+
* @param toModels - The target set of model definitions.
|
|
111
|
+
* @returns An array of SQL statements to execute.
|
|
112
|
+
*/
|
|
113
|
+
export function generateMigration(fromModels, toModels) {
|
|
114
|
+
const statements = [];
|
|
115
|
+
const fromMap = new Map();
|
|
116
|
+
for (const m of fromModels) {
|
|
117
|
+
const info = tableInfo(m);
|
|
118
|
+
fromMap.set(info.tableName, info);
|
|
119
|
+
}
|
|
120
|
+
const toMap = new Map();
|
|
121
|
+
for (const m of toModels) {
|
|
122
|
+
const info = tableInfo(m);
|
|
123
|
+
toMap.set(info.tableName, info);
|
|
124
|
+
}
|
|
125
|
+
// Tables that exist in `from` but not in `to` — drop them
|
|
126
|
+
for (const [tableName] of fromMap) {
|
|
127
|
+
if (!toMap.has(tableName)) {
|
|
128
|
+
statements.push(dropTableSQL(tableName));
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
// Tables in `to`
|
|
132
|
+
for (const [tableName, toInfo] of toMap) {
|
|
133
|
+
const fromInfo = fromMap.get(tableName);
|
|
134
|
+
if (!fromInfo) {
|
|
135
|
+
// New table — CREATE TABLE
|
|
136
|
+
statements.push(createTableSQL(toInfo.model));
|
|
137
|
+
// Create indexes for the new table
|
|
138
|
+
for (let i = 0; i < toInfo.model.indexes.length; i++) {
|
|
139
|
+
statements.push(createIndexSQL(tableName, toInfo.model.indexes[i], i));
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
else {
|
|
143
|
+
// Existing table — check for new columns
|
|
144
|
+
const existingFields = new Set(Object.keys(fromInfo.model.fields));
|
|
145
|
+
for (const [fieldName, def] of Object.entries(toInfo.model.fields)) {
|
|
146
|
+
if (!existingFields.has(fieldName)) {
|
|
147
|
+
statements.push(addColumnSQL(tableName, fieldName, def));
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
// Check for new indexes
|
|
151
|
+
const existingIndexKeys = new Set(fromInfo.model.indexes.map((idx) => idx.fields.join(",") + (idx.unique ? ":u" : "")));
|
|
152
|
+
for (let i = 0; i < toInfo.model.indexes.length; i++) {
|
|
153
|
+
const idx = toInfo.model.indexes[i];
|
|
154
|
+
const key = idx.fields.join(",") + (idx.unique ? ":u" : "");
|
|
155
|
+
if (!existingIndexKeys.has(key)) {
|
|
156
|
+
statements.push(createIndexSQL(tableName, idx, i));
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
return statements;
|
|
162
|
+
}
|
|
163
|
+
/**
|
|
164
|
+
* Execute an array of SQL migration statements against a database.
|
|
165
|
+
*
|
|
166
|
+
* The statements are run inside a transaction so that either all succeed or
|
|
167
|
+
* none are applied.
|
|
168
|
+
*
|
|
169
|
+
* @param db - A Drizzle `BetterSQLite3Database` instance (or any object whose
|
|
170
|
+
* `$client` property is a better-sqlite3 `Database`).
|
|
171
|
+
* @param sql - The SQL statements to execute.
|
|
172
|
+
*/
|
|
173
|
+
export function applyMigration(db, sql) {
|
|
174
|
+
if (sql.length === 0)
|
|
175
|
+
return;
|
|
176
|
+
const client = db.$client;
|
|
177
|
+
client.exec("BEGIN TRANSACTION");
|
|
178
|
+
try {
|
|
179
|
+
for (const stmt of sql) {
|
|
180
|
+
client.exec(stmt);
|
|
181
|
+
}
|
|
182
|
+
client.exec("COMMIT");
|
|
183
|
+
}
|
|
184
|
+
catch (err) {
|
|
185
|
+
client.exec("ROLLBACK");
|
|
186
|
+
throw err;
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
//# sourceMappingURL=migrate.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"migrate.js","sourceRoot":"","sources":["../src/migrate.ts"],"names":[],"mappings":"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"}
|
package/dist/model.d.ts
ADDED
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import type { FieldDefinition, RelationDefinition, IndexDefinition, ModelDefinition } from "./types.js";
|
|
2
|
+
type FieldOptions = Omit<FieldDefinition, "type">;
|
|
3
|
+
export declare const field: {
|
|
4
|
+
/**
|
|
5
|
+
* Primary key field — auto-generated UUID, required, unique.
|
|
6
|
+
*/
|
|
7
|
+
id(): FieldDefinition;
|
|
8
|
+
/**
|
|
9
|
+
* Short string field (maps to TEXT in SQLite).
|
|
10
|
+
*/
|
|
11
|
+
string(opts?: FieldOptions): FieldDefinition;
|
|
12
|
+
/**
|
|
13
|
+
* Long text field (maps to TEXT in SQLite).
|
|
14
|
+
*/
|
|
15
|
+
text(opts?: FieldOptions): FieldDefinition;
|
|
16
|
+
/**
|
|
17
|
+
* Integer field (maps to INTEGER in SQLite).
|
|
18
|
+
*/
|
|
19
|
+
integer(opts?: FieldOptions): FieldDefinition;
|
|
20
|
+
/**
|
|
21
|
+
* Floating-point number field (maps to REAL in SQLite).
|
|
22
|
+
*/
|
|
23
|
+
number(opts?: FieldOptions): FieldDefinition;
|
|
24
|
+
/**
|
|
25
|
+
* Boolean field (maps to INTEGER with 0/1 in SQLite).
|
|
26
|
+
*/
|
|
27
|
+
boolean(opts?: FieldOptions): FieldDefinition;
|
|
28
|
+
/**
|
|
29
|
+
* Date-only field (stored as TEXT ISO-8601 in SQLite).
|
|
30
|
+
*/
|
|
31
|
+
date(opts?: FieldOptions): FieldDefinition;
|
|
32
|
+
/**
|
|
33
|
+
* Datetime field (stored as TEXT ISO-8601 in SQLite).
|
|
34
|
+
*/
|
|
35
|
+
datetime(opts?: FieldOptions): FieldDefinition;
|
|
36
|
+
/**
|
|
37
|
+
* JSON field (stored as TEXT with JSON serialisation in SQLite).
|
|
38
|
+
*/
|
|
39
|
+
json<_T = unknown>(opts?: FieldOptions): FieldDefinition;
|
|
40
|
+
/**
|
|
41
|
+
* Enum field — stored as TEXT with a constrained set of values.
|
|
42
|
+
*
|
|
43
|
+
* @example
|
|
44
|
+
* field.enum(["open", "closed"], { default: "open" })
|
|
45
|
+
*/
|
|
46
|
+
enum(values: readonly string[], opts?: FieldOptions): FieldDefinition;
|
|
47
|
+
};
|
|
48
|
+
interface RelationOptions {
|
|
49
|
+
foreignKey?: string;
|
|
50
|
+
through?: string;
|
|
51
|
+
}
|
|
52
|
+
export declare const relation: {
|
|
53
|
+
belongsTo(model: string, opts?: RelationOptions): RelationDefinition;
|
|
54
|
+
hasMany(model: string, opts?: RelationOptions): RelationDefinition;
|
|
55
|
+
hasOne(model: string, opts?: RelationOptions): RelationDefinition;
|
|
56
|
+
manyToMany(model: string, opts?: RelationOptions): RelationDefinition;
|
|
57
|
+
};
|
|
58
|
+
export declare function defineModel(name: string, config: {
|
|
59
|
+
fields: Record<string, FieldDefinition>;
|
|
60
|
+
relations?: Record<string, RelationDefinition>;
|
|
61
|
+
indexes?: IndexDefinition[];
|
|
62
|
+
}): ModelDefinition;
|
|
63
|
+
export {};
|
|
64
|
+
//# sourceMappingURL=model.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"model.d.ts","sourceRoot":"","sources":["../src/model.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,kBAAkB,EAAE,eAAe,EAAE,eAAe,EAAc,MAAM,YAAY,CAAC;AAMpH,KAAK,YAAY,GAAG,IAAI,CAAC,eAAe,EAAE,MAAM,CAAC,CAAC;AAkBlD,eAAO,MAAM,KAAK;IAChB;;OAEG;UACG,eAAe;IAIrB;;OAEG;kBACW,YAAY,GAAG,eAAe;IAI5C;;OAEG;gBACS,YAAY,GAAG,eAAe;IAI1C;;OAEG;mBACY,YAAY,GAAG,eAAe;IAI7C;;OAEG;kBACW,YAAY,GAAG,eAAe;IAI5C;;OAEG;mBACY,YAAY,GAAG,eAAe;IAI7C;;OAEG;gBACS,YAAY,GAAG,eAAe;IAI1C;;OAEG;oBACa,YAAY,GAAG,eAAe;IAI9C;;OAEG;SACE,EAAE,mBAAmB,YAAY,GAAG,eAAe;IAIxD;;;;;OAKG;iBACU,SAAS,MAAM,EAAE,SAAS,YAAY,GAAG,eAAe;CAGtE,CAAC;AAMF,UAAU,eAAe;IACvB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,eAAO,MAAM,QAAQ;qBACF,MAAM,SAAS,eAAe,GAAG,kBAAkB;mBAIrD,MAAM,SAAS,eAAe,GAAG,kBAAkB;kBAIpD,MAAM,SAAS,eAAe,GAAG,kBAAkB;sBAI/C,MAAM,SAAS,eAAe,GAAG,kBAAkB;CAGtE,CAAC;AAMF,wBAAgB,WAAW,CACzB,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE;IACN,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,eAAe,CAAC,CAAC;IACxC,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,kBAAkB,CAAC,CAAC;IAC/C,OAAO,CAAC,EAAE,eAAe,EAAE,CAAC;CAC7B,GACA,eAAe,CAOjB"}
|
package/dist/model.js
ADDED
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
function makeField(type, opts) {
|
|
2
|
+
const def = { type };
|
|
3
|
+
if (opts) {
|
|
4
|
+
if (opts.required !== undefined)
|
|
5
|
+
def.required = opts.required;
|
|
6
|
+
if (opts.unique !== undefined)
|
|
7
|
+
def.unique = opts.unique;
|
|
8
|
+
if (opts.default !== undefined)
|
|
9
|
+
def.default = opts.default;
|
|
10
|
+
if (opts.min !== undefined)
|
|
11
|
+
def.min = opts.min;
|
|
12
|
+
if (opts.max !== undefined)
|
|
13
|
+
def.max = opts.max;
|
|
14
|
+
if (opts.enum !== undefined)
|
|
15
|
+
def.enum = opts.enum;
|
|
16
|
+
if (opts.updatedAt !== undefined)
|
|
17
|
+
def.updatedAt = opts.updatedAt;
|
|
18
|
+
if (opts.autoId !== undefined)
|
|
19
|
+
def.autoId = opts.autoId;
|
|
20
|
+
if (opts.references !== undefined)
|
|
21
|
+
def.references = opts.references;
|
|
22
|
+
}
|
|
23
|
+
return def;
|
|
24
|
+
}
|
|
25
|
+
export const field = {
|
|
26
|
+
/**
|
|
27
|
+
* Primary key field — auto-generated UUID, required, unique.
|
|
28
|
+
*/
|
|
29
|
+
id() {
|
|
30
|
+
return { type: "string", autoId: true, required: true, unique: true };
|
|
31
|
+
},
|
|
32
|
+
/**
|
|
33
|
+
* Short string field (maps to TEXT in SQLite).
|
|
34
|
+
*/
|
|
35
|
+
string(opts) {
|
|
36
|
+
return makeField("string", opts);
|
|
37
|
+
},
|
|
38
|
+
/**
|
|
39
|
+
* Long text field (maps to TEXT in SQLite).
|
|
40
|
+
*/
|
|
41
|
+
text(opts) {
|
|
42
|
+
return makeField("text", opts);
|
|
43
|
+
},
|
|
44
|
+
/**
|
|
45
|
+
* Integer field (maps to INTEGER in SQLite).
|
|
46
|
+
*/
|
|
47
|
+
integer(opts) {
|
|
48
|
+
return makeField("integer", opts);
|
|
49
|
+
},
|
|
50
|
+
/**
|
|
51
|
+
* Floating-point number field (maps to REAL in SQLite).
|
|
52
|
+
*/
|
|
53
|
+
number(opts) {
|
|
54
|
+
return makeField("number", opts);
|
|
55
|
+
},
|
|
56
|
+
/**
|
|
57
|
+
* Boolean field (maps to INTEGER with 0/1 in SQLite).
|
|
58
|
+
*/
|
|
59
|
+
boolean(opts) {
|
|
60
|
+
return makeField("boolean", opts);
|
|
61
|
+
},
|
|
62
|
+
/**
|
|
63
|
+
* Date-only field (stored as TEXT ISO-8601 in SQLite).
|
|
64
|
+
*/
|
|
65
|
+
date(opts) {
|
|
66
|
+
return makeField("date", opts);
|
|
67
|
+
},
|
|
68
|
+
/**
|
|
69
|
+
* Datetime field (stored as TEXT ISO-8601 in SQLite).
|
|
70
|
+
*/
|
|
71
|
+
datetime(opts) {
|
|
72
|
+
return makeField("datetime", opts);
|
|
73
|
+
},
|
|
74
|
+
/**
|
|
75
|
+
* JSON field (stored as TEXT with JSON serialisation in SQLite).
|
|
76
|
+
*/
|
|
77
|
+
json(opts) {
|
|
78
|
+
return makeField("json", opts);
|
|
79
|
+
},
|
|
80
|
+
/**
|
|
81
|
+
* Enum field — stored as TEXT with a constrained set of values.
|
|
82
|
+
*
|
|
83
|
+
* @example
|
|
84
|
+
* field.enum(["open", "closed"], { default: "open" })
|
|
85
|
+
*/
|
|
86
|
+
enum(values, opts) {
|
|
87
|
+
return makeField("string", { ...opts, enum: values });
|
|
88
|
+
},
|
|
89
|
+
};
|
|
90
|
+
export const relation = {
|
|
91
|
+
belongsTo(model, opts) {
|
|
92
|
+
return { kind: "belongsTo", model, ...opts };
|
|
93
|
+
},
|
|
94
|
+
hasMany(model, opts) {
|
|
95
|
+
return { kind: "hasMany", model, ...opts };
|
|
96
|
+
},
|
|
97
|
+
hasOne(model, opts) {
|
|
98
|
+
return { kind: "hasOne", model, ...opts };
|
|
99
|
+
},
|
|
100
|
+
manyToMany(model, opts) {
|
|
101
|
+
return { kind: "manyToMany", model, ...opts };
|
|
102
|
+
},
|
|
103
|
+
};
|
|
104
|
+
// ---------------------------------------------------------------------------
|
|
105
|
+
// defineModel
|
|
106
|
+
// ---------------------------------------------------------------------------
|
|
107
|
+
export function defineModel(name, config) {
|
|
108
|
+
return {
|
|
109
|
+
name,
|
|
110
|
+
fields: config.fields,
|
|
111
|
+
relations: config.relations ?? {},
|
|
112
|
+
indexes: config.indexes ?? [],
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
//# sourceMappingURL=model.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"model.js","sourceRoot":"","sources":["../src/model.ts"],"names":[],"mappings":"AAQA,SAAS,SAAS,CAAC,IAAgB,EAAE,IAAmB;IACtD,MAAM,GAAG,GAAoB,EAAE,IAAI,EAAE,CAAC;IACtC,IAAI,IAAI,EAAE,CAAC;QACT,IAAI,IAAI,CAAC,QAAQ,KAAK,SAAS;YAAE,GAAG,CAAC,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC;QAC9D,IAAI,IAAI,CAAC,MAAM,KAAK,SAAS;YAAE,GAAG,CAAC,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC;QACxD,IAAI,IAAI,CAAC,OAAO,KAAK,SAAS;YAAE,GAAG,CAAC,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC;QAC3D,IAAI,IAAI,CAAC,GAAG,KAAK,SAAS;YAAE,GAAG,CAAC,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC;QAC/C,IAAI,IAAI,CAAC,GAAG,KAAK,SAAS;YAAE,GAAG,CAAC,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC;QAC/C,IAAI,IAAI,CAAC,IAAI,KAAK,SAAS;YAAE,GAAG,CAAC,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC;QAClD,IAAI,IAAI,CAAC,SAAS,KAAK,SAAS;YAAE,GAAG,CAAC,SAAS,GAAG,IAAI,CAAC,SAAS,CAAC;QACjE,IAAI,IAAI,CAAC,MAAM,KAAK,SAAS;YAAE,GAAG,CAAC,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC;QACxD,IAAI,IAAI,CAAC,UAAU,KAAK,SAAS;YAAE,GAAG,CAAC,UAAU,GAAG,IAAI,CAAC,UAAU,CAAC;IACtE,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC;AAED,MAAM,CAAC,MAAM,KAAK,GAAG;IACnB;;OAEG;IACH,EAAE;QACA,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC;IACxE,CAAC;IAED;;OAEG;IACH,MAAM,CAAC,IAAmB;QACxB,OAAO,SAAS,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;IACnC,CAAC;IAED;;OAEG;IACH,IAAI,CAAC,IAAmB;QACtB,OAAO,SAAS,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;IACjC,CAAC;IAED;;OAEG;IACH,OAAO,CAAC,IAAmB;QACzB,OAAO,SAAS,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC;IACpC,CAAC;IAED;;OAEG;IACH,MAAM,CAAC,IAAmB;QACxB,OAAO,SAAS,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;IACnC,CAAC;IAED;;OAEG;IACH,OAAO,CAAC,IAAmB;QACzB,OAAO,SAAS,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC;IACpC,CAAC;IAED;;OAEG;IACH,IAAI,CAAC,IAAmB;QACtB,OAAO,SAAS,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;IACjC,CAAC;IAED;;OAEG;IACH,QAAQ,CAAC,IAAmB;QAC1B,OAAO,SAAS,CAAC,UAAU,EAAE,IAAI,CAAC,CAAC;IACrC,CAAC;IAED;;OAEG;IACH,IAAI,CAAe,IAAmB;QACpC,OAAO,SAAS,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;IACjC,CAAC;IAED;;;;;OAKG;IACH,IAAI,CAAC,MAAyB,EAAE,IAAmB;QACjD,OAAO,SAAS,CAAC,QAAQ,EAAE,EAAE,GAAG,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,CAAC;IACxD,CAAC;CACF,CAAC;AAWF,MAAM,CAAC,MAAM,QAAQ,GAAG;IACtB,SAAS,CAAC,KAAa,EAAE,IAAsB;QAC7C,OAAO,EAAE,IAAI,EAAE,WAAW,EAAE,KAAK,EAAE,GAAG,IAAI,EAAE,CAAC;IAC/C,CAAC;IAED,OAAO,CAAC,KAAa,EAAE,IAAsB;QAC3C,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,KAAK,EAAE,GAAG,IAAI,EAAE,CAAC;IAC7C,CAAC;IAED,MAAM,CAAC,KAAa,EAAE,IAAsB;QAC1C,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,GAAG,IAAI,EAAE,CAAC;IAC5C,CAAC;IAED,UAAU,CAAC,KAAa,EAAE,IAAsB;QAC9C,OAAO,EAAE,IAAI,EAAE,YAAY,EAAE,KAAK,EAAE,GAAG,IAAI,EAAE,CAAC;IAChD,CAAC;CACF,CAAC;AAEF,8EAA8E;AAC9E,cAAc;AACd,8EAA8E;AAE9E,MAAM,UAAU,WAAW,CACzB,IAAY,EACZ,MAIC;IAED,OAAO;QACL,IAAI;QACJ,MAAM,EAAE,MAAM,CAAC,MAAM;QACrB,SAAS,EAAE,MAAM,CAAC,SAAS,IAAI,EAAE;QACjC,OAAO,EAAE,MAAM,CAAC,OAAO,IAAI,EAAE;KAC9B,CAAC;AACJ,CAAC"}
|
package/dist/schema.d.ts
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { ModelDefinition } from "./types.js";
|
|
2
|
+
/**
|
|
3
|
+
* Generate a Drizzle ORM schema file (as a TypeScript string) from an array
|
|
4
|
+
* of model definitions.
|
|
5
|
+
*
|
|
6
|
+
* The generated code targets `drizzle-orm/sqlite-core`.
|
|
7
|
+
*
|
|
8
|
+
* @example
|
|
9
|
+
* const src = generateDrizzleSchema([ticketModel, userModel]);
|
|
10
|
+
* fs.writeFileSync("schema.ts", src);
|
|
11
|
+
*/
|
|
12
|
+
export declare function generateDrizzleSchema(models: ModelDefinition[]): string;
|
|
13
|
+
//# sourceMappingURL=schema.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../src/schema.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAA+B,MAAM,YAAY,CAAC;AA2H/E;;;;;;;;;GASG;AACH,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,eAAe,EAAE,GAAG,MAAM,CA4CvE"}
|
package/dist/schema.js
ADDED
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
// ---------------------------------------------------------------------------
|
|
2
|
+
// Helpers
|
|
3
|
+
// ---------------------------------------------------------------------------
|
|
4
|
+
/**
|
|
5
|
+
* Convert a camelCase name to snake_case for column names.
|
|
6
|
+
*/
|
|
7
|
+
function toSnakeCase(str) {
|
|
8
|
+
return str.replace(/[A-Z]/g, (ch) => `_${ch.toLowerCase()}`);
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Pluralise a model name for the table name (very simple heuristic).
|
|
12
|
+
* "Ticket" -> "tickets", "Category" -> "categories", "Status" -> "statuses"
|
|
13
|
+
*/
|
|
14
|
+
function pluralise(name) {
|
|
15
|
+
const lower = name.charAt(0).toLowerCase() + name.slice(1);
|
|
16
|
+
if (lower.endsWith("y") && !/[aeiou]y$/i.test(lower)) {
|
|
17
|
+
return lower.slice(0, -1) + "ies";
|
|
18
|
+
}
|
|
19
|
+
if (lower.endsWith("s") || lower.endsWith("x") || lower.endsWith("sh") || lower.endsWith("ch")) {
|
|
20
|
+
return lower + "es";
|
|
21
|
+
}
|
|
22
|
+
return lower + "s";
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Escape a JavaScript string value for embedding in generated code.
|
|
26
|
+
*/
|
|
27
|
+
function jsString(val) {
|
|
28
|
+
if (typeof val === "string") {
|
|
29
|
+
return `"${val.replace(/\\/g, "\\\\").replace(/"/g, '\\"')}"`;
|
|
30
|
+
}
|
|
31
|
+
return String(val);
|
|
32
|
+
}
|
|
33
|
+
function columnMapping(fieldType) {
|
|
34
|
+
switch (fieldType) {
|
|
35
|
+
case "string":
|
|
36
|
+
case "text":
|
|
37
|
+
case "date":
|
|
38
|
+
case "datetime":
|
|
39
|
+
return { builder: "text", import: "text" };
|
|
40
|
+
case "integer":
|
|
41
|
+
return { builder: "integer", import: "integer" };
|
|
42
|
+
case "number":
|
|
43
|
+
return { builder: "real", import: "real" };
|
|
44
|
+
case "boolean":
|
|
45
|
+
return { builder: "integer", import: "integer", config: '{ mode: "boolean" }' };
|
|
46
|
+
case "json":
|
|
47
|
+
return { builder: "text", import: "text", config: '{ mode: "json" }' };
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
// ---------------------------------------------------------------------------
|
|
51
|
+
// Column expression builder
|
|
52
|
+
// ---------------------------------------------------------------------------
|
|
53
|
+
function buildColumnExpr(fieldName, def) {
|
|
54
|
+
const colName = toSnakeCase(fieldName);
|
|
55
|
+
const mapping = columnMapping(def.type);
|
|
56
|
+
let expr;
|
|
57
|
+
if (mapping.config) {
|
|
58
|
+
expr = `${mapping.builder}("${colName}", ${mapping.config})`;
|
|
59
|
+
}
|
|
60
|
+
else {
|
|
61
|
+
expr = `${mapping.builder}("${colName}")`;
|
|
62
|
+
}
|
|
63
|
+
// Primary key for auto-id fields
|
|
64
|
+
if (def.autoId) {
|
|
65
|
+
expr += ".primaryKey()";
|
|
66
|
+
}
|
|
67
|
+
// NOT NULL for required fields (but not auto-id, which is already implied)
|
|
68
|
+
if (def.required && !def.autoId) {
|
|
69
|
+
expr += ".notNull()";
|
|
70
|
+
}
|
|
71
|
+
// Unique constraint
|
|
72
|
+
if (def.unique && !def.autoId) {
|
|
73
|
+
expr += ".unique()";
|
|
74
|
+
}
|
|
75
|
+
// Default values
|
|
76
|
+
if (def.default !== undefined) {
|
|
77
|
+
if (def.default === "now") {
|
|
78
|
+
// For date/datetime fields, "now" means the current ISO timestamp.
|
|
79
|
+
// We use a SQL expression: (datetime('now')) or store as text.
|
|
80
|
+
expr += `.default(sql\`(datetime('now'))\`)`;
|
|
81
|
+
}
|
|
82
|
+
else if (typeof def.default === "string") {
|
|
83
|
+
expr += `.default(${jsString(def.default)})`;
|
|
84
|
+
}
|
|
85
|
+
else if (typeof def.default === "boolean") {
|
|
86
|
+
expr += `.default(${def.default})`;
|
|
87
|
+
}
|
|
88
|
+
else if (typeof def.default === "number") {
|
|
89
|
+
expr += `.default(${def.default})`;
|
|
90
|
+
}
|
|
91
|
+
else {
|
|
92
|
+
expr += `.default(${jsString(def.default)})`;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
return expr;
|
|
96
|
+
}
|
|
97
|
+
// ---------------------------------------------------------------------------
|
|
98
|
+
// Public API
|
|
99
|
+
// ---------------------------------------------------------------------------
|
|
100
|
+
/**
|
|
101
|
+
* Generate a Drizzle ORM schema file (as a TypeScript string) from an array
|
|
102
|
+
* of model definitions.
|
|
103
|
+
*
|
|
104
|
+
* The generated code targets `drizzle-orm/sqlite-core`.
|
|
105
|
+
*
|
|
106
|
+
* @example
|
|
107
|
+
* const src = generateDrizzleSchema([ticketModel, userModel]);
|
|
108
|
+
* fs.writeFileSync("schema.ts", src);
|
|
109
|
+
*/
|
|
110
|
+
export function generateDrizzleSchema(models) {
|
|
111
|
+
// Collect all drizzle imports we need
|
|
112
|
+
const neededImports = new Set(["sqliteTable"]);
|
|
113
|
+
let needsSql = false;
|
|
114
|
+
// First pass: determine imports
|
|
115
|
+
for (const model of models) {
|
|
116
|
+
for (const def of Object.values(model.fields)) {
|
|
117
|
+
const mapping = columnMapping(def.type);
|
|
118
|
+
neededImports.add(mapping.import);
|
|
119
|
+
if (def.default === "now") {
|
|
120
|
+
needsSql = true;
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
// Build import line
|
|
125
|
+
const importNames = [...neededImports].sort();
|
|
126
|
+
const lines = [];
|
|
127
|
+
lines.push(`import { ${importNames.join(", ")} } from "drizzle-orm/sqlite-core";`);
|
|
128
|
+
if (needsSql) {
|
|
129
|
+
lines.push(`import { sql } from "drizzle-orm";`);
|
|
130
|
+
}
|
|
131
|
+
// Generate each table
|
|
132
|
+
for (const model of models) {
|
|
133
|
+
const tableName = pluralise(model.name);
|
|
134
|
+
const varName = tableName;
|
|
135
|
+
lines.push("");
|
|
136
|
+
lines.push(`export const ${varName} = sqliteTable("${tableName}", {`);
|
|
137
|
+
const fieldEntries = Object.entries(model.fields);
|
|
138
|
+
for (let i = 0; i < fieldEntries.length; i++) {
|
|
139
|
+
const [fieldName, def] = fieldEntries[i];
|
|
140
|
+
const expr = buildColumnExpr(fieldName, def);
|
|
141
|
+
const comma = i < fieldEntries.length - 1 ? "," : ",";
|
|
142
|
+
lines.push(` ${fieldName}: ${expr}${comma}`);
|
|
143
|
+
}
|
|
144
|
+
lines.push("});");
|
|
145
|
+
}
|
|
146
|
+
return lines.join("\n") + "\n";
|
|
147
|
+
}
|
|
148
|
+
//# sourceMappingURL=schema.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schema.js","sourceRoot":"","sources":["../src/schema.ts"],"names":[],"mappings":"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"}
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
export type ScalarType = "string" | "integer" | "number" | "boolean" | "date" | "datetime" | "text" | "json";
|
|
2
|
+
export interface FieldDefinition {
|
|
3
|
+
type: ScalarType;
|
|
4
|
+
required?: boolean;
|
|
5
|
+
unique?: boolean;
|
|
6
|
+
default?: unknown;
|
|
7
|
+
min?: number;
|
|
8
|
+
max?: number;
|
|
9
|
+
enum?: readonly string[];
|
|
10
|
+
/** Auto-set to current time on update */
|
|
11
|
+
updatedAt?: boolean;
|
|
12
|
+
/** Auto-generate UUID */
|
|
13
|
+
autoId?: boolean;
|
|
14
|
+
/** Reference to another model */
|
|
15
|
+
references?: string;
|
|
16
|
+
}
|
|
17
|
+
export type RelationKind = "belongsTo" | "hasMany" | "hasOne" | "manyToMany";
|
|
18
|
+
export interface RelationDefinition {
|
|
19
|
+
kind: RelationKind;
|
|
20
|
+
model: string;
|
|
21
|
+
foreignKey?: string;
|
|
22
|
+
through?: string;
|
|
23
|
+
}
|
|
24
|
+
export interface IndexDefinition {
|
|
25
|
+
fields: string[];
|
|
26
|
+
unique?: boolean;
|
|
27
|
+
order?: "asc" | "desc";
|
|
28
|
+
}
|
|
29
|
+
export interface ModelDefinition {
|
|
30
|
+
name: string;
|
|
31
|
+
fields: Record<string, FieldDefinition>;
|
|
32
|
+
relations: Record<string, RelationDefinition>;
|
|
33
|
+
indexes: IndexDefinition[];
|
|
34
|
+
}
|
|
35
|
+
export interface DatabaseConfig {
|
|
36
|
+
provider: "sqlite" | "postgres";
|
|
37
|
+
url: string;
|
|
38
|
+
}
|
|
39
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,UAAU,GAAG,QAAQ,GAAG,SAAS,GAAG,QAAQ,GAAG,SAAS,GAAG,MAAM,GAAG,UAAU,GAAG,MAAM,GAAG,MAAM,CAAC;AAE7G,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,UAAU,CAAC;IACjB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACzB,yCAAyC;IACzC,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,yBAAyB;IACzB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,iCAAiC;IACjC,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,MAAM,YAAY,GAAG,WAAW,GAAG,SAAS,GAAG,QAAQ,GAAG,YAAY,CAAC;AAE7E,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,YAAY,CAAC;IACnB,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,eAAe;IAC9B,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,KAAK,CAAC,EAAE,KAAK,GAAG,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,eAAe,CAAC,CAAC;IACxC,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,kBAAkB,CAAC,CAAC;IAC9C,OAAO,EAAE,eAAe,EAAE,CAAC;CAC5B;AAED,MAAM,WAAW,cAAc;IAC7B,QAAQ,EAAE,QAAQ,GAAG,UAAU,CAAC;IAChC,GAAG,EAAE,MAAM,CAAC;CACb"}
|
package/dist/types.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":""}
|
package/package.json
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@zauso-ai/capstan-db",
|
|
3
|
+
"version": "0.1.2",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"main": "./dist/index.js",
|
|
6
|
+
"types": "./dist/index.d.ts",
|
|
7
|
+
"exports": {
|
|
8
|
+
".": {
|
|
9
|
+
"import": "./dist/index.js",
|
|
10
|
+
"types": "./dist/index.d.ts"
|
|
11
|
+
}
|
|
12
|
+
},
|
|
13
|
+
"scripts": {
|
|
14
|
+
"build": "tsc -p tsconfig.json",
|
|
15
|
+
"typecheck": "tsc -p tsconfig.json --noEmit"
|
|
16
|
+
},
|
|
17
|
+
"dependencies": {
|
|
18
|
+
"drizzle-orm": "^0.44.0",
|
|
19
|
+
"better-sqlite3": "^11.0.0"
|
|
20
|
+
},
|
|
21
|
+
"description": "Database layer for Capstan — Drizzle ORM, defineModel, auto CRUD generation",
|
|
22
|
+
"files": [
|
|
23
|
+
"dist"
|
|
24
|
+
],
|
|
25
|
+
"repository": {
|
|
26
|
+
"type": "git",
|
|
27
|
+
"url": "https://github.com/barry3406/capstan.git",
|
|
28
|
+
"directory": "packages/db"
|
|
29
|
+
},
|
|
30
|
+
"license": "MIT",
|
|
31
|
+
"author": "barry3406",
|
|
32
|
+
"homepage": "https://github.com/barry3406/capstan",
|
|
33
|
+
"keywords": [
|
|
34
|
+
"capstan",
|
|
35
|
+
"ai-agent",
|
|
36
|
+
"full-stack",
|
|
37
|
+
"framework",
|
|
38
|
+
"mcp",
|
|
39
|
+
"a2a",
|
|
40
|
+
"typescript"
|
|
41
|
+
],
|
|
42
|
+
"publishConfig": {
|
|
43
|
+
"access": "public"
|
|
44
|
+
}
|
|
45
|
+
}
|