declastruct 1.7.3 → 1.9.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.
Files changed (29) hide show
  1. package/dist/contract/cli/apply.js +47 -13
  2. package/dist/contract/cli/apply.js.map +1 -1
  3. package/dist/contract/cli/invoke.js +45 -5
  4. package/dist/contract/cli/invoke.js.map +1 -1
  5. package/dist/contract/cli/plan.d.ts +3 -1
  6. package/dist/contract/cli/plan.js +56 -17
  7. package/dist/contract/cli/plan.js.map +1 -1
  8. package/dist/domain.objects/ContextDeclastructCli.d.ts +15 -0
  9. package/dist/domain.objects/ContextDeclastructCli.js +3 -0
  10. package/dist/domain.objects/ContextDeclastructCli.js.map +1 -0
  11. package/dist/domain.objects/DeclastructPlan.d.ts +7 -1
  12. package/dist/domain.objects/DeclastructPlan.js.map +1 -1
  13. package/dist/domain.objects/DeclastructSnapshot.d.ts +54 -0
  14. package/dist/domain.objects/DeclastructSnapshot.js +15 -0
  15. package/dist/domain.objects/DeclastructSnapshot.js.map +1 -0
  16. package/dist/domain.operations/apply/applyChanges.d.ts +2 -1
  17. package/dist/domain.operations/apply/applyChanges.js +26 -7
  18. package/dist/domain.operations/apply/applyChanges.js.map +1 -1
  19. package/dist/domain.operations/plan/planChanges.d.ts +6 -1
  20. package/dist/domain.operations/plan/planChanges.js +49 -9
  21. package/dist/domain.operations/plan/planChanges.js.map +1 -1
  22. package/dist/infra/asIndentedLines.d.ts +8 -0
  23. package/dist/infra/asIndentedLines.js +15 -0
  24. package/dist/infra/asIndentedLines.js.map +1 -0
  25. package/dist/infra/initializeProviders.d.ts +15 -0
  26. package/dist/infra/initializeProviders.js +20 -0
  27. package/dist/infra/initializeProviders.js.map +1 -0
  28. package/package.json +10 -5
  29. package/readme.md +42 -0
@@ -36,6 +36,7 @@ const path_1 = require("path");
36
36
  const rhachet_artifact_git_1 = require("rhachet-artifact-git");
37
37
  const DeclastructPlan_1 = require("../../domain.objects/DeclastructPlan");
38
38
  const applyChanges_1 = require("../../domain.operations/apply/applyChanges");
39
+ const initializeProviders_1 = require("../../infra/initializeProviders");
39
40
  const log = console;
40
41
  /**
41
42
  * .what = executes the apply command to apply infrastructure changes
@@ -50,12 +51,16 @@ const executeApplyCommand = async (input) => {
50
51
  if (isYoloMode) {
51
52
  // yolo mode requires --wish
52
53
  if (!input.wishFilePath)
53
- throw new helpful_errors_1.BadRequestError('--wish required when --plan yolo');
54
+ throw new helpful_errors_1.BadRequestError('--wish required when --plan yolo', {
55
+ hint: 'add --wish <file> to specify the wish file',
56
+ });
54
57
  }
55
58
  else {
56
59
  // standard mode requires --plan (not "yolo")
57
60
  if (!input.planFilePath)
58
- throw new helpful_errors_1.BadRequestError('--plan required');
61
+ throw new helpful_errors_1.BadRequestError('--plan required', {
62
+ hint: 'add --plan <file> to specify the plan file',
63
+ });
59
64
  }
60
65
  // resolve plan path (null for yolo mode)
61
66
  const resolvedPlanPath = isYoloMode
@@ -66,7 +71,10 @@ const executeApplyCommand = async (input) => {
66
71
  if (!resolvedPlanPath)
67
72
  return null;
68
73
  if (!(0, fs_1.existsSync)(resolvedPlanPath))
69
- throw new helpful_errors_1.BadRequestError(`Plan file not found: ${resolvedPlanPath}`);
74
+ throw new helpful_errors_1.BadRequestError('plan file not found', {
75
+ path: resolvedPlanPath,
76
+ hint: 'check that the --plan path points to an extant file',
77
+ });
70
78
  const planJson = await (0, promises_1.readFile)(resolvedPlanPath, 'utf-8');
71
79
  return new DeclastructPlan_1.DeclastructPlan(JSON.parse(planJson));
72
80
  })();
@@ -76,7 +84,10 @@ const executeApplyCommand = async (input) => {
76
84
  : plan.wish.uri;
77
85
  // validate wish file exists
78
86
  if (!(0, fs_1.existsSync)(resolvedWishPath))
79
- throw new helpful_errors_1.BadRequestError(`Wish file not found: ${resolvedWishPath}`);
87
+ throw new helpful_errors_1.BadRequestError('wish file not found', {
88
+ path: resolvedWishPath,
89
+ hint: 'check that the wish file path is correct',
90
+ });
80
91
  // get git root for relative path display
81
92
  const gitRoot = await (0, rhachet_artifact_git_1.getGitRepoRoot)({ from: process.cwd() });
82
93
  const relativePlanPath = resolvedPlanPath
@@ -86,27 +97,49 @@ const executeApplyCommand = async (input) => {
86
97
  // log header
87
98
  log.info('');
88
99
  log.info('🌊 declastruct apply');
89
- if (relativePlanPath)
90
- log.info(` plan: ${relativePlanPath}`);
91
- log.info(` wish: ${relativeWishPath}`);
100
+ if (relativePlanPath) {
101
+ log.info(` ├─ plan: ${relativePlanPath}`);
102
+ log.info(` └─ wish: ${relativeWishPath}`);
103
+ }
104
+ else {
105
+ log.info(` ├─ plan: (yolo)`);
106
+ log.info(` └─ wish: ${relativeWishPath}`);
107
+ }
92
108
  log.info('');
109
+ // create cli context with passthrough args from plan
110
+ const cliContext = {
111
+ passthrough: { argv: plan?.wish.argv ?? [] },
112
+ };
113
+ // inject argv from plan so wish file sees same args as plan time
114
+ // this ensures staleness check compares same resources
115
+ process.argv = [
116
+ process.argv[0],
117
+ process.argv[1],
118
+ ...cliContext.passthrough.argv,
119
+ ];
93
120
  // import wish file
94
121
  const wish = await Promise.resolve(`${resolvedWishPath}`).then(s => __importStar(require(s)));
95
122
  // validate exports
96
123
  if (typeof wish.getResources !== 'function')
97
- throw new helpful_errors_1.BadRequestError('Wish file must export getResources() function');
124
+ throw new helpful_errors_1.BadRequestError('wish file must export getResources() function', {
125
+ path: resolvedWishPath,
126
+ hint: 'add `export const getResources = () => [...]` to the wish file',
127
+ });
98
128
  if (typeof wish.getProviders !== 'function')
99
- throw new helpful_errors_1.BadRequestError('Wish file must export getProviders() function');
129
+ throw new helpful_errors_1.BadRequestError('wish file must export getProviders() function', {
130
+ path: resolvedWishPath,
131
+ hint: 'add `export const getProviders = () => [...]` to the wish file',
132
+ });
100
133
  // get resources and providers
101
134
  const resources = await wish.getResources();
102
135
  const providers = await wish.getProviders();
103
136
  // initialize providers
104
- // log.info('✨ start providers...');
105
- await Promise.all(providers.map((p) => p.hooks.beforeAll()));
106
- // create context
137
+ await (0, initializeProviders_1.initializeProviders)({ providers });
138
+ // create context with passthrough args
107
139
  const context = {
108
140
  bottleneck: new bottleneck_1.default({ maxConcurrent: 1 }),
109
141
  log,
142
+ passthrough: cliContext.passthrough,
110
143
  };
111
144
  // apply changes (plan=null triggers yolo mode, skipping validation)
112
145
  const result = await (0, applyChanges_1.applyChanges)({
@@ -120,7 +153,8 @@ const executeApplyCommand = async (input) => {
120
153
  await Promise.all(providers.map((p) => p.hooks.afterAll()));
121
154
  // log summary
122
155
  log.info('');
123
- log.info(`🌊 applied ${result.appliedChanges.length} changes`);
156
+ log.info('🌊 declastruct apply');
157
+ log.info(` └─ applied: ${result.appliedChanges.length}`);
124
158
  log.info('');
125
159
  };
126
160
  exports.executeApplyCommand = executeApplyCommand;
@@ -1 +1 @@
1
- {"version":3,"file":"apply.js","sourceRoot":"","sources":["../../../src/contract/cli/apply.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"apply.js","sourceRoot":"","sources":["../../../src/contract/cli/apply.ts"],"names":[],"mappings":"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"}
@@ -5,10 +5,20 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.invoke = void 0;
7
7
  const commander_1 = require("commander");
8
+ const helpful_errors_1 = require("helpful-errors");
8
9
  const package_json_1 = __importDefault(require("../../../package.json"));
9
10
  const apply_1 = require("./apply");
10
11
  const plan_1 = require("./plan");
11
12
  const log = console;
13
+ /**
14
+ * .what = determines exit code based on error type
15
+ * .why = semantic exit codes let callers know if they can retry or must fix
16
+ */
17
+ const getExitCodeForError = (error) => {
18
+ if (error instanceof helpful_errors_1.BadRequestError)
19
+ return 2;
20
+ return 1;
21
+ };
12
22
  /**
13
23
  * .what = invokes CLI commands based on user input
14
24
  * .why = provides global entry point for declastruct CLI
@@ -25,16 +35,41 @@ const invoke = async ({ args }) => {
25
35
  .description('Generate a change plan from a wish file')
26
36
  .requiredOption('--wish <file>', 'Path to wish file')
27
37
  .requiredOption('--into <file>', 'Path to output plan file')
28
- .action(async (options) => {
38
+ .option('--snap <file>', 'Path to output snapshot file')
39
+ .usage('--wish <file> --into <file> [-- <wish-args>]')
40
+ .allowExcessArguments(true)
41
+ .configureOutput({
42
+ writeErr: (str) => {
43
+ // intercept unknown option errors and add hint
44
+ if (str.includes('unknown option')) {
45
+ const match = str.match(/unknown option '([^']+)'/);
46
+ const flag = match?.[1] ?? '';
47
+ log.error(str.trim());
48
+ log.error(`hint: to pass args to your wish file, use: -- ${flag}`);
49
+ }
50
+ else {
51
+ log.error(str.trim());
52
+ }
53
+ },
54
+ })
55
+ .action(async (options, command) => {
29
56
  try {
57
+ // capture args after -- separator
58
+ const passthroughArgs = command.args;
30
59
  await (0, plan_1.executePlanCommand)({
31
60
  wishFilePath: options.wish,
32
61
  planFilePath: options.into,
62
+ snapFilePath: options.snap ?? null,
63
+ passthroughArgs,
33
64
  });
34
65
  }
35
66
  catch (error) {
36
- log.error('✖ Error during plan:', error);
37
- process.exit(1);
67
+ // allowlist: BadRequestError (user must fix) and Error (malfunction)
68
+ // rethrow anything else (non-Error thrown = unexpected)
69
+ if (!(error instanceof Error))
70
+ throw error;
71
+ log.error('✖ plan failed:', error);
72
+ process.exit(getExitCodeForError(error));
38
73
  }
39
74
  });
40
75
  program
@@ -42,6 +77,7 @@ const invoke = async ({ args }) => {
42
77
  .description('Apply changes from a plan file')
43
78
  .option('--plan <file>', 'Path to plan file, or "yolo" for immediate apply')
44
79
  .option('--wish <file>', 'Path to wish file (required when --plan yolo)')
80
+ .allowExcessArguments(true) // ignore passthrough args - apply uses plan's captured state
45
81
  .action(async (options) => {
46
82
  try {
47
83
  await (0, apply_1.executeApplyCommand)({
@@ -50,8 +86,12 @@ const invoke = async ({ args }) => {
50
86
  });
51
87
  }
52
88
  catch (error) {
53
- log.error('✖ Error during apply:', error);
54
- process.exit(1);
89
+ // allowlist: BadRequestError (user must fix) and Error (malfunction)
90
+ // rethrow non-Error values (unexpected)
91
+ if (!(error instanceof Error))
92
+ throw error;
93
+ log.error('✖ apply failed:', error);
94
+ process.exit(getExitCodeForError(error));
55
95
  }
56
96
  });
57
97
  await program.parseAsync(args, { from: 'user' });
@@ -1 +1 @@
1
- {"version":3,"file":"invoke.js","sourceRoot":"","sources":["../../../src/contract/cli/invoke.ts"],"names":[],"mappings":";;;;;;AAAA,yCAAoC;AAEpC,yEAAwC;AACxC,mCAA8C;AAC9C,iCAA4C;AAE5C,MAAM,GAAG,GAAG,OAAO,CAAC;AAEpB;;;;GAIG;AACI,MAAM,MAAM,GAAG,KAAK,EAAE,EAAE,IAAI,EAAsB,EAAiB,EAAE;IAC1E,MAAM,OAAO,GAAG,IAAI,mBAAO,EAAE,CAAC;IAE9B,OAAO;SACJ,IAAI,CAAC,aAAa,CAAC;SACnB,WAAW,CAAC,wCAAwC,CAAC;SACrD,OAAO,CAAC,sBAAG,CAAC,OAAO,CAAC,CAAC;IAExB,OAAO;SACJ,OAAO,CAAC,MAAM,CAAC;SACf,WAAW,CAAC,yCAAyC,CAAC;SACtD,cAAc,CAAC,eAAe,EAAE,mBAAmB,CAAC;SACpD,cAAc,CAAC,eAAe,EAAE,0BAA0B,CAAC;SAC3D,MAAM,CAAC,KAAK,EAAE,OAAO,EAAE,EAAE;QACxB,IAAI,CAAC;YACH,MAAM,IAAA,yBAAkB,EAAC;gBACvB,YAAY,EAAE,OAAO,CAAC,IAAI;gBAC1B,YAAY,EAAE,OAAO,CAAC,IAAI;aAC3B,CAAC,CAAC;QACL,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,GAAG,CAAC,KAAK,CAAC,sBAAsB,EAAE,KAAK,CAAC,CAAC;YACzC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;IACH,CAAC,CAAC,CAAC;IAEL,OAAO;SACJ,OAAO,CAAC,OAAO,CAAC;SAChB,WAAW,CAAC,gCAAgC,CAAC;SAC7C,MAAM,CAAC,eAAe,EAAE,kDAAkD,CAAC;SAC3E,MAAM,CAAC,eAAe,EAAE,+CAA+C,CAAC;SACxE,MAAM,CAAC,KAAK,EAAE,OAAO,EAAE,EAAE;QACxB,IAAI,CAAC;YACH,MAAM,IAAA,2BAAmB,EAAC;gBACxB,YAAY,EAAE,OAAO,CAAC,IAAI;gBAC1B,YAAY,EAAE,OAAO,CAAC,IAAI;aAC3B,CAAC,CAAC;QACL,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,GAAG,CAAC,KAAK,CAAC,uBAAuB,EAAE,KAAK,CAAC,CAAC;YAC1C,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;IACH,CAAC,CAAC,CAAC;IAEL,MAAM,OAAO,CAAC,UAAU,CAAC,IAAI,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,CAAC;AACnD,CAAC,CAAC;AA3CW,QAAA,MAAM,UA2CjB"}
1
+ {"version":3,"file":"invoke.js","sourceRoot":"","sources":["../../../src/contract/cli/invoke.ts"],"names":[],"mappings":"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"}
@@ -4,7 +4,9 @@
4
4
  * .why = provides CLI interface for planning infrastructure changes
5
5
  * .note = requires wish file with getResources() and getProviders() exports
6
6
  */
7
- export declare const executePlanCommand: ({ wishFilePath, planFilePath, }: {
7
+ export declare const executePlanCommand: ({ wishFilePath, planFilePath, snapFilePath, passthroughArgs, }: {
8
8
  wishFilePath: string;
9
9
  planFilePath: string;
10
+ snapFilePath: string | null;
11
+ passthroughArgs?: string[];
10
12
  }) => Promise<void>;
@@ -35,51 +35,81 @@ const helpful_errors_1 = require("helpful-errors");
35
35
  const path_1 = require("path");
36
36
  const rhachet_artifact_git_1 = require("rhachet-artifact-git");
37
37
  const planChanges_1 = require("../../domain.operations/plan/planChanges");
38
+ const initializeProviders_1 = require("../../infra/initializeProviders");
38
39
  const log = console;
39
40
  /**
40
41
  * .what = executes the plan command to generate an infrastructure change plan
41
42
  * .why = provides CLI interface for planning infrastructure changes
42
43
  * .note = requires wish file with getResources() and getProviders() exports
43
44
  */
44
- const executePlanCommand = async ({ wishFilePath, planFilePath, }) => {
45
+ const executePlanCommand = async ({ wishFilePath, planFilePath, snapFilePath, passthroughArgs = [], }) => {
45
46
  // resolve paths
46
47
  const resolvedWishPath = (0, path_1.resolve)(process.cwd(), wishFilePath);
47
48
  const resolvedPlanPath = (0, path_1.resolve)(process.cwd(), planFilePath);
49
+ const resolvedSnapPath = snapFilePath
50
+ ? (0, path_1.resolve)(process.cwd(), snapFilePath)
51
+ : null;
48
52
  // get git root for relative path display
49
53
  const gitRoot = await (0, rhachet_artifact_git_1.getGitRepoRoot)({ from: process.cwd() });
50
54
  const relativeWishPath = (0, path_1.relative)(gitRoot, resolvedWishPath);
51
55
  const relativePlanPath = (0, path_1.relative)(gitRoot, resolvedPlanPath);
56
+ const relativeSnapPath = resolvedSnapPath
57
+ ? (0, path_1.relative)(gitRoot, resolvedSnapPath)
58
+ : null;
52
59
  // validate wish file exists
53
60
  if (!(0, fs_1.existsSync)(resolvedWishPath)) {
54
- throw new helpful_errors_1.BadRequestError(`Wish file not found: ${resolvedWishPath}`);
61
+ throw new helpful_errors_1.BadRequestError('wish file not found', {
62
+ path: resolvedWishPath,
63
+ hint: 'check that the --wish path points to an extant file',
64
+ });
55
65
  }
56
66
  log.info('');
57
67
  log.info('🌊 declastruct plan');
58
- log.info(` wish: ${relativeWishPath}`);
59
- log.info(` plan: ${relativePlanPath}`);
68
+ log.info(` ├─ wish: ${relativeWishPath}`);
69
+ log.info(` ├─ plan: ${relativePlanPath}`);
70
+ if (relativeSnapPath)
71
+ log.info(` └─ snap: ${relativeSnapPath}`);
72
+ else
73
+ log.info(` └─ snap: (none)`);
60
74
  log.info('');
61
- // import wish file
75
+ // create cli context with passthrough args
76
+ const cliContext = {
77
+ passthrough: { argv: passthroughArgs },
78
+ };
79
+ // inject passthrough args into process.argv before import
80
+ process.argv = [
81
+ process.argv[0],
82
+ process.argv[1],
83
+ ...cliContext.passthrough.argv,
84
+ ];
85
+ // import wish file (now sees passthrough.argv in process.argv)
62
86
  const wish = await Promise.resolve(`${resolvedWishPath}`).then(s => __importStar(require(s)));
63
87
  // validate exports
64
88
  if (typeof wish.getResources !== 'function') {
65
- throw new helpful_errors_1.BadRequestError('Wish file must export getResources() function');
89
+ throw new helpful_errors_1.BadRequestError('wish file must export getResources() function', {
90
+ path: resolvedWishPath,
91
+ hint: 'add `export const getResources = () => [...]` to the wish file',
92
+ });
66
93
  }
67
94
  if (typeof wish.getProviders !== 'function') {
68
- throw new helpful_errors_1.BadRequestError('Wish file must export getProviders() function');
95
+ throw new helpful_errors_1.BadRequestError('wish file must export getProviders() function', {
96
+ path: resolvedWishPath,
97
+ hint: 'add `export const getProviders = () => [...]` to the wish file',
98
+ });
69
99
  }
70
100
  // get resources and providers
71
101
  const resources = await wish.getResources();
72
102
  const providers = await wish.getProviders();
73
103
  // initialize providers
74
- // log.info('✨ start providers...');
75
- await Promise.all(providers.map((p) => p.hooks.beforeAll()));
76
- // create context
104
+ await (0, initializeProviders_1.initializeProviders)({ providers });
105
+ // create context with passthrough args
77
106
  const context = {
78
107
  bottleneck: new bottleneck_1.default({ maxConcurrent: 1 }),
79
108
  log,
109
+ passthrough: cliContext.passthrough,
80
110
  };
81
- // plan changes (logs emitted in real-time by planChanges)
82
- const plan = await (0, planChanges_1.planChanges)({
111
+ // plan changes (outputs emitted in real-time by planChanges)
112
+ const { plan, snapshot } = await (0, planChanges_1.planChanges)({
83
113
  resources,
84
114
  providers,
85
115
  wishFilePath: resolvedWishPath,
@@ -89,14 +119,23 @@ const executePlanCommand = async ({ wishFilePath, planFilePath, }) => {
89
119
  await (0, promises_1.mkdir)(planDir, { recursive: true });
90
120
  // write plan to file
91
121
  await (0, promises_1.writeFile)(resolvedPlanPath, JSON.stringify(plan, null, 2), 'utf-8');
122
+ // write snapshot to file if requested
123
+ if (resolvedSnapPath) {
124
+ const snapDir = (0, path_1.dirname)(resolvedSnapPath);
125
+ await (0, promises_1.mkdir)(snapDir, { recursive: true });
126
+ await (0, promises_1.writeFile)(resolvedSnapPath, JSON.stringify(snapshot, null, 2), 'utf-8');
127
+ }
92
128
  // cleanup providers
93
- // log.info('');
94
- // log.info('✨ stop providers...');
95
- await Promise.all(providers.map((p) => p.hooks.afterAll()));
129
+ await (0, initializeProviders_1.finalizeProviders)({ providers });
96
130
  // log summary
97
131
  log.info('');
98
- log.info(`🌊 planned for ${plan.changes.length} resources`);
99
- log.info(` into ${relativePlanPath}`);
132
+ log.info('🌊 declastruct plan');
133
+ log.info(` ├─ resources: ${plan.changes.length}`);
134
+ log.info(` ├─ plan: ${relativePlanPath}`);
135
+ if (relativeSnapPath)
136
+ log.info(` └─ snap: ${relativeSnapPath}`);
137
+ else
138
+ log.info(` └─ snap: (none)`);
100
139
  log.info('');
101
140
  };
102
141
  exports.executePlanCommand = executePlanCommand;
@@ -1 +1 @@
1
- {"version":3,"file":"plan.js","sourceRoot":"","sources":["../../../src/contract/cli/plan.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"plan.js","sourceRoot":"","sources":["../../../src/contract/cli/plan.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAEA,4DAAoC;AACpC,2BAAgC;AAChC,0CAA+C;AAC/C,mDAAiD;AACjD,+BAAkD;AAClD,+DAAsD;AAItD,yEAAsE;AACtE,wEAGwC;AAExC,MAAM,GAAG,GAAG,OAAO,CAAC;AAEpB;;;;GAIG;AACI,MAAM,kBAAkB,GAAG,KAAK,EAAE,EACvC,YAAY,EACZ,YAAY,EACZ,YAAY,EACZ,eAAe,GAAG,EAAE,GAMrB,EAAiB,EAAE;IAClB,gBAAgB;IAChB,MAAM,gBAAgB,GAAG,IAAA,cAAO,EAAC,OAAO,CAAC,GAAG,EAAE,EAAE,YAAY,CAAC,CAAC;IAC9D,MAAM,gBAAgB,GAAG,IAAA,cAAO,EAAC,OAAO,CAAC,GAAG,EAAE,EAAE,YAAY,CAAC,CAAC;IAC9D,MAAM,gBAAgB,GAAG,YAAY;QACnC,CAAC,CAAC,IAAA,cAAO,EAAC,OAAO,CAAC,GAAG,EAAE,EAAE,YAAY,CAAC;QACtC,CAAC,CAAC,IAAI,CAAC;IAET,yCAAyC;IACzC,MAAM,OAAO,GAAG,MAAM,IAAA,qCAAc,EAAC,EAAE,IAAI,EAAE,OAAO,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;IAC9D,MAAM,gBAAgB,GAAG,IAAA,eAAQ,EAAC,OAAO,EAAE,gBAAgB,CAAC,CAAC;IAC7D,MAAM,gBAAgB,GAAG,IAAA,eAAQ,EAAC,OAAO,EAAE,gBAAgB,CAAC,CAAC;IAC7D,MAAM,gBAAgB,GAAG,gBAAgB;QACvC,CAAC,CAAC,IAAA,eAAQ,EAAC,OAAO,EAAE,gBAAgB,CAAC;QACrC,CAAC,CAAC,IAAI,CAAC;IAET,4BAA4B;IAC5B,IAAI,CAAC,IAAA,eAAU,EAAC,gBAAgB,CAAC,EAAE,CAAC;QAClC,MAAM,IAAI,gCAAe,CAAC,qBAAqB,EAAE;YAC/C,IAAI,EAAE,gBAAgB;YACtB,IAAI,EAAE,qDAAqD;SAC5D,CAAC,CAAC;IACL,CAAC;IAED,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACb,GAAG,CAAC,IAAI,CAAC,qBAAqB,CAAC,CAAC;IAChC,GAAG,CAAC,IAAI,CAAC,eAAe,gBAAgB,EAAE,CAAC,CAAC;IAC5C,GAAG,CAAC,IAAI,CAAC,eAAe,gBAAgB,EAAE,CAAC,CAAC;IAC5C,IAAI,gBAAgB;QAAE,GAAG,CAAC,IAAI,CAAC,eAAe,gBAAgB,EAAE,CAAC,CAAC;;QAC7D,GAAG,CAAC,IAAI,CAAC,oBAAoB,CAAC,CAAC;IACpC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAEb,2CAA2C;IAC3C,MAAM,UAAU,GAA0B;QACxC,WAAW,EAAE,EAAE,IAAI,EAAE,eAAe,EAAE;KACvC,CAAC;IAEF,0DAA0D;IAC1D,OAAO,CAAC,IAAI,GAAG;QACb,OAAO,CAAC,IAAI,CAAC,CAAC,CAAE;QAChB,OAAO,CAAC,IAAI,CAAC,CAAC,CAAE;QAChB,GAAG,UAAU,CAAC,WAAW,CAAC,IAAI;KAC/B,CAAC;IAEF,+DAA+D;IAC/D,MAAM,IAAI,GAAG,yBAAa,gBAAgB,uCAAC,CAAC;IAE5C,mBAAmB;IACnB,IAAI,OAAO,IAAI,CAAC,YAAY,KAAK,UAAU,EAAE,CAAC;QAC5C,MAAM,IAAI,gCAAe,CAAC,+CAA+C,EAAE;YACzE,IAAI,EAAE,gBAAgB;YACtB,IAAI,EAAE,gEAAgE;SACvE,CAAC,CAAC;IACL,CAAC;IACD,IAAI,OAAO,IAAI,CAAC,YAAY,KAAK,UAAU,EAAE,CAAC;QAC5C,MAAM,IAAI,gCAAe,CAAC,+CAA+C,EAAE;YACzE,IAAI,EAAE,gBAAgB;YACtB,IAAI,EAAE,gEAAgE;SACvE,CAAC,CAAC;IACL,CAAC;IAED,8BAA8B;IAC9B,MAAM,SAAS,GAAuB,MAAM,IAAI,CAAC,YAAY,EAAE,CAAC;IAChE,MAAM,SAAS,GAAG,MAAM,IAAI,CAAC,YAAY,EAAE,CAAC;IAE5C,uBAAuB;IACvB,MAAM,IAAA,yCAAmB,EAAC,EAAE,SAAS,EAAE,CAAC,CAAC;IAEzC,uCAAuC;IACvC,MAAM,OAAO,GAAG;QACd,UAAU,EAAE,IAAI,oBAAU,CAAC,EAAE,aAAa,EAAE,CAAC,EAAE,CAAC;QAChD,GAAG;QACH,WAAW,EAAE,UAAU,CAAC,WAAW;KACpC,CAAC;IAEF,6DAA6D;IAC7D,MAAM,EAAE,IAAI,EAAE,QAAQ,EAAE,GAAG,MAAM,IAAA,yBAAW,EAC1C;QACE,SAAS;QACT,SAAS;QACT,YAAY,EAAE,gBAAgB;KAC/B,EACD,OAAO,CACR,CAAC;IAEF,iCAAiC;IACjC,MAAM,OAAO,GAAG,IAAA,cAAO,EAAC,gBAAgB,CAAC,CAAC;IAC1C,MAAM,IAAA,gBAAK,EAAC,OAAO,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAE1C,qBAAqB;IACrB,MAAM,IAAA,oBAAS,EAAC,gBAAgB,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC;IAE1E,sCAAsC;IACtC,IAAI,gBAAgB,EAAE,CAAC;QACrB,MAAM,OAAO,GAAG,IAAA,cAAO,EAAC,gBAAgB,CAAC,CAAC;QAC1C,MAAM,IAAA,gBAAK,EAAC,OAAO,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QAC1C,MAAM,IAAA,oBAAS,EACb,gBAAgB,EAChB,IAAI,CAAC,SAAS,CAAC,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC,EACjC,OAAO,CACR,CAAC;IACJ,CAAC;IAED,oBAAoB;IACpB,MAAM,IAAA,uCAAiB,EAAC,EAAE,SAAS,EAAE,CAAC,CAAC;IAEvC,cAAc;IACd,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACb,GAAG,CAAC,IAAI,CAAC,qBAAqB,CAAC,CAAC;IAChC,GAAG,CAAC,IAAI,CAAC,oBAAoB,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;IACpD,GAAG,CAAC,IAAI,CAAC,eAAe,gBAAgB,EAAE,CAAC,CAAC;IAC5C,IAAI,gBAAgB;QAAE,GAAG,CAAC,IAAI,CAAC,eAAe,gBAAgB,EAAE,CAAC,CAAC;;QAC7D,GAAG,CAAC,IAAI,CAAC,oBAAoB,CAAC,CAAC;IACpC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;AACf,CAAC,CAAC;AA5HW,QAAA,kBAAkB,sBA4H7B"}
@@ -0,0 +1,15 @@
1
+ /**
2
+ * .what = context for CLI operations with passthrough args
3
+ * .why = enables wish files to receive args passed via -- separator
4
+ */
5
+ export type ContextDeclastructCli = {
6
+ /**
7
+ * args passed through from CLI via -- separator
8
+ */
9
+ passthrough: {
10
+ /**
11
+ * argv to inject into process.argv before wish file import
12
+ */
13
+ argv: string[];
14
+ };
15
+ };
@@ -0,0 +1,3 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ //# sourceMappingURL=ContextDeclastructCli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ContextDeclastructCli.js","sourceRoot":"","sources":["../../src/domain.objects/ContextDeclastructCli.ts"],"names":[],"mappings":""}
@@ -19,9 +19,15 @@ export interface DeclastructPlan {
19
19
  */
20
20
  wish: {
21
21
  /**
22
- * file path URI to the wish file containing resources and providers
22
+ * file path URI to the wish file
23
23
  */
24
24
  uri: string;
25
+ /**
26
+ * args passed via -- separator at plan time
27
+ *
28
+ * .why = apply must replay these to get same resources for staleness check
29
+ */
30
+ argv: string[];
25
31
  };
26
32
  /**
27
33
  * all proposed changes
@@ -1 +1 @@
1
- {"version":3,"file":"DeclastructPlan.js","sourceRoot":"","sources":["../../src/domain.objects/DeclastructPlan.ts"],"names":[],"mappings":";;;AAAA,mDAA8C;AAoC9C,MAAa,eACX,SAAQ,6BAA6B;;AADvC,0CAOC;AAHe,uBAAO,GAAG,CAAC,MAAM,CAAU,CAAC;AAC5B,sBAAM,GAAG,CAAC,MAAM,CAAU,CAAC;AAC3B,yBAAS,GAAG,EAAW,CAAC"}
1
+ {"version":3,"file":"DeclastructPlan.js","sourceRoot":"","sources":["../../src/domain.objects/DeclastructPlan.ts"],"names":[],"mappings":";;;AAAA,mDAA8C;AA2C9C,MAAa,eACX,SAAQ,6BAA6B;;AADvC,0CAOC;AAHe,uBAAO,GAAG,CAAC,MAAM,CAAU,CAAC;AAC5B,sBAAM,GAAG,CAAC,MAAM,CAAU,CAAC;AAC3B,yBAAS,GAAG,EAAW,CAAC"}
@@ -0,0 +1,54 @@
1
+ import { DomainLiteral } from 'domain-objects';
2
+ import type { IsoTimestamp } from './IsoTimestamp';
3
+ /**
4
+ * .what = a single entry in a snapshot, captures state for one resource
5
+ * .why = enables debug and audit of what declastruct observed for each resource
6
+ */
7
+ export interface DeclastructSnapshotEntry {
8
+ /**
9
+ * which resource this entry is for
10
+ */
11
+ forResource: {
12
+ /**
13
+ * class name of the resource
14
+ */
15
+ class: string;
16
+ /**
17
+ * scannable identifier of this specific resource
18
+ */
19
+ slug: string;
20
+ };
21
+ /**
22
+ * serialized state of the resource
23
+ *
24
+ * .note = null if the resource does not exist remotely (for remote[])
25
+ * .note = contains _dobj stamp from serialize()
26
+ */
27
+ state: Record<string, any> | null;
28
+ }
29
+ export declare class DeclastructSnapshotEntry extends DomainLiteral<DeclastructSnapshotEntry> implements DeclastructSnapshotEntry {
30
+ }
31
+ /**
32
+ * .what = snapshot of remote and wished state at plan time
33
+ * .why = enables debug and audit of what declastruct observed before diff
34
+ */
35
+ export interface DeclastructSnapshot {
36
+ /**
37
+ * timestamp when the snapshot was taken
38
+ */
39
+ observedAt: IsoTimestamp;
40
+ /**
41
+ * remote state for each resource (before omitReadonly)
42
+ */
43
+ remote: DeclastructSnapshotEntry[];
44
+ /**
45
+ * wished state for each resource (what user declared)
46
+ */
47
+ wished: DeclastructSnapshotEntry[];
48
+ }
49
+ export declare class DeclastructSnapshot extends DomainLiteral<DeclastructSnapshot> implements DeclastructSnapshot {
50
+ static nested: {
51
+ remote: typeof DeclastructSnapshotEntry;
52
+ wished: typeof DeclastructSnapshotEntry;
53
+ };
54
+ }
@@ -0,0 +1,15 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.DeclastructSnapshot = exports.DeclastructSnapshotEntry = void 0;
4
+ const domain_objects_1 = require("domain-objects");
5
+ class DeclastructSnapshotEntry extends domain_objects_1.DomainLiteral {
6
+ }
7
+ exports.DeclastructSnapshotEntry = DeclastructSnapshotEntry;
8
+ class DeclastructSnapshot extends domain_objects_1.DomainLiteral {
9
+ }
10
+ exports.DeclastructSnapshot = DeclastructSnapshot;
11
+ DeclastructSnapshot.nested = {
12
+ remote: DeclastructSnapshotEntry,
13
+ wished: DeclastructSnapshotEntry,
14
+ };
15
+ //# sourceMappingURL=DeclastructSnapshot.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DeclastructSnapshot.js","sourceRoot":"","sources":["../../src/domain.objects/DeclastructSnapshot.ts"],"names":[],"mappings":";;;AAAA,mDAA+C;AAiC/C,MAAa,wBACX,SAAQ,8BAAuC;CACT;AAFxC,4DAEwC;AAuBxC,MAAa,mBACX,SAAQ,8BAAkC;;AAD5C,kDAQC;AAJe,0BAAM,GAAG;IACrB,MAAM,EAAE,wBAAwB;IAChC,MAAM,EAAE,wBAAwB;CACjC,CAAC"}
@@ -1,6 +1,7 @@
1
1
  import { type DomainEntity } from 'domain-objects';
2
2
  import type { ContextLogTrail } from 'simple-log-methods';
3
3
  import type { ContextDeclastruct } from '../../domain.objects/ContextDeclastruct';
4
+ import type { ContextDeclastructCli } from '../../domain.objects/ContextDeclastructCli';
4
5
  import { type DeclastructChange } from '../../domain.objects/DeclastructChange';
5
6
  import type { DeclastructPlan } from '../../domain.objects/DeclastructPlan';
6
7
  import type { DeclastructProvider } from '../../domain.objects/DeclastructProvider';
@@ -15,6 +16,6 @@ export declare const applyChanges: (input: {
15
16
  plan: DeclastructPlan | null;
16
17
  resources: DomainEntity<any>[];
17
18
  providers: DeclastructProvider<any, any>[];
18
- }, context: ContextLogTrail & ContextDeclastruct) => Promise<{
19
+ }, context: ContextLogTrail & ContextDeclastruct & ContextDeclastructCli) => Promise<{
19
20
  appliedChanges: DeclastructChange[];
20
21
  }>;
@@ -9,6 +9,25 @@ const validate_1 = require("../../domain.operations/plan/validate");
9
9
  const colorizeAction_1 = require("../../infra/colorizeAction");
10
10
  const withSpinner_1 = require("../../infra/withSpinner");
11
11
  const applyChange_1 = require("./applyChange");
12
+ /**
13
+ * .what = checks if plan has any non-KEEP changes
14
+ * .why = determines whether apply phase should proceed
15
+ */
16
+ const hasChangesToApply = (input) => {
17
+ return input.changes.some((change) => change.action !== DeclastructChange_1.DeclastructChangeAction.KEEP);
18
+ };
19
+ /**
20
+ * .what = finds resource that matches forResource identifier
21
+ * .why = locates the declared resource for a planned change
22
+ */
23
+ const getOneResourceForChange = (input) => {
24
+ const resourceFound = input.resources.find((candidate) => candidate.constructor.name === input.forResource.class &&
25
+ (0, domain_objects_1.getUniqueIdentifierSlug)(candidate) === input.forResource.slug);
26
+ if (!resourceFound) {
27
+ helpful_errors_1.UnexpectedCodePathError.throw('could not find resource specified in plan. was it removed?', { forResource: input.forResource });
28
+ }
29
+ return resourceFound;
30
+ };
12
31
  /**
13
32
  * .what = applies changes to achieve desired state
14
33
  * .why = executes infrastructure changes in a controlled, observable manner
@@ -18,18 +37,17 @@ const applyChange_1 = require("./applyChange");
18
37
  */
19
38
  const applyChanges = async (input, context) => {
20
39
  // replan to get current state
21
- const currentPlan = await (0, planChanges_1.planChanges)({
40
+ const { plan: currentPlan } = await (0, planChanges_1.planChanges)({
22
41
  resources: input.resources,
23
42
  providers: input.providers,
24
43
  wishFilePath: input.plan?.wish.uri ?? 'ignorable',
25
44
  }, context);
26
45
  // use current plan for apply (works for both modes)
27
46
  const planToApply = currentPlan;
28
- // check if there are any actionable changes (non-KEEP)
29
- const hasActionableChanges = planToApply.changes.some((change) => change.action !== DeclastructChange_1.DeclastructChangeAction.KEEP);
30
47
  // skip apply phase if everything is in sync
31
- if (!hasActionableChanges)
48
+ if (!hasChangesToApply({ changes: planToApply.changes })) {
32
49
  return { appliedChanges: [] };
50
+ }
33
51
  // validate plan matches current state (skip if no plan provided, i.e. yolo mode)
34
52
  if (input.plan) {
35
53
  (0, validate_1.assertPlanStillValid)({
@@ -56,9 +74,10 @@ const applyChanges = async (input, context) => {
56
74
  continue;
57
75
  }
58
76
  // find the desired resource
59
- const resourceFound = input.resources.find((candidate) => candidate.constructor.name === change.forResource.class &&
60
- (0, domain_objects_1.getUniqueIdentifierSlug)(candidate) === change.forResource.slug) ??
61
- helpful_errors_1.UnexpectedCodePathError.throw('could not find resource specified in plan. was it removed?', { change });
77
+ const resourceFound = getOneResourceForChange({
78
+ resources: input.resources,
79
+ forResource: change.forResource,
80
+ });
62
81
  // log the action line (stays fixed)
63
82
  const actionLabel = (0, colorizeAction_1.colorizeAction)(change.action);
64
83
  context.log.info(`○ ${actionLabel} ${change.forResource.slug}`);
@@ -1 +1 @@
1
- {"version":3,"file":"applyChanges.js","sourceRoot":"","sources":["../../../src/domain.operations/apply/applyChanges.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"applyChanges.js","sourceRoot":"","sources":["../../../src/domain.operations/apply/applyChanges.ts"],"names":[],"mappings":"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"}
@@ -1,8 +1,10 @@
1
1
  import { type DomainEntity } from 'domain-objects';
2
2
  import type { ContextLogTrail } from 'simple-log-methods';
3
3
  import type { ContextDeclastruct } from '../../domain.objects/ContextDeclastruct';
4
+ import type { ContextDeclastructCli } from '../../domain.objects/ContextDeclastructCli';
4
5
  import { DeclastructPlan } from '../../domain.objects/DeclastructPlan';
5
6
  import type { DeclastructProvider } from '../../domain.objects/DeclastructProvider';
7
+ import { DeclastructSnapshot } from '../../domain.objects/DeclastructSnapshot';
6
8
  /**
7
9
  * .what = generates a plan of changes required to achieve desired state
8
10
  * .why = enables users to review infrastructure changes before applying them
@@ -12,4 +14,7 @@ export declare const planChanges: (input: {
12
14
  resources: DomainEntity<any>[];
13
15
  providers: DeclastructProvider<any, any>[];
14
16
  wishFilePath: string;
15
- }, context: ContextLogTrail & ContextDeclastruct) => Promise<DeclastructPlan>;
17
+ }, context: ContextLogTrail & ContextDeclastruct & ContextDeclastructCli) => Promise<{
18
+ plan: DeclastructPlan;
19
+ snapshot: DeclastructSnapshot;
20
+ }>;
@@ -2,15 +2,25 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.planChanges = void 0;
4
4
  const domain_objects_1 = require("domain-objects");
5
+ const helpful_errors_1 = require("helpful-errors");
5
6
  const DeclastructChange_1 = require("../../domain.objects/DeclastructChange");
6
7
  const DeclastructPlan_1 = require("../../domain.objects/DeclastructPlan");
8
+ const DeclastructSnapshot_1 = require("../../domain.objects/DeclastructSnapshot");
7
9
  const del_1 = require("../../domain.operations/del/del");
10
+ const asIndentedLines_1 = require("../../infra/asIndentedLines");
8
11
  const asIsoTimestamp_1 = require("../../infra/asIsoTimestamp");
9
12
  const colorizeAction_1 = require("../../infra/colorizeAction");
10
13
  const withSpinner_1 = require("../../infra/withSpinner");
11
14
  const computeChange_1 = require("./computeChange");
12
15
  const getDaoByResource_1 = require("./getDaoByResource");
13
16
  const hashChanges_1 = require("./hashChanges");
17
+ /**
18
+ * .what = checks if all changes are KEEP (no actions required)
19
+ * .why = determines whether to show "all in sync" message
20
+ */
21
+ const isAllInSync = (input) => {
22
+ return input.changes.every((change) => change.action === DeclastructChange_1.DeclastructChangeAction.KEEP);
23
+ };
14
24
  /**
15
25
  * .what = generates a plan of changes required to achieve desired state
16
26
  * .why = enables users to review infrastructure changes before applying them
@@ -24,8 +34,12 @@ const planChanges = async (input, context) => {
24
34
  const bottleneck = 'onPlan' in context.bottleneck
25
35
  ? context.bottleneck.onPlan
26
36
  : context.bottleneck;
27
- // compute change for each resource with real-time logging
37
+ // capture observation timestamp (before any API calls)
38
+ const observedAt = (0, asIsoTimestamp_1.asIsoTimestamp)(new Date());
39
+ // compute change for each resource with real-time output
28
40
  const changes = [];
41
+ const snapshotRemote = [];
42
+ const snapshotWished = [];
29
43
  for (const resource of input.resources) {
30
44
  const change = await bottleneck.schedule(async () => {
31
45
  // find DAO and provider context for this resource
@@ -45,6 +59,25 @@ const planChanges = async (input, context) => {
45
59
  context.log.info(` ├─ ✔ done in ${durationSec}s`);
46
60
  // determine desired state - null if marked for deletion
47
61
  const desiredState = (0, del_1.isMarkedForDeletion)(resource) ? null : resource;
62
+ // collect snapshot entry BEFORE omitReadonly (for debug and audit)
63
+ const forResource = {
64
+ class: resource.constructor.name,
65
+ slug: helpful_errors_1.UnexpectedCodePathError.wrap(() => (0, domain_objects_1.getUniqueIdentifierSlug)(resource), {
66
+ message: 'failed to getUniqueIdentifierSlug for snapshot',
67
+ metadata: {
68
+ resource,
69
+ ctor: resource.constructor.name,
70
+ },
71
+ })(),
72
+ };
73
+ snapshotRemote.push(new DeclastructSnapshot_1.DeclastructSnapshotEntry({
74
+ forResource,
75
+ state: remoteState ? JSON.parse((0, domain_objects_1.serialize)(remoteState)) : null,
76
+ }));
77
+ snapshotWished.push(new DeclastructSnapshot_1.DeclastructSnapshotEntry({
78
+ forResource,
79
+ state: JSON.parse((0, domain_objects_1.serialize)(resource)), // always the declared resource, not desiredState
80
+ }));
48
81
  // compute change
49
82
  const computed = (0, computeChange_1.computeChange)({
50
83
  desired: desiredState,
@@ -60,10 +93,10 @@ const planChanges = async (input, context) => {
60
93
  context.log.info(` └─ decision ${(0, colorizeAction_1.colorizeAction)(computed.action)}`);
61
94
  // and the diff too, indented to align with tree
62
95
  if (computed.state.difference) {
63
- const indentedDiff = computed.state.difference
64
- .split('\n')
65
- .map((line) => ` ${line}`)
66
- .join('\n');
96
+ const indentedDiff = (0, asIndentedLines_1.asIndentedLines)({
97
+ text: computed.state.difference,
98
+ indent: ' ',
99
+ });
67
100
  context.log.info(indentedDiff);
68
101
  }
69
102
  context.log.info('');
@@ -73,20 +106,27 @@ const planChanges = async (input, context) => {
73
106
  changes.push(change);
74
107
  }
75
108
  // log success message if everything is in sync
76
- const allInSync = changes.every((change) => change.action === DeclastructChange_1.DeclastructChangeAction.KEEP);
77
- if (allInSync) {
109
+ if (isAllInSync({ changes })) {
78
110
  context.log.info('');
79
111
  context.log.info('🎉 everything is in sync!');
80
112
  }
81
- // return plan
82
- return new DeclastructPlan_1.DeclastructPlan({
113
+ // build plan
114
+ const plan = new DeclastructPlan_1.DeclastructPlan({
83
115
  hash: (0, hashChanges_1.hashChanges)(changes),
84
116
  createdAt: (0, asIsoTimestamp_1.asIsoTimestamp)(new Date()),
85
117
  wish: {
86
118
  uri: input.wishFilePath,
119
+ argv: context.passthrough.argv,
87
120
  },
88
121
  changes,
89
122
  });
123
+ // build snapshot
124
+ const snapshot = new DeclastructSnapshot_1.DeclastructSnapshot({
125
+ observedAt,
126
+ remote: snapshotRemote,
127
+ wished: snapshotWished,
128
+ });
129
+ return { plan, snapshot };
90
130
  };
91
131
  exports.planChanges = planChanges;
92
132
  //# sourceMappingURL=planChanges.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"planChanges.js","sourceRoot":"","sources":["../../../src/domain.operations/plan/planChanges.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"planChanges.js","sourceRoot":"","sources":["../../../src/domain.operations/plan/planChanges.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ /**
2
+ * .what = indents each line of text with specified prefix
3
+ * .why = formats multi-line text to align with tree structure in logs
4
+ */
5
+ export declare const asIndentedLines: (input: {
6
+ text: string;
7
+ indent: string;
8
+ }) => string;
@@ -0,0 +1,15 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.asIndentedLines = void 0;
4
+ /**
5
+ * .what = indents each line of text with specified prefix
6
+ * .why = formats multi-line text to align with tree structure in logs
7
+ */
8
+ const asIndentedLines = (input) => {
9
+ return input.text
10
+ .split('\n')
11
+ .map((line) => `${input.indent}${line}`)
12
+ .join('\n');
13
+ };
14
+ exports.asIndentedLines = asIndentedLines;
15
+ //# sourceMappingURL=asIndentedLines.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"asIndentedLines.js","sourceRoot":"","sources":["../../src/infra/asIndentedLines.ts"],"names":[],"mappings":";;;AAAA;;;GAGG;AACI,MAAM,eAAe,GAAG,CAAC,KAG/B,EAAU,EAAE;IACX,OAAO,KAAK,CAAC,IAAI;SACd,KAAK,CAAC,IAAI,CAAC;SACX,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,GAAG,IAAI,EAAE,CAAC;SACvC,IAAI,CAAC,IAAI,CAAC,CAAC;AAChB,CAAC,CAAC;AARW,QAAA,eAAe,mBAQ1B"}
@@ -0,0 +1,15 @@
1
+ import type { DeclastructProvider } from '../domain.objects/DeclastructProvider';
2
+ /**
3
+ * .what = initializes all providers via their beforeAll hooks
4
+ * .why = providers may need to establish connections or state before use
5
+ */
6
+ export declare const initializeProviders: (input: {
7
+ providers: DeclastructProvider<any, any>[];
8
+ }) => Promise<void>;
9
+ /**
10
+ * .what = finalizes all providers via their afterAll hooks
11
+ * .why = providers may need to close connections or cleanup state after use
12
+ */
13
+ export declare const finalizeProviders: (input: {
14
+ providers: DeclastructProvider<any, any>[];
15
+ }) => Promise<void>;
@@ -0,0 +1,20 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.finalizeProviders = exports.initializeProviders = void 0;
4
+ /**
5
+ * .what = initializes all providers via their beforeAll hooks
6
+ * .why = providers may need to establish connections or state before use
7
+ */
8
+ const initializeProviders = async (input) => {
9
+ await Promise.all(input.providers.map((p) => p.hooks.beforeAll()));
10
+ };
11
+ exports.initializeProviders = initializeProviders;
12
+ /**
13
+ * .what = finalizes all providers via their afterAll hooks
14
+ * .why = providers may need to close connections or cleanup state after use
15
+ */
16
+ const finalizeProviders = async (input) => {
17
+ await Promise.all(input.providers.map((p) => p.hooks.afterAll()));
18
+ };
19
+ exports.finalizeProviders = finalizeProviders;
20
+ //# sourceMappingURL=initializeProviders.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"initializeProviders.js","sourceRoot":"","sources":["../../src/infra/initializeProviders.ts"],"names":[],"mappings":";;;AAEA;;;GAGG;AACI,MAAM,mBAAmB,GAAG,KAAK,EAAE,KAEzC,EAAiB,EAAE;IAClB,MAAM,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC;AACrE,CAAC,CAAC;AAJW,QAAA,mBAAmB,uBAI9B;AAEF;;;GAGG;AACI,MAAM,iBAAiB,GAAG,KAAK,EAAE,KAEvC,EAAiB,EAAE;IAClB,MAAM,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC;AACpE,CAAC,CAAC;AAJW,QAAA,iBAAiB,qBAI5B"}
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "declastruct",
3
3
  "author": "ehmpathy",
4
4
  "description": "Add declarative control to any resource constructs. Declare, plan, and apply within an observable pit-of-success.",
5
- "version": "1.7.3",
5
+ "version": "1.9.0",
6
6
  "repository": "ehmpathy/declastruct",
7
7
  "homepage": "https://github.com/ehmpathy/declastruct",
8
8
  "keywords": [
@@ -53,7 +53,8 @@
53
53
  "preversion": "npm run prepush",
54
54
  "postversion": "git push origin HEAD --tags --no-verify",
55
55
  "prepare:husky": "npx husky install && chmod ug+x .husky/*",
56
- "prepare": "[ -e .git ] && npm run prepare:husky || exit 0"
56
+ "prepare": "[ -e .git ] && npm run prepare:husky || exit 0 && npm run prepare:rhachet",
57
+ "prepare:rhachet": "npm run build && rhachet init --hooks --roles mechanic behaver driver reviewer librarian ergonomist architect reflector dreamer dispatcher"
57
58
  },
58
59
  "dependencies": {
59
60
  "bottleneck": "2.19.5",
@@ -84,14 +85,18 @@
84
85
  "cz-conventional-changelog": "3.3.0",
85
86
  "declapract": "^0.13.1",
86
87
  "declapract-typescript-ehmpathy": "0.45.3",
87
- "declastruct": "1.7.0",
88
+ "declastruct": "link:.",
88
89
  "declastruct-github": "1.0.7",
89
90
  "depcheck": "1.4.3",
90
91
  "esbuild-register": "3.6.0",
91
92
  "husky": "8.0.3",
92
93
  "jest": "30.2.0",
93
- "rhachet": "1.12.3",
94
- "rhachet-roles-ehmpathy": "1.12.0",
94
+ "rhachet": "1.39.13",
95
+ "rhachet-brains-anthropic": "0.4.0",
96
+ "rhachet-brains-xai": "0.3.3",
97
+ "rhachet-roles-bhrain": "0.24.1",
98
+ "rhachet-roles-bhuild": "0.17.2",
99
+ "rhachet-roles-ehmpathy": "1.34.28",
95
100
  "test-fns": "1.7.2",
96
101
  "tsc-alias": "1.8.10",
97
102
  "tsx": "4.20.6",
package/readme.md CHANGED
@@ -120,6 +120,48 @@ planned changes:
120
120
  + metadata: { source: "app-web" }
121
121
  ```
122
122
 
123
+ #### pass args to your wish file
124
+
125
+ pass args to your wish file via `--` separator:
126
+
127
+ ```sh
128
+ npx declastruct plan \
129
+ --wish provision/resources.ts \
130
+ --into provision/.temp/plan.json \
131
+ -- --env prod --region us-west-2
132
+ ```
133
+
134
+ args after `--` are injected into `process.argv` before the wish file loads. parse them with node's `parseArgs`:
135
+
136
+ ```ts
137
+ import { parseArgs } from 'util';
138
+
139
+ const { values } = parseArgs({
140
+ args: process.argv.slice(2),
141
+ options: {
142
+ env: { type: 'string', default: 'test' },
143
+ region: { type: 'string', default: 'us-east-1' },
144
+ },
145
+ });
146
+
147
+ export const getResources = async () => {
148
+ // use values.env, values.region to configure resources
149
+ return [
150
+ DeclaredAwsS3Bucket.as({
151
+ name: `app-${values.env}-assets`,
152
+ region: values.region,
153
+ }),
154
+ ];
155
+ };
156
+ ```
157
+
158
+ **typo safety:** unknown flags without `--` trigger an error with guidance:
159
+
160
+ ```
161
+ error: unknown option '--env'
162
+ hint: to pass args to your wish file, use: -- --env
163
+ ```
164
+
123
165
  ### 3. **apply** the plan 🪄
124
166
 
125
167
  apply the plan to make your wish come true