@terraforge/core 0.0.31 → 0.0.33

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.mts CHANGED
@@ -194,6 +194,7 @@ type NodeState = {
194
194
  provider: string;
195
195
  input: State;
196
196
  output: State;
197
+ drifted?: boolean;
197
198
  dependencies: URN[];
198
199
  lifecycle?: {
199
200
  retainOnDelete?: boolean;
@@ -258,8 +259,12 @@ type RefreshResourceProps<T = State> = {
258
259
  priorOutputState: T;
259
260
  };
260
261
  type RefreshResourceResult<T = State> = {
261
- kind: 'unchanged' | 'updated';
262
+ kind: 'unchanged';
262
263
  state: T;
264
+ } | {
265
+ kind: 'updated';
266
+ state: T;
267
+ inputState: T;
263
268
  } | {
264
269
  kind: 'deleted';
265
270
  };
@@ -368,11 +373,17 @@ declare class WorkSpace {
368
373
  * Refresh the state of the resources & data-sources inside your app.
369
374
  */
370
375
  refresh(app: App, options?: ProcedureOptions): Promise<{
371
- operations: {
376
+ operations: ({
377
+ urn: URN;
378
+ operation: "delete";
379
+ commit(): void;
380
+ } | {
372
381
  urn: URN;
373
- operation: "delete" | "update";
382
+ operation: "update";
383
+ before: State;
384
+ after: State;
374
385
  commit(): void;
375
- }[];
386
+ })[];
376
387
  commit: () => Promise<void>;
377
388
  } | undefined>;
378
389
  /**
package/dist/index.mjs CHANGED
@@ -953,19 +953,20 @@ const deployApp = async (app, opt) => {
953
953
  const dataSourceState = await getDataSource(meta$1, input, opt);
954
954
  nodeState = stackState.nodes[meta$1.urn] = {
955
955
  ...dataSourceState,
956
+ drifted: void 0,
956
957
  ...partialNewResourceState
957
958
  };
958
- } else if (!compareState(nodeState.input, input)) {
959
+ } else if (!compareState(nodeState.input, input) || nodeState.drifted) {
959
960
  const dataSourceState = await getDataSource(meta$1, input, opt);
960
961
  Object.assign(nodeState, {
961
962
  ...dataSourceState,
963
+ drifted: void 0,
962
964
  ...partialNewResourceState
963
965
  });
964
966
  } else Object.assign(nodeState, partialNewResourceState);
965
967
  }
966
968
  if (isResource(node)) {
967
969
  const meta$1 = getMeta(node);
968
- const provider = findProvider(opt.providers, meta$1.provider);
969
970
  if (!nodeState) if (meta$1.config?.import) {
970
971
  const importedState = await importResource(node, input, opt);
971
972
  const newResourceState = await updateResource(node, appState.idempotentToken, importedState.input, importedState.output, input, opt);
@@ -983,17 +984,12 @@ const deployApp = async (app, opt) => {
983
984
  }
984
985
  else {
985
986
  const inputChanged = !compareState(nodeState.input, input);
986
- const plannedChange = provider.planResourceChange ? await provider.planResourceChange({
987
- type: meta$1.type,
988
- priorState: nodeState.output,
989
- proposedState: input
990
- }) : void 0;
991
- const hasDrift = !inputChanged && !!provider.refreshResource && !!plannedChange && !compareState(plannedChange.state, nodeState.output);
987
+ const hasDrift = !!nodeState.drifted;
992
988
  if (!inputChanged && !hasDrift) Object.assign(nodeState, partialNewResourceState);
993
989
  else {
994
990
  let newResourceState;
995
991
  const ignoreReplace = forcedUpdateDependents.has(meta$1.urn);
996
- if (!ignoreReplace && (requiresReplacement(nodeState.input, input, meta$1.config?.replaceOnChanges ?? []) || !inputChanged && (plannedChange?.requiresReplacement ?? false))) if (meta$1.config?.createBeforeReplace) {
992
+ if (!ignoreReplace && requiresReplacement(nodeState.input, input, meta$1.config?.replaceOnChanges ?? [])) if (meta$1.config?.createBeforeReplace) {
997
993
  meta$1.resolve(input);
998
994
  try {
999
995
  for (const [dependentUrn, dependentNode] of nodeByUrn.entries()) {
@@ -1074,6 +1070,7 @@ const deployApp = async (app, opt) => {
1074
1070
  }
1075
1071
  Object.assign(nodeState, {
1076
1072
  input,
1073
+ drifted: void 0,
1077
1074
  ...newResourceState,
1078
1075
  ...partialNewResourceState
1079
1076
  });
@@ -1122,21 +1119,29 @@ const hydrate = async (app, opt) => {
1122
1119
 
1123
1120
  //#endregion
1124
1121
  //#region src/workspace/procedure/refresh.ts
1125
- const createDeleteOperation = (urn, stackState) => {
1122
+ const copy = (value) => {
1123
+ return JSON.parse(JSON.stringify(value));
1124
+ };
1125
+ const createDeleteOperation = (urn, stackState, onCommit) => {
1126
1126
  return {
1127
1127
  urn,
1128
1128
  operation: "delete",
1129
1129
  commit() {
1130
1130
  delete stackState.nodes[urn];
1131
+ onCommit();
1131
1132
  }
1132
1133
  };
1133
1134
  };
1134
- const createUpdateOperation = (urn, state, nodeState) => {
1135
+ const createUpdateOperation = (urn, state, before, after, nodeState, onCommit) => {
1135
1136
  return {
1136
1137
  urn,
1137
1138
  operation: "update",
1139
+ before: copy(before),
1140
+ after: copy(after),
1138
1141
  commit() {
1139
1142
  nodeState.output = state;
1143
+ nodeState.drifted = true;
1144
+ onCommit();
1140
1145
  }
1141
1146
  };
1142
1147
  };
@@ -1147,6 +1152,7 @@ const refresh = async (app, opt) => {
1147
1152
  if (opt.filters && opt.filters.length > 0) filteredStacks = Object.values(appState?.stacks ?? {}).filter((stackState) => {
1148
1153
  return opt.filters.includes(stackState.name);
1149
1154
  });
1155
+ let committed = 0;
1150
1156
  if (appState && filteredStacks.length > 0) {
1151
1157
  const filteredOperations = (await Promise.all(filteredStacks.map((stackState) => {
1152
1158
  return Promise.all(Object.entries(stackState.nodes).map(([_urn, nodeState]) => {
@@ -1158,9 +1164,13 @@ const refresh = async (app, opt) => {
1158
1164
  type: nodeState.type,
1159
1165
  state: nodeState.output
1160
1166
  });
1161
- if (!result) return createDeleteOperation(urn, stackState);
1167
+ if (!result) return createDeleteOperation(urn, stackState, () => {
1168
+ committed++;
1169
+ });
1162
1170
  if (compareState(result.state, nodeState.output)) return;
1163
- return createUpdateOperation(urn, result.state, nodeState);
1171
+ return createUpdateOperation(urn, result.state, nodeState.input, result.state, nodeState, () => {
1172
+ committed++;
1173
+ });
1164
1174
  }
1165
1175
  if (!provider.refreshResource) return;
1166
1176
  const refreshed = await provider.refreshResource({
@@ -1169,8 +1179,12 @@ const refresh = async (app, opt) => {
1169
1179
  priorOutputState: nodeState.output
1170
1180
  });
1171
1181
  if (!refreshed || refreshed.kind === "unchanged") return;
1172
- if (refreshed.kind === "deleted") return createDeleteOperation(urn, stackState);
1173
- return createUpdateOperation(urn, refreshed.state, nodeState);
1182
+ if (refreshed.kind === "deleted") return createDeleteOperation(urn, stackState, () => {
1183
+ committed++;
1184
+ });
1185
+ return createUpdateOperation(urn, refreshed.state, nodeState.input, refreshed.inputState, nodeState, () => {
1186
+ committed++;
1187
+ });
1174
1188
  });
1175
1189
  }));
1176
1190
  }))).flat().filter((op) => !!op);
@@ -1178,7 +1192,7 @@ const refresh = async (app, opt) => {
1178
1192
  return {
1179
1193
  operations: filteredOperations,
1180
1194
  async commit() {
1181
- await opt.backend.state.update(app.urn, appState);
1195
+ if (committed > 0) await opt.backend.state.update(app.urn, appState);
1182
1196
  }
1183
1197
  };
1184
1198
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@terraforge/core",
3
- "version": "0.0.31",
3
+ "version": "0.0.33",
4
4
  "type": "module",
5
5
  "repository": {
6
6
  "type": "git",