@terraforge/core 0.0.4 → 0.0.5
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/README.md +3 -1
- package/dist/index.d.ts +281 -267
- package/dist/index.js +337 -243
- package/package.json +2 -2
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
|
-
|
|
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
|
|
42
|
-
const duplicate = this.children.filter((c) => c instanceof
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
103
|
-
name;
|
|
98
|
+
var App = class extends Group {
|
|
104
99
|
constructor(name) {
|
|
105
|
-
super(
|
|
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
|
|
134
|
+
return new _Future((resolve2, reject) => {
|
|
141
135
|
this.then((value) => {
|
|
142
136
|
Promise.resolve(cb(value)).then((value2) => {
|
|
143
|
-
|
|
137
|
+
resolve2(value2);
|
|
144
138
|
}).catch(reject);
|
|
145
139
|
}, reject);
|
|
146
140
|
});
|
|
147
141
|
}
|
|
148
|
-
then(
|
|
142
|
+
then(resolve2, reject) {
|
|
149
143
|
if (this.status === RESOLVED) {
|
|
150
|
-
|
|
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(
|
|
158
|
-
|
|
159
|
-
this.status
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
this.
|
|
168
|
-
|
|
169
|
-
|
|
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(
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
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
|
-
|
|
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
|
|
240
|
+
return new _Output(this.dependencies, (resolve2, reject) => {
|
|
239
241
|
this.then((value) => {
|
|
240
242
|
Promise.resolve(cb(value)).then((value2) => {
|
|
241
|
-
|
|
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((
|
|
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, (
|
|
257
|
+
return new Output(deps, (resolve2, reject) => {
|
|
256
258
|
Promise.all(inputs).then((result) => {
|
|
257
|
-
|
|
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
|
-
|
|
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(
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
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
|
-
|
|
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
|
-
|
|
484
|
-
|
|
485
|
-
|
|
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
|
-
|
|
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) => {
|
|
@@ -632,7 +640,7 @@ var deleteApp = async (app, opt) => {
|
|
|
632
640
|
stackStates = stackStates.filter((stackState) => opt.filters.includes(stackState.name));
|
|
633
641
|
}
|
|
634
642
|
const queue = createConcurrencyQueue(opt.concurrency ?? 10);
|
|
635
|
-
const graph = new DependencyGraph;
|
|
643
|
+
const graph = new DependencyGraph();
|
|
636
644
|
const allNodes = {};
|
|
637
645
|
for (const stackState of Object.values(appState.stacks)) {
|
|
638
646
|
for (const [urn, nodeState] of entries(stackState.nodes)) {
|
|
@@ -668,7 +676,7 @@ var requiresReplacement = (priorState, proposedState, replaceOnChanges) => {
|
|
|
668
676
|
const priorValue = get(priorState, path);
|
|
669
677
|
const proposedValue = get(proposedState, path);
|
|
670
678
|
if (path.includes("*") && Array.isArray(priorValue)) {
|
|
671
|
-
for (let i = 0;i < priorValue.length; i++) {
|
|
679
|
+
for (let i = 0; i < priorValue.length; i++) {
|
|
672
680
|
if (!compareState(priorValue[i], proposedValue[i])) {
|
|
673
681
|
return true;
|
|
674
682
|
}
|
|
@@ -837,10 +845,12 @@ var debug7 = createDebugger("Deploy App");
|
|
|
837
845
|
var deployApp = async (app, opt) => {
|
|
838
846
|
debug7(app.name, "start");
|
|
839
847
|
const latestState = await opt.backend.state.get(app.urn);
|
|
840
|
-
const appState = migrateAppState(
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
848
|
+
const appState = migrateAppState(
|
|
849
|
+
latestState ?? {
|
|
850
|
+
name: app.name,
|
|
851
|
+
stacks: {}
|
|
852
|
+
}
|
|
853
|
+
);
|
|
844
854
|
const releaseOnExit = onExit(async () => {
|
|
845
855
|
await opt.backend.state.update(app.urn, appState);
|
|
846
856
|
});
|
|
@@ -855,7 +865,7 @@ var deployApp = async (app, opt) => {
|
|
|
855
865
|
filteredOutStacks = app.stacks.filter((stack) => !opt.filters.includes(stack.name));
|
|
856
866
|
}
|
|
857
867
|
const queue = createConcurrencyQueue(opt.concurrency ?? 10);
|
|
858
|
-
const graph = new DependencyGraph;
|
|
868
|
+
const graph = new DependencyGraph();
|
|
859
869
|
const allNodes = {};
|
|
860
870
|
for (const stackState of Object.values(appState.stacks)) {
|
|
861
871
|
for (const [urn, nodeState] of entries(stackState.nodes)) {
|
|
@@ -886,7 +896,15 @@ var deployApp = async (app, opt) => {
|
|
|
886
896
|
for (const [urn2, nodeState] of entries(stackState.nodes)) {
|
|
887
897
|
graph.add(urn2, dependentsOn(allNodes, urn2), async () => {
|
|
888
898
|
if (nodeState.tag === "resource") {
|
|
889
|
-
await queue(
|
|
899
|
+
await queue(
|
|
900
|
+
() => deleteResource(
|
|
901
|
+
//
|
|
902
|
+
appState.idempotentToken,
|
|
903
|
+
urn2,
|
|
904
|
+
nodeState,
|
|
905
|
+
opt
|
|
906
|
+
)
|
|
907
|
+
);
|
|
890
908
|
}
|
|
891
909
|
delete stackState.nodes[urn2];
|
|
892
910
|
});
|
|
@@ -903,7 +921,15 @@ var deployApp = async (app, opt) => {
|
|
|
903
921
|
if (!resource) {
|
|
904
922
|
graph.add(urn, dependentsOn(allNodes, urn), async () => {
|
|
905
923
|
if (nodeState.tag === "resource") {
|
|
906
|
-
await queue(
|
|
924
|
+
await queue(
|
|
925
|
+
() => deleteResource(
|
|
926
|
+
//
|
|
927
|
+
appState.idempotentToken,
|
|
928
|
+
urn,
|
|
929
|
+
nodeState,
|
|
930
|
+
opt
|
|
931
|
+
)
|
|
932
|
+
);
|
|
907
933
|
}
|
|
908
934
|
delete stackState.nodes[urn];
|
|
909
935
|
});
|
|
@@ -915,8 +941,9 @@ var deployApp = async (app, opt) => {
|
|
|
915
941
|
const partialNewResourceState = {
|
|
916
942
|
dependencies,
|
|
917
943
|
lifecycle: isResource(node) ? {
|
|
944
|
+
// deleteAfterCreate: meta.config?.deleteAfterCreate,
|
|
918
945
|
retainOnDelete: getMeta(node).config?.retainOnDelete
|
|
919
|
-
} :
|
|
946
|
+
} : void 0
|
|
920
947
|
};
|
|
921
948
|
graph.add(meta.urn, dependencies, () => {
|
|
922
949
|
return queue(async () => {
|
|
@@ -925,7 +952,13 @@ var deployApp = async (app, opt) => {
|
|
|
925
952
|
try {
|
|
926
953
|
input = await resolveInputs(meta.input);
|
|
927
954
|
} catch (error) {
|
|
928
|
-
throw ResourceError.wrap(
|
|
955
|
+
throw ResourceError.wrap(
|
|
956
|
+
//
|
|
957
|
+
meta.urn,
|
|
958
|
+
meta.type,
|
|
959
|
+
"resolve",
|
|
960
|
+
error
|
|
961
|
+
);
|
|
929
962
|
}
|
|
930
963
|
if (isDataSource(node)) {
|
|
931
964
|
const meta2 = getMeta(node);
|
|
@@ -950,25 +983,52 @@ var deployApp = async (app, opt) => {
|
|
|
950
983
|
if (!nodeState) {
|
|
951
984
|
if (meta2.config?.import) {
|
|
952
985
|
const importedState = await importResource(node, input, opt);
|
|
953
|
-
const newResourceState = await updateResource(
|
|
986
|
+
const newResourceState = await updateResource(
|
|
987
|
+
node,
|
|
988
|
+
appState.idempotentToken,
|
|
989
|
+
importedState.output,
|
|
990
|
+
input,
|
|
991
|
+
opt
|
|
992
|
+
);
|
|
954
993
|
nodeState = stackState.nodes[meta2.urn] = {
|
|
955
994
|
...importedState,
|
|
956
995
|
...newResourceState,
|
|
957
996
|
...partialNewResourceState
|
|
958
997
|
};
|
|
959
998
|
} else {
|
|
960
|
-
const newResourceState = await createResource(
|
|
999
|
+
const newResourceState = await createResource(
|
|
1000
|
+
node,
|
|
1001
|
+
appState.idempotentToken,
|
|
1002
|
+
input,
|
|
1003
|
+
opt
|
|
1004
|
+
);
|
|
961
1005
|
nodeState = stackState.nodes[meta2.urn] = {
|
|
962
1006
|
...newResourceState,
|
|
963
1007
|
...partialNewResourceState
|
|
964
1008
|
};
|
|
965
1009
|
}
|
|
966
|
-
} else if (
|
|
1010
|
+
} else if (
|
|
1011
|
+
// --------------------------------------------------
|
|
1012
|
+
// Check if any state has changed
|
|
1013
|
+
!compareState(nodeState.input, input)
|
|
1014
|
+
) {
|
|
967
1015
|
let newResourceState;
|
|
968
1016
|
if (requiresReplacement(nodeState.input, input, meta2.config?.replaceOnChanges ?? [])) {
|
|
969
|
-
newResourceState = await replaceResource(
|
|
1017
|
+
newResourceState = await replaceResource(
|
|
1018
|
+
node,
|
|
1019
|
+
appState.idempotentToken,
|
|
1020
|
+
nodeState.output,
|
|
1021
|
+
input,
|
|
1022
|
+
opt
|
|
1023
|
+
);
|
|
970
1024
|
} else {
|
|
971
|
-
newResourceState = await updateResource(
|
|
1025
|
+
newResourceState = await updateResource(
|
|
1026
|
+
node,
|
|
1027
|
+
appState.idempotentToken,
|
|
1028
|
+
nodeState.output,
|
|
1029
|
+
input,
|
|
1030
|
+
opt
|
|
1031
|
+
);
|
|
972
1032
|
}
|
|
973
1033
|
Object.assign(nodeState, {
|
|
974
1034
|
input,
|
|
@@ -1025,42 +1085,48 @@ var refresh = async (app, opt) => {
|
|
|
1025
1085
|
const appState = await opt.backend.state.get(app.urn);
|
|
1026
1086
|
const queue = createConcurrencyQueue(opt.concurrency ?? 10);
|
|
1027
1087
|
if (appState) {
|
|
1028
|
-
await Promise.all(
|
|
1029
|
-
|
|
1030
|
-
return
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1088
|
+
await Promise.all(
|
|
1089
|
+
Object.values(appState.stacks).map((stackState) => {
|
|
1090
|
+
return Promise.all(
|
|
1091
|
+
Object.values(stackState.nodes).map((nodeState) => {
|
|
1092
|
+
return queue(async () => {
|
|
1093
|
+
const provider = findProvider(opt.providers, nodeState.provider);
|
|
1094
|
+
if (nodeState.tag === "data") {
|
|
1095
|
+
const result = await provider.getData?.({
|
|
1096
|
+
type: nodeState.type,
|
|
1097
|
+
state: nodeState.output
|
|
1098
|
+
});
|
|
1099
|
+
if (result && !compareState(result.state, nodeState.output)) {
|
|
1100
|
+
nodeState.output = result.state;
|
|
1101
|
+
nodeState.input = result.state;
|
|
1102
|
+
}
|
|
1103
|
+
} else if (nodeState.tag === "resource") {
|
|
1104
|
+
const result = await provider.getResource({
|
|
1105
|
+
type: nodeState.type,
|
|
1106
|
+
state: nodeState.output
|
|
1107
|
+
});
|
|
1108
|
+
if (result && !compareState(result.state, nodeState.output)) {
|
|
1109
|
+
nodeState.output = result.state;
|
|
1110
|
+
nodeState.input = result.state;
|
|
1111
|
+
}
|
|
1112
|
+
}
|
|
1045
1113
|
});
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
}
|
|
1051
|
-
});
|
|
1052
|
-
}));
|
|
1053
|
-
}));
|
|
1114
|
+
})
|
|
1115
|
+
);
|
|
1116
|
+
})
|
|
1117
|
+
);
|
|
1054
1118
|
await opt.backend.state.update(app.urn, appState);
|
|
1055
1119
|
}
|
|
1056
1120
|
};
|
|
1057
1121
|
|
|
1058
1122
|
// src/workspace/workspace.ts
|
|
1059
|
-
|
|
1060
|
-
props;
|
|
1123
|
+
var WorkSpace = class {
|
|
1061
1124
|
constructor(props) {
|
|
1062
1125
|
this.props = props;
|
|
1063
1126
|
}
|
|
1127
|
+
/**
|
|
1128
|
+
* Deploy the entire app or use the filter option to deploy specific stacks inside your app.
|
|
1129
|
+
*/
|
|
1064
1130
|
deploy(app, options = {}) {
|
|
1065
1131
|
return lockApp(this.props.backend.lock, app, async () => {
|
|
1066
1132
|
try {
|
|
@@ -1070,6 +1136,9 @@ class WorkSpace {
|
|
|
1070
1136
|
}
|
|
1071
1137
|
});
|
|
1072
1138
|
}
|
|
1139
|
+
/**
|
|
1140
|
+
* Delete the entire app or use the filter option to delete specific stacks inside your app.
|
|
1141
|
+
*/
|
|
1073
1142
|
delete(app, options = {}) {
|
|
1074
1143
|
return lockApp(this.props.backend.lock, app, async () => {
|
|
1075
1144
|
try {
|
|
@@ -1079,9 +1148,15 @@ class WorkSpace {
|
|
|
1079
1148
|
}
|
|
1080
1149
|
});
|
|
1081
1150
|
}
|
|
1151
|
+
/**
|
|
1152
|
+
* Hydrate the outputs of the resources & data-sources inside your app.
|
|
1153
|
+
*/
|
|
1082
1154
|
hydrate(app) {
|
|
1083
1155
|
return hydrate(app, this.props);
|
|
1084
1156
|
}
|
|
1157
|
+
/**
|
|
1158
|
+
* Refresh the state of the resources & data-sources inside your app.
|
|
1159
|
+
*/
|
|
1085
1160
|
refresh(app) {
|
|
1086
1161
|
return lockApp(this.props.backend.lock, app, async () => {
|
|
1087
1162
|
try {
|
|
@@ -1092,14 +1167,17 @@ class WorkSpace {
|
|
|
1092
1167
|
});
|
|
1093
1168
|
}
|
|
1094
1169
|
async destroyProviders() {
|
|
1095
|
-
await Promise.all(
|
|
1096
|
-
|
|
1097
|
-
|
|
1170
|
+
await Promise.all(
|
|
1171
|
+
this.props.providers.map((p) => {
|
|
1172
|
+
return p.destroy?.();
|
|
1173
|
+
})
|
|
1174
|
+
);
|
|
1098
1175
|
}
|
|
1099
|
-
}
|
|
1176
|
+
};
|
|
1177
|
+
|
|
1100
1178
|
// src/backend/memory/state.ts
|
|
1101
|
-
|
|
1102
|
-
states = new Map;
|
|
1179
|
+
var MemoryStateBackend = class {
|
|
1180
|
+
states = /* @__PURE__ */ new Map();
|
|
1103
1181
|
async get(urn) {
|
|
1104
1182
|
return this.states.get(urn);
|
|
1105
1183
|
}
|
|
@@ -1112,10 +1190,11 @@ class MemoryStateBackend {
|
|
|
1112
1190
|
clear() {
|
|
1113
1191
|
this.states.clear();
|
|
1114
1192
|
}
|
|
1115
|
-
}
|
|
1193
|
+
};
|
|
1194
|
+
|
|
1116
1195
|
// src/backend/memory/lock.ts
|
|
1117
|
-
|
|
1118
|
-
locks = new Map;
|
|
1196
|
+
var MemoryLockBackend = class {
|
|
1197
|
+
locks = /* @__PURE__ */ new Map();
|
|
1119
1198
|
async insecureReleaseLock(urn) {
|
|
1120
1199
|
this.locks.delete(urn);
|
|
1121
1200
|
}
|
|
@@ -1137,14 +1216,13 @@ class MemoryLockBackend {
|
|
|
1137
1216
|
clear() {
|
|
1138
1217
|
this.locks.clear();
|
|
1139
1218
|
}
|
|
1140
|
-
}
|
|
1219
|
+
};
|
|
1220
|
+
|
|
1141
1221
|
// src/backend/file/state.ts
|
|
1142
|
-
import { mkdir, readFile, rm, writeFile } from "
|
|
1143
|
-
import { join } from "
|
|
1222
|
+
import { mkdir, readFile, rm, writeFile } from "fs/promises";
|
|
1223
|
+
import { join } from "path";
|
|
1144
1224
|
var debug8 = createDebugger("State");
|
|
1145
|
-
|
|
1146
|
-
class FileStateBackend {
|
|
1147
|
-
props;
|
|
1225
|
+
var FileStateBackend = class {
|
|
1148
1226
|
constructor(props) {
|
|
1149
1227
|
this.props = props;
|
|
1150
1228
|
}
|
|
@@ -1169,21 +1247,20 @@ class FileStateBackend {
|
|
|
1169
1247
|
async update(urn, state) {
|
|
1170
1248
|
debug8("update");
|
|
1171
1249
|
await this.mkdir();
|
|
1172
|
-
await writeFile(this.stateFile(urn), JSON.stringify(state,
|
|
1250
|
+
await writeFile(this.stateFile(urn), JSON.stringify(state, void 0, 2));
|
|
1173
1251
|
}
|
|
1174
1252
|
async delete(urn) {
|
|
1175
1253
|
debug8("delete");
|
|
1176
1254
|
await this.mkdir();
|
|
1177
1255
|
await rm(this.stateFile(urn));
|
|
1178
1256
|
}
|
|
1179
|
-
}
|
|
1257
|
+
};
|
|
1258
|
+
|
|
1180
1259
|
// src/backend/file/lock.ts
|
|
1181
|
-
import { mkdir as mkdir2, rm as rm2, stat } from "
|
|
1182
|
-
import { join as join2 } from "
|
|
1260
|
+
import { mkdir as mkdir2, rm as rm2, stat } from "fs/promises";
|
|
1261
|
+
import { join as join2 } from "path";
|
|
1183
1262
|
import { lock } from "proper-lockfile";
|
|
1184
|
-
|
|
1185
|
-
class FileLockBackend {
|
|
1186
|
-
props;
|
|
1263
|
+
var FileLockBackend = class {
|
|
1187
1264
|
constructor(props) {
|
|
1188
1265
|
this.props = props;
|
|
1189
1266
|
}
|
|
@@ -1210,7 +1287,8 @@ class FileLockBackend {
|
|
|
1210
1287
|
realpath: false
|
|
1211
1288
|
});
|
|
1212
1289
|
}
|
|
1213
|
-
}
|
|
1290
|
+
};
|
|
1291
|
+
|
|
1214
1292
|
// src/backend/aws/s3-state.ts
|
|
1215
1293
|
import {
|
|
1216
1294
|
DeleteObjectCommand,
|
|
@@ -1219,21 +1297,21 @@ import {
|
|
|
1219
1297
|
S3Client,
|
|
1220
1298
|
S3ServiceException
|
|
1221
1299
|
} from "@aws-sdk/client-s3";
|
|
1222
|
-
|
|
1223
|
-
class S3StateBackend {
|
|
1224
|
-
props;
|
|
1225
|
-
client;
|
|
1300
|
+
var S3StateBackend = class {
|
|
1226
1301
|
constructor(props) {
|
|
1227
1302
|
this.props = props;
|
|
1228
1303
|
this.client = new S3Client(props);
|
|
1229
1304
|
}
|
|
1305
|
+
client;
|
|
1230
1306
|
async get(urn) {
|
|
1231
1307
|
let result;
|
|
1232
1308
|
try {
|
|
1233
|
-
result = await this.client.send(
|
|
1234
|
-
|
|
1235
|
-
|
|
1236
|
-
|
|
1309
|
+
result = await this.client.send(
|
|
1310
|
+
new GetObjectCommand({
|
|
1311
|
+
Bucket: this.props.bucket,
|
|
1312
|
+
Key: `${urn}.state`
|
|
1313
|
+
})
|
|
1314
|
+
);
|
|
1237
1315
|
} catch (error) {
|
|
1238
1316
|
if (error instanceof S3ServiceException && error.name === "NoSuchKey") {
|
|
1239
1317
|
return;
|
|
@@ -1248,30 +1326,33 @@ class S3StateBackend {
|
|
|
1248
1326
|
return state;
|
|
1249
1327
|
}
|
|
1250
1328
|
async update(urn, state) {
|
|
1251
|
-
await this.client.send(
|
|
1252
|
-
|
|
1253
|
-
|
|
1254
|
-
|
|
1255
|
-
|
|
1329
|
+
await this.client.send(
|
|
1330
|
+
new PutObjectCommand({
|
|
1331
|
+
Bucket: this.props.bucket,
|
|
1332
|
+
Key: `${urn}.state`,
|
|
1333
|
+
Body: JSON.stringify(state)
|
|
1334
|
+
})
|
|
1335
|
+
);
|
|
1256
1336
|
}
|
|
1257
1337
|
async delete(urn) {
|
|
1258
|
-
await this.client.send(
|
|
1259
|
-
|
|
1260
|
-
|
|
1261
|
-
|
|
1338
|
+
await this.client.send(
|
|
1339
|
+
new DeleteObjectCommand({
|
|
1340
|
+
Bucket: this.props.bucket,
|
|
1341
|
+
Key: `${urn}.state`
|
|
1342
|
+
})
|
|
1343
|
+
);
|
|
1262
1344
|
}
|
|
1263
|
-
}
|
|
1345
|
+
};
|
|
1346
|
+
|
|
1264
1347
|
// src/backend/aws/dynamodb-lock.ts
|
|
1265
1348
|
import { DynamoDB } from "@aws-sdk/client-dynamodb";
|
|
1266
1349
|
import { marshall, unmarshall } from "@aws-sdk/util-dynamodb";
|
|
1267
|
-
|
|
1268
|
-
class DynamoLockBackend {
|
|
1269
|
-
props;
|
|
1270
|
-
client;
|
|
1350
|
+
var DynamoLockBackend = class {
|
|
1271
1351
|
constructor(props) {
|
|
1272
1352
|
this.props = props;
|
|
1273
1353
|
this.client = new DynamoDB(props);
|
|
1274
1354
|
}
|
|
1355
|
+
client;
|
|
1275
1356
|
async insecureReleaseLock(urn) {
|
|
1276
1357
|
await this.client.updateItem({
|
|
1277
1358
|
TableName: this.props.tableName,
|
|
@@ -1312,10 +1393,11 @@ class DynamoLockBackend {
|
|
|
1312
1393
|
});
|
|
1313
1394
|
};
|
|
1314
1395
|
}
|
|
1315
|
-
}
|
|
1396
|
+
};
|
|
1397
|
+
|
|
1316
1398
|
// src/helpers.ts
|
|
1317
|
-
import { createHash } from "
|
|
1318
|
-
import { readFile as readFile2 } from "
|
|
1399
|
+
import { createHash } from "crypto";
|
|
1400
|
+
import { readFile as readFile2 } from "fs/promises";
|
|
1319
1401
|
var file = (path, encoding = "utf8") => {
|
|
1320
1402
|
return new Future(async (resolve2, reject) => {
|
|
1321
1403
|
try {
|
|
@@ -1345,25 +1427,37 @@ var createCustomResourceClass = (providerId, resourceType) => {
|
|
|
1345
1427
|
}, {
|
|
1346
1428
|
construct(_, [parent, id, input, config]) {
|
|
1347
1429
|
const meta = createMeta("resource", `custom:${providerId}`, parent, resourceType, id, input, config);
|
|
1348
|
-
const node = new Proxy(
|
|
1349
|
-
|
|
1350
|
-
|
|
1351
|
-
|
|
1352
|
-
|
|
1353
|
-
|
|
1354
|
-
|
|
1355
|
-
|
|
1356
|
-
|
|
1357
|
-
|
|
1430
|
+
const node = new Proxy(
|
|
1431
|
+
{},
|
|
1432
|
+
{
|
|
1433
|
+
get(_2, key) {
|
|
1434
|
+
if (key === nodeMetaSymbol) {
|
|
1435
|
+
return meta;
|
|
1436
|
+
}
|
|
1437
|
+
if (key === "urn") {
|
|
1438
|
+
return meta.urn;
|
|
1439
|
+
}
|
|
1440
|
+
if (typeof key === "symbol") {
|
|
1441
|
+
return;
|
|
1442
|
+
}
|
|
1443
|
+
return meta.output((data) => data[key]);
|
|
1358
1444
|
}
|
|
1359
|
-
return meta.output((data) => data[key]);
|
|
1360
1445
|
}
|
|
1361
|
-
|
|
1446
|
+
);
|
|
1362
1447
|
parent.add(node);
|
|
1363
1448
|
return node;
|
|
1364
1449
|
}
|
|
1450
|
+
// get(_, key: string) {
|
|
1451
|
+
// if (key === 'get') {
|
|
1452
|
+
// return (...args: any[]) => {
|
|
1453
|
+
// return get(...args)
|
|
1454
|
+
// }
|
|
1455
|
+
// }
|
|
1456
|
+
// return
|
|
1457
|
+
// },
|
|
1365
1458
|
});
|
|
1366
1459
|
};
|
|
1460
|
+
|
|
1367
1461
|
// src/custom/provider.ts
|
|
1368
1462
|
var createCustomProvider = (providerId, resourceProviders) => {
|
|
1369
1463
|
const version = 1;
|
|
@@ -1429,34 +1523,34 @@ var createCustomProvider = (providerId, resourceProviders) => {
|
|
|
1429
1523
|
};
|
|
1430
1524
|
};
|
|
1431
1525
|
export {
|
|
1432
|
-
|
|
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,
|
|
1526
|
+
App,
|
|
1460
1527
|
AppError,
|
|
1461
|
-
|
|
1528
|
+
DynamoLockBackend,
|
|
1529
|
+
FileLockBackend,
|
|
1530
|
+
FileStateBackend,
|
|
1531
|
+
Future,
|
|
1532
|
+
Group,
|
|
1533
|
+
MemoryLockBackend,
|
|
1534
|
+
MemoryStateBackend,
|
|
1535
|
+
Output,
|
|
1536
|
+
ResourceAlreadyExists,
|
|
1537
|
+
ResourceError,
|
|
1538
|
+
ResourceNotFound,
|
|
1539
|
+
S3StateBackend,
|
|
1540
|
+
Stack,
|
|
1541
|
+
WorkSpace,
|
|
1542
|
+
createCustomProvider,
|
|
1543
|
+
createCustomResourceClass,
|
|
1544
|
+
createDebugger,
|
|
1545
|
+
createMeta,
|
|
1546
|
+
deferredOutput,
|
|
1547
|
+
enableDebug,
|
|
1548
|
+
findInputDeps,
|
|
1549
|
+
getMeta,
|
|
1550
|
+
isDataSource,
|
|
1551
|
+
isNode,
|
|
1552
|
+
isResource,
|
|
1553
|
+
nodeMetaSymbol,
|
|
1554
|
+
output,
|
|
1555
|
+
resolveInputs
|
|
1462
1556
|
};
|