@terraforge/core 0.0.2 → 0.0.4
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 +0 -3
- package/dist/index.d.ts +36 -19
- package/dist/index.js +128 -61
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -7,9 +7,6 @@ The core of Terraforge lives in `@terraforge/core`, with the Terraform bridge in
|
|
|
7
7
|
|
|
8
8
|
The most used IaC solutions are slow & don't effectively leverage diffing to speed up their deployments.
|
|
9
9
|
|
|
10
|
-
## Todo's
|
|
11
|
-
- When a resource is being deleted inside a deployment we need to make sure that resources that depends on our deleted resource will be updated first.
|
|
12
|
-
|
|
13
10
|
## Setup
|
|
14
11
|
|
|
15
12
|
Install with (NPM):
|
package/dist/index.d.ts
CHANGED
|
@@ -21,6 +21,25 @@ declare class Output<T = unknown> extends Future<T> {
|
|
|
21
21
|
}
|
|
22
22
|
declare const deferredOutput: unknown;
|
|
23
23
|
declare const output: unknown;
|
|
24
|
+
type URN = `urn:${string}`;
|
|
25
|
+
declare const nodeMetaSymbol: unknown;
|
|
26
|
+
type Node<
|
|
27
|
+
T extends Tag = Tag,
|
|
28
|
+
I extends State = State,
|
|
29
|
+
O extends State = any,
|
|
30
|
+
C extends Config = Config
|
|
31
|
+
> = {
|
|
32
|
+
readonly [nodeMetaSymbol]: Meta<T, I, O, C>;
|
|
33
|
+
readonly urn: URN;
|
|
34
|
+
} & O;
|
|
35
|
+
declare const isNode: (obj: object) => obj is {
|
|
36
|
+
[nodeMetaSymbol]: Meta;
|
|
37
|
+
};
|
|
38
|
+
declare function getMeta(node: Resource): ResourceMeta;
|
|
39
|
+
declare function getMeta(node: DataSource): DataSourceMeta;
|
|
40
|
+
declare function getMeta(node: Node): Meta;
|
|
41
|
+
declare const isResource: (obj: object) => obj is Resource;
|
|
42
|
+
declare const isDataSource: (obj: object) => obj is DataSource;
|
|
24
43
|
type ResourceConfig = Config & {
|
|
25
44
|
/** Import an existing resource instead of creating a new resource. */
|
|
26
45
|
import?: string;
|
|
@@ -39,7 +58,8 @@ type Resource<
|
|
|
39
58
|
I extends State = State,
|
|
40
59
|
O extends State = State
|
|
41
60
|
> = O & {
|
|
42
|
-
readonly
|
|
61
|
+
readonly [nodeMetaSymbol]: ResourceMeta<I, O>;
|
|
62
|
+
readonly urn: URN;
|
|
43
63
|
};
|
|
44
64
|
type ResourceClass<
|
|
45
65
|
I extends State = State,
|
|
@@ -54,7 +74,6 @@ declare class Stack extends Group {
|
|
|
54
74
|
constructor(app: App, name: string);
|
|
55
75
|
dependsOn(...stacks: Stack[]);
|
|
56
76
|
}
|
|
57
|
-
type URN = `urn:${string}`;
|
|
58
77
|
type Tag = "resource" | "data";
|
|
59
78
|
type State = Record<string, unknown>;
|
|
60
79
|
type Config = {
|
|
@@ -95,27 +114,12 @@ type DataSource<
|
|
|
95
114
|
I extends State = State,
|
|
96
115
|
O extends State = State
|
|
97
116
|
> = {
|
|
98
|
-
readonly
|
|
117
|
+
readonly [nodeMetaSymbol]: DataSourceMeta<I, O>;
|
|
99
118
|
} & O;
|
|
100
119
|
type DataSourceFunction<
|
|
101
120
|
I extends State = State,
|
|
102
121
|
O extends State = State
|
|
103
122
|
> = (parent: Group, id: string, input: I, config?: Config) => DataSource<I, O>;
|
|
104
|
-
type Node<
|
|
105
|
-
T extends Tag = Tag,
|
|
106
|
-
I extends State = State,
|
|
107
|
-
O extends State = State,
|
|
108
|
-
C extends Config = Config
|
|
109
|
-
> = {
|
|
110
|
-
$: Meta<T, I, O, C>;
|
|
111
|
-
} & O;
|
|
112
|
-
declare const isNode: (obj: object) => obj is {
|
|
113
|
-
$: {
|
|
114
|
-
tag: string;
|
|
115
|
-
};
|
|
116
|
-
};
|
|
117
|
-
declare const isResource: (obj: object) => obj is Resource;
|
|
118
|
-
declare const isDataSource: (obj: object) => obj is DataSource;
|
|
119
123
|
declare class Group {
|
|
120
124
|
readonly parent: Group | undefined;
|
|
121
125
|
readonly type: string;
|
|
@@ -230,9 +234,22 @@ type WorkSpaceOptions = {
|
|
|
230
234
|
declare class WorkSpace {
|
|
231
235
|
protected props: WorkSpaceOptions;
|
|
232
236
|
constructor(props: WorkSpaceOptions);
|
|
237
|
+
/**
|
|
238
|
+
* Deploy the entire app or use the filter option to deploy specific stacks inside your app.
|
|
239
|
+
*/
|
|
233
240
|
deploy(app: App, options?: ProcedureOptions);
|
|
241
|
+
/**
|
|
242
|
+
* Delete the entire app or use the filter option to delete specific stacks inside your app.
|
|
243
|
+
*/
|
|
234
244
|
delete(app: App, options?: ProcedureOptions);
|
|
245
|
+
/**
|
|
246
|
+
* Hydrate the outputs of the resources & data-sources inside your app.
|
|
247
|
+
*/
|
|
235
248
|
hydrate(app: App);
|
|
249
|
+
/**
|
|
250
|
+
* Refresh the state of the resources & data-sources inside your app.
|
|
251
|
+
*/
|
|
252
|
+
refresh(app: App);
|
|
236
253
|
protected destroyProviders();
|
|
237
254
|
}
|
|
238
255
|
type ResourceOperation = "create" | "update" | "delete" | "replace" | "import" | "resolve" | "get";
|
|
@@ -328,4 +345,4 @@ type CustomResourceProvider = Partial<{
|
|
|
328
345
|
getData?(props: Omit<GetDataProps, "type">): Promise<State>;
|
|
329
346
|
}>;
|
|
330
347
|
declare const createCustomProvider: (providerId: string, resourceProviders: Record<string, CustomResourceProvider>) => Provider;
|
|
331
|
-
export { resolveInputs, output, isResource, isNode, isDataSource, findInputDeps, enableDebug, deferredOutput, createMeta, createDebugger, createCustomResourceClass, createCustomProvider, WorkSpaceOptions, WorkSpace, UpdateProps, URN, Tag, StateBackend, State, Stack, S3StateBackend, ResourceNotFound, ResourceMeta, ResourceError, ResourceConfig, ResourceClass, ResourceAlreadyExists, Resource, Provider, ProcedureOptions, Output, OptionalOutput, OptionalInput, Node, Meta, MemoryStateBackend, MemoryLockBackend, LockBackend, Input, Group, GetProps, GetDataProps, Future, FileStateBackend, FileLockBackend, DynamoLockBackend, DeleteProps, DataSourceMeta, DataSourceFunction, DataSource, CustomResourceProvider, CreateProps, Config, AppError, App };
|
|
348
|
+
export { resolveInputs, output, nodeMetaSymbol, isResource, isNode, isDataSource, getMeta, findInputDeps, enableDebug, deferredOutput, createMeta, createDebugger, createCustomResourceClass, createCustomProvider, WorkSpaceOptions, WorkSpace, UpdateProps, URN, Tag, StateBackend, State, Stack, S3StateBackend, ResourceNotFound, ResourceMeta, ResourceError, ResourceConfig, ResourceClass, ResourceAlreadyExists, Resource, Provider, ProcedureOptions, Output, OptionalOutput, OptionalInput, Node, Meta, MemoryStateBackend, MemoryLockBackend, LockBackend, Input, Group, GetProps, GetDataProps, Future, FileStateBackend, FileLockBackend, DynamoLockBackend, DeleteProps, DataSourceMeta, DataSourceFunction, DataSource, CustomResourceProvider, CreateProps, Config, AppError, App };
|
package/dist/index.js
CHANGED
|
@@ -1,12 +1,17 @@
|
|
|
1
1
|
// src/node.ts
|
|
2
|
+
var nodeMetaSymbol = Symbol("metadata");
|
|
2
3
|
var isNode = (obj) => {
|
|
3
|
-
|
|
4
|
+
const meta = obj[nodeMetaSymbol];
|
|
5
|
+
return meta && typeof meta === "object" && meta !== null && "tag" in meta && typeof meta.tag === "string";
|
|
4
6
|
};
|
|
7
|
+
function getMeta(node) {
|
|
8
|
+
return node[nodeMetaSymbol];
|
|
9
|
+
}
|
|
5
10
|
var isResource = (obj) => {
|
|
6
|
-
return isNode(obj) && obj
|
|
11
|
+
return isNode(obj) && obj[nodeMetaSymbol].tag === "resource";
|
|
7
12
|
};
|
|
8
13
|
var isDataSource = (obj) => {
|
|
9
|
-
return isNode(obj) && obj
|
|
14
|
+
return isNode(obj) && obj[nodeMetaSymbol].tag === "data";
|
|
10
15
|
};
|
|
11
16
|
|
|
12
17
|
// src/group.ts
|
|
@@ -27,9 +32,10 @@ class Group {
|
|
|
27
32
|
}
|
|
28
33
|
addChild(child) {
|
|
29
34
|
if (isNode(child)) {
|
|
30
|
-
const
|
|
35
|
+
const meta = getMeta(child);
|
|
36
|
+
const duplicate = this.children.filter((c) => isResource(c)).map((c) => getMeta(c)).find((c) => c.type === meta.type && c.logicalId === meta.logicalId);
|
|
31
37
|
if (duplicate) {
|
|
32
|
-
throw new Error(`Duplicate node found: ${
|
|
38
|
+
throw new Error(`Duplicate node found: ${meta.type}:${meta.logicalId}`);
|
|
33
39
|
}
|
|
34
40
|
}
|
|
35
41
|
if (child instanceof Group) {
|
|
@@ -376,7 +382,7 @@ var lockApp = async (lockBackend, app, fn) => {
|
|
|
376
382
|
|
|
377
383
|
// src/workspace/concurrency.ts
|
|
378
384
|
import promiseLimit from "p-limit";
|
|
379
|
-
var
|
|
385
|
+
var createConcurrencyQueue = (concurrency) => {
|
|
380
386
|
const queue = promiseLimit(concurrency);
|
|
381
387
|
return (cb) => {
|
|
382
388
|
return queue(cb);
|
|
@@ -625,7 +631,7 @@ var deleteApp = async (app, opt) => {
|
|
|
625
631
|
if (opt.filters && opt.filters.length > 0) {
|
|
626
632
|
stackStates = stackStates.filter((stackState) => opt.filters.includes(stackState.name));
|
|
627
633
|
}
|
|
628
|
-
const queue =
|
|
634
|
+
const queue = createConcurrencyQueue(opt.concurrency ?? 10);
|
|
629
635
|
const graph = new DependencyGraph;
|
|
630
636
|
const allNodes = {};
|
|
631
637
|
for (const stackState of Object.values(appState.stacks)) {
|
|
@@ -678,26 +684,27 @@ var requiresReplacement = (priorState, proposedState, replaceOnChanges) => {
|
|
|
678
684
|
// src/workspace/procedure/create-resource.ts
|
|
679
685
|
var debug2 = createDebugger("Create");
|
|
680
686
|
var createResource = async (resource, appToken, input, opt) => {
|
|
681
|
-
const
|
|
682
|
-
const
|
|
683
|
-
|
|
687
|
+
const meta = getMeta(resource);
|
|
688
|
+
const provider = findProvider(opt.providers, meta.provider);
|
|
689
|
+
const idempotantToken = createIdempotantToken(appToken, meta.urn, "create");
|
|
690
|
+
debug2(meta.type);
|
|
684
691
|
debug2(input);
|
|
685
692
|
let result;
|
|
686
693
|
try {
|
|
687
694
|
result = await provider.createResource({
|
|
688
|
-
type:
|
|
695
|
+
type: meta.type,
|
|
689
696
|
state: input,
|
|
690
697
|
idempotantToken
|
|
691
698
|
});
|
|
692
699
|
} catch (error) {
|
|
693
|
-
throw ResourceError.wrap(
|
|
700
|
+
throw ResourceError.wrap(meta.urn, meta.type, "create", error);
|
|
694
701
|
}
|
|
695
702
|
return {
|
|
696
703
|
tag: "resource",
|
|
697
704
|
version: result.version,
|
|
698
|
-
type:
|
|
699
|
-
provider:
|
|
700
|
-
input:
|
|
705
|
+
type: meta.type,
|
|
706
|
+
provider: meta.provider,
|
|
707
|
+
input: meta.input,
|
|
701
708
|
output: result.state
|
|
702
709
|
};
|
|
703
710
|
};
|
|
@@ -731,27 +738,28 @@ var getDataSource = async (dataSource, input, opt) => {
|
|
|
731
738
|
// src/workspace/procedure/import-resource.ts
|
|
732
739
|
var debug4 = createDebugger("Import");
|
|
733
740
|
var importResource = async (resource, input, opt) => {
|
|
734
|
-
const
|
|
735
|
-
|
|
741
|
+
const meta = getMeta(resource);
|
|
742
|
+
const provider = findProvider(opt.providers, meta.provider);
|
|
743
|
+
debug4(meta.type);
|
|
736
744
|
debug4(input);
|
|
737
745
|
let result;
|
|
738
746
|
try {
|
|
739
747
|
result = await provider.getResource({
|
|
740
|
-
type:
|
|
748
|
+
type: meta.type,
|
|
741
749
|
state: {
|
|
742
750
|
...input,
|
|
743
|
-
id:
|
|
751
|
+
id: meta.config?.import
|
|
744
752
|
}
|
|
745
753
|
});
|
|
746
754
|
} catch (error) {
|
|
747
|
-
throw ResourceError.wrap(
|
|
755
|
+
throw ResourceError.wrap(meta.urn, meta.type, "import", error);
|
|
748
756
|
}
|
|
749
757
|
return {
|
|
750
758
|
tag: "resource",
|
|
751
759
|
version: result.version,
|
|
752
|
-
type:
|
|
753
|
-
provider:
|
|
754
|
-
input:
|
|
760
|
+
type: meta.type,
|
|
761
|
+
provider: meta.provider,
|
|
762
|
+
input: meta.input,
|
|
755
763
|
output: result.state
|
|
756
764
|
};
|
|
757
765
|
};
|
|
@@ -759,13 +767,14 @@ var importResource = async (resource, input, opt) => {
|
|
|
759
767
|
// src/workspace/procedure/replace-resource.ts
|
|
760
768
|
var debug5 = createDebugger("Replace");
|
|
761
769
|
var replaceResource = async (resource, appToken, priorState, proposedState, opt) => {
|
|
762
|
-
const
|
|
763
|
-
const
|
|
764
|
-
const
|
|
765
|
-
const
|
|
766
|
-
|
|
770
|
+
const meta = getMeta(resource);
|
|
771
|
+
const urn = meta.urn;
|
|
772
|
+
const type = meta.type;
|
|
773
|
+
const provider = findProvider(opt.providers, meta.provider);
|
|
774
|
+
const idempotantToken = createIdempotantToken(appToken, meta.urn, "replace");
|
|
775
|
+
debug5(meta.type);
|
|
767
776
|
debug5(proposedState);
|
|
768
|
-
if (
|
|
777
|
+
if (meta.config?.retainOnDelete) {
|
|
769
778
|
debug5("retain", type);
|
|
770
779
|
} else {
|
|
771
780
|
try {
|
|
@@ -801,20 +810,21 @@ var replaceResource = async (resource, appToken, priorState, proposedState, opt)
|
|
|
801
810
|
// src/workspace/procedure/update-resource.ts
|
|
802
811
|
var debug6 = createDebugger("Update");
|
|
803
812
|
var updateResource = async (resource, appToken, priorState, proposedState, opt) => {
|
|
804
|
-
const
|
|
805
|
-
const
|
|
813
|
+
const meta = getMeta(resource);
|
|
814
|
+
const provider = findProvider(opt.providers, meta.provider);
|
|
815
|
+
const idempotantToken = createIdempotantToken(appToken, meta.urn, "update");
|
|
806
816
|
let result;
|
|
807
|
-
debug6(
|
|
817
|
+
debug6(meta.type);
|
|
808
818
|
debug6(proposedState);
|
|
809
819
|
try {
|
|
810
820
|
result = await provider.updateResource({
|
|
811
|
-
type:
|
|
821
|
+
type: meta.type,
|
|
812
822
|
priorState,
|
|
813
823
|
proposedState,
|
|
814
824
|
idempotantToken
|
|
815
825
|
});
|
|
816
826
|
} catch (error) {
|
|
817
|
-
throw ResourceError.wrap(
|
|
827
|
+
throw ResourceError.wrap(meta.urn, meta.type, "update", error);
|
|
818
828
|
}
|
|
819
829
|
return {
|
|
820
830
|
version: result.version,
|
|
@@ -844,7 +854,7 @@ var deployApp = async (app, opt) => {
|
|
|
844
854
|
stacks = app.stacks.filter((stack) => opt.filters.includes(stack.name));
|
|
845
855
|
filteredOutStacks = app.stacks.filter((stack) => !opt.filters.includes(stack.name));
|
|
846
856
|
}
|
|
847
|
-
const queue =
|
|
857
|
+
const queue = createConcurrencyQueue(opt.concurrency ?? 10);
|
|
848
858
|
const graph = new DependencyGraph;
|
|
849
859
|
const allNodes = {};
|
|
850
860
|
for (const stackState of Object.values(appState.stacks)) {
|
|
@@ -856,11 +866,12 @@ var deployApp = async (app, opt) => {
|
|
|
856
866
|
const stackState = appState.stacks[stack.urn];
|
|
857
867
|
if (stackState) {
|
|
858
868
|
for (const node of stack.nodes) {
|
|
859
|
-
const
|
|
869
|
+
const meta = getMeta(node);
|
|
870
|
+
const nodeState = stackState.nodes[meta.urn];
|
|
860
871
|
if (nodeState && nodeState.output) {
|
|
861
|
-
graph.add(
|
|
862
|
-
debug7("hydrate",
|
|
863
|
-
|
|
872
|
+
graph.add(meta.urn, [], async () => {
|
|
873
|
+
debug7("hydrate", meta.urn);
|
|
874
|
+
meta.resolve(nodeState.output);
|
|
864
875
|
});
|
|
865
876
|
}
|
|
866
877
|
}
|
|
@@ -888,7 +899,7 @@ var deployApp = async (app, opt) => {
|
|
|
888
899
|
nodes: {}
|
|
889
900
|
};
|
|
890
901
|
for (const [urn, nodeState] of entries(stackState.nodes)) {
|
|
891
|
-
const resource = stack.nodes.find((r) => r
|
|
902
|
+
const resource = stack.nodes.find((r) => getMeta(r).urn === urn);
|
|
892
903
|
if (!resource) {
|
|
893
904
|
graph.add(urn, dependentsOn(allNodes, urn), async () => {
|
|
894
905
|
if (nodeState.tag === "resource") {
|
|
@@ -899,31 +910,33 @@ var deployApp = async (app, opt) => {
|
|
|
899
910
|
}
|
|
900
911
|
}
|
|
901
912
|
for (const node of stack.nodes) {
|
|
902
|
-
const
|
|
913
|
+
const meta = getMeta(node);
|
|
914
|
+
const dependencies = [...meta.dependencies];
|
|
903
915
|
const partialNewResourceState = {
|
|
904
916
|
dependencies,
|
|
905
917
|
lifecycle: isResource(node) ? {
|
|
906
|
-
retainOnDelete: node
|
|
918
|
+
retainOnDelete: getMeta(node).config?.retainOnDelete
|
|
907
919
|
} : undefined
|
|
908
920
|
};
|
|
909
|
-
graph.add(
|
|
921
|
+
graph.add(meta.urn, dependencies, () => {
|
|
910
922
|
return queue(async () => {
|
|
911
|
-
let nodeState = stackState.nodes[
|
|
923
|
+
let nodeState = stackState.nodes[meta.urn];
|
|
912
924
|
let input;
|
|
913
925
|
try {
|
|
914
|
-
input = await resolveInputs(
|
|
926
|
+
input = await resolveInputs(meta.input);
|
|
915
927
|
} catch (error) {
|
|
916
|
-
throw ResourceError.wrap(
|
|
928
|
+
throw ResourceError.wrap(meta.urn, meta.type, "resolve", error);
|
|
917
929
|
}
|
|
918
930
|
if (isDataSource(node)) {
|
|
931
|
+
const meta2 = getMeta(node);
|
|
919
932
|
if (!nodeState) {
|
|
920
|
-
const dataSourceState = await getDataSource(
|
|
921
|
-
nodeState = stackState.nodes[
|
|
933
|
+
const dataSourceState = await getDataSource(meta2, input, opt);
|
|
934
|
+
nodeState = stackState.nodes[meta2.urn] = {
|
|
922
935
|
...dataSourceState,
|
|
923
936
|
...partialNewResourceState
|
|
924
937
|
};
|
|
925
938
|
} else if (!compareState(nodeState.input, input)) {
|
|
926
|
-
const dataSourceState = await getDataSource(
|
|
939
|
+
const dataSourceState = await getDataSource(meta2, input, opt);
|
|
927
940
|
Object.assign(nodeState, {
|
|
928
941
|
...dataSourceState,
|
|
929
942
|
...partialNewResourceState
|
|
@@ -933,25 +946,26 @@ var deployApp = async (app, opt) => {
|
|
|
933
946
|
}
|
|
934
947
|
}
|
|
935
948
|
if (isResource(node)) {
|
|
949
|
+
const meta2 = getMeta(node);
|
|
936
950
|
if (!nodeState) {
|
|
937
|
-
if (
|
|
951
|
+
if (meta2.config?.import) {
|
|
938
952
|
const importedState = await importResource(node, input, opt);
|
|
939
953
|
const newResourceState = await updateResource(node, appState.idempotentToken, importedState.output, input, opt);
|
|
940
|
-
nodeState = stackState.nodes[
|
|
954
|
+
nodeState = stackState.nodes[meta2.urn] = {
|
|
941
955
|
...importedState,
|
|
942
956
|
...newResourceState,
|
|
943
957
|
...partialNewResourceState
|
|
944
958
|
};
|
|
945
959
|
} else {
|
|
946
960
|
const newResourceState = await createResource(node, appState.idempotentToken, input, opt);
|
|
947
|
-
nodeState = stackState.nodes[
|
|
961
|
+
nodeState = stackState.nodes[meta2.urn] = {
|
|
948
962
|
...newResourceState,
|
|
949
963
|
...partialNewResourceState
|
|
950
964
|
};
|
|
951
965
|
}
|
|
952
966
|
} else if (!compareState(nodeState.input, input)) {
|
|
953
967
|
let newResourceState;
|
|
954
|
-
if (requiresReplacement(nodeState.input, input,
|
|
968
|
+
if (requiresReplacement(nodeState.input, input, meta2.config?.replaceOnChanges ?? [])) {
|
|
955
969
|
newResourceState = await replaceResource(node, appState.idempotentToken, nodeState.output, input, opt);
|
|
956
970
|
} else {
|
|
957
971
|
newResourceState = await updateResource(node, appState.idempotentToken, nodeState.output, input, opt);
|
|
@@ -966,7 +980,7 @@ var deployApp = async (app, opt) => {
|
|
|
966
980
|
}
|
|
967
981
|
}
|
|
968
982
|
if (nodeState?.output) {
|
|
969
|
-
|
|
983
|
+
meta.resolve(nodeState.output);
|
|
970
984
|
}
|
|
971
985
|
});
|
|
972
986
|
});
|
|
@@ -995,9 +1009,10 @@ var hydrate = async (app, opt) => {
|
|
|
995
1009
|
const stackState = appState.stacks[stack.urn];
|
|
996
1010
|
if (stackState) {
|
|
997
1011
|
for (const node of stack.nodes) {
|
|
998
|
-
const
|
|
1012
|
+
const meta = getMeta(node);
|
|
1013
|
+
const nodeState = stackState.nodes[meta.urn];
|
|
999
1014
|
if (nodeState && nodeState.output) {
|
|
1000
|
-
|
|
1015
|
+
meta.resolve(nodeState.output);
|
|
1001
1016
|
}
|
|
1002
1017
|
}
|
|
1003
1018
|
}
|
|
@@ -1005,6 +1020,41 @@ var hydrate = async (app, opt) => {
|
|
|
1005
1020
|
}
|
|
1006
1021
|
};
|
|
1007
1022
|
|
|
1023
|
+
// src/workspace/procedure/refresh.ts
|
|
1024
|
+
var refresh = async (app, opt) => {
|
|
1025
|
+
const appState = await opt.backend.state.get(app.urn);
|
|
1026
|
+
const queue = createConcurrencyQueue(opt.concurrency ?? 10);
|
|
1027
|
+
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
|
|
1045
|
+
});
|
|
1046
|
+
if (result && !compareState(result.state, nodeState.output)) {
|
|
1047
|
+
nodeState.output = result.state;
|
|
1048
|
+
nodeState.input = result.state;
|
|
1049
|
+
}
|
|
1050
|
+
}
|
|
1051
|
+
});
|
|
1052
|
+
}));
|
|
1053
|
+
}));
|
|
1054
|
+
await opt.backend.state.update(app.urn, appState);
|
|
1055
|
+
}
|
|
1056
|
+
};
|
|
1057
|
+
|
|
1008
1058
|
// src/workspace/workspace.ts
|
|
1009
1059
|
class WorkSpace {
|
|
1010
1060
|
props;
|
|
@@ -1032,6 +1082,15 @@ class WorkSpace {
|
|
|
1032
1082
|
hydrate(app) {
|
|
1033
1083
|
return hydrate(app, this.props);
|
|
1034
1084
|
}
|
|
1085
|
+
refresh(app) {
|
|
1086
|
+
return lockApp(this.props.backend.lock, app, async () => {
|
|
1087
|
+
try {
|
|
1088
|
+
await refresh(app, this.props);
|
|
1089
|
+
} finally {
|
|
1090
|
+
await this.destroyProviders();
|
|
1091
|
+
}
|
|
1092
|
+
});
|
|
1093
|
+
}
|
|
1035
1094
|
async destroyProviders() {
|
|
1036
1095
|
await Promise.all(this.props.providers.map((p) => {
|
|
1037
1096
|
return p.destroy?.();
|
|
@@ -1285,13 +1344,19 @@ var createCustomResourceClass = (providerId, resourceType) => {
|
|
|
1285
1344
|
return new Proxy(class {
|
|
1286
1345
|
}, {
|
|
1287
1346
|
construct(_, [parent, id, input, config]) {
|
|
1288
|
-
const
|
|
1289
|
-
const node = new Proxy({
|
|
1347
|
+
const meta = createMeta("resource", `custom:${providerId}`, parent, resourceType, id, input, config);
|
|
1348
|
+
const node = new Proxy({}, {
|
|
1290
1349
|
get(_2, key) {
|
|
1291
|
-
if (key ===
|
|
1292
|
-
return
|
|
1350
|
+
if (key === nodeMetaSymbol) {
|
|
1351
|
+
return meta;
|
|
1352
|
+
}
|
|
1353
|
+
if (key === "urn") {
|
|
1354
|
+
return meta.urn;
|
|
1355
|
+
}
|
|
1356
|
+
if (typeof key === "symbol") {
|
|
1357
|
+
return;
|
|
1293
1358
|
}
|
|
1294
|
-
return
|
|
1359
|
+
return meta.output((data) => data[key]);
|
|
1295
1360
|
}
|
|
1296
1361
|
});
|
|
1297
1362
|
parent.add(node);
|
|
@@ -1366,9 +1431,11 @@ var createCustomProvider = (providerId, resourceProviders) => {
|
|
|
1366
1431
|
export {
|
|
1367
1432
|
resolveInputs,
|
|
1368
1433
|
output,
|
|
1434
|
+
nodeMetaSymbol,
|
|
1369
1435
|
isResource,
|
|
1370
1436
|
isNode,
|
|
1371
1437
|
isDataSource,
|
|
1438
|
+
getMeta,
|
|
1372
1439
|
findInputDeps,
|
|
1373
1440
|
enableDebug,
|
|
1374
1441
|
deferredOutput,
|