@remotedraw/cli 0.1.2 → 0.1.3
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 +23 -1
- package/dist/cli.d.ts +4 -1
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +247 -65
- package/dist/index.js +19 -2
- package/dist/setup-wizard.d.ts +9 -1
- package/dist/setup-wizard.d.ts.map +1 -1
- package/dist/setup-wizard.js +554 -77
- package/dist/update.d.ts +53 -0
- package/dist/update.d.ts.map +1 -0
- package/dist/update.js +235 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -88,7 +88,29 @@ remotedraw doctor
|
|
|
88
88
|
```
|
|
89
89
|
|
|
90
90
|
It checks the project configuration, installed packages, environment values,
|
|
91
|
-
and—when credentials are available—the RemoteDraw
|
|
91
|
+
the installed CLI version, and—when credentials are available—the RemoteDraw
|
|
92
|
+
API connection.
|
|
93
|
+
|
|
94
|
+
Without an override, commands talk to `https://api.remotedraw.com`. Doctor
|
|
95
|
+
prints the API base URL it resolved and where that value came from, so a
|
|
96
|
+
`.env.local` pointing at a non-production deployment is visible rather than
|
|
97
|
+
silent.
|
|
98
|
+
|
|
99
|
+
## Update the CLI
|
|
100
|
+
|
|
101
|
+
`npm install -g` pins the version it installed and never revisits it, so a
|
|
102
|
+
global RemoteDraw CLI stays on whatever release you first installed:
|
|
103
|
+
|
|
104
|
+
```sh
|
|
105
|
+
remotedraw update # install the latest published version
|
|
106
|
+
remotedraw update --check # report it without installing
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
`update` detects whether the binary came from npm, pnpm, yarn, or bun and runs
|
|
110
|
+
that package manager. Other commands check the registry at most once a day and
|
|
111
|
+
print a one-line notice when a newer version exists; that notice only appears on
|
|
112
|
+
an interactive terminal, and `REMOTEDRAW_CLI_NO_UPDATE_CHECK=1`, `CI`, or
|
|
113
|
+
`NO_UPDATE_NOTIFIER` disable it.
|
|
92
114
|
|
|
93
115
|
Useful account commands:
|
|
94
116
|
|
package/dist/cli.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { type WizardDefinition, type WizardTerminal } from "./setup-wizard.js";
|
|
2
2
|
import { type CloudRuntime } from "./cloud.js";
|
|
3
|
+
import { type UpdateRuntime } from "./update.js";
|
|
3
4
|
export declare const CLI_VERSION: string;
|
|
4
5
|
export type CliResult = {
|
|
5
6
|
exitCode: number;
|
|
@@ -27,8 +28,10 @@ export type CliPrompter = {
|
|
|
27
28
|
text: (options: TextPromptOptions) => Promise<string>;
|
|
28
29
|
select: <T extends string>(options: SelectPromptOptions<T>) => Promise<T>;
|
|
29
30
|
};
|
|
30
|
-
export type CliRuntime = CloudRuntime & {
|
|
31
|
+
export type CliRuntime = CloudRuntime & UpdateRuntime & {
|
|
31
32
|
cwd: string;
|
|
33
|
+
/** Absolute path of the running binary; drives update-command detection. */
|
|
34
|
+
binPath?: string;
|
|
32
35
|
prompts?: CliPrompter;
|
|
33
36
|
wizardTerminal?: WizardTerminal | undefined;
|
|
34
37
|
};
|
package/dist/cli.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
|
package/dist/cli.js
CHANGED
|
@@ -3,10 +3,12 @@ import { chmod, mkdir, readFile, writeFile } from "node:fs/promises";
|
|
|
3
3
|
import { spawn } from "node:child_process";
|
|
4
4
|
import path from "node:path";
|
|
5
5
|
import process from "node:process";
|
|
6
|
+
import { fileURLToPath } from "node:url";
|
|
6
7
|
import { emitKeypressEvents } from "node:readline";
|
|
7
8
|
import { createInterface } from "node:readline/promises";
|
|
8
9
|
import { createWizardTerminal, runSetupWizard, } from "./setup-wizard.js";
|
|
9
|
-
import { assertEnvCanAcceptProvisioning, currentCliAccount, globalConfigPath, loginToRemoteDraw, logoutFromRemoteDraw, provisionRemoteDrawProject, remoteDrawApiBaseUrl, writeProvisionedProjectSetup, } from "./cloud.js";
|
|
10
|
+
import { assertEnvCanAcceptProvisioning, currentCliAccount, DEFAULT_REMOTEDRAW_API_BASE_URL, globalConfigPath, loginToRemoteDraw, logoutFromRemoteDraw, provisionRemoteDrawProject, remoteDrawApiBaseUrl, writeProvisionedProjectSetup, } from "./cloud.js";
|
|
11
|
+
import { checkForUpdate, CLI_PACKAGE_NAME, detectInstallMethod, installMethodDisplay, runInstall, } from "./update.js";
|
|
10
12
|
const packageMetadata = JSON.parse(readFileSync(new URL("../package.json", import.meta.url), "utf8"));
|
|
11
13
|
export const CLI_VERSION = typeof packageMetadata.version === "string"
|
|
12
14
|
? packageMetadata.version
|
|
@@ -45,8 +47,10 @@ export function createNodeRuntime() {
|
|
|
45
47
|
return {
|
|
46
48
|
cwd,
|
|
47
49
|
env,
|
|
50
|
+
binPath: process.argv[1] ?? fileURLToPath(import.meta.url),
|
|
48
51
|
isInteractive: Boolean(process.stdin.isTTY && process.stderr.isTTY),
|
|
49
52
|
exists: existsSync,
|
|
53
|
+
spawnCommand: runChildCommand,
|
|
50
54
|
readFile: async (filePath) => {
|
|
51
55
|
return await readFile(filePath, "utf8");
|
|
52
56
|
},
|
|
@@ -78,6 +82,18 @@ export function cliEnvironmentForWorkspace(cwd, env, exists = existsSync) {
|
|
|
78
82
|
? { ...env, REMOTEDRAW_API_BASE_URL: env.CONVEX_SITE_URL }
|
|
79
83
|
: env;
|
|
80
84
|
}
|
|
85
|
+
async function runChildCommand(command, args) {
|
|
86
|
+
return await new Promise((resolve, reject) => {
|
|
87
|
+
const child = spawn(command, args, {
|
|
88
|
+
stdio: "inherit",
|
|
89
|
+
// Windows resolves npm/pnpm/yarn through .cmd shims, which need a shell.
|
|
90
|
+
shell: process.platform === "win32",
|
|
91
|
+
windowsHide: true,
|
|
92
|
+
});
|
|
93
|
+
child.once("error", reject);
|
|
94
|
+
child.once("close", (code) => resolve({ exitCode: code ?? 1 }));
|
|
95
|
+
});
|
|
96
|
+
}
|
|
81
97
|
async function openExternalUrl(url) {
|
|
82
98
|
const parsed = new URL(url);
|
|
83
99
|
if (parsed.protocol !== "https:" && parsed.protocol !== "http:") {
|
|
@@ -154,7 +170,7 @@ function terminalSelect(input, output, options) {
|
|
|
154
170
|
const selected = options.choices[selectedIndex];
|
|
155
171
|
cleanup();
|
|
156
172
|
clearRendered(output, renderedLines);
|
|
157
|
-
output.write(`${style("
|
|
173
|
+
output.write(`${style("green", "✓")} ${options.message} ${style("green", selected.label)}\n`);
|
|
158
174
|
resolve(selected.value);
|
|
159
175
|
};
|
|
160
176
|
const fail = () => {
|
|
@@ -197,18 +213,19 @@ function terminalSelect(input, output, options) {
|
|
|
197
213
|
});
|
|
198
214
|
}
|
|
199
215
|
function selectPromptLines(options, selectedIndex) {
|
|
200
|
-
const lines = [`${style("cyan", "?")} ${options.message}`];
|
|
216
|
+
const lines = [`${style("cyan", "?")} ${style("bold", options.message)}`];
|
|
201
217
|
if (options.helperText)
|
|
202
218
|
lines.push(style("dim", options.helperText));
|
|
203
219
|
for (const [index, choiceOption] of options.choices.entries()) {
|
|
204
220
|
const selected = index === selectedIndex;
|
|
221
|
+
const marker = selected ? style("cyan", "❯ ◉") : style("dim", " ○");
|
|
205
222
|
const label = selected
|
|
206
223
|
? style("bold", choiceOption.label)
|
|
207
224
|
: choiceOption.label;
|
|
208
225
|
const hint = choiceOption.hint ? ` ${style("dim", choiceOption.hint)}` : "";
|
|
209
|
-
lines.push(`${
|
|
226
|
+
lines.push(`${marker} ${label}${hint}`);
|
|
210
227
|
}
|
|
211
|
-
lines.push(style("dim", "
|
|
228
|
+
lines.push(`${style("dim", "↑/↓")} move · ${style("dim", "Enter")} select · ${style("dim", "Ctrl+C")} quit`);
|
|
212
229
|
return lines;
|
|
213
230
|
}
|
|
214
231
|
function clearRendered(output, lineCount) {
|
|
@@ -255,6 +272,8 @@ export async function runCli(args, runtime = createNodeRuntime()) {
|
|
|
255
272
|
return await newCommand(commandArgs, runtime);
|
|
256
273
|
case "init":
|
|
257
274
|
return await initCommand(commandArgs, runtime);
|
|
275
|
+
case "update":
|
|
276
|
+
return await updateCommand(commandArgs, runtime);
|
|
258
277
|
case "doctor":
|
|
259
278
|
return await doctorCommand(commandArgs, runtime);
|
|
260
279
|
case "dev":
|
|
@@ -362,6 +381,7 @@ function mainHelpText() {
|
|
|
362
381
|
" init Add RemoteDraw starter code to an existing project.",
|
|
363
382
|
" dev Print the local sandbox workflow for an integration.",
|
|
364
383
|
" doctor Check project config, packages, and environment variables.",
|
|
384
|
+
" update Install the latest published RemoteDraw CLI.",
|
|
365
385
|
" create-input Create or print a test input request payload.",
|
|
366
386
|
" examples List or install example projects.",
|
|
367
387
|
" agent Print or install the RemoteDraw agent skill.",
|
|
@@ -679,9 +699,89 @@ async function probeApiKey(runtime, apiBaseUrl, apiKey) {
|
|
|
679
699
|
return { ok: false, message: probeFailureMessage(error) };
|
|
680
700
|
}
|
|
681
701
|
}
|
|
702
|
+
/**
|
|
703
|
+
* npm never refreshes a globally installed binary on its own, so staying
|
|
704
|
+
* current is an explicit step. This command makes that step one word.
|
|
705
|
+
*/
|
|
706
|
+
async function updateCommand(args, runtime) {
|
|
707
|
+
const parsed = parseArgs(args, {
|
|
708
|
+
values: ["format"],
|
|
709
|
+
booleans: ["check", "help"],
|
|
710
|
+
});
|
|
711
|
+
if (parsed.booleans.has("help"))
|
|
712
|
+
return ok(updateHelpText());
|
|
713
|
+
const format = outputFormat(parsed);
|
|
714
|
+
const checkOnly = parsed.booleans.has("check");
|
|
715
|
+
const method = detectInstallMethod(runtime.binPath ?? "");
|
|
716
|
+
const command = installMethodDisplay(method);
|
|
717
|
+
// `remotedraw update` is an explicit request, so it ignores the cache and the
|
|
718
|
+
// ambient opt-outs that only silence the passive notice.
|
|
719
|
+
const check = await checkForUpdate(runtime, CLI_VERSION, { force: true });
|
|
720
|
+
if (!check) {
|
|
721
|
+
const message = `Could not reach the npm registry to check for ${CLI_PACKAGE_NAME} updates. Run ${command} to update anyway.`;
|
|
722
|
+
return format === "json"
|
|
723
|
+
? jsonFailure("update", new Error(message))
|
|
724
|
+
: fail(message);
|
|
725
|
+
}
|
|
726
|
+
if (!check.updateAvailable) {
|
|
727
|
+
const message = `${CLI_PACKAGE_NAME} ${check.current} is already the latest version.`;
|
|
728
|
+
return format === "json"
|
|
729
|
+
? jsonResult({ ok: true, command: "update", ...check, updated: false })
|
|
730
|
+
: ok(message);
|
|
731
|
+
}
|
|
732
|
+
if (checkOnly || method.ephemeral) {
|
|
733
|
+
const message = method.ephemeral
|
|
734
|
+
? [
|
|
735
|
+
`Update available: ${check.current} -> ${check.latest}.`,
|
|
736
|
+
`This CLI was run through npx/bunx, which resolves a version per run. Use ${CLI_PACKAGE_NAME}@latest instead of updating in place.`,
|
|
737
|
+
].join("\n")
|
|
738
|
+
: [
|
|
739
|
+
`Update available: ${check.current} -> ${check.latest}.`,
|
|
740
|
+
`Run ${command} to install it.`,
|
|
741
|
+
].join("\n");
|
|
742
|
+
return format === "json"
|
|
743
|
+
? jsonResult({
|
|
744
|
+
ok: true,
|
|
745
|
+
command: "update",
|
|
746
|
+
...check,
|
|
747
|
+
updated: false,
|
|
748
|
+
installCommand: command,
|
|
749
|
+
ephemeral: method.ephemeral,
|
|
750
|
+
})
|
|
751
|
+
: ok(message);
|
|
752
|
+
}
|
|
753
|
+
const install = await runInstall(runtime, method);
|
|
754
|
+
if (!install.ran) {
|
|
755
|
+
const message = `Update available: ${check.current} -> ${check.latest}. Run ${command} to install it.`;
|
|
756
|
+
return format === "json"
|
|
757
|
+
? jsonResult({
|
|
758
|
+
ok: true,
|
|
759
|
+
command: "update",
|
|
760
|
+
...check,
|
|
761
|
+
updated: false,
|
|
762
|
+
installCommand: command,
|
|
763
|
+
})
|
|
764
|
+
: ok(message);
|
|
765
|
+
}
|
|
766
|
+
if (install.exitCode !== 0) {
|
|
767
|
+
const message = `${command} failed with exit code ${install.exitCode}.`;
|
|
768
|
+
return format === "json"
|
|
769
|
+
? jsonFailure("update", new Error(message))
|
|
770
|
+
: fail(message);
|
|
771
|
+
}
|
|
772
|
+
return format === "json"
|
|
773
|
+
? jsonResult({
|
|
774
|
+
ok: true,
|
|
775
|
+
command: "update",
|
|
776
|
+
...check,
|
|
777
|
+
updated: true,
|
|
778
|
+
installCommand: command,
|
|
779
|
+
})
|
|
780
|
+
: ok(`Updated ${CLI_PACKAGE_NAME} to ${check.latest}.`);
|
|
781
|
+
}
|
|
682
782
|
async function doctorCommand(args, runtime) {
|
|
683
783
|
const parsed = parseArgs(args, {
|
|
684
|
-
values: ["path", "format"],
|
|
784
|
+
values: ["path", "format", "api-base-url"],
|
|
685
785
|
booleans: ["help", "offline"],
|
|
686
786
|
});
|
|
687
787
|
if (parsed.booleans.has("help"))
|
|
@@ -693,10 +793,8 @@ async function doctorCommand(args, runtime) {
|
|
|
693
793
|
const projectEnv = await environmentForProject(dir, runtime);
|
|
694
794
|
const configPath = path.join(dir, "remotedraw.config.json");
|
|
695
795
|
const packagePath = path.join(dir, "package.json");
|
|
696
|
-
const
|
|
697
|
-
const normalizedEnvApiBaseUrl =
|
|
698
|
-
? undefined
|
|
699
|
-
: normalizedOrigin(envApiBaseUrl);
|
|
796
|
+
const apiBaseUrl = resolveDoctorApiBaseUrl(projectEnv, readString(parsed, "api-base-url"));
|
|
797
|
+
const normalizedEnvApiBaseUrl = apiBaseUrl.state === "ok" ? apiBaseUrl.url : undefined;
|
|
700
798
|
const envApiKey = projectEnv.REMOTEDRAW_API_KEY;
|
|
701
799
|
const lines = ["RemoteDraw doctor", ""];
|
|
702
800
|
const checks = [];
|
|
@@ -721,9 +819,11 @@ async function doctorCommand(args, runtime) {
|
|
|
721
819
|
? "React SDK dependency is installed in package.json."
|
|
722
820
|
: "Install @remotedraw/react or rerun remotedraw init.");
|
|
723
821
|
}
|
|
724
|
-
addCheck(
|
|
725
|
-
?
|
|
726
|
-
:
|
|
822
|
+
addCheck(apiBaseUrl.state === "ok"
|
|
823
|
+
? "ok"
|
|
824
|
+
: apiBaseUrl.state === "placeholder"
|
|
825
|
+
? "warn"
|
|
826
|
+
: "error", "REMOTEDRAW_API_BASE_URL", doctorApiBaseUrlMessage(apiBaseUrl));
|
|
727
827
|
addCheck(envApiKey?.startsWith("rd_sk_") ? "ok" : "warn", "REMOTEDRAW_API_KEY", envApiKey?.startsWith("rd_sk_")
|
|
728
828
|
? "Server-side API key shape looks correct."
|
|
729
829
|
: "Keep an rd_sk_... key in backend secrets only.");
|
|
@@ -734,7 +834,7 @@ async function doctorCommand(args, runtime) {
|
|
|
734
834
|
addCheck("warn", "deployment", "Skipped network checks (--offline). Rerun without --offline to verify the key against the deployment.");
|
|
735
835
|
}
|
|
736
836
|
else if (!normalizedEnvApiBaseUrl) {
|
|
737
|
-
addCheck("warn", "deployment", "Skipped network checks because REMOTEDRAW_API_BASE_URL is not
|
|
837
|
+
addCheck("warn", "deployment", "Skipped network checks because REMOTEDRAW_API_BASE_URL is not a usable HTTP origin.");
|
|
738
838
|
}
|
|
739
839
|
else {
|
|
740
840
|
const health = await probeApiHealth(runtime, normalizedEnvApiBaseUrl);
|
|
@@ -754,6 +854,19 @@ async function doctorCommand(args, runtime) {
|
|
|
754
854
|
: probe.message);
|
|
755
855
|
}
|
|
756
856
|
}
|
|
857
|
+
// A stale global install is the quietest failure mode there is: npm pins the
|
|
858
|
+
// binary at install time and never revisits it, so doctor has to say so.
|
|
859
|
+
if (offline) {
|
|
860
|
+
addCheck("warn", "CLI version", `Running ${CLI_VERSION}. Skipped the update check (--offline).`);
|
|
861
|
+
}
|
|
862
|
+
else {
|
|
863
|
+
const update = await checkForUpdate(runtime, CLI_VERSION, { force: true });
|
|
864
|
+
addCheck(!update || !update.updateAvailable ? "ok" : "warn", "CLI version", !update
|
|
865
|
+
? `Running ${CLI_VERSION}. Could not reach the npm registry to check for updates.`
|
|
866
|
+
: update.updateAvailable
|
|
867
|
+
? `Running ${update.current}; ${update.latest} is published. Run remotedraw update.`
|
|
868
|
+
: `Running ${update.current}, the latest published version.`);
|
|
869
|
+
}
|
|
757
870
|
return format === "json"
|
|
758
871
|
? jsonResult({
|
|
759
872
|
ok: true,
|
|
@@ -992,13 +1105,27 @@ function whoamiHelpText() {
|
|
|
992
1105
|
function doctorHelpText() {
|
|
993
1106
|
return [
|
|
994
1107
|
"Usage:",
|
|
995
|
-
" remotedraw doctor [--path <dir>] [--format text|json] [--offline]",
|
|
1108
|
+
" remotedraw doctor [--path <dir>] [--api-base-url <url>] [--format text|json] [--offline]",
|
|
996
1109
|
"",
|
|
997
1110
|
"Checks local config, package.json dependencies, and the REMOTEDRAW_API_BASE_URL / REMOTEDRAW_API_KEY environment variables.",
|
|
1111
|
+
`Without an override the API base URL is ${DEFAULT_REMOTEDRAW_API_BASE_URL}; doctor names the source so a non-production URL is visible.`,
|
|
998
1112
|
"Then reaches the deployment: GET /health, and a free POST /v1/sessions/list to confirm the API key is live.",
|
|
1113
|
+
"It also compares this CLI against the latest published version.",
|
|
999
1114
|
"Pass --offline to skip the network checks.",
|
|
1000
1115
|
].join("\n");
|
|
1001
1116
|
}
|
|
1117
|
+
function updateHelpText() {
|
|
1118
|
+
return [
|
|
1119
|
+
"Usage:",
|
|
1120
|
+
" remotedraw update [--check] [--format text|json]",
|
|
1121
|
+
"",
|
|
1122
|
+
`Compares this CLI against the latest ${CLI_PACKAGE_NAME} on the npm registry and installs it with the package manager that owns this binary.`,
|
|
1123
|
+
"Global installs never refresh on their own, so this is the only in-place update path.",
|
|
1124
|
+
"Pass --check to report the available version without installing.",
|
|
1125
|
+
"",
|
|
1126
|
+
"The passive 'update available' notice on other commands can be silenced with REMOTEDRAW_CLI_NO_UPDATE_CHECK=1.",
|
|
1127
|
+
].join("\n");
|
|
1128
|
+
}
|
|
1002
1129
|
function optionsHelpText() {
|
|
1003
1130
|
return [
|
|
1004
1131
|
"Usage:",
|
|
@@ -1650,50 +1777,7 @@ export function projectSetupDefinition() {
|
|
|
1650
1777
|
packageManager: "npm",
|
|
1651
1778
|
apiEndpoint: "deployment",
|
|
1652
1779
|
},
|
|
1653
|
-
fields:
|
|
1654
|
-
{
|
|
1655
|
-
key: "appName",
|
|
1656
|
-
label: "Projectnaam",
|
|
1657
|
-
kind: "text",
|
|
1658
|
-
validate: validateWizardProjectName,
|
|
1659
|
-
},
|
|
1660
|
-
{
|
|
1661
|
-
key: "target",
|
|
1662
|
-
label: "Projecttype",
|
|
1663
|
-
kind: "select",
|
|
1664
|
-
choices: () => wizardChoices(targetPromptChoices(), targetWizardDetails),
|
|
1665
|
-
},
|
|
1666
|
-
{
|
|
1667
|
-
key: "sender",
|
|
1668
|
-
label: "Telefoonzender",
|
|
1669
|
-
kind: "select",
|
|
1670
|
-
choices: (values) => wizardChoices(senderPromptChoices(choice(values.target, targetChoices, "target")), senderWizardDetails),
|
|
1671
|
-
},
|
|
1672
|
-
{
|
|
1673
|
-
key: "sdk",
|
|
1674
|
-
label: "UI-framework / SDK",
|
|
1675
|
-
kind: "select",
|
|
1676
|
-
choices: (values) => wizardChoices(sdkPromptChoices(choice(values.target, targetChoices, "target"), choice(values.sender, senderChoices, "sender")), sdkWizardDetails),
|
|
1677
|
-
},
|
|
1678
|
-
{
|
|
1679
|
-
key: "preset",
|
|
1680
|
-
label: "Startpunt",
|
|
1681
|
-
kind: "select",
|
|
1682
|
-
choices: () => wizardChoices(presetPromptChoices(), presetWizardDetails),
|
|
1683
|
-
},
|
|
1684
|
-
{
|
|
1685
|
-
key: "packageManager",
|
|
1686
|
-
label: "Pakketbeheerder",
|
|
1687
|
-
kind: "select",
|
|
1688
|
-
choices: () => wizardChoices(packageManagerPromptChoices(), packageManagerWizardDetails),
|
|
1689
|
-
},
|
|
1690
|
-
{
|
|
1691
|
-
key: "apiEndpoint",
|
|
1692
|
-
label: "API-eindpunt",
|
|
1693
|
-
kind: "select",
|
|
1694
|
-
choices: () => wizardChoices(apiEndpointPromptChoices(), apiEndpointWizardDetails),
|
|
1695
|
-
},
|
|
1696
|
-
],
|
|
1780
|
+
fields: projectSetupFields(),
|
|
1697
1781
|
normalize(values, changed) {
|
|
1698
1782
|
const next = { ...values };
|
|
1699
1783
|
const target = choice(next.target, targetChoices, "target");
|
|
@@ -1713,19 +1797,67 @@ export function projectSetupDefinition() {
|
|
|
1713
1797
|
},
|
|
1714
1798
|
review(values) {
|
|
1715
1799
|
const plan = planFromWizardValues(values);
|
|
1800
|
+
const label = (key, fallback) => wizardChoiceLabel(key, values) ?? fallback;
|
|
1716
1801
|
return [
|
|
1717
1802
|
["Project", plan.appName],
|
|
1718
|
-
["Map", plan.slug],
|
|
1719
|
-
["Projecttype", plan.target],
|
|
1720
|
-
["Telefoonzender", plan.sender],
|
|
1721
|
-
["SDK", plan.sdk],
|
|
1722
|
-
["
|
|
1723
|
-
["Pakketbeheerder", plan.packageManager],
|
|
1803
|
+
["Map", `./${plan.slug}`],
|
|
1804
|
+
["Projecttype", label("target", plan.target)],
|
|
1805
|
+
["Telefoonzender", label("sender", plan.sender)],
|
|
1806
|
+
["SDK", label("sdk", plan.sdk)],
|
|
1807
|
+
["Pakketbeheerder", label("packageManager", plan.packageManager)],
|
|
1724
1808
|
["API-eindpunt", plan.apiBaseUrl],
|
|
1725
1809
|
];
|
|
1726
1810
|
},
|
|
1727
1811
|
};
|
|
1728
1812
|
}
|
|
1813
|
+
function projectSetupFields() {
|
|
1814
|
+
return [
|
|
1815
|
+
{
|
|
1816
|
+
key: "appName",
|
|
1817
|
+
label: "Projectnaam",
|
|
1818
|
+
kind: "text",
|
|
1819
|
+
validate: validateWizardProjectName,
|
|
1820
|
+
preview: (values) => values.appName.trim() === ""
|
|
1821
|
+
? undefined
|
|
1822
|
+
: `map ./${slugify(values.appName)} · pakket ${slugify(values.appName)}`,
|
|
1823
|
+
},
|
|
1824
|
+
{
|
|
1825
|
+
key: "target",
|
|
1826
|
+
label: "Projecttype",
|
|
1827
|
+
kind: "select",
|
|
1828
|
+
choices: () => wizardChoices(targetPromptChoices(), targetWizardDetails),
|
|
1829
|
+
},
|
|
1830
|
+
{
|
|
1831
|
+
key: "sender",
|
|
1832
|
+
label: "Telefoonzender",
|
|
1833
|
+
kind: "select",
|
|
1834
|
+
choices: (values) => wizardChoices(senderPromptChoices(choice(values.target, targetChoices, "target")), senderWizardDetails),
|
|
1835
|
+
},
|
|
1836
|
+
{
|
|
1837
|
+
key: "sdk",
|
|
1838
|
+
label: "UI-framework / SDK",
|
|
1839
|
+
kind: "select",
|
|
1840
|
+
choices: (values) => wizardChoices(sdkPromptChoices(choice(values.target, targetChoices, "target"), choice(values.sender, senderChoices, "sender")), sdkWizardDetails),
|
|
1841
|
+
},
|
|
1842
|
+
{
|
|
1843
|
+
key: "packageManager",
|
|
1844
|
+
label: "Pakketbeheerder",
|
|
1845
|
+
kind: "select",
|
|
1846
|
+
choices: () => wizardChoices(packageManagerPromptChoices(), packageManagerWizardDetails),
|
|
1847
|
+
},
|
|
1848
|
+
{
|
|
1849
|
+
key: "apiEndpoint",
|
|
1850
|
+
label: "API-eindpunt",
|
|
1851
|
+
kind: "select",
|
|
1852
|
+
choices: () => wizardChoices(apiEndpointPromptChoices(), apiEndpointWizardDetails),
|
|
1853
|
+
},
|
|
1854
|
+
];
|
|
1855
|
+
}
|
|
1856
|
+
function wizardChoiceLabel(key, values) {
|
|
1857
|
+
const field = projectSetupFields().find((entry) => entry.key === key);
|
|
1858
|
+
return field?.choices?.(values).find((option) => option.value === values[key])
|
|
1859
|
+
?.label;
|
|
1860
|
+
}
|
|
1729
1861
|
function validateWizardProjectName(value) {
|
|
1730
1862
|
return value.trim() === "" ? "Voer een projectnaam in." : undefined;
|
|
1731
1863
|
}
|
|
@@ -2824,6 +2956,56 @@ export function agentSkillMarkdown() {
|
|
|
2824
2956
|
"```",
|
|
2825
2957
|
].join("\n");
|
|
2826
2958
|
}
|
|
2959
|
+
/**
|
|
2960
|
+
* Doctor used to read REMOTEDRAW_API_BASE_URL raw and call an unset value a
|
|
2961
|
+
* problem, which disagreed with login/whoami/new — those all fall back to the
|
|
2962
|
+
* production API. Resolving it the same way here keeps every command pointed at
|
|
2963
|
+
* one deployment, and reporting the source explains a non-production URL
|
|
2964
|
+
* instead of leaving the reader to guess where it came from.
|
|
2965
|
+
*/
|
|
2966
|
+
function resolveDoctorApiBaseUrl(projectEnv, requested) {
|
|
2967
|
+
const explicit = requested ?? projectEnv.REMOTEDRAW_API_BASE_URL;
|
|
2968
|
+
const source = requested == null ? "project" : "flag";
|
|
2969
|
+
if (explicit == null || explicit.trim() === "") {
|
|
2970
|
+
return {
|
|
2971
|
+
state: "ok",
|
|
2972
|
+
url: DEFAULT_REMOTEDRAW_API_BASE_URL,
|
|
2973
|
+
source: "default",
|
|
2974
|
+
isProductionDefault: true,
|
|
2975
|
+
};
|
|
2976
|
+
}
|
|
2977
|
+
// `init --offline` writes the literal placeholder, so an unreplaced value is
|
|
2978
|
+
// an expected next step rather than a mistake.
|
|
2979
|
+
if (explicit.includes("<"))
|
|
2980
|
+
return { state: "placeholder", value: explicit };
|
|
2981
|
+
if (!isHttpOrigin(explicit)) {
|
|
2982
|
+
return { state: "invalid", value: explicit, source };
|
|
2983
|
+
}
|
|
2984
|
+
const url = normalizedOrigin(explicit);
|
|
2985
|
+
return {
|
|
2986
|
+
state: "ok",
|
|
2987
|
+
url,
|
|
2988
|
+
source,
|
|
2989
|
+
isProductionDefault: url === DEFAULT_REMOTEDRAW_API_BASE_URL,
|
|
2990
|
+
};
|
|
2991
|
+
}
|
|
2992
|
+
function doctorApiBaseUrlMessage(resolved) {
|
|
2993
|
+
if (resolved.state === "placeholder") {
|
|
2994
|
+
return `Still the ${resolved.value} placeholder. Replace it with ${DEFAULT_REMOTEDRAW_API_BASE_URL}, or with your own deployment origin.`;
|
|
2995
|
+
}
|
|
2996
|
+
if (resolved.state === "invalid") {
|
|
2997
|
+
return `${resolved.value} is not an HTTP origin. Set it to ${DEFAULT_REMOTEDRAW_API_BASE_URL}, or to your own deployment origin.`;
|
|
2998
|
+
}
|
|
2999
|
+
if (resolved.source === "default") {
|
|
3000
|
+
return `Using ${resolved.url} (RemoteDraw production API; nothing overrides it here).`;
|
|
3001
|
+
}
|
|
3002
|
+
const origin = resolved.source === "flag"
|
|
3003
|
+
? "--api-base-url"
|
|
3004
|
+
: "this project's environment";
|
|
3005
|
+
return resolved.isProductionDefault
|
|
3006
|
+
? `Using ${resolved.url} (production API, set by ${origin}).`
|
|
3007
|
+
: `Using ${resolved.url} (override from ${origin}, not the ${DEFAULT_REMOTEDRAW_API_BASE_URL} production API).`;
|
|
3008
|
+
}
|
|
2827
3009
|
function isHttpOrigin(value) {
|
|
2828
3010
|
if (value == null || value.includes("<"))
|
|
2829
3011
|
return false;
|
package/dist/index.js
CHANGED
|
@@ -1,8 +1,25 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import
|
|
3
|
-
|
|
2
|
+
import process from "node:process";
|
|
3
|
+
import { CLI_VERSION, createNodeRuntime, runCli } from "./cli.js";
|
|
4
|
+
import { checkForUpdate, detectInstallMethod, updateNotice, } from "./update.js";
|
|
5
|
+
const runtime = createNodeRuntime();
|
|
6
|
+
const result = await runCli(process.argv.slice(2), runtime);
|
|
4
7
|
if (result.stdout)
|
|
5
8
|
process.stdout.write(result.stdout);
|
|
6
9
|
if (result.stderr)
|
|
7
10
|
process.stderr.write(result.stderr);
|
|
8
11
|
process.exitCode = result.exitCode;
|
|
12
|
+
// Only a human at a terminal sees this. Piped output, CI, and machine-readable
|
|
13
|
+
// runs stay byte-for-byte what the command produced.
|
|
14
|
+
if (process.stderr.isTTY && process.argv[2] !== "update") {
|
|
15
|
+
try {
|
|
16
|
+
const check = await checkForUpdate(runtime, CLI_VERSION);
|
|
17
|
+
if (check?.updateAvailable) {
|
|
18
|
+
const method = detectInstallMethod(runtime.binPath ?? "");
|
|
19
|
+
process.stderr.write(`\n${updateNotice(check, method)}\n`);
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
catch {
|
|
23
|
+
// A failed update check never changes the outcome of the real command.
|
|
24
|
+
}
|
|
25
|
+
}
|
package/dist/setup-wizard.d.ts
CHANGED
|
@@ -18,6 +18,7 @@ export type WizardField = {
|
|
|
18
18
|
kind: "text" | "select";
|
|
19
19
|
choices?: (values: WizardValues) => readonly WizardChoice[];
|
|
20
20
|
validate?: (value: string) => string | undefined;
|
|
21
|
+
preview?: (values: WizardValues) => string | undefined;
|
|
21
22
|
};
|
|
22
23
|
export type WizardDefinition = {
|
|
23
24
|
fields: readonly WizardField[];
|
|
@@ -71,6 +72,8 @@ export type WizardSemanticView = {
|
|
|
71
72
|
activeLabel?: string | undefined;
|
|
72
73
|
value?: string | undefined;
|
|
73
74
|
valueIsDefault?: boolean | undefined;
|
|
75
|
+
valuePreview?: string | undefined;
|
|
76
|
+
completed?: readonly [string, string][] | undefined;
|
|
74
77
|
choices?: readonly WizardChoice[] | undefined;
|
|
75
78
|
selectedChoice?: string | undefined;
|
|
76
79
|
selectedDetails?: WizardChoiceDetails | undefined;
|
|
@@ -91,10 +94,14 @@ export type WizardKey = {
|
|
|
91
94
|
};
|
|
92
95
|
export type WizardTerminal = {
|
|
93
96
|
columns: number;
|
|
97
|
+
rows?: number;
|
|
94
98
|
color: boolean;
|
|
99
|
+
trueColor?: boolean;
|
|
95
100
|
hyperlinks?: boolean;
|
|
96
101
|
write: (value: string) => void;
|
|
97
102
|
readKey: () => Promise<WizardKey>;
|
|
103
|
+
readKeyWithin?: (milliseconds: number) => Promise<WizardKey | undefined>;
|
|
104
|
+
hasPendingKey?: () => boolean;
|
|
98
105
|
openUrl?: (url: string) => void | Promise<void>;
|
|
99
106
|
enter: () => void | Promise<void>;
|
|
100
107
|
restore: () => void | Promise<void>;
|
|
@@ -112,7 +119,8 @@ export declare function runSetupWizard(options: {
|
|
|
112
119
|
state: WizardState;
|
|
113
120
|
}>;
|
|
114
121
|
export declare function actionForKey(key: WizardKey, state: WizardState): WizardAction;
|
|
115
|
-
|
|
122
|
+
type Painter = Pick<WizardTerminal, "columns" | "rows" | "color" | "hyperlinks" | "trueColor">;
|
|
123
|
+
export declare function renderWizard(state: WizardState, definition: WizardDefinition, terminal: Painter, frame?: number): string;
|
|
116
124
|
type KeypressInput = NodeJS.ReadStream & {
|
|
117
125
|
isRaw?: boolean;
|
|
118
126
|
setRawMode?: (mode: boolean) => KeypressInput;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"setup-wizard.d.ts","sourceRoot":"","sources":["../src/setup-wizard.ts"],"names":[],"mappings":"AAGA,MAAM,MAAM,cAAc,GACtB,SAAS,GACT,QAAQ,GACR,QAAQ,GACR,KAAK,GACL,QAAQ,GACR,gBAAgB,GAChB,aAAa,CAAC;AAElB,MAAM,MAAM,YAAY,GAAG,MAAM,CAAC,cAAc,EAAE,MAAM,CAAC,CAAC;AAE1D,MAAM,MAAM,YAAY,GAAG;IACzB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,mBAAmB,CAAC;CAC/B,CAAC;AAEF,MAAM,MAAM,mBAAmB,GAAG;IAChC,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;CACnB,CAAC;AAEF,MAAM,MAAM,WAAW,GAAG;IACxB,GAAG,EAAE,cAAc,CAAC;IACpB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,GAAG,QAAQ,CAAC;IACxB,OAAO,CAAC,EAAE,CAAC,MAAM,EAAE,YAAY,KAAK,SAAS,YAAY,EAAE,CAAC;IAC5D,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,MAAM,GAAG,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"setup-wizard.d.ts","sourceRoot":"","sources":["../src/setup-wizard.ts"],"names":[],"mappings":"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"}
|