@mondaydotcomorg/z2h-cli 0.30.0 → 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 +2 -8
- 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 +3 -8
- package/dist/esm/templates/app/usage.mjs +5 -0
- 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/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/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/backend.ts +31 -20
- package/src/commands/create.ts +1 -0
- package/src/commands/deploy.ts +3 -9
- package/src/templates/app/usage.json +1 -0
- 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
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import { fullAncestor } from 'acorn-walk';
|
|
2
|
+
import { patternNames, enclosingScope, patternBindings } from './utils.mjs';
|
|
3
|
+
|
|
4
|
+
function functionBodyScope(node) {
|
|
5
|
+
if ((node.type === 'FunctionDeclaration' ||
|
|
6
|
+
node.type === 'FunctionExpression' ||
|
|
7
|
+
node.type === 'ArrowFunctionExpression') &&
|
|
8
|
+
node.body.type === 'BlockStatement') {
|
|
9
|
+
return node.body;
|
|
10
|
+
}
|
|
11
|
+
return node;
|
|
12
|
+
}
|
|
13
|
+
function collectBindings(program) {
|
|
14
|
+
const declarations = new Map();
|
|
15
|
+
const unpinnable = new Set();
|
|
16
|
+
const markUnpinnable = (pattern) => patternNames(pattern).forEach(n => unpinnable.add(n));
|
|
17
|
+
fullAncestor(program, (node, _state, ancestors) => {
|
|
18
|
+
switch (node.type) {
|
|
19
|
+
case 'VariableDeclaration': {
|
|
20
|
+
const scope = enclosingScope(ancestors);
|
|
21
|
+
for (const declarator of node.declarations) {
|
|
22
|
+
for (const { name, path } of patternBindings(declarator.id, [])) {
|
|
23
|
+
const list = declarations.get(name) ?? [];
|
|
24
|
+
list.push({ kind: node.kind, init: declarator.init, path, scope });
|
|
25
|
+
declarations.set(name, list);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
break;
|
|
29
|
+
}
|
|
30
|
+
case 'AssignmentExpression':
|
|
31
|
+
markUnpinnable(node.left);
|
|
32
|
+
break;
|
|
33
|
+
case 'UpdateExpression':
|
|
34
|
+
if (node.argument.type === 'Identifier') {
|
|
35
|
+
unpinnable.add(node.argument.name);
|
|
36
|
+
}
|
|
37
|
+
break;
|
|
38
|
+
case 'ForInStatement':
|
|
39
|
+
case 'ForOfStatement':
|
|
40
|
+
if (node.left.type !== 'VariableDeclaration') {
|
|
41
|
+
markUnpinnable(node.left);
|
|
42
|
+
}
|
|
43
|
+
break;
|
|
44
|
+
case 'FunctionDeclaration':
|
|
45
|
+
case 'FunctionExpression':
|
|
46
|
+
case 'ArrowFunctionExpression': {
|
|
47
|
+
const scope = functionBodyScope(node);
|
|
48
|
+
for (const param of node.params) {
|
|
49
|
+
for (const name of patternNames(param)) {
|
|
50
|
+
const list = declarations.get(name) ?? [];
|
|
51
|
+
list.push({ kind: 'param', init: undefined, path: undefined, scope });
|
|
52
|
+
declarations.set(name, list);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
break;
|
|
56
|
+
}
|
|
57
|
+
case 'CatchClause':
|
|
58
|
+
if (node.param) {
|
|
59
|
+
const scope = node.body;
|
|
60
|
+
for (const name of patternNames(node.param)) {
|
|
61
|
+
const list = declarations.get(name) ?? [];
|
|
62
|
+
list.push({ kind: 'param', init: undefined, path: undefined, scope });
|
|
63
|
+
declarations.set(name, list);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
break;
|
|
67
|
+
}
|
|
68
|
+
});
|
|
69
|
+
return { declarations, unpinnable };
|
|
70
|
+
}
|
|
71
|
+
function declarationAt(bindings, name, position) {
|
|
72
|
+
const best = (bindings.declarations.get(name) ?? [])
|
|
73
|
+
.filter(d => d.scope.start <= position && position < d.scope.end)
|
|
74
|
+
.sort((a, b) => b.scope.start - a.scope.start)[0];
|
|
75
|
+
if (!best || best.kind === 'param' || bindings.unpinnable.has(name)) {
|
|
76
|
+
return undefined;
|
|
77
|
+
}
|
|
78
|
+
return best;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
export { collectBindings, declarationAt };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"handler-declaration.d.ts","sourceRoot":"","sources":["../../../../src/backend/parser/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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"member-path.d.ts","sourceRoot":"","sources":["../../../../src/backend/parser/member-path.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAEtD,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,QAAQ,EAAE,YAAY,CAAC,EAAE,MAAM,GAAG,YAAY,CAyB1F"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { memberChain } from './utils.mjs';
|
|
2
|
+
import { declarationAt } from './bindings.mjs';
|
|
3
|
+
|
|
4
|
+
function createPathResolver(bindings, contextParam) {
|
|
5
|
+
function resolveChain(node, resolving) {
|
|
6
|
+
const chain = memberChain(node);
|
|
7
|
+
if (!chain) {
|
|
8
|
+
return undefined;
|
|
9
|
+
}
|
|
10
|
+
return [resolveRoot(chain.root, node.start, resolving), ...chain.parts].join('.');
|
|
11
|
+
}
|
|
12
|
+
function resolveRoot(name, position, resolving) {
|
|
13
|
+
if (contextParam !== undefined && name === contextParam) {
|
|
14
|
+
return 'ctx';
|
|
15
|
+
}
|
|
16
|
+
if (resolving.has(name)) {
|
|
17
|
+
return name;
|
|
18
|
+
}
|
|
19
|
+
const decl = declarationAt(bindings, name, position);
|
|
20
|
+
if (!decl || decl.kind !== 'const' || !decl.init || !decl.path) {
|
|
21
|
+
return name;
|
|
22
|
+
}
|
|
23
|
+
const base = resolveChain(decl.init, new Set(resolving).add(name));
|
|
24
|
+
return base ? [base, ...decl.path].join('.') : name;
|
|
25
|
+
}
|
|
26
|
+
return { pathOf: node => resolveChain(node, new Set()) };
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export { createPathResolver };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"messages.d.ts","sourceRoot":"","sources":["../../../../src/backend/parser/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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"parse.d.ts","sourceRoot":"","sources":["../../../../src/backend/parser/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,6 +1,6 @@
|
|
|
1
1
|
import { parse } from 'acorn';
|
|
2
2
|
import { z } from 'zod';
|
|
3
|
-
import { trackEvent } from '
|
|
3
|
+
import { trackEvent } from '../../util/tracker.mjs';
|
|
4
4
|
import { exportsHandler } from './handler-declaration.mjs';
|
|
5
5
|
import { messages } from './messages.mjs';
|
|
6
6
|
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { AnyNode } from 'acorn';
|
|
2
|
+
import type { Bindings, JsonValue, Resolved } from './types';
|
|
3
|
+
/** Source text for a node that failed to resolve — the const declaration's init when the node names one, else the node itself. */
|
|
4
|
+
export declare function bestSourceText(node: AnyNode, source: string, bindings: Bindings): string;
|
|
5
|
+
export declare function staticValue(node: AnyNode, bindings: Bindings, source: string, resolving: ReadonlySet<string>): Resolved<JsonValue> | undefined;
|
|
6
|
+
//# sourceMappingURL=static-value.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"static-value.d.ts","sourceRoot":"","sources":["../../../../src/backend/parser/static-value.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,OAAO,CAAC;AACrC,OAAO,KAAK,EAAE,QAAQ,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAgG7D,kIAAkI;AAClI,wBAAgB,cAAc,CAAC,IAAI,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,QAAQ,GAAG,MAAM,CAQxF;AAED,wBAAgB,WAAW,CACzB,IAAI,EAAE,OAAO,EACb,QAAQ,EAAE,QAAQ,EAClB,MAAM,EAAE,MAAM,EACd,SAAS,EAAE,WAAW,CAAC,MAAM,CAAC,GAC7B,QAAQ,CAAC,SAAS,CAAC,GAAG,SAAS,CA6BjC"}
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
import { sourceTextOf, displayText, resolveOrSourceText, propertyKey } from './utils.mjs';
|
|
2
|
+
import { declarationAt } from './bindings.mjs';
|
|
3
|
+
|
|
4
|
+
function resolveLiteral(node) {
|
|
5
|
+
return typeof node.value === 'string' ||
|
|
6
|
+
typeof node.value === 'number' ||
|
|
7
|
+
typeof node.value === 'boolean' ||
|
|
8
|
+
node.value === null
|
|
9
|
+
? { value: node.value }
|
|
10
|
+
: undefined;
|
|
11
|
+
}
|
|
12
|
+
/** Template holes only interpolate scalars; a resolved object/array (e.g. `$or`) is shown unresolved instead of glued inline. */
|
|
13
|
+
function resolveTemplate(node, source, inner) {
|
|
14
|
+
const text = node.quasis
|
|
15
|
+
.map((quasi, i) => {
|
|
16
|
+
const literalText = quasi.value.cooked ?? quasi.value.raw;
|
|
17
|
+
const hole = node.expressions[i];
|
|
18
|
+
if (!hole) {
|
|
19
|
+
return literalText;
|
|
20
|
+
}
|
|
21
|
+
const resolved = inner(hole);
|
|
22
|
+
const scalar = resolved !== undefined &&
|
|
23
|
+
(typeof resolved.value === 'string' ||
|
|
24
|
+
typeof resolved.value === 'number' ||
|
|
25
|
+
typeof resolved.value === 'boolean' ||
|
|
26
|
+
resolved.value === null);
|
|
27
|
+
return literalText + (scalar ? displayText(resolved.value) : `\${${sourceTextOf(hole, source)}}`);
|
|
28
|
+
})
|
|
29
|
+
.join('');
|
|
30
|
+
return { value: text };
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Each element/property resolves independently, falling back to source text. A spread is kept
|
|
34
|
+
* visible under a `...`-prefixed key/value pair rather than silently dropped.
|
|
35
|
+
*/
|
|
36
|
+
function resolveContainer(node, source, bindings, inner) {
|
|
37
|
+
const fallbackText = (n) => bestSourceText(n, source, bindings);
|
|
38
|
+
if (node.type === 'ArrayExpression') {
|
|
39
|
+
return {
|
|
40
|
+
value: node.elements.map(element => (element ? resolveOrSourceText(element, source, inner, fallbackText) : null)),
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
const result = {};
|
|
44
|
+
for (const prop of node.properties) {
|
|
45
|
+
if (prop.type === 'SpreadElement') {
|
|
46
|
+
const spreadText = sourceTextOf(prop.argument, source);
|
|
47
|
+
result[`...${spreadText}`] = spreadText;
|
|
48
|
+
continue;
|
|
49
|
+
}
|
|
50
|
+
if (prop.type !== 'Property') {
|
|
51
|
+
continue;
|
|
52
|
+
}
|
|
53
|
+
const key = prop.computed
|
|
54
|
+
? sourceTextOf(prop.key, source)
|
|
55
|
+
: propertyKey(prop.key, false) ?? sourceTextOf(prop.key, source);
|
|
56
|
+
result[key] = resolveOrSourceText(prop.value, source, inner, fallbackText);
|
|
57
|
+
}
|
|
58
|
+
return { value: result };
|
|
59
|
+
}
|
|
60
|
+
function joinBranches(left, right) {
|
|
61
|
+
return left !== undefined && right !== undefined ? { value: { $or: [left.value, right.value] } } : undefined;
|
|
62
|
+
}
|
|
63
|
+
function resolveIdentifier(node, bindings, source, resolving) {
|
|
64
|
+
if (resolving.has(node.name)) {
|
|
65
|
+
return undefined;
|
|
66
|
+
}
|
|
67
|
+
const decl = declarationAt(bindings, node.name, node.start);
|
|
68
|
+
if (!decl || decl.kind !== 'const' || !decl.init || decl.path?.length !== 0) {
|
|
69
|
+
return undefined;
|
|
70
|
+
}
|
|
71
|
+
return staticValue(decl.init, bindings, source, new Set(resolving).add(node.name));
|
|
72
|
+
}
|
|
73
|
+
/** Source text for a node that failed to resolve — the const declaration's init when the node names one, else the node itself. */
|
|
74
|
+
function bestSourceText(node, source, bindings) {
|
|
75
|
+
if (node.type === 'Identifier') {
|
|
76
|
+
const decl = declarationAt(bindings, node.name, node.start);
|
|
77
|
+
if (decl && decl.kind === 'const' && decl.init && decl.path?.length === 0) {
|
|
78
|
+
return sourceTextOf(decl.init, source);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
return sourceTextOf(node, source);
|
|
82
|
+
}
|
|
83
|
+
function staticValue(node, bindings, source, resolving) {
|
|
84
|
+
const inner = child => staticValue(child, bindings, source, resolving);
|
|
85
|
+
switch (node.type) {
|
|
86
|
+
case 'Literal':
|
|
87
|
+
return resolveLiteral(node);
|
|
88
|
+
case 'TemplateLiteral':
|
|
89
|
+
return resolveTemplate(node, source, inner);
|
|
90
|
+
case 'ArrayExpression':
|
|
91
|
+
case 'ObjectExpression':
|
|
92
|
+
return resolveContainer(node, source, bindings, inner);
|
|
93
|
+
case 'BinaryExpression': {
|
|
94
|
+
if (node.operator !== '+') {
|
|
95
|
+
return undefined;
|
|
96
|
+
}
|
|
97
|
+
const left = inner(node.left);
|
|
98
|
+
const right = inner(node.right);
|
|
99
|
+
return typeof left?.value === 'string' && typeof right?.value === 'string'
|
|
100
|
+
? { value: left.value + right.value }
|
|
101
|
+
: undefined;
|
|
102
|
+
}
|
|
103
|
+
case 'ConditionalExpression':
|
|
104
|
+
return joinBranches(inner(node.consequent), inner(node.alternate));
|
|
105
|
+
case 'LogicalExpression':
|
|
106
|
+
return joinBranches(inner(node.left), inner(node.right));
|
|
107
|
+
case 'Identifier':
|
|
108
|
+
return resolveIdentifier(node, bindings, source, resolving);
|
|
109
|
+
default:
|
|
110
|
+
return undefined;
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
export { bestSourceText, staticValue };
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import type { AnyNode, Expression, Node, VariableDeclaration } from 'acorn';
|
|
2
|
+
/** `"<domain>.<method>"` → parameter names by position, as documented for handler authors. */
|
|
3
|
+
export type ApiSignatures = Record<string, readonly string[]>;
|
|
4
|
+
export interface Declaration {
|
|
5
|
+
kind: VariableDeclaration['kind'] | 'param';
|
|
6
|
+
init: Expression | null | undefined;
|
|
7
|
+
/**
|
|
8
|
+
* Property path from `init` to this binding: `[]` for `const x = init`,
|
|
9
|
+
* `['a', 'b']` for `const { a: { b: x } } = init`, `undefined` when the value
|
|
10
|
+
* is not a plain property read (array/rest/default patterns).
|
|
11
|
+
*/
|
|
12
|
+
path: string[] | undefined;
|
|
13
|
+
scope: Node;
|
|
14
|
+
}
|
|
15
|
+
export interface Bindings {
|
|
16
|
+
declarations: Map<string, Declaration[]>;
|
|
17
|
+
/** Names reassigned or updated after declaration — never followed as a stable alias. */
|
|
18
|
+
unpinnable: Set<string>;
|
|
19
|
+
}
|
|
20
|
+
export interface PatternBinding {
|
|
21
|
+
name: string;
|
|
22
|
+
path: string[] | undefined;
|
|
23
|
+
}
|
|
24
|
+
export type JsonValue = string | number | boolean | null | JsonValue[] | {
|
|
25
|
+
[key: string]: JsonValue;
|
|
26
|
+
};
|
|
27
|
+
/** Wraps a resolved value so "resolved to null" is distinguishable from "unresolved" (`undefined`). */
|
|
28
|
+
export type Resolved<T> = {
|
|
29
|
+
readonly value: T;
|
|
30
|
+
};
|
|
31
|
+
export interface MemberChain {
|
|
32
|
+
root: string;
|
|
33
|
+
parts: string[];
|
|
34
|
+
}
|
|
35
|
+
export interface PathResolver {
|
|
36
|
+
/**
|
|
37
|
+
* Dotted path of a member chain, following `const` aliases back to their
|
|
38
|
+
* source: with `const sf = ctx.api.v1.snowflake`, `sf.query` resolves to
|
|
39
|
+
* `ctx.api.v1.snowflake.query`. Destructuring counts too
|
|
40
|
+
* (`const { snowflake: sf } = ctx.api.v1`). `undefined` if any link is dynamic.
|
|
41
|
+
*
|
|
42
|
+
* Only single, never-reassigned, never-shadowed `const` bindings are followed —
|
|
43
|
+
* anything else is left as written. The handler's first parameter is treated as
|
|
44
|
+
* `ctx` even when renamed (`handler(context)` → `context.api.v1.db` resolves as
|
|
45
|
+
* `ctx.api.v1.db`).
|
|
46
|
+
*/
|
|
47
|
+
pathOf(node: AnyNode): string | undefined;
|
|
48
|
+
}
|
|
49
|
+
/** Undocumented arguments or methods fall back to `arg<index>` keys. */
|
|
50
|
+
export type ApiCall = Record<string, JsonValue>;
|
|
51
|
+
/** `domain -> method -> calls`, later written into `usage.json` by deploy. */
|
|
52
|
+
export type ApiUsage = Record<string, Record<string, ApiCall[]>>;
|
|
53
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../../src/backend/parser/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,UAAU,EAAE,IAAI,EAAE,mBAAmB,EAAE,MAAM,OAAO,CAAC;AAE5E,8FAA8F;AAC9F,MAAM,MAAM,aAAa,GAAG,MAAM,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,CAAC,CAAC;AAI9D,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,mBAAmB,CAAC,MAAM,CAAC,GAAG,OAAO,CAAC;IAC5C,IAAI,EAAE,UAAU,GAAG,IAAI,GAAG,SAAS,CAAC;IACpC;;;;OAIG;IACH,IAAI,EAAE,MAAM,EAAE,GAAG,SAAS,CAAC;IAC3B,KAAK,EAAE,IAAI,CAAC;CACb;AAED,MAAM,WAAW,QAAQ;IACvB,YAAY,EAAE,GAAG,CAAC,MAAM,EAAE,WAAW,EAAE,CAAC,CAAC;IACzC,wFAAwF;IACxF,UAAU,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;CACzB;AAED,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,EAAE,GAAG,SAAS,CAAC;CAC5B;AAID,MAAM,MAAM,SAAS,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,IAAI,GAAG,SAAS,EAAE,GAAG;IAAE,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,CAAA;CAAE,CAAC;AAEtG,uGAAuG;AACvG,MAAM,MAAM,QAAQ,CAAC,CAAC,IAAI;IAAE,QAAQ,CAAC,KAAK,EAAE,CAAC,CAAA;CAAE,CAAC;AAIhD,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,EAAE,CAAC;CACjB;AAED,MAAM,WAAW,YAAY;IAC3B;;;;;;;;;;OAUG;IACH,MAAM,CAAC,IAAI,EAAE,OAAO,GAAG,MAAM,GAAG,SAAS,CAAC;CAC3C;AAID,wEAAwE;AACxE,MAAM,MAAM,OAAO,GAAG,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;AAEhD,8EAA8E;AAC9E,MAAM,MAAM,QAAQ,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,EAAE,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { AnyNode, Node, Pattern } from 'acorn';
|
|
2
|
+
import type { JsonValue, MemberChain, PatternBinding, Resolved } from './types';
|
|
3
|
+
export declare const sourceTextOf: (node: AnyNode, source: string) => string;
|
|
4
|
+
export declare function displayText(value: JsonValue): string;
|
|
5
|
+
export declare function resolveOrSourceText(node: AnyNode, source: string, resolve: (node: AnyNode) => Resolved<JsonValue> | undefined, fallbackText?: (node: AnyNode) => string): JsonValue;
|
|
6
|
+
/** Static property key of `obj.key` / `obj['key']` / `{ key: … }`; `undefined` when computed from a non-literal. */
|
|
7
|
+
export declare function propertyKey(key: AnyNode, computed: boolean): string | undefined;
|
|
8
|
+
/** `a.b.c` / `a['b'].c` → root `a`, parts `[b, c]`; `undefined` if any link is dynamic or the root is not an identifier. */
|
|
9
|
+
export declare function memberChain(node: AnyNode): MemberChain | undefined;
|
|
10
|
+
/**
|
|
11
|
+
* Every identifier a binding pattern introduces, with its property path from the
|
|
12
|
+
* pattern's value. `path` is deliberately not defaulted: callers pass `[]` for
|
|
13
|
+
* the root and `undefined` once the pattern stops being a plain property read.
|
|
14
|
+
*/
|
|
15
|
+
export declare function patternBindings(pattern: Pattern, path: string[] | undefined): PatternBinding[];
|
|
16
|
+
export declare const patternNames: (pattern: Pattern) => string[];
|
|
17
|
+
/** Nearest scope enclosing the last node of `ancestors` (which `fullAncestor` includes in the list). */
|
|
18
|
+
export declare function enclosingScope(ancestors: AnyNode[]): Node;
|
|
19
|
+
//# sourceMappingURL=utils.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../../../src/backend/parser/utils.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,OAAO,CAAC;AACpD,OAAO,KAAK,EAAE,SAAS,EAAE,WAAW,EAAE,cAAc,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAIhF,eAAO,MAAM,YAAY,GAAI,MAAM,OAAO,EAAE,QAAQ,MAAM,KAAG,MAA4C,CAAC;AAE1G,wBAAgB,WAAW,CAAC,KAAK,EAAE,SAAS,GAAG,MAAM,CAEpD;AAED,wBAAgB,mBAAmB,CACjC,IAAI,EAAE,OAAO,EACb,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,QAAQ,CAAC,SAAS,CAAC,GAAG,SAAS,EAC3D,YAAY,GAAE,CAAC,IAAI,EAAE,OAAO,KAAK,MAAqC,GACrE,SAAS,CAGX;AAID,oHAAoH;AACpH,wBAAgB,WAAW,CAAC,GAAG,EAAE,OAAO,EAAE,QAAQ,EAAE,OAAO,GAAG,MAAM,GAAG,SAAS,CAQ/E;AAED,4HAA4H;AAC5H,wBAAgB,WAAW,CAAC,IAAI,EAAE,OAAO,GAAG,WAAW,GAAG,SAAS,CAelE;AAID;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,SAAS,GAAG,cAAc,EAAE,CAsB9F;AAED,eAAO,MAAM,YAAY,GAAI,SAAS,OAAO,KAAG,MAAM,EAAmD,CAAC;AAc1G,wGAAwG;AACxG,wBAAgB,cAAc,CAAC,SAAS,EAAE,OAAO,EAAE,GAAG,IAAI,CAOzD"}
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
// ─────────── Source text ───────────
|
|
2
|
+
const sourceTextOf = (node, source) => source.slice(node.start, node.end);
|
|
3
|
+
function displayText(value) {
|
|
4
|
+
return typeof value === 'string' ? value : JSON.stringify(value);
|
|
5
|
+
}
|
|
6
|
+
function resolveOrSourceText(node, source, resolve, fallbackText = n => sourceTextOf(n, source)) {
|
|
7
|
+
const resolved = resolve(node);
|
|
8
|
+
return resolved !== undefined ? resolved.value : fallbackText(node);
|
|
9
|
+
}
|
|
10
|
+
// ─────────── Keys and member chains ───────────
|
|
11
|
+
/** Static property key of `obj.key` / `obj['key']` / `{ key: … }`; `undefined` when computed from a non-literal. */
|
|
12
|
+
function propertyKey(key, computed) {
|
|
13
|
+
if (key.type === 'Literal' && typeof key.value === 'string') {
|
|
14
|
+
return key.value;
|
|
15
|
+
}
|
|
16
|
+
if (!computed && key.type === 'Identifier') {
|
|
17
|
+
return key.name;
|
|
18
|
+
}
|
|
19
|
+
return undefined;
|
|
20
|
+
}
|
|
21
|
+
/** `a.b.c` / `a['b'].c` → root `a`, parts `[b, c]`; `undefined` if any link is dynamic or the root is not an identifier. */
|
|
22
|
+
function memberChain(node) {
|
|
23
|
+
if (node.type === 'ChainExpression') {
|
|
24
|
+
return memberChain(node.expression);
|
|
25
|
+
}
|
|
26
|
+
const parts = [];
|
|
27
|
+
let cur = node;
|
|
28
|
+
while (cur.type === 'MemberExpression') {
|
|
29
|
+
const key = propertyKey(cur.property, cur.computed);
|
|
30
|
+
if (key === undefined) {
|
|
31
|
+
return undefined;
|
|
32
|
+
}
|
|
33
|
+
parts.unshift(key);
|
|
34
|
+
cur = cur.object;
|
|
35
|
+
}
|
|
36
|
+
return cur.type === 'Identifier' ? { root: cur.name, parts } : undefined;
|
|
37
|
+
}
|
|
38
|
+
// ─────────── Binding patterns ───────────
|
|
39
|
+
/**
|
|
40
|
+
* Every identifier a binding pattern introduces, with its property path from the
|
|
41
|
+
* pattern's value. `path` is deliberately not defaulted: callers pass `[]` for
|
|
42
|
+
* the root and `undefined` once the pattern stops being a plain property read.
|
|
43
|
+
*/
|
|
44
|
+
function patternBindings(pattern, path) {
|
|
45
|
+
switch (pattern.type) {
|
|
46
|
+
case 'Identifier':
|
|
47
|
+
return [{ name: pattern.name, path }];
|
|
48
|
+
case 'ObjectPattern':
|
|
49
|
+
return pattern.properties.flatMap(p => {
|
|
50
|
+
if (p.type === 'RestElement') {
|
|
51
|
+
return patternBindings(p.argument, undefined);
|
|
52
|
+
}
|
|
53
|
+
const key = propertyKey(p.key, p.computed);
|
|
54
|
+
return patternBindings(p.value, path && key !== undefined ? [...path, key] : undefined);
|
|
55
|
+
});
|
|
56
|
+
case 'ArrayPattern':
|
|
57
|
+
return pattern.elements.flatMap(e => (e ? patternBindings(e, undefined) : []));
|
|
58
|
+
case 'AssignmentPattern':
|
|
59
|
+
return patternBindings(pattern.left, undefined);
|
|
60
|
+
case 'RestElement':
|
|
61
|
+
return patternBindings(pattern.argument, undefined);
|
|
62
|
+
default:
|
|
63
|
+
// MemberExpression targets (`obj.x = …`) bind no names.
|
|
64
|
+
return [];
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
const patternNames = (pattern) => patternBindings(pattern, []).map(b => b.name);
|
|
68
|
+
// ─────────── Scopes ───────────
|
|
69
|
+
const SCOPE_TYPES = new Set([
|
|
70
|
+
'Program',
|
|
71
|
+
'BlockStatement',
|
|
72
|
+
'StaticBlock',
|
|
73
|
+
'SwitchStatement',
|
|
74
|
+
'ForStatement',
|
|
75
|
+
'ForInStatement',
|
|
76
|
+
'ForOfStatement',
|
|
77
|
+
]);
|
|
78
|
+
/** Nearest scope enclosing the last node of `ancestors` (which `fullAncestor` includes in the list). */
|
|
79
|
+
function enclosingScope(ancestors) {
|
|
80
|
+
for (let i = ancestors.length - 2; i > 0; i--) {
|
|
81
|
+
if (SCOPE_TYPES.has(ancestors[i].type)) {
|
|
82
|
+
return ancestors[i];
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
return ancestors[0];
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
export { displayText, enclosingScope, memberChain, patternBindings, patternNames, propertyKey, resolveOrSourceText, sourceTextOf };
|
|
@@ -1,6 +1,9 @@
|
|
|
1
|
+
import type { ApiUsage } from './parser/types';
|
|
2
|
+
export type { ApiCall, ApiUsage } from './parser/types';
|
|
1
3
|
export interface HandlerValidation {
|
|
2
4
|
/** Every `ctx.api.v1.<domain>` the handler touches (known or not), sorted and unique. */
|
|
3
5
|
apiDomains: string[];
|
|
6
|
+
apiUsages: ApiUsage;
|
|
4
7
|
}
|
|
5
8
|
/**
|
|
6
9
|
* Validates a handler's source before upload: real parsing (via acorn) catches
|
|
@@ -12,9 +15,6 @@ export interface HandlerValidation {
|
|
|
12
15
|
* Unknown `ctx.api.v1.<domain>` usage is a warning, not a failure: this pass is
|
|
13
16
|
* build-time DX feedback for agent-generated code, never a security boundary —
|
|
14
17
|
* the isolate has no ambient capabilities regardless of what a handler contains.
|
|
15
|
-
*
|
|
16
|
-
* Returns the `ctx.api.v1.*` domains the handler touches so callers (integration
|
|
17
|
-
* detection) can reuse the parse instead of re-scanning the source.
|
|
18
18
|
*/
|
|
19
19
|
export declare function validateHandlerSource(file: string, source: string): HandlerValidation;
|
|
20
20
|
//# sourceMappingURL=validate.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"validate.d.ts","sourceRoot":"","sources":["../../../src/backend/validate.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"validate.d.ts","sourceRoot":"","sources":["../../../src/backend/validate.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAE/C,YAAY,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAIxD,MAAM,WAAW,iBAAiB;IAChC,yFAAyF;IACzF,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,SAAS,EAAE,QAAQ,CAAC;CACrB;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,iBAAiB,CAmCrF"}
|
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
import { simple } from 'acorn-walk';
|
|
2
2
|
import { ALWAYS_ON_CHANNELS, DECLARED_INTEGRATIONS } from '@mondaydotcomorg/z2h-shared-utils';
|
|
3
3
|
import { warn } from '../util/logger.mjs';
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
4
|
+
import { collectApiDomains, collectApiUsages } from './parser/api-usage.mjs';
|
|
5
|
+
import { collectBindings } from './parser/bindings.mjs';
|
|
6
|
+
import { findHandlerDeclaration, NEVER_A_FUNCTION, handlerContextParamName } from './parser/handler-declaration.mjs';
|
|
7
|
+
import { createPathResolver } from './parser/member-path.mjs';
|
|
8
|
+
import { messages } from './parser/messages.mjs';
|
|
9
|
+
import { parseOrThrow } from './parser/parse.mjs';
|
|
8
10
|
|
|
9
11
|
const KNOWN_API_DOMAINS = [...ALWAYS_ON_CHANNELS, ...DECLARED_INTEGRATIONS];
|
|
10
12
|
/**
|
|
@@ -17,9 +19,6 @@ const KNOWN_API_DOMAINS = [...ALWAYS_ON_CHANNELS, ...DECLARED_INTEGRATIONS];
|
|
|
17
19
|
* Unknown `ctx.api.v1.<domain>` usage is a warning, not a failure: this pass is
|
|
18
20
|
* build-time DX feedback for agent-generated code, never a security boundary —
|
|
19
21
|
* the isolate has no ambient capabilities regardless of what a handler contains.
|
|
20
|
-
*
|
|
21
|
-
* Returns the `ctx.api.v1.*` domains the handler touches so callers (integration
|
|
22
|
-
* detection) can reuse the parse instead of re-scanning the source.
|
|
23
22
|
*/
|
|
24
23
|
function validateHandlerSource(file, source) {
|
|
25
24
|
const program = parseOrThrow(file, source);
|
|
@@ -43,12 +42,13 @@ function validateHandlerSource(file, source) {
|
|
|
43
42
|
}
|
|
44
43
|
const paths = createPathResolver(bindings, handlerContextParamName(declaration));
|
|
45
44
|
const apiDomains = collectApiDomains(program, paths);
|
|
45
|
+
const apiUsages = collectApiUsages(program, bindings, paths, source);
|
|
46
46
|
for (const domain of apiDomains) {
|
|
47
47
|
if (!KNOWN_API_DOMAINS.includes(domain)) {
|
|
48
48
|
warn(`${file}: ctx.api.v1.${domain} is not a known capability (available: ${KNOWN_API_DOMAINS.join(', ')})`);
|
|
49
49
|
}
|
|
50
50
|
}
|
|
51
|
-
return { apiDomains: [...apiDomains].sort() };
|
|
51
|
+
return { apiDomains: [...apiDomains].sort(), apiUsages };
|
|
52
52
|
}
|
|
53
53
|
|
|
54
54
|
export { validateHandlerSource };
|
|
@@ -1,19 +1,9 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* True if the app ships an app-level backend — a `backend/handlers/` directory.
|
|
3
|
-
* Callers gate on this so the deploy path is explicit about whether a backend is in
|
|
4
|
-
* play.
|
|
5
|
-
*/
|
|
6
1
|
export declare function hasHandlers(appDir: string): boolean;
|
|
7
2
|
/**
|
|
8
3
|
* Deploy the app's backend handlers to S3 and return the integrations detected
|
|
9
4
|
* from their sources. Each `.js` handler is uploaded as its own flat file — no
|
|
10
5
|
* compilation, no bundling, no npm deps.
|
|
11
6
|
*
|
|
12
|
-
* Live and preview differ only in where the handlers land, so that is the only
|
|
13
|
-
* thing `isPreview` switches:
|
|
14
|
-
* - live: `<appName>/backend-<version>` — the app's immutable per-version slot.
|
|
15
|
-
* - preview: `<mfKeyPrefix without /MF>/MS` — beside the preview's `/MF` frontend.
|
|
16
|
-
*
|
|
17
7
|
* Integration sync note: the returned set is re-derived from the CURRENT backend
|
|
18
8
|
* sources on every deploy, and the platform set is reconciled to exactly match
|
|
19
9
|
* it (there is no stored declaration to fall back on). A deploy therefore always
|
|
@@ -29,9 +19,8 @@ export declare function deployBackend(opts: {
|
|
|
29
19
|
isPreview: boolean;
|
|
30
20
|
}): Promise<string[]>;
|
|
31
21
|
/**
|
|
32
|
-
*
|
|
33
|
-
*
|
|
34
|
-
* uploading anything. Throws on the first invalid handler.
|
|
22
|
+
* Runs the same checks deploy does against the working tree, refreshing the
|
|
23
|
+
* local `usage.json` — no upload to S3. Throws on the first invalid handler.
|
|
35
24
|
*/
|
|
36
25
|
export declare function backendValidateCommand(appDir?: string): Promise<void>;
|
|
37
26
|
export declare function backendInvokeCommand(handlerName: string, opts?: {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"backend.d.ts","sourceRoot":"","sources":["../../../src/commands/backend.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"backend.d.ts","sourceRoot":"","sources":["../../../src/commands/backend.ts"],"names":[],"mappings":"AAsBA,wBAAgB,WAAW,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAEnD;AAqDD;;;;;;;;;;GAUG;AACH,wBAAsB,aAAa,CAAC,IAAI,EAAE;IACxC,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,OAAO,CAAC;CACpB,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CASpB;AAED;;;GAGG;AACH,wBAAsB,sBAAsB,CAAC,MAAM,GAAE,MAAsB,GAAG,OAAO,CAAC,IAAI,CAAC,CAe1F;AAED,wBAAsB,oBAAoB,CAAC,WAAW,EAAE,MAAM,EAAE,IAAI,GAAE;IAAE,KAAK,CAAC,EAAE,MAAM,CAAA;CAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAa5G"}
|