@bud.sh/app 0.4.0 → 0.5.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/dist/client/assets/bud/design.js +1 -1
- package/dist/client/assets/{canvas-C8hyPWoT.js → canvas-Cu6R6xxT.js} +1 -1
- package/dist/client/assets/difference-worker-jfTSn-Tw.js +8 -0
- package/dist/client/assets/{edit-B050x0rV.js → edit-DUotSxjS.js} +12 -12
- package/dist/client/assets/files-js6ElfkU.js +1 -0
- package/dist/client/assets/i18n-DxqFr2mi.js +1 -0
- package/dist/client/assets/index-CFFxP0gS.css +2 -0
- package/dist/client/assets/{index-Dpxjiok1.js → index-ChANGtl-.js} +2 -2
- package/dist/client/assets/lru-DzKYIXMA.js +1 -0
- package/dist/client/assets/pages-6_lhiQmz.js +1 -0
- package/dist/client/assets/{project-branches-DzXdaT9L.js → project-branches-DO897zM6.js} +1 -1
- package/dist/client/assets/project-comments-DFFKVpia.js +1 -0
- package/dist/client/assets/project-thread-links-NLFWQRD2.js +1 -0
- package/dist/client/assets/{project-threads-CHGG-6fo.js → project-threads-Lay351p4.js} +105 -105
- package/dist/client/assets/{project-work-L5fYMSOu.js → project-work-du0Y-L5Y.js} +1 -1
- package/dist/client/assets/rolldown-runtime-XKyaHtl9.js +1 -0
- package/dist/client/assets/task-design-Avb2RO4w.js +23 -0
- package/dist/client/assets/tasks-CA-E8bbK.js +1 -0
- package/dist/client/assets/{tasks-request-DGigNdyK.js → tasks-request-C55IeuiP.js} +1 -1
- package/dist/client/assets/workspace-Cw5HvX5d.js +2 -0
- package/dist/client/index.html +3 -3
- package/dist/hosted/assets/{canvas-MWtOwaWm.js → canvas-V36732ER.js} +6 -4
- package/dist/hosted/assets/{comment-data-DsgJWq4n.js → comment-data-CF2ZV_3k.js} +4162 -3659
- package/dist/hosted/assets/{files-Wvo11G2A.js → files-DjSCjfU7.js} +5 -3
- package/dist/hosted/assets/{pages-BAmRFVtU.js → pages-BzjzeuPu.js} +3 -3
- package/dist/hosted/assets/{project-branches-BNloVosX.js → project-branches-BT97J9i7.js} +1 -1
- package/dist/hosted/assets/{project-thread-links-BmY8HQXt.js → project-thread-links-BRLgByEe.js} +2 -2
- package/dist/hosted/assets/{screen-QmqmI2Aq.js → screen-CKp2C7kx.js} +68 -137
- package/dist/hosted/assets/{tasks-C8iWPrWg.js → tasks-Dj7AyBJB.js} +12 -5
- package/dist/hosted/assets/{tasks-request-C89fN1dK.js → tasks-request-DZob623r.js} +1 -1
- package/dist/hosted/hosted.js +174 -18
- package/dist/node/assets/{src-BdvZ2mYc.js → src-CerrKjID.js} +57 -1
- package/dist/node/design.js +969 -809
- package/dist/node/server.js +25 -3
- package/dist/node-host/assets/{canvas-D_F8SIlm.js → canvas-TRUfxfL5.js} +6 -4
- package/dist/node-host/assets/{comment-data-q_8INiZz.js → comment-data-DyIZNpfG.js} +4143 -3640
- package/dist/node-host/assets/{files-xazOrNCX.js → files-Dh2TiQZq.js} +5 -3
- package/dist/node-host/assets/{pages-D6VkmdfQ.js → pages-BxpjbYhs.js} +3 -3
- package/dist/node-host/assets/{project-branches-C26hwmo3.js → project-branches-B7HUGiVK.js} +1 -1
- package/dist/node-host/assets/{project-thread-links-BOzjws5W.js → project-thread-links-CauJF0Cz.js} +2 -2
- package/dist/node-host/assets/{screen-Dog-YByu.js → screen-CZXWJEds.js} +68 -137
- package/dist/node-host/assets/{tasks-A1_bpb3_.js → tasks-Bs1IOpeU.js} +12 -5
- package/dist/node-host/assets/{tasks-request-Bie1PpQP.js → tasks-request-ZWmbc8fE.js} +1 -1
- package/dist/node-host/node-host.js +174 -18
- package/dist/server/assets/{canvas-Dn4RYoU2.js → canvas-Dc1mYCwQ.js} +7 -5
- package/dist/server/assets/{comment-data-B0OLHBGp.js → comment-data-CsjukwAW.js} +3911 -3619
- package/dist/server/assets/{events-6z5v7Uca.js → events-iHpLGr3k.js} +213 -2
- package/dist/server/assets/{files-C5Vilfe4.js → files-E9mSFeoc.js} +6 -4
- package/dist/server/assets/{listener-o1STuLju.js → listener-DN5TyOjJ.js} +45 -11
- package/dist/server/assets/{pages-BNa0MHEc.js → pages-BBBXyJWV.js} +4 -4
- package/dist/server/assets/{project-branches-GtQYyOH5.js → project-branches-B0YIK6Ur.js} +2 -2
- package/dist/server/assets/{project-thread-links-Nfz9NIny.js → project-thread-links-CBOpf6zk.js} +3 -3
- package/dist/server/assets/{project-work-Cy_BpHwR.js → project-work-qSKFO5yj.js} +3 -3
- package/dist/server/assets/{screen-BtcJmZwj.js → screen-BIQA2mr4.js} +69 -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-B82tHwyQ.js → tasks-CiXodsLN.js} +14 -7
- package/dist/server/assets/{tasks-request-BtJBlkxV.js → tasks-request-DhwCzpRi.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-BfF4_N3e.js +0 -8
- package/dist/client/assets/files-D_Tm7gCK.js +0 -1
- package/dist/client/assets/i18n-BtfXum8P.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-B-_CKvDS.js +0 -1
- package/dist/client/assets/project-comments-CQkB2jbE.js +0 -1
- package/dist/client/assets/project-thread-links-BN7zL0AX.js +0 -1
- package/dist/client/assets/task-design-DYqcqq1b.js +0 -23
- package/dist/client/assets/tasks-A2FKo3_h.js +0 -1
- package/dist/client/assets/workspace-CvWmU2RK.js +0 -2
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { $r as
|
|
2
|
-
import { n as requestTasks } from "./assets/tasks-request-
|
|
1
|
+
import { $r as valueByRole, $t as Button, An as parseThread, Bn as parseThreadStatusInput, Br as parseWorkActivity, Ci as parsePreviewViewport, Ct as legacyConversationHref, Dn as parseWorkChange, Dt as taskHref, Et as selectedTask, Fn as parseThreadInput, Fr as MAX_CANVAS_Y, G as mergeThreads, Gr as parseWorkItemRef, Gt as fileRoutes, Hr as parseWorkCreate, In as parseThreadLinkInput, Ir as parseElementAnchor, J as conversationId, Jr as parseWorkSnapshot, K as stableJson, Kr as parseWorkMutationResult, Kt as pageRoutes, Ln as parseThreadReplyInput, Lr as parseWorkWorkspace, Mn as parseThreadDeleteInput, Nn as parseThreadFilter, On as MAX_THREADS, Pn as parseThreadId, Q as text$6, Qr as parseWorkValue, Rn as parseThreadSnapshot, Rr as parseSectionData, S as writeRows, Si as parsePreviewPins, Tt as readConversationLocation, Ur as parseWorkDetail, V as parseTaskDesign, Vr as parseWorkConnection, W as CommentMergeError, Wr as parseWorkItem, X as parseCommentThread, Xr as parseWorkSyncResult, Y as object$2, Yr as parseWorkSync, Z as revision$2, Zr as parseWorkUpdate, Zt as Loader, _ as requestComments, ai as fieldByRole, an as LiveStatus, at as FieldCardHeader, b as plainRow, bi as parsePreviewHash, ci as WorkValidationError, ct as initialShellTabs, d as saveWorkspace, di as parseWork, dn as hasMessage, dt as readTabsCookie, ei as messageDeletionRefusal, fi as record$2, fn as isLocale, ft as stepShellTab, gi as PREVIEW_TILE_HEIGHT, gn as Text, gt as visitShellTab, hi as PREVIEW_THUMBNAIL_WIDTHS, hn as useLocaleSource, ht as tabsCookieValue, ii as withoutMessages, it as FieldCardContent, jn as parseThreadCapabilities, jt as legacyFileHref, kn as parseAnchor, l as projectStore, li as identifier$3, ln as readPreference, lt as openShellTab, mi as MAX_PREVIEW_HEIGHT, mn as t, mt as tabsCookieName, n as unavailableComments, ni as parseMessage, nn as ShellTabBar, oi as parseWorkSchema, ot as activeTab, pi as strict$2, pn as locale, pt as tabHref, q as parseCommentInput$1, qr as parseWorkQuery, qt as taskRoutes, r as followThreads, ri as parseMessageAuthor, rt as FieldCard, si as statusCategory, sn as AppShell, st as closeShellTab, t as commentsUnavailable, ti as messageDeletionRefusals, ui as nonempty$1, un as writePreference, ut as parseShellTabs, v as projectLive, vi as parsePreviewBranch, vn as RESYNC, xi as parsePreviewId, y as routes, yi as parsePreviewCapture, yn as parseLiveId, yt as conversationDestination, zn as parseThreadStatus, zr as parseWorkActionInput } from "./assets/comment-data-DyIZNpfG.js";
|
|
2
|
+
import { n as requestTasks } from "./assets/tasks-request-ZWmbc8fE.js";
|
|
3
3
|
import { access, mkdir, mkdtemp, readFile, readdir, realpath, rename, rm, stat, symlink, writeFile } from "node:fs/promises";
|
|
4
4
|
import * as Path from "node:path";
|
|
5
5
|
import { dirname, extname, isAbsolute, join, relative, resolve, sep } from "node:path";
|
|
@@ -24185,6 +24185,9 @@ function beadsWorkItem(issue, schema, ready) {
|
|
|
24185
24185
|
function taskCount(count, hidden) {
|
|
24186
24186
|
return count === null ? null : Math.max(0, count - hidden);
|
|
24187
24187
|
}
|
|
24188
|
+
let field = (value, key) => value && typeof value === "object" && !Array.isArray(value) ? value[key] : void 0;
|
|
24189
|
+
let deletedIds = field(field(field(issue.metadata ?? void 0, "budDiscussion"), "record"), "deleted");
|
|
24190
|
+
let deleted = Array.isArray(deletedIds) ? deletedIds.length : 0;
|
|
24188
24191
|
let values = {
|
|
24189
24192
|
...properties,
|
|
24190
24193
|
metadata: taskMetadata(issue.metadata)
|
|
@@ -24210,7 +24213,7 @@ function beadsWorkItem(issue, schema, ready) {
|
|
|
24210
24213
|
]) delete values[key];
|
|
24211
24214
|
let counts = {};
|
|
24212
24215
|
for (let [key, value] of [
|
|
24213
|
-
["discussion", issue.commentCount],
|
|
24216
|
+
["discussion", taskCount(issue.commentCount, deleted)],
|
|
24214
24217
|
["children", issue.epicTotalChildren],
|
|
24215
24218
|
["childrenDone", issue.epicClosedChildren],
|
|
24216
24219
|
["outgoing", taskCount(issue.dependencyCount, issue.dependencies.length - dependencies.length)],
|
|
@@ -24510,10 +24513,10 @@ var MemoryStore = class {
|
|
|
24510
24513
|
reply: this.schema.capabilities.threads,
|
|
24511
24514
|
status: this.schema.capabilities.threads,
|
|
24512
24515
|
link: this.schema.capabilities.threads,
|
|
24516
|
+
delete: this.schema.capabilities.threads,
|
|
24513
24517
|
...options.threadCapabilities,
|
|
24514
24518
|
sync: false,
|
|
24515
|
-
edit: false
|
|
24516
|
-
delete: false
|
|
24519
|
+
edit: false
|
|
24517
24520
|
});
|
|
24518
24521
|
if (this.schema.capabilities.sync) refused("Memory storage has no remote synchronization.");
|
|
24519
24522
|
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.");
|
|
@@ -24826,6 +24829,28 @@ function memoryThreads(store) {
|
|
|
24826
24829
|
status: request.status
|
|
24827
24830
|
}, at);
|
|
24828
24831
|
}),
|
|
24832
|
+
deleteMessage: (root, id, value, author) => store.run(root, true, (data, at) => {
|
|
24833
|
+
if (!store.capabilities.delete) refused("This adapter does not allow deleting messages.");
|
|
24834
|
+
let request = input$4(() => parseThreadDeleteInput(value));
|
|
24835
|
+
let trusted = input$4(() => parseMessageAuthor(author));
|
|
24836
|
+
let thread = store.thread(data, id);
|
|
24837
|
+
expected(thread, request.expectedRevision);
|
|
24838
|
+
let refusal = messageDeletionRefusal(thread.messages, request.messageId, trusted.id);
|
|
24839
|
+
if (refusal === "missing") throw new WorkError({
|
|
24840
|
+
reason: "not-found",
|
|
24841
|
+
message: messageDeletionRefusals.missing
|
|
24842
|
+
});
|
|
24843
|
+
if (refusal) refused(messageDeletionRefusals[refusal]);
|
|
24844
|
+
if (thread.messages[0].id === request.messageId) {
|
|
24845
|
+
data.threads.delete(id);
|
|
24846
|
+
store.touchThreads(data, thread.itemIds, at);
|
|
24847
|
+
return null;
|
|
24848
|
+
}
|
|
24849
|
+
return save(data, {
|
|
24850
|
+
...thread,
|
|
24851
|
+
messages: withoutMessages(thread.messages, [request.messageId])
|
|
24852
|
+
}, at);
|
|
24853
|
+
}),
|
|
24829
24854
|
link: (root, id, ids, revision) => link(root, id, ids, revision, false),
|
|
24830
24855
|
unlink: (root, id, ids, revision) => link(root, id, ids, revision, true)
|
|
24831
24856
|
};
|
|
@@ -25698,6 +25723,7 @@ function parseThreadRecord(value) {
|
|
|
25698
25723
|
"creationId",
|
|
25699
25724
|
"initial",
|
|
25700
25725
|
"bindings",
|
|
25726
|
+
"deleted",
|
|
25701
25727
|
"source",
|
|
25702
25728
|
"sourceId",
|
|
25703
25729
|
"createdAt",
|
|
@@ -25711,6 +25737,7 @@ function parseThreadRecord(value) {
|
|
|
25711
25737
|
let bindings = unique(unique(array$1(input.bindings, "bindings", binding, MAX_BEADS_THREAD_BYTES), (entry) => entry.id, "bindings.id"), (entry) => entry.nativeId, "bindings.nativeId");
|
|
25712
25738
|
if (input.source === void 0 !== (input.sourceId === void 0)) throw new WorkValidationError("thread.metadata.source");
|
|
25713
25739
|
if (input.source !== void 0 && (!text$3(input.source, "thread.metadata.source", 512).trim() || !text$3(input.sourceId, "thread.metadata.sourceId", 512).trim())) throw new WorkValidationError("thread.metadata.source");
|
|
25740
|
+
let deleted = input.deleted === void 0 ? void 0 : unique(array$1(input.deleted, "deleted", (id) => identifier$1(id, "deleted"), MAX_BEADS_THREAD_BYTES), (id) => id, "deleted");
|
|
25714
25741
|
return {
|
|
25715
25742
|
version: 1,
|
|
25716
25743
|
kind,
|
|
@@ -25718,6 +25745,7 @@ function parseThreadRecord(value) {
|
|
|
25718
25745
|
creationId: identifier$1(input.creationId, "thread.metadata.creationId"),
|
|
25719
25746
|
initial,
|
|
25720
25747
|
bindings,
|
|
25748
|
+
...deleted?.length ? { deleted } : {},
|
|
25721
25749
|
createdAt: timestamp(input.createdAt, "thread.metadata.createdAt"),
|
|
25722
25750
|
updatedAt: timestamp(input.updatedAt, "thread.metadata.updatedAt"),
|
|
25723
25751
|
...input.source === void 0 ? {} : {
|
|
@@ -25727,6 +25755,14 @@ function parseThreadRecord(value) {
|
|
|
25727
25755
|
};
|
|
25728
25756
|
}
|
|
25729
25757
|
/**
|
|
25758
|
+
* Whether a thread's first message, and with it the whole thread, was deleted.
|
|
25759
|
+
* @param record - The thread's Bud record.
|
|
25760
|
+
* @returns Whether the thread no longer shows.
|
|
25761
|
+
*/
|
|
25762
|
+
function threadDeleted(record) {
|
|
25763
|
+
return record.deleted?.includes(record.initial.id) ?? false;
|
|
25764
|
+
}
|
|
25765
|
+
/**
|
|
25730
25766
|
* Leaves unpromoted creations inspectable in Beads without listing them as durable threads.
|
|
25731
25767
|
* @param value - The native issue row.
|
|
25732
25768
|
* @returns A validated promoted row, or null for a pending creation.
|
|
@@ -25815,7 +25851,8 @@ function parseThreadComments(value, id) {
|
|
|
25815
25851
|
* Validates full persisted history independently of the browser's visible message limit.
|
|
25816
25852
|
* @param row - The native row and separately validated Bud metadata.
|
|
25817
25853
|
* @param comments - All native messages within the process output byte limit.
|
|
25818
|
-
* @returns Every
|
|
25854
|
+
* @returns Every message not deleted, with validated attribution and complete ancestry; replies
|
|
25855
|
+
* to a deleted message move up to its parent.
|
|
25819
25856
|
*/
|
|
25820
25857
|
function threadMessages(row, comments) {
|
|
25821
25858
|
let bindings = new Map(row.record.bindings.map((entry) => [entry.nativeId, entry]));
|
|
@@ -25845,6 +25882,8 @@ function threadMessages(row, comments) {
|
|
|
25845
25882
|
if (!initial || JSON.stringify(initial) !== JSON.stringify(row.record.initial)) throw new WorkValidationError("thread.messages.initial");
|
|
25846
25883
|
let parents = new Map(messages.map((message) => [message.id, message.parentId]));
|
|
25847
25884
|
if (parents.size !== messages.length) throw new WorkValidationError("thread.messages.id");
|
|
25885
|
+
let deleted = row.record.deleted ?? [];
|
|
25886
|
+
if (deleted.some((id) => !parents.has(id))) throw new WorkValidationError("thread.messages.deleted");
|
|
25848
25887
|
let complete = /* @__PURE__ */ new Set();
|
|
25849
25888
|
for (let message of messages) {
|
|
25850
25889
|
let path = /* @__PURE__ */ new Set();
|
|
@@ -25856,7 +25895,7 @@ function threadMessages(row, comments) {
|
|
|
25856
25895
|
}
|
|
25857
25896
|
for (let id of path) complete.add(id);
|
|
25858
25897
|
}
|
|
25859
|
-
return messages;
|
|
25898
|
+
return withoutMessages(messages, deleted);
|
|
25860
25899
|
}
|
|
25861
25900
|
/**
|
|
25862
25901
|
* Retains source order and the truthful attribution of native replies before a new append.
|
|
@@ -25890,6 +25929,8 @@ function threadView(row, comments, loaded) {
|
|
|
25890
25929
|
let { issue, record } = row;
|
|
25891
25930
|
let count = issue.commentCount;
|
|
25892
25931
|
if (count === null || count < 1 || comments && comments.length !== count) throw new WorkValidationError("thread.messageCount");
|
|
25932
|
+
let visible = count - (record.deleted?.length ?? 0);
|
|
25933
|
+
if (visible < 1) throw new WorkValidationError("thread.messageCount");
|
|
25893
25934
|
let all = comments ? loaded ?? threadMessages(row, comments) : [record.initial];
|
|
25894
25935
|
let messages = all.slice(0, 200);
|
|
25895
25936
|
let status = issue.status === "closed" ? "resolved" : issue.labels.includes("bud-status:needs_approval") ? "needs_approval" : issue.status;
|
|
@@ -25899,9 +25940,9 @@ function threadView(row, comments, loaded) {
|
|
|
25899
25940
|
anchor: record.anchor,
|
|
25900
25941
|
itemIds: linkedItems(row),
|
|
25901
25942
|
messages,
|
|
25902
|
-
messageCount:
|
|
25943
|
+
messageCount: visible,
|
|
25903
25944
|
messagesLoaded: comments !== void 0,
|
|
25904
|
-
messagesTruncated: comments !== void 0 &&
|
|
25945
|
+
messagesTruncated: comments !== void 0 && all.length > 200,
|
|
25905
25946
|
createdAt: record.createdAt,
|
|
25906
25947
|
updatedAt: [
|
|
25907
25948
|
record.updatedAt,
|
|
@@ -26012,6 +26053,10 @@ function readThread(session, value) {
|
|
|
26012
26053
|
reason: "uncertain",
|
|
26013
26054
|
message: "This discussion has not been promoted to durable storage. Inspect its creation in Beads before trying again."
|
|
26014
26055
|
});
|
|
26056
|
+
if (threadDeleted(row.record)) return yield* new WorkError({
|
|
26057
|
+
reason: "not-found",
|
|
26058
|
+
message: "This discussion was deleted."
|
|
26059
|
+
});
|
|
26015
26060
|
let comments = yield* session.comments(id, (value) => parseThreadComments(value, id));
|
|
26016
26061
|
if (row.issue.commentCount !== null && comments.length !== row.issue.commentCount) return yield* new WorkError({
|
|
26017
26062
|
reason: "conflict",
|
|
@@ -26141,6 +26186,20 @@ function newMessage(body, author, parentId = null) {
|
|
|
26141
26186
|
});
|
|
26142
26187
|
}
|
|
26143
26188
|
/**
|
|
26189
|
+
* Checks that the requesting author may delete a message, against full storage.
|
|
26190
|
+
* @param messages - The current complete stored messages, first message first.
|
|
26191
|
+
* @param messageId - The message to delete.
|
|
26192
|
+
* @param author - The trusted server author.
|
|
26193
|
+
* @returns A refusal unless it is the author's own message, and a first message stands alone.
|
|
26194
|
+
*/
|
|
26195
|
+
function validateDeletion(messages, messageId, author) {
|
|
26196
|
+
let refusal = messageDeletionRefusal(messages, messageId, author.id);
|
|
26197
|
+
return refusal ? fail$6(new WorkError({
|
|
26198
|
+
reason: refusal === "missing" ? "not-found" : "refused",
|
|
26199
|
+
message: messageDeletionRefusals[refusal]
|
|
26200
|
+
})) : void_;
|
|
26201
|
+
}
|
|
26202
|
+
/**
|
|
26144
26203
|
* Checks reply ancestry against full storage, independent of the UI's display bound.
|
|
26145
26204
|
* @param messages - The current complete stored messages.
|
|
26146
26205
|
* @param parentId - The requested reply parent.
|
|
@@ -26444,6 +26503,37 @@ function replyItemDiscussion(session, id, input, author) {
|
|
|
26444
26503
|
});
|
|
26445
26504
|
}
|
|
26446
26505
|
/**
|
|
26506
|
+
* Deletes one of the author's replies from a native task discussion; the task's first comment
|
|
26507
|
+
* stays. The comment stays in Beads, and the discussion record hides it.
|
|
26508
|
+
* @param session - The shared native writer.
|
|
26509
|
+
* @param id - The work-item ID, without its discussion namespace.
|
|
26510
|
+
* @param input - The revision-checked deletion.
|
|
26511
|
+
* @param author - The trusted server author.
|
|
26512
|
+
* @returns The changed, validated native discussion.
|
|
26513
|
+
*/
|
|
26514
|
+
function deleteItemDiscussionMessage(session, id, input, author) {
|
|
26515
|
+
return gen(function* () {
|
|
26516
|
+
let current = yield* required$1(session, id);
|
|
26517
|
+
yield* expectedThread(current.thread, input.expectedRevision);
|
|
26518
|
+
if (input.messageId === current.data.record.initial.id) return yield* new WorkError({
|
|
26519
|
+
reason: "refused",
|
|
26520
|
+
message: "A task's first comment stays; only replies can be deleted."
|
|
26521
|
+
});
|
|
26522
|
+
yield* validateDeletion(current.messages, input.messageId, author);
|
|
26523
|
+
let next = {
|
|
26524
|
+
...current.data,
|
|
26525
|
+
record: {
|
|
26526
|
+
...current.data.record,
|
|
26527
|
+
deleted: [...current.data.record.deleted ?? [], input.messageId],
|
|
26528
|
+
updatedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
26529
|
+
}
|
|
26530
|
+
};
|
|
26531
|
+
let json = yield* threadInput(() => payload(current.issue, next));
|
|
26532
|
+
yield* threadPayload(json, session.limits.metadataBytes);
|
|
26533
|
+
return yield* save(session, id, json, () => map$2(required$1(session, id), (result) => result.thread));
|
|
26534
|
+
});
|
|
26535
|
+
}
|
|
26536
|
+
/**
|
|
26447
26537
|
* Saves discussion-only status or linked items without mutating the work item's lifecycle.
|
|
26448
26538
|
* @param session - The shared native writer.
|
|
26449
26539
|
* @param id - The owning work item.
|
|
@@ -26620,7 +26710,7 @@ var capabilities$1 = {
|
|
|
26620
26710
|
link: true,
|
|
26621
26711
|
sync: true,
|
|
26622
26712
|
edit: false,
|
|
26623
|
-
delete:
|
|
26713
|
+
delete: true
|
|
26624
26714
|
};
|
|
26625
26715
|
var unavailableCapabilities = {
|
|
26626
26716
|
create: false,
|
|
@@ -26640,7 +26730,7 @@ function listThreads(session, filter) {
|
|
|
26640
26730
|
}, parseThreadRows);
|
|
26641
26731
|
let items = yield* listItemDiscussions(session, filter);
|
|
26642
26732
|
return yield* threadResult(() => {
|
|
26643
|
-
let threads = [...items.threads, ...rows.slice(0, MAX_THREADS).flatMap((row) => row ? [threadView(row)] : []).filter((thread) => matchesThread(thread, filter))];
|
|
26733
|
+
let threads = [...items.threads, ...rows.slice(0, MAX_THREADS).flatMap((row) => row && !threadDeleted(row.record) ? [threadView(row)] : []).filter((thread) => matchesThread(thread, filter))];
|
|
26644
26734
|
return parseThreadSnapshot({
|
|
26645
26735
|
connection: {
|
|
26646
26736
|
state: "ready",
|
|
@@ -26850,6 +26940,34 @@ var beadsStoreThreadAdapterLayer = effect(ThreadAdapter, gen(function* () {
|
|
|
26850
26940
|
}));
|
|
26851
26941
|
}));
|
|
26852
26942
|
}).pipe(mapError$2(threadFailure)),
|
|
26943
|
+
deleteMessage: (root, id, value, author) => gen(function* () {
|
|
26944
|
+
let input = yield* threadInput(() => parseThreadDeleteInput(value));
|
|
26945
|
+
let trusted = yield* threadInput(() => parseMessageAuthor(author));
|
|
26946
|
+
return yield* store.change(root, (session) => gen(function* () {
|
|
26947
|
+
let native = yield* threadInput(() => nativeDiscussionId(id));
|
|
26948
|
+
if (native) return yield* deleteItemDiscussionMessage(session, native, input, trusted);
|
|
26949
|
+
let { thread, row, messages } = yield* readThread(session, id);
|
|
26950
|
+
yield* expectedThread(thread, input.expectedRevision);
|
|
26951
|
+
yield* validateDeletion(messages, input.messageId, trusted);
|
|
26952
|
+
let record = yield* threadInput(() => parseThreadRecord({
|
|
26953
|
+
...row.record,
|
|
26954
|
+
deleted: [...row.record.deleted ?? [], input.messageId],
|
|
26955
|
+
updatedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
26956
|
+
}));
|
|
26957
|
+
let nextMetadata = {
|
|
26958
|
+
...row.issue.metadata,
|
|
26959
|
+
bud: record
|
|
26960
|
+
};
|
|
26961
|
+
yield* threadPayload(JSON.stringify(nextMetadata), session.limits.metadataBytes);
|
|
26962
|
+
return yield* threadChange(session, (writer) => gen(function* () {
|
|
26963
|
+
yield* saveRecord(writer, row, record);
|
|
26964
|
+
if (!threadDeleted(record)) return (yield* readThread(session, id)).thread;
|
|
26965
|
+
for (let item of thread.itemIds) yield* writer.removeDependency(id, item);
|
|
26966
|
+
if (thread.status !== "resolved") yield* writer.close(id, "Deleted in Bud");
|
|
26967
|
+
return null;
|
|
26968
|
+
}));
|
|
26969
|
+
}));
|
|
26970
|
+
}).pipe(mapError$2(threadFailure)),
|
|
26853
26971
|
link: (root, id, ids, revision) => link(root, id, ids, revision, false),
|
|
26854
26972
|
unlink: (root, id, ids, revision) => link(root, id, ids, revision, true),
|
|
26855
26973
|
sync: (root, direction = "both") => gen(function* () {
|
|
@@ -37473,10 +37591,10 @@ function ProjectLiveStatus(handle) {
|
|
|
37473
37591
|
//#endregion
|
|
37474
37592
|
//#region app/client/screens.ts
|
|
37475
37593
|
var builtIns = {
|
|
37476
|
-
"bud:pages": () => import("./assets/pages-
|
|
37477
|
-
"bud:canvas": () => import("./assets/canvas-
|
|
37478
|
-
"bud:tasks": () => import("./assets/tasks-
|
|
37479
|
-
"bud:files": () => import("./assets/files-
|
|
37594
|
+
"bud:pages": () => import("./assets/pages-BxpjbYhs.js"),
|
|
37595
|
+
"bud:canvas": () => import("./assets/canvas-TRUfxfL5.js"),
|
|
37596
|
+
"bud:tasks": () => import("./assets/tasks-Bs1IOpeU.js"),
|
|
37597
|
+
"bud:files": () => import("./assets/files-Dh2TiQZq.js")
|
|
37480
37598
|
};
|
|
37481
37599
|
/**
|
|
37482
37600
|
* Imports a screen module: a built-in by its key, any other by the URL the server gave it.
|
|
@@ -38049,6 +38167,11 @@ var builtInRoutes = {
|
|
|
38049
38167
|
"bud:tasks": taskRoutes,
|
|
38050
38168
|
"bud:files": fileRoutes
|
|
38051
38169
|
};
|
|
38170
|
+
function screenName(screen) {
|
|
38171
|
+
let builtIn = defaultScreens.find((candidate) => candidate.module === screen.module);
|
|
38172
|
+
let key = `screens.${builtIn?.id}`;
|
|
38173
|
+
return builtIn && screen.label === builtIn.label && hasMessage(key) ? t(key) : screen.label;
|
|
38174
|
+
}
|
|
38052
38175
|
/**
|
|
38053
38176
|
* Connects the route contract to application responses.
|
|
38054
38177
|
* @param template - The development or production HTML shell.
|
|
@@ -38089,7 +38212,10 @@ function createAppController(template, project, runtime) {
|
|
|
38089
38212
|
let module = await prepare(screen, request.signal);
|
|
38090
38213
|
let taskDesign = project && (screen.module === "bud:tasks" || conversation !== void 0 && screens.some((target) => target.module === "bud:tasks")) && project.config.designs.tasks !== "bud:beads" && runtime ? await runtime.runPromise(ScreenModules.use((modules) => modules.module(taskDesignModuleId)), { signal: request.signal }) : void 0;
|
|
38091
38214
|
let content = await renderToString(/* @__PURE__ */ jsx(WorkspacePage, {
|
|
38092
|
-
screens: items,
|
|
38215
|
+
screens: items.map((item, index) => ({
|
|
38216
|
+
...item,
|
|
38217
|
+
label: screenName(screens[index])
|
|
38218
|
+
})),
|
|
38093
38219
|
active: screen.id,
|
|
38094
38220
|
module,
|
|
38095
38221
|
taskDesign,
|
|
@@ -38116,7 +38242,7 @@ function createAppController(template, project, runtime) {
|
|
|
38116
38242
|
...patterns ? { routes: patterns } : {}
|
|
38117
38243
|
}
|
|
38118
38244
|
}));
|
|
38119
|
-
let title = (conversation ? "
|
|
38245
|
+
let title = (conversation ? t("app.controller.discussion") : screenName(screen)).replace(/[&<>]/g, (character) => `&#${character.charCodeAt(0)};`);
|
|
38120
38246
|
let logo = project?.config.logo;
|
|
38121
38247
|
let shell = logo ? withLogoIcons(template, logo, (theme) => routes.logo.href({ theme })) : template;
|
|
38122
38248
|
return new Response(shell.replace("<html lang=\"en\"", () => `<html lang="${locale()}"`).replace("<title>bud.sh</title>", () => `<title>${title} · bud.sh</title>`).replace("</head>", () => project ? `${themeStyle(project.config.theme)}</head>` : "</head>").replace("<!--app-html-->", () => content), { headers: { "Content-Type": "text/html; charset=utf-8" } });
|
|
@@ -39317,7 +39443,11 @@ function adapterRegistryLayer(project, builtIns) {
|
|
|
39317
39443
|
"setStatus",
|
|
39318
39444
|
"link",
|
|
39319
39445
|
"unlink"
|
|
39320
|
-
], [
|
|
39446
|
+
], [
|
|
39447
|
+
"sync",
|
|
39448
|
+
"import",
|
|
39449
|
+
"deleteMessage"
|
|
39450
|
+
]);
|
|
39321
39451
|
let connection = yield* threads.list(root, {}).pipe(flatMap$1((value) => try_({
|
|
39322
39452
|
try: () => parseThreadSnapshot(value).connection,
|
|
39323
39453
|
catch: failure$2(`Adapter ${selected.threads.id} returned an invalid thread connection.`)
|
|
@@ -39796,6 +39926,32 @@ function createCommentsController(project, runtime) {
|
|
|
39796
39926
|
unlink({ request, params }) {
|
|
39797
39927
|
return respond(request, (project) => written(link(request, project, params.id, true)));
|
|
39798
39928
|
},
|
|
39929
|
+
deleteMessage({ request, params }) {
|
|
39930
|
+
return respond(request, (project) => written(gen(function* () {
|
|
39931
|
+
let id = yield* input$1(() => parseThreadId(params.id));
|
|
39932
|
+
let value = yield* readProjectJsonBody(request, { maxBytes: 64e3 });
|
|
39933
|
+
let parsed = yield* input$1(() => parseThreadDeleteInput(value));
|
|
39934
|
+
let store = yield* writable(project.root, "delete");
|
|
39935
|
+
if (!store.deleteMessage) return yield* new WorkError({
|
|
39936
|
+
reason: "refused",
|
|
39937
|
+
message: "This comment adapter does not support deleting messages."
|
|
39938
|
+
});
|
|
39939
|
+
let author = yield* commentAuthor(project.root);
|
|
39940
|
+
let thread = yield* store.deleteMessage(project.root, id, parsed, author);
|
|
39941
|
+
return yield* result(() => {
|
|
39942
|
+
if (thread === null) return { thread: null };
|
|
39943
|
+
let parsed = parseThread(thread);
|
|
39944
|
+
if (parsed.id !== id) throw new Error("Unexpected discussion identity.");
|
|
39945
|
+
return { thread: parsed };
|
|
39946
|
+
}, true);
|
|
39947
|
+
})));
|
|
39948
|
+
},
|
|
39949
|
+
viewer({ request }) {
|
|
39950
|
+
return respond(request, (project) => commentAuthor(project.root).pipe(map$2((author) => ({ viewer: {
|
|
39951
|
+
id: author.id,
|
|
39952
|
+
name: author.name
|
|
39953
|
+
} })), orElseSucceed(() => ({ viewer: null }))));
|
|
39954
|
+
},
|
|
39799
39955
|
sync({ request }) {
|
|
39800
39956
|
return respond(request, (project) => gen(function* () {
|
|
39801
39957
|
let value = yield* readProjectJsonBody(request, { maxBytes: 64e3 });
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { Bt as Button,
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import { t as ProjectThreadLinks } from "./project-thread-links-
|
|
1
|
+
import { Bn as Icon } from "./events-iHpLGr3k.js";
|
|
2
|
+
import { Bt as Button, En as t, H as captureCanvasPoint, On as Text, Rt as Loader, Sn as writePreference, V as CanvasWorkspace, W as BranchSidebar, fn as ToolbarSeparator, gn as IconButton, hn as Select, l as projectStore, pn as WorkspaceLayout, t as commentsUnavailable, ut as conversationHref, vn as Tooltip, xn as readPreference } from "./comment-data-CsjukwAW.js";
|
|
3
|
+
import { i as pictureKey, n as createProjectPreviews, t as createProjectBranches } from "./project-branches-B0YIK6Ur.js";
|
|
4
|
+
import { n as createProjectComments, r as loadComments, t as defineScreen } from "./screen-BIQA2mr4.js";
|
|
5
|
+
import { t as ProjectThreadLinks } from "./project-thread-links-CBOpf6zk.js";
|
|
6
6
|
import { on, ref } from "remix/component";
|
|
7
7
|
import { Fragment, jsx, jsxs } from "remix/component/jsx-runtime";
|
|
8
8
|
//#region app/client/preview-image.tsx
|
|
@@ -1034,6 +1034,8 @@ function ProjectCanvas(handle) {
|
|
|
1034
1034
|
},
|
|
1035
1035
|
onSync: () => comments.sync().catch(() => {}),
|
|
1036
1036
|
onReload: comments.load,
|
|
1037
|
+
viewerId: comments.viewer?.id,
|
|
1038
|
+
onDeleteComment: (threadId, messageId) => comments.remove(threadId, messageId),
|
|
1037
1039
|
onCopyThreadLink: (thread) => navigator.clipboard.writeText(new URL(conversationHref(thread.id), window.location.origin).href),
|
|
1038
1040
|
interactive: false,
|
|
1039
1041
|
branch: selected,
|