userdispatch 0.1.0 → 0.2.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/index.js +234 -45
- package/package.json +3 -2
package/dist/index.js
CHANGED
|
@@ -1,4 +1,102 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
+
var __create = Object.create;
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __commonJS = (cb, mod) => function __require() {
|
|
9
|
+
return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
|
|
10
|
+
};
|
|
11
|
+
var __copyProps = (to, from, except, desc) => {
|
|
12
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
13
|
+
for (let key of __getOwnPropNames(from))
|
|
14
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
15
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
16
|
+
}
|
|
17
|
+
return to;
|
|
18
|
+
};
|
|
19
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
20
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
21
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
22
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
23
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
24
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
25
|
+
mod
|
|
26
|
+
));
|
|
27
|
+
|
|
28
|
+
// node_modules/picocolors/picocolors.js
|
|
29
|
+
var require_picocolors = __commonJS({
|
|
30
|
+
"node_modules/picocolors/picocolors.js"(exports, module) {
|
|
31
|
+
"use strict";
|
|
32
|
+
var p = process || {};
|
|
33
|
+
var argv = p.argv || [];
|
|
34
|
+
var env = p.env || {};
|
|
35
|
+
var isColorSupported = !(!!env.NO_COLOR || argv.includes("--no-color")) && (!!env.FORCE_COLOR || argv.includes("--color") || p.platform === "win32" || (p.stdout || {}).isTTY && env.TERM !== "dumb" || !!env.CI);
|
|
36
|
+
var formatter = (open, close, replace = open) => (input) => {
|
|
37
|
+
let string = "" + input, index = string.indexOf(close, open.length);
|
|
38
|
+
return ~index ? open + replaceClose(string, close, replace, index) + close : open + string + close;
|
|
39
|
+
};
|
|
40
|
+
var replaceClose = (string, close, replace, index) => {
|
|
41
|
+
let result = "", cursor = 0;
|
|
42
|
+
do {
|
|
43
|
+
result += string.substring(cursor, index) + replace;
|
|
44
|
+
cursor = index + close.length;
|
|
45
|
+
index = string.indexOf(close, cursor);
|
|
46
|
+
} while (~index);
|
|
47
|
+
return result + string.substring(cursor);
|
|
48
|
+
};
|
|
49
|
+
var createColors = (enabled = isColorSupported) => {
|
|
50
|
+
let f = enabled ? formatter : () => String;
|
|
51
|
+
return {
|
|
52
|
+
isColorSupported: enabled,
|
|
53
|
+
reset: f("\x1B[0m", "\x1B[0m"),
|
|
54
|
+
bold: f("\x1B[1m", "\x1B[22m", "\x1B[22m\x1B[1m"),
|
|
55
|
+
dim: f("\x1B[2m", "\x1B[22m", "\x1B[22m\x1B[2m"),
|
|
56
|
+
italic: f("\x1B[3m", "\x1B[23m"),
|
|
57
|
+
underline: f("\x1B[4m", "\x1B[24m"),
|
|
58
|
+
inverse: f("\x1B[7m", "\x1B[27m"),
|
|
59
|
+
hidden: f("\x1B[8m", "\x1B[28m"),
|
|
60
|
+
strikethrough: f("\x1B[9m", "\x1B[29m"),
|
|
61
|
+
black: f("\x1B[30m", "\x1B[39m"),
|
|
62
|
+
red: f("\x1B[31m", "\x1B[39m"),
|
|
63
|
+
green: f("\x1B[32m", "\x1B[39m"),
|
|
64
|
+
yellow: f("\x1B[33m", "\x1B[39m"),
|
|
65
|
+
blue: f("\x1B[34m", "\x1B[39m"),
|
|
66
|
+
magenta: f("\x1B[35m", "\x1B[39m"),
|
|
67
|
+
cyan: f("\x1B[36m", "\x1B[39m"),
|
|
68
|
+
white: f("\x1B[37m", "\x1B[39m"),
|
|
69
|
+
gray: f("\x1B[90m", "\x1B[39m"),
|
|
70
|
+
bgBlack: f("\x1B[40m", "\x1B[49m"),
|
|
71
|
+
bgRed: f("\x1B[41m", "\x1B[49m"),
|
|
72
|
+
bgGreen: f("\x1B[42m", "\x1B[49m"),
|
|
73
|
+
bgYellow: f("\x1B[43m", "\x1B[49m"),
|
|
74
|
+
bgBlue: f("\x1B[44m", "\x1B[49m"),
|
|
75
|
+
bgMagenta: f("\x1B[45m", "\x1B[49m"),
|
|
76
|
+
bgCyan: f("\x1B[46m", "\x1B[49m"),
|
|
77
|
+
bgWhite: f("\x1B[47m", "\x1B[49m"),
|
|
78
|
+
blackBright: f("\x1B[90m", "\x1B[39m"),
|
|
79
|
+
redBright: f("\x1B[91m", "\x1B[39m"),
|
|
80
|
+
greenBright: f("\x1B[92m", "\x1B[39m"),
|
|
81
|
+
yellowBright: f("\x1B[93m", "\x1B[39m"),
|
|
82
|
+
blueBright: f("\x1B[94m", "\x1B[39m"),
|
|
83
|
+
magentaBright: f("\x1B[95m", "\x1B[39m"),
|
|
84
|
+
cyanBright: f("\x1B[96m", "\x1B[39m"),
|
|
85
|
+
whiteBright: f("\x1B[97m", "\x1B[39m"),
|
|
86
|
+
bgBlackBright: f("\x1B[100m", "\x1B[49m"),
|
|
87
|
+
bgRedBright: f("\x1B[101m", "\x1B[49m"),
|
|
88
|
+
bgGreenBright: f("\x1B[102m", "\x1B[49m"),
|
|
89
|
+
bgYellowBright: f("\x1B[103m", "\x1B[49m"),
|
|
90
|
+
bgBlueBright: f("\x1B[104m", "\x1B[49m"),
|
|
91
|
+
bgMagentaBright: f("\x1B[105m", "\x1B[49m"),
|
|
92
|
+
bgCyanBright: f("\x1B[106m", "\x1B[49m"),
|
|
93
|
+
bgWhiteBright: f("\x1B[107m", "\x1B[49m")
|
|
94
|
+
};
|
|
95
|
+
};
|
|
96
|
+
module.exports = createColors();
|
|
97
|
+
module.exports.createColors = createColors;
|
|
98
|
+
}
|
|
99
|
+
});
|
|
2
100
|
|
|
3
101
|
// src/index.ts
|
|
4
102
|
import { intro as intro2, outro as outro2 } from "@clack/prompts";
|
|
@@ -7,6 +105,7 @@ import { intro as intro2, outro as outro2 } from "@clack/prompts";
|
|
|
7
105
|
import { intro, log as log7 } from "@clack/prompts";
|
|
8
106
|
|
|
9
107
|
// src/steps/auth.ts
|
|
108
|
+
var import_picocolors = __toESM(require_picocolors(), 1);
|
|
10
109
|
import { text, spinner, log, isCancel } from "@clack/prompts";
|
|
11
110
|
import { exec } from "child_process";
|
|
12
111
|
import { platform } from "os";
|
|
@@ -92,7 +191,8 @@ async function authStep(flags2) {
|
|
|
92
191
|
let token = flags2.token;
|
|
93
192
|
if (!token) {
|
|
94
193
|
const authUrl = `${PROD_URL}/cli/auth`;
|
|
95
|
-
log.step("Step 1 of 6 \u2014 Authenticate");
|
|
194
|
+
log.step(import_picocolors.default.bold("Step 1 of 6 \u2014 Authenticate"));
|
|
195
|
+
log.info("Sign in to link this project to your UserDispatch account. We'll open your browser and generate a token you can paste back here.\n");
|
|
96
196
|
log.info("Opening your browser to sign in with Google.");
|
|
97
197
|
log.info("After signing in, copy the token shown on screen and paste it here.");
|
|
98
198
|
openBrowser(authUrl);
|
|
@@ -133,6 +233,7 @@ async function authStep(flags2) {
|
|
|
133
233
|
}
|
|
134
234
|
|
|
135
235
|
// src/steps/setup.ts
|
|
236
|
+
var import_picocolors2 = __toESM(require_picocolors(), 1);
|
|
136
237
|
import { text as text2, spinner as spinner2, log as log2, isCancel as isCancel2 } from "@clack/prompts";
|
|
137
238
|
import { basename } from "path";
|
|
138
239
|
function slugify(str) {
|
|
@@ -144,18 +245,19 @@ async function promptForValue(message, defaultValue, placeholder) {
|
|
|
144
245
|
defaultValue,
|
|
145
246
|
placeholder: placeholder || defaultValue,
|
|
146
247
|
validate(value) {
|
|
147
|
-
if (!value.trim()) return "This field is required.";
|
|
248
|
+
if (!value.trim() && !defaultValue) return "This field is required.";
|
|
148
249
|
}
|
|
149
250
|
});
|
|
150
251
|
if (isCancel2(result)) {
|
|
151
252
|
log2.warn("Setup cancelled.");
|
|
152
253
|
process.exit(0);
|
|
153
254
|
}
|
|
154
|
-
return result.trim();
|
|
255
|
+
return result.trim() || defaultValue;
|
|
155
256
|
}
|
|
156
257
|
async function setupStep(auth, flags2 = {}) {
|
|
157
258
|
const s = spinner2();
|
|
158
|
-
log2.step("Step 2 of 6 \u2014 Set up your organization and app");
|
|
259
|
+
log2.step(import_picocolors2.default.bold("Step 2 of 6 \u2014 Set up your organization and app"));
|
|
260
|
+
log2.info("Create the organization and app that will receive feedback. You can add more apps later from the dashboard.\n");
|
|
159
261
|
let orgName;
|
|
160
262
|
let orgSlug;
|
|
161
263
|
if (!auth.org) {
|
|
@@ -163,7 +265,9 @@ async function setupStep(auth, flags2 = {}) {
|
|
|
163
265
|
orgName = flags2.org;
|
|
164
266
|
orgSlug = slugify(flags2.org);
|
|
165
267
|
} else {
|
|
268
|
+
log2.info("This is your team or company name \u2014 shown in the dashboard header.");
|
|
166
269
|
orgName = await promptForValue("Organization name:", "My Organization");
|
|
270
|
+
log2.info("URL-friendly identifier \u2014 your dashboard will be at userdispatch.com/org/<slug>.");
|
|
167
271
|
orgSlug = await promptForValue("Organization slug:", slugify(orgName));
|
|
168
272
|
}
|
|
169
273
|
} else {
|
|
@@ -176,7 +280,9 @@ async function setupStep(auth, flags2 = {}) {
|
|
|
176
280
|
appName = flags2.app;
|
|
177
281
|
appSlug = slugify(flags2.app);
|
|
178
282
|
} else {
|
|
283
|
+
log2.info("The project you're collecting feedback for \u2014 shown in the widget and dashboard.");
|
|
179
284
|
appName = await promptForValue("App name:", defaultAppName);
|
|
285
|
+
log2.info("URL-friendly identifier \u2014 feedback form will be at userdispatch.com/f/<org>/<app-slug>.");
|
|
180
286
|
appSlug = await promptForValue("App slug:", slugify(appName));
|
|
181
287
|
}
|
|
182
288
|
s.start("Creating your setup...");
|
|
@@ -211,6 +317,7 @@ async function setupStep(auth, flags2 = {}) {
|
|
|
211
317
|
}
|
|
212
318
|
|
|
213
319
|
// src/steps/widget.ts
|
|
320
|
+
var import_picocolors3 = __toESM(require_picocolors(), 1);
|
|
214
321
|
import { spinner as spinner3, log as log3, confirm, isCancel as isCancel3 } from "@clack/prompts";
|
|
215
322
|
import { execSync } from "child_process";
|
|
216
323
|
import { existsSync as existsSync2, readFileSync as readFileSync2, writeFileSync } from "fs";
|
|
@@ -384,7 +491,8 @@ async function widgetStep(apiKey, flags2 = {}) {
|
|
|
384
491
|
const s = spinner3();
|
|
385
492
|
const pm = detectPackageManager(cwd);
|
|
386
493
|
const detection = detectFramework(cwd);
|
|
387
|
-
log3.step("Step 3 of 6 \u2014 Install widget");
|
|
494
|
+
log3.step(import_picocolors3.default.bold("Step 3 of 6 \u2014 Install widget"));
|
|
495
|
+
log3.info("Add the feedback widget to your app. Users will see a floating button to submit bugs, feedback, and questions.\n");
|
|
388
496
|
log3.info(`Detected framework: ${detection.label}`);
|
|
389
497
|
let installed = false;
|
|
390
498
|
if (!isAlreadyInstalled(cwd)) {
|
|
@@ -449,6 +557,7 @@ async function widgetStep(apiKey, flags2 = {}) {
|
|
|
449
557
|
}
|
|
450
558
|
|
|
451
559
|
// src/steps/mcp.ts
|
|
560
|
+
var import_picocolors4 = __toESM(require_picocolors(), 1);
|
|
452
561
|
import { multiselect, spinner as spinner4, log as log4, isCancel as isCancel4 } from "@clack/prompts";
|
|
453
562
|
import { existsSync as existsSync3, readFileSync as readFileSync3, writeFileSync as writeFileSync2, mkdirSync } from "fs";
|
|
454
563
|
import { dirname, relative } from "path";
|
|
@@ -496,7 +605,8 @@ async function mcpStep(token, flags2 = {}) {
|
|
|
496
605
|
const cwd = process.cwd();
|
|
497
606
|
const agents = detectAgents(cwd);
|
|
498
607
|
const detected = agents.filter((a) => a.detected);
|
|
499
|
-
log4.step("Step 4 of 6 \u2014 Configure MCP for your coding agent");
|
|
608
|
+
log4.step(import_picocolors4.default.bold("Step 4 of 6 \u2014 Configure MCP for your coding agent"));
|
|
609
|
+
log4.info("Connect UserDispatch to your AI coding agent so it can triage bugs, reply to users, and generate digests.\n");
|
|
500
610
|
if (detected.length === 0) {
|
|
501
611
|
log4.info("No coding agents detected. You can configure MCP manually later.");
|
|
502
612
|
return { configured: [], skipped: true };
|
|
@@ -541,10 +651,12 @@ async function mcpStep(token, flags2 = {}) {
|
|
|
541
651
|
}
|
|
542
652
|
|
|
543
653
|
// src/steps/verify.ts
|
|
654
|
+
var import_picocolors5 = __toESM(require_picocolors(), 1);
|
|
544
655
|
import { spinner as spinner5, log as log5 } from "@clack/prompts";
|
|
545
656
|
async function verifyStep(apiKey) {
|
|
546
657
|
const s = spinner5();
|
|
547
|
-
log5.step("Step 5 of 6 \u2014 Verify connection");
|
|
658
|
+
log5.step(import_picocolors5.default.bold("Step 5 of 6 \u2014 Verify connection"));
|
|
659
|
+
log5.info("Send a test submission to confirm everything is wired up correctly.\n");
|
|
548
660
|
s.start("Sending a test submission to your dashboard...");
|
|
549
661
|
try {
|
|
550
662
|
await apiSubmission(
|
|
@@ -571,11 +683,12 @@ async function verifyStep(apiKey) {
|
|
|
571
683
|
}
|
|
572
684
|
|
|
573
685
|
// src/steps/summary.ts
|
|
686
|
+
var import_picocolors6 = __toESM(require_picocolors(), 1);
|
|
574
687
|
import { note, outro, log as log6 } from "@clack/prompts";
|
|
575
688
|
function summaryStep(result) {
|
|
576
689
|
const { setup, widget, mcp, verified, modifiedFiles } = result;
|
|
577
|
-
log6.step("Step 6 of 6 \u2014 Summary");
|
|
578
|
-
const maskedKey = setup.app.apiKey.slice(0, 7) + "..." + setup.app.apiKey.slice(-4);
|
|
690
|
+
log6.step(import_picocolors6.default.bold("Step 6 of 6 \u2014 Summary"));
|
|
691
|
+
const maskedKey = setup.app.apiKey ? setup.app.apiKey.slice(0, 7) + "..." + setup.app.apiKey.slice(-4) : "N/A";
|
|
579
692
|
const lines = [];
|
|
580
693
|
lines.push(`Organization: ${setup.org.name} (${setup.org.slug})`);
|
|
581
694
|
lines.push(`App: ${setup.app.name} (${setup.app.slug})`);
|
|
@@ -615,49 +728,125 @@ function summaryStep(result) {
|
|
|
615
728
|
outro("You're all set! Happy building.");
|
|
616
729
|
}
|
|
617
730
|
|
|
731
|
+
// src/lib/sentry.ts
|
|
732
|
+
import * as Sentry from "@sentry/node";
|
|
733
|
+
var SENTRY_DSN = "https://9611a3d31c8f0b5d8049c23924d0d4ad@o4510882392899584.ingest.us.sentry.io/4510965084127232";
|
|
734
|
+
var SENSITIVE_PATTERNS = [/ud_[a-zA-Z0-9_-]+/g, /pk_[a-zA-Z0-9_-]+/g, /[^\s@]+@[^\s@]+\.[^\s@]+/g];
|
|
735
|
+
function scrubSensitive(str) {
|
|
736
|
+
let result = str;
|
|
737
|
+
for (const pattern of SENSITIVE_PATTERNS) {
|
|
738
|
+
result = result.replace(pattern, "[REDACTED]");
|
|
739
|
+
}
|
|
740
|
+
return result;
|
|
741
|
+
}
|
|
742
|
+
function initSentry() {
|
|
743
|
+
Sentry.init({
|
|
744
|
+
dsn: SENTRY_DSN,
|
|
745
|
+
environment: process.env.NODE_ENV || "production",
|
|
746
|
+
release: `userdispatch-cli@${process.env.npm_package_version || "unknown"}`,
|
|
747
|
+
beforeSend(event) {
|
|
748
|
+
if (event.exception?.values) {
|
|
749
|
+
for (const ex of event.exception.values) {
|
|
750
|
+
if (ex.value) ex.value = scrubSensitive(ex.value);
|
|
751
|
+
}
|
|
752
|
+
}
|
|
753
|
+
if (event.breadcrumbs) {
|
|
754
|
+
for (const crumb of event.breadcrumbs) {
|
|
755
|
+
if (crumb.message) crumb.message = scrubSensitive(crumb.message);
|
|
756
|
+
if (crumb.data) {
|
|
757
|
+
for (const [key, val] of Object.entries(crumb.data)) {
|
|
758
|
+
if (typeof val === "string") {
|
|
759
|
+
crumb.data[key] = scrubSensitive(val);
|
|
760
|
+
}
|
|
761
|
+
}
|
|
762
|
+
}
|
|
763
|
+
}
|
|
764
|
+
}
|
|
765
|
+
return event;
|
|
766
|
+
}
|
|
767
|
+
});
|
|
768
|
+
}
|
|
769
|
+
function captureCliError(err, context) {
|
|
770
|
+
const safeContext = { ...context };
|
|
771
|
+
delete safeContext.token;
|
|
772
|
+
delete safeContext.apiKey;
|
|
773
|
+
delete safeContext.email;
|
|
774
|
+
Sentry.withScope((scope) => {
|
|
775
|
+
scope.setTag("cli_step", String(safeContext.step || "unknown"));
|
|
776
|
+
scope.setContext("cli", {
|
|
777
|
+
...safeContext,
|
|
778
|
+
platform: process.platform,
|
|
779
|
+
arch: process.arch
|
|
780
|
+
});
|
|
781
|
+
if (err instanceof Error) {
|
|
782
|
+
Sentry.captureException(err);
|
|
783
|
+
} else {
|
|
784
|
+
Sentry.captureMessage(String(err), "error");
|
|
785
|
+
}
|
|
786
|
+
});
|
|
787
|
+
}
|
|
788
|
+
|
|
618
789
|
// src/commands/init.ts
|
|
619
790
|
async function initCommand(flags2) {
|
|
791
|
+
initSentry();
|
|
620
792
|
intro("UserDispatch Setup");
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
let widget;
|
|
793
|
+
log7.info("Collect user feedback. Let your AI agent handle it.");
|
|
794
|
+
log7.info("This wizard will authenticate you, create your app, install the widget, and connect your coding agent.\n");
|
|
795
|
+
let currentStep = "init";
|
|
625
796
|
try {
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
797
|
+
currentStep = "auth";
|
|
798
|
+
const auth = await authStep(flags2);
|
|
799
|
+
currentStep = "setup";
|
|
800
|
+
const setup = await setupStep(auth, flags2);
|
|
801
|
+
const modifiedFiles = [];
|
|
802
|
+
currentStep = "widget";
|
|
803
|
+
let widget;
|
|
804
|
+
try {
|
|
805
|
+
widget = await widgetStep(setup.app.apiKey, flags2);
|
|
806
|
+
if (widget.file) modifiedFiles.push(widget.file);
|
|
807
|
+
} catch (err) {
|
|
808
|
+
captureCliError(err, { step: "widget", framework: flags2.framework, nodeVersion: process.version });
|
|
809
|
+
log7.warn(`Widget setup encountered an issue: ${err instanceof Error ? err.message : String(err)}`);
|
|
810
|
+
widget = {
|
|
811
|
+
installed: false,
|
|
812
|
+
injected: false,
|
|
813
|
+
framework: "unknown",
|
|
814
|
+
packageManager: "npm"
|
|
815
|
+
};
|
|
816
|
+
}
|
|
817
|
+
currentStep = "mcp";
|
|
818
|
+
let mcp;
|
|
819
|
+
try {
|
|
820
|
+
mcp = await mcpStep(auth.token, flags2);
|
|
821
|
+
for (const agent of mcp.configured) {
|
|
822
|
+
modifiedFiles.push(agent.configPath);
|
|
823
|
+
}
|
|
824
|
+
} catch (err) {
|
|
825
|
+
captureCliError(err, { step: "mcp", nodeVersion: process.version });
|
|
826
|
+
log7.warn(`MCP setup encountered an issue: ${err instanceof Error ? err.message : String(err)}`);
|
|
827
|
+
mcp = { configured: [], skipped: true };
|
|
642
828
|
}
|
|
829
|
+
currentStep = "verify";
|
|
830
|
+
let verified = false;
|
|
831
|
+
try {
|
|
832
|
+
verified = await verifyStep(setup.app.apiKey);
|
|
833
|
+
} catch (err) {
|
|
834
|
+
captureCliError(err, { step: "verify", nodeVersion: process.version });
|
|
835
|
+
log7.warn(`Verification encountered an issue: ${err instanceof Error ? err.message : String(err)}`);
|
|
836
|
+
}
|
|
837
|
+
currentStep = "summary";
|
|
838
|
+
summaryStep({
|
|
839
|
+
auth,
|
|
840
|
+
setup,
|
|
841
|
+
widget,
|
|
842
|
+
mcp,
|
|
843
|
+
verified,
|
|
844
|
+
modifiedFiles
|
|
845
|
+
});
|
|
643
846
|
} catch (err) {
|
|
644
|
-
|
|
645
|
-
|
|
847
|
+
captureCliError(err, { step: currentStep, nodeVersion: process.version });
|
|
848
|
+
throw err;
|
|
646
849
|
}
|
|
647
|
-
let verified = false;
|
|
648
|
-
try {
|
|
649
|
-
verified = await verifyStep(setup.app.apiKey);
|
|
650
|
-
} catch (err) {
|
|
651
|
-
log7.warn(`Verification encountered an issue: ${err instanceof Error ? err.message : String(err)}`);
|
|
652
|
-
}
|
|
653
|
-
summaryStep({
|
|
654
|
-
auth,
|
|
655
|
-
setup,
|
|
656
|
-
widget,
|
|
657
|
-
mcp,
|
|
658
|
-
verified,
|
|
659
|
-
modifiedFiles
|
|
660
|
-
});
|
|
661
850
|
}
|
|
662
851
|
|
|
663
852
|
// src/lib/args.ts
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "userdispatch",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"description": "CLI installer for UserDispatch feedback widget + MCP server",
|
|
5
5
|
"bin": {
|
|
6
6
|
"userdispatch": "dist/index.js"
|
|
@@ -19,7 +19,8 @@
|
|
|
19
19
|
"test:watch": "vitest"
|
|
20
20
|
},
|
|
21
21
|
"dependencies": {
|
|
22
|
-
"@clack/prompts": "^0.9.0"
|
|
22
|
+
"@clack/prompts": "^0.9.0",
|
|
23
|
+
"@sentry/node": "^9.0.0"
|
|
23
24
|
},
|
|
24
25
|
"devDependencies": {
|
|
25
26
|
"tsup": "^8.0.0",
|