collabmd 0.1.44 → 0.1.45
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/{chunk-AXR3VHVW-0GTk_evH.js → chunk-ERSWUTIN-ME9RVNel.js} +3 -3
- package/dist/client/assets/{chunk-CZQZEIFA-DT3N9fo7.js → chunk-YGJVY4SA-CjSe7Bx7.js} +2 -2
- package/dist/client/assets/{comment-threads-D-iKphIp.js → comment-threads-DDegmaFO.js} +1 -1
- package/dist/client/assets/drawio-editor-ClE8jpoG.js +9 -0
- package/dist/client/assets/drawioEditor-CXaTM9Ds.js +2 -0
- package/dist/client/assets/editor-session-GTwZS6Df.js +16 -0
- package/dist/client/assets/embedded-editor-base-CiNEc8vy.css +1 -0
- package/dist/client/assets/{en-GADW4C6J-DQ6zyCEM.js → en-7NFCYGKX-BrgYZAEe.js} +1 -1
- package/dist/client/assets/{excalidraw-editor-BHu6k8d4.js → excalidraw-editor-BZVM81BO.js} +2 -2
- package/dist/client/assets/excalidraw-editor-CyGwOhLz.css +1 -0
- package/dist/client/assets/excalidraw-scene-C8n9CHsK.js +176 -0
- package/dist/client/assets/excalidrawEditor-DxJanCze.js +2 -0
- package/dist/client/assets/export-page-CUfws2T-.js +39 -0
- package/dist/client/assets/exportDocument-BCuxqXDY.js +2 -0
- package/dist/client/assets/exportDocument-DV-OX74E.css +1 -0
- package/dist/client/assets/image-QXRYHUNP-lfTHE3bb.js +1 -0
- package/dist/client/assets/index-C3YnUgMD.css +1 -0
- package/dist/client/assets/index-D2wXraJ1.js +2 -0
- package/dist/client/assets/main-DtiGz7uI.js +795 -0
- package/dist/client/assets/modulepreload-polyfill-P2Xu9kJm.js +1 -0
- package/dist/client/assets/preview-diagram-utils-txBCoW8d.js +1 -0
- package/dist/client/assets/quick-switcher-controller-shW_6vPY.js +12 -0
- package/dist/client/assets/room-CQLoqtMo.js +1 -0
- package/dist/client/assets/runtime-config-DSGmGE9V.js +1 -0
- package/dist/client/assets/vault-api-client-C6bcGwy-.js +5 -0
- package/dist/client/assets/{yjs-provider-reset-guard-Cox4nxwu.js → yjs-provider-reset-guard-DE0vINDP.js} +1 -1
- package/dist/client/drawio-editor.html +3 -2
- package/dist/client/excalidraw-editor.html +3 -2
- package/dist/client/export-document.html +4 -3
- package/dist/client/index.html +97 -27
- package/package.json +10 -12
- package/src/client/app/drawio-editor-entry.js +0 -3
- package/src/client/app/drawio-editor.html +1 -0
- package/src/client/app/excalidraw-editor-entry.js +0 -3
- package/src/client/app/excalidraw-editor.html +1 -0
- package/src/client/app/export-document-entry.js +0 -3
- package/src/client/app/export-document.html +1 -0
- package/src/client/app/index.html +94 -24
- package/src/client/app/main-entry.js +0 -5
- package/src/client/application/app-shell/chat-feature.js +180 -124
- package/src/client/application/app-shell/comments-feature.js +1 -1
- package/src/client/application/app-shell/git-feature.js +4 -9
- package/src/client/application/app-shell/presence-feature.js +16 -10
- package/src/client/application/app-shell/ui-feature-shell.js +33 -15
- package/src/client/application/app-shell/ui-feature-sidebar.js +74 -1
- package/src/client/application/app-shell/ui-feature-tab-activity.js +2 -2
- package/src/client/application/app-shell/workspace-feature.js +22 -83
- package/src/client/application/app-shell-elements.js +7 -1
- package/src/client/application/diagram-chrome.js +161 -166
- package/src/client/application/diagram-preview-export.js +7 -34
- package/src/client/application/diagram-preview-hydrator.js +1 -19
- package/src/client/application/markdown-frontmatter.js +0 -2
- package/src/client/application/mermaid-preview-hydrator.js +1 -14
- package/src/client/application/plantuml-preview-hydrator.js +0 -10
- package/src/client/application/preview-diagram-utils.js +31 -2
- package/src/client/application/preview-render-compiler.js +2 -1
- package/src/client/application/preview-renderer.js +2 -2
- package/src/client/application/quick-switcher-loader.js +3 -1
- package/src/client/application/workspace-preview-controller.js +0 -3
- package/src/client/bootstrap/collabmd-app-shell.js +125 -39
- package/src/client/domain/excalidraw-collaboration.js +0 -2
- package/src/client/domain/room.js +38 -0
- package/src/client/export/export-pipeline.js +6 -34
- package/src/client/infrastructure/auth-client.js +4 -10
- package/src/client/infrastructure/browser-notification-port.js +33 -20
- package/src/client/infrastructure/browser-preferences-port.js +36 -9
- package/src/client/infrastructure/editor-view-adapter.js +87 -3
- package/src/client/infrastructure/lobby-presence.js +1 -0
- package/src/client/infrastructure/vault-api-client.js +25 -0
- package/src/client/infrastructure/workspace-sync-client.js +13 -1
- package/src/client/presentation/comment-overview-controller.js +18 -53
- package/src/client/presentation/comment-ui/comment-ui-card.js +1 -12
- package/src/client/presentation/comment-ui/comment-ui-layout.js +242 -219
- package/src/client/presentation/comment-ui/comment-ui-render.js +32 -45
- package/src/client/presentation/comment-ui/comment-ui-shared.js +65 -14
- package/src/client/presentation/comment-ui-controller.js +5 -1
- package/src/client/presentation/file-action-controller.js +32 -0
- package/src/client/presentation/file-explorer-controller.js +33 -3
- package/src/client/presentation/file-explorer-view.js +49 -5
- package/src/client/presentation/file-tree-state.js +10 -4
- package/src/client/presentation/quick-switcher-controller.js +243 -72
- package/src/client/presentation/quick-switcher-text-search.js +2 -2
- package/src/client/presentation/toast-controller.js +3 -0
- package/src/client/styles/components/feedback.css +6 -0
- package/src/client/styles/features/collaboration-chat.css +49 -53
- package/src/client/styles/features/collaboration-presence.css +9 -7
- package/src/client/styles/features/comment-card.css +25 -11
- package/src/client/styles/features/comment-overlays.css +0 -4
- package/src/client/styles/features/comment-overview.css +44 -21
- package/src/client/styles/features/comments-drawer.css +2 -100
- package/src/client/styles/features/diagram-preview.css +5 -18
- package/src/client/styles/features/embedded-preview.css +8 -33
- package/src/client/styles/features/quick-switcher.css +8 -0
- package/src/client/styles/foundation/tokens.css +1 -0
- package/src/client/styles/layout/editor-page.css +40 -0
- package/src/client/styles/layout/responsive.css +31 -1
- package/src/client/styles/layout/shell.css +25 -6
- package/src/client/styles/layout/sidebar.css +47 -15
- package/src/client/styles/overrides/codemirror.css +217 -15
- package/src/server/application/workspace-reconciliation.js +1 -1
- package/src/server/create-app-server.js +2 -3
- package/src/server/domain/bases/base-query-service.js +1 -77
- package/src/server/domain/comment-overview.js +10 -3
- package/src/server/domain/docx-exporter.js +24 -33
- package/src/server/domain/ripgrep-search-service.js +3 -1
- package/src/server/domain/workspace-state.js +32 -11
- package/src/server/infrastructure/git/diff-service.js +24 -13
- package/src/server/infrastructure/git/git-service.js +40 -10
- package/src/server/infrastructure/git/history-service.js +42 -29
- package/src/server/infrastructure/git/path-utils.js +1 -1
- package/src/server/infrastructure/git/responses.js +0 -95
- package/src/server/infrastructure/github/github-app-client.js +22 -15
- package/src/server/infrastructure/http/create-request-handler.js +2 -8
- package/src/server/infrastructure/http/create-vault-api-command-handler.js +5 -5
- package/src/server/infrastructure/http/http-errors.js +7 -1
- package/dist/client/assets/bases-preview-controller-2pLHk0uk.js +0 -143
- package/dist/client/assets/button-BCEiw4Rw.js +0 -1
- package/dist/client/assets/diagram-action-icons-aa_KOv9h.js +0 -36
- package/dist/client/assets/drawio-editor-DDvFoarP.js +0 -9
- package/dist/client/assets/drawio-embed-controller-BD1GTRwn.js +0 -1
- package/dist/client/assets/drawioEditor-Bu5grlH5.js +0 -2
- package/dist/client/assets/editor-session-DGlpiAsK.js +0 -16
- package/dist/client/assets/embedded-editor-base-C9roKYpW.css +0 -1
- package/dist/client/assets/excalidraw-editor-Cr_184EF.css +0 -1
- package/dist/client/assets/excalidraw-embed-controller-y2fenN_g.js +0 -1
- package/dist/client/assets/excalidraw-embed-reconciler-DGiagExg.js +0 -1
- package/dist/client/assets/excalidraw-scene-BvsQ6mLP.js +0 -176
- package/dist/client/assets/excalidrawEditor-4vFE--Uw.js +0 -2
- package/dist/client/assets/export-page-Cby8JzPO.js +0 -39
- package/dist/client/assets/exportDocument-C9v-bc7I.css +0 -1
- package/dist/client/assets/exportDocument-CRHCfsdo.js +0 -2
- package/dist/client/assets/file-history-view-controller-BDjEV9xJ.js +0 -112
- package/dist/client/assets/git-diff-view-controller-DgdM1aqb.js +0 -150
- package/dist/client/assets/git-panel-controller-BDTR2HVp.js +0 -207
- package/dist/client/assets/image-XGD7JQR6-XDUWHRpO.js +0 -1
- package/dist/client/assets/index-7xOyXDhP.css +0 -1
- package/dist/client/assets/index-Bz1KuQ6y.js +0 -2
- package/dist/client/assets/inter-cyrillic-ext-wght-normal-BOeWTOD4.woff2 +0 -0
- package/dist/client/assets/inter-cyrillic-wght-normal-DqGufNeO.woff2 +0 -0
- package/dist/client/assets/inter-greek-ext-wght-normal-DlzME5K_.woff2 +0 -0
- package/dist/client/assets/inter-greek-wght-normal-CkhJZR-_.woff2 +0 -0
- package/dist/client/assets/inter-latin-ext-wght-normal-DO1Apj_S.woff2 +0 -0
- package/dist/client/assets/inter-latin-wght-normal-Dx4kXJAl.woff2 +0 -0
- package/dist/client/assets/inter-vietnamese-wght-normal-CBcvBZtf.woff2 +0 -0
- package/dist/client/assets/jetbrains-mono-cyrillic-400-normal-BEIGL1Tu.woff2 +0 -0
- package/dist/client/assets/jetbrains-mono-cyrillic-400-normal-ugxPyKxw.woff +0 -0
- package/dist/client/assets/jetbrains-mono-greek-400-normal-B9oWc5Lo.woff +0 -0
- package/dist/client/assets/jetbrains-mono-greek-400-normal-C190GLew.woff2 +0 -0
- package/dist/client/assets/jetbrains-mono-latin-400-normal-6-qcROiO.woff +0 -0
- package/dist/client/assets/jetbrains-mono-latin-400-normal-V6pRDFza.woff2 +0 -0
- package/dist/client/assets/jetbrains-mono-latin-ext-400-normal-Bc8Ftmh3.woff2 +0 -0
- package/dist/client/assets/jetbrains-mono-latin-ext-400-normal-fXTG6kC5.woff +0 -0
- package/dist/client/assets/jetbrains-mono-vietnamese-400-normal-CqNFfHCs.woff +0 -0
- package/dist/client/assets/main-Ci07m9oP.js +0 -152
- package/dist/client/assets/preview-diagram-utils-n_bbJA9V.js +0 -1
- package/dist/client/assets/quick-switcher-controller-CoiYvllm.js +0 -12
- package/dist/client/assets/room-CDrmIdDt.js +0 -1
- package/dist/client/assets/runtime-config-CDgeuPWN.js +0 -1
- package/dist/client/assets/runtime-config-loader-BHGniHP5.js +0 -1
- package/dist/client/assets/runtime-paths-DvpihCEq.js +0 -1
- package/dist/client/assets/segmented-control-DJrHSz8M.js +0 -1
- package/dist/client/assets/vault-api-client-sLB2bo56.js +0 -1
- package/dist/client/assets/vault-paths-CVkuh0j-.js +0 -5
- package/src/client/bootstrap/lazy-controller-feature.js +0 -433
- package/src/client/infrastructure/backlinks-api-client.js +0 -16
- package/src/client/infrastructure/plantuml-api-client.js +0 -19
- package/src/client/infrastructure/runtime-config-loader.js +0 -56
- package/src/server/infrastructure/git/command-runner.js +0 -49
- package/src/server/infrastructure/git/errors.js +0 -8
- package/src/server/infrastructure/http/create-esm-proxy-handler.js +0 -130
|
@@ -152,82 +152,6 @@ export class BaseQueryService {
|
|
|
152
152
|
this.propertyCatalogCache = new Map();
|
|
153
153
|
}
|
|
154
154
|
|
|
155
|
-
get workspaceStateProvider() {
|
|
156
|
-
return this.snapshotStore.workspaceStateProvider;
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
set workspaceStateProvider(value) {
|
|
160
|
-
this.snapshotStore.workspaceStateProvider = value;
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
get workspaceStateSynchronizer() {
|
|
164
|
-
return this.snapshotStore.workspaceStateSynchronizer;
|
|
165
|
-
}
|
|
166
|
-
|
|
167
|
-
set workspaceStateSynchronizer(value) {
|
|
168
|
-
this.snapshotStore.workspaceStateSynchronizer = value;
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
get indexSnapshot() {
|
|
172
|
-
return this.snapshotStore.indexSnapshot;
|
|
173
|
-
}
|
|
174
|
-
|
|
175
|
-
set indexSnapshot(value) {
|
|
176
|
-
this.snapshotStore.indexSnapshot = value;
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
get lastWorkspaceState() {
|
|
180
|
-
return this.snapshotStore.lastWorkspaceState;
|
|
181
|
-
}
|
|
182
|
-
|
|
183
|
-
set lastWorkspaceState(value) {
|
|
184
|
-
this.snapshotStore.lastWorkspaceState = value;
|
|
185
|
-
}
|
|
186
|
-
|
|
187
|
-
async getWorkspaceState() {
|
|
188
|
-
return this.snapshotStore.getWorkspaceState();
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
createSnapshotRow(...args) {
|
|
192
|
-
return this.snapshotStore.createSnapshotRow(...args);
|
|
193
|
-
}
|
|
194
|
-
|
|
195
|
-
rebuildBacklinks(...args) {
|
|
196
|
-
return this.snapshotStore.rebuildBacklinks(...args);
|
|
197
|
-
}
|
|
198
|
-
|
|
199
|
-
async buildIndexSnapshot(...args) {
|
|
200
|
-
return this.snapshotStore.buildIndexSnapshot(...args);
|
|
201
|
-
}
|
|
202
|
-
|
|
203
|
-
async synchronizeWorkspaceState() {
|
|
204
|
-
return this.snapshotStore.synchronizeWorkspaceState();
|
|
205
|
-
}
|
|
206
|
-
|
|
207
|
-
removeSnapshotPath(...args) {
|
|
208
|
-
return this.snapshotStore.removeSnapshotPath(...args);
|
|
209
|
-
}
|
|
210
|
-
|
|
211
|
-
upsertSnapshotPath(...args) {
|
|
212
|
-
return this.snapshotStore.upsertSnapshotPath(...args);
|
|
213
|
-
}
|
|
214
|
-
|
|
215
|
-
collectImpactedSourcesForMembershipChanges(...args) {
|
|
216
|
-
return this.snapshotStore.collectImpactedSourcesForMembershipChanges(...args);
|
|
217
|
-
}
|
|
218
|
-
|
|
219
|
-
async refreshSnapshotRows(...args) {
|
|
220
|
-
return this.snapshotStore.refreshSnapshotRows(...args);
|
|
221
|
-
}
|
|
222
|
-
|
|
223
|
-
async ensureIndexSnapshot(...args) {
|
|
224
|
-
return this.snapshotStore.ensureIndexSnapshot(...args);
|
|
225
|
-
}
|
|
226
|
-
|
|
227
|
-
async initializeFromWorkspaceState(...args) {
|
|
228
|
-
return this.snapshotStore.initializeFromWorkspaceState(...args);
|
|
229
|
-
}
|
|
230
|
-
|
|
231
155
|
async applyWorkspaceChange(...args) {
|
|
232
156
|
const result = await this.snapshotStore.applyWorkspaceChange(...args);
|
|
233
157
|
const scannedAt = this.snapshotStore.indexSnapshot?.scannedAt;
|
|
@@ -279,7 +203,7 @@ export class BaseQueryService {
|
|
|
279
203
|
}
|
|
280
204
|
|
|
281
205
|
const definition = this.getCachedDefinition(source === null ? `file:${basePath}` : `source:${sourcePath}:${basePath}`, baseSource);
|
|
282
|
-
const snapshot = await this.ensureIndexSnapshot({
|
|
206
|
+
const snapshot = await this.snapshotStore.ensureIndexSnapshot({
|
|
283
207
|
basePath,
|
|
284
208
|
sourcePath,
|
|
285
209
|
});
|
|
@@ -1,7 +1,14 @@
|
|
|
1
|
-
import { summarizeCommentExcerpt } from '../../domain/comment-threads.js';
|
|
2
|
-
|
|
3
1
|
const COMMENT_OVERVIEW_PREVIEW_MAX_LENGTH = 140;
|
|
4
2
|
|
|
3
|
+
function summarizeCommentMarkdown(value, maxLength = COMMENT_OVERVIEW_PREVIEW_MAX_LENGTH) {
|
|
4
|
+
const normalized = String(value ?? '').replace(/\r\n?/gu, '\n').trim();
|
|
5
|
+
if (normalized.length <= maxLength) {
|
|
6
|
+
return normalized;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
return `${normalized.slice(0, Math.max(maxLength - 1, 1)).trimEnd()}…`;
|
|
10
|
+
}
|
|
11
|
+
|
|
5
12
|
function asFiniteNumber(value) {
|
|
6
13
|
return Number.isFinite(value) ? value : null;
|
|
7
14
|
}
|
|
@@ -58,7 +65,7 @@ function createThreadSummary(thread) {
|
|
|
58
65
|
latestActivityAt,
|
|
59
66
|
latestMessage: latestMessage
|
|
60
67
|
? {
|
|
61
|
-
bodyPreview:
|
|
68
|
+
bodyPreview: summarizeCommentMarkdown(latestMessage.body),
|
|
62
69
|
createdAt: asFiniteNumber(latestMessage.createdAt) ?? latestActivityAt,
|
|
63
70
|
userColor: asString(latestMessage.userColor),
|
|
64
71
|
userName: asString(latestMessage.userName) || 'Anonymous',
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
const DOCX_EXPORTER_CREATOR = 'CollabMD';
|
|
2
|
+
let converterPromise = null;
|
|
2
3
|
|
|
3
4
|
function normalizeDocxBuffer(result) {
|
|
4
5
|
if (Buffer.isBuffer(result)) {
|
|
@@ -16,47 +17,37 @@ function normalizeDocxBuffer(result) {
|
|
|
16
17
|
throw new Error('DOCX exporter returned an unsupported payload');
|
|
17
18
|
}
|
|
18
19
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
} = {}) {
|
|
23
|
-
this.loadConverter = loadConverter;
|
|
24
|
-
this.converterPromise = null;
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
async ensureConverter() {
|
|
28
|
-
if (this.converterPromise) {
|
|
29
|
-
return this.converterPromise;
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
this.converterPromise = this.loadConverter().then((module) => {
|
|
20
|
+
async function ensureConverter() {
|
|
21
|
+
if (!converterPromise) {
|
|
22
|
+
converterPromise = import('@turbodocx/html-to-docx').then((module) => {
|
|
33
23
|
const converter = module?.default ?? module?.HTMLToDOCX ?? module;
|
|
34
24
|
if (typeof converter !== 'function') {
|
|
35
25
|
throw new Error('DOCX converter failed to load');
|
|
36
26
|
}
|
|
37
27
|
return converter;
|
|
38
28
|
});
|
|
39
|
-
return this.converterPromise;
|
|
40
29
|
}
|
|
41
30
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
31
|
+
return converterPromise;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export async function renderDocx({
|
|
35
|
+
html,
|
|
36
|
+
title = '',
|
|
37
|
+
} = {}) {
|
|
38
|
+
const converter = await ensureConverter();
|
|
39
|
+
const result = await converter(String(html ?? ''), null, {
|
|
40
|
+
creator: DOCX_EXPORTER_CREATOR,
|
|
41
|
+
font: 'Arial',
|
|
42
|
+
footer: false,
|
|
43
|
+
pageNumber: false,
|
|
44
|
+
table: {
|
|
45
|
+
row: {
|
|
46
|
+
cantSplit: true,
|
|
56
47
|
},
|
|
57
|
-
|
|
58
|
-
|
|
48
|
+
},
|
|
49
|
+
title: String(title ?? ''),
|
|
50
|
+
});
|
|
59
51
|
|
|
60
|
-
|
|
61
|
-
}
|
|
52
|
+
return normalizeDocxBuffer(result);
|
|
62
53
|
}
|
|
@@ -106,7 +106,7 @@ function createRipgrepArgs(query, {
|
|
|
106
106
|
'--max-filesize',
|
|
107
107
|
String(maxFileSize || DEFAULT_MAX_FILE_SIZE),
|
|
108
108
|
'--max-count',
|
|
109
|
-
String(maxSnippetsPerFile),
|
|
109
|
+
String(Math.max(Number(maxSnippetsPerFile) || DEFAULT_MAX_SNIPPETS_PER_FILE, 1) + 1),
|
|
110
110
|
'--glob',
|
|
111
111
|
'!.git/**',
|
|
112
112
|
'--glob',
|
|
@@ -171,6 +171,7 @@ export function parseRipgrepJson(stdout, {
|
|
|
171
171
|
kind: getVaultFileKind(filePath) ?? 'text',
|
|
172
172
|
matchCount: 0,
|
|
173
173
|
snippets: [],
|
|
174
|
+
truncated: false,
|
|
174
175
|
};
|
|
175
176
|
filesByPath.set(filePath, fileGroup);
|
|
176
177
|
files.push(fileGroup);
|
|
@@ -187,6 +188,7 @@ export function parseRipgrepJson(stdout, {
|
|
|
187
188
|
matchCount += 1;
|
|
188
189
|
|
|
189
190
|
if (fileGroup.snippets.length >= maxSnippetsPerFile) {
|
|
191
|
+
fileGroup.truncated = true;
|
|
190
192
|
truncated = true;
|
|
191
193
|
continue;
|
|
192
194
|
}
|
|
@@ -42,6 +42,20 @@ export function createWorkspaceMetadata(pathValue, type, info = {}) {
|
|
|
42
42
|
};
|
|
43
43
|
}
|
|
44
44
|
|
|
45
|
+
function enrichWorkspaceEntries(entries, metadata) {
|
|
46
|
+
const enrichedEntries = new Map(entries);
|
|
47
|
+
metadata.forEach((entryMetadata, pathValue) => {
|
|
48
|
+
const entry = enrichedEntries.get(pathValue);
|
|
49
|
+
const mtimeMs = Number(entryMetadata?.mtimeMs);
|
|
50
|
+
if (!entry || !Number.isFinite(mtimeMs) || entry.mtimeMs === mtimeMs) {
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
enrichedEntries.set(pathValue, { ...entry, mtimeMs });
|
|
55
|
+
});
|
|
56
|
+
return enrichedEntries;
|
|
57
|
+
}
|
|
58
|
+
|
|
45
59
|
export function collectWorkspaceStateStats(entries = new Map(), metadata = new Map()) {
|
|
46
60
|
const filePaths = [];
|
|
47
61
|
const markdownPaths = [];
|
|
@@ -75,8 +89,11 @@ export function collectWorkspaceStateStats(entries = new Map(), metadata = new M
|
|
|
75
89
|
export function createWorkspaceStateSnapshot(entries = new Map(), metadata = new Map(), {
|
|
76
90
|
scannedAt = Date.now(),
|
|
77
91
|
} = {}) {
|
|
78
|
-
const normalizedEntries = entries instanceof Map ? entries : new Map(entries ?? []);
|
|
79
92
|
const normalizedMetadata = metadata instanceof Map ? metadata : new Map(metadata ?? []);
|
|
93
|
+
const normalizedEntries = enrichWorkspaceEntries(
|
|
94
|
+
entries instanceof Map ? entries : new Map(entries ?? []),
|
|
95
|
+
normalizedMetadata,
|
|
96
|
+
);
|
|
80
97
|
const stats = collectWorkspaceStateStats(normalizedEntries, normalizedMetadata);
|
|
81
98
|
|
|
82
99
|
return {
|
|
@@ -385,21 +402,24 @@ export function createWorkspaceTree(entries = new Map()) {
|
|
|
385
402
|
return;
|
|
386
403
|
}
|
|
387
404
|
|
|
388
|
-
|
|
389
|
-
|
|
405
|
+
const mtimeMs = Number(entry?.mtimeMs);
|
|
406
|
+
const node = entry?.type === 'directory' || entry?.nodeType === 'directory'
|
|
407
|
+
? {
|
|
390
408
|
children: [],
|
|
391
409
|
name: entry?.name ?? basename(normalizedPath),
|
|
392
410
|
path: normalizedPath,
|
|
393
411
|
type: 'directory',
|
|
394
|
-
}
|
|
395
|
-
|
|
396
|
-
|
|
412
|
+
}
|
|
413
|
+
: {
|
|
414
|
+
name: entry?.name ?? basename(normalizedPath),
|
|
415
|
+
path: normalizedPath,
|
|
416
|
+
type: entry?.type ?? getVaultTreeNodeType(normalizedPath),
|
|
417
|
+
};
|
|
397
418
|
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
});
|
|
419
|
+
if (node.type !== 'directory' && Number.isFinite(mtimeMs)) {
|
|
420
|
+
node.mtimeMs = mtimeMs;
|
|
421
|
+
}
|
|
422
|
+
nodesByPath.set(normalizedPath, node);
|
|
403
423
|
});
|
|
404
424
|
|
|
405
425
|
nodesByPath.forEach((node, pathValue) => {
|
|
@@ -423,6 +443,7 @@ export function workspaceEntriesEqual(left = {}, right = {}) {
|
|
|
423
443
|
&& left.nodeType === right.nodeType
|
|
424
444
|
&& left.parentPath === right.parentPath
|
|
425
445
|
&& left.path === right.path
|
|
446
|
+
&& left.mtimeMs === right.mtimeMs
|
|
426
447
|
&& left.type === right.type
|
|
427
448
|
);
|
|
428
449
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { countPatchLines, parseNumstatOutput, parseUnifiedDiff } from './parsers.js';
|
|
2
|
-
import {
|
|
2
|
+
import { createEmptyStats } from './responses.js';
|
|
3
3
|
|
|
4
4
|
function createSectionMap(sections = []) {
|
|
5
5
|
return new Map(sections.map((section) => [section.key, section]));
|
|
@@ -162,12 +162,18 @@ export class GitDiffService {
|
|
|
162
162
|
async getDiff({ allowLargePatch = false, metaOnly = false, path = null, scope = 'working-tree' } = {}) {
|
|
163
163
|
const isGitRepo = await this.commandRunner.isGitRepo();
|
|
164
164
|
if (!isGitRepo) {
|
|
165
|
-
return
|
|
165
|
+
return {
|
|
166
166
|
files: [],
|
|
167
167
|
isGitRepo: false,
|
|
168
168
|
metaOnly,
|
|
169
|
+
path: null,
|
|
169
170
|
scope,
|
|
170
|
-
|
|
171
|
+
summary: {
|
|
172
|
+
additions: 0,
|
|
173
|
+
deletions: 0,
|
|
174
|
+
filesChanged: 0,
|
|
175
|
+
},
|
|
176
|
+
};
|
|
171
177
|
}
|
|
172
178
|
|
|
173
179
|
const resolvedScope = scope === 'staged' || scope === 'all'
|
|
@@ -214,13 +220,14 @@ export class GitDiffService {
|
|
|
214
220
|
scope,
|
|
215
221
|
});
|
|
216
222
|
|
|
217
|
-
return
|
|
223
|
+
return {
|
|
218
224
|
files: scopedFiles,
|
|
225
|
+
isGitRepo: true,
|
|
219
226
|
metaOnly: true,
|
|
220
227
|
path,
|
|
221
228
|
scope,
|
|
222
229
|
summary: scopeSummary,
|
|
223
|
-
}
|
|
230
|
+
};
|
|
224
231
|
}
|
|
225
232
|
|
|
226
233
|
const isSinglePathRequest = Boolean(path);
|
|
@@ -234,7 +241,7 @@ export class GitDiffService {
|
|
|
234
241
|
};
|
|
235
242
|
|
|
236
243
|
if (!allowLargePatch && fileLineCount > this.maxInitialPatchLines) {
|
|
237
|
-
return
|
|
244
|
+
return {
|
|
238
245
|
files: [{
|
|
239
246
|
...currentFile,
|
|
240
247
|
canLoadFullPatch: true,
|
|
@@ -246,11 +253,12 @@ export class GitDiffService {
|
|
|
246
253
|
},
|
|
247
254
|
tooLarge: true,
|
|
248
255
|
}],
|
|
256
|
+
isGitRepo: true,
|
|
249
257
|
metaOnly: false,
|
|
250
258
|
path,
|
|
251
259
|
scope,
|
|
252
260
|
summary,
|
|
253
|
-
}
|
|
261
|
+
};
|
|
254
262
|
}
|
|
255
263
|
|
|
256
264
|
const syntheticFiles = await this.untrackedFileService.buildSyntheticDiffs([currentFile]);
|
|
@@ -263,7 +271,7 @@ export class GitDiffService {
|
|
|
263
271
|
},
|
|
264
272
|
};
|
|
265
273
|
|
|
266
|
-
return
|
|
274
|
+
return {
|
|
267
275
|
files: [{
|
|
268
276
|
...currentFile,
|
|
269
277
|
...detail,
|
|
@@ -271,11 +279,12 @@ export class GitDiffService {
|
|
|
271
279
|
patchLineCount: countPatchLines(detail),
|
|
272
280
|
tooLarge: false,
|
|
273
281
|
}],
|
|
282
|
+
isGitRepo: true,
|
|
274
283
|
metaOnly: false,
|
|
275
284
|
path,
|
|
276
285
|
scope,
|
|
277
286
|
summary,
|
|
278
|
-
}
|
|
287
|
+
};
|
|
279
288
|
}
|
|
280
289
|
|
|
281
290
|
let singleFileSummary = null;
|
|
@@ -293,7 +302,7 @@ export class GitDiffService {
|
|
|
293
302
|
&& singleFileSummary.filesChanged > 0
|
|
294
303
|
&& (singleFileSummary.additions + singleFileSummary.deletions) > this.maxInitialPatchLines
|
|
295
304
|
) {
|
|
296
|
-
return
|
|
305
|
+
return {
|
|
297
306
|
files: [{
|
|
298
307
|
...currentFile,
|
|
299
308
|
canLoadFullPatch: true,
|
|
@@ -305,11 +314,12 @@ export class GitDiffService {
|
|
|
305
314
|
},
|
|
306
315
|
tooLarge: true,
|
|
307
316
|
}],
|
|
317
|
+
isGitRepo: true,
|
|
308
318
|
metaOnly: false,
|
|
309
319
|
path,
|
|
310
320
|
scope,
|
|
311
321
|
summary: singleFileSummary,
|
|
312
|
-
}
|
|
322
|
+
};
|
|
313
323
|
}
|
|
314
324
|
}
|
|
315
325
|
|
|
@@ -378,12 +388,13 @@ export class GitDiffService {
|
|
|
378
388
|
filesChanged: 0,
|
|
379
389
|
});
|
|
380
390
|
|
|
381
|
-
return
|
|
391
|
+
return {
|
|
382
392
|
files: mergedFiles,
|
|
393
|
+
isGitRepo: true,
|
|
383
394
|
metaOnly: false,
|
|
384
395
|
path,
|
|
385
396
|
scope,
|
|
386
397
|
summary: isSinglePathRequest ? singleFileSummary ?? summary : summary,
|
|
387
|
-
}
|
|
398
|
+
};
|
|
388
399
|
}
|
|
389
400
|
}
|
|
@@ -1,6 +1,10 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { execFile as execFileCallback } from 'node:child_process';
|
|
2
|
+
import { access } from 'node:fs/promises';
|
|
3
|
+
import { join } from 'node:path';
|
|
4
|
+
import { promisify } from 'node:util';
|
|
5
|
+
|
|
6
|
+
import { createRequestError as createGitRequestError } from '../http/http-errors.js';
|
|
2
7
|
import { normalizeRelativeGitPath } from './path-utils.js';
|
|
3
|
-
import { GitCommandRunner } from './command-runner.js';
|
|
4
8
|
import { GitDiffService } from './diff-service.js';
|
|
5
9
|
import { GitHistoryService } from './history-service.js';
|
|
6
10
|
import { parseNameStatusOutput } from './parsers.js';
|
|
@@ -9,6 +13,8 @@ import { GitStatusService } from './status-service.js';
|
|
|
9
13
|
import { GitUntrackedFileService } from './untracked-files.js';
|
|
10
14
|
import { PullBackupStore } from '../persistence/pull-backup-store.js';
|
|
11
15
|
|
|
16
|
+
const execFile = promisify(execFileCallback);
|
|
17
|
+
|
|
12
18
|
function buildAuthorEnv(author = null) {
|
|
13
19
|
const name = String(author?.name ?? '').trim();
|
|
14
20
|
const email = String(author?.email ?? '').trim();
|
|
@@ -35,12 +41,36 @@ export class GitService {
|
|
|
35
41
|
statusCacheTtlMs = 2_000,
|
|
36
42
|
vaultDir,
|
|
37
43
|
}) {
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
+
const gitExecFile = execFileImpl ?? execFile;
|
|
45
|
+
this.commandRunner = {
|
|
46
|
+
async isGitRepo() {
|
|
47
|
+
if (!enabled) {
|
|
48
|
+
return false;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
try {
|
|
52
|
+
await access(join(vaultDir, '.git'));
|
|
53
|
+
return true;
|
|
54
|
+
} catch {
|
|
55
|
+
return false;
|
|
56
|
+
}
|
|
57
|
+
},
|
|
58
|
+
async execGit(args, { env = null } = {}) {
|
|
59
|
+
const result = await gitExecFile('git', ['-c', 'core.quotepath=false', ...args], {
|
|
60
|
+
cwd: vaultDir,
|
|
61
|
+
encoding: 'utf8',
|
|
62
|
+
env: {
|
|
63
|
+
...process.env,
|
|
64
|
+
...(commandEnv ?? {}),
|
|
65
|
+
...(env ?? {}),
|
|
66
|
+
},
|
|
67
|
+
maxBuffer: 5 * 1024 * 1024,
|
|
68
|
+
timeout: 10_000,
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
return String(result.stdout ?? '');
|
|
72
|
+
},
|
|
73
|
+
};
|
|
44
74
|
this.untrackedFileService = new GitUntrackedFileService({ vaultDir });
|
|
45
75
|
this.statusService = new GitStatusService({
|
|
46
76
|
commandRunner: this.commandRunner,
|
|
@@ -177,7 +207,7 @@ export class GitService {
|
|
|
177
207
|
throw createGitRequestError(
|
|
178
208
|
409,
|
|
179
209
|
'Cannot pull because local and remote commits have diverged; fast-forward only pull is not possible.',
|
|
180
|
-
'pull_diverged_ff_only',
|
|
210
|
+
{ requestCode: 'pull_diverged_ff_only' },
|
|
181
211
|
);
|
|
182
212
|
}
|
|
183
213
|
|
|
@@ -431,7 +461,7 @@ export class GitService {
|
|
|
431
461
|
return createGitRequestError(
|
|
432
462
|
409,
|
|
433
463
|
'Pull applied remote updates, but reapplying local changes caused conflicts. Review the conflicted files and the pull backup summary.',
|
|
434
|
-
'pull_conflicted_after_autostash',
|
|
464
|
+
{ requestCode: 'pull_conflicted_after_autostash' },
|
|
435
465
|
);
|
|
436
466
|
}
|
|
437
467
|
|