@mondaydotcomorg/z2h-cli 0.29.5 → 0.31.0
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/backend/handlers.d.ts +3 -0
- package/dist/backend/handlers.d.ts.map +1 -1
- package/dist/backend/handlers.js +7 -4
- package/dist/backend/parser/__tests__/ast.test.d.ts.map +1 -0
- package/dist/backend/parser/__tests__/parse.test.d.ts.map +1 -0
- package/dist/backend/parser/api-signatures.d.ts +4 -0
- package/dist/backend/parser/api-signatures.d.ts.map +1 -0
- package/dist/backend/parser/api-signatures.js +31 -0
- package/dist/backend/parser/api-usage.d.ts +5 -0
- package/dist/backend/parser/api-usage.d.ts.map +1 -0
- package/dist/backend/parser/api-usage.js +61 -0
- package/dist/backend/parser/bindings.d.ts +5 -0
- package/dist/backend/parser/bindings.d.ts.map +1 -0
- package/dist/backend/parser/bindings.js +84 -0
- package/dist/backend/parser/handler-declaration.d.ts.map +1 -0
- package/dist/backend/parser/member-path.d.ts +3 -0
- package/dist/backend/parser/member-path.d.ts.map +1 -0
- package/dist/backend/parser/member-path.js +31 -0
- package/dist/backend/parser/messages.d.ts.map +1 -0
- package/dist/backend/parser/parse.d.ts.map +1 -0
- package/dist/backend/{parse.js → parser/parse.js} +9 -9
- package/dist/backend/parser/static-value.d.ts +6 -0
- package/dist/backend/parser/static-value.d.ts.map +1 -0
- package/dist/backend/parser/static-value.js +117 -0
- package/dist/backend/parser/types.d.ts +53 -0
- package/dist/backend/parser/types.d.ts.map +1 -0
- package/dist/backend/parser/types.js +1 -0
- package/dist/backend/parser/utils.d.ts +19 -0
- package/dist/backend/parser/utils.d.ts.map +1 -0
- package/dist/backend/parser/utils.js +97 -0
- package/dist/backend/validate.d.ts +3 -3
- package/dist/backend/validate.d.ts.map +1 -1
- package/dist/backend/validate.js +18 -18
- package/dist/commands/backend.d.ts +2 -13
- package/dist/commands/backend.d.ts.map +1 -1
- package/dist/commands/backend.js +30 -21
- package/dist/commands/create.d.ts.map +1 -1
- package/dist/commands/create.js +1 -0
- package/dist/commands/deploy.d.ts.map +1 -1
- package/dist/commands/deploy.js +21 -10
- package/dist/commands/generate.d.ts.map +1 -1
- package/dist/commands/generate.js +6 -0
- package/dist/esm/backend/handlers.d.ts +3 -0
- package/dist/esm/backend/handlers.d.ts.map +1 -1
- package/dist/esm/backend/handlers.mjs +7 -4
- package/dist/esm/backend/parser/__tests__/ast.test.d.ts.map +1 -0
- package/dist/esm/backend/parser/__tests__/parse.test.d.ts.map +1 -0
- package/dist/esm/backend/parser/api-signatures.d.ts +4 -0
- package/dist/esm/backend/parser/api-signatures.d.ts.map +1 -0
- package/dist/esm/backend/parser/api-signatures.mjs +24 -0
- package/dist/esm/backend/parser/api-usage.d.ts +5 -0
- package/dist/esm/backend/parser/api-usage.d.ts.map +1 -0
- package/dist/esm/backend/parser/api-usage.mjs +58 -0
- package/dist/esm/backend/parser/bindings.d.ts +5 -0
- package/dist/esm/backend/parser/bindings.d.ts.map +1 -0
- package/dist/esm/backend/parser/bindings.mjs +81 -0
- package/dist/esm/backend/parser/handler-declaration.d.ts.map +1 -0
- package/dist/esm/backend/parser/member-path.d.ts +3 -0
- package/dist/esm/backend/parser/member-path.d.ts.map +1 -0
- package/dist/esm/backend/parser/member-path.mjs +29 -0
- package/dist/esm/backend/parser/messages.d.ts.map +1 -0
- package/dist/esm/backend/parser/parse.d.ts.map +1 -0
- package/dist/esm/backend/{parse.mjs → parser/parse.mjs} +1 -1
- package/dist/esm/backend/parser/static-value.d.ts +6 -0
- package/dist/esm/backend/parser/static-value.d.ts.map +1 -0
- package/dist/esm/backend/parser/static-value.mjs +114 -0
- package/dist/esm/backend/parser/types.d.ts +53 -0
- package/dist/esm/backend/parser/types.d.ts.map +1 -0
- package/dist/esm/backend/parser/types.mjs +1 -0
- package/dist/esm/backend/parser/utils.d.ts +19 -0
- package/dist/esm/backend/parser/utils.d.ts.map +1 -0
- package/dist/esm/backend/parser/utils.mjs +88 -0
- package/dist/esm/backend/validate.d.ts +3 -3
- package/dist/esm/backend/validate.d.ts.map +1 -1
- package/dist/esm/backend/validate.mjs +8 -8
- package/dist/esm/commands/backend.d.ts +2 -13
- package/dist/esm/commands/backend.d.ts.map +1 -1
- package/dist/esm/commands/backend.mjs +31 -22
- package/dist/esm/commands/create.d.ts.map +1 -1
- package/dist/esm/commands/create.mjs +1 -0
- package/dist/esm/commands/deploy.d.ts.map +1 -1
- package/dist/esm/commands/deploy.mjs +23 -11
- package/dist/esm/commands/generate.d.ts.map +1 -1
- package/dist/esm/commands/generate.mjs +8 -2
- package/dist/esm/templates/app/usage.mjs +5 -0
- package/dist/esm/util/broker/app.d.ts +2 -0
- package/dist/esm/util/broker/app.d.ts.map +1 -1
- package/dist/esm/util/broker/app.mjs +4 -4
- package/dist/esm/util/machine-identity.d.ts +2 -3
- package/dist/esm/util/machine-identity.d.ts.map +1 -1
- package/dist/esm/util/machine-identity.mjs +7 -4
- package/dist/templates/app/usage.js +7 -0
- package/dist/util/broker/app.d.ts +2 -0
- package/dist/util/broker/app.d.ts.map +1 -1
- package/dist/util/broker/app.js +4 -4
- package/dist/util/machine-identity.d.ts +2 -3
- package/dist/util/machine-identity.d.ts.map +1 -1
- package/dist/util/machine-identity.js +11 -3
- package/handler-api/backend-runner/channels/snowflake-channel/run-query.ts +11 -14
- package/handler-api/signatures.json +26 -0
- package/package.json +1 -1
- package/src/backend/__tests__/handlers.test.ts +13 -2
- package/src/backend/__tests__/validate.test.ts +54 -0
- package/src/backend/handlers.ts +10 -5
- package/src/backend/parser/__tests__/ast.test.ts +252 -0
- package/src/backend/{__tests__ → parser/__tests__}/parse.test.ts +2 -2
- package/src/backend/parser/api-signatures.ts +23 -0
- package/src/backend/parser/api-usage.ts +73 -0
- package/src/backend/parser/bindings.ts +87 -0
- package/src/backend/parser/member-path.ts +31 -0
- package/src/backend/{parse.ts → parser/parse.ts} +1 -1
- package/src/backend/parser/static-value.ts +145 -0
- package/src/backend/parser/types.ts +66 -0
- package/src/backend/parser/utils.ts +106 -0
- package/src/backend/validate.ts +12 -8
- package/src/commands/__tests__/backend-deploy.test.ts +70 -5
- package/src/commands/__tests__/backend-validate.test.ts +11 -1
- package/src/commands/__tests__/create.test.ts +1 -0
- package/src/commands/__tests__/deploy.test.ts +28 -0
- package/src/commands/backend.ts +31 -20
- package/src/commands/create.ts +1 -0
- package/src/commands/deploy.ts +29 -12
- package/src/commands/generate.ts +8 -1
- package/src/templates/app/usage.json +1 -0
- package/src/util/broker/app.ts +17 -4
- package/src/util/machine-identity.ts +7 -3
- package/dist/backend/__tests__/ast.test.d.ts.map +0 -1
- package/dist/backend/__tests__/parse.test.d.ts.map +0 -1
- package/dist/backend/ast.d.ts +0 -39
- package/dist/backend/ast.d.ts.map +0 -1
- package/dist/backend/ast.js +0 -149
- package/dist/backend/handler-declaration.d.ts.map +0 -1
- package/dist/backend/messages.d.ts.map +0 -1
- package/dist/backend/parse.d.ts.map +0 -1
- package/dist/esm/backend/__tests__/ast.test.d.ts.map +0 -1
- package/dist/esm/backend/__tests__/parse.test.d.ts.map +0 -1
- package/dist/esm/backend/ast.d.ts +0 -39
- package/dist/esm/backend/ast.d.ts.map +0 -1
- package/dist/esm/backend/ast.mjs +0 -144
- package/dist/esm/backend/handler-declaration.d.ts.map +0 -1
- package/dist/esm/backend/messages.d.ts.map +0 -1
- package/dist/esm/backend/parse.d.ts.map +0 -1
- package/src/backend/__tests__/ast.test.ts +0 -53
- package/src/backend/ast.ts +0 -201
- /package/dist/backend/{__tests__ → parser/__tests__}/ast.test.d.ts +0 -0
- /package/dist/backend/{__tests__ → parser/__tests__}/parse.test.d.ts +0 -0
- /package/dist/backend/{handler-declaration.d.ts → parser/handler-declaration.d.ts} +0 -0
- /package/dist/backend/{handler-declaration.js → parser/handler-declaration.js} +0 -0
- /package/dist/backend/{messages.d.ts → parser/messages.d.ts} +0 -0
- /package/dist/backend/{messages.js → parser/messages.js} +0 -0
- /package/dist/backend/{parse.d.ts → parser/parse.d.ts} +0 -0
- /package/dist/esm/backend/{__tests__ → parser/__tests__}/ast.test.d.ts +0 -0
- /package/dist/esm/backend/{__tests__ → parser/__tests__}/parse.test.d.ts +0 -0
- /package/dist/esm/backend/{handler-declaration.d.ts → parser/handler-declaration.d.ts} +0 -0
- /package/dist/esm/backend/{handler-declaration.mjs → parser/handler-declaration.mjs} +0 -0
- /package/dist/esm/backend/{messages.d.ts → parser/messages.d.ts} +0 -0
- /package/dist/esm/backend/{messages.mjs → parser/messages.mjs} +0 -0
- /package/dist/esm/backend/{parse.d.ts → parser/parse.d.ts} +0 -0
- /package/src/backend/{handler-declaration.ts → parser/handler-declaration.ts} +0 -0
- /package/src/backend/{messages.ts → parser/messages.ts} +0 -0
package/src/commands/backend.ts
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import path from 'node:path';
|
|
2
2
|
import { existsSync } from 'node:fs';
|
|
3
|
+
import { readJson, writeJson } from 'fs-extra';
|
|
3
4
|
import { PutObjectCommand } from '@aws-sdk/client-s3';
|
|
4
5
|
import { info, output } from '../util/logger';
|
|
5
6
|
import { mfAppName, getCwdAppName } from '../util/app-name';
|
|
7
|
+
import { whoAmI } from '../util/machine-identity';
|
|
6
8
|
import { readHandlers } from '../backend/handlers';
|
|
7
9
|
import { detectIntegrations } from '../backend/detect-integrations';
|
|
8
10
|
import { getS3Client } from '../util/s3/client';
|
|
@@ -18,24 +20,36 @@ function currentAppName(): string {
|
|
|
18
20
|
return mfAppName(raw);
|
|
19
21
|
}
|
|
20
22
|
|
|
21
|
-
/**
|
|
22
|
-
* True if the app ships an app-level backend — a `backend/handlers/` directory.
|
|
23
|
-
* Callers gate on this so the deploy path is explicit about whether a backend is in
|
|
24
|
-
* play.
|
|
25
|
-
*/
|
|
26
23
|
export function hasHandlers(appDir: string): boolean {
|
|
27
24
|
return existsSync(path.join(appDir, 'backend', 'handlers'));
|
|
28
25
|
}
|
|
29
26
|
|
|
27
|
+
/** Other features may add top-level fields, so writes below merge into this copy instead of replacing it. */
|
|
28
|
+
async function readExistingUsage(appDir: string): Promise<Record<string, unknown>> {
|
|
29
|
+
try {
|
|
30
|
+
return (await readJson(path.join(appDir, 'usage.json'))) as Record<string, unknown>;
|
|
31
|
+
} catch (err) {
|
|
32
|
+
if ((err as { code?: string }).code === 'ENOENT') {
|
|
33
|
+
return {};
|
|
34
|
+
}
|
|
35
|
+
throw err;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/** Keeps the app's git-tracked `usage.json` current with every handler parse (validate or deploy). */
|
|
40
|
+
async function writeUsageJson(appDir: string, patch: Record<string, unknown>): Promise<void> {
|
|
41
|
+
const existing = await readExistingUsage(appDir);
|
|
42
|
+
await writeJson(path.join(appDir, 'usage.json'), { ...existing, ...patch }, { spaces: 2 });
|
|
43
|
+
}
|
|
44
|
+
|
|
30
45
|
/**
|
|
31
|
-
*
|
|
32
|
-
*
|
|
33
|
-
* (or it is empty of sources) so callers can always pass the result to
|
|
34
|
-
* `registerOrUpdateApp` without a separate gate.
|
|
46
|
+
* Returns `[]` when there is no `backend/handlers/` dir (or it is empty of sources)
|
|
47
|
+
* so callers can always pass the result to `registerOrUpdateApp` without a separate gate.
|
|
35
48
|
*/
|
|
36
49
|
async function readDetectAndUpload(
|
|
37
50
|
appDir: string,
|
|
38
51
|
prefix: string,
|
|
52
|
+
appName: string,
|
|
39
53
|
version: number,
|
|
40
54
|
deployedBy: string,
|
|
41
55
|
logLabel: string
|
|
@@ -44,11 +58,12 @@ async function readDetectAndUpload(
|
|
|
44
58
|
return [];
|
|
45
59
|
}
|
|
46
60
|
info(`reading backend handlers ${logLabel}`);
|
|
47
|
-
const { handlers, apiDomains } = await readHandlers(appDir);
|
|
61
|
+
const { handlers, apiDomains, apiUsages } = await readHandlers(appDir);
|
|
48
62
|
const integrations = detectIntegrations(apiDomains);
|
|
49
63
|
if (Object.keys(handlers).length === 0) {
|
|
50
64
|
return integrations;
|
|
51
65
|
}
|
|
66
|
+
await writeUsageJson(appDir, { appName, deployedBy, apiUsages });
|
|
52
67
|
const s3 = getS3Client();
|
|
53
68
|
const meta = JSON.stringify({ version, deployedBy, handlers: Object.keys(handlers) });
|
|
54
69
|
const put = (key: string, body: string, contentType: string) =>
|
|
@@ -65,11 +80,6 @@ async function readDetectAndUpload(
|
|
|
65
80
|
* from their sources. Each `.js` handler is uploaded as its own flat file — no
|
|
66
81
|
* compilation, no bundling, no npm deps.
|
|
67
82
|
*
|
|
68
|
-
* Live and preview differ only in where the handlers land, so that is the only
|
|
69
|
-
* thing `isPreview` switches:
|
|
70
|
-
* - live: `<appName>/backend-<version>` — the app's immutable per-version slot.
|
|
71
|
-
* - preview: `<mfKeyPrefix without /MF>/MS` — beside the preview's `/MF` frontend.
|
|
72
|
-
*
|
|
73
83
|
* Integration sync note: the returned set is re-derived from the CURRENT backend
|
|
74
84
|
* sources on every deploy, and the platform set is reconciled to exactly match
|
|
75
85
|
* it (there is no stored declaration to fall back on). A deploy therefore always
|
|
@@ -88,25 +98,26 @@ export async function deployBackend(opts: {
|
|
|
88
98
|
const prefix = isPreview ? `${mfKeyPrefix.replace(/\/MF$/, '')}/MS` : `${appName}/backend-${version}`;
|
|
89
99
|
const logLabel = isPreview ? 'for preview' : `for "${appName}"`;
|
|
90
100
|
try {
|
|
91
|
-
return await readDetectAndUpload(appDir, prefix, version, deployedBy, logLabel);
|
|
101
|
+
return await readDetectAndUpload(appDir, prefix, appName, version, deployedBy, logLabel);
|
|
92
102
|
} catch (err) {
|
|
93
103
|
throw tagDeployError('deploy_backend_error', err);
|
|
94
104
|
}
|
|
95
105
|
}
|
|
96
106
|
|
|
97
107
|
/**
|
|
98
|
-
*
|
|
99
|
-
*
|
|
100
|
-
* uploading anything. Throws on the first invalid handler.
|
|
108
|
+
* Runs the same checks deploy does against the working tree, refreshing the
|
|
109
|
+
* local `usage.json` — no upload to S3. Throws on the first invalid handler.
|
|
101
110
|
*/
|
|
102
111
|
export async function backendValidateCommand(appDir: string = process.cwd()): Promise<void> {
|
|
103
112
|
if (!hasHandlers(appDir)) {
|
|
104
113
|
output('[z2h-cli] no backend/handlers/ directory — nothing to validate', { handlers: [], integrations: [] });
|
|
105
114
|
return;
|
|
106
115
|
}
|
|
107
|
-
const { handlers, apiDomains } = await readHandlers(appDir);
|
|
116
|
+
const { handlers, apiDomains, apiUsages } = await readHandlers(appDir);
|
|
108
117
|
const names = Object.keys(handlers).sort();
|
|
109
118
|
const integrations = detectIntegrations(apiDomains);
|
|
119
|
+
const { name } = (await readJson(path.join(appDir, 'package.json'))) as { name?: string };
|
|
120
|
+
await writeUsageJson(appDir, { appName: name ? mfAppName(name) : undefined, deployedBy: whoAmI(), apiUsages });
|
|
110
121
|
const list = (xs: string[]) => (xs.length ? xs.join(', ') : 'none');
|
|
111
122
|
output(`[z2h-cli] ${names.length} handler(s) valid: ${list(names)}\n[z2h-cli] integrations: ${list(integrations)}`, {
|
|
112
123
|
handlers: names,
|
package/src/commands/create.ts
CHANGED
|
@@ -108,6 +108,7 @@ export async function createCommand(appName: string, opts: CreateOptions = {}):
|
|
|
108
108
|
await copy(path.join(appTemplatesDir, 'gitignore'), path.join(appDir, '.gitignore'));
|
|
109
109
|
await copy(path.join(appTemplatesDir, 'claude-settings.json'), path.join(appDir, '.claude', 'settings.json'));
|
|
110
110
|
await copy(path.join(appTemplatesDir, 'CLAUDE.md'), path.join(appDir, 'CLAUDE.md'));
|
|
111
|
+
await copy(path.join(appTemplatesDir, 'usage.json'), path.join(appDir, 'usage.json'));
|
|
111
112
|
|
|
112
113
|
// html-embed: also copy the source HTML.
|
|
113
114
|
if (template === 'html-embed' && opts.htmlFile) {
|
package/src/commands/deploy.ts
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import os from 'node:os';
|
|
2
1
|
import path from 'node:path';
|
|
3
2
|
import { copy, ensureDir, readJson } from 'fs-extra';
|
|
4
3
|
import { info, warn, output, getOutputMode } from '../util/logger';
|
|
@@ -19,8 +18,8 @@ import { getRemoteUrl, guardCleanTree, pullAndResolve, pushToRemote, initRepo }
|
|
|
19
18
|
import { resolveGitEnv } from '../util/git/git-env';
|
|
20
19
|
import { type RemoteType, validateRemoteOptions, resolveRemoteUrl } from '../util/git/remote-options';
|
|
21
20
|
import { setupS3Client } from '../util/s3/client';
|
|
22
|
-
import {
|
|
23
|
-
import { registerOrUpdateApp } from '../util/broker/app';
|
|
21
|
+
import { whoAmI } from '../util/machine-identity';
|
|
22
|
+
import { fetchApp, registerOrUpdateApp } from '../util/broker/app';
|
|
24
23
|
import { openInBrowser } from '../util/open-browser';
|
|
25
24
|
import { resolvePortAndMetadata } from '../shadow/prepare';
|
|
26
25
|
import { DeployError, tagDeployError, grantReasonForStatus } from '../util/errors';
|
|
@@ -30,11 +29,6 @@ import { promptForTags } from './tag';
|
|
|
30
29
|
import type { ConsumerPaths, DeployFailureReason } from '../types';
|
|
31
30
|
import type { ManifestEntry, AssetManifestFile } from '../util/manifest';
|
|
32
31
|
|
|
33
|
-
/** Who is publishing this version — the machine identity, else the OS user. */
|
|
34
|
-
function whoDeployed(): string {
|
|
35
|
-
return getMachineAppName() ?? os.userInfo().username;
|
|
36
|
-
}
|
|
37
|
-
|
|
38
32
|
export interface DeployOptions {
|
|
39
33
|
dryRun?: boolean;
|
|
40
34
|
remote?: RemoteType;
|
|
@@ -106,7 +100,7 @@ async function buildAndStamp(opts: {
|
|
|
106
100
|
} else {
|
|
107
101
|
({ assetManifest } = await buildCommand({ publicUrl: opts.publicUrl }));
|
|
108
102
|
}
|
|
109
|
-
const deployedBy =
|
|
103
|
+
const deployedBy = whoAmI();
|
|
110
104
|
|
|
111
105
|
return {
|
|
112
106
|
...assetManifest,
|
|
@@ -132,8 +126,10 @@ async function uploadAndRegister(opts: {
|
|
|
132
126
|
gitRemote: string;
|
|
133
127
|
isPreview: boolean;
|
|
134
128
|
description?: string;
|
|
129
|
+
masterAppName?: string;
|
|
135
130
|
}): Promise<void> {
|
|
136
|
-
const { paths, keyPrefix, appName, token, nextVersion, entry, gitRemote, isPreview, description } =
|
|
131
|
+
const { paths, keyPrefix, appName, token, nextVersion, entry, gitRemote, isPreview, description, masterAppName } =
|
|
132
|
+
opts;
|
|
137
133
|
|
|
138
134
|
info(`uploading ${isPreview ? 'preview ' : ''}build → s3://${BUCKET_WRITE_NAME}/${keyPrefix}/`);
|
|
139
135
|
await uploadDir(paths.shadowBuild, keyPrefix);
|
|
@@ -146,14 +142,34 @@ async function uploadAndRegister(opts: {
|
|
|
146
142
|
appName,
|
|
147
143
|
mfKeyPrefix: keyPrefix,
|
|
148
144
|
version: nextVersion,
|
|
149
|
-
deployedBy:
|
|
145
|
+
deployedBy: whoAmI(),
|
|
150
146
|
isPreview,
|
|
151
147
|
});
|
|
152
148
|
|
|
153
|
-
await registerOrUpdateApp({
|
|
149
|
+
await registerOrUpdateApp({
|
|
150
|
+
appName,
|
|
151
|
+
token,
|
|
152
|
+
nextVersion,
|
|
153
|
+
entry,
|
|
154
|
+
gitRemote,
|
|
155
|
+
integrations,
|
|
156
|
+
description,
|
|
157
|
+
masterAppName,
|
|
158
|
+
});
|
|
154
159
|
}
|
|
155
160
|
|
|
156
161
|
async function deployPreview({ paths, consumerName, appName, token, opts }: DeployContext): Promise<void> {
|
|
162
|
+
// A preview inherits from the live app it previews, resolved by name server-side —
|
|
163
|
+
// fail fast with an actionable message if that app was never claimed/deployed (e.g. a
|
|
164
|
+
// local checkout scaffolded before `create` started claiming names), rather than
|
|
165
|
+
// letting a deep backend 404 surface as a generic "App registration failed".
|
|
166
|
+
if (!(await fetchApp(appName))) {
|
|
167
|
+
throw new DeployError(
|
|
168
|
+
'register_error',
|
|
169
|
+
`Cannot preview "${appName}": it has never been created or deployed. Run 'z2h-cli create ${consumerName}' (or deploy it once) first.`
|
|
170
|
+
);
|
|
171
|
+
}
|
|
172
|
+
|
|
157
173
|
await ensureDir(paths.shadowDir);
|
|
158
174
|
const { previewId } = await resolvePortAndMetadata(paths, cleanAppName(consumerName));
|
|
159
175
|
|
|
@@ -190,6 +206,7 @@ async function deployPreview({ paths, consumerName, appName, token, opts }: Depl
|
|
|
190
206
|
entry,
|
|
191
207
|
gitRemote: '',
|
|
192
208
|
isPreview: true,
|
|
209
|
+
masterAppName: appName,
|
|
193
210
|
});
|
|
194
211
|
|
|
195
212
|
const previewUrl = `https://bigbrain.me/bigbrain-vibe/${previewSlug}`;
|
package/src/commands/generate.ts
CHANGED
|
@@ -5,7 +5,7 @@ import { execa } from 'execa';
|
|
|
5
5
|
import { pathExists, readdir } from 'fs-extra';
|
|
6
6
|
import { assertWorkspace } from '../util/workspace';
|
|
7
7
|
import { validateAppName, cleanAppName, mfAppName } from '../util/app-name';
|
|
8
|
-
import { fetchApp } from '../util/broker/app';
|
|
8
|
+
import { claimApp, fetchApp } from '../util/broker/app';
|
|
9
9
|
import { patchBuiltBundle, patchOneFile, type PatchedConfig } from '../util/dashboard-templates/patch-bundle';
|
|
10
10
|
import { findTemplate, type DashboardTemplateEntry } from '../util/dashboard-templates/load-catalog';
|
|
11
11
|
import { initRepo, defaultS3Remote } from '../util/git/repo';
|
|
@@ -163,6 +163,13 @@ export async function generateCommand(appName: string, opts: GenerateOptions): P
|
|
|
163
163
|
throw new Error(`An app named "${appName}" already exists in the Z2H registry. Pick a different name.`);
|
|
164
164
|
}
|
|
165
165
|
|
|
166
|
+
// generate skips `create` entirely, but the preview it deploys below still resolves this
|
|
167
|
+
// app's own row by name server-side — claim it now so that lookup finds something, same as
|
|
168
|
+
// `create` does for the normal flow.
|
|
169
|
+
if (!existing) {
|
|
170
|
+
await claimApp(mfAppName(appName), defaultS3Remote(appName));
|
|
171
|
+
}
|
|
172
|
+
|
|
166
173
|
info(`copying template "${template.id}" → ${appDir}`);
|
|
167
174
|
// Excludes node_modules (installed into templateDir itself by build-templates.mjs, never
|
|
168
175
|
// needed by the generated app), .build-shadow (a scratch dir that build-templates.mjs
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{}
|
package/src/util/broker/app.ts
CHANGED
|
@@ -72,12 +72,13 @@ async function registerApp(
|
|
|
72
72
|
visibility: 'public' | 'private',
|
|
73
73
|
gitRemote: string,
|
|
74
74
|
integrations?: string[],
|
|
75
|
-
description?: string
|
|
75
|
+
description?: string,
|
|
76
|
+
masterAppName?: string
|
|
76
77
|
): Promise<void> {
|
|
77
78
|
const res = await fetch(`${brokerBaseUrl()}/z2h-cli/apps/register`, {
|
|
78
79
|
method: 'POST',
|
|
79
80
|
headers: { Authorization: `Bearer ${token}`, 'Content-Type': 'application/json', ...routingHeaders() },
|
|
80
|
-
body: JSON.stringify({ appName, version, entry, visibility, gitRemote, integrations, description }),
|
|
81
|
+
body: JSON.stringify({ appName, version, entry, visibility, gitRemote, integrations, description, masterAppName }),
|
|
81
82
|
});
|
|
82
83
|
if (!res.ok) {
|
|
83
84
|
const text = await res.text();
|
|
@@ -114,6 +115,8 @@ export interface RegisterOrUpdateOptions {
|
|
|
114
115
|
gitRemote: string;
|
|
115
116
|
integrations?: string[];
|
|
116
117
|
description?: string;
|
|
118
|
+
/** For a preview app's first registration, the real app it previews. Ignored past v1. */
|
|
119
|
+
masterAppName?: string;
|
|
117
120
|
}
|
|
118
121
|
|
|
119
122
|
/**
|
|
@@ -123,13 +126,23 @@ export interface RegisterOrUpdateOptions {
|
|
|
123
126
|
* deploy and preview so this branching logic lives in exactly one place.
|
|
124
127
|
*/
|
|
125
128
|
export async function registerOrUpdateApp(opts: RegisterOrUpdateOptions): Promise<void> {
|
|
126
|
-
const { appName, token, nextVersion, entry, gitRemote, integrations, description } = opts;
|
|
129
|
+
const { appName, token, nextVersion, entry, gitRemote, integrations, description, masterAppName } = opts;
|
|
127
130
|
|
|
128
131
|
try {
|
|
129
132
|
if (nextVersion === 1) {
|
|
130
133
|
const visibility = await resolveAppVisibility(appName);
|
|
131
134
|
info(`registering "${appName}" → v${nextVersion} (${visibility})`);
|
|
132
|
-
await registerApp(
|
|
135
|
+
await registerApp(
|
|
136
|
+
appName,
|
|
137
|
+
token,
|
|
138
|
+
nextVersion,
|
|
139
|
+
entry,
|
|
140
|
+
visibility,
|
|
141
|
+
gitRemote,
|
|
142
|
+
integrations,
|
|
143
|
+
description,
|
|
144
|
+
masterAppName
|
|
145
|
+
);
|
|
133
146
|
} else {
|
|
134
147
|
info(`updating "${appName}" → v${nextVersion}`);
|
|
135
148
|
await updateApp(appName, token, nextVersion, entry, gitRemote, integrations, description);
|
|
@@ -1,10 +1,14 @@
|
|
|
1
|
+
import os from 'node:os';
|
|
2
|
+
|
|
1
3
|
/**
|
|
2
4
|
* Returns the machine app name when running as a service (e.g. agent-runner).
|
|
3
5
|
* Available when the process is a monday.com microservice with `APP_NAME` set
|
|
4
|
-
* by the platform runtime.
|
|
5
|
-
*
|
|
6
|
-
* Returns `undefined` for interactive human users (fallback to os.userInfo).
|
|
6
|
+
* by the platform runtime. Returns `undefined` for interactive human users.
|
|
7
7
|
*/
|
|
8
8
|
export function getMachineAppName(): string | undefined {
|
|
9
9
|
return process.env.APP_NAME || undefined;
|
|
10
10
|
}
|
|
11
|
+
|
|
12
|
+
export function whoAmI(): string {
|
|
13
|
+
return getMachineAppName() ?? os.userInfo().username;
|
|
14
|
+
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"ast.test.d.ts","sourceRoot":"","sources":["../../../src/backend/__tests__/ast.test.ts"],"names":[],"mappings":""}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"parse.test.d.ts","sourceRoot":"","sources":["../../../src/backend/__tests__/parse.test.ts"],"names":[],"mappings":""}
|
package/dist/backend/ast.d.ts
DELETED
|
@@ -1,39 +0,0 @@
|
|
|
1
|
-
import type { AnyNode, Expression, Pattern, Program, VariableDeclaration } from 'acorn';
|
|
2
|
-
export interface Declaration {
|
|
3
|
-
kind: VariableDeclaration['kind'];
|
|
4
|
-
init: Expression | null | undefined;
|
|
5
|
-
/**
|
|
6
|
-
* Property path from `init` to this binding: `[]` for `const x = init`,
|
|
7
|
-
* `['a', 'b']` for `const { a: { b: x } } = init`, `undefined` when the value
|
|
8
|
-
* is not a plain property read (array/rest/default patterns).
|
|
9
|
-
*/
|
|
10
|
-
path: string[] | undefined;
|
|
11
|
-
}
|
|
12
|
-
export interface Bindings {
|
|
13
|
-
/** Every `var|let|const <name> = …` in the file, by name. */
|
|
14
|
-
declarations: Map<string, Declaration[]>;
|
|
15
|
-
/** Names whose value cannot be pinned: reassigned, updated, or bound as parameters. */
|
|
16
|
-
unpinnable: Set<string>;
|
|
17
|
-
}
|
|
18
|
-
/** Every identifier a binding pattern introduces (`{ a, b: [c] } = …` → a, c). */
|
|
19
|
-
export declare const patternNames: (pattern: Pattern) => string[];
|
|
20
|
-
export declare function collectBindings(program: Program): Bindings;
|
|
21
|
-
export interface PathResolver {
|
|
22
|
-
/**
|
|
23
|
-
* Dotted path of a member chain, following `const` aliases back to their
|
|
24
|
-
* source: with `const sf = ctx.api.v1.snowflake`, `sf.query` resolves to
|
|
25
|
-
* `ctx.api.v1.snowflake.query`. Destructuring counts too
|
|
26
|
-
* (`const { snowflake: sf } = ctx.api.v1`). `undefined` if any link is dynamic.
|
|
27
|
-
*
|
|
28
|
-
* Only single, never-reassigned, never-shadowed `const` bindings are followed —
|
|
29
|
-
* anything else is left as written, so a `let` alias or a parameter of the same
|
|
30
|
-
* name is never mistaken for the channel. The handler's first parameter is
|
|
31
|
-
* treated as `ctx` even when renamed (`handler(context)` → `context.api.v1.db`
|
|
32
|
-
* resolves as `ctx.api.v1.db`).
|
|
33
|
-
*/
|
|
34
|
-
pathOf(node: AnyNode): string | undefined;
|
|
35
|
-
}
|
|
36
|
-
export declare function createPathResolver(bindings: Bindings, contextParam?: string): PathResolver;
|
|
37
|
-
/** Every `ctx.api.v1.<domain>` the program touches (known or not), through `paths`. */
|
|
38
|
-
export declare function collectApiDomains(program: Program, paths: PathResolver): Set<string>;
|
|
39
|
-
//# sourceMappingURL=ast.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"ast.d.ts","sourceRoot":"","sources":["../../src/backend/ast.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,UAAU,EAAE,OAAO,EAAE,OAAO,EAAE,mBAAmB,EAAE,MAAM,OAAO,CAAC;AAKxF,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,mBAAmB,CAAC,MAAM,CAAC,CAAC;IAClC,IAAI,EAAE,UAAU,GAAG,IAAI,GAAG,SAAS,CAAC;IACpC;;;;OAIG;IACH,IAAI,EAAE,MAAM,EAAE,GAAG,SAAS,CAAC;CAC5B;AAED,MAAM,WAAW,QAAQ;IACvB,6DAA6D;IAC7D,YAAY,EAAE,GAAG,CAAC,MAAM,EAAE,WAAW,EAAE,CAAC,CAAC;IACzC,uFAAuF;IACvF,UAAU,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;CACzB;AA8CD,kFAAkF;AAClF,eAAO,MAAM,YAAY,GAAI,SAAS,OAAO,KAAG,MAAM,EAAmD,CAAC;AAE1G,wBAAgB,eAAe,CAAC,OAAO,EAAE,OAAO,GAAG,QAAQ,CA4C1D;AA2BD,MAAM,WAAW,YAAY;IAC3B;;;;;;;;;;;OAWG;IACH,MAAM,CAAC,IAAI,EAAE,OAAO,GAAG,MAAM,GAAG,SAAS,CAAC;CAC3C;AAED,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,QAAQ,EAAE,YAAY,CAAC,EAAE,MAAM,GAAG,YAAY,CA6B1F;AAED,uFAAuF;AACvF,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,YAAY,GAAG,GAAG,CAAC,MAAM,CAAC,CAWpF"}
|
package/dist/backend/ast.js
DELETED
|
@@ -1,149 +0,0 @@
|
|
|
1
|
-
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
2
|
-
|
|
3
|
-
const acornWalk = require('acorn-walk');
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* Every identifier a binding pattern introduces, with its property path from the
|
|
7
|
-
* pattern's value. `path` is deliberately not defaulted: callers pass `[]` for
|
|
8
|
-
* the root and `undefined` once the pattern stops being a plain property read.
|
|
9
|
-
*/
|
|
10
|
-
function patternBindings(pattern, path) {
|
|
11
|
-
switch (pattern.type) {
|
|
12
|
-
case 'Identifier':
|
|
13
|
-
return [{ name: pattern.name, path }];
|
|
14
|
-
case 'ObjectPattern':
|
|
15
|
-
return pattern.properties.flatMap(p => {
|
|
16
|
-
if (p.type === 'RestElement') {
|
|
17
|
-
return patternBindings(p.argument, undefined);
|
|
18
|
-
}
|
|
19
|
-
const key = propertyKey(p.key, p.computed);
|
|
20
|
-
return patternBindings(p.value, path && key !== undefined ? [...path, key] : undefined);
|
|
21
|
-
});
|
|
22
|
-
case 'ArrayPattern':
|
|
23
|
-
return pattern.elements.flatMap(e => (e ? patternBindings(e, undefined) : []));
|
|
24
|
-
case 'AssignmentPattern':
|
|
25
|
-
return patternBindings(pattern.left, undefined);
|
|
26
|
-
case 'RestElement':
|
|
27
|
-
return patternBindings(pattern.argument, undefined);
|
|
28
|
-
default:
|
|
29
|
-
// MemberExpression targets (`obj.x = …`) bind no names.
|
|
30
|
-
return [];
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
function propertyKey(key, computed) {
|
|
34
|
-
if (key.type === 'Literal' && typeof key.value === 'string') {
|
|
35
|
-
return key.value;
|
|
36
|
-
}
|
|
37
|
-
if (!computed && key.type === 'Identifier') {
|
|
38
|
-
return key.name;
|
|
39
|
-
}
|
|
40
|
-
return undefined;
|
|
41
|
-
}
|
|
42
|
-
/** Every identifier a binding pattern introduces (`{ a, b: [c] } = …` → a, c). */
|
|
43
|
-
const patternNames = (pattern) => patternBindings(pattern, []).map(b => b.name);
|
|
44
|
-
function collectBindings(program) {
|
|
45
|
-
const declarations = new Map();
|
|
46
|
-
const unpinnable = new Set();
|
|
47
|
-
const markUnpinnable = (pattern) => patternNames(pattern).forEach(n => unpinnable.add(n));
|
|
48
|
-
acornWalk.full(program, node => {
|
|
49
|
-
switch (node.type) {
|
|
50
|
-
case 'VariableDeclaration':
|
|
51
|
-
for (const declarator of node.declarations) {
|
|
52
|
-
for (const { name, path } of patternBindings(declarator.id, [])) {
|
|
53
|
-
const list = declarations.get(name) ?? [];
|
|
54
|
-
list.push({ kind: node.kind, init: declarator.init, path });
|
|
55
|
-
declarations.set(name, list);
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
|
-
break;
|
|
59
|
-
case 'AssignmentExpression':
|
|
60
|
-
markUnpinnable(node.left);
|
|
61
|
-
break;
|
|
62
|
-
case 'UpdateExpression':
|
|
63
|
-
if (node.argument.type === 'Identifier') {
|
|
64
|
-
unpinnable.add(node.argument.name);
|
|
65
|
-
}
|
|
66
|
-
break;
|
|
67
|
-
case 'ForInStatement':
|
|
68
|
-
case 'ForOfStatement':
|
|
69
|
-
if (node.left.type !== 'VariableDeclaration') {
|
|
70
|
-
markUnpinnable(node.left);
|
|
71
|
-
}
|
|
72
|
-
break;
|
|
73
|
-
case 'FunctionDeclaration':
|
|
74
|
-
case 'FunctionExpression':
|
|
75
|
-
case 'ArrowFunctionExpression':
|
|
76
|
-
node.params.forEach(markUnpinnable);
|
|
77
|
-
break;
|
|
78
|
-
case 'CatchClause':
|
|
79
|
-
if (node.param) {
|
|
80
|
-
markUnpinnable(node.param);
|
|
81
|
-
}
|
|
82
|
-
break;
|
|
83
|
-
}
|
|
84
|
-
});
|
|
85
|
-
return { declarations, unpinnable };
|
|
86
|
-
}
|
|
87
|
-
/** `a.b.c` / `a['b'].c` → root `a`, parts `[b, c]`; `undefined` if any link is dynamic or the root is not an identifier. */
|
|
88
|
-
function memberChain(node) {
|
|
89
|
-
if (node.type === 'ChainExpression') {
|
|
90
|
-
return memberChain(node.expression);
|
|
91
|
-
}
|
|
92
|
-
const parts = [];
|
|
93
|
-
let cur = node;
|
|
94
|
-
while (cur.type === 'MemberExpression') {
|
|
95
|
-
const key = propertyKey(cur.property, cur.computed);
|
|
96
|
-
if (key === undefined) {
|
|
97
|
-
return undefined;
|
|
98
|
-
}
|
|
99
|
-
parts.unshift(key);
|
|
100
|
-
cur = cur.object;
|
|
101
|
-
}
|
|
102
|
-
return cur.type === 'Identifier' ? { root: cur.name, parts } : undefined;
|
|
103
|
-
}
|
|
104
|
-
function createPathResolver(bindings, contextParam) {
|
|
105
|
-
function resolveChain(node, resolving) {
|
|
106
|
-
const chain = memberChain(node);
|
|
107
|
-
if (!chain) {
|
|
108
|
-
return undefined;
|
|
109
|
-
}
|
|
110
|
-
return [resolveRoot(chain.root, resolving), ...chain.parts].join('.');
|
|
111
|
-
}
|
|
112
|
-
function resolveRoot(name, resolving) {
|
|
113
|
-
if (contextParam !== undefined && name === contextParam) {
|
|
114
|
-
return 'ctx';
|
|
115
|
-
}
|
|
116
|
-
if (bindings.unpinnable.has(name) || resolving.has(name)) {
|
|
117
|
-
return name;
|
|
118
|
-
}
|
|
119
|
-
const decls = bindings.declarations.get(name);
|
|
120
|
-
if (!decls || decls.length !== 1) {
|
|
121
|
-
return name;
|
|
122
|
-
}
|
|
123
|
-
const [{ kind, init, path }] = decls;
|
|
124
|
-
if (kind !== 'const' || !init || !path) {
|
|
125
|
-
return name;
|
|
126
|
-
}
|
|
127
|
-
const base = resolveChain(init, new Set(resolving).add(name));
|
|
128
|
-
return base ? [base, ...path].join('.') : name;
|
|
129
|
-
}
|
|
130
|
-
return { pathOf: node => resolveChain(node, new Set()) };
|
|
131
|
-
}
|
|
132
|
-
/** Every `ctx.api.v1.<domain>` the program touches (known or not), through `paths`. */
|
|
133
|
-
function collectApiDomains(program, paths) {
|
|
134
|
-
const apiDomains = new Set();
|
|
135
|
-
acornWalk.simple(program, {
|
|
136
|
-
MemberExpression(node) {
|
|
137
|
-
const [obj, api, version, domain] = paths.pathOf(node)?.split('.') ?? [];
|
|
138
|
-
if (obj === 'ctx' && api === 'api' && version === 'v1' && domain) {
|
|
139
|
-
apiDomains.add(domain);
|
|
140
|
-
}
|
|
141
|
-
},
|
|
142
|
-
});
|
|
143
|
-
return apiDomains;
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
exports.collectApiDomains = collectApiDomains;
|
|
147
|
-
exports.collectBindings = collectBindings;
|
|
148
|
-
exports.createPathResolver = createPathResolver;
|
|
149
|
-
exports.patternNames = patternNames;
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"handler-declaration.d.ts","sourceRoot":"","sources":["../../src/backend/handler-declaration.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAGV,UAAU,EACV,mBAAmB,EAEnB,iBAAiB,EAEjB,SAAS,EACV,MAAM,OAAO,CAAC;AAMf,MAAM,MAAM,kBAAkB,GAC1B;IAAE,IAAI,EAAE,UAAU,CAAC;IAAC,MAAM,EAAE,mBAAmB,CAAC,QAAQ,CAAC,CAAA;CAAE,GAC3D;IAAE,IAAI,EAAE,UAAU,CAAC;IAAC,IAAI,EAAE,UAAU,GAAG,IAAI,GAAG,SAAS,CAAA;CAAE,CAAC;AAE9D,8DAA8D;AAC9D,wBAAgB,sBAAsB,CACpC,IAAI,EAAE,SAAS,CAAC,SAAS,GAAG,iBAAiB,CAAC,EAAE,GAC/C,kBAAkB,GAAG,SAAS,CAahC;AAED,yGAAyG;AACzG,wBAAgB,cAAc,CAAC,IAAI,EAAE,SAAS,GAAG,iBAAiB,GAAG,OAAO,CAe3E;AAsCD,mGAAmG;AACnG,wBAAgB,uBAAuB,CAAC,WAAW,EAAE,kBAAkB,GAAG,MAAM,GAAG,SAAS,CAG3F;AAED,gGAAgG;AAChG,eAAO,MAAM,gBAAgB,EAAE,WAAW,CAAC,MAAM,CAK/C,CAAC"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"messages.d.ts","sourceRoot":"","sources":["../../src/backend/messages.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,QAAQ;uBACA,MAAM;yBACJ,MAAM;0BACL,MAAM;iCAEC,MAAM;0BAEb,MAAM;6BAEH,MAAM,UAAU,MAAM;wBAE3B,MAAM,QAAQ,MAAM,UAAU,MAAM,UAAU,MAAM;CAEzE,CAAC"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"parse.d.ts","sourceRoot":"","sources":["../../src/backend/parse.ts"],"names":[],"mappings":"AAAA,OAAO,EAA8D,KAAK,OAAO,EAAkB,MAAM,OAAO,CAAC;AAkDjH;;;;;;;GAOG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAuBhE"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"ast.test.d.ts","sourceRoot":"","sources":["../../../../src/backend/__tests__/ast.test.ts"],"names":[],"mappings":""}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"parse.test.d.ts","sourceRoot":"","sources":["../../../../src/backend/__tests__/parse.test.ts"],"names":[],"mappings":""}
|
|
@@ -1,39 +0,0 @@
|
|
|
1
|
-
import type { AnyNode, Expression, Pattern, Program, VariableDeclaration } from 'acorn';
|
|
2
|
-
export interface Declaration {
|
|
3
|
-
kind: VariableDeclaration['kind'];
|
|
4
|
-
init: Expression | null | undefined;
|
|
5
|
-
/**
|
|
6
|
-
* Property path from `init` to this binding: `[]` for `const x = init`,
|
|
7
|
-
* `['a', 'b']` for `const { a: { b: x } } = init`, `undefined` when the value
|
|
8
|
-
* is not a plain property read (array/rest/default patterns).
|
|
9
|
-
*/
|
|
10
|
-
path: string[] | undefined;
|
|
11
|
-
}
|
|
12
|
-
export interface Bindings {
|
|
13
|
-
/** Every `var|let|const <name> = …` in the file, by name. */
|
|
14
|
-
declarations: Map<string, Declaration[]>;
|
|
15
|
-
/** Names whose value cannot be pinned: reassigned, updated, or bound as parameters. */
|
|
16
|
-
unpinnable: Set<string>;
|
|
17
|
-
}
|
|
18
|
-
/** Every identifier a binding pattern introduces (`{ a, b: [c] } = …` → a, c). */
|
|
19
|
-
export declare const patternNames: (pattern: Pattern) => string[];
|
|
20
|
-
export declare function collectBindings(program: Program): Bindings;
|
|
21
|
-
export interface PathResolver {
|
|
22
|
-
/**
|
|
23
|
-
* Dotted path of a member chain, following `const` aliases back to their
|
|
24
|
-
* source: with `const sf = ctx.api.v1.snowflake`, `sf.query` resolves to
|
|
25
|
-
* `ctx.api.v1.snowflake.query`. Destructuring counts too
|
|
26
|
-
* (`const { snowflake: sf } = ctx.api.v1`). `undefined` if any link is dynamic.
|
|
27
|
-
*
|
|
28
|
-
* Only single, never-reassigned, never-shadowed `const` bindings are followed —
|
|
29
|
-
* anything else is left as written, so a `let` alias or a parameter of the same
|
|
30
|
-
* name is never mistaken for the channel. The handler's first parameter is
|
|
31
|
-
* treated as `ctx` even when renamed (`handler(context)` → `context.api.v1.db`
|
|
32
|
-
* resolves as `ctx.api.v1.db`).
|
|
33
|
-
*/
|
|
34
|
-
pathOf(node: AnyNode): string | undefined;
|
|
35
|
-
}
|
|
36
|
-
export declare function createPathResolver(bindings: Bindings, contextParam?: string): PathResolver;
|
|
37
|
-
/** Every `ctx.api.v1.<domain>` the program touches (known or not), through `paths`. */
|
|
38
|
-
export declare function collectApiDomains(program: Program, paths: PathResolver): Set<string>;
|
|
39
|
-
//# sourceMappingURL=ast.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"ast.d.ts","sourceRoot":"","sources":["../../../src/backend/ast.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,UAAU,EAAE,OAAO,EAAE,OAAO,EAAE,mBAAmB,EAAE,MAAM,OAAO,CAAC;AAKxF,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,mBAAmB,CAAC,MAAM,CAAC,CAAC;IAClC,IAAI,EAAE,UAAU,GAAG,IAAI,GAAG,SAAS,CAAC;IACpC;;;;OAIG;IACH,IAAI,EAAE,MAAM,EAAE,GAAG,SAAS,CAAC;CAC5B;AAED,MAAM,WAAW,QAAQ;IACvB,6DAA6D;IAC7D,YAAY,EAAE,GAAG,CAAC,MAAM,EAAE,WAAW,EAAE,CAAC,CAAC;IACzC,uFAAuF;IACvF,UAAU,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;CACzB;AA8CD,kFAAkF;AAClF,eAAO,MAAM,YAAY,GAAI,SAAS,OAAO,KAAG,MAAM,EAAmD,CAAC;AAE1G,wBAAgB,eAAe,CAAC,OAAO,EAAE,OAAO,GAAG,QAAQ,CA4C1D;AA2BD,MAAM,WAAW,YAAY;IAC3B;;;;;;;;;;;OAWG;IACH,MAAM,CAAC,IAAI,EAAE,OAAO,GAAG,MAAM,GAAG,SAAS,CAAC;CAC3C;AAED,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,QAAQ,EAAE,YAAY,CAAC,EAAE,MAAM,GAAG,YAAY,CA6B1F;AAED,uFAAuF;AACvF,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,YAAY,GAAG,GAAG,CAAC,MAAM,CAAC,CAWpF"}
|