buddy-workbench 0.2.3 → 0.2.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/server/routes/jira-filters.js +30 -2
- package/server/services/clipboard-history.js +33 -3
- package/ui/dist/assets/{index-DVXjDLbz.js → index-Djh0rmM2.js} +147 -147
- package/ui/dist/assets/{xmindAdapter-Bu9WO4K1.js → xmindAdapter-CItOM4Uh.js} +1 -1
- package/ui/dist/index.html +1 -1
- package/ui/dist/sw.js +2 -2
package/package.json
CHANGED
|
@@ -328,6 +328,31 @@ async function searchJiraWithFallbacks(jiraHost, headers, jqlCandidates, fields
|
|
|
328
328
|
return [];
|
|
329
329
|
}
|
|
330
330
|
|
|
331
|
+
async function searchJiraWithFallbacksPaginated(jiraHost, headers, jqlCandidates, fields, maxResults = 100) {
|
|
332
|
+
for (const jql of jqlCandidates) {
|
|
333
|
+
if (!jql) continue;
|
|
334
|
+
try {
|
|
335
|
+
const issues = [];
|
|
336
|
+
let startAt = 0;
|
|
337
|
+
let total = 0;
|
|
338
|
+
do {
|
|
339
|
+
const searchUrl = `https://${jiraHost}/rest/api/2/search?jql=${encodeURIComponent(jql)}&startAt=${startAt}&maxResults=${maxResults}&fields=${encodeURIComponent(fields)}`;
|
|
340
|
+
const response = await httpClient.get(searchUrl, { headers });
|
|
341
|
+
if (response.status !== 200 || !Array.isArray(response.data?.issues)) throw new Error(`Jira search returned ${response.status}`);
|
|
342
|
+
const page = response.data.issues;
|
|
343
|
+
issues.push(...page);
|
|
344
|
+
total = Number(response.data.total) || issues.length;
|
|
345
|
+
startAt += page.length;
|
|
346
|
+
if (page.length === 0) break;
|
|
347
|
+
} while (startAt < total);
|
|
348
|
+
return issues;
|
|
349
|
+
} catch {
|
|
350
|
+
// Try the next JQL form when this Jira instance does not support the current one.
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
return [];
|
|
354
|
+
}
|
|
355
|
+
|
|
331
356
|
async function fetchCommentsForIssue(jiraHost, headers, issueKey, maxResults = 50) {
|
|
332
357
|
try {
|
|
333
358
|
const url = `https://${jiraHost}/rest/api/2/issue/${encodeURIComponent(issueKey)}/comment?maxResults=${maxResults}`;
|
|
@@ -365,6 +390,9 @@ router.get('/recently-commented', async (_req, res) => {
|
|
|
365
390
|
const identity = await getJiraIdentity(jiraHost, token);
|
|
366
391
|
|
|
367
392
|
const jqlCandidates = [];
|
|
393
|
+
// This function targets issues where the current user authored a comment. The
|
|
394
|
+
// text search fallbacks below can miss comments that do not mention the author.
|
|
395
|
+
jqlCandidates.push('commentedBy(currentUser()) ORDER BY updated DESC');
|
|
368
396
|
if (identity.name) {
|
|
369
397
|
jqlCandidates.push(`comment ~ "\\"${identity.name}\\"" ORDER BY updated DESC`);
|
|
370
398
|
jqlCandidates.push(`comment ~ "${identity.name}" ORDER BY updated DESC`);
|
|
@@ -378,10 +406,10 @@ router.get('/recently-commented', async (_req, res) => {
|
|
|
378
406
|
jqlCandidates.push('(assignee = currentUser() OR reporter = currentUser() OR watcher = currentUser()) AND updated >= -60d ORDER BY updated DESC');
|
|
379
407
|
jqlCandidates.push('updated >= -60d ORDER BY updated DESC');
|
|
380
408
|
|
|
381
|
-
const issues = await
|
|
409
|
+
const issues = await searchJiraWithFallbacksPaginated(jiraHost, headers, jqlCandidates, 'summary,priority,status,updated,assignee,reporter');
|
|
382
410
|
const results = [];
|
|
383
411
|
|
|
384
|
-
const issueCommentsPromises = issues.
|
|
412
|
+
const issueCommentsPromises = issues.map(async (issue) => {
|
|
385
413
|
const key = issue.key;
|
|
386
414
|
const fields = issue.fields || {};
|
|
387
415
|
const comments = await fetchCommentsForIssue(jiraHost, headers, key, 50);
|
|
@@ -23,7 +23,10 @@ let suppressImageCaptureUntil = 0;
|
|
|
23
23
|
let swiftClipboardRetryAt = 0;
|
|
24
24
|
let mozjpegWasmModule = null;
|
|
25
25
|
let macClipboardHelper = null;
|
|
26
|
+
let macClipboardHelperStarting = false;
|
|
26
27
|
let macClipboardHelperRestartTimer = null;
|
|
28
|
+
let macClipboardHelperRestartDelay = 5000;
|
|
29
|
+
let macClipboardHelperBinary = null;
|
|
27
30
|
let macClipboardHelperWatchdog = null;
|
|
28
31
|
let macClipboardHelperExitHookRegistered = false;
|
|
29
32
|
const clipboardErrorCounts = new Map();
|
|
@@ -229,6 +232,7 @@ function handleMacClipboardHelperMessage(state, line) {
|
|
|
229
232
|
|
|
230
233
|
if (message.kind === 'ready') {
|
|
231
234
|
state.ready = true;
|
|
235
|
+
macClipboardHelperRestartDelay = 5000;
|
|
232
236
|
markClipboardSuccess('native image helper startup', 'native image helper process');
|
|
233
237
|
return;
|
|
234
238
|
}
|
|
@@ -300,7 +304,8 @@ function scheduleMacClipboardHelperRestart() {
|
|
|
300
304
|
macClipboardHelperRestartTimer = setTimeout(() => {
|
|
301
305
|
macClipboardHelperRestartTimer = null;
|
|
302
306
|
startMacClipboardImageHelper();
|
|
303
|
-
},
|
|
307
|
+
}, macClipboardHelperRestartDelay);
|
|
308
|
+
macClipboardHelperRestartDelay = Math.min(macClipboardHelperRestartDelay * 2, 5 * 60 * 1000);
|
|
304
309
|
macClipboardHelperRestartTimer.unref();
|
|
305
310
|
}
|
|
306
311
|
|
|
@@ -315,7 +320,7 @@ function stopMacClipboardImageHelper() {
|
|
|
315
320
|
}
|
|
316
321
|
|
|
317
322
|
function startMacClipboardImageHelper() {
|
|
318
|
-
if (process.platform !== 'darwin' || macClipboardHelper || macClipboardHelperRestartTimer) return;
|
|
323
|
+
if (process.platform !== 'darwin' || macClipboardHelper || macClipboardHelperStarting || macClipboardHelperRestartTimer) return;
|
|
319
324
|
const outputDirectory = join(paths.clipboardDir, 'content');
|
|
320
325
|
mkdirSync(outputDirectory, { recursive: true, mode: 0o700 });
|
|
321
326
|
try { chmodSync(outputDirectory, 0o700); } catch (error) {
|
|
@@ -323,11 +328,35 @@ function startMacClipboardImageHelper() {
|
|
|
323
328
|
return;
|
|
324
329
|
}
|
|
325
330
|
const scriptPath = fileURLToPath(new URL('./mac-clipboard-helper.swift', import.meta.url));
|
|
331
|
+
const binaryPath = macClipboardHelperBinary || join(outputDirectory, 'mac-clipboard-helper');
|
|
332
|
+
macClipboardHelperStarting = true;
|
|
333
|
+
void (async () => {
|
|
334
|
+
try {
|
|
335
|
+
if (!macClipboardHelperBinary) {
|
|
336
|
+
await execFileAsync('swiftc', ['-O', scriptPath, '-o', binaryPath], {
|
|
337
|
+
timeout: 120 * 1000,
|
|
338
|
+
maxBuffer: 10 * 1024 * 1024
|
|
339
|
+
});
|
|
340
|
+
chmodSync(binaryPath, 0o700);
|
|
341
|
+
macClipboardHelperBinary = binaryPath;
|
|
342
|
+
}
|
|
343
|
+
launchMacClipboardImageHelper(binaryPath, outputDirectory);
|
|
344
|
+
} catch (error) {
|
|
345
|
+
logClipboardError('native image helper compile', error);
|
|
346
|
+
scheduleMacClipboardHelperRestart();
|
|
347
|
+
} finally {
|
|
348
|
+
macClipboardHelperStarting = false;
|
|
349
|
+
}
|
|
350
|
+
})();
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
function launchMacClipboardImageHelper(binaryPath, outputDirectory) {
|
|
326
354
|
let child;
|
|
327
355
|
try {
|
|
328
|
-
child = spawn(
|
|
356
|
+
child = spawn(binaryPath, [outputDirectory], { stdio: ['ignore', 'pipe', 'pipe'], windowsHide: true });
|
|
329
357
|
} catch (error) {
|
|
330
358
|
logClipboardError('native image helper startup', error);
|
|
359
|
+
macClipboardHelperBinary = null;
|
|
331
360
|
scheduleMacClipboardHelperRestart();
|
|
332
361
|
return;
|
|
333
362
|
}
|
|
@@ -363,6 +392,7 @@ function startMacClipboardImageHelper() {
|
|
|
363
392
|
const details = state.stderr.trim();
|
|
364
393
|
logClipboardError('native image helper process', new Error(details || `Helper exited with code ${code ?? signal ?? 'unknown'}.`));
|
|
365
394
|
}
|
|
395
|
+
if (!state.ready) macClipboardHelperBinary = null;
|
|
366
396
|
scheduleMacClipboardHelperRestart();
|
|
367
397
|
});
|
|
368
398
|
|