@bitvea/feedback-toolbar 0.0.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.
Files changed (176) hide show
  1. package/README.md +262 -0
  2. package/dist/FeedbackPanel.d.ts +117 -0
  3. package/dist/FeedbackPanel.d.ts.map +1 -0
  4. package/dist/FeedbackPanel.js +622 -0
  5. package/dist/FeedbackPanel.js.map +1 -0
  6. package/dist/FeedbackToolbar.d.ts +54 -0
  7. package/dist/FeedbackToolbar.d.ts.map +1 -0
  8. package/dist/FeedbackToolbar.js +1149 -0
  9. package/dist/FeedbackToolbar.js.map +1 -0
  10. package/dist/InboxSheet.d.ts +80 -0
  11. package/dist/InboxSheet.d.ts.map +1 -0
  12. package/dist/InboxSheet.js +580 -0
  13. package/dist/InboxSheet.js.map +1 -0
  14. package/dist/PinLayer.d.ts +59 -0
  15. package/dist/PinLayer.d.ts.map +1 -0
  16. package/dist/PinLayer.js +1702 -0
  17. package/dist/PinLayer.js.map +1 -0
  18. package/dist/RichText.d.ts +6 -0
  19. package/dist/RichText.d.ts.map +1 -0
  20. package/dist/RichText.js +135 -0
  21. package/dist/RichText.js.map +1 -0
  22. package/dist/browser/entry.d.ts +3 -0
  23. package/dist/browser/entry.d.ts.map +1 -0
  24. package/dist/browser/entry.js +13 -0
  25. package/dist/browser/entry.js.map +1 -0
  26. package/dist/browser/mount.d.ts +37 -0
  27. package/dist/browser/mount.d.ts.map +1 -0
  28. package/dist/browser/mount.js +150 -0
  29. package/dist/browser/mount.js.map +1 -0
  30. package/dist/browser/toolbar.js +38 -0
  31. package/dist/browser/toolbar.js.map +7 -0
  32. package/dist/capture.d.ts +58 -0
  33. package/dist/capture.d.ts.map +1 -0
  34. package/dist/capture.js +98 -0
  35. package/dist/capture.js.map +1 -0
  36. package/dist/cli/bin.d.ts +3 -0
  37. package/dist/cli/bin.d.ts.map +1 -0
  38. package/dist/cli/bin.js +196 -0
  39. package/dist/cli/bin.js.map +1 -0
  40. package/dist/cli/fs.d.ts +16 -0
  41. package/dist/cli/fs.d.ts.map +1 -0
  42. package/dist/cli/fs.js +33 -0
  43. package/dist/cli/fs.js.map +1 -0
  44. package/dist/cli/init.d.ts +75 -0
  45. package/dist/cli/init.d.ts.map +1 -0
  46. package/dist/cli/init.js +266 -0
  47. package/dist/cli/init.js.map +1 -0
  48. package/dist/cli/register.d.ts +55 -0
  49. package/dist/cli/register.d.ts.map +1 -0
  50. package/dist/cli/register.js +84 -0
  51. package/dist/cli/register.js.map +1 -0
  52. package/dist/cli/registration.d.ts +37 -0
  53. package/dist/cli/registration.d.ts.map +1 -0
  54. package/dist/cli/registration.js +69 -0
  55. package/dist/cli/registration.js.map +1 -0
  56. package/dist/cli/strategies.d.ts +98 -0
  57. package/dist/cli/strategies.d.ts.map +1 -0
  58. package/dist/cli/strategies.js +198 -0
  59. package/dist/cli/strategies.js.map +1 -0
  60. package/dist/client.d.ts +59 -0
  61. package/dist/client.d.ts.map +1 -0
  62. package/dist/client.js +113 -0
  63. package/dist/client.js.map +1 -0
  64. package/dist/config.d.ts +92 -0
  65. package/dist/config.d.ts.map +1 -0
  66. package/dist/config.js +65 -0
  67. package/dist/config.js.map +1 -0
  68. package/dist/deepLink.d.ts +86 -0
  69. package/dist/deepLink.d.ts.map +1 -0
  70. package/dist/deepLink.js +185 -0
  71. package/dist/deepLink.js.map +1 -0
  72. package/dist/fontFace.d.ts +70 -0
  73. package/dist/fontFace.d.ts.map +1 -0
  74. package/dist/fontFace.js +88 -0
  75. package/dist/fontFace.js.map +1 -0
  76. package/dist/gating.d.ts +32 -0
  77. package/dist/gating.d.ts.map +1 -0
  78. package/dist/gating.js +49 -0
  79. package/dist/gating.js.map +1 -0
  80. package/dist/icons.d.ts +68 -0
  81. package/dist/icons.d.ts.map +1 -0
  82. package/dist/icons.js +97 -0
  83. package/dist/icons.js.map +1 -0
  84. package/dist/index.d.ts +14 -0
  85. package/dist/index.d.ts.map +1 -0
  86. package/dist/index.js +68 -0
  87. package/dist/index.js.map +1 -0
  88. package/dist/markdown.d.ts +59 -0
  89. package/dist/markdown.d.ts.map +1 -0
  90. package/dist/markdown.js +130 -0
  91. package/dist/markdown.js.map +1 -0
  92. package/dist/motion.d.ts +178 -0
  93. package/dist/motion.d.ts.map +1 -0
  94. package/dist/motion.js +302 -0
  95. package/dist/motion.js.map +1 -0
  96. package/dist/preferences.d.ts +71 -0
  97. package/dist/preferences.d.ts.map +1 -0
  98. package/dist/preferences.js +195 -0
  99. package/dist/preferences.js.map +1 -0
  100. package/dist/rasterise.d.ts +45 -0
  101. package/dist/rasterise.d.ts.map +1 -0
  102. package/dist/rasterise.js +490 -0
  103. package/dist/rasterise.js.map +1 -0
  104. package/dist/selector.d.ts +19 -0
  105. package/dist/selector.d.ts.map +1 -0
  106. package/dist/selector.js +142 -0
  107. package/dist/selector.js.map +1 -0
  108. package/dist/session.d.ts +19 -0
  109. package/dist/session.d.ts.map +1 -0
  110. package/dist/session.js +36 -0
  111. package/dist/session.js.map +1 -0
  112. package/dist/shortcut.d.ts +88 -0
  113. package/dist/shortcut.d.ts.map +1 -0
  114. package/dist/shortcut.js +149 -0
  115. package/dist/shortcut.js.map +1 -0
  116. package/dist/tokens.d.ts +709 -0
  117. package/dist/tokens.d.ts.map +1 -0
  118. package/dist/tokens.js +749 -0
  119. package/dist/tokens.js.map +1 -0
  120. package/dist/vendor/types/account.d.ts +26 -0
  121. package/dist/vendor/types/account.d.ts.map +1 -0
  122. package/dist/vendor/types/account.js +23 -0
  123. package/dist/vendor/types/account.js.map +1 -0
  124. package/dist/vendor/types/apiKey.d.ts +38 -0
  125. package/dist/vendor/types/apiKey.d.ts.map +1 -0
  126. package/dist/vendor/types/apiKey.js +36 -0
  127. package/dist/vendor/types/apiKey.js.map +1 -0
  128. package/dist/vendor/types/auth.d.ts +10 -0
  129. package/dist/vendor/types/auth.d.ts.map +1 -0
  130. package/dist/vendor/types/auth.js +15 -0
  131. package/dist/vendor/types/auth.js.map +1 -0
  132. package/dist/vendor/types/entity.d.ts +74 -0
  133. package/dist/vendor/types/entity.d.ts.map +1 -0
  134. package/dist/vendor/types/entity.js +111 -0
  135. package/dist/vendor/types/entity.js.map +1 -0
  136. package/dist/vendor/types/feedback.d.ts +285 -0
  137. package/dist/vendor/types/feedback.d.ts.map +1 -0
  138. package/dist/vendor/types/feedback.js +286 -0
  139. package/dist/vendor/types/feedback.js.map +1 -0
  140. package/dist/vendor/types/index.d.ts +14 -0
  141. package/dist/vendor/types/index.d.ts.map +1 -0
  142. package/dist/vendor/types/index.js +16 -0
  143. package/dist/vendor/types/index.js.map +1 -0
  144. package/dist/vendor/types/invite.d.ts +42 -0
  145. package/dist/vendor/types/invite.d.ts.map +1 -0
  146. package/dist/vendor/types/invite.js +30 -0
  147. package/dist/vendor/types/invite.js.map +1 -0
  148. package/dist/vendor/types/mcpToken.d.ts +38 -0
  149. package/dist/vendor/types/mcpToken.d.ts.map +1 -0
  150. package/dist/vendor/types/mcpToken.js +39 -0
  151. package/dist/vendor/types/mcpToken.js.map +1 -0
  152. package/dist/vendor/types/organization.d.ts +13 -0
  153. package/dist/vendor/types/organization.d.ts.map +1 -0
  154. package/dist/vendor/types/organization.js +12 -0
  155. package/dist/vendor/types/organization.js.map +1 -0
  156. package/dist/vendor/types/project.d.ts +73 -0
  157. package/dist/vendor/types/project.d.ts.map +1 -0
  158. package/dist/vendor/types/project.js +117 -0
  159. package/dist/vendor/types/project.js.map +1 -0
  160. package/dist/vendor/types/role.d.ts +12 -0
  161. package/dist/vendor/types/role.d.ts.map +1 -0
  162. package/dist/vendor/types/role.js +20 -0
  163. package/dist/vendor/types/role.js.map +1 -0
  164. package/dist/vendor/types/roleDefinition.d.ts +61 -0
  165. package/dist/vendor/types/roleDefinition.d.ts.map +1 -0
  166. package/dist/vendor/types/roleDefinition.js +45 -0
  167. package/dist/vendor/types/roleDefinition.js.map +1 -0
  168. package/dist/vendor/types/team.d.ts +25 -0
  169. package/dist/vendor/types/team.d.ts.map +1 -0
  170. package/dist/vendor/types/team.js +17 -0
  171. package/dist/vendor/types/team.js.map +1 -0
  172. package/dist/vendor/types/util.d.ts +39 -0
  173. package/dist/vendor/types/util.d.ts.map +1 -0
  174. package/dist/vendor/types/util.js +31 -0
  175. package/dist/vendor/types/util.js.map +1 -0
  176. package/package.json +59 -0
@@ -0,0 +1,58 @@
1
+ import { type FeedbackMetadata } from "./vendor/types/index.js";
2
+ import type { ToolbarConfig } from "./config.js";
3
+ /** Read the page context. Pure apart from reading `window`/`document`. */
4
+ export declare function captureMetadata(config: ToolbarConfig): FeedbackMetadata;
5
+ /**
6
+ * Capture the current viewport as a PNG data URL, or null when the browser
7
+ * will not produce one.
8
+ *
9
+ * ## Why this is a DOM rasteriser and not `getDisplayMedia`
10
+ *
11
+ * The product promises an *automatic* screenshot on every submission. The
12
+ * platform's own capture API cannot deliver that: `getDisplayMedia` raises the
13
+ * browser's screen/window/tab picker on every call, the grant cannot be kept,
14
+ * and `preferCurrentTab` - the hint that makes the picker a single click - is
15
+ * Chromium-only, so a reviewer on Firefox or Safari picks a surface by hand for
16
+ * every piece of feedback they file. A modal dialog in the middle of the core
17
+ * flow is not automatic; it is the thing most likely to make a reviewer stop
18
+ * filing feedback at all.
19
+ *
20
+ * Rejected alternatives:
21
+ *
22
+ * - *Keep `getDisplayMedia`, retain the stream and reuse it across
23
+ * submissions.* A retained stream keeps the browser's "sharing this tab"
24
+ * indicator lit for the whole session. Leaving a reviewer to believe they
25
+ * are still being recorded, on somebody else's staging site, to save one
26
+ * dialog, is not a trade worth making.
27
+ * - *A rasteriser dependency (html2canvas and friends).* This bundle ships
28
+ * into every reviewed preview deployment, and CLAUDE.md section 8 puts a
29
+ * 100 KB gzipped ceiling on a package without written justification.
30
+ * html2canvas is tens of kilobytes gzipped, so the ceiling is not really
31
+ * the objection - the objection is that both it and html-to-image
32
+ * reimplement the same `foreignObject` trick that `rasterise.ts` does in
33
+ * about 300 lines and 2.5 KB minified and gzipped (measured with esbuild),
34
+ * and a toolbar with no dependencies is one less thing to keep in step
35
+ * with whatever build the host app happens to have.
36
+ * - *A hybrid: rasterise by default, offer `getDisplayMedia` as an opt-in
37
+ * "capture the real pixels" button.* Tempting, but there are two submit
38
+ * surfaces (the panel and the pin composer) and the affordance would have
39
+ * to appear identically on both to avoid teaching the reviewer that a pin
40
+ * and a general report capture different things. That is worth revisiting
41
+ * when somebody actually asks for pixel-exact capture; it is not worth
42
+ * shipping speculatively.
43
+ *
44
+ * Null stays a supported outcome all the way through. `screenshot` is optional
45
+ * on the wire and nullable in the database, because losing a reviewer's words
46
+ * to a failed screenshot would be the worse trade.
47
+ */
48
+ export declare function captureScreenshot(): Promise<string | null>;
49
+ /**
50
+ * Capture ONE element the reviewer pointed at, or null.
51
+ *
52
+ * Same posture as `captureScreenshot`: a capture that cannot be produced is a
53
+ * missing picture, never a failed reply. Everything about a report is more
54
+ * useful than nothing about it, so every failure here returns null and the
55
+ * words still get sent.
56
+ */
57
+ export declare function captureElement(element: Element): Promise<string | null>;
58
+ //# sourceMappingURL=capture.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"capture.d.ts","sourceRoot":"","sources":["../src/capture.ts"],"names":[],"mappings":"AAOA,OAAO,EAA2B,KAAK,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAE/E,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAI9C,0EAA0E;AAC1E,wBAAgB,eAAe,CAAC,MAAM,EAAE,aAAa,GAAG,gBAAgB,CAgBvE;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA0CG;AACH,wBAAsB,iBAAiB,IAAI,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAQhE;AAED;;;;;;;GAOG;AACH,wBAAsB,cAAc,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAM7E"}
@@ -0,0 +1,98 @@
1
+ // What the toolbar records about the page without asking the reviewer.
2
+ //
3
+ // The whole point of this product is that a report arrives attached to the
4
+ // page, branch and commit it is about, so none of this is typed by a human and
5
+ // none of it is optional to collect. It is collected at submission time rather
6
+ // than on open, because a reviewer may have scrolled, resized or navigated in
7
+ // between.
8
+ import { SCREENSHOT_DATA_URL_MAX } from "./vendor/types/index.js";
9
+ import { currentPageUrl } from "./deepLink.js";
10
+ import { rasteriseElement, rasteriseViewport } from "./rasterise.js";
11
+ /** Read the page context. Pure apart from reading `window`/`document`. */
12
+ export function captureMetadata(config) {
13
+ return {
14
+ // The page's identity, which has no fragment at all - see the note at the
15
+ // top of deepLink.ts. Two failures this avoids: a reviewer who followed a
16
+ // deep link and then filed a report of their own would file it against a
17
+ // URL carrying our fragment, which no other surface ever queries; and a
18
+ // report filed at `/pricing#plans` would be invisible to a deep link,
19
+ // which cannot carry the host's fragment and ours at once.
20
+ pageUrl: currentPageUrl(),
21
+ viewportWidth: window.innerWidth,
22
+ viewportHeight: window.innerHeight,
23
+ userAgent: navigator.userAgent,
24
+ gitBranch: config.gitBranch,
25
+ gitCommit: config.gitCommit,
26
+ environment: config.environment,
27
+ };
28
+ }
29
+ /**
30
+ * Capture the current viewport as a PNG data URL, or null when the browser
31
+ * will not produce one.
32
+ *
33
+ * ## Why this is a DOM rasteriser and not `getDisplayMedia`
34
+ *
35
+ * The product promises an *automatic* screenshot on every submission. The
36
+ * platform's own capture API cannot deliver that: `getDisplayMedia` raises the
37
+ * browser's screen/window/tab picker on every call, the grant cannot be kept,
38
+ * and `preferCurrentTab` - the hint that makes the picker a single click - is
39
+ * Chromium-only, so a reviewer on Firefox or Safari picks a surface by hand for
40
+ * every piece of feedback they file. A modal dialog in the middle of the core
41
+ * flow is not automatic; it is the thing most likely to make a reviewer stop
42
+ * filing feedback at all.
43
+ *
44
+ * Rejected alternatives:
45
+ *
46
+ * - *Keep `getDisplayMedia`, retain the stream and reuse it across
47
+ * submissions.* A retained stream keeps the browser's "sharing this tab"
48
+ * indicator lit for the whole session. Leaving a reviewer to believe they
49
+ * are still being recorded, on somebody else's staging site, to save one
50
+ * dialog, is not a trade worth making.
51
+ * - *A rasteriser dependency (html2canvas and friends).* This bundle ships
52
+ * into every reviewed preview deployment, and CLAUDE.md section 8 puts a
53
+ * 100 KB gzipped ceiling on a package without written justification.
54
+ * html2canvas is tens of kilobytes gzipped, so the ceiling is not really
55
+ * the objection - the objection is that both it and html-to-image
56
+ * reimplement the same `foreignObject` trick that `rasterise.ts` does in
57
+ * about 300 lines and 2.5 KB minified and gzipped (measured with esbuild),
58
+ * and a toolbar with no dependencies is one less thing to keep in step
59
+ * with whatever build the host app happens to have.
60
+ * - *A hybrid: rasterise by default, offer `getDisplayMedia` as an opt-in
61
+ * "capture the real pixels" button.* Tempting, but there are two submit
62
+ * surfaces (the panel and the pin composer) and the affordance would have
63
+ * to appear identically on both to avoid teaching the reviewer that a pin
64
+ * and a general report capture different things. That is worth revisiting
65
+ * when somebody actually asks for pixel-exact capture; it is not worth
66
+ * shipping speculatively.
67
+ *
68
+ * Null stays a supported outcome all the way through. `screenshot` is optional
69
+ * on the wire and nullable in the database, because losing a reviewer's words
70
+ * to a failed screenshot would be the worse trade.
71
+ */
72
+ export async function captureScreenshot() {
73
+ try {
74
+ return await rasteriseViewport(SCREENSHOT_DATA_URL_MAX);
75
+ }
76
+ catch {
77
+ // Unsupported, blocked, or a DOM that would not serialise. All the same to
78
+ // the caller.
79
+ return null;
80
+ }
81
+ }
82
+ /**
83
+ * Capture ONE element the reviewer pointed at, or null.
84
+ *
85
+ * Same posture as `captureScreenshot`: a capture that cannot be produced is a
86
+ * missing picture, never a failed reply. Everything about a report is more
87
+ * useful than nothing about it, so every failure here returns null and the
88
+ * words still get sent.
89
+ */
90
+ export async function captureElement(element) {
91
+ try {
92
+ return await rasteriseElement(element, SCREENSHOT_DATA_URL_MAX);
93
+ }
94
+ catch {
95
+ return null;
96
+ }
97
+ }
98
+ //# sourceMappingURL=capture.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"capture.js","sourceRoot":"","sources":["../src/capture.ts"],"names":[],"mappings":"AAAA,uEAAuE;AACvE,EAAE;AACF,2EAA2E;AAC3E,+EAA+E;AAC/E,+EAA+E;AAC/E,8EAA8E;AAC9E,WAAW;AACX,OAAO,EAAE,uBAAuB,EAAyB,MAAM,eAAe,CAAC;AAG/E,OAAO,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAC5C,OAAO,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAElE,0EAA0E;AAC1E,MAAM,UAAU,eAAe,CAAC,MAAqB;IACnD,OAAO;QACL,0EAA0E;QAC1E,0EAA0E;QAC1E,yEAAyE;QACzE,wEAAwE;QACxE,sEAAsE;QACtE,2DAA2D;QAC3D,OAAO,EAAE,cAAc,EAAE;QACzB,aAAa,EAAE,MAAM,CAAC,UAAU;QAChC,cAAc,EAAE,MAAM,CAAC,WAAW;QAClC,SAAS,EAAE,SAAS,CAAC,SAAS;QAC9B,SAAS,EAAE,MAAM,CAAC,SAAS;QAC3B,SAAS,EAAE,MAAM,CAAC,SAAS;QAC3B,WAAW,EAAE,MAAM,CAAC,WAAW;KAChC,CAAC;AACJ,CAAC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA0CG;AACH,MAAM,CAAC,KAAK,UAAU,iBAAiB;IACrC,IAAI,CAAC;QACH,OAAO,MAAM,iBAAiB,CAAC,uBAAuB,CAAC,CAAC;IAC1D,CAAC;IAAC,MAAM,CAAC;QACP,2EAA2E;QAC3E,cAAc;QACd,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,CAAC,KAAK,UAAU,cAAc,CAAC,OAAgB;IACnD,IAAI,CAAC;QACH,OAAO,MAAM,gBAAgB,CAAC,OAAO,EAAE,uBAAuB,CAAC,CAAC;IAClE,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC"}
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=bin.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bin.d.ts","sourceRoot":"","sources":["../../src/cli/bin.ts"],"names":[],"mappings":""}
@@ -0,0 +1,196 @@
1
+ #!/usr/bin/env node
2
+ // The `npx @bitvea/feedback-toolbar` entry point: two commands, `init` and
3
+ // `register`.
4
+ //
5
+ // Everything of substance is in init.ts and register.ts, behind an InstallerFs
6
+ // and an injected transport respectively. This file is the part that touches
7
+ // the real disk and the real network, parses argv, and turns a thrown error
8
+ // into an exit code and a message a developer can act on.
9
+ //
10
+ // `register` is a first-class command rather than a step inside `init`,
11
+ // because two install paths need it on its own: a Next.js app runs it from its
12
+ // build (init wires it in as `prebuild`), and a script-tag install has no
13
+ // build at all and runs it once from a terminal or CI.
14
+ import { existsSync, readFileSync, writeFileSync } from "node:fs";
15
+ import { dirname, join } from "node:path";
16
+ import { mkdirSync } from "node:fs";
17
+ import { init } from "./init.js";
18
+ import { API_KEY_ENV_VAR, register } from "./register.js";
19
+ import { RegistrationError, postRegistration } from "./registration.js";
20
+ import { InjectionError, PACKAGE_NAME } from "./strategies.js";
21
+ const realFs = {
22
+ exists: (path) => existsSync(path),
23
+ readFile: (path) => readFileSync(path, "utf8"),
24
+ writeFile: (path, contents) => {
25
+ mkdirSync(dirname(path), { recursive: true });
26
+ writeFileSync(path, contents, "utf8");
27
+ },
28
+ };
29
+ const USAGE = `feedback-toolbar - BitVea Feedback installer
30
+
31
+ init Install the toolbar into the app in the current directory.
32
+ register Make sure this deployment exists as a project in the dashboard.
33
+
34
+ npx @bitvea/feedback-toolbar init --api-url https://feedback.bitvea.com
35
+ npx @bitvea/feedback-toolbar register --project-url https://myapp.com --api-key <key>
36
+
37
+ Flags
38
+
39
+ --api-url <url> BitVea Feedback backend. Falls back to
40
+ NEXT_PUBLIC_FEEDBACK_TOOLBAR_API_URL.
41
+ --project-url <url> The deployment to register. Falls back to
42
+ VERCEL_PROJECT_PRODUCTION_URL, then VERCEL_URL.
43
+ --api-key <key> Deploy key. Falls back to FEEDBACK_TOOLBAR_API_KEY,
44
+ which is the better place for it: a key on a command
45
+ line ends up in shell history and CI logs. It is never
46
+ written to disk and never reaches a browser.
47
+ --root <path> The app to work on. Defaults to the current directory.
48
+ --environment <name> init, script-tag installs only: what the injected tag
49
+ declares. Defaults to "preview", which is what makes it
50
+ mount; pass "production" to leave the tag inert.
51
+ --optional register only: report a failure and exit 0. This is
52
+ what the prebuild hook uses, so a registration problem
53
+ can never fail somebody's deploy.`;
54
+ function readFlag(argv, name) {
55
+ const withEquals = argv.find((a) => a.startsWith(`--${name}=`));
56
+ if (withEquals)
57
+ return withEquals.slice(name.length + 3);
58
+ const index = argv.indexOf(`--${name}`);
59
+ return index >= 0 ? argv[index + 1] : undefined;
60
+ }
61
+ /**
62
+ * The host app's package name, which the backend uses to name a project when
63
+ * there is no git metadata to name it from. Best effort by design: a missing
64
+ * or unreadable package.json is not a reason to refuse to register.
65
+ */
66
+ function readPackageName(root) {
67
+ const path = join(root, "package.json");
68
+ if (!existsSync(path))
69
+ return undefined;
70
+ try {
71
+ const pkg = JSON.parse(readFileSync(path, "utf8"));
72
+ return pkg.name;
73
+ }
74
+ catch {
75
+ return undefined;
76
+ }
77
+ }
78
+ async function runInit(argv) {
79
+ const apiUrl = readFlag(argv, "api-url") ??
80
+ process.env.NEXT_PUBLIC_FEEDBACK_TOOLBAR_API_URL;
81
+ if (!apiUrl) {
82
+ console.error("missing --api-url. Pass the BitVea Feedback backend URL, e.g.\n" +
83
+ " npx @bitvea/feedback-toolbar init --api-url https://feedback.bitvea.com");
84
+ return 1;
85
+ }
86
+ try {
87
+ const result = await init(realFs, {
88
+ root: readFlag(argv, "root") ?? process.cwd(),
89
+ apiUrl,
90
+ // Only needed to register the project from this machine, which is the
91
+ // exception rather than the rule: the prebuild step init writes is what
92
+ // normally registers, from a build environment that has the key.
93
+ apiKey: readFlag(argv, "api-key") ?? process.env.FEEDBACK_TOOLBAR_API_KEY,
94
+ projectUrl: readFlag(argv, "project-url"),
95
+ environment: readFlag(argv, "environment"),
96
+ registerProject: postRegistration,
97
+ env: process.env,
98
+ });
99
+ if (result.alreadyInstalled) {
100
+ console.log("Already installed. Nothing to change.");
101
+ for (const note of result.notes)
102
+ console.log(` - ${note}`);
103
+ return 0;
104
+ }
105
+ console.log(`Installed via the ${result.strategy} strategy:`);
106
+ for (const change of result.changes)
107
+ console.log(` - ${change}`);
108
+ for (const note of result.notes)
109
+ console.log(` - ${note}`);
110
+ // What is actually left to do, named. The previous sign-off ("redeploy to
111
+ // finish") was wrong in a way that cost a whole issue: the deploy key is
112
+ // a secret, it can only come from the build environment, and without it
113
+ // the prebuild step registers nothing and no project ever appears.
114
+ console.log(result.delivery === "script-tag"
115
+ ? "\nDeploy the page to finish. Nothing to install.\n" +
116
+ "Then register the project once, from a terminal or CI:\n" +
117
+ ` npx ${PACKAGE_NAME} register --api-url ${apiUrl} --project-url <url> --api-key <key>`
118
+ : "\nTwo things left:\n" +
119
+ " 1. install dependencies, commit, and deploy\n" +
120
+ ` 2. set ${API_KEY_ENV_VAR} in your hosting provider's environment variables\n` +
121
+ " (dashboard > Settings > Deploy keys)\n" +
122
+ "The build then registers this deployment itself, on every deploy. The backend\n" +
123
+ "URL needs no configuration: it is committed in package.json and in your layout.");
124
+ return 0;
125
+ }
126
+ catch (err) {
127
+ if (err instanceof InjectionError) {
128
+ console.error(`Could not install: ${err.message}`);
129
+ return 1;
130
+ }
131
+ throw err;
132
+ }
133
+ }
134
+ async function runRegister(argv) {
135
+ const root = readFlag(argv, "root") ?? process.cwd();
136
+ // See USAGE: the prebuild hook passes this so that a registration problem
137
+ // is reported and forgiven rather than failing the host app's deploy.
138
+ const optional = argv.includes("--optional");
139
+ try {
140
+ const outcome = await register({
141
+ apiUrl: readFlag(argv, "api-url"),
142
+ apiKey: readFlag(argv, "api-key"),
143
+ projectUrl: readFlag(argv, "project-url"),
144
+ packageName: readPackageName(root),
145
+ env: process.env,
146
+ registerProject: postRegistration,
147
+ });
148
+ // Two distinct successes, said differently on purpose: somebody running
149
+ // this by hand needs to know whether they just created a project, and
150
+ // somebody reading a build log needs to see that a repeat run is normal.
151
+ if (outcome.created) {
152
+ const named = outcome.projectName ? ` as "${outcome.projectName}"` : "";
153
+ console.log(`Registered ${outcome.projectUrl}${named}. It is in the dashboard now.`);
154
+ }
155
+ else {
156
+ console.log(`${outcome.projectUrl} is already registered. Nothing to do.`);
157
+ }
158
+ return 0;
159
+ }
160
+ catch (err) {
161
+ if (err instanceof RegistrationError) {
162
+ if (optional) {
163
+ console.warn(`feedback-toolbar register: skipped - ${err.message}`);
164
+ return 0;
165
+ }
166
+ console.error(`Could not register: ${err.message}`);
167
+ return 1;
168
+ }
169
+ throw err;
170
+ }
171
+ }
172
+ async function main() {
173
+ const argv = process.argv.slice(2);
174
+ const command = argv[0];
175
+ switch (command) {
176
+ case "init":
177
+ return runInit(argv);
178
+ case "register":
179
+ return runRegister(argv);
180
+ case "help":
181
+ case "--help":
182
+ case "-h":
183
+ console.log(USAGE);
184
+ return 0;
185
+ default:
186
+ console.error(USAGE);
187
+ return 1;
188
+ }
189
+ }
190
+ main().then((code) => {
191
+ process.exitCode = code;
192
+ }, (err) => {
193
+ console.error(err);
194
+ process.exitCode = 1;
195
+ });
196
+ //# sourceMappingURL=bin.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bin.js","sourceRoot":"","sources":["../../src/cli/bin.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,16 @@
1
+ export interface InstallerFs {
2
+ exists(path: string): boolean;
3
+ readFile(path: string): string;
4
+ writeFile(path: string, contents: string): void;
5
+ }
6
+ /** An in-memory tree, which is what the installer's tests run against. */
7
+ export declare class MemoryFs implements InstallerFs {
8
+ readonly files: Map<string, string>;
9
+ constructor(files?: Record<string, string>);
10
+ exists(path: string): boolean;
11
+ readFile(path: string): string;
12
+ writeFile(path: string, contents: string): void;
13
+ }
14
+ /** Join path segments with `/`, collapsing the duplicates that creep in. */
15
+ export declare function joinPath(...parts: string[]): string;
16
+ //# sourceMappingURL=fs.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fs.d.ts","sourceRoot":"","sources":["../../src/cli/fs.ts"],"names":[],"mappings":"AAOA,MAAM,WAAW,WAAW;IAC1B,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC;IAC9B,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAAC;IAC/B,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;CACjD;AAED,0EAA0E;AAC1E,qBAAa,QAAS,YAAW,WAAW;IAC1C,QAAQ,CAAC,KAAK,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;gBAExB,KAAK,GAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAM;IAI9C,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO;IAI7B,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM;IAM9B,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,IAAI;CAGhD;AAED,4EAA4E;AAC5E,wBAAgB,QAAQ,CAAC,GAAG,KAAK,EAAE,MAAM,EAAE,GAAG,MAAM,CAKnD"}
package/dist/cli/fs.js ADDED
@@ -0,0 +1,33 @@
1
+ // The filesystem the installer talks to, as an interface.
2
+ //
3
+ // The installer edits somebody else's repository, so its tests need to run
4
+ // against a tree they fully control, and a codemod tested only against the
5
+ // real disk is a codemod nobody dares change. Everything below the interface
6
+ // is a handful of thin wrappers; everything above it is pure logic.
7
+ /** An in-memory tree, which is what the installer's tests run against. */
8
+ export class MemoryFs {
9
+ files;
10
+ constructor(files = {}) {
11
+ this.files = new Map(Object.entries(files));
12
+ }
13
+ exists(path) {
14
+ return this.files.has(path);
15
+ }
16
+ readFile(path) {
17
+ const contents = this.files.get(path);
18
+ if (contents === undefined)
19
+ throw new Error(`no such file: ${path}`);
20
+ return contents;
21
+ }
22
+ writeFile(path, contents) {
23
+ this.files.set(path, contents);
24
+ }
25
+ }
26
+ /** Join path segments with `/`, collapsing the duplicates that creep in. */
27
+ export function joinPath(...parts) {
28
+ return parts
29
+ .filter((p) => p.length > 0)
30
+ .join("/")
31
+ .replace(/\/{2,}/g, "/");
32
+ }
33
+ //# sourceMappingURL=fs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fs.js","sourceRoot":"","sources":["../../src/cli/fs.ts"],"names":[],"mappings":"AAAA,0DAA0D;AAC1D,EAAE;AACF,2EAA2E;AAC3E,2EAA2E;AAC3E,6EAA6E;AAC7E,oEAAoE;AAQpE,0EAA0E;AAC1E,MAAM,OAAO,QAAQ;IACV,KAAK,CAAsB;IAEpC,YAAY,QAAgC,EAAE;QAC5C,IAAI,CAAC,KAAK,GAAG,IAAI,GAAG,CAAC,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC;IAC9C,CAAC;IAED,MAAM,CAAC,IAAY;QACjB,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IAC9B,CAAC;IAED,QAAQ,CAAC,IAAY;QACnB,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QACtC,IAAI,QAAQ,KAAK,SAAS;YAAE,MAAM,IAAI,KAAK,CAAC,iBAAiB,IAAI,EAAE,CAAC,CAAC;QACrE,OAAO,QAAQ,CAAC;IAClB,CAAC;IAED,SAAS,CAAC,IAAY,EAAE,QAAgB;QACtC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;IACjC,CAAC;CACF;AAED,4EAA4E;AAC5E,MAAM,UAAU,QAAQ,CAAC,GAAG,KAAe;IACzC,OAAO,KAAK;SACT,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC;SAC3B,IAAI,CAAC,GAAG,CAAC;SACT,OAAO,CAAC,SAAS,EAAE,GAAG,CAAC,CAAC;AAC7B,CAAC"}
@@ -0,0 +1,75 @@
1
+ import { API_URL_ENV_VAR } from "../config.js";
2
+ import { type InstallerFs } from "./fs.js";
3
+ export { API_URL_ENV_VAR };
4
+ import { type Delivery, type InjectionStrategy } from "./strategies.js";
5
+ import type { RegisterProjectTransport } from "./registration.js";
6
+ /**
7
+ * The command wired into the host app's build, and the marker that says it is
8
+ * already wired. `--optional` is load-bearing: see the comment on
9
+ * `wirePrebuild` for why a registration failure must not fail a deploy.
10
+ */
11
+ export declare const REGISTER_COMMAND = "feedback-toolbar register";
12
+ /**
13
+ * The prebuild line, with the backend URL BAKED IN.
14
+ *
15
+ * This is the second half of #11's reopened acceptance criterion, and the
16
+ * reason it reopened twice. `register` resolves its backend URL from a flag or
17
+ * from the build environment - and the build environment does not have it:
18
+ * `init` writes `NEXT_PUBLIC_FEEDBACK_TOOLBAR_API_URL` into `.env.local`,
19
+ * which create-next-app gitignores, and a plain node process does not load a
20
+ * dotenv file anyway. So on a real Vercel build the prebuild step threw "no
21
+ * backend URL", `--optional` turned that into one warning line, and no project
22
+ * ever appeared.
23
+ *
24
+ * package.json IS committed, so putting the URL here is what carries it into
25
+ * the build. It is a public URL, not a credential; the key still comes from
26
+ * `FEEDBACK_TOOLBAR_API_KEY` in the build environment and from nowhere else.
27
+ */
28
+ export declare function prebuildScript(apiUrl: string): string;
29
+ export interface InitOptions {
30
+ /** Repository root to install into. */
31
+ root: string;
32
+ /** Base URL of the BitVea Feedback backend. */
33
+ apiUrl: string;
34
+ /**
35
+ * Deploy key authorising registration. Optional: without it the install
36
+ * still happens, and only the registration step is skipped - the prebuild
37
+ * step this writes registers on the next build instead.
38
+ */
39
+ apiKey?: string;
40
+ /** Deployment URL to register the project under, when it is known. */
41
+ projectUrl?: string;
42
+ /**
43
+ * What a script-tag install declares as its environment. Ignored by the npm
44
+ * route, which reads the host build's own `NEXT_PUBLIC_VERCEL_ENV`.
45
+ */
46
+ environment?: string;
47
+ /** Injected so tests do not have to reach the network. */
48
+ registerProject?: RegisterProjectTransport;
49
+ /** Env bag, for the Vercel git metadata. Defaults to `process.env`. */
50
+ env?: Record<string, string | undefined>;
51
+ strategies?: readonly InjectionStrategy[];
52
+ }
53
+ export interface InitResult {
54
+ /** What actually changed, one line each, for the CLI to print. */
55
+ changes: string[];
56
+ /**
57
+ * Things worth saying that are not changes: a project that was already
58
+ * registered, or a registration that did not go through. These are kept
59
+ * apart from `changes` because `alreadyInstalled` is derived from that
60
+ * list, and a re-run must still report itself as a no-op even though it
61
+ * talks to the backend every time.
62
+ */
63
+ notes: string[];
64
+ /** True when nothing needed doing, which is what a re-run should report. */
65
+ alreadyInstalled: boolean;
66
+ strategy: string;
67
+ /**
68
+ * How the host app gets the code. Reported because it decides what the
69
+ * developer has to do next: an npm install needs a dependency install and a
70
+ * redeploy, a script tag needs neither.
71
+ */
72
+ delivery: Delivery;
73
+ }
74
+ export declare function init(fs: InstallerFs, options: InitOptions): Promise<InitResult>;
75
+ //# sourceMappingURL=init.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../src/cli/init.ts"],"names":[],"mappings":"AAkCA,OAAO,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC;AAC5C,OAAO,EAAY,KAAK,WAAW,EAAE,MAAM,MAAM,CAAC;AAClD,OAAO,EAAE,eAAe,EAAE,CAAC;AAE3B,OAAO,EAML,KAAK,QAAQ,EACb,KAAK,iBAAiB,EACvB,MAAM,cAAc,CAAC;AAEtB,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,gBAAgB,CAAC;AAK/D;;;;GAIG;AACH,eAAO,MAAM,gBAAgB,8BAA8B,CAAC;AAE5D;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,cAAc,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAErD;AAED,MAAM,WAAW,WAAW;IAC1B,uCAAuC;IACvC,IAAI,EAAE,MAAM,CAAC;IACb,+CAA+C;IAC/C,MAAM,EAAE,MAAM,CAAC;IACf;;;;OAIG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,sEAAsE;IACtE,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB;;;OAGG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,0DAA0D;IAC1D,eAAe,CAAC,EAAE,wBAAwB,CAAC;IAC3C,uEAAuE;IACvE,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAC;IACzC,UAAU,CAAC,EAAE,SAAS,iBAAiB,EAAE,CAAC;CAC3C;AAED,MAAM,WAAW,UAAU;IACzB,kEAAkE;IAClE,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB;;;;;;OAMG;IACH,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,4EAA4E;IAC5E,gBAAgB,EAAE,OAAO,CAAC;IAC1B,QAAQ,EAAE,MAAM,CAAC;IACjB;;;;OAIG;IACH,QAAQ,EAAE,QAAQ,CAAC;CACpB;AAED,wBAAsB,IAAI,CACxB,EAAE,EAAE,WAAW,EACf,OAAO,EAAE,WAAW,GACnB,OAAO,CAAC,UAAU,CAAC,CA4KrB"}