chkit 0.1.0-beta.7 → 0.1.0-beta.8

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 (67) hide show
  1. package/README.md +1 -0
  2. package/dist/bin/chkit.js +254 -314
  3. package/dist/bin/chkit.js.map +1 -1
  4. package/dist/bin/command-registry.d.ts +34 -0
  5. package/dist/bin/command-registry.d.ts.map +1 -0
  6. package/dist/bin/command-registry.js +87 -0
  7. package/dist/bin/command-registry.js.map +1 -0
  8. package/dist/bin/commands/check.d.ts +2 -1
  9. package/dist/bin/commands/check.d.ts.map +1 -1
  10. package/dist/bin/commands/check.js +17 -14
  11. package/dist/bin/commands/check.js.map +1 -1
  12. package/dist/bin/commands/drift.d.ts +2 -1
  13. package/dist/bin/commands/drift.d.ts.map +1 -1
  14. package/dist/bin/commands/drift.js +13 -4
  15. package/dist/bin/commands/drift.js.map +1 -1
  16. package/dist/bin/commands/generate/plan-pipeline.d.ts +1 -1
  17. package/dist/bin/commands/generate/plan-pipeline.d.ts.map +1 -1
  18. package/dist/bin/commands/generate/plan-pipeline.js +5 -1
  19. package/dist/bin/commands/generate/plan-pipeline.js.map +1 -1
  20. package/dist/bin/commands/generate/rename-mappings.d.ts +3 -3
  21. package/dist/bin/commands/generate/rename-mappings.d.ts.map +1 -1
  22. package/dist/bin/commands/generate/rename-mappings.js +4 -16
  23. package/dist/bin/commands/generate/rename-mappings.js.map +1 -1
  24. package/dist/bin/commands/generate.d.ts +2 -1
  25. package/dist/bin/commands/generate.d.ts.map +1 -1
  26. package/dist/bin/commands/generate.js +32 -15
  27. package/dist/bin/commands/generate.js.map +1 -1
  28. package/dist/bin/commands/migrate.d.ts +2 -1
  29. package/dist/bin/commands/migrate.d.ts.map +1 -1
  30. package/dist/bin/commands/migrate.js +23 -13
  31. package/dist/bin/commands/migrate.js.map +1 -1
  32. package/dist/bin/commands/plugin.d.ts +2 -1
  33. package/dist/bin/commands/plugin.d.ts.map +1 -1
  34. package/dist/bin/commands/plugin.js +88 -32
  35. package/dist/bin/commands/plugin.js.map +1 -1
  36. package/dist/bin/commands/status.d.ts +2 -1
  37. package/dist/bin/commands/status.d.ts.map +1 -1
  38. package/dist/bin/commands/status.js +9 -3
  39. package/dist/bin/commands/status.js.map +1 -1
  40. package/dist/bin/config.d.ts +0 -13
  41. package/dist/bin/config.d.ts.map +1 -1
  42. package/dist/bin/config.js +0 -20
  43. package/dist/bin/config.js.map +1 -1
  44. package/dist/bin/global-flags.d.ts +16 -0
  45. package/dist/bin/global-flags.d.ts.map +1 -0
  46. package/dist/bin/global-flags.js +7 -0
  47. package/dist/bin/global-flags.js.map +1 -0
  48. package/dist/bin/help.d.ts +5 -0
  49. package/dist/bin/help.d.ts.map +1 -0
  50. package/dist/bin/help.js +83 -0
  51. package/dist/bin/help.js.map +1 -0
  52. package/dist/bin/json-output.d.ts +1 -1
  53. package/dist/bin/json-output.d.ts.map +1 -1
  54. package/dist/bin/json-output.js.map +1 -1
  55. package/dist/bin/lib.d.ts +1 -1
  56. package/dist/bin/lib.d.ts.map +1 -1
  57. package/dist/bin/lib.js +1 -1
  58. package/dist/bin/lib.js.map +1 -1
  59. package/dist/bin/version.d.ts +1 -1
  60. package/dist/bin/version.d.ts.map +1 -1
  61. package/dist/bin/version.js +4 -1
  62. package/dist/bin/version.js.map +1 -1
  63. package/dist/plugins.d.ts +35 -11
  64. package/dist/plugins.d.ts.map +1 -1
  65. package/dist/plugins.js +1 -0
  66. package/dist/plugins.js.map +1 -1
  67. package/package.json +4 -5
package/README.md CHANGED
@@ -53,6 +53,7 @@ All commands support `--json` for machine-readable output and `--config <path>`
53
53
  | [`@chkit/plugin-codegen`](https://www.npmjs.com/package/@chkit/plugin-codegen) | Generate TypeScript row types and Zod schemas |
54
54
  | [`@chkit/plugin-pull`](https://www.npmjs.com/package/@chkit/plugin-pull) | Pull schemas from a live ClickHouse instance |
55
55
  | [`@chkit/plugin-backfill`](https://www.npmjs.com/package/@chkit/plugin-backfill) | Time-windowed data backfill with checkpoints |
56
+ | [`@chkit/plugin-obsessiondb`](https://www.npmjs.com/package/@chkit/plugin-obsessiondb) | Auto-rewrite Shared engines for ObsessionDB compatibility |
56
57
 
57
58
  ## Documentation
58
59
 
package/dist/bin/chkit.js CHANGED
@@ -1,73 +1,55 @@
1
1
  #!/usr/bin/env node
2
2
  import process from 'node:process';
3
- import { buildApplication, buildCommand, buildRouteMap, run } from '@stricli/core';
4
- import { CLI_VERSION } from './lib.js';
5
- import { cmdCheck } from './commands/check.js';
6
- import { cmdDrift } from './commands/drift.js';
7
- import { cmdGenerate } from './commands/generate.js';
3
+ import { typedFlags } from '../plugins.js';
4
+ import { createCommandRegistry } from './command-registry.js';
5
+ import { generateCommand } from './commands/generate.js';
6
+ import { migrateCommand } from './commands/migrate.js';
7
+ import { statusCommand } from './commands/status.js';
8
+ import { driftCommand } from './commands/drift.js';
9
+ import { checkCommand } from './commands/check.js';
10
+ import { pluginCommand } from './commands/plugin.js';
8
11
  import { cmdInit } from './commands/init.js';
9
- import { cmdMigrate } from './commands/migrate.js';
10
- import { cmdPlugin } from './commands/plugin.js';
11
- import { cmdPull } from './commands/pull.js';
12
- import { cmdStatus } from './commands/status.js';
13
- import { cmdCodegen } from './commands/codegen.js';
14
- function printHelp() {
15
- console.log(`chkit - ClickHouse toolkit\n
16
- Usage:
17
- chkit init
18
- chkit generate [--name <migration-name>] [--migration-id <id>] [--rename-table <old_db.old_table=new_db.new_table>] [--rename-column <db.table.old_column=new_column>] [--table <selector>] [--config <path>] [--dryrun] [--json]
19
- chkit pull [--out-file <path>] [--database <db>] [--dryrun] [--force] [--config <path>] [--json]
20
- chkit codegen [--check] [--out-file <path>] [--emit-zod] [--no-emit-zod] [--emit-ingest] [--no-emit-ingest] [--ingest-out-file <path>] [--bigint-mode <string|bigint>] [--include-views] [--config <path>] [--json]
21
- chkit migrate [--config <path>] [--apply|--execute] [--allow-destructive] [--table <selector>] [--json]
22
- chkit status [--config <path>] [--json]
23
- chkit drift [--config <path>] [--table <selector>] [--json]
24
- chkit check [--config <path>] [--strict] [--json]
25
- chkit plugin [<plugin-name> [<command> ...]] [--config <path>] [--json]
26
-
27
- Options:
28
- --config <path> Path to config file (default: clickhouse.config.ts)
29
- --name <name> Migration name for generate
30
- --migration-id <id>
31
- Deterministic migration file prefix override (e.g. 20260101010101)
32
- --rename-table <old_db.old_table=new_db.new_table>
33
- Explicit table rename mapping (comma-separated values supported)
34
- --rename-column <db.table.old_column=new_column>
35
- Explicit column rename mapping (comma-separated values supported)
36
- --table <selector>
37
- Limit command scope to tables by exact name or trailing wildcard prefix
38
- --apply Apply pending migrations on ClickHouse (no prompt)
39
- --execute Alias for --apply
40
- --allow-destructive
41
- Required in non-interactive mode when pending migrations contain destructive operations
42
- --dryrun Print operation plan without writing artifacts
43
- --check Validate generated type artifacts are up-to-date
44
- --out-file <path>
45
- Override output file path for pull/codegen one run
46
- --database <db> Limit pull to one or more databases (repeat or comma-separate)
47
- --force Allow pull schema to overwrite existing output file
48
- --emit-zod Enable Zod validator generation in codegen
49
- --no-emit-zod Disable Zod validator generation in codegen
50
- --emit-ingest Enable ingestion function generation in codegen
51
- --no-emit-ingest Disable ingestion function generation in codegen
52
- --ingest-out-file <path>
53
- Override ingestion output file path for codegen
54
- --bigint-mode <mode>
55
- Set large integer mapping mode for codegen (string|bigint)
56
- --include-views Include views in codegen output
57
- --strict Force all check policies on for this invocation
58
- --json Emit machine-readable JSON output
59
- -h, --help Show help
60
- -v, --version Show version
61
- `);
12
+ import { loadConfig, resolveDirs } from './config.js';
13
+ import { GLOBAL_FLAGS } from './global-flags.js';
14
+ import { formatGlobalHelp, formatCommandHelp } from './help.js';
15
+ import { parseFlags, UnknownFlagError, MissingFlagValueError } from '@chkit/core';
16
+ import { loadPluginRuntime } from './plugin-runtime.js';
17
+ import { resolveTableScope, tableKeysFromDefinitions } from './table-scope.js';
18
+ import { loadSchemaDefinitions } from './schema-loader.js';
19
+ import { CLI_VERSION } from './version.js';
20
+ const WELL_KNOWN_PLUGIN_COMMANDS = {
21
+ codegen: 'Codegen',
22
+ pull: 'Pull',
23
+ };
24
+ function extractConfigPath(argv) {
25
+ const idx = argv.indexOf('--config');
26
+ if (idx === -1)
27
+ return undefined;
28
+ return argv[idx + 1];
62
29
  }
63
- function addStringFlag(args, flag, value) {
64
- if (value === undefined || value.length === 0)
65
- return;
66
- args.push(flag, value);
67
- }
68
- function addBooleanFlag(args, flag, enabled) {
69
- if (enabled)
70
- args.push(flag);
30
+ /** Strip global flags (--config, --json, --table) from argv, returning their values and the rest. */
31
+ function stripGlobalFlags(argv) {
32
+ const rest = [];
33
+ let jsonMode = false;
34
+ let tableSelector;
35
+ for (let i = 0; i < argv.length; i++) {
36
+ const token = argv[i];
37
+ if (token === '--json') {
38
+ jsonMode = true;
39
+ continue;
40
+ }
41
+ if (token === '--config' && i + 1 < argv.length) {
42
+ i++;
43
+ continue;
44
+ }
45
+ if (token === '--table' && i + 1 < argv.length) {
46
+ tableSelector = argv[i + 1];
47
+ i++;
48
+ continue;
49
+ }
50
+ rest.push(token);
51
+ }
52
+ return { jsonMode, tableSelector, rest };
71
53
  }
72
54
  function exitIfNeeded() {
73
55
  const code = typeof process.exitCode === 'number'
@@ -79,259 +61,217 @@ function exitIfNeeded() {
79
61
  process.exit(code);
80
62
  }
81
63
  }
82
- const optionalStringFlag = (brief, placeholder = 'value') => ({
83
- kind: 'parsed',
84
- brief,
85
- parse: (input) => input,
86
- optional: true,
87
- placeholder,
88
- });
89
- const optionalBooleanFlag = (brief) => ({
90
- kind: 'boolean',
91
- brief,
92
- optional: true,
93
- });
94
- const app = buildApplication(buildRouteMap({
95
- docs: {
96
- brief: 'ClickHouse schema and migration toolkit',
97
- },
98
- routes: {
99
- init: buildCommand({
100
- parameters: {},
101
- docs: {
102
- brief: 'Initialize config and schema starter files',
103
- },
104
- async func() {
105
- await cmdInit();
106
- },
107
- }),
108
- generate: buildCommand({
109
- parameters: {
110
- flags: {
111
- config: optionalStringFlag('Path to config file', 'path'),
112
- name: optionalStringFlag('Migration name', 'name'),
113
- migrationId: optionalStringFlag('Deterministic migration file prefix', 'id'),
114
- renameTable: optionalStringFlag('Explicit table rename mapping old_db.old_table=new_db.new_table'),
115
- renameColumn: optionalStringFlag('Explicit column rename mapping db.table.old_column=new_column'),
116
- table: optionalStringFlag('Table selector (exact or trailing wildcard prefix)'),
117
- dryrun: optionalBooleanFlag('Print operation plan without writing artifacts'),
118
- json: optionalBooleanFlag('Emit machine-readable JSON output'),
119
- },
120
- },
121
- docs: {
122
- brief: 'Generate migration artifacts from schema definitions',
123
- },
124
- async func(flags) {
125
- const args = [];
126
- addStringFlag(args, '--config', flags.config);
127
- addStringFlag(args, '--name', flags.name);
128
- addStringFlag(args, '--migration-id', flags.migrationId);
129
- addStringFlag(args, '--rename-table', flags.renameTable);
130
- addStringFlag(args, '--rename-column', flags.renameColumn);
131
- addStringFlag(args, '--table', flags.table);
132
- addBooleanFlag(args, '--dryrun', flags.dryrun);
133
- addBooleanFlag(args, '--json', flags.json);
134
- await cmdGenerate(args);
135
- exitIfNeeded();
136
- },
137
- }),
138
- codegen: buildCommand({
139
- parameters: {
140
- flags: {
141
- config: optionalStringFlag('Path to config file', 'path'),
142
- check: optionalBooleanFlag('Check for stale generated artifacts without writing'),
143
- outFile: optionalStringFlag('Output file path override', 'path'),
144
- emitZod: optionalBooleanFlag('Emit Zod validators'),
145
- noEmitZod: optionalBooleanFlag('Disable Zod validator emission'),
146
- emitIngest: optionalBooleanFlag('Emit ingestion functions'),
147
- noEmitIngest: optionalBooleanFlag('Disable ingestion function emission'),
148
- ingestOutFile: optionalStringFlag('Ingestion output file path override', 'path'),
149
- bigintMode: optionalStringFlag('Bigint type mode: string or bigint', 'mode'),
150
- includeViews: optionalBooleanFlag('Include views in generated types'),
151
- json: optionalBooleanFlag('Emit machine-readable JSON output'),
152
- },
153
- },
154
- docs: {
155
- brief: 'Run code generation plugin workflow',
156
- },
157
- async func(flags) {
158
- const args = [];
159
- addStringFlag(args, '--config', flags.config);
160
- addBooleanFlag(args, '--check', flags.check);
161
- addStringFlag(args, '--out-file', flags.outFile);
162
- addBooleanFlag(args, '--emit-zod', flags.emitZod);
163
- addBooleanFlag(args, '--no-emit-zod', flags.noEmitZod);
164
- addBooleanFlag(args, '--emit-ingest', flags.emitIngest);
165
- addBooleanFlag(args, '--no-emit-ingest', flags.noEmitIngest);
166
- addStringFlag(args, '--ingest-out-file', flags.ingestOutFile);
167
- addStringFlag(args, '--bigint-mode', flags.bigintMode);
168
- addBooleanFlag(args, '--include-views', flags.includeViews);
169
- addBooleanFlag(args, '--json', flags.json);
170
- await cmdCodegen(args);
171
- exitIfNeeded();
172
- },
173
- }),
174
- migrate: buildCommand({
175
- parameters: {
176
- flags: {
177
- config: optionalStringFlag('Path to config file', 'path'),
178
- apply: optionalBooleanFlag('Apply pending migrations on ClickHouse'),
179
- execute: optionalBooleanFlag('Execute pending migrations on ClickHouse'),
180
- allowDestructive: optionalBooleanFlag('Allow destructive migrations tagged with risk=danger'),
181
- table: optionalStringFlag('Table selector (exact or trailing wildcard prefix)'),
182
- json: optionalBooleanFlag('Emit machine-readable JSON output'),
183
- },
184
- },
185
- docs: {
186
- brief: 'Review or execute pending migrations',
187
- },
188
- async func(flags) {
189
- const args = [];
190
- addStringFlag(args, '--config', flags.config);
191
- addBooleanFlag(args, '--apply', flags.apply);
192
- addBooleanFlag(args, '--execute', flags.execute);
193
- addBooleanFlag(args, '--allow-destructive', flags.allowDestructive);
194
- addStringFlag(args, '--table', flags.table);
195
- addBooleanFlag(args, '--json', flags.json);
196
- await cmdMigrate(args);
197
- exitIfNeeded();
198
- },
199
- }),
200
- status: buildCommand({
201
- parameters: {
202
- flags: {
203
- config: optionalStringFlag('Path to config file', 'path'),
204
- json: optionalBooleanFlag('Emit machine-readable JSON output'),
205
- },
206
- },
207
- docs: {
208
- brief: 'Show migration status and checksum mismatch information',
209
- },
210
- async func(flags) {
211
- const args = [];
212
- addStringFlag(args, '--config', flags.config);
213
- addBooleanFlag(args, '--json', flags.json);
214
- await cmdStatus(args);
215
- exitIfNeeded();
216
- },
217
- }),
218
- drift: buildCommand({
219
- parameters: {
220
- flags: {
221
- config: optionalStringFlag('Path to config file', 'path'),
222
- table: optionalStringFlag('Table selector (exact or trailing wildcard prefix)'),
223
- json: optionalBooleanFlag('Emit machine-readable JSON output'),
224
- },
225
- },
226
- docs: {
227
- brief: 'Compare snapshot state with current ClickHouse objects',
228
- },
229
- async func(flags) {
230
- const args = [];
231
- addStringFlag(args, '--config', flags.config);
232
- addStringFlag(args, '--table', flags.table);
233
- addBooleanFlag(args, '--json', flags.json);
234
- await cmdDrift(args);
235
- exitIfNeeded();
236
- },
237
- }),
238
- check: buildCommand({
239
- parameters: {
240
- flags: {
241
- config: optionalStringFlag('Path to config file', 'path'),
242
- strict: optionalBooleanFlag('Enable all policy checks'),
243
- json: optionalBooleanFlag('Emit machine-readable JSON output'),
244
- },
245
- },
246
- docs: {
247
- brief: 'Run policy checks for CI and release gates',
248
- },
249
- async func(flags) {
250
- const args = [];
251
- addStringFlag(args, '--config', flags.config);
252
- addBooleanFlag(args, '--strict', flags.strict);
253
- addBooleanFlag(args, '--json', flags.json);
254
- await cmdCheck(args);
255
- exitIfNeeded();
256
- },
257
- }),
258
- plugin: buildCommand({
259
- parameters: {
260
- flags: {
261
- config: optionalStringFlag('Path to config file', 'path'),
262
- json: optionalBooleanFlag('Emit machine-readable JSON output'),
263
- },
264
- },
265
- docs: {
266
- brief: 'List plugins and run plugin namespace commands',
267
- },
268
- async func(flags) {
269
- const args = [];
270
- addStringFlag(args, '--config', flags.config);
271
- addBooleanFlag(args, '--json', flags.json);
272
- await cmdPlugin(args);
273
- exitIfNeeded();
274
- },
275
- }),
276
- help: buildCommand({
277
- parameters: {},
278
- docs: {
279
- brief: 'Print help information',
280
- },
281
- func() {
282
- printHelp();
283
- },
284
- }),
285
- version: buildCommand({
286
- parameters: {},
287
- docs: {
288
- brief: 'Print version information',
289
- },
290
- func() {
291
- console.log(CLI_VERSION);
292
- },
293
- }),
294
- },
295
- }), {
296
- name: 'chkit',
297
- versionInfo: { currentVersion: CLI_VERSION },
298
- scanner: { caseStyle: 'allow-kebab-for-camel' },
299
- });
300
- const argv = process.argv.slice(2);
301
- if (argv[0] === 'plugin') {
302
- cmdPlugin(argv.slice(1))
303
- .then(() => {
304
- exitIfNeeded();
305
- })
306
- .catch((error) => {
307
- console.error(error instanceof Error ? error.message : String(error));
308
- process.exit(1);
64
+ function collectExtensions(runtime) {
65
+ return runtime.plugins.flatMap((p) => {
66
+ const extensions = p.plugin.extendCommands;
67
+ if (!extensions || extensions.length === 0)
68
+ return [];
69
+ return [{ pluginName: p.plugin.manifest.name, extensions }];
309
70
  });
310
71
  }
311
- else if (argv[0] === 'codegen') {
312
- cmdCodegen(argv.slice(1))
313
- .then(() => {
314
- exitIfNeeded();
315
- })
316
- .catch((error) => {
317
- console.error(error instanceof Error ? error.message : String(error));
318
- process.exit(1);
72
+ function collectPluginCommands(runtime) {
73
+ return runtime.plugins.flatMap((p) => {
74
+ const commands = p.plugin.commands;
75
+ if (!commands || commands.length === 0)
76
+ return [];
77
+ return [{ pluginName: p.plugin.manifest.name, commands, manifestName: p.plugin.manifest.name }];
319
78
  });
320
79
  }
321
- else if (argv[0] === 'pull') {
322
- cmdPull(argv.slice(1))
323
- .then(() => {
324
- exitIfNeeded();
325
- })
326
- .catch((error) => {
327
- console.error(error instanceof Error ? error.message : String(error));
328
- process.exit(1);
80
+ async function main() {
81
+ const argv = process.argv.slice(2);
82
+ const commandName = argv[0];
83
+ if (!commandName || commandName === '-h' || commandName === '--help') {
84
+ const configPathArg = extractConfigPath(argv);
85
+ try {
86
+ const { config, path: configPath } = await loadConfig(configPathArg);
87
+ const pluginRuntime = await loadPluginRuntime({ config, configPath, cliVersion: CLI_VERSION });
88
+ const registry = createCommandRegistry({
89
+ coreCommands: [generateCommand, migrateCommand, statusCommand, driftCommand, checkCommand, pluginCommand],
90
+ globalFlags: GLOBAL_FLAGS,
91
+ pluginExtensions: collectExtensions(pluginRuntime),
92
+ pluginCommands: collectPluginCommands(pluginRuntime),
93
+ });
94
+ console.log(formatGlobalHelp(registry, CLI_VERSION));
95
+ }
96
+ catch {
97
+ const registry = createCommandRegistry({
98
+ coreCommands: [generateCommand, migrateCommand, statusCommand, driftCommand, checkCommand, pluginCommand],
99
+ globalFlags: GLOBAL_FLAGS,
100
+ pluginExtensions: [],
101
+ pluginCommands: [],
102
+ });
103
+ console.log(formatGlobalHelp(registry, CLI_VERSION));
104
+ }
105
+ return;
106
+ }
107
+ if (commandName === '-v' || commandName === '--version') {
108
+ console.log(CLI_VERSION);
109
+ return;
110
+ }
111
+ if (commandName === 'init') {
112
+ await cmdInit();
113
+ return;
114
+ }
115
+ const configPathArg = extractConfigPath(argv);
116
+ const { config, path: configPath } = await loadConfig(configPathArg);
117
+ const pluginRuntime = await loadPluginRuntime({ config, configPath, cliVersion: CLI_VERSION });
118
+ const registry = createCommandRegistry({
119
+ coreCommands: [generateCommand, migrateCommand, statusCommand, driftCommand, checkCommand, pluginCommand],
120
+ globalFlags: GLOBAL_FLAGS,
121
+ pluginExtensions: collectExtensions(pluginRuntime),
122
+ pluginCommands: collectPluginCommands(pluginRuntime),
329
123
  });
330
- }
331
- else {
332
- run(app, argv, { process }).catch((error) => {
333
- console.error(error instanceof Error ? error.message : String(error));
334
- process.exit(1);
124
+ const resolved = registry.get(commandName);
125
+ if (!resolved) {
126
+ const wellKnown = WELL_KNOWN_PLUGIN_COMMANDS[commandName];
127
+ if (wellKnown) {
128
+ console.error(`${wellKnown} plugin is not configured. Add it to config.plugins first.`);
129
+ process.exitCode = 1;
130
+ return;
131
+ }
132
+ console.error(`Unknown command: ${commandName}`);
133
+ console.log('');
134
+ console.log(formatGlobalHelp(registry, CLI_VERSION));
135
+ process.exitCode = 1;
136
+ return;
137
+ }
138
+ if (argv.includes('--help') || argv.includes('-h')) {
139
+ console.log(formatCommandHelp(resolved, registry.globalFlags));
140
+ return;
141
+ }
142
+ if (resolved.isPlugin && !resolved.run) {
143
+ const argsAfterCommand = argv.slice(1);
144
+ let subcommandName;
145
+ if (resolved.subcommands) {
146
+ // Match against known subcommand names to avoid confusing flag values
147
+ // (e.g., config paths) with subcommand candidates
148
+ const matchedSub = resolved.subcommands.find((s) => argsAfterCommand.includes(s.name));
149
+ if (matchedSub) {
150
+ subcommandName = matchedSub.name;
151
+ }
152
+ else if (resolved.subcommands.length === 1) {
153
+ subcommandName = resolved.subcommands[0]?.name;
154
+ }
155
+ else {
156
+ console.log(formatCommandHelp(resolved, registry.globalFlags));
157
+ return;
158
+ }
159
+ }
160
+ const allPluginFlags = registry.resolveFlags(commandName, subcommandName);
161
+ let flags;
162
+ try {
163
+ flags = parseFlags(argsAfterCommand, allPluginFlags);
164
+ }
165
+ catch (error) {
166
+ if (error instanceof UnknownFlagError || error instanceof MissingFlagValueError) {
167
+ console.error(error.message);
168
+ process.exitCode = 1;
169
+ return;
170
+ }
171
+ throw error;
172
+ }
173
+ const gf = typedFlags(flags, GLOBAL_FLAGS);
174
+ const jsonMode = gf['--json'] === true;
175
+ const tableSelector = gf['--table'];
176
+ let tableScope;
177
+ try {
178
+ const definitions = await loadSchemaDefinitions(config.schema);
179
+ tableScope = resolveTableScope(tableSelector, tableKeysFromDefinitions(definitions));
180
+ }
181
+ catch {
182
+ tableScope = resolveTableScope(tableSelector, []);
183
+ }
184
+ try {
185
+ await pluginRuntime.runOnConfigLoaded({
186
+ command: commandName,
187
+ config,
188
+ configPath,
189
+ tableScope,
190
+ flags,
191
+ });
192
+ }
193
+ catch (error) {
194
+ const message = error instanceof Error ? error.message : String(error);
195
+ if (jsonMode) {
196
+ console.log(JSON.stringify({ ok: false, error: message }));
197
+ }
198
+ else {
199
+ console.error(message);
200
+ }
201
+ process.exitCode = 2;
202
+ exitIfNeeded();
203
+ return;
204
+ }
205
+ const pluginName = resolved.pluginName ?? commandName;
206
+ const pluginCommandName = subcommandName ?? commandName;
207
+ const { printOutput } = await import('./json-output.js');
208
+ const exitCode = await pluginRuntime.runPluginCommand(pluginName, pluginCommandName, {
209
+ config,
210
+ configPath,
211
+ jsonMode,
212
+ tableScope,
213
+ args: [],
214
+ flags,
215
+ print(value) {
216
+ printOutput(value, jsonMode);
217
+ },
218
+ });
219
+ if (exitCode !== 0)
220
+ process.exitCode = exitCode;
221
+ exitIfNeeded();
222
+ return;
223
+ }
224
+ // For the 'plugin' command, use lenient flag extraction since plugin-specific
225
+ // flags are handled by the plugin's own parser
226
+ if (commandName === 'plugin') {
227
+ const { jsonMode, tableSelector } = stripGlobalFlags(argv.slice(1));
228
+ const flags = {};
229
+ if (jsonMode)
230
+ flags['--json'] = true;
231
+ if (tableSelector)
232
+ flags['--table'] = tableSelector;
233
+ const dirs = resolveDirs(config);
234
+ if (!resolved.run)
235
+ throw new Error(`Command '${commandName}' has no run handler`);
236
+ await resolved.run({
237
+ command: commandName,
238
+ flags,
239
+ config,
240
+ configPath,
241
+ dirs,
242
+ pluginRuntime,
243
+ });
244
+ exitIfNeeded();
245
+ return;
246
+ }
247
+ const allFlags = registry.resolveFlags(commandName);
248
+ let flags;
249
+ try {
250
+ flags = parseFlags(argv.slice(1), allFlags);
251
+ }
252
+ catch (error) {
253
+ if (error instanceof UnknownFlagError || error instanceof MissingFlagValueError) {
254
+ console.error(error.message);
255
+ process.exitCode = 1;
256
+ return;
257
+ }
258
+ throw error;
259
+ }
260
+ const dirs = resolveDirs(config);
261
+ if (!resolved.run)
262
+ throw new Error(`Command '${commandName}' has no run handler`);
263
+ await resolved.run({
264
+ command: commandName,
265
+ flags,
266
+ config,
267
+ configPath,
268
+ dirs,
269
+ pluginRuntime,
335
270
  });
271
+ exitIfNeeded();
336
272
  }
273
+ main().catch((error) => {
274
+ console.error(error instanceof Error ? error.message : String(error));
275
+ process.exit(1);
276
+ });
337
277
  //# sourceMappingURL=chkit.js.map