@zackbart/connecta 0.1.1 → 0.2.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.
Files changed (45) hide show
  1. package/CHANGELOG.md +60 -0
  2. package/dist/connectors/remote-mcp.d.ts.map +1 -1
  3. package/dist/connectors/remote-mcp.js +2 -1
  4. package/dist/connectors/remote-mcp.js.map +1 -1
  5. package/dist/execute.d.ts.map +1 -1
  6. package/dist/execute.js +7 -0
  7. package/dist/execute.js.map +1 -1
  8. package/dist/index.d.ts +2 -4
  9. package/dist/index.d.ts.map +1 -1
  10. package/dist/index.js +3 -5
  11. package/dist/index.js.map +1 -1
  12. package/dist/meta-tools.d.ts.map +1 -1
  13. package/dist/meta-tools.js +35 -0
  14. package/dist/meta-tools.js.map +1 -1
  15. package/dist/node.d.ts +20 -2
  16. package/dist/node.d.ts.map +1 -1
  17. package/dist/node.js +89 -10
  18. package/dist/node.js.map +1 -1
  19. package/dist/server.d.ts.map +1 -1
  20. package/dist/server.js +28 -9
  21. package/dist/server.js.map +1 -1
  22. package/dist/storage/file.d.ts.map +1 -1
  23. package/dist/storage/file.js +20 -1
  24. package/dist/storage/file.js.map +1 -1
  25. package/dist/types.d.ts +38 -1
  26. package/dist/types.d.ts.map +1 -1
  27. package/dist/ui.d.ts +6 -0
  28. package/dist/ui.d.ts.map +1 -1
  29. package/dist/ui.js +34 -13
  30. package/dist/ui.js.map +1 -1
  31. package/dist/version.d.ts +8 -0
  32. package/dist/version.d.ts.map +1 -0
  33. package/dist/version.js +8 -0
  34. package/dist/version.js.map +1 -0
  35. package/package.json +1 -1
  36. package/src/connectors/remote-mcp.ts +2 -1
  37. package/src/execute.ts +7 -0
  38. package/src/index.ts +7 -9
  39. package/src/meta-tools.ts +37 -0
  40. package/src/node.ts +119 -10
  41. package/src/server.ts +32 -9
  42. package/src/storage/file.ts +23 -1
  43. package/src/types.ts +41 -1
  44. package/src/ui.ts +42 -13
  45. package/src/version.ts +7 -0
package/src/ui.ts CHANGED
@@ -13,28 +13,51 @@ export const CONNECTA_FAVICON_SVG = `<svg xmlns="http://www.w3.org/2000/svg" vie
13
13
 
14
14
  interface ResolvedBranding {
15
15
  productName: string;
16
+ productUrl?: string;
16
17
  ownerName?: string;
17
18
  ownerUrl?: string;
18
19
  description: string;
20
+ /** Browser tab title and page meta name. */
21
+ pageTitle: string;
22
+ /** href for the page's icon link. */
23
+ faviconHref: string;
24
+ themeColor: string;
19
25
  }
20
26
 
21
27
  export function resolveBranding(
22
28
  branding?: ConnectaBranding,
23
29
  ): ResolvedBranding {
30
+ const productName = branding?.productName?.trim() || "Connecta";
31
+ const ownerName = branding?.ownerName?.trim();
24
32
  return {
25
- productName: branding?.productName?.trim() || "Connecta",
26
- ...(branding?.ownerName?.trim()
27
- ? { ownerName: branding.ownerName.trim() }
33
+ productName,
34
+ ...(branding?.productUrl?.trim()
35
+ ? { productUrl: branding.productUrl.trim() }
28
36
  : {}),
37
+ ...(ownerName ? { ownerName } : {}),
29
38
  ...(branding?.ownerUrl?.trim()
30
39
  ? { ownerUrl: branding.ownerUrl.trim() }
31
40
  : {}),
32
41
  description:
33
42
  branding?.description?.trim() ||
34
- "Manage the services this Connecta instance makes available to agents.",
43
+ `Manage the services this ${productName} instance makes available to agents.`,
44
+ pageTitle:
45
+ branding?.pageTitle?.trim() ||
46
+ (ownerName ? `${productName} — ${ownerName}` : productName),
47
+ faviconHref: branding?.favicon?.href?.trim() || "/favicon.svg",
48
+ themeColor: branding?.themeColor?.trim() || "#ffffff",
35
49
  };
36
50
  }
37
51
 
52
+ /**
53
+ * A JS string literal safe to inline in a <script> block. JSON.stringify alone
54
+ * leaves `/` untouched, so a value containing "</script>" would close the
55
+ * element early — operator-supplied branding still goes through here.
56
+ */
57
+ function escapeScriptString(value: string): string {
58
+ return JSON.stringify(value).replace(/\//g, "\\/");
59
+ }
60
+
38
61
  /**
39
62
  * True only for absolute `http:`/`https:` URLs. Downstream connectors control
40
63
  * their `authorizationUrl`, so a hostile/misconfigured one could hand back a
@@ -282,16 +305,21 @@ export function renderUiHtml(
282
305
  ): string {
283
306
  const auth = uiAuth ?? { kind: "bearer" as const };
284
307
  const brand = resolveBranding(branding);
285
- const title = brand.ownerName
286
- ? `${brand.productName} ${brand.ownerName}`
287
- : brand.productName;
308
+ const title = brand.pageTitle;
309
+ // Top-left corner. With an owner set it reads "<owner> <product>"; without
310
+ // one the product label stands alone. Either half links out when the
311
+ // matching URL is configured.
288
312
  const owner = brand.ownerName
289
313
  ? brand.ownerUrl
290
314
  ? `<a class="brand navlink" href="${escapeHtmlAttr(brand.ownerUrl)}">${escapeHtmlAttr(brand.ownerName)}</a>`
291
315
  : `<span class="brand">${escapeHtmlAttr(brand.ownerName)}</span>`
292
- : `<span class="brand">${escapeHtmlAttr(brand.productName)}</span>`;
316
+ : brand.productUrl
317
+ ? `<a class="brand navlink" href="${escapeHtmlAttr(brand.productUrl)}">${escapeHtmlAttr(brand.productName)}</a>`
318
+ : `<span class="brand">${escapeHtmlAttr(brand.productName)}</span>`;
293
319
  const product = brand.ownerName
294
- ? `<span class="product">${escapeHtmlAttr(brand.productName)}</span>`
320
+ ? brand.productUrl
321
+ ? `<a class="product navlink" href="${escapeHtmlAttr(brand.productUrl)}">${escapeHtmlAttr(brand.productName)}</a>`
322
+ : `<span class="product">${escapeHtmlAttr(brand.productName)}</span>`
295
323
  : "";
296
324
  const clerkScript =
297
325
  uiAuth?.kind === "clerk"
@@ -303,8 +331,9 @@ export function renderUiHtml(
303
331
  <head>
304
332
  <meta charset="utf-8">
305
333
  <meta name="viewport" content="width=device-width, initial-scale=1">
306
- <meta name="theme-color" content="#ffffff">
307
- <link rel="icon" href="/favicon.svg" type="image/svg+xml">
334
+ <meta name="theme-color" content="${escapeHtmlAttr(brand.themeColor)}">
335
+ <meta name="description" content="${escapeHtmlAttr(brand.description)}">
336
+ <link rel="icon" href="${escapeHtmlAttr(brand.faviconHref)}" type="image/svg+xml">
308
337
  <link rel="shortcut icon" href="/favicon.ico">
309
338
  <title>${escapeHtmlAttr(title)}</title>
310
339
  ${clerkScript}
@@ -620,7 +649,7 @@ ${clerkScript}
620
649
  <button id="copyMcpUrl" class="linklike" type="button">Copy URL</button>
621
650
  </div>
622
651
  </div>
623
- <p class="cap" id="serverInfo">Connecta status dashboard</p>
652
+ <p class="cap" id="serverInfo">${escapeHtmlAttr(brand.productName)} status dashboard</p>
624
653
  </div>
625
654
  </div>
626
655
  <section class="section pgrid" aria-labelledby="connectorsHeading">
@@ -745,7 +774,7 @@ async function load() {
745
774
  $("app").classList.remove("hidden");
746
775
  $("appNav").classList.remove("hidden");
747
776
  const si = DATA.serverInfo || {};
748
- $("serverInfo").textContent = (si.name || "Connecta") + " v" + (si.version || "?");
777
+ $("serverInfo").textContent = (si.name || ${escapeScriptString(brand.productName)}) + " v" + (si.version || "?");
749
778
  $("activityTab").classList.toggle("hidden", !DATA.activityEnabled);
750
779
  render();
751
780
  }
package/src/version.ts ADDED
@@ -0,0 +1,7 @@
1
+ /**
2
+ * The package version, as a Workers-safe constant — no filesystem read, no
3
+ * import assertion. `test/version.test.ts` asserts it matches package.json, so
4
+ * a bump that forgets this file fails the build rather than shipping a stale
5
+ * version to `/health` and to downstream MCP handshakes.
6
+ */
7
+ export const CONNECTA_VERSION = "0.2.0";