zitejs 0.9.42 → 0.9.43

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.
@@ -250,6 +250,15 @@ function createAliasPlugin(opts) {
250
250
  }
251
251
  return { path: 'zitejs/db', external: true };
252
252
  });
253
+ // Resolve zitejs/integrations to .zite/integrations/airtable.ts
254
+ build.onResolve({ filter: /^zitejs\/integrations$/ }, () => {
255
+ if (opts.baseDir) {
256
+ const intPath = path.resolve(opts.baseDir, '.zite/integrations/airtable.ts');
257
+ if (fs.existsSync(intPath))
258
+ return { path: intPath };
259
+ }
260
+ return { path: 'zitejs/integrations', external: true };
261
+ });
253
262
  // zitejs/runtime is NOT in PREBUNDLED_LIBS — it's a thin fetch()
254
263
  // wrapper that gets bundled inline by esbuild (no special handling).
255
264
  for (const [pkgName, modulePath] of Object.entries(PREBUNDLED_LIBS)) {
@@ -53,6 +53,42 @@ function regenerateAppApiTs(appDir) {
53
53
  console.log(`Updated apps/${appDir}/.zite/api.ts`);
54
54
  }
55
55
  }
56
+ function regenerateAppAirtableSdk(appDir) {
57
+ const lockPath = (0, path_1.join)('apps', appDir, 'zite.lock');
58
+ if (!(0, fs_2.existsSync)(lockPath))
59
+ return;
60
+ try {
61
+ const lockContent = JSON.parse((0, fs_2.readFileSync)(lockPath, 'utf-8'));
62
+ const integrations = lockContent.integrations ?? {};
63
+ for (const [integrationId, integration] of Object.entries(integrations)) {
64
+ const int = integration;
65
+ if (!int.idMappings?.tables)
66
+ continue;
67
+ const airtableLock = {
68
+ integrationId,
69
+ tables: Object.entries(int.idMappings.tables).map(([sdkName, tableId]) => ({
70
+ id: tableId,
71
+ sdkName,
72
+ fields: Object.entries(int.idMappings?.fields?.[sdkName] ?? {}).map(([fieldSdkName, fieldId]) => ({
73
+ id: fieldId,
74
+ sdkName: fieldSdkName,
75
+ type: 'singleLineText',
76
+ })),
77
+ })),
78
+ };
79
+ const content = (0, lib_js_1.generateAirtableTs)(airtableLock);
80
+ if (content) {
81
+ const outDir = (0, path_1.join)('apps', appDir, '.zite', 'integrations');
82
+ (0, fs_2.mkdirSync)(outDir, { recursive: true });
83
+ (0, fs_2.writeFileSync)((0, path_1.join)(outDir, 'airtable.ts'), content);
84
+ console.log(`Updated apps/${appDir}/.zite/integrations/airtable.ts`);
85
+ }
86
+ }
87
+ }
88
+ catch {
89
+ // Lock file invalid or missing — skip
90
+ }
91
+ }
56
92
  async function runGenerate() {
57
93
  // 1. Run sync (generates root .zite/db.ts)
58
94
  try {
@@ -66,6 +102,7 @@ async function runGenerate() {
66
102
  for (const app of appDirs) {
67
103
  regenerateAppApiTs(app);
68
104
  regenerateAppTypedWrappers(app);
105
+ regenerateAppAirtableSdk(app);
69
106
  }
70
107
  console.log('Done!');
71
108
  }
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.createCaller = void 0;
4
4
  exports.createTableClient = createTableClient;
5
5
  exports.createSqlClient = createSqlClient;
6
+ exports.createAirtableClient = createAirtableClient;
6
7
  function getSdkCall() {
7
8
  const fn = globalThis.__wrapSdkCall;
8
9
  if (!fn) {
@@ -76,5 +77,34 @@ function createSqlClient() {
76
77
  ...params,
77
78
  });
78
79
  }
80
+ function createAirtableClient(integrationId, className, implicitParams) {
81
+ return {
82
+ findAll: (options) => getSdkCall()(integrationId, className, "findAll", {
83
+ ...implicitParams,
84
+ ...options,
85
+ }),
86
+ findOne: (params) => getSdkCall()(integrationId, className, "findOne", {
87
+ ...implicitParams,
88
+ ...params,
89
+ }),
90
+ create: (data) => getSdkCall()(integrationId, className, "create", {
91
+ ...implicitParams,
92
+ ...data,
93
+ }),
94
+ bulkCreate: (records) => getSdkCall()(integrationId, className, "bulkCreate", {
95
+ ...implicitParams,
96
+ records,
97
+ }),
98
+ update: (id, data) => getSdkCall()(integrationId, className, "update", {
99
+ ...implicitParams,
100
+ id,
101
+ ...data,
102
+ }),
103
+ delete: (id) => getSdkCall()(integrationId, className, "delete", {
104
+ ...implicitParams,
105
+ id,
106
+ }),
107
+ };
108
+ }
79
109
  var index_js_1 = require("../caller/index.js");
80
110
  Object.defineProperty(exports, "createCaller", { enumerable: true, get: function () { return index_js_1.createCaller; } });
@@ -7,6 +7,7 @@ exports.generateDbTs = generateDbTs;
7
7
  exports.generateApiTs = generateApiTs;
8
8
  exports.generateUserTs = generateUserTs;
9
9
  exports.generateAuthWrapperTs = generateAuthWrapperTs;
10
+ exports.generateAirtableTs = generateAirtableTs;
10
11
  exports.generateBackendWrapperTs = generateBackendWrapperTs;
11
12
  const FIELD_TYPE_MAP = {
12
13
  single_line_text: "string",
@@ -357,6 +358,86 @@ function generateAuthWrapperTs() {
357
358
  "",
358
359
  ].join("\n");
359
360
  }
361
+ const AIRTABLE_FIELD_TYPE_MAP = {
362
+ singleLineText: "string",
363
+ multilineText: "string",
364
+ richText: "string",
365
+ email: "string",
366
+ url: "string",
367
+ phoneNumber: "string",
368
+ number: "number",
369
+ currency: "number",
370
+ percent: "number",
371
+ rating: "number",
372
+ duration: "number",
373
+ singleSelect: "string",
374
+ multipleSelects: "string[]",
375
+ checkbox: "boolean",
376
+ date: "string",
377
+ dateTime: "string",
378
+ attachment: "Array<{ url: string; filename?: string }>",
379
+ multipleRecordLinks: "string | string[]",
380
+ formula: "unknown",
381
+ rollup: "unknown",
382
+ lookup: "unknown",
383
+ count: "number",
384
+ autoNumber: "number",
385
+ barcode: "string",
386
+ button: "unknown",
387
+ createdTime: "string",
388
+ lastModifiedTime: "string",
389
+ createdBy: "unknown",
390
+ lastModifiedBy: "unknown",
391
+ externalSyncSource: "unknown",
392
+ aiText: "string",
393
+ };
394
+ function airtableTsType(field) {
395
+ if ((field.type === "singleSelect" || field.type === "multipleSelects") &&
396
+ field.options &&
397
+ field.options.length > 0) {
398
+ const literals = field.options
399
+ .slice(0, MAX_SELECT_OPTIONS)
400
+ .map((o) => `"${o.replace(/"/g, '\\"')}"`)
401
+ .join(" | ");
402
+ const union = `${literals} | string`;
403
+ if (field.type === "multipleSelects")
404
+ return `(${union})[]`;
405
+ return union;
406
+ }
407
+ return AIRTABLE_FIELD_TYPE_MAP[field.type] ?? "unknown";
408
+ }
409
+ function generateAirtableTs(lock) {
410
+ if (lock.tables.length === 0)
411
+ return null;
412
+ const lines = [
413
+ "// Auto-generated by zitejs generate from zite.lock. Do not edit manually.",
414
+ "// Airtable SDK — uses createAirtableClient from zitejs/runtime.",
415
+ "// The airtable package is externalized (not bundled per-endpoint).",
416
+ "",
417
+ "import { createAirtableClient } from 'zitejs/runtime';",
418
+ "",
419
+ ];
420
+ for (const table of lock.tables) {
421
+ const recordType = `${table.sdkName}RecordType`;
422
+ lines.push(`export type ${recordType} = {`);
423
+ lines.push(" id: string;");
424
+ for (const field of table.fields) {
425
+ if (field.sdkName === "id")
426
+ continue;
427
+ const tsType = airtableTsType(field);
428
+ lines.push(` ${field.sdkName}: ${tsType};`);
429
+ }
430
+ lines.push("};");
431
+ lines.push("");
432
+ lines.push(`export const ${table.sdkName} = createAirtableClient<${recordType}>(`);
433
+ lines.push(` '${lock.integrationId}',`);
434
+ lines.push(` '${table.sdkName}',`);
435
+ lines.push(` { tableId: '${table.id}' },`);
436
+ lines.push(`);`);
437
+ lines.push("");
438
+ }
439
+ return lines.join("\n");
440
+ }
360
441
  function generateBackendWrapperTs() {
361
442
  return [
362
443
  "// Auto-generated type-narrowing wrapper. Do not edit manually.",
@@ -214,6 +214,15 @@ function createAliasPlugin(opts) {
214
214
  }
215
215
  return { path: 'zitejs/db', external: true };
216
216
  });
217
+ // Resolve zitejs/integrations to .zite/integrations/airtable.ts
218
+ build.onResolve({ filter: /^zitejs\/integrations$/ }, () => {
219
+ if (opts.baseDir) {
220
+ const intPath = path.resolve(opts.baseDir, '.zite/integrations/airtable.ts');
221
+ if (fs.existsSync(intPath))
222
+ return { path: intPath };
223
+ }
224
+ return { path: 'zitejs/integrations', external: true };
225
+ });
217
226
  // zitejs/runtime is NOT in PREBUNDLED_LIBS — it's a thin fetch()
218
227
  // wrapper that gets bundled inline by esbuild (no special handling).
219
228
  for (const [pkgName, modulePath] of Object.entries(PREBUNDLED_LIBS)) {
@@ -2,7 +2,7 @@ import { watch } from 'fs';
2
2
  import { existsSync, readdirSync, readFileSync, writeFileSync, mkdirSync, } from 'fs';
3
3
  import { join } from 'path';
4
4
  import { runSync } from '../sync/index.js';
5
- import { generateApiTs, generateUserTs, generateAuthWrapperTs, generateBackendWrapperTs, } from '../sync/lib.js';
5
+ import { generateApiTs, generateUserTs, generateAuthWrapperTs, generateBackendWrapperTs, generateAirtableTs, } from '../sync/lib.js';
6
6
  const debounceTimers = new Map();
7
7
  function debounce(key, fn, ms) {
8
8
  const existing = debounceTimers.get(key);
@@ -49,6 +49,42 @@ function regenerateAppApiTs(appDir) {
49
49
  console.log(`Updated apps/${appDir}/.zite/api.ts`);
50
50
  }
51
51
  }
52
+ function regenerateAppAirtableSdk(appDir) {
53
+ const lockPath = join('apps', appDir, 'zite.lock');
54
+ if (!existsSync(lockPath))
55
+ return;
56
+ try {
57
+ const lockContent = JSON.parse(readFileSync(lockPath, 'utf-8'));
58
+ const integrations = lockContent.integrations ?? {};
59
+ for (const [integrationId, integration] of Object.entries(integrations)) {
60
+ const int = integration;
61
+ if (!int.idMappings?.tables)
62
+ continue;
63
+ const airtableLock = {
64
+ integrationId,
65
+ tables: Object.entries(int.idMappings.tables).map(([sdkName, tableId]) => ({
66
+ id: tableId,
67
+ sdkName,
68
+ fields: Object.entries(int.idMappings?.fields?.[sdkName] ?? {}).map(([fieldSdkName, fieldId]) => ({
69
+ id: fieldId,
70
+ sdkName: fieldSdkName,
71
+ type: 'singleLineText',
72
+ })),
73
+ })),
74
+ };
75
+ const content = generateAirtableTs(airtableLock);
76
+ if (content) {
77
+ const outDir = join('apps', appDir, '.zite', 'integrations');
78
+ mkdirSync(outDir, { recursive: true });
79
+ writeFileSync(join(outDir, 'airtable.ts'), content);
80
+ console.log(`Updated apps/${appDir}/.zite/integrations/airtable.ts`);
81
+ }
82
+ }
83
+ }
84
+ catch {
85
+ // Lock file invalid or missing — skip
86
+ }
87
+ }
52
88
  export async function runGenerate() {
53
89
  // 1. Run sync (generates root .zite/db.ts)
54
90
  try {
@@ -62,6 +98,7 @@ export async function runGenerate() {
62
98
  for (const app of appDirs) {
63
99
  regenerateAppApiTs(app);
64
100
  regenerateAppTypedWrappers(app);
101
+ regenerateAppAirtableSdk(app);
65
102
  }
66
103
  console.log('Done!');
67
104
  }
@@ -39,5 +39,31 @@ export declare function createSqlClient(): (params: {
39
39
  query: string;
40
40
  params?: unknown[];
41
41
  }) => Promise<SqlResult>;
42
+ export interface AirtableTableClient<T> {
43
+ findAll(options?: {
44
+ offset?: string;
45
+ limit?: number;
46
+ filters?: unknown;
47
+ }): Promise<{
48
+ records: T[];
49
+ offset: string | undefined;
50
+ hasMore: boolean;
51
+ }>;
52
+ findOne(params: {
53
+ id?: string;
54
+ filters?: unknown;
55
+ }): Promise<T | undefined>;
56
+ create(data: {
57
+ record: Partial<T>;
58
+ }): Promise<T>;
59
+ bulkCreate(records: Partial<T>[]): Promise<T[]>;
60
+ update(id: string, data: {
61
+ record: Partial<T>;
62
+ }): Promise<T>;
63
+ delete(id: string): Promise<{
64
+ deleted: true;
65
+ }>;
66
+ }
67
+ export declare function createAirtableClient<T>(integrationId: string, className: string, implicitParams: Record<string, unknown>): AirtableTableClient<T>;
42
68
  export { createCaller } from "../caller/index.js";
43
69
  export type { EndpointConfig } from "../caller/index.js";
@@ -71,4 +71,33 @@ export function createSqlClient() {
71
71
  ...params,
72
72
  });
73
73
  }
74
+ export function createAirtableClient(integrationId, className, implicitParams) {
75
+ return {
76
+ findAll: (options) => getSdkCall()(integrationId, className, "findAll", {
77
+ ...implicitParams,
78
+ ...options,
79
+ }),
80
+ findOne: (params) => getSdkCall()(integrationId, className, "findOne", {
81
+ ...implicitParams,
82
+ ...params,
83
+ }),
84
+ create: (data) => getSdkCall()(integrationId, className, "create", {
85
+ ...implicitParams,
86
+ ...data,
87
+ }),
88
+ bulkCreate: (records) => getSdkCall()(integrationId, className, "bulkCreate", {
89
+ ...implicitParams,
90
+ records,
91
+ }),
92
+ update: (id, data) => getSdkCall()(integrationId, className, "update", {
93
+ ...implicitParams,
94
+ id,
95
+ ...data,
96
+ }),
97
+ delete: (id) => getSdkCall()(integrationId, className, "delete", {
98
+ ...implicitParams,
99
+ id,
100
+ }),
101
+ };
102
+ }
74
103
  export { createCaller } from "../caller/index.js";
@@ -36,4 +36,20 @@ export declare function generateUserTs(usersTableFields?: Array<{
36
36
  type: string;
37
37
  }>): string;
38
38
  export declare function generateAuthWrapperTs(): string;
39
+ export type AirtableLockField = {
40
+ id: string;
41
+ sdkName: string;
42
+ type: string;
43
+ options?: string[];
44
+ };
45
+ export type AirtableLockTable = {
46
+ id: string;
47
+ sdkName: string;
48
+ fields: AirtableLockField[];
49
+ };
50
+ export type AirtableLock = {
51
+ integrationId: string;
52
+ tables: AirtableLockTable[];
53
+ };
54
+ export declare function generateAirtableTs(lock: AirtableLock): string | null;
39
55
  export declare function generateBackendWrapperTs(): string;
@@ -347,6 +347,86 @@ export function generateAuthWrapperTs() {
347
347
  "",
348
348
  ].join("\n");
349
349
  }
350
+ const AIRTABLE_FIELD_TYPE_MAP = {
351
+ singleLineText: "string",
352
+ multilineText: "string",
353
+ richText: "string",
354
+ email: "string",
355
+ url: "string",
356
+ phoneNumber: "string",
357
+ number: "number",
358
+ currency: "number",
359
+ percent: "number",
360
+ rating: "number",
361
+ duration: "number",
362
+ singleSelect: "string",
363
+ multipleSelects: "string[]",
364
+ checkbox: "boolean",
365
+ date: "string",
366
+ dateTime: "string",
367
+ attachment: "Array<{ url: string; filename?: string }>",
368
+ multipleRecordLinks: "string | string[]",
369
+ formula: "unknown",
370
+ rollup: "unknown",
371
+ lookup: "unknown",
372
+ count: "number",
373
+ autoNumber: "number",
374
+ barcode: "string",
375
+ button: "unknown",
376
+ createdTime: "string",
377
+ lastModifiedTime: "string",
378
+ createdBy: "unknown",
379
+ lastModifiedBy: "unknown",
380
+ externalSyncSource: "unknown",
381
+ aiText: "string",
382
+ };
383
+ function airtableTsType(field) {
384
+ if ((field.type === "singleSelect" || field.type === "multipleSelects") &&
385
+ field.options &&
386
+ field.options.length > 0) {
387
+ const literals = field.options
388
+ .slice(0, MAX_SELECT_OPTIONS)
389
+ .map((o) => `"${o.replace(/"/g, '\\"')}"`)
390
+ .join(" | ");
391
+ const union = `${literals} | string`;
392
+ if (field.type === "multipleSelects")
393
+ return `(${union})[]`;
394
+ return union;
395
+ }
396
+ return AIRTABLE_FIELD_TYPE_MAP[field.type] ?? "unknown";
397
+ }
398
+ export function generateAirtableTs(lock) {
399
+ if (lock.tables.length === 0)
400
+ return null;
401
+ const lines = [
402
+ "// Auto-generated by zitejs generate from zite.lock. Do not edit manually.",
403
+ "// Airtable SDK — uses createAirtableClient from zitejs/runtime.",
404
+ "// The airtable package is externalized (not bundled per-endpoint).",
405
+ "",
406
+ "import { createAirtableClient } from 'zitejs/runtime';",
407
+ "",
408
+ ];
409
+ for (const table of lock.tables) {
410
+ const recordType = `${table.sdkName}RecordType`;
411
+ lines.push(`export type ${recordType} = {`);
412
+ lines.push(" id: string;");
413
+ for (const field of table.fields) {
414
+ if (field.sdkName === "id")
415
+ continue;
416
+ const tsType = airtableTsType(field);
417
+ lines.push(` ${field.sdkName}: ${tsType};`);
418
+ }
419
+ lines.push("};");
420
+ lines.push("");
421
+ lines.push(`export const ${table.sdkName} = createAirtableClient<${recordType}>(`);
422
+ lines.push(` '${lock.integrationId}',`);
423
+ lines.push(` '${table.sdkName}',`);
424
+ lines.push(` { tableId: '${table.id}' },`);
425
+ lines.push(`);`);
426
+ lines.push("");
427
+ }
428
+ return lines.join("\n");
429
+ }
350
430
  export function generateBackendWrapperTs() {
351
431
  return [
352
432
  "// Auto-generated type-narrowing wrapper. Do not edit manually.",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "zitejs",
3
- "version": "0.9.42",
3
+ "version": "0.9.43",
4
4
  "description": "The Zite framework — build apps on Zite Database",
5
5
  "type": "module",
6
6
  "main": "./dist/cjs/index.js",