zitejs 0.9.33 → 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/dev/index.js +1 -1
- package/dist/cjs/runtime/index.js +17 -14
- package/dist/cjs/sync/index.js +22 -22
- package/dist/cjs/sync/lib.js +141 -170
- package/dist/esm/dev/index.js +1 -1
- 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 +1 -2
- package/dist/esm/sync/lib.js +141 -169
- package/package.json +1 -1
package/dist/cjs/dev/index.js
CHANGED
|
@@ -45,7 +45,7 @@ function regenerateAppApiTs(appDir) {
|
|
|
45
45
|
if (!(0, fs_2.existsSync)(apiDir))
|
|
46
46
|
return;
|
|
47
47
|
const endpointFiles = (0, fs_2.readdirSync)(apiDir).filter((f) => f.endsWith('.ts') || f.endsWith('.js'));
|
|
48
|
-
const content = (0, lib_js_1.generateApiTs)(endpointFiles
|
|
48
|
+
const content = (0, lib_js_1.generateApiTs)(endpointFiles);
|
|
49
49
|
if (content) {
|
|
50
50
|
const outDir = (0, path_1.join)('apps', appDir, '.zite');
|
|
51
51
|
(0, fs_2.mkdirSync)(outDir, { recursive: true });
|
|
@@ -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,222 +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(
|
|
122
|
+
lines.push("};");
|
|
123
|
+
lines.push("");
|
|
124
|
+
return lines.join("\n");
|
|
111
125
|
}
|
|
112
|
-
function
|
|
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');
|
|
152
|
-
}
|
|
153
|
-
function generateApiTs(endpointFiles, flowId) {
|
|
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
|
-
|
|
170
|
-
lines.push('');
|
|
171
|
-
// Named exports for each endpoint (backwards compat with old zite-endpoints-sdk imports)
|
|
142
|
+
lines.push("");
|
|
172
143
|
for (const name of endpointNames) {
|
|
173
|
-
lines.push(`export const ${name} = createCaller(${name}Endpoint, '${name}'
|
|
144
|
+
lines.push(`export const ${name} = createCaller(${name}Endpoint, '${name}');`);
|
|
174
145
|
}
|
|
175
|
-
lines.push(
|
|
146
|
+
lines.push("");
|
|
176
147
|
// Inferred input/output types per endpoint (e.g. GetDashboardInputType, GetDashboardOutputType)
|
|
177
148
|
for (const name of endpointNames) {
|
|
178
149
|
const pascal = toPascalCase(name);
|
|
179
150
|
lines.push(`export type ${pascal}InputType = Parameters<typeof ${name}Endpoint.execute>[0]['input'];`);
|
|
180
151
|
lines.push(`export type ${pascal}OutputType = Awaited<ReturnType<typeof ${name}Endpoint.execute>>;`);
|
|
181
152
|
}
|
|
182
|
-
lines.push(
|
|
153
|
+
lines.push("");
|
|
183
154
|
// Also export as a single api object
|
|
184
|
-
lines.push(
|
|
155
|
+
lines.push("export const api = {");
|
|
185
156
|
for (const name of endpointNames) {
|
|
186
157
|
lines.push(` ${name},`);
|
|
187
158
|
}
|
|
188
|
-
lines.push(
|
|
189
|
-
lines.push(
|
|
190
|
-
return lines.join(
|
|
159
|
+
lines.push("};");
|
|
160
|
+
lines.push("");
|
|
161
|
+
return lines.join("\n");
|
|
191
162
|
}
|
|
192
163
|
function generateUserTs(usersTableFields) {
|
|
193
164
|
const lines = [
|
|
194
|
-
|
|
195
|
-
|
|
165
|
+
"// Auto-generated by zitejs sync. Do not edit manually.",
|
|
166
|
+
"",
|
|
196
167
|
];
|
|
197
168
|
if (usersTableFields && usersTableFields.length > 0) {
|
|
198
|
-
lines.push(
|
|
199
|
-
lines.push(
|
|
200
|
-
lines.push(
|
|
169
|
+
lines.push("export type User = {");
|
|
170
|
+
lines.push(" id: string;");
|
|
171
|
+
lines.push(" email: string;");
|
|
201
172
|
for (const field of usersTableFields) {
|
|
202
173
|
const lowerName = field.name.toLowerCase();
|
|
203
|
-
if (lowerName ===
|
|
174
|
+
if (lowerName === "id" || lowerName === "email")
|
|
204
175
|
continue;
|
|
205
176
|
const fieldName = toCamelCase(field.name);
|
|
206
177
|
const tsType = tsTypeForField(field);
|
|
207
178
|
lines.push(` ${fieldName}: ${tsType};`);
|
|
208
179
|
}
|
|
209
|
-
lines.push(
|
|
210
|
-
lines.push(
|
|
180
|
+
lines.push(" [key: string]: unknown;");
|
|
181
|
+
lines.push("};");
|
|
211
182
|
}
|
|
212
183
|
else {
|
|
213
|
-
lines.push(
|
|
214
|
-
lines.push(
|
|
215
|
-
lines.push(
|
|
216
|
-
lines.push(
|
|
217
|
-
lines.push(
|
|
218
|
-
lines.push(
|
|
219
|
-
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("};");
|
|
220
191
|
}
|
|
221
|
-
lines.push(
|
|
222
|
-
return lines.join(
|
|
192
|
+
lines.push("");
|
|
193
|
+
return lines.join("\n");
|
|
223
194
|
}
|
|
224
195
|
function generateAuthWrapperTs() {
|
|
225
196
|
return [
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
197
|
+
"// Auto-generated type-narrowing wrapper. Do not edit manually.",
|
|
198
|
+
"// The real auth logic lives in the zitejs npm package (zitejs/auth).",
|
|
199
|
+
"",
|
|
229
200
|
"import { useAuth as _useAuth } from 'zitejs/auth/base';",
|
|
230
201
|
"import type { User } from './user';",
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
].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");
|
|
239
210
|
}
|
|
240
211
|
function generateBackendWrapperTs() {
|
|
241
212
|
return [
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
213
|
+
"// Auto-generated type-narrowing wrapper. Do not edit manually.",
|
|
214
|
+
"// Re-exports createEndpoint with context.user typed to the app User.",
|
|
215
|
+
"",
|
|
245
216
|
"import type { ZiteRequestContext as _ZiteRequestContext, ZiteScheduledContext as _ZiteScheduledContext } from 'zitejs/backend/base';",
|
|
246
217
|
"import type { User } from './user';",
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
218
|
+
"",
|
|
219
|
+
"export class ZiteError extends Error {",
|
|
220
|
+
" statusCode: number;",
|
|
221
|
+
" constructor(message: string, options?: { statusCode?: number }) {",
|
|
222
|
+
" super(message);",
|
|
252
223
|
" this.name = 'ZiteError';",
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
224
|
+
" this.statusCode = options?.statusCode ?? 500;",
|
|
225
|
+
" }",
|
|
226
|
+
"}",
|
|
227
|
+
"",
|
|
257
228
|
'export interface ZiteRequestContext extends Omit<_ZiteRequestContext, "user"> {',
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
229
|
+
" user: User;",
|
|
230
|
+
"}",
|
|
231
|
+
"",
|
|
261
232
|
'export interface ZiteScheduledContext extends Omit<_ZiteScheduledContext, "user"> {',
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
233
|
+
" user: User;",
|
|
234
|
+
" scheduledAt: string;",
|
|
235
|
+
"}",
|
|
236
|
+
"",
|
|
266
237
|
"type SchemaLike<T> = { _output: T; parse: (data: unknown) => T };",
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
].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");
|
|
284
255
|
}
|
package/dist/esm/dev/index.js
CHANGED
|
@@ -41,7 +41,7 @@ function regenerateAppApiTs(appDir) {
|
|
|
41
41
|
if (!existsSync(apiDir))
|
|
42
42
|
return;
|
|
43
43
|
const endpointFiles = readdirSync(apiDir).filter((f) => f.endsWith('.ts') || f.endsWith('.js'));
|
|
44
|
-
const content = generateApiTs(endpointFiles
|
|
44
|
+
const content = generateApiTs(endpointFiles);
|
|
45
45
|
if (content) {
|
|
46
46
|
const outDir = join('apps', appDir, '.zite');
|
|
47
47
|
mkdirSync(outDir, { recursive: true });
|
|
@@ -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,8 +21,7 @@ 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
|
|
25
|
-
export declare function generateApiTs(endpointFiles: string[], flowId?: string): string | null;
|
|
24
|
+
export declare function generateApiTs(endpointFiles: string[]): string | null;
|
|
26
25
|
export declare function generateUserTs(usersTableFields?: Array<{
|
|
27
26
|
name: string;
|
|
28
27
|
type: 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,222 +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(
|
|
112
|
+
lines.push("};");
|
|
113
|
+
lines.push("");
|
|
114
|
+
return lines.join("\n");
|
|
100
115
|
}
|
|
101
|
-
export function
|
|
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');
|
|
141
|
-
}
|
|
142
|
-
export function generateApiTs(endpointFiles, flowId) {
|
|
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
|
-
|
|
159
|
-
lines.push('');
|
|
160
|
-
// Named exports for each endpoint (backwards compat with old zite-endpoints-sdk imports)
|
|
132
|
+
lines.push("");
|
|
161
133
|
for (const name of endpointNames) {
|
|
162
|
-
lines.push(`export const ${name} = createCaller(${name}Endpoint, '${name}'
|
|
134
|
+
lines.push(`export const ${name} = createCaller(${name}Endpoint, '${name}');`);
|
|
163
135
|
}
|
|
164
|
-
lines.push(
|
|
136
|
+
lines.push("");
|
|
165
137
|
// Inferred input/output types per endpoint (e.g. GetDashboardInputType, GetDashboardOutputType)
|
|
166
138
|
for (const name of endpointNames) {
|
|
167
139
|
const pascal = toPascalCase(name);
|
|
168
140
|
lines.push(`export type ${pascal}InputType = Parameters<typeof ${name}Endpoint.execute>[0]['input'];`);
|
|
169
141
|
lines.push(`export type ${pascal}OutputType = Awaited<ReturnType<typeof ${name}Endpoint.execute>>;`);
|
|
170
142
|
}
|
|
171
|
-
lines.push(
|
|
143
|
+
lines.push("");
|
|
172
144
|
// Also export as a single api object
|
|
173
|
-
lines.push(
|
|
145
|
+
lines.push("export const api = {");
|
|
174
146
|
for (const name of endpointNames) {
|
|
175
147
|
lines.push(` ${name},`);
|
|
176
148
|
}
|
|
177
|
-
lines.push(
|
|
178
|
-
lines.push(
|
|
179
|
-
return lines.join(
|
|
149
|
+
lines.push("};");
|
|
150
|
+
lines.push("");
|
|
151
|
+
return lines.join("\n");
|
|
180
152
|
}
|
|
181
153
|
export function generateUserTs(usersTableFields) {
|
|
182
154
|
const lines = [
|
|
183
|
-
|
|
184
|
-
|
|
155
|
+
"// Auto-generated by zitejs sync. Do not edit manually.",
|
|
156
|
+
"",
|
|
185
157
|
];
|
|
186
158
|
if (usersTableFields && usersTableFields.length > 0) {
|
|
187
|
-
lines.push(
|
|
188
|
-
lines.push(
|
|
189
|
-
lines.push(
|
|
159
|
+
lines.push("export type User = {");
|
|
160
|
+
lines.push(" id: string;");
|
|
161
|
+
lines.push(" email: string;");
|
|
190
162
|
for (const field of usersTableFields) {
|
|
191
163
|
const lowerName = field.name.toLowerCase();
|
|
192
|
-
if (lowerName ===
|
|
164
|
+
if (lowerName === "id" || lowerName === "email")
|
|
193
165
|
continue;
|
|
194
166
|
const fieldName = toCamelCase(field.name);
|
|
195
167
|
const tsType = tsTypeForField(field);
|
|
196
168
|
lines.push(` ${fieldName}: ${tsType};`);
|
|
197
169
|
}
|
|
198
|
-
lines.push(
|
|
199
|
-
lines.push(
|
|
170
|
+
lines.push(" [key: string]: unknown;");
|
|
171
|
+
lines.push("};");
|
|
200
172
|
}
|
|
201
173
|
else {
|
|
202
|
-
lines.push(
|
|
203
|
-
lines.push(
|
|
204
|
-
lines.push(
|
|
205
|
-
lines.push(
|
|
206
|
-
lines.push(
|
|
207
|
-
lines.push(
|
|
208
|
-
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("};");
|
|
209
181
|
}
|
|
210
|
-
lines.push(
|
|
211
|
-
return lines.join(
|
|
182
|
+
lines.push("");
|
|
183
|
+
return lines.join("\n");
|
|
212
184
|
}
|
|
213
185
|
export function generateAuthWrapperTs() {
|
|
214
186
|
return [
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
187
|
+
"// Auto-generated type-narrowing wrapper. Do not edit manually.",
|
|
188
|
+
"// The real auth logic lives in the zitejs npm package (zitejs/auth).",
|
|
189
|
+
"",
|
|
218
190
|
"import { useAuth as _useAuth } from 'zitejs/auth/base';",
|
|
219
191
|
"import type { User } from './user';",
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
].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");
|
|
228
200
|
}
|
|
229
201
|
export function generateBackendWrapperTs() {
|
|
230
202
|
return [
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
203
|
+
"// Auto-generated type-narrowing wrapper. Do not edit manually.",
|
|
204
|
+
"// Re-exports createEndpoint with context.user typed to the app User.",
|
|
205
|
+
"",
|
|
234
206
|
"import type { ZiteRequestContext as _ZiteRequestContext, ZiteScheduledContext as _ZiteScheduledContext } from 'zitejs/backend/base';",
|
|
235
207
|
"import type { User } from './user';",
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
208
|
+
"",
|
|
209
|
+
"export class ZiteError extends Error {",
|
|
210
|
+
" statusCode: number;",
|
|
211
|
+
" constructor(message: string, options?: { statusCode?: number }) {",
|
|
212
|
+
" super(message);",
|
|
241
213
|
" this.name = 'ZiteError';",
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
214
|
+
" this.statusCode = options?.statusCode ?? 500;",
|
|
215
|
+
" }",
|
|
216
|
+
"}",
|
|
217
|
+
"",
|
|
246
218
|
'export interface ZiteRequestContext extends Omit<_ZiteRequestContext, "user"> {',
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
219
|
+
" user: User;",
|
|
220
|
+
"}",
|
|
221
|
+
"",
|
|
250
222
|
'export interface ZiteScheduledContext extends Omit<_ZiteScheduledContext, "user"> {',
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
223
|
+
" user: User;",
|
|
224
|
+
" scheduledAt: string;",
|
|
225
|
+
"}",
|
|
226
|
+
"",
|
|
255
227
|
"type SchemaLike<T> = { _output: T; parse: (data: unknown) => T };",
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
].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");
|
|
273
245
|
}
|