@hypequery/cli 1.22.0 → 1.24.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/bin/cli.js +77 -12
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +20 -15
- package/dist/commands/dev.d.ts.map +1 -1
- package/dist/commands/dev.js +25 -5
- package/dist/commands/generate-datasets.d.ts +0 -6
- package/dist/commands/generate-datasets.d.ts.map +1 -1
- package/dist/commands/generate-datasets.js +17 -1
- package/dist/commands/generate-manifest.d.ts.map +1 -1
- package/dist/commands/generate-manifest.js +4 -0
- package/dist/commands/generate.d.ts.map +1 -1
- package/dist/commands/generate.js +14 -1
- package/dist/commands/init.d.ts.map +1 -1
- package/dist/commands/init.js +80 -55
- package/dist/commands/mcp.d.ts.map +1 -1
- package/dist/commands/mcp.js +47 -10
- package/dist/commands/telemetry.d.ts +3 -0
- package/dist/commands/telemetry.d.ts.map +1 -0
- package/dist/commands/telemetry.js +19 -0
- package/dist/generators/chdb.d.ts +3 -0
- package/dist/generators/chdb.d.ts.map +1 -1
- package/dist/generators/chdb.js +2 -0
- package/dist/generators/clickhouse.d.ts +3 -1
- package/dist/generators/clickhouse.d.ts.map +1 -1
- package/dist/generators/clickhouse.js +2 -0
- package/dist/typegen/generate-types.d.ts +3 -0
- package/dist/typegen/generate-types.d.ts.map +1 -1
- package/dist/typegen/generate-types.js +5 -1
- package/dist/typegen/type-parsing.d.ts +1 -1
- package/dist/typegen/type-parsing.d.ts.map +1 -1
- package/dist/typegen/type-parsing.js +11 -7
- package/dist/utils/chdb-gitignore-entry.d.ts +2 -0
- package/dist/utils/chdb-gitignore-entry.d.ts.map +1 -0
- package/dist/utils/chdb-gitignore-entry.js +17 -0
- package/dist/utils/cli-version.d.ts +2 -0
- package/dist/utils/cli-version.d.ts.map +1 -0
- package/dist/utils/cli-version.js +11 -0
- package/dist/utils/cloud-credential-store.d.ts.map +1 -1
- package/dist/utils/cloud-credential-store.js +2 -13
- package/dist/utils/command-exit.d.ts +13 -0
- package/dist/utils/command-exit.d.ts.map +1 -0
- package/dist/utils/command-exit.js +31 -0
- package/dist/utils/config-directory.d.ts +3 -0
- package/dist/utils/config-directory.d.ts.map +1 -0
- package/dist/utils/config-directory.js +14 -0
- package/dist/utils/detect-database-environment.d.ts +3 -0
- package/dist/utils/detect-database-environment.d.ts.map +1 -0
- package/dist/utils/detect-database-environment.js +8 -0
- package/dist/utils/detect-database.d.ts.map +1 -1
- package/dist/utils/detect-database.js +4 -8
- package/dist/utils/init-options.d.ts +11 -0
- package/dist/utils/init-options.d.ts.map +1 -0
- package/dist/utils/init-options.js +28 -0
- package/dist/utils/load-api.d.ts +2 -0
- package/dist/utils/load-api.d.ts.map +1 -1
- package/dist/utils/load-api.js +50 -51
- package/dist/utils/load-env-files.d.ts +10 -0
- package/dist/utils/load-env-files.d.ts.map +1 -0
- package/dist/utils/load-env-files.js +27 -0
- package/dist/utils/project-root.d.ts +14 -0
- package/dist/utils/project-root.d.ts.map +1 -0
- package/dist/utils/project-root.js +41 -0
- package/dist/utils/telemetry/buckets.d.ts +5 -0
- package/dist/utils/telemetry/buckets.d.ts.map +1 -0
- package/dist/utils/telemetry/buckets.js +23 -0
- package/dist/utils/telemetry/catalog-docs.d.ts +3 -0
- package/dist/utils/telemetry/catalog-docs.d.ts.map +1 -0
- package/dist/utils/telemetry/catalog-docs.js +52 -0
- package/dist/utils/telemetry/catalog.d.ts +1124 -0
- package/dist/utils/telemetry/catalog.d.ts.map +1 -0
- package/dist/utils/telemetry/catalog.js +154 -0
- package/dist/utils/telemetry/command-context.d.ts +17 -0
- package/dist/utils/telemetry/command-context.d.ts.map +1 -0
- package/dist/utils/telemetry/command-context.js +30 -0
- package/dist/utils/telemetry/config-schema.d.ts +14 -0
- package/dist/utils/telemetry/config-schema.d.ts.map +1 -0
- package/dist/utils/telemetry/config-schema.js +35 -0
- package/dist/utils/telemetry/config-store.d.ts +35 -0
- package/dist/utils/telemetry/config-store.d.ts.map +1 -0
- package/dist/utils/telemetry/config-store.js +147 -0
- package/dist/utils/telemetry/delivery.d.ts +13 -0
- package/dist/utils/telemetry/delivery.d.ts.map +1 -0
- package/dist/utils/telemetry/delivery.js +26 -0
- package/dist/utils/telemetry/detached-dispatch.d.ts +12 -0
- package/dist/utils/telemetry/detached-dispatch.d.ts.map +1 -0
- package/dist/utils/telemetry/detached-dispatch.js +33 -0
- package/dist/utils/telemetry/detached-sender.d.ts +2 -0
- package/dist/utils/telemetry/detached-sender.d.ts.map +1 -0
- package/dist/utils/telemetry/detached-sender.js +31 -0
- package/dist/utils/telemetry/dev-session.d.ts +15 -0
- package/dist/utils/telemetry/dev-session.d.ts.map +1 -0
- package/dist/utils/telemetry/dev-session.js +25 -0
- package/dist/utils/telemetry/domains.d.ts +69 -0
- package/dist/utils/telemetry/domains.d.ts.map +1 -0
- package/dist/utils/telemetry/domains.js +64 -0
- package/dist/utils/telemetry/endpoint.d.ts +3 -0
- package/dist/utils/telemetry/endpoint.d.ts.map +1 -0
- package/dist/utils/telemetry/endpoint.js +15 -0
- package/dist/utils/telemetry/environment.d.ts +27 -0
- package/dist/utils/telemetry/environment.d.ts.map +1 -0
- package/dist/utils/telemetry/environment.js +95 -0
- package/dist/utils/telemetry/error-code.d.ts +4 -0
- package/dist/utils/telemetry/error-code.d.ts.map +1 -0
- package/dist/utils/telemetry/error-code.js +57 -0
- package/dist/utils/telemetry/flags.d.ts +5 -0
- package/dist/utils/telemetry/flags.d.ts.map +1 -0
- package/dist/utils/telemetry/flags.js +41 -0
- package/dist/utils/telemetry/generation-metrics.d.ts +15 -0
- package/dist/utils/telemetry/generation-metrics.d.ts.map +1 -0
- package/dist/utils/telemetry/generation-metrics.js +35 -0
- package/dist/utils/telemetry/identity.d.ts +12 -0
- package/dist/utils/telemetry/identity.d.ts.map +1 -0
- package/dist/utils/telemetry/identity.js +42 -0
- package/dist/utils/telemetry/init-funnel.d.ts +15 -0
- package/dist/utils/telemetry/init-funnel.d.ts.map +1 -0
- package/dist/utils/telemetry/init-funnel.js +25 -0
- package/dist/utils/telemetry/invocation.d.ts +22 -0
- package/dist/utils/telemetry/invocation.d.ts.map +1 -0
- package/dist/utils/telemetry/invocation.js +44 -0
- package/dist/utils/telemetry/lifecycle.d.ts +32 -0
- package/dist/utils/telemetry/lifecycle.d.ts.map +1 -0
- package/dist/utils/telemetry/lifecycle.js +99 -0
- package/dist/utils/telemetry/mcp-session.d.ts +10 -0
- package/dist/utils/telemetry/mcp-session.d.ts.map +1 -0
- package/dist/utils/telemetry/mcp-session.js +36 -0
- package/dist/utils/telemetry/notice.d.ts +11 -0
- package/dist/utils/telemetry/notice.d.ts.map +1 -0
- package/dist/utils/telemetry/notice.js +24 -0
- package/dist/utils/telemetry/opt-out.d.ts +16 -0
- package/dist/utils/telemetry/opt-out.d.ts.map +1 -0
- package/dist/utils/telemetry/opt-out.js +32 -0
- package/dist/utils/telemetry/post-json.d.ts +13 -0
- package/dist/utils/telemetry/post-json.d.ts.map +1 -0
- package/dist/utils/telemetry/post-json.js +32 -0
- package/dist/utils/telemetry/project-context.d.ts +15 -0
- package/dist/utils/telemetry/project-context.d.ts.map +1 -0
- package/dist/utils/telemetry/project-context.js +86 -0
- package/dist/utils/telemetry/schema.d.ts +72 -0
- package/dist/utils/telemetry/schema.d.ts.map +1 -0
- package/dist/utils/telemetry/schema.js +17 -0
- package/dist/utils/telemetry/session-config.d.ts +6 -0
- package/dist/utils/telemetry/session-config.d.ts.map +1 -0
- package/dist/utils/telemetry/session-config.js +17 -0
- package/dist/utils/telemetry/settings-lock.d.ts +36 -0
- package/dist/utils/telemetry/settings-lock.d.ts.map +1 -0
- package/dist/utils/telemetry/settings-lock.js +102 -0
- package/dist/utils/telemetry/transport.d.ts +25 -0
- package/dist/utils/telemetry/transport.d.ts.map +1 -0
- package/dist/utils/telemetry/transport.js +76 -0
- package/dist/utils/telemetry/validation.d.ts +10 -0
- package/dist/utils/telemetry/validation.d.ts.map +1 -0
- package/dist/utils/telemetry/validation.js +77 -0
- package/dist/utils/telemetry/value-formats.d.ts +30 -0
- package/dist/utils/telemetry/value-formats.d.ts.map +1 -0
- package/dist/utils/telemetry/value-formats.js +13 -0
- 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 @@
|
|
|
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 @@
|
|
|
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;
|
|
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
|
-
??
|
|
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 @@
|
|
|
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":"
|
|
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
|
-
|
|
11
|
-
|
|
12
|
-
|
|
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
|
+
}
|
package/dist/utils/load-api.d.ts
CHANGED
|
@@ -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":"
|
|
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"}
|
package/dist/utils/load-api.js
CHANGED
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
import { pathToFileURL } from 'node:url';
|
|
2
|
-
import {
|
|
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
|
-
|
|
96
|
-
const
|
|
97
|
-
const
|
|
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
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
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
|
-
|
|
108
|
-
|
|
109
|
-
|
|
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
|
-
|
|
133
|
+
tempDirPromises.set(projectRoot, promise);
|
|
123
134
|
}
|
|
124
|
-
return
|
|
135
|
+
return promise;
|
|
125
136
|
}
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
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
|
-
|
|
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
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
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
|
-
|
|
154
|
+
rmdirSync(root);
|
|
145
155
|
}
|
|
146
156
|
catch {
|
|
147
|
-
//
|
|
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
|
-
|
|
160
|
-
|
|
161
|
-
|
|
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
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
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:
|
|
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"}
|