@mondaydotcomorg/z2h-cli 0.30.0 → 0.32.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.
Files changed (175) hide show
  1. package/dist/backend/handlers.d.ts +3 -0
  2. package/dist/backend/handlers.d.ts.map +1 -1
  3. package/dist/backend/handlers.js +7 -4
  4. package/dist/backend/parser/__tests__/ast.test.d.ts.map +1 -0
  5. package/dist/backend/parser/__tests__/parse.test.d.ts.map +1 -0
  6. package/dist/backend/parser/api-signatures.d.ts +4 -0
  7. package/dist/backend/parser/api-signatures.d.ts.map +1 -0
  8. package/dist/backend/parser/api-signatures.js +31 -0
  9. package/dist/backend/parser/api-usage.d.ts +5 -0
  10. package/dist/backend/parser/api-usage.d.ts.map +1 -0
  11. package/dist/backend/parser/api-usage.js +61 -0
  12. package/dist/backend/parser/bindings.d.ts +5 -0
  13. package/dist/backend/parser/bindings.d.ts.map +1 -0
  14. package/dist/backend/parser/bindings.js +84 -0
  15. package/dist/backend/parser/handler-declaration.d.ts.map +1 -0
  16. package/dist/backend/parser/member-path.d.ts +3 -0
  17. package/dist/backend/parser/member-path.d.ts.map +1 -0
  18. package/dist/backend/parser/member-path.js +31 -0
  19. package/dist/backend/parser/messages.d.ts.map +1 -0
  20. package/dist/backend/parser/parse.d.ts.map +1 -0
  21. package/dist/backend/{parse.js → parser/parse.js} +9 -9
  22. package/dist/backend/parser/static-value.d.ts +6 -0
  23. package/dist/backend/parser/static-value.d.ts.map +1 -0
  24. package/dist/backend/parser/static-value.js +117 -0
  25. package/dist/backend/parser/types.d.ts +53 -0
  26. package/dist/backend/parser/types.d.ts.map +1 -0
  27. package/dist/backend/parser/types.js +1 -0
  28. package/dist/backend/parser/utils.d.ts +19 -0
  29. package/dist/backend/parser/utils.d.ts.map +1 -0
  30. package/dist/backend/parser/utils.js +97 -0
  31. package/dist/backend/validate.d.ts +3 -3
  32. package/dist/backend/validate.d.ts.map +1 -1
  33. package/dist/backend/validate.js +18 -18
  34. package/dist/commands/__tests__/llm-migration.test.d.ts +2 -0
  35. package/dist/commands/__tests__/llm-migration.test.d.ts.map +1 -0
  36. package/dist/commands/backend.d.ts +2 -13
  37. package/dist/commands/backend.d.ts.map +1 -1
  38. package/dist/commands/backend.js +30 -21
  39. package/dist/commands/create.d.ts.map +1 -1
  40. package/dist/commands/create.js +1 -0
  41. package/dist/commands/deploy.d.ts.map +1 -1
  42. package/dist/commands/deploy.js +2 -8
  43. package/dist/commands/llm-migration.d.ts +6 -0
  44. package/dist/commands/llm-migration.d.ts.map +1 -0
  45. package/dist/commands/llm-migration.js +33 -0
  46. package/dist/commands/migrate.d.ts.map +1 -1
  47. package/dist/commands/migrate.js +6 -13
  48. package/dist/esm/backend/handlers.d.ts +3 -0
  49. package/dist/esm/backend/handlers.d.ts.map +1 -1
  50. package/dist/esm/backend/handlers.mjs +7 -4
  51. package/dist/esm/backend/parser/__tests__/ast.test.d.ts.map +1 -0
  52. package/dist/esm/backend/parser/__tests__/parse.test.d.ts.map +1 -0
  53. package/dist/esm/backend/parser/api-signatures.d.ts +4 -0
  54. package/dist/esm/backend/parser/api-signatures.d.ts.map +1 -0
  55. package/dist/esm/backend/parser/api-signatures.mjs +24 -0
  56. package/dist/esm/backend/parser/api-usage.d.ts +5 -0
  57. package/dist/esm/backend/parser/api-usage.d.ts.map +1 -0
  58. package/dist/esm/backend/parser/api-usage.mjs +58 -0
  59. package/dist/esm/backend/parser/bindings.d.ts +5 -0
  60. package/dist/esm/backend/parser/bindings.d.ts.map +1 -0
  61. package/dist/esm/backend/parser/bindings.mjs +81 -0
  62. package/dist/esm/backend/parser/handler-declaration.d.ts.map +1 -0
  63. package/dist/esm/backend/parser/member-path.d.ts +3 -0
  64. package/dist/esm/backend/parser/member-path.d.ts.map +1 -0
  65. package/dist/esm/backend/parser/member-path.mjs +29 -0
  66. package/dist/esm/backend/parser/messages.d.ts.map +1 -0
  67. package/dist/esm/backend/parser/parse.d.ts.map +1 -0
  68. package/dist/esm/backend/{parse.mjs → parser/parse.mjs} +1 -1
  69. package/dist/esm/backend/parser/static-value.d.ts +6 -0
  70. package/dist/esm/backend/parser/static-value.d.ts.map +1 -0
  71. package/dist/esm/backend/parser/static-value.mjs +114 -0
  72. package/dist/esm/backend/parser/types.d.ts +53 -0
  73. package/dist/esm/backend/parser/types.d.ts.map +1 -0
  74. package/dist/esm/backend/parser/types.mjs +1 -0
  75. package/dist/esm/backend/parser/utils.d.ts +19 -0
  76. package/dist/esm/backend/parser/utils.d.ts.map +1 -0
  77. package/dist/esm/backend/parser/utils.mjs +88 -0
  78. package/dist/esm/backend/validate.d.ts +3 -3
  79. package/dist/esm/backend/validate.d.ts.map +1 -1
  80. package/dist/esm/backend/validate.mjs +8 -8
  81. package/dist/esm/commands/__tests__/llm-migration.test.d.ts +2 -0
  82. package/dist/esm/commands/__tests__/llm-migration.test.d.ts.map +1 -0
  83. package/dist/esm/commands/backend.d.ts +2 -13
  84. package/dist/esm/commands/backend.d.ts.map +1 -1
  85. package/dist/esm/commands/backend.mjs +31 -22
  86. package/dist/esm/commands/create.d.ts.map +1 -1
  87. package/dist/esm/commands/create.mjs +1 -0
  88. package/dist/esm/commands/deploy.d.ts.map +1 -1
  89. package/dist/esm/commands/deploy.mjs +3 -8
  90. package/dist/esm/commands/llm-migration.d.ts +6 -0
  91. package/dist/esm/commands/llm-migration.d.ts.map +1 -0
  92. package/dist/esm/commands/llm-migration.mjs +27 -0
  93. package/dist/esm/commands/migrate.d.ts.map +1 -1
  94. package/dist/esm/commands/migrate.mjs +6 -12
  95. package/dist/esm/index.mjs +6 -0
  96. package/dist/esm/templates/app/usage.mjs +5 -0
  97. package/dist/esm/util/machine-identity.d.ts +2 -3
  98. package/dist/esm/util/machine-identity.d.ts.map +1 -1
  99. package/dist/esm/util/machine-identity.mjs +7 -4
  100. package/dist/esm/util/migrations-json.d.ts +28 -0
  101. package/dist/esm/util/migrations-json.d.ts.map +1 -0
  102. package/dist/esm/util/migrations-json.mjs +17 -0
  103. package/dist/index.js +6 -0
  104. package/dist/templates/app/usage.js +7 -0
  105. package/dist/util/machine-identity.d.ts +2 -3
  106. package/dist/util/machine-identity.d.ts.map +1 -1
  107. package/dist/util/machine-identity.js +11 -3
  108. package/dist/util/migrations-json.d.ts +28 -0
  109. package/dist/util/migrations-json.d.ts.map +1 -0
  110. package/dist/util/migrations-json.js +25 -0
  111. package/handler-api/signatures.json +26 -0
  112. package/migrations.json +6 -0
  113. package/package.json +1 -1
  114. package/src/backend/__tests__/handlers.test.ts +13 -2
  115. package/src/backend/__tests__/validate.test.ts +54 -0
  116. package/src/backend/handlers.ts +10 -5
  117. package/src/backend/parser/__tests__/ast.test.ts +252 -0
  118. package/src/backend/{__tests__ → parser/__tests__}/parse.test.ts +2 -2
  119. package/src/backend/parser/api-signatures.ts +23 -0
  120. package/src/backend/parser/api-usage.ts +73 -0
  121. package/src/backend/parser/bindings.ts +87 -0
  122. package/src/backend/parser/member-path.ts +31 -0
  123. package/src/backend/{parse.ts → parser/parse.ts} +1 -1
  124. package/src/backend/parser/static-value.ts +145 -0
  125. package/src/backend/parser/types.ts +66 -0
  126. package/src/backend/parser/utils.ts +106 -0
  127. package/src/backend/validate.ts +12 -8
  128. package/src/commands/__tests__/backend-deploy.test.ts +70 -5
  129. package/src/commands/__tests__/backend-validate.test.ts +11 -1
  130. package/src/commands/__tests__/create.test.ts +1 -0
  131. package/src/commands/__tests__/llm-migration.test.ts +98 -0
  132. package/src/commands/backend.ts +31 -20
  133. package/src/commands/create.ts +1 -0
  134. package/src/commands/deploy.ts +3 -9
  135. package/src/commands/llm-migration.ts +33 -0
  136. package/src/commands/migrate.ts +7 -25
  137. package/src/index.ts +7 -0
  138. package/src/migrations-llm/snowflake-service-to-backend-runner.md +168 -0
  139. package/src/templates/app/usage.json +1 -0
  140. package/src/util/machine-identity.ts +7 -3
  141. package/src/util/migrations-json.ts +45 -0
  142. package/dist/backend/__tests__/ast.test.d.ts.map +0 -1
  143. package/dist/backend/__tests__/parse.test.d.ts.map +0 -1
  144. package/dist/backend/ast.d.ts +0 -39
  145. package/dist/backend/ast.d.ts.map +0 -1
  146. package/dist/backend/ast.js +0 -149
  147. package/dist/backend/handler-declaration.d.ts.map +0 -1
  148. package/dist/backend/messages.d.ts.map +0 -1
  149. package/dist/backend/parse.d.ts.map +0 -1
  150. package/dist/esm/backend/__tests__/ast.test.d.ts.map +0 -1
  151. package/dist/esm/backend/__tests__/parse.test.d.ts.map +0 -1
  152. package/dist/esm/backend/ast.d.ts +0 -39
  153. package/dist/esm/backend/ast.d.ts.map +0 -1
  154. package/dist/esm/backend/ast.mjs +0 -144
  155. package/dist/esm/backend/handler-declaration.d.ts.map +0 -1
  156. package/dist/esm/backend/messages.d.ts.map +0 -1
  157. package/dist/esm/backend/parse.d.ts.map +0 -1
  158. package/src/backend/__tests__/ast.test.ts +0 -53
  159. package/src/backend/ast.ts +0 -201
  160. /package/dist/backend/{__tests__ → parser/__tests__}/ast.test.d.ts +0 -0
  161. /package/dist/backend/{__tests__ → parser/__tests__}/parse.test.d.ts +0 -0
  162. /package/dist/backend/{handler-declaration.d.ts → parser/handler-declaration.d.ts} +0 -0
  163. /package/dist/backend/{handler-declaration.js → parser/handler-declaration.js} +0 -0
  164. /package/dist/backend/{messages.d.ts → parser/messages.d.ts} +0 -0
  165. /package/dist/backend/{messages.js → parser/messages.js} +0 -0
  166. /package/dist/backend/{parse.d.ts → parser/parse.d.ts} +0 -0
  167. /package/dist/esm/backend/{__tests__ → parser/__tests__}/ast.test.d.ts +0 -0
  168. /package/dist/esm/backend/{__tests__ → parser/__tests__}/parse.test.d.ts +0 -0
  169. /package/dist/esm/backend/{handler-declaration.d.ts → parser/handler-declaration.d.ts} +0 -0
  170. /package/dist/esm/backend/{handler-declaration.mjs → parser/handler-declaration.mjs} +0 -0
  171. /package/dist/esm/backend/{messages.d.ts → parser/messages.d.ts} +0 -0
  172. /package/dist/esm/backend/{messages.mjs → parser/messages.mjs} +0 -0
  173. /package/dist/esm/backend/{parse.d.ts → parser/parse.d.ts} +0 -0
  174. /package/src/backend/{handler-declaration.ts → parser/handler-declaration.ts} +0 -0
  175. /package/src/backend/{messages.ts → parser/messages.ts} +0 -0
@@ -1,8 +1,11 @@
1
+ import { type ApiUsage } from './validate';
1
2
  export interface ReadHandlersResult {
2
3
  /** handler name (filename without .js) → JS source */
3
4
  handlers: Record<string, string>;
4
5
  /** Every `ctx.api.v1.<domain>` any handler touches, sorted and unique. */
5
6
  apiDomains: string[];
7
+ /** handler name → per-call `ctx.api.v1` usage, for `usage.json`. */
8
+ apiUsages: Record<string, ApiUsage>;
6
9
  }
7
10
  /**
8
11
  * Reads every `backend/handlers/*.js` file inside `consumerDir` and returns a
@@ -1 +1 @@
1
- {"version":3,"file":"handlers.d.ts","sourceRoot":"","sources":["../../src/backend/handlers.ts"],"names":[],"mappings":"AAOA,MAAM,WAAW,kBAAkB;IACjC,sDAAsD;IACtD,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC,0EAA0E;IAC1E,UAAU,EAAE,MAAM,EAAE,CAAC;CACtB;AAED;;;;GAIG;AACH,wBAAsB,YAAY,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,kBAAkB,CAAC,CA2BnF"}
1
+ {"version":3,"file":"handlers.d.ts","sourceRoot":"","sources":["../../src/backend/handlers.ts"],"names":[],"mappings":"AAGA,OAAO,EAAyB,KAAK,QAAQ,EAAE,MAAM,YAAY,CAAC;AAIlE,MAAM,WAAW,kBAAkB;IACjC,sDAAsD;IACtD,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC,0EAA0E;IAC1E,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,oEAAoE;IACpE,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;CACrC;AAED;;;;GAIG;AACH,wBAAsB,YAAY,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,kBAAkB,CAAC,CA8BnF"}
@@ -18,27 +18,30 @@ const HANDLERS_DIR = path__default.default.join('backend', 'handlers');
18
18
  async function readHandlers(consumerDir) {
19
19
  const handlersDir = path__default.default.join(consumerDir, HANDLERS_DIR);
20
20
  if (!(await fs.pathExists(handlersDir))) {
21
- return { handlers: {}, apiDomains: [] };
21
+ return { handlers: {}, apiDomains: [], apiUsages: {} };
22
22
  }
23
23
  const entries = await promises.readdir(handlersDir);
24
24
  const tsFiles = entries.filter(f => f.endsWith('.ts'));
25
25
  if (tsFiles.length > 0) {
26
26
  throw new Error(`TypeScript handlers are not yet supported (${tsFiles.join(', ')}). Compile to .js first.`);
27
27
  }
28
- const jsFiles = entries.filter(f => f.endsWith('.js'));
28
+ // Sorted so usage.json's key order is deterministic across machines, not readdir()'s.
29
+ const jsFiles = entries.filter(f => f.endsWith('.js')).sort();
29
30
  if (jsFiles.length === 0) {
30
- return { handlers: {}, apiDomains: [] };
31
+ return { handlers: {}, apiDomains: [], apiUsages: {} };
31
32
  }
32
33
  const handlers = {};
33
34
  const apiDomains = new Set();
35
+ const apiUsages = {};
34
36
  for (const file of jsFiles) {
35
37
  const handlerName = path__default.default.parse(file).name;
36
38
  const source = await promises.readFile(path__default.default.join(handlersDir, file), 'utf8');
37
39
  const validation = backend_validate.validateHandlerSource(file, source);
38
40
  validation.apiDomains.forEach(d => apiDomains.add(d));
39
41
  handlers[handlerName] = source;
42
+ apiUsages[handlerName] = validation.apiUsages;
40
43
  }
41
- return { handlers, apiDomains: [...apiDomains].sort() };
44
+ return { handlers, apiDomains: [...apiDomains].sort(), apiUsages };
42
45
  }
43
46
 
44
47
  exports.readHandlers = readHandlers;
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ast.test.d.ts","sourceRoot":"","sources":["../../../../src/backend/parser/__tests__/ast.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parse.test.d.ts","sourceRoot":"","sources":["../../../../src/backend/parser/__tests__/parse.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,4 @@
1
+ import type { ApiSignatures } from './types';
2
+ /** Derived from the runner's channel docs by `scripts/generate-handler-api.mjs` at build time. */
3
+ export declare function loadApiSignatures(): ApiSignatures;
4
+ //# sourceMappingURL=api-signatures.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"api-signatures.d.ts","sourceRoot":"","sources":["../../../src/backend/parser/api-signatures.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAI7C,kGAAkG;AAClG,wBAAgB,iBAAiB,IAAI,aAAa,CAcjD"}
@@ -0,0 +1,31 @@
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
2
+
3
+ const fs = require('node:fs');
4
+ const node_module = require('node:module');
5
+ const path = require('node:path');
6
+
7
+ var _documentCurrentScript = typeof document !== 'undefined' ? document.currentScript : null;
8
+ const _interopDefault = e => e && e.__esModule ? e : { default: e };
9
+
10
+ const path__default = /*#__PURE__*/_interopDefault(path);
11
+
12
+ let cached;
13
+ /** Derived from the runner's channel docs by `scripts/generate-handler-api.mjs` at build time. */
14
+ function loadApiSignatures() {
15
+ if (cached) {
16
+ return cached;
17
+ }
18
+ const root = path__default.default.dirname(node_module.createRequire((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('backend/parser/api-signatures.js', document.baseURI).href))).resolve('@mondaydotcomorg/z2h-cli/package.json'));
19
+ try {
20
+ cached = JSON.parse(fs.readFileSync(path__default.default.join(root, 'handler-api', 'signatures.json'), 'utf8'));
21
+ }
22
+ catch (err) {
23
+ if (err.code !== 'ENOENT') {
24
+ throw err;
25
+ }
26
+ cached = {};
27
+ }
28
+ return cached;
29
+ }
30
+
31
+ exports.loadApiSignatures = loadApiSignatures;
@@ -0,0 +1,5 @@
1
+ import type { Program } from 'acorn';
2
+ import type { ApiSignatures, ApiUsage, Bindings, PathResolver } from './types';
3
+ export declare function collectApiDomains(program: Program, paths: PathResolver): Set<string>;
4
+ export declare function collectApiUsages(program: Program, bindings: Bindings, paths: PathResolver, source: string, signatures?: ApiSignatures): ApiUsage;
5
+ //# sourceMappingURL=api-usage.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"api-usage.d.ts","sourceRoot":"","sources":["../../../src/backend/parser/api-usage.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,OAAO,CAAC;AACrC,OAAO,KAAK,EAAW,aAAa,EAAE,QAAQ,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAcxF,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,YAAY,GAAG,GAAG,CAAC,MAAM,CAAC,CAWpF;AAED,wBAAgB,gBAAgB,CAC9B,OAAO,EAAE,OAAO,EAChB,QAAQ,EAAE,QAAQ,EAClB,KAAK,EAAE,YAAY,EACnB,MAAM,EAAE,MAAM,EACd,UAAU,GAAE,aAAmC,GAC9C,QAAQ,CAkCV"}
@@ -0,0 +1,61 @@
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
2
+
3
+ const acornWalk = require('acorn-walk');
4
+ const backend_parser_utils = require('./utils.js');
5
+ const backend_parser_staticValue = require('./static-value.js');
6
+ const backend_parser_apiSignatures = require('./api-signatures.js');
7
+
8
+ // ctx.api.v1.<domain>.<method>(...) — the only API shape the runner exposes today
9
+ const API_PREFIX = ['ctx', 'api', 'v1'];
10
+ const API_CALL_MIN_PARTS = API_PREFIX.length + 2;
11
+ function isApiPath(parts) {
12
+ return parts[0] === API_PREFIX[0] && parts[1] === API_PREFIX[1] && parts[2] === API_PREFIX[2];
13
+ }
14
+ function isApiCall(parts) {
15
+ return isApiPath(parts) && parts.length >= API_CALL_MIN_PARTS;
16
+ }
17
+ function collectApiDomains(program, paths) {
18
+ const apiDomains = new Set();
19
+ acornWalk.simple(program, {
20
+ MemberExpression(node) {
21
+ const parts = paths.pathOf(node)?.split('.') ?? [];
22
+ if (isApiPath(parts) && parts[3]) {
23
+ apiDomains.add(parts[3]);
24
+ }
25
+ },
26
+ });
27
+ return apiDomains;
28
+ }
29
+ function collectApiUsages(program, bindings, paths, source, signatures = backend_parser_apiSignatures.loadApiSignatures()) {
30
+ const apiUsages = {};
31
+ acornWalk.simple(program, {
32
+ CallExpression(node) {
33
+ if (node.callee.type !== 'MemberExpression' && node.callee.type !== 'Identifier') {
34
+ return;
35
+ }
36
+ const parts = paths.pathOf(node.callee)?.split('.') ?? [];
37
+ if (!isApiCall(parts)) {
38
+ return;
39
+ }
40
+ const [, , , domain, ...methodParts] = parts;
41
+ const method = methodParts.join('.');
42
+ const sigKey = `${domain}.${method}`;
43
+ const names = signatures[sigKey];
44
+ if (!names) {
45
+ // eslint-disable-next-line no-console
46
+ console.warn(`[ast] no signature for ${sigKey} — argument names will be positional`);
47
+ }
48
+ const call = {};
49
+ node.arguments.forEach((arg, i) => {
50
+ call[names?.[i] ?? `arg${i}`] = backend_parser_utils.resolveOrSourceText(arg, source, node => backend_parser_staticValue.staticValue(node, bindings, source, new Set()), node => backend_parser_staticValue.bestSourceText(node, source, bindings));
51
+ });
52
+ const methods = (apiUsages[domain] ??= {});
53
+ const calls = (methods[method] ??= []);
54
+ calls.push(call);
55
+ },
56
+ });
57
+ return apiUsages;
58
+ }
59
+
60
+ exports.collectApiDomains = collectApiDomains;
61
+ exports.collectApiUsages = collectApiUsages;
@@ -0,0 +1,5 @@
1
+ import type { Program } from 'acorn';
2
+ import type { Bindings, Declaration } from './types';
3
+ export declare function collectBindings(program: Program): Bindings;
4
+ export declare function declarationAt(bindings: Bindings, name: string, position: number): Declaration | undefined;
5
+ //# sourceMappingURL=bindings.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bindings.d.ts","sourceRoot":"","sources":["../../../src/backend/parser/bindings.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAA0B,OAAO,EAAE,MAAM,OAAO,CAAC;AAC7D,OAAO,KAAK,EAAE,QAAQ,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAcrD,wBAAgB,eAAe,CAAC,OAAO,EAAE,OAAO,GAAG,QAAQ,CA2D1D;AAED,wBAAgB,aAAa,CAAC,QAAQ,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,WAAW,GAAG,SAAS,CAQzG"}
@@ -0,0 +1,84 @@
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
2
+
3
+ const acornWalk = require('acorn-walk');
4
+ const backend_parser_utils = require('./utils.js');
5
+
6
+ function functionBodyScope(node) {
7
+ if ((node.type === 'FunctionDeclaration' ||
8
+ node.type === 'FunctionExpression' ||
9
+ node.type === 'ArrowFunctionExpression') &&
10
+ node.body.type === 'BlockStatement') {
11
+ return node.body;
12
+ }
13
+ return node;
14
+ }
15
+ function collectBindings(program) {
16
+ const declarations = new Map();
17
+ const unpinnable = new Set();
18
+ const markUnpinnable = (pattern) => backend_parser_utils.patternNames(pattern).forEach(n => unpinnable.add(n));
19
+ acornWalk.fullAncestor(program, (node, _state, ancestors) => {
20
+ switch (node.type) {
21
+ case 'VariableDeclaration': {
22
+ const scope = backend_parser_utils.enclosingScope(ancestors);
23
+ for (const declarator of node.declarations) {
24
+ for (const { name, path } of backend_parser_utils.patternBindings(declarator.id, [])) {
25
+ const list = declarations.get(name) ?? [];
26
+ list.push({ kind: node.kind, init: declarator.init, path, scope });
27
+ declarations.set(name, list);
28
+ }
29
+ }
30
+ break;
31
+ }
32
+ case 'AssignmentExpression':
33
+ markUnpinnable(node.left);
34
+ break;
35
+ case 'UpdateExpression':
36
+ if (node.argument.type === 'Identifier') {
37
+ unpinnable.add(node.argument.name);
38
+ }
39
+ break;
40
+ case 'ForInStatement':
41
+ case 'ForOfStatement':
42
+ if (node.left.type !== 'VariableDeclaration') {
43
+ markUnpinnable(node.left);
44
+ }
45
+ break;
46
+ case 'FunctionDeclaration':
47
+ case 'FunctionExpression':
48
+ case 'ArrowFunctionExpression': {
49
+ const scope = functionBodyScope(node);
50
+ for (const param of node.params) {
51
+ for (const name of backend_parser_utils.patternNames(param)) {
52
+ const list = declarations.get(name) ?? [];
53
+ list.push({ kind: 'param', init: undefined, path: undefined, scope });
54
+ declarations.set(name, list);
55
+ }
56
+ }
57
+ break;
58
+ }
59
+ case 'CatchClause':
60
+ if (node.param) {
61
+ const scope = node.body;
62
+ for (const name of backend_parser_utils.patternNames(node.param)) {
63
+ const list = declarations.get(name) ?? [];
64
+ list.push({ kind: 'param', init: undefined, path: undefined, scope });
65
+ declarations.set(name, list);
66
+ }
67
+ }
68
+ break;
69
+ }
70
+ });
71
+ return { declarations, unpinnable };
72
+ }
73
+ function declarationAt(bindings, name, position) {
74
+ const best = (bindings.declarations.get(name) ?? [])
75
+ .filter(d => d.scope.start <= position && position < d.scope.end)
76
+ .sort((a, b) => b.scope.start - a.scope.start)[0];
77
+ if (!best || best.kind === 'param' || bindings.unpinnable.has(name)) {
78
+ return undefined;
79
+ }
80
+ return best;
81
+ }
82
+
83
+ exports.collectBindings = collectBindings;
84
+ exports.declarationAt = 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,3 @@
1
+ import type { Bindings, PathResolver } from './types';
2
+ export declare function createPathResolver(bindings: Bindings, contextParam?: string): PathResolver;
3
+ //# sourceMappingURL=member-path.d.ts.map
@@ -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,31 @@
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
2
+
3
+ const backend_parser_utils = require('./utils.js');
4
+ const backend_parser_bindings = require('./bindings.js');
5
+
6
+ function createPathResolver(bindings, contextParam) {
7
+ function resolveChain(node, resolving) {
8
+ const chain = backend_parser_utils.memberChain(node);
9
+ if (!chain) {
10
+ return undefined;
11
+ }
12
+ return [resolveRoot(chain.root, node.start, resolving), ...chain.parts].join('.');
13
+ }
14
+ function resolveRoot(name, position, resolving) {
15
+ if (contextParam !== undefined && name === contextParam) {
16
+ return 'ctx';
17
+ }
18
+ if (resolving.has(name)) {
19
+ return name;
20
+ }
21
+ const decl = backend_parser_bindings.declarationAt(bindings, name, position);
22
+ if (!decl || decl.kind !== 'const' || !decl.init || !decl.path) {
23
+ return name;
24
+ }
25
+ const base = resolveChain(decl.init, new Set(resolving).add(name));
26
+ return base ? [base, ...decl.path].join('.') : name;
27
+ }
28
+ return { pathOf: node => resolveChain(node, new Set()) };
29
+ }
30
+
31
+ exports.createPathResolver = 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"}
@@ -2,9 +2,9 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
2
2
 
3
3
  const acorn = require('acorn');
4
4
  const zod = require('zod');
5
- const util_tracker = require('../util/tracker.js');
6
- const backend_handlerDeclaration = require('./handler-declaration.js');
7
- const backend_messages = require('./messages.js');
5
+ const util_tracker = require('../../util/tracker.js');
6
+ const backend_parser_handlerDeclaration = require('./handler-declaration.js');
7
+ const backend_parser_messages = require('./messages.js');
8
8
 
9
9
  const acornLocSchema = zod.z.object({ line: zod.z.number(), column: zod.z.number() });
10
10
  function isAcornSyntaxError(err) {
@@ -48,19 +48,19 @@ function parseOrThrow(file, code) {
48
48
  const asModule = tryParse(code, 'module');
49
49
  if (asModule.ok) {
50
50
  const { body } = asModule.program;
51
- if (body.some(backend_handlerDeclaration.exportsHandler)) {
52
- throw parseError(backend_messages.messages.mustNotExportHandler(file));
51
+ if (body.some(backend_parser_handlerDeclaration.exportsHandler)) {
52
+ throw parseError(backend_parser_messages.messages.mustNotExportHandler(file));
53
53
  }
54
54
  if (body.some(isImportLike)) {
55
- throw parseError(backend_messages.messages.mustNotImport(file));
55
+ throw parseError(backend_parser_messages.messages.mustNotImport(file));
56
56
  }
57
57
  if (body.some(isExport)) {
58
- throw parseError(backend_messages.messages.mustNotExport(file));
58
+ throw parseError(backend_parser_messages.messages.mustNotExport(file));
59
59
  }
60
- throw parseError(backend_messages.messages.moduleOnlySyntax(file, stripPosition(asScript.error.message)));
60
+ throw parseError(backend_parser_messages.messages.moduleOnlySyntax(file, stripPosition(asScript.error.message)));
61
61
  }
62
62
  const { line, column } = asScript.error.loc;
63
- throw parseError(backend_messages.messages.syntaxError(file, line, column, stripPosition(asScript.error.message)));
63
+ throw parseError(backend_parser_messages.messages.syntaxError(file, line, column, stripPosition(asScript.error.message)));
64
64
  }
65
65
 
66
66
  exports.parseOrThrow = parseOrThrow;
@@ -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,117 @@
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
2
+
3
+ const backend_parser_utils = require('./utils.js');
4
+ const backend_parser_bindings = require('./bindings.js');
5
+
6
+ function resolveLiteral(node) {
7
+ return typeof node.value === 'string' ||
8
+ typeof node.value === 'number' ||
9
+ typeof node.value === 'boolean' ||
10
+ node.value === null
11
+ ? { value: node.value }
12
+ : undefined;
13
+ }
14
+ /** Template holes only interpolate scalars; a resolved object/array (e.g. `$or`) is shown unresolved instead of glued inline. */
15
+ function resolveTemplate(node, source, inner) {
16
+ const text = node.quasis
17
+ .map((quasi, i) => {
18
+ const literalText = quasi.value.cooked ?? quasi.value.raw;
19
+ const hole = node.expressions[i];
20
+ if (!hole) {
21
+ return literalText;
22
+ }
23
+ const resolved = inner(hole);
24
+ const scalar = resolved !== undefined &&
25
+ (typeof resolved.value === 'string' ||
26
+ typeof resolved.value === 'number' ||
27
+ typeof resolved.value === 'boolean' ||
28
+ resolved.value === null);
29
+ return literalText + (scalar ? backend_parser_utils.displayText(resolved.value) : `\${${backend_parser_utils.sourceTextOf(hole, source)}}`);
30
+ })
31
+ .join('');
32
+ return { value: text };
33
+ }
34
+ /**
35
+ * Each element/property resolves independently, falling back to source text. A spread is kept
36
+ * visible under a `...`-prefixed key/value pair rather than silently dropped.
37
+ */
38
+ function resolveContainer(node, source, bindings, inner) {
39
+ const fallbackText = (n) => bestSourceText(n, source, bindings);
40
+ if (node.type === 'ArrayExpression') {
41
+ return {
42
+ value: node.elements.map(element => (element ? backend_parser_utils.resolveOrSourceText(element, source, inner, fallbackText) : null)),
43
+ };
44
+ }
45
+ const result = {};
46
+ for (const prop of node.properties) {
47
+ if (prop.type === 'SpreadElement') {
48
+ const spreadText = backend_parser_utils.sourceTextOf(prop.argument, source);
49
+ result[`...${spreadText}`] = spreadText;
50
+ continue;
51
+ }
52
+ if (prop.type !== 'Property') {
53
+ continue;
54
+ }
55
+ const key = prop.computed
56
+ ? backend_parser_utils.sourceTextOf(prop.key, source)
57
+ : backend_parser_utils.propertyKey(prop.key, false) ?? backend_parser_utils.sourceTextOf(prop.key, source);
58
+ result[key] = backend_parser_utils.resolveOrSourceText(prop.value, source, inner, fallbackText);
59
+ }
60
+ return { value: result };
61
+ }
62
+ function joinBranches(left, right) {
63
+ return left !== undefined && right !== undefined ? { value: { $or: [left.value, right.value] } } : undefined;
64
+ }
65
+ function resolveIdentifier(node, bindings, source, resolving) {
66
+ if (resolving.has(node.name)) {
67
+ return undefined;
68
+ }
69
+ const decl = backend_parser_bindings.declarationAt(bindings, node.name, node.start);
70
+ if (!decl || decl.kind !== 'const' || !decl.init || decl.path?.length !== 0) {
71
+ return undefined;
72
+ }
73
+ return staticValue(decl.init, bindings, source, new Set(resolving).add(node.name));
74
+ }
75
+ /** Source text for a node that failed to resolve — the const declaration's init when the node names one, else the node itself. */
76
+ function bestSourceText(node, source, bindings) {
77
+ if (node.type === 'Identifier') {
78
+ const decl = backend_parser_bindings.declarationAt(bindings, node.name, node.start);
79
+ if (decl && decl.kind === 'const' && decl.init && decl.path?.length === 0) {
80
+ return backend_parser_utils.sourceTextOf(decl.init, source);
81
+ }
82
+ }
83
+ return backend_parser_utils.sourceTextOf(node, source);
84
+ }
85
+ function staticValue(node, bindings, source, resolving) {
86
+ const inner = child => staticValue(child, bindings, source, resolving);
87
+ switch (node.type) {
88
+ case 'Literal':
89
+ return resolveLiteral(node);
90
+ case 'TemplateLiteral':
91
+ return resolveTemplate(node, source, inner);
92
+ case 'ArrayExpression':
93
+ case 'ObjectExpression':
94
+ return resolveContainer(node, source, bindings, inner);
95
+ case 'BinaryExpression': {
96
+ if (node.operator !== '+') {
97
+ return undefined;
98
+ }
99
+ const left = inner(node.left);
100
+ const right = inner(node.right);
101
+ return typeof left?.value === 'string' && typeof right?.value === 'string'
102
+ ? { value: left.value + right.value }
103
+ : undefined;
104
+ }
105
+ case 'ConditionalExpression':
106
+ return joinBranches(inner(node.consequent), inner(node.alternate));
107
+ case 'LogicalExpression':
108
+ return joinBranches(inner(node.left), inner(node.right));
109
+ case 'Identifier':
110
+ return resolveIdentifier(node, bindings, source, resolving);
111
+ default:
112
+ return undefined;
113
+ }
114
+ }
115
+
116
+ exports.bestSourceText = bestSourceText;
117
+ exports.staticValue = 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"}