zitejs 0.9.34 → 0.9.35
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/cjs/runtime/index.js +17 -14
- package/dist/cjs/sync/index.js +22 -22
- package/dist/cjs/sync/lib.js +139 -166
- package/dist/esm/runtime/index.d.ts +13 -7
- package/dist/esm/runtime/index.js +18 -15
- package/dist/esm/sync/index.js +25 -25
- package/dist/esm/sync/lib.d.ts +0 -1
- package/dist/esm/sync/lib.js +139 -165
- package/package.json +1 -1
|
@@ -6,15 +6,15 @@ exports.createSqlClient = createSqlClient;
|
|
|
6
6
|
function getSdkCall() {
|
|
7
7
|
const fn = globalThis.__wrapSdkCall;
|
|
8
8
|
if (!fn) {
|
|
9
|
-
throw new Error(
|
|
9
|
+
throw new Error("Zite SDK runtime not initialized. Endpoints must run inside the Zite worker.");
|
|
10
10
|
}
|
|
11
11
|
return fn;
|
|
12
12
|
}
|
|
13
|
-
const DB_INTEGRATION_ID =
|
|
13
|
+
const DB_INTEGRATION_ID = "databases";
|
|
14
14
|
function getBaseId() {
|
|
15
15
|
try {
|
|
16
|
-
return globalThis.__ZITE_EXECUTION_CONFIG__?.baseId
|
|
17
|
-
|
|
16
|
+
return (globalThis.__ZITE_EXECUTION_CONFIG__?.baseId ??
|
|
17
|
+
(typeof process !== "undefined" ? process.env?.ZITE_BASE_ID : undefined));
|
|
18
18
|
}
|
|
19
19
|
catch {
|
|
20
20
|
return undefined;
|
|
@@ -23,8 +23,8 @@ function getBaseId() {
|
|
|
23
23
|
function resolveTableId(className) {
|
|
24
24
|
try {
|
|
25
25
|
const config = globalThis.__ZITE_EXECUTION_CONFIG__;
|
|
26
|
-
const tables = config?.integrationSettings?.[DB_INTEGRATION_ID]
|
|
27
|
-
?.
|
|
26
|
+
const tables = config?.integrationSettings?.[DB_INTEGRATION_ID]?.settings?.nameMappings
|
|
27
|
+
?.tables;
|
|
28
28
|
if (!tables)
|
|
29
29
|
return className;
|
|
30
30
|
for (const [realId, entry] of Object.entries(tables)) {
|
|
@@ -37,33 +37,33 @@ function resolveTableId(className) {
|
|
|
37
37
|
}
|
|
38
38
|
function createTableClient(className) {
|
|
39
39
|
return {
|
|
40
|
-
findAll: (options) => getSdkCall()(DB_INTEGRATION_ID, className,
|
|
40
|
+
findAll: (options) => getSdkCall()(DB_INTEGRATION_ID, className, "findAll", {
|
|
41
41
|
baseId: getBaseId(),
|
|
42
42
|
tableId: resolveTableId(className),
|
|
43
43
|
...options,
|
|
44
44
|
}),
|
|
45
|
-
findOne: (recordId) => getSdkCall()(DB_INTEGRATION_ID, className,
|
|
45
|
+
findOne: (recordId) => getSdkCall()(DB_INTEGRATION_ID, className, "findOne", {
|
|
46
46
|
baseId: getBaseId(),
|
|
47
47
|
tableId: resolveTableId(className),
|
|
48
|
-
...(typeof recordId ===
|
|
48
|
+
...(typeof recordId === "string" ? { id: recordId } : recordId),
|
|
49
49
|
}),
|
|
50
|
-
create: (data) => getSdkCall()(DB_INTEGRATION_ID, className,
|
|
50
|
+
create: (data) => getSdkCall()(DB_INTEGRATION_ID, className, "create", {
|
|
51
51
|
baseId: getBaseId(),
|
|
52
52
|
tableId: resolveTableId(className),
|
|
53
53
|
record: data,
|
|
54
54
|
}),
|
|
55
|
-
update: (id, data) => getSdkCall()(DB_INTEGRATION_ID, className,
|
|
55
|
+
update: (id, data) => getSdkCall()(DB_INTEGRATION_ID, className, "update", {
|
|
56
56
|
baseId: getBaseId(),
|
|
57
57
|
tableId: resolveTableId(className),
|
|
58
58
|
id,
|
|
59
59
|
record: data,
|
|
60
60
|
}),
|
|
61
|
-
delete: (id) => getSdkCall()(DB_INTEGRATION_ID, className,
|
|
61
|
+
delete: (id) => getSdkCall()(DB_INTEGRATION_ID, className, "delete", {
|
|
62
62
|
baseId: getBaseId(),
|
|
63
63
|
tableId: resolveTableId(className),
|
|
64
64
|
id,
|
|
65
65
|
}),
|
|
66
|
-
bulkCreate: (records) => getSdkCall()(DB_INTEGRATION_ID, className,
|
|
66
|
+
bulkCreate: (records) => getSdkCall()(DB_INTEGRATION_ID, className, "bulkCreate", {
|
|
67
67
|
baseId: getBaseId(),
|
|
68
68
|
tableId: resolveTableId(className),
|
|
69
69
|
records,
|
|
@@ -71,7 +71,10 @@ function createTableClient(className) {
|
|
|
71
71
|
};
|
|
72
72
|
}
|
|
73
73
|
function createSqlClient() {
|
|
74
|
-
return (params) => getSdkCall()(DB_INTEGRATION_ID,
|
|
74
|
+
return (params) => getSdkCall()(DB_INTEGRATION_ID, "Db", "executeSql", {
|
|
75
|
+
baseId: getBaseId(),
|
|
76
|
+
...params,
|
|
77
|
+
});
|
|
75
78
|
}
|
|
76
79
|
var index_js_1 = require("../caller/index.js");
|
|
77
80
|
Object.defineProperty(exports, "createCaller", { enumerable: true, get: function () { return index_js_1.createCaller; } });
|
package/dist/cjs/sync/index.js
CHANGED
|
@@ -7,13 +7,13 @@ const fs_1 = require("fs");
|
|
|
7
7
|
const path_1 = require("path");
|
|
8
8
|
const lib_js_1 = require("./lib.js");
|
|
9
9
|
const DB_ENVIRONMENTS = {
|
|
10
|
-
production:
|
|
11
|
-
staging:
|
|
12
|
-
local:
|
|
10
|
+
production: "https://tables.fillout.com/api/v1",
|
|
11
|
+
staging: "https://tables.filloutstaging.com/api/v1",
|
|
12
|
+
local: "http://localhost:2507/api/v1",
|
|
13
13
|
};
|
|
14
|
-
const env = process.env.ZITE_ENV ??
|
|
14
|
+
const env = process.env.ZITE_ENV ?? "production";
|
|
15
15
|
const BASE_URL = process.env.ZITE_DB_URL ?? DB_ENVIRONMENTS[env] ?? DB_ENVIRONMENTS.production;
|
|
16
|
-
const TOKEN = process.env.ZITE_DB_TOKEN ??
|
|
16
|
+
const TOKEN = process.env.ZITE_DB_TOKEN ?? "";
|
|
17
17
|
async function fetchBaseMetadata(baseId) {
|
|
18
18
|
const url = `${BASE_URL}/bases/${encodeURIComponent(baseId)}`;
|
|
19
19
|
const res = await fetch(url, {
|
|
@@ -28,7 +28,7 @@ function resolveBaseId() {
|
|
|
28
28
|
if (process.env.ZITE_BASE_ID)
|
|
29
29
|
return process.env.ZITE_BASE_ID;
|
|
30
30
|
try {
|
|
31
|
-
const config = JSON.parse((0, fs_1.readFileSync)(
|
|
31
|
+
const config = JSON.parse((0, fs_1.readFileSync)("zite.config.json", "utf-8"));
|
|
32
32
|
return config.project?.basePublicIdentifier;
|
|
33
33
|
}
|
|
34
34
|
catch {
|
|
@@ -37,43 +37,43 @@ function resolveBaseId() {
|
|
|
37
37
|
}
|
|
38
38
|
async function runSync() {
|
|
39
39
|
if (!TOKEN) {
|
|
40
|
-
throw new Error(
|
|
40
|
+
throw new Error("ZITE_DB_TOKEN is required.");
|
|
41
41
|
}
|
|
42
42
|
const baseId = resolveBaseId();
|
|
43
43
|
if (!baseId) {
|
|
44
|
-
throw new Error(
|
|
44
|
+
throw new Error("Could not determine base ID.");
|
|
45
45
|
}
|
|
46
46
|
console.log(`Syncing database ${baseId}...`);
|
|
47
47
|
const base = await fetchBaseMetadata(baseId);
|
|
48
48
|
console.log(`Found ${base.tables?.length ?? 0} tables`);
|
|
49
49
|
const schema = (0, lib_js_1.generateSchema)(base);
|
|
50
|
-
(0, fs_1.writeFileSync)(
|
|
51
|
-
console.log(
|
|
50
|
+
(0, fs_1.writeFileSync)("zite.schema.json", JSON.stringify(schema, null, 2));
|
|
51
|
+
console.log("Wrote zite.schema.json");
|
|
52
52
|
const dbTs = (0, lib_js_1.generateDbTs)(base, schema);
|
|
53
|
-
const dotZite =
|
|
53
|
+
const dotZite = ".zite";
|
|
54
54
|
(0, fs_1.mkdirSync)(dotZite, { recursive: true });
|
|
55
|
-
(0, fs_1.writeFileSync)((0, path_1.join)(dotZite,
|
|
56
|
-
console.log(
|
|
55
|
+
(0, fs_1.writeFileSync)((0, path_1.join)(dotZite, "db.ts"), dbTs);
|
|
56
|
+
console.log("Wrote .zite/db.ts");
|
|
57
57
|
regenerateApiTs();
|
|
58
|
-
console.log(
|
|
58
|
+
console.log("Done!");
|
|
59
59
|
}
|
|
60
60
|
function regenerateApiTs() {
|
|
61
|
-
const apiDir = (0, path_1.join)(
|
|
61
|
+
const apiDir = (0, path_1.join)("src", "api");
|
|
62
62
|
if (!(0, fs_1.existsSync)(apiDir))
|
|
63
63
|
return;
|
|
64
|
-
const endpointFiles = (0, fs_1.readdirSync)(apiDir).filter((f) => f.endsWith(
|
|
64
|
+
const endpointFiles = (0, fs_1.readdirSync)(apiDir).filter((f) => f.endsWith(".ts") || f.endsWith(".js"));
|
|
65
65
|
const apiTs = (0, lib_js_1.generateApiTs)(endpointFiles);
|
|
66
66
|
if (apiTs) {
|
|
67
|
-
(0, fs_1.mkdirSync)(
|
|
68
|
-
(0, fs_1.writeFileSync)((0, path_1.join)(
|
|
69
|
-
console.log(
|
|
67
|
+
(0, fs_1.mkdirSync)(".zite", { recursive: true });
|
|
68
|
+
(0, fs_1.writeFileSync)((0, path_1.join)(".zite", "api.ts"), apiTs);
|
|
69
|
+
console.log("Wrote .zite/api.ts");
|
|
70
70
|
}
|
|
71
71
|
}
|
|
72
72
|
// Direct execution (npx zitejs sync)
|
|
73
|
-
if (process.argv[1]?.endsWith(
|
|
74
|
-
process.argv[1]?.endsWith(
|
|
73
|
+
if (process.argv[1]?.endsWith("sync/index.js") ||
|
|
74
|
+
process.argv[1]?.endsWith("sync/index.ts")) {
|
|
75
75
|
runSync().catch((err) => {
|
|
76
|
-
console.error(
|
|
76
|
+
console.error("Sync failed:", err.message);
|
|
77
77
|
process.exit(1);
|
|
78
78
|
});
|
|
79
79
|
}
|
package/dist/cjs/sync/lib.js
CHANGED
|
@@ -4,32 +4,31 @@ exports.toPascalCase = toPascalCase;
|
|
|
4
4
|
exports.toCamelCase = toCamelCase;
|
|
5
5
|
exports.generateSchema = generateSchema;
|
|
6
6
|
exports.generateDbTs = generateDbTs;
|
|
7
|
-
exports.generateDbDts = generateDbDts;
|
|
8
7
|
exports.generateApiTs = generateApiTs;
|
|
9
8
|
exports.generateUserTs = generateUserTs;
|
|
10
9
|
exports.generateAuthWrapperTs = generateAuthWrapperTs;
|
|
11
10
|
exports.generateBackendWrapperTs = generateBackendWrapperTs;
|
|
12
11
|
const FIELD_TYPE_MAP = {
|
|
13
|
-
single_line_text:
|
|
14
|
-
long_text:
|
|
15
|
-
email:
|
|
16
|
-
url:
|
|
17
|
-
phone_number:
|
|
18
|
-
number:
|
|
19
|
-
currency:
|
|
20
|
-
percent:
|
|
21
|
-
rating:
|
|
22
|
-
duration:
|
|
23
|
-
single_select:
|
|
24
|
-
multiple_select:
|
|
25
|
-
checkbox:
|
|
26
|
-
date:
|
|
27
|
-
datetime:
|
|
28
|
-
attachments:
|
|
29
|
-
linked_record:
|
|
30
|
-
lookup:
|
|
31
|
-
autonumber:
|
|
32
|
-
source:
|
|
12
|
+
single_line_text: "string",
|
|
13
|
+
long_text: "string",
|
|
14
|
+
email: "string",
|
|
15
|
+
url: "string",
|
|
16
|
+
phone_number: "string",
|
|
17
|
+
number: "number",
|
|
18
|
+
currency: "number",
|
|
19
|
+
percent: "number",
|
|
20
|
+
rating: "number",
|
|
21
|
+
duration: "number",
|
|
22
|
+
single_select: "string",
|
|
23
|
+
multiple_select: "string[]",
|
|
24
|
+
checkbox: "boolean",
|
|
25
|
+
date: "string",
|
|
26
|
+
datetime: "string",
|
|
27
|
+
attachments: "Array<{ url: string; name?: string }>",
|
|
28
|
+
linked_record: "string | string[]",
|
|
29
|
+
lookup: "unknown",
|
|
30
|
+
autonumber: "number",
|
|
31
|
+
source: "string",
|
|
33
32
|
};
|
|
34
33
|
function toPascalCase(name) {
|
|
35
34
|
return name
|
|
@@ -43,11 +42,14 @@ function toCamelCase(name) {
|
|
|
43
42
|
function tsTypeForField(field) {
|
|
44
43
|
if (FIELD_TYPE_MAP[field.type])
|
|
45
44
|
return FIELD_TYPE_MAP[field.type];
|
|
46
|
-
const lowerName = field.name?.toLowerCase() ??
|
|
47
|
-
if (lowerName ===
|
|
48
|
-
|
|
45
|
+
const lowerName = field.name?.toLowerCase() ?? "";
|
|
46
|
+
if (lowerName === "createdat" ||
|
|
47
|
+
lowerName === "created_at" ||
|
|
48
|
+
lowerName === "updatedat" ||
|
|
49
|
+
lowerName === "updated_at") {
|
|
50
|
+
return "string";
|
|
49
51
|
}
|
|
50
|
-
return
|
|
52
|
+
return "string";
|
|
51
53
|
}
|
|
52
54
|
function generateSchema(base) {
|
|
53
55
|
const schema = { tables: {} };
|
|
@@ -63,220 +65,191 @@ function generateSchema(base) {
|
|
|
63
65
|
}
|
|
64
66
|
function generateDbTs(base, schema) {
|
|
65
67
|
const lines = [];
|
|
66
|
-
lines.push(
|
|
67
|
-
lines.push(
|
|
68
|
-
lines.push(
|
|
68
|
+
lines.push("// Auto-generated by zitejs sync. Do not edit manually.");
|
|
69
|
+
lines.push("//");
|
|
70
|
+
lines.push("// Usage in endpoint files (src/api/*.ts):");
|
|
69
71
|
lines.push('// import { zite } from "zitejs/db";');
|
|
70
|
-
lines.push(
|
|
72
|
+
lines.push("//");
|
|
71
73
|
lines.push('// Always use "zitejs/db" — never use relative paths like "../../.zite/db".');
|
|
72
|
-
lines.push(
|
|
73
|
-
lines.push(
|
|
74
|
-
lines.push(
|
|
75
|
-
lines.push(
|
|
76
|
-
lines.push(
|
|
77
|
-
lines.push(
|
|
78
|
-
lines.push(
|
|
79
|
-
lines.push(
|
|
80
|
-
lines.push(
|
|
81
|
-
lines.push(
|
|
82
|
-
lines.push(
|
|
83
|
-
lines.push(
|
|
74
|
+
lines.push("// The tsconfig aliases resolve zitejs/* imports to the correct .zite/ files.");
|
|
75
|
+
lines.push("//");
|
|
76
|
+
lines.push("// Table client methods:");
|
|
77
|
+
lines.push("// .findAll(opts?) → { records: T[], total: number, hasMore: boolean }");
|
|
78
|
+
lines.push("// opts: { limit?, offset?, sort?, filter?, filters? }");
|
|
79
|
+
lines.push("// .findOne(id | { filters }) → T");
|
|
80
|
+
lines.push("// .create({ record }) → T");
|
|
81
|
+
lines.push("// .update(id, { record }) → T");
|
|
82
|
+
lines.push("// .delete(id) → { deleted: true }");
|
|
83
|
+
lines.push("// .bulkCreate(records) → T[]");
|
|
84
|
+
lines.push("//");
|
|
85
|
+
lines.push("// Raw SQL (read-only SELECTs for aggregates, joins, multi-table queries):");
|
|
86
|
+
lines.push('// zite.sql({ query: "SELECT ...", params?: [...] })');
|
|
87
|
+
lines.push("// → { rows: Record<string, unknown>[], columns, rowCount, truncated }");
|
|
88
|
+
lines.push("//");
|
|
89
|
+
lines.push("// SQL guidelines:");
|
|
90
|
+
lines.push("// - Use SDK names for tables (PascalCase) and fields (camelCase)");
|
|
91
|
+
lines.push('// - ALWAYS double-quote every identifier: FROM "Orders", WHERE "status" = $1');
|
|
92
|
+
lines.push("// - Use params array for user input ($1, $2, ...): never interpolate into SQL");
|
|
93
|
+
lines.push('// - Link tables: alphabetical PascalCase concat (Items+Orders → "ItemsOrders")');
|
|
94
|
+
lines.push('// with id columns: "itemsId", "ordersId"');
|
|
95
|
+
lines.push("// - Soft-deleted rows are excluded automatically — no WHERE deleted_at IS NULL");
|
|
96
|
+
lines.push("// - SELECT only — use .create/.update/.delete for writes");
|
|
97
|
+
lines.push('// - Load the "zite:sql" skill for full SQL reference (formulas, lookups, etc.)');
|
|
84
98
|
lines.push("import { createTableClient, createSqlClient } from 'zitejs/runtime';");
|
|
85
|
-
lines.push(
|
|
99
|
+
lines.push("");
|
|
86
100
|
for (const table of base.tables ?? []) {
|
|
87
101
|
const className = toPascalCase(table.name);
|
|
88
102
|
const recordType = `${className}RecordType`;
|
|
89
103
|
lines.push(`export type ${recordType} = {`);
|
|
90
|
-
lines.push(
|
|
104
|
+
lines.push(" id: string;");
|
|
91
105
|
for (const field of table.fields ?? []) {
|
|
92
106
|
const fieldName = toCamelCase(field.name);
|
|
93
|
-
if (fieldName ===
|
|
107
|
+
if (fieldName === "id")
|
|
94
108
|
continue;
|
|
95
109
|
const tsType = tsTypeForField(field);
|
|
96
110
|
lines.push(` ${fieldName}: ${tsType};`);
|
|
97
111
|
}
|
|
98
|
-
lines.push(
|
|
99
|
-
lines.push(
|
|
112
|
+
lines.push("};");
|
|
113
|
+
lines.push("");
|
|
100
114
|
}
|
|
101
|
-
lines.push(
|
|
115
|
+
lines.push("export const zite = {");
|
|
102
116
|
for (const table of base.tables ?? []) {
|
|
103
117
|
const className = toPascalCase(table.name);
|
|
104
118
|
const propName = toCamelCase(table.name);
|
|
105
119
|
lines.push(` ${propName}: createTableClient<${className}RecordType>('${className}'),`);
|
|
106
120
|
}
|
|
107
121
|
lines.push(` sql: createSqlClient(),`);
|
|
108
|
-
lines.push(
|
|
109
|
-
lines.push(
|
|
110
|
-
return lines.join(
|
|
111
|
-
}
|
|
112
|
-
function generateDbDts(base, schema) {
|
|
113
|
-
const lines = [
|
|
114
|
-
'// Auto-generated by zitejs sync. Do not edit manually.',
|
|
115
|
-
'// Type declarations for IDE and LLM context. See db.ts for runtime.',
|
|
116
|
-
'',
|
|
117
|
-
'interface TableClient<T> {',
|
|
118
|
-
' findAll(options?: { limit?: number; offset?: number; sort?: unknown[]; filter?: unknown; filters?: unknown }): Promise<{ records: T[]; total: number; hasMore: boolean }>;',
|
|
119
|
-
' findOne(recordId: string | { filters?: unknown; filter?: unknown }): Promise<T>;',
|
|
120
|
-
' create(data: Partial<T>): Promise<T>;',
|
|
121
|
-
' update(id: string, data: Partial<T>): Promise<T>;',
|
|
122
|
-
' delete(id: string): Promise<{ deleted: true }>;',
|
|
123
|
-
' bulkCreate(records: Partial<T>[]): Promise<T[]>;',
|
|
124
|
-
'}',
|
|
125
|
-
'',
|
|
126
|
-
];
|
|
127
|
-
for (const table of base.tables ?? []) {
|
|
128
|
-
const className = toPascalCase(table.name);
|
|
129
|
-
const recordType = `${className}RecordType`;
|
|
130
|
-
lines.push(`export type ${recordType} = {`);
|
|
131
|
-
lines.push(' id: string;');
|
|
132
|
-
for (const field of table.fields ?? []) {
|
|
133
|
-
const fieldName = toCamelCase(field.name);
|
|
134
|
-
if (fieldName === 'id')
|
|
135
|
-
continue;
|
|
136
|
-
const tsType = tsTypeForField(field);
|
|
137
|
-
lines.push(` ${fieldName}: ${tsType};`);
|
|
138
|
-
}
|
|
139
|
-
lines.push('};');
|
|
140
|
-
lines.push('');
|
|
141
|
-
}
|
|
142
|
-
lines.push('export declare const zite: {');
|
|
143
|
-
for (const table of base.tables ?? []) {
|
|
144
|
-
const className = toPascalCase(table.name);
|
|
145
|
-
const propName = toCamelCase(table.name);
|
|
146
|
-
lines.push(` ${propName}: TableClient<${className}RecordType>;`);
|
|
147
|
-
}
|
|
148
|
-
lines.push(' sql: (params: { query?: string; sql?: string; params?: unknown[] }) => Promise<{ rows: Record<string, unknown>[] }>;');
|
|
149
|
-
lines.push('};');
|
|
150
|
-
lines.push('');
|
|
151
|
-
return lines.join('\n');
|
|
122
|
+
lines.push("};");
|
|
123
|
+
lines.push("");
|
|
124
|
+
return lines.join("\n");
|
|
152
125
|
}
|
|
153
126
|
function generateApiTs(endpointFiles) {
|
|
154
127
|
if (!endpointFiles || endpointFiles.length === 0)
|
|
155
128
|
return null;
|
|
156
129
|
const lines = [
|
|
157
|
-
|
|
158
|
-
|
|
130
|
+
"// Auto-generated by zitejs sync. Do not edit manually.",
|
|
131
|
+
"",
|
|
159
132
|
"import { createCaller } from 'zitejs/caller';",
|
|
160
|
-
|
|
133
|
+
"",
|
|
161
134
|
];
|
|
162
135
|
const endpointNames = [];
|
|
163
136
|
for (const file of endpointFiles) {
|
|
164
|
-
const name = file.replace(/\.(ts|js)$/,
|
|
137
|
+
const name = file.replace(/\.(ts|js)$/, "");
|
|
165
138
|
const camelName = toCamelCase(name);
|
|
166
139
|
lines.push(`import ${camelName}Endpoint from '../src/api/${name}';`);
|
|
167
140
|
endpointNames.push(camelName);
|
|
168
141
|
}
|
|
169
|
-
lines.push(
|
|
142
|
+
lines.push("");
|
|
170
143
|
for (const name of endpointNames) {
|
|
171
144
|
lines.push(`export const ${name} = createCaller(${name}Endpoint, '${name}');`);
|
|
172
145
|
}
|
|
173
|
-
lines.push(
|
|
146
|
+
lines.push("");
|
|
174
147
|
// Inferred input/output types per endpoint (e.g. GetDashboardInputType, GetDashboardOutputType)
|
|
175
148
|
for (const name of endpointNames) {
|
|
176
149
|
const pascal = toPascalCase(name);
|
|
177
150
|
lines.push(`export type ${pascal}InputType = Parameters<typeof ${name}Endpoint.execute>[0]['input'];`);
|
|
178
151
|
lines.push(`export type ${pascal}OutputType = Awaited<ReturnType<typeof ${name}Endpoint.execute>>;`);
|
|
179
152
|
}
|
|
180
|
-
lines.push(
|
|
153
|
+
lines.push("");
|
|
181
154
|
// Also export as a single api object
|
|
182
|
-
lines.push(
|
|
155
|
+
lines.push("export const api = {");
|
|
183
156
|
for (const name of endpointNames) {
|
|
184
157
|
lines.push(` ${name},`);
|
|
185
158
|
}
|
|
186
|
-
lines.push(
|
|
187
|
-
lines.push(
|
|
188
|
-
return lines.join(
|
|
159
|
+
lines.push("};");
|
|
160
|
+
lines.push("");
|
|
161
|
+
return lines.join("\n");
|
|
189
162
|
}
|
|
190
163
|
function generateUserTs(usersTableFields) {
|
|
191
164
|
const lines = [
|
|
192
|
-
|
|
193
|
-
|
|
165
|
+
"// Auto-generated by zitejs sync. Do not edit manually.",
|
|
166
|
+
"",
|
|
194
167
|
];
|
|
195
168
|
if (usersTableFields && usersTableFields.length > 0) {
|
|
196
|
-
lines.push(
|
|
197
|
-
lines.push(
|
|
198
|
-
lines.push(
|
|
169
|
+
lines.push("export type User = {");
|
|
170
|
+
lines.push(" id: string;");
|
|
171
|
+
lines.push(" email: string;");
|
|
199
172
|
for (const field of usersTableFields) {
|
|
200
173
|
const lowerName = field.name.toLowerCase();
|
|
201
|
-
if (lowerName ===
|
|
174
|
+
if (lowerName === "id" || lowerName === "email")
|
|
202
175
|
continue;
|
|
203
176
|
const fieldName = toCamelCase(field.name);
|
|
204
177
|
const tsType = tsTypeForField(field);
|
|
205
178
|
lines.push(` ${fieldName}: ${tsType};`);
|
|
206
179
|
}
|
|
207
|
-
lines.push(
|
|
208
|
-
lines.push(
|
|
180
|
+
lines.push(" [key: string]: unknown;");
|
|
181
|
+
lines.push("};");
|
|
209
182
|
}
|
|
210
183
|
else {
|
|
211
|
-
lines.push(
|
|
212
|
-
lines.push(
|
|
213
|
-
lines.push(
|
|
214
|
-
lines.push(
|
|
215
|
-
lines.push(
|
|
216
|
-
lines.push(
|
|
217
|
-
lines.push(
|
|
184
|
+
lines.push("export type User = {");
|
|
185
|
+
lines.push(" id: string;");
|
|
186
|
+
lines.push(" email: string;");
|
|
187
|
+
lines.push(" firstName?: string;");
|
|
188
|
+
lines.push(" lastName?: string;");
|
|
189
|
+
lines.push(" [key: string]: unknown;");
|
|
190
|
+
lines.push("};");
|
|
218
191
|
}
|
|
219
|
-
lines.push(
|
|
220
|
-
return lines.join(
|
|
192
|
+
lines.push("");
|
|
193
|
+
return lines.join("\n");
|
|
221
194
|
}
|
|
222
195
|
function generateAuthWrapperTs() {
|
|
223
196
|
return [
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
197
|
+
"// Auto-generated type-narrowing wrapper. Do not edit manually.",
|
|
198
|
+
"// The real auth logic lives in the zitejs npm package (zitejs/auth).",
|
|
199
|
+
"",
|
|
227
200
|
"import { useAuth as _useAuth } from 'zitejs/auth/base';",
|
|
228
201
|
"import type { User } from './user';",
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
].join(
|
|
202
|
+
"",
|
|
203
|
+
"export type { User };",
|
|
204
|
+
"",
|
|
205
|
+
"export function useAuth() {",
|
|
206
|
+
" return _useAuth() as ReturnType<typeof _useAuth> & { user: User | undefined };",
|
|
207
|
+
"}",
|
|
208
|
+
"",
|
|
209
|
+
].join("\n");
|
|
237
210
|
}
|
|
238
211
|
function generateBackendWrapperTs() {
|
|
239
212
|
return [
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
213
|
+
"// Auto-generated type-narrowing wrapper. Do not edit manually.",
|
|
214
|
+
"// Re-exports createEndpoint with context.user typed to the app User.",
|
|
215
|
+
"",
|
|
243
216
|
"import type { ZiteRequestContext as _ZiteRequestContext, ZiteScheduledContext as _ZiteScheduledContext } from 'zitejs/backend/base';",
|
|
244
217
|
"import type { User } from './user';",
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
218
|
+
"",
|
|
219
|
+
"export class ZiteError extends Error {",
|
|
220
|
+
" statusCode: number;",
|
|
221
|
+
" constructor(message: string, options?: { statusCode?: number }) {",
|
|
222
|
+
" super(message);",
|
|
250
223
|
" this.name = 'ZiteError';",
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
224
|
+
" this.statusCode = options?.statusCode ?? 500;",
|
|
225
|
+
" }",
|
|
226
|
+
"}",
|
|
227
|
+
"",
|
|
255
228
|
'export interface ZiteRequestContext extends Omit<_ZiteRequestContext, "user"> {',
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
229
|
+
" user: User;",
|
|
230
|
+
"}",
|
|
231
|
+
"",
|
|
259
232
|
'export interface ZiteScheduledContext extends Omit<_ZiteScheduledContext, "user"> {',
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
233
|
+
" user: User;",
|
|
234
|
+
" scheduledAt: string;",
|
|
235
|
+
"}",
|
|
236
|
+
"",
|
|
264
237
|
"type SchemaLike<T> = { _output: T; parse: (data: unknown) => T };",
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
].join(
|
|
238
|
+
"",
|
|
239
|
+
"export interface EndpointConfig<TInput = unknown, TOutput = unknown> {",
|
|
240
|
+
" description?: string;",
|
|
241
|
+
" inputSchema?: SchemaLike<TInput>;",
|
|
242
|
+
" outputSchema?: SchemaLike<TOutput>;",
|
|
243
|
+
" stream?: boolean;",
|
|
244
|
+
" authenticated?: boolean;",
|
|
245
|
+
" execute: (params: { input: TInput; context: ZiteRequestContext | ZiteScheduledContext }) => Promise<TOutput> | TOutput;",
|
|
246
|
+
"}",
|
|
247
|
+
"",
|
|
248
|
+
"export function createEndpoint<TInput = unknown, TOutput = unknown>(",
|
|
249
|
+
" config: EndpointConfig<TInput, TOutput>,",
|
|
250
|
+
"): EndpointConfig<TInput, TOutput> {",
|
|
251
|
+
" return config;",
|
|
252
|
+
"}",
|
|
253
|
+
"",
|
|
254
|
+
].join("\n");
|
|
282
255
|
}
|
|
@@ -22,12 +22,18 @@ export interface TableClient<T> {
|
|
|
22
22
|
bulkCreate(records: Partial<T>[]): Promise<T[]>;
|
|
23
23
|
}
|
|
24
24
|
export declare function createTableClient<T>(className: string): TableClient<T>;
|
|
25
|
+
export interface SqlResult {
|
|
26
|
+
rows: Record<string, unknown>[];
|
|
27
|
+
columns: Array<{
|
|
28
|
+
name: string;
|
|
29
|
+
originalName: string;
|
|
30
|
+
}>;
|
|
31
|
+
rowCount: number;
|
|
32
|
+
truncated: boolean;
|
|
33
|
+
}
|
|
25
34
|
export declare function createSqlClient(): (params: {
|
|
26
|
-
query
|
|
27
|
-
sql?: string;
|
|
35
|
+
query: string;
|
|
28
36
|
params?: unknown[];
|
|
29
|
-
}) => Promise<
|
|
30
|
-
|
|
31
|
-
}
|
|
32
|
-
export { createCaller } from '../caller/index.js';
|
|
33
|
-
export type { EndpointConfig } from '../caller/index.js';
|
|
37
|
+
}) => Promise<SqlResult>;
|
|
38
|
+
export { createCaller } from "../caller/index.js";
|
|
39
|
+
export type { EndpointConfig } from "../caller/index.js";
|
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
function getSdkCall() {
|
|
2
2
|
const fn = globalThis.__wrapSdkCall;
|
|
3
3
|
if (!fn) {
|
|
4
|
-
throw new Error(
|
|
4
|
+
throw new Error("Zite SDK runtime not initialized. Endpoints must run inside the Zite worker.");
|
|
5
5
|
}
|
|
6
6
|
return fn;
|
|
7
7
|
}
|
|
8
|
-
const DB_INTEGRATION_ID =
|
|
8
|
+
const DB_INTEGRATION_ID = "databases";
|
|
9
9
|
function getBaseId() {
|
|
10
10
|
try {
|
|
11
|
-
return globalThis.__ZITE_EXECUTION_CONFIG__?.baseId
|
|
12
|
-
|
|
11
|
+
return (globalThis.__ZITE_EXECUTION_CONFIG__?.baseId ??
|
|
12
|
+
(typeof process !== "undefined" ? process.env?.ZITE_BASE_ID : undefined));
|
|
13
13
|
}
|
|
14
14
|
catch {
|
|
15
15
|
return undefined;
|
|
@@ -18,8 +18,8 @@ function getBaseId() {
|
|
|
18
18
|
function resolveTableId(className) {
|
|
19
19
|
try {
|
|
20
20
|
const config = globalThis.__ZITE_EXECUTION_CONFIG__;
|
|
21
|
-
const tables = config?.integrationSettings?.[DB_INTEGRATION_ID]
|
|
22
|
-
?.
|
|
21
|
+
const tables = config?.integrationSettings?.[DB_INTEGRATION_ID]?.settings?.nameMappings
|
|
22
|
+
?.tables;
|
|
23
23
|
if (!tables)
|
|
24
24
|
return className;
|
|
25
25
|
for (const [realId, entry] of Object.entries(tables)) {
|
|
@@ -32,33 +32,33 @@ function resolveTableId(className) {
|
|
|
32
32
|
}
|
|
33
33
|
export function createTableClient(className) {
|
|
34
34
|
return {
|
|
35
|
-
findAll: (options) => getSdkCall()(DB_INTEGRATION_ID, className,
|
|
35
|
+
findAll: (options) => getSdkCall()(DB_INTEGRATION_ID, className, "findAll", {
|
|
36
36
|
baseId: getBaseId(),
|
|
37
37
|
tableId: resolveTableId(className),
|
|
38
38
|
...options,
|
|
39
39
|
}),
|
|
40
|
-
findOne: (recordId) => getSdkCall()(DB_INTEGRATION_ID, className,
|
|
40
|
+
findOne: (recordId) => getSdkCall()(DB_INTEGRATION_ID, className, "findOne", {
|
|
41
41
|
baseId: getBaseId(),
|
|
42
42
|
tableId: resolveTableId(className),
|
|
43
|
-
...(typeof recordId ===
|
|
43
|
+
...(typeof recordId === "string" ? { id: recordId } : recordId),
|
|
44
44
|
}),
|
|
45
|
-
create: (data) => getSdkCall()(DB_INTEGRATION_ID, className,
|
|
45
|
+
create: (data) => getSdkCall()(DB_INTEGRATION_ID, className, "create", {
|
|
46
46
|
baseId: getBaseId(),
|
|
47
47
|
tableId: resolveTableId(className),
|
|
48
48
|
record: data,
|
|
49
49
|
}),
|
|
50
|
-
update: (id, data) => getSdkCall()(DB_INTEGRATION_ID, className,
|
|
50
|
+
update: (id, data) => getSdkCall()(DB_INTEGRATION_ID, className, "update", {
|
|
51
51
|
baseId: getBaseId(),
|
|
52
52
|
tableId: resolveTableId(className),
|
|
53
53
|
id,
|
|
54
54
|
record: data,
|
|
55
55
|
}),
|
|
56
|
-
delete: (id) => getSdkCall()(DB_INTEGRATION_ID, className,
|
|
56
|
+
delete: (id) => getSdkCall()(DB_INTEGRATION_ID, className, "delete", {
|
|
57
57
|
baseId: getBaseId(),
|
|
58
58
|
tableId: resolveTableId(className),
|
|
59
59
|
id,
|
|
60
60
|
}),
|
|
61
|
-
bulkCreate: (records) => getSdkCall()(DB_INTEGRATION_ID, className,
|
|
61
|
+
bulkCreate: (records) => getSdkCall()(DB_INTEGRATION_ID, className, "bulkCreate", {
|
|
62
62
|
baseId: getBaseId(),
|
|
63
63
|
tableId: resolveTableId(className),
|
|
64
64
|
records,
|
|
@@ -66,6 +66,9 @@ export function createTableClient(className) {
|
|
|
66
66
|
};
|
|
67
67
|
}
|
|
68
68
|
export function createSqlClient() {
|
|
69
|
-
return (params) => getSdkCall()(DB_INTEGRATION_ID,
|
|
69
|
+
return (params) => getSdkCall()(DB_INTEGRATION_ID, "Db", "executeSql", {
|
|
70
|
+
baseId: getBaseId(),
|
|
71
|
+
...params,
|
|
72
|
+
});
|
|
70
73
|
}
|
|
71
|
-
export { createCaller } from
|
|
74
|
+
export { createCaller } from "../caller/index.js";
|
package/dist/esm/sync/index.js
CHANGED
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { readFileSync, writeFileSync, mkdirSync, existsSync, readdirSync, } from
|
|
3
|
-
import { join } from
|
|
4
|
-
import { generateSchema, generateDbTs, generateApiTs
|
|
2
|
+
import { readFileSync, writeFileSync, mkdirSync, existsSync, readdirSync, } from "fs";
|
|
3
|
+
import { join } from "path";
|
|
4
|
+
import { generateSchema, generateDbTs, generateApiTs } from "./lib.js";
|
|
5
5
|
const DB_ENVIRONMENTS = {
|
|
6
|
-
production:
|
|
7
|
-
staging:
|
|
8
|
-
local:
|
|
6
|
+
production: "https://tables.fillout.com/api/v1",
|
|
7
|
+
staging: "https://tables.filloutstaging.com/api/v1",
|
|
8
|
+
local: "http://localhost:2507/api/v1",
|
|
9
9
|
};
|
|
10
|
-
const env = process.env.ZITE_ENV ??
|
|
10
|
+
const env = process.env.ZITE_ENV ?? "production";
|
|
11
11
|
const BASE_URL = process.env.ZITE_DB_URL ?? DB_ENVIRONMENTS[env] ?? DB_ENVIRONMENTS.production;
|
|
12
|
-
const TOKEN = process.env.ZITE_DB_TOKEN ??
|
|
12
|
+
const TOKEN = process.env.ZITE_DB_TOKEN ?? "";
|
|
13
13
|
async function fetchBaseMetadata(baseId) {
|
|
14
14
|
const url = `${BASE_URL}/bases/${encodeURIComponent(baseId)}`;
|
|
15
15
|
const res = await fetch(url, {
|
|
@@ -24,7 +24,7 @@ function resolveBaseId() {
|
|
|
24
24
|
if (process.env.ZITE_BASE_ID)
|
|
25
25
|
return process.env.ZITE_BASE_ID;
|
|
26
26
|
try {
|
|
27
|
-
const config = JSON.parse(readFileSync(
|
|
27
|
+
const config = JSON.parse(readFileSync("zite.config.json", "utf-8"));
|
|
28
28
|
return config.project?.basePublicIdentifier;
|
|
29
29
|
}
|
|
30
30
|
catch {
|
|
@@ -33,43 +33,43 @@ function resolveBaseId() {
|
|
|
33
33
|
}
|
|
34
34
|
export async function runSync() {
|
|
35
35
|
if (!TOKEN) {
|
|
36
|
-
throw new Error(
|
|
36
|
+
throw new Error("ZITE_DB_TOKEN is required.");
|
|
37
37
|
}
|
|
38
38
|
const baseId = resolveBaseId();
|
|
39
39
|
if (!baseId) {
|
|
40
|
-
throw new Error(
|
|
40
|
+
throw new Error("Could not determine base ID.");
|
|
41
41
|
}
|
|
42
42
|
console.log(`Syncing database ${baseId}...`);
|
|
43
43
|
const base = await fetchBaseMetadata(baseId);
|
|
44
44
|
console.log(`Found ${base.tables?.length ?? 0} tables`);
|
|
45
45
|
const schema = generateSchema(base);
|
|
46
|
-
writeFileSync(
|
|
47
|
-
console.log(
|
|
46
|
+
writeFileSync("zite.schema.json", JSON.stringify(schema, null, 2));
|
|
47
|
+
console.log("Wrote zite.schema.json");
|
|
48
48
|
const dbTs = generateDbTs(base, schema);
|
|
49
|
-
const dotZite =
|
|
49
|
+
const dotZite = ".zite";
|
|
50
50
|
mkdirSync(dotZite, { recursive: true });
|
|
51
|
-
writeFileSync(join(dotZite,
|
|
52
|
-
console.log(
|
|
51
|
+
writeFileSync(join(dotZite, "db.ts"), dbTs);
|
|
52
|
+
console.log("Wrote .zite/db.ts");
|
|
53
53
|
regenerateApiTs();
|
|
54
|
-
console.log(
|
|
54
|
+
console.log("Done!");
|
|
55
55
|
}
|
|
56
56
|
export function regenerateApiTs() {
|
|
57
|
-
const apiDir = join(
|
|
57
|
+
const apiDir = join("src", "api");
|
|
58
58
|
if (!existsSync(apiDir))
|
|
59
59
|
return;
|
|
60
|
-
const endpointFiles = readdirSync(apiDir).filter((f) => f.endsWith(
|
|
60
|
+
const endpointFiles = readdirSync(apiDir).filter((f) => f.endsWith(".ts") || f.endsWith(".js"));
|
|
61
61
|
const apiTs = generateApiTs(endpointFiles);
|
|
62
62
|
if (apiTs) {
|
|
63
|
-
mkdirSync(
|
|
64
|
-
writeFileSync(join(
|
|
65
|
-
console.log(
|
|
63
|
+
mkdirSync(".zite", { recursive: true });
|
|
64
|
+
writeFileSync(join(".zite", "api.ts"), apiTs);
|
|
65
|
+
console.log("Wrote .zite/api.ts");
|
|
66
66
|
}
|
|
67
67
|
}
|
|
68
68
|
// Direct execution (npx zitejs sync)
|
|
69
|
-
if (process.argv[1]?.endsWith(
|
|
70
|
-
process.argv[1]?.endsWith(
|
|
69
|
+
if (process.argv[1]?.endsWith("sync/index.js") ||
|
|
70
|
+
process.argv[1]?.endsWith("sync/index.ts")) {
|
|
71
71
|
runSync().catch((err) => {
|
|
72
|
-
console.error(
|
|
72
|
+
console.error("Sync failed:", err.message);
|
|
73
73
|
process.exit(1);
|
|
74
74
|
});
|
|
75
75
|
}
|
package/dist/esm/sync/lib.d.ts
CHANGED
|
@@ -21,7 +21,6 @@ export declare function toPascalCase(name: string): string;
|
|
|
21
21
|
export declare function toCamelCase(name: string): string;
|
|
22
22
|
export declare function generateSchema(base: BaseMetadata): ZiteSchema;
|
|
23
23
|
export declare function generateDbTs(base: BaseMetadata, schema: ZiteSchema): string;
|
|
24
|
-
export declare function generateDbDts(base: BaseMetadata, schema: ZiteSchema): string;
|
|
25
24
|
export declare function generateApiTs(endpointFiles: string[]): string | null;
|
|
26
25
|
export declare function generateUserTs(usersTableFields?: Array<{
|
|
27
26
|
name: string;
|
package/dist/esm/sync/lib.js
CHANGED
|
@@ -1,24 +1,24 @@
|
|
|
1
1
|
const FIELD_TYPE_MAP = {
|
|
2
|
-
single_line_text:
|
|
3
|
-
long_text:
|
|
4
|
-
email:
|
|
5
|
-
url:
|
|
6
|
-
phone_number:
|
|
7
|
-
number:
|
|
8
|
-
currency:
|
|
9
|
-
percent:
|
|
10
|
-
rating:
|
|
11
|
-
duration:
|
|
12
|
-
single_select:
|
|
13
|
-
multiple_select:
|
|
14
|
-
checkbox:
|
|
15
|
-
date:
|
|
16
|
-
datetime:
|
|
17
|
-
attachments:
|
|
18
|
-
linked_record:
|
|
19
|
-
lookup:
|
|
20
|
-
autonumber:
|
|
21
|
-
source:
|
|
2
|
+
single_line_text: "string",
|
|
3
|
+
long_text: "string",
|
|
4
|
+
email: "string",
|
|
5
|
+
url: "string",
|
|
6
|
+
phone_number: "string",
|
|
7
|
+
number: "number",
|
|
8
|
+
currency: "number",
|
|
9
|
+
percent: "number",
|
|
10
|
+
rating: "number",
|
|
11
|
+
duration: "number",
|
|
12
|
+
single_select: "string",
|
|
13
|
+
multiple_select: "string[]",
|
|
14
|
+
checkbox: "boolean",
|
|
15
|
+
date: "string",
|
|
16
|
+
datetime: "string",
|
|
17
|
+
attachments: "Array<{ url: string; name?: string }>",
|
|
18
|
+
linked_record: "string | string[]",
|
|
19
|
+
lookup: "unknown",
|
|
20
|
+
autonumber: "number",
|
|
21
|
+
source: "string",
|
|
22
22
|
};
|
|
23
23
|
export function toPascalCase(name) {
|
|
24
24
|
return name
|
|
@@ -32,11 +32,14 @@ export function toCamelCase(name) {
|
|
|
32
32
|
function tsTypeForField(field) {
|
|
33
33
|
if (FIELD_TYPE_MAP[field.type])
|
|
34
34
|
return FIELD_TYPE_MAP[field.type];
|
|
35
|
-
const lowerName = field.name?.toLowerCase() ??
|
|
36
|
-
if (lowerName ===
|
|
37
|
-
|
|
35
|
+
const lowerName = field.name?.toLowerCase() ?? "";
|
|
36
|
+
if (lowerName === "createdat" ||
|
|
37
|
+
lowerName === "created_at" ||
|
|
38
|
+
lowerName === "updatedat" ||
|
|
39
|
+
lowerName === "updated_at") {
|
|
40
|
+
return "string";
|
|
38
41
|
}
|
|
39
|
-
return
|
|
42
|
+
return "string";
|
|
40
43
|
}
|
|
41
44
|
export function generateSchema(base) {
|
|
42
45
|
const schema = { tables: {} };
|
|
@@ -52,220 +55,191 @@ export function generateSchema(base) {
|
|
|
52
55
|
}
|
|
53
56
|
export function generateDbTs(base, schema) {
|
|
54
57
|
const lines = [];
|
|
55
|
-
lines.push(
|
|
56
|
-
lines.push(
|
|
57
|
-
lines.push(
|
|
58
|
+
lines.push("// Auto-generated by zitejs sync. Do not edit manually.");
|
|
59
|
+
lines.push("//");
|
|
60
|
+
lines.push("// Usage in endpoint files (src/api/*.ts):");
|
|
58
61
|
lines.push('// import { zite } from "zitejs/db";');
|
|
59
|
-
lines.push(
|
|
62
|
+
lines.push("//");
|
|
60
63
|
lines.push('// Always use "zitejs/db" — never use relative paths like "../../.zite/db".');
|
|
61
|
-
lines.push(
|
|
62
|
-
lines.push(
|
|
63
|
-
lines.push(
|
|
64
|
-
lines.push(
|
|
65
|
-
lines.push(
|
|
66
|
-
lines.push(
|
|
67
|
-
lines.push(
|
|
68
|
-
lines.push(
|
|
69
|
-
lines.push(
|
|
70
|
-
lines.push(
|
|
71
|
-
lines.push(
|
|
72
|
-
lines.push(
|
|
64
|
+
lines.push("// The tsconfig aliases resolve zitejs/* imports to the correct .zite/ files.");
|
|
65
|
+
lines.push("//");
|
|
66
|
+
lines.push("// Table client methods:");
|
|
67
|
+
lines.push("// .findAll(opts?) → { records: T[], total: number, hasMore: boolean }");
|
|
68
|
+
lines.push("// opts: { limit?, offset?, sort?, filter?, filters? }");
|
|
69
|
+
lines.push("// .findOne(id | { filters }) → T");
|
|
70
|
+
lines.push("// .create({ record }) → T");
|
|
71
|
+
lines.push("// .update(id, { record }) → T");
|
|
72
|
+
lines.push("// .delete(id) → { deleted: true }");
|
|
73
|
+
lines.push("// .bulkCreate(records) → T[]");
|
|
74
|
+
lines.push("//");
|
|
75
|
+
lines.push("// Raw SQL (read-only SELECTs for aggregates, joins, multi-table queries):");
|
|
76
|
+
lines.push('// zite.sql({ query: "SELECT ...", params?: [...] })');
|
|
77
|
+
lines.push("// → { rows: Record<string, unknown>[], columns, rowCount, truncated }");
|
|
78
|
+
lines.push("//");
|
|
79
|
+
lines.push("// SQL guidelines:");
|
|
80
|
+
lines.push("// - Use SDK names for tables (PascalCase) and fields (camelCase)");
|
|
81
|
+
lines.push('// - ALWAYS double-quote every identifier: FROM "Orders", WHERE "status" = $1');
|
|
82
|
+
lines.push("// - Use params array for user input ($1, $2, ...): never interpolate into SQL");
|
|
83
|
+
lines.push('// - Link tables: alphabetical PascalCase concat (Items+Orders → "ItemsOrders")');
|
|
84
|
+
lines.push('// with id columns: "itemsId", "ordersId"');
|
|
85
|
+
lines.push("// - Soft-deleted rows are excluded automatically — no WHERE deleted_at IS NULL");
|
|
86
|
+
lines.push("// - SELECT only — use .create/.update/.delete for writes");
|
|
87
|
+
lines.push('// - Load the "zite:sql" skill for full SQL reference (formulas, lookups, etc.)');
|
|
73
88
|
lines.push("import { createTableClient, createSqlClient } from 'zitejs/runtime';");
|
|
74
|
-
lines.push(
|
|
89
|
+
lines.push("");
|
|
75
90
|
for (const table of base.tables ?? []) {
|
|
76
91
|
const className = toPascalCase(table.name);
|
|
77
92
|
const recordType = `${className}RecordType`;
|
|
78
93
|
lines.push(`export type ${recordType} = {`);
|
|
79
|
-
lines.push(
|
|
94
|
+
lines.push(" id: string;");
|
|
80
95
|
for (const field of table.fields ?? []) {
|
|
81
96
|
const fieldName = toCamelCase(field.name);
|
|
82
|
-
if (fieldName ===
|
|
97
|
+
if (fieldName === "id")
|
|
83
98
|
continue;
|
|
84
99
|
const tsType = tsTypeForField(field);
|
|
85
100
|
lines.push(` ${fieldName}: ${tsType};`);
|
|
86
101
|
}
|
|
87
|
-
lines.push(
|
|
88
|
-
lines.push(
|
|
102
|
+
lines.push("};");
|
|
103
|
+
lines.push("");
|
|
89
104
|
}
|
|
90
|
-
lines.push(
|
|
105
|
+
lines.push("export const zite = {");
|
|
91
106
|
for (const table of base.tables ?? []) {
|
|
92
107
|
const className = toPascalCase(table.name);
|
|
93
108
|
const propName = toCamelCase(table.name);
|
|
94
109
|
lines.push(` ${propName}: createTableClient<${className}RecordType>('${className}'),`);
|
|
95
110
|
}
|
|
96
111
|
lines.push(` sql: createSqlClient(),`);
|
|
97
|
-
lines.push(
|
|
98
|
-
lines.push(
|
|
99
|
-
return lines.join(
|
|
100
|
-
}
|
|
101
|
-
export function generateDbDts(base, schema) {
|
|
102
|
-
const lines = [
|
|
103
|
-
'// Auto-generated by zitejs sync. Do not edit manually.',
|
|
104
|
-
'// Type declarations for IDE and LLM context. See db.ts for runtime.',
|
|
105
|
-
'',
|
|
106
|
-
'interface TableClient<T> {',
|
|
107
|
-
' findAll(options?: { limit?: number; offset?: number; sort?: unknown[]; filter?: unknown; filters?: unknown }): Promise<{ records: T[]; total: number; hasMore: boolean }>;',
|
|
108
|
-
' findOne(recordId: string | { filters?: unknown; filter?: unknown }): Promise<T>;',
|
|
109
|
-
' create(data: Partial<T>): Promise<T>;',
|
|
110
|
-
' update(id: string, data: Partial<T>): Promise<T>;',
|
|
111
|
-
' delete(id: string): Promise<{ deleted: true }>;',
|
|
112
|
-
' bulkCreate(records: Partial<T>[]): Promise<T[]>;',
|
|
113
|
-
'}',
|
|
114
|
-
'',
|
|
115
|
-
];
|
|
116
|
-
for (const table of base.tables ?? []) {
|
|
117
|
-
const className = toPascalCase(table.name);
|
|
118
|
-
const recordType = `${className}RecordType`;
|
|
119
|
-
lines.push(`export type ${recordType} = {`);
|
|
120
|
-
lines.push(' id: string;');
|
|
121
|
-
for (const field of table.fields ?? []) {
|
|
122
|
-
const fieldName = toCamelCase(field.name);
|
|
123
|
-
if (fieldName === 'id')
|
|
124
|
-
continue;
|
|
125
|
-
const tsType = tsTypeForField(field);
|
|
126
|
-
lines.push(` ${fieldName}: ${tsType};`);
|
|
127
|
-
}
|
|
128
|
-
lines.push('};');
|
|
129
|
-
lines.push('');
|
|
130
|
-
}
|
|
131
|
-
lines.push('export declare const zite: {');
|
|
132
|
-
for (const table of base.tables ?? []) {
|
|
133
|
-
const className = toPascalCase(table.name);
|
|
134
|
-
const propName = toCamelCase(table.name);
|
|
135
|
-
lines.push(` ${propName}: TableClient<${className}RecordType>;`);
|
|
136
|
-
}
|
|
137
|
-
lines.push(' sql: (params: { query?: string; sql?: string; params?: unknown[] }) => Promise<{ rows: Record<string, unknown>[] }>;');
|
|
138
|
-
lines.push('};');
|
|
139
|
-
lines.push('');
|
|
140
|
-
return lines.join('\n');
|
|
112
|
+
lines.push("};");
|
|
113
|
+
lines.push("");
|
|
114
|
+
return lines.join("\n");
|
|
141
115
|
}
|
|
142
116
|
export function generateApiTs(endpointFiles) {
|
|
143
117
|
if (!endpointFiles || endpointFiles.length === 0)
|
|
144
118
|
return null;
|
|
145
119
|
const lines = [
|
|
146
|
-
|
|
147
|
-
|
|
120
|
+
"// Auto-generated by zitejs sync. Do not edit manually.",
|
|
121
|
+
"",
|
|
148
122
|
"import { createCaller } from 'zitejs/caller';",
|
|
149
|
-
|
|
123
|
+
"",
|
|
150
124
|
];
|
|
151
125
|
const endpointNames = [];
|
|
152
126
|
for (const file of endpointFiles) {
|
|
153
|
-
const name = file.replace(/\.(ts|js)$/,
|
|
127
|
+
const name = file.replace(/\.(ts|js)$/, "");
|
|
154
128
|
const camelName = toCamelCase(name);
|
|
155
129
|
lines.push(`import ${camelName}Endpoint from '../src/api/${name}';`);
|
|
156
130
|
endpointNames.push(camelName);
|
|
157
131
|
}
|
|
158
|
-
lines.push(
|
|
132
|
+
lines.push("");
|
|
159
133
|
for (const name of endpointNames) {
|
|
160
134
|
lines.push(`export const ${name} = createCaller(${name}Endpoint, '${name}');`);
|
|
161
135
|
}
|
|
162
|
-
lines.push(
|
|
136
|
+
lines.push("");
|
|
163
137
|
// Inferred input/output types per endpoint (e.g. GetDashboardInputType, GetDashboardOutputType)
|
|
164
138
|
for (const name of endpointNames) {
|
|
165
139
|
const pascal = toPascalCase(name);
|
|
166
140
|
lines.push(`export type ${pascal}InputType = Parameters<typeof ${name}Endpoint.execute>[0]['input'];`);
|
|
167
141
|
lines.push(`export type ${pascal}OutputType = Awaited<ReturnType<typeof ${name}Endpoint.execute>>;`);
|
|
168
142
|
}
|
|
169
|
-
lines.push(
|
|
143
|
+
lines.push("");
|
|
170
144
|
// Also export as a single api object
|
|
171
|
-
lines.push(
|
|
145
|
+
lines.push("export const api = {");
|
|
172
146
|
for (const name of endpointNames) {
|
|
173
147
|
lines.push(` ${name},`);
|
|
174
148
|
}
|
|
175
|
-
lines.push(
|
|
176
|
-
lines.push(
|
|
177
|
-
return lines.join(
|
|
149
|
+
lines.push("};");
|
|
150
|
+
lines.push("");
|
|
151
|
+
return lines.join("\n");
|
|
178
152
|
}
|
|
179
153
|
export function generateUserTs(usersTableFields) {
|
|
180
154
|
const lines = [
|
|
181
|
-
|
|
182
|
-
|
|
155
|
+
"// Auto-generated by zitejs sync. Do not edit manually.",
|
|
156
|
+
"",
|
|
183
157
|
];
|
|
184
158
|
if (usersTableFields && usersTableFields.length > 0) {
|
|
185
|
-
lines.push(
|
|
186
|
-
lines.push(
|
|
187
|
-
lines.push(
|
|
159
|
+
lines.push("export type User = {");
|
|
160
|
+
lines.push(" id: string;");
|
|
161
|
+
lines.push(" email: string;");
|
|
188
162
|
for (const field of usersTableFields) {
|
|
189
163
|
const lowerName = field.name.toLowerCase();
|
|
190
|
-
if (lowerName ===
|
|
164
|
+
if (lowerName === "id" || lowerName === "email")
|
|
191
165
|
continue;
|
|
192
166
|
const fieldName = toCamelCase(field.name);
|
|
193
167
|
const tsType = tsTypeForField(field);
|
|
194
168
|
lines.push(` ${fieldName}: ${tsType};`);
|
|
195
169
|
}
|
|
196
|
-
lines.push(
|
|
197
|
-
lines.push(
|
|
170
|
+
lines.push(" [key: string]: unknown;");
|
|
171
|
+
lines.push("};");
|
|
198
172
|
}
|
|
199
173
|
else {
|
|
200
|
-
lines.push(
|
|
201
|
-
lines.push(
|
|
202
|
-
lines.push(
|
|
203
|
-
lines.push(
|
|
204
|
-
lines.push(
|
|
205
|
-
lines.push(
|
|
206
|
-
lines.push(
|
|
174
|
+
lines.push("export type User = {");
|
|
175
|
+
lines.push(" id: string;");
|
|
176
|
+
lines.push(" email: string;");
|
|
177
|
+
lines.push(" firstName?: string;");
|
|
178
|
+
lines.push(" lastName?: string;");
|
|
179
|
+
lines.push(" [key: string]: unknown;");
|
|
180
|
+
lines.push("};");
|
|
207
181
|
}
|
|
208
|
-
lines.push(
|
|
209
|
-
return lines.join(
|
|
182
|
+
lines.push("");
|
|
183
|
+
return lines.join("\n");
|
|
210
184
|
}
|
|
211
185
|
export function generateAuthWrapperTs() {
|
|
212
186
|
return [
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
187
|
+
"// Auto-generated type-narrowing wrapper. Do not edit manually.",
|
|
188
|
+
"// The real auth logic lives in the zitejs npm package (zitejs/auth).",
|
|
189
|
+
"",
|
|
216
190
|
"import { useAuth as _useAuth } from 'zitejs/auth/base';",
|
|
217
191
|
"import type { User } from './user';",
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
].join(
|
|
192
|
+
"",
|
|
193
|
+
"export type { User };",
|
|
194
|
+
"",
|
|
195
|
+
"export function useAuth() {",
|
|
196
|
+
" return _useAuth() as ReturnType<typeof _useAuth> & { user: User | undefined };",
|
|
197
|
+
"}",
|
|
198
|
+
"",
|
|
199
|
+
].join("\n");
|
|
226
200
|
}
|
|
227
201
|
export function generateBackendWrapperTs() {
|
|
228
202
|
return [
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
203
|
+
"// Auto-generated type-narrowing wrapper. Do not edit manually.",
|
|
204
|
+
"// Re-exports createEndpoint with context.user typed to the app User.",
|
|
205
|
+
"",
|
|
232
206
|
"import type { ZiteRequestContext as _ZiteRequestContext, ZiteScheduledContext as _ZiteScheduledContext } from 'zitejs/backend/base';",
|
|
233
207
|
"import type { User } from './user';",
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
208
|
+
"",
|
|
209
|
+
"export class ZiteError extends Error {",
|
|
210
|
+
" statusCode: number;",
|
|
211
|
+
" constructor(message: string, options?: { statusCode?: number }) {",
|
|
212
|
+
" super(message);",
|
|
239
213
|
" this.name = 'ZiteError';",
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
214
|
+
" this.statusCode = options?.statusCode ?? 500;",
|
|
215
|
+
" }",
|
|
216
|
+
"}",
|
|
217
|
+
"",
|
|
244
218
|
'export interface ZiteRequestContext extends Omit<_ZiteRequestContext, "user"> {',
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
219
|
+
" user: User;",
|
|
220
|
+
"}",
|
|
221
|
+
"",
|
|
248
222
|
'export interface ZiteScheduledContext extends Omit<_ZiteScheduledContext, "user"> {',
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
223
|
+
" user: User;",
|
|
224
|
+
" scheduledAt: string;",
|
|
225
|
+
"}",
|
|
226
|
+
"",
|
|
253
227
|
"type SchemaLike<T> = { _output: T; parse: (data: unknown) => T };",
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
].join(
|
|
228
|
+
"",
|
|
229
|
+
"export interface EndpointConfig<TInput = unknown, TOutput = unknown> {",
|
|
230
|
+
" description?: string;",
|
|
231
|
+
" inputSchema?: SchemaLike<TInput>;",
|
|
232
|
+
" outputSchema?: SchemaLike<TOutput>;",
|
|
233
|
+
" stream?: boolean;",
|
|
234
|
+
" authenticated?: boolean;",
|
|
235
|
+
" execute: (params: { input: TInput; context: ZiteRequestContext | ZiteScheduledContext }) => Promise<TOutput> | TOutput;",
|
|
236
|
+
"}",
|
|
237
|
+
"",
|
|
238
|
+
"export function createEndpoint<TInput = unknown, TOutput = unknown>(",
|
|
239
|
+
" config: EndpointConfig<TInput, TOutput>,",
|
|
240
|
+
"): EndpointConfig<TInput, TOutput> {",
|
|
241
|
+
" return config;",
|
|
242
|
+
"}",
|
|
243
|
+
"",
|
|
244
|
+
].join("\n");
|
|
271
245
|
}
|