@mhosaic/feedback-cli 0.3.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.
package/dist/bin.js ADDED
@@ -0,0 +1,36 @@
1
+ #!/usr/bin/env node
2
+
3
+ // src/bin.ts
4
+ async function main() {
5
+ const [, , cmd, ...args] = process.argv;
6
+ if (!cmd || cmd === "init") {
7
+ const { runInit } = await import("./init-6I2XNWE7.js");
8
+ return runInit(args);
9
+ }
10
+ if (cmd === "doctor") {
11
+ const { runDoctor } = await import("./doctor-HTTAR4ZB.js");
12
+ return runDoctor(args);
13
+ }
14
+ if (cmd === "eject") {
15
+ const { runEject } = await import("./eject-VNJVOCQM.js");
16
+ return runEject(args);
17
+ }
18
+ if (cmd === "--version" || cmd === "-v") {
19
+ process.stdout.write("0.3.0\n");
20
+ return;
21
+ }
22
+ process.stderr.write(`Unknown command: ${cmd}
23
+
24
+ Usage:
25
+ mhosaic-feedback init
26
+ mhosaic-feedback doctor
27
+ mhosaic-feedback eject
28
+ `);
29
+ process.exitCode = 1;
30
+ }
31
+ main().catch((err) => {
32
+ process.stderr.write(`${err instanceof Error ? err.message : String(err)}
33
+ `);
34
+ process.exitCode = 1;
35
+ });
36
+ //# sourceMappingURL=bin.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/bin.ts"],"sourcesContent":["async function main() {\n const [, , cmd, ...args] = process.argv\n if (!cmd || cmd === 'init') {\n const { runInit } = await import('./commands/init')\n return runInit(args)\n }\n if (cmd === 'doctor') {\n const { runDoctor } = await import('./commands/doctor')\n return runDoctor(args)\n }\n if (cmd === 'eject') {\n const { runEject } = await import('./commands/eject')\n return runEject(args)\n }\n if (cmd === '--version' || cmd === '-v') {\n process.stdout.write('0.3.0\\n')\n return\n }\n process.stderr.write(`Unknown command: ${cmd}\\n\\nUsage:\\n mhosaic-feedback init\\n mhosaic-feedback doctor\\n mhosaic-feedback eject\\n`)\n process.exitCode = 1\n}\n\nmain().catch((err) => {\n process.stderr.write(`${err instanceof Error ? err.message : String(err)}\\n`)\n process.exitCode = 1\n})\n"],"mappings":";;;AAAA,eAAe,OAAO;AACpB,QAAM,CAAC,EAAE,EAAE,KAAK,GAAG,IAAI,IAAI,QAAQ;AACnC,MAAI,CAAC,OAAO,QAAQ,QAAQ;AAC1B,UAAM,EAAE,QAAQ,IAAI,MAAM,OAAO,oBAAiB;AAClD,WAAO,QAAQ,IAAI;AAAA,EACrB;AACA,MAAI,QAAQ,UAAU;AACpB,UAAM,EAAE,UAAU,IAAI,MAAM,OAAO,sBAAmB;AACtD,WAAO,UAAU,IAAI;AAAA,EACvB;AACA,MAAI,QAAQ,SAAS;AACnB,UAAM,EAAE,SAAS,IAAI,MAAM,OAAO,qBAAkB;AACpD,WAAO,SAAS,IAAI;AAAA,EACtB;AACA,MAAI,QAAQ,eAAe,QAAQ,MAAM;AACvC,YAAQ,OAAO,MAAM,SAAS;AAC9B;AAAA,EACF;AACA,UAAQ,OAAO,MAAM,oBAAoB,GAAG;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,CAA4F;AACxI,UAAQ,WAAW;AACrB;AAEA,KAAK,EAAE,MAAM,CAAC,QAAQ;AACpB,UAAQ,OAAO,MAAM,GAAG,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,CAAC;AAAA,CAAI;AAC5E,UAAQ,WAAW;AACrB,CAAC;","names":[]}
@@ -0,0 +1,26 @@
1
+ #!/usr/bin/env node
2
+
3
+ // src/detect.ts
4
+ import { readFile } from "fs/promises";
5
+ import { join } from "path";
6
+ function detectFromPackage(pkg) {
7
+ const deps = { ...pkg.dependencies ?? {}, ...pkg.devDependencies ?? {} };
8
+ if (deps.next) return { kind: "nextjs", entry: "app/layout.tsx" };
9
+ if (deps["@remix-run/react"]) return { kind: "remix", entry: "app/root.tsx" };
10
+ if (deps["react-scripts"]) return { kind: "cra", entry: "src/index.tsx" };
11
+ if (deps.vite && (deps.react || deps["@vitejs/plugin-react"])) return { kind: "vite-react", entry: "src/main.tsx" };
12
+ return { kind: "unknown", entry: null };
13
+ }
14
+ async function detectFramework(cwd) {
15
+ try {
16
+ const raw = await readFile(join(cwd, "package.json"), "utf8");
17
+ return detectFromPackage(JSON.parse(raw));
18
+ } catch {
19
+ return { kind: "plain", entry: null };
20
+ }
21
+ }
22
+
23
+ export {
24
+ detectFramework
25
+ };
26
+ //# sourceMappingURL=chunk-COJ75KUD.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/detect.ts"],"sourcesContent":["import { readFile } from 'node:fs/promises'\nimport { join } from 'node:path'\n\nexport type Framework =\n | { kind: 'vite-react'; entry: string }\n | { kind: 'nextjs'; entry: string }\n | { kind: 'remix'; entry: string }\n | { kind: 'cra'; entry: string }\n | { kind: 'plain'; entry: null }\n | { kind: 'unknown'; entry: null }\n\nexport interface PackageShape {\n dependencies?: Record<string, string>\n devDependencies?: Record<string, string>\n}\n\nexport function detectFromPackage(pkg: PackageShape): Framework {\n const deps = { ...(pkg.dependencies ?? {}), ...(pkg.devDependencies ?? {}) }\n if (deps.next) return { kind: 'nextjs', entry: 'app/layout.tsx' }\n if (deps['@remix-run/react']) return { kind: 'remix', entry: 'app/root.tsx' }\n if (deps['react-scripts']) return { kind: 'cra', entry: 'src/index.tsx' }\n if (deps.vite && (deps.react || deps['@vitejs/plugin-react'])) return { kind: 'vite-react', entry: 'src/main.tsx' }\n return { kind: 'unknown', entry: null }\n}\n\nexport async function detectFramework(cwd: string): Promise<Framework> {\n try {\n const raw = await readFile(join(cwd, 'package.json'), 'utf8')\n return detectFromPackage(JSON.parse(raw))\n } catch {\n return { kind: 'plain', entry: null }\n }\n}\n"],"mappings":";;;AAAA,SAAS,gBAAgB;AACzB,SAAS,YAAY;AAed,SAAS,kBAAkB,KAA8B;AAC9D,QAAM,OAAO,EAAE,GAAI,IAAI,gBAAgB,CAAC,GAAI,GAAI,IAAI,mBAAmB,CAAC,EAAG;AAC3E,MAAI,KAAK,KAAM,QAAO,EAAE,MAAM,UAAU,OAAO,iBAAiB;AAChE,MAAI,KAAK,kBAAkB,EAAG,QAAO,EAAE,MAAM,SAAS,OAAO,eAAe;AAC5E,MAAI,KAAK,eAAe,EAAG,QAAO,EAAE,MAAM,OAAO,OAAO,gBAAgB;AACxE,MAAI,KAAK,SAAS,KAAK,SAAS,KAAK,sBAAsB,GAAI,QAAO,EAAE,MAAM,cAAc,OAAO,eAAe;AAClH,SAAO,EAAE,MAAM,WAAW,OAAO,KAAK;AACxC;AAEA,eAAsB,gBAAgB,KAAiC;AACrE,MAAI;AACF,UAAM,MAAM,MAAM,SAAS,KAAK,KAAK,cAAc,GAAG,MAAM;AAC5D,WAAO,kBAAkB,KAAK,MAAM,GAAG,CAAC;AAAA,EAC1C,QAAQ;AACN,WAAO,EAAE,MAAM,SAAS,OAAO,KAAK;AAAA,EACtC;AACF;","names":[]}
@@ -0,0 +1,42 @@
1
+ #!/usr/bin/env node
2
+ import {
3
+ detectFramework
4
+ } from "./chunk-COJ75KUD.js";
5
+
6
+ // src/commands/doctor.ts
7
+ import { existsSync, readFileSync } from "fs";
8
+ import { join } from "path";
9
+ import kleur from "kleur";
10
+ async function runDoctor(argv) {
11
+ const cwd = argv.includes("--cwd") ? argv[argv.indexOf("--cwd") + 1] ?? process.cwd() : process.cwd();
12
+ const checks = [];
13
+ const framework = await detectFramework(cwd);
14
+ checks.push({ name: `framework detected: ${framework.kind}`, ok: framework.kind !== "unknown" && framework.kind !== "plain" });
15
+ const envPath = join(cwd, ".env.local");
16
+ const envOk = existsSync(envPath) && readFileSync(envPath, "utf8").includes("VITE_FEEDBACK_API_KEY=");
17
+ checks.push({ name: ".env.local has VITE_FEEDBACK_API_KEY", ok: envOk, hint: "run `mhosaic-feedback init`" });
18
+ const giPath = join(cwd, ".gitignore");
19
+ const giOk = existsSync(giPath) && readFileSync(giPath, "utf8").includes(".env.local");
20
+ checks.push({ name: ".gitignore ignores .env.local", ok: giOk, hint: "add `.env.local` to .gitignore" });
21
+ let wrapOk = false;
22
+ if (framework.entry) {
23
+ const entryPath = join(cwd, framework.entry);
24
+ if (existsSync(entryPath)) {
25
+ const src = readFileSync(entryPath, "utf8");
26
+ wrapOk = src.includes("<FeedbackProvider") && src.includes("@mhosaic/feedback/react");
27
+ }
28
+ }
29
+ checks.push({ name: "<FeedbackProvider> wired in entry", ok: wrapOk, hint: "run `mhosaic-feedback init`" });
30
+ let hasFailure = false;
31
+ for (const c of checks) {
32
+ const icon = c.ok ? kleur.green("\u2713") : kleur.red("\u2717");
33
+ process.stdout.write(`${icon} ${c.name}${!c.ok && c.hint ? kleur.gray(" \u2014 " + c.hint) : ""}
34
+ `);
35
+ if (!c.ok) hasFailure = true;
36
+ }
37
+ if (hasFailure) process.exitCode = 1;
38
+ }
39
+ export {
40
+ runDoctor
41
+ };
42
+ //# sourceMappingURL=doctor-HTTAR4ZB.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/commands/doctor.ts"],"sourcesContent":["import { existsSync, readFileSync } from 'node:fs'\nimport { join } from 'node:path'\n\nimport kleur from 'kleur'\n\nimport { detectFramework } from '../detect'\n\nexport async function runDoctor(argv: string[]): Promise<void> {\n const cwd = argv.includes('--cwd') ? argv[argv.indexOf('--cwd') + 1] ?? process.cwd() : process.cwd()\n\n const checks: Array<{ name: string; ok: boolean; hint?: string }> = []\n\n const framework = await detectFramework(cwd)\n checks.push({ name: `framework detected: ${framework.kind}`, ok: framework.kind !== 'unknown' && framework.kind !== 'plain' })\n\n const envPath = join(cwd, '.env.local')\n const envOk = existsSync(envPath) && readFileSync(envPath, 'utf8').includes('VITE_FEEDBACK_API_KEY=')\n checks.push({ name: '.env.local has VITE_FEEDBACK_API_KEY', ok: envOk, hint: 'run `mhosaic-feedback init`' })\n\n const giPath = join(cwd, '.gitignore')\n const giOk = existsSync(giPath) && readFileSync(giPath, 'utf8').includes('.env.local')\n checks.push({ name: '.gitignore ignores .env.local', ok: giOk, hint: 'add `.env.local` to .gitignore' })\n\n let wrapOk = false\n if (framework.entry) {\n const entryPath = join(cwd, framework.entry)\n if (existsSync(entryPath)) {\n const src = readFileSync(entryPath, 'utf8')\n wrapOk = src.includes('<FeedbackProvider') && src.includes(\"@mhosaic/feedback/react\")\n }\n }\n checks.push({ name: '<FeedbackProvider> wired in entry', ok: wrapOk, hint: 'run `mhosaic-feedback init`' })\n\n let hasFailure = false\n for (const c of checks) {\n const icon = c.ok ? kleur.green('✓') : kleur.red('✗')\n process.stdout.write(`${icon} ${c.name}${!c.ok && c.hint ? kleur.gray(' — ' + c.hint) : ''}\\n`)\n if (!c.ok) hasFailure = true\n }\n if (hasFailure) process.exitCode = 1\n}\n"],"mappings":";;;;;;AAAA,SAAS,YAAY,oBAAoB;AACzC,SAAS,YAAY;AAErB,OAAO,WAAW;AAIlB,eAAsB,UAAU,MAA+B;AAC7D,QAAM,MAAM,KAAK,SAAS,OAAO,IAAI,KAAK,KAAK,QAAQ,OAAO,IAAI,CAAC,KAAK,QAAQ,IAAI,IAAI,QAAQ,IAAI;AAEpG,QAAM,SAA8D,CAAC;AAErE,QAAM,YAAY,MAAM,gBAAgB,GAAG;AAC3C,SAAO,KAAK,EAAE,MAAM,uBAAuB,UAAU,IAAI,IAAI,IAAI,UAAU,SAAS,aAAa,UAAU,SAAS,QAAQ,CAAC;AAE7H,QAAM,UAAU,KAAK,KAAK,YAAY;AACtC,QAAM,QAAQ,WAAW,OAAO,KAAK,aAAa,SAAS,MAAM,EAAE,SAAS,wBAAwB;AACpG,SAAO,KAAK,EAAE,MAAM,wCAAwC,IAAI,OAAO,MAAM,8BAA8B,CAAC;AAE5G,QAAM,SAAS,KAAK,KAAK,YAAY;AACrC,QAAM,OAAO,WAAW,MAAM,KAAK,aAAa,QAAQ,MAAM,EAAE,SAAS,YAAY;AACrF,SAAO,KAAK,EAAE,MAAM,iCAAiC,IAAI,MAAM,MAAM,iCAAiC,CAAC;AAEvG,MAAI,SAAS;AACb,MAAI,UAAU,OAAO;AACnB,UAAM,YAAY,KAAK,KAAK,UAAU,KAAK;AAC3C,QAAI,WAAW,SAAS,GAAG;AACzB,YAAM,MAAM,aAAa,WAAW,MAAM;AAC1C,eAAS,IAAI,SAAS,mBAAmB,KAAK,IAAI,SAAS,yBAAyB;AAAA,IACtF;AAAA,EACF;AACA,SAAO,KAAK,EAAE,MAAM,qCAAqC,IAAI,QAAQ,MAAM,8BAA8B,CAAC;AAE1G,MAAI,aAAa;AACjB,aAAW,KAAK,QAAQ;AACtB,UAAM,OAAO,EAAE,KAAK,MAAM,MAAM,QAAG,IAAI,MAAM,IAAI,QAAG;AACpD,YAAQ,OAAO,MAAM,GAAG,IAAI,IAAI,EAAE,IAAI,GAAG,CAAC,EAAE,MAAM,EAAE,OAAO,MAAM,KAAK,aAAQ,EAAE,IAAI,IAAI,EAAE;AAAA,CAAI;AAC9F,QAAI,CAAC,EAAE,GAAI,cAAa;AAAA,EAC1B;AACA,MAAI,WAAY,SAAQ,WAAW;AACrC;","names":[]}
@@ -0,0 +1,40 @@
1
+ #!/usr/bin/env node
2
+ import {
3
+ detectFramework
4
+ } from "./chunk-COJ75KUD.js";
5
+
6
+ // src/commands/eject.ts
7
+ import { existsSync, readFileSync } from "fs";
8
+ import { writeFile } from "fs/promises";
9
+ import { join } from "path";
10
+ import kleur from "kleur";
11
+ async function runEject(argv) {
12
+ const cwd = argv.includes("--cwd") ? argv[argv.indexOf("--cwd") + 1] ?? process.cwd() : process.cwd();
13
+ const framework = await detectFramework(cwd);
14
+ if (framework.entry) {
15
+ const entryPath = join(cwd, framework.entry);
16
+ if (existsSync(entryPath)) {
17
+ const src = readFileSync(entryPath, "utf8");
18
+ const stripped = src.replace(/\/\/ === mhosaic-feedback:import:start ===[\s\S]*?\/\/ === mhosaic-feedback:import:end ===\n?/g, "").replace(/\{\/\* === mhosaic-feedback:wrap:start === \*\/\}[\s\S]*?\{\/\* === mhosaic-feedback:wrap:end === \*\/\}\n?/g, "");
19
+ if (stripped !== src) {
20
+ await writeFile(entryPath, stripped);
21
+ process.stdout.write(kleur.green(`\u2713 Stripped markers from ${framework.entry}
22
+ `));
23
+ }
24
+ }
25
+ }
26
+ const envPath = join(cwd, ".env.local");
27
+ if (existsSync(envPath)) {
28
+ const src = readFileSync(envPath, "utf8");
29
+ const cleaned = src.replace(/# === mhosaic-feedback ===\n[\s\S]*?# === mhosaic-feedback ===\n?/g, "").replace(/\n{3,}/g, "\n\n");
30
+ if (cleaned !== src) {
31
+ await writeFile(envPath, cleaned);
32
+ process.stdout.write(kleur.green("\u2713 Removed env block from .env.local\n"));
33
+ }
34
+ }
35
+ process.stdout.write(kleur.gray("Run `pnpm remove @mhosaic/feedback` (or npm/yarn equivalent) to uninstall the package.\n"));
36
+ }
37
+ export {
38
+ runEject
39
+ };
40
+ //# sourceMappingURL=eject-VNJVOCQM.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/commands/eject.ts"],"sourcesContent":["import { existsSync, readFileSync } from 'node:fs'\nimport { writeFile } from 'node:fs/promises'\nimport { join } from 'node:path'\n\nimport kleur from 'kleur'\n\nimport { detectFramework } from '../detect'\n\nexport async function runEject(argv: string[]): Promise<void> {\n const cwd = argv.includes('--cwd') ? argv[argv.indexOf('--cwd') + 1] ?? process.cwd() : process.cwd()\n\n const framework = await detectFramework(cwd)\n if (framework.entry) {\n const entryPath = join(cwd, framework.entry)\n if (existsSync(entryPath)) {\n const src = readFileSync(entryPath, 'utf8')\n const stripped = src\n .replace(/\\/\\/ === mhosaic-feedback:import:start ===[\\s\\S]*?\\/\\/ === mhosaic-feedback:import:end ===\\n?/g, '')\n .replace(/\\{\\/\\* === mhosaic-feedback:wrap:start === \\*\\/\\}[\\s\\S]*?\\{\\/\\* === mhosaic-feedback:wrap:end === \\*\\/\\}\\n?/g, '')\n if (stripped !== src) {\n await writeFile(entryPath, stripped)\n process.stdout.write(kleur.green(`✓ Stripped markers from ${framework.entry}\\n`))\n }\n }\n }\n\n const envPath = join(cwd, '.env.local')\n if (existsSync(envPath)) {\n const src = readFileSync(envPath, 'utf8')\n const cleaned = src.replace(/# === mhosaic-feedback ===\\n[\\s\\S]*?# === mhosaic-feedback ===\\n?/g, '').replace(/\\n{3,}/g, '\\n\\n')\n if (cleaned !== src) {\n await writeFile(envPath, cleaned)\n process.stdout.write(kleur.green('✓ Removed env block from .env.local\\n'))\n }\n }\n\n process.stdout.write(kleur.gray(\"Run `pnpm remove @mhosaic/feedback` (or npm/yarn equivalent) to uninstall the package.\\n\"))\n}\n"],"mappings":";;;;;;AAAA,SAAS,YAAY,oBAAoB;AACzC,SAAS,iBAAiB;AAC1B,SAAS,YAAY;AAErB,OAAO,WAAW;AAIlB,eAAsB,SAAS,MAA+B;AAC5D,QAAM,MAAM,KAAK,SAAS,OAAO,IAAI,KAAK,KAAK,QAAQ,OAAO,IAAI,CAAC,KAAK,QAAQ,IAAI,IAAI,QAAQ,IAAI;AAEpG,QAAM,YAAY,MAAM,gBAAgB,GAAG;AAC3C,MAAI,UAAU,OAAO;AACnB,UAAM,YAAY,KAAK,KAAK,UAAU,KAAK;AAC3C,QAAI,WAAW,SAAS,GAAG;AACzB,YAAM,MAAM,aAAa,WAAW,MAAM;AAC1C,YAAM,WAAW,IACd,QAAQ,kGAAkG,EAAE,EAC5G,QAAQ,gHAAgH,EAAE;AAC7H,UAAI,aAAa,KAAK;AACpB,cAAM,UAAU,WAAW,QAAQ;AACnC,gBAAQ,OAAO,MAAM,MAAM,MAAM,gCAA2B,UAAU,KAAK;AAAA,CAAI,CAAC;AAAA,MAClF;AAAA,IACF;AAAA,EACF;AAEA,QAAM,UAAU,KAAK,KAAK,YAAY;AACtC,MAAI,WAAW,OAAO,GAAG;AACvB,UAAM,MAAM,aAAa,SAAS,MAAM;AACxC,UAAM,UAAU,IAAI,QAAQ,sEAAsE,EAAE,EAAE,QAAQ,WAAW,MAAM;AAC/H,QAAI,YAAY,KAAK;AACnB,YAAM,UAAU,SAAS,OAAO;AAChC,cAAQ,OAAO,MAAM,MAAM,MAAM,4CAAuC,CAAC;AAAA,IAC3E;AAAA,EACF;AAEA,UAAQ,OAAO,MAAM,MAAM,KAAK,0FAA0F,CAAC;AAC7H;","names":[]}
@@ -0,0 +1,230 @@
1
+ #!/usr/bin/env node
2
+ import {
3
+ detectFramework
4
+ } from "./chunk-COJ75KUD.js";
5
+
6
+ // src/commands/init.ts
7
+ import { existsSync as existsSync3 } from "fs";
8
+ import { join } from "path";
9
+ import { spawnSync } from "child_process";
10
+ import kleur from "kleur";
11
+ import prompts from "prompts";
12
+
13
+ // src/edits/env.ts
14
+ import { readFile, writeFile } from "fs/promises";
15
+ import { existsSync } from "fs";
16
+ var MARK = "# === mhosaic-feedback ===";
17
+ function renderEnv(existing, entries) {
18
+ const lines = existing.split(/\r?\n/);
19
+ const filtered = [];
20
+ let inBlock = false;
21
+ for (const line of lines) {
22
+ if (line.trim() === MARK) {
23
+ inBlock = !inBlock;
24
+ continue;
25
+ }
26
+ if (inBlock) continue;
27
+ if (line.startsWith("VITE_FEEDBACK_API_KEY=") || line.startsWith("VITE_FEEDBACK_ENDPOINT=")) continue;
28
+ filtered.push(line);
29
+ }
30
+ while (filtered.length > 0 && filtered[filtered.length - 1] === "") filtered.pop();
31
+ const block = [
32
+ MARK,
33
+ `VITE_FEEDBACK_API_KEY=${entries.apiKey}`,
34
+ `VITE_FEEDBACK_ENDPOINT=${entries.endpoint}`,
35
+ MARK
36
+ ].join("\n");
37
+ return (filtered.length > 0 ? filtered.join("\n") + "\n\n" : "") + block + "\n";
38
+ }
39
+ async function writeEnvLocal(path, entries) {
40
+ const existing = existsSync(path) ? await readFile(path, "utf8") : "";
41
+ await writeFile(path, renderEnv(existing, entries));
42
+ }
43
+
44
+ // src/edits/gitignore.ts
45
+ import { readFile as readFile2, writeFile as writeFile2 } from "fs/promises";
46
+ import { existsSync as existsSync2 } from "fs";
47
+ var REQUIRED = [".env.local"];
48
+ function renderGitignore(existing) {
49
+ const lines = new Set(existing.split(/\r?\n/).map((l) => l.trim()));
50
+ const missing = REQUIRED.filter((entry) => !lines.has(entry));
51
+ if (missing.length === 0) return existing;
52
+ const trailingNewline = existing.endsWith("\n") || existing === "";
53
+ return existing + (trailingNewline ? "" : "\n") + missing.join("\n") + "\n";
54
+ }
55
+ async function ensureGitignore(path) {
56
+ const existing = existsSync2(path) ? await readFile2(path, "utf8") : "";
57
+ const next = renderGitignore(existing);
58
+ if (next !== existing) await writeFile2(path, next);
59
+ }
60
+
61
+ // src/edits/react.ts
62
+ import { readFile as readFile3, writeFile as writeFile3 } from "fs/promises";
63
+ var IMPORT_MARK_START = "// === mhosaic-feedback:import:start ===";
64
+ var IMPORT_MARK_END = "// === mhosaic-feedback:import:end ===";
65
+ var WRAP_MARK_START = "{/* === mhosaic-feedback:wrap:start === */}";
66
+ var WRAP_MARK_END = "{/* === mhosaic-feedback:wrap:end === */}";
67
+ function escapeRegex(s) {
68
+ return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
69
+ }
70
+ function buildImportBlock() {
71
+ return [
72
+ IMPORT_MARK_START,
73
+ "import { FeedbackProvider } from '@mhosaic/feedback/react'",
74
+ IMPORT_MARK_END
75
+ ].join("\n");
76
+ }
77
+ function buildWrapOpen(opts) {
78
+ return [
79
+ WRAP_MARK_START,
80
+ `<FeedbackProvider apiKey={import.meta.env.${opts.apiKeyEnv} as string} endpoint={import.meta.env.${opts.endpointEnv} as string} env="prod">`
81
+ ].join("\n ");
82
+ }
83
+ function buildWrapClose() {
84
+ return ["</FeedbackProvider>", WRAP_MARK_END].join("\n ");
85
+ }
86
+ function transformReactEntry(source, opts) {
87
+ let out = source;
88
+ const alreadyWrapped = out.includes(IMPORT_MARK_START) && out.includes(WRAP_MARK_START);
89
+ if (alreadyWrapped) {
90
+ out = out.replace(
91
+ new RegExp(`(${escapeRegex(IMPORT_MARK_START)}\\n)[^\\n]*(\\n${escapeRegex(IMPORT_MARK_END)})`),
92
+ `$1import { FeedbackProvider } from '@mhosaic/feedback/react'$2`
93
+ );
94
+ out = out.replace(
95
+ /<FeedbackProvider[^>]*>/,
96
+ `<FeedbackProvider apiKey={import.meta.env.${opts.apiKeyEnv} as string} endpoint={import.meta.env.${opts.endpointEnv} as string} env="prod">`
97
+ );
98
+ return out;
99
+ }
100
+ out = out.replace(
101
+ new RegExp(`${escapeRegex(IMPORT_MARK_START)}[\\s\\S]*?${escapeRegex(IMPORT_MARK_END)}\\n?`, "g"),
102
+ ""
103
+ );
104
+ out = out.replace(
105
+ new RegExp(`${escapeRegex(WRAP_MARK_START)}[\\s\\S]*?${escapeRegex(WRAP_MARK_END)}\\n?`, "g"),
106
+ ""
107
+ );
108
+ const importRegex = /^(import[^\n]+\n)+/m;
109
+ const importMatch = out.match(importRegex);
110
+ if (importMatch) {
111
+ const idx = importMatch.index + importMatch[0].length;
112
+ out = out.slice(0, idx) + buildImportBlock() + "\n\n" + out.slice(idx);
113
+ } else {
114
+ out = buildImportBlock() + "\n\n" + out;
115
+ }
116
+ const renderPatterns = [
117
+ /\.render\(\s*([\s\S]*?)\s*\)\s*[,;]?\s*\n/,
118
+ /ReactDOM\.render\(\s*([\s\S]*?),\s*document\.getElementById/
119
+ ];
120
+ for (const re of renderPatterns) {
121
+ const m = out.match(re);
122
+ if (m && m.index !== void 0) {
123
+ const jsx = m[1].replace(/[,;]\s*$/, "");
124
+ const wrapped = `
125
+ ${buildWrapOpen(opts)}
126
+ ${jsx.replace(/\n/g, "\n ")}
127
+ ${buildWrapClose()}
128
+ `;
129
+ const startIdx = m.index + m[0].indexOf(m[1]);
130
+ out = out.slice(0, startIdx) + wrapped + out.slice(startIdx + m[1].length);
131
+ break;
132
+ }
133
+ }
134
+ return out;
135
+ }
136
+ async function wrapReactEntry(path, opts) {
137
+ const source = await readFile3(path, "utf8");
138
+ const next = transformReactEntry(source, opts);
139
+ if (next !== source) await writeFile3(path, next);
140
+ }
141
+
142
+ // src/commands/init.ts
143
+ function parseArgs(argv) {
144
+ const out = { yes: false, install: true, cwd: process.cwd() };
145
+ for (let i = 0; i < argv.length; i++) {
146
+ const a = argv[i];
147
+ if (a === "--api-key") {
148
+ const v = argv[++i];
149
+ if (v !== void 0) out.apiKey = v;
150
+ } else if (a === "--endpoint") {
151
+ const v = argv[++i];
152
+ if (v !== void 0) out.endpoint = v;
153
+ } else if (a === "--yes" || a === "-y") out.yes = true;
154
+ else if (a === "--no-install") out.install = false;
155
+ else if (a === "--cwd") out.cwd = argv[++i] ?? process.cwd();
156
+ }
157
+ return out;
158
+ }
159
+ function detectPackageManager(cwd) {
160
+ if (existsSync3(join(cwd, "pnpm-lock.yaml"))) return "pnpm";
161
+ if (existsSync3(join(cwd, "yarn.lock"))) return "yarn";
162
+ return "npm";
163
+ }
164
+ async function runInit(argv) {
165
+ const args = parseArgs(argv);
166
+ const { cwd } = args;
167
+ process.stdout.write(kleur.bold("\n\u26A1 Mhosaic Feedback setup\n\n"));
168
+ const framework = await detectFramework(cwd);
169
+ process.stdout.write(kleur.gray(`Detected: ${framework.kind}${framework.entry ? " (" + framework.entry + ")" : ""}
170
+ `));
171
+ let apiKey = args.apiKey;
172
+ let endpoint = args.endpoint ?? "http://localhost:8000";
173
+ if (!args.yes && !apiKey) {
174
+ const answers = await prompts([
175
+ { type: "text", name: "endpoint", message: "Backend endpoint", initial: endpoint },
176
+ { type: "text", name: "apiKey", message: "Public API key (pk_proj_\u2026)", validate: (v) => v.startsWith("pk_proj_") || "must start with pk_proj_" }
177
+ ]);
178
+ if (!answers.apiKey) {
179
+ process.stdout.write(kleur.red("Aborted.\n"));
180
+ process.exitCode = 1;
181
+ return;
182
+ }
183
+ endpoint = answers.endpoint;
184
+ apiKey = answers.apiKey;
185
+ }
186
+ if (!apiKey) {
187
+ process.stderr.write("api-key is required (flag or prompt)\n");
188
+ process.exitCode = 1;
189
+ return;
190
+ }
191
+ const pm = detectPackageManager(cwd);
192
+ if (args.install) {
193
+ process.stdout.write(kleur.gray(`Installing @mhosaic/feedback via ${pm}\u2026
194
+ `));
195
+ const cmd = pm === "pnpm" ? ["pnpm", "add", "@mhosaic/feedback"] : pm === "yarn" ? ["yarn", "add", "@mhosaic/feedback"] : ["npm", "install", "@mhosaic/feedback"];
196
+ const res = spawnSync(cmd[0], cmd.slice(1), { cwd, stdio: "inherit" });
197
+ if (res.status !== 0) {
198
+ process.stderr.write(kleur.red("install failed\n"));
199
+ process.exitCode = res.status ?? 1;
200
+ return;
201
+ }
202
+ process.stdout.write(kleur.green("\u2713 Installed @mhosaic/feedback\n"));
203
+ }
204
+ await writeEnvLocal(join(cwd, ".env.local"), { apiKey, endpoint });
205
+ process.stdout.write(kleur.green("\u2713 Wrote .env.local\n"));
206
+ await ensureGitignore(join(cwd, ".gitignore"));
207
+ process.stdout.write(kleur.green("\u2713 Updated .gitignore\n"));
208
+ if (framework.entry && framework.kind === "vite-react") {
209
+ const entryPath = join(cwd, framework.entry);
210
+ if (existsSync3(entryPath)) {
211
+ await wrapReactEntry(entryPath, {
212
+ apiKeyEnv: "VITE_FEEDBACK_API_KEY",
213
+ endpointEnv: "VITE_FEEDBACK_ENDPOINT"
214
+ });
215
+ process.stdout.write(kleur.green(`\u2713 Wrapped ${framework.entry}
216
+ `));
217
+ } else {
218
+ process.stdout.write(kleur.yellow(`\u26A0 Expected entry ${framework.entry} not found \u2014 wire <FeedbackProvider> manually.
219
+ `));
220
+ }
221
+ } else if (framework.kind !== "vite-react") {
222
+ process.stdout.write(kleur.yellow(`\u26A0 Auto-wiring is only supported for Vite + React today. For ${framework.kind}, add <FeedbackProvider> manually.
223
+ `));
224
+ }
225
+ process.stdout.write(kleur.bold("\nDone.\n"));
226
+ }
227
+ export {
228
+ runInit
229
+ };
230
+ //# sourceMappingURL=init-6I2XNWE7.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/commands/init.ts","../src/edits/env.ts","../src/edits/gitignore.ts","../src/edits/react.ts"],"sourcesContent":["import { existsSync } from 'node:fs'\nimport { join } from 'node:path'\nimport { spawnSync } from 'node:child_process'\n\nimport kleur from 'kleur'\nimport prompts from 'prompts'\n\nimport { detectFramework } from '../detect'\nimport { writeEnvLocal } from '../edits/env'\nimport { ensureGitignore } from '../edits/gitignore'\nimport { wrapReactEntry } from '../edits/react'\n\ninterface InitArgs {\n apiKey?: string\n endpoint?: string\n yes: boolean\n install: boolean\n cwd: string\n}\n\nfunction parseArgs(argv: string[]): InitArgs {\n const out: InitArgs = { yes: false, install: true, cwd: process.cwd() }\n for (let i = 0; i < argv.length; i++) {\n const a = argv[i]!\n if (a === '--api-key') { const v = argv[++i]; if (v !== undefined) out.apiKey = v }\n else if (a === '--endpoint') { const v = argv[++i]; if (v !== undefined) out.endpoint = v }\n else if (a === '--yes' || a === '-y') out.yes = true\n else if (a === '--no-install') out.install = false\n else if (a === '--cwd') out.cwd = argv[++i] ?? process.cwd()\n }\n return out\n}\n\nfunction detectPackageManager(cwd: string): 'pnpm' | 'yarn' | 'npm' {\n if (existsSync(join(cwd, 'pnpm-lock.yaml'))) return 'pnpm'\n if (existsSync(join(cwd, 'yarn.lock'))) return 'yarn'\n return 'npm'\n}\n\nexport async function runInit(argv: string[]): Promise<void> {\n const args = parseArgs(argv)\n const { cwd } = args\n\n process.stdout.write(kleur.bold('\\n⚡ Mhosaic Feedback setup\\n\\n'))\n\n const framework = await detectFramework(cwd)\n process.stdout.write(kleur.gray(`Detected: ${framework.kind}${framework.entry ? ' (' + framework.entry + ')' : ''}\\n`))\n\n let apiKey = args.apiKey\n let endpoint = args.endpoint ?? 'http://localhost:8000'\n if (!args.yes && !apiKey) {\n const answers = await prompts([\n { type: 'text', name: 'endpoint', message: 'Backend endpoint', initial: endpoint },\n { type: 'text', name: 'apiKey', message: 'Public API key (pk_proj_…)', validate: (v: string) => v.startsWith('pk_proj_') || 'must start with pk_proj_' },\n ])\n if (!answers.apiKey) {\n process.stdout.write(kleur.red('Aborted.\\n'))\n process.exitCode = 1\n return\n }\n endpoint = answers.endpoint\n apiKey = answers.apiKey\n }\n if (!apiKey) {\n process.stderr.write('api-key is required (flag or prompt)\\n')\n process.exitCode = 1\n return\n }\n\n const pm = detectPackageManager(cwd)\n if (args.install) {\n process.stdout.write(kleur.gray(`Installing @mhosaic/feedback via ${pm}…\\n`))\n const cmd = pm === 'pnpm' ? ['pnpm', 'add', '@mhosaic/feedback'] : pm === 'yarn' ? ['yarn', 'add', '@mhosaic/feedback'] : ['npm', 'install', '@mhosaic/feedback']\n const res = spawnSync(cmd[0]!, cmd.slice(1), { cwd, stdio: 'inherit' })\n if (res.status !== 0) {\n process.stderr.write(kleur.red('install failed\\n'))\n process.exitCode = res.status ?? 1\n return\n }\n process.stdout.write(kleur.green('✓ Installed @mhosaic/feedback\\n'))\n }\n\n await writeEnvLocal(join(cwd, '.env.local'), { apiKey, endpoint })\n process.stdout.write(kleur.green('✓ Wrote .env.local\\n'))\n\n await ensureGitignore(join(cwd, '.gitignore'))\n process.stdout.write(kleur.green('✓ Updated .gitignore\\n'))\n\n if (framework.entry && framework.kind === 'vite-react') {\n const entryPath = join(cwd, framework.entry)\n if (existsSync(entryPath)) {\n await wrapReactEntry(entryPath, {\n apiKeyEnv: 'VITE_FEEDBACK_API_KEY',\n endpointEnv: 'VITE_FEEDBACK_ENDPOINT',\n })\n process.stdout.write(kleur.green(`✓ Wrapped ${framework.entry}\\n`))\n } else {\n process.stdout.write(kleur.yellow(`⚠ Expected entry ${framework.entry} not found — wire <FeedbackProvider> manually.\\n`))\n }\n } else if (framework.kind !== 'vite-react') {\n process.stdout.write(kleur.yellow(`⚠ Auto-wiring is only supported for Vite + React today. For ${framework.kind}, add <FeedbackProvider> manually.\\n`))\n }\n\n process.stdout.write(kleur.bold('\\nDone.\\n'))\n}\n","import { readFile, writeFile } from 'node:fs/promises'\nimport { existsSync } from 'node:fs'\n\nconst MARK = '# === mhosaic-feedback ==='\n\nexport interface EnvEntries {\n apiKey: string\n endpoint: string\n}\n\nexport function renderEnv(existing: string, entries: EnvEntries): string {\n const lines = existing.split(/\\r?\\n/)\n const filtered: string[] = []\n let inBlock = false\n for (const line of lines) {\n if (line.trim() === MARK) { inBlock = !inBlock; continue }\n if (inBlock) continue\n if (line.startsWith('VITE_FEEDBACK_API_KEY=') || line.startsWith('VITE_FEEDBACK_ENDPOINT=')) continue\n filtered.push(line)\n }\n // Trim trailing empty lines\n while (filtered.length > 0 && filtered[filtered.length - 1] === '') filtered.pop()\n const block = [\n MARK,\n `VITE_FEEDBACK_API_KEY=${entries.apiKey}`,\n `VITE_FEEDBACK_ENDPOINT=${entries.endpoint}`,\n MARK,\n ].join('\\n')\n return (filtered.length > 0 ? filtered.join('\\n') + '\\n\\n' : '') + block + '\\n'\n}\n\nexport async function writeEnvLocal(path: string, entries: EnvEntries): Promise<void> {\n const existing = existsSync(path) ? await readFile(path, 'utf8') : ''\n await writeFile(path, renderEnv(existing, entries))\n}\n","import { readFile, writeFile } from 'node:fs/promises'\nimport { existsSync } from 'node:fs'\n\nconst REQUIRED = ['.env.local']\n\nexport function renderGitignore(existing: string): string {\n const lines = new Set(existing.split(/\\r?\\n/).map((l) => l.trim()))\n const missing = REQUIRED.filter((entry) => !lines.has(entry))\n if (missing.length === 0) return existing\n const trailingNewline = existing.endsWith('\\n') || existing === ''\n return existing + (trailingNewline ? '' : '\\n') + missing.join('\\n') + '\\n'\n}\n\nexport async function ensureGitignore(path: string): Promise<void> {\n const existing = existsSync(path) ? await readFile(path, 'utf8') : ''\n const next = renderGitignore(existing)\n if (next !== existing) await writeFile(path, next)\n}\n","import { readFile, writeFile } from 'node:fs/promises'\n\nconst IMPORT_MARK_START = '// === mhosaic-feedback:import:start ==='\nconst IMPORT_MARK_END = '// === mhosaic-feedback:import:end ==='\nconst WRAP_MARK_START = '{/* === mhosaic-feedback:wrap:start === */}'\nconst WRAP_MARK_END = '{/* === mhosaic-feedback:wrap:end === */}'\n\nexport interface WrapOptions {\n apiKeyEnv: string // 'VITE_FEEDBACK_API_KEY'\n endpointEnv: string // 'VITE_FEEDBACK_ENDPOINT'\n}\n\nfunction escapeRegex(s: string): string {\n return s.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&')\n}\n\nfunction buildImportBlock(): string {\n return [\n IMPORT_MARK_START,\n \"import { FeedbackProvider } from '@mhosaic/feedback/react'\",\n IMPORT_MARK_END,\n ].join('\\n')\n}\n\nfunction buildWrapOpen(opts: WrapOptions): string {\n return [\n WRAP_MARK_START,\n `<FeedbackProvider apiKey={import.meta.env.${opts.apiKeyEnv} as string} endpoint={import.meta.env.${opts.endpointEnv} as string} env=\"prod\">`,\n ].join('\\n ')\n}\n\nfunction buildWrapClose(): string {\n return ['</FeedbackProvider>', WRAP_MARK_END].join('\\n ')\n}\n\nexport function transformReactEntry(source: string, opts: WrapOptions): string {\n let out = source\n\n // If markers are already present, do an in-place update of the FeedbackProvider\n // props (import block + wrap tag) without restructuring anything — this is what\n // makes re-runs idempotent without needing to parse/unwrap the JSX tree.\n const alreadyWrapped =\n out.includes(IMPORT_MARK_START) && out.includes(WRAP_MARK_START)\n\n if (alreadyWrapped) {\n // Update import block (replace old import line inside the markers)\n out = out.replace(\n new RegExp(`(${escapeRegex(IMPORT_MARK_START)}\\\\n)[^\\\\n]*(\\\\n${escapeRegex(IMPORT_MARK_END)})`),\n `$1import { FeedbackProvider } from '@mhosaic/feedback/react'$2`,\n )\n // Update FeedbackProvider opening tag props\n out = out.replace(\n /<FeedbackProvider[^>]*>/,\n `<FeedbackProvider apiKey={import.meta.env.${opts.apiKeyEnv} as string} endpoint={import.meta.env.${opts.endpointEnv} as string} env=\"prod\">`,\n )\n return out\n }\n\n // Fresh insert: strip any partial markers that may exist (safety), then insert.\n out = out.replace(\n new RegExp(`${escapeRegex(IMPORT_MARK_START)}[\\\\s\\\\S]*?${escapeRegex(IMPORT_MARK_END)}\\\\n?`, 'g'),\n '',\n )\n out = out.replace(\n new RegExp(`${escapeRegex(WRAP_MARK_START)}[\\\\s\\\\S]*?${escapeRegex(WRAP_MARK_END)}\\\\n?`, 'g'),\n '',\n )\n\n // Insert import block after the last existing import statement.\n const importRegex = /^(import[^\\n]+\\n)+/m\n const importMatch = out.match(importRegex)\n if (importMatch) {\n const idx = importMatch.index! + importMatch[0].length\n out = out.slice(0, idx) + buildImportBlock() + '\\n\\n' + out.slice(idx)\n } else {\n out = buildImportBlock() + '\\n\\n' + out\n }\n\n // Wrap the App component inside the render call.\n // Pattern A: createRoot(...).render(<jsx>) — covers both single-line and multi-line.\n // Pattern B: ReactDOM.render(<jsx>, document.getElementById(...))\n const renderPatterns: Array<RegExp> = [\n /\\.render\\(\\s*([\\s\\S]*?)\\s*\\)\\s*[,;]?\\s*\\n/,\n /ReactDOM\\.render\\(\\s*([\\s\\S]*?),\\s*document\\.getElementById/,\n ]\n for (const re of renderPatterns) {\n const m = out.match(re)\n if (m && m.index !== undefined) {\n // Strip any trailing argument-list punctuation from the captured JSX —\n // `render(<App />,)` is valid JS but wrapping a trailing `,` inside the\n // FeedbackProvider children would render a literal \",\" as a text node.\n const jsx = m[1]!.replace(/[,;]\\s*$/, '')\n const wrapped = `\\n ${buildWrapOpen(opts)}\\n ${jsx.replace(/\\n/g, '\\n ')}\\n ${buildWrapClose()}\\n `\n const startIdx = m.index + m[0].indexOf(m[1]!)\n out = out.slice(0, startIdx) + wrapped + out.slice(startIdx + m[1]!.length)\n break\n }\n }\n\n return out\n}\n\nexport async function wrapReactEntry(path: string, opts: WrapOptions): Promise<void> {\n const source = await readFile(path, 'utf8')\n const next = transformReactEntry(source, opts)\n if (next !== source) await writeFile(path, next)\n}\n"],"mappings":"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","names":["existsSync","readFile","writeFile","existsSync","readFile","writeFile","existsSync"]}
package/package.json ADDED
@@ -0,0 +1,29 @@
1
+ {
2
+ "name": "@mhosaic/feedback-cli",
3
+ "version": "0.3.0",
4
+ "type": "module",
5
+ "bin": {
6
+ "mhosaic-feedback": "./dist/bin.js",
7
+ "@mhosaic/feedback": "./dist/bin.js"
8
+ },
9
+ "files": [
10
+ "dist"
11
+ ],
12
+ "dependencies": {
13
+ "kleur": "^4.1.5",
14
+ "prompts": "^2.4.2"
15
+ },
16
+ "devDependencies": {
17
+ "@types/node": "^22.5.0",
18
+ "@types/prompts": "^2.4.9",
19
+ "tsup": "^8.3.0",
20
+ "typescript": "5.6.3",
21
+ "vitest": "^2.1.0"
22
+ },
23
+ "scripts": {
24
+ "build": "tsup",
25
+ "dev": "tsup --watch",
26
+ "test": "vitest",
27
+ "typecheck": "tsc --noEmit"
28
+ }
29
+ }