@mondaydotcomorg/z2h-cli 0.34.1 → 0.34.2

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 (125) hide show
  1. package/CHANGELOG.md +2969 -0
  2. package/dist/backend/__tests__/ast.test.d.ts +2 -0
  3. package/dist/backend/__tests__/ast.test.d.ts.map +1 -0
  4. package/dist/backend/__tests__/parse.test.d.ts +2 -0
  5. package/dist/backend/__tests__/parse.test.d.ts.map +1 -0
  6. package/dist/backend/ast.d.ts +41 -0
  7. package/dist/backend/ast.d.ts.map +1 -0
  8. package/dist/backend/ast.js +152 -0
  9. package/dist/backend/handler-declaration.d.ts +17 -0
  10. package/dist/backend/handler-declaration.d.ts.map +1 -0
  11. package/dist/backend/handler-declaration.js +83 -0
  12. package/dist/backend/messages.d.ts +10 -0
  13. package/dist/backend/messages.d.ts.map +1 -0
  14. package/dist/backend/messages.js +14 -0
  15. package/dist/backend/parse.d.ts +11 -0
  16. package/dist/backend/parse.d.ts.map +1 -0
  17. package/dist/backend/parse.js +66 -0
  18. package/dist/backend/rules/__tests__/snowflake-static-sql.test.d.ts +2 -0
  19. package/dist/backend/rules/__tests__/snowflake-static-sql.test.d.ts.map +1 -0
  20. package/dist/backend/rules/index.d.ts +5 -0
  21. package/dist/backend/rules/index.d.ts.map +1 -0
  22. package/dist/backend/rules/index.js +8 -0
  23. package/dist/backend/rules/snowflake-static-sql.d.ts +15 -0
  24. package/dist/backend/rules/snowflake-static-sql.d.ts.map +1 -0
  25. package/dist/backend/rules/snowflake-static-sql.js +75 -0
  26. package/dist/backend/rules/types.d.ts +29 -0
  27. package/dist/backend/rules/types.d.ts.map +1 -0
  28. package/dist/backend/rules/types.js +1 -0
  29. package/dist/commands/__tests__/delete.test.d.ts +2 -0
  30. package/dist/commands/__tests__/delete.test.d.ts.map +1 -0
  31. package/dist/commands/backend.d.ts +0 -1
  32. package/dist/commands/backend.d.ts.map +1 -1
  33. package/dist/commands/backend.js +4 -4
  34. package/dist/commands/deploy.d.ts.map +1 -1
  35. package/dist/commands/deploy.js +7 -5
  36. package/dist/constants.d.ts +2 -1
  37. package/dist/constants.d.ts.map +1 -1
  38. package/dist/constants.js +12 -0
  39. package/dist/esm/backend/__tests__/ast.test.d.ts +2 -0
  40. package/dist/esm/backend/__tests__/ast.test.d.ts.map +1 -0
  41. package/dist/esm/backend/__tests__/parse.test.d.ts +2 -0
  42. package/dist/esm/backend/__tests__/parse.test.d.ts.map +1 -0
  43. package/dist/esm/backend/ast.d.ts +41 -0
  44. package/dist/esm/backend/ast.d.ts.map +1 -0
  45. package/dist/esm/backend/ast.mjs +146 -0
  46. package/dist/esm/backend/handler-declaration.d.ts +17 -0
  47. package/dist/esm/backend/handler-declaration.d.ts.map +1 -0
  48. package/dist/esm/backend/handler-declaration.mjs +78 -0
  49. package/dist/esm/backend/messages.d.ts +10 -0
  50. package/dist/esm/backend/messages.d.ts.map +1 -0
  51. package/dist/esm/backend/messages.mjs +12 -0
  52. package/dist/esm/backend/parse.d.ts +11 -0
  53. package/dist/esm/backend/parse.d.ts.map +1 -0
  54. package/dist/esm/backend/parse.mjs +64 -0
  55. package/dist/esm/backend/rules/__tests__/snowflake-static-sql.test.d.ts +2 -0
  56. package/dist/esm/backend/rules/__tests__/snowflake-static-sql.test.d.ts.map +1 -0
  57. package/dist/esm/backend/rules/index.d.ts +5 -0
  58. package/dist/esm/backend/rules/index.d.ts.map +1 -0
  59. package/dist/esm/backend/rules/index.mjs +6 -0
  60. package/dist/esm/backend/rules/snowflake-static-sql.d.ts +15 -0
  61. package/dist/esm/backend/rules/snowflake-static-sql.d.ts.map +1 -0
  62. package/dist/esm/backend/rules/snowflake-static-sql.mjs +73 -0
  63. package/dist/esm/backend/rules/types.d.ts +29 -0
  64. package/dist/esm/backend/rules/types.d.ts.map +1 -0
  65. package/dist/esm/backend/rules/types.mjs +1 -0
  66. package/dist/esm/commands/__tests__/delete.test.d.ts +2 -0
  67. package/dist/esm/commands/__tests__/delete.test.d.ts.map +1 -0
  68. package/dist/esm/commands/backend.d.ts +0 -1
  69. package/dist/esm/commands/backend.d.ts.map +1 -1
  70. package/dist/esm/commands/backend.mjs +4 -4
  71. package/dist/esm/commands/deploy.d.ts.map +1 -1
  72. package/dist/esm/commands/deploy.mjs +7 -5
  73. package/dist/esm/constants.d.ts +2 -1
  74. package/dist/esm/constants.d.ts.map +1 -1
  75. package/dist/esm/constants.mjs +5 -2
  76. package/dist/esm/util/__tests__/usage-upload.test.d.ts +2 -0
  77. package/dist/esm/util/__tests__/usage-upload.test.d.ts.map +1 -0
  78. package/dist/esm/util/auth/__tests__/index.test.d.ts +2 -0
  79. package/dist/esm/util/auth/__tests__/index.test.d.ts.map +1 -0
  80. package/dist/esm/util/auth/broker-credential-provider.d.ts +6 -1
  81. package/dist/esm/util/auth/broker-credential-provider.d.ts.map +1 -1
  82. package/dist/esm/util/auth/broker-credential-provider.mjs +2 -2
  83. package/dist/esm/util/auth/index.d.ts +3 -0
  84. package/dist/esm/util/auth/index.d.ts.map +1 -0
  85. package/dist/esm/util/auth/index.mjs +2 -0
  86. package/dist/esm/util/broker/app.d.ts +0 -1
  87. package/dist/esm/util/broker/app.d.ts.map +1 -1
  88. package/dist/esm/util/broker/app.mjs +3 -4
  89. package/dist/esm/util/usage-json.d.ts +2 -2
  90. package/dist/esm/util/usage-json.d.ts.map +1 -1
  91. package/dist/esm/util/usage-json.mjs +5 -2
  92. package/dist/esm/util/usage-upload.d.ts +3 -0
  93. package/dist/esm/util/usage-upload.d.ts.map +1 -0
  94. package/dist/esm/util/usage-upload.mjs +29 -0
  95. package/dist/util/__tests__/usage-upload.test.d.ts +2 -0
  96. package/dist/util/__tests__/usage-upload.test.d.ts.map +1 -0
  97. package/dist/util/auth/__tests__/index.test.d.ts +2 -0
  98. package/dist/util/auth/__tests__/index.test.d.ts.map +1 -0
  99. package/dist/util/auth/broker-credential-provider.d.ts +6 -1
  100. package/dist/util/auth/broker-credential-provider.d.ts.map +1 -1
  101. package/dist/util/auth/broker-credential-provider.js +2 -2
  102. package/dist/util/auth/index.d.ts +3 -0
  103. package/dist/util/auth/index.d.ts.map +1 -0
  104. package/dist/util/auth/index.js +11 -0
  105. package/dist/util/broker/app.d.ts +0 -1
  106. package/dist/util/broker/app.d.ts.map +1 -1
  107. package/dist/util/broker/app.js +3 -4
  108. package/dist/util/usage-json.d.ts +2 -2
  109. package/dist/util/usage-json.d.ts.map +1 -1
  110. package/dist/util/usage-json.js +5 -2
  111. package/dist/util/usage-upload.d.ts +3 -0
  112. package/dist/util/usage-upload.d.ts.map +1 -0
  113. package/dist/util/usage-upload.js +31 -0
  114. package/package.json +3 -3
  115. package/src/commands/__tests__/backend-deploy.test.ts +2 -4
  116. package/src/commands/__tests__/deploy.test.ts +43 -11
  117. package/src/commands/backend.ts +4 -5
  118. package/src/commands/deploy.ts +9 -5
  119. package/src/constants.ts +6 -0
  120. package/src/util/__tests__/usage-upload.test.ts +58 -0
  121. package/src/util/auth/__tests__/broker-credential-provider.test.ts +4 -4
  122. package/src/util/auth/broker-credential-provider.ts +4 -4
  123. package/src/util/broker/app.ts +2 -15
  124. package/src/util/usage-json.ts +11 -4
  125. package/src/util/usage-upload.ts +38 -0
@@ -1 +1 @@
1
- {"version":3,"file":"deploy.d.ts","sourceRoot":"","sources":["../../src/commands/deploy.ts"],"names":[],"mappings":"AAmBA,OAAO,EAAE,KAAK,UAAU,EAA2C,MAAM,4BAA4B,CAAC;AAatG,MAAM,WAAW,aAAa;IAC5B,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,MAAM,CAAC,EAAE,UAAU,CAAC;IACpB,OAAO,CAAC,EAAE,MAAM,CAAC;IAEjB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IAIrB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAWD,wBAAsB,aAAa,CAAC,IAAI,GAAE,aAAkB,GAAG,OAAO,CAAC,IAAI,CAAC,CAyB3E"}
1
+ {"version":3,"file":"deploy.d.ts","sourceRoot":"","sources":["../../src/commands/deploy.ts"],"names":[],"mappings":"AAoBA,OAAO,EAAE,KAAK,UAAU,EAA2C,MAAM,4BAA4B,CAAC;AAatG,MAAM,WAAW,aAAa;IAC5B,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,MAAM,CAAC,EAAE,UAAU,CAAC;IACpB,OAAO,CAAC,EAAE,MAAM,CAAC;IAEjB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IAIrB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAWD,wBAAsB,aAAa,CAAC,IAAI,GAAE,aAAkB,GAAG,OAAO,CAAC,IAAI,CAAC,CAyB3E"}
@@ -12,6 +12,7 @@ const util_auth_authStore = require('../util/auth/auth-store.js');
12
12
  const util_appName = require('../util/app-name.js');
13
13
  const util_git_repo = require('../util/git/repo.js');
14
14
  const util_usageJson = require('../util/usage-json.js');
15
+ const util_usageUpload = require('../util/usage-upload.js');
15
16
  const util_git_gitEnv = require('../util/git/git-env.js');
16
17
  const util_git_remoteOptions = require('../util/git/remote-options.js');
17
18
  const util_s3_client = require('../util/s3/client.js');
@@ -89,7 +90,7 @@ async function uploadAndRegister(opts) {
89
90
  const { paths, keyPrefix, appName, token, nextVersion, entry, gitRemote, isPreview, description, masterAppName } = opts;
90
91
  // Runs before the frontend upload so a `deployBackend` failure can't leave a
91
92
  // preview's unversioned `MF` dir overwritten with no rollback.
92
- const { integrations, handlerNames, apiUsages } = await commands_backend.deployBackend({
93
+ const { integrations, handlerNames } = await commands_backend.deployBackend({
93
94
  appDir: process.cwd(),
94
95
  appName,
95
96
  mfKeyPrefix: keyPrefix,
@@ -108,7 +109,6 @@ async function uploadAndRegister(opts) {
108
109
  gitRemote,
109
110
  integrations,
110
111
  handlerNames,
111
- apiUsages,
112
112
  description,
113
113
  masterAppName,
114
114
  });
@@ -142,7 +142,7 @@ async function deployPreview({ paths, consumerName, appName, token, opts }) {
142
142
  const url = `${z2hSharedUtils.BUCKET_READ_DNS_URL}/${keyPrefix}`;
143
143
  // No catch-all: every stage below tags its own DeployError reason at the throw site,
144
144
  // and anything unclassified reports as `unknown` via reasonOf() in runCommand.
145
- const nextVersion = (await util_auth_brokerCredentialProvider.fetchDeployVersion(previewAppName)) + 1;
145
+ const nextVersion = (await util_auth_brokerCredentialProvider.fetchDeployVersion(previewAppName)).version + 1;
146
146
  util_logger.info('building');
147
147
  const entry = await buildAndStamp({
148
148
  paths,
@@ -207,9 +207,10 @@ async function deployLive({ paths, consumerName, appName, token, opts }) {
207
207
  await util_git_repo.initRepo(process.cwd(), remote);
208
208
  gitRemote = remote;
209
209
  }
210
- const version = await util_auth_brokerCredentialProvider.fetchDeployVersion(appName);
210
+ const { version, id: appId } = await util_auth_brokerCredentialProvider.fetchDeployVersion(appName);
211
211
  const nextVersion = version + 1;
212
212
  const gitEnv = await util_git_gitEnv.resolveGitEnv(appName, gitRemote);
213
+ let usage = {};
213
214
  // Sync git first so a divergence (GitConflictError) stops us.
214
215
  // The skill commits the working tree (with an LLM-authored message) before
215
216
  // invoking deploy, so the tree should be clean here.
@@ -218,7 +219,7 @@ async function deployLive({ paths, consumerName, appName, token, opts }) {
218
219
  await util_git_repo.guardCleanTree(process.cwd());
219
220
  util_logger.info('syncing with git remote');
220
221
  await util_git_repo.pullAndResolve(process.cwd(), gitEnv);
221
- await util_usageJson.updateOrCreateUsageJson(process.cwd(), appName, util_machineIdentity.whoAmI());
222
+ usage = await util_usageJson.updateOrCreateUsageJson(process.cwd(), appName, util_machineIdentity.whoAmI());
222
223
  }
223
224
  catch (err) {
224
225
  throw util_errors.tagDeployError('git_error', err);
@@ -275,6 +276,7 @@ async function deployLive({ paths, consumerName, appName, token, opts }) {
275
276
  util_logger.info('releasing deploy lock');
276
277
  await releaseLockBestEffort(appName, token);
277
278
  }
279
+ await util_usageUpload.putAppUsage(appName, appId, usage, nextVersion);
278
280
  // Tags are a post-deploy concern: the S3 upload has already succeeded, so a
279
281
  // tag failure never fails the deploy (handled inside).
280
282
  await handleDeployTags(appName);
@@ -8,7 +8,7 @@ export declare const SHADOW_DEV_DEPS: Record<string, string>;
8
8
  export declare const MIN_PORT = 13000;
9
9
  export declare const MAX_PORT = 19999;
10
10
  export declare const GITIGNORE_ENTRIES: string[];
11
- export { ALWAYS_ON_CHANNELS, APP_NAME_PATTERN, BUCKET_READ_DNS_NAME, BUCKET_READ_DNS_URL, BUCKET_WRITE_NAME, BUCKET_WRITE_URL, DATAVIZ_SKILLS_PREFIX, DECLARED_INTEGRATIONS, MANIFEST_KEY, MANIFEST_READ_URL, PREVIEW_APP_NAME_PREFIX, REGION, S3_PREVIEWS_FOLDER, S3_SKILLS_BUCKET_NAME, type DeclaredIntegration, } from '@mondaydotcomorg/z2h-shared-utils';
11
+ export { ALWAYS_ON_CHANNELS, APP_USAGE_BUCKET_NAME, appUsageFolder, APP_NAME_PATTERN, BUCKET_READ_DNS_NAME, BUCKET_READ_DNS_URL, BUCKET_WRITE_NAME, BUCKET_WRITE_URL, DATAVIZ_SKILLS_PREFIX, DECLARED_INTEGRATIONS, MANIFEST_KEY, MANIFEST_READ_URL, PREVIEW_APP_NAME_PREFIX, REGION, S3_PREVIEWS_FOLDER, S3_SKILLS_BUCKET_NAME, type DeclaredIntegration, } from '@mondaydotcomorg/z2h-shared-utils';
12
12
  export declare const DEFAULT_BROKER_BASE_URL = "https://bigbrain-zth.bigbrain.me";
13
13
  /**
14
14
  * Resolves the broker origin (no trailing slash). Honors
@@ -16,6 +16,7 @@ export declare const DEFAULT_BROKER_BASE_URL = "https://bigbrain-zth.bigbrain.me
16
16
  * STS credential provider and the npm-broker registry URL.
17
17
  */
18
18
  export declare function brokerBaseUrl(): string;
19
+ export declare function isProdBroker(): boolean;
19
20
  export declare function routingHeaders(): Record<string, string>;
20
21
  export declare const NPM_BROKER_PATH = "/z2h-cli/npm";
21
22
  export declare const BROKER_NPM_SCOPE = "@mondaydotcomorg";
@@ -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;AAI3C,OAAO,EACL,kBAAkB,EAClB,gBAAgB,EAChB,oBAAoB,EACpB,mBAAmB,EACnB,iBAAiB,EACjB,gBAAgB,EAChB,qBAAqB,EACrB,qBAAqB,EACrB,YAAY,EACZ,iBAAiB,EACjB,uBAAuB,EACvB,MAAM,EACN,kBAAkB,EAClB,qBAAqB,EACrB,KAAK,mBAAmB,GACzB,MAAM,mCAAmC,CAAC;AAK3C,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;AAI3C,OAAO,EACL,kBAAkB,EAClB,qBAAqB,EACrB,cAAc,EACd,gBAAgB,EAChB,oBAAoB,EACpB,mBAAmB,EACnB,iBAAiB,EACjB,gBAAgB,EAChB,qBAAqB,EACrB,qBAAqB,EACrB,YAAY,EACZ,iBAAiB,EACjB,uBAAuB,EACvB,MAAM,EACN,kBAAkB,EAClB,qBAAqB,EACrB,KAAK,mBAAmB,GACzB,MAAM,mCAAmC,CAAC;AAK3C,eAAO,MAAM,uBAAuB,qCAAqC,CAAC;AAE1E;;;;GAIG;AACH,wBAAgB,aAAa,IAAI,MAAM,CAEtC;AAED,wBAAgB,YAAY,IAAI,OAAO,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"}
package/dist/constants.js CHANGED
@@ -38,6 +38,9 @@ const DEFAULT_BROKER_BASE_URL = 'https://bigbrain-zth.bigbrain.me';
38
38
  function brokerBaseUrl() {
39
39
  return process.env.Z2H_BROKER_BASE_URL || DEFAULT_BROKER_BASE_URL;
40
40
  }
41
+ function isProdBroker() {
42
+ return brokerBaseUrl() === DEFAULT_BROKER_BASE_URL;
43
+ }
41
44
  // Returns Baggage header for monday-mirror routing when Z2H_ROUTING_KEY is set.
42
45
  // No-op in production (returns {}) — only activates when the env var is set.
43
46
  function routingHeaders() {
@@ -75,6 +78,10 @@ Object.defineProperty(exports, 'APP_NAME_PATTERN', {
75
78
  enumerable: true,
76
79
  get: () => z2hSharedUtils.APP_NAME_PATTERN
77
80
  });
81
+ Object.defineProperty(exports, 'APP_USAGE_BUCKET_NAME', {
82
+ enumerable: true,
83
+ get: () => z2hSharedUtils.APP_USAGE_BUCKET_NAME
84
+ });
78
85
  Object.defineProperty(exports, 'BUCKET_READ_DNS_NAME', {
79
86
  enumerable: true,
80
87
  get: () => z2hSharedUtils.BUCKET_READ_DNS_NAME
@@ -123,6 +130,10 @@ Object.defineProperty(exports, 'S3_SKILLS_BUCKET_NAME', {
123
130
  enumerable: true,
124
131
  get: () => z2hSharedUtils.S3_SKILLS_BUCKET_NAME
125
132
  });
133
+ Object.defineProperty(exports, 'appUsageFolder', {
134
+ enumerable: true,
135
+ get: () => z2hSharedUtils.appUsageFolder
136
+ });
126
137
  exports.BROKER_NPM_SCOPE = BROKER_NPM_SCOPE;
127
138
  exports.DEFAULT_BROKER_BASE_URL = DEFAULT_BROKER_BASE_URL;
128
139
  exports.GITIGNORE_ENTRIES = GITIGNORE_ENTRIES;
@@ -136,4 +147,5 @@ exports.SHADOW_SCRIPTS = SHADOW_SCRIPTS;
136
147
  exports.Z2H_NPM_TOKEN_ENV = Z2H_NPM_TOKEN_ENV;
137
148
  exports.brokerBaseUrl = brokerBaseUrl;
138
149
  exports.brokerNpmRegistryUrl = brokerNpmRegistryUrl;
150
+ exports.isProdBroker = isProdBroker;
139
151
  exports.routingHeaders = routingHeaders;
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=ast.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ast.test.d.ts","sourceRoot":"","sources":["../../../../src/backend/__tests__/ast.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=parse.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parse.test.d.ts","sourceRoot":"","sources":["../../../../src/backend/__tests__/parse.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,41 @@
1
+ import type { AnyNode, Expression, Node, Pattern, Program, VariableDeclaration } from 'acorn';
2
+ /** 1-based line a node starts on; requires the program to be parsed with `locations: true`. */
3
+ export declare const lineOf: (node: Node) => number | undefined;
4
+ export interface Declaration {
5
+ kind: VariableDeclaration['kind'];
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
+ }
14
+ export interface Bindings {
15
+ /** Every `var|let|const <name> = …` in the file, by name. */
16
+ declarations: Map<string, Declaration[]>;
17
+ /** Names whose value cannot be pinned: reassigned, updated, or bound as parameters. */
18
+ unpinnable: Set<string>;
19
+ }
20
+ /** Every identifier a binding pattern introduces (`{ a, b: [c] } = …` → a, c). */
21
+ export declare const patternNames: (pattern: Pattern) => string[];
22
+ export declare function collectBindings(program: Program): Bindings;
23
+ export interface PathResolver {
24
+ /**
25
+ * Dotted path of a member chain, following `const` aliases back to their
26
+ * source: with `const sf = ctx.api.v1.snowflake`, `sf.query` resolves to
27
+ * `ctx.api.v1.snowflake.query`. Destructuring counts too
28
+ * (`const { snowflake: sf } = ctx.api.v1`). `undefined` if any link is dynamic.
29
+ *
30
+ * Only single, never-reassigned, never-shadowed `const` bindings are followed —
31
+ * anything else is left as written, so a `let` alias or a parameter of the same
32
+ * name is never mistaken for the channel. The handler's first parameter is
33
+ * treated as `ctx` even when renamed (`handler(context)` → `context.api.v1.db`
34
+ * resolves as `ctx.api.v1.db`).
35
+ */
36
+ pathOf(node: AnyNode): string | undefined;
37
+ }
38
+ export declare function createPathResolver(bindings: Bindings, contextParam?: string): PathResolver;
39
+ /** Every `ctx.api.v1.<domain>` the program touches (known or not), through `paths`. */
40
+ export declare function collectApiDomains(program: Program, paths: PathResolver): Set<string>;
41
+ //# sourceMappingURL=ast.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ast.d.ts","sourceRoot":"","sources":["../../../src/backend/ast.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,UAAU,EAAE,IAAI,EAAE,OAAO,EAAE,OAAO,EAAE,mBAAmB,EAAE,MAAM,OAAO,CAAC;AAG9F,+FAA+F;AAC/F,eAAO,MAAM,MAAM,GAAI,MAAM,IAAI,KAAG,MAAM,GAAG,SAAiC,CAAC;AAI/E,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,mBAAmB,CAAC,MAAM,CAAC,CAAC;IAClC,IAAI,EAAE,UAAU,GAAG,IAAI,GAAG,SAAS,CAAC;IACpC;;;;OAIG;IACH,IAAI,EAAE,MAAM,EAAE,GAAG,SAAS,CAAC;CAC5B;AAED,MAAM,WAAW,QAAQ;IACvB,6DAA6D;IAC7D,YAAY,EAAE,GAAG,CAAC,MAAM,EAAE,WAAW,EAAE,CAAC,CAAC;IACzC,uFAAuF;IACvF,UAAU,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;CACzB;AA8CD,kFAAkF;AAClF,eAAO,MAAM,YAAY,GAAI,SAAS,OAAO,KAAG,MAAM,EAAmD,CAAC;AAE1G,wBAAgB,eAAe,CAAC,OAAO,EAAE,OAAO,GAAG,QAAQ,CA4C1D;AA2BD,MAAM,WAAW,YAAY;IAC3B;;;;;;;;;;;OAWG;IACH,MAAM,CAAC,IAAI,EAAE,OAAO,GAAG,MAAM,GAAG,SAAS,CAAC;CAC3C;AAED,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,QAAQ,EAAE,YAAY,CAAC,EAAE,MAAM,GAAG,YAAY,CA6B1F;AAED,uFAAuF;AACvF,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,YAAY,GAAG,GAAG,CAAC,MAAM,CAAC,CAWpF"}
@@ -0,0 +1,146 @@
1
+ import { full, simple } from 'acorn-walk';
2
+
3
+ /** 1-based line a node starts on; requires the program to be parsed with `locations: true`. */
4
+ const lineOf = (node) => node.loc?.start.line;
5
+ /**
6
+ * Every identifier a binding pattern introduces, with its property path from the
7
+ * pattern's value. `path` is deliberately not defaulted: callers pass `[]` for
8
+ * the root and `undefined` once the pattern stops being a plain property read.
9
+ */
10
+ function patternBindings(pattern, path) {
11
+ switch (pattern.type) {
12
+ case 'Identifier':
13
+ return [{ name: pattern.name, path }];
14
+ case 'ObjectPattern':
15
+ return pattern.properties.flatMap(p => {
16
+ if (p.type === 'RestElement') {
17
+ return patternBindings(p.argument, undefined);
18
+ }
19
+ const key = propertyKey(p.key, p.computed);
20
+ return patternBindings(p.value, path && key !== undefined ? [...path, key] : undefined);
21
+ });
22
+ case 'ArrayPattern':
23
+ return pattern.elements.flatMap(e => (e ? patternBindings(e, undefined) : []));
24
+ case 'AssignmentPattern':
25
+ return patternBindings(pattern.left, undefined);
26
+ case 'RestElement':
27
+ return patternBindings(pattern.argument, undefined);
28
+ default:
29
+ // MemberExpression targets (`obj.x = …`) bind no names.
30
+ return [];
31
+ }
32
+ }
33
+ function propertyKey(key, computed) {
34
+ if (key.type === 'Literal' && typeof key.value === 'string') {
35
+ return key.value;
36
+ }
37
+ if (!computed && key.type === 'Identifier') {
38
+ return key.name;
39
+ }
40
+ return undefined;
41
+ }
42
+ /** Every identifier a binding pattern introduces (`{ a, b: [c] } = …` → a, c). */
43
+ const patternNames = (pattern) => patternBindings(pattern, []).map(b => b.name);
44
+ function collectBindings(program) {
45
+ const declarations = new Map();
46
+ const unpinnable = new Set();
47
+ const markUnpinnable = (pattern) => patternNames(pattern).forEach(n => unpinnable.add(n));
48
+ full(program, node => {
49
+ switch (node.type) {
50
+ case 'VariableDeclaration':
51
+ for (const declarator of node.declarations) {
52
+ for (const { name, path } of patternBindings(declarator.id, [])) {
53
+ const list = declarations.get(name) ?? [];
54
+ list.push({ kind: node.kind, init: declarator.init, path });
55
+ declarations.set(name, list);
56
+ }
57
+ }
58
+ break;
59
+ case 'AssignmentExpression':
60
+ markUnpinnable(node.left);
61
+ break;
62
+ case 'UpdateExpression':
63
+ if (node.argument.type === 'Identifier') {
64
+ unpinnable.add(node.argument.name);
65
+ }
66
+ break;
67
+ case 'ForInStatement':
68
+ case 'ForOfStatement':
69
+ if (node.left.type !== 'VariableDeclaration') {
70
+ markUnpinnable(node.left);
71
+ }
72
+ break;
73
+ case 'FunctionDeclaration':
74
+ case 'FunctionExpression':
75
+ case 'ArrowFunctionExpression':
76
+ node.params.forEach(markUnpinnable);
77
+ break;
78
+ case 'CatchClause':
79
+ if (node.param) {
80
+ markUnpinnable(node.param);
81
+ }
82
+ break;
83
+ }
84
+ });
85
+ return { declarations, unpinnable };
86
+ }
87
+ /** `a.b.c` / `a['b'].c` → root `a`, parts `[b, c]`; `undefined` if any link is dynamic or the root is not an identifier. */
88
+ function memberChain(node) {
89
+ if (node.type === 'ChainExpression') {
90
+ return memberChain(node.expression);
91
+ }
92
+ const parts = [];
93
+ let cur = node;
94
+ while (cur.type === 'MemberExpression') {
95
+ const key = propertyKey(cur.property, cur.computed);
96
+ if (key === undefined) {
97
+ return undefined;
98
+ }
99
+ parts.unshift(key);
100
+ cur = cur.object;
101
+ }
102
+ return cur.type === 'Identifier' ? { root: cur.name, parts } : undefined;
103
+ }
104
+ function createPathResolver(bindings, contextParam) {
105
+ function resolveChain(node, resolving) {
106
+ const chain = memberChain(node);
107
+ if (!chain) {
108
+ return undefined;
109
+ }
110
+ return [resolveRoot(chain.root, resolving), ...chain.parts].join('.');
111
+ }
112
+ function resolveRoot(name, resolving) {
113
+ if (contextParam !== undefined && name === contextParam) {
114
+ return 'ctx';
115
+ }
116
+ if (bindings.unpinnable.has(name) || resolving.has(name)) {
117
+ return name;
118
+ }
119
+ const decls = bindings.declarations.get(name);
120
+ if (!decls || decls.length !== 1) {
121
+ return name;
122
+ }
123
+ const [{ kind, init, path }] = decls;
124
+ if (kind !== 'const' || !init || !path) {
125
+ return name;
126
+ }
127
+ const base = resolveChain(init, new Set(resolving).add(name));
128
+ return base ? [base, ...path].join('.') : name;
129
+ }
130
+ return { pathOf: node => resolveChain(node, new Set()) };
131
+ }
132
+ /** Every `ctx.api.v1.<domain>` the program touches (known or not), through `paths`. */
133
+ function collectApiDomains(program, paths) {
134
+ const apiDomains = new Set();
135
+ simple(program, {
136
+ MemberExpression(node) {
137
+ const [obj, api, version, domain] = paths.pathOf(node)?.split('.') ?? [];
138
+ if (obj === 'ctx' && api === 'api' && version === 'v1' && domain) {
139
+ apiDomains.add(domain);
140
+ }
141
+ },
142
+ });
143
+ return apiDomains;
144
+ }
145
+
146
+ export { collectApiDomains, collectBindings, createPathResolver, lineOf, patternNames };
@@ -0,0 +1,17 @@
1
+ import type { Expression, FunctionDeclaration, ModuleDeclaration, Statement } from 'acorn';
2
+ export type HandlerDeclaration = {
3
+ kind: 'function';
4
+ params: FunctionDeclaration['params'];
5
+ } | {
6
+ kind: 'variable';
7
+ init: Expression | null | undefined;
8
+ };
9
+ /** The top-level declaration that binds `handler`, if any. */
10
+ export declare function findHandlerDeclaration(body: readonly (Statement | ModuleDeclaration)[]): HandlerDeclaration | undefined;
11
+ /** `export function handler`, `export const handler`, `export { handler }`, `export default handler`. */
12
+ export declare function exportsHandler(node: Statement | ModuleDeclaration): boolean;
13
+ /** First positional parameter of `handler`, when it's a plain identifier (`ctx`, `context`, …). */
14
+ export declare function handlerContextParamName(declaration: HandlerDeclaration): string | undefined;
15
+ /** Values that can never be a function, so `const handler = <this>` is caught at build time. */
16
+ export declare const NEVER_A_FUNCTION: ReadonlySet<string>;
17
+ //# sourceMappingURL=handler-declaration.d.ts.map
@@ -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 };
@@ -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"}