@openparachute/hub 0.5.13-rc.35 → 0.5.13-rc.37

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@openparachute/hub",
3
- "version": "0.5.13-rc.35",
3
+ "version": "0.5.13-rc.37",
4
4
  "description": "parachute — the local hub for the Parachute ecosystem (discovery, ports, lifecycle, soon OAuth).",
5
5
  "license": "AGPL-3.0",
6
6
  "publishConfig": {
@@ -13,6 +13,25 @@ describe("renderHub", () => {
13
13
  expect(html).toContain("<script>");
14
14
  });
15
15
 
16
+ test("inline <script> body parses as valid JS (regression: hub#366)", () => {
17
+ // The script lives inside HTML_TEMPLATE — a backtick template literal.
18
+ // Backslash escapes inside the template silently mangle regex literals:
19
+ // `/\/+$/` written in the source becomes `//+$/` in the served HTML,
20
+ // which JS parses as the start of a line comment, killing the entire
21
+ // IIFE. Every section that renders inside that IIFE (Get started,
22
+ // Services, Admin) then never paints.
23
+ //
24
+ // Content assertions don't catch this — they pass on the broken
25
+ // string. A parse-check via `new Function(body)` does: it parses
26
+ // (no execution, no DOM needed) and throws SyntaxError on the bad
27
+ // regex. Wrap in a try/catch so future template-escaping regressions
28
+ // surface here with a clear message rather than as a runtime mystery.
29
+ const m = html.match(/<script>([\s\S]*?)<\/script>/);
30
+ const scriptBody = m?.[1];
31
+ expect(scriptBody).toBeDefined();
32
+ expect(() => new Function(scriptBody as string)).not.toThrow();
33
+ });
34
+
16
35
  test("fetches /.well-known/parachute.json for the Use section", () => {
17
36
  expect(html).toContain("/.well-known/parachute.json");
18
37
  expect(html).toContain("doc.services");
package/src/hub.ts CHANGED
@@ -496,7 +496,11 @@ const HTML_TEMPLATE = `<!doctype html>
496
496
  // firstVaultName() shape.
497
497
  let vaultName = 'default';
498
498
  if (typeof vault.path === 'string' && vault.path.startsWith('/vault/')) {
499
- const tail = vault.path.slice('/vault/'.length).replace(/\/+$/, '');
499
+ // Character class for the slash so the template literal can't eat
500
+ // the backslash-escape — \/ collapses to / inside backticks, and
501
+ // /\/+$/ degenerates to a // line comment that breaks the whole
502
+ // IIFE. [/]+$ keeps the same semantics with no escape needed.
503
+ const tail = vault.path.slice('/vault/'.length).replace(/[/]+$/, '');
500
504
  if (tail.length > 0) vaultName = tail;
501
505
  }
502
506
  tiles.push({