@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 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 $: ResourceMeta<I, O>;
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 $: DataSourceMeta<I, O>;
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
- return "$" in obj && typeof obj.$ === "object" && obj.$ !== null && "tag" in obj.$ && typeof obj.$.tag === "string";
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.$.tag === "resource";
11
+ return isNode(obj) && obj[nodeMetaSymbol].tag === "resource";
7
12
  };
8
13
  var isDataSource = (obj) => {
9
- return isNode(obj) && obj.$.tag === "data";
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 duplicate = this.children.filter((c) => isResource(c)).find((c) => c.$.type === child.$.type && c.$.logicalId === child.$.logicalId);
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: ${child.$.type}:${child.$.logicalId}`);
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 concurrencyQueue = (concurrency) => {
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 = concurrencyQueue(opt.concurrency ?? 10);
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 provider = findProvider(opt.providers, resource.$.provider);
682
- const idempotantToken = createIdempotantToken(appToken, resource.$.urn, "create");
683
- debug2(resource.$.type);
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: resource.$.type,
695
+ type: meta.type,
689
696
  state: input,
690
697
  idempotantToken
691
698
  });
692
699
  } catch (error) {
693
- throw ResourceError.wrap(resource.$.urn, resource.$.type, "create", error);
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: resource.$.type,
699
- provider: resource.$.provider,
700
- input: resource.$.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 provider = findProvider(opt.providers, resource.$.provider);
735
- debug4(resource.$.type);
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: resource.$.type,
748
+ type: meta.type,
741
749
  state: {
742
750
  ...input,
743
- id: resource.$.config?.import
751
+ id: meta.config?.import
744
752
  }
745
753
  });
746
754
  } catch (error) {
747
- throw ResourceError.wrap(resource.$.urn, resource.$.type, "import", error);
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: resource.$.type,
753
- provider: resource.$.provider,
754
- input: resource.$.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 urn = resource.$.urn;
763
- const type = resource.$.type;
764
- const provider = findProvider(opt.providers, resource.$.provider);
765
- const idempotantToken = createIdempotantToken(appToken, resource.$.urn, "replace");
766
- debug5(resource.$.type);
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 (resource.$.config?.retainOnDelete) {
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 provider = findProvider(opt.providers, resource.$.provider);
805
- const idempotantToken = createIdempotantToken(appToken, resource.$.urn, "update");
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(resource.$.type);
817
+ debug6(meta.type);
808
818
  debug6(proposedState);
809
819
  try {
810
820
  result = await provider.updateResource({
811
- type: resource.$.type,
821
+ type: meta.type,
812
822
  priorState,
813
823
  proposedState,
814
824
  idempotantToken
815
825
  });
816
826
  } catch (error) {
817
- throw ResourceError.wrap(resource.$.urn, resource.$.type, "update", error);
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 = concurrencyQueue(opt.concurrency ?? 10);
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 nodeState = stackState.nodes[node.$.urn];
869
+ const meta = getMeta(node);
870
+ const nodeState = stackState.nodes[meta.urn];
860
871
  if (nodeState && nodeState.output) {
861
- graph.add(node.$.urn, [], async () => {
862
- debug7("hydrate", node.$.urn);
863
- node.$.resolve(nodeState.output);
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.$.urn === urn);
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 dependencies = [...node.$.dependencies];
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.$.config?.retainOnDelete
918
+ retainOnDelete: getMeta(node).config?.retainOnDelete
907
919
  } : undefined
908
920
  };
909
- graph.add(node.$.urn, dependencies, () => {
921
+ graph.add(meta.urn, dependencies, () => {
910
922
  return queue(async () => {
911
- let nodeState = stackState.nodes[node.$.urn];
923
+ let nodeState = stackState.nodes[meta.urn];
912
924
  let input;
913
925
  try {
914
- input = await resolveInputs(node.$.input);
926
+ input = await resolveInputs(meta.input);
915
927
  } catch (error) {
916
- throw ResourceError.wrap(node.$.urn, node.$.type, "resolve", error);
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(node.$, input, opt);
921
- nodeState = stackState.nodes[node.$.urn] = {
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(node.$, input, opt);
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 (node.$.config?.import) {
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[node.$.urn] = {
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[node.$.urn] = {
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, node.$.config?.replaceOnChanges ?? [])) {
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
- node.$.resolve(nodeState.output);
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 nodeState = stackState.nodes[node.$.urn];
1012
+ const meta = getMeta(node);
1013
+ const nodeState = stackState.nodes[meta.urn];
999
1014
  if (nodeState && nodeState.output) {
1000
- node.$.resolve(nodeState.output);
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 $ = createMeta("resource", `custom:${providerId}`, parent, resourceType, id, input, config);
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 $.output((data) => data[key]);
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,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@terraforge/core",
3
- "version": "0.0.2",
3
+ "version": "0.0.4",
4
4
  "type": "module",
5
5
  "module": "./dist/index.js",
6
6
  "types": "./dist/index.d.ts",