@highstate/backend 0.9.35 → 0.9.37

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.
@@ -320,7 +320,54 @@ describe("OperationPlan - Update Operations", () => {
320
320
  },
321
321
  {
322
322
  "id": "component.v1:GhostChild",
323
- "message": "included in operation",
323
+ "message": "ghost cleanup",
324
+ "parentId": "composite.v1:Parent",
325
+ },
326
+ ],
327
+ "type": "destroy",
328
+ },
329
+ ]
330
+ `)
331
+ },
332
+ )
333
+
334
+ operationPlanTest(
335
+ "5a. should skip ghost children in update phase when forcing child updates",
336
+ async ({ testBuilder, expect }) => {
337
+ // arrange
338
+ const { context, operation } = await testBuilder()
339
+ .composite("Parent")
340
+ .unit("GhostChild")
341
+ .children("Parent", "GhostChild")
342
+ .states({
343
+ Parent: "upToDate",
344
+ GhostChild: "ghost",
345
+ })
346
+ .options({ forceUpdateChildren: true })
347
+ .request("update", "Parent")
348
+ .build()
349
+
350
+ // act
351
+ const plan = createOperationPlan(
352
+ context,
353
+ operation.type,
354
+ operation.requestedInstanceIds,
355
+ operation.options,
356
+ )
357
+
358
+ // assert
359
+ expect(plan).toMatchInlineSnapshot(`
360
+ [
361
+ {
362
+ "instances": [
363
+ {
364
+ "id": "composite.v1:Parent",
365
+ "message": "explicitly requested",
366
+ "parentId": undefined,
367
+ },
368
+ {
369
+ "id": "component.v1:GhostChild",
370
+ "message": "ghost cleanup",
324
371
  "parentId": "composite.v1:Parent",
325
372
  },
326
373
  ],
@@ -946,7 +993,7 @@ describe("OperationPlan - Update Operations", () => {
946
993
  },
947
994
  {
948
995
  "id": "component.v1:GhostChild",
949
- "message": "included in operation",
996
+ "message": "ghost cleanup",
950
997
  "parentId": "composite.v1:Parent",
951
998
  },
952
999
  ],
@@ -794,6 +794,14 @@ export class RuntimeOperation {
794
794
  }
795
795
  : undefined,
796
796
  })
797
+
798
+ if (
799
+ update.operationType === "destroy" &&
800
+ this.workset.isLastPhaseForInstance(instance.id) &&
801
+ this.context.isGhostInstance(instance.id)
802
+ ) {
803
+ this.instanceStateService.publishGhostInstanceDeletion(this.project.id, [instance.id])
804
+ }
797
805
  }
798
806
 
799
807
  private getInstancePromise(
@@ -108,7 +108,7 @@ export class CodebaseProjectModelBackend implements ProjectModelBackend {
108
108
  assertCodebaseSpec(spec)
109
109
 
110
110
  try {
111
- return await this.withInstance(project.name, instanceId, instance => {
111
+ return await this.withInstance(project.id, project.name, instanceId, instance => {
112
112
  applyInstancePatch(instance, patch)
113
113
  return instance
114
114
  })
@@ -312,6 +312,7 @@ export class CodebaseProjectModelBackend implements ProjectModelBackend {
312
312
  }
313
313
 
314
314
  private async withInstance<T>(
315
+ projectId: string,
315
316
  projectName: string,
316
317
  instanceId: string,
317
318
  callback: (instance: InstanceModel) => T,
@@ -319,7 +320,7 @@ export class CodebaseProjectModelBackend implements ProjectModelBackend {
319
320
  return await this.withProject(projectName, projectData => {
320
321
  const instance = projectData.instances[instanceId]
321
322
  if (!instance) {
322
- throw new Error(`Instance ${instanceId} not found`)
323
+ throw new ProjectModelInstanceNotFoundError(projectId, instanceId)
323
324
  }
324
325
 
325
326
  return callback(instance)
@@ -2,3 +2,4 @@ export type { ProjectModelBackend } from "./abstractions"
2
2
  export * from "../business/evaluation"
3
3
  export * from "./errors"
4
4
  export { createProjectModelBackends } from "./factory"
5
+ export { applyInstancePatch } from "./utils"