@terraforge/core 0.0.3 → 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 +282 -253
- package/dist/index.js +359 -218
- 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);
|
|
@@ -382,7 +396,7 @@ var lockApp = async (lockBackend, app, fn) => {
|
|
|
382
396
|
|
|
383
397
|
// src/workspace/concurrency.ts
|
|
384
398
|
import promiseLimit from "p-limit";
|
|
385
|
-
var
|
|
399
|
+
var createConcurrencyQueue = (concurrency) => {
|
|
386
400
|
const queue = promiseLimit(concurrency);
|
|
387
401
|
return (cb) => {
|
|
388
402
|
return queue(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) => {
|
|
@@ -631,8 +639,8 @@ var deleteApp = async (app, opt) => {
|
|
|
631
639
|
if (opt.filters && opt.filters.length > 0) {
|
|
632
640
|
stackStates = stackStates.filter((stackState) => opt.filters.includes(stackState.name));
|
|
633
641
|
}
|
|
634
|
-
const queue =
|
|
635
|
-
const graph = new DependencyGraph;
|
|
642
|
+
const queue = createConcurrencyQueue(opt.concurrency ?? 10);
|
|
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
|
});
|
|
@@ -854,8 +864,8 @@ var deployApp = async (app, opt) => {
|
|
|
854
864
|
stacks = app.stacks.filter((stack) => opt.filters.includes(stack.name));
|
|
855
865
|
filteredOutStacks = app.stacks.filter((stack) => !opt.filters.includes(stack.name));
|
|
856
866
|
}
|
|
857
|
-
const queue =
|
|
858
|
-
const graph = new DependencyGraph;
|
|
867
|
+
const queue = createConcurrencyQueue(opt.concurrency ?? 10);
|
|
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,
|
|
@@ -1020,12 +1080,53 @@ var hydrate = async (app, opt) => {
|
|
|
1020
1080
|
}
|
|
1021
1081
|
};
|
|
1022
1082
|
|
|
1083
|
+
// src/workspace/procedure/refresh.ts
|
|
1084
|
+
var refresh = async (app, opt) => {
|
|
1085
|
+
const appState = await opt.backend.state.get(app.urn);
|
|
1086
|
+
const queue = createConcurrencyQueue(opt.concurrency ?? 10);
|
|
1087
|
+
if (appState) {
|
|
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
|
+
}
|
|
1113
|
+
});
|
|
1114
|
+
})
|
|
1115
|
+
);
|
|
1116
|
+
})
|
|
1117
|
+
);
|
|
1118
|
+
await opt.backend.state.update(app.urn, appState);
|
|
1119
|
+
}
|
|
1120
|
+
};
|
|
1121
|
+
|
|
1023
1122
|
// src/workspace/workspace.ts
|
|
1024
|
-
|
|
1025
|
-
props;
|
|
1123
|
+
var WorkSpace = class {
|
|
1026
1124
|
constructor(props) {
|
|
1027
1125
|
this.props = props;
|
|
1028
1126
|
}
|
|
1127
|
+
/**
|
|
1128
|
+
* Deploy the entire app or use the filter option to deploy specific stacks inside your app.
|
|
1129
|
+
*/
|
|
1029
1130
|
deploy(app, options = {}) {
|
|
1030
1131
|
return lockApp(this.props.backend.lock, app, async () => {
|
|
1031
1132
|
try {
|
|
@@ -1035,6 +1136,9 @@ class WorkSpace {
|
|
|
1035
1136
|
}
|
|
1036
1137
|
});
|
|
1037
1138
|
}
|
|
1139
|
+
/**
|
|
1140
|
+
* Delete the entire app or use the filter option to delete specific stacks inside your app.
|
|
1141
|
+
*/
|
|
1038
1142
|
delete(app, options = {}) {
|
|
1039
1143
|
return lockApp(this.props.backend.lock, app, async () => {
|
|
1040
1144
|
try {
|
|
@@ -1044,18 +1148,36 @@ class WorkSpace {
|
|
|
1044
1148
|
}
|
|
1045
1149
|
});
|
|
1046
1150
|
}
|
|
1151
|
+
/**
|
|
1152
|
+
* Hydrate the outputs of the resources & data-sources inside your app.
|
|
1153
|
+
*/
|
|
1047
1154
|
hydrate(app) {
|
|
1048
1155
|
return hydrate(app, this.props);
|
|
1049
1156
|
}
|
|
1157
|
+
/**
|
|
1158
|
+
* Refresh the state of the resources & data-sources inside your app.
|
|
1159
|
+
*/
|
|
1160
|
+
refresh(app) {
|
|
1161
|
+
return lockApp(this.props.backend.lock, app, async () => {
|
|
1162
|
+
try {
|
|
1163
|
+
await refresh(app, this.props);
|
|
1164
|
+
} finally {
|
|
1165
|
+
await this.destroyProviders();
|
|
1166
|
+
}
|
|
1167
|
+
});
|
|
1168
|
+
}
|
|
1050
1169
|
async destroyProviders() {
|
|
1051
|
-
await Promise.all(
|
|
1052
|
-
|
|
1053
|
-
|
|
1170
|
+
await Promise.all(
|
|
1171
|
+
this.props.providers.map((p) => {
|
|
1172
|
+
return p.destroy?.();
|
|
1173
|
+
})
|
|
1174
|
+
);
|
|
1054
1175
|
}
|
|
1055
|
-
}
|
|
1176
|
+
};
|
|
1177
|
+
|
|
1056
1178
|
// src/backend/memory/state.ts
|
|
1057
|
-
|
|
1058
|
-
states = new Map;
|
|
1179
|
+
var MemoryStateBackend = class {
|
|
1180
|
+
states = /* @__PURE__ */ new Map();
|
|
1059
1181
|
async get(urn) {
|
|
1060
1182
|
return this.states.get(urn);
|
|
1061
1183
|
}
|
|
@@ -1068,10 +1190,11 @@ class MemoryStateBackend {
|
|
|
1068
1190
|
clear() {
|
|
1069
1191
|
this.states.clear();
|
|
1070
1192
|
}
|
|
1071
|
-
}
|
|
1193
|
+
};
|
|
1194
|
+
|
|
1072
1195
|
// src/backend/memory/lock.ts
|
|
1073
|
-
|
|
1074
|
-
locks = new Map;
|
|
1196
|
+
var MemoryLockBackend = class {
|
|
1197
|
+
locks = /* @__PURE__ */ new Map();
|
|
1075
1198
|
async insecureReleaseLock(urn) {
|
|
1076
1199
|
this.locks.delete(urn);
|
|
1077
1200
|
}
|
|
@@ -1093,14 +1216,13 @@ class MemoryLockBackend {
|
|
|
1093
1216
|
clear() {
|
|
1094
1217
|
this.locks.clear();
|
|
1095
1218
|
}
|
|
1096
|
-
}
|
|
1219
|
+
};
|
|
1220
|
+
|
|
1097
1221
|
// src/backend/file/state.ts
|
|
1098
|
-
import { mkdir, readFile, rm, writeFile } from "
|
|
1099
|
-
import { join } from "
|
|
1222
|
+
import { mkdir, readFile, rm, writeFile } from "fs/promises";
|
|
1223
|
+
import { join } from "path";
|
|
1100
1224
|
var debug8 = createDebugger("State");
|
|
1101
|
-
|
|
1102
|
-
class FileStateBackend {
|
|
1103
|
-
props;
|
|
1225
|
+
var FileStateBackend = class {
|
|
1104
1226
|
constructor(props) {
|
|
1105
1227
|
this.props = props;
|
|
1106
1228
|
}
|
|
@@ -1125,21 +1247,20 @@ class FileStateBackend {
|
|
|
1125
1247
|
async update(urn, state) {
|
|
1126
1248
|
debug8("update");
|
|
1127
1249
|
await this.mkdir();
|
|
1128
|
-
await writeFile(this.stateFile(urn), JSON.stringify(state,
|
|
1250
|
+
await writeFile(this.stateFile(urn), JSON.stringify(state, void 0, 2));
|
|
1129
1251
|
}
|
|
1130
1252
|
async delete(urn) {
|
|
1131
1253
|
debug8("delete");
|
|
1132
1254
|
await this.mkdir();
|
|
1133
1255
|
await rm(this.stateFile(urn));
|
|
1134
1256
|
}
|
|
1135
|
-
}
|
|
1257
|
+
};
|
|
1258
|
+
|
|
1136
1259
|
// src/backend/file/lock.ts
|
|
1137
|
-
import { mkdir as mkdir2, rm as rm2, stat } from "
|
|
1138
|
-
import { join as join2 } from "
|
|
1260
|
+
import { mkdir as mkdir2, rm as rm2, stat } from "fs/promises";
|
|
1261
|
+
import { join as join2 } from "path";
|
|
1139
1262
|
import { lock } from "proper-lockfile";
|
|
1140
|
-
|
|
1141
|
-
class FileLockBackend {
|
|
1142
|
-
props;
|
|
1263
|
+
var FileLockBackend = class {
|
|
1143
1264
|
constructor(props) {
|
|
1144
1265
|
this.props = props;
|
|
1145
1266
|
}
|
|
@@ -1166,7 +1287,8 @@ class FileLockBackend {
|
|
|
1166
1287
|
realpath: false
|
|
1167
1288
|
});
|
|
1168
1289
|
}
|
|
1169
|
-
}
|
|
1290
|
+
};
|
|
1291
|
+
|
|
1170
1292
|
// src/backend/aws/s3-state.ts
|
|
1171
1293
|
import {
|
|
1172
1294
|
DeleteObjectCommand,
|
|
@@ -1175,21 +1297,21 @@ import {
|
|
|
1175
1297
|
S3Client,
|
|
1176
1298
|
S3ServiceException
|
|
1177
1299
|
} from "@aws-sdk/client-s3";
|
|
1178
|
-
|
|
1179
|
-
class S3StateBackend {
|
|
1180
|
-
props;
|
|
1181
|
-
client;
|
|
1300
|
+
var S3StateBackend = class {
|
|
1182
1301
|
constructor(props) {
|
|
1183
1302
|
this.props = props;
|
|
1184
1303
|
this.client = new S3Client(props);
|
|
1185
1304
|
}
|
|
1305
|
+
client;
|
|
1186
1306
|
async get(urn) {
|
|
1187
1307
|
let result;
|
|
1188
1308
|
try {
|
|
1189
|
-
result = await this.client.send(
|
|
1190
|
-
|
|
1191
|
-
|
|
1192
|
-
|
|
1309
|
+
result = await this.client.send(
|
|
1310
|
+
new GetObjectCommand({
|
|
1311
|
+
Bucket: this.props.bucket,
|
|
1312
|
+
Key: `${urn}.state`
|
|
1313
|
+
})
|
|
1314
|
+
);
|
|
1193
1315
|
} catch (error) {
|
|
1194
1316
|
if (error instanceof S3ServiceException && error.name === "NoSuchKey") {
|
|
1195
1317
|
return;
|
|
@@ -1204,30 +1326,33 @@ class S3StateBackend {
|
|
|
1204
1326
|
return state;
|
|
1205
1327
|
}
|
|
1206
1328
|
async update(urn, state) {
|
|
1207
|
-
await this.client.send(
|
|
1208
|
-
|
|
1209
|
-
|
|
1210
|
-
|
|
1211
|
-
|
|
1329
|
+
await this.client.send(
|
|
1330
|
+
new PutObjectCommand({
|
|
1331
|
+
Bucket: this.props.bucket,
|
|
1332
|
+
Key: `${urn}.state`,
|
|
1333
|
+
Body: JSON.stringify(state)
|
|
1334
|
+
})
|
|
1335
|
+
);
|
|
1212
1336
|
}
|
|
1213
1337
|
async delete(urn) {
|
|
1214
|
-
await this.client.send(
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
|
|
1338
|
+
await this.client.send(
|
|
1339
|
+
new DeleteObjectCommand({
|
|
1340
|
+
Bucket: this.props.bucket,
|
|
1341
|
+
Key: `${urn}.state`
|
|
1342
|
+
})
|
|
1343
|
+
);
|
|
1218
1344
|
}
|
|
1219
|
-
}
|
|
1345
|
+
};
|
|
1346
|
+
|
|
1220
1347
|
// src/backend/aws/dynamodb-lock.ts
|
|
1221
1348
|
import { DynamoDB } from "@aws-sdk/client-dynamodb";
|
|
1222
1349
|
import { marshall, unmarshall } from "@aws-sdk/util-dynamodb";
|
|
1223
|
-
|
|
1224
|
-
class DynamoLockBackend {
|
|
1225
|
-
props;
|
|
1226
|
-
client;
|
|
1350
|
+
var DynamoLockBackend = class {
|
|
1227
1351
|
constructor(props) {
|
|
1228
1352
|
this.props = props;
|
|
1229
1353
|
this.client = new DynamoDB(props);
|
|
1230
1354
|
}
|
|
1355
|
+
client;
|
|
1231
1356
|
async insecureReleaseLock(urn) {
|
|
1232
1357
|
await this.client.updateItem({
|
|
1233
1358
|
TableName: this.props.tableName,
|
|
@@ -1268,10 +1393,11 @@ class DynamoLockBackend {
|
|
|
1268
1393
|
});
|
|
1269
1394
|
};
|
|
1270
1395
|
}
|
|
1271
|
-
}
|
|
1396
|
+
};
|
|
1397
|
+
|
|
1272
1398
|
// src/helpers.ts
|
|
1273
|
-
import { createHash } from "
|
|
1274
|
-
import { readFile as readFile2 } from "
|
|
1399
|
+
import { createHash } from "crypto";
|
|
1400
|
+
import { readFile as readFile2 } from "fs/promises";
|
|
1275
1401
|
var file = (path, encoding = "utf8") => {
|
|
1276
1402
|
return new Future(async (resolve2, reject) => {
|
|
1277
1403
|
try {
|
|
@@ -1301,22 +1427,37 @@ var createCustomResourceClass = (providerId, resourceType) => {
|
|
|
1301
1427
|
}, {
|
|
1302
1428
|
construct(_, [parent, id, input, config]) {
|
|
1303
1429
|
const meta = createMeta("resource", `custom:${providerId}`, parent, resourceType, id, input, config);
|
|
1304
|
-
const node = new Proxy(
|
|
1305
|
-
|
|
1306
|
-
|
|
1307
|
-
|
|
1308
|
-
|
|
1309
|
-
|
|
1310
|
-
|
|
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]);
|
|
1311
1444
|
}
|
|
1312
|
-
return meta.output((data) => data[key]);
|
|
1313
1445
|
}
|
|
1314
|
-
|
|
1446
|
+
);
|
|
1315
1447
|
parent.add(node);
|
|
1316
1448
|
return node;
|
|
1317
1449
|
}
|
|
1450
|
+
// get(_, key: string) {
|
|
1451
|
+
// if (key === 'get') {
|
|
1452
|
+
// return (...args: any[]) => {
|
|
1453
|
+
// return get(...args)
|
|
1454
|
+
// }
|
|
1455
|
+
// }
|
|
1456
|
+
// return
|
|
1457
|
+
// },
|
|
1318
1458
|
});
|
|
1319
1459
|
};
|
|
1460
|
+
|
|
1320
1461
|
// src/custom/provider.ts
|
|
1321
1462
|
var createCustomProvider = (providerId, resourceProviders) => {
|
|
1322
1463
|
const version = 1;
|
|
@@ -1382,34 +1523,34 @@ var createCustomProvider = (providerId, resourceProviders) => {
|
|
|
1382
1523
|
};
|
|
1383
1524
|
};
|
|
1384
1525
|
export {
|
|
1385
|
-
|
|
1386
|
-
output,
|
|
1387
|
-
nodeMetaSymbol,
|
|
1388
|
-
isResource,
|
|
1389
|
-
isNode,
|
|
1390
|
-
isDataSource,
|
|
1391
|
-
getMeta,
|
|
1392
|
-
findInputDeps,
|
|
1393
|
-
enableDebug,
|
|
1394
|
-
deferredOutput,
|
|
1395
|
-
createMeta,
|
|
1396
|
-
createDebugger,
|
|
1397
|
-
createCustomResourceClass,
|
|
1398
|
-
createCustomProvider,
|
|
1399
|
-
WorkSpace,
|
|
1400
|
-
Stack,
|
|
1401
|
-
S3StateBackend,
|
|
1402
|
-
ResourceNotFound,
|
|
1403
|
-
ResourceError,
|
|
1404
|
-
ResourceAlreadyExists,
|
|
1405
|
-
Output,
|
|
1406
|
-
MemoryStateBackend,
|
|
1407
|
-
MemoryLockBackend,
|
|
1408
|
-
Group,
|
|
1409
|
-
Future,
|
|
1410
|
-
FileStateBackend,
|
|
1411
|
-
FileLockBackend,
|
|
1412
|
-
DynamoLockBackend,
|
|
1526
|
+
App,
|
|
1413
1527
|
AppError,
|
|
1414
|
-
|
|
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
|
|
1415
1556
|
};
|