@visualautomate/cli 0.4.0 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/README.md +27 -18
  2. package/dist/index.js +65 -22
  3. package/package.json +5 -4
package/README.md CHANGED
@@ -4,14 +4,14 @@ Build and publish VisualAutomate plugins.
4
4
 
5
5
  ```bash
6
6
  npm install -g @visualautomate/cli
7
- visualautomate login
8
- visualautomate init my-step
7
+ vsa login
8
+ vsa init my-step
9
9
  cd my-step
10
- visualautomate dev # run it on every save
11
- visualautomate push
10
+ vsa dev # the sandbox, and a run again on every save
11
+ vsa push
12
12
  ```
13
13
 
14
- `va` is the same command, shorter.
14
+ `va` and `visualautomate` are the same command.
15
15
 
16
16
  That is the whole toolchain. There is nothing else to install: the CLI carries
17
17
  the SDK inside it, compiles your TypeScript itself, and writes the type
@@ -85,14 +85,18 @@ unbundled, because that is the file the sandbox loads.
85
85
 
86
86
  ## `dev`
87
87
 
88
- `test`, and again on every save. Only the module whose folder changed runs
89
- again; a change anywhere else runs them all. Ctrl+C stops it.
90
-
91
88
  ```bash
92
- va dev
93
- va dev --module send-message
89
+ vsa dev
90
+ vsa dev --module send-message
91
+ vsa dev --tier boosted
92
+ vsa dev --local # on this machine's Node, without the sandbox
94
93
  ```
95
94
 
95
+ Everything in one command: it starts Docker if it is not running, fetches the
96
+ sandbox image the first time, runs every module, and runs them again on every
97
+ save. Only the module whose folder changed runs again; a change anywhere else
98
+ runs them all. Ctrl+C stops it.
99
+
96
100
  `context.connections` and `context.media` are **not** simulated. One is
97
101
  somebody's OAuth account and the other is an ffmpeg container; pretending to be
98
102
  either would produce a plugin that passes here and fails on a canvas. Asking for
@@ -140,14 +144,17 @@ Keeps storage and state between runs, in `.visualautomate/` next to the plugin:
140
144
  Once that folder exists it is used without the flag. Delete it to start over,
141
145
  and add it to `.gitignore`.
142
146
 
143
- ## `--docker`: the sandbox on your machine
147
+ ## The sandbox on your machine
148
+
149
+ `dev` uses it by default; `test` does with `--docker`:
144
150
 
145
151
  ```bash
146
- va test --docker
147
- va dev --docker --tier boosted
152
+ vsa dev
153
+ vsa test --docker
154
+ vsa dev --tier boosted
148
155
  ```
149
156
 
150
- Runs the test inside the plugin sandbox image,
157
+ Your plugin runs inside the plugin sandbox image,
151
158
  `ghcr.io/visualautomate/plugin-sandbox`, at the version of this CLI:
152
159
 
153
160
  - the Node version the platform runs plugins on, with every allowed npm
@@ -157,10 +164,12 @@ Runs the test inside the plugin sandbox image,
157
164
  - no Linux capabilities, a read-only filesystem apart from your project and a
158
165
  small `/tmp`, and nothing else from your machine.
159
166
 
160
- A step that runs out of memory or time here does the same on the platform. Docker
161
- must be running. `--image` uses a different image, for example one you built
162
- yourself. With `dev`, the watcher stays on your machine and each run starts a
163
- fresh container.
167
+ A step that runs out of memory or time here does the same on the platform.
168
+
169
+ Docker does not have to be running: `dev` starts Docker Desktop and waits for it,
170
+ then fetches the image if this machine does not have it. `--image` uses a
171
+ different image, for example one you built yourself. The watcher stays on your
172
+ machine, and each run starts a fresh container.
164
173
 
165
174
  `context.media` is not available locally, in or out of Docker.
166
175
 
package/dist/index.js CHANGED
@@ -1999,7 +1999,7 @@ function permits(policy, host) {
1999
1999
  return policy.hosts.some((allowed) => host === allowed || host.endsWith(`.${allowed}`));
2000
2000
  }
2001
2001
  function guardFetch(policy, base, onDenied) {
2002
- return (resource, init) => {
2002
+ return ((resource, init) => {
2003
2003
  const raw = typeof resource === "string" ? resource : resource instanceof URL ? resource.href : resource.url;
2004
2004
  const host = hostOf(raw);
2005
2005
  if (host && !permits(policy, host)) {
@@ -2011,7 +2011,7 @@ function guardFetch(policy, base, onDenied) {
2011
2011
  }
2012
2012
  }
2013
2013
  return base(resource, init);
2014
- };
2014
+ });
2015
2015
  }
2016
2016
 
2017
2017
  // src/persist.ts
@@ -2139,6 +2139,35 @@ function explainExit(code, tier) {
2139
2139
  if (code === 125) return "\u2717 Docker could not start the container. Is the image available? Try: docker pull " + IMAGE;
2140
2140
  return null;
2141
2141
  }
2142
+ function ensureDocker(say, waitMs = 12e4) {
2143
+ const problem = dockerProblem();
2144
+ if (!problem) return null;
2145
+ if (problem.includes("not installed")) return problem;
2146
+ say("Docker is not running. Starting Docker Desktop\u2026");
2147
+ const started = spawnSync("docker", ["desktop", "start"], { encoding: "utf8" });
2148
+ if (started.status !== 0) {
2149
+ say("Could not start it from here \u2014 start Docker Desktop yourself; this will carry on when it is up.");
2150
+ }
2151
+ const until = Date.now() + waitMs;
2152
+ while (Date.now() < until) {
2153
+ spawnSync(process.execPath, ["-e", "setTimeout(() => {}, 1000)"]);
2154
+ if (!dockerProblem()) {
2155
+ say("Docker is ready.");
2156
+ return null;
2157
+ }
2158
+ }
2159
+ return "Docker did not come up in time. Start Docker Desktop and try again.";
2160
+ }
2161
+ function hasImage(image) {
2162
+ return spawnSync("docker", ["image", "inspect", image], { stdio: "ignore" }).status === 0;
2163
+ }
2164
+ function pullImage(image, say) {
2165
+ if (hasImage(image)) return null;
2166
+ say(`Fetching ${image} \u2014 once, about 700 MB.`);
2167
+ const pulled = spawnSync("docker", ["pull", image], { stdio: "inherit" });
2168
+ if (pulled.status === 0) return null;
2169
+ return `Could not fetch ${image}. Check your connection, or pass --image with one you have.`;
2170
+ }
2142
2171
  function runInDocker(run) {
2143
2172
  const result = spawnSync("docker", dockerArgs(run), { stdio: "inherit" });
2144
2173
  const code = result.status ?? 1;
@@ -2148,7 +2177,7 @@ function runInDocker(run) {
2148
2177
  }
2149
2178
 
2150
2179
  // src/index.ts
2151
- var VERSION = true ? "0.4.0" : "0.0.0-dev";
2180
+ var VERSION = true ? "0.5.0" : "0.0.0-dev";
2152
2181
  var DEFAULT_API_URL = "https://visualautomate.com";
2153
2182
  function configPath() {
2154
2183
  return join3(homedir(), ".visualautomate", "config.json");
@@ -2472,9 +2501,16 @@ function packageLoader(dir) {
2472
2501
  }
2473
2502
  };
2474
2503
  }
2504
+ function imageFor(flags) {
2505
+ return flags.image || `${IMAGE}:${VERSION}`;
2506
+ }
2507
+ function prepareSandbox(flags) {
2508
+ const docker = ensureDocker(ok);
2509
+ if (docker) fail(docker);
2510
+ const image = pullImage(imageFor(flags), ok);
2511
+ if (image) fail(image);
2512
+ }
2475
2513
  function dockerRunFor(flags, args) {
2476
- const problem = dockerProblem();
2477
- if (problem) fail(problem);
2478
2514
  let tier;
2479
2515
  try {
2480
2516
  tier = tierOf(flags.tier);
@@ -2483,7 +2519,7 @@ function dockerRunFor(flags, args) {
2483
2519
  }
2484
2520
  return {
2485
2521
  cwd: process.cwd(),
2486
- image: flags.image || `${IMAGE}:${VERSION}`,
2522
+ image: imageFor(flags),
2487
2523
  tier,
2488
2524
  args,
2489
2525
  user: typeof process.getuid === "function" && typeof process.getgid === "function" ? { uid: process.getuid(), gid: process.getgid() } : void 0
@@ -2511,19 +2547,22 @@ function targetsOrFail(flags) {
2511
2547
  }
2512
2548
  async function cmdTest(flags) {
2513
2549
  const targets = targetsOrFail(flags);
2550
+ if (flags.docker) prepareSandbox(flags);
2514
2551
  const passed = flags.docker ? runTargetsInDocker(targets, targets, flags) : await runTargets(targets, flags);
2515
2552
  if (!passed) process.exitCode = 1;
2516
2553
  }
2517
2554
  async function cmdDev(flags) {
2518
2555
  const root = process.cwd();
2519
2556
  let targets = targetsOrFail(flags);
2557
+ const inSandbox = flags.local !== "true";
2558
+ if (inSandbox) prepareSandbox(flags);
2520
2559
  const header = () => {
2521
2560
  process.stdout.write("\x1Bc");
2522
- ok(`visualautomate dev \u2014 ${(/* @__PURE__ */ new Date()).toLocaleTimeString()} \u2014 Ctrl+C to stop`);
2561
+ ok(`vsa dev \u2014 ${(/* @__PURE__ */ new Date()).toLocaleTimeString()} \u2014 Ctrl+C to stop`);
2523
2562
  };
2524
- const run = async (chosen) => flags.docker ? runTargetsInDocker(chosen, targets, flags) : runTargets(chosen, flags);
2563
+ const run = async (chosen) => inSandbox ? runTargetsInDocker(chosen, targets, flags) : runTargets(chosen, flags);
2525
2564
  header();
2526
- if (flags.docker) ok(`in ${flags.image || `${IMAGE}:${VERSION}`}, tier ${flags.tier || "standard"}`);
2565
+ ok(inSandbox ? `in ${imageFor(flags)}, tier ${flags.tier || "standard"}` : "on this machine, not in the sandbox");
2527
2566
  await run(targets);
2528
2567
  const ignored = [`${sep2}node_modules${sep2}`, `${sep2}.git${sep2}`, `${sep2}dist${sep2}`, `${sep2}.visualautomate${sep2}`];
2529
2568
  const pending = /* @__PURE__ */ new Set();
@@ -2656,16 +2695,18 @@ ${text.slice(0, 500)}`);
2656
2695
  }
2657
2696
  function printHelp() {
2658
2697
  console.log(`
2659
- visualautomate \u2014 build and publish plugins
2698
+ vsa \u2014 build and publish VisualAutomate plugins
2699
+
2700
+ vsa login sign this machine in
2701
+ vsa init <name> [--template] start a plugin
2702
+ vsa dev [--module <name>] the sandbox, and a run again on every save
2703
+ vsa test [--module <name>] run it once, as the platform's check does
2704
+ vsa push publish it
2705
+ vsa whoami which account this is
2706
+ vsa logout forget the token
2707
+ vsa --version this CLI's version
2660
2708
 
2661
- visualautomate login sign this machine in
2662
- visualautomate init <name> [--template] start a plugin
2663
- visualautomate test [--module <name>] run it here, as the platform's check does
2664
- visualautomate dev [--module <name>] run it again on every save
2665
- visualautomate --version this CLI's version
2666
- visualautomate push publish it
2667
- visualautomate whoami which account this is
2668
- visualautomate logout forget the token
2709
+ \`va\` and \`visualautomate\` are the same command.
2669
2710
 
2670
2711
  Templates: ${Object.keys(TEMPLATES).join(", ")}
2671
2712
 
@@ -2674,11 +2715,13 @@ GitHub repository, and at the root of an app's repository, where every folder
2674
2715
  in modules/ is run (or the one named with --module). The run's settings come
2675
2716
  from visualautomate.test.json, test.json, or --input <file>.
2676
2717
 
2677
- Options for \`test\` and \`dev\`:
2678
- --docker run inside the plugin sandbox image (Docker must be running)
2679
- --tier <name> with --docker: standard, boosted, high or max
2680
- --image <ref> with --docker: a different image
2718
+ Options for \`dev\` and \`test\`:
2719
+ --module <name> one folder of modules/ instead of all of them
2720
+ --tier <name> the sandbox's size: standard, boosted, high or max
2721
+ --image <ref> a different sandbox image
2681
2722
  --persist keep storage and state in .visualautomate/ between runs
2723
+ --local \`dev\` without the sandbox, on this machine's Node
2724
+ --docker \`test\` inside the sandbox, as \`dev\` does
2682
2725
 
2683
2726
  Environment (for CI, where there is no browser):
2684
2727
  VISUALAUTOMATE_API_TOKEN use instead of \`login\`
package/package.json CHANGED
@@ -1,12 +1,13 @@
1
1
  {
2
2
  "name": "@visualautomate/cli",
3
- "version": "0.4.0",
3
+ "version": "0.5.0",
4
4
  "description": "Build and publish VisualAutomate plugins.",
5
5
  "license": "MIT",
6
6
  "type": "module",
7
7
  "bin": {
8
- "visualautomate": "./dist/index.js",
9
- "va": "./dist/index.js"
8
+ "visualautomate": "dist/index.js",
9
+ "va": "dist/index.js",
10
+ "vsa": "dist/index.js"
10
11
  },
11
12
  "files": [
12
13
  "dist",
@@ -26,7 +27,7 @@
26
27
  "node": ">=20"
27
28
  },
28
29
  "dependencies": {
29
- "esbuild": "^0.23.0"
30
+ "esbuild": "^0.28.2"
30
31
  },
31
32
  "devDependencies": {
32
33
  "@types/node": "^22",