@visualautomate/cli 0.6.0 → 0.6.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.
Files changed (3) hide show
  1. package/README.md +4 -0
  2. package/dist/index.js +64 -28
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -77,6 +77,10 @@ Types: `string`, `number`, `boolean`, `select`, `multiselect`, `json`, `color`,
77
77
  `date`, `connection`, `file`, `path`, `paths`. A `select` or `multiselect` needs
78
78
  `--options`, and a `connection` needs `--provider <name>`.
79
79
 
80
+ The same field is added to `visualautomate.test.json` under `config`, with its
81
+ default or a value of the right shape, so the next `vsa test` passes something
82
+ for it instead of nothing. A value you have already put there is kept.
83
+
80
84
  At the root of an app's repository, `--module <name>` says which one — the same
81
85
  short names `test` and `dev` take. The manifest is edited where it stands: your
82
86
  comments, the examples underneath and your own formatting stay as they are.
package/dist/index.js CHANGED
@@ -3,7 +3,7 @@
3
3
  // src/index.ts
4
4
  import { mkdir as mkdir2, readFile as readFile3, writeFile as writeFile2 } from "node:fs/promises";
5
5
  import { existsSync as existsSync4, watch } from "node:fs";
6
- import { join as join4, relative as relative3, resolve as resolve3, sep as sep2 } from "node:path";
6
+ import { basename as basename3, join as join4, relative as relative3, resolve as resolve3, sep as sep2 } from "node:path";
7
7
  import { createRequire } from "node:module";
8
8
  import { build, stop as stopBundler } from "esbuild";
9
9
 
@@ -2051,24 +2051,25 @@ function lastContent(bare, from, to) {
2051
2051
  function indented(value, indent, depth) {
2052
2052
  return JSON.stringify(value, null, indent.length === 1 ? " " : indent.length).replace(/\{\s*"label": ("(?:[^"\\]|\\.)*"),\s*"value": ("(?:[^"\\]|\\.)*")\s*\}/g, '{ "label": $1, "value": $2 }').split("\n").map((line2, index) => index === 0 ? line2 : indent.repeat(depth) + line2).join("\n");
2053
2053
  }
2054
- function withProperty(text, name, property) {
2054
+ function withMember(text, container, key, value) {
2055
2055
  const bare = stripJsonComments(text);
2056
2056
  const { object, members } = topLevelMembers(bare);
2057
- if (!object || object.end === -1) throw new Error("This manifest is not a JSON object.");
2057
+ if (!object || object.end === -1) throw new Error("This file is not a JSON object.");
2058
2058
  const indent = indentOf(text);
2059
- const entry = `"${name}": ${indented(property, indent, 2)}`;
2060
- const existing = members.get("properties");
2059
+ const entry = `"${key}": ${indented(value, indent, 2)}`;
2060
+ const existing = members.get(container);
2061
2061
  let next;
2062
2062
  if (existing && bare[existing.start] === "{") {
2063
2063
  const last = lastContent(bare, existing.start, existing.end);
2064
+ const oneLine = last !== -1 && !text.slice(existing.start, existing.end).includes("\n");
2064
2065
  next = last === -1 ? text.slice(0, existing.start + 1) + `
2065
2066
  ${indent.repeat(2)}${entry}
2066
- ${indent}` + text.slice(existing.end) : text.slice(0, last + 1) + `,
2067
+ ${indent}` + text.slice(existing.end) : oneLine ? text.slice(0, last + 1) + `, "${key}": ${JSON.stringify(value)}` + text.slice(last + 1) : text.slice(0, last + 1) + `,
2067
2068
  ${indent.repeat(2)}${entry}` + text.slice(last + 1);
2068
2069
  } else if (existing) {
2069
- throw new Error('"properties" in this manifest is not an object, so nothing can be added to it.');
2070
+ throw new Error(`"${container}" in this file is not an object, so nothing can be added to it.`);
2070
2071
  } else {
2071
- const block = `"properties": {
2072
+ const block = `"${container}": {
2072
2073
  ${indent.repeat(2)}${entry}
2073
2074
  ${indent}}`;
2074
2075
  const last = lastContent(bare, object.start, object.end);
@@ -2078,14 +2079,35 @@ ${indent}${block}
2078
2079
  ${indent}${block}` + text.slice(last + 1);
2079
2080
  }
2080
2081
  const parsed = JSON.parse(stripJsonComments(next));
2081
- if (!parsed.properties || !(name in parsed.properties)) {
2082
- throw new Error("The property could not be placed in this manifest. Add it by hand, or say where this went wrong.");
2082
+ if (!parsed[container] || !(key in parsed[container])) {
2083
+ throw new Error(`${key} could not be placed in this file. Add it by hand, or say where this went wrong.`);
2083
2084
  }
2084
2085
  return next;
2085
2086
  }
2086
- function hasProperty(text, name) {
2087
+ function hasMember(text, container, key) {
2087
2088
  const parsed = JSON.parse(stripJsonComments(text));
2088
- return Boolean(parsed.properties && typeof parsed.properties === "object" && name in parsed.properties);
2089
+ const inside = parsed[container];
2090
+ return Boolean(inside && typeof inside === "object" && !Array.isArray(inside) && key in inside);
2091
+ }
2092
+ function sampleFor(property) {
2093
+ if ("default" in property) return property.default;
2094
+ switch (property.type) {
2095
+ case "number":
2096
+ return 0;
2097
+ case "boolean":
2098
+ return false;
2099
+ case "multiselect":
2100
+ case "paths":
2101
+ return [];
2102
+ case "json":
2103
+ return {};
2104
+ case "select": {
2105
+ const options = property.options;
2106
+ return options?.[0]?.value ?? "";
2107
+ }
2108
+ default:
2109
+ return "";
2110
+ }
2089
2111
  }
2090
2112
 
2091
2113
  // src/project.ts
@@ -2497,7 +2519,7 @@ function runInDocker(run) {
2497
2519
  }
2498
2520
 
2499
2521
  // src/index.ts
2500
- var VERSION = true ? "0.6.0" : "0.0.0-dev";
2522
+ var VERSION = true ? "0.6.1" : "0.0.0-dev";
2501
2523
  function fail(message) {
2502
2524
  console.error(red(message));
2503
2525
  throw new SilentExit();
@@ -2817,30 +2839,44 @@ Types: ${PROPERTY_TYPES.join(", ")}`
2817
2839
  const file2 = join4(target.dir, "manifest.json");
2818
2840
  if (!existsSync4(file2)) fail(`${target.name} has no manifest.json.`);
2819
2841
  const text = await readFile3(file2, "utf8");
2820
- if (hasProperty(text, name)) {
2842
+ if (hasMember(text, "properties", name)) {
2821
2843
  fail(`${target.name} already has a property called ${name}. Change it in ${target.name}/manifest.json.`);
2822
2844
  }
2845
+ let property;
2823
2846
  let next;
2824
2847
  try {
2825
- next = withProperty(
2826
- text,
2848
+ property = buildProperty({
2849
+ type,
2827
2850
  name,
2828
- buildProperty({
2829
- type,
2830
- name,
2831
- description,
2832
- value,
2833
- label: flags.label,
2834
- required: flags.required === "true",
2835
- options: flags.options,
2836
- provider: flags.provider
2837
- })
2838
- );
2851
+ description,
2852
+ value,
2853
+ label: flags.label,
2854
+ required: flags.required === "true",
2855
+ options: flags.options,
2856
+ provider: flags.provider
2857
+ });
2858
+ next = withMember(text, "properties", name, property);
2839
2859
  } catch (error) {
2840
2860
  fail(error instanceof Error ? error.message : String(error));
2841
2861
  }
2842
2862
  await writeFile2(file2, next, "utf8");
2843
- ok(green(`\u2713 Added ${name} to ${target.name}`));
2863
+ const written = [`${target.name}/manifest.json`];
2864
+ const testPath = TEST_FILES.map((name2) => join4(target.dir, name2)).find((path) => existsSync4(path)) ?? join4(target.dir, TEST_FILES[0]);
2865
+ const sample = sampleFor(property);
2866
+ try {
2867
+ const before = existsSync4(testPath) ? await readFile3(testPath, "utf8") : `{
2868
+ "config": {},
2869
+ "input": {}
2870
+ }
2871
+ `;
2872
+ if (!hasMember(before, "config", name)) {
2873
+ await writeFile2(testPath, withMember(before, "config", name, sample), "utf8");
2874
+ written.push(`${target.name}/${basename3(testPath)}`);
2875
+ }
2876
+ } catch (error) {
2877
+ ok(yellow(` ${basename3(testPath)} was left alone: ${error instanceof Error ? error.message : String(error)}`));
2878
+ }
2879
+ ok(green(`\u2713 Added ${name} to ${written.join(" and ")}`));
2844
2880
  ok(dim(` Read it in your code as config.${name}`));
2845
2881
  }
2846
2882
  async function cmdDev(args, flags) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@visualautomate/cli",
3
- "version": "0.6.0",
3
+ "version": "0.6.1",
4
4
  "description": "Build and test VisualAutomate plugins.",
5
5
  "license": "MIT",
6
6
  "type": "module",