@maykonpaulo/maestro-cli 0.2.0 → 0.2.1-next.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.
@@ -162,8 +162,8 @@ Recommended flow:
162
162
  3. Load it back: loadDeclarativeConfigFromFile('./maestro.config.yaml', { yamlParser })
163
163
  4. Pass the result to createMaestro({ declarations })`;
164
164
  function assertGeneratorInput(value, sourcePath) {
165
- const isObject2 = typeof value === "object" && value !== null && !Array.isArray(value);
166
- const hasEntities = isObject2 && Array.isArray(value["entities"]);
165
+ const isObject = typeof value === "object" && value !== null && !Array.isArray(value);
166
+ const hasEntities = isObject && Array.isArray(value["entities"]);
167
167
  if (!hasEntities) {
168
168
  throw new Error(`'${sourcePath}' must be a JSON object with an "entities" array.`);
169
169
  }
@@ -1011,78 +1011,22 @@ function parseIntrospectArgs(argv) {
1011
1011
  }
1012
1012
 
1013
1013
  // src/commands/introspect/buildIntrospection.ts
1014
+ import {
1015
+ validateIntrospectionResult as coreValidateIntrospectionResult,
1016
+ normalizeIntrospectionResult
1017
+ } from "@maykonpaulo/maestro-core";
1014
1018
  var INTROSPECTION_SCHEMA_VERSION = 1;
1015
1019
  var INTROSPECTION_KIND = "maestro.introspection";
1016
- function isObject(value) {
1017
- return value !== null && typeof value === "object" && !Array.isArray(value);
1018
- }
1019
- function nonEmptyString(value) {
1020
- return typeof value === "string" && value.length > 0;
1021
- }
1022
- function validateEndpoint(endpoint, path) {
1023
- if (!isObject(endpoint)) return `${path} must be an object with "table" and "field".`;
1024
- if (!nonEmptyString(endpoint["table"])) return `${path}.table must be a non-empty string.`;
1025
- if (!nonEmptyString(endpoint["field"])) return `${path}.field must be a non-empty string.`;
1026
- return void 0;
1027
- }
1028
1020
  function validateIntrospectionResult(value) {
1029
- if (!isObject(value)) {
1030
- return { ok: false, error: 'input must be a JSON object with "entities" and "relations" arrays.' };
1031
- }
1032
- if (!Array.isArray(value["entities"])) {
1033
- return { ok: false, error: '"entities" must be an array.' };
1034
- }
1035
- if (!Array.isArray(value["relations"])) {
1036
- return { ok: false, error: '"relations" must be an array.' };
1037
- }
1038
- const entities = value["entities"];
1039
- for (let i = 0; i < entities.length; i++) {
1040
- const entity = entities[i];
1041
- if (!isObject(entity)) return { ok: false, error: `entities[${i}] must be an object.` };
1042
- if (!nonEmptyString(entity["table"])) {
1043
- return { ok: false, error: `entities[${i}].table must be a non-empty string.` };
1044
- }
1045
- if (!Array.isArray(entity["fields"])) {
1046
- return { ok: false, error: `entities[${i}].fields must be an array.` };
1047
- }
1048
- const fields = entity["fields"];
1049
- for (let j = 0; j < fields.length; j++) {
1050
- const field = fields[j];
1051
- const at = `entities[${i}].fields[${j}]`;
1052
- if (!isObject(field)) return { ok: false, error: `${at} must be an object.` };
1053
- if (!nonEmptyString(field["name"])) return { ok: false, error: `${at}.name must be a non-empty string.` };
1054
- if (typeof field["nativeType"] !== "string") return { ok: false, error: `${at}.nativeType must be a string.` };
1055
- if (typeof field["type"] !== "string") return { ok: false, error: `${at}.type must be a string.` };
1056
- if (typeof field["nullable"] !== "boolean") return { ok: false, error: `${at}.nullable must be a boolean.` };
1057
- if (typeof field["isPrimaryKey"] !== "boolean") {
1058
- return { ok: false, error: `${at}.isPrimaryKey must be a boolean.` };
1059
- }
1060
- }
1061
- }
1062
- const relations = value["relations"];
1063
- for (let i = 0; i < relations.length; i++) {
1064
- const relation = relations[i];
1065
- const at = `relations[${i}]`;
1066
- if (!isObject(relation)) return { ok: false, error: `${at} must be an object.` };
1067
- if (!nonEmptyString(relation["id"])) return { ok: false, error: `${at}.id must be a non-empty string.` };
1068
- if (typeof relation["type"] !== "string") return { ok: false, error: `${at}.type must be a string.` };
1069
- const fromError = validateEndpoint(relation["from"], `${at}.from`);
1070
- if (fromError) return { ok: false, error: fromError };
1071
- const toError = validateEndpoint(relation["to"], `${at}.to`);
1072
- if (toError) return { ok: false, error: toError };
1073
- if (relation["confidence"] !== "definite" && relation["confidence"] !== "inferred") {
1074
- return { ok: false, error: `${at}.confidence must be "definite" or "inferred".` };
1075
- }
1021
+ const result = coreValidateIntrospectionResult(value);
1022
+ if (!result.valid) {
1023
+ const error = result.issues.map((issue) => issue.path ? `${issue.path}: ${issue.message}` : issue.message).join("; ");
1024
+ return { ok: false, error };
1076
1025
  }
1077
1026
  return { ok: true, value };
1078
1027
  }
1079
- function compareStrings2(a, b) {
1080
- return a < b ? -1 : a > b ? 1 : 0;
1081
- }
1082
1028
  function canonicalizeResult(result) {
1083
- const entities = [...result.entities].sort((a, b) => compareStrings2(a.table, b.table));
1084
- const relations = [...result.relations].sort((a, b) => compareStrings2(a.id, b.id));
1085
- return { entities, relations };
1029
+ return normalizeIntrospectionResult(result);
1086
1030
  }
1087
1031
  function sortKeys2(value) {
1088
1032
  if (Array.isArray(value)) return value.map(sortKeys2);
@@ -1306,4 +1250,4 @@ export {
1306
1250
  defaultRegistry,
1307
1251
  runCli
1308
1252
  };
1309
- //# sourceMappingURL=chunk-CSDLIL7L.js.map
1253
+ //# sourceMappingURL=chunk-IZKOQGEL.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/commands/registry.ts","../src/commands/planned.ts","../src/parseArgs.ts","../src/help.ts","../src/version.ts","../src/commands/generate/parseGenerateArgs.ts","../src/commands/generate/GenerateCommand.ts","../src/commands/validate/parseValidateArgs.ts","../src/commands/validate/ValidateCommand.ts","../src/commands/diff/parseDiffArgs.ts","../src/commands/diff/diffDeclarativeConfigs.ts","../src/commands/diff/DiffCommand.ts","../src/commands/snapshot/parseSnapshotArgs.ts","../src/commands/snapshot/buildDeclarativeSnapshot.ts","../src/commands/snapshot/SnapshotCommand.ts","../src/commands/introspect/parseIntrospectArgs.ts","../src/commands/introspect/buildIntrospection.ts","../src/commands/introspect/IntrospectCommand.ts","../src/runCli.ts"],"sourcesContent":["import type { Command } from './Command.js';\n\nexport class CommandRegistry {\n private readonly commands = new Map<string, Command>();\n\n register(command: Command): void {\n if (this.commands.has(command.name)) {\n throw new Error(`Command '${command.name}' is already registered.`);\n }\n this.commands.set(command.name, command);\n }\n\n get(name: string): Command | undefined {\n return this.commands.get(name);\n }\n\n list(): Command[] {\n return [...this.commands.values()];\n }\n}\n","export interface PlannedCommand {\n name: string;\n description: string;\n}\n\n/**\n * Commands planned for future phases. Listed in `--help` output for discoverability only —\n * none of these are wired to the registry or execute any real logic yet.\n * `generate`, `validate`, `diff`, `snapshot` and `introspect` are no longer here — they're implemented\n * and registered. Real-datasource connectors remain a future phase but have no CLI surface yet.\n */\nexport const PLANNED_COMMANDS: PlannedCommand[] = [];\n","export interface ParsedArgs {\n command?: string;\n /** Remaining args for the command, or the full argv when there is no command (e.g. bare --help). */\n args: string[];\n help: boolean;\n version: boolean;\n}\n\n/**\n * Minimal argument parser: detects the global --help/-h and --version/-v flags anywhere in argv,\n * and treats the first non-flag argument as the command name. Deliberately simple — a dedicated\n * parsing library isn't justified for a single command slot plus two global flags.\n */\nexport function parseArgs(argv: string[]): ParsedArgs {\n const help = argv.includes('--help') || argv.includes('-h');\n const version = argv.includes('--version') || argv.includes('-v');\n const [first, ...rest] = argv;\n const hasCommand = first !== undefined && !first.startsWith('-');\n\n return {\n command: hasCommand ? first : undefined,\n args: hasCommand ? rest : argv,\n help,\n version,\n };\n}\n","import type { CommandRegistry } from './commands/registry.js';\nimport { PLANNED_COMMANDS } from './commands/planned.js';\n\nexport function formatHelp(registry: CommandRegistry): string {\n const lines: string[] = [\n 'maestro — Maestro CLI',\n '',\n 'Command-line interface for the Maestro declarative engine.',\n '',\n 'Usage:',\n ' maestro <command> [options]',\n '',\n 'Options:',\n ' -h, --help Show this help message',\n ' -v, --version Show the CLI version',\n '',\n ];\n\n const available = registry.list();\n if (available.length > 0) {\n lines.push('Available commands:');\n for (const command of available) {\n lines.push(` ${command.name.padEnd(12)} ${command.description}`);\n }\n lines.push('');\n }\n\n if (PLANNED_COMMANDS.length > 0) {\n lines.push('Planned commands (not yet implemented):');\n for (const planned of PLANNED_COMMANDS) {\n lines.push(` ${planned.name.padEnd(12)} ${planned.description}`);\n }\n }\n\n return lines.join('\\n');\n}\n","import { createRequire } from 'node:module';\n\nconst require = createRequire(import.meta.url);\n\n/** Reads the CLI's own version from package.json — works from both src/ (via tsx) and dist/ (built), since both sit one level below the package root. */\nexport function getCliVersion(): string {\n const pkg = require('../package.json') as { version: string };\n return pkg.version;\n}\n","export type GenerateInputType = 'metadata' | 'schema';\nexport type GenerateOutputFormat = 'json' | 'yaml';\n\nexport interface GenerateArgs {\n input: string;\n type: GenerateInputType;\n format: GenerateOutputFormat;\n out?: string;\n}\n\nexport type ParseGenerateArgsResult = { ok: true; value: GenerateArgs } | { ok: false; error: string };\n\n/** Parses `--key value` and `--key=value` flags. Boolean-style flags (no value, next token is another flag) resolve to 'true'. */\nfunction parseFlags(argv: string[]): Record<string, string> {\n const flags: Record<string, string> = {};\n for (let i = 0; i < argv.length; i++) {\n const arg = argv[i];\n if (!arg.startsWith('--')) continue;\n\n const eqIndex = arg.indexOf('=');\n if (eqIndex !== -1) {\n flags[arg.slice(2, eqIndex)] = arg.slice(eqIndex + 1);\n continue;\n }\n\n const key = arg.slice(2);\n const next = argv[i + 1];\n if (next !== undefined && !next.startsWith('--')) {\n flags[key] = next;\n i++;\n } else {\n flags[key] = 'true';\n }\n }\n return flags;\n}\n\nexport function parseGenerateArgs(argv: string[]): ParseGenerateArgsResult {\n const flags = parseFlags(argv);\n\n const input = flags['input'];\n if (!input) {\n return { ok: false, error: 'Missing required flag --input <path>.' };\n }\n\n const type = flags['type'];\n if (type !== 'metadata' && type !== 'schema') {\n return {\n ok: false,\n error: `Missing or invalid --type flag. Expected \"metadata\" or \"schema\"${type ? `, got \"${type}\"` : ''}.`,\n };\n }\n\n const format = flags['format'] ?? 'json';\n if (format !== 'json' && format !== 'yaml') {\n return { ok: false, error: `Invalid --format flag. Expected \"json\" or \"yaml\", got \"${format}\".` };\n }\n\n return { ok: true, value: { input, type, format, out: flags['out'] } };\n}\n","import { readFileSync, writeFileSync } from 'node:fs';\nimport * as YAML from 'yaml';\nimport {\n generateDeclarativeConfigFromMetadata,\n generateDeclarativeConfigFromSchema,\n serializeDeclarativeConfig,\n type DeclarativeGeneratorMetadataInput,\n type DeclarativeGeneratorSchemaInput,\n} from '@maykonpaulo/maestro-core';\nimport type { Command, CommandContext } from '../Command.js';\nimport { parseGenerateArgs } from './parseGenerateArgs.js';\n\nexport interface GenerateCommandDeps {\n readFile: (path: string) => string;\n writeFile: (path: string, content: string) => void;\n}\n\nconst defaultDeps: GenerateCommandDeps = {\n readFile: (path) => readFileSync(path, 'utf-8'),\n writeFile: (path, content) => writeFileSync(path, content, 'utf-8'),\n};\n\nfunction errorMessage(error: unknown): string {\n return error instanceof Error ? error.message : String(error);\n}\n\nconst GENERATE_HELP_TEXT = `maestro generate — Generate a declarative config from a local metadata/schema JSON file\n\nReads a local JSON file containing already-built EntityMetadata[] (--type metadata) or\nEntitySchema[] (--type schema) and generates a declarative config (EntityDeclaration[], plus an\noptional default consumer) using the core's Declarative Config Generator. The result is written to\nstdout, or to a file with --out.\n\nThis command does NOT perform introspection, does NOT connect to any database or datasource, and\ndoes NOT create a Maestro engine — it only reads a file, transforms it, and writes text. The input\nmust already be metadata/schema you produced some other way (e.g. via engine.getMetadata(), or a\nhand-written EntitySchema[]). Introspecting a live datasource is a separate, not-yet-implemented\ncommand (\"maestro introspect\").\n\nUsage:\n maestro generate --input <path> --type <metadata|schema> [--format <json|yaml>] [--out <path>]\n\nFlags:\n --input <path> Required. Path to a local JSON file.\n --type <metadata|schema> Required. Whether --input holds EntityMetadata[] or EntitySchema[].\n --format <json|yaml> Optional. Output format. Default: json.\n --out <path> Optional. Write the result to this file instead of stdout.\n\nExamples:\n maestro generate --input ./metadata.json --type metadata --format json\n maestro generate --input ./metadata.json --type metadata --format yaml --out ./maestro.config.yaml\n maestro generate --input ./schema.json --type schema --format json --out ./maestro.config.json\n\nRecommended flow:\n 1. Produce EntityMetadata[] or EntitySchema[] as JSON (e.g. JSON.stringify(engine.getMetadata().entities)).\n 2. maestro generate --input <that file> --type <metadata|schema> --out maestro.config.yaml\n 3. Load it back: loadDeclarativeConfigFromFile('./maestro.config.yaml', { yamlParser })\n 4. Pass the result to createMaestro({ declarations })`;\n\n/** Narrows to the minimal shape both generator inputs share, without validating field-level correctness — that's the core generator's job, not the CLI's. */\nfunction assertGeneratorInput(\n value: unknown,\n sourcePath: string,\n): asserts value is { entities: unknown[]; relations?: unknown[]; operations?: unknown[] } {\n const isObject = typeof value === 'object' && value !== null && !Array.isArray(value);\n const hasEntities = isObject && Array.isArray((value as Record<string, unknown>)['entities']);\n if (!hasEntities) {\n throw new Error(`'${sourcePath}' must be a JSON object with an \"entities\" array.`);\n }\n}\n\n/**\n * `maestro generate` — reads a local JSON file containing EntityMetadata[]/EntitySchema[]\n * (matching DeclarativeGeneratorMetadataInput/DeclarativeGeneratorSchemaInput) and generates a\n * declarative config using the core's Declarative Config Generator. No introspection, no\n * datasource/provider access, no engine is created — this command is a thin CLI wrapper.\n */\nexport function createGenerateCommand(deps: GenerateCommandDeps = defaultDeps): Command {\n return {\n name: 'generate',\n description: 'Generate a declarative config from a local metadata/schema JSON file',\n helpText: GENERATE_HELP_TEXT,\n run(context: CommandContext): number {\n const parsed = parseGenerateArgs(context.argv);\n if (!parsed.ok) {\n context.stderr(`maestro generate: ${parsed.error}`);\n return 1;\n }\n const { input, type, format, out } = parsed.value;\n\n let rawInput: string;\n try {\n rawInput = deps.readFile(input);\n } catch (error) {\n context.stderr(`maestro generate: could not read input file '${input}': ${errorMessage(error)}`);\n return 1;\n }\n\n let parsedInput: unknown;\n try {\n parsedInput = JSON.parse(rawInput);\n } catch (error) {\n context.stderr(`maestro generate: '${input}' is not valid JSON: ${errorMessage(error)}`);\n return 1;\n }\n\n let generated;\n try {\n assertGeneratorInput(parsedInput, input);\n generated =\n type === 'metadata'\n ? generateDeclarativeConfigFromMetadata(parsedInput as unknown as DeclarativeGeneratorMetadataInput)\n : generateDeclarativeConfigFromSchema(parsedInput as unknown as DeclarativeGeneratorSchemaInput);\n } catch (error) {\n context.stderr(`maestro generate: failed to generate declarative config: ${errorMessage(error)}`);\n return 1;\n }\n\n let output: string;\n try {\n output = serializeDeclarativeConfig(generated, {\n format,\n yamlSerializer: format === 'yaml' ? { stringify: (value: unknown) => YAML.stringify(value) } : undefined,\n });\n } catch (error) {\n context.stderr(`maestro generate: ${errorMessage(error)}`);\n return 1;\n }\n\n if (out) {\n try {\n deps.writeFile(out, output);\n } catch (error) {\n context.stderr(`maestro generate: could not write output file '${out}': ${errorMessage(error)}`);\n return 1;\n }\n context.stdout(`Declarative config written to ${out}`);\n } else {\n context.stdout(output);\n }\n\n return 0;\n },\n };\n}\n","export type ValidateFormat = 'json' | 'yaml';\n\nexport interface ValidateArgs {\n input: string;\n /** Explicit format override. When omitted, the command detects it from the file extension. */\n format?: ValidateFormat;\n}\n\nexport type ParseValidateArgsResult = { ok: true; value: ValidateArgs } | { ok: false; error: string };\n\n/** Short flags mapped to their long form before parsing. */\nconst ALIASES: Record<string, string> = { i: 'input' };\n\n/** Parses `--key value`, `--key=value` and short `-i value`. Boolean-style flags (no value) resolve to 'true'. */\nfunction parseFlags(argv: string[]): Record<string, string> {\n const flags: Record<string, string> = {};\n for (let i = 0; i < argv.length; i++) {\n const arg = argv[i];\n const isLong = arg.startsWith('--');\n const isShort = !isLong && arg.startsWith('-') && arg.length > 1;\n if (!isLong && !isShort) continue;\n\n const body = isLong ? arg.slice(2) : arg.slice(1);\n const eqIndex = body.indexOf('=');\n if (eqIndex !== -1) {\n const key = body.slice(0, eqIndex);\n flags[ALIASES[key] ?? key] = body.slice(eqIndex + 1);\n continue;\n }\n\n const key = ALIASES[body] ?? body;\n const next = argv[i + 1];\n if (next !== undefined && !next.startsWith('-')) {\n flags[key] = next;\n i++;\n } else {\n flags[key] = 'true';\n }\n }\n return flags;\n}\n\nexport function parseValidateArgs(argv: string[]): ParseValidateArgsResult {\n const flags = parseFlags(argv);\n\n const input = flags['input'];\n if (!input || input === 'true') {\n return { ok: false, error: 'Missing required flag --input <path> (or -i <path>).' };\n }\n\n const format = flags['format'];\n if (format !== undefined && format !== 'json' && format !== 'yaml') {\n return { ok: false, error: `Invalid --format flag. Expected \"json\" or \"yaml\", got \"${format}\".` };\n }\n\n return { ok: true, value: { input, format: format as ValidateFormat | undefined } };\n}\n","import { readFileSync } from 'node:fs';\nimport { extname } from 'node:path';\nimport * as YAML from 'yaml';\nimport {\n loadDeclarativeConfigFromString,\n type DeclarativeFileFormat,\n} from '@maykonpaulo/maestro-core';\nimport type { Command, CommandContext } from '../Command.js';\nimport { parseValidateArgs, type ValidateFormat } from './parseValidateArgs.js';\n\nexport interface ValidateCommandDeps {\n readFile: (path: string) => string;\n}\n\nconst defaultDeps: ValidateCommandDeps = {\n readFile: (path) => readFileSync(path, 'utf-8'),\n};\n\nfunction errorMessage(error: unknown): string {\n return error instanceof Error ? error.message : String(error);\n}\n\nconst VALIDATE_HELP_TEXT = `maestro validate — Validate a declarative config file (YAML or JSON)\n\nLoads a local declarative config file (maestro.config.yaml/.yml/.json) and validates its structure\nusing the core's Declarative File Loader. Prints a readable summary on success and a readable error\non failure.\n\nThis command does NOT create a Maestro engine (no createMaestro()), does NOT connect to any database,\ndatasource or provider, and does NOT require declared operations to have a real implementation.\nStructural validation of the declarative file is all it does; wiring operations to code and starting\nthe runtime is what createMaestro() does separately.\n\nUsage:\n maestro validate --input <path> [--format <json|yaml>]\n maestro validate -i <path>\n\nFlags:\n --input, -i <path> Required. Path to a local declarative config file (.yaml, .yml or .json).\n --format <json|yaml> Optional. Overrides the format detected from the file extension.\n\nAccepted file formats:\n .json → parsed as JSON\n .yaml, .yml → parsed as YAML\n (other) → pass --format explicitly\n\nWhat is validated:\n - The file parses as JSON/YAML.\n - The top-level shape (optional \"entities\" and \"consumers\" arrays; no unknown keys).\n - Each entity declaration (fields, types, capabilities, operations, relationships, enumOptions).\n - Each consumer declaration against its referenced entity.\n\nWhat is NOT validated:\n - Operation bindings (whether declared operations have a real handler) — that's createMaestro().\n - Datasource/provider connectivity — no database or external system is contacted.\n\nExamples:\n maestro validate --input ./maestro.config.yaml\n maestro validate --input ./maestro.config.json\n maestro validate -i ./maestro.config.yaml\n maestro validate --input ./maestro.config --format yaml`;\n\nconst yamlParser = { parse: (content: string): unknown => YAML.parse(content) };\n\n/** Resolves the declarative file format from an explicit override or the file extension. */\nfunction resolveFormat(\n input: string,\n override: ValidateFormat | undefined,\n): { ok: true; format: DeclarativeFileFormat } | { ok: false; error: string } {\n if (override) return { ok: true, format: override };\n\n const ext = extname(input).toLowerCase();\n if (ext === '.json') return { ok: true, format: 'json' };\n if (ext === '.yaml' || ext === '.yml') return { ok: true, format: 'yaml' };\n\n return {\n ok: false,\n error: `cannot detect format from file extension \"${ext || '(none)'}\" of '${input}'. Supported: .json, .yaml, .yml. Pass --format <json|yaml> to override.`,\n };\n}\n\n/**\n * `maestro validate` — reads a local declarative config file (YAML/JSON) and validates its structure\n * via the core's `loadDeclarativeConfigFromString`. It never calls `createMaestro()`, never connects\n * to a datasource/provider, and never requires operation bindings to exist — it is a thin CLI wrapper\n * over the core's declarative validation.\n */\nexport function createValidateCommand(deps: ValidateCommandDeps = defaultDeps): Command {\n return {\n name: 'validate',\n description: 'Validate a declarative config file (YAML or JSON)',\n helpText: VALIDATE_HELP_TEXT,\n run(context: CommandContext): number {\n const parsed = parseValidateArgs(context.argv);\n if (!parsed.ok) {\n context.stderr(`maestro validate: ${parsed.error}`);\n return 1;\n }\n const { input, format: formatOverride } = parsed.value;\n\n const resolved = resolveFormat(input, formatOverride);\n if (!resolved.ok) {\n context.stderr(`maestro validate: ${resolved.error}`);\n return 1;\n }\n const { format } = resolved;\n\n let content: string;\n try {\n content = deps.readFile(input);\n } catch (error) {\n context.stderr(`maestro validate: could not read input file '${input}': ${errorMessage(error)}`);\n return 1;\n }\n\n let config;\n try {\n config = loadDeclarativeConfigFromString(content, {\n format,\n yamlParser: format === 'yaml' ? yamlParser : undefined,\n source: input,\n });\n } catch (error) {\n context.stderr(`maestro validate: ${errorMessage(error)}`);\n return 1;\n }\n\n context.stdout(`Valid declarative config: ${input}`);\n context.stdout(`Entities: ${config.entities.length}`);\n context.stdout(`Consumers: ${config.consumers?.length ?? 0}`);\n return 0;\n },\n };\n}\n","export type DiffFormat = 'json' | 'yaml';\n\nexport interface DiffArgs {\n from: string;\n to: string;\n /** Explicit format override for the `from` file. Detected from the extension when omitted. */\n fromFormat?: DiffFormat;\n /** Explicit format override for the `to` file. Detected from the extension when omitted. */\n toFormat?: DiffFormat;\n}\n\nexport type ParseDiffArgsResult = { ok: true; value: DiffArgs } | { ok: false; error: string };\n\n/** Short flags mapped to their long form before parsing. */\nconst ALIASES: Record<string, string> = { f: 'from', t: 'to' };\n\n/** Parses `--key value`, `--key=value` and short `-f value`. Boolean-style flags (no value) resolve to 'true'. */\nfunction parseFlags(argv: string[]): Record<string, string> {\n const flags: Record<string, string> = {};\n for (let i = 0; i < argv.length; i++) {\n const arg = argv[i];\n const isLong = arg.startsWith('--');\n const isShort = !isLong && arg.startsWith('-') && arg.length > 1;\n if (!isLong && !isShort) continue;\n\n const body = isLong ? arg.slice(2) : arg.slice(1);\n const eqIndex = body.indexOf('=');\n if (eqIndex !== -1) {\n const key = body.slice(0, eqIndex);\n flags[ALIASES[key] ?? key] = body.slice(eqIndex + 1);\n continue;\n }\n\n const key = ALIASES[body] ?? body;\n const next = argv[i + 1];\n if (next !== undefined && !next.startsWith('-')) {\n flags[key] = next;\n i++;\n } else {\n flags[key] = 'true';\n }\n }\n return flags;\n}\n\nfunction validateFormat(\n value: string | undefined,\n flag: string,\n): { ok: true; value: DiffFormat | undefined } | { ok: false; error: string } {\n if (value === undefined) return { ok: true, value: undefined };\n if (value !== 'json' && value !== 'yaml') {\n return { ok: false, error: `Invalid ${flag} flag. Expected \"json\" or \"yaml\", got \"${value}\".` };\n }\n return { ok: true, value };\n}\n\nexport function parseDiffArgs(argv: string[]): ParseDiffArgsResult {\n const flags = parseFlags(argv);\n\n const from = flags['from'];\n if (!from || from === 'true') {\n return { ok: false, error: 'Missing required flag --from <path> (or -f <path>).' };\n }\n\n const to = flags['to'];\n if (!to || to === 'true') {\n return { ok: false, error: 'Missing required flag --to <path> (or -t <path>).' };\n }\n\n const fromFormat = validateFormat(flags['from-format'], '--from-format');\n if (!fromFormat.ok) return fromFormat;\n\n const toFormat = validateFormat(flags['to-format'], '--to-format');\n if (!toFormat.ok) return toFormat;\n\n return { ok: true, value: { from, to, fromFormat: fromFormat.value, toFormat: toFormat.value } };\n}\n","import type {\n DeclarativeFileConfig,\n EntityDeclaration,\n RelationDeclaration,\n ConsumerDeclaration,\n} from '@maykonpaulo/maestro-core';\n\n/** How a member (entity, field, consumer, …) changed between the two configs. */\nexport type ChangeKind = 'added' | 'removed' | 'changed';\n\n/** A single scalar/leaf property that differs between two objects of the same identity. */\nexport interface LeafChange {\n /** Property name (e.g. `label`, `type`). */\n path: string;\n from: unknown;\n to: unknown;\n}\n\n/** A named group of nested member diffs (e.g. an entity's `fields` or `operations`). */\nexport interface MemberGroup {\n title: string;\n members: MemberDiff[];\n}\n\n/** A diff entry for one identified member (entity, field, operation, relationship, consumer). */\nexport interface MemberDiff {\n name: string;\n kind: ChangeKind;\n /** Leaf-property differences (only for `changed`). */\n leafChanges?: LeafChange[];\n /** Nested member groups (only for `changed` entities). */\n groups?: MemberGroup[];\n}\n\n/** Structured, deterministic diff between two declarative configs. */\nexport interface DeclarativeDiff {\n entities: MemberDiff[];\n consumers: MemberDiff[];\n hasDifferences: boolean;\n}\n\n/**\n * Recursively sorts object keys so two structurally-equal values produce an identical string\n * regardless of the key order in the source files. Used both for equality and for display,\n * which keeps the diff deterministic (RF-016).\n */\nfunction canonicalize(value: unknown): unknown {\n if (Array.isArray(value)) return value.map(canonicalize);\n if (value !== null && typeof value === 'object') {\n const entries = Object.entries(value as Record<string, unknown>)\n .filter(([, v]) => v !== undefined)\n .sort(([a], [b]) => (a < b ? -1 : a > b ? 1 : 0));\n const out: Record<string, unknown> = {};\n for (const [k, v] of entries) out[k] = canonicalize(v);\n return out;\n }\n return value;\n}\n\nfunction canonicalString(value: unknown): string {\n return JSON.stringify(canonicalize(value)) ?? 'undefined';\n}\n\nfunction deepEqual(a: unknown, b: unknown): boolean {\n return canonicalString(a) === canonicalString(b);\n}\n\n/** Sorted union of the keys of two records (either may be undefined). */\nfunction sortedKeyUnion(...records: Array<Record<string, unknown> | undefined>): string[] {\n const keys = new Set<string>();\n for (const record of records) {\n if (record) for (const key of Object.keys(record)) keys.add(key);\n }\n return [...keys].sort((a, b) => (a < b ? -1 : a > b ? 1 : 0));\n}\n\n/** Compares two objects key-by-key (deep), producing one LeafChange per differing property. */\nfunction leafChanges(\n a: Record<string, unknown>,\n b: Record<string, unknown>,\n keys?: string[],\n): LeafChange[] {\n const paths = keys ?? sortedKeyUnion(a, b);\n const changes: LeafChange[] = [];\n for (const path of paths) {\n if (!deepEqual(a[path], b[path])) {\n changes.push({ path, from: a[path], to: b[path] });\n }\n }\n return changes;\n}\n\n/**\n * Diffs two `Record<string, object>` collections (fields or operations) by key. Members present\n * on only one side are `added`/`removed`; members on both sides are `changed` when any leaf differs.\n * Absent leaves become no entry when the objects are equal (deterministic, sorted output).\n */\nfunction diffRecord(\n from: Record<string, unknown> | undefined,\n to: Record<string, unknown> | undefined,\n): MemberDiff[] {\n const result: MemberDiff[] = [];\n for (const name of sortedKeyUnion(from, to)) {\n const a = from?.[name];\n const b = to?.[name];\n if (a === undefined) {\n result.push({ name, kind: 'added' });\n } else if (b === undefined) {\n result.push({ name, kind: 'removed' });\n } else {\n const changes = leafChanges(a as Record<string, unknown>, b as Record<string, unknown>);\n if (changes.length > 0) result.push({ name, kind: 'changed', leafChanges: changes });\n }\n }\n return result;\n}\n\n/**\n * Turns a relationship array into a keyed record so it can be diffed like fields/operations.\n * Keyed by explicit `id`, falling back to `${fromField}->${toEntity}.${toField}` — the tuple that\n * uniquely identifies a declarative relationship when no id is given.\n */\nfunction relationRecord(\n relationships: RelationDeclaration[] | undefined,\n): Record<string, RelationDeclaration> {\n const record: Record<string, RelationDeclaration> = {};\n for (const relation of relationships ?? []) {\n const key = relation.id ?? `${relation.fromField}->${relation.toEntity}.${relation.toField}`;\n record[key] = relation;\n }\n return record;\n}\n\n/** Scalar entity properties compared directly (nested collections are handled separately). */\nconst ENTITY_SCALAR_KEYS = ['label', 'pluralLabel', 'description', 'capabilities'];\n\n/** Consumer projection sections compared directly (identity keys `consumer`/`entity` excluded). */\nconst CONSUMER_KEYS = ['list', 'detail', 'forms', 'actions'];\n\n/** Diffs one entity that exists on both sides. Returns null when nothing changed. */\nfunction diffEntity(a: EntityDeclaration, b: EntityDeclaration): MemberDiff | null {\n const leaf = leafChanges(\n a as unknown as Record<string, unknown>,\n b as unknown as Record<string, unknown>,\n ENTITY_SCALAR_KEYS,\n );\n\n const groups: MemberGroup[] = [];\n const fields = diffRecord(a.fields, b.fields);\n if (fields.length > 0) groups.push({ title: 'fields', members: fields });\n const operations = diffRecord(a.operations, b.operations);\n if (operations.length > 0) groups.push({ title: 'operations', members: operations });\n const relationships = diffRecord(relationRecord(a.relationships), relationRecord(b.relationships));\n if (relationships.length > 0) groups.push({ title: 'relationships', members: relationships });\n\n if (leaf.length === 0 && groups.length === 0) return null;\n return { name: a.entity, kind: 'changed', leafChanges: leaf, groups };\n}\n\n/** Indexes entities by their `entity` identifier. */\nfunction entityIndex(config: DeclarativeFileConfig): Record<string, EntityDeclaration> {\n const index: Record<string, EntityDeclaration> = {};\n for (const entity of config.entities) index[entity.entity] = entity;\n return index;\n}\n\n/**\n * Indexes consumers by a composite `consumer:entity` key. A declarative config may declare the same\n * consumer against multiple entities, so the entity is part of the identity.\n */\nfunction consumerIndex(config: DeclarativeFileConfig): Record<string, ConsumerDeclaration> {\n const index: Record<string, ConsumerDeclaration> = {};\n for (const consumer of config.consumers ?? []) {\n index[`${consumer.consumer}:${consumer.entity}`] = consumer;\n }\n return index;\n}\n\nfunction diffEntities(from: DeclarativeFileConfig, to: DeclarativeFileConfig): MemberDiff[] {\n const a = entityIndex(from);\n const b = entityIndex(to);\n const result: MemberDiff[] = [];\n for (const name of sortedKeyUnion(a, b)) {\n if (a[name] === undefined) {\n result.push({ name, kind: 'added' });\n } else if (b[name] === undefined) {\n result.push({ name, kind: 'removed' });\n } else {\n const changed = diffEntity(a[name], b[name]);\n if (changed) result.push(changed);\n }\n }\n return result;\n}\n\nfunction diffConsumers(from: DeclarativeFileConfig, to: DeclarativeFileConfig): MemberDiff[] {\n const a = consumerIndex(from);\n const b = consumerIndex(to);\n const result: MemberDiff[] = [];\n for (const name of sortedKeyUnion(a, b)) {\n if (a[name] === undefined) {\n result.push({ name, kind: 'added' });\n } else if (b[name] === undefined) {\n result.push({ name, kind: 'removed' });\n } else {\n const changes = leafChanges(\n a[name] as unknown as Record<string, unknown>,\n b[name] as unknown as Record<string, unknown>,\n CONSUMER_KEYS,\n );\n if (changes.length > 0) result.push({ name, kind: 'changed', leafChanges: changes });\n }\n }\n return result;\n}\n\n/**\n * Compares two loaded declarative configs structurally and deterministically. Operates only on the\n * two in-memory configs — no engine, no datasource, no runtime. Entities and consumers are compared\n * by identity; changed entities are further compared across fields, operations and relationships.\n */\nexport function diffDeclarativeConfigs(\n from: DeclarativeFileConfig,\n to: DeclarativeFileConfig,\n): DeclarativeDiff {\n const entities = diffEntities(from, to);\n const consumers = diffConsumers(from, to);\n return { entities, consumers, hasDifferences: entities.length > 0 || consumers.length > 0 };\n}\n\nconst SYMBOL: Record<ChangeKind, string> = { added: '+', removed: '-', changed: '~' };\n\n/** Renders a leaf value for display: strings quoted, objects as canonical JSON, absence as `(unset)`. */\nfunction renderValue(value: unknown): string {\n if (value === undefined) return '(unset)';\n return canonicalString(value);\n}\n\nfunction renderLeafChange(change: LeafChange, indent: string): string {\n return `${indent}${change.path}: ${renderValue(change.from)} → ${renderValue(change.to)}`;\n}\n\nfunction renderMember(member: MemberDiff, indent: string, lines: string[]): void {\n lines.push(`${indent}${SYMBOL[member.kind]} ${member.name}`);\n const childIndent = `${indent} `;\n for (const change of member.leafChanges ?? []) {\n lines.push(renderLeafChange(change, childIndent));\n }\n for (const group of member.groups ?? []) {\n lines.push(`${childIndent}${group.title}:`);\n for (const child of group.members) {\n renderMember(child, `${childIndent} `, lines);\n }\n }\n}\n\n/**\n * Formats a `DeclarativeDiff` as compact, terminal-friendly text. Returns `No differences found.`\n * when the configs are equal, otherwise a `Differences found.` report grouped by Entities/Consumers.\n */\nexport function formatDeclarativeDiff(diff: DeclarativeDiff): string {\n if (!diff.hasDifferences) return 'No differences found.';\n\n const lines: string[] = ['Differences found.'];\n if (diff.entities.length > 0) {\n lines.push('', 'Entities:');\n for (const member of diff.entities) renderMember(member, ' ', lines);\n }\n if (diff.consumers.length > 0) {\n lines.push('', 'Consumers:');\n for (const member of diff.consumers) renderMember(member, ' ', lines);\n }\n return lines.join('\\n');\n}\n","import { readFileSync } from 'node:fs';\nimport { extname } from 'node:path';\nimport * as YAML from 'yaml';\nimport {\n loadDeclarativeConfigFromString,\n type DeclarativeFileConfig,\n type DeclarativeFileFormat,\n} from '@maykonpaulo/maestro-core';\nimport type { Command, CommandContext } from '../Command.js';\nimport { parseDiffArgs, type DiffFormat } from './parseDiffArgs.js';\nimport { diffDeclarativeConfigs, formatDeclarativeDiff } from './diffDeclarativeConfigs.js';\n\nexport interface DiffCommandDeps {\n readFile: (path: string) => string;\n}\n\nconst defaultDeps: DiffCommandDeps = {\n readFile: (path) => readFileSync(path, 'utf-8'),\n};\n\n/** Exit code returned when the two files are valid and differ (RF-018). */\nconst EXIT_DIFFERENCES = 1;\n/** Exit code returned for any usage, read, parse or validation error (RF-018). */\nconst EXIT_ERROR = 2;\n\nfunction errorMessage(error: unknown): string {\n return error instanceof Error ? error.message : String(error);\n}\n\nconst DIFF_HELP_TEXT = `maestro diff — Compare two declarative config files (YAML or JSON)\n\nLoads two local declarative config files (maestro.config.yaml/.yml/.json) with the core's Declarative\nFile Loader, then compares their normalised structures and prints a readable, deterministic report of\nwhat changed. Useful before promoting, reviewing or versioning a config.\n\nThis command does NOT create a Maestro engine (no createMaestro()), does NOT connect to any database,\ndatasource or provider, does NOT execute operations, and does NOT require declared operations to have\na real implementation. It is a read-only, local comparison of two declarative files.\n\nUsage:\n maestro diff --from <path> --to <path> [--from-format <json|yaml>] [--to-format <json|yaml>]\n maestro diff -f <path> -t <path>\n\nFlags:\n --from, -f <path> Required. Path to the baseline declarative config file.\n --to, -t <path> Required. Path to the changed declarative config file.\n --from-format <json|yaml> Optional. Overrides the format detected from the --from extension.\n --to-format <json|yaml> Optional. Overrides the format detected from the --to extension.\n\nAccepted file formats:\n .json → parsed as JSON\n .yaml, .yml → parsed as YAML\n (other) → pass --from-format / --to-format explicitly\n\nWhat is compared:\n - Entities (added / removed / changed): label, pluralLabel, description, capabilities.\n - Entity fields (added / removed / changed): type, label, required, readonly, description,\n enumOptions, relationEntity and any other declarative field property.\n - Entity operations (added / removed / changed) — no handler/implementation required.\n - Entity relationships (added / removed / changed).\n - Consumers (added / removed / changed): list, detail, forms and actions projections.\n\nWhat is NOT compared:\n - Operation bindings or handlers — that's createMaestro(), not diff.\n - Live database/introspection metadata — this diffs declarative files, not a real schema.\n\nExit codes:\n 0 Both files are valid and there are no differences.\n 1 Both files are valid and there are differences.\n 2 Usage, file-read, parse or validation error.\n\nExamples:\n maestro diff --from ./maestro.config.old.yaml --to ./maestro.config.new.yaml\n maestro diff -f ./before.json -t ./after.json\n maestro diff --from ./before.config --from-format yaml --to ./after.config --to-format yaml`;\n\nconst yamlParser = { parse: (content: string): unknown => YAML.parse(content) };\n\n/** Resolves a declarative file format from an explicit override or the file extension. */\nfunction resolveFormat(\n path: string,\n override: DiffFormat | undefined,\n flag: string,\n): { ok: true; format: DeclarativeFileFormat } | { ok: false; error: string } {\n if (override) return { ok: true, format: override };\n\n const ext = extname(path).toLowerCase();\n if (ext === '.json') return { ok: true, format: 'json' };\n if (ext === '.yaml' || ext === '.yml') return { ok: true, format: 'yaml' };\n\n return {\n ok: false,\n error: `cannot detect format from file extension \"${ext || '(none)'}\" of '${path}'. Supported: .json, .yaml, .yml. Pass ${flag} <json|yaml> to override.`,\n };\n}\n\n/** Reads and loads a declarative config file, returning a readable error result instead of throwing. */\nfunction loadConfig(\n deps: DiffCommandDeps,\n path: string,\n format: DeclarativeFileFormat,\n): { ok: true; config: DeclarativeFileConfig } | { ok: false; error: string } {\n let content: string;\n try {\n content = deps.readFile(path);\n } catch (error) {\n return { ok: false, error: `could not read file '${path}': ${errorMessage(error)}` };\n }\n\n try {\n const config = loadDeclarativeConfigFromString(content, {\n format,\n yamlParser: format === 'yaml' ? yamlParser : undefined,\n source: path,\n });\n return { ok: true, config };\n } catch (error) {\n return { ok: false, error: errorMessage(error) };\n }\n}\n\n/**\n * `maestro diff` — reads two local declarative config files (YAML/JSON), validates each via the\n * core's `loadDeclarativeConfigFromString`, then structurally compares them. It never calls\n * `createMaestro()`, never connects to a datasource/provider, never executes operations, and never\n * requires operation bindings to exist. Read-only. Exit codes: 0 = no diff, 1 = diff, 2 = error.\n */\nexport function createDiffCommand(deps: DiffCommandDeps = defaultDeps): Command {\n return {\n name: 'diff',\n description: 'Compare two declarative config files (YAML or JSON)',\n helpText: DIFF_HELP_TEXT,\n run(context: CommandContext): number {\n const parsed = parseDiffArgs(context.argv);\n if (!parsed.ok) {\n context.stderr(`maestro diff: ${parsed.error}`);\n return EXIT_ERROR;\n }\n const { from, to, fromFormat, toFormat } = parsed.value;\n\n const fromResolved = resolveFormat(from, fromFormat, '--from-format');\n if (!fromResolved.ok) {\n context.stderr(`maestro diff: ${fromResolved.error}`);\n return EXIT_ERROR;\n }\n const toResolved = resolveFormat(to, toFormat, '--to-format');\n if (!toResolved.ok) {\n context.stderr(`maestro diff: ${toResolved.error}`);\n return EXIT_ERROR;\n }\n\n const fromConfig = loadConfig(deps, from, fromResolved.format);\n if (!fromConfig.ok) {\n context.stderr(`maestro diff: ${fromConfig.error}`);\n return EXIT_ERROR;\n }\n const toConfig = loadConfig(deps, to, toResolved.format);\n if (!toConfig.ok) {\n context.stderr(`maestro diff: ${toConfig.error}`);\n return EXIT_ERROR;\n }\n\n const diff = diffDeclarativeConfigs(fromConfig.config, toConfig.config);\n context.stdout(formatDeclarativeDiff(diff));\n return diff.hasDifferences ? EXIT_DIFFERENCES : 0;\n },\n };\n}\n","export type SnapshotInputFormat = 'json' | 'yaml';\nexport type SnapshotOutputFormat = 'json';\n\nexport interface SnapshotArgs {\n input: string;\n /** Explicit input format override. Detected from the file extension when omitted. */\n inputFormat?: SnapshotInputFormat;\n /** Output file path. When omitted, the snapshot is written to stdout. */\n out?: string;\n /** Snapshot output format. Only `json` is supported for now. */\n format: SnapshotOutputFormat;\n}\n\nexport type ParseSnapshotArgsResult =\n | { ok: true; value: SnapshotArgs }\n | { ok: false; error: string };\n\n/** Short flags mapped to their long form before parsing. */\nconst ALIASES: Record<string, string> = { i: 'input' };\n\n/** Parses `--key value`, `--key=value` and short `-i value`. Boolean-style flags (no value) resolve to 'true'. */\nfunction parseFlags(argv: string[]): Record<string, string> {\n const flags: Record<string, string> = {};\n for (let i = 0; i < argv.length; i++) {\n const arg = argv[i];\n const isLong = arg.startsWith('--');\n const isShort = !isLong && arg.startsWith('-') && arg.length > 1;\n if (!isLong && !isShort) continue;\n\n const body = isLong ? arg.slice(2) : arg.slice(1);\n const eqIndex = body.indexOf('=');\n if (eqIndex !== -1) {\n const key = body.slice(0, eqIndex);\n flags[ALIASES[key] ?? key] = body.slice(eqIndex + 1);\n continue;\n }\n\n const key = ALIASES[body] ?? body;\n const next = argv[i + 1];\n if (next !== undefined && !next.startsWith('-')) {\n flags[key] = next;\n i++;\n } else {\n flags[key] = 'true';\n }\n }\n return flags;\n}\n\nfunction validateInputFormat(\n value: string | undefined,\n): { ok: true; value: SnapshotInputFormat | undefined } | { ok: false; error: string } {\n if (value === undefined) return { ok: true, value: undefined };\n if (value !== 'json' && value !== 'yaml') {\n return {\n ok: false,\n error: `Invalid --input-format flag. Expected \"json\" or \"yaml\", got \"${value}\".`,\n };\n }\n return { ok: true, value };\n}\n\nfunction validateOutputFormat(\n value: string | undefined,\n): { ok: true; value: SnapshotOutputFormat } | { ok: false; error: string } {\n if (value === undefined) return { ok: true, value: 'json' };\n if (value !== 'json') {\n return { ok: false, error: `Invalid --format flag. Expected \"json\", got \"${value}\".` };\n }\n return { ok: true, value };\n}\n\nexport function parseSnapshotArgs(argv: string[]): ParseSnapshotArgsResult {\n const flags = parseFlags(argv);\n\n const input = flags['input'];\n if (!input || input === 'true') {\n return { ok: false, error: 'Missing required flag --input <path> (or -i <path>).' };\n }\n\n const inputFormat = validateInputFormat(flags['input-format']);\n if (!inputFormat.ok) return inputFormat;\n\n const format = validateOutputFormat(flags['format']);\n if (!format.ok) return format;\n\n const out = flags['out'] && flags['out'] !== 'true' ? flags['out'] : undefined;\n\n return {\n ok: true,\n value: { input, inputFormat: inputFormat.value, out, format: format.value },\n };\n}\n","import type {\n DeclarativeFileConfig,\n DeclarativeFileFormat,\n EntityDeclaration,\n ConsumerDeclaration,\n RelationDeclaration,\n} from '@maykonpaulo/maestro-core';\n\n/** Bumped only when the snapshot structure changes in a backwards-incompatible way. */\nexport const SNAPSHOT_SCHEMA_VERSION = 1;\nexport const SNAPSHOT_KIND = 'maestro.declarative.snapshot';\n\nexport interface SnapshotSource {\n /** Path exactly as passed on the command line — never resolved to an absolute path (determinism). */\n path: string;\n format: DeclarativeFileFormat;\n}\n\nexport interface SnapshotSummary {\n entities: number;\n consumers: number;\n relations: number;\n}\n\n/** A relationship flattened out of its owning entity, tagged with the entity it belongs to. */\nexport interface SnapshotRelation extends RelationDeclaration {\n /** Identifier of the entity that declares this relationship. */\n fromEntity: string;\n}\n\nexport interface SnapshotDeclarations {\n entities: EntityDeclaration[];\n consumers: ConsumerDeclaration[];\n relations: SnapshotRelation[];\n}\n\nexport interface DeclarativeSnapshot {\n schemaVersion: number;\n kind: string;\n source: SnapshotSource;\n summary: SnapshotSummary;\n declarations: SnapshotDeclarations;\n}\n\n/** Derived, stable identifier for a relationship — mirrors the core's default (`${fromEntity}.${toEntity}`). */\nfunction relationId(fromEntity: string, relation: RelationDeclaration): string {\n return relation.id ?? `${fromEntity}.${relation.toEntity}`;\n}\n\nfunction compareStrings(a: string, b: string): number {\n return a < b ? -1 : a > b ? 1 : 0;\n}\n\n/**\n * Builds a canonical, deterministic snapshot object from an already-loaded (and validated)\n * declarative config. Ordering is stable: entities by `entity`, consumers by `consumer`,\n * relationships (and the flattened relations index) by derived id. Object-key ordering is applied\n * later by {@link serializeSnapshot}. No volatile data (timestamps, absolute paths, hashes).\n */\nexport function buildDeclarativeSnapshot(\n config: DeclarativeFileConfig,\n source: SnapshotSource,\n): DeclarativeSnapshot {\n const entities = [...config.entities]\n .sort((a, b) => compareStrings(a.entity, b.entity))\n .map((entity) => canonicalizeEntity(entity));\n\n const consumers = [...(config.consumers ?? [])].sort((a, b) =>\n compareStrings(a.consumer, b.consumer),\n );\n\n const relations = entities\n .flatMap((entity) =>\n (entity.relationships ?? []).map(\n (relation): SnapshotRelation => ({ fromEntity: entity.entity, ...relation }),\n ),\n )\n .sort((a, b) => {\n const byId = compareStrings(relationId(a.fromEntity, a), relationId(b.fromEntity, b));\n return byId !== 0 ? byId : compareStrings(a.fromEntity, b.fromEntity);\n });\n\n return {\n schemaVersion: SNAPSHOT_SCHEMA_VERSION,\n kind: SNAPSHOT_KIND,\n source,\n summary: {\n entities: entities.length,\n consumers: consumers.length,\n relations: relations.length,\n },\n declarations: { entities, consumers, relations },\n };\n}\n\n/** Returns the entity with its relationships array sorted by derived id (fields/operations are Records — key order is handled during serialization). */\nfunction canonicalizeEntity(entity: EntityDeclaration): EntityDeclaration {\n if (!entity.relationships || entity.relationships.length === 0) return entity;\n const relationships = [...entity.relationships].sort((a, b) =>\n compareStrings(relationId(entity.entity, a), relationId(entity.entity, b)),\n );\n return { ...entity, relationships };\n}\n\n/** Recursively sorts object keys so equivalent objects serialize identically, regardless of authoring order. Array order is preserved. */\nfunction sortKeys(value: unknown): unknown {\n if (Array.isArray(value)) return value.map(sortKeys);\n if (value !== null && typeof value === 'object') {\n const sorted: Record<string, unknown> = {};\n for (const key of Object.keys(value).sort()) {\n sorted[key] = sortKeys((value as Record<string, unknown>)[key]);\n }\n return sorted;\n }\n return value;\n}\n\n/** Serializes a snapshot to canonical JSON: recursively sorted object keys, 2-space indent, trailing newline. */\nexport function serializeSnapshot(snapshot: DeclarativeSnapshot): string {\n return `${JSON.stringify(sortKeys(snapshot), null, 2)}\\n`;\n}\n","import { readFileSync, writeFileSync } from 'node:fs';\nimport { extname } from 'node:path';\nimport * as YAML from 'yaml';\nimport {\n loadDeclarativeConfigFromString,\n type DeclarativeFileConfig,\n type DeclarativeFileFormat,\n} from '@maykonpaulo/maestro-core';\nimport type { Command, CommandContext } from '../Command.js';\nimport { parseSnapshotArgs, type SnapshotInputFormat } from './parseSnapshotArgs.js';\nimport { buildDeclarativeSnapshot, serializeSnapshot } from './buildDeclarativeSnapshot.js';\n\nexport interface SnapshotCommandDeps {\n readFile: (path: string) => string;\n writeFile: (path: string, content: string) => void;\n}\n\nconst defaultDeps: SnapshotCommandDeps = {\n readFile: (path) => readFileSync(path, 'utf-8'),\n writeFile: (path, content) => writeFileSync(path, content, 'utf-8'),\n};\n\nfunction errorMessage(error: unknown): string {\n return error instanceof Error ? error.message : String(error);\n}\n\nconst SNAPSHOT_HELP_TEXT = `maestro snapshot — Produce a canonical, deterministic snapshot of a declarative config file\n\nLoads a local declarative config file (maestro.config.yaml/.yml/.json) with the core's Declarative\nFile Loader, validates it, then emits a canonical JSON snapshot of its declarations. The snapshot is a\nstable, versionable artifact for auditing, PR review and future comparison — the same (semantically\nequivalent) input always produces byte-identical output.\n\nThis command does NOT create a Maestro engine (no createMaestro()), does NOT connect to any database,\ndatasource or provider, does NOT execute operations, and does NOT require declared operations to have\na real implementation. It is a read-only, local, declarative snapshot — NOT a snapshot of a live\ndatabase or of runtime introspection.\n\nUsage:\n maestro snapshot --input <path> [--input-format <json|yaml>] [--format json] [--out <path>]\n maestro snapshot -i <path>\n\nFlags:\n --input, -i <path> Required. Path to a local declarative config file (.yaml, .yml or .json).\n --input-format <json|yaml> Optional. Overrides the format detected from the --input extension.\n --format json Optional. Snapshot output format. Only \"json\" is supported. Default: json.\n --out <path> Optional. Write the snapshot to this file instead of stdout.\n\nAccepted input formats:\n .json → parsed as JSON\n .yaml, .yml → parsed as YAML\n (other) → pass --input-format <json|yaml> explicitly\n\nSnapshot format (JSON):\n {\n \"schemaVersion\": 1,\n \"kind\": \"maestro.declarative.snapshot\",\n \"source\": { \"path\": \"<the --input value>\", \"format\": \"yaml\" },\n \"summary\": { \"entities\": N, \"consumers\": N, \"relations\": N },\n \"declarations\": { \"entities\": [...], \"consumers\": [...], \"relations\": [...] }\n }\n\nWhat is included:\n - Every declared entity (fields, capabilities, operations, relationships), consumer and relationship.\n - A flattened \"relations\" index of all entity relationships, each tagged with its \"fromEntity\".\n - Stable ordering (entities/consumers/relations sorted; object keys sorted) for deterministic output.\n\nWhat is NOT included:\n - Timestamps, absolute paths, hashes or any value that varies between runs of the same input.\n - Operation bindings/handlers, live database or runtime introspection data.\n\nExit codes:\n 0 The file is valid and the snapshot was produced.\n 1 Usage, file-read, parse, validation or write error.\n\nExamples:\n maestro snapshot --input ./maestro.config.yaml\n maestro snapshot -i ./maestro.config.json\n maestro snapshot --input ./maestro.config.yaml --out ./maestro.snapshot.json\n maestro snapshot --input ./maestro.config --input-format yaml --out ./maestro.snapshot.json`;\n\nconst yamlParser = { parse: (content: string): unknown => YAML.parse(content) };\n\n/** Resolves the declarative input format from an explicit override or the file extension. */\nfunction resolveFormat(\n input: string,\n override: SnapshotInputFormat | undefined,\n): { ok: true; format: DeclarativeFileFormat } | { ok: false; error: string } {\n if (override) return { ok: true, format: override };\n\n const ext = extname(input).toLowerCase();\n if (ext === '.json') return { ok: true, format: 'json' };\n if (ext === '.yaml' || ext === '.yml') return { ok: true, format: 'yaml' };\n\n return {\n ok: false,\n error: `cannot detect format from file extension \"${ext || '(none)'}\" of '${input}'. Supported: .json, .yaml, .yml. Pass --input-format <json|yaml> to override.`,\n };\n}\n\n/**\n * `maestro snapshot` — reads a local declarative config file (YAML/JSON), validates it via the core's\n * `loadDeclarativeConfigFromString`, then emits a canonical, deterministic JSON snapshot of its\n * declarations. It never calls `createMaestro()`, never connects to a datasource/provider, never\n * executes operations, and never requires operation bindings to exist. Read-only, local, declarative.\n * Exit codes: 0 = snapshot produced, 1 = any error.\n */\nexport function createSnapshotCommand(deps: SnapshotCommandDeps = defaultDeps): Command {\n return {\n name: 'snapshot',\n description: 'Produce a canonical snapshot of a declarative config file (YAML or JSON)',\n helpText: SNAPSHOT_HELP_TEXT,\n run(context: CommandContext): number {\n const parsed = parseSnapshotArgs(context.argv);\n if (!parsed.ok) {\n context.stderr(`maestro snapshot: ${parsed.error}`);\n return 1;\n }\n const { input, inputFormat, out } = parsed.value;\n\n const resolved = resolveFormat(input, inputFormat);\n if (!resolved.ok) {\n context.stderr(`maestro snapshot: ${resolved.error}`);\n return 1;\n }\n const { format } = resolved;\n\n let content: string;\n try {\n content = deps.readFile(input);\n } catch (error) {\n context.stderr(`maestro snapshot: could not read input file '${input}': ${errorMessage(error)}`);\n return 1;\n }\n\n let config: DeclarativeFileConfig;\n try {\n config = loadDeclarativeConfigFromString(content, {\n format,\n yamlParser: format === 'yaml' ? yamlParser : undefined,\n source: input,\n });\n } catch (error) {\n context.stderr(`maestro snapshot: ${errorMessage(error)}`);\n return 1;\n }\n\n const snapshot = buildDeclarativeSnapshot(config, { path: input, format });\n const output = serializeSnapshot(snapshot);\n\n if (out) {\n try {\n deps.writeFile(out, output);\n } catch (error) {\n context.stderr(`maestro snapshot: could not write output file '${out}': ${errorMessage(error)}`);\n return 1;\n }\n context.stdout(`Snapshot written: ${out}`);\n context.stdout(`Entities: ${snapshot.summary.entities}`);\n context.stdout(`Consumers: ${snapshot.summary.consumers}`);\n context.stdout(`Relations: ${snapshot.summary.relations}`);\n } else {\n context.stdout(output.replace(/\\n$/, ''));\n }\n\n return 0;\n },\n };\n}\n","export interface IntrospectArgs {\n /** Path to the local IntrospectionResult JSON file. */\n input: string;\n /** Output file path. When omitted, the canonical JSON is written to stdout. */\n out?: string;\n}\n\nexport type ParseIntrospectArgsResult =\n | { ok: true; value: IntrospectArgs }\n | { ok: false; error: string };\n\n/** Short flags mapped to their long form before parsing. */\nconst ALIASES: Record<string, string> = { i: 'input' };\n\n/** Parses `--key value`, `--key=value` and short `-i value`. Boolean-style flags (no value) resolve to 'true'. */\nfunction parseFlags(argv: string[]): Record<string, string> {\n const flags: Record<string, string> = {};\n for (let i = 0; i < argv.length; i++) {\n const arg = argv[i];\n const isLong = arg.startsWith('--');\n const isShort = !isLong && arg.startsWith('-') && arg.length > 1;\n if (!isLong && !isShort) continue;\n\n const body = isLong ? arg.slice(2) : arg.slice(1);\n const eqIndex = body.indexOf('=');\n if (eqIndex !== -1) {\n const key = body.slice(0, eqIndex);\n flags[ALIASES[key] ?? key] = body.slice(eqIndex + 1);\n continue;\n }\n\n const key = ALIASES[body] ?? body;\n const next = argv[i + 1];\n if (next !== undefined && !next.startsWith('-')) {\n flags[key] = next;\n i++;\n } else {\n flags[key] = 'true';\n }\n }\n return flags;\n}\n\nexport function parseIntrospectArgs(argv: string[]): ParseIntrospectArgsResult {\n const flags = parseFlags(argv);\n\n const input = flags['input'];\n if (!input || input === 'true') {\n return { ok: false, error: 'Missing required flag --input <path> (or -i <path>).' };\n }\n\n const out = flags['out'] && flags['out'] !== 'true' ? flags['out'] : undefined;\n\n return { ok: true, value: { input, out } };\n}\n","import type { IntrospectionResult } from '@maykonpaulo/maestro-core';\n\n/** Bumped only when the artifact structure changes in a backwards-incompatible way. */\nexport const INTROSPECTION_SCHEMA_VERSION = 1;\nexport const INTROSPECTION_KIND = 'maestro.introspection';\n\nexport interface IntrospectionSource {\n /** Path exactly as passed on the command line — never resolved to an absolute path (determinism). */\n path: string;\n}\n\nexport interface IntrospectionSummary {\n entities: number;\n relations: number;\n}\n\n/**\n * CLI-level artifact wrapping a validated, canonicalized `IntrospectionResult`. The `result` payload\n * is the core's real `IntrospectionResult` shape — this envelope adds only versioning, a summary and\n * the source path, exactly like the declarative snapshot artifact does for declarative configs.\n */\nexport interface IntrospectionArtifact {\n schemaVersion: number;\n kind: string;\n source: IntrospectionSource;\n summary: IntrospectionSummary;\n result: IntrospectionResult;\n}\n\nexport type ValidateIntrospectionResult =\n | { ok: true; value: IntrospectionResult }\n | { ok: false; error: string };\n\nfunction isObject(value: unknown): value is Record<string, unknown> {\n return value !== null && typeof value === 'object' && !Array.isArray(value);\n}\n\nfunction nonEmptyString(value: unknown): value is string {\n return typeof value === 'string' && value.length > 0;\n}\n\n/** Validates one `{ table, field }` endpoint of a relation. */\nfunction validateEndpoint(endpoint: unknown, path: string): string | undefined {\n if (!isObject(endpoint)) return `${path} must be an object with \"table\" and \"field\".`;\n if (!nonEmptyString(endpoint['table'])) return `${path}.table must be a non-empty string.`;\n if (!nonEmptyString(endpoint['field'])) return `${path}.field must be a non-empty string.`;\n return undefined;\n}\n\n/**\n * Validates that a parsed JSON value matches the core's `IntrospectionResult` contract closely enough\n * to be safely consumed downstream. Only the required (non-optional) fields of the core types are\n * enforced; optional derived flags (isUnique, candidateForSearch, …) are passed through untouched.\n * This is a local, minimal wrapper — the core exposes no public `IntrospectionResult` validator yet.\n */\nexport function validateIntrospectionResult(value: unknown): ValidateIntrospectionResult {\n if (!isObject(value)) {\n return { ok: false, error: 'input must be a JSON object with \"entities\" and \"relations\" arrays.' };\n }\n\n if (!Array.isArray(value['entities'])) {\n return { ok: false, error: '\"entities\" must be an array.' };\n }\n if (!Array.isArray(value['relations'])) {\n return { ok: false, error: '\"relations\" must be an array.' };\n }\n\n const entities = value['entities'] as unknown[];\n for (let i = 0; i < entities.length; i++) {\n const entity = entities[i];\n if (!isObject(entity)) return { ok: false, error: `entities[${i}] must be an object.` };\n if (!nonEmptyString(entity['table'])) {\n return { ok: false, error: `entities[${i}].table must be a non-empty string.` };\n }\n if (!Array.isArray(entity['fields'])) {\n return { ok: false, error: `entities[${i}].fields must be an array.` };\n }\n const fields = entity['fields'] as unknown[];\n for (let j = 0; j < fields.length; j++) {\n const field = fields[j];\n const at = `entities[${i}].fields[${j}]`;\n if (!isObject(field)) return { ok: false, error: `${at} must be an object.` };\n if (!nonEmptyString(field['name'])) return { ok: false, error: `${at}.name must be a non-empty string.` };\n if (typeof field['nativeType'] !== 'string') return { ok: false, error: `${at}.nativeType must be a string.` };\n if (typeof field['type'] !== 'string') return { ok: false, error: `${at}.type must be a string.` };\n if (typeof field['nullable'] !== 'boolean') return { ok: false, error: `${at}.nullable must be a boolean.` };\n if (typeof field['isPrimaryKey'] !== 'boolean') {\n return { ok: false, error: `${at}.isPrimaryKey must be a boolean.` };\n }\n }\n }\n\n const relations = value['relations'] as unknown[];\n for (let i = 0; i < relations.length; i++) {\n const relation = relations[i];\n const at = `relations[${i}]`;\n if (!isObject(relation)) return { ok: false, error: `${at} must be an object.` };\n if (!nonEmptyString(relation['id'])) return { ok: false, error: `${at}.id must be a non-empty string.` };\n if (typeof relation['type'] !== 'string') return { ok: false, error: `${at}.type must be a string.` };\n const fromError = validateEndpoint(relation['from'], `${at}.from`);\n if (fromError) return { ok: false, error: fromError };\n const toError = validateEndpoint(relation['to'], `${at}.to`);\n if (toError) return { ok: false, error: toError };\n if (relation['confidence'] !== 'definite' && relation['confidence'] !== 'inferred') {\n return { ok: false, error: `${at}.confidence must be \"definite\" or \"inferred\".` };\n }\n }\n\n return { ok: true, value: value as unknown as IntrospectionResult };\n}\n\nfunction compareStrings(a: string, b: string): number {\n return a < b ? -1 : a > b ? 1 : 0;\n}\n\n/**\n * Canonicalizes an `IntrospectionResult`: entities sorted by `table`, relations by `id`. Field and\n * index array order is preserved (column order is meaningful); object-key ordering is applied later\n * by {@link serializeIntrospection}.\n */\nfunction canonicalizeResult(result: IntrospectionResult): IntrospectionResult {\n const entities = [...result.entities].sort((a, b) => compareStrings(a.table, b.table));\n const relations = [...result.relations].sort((a, b) => compareStrings(a.id, b.id));\n return { entities, relations };\n}\n\n/** Recursively sorts object keys so equivalent objects serialize identically. Array order is preserved. */\nfunction sortKeys(value: unknown): unknown {\n if (Array.isArray(value)) return value.map(sortKeys);\n if (value !== null && typeof value === 'object') {\n const sorted: Record<string, unknown> = {};\n for (const key of Object.keys(value).sort()) {\n sorted[key] = sortKeys((value as Record<string, unknown>)[key]);\n }\n return sorted;\n }\n return value;\n}\n\n/**\n * Builds a canonical, deterministic introspection artifact from an already-validated result. No\n * volatile data (timestamps, absolute paths, hashes) — the same input always produces the same output.\n */\nexport function buildIntrospectionArtifact(\n result: IntrospectionResult,\n source: IntrospectionSource,\n): IntrospectionArtifact {\n const canonical = canonicalizeResult(result);\n return {\n schemaVersion: INTROSPECTION_SCHEMA_VERSION,\n kind: INTROSPECTION_KIND,\n source,\n summary: {\n entities: canonical.entities.length,\n relations: canonical.relations.length,\n },\n result: canonical,\n };\n}\n\n/** Serializes an artifact to canonical JSON: recursively sorted object keys, 2-space indent, trailing newline. */\nexport function serializeIntrospection(artifact: IntrospectionArtifact): string {\n return `${JSON.stringify(sortKeys(artifact), null, 2)}\\n`;\n}\n","import { readFileSync, writeFileSync } from 'node:fs';\nimport type { Command, CommandContext } from '../Command.js';\nimport { parseIntrospectArgs } from './parseIntrospectArgs.js';\nimport {\n validateIntrospectionResult,\n buildIntrospectionArtifact,\n serializeIntrospection,\n} from './buildIntrospection.js';\n\nexport interface IntrospectCommandDeps {\n readFile: (path: string) => string;\n writeFile: (path: string, content: string) => void;\n}\n\nconst defaultDeps: IntrospectCommandDeps = {\n readFile: (path) => readFileSync(path, 'utf-8'),\n writeFile: (path, content) => writeFileSync(path, content, 'utf-8'),\n};\n\nfunction errorMessage(error: unknown): string {\n return error instanceof Error ? error.message : String(error);\n}\n\nconst INTROSPECT_HELP_TEXT = `maestro introspect — Validate and canonicalize a local IntrospectionResult (offline)\n\nReads a local JSON file describing an IntrospectionResult (the core's introspection contract:\n{ \"entities\": [...], \"relations\": [...] }), validates it against that contract, and emits a canonical,\ndeterministic JSON artifact. The same (semantically equivalent) input always produces byte-identical\noutput, so the artifact is a stable, versionable input for future comparison, generation or review.\n\nOFFLINE / LOCAL ONLY — this is NOT a database connector (yet). It does NOT connect to PostgreSQL,\nMySQL, MongoDB or any database, does NOT read a connection string or .env, does NOT load an ORM/driver,\nand does NOT execute any query. It operates only on the local JSON file you pass with --input, which is\nan intermediate/offline representation of an introspection — not a live schema read. Connecting to real\ndatasources is a separate, not-yet-implemented step.\n\nThis command does NOT create a Maestro engine (no createMaestro()), does NOT execute operations, and\ndoes NOT require declared operations to have an implementation. It never modifies the input file.\n\nUsage:\n maestro introspect --input <path> [--out <path>]\n maestro introspect -i <path>\n\nFlags:\n --input, -i <path> Required. Path to a local IntrospectionResult JSON file.\n --out <path> Optional. Write the canonical artifact to this file instead of stdout.\n\nInput format (JSON — the core's IntrospectionResult contract):\n {\n \"entities\": [\n {\n \"table\": \"users\",\n \"fields\": [\n { \"name\": \"id\", \"nativeType\": \"uuid\", \"type\": \"uuid\", \"nullable\": false, \"isPrimaryKey\": true }\n ]\n }\n ],\n \"relations\": [\n {\n \"id\": \"orders.user_id->users.id\",\n \"type\": \"many-to-one\",\n \"from\": { \"table\": \"orders\", \"field\": \"user_id\" },\n \"to\": { \"table\": \"users\", \"field\": \"id\" },\n \"confidence\": \"definite\"\n }\n ]\n }\n\nOutput format (JSON):\n {\n \"schemaVersion\": 1,\n \"kind\": \"maestro.introspection\",\n \"source\": { \"path\": \"<the --input value>\" },\n \"summary\": { \"entities\": N, \"relations\": N },\n \"result\": { \"entities\": [...], \"relations\": [...] }\n }\n\nDeterminism:\n Entities are sorted by table, relations by id, and every object key is sorted. No timestamps,\n absolute paths or hashes are ever included.\n\nDifference from other commands:\n - introspect: validates/canonicalizes an IntrospectionResult (real DB-schema contract), offline.\n - snapshot: canonicalizes a declarative config file (maestro.config.yaml/json).\n - diff: compares two declarative config files.\n\nExit codes:\n 0 The input is a valid IntrospectionResult and the artifact was produced.\n 1 Usage, file-read, parse, validation or write error.\n\nExamples:\n maestro introspect --input ./introspection.json\n maestro introspect -i ./introspection.json\n maestro introspect --input ./introspection.json --out ./maestro.introspection.json`;\n\n/**\n * `maestro introspect` — reads a local `IntrospectionResult` JSON file, validates it against the core's\n * introspection contract, then emits a canonical, deterministic JSON artifact. It is offline/local only:\n * it never connects to a database/provider, never reads a connection string or `.env`, never loads a\n * driver/ORM, never calls `createMaestro()`, and never executes operations. It never modifies the input.\n * Exit codes: 0 = artifact produced, 1 = any error.\n */\nexport function createIntrospectCommand(deps: IntrospectCommandDeps = defaultDeps): Command {\n return {\n name: 'introspect',\n description: 'Validate and canonicalize a local IntrospectionResult JSON file (offline)',\n helpText: INTROSPECT_HELP_TEXT,\n run(context: CommandContext): number {\n const parsed = parseIntrospectArgs(context.argv);\n if (!parsed.ok) {\n context.stderr(`maestro introspect: ${parsed.error}`);\n return 1;\n }\n const { input, out } = parsed.value;\n\n let content: string;\n try {\n content = deps.readFile(input);\n } catch (error) {\n context.stderr(`maestro introspect: could not read input file '${input}': ${errorMessage(error)}`);\n return 1;\n }\n\n let raw: unknown;\n try {\n raw = JSON.parse(content);\n } catch (error) {\n context.stderr(`maestro introspect: invalid JSON in '${input}': ${errorMessage(error)}`);\n return 1;\n }\n\n const validated = validateIntrospectionResult(raw);\n if (!validated.ok) {\n context.stderr(`maestro introspect: ${validated.error}`);\n return 1;\n }\n\n const artifact = buildIntrospectionArtifact(validated.value, { path: input });\n const output = serializeIntrospection(artifact);\n\n if (out) {\n try {\n deps.writeFile(out, output);\n } catch (error) {\n context.stderr(`maestro introspect: could not write output file '${out}': ${errorMessage(error)}`);\n return 1;\n }\n context.stdout(`Introspection written: ${out}`);\n context.stdout(`Entities: ${artifact.summary.entities}`);\n context.stdout(`Relations: ${artifact.summary.relations}`);\n } else {\n context.stdout(output.replace(/\\n$/, ''));\n }\n\n return 0;\n },\n };\n}\n","import { CommandRegistry } from './commands/registry.js';\nimport { parseArgs } from './parseArgs.js';\nimport { formatHelp } from './help.js';\nimport { getCliVersion } from './version.js';\nimport { createGenerateCommand } from './commands/generate/GenerateCommand.js';\nimport { createValidateCommand } from './commands/validate/ValidateCommand.js';\nimport { createDiffCommand } from './commands/diff/DiffCommand.js';\nimport { createSnapshotCommand } from './commands/snapshot/SnapshotCommand.js';\nimport { createIntrospectCommand } from './commands/introspect/IntrospectCommand.js';\n\n/** Real, registered commands. Future phases register new commands here as they're implemented. */\nexport const defaultRegistry = new CommandRegistry();\ndefaultRegistry.register(createGenerateCommand());\ndefaultRegistry.register(createValidateCommand());\ndefaultRegistry.register(createDiffCommand());\ndefaultRegistry.register(createSnapshotCommand());\ndefaultRegistry.register(createIntrospectCommand());\n\nexport interface RunCliOptions {\n argv: string[];\n stdout?: (message: string) => void;\n stderr?: (message: string) => void;\n registry?: CommandRegistry;\n}\n\n/** Parses argv, dispatches to a registered command (or --help/--version), and returns the process exit code. */\nexport async function runCli(options: RunCliOptions): Promise<number> {\n const stdout = options.stdout ?? ((message: string) => console.log(message));\n const stderr = options.stderr ?? ((message: string) => console.error(message));\n const registry = options.registry ?? defaultRegistry;\n const parsed = parseArgs(options.argv);\n\n if (parsed.version) {\n stdout(getCliVersion());\n return 0;\n }\n\n const command = parsed.command ? registry.get(parsed.command) : undefined;\n\n if (parsed.help) {\n // A command with its own help text wins; otherwise (no command, or an unknown one) fall back to the global help.\n stdout(command?.helpText ?? formatHelp(registry));\n return 0;\n }\n\n if (!parsed.command) {\n stdout(formatHelp(registry));\n return 0;\n }\n\n if (!command) {\n stderr(`Unknown command '${parsed.command}'. Run \"maestro --help\" to see available commands.`);\n return 1;\n }\n\n return command.run({ argv: parsed.args, stdout, stderr });\n}\n"],"mappings":"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","names":["require","isObject","parseFlags","key","readFileSync","YAML","defaultDeps","readFileSync","errorMessage","ALIASES","parseFlags","key","readFileSync","extname","YAML","loadDeclarativeConfigFromString","defaultDeps","readFileSync","errorMessage","yamlParser","resolveFormat","extname","loadDeclarativeConfigFromString","ALIASES","parseFlags","key","readFileSync","writeFileSync","extname","YAML","loadDeclarativeConfigFromString","defaultDeps","readFileSync","writeFileSync","errorMessage","yamlParser","resolveFormat","extname","loadDeclarativeConfigFromString","ALIASES","parseFlags","key","compareStrings","sortKeys","readFileSync","writeFileSync","defaultDeps","readFileSync","writeFileSync","errorMessage"]}
1
+ {"version":3,"sources":["../src/commands/registry.ts","../src/commands/planned.ts","../src/parseArgs.ts","../src/help.ts","../src/version.ts","../src/commands/generate/parseGenerateArgs.ts","../src/commands/generate/GenerateCommand.ts","../src/commands/validate/parseValidateArgs.ts","../src/commands/validate/ValidateCommand.ts","../src/commands/diff/parseDiffArgs.ts","../src/commands/diff/diffDeclarativeConfigs.ts","../src/commands/diff/DiffCommand.ts","../src/commands/snapshot/parseSnapshotArgs.ts","../src/commands/snapshot/buildDeclarativeSnapshot.ts","../src/commands/snapshot/SnapshotCommand.ts","../src/commands/introspect/parseIntrospectArgs.ts","../src/commands/introspect/buildIntrospection.ts","../src/commands/introspect/IntrospectCommand.ts","../src/runCli.ts"],"sourcesContent":["import type { Command } from './Command.js';\n\nexport class CommandRegistry {\n private readonly commands = new Map<string, Command>();\n\n register(command: Command): void {\n if (this.commands.has(command.name)) {\n throw new Error(`Command '${command.name}' is already registered.`);\n }\n this.commands.set(command.name, command);\n }\n\n get(name: string): Command | undefined {\n return this.commands.get(name);\n }\n\n list(): Command[] {\n return [...this.commands.values()];\n }\n}\n","export interface PlannedCommand {\n name: string;\n description: string;\n}\n\n/**\n * Commands planned for future phases. Listed in `--help` output for discoverability only —\n * none of these are wired to the registry or execute any real logic yet.\n * `generate`, `validate`, `diff`, `snapshot` and `introspect` are no longer here — they're implemented\n * and registered. Real-datasource connectors remain a future phase but have no CLI surface yet.\n */\nexport const PLANNED_COMMANDS: PlannedCommand[] = [];\n","export interface ParsedArgs {\n command?: string;\n /** Remaining args for the command, or the full argv when there is no command (e.g. bare --help). */\n args: string[];\n help: boolean;\n version: boolean;\n}\n\n/**\n * Minimal argument parser: detects the global --help/-h and --version/-v flags anywhere in argv,\n * and treats the first non-flag argument as the command name. Deliberately simple — a dedicated\n * parsing library isn't justified for a single command slot plus two global flags.\n */\nexport function parseArgs(argv: string[]): ParsedArgs {\n const help = argv.includes('--help') || argv.includes('-h');\n const version = argv.includes('--version') || argv.includes('-v');\n const [first, ...rest] = argv;\n const hasCommand = first !== undefined && !first.startsWith('-');\n\n return {\n command: hasCommand ? first : undefined,\n args: hasCommand ? rest : argv,\n help,\n version,\n };\n}\n","import type { CommandRegistry } from './commands/registry.js';\nimport { PLANNED_COMMANDS } from './commands/planned.js';\n\nexport function formatHelp(registry: CommandRegistry): string {\n const lines: string[] = [\n 'maestro — Maestro CLI',\n '',\n 'Command-line interface for the Maestro declarative engine.',\n '',\n 'Usage:',\n ' maestro <command> [options]',\n '',\n 'Options:',\n ' -h, --help Show this help message',\n ' -v, --version Show the CLI version',\n '',\n ];\n\n const available = registry.list();\n if (available.length > 0) {\n lines.push('Available commands:');\n for (const command of available) {\n lines.push(` ${command.name.padEnd(12)} ${command.description}`);\n }\n lines.push('');\n }\n\n if (PLANNED_COMMANDS.length > 0) {\n lines.push('Planned commands (not yet implemented):');\n for (const planned of PLANNED_COMMANDS) {\n lines.push(` ${planned.name.padEnd(12)} ${planned.description}`);\n }\n }\n\n return lines.join('\\n');\n}\n","import { createRequire } from 'node:module';\n\nconst require = createRequire(import.meta.url);\n\n/** Reads the CLI's own version from package.json — works from both src/ (via tsx) and dist/ (built), since both sit one level below the package root. */\nexport function getCliVersion(): string {\n const pkg = require('../package.json') as { version: string };\n return pkg.version;\n}\n","export type GenerateInputType = 'metadata' | 'schema';\nexport type GenerateOutputFormat = 'json' | 'yaml';\n\nexport interface GenerateArgs {\n input: string;\n type: GenerateInputType;\n format: GenerateOutputFormat;\n out?: string;\n}\n\nexport type ParseGenerateArgsResult = { ok: true; value: GenerateArgs } | { ok: false; error: string };\n\n/** Parses `--key value` and `--key=value` flags. Boolean-style flags (no value, next token is another flag) resolve to 'true'. */\nfunction parseFlags(argv: string[]): Record<string, string> {\n const flags: Record<string, string> = {};\n for (let i = 0; i < argv.length; i++) {\n const arg = argv[i];\n if (!arg.startsWith('--')) continue;\n\n const eqIndex = arg.indexOf('=');\n if (eqIndex !== -1) {\n flags[arg.slice(2, eqIndex)] = arg.slice(eqIndex + 1);\n continue;\n }\n\n const key = arg.slice(2);\n const next = argv[i + 1];\n if (next !== undefined && !next.startsWith('--')) {\n flags[key] = next;\n i++;\n } else {\n flags[key] = 'true';\n }\n }\n return flags;\n}\n\nexport function parseGenerateArgs(argv: string[]): ParseGenerateArgsResult {\n const flags = parseFlags(argv);\n\n const input = flags['input'];\n if (!input) {\n return { ok: false, error: 'Missing required flag --input <path>.' };\n }\n\n const type = flags['type'];\n if (type !== 'metadata' && type !== 'schema') {\n return {\n ok: false,\n error: `Missing or invalid --type flag. Expected \"metadata\" or \"schema\"${type ? `, got \"${type}\"` : ''}.`,\n };\n }\n\n const format = flags['format'] ?? 'json';\n if (format !== 'json' && format !== 'yaml') {\n return { ok: false, error: `Invalid --format flag. Expected \"json\" or \"yaml\", got \"${format}\".` };\n }\n\n return { ok: true, value: { input, type, format, out: flags['out'] } };\n}\n","import { readFileSync, writeFileSync } from 'node:fs';\nimport * as YAML from 'yaml';\nimport {\n generateDeclarativeConfigFromMetadata,\n generateDeclarativeConfigFromSchema,\n serializeDeclarativeConfig,\n type DeclarativeGeneratorMetadataInput,\n type DeclarativeGeneratorSchemaInput,\n} from '@maykonpaulo/maestro-core';\nimport type { Command, CommandContext } from '../Command.js';\nimport { parseGenerateArgs } from './parseGenerateArgs.js';\n\nexport interface GenerateCommandDeps {\n readFile: (path: string) => string;\n writeFile: (path: string, content: string) => void;\n}\n\nconst defaultDeps: GenerateCommandDeps = {\n readFile: (path) => readFileSync(path, 'utf-8'),\n writeFile: (path, content) => writeFileSync(path, content, 'utf-8'),\n};\n\nfunction errorMessage(error: unknown): string {\n return error instanceof Error ? error.message : String(error);\n}\n\nconst GENERATE_HELP_TEXT = `maestro generate — Generate a declarative config from a local metadata/schema JSON file\n\nReads a local JSON file containing already-built EntityMetadata[] (--type metadata) or\nEntitySchema[] (--type schema) and generates a declarative config (EntityDeclaration[], plus an\noptional default consumer) using the core's Declarative Config Generator. The result is written to\nstdout, or to a file with --out.\n\nThis command does NOT perform introspection, does NOT connect to any database or datasource, and\ndoes NOT create a Maestro engine — it only reads a file, transforms it, and writes text. The input\nmust already be metadata/schema you produced some other way (e.g. via engine.getMetadata(), or a\nhand-written EntitySchema[]). Introspecting a live datasource is a separate, not-yet-implemented\ncommand (\"maestro introspect\").\n\nUsage:\n maestro generate --input <path> --type <metadata|schema> [--format <json|yaml>] [--out <path>]\n\nFlags:\n --input <path> Required. Path to a local JSON file.\n --type <metadata|schema> Required. Whether --input holds EntityMetadata[] or EntitySchema[].\n --format <json|yaml> Optional. Output format. Default: json.\n --out <path> Optional. Write the result to this file instead of stdout.\n\nExamples:\n maestro generate --input ./metadata.json --type metadata --format json\n maestro generate --input ./metadata.json --type metadata --format yaml --out ./maestro.config.yaml\n maestro generate --input ./schema.json --type schema --format json --out ./maestro.config.json\n\nRecommended flow:\n 1. Produce EntityMetadata[] or EntitySchema[] as JSON (e.g. JSON.stringify(engine.getMetadata().entities)).\n 2. maestro generate --input <that file> --type <metadata|schema> --out maestro.config.yaml\n 3. Load it back: loadDeclarativeConfigFromFile('./maestro.config.yaml', { yamlParser })\n 4. Pass the result to createMaestro({ declarations })`;\n\n/** Narrows to the minimal shape both generator inputs share, without validating field-level correctness — that's the core generator's job, not the CLI's. */\nfunction assertGeneratorInput(\n value: unknown,\n sourcePath: string,\n): asserts value is { entities: unknown[]; relations?: unknown[]; operations?: unknown[] } {\n const isObject = typeof value === 'object' && value !== null && !Array.isArray(value);\n const hasEntities = isObject && Array.isArray((value as Record<string, unknown>)['entities']);\n if (!hasEntities) {\n throw new Error(`'${sourcePath}' must be a JSON object with an \"entities\" array.`);\n }\n}\n\n/**\n * `maestro generate` — reads a local JSON file containing EntityMetadata[]/EntitySchema[]\n * (matching DeclarativeGeneratorMetadataInput/DeclarativeGeneratorSchemaInput) and generates a\n * declarative config using the core's Declarative Config Generator. No introspection, no\n * datasource/provider access, no engine is created — this command is a thin CLI wrapper.\n */\nexport function createGenerateCommand(deps: GenerateCommandDeps = defaultDeps): Command {\n return {\n name: 'generate',\n description: 'Generate a declarative config from a local metadata/schema JSON file',\n helpText: GENERATE_HELP_TEXT,\n run(context: CommandContext): number {\n const parsed = parseGenerateArgs(context.argv);\n if (!parsed.ok) {\n context.stderr(`maestro generate: ${parsed.error}`);\n return 1;\n }\n const { input, type, format, out } = parsed.value;\n\n let rawInput: string;\n try {\n rawInput = deps.readFile(input);\n } catch (error) {\n context.stderr(`maestro generate: could not read input file '${input}': ${errorMessage(error)}`);\n return 1;\n }\n\n let parsedInput: unknown;\n try {\n parsedInput = JSON.parse(rawInput);\n } catch (error) {\n context.stderr(`maestro generate: '${input}' is not valid JSON: ${errorMessage(error)}`);\n return 1;\n }\n\n let generated;\n try {\n assertGeneratorInput(parsedInput, input);\n generated =\n type === 'metadata'\n ? generateDeclarativeConfigFromMetadata(parsedInput as unknown as DeclarativeGeneratorMetadataInput)\n : generateDeclarativeConfigFromSchema(parsedInput as unknown as DeclarativeGeneratorSchemaInput);\n } catch (error) {\n context.stderr(`maestro generate: failed to generate declarative config: ${errorMessage(error)}`);\n return 1;\n }\n\n let output: string;\n try {\n output = serializeDeclarativeConfig(generated, {\n format,\n yamlSerializer: format === 'yaml' ? { stringify: (value: unknown) => YAML.stringify(value) } : undefined,\n });\n } catch (error) {\n context.stderr(`maestro generate: ${errorMessage(error)}`);\n return 1;\n }\n\n if (out) {\n try {\n deps.writeFile(out, output);\n } catch (error) {\n context.stderr(`maestro generate: could not write output file '${out}': ${errorMessage(error)}`);\n return 1;\n }\n context.stdout(`Declarative config written to ${out}`);\n } else {\n context.stdout(output);\n }\n\n return 0;\n },\n };\n}\n","export type ValidateFormat = 'json' | 'yaml';\n\nexport interface ValidateArgs {\n input: string;\n /** Explicit format override. When omitted, the command detects it from the file extension. */\n format?: ValidateFormat;\n}\n\nexport type ParseValidateArgsResult = { ok: true; value: ValidateArgs } | { ok: false; error: string };\n\n/** Short flags mapped to their long form before parsing. */\nconst ALIASES: Record<string, string> = { i: 'input' };\n\n/** Parses `--key value`, `--key=value` and short `-i value`. Boolean-style flags (no value) resolve to 'true'. */\nfunction parseFlags(argv: string[]): Record<string, string> {\n const flags: Record<string, string> = {};\n for (let i = 0; i < argv.length; i++) {\n const arg = argv[i];\n const isLong = arg.startsWith('--');\n const isShort = !isLong && arg.startsWith('-') && arg.length > 1;\n if (!isLong && !isShort) continue;\n\n const body = isLong ? arg.slice(2) : arg.slice(1);\n const eqIndex = body.indexOf('=');\n if (eqIndex !== -1) {\n const key = body.slice(0, eqIndex);\n flags[ALIASES[key] ?? key] = body.slice(eqIndex + 1);\n continue;\n }\n\n const key = ALIASES[body] ?? body;\n const next = argv[i + 1];\n if (next !== undefined && !next.startsWith('-')) {\n flags[key] = next;\n i++;\n } else {\n flags[key] = 'true';\n }\n }\n return flags;\n}\n\nexport function parseValidateArgs(argv: string[]): ParseValidateArgsResult {\n const flags = parseFlags(argv);\n\n const input = flags['input'];\n if (!input || input === 'true') {\n return { ok: false, error: 'Missing required flag --input <path> (or -i <path>).' };\n }\n\n const format = flags['format'];\n if (format !== undefined && format !== 'json' && format !== 'yaml') {\n return { ok: false, error: `Invalid --format flag. Expected \"json\" or \"yaml\", got \"${format}\".` };\n }\n\n return { ok: true, value: { input, format: format as ValidateFormat | undefined } };\n}\n","import { readFileSync } from 'node:fs';\nimport { extname } from 'node:path';\nimport * as YAML from 'yaml';\nimport {\n loadDeclarativeConfigFromString,\n type DeclarativeFileFormat,\n} from '@maykonpaulo/maestro-core';\nimport type { Command, CommandContext } from '../Command.js';\nimport { parseValidateArgs, type ValidateFormat } from './parseValidateArgs.js';\n\nexport interface ValidateCommandDeps {\n readFile: (path: string) => string;\n}\n\nconst defaultDeps: ValidateCommandDeps = {\n readFile: (path) => readFileSync(path, 'utf-8'),\n};\n\nfunction errorMessage(error: unknown): string {\n return error instanceof Error ? error.message : String(error);\n}\n\nconst VALIDATE_HELP_TEXT = `maestro validate — Validate a declarative config file (YAML or JSON)\n\nLoads a local declarative config file (maestro.config.yaml/.yml/.json) and validates its structure\nusing the core's Declarative File Loader. Prints a readable summary on success and a readable error\non failure.\n\nThis command does NOT create a Maestro engine (no createMaestro()), does NOT connect to any database,\ndatasource or provider, and does NOT require declared operations to have a real implementation.\nStructural validation of the declarative file is all it does; wiring operations to code and starting\nthe runtime is what createMaestro() does separately.\n\nUsage:\n maestro validate --input <path> [--format <json|yaml>]\n maestro validate -i <path>\n\nFlags:\n --input, -i <path> Required. Path to a local declarative config file (.yaml, .yml or .json).\n --format <json|yaml> Optional. Overrides the format detected from the file extension.\n\nAccepted file formats:\n .json → parsed as JSON\n .yaml, .yml → parsed as YAML\n (other) → pass --format explicitly\n\nWhat is validated:\n - The file parses as JSON/YAML.\n - The top-level shape (optional \"entities\" and \"consumers\" arrays; no unknown keys).\n - Each entity declaration (fields, types, capabilities, operations, relationships, enumOptions).\n - Each consumer declaration against its referenced entity.\n\nWhat is NOT validated:\n - Operation bindings (whether declared operations have a real handler) — that's createMaestro().\n - Datasource/provider connectivity — no database or external system is contacted.\n\nExamples:\n maestro validate --input ./maestro.config.yaml\n maestro validate --input ./maestro.config.json\n maestro validate -i ./maestro.config.yaml\n maestro validate --input ./maestro.config --format yaml`;\n\nconst yamlParser = { parse: (content: string): unknown => YAML.parse(content) };\n\n/** Resolves the declarative file format from an explicit override or the file extension. */\nfunction resolveFormat(\n input: string,\n override: ValidateFormat | undefined,\n): { ok: true; format: DeclarativeFileFormat } | { ok: false; error: string } {\n if (override) return { ok: true, format: override };\n\n const ext = extname(input).toLowerCase();\n if (ext === '.json') return { ok: true, format: 'json' };\n if (ext === '.yaml' || ext === '.yml') return { ok: true, format: 'yaml' };\n\n return {\n ok: false,\n error: `cannot detect format from file extension \"${ext || '(none)'}\" of '${input}'. Supported: .json, .yaml, .yml. Pass --format <json|yaml> to override.`,\n };\n}\n\n/**\n * `maestro validate` — reads a local declarative config file (YAML/JSON) and validates its structure\n * via the core's `loadDeclarativeConfigFromString`. It never calls `createMaestro()`, never connects\n * to a datasource/provider, and never requires operation bindings to exist — it is a thin CLI wrapper\n * over the core's declarative validation.\n */\nexport function createValidateCommand(deps: ValidateCommandDeps = defaultDeps): Command {\n return {\n name: 'validate',\n description: 'Validate a declarative config file (YAML or JSON)',\n helpText: VALIDATE_HELP_TEXT,\n run(context: CommandContext): number {\n const parsed = parseValidateArgs(context.argv);\n if (!parsed.ok) {\n context.stderr(`maestro validate: ${parsed.error}`);\n return 1;\n }\n const { input, format: formatOverride } = parsed.value;\n\n const resolved = resolveFormat(input, formatOverride);\n if (!resolved.ok) {\n context.stderr(`maestro validate: ${resolved.error}`);\n return 1;\n }\n const { format } = resolved;\n\n let content: string;\n try {\n content = deps.readFile(input);\n } catch (error) {\n context.stderr(`maestro validate: could not read input file '${input}': ${errorMessage(error)}`);\n return 1;\n }\n\n let config;\n try {\n config = loadDeclarativeConfigFromString(content, {\n format,\n yamlParser: format === 'yaml' ? yamlParser : undefined,\n source: input,\n });\n } catch (error) {\n context.stderr(`maestro validate: ${errorMessage(error)}`);\n return 1;\n }\n\n context.stdout(`Valid declarative config: ${input}`);\n context.stdout(`Entities: ${config.entities.length}`);\n context.stdout(`Consumers: ${config.consumers?.length ?? 0}`);\n return 0;\n },\n };\n}\n","export type DiffFormat = 'json' | 'yaml';\n\nexport interface DiffArgs {\n from: string;\n to: string;\n /** Explicit format override for the `from` file. Detected from the extension when omitted. */\n fromFormat?: DiffFormat;\n /** Explicit format override for the `to` file. Detected from the extension when omitted. */\n toFormat?: DiffFormat;\n}\n\nexport type ParseDiffArgsResult = { ok: true; value: DiffArgs } | { ok: false; error: string };\n\n/** Short flags mapped to their long form before parsing. */\nconst ALIASES: Record<string, string> = { f: 'from', t: 'to' };\n\n/** Parses `--key value`, `--key=value` and short `-f value`. Boolean-style flags (no value) resolve to 'true'. */\nfunction parseFlags(argv: string[]): Record<string, string> {\n const flags: Record<string, string> = {};\n for (let i = 0; i < argv.length; i++) {\n const arg = argv[i];\n const isLong = arg.startsWith('--');\n const isShort = !isLong && arg.startsWith('-') && arg.length > 1;\n if (!isLong && !isShort) continue;\n\n const body = isLong ? arg.slice(2) : arg.slice(1);\n const eqIndex = body.indexOf('=');\n if (eqIndex !== -1) {\n const key = body.slice(0, eqIndex);\n flags[ALIASES[key] ?? key] = body.slice(eqIndex + 1);\n continue;\n }\n\n const key = ALIASES[body] ?? body;\n const next = argv[i + 1];\n if (next !== undefined && !next.startsWith('-')) {\n flags[key] = next;\n i++;\n } else {\n flags[key] = 'true';\n }\n }\n return flags;\n}\n\nfunction validateFormat(\n value: string | undefined,\n flag: string,\n): { ok: true; value: DiffFormat | undefined } | { ok: false; error: string } {\n if (value === undefined) return { ok: true, value: undefined };\n if (value !== 'json' && value !== 'yaml') {\n return { ok: false, error: `Invalid ${flag} flag. Expected \"json\" or \"yaml\", got \"${value}\".` };\n }\n return { ok: true, value };\n}\n\nexport function parseDiffArgs(argv: string[]): ParseDiffArgsResult {\n const flags = parseFlags(argv);\n\n const from = flags['from'];\n if (!from || from === 'true') {\n return { ok: false, error: 'Missing required flag --from <path> (or -f <path>).' };\n }\n\n const to = flags['to'];\n if (!to || to === 'true') {\n return { ok: false, error: 'Missing required flag --to <path> (or -t <path>).' };\n }\n\n const fromFormat = validateFormat(flags['from-format'], '--from-format');\n if (!fromFormat.ok) return fromFormat;\n\n const toFormat = validateFormat(flags['to-format'], '--to-format');\n if (!toFormat.ok) return toFormat;\n\n return { ok: true, value: { from, to, fromFormat: fromFormat.value, toFormat: toFormat.value } };\n}\n","import type {\n DeclarativeFileConfig,\n EntityDeclaration,\n RelationDeclaration,\n ConsumerDeclaration,\n} from '@maykonpaulo/maestro-core';\n\n/** How a member (entity, field, consumer, …) changed between the two configs. */\nexport type ChangeKind = 'added' | 'removed' | 'changed';\n\n/** A single scalar/leaf property that differs between two objects of the same identity. */\nexport interface LeafChange {\n /** Property name (e.g. `label`, `type`). */\n path: string;\n from: unknown;\n to: unknown;\n}\n\n/** A named group of nested member diffs (e.g. an entity's `fields` or `operations`). */\nexport interface MemberGroup {\n title: string;\n members: MemberDiff[];\n}\n\n/** A diff entry for one identified member (entity, field, operation, relationship, consumer). */\nexport interface MemberDiff {\n name: string;\n kind: ChangeKind;\n /** Leaf-property differences (only for `changed`). */\n leafChanges?: LeafChange[];\n /** Nested member groups (only for `changed` entities). */\n groups?: MemberGroup[];\n}\n\n/** Structured, deterministic diff between two declarative configs. */\nexport interface DeclarativeDiff {\n entities: MemberDiff[];\n consumers: MemberDiff[];\n hasDifferences: boolean;\n}\n\n/**\n * Recursively sorts object keys so two structurally-equal values produce an identical string\n * regardless of the key order in the source files. Used both for equality and for display,\n * which keeps the diff deterministic (RF-016).\n */\nfunction canonicalize(value: unknown): unknown {\n if (Array.isArray(value)) return value.map(canonicalize);\n if (value !== null && typeof value === 'object') {\n const entries = Object.entries(value as Record<string, unknown>)\n .filter(([, v]) => v !== undefined)\n .sort(([a], [b]) => (a < b ? -1 : a > b ? 1 : 0));\n const out: Record<string, unknown> = {};\n for (const [k, v] of entries) out[k] = canonicalize(v);\n return out;\n }\n return value;\n}\n\nfunction canonicalString(value: unknown): string {\n return JSON.stringify(canonicalize(value)) ?? 'undefined';\n}\n\nfunction deepEqual(a: unknown, b: unknown): boolean {\n return canonicalString(a) === canonicalString(b);\n}\n\n/** Sorted union of the keys of two records (either may be undefined). */\nfunction sortedKeyUnion(...records: Array<Record<string, unknown> | undefined>): string[] {\n const keys = new Set<string>();\n for (const record of records) {\n if (record) for (const key of Object.keys(record)) keys.add(key);\n }\n return [...keys].sort((a, b) => (a < b ? -1 : a > b ? 1 : 0));\n}\n\n/** Compares two objects key-by-key (deep), producing one LeafChange per differing property. */\nfunction leafChanges(\n a: Record<string, unknown>,\n b: Record<string, unknown>,\n keys?: string[],\n): LeafChange[] {\n const paths = keys ?? sortedKeyUnion(a, b);\n const changes: LeafChange[] = [];\n for (const path of paths) {\n if (!deepEqual(a[path], b[path])) {\n changes.push({ path, from: a[path], to: b[path] });\n }\n }\n return changes;\n}\n\n/**\n * Diffs two `Record<string, object>` collections (fields or operations) by key. Members present\n * on only one side are `added`/`removed`; members on both sides are `changed` when any leaf differs.\n * Absent leaves become no entry when the objects are equal (deterministic, sorted output).\n */\nfunction diffRecord(\n from: Record<string, unknown> | undefined,\n to: Record<string, unknown> | undefined,\n): MemberDiff[] {\n const result: MemberDiff[] = [];\n for (const name of sortedKeyUnion(from, to)) {\n const a = from?.[name];\n const b = to?.[name];\n if (a === undefined) {\n result.push({ name, kind: 'added' });\n } else if (b === undefined) {\n result.push({ name, kind: 'removed' });\n } else {\n const changes = leafChanges(a as Record<string, unknown>, b as Record<string, unknown>);\n if (changes.length > 0) result.push({ name, kind: 'changed', leafChanges: changes });\n }\n }\n return result;\n}\n\n/**\n * Turns a relationship array into a keyed record so it can be diffed like fields/operations.\n * Keyed by explicit `id`, falling back to `${fromField}->${toEntity}.${toField}` — the tuple that\n * uniquely identifies a declarative relationship when no id is given.\n */\nfunction relationRecord(\n relationships: RelationDeclaration[] | undefined,\n): Record<string, RelationDeclaration> {\n const record: Record<string, RelationDeclaration> = {};\n for (const relation of relationships ?? []) {\n const key = relation.id ?? `${relation.fromField}->${relation.toEntity}.${relation.toField}`;\n record[key] = relation;\n }\n return record;\n}\n\n/** Scalar entity properties compared directly (nested collections are handled separately). */\nconst ENTITY_SCALAR_KEYS = ['label', 'pluralLabel', 'description', 'capabilities'];\n\n/** Consumer projection sections compared directly (identity keys `consumer`/`entity` excluded). */\nconst CONSUMER_KEYS = ['list', 'detail', 'forms', 'actions'];\n\n/** Diffs one entity that exists on both sides. Returns null when nothing changed. */\nfunction diffEntity(a: EntityDeclaration, b: EntityDeclaration): MemberDiff | null {\n const leaf = leafChanges(\n a as unknown as Record<string, unknown>,\n b as unknown as Record<string, unknown>,\n ENTITY_SCALAR_KEYS,\n );\n\n const groups: MemberGroup[] = [];\n const fields = diffRecord(a.fields, b.fields);\n if (fields.length > 0) groups.push({ title: 'fields', members: fields });\n const operations = diffRecord(a.operations, b.operations);\n if (operations.length > 0) groups.push({ title: 'operations', members: operations });\n const relationships = diffRecord(relationRecord(a.relationships), relationRecord(b.relationships));\n if (relationships.length > 0) groups.push({ title: 'relationships', members: relationships });\n\n if (leaf.length === 0 && groups.length === 0) return null;\n return { name: a.entity, kind: 'changed', leafChanges: leaf, groups };\n}\n\n/** Indexes entities by their `entity` identifier. */\nfunction entityIndex(config: DeclarativeFileConfig): Record<string, EntityDeclaration> {\n const index: Record<string, EntityDeclaration> = {};\n for (const entity of config.entities) index[entity.entity] = entity;\n return index;\n}\n\n/**\n * Indexes consumers by a composite `consumer:entity` key. A declarative config may declare the same\n * consumer against multiple entities, so the entity is part of the identity.\n */\nfunction consumerIndex(config: DeclarativeFileConfig): Record<string, ConsumerDeclaration> {\n const index: Record<string, ConsumerDeclaration> = {};\n for (const consumer of config.consumers ?? []) {\n index[`${consumer.consumer}:${consumer.entity}`] = consumer;\n }\n return index;\n}\n\nfunction diffEntities(from: DeclarativeFileConfig, to: DeclarativeFileConfig): MemberDiff[] {\n const a = entityIndex(from);\n const b = entityIndex(to);\n const result: MemberDiff[] = [];\n for (const name of sortedKeyUnion(a, b)) {\n if (a[name] === undefined) {\n result.push({ name, kind: 'added' });\n } else if (b[name] === undefined) {\n result.push({ name, kind: 'removed' });\n } else {\n const changed = diffEntity(a[name], b[name]);\n if (changed) result.push(changed);\n }\n }\n return result;\n}\n\nfunction diffConsumers(from: DeclarativeFileConfig, to: DeclarativeFileConfig): MemberDiff[] {\n const a = consumerIndex(from);\n const b = consumerIndex(to);\n const result: MemberDiff[] = [];\n for (const name of sortedKeyUnion(a, b)) {\n if (a[name] === undefined) {\n result.push({ name, kind: 'added' });\n } else if (b[name] === undefined) {\n result.push({ name, kind: 'removed' });\n } else {\n const changes = leafChanges(\n a[name] as unknown as Record<string, unknown>,\n b[name] as unknown as Record<string, unknown>,\n CONSUMER_KEYS,\n );\n if (changes.length > 0) result.push({ name, kind: 'changed', leafChanges: changes });\n }\n }\n return result;\n}\n\n/**\n * Compares two loaded declarative configs structurally and deterministically. Operates only on the\n * two in-memory configs — no engine, no datasource, no runtime. Entities and consumers are compared\n * by identity; changed entities are further compared across fields, operations and relationships.\n */\nexport function diffDeclarativeConfigs(\n from: DeclarativeFileConfig,\n to: DeclarativeFileConfig,\n): DeclarativeDiff {\n const entities = diffEntities(from, to);\n const consumers = diffConsumers(from, to);\n return { entities, consumers, hasDifferences: entities.length > 0 || consumers.length > 0 };\n}\n\nconst SYMBOL: Record<ChangeKind, string> = { added: '+', removed: '-', changed: '~' };\n\n/** Renders a leaf value for display: strings quoted, objects as canonical JSON, absence as `(unset)`. */\nfunction renderValue(value: unknown): string {\n if (value === undefined) return '(unset)';\n return canonicalString(value);\n}\n\nfunction renderLeafChange(change: LeafChange, indent: string): string {\n return `${indent}${change.path}: ${renderValue(change.from)} → ${renderValue(change.to)}`;\n}\n\nfunction renderMember(member: MemberDiff, indent: string, lines: string[]): void {\n lines.push(`${indent}${SYMBOL[member.kind]} ${member.name}`);\n const childIndent = `${indent} `;\n for (const change of member.leafChanges ?? []) {\n lines.push(renderLeafChange(change, childIndent));\n }\n for (const group of member.groups ?? []) {\n lines.push(`${childIndent}${group.title}:`);\n for (const child of group.members) {\n renderMember(child, `${childIndent} `, lines);\n }\n }\n}\n\n/**\n * Formats a `DeclarativeDiff` as compact, terminal-friendly text. Returns `No differences found.`\n * when the configs are equal, otherwise a `Differences found.` report grouped by Entities/Consumers.\n */\nexport function formatDeclarativeDiff(diff: DeclarativeDiff): string {\n if (!diff.hasDifferences) return 'No differences found.';\n\n const lines: string[] = ['Differences found.'];\n if (diff.entities.length > 0) {\n lines.push('', 'Entities:');\n for (const member of diff.entities) renderMember(member, ' ', lines);\n }\n if (diff.consumers.length > 0) {\n lines.push('', 'Consumers:');\n for (const member of diff.consumers) renderMember(member, ' ', lines);\n }\n return lines.join('\\n');\n}\n","import { readFileSync } from 'node:fs';\nimport { extname } from 'node:path';\nimport * as YAML from 'yaml';\nimport {\n loadDeclarativeConfigFromString,\n type DeclarativeFileConfig,\n type DeclarativeFileFormat,\n} from '@maykonpaulo/maestro-core';\nimport type { Command, CommandContext } from '../Command.js';\nimport { parseDiffArgs, type DiffFormat } from './parseDiffArgs.js';\nimport { diffDeclarativeConfigs, formatDeclarativeDiff } from './diffDeclarativeConfigs.js';\n\nexport interface DiffCommandDeps {\n readFile: (path: string) => string;\n}\n\nconst defaultDeps: DiffCommandDeps = {\n readFile: (path) => readFileSync(path, 'utf-8'),\n};\n\n/** Exit code returned when the two files are valid and differ (RF-018). */\nconst EXIT_DIFFERENCES = 1;\n/** Exit code returned for any usage, read, parse or validation error (RF-018). */\nconst EXIT_ERROR = 2;\n\nfunction errorMessage(error: unknown): string {\n return error instanceof Error ? error.message : String(error);\n}\n\nconst DIFF_HELP_TEXT = `maestro diff — Compare two declarative config files (YAML or JSON)\n\nLoads two local declarative config files (maestro.config.yaml/.yml/.json) with the core's Declarative\nFile Loader, then compares their normalised structures and prints a readable, deterministic report of\nwhat changed. Useful before promoting, reviewing or versioning a config.\n\nThis command does NOT create a Maestro engine (no createMaestro()), does NOT connect to any database,\ndatasource or provider, does NOT execute operations, and does NOT require declared operations to have\na real implementation. It is a read-only, local comparison of two declarative files.\n\nUsage:\n maestro diff --from <path> --to <path> [--from-format <json|yaml>] [--to-format <json|yaml>]\n maestro diff -f <path> -t <path>\n\nFlags:\n --from, -f <path> Required. Path to the baseline declarative config file.\n --to, -t <path> Required. Path to the changed declarative config file.\n --from-format <json|yaml> Optional. Overrides the format detected from the --from extension.\n --to-format <json|yaml> Optional. Overrides the format detected from the --to extension.\n\nAccepted file formats:\n .json → parsed as JSON\n .yaml, .yml → parsed as YAML\n (other) → pass --from-format / --to-format explicitly\n\nWhat is compared:\n - Entities (added / removed / changed): label, pluralLabel, description, capabilities.\n - Entity fields (added / removed / changed): type, label, required, readonly, description,\n enumOptions, relationEntity and any other declarative field property.\n - Entity operations (added / removed / changed) — no handler/implementation required.\n - Entity relationships (added / removed / changed).\n - Consumers (added / removed / changed): list, detail, forms and actions projections.\n\nWhat is NOT compared:\n - Operation bindings or handlers — that's createMaestro(), not diff.\n - Live database/introspection metadata — this diffs declarative files, not a real schema.\n\nExit codes:\n 0 Both files are valid and there are no differences.\n 1 Both files are valid and there are differences.\n 2 Usage, file-read, parse or validation error.\n\nExamples:\n maestro diff --from ./maestro.config.old.yaml --to ./maestro.config.new.yaml\n maestro diff -f ./before.json -t ./after.json\n maestro diff --from ./before.config --from-format yaml --to ./after.config --to-format yaml`;\n\nconst yamlParser = { parse: (content: string): unknown => YAML.parse(content) };\n\n/** Resolves a declarative file format from an explicit override or the file extension. */\nfunction resolveFormat(\n path: string,\n override: DiffFormat | undefined,\n flag: string,\n): { ok: true; format: DeclarativeFileFormat } | { ok: false; error: string } {\n if (override) return { ok: true, format: override };\n\n const ext = extname(path).toLowerCase();\n if (ext === '.json') return { ok: true, format: 'json' };\n if (ext === '.yaml' || ext === '.yml') return { ok: true, format: 'yaml' };\n\n return {\n ok: false,\n error: `cannot detect format from file extension \"${ext || '(none)'}\" of '${path}'. Supported: .json, .yaml, .yml. Pass ${flag} <json|yaml> to override.`,\n };\n}\n\n/** Reads and loads a declarative config file, returning a readable error result instead of throwing. */\nfunction loadConfig(\n deps: DiffCommandDeps,\n path: string,\n format: DeclarativeFileFormat,\n): { ok: true; config: DeclarativeFileConfig } | { ok: false; error: string } {\n let content: string;\n try {\n content = deps.readFile(path);\n } catch (error) {\n return { ok: false, error: `could not read file '${path}': ${errorMessage(error)}` };\n }\n\n try {\n const config = loadDeclarativeConfigFromString(content, {\n format,\n yamlParser: format === 'yaml' ? yamlParser : undefined,\n source: path,\n });\n return { ok: true, config };\n } catch (error) {\n return { ok: false, error: errorMessage(error) };\n }\n}\n\n/**\n * `maestro diff` — reads two local declarative config files (YAML/JSON), validates each via the\n * core's `loadDeclarativeConfigFromString`, then structurally compares them. It never calls\n * `createMaestro()`, never connects to a datasource/provider, never executes operations, and never\n * requires operation bindings to exist. Read-only. Exit codes: 0 = no diff, 1 = diff, 2 = error.\n */\nexport function createDiffCommand(deps: DiffCommandDeps = defaultDeps): Command {\n return {\n name: 'diff',\n description: 'Compare two declarative config files (YAML or JSON)',\n helpText: DIFF_HELP_TEXT,\n run(context: CommandContext): number {\n const parsed = parseDiffArgs(context.argv);\n if (!parsed.ok) {\n context.stderr(`maestro diff: ${parsed.error}`);\n return EXIT_ERROR;\n }\n const { from, to, fromFormat, toFormat } = parsed.value;\n\n const fromResolved = resolveFormat(from, fromFormat, '--from-format');\n if (!fromResolved.ok) {\n context.stderr(`maestro diff: ${fromResolved.error}`);\n return EXIT_ERROR;\n }\n const toResolved = resolveFormat(to, toFormat, '--to-format');\n if (!toResolved.ok) {\n context.stderr(`maestro diff: ${toResolved.error}`);\n return EXIT_ERROR;\n }\n\n const fromConfig = loadConfig(deps, from, fromResolved.format);\n if (!fromConfig.ok) {\n context.stderr(`maestro diff: ${fromConfig.error}`);\n return EXIT_ERROR;\n }\n const toConfig = loadConfig(deps, to, toResolved.format);\n if (!toConfig.ok) {\n context.stderr(`maestro diff: ${toConfig.error}`);\n return EXIT_ERROR;\n }\n\n const diff = diffDeclarativeConfigs(fromConfig.config, toConfig.config);\n context.stdout(formatDeclarativeDiff(diff));\n return diff.hasDifferences ? EXIT_DIFFERENCES : 0;\n },\n };\n}\n","export type SnapshotInputFormat = 'json' | 'yaml';\nexport type SnapshotOutputFormat = 'json';\n\nexport interface SnapshotArgs {\n input: string;\n /** Explicit input format override. Detected from the file extension when omitted. */\n inputFormat?: SnapshotInputFormat;\n /** Output file path. When omitted, the snapshot is written to stdout. */\n out?: string;\n /** Snapshot output format. Only `json` is supported for now. */\n format: SnapshotOutputFormat;\n}\n\nexport type ParseSnapshotArgsResult =\n | { ok: true; value: SnapshotArgs }\n | { ok: false; error: string };\n\n/** Short flags mapped to their long form before parsing. */\nconst ALIASES: Record<string, string> = { i: 'input' };\n\n/** Parses `--key value`, `--key=value` and short `-i value`. Boolean-style flags (no value) resolve to 'true'. */\nfunction parseFlags(argv: string[]): Record<string, string> {\n const flags: Record<string, string> = {};\n for (let i = 0; i < argv.length; i++) {\n const arg = argv[i];\n const isLong = arg.startsWith('--');\n const isShort = !isLong && arg.startsWith('-') && arg.length > 1;\n if (!isLong && !isShort) continue;\n\n const body = isLong ? arg.slice(2) : arg.slice(1);\n const eqIndex = body.indexOf('=');\n if (eqIndex !== -1) {\n const key = body.slice(0, eqIndex);\n flags[ALIASES[key] ?? key] = body.slice(eqIndex + 1);\n continue;\n }\n\n const key = ALIASES[body] ?? body;\n const next = argv[i + 1];\n if (next !== undefined && !next.startsWith('-')) {\n flags[key] = next;\n i++;\n } else {\n flags[key] = 'true';\n }\n }\n return flags;\n}\n\nfunction validateInputFormat(\n value: string | undefined,\n): { ok: true; value: SnapshotInputFormat | undefined } | { ok: false; error: string } {\n if (value === undefined) return { ok: true, value: undefined };\n if (value !== 'json' && value !== 'yaml') {\n return {\n ok: false,\n error: `Invalid --input-format flag. Expected \"json\" or \"yaml\", got \"${value}\".`,\n };\n }\n return { ok: true, value };\n}\n\nfunction validateOutputFormat(\n value: string | undefined,\n): { ok: true; value: SnapshotOutputFormat } | { ok: false; error: string } {\n if (value === undefined) return { ok: true, value: 'json' };\n if (value !== 'json') {\n return { ok: false, error: `Invalid --format flag. Expected \"json\", got \"${value}\".` };\n }\n return { ok: true, value };\n}\n\nexport function parseSnapshotArgs(argv: string[]): ParseSnapshotArgsResult {\n const flags = parseFlags(argv);\n\n const input = flags['input'];\n if (!input || input === 'true') {\n return { ok: false, error: 'Missing required flag --input <path> (or -i <path>).' };\n }\n\n const inputFormat = validateInputFormat(flags['input-format']);\n if (!inputFormat.ok) return inputFormat;\n\n const format = validateOutputFormat(flags['format']);\n if (!format.ok) return format;\n\n const out = flags['out'] && flags['out'] !== 'true' ? flags['out'] : undefined;\n\n return {\n ok: true,\n value: { input, inputFormat: inputFormat.value, out, format: format.value },\n };\n}\n","import type {\n DeclarativeFileConfig,\n DeclarativeFileFormat,\n EntityDeclaration,\n ConsumerDeclaration,\n RelationDeclaration,\n} from '@maykonpaulo/maestro-core';\n\n/** Bumped only when the snapshot structure changes in a backwards-incompatible way. */\nexport const SNAPSHOT_SCHEMA_VERSION = 1;\nexport const SNAPSHOT_KIND = 'maestro.declarative.snapshot';\n\nexport interface SnapshotSource {\n /** Path exactly as passed on the command line — never resolved to an absolute path (determinism). */\n path: string;\n format: DeclarativeFileFormat;\n}\n\nexport interface SnapshotSummary {\n entities: number;\n consumers: number;\n relations: number;\n}\n\n/** A relationship flattened out of its owning entity, tagged with the entity it belongs to. */\nexport interface SnapshotRelation extends RelationDeclaration {\n /** Identifier of the entity that declares this relationship. */\n fromEntity: string;\n}\n\nexport interface SnapshotDeclarations {\n entities: EntityDeclaration[];\n consumers: ConsumerDeclaration[];\n relations: SnapshotRelation[];\n}\n\nexport interface DeclarativeSnapshot {\n schemaVersion: number;\n kind: string;\n source: SnapshotSource;\n summary: SnapshotSummary;\n declarations: SnapshotDeclarations;\n}\n\n/** Derived, stable identifier for a relationship — mirrors the core's default (`${fromEntity}.${toEntity}`). */\nfunction relationId(fromEntity: string, relation: RelationDeclaration): string {\n return relation.id ?? `${fromEntity}.${relation.toEntity}`;\n}\n\nfunction compareStrings(a: string, b: string): number {\n return a < b ? -1 : a > b ? 1 : 0;\n}\n\n/**\n * Builds a canonical, deterministic snapshot object from an already-loaded (and validated)\n * declarative config. Ordering is stable: entities by `entity`, consumers by `consumer`,\n * relationships (and the flattened relations index) by derived id. Object-key ordering is applied\n * later by {@link serializeSnapshot}. No volatile data (timestamps, absolute paths, hashes).\n */\nexport function buildDeclarativeSnapshot(\n config: DeclarativeFileConfig,\n source: SnapshotSource,\n): DeclarativeSnapshot {\n const entities = [...config.entities]\n .sort((a, b) => compareStrings(a.entity, b.entity))\n .map((entity) => canonicalizeEntity(entity));\n\n const consumers = [...(config.consumers ?? [])].sort((a, b) =>\n compareStrings(a.consumer, b.consumer),\n );\n\n const relations = entities\n .flatMap((entity) =>\n (entity.relationships ?? []).map(\n (relation): SnapshotRelation => ({ fromEntity: entity.entity, ...relation }),\n ),\n )\n .sort((a, b) => {\n const byId = compareStrings(relationId(a.fromEntity, a), relationId(b.fromEntity, b));\n return byId !== 0 ? byId : compareStrings(a.fromEntity, b.fromEntity);\n });\n\n return {\n schemaVersion: SNAPSHOT_SCHEMA_VERSION,\n kind: SNAPSHOT_KIND,\n source,\n summary: {\n entities: entities.length,\n consumers: consumers.length,\n relations: relations.length,\n },\n declarations: { entities, consumers, relations },\n };\n}\n\n/** Returns the entity with its relationships array sorted by derived id (fields/operations are Records — key order is handled during serialization). */\nfunction canonicalizeEntity(entity: EntityDeclaration): EntityDeclaration {\n if (!entity.relationships || entity.relationships.length === 0) return entity;\n const relationships = [...entity.relationships].sort((a, b) =>\n compareStrings(relationId(entity.entity, a), relationId(entity.entity, b)),\n );\n return { ...entity, relationships };\n}\n\n/** Recursively sorts object keys so equivalent objects serialize identically, regardless of authoring order. Array order is preserved. */\nfunction sortKeys(value: unknown): unknown {\n if (Array.isArray(value)) return value.map(sortKeys);\n if (value !== null && typeof value === 'object') {\n const sorted: Record<string, unknown> = {};\n for (const key of Object.keys(value).sort()) {\n sorted[key] = sortKeys((value as Record<string, unknown>)[key]);\n }\n return sorted;\n }\n return value;\n}\n\n/** Serializes a snapshot to canonical JSON: recursively sorted object keys, 2-space indent, trailing newline. */\nexport function serializeSnapshot(snapshot: DeclarativeSnapshot): string {\n return `${JSON.stringify(sortKeys(snapshot), null, 2)}\\n`;\n}\n","import { readFileSync, writeFileSync } from 'node:fs';\nimport { extname } from 'node:path';\nimport * as YAML from 'yaml';\nimport {\n loadDeclarativeConfigFromString,\n type DeclarativeFileConfig,\n type DeclarativeFileFormat,\n} from '@maykonpaulo/maestro-core';\nimport type { Command, CommandContext } from '../Command.js';\nimport { parseSnapshotArgs, type SnapshotInputFormat } from './parseSnapshotArgs.js';\nimport { buildDeclarativeSnapshot, serializeSnapshot } from './buildDeclarativeSnapshot.js';\n\nexport interface SnapshotCommandDeps {\n readFile: (path: string) => string;\n writeFile: (path: string, content: string) => void;\n}\n\nconst defaultDeps: SnapshotCommandDeps = {\n readFile: (path) => readFileSync(path, 'utf-8'),\n writeFile: (path, content) => writeFileSync(path, content, 'utf-8'),\n};\n\nfunction errorMessage(error: unknown): string {\n return error instanceof Error ? error.message : String(error);\n}\n\nconst SNAPSHOT_HELP_TEXT = `maestro snapshot — Produce a canonical, deterministic snapshot of a declarative config file\n\nLoads a local declarative config file (maestro.config.yaml/.yml/.json) with the core's Declarative\nFile Loader, validates it, then emits a canonical JSON snapshot of its declarations. The snapshot is a\nstable, versionable artifact for auditing, PR review and future comparison — the same (semantically\nequivalent) input always produces byte-identical output.\n\nThis command does NOT create a Maestro engine (no createMaestro()), does NOT connect to any database,\ndatasource or provider, does NOT execute operations, and does NOT require declared operations to have\na real implementation. It is a read-only, local, declarative snapshot — NOT a snapshot of a live\ndatabase or of runtime introspection.\n\nUsage:\n maestro snapshot --input <path> [--input-format <json|yaml>] [--format json] [--out <path>]\n maestro snapshot -i <path>\n\nFlags:\n --input, -i <path> Required. Path to a local declarative config file (.yaml, .yml or .json).\n --input-format <json|yaml> Optional. Overrides the format detected from the --input extension.\n --format json Optional. Snapshot output format. Only \"json\" is supported. Default: json.\n --out <path> Optional. Write the snapshot to this file instead of stdout.\n\nAccepted input formats:\n .json → parsed as JSON\n .yaml, .yml → parsed as YAML\n (other) → pass --input-format <json|yaml> explicitly\n\nSnapshot format (JSON):\n {\n \"schemaVersion\": 1,\n \"kind\": \"maestro.declarative.snapshot\",\n \"source\": { \"path\": \"<the --input value>\", \"format\": \"yaml\" },\n \"summary\": { \"entities\": N, \"consumers\": N, \"relations\": N },\n \"declarations\": { \"entities\": [...], \"consumers\": [...], \"relations\": [...] }\n }\n\nWhat is included:\n - Every declared entity (fields, capabilities, operations, relationships), consumer and relationship.\n - A flattened \"relations\" index of all entity relationships, each tagged with its \"fromEntity\".\n - Stable ordering (entities/consumers/relations sorted; object keys sorted) for deterministic output.\n\nWhat is NOT included:\n - Timestamps, absolute paths, hashes or any value that varies between runs of the same input.\n - Operation bindings/handlers, live database or runtime introspection data.\n\nExit codes:\n 0 The file is valid and the snapshot was produced.\n 1 Usage, file-read, parse, validation or write error.\n\nExamples:\n maestro snapshot --input ./maestro.config.yaml\n maestro snapshot -i ./maestro.config.json\n maestro snapshot --input ./maestro.config.yaml --out ./maestro.snapshot.json\n maestro snapshot --input ./maestro.config --input-format yaml --out ./maestro.snapshot.json`;\n\nconst yamlParser = { parse: (content: string): unknown => YAML.parse(content) };\n\n/** Resolves the declarative input format from an explicit override or the file extension. */\nfunction resolveFormat(\n input: string,\n override: SnapshotInputFormat | undefined,\n): { ok: true; format: DeclarativeFileFormat } | { ok: false; error: string } {\n if (override) return { ok: true, format: override };\n\n const ext = extname(input).toLowerCase();\n if (ext === '.json') return { ok: true, format: 'json' };\n if (ext === '.yaml' || ext === '.yml') return { ok: true, format: 'yaml' };\n\n return {\n ok: false,\n error: `cannot detect format from file extension \"${ext || '(none)'}\" of '${input}'. Supported: .json, .yaml, .yml. Pass --input-format <json|yaml> to override.`,\n };\n}\n\n/**\n * `maestro snapshot` — reads a local declarative config file (YAML/JSON), validates it via the core's\n * `loadDeclarativeConfigFromString`, then emits a canonical, deterministic JSON snapshot of its\n * declarations. It never calls `createMaestro()`, never connects to a datasource/provider, never\n * executes operations, and never requires operation bindings to exist. Read-only, local, declarative.\n * Exit codes: 0 = snapshot produced, 1 = any error.\n */\nexport function createSnapshotCommand(deps: SnapshotCommandDeps = defaultDeps): Command {\n return {\n name: 'snapshot',\n description: 'Produce a canonical snapshot of a declarative config file (YAML or JSON)',\n helpText: SNAPSHOT_HELP_TEXT,\n run(context: CommandContext): number {\n const parsed = parseSnapshotArgs(context.argv);\n if (!parsed.ok) {\n context.stderr(`maestro snapshot: ${parsed.error}`);\n return 1;\n }\n const { input, inputFormat, out } = parsed.value;\n\n const resolved = resolveFormat(input, inputFormat);\n if (!resolved.ok) {\n context.stderr(`maestro snapshot: ${resolved.error}`);\n return 1;\n }\n const { format } = resolved;\n\n let content: string;\n try {\n content = deps.readFile(input);\n } catch (error) {\n context.stderr(`maestro snapshot: could not read input file '${input}': ${errorMessage(error)}`);\n return 1;\n }\n\n let config: DeclarativeFileConfig;\n try {\n config = loadDeclarativeConfigFromString(content, {\n format,\n yamlParser: format === 'yaml' ? yamlParser : undefined,\n source: input,\n });\n } catch (error) {\n context.stderr(`maestro snapshot: ${errorMessage(error)}`);\n return 1;\n }\n\n const snapshot = buildDeclarativeSnapshot(config, { path: input, format });\n const output = serializeSnapshot(snapshot);\n\n if (out) {\n try {\n deps.writeFile(out, output);\n } catch (error) {\n context.stderr(`maestro snapshot: could not write output file '${out}': ${errorMessage(error)}`);\n return 1;\n }\n context.stdout(`Snapshot written: ${out}`);\n context.stdout(`Entities: ${snapshot.summary.entities}`);\n context.stdout(`Consumers: ${snapshot.summary.consumers}`);\n context.stdout(`Relations: ${snapshot.summary.relations}`);\n } else {\n context.stdout(output.replace(/\\n$/, ''));\n }\n\n return 0;\n },\n };\n}\n","export interface IntrospectArgs {\n /** Path to the local IntrospectionResult JSON file. */\n input: string;\n /** Output file path. When omitted, the canonical JSON is written to stdout. */\n out?: string;\n}\n\nexport type ParseIntrospectArgsResult =\n | { ok: true; value: IntrospectArgs }\n | { ok: false; error: string };\n\n/** Short flags mapped to their long form before parsing. */\nconst ALIASES: Record<string, string> = { i: 'input' };\n\n/** Parses `--key value`, `--key=value` and short `-i value`. Boolean-style flags (no value) resolve to 'true'. */\nfunction parseFlags(argv: string[]): Record<string, string> {\n const flags: Record<string, string> = {};\n for (let i = 0; i < argv.length; i++) {\n const arg = argv[i];\n const isLong = arg.startsWith('--');\n const isShort = !isLong && arg.startsWith('-') && arg.length > 1;\n if (!isLong && !isShort) continue;\n\n const body = isLong ? arg.slice(2) : arg.slice(1);\n const eqIndex = body.indexOf('=');\n if (eqIndex !== -1) {\n const key = body.slice(0, eqIndex);\n flags[ALIASES[key] ?? key] = body.slice(eqIndex + 1);\n continue;\n }\n\n const key = ALIASES[body] ?? body;\n const next = argv[i + 1];\n if (next !== undefined && !next.startsWith('-')) {\n flags[key] = next;\n i++;\n } else {\n flags[key] = 'true';\n }\n }\n return flags;\n}\n\nexport function parseIntrospectArgs(argv: string[]): ParseIntrospectArgsResult {\n const flags = parseFlags(argv);\n\n const input = flags['input'];\n if (!input || input === 'true') {\n return { ok: false, error: 'Missing required flag --input <path> (or -i <path>).' };\n }\n\n const out = flags['out'] && flags['out'] !== 'true' ? flags['out'] : undefined;\n\n return { ok: true, value: { input, out } };\n}\n","import type { IntrospectionResult } from '@maykonpaulo/maestro-core';\nimport {\n validateIntrospectionResult as coreValidateIntrospectionResult,\n normalizeIntrospectionResult,\n} from '@maykonpaulo/maestro-core';\n\n/** Bumped only when the artifact structure changes in a backwards-incompatible way. */\nexport const INTROSPECTION_SCHEMA_VERSION = 1;\nexport const INTROSPECTION_KIND = 'maestro.introspection';\n\nexport interface IntrospectionSource {\n /** Path exactly as passed on the command line — never resolved to an absolute path (determinism). */\n path: string;\n}\n\nexport interface IntrospectionSummary {\n entities: number;\n relations: number;\n}\n\n/**\n * CLI-level artifact wrapping a validated, canonicalized `IntrospectionResult`. The `result` payload\n * is the core's real `IntrospectionResult` shape — this envelope adds only versioning, a summary and\n * the source path, exactly like the declarative snapshot artifact does for declarative configs.\n */\nexport interface IntrospectionArtifact {\n schemaVersion: number;\n kind: string;\n source: IntrospectionSource;\n summary: IntrospectionSummary;\n result: IntrospectionResult;\n}\n\nexport type ValidateIntrospectionResult =\n | { ok: true; value: IntrospectionResult }\n | { ok: false; error: string };\n\n/**\n * Validates a parsed JSON value against the core's public `IntrospectionResult` contract and adapts the\n * result to a single-line, CLI-friendly shape (a stderr message + exit code). All structural validation\n * rules live in `@maykonpaulo/maestro-core`'s `validateIntrospectionResult` — this wrapper only formats\n * the core's issue list for command-line output.\n */\nexport function validateIntrospectionResult(value: unknown): ValidateIntrospectionResult {\n const result = coreValidateIntrospectionResult(value);\n if (!result.valid) {\n const error = result.issues\n .map((issue) => (issue.path ? `${issue.path}: ${issue.message}` : issue.message))\n .join('; ');\n return { ok: false, error };\n }\n return { ok: true, value: value as IntrospectionResult };\n}\n\n/**\n * Canonicalizes an `IntrospectionResult` via the core's `normalizeIntrospectionResult`: entities sorted\n * by `table`, relations by `id`. Field and index array order is preserved (column order is meaningful);\n * object-key ordering is applied later by {@link serializeIntrospection}.\n */\nfunction canonicalizeResult(result: IntrospectionResult): IntrospectionResult {\n return normalizeIntrospectionResult(result);\n}\n\n/** Recursively sorts object keys so equivalent objects serialize identically. Array order is preserved. */\nfunction sortKeys(value: unknown): unknown {\n if (Array.isArray(value)) return value.map(sortKeys);\n if (value !== null && typeof value === 'object') {\n const sorted: Record<string, unknown> = {};\n for (const key of Object.keys(value).sort()) {\n sorted[key] = sortKeys((value as Record<string, unknown>)[key]);\n }\n return sorted;\n }\n return value;\n}\n\n/**\n * Builds a canonical, deterministic introspection artifact from an already-validated result. No\n * volatile data (timestamps, absolute paths, hashes) — the same input always produces the same output.\n */\nexport function buildIntrospectionArtifact(\n result: IntrospectionResult,\n source: IntrospectionSource,\n): IntrospectionArtifact {\n const canonical = canonicalizeResult(result);\n return {\n schemaVersion: INTROSPECTION_SCHEMA_VERSION,\n kind: INTROSPECTION_KIND,\n source,\n summary: {\n entities: canonical.entities.length,\n relations: canonical.relations.length,\n },\n result: canonical,\n };\n}\n\n/** Serializes an artifact to canonical JSON: recursively sorted object keys, 2-space indent, trailing newline. */\nexport function serializeIntrospection(artifact: IntrospectionArtifact): string {\n return `${JSON.stringify(sortKeys(artifact), null, 2)}\\n`;\n}\n","import { readFileSync, writeFileSync } from 'node:fs';\nimport type { Command, CommandContext } from '../Command.js';\nimport { parseIntrospectArgs } from './parseIntrospectArgs.js';\nimport {\n validateIntrospectionResult,\n buildIntrospectionArtifact,\n serializeIntrospection,\n} from './buildIntrospection.js';\n\nexport interface IntrospectCommandDeps {\n readFile: (path: string) => string;\n writeFile: (path: string, content: string) => void;\n}\n\nconst defaultDeps: IntrospectCommandDeps = {\n readFile: (path) => readFileSync(path, 'utf-8'),\n writeFile: (path, content) => writeFileSync(path, content, 'utf-8'),\n};\n\nfunction errorMessage(error: unknown): string {\n return error instanceof Error ? error.message : String(error);\n}\n\nconst INTROSPECT_HELP_TEXT = `maestro introspect — Validate and canonicalize a local IntrospectionResult (offline)\n\nReads a local JSON file describing an IntrospectionResult (the core's introspection contract:\n{ \"entities\": [...], \"relations\": [...] }), validates it against that contract, and emits a canonical,\ndeterministic JSON artifact. The same (semantically equivalent) input always produces byte-identical\noutput, so the artifact is a stable, versionable input for future comparison, generation or review.\n\nOFFLINE / LOCAL ONLY — this is NOT a database connector (yet). It does NOT connect to PostgreSQL,\nMySQL, MongoDB or any database, does NOT read a connection string or .env, does NOT load an ORM/driver,\nand does NOT execute any query. It operates only on the local JSON file you pass with --input, which is\nan intermediate/offline representation of an introspection — not a live schema read. Connecting to real\ndatasources is a separate, not-yet-implemented step.\n\nThis command does NOT create a Maestro engine (no createMaestro()), does NOT execute operations, and\ndoes NOT require declared operations to have an implementation. It never modifies the input file.\n\nUsage:\n maestro introspect --input <path> [--out <path>]\n maestro introspect -i <path>\n\nFlags:\n --input, -i <path> Required. Path to a local IntrospectionResult JSON file.\n --out <path> Optional. Write the canonical artifact to this file instead of stdout.\n\nInput format (JSON — the core's IntrospectionResult contract):\n {\n \"entities\": [\n {\n \"table\": \"users\",\n \"fields\": [\n { \"name\": \"id\", \"nativeType\": \"uuid\", \"type\": \"uuid\", \"nullable\": false, \"isPrimaryKey\": true }\n ]\n }\n ],\n \"relations\": [\n {\n \"id\": \"orders.user_id->users.id\",\n \"type\": \"many-to-one\",\n \"from\": { \"table\": \"orders\", \"field\": \"user_id\" },\n \"to\": { \"table\": \"users\", \"field\": \"id\" },\n \"confidence\": \"definite\"\n }\n ]\n }\n\nOutput format (JSON):\n {\n \"schemaVersion\": 1,\n \"kind\": \"maestro.introspection\",\n \"source\": { \"path\": \"<the --input value>\" },\n \"summary\": { \"entities\": N, \"relations\": N },\n \"result\": { \"entities\": [...], \"relations\": [...] }\n }\n\nDeterminism:\n Entities are sorted by table, relations by id, and every object key is sorted. No timestamps,\n absolute paths or hashes are ever included.\n\nDifference from other commands:\n - introspect: validates/canonicalizes an IntrospectionResult (real DB-schema contract), offline.\n - snapshot: canonicalizes a declarative config file (maestro.config.yaml/json).\n - diff: compares two declarative config files.\n\nExit codes:\n 0 The input is a valid IntrospectionResult and the artifact was produced.\n 1 Usage, file-read, parse, validation or write error.\n\nExamples:\n maestro introspect --input ./introspection.json\n maestro introspect -i ./introspection.json\n maestro introspect --input ./introspection.json --out ./maestro.introspection.json`;\n\n/**\n * `maestro introspect` — reads a local `IntrospectionResult` JSON file, validates it against the core's\n * introspection contract, then emits a canonical, deterministic JSON artifact. It is offline/local only:\n * it never connects to a database/provider, never reads a connection string or `.env`, never loads a\n * driver/ORM, never calls `createMaestro()`, and never executes operations. It never modifies the input.\n * Exit codes: 0 = artifact produced, 1 = any error.\n */\nexport function createIntrospectCommand(deps: IntrospectCommandDeps = defaultDeps): Command {\n return {\n name: 'introspect',\n description: 'Validate and canonicalize a local IntrospectionResult JSON file (offline)',\n helpText: INTROSPECT_HELP_TEXT,\n run(context: CommandContext): number {\n const parsed = parseIntrospectArgs(context.argv);\n if (!parsed.ok) {\n context.stderr(`maestro introspect: ${parsed.error}`);\n return 1;\n }\n const { input, out } = parsed.value;\n\n let content: string;\n try {\n content = deps.readFile(input);\n } catch (error) {\n context.stderr(`maestro introspect: could not read input file '${input}': ${errorMessage(error)}`);\n return 1;\n }\n\n let raw: unknown;\n try {\n raw = JSON.parse(content);\n } catch (error) {\n context.stderr(`maestro introspect: invalid JSON in '${input}': ${errorMessage(error)}`);\n return 1;\n }\n\n const validated = validateIntrospectionResult(raw);\n if (!validated.ok) {\n context.stderr(`maestro introspect: ${validated.error}`);\n return 1;\n }\n\n const artifact = buildIntrospectionArtifact(validated.value, { path: input });\n const output = serializeIntrospection(artifact);\n\n if (out) {\n try {\n deps.writeFile(out, output);\n } catch (error) {\n context.stderr(`maestro introspect: could not write output file '${out}': ${errorMessage(error)}`);\n return 1;\n }\n context.stdout(`Introspection written: ${out}`);\n context.stdout(`Entities: ${artifact.summary.entities}`);\n context.stdout(`Relations: ${artifact.summary.relations}`);\n } else {\n context.stdout(output.replace(/\\n$/, ''));\n }\n\n return 0;\n },\n };\n}\n","import { CommandRegistry } from './commands/registry.js';\nimport { parseArgs } from './parseArgs.js';\nimport { formatHelp } from './help.js';\nimport { getCliVersion } from './version.js';\nimport { createGenerateCommand } from './commands/generate/GenerateCommand.js';\nimport { createValidateCommand } from './commands/validate/ValidateCommand.js';\nimport { createDiffCommand } from './commands/diff/DiffCommand.js';\nimport { createSnapshotCommand } from './commands/snapshot/SnapshotCommand.js';\nimport { createIntrospectCommand } from './commands/introspect/IntrospectCommand.js';\n\n/** Real, registered commands. Future phases register new commands here as they're implemented. */\nexport const defaultRegistry = new CommandRegistry();\ndefaultRegistry.register(createGenerateCommand());\ndefaultRegistry.register(createValidateCommand());\ndefaultRegistry.register(createDiffCommand());\ndefaultRegistry.register(createSnapshotCommand());\ndefaultRegistry.register(createIntrospectCommand());\n\nexport interface RunCliOptions {\n argv: string[];\n stdout?: (message: string) => void;\n stderr?: (message: string) => void;\n registry?: CommandRegistry;\n}\n\n/** Parses argv, dispatches to a registered command (or --help/--version), and returns the process exit code. */\nexport async function runCli(options: RunCliOptions): Promise<number> {\n const stdout = options.stdout ?? ((message: string) => console.log(message));\n const stderr = options.stderr ?? ((message: string) => console.error(message));\n const registry = options.registry ?? defaultRegistry;\n const parsed = parseArgs(options.argv);\n\n if (parsed.version) {\n stdout(getCliVersion());\n return 0;\n }\n\n const command = parsed.command ? registry.get(parsed.command) : undefined;\n\n if (parsed.help) {\n // A command with its own help text wins; otherwise (no command, or an unknown one) fall back to the global help.\n stdout(command?.helpText ?? formatHelp(registry));\n return 0;\n }\n\n if (!parsed.command) {\n stdout(formatHelp(registry));\n return 0;\n }\n\n if (!command) {\n stderr(`Unknown command '${parsed.command}'. Run \"maestro --help\" to see available commands.`);\n return 1;\n }\n\n return command.run({ argv: parsed.args, stdout, stderr });\n}\n"],"mappings":"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","names":["require","parseFlags","key","readFileSync","YAML","defaultDeps","readFileSync","errorMessage","ALIASES","parseFlags","key","readFileSync","extname","YAML","loadDeclarativeConfigFromString","defaultDeps","readFileSync","errorMessage","yamlParser","resolveFormat","extname","loadDeclarativeConfigFromString","ALIASES","parseFlags","key","readFileSync","writeFileSync","extname","YAML","loadDeclarativeConfigFromString","defaultDeps","readFileSync","writeFileSync","errorMessage","yamlParser","resolveFormat","extname","loadDeclarativeConfigFromString","ALIASES","parseFlags","key","sortKeys","readFileSync","writeFileSync","defaultDeps","readFileSync","writeFileSync","errorMessage"]}
package/dist/cli.js CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  runCli
4
- } from "./chunk-CSDLIL7L.js";
4
+ } from "./chunk-IZKOQGEL.js";
5
5
 
6
6
  // src/cli.ts
7
7
  runCli({ argv: process.argv.slice(2) }).then((exitCode) => {
package/dist/index.d.ts CHANGED
@@ -321,10 +321,10 @@ type ValidateIntrospectionResult = {
321
321
  error: string;
322
322
  };
323
323
  /**
324
- * Validates that a parsed JSON value matches the core's `IntrospectionResult` contract closely enough
325
- * to be safely consumed downstream. Only the required (non-optional) fields of the core types are
326
- * enforced; optional derived flags (isUnique, candidateForSearch, …) are passed through untouched.
327
- * This is a local, minimal wrapper — the core exposes no public `IntrospectionResult` validator yet.
324
+ * Validates a parsed JSON value against the core's public `IntrospectionResult` contract and adapts the
325
+ * result to a single-line, CLI-friendly shape (a stderr message + exit code). All structural validation
326
+ * rules live in `@maykonpaulo/maestro-core`'s `validateIntrospectionResult` this wrapper only formats
327
+ * the core's issue list for command-line output.
328
328
  */
329
329
  declare function validateIntrospectionResult(value: unknown): ValidateIntrospectionResult;
330
330
  /**
package/dist/index.js CHANGED
@@ -27,7 +27,7 @@ import {
27
27
  serializeIntrospection,
28
28
  serializeSnapshot,
29
29
  validateIntrospectionResult
30
- } from "./chunk-CSDLIL7L.js";
30
+ } from "./chunk-IZKOQGEL.js";
31
31
  export {
32
32
  CommandRegistry,
33
33
  INTROSPECTION_KIND,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@maykonpaulo/maestro-cli",
3
- "version": "0.2.0",
3
+ "version": "0.2.1-next.0",
4
4
  "description": "Command-line interface for the Maestro declarative engine — offline generate, validate, diff, snapshot and introspect commands over @maykonpaulo/maestro-core.",
5
5
  "type": "module",
6
6
  "bin": {
@@ -24,7 +24,7 @@
24
24
  },
25
25
  "dependencies": {
26
26
  "yaml": "^2.6.0",
27
- "@maykonpaulo/maestro-core": "0.6.0"
27
+ "@maykonpaulo/maestro-core": "0.7.0-next.0"
28
28
  },
29
29
  "devDependencies": {
30
30
  "@types/node": "^22.0.0",