zitejs 0.9.126 → 0.9.127

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.
@@ -21,14 +21,55 @@ export type ZiteTrigger = {
21
21
  /** The sentence the editor shows for what fires this endpoint, e.g. "When a task is completed in Asana". */
22
22
  label?: string;
23
23
  paused?: boolean;
24
+ every?: never;
24
25
  } | {
25
- provider: "poll";
26
- /** `<n>m` (1–59) or `<n>h` (1–23) */
26
+ /** `<n>m` (1–59) or `<n>h` (1–23). What makes the trigger a poll. */
27
27
  every: string;
28
+ /** The connection the poll checks, if any, so the editor can name it. */
29
+ integration?: string;
28
30
  /** The sentence the editor shows for this poll, e.g. "Every 10 minutes, new Stripe charges". */
29
31
  label?: string;
30
32
  paused?: boolean;
31
33
  };
34
+ /**
35
+ * What a provider trigger's `subscribe` export receives. Write it as
36
+ * `export const subscribe = (async input => { ... }) satisfies ZiteTriggerSubscribe`
37
+ * so the input is typed and a wrong return shape is a typecheck error.
38
+ */
39
+ export type ZiteTriggerSubscribeInput = {
40
+ /** Where the provider must deliver, token included. */
41
+ notificationUrl: string;
42
+ /** The connection's name, as the trigger names it. */
43
+ integration: string;
44
+ endpointId: string;
45
+ /** A fresh 64-char hex secret, for providers that let the caller choose the signing secret. */
46
+ secret: string;
47
+ /** Set on a re-subscribe, including a renewal. */
48
+ previous: {
49
+ externalId: string;
50
+ state: Record<string, unknown>;
51
+ } | null;
52
+ };
53
+ export type ZiteTriggerSubscribeResult = {
54
+ /** The provider's id for the registration; what `unsubscribe` receives. */
55
+ externalId: string;
56
+ /** The signing secret, if the provider issued one or accepted `input.secret`. */
57
+ secret?: string;
58
+ /** Anything `unsubscribe` needs later; handed back to it and to the next `subscribe`. */
59
+ state?: Record<string, unknown>;
60
+ /** The provider's starting change marker, for notifications that only say something changed. */
61
+ cursor?: string;
62
+ /** ISO time the provider says the registration lapses, read from its response. */
63
+ expiresAt?: string;
64
+ };
65
+ export type ZiteTriggerUnsubscribeInput = {
66
+ externalId: string;
67
+ state: Record<string, unknown>;
68
+ integration: string;
69
+ endpointId: string;
70
+ };
71
+ export type ZiteTriggerSubscribe = (input: ZiteTriggerSubscribeInput) => Promise<ZiteTriggerSubscribeResult> | ZiteTriggerSubscribeResult;
72
+ export type ZiteTriggerUnsubscribe = (input: ZiteTriggerUnsubscribeInput) => Promise<void> | void;
32
73
  /**
33
74
  * What a poll-triggered run receives as `input.__poll`. Only on a fire from
34
75
  * the poll's schedule; a request call to the same endpoint carries none.
@@ -159,7 +200,7 @@ export interface EndpointConfig<TInput = unknown, TOutput = unknown, TStream ext
159
200
  validatesInput?: boolean;
160
201
  execute: (params: {
161
202
  input: TTrigger extends {
162
- provider: "poll";
203
+ every: string;
163
204
  } ? TInput & {
164
205
  __poll?: ZitePollInput;
165
206
  } : TTrigger extends {
@@ -136,7 +136,7 @@ const requestContext = { user: { id: "u1", email: "a@b.c" } };
136
136
  (0, vitest_1.it)("hands a poll its cursor and seen ids, typed", async () => {
137
137
  const endpoint = (0, index_js_1.createEndpoint)({
138
138
  inputSchema: zod_1.z.object({}),
139
- trigger: { provider: "poll", every: "5m" },
139
+ trigger: { every: "5m", integration: "stripe" },
140
140
  execute: async ({ input }) => {
141
141
  const seen = new Set(input.__poll?.seen);
142
142
  const items = ["a", "b"].filter((id) => !seen.has(id));
@@ -158,6 +158,32 @@ const requestContext = { user: { id: "u1", email: "a@b.c" } };
158
158
  },
159
159
  });
160
160
  });
161
+ (0, vitest_1.it)("types a trigger's registration exports and checks what subscribe returns", async () => {
162
+ const subscribe = (async (input) => ({
163
+ externalId: `hook-for-${input.endpointId}`,
164
+ secret: input.secret,
165
+ state: { repo: "acme/api" },
166
+ }));
167
+ const unsubscribe = (async (input) => {
168
+ (0, vitest_1.expect)(input.state.repo).toBe("acme/api");
169
+ });
170
+ // @ts-expect-error subscribe has to return the provider's id
171
+ void (async () => ({ secret: "s" }));
172
+ const registered = await subscribe({
173
+ notificationUrl: "https://x",
174
+ integration: "github",
175
+ endpointId: "onPush",
176
+ secret: "abc",
177
+ previous: null,
178
+ });
179
+ (0, vitest_1.expect)(registered.externalId).toBe("hook-for-onPush");
180
+ await unsubscribe({
181
+ externalId: registered.externalId,
182
+ state: registered.state ?? {},
183
+ integration: "github",
184
+ endpointId: "onPush",
185
+ });
186
+ });
161
187
  (0, vitest_1.it)("hands a provider trigger's delivery its cursor and seen ids, typed", async () => {
162
188
  const endpoint = (0, index_js_1.createEndpoint)({
163
189
  inputSchema: zod_1.z.object({}),
@@ -592,6 +592,10 @@ ${bodySection}
592
592
  },
593
593
  minify: false,
594
594
  logLevel: 'silent',
595
+ // A script that imports an endpoint file's named exports (a trigger's
596
+ // subscribe/unsubscribe) must not carry the endpoint along with them:
597
+ // unused, its `createEndpoint(...)` and everything `execute` imports go.
598
+ pure: ['createEndpoint'],
595
599
  plugins: [plugin],
596
600
  });
597
601
  if (result.errors.length > 0) {
@@ -21,14 +21,55 @@ export type ZiteTrigger = {
21
21
  /** The sentence the editor shows for what fires this endpoint, e.g. "When a task is completed in Asana". */
22
22
  label?: string;
23
23
  paused?: boolean;
24
+ every?: never;
24
25
  } | {
25
- provider: "poll";
26
- /** `<n>m` (1–59) or `<n>h` (1–23) */
26
+ /** `<n>m` (1–59) or `<n>h` (1–23). What makes the trigger a poll. */
27
27
  every: string;
28
+ /** The connection the poll checks, if any, so the editor can name it. */
29
+ integration?: string;
28
30
  /** The sentence the editor shows for this poll, e.g. "Every 10 minutes, new Stripe charges". */
29
31
  label?: string;
30
32
  paused?: boolean;
31
33
  };
34
+ /**
35
+ * What a provider trigger's `subscribe` export receives. Write it as
36
+ * `export const subscribe = (async input => { ... }) satisfies ZiteTriggerSubscribe`
37
+ * so the input is typed and a wrong return shape is a typecheck error.
38
+ */
39
+ export type ZiteTriggerSubscribeInput = {
40
+ /** Where the provider must deliver, token included. */
41
+ notificationUrl: string;
42
+ /** The connection's name, as the trigger names it. */
43
+ integration: string;
44
+ endpointId: string;
45
+ /** A fresh 64-char hex secret, for providers that let the caller choose the signing secret. */
46
+ secret: string;
47
+ /** Set on a re-subscribe, including a renewal. */
48
+ previous: {
49
+ externalId: string;
50
+ state: Record<string, unknown>;
51
+ } | null;
52
+ };
53
+ export type ZiteTriggerSubscribeResult = {
54
+ /** The provider's id for the registration; what `unsubscribe` receives. */
55
+ externalId: string;
56
+ /** The signing secret, if the provider issued one or accepted `input.secret`. */
57
+ secret?: string;
58
+ /** Anything `unsubscribe` needs later; handed back to it and to the next `subscribe`. */
59
+ state?: Record<string, unknown>;
60
+ /** The provider's starting change marker, for notifications that only say something changed. */
61
+ cursor?: string;
62
+ /** ISO time the provider says the registration lapses, read from its response. */
63
+ expiresAt?: string;
64
+ };
65
+ export type ZiteTriggerUnsubscribeInput = {
66
+ externalId: string;
67
+ state: Record<string, unknown>;
68
+ integration: string;
69
+ endpointId: string;
70
+ };
71
+ export type ZiteTriggerSubscribe = (input: ZiteTriggerSubscribeInput) => Promise<ZiteTriggerSubscribeResult> | ZiteTriggerSubscribeResult;
72
+ export type ZiteTriggerUnsubscribe = (input: ZiteTriggerUnsubscribeInput) => Promise<void> | void;
32
73
  /**
33
74
  * What a poll-triggered run receives as `input.__poll`. Only on a fire from
34
75
  * the poll's schedule; a request call to the same endpoint carries none.
@@ -159,7 +200,7 @@ export interface EndpointConfig<TInput = unknown, TOutput = unknown, TStream ext
159
200
  validatesInput?: boolean;
160
201
  execute: (params: {
161
202
  input: TTrigger extends {
162
- provider: "poll";
203
+ every: string;
163
204
  } ? TInput & {
164
205
  __poll?: ZitePollInput;
165
206
  } : TTrigger extends {
@@ -1,6 +1,6 @@
1
1
  import { describe, it, expect, afterEach, vi } from "vitest";
2
2
  import { z } from "zod";
3
- import { createEndpoint, ZiteError } from "./index.js";
3
+ import { createEndpoint, ZiteError, } from "./index.js";
4
4
  import { createTableClient } from "../runtime/index.js";
5
5
  const requestContext = { user: { id: "u1", email: "a@b.c" } };
6
6
  afterEach(() => {
@@ -134,7 +134,7 @@ describe("platform-triggered runs", () => {
134
134
  it("hands a poll its cursor and seen ids, typed", async () => {
135
135
  const endpoint = createEndpoint({
136
136
  inputSchema: z.object({}),
137
- trigger: { provider: "poll", every: "5m" },
137
+ trigger: { every: "5m", integration: "stripe" },
138
138
  execute: async ({ input }) => {
139
139
  const seen = new Set(input.__poll?.seen);
140
140
  const items = ["a", "b"].filter((id) => !seen.has(id));
@@ -156,6 +156,32 @@ describe("platform-triggered runs", () => {
156
156
  },
157
157
  });
158
158
  });
159
+ it("types a trigger's registration exports and checks what subscribe returns", async () => {
160
+ const subscribe = (async (input) => ({
161
+ externalId: `hook-for-${input.endpointId}`,
162
+ secret: input.secret,
163
+ state: { repo: "acme/api" },
164
+ }));
165
+ const unsubscribe = (async (input) => {
166
+ expect(input.state.repo).toBe("acme/api");
167
+ });
168
+ // @ts-expect-error subscribe has to return the provider's id
169
+ void (async () => ({ secret: "s" }));
170
+ const registered = await subscribe({
171
+ notificationUrl: "https://x",
172
+ integration: "github",
173
+ endpointId: "onPush",
174
+ secret: "abc",
175
+ previous: null,
176
+ });
177
+ expect(registered.externalId).toBe("hook-for-onPush");
178
+ await unsubscribe({
179
+ externalId: registered.externalId,
180
+ state: registered.state ?? {},
181
+ integration: "github",
182
+ endpointId: "onPush",
183
+ });
184
+ });
159
185
  it("hands a provider trigger's delivery its cursor and seen ids, typed", async () => {
160
186
  const endpoint = createEndpoint({
161
187
  inputSchema: z.object({}),
@@ -554,6 +554,10 @@ ${bodySection}
554
554
  },
555
555
  minify: false,
556
556
  logLevel: 'silent',
557
+ // A script that imports an endpoint file's named exports (a trigger's
558
+ // subscribe/unsubscribe) must not carry the endpoint along with them:
559
+ // unused, its `createEndpoint(...)` and everything `execute` imports go.
560
+ pure: ['createEndpoint'],
557
561
  plugins: [plugin],
558
562
  });
559
563
  if (result.errors.length > 0) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "zitejs",
3
- "version": "0.9.126",
3
+ "version": "0.9.127",
4
4
  "description": "The Zite framework — build apps on Zite Database",
5
5
  "type": "module",
6
6
  "sideEffects": false,