zitejs 0.9.124 → 0.9.126
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/backend/index.d.ts +53 -3
- package/dist/cjs/backend/index.test.js +42 -0
- package/dist/cjs/bundle/index.d.ts +1 -1
- package/dist/cjs/bundle/index.js +2 -2
- package/dist/cjs/cli.js +1 -1
- package/dist/cjs/integrations/rules.d.ts +1 -0
- package/dist/cjs/integrations/rules.js +1 -0
- package/dist/cjs/integrations/rules.test.js +1 -0
- package/dist/cjs/meta/index.d.ts +14 -0
- package/dist/cjs/meta/index.js +12 -0
- package/dist/cjs/notifications/index.d.ts +25 -0
- package/dist/cjs/notifications/index.js +12 -0
- package/dist/cjs/sourceRoots.d.ts +3 -3
- package/dist/cjs/sourceRoots.js +6 -6
- package/dist/cjs/sourceRoots.test.js +4 -4
- package/dist/cjs/sync/lib.js +1 -1
- package/dist/cjs/sync/lib.test.js +1 -1
- package/dist/esm/backend/index.d.ts +53 -3
- package/dist/esm/backend/index.test.js +42 -0
- package/dist/esm/bundle/index.d.ts +1 -1
- package/dist/esm/bundle/index.js +2 -2
- package/dist/esm/cli.js +1 -1
- package/dist/esm/integrations/rules.d.ts +1 -0
- package/dist/esm/integrations/rules.js +1 -0
- package/dist/esm/integrations/rules.test.js +1 -0
- package/dist/esm/meta/index.d.ts +14 -0
- package/dist/esm/meta/index.js +8 -0
- package/dist/esm/notifications/index.d.ts +25 -0
- package/dist/esm/notifications/index.js +8 -0
- package/dist/esm/sourceRoots.d.ts +3 -3
- package/dist/esm/sourceRoots.js +5 -5
- package/dist/esm/sourceRoots.test.js +4 -4
- package/dist/esm/sync/lib.js +1 -1
- package/dist/esm/sync/lib.test.js +1 -1
- package/package.json +1 -1
|
@@ -13,17 +13,59 @@ export type ZiteWebhook = {
|
|
|
13
13
|
export type ZiteTrigger = {
|
|
14
14
|
/**
|
|
15
15
|
* The connection's name in `zite.config.json`. Registered with the
|
|
16
|
-
* provider by `
|
|
17
|
-
* by `unsubscribe
|
|
16
|
+
* provider by the endpoint file's own `subscribe` export and taken down
|
|
17
|
+
* by its `unsubscribe` export, which the platform runs at publish and
|
|
18
|
+
* teardown.
|
|
18
19
|
*/
|
|
19
20
|
integration: string;
|
|
21
|
+
/** The sentence the editor shows for what fires this endpoint, e.g. "When a task is completed in Asana". */
|
|
22
|
+
label?: string;
|
|
20
23
|
paused?: boolean;
|
|
21
24
|
} | {
|
|
22
25
|
provider: "poll";
|
|
23
26
|
/** `<n>m` (1–59) or `<n>h` (1–23) */
|
|
24
27
|
every: string;
|
|
28
|
+
/** The sentence the editor shows for this poll, e.g. "Every 10 minutes, new Stripe charges". */
|
|
29
|
+
label?: string;
|
|
25
30
|
paused?: boolean;
|
|
26
31
|
};
|
|
32
|
+
/**
|
|
33
|
+
* What a poll-triggered run receives as `input.__poll`. Only on a fire from
|
|
34
|
+
* the poll's schedule; a request call to the same endpoint carries none.
|
|
35
|
+
*/
|
|
36
|
+
export type ZitePollInput = {
|
|
37
|
+
/** What the previous successful run returned as `cursor`; null on the first run. */
|
|
38
|
+
cursor: string | null;
|
|
39
|
+
/** Ids earlier runs returned as `handled`, newest last. Skip these. */
|
|
40
|
+
seen: string[];
|
|
41
|
+
};
|
|
42
|
+
/**
|
|
43
|
+
* What a provider trigger's delivery carries as `input.__webhook`, beside the
|
|
44
|
+
* provider's own body. `cursor` and `seen` work as they do for a poll: for a
|
|
45
|
+
* provider whose notification only says that something changed, `subscribe`
|
|
46
|
+
* returns a starting `cursor` and each delivery returns the next one. A
|
|
47
|
+
* trigger that keeps a cursor gets one delivery at a time.
|
|
48
|
+
*/
|
|
49
|
+
export type ZiteTriggerDelivery = {
|
|
50
|
+
headers: Record<string, string>;
|
|
51
|
+
/** The provider's id for this delivery; redeliveries share it. */
|
|
52
|
+
deliveryId?: string;
|
|
53
|
+
provider?: string;
|
|
54
|
+
/** What `subscribe` or the previous successful delivery returned as `cursor`. */
|
|
55
|
+
cursor: string | null;
|
|
56
|
+
/** Ids earlier deliveries returned as `handled`, newest last. Skip these. */
|
|
57
|
+
seen: string[];
|
|
58
|
+
};
|
|
59
|
+
/**
|
|
60
|
+
* What a poll-triggered run, or a provider trigger's delivery, returns for
|
|
61
|
+
* the platform to keep: its new `cursor`, and the id of every item it acted
|
|
62
|
+
* on, so the next run's `seen` includes them even if the cursor hands them
|
|
63
|
+
* back.
|
|
64
|
+
*/
|
|
65
|
+
export type ZitePollResult = {
|
|
66
|
+
cursor?: string;
|
|
67
|
+
handled?: string[];
|
|
68
|
+
};
|
|
27
69
|
export interface ZiteRequestContext {
|
|
28
70
|
user: {
|
|
29
71
|
id: string;
|
|
@@ -116,7 +158,15 @@ export interface EndpointConfig<TInput = unknown, TOutput = unknown, TStream ext
|
|
|
116
158
|
*/
|
|
117
159
|
validatesInput?: boolean;
|
|
118
160
|
execute: (params: {
|
|
119
|
-
input:
|
|
161
|
+
input: TTrigger extends {
|
|
162
|
+
provider: "poll";
|
|
163
|
+
} ? TInput & {
|
|
164
|
+
__poll?: ZitePollInput;
|
|
165
|
+
} : TTrigger extends {
|
|
166
|
+
integration: string;
|
|
167
|
+
} ? TInput & {
|
|
168
|
+
__webhook?: ZiteTriggerDelivery;
|
|
169
|
+
} : TInput;
|
|
120
170
|
context: TSchedule extends ZiteSchedule ? ZiteRequestContext | ZiteScheduledContext : TWebhook extends ZiteWebhook ? ZiteRequestContext | ZiteScheduledContext : TTrigger extends ZiteTrigger ? ZiteRequestContext | ZiteScheduledContext : ZiteRequestContext;
|
|
121
171
|
} & (TStream extends true ? {
|
|
122
172
|
stream: ZiteStreamInterface;
|
|
@@ -133,6 +133,48 @@ const requestContext = { user: { id: "u1", email: "a@b.c" } };
|
|
|
133
133
|
});
|
|
134
134
|
await (0, vitest_1.expect)(endpoint.execute({ input: undefined, context: requestContext })).rejects.toMatchObject({ code: "BAD_REQUEST" });
|
|
135
135
|
});
|
|
136
|
+
(0, vitest_1.it)("hands a poll its cursor and seen ids, typed", async () => {
|
|
137
|
+
const endpoint = (0, index_js_1.createEndpoint)({
|
|
138
|
+
inputSchema: zod_1.z.object({}),
|
|
139
|
+
trigger: { provider: "poll", every: "5m" },
|
|
140
|
+
execute: async ({ input }) => {
|
|
141
|
+
const seen = new Set(input.__poll?.seen);
|
|
142
|
+
const items = ["a", "b"].filter((id) => !seen.has(id));
|
|
143
|
+
return { cursor: input.__poll?.cursor ?? "start", handled: items };
|
|
144
|
+
},
|
|
145
|
+
});
|
|
146
|
+
await (0, vitest_1.expect)(endpoint.execute({
|
|
147
|
+
input: { __poll: { cursor: "c1", seen: ["a"] } },
|
|
148
|
+
context: { user: null },
|
|
149
|
+
})).resolves.toEqual({ cursor: "c1", handled: ["b"] });
|
|
150
|
+
});
|
|
151
|
+
(0, vitest_1.it)("gives __poll only to poll triggers", () => {
|
|
152
|
+
(0, index_js_1.createEndpoint)({
|
|
153
|
+
inputSchema: zod_1.z.object({ action: zod_1.z.string() }),
|
|
154
|
+
trigger: { integration: "github" },
|
|
155
|
+
execute: async ({ input }) => {
|
|
156
|
+
// @ts-expect-error a provider trigger's input has no __poll
|
|
157
|
+
return input.__poll;
|
|
158
|
+
},
|
|
159
|
+
});
|
|
160
|
+
});
|
|
161
|
+
(0, vitest_1.it)("hands a provider trigger's delivery its cursor and seen ids, typed", async () => {
|
|
162
|
+
const endpoint = (0, index_js_1.createEndpoint)({
|
|
163
|
+
inputSchema: zod_1.z.object({}),
|
|
164
|
+
trigger: { integration: "googleCalendar" },
|
|
165
|
+
execute: async ({ input }) => {
|
|
166
|
+
const seen = new Set(input.__webhook?.seen);
|
|
167
|
+
const changed = ["e1", "e2"].filter((id) => !seen.has(id));
|
|
168
|
+
return { cursor: `${input.__webhook?.cursor}+1`, handled: changed };
|
|
169
|
+
},
|
|
170
|
+
});
|
|
171
|
+
await (0, vitest_1.expect)(endpoint.execute({
|
|
172
|
+
input: {
|
|
173
|
+
__webhook: { headers: {}, cursor: "sync1", seen: ["e1"] },
|
|
174
|
+
},
|
|
175
|
+
context: { user: null },
|
|
176
|
+
})).resolves.toEqual({ cursor: "sync1+1", handled: ["e2"] });
|
|
177
|
+
});
|
|
136
178
|
(0, vitest_1.it)("does not validate a webhook fire", async () => {
|
|
137
179
|
const endpoint = (0, index_js_1.createEndpoint)({
|
|
138
180
|
inputSchema: zod_1.z.object({ token: zod_1.z.string().min(10) }),
|
|
@@ -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 an app's src/api/*.ts endpoints (an automation's single src/
|
|
5
|
+
* Reads an app's src/api/*.ts endpoints (an automation's single src/index.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
|
*
|
package/dist/cjs/bundle/index.js
CHANGED
|
@@ -40,7 +40,7 @@ exports.runBundle = runBundle;
|
|
|
40
40
|
* `npx zitejs bundle` — Bundle endpoint files for cloudflare-lambda deployment.
|
|
41
41
|
*
|
|
42
42
|
* Replaces the legacy `scripts/bundle-endpoints.js` from zitejs-starter.
|
|
43
|
-
* Reads an app's src/api/*.ts endpoints (an automation's single src/
|
|
43
|
+
* Reads an app's src/api/*.ts endpoints (an automation's single src/index.ts), resolves SDK imports via .zite/backend.ts
|
|
44
44
|
* (monorepo) or src/__zite__/integrations.ts (legacy), and outputs bundled ESM
|
|
45
45
|
* code suitable for the cloudflare-lambda worker runtime.
|
|
46
46
|
*
|
|
@@ -420,7 +420,7 @@ async function bundleEndpointsImpl(baseDir, root, endpointNames) {
|
|
|
420
420
|
for (const name of endpointNames) {
|
|
421
421
|
if (root === 'automations' && name !== sourceRoots_js_1.AUTOMATION_ENDPOINT_NAME) {
|
|
422
422
|
endpointErrors[name] =
|
|
423
|
-
`An automation is one workflow, src/
|
|
423
|
+
`An automation is one workflow, src/index.ts, bundled as "${sourceRoots_js_1.AUTOMATION_ENDPOINT_NAME}"; there is no endpoint "${name}"`;
|
|
424
424
|
continue;
|
|
425
425
|
}
|
|
426
426
|
const entryFile = (0, sourceRoots_js_1.endpointEntryFile)(root, name);
|
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 endpoints (src/api/*.ts, or an automation\'s src/
|
|
78
|
+
console.error(' bundle Bundle endpoints (src/api/*.ts, or an automation\'s src/index.ts) for cloudflare-lambda');
|
|
79
79
|
process.exit(1);
|
|
80
80
|
}
|
|
81
81
|
}
|
|
@@ -39,6 +39,7 @@ declare const FIELDS_BY_TYPE: {
|
|
|
39
39
|
typeform: readonly string[];
|
|
40
40
|
apollo: readonly string[];
|
|
41
41
|
attio: readonly string[];
|
|
42
|
+
granola: readonly string[];
|
|
42
43
|
};
|
|
43
44
|
/** A service type `integrations.get` serves: one used through its npm package with a token. */
|
|
44
45
|
export type CredentialServiceType = keyof typeof FIELDS_BY_TYPE;
|
|
@@ -48,6 +48,7 @@ const FIELDS_BY_TYPE = {
|
|
|
48
48
|
typeform: extras(),
|
|
49
49
|
apollo: extras(),
|
|
50
50
|
attio: extras(),
|
|
51
|
+
granola: extras(),
|
|
51
52
|
};
|
|
52
53
|
/** Per service type: `accessToken`, then its extra labels sorted (Salesforce `instanceUrl`). */
|
|
53
54
|
exports.CREDENTIAL_FIELDS = FIELDS_BY_TYPE;
|
|
@@ -17,6 +17,7 @@ const index_js_1 = require("../index.js");
|
|
|
17
17
|
"realmId",
|
|
18
18
|
]);
|
|
19
19
|
(0, vitest_1.expect)(index_js_1.CREDENTIAL_FIELDS.jira).toEqual(["accessToken", "cloudId", "siteUrl"]);
|
|
20
|
+
(0, vitest_1.expect)(index_js_1.CREDENTIAL_FIELDS.granola).toEqual(["accessToken"]);
|
|
20
21
|
});
|
|
21
22
|
(0, vitest_1.it)("has no type the runtime never serves", () => {
|
|
22
23
|
for (const type of index_js_1.NON_CREDENTIAL_SERVICE_TYPES) {
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export type ZiteProjectUser = {
|
|
2
|
+
uuid: string;
|
|
3
|
+
firstName: string | null;
|
|
4
|
+
lastName: string | null;
|
|
5
|
+
email: string;
|
|
6
|
+
profilePictureUrl: string | null;
|
|
7
|
+
};
|
|
8
|
+
export type MetaListUsersResult = {
|
|
9
|
+
users: ZiteProjectUser[];
|
|
10
|
+
};
|
|
11
|
+
export declare class ZiteMeta {
|
|
12
|
+
static listUsers(): Promise<MetaListUsersResult>;
|
|
13
|
+
}
|
|
14
|
+
export declare const Meta: typeof ZiteMeta;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.Meta = exports.ZiteMeta = void 0;
|
|
4
|
+
const sdkCall_js_1 = require("../internal/sdkCall.js");
|
|
5
|
+
const META_SDK_INTEGRATION_ID = '__meta__';
|
|
6
|
+
class ZiteMeta {
|
|
7
|
+
static listUsers() {
|
|
8
|
+
return (0, sdkCall_js_1.getSdkCall)()(META_SDK_INTEGRATION_ID, 'ZiteMeta', 'listUsers', {});
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
exports.ZiteMeta = ZiteMeta;
|
|
12
|
+
exports.Meta = ZiteMeta;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
export interface NotificationLink {
|
|
2
|
+
path?: string;
|
|
3
|
+
params?: Record<string, string>;
|
|
4
|
+
}
|
|
5
|
+
export type NotificationsCreateParams = {
|
|
6
|
+
recipients: string[];
|
|
7
|
+
title: string;
|
|
8
|
+
body?: string;
|
|
9
|
+
link?: NotificationLink;
|
|
10
|
+
path?: string;
|
|
11
|
+
params?: Record<string, string>;
|
|
12
|
+
payload?: Record<string, unknown>;
|
|
13
|
+
idempotencyKey?: string;
|
|
14
|
+
};
|
|
15
|
+
export type NotificationsCreateResult = {
|
|
16
|
+
created: number;
|
|
17
|
+
} | {
|
|
18
|
+
created: 0;
|
|
19
|
+
preview: true;
|
|
20
|
+
wouldCreate: number;
|
|
21
|
+
};
|
|
22
|
+
export declare class ZiteNotifications {
|
|
23
|
+
static create(params: NotificationsCreateParams): Promise<NotificationsCreateResult>;
|
|
24
|
+
}
|
|
25
|
+
export declare const Notifications: typeof ZiteNotifications;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.Notifications = exports.ZiteNotifications = void 0;
|
|
4
|
+
const sdkCall_js_1 = require("../internal/sdkCall.js");
|
|
5
|
+
const NOTIFICATIONS_SDK_INTEGRATION_ID = '__notifications__';
|
|
6
|
+
class ZiteNotifications {
|
|
7
|
+
static create(params) {
|
|
8
|
+
return (0, sdkCall_js_1.getSdkCall)()(NOTIFICATIONS_SDK_INTEGRATION_ID, 'ZiteNotifications', 'create', params);
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
exports.ZiteNotifications = ZiteNotifications;
|
|
12
|
+
exports.Notifications = ZiteNotifications;
|
|
@@ -18,12 +18,12 @@ export declare function listSourceDirs(cwd?: string): SourceDir[];
|
|
|
18
18
|
/** The source dir with this bare name, under whichever root holds it. */
|
|
19
19
|
export declare function findSourceDir(name: string, cwd?: string): SourceDir | undefined;
|
|
20
20
|
/**
|
|
21
|
-
* An automation is one workflow: its single endpoint is `src/
|
|
21
|
+
* An automation is one workflow: its single endpoint is `src/index.ts` and
|
|
22
22
|
* its name is fixed, so nothing about an automation is keyed on a file name
|
|
23
23
|
* the way an app's `src/api/<name>.ts` endpoints are.
|
|
24
24
|
*/
|
|
25
|
-
export declare const AUTOMATION_ENDPOINT_NAME = "
|
|
26
|
-
export declare const
|
|
25
|
+
export declare const AUTOMATION_ENDPOINT_NAME = "index";
|
|
26
|
+
export declare const AUTOMATION_ENTRY_FILE = "src/index.ts";
|
|
27
27
|
/** The root a source dir sits under, read from its parent directory. */
|
|
28
28
|
export declare function sourceRootOf(sourceDirPath: string): SourceRoot | undefined;
|
|
29
29
|
/** An endpoint's entry file, relative to the source dir. */
|
package/dist/cjs/sourceRoots.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
3
|
+
exports.AUTOMATION_ENTRY_FILE = exports.AUTOMATION_ENDPOINT_NAME = exports.SOURCE_ROOTS = void 0;
|
|
4
4
|
exports.listSourceDirs = listSourceDirs;
|
|
5
5
|
exports.findSourceDir = findSourceDir;
|
|
6
6
|
exports.sourceRootOf = sourceRootOf;
|
|
@@ -35,12 +35,12 @@ function findSourceDir(name, cwd = ".") {
|
|
|
35
35
|
return listSourceDirs(cwd).find((d) => d.dir === name);
|
|
36
36
|
}
|
|
37
37
|
/**
|
|
38
|
-
* An automation is one workflow: its single endpoint is `src/
|
|
38
|
+
* An automation is one workflow: its single endpoint is `src/index.ts` and
|
|
39
39
|
* its name is fixed, so nothing about an automation is keyed on a file name
|
|
40
40
|
* the way an app's `src/api/<name>.ts` endpoints are.
|
|
41
41
|
*/
|
|
42
|
-
exports.AUTOMATION_ENDPOINT_NAME = "
|
|
43
|
-
exports.
|
|
42
|
+
exports.AUTOMATION_ENDPOINT_NAME = "index";
|
|
43
|
+
exports.AUTOMATION_ENTRY_FILE = "src/index.ts";
|
|
44
44
|
/** The root a source dir sits under, read from its parent directory. */
|
|
45
45
|
function sourceRootOf(sourceDirPath) {
|
|
46
46
|
const parent = (0, path_1.basename)((0, path_1.dirname)((0, path_1.resolve)(sourceDirPath)));
|
|
@@ -51,13 +51,13 @@ function sourceRootOf(sourceDirPath) {
|
|
|
51
51
|
/** An endpoint's entry file, relative to the source dir. */
|
|
52
52
|
function endpointEntryFile(root, name) {
|
|
53
53
|
return root === "automations"
|
|
54
|
-
? exports.
|
|
54
|
+
? exports.AUTOMATION_ENTRY_FILE
|
|
55
55
|
: (0, path_1.join)("src", "api", `${name}.ts`);
|
|
56
56
|
}
|
|
57
57
|
/** Every endpoint name a source dir has on disk. */
|
|
58
58
|
function listEndpointNames(root, sourceDirPath) {
|
|
59
59
|
if (root === "automations") {
|
|
60
|
-
return (0, fs_1.existsSync)((0, path_1.join)(sourceDirPath, exports.
|
|
60
|
+
return (0, fs_1.existsSync)((0, path_1.join)(sourceDirPath, exports.AUTOMATION_ENTRY_FILE))
|
|
61
61
|
? [exports.AUTOMATION_ENDPOINT_NAME]
|
|
62
62
|
: [];
|
|
63
63
|
}
|
|
@@ -11,9 +11,9 @@ const sourceRoots_js_1 = require("./sourceRoots.js");
|
|
|
11
11
|
(0, vitest_1.expect)((0, sourceRoots_js_1.sourceRootOf)("/repo/automations/digest")).toBe("automations");
|
|
12
12
|
(0, vitest_1.expect)((0, sourceRoots_js_1.sourceRootOf)("/repo/packages/ui")).toBeUndefined();
|
|
13
13
|
});
|
|
14
|
-
(0, vitest_1.it)("an app's endpoints are src/api/<name>.ts; an automation's one endpoint is src/
|
|
14
|
+
(0, vitest_1.it)("an app's endpoints are src/api/<name>.ts; an automation's one endpoint is src/index.ts", () => {
|
|
15
15
|
(0, vitest_1.expect)((0, sourceRoots_js_1.endpointEntryFile)("apps", "listItems")).toBe("src/api/listItems.ts");
|
|
16
|
-
(0, vitest_1.expect)((0, sourceRoots_js_1.endpointEntryFile)("automations", "
|
|
16
|
+
(0, vitest_1.expect)((0, sourceRoots_js_1.endpointEntryFile)("automations", "index")).toBe("src/index.ts");
|
|
17
17
|
});
|
|
18
18
|
(0, vitest_1.it)("lists what is on disk under each layout", () => {
|
|
19
19
|
const repo = (0, fs_1.mkdtempSync)((0, path_1.join)((0, os_1.tmpdir)(), "zitejs-roots-"));
|
|
@@ -22,9 +22,9 @@ const sourceRoots_js_1 = require("./sourceRoots.js");
|
|
|
22
22
|
(0, fs_1.writeFileSync)((0, path_1.join)(repo, "apps/crm/src/api/apiTypes.d.ts"), "");
|
|
23
23
|
(0, fs_1.mkdirSync)((0, path_1.join)(repo, "automations/digest/src"), { recursive: true });
|
|
24
24
|
(0, fs_1.mkdirSync)((0, path_1.join)(repo, "automations/empty/src"), { recursive: true });
|
|
25
|
-
(0, fs_1.writeFileSync)((0, path_1.join)(repo, "automations/digest/src/
|
|
25
|
+
(0, fs_1.writeFileSync)((0, path_1.join)(repo, "automations/digest/src/index.ts"), "");
|
|
26
26
|
(0, vitest_1.expect)((0, sourceRoots_js_1.listEndpointNames)("apps", (0, path_1.join)(repo, "apps/crm"))).toEqual(["listItems"]);
|
|
27
|
-
(0, vitest_1.expect)((0, sourceRoots_js_1.listEndpointNames)("automations", (0, path_1.join)(repo, "automations/digest"))).toEqual(["
|
|
27
|
+
(0, vitest_1.expect)((0, sourceRoots_js_1.listEndpointNames)("automations", (0, path_1.join)(repo, "automations/digest"))).toEqual(["index"]);
|
|
28
28
|
(0, vitest_1.expect)((0, sourceRoots_js_1.listEndpointNames)("automations", (0, path_1.join)(repo, "automations/empty"))).toEqual([]);
|
|
29
29
|
});
|
|
30
30
|
});
|
package/dist/cjs/sync/lib.js
CHANGED
|
@@ -1426,7 +1426,7 @@ function generateIntegrationsIndex(entries, opts) {
|
|
|
1426
1426
|
"// Auto-generated by zitejs generate from zite.config.json. Do not edit manually.",
|
|
1427
1427
|
"// zitejs/integrations — an integration's credentials by its zite.config.json entry name.",
|
|
1428
1428
|
"//",
|
|
1429
|
-
"// Usage in endpoints (src/api/*.ts) and automations (src/
|
|
1429
|
+
"// Usage in endpoints (src/api/*.ts) and automations (src/index.ts):",
|
|
1430
1430
|
"// import { integrations } from 'zitejs/integrations';",
|
|
1431
1431
|
"//",
|
|
1432
1432
|
"// const crm = await integrations.get('<entry name>');",
|
|
@@ -465,7 +465,7 @@ const duplicateIdentifierErrorsIn = (source) => {
|
|
|
465
465
|
"// Auto-generated by zitejs generate from zite.config.json. Do not edit manually.
|
|
466
466
|
// zitejs/integrations — an integration's credentials by its zite.config.json entry name.
|
|
467
467
|
//
|
|
468
|
-
// Usage in endpoints (src/api/*.ts) and automations (src/
|
|
468
|
+
// Usage in endpoints (src/api/*.ts) and automations (src/index.ts):
|
|
469
469
|
// import { integrations } from 'zitejs/integrations';
|
|
470
470
|
//
|
|
471
471
|
// const crm = await integrations.get('<entry name>');
|
|
@@ -13,17 +13,59 @@ export type ZiteWebhook = {
|
|
|
13
13
|
export type ZiteTrigger = {
|
|
14
14
|
/**
|
|
15
15
|
* The connection's name in `zite.config.json`. Registered with the
|
|
16
|
-
* provider by `
|
|
17
|
-
* by `unsubscribe
|
|
16
|
+
* provider by the endpoint file's own `subscribe` export and taken down
|
|
17
|
+
* by its `unsubscribe` export, which the platform runs at publish and
|
|
18
|
+
* teardown.
|
|
18
19
|
*/
|
|
19
20
|
integration: string;
|
|
21
|
+
/** The sentence the editor shows for what fires this endpoint, e.g. "When a task is completed in Asana". */
|
|
22
|
+
label?: string;
|
|
20
23
|
paused?: boolean;
|
|
21
24
|
} | {
|
|
22
25
|
provider: "poll";
|
|
23
26
|
/** `<n>m` (1–59) or `<n>h` (1–23) */
|
|
24
27
|
every: string;
|
|
28
|
+
/** The sentence the editor shows for this poll, e.g. "Every 10 minutes, new Stripe charges". */
|
|
29
|
+
label?: string;
|
|
25
30
|
paused?: boolean;
|
|
26
31
|
};
|
|
32
|
+
/**
|
|
33
|
+
* What a poll-triggered run receives as `input.__poll`. Only on a fire from
|
|
34
|
+
* the poll's schedule; a request call to the same endpoint carries none.
|
|
35
|
+
*/
|
|
36
|
+
export type ZitePollInput = {
|
|
37
|
+
/** What the previous successful run returned as `cursor`; null on the first run. */
|
|
38
|
+
cursor: string | null;
|
|
39
|
+
/** Ids earlier runs returned as `handled`, newest last. Skip these. */
|
|
40
|
+
seen: string[];
|
|
41
|
+
};
|
|
42
|
+
/**
|
|
43
|
+
* What a provider trigger's delivery carries as `input.__webhook`, beside the
|
|
44
|
+
* provider's own body. `cursor` and `seen` work as they do for a poll: for a
|
|
45
|
+
* provider whose notification only says that something changed, `subscribe`
|
|
46
|
+
* returns a starting `cursor` and each delivery returns the next one. A
|
|
47
|
+
* trigger that keeps a cursor gets one delivery at a time.
|
|
48
|
+
*/
|
|
49
|
+
export type ZiteTriggerDelivery = {
|
|
50
|
+
headers: Record<string, string>;
|
|
51
|
+
/** The provider's id for this delivery; redeliveries share it. */
|
|
52
|
+
deliveryId?: string;
|
|
53
|
+
provider?: string;
|
|
54
|
+
/** What `subscribe` or the previous successful delivery returned as `cursor`. */
|
|
55
|
+
cursor: string | null;
|
|
56
|
+
/** Ids earlier deliveries returned as `handled`, newest last. Skip these. */
|
|
57
|
+
seen: string[];
|
|
58
|
+
};
|
|
59
|
+
/**
|
|
60
|
+
* What a poll-triggered run, or a provider trigger's delivery, returns for
|
|
61
|
+
* the platform to keep: its new `cursor`, and the id of every item it acted
|
|
62
|
+
* on, so the next run's `seen` includes them even if the cursor hands them
|
|
63
|
+
* back.
|
|
64
|
+
*/
|
|
65
|
+
export type ZitePollResult = {
|
|
66
|
+
cursor?: string;
|
|
67
|
+
handled?: string[];
|
|
68
|
+
};
|
|
27
69
|
export interface ZiteRequestContext {
|
|
28
70
|
user: {
|
|
29
71
|
id: string;
|
|
@@ -116,7 +158,15 @@ export interface EndpointConfig<TInput = unknown, TOutput = unknown, TStream ext
|
|
|
116
158
|
*/
|
|
117
159
|
validatesInput?: boolean;
|
|
118
160
|
execute: (params: {
|
|
119
|
-
input:
|
|
161
|
+
input: TTrigger extends {
|
|
162
|
+
provider: "poll";
|
|
163
|
+
} ? TInput & {
|
|
164
|
+
__poll?: ZitePollInput;
|
|
165
|
+
} : TTrigger extends {
|
|
166
|
+
integration: string;
|
|
167
|
+
} ? TInput & {
|
|
168
|
+
__webhook?: ZiteTriggerDelivery;
|
|
169
|
+
} : TInput;
|
|
120
170
|
context: TSchedule extends ZiteSchedule ? ZiteRequestContext | ZiteScheduledContext : TWebhook extends ZiteWebhook ? ZiteRequestContext | ZiteScheduledContext : TTrigger extends ZiteTrigger ? ZiteRequestContext | ZiteScheduledContext : ZiteRequestContext;
|
|
121
171
|
} & (TStream extends true ? {
|
|
122
172
|
stream: ZiteStreamInterface;
|
|
@@ -131,6 +131,48 @@ describe("platform-triggered runs", () => {
|
|
|
131
131
|
});
|
|
132
132
|
await expect(endpoint.execute({ input: undefined, context: requestContext })).rejects.toMatchObject({ code: "BAD_REQUEST" });
|
|
133
133
|
});
|
|
134
|
+
it("hands a poll its cursor and seen ids, typed", async () => {
|
|
135
|
+
const endpoint = createEndpoint({
|
|
136
|
+
inputSchema: z.object({}),
|
|
137
|
+
trigger: { provider: "poll", every: "5m" },
|
|
138
|
+
execute: async ({ input }) => {
|
|
139
|
+
const seen = new Set(input.__poll?.seen);
|
|
140
|
+
const items = ["a", "b"].filter((id) => !seen.has(id));
|
|
141
|
+
return { cursor: input.__poll?.cursor ?? "start", handled: items };
|
|
142
|
+
},
|
|
143
|
+
});
|
|
144
|
+
await expect(endpoint.execute({
|
|
145
|
+
input: { __poll: { cursor: "c1", seen: ["a"] } },
|
|
146
|
+
context: { user: null },
|
|
147
|
+
})).resolves.toEqual({ cursor: "c1", handled: ["b"] });
|
|
148
|
+
});
|
|
149
|
+
it("gives __poll only to poll triggers", () => {
|
|
150
|
+
createEndpoint({
|
|
151
|
+
inputSchema: z.object({ action: z.string() }),
|
|
152
|
+
trigger: { integration: "github" },
|
|
153
|
+
execute: async ({ input }) => {
|
|
154
|
+
// @ts-expect-error a provider trigger's input has no __poll
|
|
155
|
+
return input.__poll;
|
|
156
|
+
},
|
|
157
|
+
});
|
|
158
|
+
});
|
|
159
|
+
it("hands a provider trigger's delivery its cursor and seen ids, typed", async () => {
|
|
160
|
+
const endpoint = createEndpoint({
|
|
161
|
+
inputSchema: z.object({}),
|
|
162
|
+
trigger: { integration: "googleCalendar" },
|
|
163
|
+
execute: async ({ input }) => {
|
|
164
|
+
const seen = new Set(input.__webhook?.seen);
|
|
165
|
+
const changed = ["e1", "e2"].filter((id) => !seen.has(id));
|
|
166
|
+
return { cursor: `${input.__webhook?.cursor}+1`, handled: changed };
|
|
167
|
+
},
|
|
168
|
+
});
|
|
169
|
+
await expect(endpoint.execute({
|
|
170
|
+
input: {
|
|
171
|
+
__webhook: { headers: {}, cursor: "sync1", seen: ["e1"] },
|
|
172
|
+
},
|
|
173
|
+
context: { user: null },
|
|
174
|
+
})).resolves.toEqual({ cursor: "sync1+1", handled: ["e2"] });
|
|
175
|
+
});
|
|
134
176
|
it("does not validate a webhook fire", async () => {
|
|
135
177
|
const endpoint = createEndpoint({
|
|
136
178
|
inputSchema: z.object({ token: z.string().min(10) }),
|
|
@@ -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 an app's src/api/*.ts endpoints (an automation's single src/
|
|
5
|
+
* Reads an app's src/api/*.ts endpoints (an automation's single src/index.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
|
*
|
package/dist/esm/bundle/index.js
CHANGED
|
@@ -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 an app's src/api/*.ts endpoints (an automation's single src/
|
|
5
|
+
* Reads an app's src/api/*.ts endpoints (an automation's single src/index.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
|
*
|
|
@@ -382,7 +382,7 @@ async function bundleEndpointsImpl(baseDir, root, endpointNames) {
|
|
|
382
382
|
for (const name of endpointNames) {
|
|
383
383
|
if (root === 'automations' && name !== AUTOMATION_ENDPOINT_NAME) {
|
|
384
384
|
endpointErrors[name] =
|
|
385
|
-
`An automation is one workflow, src/
|
|
385
|
+
`An automation is one workflow, src/index.ts, bundled as "${AUTOMATION_ENDPOINT_NAME}"; there is no endpoint "${name}"`;
|
|
386
386
|
continue;
|
|
387
387
|
}
|
|
388
388
|
const entryFile = endpointEntryFile(root, name);
|
package/dist/esm/cli.js
CHANGED
|
@@ -40,7 +40,7 @@ async function main() {
|
|
|
40
40
|
console.error(' dev Run sync then watch for changes (like npx convex dev)');
|
|
41
41
|
console.error(' generate Regenerate every app and automation .zite/ (monorepo)');
|
|
42
42
|
console.error(' check Run tsc --noEmit (and vite build where there is one) for every app and automation');
|
|
43
|
-
console.error(' bundle Bundle endpoints (src/api/*.ts, or an automation\'s src/
|
|
43
|
+
console.error(' bundle Bundle endpoints (src/api/*.ts, or an automation\'s src/index.ts) for cloudflare-lambda');
|
|
44
44
|
process.exit(1);
|
|
45
45
|
}
|
|
46
46
|
}
|
|
@@ -39,6 +39,7 @@ declare const FIELDS_BY_TYPE: {
|
|
|
39
39
|
typeform: readonly string[];
|
|
40
40
|
apollo: readonly string[];
|
|
41
41
|
attio: readonly string[];
|
|
42
|
+
granola: readonly string[];
|
|
42
43
|
};
|
|
43
44
|
/** A service type `integrations.get` serves: one used through its npm package with a token. */
|
|
44
45
|
export type CredentialServiceType = keyof typeof FIELDS_BY_TYPE;
|
|
@@ -45,6 +45,7 @@ const FIELDS_BY_TYPE = {
|
|
|
45
45
|
typeform: extras(),
|
|
46
46
|
apollo: extras(),
|
|
47
47
|
attio: extras(),
|
|
48
|
+
granola: extras(),
|
|
48
49
|
};
|
|
49
50
|
/** Per service type: `accessToken`, then its extra labels sorted (Salesforce `instanceUrl`). */
|
|
50
51
|
export const CREDENTIAL_FIELDS = FIELDS_BY_TYPE;
|
|
@@ -15,6 +15,7 @@ describe("CREDENTIAL_FIELDS", () => {
|
|
|
15
15
|
"realmId",
|
|
16
16
|
]);
|
|
17
17
|
expect(CREDENTIAL_FIELDS.jira).toEqual(["accessToken", "cloudId", "siteUrl"]);
|
|
18
|
+
expect(CREDENTIAL_FIELDS.granola).toEqual(["accessToken"]);
|
|
18
19
|
});
|
|
19
20
|
it("has no type the runtime never serves", () => {
|
|
20
21
|
for (const type of NON_CREDENTIAL_SERVICE_TYPES) {
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export type ZiteProjectUser = {
|
|
2
|
+
uuid: string;
|
|
3
|
+
firstName: string | null;
|
|
4
|
+
lastName: string | null;
|
|
5
|
+
email: string;
|
|
6
|
+
profilePictureUrl: string | null;
|
|
7
|
+
};
|
|
8
|
+
export type MetaListUsersResult = {
|
|
9
|
+
users: ZiteProjectUser[];
|
|
10
|
+
};
|
|
11
|
+
export declare class ZiteMeta {
|
|
12
|
+
static listUsers(): Promise<MetaListUsersResult>;
|
|
13
|
+
}
|
|
14
|
+
export declare const Meta: typeof ZiteMeta;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
export interface NotificationLink {
|
|
2
|
+
path?: string;
|
|
3
|
+
params?: Record<string, string>;
|
|
4
|
+
}
|
|
5
|
+
export type NotificationsCreateParams = {
|
|
6
|
+
recipients: string[];
|
|
7
|
+
title: string;
|
|
8
|
+
body?: string;
|
|
9
|
+
link?: NotificationLink;
|
|
10
|
+
path?: string;
|
|
11
|
+
params?: Record<string, string>;
|
|
12
|
+
payload?: Record<string, unknown>;
|
|
13
|
+
idempotencyKey?: string;
|
|
14
|
+
};
|
|
15
|
+
export type NotificationsCreateResult = {
|
|
16
|
+
created: number;
|
|
17
|
+
} | {
|
|
18
|
+
created: 0;
|
|
19
|
+
preview: true;
|
|
20
|
+
wouldCreate: number;
|
|
21
|
+
};
|
|
22
|
+
export declare class ZiteNotifications {
|
|
23
|
+
static create(params: NotificationsCreateParams): Promise<NotificationsCreateResult>;
|
|
24
|
+
}
|
|
25
|
+
export declare const Notifications: typeof ZiteNotifications;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { getSdkCall } from '../internal/sdkCall.js';
|
|
2
|
+
const NOTIFICATIONS_SDK_INTEGRATION_ID = '__notifications__';
|
|
3
|
+
export class ZiteNotifications {
|
|
4
|
+
static create(params) {
|
|
5
|
+
return getSdkCall()(NOTIFICATIONS_SDK_INTEGRATION_ID, 'ZiteNotifications', 'create', params);
|
|
6
|
+
}
|
|
7
|
+
}
|
|
8
|
+
export const Notifications = ZiteNotifications;
|
|
@@ -18,12 +18,12 @@ export declare function listSourceDirs(cwd?: string): SourceDir[];
|
|
|
18
18
|
/** The source dir with this bare name, under whichever root holds it. */
|
|
19
19
|
export declare function findSourceDir(name: string, cwd?: string): SourceDir | undefined;
|
|
20
20
|
/**
|
|
21
|
-
* An automation is one workflow: its single endpoint is `src/
|
|
21
|
+
* An automation is one workflow: its single endpoint is `src/index.ts` and
|
|
22
22
|
* its name is fixed, so nothing about an automation is keyed on a file name
|
|
23
23
|
* the way an app's `src/api/<name>.ts` endpoints are.
|
|
24
24
|
*/
|
|
25
|
-
export declare const AUTOMATION_ENDPOINT_NAME = "
|
|
26
|
-
export declare const
|
|
25
|
+
export declare const AUTOMATION_ENDPOINT_NAME = "index";
|
|
26
|
+
export declare const AUTOMATION_ENTRY_FILE = "src/index.ts";
|
|
27
27
|
/** The root a source dir sits under, read from its parent directory. */
|
|
28
28
|
export declare function sourceRootOf(sourceDirPath: string): SourceRoot | undefined;
|
|
29
29
|
/** An endpoint's entry file, relative to the source dir. */
|
package/dist/esm/sourceRoots.js
CHANGED
|
@@ -27,12 +27,12 @@ export function findSourceDir(name, cwd = ".") {
|
|
|
27
27
|
return listSourceDirs(cwd).find((d) => d.dir === name);
|
|
28
28
|
}
|
|
29
29
|
/**
|
|
30
|
-
* An automation is one workflow: its single endpoint is `src/
|
|
30
|
+
* An automation is one workflow: its single endpoint is `src/index.ts` and
|
|
31
31
|
* its name is fixed, so nothing about an automation is keyed on a file name
|
|
32
32
|
* the way an app's `src/api/<name>.ts` endpoints are.
|
|
33
33
|
*/
|
|
34
|
-
export const AUTOMATION_ENDPOINT_NAME = "
|
|
35
|
-
export const
|
|
34
|
+
export const AUTOMATION_ENDPOINT_NAME = "index";
|
|
35
|
+
export const AUTOMATION_ENTRY_FILE = "src/index.ts";
|
|
36
36
|
/** The root a source dir sits under, read from its parent directory. */
|
|
37
37
|
export function sourceRootOf(sourceDirPath) {
|
|
38
38
|
const parent = basename(dirname(resolve(sourceDirPath)));
|
|
@@ -43,13 +43,13 @@ export function sourceRootOf(sourceDirPath) {
|
|
|
43
43
|
/** An endpoint's entry file, relative to the source dir. */
|
|
44
44
|
export function endpointEntryFile(root, name) {
|
|
45
45
|
return root === "automations"
|
|
46
|
-
?
|
|
46
|
+
? AUTOMATION_ENTRY_FILE
|
|
47
47
|
: join("src", "api", `${name}.ts`);
|
|
48
48
|
}
|
|
49
49
|
/** Every endpoint name a source dir has on disk. */
|
|
50
50
|
export function listEndpointNames(root, sourceDirPath) {
|
|
51
51
|
if (root === "automations") {
|
|
52
|
-
return existsSync(join(sourceDirPath,
|
|
52
|
+
return existsSync(join(sourceDirPath, AUTOMATION_ENTRY_FILE))
|
|
53
53
|
? [AUTOMATION_ENDPOINT_NAME]
|
|
54
54
|
: [];
|
|
55
55
|
}
|
|
@@ -9,9 +9,9 @@ describe("source roots", () => {
|
|
|
9
9
|
expect(sourceRootOf("/repo/automations/digest")).toBe("automations");
|
|
10
10
|
expect(sourceRootOf("/repo/packages/ui")).toBeUndefined();
|
|
11
11
|
});
|
|
12
|
-
it("an app's endpoints are src/api/<name>.ts; an automation's one endpoint is src/
|
|
12
|
+
it("an app's endpoints are src/api/<name>.ts; an automation's one endpoint is src/index.ts", () => {
|
|
13
13
|
expect(endpointEntryFile("apps", "listItems")).toBe("src/api/listItems.ts");
|
|
14
|
-
expect(endpointEntryFile("automations", "
|
|
14
|
+
expect(endpointEntryFile("automations", "index")).toBe("src/index.ts");
|
|
15
15
|
});
|
|
16
16
|
it("lists what is on disk under each layout", () => {
|
|
17
17
|
const repo = mkdtempSync(join(tmpdir(), "zitejs-roots-"));
|
|
@@ -20,9 +20,9 @@ describe("source roots", () => {
|
|
|
20
20
|
writeFileSync(join(repo, "apps/crm/src/api/apiTypes.d.ts"), "");
|
|
21
21
|
mkdirSync(join(repo, "automations/digest/src"), { recursive: true });
|
|
22
22
|
mkdirSync(join(repo, "automations/empty/src"), { recursive: true });
|
|
23
|
-
writeFileSync(join(repo, "automations/digest/src/
|
|
23
|
+
writeFileSync(join(repo, "automations/digest/src/index.ts"), "");
|
|
24
24
|
expect(listEndpointNames("apps", join(repo, "apps/crm"))).toEqual(["listItems"]);
|
|
25
|
-
expect(listEndpointNames("automations", join(repo, "automations/digest"))).toEqual(["
|
|
25
|
+
expect(listEndpointNames("automations", join(repo, "automations/digest"))).toEqual(["index"]);
|
|
26
26
|
expect(listEndpointNames("automations", join(repo, "automations/empty"))).toEqual([]);
|
|
27
27
|
});
|
|
28
28
|
});
|
package/dist/esm/sync/lib.js
CHANGED
|
@@ -1411,7 +1411,7 @@ export function generateIntegrationsIndex(entries, opts) {
|
|
|
1411
1411
|
"// Auto-generated by zitejs generate from zite.config.json. Do not edit manually.",
|
|
1412
1412
|
"// zitejs/integrations — an integration's credentials by its zite.config.json entry name.",
|
|
1413
1413
|
"//",
|
|
1414
|
-
"// Usage in endpoints (src/api/*.ts) and automations (src/
|
|
1414
|
+
"// Usage in endpoints (src/api/*.ts) and automations (src/index.ts):",
|
|
1415
1415
|
"// import { integrations } from 'zitejs/integrations';",
|
|
1416
1416
|
"//",
|
|
1417
1417
|
"// const crm = await integrations.get('<entry name>');",
|
|
@@ -460,7 +460,7 @@ describe('generateIntegrationsIndex', () => {
|
|
|
460
460
|
"// Auto-generated by zitejs generate from zite.config.json. Do not edit manually.
|
|
461
461
|
// zitejs/integrations — an integration's credentials by its zite.config.json entry name.
|
|
462
462
|
//
|
|
463
|
-
// Usage in endpoints (src/api/*.ts) and automations (src/
|
|
463
|
+
// Usage in endpoints (src/api/*.ts) and automations (src/index.ts):
|
|
464
464
|
// import { integrations } from 'zitejs/integrations';
|
|
465
465
|
//
|
|
466
466
|
// const crm = await integrations.get('<entry name>');
|