@hypequery/cli 1.22.0 → 1.23.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 (156) hide show
  1. package/dist/bin/cli.js +77 -12
  2. package/dist/cli.d.ts.map +1 -1
  3. package/dist/cli.js +20 -15
  4. package/dist/commands/dev.d.ts.map +1 -1
  5. package/dist/commands/dev.js +25 -5
  6. package/dist/commands/generate-datasets.d.ts +0 -6
  7. package/dist/commands/generate-datasets.d.ts.map +1 -1
  8. package/dist/commands/generate-datasets.js +17 -1
  9. package/dist/commands/generate-manifest.d.ts.map +1 -1
  10. package/dist/commands/generate-manifest.js +4 -0
  11. package/dist/commands/generate.d.ts.map +1 -1
  12. package/dist/commands/generate.js +14 -1
  13. package/dist/commands/init.d.ts.map +1 -1
  14. package/dist/commands/init.js +80 -55
  15. package/dist/commands/mcp.d.ts.map +1 -1
  16. package/dist/commands/mcp.js +47 -10
  17. package/dist/commands/telemetry.d.ts +3 -0
  18. package/dist/commands/telemetry.d.ts.map +1 -0
  19. package/dist/commands/telemetry.js +19 -0
  20. package/dist/generators/chdb.d.ts +3 -0
  21. package/dist/generators/chdb.d.ts.map +1 -1
  22. package/dist/generators/chdb.js +2 -0
  23. package/dist/generators/clickhouse.d.ts +3 -1
  24. package/dist/generators/clickhouse.d.ts.map +1 -1
  25. package/dist/generators/clickhouse.js +2 -0
  26. package/dist/typegen/generate-types.d.ts +3 -0
  27. package/dist/typegen/generate-types.d.ts.map +1 -1
  28. package/dist/typegen/generate-types.js +5 -1
  29. package/dist/typegen/type-parsing.d.ts +1 -1
  30. package/dist/typegen/type-parsing.d.ts.map +1 -1
  31. package/dist/typegen/type-parsing.js +11 -7
  32. package/dist/utils/chdb-gitignore-entry.d.ts +2 -0
  33. package/dist/utils/chdb-gitignore-entry.d.ts.map +1 -0
  34. package/dist/utils/chdb-gitignore-entry.js +17 -0
  35. package/dist/utils/cli-version.d.ts +2 -0
  36. package/dist/utils/cli-version.d.ts.map +1 -0
  37. package/dist/utils/cli-version.js +11 -0
  38. package/dist/utils/cloud-credential-store.d.ts.map +1 -1
  39. package/dist/utils/cloud-credential-store.js +2 -13
  40. package/dist/utils/command-exit.d.ts +13 -0
  41. package/dist/utils/command-exit.d.ts.map +1 -0
  42. package/dist/utils/command-exit.js +31 -0
  43. package/dist/utils/config-directory.d.ts +3 -0
  44. package/dist/utils/config-directory.d.ts.map +1 -0
  45. package/dist/utils/config-directory.js +14 -0
  46. package/dist/utils/detect-database-environment.d.ts +3 -0
  47. package/dist/utils/detect-database-environment.d.ts.map +1 -0
  48. package/dist/utils/detect-database-environment.js +8 -0
  49. package/dist/utils/detect-database.d.ts.map +1 -1
  50. package/dist/utils/detect-database.js +4 -8
  51. package/dist/utils/init-options.d.ts +11 -0
  52. package/dist/utils/init-options.d.ts.map +1 -0
  53. package/dist/utils/init-options.js +28 -0
  54. package/dist/utils/load-api.d.ts +2 -0
  55. package/dist/utils/load-api.d.ts.map +1 -1
  56. package/dist/utils/load-api.js +50 -51
  57. package/dist/utils/load-env-files.d.ts +10 -0
  58. package/dist/utils/load-env-files.d.ts.map +1 -0
  59. package/dist/utils/load-env-files.js +27 -0
  60. package/dist/utils/project-root.d.ts +14 -0
  61. package/dist/utils/project-root.d.ts.map +1 -0
  62. package/dist/utils/project-root.js +41 -0
  63. package/dist/utils/telemetry/buckets.d.ts +5 -0
  64. package/dist/utils/telemetry/buckets.d.ts.map +1 -0
  65. package/dist/utils/telemetry/buckets.js +23 -0
  66. package/dist/utils/telemetry/catalog-docs.d.ts +3 -0
  67. package/dist/utils/telemetry/catalog-docs.d.ts.map +1 -0
  68. package/dist/utils/telemetry/catalog-docs.js +52 -0
  69. package/dist/utils/telemetry/catalog.d.ts +1124 -0
  70. package/dist/utils/telemetry/catalog.d.ts.map +1 -0
  71. package/dist/utils/telemetry/catalog.js +154 -0
  72. package/dist/utils/telemetry/command-context.d.ts +17 -0
  73. package/dist/utils/telemetry/command-context.d.ts.map +1 -0
  74. package/dist/utils/telemetry/command-context.js +30 -0
  75. package/dist/utils/telemetry/config-schema.d.ts +12 -0
  76. package/dist/utils/telemetry/config-schema.d.ts.map +1 -0
  77. package/dist/utils/telemetry/config-schema.js +33 -0
  78. package/dist/utils/telemetry/config-store.d.ts +35 -0
  79. package/dist/utils/telemetry/config-store.d.ts.map +1 -0
  80. package/dist/utils/telemetry/config-store.js +147 -0
  81. package/dist/utils/telemetry/delivery.d.ts +13 -0
  82. package/dist/utils/telemetry/delivery.d.ts.map +1 -0
  83. package/dist/utils/telemetry/delivery.js +26 -0
  84. package/dist/utils/telemetry/detached-dispatch.d.ts +12 -0
  85. package/dist/utils/telemetry/detached-dispatch.d.ts.map +1 -0
  86. package/dist/utils/telemetry/detached-dispatch.js +33 -0
  87. package/dist/utils/telemetry/detached-sender.d.ts +2 -0
  88. package/dist/utils/telemetry/detached-sender.d.ts.map +1 -0
  89. package/dist/utils/telemetry/detached-sender.js +31 -0
  90. package/dist/utils/telemetry/dev-session.d.ts +15 -0
  91. package/dist/utils/telemetry/dev-session.d.ts.map +1 -0
  92. package/dist/utils/telemetry/dev-session.js +25 -0
  93. package/dist/utils/telemetry/domains.d.ts +69 -0
  94. package/dist/utils/telemetry/domains.d.ts.map +1 -0
  95. package/dist/utils/telemetry/domains.js +64 -0
  96. package/dist/utils/telemetry/endpoint.d.ts +3 -0
  97. package/dist/utils/telemetry/endpoint.d.ts.map +1 -0
  98. package/dist/utils/telemetry/endpoint.js +15 -0
  99. package/dist/utils/telemetry/environment.d.ts +27 -0
  100. package/dist/utils/telemetry/environment.d.ts.map +1 -0
  101. package/dist/utils/telemetry/environment.js +95 -0
  102. package/dist/utils/telemetry/error-code.d.ts +4 -0
  103. package/dist/utils/telemetry/error-code.d.ts.map +1 -0
  104. package/dist/utils/telemetry/error-code.js +57 -0
  105. package/dist/utils/telemetry/flags.d.ts +5 -0
  106. package/dist/utils/telemetry/flags.d.ts.map +1 -0
  107. package/dist/utils/telemetry/flags.js +41 -0
  108. package/dist/utils/telemetry/generation-metrics.d.ts +15 -0
  109. package/dist/utils/telemetry/generation-metrics.d.ts.map +1 -0
  110. package/dist/utils/telemetry/generation-metrics.js +35 -0
  111. package/dist/utils/telemetry/identity.d.ts +12 -0
  112. package/dist/utils/telemetry/identity.d.ts.map +1 -0
  113. package/dist/utils/telemetry/identity.js +42 -0
  114. package/dist/utils/telemetry/init-funnel.d.ts +15 -0
  115. package/dist/utils/telemetry/init-funnel.d.ts.map +1 -0
  116. package/dist/utils/telemetry/init-funnel.js +25 -0
  117. package/dist/utils/telemetry/invocation.d.ts +22 -0
  118. package/dist/utils/telemetry/invocation.d.ts.map +1 -0
  119. package/dist/utils/telemetry/invocation.js +46 -0
  120. package/dist/utils/telemetry/lifecycle.d.ts +32 -0
  121. package/dist/utils/telemetry/lifecycle.d.ts.map +1 -0
  122. package/dist/utils/telemetry/lifecycle.js +99 -0
  123. package/dist/utils/telemetry/mcp-session.d.ts +10 -0
  124. package/dist/utils/telemetry/mcp-session.d.ts.map +1 -0
  125. package/dist/utils/telemetry/mcp-session.js +36 -0
  126. package/dist/utils/telemetry/notice.d.ts +11 -0
  127. package/dist/utils/telemetry/notice.d.ts.map +1 -0
  128. package/dist/utils/telemetry/notice.js +24 -0
  129. package/dist/utils/telemetry/opt-out.d.ts +16 -0
  130. package/dist/utils/telemetry/opt-out.d.ts.map +1 -0
  131. package/dist/utils/telemetry/opt-out.js +32 -0
  132. package/dist/utils/telemetry/post-json.d.ts +13 -0
  133. package/dist/utils/telemetry/post-json.d.ts.map +1 -0
  134. package/dist/utils/telemetry/post-json.js +32 -0
  135. package/dist/utils/telemetry/project-context.d.ts +15 -0
  136. package/dist/utils/telemetry/project-context.d.ts.map +1 -0
  137. package/dist/utils/telemetry/project-context.js +86 -0
  138. package/dist/utils/telemetry/schema.d.ts +72 -0
  139. package/dist/utils/telemetry/schema.d.ts.map +1 -0
  140. package/dist/utils/telemetry/schema.js +17 -0
  141. package/dist/utils/telemetry/session-config.d.ts +6 -0
  142. package/dist/utils/telemetry/session-config.d.ts.map +1 -0
  143. package/dist/utils/telemetry/session-config.js +17 -0
  144. package/dist/utils/telemetry/settings-lock.d.ts +36 -0
  145. package/dist/utils/telemetry/settings-lock.d.ts.map +1 -0
  146. package/dist/utils/telemetry/settings-lock.js +102 -0
  147. package/dist/utils/telemetry/transport.d.ts +25 -0
  148. package/dist/utils/telemetry/transport.d.ts.map +1 -0
  149. package/dist/utils/telemetry/transport.js +76 -0
  150. package/dist/utils/telemetry/validation.d.ts +10 -0
  151. package/dist/utils/telemetry/validation.d.ts.map +1 -0
  152. package/dist/utils/telemetry/validation.js +77 -0
  153. package/dist/utils/telemetry/value-formats.d.ts +30 -0
  154. package/dist/utils/telemetry/value-formats.d.ts.map +1 -0
  155. package/dist/utils/telemetry/value-formats.js +13 -0
  156. package/package.json +12 -8
@@ -167,19 +167,19 @@ function getPrimitiveTsType(type) {
167
167
  * Converts a ClickHouse type string, as returned by `DESCRIBE TABLE`, into the
168
168
  * equivalent TypeScript type string.
169
169
  */
170
- export const clickhouseToTsType = (type) => {
170
+ export const clickhouseToTsType = (type, onUnsupported) => {
171
171
  const normalizedType = type.trim();
172
172
  const wrappedArrayType = unwrapType(normalizedType, 'Array');
173
173
  if (wrappedArrayType) {
174
- return `Array<${clickhouseToTsType(wrappedArrayType)}>`;
174
+ return `Array<${clickhouseToTsType(wrappedArrayType, onUnsupported)}>`;
175
175
  }
176
176
  const wrappedNullableType = unwrapType(normalizedType, 'Nullable');
177
177
  if (wrappedNullableType) {
178
- return `${clickhouseToTsType(wrappedNullableType)} | null`;
178
+ return `${clickhouseToTsType(wrappedNullableType, onUnsupported)} | null`;
179
179
  }
180
180
  const wrappedLowCardinalityType = unwrapType(normalizedType, 'LowCardinality');
181
181
  if (wrappedLowCardinalityType) {
182
- return clickhouseToTsType(wrappedLowCardinalityType);
182
+ return clickhouseToTsType(wrappedLowCardinalityType, onUnsupported);
183
183
  }
184
184
  const wrappedTupleType = unwrapType(normalizedType, 'Tuple');
185
185
  if (wrappedTupleType) {
@@ -187,10 +187,10 @@ export const clickhouseToTsType = (type) => {
187
187
  const namedParts = tupleParts.map(parseNamedTuplePart);
188
188
  if (namedParts.length > 0 && namedParts.every((part) => part !== null)) {
189
189
  return `{ ${namedParts
190
- .map((part) => `${formatTypeScriptProperty(part.name)}: ${clickhouseToTsType(part.type)}`)
190
+ .map((part) => `${formatTypeScriptProperty(part.name)}: ${clickhouseToTsType(part.type, onUnsupported)}`)
191
191
  .join('; ')} }`;
192
192
  }
193
- return `[${tupleParts.map((part) => clickhouseToTsType(part)).join(', ')}]`;
193
+ return `[${tupleParts.map((part) => clickhouseToTsType(part, onUnsupported)).join(', ')}]`;
194
194
  }
195
195
  const wrappedMapType = unwrapType(normalizedType, 'Map');
196
196
  if (wrappedMapType) {
@@ -198,7 +198,7 @@ export const clickhouseToTsType = (type) => {
198
198
  if (mapParts.length === 2) {
199
199
  const [, valueType] = mapParts;
200
200
  // JSON object keys are strings even when ClickHouse map keys are numeric.
201
- return `Record<string, ${clickhouseToTsType(valueType)}>`;
201
+ return `Record<string, ${clickhouseToTsType(valueType, onUnsupported)}>`;
202
202
  }
203
203
  return 'Record<string, unknown>';
204
204
  }
@@ -206,5 +206,9 @@ export const clickhouseToTsType = (type) => {
206
206
  if (primitiveType)
207
207
  return primitiveType;
208
208
  // Unsupported or more complex ClickHouse types currently preserve the historical fallback.
209
+ try {
210
+ onUnsupported?.(normalizedType);
211
+ }
212
+ catch { /* Optional observers cannot change generated types. */ }
209
213
  return 'string';
210
214
  };
@@ -0,0 +1,2 @@
1
+ export declare function getChdbGitignoreEntry(chdbPath: string | undefined, cwd: string): string | undefined;
2
+ //# sourceMappingURL=chdb-gitignore-entry.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"chdb-gitignore-entry.d.ts","sourceRoot":"","sources":["../../src/utils/chdb-gitignore-entry.ts"],"names":[],"mappings":"AAEA,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,MAAM,GAAG,SAAS,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAmBnG"}
@@ -0,0 +1,17 @@
1
+ import path from 'node:path';
2
+ export function getChdbGitignoreEntry(chdbPath, cwd) {
3
+ if (!chdbPath || /[\0\r\n]/.test(chdbPath)) {
4
+ return undefined;
5
+ }
6
+ cwd = path.resolve(cwd);
7
+ const relativePath = path.relative(cwd, path.resolve(cwd, chdbPath));
8
+ if (relativePath.length === 0 ||
9
+ relativePath === '..' ||
10
+ relativePath.startsWith(`..${path.sep}`) ||
11
+ path.isAbsolute(relativePath)) {
12
+ return undefined;
13
+ }
14
+ const normalizedPath = relativePath.split(path.sep).join('/');
15
+ const escapedPath = normalizedPath.replace(/[\\*?[\]]/g, '\\$&');
16
+ return `/${escapedPath}/`;
17
+ }
@@ -0,0 +1,2 @@
1
+ export declare function getCliVersion(): string;
2
+ //# sourceMappingURL=cli-version.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli-version.d.ts","sourceRoot":"","sources":["../../src/utils/cli-version.ts"],"names":[],"mappings":"AAGA,wBAAgB,aAAa,IAAI,MAAM,CAKtC"}
@@ -0,0 +1,11 @@
1
+ import { readFileSync } from 'node:fs';
2
+ import { fileURLToPath } from 'node:url';
3
+ export function getCliVersion() {
4
+ try {
5
+ const pkg = JSON.parse(readFileSync(fileURLToPath(new URL('../../package.json', import.meta.url)), 'utf8'));
6
+ return pkg.version ?? '0.0.0';
7
+ }
8
+ catch {
9
+ return '0.0.0';
10
+ }
11
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"cloud-credential-store.d.ts","sourceRoot":"","sources":["../../src/utils/cloud-credential-store.ts"],"names":[],"mappings":"AAIA,OAAO,EAEL,KAAK,+BAA+B,EACrC,MAAM,qBAAqB,CAAC;AAI7B,eAAO,MAAM,sBAAsB,kBAAkB,CAAC;AACtD,eAAO,MAAM,kBAAkB,qCAAqC,CAAC;AAGrE,MAAM,WAAW,qBAAqB;IACpC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,kBAAkB,EAAE,MAAM,CAAC;IACpC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,MAAM,CAAC,EAAE,+BAA+B,CAAC;IAClD,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;CACxB;AAYD,UAAU,YAAY;IACpB,WAAW,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACpD,WAAW,IAAI,MAAM,GAAG,IAAI,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;IACtD,cAAc,IAAI,OAAO,CAAC;CAC3B;AAQD,MAAM,WAAW,gCAAgC;IAC/C,QAAQ,CAAC,eAAe,CAAC,EAAE,MAAM,CAAC;IAClC,QAAQ,CAAC,kBAAkB,CAAC,EAAE,CAC5B,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,MAAM,KACZ,OAAO,CAAC,YAAY,CAAC,GAAG,YAAY,CAAC;IAC1C,QAAQ,CAAC,GAAG,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAC,CAAC;IAC5D,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC,QAAQ,CAAC;CACrC;AAyCD,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAc1D;AAED,wBAAgB,gCAAgC,CAC9C,KAAK,EAAE,MAAM,EACb,WAAW,EAAE,MAAM,GAClB,MAAM,CAmBR;AAmFD,wBAAsB,mBAAmB,CACvC,UAAU,EAAE,qBAAqB,EACjC,YAAY,GAAE,gCAAqC,iBAkEpD;AAED,wBAAsB,mBAAmB,CACvC,YAAY,GAAE,gCAAqC,GAClD,OAAO,CAAC,qBAAqB,GAAG,IAAI,CAAC,CAsBvC;AA0BD,wBAAsB,qBAAqB,CACzC,YAAY,GAAE,gCAAqC,iBA0BpD"}
1
+ {"version":3,"file":"cloud-credential-store.d.ts","sourceRoot":"","sources":["../../src/utils/cloud-credential-store.ts"],"names":[],"mappings":"AAIA,OAAO,EAEL,KAAK,+BAA+B,EACrC,MAAM,qBAAqB,CAAC;AAI7B,eAAO,MAAM,sBAAsB,kBAAkB,CAAC;AACtD,eAAO,MAAM,kBAAkB,qCAAqC,CAAC;AAGrE,MAAM,WAAW,qBAAqB;IACpC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,kBAAkB,EAAE,MAAM,CAAC;IACpC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,MAAM,CAAC,EAAE,+BAA+B,CAAC;IAClD,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;CACxB;AAYD,UAAU,YAAY;IACpB,WAAW,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACpD,WAAW,IAAI,MAAM,GAAG,IAAI,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;IACtD,cAAc,IAAI,OAAO,CAAC;CAC3B;AAQD,MAAM,WAAW,gCAAgC;IAC/C,QAAQ,CAAC,eAAe,CAAC,EAAE,MAAM,CAAC;IAClC,QAAQ,CAAC,kBAAkB,CAAC,EAAE,CAC5B,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,MAAM,KACZ,OAAO,CAAC,YAAY,CAAC,GAAG,YAAY,CAAC;IAC1C,QAAQ,CAAC,GAAG,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAC,CAAC;IAC5D,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC,QAAQ,CAAC;CACrC;AA2BD,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAc1D;AAED,wBAAgB,gCAAgC,CAC9C,KAAK,EAAE,MAAM,EACb,WAAW,EAAE,MAAM,GAClB,MAAM,CAmBR;AAmFD,wBAAsB,mBAAmB,CACvC,UAAU,EAAE,qBAAqB,EACjC,YAAY,GAAE,gCAAqC,iBAkEpD;AAED,wBAAsB,mBAAmB,CACvC,YAAY,GAAE,gCAAqC,GAClD,OAAO,CAAC,qBAAqB,GAAG,IAAI,CAAC,CAsBvC;AA0BD,wBAAsB,qBAAqB,CACzC,YAAY,GAAE,gCAAqC,iBA0BpD"}
@@ -1,24 +1,13 @@
1
1
  import { randomUUID } from 'node:crypto';
2
2
  import { chmod, mkdir, readFile, rename, unlink, writeFile } from 'node:fs/promises';
3
- import { homedir } from 'node:os';
4
3
  import path from 'node:path';
4
+ import { configDirectory } from './config-directory.js';
5
5
  import { validateProtocolDeploymentReleaseTarget, } from '@hypequery/protocol';
6
6
  const KEYCHAIN_SERVICE = 'dev.hypequery.cli';
7
7
  const PROFILE_FILE = 'cloud-profile.json';
8
8
  export const CLOUD_DEPLOYMENT_SCOPE = 'deploy:submit';
9
9
  export const CLOUD_SOURCE_SCOPE = 'deploy:submit deploy:read-source';
10
10
  const MAX_KEYCHAIN_ACCOUNT_LENGTH = 2048;
11
- function defaultConfigDirectory(env, platform) {
12
- if (env.HYPEQUERY_CONFIG_DIR)
13
- return env.HYPEQUERY_CONFIG_DIR;
14
- if (platform === 'win32') {
15
- return path.join(env.APPDATA ?? env.LOCALAPPDATA ?? homedir(), 'hypequery');
16
- }
17
- if (platform === 'darwin') {
18
- return path.join(homedir(), 'Library', 'Application Support', 'hypequery');
19
- }
20
- return path.join(env.XDG_CONFIG_HOME ?? path.join(homedir(), '.config'), 'hypequery');
21
- }
22
11
  function vaultUnavailable(error) {
23
12
  return new Error('The operating-system credential vault is unavailable. '
24
13
  + 'Install its keyring service or use HYPEQUERY_API_TOKEN for manual authentication.', { cause: error });
@@ -36,7 +25,7 @@ function paths(dependencies) {
36
25
  const env = dependencies.env ?? process.env;
37
26
  const platform = dependencies.platform ?? process.platform;
38
27
  const directory = dependencies.configDirectory
39
- ?? defaultConfigDirectory(env, platform);
28
+ ?? configDirectory(env, platform);
40
29
  return { directory, profile: path.join(directory, PROFILE_FILE) };
41
30
  }
42
31
  export function normalizeCloudOrigin(input) {
@@ -0,0 +1,13 @@
1
+ import type { ERROR_CODES, OUTCOMES } from './telemetry/domains.js';
2
+ export declare class CommandExit extends Error {
3
+ readonly exitCode: number;
4
+ readonly outcome: typeof OUTCOMES[number];
5
+ readonly errorCode?: (typeof ERROR_CODES)[number] | undefined;
6
+ constructor(exitCode: number, outcome: typeof OUTCOMES[number], errorCode?: (typeof ERROR_CODES)[number] | undefined);
7
+ }
8
+ /** Only the executable installs this; standalone command calls preserve their legacy exits. */
9
+ export declare function installCommandExitFinalizer(finish: (exit: CommandExit) => Promise<void>): () => void;
10
+ export declare function exitWith(code: number, outcome?: CommandExit['outcome'], errorCode?: CommandExit['errorCode']): never;
11
+ /** Signal-driven shutdown runs after the owning command's resource cleanup. */
12
+ export declare function finishAndExit(code: number, outcome: CommandExit['outcome'], errorCode?: CommandExit['errorCode']): Promise<never>;
13
+ //# sourceMappingURL=command-exit.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"command-exit.d.ts","sourceRoot":"","sources":["../../src/utils/command-exit.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,wBAAwB,CAAC;AAEpE,qBAAa,WAAY,SAAQ,KAAK;IAElC,QAAQ,CAAC,QAAQ,EAAE,MAAM;IACzB,QAAQ,CAAC,OAAO,EAAE,OAAO,QAAQ,CAAC,MAAM,CAAC;IACzC,QAAQ,CAAC,SAAS,CAAC,EAAE,CAAA,OAAO,WAAW,EAAC,MAAM,CAAC;gBAFtC,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,OAAO,QAAQ,CAAC,MAAM,CAAC,EAChC,SAAS,CAAC,EAAE,CAAA,OAAO,WAAW,EAAC,MAAM,CAAC,YAAA;CAElD;AAID,+FAA+F;AAC/F,wBAAgB,2BAA2B,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,WAAW,KAAK,OAAO,CAAC,IAAI,CAAC,GAAG,MAAM,IAAI,CAGpG;AAED,wBAAgB,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,GAAE,WAAW,CAAC,SAAS,CAAwC,EAAE,SAAS,CAAC,EAAE,WAAW,CAAC,WAAW,CAAC,GAAG,KAAK,CAG1J;AAED,+EAA+E;AAC/E,wBAAsB,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,WAAW,CAAC,SAAS,CAAC,EAAE,SAAS,CAAC,EAAE,WAAW,CAAC,WAAW,CAAC,GAAG,OAAO,CAAC,KAAK,CAAC,CAGvI"}
@@ -0,0 +1,31 @@
1
+ export class CommandExit extends Error {
2
+ exitCode;
3
+ outcome;
4
+ errorCode;
5
+ constructor(exitCode, outcome, errorCode) {
6
+ super('Command requested exit');
7
+ this.exitCode = exitCode;
8
+ this.outcome = outcome;
9
+ this.errorCode = errorCode;
10
+ }
11
+ }
12
+ let finalizer;
13
+ /** Only the executable installs this; standalone command calls preserve their legacy exits. */
14
+ export function installCommandExitFinalizer(finish) {
15
+ finalizer = finish;
16
+ return () => { if (finalizer === finish)
17
+ finalizer = undefined; };
18
+ }
19
+ export function exitWith(code, outcome = code === 0 ? 'cancelled' : 'failure', errorCode) {
20
+ if (finalizer)
21
+ throw new CommandExit(code, outcome, errorCode);
22
+ return process.exit(code);
23
+ }
24
+ /** Signal-driven shutdown runs after the owning command's resource cleanup. */
25
+ export async function finishAndExit(code, outcome, errorCode) {
26
+ try {
27
+ await finalizer?.(new CommandExit(code, outcome, errorCode));
28
+ }
29
+ catch { /* Preserve exit semantics. */ }
30
+ return process.exit(code);
31
+ }
@@ -0,0 +1,3 @@
1
+ /** Shared location for CLI settings and the Cloud credential profile. */
2
+ export declare function configDirectory(env: Readonly<Record<string, string | undefined>>, platform: NodeJS.Platform, home?: string): string;
3
+ //# sourceMappingURL=config-directory.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config-directory.d.ts","sourceRoot":"","sources":["../../src/utils/config-directory.ts"],"names":[],"mappings":"AAGA,yEAAyE;AACzE,wBAAgB,eAAe,CAC7B,GAAG,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAC,EACjD,QAAQ,EAAE,MAAM,CAAC,QAAQ,EACzB,IAAI,SAAY,GACf,MAAM,CASR"}
@@ -0,0 +1,14 @@
1
+ import { homedir } from 'node:os';
2
+ import path from 'node:path';
3
+ /** Shared location for CLI settings and the Cloud credential profile. */
4
+ export function configDirectory(env, platform, home = homedir()) {
5
+ if (env.HYPEQUERY_CONFIG_DIR)
6
+ return env.HYPEQUERY_CONFIG_DIR;
7
+ if (platform === 'win32') {
8
+ return path.join(env.APPDATA ?? env.LOCALAPPDATA ?? home, 'hypequery');
9
+ }
10
+ if (platform === 'darwin') {
11
+ return path.join(home, 'Library', 'Application Support', 'hypequery');
12
+ }
13
+ return path.join(env.XDG_CONFIG_HOME ?? path.join(home, '.config'), 'hypequery');
14
+ }
@@ -0,0 +1,3 @@
1
+ /** Detect backend intent without reading values into diagnostics or contacting a server. */
2
+ export declare function detectDatabaseFromEnvironment(env: Readonly<Record<string, string | undefined>>): 'clickhouse' | 'bigquery' | undefined;
3
+ //# sourceMappingURL=detect-database-environment.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"detect-database-environment.d.ts","sourceRoot":"","sources":["../../src/utils/detect-database-environment.ts"],"names":[],"mappings":"AAAA,4FAA4F;AAC5F,wBAAgB,6BAA6B,CAC3C,GAAG,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAC,GAChD,YAAY,GAAG,UAAU,GAAG,SAAS,CAIvC"}
@@ -0,0 +1,8 @@
1
+ /** Detect backend intent without reading values into diagnostics or contacting a server. */
2
+ export function detectDatabaseFromEnvironment(env) {
3
+ if (env.CLICKHOUSE_HOST || env.CLICKHOUSE_URL || env.CLICKHOUSE_DATABASE)
4
+ return 'clickhouse';
5
+ if (env.BIGQUERY_PROJECT_ID || env.GOOGLE_APPLICATION_CREDENTIALS)
6
+ return 'bigquery';
7
+ return undefined;
8
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"detect-database.d.ts","sourceRoot":"","sources":["../../src/utils/detect-database.ts"],"names":[],"mappings":"AAKA;;GAEG;AACH,MAAM,MAAM,YAAY,GAAG,YAAY,GAAG,MAAM,GAAG,UAAU,GAAG,SAAS,CAAC;AAE1E;;;GAGG;AACH,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED;;GAEG;AACH,wBAAsB,cAAc,IAAI,OAAO,CAAC,YAAY,CAAC,CAuD5D;AAED;;GAEG;AACH,wBAAsB,kBAAkB,CACtC,MAAM,EAAE,YAAY,EACpB,OAAO,GAAE,eAAoB,GAC5B,OAAO,CAAC,OAAO,CAAC,CAWlB;AAuBD;;GAEG;AACH,wBAAsB,aAAa,CACjC,MAAM,EAAE,YAAY,EACpB,OAAO,GAAE,eAAoB,GAC5B,OAAO,CAAC,MAAM,CAAC,CASjB;AAyBD;;GAEG;AACH,wBAAsB,SAAS,CAC7B,MAAM,EAAE,YAAY,EACpB,OAAO,GAAE,eAAoB,GAC5B,OAAO,CAAC,MAAM,EAAE,CAAC,CASnB"}
1
+ {"version":3,"file":"detect-database.d.ts","sourceRoot":"","sources":["../../src/utils/detect-database.ts"],"names":[],"mappings":"AAMA;;GAEG;AACH,MAAM,MAAM,YAAY,GAAG,YAAY,GAAG,MAAM,GAAG,UAAU,GAAG,SAAS,CAAC;AAE1E;;;GAGG;AACH,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED;;GAEG;AACH,wBAAsB,cAAc,IAAI,OAAO,CAAC,YAAY,CAAC,CA8C5D;AAED;;GAEG;AACH,wBAAsB,kBAAkB,CACtC,MAAM,EAAE,YAAY,EACpB,OAAO,GAAE,eAAoB,GAC5B,OAAO,CAAC,OAAO,CAAC,CAWlB;AAuBD;;GAEG;AACH,wBAAsB,aAAa,CACjC,MAAM,EAAE,YAAY,EACpB,OAAO,GAAE,eAAoB,GAC5B,OAAO,CAAC,MAAM,CAAC,CASjB;AAyBD;;GAEG;AACH,wBAAsB,SAAS,CAC7B,MAAM,EAAE,YAAY,EACpB,OAAO,GAAE,eAAoB,GAC5B,OAAO,CAAC,MAAM,EAAE,CAAC,CASnB"}
@@ -2,19 +2,15 @@ import { access, readFile } from 'node:fs/promises';
2
2
  import path from 'node:path';
3
3
  import { getClickHouseClient } from './clickhouse-client.js';
4
4
  import { validateChdb, getChdbTables } from './chdb-client.js';
5
+ import { detectDatabaseFromEnvironment } from './detect-database-environment.js';
5
6
  /**
6
7
  * Auto-detect database type from environment or config files
7
8
  */
8
9
  export async function detectDatabase() {
9
10
  // Check environment variables
10
- if (process.env.CLICKHOUSE_HOST ||
11
- process.env.CLICKHOUSE_URL ||
12
- process.env.CLICKHOUSE_DATABASE) {
13
- return 'clickhouse';
14
- }
15
- if (process.env.BIGQUERY_PROJECT_ID || process.env.GOOGLE_APPLICATION_CREDENTIALS) {
16
- return 'bigquery';
17
- }
11
+ const detected = detectDatabaseFromEnvironment(process.env);
12
+ if (detected)
13
+ return detected;
18
14
  // Check for .env file and parse it
19
15
  try {
20
16
  const envPath = path.join(process.cwd(), '.env');
@@ -0,0 +1,11 @@
1
+ import type { InitOptions } from '../commands/init.js';
2
+ import type { InitStyle } from './prompts.js';
3
+ import type { AuthTemplateMode } from '../templates/queries.js';
4
+ import type { DatabaseType } from './detect-database.js';
5
+ type InitDatabase = Extract<DatabaseType, 'clickhouse' | 'chdb'>;
6
+ export declare function normalizeInitDatabase(database: InitOptions['database']): InitDatabase;
7
+ export declare function normalizeInitStyle(style: InitOptions['style']): InitStyle;
8
+ export declare function normalizeAuthMode(auth: InitOptions['auth']): AuthTemplateMode;
9
+ export declare function parseTableList(value: string | undefined): string[] | undefined;
10
+ export {};
11
+ //# sourceMappingURL=init-options.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"init-options.d.ts","sourceRoot":"","sources":["../../src/utils/init-options.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AACvD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAC9C,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAChE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAEzD,KAAK,YAAY,GAAG,OAAO,CAAC,YAAY,EAAE,YAAY,GAAG,MAAM,CAAC,CAAC;AAEjE,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,WAAW,CAAC,UAAU,CAAC,GAAG,YAAY,CAQrF;AAED,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,WAAW,CAAC,OAAO,CAAC,GAAG,SAAS,CAEzE;AAED,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,WAAW,CAAC,MAAM,CAAC,GAAG,gBAAgB,CAQ7E;AAED,wBAAgB,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,EAAE,GAAG,SAAS,CAO9E"}
@@ -0,0 +1,28 @@
1
+ export function normalizeInitDatabase(database) {
2
+ if (!database || database === 'clickhouse') {
3
+ return 'clickhouse';
4
+ }
5
+ if (database === 'chdb') {
6
+ return 'chdb';
7
+ }
8
+ throw new Error(`Unsupported database "${database}". Use "clickhouse" or "chdb".`);
9
+ }
10
+ export function normalizeInitStyle(style) {
11
+ return style === 'datasets' ? 'datasets' : 'queries';
12
+ }
13
+ export function normalizeAuthMode(auth) {
14
+ if (!auth || auth === 'none') {
15
+ return 'none';
16
+ }
17
+ if (auth === 'context') {
18
+ return 'context';
19
+ }
20
+ throw new Error(`Unsupported auth mode "${auth}". Use "none" or "context".`);
21
+ }
22
+ export function parseTableList(value) {
23
+ const parsed = value
24
+ ?.split(',')
25
+ .map((table) => table.trim())
26
+ .filter(Boolean);
27
+ return parsed && parsed.length > 0 ? parsed : undefined;
28
+ }
@@ -1,4 +1,6 @@
1
1
  export declare function loadApiModule(modulePath: string): Promise<any>;
2
2
  export declare function loadModule(modulePath: string): Promise<any>;
3
+ /** Remove this process's bundles; the CLI awaits this before it exits. */
4
+ export declare function cleanupLoadedApiArtifacts(): Promise<void>;
3
5
  export declare function findNearestTsconfig(filePath: string): Promise<string | null>;
4
6
  //# sourceMappingURL=load-api.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"load-api.d.ts","sourceRoot":"","sources":["../../src/utils/load-api.ts"],"names":[],"mappings":"AAaA,wBAAsB,aAAa,CAAC,UAAU,EAAE,MAAM,gBA2DrD;AAED,wBAAsB,UAAU,CAAC,UAAU,EAAE,MAAM,gBAkClD;AA0JD,wBAAsB,mBAAmB,CAAC,QAAQ,EAAE,MAAM,0BA8BzD"}
1
+ {"version":3,"file":"load-api.d.ts","sourceRoot":"","sources":["../../src/utils/load-api.ts"],"names":[],"mappings":"AAgBA,wBAAsB,aAAa,CAAC,UAAU,EAAE,MAAM,gBA2DrD;AAED,wBAAsB,UAAU,CAAC,UAAU,EAAE,MAAM,gBAwClD;AAuED,0EAA0E;AAC1E,wBAAsB,yBAAyB,kBAE9C;AAqED,wBAAsB,mBAAmB,CAAC,QAAQ,EAAE,MAAM,0BA8BzD"}
@@ -1,8 +1,11 @@
1
1
  import { pathToFileURL } from 'node:url';
2
- import { access, mkdtemp, rm, mkdir, writeFile } from 'node:fs/promises';
2
+ import { rmdirSync, rmSync } from 'node:fs';
3
+ import { access, mkdtemp, mkdir, writeFile } from 'node:fs/promises';
3
4
  import os from 'node:os';
4
5
  import path from 'node:path';
5
6
  import { build } from 'esbuild';
7
+ import { loadEnvFiles } from './load-env-files.js';
8
+ import { findProjectRoot } from './project-root.js';
6
9
  if (typeof process.setMaxListeners === 'function') {
7
10
  process.setMaxListeners(0);
8
11
  }
@@ -68,6 +71,11 @@ export async function loadModule(modulePath) {
68
71
  const relativePath = path.relative(process.cwd(), resolved);
69
72
  throw new Error(`File not found: ${relativePath}`);
70
73
  }
74
+ // The CLI loaded the launch directory's env files at startup. An entry in
75
+ // another project (`hypequery mcp /abs/path/api.ts`) reads its connection
76
+ // settings from that project's env files, so load those too before its
77
+ // client module runs. Values already set keep precedence.
78
+ await loadEnvFiles(await findProjectRoot(resolved));
71
79
  const extension = path.extname(resolved).toLowerCase();
72
80
  const isTypeScript = TYPESCRIPT_EXTENSIONS.has(extension);
73
81
  const moduleUrl = isTypeScript
@@ -92,23 +100,26 @@ export async function loadModule(modulePath) {
92
100
  }
93
101
  }
94
102
  const globalState = globalThis;
95
- let tempDirPromise = globalState.__hypequeryCliTempDirPromise ?? null;
96
- const tempFiles = globalState.__hypequeryCliTempFiles ?? new Set();
97
- const tempDirs = globalState.__hypequeryCliTempDirs ?? new Set();
103
+ // One bundle directory per project root, keyed by that root.
104
+ const tempDirPromises = globalState.__hypequeryCliTempDirPromises ??= new Map();
105
+ const tempFiles = globalState.__hypequeryCliTempFiles ??= new Set();
106
+ const tempDirs = globalState.__hypequeryCliTempDirs ??= new Set();
107
+ const tempRoots = globalState.__hypequeryCliTempRoots ??= new Set();
98
108
  let cleanupHooksInstalled = globalState.__hypequeryCliCleanupInstalled ?? false;
99
- if (!globalState.__hypequeryCliTempFiles) {
100
- globalState.__hypequeryCliTempFiles = tempFiles;
101
- }
102
- if (!globalState.__hypequeryCliTempDirs) {
103
- globalState.__hypequeryCliTempDirs = tempDirs;
104
- }
105
- function ensureTempDir() {
109
+ /**
110
+ * The bundle has to live inside the entry's project: its bare imports
111
+ * (`@hypequery/serve`, ...) resolve from the bundle's location, and the
112
+ * process's working directory may be anywhere (MCP clients launch from `/`).
113
+ */
114
+ function ensureTempDir(projectRoot) {
106
115
  installCleanupHooks();
107
- if (!tempDirPromise) {
108
- tempDirPromise = (async () => {
109
- const projectTempRoot = path.join(process.cwd(), '.hypequery', 'tmp');
116
+ let promise = tempDirPromises.get(projectRoot);
117
+ if (!promise) {
118
+ promise = (async () => {
119
+ const projectTempRoot = path.join(projectRoot, '.hypequery', 'tmp');
110
120
  try {
111
121
  await mkdir(projectTempRoot, { recursive: true });
122
+ tempRoots.add(projectTempRoot);
112
123
  const dir = await mkdtemp(path.join(projectTempRoot, 'bundle-'));
113
124
  tempDirs.add(dir);
114
125
  return dir;
@@ -119,65 +130,53 @@ function ensureTempDir() {
119
130
  return fallbackDir;
120
131
  }
121
132
  })();
122
- globalState.__hypequeryCliTempDirPromise = tempDirPromise;
133
+ tempDirPromises.set(projectRoot, promise);
123
134
  }
124
- return tempDirPromise;
135
+ return promise;
125
136
  }
126
- async function cleanupTempFiles() {
127
- if (tempFiles.size === 0)
128
- return;
129
- await Promise.all(Array.from(tempFiles).map(async (file) => {
137
+ // Synchronous so it completes inside an 'exit' handler.
138
+ function cleanupTempArtifacts() {
139
+ for (const target of [...tempFiles, ...tempDirs]) {
130
140
  try {
131
- await rm(file, { force: true });
141
+ rmSync(target, { recursive: true, force: true });
132
142
  }
133
143
  catch {
134
144
  // ignore cleanup failures
135
145
  }
136
- }));
146
+ }
137
147
  tempFiles.clear();
138
- }
139
- async function cleanupTempDirs() {
140
- if (tempDirs.size === 0)
141
- return;
142
- await Promise.all(Array.from(tempDirs).map(async (dir) => {
148
+ tempDirs.clear();
149
+ tempDirPromises.clear();
150
+ // Only remove the shared tmp root once empty: another hypequery process in the
151
+ // same project (e.g. `hypequery dev` beside an MCP client) may still use it.
152
+ for (const root of tempRoots) {
143
153
  try {
144
- await rm(dir, { recursive: true, force: true });
154
+ rmdirSync(root);
145
155
  }
146
156
  catch {
147
- // ignore cleanup failures
157
+ // not empty or already gone
148
158
  }
149
- }));
150
- tempDirs.clear();
151
- const projectTempRoot = path.join(process.cwd(), '.hypequery', 'tmp');
152
- try {
153
- await rm(projectTempRoot, { recursive: true, force: true });
154
- }
155
- catch {
156
- // ignore cleanup failures
157
159
  }
160
+ tempRoots.clear();
158
161
  }
159
- async function cleanupTempArtifacts() {
160
- await cleanupTempFiles();
161
- await cleanupTempDirs();
162
+ /** Remove this process's bundles; the CLI awaits this before it exits. */
163
+ export async function cleanupLoadedApiArtifacts() {
164
+ cleanupTempArtifacts();
162
165
  }
163
166
  function installCleanupHooks() {
164
167
  if (cleanupHooksInstalled)
165
168
  return;
166
169
  cleanupHooksInstalled = true;
167
170
  globalState.__hypequeryCliCleanupInstalled = true;
168
- process.once('exit', () => {
169
- cleanupTempArtifacts().catch(() => undefined);
170
- });
171
- ['SIGINT', 'SIGTERM'].forEach(signal => {
172
- process.once(signal, () => {
173
- cleanupTempArtifacts().catch(() => undefined);
174
- process.exit();
175
- });
176
- });
171
+ // Synchronous, so it still completes when this is the last thing to run.
172
+ process.once('exit', cleanupTempArtifacts);
173
+ // Signal shutdown belongs to the CLI/owning server. Exiting from a module
174
+ // cleanup listener bypassed server teardown and the bounded telemetry flush.
177
175
  }
178
176
  async function bundleTypeScriptModule(entryPath) {
179
177
  const relativePath = path.relative(process.cwd(), entryPath);
180
178
  const tsconfigPath = await findNearestTsconfig(entryPath);
179
+ const projectRoot = await findProjectRoot(entryPath);
181
180
  try {
182
181
  const result = await build({
183
182
  entryPoints: [entryPath],
@@ -188,7 +187,7 @@ async function bundleTypeScriptModule(entryPath) {
188
187
  sourcemap: 'inline',
189
188
  write: false,
190
189
  logLevel: 'silent',
191
- absWorkingDir: process.cwd(),
190
+ absWorkingDir: projectRoot,
192
191
  packages: 'external',
193
192
  tsconfig: tsconfigPath ?? undefined,
194
193
  loader: {
@@ -202,7 +201,7 @@ async function bundleTypeScriptModule(entryPath) {
202
201
  if (!output) {
203
202
  throw new Error('esbuild produced no output');
204
203
  }
205
- const tempDir = await ensureTempDir();
204
+ const tempDir = await ensureTempDir(projectRoot);
206
205
  const timestamp = Date.now();
207
206
  const tempFile = path.join(tempDir, `${path.basename(entryPath, path.extname(entryPath))}-${timestamp}.mjs`);
208
207
  const contents = `${output.text}\n` +
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Loads the `.env*` cascade from `directory` into `process.env`.
3
+ *
4
+ * `dotenv` never overwrites a variable that is already set, so a real
5
+ * environment variable beats every file, and a directory loaded earlier (the
6
+ * launch directory, at startup) beats one loaded later. Each directory is read
7
+ * once per process; `hypequery dev` reloads the API on every change.
8
+ */
9
+ export declare function loadEnvFiles(directory: string): Promise<void>;
10
+ //# sourceMappingURL=load-env-files.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"load-env-files.d.ts","sourceRoot":"","sources":["../../src/utils/load-env-files.ts"],"names":[],"mappings":"AAKA;;;;;;;GAOG;AACH,wBAAsB,YAAY,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAcnE"}
@@ -0,0 +1,27 @@
1
+ import path from 'node:path';
2
+ import { envFiles } from './env-files.js';
3
+ const loadedDirectories = new Set();
4
+ /**
5
+ * Loads the `.env*` cascade from `directory` into `process.env`.
6
+ *
7
+ * `dotenv` never overwrites a variable that is already set, so a real
8
+ * environment variable beats every file, and a directory loaded earlier (the
9
+ * launch directory, at startup) beats one loaded later. Each directory is read
10
+ * once per process; `hypequery dev` reloads the API on every change.
11
+ */
12
+ export async function loadEnvFiles(directory) {
13
+ const resolved = path.resolve(directory);
14
+ if (loadedDirectories.has(resolved))
15
+ return;
16
+ loadedDirectories.add(resolved);
17
+ try {
18
+ const { config } = await import('dotenv');
19
+ for (const file of envFiles(process.env.NODE_ENV)) {
20
+ // Missing files are a no-op.
21
+ config({ path: path.join(resolved, file) });
22
+ }
23
+ }
24
+ catch {
25
+ // dotenv is optional; continue if not available
26
+ }
27
+ }
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Finds the directory that owns `filePath`: the nearest ancestor with a
3
+ * `package.json`, or the file's own directory when there is none. Bare imports
4
+ * in the file resolve from here, whatever the process's working directory is.
5
+ */
6
+ export declare function findProjectRoot(filePath: string): Promise<string>;
7
+ /**
8
+ * Imports `specifier` as `fromFile` would see it, so a package installed in the
9
+ * user's project is found even when the CLI runs from elsewhere (for example
10
+ * through `npx -y @hypequery/cli`). Falls back to `fallback` — the CLI's own
11
+ * resolution — when the project does not have the package.
12
+ */
13
+ export declare function importFromProject<T>(specifier: string, fromFile: string, fallback: () => Promise<T>): Promise<T>;
14
+ //# sourceMappingURL=project-root.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"project-root.d.ts","sourceRoot":"","sources":["../../src/utils/project-root.ts"],"names":[],"mappings":"AAKA;;;;GAIG;AACH,wBAAsB,eAAe,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAcvE;AAED;;;;;GAKG;AACH,wBAAsB,iBAAiB,CAAC,CAAC,EACvC,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GACzB,OAAO,CAAC,CAAC,CAAC,CAQZ"}
@@ -0,0 +1,41 @@
1
+ import { access } from 'node:fs/promises';
2
+ import { createRequire } from 'node:module';
3
+ import path from 'node:path';
4
+ import { pathToFileURL } from 'node:url';
5
+ /**
6
+ * Finds the directory that owns `filePath`: the nearest ancestor with a
7
+ * `package.json`, or the file's own directory when there is none. Bare imports
8
+ * in the file resolve from here, whatever the process's working directory is.
9
+ */
10
+ export async function findProjectRoot(filePath) {
11
+ const start = path.dirname(path.resolve(filePath));
12
+ let dir = start;
13
+ while (true) {
14
+ try {
15
+ await access(path.join(dir, 'package.json'));
16
+ return dir;
17
+ }
18
+ catch {
19
+ const parent = path.dirname(dir);
20
+ if (parent === dir)
21
+ return start;
22
+ dir = parent;
23
+ }
24
+ }
25
+ }
26
+ /**
27
+ * Imports `specifier` as `fromFile` would see it, so a package installed in the
28
+ * user's project is found even when the CLI runs from elsewhere (for example
29
+ * through `npx -y @hypequery/cli`). Falls back to `fallback` — the CLI's own
30
+ * resolution — when the project does not have the package.
31
+ */
32
+ export async function importFromProject(specifier, fromFile, fallback) {
33
+ let resolved;
34
+ try {
35
+ resolved = createRequire(path.resolve(fromFile)).resolve(specifier);
36
+ }
37
+ catch {
38
+ return fallback();
39
+ }
40
+ return import(/* @vite-ignore */ pathToFileURL(resolved).href);
41
+ }
@@ -0,0 +1,5 @@
1
+ import { COUNT_BUCKETS, DURATION_BUCKETS } from './domains.js';
2
+ /** Invalid measurements are omitted rather than coerced into a misleading bucket. */
3
+ export declare function countBucket(count: number): typeof COUNT_BUCKETS[number] | undefined;
4
+ export declare function durationBucket(milliseconds: number): typeof DURATION_BUCKETS[number] | undefined;
5
+ //# sourceMappingURL=buckets.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"buckets.d.ts","sourceRoot":"","sources":["../../../src/utils/telemetry/buckets.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAE/D,qFAAqF;AACrF,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,aAAa,CAAC,MAAM,CAAC,GAAG,SAAS,CAQnF;AAED,wBAAgB,cAAc,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,gBAAgB,CAAC,MAAM,CAAC,GAAG,SAAS,CAIhG"}