@worca/app 0.1.0 → 1.0.0-rc.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/ui/server.mjs CHANGED
@@ -1538,6 +1538,29 @@ app.get('/api/history/:key/:id/log', async (req, res) => {
1538
1538
  }
1539
1539
  });
1540
1540
 
1541
+ // ---------------------------------------------------------------------------
1542
+ // GET /api/history/:key/:id/diff -> the run's persisted diff-patch.patch, inline
1543
+ // (text/x-diff). Exists only for runs that reached done (results are built on
1544
+ // the done path only); everything else 404s and the UI shows its empty state.
1545
+ // Key validation mirrors the /log route (:1529); the artifact read follows the
1546
+ // recovery-patch route's readRunArtifactText pattern (:1408) — the log routes
1547
+ // themselves use the specialized readRunLogText. The relPath is the CONSTANT
1548
+ // DIFF_PATCH_FILE: readRunArtifactText does not guard traversal, so no route may
1549
+ // ever pass user input there.
1550
+ // ---------------------------------------------------------------------------
1551
+ app.get('/api/history/:key/:id/diff', async (req, res) => {
1552
+ if (!/^[a-z0-9][a-z0-9-]*-[0-9a-f]{8}$/.test(req.params.key)) {
1553
+ return res.status(404).json({ error: 'pipeline not found' });
1554
+ }
1555
+ try {
1556
+ const text = await readRunArtifactText(req.params.key, req.params.id, DIFF_PATCH_FILE);
1557
+ if (text == null) return res.status(404).json({ error: 'no diff' });
1558
+ res.type('text/x-diff').send(text);
1559
+ } catch (err) {
1560
+ res.status(500).json({ error: err && err.message ? err.message : String(err) });
1561
+ }
1562
+ });
1563
+
1541
1564
  // ---------------------------------------------------------------------------
1542
1565
  // DELETE /api/runs/:id?projectKey=... (or ?projectDir=...)
1543
1566
  // ARCHIVE a FINISHED pipeline: reclaims everything on disk — its store folder,
@@ -2039,6 +2062,19 @@ app.get('/api/workspaces/:id/runs/:runId/log', async (req, res) => {
2039
2062
  }
2040
2063
  });
2041
2064
 
2065
+ app.get('/api/workspaces/:id/runs/:runId/diff', async (req, res) => {
2066
+ if (!WORKSPACE_KEY_RE.test(req.params.id)) {
2067
+ return res.status(404).json({ error: 'pipeline not found' });
2068
+ }
2069
+ try {
2070
+ const text = await readRunArtifactText(`workspaces/${req.params.id}`, req.params.runId, DIFF_PATCH_FILE);
2071
+ if (text == null) return res.status(404).json({ error: 'no diff' });
2072
+ res.type('text/x-diff').send(text);
2073
+ } catch (err) {
2074
+ res.status(500).json({ error: err && err.message ? err.message : String(err) });
2075
+ }
2076
+ });
2077
+
2042
2078
  // ---------------------------------------------------------------------------
2043
2079
  // GET /api/settings -> { root, projectsRoot, projectsRootDefault, default }
2044
2080
  // root : the configured Worca CC data-root base, '' when unset