@userreason/wizard 0.2.1 → 0.3.1
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/README.md +95 -0
- package/dist/agent-note.js +7 -6
- package/dist/agent-skill.js +6 -5
- package/dist/analytics.js +9 -0
- package/dist/bin.js +222 -51
- package/dist/chunk-4INLEQE2.js +196 -0
- package/dist/{chunk-GGARVSPT.js → chunk-7AAH6C4L.js} +9198 -5670
- package/dist/{chunk-ULHKVBPD.js → chunk-7O7H3PIM.js} +7 -7
- package/dist/chunk-CSZW2ULJ.js +152 -0
- package/dist/{chunk-3RDJORRS.js → chunk-DMXUXEQI.js} +1 -1
- package/dist/{chunk-SJVLAYGG.js → chunk-EVNEX5N5.js} +8 -1
- package/dist/chunk-KF37D5WL.js +44 -0
- package/dist/{chunk-5SC2K42Q.js → chunk-LEJFE4U5.js} +2 -2
- package/dist/{chunk-OEGNGGZ2.js → chunk-NMHTFC5Q.js} +10 -3
- package/dist/{chunk-6CJ4ANMN.js → chunk-NNPYUATH.js} +1 -1
- package/dist/chunk-PJQOSDYS.js +50 -0
- package/dist/chunk-Q5U5UOQN.js +288 -0
- package/dist/{chunk-5Z5J6PY5.js → chunk-SB3AYQWG.js} +6 -6
- package/dist/{chunk-YMSGDC4B.js → chunk-TOID3NYP.js} +40 -11
- package/dist/{chunk-JD5U4U26.js → chunk-TRBSH5G7.js} +6 -6
- package/dist/{chunk-ZGZOBW2B.js → chunk-XASPGFYK.js} +3 -3
- package/dist/{chunk-HACTNBV3.js → chunk-XPFKXLIZ.js} +3 -3
- package/dist/chunk-ZHJV247H.js +31 -0
- package/dist/cli-access.js +3 -3
- package/dist/connection.js +2 -2
- package/dist/first-survey.js +11 -0
- package/dist/footer.js +17 -0
- package/dist/global-cli.js +6 -5
- package/dist/install-diagnostics.js +9 -0
- package/dist/integrate.js +5 -4
- package/dist/project.js +8 -3
- package/dist/registry.js +5 -3
- package/dist/setup-flow.js +25 -0
- package/dist/setup.js +33 -0
- package/dist/skills/userreason/SKILL.md +43 -0
- package/dist/skills/userreason/references/management.md +6 -0
- package/dist/startup.js +2 -2
- package/dist/state.js +6 -5
- package/dist/ui.js +2 -2
- package/package.json +1 -2
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
import { createRequire as createWizardRequire } from 'node:module'; import { fileURLToPath as wizardFileURLToPath } from 'node:url'; import { dirname as wizardDirname } from 'node:path'; const require = createWizardRequire(import.meta.url); const __filename = wizardFileURLToPath(import.meta.url); const __dirname = wizardDirname(__filename);
|
|
2
|
-
import {
|
|
3
|
-
Cancelled
|
|
4
|
-
} from "./chunk-SJVLAYGG.js";
|
|
5
2
|
import {
|
|
6
3
|
initializationPath
|
|
7
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-LEJFE4U5.js";
|
|
8
5
|
import {
|
|
9
6
|
cliCommand
|
|
10
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-TOID3NYP.js";
|
|
8
|
+
import {
|
|
9
|
+
Cancelled
|
|
10
|
+
} from "./chunk-EVNEX5N5.js";
|
|
11
11
|
import {
|
|
12
12
|
packageProfile
|
|
13
|
-
} from "./chunk-
|
|
13
|
+
} from "./chunk-7AAH6C4L.js";
|
|
14
14
|
|
|
15
15
|
// src/agent-note.ts
|
|
16
16
|
import { constants } from "node:fs";
|
|
@@ -152,7 +152,7 @@ ${plan.snippet}` : plan.snippet,
|
|
|
152
152
|
terminal.success(`User feedback note ${plan.replacement ? "updated in" : "added to"} ${plan.file}`);
|
|
153
153
|
return { status: plan.replacement ? "updated" : "added", file: plan.file };
|
|
154
154
|
} catch (error) {
|
|
155
|
-
if (error instanceof Cancelled) return { status: "declined" };
|
|
155
|
+
if (error instanceof Cancelled) return { status: "declined", reason: "user_cancelled" };
|
|
156
156
|
terminal.warn("Installation is complete. The optional user feedback note could not be added; the guidance file needs review.");
|
|
157
157
|
return { status: "failed", reason: "guidance_file_needs_review" };
|
|
158
158
|
}
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
import { createRequire as createWizardRequire } from 'node:module'; import { fileURLToPath as wizardFileURLToPath } from 'node:url'; import { dirname as wizardDirname } from 'node:path'; const require = createWizardRequire(import.meta.url); const __filename = wizardFileURLToPath(import.meta.url); const __dirname = wizardDirname(__filename);
|
|
2
|
+
import {
|
|
3
|
+
connectSetup,
|
|
4
|
+
resumeSetup,
|
|
5
|
+
runSetup
|
|
6
|
+
} from "./chunk-Q5U5UOQN.js";
|
|
7
|
+
import {
|
|
8
|
+
clean,
|
|
9
|
+
openBrowser
|
|
10
|
+
} from "./chunk-EVNEX5N5.js";
|
|
11
|
+
import {
|
|
12
|
+
BrowserSetupUnavailable
|
|
13
|
+
} from "./chunk-7AAH6C4L.js";
|
|
14
|
+
|
|
15
|
+
// src/setup-flow.ts
|
|
16
|
+
var shell = (value) => /^[A-Za-z0-9_./:@=-]+$/.test(value) ? value : `'${value.replace(/'/g, `'"'"'`)}'`;
|
|
17
|
+
var registryArgs = (profile) => profile?.kind === "local-development" ? ["--prefer-online", `--registry=${profile.registry}`, `--@userreason:registry=${profile.registry}`] : [];
|
|
18
|
+
function setupSampleCommand(setupId, apiOrigin, cliVersion, profile) {
|
|
19
|
+
return ["npx", "-y", ...registryArgs(profile), `@userreason/cli@${cliVersion}`, "setup", "sample", "--setup", setupId, "--api-url", apiOrigin, "--directory", ".", "--json"].map(shell).join(" ");
|
|
20
|
+
}
|
|
21
|
+
function setupResumeCommand(setupId, apiOrigin, version, profile) {
|
|
22
|
+
return ["npx", "-y", ...registryArgs(profile), `@userreason/wizard@${version}`, "--resume-setup", setupId, "--api-url", apiOrigin, "--directory", "."].map(shell).join(" ");
|
|
23
|
+
}
|
|
24
|
+
var setupManualGuidance = {
|
|
25
|
+
install_packages: "Review the project dependency and registry settings, install compatible @userreason/js and @userreason/cli versions with the project package manager, then rerun setup. See https://docs.userreason.com/get-started/quickstart/.",
|
|
26
|
+
initialize_sdk: "Identify the existing browser entry and initialize UserReason once with the selected site\u2019s public ID, preserving any existing initialization. See https://docs.userreason.com/sdk/initialization/.",
|
|
27
|
+
install_skill: "Review the existing agent guidance and merge the UserReason skill manually from the installed @userreason/cli skills/userreason directory. Preserve your existing edits and do not overwrite a customized skill.",
|
|
28
|
+
insert_footer: "Identify the intended existing site footer and manually add a Powered by UserReason link to https://userreason.com/. Preserve its content and layout; resolve ambiguous placement before editing."
|
|
29
|
+
};
|
|
30
|
+
function setupSummary(session) {
|
|
31
|
+
return {
|
|
32
|
+
setup_id: session.setup_id,
|
|
33
|
+
phase: session.phase,
|
|
34
|
+
workspace_id: session.workspace_id,
|
|
35
|
+
site_id: session.site_id,
|
|
36
|
+
local_operations: session.commands.map((command) => ({ kind: command.kind, status: command.status, code: command.result?.code ?? null })),
|
|
37
|
+
manual_steps: session.local_plan?.manual_steps ?? [],
|
|
38
|
+
source: session.source?.status ?? "not_started",
|
|
39
|
+
drafts: session.draft_outcomes.map((draft) => ({ candidate_id: draft.candidate_id, prompt_id: draft.prompt_id, status: draft.status, revision: draft.revision })),
|
|
40
|
+
sample: session.sample.status,
|
|
41
|
+
cli_access: "not_requested"
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
async function runBrowserWizard(input) {
|
|
45
|
+
const { terminal, project, apiOrigin, signal } = input;
|
|
46
|
+
let connected;
|
|
47
|
+
try {
|
|
48
|
+
connected = input.resumeId ? await resumeSetup(apiOrigin, input.resumeId, project, { signal, measurementDisabled: input.measurementDisabled }) : await connectSetup(apiOrigin, project, async (url, code) => {
|
|
49
|
+
terminal.block("Continue in your browser", [url, `Verification code: ${code}`, input.development ? "Choose your workspace, site and installation options in the browser." : "Review the project, local changes and source permissions there."]);
|
|
50
|
+
if (!input.noOpen && !await openBrowser(url)) terminal.info("Open the link above to continue.");
|
|
51
|
+
}, {
|
|
52
|
+
signal,
|
|
53
|
+
browserOrigin: input.browserOrigin,
|
|
54
|
+
automaticSetup: input.development,
|
|
55
|
+
measurementDisabled: input.measurementDisabled,
|
|
56
|
+
...input.development ? { launcher: { wizard_version: input.version, api_origin: apiOrigin, ...input.profile.kind === "local-development" ? { registry: input.profile.registry } : {} } } : {}
|
|
57
|
+
});
|
|
58
|
+
} catch (error) {
|
|
59
|
+
if (!input.resumeId && error instanceof BrowserSetupUnavailable) return false;
|
|
60
|
+
throw error;
|
|
61
|
+
}
|
|
62
|
+
const resume = setupResumeCommand(connected.client.identity.setup_id, apiOrigin, input.version, input.profile);
|
|
63
|
+
terminal.block("Setup connected", [`Setup: ${connected.client.identity.setup_id}`, "Keep this terminal open while you complete setup in the browser.", `To reconnect from this project: ${resume}`]);
|
|
64
|
+
let status = "", displayedPacket = "";
|
|
65
|
+
const shownManual = /* @__PURE__ */ new Set();
|
|
66
|
+
try {
|
|
67
|
+
const automaticSetup = connected.session.capabilities.onboarding_v2 === true;
|
|
68
|
+
const result = await runSetup(connected.client, project, {
|
|
69
|
+
signal,
|
|
70
|
+
automaticSetup,
|
|
71
|
+
onOperationError({ kind, message, receiptPath }) {
|
|
72
|
+
terminal.block(`${kind === "install_packages" ? "Package installation" : kind.replaceAll("_", " ")} failed`, [
|
|
73
|
+
...message.split("\n").map(clean),
|
|
74
|
+
`Local diagnostic receipt: ${receiptPath}`,
|
|
75
|
+
"The detailed error stays on this computer; the browser receives only the operation status."
|
|
76
|
+
]);
|
|
77
|
+
},
|
|
78
|
+
onSession(session) {
|
|
79
|
+
for (const step of session.local_plan?.manual_steps ?? []) {
|
|
80
|
+
const key = `${step.kind}:${step.code}`;
|
|
81
|
+
if (shownManual.has(key)) continue;
|
|
82
|
+
shownManual.add(key);
|
|
83
|
+
terminal.block(`Manual step: ${step.kind}`, [setupManualGuidance[step.kind]]);
|
|
84
|
+
}
|
|
85
|
+
const next = `${session.phase}:${session.source?.status ?? ""}:${session.sample.status}`;
|
|
86
|
+
if (next === status) return;
|
|
87
|
+
status = next;
|
|
88
|
+
const messages = {
|
|
89
|
+
configuring: "Choose the workspace, site and installation options in the browser.",
|
|
90
|
+
awaiting_local_approval: automaticSetup ? "Choose your setup options in the browser." : "Review and approve the exact local changes in the browser.",
|
|
91
|
+
applying: "Applying browser-approved local changes.",
|
|
92
|
+
ready_for_recommendations: !session.capabilities.source_review ? session.commands.some((command) => ["failed", "manual", "outcome_unknown"].includes(command.status)) ? "Setup needs attention. Check the error above and review the results in the browser." : session.capabilities.sample_read ? "Finish setup or try the optional agent check in the browser." : "Finish setup in the browser." : !automaticSetup && session.source?.status === "pending" ? "Review source files and provider details in the browser before any source upload." : "Continue with recommendations or skip that step in the browser.",
|
|
93
|
+
analyzing: automaticSetup ? "Preparing survey suggestions from your project." : "Analyzing the source packet approved in the browser.",
|
|
94
|
+
selecting_drafts: "Review recommendations and select drafts in the browser.",
|
|
95
|
+
creating_drafts: "Creating only the drafts selected in the browser.",
|
|
96
|
+
agent_test: session.sample.status === "received" ? "Simulated sample received. Finish or skip in the browser." : "Complete or skip the optional agent test in the browser.",
|
|
97
|
+
complete: "Browser setup completed.",
|
|
98
|
+
cancelled: "Browser setup cancelled. Applied changes and created drafts are listed below.",
|
|
99
|
+
expired: "Browser setup expired. Applied changes and created drafts are listed below."
|
|
100
|
+
};
|
|
101
|
+
terminal.info(messages[session.phase]);
|
|
102
|
+
},
|
|
103
|
+
onSourceIssue(code) {
|
|
104
|
+
if (automaticSetup) {
|
|
105
|
+
terminal.warn(`Survey suggestions need attention (${clean(code)}). Retry in the browser or continue without suggestions.`);
|
|
106
|
+
return;
|
|
107
|
+
}
|
|
108
|
+
terminal.warn(`Source analysis needs review (${clean(code)}). Check the browser status, then retry source review or skip it. Changed local source requires fresh approval.`);
|
|
109
|
+
},
|
|
110
|
+
onSourcePrepared(packet) {
|
|
111
|
+
if (automaticSetup) return;
|
|
112
|
+
if (displayedPacket === packet.manifest.packet_digest) return;
|
|
113
|
+
displayedPacket = packet.manifest.packet_digest;
|
|
114
|
+
terminal.block("Local source review", [
|
|
115
|
+
"The exact bounded excerpts below stay local until you approve this packet and its providers in the browser.",
|
|
116
|
+
`Packet SHA-256: ${packet.manifest.packet_digest}`,
|
|
117
|
+
...packet.evidence.flatMap((item) => [`${clean(item.path)}:${item.start_line}-${item.end_line} (file SHA-256 ${item.file_hash})`, ...item.excerpt.split("\n").map((line) => `> ${clean(line)}`)]),
|
|
118
|
+
`Omitted files: ${packet.manifest.omitted_files}. Truncated: ${packet.manifest.truncated ? "yes" : "no"}. Git history is excluded.`
|
|
119
|
+
]);
|
|
120
|
+
},
|
|
121
|
+
onSample(session) {
|
|
122
|
+
terminal.block("Try your agent", ["Ask: What do UserReason dummy respondents think?", "Tell your agent to read this setup\u2019s simulated sample, using:", setupSampleCommand(session.setup_id, apiOrigin, input.profile.cliVersion, input.profile), "This is example data. It does not read production responses or grant ongoing CLI access."]);
|
|
123
|
+
}
|
|
124
|
+
});
|
|
125
|
+
const summary = setupSummary(result);
|
|
126
|
+
const needsAttention = result.commands.some((command) => ["failed", "manual", "outcome_unknown"].includes(command.status));
|
|
127
|
+
terminal.block("Setup result", [
|
|
128
|
+
`Status: ${result.phase}${needsAttention ? " (installation needs attention)" : ""}`,
|
|
129
|
+
...summary.local_operations.map((operation) => `${operation.kind}: ${operation.status}${operation.code ? ` (${operation.code})` : ""}`),
|
|
130
|
+
...summary.manual_steps.map((step) => `${step.kind}: manual (${step.code})`),
|
|
131
|
+
...summary.drafts.map((draft) => `Draft ${draft.prompt_id}: ${draft.status}${draft.revision ? ` (revision ${draft.revision})` : ""}`),
|
|
132
|
+
`Simulated sample: ${summary.sample}`,
|
|
133
|
+
"Ongoing CLI access was not requested. Use a separate `userreason login --open` when you want to authorize it."
|
|
134
|
+
]);
|
|
135
|
+
if (input.json) process.stdout.write(`${JSON.stringify(summary)}
|
|
136
|
+
`);
|
|
137
|
+
if (result.phase === "cancelled") process.exitCode = 130;
|
|
138
|
+
else if (result.phase !== "complete" || needsAttention) process.exitCode = 1;
|
|
139
|
+
return true;
|
|
140
|
+
} catch (error) {
|
|
141
|
+
terminal.info(`Resume from this project: ${resume}`);
|
|
142
|
+
throw error;
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
export {
|
|
147
|
+
setupSampleCommand,
|
|
148
|
+
setupResumeCommand,
|
|
149
|
+
setupManualGuidance,
|
|
150
|
+
setupSummary,
|
|
151
|
+
runBrowserWizard
|
|
152
|
+
};
|
|
@@ -7,7 +7,7 @@ import {
|
|
|
7
7
|
plainLine,
|
|
8
8
|
stripAnsi,
|
|
9
9
|
textWidth
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-7AAH6C4L.js";
|
|
11
11
|
import {
|
|
12
12
|
__commonJS,
|
|
13
13
|
__toESM
|
|
@@ -1235,6 +1235,7 @@ function approvalProgressMessage(progress) {
|
|
|
1235
1235
|
var Cancelled = class extends Error {
|
|
1236
1236
|
constructor() {
|
|
1237
1237
|
super("Installation cancelled.");
|
|
1238
|
+
this.name = "Cancelled";
|
|
1238
1239
|
}
|
|
1239
1240
|
};
|
|
1240
1241
|
var clean = (value) => value.replace(/\r\n?/g, "\n").replace(/\t/g, " ").replace(/[\x00-\x09\x0b-\x1f\x7f-\x9f]/g, "");
|
|
@@ -1279,6 +1280,7 @@ var Terminal = class {
|
|
|
1279
1280
|
constructor(interactive, json, options = {}) {
|
|
1280
1281
|
this.interactive = interactive;
|
|
1281
1282
|
this.json = json;
|
|
1283
|
+
this.onCancel = options.onCancel;
|
|
1282
1284
|
this.kit = createUiKit({ level: detectColorLevel({ stream: process.stdout, off: options.color === false }) });
|
|
1283
1285
|
}
|
|
1284
1286
|
interactive;
|
|
@@ -1288,6 +1290,7 @@ var Terminal = class {
|
|
|
1288
1290
|
cancelState = "nothing was written";
|
|
1289
1291
|
/** True after output that leaves no guide line behind, so the next event adds one. */
|
|
1290
1292
|
gap = false;
|
|
1293
|
+
onCancel;
|
|
1291
1294
|
header(options) {
|
|
1292
1295
|
const lines = this.kit.header({ ...options, trademark: this.interactive });
|
|
1293
1296
|
if (this.interactive) for (const line of lines) process.stdout.write(cleanStyled(line) + "\n");
|
|
@@ -1373,6 +1376,10 @@ var Terminal = class {
|
|
|
1373
1376
|
cancelled(afterSpinner = false) {
|
|
1374
1377
|
if (this.interactive && afterSpinner) process.stdout.write("\n");
|
|
1375
1378
|
this.error(`Cancelled ${this.kit.c.muted(`${this.kit.S.dot} ${this.cancelState}`)}`);
|
|
1379
|
+
if (this.onCancel) {
|
|
1380
|
+
this.onCancel();
|
|
1381
|
+
return;
|
|
1382
|
+
}
|
|
1376
1383
|
process.exit(130);
|
|
1377
1384
|
}
|
|
1378
1385
|
async text(message, initialValue, validate) {
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { createRequire as createWizardRequire } from 'node:module'; import { fileURLToPath as wizardFileURLToPath } from 'node:url'; import { dirname as wizardDirname } from 'node:path'; const require = createWizardRequire(import.meta.url); const __filename = wizardFileURLToPath(import.meta.url); const __dirname = wizardDirname(__filename);
|
|
2
|
+
import {
|
|
3
|
+
TELEMETRY_REASONS,
|
|
4
|
+
ToolTelemetry
|
|
5
|
+
} from "./chunk-7AAH6C4L.js";
|
|
6
|
+
|
|
7
|
+
// src/analytics.ts
|
|
8
|
+
var WizardAnalytics = class extends ToolTelemetry {
|
|
9
|
+
starts = /* @__PURE__ */ new Map();
|
|
10
|
+
begin(step) {
|
|
11
|
+
this.starts.set(step, performance.now());
|
|
12
|
+
this.step(step, "started");
|
|
13
|
+
}
|
|
14
|
+
end(step, phase = "completed") {
|
|
15
|
+
const start = this.starts.get(step);
|
|
16
|
+
this.step(step, phase, start === void 0 ? {} : { duration_ms: performance.now() - start });
|
|
17
|
+
this.starts.delete(step);
|
|
18
|
+
}
|
|
19
|
+
async measure(step, operation, phase = "applied") {
|
|
20
|
+
const start = performance.now();
|
|
21
|
+
this.begin(step);
|
|
22
|
+
await this.checkpoint();
|
|
23
|
+
try {
|
|
24
|
+
const value = await operation();
|
|
25
|
+
const result = value && typeof value === "object" ? value : void 0;
|
|
26
|
+
const outcome = result?.reason === "user_cancelled" ? "cancelled" : result?.status === "already_present" ? "already_present" : result?.status === "declined" ? "declined" : result?.status === "skipped" ? "skipped" : result?.status === "failed" ? "failed" : phase;
|
|
27
|
+
const reason = result?.reason && TELEMETRY_REASONS.includes(result.reason) ? result.reason : result?.reason?.includes("review") ? "validation_failed" : result?.reason?.includes("preserved") || result?.reason === "existing_feedback_section" ? "existing_content_preserved" : outcome === "failed" ? "operation_failed" : outcome === "skipped" ? "unsupported" : void 0;
|
|
28
|
+
this.step(step, outcome, { duration_ms: performance.now() - start, ...reason ? { reason } : {}, ...result?.file === "AGENTS.md" || result?.file === "CLAUDE.md" ? { guidance_file: result.file } : {} });
|
|
29
|
+
this.starts.delete(step);
|
|
30
|
+
return value;
|
|
31
|
+
} catch (error) {
|
|
32
|
+
this.step(step, error instanceof Error && error.name === "Cancelled" ? "cancelled" : "failed", { duration_ms: performance.now() - start, reason: error instanceof Error && error.name === "Cancelled" ? "user_cancelled" : "operation_failed" });
|
|
33
|
+
this.starts.delete(step);
|
|
34
|
+
throw error;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
finish(cancelled = false, failed = false) {
|
|
38
|
+
for (const step of [...this.starts.keys()].reverse()) this.end(step, cancelled ? "cancelled" : failed ? "failed" : "completed");
|
|
39
|
+
}
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
export {
|
|
43
|
+
WizardAnalytics
|
|
44
|
+
};
|
|
@@ -3,10 +3,10 @@ import {
|
|
|
3
3
|
DEFAULT_API,
|
|
4
4
|
initializationSource,
|
|
5
5
|
integrationSource
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-TOID3NYP.js";
|
|
7
7
|
import {
|
|
8
8
|
require_typescript
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-7AAH6C4L.js";
|
|
10
10
|
import {
|
|
11
11
|
__toESM
|
|
12
12
|
} from "./chunk-WL3NOIM6.js";
|
|
@@ -7342,8 +7342,8 @@ import { lstat, readFile, open } from "node:fs/promises";
|
|
|
7342
7342
|
import { join } from "node:path";
|
|
7343
7343
|
import { execFile } from "node:child_process";
|
|
7344
7344
|
import { promisify } from "node:util";
|
|
7345
|
-
async function
|
|
7346
|
-
if (profile.kind !== "local-development") return;
|
|
7345
|
+
async function planPackageRegistry(project, profile) {
|
|
7346
|
+
if (profile.kind !== "local-development") return null;
|
|
7347
7347
|
const modernYarn = project.packageManager === "yarn" && (project.yarnMajor ?? 1) >= 2;
|
|
7348
7348
|
const path = join(project.directory, modernYarn ? ".yarnrc.yml" : ".npmrc");
|
|
7349
7349
|
let before = "", metadata;
|
|
@@ -7382,7 +7382,13 @@ async function configurePackageRegistry(project, profile) {
|
|
|
7382
7382
|
after = configured === profile.registry ? before : `${before}${before && !before.endsWith("\n") ? "\n" : ""}${line}
|
|
7383
7383
|
`;
|
|
7384
7384
|
}
|
|
7385
|
-
|
|
7385
|
+
return { path, before: metadata ? before : null, after };
|
|
7386
|
+
}
|
|
7387
|
+
async function configurePackageRegistry(project, profile) {
|
|
7388
|
+
const plan = await planPackageRegistry(project, profile);
|
|
7389
|
+
if (!plan || plan.after === plan.before) return;
|
|
7390
|
+
const { path, after } = plan, before = plan.before ?? "";
|
|
7391
|
+
const metadata = plan.before === null ? null : await lstat(path);
|
|
7386
7392
|
const handle = await open(path, metadata ? constants.O_WRONLY | (constants.O_NOFOLLOW ?? 0) : "wx", 420);
|
|
7387
7393
|
try {
|
|
7388
7394
|
if (metadata) {
|
|
@@ -7399,5 +7405,6 @@ async function configurePackageRegistry(project, profile) {
|
|
|
7399
7405
|
|
|
7400
7406
|
export {
|
|
7401
7407
|
require_dist,
|
|
7408
|
+
planPackageRegistry,
|
|
7402
7409
|
configurePackageRegistry
|
|
7403
7410
|
};
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { createRequire as createWizardRequire } from 'node:module'; import { fileURLToPath as wizardFileURLToPath } from 'node:url'; import { dirname as wizardDirname } from 'node:path'; const require = createWizardRequire(import.meta.url); const __filename = wizardFileURLToPath(import.meta.url); const __dirname = wizardDirname(__filename);
|
|
2
2
|
import {
|
|
3
3
|
currentPackageProfile
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-7AAH6C4L.js";
|
|
5
5
|
|
|
6
6
|
// src/startup.ts
|
|
7
7
|
import { readFile } from "node:fs/promises";
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { createRequire as createWizardRequire } from 'node:module'; import { fileURLToPath as wizardFileURLToPath } from 'node:url'; import { dirname as wizardDirname } from 'node:path'; const require = createWizardRequire(import.meta.url); const __filename = wizardFileURLToPath(import.meta.url); const __dirname = wizardDirname(__filename);
|
|
2
|
+
import {
|
|
3
|
+
sanitizeSetupDiagnostic
|
|
4
|
+
} from "./chunk-7AAH6C4L.js";
|
|
5
|
+
|
|
6
|
+
// src/install-diagnostics.ts
|
|
7
|
+
import { readFile, readdir, stat } from "node:fs/promises";
|
|
8
|
+
import { homedir } from "node:os";
|
|
9
|
+
import { join } from "node:path";
|
|
10
|
+
async function installFailureDetails(directory, cache, output) {
|
|
11
|
+
const secrets = [], missing = /* @__PURE__ */ new Set();
|
|
12
|
+
for (const path of /* @__PURE__ */ new Set([join(directory, ".npmrc"), process.env.npm_config_userconfig ?? process.env.NPM_CONFIG_USERCONFIG ?? join(homedir(), ".npmrc")])) {
|
|
13
|
+
try {
|
|
14
|
+
if ((await stat(path)).size > 1e6) continue;
|
|
15
|
+
for (const line of (await readFile(path, "utf8")).split(/\r?\n/)) {
|
|
16
|
+
const match = /^\s*[^=]*(?:_authToken|_auth|_password)\s*=\s*(.+)$/i.exec(line);
|
|
17
|
+
if (!match) continue;
|
|
18
|
+
const value = match[1].trim();
|
|
19
|
+
const variable = /^\$\{([A-Za-z_][A-Za-z0-9_]*)\}$/.exec(value);
|
|
20
|
+
if (variable) {
|
|
21
|
+
if (!process.env[variable[1]]) missing.add(variable[1]);
|
|
22
|
+
} else secrets.push(value);
|
|
23
|
+
}
|
|
24
|
+
} catch {
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
const requests = /* @__PURE__ */ new Set();
|
|
28
|
+
if (cache) try {
|
|
29
|
+
const folder = join(cache, "_logs");
|
|
30
|
+
for (const name of (await readdir(folder)).filter((name2) => name2.endsWith("-debug-0.log")).sort().slice(-3)) {
|
|
31
|
+
const path = join(folder, name);
|
|
32
|
+
if ((await stat(path)).size > 2e6) continue;
|
|
33
|
+
for (const line of (await readFile(path, "utf8")).split("\n")) {
|
|
34
|
+
const match = /\bhttp fetch (GET|POST|PUT) ([45]\d\d) (https?:\/\/\S+)/.exec(line);
|
|
35
|
+
if (match && requests.size < 12) requests.add(`${match[2]} ${match[1]} ${match[3]}`);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
} catch {
|
|
39
|
+
}
|
|
40
|
+
const lines = output.split(/\r?\n/).filter((line) => !/complete log of this run|npm notice/.test(line)).slice(-45);
|
|
41
|
+
return sanitizeSetupDiagnostic([
|
|
42
|
+
...requests,
|
|
43
|
+
...lines,
|
|
44
|
+
...[...missing].map((name) => `Authentication variable ${name} is not set in the wizard process.`)
|
|
45
|
+
].join("\n"), secrets);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
export {
|
|
49
|
+
installFailureDetails
|
|
50
|
+
};
|