@mondaydotcomorg/z2h-cli 0.27.1 → 0.28.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 (116) hide show
  1. package/dist/backend/__tests__/ast.test.d.ts +2 -0
  2. package/dist/backend/__tests__/ast.test.d.ts.map +1 -0
  3. package/dist/backend/__tests__/parse.test.d.ts +2 -0
  4. package/dist/backend/__tests__/parse.test.d.ts.map +1 -0
  5. package/dist/backend/__tests__/validate.test.d.ts +2 -0
  6. package/dist/backend/__tests__/validate.test.d.ts.map +1 -0
  7. package/dist/backend/ast.d.ts +41 -0
  8. package/dist/backend/ast.d.ts.map +1 -0
  9. package/dist/backend/ast.js +152 -0
  10. package/dist/backend/detect-integrations.d.ts +8 -4
  11. package/dist/backend/detect-integrations.d.ts.map +1 -1
  12. package/dist/backend/detect-integrations.js +12 -15
  13. package/dist/backend/handler-declaration.d.ts +17 -0
  14. package/dist/backend/handler-declaration.d.ts.map +1 -0
  15. package/dist/backend/handler-declaration.js +83 -0
  16. package/dist/backend/handlers.d.ts +2 -0
  17. package/dist/backend/handlers.d.ts.map +1 -1
  18. package/dist/backend/handlers.js +7 -36
  19. package/dist/backend/messages.d.ts +10 -0
  20. package/dist/backend/messages.d.ts.map +1 -0
  21. package/dist/backend/messages.js +14 -0
  22. package/dist/backend/parse.d.ts +11 -0
  23. package/dist/backend/parse.d.ts.map +1 -0
  24. package/dist/backend/parse.js +66 -0
  25. package/dist/backend/rules/__tests__/snowflake-static-sql.test.d.ts +2 -0
  26. package/dist/backend/rules/__tests__/snowflake-static-sql.test.d.ts.map +1 -0
  27. package/dist/backend/rules/index.d.ts +5 -0
  28. package/dist/backend/rules/index.d.ts.map +1 -0
  29. package/dist/backend/rules/index.js +8 -0
  30. package/dist/backend/rules/snowflake-static-sql.d.ts +15 -0
  31. package/dist/backend/rules/snowflake-static-sql.d.ts.map +1 -0
  32. package/dist/backend/rules/snowflake-static-sql.js +75 -0
  33. package/dist/backend/rules/types.d.ts +29 -0
  34. package/dist/backend/rules/types.d.ts.map +1 -0
  35. package/dist/backend/rules/types.js +1 -0
  36. package/dist/backend/validate.d.ts +23 -0
  37. package/dist/backend/validate.d.ts.map +1 -0
  38. package/dist/backend/validate.js +64 -0
  39. package/dist/commands/__tests__/backend-validate.test.d.ts +2 -0
  40. package/dist/commands/__tests__/backend-validate.test.d.ts.map +1 -0
  41. package/dist/commands/backend.d.ts +6 -0
  42. package/dist/commands/backend.d.ts.map +1 -1
  43. package/dist/commands/backend.js +22 -2
  44. package/dist/constants.d.ts +1 -2
  45. package/dist/constants.d.ts.map +1 -1
  46. package/dist/constants.js +10 -6
  47. package/dist/esm/backend/__tests__/ast.test.d.ts +2 -0
  48. package/dist/esm/backend/__tests__/ast.test.d.ts.map +1 -0
  49. package/dist/esm/backend/__tests__/parse.test.d.ts +2 -0
  50. package/dist/esm/backend/__tests__/parse.test.d.ts.map +1 -0
  51. package/dist/esm/backend/__tests__/validate.test.d.ts +2 -0
  52. package/dist/esm/backend/__tests__/validate.test.d.ts.map +1 -0
  53. package/dist/esm/backend/ast.d.ts +41 -0
  54. package/dist/esm/backend/ast.d.ts.map +1 -0
  55. package/dist/esm/backend/ast.mjs +146 -0
  56. package/dist/esm/backend/detect-integrations.d.ts +8 -4
  57. package/dist/esm/backend/detect-integrations.d.ts.map +1 -1
  58. package/dist/esm/backend/detect-integrations.mjs +12 -15
  59. package/dist/esm/backend/handler-declaration.d.ts +17 -0
  60. package/dist/esm/backend/handler-declaration.d.ts.map +1 -0
  61. package/dist/esm/backend/handler-declaration.mjs +78 -0
  62. package/dist/esm/backend/handlers.d.ts +2 -0
  63. package/dist/esm/backend/handlers.d.ts.map +1 -1
  64. package/dist/esm/backend/handlers.mjs +7 -36
  65. package/dist/esm/backend/messages.d.ts +10 -0
  66. package/dist/esm/backend/messages.d.ts.map +1 -0
  67. package/dist/esm/backend/messages.mjs +12 -0
  68. package/dist/esm/backend/parse.d.ts +11 -0
  69. package/dist/esm/backend/parse.d.ts.map +1 -0
  70. package/dist/esm/backend/parse.mjs +64 -0
  71. package/dist/esm/backend/rules/__tests__/snowflake-static-sql.test.d.ts +2 -0
  72. package/dist/esm/backend/rules/__tests__/snowflake-static-sql.test.d.ts.map +1 -0
  73. package/dist/esm/backend/rules/index.d.ts +5 -0
  74. package/dist/esm/backend/rules/index.d.ts.map +1 -0
  75. package/dist/esm/backend/rules/index.mjs +6 -0
  76. package/dist/esm/backend/rules/snowflake-static-sql.d.ts +15 -0
  77. package/dist/esm/backend/rules/snowflake-static-sql.d.ts.map +1 -0
  78. package/dist/esm/backend/rules/snowflake-static-sql.mjs +73 -0
  79. package/dist/esm/backend/rules/types.d.ts +29 -0
  80. package/dist/esm/backend/rules/types.d.ts.map +1 -0
  81. package/dist/esm/backend/rules/types.mjs +1 -0
  82. package/dist/esm/backend/validate.d.ts +23 -0
  83. package/dist/esm/backend/validate.d.ts.map +1 -0
  84. package/dist/esm/backend/validate.mjs +62 -0
  85. package/dist/esm/commands/__tests__/backend-validate.test.d.ts +2 -0
  86. package/dist/esm/commands/__tests__/backend-validate.test.d.ts.map +1 -0
  87. package/dist/esm/commands/backend.d.ts +6 -0
  88. package/dist/esm/commands/backend.d.ts.map +1 -1
  89. package/dist/esm/commands/backend.mjs +23 -4
  90. package/dist/esm/constants.d.ts +1 -2
  91. package/dist/esm/constants.d.ts.map +1 -1
  92. package/dist/esm/constants.mjs +3 -6
  93. package/dist/esm/index.mjs +6 -2
  94. package/dist/index.js +5 -1
  95. package/package.json +4 -2
  96. package/src/backend/__tests__/ast.test.ts +53 -0
  97. package/src/backend/__tests__/detect-integrations.test.ts +12 -30
  98. package/src/backend/__tests__/handlers.test.ts +21 -34
  99. package/src/backend/__tests__/parse.test.ts +25 -0
  100. package/src/backend/__tests__/validate.test.ts +246 -0
  101. package/src/backend/ast.ts +204 -0
  102. package/src/backend/detect-integrations.ts +12 -14
  103. package/src/backend/handler-declaration.ts +104 -0
  104. package/src/backend/handlers.ts +9 -44
  105. package/src/backend/messages.ts +16 -0
  106. package/src/backend/parse.ts +82 -0
  107. package/src/backend/rules/__tests__/snowflake-static-sql.test.ts +175 -0
  108. package/src/backend/rules/index.ts +7 -0
  109. package/src/backend/rules/snowflake-static-sql.ts +78 -0
  110. package/src/backend/rules/types.ts +30 -0
  111. package/src/backend/validate.ts +73 -0
  112. package/src/commands/__tests__/backend-deploy.test.ts +5 -3
  113. package/src/commands/__tests__/backend-validate.test.ts +71 -0
  114. package/src/commands/backend.ts +23 -3
  115. package/src/constants.ts +5 -6
  116. package/src/index.ts +9 -2
@@ -0,0 +1 @@
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"}
@@ -0,0 +1,78 @@
1
+ /** True for the `handler` identifier specifically — used everywhere a node might name the binding. */
2
+ const isHandlerIdentifier = (candidate) => candidate?.type === 'Identifier' && candidate.name === 'handler';
3
+ /** The top-level declaration that binds `handler`, if any. */
4
+ function findHandlerDeclaration(body) {
5
+ for (const node of body) {
6
+ if (node.type === 'FunctionDeclaration' && isHandlerIdentifier(node.id)) {
7
+ return { kind: 'function', params: node.params };
8
+ }
9
+ if (node.type === 'VariableDeclaration') {
10
+ const declarator = node.declarations.find(d => isHandlerIdentifier(d.id));
11
+ if (declarator) {
12
+ return { kind: 'variable', init: declarator.init };
13
+ }
14
+ }
15
+ }
16
+ return undefined;
17
+ }
18
+ /** `export function handler`, `export const handler`, `export { handler }`, `export default handler`. */
19
+ function exportsHandler(node) {
20
+ if (node.type === 'ExportNamedDeclaration') {
21
+ return ((node.declaration != null && findHandlerDeclaration([node.declaration]) !== undefined) ||
22
+ node.specifiers.some(s => isHandlerIdentifier(s.local) || isHandlerIdentifier(s.exported)));
23
+ }
24
+ if (node.type === 'ExportDefaultDeclaration') {
25
+ const { declaration } = node;
26
+ return ((declaration.type === 'FunctionDeclaration' && isHandlerIdentifier(declaration.id)) ||
27
+ isHandlerIdentifier(declaration));
28
+ }
29
+ return false;
30
+ }
31
+ /** Peel `wrap(fn)`, `(0, fn)`, and the like until a function expression remains. */
32
+ function asFunction(expr) {
33
+ if (!expr) {
34
+ return undefined;
35
+ }
36
+ switch (expr.type) {
37
+ case 'FunctionExpression':
38
+ case 'ArrowFunctionExpression':
39
+ return expr;
40
+ case 'SequenceExpression':
41
+ return asFunction(expr.expressions.at(-1));
42
+ case 'CallExpression': {
43
+ for (const arg of expr.arguments) {
44
+ if (arg.type === 'SpreadElement') {
45
+ continue;
46
+ }
47
+ const fn = asFunction(arg);
48
+ if (fn) {
49
+ return fn;
50
+ }
51
+ }
52
+ return undefined;
53
+ }
54
+ default:
55
+ return undefined;
56
+ }
57
+ }
58
+ function firstParamName(params) {
59
+ let first = params[0];
60
+ if (first?.type === 'AssignmentPattern') {
61
+ first = first.left;
62
+ }
63
+ return first?.type === 'Identifier' ? first.name : undefined;
64
+ }
65
+ /** First positional parameter of `handler`, when it's a plain identifier (`ctx`, `context`, …). */
66
+ function handlerContextParamName(declaration) {
67
+ const params = declaration.kind === 'function' ? declaration.params : asFunction(declaration.init)?.params;
68
+ return params ? firstParamName(params) : undefined;
69
+ }
70
+ /** Values that can never be a function, so `const handler = <this>` is caught at build time. */
71
+ const NEVER_A_FUNCTION = new Set([
72
+ 'Literal',
73
+ 'ObjectExpression',
74
+ 'ArrayExpression',
75
+ 'TemplateLiteral',
76
+ ]);
77
+
78
+ export { NEVER_A_FUNCTION, exportsHandler, findHandlerDeclaration, handlerContextParamName };
@@ -1,6 +1,8 @@
1
1
  export interface ReadHandlersResult {
2
2
  /** handler name (filename without .js) → JS source */
3
3
  handlers: Record<string, string>;
4
+ /** Every `ctx.api.v1.<domain>` any handler touches, sorted and unique. */
5
+ apiDomains: string[];
4
6
  }
5
7
  /**
6
8
  * 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":"AAMA,MAAM,WAAW,kBAAkB;IACjC,sDAAsD;IACtD,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAClC;AA4BD;;;;GAIG;AACH,wBAAsB,YAAY,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,kBAAkB,CAAC,CAuCnF"}
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,31 +1,9 @@
1
1
  import path from 'node:path';
2
2
  import { readdir, readFile } from 'node:fs/promises';
3
3
  import { pathExists } from 'fs-extra';
4
+ import { validateHandlerSource } from './validate.mjs';
4
5
 
5
6
  const HANDLERS_DIR = path.join('backend', 'handlers');
6
- /**
7
- * True if the source defines a `handler` function or variable at the top level.
8
- * Handlers run in a V8 isolate with no module system — `handler` must be a plain
9
- * global, not an export.
10
- */
11
- function definesHandler(source) {
12
- return /\bfunction\s+handler\b/.test(source) || /\b(const|let|var)\s+handler\b/.test(source);
13
- }
14
- /**
15
- * True if `handler` is declared with an `export` prefix. It reads as valid source but
16
- * the isolate has no module system, so an exported handler is simply invisible to the
17
- * runner — caught here rather than failing opaquely at invoke time.
18
- */
19
- function exportsHandler(source) {
20
- return /\bexport\s+(default\s+)?(async\s+)?(function\s+handler\b|(?:const|let|var)\s+handler\b)/.test(source);
21
- }
22
- /**
23
- * True if the source contains any `import` or `require` call. Neither works in
24
- * the V8 isolate — reach the outside world through `ctx` capabilities instead.
25
- */
26
- function hasImports(source) {
27
- return /^\s*import\b/m.test(source) || /\brequire\s*\(/.test(source);
28
- }
29
7
  /**
30
8
  * Reads every `backend/handlers/*.js` file inside `consumerDir` and returns a
31
9
  * map from handler name (filename without `.js`) to source. No compilation —
@@ -34,7 +12,7 @@ function hasImports(source) {
34
12
  async function readHandlers(consumerDir) {
35
13
  const handlersDir = path.join(consumerDir, HANDLERS_DIR);
36
14
  if (!(await pathExists(handlersDir))) {
37
- return { handlers: {} };
15
+ return { handlers: {}, apiDomains: [] };
38
16
  }
39
17
  const entries = await readdir(handlersDir);
40
18
  const tsFiles = entries.filter(f => f.endsWith('.ts'));
@@ -43,25 +21,18 @@ async function readHandlers(consumerDir) {
43
21
  }
44
22
  const jsFiles = entries.filter(f => f.endsWith('.js'));
45
23
  if (jsFiles.length === 0) {
46
- return { handlers: {} };
24
+ return { handlers: {}, apiDomains: [] };
47
25
  }
48
26
  const handlers = {};
27
+ const apiDomains = new Set();
49
28
  for (const file of jsFiles) {
50
29
  const handlerName = path.parse(file).name;
51
30
  const source = await readFile(path.join(handlersDir, file), 'utf8');
52
- // Before the definesHandler check: `export const handler` satisfies that one too.
53
- if (exportsHandler(source)) {
54
- throw new Error(`${file} must not export handler — the isolate has no module system; declare it as a plain global, e.g. async function handler(ctx) { ... }`);
55
- }
56
- if (!definesHandler(source)) {
57
- throw new Error(`${file} must define a handler — e.g. async function handler(ctx) { ... }`);
58
- }
59
- if (hasImports(source)) {
60
- throw new Error(`${file} must not import other files or packages — handlers are self-contained; reach the outside world through ctx capabilities`);
61
- }
31
+ const validation = validateHandlerSource(file, source);
32
+ validation.apiDomains.forEach(d => apiDomains.add(d));
62
33
  handlers[handlerName] = source;
63
34
  }
64
- return { handlers };
35
+ return { handlers, apiDomains: [...apiDomains].sort() };
65
36
  }
66
37
 
67
38
  export { readHandlers };
@@ -0,0 +1,10 @@
1
+ export declare const messages: {
2
+ mustDefine: (file: string) => string;
3
+ notAFunction: (file: string) => string;
4
+ mustNotImport: (file: string) => string;
5
+ mustNotExportHandler: (file: string) => string;
6
+ mustNotExport: (file: string) => string;
7
+ moduleOnlySyntax: (file: string, detail: string) => string;
8
+ syntaxError: (file: string, line: number, column: number, detail: string) => string;
9
+ };
10
+ //# sourceMappingURL=messages.d.ts.map
@@ -0,0 +1 @@
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"}
@@ -0,0 +1,12 @@
1
+ const EXAMPLE = 'async function handler(ctx) { ... }';
2
+ const messages = {
3
+ mustDefine: (file) => `${file} must define a handler — e.g. ${EXAMPLE}`,
4
+ notAFunction: (file) => `${file} declares handler but it is not a function — e.g. ${EXAMPLE}`,
5
+ mustNotImport: (file) => `${file} must not import other files or packages — handlers are self-contained; reach the outside world through ctx capabilities`,
6
+ mustNotExportHandler: (file) => `${file} must not export handler — the isolate has no module system; declare it as a plain global, e.g. ${EXAMPLE}`,
7
+ mustNotExport: (file) => `${file} must not use export — the isolate has no module system; declare handler as a plain global, e.g. ${EXAMPLE}`,
8
+ moduleOnlySyntax: (file, detail) => `${file} uses module-only syntax (${detail}) — handlers run as plain scripts, so top-level await and import.meta are not available`,
9
+ syntaxError: (file, line, column, detail) => `${file}:${line}:${column}: not valid JavaScript — ${detail}`,
10
+ };
11
+
12
+ export { messages };
@@ -0,0 +1,11 @@
1
+ import { type Program } from 'acorn';
2
+ /**
3
+ * The runner compiles handlers with `isolate.compileScript`, i.e. the classic
4
+ * *script* grammar — so that is the grammar we validate against. `import`/`export`
5
+ * declarations and top-level `await`/`import.meta` are only legal under the
6
+ * *module* grammar, so a handler using any of them fails the script parse; we
7
+ * re-parse it as a module purely to name which of those four things it was,
8
+ * instead of surfacing V8's bare "Unexpected token 'export'".
9
+ */
10
+ export declare function parseOrThrow(file: string, code: string): Program;
11
+ //# sourceMappingURL=parse.d.ts.map
@@ -0,0 +1 @@
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"}
@@ -0,0 +1,64 @@
1
+ import { parse } from 'acorn';
2
+ import { z } from 'zod';
3
+ import { trackEvent } from '../util/tracker.mjs';
4
+ import { exportsHandler } from './handler-declaration.mjs';
5
+ import { messages } from './messages.mjs';
6
+
7
+ const acornLocSchema = z.object({ line: z.number(), column: z.number() });
8
+ function isAcornSyntaxError(err) {
9
+ return err instanceof SyntaxError && acornLocSchema.safeParse(err.loc).success;
10
+ }
11
+ function tryParse(code, sourceType) {
12
+ try {
13
+ return { ok: true, program: parse(code, { ecmaVersion: 'latest', sourceType, locations: true }) };
14
+ }
15
+ catch (err) {
16
+ if (isAcornSyntaxError(err)) {
17
+ return { ok: false, error: err };
18
+ }
19
+ throw err;
20
+ }
21
+ }
22
+ /** Acorn appends ` (line:col)` to its messages; we report the position ourselves. */
23
+ const stripPosition = (message) => message.replace(/ \(\d+:\d+\)$/, '');
24
+ const isImportLike = (node) => node.type === 'ImportDeclaration' ||
25
+ node.type === 'ExportAllDeclaration' ||
26
+ (node.type === 'ExportNamedDeclaration' && node.source != null);
27
+ const isExport = (node) => node.type === 'ExportNamedDeclaration' || node.type === 'ExportDefaultDeclaration';
28
+ /** Reports the failure, then returns the error for the caller to throw. */
29
+ function parseError(message) {
30
+ void trackEvent('z2h_cli_handler_parse_error', { error: message });
31
+ return new Error(message);
32
+ }
33
+ /**
34
+ * The runner compiles handlers with `isolate.compileScript`, i.e. the classic
35
+ * *script* grammar — so that is the grammar we validate against. `import`/`export`
36
+ * declarations and top-level `await`/`import.meta` are only legal under the
37
+ * *module* grammar, so a handler using any of them fails the script parse; we
38
+ * re-parse it as a module purely to name which of those four things it was,
39
+ * instead of surfacing V8's bare "Unexpected token 'export'".
40
+ */
41
+ function parseOrThrow(file, code) {
42
+ const asScript = tryParse(code, 'script');
43
+ if (asScript.ok) {
44
+ return asScript.program;
45
+ }
46
+ const asModule = tryParse(code, 'module');
47
+ if (asModule.ok) {
48
+ const { body } = asModule.program;
49
+ if (body.some(exportsHandler)) {
50
+ throw parseError(messages.mustNotExportHandler(file));
51
+ }
52
+ if (body.some(isImportLike)) {
53
+ throw parseError(messages.mustNotImport(file));
54
+ }
55
+ if (body.some(isExport)) {
56
+ throw parseError(messages.mustNotExport(file));
57
+ }
58
+ throw parseError(messages.moduleOnlySyntax(file, stripPosition(asScript.error.message)));
59
+ }
60
+ const { line, column } = asScript.error.loc;
61
+ throw parseError(messages.syntaxError(file, line, column, stripPosition(asScript.error.message)));
62
+ }
63
+
64
+ export { parseOrThrow };
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=snowflake-static-sql.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"snowflake-static-sql.test.d.ts","sourceRoot":"","sources":["../../../../../src/backend/rules/__tests__/snowflake-static-sql.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,5 @@
1
+ import type { HandlerRule } from './types';
2
+ export type { HandlerRule, RuleContext } from './types';
3
+ /** Every rule the validator runs, in order. Add new capability rules here. */
4
+ export declare const HANDLER_RULES: readonly HandlerRule[];
5
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/backend/rules/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAG3C,YAAY,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAExD,8EAA8E;AAC9E,eAAO,MAAM,aAAa,EAAE,SAAS,WAAW,EAAmC,CAAC"}
@@ -0,0 +1,6 @@
1
+ import { SnowflakeStaticSqlRule } from './snowflake-static-sql.mjs';
2
+
3
+ /** Every rule the validator runs, in order. Add new capability rules here. */
4
+ const HANDLER_RULES = [new SnowflakeStaticSqlRule()];
5
+
6
+ export { HANDLER_RULES };
@@ -0,0 +1,15 @@
1
+ import type { HandlerRule, RuleContext } from './types';
2
+ /**
3
+ * `ctx.api.v1.snowflake.query(sql, params?, options?)` — the SQL text must live
4
+ * in the handler. The frontend chooses *which* handler to call and supplies
5
+ * `params` / `options`; it never ships SQL. Binding placeholders (`:name`) are
6
+ * how client values reach the query.
7
+ *
8
+ * The call is matched through `const` aliases of the channel
9
+ * (`const sf = ctx.api.v1.snowflake; sf.query(…)`), see `PathResolver`.
10
+ */
11
+ export declare class SnowflakeStaticSqlRule implements HandlerRule {
12
+ readonly name = "snowflake/static-sql";
13
+ check({ file, program, bindings, paths }: RuleContext): string[];
14
+ }
15
+ //# sourceMappingURL=snowflake-static-sql.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"snowflake-static-sql.d.ts","sourceRoot":"","sources":["../../../../src/backend/rules/snowflake-static-sql.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAgDxD;;;;;;;;GAQG;AACH,qBAAa,sBAAuB,YAAW,WAAW;IACxD,QAAQ,CAAC,IAAI,0BAA0B;IAEvC,KAAK,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,EAAE,WAAW,GAAG,MAAM,EAAE;CAcjE"}
@@ -0,0 +1,73 @@
1
+ import { simple } from 'acorn-walk';
2
+ import { lineOf } from '../ast.mjs';
3
+
4
+ const SNOWFLAKE_QUERY = 'ctx.api.v1.snowflake.query';
5
+ const message = (file, line) => `${file}${line ? `:${line}` : ''}: ${SNOWFLAKE_QUERY} must receive SQL written in the handler — a string literal, ` +
6
+ `or a variable bound to one. Client-supplied values go through params (\`:name\` bindings) and options, never into the SQL text.`;
7
+ /**
8
+ * True when every possible value of `node` is text authored in this file:
9
+ * string literals, templates whose holes are themselves static, `+`
10
+ * concatenation, either branch of a conditional, and identifiers that resolve
11
+ * (within the file) to such values. Anything reaching outside the file —
12
+ * `ctx.input`, calls, member reads, destructuring — is not static.
13
+ */
14
+ function isStaticSql(node, bindings, resolving) {
15
+ if (!node) {
16
+ return false;
17
+ }
18
+ const staticChild = (child) => isStaticSql(child, bindings, resolving);
19
+ switch (node.type) {
20
+ case 'Literal':
21
+ return typeof node.value === 'string';
22
+ case 'TemplateLiteral':
23
+ return node.expressions.every(staticChild);
24
+ case 'BinaryExpression':
25
+ return node.operator === '+' && staticChild(node.left) && staticChild(node.right);
26
+ case 'ConditionalExpression':
27
+ return staticChild(node.consequent) && staticChild(node.alternate);
28
+ case 'LogicalExpression':
29
+ return staticChild(node.left) && staticChild(node.right);
30
+ case 'Identifier': {
31
+ const { name } = node;
32
+ if (bindings.unpinnable.has(name) || resolving.has(name)) {
33
+ return false;
34
+ }
35
+ const decls = bindings.declarations.get(name);
36
+ if (!decls || decls.length === 0) {
37
+ return false;
38
+ }
39
+ const next = new Set(resolving).add(name);
40
+ return decls.every(d => d.path?.length === 0 && isStaticSql(d.init, bindings, next));
41
+ }
42
+ default:
43
+ return false;
44
+ }
45
+ }
46
+ /**
47
+ * `ctx.api.v1.snowflake.query(sql, params?, options?)` — the SQL text must live
48
+ * in the handler. The frontend chooses *which* handler to call and supplies
49
+ * `params` / `options`; it never ships SQL. Binding placeholders (`:name`) are
50
+ * how client values reach the query.
51
+ *
52
+ * The call is matched through `const` aliases of the channel
53
+ * (`const sf = ctx.api.v1.snowflake; sf.query(…)`), see `PathResolver`.
54
+ */
55
+ class SnowflakeStaticSqlRule {
56
+ name = 'snowflake/static-sql';
57
+ check({ file, program, bindings, paths }) {
58
+ const violations = [];
59
+ simple(program, {
60
+ CallExpression(node) {
61
+ if (paths.pathOf(node.callee) !== SNOWFLAKE_QUERY) {
62
+ return;
63
+ }
64
+ if (!isStaticSql(node.arguments[0], bindings, new Set())) {
65
+ violations.push(message(file, lineOf(node)));
66
+ }
67
+ },
68
+ });
69
+ return violations;
70
+ }
71
+ }
72
+
73
+ export { SnowflakeStaticSqlRule };
@@ -0,0 +1,29 @@
1
+ import type { Program } from 'acorn';
2
+ import type { Bindings, PathResolver } from '../ast';
3
+ export interface RuleContext {
4
+ /** Handler file name, used to prefix messages. */
5
+ file: string;
6
+ /** Parsed with `locations: true`, so rules can point at a line. */
7
+ program: Program;
8
+ /** Every variable binding in the file — see `collectBindings`. */
9
+ bindings: Bindings;
10
+ /** Resolves member chains through `const` aliases — see `createPathResolver`. */
11
+ paths: PathResolver;
12
+ }
13
+ /**
14
+ * A capability-specific check that runs once the handler is structurally valid
15
+ * (parses as a script, defines `handler`, imports nothing).
16
+ *
17
+ * Rules return human-readable violations rather than throwing so the validator
18
+ * can report every problem in one pass — agent-generated handlers are fixed in
19
+ * a loop, and one round-trip per violation is slow.
20
+ *
21
+ * Implement as a class (see `SnowflakeStaticSqlRule`) and add an instance to
22
+ * `HANDLER_RULES` in `./index.ts` — keeps every rule the same shape to read.
23
+ */
24
+ export interface HandlerRule {
25
+ /** Stable identifier, e.g. `snowflake/static-sql`. */
26
+ name: string;
27
+ check(ctx: RuleContext): string[];
28
+ }
29
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../../src/backend/rules/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,OAAO,CAAC;AACrC,OAAO,KAAK,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAC;AAErD,MAAM,WAAW,WAAW;IAC1B,kDAAkD;IAClD,IAAI,EAAE,MAAM,CAAC;IACb,mEAAmE;IACnE,OAAO,EAAE,OAAO,CAAC;IACjB,kEAAkE;IAClE,QAAQ,EAAE,QAAQ,CAAC;IACnB,iFAAiF;IACjF,KAAK,EAAE,YAAY,CAAC;CACrB;AAED;;;;;;;;;;GAUG;AACH,MAAM,WAAW,WAAW;IAC1B,sDAAsD;IACtD,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,GAAG,EAAE,WAAW,GAAG,MAAM,EAAE,CAAC;CACnC"}
@@ -0,0 +1 @@
1
+
@@ -0,0 +1,23 @@
1
+ export interface HandlerValidation {
2
+ /** Every `ctx.api.v1.<domain>` the handler touches (known or not), sorted and unique. */
3
+ apiDomains: string[];
4
+ }
5
+ /**
6
+ * Validates a handler's source before upload: real parsing (via acorn) catches
7
+ * syntax errors at build time instead of an opaque failure inside the isolate.
8
+ * Handlers run with no module system and no bundler — `handler` must be a plain
9
+ * top-level global, and imports/requires (which would resolve to nothing at
10
+ * runtime) are rejected.
11
+ *
12
+ * Once the handler is structurally sound, capability-specific rules from
13
+ * `./rules` run and every violation is reported at once.
14
+ *
15
+ * Unknown `ctx.api.v1.<domain>` usage is a warning, not a failure: this pass is
16
+ * build-time DX feedback for agent-generated code, never a security boundary —
17
+ * the isolate has no ambient capabilities regardless of what a handler contains.
18
+ *
19
+ * Returns the `ctx.api.v1.*` domains the handler touches so callers (integration
20
+ * detection) can reuse the parse instead of re-scanning the source.
21
+ */
22
+ export declare function validateHandlerSource(file: string, source: string): HandlerValidation;
23
+ //# sourceMappingURL=validate.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validate.d.ts","sourceRoot":"","sources":["../../../src/backend/validate.ts"],"names":[],"mappings":"AAWA,MAAM,WAAW,iBAAiB;IAChC,yFAAyF;IACzF,UAAU,EAAE,MAAM,EAAE,CAAC;CACtB;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,iBAAiB,CAuCrF"}
@@ -0,0 +1,62 @@
1
+ import { simple } from 'acorn-walk';
2
+ import { ALWAYS_ON_CHANNELS, DECLARED_INTEGRATIONS } from '@mondaydotcomorg/z2h-shared-utils';
3
+ import { warn } from '../util/logger.mjs';
4
+ import { collectBindings, createPathResolver, collectApiDomains } from './ast.mjs';
5
+ import { findHandlerDeclaration, NEVER_A_FUNCTION, handlerContextParamName } from './handler-declaration.mjs';
6
+ import { messages } from './messages.mjs';
7
+ import { parseOrThrow } from './parse.mjs';
8
+ import { HANDLER_RULES } from './rules/index.mjs';
9
+
10
+ const KNOWN_API_DOMAINS = [...ALWAYS_ON_CHANNELS, ...DECLARED_INTEGRATIONS];
11
+ /**
12
+ * Validates a handler's source before upload: real parsing (via acorn) catches
13
+ * syntax errors at build time instead of an opaque failure inside the isolate.
14
+ * Handlers run with no module system and no bundler — `handler` must be a plain
15
+ * top-level global, and imports/requires (which would resolve to nothing at
16
+ * runtime) are rejected.
17
+ *
18
+ * Once the handler is structurally sound, capability-specific rules from
19
+ * `./rules` run and every violation is reported at once.
20
+ *
21
+ * Unknown `ctx.api.v1.<domain>` usage is a warning, not a failure: this pass is
22
+ * build-time DX feedback for agent-generated code, never a security boundary —
23
+ * the isolate has no ambient capabilities regardless of what a handler contains.
24
+ *
25
+ * Returns the `ctx.api.v1.*` domains the handler touches so callers (integration
26
+ * detection) can reuse the parse instead of re-scanning the source.
27
+ */
28
+ function validateHandlerSource(file, source) {
29
+ const program = parseOrThrow(file, source);
30
+ const bindings = collectBindings(program);
31
+ simple(program, {
32
+ CallExpression(node) {
33
+ if (node.callee.type === 'Identifier' && node.callee.name === 'require') {
34
+ throw new Error(messages.mustNotImport(file));
35
+ }
36
+ },
37
+ ImportExpression() {
38
+ throw new Error(messages.mustNotImport(file));
39
+ },
40
+ });
41
+ const declaration = findHandlerDeclaration(program.body);
42
+ if (!declaration) {
43
+ throw new Error(messages.mustDefine(file));
44
+ }
45
+ if (declaration.kind === 'variable' && (!declaration.init || NEVER_A_FUNCTION.has(declaration.init.type))) {
46
+ throw new Error(messages.notAFunction(file));
47
+ }
48
+ const paths = createPathResolver(bindings, handlerContextParamName(declaration));
49
+ const apiDomains = collectApiDomains(program, paths);
50
+ const violations = HANDLER_RULES.flatMap(rule => rule.check({ file, program, bindings, paths }));
51
+ if (violations.length > 0) {
52
+ throw new Error(violations.join('\n'));
53
+ }
54
+ for (const domain of apiDomains) {
55
+ if (!KNOWN_API_DOMAINS.includes(domain)) {
56
+ warn(`${file}: ctx.api.v1.${domain} is not a known capability (available: ${KNOWN_API_DOMAINS.join(', ')})`);
57
+ }
58
+ }
59
+ return { apiDomains: [...apiDomains].sort() };
60
+ }
61
+
62
+ export { validateHandlerSource };
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=backend-validate.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"backend-validate.test.d.ts","sourceRoot":"","sources":["../../../../src/commands/__tests__/backend-validate.test.ts"],"names":[],"mappings":""}
@@ -28,6 +28,12 @@ export declare function deployBackend(opts: {
28
28
  deployedBy: string;
29
29
  isPreview: boolean;
30
30
  }): Promise<string[]>;
31
+ /**
32
+ * Run the same handler validation deploy runs (syntax, isolate constraints,
33
+ * handler rules, integration detection) against the working tree — without
34
+ * uploading anything. Throws on the first invalid handler.
35
+ */
36
+ export declare function backendValidateCommand(appDir?: string): Promise<void>;
31
37
  export declare function backendInvokeCommand(handlerName: string, opts?: {
32
38
  input?: string;
33
39
  }): Promise<void>;
@@ -1 +1 @@
1
- {"version":3,"file":"backend.d.ts","sourceRoot":"","sources":["../../../src/commands/backend.ts"],"names":[],"mappings":"AAoBA;;;;GAIG;AACH,wBAAgB,WAAW,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAEnD;AAmCD;;;;;;;;;;;;;;;GAeG;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,wBAAsB,oBAAoB,CAAC,WAAW,EAAE,MAAM,EAAE,IAAI,GAAE;IAAE,KAAK,CAAC,EAAE,MAAM,CAAA;CAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAa5G"}
1
+ {"version":3,"file":"backend.d.ts","sourceRoot":"","sources":["../../../src/commands/backend.ts"],"names":[],"mappings":"AAoBA;;;;GAIG;AACH,wBAAgB,WAAW,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAEnD;AAmCD;;;;;;;;;;;;;;;GAeG;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;;;;GAIG;AACH,wBAAsB,sBAAsB,CAAC,MAAM,GAAE,MAAsB,GAAG,OAAO,CAAC,IAAI,CAAC,CAa1F;AAED,wBAAsB,oBAAoB,CAAC,WAAW,EAAE,MAAM,EAAE,IAAI,GAAE;IAAE,KAAK,CAAC,EAAE,MAAM,CAAA;CAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAa5G"}
@@ -4,7 +4,7 @@ import { PutObjectCommand } from '@aws-sdk/client-s3';
4
4
  import { output, info } from '../util/logger.mjs';
5
5
  import { getCwdAppName, mfAppName } from '../util/app-name.mjs';
6
6
  import { readHandlers } from '../backend/handlers.mjs';
7
- import { detectIntegrationsFromHandlers } from '../backend/detect-integrations.mjs';
7
+ import { detectIntegrations } from '../backend/detect-integrations.mjs';
8
8
  import { getS3Client } from '../util/s3/client.mjs';
9
9
  import { BUCKET_WRITE_NAME } from '../constants.mjs';
10
10
  import { invokeBackend } from '../backend/client.mjs';
@@ -36,8 +36,8 @@ async function readDetectAndUpload(appDir, prefix, version, deployedBy, logLabel
36
36
  return [];
37
37
  }
38
38
  info(`reading backend handlers ${logLabel}`);
39
- const { handlers } = await readHandlers(appDir);
40
- const integrations = detectIntegrationsFromHandlers(handlers);
39
+ const { handlers, apiDomains } = await readHandlers(appDir);
40
+ const integrations = detectIntegrations(apiDomains);
41
41
  if (Object.keys(handlers).length === 0) {
42
42
  return integrations;
43
43
  }
@@ -77,6 +77,25 @@ async function deployBackend(opts) {
77
77
  throw tagDeployError('deploy_backend_error', err);
78
78
  }
79
79
  }
80
+ /**
81
+ * Run the same handler validation deploy runs (syntax, isolate constraints,
82
+ * handler rules, integration detection) against the working tree — without
83
+ * uploading anything. Throws on the first invalid handler.
84
+ */
85
+ async function backendValidateCommand(appDir = process.cwd()) {
86
+ if (!hasHandlers(appDir)) {
87
+ output('[z2h-cli] no backend/handlers/ directory — nothing to validate', { handlers: [], integrations: [] });
88
+ return;
89
+ }
90
+ const { handlers, apiDomains } = await readHandlers(appDir);
91
+ const names = Object.keys(handlers).sort();
92
+ const integrations = detectIntegrations(apiDomains);
93
+ const list = (xs) => (xs.length ? xs.join(', ') : 'none');
94
+ output(`[z2h-cli] ${names.length} handler(s) valid: ${list(names)}\n[z2h-cli] integrations: ${list(integrations)}`, {
95
+ handlers: names,
96
+ integrations,
97
+ });
98
+ }
80
99
  async function backendInvokeCommand(handlerName, opts = {}) {
81
100
  const appName = currentAppName();
82
101
  let input = null;
@@ -92,4 +111,4 @@ async function backendInvokeCommand(handlerName, opts = {}) {
92
111
  output(`[z2h-cli] result (${Math.round(res.durationMs)}ms):\n${JSON.stringify(res.result, null, 2)}`, res);
93
112
  }
94
113
 
95
- export { backendInvokeCommand, deployBackend, hasHandlers };
114
+ export { backendInvokeCommand, backendValidateCommand, deployBackend, hasHandlers };
@@ -20,8 +20,7 @@ export declare const S3_SKILLS_BUCKET_NAME = "prod-use1-bigbrain-zth-skills";
20
20
  export declare const DATAVIZ_SKILLS_PREFIX = "dataviz/";
21
21
  export declare const APP_NAME_PATTERN: RegExp;
22
22
  export declare const PREVIEW_APP_NAME_PREFIX = "zth-preview-";
23
- export declare const DECLARED_INTEGRATIONS: readonly ["monday"];
24
- export type DeclaredIntegration = (typeof DECLARED_INTEGRATIONS)[number];
23
+ export { ALWAYS_ON_CHANNELS, DECLARED_INTEGRATIONS, type DeclaredIntegration } from '@mondaydotcomorg/z2h-shared-utils';
25
24
  export declare const DEFAULT_BROKER_BASE_URL = "https://bigbrain-zth.bigbrain.me";
26
25
  /**
27
26
  * Resolves the broker origin (no trailing slash). Honors
@@ -1 +1 @@
1
- {"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../../src/constants.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,eAAO,MAAM,eAAe,SAAS,CAAC;AAGtC,eAAO,MAAM,cAAc,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAEjD,CAAC;AAKF,eAAO,MAAM,eAAe,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAElD,CAAC;AAMF,eAAO,MAAM,QAAQ,QAAQ,CAAC;AAC9B,eAAO,MAAM,QAAQ,QAAQ,CAAC;AAG9B,eAAO,MAAM,iBAAiB,UAAY,CAAC;AAQ3C,eAAO,MAAM,iBAAiB,qCAAqC,CAAC;AACpE,eAAO,MAAM,MAAM,cAAc,CAAC;AAClC,eAAO,MAAM,gBAAgB,wEAA4D,CAAC;AAE1F,eAAO,MAAM,oBAAoB,2BAA2B,CAAC;AAC7D,eAAO,MAAM,mBAAmB,+CAAgD,CAAC;AAKjF,eAAO,MAAM,kBAAkB,aAAa,CAAC;AAK7C,eAAO,MAAM,YAAY,cAAc,CAAC;AACxC,eAAO,MAAM,iBAAiB,yDAA2C,CAAC;AAM1E,eAAO,MAAM,qBAAqB,kCAAkC,CAAC;AAIrE,eAAO,MAAM,qBAAqB,aAAa,CAAC;AAMhD,eAAO,MAAM,gBAAgB,QAA2B,CAAC;AAEzD,eAAO,MAAM,uBAAuB,iBAAiB,CAAC;AAMtD,eAAO,MAAM,qBAAqB,qBAAsB,CAAC;AACzD,MAAM,MAAM,mBAAmB,GAAG,CAAC,OAAO,qBAAqB,CAAC,CAAC,MAAM,CAAC,CAAC;AAKzE,eAAO,MAAM,uBAAuB,qCAAqC,CAAC;AAE1E;;;;GAIG;AACH,wBAAgB,aAAa,IAAI,MAAM,CAEtC;AAID,wBAAgB,cAAc,IAAI,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAGvD;AAKD,eAAO,MAAM,eAAe,iBAAiB,CAAC;AAG9C,eAAO,MAAM,gBAAgB,qBAAqB,CAAC;AAGnD,eAAO,MAAM,uBAAuB,gCAAgC,CAAC;AAMrE,eAAO,MAAM,iBAAiB,EAAG,eAAwB,CAAC;AAE1D;;;;;GAKG;AACH,wBAAgB,oBAAoB,IAAI,MAAM,CAE7C"}
1
+ {"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../../src/constants.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,eAAO,MAAM,eAAe,SAAS,CAAC;AAGtC,eAAO,MAAM,cAAc,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAEjD,CAAC;AAKF,eAAO,MAAM,eAAe,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAElD,CAAC;AAMF,eAAO,MAAM,QAAQ,QAAQ,CAAC;AAC9B,eAAO,MAAM,QAAQ,QAAQ,CAAC;AAG9B,eAAO,MAAM,iBAAiB,UAAY,CAAC;AAQ3C,eAAO,MAAM,iBAAiB,qCAAqC,CAAC;AACpE,eAAO,MAAM,MAAM,cAAc,CAAC;AAClC,eAAO,MAAM,gBAAgB,wEAA4D,CAAC;AAE1F,eAAO,MAAM,oBAAoB,2BAA2B,CAAC;AAC7D,eAAO,MAAM,mBAAmB,+CAAgD,CAAC;AAKjF,eAAO,MAAM,kBAAkB,aAAa,CAAC;AAK7C,eAAO,MAAM,YAAY,cAAc,CAAC;AACxC,eAAO,MAAM,iBAAiB,yDAA2C,CAAC;AAM1E,eAAO,MAAM,qBAAqB,kCAAkC,CAAC;AAIrE,eAAO,MAAM,qBAAqB,aAAa,CAAC;AAMhD,eAAO,MAAM,gBAAgB,QAA2B,CAAC;AAEzD,eAAO,MAAM,uBAAuB,iBAAiB,CAAC;AAMtD,OAAO,EAAE,kBAAkB,EAAE,qBAAqB,EAAE,KAAK,mBAAmB,EAAE,MAAM,mCAAmC,CAAC;AAKxH,eAAO,MAAM,uBAAuB,qCAAqC,CAAC;AAE1E;;;;GAIG;AACH,wBAAgB,aAAa,IAAI,MAAM,CAEtC;AAID,wBAAgB,cAAc,IAAI,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAGvD;AAKD,eAAO,MAAM,eAAe,iBAAiB,CAAC;AAG9C,eAAO,MAAM,gBAAgB,qBAAqB,CAAC;AAGnD,eAAO,MAAM,uBAAuB,gCAAgC,CAAC;AAMrE,eAAO,MAAM,iBAAiB,EAAG,eAAwB,CAAC;AAE1D;;;;;GAKG;AACH,wBAAgB,oBAAoB,IAAI,MAAM,CAE7C"}