@frockbot/plugin-flock 0.3.14 → 0.3.16

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@frockbot/plugin-flock",
3
- "version": "0.3.14",
3
+ "version": "0.3.16",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "exports": {
@@ -27,16 +27,16 @@
27
27
  "typecheck": "vue-tsc --noEmit -p tsconfig.json"
28
28
  },
29
29
  "dependencies": {
30
- "@frockbot/client-core": "0.3.14",
31
- "@frockbot/client-ui": "0.3.14",
32
- "@frockbot/configuration-core": "0.3.14",
33
- "@frockbot/kernel-contracts": "0.3.14",
34
- "@frockbot/plugin-shell": "0.3.14",
30
+ "@frockbot/client-core": "0.3.16",
31
+ "@frockbot/client-ui": "0.3.16",
32
+ "@frockbot/configuration-core": "0.3.16",
33
+ "@frockbot/kernel-contracts": "0.3.16",
34
+ "@frockbot/plugin-shell": "0.3.16",
35
35
  "cordis": "4.0.0-rc.8",
36
36
  "vue": "3.5.41"
37
37
  },
38
38
  "devDependencies": {
39
- "@frockbot/plugin-testkit": "0.3.14",
39
+ "@frockbot/plugin-testkit": "0.3.16",
40
40
  "@types/bun": "1.4.0",
41
41
  "@vitejs/plugin-vue": "6.0.8",
42
42
  "css-tree": "2.3.1",
package/src/bot.test.ts CHANGED
@@ -49,7 +49,7 @@ describe("Flock Bot contribution", () => {
49
49
  return Promise.resolve();
50
50
  },
51
51
  archiveEligible: () => Promise.resolve(true),
52
- tearDown: () => Promise.resolve(),
52
+ tearDown: () => Promise.resolve("complete"),
53
53
  });
54
54
  expect(await create().read(registration, "user-1")).toMatchObject({
55
55
  botId: "alpha",
@@ -96,7 +96,7 @@ describe("Flock Bot contribution", () => {
96
96
  storage,
97
97
  materializeSettings: () => Promise.resolve(),
98
98
  archiveEligible: () => Promise.resolve(eligible),
99
- tearDown: () => Promise.resolve(),
99
+ tearDown: () => Promise.resolve("complete"),
100
100
  });
101
101
  const contribution = create();
102
102
  await contribution.read(registration, "user-1");
@@ -171,7 +171,7 @@ describe("Flock Bot contribution", () => {
171
171
  torn.push(identity);
172
172
  alarms = 0;
173
173
  storage.values.clear();
174
- return Promise.resolve();
174
+ return Promise.resolve("complete" as const);
175
175
  },
176
176
  });
177
177
  const contribution = create();
@@ -237,13 +237,47 @@ describe("Flock Bot contribution", () => {
237
237
  );
238
238
  });
239
239
 
240
+ test("keeps deletion pending until the host has purged derived state", async () => {
241
+ const storage = new MemoryStorage();
242
+ const outcomes: Array<"pending" | "complete"> = ["pending", "complete"];
243
+ const contribution = createFlockBotBackendContribution({
244
+ storage,
245
+ materializeSettings: () => Promise.resolve(),
246
+ archiveEligible: () => Promise.resolve(true),
247
+ tearDown: () => Promise.resolve(outcomes.shift() ?? "complete"),
248
+ });
249
+ await contribution.read(registration, "user-1");
250
+ const command = {
251
+ schemaVersion: 1 as const,
252
+ type: "bot/delete" as const,
253
+ commandId: "delete-paged",
254
+ botId: "alpha",
255
+ };
256
+
257
+ expect(
258
+ await contribution.executeLifecycle(registration, "user-1", command),
259
+ ).toMatchObject({
260
+ status: "pending",
261
+ lifecycle: { status: "active" },
262
+ });
263
+ expect(
264
+ await contribution.readLifecycle(registration, "user-1"),
265
+ ).toMatchObject({ status: "active" });
266
+ expect(
267
+ await contribution.executeLifecycle(registration, "user-1", command),
268
+ ).toMatchObject({
269
+ status: "applied",
270
+ lifecycle: { status: "deleted" },
271
+ });
272
+ });
273
+
240
274
  test("rejects malformed durable sheep identity and receipt records", async () => {
241
275
  const storage = new MemoryStorage();
242
276
  const contribution = createFlockBotBackendContribution({
243
277
  storage,
244
278
  materializeSettings: () => Promise.resolve(),
245
279
  archiveEligible: () => Promise.resolve(true),
246
- tearDown: () => Promise.resolve(),
280
+ tearDown: () => Promise.resolve("complete"),
247
281
  });
248
282
  await storage.put("flock:sheep:v1", {
249
283
  schemaVersion: 1,
package/src/bot.ts CHANGED
@@ -52,7 +52,10 @@ export interface FlockBotBackendHost {
52
52
  * named here at all. It must be idempotent: the delete saga replays, and a
53
53
  * Bot torn down twice is torn down once.
54
54
  */
55
- tearDown(identity: { userId: string; botId: string }): Promise<void>;
55
+ tearDown(identity: {
56
+ userId: string;
57
+ botId: string;
58
+ }): Promise<"complete" | "pending">;
56
59
  }
57
60
 
58
61
  export class BotArchivedError extends Error {
@@ -314,7 +317,26 @@ export class FlockBotBackendContribution {
314
317
  : decodeBotLifecycleViewV1(currentValue);
315
318
  if (current && current.botId !== registration.botId)
316
319
  throw new Error("Bot lifecycle identity does not match");
317
- await this.host.tearDown({ userId, botId: registration.botId });
320
+ const teardown = await this.host.tearDown({
321
+ userId,
322
+ botId: registration.botId,
323
+ });
324
+ if (teardown === "pending") {
325
+ return decodeBotLifecycleReceiptV1({
326
+ schemaVersion: 1,
327
+ commandId: command.commandId,
328
+ botId: command.botId,
329
+ status: "pending",
330
+ lifecycle:
331
+ current ??
332
+ ({
333
+ schemaVersion: 1,
334
+ botId: command.botId,
335
+ status: "active",
336
+ revision: 0,
337
+ } satisfies BotLifecycleViewV1),
338
+ });
339
+ }
318
340
  const lifecycle = {
319
341
  schemaVersion: 1,
320
342
  botId: command.botId,