@rose42/feedback-capture 0.1.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 (127) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +107 -0
  3. package/dist/clipboard.d.ts +7 -0
  4. package/dist/clipboard.d.ts.map +1 -0
  5. package/dist/clipboard.js +33 -0
  6. package/dist/clipboard.js.map +1 -0
  7. package/dist/context.d.ts +10 -0
  8. package/dist/context.d.ts.map +1 -0
  9. package/dist/context.js +7 -0
  10. package/dist/context.js.map +1 -0
  11. package/dist/crop.d.ts +61 -0
  12. package/dist/crop.d.ts.map +1 -0
  13. package/dist/crop.js +112 -0
  14. package/dist/crop.js.map +1 -0
  15. package/dist/index.d.ts +16 -0
  16. package/dist/index.d.ts.map +1 -0
  17. package/dist/index.js +11 -0
  18. package/dist/index.js.map +1 -0
  19. package/dist/plugins/comment.d.ts +11 -0
  20. package/dist/plugins/comment.d.ts.map +1 -0
  21. package/dist/plugins/comment.js +14 -0
  22. package/dist/plugins/comment.js.map +1 -0
  23. package/dist/plugins/consoleLogs.d.ts +14 -0
  24. package/dist/plugins/consoleLogs.d.ts.map +1 -0
  25. package/dist/plugins/consoleLogs.js +98 -0
  26. package/dist/plugins/consoleLogs.js.map +1 -0
  27. package/dist/plugins/core.d.ts +24 -0
  28. package/dist/plugins/core.d.ts.map +1 -0
  29. package/dist/plugins/core.js +62 -0
  30. package/dist/plugins/core.js.map +1 -0
  31. package/dist/plugins/elementTarget.d.ts +156 -0
  32. package/dist/plugins/elementTarget.d.ts.map +1 -0
  33. package/dist/plugins/elementTarget.js +537 -0
  34. package/dist/plugins/elementTarget.js.map +1 -0
  35. package/dist/plugins/frameBurst.d.ts +60 -0
  36. package/dist/plugins/frameBurst.d.ts.map +1 -0
  37. package/dist/plugins/frameBurst.js +260 -0
  38. package/dist/plugins/frameBurst.js.map +1 -0
  39. package/dist/plugins/index.d.ts +17 -0
  40. package/dist/plugins/index.d.ts.map +1 -0
  41. package/dist/plugins/index.js +9 -0
  42. package/dist/plugins/index.js.map +1 -0
  43. package/dist/plugins/pageContext.d.ts +13 -0
  44. package/dist/plugins/pageContext.d.ts.map +1 -0
  45. package/dist/plugins/pageContext.js +23 -0
  46. package/dist/plugins/pageContext.js.map +1 -0
  47. package/dist/plugins/screenshot.d.ts +34 -0
  48. package/dist/plugins/screenshot.d.ts.map +1 -0
  49. package/dist/plugins/screenshot.js +183 -0
  50. package/dist/plugins/screenshot.js.map +1 -0
  51. package/dist/plugins/version.d.ts +16 -0
  52. package/dist/plugins/version.d.ts.map +1 -0
  53. package/dist/plugins/version.js +21 -0
  54. package/dist/plugins/version.js.map +1 -0
  55. package/dist/session.d.ts +19 -0
  56. package/dist/session.d.ts.map +1 -0
  57. package/dist/session.js +18 -0
  58. package/dist/session.js.map +1 -0
  59. package/dist/source/adapters/compose.d.ts +7 -0
  60. package/dist/source/adapters/compose.d.ts.map +1 -0
  61. package/dist/source/adapters/compose.js +21 -0
  62. package/dist/source/adapters/compose.js.map +1 -0
  63. package/dist/source/adapters/createSourceResolver.d.ts +28 -0
  64. package/dist/source/adapters/createSourceResolver.d.ts.map +1 -0
  65. package/dist/source/adapters/createSourceResolver.js +59 -0
  66. package/dist/source/adapters/createSourceResolver.js.map +1 -0
  67. package/dist/source/adapters/detect.d.ts +22 -0
  68. package/dist/source/adapters/detect.d.ts.map +1 -0
  69. package/dist/source/adapters/detect.js +133 -0
  70. package/dist/source/adapters/detect.js.map +1 -0
  71. package/dist/source/adapters/index.d.ts +18 -0
  72. package/dist/source/adapters/index.d.ts.map +1 -0
  73. package/dist/source/adapters/index.js +10 -0
  74. package/dist/source/adapters/index.js.map +1 -0
  75. package/dist/source/adapters/locator.d.ts +14 -0
  76. package/dist/source/adapters/locator.d.ts.map +1 -0
  77. package/dist/source/adapters/locator.js +69 -0
  78. package/dist/source/adapters/locator.js.map +1 -0
  79. package/dist/source/adapters/next.d.ts +46 -0
  80. package/dist/source/adapters/next.d.ts.map +1 -0
  81. package/dist/source/adapters/next.js +124 -0
  82. package/dist/source/adapters/next.js.map +1 -0
  83. package/dist/source/adapters/nextFlight.d.ts +19 -0
  84. package/dist/source/adapters/nextFlight.d.ts.map +1 -0
  85. package/dist/source/adapters/nextFlight.js +80 -0
  86. package/dist/source/adapters/nextFlight.js.map +1 -0
  87. package/dist/source/adapters/qwik.d.ts +16 -0
  88. package/dist/source/adapters/qwik.d.ts.map +1 -0
  89. package/dist/source/adapters/qwik.js +49 -0
  90. package/dist/source/adapters/qwik.js.map +1 -0
  91. package/dist/source/adapters/react.d.ts +46 -0
  92. package/dist/source/adapters/react.d.ts.map +1 -0
  93. package/dist/source/adapters/react.js +201 -0
  94. package/dist/source/adapters/react.js.map +1 -0
  95. package/dist/source/adapters/svelte.d.ts +23 -0
  96. package/dist/source/adapters/svelte.d.ts.map +1 -0
  97. package/dist/source/adapters/svelte.js +64 -0
  98. package/dist/source/adapters/svelte.js.map +1 -0
  99. package/dist/source/adapters/vue.d.ts +27 -0
  100. package/dist/source/adapters/vue.d.ts.map +1 -0
  101. package/dist/source/adapters/vue.js +76 -0
  102. package/dist/source/adapters/vue.js.map +1 -0
  103. package/dist/source/locateJsx.d.ts +25 -0
  104. package/dist/source/locateJsx.d.ts.map +1 -0
  105. package/dist/source/locateJsx.js +67 -0
  106. package/dist/source/locateJsx.js.map +1 -0
  107. package/dist/source/rankSourceHierarchy.d.ts +25 -0
  108. package/dist/source/rankSourceHierarchy.d.ts.map +1 -0
  109. package/dist/source/rankSourceHierarchy.js +60 -0
  110. package/dist/source/rankSourceHierarchy.js.map +1 -0
  111. package/dist/source/reactSourceResolver.d.ts +3 -0
  112. package/dist/source/reactSourceResolver.d.ts.map +1 -0
  113. package/dist/source/reactSourceResolver.js +3 -0
  114. package/dist/source/reactSourceResolver.js.map +1 -0
  115. package/dist/source/sourceMap.d.ts +41 -0
  116. package/dist/source/sourceMap.d.ts.map +1 -0
  117. package/dist/source/sourceMap.js +235 -0
  118. package/dist/source/sourceMap.js.map +1 -0
  119. package/dist/transport.d.ts +13 -0
  120. package/dist/transport.d.ts.map +1 -0
  121. package/dist/transport.js +37 -0
  122. package/dist/transport.js.map +1 -0
  123. package/dist/types.d.ts +28 -0
  124. package/dist/types.d.ts.map +1 -0
  125. package/dist/types.js +2 -0
  126. package/dist/types.js.map +1 -0
  127. package/package.json +68 -0
@@ -0,0 +1,235 @@
1
+ import { SourceMapConsumer } from "source-map-js";
2
+ const SOURCE_MAP_COMMENT_RE = /[#@]\s*sourceMappingURL\s*=\s*(\S+)\s*$/m;
3
+ const mapCache = new Map();
4
+ const textCache = new Map();
5
+ /** Clear fetch / consumer caches (tests). */
6
+ export function clearSourceMapCaches() {
7
+ mapCache.clear();
8
+ textCache.clear();
9
+ }
10
+ async function fetchText(url, fetchFn) {
11
+ let pending = textCache.get(url);
12
+ if (!pending) {
13
+ pending = (async () => {
14
+ try {
15
+ const res = await fetchFn(url);
16
+ if (!res.ok)
17
+ return null;
18
+ return await res.text();
19
+ }
20
+ catch {
21
+ return null;
22
+ }
23
+ })();
24
+ textCache.set(url, pending);
25
+ }
26
+ return pending;
27
+ }
28
+ function parseDataUrl(dataUrl) {
29
+ const match = /^data:([^,]*?),(.*)$/s.exec(dataUrl);
30
+ if (!match)
31
+ return null;
32
+ const meta = match[1] ?? "";
33
+ const data = match[2] ?? "";
34
+ try {
35
+ if (/;base64/i.test(meta)) {
36
+ if (typeof atob !== "function")
37
+ return null;
38
+ // Percent-decode binary-ish atob output into a UTF-8 string.
39
+ const binary = atob(data);
40
+ const bytes = Uint8Array.from(binary, (c) => c.charCodeAt(0));
41
+ if (typeof TextDecoder !== "undefined") {
42
+ return new TextDecoder("utf-8").decode(bytes);
43
+ }
44
+ return binary;
45
+ }
46
+ return decodeURIComponent(data);
47
+ }
48
+ catch {
49
+ return null;
50
+ }
51
+ }
52
+ function resolveUrl(base, relative) {
53
+ try {
54
+ return new URL(relative, base).href;
55
+ }
56
+ catch {
57
+ return relative;
58
+ }
59
+ }
60
+ /**
61
+ * Strip Vite/query noise and leading `/@fs/` / protocol so agents see a
62
+ * repo-friendly path when possible.
63
+ */
64
+ export function normalizeSourcePath(fileName) {
65
+ let path = fileName;
66
+ try {
67
+ const u = new URL(fileName, "http://local.invalid");
68
+ path = u.pathname + u.hash;
69
+ }
70
+ catch {
71
+ // already a path
72
+ }
73
+ path = path.replace(/^\/@fs\//, "/");
74
+ // Drop Vite timestamp / import query if still present on path-like strings.
75
+ path = path.replace(/\?.*$/, "");
76
+ // Keep `node_modules/…` intact — do not collapse via `/src/` (Next maps
77
+ // `next/src/client/app-dir/link.tsx` which would otherwise become a fake
78
+ // app-relative `src/client/app-dir/link.tsx`).
79
+ const nmIdx = path.indexOf("/node_modules/");
80
+ if (nmIdx >= 0)
81
+ return path.slice(nmIdx + 1);
82
+ // Prefer monorepo app / package paths before a bare `/src/` suffix.
83
+ const appsIdx = path.indexOf("/apps/");
84
+ if (appsIdx >= 0)
85
+ return path.slice(appsIdx + 1);
86
+ const packagesIdx = path.indexOf("/packages/");
87
+ if (packagesIdx >= 0)
88
+ return path.slice(packagesIdx + 1);
89
+ const srcIdx = path.indexOf("/src/");
90
+ if (srcIdx >= 0)
91
+ return path.slice(srcIdx + 1);
92
+ return path.replace(/^\//, "");
93
+ }
94
+ async function loadSourceMap(generatedUrl, fetchFn) {
95
+ let pending = mapCache.get(generatedUrl);
96
+ if (!pending) {
97
+ pending = (async () => {
98
+ const sourceText = await fetchText(generatedUrl, fetchFn);
99
+ if (sourceText == null)
100
+ return null;
101
+ const comment = SOURCE_MAP_COMMENT_RE.exec(sourceText);
102
+ if (!comment?.[1])
103
+ return null;
104
+ const mapRef = comment[1];
105
+ let mapJson;
106
+ let mapUrl;
107
+ if (mapRef.startsWith("data:")) {
108
+ mapJson = parseDataUrl(mapRef);
109
+ mapUrl = generatedUrl;
110
+ }
111
+ else {
112
+ mapUrl = resolveUrl(generatedUrl, mapRef);
113
+ mapJson = await fetchText(mapUrl, fetchFn);
114
+ }
115
+ if (!mapJson)
116
+ return null;
117
+ try {
118
+ const raw = JSON.parse(mapJson);
119
+ const consumer = new SourceMapConsumer(raw);
120
+ return { consumer, mapUrl };
121
+ }
122
+ catch {
123
+ return null;
124
+ }
125
+ })();
126
+ mapCache.set(generatedUrl, pending);
127
+ }
128
+ return pending;
129
+ }
130
+ /**
131
+ * Map a generated stack position to original source via Source Map V3.
132
+ * Falls back to a normalized URL path when no map is available.
133
+ */
134
+ export async function resolveOriginalPosition(position, options = {}) {
135
+ const fetchFn = options.fetchFn ?? fetch;
136
+ const mapped = await loadSourceMap(position.url, fetchFn);
137
+ if (mapped) {
138
+ const original = mapped.consumer.originalPositionFor({
139
+ line: position.line,
140
+ column: position.column,
141
+ });
142
+ if (original.source != null && original.line != null) {
143
+ const resolvedSource = resolveUrl(mapped.mapUrl, original.source);
144
+ return {
145
+ fileName: normalizeSourcePath(resolvedSource),
146
+ line: original.line,
147
+ column: original.column ?? 0,
148
+ ...(original.name || position.name ? { name: original.name || position.name } : {}),
149
+ };
150
+ }
151
+ }
152
+ return {
153
+ fileName: normalizeSourcePath(position.url),
154
+ line: position.line,
155
+ column: position.column,
156
+ ...(position.name ? { name: position.name } : {}),
157
+ };
158
+ }
159
+ /**
160
+ * Parse V8-style stack frames into generated positions.
161
+ * Supports `at name (url:line:col)` and `at url:line:col`.
162
+ */
163
+ export function parseStackFrames(stack) {
164
+ const frames = [];
165
+ for (const line of stack.split("\n")) {
166
+ const trimmed = line.trim();
167
+ // at Foo (http://…/file.tsx:12:5) OR at http://…/file.tsx:12:5
168
+ const withName = /^at\s+(.+?)\s+\((.+):(\d+):(\d+)\)$/.exec(trimmed);
169
+ const bare = /^at\s+(.+):(\d+):(\d+)$/.exec(trimmed);
170
+ if (withName) {
171
+ const [, name, url, lineStr, colStr] = withName;
172
+ if (!url || url.startsWith("native") || url === "<anonymous>")
173
+ continue;
174
+ frames.push({
175
+ ...(name && name !== "Object.<anonymous>" ? { name } : {}),
176
+ url,
177
+ line: Number(lineStr),
178
+ column: Number(colStr),
179
+ });
180
+ continue;
181
+ }
182
+ if (bare) {
183
+ const [, url, lineStr, colStr] = bare;
184
+ if (!url || url.startsWith("native") || url === "<anonymous>")
185
+ continue;
186
+ frames.push({
187
+ url,
188
+ line: Number(lineStr),
189
+ column: Number(colStr),
190
+ });
191
+ }
192
+ }
193
+ return frames;
194
+ }
195
+ const SKIP_URL_RE = /(?:^|\/)(?:node_modules|react-dom|react\/|scheduler|chunk-|\.vite\/deps)\b/i;
196
+ /**
197
+ * Next/Turbopack serves compiled React (jsx-runtime, scheduler, …) as
198
+ * `/_next/static/chunks/*next_dist_compiled*` — no `node_modules` in the URL, so
199
+ * {@link SKIP_URL_RE} alone is not enough.
200
+ */
201
+ const SKIP_NEXT_COMPILED_CHUNK_RE = /(?:^|\/)_next\/static\/chunks\/[^/]*next_dist_compiled[^/]*$/i;
202
+ /** Prefer app frames over React / bundler internals. */
203
+ export function isAppFrame(frame) {
204
+ if (SKIP_URL_RE.test(frame.url))
205
+ return false;
206
+ if (SKIP_NEXT_COMPILED_CHUNK_RE.test(frame.url.split("?")[0] ?? frame.url)) {
207
+ return false;
208
+ }
209
+ if (frame.name && /^(?:React|Schedule|commit|renderWithHooks)/i.test(frame.name)) {
210
+ return false;
211
+ }
212
+ return true;
213
+ }
214
+ /**
215
+ * After Source Map V3, reject React / Next / package internals so callers can
216
+ * walk to the next stack frame (Next `_debugStack` often maps to jsx-runtime).
217
+ */
218
+ export function isAppSourcePath(fileName) {
219
+ const path = fileName.replace(/\\/g, "/");
220
+ if (/(?:^|\/)node_modules(?:\/|$)/i.test(path))
221
+ return false;
222
+ if (/(?:^|\/)next\/dist(?:\/|$)/i.test(path))
223
+ return false;
224
+ if (/react-jsx(?:-dev)?-runtime/i.test(path))
225
+ return false;
226
+ if (/(?:^|\/)_next\//i.test(path))
227
+ return false;
228
+ if (/\[project\]\/node_modules\//i.test(path))
229
+ return false;
230
+ // Next.js package layout (if `/src/` was collapsed before node_modules check).
231
+ if (/(?:^|\/)src\/client\/app-dir\//i.test(path))
232
+ return false;
233
+ return true;
234
+ }
235
+ //# sourceMappingURL=sourceMap.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sourceMap.js","sourceRoot":"","sources":["../../src/source/sourceMap.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,13 @@
1
+ import type { FeedbackTransport } from "./types.js";
2
+ export type HttpTransportOptions = {
3
+ /** Absolute or same-origin URL to POST the envelope JSON to. */
4
+ url: string;
5
+ /** Extra headers merged with Content-Type: application/json. */
6
+ headers?: Record<string, string>;
7
+ };
8
+ /**
9
+ * Transport that POSTs the envelope as JSON.
10
+ * Throws on non-OK responses (uses `error` field from JSON body when present).
11
+ */
12
+ export declare function createHttpTransport(options: HttpTransportOptions): FeedbackTransport;
13
+ //# sourceMappingURL=transport.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"transport.d.ts","sourceRoot":"","sources":["../src/transport.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAoB,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAEtE,MAAM,MAAM,oBAAoB,GAAG;IACjC,gEAAgE;IAChE,GAAG,EAAE,MAAM,CAAC;IACZ,gEAAgE;IAChE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAClC,CAAC;AAEF;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,oBAAoB,GAAG,iBAAiB,CA+BpF"}
@@ -0,0 +1,37 @@
1
+ /**
2
+ * Transport that POSTs the envelope as JSON.
3
+ * Throws on non-OK responses (uses `error` field from JSON body when present).
4
+ */
5
+ export function createHttpTransport(options) {
6
+ const { url, headers } = options;
7
+ return {
8
+ async send(envelope) {
9
+ const res = await fetch(url, {
10
+ method: "POST",
11
+ headers: {
12
+ "Content-Type": "application/json",
13
+ ...headers,
14
+ },
15
+ body: JSON.stringify(envelope),
16
+ });
17
+ let body = undefined;
18
+ try {
19
+ body = await res.json();
20
+ }
21
+ catch {
22
+ body = undefined;
23
+ }
24
+ if (!res.ok) {
25
+ const errMsg = body &&
26
+ typeof body === "object" &&
27
+ "error" in body &&
28
+ typeof body.error === "string"
29
+ ? body.error
30
+ : `HTTP ${res.status}`;
31
+ throw new Error(errMsg);
32
+ }
33
+ return body;
34
+ },
35
+ };
36
+ }
37
+ //# sourceMappingURL=transport.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"transport.js","sourceRoot":"","sources":["../src/transport.ts"],"names":[],"mappings":"AASA;;;GAGG;AACH,MAAM,UAAU,mBAAmB,CAAC,OAA6B;IAC/D,MAAM,EAAE,GAAG,EAAE,OAAO,EAAE,GAAG,OAAO,CAAC;IACjC,OAAO;QACL,KAAK,CAAC,IAAI,CAAC,QAA0B;YACnC,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,EAAE;gBAC3B,MAAM,EAAE,MAAM;gBACd,OAAO,EAAE;oBACP,cAAc,EAAE,kBAAkB;oBAClC,GAAG,OAAO;iBACX;gBACD,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC;aAC/B,CAAC,CAAC;YACH,IAAI,IAAI,GAAY,SAAS,CAAC;YAC9B,IAAI,CAAC;gBACH,IAAI,GAAG,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC;YAC1B,CAAC;YAAC,MAAM,CAAC;gBACP,IAAI,GAAG,SAAS,CAAC;YACnB,CAAC;YACD,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;gBACZ,MAAM,MAAM,GACV,IAAI;oBACJ,OAAO,IAAI,KAAK,QAAQ;oBACxB,OAAO,IAAI,IAAI;oBACf,OAAQ,IAA2B,CAAC,KAAK,KAAK,QAAQ;oBACpD,CAAC,CAAE,IAA0B,CAAC,KAAK;oBACnC,CAAC,CAAC,QAAQ,GAAG,CAAC,MAAM,EAAE,CAAC;gBAC3B,MAAM,IAAI,KAAK,CAAC,MAAM,CAAC,CAAC;YAC1B,CAAC;YACD,OAAO,IAAI,CAAC;QACd,CAAC;KACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,28 @@
1
+ import type { FeedbackCapturePlugin } from "./plugins/core.js";
2
+ /** Viewport metrics (used by pageContext plugin). */
3
+ export type FeedbackViewport = {
4
+ width: number;
5
+ height: number;
6
+ devicePixelRatio: number;
7
+ };
8
+ export type PluginCollectData<P> = P extends FeedbackCapturePlugin<string, infer D> ? Exclude<Awaited<D>, undefined> : never;
9
+ /** Per-plugin collect outcome under a FeedbackEnvelope key. */
10
+ export type PluginResult<T> = {
11
+ ok: true;
12
+ value: T;
13
+ } | {
14
+ ok: false;
15
+ error: string;
16
+ };
17
+ /**
18
+ * Envelope is exactly the merge of registered plugins (no base fields).
19
+ * Keys are plugin ids; values are discriminated collect results.
20
+ */
21
+ export type FeedbackEnvelope<Ps extends readonly FeedbackCapturePlugin[] = readonly FeedbackCapturePlugin[]> = {
22
+ [P in Ps[number] as P["id"]]?: PluginResult<PluginCollectData<P>>;
23
+ };
24
+ /** Pluggable sink for sending a built envelope (HTTP, Vite middleware, app API, …). */
25
+ export type FeedbackTransport = {
26
+ send: (envelope: FeedbackEnvelope) => Promise<unknown>;
27
+ };
28
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,mBAAmB,CAAC;AAE/D,qDAAqD;AACrD,MAAM,MAAM,gBAAgB,GAAG;IAC7B,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,gBAAgB,EAAE,MAAM,CAAC;CAC1B,CAAC;AAEF,MAAM,MAAM,iBAAiB,CAAC,CAAC,IAC7B,CAAC,SAAS,qBAAqB,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,SAAS,CAAC,GAAG,KAAK,CAAC;AAE5F,+DAA+D;AAC/D,MAAM,MAAM,YAAY,CAAC,CAAC,IAAI;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,KAAK,EAAE,CAAC,CAAA;CAAE,GAAG;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC;AAEpF;;;GAGG;AACH,MAAM,MAAM,gBAAgB,CAC1B,EAAE,SAAS,SAAS,qBAAqB,EAAE,GAAG,SAAS,qBAAqB,EAAE,IAC5E;KACD,CAAC,IAAI,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,YAAY,CAAC,iBAAiB,CAAC,CAAC,CAAC,CAAC;CAClE,CAAC;AAEF,uFAAuF;AACvF,MAAM,MAAM,iBAAiB,GAAG;IAC9B,IAAI,EAAE,CAAC,QAAQ,EAAE,gBAAgB,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;CACxD,CAAC"}
package/dist/types.js ADDED
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":""}
package/package.json ADDED
@@ -0,0 +1,68 @@
1
+ {
2
+ "name": "@rose42/feedback-capture",
3
+ "version": "0.1.0",
4
+ "type": "module",
5
+ "description": "Capture web app feedback (screenshot, URL, user comment, …)",
6
+ "license": "MIT",
7
+ "keywords": [
8
+ "feedback",
9
+ "screenshot",
10
+ "bug-report",
11
+ "devtools"
12
+ ],
13
+ "repository": {
14
+ "type": "git",
15
+ "url": "git+https://gitlab.com/rose42/feedback-capture.git"
16
+ },
17
+ "homepage": "https://gitlab.com/rose42/feedback-capture",
18
+ "bugs": {
19
+ "url": "https://gitlab.com/rose42/feedback-capture/-/issues"
20
+ },
21
+ "sideEffects": false,
22
+ "publishConfig": {
23
+ "access": "public"
24
+ },
25
+ "exports": {
26
+ ".": {
27
+ "types": "./dist/index.d.ts",
28
+ "import": "./dist/index.js"
29
+ }
30
+ },
31
+ "files": [
32
+ "dist"
33
+ ],
34
+ "scripts": {
35
+ "dev": "tsc -p tsconfig.build.json --watch",
36
+ "build": "rm -rf dist && tsc -p tsconfig.build.json",
37
+ "typecheck": "tsc -p tsconfig.json --noEmit",
38
+ "lint": "eslint .",
39
+ "format": "prettier --write .",
40
+ "format:check": "prettier --check .",
41
+ "test": "vitest run",
42
+ "test:watch": "vitest",
43
+ "release": "bash scripts/release.sh",
44
+ "prepublishOnly": "pnpm typecheck && pnpm lint && pnpm test && pnpm build"
45
+ },
46
+ "engines": {
47
+ "node": ">=24"
48
+ },
49
+ "packageManager": "pnpm@10.21.0",
50
+ "pnpm": {
51
+ "onlyBuiltDependencies": [
52
+ "esbuild"
53
+ ]
54
+ },
55
+ "devDependencies": {
56
+ "@eslint/js": "^9.39.1",
57
+ "eslint": "^9.39.1",
58
+ "eslint-config-prettier": "^10.1.8",
59
+ "happy-dom": "^20.0.10",
60
+ "prettier": "^3.6.2",
61
+ "typescript": "^5.9.3",
62
+ "typescript-eslint": "^8.46.4",
63
+ "vitest": "^3.2.4"
64
+ },
65
+ "dependencies": {
66
+ "source-map-js": "1.2.1"
67
+ }
68
+ }