@kubb/studio 5.11.4 → 5.11.5

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.cjs CHANGED
@@ -220,7 +220,7 @@ function getElapsedMs(hrStart) {
220
220
  }
221
221
  //#endregion
222
222
  //#region package.json
223
- var version = "5.11.4";
223
+ var version = "5.11.5";
224
224
  //#endregion
225
225
  //#region src/resolveConfig.ts
226
226
  /**
@@ -1082,13 +1082,17 @@ function applySet(source, call, path, value, quote) {
1082
1082
  }
1083
1083
  return { source: splice(source, rangeOf(target.value).start, rangeOf(target.value).end, printValue(value, quote)) };
1084
1084
  }
1085
- /** Deletes the option at `path`, falling the plugin back to its default for it. */
1085
+ /**
1086
+ * Deletes the option at `path`, falling the plugin back to its default for it. An option the file
1087
+ * does not set already has its default, so removing it changes nothing.
1088
+ */
1086
1089
  function applyRemove(source, call, path) {
1087
1090
  const options = call.arguments[0];
1088
- if (options?.type !== "ObjectExpression") return { reason: "the factory call has no options to remove" };
1091
+ if (!options) return { source };
1092
+ if (options.type !== "ObjectExpression") return { reason: "the factory was not called with an object literal" };
1089
1093
  const target = walk(options, path);
1090
1094
  if ("reason" in target) return target;
1091
- if ("missing" in target) return { reason: `${path.join(".")} is not set` };
1095
+ if ("missing" in target) return { source };
1092
1096
  return { source: removeMember(source, target.object, target.index) };
1093
1097
  }
1094
1098
  /**
@@ -1128,6 +1132,22 @@ function applyAddPlugin({ source, parsed, config, edit, quote, extensions }) {
1128
1132
  const next = insertItem(source, plugins, `${importName}(${Object.keys(options).length ? printValue(options, quote) : ""})`);
1129
1133
  return { source: taken ? next : insertImport(next, parsed, importName, edit.plugin) };
1130
1134
  }
1135
+ /**
1136
+ * Rewrites the config's `plugins` array with one item per line, so a call can be commented out without
1137
+ * taking its neighbors with it. Not done when a comment sits between the items, which would have to move.
1138
+ */
1139
+ function expandPluginsArray(source, config) {
1140
+ const array = property(config, "plugins");
1141
+ if (array?.type !== "ArrayExpression") return void 0;
1142
+ const items = array.elements.flatMap((element) => element ? [element] : []);
1143
+ const { start, end } = rangeOf(array);
1144
+ const ranges = items.map(rangeOf);
1145
+ const gaps = [source.slice(start + 1, ranges[0]?.start ?? end - 1), ...ranges.map((range, index) => source.slice(range.end, ranges[index + 1]?.start ?? end - 1))];
1146
+ if (!items.length || gaps.some((gap) => !/^[\s,]*$/.test(gap))) return void 0;
1147
+ const lineStart = source.lastIndexOf("\n", start - 1) + 1;
1148
+ const indent = source.slice(lineStart).match(/^[ \t]*/)?.[0] ?? "";
1149
+ return splice(source, start, end, `[\n${ranges.map((range) => `${indent} ${source.slice(range.start, range.end)},`).join("\n")}\n${indent}]`);
1150
+ }
1131
1151
  /** Comments out a plugin call in place, keeping its options on disk so `enable-plugin` can restore them exactly. */
1132
1152
  function disablePlugin(source, mod, config, plugin) {
1133
1153
  const loc = factoryCalls(mod, config).find((entry) => entry.packageName === plugin)?.call.loc;
@@ -1155,9 +1175,17 @@ function applyEdit({ source, edit, quote, extensions }) {
1155
1175
  const parsed = parseConfigs(source);
1156
1176
  if ("reason" in parsed) return parsed;
1157
1177
  const ref = edit.config;
1158
- const config = typeof ref === "string" ? parsed.configs.find((entry) => configName(entry) === ref) : parsed.configs[ref ?? 0];
1178
+ const findConfig = (entries) => typeof ref === "string" ? entries.configs.find((entry) => configName(entry) === ref) : entries.configs[ref ?? 0];
1179
+ const config = findConfig(parsed);
1159
1180
  if (!config) return { reason: `no config entry found for ${JSON.stringify(ref)}` };
1160
- if (edit.operation === "disable-plugin") return disablePlugin(source, parsed.mod, config, edit.plugin);
1181
+ if (edit.operation === "disable-plugin") {
1182
+ const result = disablePlugin(source, parsed.mod, config, edit.plugin);
1183
+ if (!("reason" in result) || !result.reason.includes("shares a line")) return result;
1184
+ const expanded = expandPluginsArray(source, config);
1185
+ const reparsed = expanded === void 0 ? void 0 : parseConfigs(expanded);
1186
+ const reparsedConfig = reparsed && !("reason" in reparsed) ? findConfig(reparsed) : void 0;
1187
+ return expanded !== void 0 && reparsed && !("reason" in reparsed) && reparsedConfig ? disablePlugin(expanded, reparsed.mod, reparsedConfig, edit.plugin) : result;
1188
+ }
1161
1189
  if (edit.operation === "enable-plugin") return enablePlugin(source, config, edit.plugin);
1162
1190
  if (edit.operation === "add-plugin") return applyAddPlugin({
1163
1191
  source,
@@ -1979,7 +2007,7 @@ var Agent = class extends capnweb.RpcTarget {
1979
2007
  });
1980
2008
  return this.#store;
1981
2009
  }
1982
- async [Symbol.asyncDispose]() {
2010
+ async clear() {
1983
2011
  if (this.#sandbox) await (0, node_fs_promises.rm)((0, _kubb_core.resolveCacheDir)(this.#sandboxCacheRoot), {
1984
2012
  recursive: true,
1985
2013
  force: true
@@ -2009,10 +2037,12 @@ var Agent = class extends capnweb.RpcTarget {
2009
2037
  message: "Studio must call connect() before any other command"
2010
2038
  });
2011
2039
  }
2012
- #logCommand(command, info) {
2040
+ #logCommand(command, info, requestedBy, failed) {
2013
2041
  return emit(this.#options.hooks, "studio:command", {
2014
2042
  command,
2015
- info
2043
+ info,
2044
+ requestedBy,
2045
+ failed
2016
2046
  });
2017
2047
  }
2018
2048
  async #readConfigFileView(source) {
@@ -2216,6 +2246,7 @@ var Agent = class extends capnweb.RpcTarget {
2216
2246
  allowExec: this.#permissions.allowWrite && this.#permissions.allowExec
2217
2247
  }).catch(async (error) => {
2218
2248
  await this.#generations.drop(jobId);
2249
+ await this.#logCommand("generate", getErrorMessage(error), input.requestedBy, true);
2219
2250
  throw error;
2220
2251
  });
2221
2252
  const output = await this.#generations.keep({
@@ -2234,7 +2265,7 @@ var Agent = class extends capnweb.RpcTarget {
2234
2265
  output,
2235
2266
  inputBytes
2236
2267
  });
2237
- await this.#logCommand("generate", `${activePlugins.length} plugin${activePlugins.length === 1 ? "" : "s"}, ${this.#permissions.allowWrite ? "written to disk" : "staged on disk"}${studioInput !== void 0 ? ", from a Studio spec" : ""}`);
2268
+ await this.#logCommand("generate", `${activePlugins.length} plugin${activePlugins.length === 1 ? "" : "s"}, ${this.#permissions.allowWrite ? "written to disk" : "staged on disk"}${studioInput !== void 0 ? ", from a Studio spec" : ""}`, input.requestedBy);
2238
2269
  return {
2239
2270
  status: "success",
2240
2271
  files: [...files.paths],
@@ -2273,7 +2304,7 @@ var Agent = class extends capnweb.RpcTarget {
2273
2304
  extensions: await this.#installedExtensions()
2274
2305
  });
2275
2306
  const applied = outcomes.filter((outcome) => outcome.applied).length;
2276
- await this.#logCommand("saveConfig", `applied ${applied}/${outcomes.length} edits to ${configPath}`);
2307
+ await this.#logCommand("saveConfig", `applied ${applied}/${outcomes.length} edits to ${configPath}`, input.requestedBy);
2277
2308
  return {
2278
2309
  outcomes,
2279
2310
  changed
@@ -2465,7 +2496,7 @@ async function runSession({ options, openRpc, url, instanceId }) {
2465
2496
  await emit(hooks, "studio:warn", { message: "Canceled the running generation: the connection to Kubb Studio closed" });
2466
2497
  }
2467
2498
  await active?.settled;
2468
- await agent[Symbol.asyncDispose]();
2499
+ await agent.clear();
2469
2500
  return {
2470
2501
  ...close,
2471
2502
  connected: session.info !== void 0
@@ -2933,6 +2964,7 @@ exports.InvalidAgentTokenError = InvalidAgentTokenError;
2933
2964
  exports.PairingCanceledError = PairingCanceledError;
2934
2965
  exports.PairingDeniedError = PairingDeniedError;
2935
2966
  exports.PairingExpiredError = PairingExpiredError;
2967
+ exports.applyConfigEdits = applyConfigEdits;
2936
2968
  exports.connectAgent = connectAgent;
2937
2969
  exports.createSnapshot = createSnapshot;
2938
2970
  exports.defaultStudioUrl = defaultStudioUrl;