@hydranium/cli 1.0.0-next.408 → 1.0.0-next.411

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 (51) hide show
  1. package/README.md +23 -5
  2. package/lib/cli.js +2 -0
  3. package/lib/cli.js.map +1 -1
  4. package/lib/commands/ast-ground-truth-args.js +2 -2
  5. package/lib/commands/ast-ground-truth-args.js.map +1 -1
  6. package/lib/commands/harness-args.d.ts +6 -5
  7. package/lib/commands/harness-args.d.ts.map +1 -1
  8. package/lib/commands/harness-args.js +66 -7
  9. package/lib/commands/harness-args.js.map +1 -1
  10. package/lib/commands/init-templates.d.ts.map +1 -1
  11. package/lib/commands/init-templates.js +11 -7
  12. package/lib/commands/init-templates.js.map +1 -1
  13. package/lib/commands/init.d.ts.map +1 -1
  14. package/lib/commands/init.js +3 -1
  15. package/lib/commands/init.js.map +1 -1
  16. package/lib/commands/lint-grammar-args.js +2 -2
  17. package/lib/commands/lint-grammar-args.js.map +1 -1
  18. package/lib/commands/measure-memory-args.js +2 -2
  19. package/lib/commands/measure-memory-args.js.map +1 -1
  20. package/lib/commands/message-catalogue-args.d.ts +16 -0
  21. package/lib/commands/message-catalogue-args.d.ts.map +1 -0
  22. package/lib/commands/message-catalogue-args.js +53 -0
  23. package/lib/commands/message-catalogue-args.js.map +1 -0
  24. package/lib/commands/message-catalogue.d.ts +21 -0
  25. package/lib/commands/message-catalogue.d.ts.map +1 -0
  26. package/lib/commands/message-catalogue.js +48 -0
  27. package/lib/commands/message-catalogue.js.map +1 -0
  28. package/lib/commands/model-docs-args.js +2 -2
  29. package/lib/commands/model-docs-args.js.map +1 -1
  30. package/lib/commands/reflect-args.js +2 -2
  31. package/lib/commands/reflect-args.js.map +1 -1
  32. package/lib/commands/validate-args.js +2 -2
  33. package/lib/commands/validate-args.js.map +1 -1
  34. package/lib/index.d.ts +1 -0
  35. package/lib/index.d.ts.map +1 -1
  36. package/lib/index.js +1 -0
  37. package/lib/index.js.map +1 -1
  38. package/package.json +19 -18
  39. package/src/cli.ts +2 -0
  40. package/src/commands/ast-ground-truth-args.ts +2 -2
  41. package/src/commands/harness-args.ts +69 -7
  42. package/src/commands/init-templates.ts +11 -7
  43. package/src/commands/init.ts +5 -1
  44. package/src/commands/lint-grammar-args.ts +2 -2
  45. package/src/commands/measure-memory-args.ts +2 -2
  46. package/src/commands/message-catalogue-args.ts +55 -0
  47. package/src/commands/message-catalogue.ts +56 -0
  48. package/src/commands/model-docs-args.ts +2 -2
  49. package/src/commands/reflect-args.ts +2 -2
  50. package/src/commands/validate-args.ts +2 -2
  51. package/src/index.ts +1 -0
@@ -0,0 +1,55 @@
1
+ /********************************************************************************
2
+ * Copyright (c) 2026 CrossBreeze, EclipseSource and others.
3
+ *
4
+ * This program and the accompanying materials are made available under the
5
+ * terms of the MIT License which is available in the project root.
6
+ *
7
+ * SPDX-License-Identifier: MIT
8
+ ********************************************************************************/
9
+
10
+ import { assertRequired, exitWithUsage, helpRequested, printHelp, type UsageError } from './harness-args.js';
11
+ import { runMessageCatalogue, type MessageCatalogueCommandOptions } from './message-catalogue.js';
12
+
13
+ export const MESSAGE_CATALOGUE_FLAGS: readonly string[] = ['--barrel', '--out-file'];
14
+ export const MESSAGE_CATALOGUE_VALUE_FLAGS = MESSAGE_CATALOGUE_FLAGS;
15
+ export const MESSAGE_CATALOGUE_HELP: readonly string[] = [
16
+ 'Usage: hydranium-cli message-catalogue --barrel <module>... [--out-file <file>]',
17
+ '',
18
+ 'Emit a flat JSON starter catalogue mapping message codes to English defaults.',
19
+ 'Modules are resolved from the current project and must be built first.',
20
+ 'Repeat --barrel for each framework head and your own messages. No server starts.',
21
+ '',
22
+ 'Options:',
23
+ ' --barrel <module> Messages package specifier or ESM file (required). Repeatable.',
24
+ ' --out-file <file> Write JSON here instead of stdout, after all imports succeed.'
25
+ ];
26
+
27
+ export function parseMessageCatalogueArgs(args: string[], onError: UsageError = exitWithUsage): MessageCatalogueCommandOptions {
28
+ const barrels: string[] = [];
29
+ let outFile: string | undefined;
30
+ for (let index = 0; index < args.length; index++) {
31
+ const flag = args[index];
32
+ if (!MESSAGE_CATALOGUE_FLAGS.includes(flag)) {
33
+ return onError(`Unexpected argument: ${flag} (hydranium-cli message-catalogue --help)`);
34
+ }
35
+ const value = args[++index];
36
+ if (value === undefined || value.startsWith('--')) {
37
+ return onError(`Missing value for ${flag}`);
38
+ }
39
+ if (flag === '--barrel') {
40
+ barrels.push(value);
41
+ } else {
42
+ outFile = value;
43
+ }
44
+ }
45
+ assertRequired(barrels[0], '--barrel', 'message-catalogue', onError);
46
+ return { barrels, outFile };
47
+ }
48
+
49
+ export async function runMessageCatalogueCommand(args: string[]): Promise<void> {
50
+ if (helpRequested(args, MESSAGE_CATALOGUE_VALUE_FLAGS)) {
51
+ printHelp(MESSAGE_CATALOGUE_HELP);
52
+ return;
53
+ }
54
+ await runMessageCatalogue(parseMessageCatalogueArgs(args));
55
+ }
@@ -0,0 +1,56 @@
1
+ /********************************************************************************
2
+ * Copyright (c) 2026 CrossBreeze, EclipseSource and others.
3
+ *
4
+ * This program and the accompanying materials are made available under the
5
+ * terms of the MIT License which is available in the project root.
6
+ *
7
+ * SPDX-License-Identifier: MIT
8
+ ********************************************************************************/
9
+
10
+ import { collectMessages, type MessageCatalogue } from '@hydranium/protocol';
11
+ import { resolve as resolveModule } from 'import-meta-resolve';
12
+ import { isAbsolute, resolve } from 'node:path';
13
+ import { pathToFileURL } from 'node:url';
14
+ import { emitReport } from './headless-harness.js';
15
+
16
+ /**
17
+ * Enumerate declarations rather than scanning source. Conflicting defaults
18
+ * must fail before any output is written, or import order chooses the English.
19
+ */
20
+ export function createMessageCatalogue(barrels: readonly object[]): MessageCatalogue {
21
+ const entries = new Map<string, string>();
22
+ for (const barrel of barrels) {
23
+ for (const message of collectMessages(barrel)) {
24
+ const previous = entries.get(message.code);
25
+ if (previous !== undefined && previous !== message.text) {
26
+ throw new Error(`Conflicting English defaults for message '${message.code}'.`);
27
+ }
28
+ entries.set(message.code, message.text);
29
+ }
30
+ }
31
+ return Object.fromEntries([...entries].sort(([a], [b]) => (a < b ? -1 : a > b ? 1 : 0)));
32
+ }
33
+
34
+ export interface MessageCatalogueCommandOptions {
35
+ readonly barrels: readonly string[];
36
+ readonly outFile?: string;
37
+ }
38
+
39
+ /** Resolve against the caller's project, including when the CLI is installed globally. */
40
+ export async function runMessageCatalogue(options: MessageCatalogueCommandOptions): Promise<void> {
41
+ const projectUrl = pathToFileURL(resolve('package.json')).href;
42
+ const barrels: object[] = [];
43
+ for (const specifier of options.barrels) {
44
+ const target =
45
+ specifier.startsWith('.') || isAbsolute(specifier) ? pathToFileURL(resolve(specifier)).href : resolveModule(specifier, projectUrl);
46
+ const barrel = (await import(target)) as object;
47
+ if (collectMessages(barrel).length === 0) {
48
+ throw new Error(`Message barrel '${specifier}' exports no declarations. Pass a built messages module.`);
49
+ }
50
+ barrels.push(barrel);
51
+ }
52
+ if (barrels.length === 0) {
53
+ throw new Error('Pass at least one --barrel messages module.');
54
+ }
55
+ emitReport(JSON.stringify(createMessageCatalogue(barrels), undefined, 2), options.outFile);
56
+ }
@@ -37,7 +37,7 @@ export const MODEL_DOCS_VALUE_FLAGS: readonly string[] = MODEL_DOCS_FLAGS;
37
37
 
38
38
  /** The `--help` text, as data, held to {@link MODEL_DOCS_FLAGS} by a test. */
39
39
  export const MODEL_DOCS_HELP: readonly string[] = [
40
- 'Usage: hydranium-cli model-docs --services <module> [--import <specifier>]... [--out-file <file>] [--log-level <lvl>] [--log-file <file>] [--log-file-level <lvl>]',
40
+ 'Usage: hydranium-cli model-docs [--services <module>] [--import <specifier>]... [--out-file <file>] [--log-level <lvl>] [--log-file <file>] [--log-file-level <lvl>]',
41
41
  '',
42
42
  'Generate a navigable Markdown reference of every AST node type — a type index,',
43
43
  'cross-linked super/sub types, a reverse "referenced by" index, and a per-language',
@@ -47,7 +47,7 @@ export const MODEL_DOCS_HELP: readonly string[] = [
47
47
  'zero-arg `createServices(): { shared }` thunk. Needs @hydranium/core.',
48
48
  '',
49
49
  'Options:',
50
- ' --services <module> ESM module exporting `createServices(): { shared }` (required).',
50
+ ' --services <module> ESM module exporting `createServices(): { shared }` (required) unless package.json sets hydranium.services.',
51
51
  ...importHelpLines(22),
52
52
  ' --out-file <file> Write the Markdown to this file instead of stdout. Written',
53
53
  ' only once the report exists, unlike a shell redirection,',
@@ -38,7 +38,7 @@ export const REFLECT_VALUE_FLAGS: readonly string[] = [...HARNESS_VALUE_FLAGS, .
38
38
 
39
39
  /** The `--help` text, as data, held to {@link REFLECT_FLAGS} by a test. */
40
40
  export const REFLECT_HELP: readonly string[] = [
41
- 'Usage: hydranium-cli reflect --services <module> [--import <specifier>]... [--json] [--out-file <file>] [--log-level <lvl>] [--log-file <file>] [--log-file-level <lvl>]',
41
+ 'Usage: hydranium-cli reflect [--services <module>] [--import <specifier>]... [--json] [--out-file <file>] [--log-level <lvl>] [--log-file <file>] [--log-file-level <lvl>]',
42
42
  '',
43
43
  "Dump a head's grammar/AST reflection — the type hierarchy, each language's",
44
44
  'terminals and entry rule, and every cross-reference target. Read-only: no',
@@ -47,7 +47,7 @@ export const REFLECT_HELP: readonly string[] = [
47
47
  'exporting a zero-arg `createServices(): { shared }` thunk. Needs @hydranium/core.',
48
48
  '',
49
49
  'Options:',
50
- ' --services <module> ESM module exporting `createServices(): { shared }` (required).',
50
+ ' --services <module> ESM module exporting `createServices(): { shared }` (required) unless package.json sets hydranium.services.',
51
51
  ...importHelpLines(22),
52
52
  ' --json Emit the raw JSON reflection instead of the Markdown report.',
53
53
  ' --out-file <file> Write the report to this file instead of stdout. Written',
@@ -38,7 +38,7 @@ export const VALIDATE_VALUE_FLAGS: readonly string[] = [...HARNESS_VALUE_FLAGS,
38
38
 
39
39
  /** The `--help` text, as data, held to {@link VALIDATE_FLAGS} by a test. */
40
40
  export const VALIDATE_HELP: readonly string[] = [
41
- 'Usage: hydranium-cli validate --services <module> [--import <specifier>]... <workspace> [--strict] [--json] [--out-file <file>] [--log-level <lvl>] [--log-file <file>] [--log-file-level <lvl>]',
41
+ 'Usage: hydranium-cli validate [--services <module>] [--import <specifier>]... <workspace> [--strict] [--json] [--out-file <file>] [--log-level <lvl>] [--log-file <file>] [--log-file-level <lvl>]',
42
42
  '',
43
43
  'Build a workspace headlessly and report its validation diagnostics — a CI gate:',
44
44
  'the process exits non-zero when any error is found. `<module>` is an ESM module',
@@ -46,7 +46,7 @@ export const VALIDATE_HELP: readonly string[] = [
46
46
  'filesystem inside). Needs @hydranium/core.',
47
47
  '',
48
48
  'Options:',
49
- ' --services <module> ESM module exporting `createServices(): { shared }` (required).',
49
+ ' --services <module> ESM module exporting `createServices(): { shared }` (required) unless package.json sets hydranium.services.',
50
50
  ...importHelpLines(22),
51
51
  ' <workspace> Workspace root (path or file URI) to validate (required).',
52
52
  ' --strict Also fail (non-zero exit) on warnings, not only errors.',
package/src/index.ts CHANGED
@@ -17,3 +17,4 @@ export * from './commands/save.js';
17
17
  export * from './commands/watch.js';
18
18
  export * from './package-name.js';
19
19
  export * from './spawn-data-server.js';
20
+ export * from './commands/message-catalogue.js';