@stephenov/feedbackwidget 0.6.0 → 1.0.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 (3) hide show
  1. package/dist/cli.js +61 -42
  2. package/dist/cli.mjs +61 -42
  3. package/package.json +1 -1
package/dist/cli.js CHANGED
@@ -89,44 +89,63 @@ async function initProject() {
89
89
  }, 5 * 60 * 1e3);
90
90
  });
91
91
  const framework = detectFramework();
92
- const snippet = `<FeedbackWidget apiKey="${apiKey}" />`;
93
- let copied = false;
94
- try {
95
- await copyToClipboard(snippet);
96
- copied = true;
97
- } catch {
98
- }
99
- console.log("\u2705 Authenticated!\n");
100
- console.log("\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\n");
92
+ const cwd = process.cwd();
93
+ const fullPath = framework.fullPath ? import_path.default.join(cwd, framework.fullPath) : null;
94
+ const scriptTag = `<script src="https://feedbackwidget-api.vercel.app/widget.js" data-api-key="${apiKey}"></script>`;
95
+ console.log("\n\u2705 Authenticated!\n");
101
96
  if (framework.name) {
102
- console.log(` Detected: ${framework.name}
97
+ console.log(`Detected: ${framework.name}
103
98
  `);
104
99
  }
105
- console.log(" Step 1: Add the import to " + framework.file + "\n");
106
- if (framework.name === "Astro") {
107
- console.log(" ---");
108
- console.log(' import { FeedbackWidget } from "@stephenov/feedbackwidget";');
109
- console.log(" ---\n");
110
- } else {
111
- console.log(' import { FeedbackWidget } from "@stephenov/feedbackwidget"\n');
100
+ let injected = false;
101
+ if (fullPath && import_fs.default.existsSync(fullPath)) {
102
+ try {
103
+ let content = import_fs.default.readFileSync(fullPath, "utf-8");
104
+ if (content.includes("feedbackwidget-api.vercel.app/widget.js")) {
105
+ console.log("Widget already installed in this project.\n");
106
+ injected = true;
107
+ } else {
108
+ const headCloseMatch = content.match(/<\/head>/i);
109
+ if (headCloseMatch && headCloseMatch.index !== void 0) {
110
+ const insertPos = headCloseMatch.index;
111
+ const indent = " ";
112
+ content = content.slice(0, insertPos) + indent + scriptTag + "\n " + content.slice(insertPos);
113
+ import_fs.default.writeFileSync(fullPath, content, "utf-8");
114
+ const verify = import_fs.default.readFileSync(fullPath, "utf-8");
115
+ if (verify.includes("feedbackwidget-api.vercel.app/widget.js")) {
116
+ injected = true;
117
+ }
118
+ }
119
+ }
120
+ } catch (err) {
121
+ }
112
122
  }
113
- console.log(" Step 2: Add the component " + (framework.note || "inside <body>") + "\n");
114
- if (framework.name === "Astro") {
115
- console.log(` <FeedbackWidget client:load apiKey="${apiKey}" />
123
+ if (injected) {
124
+ console.log("\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\n");
125
+ console.log("\u{1F389} WIDGET INSTALLED!\n");
126
+ console.log("\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\n");
127
+ console.log(`Added to: ${fullPath}
128
+ `);
129
+ console.log(`Run: ${framework.devCommand || "npm run dev"}
116
130
  `);
131
+ console.log("Refresh your browser - the widget will appear in the bottom-right.\n");
132
+ console.log("View feedback at: https://feedbackwidget-api.vercel.app/dashboard\n");
117
133
  } else {
118
- console.log(` ${snippet}
134
+ console.log("\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\n");
135
+ console.log("Add this script tag inside <head>:\n");
136
+ console.log("\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\n");
137
+ console.log(` ${scriptTag}
119
138
  `);
120
- }
121
- console.log(" Step 3: Run your dev server\n");
122
- console.log(` ${framework.devCommand || "npm run dev"}
139
+ try {
140
+ await copyToClipboard(scriptTag);
141
+ console.log(" \u{1F4CB} Copied to clipboard!\n");
142
+ } catch {
143
+ }
144
+ console.log(`File: ${fullPath || framework.file}
145
+ `);
146
+ console.log(`Then run: ${framework.devCommand || "npm run dev"}
123
147
  `);
124
- console.log(" Step 4: Refresh browser - widget appears in bottom-right\n");
125
- console.log("\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\n");
126
- console.log(" Once the widget appears, view feedback at:");
127
- console.log(" https://feedbackwidget-api.vercel.app/dashboard\n");
128
- if (copied) {
129
- console.log(" \u{1F4CB} Snippet copied to clipboard!\n");
148
+ console.log("\nView feedback at: https://feedbackwidget-api.vercel.app/dashboard\n");
130
149
  }
131
150
  }
132
151
  async function whoami() {
@@ -200,49 +219,49 @@ function detectFramework() {
200
219
  const deps = { ...pkg.dependencies, ...pkg.devDependencies };
201
220
  if (deps.astro) {
202
221
  if (import_fs.default.existsSync(import_path.default.join(cwd, "src", "layouts", "Layout.astro"))) {
203
- return { name: "Astro", file: "src/layouts/Layout.astro", note: "inside <body>", devCommand: "npm run dev" };
222
+ return { name: "Astro", file: "src/layouts/Layout.astro", fullPath: "src/layouts/Layout.astro", note: "inside <body>", devCommand: "npm run dev" };
204
223
  }
205
224
  if (import_fs.default.existsSync(import_path.default.join(cwd, "src", "layouts", "BaseLayout.astro"))) {
206
- return { name: "Astro", file: "src/layouts/BaseLayout.astro", note: "inside <body>", devCommand: "npm run dev" };
225
+ return { name: "Astro", file: "src/layouts/BaseLayout.astro", fullPath: "src/layouts/BaseLayout.astro", note: "inside <body>", devCommand: "npm run dev" };
207
226
  }
208
227
  return { name: "Astro", file: "your main layout .astro file", note: "inside <body>", devCommand: "npm run dev" };
209
228
  }
210
229
  if (deps.next) {
211
230
  if (import_fs.default.existsSync(import_path.default.join(cwd, "app", "layout.tsx"))) {
212
- return { name: "Next.js (App Router)", file: "app/layout.tsx", note: "inside <body>, before {children}", devCommand: "npm run dev" };
231
+ return { name: "Next.js (App Router)", file: "app/layout.tsx", fullPath: "app/layout.tsx", note: "inside <body>, before {children}", devCommand: "npm run dev" };
213
232
  }
214
233
  if (import_fs.default.existsSync(import_path.default.join(cwd, "app", "layout.js"))) {
215
- return { name: "Next.js (App Router)", file: "app/layout.js", note: "inside <body>, before {children}", devCommand: "npm run dev" };
234
+ return { name: "Next.js (App Router)", file: "app/layout.js", fullPath: "app/layout.js", note: "inside <body>, before {children}", devCommand: "npm run dev" };
216
235
  }
217
236
  if (import_fs.default.existsSync(import_path.default.join(cwd, "src", "app", "layout.tsx"))) {
218
- return { name: "Next.js (App Router)", file: "src/app/layout.tsx", note: "inside <body>, before {children}", devCommand: "npm run dev" };
237
+ return { name: "Next.js (App Router)", file: "src/app/layout.tsx", fullPath: "src/app/layout.tsx", note: "inside <body>, before {children}", devCommand: "npm run dev" };
219
238
  }
220
239
  if (import_fs.default.existsSync(import_path.default.join(cwd, "pages", "_app.tsx"))) {
221
- return { name: "Next.js (Pages Router)", file: "pages/_app.tsx", note: "after <Component {...pageProps} />", devCommand: "npm run dev" };
240
+ return { name: "Next.js (Pages Router)", file: "pages/_app.tsx", fullPath: "pages/_app.tsx", note: "after <Component {...pageProps} />", devCommand: "npm run dev" };
222
241
  }
223
242
  if (import_fs.default.existsSync(import_path.default.join(cwd, "pages", "_app.js"))) {
224
- return { name: "Next.js (Pages Router)", file: "pages/_app.js", note: "after <Component {...pageProps} />", devCommand: "npm run dev" };
243
+ return { name: "Next.js (Pages Router)", file: "pages/_app.js", fullPath: "pages/_app.js", note: "after <Component {...pageProps} />", devCommand: "npm run dev" };
225
244
  }
226
245
  }
227
246
  if (deps["@remix-run/react"]) {
228
247
  if (import_fs.default.existsSync(import_path.default.join(cwd, "app", "root.tsx"))) {
229
- return { name: "Remix", file: "app/root.tsx", note: "inside <body>", devCommand: "npm run dev" };
248
+ return { name: "Remix", file: "app/root.tsx", fullPath: "app/root.tsx", note: "inside <body>", devCommand: "npm run dev" };
230
249
  }
231
250
  }
232
251
  if (deps.vite && (deps.react || deps["@vitejs/plugin-react"])) {
233
252
  if (import_fs.default.existsSync(import_path.default.join(cwd, "src", "App.tsx"))) {
234
- return { name: "Vite + React", file: "src/App.tsx", note: "at the end of your App component", devCommand: "npm run dev" };
253
+ return { name: "Vite + React", file: "src/App.tsx", fullPath: "src/App.tsx", note: "at the end of your App component", devCommand: "npm run dev" };
235
254
  }
236
255
  if (import_fs.default.existsSync(import_path.default.join(cwd, "src", "App.jsx"))) {
237
- return { name: "Vite + React", file: "src/App.jsx", note: "at the end of your App component", devCommand: "npm run dev" };
256
+ return { name: "Vite + React", file: "src/App.jsx", fullPath: "src/App.jsx", note: "at the end of your App component", devCommand: "npm run dev" };
238
257
  }
239
258
  }
240
259
  if (deps["react-scripts"]) {
241
260
  if (import_fs.default.existsSync(import_path.default.join(cwd, "src", "App.tsx"))) {
242
- return { name: "Create React App", file: "src/App.tsx", note: "at the end of your App component", devCommand: "npm start" };
261
+ return { name: "Create React App", file: "src/App.tsx", fullPath: "src/App.tsx", note: "at the end of your App component", devCommand: "npm start" };
243
262
  }
244
263
  if (import_fs.default.existsSync(import_path.default.join(cwd, "src", "App.js"))) {
245
- return { name: "Create React App", file: "src/App.js", note: "at the end of your App component", devCommand: "npm start" };
264
+ return { name: "Create React App", file: "src/App.js", fullPath: "src/App.js", note: "at the end of your App component", devCommand: "npm start" };
246
265
  }
247
266
  }
248
267
  if (deps.react) {
package/dist/cli.mjs CHANGED
@@ -66,44 +66,63 @@ async function initProject() {
66
66
  }, 5 * 60 * 1e3);
67
67
  });
68
68
  const framework = detectFramework();
69
- const snippet = `<FeedbackWidget apiKey="${apiKey}" />`;
70
- let copied = false;
71
- try {
72
- await copyToClipboard(snippet);
73
- copied = true;
74
- } catch {
75
- }
76
- console.log("\u2705 Authenticated!\n");
77
- console.log("\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\n");
69
+ const cwd = process.cwd();
70
+ const fullPath = framework.fullPath ? path.join(cwd, framework.fullPath) : null;
71
+ const scriptTag = `<script src="https://feedbackwidget-api.vercel.app/widget.js" data-api-key="${apiKey}"></script>`;
72
+ console.log("\n\u2705 Authenticated!\n");
78
73
  if (framework.name) {
79
- console.log(` Detected: ${framework.name}
74
+ console.log(`Detected: ${framework.name}
80
75
  `);
81
76
  }
82
- console.log(" Step 1: Add the import to " + framework.file + "\n");
83
- if (framework.name === "Astro") {
84
- console.log(" ---");
85
- console.log(' import { FeedbackWidget } from "@stephenov/feedbackwidget";');
86
- console.log(" ---\n");
87
- } else {
88
- console.log(' import { FeedbackWidget } from "@stephenov/feedbackwidget"\n');
77
+ let injected = false;
78
+ if (fullPath && fs.existsSync(fullPath)) {
79
+ try {
80
+ let content = fs.readFileSync(fullPath, "utf-8");
81
+ if (content.includes("feedbackwidget-api.vercel.app/widget.js")) {
82
+ console.log("Widget already installed in this project.\n");
83
+ injected = true;
84
+ } else {
85
+ const headCloseMatch = content.match(/<\/head>/i);
86
+ if (headCloseMatch && headCloseMatch.index !== void 0) {
87
+ const insertPos = headCloseMatch.index;
88
+ const indent = " ";
89
+ content = content.slice(0, insertPos) + indent + scriptTag + "\n " + content.slice(insertPos);
90
+ fs.writeFileSync(fullPath, content, "utf-8");
91
+ const verify = fs.readFileSync(fullPath, "utf-8");
92
+ if (verify.includes("feedbackwidget-api.vercel.app/widget.js")) {
93
+ injected = true;
94
+ }
95
+ }
96
+ }
97
+ } catch (err) {
98
+ }
89
99
  }
90
- console.log(" Step 2: Add the component " + (framework.note || "inside <body>") + "\n");
91
- if (framework.name === "Astro") {
92
- console.log(` <FeedbackWidget client:load apiKey="${apiKey}" />
100
+ if (injected) {
101
+ console.log("\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\n");
102
+ console.log("\u{1F389} WIDGET INSTALLED!\n");
103
+ console.log("\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\n");
104
+ console.log(`Added to: ${fullPath}
105
+ `);
106
+ console.log(`Run: ${framework.devCommand || "npm run dev"}
93
107
  `);
108
+ console.log("Refresh your browser - the widget will appear in the bottom-right.\n");
109
+ console.log("View feedback at: https://feedbackwidget-api.vercel.app/dashboard\n");
94
110
  } else {
95
- console.log(` ${snippet}
111
+ console.log("\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\n");
112
+ console.log("Add this script tag inside <head>:\n");
113
+ console.log("\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\n");
114
+ console.log(` ${scriptTag}
96
115
  `);
97
- }
98
- console.log(" Step 3: Run your dev server\n");
99
- console.log(` ${framework.devCommand || "npm run dev"}
116
+ try {
117
+ await copyToClipboard(scriptTag);
118
+ console.log(" \u{1F4CB} Copied to clipboard!\n");
119
+ } catch {
120
+ }
121
+ console.log(`File: ${fullPath || framework.file}
122
+ `);
123
+ console.log(`Then run: ${framework.devCommand || "npm run dev"}
100
124
  `);
101
- console.log(" Step 4: Refresh browser - widget appears in bottom-right\n");
102
- console.log("\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\n");
103
- console.log(" Once the widget appears, view feedback at:");
104
- console.log(" https://feedbackwidget-api.vercel.app/dashboard\n");
105
- if (copied) {
106
- console.log(" \u{1F4CB} Snippet copied to clipboard!\n");
125
+ console.log("\nView feedback at: https://feedbackwidget-api.vercel.app/dashboard\n");
107
126
  }
108
127
  }
109
128
  async function whoami() {
@@ -177,49 +196,49 @@ function detectFramework() {
177
196
  const deps = { ...pkg.dependencies, ...pkg.devDependencies };
178
197
  if (deps.astro) {
179
198
  if (fs.existsSync(path.join(cwd, "src", "layouts", "Layout.astro"))) {
180
- return { name: "Astro", file: "src/layouts/Layout.astro", note: "inside <body>", devCommand: "npm run dev" };
199
+ return { name: "Astro", file: "src/layouts/Layout.astro", fullPath: "src/layouts/Layout.astro", note: "inside <body>", devCommand: "npm run dev" };
181
200
  }
182
201
  if (fs.existsSync(path.join(cwd, "src", "layouts", "BaseLayout.astro"))) {
183
- return { name: "Astro", file: "src/layouts/BaseLayout.astro", note: "inside <body>", devCommand: "npm run dev" };
202
+ return { name: "Astro", file: "src/layouts/BaseLayout.astro", fullPath: "src/layouts/BaseLayout.astro", note: "inside <body>", devCommand: "npm run dev" };
184
203
  }
185
204
  return { name: "Astro", file: "your main layout .astro file", note: "inside <body>", devCommand: "npm run dev" };
186
205
  }
187
206
  if (deps.next) {
188
207
  if (fs.existsSync(path.join(cwd, "app", "layout.tsx"))) {
189
- return { name: "Next.js (App Router)", file: "app/layout.tsx", note: "inside <body>, before {children}", devCommand: "npm run dev" };
208
+ return { name: "Next.js (App Router)", file: "app/layout.tsx", fullPath: "app/layout.tsx", note: "inside <body>, before {children}", devCommand: "npm run dev" };
190
209
  }
191
210
  if (fs.existsSync(path.join(cwd, "app", "layout.js"))) {
192
- return { name: "Next.js (App Router)", file: "app/layout.js", note: "inside <body>, before {children}", devCommand: "npm run dev" };
211
+ return { name: "Next.js (App Router)", file: "app/layout.js", fullPath: "app/layout.js", note: "inside <body>, before {children}", devCommand: "npm run dev" };
193
212
  }
194
213
  if (fs.existsSync(path.join(cwd, "src", "app", "layout.tsx"))) {
195
- return { name: "Next.js (App Router)", file: "src/app/layout.tsx", note: "inside <body>, before {children}", devCommand: "npm run dev" };
214
+ return { name: "Next.js (App Router)", file: "src/app/layout.tsx", fullPath: "src/app/layout.tsx", note: "inside <body>, before {children}", devCommand: "npm run dev" };
196
215
  }
197
216
  if (fs.existsSync(path.join(cwd, "pages", "_app.tsx"))) {
198
- return { name: "Next.js (Pages Router)", file: "pages/_app.tsx", note: "after <Component {...pageProps} />", devCommand: "npm run dev" };
217
+ return { name: "Next.js (Pages Router)", file: "pages/_app.tsx", fullPath: "pages/_app.tsx", note: "after <Component {...pageProps} />", devCommand: "npm run dev" };
199
218
  }
200
219
  if (fs.existsSync(path.join(cwd, "pages", "_app.js"))) {
201
- return { name: "Next.js (Pages Router)", file: "pages/_app.js", note: "after <Component {...pageProps} />", devCommand: "npm run dev" };
220
+ return { name: "Next.js (Pages Router)", file: "pages/_app.js", fullPath: "pages/_app.js", note: "after <Component {...pageProps} />", devCommand: "npm run dev" };
202
221
  }
203
222
  }
204
223
  if (deps["@remix-run/react"]) {
205
224
  if (fs.existsSync(path.join(cwd, "app", "root.tsx"))) {
206
- return { name: "Remix", file: "app/root.tsx", note: "inside <body>", devCommand: "npm run dev" };
225
+ return { name: "Remix", file: "app/root.tsx", fullPath: "app/root.tsx", note: "inside <body>", devCommand: "npm run dev" };
207
226
  }
208
227
  }
209
228
  if (deps.vite && (deps.react || deps["@vitejs/plugin-react"])) {
210
229
  if (fs.existsSync(path.join(cwd, "src", "App.tsx"))) {
211
- return { name: "Vite + React", file: "src/App.tsx", note: "at the end of your App component", devCommand: "npm run dev" };
230
+ return { name: "Vite + React", file: "src/App.tsx", fullPath: "src/App.tsx", note: "at the end of your App component", devCommand: "npm run dev" };
212
231
  }
213
232
  if (fs.existsSync(path.join(cwd, "src", "App.jsx"))) {
214
- return { name: "Vite + React", file: "src/App.jsx", note: "at the end of your App component", devCommand: "npm run dev" };
233
+ return { name: "Vite + React", file: "src/App.jsx", fullPath: "src/App.jsx", note: "at the end of your App component", devCommand: "npm run dev" };
215
234
  }
216
235
  }
217
236
  if (deps["react-scripts"]) {
218
237
  if (fs.existsSync(path.join(cwd, "src", "App.tsx"))) {
219
- return { name: "Create React App", file: "src/App.tsx", note: "at the end of your App component", devCommand: "npm start" };
238
+ return { name: "Create React App", file: "src/App.tsx", fullPath: "src/App.tsx", note: "at the end of your App component", devCommand: "npm start" };
220
239
  }
221
240
  if (fs.existsSync(path.join(cwd, "src", "App.js"))) {
222
- return { name: "Create React App", file: "src/App.js", note: "at the end of your App component", devCommand: "npm start" };
241
+ return { name: "Create React App", file: "src/App.js", fullPath: "src/App.js", note: "at the end of your App component", devCommand: "npm start" };
223
242
  }
224
243
  }
225
244
  if (deps.react) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@stephenov/feedbackwidget",
3
- "version": "0.6.0",
3
+ "version": "1.0.0",
4
4
  "description": "Voice-first feedback widget with AI analysis, GitHub, and Slack integration",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",