@terraforge/core 0.0.4 → 0.0.6

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.
package/dist/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  // src/node.ts
2
- var nodeMetaSymbol = Symbol("metadata");
2
+ var nodeMetaSymbol = /* @__PURE__ */ Symbol("metadata");
3
3
  var isNode = (obj) => {
4
4
  const meta = obj[nodeMetaSymbol];
5
5
  return meta && typeof meta === "object" && meta !== null && "tag" in meta && typeof meta.tag === "string";
@@ -15,17 +15,14 @@ var isDataSource = (obj) => {
15
15
  };
16
16
 
17
17
  // src/group.ts
18
- class Group {
19
- parent;
20
- type;
21
- name;
22
- children = [];
18
+ var Group = class _Group {
23
19
  constructor(parent, type, name) {
24
20
  this.parent = parent;
25
21
  this.type = type;
26
22
  this.name = name;
27
23
  parent?.children.push(this);
28
24
  }
25
+ children = [];
29
26
  get urn() {
30
27
  const urn = this.parent ? this.parent.urn : "urn";
31
28
  return `${urn}:${this.type}:{${this.name}}`;
@@ -38,8 +35,8 @@ class Group {
38
35
  throw new Error(`Duplicate node found: ${meta.type}:${meta.logicalId}`);
39
36
  }
40
37
  }
41
- if (child instanceof Group) {
42
- const duplicate = this.children.filter((c) => c instanceof Group).find((c) => c.type === child.type && c.name === child.name);
38
+ if (child instanceof _Group) {
39
+ const duplicate = this.children.filter((c) => c instanceof _Group).find((c) => c.type === child.type && c.name === child.name);
43
40
  if (duplicate) {
44
41
  throw new Error(`Duplicate group found: ${child.type}:${child.name}`);
45
42
  }
@@ -53,7 +50,7 @@ class Group {
53
50
  }
54
51
  get nodes() {
55
52
  return this.children.map((child) => {
56
- if (child instanceof Group) {
53
+ if (child instanceof _Group) {
57
54
  return child.nodes;
58
55
  }
59
56
  if (isNode(child)) {
@@ -68,16 +65,15 @@ class Group {
68
65
  get dataSources() {
69
66
  return this.nodes.filter((node) => isDataSource(node));
70
67
  }
71
- }
68
+ };
72
69
 
73
70
  // src/stack.ts
74
- class Stack extends Group {
75
- app;
76
- dependencies = new Set;
71
+ var Stack = class extends Group {
77
72
  constructor(app, name) {
78
73
  super(app, "stack", name);
79
74
  this.app = app;
80
75
  }
76
+ dependencies = /* @__PURE__ */ new Set();
81
77
  dependsOn(...stacks) {
82
78
  for (const stack of stacks) {
83
79
  if (stack.app !== this.app) {
@@ -87,7 +83,7 @@ class Stack extends Group {
87
83
  }
88
84
  return this;
89
85
  }
90
- }
86
+ };
91
87
  var findParentStack = (group) => {
92
88
  if (group instanceof Stack) {
93
89
  return group;
@@ -99,31 +95,29 @@ var findParentStack = (group) => {
99
95
  };
100
96
 
101
97
  // src/app.ts
102
- class App extends Group {
103
- name;
98
+ var App = class extends Group {
104
99
  constructor(name) {
105
- super(undefined, "app", name);
100
+ super(void 0, "app", name);
106
101
  this.name = name;
107
102
  }
108
103
  get stacks() {
109
104
  return this.children.filter((child) => child instanceof Stack);
110
105
  }
111
- }
106
+ };
107
+
112
108
  // src/future.ts
113
109
  var IDLE = 0;
114
110
  var PENDING = 1;
115
111
  var RESOLVED = 2;
116
112
  var REJECTED = 3;
117
-
118
- class Future {
119
- callback;
120
- listeners = new Set;
121
- status = IDLE;
122
- data;
123
- error;
113
+ var Future = class _Future {
124
114
  constructor(callback) {
125
115
  this.callback = callback;
126
116
  }
117
+ listeners = /* @__PURE__ */ new Set();
118
+ status = IDLE;
119
+ data;
120
+ error;
127
121
  get [Symbol.toStringTag]() {
128
122
  switch (this.status) {
129
123
  case IDLE:
@@ -137,42 +131,45 @@ class Future {
137
131
  }
138
132
  }
139
133
  pipe(cb) {
140
- return new Future((resolve, reject) => {
134
+ return new _Future((resolve2, reject) => {
141
135
  this.then((value) => {
142
136
  Promise.resolve(cb(value)).then((value2) => {
143
- resolve(value2);
137
+ resolve2(value2);
144
138
  }).catch(reject);
145
139
  }, reject);
146
140
  });
147
141
  }
148
- then(resolve, reject) {
142
+ then(resolve2, reject) {
149
143
  if (this.status === RESOLVED) {
150
- resolve(this.data);
144
+ resolve2(this.data);
151
145
  } else if (this.status === REJECTED) {
152
146
  reject?.(this.error);
153
147
  } else {
154
- this.listeners.add({ resolve, reject });
148
+ this.listeners.add({ resolve: resolve2, reject });
155
149
  if (this.status === IDLE) {
156
150
  this.status = PENDING;
157
- this.callback((data) => {
158
- if (this.status === PENDING) {
159
- this.status = RESOLVED;
160
- this.data = data;
161
- this.listeners.forEach(({ resolve: resolve2 }) => resolve2(data));
162
- this.listeners.clear();
163
- }
164
- }, (error) => {
165
- if (this.status === PENDING) {
166
- this.status = REJECTED;
167
- this.error = error;
168
- this.listeners.forEach(({ reject: reject2 }) => reject2?.(error));
169
- this.listeners.clear();
151
+ this.callback(
152
+ (data) => {
153
+ if (this.status === PENDING) {
154
+ this.status = RESOLVED;
155
+ this.data = data;
156
+ this.listeners.forEach(({ resolve: resolve3 }) => resolve3(data));
157
+ this.listeners.clear();
158
+ }
159
+ },
160
+ (error) => {
161
+ if (this.status === PENDING) {
162
+ this.status = REJECTED;
163
+ this.error = error;
164
+ this.listeners.forEach(({ reject: reject2 }) => reject2?.(error));
165
+ this.listeners.clear();
166
+ }
170
167
  }
171
- });
168
+ );
172
169
  }
173
170
  }
174
171
  }
175
- }
172
+ };
176
173
 
177
174
  // src/input.ts
178
175
  var findInputDeps = (props) => {
@@ -201,26 +198,32 @@ var resolveInputs = async (inputs) => {
201
198
  }
202
199
  };
203
200
  find(inputs, {}, "root");
204
- const responses = await Promise.all(unresolved.map(async ([obj, key]) => {
205
- const promise = obj[key];
206
- let timeout;
207
- const response = await Promise.race([
208
- promise,
209
- new Promise((_, reject) => {
210
- timeout = setTimeout(() => {
211
- if (promise instanceof Output) {
212
- reject(new Error(`Resolving Output<${[...promise.dependencies].map((d) => d.urn).join(", ")}> took too long.`));
213
- } else if (promise instanceof Future) {
214
- reject(new Error("Resolving Future took too long."));
215
- } else {
216
- reject(new Error("Resolving Promise took too long."));
217
- }
218
- }, 3000);
219
- })
220
- ]);
221
- clearTimeout(timeout);
222
- return response;
223
- }));
201
+ const responses = await Promise.all(
202
+ unresolved.map(async ([obj, key]) => {
203
+ const promise = obj[key];
204
+ let timeout;
205
+ const response = await Promise.race([
206
+ promise,
207
+ new Promise((_, reject) => {
208
+ timeout = setTimeout(() => {
209
+ if (promise instanceof Output) {
210
+ reject(
211
+ new Error(
212
+ `Resolving Output<${[...promise.dependencies].map((d) => d.urn).join(", ")}> took too long.`
213
+ )
214
+ );
215
+ } else if (promise instanceof Future) {
216
+ reject(new Error("Resolving Future took too long."));
217
+ } else {
218
+ reject(new Error("Resolving Promise took too long."));
219
+ }
220
+ }, 3e3);
221
+ })
222
+ ]);
223
+ clearTimeout(timeout);
224
+ return response;
225
+ })
226
+ );
224
227
  unresolved.forEach(([props, key], i) => {
225
228
  props[key] = responses[i];
226
229
  });
@@ -228,33 +231,32 @@ var resolveInputs = async (inputs) => {
228
231
  };
229
232
 
230
233
  // src/output.ts
231
- class Output extends Future {
232
- dependencies;
234
+ var Output = class _Output extends Future {
233
235
  constructor(dependencies, callback) {
234
236
  super(callback);
235
237
  this.dependencies = dependencies;
236
238
  }
237
239
  pipe(cb) {
238
- return new Output(this.dependencies, (resolve, reject) => {
240
+ return new _Output(this.dependencies, (resolve2, reject) => {
239
241
  this.then((value) => {
240
242
  Promise.resolve(cb(value)).then((value2) => {
241
- resolve(value2);
243
+ resolve2(value2);
242
244
  }).catch(reject);
243
245
  }, reject);
244
246
  });
245
247
  }
246
- }
248
+ };
247
249
  var deferredOutput = (cb) => {
248
- return new Output(new Set, cb);
250
+ return new Output(/* @__PURE__ */ new Set(), cb);
249
251
  };
250
252
  var output = (value) => {
251
- return deferredOutput((resolve) => resolve(value));
253
+ return deferredOutput((resolve2) => resolve2(value));
252
254
  };
253
255
  var combine = (...inputs) => {
254
256
  const deps = new Set(findInputDeps(inputs));
255
- return new Output(deps, (resolve, reject) => {
257
+ return new Output(deps, (resolve2, reject) => {
256
258
  Promise.all(inputs).then((result) => {
257
- resolve(result);
259
+ resolve2(result);
258
260
  }, reject);
259
261
  });
260
262
  };
@@ -266,13 +268,14 @@ var resolve = (inputs, transformer) => {
266
268
  var interpolate = (literals, ...placeholders) => {
267
269
  return combine(...placeholders).pipe((unwrapped) => {
268
270
  const result = [];
269
- for (let i = 0;i < unwrapped.length; i++) {
271
+ for (let i = 0; i < unwrapped.length; i++) {
270
272
  result.push(literals[i], unwrapped[i]);
271
273
  }
272
274
  result.push(literals.at(-1));
273
275
  return result.join("");
274
276
  });
275
277
  };
278
+
276
279
  // src/urn.ts
277
280
  var createUrn = (tag, type, name, parentUrn) => {
278
281
  return `${parentUrn ? parentUrn : "urn"}:${tag}:${type}:{${name}}`;
@@ -293,7 +296,7 @@ var createMeta = (tag, provider, parent, type, logicalId, input, config) => {
293
296
  input,
294
297
  config,
295
298
  get dependencies() {
296
- const dependencies = new Set;
299
+ const dependencies = /* @__PURE__ */ new Set();
297
300
  const linkMetaDep = (dep) => {
298
301
  if (dep.urn === urn) {
299
302
  throw new Error("You can't depend on yourself");
@@ -308,11 +311,20 @@ var createMeta = (tag, provider, parent, type, logicalId, input, config) => {
308
311
  }
309
312
  return dependencies;
310
313
  },
314
+ // attach(value) {
315
+ // resource = value
316
+ // },
317
+ // dependOn(...resources: Resource[]) {},
318
+ // attachDependencies(props) {
319
+ // for (const dep of findInputDeps(props)) {
320
+ // linkMetaDep(dep)
321
+ // }
322
+ // },
311
323
  resolve(data) {
312
324
  output2 = data;
313
325
  },
314
326
  output(cb) {
315
- return new Output(new Set([this]), (resolve2) => {
327
+ return new Output(/* @__PURE__ */ new Set([this]), (resolve2) => {
316
328
  if (!output2) {
317
329
  throw new Error(`Unresolved output for ${tag}: ${urn}`);
318
330
  }
@@ -321,6 +333,7 @@ var createMeta = (tag, provider, parent, type, logicalId, input, config) => {
321
333
  }
322
334
  };
323
335
  };
336
+
324
337
  // src/debug.ts
325
338
  var enabled = false;
326
339
  var enableDebug = () => {
@@ -336,9 +349,10 @@ var createDebugger = (group) => {
336
349
  console.log();
337
350
  };
338
351
  };
352
+
339
353
  // src/workspace/exit.ts
340
354
  import asyncOnExit from "async-on-exit";
341
- var listeners = new Set;
355
+ var listeners = /* @__PURE__ */ new Set();
342
356
  var listening = false;
343
357
  var onExit = (cb) => {
344
358
  listeners.add(cb);
@@ -399,9 +413,9 @@ var entries = (object) => {
399
413
  };
400
414
 
401
415
  // src/workspace/dependency.ts
402
- class DependencyGraph {
403
- graph = new DirectedGraph;
404
- callbacks = new Map;
416
+ var DependencyGraph = class {
417
+ graph = new DirectedGraph();
418
+ callbacks = /* @__PURE__ */ new Map();
405
419
  add(urn, deps, callback) {
406
420
  this.callbacks.set(urn, callback);
407
421
  this.graph.mergeNode(urn);
@@ -428,13 +442,15 @@ class DependencyGraph {
428
442
  const graph = topologicalGenerations(this.graph);
429
443
  const errors = [];
430
444
  for (const list of graph) {
431
- const result = await Promise.allSettled(list.map((urn) => {
432
- const callback = this.callbacks.get(urn);
433
- if (!callback) {
434
- return;
435
- }
436
- return callback();
437
- }));
445
+ const result = await Promise.allSettled(
446
+ list.map((urn) => {
447
+ const callback = this.callbacks.get(urn);
448
+ if (!callback) {
449
+ return;
450
+ }
451
+ return callback();
452
+ })
453
+ );
438
454
  for (const entry of result) {
439
455
  if (entry.status === "rejected") {
440
456
  if (entry.reason instanceof Error) {
@@ -450,7 +466,7 @@ class DependencyGraph {
450
466
  }
451
467
  return errors;
452
468
  }
453
- }
469
+ };
454
470
  var dependentsOn = (resources, dependency) => {
455
471
  const dependents = [];
456
472
  for (const [urn, resource] of entries(resources)) {
@@ -462,39 +478,31 @@ var dependentsOn = (resources, dependency) => {
462
478
  };
463
479
 
464
480
  // src/workspace/error.ts
465
- class ResourceError extends Error {
466
- urn;
467
- type;
468
- operation;
469
- static wrap(urn, type, operation, error) {
470
- if (error instanceof Error) {
471
- return new ResourceError(urn, type, operation, error.message);
472
- }
473
- return new ResourceError(urn, type, operation, "Unknown Error");
474
- }
481
+ var ResourceError = class _ResourceError extends Error {
475
482
  constructor(urn, type, operation, message) {
476
483
  super(message);
477
484
  this.urn = urn;
478
485
  this.type = type;
479
486
  this.operation = operation;
480
487
  }
481
- }
482
-
483
- class AppError extends Error {
484
- app;
485
- issues;
488
+ static wrap(urn, type, operation, error) {
489
+ if (error instanceof Error) {
490
+ return new _ResourceError(urn, type, operation, error.message);
491
+ }
492
+ return new _ResourceError(urn, type, operation, "Unknown Error");
493
+ }
494
+ };
495
+ var AppError = class extends Error {
486
496
  constructor(app, issues, message) {
487
497
  super(message);
488
498
  this.app = app;
489
499
  this.issues = issues;
490
500
  }
491
- }
492
-
493
- class ResourceNotFound extends Error {
494
- }
495
-
496
- class ResourceAlreadyExists extends Error {
497
- }
501
+ };
502
+ var ResourceNotFound = class extends Error {
503
+ };
504
+ var ResourceAlreadyExists = class extends Error {
505
+ };
498
506
 
499
507
  // src/workspace/state.ts
500
508
  var compareState = (left, right) => {
@@ -602,11 +610,23 @@ var deleteResource = async (appToken, urn, state, opt) => {
602
610
  const idempotantToken = createIdempotantToken(appToken, urn, "delete");
603
611
  const provider = findProvider(opt.providers, state.provider);
604
612
  try {
613
+ await opt.hooks?.beforeResourceDelete?.({
614
+ urn,
615
+ type: state.type,
616
+ oldInput: state.input,
617
+ oldOutput: state.output
618
+ });
605
619
  await provider.deleteResource({
606
620
  type: state.type,
607
621
  state: state.output,
608
622
  idempotantToken
609
623
  });
624
+ await opt.hooks?.afterResourceDelete?.({
625
+ urn,
626
+ type: state.type,
627
+ oldInput: state.input,
628
+ oldOutput: state.output
629
+ });
610
630
  } catch (error) {
611
631
  if (error instanceof ResourceNotFound) {
612
632
  debug(state.type, "already deleted");
@@ -632,7 +652,7 @@ var deleteApp = async (app, opt) => {
632
652
  stackStates = stackStates.filter((stackState) => opt.filters.includes(stackState.name));
633
653
  }
634
654
  const queue = createConcurrencyQueue(opt.concurrency ?? 10);
635
- const graph = new DependencyGraph;
655
+ const graph = new DependencyGraph();
636
656
  const allNodes = {};
637
657
  for (const stackState of Object.values(appState.stacks)) {
638
658
  for (const [urn, nodeState] of entries(stackState.nodes)) {
@@ -668,7 +688,7 @@ var requiresReplacement = (priorState, proposedState, replaceOnChanges) => {
668
688
  const priorValue = get(priorState, path);
669
689
  const proposedValue = get(proposedState, path);
670
690
  if (path.includes("*") && Array.isArray(priorValue)) {
671
- for (let i = 0;i < priorValue.length; i++) {
691
+ for (let i = 0; i < priorValue.length; i++) {
672
692
  if (!compareState(priorValue[i], proposedValue[i])) {
673
693
  return true;
674
694
  }
@@ -691,11 +711,24 @@ var createResource = async (resource, appToken, input, opt) => {
691
711
  debug2(input);
692
712
  let result;
693
713
  try {
714
+ await opt.hooks?.beforeResourceCreate?.({
715
+ urn: resource.urn,
716
+ type: meta.type,
717
+ resource,
718
+ newInput: input
719
+ });
694
720
  result = await provider.createResource({
695
721
  type: meta.type,
696
722
  state: input,
697
723
  idempotantToken
698
724
  });
725
+ await opt.hooks?.afterResourceCreate?.({
726
+ urn: resource.urn,
727
+ type: meta.type,
728
+ resource,
729
+ newInput: input,
730
+ newOutput: result.state
731
+ });
699
732
  } catch (error) {
700
733
  throw ResourceError.wrap(meta.urn, meta.type, "create", error);
701
734
  }
@@ -766,7 +799,7 @@ var importResource = async (resource, input, opt) => {
766
799
 
767
800
  // src/workspace/procedure/replace-resource.ts
768
801
  var debug5 = createDebugger("Replace");
769
- var replaceResource = async (resource, appToken, priorState, proposedState, opt) => {
802
+ var replaceResource = async (resource, appToken, priorInputState, priorOutputState, proposedState, opt) => {
770
803
  const meta = getMeta(resource);
771
804
  const urn = meta.urn;
772
805
  const type = meta.type;
@@ -778,11 +811,23 @@ var replaceResource = async (resource, appToken, priorState, proposedState, opt)
778
811
  debug5("retain", type);
779
812
  } else {
780
813
  try {
814
+ await opt.hooks?.beforeResourceDelete?.({
815
+ urn,
816
+ type,
817
+ oldInput: priorInputState,
818
+ oldOutput: priorOutputState
819
+ });
781
820
  await provider.deleteResource({
782
821
  type,
783
- state: priorState,
822
+ state: priorOutputState,
784
823
  idempotantToken
785
824
  });
825
+ await opt.hooks?.afterResourceDelete?.({
826
+ urn,
827
+ type,
828
+ oldInput: priorInputState,
829
+ oldOutput: priorOutputState
830
+ });
786
831
  } catch (error) {
787
832
  if (error instanceof ResourceNotFound) {
788
833
  debug5(type, "already deleted");
@@ -793,11 +838,24 @@ var replaceResource = async (resource, appToken, priorState, proposedState, opt)
793
838
  }
794
839
  let result;
795
840
  try {
841
+ await opt.hooks?.beforeResourceCreate?.({
842
+ urn,
843
+ type,
844
+ resource,
845
+ newInput: proposedState
846
+ });
796
847
  result = await provider.createResource({
797
848
  type,
798
849
  state: proposedState,
799
850
  idempotantToken
800
851
  });
852
+ await opt.hooks?.afterResourceCreate?.({
853
+ urn,
854
+ type,
855
+ resource,
856
+ newInput: proposedState,
857
+ newOutput: result.state
858
+ });
801
859
  } catch (error) {
802
860
  throw ResourceError.wrap(urn, type, "replace", error);
803
861
  }
@@ -809,7 +867,7 @@ var replaceResource = async (resource, appToken, priorState, proposedState, opt)
809
867
 
810
868
  // src/workspace/procedure/update-resource.ts
811
869
  var debug6 = createDebugger("Update");
812
- var updateResource = async (resource, appToken, priorState, proposedState, opt) => {
870
+ var updateResource = async (resource, appToken, priorInputState, priorOutputState, proposedState, opt) => {
813
871
  const meta = getMeta(resource);
814
872
  const provider = findProvider(opt.providers, meta.provider);
815
873
  const idempotantToken = createIdempotantToken(appToken, meta.urn, "update");
@@ -817,12 +875,29 @@ var updateResource = async (resource, appToken, priorState, proposedState, opt)
817
875
  debug6(meta.type);
818
876
  debug6(proposedState);
819
877
  try {
878
+ await opt.hooks?.beforeResourceUpdate?.({
879
+ urn: resource.urn,
880
+ type: meta.type,
881
+ resource,
882
+ newInput: proposedState,
883
+ oldInput: priorInputState,
884
+ oldOutput: priorOutputState
885
+ });
820
886
  result = await provider.updateResource({
821
887
  type: meta.type,
822
- priorState,
888
+ priorState: priorOutputState,
823
889
  proposedState,
824
890
  idempotantToken
825
891
  });
892
+ await opt.hooks?.afterResourceUpdate?.({
893
+ urn: resource.urn,
894
+ type: meta.type,
895
+ resource,
896
+ newInput: proposedState,
897
+ oldInput: priorInputState,
898
+ newOutput: result.state,
899
+ oldOutput: priorOutputState
900
+ });
826
901
  } catch (error) {
827
902
  throw ResourceError.wrap(meta.urn, meta.type, "update", error);
828
903
  }
@@ -834,13 +909,98 @@ var updateResource = async (resource, appToken, priorState, proposedState, opt)
834
909
 
835
910
  // src/workspace/procedure/deploy-app.ts
836
911
  var debug7 = createDebugger("Deploy App");
912
+ var findDependencyPaths = (value, dependencyUrn, path = []) => {
913
+ const paths = [];
914
+ const visit = (current, currentPath) => {
915
+ if (current instanceof Output) {
916
+ for (const dep of current.dependencies) {
917
+ if (dep.urn === dependencyUrn) {
918
+ paths.push(currentPath);
919
+ return;
920
+ }
921
+ }
922
+ return;
923
+ }
924
+ if (Array.isArray(current)) {
925
+ current.forEach((item, index) => {
926
+ visit(item, [...currentPath, index]);
927
+ });
928
+ return;
929
+ }
930
+ if (current && typeof current === "object") {
931
+ for (const [key, item] of Object.entries(current)) {
932
+ visit(item, [...currentPath, key]);
933
+ }
934
+ }
935
+ };
936
+ visit(value, path);
937
+ return paths;
938
+ };
939
+ var cloneState = (value) => JSON.parse(JSON.stringify(value));
940
+ var removeAtPath = (target, path) => {
941
+ if (path.length === 0) return;
942
+ let parent = target;
943
+ for (let i = 0; i < path.length - 1; i++) {
944
+ if (parent == null) return;
945
+ parent = parent[path[i]];
946
+ }
947
+ const last = path[path.length - 1];
948
+ if (Array.isArray(parent) && typeof last === "number") {
949
+ if (last >= 0 && last < parent.length) {
950
+ parent.splice(last, 1);
951
+ }
952
+ return;
953
+ }
954
+ if (parent && typeof parent === "object") {
955
+ delete parent[last];
956
+ }
957
+ };
958
+ var stripDependencyInputs = (input, metaInput, dependencyUrn) => {
959
+ const paths = findDependencyPaths(metaInput, dependencyUrn);
960
+ if (paths.length === 0) {
961
+ return input;
962
+ }
963
+ const detached = cloneState(input);
964
+ const sortedPaths = [...paths].sort((a, b) => {
965
+ if (a.length !== b.length) return b.length - a.length;
966
+ const aLast = a[a.length - 1];
967
+ const bLast = b[b.length - 1];
968
+ if (typeof aLast === "number" && typeof bLast === "number") {
969
+ return bLast - aLast;
970
+ }
971
+ return 0;
972
+ });
973
+ for (const path of sortedPaths) {
974
+ removeAtPath(detached, path);
975
+ }
976
+ return detached;
977
+ };
978
+ var allowsDependentReplace = (replaceOnChanges, dependencyPaths) => {
979
+ if (!replaceOnChanges || replaceOnChanges.length === 0) {
980
+ return false;
981
+ }
982
+ for (const path of dependencyPaths) {
983
+ const base = typeof path[0] === "string" ? path[0] : void 0;
984
+ if (!base) {
985
+ continue;
986
+ }
987
+ for (const replacePath of replaceOnChanges) {
988
+ if (replacePath === base || replacePath.startsWith(`${base}.`) || replacePath.startsWith(`${base}[`) || replacePath.startsWith(`${base}.*`)) {
989
+ return true;
990
+ }
991
+ }
992
+ }
993
+ return false;
994
+ };
837
995
  var deployApp = async (app, opt) => {
838
996
  debug7(app.name, "start");
839
997
  const latestState = await opt.backend.state.get(app.urn);
840
- const appState = migrateAppState(latestState ?? {
841
- name: app.name,
842
- stacks: {}
843
- });
998
+ const appState = migrateAppState(
999
+ latestState ?? {
1000
+ name: app.name,
1001
+ stacks: {}
1002
+ }
1003
+ );
844
1004
  const releaseOnExit = onExit(async () => {
845
1005
  await opt.backend.state.update(app.urn, appState);
846
1006
  });
@@ -854,8 +1014,22 @@ var deployApp = async (app, opt) => {
854
1014
  stacks = app.stacks.filter((stack) => opt.filters.includes(stack.name));
855
1015
  filteredOutStacks = app.stacks.filter((stack) => !opt.filters.includes(stack.name));
856
1016
  }
1017
+ const nodeByUrn = /* @__PURE__ */ new Map();
1018
+ const stackStates = /* @__PURE__ */ new Map();
1019
+ const plannedDependents = /* @__PURE__ */ new Set();
1020
+ const forcedUpdateDependents = /* @__PURE__ */ new Set();
1021
+ for (const stack of stacks) {
1022
+ const stackState = appState.stacks[stack.urn] = appState.stacks[stack.urn] ?? {
1023
+ name: stack.name,
1024
+ nodes: {}
1025
+ };
1026
+ stackStates.set(stack.urn, stackState);
1027
+ for (const node of stack.nodes) {
1028
+ nodeByUrn.set(getMeta(node).urn, node);
1029
+ }
1030
+ }
857
1031
  const queue = createConcurrencyQueue(opt.concurrency ?? 10);
858
- const graph = new DependencyGraph;
1032
+ const graph = new DependencyGraph();
859
1033
  const allNodes = {};
860
1034
  for (const stackState of Object.values(appState.stacks)) {
861
1035
  for (const [urn, nodeState] of entries(stackState.nodes)) {
@@ -886,7 +1060,15 @@ var deployApp = async (app, opt) => {
886
1060
  for (const [urn2, nodeState] of entries(stackState.nodes)) {
887
1061
  graph.add(urn2, dependentsOn(allNodes, urn2), async () => {
888
1062
  if (nodeState.tag === "resource") {
889
- await queue(() => deleteResource(appState.idempotentToken, urn2, nodeState, opt));
1063
+ await queue(
1064
+ () => deleteResource(
1065
+ //
1066
+ appState.idempotentToken,
1067
+ urn2,
1068
+ nodeState,
1069
+ opt
1070
+ )
1071
+ );
890
1072
  }
891
1073
  delete stackState.nodes[urn2];
892
1074
  });
@@ -894,16 +1076,21 @@ var deployApp = async (app, opt) => {
894
1076
  }
895
1077
  }
896
1078
  for (const stack of stacks) {
897
- const stackState = appState.stacks[stack.urn] = appState.stacks[stack.urn] ?? {
898
- name: stack.name,
899
- nodes: {}
900
- };
1079
+ const stackState = stackStates.get(stack.urn);
901
1080
  for (const [urn, nodeState] of entries(stackState.nodes)) {
902
1081
  const resource = stack.nodes.find((r) => getMeta(r).urn === urn);
903
1082
  if (!resource) {
904
1083
  graph.add(urn, dependentsOn(allNodes, urn), async () => {
905
1084
  if (nodeState.tag === "resource") {
906
- await queue(() => deleteResource(appState.idempotentToken, urn, nodeState, opt));
1085
+ await queue(
1086
+ () => deleteResource(
1087
+ //
1088
+ appState.idempotentToken,
1089
+ urn,
1090
+ nodeState,
1091
+ opt
1092
+ )
1093
+ );
907
1094
  }
908
1095
  delete stackState.nodes[urn];
909
1096
  });
@@ -915,8 +1102,9 @@ var deployApp = async (app, opt) => {
915
1102
  const partialNewResourceState = {
916
1103
  dependencies,
917
1104
  lifecycle: isResource(node) ? {
1105
+ // deleteAfterCreate: meta.config?.deleteAfterCreate,
918
1106
  retainOnDelete: getMeta(node).config?.retainOnDelete
919
- } : undefined
1107
+ } : void 0
920
1108
  };
921
1109
  graph.add(meta.urn, dependencies, () => {
922
1110
  return queue(async () => {
@@ -925,7 +1113,13 @@ var deployApp = async (app, opt) => {
925
1113
  try {
926
1114
  input = await resolveInputs(meta.input);
927
1115
  } catch (error) {
928
- throw ResourceError.wrap(meta.urn, meta.type, "resolve", error);
1116
+ throw ResourceError.wrap(
1117
+ //
1118
+ meta.urn,
1119
+ meta.type,
1120
+ "resolve",
1121
+ error
1122
+ );
929
1123
  }
930
1124
  if (isDataSource(node)) {
931
1125
  const meta2 = getMeta(node);
@@ -950,25 +1144,144 @@ var deployApp = async (app, opt) => {
950
1144
  if (!nodeState) {
951
1145
  if (meta2.config?.import) {
952
1146
  const importedState = await importResource(node, input, opt);
953
- const newResourceState = await updateResource(node, appState.idempotentToken, importedState.output, input, opt);
1147
+ const newResourceState = await updateResource(
1148
+ node,
1149
+ appState.idempotentToken,
1150
+ importedState.input,
1151
+ importedState.output,
1152
+ input,
1153
+ opt
1154
+ );
954
1155
  nodeState = stackState.nodes[meta2.urn] = {
955
1156
  ...importedState,
956
1157
  ...newResourceState,
957
1158
  ...partialNewResourceState
958
1159
  };
959
1160
  } else {
960
- const newResourceState = await createResource(node, appState.idempotentToken, input, opt);
1161
+ const newResourceState = await createResource(
1162
+ node,
1163
+ appState.idempotentToken,
1164
+ input,
1165
+ opt
1166
+ );
961
1167
  nodeState = stackState.nodes[meta2.urn] = {
962
1168
  ...newResourceState,
963
1169
  ...partialNewResourceState
964
1170
  };
965
1171
  }
966
- } else if (!compareState(nodeState.input, input)) {
1172
+ } else if (
1173
+ // --------------------------------------------------
1174
+ // Check if any state has changed
1175
+ !compareState(nodeState.input, input)
1176
+ ) {
967
1177
  let newResourceState;
968
- if (requiresReplacement(nodeState.input, input, meta2.config?.replaceOnChanges ?? [])) {
969
- newResourceState = await replaceResource(node, appState.idempotentToken, nodeState.output, input, opt);
1178
+ const ignoreReplace = forcedUpdateDependents.has(meta2.urn);
1179
+ if (!ignoreReplace && requiresReplacement(nodeState.input, input, meta2.config?.replaceOnChanges ?? [])) {
1180
+ for (const [dependentUrn, dependentNode] of nodeByUrn.entries()) {
1181
+ if (!isResource(dependentNode)) {
1182
+ continue;
1183
+ }
1184
+ const dependentMeta = getMeta(dependentNode);
1185
+ if (!dependentMeta.dependencies.has(meta2.urn)) {
1186
+ continue;
1187
+ }
1188
+ if (plannedDependents.has(dependentUrn)) {
1189
+ continue;
1190
+ }
1191
+ const dependentStackState = stackStates.get(dependentMeta.stack.urn);
1192
+ const dependentState = dependentStackState?.nodes[dependentUrn];
1193
+ if (!dependentStackState || !dependentState) {
1194
+ continue;
1195
+ }
1196
+ const dependencyPaths = findDependencyPaths(dependentMeta.input, meta2.urn);
1197
+ if (dependencyPaths.length === 0) {
1198
+ continue;
1199
+ }
1200
+ const detachedInput = stripDependencyInputs(
1201
+ dependentState.input,
1202
+ dependentMeta.input,
1203
+ meta2.urn
1204
+ );
1205
+ if (compareState(dependentState.input, detachedInput)) {
1206
+ continue;
1207
+ }
1208
+ plannedDependents.add(dependentUrn);
1209
+ let dependentRequiresReplacement = false;
1210
+ const dependentProvider = findProvider(opt.providers, dependentMeta.provider);
1211
+ if (dependentProvider.planResourceChange) {
1212
+ try {
1213
+ const dependentPlan = await dependentProvider.planResourceChange({
1214
+ type: dependentMeta.type,
1215
+ priorState: dependentState.output,
1216
+ proposedState: detachedInput
1217
+ });
1218
+ dependentRequiresReplacement = dependentPlan.requiresReplacement;
1219
+ } catch (error) {
1220
+ throw ResourceError.wrap(
1221
+ dependentMeta.urn,
1222
+ dependentMeta.type,
1223
+ "update",
1224
+ error
1225
+ );
1226
+ }
1227
+ }
1228
+ if (dependentRequiresReplacement) {
1229
+ if (!allowsDependentReplace(
1230
+ dependentMeta.config?.replaceOnChanges,
1231
+ dependencyPaths
1232
+ )) {
1233
+ throw ResourceError.wrap(
1234
+ dependentMeta.urn,
1235
+ dependentMeta.type,
1236
+ "update",
1237
+ new Error(
1238
+ `Replacing ${meta2.urn} requires ${dependentMeta.urn} to set replaceOnChanges for its dependency fields.`
1239
+ )
1240
+ );
1241
+ }
1242
+ await deleteResource(
1243
+ appState.idempotentToken,
1244
+ dependentUrn,
1245
+ dependentState,
1246
+ opt
1247
+ );
1248
+ delete dependentStackState.nodes[dependentUrn];
1249
+ } else {
1250
+ const updated = await updateResource(
1251
+ dependentNode,
1252
+ appState.idempotentToken,
1253
+ dependentState.input,
1254
+ dependentState.output,
1255
+ detachedInput,
1256
+ opt
1257
+ );
1258
+ Object.assign(dependentState, {
1259
+ input: detachedInput,
1260
+ ...updated
1261
+ });
1262
+ forcedUpdateDependents.add(dependentUrn);
1263
+ }
1264
+ }
1265
+ newResourceState = await replaceResource(
1266
+ node,
1267
+ appState.idempotentToken,
1268
+ nodeState.input,
1269
+ nodeState.output,
1270
+ input,
1271
+ opt
1272
+ );
970
1273
  } else {
971
- newResourceState = await updateResource(node, appState.idempotentToken, nodeState.output, input, opt);
1274
+ newResourceState = await updateResource(
1275
+ node,
1276
+ appState.idempotentToken,
1277
+ nodeState.input,
1278
+ nodeState.output,
1279
+ input,
1280
+ opt
1281
+ );
1282
+ if (ignoreReplace) {
1283
+ forcedUpdateDependents.delete(meta2.urn);
1284
+ }
972
1285
  }
973
1286
  Object.assign(nodeState, {
974
1287
  input,
@@ -1025,42 +1338,48 @@ var refresh = async (app, opt) => {
1025
1338
  const appState = await opt.backend.state.get(app.urn);
1026
1339
  const queue = createConcurrencyQueue(opt.concurrency ?? 10);
1027
1340
  if (appState) {
1028
- await Promise.all(Object.values(appState.stacks).map((stackState) => {
1029
- return Promise.all(Object.values(stackState.nodes).map((nodeState) => {
1030
- return queue(async () => {
1031
- const provider = findProvider(opt.providers, nodeState.provider);
1032
- if (nodeState.tag === "data") {
1033
- const result = await provider.getData?.({
1034
- type: nodeState.type,
1035
- state: nodeState.output
1036
- });
1037
- if (result && !compareState(result.state, nodeState.output)) {
1038
- nodeState.output = result.state;
1039
- nodeState.input = result.state;
1040
- }
1041
- } else if (nodeState.tag === "resource") {
1042
- const result = await provider.getResource({
1043
- type: nodeState.type,
1044
- state: nodeState.output
1341
+ await Promise.all(
1342
+ Object.values(appState.stacks).map((stackState) => {
1343
+ return Promise.all(
1344
+ Object.values(stackState.nodes).map((nodeState) => {
1345
+ return queue(async () => {
1346
+ const provider = findProvider(opt.providers, nodeState.provider);
1347
+ if (nodeState.tag === "data") {
1348
+ const result = await provider.getData?.({
1349
+ type: nodeState.type,
1350
+ state: nodeState.output
1351
+ });
1352
+ if (result && !compareState(result.state, nodeState.output)) {
1353
+ nodeState.output = result.state;
1354
+ nodeState.input = result.state;
1355
+ }
1356
+ } else if (nodeState.tag === "resource") {
1357
+ const result = await provider.getResource({
1358
+ type: nodeState.type,
1359
+ state: nodeState.output
1360
+ });
1361
+ if (result && !compareState(result.state, nodeState.output)) {
1362
+ nodeState.output = result.state;
1363
+ nodeState.input = result.state;
1364
+ }
1365
+ }
1045
1366
  });
1046
- if (result && !compareState(result.state, nodeState.output)) {
1047
- nodeState.output = result.state;
1048
- nodeState.input = result.state;
1049
- }
1050
- }
1051
- });
1052
- }));
1053
- }));
1367
+ })
1368
+ );
1369
+ })
1370
+ );
1054
1371
  await opt.backend.state.update(app.urn, appState);
1055
1372
  }
1056
1373
  };
1057
1374
 
1058
1375
  // src/workspace/workspace.ts
1059
- class WorkSpace {
1060
- props;
1376
+ var WorkSpace = class {
1061
1377
  constructor(props) {
1062
1378
  this.props = props;
1063
1379
  }
1380
+ /**
1381
+ * Deploy the entire app or use the filter option to deploy specific stacks inside your app.
1382
+ */
1064
1383
  deploy(app, options = {}) {
1065
1384
  return lockApp(this.props.backend.lock, app, async () => {
1066
1385
  try {
@@ -1070,6 +1389,9 @@ class WorkSpace {
1070
1389
  }
1071
1390
  });
1072
1391
  }
1392
+ /**
1393
+ * Delete the entire app or use the filter option to delete specific stacks inside your app.
1394
+ */
1073
1395
  delete(app, options = {}) {
1074
1396
  return lockApp(this.props.backend.lock, app, async () => {
1075
1397
  try {
@@ -1079,9 +1401,15 @@ class WorkSpace {
1079
1401
  }
1080
1402
  });
1081
1403
  }
1404
+ /**
1405
+ * Hydrate the outputs of the resources & data-sources inside your app.
1406
+ */
1082
1407
  hydrate(app) {
1083
1408
  return hydrate(app, this.props);
1084
1409
  }
1410
+ /**
1411
+ * Refresh the state of the resources & data-sources inside your app.
1412
+ */
1085
1413
  refresh(app) {
1086
1414
  return lockApp(this.props.backend.lock, app, async () => {
1087
1415
  try {
@@ -1092,14 +1420,17 @@ class WorkSpace {
1092
1420
  });
1093
1421
  }
1094
1422
  async destroyProviders() {
1095
- await Promise.all(this.props.providers.map((p) => {
1096
- return p.destroy?.();
1097
- }));
1423
+ await Promise.all(
1424
+ this.props.providers.map((p) => {
1425
+ return p.destroy?.();
1426
+ })
1427
+ );
1098
1428
  }
1099
- }
1429
+ };
1430
+
1100
1431
  // src/backend/memory/state.ts
1101
- class MemoryStateBackend {
1102
- states = new Map;
1432
+ var MemoryStateBackend = class {
1433
+ states = /* @__PURE__ */ new Map();
1103
1434
  async get(urn) {
1104
1435
  return this.states.get(urn);
1105
1436
  }
@@ -1112,10 +1443,11 @@ class MemoryStateBackend {
1112
1443
  clear() {
1113
1444
  this.states.clear();
1114
1445
  }
1115
- }
1446
+ };
1447
+
1116
1448
  // src/backend/memory/lock.ts
1117
- class MemoryLockBackend {
1118
- locks = new Map;
1449
+ var MemoryLockBackend = class {
1450
+ locks = /* @__PURE__ */ new Map();
1119
1451
  async insecureReleaseLock(urn) {
1120
1452
  this.locks.delete(urn);
1121
1453
  }
@@ -1137,14 +1469,13 @@ class MemoryLockBackend {
1137
1469
  clear() {
1138
1470
  this.locks.clear();
1139
1471
  }
1140
- }
1472
+ };
1473
+
1141
1474
  // src/backend/file/state.ts
1142
- import { mkdir, readFile, rm, writeFile } from "node:fs/promises";
1143
- import { join } from "node:path";
1475
+ import { mkdir, readFile, rm, writeFile } from "fs/promises";
1476
+ import { join } from "path";
1144
1477
  var debug8 = createDebugger("State");
1145
-
1146
- class FileStateBackend {
1147
- props;
1478
+ var FileStateBackend = class {
1148
1479
  constructor(props) {
1149
1480
  this.props = props;
1150
1481
  }
@@ -1169,21 +1500,20 @@ class FileStateBackend {
1169
1500
  async update(urn, state) {
1170
1501
  debug8("update");
1171
1502
  await this.mkdir();
1172
- await writeFile(this.stateFile(urn), JSON.stringify(state, undefined, 2));
1503
+ await writeFile(this.stateFile(urn), JSON.stringify(state, void 0, 2));
1173
1504
  }
1174
1505
  async delete(urn) {
1175
1506
  debug8("delete");
1176
1507
  await this.mkdir();
1177
1508
  await rm(this.stateFile(urn));
1178
1509
  }
1179
- }
1510
+ };
1511
+
1180
1512
  // src/backend/file/lock.ts
1181
- import { mkdir as mkdir2, rm as rm2, stat } from "node:fs/promises";
1182
- import { join as join2 } from "node:path";
1513
+ import { mkdir as mkdir2, rm as rm2, stat } from "fs/promises";
1514
+ import { join as join2 } from "path";
1183
1515
  import { lock } from "proper-lockfile";
1184
-
1185
- class FileLockBackend {
1186
- props;
1516
+ var FileLockBackend = class {
1187
1517
  constructor(props) {
1188
1518
  this.props = props;
1189
1519
  }
@@ -1210,7 +1540,8 @@ class FileLockBackend {
1210
1540
  realpath: false
1211
1541
  });
1212
1542
  }
1213
- }
1543
+ };
1544
+
1214
1545
  // src/backend/aws/s3-state.ts
1215
1546
  import {
1216
1547
  DeleteObjectCommand,
@@ -1219,21 +1550,21 @@ import {
1219
1550
  S3Client,
1220
1551
  S3ServiceException
1221
1552
  } from "@aws-sdk/client-s3";
1222
-
1223
- class S3StateBackend {
1224
- props;
1225
- client;
1553
+ var S3StateBackend = class {
1226
1554
  constructor(props) {
1227
1555
  this.props = props;
1228
1556
  this.client = new S3Client(props);
1229
1557
  }
1558
+ client;
1230
1559
  async get(urn) {
1231
1560
  let result;
1232
1561
  try {
1233
- result = await this.client.send(new GetObjectCommand({
1234
- Bucket: this.props.bucket,
1235
- Key: `${urn}.state`
1236
- }));
1562
+ result = await this.client.send(
1563
+ new GetObjectCommand({
1564
+ Bucket: this.props.bucket,
1565
+ Key: `${urn}.state`
1566
+ })
1567
+ );
1237
1568
  } catch (error) {
1238
1569
  if (error instanceof S3ServiceException && error.name === "NoSuchKey") {
1239
1570
  return;
@@ -1248,30 +1579,33 @@ class S3StateBackend {
1248
1579
  return state;
1249
1580
  }
1250
1581
  async update(urn, state) {
1251
- await this.client.send(new PutObjectCommand({
1252
- Bucket: this.props.bucket,
1253
- Key: `${urn}.state`,
1254
- Body: JSON.stringify(state)
1255
- }));
1582
+ await this.client.send(
1583
+ new PutObjectCommand({
1584
+ Bucket: this.props.bucket,
1585
+ Key: `${urn}.state`,
1586
+ Body: JSON.stringify(state)
1587
+ })
1588
+ );
1256
1589
  }
1257
1590
  async delete(urn) {
1258
- await this.client.send(new DeleteObjectCommand({
1259
- Bucket: this.props.bucket,
1260
- Key: `${urn}.state`
1261
- }));
1591
+ await this.client.send(
1592
+ new DeleteObjectCommand({
1593
+ Bucket: this.props.bucket,
1594
+ Key: `${urn}.state`
1595
+ })
1596
+ );
1262
1597
  }
1263
- }
1598
+ };
1599
+
1264
1600
  // src/backend/aws/dynamodb-lock.ts
1265
1601
  import { DynamoDB } from "@aws-sdk/client-dynamodb";
1266
1602
  import { marshall, unmarshall } from "@aws-sdk/util-dynamodb";
1267
-
1268
- class DynamoLockBackend {
1269
- props;
1270
- client;
1603
+ var DynamoLockBackend = class {
1271
1604
  constructor(props) {
1272
1605
  this.props = props;
1273
1606
  this.client = new DynamoDB(props);
1274
1607
  }
1608
+ client;
1275
1609
  async insecureReleaseLock(urn) {
1276
1610
  await this.client.updateItem({
1277
1611
  TableName: this.props.tableName,
@@ -1312,10 +1646,11 @@ class DynamoLockBackend {
1312
1646
  });
1313
1647
  };
1314
1648
  }
1315
- }
1649
+ };
1650
+
1316
1651
  // src/helpers.ts
1317
- import { createHash } from "node:crypto";
1318
- import { readFile as readFile2 } from "node:fs/promises";
1652
+ import { createHash } from "crypto";
1653
+ import { readFile as readFile2 } from "fs/promises";
1319
1654
  var file = (path, encoding = "utf8") => {
1320
1655
  return new Future(async (resolve2, reject) => {
1321
1656
  try {
@@ -1345,25 +1680,37 @@ var createCustomResourceClass = (providerId, resourceType) => {
1345
1680
  }, {
1346
1681
  construct(_, [parent, id, input, config]) {
1347
1682
  const meta = createMeta("resource", `custom:${providerId}`, parent, resourceType, id, input, config);
1348
- const node = new Proxy({}, {
1349
- get(_2, key) {
1350
- if (key === nodeMetaSymbol) {
1351
- return meta;
1352
- }
1353
- if (key === "urn") {
1354
- return meta.urn;
1355
- }
1356
- if (typeof key === "symbol") {
1357
- return;
1683
+ const node = new Proxy(
1684
+ {},
1685
+ {
1686
+ get(_2, key) {
1687
+ if (key === nodeMetaSymbol) {
1688
+ return meta;
1689
+ }
1690
+ if (key === "urn") {
1691
+ return meta.urn;
1692
+ }
1693
+ if (typeof key === "symbol") {
1694
+ return;
1695
+ }
1696
+ return meta.output((data) => data[key]);
1358
1697
  }
1359
- return meta.output((data) => data[key]);
1360
1698
  }
1361
- });
1699
+ );
1362
1700
  parent.add(node);
1363
1701
  return node;
1364
1702
  }
1703
+ // get(_, key: string) {
1704
+ // if (key === 'get') {
1705
+ // return (...args: any[]) => {
1706
+ // return get(...args)
1707
+ // }
1708
+ // }
1709
+ // return
1710
+ // },
1365
1711
  });
1366
1712
  };
1713
+
1367
1714
  // src/custom/provider.ts
1368
1715
  var createCustomProvider = (providerId, resourceProviders) => {
1369
1716
  const version = 1;
@@ -1420,6 +1767,21 @@ var createCustomProvider = (providerId, resourceProviders) => {
1420
1767
  async deleteResource({ type, ...props }) {
1421
1768
  await getProvider(type).deleteResource?.(props);
1422
1769
  },
1770
+ async planResourceChange({ type, ...props }) {
1771
+ const provider = getProvider(type);
1772
+ if (!provider.planResourceChange) {
1773
+ return {
1774
+ version,
1775
+ state: props.proposedState,
1776
+ requiresReplacement: false
1777
+ };
1778
+ }
1779
+ const result = await provider.planResourceChange(props);
1780
+ return {
1781
+ version,
1782
+ ...result
1783
+ };
1784
+ },
1423
1785
  async getData({ type, ...props }) {
1424
1786
  return {
1425
1787
  version,
@@ -1429,34 +1791,34 @@ var createCustomProvider = (providerId, resourceProviders) => {
1429
1791
  };
1430
1792
  };
1431
1793
  export {
1432
- resolveInputs,
1433
- output,
1434
- nodeMetaSymbol,
1435
- isResource,
1436
- isNode,
1437
- isDataSource,
1438
- getMeta,
1439
- findInputDeps,
1440
- enableDebug,
1441
- deferredOutput,
1442
- createMeta,
1443
- createDebugger,
1444
- createCustomResourceClass,
1445
- createCustomProvider,
1446
- WorkSpace,
1447
- Stack,
1448
- S3StateBackend,
1449
- ResourceNotFound,
1450
- ResourceError,
1451
- ResourceAlreadyExists,
1452
- Output,
1453
- MemoryStateBackend,
1454
- MemoryLockBackend,
1455
- Group,
1456
- Future,
1457
- FileStateBackend,
1458
- FileLockBackend,
1459
- DynamoLockBackend,
1794
+ App,
1460
1795
  AppError,
1461
- App
1796
+ DynamoLockBackend,
1797
+ FileLockBackend,
1798
+ FileStateBackend,
1799
+ Future,
1800
+ Group,
1801
+ MemoryLockBackend,
1802
+ MemoryStateBackend,
1803
+ Output,
1804
+ ResourceAlreadyExists,
1805
+ ResourceError,
1806
+ ResourceNotFound,
1807
+ S3StateBackend,
1808
+ Stack,
1809
+ WorkSpace,
1810
+ createCustomProvider,
1811
+ createCustomResourceClass,
1812
+ createDebugger,
1813
+ createMeta,
1814
+ deferredOutput,
1815
+ enableDebug,
1816
+ findInputDeps,
1817
+ getMeta,
1818
+ isDataSource,
1819
+ isNode,
1820
+ isResource,
1821
+ nodeMetaSymbol,
1822
+ output,
1823
+ resolveInputs
1462
1824
  };