sv 1.0.0-next.7 → 1.0.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/{addons-DWX20ipF.mjs → addons-So36TZLY.mjs} +299 -230
- package/dist/bin.d.mts +1 -1
- package/dist/bin.mjs +145 -95
- package/dist/{engine-BKdrqoIo.d.mts → engine-D2x5kvrf.d.mts} +146 -135
- package/dist/{engine-w0Kq5hjN.mjs → engine-Do1htOYy.mjs} +131 -91
- package/dist/shared.json +2 -2
- package/dist/src/index.d.mts +3 -7
- package/dist/src/index.mjs +2 -2
- package/dist/src/testing.d.mts +26 -37
- package/dist/src/testing.mjs +48 -34
- package/dist/templates/addon/package.json +3 -3
- package/dist/templates/demo/files.types=checkjs.json +1 -1
- package/dist/templates/demo/files.types=none.json +1 -1
- package/dist/templates/demo/files.types=typescript.json +1 -1
- package/dist/templates/demo/package.json +3 -3
- package/dist/templates/library/package.json +3 -3
- package/dist/templates/minimal/package.json +3 -3
- package/package.json +14 -3
- package/dist/templates/demo/assets/src/lib/images/svelte-welcome.webp +0 -0
package/dist/bin.d.mts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export {
|
|
1
|
+
export {}
|
package/dist/bin.mjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { $ as pipe, A as filePaths, B as updateAgent, C as templates, D as buildAndLogArgs, E as PackageJSONSchema, F as isNodeError, G as version, H as updateReadme, I as normalizePosix, J as literal, K as array, L as parseAddonOptions, M as getHelpSections, N as getPadding, O as cliOptions, P as helpConfig, Q as picklist, R as runAndValidateVerifications, S as create$1, T as getSharedFiles, U as UnsupportedError, V as updateLibraryBuild, W as name, X as optional, Y as nonEmpty, Z as parse$1, _t as we, a as setupAddons, at as union, b as exec, c as AGENT_NAMES, ct as Option, d as installDependencies, dt as R, et as record, f as installOption, ft as Re, g as createLoadedAddon, gt as vt, h as from, ht as pe, i as prepareSvApi, it as transform, j as forwardExitCode, k as errorAndExit, l as
|
|
3
|
-
import { n as officialAddons$1, t as getAddonDetails } from "./addons-
|
|
2
|
+
import { $ as pipe, A as filePaths, B as updateAgent, C as templates, D as buildAndLogArgs, E as PackageJSONSchema, F as isNodeError, G as version, H as updateReadme, I as normalizePosix, J as literal, K as array, L as parseAddonOptions, M as getHelpSections, N as getPadding, O as cliOptions, P as helpConfig, Q as picklist, R as runAndValidateVerifications, S as create$1, T as getSharedFiles, U as UnsupportedError, V as updateLibraryBuild, W as name, X as optional, Y as nonEmpty, Z as parse$1, _t as we, a as setupAddons, at as union, b as exec, c as AGENT_NAMES, ct as Option, d as installDependencies, dt as R, et as record, f as installOption, ft as Re, g as createLoadedAddon, gt as vt, h as from, ht as pe, i as prepareSvApi, it as transform, j as forwardExitCode, k as errorAndExit, l as addAllowBuildsIfPnpm, lt as Ce, m as up$1, mt as le, n as applyAddons, nt as strictObject, o as createWorkspace, ot as program, p as packageManagerPrompt, pt as ge, q as boolean, r as orderAddons, rt as string, s as findWorkspaceRoot, st as Command, tt as safeParse, u as detectPackageManager, ut as Ee, vt as R$1, w as dist, x as execSync, y as getErrorHint, z as runCommand } from "./engine-Do1htOYy.mjs";
|
|
3
|
+
import { n as officialAddons$1, t as getAddonDetails } from "./addons-So36TZLY.mjs";
|
|
4
4
|
import * as fs$1 from "node:fs";
|
|
5
5
|
import fs from "node:fs";
|
|
6
6
|
import * as path$1 from "node:path";
|
|
@@ -110,7 +110,7 @@ function createChunkQueue() {
|
|
|
110
110
|
totalAvailable -= count;
|
|
111
111
|
if (totalAvailable === 0 && chunks.length > INITIAL_CAPACITY) {
|
|
112
112
|
chunks = new Array(INITIAL_CAPACITY);
|
|
113
|
-
capacityMask =
|
|
113
|
+
capacityMask = 255;
|
|
114
114
|
head = 0;
|
|
115
115
|
tail = 0;
|
|
116
116
|
}
|
|
@@ -299,7 +299,7 @@ function getMetaParser(type) {
|
|
|
299
299
|
}
|
|
300
300
|
const STATE_HEADER = 0;
|
|
301
301
|
const STATE_BODY = 1;
|
|
302
|
-
const MAX_META_SIZE =
|
|
302
|
+
const MAX_META_SIZE = 8388608;
|
|
303
303
|
const truncateErr = /* @__PURE__ */ new Error("Tar archive is truncated.");
|
|
304
304
|
function createUnpacker(options = {}) {
|
|
305
305
|
const strict = options.strict ?? false;
|
|
@@ -337,7 +337,7 @@ function createUnpacker(options = {}) {
|
|
|
337
337
|
}
|
|
338
338
|
const headerBlock = peek(512);
|
|
339
339
|
if (isZeroBlock(headerBlock)) {
|
|
340
|
-
if (available() <
|
|
340
|
+
if (available() < 1024) {
|
|
341
341
|
if (ended) {
|
|
342
342
|
if (strict) throw truncateErr;
|
|
343
343
|
done = true;
|
|
@@ -345,8 +345,8 @@ function createUnpacker(options = {}) {
|
|
|
345
345
|
}
|
|
346
346
|
return null;
|
|
347
347
|
}
|
|
348
|
-
if (isZeroBlock(peek(
|
|
349
|
-
discard(
|
|
348
|
+
if (isZeroBlock(peek(1024).subarray(512))) {
|
|
349
|
+
discard(1024);
|
|
350
350
|
done = true;
|
|
351
351
|
eof = true;
|
|
352
352
|
return;
|
|
@@ -514,7 +514,7 @@ const createOperationQueue = (concurrency) => {
|
|
|
514
514
|
}
|
|
515
515
|
};
|
|
516
516
|
};
|
|
517
|
-
const BATCH_BYTES =
|
|
517
|
+
const BATCH_BYTES = 262144;
|
|
518
518
|
const CREATE_FLAGS = fs$1.constants.O_WRONLY | fs$1.constants.O_CREAT | fs$1.constants.O_TRUNC | (fs$1.constants.O_NOFOLLOW ?? 0) | fs$1.constants.O_EXCL;
|
|
519
519
|
const STATE_OPENING = 1;
|
|
520
520
|
const STATE_OPEN = 2;
|
|
@@ -1063,7 +1063,10 @@ function unpackTar(directoryPath, options = {}) {
|
|
|
1063
1063
|
}
|
|
1064
1064
|
//#endregion
|
|
1065
1065
|
//#region src/core/fetch-packages.ts
|
|
1066
|
-
const
|
|
1066
|
+
const packageJsonPath = up({ cwd: import.meta.dirname });
|
|
1067
|
+
if (!packageJsonPath) throw new Error("Could not locate the `package.json` of `sv`");
|
|
1068
|
+
/** path to the `node_modules` directory of `sv` */
|
|
1069
|
+
const NODE_MODULES = path.join(path.dirname(packageJsonPath), "node_modules");
|
|
1067
1070
|
function parsePackageJSON(value, specifier) {
|
|
1068
1071
|
const result = safeParse(PackageJSONSchema, value);
|
|
1069
1072
|
if (!result.success) throw new Error(`Invalid add-on package specified: '${specifier}' has invalid package metadata`);
|
|
@@ -1098,9 +1101,12 @@ function copyDirectorySync(src, dest) {
|
|
|
1098
1101
|
*/
|
|
1099
1102
|
async function downloadPackage(options) {
|
|
1100
1103
|
const { pkg } = options;
|
|
1104
|
+
const dest = path.join(NODE_MODULES, pkg.name.split("/").join(path.sep));
|
|
1105
|
+
fs.rmSync(dest, {
|
|
1106
|
+
recursive: true,
|
|
1107
|
+
force: true
|
|
1108
|
+
});
|
|
1101
1109
|
if (options.path) {
|
|
1102
|
-
const dest = path.join(NODE_MODULES, pkg.name.split("/").join(path.sep));
|
|
1103
|
-
if (fs.existsSync(dest)) fs.rmSync(dest, { recursive: true });
|
|
1104
1110
|
const dir = path.dirname(dest);
|
|
1105
1111
|
if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });
|
|
1106
1112
|
try {
|
|
@@ -1109,13 +1115,13 @@ async function downloadPackage(options) {
|
|
|
1109
1115
|
if (platform() === "win32" && isNodeError(error) && (error.code === "EPERM" || error.code === "EACCES")) copyDirectorySync(options.path, dest);
|
|
1110
1116
|
else throw error;
|
|
1111
1117
|
}
|
|
1112
|
-
|
|
1118
|
+
} else {
|
|
1119
|
+
const tarballUrl = pkg.dist?.tarball;
|
|
1120
|
+
if (!tarballUrl) throw new Error(`Invalid add-on package: '${pkg.name}' is missing 'dist.tarball'`);
|
|
1121
|
+
const data = await fetch(tarballUrl);
|
|
1122
|
+
if (!data.body) throw new Error(`Unexpected response: '${tarballUrl}' responded with no body`);
|
|
1123
|
+
await pipeline(data.body, createGunzip(), unpackTar(dest, { strip: 1 }));
|
|
1113
1124
|
}
|
|
1114
|
-
const tarballUrl = pkg.dist?.tarball;
|
|
1115
|
-
if (!tarballUrl) throw new Error(`Invalid add-on package: '${pkg.name}' is missing 'dist.tarball'`);
|
|
1116
|
-
const data = await fetch(tarballUrl);
|
|
1117
|
-
if (!data.body) throw new Error(`Unexpected response: '${tarballUrl}' responded with no body`);
|
|
1118
|
-
await pipeline(data.body, createGunzip(), unpackTar(path.join(NODE_MODULES, pkg.name), { strip: 1 }));
|
|
1119
1125
|
return await importAddonCode(pkg.name, pkg.version, pkg.exports);
|
|
1120
1126
|
}
|
|
1121
1127
|
async function importAddonCode(pkgName, pkgVersion, exports) {
|
|
@@ -1244,14 +1250,20 @@ async function withSpinner(startMsg, task) {
|
|
|
1244
1250
|
async function run(command, args, cwd) {
|
|
1245
1251
|
try {
|
|
1246
1252
|
await exec(command, args, {
|
|
1247
|
-
nodeOptions: {
|
|
1253
|
+
nodeOptions: {
|
|
1254
|
+
cwd,
|
|
1255
|
+
stdio: "pipe"
|
|
1256
|
+
},
|
|
1248
1257
|
throwOnError: true
|
|
1249
1258
|
});
|
|
1250
1259
|
return {};
|
|
1251
1260
|
} catch (e) {
|
|
1252
|
-
if (
|
|
1253
|
-
|
|
1254
|
-
|
|
1261
|
+
if (e?.code === "ENOENT") return {
|
|
1262
|
+
notFound: true,
|
|
1263
|
+
error: `${command} not found`
|
|
1264
|
+
};
|
|
1265
|
+
const output = e?.output;
|
|
1266
|
+
return { error: [output?.stderr, output?.stdout].filter(Boolean).join("\n").trim() || (e instanceof Error ? e.message : "unknown error") };
|
|
1255
1267
|
}
|
|
1256
1268
|
}
|
|
1257
1269
|
//#endregion
|
|
@@ -1502,7 +1514,8 @@ async function resolveNonOfficialAddons(refs, downloadCheck) {
|
|
|
1502
1514
|
stop("Downloaded community add-on packages");
|
|
1503
1515
|
} catch (err) {
|
|
1504
1516
|
stop("Failed to download community add-on packages");
|
|
1505
|
-
|
|
1517
|
+
const msg = err instanceof Error ? err.message : "Unknown error";
|
|
1518
|
+
errorAndExit(msg);
|
|
1506
1519
|
}
|
|
1507
1520
|
return selectedAddons;
|
|
1508
1521
|
}
|
|
@@ -1557,9 +1570,10 @@ async function promptAddonQuestions({ options, loadedAddons, workspace }) {
|
|
|
1557
1570
|
}
|
|
1558
1571
|
if (question.type === "boolean") answers[addonId][questionId] = optionValue === "yes";
|
|
1559
1572
|
else if (question.type === "number") answers[addonId][questionId] = Number(optionValue);
|
|
1560
|
-
else if (question.type === "multiselect")
|
|
1561
|
-
|
|
1562
|
-
|
|
1573
|
+
else if (question.type === "multiselect") {
|
|
1574
|
+
if (optionValue === "none" || optionValue === "") answers[addonId][questionId] = [];
|
|
1575
|
+
else answers[addonId][questionId] = optionValue.split(",").map((v) => v.trim());
|
|
1576
|
+
} else answers[addonId][questionId] = optionValue;
|
|
1563
1577
|
}
|
|
1564
1578
|
for (const [id, question] of Object.entries(details.options)) if (question.condition?.(answers[addonId]) === false) {
|
|
1565
1579
|
if (answers[addonId][id] !== void 0) throw new Error(`Incompatible '${addonId}' option specified: '${answers[addonId][id]}'`);
|
|
@@ -1570,7 +1584,8 @@ async function promptAddonQuestions({ options, loadedAddons, workspace }) {
|
|
|
1570
1584
|
let setupResults = {};
|
|
1571
1585
|
if (addons.length > 0) setupResults = await setupAddons(addons, workspace);
|
|
1572
1586
|
if (addons.length === 0) {
|
|
1573
|
-
const
|
|
1587
|
+
const officialLoaded = officialAddons.map((a) => createLoadedAddon(a));
|
|
1588
|
+
const results = await setupAddons(officialLoaded, workspace);
|
|
1574
1589
|
const addonOptions = officialAddons.filter(({ id, hidden }) => results[id].unsupported.length === 0 && !hidden).map(({ id, homepage, shortDescription }) => ({
|
|
1575
1590
|
label: id,
|
|
1576
1591
|
value: id,
|
|
@@ -1609,11 +1624,14 @@ async function promptAddonQuestions({ options, loadedAddons, workspace }) {
|
|
|
1609
1624
|
const missingDependencies = setupResult.dependsOn.filter((depId) => !addons.some((a) => a.addon.id === depId));
|
|
1610
1625
|
for (const depId of missingDependencies) {
|
|
1611
1626
|
const addonChain = dependencyChains.get(addonId) ?? /* @__PURE__ */ new Set();
|
|
1612
|
-
if (addonChain.has(depId))
|
|
1613
|
-
|
|
1614
|
-
|
|
1615
|
-
|
|
1616
|
-
|
|
1627
|
+
if (addonChain.has(depId)) {
|
|
1628
|
+
const cyclePath = [
|
|
1629
|
+
...addonChain,
|
|
1630
|
+
addonId,
|
|
1631
|
+
depId
|
|
1632
|
+
].join(" → ");
|
|
1633
|
+
errorAndExit(`Circular dependency detected: ${cyclePath}\nAdd-ons cannot have circular dependencies.`);
|
|
1634
|
+
}
|
|
1617
1635
|
const depChain = new Set(addonChain);
|
|
1618
1636
|
depChain.add(addonId);
|
|
1619
1637
|
dependencyChains.set(depId, depChain);
|
|
@@ -1639,7 +1657,8 @@ async function promptAddonQuestions({ options, loadedAddons, workspace }) {
|
|
|
1639
1657
|
}
|
|
1640
1658
|
}
|
|
1641
1659
|
const addonDefinitions = addons.map((a) => a.addon);
|
|
1642
|
-
|
|
1660
|
+
const verifications = [...verifyCleanWorkingDirectory(options.cwd, options.gitCheck), ...verifyUnsupportedAddons(addonDefinitions, setupResults)];
|
|
1661
|
+
await runAndValidateVerifications(verifications);
|
|
1643
1662
|
for (const loaded of addons) {
|
|
1644
1663
|
const addon = loaded.addon;
|
|
1645
1664
|
const addonId = addon.id;
|
|
@@ -1687,7 +1706,10 @@ async function promptAddonQuestions({ options, loadedAddons, workspace }) {
|
|
|
1687
1706
|
};
|
|
1688
1707
|
}
|
|
1689
1708
|
async function runAddonsApply({ answers, options, loadedAddons, setupResults, workspace, fromCommand }) {
|
|
1690
|
-
if (!setupResults)
|
|
1709
|
+
if (!setupResults) {
|
|
1710
|
+
const setups = loadedAddons.length ? loadedAddons : officialAddons.map((a) => createLoadedAddon(a));
|
|
1711
|
+
setupResults = await setupAddons(setups, workspace);
|
|
1712
|
+
}
|
|
1691
1713
|
if (loadedAddons.length === 0) return {
|
|
1692
1714
|
nextSteps: [],
|
|
1693
1715
|
argsFormattedAddons: [],
|
|
@@ -1709,17 +1731,22 @@ async function runAddonsApply({ answers, options, loadedAddons, setupResults, wo
|
|
|
1709
1731
|
canceledAddonIds.push(addonId);
|
|
1710
1732
|
}
|
|
1711
1733
|
const successfulAddons = loadedAddons.filter((a) => !canceledAddonIds.includes(a.addon.id));
|
|
1712
|
-
if (addonSuccess.length === 0)
|
|
1713
|
-
|
|
1714
|
-
|
|
1715
|
-
|
|
1716
|
-
|
|
1717
|
-
|
|
1734
|
+
if (addonSuccess.length === 0) {
|
|
1735
|
+
if (fromCommand === "create") R.warn("All selected add-ons were canceled.");
|
|
1736
|
+
else {
|
|
1737
|
+
ge("All selected add-ons were canceled.");
|
|
1738
|
+
V.exit(1);
|
|
1739
|
+
}
|
|
1740
|
+
} else R.success(`Successfully setup add-ons: ${addonSuccess.map((c) => color.addon(c)).join(", ")}`);
|
|
1718
1741
|
let packageManager = null;
|
|
1719
1742
|
if (options.install === true) {
|
|
1720
1743
|
if (installNeeded) packageManager = await packageManagerPrompt(options.cwd);
|
|
1721
1744
|
} else if (options.install === false) {} else packageManager = options.install;
|
|
1722
|
-
|
|
1745
|
+
addAllowBuildsIfPnpm({
|
|
1746
|
+
cwd: workspace.cwd,
|
|
1747
|
+
packageManager,
|
|
1748
|
+
packages: ["esbuild"]
|
|
1749
|
+
});
|
|
1723
1750
|
const argsFormattedAddons = [];
|
|
1724
1751
|
for (const loaded of successfulAddons) {
|
|
1725
1752
|
const addonId = loaded.addon.id;
|
|
@@ -1735,10 +1762,12 @@ async function runAddonsApply({ answers, options, loadedAddons, setupResults, wo
|
|
|
1735
1762
|
let formattedValue;
|
|
1736
1763
|
if (question.type === "boolean") formattedValue = value ? "yes" : "no";
|
|
1737
1764
|
else if (question.type === "number") formattedValue = String(value);
|
|
1738
|
-
else if (question.type === "multiselect")
|
|
1739
|
-
|
|
1740
|
-
|
|
1741
|
-
|
|
1765
|
+
else if (question.type === "multiselect") {
|
|
1766
|
+
if (Array.isArray(value)) {
|
|
1767
|
+
if (value.length === 0) formattedValue = "none";
|
|
1768
|
+
else formattedValue = value.join(",");
|
|
1769
|
+
} else formattedValue = String(value);
|
|
1770
|
+
} else formattedValue = String(value);
|
|
1742
1771
|
optionParts.push(`${optionId}:${formattedValue}`);
|
|
1743
1772
|
}
|
|
1744
1773
|
if (optionParts.length > 0) argsFormattedAddons.push(`${addonSpecifier}="${optionParts.join("+")}"`);
|
|
@@ -1771,7 +1800,8 @@ async function runAddonsApply({ answers, options, loadedAddons, setupResults, wo
|
|
|
1771
1800
|
};
|
|
1772
1801
|
}
|
|
1773
1802
|
function getNextSteps(loadedAddons, workspace, answers, setupResults) {
|
|
1774
|
-
|
|
1803
|
+
const addonDefs = loadedAddons.map((l) => l.addon);
|
|
1804
|
+
return orderAddons(addonDefs, setupResults).map((loaded) => {
|
|
1775
1805
|
const { addon } = loadedAddons.find((l) => l.addon.id === loaded.id);
|
|
1776
1806
|
if (!addon.nextSteps) return;
|
|
1777
1807
|
const addonOptions = answers[addon.id];
|
|
@@ -2212,10 +2242,11 @@ async function createProject(cwd, options) {
|
|
|
2212
2242
|
template: () => {
|
|
2213
2243
|
if (options.template) return Promise.resolve(options.template);
|
|
2214
2244
|
if (options.fromPlayground) return Promise.resolve("minimal");
|
|
2245
|
+
const availableTemplates = options.add.length > 0 ? templates.filter((t) => t.name !== "addon") : templates;
|
|
2215
2246
|
return Ee({
|
|
2216
2247
|
message: "Which template would you like?",
|
|
2217
2248
|
initialValue: "minimal",
|
|
2218
|
-
options:
|
|
2249
|
+
options: availableTemplates.map((t) => ({
|
|
2219
2250
|
label: t.title,
|
|
2220
2251
|
value: t.name,
|
|
2221
2252
|
hint: t.description
|
|
@@ -2293,6 +2324,11 @@ async function createProject(cwd, options) {
|
|
|
2293
2324
|
loadedAddons = result.loadedAddons;
|
|
2294
2325
|
answers = result.answers;
|
|
2295
2326
|
}
|
|
2327
|
+
if (template === "demo" && !loadedAddons.some((a) => a.addon.id === "enhanced-img")) {
|
|
2328
|
+
const addon = getAddonDetails("enhanced-img");
|
|
2329
|
+
loadedAddons.push(createLoadedAddon(addon));
|
|
2330
|
+
answers["enhanced-img"] = {};
|
|
2331
|
+
}
|
|
2296
2332
|
create$1({
|
|
2297
2333
|
cwd: projectPath,
|
|
2298
2334
|
name: projectName,
|
|
@@ -2310,7 +2346,7 @@ async function createProject(cwd, options) {
|
|
|
2310
2346
|
let addOnFilesToFormat = [];
|
|
2311
2347
|
let addOnSuccessfulAddons = [];
|
|
2312
2348
|
let addonSetupResults = {};
|
|
2313
|
-
if (
|
|
2349
|
+
if (loadedAddons.length > 0) {
|
|
2314
2350
|
const { argsFormattedAddons: argsFormatted, filesToFormat, successfulAddons, setupResults } = await runAddonsApply({
|
|
2315
2351
|
answers,
|
|
2316
2352
|
options: {
|
|
@@ -2336,10 +2372,15 @@ async function createProject(cwd, options) {
|
|
|
2336
2372
|
else if (language === "checkjs") argsFormatted.push("--types", "jsdoc");
|
|
2337
2373
|
else if (language === "none") argsFormatted.push("--no-types");
|
|
2338
2374
|
if (argsFormattedAddons.length > 0) argsFormatted.push("--add", ...argsFormattedAddons);
|
|
2339
|
-
|
|
2375
|
+
const prompt = buildAndLogArgs(packageManager, "create", argsFormatted, [directory]);
|
|
2376
|
+
updateReadme(directory, prompt);
|
|
2340
2377
|
updateAgent(directory, language, packageManager ?? "npm", loadedAddons);
|
|
2341
2378
|
const addOnNextSteps = getNextSteps(addOnSuccessfulAddons, workspace, answers, addonSetupResults);
|
|
2342
|
-
|
|
2379
|
+
addAllowBuildsIfPnpm({
|
|
2380
|
+
cwd: projectPath,
|
|
2381
|
+
packageManager,
|
|
2382
|
+
packages: ["esbuild"]
|
|
2383
|
+
});
|
|
2343
2384
|
let depsInstalled = false;
|
|
2344
2385
|
if (packageManager) {
|
|
2345
2386
|
depsInstalled = await installDependencies(packageManager, projectPath);
|
|
@@ -2386,7 +2427,8 @@ async function createVirtualWorkspace({ cwd, template, type }) {
|
|
|
2386
2427
|
kitRoutes: "src/routes"
|
|
2387
2428
|
};
|
|
2388
2429
|
}
|
|
2389
|
-
const
|
|
2430
|
+
const templatePackageJsonPath = dist(`templates/${template}`);
|
|
2431
|
+
const { data: packageJson } = loadPackageJson(templatePackageJsonPath);
|
|
2390
2432
|
override.dependencies = {
|
|
2391
2433
|
...packageJson.devDependencies,
|
|
2392
2434
|
...packageJson.dependencies,
|
|
@@ -2711,7 +2753,7 @@ const legacyMigrations = [
|
|
|
2711
2753
|
//#endregion
|
|
2712
2754
|
//#region src/migrate/migrations/sveltekit-3/tasks/collect-migration-instructions.ts
|
|
2713
2755
|
const REPORT_PATH = "MIGRATION_TASKS.md";
|
|
2714
|
-
const GUIDE_URL = "https://
|
|
2756
|
+
const GUIDE_URL = "https://svelte.dev/docs/kit/migrating-to-sveltekit-3";
|
|
2715
2757
|
const CODE_FILES = "**/*.{js,ts,svelte,mjs,mts,cjs,cts}";
|
|
2716
2758
|
const GENERATED_MARKER = "<!-- Generated by sv migrate sveltekit-3:collect-migration-instructions -->";
|
|
2717
2759
|
function guideLink(anchor) {
|
|
@@ -3090,6 +3132,27 @@ function matches(content, pattern) {
|
|
|
3090
3132
|
return typeof pattern === "string" ? content.includes(pattern) : pattern.test(content);
|
|
3091
3133
|
}
|
|
3092
3134
|
function renderReport(findings) {
|
|
3135
|
+
const sections = findings.map(({ task, files }) => {
|
|
3136
|
+
const links = task.links.map(({ label, url }) => `- [${label}](${url})`).join("\n");
|
|
3137
|
+
const locations = files.map((file) => `- [ ] \`${normalizePosix(file)}\``).join("\n");
|
|
3138
|
+
let output = `### ${task.title}
|
|
3139
|
+
|
|
3140
|
+
${task.summary}
|
|
3141
|
+
|
|
3142
|
+
#### What to do
|
|
3143
|
+
|
|
3144
|
+
${task.instructions}
|
|
3145
|
+
|
|
3146
|
+
#### References
|
|
3147
|
+
|
|
3148
|
+
${links}`;
|
|
3149
|
+
if (locations.length) output += `
|
|
3150
|
+
|
|
3151
|
+
#### Files to review
|
|
3152
|
+
|
|
3153
|
+
${locations}`;
|
|
3154
|
+
return output;
|
|
3155
|
+
});
|
|
3093
3156
|
return `${GENERATED_MARKER}
|
|
3094
3157
|
# SvelteKit 3 migration tasks
|
|
3095
3158
|
|
|
@@ -3110,27 +3173,7 @@ Also search the project for \`@migration-task\` comments. They may describe addi
|
|
|
3110
3173
|
|
|
3111
3174
|
## Migration tasks
|
|
3112
3175
|
|
|
3113
|
-
${
|
|
3114
|
-
const links = task.links.map(({ label, url }) => `- [${label}](${url})`).join("\n");
|
|
3115
|
-
const locations = files.map((file) => `- [ ] \`${normalizePosix(file)}\``).join("\n");
|
|
3116
|
-
let output = `### ${task.title}
|
|
3117
|
-
|
|
3118
|
-
${task.summary}
|
|
3119
|
-
|
|
3120
|
-
#### What to do
|
|
3121
|
-
|
|
3122
|
-
${task.instructions}
|
|
3123
|
-
|
|
3124
|
-
#### References
|
|
3125
|
-
|
|
3126
|
-
${links}`;
|
|
3127
|
-
if (locations.length) output += `
|
|
3128
|
-
|
|
3129
|
-
#### Files to review
|
|
3130
|
-
|
|
3131
|
-
${locations}`;
|
|
3132
|
-
return output;
|
|
3133
|
-
}).join("\n\n")}
|
|
3176
|
+
${sections.join("\n\n")}
|
|
3134
3177
|
|
|
3135
3178
|
## Final verification
|
|
3136
3179
|
|
|
@@ -3833,28 +3876,28 @@ var lib_alias_default = defineMigrationTask({
|
|
|
3833
3876
|
});
|
|
3834
3877
|
//#endregion
|
|
3835
3878
|
//#region src/migrate/migrations/sveltekit-3/tasks/package-json.ts
|
|
3836
|
-
const
|
|
3879
|
+
const KIT3_MIN_VERSIONS = {
|
|
3837
3880
|
vite: "^8.0.12",
|
|
3838
3881
|
"@sveltejs/vite-plugin-svelte": "^7.0.0",
|
|
3839
3882
|
svelte: "^5.56.4",
|
|
3883
|
+
"@sveltejs/package": "^2.5.8",
|
|
3840
3884
|
"svelte-check": "^4.7.5",
|
|
3841
3885
|
typescript: "^6.0.0"
|
|
3842
3886
|
};
|
|
3843
3887
|
const ADAPTERS = {
|
|
3844
|
-
"@sveltejs/adapter-auto": "^8.0.0
|
|
3845
|
-
"@sveltejs/adapter-cloudflare": "^8.0.0
|
|
3846
|
-
"@sveltejs/adapter-netlify": "^7.0.0
|
|
3847
|
-
"@sveltejs/adapter-node": "^6.0.0
|
|
3848
|
-
"@sveltejs/adapter-static": "^4.0.0
|
|
3849
|
-
"@sveltejs/adapter-vercel": "^7.0.0
|
|
3888
|
+
"@sveltejs/adapter-auto": "^8.0.0",
|
|
3889
|
+
"@sveltejs/adapter-cloudflare": "^8.0.0",
|
|
3890
|
+
"@sveltejs/adapter-netlify": "^7.0.0",
|
|
3891
|
+
"@sveltejs/adapter-node": "^6.0.0",
|
|
3892
|
+
"@sveltejs/adapter-static": "^4.0.0",
|
|
3893
|
+
"@sveltejs/adapter-vercel": "^7.0.0"
|
|
3850
3894
|
};
|
|
3851
3895
|
var package_json_default = defineMigrationTask({
|
|
3852
3896
|
id: "package-json",
|
|
3853
3897
|
description: "Update package.json to be compatible with SvelteKit 3.0",
|
|
3854
|
-
run: ({ sv, cwd,
|
|
3855
|
-
sv.devDependency("@sveltejs/kit", "^3.0.0
|
|
3856
|
-
for (const [pkg, range] of Object.entries(
|
|
3857
|
-
if (pkg === "typescript" && language !== "ts") continue;
|
|
3898
|
+
run: ({ sv, cwd, dependencyVersion }) => {
|
|
3899
|
+
sv.devDependency("@sveltejs/kit", "^3.0.0");
|
|
3900
|
+
for (const [pkg, range] of Object.entries(KIT3_MIN_VERSIONS)) {
|
|
3858
3901
|
const current = dependencyVersion(pkg);
|
|
3859
3902
|
if (current && isVersionUnsupportedBelow(current, range)) sv.devDependency(pkg, range);
|
|
3860
3903
|
}
|
|
@@ -4394,9 +4437,9 @@ function migrateShallowRouting(ast) {
|
|
|
4394
4437
|
ast.body = ast.body.filter((statement) => statement.type !== "ImportDeclaration" || !emptiedImports.has(statement));
|
|
4395
4438
|
changed = true;
|
|
4396
4439
|
}
|
|
4397
|
-
Walker.walk(ast, null, { CallExpression(node,
|
|
4440
|
+
Walker.walk(ast, null, { CallExpression(node, ctx) {
|
|
4398
4441
|
if (node.callee.type !== "Identifier") {
|
|
4399
|
-
next();
|
|
4442
|
+
ctx.next();
|
|
4400
4443
|
return;
|
|
4401
4444
|
}
|
|
4402
4445
|
const replace = methods.get(node.callee.name);
|
|
@@ -4407,17 +4450,19 @@ function migrateShallowRouting(ast) {
|
|
|
4407
4450
|
changed = true;
|
|
4408
4451
|
}
|
|
4409
4452
|
if (hooks.has(node.callee.name) && migrateNavigationHook(node)) changed = true;
|
|
4410
|
-
next();
|
|
4453
|
+
ctx.next();
|
|
4411
4454
|
} });
|
|
4412
4455
|
return changed;
|
|
4413
4456
|
}
|
|
4414
4457
|
function scanMethodCalls(ast, methods) {
|
|
4415
4458
|
const unmigratable = /* @__PURE__ */ new Set();
|
|
4416
4459
|
let migratable = false;
|
|
4417
|
-
Walker.walk(ast, null, { CallExpression(node,
|
|
4418
|
-
if (node.callee.type === "Identifier" && methods.has(node.callee.name))
|
|
4419
|
-
|
|
4420
|
-
|
|
4460
|
+
Walker.walk(ast, null, { CallExpression(node, ctx) {
|
|
4461
|
+
if (node.callee.type === "Identifier" && methods.has(node.callee.name)) {
|
|
4462
|
+
if (node.arguments.some((argument) => argument.type === "SpreadElement")) unmigratable.add(node.callee.name);
|
|
4463
|
+
else migratable = true;
|
|
4464
|
+
}
|
|
4465
|
+
ctx.next();
|
|
4421
4466
|
} });
|
|
4422
4467
|
return {
|
|
4423
4468
|
unmigratable,
|
|
@@ -4850,7 +4895,7 @@ function isIncludePush(callee) {
|
|
|
4850
4895
|
const migrations = [
|
|
4851
4896
|
defineMigration({
|
|
4852
4897
|
id: "sveltekit-3",
|
|
4853
|
-
changelog: "https://
|
|
4898
|
+
changelog: "https://svelte.dev/docs/kit/migrating-to-sveltekit-3",
|
|
4854
4899
|
description: "A set of migrations for SvelteKit 3.0",
|
|
4855
4900
|
setup: ({ pkg, requires }) => {
|
|
4856
4901
|
const kitPackageName = "@sveltejs/kit";
|
|
@@ -4898,7 +4943,10 @@ const migrate = new Command("migrate").description("a CLI for migrating Svelte(K
|
|
|
4898
4943
|
runCommand(async () => {
|
|
4899
4944
|
const pkg = ensureValidWorkspace(verifiedOptions.cwd);
|
|
4900
4945
|
if (!pkg) return;
|
|
4901
|
-
if (verifiedOptions.tasks?.length !== 0)
|
|
4946
|
+
if (verifiedOptions.tasks?.length !== 0) {
|
|
4947
|
+
const verifications = [...verifyCleanWorkingDirectory(options.cwd, options.gitCheck)];
|
|
4948
|
+
await runAndValidateVerifications(verifications);
|
|
4949
|
+
}
|
|
4902
4950
|
if (!verifiedMigrationName) verifiedMigrationName = await Ee({
|
|
4903
4951
|
message: "Select a migration to run",
|
|
4904
4952
|
options: migrations.map((m) => ({
|
|
@@ -5013,9 +5061,10 @@ async function determineTasks(migration, options, pkg) {
|
|
|
5013
5061
|
errorAndExit("No tasks selected to run.");
|
|
5014
5062
|
return;
|
|
5015
5063
|
}
|
|
5016
|
-
|
|
5064
|
+
const recapMessage = tasksToRun.map(({ id, description }) => {
|
|
5017
5065
|
return `${id} ${color.optional(`(${description})`)}`;
|
|
5018
|
-
}).join("\n- ")
|
|
5066
|
+
}).join("\n- ");
|
|
5067
|
+
Ce(`- ${recapMessage}`, "Migration steps", { format: (line) => line });
|
|
5019
5068
|
if (!options.confirm) {
|
|
5020
5069
|
const proceed = await le({
|
|
5021
5070
|
message: "Do you want to proceed?",
|
|
@@ -5061,7 +5110,8 @@ function selectTasksFromArgs(selectedTaskIds, selectableTasks) {
|
|
|
5061
5110
|
function reportNextSteps() {
|
|
5062
5111
|
const total = getMigrationTaskCount();
|
|
5063
5112
|
if (total === 0) return;
|
|
5064
|
-
|
|
5113
|
+
const body = [`${total} ${total === 1 ? "comment" : "comments"} to review.`, `Search for ${color.command(MIGRATION_TASK_MARKER)} to resolve ${total === 1 ? "it" : "them"}.`];
|
|
5114
|
+
Ce(body.join("\n"), "Next steps", { format: (line) => line });
|
|
5065
5115
|
}
|
|
5066
5116
|
function hasInstallConflict(argv) {
|
|
5067
5117
|
return argv.some((arg) => arg === "--install" || arg.startsWith("--install=")) && argv.includes("--no-install");
|