@zodmire/cli 0.1.1 → 0.1.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/mod.mjs +315 -18
  2. package/package.json +3 -3
package/mod.mjs CHANGED
@@ -2,8 +2,9 @@ import { register } from "node:module";
2
2
  import { mkdir, readFile, writeFile } from "node:fs/promises";
3
3
  import { fileURLToPath } from "node:url";
4
4
  import { dirname, resolve } from "node:path";
5
- import { VENDORED_FILE_MANIFEST, buildCompositionArtifacts, buildContextNormalizedSpecFromConfig, buildFileArtifactTags, buildNormalizedCompositionSpec, buildNormalizedSpecTags, buildV5ContextArtifacts, filterPerContextArtifactsForComposition, inferReconcileScopes, mergeGeneratedArtifacts, prepareAllVendoredFiles, resolveAbsoluteContextInputs, serializeCompositionSpec, serializeContextSpec } from "@zodmire/core";
6
- import { materializeOwnedArtifacts } from "@zodmire/core/materialize";
5
+ import { VENDORED_FILE_MANIFEST, buildCompositionArtifacts, buildContextNormalizedSpecFromConfig, buildFileArtifactTags, buildNormalizedCompositionSpec, buildNormalizedSpecTags, buildV5ContextArtifacts, ensureContextSupportFilesExist, filterPerContextArtifactsForComposition, generateContextArtifacts, inferReconcileScopes, mergeGeneratedArtifacts, prepareAllVendoredFiles, resolveAbsoluteContextInputs, resolveArtifactOwnership, serializeCompositionSpec, serializeContextSpec, validateContextImports } from "@zodmire/core";
6
+ import { MaterializationManifestSchema, getPersistedMaterializationManifestPath, materializeOwnedArtifacts } from "@zodmire/core/materialize";
7
+ import { CompositionConfigSchema } from "@zodmire/config";
7
8
  import { statSync } from "node:fs";
8
9
  import { spawn } from "node:child_process";
9
10
 
@@ -109,10 +110,10 @@ async function mirrorToSwampDataLayer(opts) {
109
110
  //#region packages/cli/generate.ts
110
111
  async function runGenerate(opts) {
111
112
  const configPath = opts.configPath.startsWith("/") ? opts.configPath : `${process.cwd()}/${opts.configPath}`;
112
- if (opts.composition) await runCompositionGenerate(configPath, opts.targetOverride, opts.versionData);
113
- else await runContextGenerate(configPath, opts.targetOverride, opts.versionData);
113
+ if (opts.composition) await runCompositionGenerate(configPath, opts.targetOverride, opts.versionData, opts.dryRun);
114
+ else await runContextGenerate(configPath, opts.targetOverride, opts.versionData, opts.dryRun);
114
115
  }
115
- async function runContextGenerate(configPath, targetOverride, versionData) {
116
+ async function runContextGenerate(configPath, targetOverride, versionData, dryRun) {
116
117
  const resolvedInputs = await resolveAbsoluteContextInputs(configPath);
117
118
  const config = resolvedInputs.config;
118
119
  const codegenSupportPath = resolvedInputs.codegenSupportPath;
@@ -120,13 +121,21 @@ async function runContextGenerate(configPath, targetOverride, versionData) {
120
121
  console.log(` codegen support: ${codegenSupportPath}`);
121
122
  const artifacts = await buildV5ContextArtifacts({
122
123
  contextConfigPath: configPath,
123
- codegenSupportPath
124
+ codegenSupportPath,
125
+ generation: config.generation
124
126
  });
125
127
  const targetRoot = targetOverride ?? config.materialization?.targetRoot;
126
128
  if (!targetRoot) throw new Error("No --target specified and context config has no materialization.targetRoot");
127
129
  const resolvedTarget = targetRoot.startsWith("/") ? targetRoot : `${process.cwd()}/${targetRoot}`;
128
130
  console.log(` target: ${resolvedTarget}`);
129
- const result = await materializeOwnedArtifacts(resolvedTarget, artifacts, GENERATOR_VERSION, { reconcileScopes: inferReconcileScopes(artifacts) });
131
+ const result = await materializeOwnedArtifacts(resolvedTarget, artifacts, GENERATOR_VERSION, {
132
+ reconcileScopes: inferReconcileScopes(artifacts),
133
+ dryRun
134
+ });
135
+ if (dryRun) {
136
+ printDryRunSummary(resolvedTarget, result);
137
+ return;
138
+ }
130
139
  if (versionData) {
131
140
  if (!isSwampRepoAvailable()) throw new Error("Swamp repo not initialized. Run `swamp init` or omit --version-data");
132
141
  const contextSpec = await buildContextNormalizedSpecFromConfig({
@@ -159,12 +168,27 @@ async function runContextGenerate(configPath, targetOverride, versionData) {
159
168
  }
160
169
  console.log(`\nMaterialized ${result.files.length} files to ${result.targetRoot}`);
161
170
  }
162
- async function runCompositionGenerate(compositionConfigPath, targetOverride, versionData) {
163
- const compositionConfig = (await import(new URL(compositionConfigPath, "file:///").href)).default;
171
+ function printDryRunSummary(target, result) {
172
+ const counts = {
173
+ write: 0,
174
+ overwrite: 0,
175
+ conflict: 0,
176
+ skip: 0,
177
+ delete: 0
178
+ };
179
+ for (const file of result.files) counts[file.action] = (counts[file.action] ?? 0) + 1;
180
+ console.log(`\nDry run for ${target}:`);
181
+ console.log(` write: ${counts.write} files`);
182
+ console.log(` overwrite: ${counts.overwrite} files`);
183
+ console.log(` delete: ${counts.delete} files`);
184
+ console.log(` skip: ${counts.skip} files`);
185
+ }
186
+ async function runCompositionGenerate(compositionConfigPath, targetOverride, versionData, dryRun) {
187
+ const configModule = await import(new URL(compositionConfigPath, "file:///").href);
188
+ const compositionConfig = CompositionConfigSchema.parse(configModule.default);
164
189
  const targetRoot = targetOverride ?? compositionConfig.materialization?.targetRoot;
165
190
  if (!targetRoot) throw new Error("No --target specified and composition config has no materialization.targetRoot");
166
191
  const resolvedTarget = targetRoot.startsWith("/") ? targetRoot : `${process.cwd()}/${targetRoot}`;
167
- if (!compositionConfig.contextConfigs || compositionConfig.contextConfigs.length === 0) throw new Error("Composition config must include contextConfigs array with { contextConfigPath, codegenSupportPath } entries");
168
192
  const compositionDir = compositionConfigPath.substring(0, compositionConfigPath.lastIndexOf("/") + 1);
169
193
  const resolvedContextConfigs = compositionConfig.contextConfigs.map((cfg) => ({
170
194
  contextConfigPath: cfg.contextConfigPath.startsWith("/") ? cfg.contextConfigPath : compositionDir + cfg.contextConfigPath.replace(/^\.\//, ""),
@@ -173,14 +197,21 @@ async function runCompositionGenerate(compositionConfigPath, targetOverride, ver
173
197
  console.log(`Generating composition from ${compositionConfigPath}`);
174
198
  console.log(` contexts: ${resolvedContextConfigs.length}`);
175
199
  const contextSpecs = await Promise.all(resolvedContextConfigs.map((cfg) => buildContextNormalizedSpecFromConfig(cfg)));
176
- const perContextArtifacts = await Promise.all(resolvedContextConfigs.map((cfg) => buildV5ContextArtifacts(cfg)));
200
+ const compositionSpec = buildNormalizedCompositionSpec(compositionConfig, contextSpecs);
201
+ const perContextArtifacts = contextSpecs.map((contextSpec) => generateContextArtifacts(contextSpec, { infrastructureStrategy: compositionSpec.infrastructure }));
177
202
  const compositionArtifacts = await buildCompositionArtifacts(compositionConfigPath, contextSpecs);
178
203
  const allArtifacts = mergeGeneratedArtifacts(...perContextArtifacts.map(filterPerContextArtifactsForComposition), compositionArtifacts).sort((a, b) => a.logicalPath.localeCompare(b.logicalPath));
179
204
  console.log(` target: ${resolvedTarget}`);
180
- const result = await materializeOwnedArtifacts(resolvedTarget, allArtifacts, GENERATOR_VERSION, { reconcileScopes: inferReconcileScopes(allArtifacts) });
205
+ const result = await materializeOwnedArtifacts(resolvedTarget, allArtifacts, GENERATOR_VERSION, {
206
+ reconcileScopes: inferReconcileScopes(allArtifacts),
207
+ dryRun
208
+ });
209
+ if (dryRun) {
210
+ printDryRunSummary(resolvedTarget, result);
211
+ return;
212
+ }
181
213
  if (versionData) {
182
214
  if (!isSwampRepoAvailable()) throw new Error("Swamp repo not initialized. Run `swamp init` or omit --version-data");
183
- const compositionSpec = buildNormalizedCompositionSpec(compositionConfig, contextSpecs);
184
215
  const specJson = serializeCompositionSpec(compositionSpec, GENERATOR_VERSION);
185
216
  const generationRunId = `run-${(/* @__PURE__ */ new Date()).toISOString()}-${crypto.randomUUID().slice(0, 8)}`;
186
217
  console.log(" mirroring to Swamp data layer...");
@@ -208,6 +239,211 @@ async function runCompositionGenerate(compositionConfigPath, targetOverride, ver
208
239
  console.log(`\nMaterialized ${result.files.length} files to ${result.targetRoot}`);
209
240
  }
210
241
 
242
+ //#endregion
243
+ //#region packages/cli/validate.ts
244
+ async function runCheck(name, fn) {
245
+ try {
246
+ await fn();
247
+ return {
248
+ name,
249
+ pass: true
250
+ };
251
+ } catch (error) {
252
+ return {
253
+ name,
254
+ pass: false,
255
+ error: error instanceof Error ? error.message : String(error)
256
+ };
257
+ }
258
+ }
259
+ async function runValidate(opts) {
260
+ const configPath = opts.configPath.startsWith("/") ? opts.configPath : `${process.cwd()}/${opts.configPath}`;
261
+ const results = [];
262
+ if (opts.composition) {
263
+ results.push(await runCheck("composition-config-import", async () => {
264
+ const configModule = await import(new URL(configPath, "file:///").href);
265
+ CompositionConfigSchema.parse(configModule.default);
266
+ }));
267
+ results.push(await runCheck("composition-context-configs", async () => {
268
+ const configModule = await import(new URL(configPath, "file:///").href);
269
+ const compositionConfig = CompositionConfigSchema.parse(configModule.default);
270
+ const compositionDir = configPath.substring(0, configPath.lastIndexOf("/") + 1);
271
+ for (const cfg of compositionConfig.contextConfigs) {
272
+ const contextConfigPath = cfg.contextConfigPath.startsWith("/") ? cfg.contextConfigPath : compositionDir + cfg.contextConfigPath.replace(/^\.\//, "");
273
+ const codegenSupportPath = cfg.codegenSupportPath.startsWith("/") ? cfg.codegenSupportPath : compositionDir + cfg.codegenSupportPath.replace(/^\.\//, "");
274
+ const resolved = await resolveAbsoluteContextInputs(contextConfigPath);
275
+ await ensureContextSupportFilesExist(resolved);
276
+ await validateContextImports({
277
+ ...resolved,
278
+ codegenSupportPath
279
+ });
280
+ }
281
+ }));
282
+ } else {
283
+ results.push(await runCheck("context-inputs-resolve", async () => {
284
+ await resolveAbsoluteContextInputs(configPath);
285
+ }));
286
+ results.push(await runCheck("schema-files-exist", async () => {
287
+ await ensureContextSupportFilesExist(await resolveAbsoluteContextInputs(configPath));
288
+ }));
289
+ results.push(await runCheck("schema-imports-parse", async () => {
290
+ await validateContextImports(await resolveAbsoluteContextInputs(configPath));
291
+ }));
292
+ }
293
+ let hasFailure = false;
294
+ for (const result of results) {
295
+ const icon = result.pass ? "✓" : "✗";
296
+ console.log(` ${icon} ${result.name}`);
297
+ if (!result.pass && result.error) {
298
+ console.log(` ${result.error}`);
299
+ hasFailure = true;
300
+ }
301
+ }
302
+ if (hasFailure) {
303
+ console.log("\nValidation failed.");
304
+ process.exit(1);
305
+ } else console.log("\nAll checks passed.");
306
+ }
307
+
308
+ //#endregion
309
+ //#region packages/cli/inspect.ts
310
+ async function runInspect(opts) {
311
+ const configPath = opts.configPath.startsWith("/") ? opts.configPath : `${process.cwd()}/${opts.configPath}`;
312
+ if (opts.composition) await runCompositionInspect(configPath);
313
+ else await runContextInspect(configPath);
314
+ }
315
+ async function runContextInspect(configPath) {
316
+ const codegenSupportPath = (await resolveAbsoluteContextInputs(configPath)).codegenSupportPath;
317
+ const json = serializeContextSpec(await buildContextNormalizedSpecFromConfig({
318
+ contextConfigPath: configPath,
319
+ codegenSupportPath
320
+ }), GENERATOR_VERSION);
321
+ console.log(json);
322
+ }
323
+ async function runCompositionInspect(compositionConfigPath) {
324
+ const configModule = await import(new URL(compositionConfigPath, "file:///").href);
325
+ const compositionConfig = CompositionConfigSchema.parse(configModule.default);
326
+ const compositionDir = compositionConfigPath.substring(0, compositionConfigPath.lastIndexOf("/") + 1);
327
+ const resolvedContextConfigs = compositionConfig.contextConfigs.map((cfg) => ({
328
+ contextConfigPath: cfg.contextConfigPath.startsWith("/") ? cfg.contextConfigPath : compositionDir + cfg.contextConfigPath.replace(/^\.\//, ""),
329
+ codegenSupportPath: cfg.codegenSupportPath.startsWith("/") ? cfg.codegenSupportPath : compositionDir + cfg.codegenSupportPath.replace(/^\.\//, "")
330
+ }));
331
+ const json = serializeCompositionSpec(buildNormalizedCompositionSpec(compositionConfig, await Promise.all(resolvedContextConfigs.map((cfg) => buildContextNormalizedSpecFromConfig(cfg)))), GENERATOR_VERSION);
332
+ console.log(json);
333
+ }
334
+
335
+ //#endregion
336
+ //#region packages/cli/plan_cmd.ts
337
+ async function runPlan(opts) {
338
+ const configPath = opts.configPath.startsWith("/") ? opts.configPath : `${process.cwd()}/${opts.configPath}`;
339
+ if (opts.composition) await runCompositionPlan(configPath);
340
+ else await runContextPlan(configPath);
341
+ }
342
+ async function runContextPlan(configPath) {
343
+ const codegenSupportPath = (await resolveAbsoluteContextInputs(configPath)).codegenSupportPath;
344
+ printPlan(configPath, await buildV5ContextArtifacts({
345
+ contextConfigPath: configPath,
346
+ codegenSupportPath
347
+ }));
348
+ }
349
+ async function runCompositionPlan(compositionConfigPath) {
350
+ const configModule = await import(new URL(compositionConfigPath, "file:///").href);
351
+ const compositionConfig = CompositionConfigSchema.parse(configModule.default);
352
+ const compositionDir = compositionConfigPath.substring(0, compositionConfigPath.lastIndexOf("/") + 1);
353
+ const resolvedContextConfigs = compositionConfig.contextConfigs.map((cfg) => ({
354
+ contextConfigPath: cfg.contextConfigPath.startsWith("/") ? cfg.contextConfigPath : compositionDir + cfg.contextConfigPath.replace(/^\.\//, ""),
355
+ codegenSupportPath: cfg.codegenSupportPath.startsWith("/") ? cfg.codegenSupportPath : compositionDir + cfg.codegenSupportPath.replace(/^\.\//, "")
356
+ }));
357
+ const contextSpecs = await Promise.all(resolvedContextConfigs.map((cfg) => buildContextNormalizedSpecFromConfig(cfg)));
358
+ const compositionSpec = buildNormalizedCompositionSpec(compositionConfig, contextSpecs);
359
+ const perContextArtifacts = contextSpecs.map((contextSpec) => generateContextArtifacts(contextSpec, { infrastructureStrategy: compositionSpec.infrastructure }));
360
+ const compositionArtifacts = await buildCompositionArtifacts(compositionConfigPath, contextSpecs);
361
+ printPlan(compositionConfigPath, mergeGeneratedArtifacts(...perContextArtifacts.map(filterPerContextArtifactsForComposition), compositionArtifacts).sort((a, b) => a.logicalPath.localeCompare(b.logicalPath)));
362
+ }
363
+ function printPlan(configPath, artifacts) {
364
+ console.log(`Plan for ${configPath}:`);
365
+ for (const artifact of artifacts) {
366
+ const label = `[${resolveArtifactOwnership(artifact).ownershipScope}]`;
367
+ console.log(` ${label.padEnd(16)} ${artifact.logicalPath}`);
368
+ }
369
+ console.log(`\n${artifacts.length} artifacts would be generated.`);
370
+ }
371
+
372
+ //#endregion
373
+ //#region packages/cli/diff.ts
374
+ async function runDiff(opts) {
375
+ const configPath = opts.configPath.startsWith("/") ? opts.configPath : `${process.cwd()}/${opts.configPath}`;
376
+ if (opts.composition) await runCompositionDiff(configPath, opts.targetOverride);
377
+ else await runContextDiff(configPath, opts.targetOverride);
378
+ }
379
+ async function runContextDiff(configPath, targetOverride) {
380
+ const resolvedInputs = await resolveAbsoluteContextInputs(configPath);
381
+ const config = resolvedInputs.config;
382
+ const codegenSupportPath = resolvedInputs.codegenSupportPath;
383
+ const artifacts = await buildV5ContextArtifacts({
384
+ contextConfigPath: configPath,
385
+ codegenSupportPath
386
+ });
387
+ const targetRoot = targetOverride ?? config.materialization?.targetRoot;
388
+ if (!targetRoot) throw new Error("No --target specified and context config has no materialization.targetRoot");
389
+ printDiff(targetRoot.startsWith("/") ? targetRoot : `${process.cwd()}/${targetRoot}`, artifacts);
390
+ }
391
+ async function runCompositionDiff(compositionConfigPath, targetOverride) {
392
+ const configModule = await import(new URL(compositionConfigPath, "file:///").href);
393
+ const compositionConfig = CompositionConfigSchema.parse(configModule.default);
394
+ const targetRoot = targetOverride ?? compositionConfig.materialization?.targetRoot;
395
+ if (!targetRoot) throw new Error("No --target specified and composition config has no materialization.targetRoot");
396
+ const resolvedTarget = targetRoot.startsWith("/") ? targetRoot : `${process.cwd()}/${targetRoot}`;
397
+ const compositionDir = compositionConfigPath.substring(0, compositionConfigPath.lastIndexOf("/") + 1);
398
+ const resolvedContextConfigs = compositionConfig.contextConfigs.map((cfg) => ({
399
+ contextConfigPath: cfg.contextConfigPath.startsWith("/") ? cfg.contextConfigPath : compositionDir + cfg.contextConfigPath.replace(/^\.\//, ""),
400
+ codegenSupportPath: cfg.codegenSupportPath.startsWith("/") ? cfg.codegenSupportPath : compositionDir + cfg.codegenSupportPath.replace(/^\.\//, "")
401
+ }));
402
+ const contextSpecs = await Promise.all(resolvedContextConfigs.map((cfg) => buildContextNormalizedSpecFromConfig(cfg)));
403
+ const compositionSpec = buildNormalizedCompositionSpec(compositionConfig, contextSpecs);
404
+ const perContextArtifacts = contextSpecs.map((contextSpec) => generateContextArtifacts(contextSpec, { infrastructureStrategy: compositionSpec.infrastructure }));
405
+ const compositionArtifacts = await buildCompositionArtifacts(compositionConfigPath, contextSpecs);
406
+ printDiff(resolvedTarget, mergeGeneratedArtifacts(...perContextArtifacts.map(filterPerContextArtifactsForComposition), compositionArtifacts).sort((a, b) => a.logicalPath.localeCompare(b.logicalPath)));
407
+ }
408
+ async function printDiff(targetRoot, artifacts) {
409
+ const manifestPath = getPersistedMaterializationManifestPath(targetRoot);
410
+ let manifestEntries;
411
+ try {
412
+ const manifestText = await readFile(manifestPath, "utf-8");
413
+ const manifest = MaterializationManifestSchema.parse(JSON.parse(manifestText));
414
+ manifestEntries = new Set(manifest.files.map((f) => f.logicalPath));
415
+ } catch (error) {
416
+ if (error.code === "ENOENT") {
417
+ console.log(`No existing manifest found at ${manifestPath}`);
418
+ console.log(`All ${artifacts.length} artifacts would be new.\n`);
419
+ for (const artifact of artifacts) console.log(` + ${artifact.logicalPath}`);
420
+ return;
421
+ }
422
+ throw error;
423
+ }
424
+ const plannedPaths = new Set(artifacts.map((a) => a.logicalPath));
425
+ const added = [];
426
+ const removed = [];
427
+ const unchanged = [];
428
+ for (const artifact of artifacts) if (manifestEntries.has(artifact.logicalPath)) unchanged.push(artifact.logicalPath);
429
+ else added.push(artifact.logicalPath);
430
+ for (const existingPath of manifestEntries) if (!plannedPaths.has(existingPath)) removed.push(existingPath);
431
+ console.log(`Diff against ${manifestPath}:\n`);
432
+ if (added.length > 0) {
433
+ console.log(` Added (${added.length}):`);
434
+ for (const path of added) console.log(` + ${path}`);
435
+ }
436
+ if (removed.length > 0) {
437
+ console.log(` Removed (${removed.length}):`);
438
+ for (const path of removed) console.log(` - ${path}`);
439
+ }
440
+ if (unchanged.length > 0) {
441
+ console.log(` Unchanged (${unchanged.length}):`);
442
+ for (const path of unchanged) console.log(` = ${path}`);
443
+ }
444
+ console.log(`\nSummary: ${added.length} added, ${removed.length} removed, ${unchanged.length} unchanged`);
445
+ }
446
+
211
447
  //#endregion
212
448
  //#region packages/cli/mod.ts
213
449
  register(`data:text/javascript,${encodeURIComponent(`
@@ -226,20 +462,29 @@ function printUsage() {
226
462
 
227
463
  Usage:
228
464
  zodmire init --target <dir>
229
- zodmire generate --config <path> [--composition] [--target <dir>] [--version-data]
465
+ zodmire generate --config <path> [--composition] [--target <dir>] [--version-data] [--dry-run]
466
+ zodmire validate --config <path> [--composition]
467
+ zodmire inspect-spec --config <path> [--composition]
468
+ zodmire plan --config <path> [--composition] [--target <dir>]
469
+ zodmire diff --config <path> [--composition] [--target <dir>]
230
470
  zodmire --version
231
471
  zodmire --help
232
472
 
233
473
  Commands:
234
- init Scaffold codegen helper files into your project
235
- generate Generate a bounded context skeleton from Zod schemas
474
+ init Scaffold codegen helper files into your project
475
+ generate Generate a bounded context skeleton from Zod schemas
476
+ validate Run pre-flight checks on context or composition configs
477
+ inspect-spec Print the normalized spec as JSON
478
+ plan Show what artifacts would be generated
479
+ diff Compare planned output against existing manifest
236
480
 
237
481
  Options:
238
482
  --target For init: directory to write helpers into
239
- For generate: override materialization target directory
483
+ For generate/plan/diff: override materialization target directory
240
484
  --config Path to context config (.context.ts) or composition config
241
485
  --composition Treat --config as a composition config (multi-context)
242
486
  --version-data Mirror artifacts to Swamp data layer (requires .swamp/ repo)
487
+ --dry-run Run full pipeline but skip file writes (generate only)
243
488
  --version Print version
244
489
  --help Print this help
245
490
  `);
@@ -252,6 +497,7 @@ function parseArgs(args) {
252
497
  const arg = args[i];
253
498
  if (arg === "--composition") flags.composition = true;
254
499
  else if (arg === "--version-data") flags["version-data"] = true;
500
+ else if (arg === "--dry-run") flags["dry-run"] = true;
255
501
  else if (arg.startsWith("--") && i + 1 < args.length && !args[i + 1].startsWith("--")) {
256
502
  flags[arg.slice(2)] = args[i + 1];
257
503
  i++;
@@ -292,7 +538,58 @@ async function main() {
292
538
  configPath: config,
293
539
  composition: flags.composition === true,
294
540
  targetOverride: typeof flags.target === "string" ? flags.target : void 0,
295
- versionData: flags["version-data"] === true
541
+ versionData: flags["version-data"] === true,
542
+ dryRun: flags["dry-run"] === true
543
+ });
544
+ break;
545
+ }
546
+ case "validate": {
547
+ const config = flags.config;
548
+ if (typeof config !== "string") {
549
+ console.error("Error: --config <path> is required for validate");
550
+ process.exit(1);
551
+ }
552
+ await runValidate({
553
+ configPath: config,
554
+ composition: flags.composition === true
555
+ });
556
+ break;
557
+ }
558
+ case "inspect-spec": {
559
+ const config = flags.config;
560
+ if (typeof config !== "string") {
561
+ console.error("Error: --config <path> is required for inspect-spec");
562
+ process.exit(1);
563
+ }
564
+ await runInspect({
565
+ configPath: config,
566
+ composition: flags.composition === true
567
+ });
568
+ break;
569
+ }
570
+ case "plan": {
571
+ const config = flags.config;
572
+ if (typeof config !== "string") {
573
+ console.error("Error: --config <path> is required for plan");
574
+ process.exit(1);
575
+ }
576
+ await runPlan({
577
+ configPath: config,
578
+ composition: flags.composition === true,
579
+ targetOverride: typeof flags.target === "string" ? flags.target : void 0
580
+ });
581
+ break;
582
+ }
583
+ case "diff": {
584
+ const config = flags.config;
585
+ if (typeof config !== "string") {
586
+ console.error("Error: --config <path> is required for diff");
587
+ process.exit(1);
588
+ }
589
+ await runDiff({
590
+ configPath: config,
591
+ composition: flags.composition === true,
592
+ targetOverride: typeof flags.target === "string" ? flags.target : void 0
296
593
  });
297
594
  break;
298
595
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zodmire/cli",
3
- "version": "0.1.1",
3
+ "version": "0.1.3",
4
4
  "license": "MIT",
5
5
  "type": "module",
6
6
  "main": "./mod.mjs",
@@ -13,8 +13,8 @@
13
13
  }
14
14
  },
15
15
  "dependencies": {
16
- "@zodmire/config": "^0.1.1",
17
- "@zodmire/core": "^0.1.1"
16
+ "@zodmire/config": "^0.1.3",
17
+ "@zodmire/core": "^0.1.3"
18
18
  },
19
19
  "bin": {
20
20
  "zodmire": "./bin/zodmire.js"