@stephenov/feedbackwidget 0.7.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 +45 -51
  2. package/dist/cli.mjs +45 -51
  3. package/package.json +1 -1
package/dist/cli.js CHANGED
@@ -91,68 +91,62 @@ async function initProject() {
91
91
  const framework = detectFramework();
92
92
  const cwd = process.cwd();
93
93
  const fullPath = framework.fullPath ? import_path.default.join(cwd, framework.fullPath) : null;
94
- const targetFile = fullPath || framework.file;
95
- const isAstro = framework.name === "Astro";
96
- const importLine = 'import { FeedbackWidget } from "@stephenov/feedbackwidget";';
97
- const componentSnippet = isAstro ? `<FeedbackWidget client:load apiKey="${apiKey}" />` : `<FeedbackWidget apiKey="${apiKey}" />`;
94
+ const scriptTag = `<script src="https://feedbackwidget-api.vercel.app/widget.js" data-api-key="${apiKey}"></script>`;
98
95
  console.log("\n\u2705 Authenticated!\n");
99
96
  if (framework.name) {
100
97
  console.log(`Detected: ${framework.name}
101
98
  `);
102
99
  }
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("STEP 1: Add the import\n");
105
- 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");
106
- console.log(`Open: ${targetFile}
107
- `);
108
- if (isAstro) {
109
- console.log("Add this inside the --- frontmatter block:\n");
110
- } else {
111
- console.log("Add this with your other imports:\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(` ${importLine}
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}
114
128
  `);
115
- await waitForEnter("Press ENTER when you've added the import...");
116
- console.log("\n\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\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");
117
- console.log("STEP 2: Add the component\n");
118
- 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");
119
- console.log(`In the same file, add this ${framework.note || "inside <body>"}:
129
+ console.log(`Run: ${framework.devCommand || "npm run dev"}
120
130
  `);
121
- console.log(` ${componentSnippet}
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");
133
+ } else {
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}
122
138
  `);
123
- try {
124
- await copyToClipboard(componentSnippet);
125
- console.log(" \u{1F4CB} Copied to clipboard!\n");
126
- } catch {
127
- }
128
- await waitForEnter("Press ENTER when you've added the component...");
129
- let verified = false;
130
- if (fullPath && import_fs.default.existsSync(fullPath)) {
131
- const content = import_fs.default.readFileSync(fullPath, "utf-8");
132
- if (content.includes("FeedbackWidget")) {
133
- verified = true;
139
+ try {
140
+ await copyToClipboard(scriptTag);
141
+ console.log(" \u{1F4CB} Copied to clipboard!\n");
142
+ } catch {
134
143
  }
135
- }
136
- if (verified) {
137
- console.log("\n\u2705 Found FeedbackWidget in your file!\n");
138
- }
139
- 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");
140
- console.log("\u{1F389} SETUP COMPLETE!\n");
141
- 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");
142
- console.log(`Run: ${framework.devCommand || "npm run dev"}
144
+ console.log(`File: ${fullPath || framework.file}
143
145
  `);
144
- console.log("Refresh your browser - the widget will appear in the bottom-right.\n");
145
- console.log("View feedback at: https://feedbackwidget-api.vercel.app/dashboard\n");
146
- }
147
- function waitForEnter(prompt) {
148
- return new Promise((resolve) => {
149
- process.stdout.write(prompt);
150
- process.stdin.setRawMode?.(false);
151
- process.stdin.resume();
152
- process.stdin.once("data", () => {
153
- resolve();
154
- });
155
- });
146
+ console.log(`Then run: ${framework.devCommand || "npm run dev"}
147
+ `);
148
+ console.log("\nView feedback at: https://feedbackwidget-api.vercel.app/dashboard\n");
149
+ }
156
150
  }
157
151
  async function whoami() {
158
152
  console.log("\nRun 'npx feedbackwidget init' to get your API key.\n");
package/dist/cli.mjs CHANGED
@@ -68,68 +68,62 @@ async function initProject() {
68
68
  const framework = detectFramework();
69
69
  const cwd = process.cwd();
70
70
  const fullPath = framework.fullPath ? path.join(cwd, framework.fullPath) : null;
71
- const targetFile = fullPath || framework.file;
72
- const isAstro = framework.name === "Astro";
73
- const importLine = 'import { FeedbackWidget } from "@stephenov/feedbackwidget";';
74
- const componentSnippet = isAstro ? `<FeedbackWidget client:load apiKey="${apiKey}" />` : `<FeedbackWidget apiKey="${apiKey}" />`;
71
+ const scriptTag = `<script src="https://feedbackwidget-api.vercel.app/widget.js" data-api-key="${apiKey}"></script>`;
75
72
  console.log("\n\u2705 Authenticated!\n");
76
73
  if (framework.name) {
77
74
  console.log(`Detected: ${framework.name}
78
75
  `);
79
76
  }
80
- 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");
81
- console.log("STEP 1: Add the import\n");
82
- 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");
83
- console.log(`Open: ${targetFile}
84
- `);
85
- if (isAstro) {
86
- console.log("Add this inside the --- frontmatter block:\n");
87
- } else {
88
- console.log("Add this with your other imports:\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(` ${importLine}
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}
91
105
  `);
92
- await waitForEnter("Press ENTER when you've added the import...");
93
- console.log("\n\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\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");
94
- console.log("STEP 2: Add the component\n");
95
- 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");
96
- console.log(`In the same file, add this ${framework.note || "inside <body>"}:
106
+ console.log(`Run: ${framework.devCommand || "npm run dev"}
97
107
  `);
98
- console.log(` ${componentSnippet}
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");
110
+ } else {
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}
99
115
  `);
100
- try {
101
- await copyToClipboard(componentSnippet);
102
- console.log(" \u{1F4CB} Copied to clipboard!\n");
103
- } catch {
104
- }
105
- await waitForEnter("Press ENTER when you've added the component...");
106
- let verified = false;
107
- if (fullPath && fs.existsSync(fullPath)) {
108
- const content = fs.readFileSync(fullPath, "utf-8");
109
- if (content.includes("FeedbackWidget")) {
110
- verified = true;
116
+ try {
117
+ await copyToClipboard(scriptTag);
118
+ console.log(" \u{1F4CB} Copied to clipboard!\n");
119
+ } catch {
111
120
  }
112
- }
113
- if (verified) {
114
- console.log("\n\u2705 Found FeedbackWidget in your file!\n");
115
- }
116
- 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");
117
- console.log("\u{1F389} SETUP COMPLETE!\n");
118
- 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");
119
- console.log(`Run: ${framework.devCommand || "npm run dev"}
121
+ console.log(`File: ${fullPath || framework.file}
120
122
  `);
121
- console.log("Refresh your browser - the widget will appear in the bottom-right.\n");
122
- console.log("View feedback at: https://feedbackwidget-api.vercel.app/dashboard\n");
123
- }
124
- function waitForEnter(prompt) {
125
- return new Promise((resolve) => {
126
- process.stdout.write(prompt);
127
- process.stdin.setRawMode?.(false);
128
- process.stdin.resume();
129
- process.stdin.once("data", () => {
130
- resolve();
131
- });
132
- });
123
+ console.log(`Then run: ${framework.devCommand || "npm run dev"}
124
+ `);
125
+ console.log("\nView feedback at: https://feedbackwidget-api.vercel.app/dashboard\n");
126
+ }
133
127
  }
134
128
  async function whoami() {
135
129
  console.log("\nRun 'npx feedbackwidget init' to get your API key.\n");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@stephenov/feedbackwidget",
3
- "version": "0.7.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",