zitejs 0.10.0-start.1 → 0.10.0-start.12
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/auth/index.d.ts +2 -2
- package/dist/cjs/auth/index.test.js +30 -0
- package/dist/cjs/backend/index.d.ts +115 -3
- package/dist/cjs/backend/index.test.js +58 -0
- package/dist/cjs/check/index.d.ts +33 -1
- package/dist/cjs/check/index.js +187 -59
- package/dist/cjs/check/start/describeRules.d.ts +35 -0
- package/dist/cjs/check/start/describeRules.js +89 -0
- package/dist/cjs/check/start/problem.d.ts +11 -0
- package/dist/cjs/check/start/problem.js +5 -0
- package/dist/cjs/check/start/sourceRules.d.ts +3 -0
- package/dist/cjs/check/start/sourceRules.js +441 -0
- package/dist/cjs/cli.js +1 -1
- package/dist/cjs/integrations/rules.d.ts +13 -0
- package/dist/cjs/integrations/rules.js +29 -0
- package/dist/cjs/integrations/rules.test.js +1 -0
- package/dist/cjs/start/entries.d.ts +11 -2
- package/dist/cjs/start/entries.js +48 -6
- package/dist/cjs/start/problems.d.ts +19 -0
- package/dist/cjs/start/problems.js +11 -0
- package/dist/cjs/sync/lib.js +10 -13
- package/dist/cjs/vite/index.js +8 -3
- package/dist/cjs/vite/index.test.js +10 -2
- package/dist/esm/auth/index.d.ts +2 -2
- package/dist/esm/auth/index.test.js +30 -0
- package/dist/esm/backend/index.d.ts +115 -3
- package/dist/esm/backend/index.test.js +58 -0
- package/dist/esm/check/index.d.ts +33 -1
- package/dist/esm/check/index.js +153 -61
- package/dist/esm/check/start/describeRules.d.ts +35 -0
- package/dist/esm/check/start/describeRules.js +86 -0
- package/dist/esm/check/start/problem.d.ts +11 -0
- package/dist/esm/check/start/problem.js +1 -0
- package/dist/esm/check/start/sourceRules.d.ts +3 -0
- package/dist/esm/check/start/sourceRules.js +438 -0
- package/dist/esm/cli.js +1 -1
- package/dist/esm/integrations/rules.d.ts +13 -0
- package/dist/esm/integrations/rules.js +29 -0
- package/dist/esm/integrations/rules.test.js +1 -0
- package/dist/esm/start/airtable/arrayFields.d.ts +10 -0
- package/dist/esm/start/airtable/arrayFields.js +30 -0
- package/dist/esm/start/airtable/dispatch.d.ts +54 -0
- package/dist/esm/start/airtable/dispatch.js +465 -0
- package/dist/esm/start/airtable/formulas.d.ts +69 -0
- package/dist/esm/start/airtable/formulas.js +235 -0
- package/dist/esm/start/airtable/index.d.ts +11 -0
- package/dist/esm/start/airtable/index.js +70 -0
- package/dist/esm/start/authHooks.d.ts +7 -0
- package/dist/esm/start/authHooks.js +10 -0
- package/dist/esm/start/authHooksModule.d.ts +1 -0
- package/dist/esm/start/authHooksModule.js +3 -0
- package/dist/esm/start/clientErrorMessage.test.d.ts +1 -0
- package/dist/esm/start/clientErrorMessage.test.js +105 -0
- package/dist/esm/start/data/baseRunner.d.ts +92 -0
- package/dist/esm/start/data/baseRunner.js +83 -0
- package/dist/esm/start/data/dispatch.d.ts +16 -0
- package/dist/esm/start/data/dispatch.js +198 -0
- package/dist/esm/start/data/index.d.ts +18 -0
- package/dist/esm/start/data/index.js +76 -0
- package/dist/esm/start/data/sqlNameMappings.d.ts +58 -0
- package/dist/esm/start/data/sqlNameMappings.js +92 -0
- package/dist/esm/start/data/transformations.d.ts +128 -0
- package/dist/esm/start/data/transformations.js +318 -0
- package/dist/esm/start/data/types.d.ts +91 -0
- package/dist/esm/start/data/types.js +14 -0
- package/dist/esm/start/describe.d.ts +46 -1
- package/dist/esm/start/describe.js +91 -9
- package/dist/esm/start/descriptions.d.ts +4 -0
- package/dist/esm/start/descriptions.js +47 -0
- package/dist/esm/start/entries.d.ts +11 -2
- package/dist/esm/start/entries.js +46 -7
- package/dist/esm/start/errors.d.ts +51 -0
- package/dist/esm/start/errors.js +104 -0
- package/dist/esm/start/errors.test.d.ts +1 -0
- package/dist/esm/start/errors.test.js +23 -0
- package/dist/esm/start/factories.test-d.d.ts +1 -0
- package/dist/esm/start/factories.test-d.js +20 -0
- package/dist/esm/start/index.d.ts +24 -22
- package/dist/esm/start/index.js +61 -38
- package/dist/esm/start/instance.d.ts +3 -3
- package/dist/esm/start/instance.js +22 -22
- package/dist/esm/start/previewClaim.d.ts +10 -0
- package/dist/esm/start/previewClaim.js +32 -0
- package/dist/esm/start/problems.d.ts +19 -0
- package/dist/esm/start/problems.js +8 -0
- package/dist/esm/start/quiet.d.ts +2 -0
- package/dist/esm/start/quiet.js +27 -0
- package/dist/esm/start/redactSecrets.d.ts +7 -0
- package/dist/esm/start/redactSecrets.js +131 -0
- package/dist/esm/start/redactSecrets.test.d.ts +1 -0
- package/dist/esm/start/redactSecrets.test.js +151 -0
- package/dist/esm/start/registration.d.ts +13 -0
- package/dist/esm/start/registration.js +21 -0
- package/dist/esm/start/router.d.ts +12 -3
- package/dist/esm/start/router.js +86 -7
- package/dist/esm/start/runLog.d.ts +8 -0
- package/dist/esm/start/runLog.js +76 -0
- package/dist/esm/start/scope.d.ts +2 -2
- package/dist/esm/start/server.d.ts +47 -35
- package/dist/esm/start/server.js +320 -42
- package/dist/esm/start/steps.d.ts +28 -0
- package/dist/esm/start/steps.js +97 -0
- package/dist/esm/start/types.d.ts +145 -5
- package/dist/esm/start/version.d.ts +1 -0
- package/dist/esm/start/version.js +2 -0
- package/dist/esm/start/vite.js +67 -8
- package/dist/esm/start/worker.d.ts +11 -0
- package/dist/esm/start/worker.js +20 -0
- package/dist/esm/start/workflow.d.ts +59 -0
- package/dist/esm/start/workflow.js +13 -0
- package/dist/esm/start/workflow.test-d.d.ts +1 -0
- package/dist/esm/start/workflow.test-d.js +50 -0
- package/dist/esm/start/workflowModules.d.ts +1 -0
- package/dist/esm/start/workflowModules.js +3 -0
- package/dist/esm/start/workflowRun.d.ts +93 -0
- package/dist/esm/start/workflowRun.js +128 -0
- package/dist/esm/sync/lib.js +10 -13
- package/dist/esm/vite/index.js +8 -3
- package/dist/esm/vite/index.test.js +10 -2
- package/package.json +21 -8
package/dist/cjs/auth/index.d.ts
CHANGED
|
@@ -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: "salesforce" | "slack" | "linear" | "notion" | "linkedin" | "github" | "dropbox" | (string & {}) | "huggingface" | "apple" | "atlassian" | "cognito" | "discord" | "facebook" | "figma" | "microsoft" | "google" | "spotify" | "twitch" | "twitter" | "kick" | "gitlab" | "tiktok" | "reddit" | "roblox" | "vk" | "zoom" | "kakao" | "naver" | "
|
|
70
|
+
provider: "salesforce" | "slack" | "linear" | "notion" | "linkedin" | "github" | "dropbox" | "line" | (string & {}) | "huggingface" | "apple" | "atlassian" | "cognito" | "discord" | "facebook" | "figma" | "microsoft" | "google" | "spotify" | "twitch" | "twitter" | "kick" | "gitlab" | "tiktok" | "reddit" | "roblox" | "vk" | "zoom" | "kakao" | "naver" | "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: "salesforce" | "slack" | "linear" | "notion" | "linkedin" | "github" | "dropbox" | (string & {}) | "huggingface" | "apple" | "atlassian" | "cognito" | "discord" | "facebook" | "figma" | "microsoft" | "google" | "spotify" | "twitch" | "twitter" | "kick" | "gitlab" | "tiktok" | "reddit" | "roblox" | "vk" | "zoom" | "kakao" | "naver" | "
|
|
94
|
+
provider: "salesforce" | "slack" | "linear" | "notion" | "linkedin" | "github" | "dropbox" | "line" | (string & {}) | "huggingface" | "apple" | "atlassian" | "cognito" | "discord" | "facebook" | "figma" | "microsoft" | "google" | "spotify" | "twitch" | "twitter" | "kick" | "gitlab" | "tiktok" | "reddit" | "roblox" | "vk" | "zoom" | "kakao" | "naver" | "paybin" | "paypal" | "polar" | "railway" | "vercel" | "wechat";
|
|
95
95
|
callbackURL?: string | undefined;
|
|
96
96
|
newUserCallbackURL?: string | undefined;
|
|
97
97
|
errorCallbackURL?: string | undefined;
|
|
@@ -187,3 +187,33 @@ function redirectParamOf(href) {
|
|
|
187
187
|
(0, vitest_1.expect)(params.get('usageToken')).toBeNull();
|
|
188
188
|
});
|
|
189
189
|
});
|
|
190
|
+
// AUTH-03: what the platform's auth routes receive from the client, on the app's own origin.
|
|
191
|
+
(0, vitest_1.describe)("the client's calls", () => {
|
|
192
|
+
const calls = () => {
|
|
193
|
+
const sent = [];
|
|
194
|
+
vitest_1.vi.stubGlobal('fetch', vitest_1.vi.fn(async (input, init) => {
|
|
195
|
+
const request = new Request(new URL(String(input instanceof Request ? input.url : input), 'https://app.zite.so'), init);
|
|
196
|
+
sent.push({
|
|
197
|
+
path: new URL(request.url).pathname,
|
|
198
|
+
method: request.method,
|
|
199
|
+
body: request.method === 'POST' ? await request.json().catch(() => null) : null,
|
|
200
|
+
});
|
|
201
|
+
return Response.json({});
|
|
202
|
+
}));
|
|
203
|
+
return sent;
|
|
204
|
+
};
|
|
205
|
+
(0, vitest_1.it)('sign in by link, sign out and edit the profile on /api/auth', async () => {
|
|
206
|
+
const sent = calls();
|
|
207
|
+
// The client takes its fetch when the module loads.
|
|
208
|
+
vitest_1.vi.resetModules();
|
|
209
|
+
const { signIn, signOut, updateProfile } = await Promise.resolve().then(() => __importStar(require('./index.js')));
|
|
210
|
+
await signIn.magicLink({ email: 'ada@x.co' });
|
|
211
|
+
await signOut();
|
|
212
|
+
await updateProfile({ firstName: 'Ada' });
|
|
213
|
+
(0, vitest_1.expect)(sent).toEqual([
|
|
214
|
+
{ path: '/api/auth/sign-in/magic-link', method: 'POST', body: vitest_1.expect.objectContaining({ email: 'ada@x.co' }) },
|
|
215
|
+
{ path: '/api/auth/sign-out', method: 'POST', body: vitest_1.expect.anything() },
|
|
216
|
+
{ path: '/api/auth/update-user', method: 'POST', body: { firstName: 'Ada' } },
|
|
217
|
+
]);
|
|
218
|
+
});
|
|
219
|
+
});
|
|
@@ -23,6 +23,8 @@ export type ZiteTrigger = {
|
|
|
23
23
|
paused?: boolean;
|
|
24
24
|
every?: never;
|
|
25
25
|
events?: never;
|
|
26
|
+
table?: never;
|
|
27
|
+
form?: never;
|
|
26
28
|
} | {
|
|
27
29
|
/**
|
|
28
30
|
* The connection's name in `zite.config.json`, for a provider whose
|
|
@@ -37,6 +39,8 @@ export type ZiteTrigger = {
|
|
|
37
39
|
label?: string;
|
|
38
40
|
paused?: boolean;
|
|
39
41
|
every?: never;
|
|
42
|
+
table?: never;
|
|
43
|
+
form?: never;
|
|
40
44
|
} | {
|
|
41
45
|
/** `<n>m` (1–59) or `<n>h` (1–23). What makes the trigger a poll. */
|
|
42
46
|
every: string;
|
|
@@ -46,6 +50,78 @@ export type ZiteTrigger = {
|
|
|
46
50
|
label?: string;
|
|
47
51
|
paused?: boolean;
|
|
48
52
|
events?: never;
|
|
53
|
+
table?: never;
|
|
54
|
+
form?: never;
|
|
55
|
+
} | {
|
|
56
|
+
/**
|
|
57
|
+
* A table in the project's own database, as `zite.<table>` names it.
|
|
58
|
+
* Every write to it reaches the trigger, from apps, forms, imports, the
|
|
59
|
+
* database view and other automations; nothing is registered.
|
|
60
|
+
*/
|
|
61
|
+
table: string;
|
|
62
|
+
on: ZiteDatabaseTriggerEvent[];
|
|
63
|
+
/** Narrows `"updated"` to updates that changed one of these fields. */
|
|
64
|
+
fields?: string[];
|
|
65
|
+
/** The sentence the editor shows, e.g. "When an order ships". */
|
|
66
|
+
label?: string;
|
|
67
|
+
paused?: boolean;
|
|
68
|
+
integration?: never;
|
|
69
|
+
every?: never;
|
|
70
|
+
events?: never;
|
|
71
|
+
form?: never;
|
|
72
|
+
} | {
|
|
73
|
+
/**
|
|
74
|
+
* One of the project's own Fillout forms, by its name as the project
|
|
75
|
+
* lists it, or its id. Each finished live submission fires the
|
|
76
|
+
* endpoint; nothing is registered.
|
|
77
|
+
*/
|
|
78
|
+
form: string;
|
|
79
|
+
on: "submitted"[];
|
|
80
|
+
/** The sentence the editor shows, e.g. "When someone fills in the intake form". */
|
|
81
|
+
label?: string;
|
|
82
|
+
paused?: boolean;
|
|
83
|
+
integration?: never;
|
|
84
|
+
every?: never;
|
|
85
|
+
events?: never;
|
|
86
|
+
table?: never;
|
|
87
|
+
};
|
|
88
|
+
/**
|
|
89
|
+
* What a form trigger's run gets as `input`: one submission. `answers` is
|
|
90
|
+
* keyed by question name, `answersById` by question id; `submission` is the
|
|
91
|
+
* whole export, as the Fillout API returns it (`questions`, `calculations`,
|
|
92
|
+
* `urlParameters`, …). Two questions with the same label are named
|
|
93
|
+
* `Email` and `Email (1)` in an order the form doesn't show, so read those by
|
|
94
|
+
* id.
|
|
95
|
+
*/
|
|
96
|
+
export type ZiteFormTriggerInput = {
|
|
97
|
+
event: "submitted";
|
|
98
|
+
form: string;
|
|
99
|
+
formId: string;
|
|
100
|
+
submissionId: string;
|
|
101
|
+
submittedAt: string | null;
|
|
102
|
+
answers: Record<string, unknown>;
|
|
103
|
+
answersById: Record<string, unknown>;
|
|
104
|
+
submission: Record<string, unknown> & {
|
|
105
|
+
submissionId: string;
|
|
106
|
+
};
|
|
107
|
+
};
|
|
108
|
+
export type ZiteDatabaseTriggerEvent = "created" | "updated" | "deleted";
|
|
109
|
+
/**
|
|
110
|
+
* What a database trigger's run gets as `input`: one changed record. Field
|
|
111
|
+
* keys are the SDK's, as `zite.<table>.findOne` returns them; cast `record`
|
|
112
|
+
* and `previous` to the table's generated `<Table>RecordType` from
|
|
113
|
+
* `zitejs/db` to type their fields.
|
|
114
|
+
*/
|
|
115
|
+
export type ZiteDatabaseTriggerInput<TRecord extends Record<string, unknown> = Record<string, unknown>> = {
|
|
116
|
+
event: ZiteDatabaseTriggerEvent;
|
|
117
|
+
table: string;
|
|
118
|
+
recordId: string;
|
|
119
|
+
/** Null if it was deleted before the run read it; on `"deleted"`, the record as it was. */
|
|
120
|
+
record: TRecord | null;
|
|
121
|
+
/** The record before an `"updated"`; null otherwise, and on a very large bulk write. */
|
|
122
|
+
previous: TRecord | null;
|
|
123
|
+
/** What an `"updated"` changed. */
|
|
124
|
+
changedFields: string[];
|
|
49
125
|
};
|
|
50
126
|
/**
|
|
51
127
|
* What a provider trigger's `subscribe` export receives. Write it as
|
|
@@ -115,10 +191,20 @@ export type ZiteTriggerDeliveryRun = ZiteTriggerRun & ZiteTriggerDeliveryInfo;
|
|
|
115
191
|
export type ZiteTriggerContext<TTrigger> = TTrigger extends {
|
|
116
192
|
every: string;
|
|
117
193
|
} ? ZiteTriggerRun : TTrigger extends {
|
|
194
|
+
table: string;
|
|
195
|
+
} | {
|
|
196
|
+
form: string;
|
|
197
|
+
} ? ZiteTriggerDeliveryInfo : TTrigger extends {
|
|
118
198
|
events: string[];
|
|
119
199
|
} ? ZiteTriggerDeliveryInfo : TTrigger extends {
|
|
120
200
|
integration: string;
|
|
121
201
|
} ? ZiteTriggerDeliveryRun : never;
|
|
202
|
+
/** A database or form trigger's runs get the change or submission as `input`. */
|
|
203
|
+
export type ZiteEndpointInput<TInput, TTrigger> = TTrigger extends {
|
|
204
|
+
table: string;
|
|
205
|
+
} ? ZiteDatabaseTriggerInput : TTrigger extends {
|
|
206
|
+
form: string;
|
|
207
|
+
} ? ZiteFormTriggerInput : TInput;
|
|
122
208
|
export interface ZiteRequestContext {
|
|
123
209
|
user: {
|
|
124
210
|
id: string;
|
|
@@ -215,13 +301,15 @@ export interface EndpointConfig<TInput = unknown, TOutput = unknown, TStream ext
|
|
|
215
301
|
*/
|
|
216
302
|
validatesInput?: boolean;
|
|
217
303
|
execute: (params: {
|
|
218
|
-
input: TInput
|
|
304
|
+
input: ZiteEndpointInput<TInput, TTrigger>;
|
|
219
305
|
/**
|
|
220
306
|
* Durable steps. `step.run(name, fn)` runs `fn` once per logical run:
|
|
221
307
|
* its result is saved before anything after it executes, and when a
|
|
222
308
|
* failed run is resumed, completed steps return their saved results
|
|
223
309
|
* instead of re-running their side effects. Names must be unique within
|
|
224
|
-
* a run, and results must be plain JSON data under 256KB.
|
|
310
|
+
* a run, and results must be plain JSON data under 256KB. In a run
|
|
311
|
+
* fired by a schedule, webhook or trigger, `step.sleep` pauses the run
|
|
312
|
+
* and a failed step is tried again.
|
|
225
313
|
*/
|
|
226
314
|
step: ZiteStep;
|
|
227
315
|
context: TSchedule extends ZiteSchedule ? ZiteRequestContext | ZiteScheduledContext : TWebhook extends ZiteWebhook ? ZiteRequestContext | ZiteScheduledContext : TTrigger extends ZiteTrigger ? ZiteRequestContext | ZiteScheduledContext : ZiteRequestContext;
|
|
@@ -240,8 +328,32 @@ export interface EndpointConfig<TInput = unknown, TOutput = unknown, TStream ext
|
|
|
240
328
|
* it would matter, and give a step inside a loop the item's id in its name.
|
|
241
329
|
*/
|
|
242
330
|
export interface ZiteStep {
|
|
243
|
-
|
|
331
|
+
/**
|
|
332
|
+
* In a run fired by a schedule, webhook or trigger, a step that throws is
|
|
333
|
+
* tried again `retries` more times (default 3, at most 10), 30 seconds,
|
|
334
|
+
* 2 minutes, then 10 minutes apart. Elsewhere its error fails the request.
|
|
335
|
+
*/
|
|
336
|
+
run<T>(name: string, fn: () => Promise<T> | T, options?: ZiteStepOptions): Promise<T>;
|
|
337
|
+
/**
|
|
338
|
+
* Pause the run for `duration`: `"30s"`, `"15m"`, `"2h"`, `"3d"`, `"1w"`,
|
|
339
|
+
* or milliseconds, at most 30 days. Only a run fired by a schedule, webhook
|
|
340
|
+
* or trigger can wait; an editor test run goes straight past, and a request
|
|
341
|
+
* from the app throws.
|
|
342
|
+
*
|
|
343
|
+
* The run continues in a later call, which runs `execute` again from the
|
|
344
|
+
* top: finished steps return their saved results, and code outside a step
|
|
345
|
+
* runs again, so keep side effects inside steps.
|
|
346
|
+
*/
|
|
347
|
+
sleep(name: string, duration: ZiteStepDuration): Promise<void>;
|
|
348
|
+
/** Pause the run until `when`, at most 30 days ahead. See {@link ZiteStep.sleep}. */
|
|
349
|
+
sleepUntil(name: string, when: Date | string): Promise<void>;
|
|
350
|
+
}
|
|
351
|
+
export interface ZiteStepOptions {
|
|
352
|
+
/** How many more times to try the step after it throws: 0 to 10, default 3. */
|
|
353
|
+
retries?: number;
|
|
244
354
|
}
|
|
355
|
+
/** Milliseconds, or a number with a unit: `ms`, `s`, `m`, `h`, `d` or `w`. */
|
|
356
|
+
export type ZiteStepDuration = number | `${number}${"ms" | "s" | "m" | "h" | "d" | "w"}`;
|
|
245
357
|
/**
|
|
246
358
|
* Create an endpoint definition, parsing `input` against `inputSchema` before
|
|
247
359
|
* `execute` runs. Nothing downstream parses it — the worker calls `execute` on
|
|
@@ -8,6 +8,8 @@ const requestContext = { user: { id: "u1", email: "a@b.c", roles: [] } };
|
|
|
8
8
|
// Direct execute() calls need the step surface the runtime always provides.
|
|
9
9
|
const stepStub = {
|
|
10
10
|
run: async (_name, fn) => await fn(),
|
|
11
|
+
sleep: async () => { },
|
|
12
|
+
sleepUntil: async () => { },
|
|
11
13
|
};
|
|
12
14
|
(0, vitest_1.afterEach)(() => {
|
|
13
15
|
vitest_1.vi.unstubAllGlobals();
|
|
@@ -207,6 +209,62 @@ const stepStub = {
|
|
|
207
209
|
return params.trigger;
|
|
208
210
|
},
|
|
209
211
|
});
|
|
212
|
+
(0, index_js_1.createEndpoint)({
|
|
213
|
+
trigger: { table: "orders", on: ["updated"], fields: ["status"] },
|
|
214
|
+
execute: async ({ input, trigger }) => {
|
|
215
|
+
// @ts-expect-error a database change has no cursor API
|
|
216
|
+
trigger?.advance("x");
|
|
217
|
+
const status = input.record?.status;
|
|
218
|
+
return { status, changed: input.changedFields, at: input.event };
|
|
219
|
+
},
|
|
220
|
+
});
|
|
221
|
+
(0, index_js_1.createEndpoint)({
|
|
222
|
+
// @ts-expect-error a database trigger names its table, not a connection
|
|
223
|
+
trigger: { table: "orders", on: ["created"], integration: "x" },
|
|
224
|
+
execute: async () => 1,
|
|
225
|
+
});
|
|
226
|
+
(0, index_js_1.createEndpoint)({
|
|
227
|
+
trigger: { form: "Intake form", on: ["submitted"] },
|
|
228
|
+
execute: async ({ input, trigger }) => {
|
|
229
|
+
// @ts-expect-error a form submission has no cursor API
|
|
230
|
+
trigger?.advance("x");
|
|
231
|
+
return {
|
|
232
|
+
email: input.answers.Email,
|
|
233
|
+
workEmail: input.answersById["wWorkEmail"],
|
|
234
|
+
id: input.submissionId,
|
|
235
|
+
};
|
|
236
|
+
},
|
|
237
|
+
});
|
|
238
|
+
(0, index_js_1.createEndpoint)({
|
|
239
|
+
// @ts-expect-error a form trigger watches submissions only
|
|
240
|
+
trigger: { form: "Intake form", on: ["updated"] },
|
|
241
|
+
execute: async () => 1,
|
|
242
|
+
});
|
|
243
|
+
(0, index_js_1.createEndpoint)({
|
|
244
|
+
// @ts-expect-error only created, updated and deleted
|
|
245
|
+
trigger: { table: "orders", on: ["archived"] },
|
|
246
|
+
execute: async () => 1,
|
|
247
|
+
});
|
|
248
|
+
});
|
|
249
|
+
(0, vitest_1.it)("hands a database trigger its change without parsing it against the input schema", async () => {
|
|
250
|
+
const endpoint = (0, index_js_1.createEndpoint)({
|
|
251
|
+
inputSchema: zod_1.z.object({ orderId: zod_1.z.string() }),
|
|
252
|
+
trigger: { table: "orders", on: ["created"] },
|
|
253
|
+
execute: async ({ input }) => input.recordId,
|
|
254
|
+
});
|
|
255
|
+
await (0, vitest_1.expect)(endpoint.execute({
|
|
256
|
+
step: stepStub,
|
|
257
|
+
input: {
|
|
258
|
+
event: "created",
|
|
259
|
+
table: "orders",
|
|
260
|
+
recordId: "rec_1",
|
|
261
|
+
record: { id: "rec_1" },
|
|
262
|
+
previous: null,
|
|
263
|
+
changedFields: [],
|
|
264
|
+
},
|
|
265
|
+
context: { user: null },
|
|
266
|
+
trigger: { headers: {}, deliveryId: "db:e1:rec_1" },
|
|
267
|
+
})).resolves.toBe("rec_1");
|
|
210
268
|
});
|
|
211
269
|
(0, vitest_1.it)("types a trigger's registration exports and checks what subscribe returns", async () => {
|
|
212
270
|
const subscribe = (async (input) => ({
|
|
@@ -1 +1,33 @@
|
|
|
1
|
-
|
|
1
|
+
import { type Problem } from './start/problem.js';
|
|
2
|
+
type Step = {
|
|
3
|
+
name: string;
|
|
4
|
+
ok: boolean;
|
|
5
|
+
output?: string;
|
|
6
|
+
};
|
|
7
|
+
/** One app's check, as `--json` reports it. */
|
|
8
|
+
export type AppCheck = {
|
|
9
|
+
path: string;
|
|
10
|
+
runtime: 'classic' | 'start';
|
|
11
|
+
ok: boolean;
|
|
12
|
+
steps: Step[];
|
|
13
|
+
problems: Problem[];
|
|
14
|
+
};
|
|
15
|
+
/**
|
|
16
|
+
* While `--json` checks, stdout carries only the report: app code that logs as
|
|
17
|
+
* it's described in-process goes to stderr instead.
|
|
18
|
+
*/
|
|
19
|
+
export declare const withStdoutOnStderr: <T>(run: () => Promise<T>) => Promise<T>;
|
|
20
|
+
/** Prints as it goes, or with `--json` stays quiet and reports everything at the end. */
|
|
21
|
+
export declare class Reporter {
|
|
22
|
+
private readonly json;
|
|
23
|
+
readonly apps: AppCheck[];
|
|
24
|
+
constructor(json: boolean);
|
|
25
|
+
app(path: string, runtime: AppCheck['runtime'], heading: boolean): AppCheck;
|
|
26
|
+
step(app: AppCheck, name: string, result: {
|
|
27
|
+
ok: boolean;
|
|
28
|
+
output?: string;
|
|
29
|
+
}): boolean;
|
|
30
|
+
problems(app: AppCheck, problems: Problem[]): void;
|
|
31
|
+
}
|
|
32
|
+
export declare function runCheck(args?: string[]): Promise<void>;
|
|
33
|
+
export {};
|
package/dist/cjs/check/index.js
CHANGED
|
@@ -1,10 +1,45 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
2
35
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.Reporter = exports.withStdoutOnStderr = void 0;
|
|
3
37
|
exports.runCheck = runCheck;
|
|
4
38
|
const child_process_1 = require("child_process");
|
|
5
39
|
const fs_1 = require("fs");
|
|
6
40
|
const path_1 = require("path");
|
|
7
41
|
const sourceRoots_js_1 = require("../sourceRoots.js");
|
|
42
|
+
const problem_js_1 = require("./start/problem.js");
|
|
8
43
|
/**
|
|
9
44
|
* An argument array, not a command string, so no shell is involved.
|
|
10
45
|
*
|
|
@@ -58,73 +93,166 @@ function bundleFailures(output) {
|
|
|
58
93
|
}
|
|
59
94
|
return failures;
|
|
60
95
|
}
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
96
|
+
const indent = (output) => output.trim().split('\n').map(l => ` ${l}`).join('\n');
|
|
97
|
+
/**
|
|
98
|
+
* While `--json` checks, stdout carries only the report: app code that logs as
|
|
99
|
+
* it's described in-process goes to stderr instead.
|
|
100
|
+
*/
|
|
101
|
+
const withStdoutOnStderr = async (run) => {
|
|
102
|
+
const write = process.stdout.write;
|
|
103
|
+
process.stdout.write = process.stderr.write.bind(process.stderr);
|
|
104
|
+
try {
|
|
105
|
+
return await run();
|
|
66
106
|
}
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
107
|
+
finally {
|
|
108
|
+
process.stdout.write = write;
|
|
109
|
+
}
|
|
110
|
+
};
|
|
111
|
+
exports.withStdoutOnStderr = withStdoutOnStderr;
|
|
112
|
+
/** Prints as it goes, or with `--json` stays quiet and reports everything at the end. */
|
|
113
|
+
class Reporter {
|
|
114
|
+
json;
|
|
115
|
+
apps = [];
|
|
116
|
+
constructor(json) {
|
|
117
|
+
this.json = json;
|
|
118
|
+
}
|
|
119
|
+
app(path, runtime, heading) {
|
|
120
|
+
const app = { path, runtime, ok: true, steps: [], problems: [] };
|
|
121
|
+
this.apps.push(app);
|
|
122
|
+
if (heading && !this.json)
|
|
123
|
+
console.log(`\n── ${path} ──`);
|
|
124
|
+
return app;
|
|
125
|
+
}
|
|
126
|
+
step(app, name, result) {
|
|
127
|
+
const output = result.output?.trim();
|
|
128
|
+
app.steps.push({ name, ok: result.ok, ...(output && !result.ok && { output }) });
|
|
129
|
+
if (!result.ok)
|
|
130
|
+
app.ok = false;
|
|
131
|
+
if (!this.json) {
|
|
132
|
+
console.log(` ${name} ... ${result.ok ? '✓' : '✗'}`);
|
|
133
|
+
if (!result.ok && output)
|
|
134
|
+
console.log(indent(output));
|
|
91
135
|
}
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
136
|
+
return result.ok;
|
|
137
|
+
}
|
|
138
|
+
problems(app, problems) {
|
|
139
|
+
app.problems.push(...problems);
|
|
140
|
+
if (problems.some(p => p.severity === 'error'))
|
|
141
|
+
app.ok = false;
|
|
142
|
+
if (!this.json && problems.length)
|
|
143
|
+
console.log(problems.map(p => ` ${(0, problem_js_1.formatProblem)(p)}`).join('\n'));
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
exports.Reporter = Reporter;
|
|
147
|
+
const SKIPPED_DIRS = new Set(['node_modules', 'dist', '.output', '.tanstack', '.wrangler']);
|
|
148
|
+
/** The app's own source, by app-relative path. */
|
|
149
|
+
function readAppSources(appPath) {
|
|
150
|
+
const sources = {};
|
|
151
|
+
const visit = (dir) => {
|
|
152
|
+
for (const entry of (0, fs_1.readdirSync)(dir, { withFileTypes: true })) {
|
|
153
|
+
if (SKIPPED_DIRS.has(entry.name))
|
|
154
|
+
continue;
|
|
155
|
+
const full = (0, path_1.join)(dir, entry.name);
|
|
156
|
+
if (entry.isDirectory())
|
|
157
|
+
visit(full);
|
|
158
|
+
else if (/\.[cm]?[jt]sx?$/.test(entry.name))
|
|
159
|
+
sources[(0, path_1.relative)(appPath, full)] = (0, fs_1.readFileSync)(full, 'utf-8');
|
|
107
160
|
}
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
161
|
+
};
|
|
162
|
+
const src = (0, path_1.join)(appPath, 'src');
|
|
163
|
+
if ((0, fs_1.existsSync)(src))
|
|
164
|
+
visit(src);
|
|
165
|
+
return sources;
|
|
166
|
+
}
|
|
167
|
+
const isInternalApp = (appPath) => {
|
|
168
|
+
try {
|
|
169
|
+
return JSON.parse((0, fs_1.readFileSync)((0, path_1.join)(appPath, 'zite.config.json'), 'utf-8'))?.accessMode === 'internal';
|
|
170
|
+
}
|
|
171
|
+
catch {
|
|
172
|
+
return false;
|
|
173
|
+
}
|
|
174
|
+
};
|
|
175
|
+
/**
|
|
176
|
+
* A Start app: `vite build` first, since it regenerates the route tree tsc
|
|
177
|
+
* reads, then tsc, then describe, which reports what the platform's build
|
|
178
|
+
* refuses, read the same way, then the source hints.
|
|
179
|
+
*/
|
|
180
|
+
async function checkStartApp(reporter, app, appPath) {
|
|
181
|
+
if (!reporter.step(app, 'vite build', run('npx', ['vite', 'build'], appPath)))
|
|
182
|
+
return;
|
|
183
|
+
// --pretty for `file:line:col - error` lines, the shape the platform re-roots.
|
|
184
|
+
reporter.step(app, 'tsc --noEmit', run('npx', ['tsc', '--noEmit', '--pretty', '-p', 'tsconfig.app.json'], appPath));
|
|
185
|
+
const { describedProblems } = await Promise.resolve().then(() => __importStar(require('./start/describeRules.js')));
|
|
186
|
+
const { sourceProblems } = await Promise.resolve().then(() => __importStar(require('./start/sourceRules.js')));
|
|
187
|
+
try {
|
|
188
|
+
const { describeBuiltApp } = await Promise.resolve().then(() => __importStar(require('../start/describeBuilt.js')));
|
|
189
|
+
const description = (await describeBuiltApp(appPath));
|
|
190
|
+
const problems = describedProblems(description, { internal: isInternalApp(appPath) });
|
|
191
|
+
reporter.step(app, 'describe', { ok: !problems.some(p => p.severity === 'error') });
|
|
192
|
+
reporter.problems(app, problems);
|
|
193
|
+
}
|
|
194
|
+
catch (err) {
|
|
195
|
+
reporter.step(app, 'describe', { ok: false, output: err instanceof Error ? err.message : String(err) });
|
|
196
|
+
}
|
|
197
|
+
const hints = sourceProblems(readAppSources(appPath));
|
|
198
|
+
reporter.step(app, 'source', { ok: !hints.some(p => p.severity === 'error') });
|
|
199
|
+
reporter.problems(app, hints);
|
|
200
|
+
}
|
|
201
|
+
function checkClassicApp(reporter, app, root, dir, appPath) {
|
|
202
|
+
// Only tsconfig.app.json compiles anything. The app's tsconfig.json is a
|
|
203
|
+
// solution-style config — `"files": []` plus a reference — so
|
|
204
|
+
// `tsc --noEmit -p tsconfig.json` type-checks zero files and exits 0. It
|
|
205
|
+
// used to be the fallback, which meant an app missing tsconfig.app.json
|
|
206
|
+
// reported a passing typecheck it never ran.
|
|
207
|
+
const tsconfigAppPath = (0, path_1.join)(appPath, 'tsconfig.app.json');
|
|
208
|
+
reporter.step(app, 'tsc --noEmit', (0, fs_1.existsSync)(tsconfigAppPath)
|
|
209
|
+
? run('npx', ['tsc', '--noEmit', '-p', tsconfigAppPath], '.')
|
|
210
|
+
: { ok: false, output: `no ${tsconfigAppPath}` });
|
|
211
|
+
// Endpoints never reach vite — they are bundled separately for the lambda,
|
|
212
|
+
// against a different resolver. tsc and vite both pass on an endpoint whose
|
|
213
|
+
// `zitejs/*` alias has no generated file behind it; only the bundler knows.
|
|
214
|
+
if ((0, sourceRoots_js_1.listEndpointNames)(root, appPath).length > 0) {
|
|
215
|
+
const bundle = run('npx', ['zitejs', 'bundle', '--app', dir], '.');
|
|
216
|
+
const failures = bundle.ok ? bundleFailures(bundle.output) : [bundle.output];
|
|
217
|
+
reporter.step(app, 'bundle endpoints', { ok: failures.length === 0, output: failures.join('\n') });
|
|
218
|
+
}
|
|
219
|
+
if ((0, fs_1.existsSync)((0, path_1.join)(appPath, 'vite.config.ts'))) {
|
|
220
|
+
reporter.step(app, 'vite build', run('npx', ['vite', 'build'], appPath));
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
async function runCheck(args = process.argv.slice(3)) {
|
|
224
|
+
const json = args.includes('--json');
|
|
225
|
+
const reporter = new Reporter(json);
|
|
226
|
+
const { isStartAppDir } = await Promise.resolve().then(() => __importStar(require('../start/entries.js')));
|
|
227
|
+
// Run inside a Start app, its own zitejs checks just that app: the workspace
|
|
228
|
+
// root's is a classic release that doesn't know Start.
|
|
229
|
+
const inStartApp = isStartAppDir('.');
|
|
230
|
+
const appDirs = inStartApp ? [] : (0, sourceRoots_js_1.listSourceDirs)();
|
|
231
|
+
if (!inStartApp && appDirs.length === 0) {
|
|
232
|
+
console.error('No apps or automations found under apps/ or automations/.');
|
|
233
|
+
process.exit(1);
|
|
234
|
+
}
|
|
235
|
+
const checkAll = async () => {
|
|
236
|
+
if (inStartApp)
|
|
237
|
+
await checkStartApp(reporter, reporter.app('.', 'start', false), '.');
|
|
238
|
+
for (const { root, dir, path: appPath } of appDirs) {
|
|
239
|
+
if (isStartAppDir(appPath)) {
|
|
240
|
+
await checkStartApp(reporter, reporter.app(appPath, 'start', true), appPath);
|
|
114
241
|
}
|
|
115
242
|
else {
|
|
116
|
-
|
|
117
|
-
console.log(vite.output.trim().split('\n').map(l => ` ${l}`).join('\n'));
|
|
118
|
-
allPassed = false;
|
|
243
|
+
checkClassicApp(reporter, reporter.app(appPath, 'classic', true), root, dir, appPath);
|
|
119
244
|
}
|
|
120
245
|
}
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
246
|
+
};
|
|
247
|
+
await (json ? (0, exports.withStdoutOnStderr)(checkAll) : checkAll());
|
|
248
|
+
const allPassed = reporter.apps.every(app => app.ok);
|
|
249
|
+
if (json) {
|
|
250
|
+
process.stdout.write(`${JSON.stringify({ ok: allPassed, apps: reporter.apps })}\n`);
|
|
125
251
|
}
|
|
126
252
|
else {
|
|
127
|
-
console.log('
|
|
128
|
-
|
|
253
|
+
console.log('');
|
|
254
|
+
console.log(allPassed ? 'All apps pass.' : 'Some apps failed.');
|
|
129
255
|
}
|
|
256
|
+
if (!allPassed)
|
|
257
|
+
process.exit(1);
|
|
130
258
|
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import type { Problem } from "./problem.js";
|
|
2
|
+
type Access = {
|
|
3
|
+
kind: string;
|
|
4
|
+
roles?: string[];
|
|
5
|
+
};
|
|
6
|
+
export type CheckedDescription = {
|
|
7
|
+
functions: Array<{
|
|
8
|
+
id: string;
|
|
9
|
+
name?: string;
|
|
10
|
+
file?: string;
|
|
11
|
+
access: Access;
|
|
12
|
+
input?: unknown;
|
|
13
|
+
problems: string[];
|
|
14
|
+
}>;
|
|
15
|
+
routes: Array<{
|
|
16
|
+
path: string;
|
|
17
|
+
file?: string;
|
|
18
|
+
description?: string;
|
|
19
|
+
methods: Record<string, Access>;
|
|
20
|
+
problems: string[];
|
|
21
|
+
}>;
|
|
22
|
+
pages?: Array<{
|
|
23
|
+
path: string;
|
|
24
|
+
file?: string;
|
|
25
|
+
}>;
|
|
26
|
+
workflows?: Array<{
|
|
27
|
+
id: string;
|
|
28
|
+
file: string;
|
|
29
|
+
problems: string[];
|
|
30
|
+
}>;
|
|
31
|
+
};
|
|
32
|
+
export declare function describedProblems(description: CheckedDescription, { internal }: {
|
|
33
|
+
internal: boolean;
|
|
34
|
+
}): Problem[];
|
|
35
|
+
export {};
|