@hypequery/cli 1.21.2 → 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.
- package/README.md +1 -0
- package/dist/bin/cli.js +77 -12
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +33 -15
- package/dist/commands/deploy.d.ts +5 -0
- package/dist/commands/deploy.d.ts.map +1 -1
- package/dist/commands/deploy.js +10 -0
- package/dist/commands/deployment-status.d.ts +16 -0
- package/dist/commands/deployment-status.d.ts.map +1 -0
- package/dist/commands/deployment-status.js +36 -0
- 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/live-source.d.ts.map +1 -1
- package/dist/commands/live-source.js +3 -21
- package/dist/commands/mcp.d.ts +10 -0
- package/dist/commands/mcp.d.ts.map +1 -1
- package/dist/commands/mcp.js +93 -8
- 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/test-utils.d.ts +1 -1
- 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/deployment-target.d.ts +7 -0
- package/dist/utils/deployment-target.d.ts.map +1 -0
- package/dist/utils/deployment-target.js +19 -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/hosted-endpoints-output.d.ts +4 -0
- package/dist/utils/hosted-endpoints-output.d.ts.map +1 -0
- package/dist/utils/hosted-endpoints-output.js +27 -0
- package/dist/utils/hosted-endpoints.d.ts +37 -0
- package/dist/utils/hosted-endpoints.d.ts.map +1 -0
- package/dist/utils/hosted-endpoints.js +81 -0
- 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/live-deployment.d.ts +6 -0
- package/dist/utils/live-deployment.d.ts.map +1 -1
- package/dist/utils/live-deployment.js +6 -1
- 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/mcp-remote-check.d.ts +19 -0
- package/dist/utils/mcp-remote-check.d.ts.map +1 -0
- package/dist/utils/mcp-remote-check.js +96 -0
- package/dist/utils/mcp-response.d.ts +3 -0
- package/dist/utils/mcp-response.d.ts.map +1 -0
- package/dist/utils/mcp-response.js +58 -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 +12 -0
- package/dist/utils/telemetry/config-schema.d.ts.map +1 -0
- package/dist/utils/telemetry/config-schema.js +33 -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 +46 -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 +16 -12
package/README.md
CHANGED
|
@@ -39,6 +39,7 @@ npx hypequery init \
|
|
|
39
39
|
| `hypequery generate:datasets` | Dataset definitions scaffolded from tables |
|
|
40
40
|
| `hypequery generate:manifest` | A browser-safe route manifest for React hooks |
|
|
41
41
|
| `hypequery pull` / `diff` | Live source inspection and comparison |
|
|
42
|
+
| `hypequery deployment:status` | Live release and Cloud-provided connection URLs |
|
|
42
43
|
|
|
43
44
|
Non-interactive ClickHouse commands read `CLICKHOUSE_URL`, `CLICKHOUSE_DATABASE`, `CLICKHOUSE_USERNAME`, and `CLICKHOUSE_PASSWORD`.
|
|
44
45
|
|
package/dist/bin/cli.js
CHANGED
|
@@ -1,6 +1,12 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { program } from '../cli.js';
|
|
3
|
-
import {
|
|
3
|
+
import { loadEnvFiles } from '../utils/load-env-files.js';
|
|
4
|
+
import { CommandExit, finishAndExit, installCommandExitFinalizer } from '../utils/command-exit.js';
|
|
5
|
+
import { CommandLifecycle } from '../utils/telemetry/lifecycle.js';
|
|
6
|
+
import { telemetryErrorCode } from '../utils/telemetry/error-code.js';
|
|
7
|
+
import { cleanupLoadedApiArtifacts } from '../utils/load-api.js';
|
|
8
|
+
import { withCommandTelemetry } from '../utils/telemetry/command-context.js';
|
|
9
|
+
import { settleTelemetrySettings } from '../utils/telemetry/config-store.js';
|
|
4
10
|
async function loadEnv() {
|
|
5
11
|
try {
|
|
6
12
|
const dotenvx = await import('@dotenvx/dotenvx');
|
|
@@ -14,19 +20,78 @@ async function loadEnv() {
|
|
|
14
20
|
catch {
|
|
15
21
|
// Optional dependency, ignore if missing
|
|
16
22
|
}
|
|
17
|
-
|
|
18
|
-
const { config } = await import('dotenv');
|
|
19
|
-
for (const path of envFiles(process.env.NODE_ENV)) {
|
|
20
|
-
// Missing files are a no-op.
|
|
21
|
-
config({ path });
|
|
22
|
-
}
|
|
23
|
-
}
|
|
24
|
-
catch {
|
|
25
|
-
// dotenv is optional; continue if not available
|
|
26
|
-
}
|
|
23
|
+
await loadEnvFiles(process.cwd());
|
|
27
24
|
}
|
|
28
25
|
async function main() {
|
|
29
26
|
await loadEnv();
|
|
30
|
-
|
|
27
|
+
const args = process.argv.slice(2);
|
|
28
|
+
const requested = args.find(arg => !arg.startsWith('-'));
|
|
29
|
+
const lifecycle = new CommandLifecycle(args, {
|
|
30
|
+
telemetry: args.includes('--no-telemetry') ? false : undefined,
|
|
31
|
+
});
|
|
32
|
+
let selected;
|
|
33
|
+
let finishing;
|
|
34
|
+
const finish = (exit) => {
|
|
35
|
+
finishing ??= (async () => {
|
|
36
|
+
// finish() never rejects; the guard keeps cleanup independent of telemetry.
|
|
37
|
+
await lifecycle.finish(exit, selected?.name() === 'help' ? selected.args[0] : undefined).catch(() => undefined);
|
|
38
|
+
// Signals end in process.exit(), which skips finally blocks: let any
|
|
39
|
+
// settings write release its lock first (bounded).
|
|
40
|
+
await settleTelemetrySettings();
|
|
41
|
+
await cleanupLoadedApiArtifacts();
|
|
42
|
+
})();
|
|
43
|
+
return finishing;
|
|
44
|
+
};
|
|
45
|
+
installCommandExitFinalizer(finish);
|
|
46
|
+
const crash = (error) => lifecycle.crash(error);
|
|
47
|
+
process.on('uncaughtExceptionMonitor', crash);
|
|
48
|
+
program.exitOverride();
|
|
49
|
+
for (const command of program.commands)
|
|
50
|
+
command.exitOverride();
|
|
51
|
+
program.hook('preAction', async (_root, command) => {
|
|
52
|
+
selected = command;
|
|
53
|
+
await lifecycle.begin(command.name(), command.opts().database);
|
|
54
|
+
});
|
|
55
|
+
const observeSignal = (signal) => {
|
|
56
|
+
lifecycle.markInterrupted();
|
|
57
|
+
// dev and mcp own asynchronous server teardown once their handlers exist.
|
|
58
|
+
// During startup, or for short commands, the executable owns shutdown.
|
|
59
|
+
if ((lifecycle.command === 'dev' || lifecycle.command === 'mcp') && process.listenerCount(signal) > 1)
|
|
60
|
+
return;
|
|
61
|
+
void finishAndExit(lifecycle.command === 'dev' || lifecycle.command === 'mcp' ? 0 : signal === 'SIGINT' ? 130 : 143, 'interrupted');
|
|
62
|
+
};
|
|
63
|
+
process.on('SIGINT', () => observeSignal('SIGINT'));
|
|
64
|
+
process.on('SIGTERM', () => observeSignal('SIGTERM'));
|
|
65
|
+
try {
|
|
66
|
+
await withCommandTelemetry(lifecycle, () => program.parseAsync(process.argv));
|
|
67
|
+
if (lifecycle.command === 'dev')
|
|
68
|
+
return; // Its shutdown handler finalizes after teardown.
|
|
69
|
+
await finish(new CommandExit(Number(process.exitCode ?? 0), process.exitCode ? 'failure' : 'success', process.exitCode ? 'unknown' : undefined));
|
|
70
|
+
}
|
|
71
|
+
catch (error) {
|
|
72
|
+
const commander = error;
|
|
73
|
+
if (commander.code === 'commander.helpDisplayed' || commander.code === 'commander.help') {
|
|
74
|
+
const topic = selected?.name() === 'help' ? selected.args[0] : selected?.name()
|
|
75
|
+
?? program.commands.find(command => requested === command.name())?.name();
|
|
76
|
+
await lifecycle.begin('help');
|
|
77
|
+
const code = commander.exitCode ?? 0;
|
|
78
|
+
await lifecycle.finish(new CommandExit(code, code ? 'failure' : 'success', code ? 'validation_failed' : undefined), topic)
|
|
79
|
+
.catch(() => undefined);
|
|
80
|
+
process.exitCode = code;
|
|
81
|
+
await settleTelemetrySettings();
|
|
82
|
+
await cleanupLoadedApiArtifacts();
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
85
|
+
if (commander.code === 'commander.version') {
|
|
86
|
+
await lifecycle.begin('version');
|
|
87
|
+
await finish(new CommandExit(0, 'success'));
|
|
88
|
+
return;
|
|
89
|
+
}
|
|
90
|
+
if (!selected)
|
|
91
|
+
await lifecycle.begin(['unknown_command', 'unknown_option'].includes(telemetryErrorCode(error)) ? 'unknown' : requested ?? 'unknown');
|
|
92
|
+
const exit = error instanceof CommandExit ? error
|
|
93
|
+
: new CommandExit(commander.exitCode ?? 1, 'failure', telemetryErrorCode(error));
|
|
94
|
+
await finishAndExit(exit.exitCode, exit.outcome, exit.errorCode);
|
|
95
|
+
}
|
|
31
96
|
}
|
|
32
97
|
main();
|
package/dist/cli.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAyCpC,QAAA,MAAM,OAAO,SAAgB,CAAC;AAE9B,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;;EAKpE;AA8RD,OAAO,EAAE,OAAO,EAAE,CAAC"}
|
package/dist/cli.js
CHANGED
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
import { readFileSync } from 'node:fs';
|
|
2
|
-
import { fileURLToPath } from 'node:url';
|
|
3
1
|
import { Command } from 'commander';
|
|
4
2
|
import { initCommand } from './commands/init.js';
|
|
5
3
|
import { mcpCommand } from './commands/mcp.js';
|
|
@@ -9,19 +7,15 @@ import { generateDatasetsCommand } from './commands/generate-datasets.js';
|
|
|
9
7
|
import { generateManifestCommand } from './commands/generate-manifest.js';
|
|
10
8
|
import { buildDeploymentCommand, prepareDeploymentReleaseCommand, validateDeploymentCommand, } from './commands/deployment.js';
|
|
11
9
|
import { deployCommand, submitDeploymentCommand, } from './commands/deploy.js';
|
|
10
|
+
import { deploymentStatusCommand, } from './commands/deployment-status.js';
|
|
12
11
|
import { loginCommand, logoutCommand, } from './commands/login.js';
|
|
13
12
|
import { diffCommand, pullCommand, } from './commands/live-source.js';
|
|
14
13
|
import { isPromptCancelled } from './utils/prompts.js';
|
|
14
|
+
import { telemetryCommand } from './commands/telemetry.js';
|
|
15
|
+
import { getCliVersion } from './utils/cli-version.js';
|
|
16
|
+
import { CommandExit } from './utils/command-exit.js';
|
|
17
|
+
import { telemetryErrorCode } from './utils/telemetry/error-code.js';
|
|
15
18
|
const program = new Command();
|
|
16
|
-
function getCliVersion() {
|
|
17
|
-
try {
|
|
18
|
-
const pkg = JSON.parse(readFileSync(fileURLToPath(new URL('../package.json', import.meta.url)), 'utf8'));
|
|
19
|
-
return pkg.version ?? '0.0.0';
|
|
20
|
-
}
|
|
21
|
-
catch {
|
|
22
|
-
return '0.0.0';
|
|
23
|
-
}
|
|
24
|
-
}
|
|
25
19
|
export function normalizeInitOptions(options) {
|
|
26
20
|
return {
|
|
27
21
|
...options,
|
|
@@ -31,7 +25,14 @@ export function normalizeInitOptions(options) {
|
|
|
31
25
|
program
|
|
32
26
|
.name('hypequery')
|
|
33
27
|
.description('Type-safe analytics layer for ClickHouse')
|
|
34
|
-
.version(getCliVersion())
|
|
28
|
+
.version(getCliVersion())
|
|
29
|
+
.option('--no-telemetry', 'Disable anonymous usage telemetry for this invocation');
|
|
30
|
+
program
|
|
31
|
+
.command('telemetry [action]')
|
|
32
|
+
.description('Show or change anonymous usage telemetry settings (status|enable|disable)')
|
|
33
|
+
.action(runCommand(async (action) => {
|
|
34
|
+
await telemetryCommand(action, { telemetry: program.opts().telemetry });
|
|
35
|
+
}));
|
|
35
36
|
program
|
|
36
37
|
.command('login')
|
|
37
38
|
.description('Authorize this machine with Hypequery Cloud')
|
|
@@ -71,14 +72,16 @@ function runCommand(action) {
|
|
|
71
72
|
await action(...args);
|
|
72
73
|
}
|
|
73
74
|
catch (error) {
|
|
75
|
+
if (error instanceof CommandExit)
|
|
76
|
+
throw error;
|
|
74
77
|
// Ctrl+C at a prompt is a deliberate abort, not a failure: report it as
|
|
75
78
|
// the interrupt it is instead of dumping an error and exiting 1.
|
|
76
79
|
if (isPromptCancelled(error)) {
|
|
77
80
|
console.log('\nCancelled.');
|
|
78
|
-
|
|
81
|
+
throw new CommandExit(130, 'cancelled', 'prompt_cancelled');
|
|
79
82
|
}
|
|
80
83
|
console.error(error instanceof Error ? error.message : error);
|
|
81
|
-
|
|
84
|
+
throw new CommandExit(1, 'failure', telemetryErrorCode(error));
|
|
82
85
|
}
|
|
83
86
|
};
|
|
84
87
|
}
|
|
@@ -133,6 +136,7 @@ program
|
|
|
133
136
|
.option('--path <path>', 'Analytics directory (loads <path>/api.ts or <path>/queries.ts)')
|
|
134
137
|
.option('--tenant <id>', 'Trusted tenant applied to every tenant-scoped dataset')
|
|
135
138
|
.option('--self-test', 'Check the entrypoint and exit without speaking MCP')
|
|
139
|
+
.option('--url <url>', 'With --self-test: check a hosted MCP endpoint (key from HYPEQUERY_API_KEY)')
|
|
136
140
|
.action(runCommand(async (file, options) => {
|
|
137
141
|
await mcpCommand(file, options);
|
|
138
142
|
}));
|
|
@@ -198,6 +202,16 @@ program
|
|
|
198
202
|
.action(runCommand(async (bundle, options) => {
|
|
199
203
|
await submitDeploymentCommand(bundle, options);
|
|
200
204
|
}));
|
|
205
|
+
program
|
|
206
|
+
.command('deployment:status')
|
|
207
|
+
.description('Show the live release and hosted connection details for a Cloud target')
|
|
208
|
+
.option('--project <project>', 'Target project identifier (advanced override)')
|
|
209
|
+
.option('--environment <environment>', 'Target environment identifier (advanced override)')
|
|
210
|
+
.option('--endpoint <url>', 'HTTPS submission endpoint; requires HYPEQUERY_API_TOKEN')
|
|
211
|
+
.option('--mcp-config', 'Also print MCP client configuration for the hosted endpoint')
|
|
212
|
+
.action(runCommand(async (options) => {
|
|
213
|
+
await deploymentStatusCommand(options);
|
|
214
|
+
}));
|
|
201
215
|
program
|
|
202
216
|
.command('deploy <source>')
|
|
203
217
|
.description('Build, prepare, and deploy a dataset-only Cloud publication')
|
|
@@ -208,6 +222,7 @@ program
|
|
|
208
222
|
.option('--no-source', 'Exclude project source files from the deployment bundle')
|
|
209
223
|
.option('--endpoint <url>', 'HTTPS submission endpoint; requires HYPEQUERY_API_TOKEN')
|
|
210
224
|
.option('--replace-restored', 'Intentionally replace a restored live release')
|
|
225
|
+
.option('--mcp-config', 'Also print MCP client configuration for the hosted endpoint')
|
|
211
226
|
.action(runCommand(async (source, options) => {
|
|
212
227
|
await deployCommand(source, options);
|
|
213
228
|
}));
|
|
@@ -223,7 +238,7 @@ program
|
|
|
223
238
|
}
|
|
224
239
|
else {
|
|
225
240
|
console.error(`Unknown command: ${command}`);
|
|
226
|
-
|
|
241
|
+
throw new CommandExit(1, 'failure', 'unknown_command');
|
|
227
242
|
}
|
|
228
243
|
}
|
|
229
244
|
else {
|
|
@@ -234,6 +249,9 @@ program
|
|
|
234
249
|
program.on('--help', () => {
|
|
235
250
|
console.log('');
|
|
236
251
|
console.log('Examples:');
|
|
252
|
+
console.log(' hypequery telemetry status');
|
|
253
|
+
console.log(' hypequery telemetry disable');
|
|
254
|
+
console.log(' hypequery --no-telemetry init');
|
|
237
255
|
console.log(' hypequery login');
|
|
238
256
|
console.log(' hypequery logout');
|
|
239
257
|
console.log(' hypequery init');
|
|
@@ -1,11 +1,14 @@
|
|
|
1
1
|
import { createHttpDeploymentUploadTransport, type DeploymentSubmissionResponse } from '../utils/deployment-upload.js';
|
|
2
2
|
import { type StoredCloudCredential } from '../utils/cloud-credential-store.js';
|
|
3
3
|
import { fetchLiveDeployment } from '../utils/live-deployment.js';
|
|
4
|
+
import { fetchHostedEndpoints } from '../utils/hosted-endpoints.js';
|
|
4
5
|
import { buildDeploymentCommand, prepareDeploymentReleaseCommand } from './deployment.js';
|
|
5
6
|
export interface SubmitDeploymentOptions {
|
|
6
7
|
release?: string;
|
|
7
8
|
endpoint?: string;
|
|
8
9
|
replaceRestored?: boolean;
|
|
10
|
+
/** Also print MCP client configuration for the hosted endpoint. */
|
|
11
|
+
mcpConfig?: boolean;
|
|
9
12
|
}
|
|
10
13
|
export interface DeployOptions {
|
|
11
14
|
endpoint?: string;
|
|
@@ -15,12 +18,14 @@ export interface DeployOptions {
|
|
|
15
18
|
bundleOutput?: string;
|
|
16
19
|
releaseOutput?: string;
|
|
17
20
|
source?: boolean;
|
|
21
|
+
mcpConfig?: boolean;
|
|
18
22
|
}
|
|
19
23
|
export interface SubmitDeploymentDependencies {
|
|
20
24
|
readonly env?: Readonly<Record<string, string | undefined>>;
|
|
21
25
|
readonly createTransport?: typeof createHttpDeploymentUploadTransport;
|
|
22
26
|
readonly loadCredential?: () => Promise<StoredCloudCredential | null>;
|
|
23
27
|
readonly fetchLive?: typeof fetchLiveDeployment;
|
|
28
|
+
readonly fetchEndpoints?: typeof fetchHostedEndpoints;
|
|
24
29
|
}
|
|
25
30
|
export interface DeployDependencies extends SubmitDeploymentDependencies {
|
|
26
31
|
readonly buildDeployment?: typeof buildDeploymentCommand;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"deploy.d.ts","sourceRoot":"","sources":["../../src/commands/deploy.ts"],"names":[],"mappings":"AASA,OAAO,EACL,mCAAmC,EAEnC,KAAK,4BAA4B,EAElC,MAAM,+BAA+B,CAAC;AAEvC,OAAO,EACL,KAAK,qBAAqB,EAC3B,MAAM,oCAAoC,CAAC;AAE5C,OAAO,EAAE,mBAAmB,EAAE,MAAM,6BAA6B,CAAC;AAClE,OAAO,EACL,sBAAsB,EACtB,+BAA+B,EAChC,MAAM,iBAAiB,CAAC;AAMzB,MAAM,WAAW,uBAAuB;IACtC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,eAAe,CAAC,EAAE,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"deploy.d.ts","sourceRoot":"","sources":["../../src/commands/deploy.ts"],"names":[],"mappings":"AASA,OAAO,EACL,mCAAmC,EAEnC,KAAK,4BAA4B,EAElC,MAAM,+BAA+B,CAAC;AAEvC,OAAO,EACL,KAAK,qBAAqB,EAC3B,MAAM,oCAAoC,CAAC;AAE5C,OAAO,EAAE,mBAAmB,EAAE,MAAM,6BAA6B,CAAC;AAClE,OAAO,EACL,oBAAoB,EACrB,MAAM,8BAA8B,CAAC;AAEtC,OAAO,EACL,sBAAsB,EACtB,+BAA+B,EAChC,MAAM,iBAAiB,CAAC;AAMzB,MAAM,WAAW,uBAAuB;IACtC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,mEAAmE;IACnE,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB;AAED,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB;AAED,MAAM,WAAW,4BAA4B;IAC3C,QAAQ,CAAC,GAAG,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAC,CAAC;IAC5D,QAAQ,CAAC,eAAe,CAAC,EAAE,OAAO,mCAAmC,CAAC;IACtE,QAAQ,CAAC,cAAc,CAAC,EAAE,MAAM,OAAO,CAAC,qBAAqB,GAAG,IAAI,CAAC,CAAC;IACtE,QAAQ,CAAC,SAAS,CAAC,EAAE,OAAO,mBAAmB,CAAC;IAChD,QAAQ,CAAC,cAAc,CAAC,EAAE,OAAO,oBAAoB,CAAC;CACvD;AAED,MAAM,WAAW,kBAAmB,SAAQ,4BAA4B;IACtE,QAAQ,CAAC,eAAe,CAAC,EAAE,OAAO,sBAAsB,CAAC;IACzD,QAAQ,CAAC,wBAAwB,CAAC,EAAE,OAAO,+BAA+B,CAAC;IAC3E,QAAQ,CAAC,gBAAgB,CAAC,EAAE,OAAO,uBAAuB,CAAC;CAC5D;AA4DD,wBAAsB,uBAAuB,CAC3C,UAAU,EAAE,MAAM,GAAG,SAAS,EAC9B,OAAO,GAAE,uBAA4B,EACrC,YAAY,GAAE,4BAAiC,GAC9C,OAAO,CAAC,4BAA4B,CAAC,CAiFvC;AAsBD,wBAAsB,aAAa,CACjC,UAAU,EAAE,MAAM,GAAG,SAAS,EAC9B,OAAO,GAAE,aAAkB,EAC3B,YAAY,GAAE,kBAAuB,GACpC,OAAO,CAAC,4BAA4B,CAAC,CAwCvC"}
|
package/dist/commands/deploy.js
CHANGED
|
@@ -6,6 +6,8 @@ import { createHttpDeploymentUploadTransport, DeploymentUploadError, } from '../
|
|
|
6
6
|
import { logger } from '../utils/logger.js';
|
|
7
7
|
import { resolveDeploymentCredential } from '../utils/cloud-deployment-access.js';
|
|
8
8
|
import { fetchLiveDeployment } from '../utils/live-deployment.js';
|
|
9
|
+
import { fetchHostedEndpoints, } from '../utils/hosted-endpoints.js';
|
|
10
|
+
import { printHostedEndpoints } from '../utils/hosted-endpoints-output.js';
|
|
9
11
|
import { buildDeploymentCommand, prepareDeploymentReleaseCommand, } from './deployment.js';
|
|
10
12
|
const MAX_RELEASE_FILE_BYTES = 16 * 1024;
|
|
11
13
|
const DEFAULT_BUNDLE_PATH = 'analytics/hypequery-deployment';
|
|
@@ -120,6 +122,13 @@ export async function submitDeploymentCommand(bundlePath, options = {}, dependen
|
|
|
120
122
|
: 'Deployment release already exists');
|
|
121
123
|
logger.info(`Release identity: ${result.releaseIdentity}`);
|
|
122
124
|
logger.info(`Bundle identity: ${result.bundleIdentity}`);
|
|
125
|
+
const endpoints = await (dependencies.fetchEndpoints ?? fetchHostedEndpoints)({
|
|
126
|
+
endpoint: deploymentEndpoint,
|
|
127
|
+
token,
|
|
128
|
+
target: release.release.target,
|
|
129
|
+
});
|
|
130
|
+
if (endpoints)
|
|
131
|
+
printHostedEndpoints(endpoints, options.mcpConfig === true);
|
|
123
132
|
return result;
|
|
124
133
|
}
|
|
125
134
|
/**
|
|
@@ -172,5 +181,6 @@ export async function deployCommand(sourcePath, options = {}, dependencies = {})
|
|
|
172
181
|
release: releasePath,
|
|
173
182
|
endpoint: options.endpoint,
|
|
174
183
|
replaceRestored: options.replaceRestored,
|
|
184
|
+
mcpConfig: options.mcpConfig,
|
|
175
185
|
}, dependencies);
|
|
176
186
|
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { type CloudDeploymentAccessDependencies } from '../utils/cloud-deployment-access.js';
|
|
2
|
+
import { fetchHostedEndpoints } from '../utils/hosted-endpoints.js';
|
|
3
|
+
import { fetchLiveDeployment } from '../utils/live-deployment.js';
|
|
4
|
+
export interface DeploymentStatusOptions {
|
|
5
|
+
readonly endpoint?: string;
|
|
6
|
+
readonly project?: string;
|
|
7
|
+
readonly environment?: string;
|
|
8
|
+
readonly mcpConfig?: boolean;
|
|
9
|
+
}
|
|
10
|
+
export interface DeploymentStatusDependencies extends CloudDeploymentAccessDependencies {
|
|
11
|
+
readonly fetchLive?: typeof fetchLiveDeployment;
|
|
12
|
+
readonly fetchEndpoints?: typeof fetchHostedEndpoints;
|
|
13
|
+
}
|
|
14
|
+
/** Read the current target and its hosted connection details without deploying. */
|
|
15
|
+
export declare function deploymentStatusCommand(options?: DeploymentStatusOptions, dependencies?: DeploymentStatusDependencies): Promise<void>;
|
|
16
|
+
//# sourceMappingURL=deployment-status.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"deployment-status.d.ts","sourceRoot":"","sources":["../../src/commands/deployment-status.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,iCAAiC,EACvC,MAAM,qCAAqC,CAAC;AAE7C,OAAO,EAAE,oBAAoB,EAAE,MAAM,8BAA8B,CAAC;AAEpE,OAAO,EAAE,mBAAmB,EAAE,MAAM,6BAA6B,CAAC;AAGlE,MAAM,WAAW,uBAAuB;IACtC,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,SAAS,CAAC,EAAE,OAAO,CAAC;CAC9B;AAED,MAAM,WAAW,4BAA6B,SAAQ,iCAAiC;IACrF,QAAQ,CAAC,SAAS,CAAC,EAAE,OAAO,mBAAmB,CAAC;IAChD,QAAQ,CAAC,cAAc,CAAC,EAAE,OAAO,oBAAoB,CAAC;CACvD;AAED,mFAAmF;AACnF,wBAAsB,uBAAuB,CAC3C,OAAO,GAAE,uBAA4B,EACrC,YAAY,GAAE,4BAAiC,GAC9C,OAAO,CAAC,IAAI,CAAC,CAyBf"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { resolveDeploymentCredential, } from '../utils/cloud-deployment-access.js';
|
|
2
|
+
import { deploymentTargetFromOptions } from '../utils/deployment-target.js';
|
|
3
|
+
import { fetchHostedEndpoints } from '../utils/hosted-endpoints.js';
|
|
4
|
+
import { printHostedEndpoints } from '../utils/hosted-endpoints-output.js';
|
|
5
|
+
import { fetchLiveDeployment } from '../utils/live-deployment.js';
|
|
6
|
+
import { logger } from '../utils/logger.js';
|
|
7
|
+
/** Read the current target and its hosted connection details without deploying. */
|
|
8
|
+
export async function deploymentStatusCommand(options = {}, dependencies = {}) {
|
|
9
|
+
const access = await resolveDeploymentCredential(options.endpoint, dependencies);
|
|
10
|
+
const target = deploymentTargetFromOptions(options, access.storedCredential);
|
|
11
|
+
const live = await (dependencies.fetchLive ?? fetchLiveDeployment)({
|
|
12
|
+
endpoint: access.endpoint,
|
|
13
|
+
token: access.token,
|
|
14
|
+
target,
|
|
15
|
+
resource: 'state',
|
|
16
|
+
});
|
|
17
|
+
logger.info(`Target: ${target.project} / ${target.environment}`);
|
|
18
|
+
if (live?.active) {
|
|
19
|
+
logger.success(`Live release: ${live.active.releaseIdentity}`);
|
|
20
|
+
logger.info(`Activated: ${live.active.activatedAt}`);
|
|
21
|
+
if (live.active.restored)
|
|
22
|
+
logger.info('This release was restored from history.');
|
|
23
|
+
}
|
|
24
|
+
else {
|
|
25
|
+
logger.info('No live release yet.');
|
|
26
|
+
}
|
|
27
|
+
const endpoints = await (dependencies.fetchEndpoints ?? fetchHostedEndpoints)({
|
|
28
|
+
endpoint: access.endpoint,
|
|
29
|
+
token: access.token,
|
|
30
|
+
target,
|
|
31
|
+
});
|
|
32
|
+
if (endpoints)
|
|
33
|
+
printHostedEndpoints(endpoints, options.mcpConfig === true);
|
|
34
|
+
else
|
|
35
|
+
logger.warn('Cloud did not return hosted endpoint details.');
|
|
36
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dev.d.ts","sourceRoot":"","sources":["../../src/commands/dev.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"dev.d.ts","sourceRoot":"","sources":["../../src/commands/dev.ts"],"names":[],"mappings":"AAkCA,MAAM,WAAW,UAAU;IACzB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,wBAAsB,UAAU,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,OAAO,GAAE,UAAe,iBA2OvE"}
|
package/dist/commands/dev.js
CHANGED
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
import { exitWith, finishAndExit } from '../utils/command-exit.js';
|
|
2
|
+
import { telemetryErrorCode } from '../utils/telemetry/error-code.js';
|
|
3
|
+
import { DevSession } from '../utils/telemetry/dev-session.js';
|
|
4
|
+
import { setCommandTelemetryError } from '../utils/telemetry/command-context.js';
|
|
1
5
|
import { watch } from 'node:fs';
|
|
2
6
|
import path from 'node:path';
|
|
3
7
|
import ora from 'ora';
|
|
@@ -27,6 +31,7 @@ function displayQueriesFileNotFoundError(commandName) {
|
|
|
27
31
|
logger.newline();
|
|
28
32
|
}
|
|
29
33
|
export async function devCommand(file, options = {}) {
|
|
34
|
+
const telemetry = new DevSession();
|
|
30
35
|
// Step 1: Find queries file
|
|
31
36
|
const queriesFile = file
|
|
32
37
|
? await findQueriesFile(file)
|
|
@@ -35,10 +40,11 @@ export async function devCommand(file, options = {}) {
|
|
|
35
40
|
: await findQueriesFile();
|
|
36
41
|
if (!queriesFile) {
|
|
37
42
|
displayQueriesFileNotFoundError('dev');
|
|
38
|
-
|
|
43
|
+
exitWith(1, 'failure', 'entrypoint_not_found');
|
|
39
44
|
}
|
|
40
45
|
logger.info(`Found: ${path.relative(process.cwd(), queriesFile)}`);
|
|
41
46
|
logger.newline();
|
|
47
|
+
telemetry.start(queriesFile, file, options);
|
|
42
48
|
let currentServer = null;
|
|
43
49
|
let lifecycleOperation = Promise.resolve();
|
|
44
50
|
let shutdownRequested = false;
|
|
@@ -61,9 +67,11 @@ export async function devCommand(file, options = {}) {
|
|
|
61
67
|
// Loading spinners for slow operations
|
|
62
68
|
const compileSpinner = ora('Compiling queries...').start();
|
|
63
69
|
const dbSpinner = ora('Connecting to ClickHouse...').start();
|
|
70
|
+
let loading = true;
|
|
64
71
|
try {
|
|
65
72
|
// Load the API module
|
|
66
73
|
const api = await loadApiModule(queriesFile);
|
|
74
|
+
loading = false;
|
|
67
75
|
compileSpinner.succeed('Compiled queries');
|
|
68
76
|
// Get table count for display
|
|
69
77
|
let tableCount = 0;
|
|
@@ -125,8 +133,10 @@ export async function devCommand(file, options = {}) {
|
|
|
125
133
|
logger.indent(`Visit: ${baseUrl}`);
|
|
126
134
|
}
|
|
127
135
|
}
|
|
136
|
+
return true;
|
|
128
137
|
}
|
|
129
138
|
catch (error) {
|
|
139
|
+
const code = loading ? telemetry.loadFailed(error) : telemetryErrorCode(error);
|
|
130
140
|
// If server startup or later setup fails, tear down any resources
|
|
131
141
|
// acquired by this attempt before retrying or exiting.
|
|
132
142
|
try {
|
|
@@ -158,21 +168,31 @@ export async function devCommand(file, options = {}) {
|
|
|
158
168
|
}
|
|
159
169
|
logger.newline();
|
|
160
170
|
if (!shouldWatch) {
|
|
161
|
-
|
|
171
|
+
setCommandTelemetryError(code);
|
|
172
|
+
exitWith(1, 'failure', code);
|
|
162
173
|
}
|
|
174
|
+
return false;
|
|
163
175
|
}
|
|
164
176
|
};
|
|
165
177
|
const restartServer = () => queueLifecycleOperation(async () => {
|
|
166
178
|
if (shutdownRequested)
|
|
167
179
|
return;
|
|
180
|
+
telemetry.reload();
|
|
168
181
|
if (currentServer) {
|
|
169
182
|
logger.newline();
|
|
170
183
|
logger.reload('File changed, restarting...');
|
|
171
184
|
logger.newline();
|
|
172
|
-
|
|
185
|
+
try {
|
|
186
|
+
await stopCurrentRuntime();
|
|
187
|
+
}
|
|
188
|
+
catch (error) {
|
|
189
|
+
telemetry.reloadFailed();
|
|
190
|
+
throw error;
|
|
191
|
+
}
|
|
173
192
|
}
|
|
174
193
|
if (!shutdownRequested) {
|
|
175
|
-
await startServer()
|
|
194
|
+
if (!await startServer())
|
|
195
|
+
telemetry.reloadFailed();
|
|
176
196
|
}
|
|
177
197
|
});
|
|
178
198
|
const shutdown = () => {
|
|
@@ -183,7 +203,7 @@ export async function devCommand(file, options = {}) {
|
|
|
183
203
|
logger.info('Shutting down dev server...');
|
|
184
204
|
return queueLifecycleOperation(async () => {
|
|
185
205
|
await stopCurrentRuntime();
|
|
186
|
-
|
|
206
|
+
await finishAndExit(0, 'interrupted');
|
|
187
207
|
});
|
|
188
208
|
};
|
|
189
209
|
// Start initial server
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"generate-datasets.d.ts","sourceRoot":"","sources":["../../src/commands/generate-datasets.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"generate-datasets.d.ts","sourceRoot":"","sources":["../../src/commands/generate-datasets.ts"],"names":[],"mappings":"AAsBA,MAAM,WAAW,uBAAuB;IACtC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB;AA2BD,wBAAsB,uBAAuB,CAAC,OAAO,GAAE,uBAA4B,iBA+KlF"}
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { exitWith } from '../utils/command-exit.js';
|
|
2
|
+
import { telemetryErrorCode } from '../utils/telemetry/error-code.js';
|
|
1
3
|
/**
|
|
2
4
|
* Generate Datasets Command
|
|
3
5
|
*
|
|
@@ -13,6 +15,9 @@ import { redactConnectionUrl } from '../utils/redact-connection-url.js';
|
|
|
13
15
|
import { logDatasetGenerationWarnings } from '../utils/dataset-generation-warnings.js';
|
|
14
16
|
import { formatGeneratedFileDiff } from '../utils/generated-file-diff.js';
|
|
15
17
|
import { readGeneratedFile, writeGeneratedFileAtomically } from '../utils/generated-file.js';
|
|
18
|
+
import { updateCommandTelemetry, setCommandTelemetryError } from '../utils/telemetry/command-context.js';
|
|
19
|
+
import { countBucket } from '../utils/telemetry/buckets.js';
|
|
20
|
+
import { warningBuckets } from '../utils/telemetry/generation-metrics.js';
|
|
16
21
|
/**
|
|
17
22
|
* Turns the written path into something pasteable into an import statement:
|
|
18
23
|
* strips the `.ts` extension and makes it explicitly relative.
|
|
@@ -35,6 +40,8 @@ function parseTableList(value) {
|
|
|
35
40
|
return parsed && parsed.length > 0 ? parsed : undefined;
|
|
36
41
|
}
|
|
37
42
|
export async function generateDatasetsCommand(options = {}) {
|
|
43
|
+
updateCommandTelemetry('generate:datasets', { mode: options.check ? 'check' : options.diff ? 'diff' : 'write', force: !!options.force,
|
|
44
|
+
tenant_column_used: !!options.tenantColumn, tables_filter_used: !!options.tables, exclude_filter_used: !!options.excludeTables });
|
|
38
45
|
// Determine output path
|
|
39
46
|
let outputPath;
|
|
40
47
|
if (options.output) {
|
|
@@ -52,6 +59,7 @@ export async function generateDatasetsCommand(options = {}) {
|
|
|
52
59
|
const excludedTables = parseTableList(options.excludeTables);
|
|
53
60
|
if (options.force && (options.check || options.diff)) {
|
|
54
61
|
logger.error('--force cannot be combined with --check or --diff.');
|
|
62
|
+
setCommandTelemetryError('validation_failed');
|
|
55
63
|
process.exitCode = 1;
|
|
56
64
|
return;
|
|
57
65
|
}
|
|
@@ -80,9 +88,16 @@ export async function generateDatasetsCommand(options = {}) {
|
|
|
80
88
|
const generatedCount = generatedTables.length || tableCount;
|
|
81
89
|
datasetSpinner.succeed(`Generated dataset definitions for ${generatedCount} ${generatedCount === 1 ? 'table' : 'tables'}`);
|
|
82
90
|
logDatasetGenerationWarnings(generated?.warnings);
|
|
91
|
+
updateCommandTelemetry('generate:datasets', { datasets_generated_bucket: countBucket(generated.tables.length), warning_counts: warningBuckets(generated.warnings) });
|
|
83
92
|
const relativeOutput = path.relative(process.cwd(), outputPath);
|
|
84
93
|
const currentContents = await readGeneratedFile(outputPath);
|
|
85
94
|
const contentsMatch = currentContents === generated.contents;
|
|
95
|
+
if (options.check) {
|
|
96
|
+
const result = contentsMatch ? 'up_to_date' : currentContents === undefined ? 'missing' : 'out_of_date';
|
|
97
|
+
updateCommandTelemetry('generate:datasets', { check_result: result });
|
|
98
|
+
if (!contentsMatch)
|
|
99
|
+
setCommandTelemetryError(currentContents === undefined ? 'output_missing' : 'output_out_of_date');
|
|
100
|
+
}
|
|
86
101
|
if (contentsMatch) {
|
|
87
102
|
logger.success(options.check || options.diff
|
|
88
103
|
? `Dataset definitions are up to date: ${relativeOutput}`
|
|
@@ -92,6 +107,7 @@ export async function generateDatasetsCommand(options = {}) {
|
|
|
92
107
|
}
|
|
93
108
|
}
|
|
94
109
|
else if (options.diff) {
|
|
110
|
+
setCommandTelemetryError('output_out_of_date');
|
|
95
111
|
logger.raw(formatGeneratedFileDiff(currentContents ?? '', generated.contents, relativeOutput));
|
|
96
112
|
logger.error(`Generated dataset definitions differ: ${relativeOutput}`);
|
|
97
113
|
process.exitCode = 1;
|
|
@@ -173,6 +189,6 @@ export async function generateDatasetsCommand(options = {}) {
|
|
|
173
189
|
logger.error(String(error));
|
|
174
190
|
}
|
|
175
191
|
logger.newline();
|
|
176
|
-
|
|
192
|
+
exitWith(1, 'failure', telemetryErrorCode(error));
|
|
177
193
|
}
|
|
178
194
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"generate-manifest.d.ts","sourceRoot":"","sources":["../../src/commands/generate-manifest.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"generate-manifest.d.ts","sourceRoot":"","sources":["../../src/commands/generate-manifest.ts"],"names":[],"mappings":"AAOA,MAAM,WAAW,uBAAuB;IACtC,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,wBAAsB,uBAAuB,CAC3C,OAAO,EAAE,MAAM,GAAG,SAAS,EAC3B,OAAO,GAAE,uBAA4B,iBA2BtC"}
|
|
@@ -2,7 +2,10 @@ import { mkdir, writeFile } from 'node:fs/promises';
|
|
|
2
2
|
import path from 'node:path';
|
|
3
3
|
import { loadApiModule } from '../utils/load-api.js';
|
|
4
4
|
import { logger } from '../utils/logger.js';
|
|
5
|
+
import { updateCommandTelemetry } from '../utils/telemetry/command-context.js';
|
|
6
|
+
import { manifestMetrics } from '../utils/telemetry/generation-metrics.js';
|
|
5
7
|
export async function generateManifestCommand(apiPath, options = {}) {
|
|
8
|
+
updateCommandTelemetry('generate:manifest', { custom_output: options.output !== undefined });
|
|
6
9
|
if (!apiPath) {
|
|
7
10
|
throw new Error('Missing API module path.\n\n' +
|
|
8
11
|
'Usage: hypequery generate:manifest analytics/api.ts --output analytics/hypequery-manifest.json');
|
|
@@ -15,6 +18,7 @@ export async function generateManifestCommand(apiPath, options = {}) {
|
|
|
15
18
|
`Export the value returned by createAPI() or initServe(...).serve(...).`);
|
|
16
19
|
}
|
|
17
20
|
const manifest = api.manifest();
|
|
21
|
+
updateCommandTelemetry('generate:manifest', manifestMetrics(api, manifest));
|
|
18
22
|
await mkdir(path.dirname(outputPath), { recursive: true });
|
|
19
23
|
await writeFile(outputPath, `${JSON.stringify(manifest, null, 2)}\n`, 'utf8');
|
|
20
24
|
logger.success(`Manifest written to ${outputPath}`);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"generate.d.ts","sourceRoot":"","sources":["../../src/commands/generate.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"generate.d.ts","sourceRoot":"","sources":["../../src/commands/generate.ts"],"names":[],"mappings":"AAMA,OAAO,EAAiC,KAAK,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAQ/F,MAAM,WAAW,eAAe;IAC9B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,YAAY,CAAC;IACxB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,wBAAsB,eAAe,CAAC,OAAO,GAAE,eAAoB,iBAqKlE"}
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { exitWith } from '../utils/command-exit.js';
|
|
2
|
+
import { telemetryErrorCode } from '../utils/telemetry/error-code.js';
|
|
1
3
|
import path from 'node:path';
|
|
2
4
|
import ora from 'ora';
|
|
3
5
|
import { logger } from '../utils/logger.js';
|
|
@@ -6,7 +8,13 @@ import { detectDatabase, getTableCount } from '../utils/detect-database.js';
|
|
|
6
8
|
import { ensureChdbInstalled } from '../utils/chdb-client.js';
|
|
7
9
|
import { getTypeGenerator } from '../generators/index.js';
|
|
8
10
|
import { redactConnectionUrl } from '../utils/redact-connection-url.js';
|
|
11
|
+
import { updateCommandTelemetry } from '../utils/telemetry/command-context.js';
|
|
12
|
+
import { countBucket } from '../utils/telemetry/buckets.js';
|
|
13
|
+
import { TypeGenerationMetrics } from '../utils/telemetry/generation-metrics.js';
|
|
9
14
|
export async function generateCommand(options = {}) {
|
|
15
|
+
const command = options.commandName === 'hypequery generate:types' ? 'generate:types' : 'generate';
|
|
16
|
+
const metrics = new TypeGenerationMetrics();
|
|
17
|
+
updateCommandTelemetry(command, { custom_output: !!(options.output || options.path), tables_filter_used: !!options.tables, chdb_path_given: !!options.chdbPath });
|
|
10
18
|
// Determine output path
|
|
11
19
|
let outputPath;
|
|
12
20
|
if (options.output) {
|
|
@@ -35,6 +43,7 @@ export async function generateCommand(options = {}) {
|
|
|
35
43
|
const requestedDbType = options.database;
|
|
36
44
|
const dbType = requestedDbType ?? (await detectDatabase());
|
|
37
45
|
const chdbPath = dbType === 'chdb' ? options.chdbPath : undefined;
|
|
46
|
+
updateCommandTelemetry(command, { database: dbType === 'clickhouse' || dbType === 'chdb' || dbType === 'bigquery' ? dbType : 'unknown', chdb_path_given: !!chdbPath });
|
|
38
47
|
if (dbType === 'chdb' && !requestedDbType) {
|
|
39
48
|
throw new Error('chDB generation must be explicit. Re-run with --database chdb and add --chdb-path <dir> for persistent storage.');
|
|
40
49
|
}
|
|
@@ -68,10 +77,13 @@ export async function generateCommand(options = {}) {
|
|
|
68
77
|
outputPath,
|
|
69
78
|
includeTables: parsedTables,
|
|
70
79
|
chdbPath,
|
|
80
|
+
onColumn: () => metrics.column(),
|
|
81
|
+
onUnsupportedType: type => metrics.fallback(type),
|
|
71
82
|
});
|
|
72
83
|
// The generator returns what it actually wrote after applying filters.
|
|
73
84
|
// Requested names may contain duplicates or tables that do not exist.
|
|
74
85
|
const generatedCount = generatedTables.length;
|
|
86
|
+
updateCommandTelemetry(command, { ...metrics.snapshot(), table_count_bucket: countBucket(generatedCount) });
|
|
75
87
|
typeSpinner.succeed(`Generated types for ${generatedCount} ${generatedCount === 1 ? 'table' : 'tables'}`);
|
|
76
88
|
logger.success(`Updated ${path.relative(process.cwd(), outputPath)}`);
|
|
77
89
|
logger.newline();
|
|
@@ -79,6 +91,7 @@ export async function generateCommand(options = {}) {
|
|
|
79
91
|
logger.newline();
|
|
80
92
|
}
|
|
81
93
|
catch (error) {
|
|
94
|
+
updateCommandTelemetry(command, metrics.snapshot());
|
|
82
95
|
activeSpinner.fail(failureMessage);
|
|
83
96
|
logger.newline();
|
|
84
97
|
if (error instanceof Error) {
|
|
@@ -140,6 +153,6 @@ export async function generateCommand(options = {}) {
|
|
|
140
153
|
logger.error(String(error));
|
|
141
154
|
}
|
|
142
155
|
logger.newline();
|
|
143
|
-
|
|
156
|
+
exitWith(1, 'failure', telemetryErrorCode(error));
|
|
144
157
|
}
|
|
145
158
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":"AAUA,OAAO,EAcL,KAAK,SAAS,EACf,MAAM,qBAAqB,CAAC;AAc7B,OAAO,EAA2B,KAAK,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAYzF,MAAM,WAAW,WAAW;IAC1B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,SAAS,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,IAAI,CAAC,EAAE,gBAAgB,CAAC;CACzB;AA6GD,wBAAsB,WAAW,CAAC,OAAO,GAAE,WAAgB,iBAY1D"}
|