zitejs 0.9.122 → 0.9.124

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.
Files changed (70) hide show
  1. package/README.md +4 -0
  2. package/dist/cjs/auth/index.d.ts +2 -2
  3. package/dist/cjs/bundle/index.d.ts +5 -1
  4. package/dist/cjs/bundle/index.js +46 -26
  5. package/dist/cjs/check/index.js +2 -2
  6. package/dist/cjs/cli.js +1 -1
  7. package/dist/cjs/dev/index.d.ts +5 -0
  8. package/dist/cjs/dev/index.js +47 -1
  9. package/dist/cjs/index.d.ts +2 -0
  10. package/dist/cjs/index.js +7 -1
  11. package/dist/cjs/integrations/client.d.ts +25 -0
  12. package/dist/cjs/integrations/client.js +21 -0
  13. package/dist/cjs/integrations/client.test-d.d.ts +1 -0
  14. package/dist/cjs/integrations/client.test-d.js +50 -0
  15. package/dist/cjs/integrations/index.d.ts +3 -0
  16. package/dist/cjs/integrations/index.js +6 -0
  17. package/dist/cjs/integrations/rules.d.ts +67 -0
  18. package/dist/cjs/integrations/rules.js +104 -0
  19. package/dist/cjs/integrations/rules.test.d.ts +1 -0
  20. package/dist/cjs/integrations/rules.test.js +86 -0
  21. package/dist/cjs/internal/sdkCall.d.ts +1 -0
  22. package/dist/cjs/internal/sdkCall.js +3 -1
  23. package/dist/cjs/runtime/index.d.ts +1 -0
  24. package/dist/cjs/runtime/index.js +3 -1
  25. package/dist/cjs/sourceRoots.d.ts +13 -0
  26. package/dist/cjs/sourceRoots.js +38 -1
  27. package/dist/cjs/sourceRoots.test.d.ts +1 -0
  28. package/dist/cjs/sourceRoots.test.js +30 -0
  29. package/dist/cjs/sync/lib.d.ts +9 -0
  30. package/dist/cjs/sync/lib.js +53 -0
  31. package/dist/cjs/sync/lib.test.js +119 -0
  32. package/dist/esm/auth/index.d.ts +2 -2
  33. package/dist/esm/bundle/index.d.ts +5 -1
  34. package/dist/esm/bundle/index.js +47 -28
  35. package/dist/esm/check/index.js +3 -3
  36. package/dist/esm/cli.js +1 -1
  37. package/dist/esm/dev/index.d.ts +5 -0
  38. package/dist/esm/dev/index.js +48 -3
  39. package/dist/esm/index.d.ts +2 -0
  40. package/dist/esm/index.js +1 -0
  41. package/dist/esm/integrations/client.d.ts +25 -0
  42. package/dist/esm/integrations/client.js +17 -0
  43. package/dist/esm/integrations/client.test-d.d.ts +1 -0
  44. package/dist/esm/integrations/client.test-d.js +48 -0
  45. package/dist/esm/integrations/index.d.ts +3 -0
  46. package/dist/esm/integrations/index.js +3 -0
  47. package/dist/esm/integrations/rules.d.ts +67 -0
  48. package/dist/esm/integrations/rules.js +98 -0
  49. package/dist/esm/integrations/rules.test.d.ts +1 -0
  50. package/dist/esm/integrations/rules.test.js +84 -0
  51. package/dist/esm/internal/sdkCall.d.ts +1 -0
  52. package/dist/esm/internal/sdkCall.js +2 -1
  53. package/dist/esm/runtime/index.d.ts +1 -0
  54. package/dist/esm/runtime/index.js +1 -0
  55. package/dist/esm/sourceRoots.d.ts +13 -0
  56. package/dist/esm/sourceRoots.js +35 -1
  57. package/dist/esm/sourceRoots.test.d.ts +1 -0
  58. package/dist/esm/sourceRoots.test.js +28 -0
  59. package/dist/esm/sync/lib.d.ts +9 -0
  60. package/dist/esm/sync/lib.js +52 -0
  61. package/dist/esm/sync/lib.test.js +120 -1
  62. package/package.json +10 -1
  63. package/dist/cjs/meta/index.d.ts +0 -14
  64. package/dist/cjs/meta/index.js +0 -12
  65. package/dist/cjs/notifications/index.d.ts +0 -25
  66. package/dist/cjs/notifications/index.js +0 -12
  67. package/dist/esm/meta/index.d.ts +0 -14
  68. package/dist/esm/meta/index.js +0 -8
  69. package/dist/esm/notifications/index.d.ts +0 -25
  70. package/dist/esm/notifications/index.js +0 -8
package/README.md CHANGED
@@ -41,4 +41,8 @@ import { ZitePdf } from 'zitejs/pdf';
41
41
 
42
42
  // Scheduled tasks
43
43
  import { ZiteSchedule } from 'zitejs/schedules';
44
+
45
+ // An integration's credentials, by its zite.config.json entry name
46
+ import { integrations } from 'zitejs/integrations';
47
+ const crm = await integrations.get('crm');
44
48
  ```
@@ -67,7 +67,7 @@ export declare const signIn: {
67
67
  }, FetchOptions["throw"] extends true ? true : false>>;
68
68
  } & {
69
69
  social: <FetchOptions extends import("@better-auth/core").ClientFetchOption<Partial<{
70
- provider: (string & {}) | "linear" | "huggingface" | "github" | "apple" | "atlassian" | "cognito" | "discord" | "facebook" | "figma" | "microsoft" | "google" | "slack" | "spotify" | "twitch" | "twitter" | "dropbox" | "kick" | "linkedin" | "gitlab" | "tiktok" | "reddit" | "roblox" | "salesforce" | "vk" | "zoom" | "notion" | "kakao" | "naver" | "line" | "paybin" | "paypal" | "polar" | "railway" | "vercel" | "wechat";
70
+ provider: "salesforce" | "slack" | "linear" | "notion" | "linkedin" | "github" | (string & {}) | "huggingface" | "apple" | "atlassian" | "cognito" | "discord" | "facebook" | "figma" | "microsoft" | "google" | "spotify" | "twitch" | "twitter" | "dropbox" | "kick" | "gitlab" | "tiktok" | "reddit" | "roblox" | "vk" | "zoom" | "kakao" | "naver" | "line" | "paybin" | "paypal" | "polar" | "railway" | "vercel" | "wechat";
71
71
  callbackURL?: string | undefined;
72
72
  newUserCallbackURL?: string | undefined;
73
73
  errorCallbackURL?: string | undefined;
@@ -91,7 +91,7 @@ export declare const signIn: {
91
91
  loginHint?: string | undefined;
92
92
  additionalData?: Record<string, any> | undefined;
93
93
  }> & Record<string, any>, Partial<Record<string, any>> & Record<string, any>, Record<string, any> | undefined>>(data_0: import("better-auth/react").Prettify<{
94
- provider: (string & {}) | "linear" | "huggingface" | "github" | "apple" | "atlassian" | "cognito" | "discord" | "facebook" | "figma" | "microsoft" | "google" | "slack" | "spotify" | "twitch" | "twitter" | "dropbox" | "kick" | "linkedin" | "gitlab" | "tiktok" | "reddit" | "roblox" | "salesforce" | "vk" | "zoom" | "notion" | "kakao" | "naver" | "line" | "paybin" | "paypal" | "polar" | "railway" | "vercel" | "wechat";
94
+ provider: "salesforce" | "slack" | "linear" | "notion" | "linkedin" | "github" | (string & {}) | "huggingface" | "apple" | "atlassian" | "cognito" | "discord" | "facebook" | "figma" | "microsoft" | "google" | "spotify" | "twitch" | "twitter" | "dropbox" | "kick" | "gitlab" | "tiktok" | "reddit" | "roblox" | "vk" | "zoom" | "kakao" | "naver" | "line" | "paybin" | "paypal" | "polar" | "railway" | "vercel" | "wechat";
95
95
  callbackURL?: string | undefined;
96
96
  newUserCallbackURL?: string | undefined;
97
97
  errorCallbackURL?: string | undefined;
@@ -2,7 +2,7 @@
2
2
  * `npx zitejs bundle` — Bundle endpoint files for cloudflare-lambda deployment.
3
3
  *
4
4
  * Replaces the legacy `scripts/bundle-endpoints.js` from zitejs-starter.
5
- * Reads endpoints from src/api/*.ts, resolves SDK imports via .zite/backend.ts
5
+ * Reads an app's src/api/*.ts endpoints (an automation's single src/workflow.ts), resolves SDK imports via .zite/backend.ts
6
6
  * (monorepo) or src/__zite__/integrations.ts (legacy), and outputs bundled ESM
7
7
  * code suitable for the cloudflare-lambda worker runtime.
8
8
  *
@@ -22,4 +22,8 @@
22
22
  import * as esbuild from 'esbuild';
23
23
  export declare const UNSUPPORTED_IN_WORKERD: Set<string>;
24
24
  export declare const BASE_BUILD_OPTIONS: esbuild.BuildOptions;
25
+ export declare function createAliasPlugin(opts: {
26
+ baseDir?: string;
27
+ sdkPath?: string;
28
+ }): esbuild.Plugin;
25
29
  export declare function runBundle(): Promise<void>;
@@ -34,12 +34,13 @@ var __importStar = (this && this.__importStar) || (function () {
34
34
  })();
35
35
  Object.defineProperty(exports, "__esModule", { value: true });
36
36
  exports.BASE_BUILD_OPTIONS = exports.UNSUPPORTED_IN_WORKERD = void 0;
37
+ exports.createAliasPlugin = createAliasPlugin;
37
38
  exports.runBundle = runBundle;
38
39
  /**
39
40
  * `npx zitejs bundle` — Bundle endpoint files for cloudflare-lambda deployment.
40
41
  *
41
42
  * Replaces the legacy `scripts/bundle-endpoints.js` from zitejs-starter.
42
- * Reads endpoints from src/api/*.ts, resolves SDK imports via .zite/backend.ts
43
+ * Reads an app's src/api/*.ts endpoints (an automation's single src/workflow.ts), resolves SDK imports via .zite/backend.ts
43
44
  * (monorepo) or src/__zite__/integrations.ts (legacy), and outputs bundled ESM
44
45
  * code suitable for the cloudflare-lambda worker runtime.
45
46
  *
@@ -61,6 +62,8 @@ const path = __importStar(require("path"));
61
62
  const fs = __importStar(require("fs"));
62
63
  const parser_1 = require("@babel/parser");
63
64
  const node_module_1 = require("node:module");
65
+ const client_js_1 = require("../integrations/client.js");
66
+ const sdkCall_js_1 = require("../internal/sdkCall.js");
64
67
  const sourceRoots_js_1 = require("../sourceRoots.js");
65
68
  // workerd's `nodejs_compat` does not provide these. Left external they bundle
66
69
  // fine and then kill the worker at load time with `No such module`; excluded,
@@ -229,7 +232,7 @@ function getSdkImportSource(baseDir) {
229
232
  return 'zite-integrations-backend-sdk';
230
233
  }
231
234
  /**
232
- * `zitejs/db`, `zitejs/api`, `zitejs/integrations` and `zitejs/email` are
235
+ * `zitejs/db`, `zitejs/api` and `zitejs/email` are
233
236
  * tsconfig aliases onto generated files, not real package subpaths — they are
234
237
  * absent from the `exports` map. `zitejs/backend` IS a real subpath export, but
235
238
  * it lands here too and `zitejs` is not in PREBUNDLED_LIBS, so nothing would
@@ -242,6 +245,18 @@ const unresolvedAlias = (specifier, expectedPath) => {
242
245
  throw new Error(`Cannot resolve '${specifier}': expected generated file at ${expectedPath}. ` +
243
246
  `Run \`npx zitejs generate\` before bundling.`);
244
247
  };
248
+ const AUTH_SERVER_SHIM_PATH = 'zitejs-auth-server-shim';
249
+ const INTEGRATIONS_SHIM_PATH = 'zitejs-integrations-shim';
250
+ const VIRTUAL_MODULES = {
251
+ [AUTH_SERVER_SHIM_PATH]: 'export const ziteAuth = (config) => config;',
252
+ [INTEGRATIONS_SHIM_PATH]: `export const integrations = {
253
+ get(name) {
254
+ const sdkCall = globalThis.__wrapSdkCall;
255
+ if (!sdkCall) throw new Error(${JSON.stringify(sdkCall_js_1.SDK_NOT_INITIALIZED_MESSAGE)});
256
+ return sdkCall(${JSON.stringify(client_js_1.INTEGRATIONS_SDK_INTEGRATION_ID)}, ${JSON.stringify(client_js_1.INTEGRATIONS_CLASS_NAME)}, 'get', { name });
257
+ },
258
+ };`,
259
+ };
245
260
  function createAliasPlugin(opts) {
246
261
  return {
247
262
  name: 'zite-alias',
@@ -293,14 +308,18 @@ function createAliasPlugin(opts) {
293
308
  }
294
309
  return unresolvedAlias('zitejs/api', `${opts.baseDir}/.zite/api.ts`);
295
310
  });
296
- // Resolve zitejs/integrations to .zite/integrations/airtable.ts
311
+ // zitejs/integrations: the generated index (the integrations client plus
312
+ // any Airtable clients), else Airtable alone from an older generate, else
313
+ // this bundler's own client, whatever zitejs the project pins.
297
314
  build.onResolve({ filter: /^zitejs\/integrations$/ }, () => {
298
315
  if (opts.baseDir) {
299
- const intPath = path.resolve(opts.baseDir, '.zite/integrations/airtable.ts');
300
- if (fs.existsSync(intPath))
301
- return { path: intPath };
316
+ for (const file of ['index.ts', 'airtable.ts']) {
317
+ const intPath = path.resolve(opts.baseDir, '.zite/integrations', file);
318
+ if (fs.existsSync(intPath))
319
+ return { path: intPath };
320
+ }
302
321
  }
303
- return unresolvedAlias('zitejs/integrations', `${opts.baseDir}/.zite/integrations/airtable.ts`);
322
+ return { path: INTEGRATIONS_SHIM_PATH, namespace: 'zite-virtual' };
304
323
  });
305
324
  // Resolve zitejs/email to .zite/integrations/email.ts
306
325
  build.onResolve({ filter: /^zitejs\/email$/ }, () => {
@@ -314,11 +333,11 @@ function createAliasPlugin(opts) {
314
333
  // zitejs/auth/server is types + an identity wrapper — inline a shim so
315
334
  // zite.auth.ts bundles without resolving the installed package.
316
335
  build.onResolve({ filter: /^zitejs\/auth\/server$/ }, () => ({
317
- path: 'zitejs-auth-server-shim',
336
+ path: AUTH_SERVER_SHIM_PATH,
318
337
  namespace: 'zite-virtual',
319
338
  }));
320
- build.onLoad({ filter: /.*/, namespace: 'zite-virtual' }, () => ({
321
- contents: 'export const ziteAuth = (config) => config;',
339
+ build.onLoad({ filter: /.*/, namespace: 'zite-virtual' }, (args) => ({
340
+ contents: VIRTUAL_MODULES[args.path],
322
341
  loader: 'js',
323
342
  }));
324
343
  // zitejs/runtime is NOT in PREBUNDLED_LIBS — it's a thin fetch()
@@ -334,7 +353,7 @@ function createAliasPlugin(opts) {
334
353
  },
335
354
  };
336
355
  }
337
- function generateEndpointWrapper(endpointName, usedImports, sdkExportKinds, sdkSource) {
356
+ function generateEndpointWrapper(entryImport, usedImports, sdkExportKinds, sdkSource) {
338
357
  // Always import the prebundled runtime to ensure globalThis.__wrapSdkCall
339
358
  // is available for createTableClient/createSqlClient from zitejs/runtime.
340
359
  const runtimeInit = `import { __wrapSdkCall, initRuntime } from '@zite/endpoints-runtime-sdk';
@@ -345,14 +364,14 @@ initRuntime();`;
345
364
  ${runtimeInit}
346
365
  import * as sdk from '${sdkSource}';
347
366
  Object.assign(globalThis, sdk);
348
- import endpoint from './api/${endpointName}';
367
+ import endpoint from '${entryImport}';
349
368
  globalThis.__endpoint = endpoint;
350
369
  `;
351
370
  }
352
371
  if (usedImports.length === 0) {
353
372
  return `
354
373
  ${runtimeInit}
355
- import endpoint from './api/${endpointName}';
374
+ import endpoint from '${entryImport}';
356
375
  globalThis.__endpoint = endpoint;
357
376
  `;
358
377
  }
@@ -380,11 +399,11 @@ globalThis.__endpoint = endpoint;
380
399
  ${runtimeInit}
381
400
  ${importStatements.join('\n')}
382
401
  ${globalAssign}
383
- import endpoint from './api/${endpointName}';
402
+ import endpoint from '${entryImport}';
384
403
  globalThis.__endpoint = endpoint;
385
404
  `;
386
405
  }
387
- async function bundleEndpointsImpl(baseDir, endpointNames) {
406
+ async function bundleEndpointsImpl(baseDir, root, endpointNames) {
388
407
  const bundledEndpoints = {};
389
408
  const endpointErrors = {};
390
409
  const aliasPlugin = createAliasPlugin({ baseDir });
@@ -399,14 +418,20 @@ async function bundleEndpointsImpl(baseDir, endpointNames) {
399
418
  }
400
419
  catch { }
401
420
  for (const name of endpointNames) {
421
+ if (root === 'automations' && name !== sourceRoots_js_1.AUTOMATION_ENDPOINT_NAME) {
422
+ endpointErrors[name] =
423
+ `An automation is one workflow, src/workflow.ts, bundled as "${sourceRoots_js_1.AUTOMATION_ENDPOINT_NAME}"; there is no endpoint "${name}"`;
424
+ continue;
425
+ }
426
+ const entryFile = (0, sourceRoots_js_1.endpointEntryFile)(root, name);
402
427
  let usedImports = null;
403
428
  try {
404
- const endpointPath = path.join(baseDir, 'src', 'api', `${name}.ts`);
405
- const endpointCode = fs.readFileSync(endpointPath, 'utf-8');
429
+ const endpointCode = fs.readFileSync(path.join(baseDir, entryFile), 'utf-8');
406
430
  usedImports = getUsedSdkImports(endpointCode);
407
431
  }
408
432
  catch { }
409
- const wrapperCode = generateEndpointWrapper(name, usedImports, sdkExportKinds, sdkSource);
433
+ // The wrapper resolves from `src/`, so the entry is imported relative to it.
434
+ const wrapperCode = generateEndpointWrapper('./' + path.relative('src', entryFile).replace(/\.ts$/, ''), usedImports, sdkExportKinds, sdkSource);
410
435
  try {
411
436
  const result = await esbuild.build({
412
437
  ...exports.BASE_BUILD_OPTIONS,
@@ -629,18 +654,13 @@ async function runBundle() {
629
654
  // as missing.
630
655
  const explicitNames = args.filter((a, i) => !a.startsWith('--') && !(appFlag !== -1 && i === appFlag + 1));
631
656
  let endpointNames;
657
+ const root = (0, sourceRoots_js_1.sourceRootOf)(baseDir) ?? 'apps';
632
658
  if (explicitNames.length > 0) {
633
659
  endpointNames = explicitNames;
634
660
  }
635
661
  else {
636
- const apiDir = path.join(baseDir, 'src', 'api');
637
- endpointNames = fs.existsSync(apiDir)
638
- ? fs
639
- .readdirSync(apiDir)
640
- .filter(f => f.endsWith('.ts'))
641
- .map(f => f.replace('.ts', ''))
642
- : [];
662
+ endpointNames = (0, sourceRoots_js_1.listEndpointNames)(root, baseDir);
643
663
  }
644
664
  // Even with no endpoints, zite.auth.ts may still need bundling.
645
- return bundleEndpointsImpl(baseDir, endpointNames);
665
+ return bundleEndpointsImpl(baseDir, root, endpointNames);
646
666
  }
@@ -65,7 +65,7 @@ async function runCheck() {
65
65
  process.exit(1);
66
66
  }
67
67
  let allPassed = true;
68
- for (const { dir: app, path: appPath } of appDirs) {
68
+ for (const { root, dir: app, path: appPath } of appDirs) {
69
69
  console.log(`\n── ${appPath} ──`);
70
70
  // Only tsconfig.app.json compiles anything. The app's tsconfig.json is a
71
71
  // solution-style config — `"files": []` plus a reference — so
@@ -92,7 +92,7 @@ async function runCheck() {
92
92
  // Endpoints never reach vite — they are bundled separately for the lambda,
93
93
  // against a different resolver. tsc and vite both pass on an endpoint whose
94
94
  // `zitejs/*` alias has no generated file behind it; only the bundler knows.
95
- if ((0, fs_1.existsSync)((0, path_1.join)(appPath, 'src', 'api'))) {
95
+ if ((0, sourceRoots_js_1.listEndpointNames)(root, appPath).length > 0) {
96
96
  process.stdout.write(' bundle endpoints ... ');
97
97
  const bundle = run('npx', ['zitejs', 'bundle', '--app', app], '.');
98
98
  const failures = bundle.ok ? bundleFailures(bundle.output) : [bundle.output];
package/dist/cjs/cli.js CHANGED
@@ -75,7 +75,7 @@ async function main() {
75
75
  console.error(' dev Run sync then watch for changes (like npx convex dev)');
76
76
  console.error(' generate Regenerate every app and automation .zite/ (monorepo)');
77
77
  console.error(' check Run tsc --noEmit (and vite build where there is one) for every app and automation');
78
- console.error(' bundle Bundle src/api/*.ts endpoints for cloudflare-lambda');
78
+ console.error(' bundle Bundle endpoints (src/api/*.ts, or an automation\'s src/workflow.ts) for cloudflare-lambda');
79
79
  process.exit(1);
80
80
  }
81
81
  }
@@ -1,2 +1,7 @@
1
+ /**
2
+ * Whether the zitejs that `fromDir` resolves, nearest first up to the project root,
3
+ * has the integrations client: the CLI running generate can be newer than that pin.
4
+ */
5
+ export declare function projectRuntimeHasIntegrationsClient(fromDir: string, projectRoot?: string): boolean;
1
6
  export declare function runGenerate(): Promise<void>;
2
7
  export declare function runDev(): Promise<void>;
@@ -1,5 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.projectRuntimeHasIntegrationsClient = projectRuntimeHasIntegrationsClient;
3
4
  exports.runGenerate = runGenerate;
4
5
  exports.runDev = runDev;
5
6
  const fs_1 = require("fs");
@@ -8,6 +9,7 @@ const path_1 = require("path");
8
9
  const sourceRoots_js_1 = require("../sourceRoots.js");
9
10
  const index_js_1 = require("../sync/index.js");
10
11
  const lib_js_1 = require("../sync/lib.js");
12
+ const rules_js_1 = require("../integrations/rules.js");
11
13
  const debounceTimers = new Map();
12
14
  function debounce(key, fn, ms) {
13
15
  const existing = debounceTimers.get(key);
@@ -39,6 +41,48 @@ const readJsonFile = (path) => {
39
41
  function getEmailIntegrationId(appDir) {
40
42
  return (0, lib_js_1.findEmailIntegrationId)(readJsonFile((0, path_1.join)(appDir.path, "zite.config.json")), readJsonFile("zite.config.json"));
41
43
  }
44
+ // `{}` with no file; undefined when unreadable, so a failed read keeps the old file.
45
+ const readConfigIntegrations = (path) => {
46
+ if (!(0, fs_2.existsSync)(path))
47
+ return {};
48
+ const config = readJsonFile(path);
49
+ if (typeof config !== "object" || config === null)
50
+ return undefined;
51
+ const { integrations } = config;
52
+ if (integrations == null)
53
+ return {};
54
+ return typeof integrations === "object" && !Array.isArray(integrations)
55
+ ? integrations
56
+ : undefined;
57
+ };
58
+ /**
59
+ * Whether the zitejs that `fromDir` resolves, nearest first up to the project root,
60
+ * has the integrations client: the CLI running generate can be newer than that pin.
61
+ */
62
+ function projectRuntimeHasIntegrationsClient(fromDir, projectRoot = process.cwd()) {
63
+ const root = (0, path_1.resolve)(projectRoot);
64
+ for (let dir = (0, path_1.resolve)(fromDir);; dir = (0, path_1.dirname)(dir)) {
65
+ const pkg = readJsonFile((0, path_1.join)(dir, "node_modules", "zitejs", "package.json"));
66
+ if (pkg)
67
+ return pkg.exports?.["./integrations"] !== undefined;
68
+ if (dir === root || (0, path_1.dirname)(dir) === dir)
69
+ return false;
70
+ }
71
+ }
72
+ // Runs after the Airtable step, so the index re-exports its clients when they exist.
73
+ function regenerateAppIntegrationsIndex(appDir) {
74
+ if (!projectRuntimeHasIntegrationsClient(appDir.path))
75
+ return;
76
+ const root = readConfigIntegrations("zite.config.json");
77
+ const own = readConfigIntegrations((0, path_1.join)(appDir.path, "zite.config.json"));
78
+ if (!root || !own)
79
+ return;
80
+ const intDir = (0, path_1.join)(appDir.path, ".zite", "integrations");
81
+ (0, fs_2.mkdirSync)(intDir, { recursive: true });
82
+ (0, fs_2.writeFileSync)((0, path_1.join)(intDir, "index.ts"), (0, lib_js_1.generateIntegrationsIndex)((0, rules_js_1.gettableIntegrations)(root, own), {
83
+ reexportAirtable: (0, fs_2.existsSync)((0, path_1.join)(intDir, "airtable.ts")),
84
+ }));
85
+ }
42
86
  function getDeclaredEnvVarNames(appDir) {
43
87
  try {
44
88
  const configPath = (0, path_1.join)(appDir.path, "zite.config.json");
@@ -153,6 +197,7 @@ async function runGenerate() {
153
197
  regenerateAppApiTs(app);
154
198
  regenerateAppTypedWrappers(app);
155
199
  regenerateAppAirtableSdk(app);
200
+ regenerateAppIntegrationsIndex(app);
156
201
  }
157
202
  console.log("Done!");
158
203
  }
@@ -173,6 +218,7 @@ async function runDev() {
173
218
  for (const app of appDirs) {
174
219
  regenerateAppApiTs(app);
175
220
  regenerateAppTypedWrappers(app);
221
+ regenerateAppIntegrationsIndex(app);
176
222
  }
177
223
  // 3. Watch each dir's src/api/ for endpoint changes
178
224
  let watchingAny = false;
@@ -194,7 +240,7 @@ async function runDev() {
194
240
  });
195
241
  }
196
242
  if (!watchingAny) {
197
- console.log("No apps or automations with src/api/ found.");
243
+ console.log("No apps with src/api/ found.");
198
244
  }
199
245
  // 4. Watch zite.schema.json for schema drift
200
246
  if ((0, fs_2.existsSync)("zite.schema.json")) {
@@ -1,3 +1,5 @@
1
1
  export { Zite } from "./client/index.js";
2
2
  export type { Record, RecordListOutput, RecordListOptions, FieldCreateInput, FieldUpdateInput, TableCreateInput, TableUpdateInput, DatabaseCreateInput, DatabaseListOutput, } from "./client/index.js";
3
3
  export * from "./types/index.js";
4
+ export { CREDENTIAL_FIELDS, NON_CREDENTIAL_SERVICE_TYPES, gettableIntegrations, isCredentialServiceType, normalizeIntegrationServiceType, } from "./integrations/rules.js";
5
+ export type { ConfigIntegrations, CredentialServiceType, GettableIntegration, } from "./integrations/rules.js";
package/dist/cjs/index.js CHANGED
@@ -14,7 +14,13 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
14
  for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
15
  };
16
16
  Object.defineProperty(exports, "__esModule", { value: true });
17
- exports.Zite = void 0;
17
+ exports.normalizeIntegrationServiceType = exports.isCredentialServiceType = exports.gettableIntegrations = exports.NON_CREDENTIAL_SERVICE_TYPES = exports.CREDENTIAL_FIELDS = exports.Zite = void 0;
18
18
  var index_js_1 = require("./client/index.js");
19
19
  Object.defineProperty(exports, "Zite", { enumerable: true, get: function () { return index_js_1.Zite; } });
20
20
  __exportStar(require("./types/index.js"), exports);
21
+ var rules_js_1 = require("./integrations/rules.js");
22
+ Object.defineProperty(exports, "CREDENTIAL_FIELDS", { enumerable: true, get: function () { return rules_js_1.CREDENTIAL_FIELDS; } });
23
+ Object.defineProperty(exports, "NON_CREDENTIAL_SERVICE_TYPES", { enumerable: true, get: function () { return rules_js_1.NON_CREDENTIAL_SERVICE_TYPES; } });
24
+ Object.defineProperty(exports, "gettableIntegrations", { enumerable: true, get: function () { return rules_js_1.gettableIntegrations; } });
25
+ Object.defineProperty(exports, "isCredentialServiceType", { enumerable: true, get: function () { return rules_js_1.isCredentialServiceType; } });
26
+ Object.defineProperty(exports, "normalizeIntegrationServiceType", { enumerable: true, get: function () { return rules_js_1.normalizeIntegrationServiceType; } });
@@ -0,0 +1,25 @@
1
+ export declare const INTEGRATIONS_SDK_INTEGRATION_ID = "__connections__";
2
+ export declare const INTEGRATIONS_CLASS_NAME = "Connections";
3
+ /**
4
+ * `accessToken` is the service's primary credential (for Twilio the account SID).
5
+ * Call `get` where the value is used: a token refreshed mid-run is what the next call returns.
6
+ */
7
+ export type Connected<Extra = {}> = {
8
+ status: "connected";
9
+ accessToken: string;
10
+ } & Extra;
11
+ /** No account behind the entry, or its token could not be refreshed. `connectUrl` is where a person fixes that. */
12
+ export type NeedsConnect = {
13
+ status: "missing" | "expired";
14
+ connectUrl: string;
15
+ };
16
+ export interface IntegrationsClient<ByName extends Record<string, unknown>> {
17
+ /** The credentials of the `zite.config.json` integration entry named `name`. */
18
+ get<Name extends keyof ByName & string>(name: Name): Promise<ByName[Name]>;
19
+ }
20
+ /**
21
+ * `ByName` maps each entry name to its answer, e.g.
22
+ * `{ crm: Connected<{ instanceUrl: string }> | NeedsConnect }`; `zitejs generate`
23
+ * writes it per app into `.zite/integrations/index.ts`.
24
+ */
25
+ export declare function createIntegrationsClient<ByName extends Record<string, unknown>>(): IntegrationsClient<ByName>;
@@ -0,0 +1,21 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.INTEGRATIONS_CLASS_NAME = exports.INTEGRATIONS_SDK_INTEGRATION_ID = void 0;
4
+ exports.createIntegrationsClient = createIntegrationsClient;
5
+ const sdkCall_js_1 = require("../internal/sdkCall.js");
6
+ // The worker and runner answer this call under its original name; renaming the
7
+ // wire protocol would break every deployed bundle for no user-visible gain.
8
+ exports.INTEGRATIONS_SDK_INTEGRATION_ID = "__connections__";
9
+ exports.INTEGRATIONS_CLASS_NAME = "Connections";
10
+ /**
11
+ * `ByName` maps each entry name to its answer, e.g.
12
+ * `{ crm: Connected<{ instanceUrl: string }> | NeedsConnect }`; `zitejs generate`
13
+ * writes it per app into `.zite/integrations/index.ts`.
14
+ */
15
+ function createIntegrationsClient() {
16
+ return {
17
+ get(name) {
18
+ return (0, sdkCall_js_1.getSdkCall)()(exports.INTEGRATIONS_SDK_INTEGRATION_ID, exports.INTEGRATIONS_CLASS_NAME, "get", { name });
19
+ },
20
+ };
21
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,50 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const vitest_1 = require("vitest");
4
+ const client_js_1 = require("./client.js");
5
+ const index_js_1 = require("./index.js");
6
+ const index_js_2 = require("../index.js");
7
+ (0, vitest_1.describe)("createIntegrationsClient", () => {
8
+ const client = (0, client_js_1.createIntegrationsClient)();
9
+ (0, vitest_1.it)("types each name's answer", () => {
10
+ (0, vitest_1.expectTypeOf)(client.get("crm")).resolves.toEqualTypeOf();
11
+ });
12
+ (0, vitest_1.it)("rejects a name the app cannot see", () => {
13
+ // @ts-expect-error not a visible entry
14
+ void client.get("nope");
15
+ });
16
+ // What `.zite/integrations/index.ts` emits when nothing is visible.
17
+ (0, vitest_1.it)("accepts an empty map, naming nothing", () => {
18
+ const none = (0, client_js_1.createIntegrationsClient)();
19
+ (0, vitest_1.expectTypeOf)().toEqualTypeOf();
20
+ });
21
+ (0, vitest_1.it)("narrows to the connected fields on status", async () => {
22
+ const crm = await client.get("crm");
23
+ if (crm.status === "connected") {
24
+ (0, vitest_1.expectTypeOf)(crm.instanceUrl).toEqualTypeOf();
25
+ }
26
+ else {
27
+ (0, vitest_1.expectTypeOf)(crm.connectUrl).toEqualTypeOf();
28
+ }
29
+ });
30
+ });
31
+ (0, vitest_1.describe)("the untyped zitejs/integrations client", () => {
32
+ (0, vitest_1.it)("takes any name; only accessToken is certain", async () => {
33
+ const entry = await index_js_1.integrations.get("anything");
34
+ if (entry.status === "connected") {
35
+ (0, vitest_1.expectTypeOf)(entry.accessToken).toEqualTypeOf();
36
+ (0, vitest_1.expectTypeOf)(entry.instanceUrl).toEqualTypeOf();
37
+ }
38
+ });
39
+ });
40
+ (0, vitest_1.describe)("CREDENTIAL_FIELDS", () => {
41
+ (0, vitest_1.it)("is keyed by service type, and a string narrows to one", () => {
42
+ (0, vitest_1.expectTypeOf)(index_js_2.CREDENTIAL_FIELDS.salesforce).toEqualTypeOf();
43
+ const type = "salesforce";
44
+ // @ts-expect-error a plain string is not a service type
45
+ void index_js_2.CREDENTIAL_FIELDS[type];
46
+ if ((0, index_js_2.isCredentialServiceType)(type)) {
47
+ (0, vitest_1.expectTypeOf)(index_js_2.CREDENTIAL_FIELDS[type]).toEqualTypeOf();
48
+ }
49
+ });
50
+ });
@@ -0,0 +1,3 @@
1
+ import { type Connected, type NeedsConnect } from "./client.js";
2
+ export type { Connected, NeedsConnect } from "./client.js";
3
+ export declare const integrations: import("./client.js").IntegrationsClient<Record<string, NeedsConnect | Connected<Partial<Record<string, string>>>>>;
@@ -0,0 +1,6 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.integrations = void 0;
4
+ const client_js_1 = require("./client.js");
5
+ // What code with no generated `.zite/integrations/index.ts` gets, e.g. a repo-root script.
6
+ exports.integrations = (0, client_js_1.createIntegrationsClient)();
@@ -0,0 +1,67 @@
1
+ declare const FIELDS_BY_TYPE: {
2
+ googleCalendar: readonly string[];
3
+ googleDrive: readonly string[];
4
+ gmail: readonly string[];
5
+ googleDocs: readonly string[];
6
+ hubspot: readonly string[];
7
+ salesforce: readonly string[];
8
+ twilio: readonly string[];
9
+ slack: readonly string[];
10
+ linear: readonly string[];
11
+ openai: readonly string[];
12
+ googlesheets: readonly string[];
13
+ microsoftTeams: readonly string[];
14
+ onedrive: readonly string[];
15
+ outlook: readonly string[];
16
+ intercom: readonly string[];
17
+ mailchimp: readonly string[];
18
+ anthropic: readonly string[];
19
+ gemini: readonly string[];
20
+ stripe: readonly string[];
21
+ trello: readonly string[];
22
+ notion: readonly string[];
23
+ facebookPages: readonly string[];
24
+ monday: readonly string[];
25
+ resend: readonly string[];
26
+ clickhouse: readonly string[];
27
+ amplitude: readonly string[];
28
+ elevenlabs: readonly string[];
29
+ brevo: readonly string[];
30
+ calendly: readonly string[];
31
+ asana: readonly string[];
32
+ xero: readonly string[];
33
+ googleForms: readonly string[];
34
+ linkedin: readonly string[];
35
+ github: readonly string[];
36
+ quickbooks: readonly string[];
37
+ firecrawl: readonly string[];
38
+ jira: readonly string[];
39
+ typeform: readonly string[];
40
+ apollo: readonly string[];
41
+ attio: readonly string[];
42
+ };
43
+ /** A service type `integrations.get` serves: one used through its npm package with a token. */
44
+ export type CredentialServiceType = keyof typeof FIELDS_BY_TYPE;
45
+ /** Per service type: `accessToken`, then its extra labels sorted (Salesforce `instanceUrl`). */
46
+ export declare const CREDENTIAL_FIELDS: Readonly<Record<CredentialServiceType, readonly string[]>>;
47
+ /**
48
+ * Types the runtime never serves: those with a generated client (Airtable, email,
49
+ * the project database, Fillout) and those whose key is a frontend value (Maps, Analytics).
50
+ */
51
+ export declare const NON_CREDENTIAL_SERVICE_TYPES: readonly string[];
52
+ export declare const normalizeIntegrationServiceType: (type: string) => string;
53
+ export declare const isCredentialServiceType: (type: string) => type is CredentialServiceType;
54
+ /** One entry `integrations.get` can name from a source dir. */
55
+ export type GettableIntegration = {
56
+ name: string;
57
+ serviceType: CredentialServiceType;
58
+ };
59
+ export type ConfigIntegrations = Readonly<Record<string, {
60
+ type?: unknown;
61
+ } | undefined>>;
62
+ /**
63
+ * The entries a source dir can name, by name: its own, then the workspace's under
64
+ * keys it has not taken. An entry whose type the runtime would not serve is dropped.
65
+ */
66
+ export declare const gettableIntegrations: (rootIntegrations: ConfigIntegrations | undefined, appIntegrations?: ConfigIntegrations) => GettableIntegration[];
67
+ export {};