sv 0.16.5 → 0.17.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.
- package/dist/bin.mjs +1 -1
- package/dist/{engine-CtSoxta7.d.mts → engine-5Sg3lJiQ.d.mts} +19 -6
- package/dist/{engine-CCAozEpo.mjs → engine-B7chsCPG.mjs} +508 -239
- package/dist/shared.json +96 -0
- package/dist/src/index.d.mts +1 -1
- package/dist/src/index.mjs +1 -1
- package/dist/src/testing.d.mts +1 -1
- package/dist/src/testing.mjs +1 -1
- package/dist/templates/addon/package.json +3 -3
- package/package.json +2 -2
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { createRequire } from "node:module";
|
|
2
|
-
import { AGENTS, COMMANDS, Walker, coerceVersion, color, constructCommand, createPrinter, dedent, defineEnv, detect, downloadJson, fileExists, isVersionUnsupportedBelow, js, loadFile, loadPackageJson, minVersion, parse, pnpm, resolveCommand, resolveCommandArray, sanitizeName, saveFile, svelte, svelteConfig, transforms } from "@sveltejs/sv-utils";
|
|
2
|
+
import { AGENTS, COMMANDS, KIT3_TSCONFIG, KIT3_TSCONFIG_DEFAULT, Walker, coerceVersion, color, constructCommand, createPrinter, dedent, defineEnv, detect, downloadJson, fileExists, isKit3, isVersionUnsupportedBelow, js, libSubpathImports, loadFile, loadPackageJson, minVersion, parse, pnpm, resolveCommand, resolveCommandArray, resolveLibPrefix, sanitizeName, saveFile, svelte, svelteConfig, transforms } from "@sveltejs/sv-utils";
|
|
3
3
|
import fs, { closeSync, existsSync, openSync, readSync, statSync } from "node:fs";
|
|
4
4
|
import path, { basename, delimiter, dirname, isAbsolute, join, normalize, resolve } from "node:path";
|
|
5
5
|
import { promisify, stripVTControlCharacters, styleText } from "node:util";
|
|
@@ -8,7 +8,7 @@ import * as b$1 from "node:readline";
|
|
|
8
8
|
import G from "node:readline";
|
|
9
9
|
import { ReadStream } from "node:tty";
|
|
10
10
|
import { fileURLToPath } from "node:url";
|
|
11
|
-
import childProcess, { exec, spawn } from "node:child_process";
|
|
11
|
+
import childProcess, { exec, spawn, spawnSync } from "node:child_process";
|
|
12
12
|
import { pipeline } from "node:stream/promises";
|
|
13
13
|
import { PassThrough } from "node:stream";
|
|
14
14
|
import { EventEmitter } from "node:events";
|
|
@@ -493,9 +493,9 @@ function W({ input: r = stdin, output: t = stdout, overwrite: s = !0, hideCursor
|
|
|
493
493
|
r.off("keypress", n), e && t.write(import_src.cursor.show), r instanceof ReadStream && r.isTTY && !q$1 && r.setRawMode(!1), i.terminal = !1, i.close();
|
|
494
494
|
};
|
|
495
495
|
}
|
|
496
|
-
const A = (r) => "columns" in r && typeof r.columns == "number" ? r.columns : 80, L = (r) => "rows" in r && typeof r.rows == "number" ? r.rows : 20;
|
|
497
|
-
function B(r, t, s, e = s, i = s, n) {
|
|
498
|
-
return wrapAnsi(t, A(r ?? stdout) - s.length, {
|
|
496
|
+
const A$1 = (r) => "columns" in r && typeof r.columns == "number" ? r.columns : 80, L$1 = (r) => "rows" in r && typeof r.rows == "number" ? r.rows : 20;
|
|
497
|
+
function B$1(r, t, s, e = s, i = s, n) {
|
|
498
|
+
return wrapAnsi(t, A$1(r ?? stdout) - s.length, {
|
|
499
499
|
hard: !0,
|
|
500
500
|
trim: !1
|
|
501
501
|
}).split(`
|
|
@@ -629,7 +629,7 @@ var m = class {
|
|
|
629
629
|
if (t !== this._prevFrame) {
|
|
630
630
|
if (this.state === "initial") this.output.write(import_src.cursor.hide);
|
|
631
631
|
else {
|
|
632
|
-
const s = Y$1(this._prevFrame, t), e = L(this.output);
|
|
632
|
+
const s = Y$1(this._prevFrame, t), e = L$1(this.output);
|
|
633
633
|
if (this.restoreCursor(), s) {
|
|
634
634
|
const i = Math.max(0, s.numLinesAfter - e), n = Math.max(0, s.numLinesBefore - e);
|
|
635
635
|
let o = s.lines.find((u) => u >= i);
|
|
@@ -805,7 +805,7 @@ const tt = se(), at = () => process.env.CI === "true", Tt = (t) => t.isTTY === !
|
|
|
805
805
|
removals: c
|
|
806
806
|
};
|
|
807
807
|
}, F$1 = ({ cursor: t, options: i, style: s, output: r = process.stdout, maxItems: u = Number.POSITIVE_INFINITY, columnPadding: n = 0, rowPadding: a = 4 }) => {
|
|
808
|
-
const c = A(r) - n, o = L(r), l = styleText("dim", "..."), d = Math.max(o - a, 0), g = Math.max(Math.min(u, d), 5);
|
|
808
|
+
const c = A$1(r) - n, o = L$1(r), l = styleText("dim", "..."), d = Math.max(o - a, 0), g = Math.max(Math.min(u, d), 5);
|
|
809
809
|
let p = 0;
|
|
810
810
|
t >= g - 3 && (p = Math.max(Math.min(t - g + 3, i.length - g), 0));
|
|
811
811
|
let f = g < i.length && p > 0, h = g < i.length && p + g < i.length;
|
|
@@ -843,7 +843,7 @@ const le = (t) => {
|
|
|
843
843
|
output: t.output,
|
|
844
844
|
initialValue: t.initialValue ?? !0,
|
|
845
845
|
render() {
|
|
846
|
-
const r = t.withGuide ?? h$1.withGuide, u = `${P$1(this.state)} `, n = r ? `${styleText("gray", $)} ` : "", a = B(t.output, t.message, n, u), c = `${r ? `${styleText("gray", $)}
|
|
846
|
+
const r = t.withGuide ?? h$1.withGuide, u = `${P$1(this.state)} `, n = r ? `${styleText("gray", $)} ` : "", a = B$1(t.output, t.message, n, u), c = `${r ? `${styleText("gray", $)}
|
|
847
847
|
` : ""}${a}
|
|
848
848
|
`, o = this.value ? i : s;
|
|
849
849
|
switch (this.state) {
|
|
@@ -961,7 +961,7 @@ ${styleText("reset", styleText("dim", `Press ${styleText([
|
|
|
961
961
|
], " space ")} to select, ${styleText("gray", styleText("bgWhite", styleText("inverse", " enter ")))} to submit`))}`;
|
|
962
962
|
},
|
|
963
963
|
render() {
|
|
964
|
-
const r = t.withGuide ?? h$1.withGuide, u = B(t.output, t.message, r ? `${ft(this.state)} ` : "", `${P$1(this.state)} `), n = `${r ? `${styleText("gray", $)}
|
|
964
|
+
const r = t.withGuide ?? h$1.withGuide, u = B$1(t.output, t.message, r ? `${ft(this.state)} ` : "", `${P$1(this.state)} `), n = `${r ? `${styleText("gray", $)}
|
|
965
965
|
` : ""}${u}
|
|
966
966
|
`, a = this.value ?? [], c = (o, l) => {
|
|
967
967
|
if (o.disabled) return i(o, "disabled");
|
|
@@ -971,12 +971,12 @@ ${styleText("reset", styleText("dim", `Press ${styleText([
|
|
|
971
971
|
switch (this.state) {
|
|
972
972
|
case "submit": {
|
|
973
973
|
const o = this.options.filter(({ value: d }) => a.includes(d)).map((d) => i(d, "submitted")).join(styleText("dim", ", ")) || styleText("dim", "none");
|
|
974
|
-
return `${n}${B(t.output, o, r ? `${styleText("gray", $)} ` : "")}`;
|
|
974
|
+
return `${n}${B$1(t.output, o, r ? `${styleText("gray", $)} ` : "")}`;
|
|
975
975
|
}
|
|
976
976
|
case "cancel": {
|
|
977
977
|
const o = this.options.filter(({ value: d }) => a.includes(d)).map((d) => i(d, "cancelled")).join(styleText("dim", ", "));
|
|
978
978
|
if (o.trim() === "") return `${n}${styleText("gray", $)}`;
|
|
979
|
-
return `${n}${B(t.output, o, r ? `${styleText("gray", $)} ` : "")}${r ? `
|
|
979
|
+
return `${n}${B$1(t.output, o, r ? `${styleText("gray", $)} ` : "")}${r ? `
|
|
980
980
|
${styleText("gray", $)}` : ""}`;
|
|
981
981
|
}
|
|
982
982
|
case "error": {
|
|
@@ -1027,7 +1027,7 @@ ${r ? styleText("cyan", x$1) : ""}
|
|
|
1027
1027
|
}, Ce = (t = "", i = "", s) => {
|
|
1028
1028
|
const r = s?.output ?? V.stdout, u = s?.withGuide ?? h$1.withGuide, n = s?.format ?? be, a = [
|
|
1029
1029
|
"",
|
|
1030
|
-
...Se(t, A(r) - 6, n).split(`
|
|
1030
|
+
...Se(t, A$1(r) - 6, n).split(`
|
|
1031
1031
|
`).map(n),
|
|
1032
1032
|
""
|
|
1033
1033
|
], c = fastStringWidth(i), o = Math.max(a.reduce((p, f) => {
|
|
@@ -1053,7 +1053,7 @@ ${styleText("gray", g + st.repeat(o + 2) + dt)}
|
|
|
1053
1053
|
], delay: a = tt ? 80 : 120, signal: c, ...o } = {}) => {
|
|
1054
1054
|
const l = at();
|
|
1055
1055
|
let d, g, p = !1, f = !1, h = "", I, m = performance.now();
|
|
1056
|
-
const y = A(s), v = o?.styleFrame ?? _e, C = (_) => {
|
|
1056
|
+
const y = A$1(s), v = o?.styleFrame ?? _e, C = (_) => {
|
|
1057
1057
|
const A = _ > 1 ? u ?? h$1.messages.error : r ?? h$1.messages.cancel;
|
|
1058
1058
|
f = _ === 1, p && (W$1(A, _), f && typeof i == "function" && i());
|
|
1059
1059
|
}, S = () => C(2), b = () => C(1), G = () => {
|
|
@@ -1136,17 +1136,17 @@ ${styleText("gray", g + st.repeat(o + 2) + dt)}
|
|
|
1136
1136
|
output: t.output,
|
|
1137
1137
|
initialValue: t.initialValue,
|
|
1138
1138
|
render() {
|
|
1139
|
-
const s = t.withGuide ?? h$1.withGuide, r = `${P$1(this.state)} `, u = `${ft(this.state)} `, n = B(t.output, t.message, u, r), a = `${s ? `${styleText("gray", $)}
|
|
1139
|
+
const s = t.withGuide ?? h$1.withGuide, r = `${P$1(this.state)} `, u = `${ft(this.state)} `, n = B$1(t.output, t.message, u, r), a = `${s ? `${styleText("gray", $)}
|
|
1140
1140
|
` : ""}${n}
|
|
1141
1141
|
`;
|
|
1142
1142
|
switch (this.state) {
|
|
1143
1143
|
case "submit": {
|
|
1144
1144
|
const c = s ? `${styleText("gray", $)} ` : "";
|
|
1145
|
-
return `${a}${B(t.output, i(this.options[this.cursor], "selected"), c)}`;
|
|
1145
|
+
return `${a}${B$1(t.output, i(this.options[this.cursor], "selected"), c)}`;
|
|
1146
1146
|
}
|
|
1147
1147
|
case "cancel": {
|
|
1148
1148
|
const c = s ? `${styleText("gray", $)} ` : "";
|
|
1149
|
-
return `${a}${B(t.output, i(this.options[this.cursor], "cancelled"), c)}${s ? `
|
|
1149
|
+
return `${a}${B$1(t.output, i(this.options[this.cursor], "cancelled"), c)}${s ? `
|
|
1150
1150
|
${styleText("gray", $)}` : ""}`;
|
|
1151
1151
|
}
|
|
1152
1152
|
default: {
|
|
@@ -1192,7 +1192,7 @@ ${Bt}${r.trimStart()}`), s = 3 + stripVTControlCharacters(r.trimStart()).length)
|
|
|
1192
1192
|
warning: (t) => q.warn(t),
|
|
1193
1193
|
error: (t) => q.message(t, { symbol: styleText("red", yt) })
|
|
1194
1194
|
}, Oe = (t) => t.replace(/\x1b\[(?:\d+;)*\d*[ABCDEFGHfJKSTsu]|\x1b\[(s|u)/g, ""), Pe = (t) => {
|
|
1195
|
-
const i = t.output ?? process.stdout, s = A(i), r = styleText("gray", $), u = t.spacing ?? 1, n = 3, a = t.retainLog === !0, c = !at() && Tt(i);
|
|
1195
|
+
const i = t.output ?? process.stdout, s = A$1(i), r = styleText("gray", $), u = t.spacing ?? 1, n = 3, a = t.retainLog === !0, c = !at() && Tt(i);
|
|
1196
1196
|
i.write(`${r}
|
|
1197
1197
|
`), i.write(`${styleText("green", H)} ${t.title}
|
|
1198
1198
|
`);
|
|
@@ -1348,7 +1348,7 @@ ${i ? styleText("cyan", x$1) : ""}
|
|
|
1348
1348
|
//#endregion
|
|
1349
1349
|
//#region package.json
|
|
1350
1350
|
var name = "sv";
|
|
1351
|
-
var version = "0.
|
|
1351
|
+
var version = "0.17.0";
|
|
1352
1352
|
//#endregion
|
|
1353
1353
|
//#region src/core/errors.ts
|
|
1354
1354
|
var UnsupportedError = class extends Error {
|
|
@@ -1361,6 +1361,7 @@ var UnsupportedError = class extends Error {
|
|
|
1361
1361
|
};
|
|
1362
1362
|
//#endregion
|
|
1363
1363
|
//#region src/core/common.ts
|
|
1364
|
+
const RX_IMPORT_ONLY = /^\s*@\S+\s*$/;
|
|
1364
1365
|
const NO_PREFIX = "--no-";
|
|
1365
1366
|
let options$8 = [];
|
|
1366
1367
|
function getLongFlag(flags) {
|
|
@@ -1530,7 +1531,7 @@ function updateAgent(projectPath, language, packageManager, loadedAddons) {
|
|
|
1530
1531
|
const agentFiles = [
|
|
1531
1532
|
"AGENTS.md",
|
|
1532
1533
|
"GEMINI.md",
|
|
1533
|
-
"CLAUDE.md"
|
|
1534
|
+
".claude/CLAUDE.md"
|
|
1534
1535
|
];
|
|
1535
1536
|
const languageLabel = language === "typescript" ? "TypeScript" : language === "checkjs" ? "JavaScript (JSDoc)" : "None";
|
|
1536
1537
|
const packageManagerLabel = packageManager ?? "npm";
|
|
@@ -1549,6 +1550,7 @@ function updateAgent(projectPath, language, packageManager, loadedAddons) {
|
|
|
1549
1550
|
const agentPath = path.join(projectPath, fileName);
|
|
1550
1551
|
if (!fs.existsSync(agentPath)) continue;
|
|
1551
1552
|
let content = fs.readFileSync(agentPath, "utf-8");
|
|
1553
|
+
if (RX_IMPORT_ONLY.test(content)) continue;
|
|
1552
1554
|
content = content.replace(existingSectionPattern, "");
|
|
1553
1555
|
content = configSection + content;
|
|
1554
1556
|
fs.writeFileSync(agentPath, content);
|
|
@@ -1885,10 +1887,12 @@ var k = class extends Error {
|
|
|
1885
1887
|
this.output = t;
|
|
1886
1888
|
}
|
|
1887
1889
|
};
|
|
1890
|
+
const A = /\r?\n/;
|
|
1888
1891
|
const j = {
|
|
1889
1892
|
timeout: void 0,
|
|
1890
1893
|
persist: false
|
|
1891
1894
|
};
|
|
1895
|
+
const M = { timeout: void 0 };
|
|
1892
1896
|
const N = { windowsHide: true };
|
|
1893
1897
|
function P(e) {
|
|
1894
1898
|
const t = new AbortController();
|
|
@@ -2036,12 +2040,56 @@ var I = class {
|
|
|
2036
2040
|
if (this._resolveClose) this._resolveClose();
|
|
2037
2041
|
};
|
|
2038
2042
|
};
|
|
2043
|
+
function L(e, r, i) {
|
|
2044
|
+
const a = {
|
|
2045
|
+
...M,
|
|
2046
|
+
...i
|
|
2047
|
+
};
|
|
2048
|
+
const o = cwd();
|
|
2049
|
+
const s = {
|
|
2050
|
+
windowsHide: true,
|
|
2051
|
+
...a.nodeOptions
|
|
2052
|
+
};
|
|
2053
|
+
if (a.timeout !== void 0) s.timeout = a.timeout;
|
|
2054
|
+
s.env = y(o, s.env, a.nodePath);
|
|
2055
|
+
const c = D(e, r ?? [], s);
|
|
2056
|
+
const l = spawnSync(c.command, c.args, c.options);
|
|
2057
|
+
if (l.error) throw l.error;
|
|
2058
|
+
const u = l.stdout?.toString() ?? "";
|
|
2059
|
+
const d = l.stderr?.toString() ?? "";
|
|
2060
|
+
const f = l.status ?? void 0;
|
|
2061
|
+
const p = l.signal != null;
|
|
2062
|
+
const m = {
|
|
2063
|
+
stdout: u,
|
|
2064
|
+
stderr: d,
|
|
2065
|
+
get exitCode() {
|
|
2066
|
+
return f;
|
|
2067
|
+
},
|
|
2068
|
+
get pid() {
|
|
2069
|
+
return l.pid;
|
|
2070
|
+
},
|
|
2071
|
+
get killed() {
|
|
2072
|
+
return p;
|
|
2073
|
+
},
|
|
2074
|
+
*[Symbol.iterator]() {
|
|
2075
|
+
for (const e of [u, d]) {
|
|
2076
|
+
if (!e) continue;
|
|
2077
|
+
const t = e.split(A);
|
|
2078
|
+
if (t[t.length - 1] === "") t.pop();
|
|
2079
|
+
yield* t;
|
|
2080
|
+
}
|
|
2081
|
+
}
|
|
2082
|
+
};
|
|
2083
|
+
if (a.throwOnError && f !== 0 && f !== void 0) throw new k(m, m);
|
|
2084
|
+
return m;
|
|
2085
|
+
}
|
|
2039
2086
|
const R = (e, t, n) => {
|
|
2040
2087
|
const r = new I(e, t, n);
|
|
2041
2088
|
r.spawn();
|
|
2042
2089
|
return r;
|
|
2043
2090
|
};
|
|
2044
2091
|
const z = R;
|
|
2092
|
+
const B = L;
|
|
2045
2093
|
//#endregion
|
|
2046
2094
|
//#region ../../node_modules/.pnpm/commander@15.0.0/node_modules/commander/lib/error.js
|
|
2047
2095
|
/**
|
|
@@ -5637,11 +5685,9 @@ function pipe(...pipe$1) {
|
|
|
5637
5685
|
}
|
|
5638
5686
|
//#endregion
|
|
5639
5687
|
//#region src/core/config.ts
|
|
5640
|
-
|
|
5641
|
-
|
|
5642
|
-
|
|
5643
|
-
function defineAddon(config) {
|
|
5644
|
-
return config;
|
|
5688
|
+
function defineAddon(...args) {
|
|
5689
|
+
if (args.length === 0) return (config) => config;
|
|
5690
|
+
return args[0];
|
|
5645
5691
|
}
|
|
5646
5692
|
/**
|
|
5647
5693
|
* Generates an inline error hint based on the addon source
|
|
@@ -5690,6 +5736,263 @@ function createOptionBuilder(options) {
|
|
|
5690
5736
|
};
|
|
5691
5737
|
}
|
|
5692
5738
|
//#endregion
|
|
5739
|
+
//#region src/addons/ai-tools.ts
|
|
5740
|
+
const REGEX_MD = /\.md$/;
|
|
5741
|
+
const CLIENTS = {
|
|
5742
|
+
"claude-code": {
|
|
5743
|
+
label: "Claude Code",
|
|
5744
|
+
pluginSettings: {
|
|
5745
|
+
path: ".claude/settings.json",
|
|
5746
|
+
marketplace: "svelte",
|
|
5747
|
+
repo: "sveltejs/ai-tools",
|
|
5748
|
+
id: "svelte@svelte"
|
|
5749
|
+
},
|
|
5750
|
+
agentPath: "AGENTS.md",
|
|
5751
|
+
agentLink: {
|
|
5752
|
+
path: ".claude/CLAUDE.md",
|
|
5753
|
+
contents: "@../AGENTS.md\n"
|
|
5754
|
+
},
|
|
5755
|
+
configPath: ".mcp.json",
|
|
5756
|
+
skillsPath: ".claude/skills",
|
|
5757
|
+
agentsPath: ".claude/agents",
|
|
5758
|
+
mcpOptions: {
|
|
5759
|
+
typeLocal: "stdio",
|
|
5760
|
+
typeRemote: "http",
|
|
5761
|
+
env: true
|
|
5762
|
+
}
|
|
5763
|
+
},
|
|
5764
|
+
cursor: {
|
|
5765
|
+
label: "Cursor",
|
|
5766
|
+
agentPath: "AGENTS.md",
|
|
5767
|
+
configPath: ".cursor/mcp.json",
|
|
5768
|
+
skillsPath: ".cursor/skills",
|
|
5769
|
+
agentsPath: ".cursor/agents",
|
|
5770
|
+
mcpOptions: {}
|
|
5771
|
+
},
|
|
5772
|
+
gemini: {
|
|
5773
|
+
label: "Gemini",
|
|
5774
|
+
agentPath: "GEMINI.md",
|
|
5775
|
+
configPath: ".gemini/settings.json",
|
|
5776
|
+
skillsPath: ".gemini/skills",
|
|
5777
|
+
agentsPath: ".gemini/agents",
|
|
5778
|
+
schema: "https://raw.githubusercontent.com/google-gemini/gemini-cli/main/schemas/settings.schema.json",
|
|
5779
|
+
mcpOptions: {}
|
|
5780
|
+
},
|
|
5781
|
+
opencode: {
|
|
5782
|
+
label: "OpenCode",
|
|
5783
|
+
pluginOnly: true,
|
|
5784
|
+
agentPath: "AGENTS.md",
|
|
5785
|
+
configPath: ".opencode/opencode.json",
|
|
5786
|
+
schema: "https://opencode.ai/config.json",
|
|
5787
|
+
customData: { plugin: ["@sveltejs/opencode"] },
|
|
5788
|
+
extraFiles: [{
|
|
5789
|
+
path: ".opencode/svelte.json",
|
|
5790
|
+
data: { $schema: "https://svelte.dev/opencode/schema.json" }
|
|
5791
|
+
}]
|
|
5792
|
+
},
|
|
5793
|
+
vscode: {
|
|
5794
|
+
label: "VS Code",
|
|
5795
|
+
agentPath: "AGENTS.md",
|
|
5796
|
+
configPath: ".vscode/mcp.json",
|
|
5797
|
+
skillsPath: ".github/skills",
|
|
5798
|
+
agentsPath: ".github/agents",
|
|
5799
|
+
agentExtension: ".agent.md",
|
|
5800
|
+
mcpOptions: { serversKey: "servers" }
|
|
5801
|
+
},
|
|
5802
|
+
other: {
|
|
5803
|
+
label: "Other",
|
|
5804
|
+
agentPath: "AGENTS.md"
|
|
5805
|
+
}
|
|
5806
|
+
};
|
|
5807
|
+
const acceptsTools = (client) => Boolean(client && !client.pluginOnly && (client.skillsPath || client.agentsPath || client.configPath));
|
|
5808
|
+
const wantsLooseTools = (client, delivery) => acceptsTools(client) && (!client.pluginSettings || delivery !== "plugin");
|
|
5809
|
+
const wantsMcpConfig = (client, delivery) => Boolean(client?.mcpOptions) && wantsLooseTools(client, delivery);
|
|
5810
|
+
const TOOLS = {
|
|
5811
|
+
mcp: {
|
|
5812
|
+
label: "MCP server",
|
|
5813
|
+
kind: "mcp"
|
|
5814
|
+
},
|
|
5815
|
+
"svelte-code-writer": {
|
|
5816
|
+
label: "svelte-code-writer",
|
|
5817
|
+
kind: "skill",
|
|
5818
|
+
hint: "skill"
|
|
5819
|
+
},
|
|
5820
|
+
"svelte-core-bestpractices": {
|
|
5821
|
+
label: "svelte-core-bestpractices",
|
|
5822
|
+
kind: "skill",
|
|
5823
|
+
hint: "skill"
|
|
5824
|
+
},
|
|
5825
|
+
"svelte-file-editor": {
|
|
5826
|
+
label: "svelte-file-editor",
|
|
5827
|
+
kind: "agent",
|
|
5828
|
+
hint: "sub-agent"
|
|
5829
|
+
}
|
|
5830
|
+
};
|
|
5831
|
+
var ai_tools_default = defineAddon({
|
|
5832
|
+
id: "ai-tools",
|
|
5833
|
+
shortDescription: "Svelte AI tools",
|
|
5834
|
+
homepage: "https://svelte.dev/docs/ai",
|
|
5835
|
+
options: defineAddonOptions().add("ide", {
|
|
5836
|
+
question: "Which client would you like to use?",
|
|
5837
|
+
type: "multiselect",
|
|
5838
|
+
default: [],
|
|
5839
|
+
options: Object.entries(CLIENTS).map(([value, client]) => ({
|
|
5840
|
+
value,
|
|
5841
|
+
label: client.label
|
|
5842
|
+
})),
|
|
5843
|
+
required: true
|
|
5844
|
+
}).add("delivery", {
|
|
5845
|
+
question: "How would you like to add the Svelte tools?",
|
|
5846
|
+
type: "select",
|
|
5847
|
+
default: "plugin",
|
|
5848
|
+
options: [{
|
|
5849
|
+
value: "plugin",
|
|
5850
|
+
label: "Svelte plugin",
|
|
5851
|
+
hint: "recommended, auto-installs & updates"
|
|
5852
|
+
}, {
|
|
5853
|
+
value: "tools",
|
|
5854
|
+
label: "Individual tools",
|
|
5855
|
+
hint: "choose exactly what to add"
|
|
5856
|
+
}],
|
|
5857
|
+
condition: ({ ide }) => ide.some((i) => CLIENTS[i]?.pluginSettings)
|
|
5858
|
+
}).add("tools", {
|
|
5859
|
+
question: "Which tools would you like to add?",
|
|
5860
|
+
type: "multiselect",
|
|
5861
|
+
default: Object.keys(TOOLS),
|
|
5862
|
+
options: Object.entries(TOOLS).map(([value, t]) => ({
|
|
5863
|
+
value,
|
|
5864
|
+
label: t.label,
|
|
5865
|
+
hint: t.hint
|
|
5866
|
+
})),
|
|
5867
|
+
required: false,
|
|
5868
|
+
condition: ({ ide, delivery }) => ide.some((i) => wantsLooseTools(CLIENTS[i], delivery))
|
|
5869
|
+
}).add("mcpSetup", {
|
|
5870
|
+
question: "Which MCP setup would you like to use?",
|
|
5871
|
+
type: "select",
|
|
5872
|
+
default: "remote",
|
|
5873
|
+
options: [{
|
|
5874
|
+
value: "local",
|
|
5875
|
+
label: "Local",
|
|
5876
|
+
hint: "will use stdio"
|
|
5877
|
+
}, {
|
|
5878
|
+
value: "remote",
|
|
5879
|
+
label: "Remote",
|
|
5880
|
+
hint: "will use a remote endpoint"
|
|
5881
|
+
}],
|
|
5882
|
+
condition: ({ ide, delivery, tools }) => (tools === void 0 || tools.includes("mcp")) && ide.some((i) => wantsMcpConfig(CLIENTS[i], delivery))
|
|
5883
|
+
}).build(),
|
|
5884
|
+
run: ({ sv, options }) => {
|
|
5885
|
+
const usePlugin = options.delivery === "plugin";
|
|
5886
|
+
const selected = options.tools ?? Object.keys(TOOLS);
|
|
5887
|
+
const selectedSkills = selected.filter((t) => TOOLS[t]?.kind === "skill");
|
|
5888
|
+
const selectedAgents = selected.filter((t) => TOOLS[t]?.kind === "agent");
|
|
5889
|
+
const wantsMcp = selected.includes("mcp");
|
|
5890
|
+
const getLocalConfig = (o) => {
|
|
5891
|
+
return {
|
|
5892
|
+
...o?.typeLocal ? { type: o.typeLocal } : {},
|
|
5893
|
+
command: o?.command ?? "npx",
|
|
5894
|
+
...o?.env ? { env: {} } : {},
|
|
5895
|
+
...o?.args === null ? {} : { args: o?.args ?? ["-y", "@sveltejs/mcp"] }
|
|
5896
|
+
};
|
|
5897
|
+
};
|
|
5898
|
+
const getRemoteConfig = (o) => {
|
|
5899
|
+
return {
|
|
5900
|
+
...o?.typeRemote ? { type: o.typeRemote } : {},
|
|
5901
|
+
url: "https://mcp.svelte.dev/mcp"
|
|
5902
|
+
};
|
|
5903
|
+
};
|
|
5904
|
+
const filesAdded = [];
|
|
5905
|
+
const filesExistingAlready = [];
|
|
5906
|
+
const sharedFiles = getSharedFiles();
|
|
5907
|
+
const mcpFiles = sharedFiles.filter((file) => file.include.includes("mcp"));
|
|
5908
|
+
const skillFiles = sharedFiles.filter((file) => file.include.includes("skills"));
|
|
5909
|
+
const agentFiles = sharedFiles.filter((file) => file.include.includes("agents"));
|
|
5910
|
+
const agentFile = mcpFiles.find((file) => file.name === "AGENTS.md");
|
|
5911
|
+
const addFile = (path, contents) => {
|
|
5912
|
+
sv.file(path, (content) => {
|
|
5913
|
+
if (content) {
|
|
5914
|
+
filesExistingAlready.push(path);
|
|
5915
|
+
return false;
|
|
5916
|
+
}
|
|
5917
|
+
if (!filesAdded.includes(path)) filesAdded.push(path);
|
|
5918
|
+
return contents;
|
|
5919
|
+
});
|
|
5920
|
+
};
|
|
5921
|
+
for (const ide of options.ide) {
|
|
5922
|
+
const client = CLIENTS[ide];
|
|
5923
|
+
if (!client) continue;
|
|
5924
|
+
if (client.pluginSettings && usePlugin) {
|
|
5925
|
+
const plugin = client.pluginSettings;
|
|
5926
|
+
sv.file(plugin.path, transforms.json(({ data }) => {
|
|
5927
|
+
data.extraKnownMarketplaces ??= {};
|
|
5928
|
+
data.extraKnownMarketplaces[plugin.marketplace] ??= { source: {
|
|
5929
|
+
source: "github",
|
|
5930
|
+
repo: plugin.repo
|
|
5931
|
+
} };
|
|
5932
|
+
data.enabledPlugins ??= {};
|
|
5933
|
+
data.enabledPlugins[plugin.id] = true;
|
|
5934
|
+
}));
|
|
5935
|
+
continue;
|
|
5936
|
+
}
|
|
5937
|
+
if (!client.agentPath) continue;
|
|
5938
|
+
const { mcpOptions, agentPath, agentLink, configPath, skillsPath, agentsPath, agentExtension, schema, customData, extraFiles } = client;
|
|
5939
|
+
if (!filesAdded.includes(agentPath)) sv.file(agentPath, (content) => {
|
|
5940
|
+
if (content) {
|
|
5941
|
+
filesExistingAlready.push(agentPath);
|
|
5942
|
+
return false;
|
|
5943
|
+
}
|
|
5944
|
+
filesAdded.push(agentPath);
|
|
5945
|
+
return agentFile?.contents ?? "";
|
|
5946
|
+
});
|
|
5947
|
+
if (agentLink) addFile(agentLink.path, agentLink.contents);
|
|
5948
|
+
const writeMcp = Boolean(mcpOptions) && wantsMcp;
|
|
5949
|
+
if (configPath && (writeMcp || customData)) sv.file(configPath, transforms.json(({ data }) => {
|
|
5950
|
+
if (schema) data["$schema"] = schema;
|
|
5951
|
+
if (customData) for (const [key, value] of Object.entries(customData)) data[key] = value;
|
|
5952
|
+
if (writeMcp) {
|
|
5953
|
+
const key = mcpOptions.serversKey ?? "mcpServers";
|
|
5954
|
+
data[key] ??= {};
|
|
5955
|
+
data[key].svelte = options.mcpSetup === "local" ? getLocalConfig(mcpOptions) : getRemoteConfig(mcpOptions);
|
|
5956
|
+
}
|
|
5957
|
+
}));
|
|
5958
|
+
if (extraFiles) for (const extra of extraFiles) sv.file(extra.path, transforms.json(({ data }) => {
|
|
5959
|
+
for (const [key, value] of Object.entries(extra.data)) data[key] = value;
|
|
5960
|
+
}));
|
|
5961
|
+
if (skillsPath) for (const file of skillFiles) {
|
|
5962
|
+
if (!selectedSkills.includes(file.name.split("/")[0])) continue;
|
|
5963
|
+
addFile(`${skillsPath}/${file.name}`, file.contents);
|
|
5964
|
+
}
|
|
5965
|
+
if (agentsPath) for (const file of agentFiles) {
|
|
5966
|
+
if (!selectedAgents.includes(file.name.replace(REGEX_MD, ""))) continue;
|
|
5967
|
+
const ext = agentExtension ?? ".md";
|
|
5968
|
+
addFile(`${agentsPath}/${file.name.replace(REGEX_MD, ext)}`, file.contents);
|
|
5969
|
+
}
|
|
5970
|
+
}
|
|
5971
|
+
if (filesExistingAlready.length > 0) R$1.warn(`${filesExistingAlready.map((path) => color.path(path)).join(", ")} already exists, we didn't touch ${filesExistingAlready.length > 1 ? "them" : "it"}. See ${color.website("https://svelte.dev/docs/ai")} for manual setup.`);
|
|
5972
|
+
},
|
|
5973
|
+
nextSteps({ options, cwd }) {
|
|
5974
|
+
const steps = [];
|
|
5975
|
+
for (const ide of options.ide) {
|
|
5976
|
+
const client = CLIENTS[ide];
|
|
5977
|
+
if (!client?.pluginSettings) continue;
|
|
5978
|
+
const plugin = client.pluginSettings;
|
|
5979
|
+
const settingsPath = path.resolve(cwd, plugin.path);
|
|
5980
|
+
if (!fs.existsSync(settingsPath)) continue;
|
|
5981
|
+
let pluginEnabled = false;
|
|
5982
|
+
try {
|
|
5983
|
+
pluginEnabled = Boolean(JSON.parse(fs.readFileSync(settingsPath, "utf8")).enabledPlugins?.[plugin.id]);
|
|
5984
|
+
} catch {}
|
|
5985
|
+
if (!pluginEnabled) continue;
|
|
5986
|
+
const looseDirs = [client.skillsPath, client.agentsPath].filter((dir) => Boolean(dir) && fs.existsSync(path.resolve(cwd, dir)) && fs.readdirSync(path.resolve(cwd, dir)).some((entry) => Object.keys(TOOLS).includes(entry.replace(REGEX_MD, ""))));
|
|
5987
|
+
if (looseDirs.length === 0) continue;
|
|
5988
|
+
steps.push(`${client.label}: the Svelte plugin is enabled and ${looseDirs.map((d) => color.path(d)).join(" + ")} also exist${looseDirs.length > 1 ? "" : "s"} - remove ${looseDirs.length > 1 ? "them" : "it"} (or disable the plugin) to avoid duplicate skills/sub-agents.`);
|
|
5989
|
+
}
|
|
5990
|
+
if (options.delivery === "plugin" && options.ide.includes("claude-code")) steps.push(`Open the project in Claude Code and trust the workspace - the Svelte plugin installs automatically.`);
|
|
5991
|
+
if (options.ide.includes("other")) steps.push(`For other clients: ${color.website(`https://svelte.dev/docs/ai/${options.mcpSetup ?? "remote"}-setup#Other-clients`)}`);
|
|
5992
|
+
return steps;
|
|
5993
|
+
}
|
|
5994
|
+
});
|
|
5995
|
+
//#endregion
|
|
5693
5996
|
//#region src/addons/common.ts
|
|
5694
5997
|
const ESLINT_VERSION = "^10.4.1";
|
|
5695
5998
|
const addEslintConfigPrettier = transforms.script(({ ast, js }) => {
|
|
@@ -5842,6 +6145,7 @@ var better_auth_default = defineAddon({
|
|
|
5842
6145
|
runsAfter("experimental");
|
|
5843
6146
|
},
|
|
5844
6147
|
run: ({ sv, cwd, language, options, directory, dependencyVersion, file }) => {
|
|
6148
|
+
const lib = resolveLibPrefix(dependencyVersion("@sveltejs/kit"));
|
|
5845
6149
|
const svelteVersion = dependencyVersion("svelte");
|
|
5846
6150
|
const svelte5 = !!svelteVersion && coerceVersion(svelteVersion).major === 5;
|
|
5847
6151
|
const [ts, s5] = createPrinter(language === "ts", svelte5);
|
|
@@ -5888,7 +6192,7 @@ var better_auth_default = defineAddon({
|
|
|
5888
6192
|
}
|
|
5889
6193
|
sv.file(`${directory.lib}/server/auth.${language}`, transforms.script(({ ast, comments, js }) => {
|
|
5890
6194
|
js.imports.addNamed(ast, {
|
|
5891
|
-
from:
|
|
6195
|
+
from: `${lib}/server/db`,
|
|
5892
6196
|
imports: [d1 ? "getDb" : "db"]
|
|
5893
6197
|
});
|
|
5894
6198
|
js.imports.addNamed(ast, {
|
|
@@ -5945,7 +6249,7 @@ var better_auth_default = defineAddon({
|
|
|
5945
6249
|
/**
|
|
5946
6250
|
* DO NOT USE!
|
|
5947
6251
|
*
|
|
5948
|
-
* This instance is used by the \`
|
|
6252
|
+
* This instance is used by the \`auth\` CLI for schema generation ONLY.
|
|
5949
6253
|
* To access \`auth\` at runtime, use \`event.locals.auth\`.
|
|
5950
6254
|
*/
|
|
5951
6255
|
export const auth = createAuth(null${ts("!")});`;
|
|
@@ -5969,7 +6273,7 @@ var better_auth_default = defineAddon({
|
|
|
5969
6273
|
const authConfigPath = `${directory.lib}/server/auth.${language}`;
|
|
5970
6274
|
const authSchemaPath = `${directory.lib}/server/db/auth.schema.${language}`;
|
|
5971
6275
|
sv.file(file.package, transforms.json(({ data, json }) => {
|
|
5972
|
-
json.packageScriptsUpsert(data, "auth:schema", `
|
|
6276
|
+
json.packageScriptsUpsert(data, "auth:schema", `auth generate --config ${authConfigPath} --output ${authSchemaPath} --yes`);
|
|
5973
6277
|
}));
|
|
5974
6278
|
sv.file(`${directory.lib}/server/db/auth.schema.${language}`, transforms.text(({ content }) => {
|
|
5975
6279
|
if (content) return false;
|
|
@@ -5984,7 +6288,7 @@ var better_auth_default = defineAddon({
|
|
|
5984
6288
|
sv.file("src/app.d.ts", transforms.script(({ ast, comments, js }) => {
|
|
5985
6289
|
if (d1) js.imports.addNamed(ast, {
|
|
5986
6290
|
imports: ["createAuth"],
|
|
5987
|
-
from:
|
|
6291
|
+
from: `${lib}/server/auth`
|
|
5988
6292
|
});
|
|
5989
6293
|
js.imports.addNamed(ast, {
|
|
5990
6294
|
imports: ["User", "Session"],
|
|
@@ -6008,7 +6312,7 @@ var better_auth_default = defineAddon({
|
|
|
6008
6312
|
});
|
|
6009
6313
|
js.imports.addNamed(ast, {
|
|
6010
6314
|
imports: [d1 ? "createAuth" : "auth"],
|
|
6011
|
-
from:
|
|
6315
|
+
from: `${lib}/server/auth`
|
|
6012
6316
|
});
|
|
6013
6317
|
env.importEnv(ast, js, ["building"]);
|
|
6014
6318
|
const handleContent = dedent`
|
|
@@ -6116,7 +6420,7 @@ var better_auth_default = defineAddon({
|
|
|
6116
6420
|
import { fail, redirect } from '@sveltejs/kit';
|
|
6117
6421
|
${ts("import type { Actions } from './$types';")}
|
|
6118
6422
|
${ts("import type { PageServerLoad } from './$types';")}
|
|
6119
|
-
${!d1 ?
|
|
6423
|
+
${!d1 ? `import { auth } from '${lib}/server/auth';` : ""}
|
|
6120
6424
|
${needsAPIError ? "import { APIError } from 'better-auth/api';" : ""}
|
|
6121
6425
|
|
|
6122
6426
|
export const load${ts(": PageServerLoad")} = (event) => {
|
|
@@ -6185,7 +6489,7 @@ var better_auth_default = defineAddon({
|
|
|
6185
6489
|
import { redirect } from '@sveltejs/kit';
|
|
6186
6490
|
${ts("import type { Actions } from './$types';")}
|
|
6187
6491
|
${ts("import type { PageServerLoad } from './$types';")}
|
|
6188
|
-
${!d1 ?
|
|
6492
|
+
${!d1 ? `import { auth } from '${lib}/server/auth';` : ""}
|
|
6189
6493
|
|
|
6190
6494
|
export const load${ts(": PageServerLoad")} = (event) => {
|
|
6191
6495
|
if (!event.locals.user) {
|
|
@@ -6352,7 +6656,7 @@ var drizzle_default = defineAddon({
|
|
|
6352
6656
|
runsAfter("experimental");
|
|
6353
6657
|
if (!isKit) return unsupported("Requires SvelteKit");
|
|
6354
6658
|
},
|
|
6355
|
-
run: ({ sv, language, options, directory, dependencyVersion, cwd, cancel, file
|
|
6659
|
+
run: ({ sv, language, options, directory, dependencyVersion, cwd, cancel, file }) => {
|
|
6356
6660
|
const [ts] = createPrinter(language === "ts");
|
|
6357
6661
|
const baseDBPath = path.resolve(cwd, directory.lib, "server", "db");
|
|
6358
6662
|
const paths = {
|
|
@@ -6369,9 +6673,8 @@ var drizzle_default = defineAddon({
|
|
|
6369
6673
|
if (options.postgresql === "neon") sv.devDependency("@neondatabase/serverless", "^1.1.0");
|
|
6370
6674
|
if (options.postgresql === "postgres.js") sv.devDependency("postgres", "^3.4.9");
|
|
6371
6675
|
if (options.sqlite === "better-sqlite3") {
|
|
6372
|
-
sv.dependency("better-sqlite3", "^
|
|
6676
|
+
sv.dependency("better-sqlite3", "^13.0.2");
|
|
6373
6677
|
sv.devDependency("@types/better-sqlite3", "^7.6.13");
|
|
6374
|
-
if (packageManager === "pnpm") sv.file(file.findUp("pnpm-workspace.yaml"), pnpm.allowBuilds("better-sqlite3"));
|
|
6375
6678
|
}
|
|
6376
6679
|
if (options.sqlite === "libsql" || options.sqlite === "turso") sv.devDependency("@libsql/client", "^0.17.3");
|
|
6377
6680
|
sv.file(".env", generateEnv(options, false));
|
|
@@ -6469,7 +6772,13 @@ var drizzle_default = defineAddon({
|
|
|
6469
6772
|
})
|
|
6470
6773
|
`) });
|
|
6471
6774
|
}));
|
|
6472
|
-
|
|
6775
|
+
if (isKit3(dependencyVersion("@sveltejs/kit"))) {
|
|
6776
|
+
const configFile = language === "ts" ? "tsconfig.json" : "jsconfig.json";
|
|
6777
|
+
if (fileExists(cwd, configFile)) sv.file(configFile, transforms.json(({ data }) => {
|
|
6778
|
+
const include = data.include ??= ["src"];
|
|
6779
|
+
if (!include.includes(`drizzle.config.${language}`)) include.push(`drizzle.config.${language}`);
|
|
6780
|
+
}));
|
|
6781
|
+
} else svelteConfig.edit({
|
|
6473
6782
|
sv,
|
|
6474
6783
|
cwd
|
|
6475
6784
|
}, ({ override, js }) => {
|
|
@@ -6885,12 +7194,25 @@ const FEATURES = {
|
|
|
6885
7194
|
hint: "kit ^2 only",
|
|
6886
7195
|
inNext: false
|
|
6887
7196
|
},
|
|
6888
|
-
handleRenderingErrors: {
|
|
7197
|
+
handleRenderingErrors: {
|
|
7198
|
+
label: "rendering error boundaries",
|
|
7199
|
+
hint: "kit ^2 only",
|
|
7200
|
+
inNext: false
|
|
7201
|
+
},
|
|
6889
7202
|
forkPreloads: {
|
|
6890
7203
|
label: "forked preloading",
|
|
6891
7204
|
off: true
|
|
6892
7205
|
}
|
|
6893
7206
|
};
|
|
7207
|
+
const SOURCE_EXTENSIONS = [
|
|
7208
|
+
".svelte",
|
|
7209
|
+
".svelte.ts",
|
|
7210
|
+
".svelte.js",
|
|
7211
|
+
".ts",
|
|
7212
|
+
".js",
|
|
7213
|
+
".svx",
|
|
7214
|
+
".md"
|
|
7215
|
+
];
|
|
6894
7216
|
const KIT3_PEERS = {
|
|
6895
7217
|
vite: "^8.0.0",
|
|
6896
7218
|
"@sveltejs/vite-plugin-svelte": "^7.0.0",
|
|
@@ -6922,7 +7244,7 @@ var experimental_default = defineAddon({
|
|
|
6922
7244
|
required: false
|
|
6923
7245
|
}).build(),
|
|
6924
7246
|
setup: ({ runsAfter }) => runsAfter("sveltekitAdapter"),
|
|
6925
|
-
run: ({ sv, cwd, options, language, dependencyVersion }) => {
|
|
7247
|
+
run: ({ sv, cwd, options, language, directory, dependencyVersion }) => {
|
|
6926
7248
|
const kitNext = options.versions.includes("kit");
|
|
6927
7249
|
if (kitNext) {
|
|
6928
7250
|
sv.devDependency("@sveltejs/kit", "next");
|
|
@@ -6938,6 +7260,23 @@ var experimental_default = defineAddon({
|
|
|
6938
7260
|
};
|
|
6939
7261
|
for (const name of Object.keys(deps)) if (name.startsWith("@sveltejs/adapter-")) sv.devDependency(name, "next");
|
|
6940
7262
|
}
|
|
7263
|
+
if (kitNext) {
|
|
7264
|
+
for (const name of ["tsconfig.json", "jsconfig.json"]) {
|
|
7265
|
+
if (!fileExists(cwd, name)) continue;
|
|
7266
|
+
sv.file(name, transforms.json(({ data }) => {
|
|
7267
|
+
data.extends = KIT3_TSCONFIG;
|
|
7268
|
+
data.include ??= [directory.src];
|
|
7269
|
+
for (const [key, value] of Object.entries(data.compilerOptions ?? {})) if (KIT3_TSCONFIG_DEFAULT[key] === value) delete data.compilerOptions[key];
|
|
7270
|
+
}));
|
|
7271
|
+
}
|
|
7272
|
+
sv.file("package.json", transforms.json(({ data }) => {
|
|
7273
|
+
data.imports = {
|
|
7274
|
+
...libSubpathImports(directory.lib),
|
|
7275
|
+
...data.imports
|
|
7276
|
+
};
|
|
7277
|
+
}));
|
|
7278
|
+
for (const relative of sourceFiles(cwd, directory.src)) sv.file(relative, (content) => content.includes("$lib") ? content.replaceAll("$lib", "#lib") : false);
|
|
7279
|
+
}
|
|
6941
7280
|
const config = {};
|
|
6942
7281
|
for (const [name, f] of Object.entries(FEATURES)) {
|
|
6943
7282
|
if (!options.features.includes(name)) continue;
|
|
@@ -6953,147 +7292,12 @@ var experimental_default = defineAddon({
|
|
|
6953
7292
|
}, ({ override }) => override(config));
|
|
6954
7293
|
}
|
|
6955
7294
|
});
|
|
6956
|
-
|
|
6957
|
-
|
|
6958
|
-
|
|
6959
|
-
|
|
6960
|
-
|
|
6961
|
-
|
|
6962
|
-
type: "multiselect",
|
|
6963
|
-
default: [],
|
|
6964
|
-
options: [
|
|
6965
|
-
{
|
|
6966
|
-
value: "claude-code",
|
|
6967
|
-
label: "claude code"
|
|
6968
|
-
},
|
|
6969
|
-
{
|
|
6970
|
-
value: "cursor",
|
|
6971
|
-
label: "Cursor"
|
|
6972
|
-
},
|
|
6973
|
-
{
|
|
6974
|
-
value: "gemini",
|
|
6975
|
-
label: "Gemini"
|
|
6976
|
-
},
|
|
6977
|
-
{
|
|
6978
|
-
value: "opencode",
|
|
6979
|
-
label: "opencode"
|
|
6980
|
-
},
|
|
6981
|
-
{
|
|
6982
|
-
value: "vscode",
|
|
6983
|
-
label: "VSCode"
|
|
6984
|
-
},
|
|
6985
|
-
{
|
|
6986
|
-
value: "other",
|
|
6987
|
-
label: "Other"
|
|
6988
|
-
}
|
|
6989
|
-
],
|
|
6990
|
-
required: true
|
|
6991
|
-
}).add("setup", {
|
|
6992
|
-
question: "What setup would you like to use?",
|
|
6993
|
-
type: "select",
|
|
6994
|
-
default: "remote",
|
|
6995
|
-
options: [{
|
|
6996
|
-
value: "local",
|
|
6997
|
-
label: "Local",
|
|
6998
|
-
hint: "will use stdio"
|
|
6999
|
-
}, {
|
|
7000
|
-
value: "remote",
|
|
7001
|
-
label: "Remote",
|
|
7002
|
-
hint: "will use a remote endpoint"
|
|
7003
|
-
}],
|
|
7004
|
-
required: true,
|
|
7005
|
-
condition: ({ ide }) => !(ide.length === 1 && ide.includes("opencode"))
|
|
7006
|
-
}).build(),
|
|
7007
|
-
run: ({ sv, options }) => {
|
|
7008
|
-
const getLocalConfig = (o) => {
|
|
7009
|
-
return {
|
|
7010
|
-
...o?.typeLocal ? { type: o.typeLocal } : {},
|
|
7011
|
-
command: o?.command ?? "npx",
|
|
7012
|
-
...o?.env ? { env: {} } : {},
|
|
7013
|
-
...o?.args === null ? {} : { args: o?.args ?? ["-y", "@sveltejs/mcp"] }
|
|
7014
|
-
};
|
|
7015
|
-
};
|
|
7016
|
-
const getRemoteConfig = (o) => {
|
|
7017
|
-
return {
|
|
7018
|
-
...o?.typeRemote ? { type: o.typeRemote } : {},
|
|
7019
|
-
url: "https://mcp.svelte.dev/mcp"
|
|
7020
|
-
};
|
|
7021
|
-
};
|
|
7022
|
-
const configurator = {
|
|
7023
|
-
"claude-code": {
|
|
7024
|
-
agentPath: "CLAUDE.md",
|
|
7025
|
-
configPath: ".mcp.json",
|
|
7026
|
-
mcpOptions: {
|
|
7027
|
-
typeLocal: "stdio",
|
|
7028
|
-
typeRemote: "http",
|
|
7029
|
-
env: true
|
|
7030
|
-
}
|
|
7031
|
-
},
|
|
7032
|
-
cursor: {
|
|
7033
|
-
agentPath: "AGENTS.md",
|
|
7034
|
-
configPath: ".cursor/mcp.json",
|
|
7035
|
-
mcpOptions: {}
|
|
7036
|
-
},
|
|
7037
|
-
gemini: {
|
|
7038
|
-
agentPath: "GEMINI.md",
|
|
7039
|
-
configPath: ".gemini/settings.json",
|
|
7040
|
-
schema: "https://raw.githubusercontent.com/google-gemini/gemini-cli/main/schemas/settings.schema.json",
|
|
7041
|
-
mcpOptions: {}
|
|
7042
|
-
},
|
|
7043
|
-
opencode: {
|
|
7044
|
-
agentPath: "AGENTS.md",
|
|
7045
|
-
configPath: ".opencode/opencode.json",
|
|
7046
|
-
schema: "https://opencode.ai/config.json",
|
|
7047
|
-
customData: { plugin: ["@sveltejs/opencode"] },
|
|
7048
|
-
extraFiles: [{
|
|
7049
|
-
path: ".opencode/svelte.json",
|
|
7050
|
-
data: { $schema: "https://svelte.dev/opencode/schema.json" }
|
|
7051
|
-
}]
|
|
7052
|
-
},
|
|
7053
|
-
vscode: {
|
|
7054
|
-
agentPath: "AGENTS.md",
|
|
7055
|
-
configPath: ".vscode/mcp.json",
|
|
7056
|
-
mcpOptions: { serversKey: "servers" }
|
|
7057
|
-
},
|
|
7058
|
-
other: { other: true }
|
|
7059
|
-
};
|
|
7060
|
-
const filesAdded = [];
|
|
7061
|
-
const filesExistingAlready = [];
|
|
7062
|
-
const agentFile = getSharedFiles().filter((file) => file.include.includes("mcp")).find((file) => file.name === "AGENTS.md");
|
|
7063
|
-
for (const ide of options.ide) {
|
|
7064
|
-
const value = configurator[ide];
|
|
7065
|
-
if (value === void 0) continue;
|
|
7066
|
-
if ("other" in value) continue;
|
|
7067
|
-
const { mcpOptions, agentPath, configPath, schema, customData, extraFiles } = value;
|
|
7068
|
-
if (!filesAdded.includes(agentPath)) sv.file(agentPath, (content) => {
|
|
7069
|
-
if (content) {
|
|
7070
|
-
filesExistingAlready.push(agentPath);
|
|
7071
|
-
return false;
|
|
7072
|
-
}
|
|
7073
|
-
filesAdded.push(agentPath);
|
|
7074
|
-
return agentFile?.contents ?? "";
|
|
7075
|
-
});
|
|
7076
|
-
sv.file(configPath, transforms.json(({ data }) => {
|
|
7077
|
-
if (schema) data["$schema"] = schema;
|
|
7078
|
-
if (customData) for (const [key, value] of Object.entries(customData)) data[key] = value;
|
|
7079
|
-
if (mcpOptions) {
|
|
7080
|
-
const key = mcpOptions.serversKey ?? "mcpServers";
|
|
7081
|
-
data[key] ??= {};
|
|
7082
|
-
data[key].svelte = options.setup === "local" ? getLocalConfig(mcpOptions) : getRemoteConfig(mcpOptions);
|
|
7083
|
-
}
|
|
7084
|
-
}));
|
|
7085
|
-
if (extraFiles) for (const extra of extraFiles) sv.file(extra.path, transforms.json(({ data }) => {
|
|
7086
|
-
for (const [key, value] of Object.entries(extra.data)) data[key] = value;
|
|
7087
|
-
}));
|
|
7088
|
-
}
|
|
7089
|
-
if (filesExistingAlready.length > 0) R$1.warn(`${filesExistingAlready.map((path) => color.path(path)).join(", ")} already exists, we didn't touch ${filesExistingAlready.length > 1 ? "them" : "it"}. See ${color.website("https://svelte.dev/docs/mcp/overview#Usage")} for manual setup.`);
|
|
7090
|
-
},
|
|
7091
|
-
nextSteps({ options }) {
|
|
7092
|
-
const steps = [];
|
|
7093
|
-
if (options.ide.includes("other")) steps.push(`For other clients: ${color.website(`https://svelte.dev/docs/mcp/${options.setup}-setup#Other-clients`)}`);
|
|
7094
|
-
return steps;
|
|
7095
|
-
}
|
|
7096
|
-
});
|
|
7295
|
+
/** Workspace-relative source files under `src`, for the `$lib` -> `#lib` rewrite. */
|
|
7296
|
+
function sourceFiles(cwd, src) {
|
|
7297
|
+
const root = path.resolve(cwd, src);
|
|
7298
|
+
if (!fs.existsSync(root)) return [];
|
|
7299
|
+
return fs.readdirSync(root, { recursive: true }).map((entry) => path.join(src, entry)).filter((relative) => SOURCE_EXTENSIONS.some((ext) => relative.endsWith(ext)) && fs.statSync(path.resolve(cwd, relative)).isFile());
|
|
7300
|
+
}
|
|
7097
7301
|
//#endregion
|
|
7098
7302
|
//#region src/addons/mdsvex.ts
|
|
7099
7303
|
var mdsvex_default = defineAddon({
|
|
@@ -7162,11 +7366,15 @@ var paraglide_default = defineAddon({
|
|
|
7162
7366
|
shortDescription: "i18n",
|
|
7163
7367
|
homepage: "https://inlang.com/m/gerre34r/library-inlang-paraglideJs",
|
|
7164
7368
|
options: options$3,
|
|
7165
|
-
setup: ({ isKit, unsupported }) => {
|
|
7369
|
+
setup: ({ isKit, unsupported, runsAfter }) => {
|
|
7166
7370
|
if (!isKit) unsupported("Requires SvelteKit");
|
|
7371
|
+
runsAfter("experimental");
|
|
7167
7372
|
},
|
|
7168
|
-
run: ({ sv, options, file, language, directory }) => {
|
|
7373
|
+
run: ({ sv, options, file, language, directory, dependencyVersion }) => {
|
|
7169
7374
|
const [ts] = createPrinter(language === "ts");
|
|
7375
|
+
const kitRange = dependencyVersion("@sveltejs/kit");
|
|
7376
|
+
const lib = resolveLibPrefix(kitRange);
|
|
7377
|
+
const pathType = isKit3(kitRange) ? "Path" : "Pathname";
|
|
7170
7378
|
const paraglideOutDir = `${directory.lib}/paraglide`;
|
|
7171
7379
|
sv.devDependency("@inlang/paraglide-js", "^2.18.2");
|
|
7172
7380
|
sv.file(file.viteConfig, transforms.script(({ ast, js }) => {
|
|
@@ -7183,7 +7391,7 @@ var paraglide_default = defineAddon({
|
|
|
7183
7391
|
}));
|
|
7184
7392
|
sv.file(`src/hooks.${language}`, transforms.script(({ ast, comments, js }) => {
|
|
7185
7393
|
js.imports.addNamed(ast, {
|
|
7186
|
-
from:
|
|
7394
|
+
from: `${lib}/paraglide/runtime`,
|
|
7187
7395
|
imports: ["deLocalizeUrl"]
|
|
7188
7396
|
});
|
|
7189
7397
|
const expression = js.common.parseExpression("(request) => deLocalizeUrl(request.url).pathname");
|
|
@@ -7206,11 +7414,11 @@ var paraglide_default = defineAddon({
|
|
|
7206
7414
|
}));
|
|
7207
7415
|
sv.file(`src/hooks.server.${language}`, transforms.script(({ ast, comments, js }) => {
|
|
7208
7416
|
js.imports.addNamed(ast, {
|
|
7209
|
-
from:
|
|
7417
|
+
from: `${lib}/paraglide/server`,
|
|
7210
7418
|
imports: ["paraglideMiddleware"]
|
|
7211
7419
|
});
|
|
7212
7420
|
js.imports.addNamed(ast, {
|
|
7213
|
-
from:
|
|
7421
|
+
from: `${lib}/paraglide/runtime`,
|
|
7214
7422
|
imports: ["getTextDirection"]
|
|
7215
7423
|
});
|
|
7216
7424
|
js.kit.addHooksHandle(ast, {
|
|
@@ -7250,7 +7458,7 @@ var paraglide_default = defineAddon({
|
|
|
7250
7458
|
sv.file(`${directory.kitRoutes}/+layout.svelte`, transforms.svelteScript({ language }, ({ ast, svelte, js }) => {
|
|
7251
7459
|
js.imports.addNamed(ast.instance.content, {
|
|
7252
7460
|
imports: ["locales", "localizeHref"],
|
|
7253
|
-
from:
|
|
7461
|
+
from: `${lib}/paraglide/runtime`
|
|
7254
7462
|
});
|
|
7255
7463
|
js.imports.addNamed(ast.instance.content, {
|
|
7256
7464
|
imports: ["page"],
|
|
@@ -7261,14 +7469,14 @@ var paraglide_default = defineAddon({
|
|
|
7261
7469
|
from: "$app/paths"
|
|
7262
7470
|
});
|
|
7263
7471
|
if (language === "ts") js.imports.addNamed(ast.instance.content, {
|
|
7264
|
-
imports: [
|
|
7472
|
+
imports: [pathType],
|
|
7265
7473
|
from: "$app/types",
|
|
7266
7474
|
isType: true
|
|
7267
7475
|
});
|
|
7268
7476
|
svelte.addFragment(ast, dedent`
|
|
7269
7477
|
<div style="display:none">
|
|
7270
7478
|
{#each locales as locale (locale)}
|
|
7271
|
-
<a href={resolve(localizeHref(page.url.pathname, { locale })${ts(
|
|
7479
|
+
<a href={resolve(localizeHref(page.url.pathname, { locale })${ts(` as ${pathType}`)})}>{locale}</a>
|
|
7272
7480
|
{/each}
|
|
7273
7481
|
</div>`, { language });
|
|
7274
7482
|
}));
|
|
@@ -7277,11 +7485,11 @@ var paraglide_default = defineAddon({
|
|
|
7277
7485
|
sv.file(`${directory.kitRoutes}/demo/paraglide/+page.svelte`, transforms.svelteScript({ language }, ({ ast, svelte, js }) => {
|
|
7278
7486
|
js.imports.addNamed(ast.instance.content, {
|
|
7279
7487
|
imports: { m: "m" },
|
|
7280
|
-
from:
|
|
7488
|
+
from: `${lib}/paraglide/messages.js`
|
|
7281
7489
|
});
|
|
7282
7490
|
js.imports.addNamed(ast.instance.content, {
|
|
7283
7491
|
imports: { setLocale: "setLocale" },
|
|
7284
|
-
from:
|
|
7492
|
+
from: `${lib}/paraglide/runtime`
|
|
7285
7493
|
});
|
|
7286
7494
|
let templateCode = "<h1>{m.hello_world({ name: 'SvelteKit User' })}</h1>";
|
|
7287
7495
|
const { validLanguageTags } = parseLanguageTagInput(options.languageTags);
|
|
@@ -7559,7 +7767,7 @@ var sveltekit_adapter_default = defineAddon({
|
|
|
7559
7767
|
});
|
|
7560
7768
|
if (adapter.package === "@sveltejs/adapter-cloudflare") {
|
|
7561
7769
|
sv.devDependency("wrangler", "^4.97.0");
|
|
7562
|
-
if (packageManager === "pnpm") sv.file(file.findUp("pnpm-workspace.yaml"), pnpm.allowBuilds("workerd"
|
|
7770
|
+
if (packageManager === "pnpm") sv.file(file.findUp("pnpm-workspace.yaml"), pnpm.allowBuilds("workerd"));
|
|
7563
7771
|
const ext = fileExists(cwd, "wrangler.toml") ? "toml" : "jsonc";
|
|
7564
7772
|
const applyWranglerConfig = (data) => {
|
|
7565
7773
|
if (ext === "jsonc") data.$schema ??= "./node_modules/wrangler/config-schema.json";
|
|
@@ -7635,11 +7843,10 @@ var tailwindcss_default = defineAddon({
|
|
|
7635
7843
|
default: [],
|
|
7636
7844
|
required: false
|
|
7637
7845
|
}).build(),
|
|
7638
|
-
run: ({ sv, options, file, isKit, directory, dependencyVersion, language
|
|
7846
|
+
run: ({ sv, options, file, isKit, directory, dependencyVersion, language }) => {
|
|
7639
7847
|
const prettierInstalled = Boolean(dependencyVersion("prettier"));
|
|
7640
7848
|
sv.devDependency("tailwindcss", "^4.3.0");
|
|
7641
7849
|
sv.devDependency("@tailwindcss/vite", "^4.3.0");
|
|
7642
|
-
if (packageManager === "pnpm") sv.file(file.findUp("pnpm-workspace.yaml"), pnpm.allowBuilds("@tailwindcss/oxide"));
|
|
7643
7850
|
if (prettierInstalled) sv.devDependency("prettier-plugin-tailwindcss", "^0.8.0");
|
|
7644
7851
|
for (const plugin of plugins) {
|
|
7645
7852
|
if (!options.plugins.includes(plugin.id)) continue;
|
|
@@ -7877,7 +8084,7 @@ const officialAddons$1 = {
|
|
|
7877
8084
|
mdsvex: mdsvex_default,
|
|
7878
8085
|
paraglide: paraglide_default,
|
|
7879
8086
|
storybook: storybook_default,
|
|
7880
|
-
|
|
8087
|
+
aiTools: ai_tools_default,
|
|
7881
8088
|
experimental: experimental_default
|
|
7882
8089
|
};
|
|
7883
8090
|
function getAddonDetails(id) {
|
|
@@ -10693,50 +10900,61 @@ async function formatFiles(options) {
|
|
|
10693
10900
|
const { start, stop } = vt();
|
|
10694
10901
|
start("Formatting modified files");
|
|
10695
10902
|
const args = [
|
|
10696
|
-
"prettier",
|
|
10697
10903
|
"--write",
|
|
10698
10904
|
"--ignore-unknown",
|
|
10699
10905
|
...options.filesToFormat
|
|
10700
10906
|
];
|
|
10701
|
-
|
|
10907
|
+
let result = await run("prettier", args, options.cwd);
|
|
10908
|
+
if (result.notFound) {
|
|
10909
|
+
const cmd = resolveCommand(options.packageManager, "execute-local", ["prettier", ...args]);
|
|
10910
|
+
result = await run(cmd.command, cmd.args, options.cwd);
|
|
10911
|
+
}
|
|
10912
|
+
if (result.error !== void 0) {
|
|
10913
|
+
stop("Failed to format files");
|
|
10914
|
+
R$1.error(result.error);
|
|
10915
|
+
return;
|
|
10916
|
+
}
|
|
10917
|
+
stop("Successfully formatted modified files");
|
|
10918
|
+
}
|
|
10919
|
+
async function run(command, args, cwd) {
|
|
10702
10920
|
try {
|
|
10703
|
-
|
|
10921
|
+
await z(command, args, {
|
|
10704
10922
|
nodeOptions: {
|
|
10705
|
-
cwd
|
|
10923
|
+
cwd,
|
|
10706
10924
|
stdio: "pipe"
|
|
10707
10925
|
},
|
|
10708
10926
|
throwOnError: true
|
|
10709
10927
|
});
|
|
10710
|
-
|
|
10711
|
-
stop("Failed to format files");
|
|
10712
|
-
R$1.error(result.stderr);
|
|
10713
|
-
return;
|
|
10714
|
-
}
|
|
10928
|
+
return {};
|
|
10715
10929
|
} catch (e) {
|
|
10716
|
-
|
|
10717
|
-
|
|
10718
|
-
|
|
10930
|
+
if (e?.code === "ENOENT") return {
|
|
10931
|
+
notFound: true,
|
|
10932
|
+
error: `${command} not found`
|
|
10933
|
+
};
|
|
10934
|
+
const output = e?.output;
|
|
10935
|
+
return { error: [output?.stderr, output?.stdout].filter(Boolean).join("\n").trim() || (e instanceof Error ? e.message : "unknown error") };
|
|
10719
10936
|
}
|
|
10720
|
-
stop("Successfully formatted modified files");
|
|
10721
10937
|
}
|
|
10722
10938
|
//#endregion
|
|
10723
10939
|
//#region src/core/package-manager.ts
|
|
10724
10940
|
const AGENT_NAMES = AGENTS.filter((agent) => !agent.includes("@"));
|
|
10725
|
-
const agentOptions = AGENT_NAMES.map((pm) => ({
|
|
10726
|
-
value: pm,
|
|
10727
|
-
label: pm
|
|
10728
|
-
}));
|
|
10729
|
-
agentOptions.unshift({
|
|
10730
|
-
label: "None",
|
|
10731
|
-
value: void 0
|
|
10732
|
-
});
|
|
10733
10941
|
const installOption = new Option("--install <package-manager>", "installs dependencies with a specified package manager").choices(AGENT_NAMES);
|
|
10734
10942
|
async function packageManagerPrompt(cwd) {
|
|
10735
10943
|
const agent = (await detect({ cwd }))?.name ?? getUserAgent();
|
|
10736
10944
|
if (!V.stdout.isTTY) return agent;
|
|
10737
10945
|
const pm = await Ee({
|
|
10738
10946
|
message: "Which package manager do you want to install dependencies with?",
|
|
10739
|
-
options:
|
|
10947
|
+
options: [{
|
|
10948
|
+
label: "None",
|
|
10949
|
+
value: void 0
|
|
10950
|
+
}, ...AGENT_NAMES.map((agent) => {
|
|
10951
|
+
const installed = isInstalled(agent);
|
|
10952
|
+
return {
|
|
10953
|
+
value: agent,
|
|
10954
|
+
label: installed ? agent : color.dim(`${agent} (not installed)`),
|
|
10955
|
+
installed
|
|
10956
|
+
};
|
|
10957
|
+
}).sort((a, b) => Number(b.installed) - Number(a.installed))],
|
|
10740
10958
|
initialValue: agent
|
|
10741
10959
|
});
|
|
10742
10960
|
if (R$2(pm)) {
|
|
@@ -10745,7 +10963,12 @@ async function packageManagerPrompt(cwd) {
|
|
|
10745
10963
|
}
|
|
10746
10964
|
return pm;
|
|
10747
10965
|
}
|
|
10966
|
+
/** Returns `false` when the package manager isn't installed and the install was skipped. */
|
|
10748
10967
|
async function installDependencies(agent, cwd) {
|
|
10968
|
+
if (!isInstalled(agent)) {
|
|
10969
|
+
R$1.warn(`${color.command(agent)} is not installed, skipping dependency installation.`);
|
|
10970
|
+
return false;
|
|
10971
|
+
}
|
|
10749
10972
|
const task = Pe({
|
|
10750
10973
|
title: `Installing dependencies with ${color.command(agent)}...`,
|
|
10751
10974
|
limit: Math.ceil(V.stdout.rows / 2),
|
|
@@ -10769,12 +10992,12 @@ async function installDependencies(agent, cwd) {
|
|
|
10769
10992
|
} catch {}
|
|
10770
10993
|
if ((proc.exitCode ?? 0) === 0) {
|
|
10771
10994
|
task.success(`Successfully installed dependencies with ${color.command(agent)}`);
|
|
10772
|
-
return;
|
|
10995
|
+
return true;
|
|
10773
10996
|
}
|
|
10774
10997
|
if (agent === "pnpm" && output.join("\n").includes("ERR_PNPM_IGNORED_BUILDS")) {
|
|
10775
10998
|
task.success(`Installed dependencies with ${color.command(agent)}`);
|
|
10776
10999
|
R$1.warn(`Some build scripts were skipped. Run ${color.command(`${agent} approve-builds`)} to approve them.`);
|
|
10777
|
-
return;
|
|
11000
|
+
return true;
|
|
10778
11001
|
}
|
|
10779
11002
|
task.error("Failed to install dependencies");
|
|
10780
11003
|
ge("Operation failed.");
|
|
@@ -10791,6 +11014,20 @@ function getUserAgent() {
|
|
|
10791
11014
|
const name = pmSpec.substring(0, separatorPos);
|
|
10792
11015
|
return AGENTS.includes(name) ? name : void 0;
|
|
10793
11016
|
}
|
|
11017
|
+
const installedCache = /* @__PURE__ */ new Map();
|
|
11018
|
+
function isInstalled(agent) {
|
|
11019
|
+
let installed = installedCache.get(agent);
|
|
11020
|
+
if (installed === void 0) {
|
|
11021
|
+
try {
|
|
11022
|
+
B(agent, ["--version"], { nodeOptions: { stdio: "ignore" } });
|
|
11023
|
+
installed = true;
|
|
11024
|
+
} catch {
|
|
11025
|
+
installed = false;
|
|
11026
|
+
}
|
|
11027
|
+
installedCache.set(agent, installed);
|
|
11028
|
+
}
|
|
11029
|
+
return installed;
|
|
11030
|
+
}
|
|
10794
11031
|
function addPnpmAllowBuilds(cwd, packageManager, ...packages) {
|
|
10795
11032
|
if (packageManager !== "pnpm" || packages.length === 0) return;
|
|
10796
11033
|
const found = up$1("pnpm-workspace.yaml", { cwd });
|
|
@@ -11225,7 +11462,7 @@ const create = new Command("create").description("Scaffold a new project (--add
|
|
|
11225
11462
|
V.exit(1);
|
|
11226
11463
|
}
|
|
11227
11464
|
runCommand(async () => {
|
|
11228
|
-
const { directory, addOnNextSteps, packageManager } = await createProject(cwd, options);
|
|
11465
|
+
const { directory, addOnNextSteps, packageManager, depsInstalled } = await createProject(cwd, options);
|
|
11229
11466
|
let i = 1;
|
|
11230
11467
|
const initialSteps = ["📁 Project steps", ""];
|
|
11231
11468
|
const relative = path.relative(V.cwd(), directory);
|
|
@@ -11234,7 +11471,8 @@ const create = new Command("create").description("Scaffold a new project (--add
|
|
|
11234
11471
|
const pathHasSpaces = relative.includes(" ");
|
|
11235
11472
|
initialSteps.push(` ${i++}: ${color.command(`cd ${pathHasSpaces ? `"${relative}"` : relative}`)}`);
|
|
11236
11473
|
}
|
|
11237
|
-
if (!
|
|
11474
|
+
if (packageManager && !depsInstalled) initialSteps.push(` ${i++}: Install ${color.command(pm)}`);
|
|
11475
|
+
if (!packageManager || !depsInstalled) initialSteps.push(` ${i++}: ${color.command(resolveCommandArray(pm, "install", []))}`);
|
|
11238
11476
|
const steps = [
|
|
11239
11477
|
...initialSteps,
|
|
11240
11478
|
` ${i++}: ${color.command(resolveCommandArray(pm, "run", ["dev", "--open"]))}`,
|
|
@@ -11410,18 +11648,20 @@ async function createProject(cwd, options) {
|
|
|
11410
11648
|
updateAgent(directory, language, packageManager ?? "npm", loadedAddons);
|
|
11411
11649
|
const addOnNextSteps = getNextSteps(addOnSuccessfulAddons, workspace, answers, addonSetupResults);
|
|
11412
11650
|
addPnpmAllowBuilds(projectPath, packageManager, "esbuild");
|
|
11651
|
+
let depsInstalled = false;
|
|
11413
11652
|
if (packageManager) {
|
|
11414
|
-
await installDependencies(packageManager, projectPath);
|
|
11415
|
-
await formatFiles({
|
|
11653
|
+
depsInstalled = await installDependencies(packageManager, projectPath);
|
|
11654
|
+
if (depsInstalled) await formatFiles({
|
|
11416
11655
|
packageManager,
|
|
11417
11656
|
cwd: projectPath,
|
|
11418
|
-
filesToFormat: addOnFilesToFormat
|
|
11657
|
+
filesToFormat: addOnSuccessfulAddons.some((addon) => addon.addon.id === "prettier") ? ["."] : addOnFilesToFormat
|
|
11419
11658
|
});
|
|
11420
11659
|
}
|
|
11421
11660
|
return {
|
|
11422
11661
|
directory: projectPath,
|
|
11423
11662
|
addOnNextSteps,
|
|
11424
|
-
packageManager
|
|
11663
|
+
packageManager,
|
|
11664
|
+
depsInstalled
|
|
11425
11665
|
};
|
|
11426
11666
|
}
|
|
11427
11667
|
async function createProjectFromPlayground(url, cwd) {
|
|
@@ -11713,9 +11953,9 @@ async function promptAddonQuestions({ options, loadedAddons, workspace }) {
|
|
|
11713
11953
|
}
|
|
11714
11954
|
for (const loaded of addons) answers[loaded.addon.id] ??= {};
|
|
11715
11955
|
let setupResults = {};
|
|
11716
|
-
if (addons.length > 0) setupResults = setupAddons(addons, workspace);
|
|
11956
|
+
if (addons.length > 0) setupResults = await setupAddons(addons, workspace);
|
|
11717
11957
|
if (addons.length === 0) {
|
|
11718
|
-
const results = setupAddons(officialAddons.map((a) => createLoadedAddon(a)), workspace);
|
|
11958
|
+
const results = await setupAddons(officialAddons.map((a) => createLoadedAddon(a)), workspace);
|
|
11719
11959
|
const addonOptions = officialAddons.filter(({ id, hidden }) => results[id].unsupported.length === 0 && !hidden).map(({ id, homepage, shortDescription }) => ({
|
|
11720
11960
|
label: id,
|
|
11721
11961
|
value: id,
|
|
@@ -11735,11 +11975,11 @@ async function promptAddonQuestions({ options, loadedAddons, workspace }) {
|
|
|
11735
11975
|
addons.push(createLoadedAddon(addon));
|
|
11736
11976
|
answers[id] = {};
|
|
11737
11977
|
}
|
|
11738
|
-
setupResults = setupAddons(addons, workspace);
|
|
11978
|
+
setupResults = await setupAddons(addons, workspace);
|
|
11739
11979
|
}
|
|
11740
11980
|
const missingSetupResults = addons.filter((a) => !setupResults[a.addon.id]);
|
|
11741
11981
|
if (missingSetupResults.length > 0) {
|
|
11742
|
-
const additionalSetupResults = setupAddons(missingSetupResults, workspace);
|
|
11982
|
+
const additionalSetupResults = await setupAddons(missingSetupResults, workspace);
|
|
11743
11983
|
Object.assign(setupResults, additionalSetupResults);
|
|
11744
11984
|
}
|
|
11745
11985
|
const dependencyChains = /* @__PURE__ */ new Map();
|
|
@@ -11779,7 +12019,7 @@ async function promptAddonQuestions({ options, loadedAddons, workspace }) {
|
|
|
11779
12019
|
}
|
|
11780
12020
|
const newlyAddedAddons = addons.filter((a) => !setupResults[a.addon.id]);
|
|
11781
12021
|
if (newlyAddedAddons.length > 0) {
|
|
11782
|
-
const newSetupResults = setupAddons(newlyAddedAddons, workspace);
|
|
12022
|
+
const newSetupResults = await setupAddons(newlyAddedAddons, workspace);
|
|
11783
12023
|
Object.assign(setupResults, newSetupResults);
|
|
11784
12024
|
}
|
|
11785
12025
|
}
|
|
@@ -11851,7 +12091,7 @@ async function promptAddonQuestions({ options, loadedAddons, workspace }) {
|
|
|
11851
12091
|
};
|
|
11852
12092
|
}
|
|
11853
12093
|
async function runAddonsApply({ answers, options, loadedAddons, setupResults, workspace, fromCommand }) {
|
|
11854
|
-
if (!setupResults) setupResults = setupAddons(loadedAddons.length ? loadedAddons : officialAddons.map((a) => createLoadedAddon(a)), workspace);
|
|
12094
|
+
if (!setupResults) setupResults = await setupAddons(loadedAddons.length ? loadedAddons : officialAddons.map((a) => createLoadedAddon(a)), workspace);
|
|
11855
12095
|
if (loadedAddons.length === 0) return {
|
|
11856
12096
|
nextSteps: [],
|
|
11857
12097
|
argsFormattedAddons: [],
|
|
@@ -11910,17 +12150,20 @@ async function runAddonsApply({ answers, options, loadedAddons, setupResults, wo
|
|
|
11910
12150
|
if (!options.gitCheck) argsFormattedAddons.push("--no-git-check");
|
|
11911
12151
|
buildAndLogArgs(packageManager, "add", argsFormattedAddons);
|
|
11912
12152
|
}
|
|
12153
|
+
let depsInstalled = true;
|
|
11913
12154
|
if (packageManager) {
|
|
11914
12155
|
workspace.packageManager = packageManager;
|
|
11915
|
-
await installDependencies(packageManager, options.cwd);
|
|
11916
|
-
await formatFiles({
|
|
12156
|
+
depsInstalled = await installDependencies(packageManager, options.cwd);
|
|
12157
|
+
if (depsInstalled) await formatFiles({
|
|
11917
12158
|
packageManager,
|
|
11918
12159
|
cwd: options.cwd,
|
|
11919
12160
|
filesToFormat
|
|
11920
12161
|
});
|
|
11921
12162
|
}
|
|
12163
|
+
const nextSteps = getNextSteps(successfulAddons, workspace, answers, setupResults);
|
|
12164
|
+
if (packageManager && !depsInstalled) nextSteps.unshift(`Install ${color.command(packageManager)}, then run ${color.command(resolveCommandArray(packageManager, "install", []))}`);
|
|
11922
12165
|
return {
|
|
11923
|
-
nextSteps
|
|
12166
|
+
nextSteps,
|
|
11924
12167
|
argsFormattedAddons,
|
|
11925
12168
|
filesToFormat,
|
|
11926
12169
|
successfulAddons,
|
|
@@ -12133,7 +12376,7 @@ async function add({ addons, cwd, options, packageManager = "npm" }) {
|
|
|
12133
12376
|
loadedAddons,
|
|
12134
12377
|
workspace,
|
|
12135
12378
|
options,
|
|
12136
|
-
setupResults: setupAddons(loadedAddons, workspace)
|
|
12379
|
+
setupResults: await setupAddons(loadedAddons, workspace)
|
|
12137
12380
|
});
|
|
12138
12381
|
}
|
|
12139
12382
|
async function applyAddons({ loadedAddons, workspace, setupResults, options }) {
|
|
@@ -12176,29 +12419,35 @@ async function applyAddons({ loadedAddons, workspace, setupResults, options }) {
|
|
|
12176
12419
|
};
|
|
12177
12420
|
}
|
|
12178
12421
|
/** Setup addons - takes LoadedAddon[] and returns setup results */
|
|
12179
|
-
function setupAddons(loadedAddons, workspace) {
|
|
12422
|
+
async function setupAddons(loadedAddons, workspace) {
|
|
12180
12423
|
const setupResults = {};
|
|
12181
12424
|
for (const loaded of loadedAddons) {
|
|
12182
12425
|
const addon = loaded.addon;
|
|
12426
|
+
const additionalOptions = {};
|
|
12183
12427
|
const setupResult = {
|
|
12184
12428
|
unsupported: [],
|
|
12185
12429
|
dependsOn: [],
|
|
12186
|
-
runsAfter: []
|
|
12430
|
+
runsAfter: [],
|
|
12431
|
+
additionalOptions
|
|
12187
12432
|
};
|
|
12188
12433
|
try {
|
|
12189
|
-
addon.setup?.({
|
|
12434
|
+
await addon.setup?.({
|
|
12190
12435
|
...workspace,
|
|
12191
12436
|
dependsOn: (name) => {
|
|
12192
12437
|
setupResult.dependsOn.push(name);
|
|
12193
12438
|
setupResult.runsAfter.push(name);
|
|
12194
12439
|
},
|
|
12195
12440
|
unsupported: (reason) => setupResult.unsupported.push(reason),
|
|
12196
|
-
runsAfter: (name) => setupResult.runsAfter.push(name)
|
|
12441
|
+
runsAfter: (name) => setupResult.runsAfter.push(name),
|
|
12442
|
+
addOption: (key, question) => {
|
|
12443
|
+
additionalOptions[key] = question;
|
|
12444
|
+
}
|
|
12197
12445
|
});
|
|
12198
12446
|
} catch (err) {
|
|
12199
12447
|
const msg = err instanceof Error ? err.message : String(err);
|
|
12200
12448
|
throw new Error(`Add-on '${addon.id}' failed during setup: ${msg}\n\n${getErrorHint(loaded.reference.source)}`, { cause: err });
|
|
12201
12449
|
}
|
|
12450
|
+
if (Object.keys(additionalOptions).length > 0) Object.assign(addon.options, additionalOptions);
|
|
12202
12451
|
setupResults[addon.id] = setupResult;
|
|
12203
12452
|
}
|
|
12204
12453
|
return setupResults;
|
|
@@ -12285,10 +12534,30 @@ async function runAddon({ addon, loaded, multiple, workspace, workspaceOptions }
|
|
|
12285
12534
|
cancels
|
|
12286
12535
|
};
|
|
12287
12536
|
}
|
|
12537
|
+
/**
|
|
12538
|
+
* Orders add-ons so every `runsAfter` is honoured, keeping the original order between add-ons that
|
|
12539
|
+
* don't constrain each other. Cycles and unknown ids are ignored rather than fatal - an add-on that
|
|
12540
|
+
* can't be placed simply keeps its position.
|
|
12541
|
+
*/
|
|
12288
12542
|
function orderAddons(addons, setupResults) {
|
|
12289
|
-
|
|
12290
|
-
|
|
12291
|
-
|
|
12543
|
+
const byId = new Map(addons.map((addon) => [addon.id, addon]));
|
|
12544
|
+
const ordered = [];
|
|
12545
|
+
const placed = /* @__PURE__ */ new Set();
|
|
12546
|
+
const visiting = /* @__PURE__ */ new Set();
|
|
12547
|
+
const place = (addon) => {
|
|
12548
|
+
if (placed.has(addon.id) || visiting.has(addon.id)) return;
|
|
12549
|
+
visiting.add(addon.id);
|
|
12550
|
+
for (const id of setupResults[addon.id]?.runsAfter ?? []) {
|
|
12551
|
+
const dependency = byId.get(id);
|
|
12552
|
+
if (dependency) place(dependency);
|
|
12553
|
+
}
|
|
12554
|
+
visiting.delete(addon.id);
|
|
12555
|
+
placed.add(addon.id);
|
|
12556
|
+
ordered.push(addon);
|
|
12557
|
+
};
|
|
12558
|
+
const seeded = [...addons].sort((a, b) => (setupResults[a.id]?.runsAfter?.length ?? 0) - (setupResults[b.id]?.runsAfter?.length ?? 0));
|
|
12559
|
+
for (const addon of seeded) place(addon);
|
|
12560
|
+
return ordered;
|
|
12292
12561
|
}
|
|
12293
12562
|
//#endregion
|
|
12294
12563
|
export { __toESM as S, name as _, detectPackageManager as a, __commonJSMin as b, defineAddonOptions as c, Command as d, R as f, helpConfig as g, forwardExitCode as h, addPnpmAllowBuilds as i, from as l, create$1 as m, add$1 as n, officialAddons$1 as o, z as p, create as r, defineAddon as s, add as t, program as u, version as v, __require as x, svDeprecated as y };
|