@critical-path/svelte 0.5.3 → 0.6.0
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/CHANGELOG.md +18 -0
- package/dist/activity-state.svelte.d.ts.map +1 -1
- package/dist/attachment-state.svelte.d.ts.map +1 -1
- package/dist/comment-state.svelte.d.ts.map +1 -1
- package/dist/index.js +50 -12
- package/dist/task-state.svelte.d.ts +1 -0
- package/dist/task-state.svelte.d.ts.map +1 -1
- package/package.json +3 -3
- package/src/activity-state.svelte.ts +6 -2
- package/src/attachment-state.svelte.ts +3 -1
- package/src/comment-state.svelte.ts +3 -1
- package/src/index.test.ts +37 -1
- package/src/task-state.svelte.ts +41 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,23 @@
|
|
|
1
1
|
# @critical-path/svelte
|
|
2
2
|
|
|
3
|
+
## 0.6.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- e983557: Add first-class optional todo list (checklist) support to Task model and TaskEntity with helper methods (addTodo, toggleTodo, removeTodo) and updateTask helper in @critical-path/svelte.
|
|
8
|
+
|
|
9
|
+
### Patch Changes
|
|
10
|
+
|
|
11
|
+
- Updated dependencies [e983557]
|
|
12
|
+
- @critical-path/core@0.9.0
|
|
13
|
+
- @critical-path/client@0.4.4
|
|
14
|
+
|
|
15
|
+
## 0.5.4
|
|
16
|
+
|
|
17
|
+
### Patch Changes
|
|
18
|
+
|
|
19
|
+
- 9aa53f7: Optimistically remove comments and attachments upon delete with automatic rollback on network failure
|
|
20
|
+
|
|
3
21
|
## 0.5.3
|
|
4
22
|
|
|
5
23
|
### Patch Changes
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"activity-state.svelte.d.ts","sourceRoot":"","sources":["../src/activity-state.svelte.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AAChE,OAAO,KAAK,EAAE,OAAO,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAE/D,MAAM,WAAW,8BAA+B,SAAQ,OAAO;IAC7D,WAAW,EAAE,UAAU,EAAE,CAAC;IAC1B,OAAO,EAAE,8BAA8B,EAAE,CAAC;CAC3C;AAED,qBAAa,iBAAiB;IA6ChB,OAAO,CAAC,MAAM;IAA6B,MAAM,CAAC,EAAE,MAAM;IA5CtE,QAAQ,YAAyB;IACjC,WAAW,eAA4B;IACvC,OAAO,UAA0B;IACjC,KAAK,eAA8B;IAEnC,OAAO,mCAiCJ;IAEH,qBAAqB,eAElB;gBAEiB,MAAM,EAAE,kBAAkB,EAAS,MAAM,CAAC,EAAE,MAAM,YAAA;IAEhE,KAAK,CAAC,MAAM,CAAC,EAAE,MAAM;IAwBrB,UAAU,CACd,KAAK,EAAE,IAAI,CAAC,OAAO,EAAE,IAAI,GAAG,QAAQ,GAAG,WAAW,GAAG,WAAW,CAAC,EACjE,gBAAgB,CAAC,EAAE,KAAK,CAAC,IAAI,CAAC,UAAU,EAAE,IAAI,GAAG,QAAQ,GAAG,WAAW,GAAG,WAAW,GAAG,WAAW,CAAC,CAAC;;;;IAiCjG,aAAa,CAAC,KAAK,EAAE,IAAI,CAAC,UAAU,EAAE,IAAI,GAAG,QAAQ,GAAG,WAAW,GAAG,WAAW,CAAC;IAelF,aAAa,CAAC,EAAE,EAAE,MAAM;
|
|
1
|
+
{"version":3,"file":"activity-state.svelte.d.ts","sourceRoot":"","sources":["../src/activity-state.svelte.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AAChE,OAAO,KAAK,EAAE,OAAO,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAE/D,MAAM,WAAW,8BAA+B,SAAQ,OAAO;IAC7D,WAAW,EAAE,UAAU,EAAE,CAAC;IAC1B,OAAO,EAAE,8BAA8B,EAAE,CAAC;CAC3C;AAED,qBAAa,iBAAiB;IA6ChB,OAAO,CAAC,MAAM;IAA6B,MAAM,CAAC,EAAE,MAAM;IA5CtE,QAAQ,YAAyB;IACjC,WAAW,eAA4B;IACvC,OAAO,UAA0B;IACjC,KAAK,eAA8B;IAEnC,OAAO,mCAiCJ;IAEH,qBAAqB,eAElB;gBAEiB,MAAM,EAAE,kBAAkB,EAAS,MAAM,CAAC,EAAE,MAAM,YAAA;IAEhE,KAAK,CAAC,MAAM,CAAC,EAAE,MAAM;IAwBrB,UAAU,CACd,KAAK,EAAE,IAAI,CAAC,OAAO,EAAE,IAAI,GAAG,QAAQ,GAAG,WAAW,GAAG,WAAW,CAAC,EACjE,gBAAgB,CAAC,EAAE,KAAK,CAAC,IAAI,CAAC,UAAU,EAAE,IAAI,GAAG,QAAQ,GAAG,WAAW,GAAG,WAAW,GAAG,WAAW,CAAC,CAAC;;;;IAiCjG,aAAa,CAAC,KAAK,EAAE,IAAI,CAAC,UAAU,EAAE,IAAI,GAAG,QAAQ,GAAG,WAAW,GAAG,WAAW,CAAC;IAelF,aAAa,CAAC,EAAE,EAAE,MAAM;IAaxB,gBAAgB,CAAC,EAAE,EAAE,MAAM;CAYlC;AAED,wBAAgB,uBAAuB,CAAC,MAAM,EAAE,kBAAkB,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,iBAAiB,CAEtG"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"attachment-state.svelte.d.ts","sourceRoot":"","sources":["../src/attachment-state.svelte.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AAChE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAEtD,MAAM,WAAW,gBAAgB;IAC/B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,qBAAa,eAAe;IAKd,OAAO,CAAC,MAAM;IAA6B,MAAM,CAAC,EAAE,gBAAgB;IAJhF,IAAI,eAA4B;IAChC,OAAO,UAA0B;IACjC,KAAK,eAA8B;gBAEf,MAAM,EAAE,kBAAkB,EAAS,MAAM,CAAC,EAAE,gBAAgB,YAAA;IAE1E,KAAK,CAAC,MAAM,CAAC,EAAE,gBAAgB;IAe/B,gBAAgB,CAAC,KAAK,EAAE,IAAI,CAAC,UAAU,EAAE,IAAI,GAAG,WAAW,GAAG,WAAW,CAAC;IAY1E,gBAAgB,CAAC,EAAE,EAAE,MAAM;
|
|
1
|
+
{"version":3,"file":"attachment-state.svelte.d.ts","sourceRoot":"","sources":["../src/attachment-state.svelte.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AAChE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAEtD,MAAM,WAAW,gBAAgB;IAC/B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,qBAAa,eAAe;IAKd,OAAO,CAAC,MAAM;IAA6B,MAAM,CAAC,EAAE,gBAAgB;IAJhF,IAAI,eAA4B;IAChC,OAAO,UAA0B;IACjC,KAAK,eAA8B;gBAEf,MAAM,EAAE,kBAAkB,EAAS,MAAM,CAAC,EAAE,gBAAgB,YAAA;IAE1E,KAAK,CAAC,MAAM,CAAC,EAAE,gBAAgB;IAe/B,gBAAgB,CAAC,KAAK,EAAE,IAAI,CAAC,UAAU,EAAE,IAAI,GAAG,WAAW,GAAG,WAAW,CAAC;IAY1E,gBAAgB,CAAC,EAAE,EAAE,MAAM;CAYlC;AAED,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,kBAAkB,EAAE,aAAa,CAAC,EAAE,gBAAgB,GAAG,eAAe,CAEnH"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"comment-state.svelte.d.ts","sourceRoot":"","sources":["../src/comment-state.svelte.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AAChE,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAC;AAEnD,MAAM,WAAW,eAAgB,SAAQ,OAAO;IAC9C,OAAO,EAAE,eAAe,EAAE,CAAC;CAC5B;AAED,qBAAa,YAAY;IAyBX,OAAO,CAAC,MAAM;IAA6B,MAAM,CAAC,EAAE,MAAM;IAxBtE,IAAI,YAAyB;IAC7B,OAAO,UAA0B;IACjC,KAAK,eAA8B;IAEnC,OAAO,oBAkBJ;gBAEiB,MAAM,EAAE,kBAAkB,EAAS,MAAM,CAAC,EAAE,MAAM,YAAA;IAEhE,KAAK,CAAC,MAAM,CAAC,EAAE,MAAM;IAkBrB,UAAU,CAAC,KAAK,EAAE,IAAI,CAAC,OAAO,EAAE,IAAI,GAAG,QAAQ,GAAG,WAAW,GAAG,WAAW,CAAC;IAe5E,aAAa,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,CAAC,OAAO,CAAC;IAYnD,aAAa,CAAC,EAAE,EAAE,MAAM;
|
|
1
|
+
{"version":3,"file":"comment-state.svelte.d.ts","sourceRoot":"","sources":["../src/comment-state.svelte.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AAChE,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAC;AAEnD,MAAM,WAAW,eAAgB,SAAQ,OAAO;IAC9C,OAAO,EAAE,eAAe,EAAE,CAAC;CAC5B;AAED,qBAAa,YAAY;IAyBX,OAAO,CAAC,MAAM;IAA6B,MAAM,CAAC,EAAE,MAAM;IAxBtE,IAAI,YAAyB;IAC7B,OAAO,UAA0B;IACjC,KAAK,eAA8B;IAEnC,OAAO,oBAkBJ;gBAEiB,MAAM,EAAE,kBAAkB,EAAS,MAAM,CAAC,EAAE,MAAM,YAAA;IAEhE,KAAK,CAAC,MAAM,CAAC,EAAE,MAAM;IAkBrB,UAAU,CAAC,KAAK,EAAE,IAAI,CAAC,OAAO,EAAE,IAAI,GAAG,QAAQ,GAAG,WAAW,GAAG,WAAW,CAAC;IAe5E,aAAa,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,CAAC,OAAO,CAAC;IAYnD,aAAa,CAAC,EAAE,EAAE,MAAM;CAY/B;AAED,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,kBAAkB,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,YAAY,CAE5F"}
|
package/dist/index.js
CHANGED
|
@@ -114,6 +114,32 @@ var i = class {
|
|
|
114
114
|
throw this.error = n, n;
|
|
115
115
|
}
|
|
116
116
|
}
|
|
117
|
+
async updateTask(e, t) {
|
|
118
|
+
let n = this.data.findIndex((t) => t.id === e);
|
|
119
|
+
if (n === -1) return this.client.updateTask(e, t);
|
|
120
|
+
let r = this.data[n], i = {
|
|
121
|
+
...r,
|
|
122
|
+
...t,
|
|
123
|
+
updatedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
124
|
+
}, a = [...this.data];
|
|
125
|
+
a[n] = i, this.data = a;
|
|
126
|
+
try {
|
|
127
|
+
let n = await this.client.updateTask(e, t), r = this.data.findIndex((t) => t.id === e);
|
|
128
|
+
if (r !== -1) {
|
|
129
|
+
let e = [...this.data];
|
|
130
|
+
e[r] = n, this.data = e;
|
|
131
|
+
}
|
|
132
|
+
return n;
|
|
133
|
+
} catch (t) {
|
|
134
|
+
let n = this.data.findIndex((t) => t.id === e);
|
|
135
|
+
if (n !== -1) {
|
|
136
|
+
let e = [...this.data];
|
|
137
|
+
e[n] = r, this.data = e;
|
|
138
|
+
}
|
|
139
|
+
let i = t instanceof Error ? t : Error(String(t));
|
|
140
|
+
throw this.error = i, i;
|
|
141
|
+
}
|
|
142
|
+
}
|
|
117
143
|
async updateTaskStatus(e, t) {
|
|
118
144
|
let n = this.data.findIndex((t) => t.id === e);
|
|
119
145
|
if (n === -1) return this.client.updateTask(e, { status: t });
|
|
@@ -311,11 +337,14 @@ var c = class {
|
|
|
311
337
|
}
|
|
312
338
|
}
|
|
313
339
|
async deleteComment(e) {
|
|
340
|
+
let t = this.data;
|
|
341
|
+
this.data = this.data.filter((t) => t.id !== e);
|
|
314
342
|
try {
|
|
315
|
-
await this.client.deleteComment(e)
|
|
343
|
+
await this.client.deleteComment(e);
|
|
316
344
|
} catch (e) {
|
|
317
|
-
|
|
318
|
-
|
|
345
|
+
this.data = t;
|
|
346
|
+
let n = e instanceof Error ? e : Error(String(e));
|
|
347
|
+
throw this.error = n, n;
|
|
319
348
|
}
|
|
320
349
|
}
|
|
321
350
|
};
|
|
@@ -371,11 +400,14 @@ var u = class {
|
|
|
371
400
|
}
|
|
372
401
|
}
|
|
373
402
|
async deleteAttachment(e) {
|
|
403
|
+
let t = this.data;
|
|
404
|
+
this.data = this.data.filter((t) => t.id !== e);
|
|
374
405
|
try {
|
|
375
|
-
await this.client.deleteAttachment(e)
|
|
406
|
+
await this.client.deleteAttachment(e);
|
|
376
407
|
} catch (e) {
|
|
377
|
-
|
|
378
|
-
|
|
408
|
+
this.data = t;
|
|
409
|
+
let n = e instanceof Error ? e : Error(String(e));
|
|
410
|
+
throw this.error = n, n;
|
|
379
411
|
}
|
|
380
412
|
}
|
|
381
413
|
};
|
|
@@ -495,19 +527,25 @@ var f = class {
|
|
|
495
527
|
}
|
|
496
528
|
}
|
|
497
529
|
async deleteComment(e) {
|
|
530
|
+
let t = this.comments;
|
|
531
|
+
this.comments = this.comments.filter((t) => t.id !== e);
|
|
498
532
|
try {
|
|
499
|
-
await this.client.deleteComment(e)
|
|
533
|
+
await this.client.deleteComment(e);
|
|
500
534
|
} catch (e) {
|
|
501
|
-
|
|
502
|
-
|
|
535
|
+
this.comments = t;
|
|
536
|
+
let n = e instanceof Error ? e : Error(String(e));
|
|
537
|
+
throw this.error = n, n;
|
|
503
538
|
}
|
|
504
539
|
}
|
|
505
540
|
async deleteAttachment(e) {
|
|
541
|
+
let t = this.attachments;
|
|
542
|
+
this.attachments = this.attachments.filter((t) => t.id !== e);
|
|
506
543
|
try {
|
|
507
|
-
await this.client.deleteAttachment(e)
|
|
544
|
+
await this.client.deleteAttachment(e);
|
|
508
545
|
} catch (e) {
|
|
509
|
-
|
|
510
|
-
|
|
546
|
+
this.attachments = t;
|
|
547
|
+
let n = e instanceof Error ? e : Error(String(e));
|
|
548
|
+
throw this.error = n, n;
|
|
511
549
|
}
|
|
512
550
|
}
|
|
513
551
|
};
|
|
@@ -9,6 +9,7 @@ export declare class TaskState {
|
|
|
9
9
|
constructor(client: CriticalPathClient, projectId?: string | undefined);
|
|
10
10
|
fetch(): Promise<void>;
|
|
11
11
|
createTask(input: Omit<Task, 'id' | 'createdAt' | 'updatedAt'>): Promise<Task>;
|
|
12
|
+
updateTask(taskId: string, updates: Partial<Task>): Promise<Task>;
|
|
12
13
|
updateTaskStatus(taskId: string, status: TaskStatus): Promise<Task>;
|
|
13
14
|
deleteTask(taskId: string): Promise<boolean | undefined>;
|
|
14
15
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"task-state.svelte.d.ts","sourceRoot":"","sources":["../src/task-state.svelte.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AAChE,OAAO,KAAK,EAAE,IAAI,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAE5D,qBAAa,SAAS;IAMlB,OAAO,CAAC,MAAM;IACP,SAAS,CAAC,EAAE,MAAM;IAN3B,IAAI,SAAsB;IAC1B,OAAO,UAA0B;IACjC,KAAK,eAA8B;gBAGzB,MAAM,EAAE,kBAAkB,EAC3B,SAAS,CAAC,EAAE,MAAM,YAAA;IAGrB,KAAK;IAYL,UAAU,CAAC,KAAK,EAAE,IAAI,CAAC,IAAI,EAAE,IAAI,GAAG,WAAW,GAAG,WAAW,CAAC;IA2B9D,gBAAgB,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,UAAU;IAyCnD,UAAU,CAAC,MAAM,EAAE,MAAM;CAuBhC;AAED,wBAAgB,eAAe,CAC7B,MAAM,EAAE,kBAAkB,EAC1B,SAAS,CAAC,EAAE,MAAM,GACjB,SAAS,CAEX"}
|
|
1
|
+
{"version":3,"file":"task-state.svelte.d.ts","sourceRoot":"","sources":["../src/task-state.svelte.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AAChE,OAAO,KAAK,EAAE,IAAI,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAE5D,qBAAa,SAAS;IAMlB,OAAO,CAAC,MAAM;IACP,SAAS,CAAC,EAAE,MAAM;IAN3B,IAAI,SAAsB;IAC1B,OAAO,UAA0B;IACjC,KAAK,eAA8B;gBAGzB,MAAM,EAAE,kBAAkB,EAC3B,SAAS,CAAC,EAAE,MAAM,YAAA;IAGrB,KAAK;IAYL,UAAU,CAAC,KAAK,EAAE,IAAI,CAAC,IAAI,EAAE,IAAI,GAAG,WAAW,GAAG,WAAW,CAAC;IA2B9D,UAAU,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,CAAC,IAAI,CAAC;IAyCjD,gBAAgB,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,UAAU;IAyCnD,UAAU,CAAC,MAAM,EAAE,MAAM;CAuBhC;AAED,wBAAgB,eAAe,CAC7B,MAAM,EAAE,kBAAkB,EAC1B,SAAS,CAAC,EAAE,MAAM,GACjB,SAAS,CAEX"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@critical-path/svelte",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.6.0",
|
|
4
4
|
"description": "Svelte 5 Runes state and reactive integrations for Critical Path headless project management framework",
|
|
5
5
|
"author": "Jack James",
|
|
6
6
|
"license": "MIT",
|
|
@@ -18,8 +18,8 @@
|
|
|
18
18
|
}
|
|
19
19
|
},
|
|
20
20
|
"dependencies": {
|
|
21
|
-
"@critical-path/
|
|
22
|
-
"@critical-path/
|
|
21
|
+
"@critical-path/core": "0.9.0",
|
|
22
|
+
"@critical-path/client": "0.4.4"
|
|
23
23
|
},
|
|
24
24
|
"peerDependencies": {
|
|
25
25
|
"svelte": "^5.0.0"
|
|
@@ -129,10 +129,12 @@ export class TaskActivityState {
|
|
|
129
129
|
}
|
|
130
130
|
|
|
131
131
|
async deleteComment(id: string) {
|
|
132
|
+
const previous = this.comments;
|
|
133
|
+
this.comments = this.comments.filter((c) => c.id !== id);
|
|
132
134
|
try {
|
|
133
135
|
await this.client.deleteComment(id);
|
|
134
|
-
this.comments = this.comments.filter((c) => c.id !== id);
|
|
135
136
|
} catch (err) {
|
|
137
|
+
this.comments = previous;
|
|
136
138
|
const errorObj = err instanceof Error ? err : new Error(String(err));
|
|
137
139
|
this.error = errorObj;
|
|
138
140
|
throw errorObj;
|
|
@@ -140,10 +142,12 @@ export class TaskActivityState {
|
|
|
140
142
|
}
|
|
141
143
|
|
|
142
144
|
async deleteAttachment(id: string) {
|
|
145
|
+
const previous = this.attachments;
|
|
146
|
+
this.attachments = this.attachments.filter((a) => a.id !== id);
|
|
143
147
|
try {
|
|
144
148
|
await this.client.deleteAttachment(id);
|
|
145
|
-
this.attachments = this.attachments.filter((a) => a.id !== id);
|
|
146
149
|
} catch (err) {
|
|
150
|
+
this.attachments = previous;
|
|
147
151
|
const errorObj = err instanceof Error ? err : new Error(String(err));
|
|
148
152
|
this.error = errorObj;
|
|
149
153
|
throw errorObj;
|
|
@@ -43,10 +43,12 @@ export class AttachmentState {
|
|
|
43
43
|
}
|
|
44
44
|
|
|
45
45
|
async deleteAttachment(id: string) {
|
|
46
|
+
const previous = this.data;
|
|
47
|
+
this.data = this.data.filter((a) => a.id !== id);
|
|
46
48
|
try {
|
|
47
49
|
await this.client.deleteAttachment(id);
|
|
48
|
-
this.data = this.data.filter((a) => a.id !== id);
|
|
49
50
|
} catch (err) {
|
|
51
|
+
this.data = previous;
|
|
50
52
|
const errorObj = err instanceof Error ? err : new Error(String(err));
|
|
51
53
|
this.error = errorObj;
|
|
52
54
|
throw errorObj;
|
|
@@ -79,10 +79,12 @@ export class CommentState {
|
|
|
79
79
|
}
|
|
80
80
|
|
|
81
81
|
async deleteComment(id: string) {
|
|
82
|
+
const previous = this.data;
|
|
83
|
+
this.data = this.data.filter((c) => c.id !== id);
|
|
82
84
|
try {
|
|
83
85
|
await this.client.deleteComment(id);
|
|
84
|
-
this.data = this.data.filter((c) => c.id !== id);
|
|
85
86
|
} catch (err) {
|
|
87
|
+
this.data = previous;
|
|
86
88
|
const errorObj = err instanceof Error ? err : new Error(String(err));
|
|
87
89
|
this.error = errorObj;
|
|
88
90
|
throw errorObj;
|
package/src/index.test.ts
CHANGED
|
@@ -131,7 +131,7 @@ describe('@critical-path/svelte Svelte 5 Runes Test Suite', () => {
|
|
|
131
131
|
const mockClient = {
|
|
132
132
|
getTasks: vi.fn().mockResolvedValue([mockTask]),
|
|
133
133
|
createTask: vi.fn().mockResolvedValue(mockTask),
|
|
134
|
-
updateTask: vi.fn().
|
|
134
|
+
updateTask: vi.fn().mockImplementation((taskId: string, updates: Partial<Task>) => Promise.resolve({ ...mockTask, ...updates })),
|
|
135
135
|
deleteTask: vi.fn().mockResolvedValue(undefined)
|
|
136
136
|
} as unknown as CriticalPathClient;
|
|
137
137
|
|
|
@@ -144,6 +144,12 @@ describe('@critical-path/svelte Svelte 5 Runes Test Suite', () => {
|
|
|
144
144
|
await taskState.updateTaskStatus('task_1', 'in_progress');
|
|
145
145
|
expect(taskState.data[0].status).toBe('in_progress');
|
|
146
146
|
|
|
147
|
+
// Update task generic updates (e.g. todos)
|
|
148
|
+
await taskState.updateTask('task_1', {
|
|
149
|
+
todos: [{ id: 'todo_1', title: 'Checklist item', completed: true }]
|
|
150
|
+
});
|
|
151
|
+
expect(taskState.data[0].todos).toEqual([{ id: 'todo_1', title: 'Checklist item', completed: true }]);
|
|
152
|
+
|
|
147
153
|
// Delete task
|
|
148
154
|
await taskState.deleteTask('task_1');
|
|
149
155
|
expect(taskState.data).toEqual([]);
|
|
@@ -259,6 +265,32 @@ describe('@critical-path/svelte Svelte 5 Runes Test Suite', () => {
|
|
|
259
265
|
await attachmentState.deleteAttachment('att_1');
|
|
260
266
|
expect(attachmentState.data).toEqual([]);
|
|
261
267
|
});
|
|
268
|
+
|
|
269
|
+
it('rolls back optimistic deletion if deleteAttachment fails', async () => {
|
|
270
|
+
const mockAttachment = {
|
|
271
|
+
id: 'att_2',
|
|
272
|
+
filename: 'notes.txt',
|
|
273
|
+
mimeType: 'text/plain',
|
|
274
|
+
sizeBytes: 100,
|
|
275
|
+
url: 'https://storage.example.com/notes.txt',
|
|
276
|
+
uploaderId: 'u1',
|
|
277
|
+
uploaderType: 'user' as const,
|
|
278
|
+
createdAt: '2026-01-01',
|
|
279
|
+
updatedAt: '2026-01-01'
|
|
280
|
+
};
|
|
281
|
+
|
|
282
|
+
const mockClient = {
|
|
283
|
+
getAttachments: vi.fn().mockResolvedValue([mockAttachment]),
|
|
284
|
+
deleteAttachment: vi.fn().mockRejectedValue(new Error('Network error'))
|
|
285
|
+
} as unknown as CriticalPathClient;
|
|
286
|
+
|
|
287
|
+
const attachmentState = new AttachmentState(mockClient, { taskId: 'task_1' });
|
|
288
|
+
await attachmentState.fetch();
|
|
289
|
+
|
|
290
|
+
expect(attachmentState.data).toHaveLength(1);
|
|
291
|
+
await expect(attachmentState.deleteAttachment('att_2')).rejects.toThrow('Network error');
|
|
292
|
+
expect(attachmentState.data).toEqual([mockAttachment]);
|
|
293
|
+
});
|
|
262
294
|
});
|
|
263
295
|
|
|
264
296
|
describe('TaskActivityState', () => {
|
|
@@ -304,6 +336,10 @@ describe('@critical-path/svelte Svelte 5 Runes Test Suite', () => {
|
|
|
304
336
|
expect(activityState.threads).toHaveLength(1);
|
|
305
337
|
expect(activityState.threads[0].attachments).toEqual([mockAttachment]);
|
|
306
338
|
expect(activityState.standaloneAttachments).toHaveLength(0);
|
|
339
|
+
|
|
340
|
+
await activityState.deleteAttachment('att_1');
|
|
341
|
+
expect(activityState.attachments).toEqual([]);
|
|
342
|
+
expect(activityState.threads[0].attachments).toEqual([]);
|
|
307
343
|
});
|
|
308
344
|
});
|
|
309
345
|
});
|
package/src/task-state.svelte.ts
CHANGED
|
@@ -51,6 +51,47 @@ export class TaskState {
|
|
|
51
51
|
}
|
|
52
52
|
}
|
|
53
53
|
|
|
54
|
+
async updateTask(taskId: string, updates: Partial<Task>) {
|
|
55
|
+
const idx = this.data.findIndex((t) => t.id === taskId);
|
|
56
|
+
if (idx === -1) {
|
|
57
|
+
return this.client.updateTask(taskId, updates);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
const previousTask = this.data[idx];
|
|
61
|
+
const optimisticTask: Task = {
|
|
62
|
+
...previousTask,
|
|
63
|
+
...updates,
|
|
64
|
+
updatedAt: new Date().toISOString()
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
// Optimistically update local task
|
|
68
|
+
const newData = [...this.data];
|
|
69
|
+
newData[idx] = optimisticTask;
|
|
70
|
+
this.data = newData;
|
|
71
|
+
|
|
72
|
+
try {
|
|
73
|
+
const updated = await this.client.updateTask(taskId, updates);
|
|
74
|
+
const currentIdx = this.data.findIndex((t) => t.id === taskId);
|
|
75
|
+
if (currentIdx !== -1) {
|
|
76
|
+
const confirmedData = [...this.data];
|
|
77
|
+
confirmedData[currentIdx] = updated;
|
|
78
|
+
this.data = confirmedData;
|
|
79
|
+
}
|
|
80
|
+
return updated;
|
|
81
|
+
} catch (err) {
|
|
82
|
+
// Rollback to previous task on error
|
|
83
|
+
const rollbackIdx = this.data.findIndex((t) => t.id === taskId);
|
|
84
|
+
if (rollbackIdx !== -1) {
|
|
85
|
+
const rollbackData = [...this.data];
|
|
86
|
+
rollbackData[rollbackIdx] = previousTask;
|
|
87
|
+
this.data = rollbackData;
|
|
88
|
+
}
|
|
89
|
+
const errorObj = err instanceof Error ? err : new Error(String(err));
|
|
90
|
+
this.error = errorObj;
|
|
91
|
+
throw errorObj;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
54
95
|
async updateTaskStatus(taskId: string, status: TaskStatus) {
|
|
55
96
|
const idx = this.data.findIndex((t) => t.id === taskId);
|
|
56
97
|
if (idx === -1) {
|