zitejs 0.9.119 → 0.9.121
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/config.d.ts +3 -0
- package/dist/cjs/auth/config.js +7 -0
- package/dist/cjs/auth/index.js +30 -4
- package/dist/cjs/auth/useAuth.test.d.ts +1 -0
- package/dist/cjs/auth/useAuth.test.js +82 -0
- package/dist/cjs/backend/index.d.ts +30 -3
- package/dist/cjs/backend/index.js +2 -2
- package/dist/cjs/bundle/index.d.ts +1 -1
- package/dist/cjs/bundle/index.js +6 -2
- package/dist/cjs/check/index.js +5 -13
- package/dist/cjs/cli.js +2 -2
- package/dist/cjs/dev/index.js +31 -44
- 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 +19 -0
- package/dist/cjs/sourceRoots.js +33 -0
- package/dist/cjs/sync/lib.d.ts +6 -0
- package/dist/cjs/sync/lib.js +13 -0
- package/dist/cjs/sync/lib.test.js +28 -0
- package/dist/cjs/upload/index.js +19 -0
- package/dist/cjs/upload/index.test.js +30 -3
- package/dist/cjs/vite/domTagNames.d.ts +1 -0
- package/dist/cjs/vite/domTagNames.js +257 -0
- package/dist/cjs/vite/index.js +20 -11
- package/dist/cjs/vite/index.test.d.ts +1 -0
- package/dist/cjs/vite/index.test.js +53 -0
- package/dist/esm/auth/config.d.ts +3 -0
- package/dist/esm/auth/config.js +6 -0
- package/dist/esm/auth/index.js +28 -2
- package/dist/esm/auth/useAuth.test.d.ts +1 -0
- package/dist/esm/auth/useAuth.test.js +80 -0
- package/dist/esm/backend/index.d.ts +30 -3
- package/dist/esm/backend/index.js +2 -2
- package/dist/esm/bundle/index.d.ts +1 -1
- package/dist/esm/bundle/index.js +6 -2
- package/dist/esm/check/index.js +6 -14
- package/dist/esm/cli.js +2 -2
- package/dist/esm/dev/index.js +32 -45
- 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 +19 -0
- package/dist/esm/sourceRoots.js +28 -0
- package/dist/esm/sync/lib.d.ts +6 -0
- package/dist/esm/sync/lib.js +12 -0
- package/dist/esm/sync/lib.test.js +29 -1
- package/dist/esm/upload/index.js +19 -0
- package/dist/esm/upload/index.test.js +30 -3
- package/dist/esm/vite/domTagNames.d.ts +1 -0
- package/dist/esm/vite/domTagNames.js +254 -0
- package/dist/esm/vite/index.js +20 -11
- package/dist/esm/vite/index.test.d.ts +1 -0
- package/dist/esm/vite/index.test.js +48 -0
- package/package.json +1 -1
|
@@ -2,3 +2,6 @@ export declare function getFlowId(): string;
|
|
|
2
2
|
export declare function getApiUrl(): string;
|
|
3
3
|
export declare function getAuthPageUrl(): string;
|
|
4
4
|
export declare function getDbToken(): string;
|
|
5
|
+
/** Undefined for apps built before the platform sent this — treat as unknown,
|
|
6
|
+
* never as a default side. */
|
|
7
|
+
export declare function getAccessMode(): 'internal' | 'external' | undefined;
|
package/dist/cjs/auth/config.js
CHANGED
|
@@ -4,6 +4,7 @@ exports.getFlowId = getFlowId;
|
|
|
4
4
|
exports.getApiUrl = getApiUrl;
|
|
5
5
|
exports.getAuthPageUrl = getAuthPageUrl;
|
|
6
6
|
exports.getDbToken = getDbToken;
|
|
7
|
+
exports.getAccessMode = getAccessMode;
|
|
7
8
|
const env_js_1 = require("../internal/env.js");
|
|
8
9
|
const API_ENVIRONMENTS = {
|
|
9
10
|
production: 'https://api.fillout.com',
|
|
@@ -36,3 +37,9 @@ function getAuthPageUrl() {
|
|
|
36
37
|
function getDbToken() {
|
|
37
38
|
return (0, env_js_1.getEnv)('ZITE_DB_TOKEN', 'VITE_ZITE_DB_TOKEN') ?? '';
|
|
38
39
|
}
|
|
40
|
+
/** Undefined for apps built before the platform sent this — treat as unknown,
|
|
41
|
+
* never as a default side. */
|
|
42
|
+
function getAccessMode() {
|
|
43
|
+
const mode = (0, env_js_1.getEnv)('ZITE_ACCESS_MODE', 'VITE_ZITE_ACCESS_MODE');
|
|
44
|
+
return mode === 'internal' || mode === 'external' ? mode : undefined;
|
|
45
|
+
}
|
package/dist/cjs/auth/index.js
CHANGED
|
@@ -5,10 +5,12 @@ exports.useAuth = useAuth;
|
|
|
5
5
|
exports.loginWithRedirect = loginWithRedirect;
|
|
6
6
|
exports.logout = logout;
|
|
7
7
|
exports.updateProfile = updateProfile;
|
|
8
|
-
const react_1 = require("
|
|
8
|
+
const react_1 = require("react");
|
|
9
|
+
const react_2 = require("better-auth/react");
|
|
9
10
|
const plugins_1 = require("better-auth/client/plugins");
|
|
10
11
|
const constants_js_1 = require("./constants.js");
|
|
11
|
-
const
|
|
12
|
+
const config_js_1 = require("./config.js");
|
|
13
|
+
const authClient = (0, react_2.createAuthClient)({
|
|
12
14
|
baseURL: '',
|
|
13
15
|
plugins: [
|
|
14
16
|
(0, plugins_1.magicLinkClient)(),
|
|
@@ -21,6 +23,22 @@ const authClient = (0, react_1.createAuthClient)({
|
|
|
21
23
|
],
|
|
22
24
|
});
|
|
23
25
|
exports.useSession = authClient.useSession;
|
|
26
|
+
/**
|
|
27
|
+
* An internal app has no signed-out state — SSO runs before the bundle — so an
|
|
28
|
+
* empty session means it died underneath the app. Only `internal`: elsewhere a
|
|
29
|
+
* signed-out visitor is legitimate.
|
|
30
|
+
*/
|
|
31
|
+
function shouldRedirectSignedOut(isPending, hasUser) {
|
|
32
|
+
if (isPending || hasUser)
|
|
33
|
+
return false;
|
|
34
|
+
if ((0, config_js_1.getAccessMode)() !== 'internal')
|
|
35
|
+
return false;
|
|
36
|
+
if (typeof window === 'undefined')
|
|
37
|
+
return false;
|
|
38
|
+
// `loginWithRedirect` won't navigate from an auth page, so claiming a
|
|
39
|
+
// redirect here would hang `isLoading` forever.
|
|
40
|
+
return !window.location.pathname.startsWith('/auth/');
|
|
41
|
+
}
|
|
24
42
|
/**
|
|
25
43
|
* `loginWithRedirect` and `logout` are returned as well as exported. The
|
|
26
44
|
* pre-monorepo `useAuth()` returned them, so app code that destructures them
|
|
@@ -29,9 +47,17 @@ exports.useSession = authClient.useSession;
|
|
|
29
47
|
*/
|
|
30
48
|
function useAuth() {
|
|
31
49
|
const { data, isPending } = (0, exports.useSession)();
|
|
50
|
+
const user = data?.user ?? null;
|
|
51
|
+
const redirecting = shouldRedirectSignedOut(isPending, user !== null);
|
|
52
|
+
(0, react_1.useEffect)(() => {
|
|
53
|
+
if (redirecting)
|
|
54
|
+
loginWithRedirect();
|
|
55
|
+
}, [redirecting]);
|
|
32
56
|
return {
|
|
33
|
-
user
|
|
34
|
-
|
|
57
|
+
user,
|
|
58
|
+
// Loading, not signed out: the signed-out branch is the empty screen this
|
|
59
|
+
// exists to prevent.
|
|
60
|
+
isLoading: isPending || redirecting,
|
|
35
61
|
loginWithRedirect,
|
|
36
62
|
logout,
|
|
37
63
|
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const vitest_1 = require("vitest");
|
|
4
|
+
// Separate from index.test.ts: driving `useSession` means replacing
|
|
5
|
+
// `better-auth/react`, which would strip the real client asserted against there.
|
|
6
|
+
const { useSessionMock } = vitest_1.vi.hoisted(() => ({ useSessionMock: vitest_1.vi.fn() }));
|
|
7
|
+
vitest_1.vi.mock('better-auth/react', () => ({
|
|
8
|
+
createAuthClient: () => ({
|
|
9
|
+
useSession: useSessionMock,
|
|
10
|
+
signIn: {},
|
|
11
|
+
signUp: {},
|
|
12
|
+
signOut: vitest_1.vi.fn(),
|
|
13
|
+
updateUser: vitest_1.vi.fn(),
|
|
14
|
+
}),
|
|
15
|
+
}));
|
|
16
|
+
vitest_1.vi.mock('better-auth/client/plugins', () => ({
|
|
17
|
+
magicLinkClient: () => ({}),
|
|
18
|
+
inferAdditionalFields: () => ({}),
|
|
19
|
+
}));
|
|
20
|
+
// `useAuth` uses only `useEffect`; running it inline avoids pulling in a renderer.
|
|
21
|
+
vitest_1.vi.mock('react', () => ({ useEffect: (fn) => fn() }));
|
|
22
|
+
const index_js_1 = require("./index.js");
|
|
23
|
+
const APP_URL = 'https://app.zite.so/dashboard';
|
|
24
|
+
function stubLocation(href) {
|
|
25
|
+
const location = { pathname: new URL(href).pathname, href };
|
|
26
|
+
vitest_1.vi.stubGlobal('window', { location });
|
|
27
|
+
return location;
|
|
28
|
+
}
|
|
29
|
+
const signedOut = { data: null, isPending: false };
|
|
30
|
+
(0, vitest_1.beforeEach)(() => {
|
|
31
|
+
delete process.env.ZITE_ACCESS_MODE;
|
|
32
|
+
});
|
|
33
|
+
(0, vitest_1.afterEach)(() => {
|
|
34
|
+
delete process.env.ZITE_ACCESS_MODE;
|
|
35
|
+
vitest_1.vi.unstubAllGlobals();
|
|
36
|
+
useSessionMock.mockReset();
|
|
37
|
+
});
|
|
38
|
+
const render = (session, { accessMode, href = APP_URL } = {}) => {
|
|
39
|
+
if (accessMode !== undefined)
|
|
40
|
+
process.env.ZITE_ACCESS_MODE = accessMode;
|
|
41
|
+
const location = stubLocation(href);
|
|
42
|
+
useSessionMock.mockReturnValue(session);
|
|
43
|
+
return { result: (0, index_js_1.useAuth)(), location };
|
|
44
|
+
};
|
|
45
|
+
(0, vitest_1.describe)('useAuth signed-out handling', () => {
|
|
46
|
+
(0, vitest_1.it)('sends a signed-out visitor on an internal app to sign-in', () => {
|
|
47
|
+
const { result, location } = render(signedOut, { accessMode: 'internal' });
|
|
48
|
+
(0, vitest_1.expect)(location.href.startsWith('/auth/login')).toBe(true);
|
|
49
|
+
(0, vitest_1.expect)(result.isLoading).toBe(true);
|
|
50
|
+
});
|
|
51
|
+
(0, vitest_1.it)('leaves a signed-out visitor on an external app alone', () => {
|
|
52
|
+
const { result, location } = render(signedOut, { accessMode: 'external' });
|
|
53
|
+
(0, vitest_1.expect)(location.href).toBe(APP_URL);
|
|
54
|
+
(0, vitest_1.expect)(result.isLoading).toBe(false);
|
|
55
|
+
(0, vitest_1.expect)(result.user).toBe(null);
|
|
56
|
+
});
|
|
57
|
+
// i.e. every app published before the platform sent an access mode.
|
|
58
|
+
(0, vitest_1.it)('leaves an app that never declared an access mode alone', () => {
|
|
59
|
+
const { result, location } = render(signedOut);
|
|
60
|
+
(0, vitest_1.expect)(location.href).toBe(APP_URL);
|
|
61
|
+
(0, vitest_1.expect)(result.isLoading).toBe(false);
|
|
62
|
+
});
|
|
63
|
+
(0, vitest_1.it)('does not redirect while the session is still resolving', () => {
|
|
64
|
+
const { result, location } = render({ data: null, isPending: true }, { accessMode: 'internal' });
|
|
65
|
+
(0, vitest_1.expect)(location.href).toBe(APP_URL);
|
|
66
|
+
(0, vitest_1.expect)(result.isLoading).toBe(true);
|
|
67
|
+
});
|
|
68
|
+
(0, vitest_1.it)('does not redirect a signed-in visitor', () => {
|
|
69
|
+
const { result, location } = render({ data: { user: { id: 'u1', email: 'a@b.com' } }, isPending: false }, { accessMode: 'internal' });
|
|
70
|
+
(0, vitest_1.expect)(location.href).toBe(APP_URL);
|
|
71
|
+
(0, vitest_1.expect)(result.isLoading).toBe(false);
|
|
72
|
+
(0, vitest_1.expect)(result.user).toMatchObject({ id: 'u1' });
|
|
73
|
+
});
|
|
74
|
+
// Claiming a redirect it can't make would hang `isLoading` forever.
|
|
75
|
+
(0, vitest_1.it)('does not claim to be loading on an auth page it cannot leave', () => {
|
|
76
|
+
const { result } = render(signedOut, {
|
|
77
|
+
accessMode: 'internal',
|
|
78
|
+
href: 'https://app.zite.so/auth/login',
|
|
79
|
+
});
|
|
80
|
+
(0, vitest_1.expect)(result.isLoading).toBe(false);
|
|
81
|
+
});
|
|
82
|
+
});
|
|
@@ -3,6 +3,27 @@ export type { ZiteSchedule };
|
|
|
3
3
|
export type ZiteWebhook = {
|
|
4
4
|
paused?: boolean;
|
|
5
5
|
};
|
|
6
|
+
/**
|
|
7
|
+
* A provider trigger: what should fire the endpoint, declared as a literal.
|
|
8
|
+
* The platform registers it with the provider at publish, verifies each
|
|
9
|
+
* delivery and queues it; the endpoint only sees the payload. A `poll`
|
|
10
|
+
* trigger runs the endpoint on a cadence with `input.__poll.cursor` from the
|
|
11
|
+
* previous run, and the endpoint returns `{ cursor }` to advance it.
|
|
12
|
+
*/
|
|
13
|
+
export type ZiteTrigger = {
|
|
14
|
+
/**
|
|
15
|
+
* The connection's name in `zite.config.json`. Registered with the
|
|
16
|
+
* provider by `src/triggers/<endpointId>/subscribe.ts` and taken down
|
|
17
|
+
* by `unsubscribe.ts`, which the platform runs at publish and teardown.
|
|
18
|
+
*/
|
|
19
|
+
integration: string;
|
|
20
|
+
paused?: boolean;
|
|
21
|
+
} | {
|
|
22
|
+
provider: "poll";
|
|
23
|
+
/** `<n>m` (1–59) or `<n>h` (1–23) */
|
|
24
|
+
every: string;
|
|
25
|
+
paused?: boolean;
|
|
26
|
+
};
|
|
6
27
|
export interface ZiteRequestContext {
|
|
7
28
|
user: {
|
|
8
29
|
id: string;
|
|
@@ -58,7 +79,7 @@ export type ZiteStreamInterface = {
|
|
|
58
79
|
write: (data: unknown) => Promise<void>;
|
|
59
80
|
forward: (asyncIterable: AsyncIterable<string>) => Promise<string>;
|
|
60
81
|
};
|
|
61
|
-
export interface EndpointConfig<TInput = unknown, TOutput = unknown, TStream extends boolean = false, TSchedule extends ZiteSchedule | undefined = undefined, TWebhook extends ZiteWebhook | undefined = undefined, TRawInput = TInput> {
|
|
82
|
+
export interface EndpointConfig<TInput = unknown, TOutput = unknown, TStream extends boolean = false, TSchedule extends ZiteSchedule | undefined = undefined, TWebhook extends ZiteWebhook | undefined = undefined, TRawInput = TInput, TTrigger extends ZiteTrigger | undefined = undefined> {
|
|
62
83
|
description?: string;
|
|
63
84
|
inputSchema?: SchemaLike<TInput, TRawInput>;
|
|
64
85
|
/**
|
|
@@ -82,6 +103,12 @@ export interface EndpointConfig<TInput = unknown, TOutput = unknown, TStream ext
|
|
|
82
103
|
* `{ user: null }` for a webhook fire exactly as it does for a cron one.
|
|
83
104
|
*/
|
|
84
105
|
webhook?: TWebhook;
|
|
106
|
+
/**
|
|
107
|
+
* When set, the platform fires this endpoint from the named provider. Like
|
|
108
|
+
* `schedule` and `webhook`, this widens `context`: a provider delivery has
|
|
109
|
+
* no signed-in user.
|
|
110
|
+
*/
|
|
111
|
+
trigger?: TTrigger;
|
|
85
112
|
/**
|
|
86
113
|
* Set by {@link createEndpoint}, not by hand. The worker validates
|
|
87
114
|
* `inputSchema` for bundles built before this did, and skips ones that
|
|
@@ -90,7 +117,7 @@ export interface EndpointConfig<TInput = unknown, TOutput = unknown, TStream ext
|
|
|
90
117
|
validatesInput?: boolean;
|
|
91
118
|
execute: (params: {
|
|
92
119
|
input: TInput;
|
|
93
|
-
context: TSchedule extends ZiteSchedule ? ZiteRequestContext | ZiteScheduledContext : TWebhook extends ZiteWebhook ? ZiteRequestContext | ZiteScheduledContext : ZiteRequestContext;
|
|
120
|
+
context: TSchedule extends ZiteSchedule ? ZiteRequestContext | ZiteScheduledContext : TWebhook extends ZiteWebhook ? ZiteRequestContext | ZiteScheduledContext : TTrigger extends ZiteTrigger ? ZiteRequestContext | ZiteScheduledContext : ZiteRequestContext;
|
|
94
121
|
} & (TStream extends true ? {
|
|
95
122
|
stream: ZiteStreamInterface;
|
|
96
123
|
} : {})) => Promise<TOutput> | TOutput;
|
|
@@ -102,4 +129,4 @@ export interface EndpointConfig<TInput = unknown, TOutput = unknown, TStream ext
|
|
|
102
129
|
* field could be missing and the endpoint ran anyway. Parsing here is also what
|
|
103
130
|
* makes `TRawInput` -> `TInput` (defaults, transforms) true at runtime.
|
|
104
131
|
*/
|
|
105
|
-
export declare function createEndpoint<TInput = unknown, TOutput = unknown, TStream extends boolean = false, TSchedule extends ZiteSchedule | undefined = undefined, TWebhook extends ZiteWebhook | undefined = undefined, TRawInput = TInput>(config: EndpointConfig<TInput, TOutput, TStream, TSchedule, TWebhook, TRawInput>): EndpointConfig<TInput, TOutput, TStream, TSchedule, TWebhook, TRawInput>;
|
|
132
|
+
export declare function createEndpoint<TInput = unknown, TOutput = unknown, TStream extends boolean = false, TSchedule extends ZiteSchedule | undefined = undefined, TWebhook extends ZiteWebhook | undefined = undefined, TRawInput = TInput, TTrigger extends ZiteTrigger | undefined = undefined>(config: EndpointConfig<TInput, TOutput, TStream, TSchedule, TWebhook, TRawInput, TTrigger>): EndpointConfig<TInput, TOutput, TStream, TSchedule, TWebhook, TRawInput, TTrigger>;
|
|
@@ -32,7 +32,7 @@ class ZiteError extends Error {
|
|
|
32
32
|
}
|
|
33
33
|
exports.ZiteError = ZiteError;
|
|
34
34
|
/** Injected by the runner on a platform-fired run — see `isPlatformTriggeredInput`. */
|
|
35
|
-
const PLATFORM_TRIGGER_KEYS = ["__cron", "__webhook"];
|
|
35
|
+
const PLATFORM_TRIGGER_KEYS = ["__cron", "__webhook", "__poll"];
|
|
36
36
|
function isPlatformTriggeredInput(input) {
|
|
37
37
|
if (typeof input !== "object" || input === null)
|
|
38
38
|
return false;
|
|
@@ -60,7 +60,7 @@ function describeIssues(error) {
|
|
|
60
60
|
*/
|
|
61
61
|
function createEndpoint(config) {
|
|
62
62
|
const { inputSchema, execute } = config;
|
|
63
|
-
const firesWithoutARequest = Boolean(config.schedule || config.webhook);
|
|
63
|
+
const firesWithoutARequest = Boolean(config.schedule || config.webhook || config.trigger);
|
|
64
64
|
// An `inputSchema` that isn't a validator stays inert, as it was.
|
|
65
65
|
if (!inputSchema || typeof inputSchema.parse !== "function")
|
|
66
66
|
return config;
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
*
|
|
9
9
|
* Usage:
|
|
10
10
|
* npx zitejs bundle # bundle all endpoints
|
|
11
|
-
* npx zitejs bundle --app admin-panel # bundle endpoints for
|
|
11
|
+
* npx zitejs bundle --app admin-panel # bundle endpoints for one app or automation, by dir name
|
|
12
12
|
* npx zitejs bundle --script <path> # bundle a one-off script
|
|
13
13
|
*
|
|
14
14
|
* Output: JSON to stdout
|
package/dist/cjs/bundle/index.js
CHANGED
|
@@ -45,7 +45,7 @@ exports.runBundle = runBundle;
|
|
|
45
45
|
*
|
|
46
46
|
* Usage:
|
|
47
47
|
* npx zitejs bundle # bundle all endpoints
|
|
48
|
-
* npx zitejs bundle --app admin-panel # bundle endpoints for
|
|
48
|
+
* npx zitejs bundle --app admin-panel # bundle endpoints for one app or automation, by dir name
|
|
49
49
|
* npx zitejs bundle --script <path> # bundle a one-off script
|
|
50
50
|
*
|
|
51
51
|
* Output: JSON to stdout
|
|
@@ -61,6 +61,7 @@ const path = __importStar(require("path"));
|
|
|
61
61
|
const fs = __importStar(require("fs"));
|
|
62
62
|
const parser_1 = require("@babel/parser");
|
|
63
63
|
const node_module_1 = require("node:module");
|
|
64
|
+
const sourceRoots_js_1 = require("../sourceRoots.js");
|
|
64
65
|
// workerd's `nodejs_compat` does not provide these. Left external they bundle
|
|
65
66
|
// fine and then kill the worker at load time with `No such module`; excluded,
|
|
66
67
|
// esbuild fails the one endpoint with a resolvable error instead. Pinned by
|
|
@@ -615,7 +616,10 @@ async function runBundle() {
|
|
|
615
616
|
const appFlag = args.indexOf('--app');
|
|
616
617
|
let baseDir = process.cwd();
|
|
617
618
|
if (appFlag !== -1 && args[appFlag + 1]) {
|
|
618
|
-
|
|
619
|
+
const name = args[appFlag + 1];
|
|
620
|
+
// A dir that exists under no root still resolves under `apps/`, so the
|
|
621
|
+
// error names the path a caller expects rather than "not found".
|
|
622
|
+
baseDir = path.resolve(baseDir, (0, sourceRoots_js_1.findSourceDir)(name, baseDir)?.path ?? path.join('apps', name));
|
|
619
623
|
}
|
|
620
624
|
// If explicit endpoint names passed, use those; otherwise find all.
|
|
621
625
|
// Skipping `--app`'s VALUE as well as the flag: it is a positional arg, so
|
package/dist/cjs/check/index.js
CHANGED
|
@@ -4,14 +4,7 @@ exports.runCheck = runCheck;
|
|
|
4
4
|
const child_process_1 = require("child_process");
|
|
5
5
|
const fs_1 = require("fs");
|
|
6
6
|
const path_1 = require("path");
|
|
7
|
-
|
|
8
|
-
const appsDir = 'apps';
|
|
9
|
-
if (!(0, fs_1.existsSync)(appsDir))
|
|
10
|
-
return [];
|
|
11
|
-
return (0, fs_1.readdirSync)(appsDir, { withFileTypes: true })
|
|
12
|
-
.filter(d => d.isDirectory())
|
|
13
|
-
.map(d => d.name);
|
|
14
|
-
}
|
|
7
|
+
const sourceRoots_js_1 = require("../sourceRoots.js");
|
|
15
8
|
/**
|
|
16
9
|
* An argument array, not a command string, so no shell is involved.
|
|
17
10
|
*
|
|
@@ -66,15 +59,14 @@ function bundleFailures(output) {
|
|
|
66
59
|
return failures;
|
|
67
60
|
}
|
|
68
61
|
async function runCheck() {
|
|
69
|
-
const appDirs =
|
|
62
|
+
const appDirs = (0, sourceRoots_js_1.listSourceDirs)();
|
|
70
63
|
if (appDirs.length === 0) {
|
|
71
|
-
console.error('No apps found
|
|
64
|
+
console.error('No apps or automations found under apps/ or automations/.');
|
|
72
65
|
process.exit(1);
|
|
73
66
|
}
|
|
74
67
|
let allPassed = true;
|
|
75
|
-
for (const app of appDirs) {
|
|
76
|
-
|
|
77
|
-
console.log(`\n── ${app} ──`);
|
|
68
|
+
for (const { dir: app, path: appPath } of appDirs) {
|
|
69
|
+
console.log(`\n── ${appPath} ──`);
|
|
78
70
|
// Only tsconfig.app.json compiles anything. The app's tsconfig.json is a
|
|
79
71
|
// solution-style config — `"files": []` plus a reference — so
|
|
80
72
|
// `tsc --noEmit -p tsconfig.json` type-checks zero files and exits 0. It
|
package/dist/cjs/cli.js
CHANGED
|
@@ -73,8 +73,8 @@ async function main() {
|
|
|
73
73
|
console.error('Commands:');
|
|
74
74
|
console.error(' sync Generate .zite/db.ts from database schema (single-app)');
|
|
75
75
|
console.error(' dev Run sync then watch for changes (like npx convex dev)');
|
|
76
|
-
console.error(' generate
|
|
77
|
-
console.error(' check Run tsc --noEmit and vite build for
|
|
76
|
+
console.error(' generate Regenerate every app and automation .zite/ (monorepo)');
|
|
77
|
+
console.error(' check Run tsc --noEmit (and vite build where there is one) for every app and automation');
|
|
78
78
|
console.error(' bundle Bundle src/api/*.ts endpoints for cloudflare-lambda');
|
|
79
79
|
process.exit(1);
|
|
80
80
|
}
|
package/dist/cjs/dev/index.js
CHANGED
|
@@ -5,6 +5,7 @@ exports.runDev = runDev;
|
|
|
5
5
|
const fs_1 = require("fs");
|
|
6
6
|
const fs_2 = require("fs");
|
|
7
7
|
const path_1 = require("path");
|
|
8
|
+
const sourceRoots_js_1 = require("../sourceRoots.js");
|
|
8
9
|
const index_js_1 = require("../sync/index.js");
|
|
9
10
|
const lib_js_1 = require("../sync/lib.js");
|
|
10
11
|
const debounceTimers = new Map();
|
|
@@ -14,17 +15,9 @@ function debounce(key, fn, ms) {
|
|
|
14
15
|
clearTimeout(existing);
|
|
15
16
|
debounceTimers.set(key, setTimeout(fn, ms));
|
|
16
17
|
}
|
|
17
|
-
function findAppDirs() {
|
|
18
|
-
const appsDir = "apps";
|
|
19
|
-
if (!(0, fs_2.existsSync)(appsDir))
|
|
20
|
-
return [];
|
|
21
|
-
return (0, fs_2.readdirSync)(appsDir, { withFileTypes: true })
|
|
22
|
-
.filter((d) => d.isDirectory())
|
|
23
|
-
.map((d) => d.name);
|
|
24
|
-
}
|
|
25
18
|
function getFlowId(appDir) {
|
|
26
19
|
try {
|
|
27
|
-
const configPath = (0, path_1.join)(
|
|
20
|
+
const configPath = (0, path_1.join)(appDir.path, "zite.config.json");
|
|
28
21
|
if ((0, fs_2.existsSync)(configPath)) {
|
|
29
22
|
const config = JSON.parse((0, fs_2.readFileSync)(configPath, "utf-8"));
|
|
30
23
|
return config.id;
|
|
@@ -33,28 +26,22 @@ function getFlowId(appDir) {
|
|
|
33
26
|
catch { }
|
|
34
27
|
return undefined;
|
|
35
28
|
}
|
|
36
|
-
|
|
37
|
-
* Find the connected email integration's key in an app's zite.config.json,
|
|
38
|
-
* if any. The key is the integrationId used by the runtime SDK bridge.
|
|
39
|
-
*/
|
|
40
|
-
function getEmailIntegrationId(appDir) {
|
|
29
|
+
const readJsonFile = (path) => {
|
|
41
30
|
try {
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
const config = JSON.parse((0, fs_2.readFileSync)(configPath, "utf-8"));
|
|
46
|
-
const integrations = config.integrations ?? {};
|
|
47
|
-
for (const [id, int] of Object.entries(integrations)) {
|
|
48
|
-
if (int?.type === "email")
|
|
49
|
-
return id;
|
|
50
|
-
}
|
|
31
|
+
return (0, fs_2.existsSync)(path)
|
|
32
|
+
? JSON.parse((0, fs_2.readFileSync)(path, "utf-8"))
|
|
33
|
+
: undefined;
|
|
51
34
|
}
|
|
52
|
-
catch {
|
|
53
|
-
|
|
35
|
+
catch {
|
|
36
|
+
return undefined;
|
|
37
|
+
}
|
|
38
|
+
};
|
|
39
|
+
function getEmailIntegrationId(appDir) {
|
|
40
|
+
return (0, lib_js_1.findEmailIntegrationId)(readJsonFile((0, path_1.join)(appDir.path, "zite.config.json")), readJsonFile("zite.config.json"));
|
|
54
41
|
}
|
|
55
42
|
function getDeclaredEnvVarNames(appDir) {
|
|
56
43
|
try {
|
|
57
|
-
const configPath = (0, path_1.join)(
|
|
44
|
+
const configPath = (0, path_1.join)(appDir.path, "zite.config.json");
|
|
58
45
|
if (!(0, fs_2.existsSync)(configPath))
|
|
59
46
|
return [];
|
|
60
47
|
const config = JSON.parse((0, fs_2.readFileSync)(configPath, "utf-8"));
|
|
@@ -65,7 +52,7 @@ function getDeclaredEnvVarNames(appDir) {
|
|
|
65
52
|
}
|
|
66
53
|
}
|
|
67
54
|
function regenerateAppTypedWrappers(appDir) {
|
|
68
|
-
const outDir = (0, path_1.join)(
|
|
55
|
+
const outDir = (0, path_1.join)(appDir.path, ".zite");
|
|
69
56
|
(0, fs_2.mkdirSync)(outDir, { recursive: true });
|
|
70
57
|
// user.ts and auth.ts no longer generated — User type is fixed in zitejs/auth
|
|
71
58
|
// Email integration: generate the Email client at .zite/integrations/email.ts.
|
|
@@ -80,7 +67,7 @@ function regenerateAppTypedWrappers(appDir) {
|
|
|
80
67
|
(0, fs_2.writeFileSync)((0, path_1.join)(outDir, "backend.ts"), (0, lib_js_1.generateBackendWrapperTs)(getDeclaredEnvVarNames(appDir)));
|
|
81
68
|
}
|
|
82
69
|
function regenerateAppApiTs(appDir) {
|
|
83
|
-
const apiDir = (0, path_1.join)(
|
|
70
|
+
const apiDir = (0, path_1.join)(appDir.path, "src", "api");
|
|
84
71
|
if (!(0, fs_2.existsSync)(apiDir))
|
|
85
72
|
return;
|
|
86
73
|
// Sorted because `readdir` order is unspecified — it is whatever the
|
|
@@ -100,14 +87,14 @@ function regenerateAppApiTs(appDir) {
|
|
|
100
87
|
}));
|
|
101
88
|
const content = (0, lib_js_1.generateApiTs)(endpointFiles);
|
|
102
89
|
if (content) {
|
|
103
|
-
const outDir = (0, path_1.join)(
|
|
90
|
+
const outDir = (0, path_1.join)(appDir.path, ".zite");
|
|
104
91
|
(0, fs_2.mkdirSync)(outDir, { recursive: true });
|
|
105
92
|
(0, fs_2.writeFileSync)((0, path_1.join)(outDir, "api.ts"), content);
|
|
106
|
-
console.log(`Updated
|
|
93
|
+
console.log(`Updated ${appDir.path}/.zite/api.ts`);
|
|
107
94
|
}
|
|
108
95
|
}
|
|
109
96
|
function regenerateAppAirtableSdk(appDir) {
|
|
110
|
-
const lockPath = (0, path_1.join)(
|
|
97
|
+
const lockPath = (0, path_1.join)(appDir.path, "zite.lock");
|
|
111
98
|
console.log(`[airtable-sdk] Checking ${lockPath} exists: ${(0, fs_2.existsSync)(lockPath)}`);
|
|
112
99
|
if (!(0, fs_2.existsSync)(lockPath))
|
|
113
100
|
return;
|
|
@@ -128,15 +115,15 @@ function regenerateAppAirtableSdk(appDir) {
|
|
|
128
115
|
};
|
|
129
116
|
const content = (0, lib_js_1.generateAirtableTs)(airtableLock);
|
|
130
117
|
if (content) {
|
|
131
|
-
const outDir = (0, path_1.join)(
|
|
118
|
+
const outDir = (0, path_1.join)(appDir.path, ".zite", "integrations");
|
|
132
119
|
(0, fs_2.mkdirSync)(outDir, { recursive: true });
|
|
133
120
|
(0, fs_2.writeFileSync)((0, path_1.join)(outDir, "airtable.ts"), content);
|
|
134
|
-
console.log(`Updated
|
|
121
|
+
console.log(`Updated ${appDir.path}/.zite/integrations/airtable.ts`);
|
|
135
122
|
}
|
|
136
123
|
}
|
|
137
124
|
}
|
|
138
125
|
catch (err) {
|
|
139
|
-
console.error(`[airtable-sdk] Error processing lock for ${appDir}:`, err);
|
|
126
|
+
console.error(`[airtable-sdk] Error processing lock for ${appDir.path}:`, err);
|
|
140
127
|
}
|
|
141
128
|
}
|
|
142
129
|
async function runGenerate() {
|
|
@@ -160,8 +147,8 @@ async function runGenerate() {
|
|
|
160
147
|
catch (err) {
|
|
161
148
|
console.warn("DB SDK generation failed:", err instanceof Error ? err.message : err);
|
|
162
149
|
}
|
|
163
|
-
// 2. Find
|
|
164
|
-
const appDirs =
|
|
150
|
+
// 2. Find every app and automation and regenerate their .zite/ files
|
|
151
|
+
const appDirs = (0, sourceRoots_js_1.listSourceDirs)();
|
|
165
152
|
for (const app of appDirs) {
|
|
166
153
|
regenerateAppApiTs(app);
|
|
167
154
|
regenerateAppTypedWrappers(app);
|
|
@@ -181,33 +168,33 @@ async function runDev() {
|
|
|
181
168
|
console.warn("Initial sync failed (continuing with watcher):", err instanceof Error ? err.message : err);
|
|
182
169
|
}
|
|
183
170
|
console.log("");
|
|
184
|
-
// 2. Find
|
|
185
|
-
const appDirs =
|
|
171
|
+
// 2. Find every app and automation and regenerate their .zite/ files
|
|
172
|
+
const appDirs = (0, sourceRoots_js_1.listSourceDirs)();
|
|
186
173
|
for (const app of appDirs) {
|
|
187
174
|
regenerateAppApiTs(app);
|
|
188
175
|
regenerateAppTypedWrappers(app);
|
|
189
176
|
}
|
|
190
|
-
// 3. Watch each
|
|
177
|
+
// 3. Watch each dir's src/api/ for endpoint changes
|
|
191
178
|
let watchingAny = false;
|
|
192
179
|
for (const app of appDirs) {
|
|
193
|
-
const apiDir = (0, path_1.join)(
|
|
180
|
+
const apiDir = (0, path_1.join)(app.path, "src", "api");
|
|
194
181
|
if (!(0, fs_2.existsSync)(apiDir))
|
|
195
182
|
continue;
|
|
196
183
|
watchingAny = true;
|
|
197
|
-
console.log(`Watching
|
|
184
|
+
console.log(`Watching ${app.path}/src/api/ for endpoint changes...`);
|
|
198
185
|
(0, fs_1.watch)(apiDir, { recursive: true }, (_event, filename) => {
|
|
199
186
|
if (!filename)
|
|
200
187
|
return;
|
|
201
188
|
if (!filename.endsWith(".ts") && !filename.endsWith(".js"))
|
|
202
189
|
return;
|
|
203
|
-
debounce(app, () => {
|
|
204
|
-
console.log(`Endpoint changed in ${app}: ${filename}`);
|
|
190
|
+
debounce(app.path, () => {
|
|
191
|
+
console.log(`Endpoint changed in ${app.path}: ${filename}`);
|
|
205
192
|
regenerateAppApiTs(app);
|
|
206
193
|
}, 200);
|
|
207
194
|
});
|
|
208
195
|
}
|
|
209
196
|
if (!watchingAny) {
|
|
210
|
-
console.log("No apps with src/api/ found.");
|
|
197
|
+
console.log("No apps or automations with src/api/ found.");
|
|
211
198
|
}
|
|
212
199
|
// 4. Watch zite.schema.json for schema drift
|
|
213
200
|
if ((0, fs_2.existsSync)("zite.schema.json")) {
|
|
@@ -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;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The repo-root directories a project's own source lives under: `apps/` for
|
|
3
|
+
* apps and `automations/` for automations (endpoints with no frontend). The
|
|
4
|
+
* backend keeps the same list; a dir name is unique across both roots, so a
|
|
5
|
+
* bare name still identifies one dir.
|
|
6
|
+
*/
|
|
7
|
+
export declare const SOURCE_ROOTS: readonly ["apps", "automations"];
|
|
8
|
+
export type SourceRoot = (typeof SOURCE_ROOTS)[number];
|
|
9
|
+
export interface SourceDir {
|
|
10
|
+
root: SourceRoot;
|
|
11
|
+
/** The bare directory name. */
|
|
12
|
+
dir: string;
|
|
13
|
+
/** `<root>/<dir>`, relative to the repo root. */
|
|
14
|
+
path: string;
|
|
15
|
+
}
|
|
16
|
+
/** Every source dir under every root, in root order then name order. */
|
|
17
|
+
export declare function listSourceDirs(cwd?: string): SourceDir[];
|
|
18
|
+
/** The source dir with this bare name, under whichever root holds it. */
|
|
19
|
+
export declare function findSourceDir(name: string, cwd?: string): SourceDir | undefined;
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.SOURCE_ROOTS = void 0;
|
|
4
|
+
exports.listSourceDirs = listSourceDirs;
|
|
5
|
+
exports.findSourceDir = findSourceDir;
|
|
6
|
+
const fs_1 = require("fs");
|
|
7
|
+
const path_1 = require("path");
|
|
8
|
+
/**
|
|
9
|
+
* The repo-root directories a project's own source lives under: `apps/` for
|
|
10
|
+
* apps and `automations/` for automations (endpoints with no frontend). The
|
|
11
|
+
* backend keeps the same list; a dir name is unique across both roots, so a
|
|
12
|
+
* bare name still identifies one dir.
|
|
13
|
+
*/
|
|
14
|
+
exports.SOURCE_ROOTS = ["apps", "automations"];
|
|
15
|
+
/** Every source dir under every root, in root order then name order. */
|
|
16
|
+
function listSourceDirs(cwd = ".") {
|
|
17
|
+
const dirs = [];
|
|
18
|
+
for (const root of exports.SOURCE_ROOTS) {
|
|
19
|
+
const rootPath = (0, path_1.join)(cwd, root);
|
|
20
|
+
if (!(0, fs_1.existsSync)(rootPath))
|
|
21
|
+
continue;
|
|
22
|
+
for (const entry of (0, fs_1.readdirSync)(rootPath, { withFileTypes: true })) {
|
|
23
|
+
if (!entry.isDirectory())
|
|
24
|
+
continue;
|
|
25
|
+
dirs.push({ root, dir: entry.name, path: (0, path_1.join)(root, entry.name) });
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
return dirs;
|
|
29
|
+
}
|
|
30
|
+
/** The source dir with this bare name, under whichever root holds it. */
|
|
31
|
+
function findSourceDir(name, cwd = ".") {
|
|
32
|
+
return listSourceDirs(cwd).find((d) => d.dir === name);
|
|
33
|
+
}
|
package/dist/cjs/sync/lib.d.ts
CHANGED
|
@@ -82,6 +82,12 @@ export declare function normalizeAirtableLockNames(lock: AirtableLock): {
|
|
|
82
82
|
};
|
|
83
83
|
export declare function generateAirtableTs(inputLock: AirtableLock): string | null;
|
|
84
84
|
export declare function generateBackendWrapperTs(envVarNames?: string[]): string;
|
|
85
|
+
/**
|
|
86
|
+
* The key of the email integration an app sends through, which is the
|
|
87
|
+
* integrationId the runtime SDK bridge dispatches on. The app's own entry wins;
|
|
88
|
+
* otherwise it is the workspace email the app has `integrationSettings` for.
|
|
89
|
+
*/
|
|
90
|
+
export declare function findEmailIntegrationId(appConfig: unknown, workspaceConfig: unknown): string | undefined;
|
|
85
91
|
/**
|
|
86
92
|
* Generate `.zite/integrations/email.ts` — the `Email` client for an app with
|
|
87
93
|
* an email integration connected. Mirrors the airtable SDK generation: a thin
|