@bud.sh/app 0.4.1 → 0.5.1
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/client/assets/bud/design.js +1 -1
- package/dist/client/assets/{canvas-DIKX_HCJ.js → canvas-8GXJIuDK.js} +1 -1
- package/dist/client/assets/difference-worker-C99ychYw.js +8 -0
- package/dist/client/assets/{edit-B050x0rV.js → edit-DUotSxjS.js} +12 -12
- package/dist/client/assets/files-DkWt1l9H.js +1 -0
- package/dist/client/assets/i18n-hH_Ba5QO.js +1 -0
- package/dist/client/assets/{index-COvyj5zV.js → index-Dn2pfmXf.js} +2 -2
- package/dist/client/assets/index-tpHYVXma.css +2 -0
- package/dist/client/assets/lru-DzKYIXMA.js +1 -0
- package/dist/client/assets/pages-BVd6MQmu.js +1 -0
- package/dist/client/assets/{project-branches-DwKjCwZv.js → project-branches-CMGRmrqr.js} +1 -1
- package/dist/client/assets/project-comments-D1IIQwsW.js +1 -0
- package/dist/client/assets/project-thread-links-DKwe_SYb.js +1 -0
- package/dist/client/assets/{project-threads-DeKXNqeP.js → project-threads-ZbKDh78d.js} +105 -105
- package/dist/client/assets/{project-work-B7PGQtV9.js → project-work-D4DZqBCZ.js} +1 -1
- package/dist/client/assets/rolldown-runtime-XKyaHtl9.js +1 -0
- package/dist/client/assets/task-design-BPpc4Gd7.js +23 -0
- package/dist/client/assets/tasks-Cn0VOZ9Z.js +1 -0
- package/dist/client/assets/{tasks-request-CsUB5__X.js → tasks-request-BLyOzokZ.js} +1 -1
- package/dist/client/assets/workspace-DGErsSg6.js +2 -0
- package/dist/client/index.html +3 -3
- package/dist/hosted/assets/{canvas-gWj_ocKK.js → canvas-BYTOp1p7.js} +6 -4
- package/dist/hosted/assets/{comment-data-C-rNCB1n.js → comment-data-Cn5y2VxV.js} +4026 -3665
- package/dist/hosted/assets/{files-CAPvbavY.js → files-B1P2_24q.js} +5 -3
- package/dist/hosted/assets/{pages-DJiOvT-l.js → pages-B0ZlVdci.js} +3 -3
- package/dist/hosted/assets/{project-branches-BgrfdvtL.js → project-branches-DlCWmfRo.js} +1 -1
- package/dist/hosted/assets/{project-thread-links-B7uzThL9.js → project-thread-links-BZXQ200n.js} +2 -2
- package/dist/hosted/assets/{screen-D4D9nh4V.js → screen-CfdC3NbR.js} +72 -137
- package/dist/hosted/assets/{tasks-C7aGLzBw.js → tasks-_yKh2Z6q.js} +12 -5
- package/dist/hosted/assets/{tasks-request-CikFdCgP.js → tasks-request-CFPLvLc7.js} +1 -1
- package/dist/hosted/hosted.js +164 -16
- package/dist/node/assets/{src-BdvZ2mYc.js → src-CerrKjID.js} +57 -1
- package/dist/node/design.js +826 -791
- package/dist/node/server.js +25 -3
- package/dist/node-host/assets/{canvas-kXzp80a5.js → canvas-DxmcFZCh.js} +6 -4
- package/dist/node-host/assets/{comment-data-CeuJbJKJ.js → comment-data-yfWEdDQL.js} +4004 -3643
- package/dist/node-host/assets/{files-0YIuvKzb.js → files-anHi-apm.js} +5 -3
- package/dist/node-host/assets/{pages-DOF22SyG.js → pages-CW4aF6dK.js} +3 -3
- package/dist/node-host/assets/{project-branches-BeEwMBIw.js → project-branches-D7rVCxQX.js} +1 -1
- package/dist/node-host/assets/{project-thread-links-Bs_MtfBC.js → project-thread-links-m-OLpsD9.js} +2 -2
- package/dist/node-host/assets/{screen-DRTAKkn3.js → screen-DapOVrga.js} +72 -137
- package/dist/node-host/assets/{tasks-BA_hcbj5.js → tasks-BBK_CybR.js} +12 -5
- package/dist/node-host/assets/{tasks-request-Doc9y_20.js → tasks-request-B0aeNocI.js} +1 -1
- package/dist/node-host/node-host.js +164 -16
- package/dist/server/assets/{canvas-CiN6jNIZ.js → canvas-CkMK4hoN.js} +7 -5
- package/dist/server/assets/{comment-data-9SqALQjT.js → comment-data-NLeHG89b.js} +3781 -3631
- package/dist/server/assets/{events-6z5v7Uca.js → events-iHpLGr3k.js} +213 -2
- package/dist/server/assets/{files-DBVqeLdL.js → files-CRdl489E.js} +6 -4
- package/dist/server/assets/{listener-DGWKUc2o.js → listener-BAYn9Q-u.js} +35 -9
- package/dist/server/assets/{pages-DJMLr6j9.js → pages-DXVlJlBC.js} +4 -4
- package/dist/server/assets/{project-branches-DbKEmiQT.js → project-branches-CwTsf6WQ.js} +2 -2
- package/dist/server/assets/{project-thread-links-C0kV_Pcl.js → project-thread-links-lLS_rq7c.js} +3 -3
- package/dist/server/assets/{project-work-C0FN3w5Y.js → project-work-CSZlCwH-.js} +3 -3
- package/dist/server/assets/{screen-BtvzEiIa.js → screen-B1zH_1O3.js} +73 -138
- package/dist/server/assets/{server-CYvuOSBA.js → server-DxK-UB_Z.js} +30 -4
- package/dist/server/assets/{services-DK4fqrlF.js → services-BRrgXYlT.js} +105 -9
- package/dist/server/assets/{tasks-DX71x8f9.js → tasks-CGdz-uox.js} +14 -7
- package/dist/server/assets/{tasks-request-C3jk9Jyu.js → tasks-request-D2NBjCTl.js} +2 -2
- package/dist/server/migration.js +3 -3
- package/dist/server/runtime.js +3 -3
- package/dist/server/server.js +2 -2
- package/dist/types/server.d.ts +11 -1
- package/package.json +1 -1
- package/dist/client/assets/difference-worker-CwQNxTJL.js +0 -8
- package/dist/client/assets/files-BQ9O3Z8-.js +0 -1
- package/dist/client/assets/i18n-CL0jBP7Y.js +0 -1
- package/dist/client/assets/index-CjhJtepP.css +0 -2
- package/dist/client/assets/lru-BkhKJhvt.js +0 -1
- package/dist/client/assets/pages-BGl2Yuza.js +0 -1
- package/dist/client/assets/project-comments-Cdip2Y10.js +0 -1
- package/dist/client/assets/project-thread-links-BGIkGQeU.js +0 -1
- package/dist/client/assets/task-design-DJp5yho1.js +0 -23
- package/dist/client/assets/tasks-BHXj727C.js +0 -1
- package/dist/client/assets/workspace-CbO7RsI2.js +0 -2
|
@@ -1,144 +1,21 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { En as t, _ as requestComments, a as saveThreads, b as writeOptimistically, bn as toast, g as CommentsRequestError, i as saveThread, l as projectStore, n as unavailableComments, o as threadMatches, y as plainRow } from "./comment-data-
|
|
3
|
-
//#region
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
* @param now - The creation time.
|
|
12
|
-
* @returns The provisional task.
|
|
13
|
-
*/
|
|
14
|
-
function predictWorkCreate(schema, id, create, now = /* @__PURE__ */ new Date()) {
|
|
15
|
-
let values = { ...create.values };
|
|
16
|
-
for (let field of schema.fields) if ((field.role === "created" || field.role === "updated") && values[field.id] === void 0) values[field.id] = field.kind === "date" ? now.toISOString().slice(0, 10) : now.toISOString();
|
|
17
|
-
return {
|
|
18
|
-
id,
|
|
19
|
-
revision: null,
|
|
20
|
-
values,
|
|
21
|
-
relations: [],
|
|
22
|
-
counts: {},
|
|
23
|
-
contentLoaded: false,
|
|
24
|
-
extra: null
|
|
25
|
-
};
|
|
26
|
-
}
|
|
27
|
-
/**
|
|
28
|
-
* How a task shows until its adapter confirms an edit: the edited values over its own.
|
|
29
|
-
* @param item - The task as last confirmed.
|
|
30
|
-
* @param update - The update request.
|
|
31
|
-
* @returns The predicted task.
|
|
32
|
-
*/
|
|
33
|
-
function predictWorkUpdate(item, update) {
|
|
34
|
-
return {
|
|
35
|
-
...item,
|
|
36
|
-
values: {
|
|
37
|
-
...item.values,
|
|
38
|
-
...update.values
|
|
39
|
-
}
|
|
40
|
-
};
|
|
41
|
-
}
|
|
42
|
-
var targets = {
|
|
43
|
-
close: ["done", "cancelled"],
|
|
44
|
-
reopen: [
|
|
45
|
-
"unstarted",
|
|
46
|
-
"backlog",
|
|
47
|
-
"started"
|
|
48
|
-
]
|
|
49
|
-
};
|
|
50
|
-
/**
|
|
51
|
-
* How a task shows until its adapter confirms an action. Closing and reopening move it to
|
|
52
|
-
* the schema's first matching status; otherwise only input naming the task's own fields
|
|
53
|
-
* applies, since an action's effects belong to the adapter.
|
|
54
|
-
* @param schema - The board's schema.
|
|
55
|
-
* @param item - The task as last confirmed.
|
|
56
|
-
* @param action - The action request.
|
|
57
|
-
* @returns The predicted task.
|
|
58
|
-
*/
|
|
59
|
-
function predictWorkAction(schema, item, action) {
|
|
60
|
-
let fields = new Set(schema.fields.map((field) => field.id));
|
|
61
|
-
let values = { ...item.values };
|
|
62
|
-
for (let [id, value] of Object.entries(action.input)) if (fields.has(id)) values[id] = value;
|
|
63
|
-
let kind = schema.actions.find((candidate) => candidate.id === action.action)?.kind;
|
|
64
|
-
let categories = kind ? targets[kind] : void 0;
|
|
65
|
-
let field = schema.fields.find((candidate) => candidate.role === "status");
|
|
66
|
-
let status = categories?.map((category) => schema.statuses.find((candidate) => candidate.category === category)).find(Boolean);
|
|
67
|
-
if (field && status) values[field.id] = status.value;
|
|
68
|
-
return {
|
|
69
|
-
...item,
|
|
70
|
-
values
|
|
71
|
-
};
|
|
72
|
-
}
|
|
73
|
-
/** Who a message shows as until the server, which derives authors from Git, confirms it. */
|
|
74
|
-
var pendingAuthor = {
|
|
75
|
-
id: "pending",
|
|
76
|
-
name: "You",
|
|
77
|
-
email: ""
|
|
78
|
-
};
|
|
79
|
-
function message(id, body, parentId, now) {
|
|
80
|
-
return {
|
|
81
|
-
id,
|
|
82
|
-
body: body.trim(),
|
|
83
|
-
author: pendingAuthor,
|
|
84
|
-
createdAt: now.toISOString(),
|
|
85
|
-
parentId
|
|
86
|
-
};
|
|
87
|
-
}
|
|
88
|
-
/**
|
|
89
|
-
* How a new discussion shows until its adapter confirms it.
|
|
90
|
-
* @param id - A provisional identity, also used for its first message.
|
|
91
|
-
* @param input - The create request.
|
|
92
|
-
* @param now - The creation time.
|
|
93
|
-
* @returns The provisional discussion.
|
|
94
|
-
*/
|
|
95
|
-
function predictThreadCreate(id, input, now = /* @__PURE__ */ new Date()) {
|
|
96
|
-
let createdAt = now.toISOString();
|
|
97
|
-
return {
|
|
98
|
-
id,
|
|
99
|
-
status: "open",
|
|
100
|
-
anchor: input.anchor,
|
|
101
|
-
itemIds: [...input.itemIds],
|
|
102
|
-
messages: [message(id, input.body, null, now)],
|
|
103
|
-
messageCount: 1,
|
|
104
|
-
messagesLoaded: true,
|
|
105
|
-
messagesTruncated: false,
|
|
106
|
-
createdAt,
|
|
107
|
-
updatedAt: createdAt,
|
|
108
|
-
revision: null
|
|
1
|
+
import { F as parseThreadId, P as parseThreadFilter, b as predictThreadReply, i as routes, j as parseThread, v as predictThreadCreate, x as predictThreadStatus, y as predictThreadDelete, z as parseThreadSnapshot } from "./events-iHpLGr3k.js";
|
|
2
|
+
import { En as t, _ as requestComments, a as saveThreads, b as writeOptimistically, bn as toast, g as CommentsRequestError, i as saveThread, l as projectStore, n as unavailableComments, o as threadMatches, x as writeRows, y as plainRow } from "./comment-data-NLeHG89b.js";
|
|
3
|
+
//#region app/client/project-comments.ts
|
|
4
|
+
var viewers = /* @__PURE__ */ new Map();
|
|
5
|
+
function parseViewer(value) {
|
|
6
|
+
let viewer = value && typeof value === "object" && "viewer" in value ? value.viewer : void 0;
|
|
7
|
+
if (viewer === null) return null;
|
|
8
|
+
if (viewer && typeof viewer === "object" && "id" in viewer && "name" in viewer && typeof viewer.id === "string" && typeof viewer.name === "string" && viewer.id.length <= 256 && viewer.name.length <= 1e3) return {
|
|
9
|
+
id: viewer.id,
|
|
10
|
+
name: viewer.name
|
|
109
11
|
};
|
|
12
|
+
throw new TypeError("Invalid viewer.");
|
|
110
13
|
}
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
* @param id - A provisional message identity.
|
|
115
|
-
* @param input - The reply request.
|
|
116
|
-
* @param now - The reply time.
|
|
117
|
-
* @returns The predicted discussion.
|
|
118
|
-
*/
|
|
119
|
-
function predictThreadReply(thread, id, input, now = /* @__PURE__ */ new Date()) {
|
|
120
|
-
return {
|
|
121
|
-
...thread,
|
|
122
|
-
messages: thread.messagesLoaded ? [...thread.messages, message(id, input.body, input.parentId, now)] : thread.messages,
|
|
123
|
-
messageCount: thread.messageCount + 1,
|
|
124
|
-
updatedAt: now.toISOString()
|
|
125
|
-
};
|
|
14
|
+
function parseDeletion(value) {
|
|
15
|
+
if (!value || typeof value !== "object" || !("thread" in value)) throw new TypeError("Invalid deletion.");
|
|
16
|
+
return { thread: value.thread === null ? null : parseThread(value.thread) };
|
|
126
17
|
}
|
|
127
18
|
/**
|
|
128
|
-
* How a discussion shows until its adapter confirms a status change.
|
|
129
|
-
* @param thread - The discussion as last confirmed.
|
|
130
|
-
* @param input - The status request.
|
|
131
|
-
* @returns The predicted discussion.
|
|
132
|
-
*/
|
|
133
|
-
function predictThreadStatus(thread, input) {
|
|
134
|
-
return {
|
|
135
|
-
...thread,
|
|
136
|
-
status: input.status
|
|
137
|
-
};
|
|
138
|
-
}
|
|
139
|
-
//#endregion
|
|
140
|
-
//#region app/client/project-comments.ts
|
|
141
|
-
/**
|
|
142
19
|
* Reads one task's discussions with their messages in a single round, so the task page
|
|
143
20
|
* renders complete instead of loading its discussion after it appears.
|
|
144
21
|
* @param token - The current companion capability.
|
|
@@ -246,6 +123,21 @@ function createProjectComments(options) {
|
|
|
246
123
|
let generation = 0, reading;
|
|
247
124
|
let details = /* @__PURE__ */ new Map();
|
|
248
125
|
let detailFailures = /* @__PURE__ */ new Set();
|
|
126
|
+
let viewer = null, askedViewer = false;
|
|
127
|
+
function askViewer() {
|
|
128
|
+
if (askedViewer || !snapshot.capabilities.delete) return;
|
|
129
|
+
askedViewer = true;
|
|
130
|
+
let pending = viewers.get(options.token);
|
|
131
|
+
if (!pending) {
|
|
132
|
+
pending = requestComments(routes.comments.viewer.href(), options.token, new AbortController().signal, parseViewer, options.fetcher).catch(() => null);
|
|
133
|
+
viewers.set(options.token, pending);
|
|
134
|
+
}
|
|
135
|
+
pending.then((value) => {
|
|
136
|
+
viewer = value;
|
|
137
|
+
changed();
|
|
138
|
+
});
|
|
139
|
+
}
|
|
140
|
+
askViewer();
|
|
249
141
|
let opened = Promise.resolve(options.store).then(async (ready) => {
|
|
250
142
|
store = ready;
|
|
251
143
|
if (options.initial?.snapshot && !options.initial.stored) await saveThreads(ready, options.initial.snapshot, filter);
|
|
@@ -265,6 +157,7 @@ function createProjectComments(options) {
|
|
|
265
157
|
loaded = true;
|
|
266
158
|
now = Date.now();
|
|
267
159
|
version++;
|
|
160
|
+
askViewer();
|
|
268
161
|
changed();
|
|
269
162
|
}
|
|
270
163
|
function request(url, signal, parse, body) {
|
|
@@ -282,6 +175,12 @@ function createProjectComments(options) {
|
|
|
282
175
|
await saveThread(store, thread);
|
|
283
176
|
view();
|
|
284
177
|
}
|
|
178
|
+
async function forget(id) {
|
|
179
|
+
await opened;
|
|
180
|
+
members?.delete(id);
|
|
181
|
+
await writeRows(store.threads, { delete: [id] });
|
|
182
|
+
view();
|
|
183
|
+
}
|
|
285
184
|
function includes(thread) {
|
|
286
185
|
return threadMatches(thread, filter);
|
|
287
186
|
}
|
|
@@ -335,6 +234,10 @@ function createProjectComments(options) {
|
|
|
335
234
|
if (!detailFailures.size) error = "";
|
|
336
235
|
}
|
|
337
236
|
} catch (cause) {
|
|
237
|
+
if (!signal.aborted && turn === generation && cause instanceof CommentsRequestError && cause.code === "not-found") {
|
|
238
|
+
await forget(id);
|
|
239
|
+
return;
|
|
240
|
+
}
|
|
338
241
|
if (!signal.aborted && turn === generation) {
|
|
339
242
|
detailFailures.add(id);
|
|
340
243
|
error = cause instanceof Error ? cause.message : t("app.client.projectComments.couldNotLoadDiscussion");
|
|
@@ -414,6 +317,13 @@ function createProjectComments(options) {
|
|
|
414
317
|
get ready() {
|
|
415
318
|
return loaded && snapshot.connection.state === "ready";
|
|
416
319
|
},
|
|
320
|
+
/**
|
|
321
|
+
* Who this browser comments as, once the server said.
|
|
322
|
+
* @returns The viewer, or null until then or without one.
|
|
323
|
+
*/
|
|
324
|
+
get viewer() {
|
|
325
|
+
return viewer;
|
|
326
|
+
},
|
|
417
327
|
loadingThread: (id) => details.has(id),
|
|
418
328
|
load,
|
|
419
329
|
loadThread,
|
|
@@ -475,6 +385,31 @@ function createProjectComments(options) {
|
|
|
475
385
|
thread: saved
|
|
476
386
|
};
|
|
477
387
|
},
|
|
388
|
+
/**
|
|
389
|
+
* Deletes one of the viewer's messages; its first message deletes the whole discussion.
|
|
390
|
+
* @param threadId - The discussion.
|
|
391
|
+
* @param messageId - The message to delete.
|
|
392
|
+
* @returns The snapshot after the confirmed deletion.
|
|
393
|
+
*/
|
|
394
|
+
async remove(threadId, messageId) {
|
|
395
|
+
requireCapability("delete");
|
|
396
|
+
let id = parseThreadId(threadId), thread = snapshot.threads.find((item) => item.id === id);
|
|
397
|
+
if (!thread?.revision) throw new Error(t("app.client.projectComments.reloadDiscussionBeforeSaving"));
|
|
398
|
+
let next = predictThreadDelete(thread, messageId);
|
|
399
|
+
return operate(routes.comments.deleteMessage.href({ id }), {
|
|
400
|
+
messageId,
|
|
401
|
+
expectedRevision: thread.revision
|
|
402
|
+
}, parseDeletion, (result) => {
|
|
403
|
+
if (!result.thread) return forget(id);
|
|
404
|
+
if (result.thread.id !== id) throw new CommentsRequestError(t("app.client.projectComments.refreshBeforeTryingAgain"), 409, "uncertain");
|
|
405
|
+
return merge(result.thread);
|
|
406
|
+
}, next ? t("app.client.projectComments.commentDeleted") : t("app.client.projectComments.discussionDeleted"), id, (store) => {
|
|
407
|
+
if (next && store.threads.has(id)) store.threads.update(id, (draft) => {
|
|
408
|
+
draft.messages = next.messages;
|
|
409
|
+
draft.messageCount = next.messageCount;
|
|
410
|
+
});
|
|
411
|
+
});
|
|
412
|
+
},
|
|
478
413
|
async sync() {
|
|
479
414
|
requireCapability("sync");
|
|
480
415
|
return operate(routes.comments.sync.href(), { direction: "both" }, parseThreadSnapshot, adopt, t("app.client.projectComments.commentsSynced"));
|
|
@@ -492,4 +427,4 @@ function defineScreen(screen) {
|
|
|
492
427
|
return screen;
|
|
493
428
|
}
|
|
494
429
|
//#endregion
|
|
495
|
-
export {
|
|
430
|
+
export { loadItemComments as i, createProjectComments as n, loadComments as r, defineScreen as t };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { $ as publishAll, $n as forkUnsafe, $t as provideContext, An as uninterruptible, At as catch_, Bn as effectDiscard, Bt as forever, Cn as tap, Ct as as$1, D as as, Dn as tryPromise, E as FileSystem, Fn as currentTimeMillis, Ft as fail$1, G as make$3, Gn as mergeAll, Gt as map, H as runForEach, Hn as isLayer, Ht as forkScoped, I as fromPubSub, In as build, It as filterOrFail, J as offerUnsafe, Jn as succeed$1, Jt as option, Kn as provide$1, Kt as mapError, L as ignore$1, Ln as buildWithMemoMap, Lt as flatMap, Mn as void_$1, N as empty$1, Nn as withFiber, Nt as die, O as callback, On as try_, Ot as catchIf, P as filter, Pn as yieldNow, Pt as ensuring, Q as publish, Qn as close, R as make$2, Rn as effect, Rt as flatten, S as writeTextAtomic, Sn as sync, St as andThen, T as Path, Tn as timeoutOption, Tt as asVoid, U as tap$1, Un as makeMemoMapUnsafe, Ut as gen, V as merge, Vn as empty, Vt as forkIn, W as unwrap$1, Wt as ignore, X as sliding$1, Xn as sync$1, Xt as orElseSucceed, Y as shutdown$1, Yt as orDie, Z as take, Zn as unwrap, Zt as promise, _n as serviceOption, _t as bytes$1, an as runFork, ar as void_, at as runIn, bn as succeedNone, bt as addFinalizer, cn as runPromiseExit, cr as add, dn as runSync, dr as getOrNull, en as provideService, er as makeUnsafe, et as shutdown, fn as runSyncExit, fr as getOrUndefined, gn as scoped, gr as TaggedError, hn as scope, hr as some, in as runCallbackWith, ir as succeed$2, it as interrupt, j as debounce, jn as uninterruptibleMask, jt as clockWith, kn as undefined_$1, kt as catchTag, ln as runPromiseExitWith, lr as getOption, m as projectModuleFile, mn as runSyncWith, mr as none, nr as doneUnsafe, nt as unbounded, on as runForkWith, or as scopeRemoveFinalizerUnsafe, pn as runSyncExitWith, pr as isNone, q as offer, rn as runCallback, rr as make$4, rt as await_, sn as runPromise, sr as Service, tn as result, tr as _await, tt as sliding, u as Git, un as runPromiseWith, ur as make$1, vn as sleep, vt as acquireRelease, w as RuntimePolicy, wn as tapError, wt as asSome, xn as suspend, xt as all, yn as succeed, zn as effectContext, zt as forEach } from "./branch-previews-ClkoJ0lM.js";
|
|
2
|
-
import { $ as
|
|
2
|
+
import { $t as list, At as parseReviewSourceQuery, Cn as parseWorkValue, Ct as parseReviewDiffQuery, D as MAX_THREADS, Dn as parseMessage, En as messageDeletionRefusals, Fn as identifier, Ft as parseFileSearchQuery, G as applyReviewSelection, I as parseThreadInput, In as nonempty, Jt as isWithinDirectory, Kt as parseFileIndexQuery, L as parseThreadLinkInput, Ln as parseWork, Lt as classifyText, M as parseThreadCapabilities, Mn as parseWorkSchema, Mt as matchFileText, N as parseThreadDeleteInput, Nn as statusCategory, On as parseMessageAuthor, P as parseThreadFilter, Pn as WorkValidationError, Pt as searchPathMatches, Qt as integer, R as parseThreadReplyInput, Rn as record$1, Rt as filterFileEntries, Sn as parseWorkUpdate, Tn as messageDeletionRefusal, Tt as parseReviewHistoryQuery, V as parseThreadStatusInput, Vn as iconNames, Xt as parseFilePath, Yt as parentPath, Zt as pathHierarchy, _t as parseRecovery, an as parseWorkWorkspace, cn as parseSectionData, dn as parseWorkConnection, en as parseContract, fn as parseWorkCreate, ft as parseMutationApply, gn as parseWorkMutationResult, hn as parseWorkItemRef, i as routes, it as parseReviewActionIntent, j as parseThread, jn as fieldByRole, jt as compileSearchPattern, kn as withoutMessages, ln as parseWorkActionInput, lt as parseFileSaveRequest, mn as parseWorkItem, nn as strict$1, pn as parseWorkDetail, pt as parseMutationIntent, qt as isProtectedPath, r as parseLiveId, rt as parseReviewActionApply, st as parseReviewActionRecovery, t as RESYNC, tn as revision, vn as parseWorkQuery, vt as pathCollisionKey, wn as valueByRole, xt as parseReviewComparison, yn as parseWorkSnapshot, yt as validateMutationSelection, z as parseThreadSnapshot, zn as strict, zt as orderFileEntries } from "./events-iHpLGr3k.js";
|
|
3
3
|
import { pathToFileURL } from "node:url";
|
|
4
4
|
import { createHash, randomBytes, randomUUID } from "node:crypto";
|
|
5
5
|
import { closeSync, constants, fchmodSync, fstatSync, fsyncSync, linkSync, lstatSync, mkdirSync, openSync, readSync, readdirSync, realpathSync, renameSync, rmdirSync, unlinkSync, writeSync } from "node:fs";
|
|
@@ -493,10 +493,10 @@ var MemoryStore = class {
|
|
|
493
493
|
reply: this.schema.capabilities.threads,
|
|
494
494
|
status: this.schema.capabilities.threads,
|
|
495
495
|
link: this.schema.capabilities.threads,
|
|
496
|
+
delete: this.schema.capabilities.threads,
|
|
496
497
|
...options.threadCapabilities,
|
|
497
498
|
sync: false,
|
|
498
|
-
edit: false
|
|
499
|
-
delete: false
|
|
499
|
+
edit: false
|
|
500
500
|
});
|
|
501
501
|
if (this.schema.capabilities.sync) refused("Memory storage has no remote synchronization.");
|
|
502
502
|
for (let action of this.schema.actions) if (action.kind === "custom" && !this.options.actions?.[action.id]) refused("Declare an implementation for each custom memory action.");
|
|
@@ -809,6 +809,28 @@ function memoryThreads(store) {
|
|
|
809
809
|
status: request.status
|
|
810
810
|
}, at);
|
|
811
811
|
}),
|
|
812
|
+
deleteMessage: (root, id, value, author) => store.run(root, true, (data, at) => {
|
|
813
|
+
if (!store.capabilities.delete) refused("This adapter does not allow deleting messages.");
|
|
814
|
+
let request = input$3(() => parseThreadDeleteInput(value));
|
|
815
|
+
let trusted = input$3(() => parseMessageAuthor(author));
|
|
816
|
+
let thread = store.thread(data, id);
|
|
817
|
+
expected(thread, request.expectedRevision);
|
|
818
|
+
let refusal = messageDeletionRefusal(thread.messages, request.messageId, trusted.id);
|
|
819
|
+
if (refusal === "missing") throw new WorkError({
|
|
820
|
+
reason: "not-found",
|
|
821
|
+
message: messageDeletionRefusals.missing
|
|
822
|
+
});
|
|
823
|
+
if (refusal) refused(messageDeletionRefusals[refusal]);
|
|
824
|
+
if (thread.messages[0].id === request.messageId) {
|
|
825
|
+
data.threads.delete(id);
|
|
826
|
+
store.touchThreads(data, thread.itemIds, at);
|
|
827
|
+
return null;
|
|
828
|
+
}
|
|
829
|
+
return save(data, {
|
|
830
|
+
...thread,
|
|
831
|
+
messages: withoutMessages(thread.messages, [request.messageId])
|
|
832
|
+
}, at);
|
|
833
|
+
}),
|
|
812
834
|
link: (root, id, ids, revision) => link(root, id, ids, revision, false),
|
|
813
835
|
unlink: (root, id, ids, revision) => link(root, id, ids, revision, true)
|
|
814
836
|
};
|
|
@@ -1267,7 +1289,11 @@ function adapterRegistryLayer(project, builtIns) {
|
|
|
1267
1289
|
"setStatus",
|
|
1268
1290
|
"link",
|
|
1269
1291
|
"unlink"
|
|
1270
|
-
], [
|
|
1292
|
+
], [
|
|
1293
|
+
"sync",
|
|
1294
|
+
"import",
|
|
1295
|
+
"deleteMessage"
|
|
1296
|
+
]);
|
|
1271
1297
|
let connection = yield* threads.list(root, {}).pipe(flatMap((value) => try_({
|
|
1272
1298
|
try: () => parseThreadSnapshot(value).connection,
|
|
1273
1299
|
catch: failure$3(`Adapter ${selected.threads.id} returned an invalid thread connection.`)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { A as concat, At as catch_, B as mapError$1, Bn as effectDiscard, C as ProcessRunner, Cn as tap, Ct as as, D as as$1, E as FileSystem, En as timeoutOrElse, Et as cached, F as fromEffect, Fn as currentTimeMillis, Ft as fail, Gn as mergeAll, Gt as map, H as runForEach, Ht as forkScoped, It as filterOrFail, Jn as succeed$1, K as makeUnsafe, Kn as provide, Kt as mapError, Lt as flatMap, M as drop, Mn as void_, Mt as context, N as empty, Nt as die, On as try_, Ot as catchIf, Pt as ensuring, R as make, Rn as effect, Sn as sync, St as andThen, T as Path, Tt as asVoid, Ut as gen, W as unwrap, Wn as merge, Wt as ignore, Xt as orElseSucceed, Yn as succeedContext, Zn as unwrap$1, _n as serviceOption, b as nodeLayer, c as previewsLayer, cr as add, ct as String$1, d as gitLayer, dt as Union, f as Project, fr as getOrUndefined, ft as decodeEffect, gn as scoped, gr as TaggedError, gt as optional, ht as isPattern, i as projectFlows, j as debounce, k as changes, kt as catchTag, lt as Struct, mt as isNonEmpty, nn as retry, ot as ArraySchema, pt as isMaxLength, qn as provideMerge, r as branchPreviewsLayer, s as Previews, sr as Service, st as Record, t as BranchPreviews, tn as result, u as Git, ur as make$1, ut as Undefined, w as RuntimePolicy, xn as suspend, xt as all, yn as succeed, yt as acquireUseRelease, z as mapEffect, zn as effectContext, zt as forEach } from "./branch-previews-ClkoJ0lM.js";
|
|
2
|
-
import { A as adapterRegistryLayer, D as publishChanges, E as liveChannelLayer, F as WorkAdapter, I as WorkError, M as memoryAdapterLayer, N as parseThreadImport, O as AdapterRegistry, P as ThreadAdapter, R as bundledScreensLayer, T as LiveChannel, _ as storeActivityLayer, c as FileReview, d as fileSearchLayer, f as Files, g as StoreActivity, i as fileSavesLayer, j as defineAdapter, k as adapterModuleLoaderLayer, l as fileReviewLayer, n as fileReviewActionsLayer, o as fileMutationsLayer, p as filesLayer, s as fileWriteLockLayer, v as storeLiveLayer, z as sourceScreensLayer } from "./server-
|
|
3
|
-
import { A as
|
|
2
|
+
import { A as adapterRegistryLayer, D as publishChanges, E as liveChannelLayer, F as WorkAdapter, I as WorkError, M as memoryAdapterLayer, N as parseThreadImport, O as AdapterRegistry, P as ThreadAdapter, R as bundledScreensLayer, T as LiveChannel, _ as storeActivityLayer, c as FileReview, d as fileSearchLayer, f as Files, g as StoreActivity, i as fileSavesLayer, j as defineAdapter, k as adapterModuleLoaderLayer, l as fileReviewLayer, n as fileReviewActionsLayer, o as fileMutationsLayer, p as filesLayer, s as fileWriteLockLayer, v as storeLiveLayer, z as sourceScreensLayer } from "./server-DxK-UB_Z.js";
|
|
3
|
+
import { A as parseAnchor, B as parseThreadStatus, D as MAX_THREADS, Dn as parseMessage, En as messageDeletionRefusals, I as parseThreadInput, L as parseThreadLinkInput, Mn as parseWorkSchema, N as parseThreadDeleteInput, On as parseMessageAuthor, P as parseThreadFilter, Pn as WorkValidationError, R as parseThreadReplyInput, Sn as parseWorkUpdate, Tn as messageDeletionRefusal, V as parseThreadStatusInput, a as CommentMergeError, bn as parseWorkSync, c as parseCommentInput, cn as parseSectionData, d as parseCommentThread, dn as parseWorkConnection, f as revision, fn as parseWorkCreate, gn as parseWorkMutationResult, j as parseThread, kn as withoutMessages, l as conversationId, ln as parseWorkActionInput, mn as parseWorkItem, o as mergeThreads, p as text$2, pn as parseWorkDetail, s as stableJson, u as object$1, un as parseWorkActivity, vn as parseWorkQuery, xn as parseWorkSyncResult, yn as parseWorkSnapshot, z as parseThreadSnapshot } from "./events-iHpLGr3k.js";
|
|
4
4
|
import { n as PICKER_MODULE_URL, t as pickerPageScript } from "./bridge-B_Blt55E.js";
|
|
5
5
|
import { createHash, randomUUID } from "node:crypto";
|
|
6
6
|
import { join, relative, sep } from "node:path";
|
|
@@ -2364,6 +2364,9 @@ function beadsWorkItem(issue, schema, ready) {
|
|
|
2364
2364
|
function taskCount(count, hidden) {
|
|
2365
2365
|
return count === null ? null : Math.max(0, count - hidden);
|
|
2366
2366
|
}
|
|
2367
|
+
let field = (value, key) => value && typeof value === "object" && !Array.isArray(value) ? value[key] : void 0;
|
|
2368
|
+
let deletedIds = field(field(field(issue.metadata ?? void 0, "budDiscussion"), "record"), "deleted");
|
|
2369
|
+
let deleted = Array.isArray(deletedIds) ? deletedIds.length : 0;
|
|
2367
2370
|
let values = {
|
|
2368
2371
|
...properties,
|
|
2369
2372
|
metadata: taskMetadata(issue.metadata)
|
|
@@ -2389,7 +2392,7 @@ function beadsWorkItem(issue, schema, ready) {
|
|
|
2389
2392
|
]) delete values[key];
|
|
2390
2393
|
let counts = {};
|
|
2391
2394
|
for (let [key, value] of [
|
|
2392
|
-
["discussion", issue.commentCount],
|
|
2395
|
+
["discussion", taskCount(issue.commentCount, deleted)],
|
|
2393
2396
|
["children", issue.epicTotalChildren],
|
|
2394
2397
|
["childrenDone", issue.epicClosedChildren],
|
|
2395
2398
|
["outgoing", taskCount(issue.dependencyCount, issue.dependencies.length - dependencies.length)],
|
|
@@ -2925,6 +2928,7 @@ function parseThreadRecord(value) {
|
|
|
2925
2928
|
"creationId",
|
|
2926
2929
|
"initial",
|
|
2927
2930
|
"bindings",
|
|
2931
|
+
"deleted",
|
|
2928
2932
|
"source",
|
|
2929
2933
|
"sourceId",
|
|
2930
2934
|
"createdAt",
|
|
@@ -2938,6 +2942,7 @@ function parseThreadRecord(value) {
|
|
|
2938
2942
|
let bindings = unique(unique(array(input.bindings, "bindings", binding, MAX_BEADS_THREAD_BYTES), (entry) => entry.id, "bindings.id"), (entry) => entry.nativeId, "bindings.nativeId");
|
|
2939
2943
|
if (input.source === void 0 !== (input.sourceId === void 0)) throw new WorkValidationError("thread.metadata.source");
|
|
2940
2944
|
if (input.source !== void 0 && (!text$1(input.source, "thread.metadata.source", 512).trim() || !text$1(input.sourceId, "thread.metadata.sourceId", 512).trim())) throw new WorkValidationError("thread.metadata.source");
|
|
2945
|
+
let deleted = input.deleted === void 0 ? void 0 : unique(array(input.deleted, "deleted", (id) => identifier(id, "deleted"), MAX_BEADS_THREAD_BYTES), (id) => id, "deleted");
|
|
2941
2946
|
return {
|
|
2942
2947
|
version: 1,
|
|
2943
2948
|
kind,
|
|
@@ -2945,6 +2950,7 @@ function parseThreadRecord(value) {
|
|
|
2945
2950
|
creationId: identifier(input.creationId, "thread.metadata.creationId"),
|
|
2946
2951
|
initial,
|
|
2947
2952
|
bindings,
|
|
2953
|
+
...deleted?.length ? { deleted } : {},
|
|
2948
2954
|
createdAt: timestamp(input.createdAt, "thread.metadata.createdAt"),
|
|
2949
2955
|
updatedAt: timestamp(input.updatedAt, "thread.metadata.updatedAt"),
|
|
2950
2956
|
...input.source === void 0 ? {} : {
|
|
@@ -2954,6 +2960,14 @@ function parseThreadRecord(value) {
|
|
|
2954
2960
|
};
|
|
2955
2961
|
}
|
|
2956
2962
|
/**
|
|
2963
|
+
* Whether a thread's first message, and with it the whole thread, was deleted.
|
|
2964
|
+
* @param record - The thread's Bud record.
|
|
2965
|
+
* @returns Whether the thread no longer shows.
|
|
2966
|
+
*/
|
|
2967
|
+
function threadDeleted(record) {
|
|
2968
|
+
return record.deleted?.includes(record.initial.id) ?? false;
|
|
2969
|
+
}
|
|
2970
|
+
/**
|
|
2957
2971
|
* Leaves unpromoted creations inspectable in Beads without listing them as durable threads.
|
|
2958
2972
|
* @param value - The native issue row.
|
|
2959
2973
|
* @returns A validated promoted row, or null for a pending creation.
|
|
@@ -3042,7 +3056,8 @@ function parseThreadComments(value, id) {
|
|
|
3042
3056
|
* Validates full persisted history independently of the browser's visible message limit.
|
|
3043
3057
|
* @param row - The native row and separately validated Bud metadata.
|
|
3044
3058
|
* @param comments - All native messages within the process output byte limit.
|
|
3045
|
-
* @returns Every
|
|
3059
|
+
* @returns Every message not deleted, with validated attribution and complete ancestry; replies
|
|
3060
|
+
* to a deleted message move up to its parent.
|
|
3046
3061
|
*/
|
|
3047
3062
|
function threadMessages(row, comments) {
|
|
3048
3063
|
let bindings = new Map(row.record.bindings.map((entry) => [entry.nativeId, entry]));
|
|
@@ -3072,6 +3087,8 @@ function threadMessages(row, comments) {
|
|
|
3072
3087
|
if (!initial || JSON.stringify(initial) !== JSON.stringify(row.record.initial)) throw new WorkValidationError("thread.messages.initial");
|
|
3073
3088
|
let parents = new Map(messages.map((message) => [message.id, message.parentId]));
|
|
3074
3089
|
if (parents.size !== messages.length) throw new WorkValidationError("thread.messages.id");
|
|
3090
|
+
let deleted = row.record.deleted ?? [];
|
|
3091
|
+
if (deleted.some((id) => !parents.has(id))) throw new WorkValidationError("thread.messages.deleted");
|
|
3075
3092
|
let complete = /* @__PURE__ */ new Set();
|
|
3076
3093
|
for (let message of messages) {
|
|
3077
3094
|
let path = /* @__PURE__ */ new Set();
|
|
@@ -3083,7 +3100,7 @@ function threadMessages(row, comments) {
|
|
|
3083
3100
|
}
|
|
3084
3101
|
for (let id of path) complete.add(id);
|
|
3085
3102
|
}
|
|
3086
|
-
return messages;
|
|
3103
|
+
return withoutMessages(messages, deleted);
|
|
3087
3104
|
}
|
|
3088
3105
|
/**
|
|
3089
3106
|
* Retains source order and the truthful attribution of native replies before a new append.
|
|
@@ -3117,6 +3134,8 @@ function threadView(row, comments, loaded) {
|
|
|
3117
3134
|
let { issue, record } = row;
|
|
3118
3135
|
let count = issue.commentCount;
|
|
3119
3136
|
if (count === null || count < 1 || comments && comments.length !== count) throw new WorkValidationError("thread.messageCount");
|
|
3137
|
+
let visible = count - (record.deleted?.length ?? 0);
|
|
3138
|
+
if (visible < 1) throw new WorkValidationError("thread.messageCount");
|
|
3120
3139
|
let all = comments ? loaded ?? threadMessages(row, comments) : [record.initial];
|
|
3121
3140
|
let messages = all.slice(0, 200);
|
|
3122
3141
|
let status = issue.status === "closed" ? "resolved" : issue.labels.includes("bud-status:needs_approval") ? "needs_approval" : issue.status;
|
|
@@ -3126,9 +3145,9 @@ function threadView(row, comments, loaded) {
|
|
|
3126
3145
|
anchor: record.anchor,
|
|
3127
3146
|
itemIds: linkedItems(row),
|
|
3128
3147
|
messages,
|
|
3129
|
-
messageCount:
|
|
3148
|
+
messageCount: visible,
|
|
3130
3149
|
messagesLoaded: comments !== void 0,
|
|
3131
|
-
messagesTruncated: comments !== void 0 &&
|
|
3150
|
+
messagesTruncated: comments !== void 0 && all.length > 200,
|
|
3132
3151
|
createdAt: record.createdAt,
|
|
3133
3152
|
updatedAt: [
|
|
3134
3153
|
record.updatedAt,
|
|
@@ -3239,6 +3258,10 @@ function readThread(session, value) {
|
|
|
3239
3258
|
reason: "uncertain",
|
|
3240
3259
|
message: "This discussion has not been promoted to durable storage. Inspect its creation in Beads before trying again."
|
|
3241
3260
|
});
|
|
3261
|
+
if (threadDeleted(row.record)) return yield* new WorkError({
|
|
3262
|
+
reason: "not-found",
|
|
3263
|
+
message: "This discussion was deleted."
|
|
3264
|
+
});
|
|
3242
3265
|
let comments = yield* session.comments(id, (value) => parseThreadComments(value, id));
|
|
3243
3266
|
if (row.issue.commentCount !== null && comments.length !== row.issue.commentCount) return yield* new WorkError({
|
|
3244
3267
|
reason: "conflict",
|
|
@@ -3368,6 +3391,20 @@ function newMessage(body, author, parentId = null) {
|
|
|
3368
3391
|
});
|
|
3369
3392
|
}
|
|
3370
3393
|
/**
|
|
3394
|
+
* Checks that the requesting author may delete a message, against full storage.
|
|
3395
|
+
* @param messages - The current complete stored messages, first message first.
|
|
3396
|
+
* @param messageId - The message to delete.
|
|
3397
|
+
* @param author - The trusted server author.
|
|
3398
|
+
* @returns A refusal unless it is the author's own message, and a first message stands alone.
|
|
3399
|
+
*/
|
|
3400
|
+
function validateDeletion(messages, messageId, author) {
|
|
3401
|
+
let refusal = messageDeletionRefusal(messages, messageId, author.id);
|
|
3402
|
+
return refusal ? fail(new WorkError({
|
|
3403
|
+
reason: refusal === "missing" ? "not-found" : "refused",
|
|
3404
|
+
message: messageDeletionRefusals[refusal]
|
|
3405
|
+
})) : void_;
|
|
3406
|
+
}
|
|
3407
|
+
/**
|
|
3371
3408
|
* Checks reply ancestry against full storage, independent of the UI's display bound.
|
|
3372
3409
|
* @param messages - The current complete stored messages.
|
|
3373
3410
|
* @param parentId - The requested reply parent.
|
|
@@ -3671,6 +3708,37 @@ function replyItemDiscussion(session, id, input, author) {
|
|
|
3671
3708
|
});
|
|
3672
3709
|
}
|
|
3673
3710
|
/**
|
|
3711
|
+
* Deletes one of the author's replies from a native task discussion; the task's first comment
|
|
3712
|
+
* stays. The comment stays in Beads, and the discussion record hides it.
|
|
3713
|
+
* @param session - The shared native writer.
|
|
3714
|
+
* @param id - The work-item ID, without its discussion namespace.
|
|
3715
|
+
* @param input - The revision-checked deletion.
|
|
3716
|
+
* @param author - The trusted server author.
|
|
3717
|
+
* @returns The changed, validated native discussion.
|
|
3718
|
+
*/
|
|
3719
|
+
function deleteItemDiscussionMessage(session, id, input, author) {
|
|
3720
|
+
return gen(function* () {
|
|
3721
|
+
let current = yield* required(session, id);
|
|
3722
|
+
yield* expectedThread(current.thread, input.expectedRevision);
|
|
3723
|
+
if (input.messageId === current.data.record.initial.id) return yield* new WorkError({
|
|
3724
|
+
reason: "refused",
|
|
3725
|
+
message: "A task's first comment stays; only replies can be deleted."
|
|
3726
|
+
});
|
|
3727
|
+
yield* validateDeletion(current.messages, input.messageId, author);
|
|
3728
|
+
let next = {
|
|
3729
|
+
...current.data,
|
|
3730
|
+
record: {
|
|
3731
|
+
...current.data.record,
|
|
3732
|
+
deleted: [...current.data.record.deleted ?? [], input.messageId],
|
|
3733
|
+
updatedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
3734
|
+
}
|
|
3735
|
+
};
|
|
3736
|
+
let json = yield* threadInput(() => payload(current.issue, next));
|
|
3737
|
+
yield* threadPayload(json, session.limits.metadataBytes);
|
|
3738
|
+
return yield* save(session, id, json, () => map(required(session, id), (result) => result.thread));
|
|
3739
|
+
});
|
|
3740
|
+
}
|
|
3741
|
+
/**
|
|
3674
3742
|
* Saves discussion-only status or linked items without mutating the work item's lifecycle.
|
|
3675
3743
|
* @param session - The shared native writer.
|
|
3676
3744
|
* @param id - The owning work item.
|
|
@@ -3847,7 +3915,7 @@ var capabilities$1 = {
|
|
|
3847
3915
|
link: true,
|
|
3848
3916
|
sync: true,
|
|
3849
3917
|
edit: false,
|
|
3850
|
-
delete:
|
|
3918
|
+
delete: true
|
|
3851
3919
|
};
|
|
3852
3920
|
var unavailableCapabilities = {
|
|
3853
3921
|
create: false,
|
|
@@ -3867,7 +3935,7 @@ function listThreads(session, filter) {
|
|
|
3867
3935
|
}, parseThreadRows);
|
|
3868
3936
|
let items = yield* listItemDiscussions(session, filter);
|
|
3869
3937
|
return yield* threadResult(() => {
|
|
3870
|
-
let threads = [...items.threads, ...rows.slice(0, MAX_THREADS).flatMap((row) => row ? [threadView(row)] : []).filter((thread) => matchesThread(thread, filter))];
|
|
3938
|
+
let threads = [...items.threads, ...rows.slice(0, MAX_THREADS).flatMap((row) => row && !threadDeleted(row.record) ? [threadView(row)] : []).filter((thread) => matchesThread(thread, filter))];
|
|
3871
3939
|
return parseThreadSnapshot({
|
|
3872
3940
|
connection: {
|
|
3873
3941
|
state: "ready",
|
|
@@ -4077,6 +4145,34 @@ var beadsStoreThreadAdapterLayer = effect(ThreadAdapter, gen(function* () {
|
|
|
4077
4145
|
}));
|
|
4078
4146
|
}));
|
|
4079
4147
|
}).pipe(mapError(threadFailure)),
|
|
4148
|
+
deleteMessage: (root, id, value, author) => gen(function* () {
|
|
4149
|
+
let input = yield* threadInput(() => parseThreadDeleteInput(value));
|
|
4150
|
+
let trusted = yield* threadInput(() => parseMessageAuthor(author));
|
|
4151
|
+
return yield* store.change(root, (session) => gen(function* () {
|
|
4152
|
+
let native = yield* threadInput(() => nativeDiscussionId(id));
|
|
4153
|
+
if (native) return yield* deleteItemDiscussionMessage(session, native, input, trusted);
|
|
4154
|
+
let { thread, row, messages } = yield* readThread(session, id);
|
|
4155
|
+
yield* expectedThread(thread, input.expectedRevision);
|
|
4156
|
+
yield* validateDeletion(messages, input.messageId, trusted);
|
|
4157
|
+
let record = yield* threadInput(() => parseThreadRecord({
|
|
4158
|
+
...row.record,
|
|
4159
|
+
deleted: [...row.record.deleted ?? [], input.messageId],
|
|
4160
|
+
updatedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
4161
|
+
}));
|
|
4162
|
+
let nextMetadata = {
|
|
4163
|
+
...row.issue.metadata,
|
|
4164
|
+
bud: record
|
|
4165
|
+
};
|
|
4166
|
+
yield* threadPayload(JSON.stringify(nextMetadata), session.limits.metadataBytes);
|
|
4167
|
+
return yield* threadChange(session, (writer) => gen(function* () {
|
|
4168
|
+
yield* saveRecord(writer, row, record);
|
|
4169
|
+
if (!threadDeleted(record)) return (yield* readThread(session, id)).thread;
|
|
4170
|
+
for (let item of thread.itemIds) yield* writer.removeDependency(id, item);
|
|
4171
|
+
if (thread.status !== "resolved") yield* writer.close(id, "Deleted in Bud");
|
|
4172
|
+
return null;
|
|
4173
|
+
}));
|
|
4174
|
+
}));
|
|
4175
|
+
}).pipe(mapError(threadFailure)),
|
|
4080
4176
|
link: (root, id, ids, revision) => link(root, id, ids, revision, false),
|
|
4081
4177
|
unlink: (root, id, ids, revision) => link(root, id, ids, revision, true),
|
|
4082
4178
|
sync: (root, direction = "both") => gen(function* () {
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { Bt as Button, En as t, Ft as CommentThreadDetail, It as CommentThreadItem, K as CommentThreadHeading, Lt as CommentComposer, On as Text, S as ThreadTaskLinks, _t as taskHref, b as writeOptimistically, bn as toast, dt as conversationLabel, gt as selectedTask, h as storedWorkspace, ht as readConversationLocation, l as projectStore, vt as taskRole, w as ItemDiscussion, x as writeRows, y as plainRow, z as TaskWorkspace } from "./comment-data-
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import { t as
|
|
6
|
-
import { n as ProjectTaskPicker, t as ProjectThreadLinks } from "./project-thread-links-
|
|
1
|
+
import { C as predictWorkCreate, S as predictWorkAction, _ as taskRoutes, cn as parseSectionData, gn as parseWorkMutationResult, i as routes, pn as parseWorkDetail, w as predictWorkUpdate, xn as parseWorkSyncResult } from "./events-iHpLGr3k.js";
|
|
2
|
+
import { Bt as Button, En as t, Ft as CommentThreadDetail, It as CommentThreadItem, K as CommentThreadHeading, Lt as CommentComposer, On as Text, S as ThreadTaskLinks, _t as taskHref, b as writeOptimistically, bn as toast, dt as conversationLabel, gt as selectedTask, h as storedWorkspace, ht as readConversationLocation, l as projectStore, vt as taskRole, w as ItemDiscussion, x as writeRows, y as plainRow, z as TaskWorkspace } from "./comment-data-NLeHG89b.js";
|
|
3
|
+
import { n as requestTasks, t as TaskRequestError } from "./tasks-request-D2NBjCTl.js";
|
|
4
|
+
import { t as projectWork } from "./project-work-CSZlCwH-.js";
|
|
5
|
+
import { i as loadItemComments, n as createProjectComments, t as defineScreen } from "./screen-B1zH_1O3.js";
|
|
6
|
+
import { n as ProjectTaskPicker, t as ProjectThreadLinks } from "./project-thread-links-lLS_rq7c.js";
|
|
7
7
|
import { on, ref } from "remix/component";
|
|
8
8
|
import { Fragment, jsx, jsxs } from "remix/component/jsx-runtime";
|
|
9
9
|
//#region app/client/task-discussion.tsx
|
|
@@ -196,7 +196,14 @@ function TaskDiscussion(handle) {
|
|
|
196
196
|
id: thread.id,
|
|
197
197
|
body,
|
|
198
198
|
parentId
|
|
199
|
-
}) : void 0
|
|
199
|
+
}) : void 0,
|
|
200
|
+
viewerId: comments.viewer?.id,
|
|
201
|
+
onDelete: capabilities.delete ? async (messageId) => {
|
|
202
|
+
let whole = thread.messages[0]?.id === messageId;
|
|
203
|
+
await comments.remove(thread.id, messageId);
|
|
204
|
+
if (whole && selected === thread.id) selected = void 0;
|
|
205
|
+
handle.update();
|
|
206
|
+
} : void 0
|
|
200
207
|
})
|
|
201
208
|
}, thread.id)) : /* @__PURE__ */ jsx(Text, {
|
|
202
209
|
variant: "ui-caption",
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { En as t } from "./comment-data-
|
|
1
|
+
import { hn as parseWorkItemRef, i as routes, vn as parseWorkQuery } from "./events-iHpLGr3k.js";
|
|
2
|
+
import { En as t } from "./comment-data-NLeHG89b.js";
|
|
3
3
|
import { createMultiMatcher } from "remix/route-pattern/match";
|
|
4
4
|
//#region app/client/tasks-request.ts
|
|
5
5
|
var reads = createMultiMatcher();
|
package/dist/server/migration.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Kt as mapError, Lt as flatMap, On as try_, Ut as gen, _ as resolveStorage, f as Project, p as createProjectContext, sn as runPromise, u as Git } from "./assets/branch-previews-ClkoJ0lM.js";
|
|
2
|
-
import { H as make, I as WorkError, O as AdapterRegistry } from "./assets/server-
|
|
3
|
-
import { j as
|
|
4
|
-
import { n as storageLayer, r as readGitThreadImports } from "./assets/services-
|
|
2
|
+
import { H as make, I as WorkError, O as AdapterRegistry } from "./assets/server-DxK-UB_Z.js";
|
|
3
|
+
import { j as parseThread, z as parseThreadSnapshot } from "./assets/events-iHpLGr3k.js";
|
|
4
|
+
import { n as storageLayer, r as readGitThreadImports } from "./assets/services-BRrgXYlT.js";
|
|
5
5
|
//#region app/server/comment-migration.ts
|
|
6
6
|
function identity(metadata) {
|
|
7
7
|
if (!metadata || typeof metadata !== "object" || Array.isArray(metadata)) return null;
|
package/dist/server/runtime.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { An as uninterruptible, Dn as tryPromise, Kt as mapError, Rn as effect, Ut as gen, Zt as promise, p as createProjectContext, qn as provideMerge, sn as runPromise, sr as Service, vt as acquireRelease, x as readText } from "./assets/branch-previews-ClkoJ0lM.js";
|
|
2
|
-
import { B as sharedModules, H as make } from "./assets/server-
|
|
3
|
-
import { n as listen, r as createApp, t as ServerError } from "./assets/listener-
|
|
4
|
-
import { t as applicationLayer } from "./assets/services-
|
|
2
|
+
import { B as sharedModules, H as make } from "./assets/server-DxK-UB_Z.js";
|
|
3
|
+
import { n as listen, r as createApp, t as ServerError } from "./assets/listener-BAYn9Q-u.js";
|
|
4
|
+
import { t as applicationLayer } from "./assets/services-BRrgXYlT.js";
|
|
5
5
|
import { fileURLToPath } from "node:url";
|
|
6
6
|
//#region app/server/runtime.ts
|
|
7
7
|
var BudListener = class extends Service()("bud/Listener") {};
|