@kubb/studio 5.12.3 → 5.12.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 +120 -7
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +120 -7
- package/dist/index.js.map +1 -1
- package/dist/{protocol-WYICLbSg.d.ts → protocol-C4loKcxw.d.cts} +33 -8
- package/dist/{protocol-WYICLbSg.d.cts → protocol-C4loKcxw.d.ts} +33 -8
- package/dist/protocol.cjs +3 -1
- package/dist/protocol.cjs.map +1 -1
- package/dist/protocol.d.cts +2 -2
- package/dist/protocol.d.ts +2 -2
- package/dist/protocol.js +3 -1
- package/dist/protocol.js.map +1 -1
- package/package.json +4 -4
package/dist/index.cjs
CHANGED
|
@@ -59,12 +59,23 @@ let node_zlib = require("node:zlib");
|
|
|
59
59
|
*
|
|
60
60
|
* When `pascal` is `true` the first word is also capitalized (PascalCase), otherwise only subsequent words are.
|
|
61
61
|
*/
|
|
62
|
-
function
|
|
62
|
+
function convert(text, pascal) {
|
|
63
63
|
return text.trim().replace(/([a-z\d])([A-Z])/g, "$1 $2").replace(/([A-Z]+)([A-Z][a-z])/g, "$1 $2").replace(/(\d)([a-z])/g, "$1 $2").split(/[\s\-_./\\:]+/).filter(Boolean).map((word, i) => {
|
|
64
64
|
if (word.length > 1 && word === word.toUpperCase()) return word;
|
|
65
65
|
return (i === 0 && !pascal ? word.charAt(0).toLowerCase() : word.charAt(0).toUpperCase()) + word.slice(1);
|
|
66
66
|
}).join("").replace(/[^a-zA-Z0-9]/g, "");
|
|
67
67
|
}
|
|
68
|
+
const cache = /* @__PURE__ */ new Map();
|
|
69
|
+
const cacheLimit = 1e4;
|
|
70
|
+
function toCamelOrPascal(text, pascal) {
|
|
71
|
+
const key = `${pascal ? "P" : "c"}${text}`;
|
|
72
|
+
const cached = cache.get(key);
|
|
73
|
+
if (cached !== void 0) return cached;
|
|
74
|
+
const result = convert(text, pascal);
|
|
75
|
+
if (cache.size >= cacheLimit) cache.clear();
|
|
76
|
+
cache.set(key, result);
|
|
77
|
+
return result;
|
|
78
|
+
}
|
|
68
79
|
/**
|
|
69
80
|
* Converts `text` to camelCase.
|
|
70
81
|
*
|
|
@@ -230,7 +241,7 @@ function getElapsedMs(hrStart) {
|
|
|
230
241
|
}
|
|
231
242
|
//#endregion
|
|
232
243
|
//#region package.json
|
|
233
|
-
var version = "5.12.
|
|
244
|
+
var version = "5.12.5";
|
|
234
245
|
//#endregion
|
|
235
246
|
//#region src/resolveConfig.ts
|
|
236
247
|
/**
|
|
@@ -586,6 +597,44 @@ async function rebuildExtension({ disk, studioOptions, kind, extensions }) {
|
|
|
586
597
|
});
|
|
587
598
|
}))(mergeOptions(disk.options ?? {}, studioOptions));
|
|
588
599
|
}
|
|
600
|
+
/** The root `output` members Studio may set, with the values each takes. The rest, `path` and `postGenerate` among them, stay with the config file. */
|
|
601
|
+
const OUTPUT_VALUES = {
|
|
602
|
+
barrel: (value) => value === false || isPlainObject(value) && Object.keys(value).length === 1 && (value.type === "named" || value.type === "all"),
|
|
603
|
+
format: (value) => value === false || [
|
|
604
|
+
"auto",
|
|
605
|
+
"prettier",
|
|
606
|
+
"biome",
|
|
607
|
+
"oxfmt"
|
|
608
|
+
].includes(value),
|
|
609
|
+
lint: (value) => value === false || [
|
|
610
|
+
"auto",
|
|
611
|
+
"eslint",
|
|
612
|
+
"biome",
|
|
613
|
+
"oxlint"
|
|
614
|
+
].includes(value),
|
|
615
|
+
clean: (value) => typeof value === "boolean",
|
|
616
|
+
defaultBanner: (value) => value === false || value === "simple" || value === "full"
|
|
617
|
+
};
|
|
618
|
+
/** Whether Studio may set the root `output` member `key`. */
|
|
619
|
+
function isOutputKey(key) {
|
|
620
|
+
return Object.hasOwn(OUTPUT_VALUES, key);
|
|
621
|
+
}
|
|
622
|
+
/** Whether Studio may set the root `output` member `key` to `value`. */
|
|
623
|
+
function isOutputValue({ key, value }) {
|
|
624
|
+
return isOutputKey(key) && OUTPUT_VALUES[key](value);
|
|
625
|
+
}
|
|
626
|
+
/** The members of `output` Studio may see and set. */
|
|
627
|
+
function pickOutput(output) {
|
|
628
|
+
return Object.fromEntries(Object.entries(output).filter(([key]) => isOutputKey(key)));
|
|
629
|
+
}
|
|
630
|
+
/** Merges Studio's valid `output` overrides, with `null` unsetting a member. */
|
|
631
|
+
function mergeOutput({ output, studio }) {
|
|
632
|
+
if (!isPlainObject(studio)) return output;
|
|
633
|
+
return mergeOptions(output, Object.fromEntries(Object.entries(studio).filter(([key, value]) => value === null ? isOutputKey(key) : isOutputValue({
|
|
634
|
+
key,
|
|
635
|
+
value
|
|
636
|
+
}))));
|
|
637
|
+
}
|
|
589
638
|
/**
|
|
590
639
|
* Merges Studio-provided adapter option overrides into the disk config's adapter, see {@link rebuildExtension}.
|
|
591
640
|
*/
|
|
@@ -643,14 +692,16 @@ function invalidEdit(edit) {
|
|
|
643
692
|
if (typeof operation !== "string" || !OPERATIONS.has(operation)) return `unknown operation ${JSON.stringify(operation)}`;
|
|
644
693
|
if (config !== void 0 && typeof config !== "string" && !Number.isSafeInteger(config)) return "config must name an entry or give its index";
|
|
645
694
|
if (operation === require_protocol.ConfigEditOperation.SET_INPUT) return typeof input === "string" && input.trim() ? void 0 : "the edit names no input";
|
|
646
|
-
|
|
695
|
+
const isOutput = operation === require_protocol.ConfigEditOperation.SET_OUTPUT || operation === require_protocol.ConfigEditOperation.REMOVE_OUTPUT;
|
|
696
|
+
if (!isOutput && (typeof plugin !== "string" || !plugin)) return "the edit names no plugin";
|
|
647
697
|
if (kind !== void 0 && (typeof kind !== "string" || !KINDS.has(kind))) return `unknown kind ${JSON.stringify(kind)}`;
|
|
648
698
|
if (kind !== void 0 && operation !== require_protocol.ConfigEditOperation.SET && operation !== require_protocol.ConfigEditOperation.REMOVE) return `${operation} edits the plugins array, so it takes no kind`;
|
|
649
|
-
if (operation === require_protocol.ConfigEditOperation.SET || operation === require_protocol.ConfigEditOperation.REMOVE) {
|
|
699
|
+
if (isOutput || operation === require_protocol.ConfigEditOperation.SET || operation === require_protocol.ConfigEditOperation.REMOVE) {
|
|
650
700
|
if (!Array.isArray(path) || !path.every((key) => typeof key === "string" && key)) return "path must be a list of option names";
|
|
651
701
|
if (!path.length) return "no option path given";
|
|
652
702
|
const unsafe = path.find((key) => !isSafeKey(key));
|
|
653
703
|
if (unsafe !== void 0) return `${unsafe} cannot be used as an option name`;
|
|
704
|
+
if (isOutput && !isOutputKey(path[0])) return `output.${path[0]} can only be changed in the config file`;
|
|
654
705
|
}
|
|
655
706
|
}
|
|
656
707
|
/** Where a node sits in the source text. */
|
|
@@ -951,9 +1002,12 @@ function readPartial(node, prefix = []) {
|
|
|
951
1002
|
}
|
|
952
1003
|
/** The top-level options of a plugin call, each flagged with whether Studio may write it. */
|
|
953
1004
|
function readOptions(call) {
|
|
954
|
-
const entries = {};
|
|
955
1005
|
const options = call.arguments[0];
|
|
956
|
-
|
|
1006
|
+
return options?.type === "ObjectExpression" ? readObject(options) : {};
|
|
1007
|
+
}
|
|
1008
|
+
/** The members of an object literal, each flagged with whether Studio may write it. */
|
|
1009
|
+
function readObject(options) {
|
|
1010
|
+
const entries = {};
|
|
957
1011
|
for (const [index, entry] of options.properties.entries()) {
|
|
958
1012
|
const key = memberKey(entry);
|
|
959
1013
|
if (key === void 0 || !isSafeKey(key)) continue;
|
|
@@ -1026,11 +1080,13 @@ function readConfig(source) {
|
|
|
1026
1080
|
});
|
|
1027
1081
|
const [adapter] = factoryCalls(mod, config, "adapter").map(toView);
|
|
1028
1082
|
const parsers = factoryCalls(mod, config, "parser").map(toView);
|
|
1083
|
+
const output = outputObject(config);
|
|
1029
1084
|
return {
|
|
1030
1085
|
name: configName(config),
|
|
1031
1086
|
plugins,
|
|
1032
1087
|
...adapter && { adapter },
|
|
1033
|
-
...parsers.length ? { parsers } : {}
|
|
1088
|
+
...parsers.length ? { parsers } : {},
|
|
1089
|
+
...!("reason" in output) && { output: pickOutput(readObject(output.object)) }
|
|
1034
1090
|
};
|
|
1035
1091
|
})
|
|
1036
1092
|
};
|
|
@@ -1079,6 +1135,16 @@ function applySet(source, call, path, value, quote) {
|
|
|
1079
1135
|
return { source: splice(source, closing, closing, printValue(nest(path, value), quote)) };
|
|
1080
1136
|
}
|
|
1081
1137
|
if (options.type !== "ObjectExpression") return { reason: "the factory was not called with an object literal" };
|
|
1138
|
+
return setIn({
|
|
1139
|
+
source,
|
|
1140
|
+
options,
|
|
1141
|
+
path,
|
|
1142
|
+
value,
|
|
1143
|
+
quote
|
|
1144
|
+
});
|
|
1145
|
+
}
|
|
1146
|
+
/** Writes the literal `value` at `path` inside `options`, adding any intermediate object it needs. */
|
|
1147
|
+
function setIn({ source, options, path, value, quote }) {
|
|
1082
1148
|
const target = walk(options, path);
|
|
1083
1149
|
if ("reason" in target) return target;
|
|
1084
1150
|
if ("missing" in target) {
|
|
@@ -1096,6 +1162,34 @@ function applySetInput(source, config, input, quote) {
|
|
|
1096
1162
|
if (isShadowed(config, found.index)) return { reason: "a spread after input could override it" };
|
|
1097
1163
|
return { source: splice(source, rangeOf(found.member.value).start, rangeOf(found.member.value).end, value) };
|
|
1098
1164
|
}
|
|
1165
|
+
/** The config's root `output` object literal, or why Studio cannot edit inside it. */
|
|
1166
|
+
function outputObject(config) {
|
|
1167
|
+
const found = findMember(config, "output");
|
|
1168
|
+
if (found?.member.type !== "ObjectProperty" || found.member.value.type !== "ObjectExpression") return { reason: "output is not an object literal" };
|
|
1169
|
+
if (isShadowed(config, found.index)) return { reason: "a spread after output could override it" };
|
|
1170
|
+
return { object: found.member.value };
|
|
1171
|
+
}
|
|
1172
|
+
/** Writes or drops a member of the config's root `output` object. */
|
|
1173
|
+
function applyOutputEdit({ source, config, edit, quote }) {
|
|
1174
|
+
const output = outputObject(config);
|
|
1175
|
+
if ("reason" in output) return output;
|
|
1176
|
+
if (edit.operation === require_protocol.ConfigEditOperation.REMOVE_OUTPUT) return removeIn({
|
|
1177
|
+
source,
|
|
1178
|
+
options: output.object,
|
|
1179
|
+
path: edit.path
|
|
1180
|
+
});
|
|
1181
|
+
if (!isOptionValue(edit.value) || !isOutputValue({
|
|
1182
|
+
key: edit.path[0],
|
|
1183
|
+
value: nest(edit.path.slice(1), edit.value)
|
|
1184
|
+
})) return { reason: `the value is not one output.${edit.path[0]} takes` };
|
|
1185
|
+
return setIn({
|
|
1186
|
+
source,
|
|
1187
|
+
options: output.object,
|
|
1188
|
+
path: edit.path,
|
|
1189
|
+
value: edit.value,
|
|
1190
|
+
quote
|
|
1191
|
+
});
|
|
1192
|
+
}
|
|
1099
1193
|
/**
|
|
1100
1194
|
* Deletes the option at `path`, falling the plugin back to its default for it. An option the file
|
|
1101
1195
|
* does not set already has its default, so removing it changes nothing.
|
|
@@ -1104,6 +1198,14 @@ function applyRemove(source, call, path) {
|
|
|
1104
1198
|
const options = call.arguments[0];
|
|
1105
1199
|
if (!options) return { source };
|
|
1106
1200
|
if (options.type !== "ObjectExpression") return { reason: "the factory was not called with an object literal" };
|
|
1201
|
+
return removeIn({
|
|
1202
|
+
source,
|
|
1203
|
+
options,
|
|
1204
|
+
path
|
|
1205
|
+
});
|
|
1206
|
+
}
|
|
1207
|
+
/** Deletes the member at `path` inside `options`. A path that is not there already holds its default. */
|
|
1208
|
+
function removeIn({ source, options, path }) {
|
|
1107
1209
|
const target = walk(options, path);
|
|
1108
1210
|
if ("reason" in target) return target;
|
|
1109
1211
|
if ("missing" in target) return { source };
|
|
@@ -1193,6 +1295,12 @@ function applyEdit({ source, edit, quote, extensions }) {
|
|
|
1193
1295
|
const config = findConfig(parsed);
|
|
1194
1296
|
if (!config) return { reason: `no config entry found for ${JSON.stringify(ref)}` };
|
|
1195
1297
|
if (edit.operation === require_protocol.ConfigEditOperation.SET_INPUT) return applySetInput(source, config, edit.input, quote);
|
|
1298
|
+
if (edit.operation === require_protocol.ConfigEditOperation.SET_OUTPUT || edit.operation === require_protocol.ConfigEditOperation.REMOVE_OUTPUT) return applyOutputEdit({
|
|
1299
|
+
source,
|
|
1300
|
+
config,
|
|
1301
|
+
edit,
|
|
1302
|
+
quote
|
|
1303
|
+
});
|
|
1196
1304
|
if (edit.operation === require_protocol.ConfigEditOperation.DISABLE_PLUGIN) {
|
|
1197
1305
|
const result = disablePlugin(source, parsed.mod, config, edit.plugin);
|
|
1198
1306
|
if (!("reason" in result) || !result.reason.includes("shares a line")) return result;
|
|
@@ -2392,6 +2500,10 @@ var Agent = class extends capnweb.RpcTarget {
|
|
|
2392
2500
|
...config,
|
|
2393
2501
|
root,
|
|
2394
2502
|
input: checkout?.path ?? studioInput ?? config.input,
|
|
2503
|
+
output: mergeOutput({
|
|
2504
|
+
output: config.output,
|
|
2505
|
+
studio: patch?.output
|
|
2506
|
+
}),
|
|
2395
2507
|
storage: outputRoot ? stagingStorage({
|
|
2396
2508
|
root,
|
|
2397
2509
|
directory: outputRoot
|
|
@@ -2851,6 +2963,7 @@ function toEntryView(config, extensions) {
|
|
|
2851
2963
|
...config.name !== void 0 && { name: config.name },
|
|
2852
2964
|
...input !== void 0 && { input },
|
|
2853
2965
|
output: config.output.path,
|
|
2966
|
+
outputOptions: toJSONOptions(pickOutput(config.output)),
|
|
2854
2967
|
plugins: config.plugins.map((plugin) => ({
|
|
2855
2968
|
name: toStudioName({
|
|
2856
2969
|
name: (0, _kubb_core.resolveMeta)(plugin).name,
|