sv 1.0.1 → 1.1.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-BvT-iII-.mjs → addons-OcP_HeQ_.mjs} +407 -326
- package/dist/bin.mjs +88 -66
- package/dist/{engine-D2x5kvrf.d.mts → engine-BLZdMrao.d.mts} +44 -26
- package/dist/{engine-LhRAh1ZA.mjs → engine-DB9amJxd.mjs} +18 -20
- package/dist/src/index.d.mts +79 -2
- package/dist/src/index.mjs +2 -2
- package/dist/src/testing.d.mts +1 -1
- package/dist/src/testing.mjs +1 -1
- package/dist/templates/addon/package.json +3 -3
- package/dist/templates/demo/files.types=checkjs.json +2 -2
- package/dist/templates/demo/files.types=none.json +2 -2
- package/dist/templates/demo/files.types=typescript.json +3 -3
- package/dist/templates/demo/package.json +1 -1
- package/dist/templates/library/package.json +1 -1
- package/dist/templates/minimal/files.types=checkjs.json +1 -1
- package/dist/templates/minimal/files.types=typescript.json +1 -1
- package/dist/templates/minimal/package.json +1 -1
- package/dist/templates/svelte/assets/public/favicon.svg +1 -0
- package/dist/templates/svelte/assets/public/icons.svg +24 -0
- package/dist/templates/svelte/assets/src/assets/hero.png +0 -0
- package/dist/templates/svelte/assets/src/assets/vite.svg +1 -0
- package/dist/templates/svelte/files.types=none.json +7 -7
- package/dist/templates/svelte/files.types=typescript.json +9 -9
- package/package.json +3 -3
- package/dist/templates/svelte/assets/public/vite.svg +0 -1
package/dist/bin.mjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { $ as
|
|
3
|
-
import { n as officialAddons$1, t as getAddonDetails } from "./addons-
|
|
2
|
+
import { $ as parse$1, A as cliOptions, B as runAndValidateVerifications, C as execSync, D as getSharedFiles, E as dist, F as getPadding, G as UnsupportedError, H as updateAgent, I as helpConfig, J as array, K as name, L as isNodeError, M as filePaths, N as forwardExitCode, O as PackageJSONSchema, P as getHelpSections, Q as optional, R as normalizePosix, S as exec, T as templates, U as updateLibraryBuild, V as runCommand, W as updateReadme, X as literal, Y as boolean, Z as nonEmpty, _ as createLoadedAddon, _t as pe, a as setupAddons, at as string, b as getErrorHint, bt as R$1, c as AGENT_NAMES, ct as program, d as installDependencies, dt as Ce, et as picklist, f as installOption, ft as Ee, g as from, gt as le, h as up$2, ht as ge, i as prepareSvApi, it as strictObject, j as errorAndExit, k as buildAndLogArgs, l as addAllowBuildsIfPnpm, lt as Command, m as up$1, mt as Re, n as applyAddons, nt as record, o as createWorkspace, ot as transform, p as packageManagerPrompt, pt as R, q as version, r as orderAddons, rt as safeParse, s as findWorkspaceRoot, st as union, tt as pipe, u as detectPackageManager, ut as Option, vt, w as create$1, x as NonZeroExitError, yt as we, z as parseAddonOptions } from "./engine-DB9amJxd.mjs";
|
|
3
|
+
import { n as officialAddons$1, t as getAddonDetails } from "./addons-OcP_HeQ_.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";
|
|
@@ -1218,22 +1218,16 @@ function isPrettierInstalled(cwd) {
|
|
|
1218
1218
|
/** Nearest dir from `cwd` up to the workspace root with a `format` or `fmt` package.json script. */
|
|
1219
1219
|
function findFormatScript(cwd) {
|
|
1220
1220
|
const workspaceRoot = findWorkspaceRoot(cwd);
|
|
1221
|
-
|
|
1222
|
-
|
|
1223
|
-
|
|
1224
|
-
|
|
1225
|
-
|
|
1226
|
-
|
|
1227
|
-
|
|
1228
|
-
|
|
1229
|
-
|
|
1230
|
-
|
|
1231
|
-
dir: directory,
|
|
1232
|
-
name: "fmt"
|
|
1233
|
-
};
|
|
1234
|
-
}
|
|
1235
|
-
if (directory === root) break;
|
|
1236
|
-
directory = path.dirname(directory);
|
|
1221
|
+
for (const directory of up$2(path.resolve(cwd), { last: workspaceRoot })) if (fs.existsSync(path.join(directory, "package.json"))) {
|
|
1222
|
+
const { data } = loadPackageJson(directory);
|
|
1223
|
+
if (data.scripts?.format) return {
|
|
1224
|
+
dir: directory,
|
|
1225
|
+
name: "format"
|
|
1226
|
+
};
|
|
1227
|
+
if (data.scripts?.fmt) return {
|
|
1228
|
+
dir: directory,
|
|
1229
|
+
name: "fmt"
|
|
1230
|
+
};
|
|
1237
1231
|
}
|
|
1238
1232
|
}
|
|
1239
1233
|
async function withSpinner(startMsg, task) {
|
|
@@ -1258,12 +1252,16 @@ async function run(command, args, cwd) {
|
|
|
1258
1252
|
});
|
|
1259
1253
|
return {};
|
|
1260
1254
|
} catch (e) {
|
|
1261
|
-
if (e
|
|
1255
|
+
if (e instanceof NonZeroExitError) {
|
|
1256
|
+
const { stdout, stderr } = e.output ?? {};
|
|
1257
|
+
return { error: [stderr, stdout].filter(Boolean).join("\n").trim() };
|
|
1258
|
+
}
|
|
1259
|
+
if (!isNodeError(e)) return { error: "unknown error" };
|
|
1260
|
+
if (e.code === "ENOENT") return {
|
|
1262
1261
|
notFound: true,
|
|
1263
1262
|
error: `${command} not found`
|
|
1264
1263
|
};
|
|
1265
|
-
|
|
1266
|
-
return { error: [output?.stderr, output?.stdout].filter(Boolean).join("\n").trim() || (e instanceof Error ? e.message : "unknown error") };
|
|
1264
|
+
return { error: e.message };
|
|
1267
1265
|
}
|
|
1268
1266
|
}
|
|
1269
1267
|
//#endregion
|
|
@@ -1519,6 +1517,32 @@ async function resolveNonOfficialAddons(refs, downloadCheck) {
|
|
|
1519
1517
|
}
|
|
1520
1518
|
return selectedAddons;
|
|
1521
1519
|
}
|
|
1520
|
+
/**
|
|
1521
|
+
* Walks the `dependsOn` graph and returns the first cycle found as a path
|
|
1522
|
+
* (e.g. `['a', 'b', 'a']`), or `undefined` when the graph is acyclic.
|
|
1523
|
+
*/
|
|
1524
|
+
function findDependencyCycle(addonIds, setupResults) {
|
|
1525
|
+
const known = new Set(addonIds);
|
|
1526
|
+
const settled = /* @__PURE__ */ new Set();
|
|
1527
|
+
const path = [];
|
|
1528
|
+
const visit = (id) => {
|
|
1529
|
+
if (settled.has(id)) return;
|
|
1530
|
+
const cycleStart = path.indexOf(id);
|
|
1531
|
+
if (cycleStart !== -1) return [...path.slice(cycleStart), id];
|
|
1532
|
+
path.push(id);
|
|
1533
|
+
for (const depId of setupResults[id]?.dependsOn ?? []) {
|
|
1534
|
+
if (!known.has(depId)) continue;
|
|
1535
|
+
const cycle = visit(depId);
|
|
1536
|
+
if (cycle) return cycle;
|
|
1537
|
+
}
|
|
1538
|
+
path.pop();
|
|
1539
|
+
settled.add(id);
|
|
1540
|
+
};
|
|
1541
|
+
for (const id of addonIds) {
|
|
1542
|
+
const cycle = visit(id);
|
|
1543
|
+
if (cycle) return cycle;
|
|
1544
|
+
}
|
|
1545
|
+
}
|
|
1522
1546
|
async function promptAddonQuestions({ options, loadedAddons, workspace }) {
|
|
1523
1547
|
const addons = [...loadedAddons];
|
|
1524
1548
|
const emptyAnswersReducer = (acc, id) => {
|
|
@@ -1612,7 +1636,6 @@ async function promptAddonQuestions({ options, loadedAddons, workspace }) {
|
|
|
1612
1636
|
const additionalSetupResults = await setupAddons(missingSetupResults, workspace);
|
|
1613
1637
|
Object.assign(setupResults, additionalSetupResults);
|
|
1614
1638
|
}
|
|
1615
|
-
const dependencyChains = /* @__PURE__ */ new Map();
|
|
1616
1639
|
let hasNewDependencies = true;
|
|
1617
1640
|
while (hasNewDependencies) {
|
|
1618
1641
|
hasNewDependencies = false;
|
|
@@ -1623,30 +1646,9 @@ async function promptAddonQuestions({ options, loadedAddons, workspace }) {
|
|
|
1623
1646
|
if (!setupResult) errorAndExit(`Setup result missing for addon: ${addonId}`);
|
|
1624
1647
|
const missingDependencies = setupResult.dependsOn.filter((depId) => !addons.some((a) => a.addon.id === depId));
|
|
1625
1648
|
for (const depId of missingDependencies) {
|
|
1626
|
-
|
|
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
|
-
}
|
|
1635
|
-
const depChain = new Set(addonChain);
|
|
1636
|
-
depChain.add(addonId);
|
|
1637
|
-
dependencyChains.set(depId, depChain);
|
|
1649
|
+
if (!officialAddons.some((a) => a.id === depId)) errorAndExit(`'${color.addon(addonId)}' depends on '${color.addon(depId)}', which is not an official add-on.\nAdd it to the command explicitly.`);
|
|
1638
1650
|
hasNewDependencies = true;
|
|
1639
|
-
|
|
1640
|
-
if (!officialAddons.find((a) => a.id === depId)) throw new Error(`'${addonId}' depends on an invalid add-on: '${depId}'`);
|
|
1641
|
-
const officialAddonDetails = getAddonDetails(depId);
|
|
1642
|
-
addons.push(createLoadedAddon(officialAddonDetails));
|
|
1643
|
-
answers[depId] = {};
|
|
1644
|
-
continue;
|
|
1645
|
-
}
|
|
1646
|
-
if (await le({ message: `The ${color.addon(addonId)} add-on requires ${color.addon(depId)} to also be setup. ${color.success("Include it?")}` }) !== true) {
|
|
1647
|
-
ge("Operation cancelled.");
|
|
1648
|
-
V.exit(1);
|
|
1649
|
-
}
|
|
1651
|
+
addons.push(createLoadedAddon(getAddonDetails(depId)));
|
|
1650
1652
|
answers[depId] = {};
|
|
1651
1653
|
}
|
|
1652
1654
|
}
|
|
@@ -1656,6 +1658,8 @@ async function promptAddonQuestions({ options, loadedAddons, workspace }) {
|
|
|
1656
1658
|
Object.assign(setupResults, newSetupResults);
|
|
1657
1659
|
}
|
|
1658
1660
|
}
|
|
1661
|
+
const cycle = findDependencyCycle(addons.map((a) => a.addon.id), setupResults);
|
|
1662
|
+
if (cycle) errorAndExit(`Circular dependency detected: ${cycle.map((id) => color.addon(id)).join(" → ")}\nAdd-ons cannot have circular dependencies.`);
|
|
1659
1663
|
const addonDefinitions = addons.map((a) => a.addon);
|
|
1660
1664
|
const verifications = [...verifyCleanWorkingDirectory(options.cwd, options.gitCheck), ...verifyUnsupportedAddons(addonDefinitions, setupResults)];
|
|
1661
1665
|
await runAndValidateVerifications(verifications);
|
|
@@ -3003,21 +3007,9 @@ const migrationTasks = [
|
|
|
3003
3007
|
},
|
|
3004
3008
|
{
|
|
3005
3009
|
title: "Move adapter-node `ORIGIN` to `paths.origin`",
|
|
3006
|
-
|
|
3007
|
-
include: [
|
|
3008
|
-
"Dockerfile*",
|
|
3009
|
-
"**/Dockerfile*",
|
|
3010
|
-
"**/*.{js,ts,mjs,mts,json,jsonc,yml,yaml,toml}"
|
|
3011
|
-
],
|
|
3012
|
-
patterns: [
|
|
3013
|
-
/\bprocess\.env\.ORIGIN\b/,
|
|
3014
|
-
/\benv\s*\[\s*['"]ORIGIN['"]\s*\]/,
|
|
3015
|
-
/^\s*(?:ENV|ARG)\s+ORIGIN\b/m,
|
|
3016
|
-
/^\s*ORIGIN\s*[:=]/m
|
|
3017
|
-
]
|
|
3018
|
-
}],
|
|
3010
|
+
dependency: "@sveltejs/adapter-node",
|
|
3019
3011
|
summary: "The adapter-node `ORIGIN` environment variable is removed.",
|
|
3020
|
-
instructions: "
|
|
3012
|
+
instructions: "Find where `ORIGIN` is set (`.env` files, scripts, hosting dashboard, ...) and move the public-facing origin to `paths.origin` in `sveltekit(...)`. Do not delete `ORIGIN`: it is ignored by adapter-node now and may have other uses.",
|
|
3021
3013
|
links: guideLink("Adapters-adapter-node")
|
|
3022
3014
|
},
|
|
3023
3015
|
{
|
|
@@ -3098,9 +3090,10 @@ const migrationTasks = [
|
|
|
3098
3090
|
var collect_migration_instructions_default = defineMigrationTask({
|
|
3099
3091
|
id: "collect-migration-instructions",
|
|
3100
3092
|
description: `Collect instructions for non-automated migration tasks; creates ${REPORT_PATH} whose instructions you should follow to complete the migration`,
|
|
3101
|
-
run: ({ sv }) => {
|
|
3093
|
+
run: ({ sv, dependencyVersion }) => {
|
|
3102
3094
|
const findings = [];
|
|
3103
3095
|
for (const task of migrationTasks) {
|
|
3096
|
+
if (task.dependency && !dependencyVersion(task.dependency)) continue;
|
|
3104
3097
|
const files = /* @__PURE__ */ new Set();
|
|
3105
3098
|
if (!task.checks) findings.push({
|
|
3106
3099
|
task,
|
|
@@ -3879,7 +3872,7 @@ var lib_alias_default = defineMigrationTask({
|
|
|
3879
3872
|
const KIT3_MIN_VERSIONS = {
|
|
3880
3873
|
vite: "^8.0.12",
|
|
3881
3874
|
"@sveltejs/vite-plugin-svelte": "^7.0.0",
|
|
3882
|
-
svelte: "^5.
|
|
3875
|
+
svelte: "^5.57.1",
|
|
3883
3876
|
"@sveltejs/package": "^2.5.8",
|
|
3884
3877
|
"svelte-check": "^4.7.5",
|
|
3885
3878
|
typescript: "^6.0.0"
|
|
@@ -3962,6 +3955,7 @@ function migrateMatcher(cwd, file, target, context) {
|
|
|
3962
3955
|
const importDeclarations = [];
|
|
3963
3956
|
const body = [];
|
|
3964
3957
|
const paramMatcherTypes = /* @__PURE__ */ new Set(["ParamMatcher"]);
|
|
3958
|
+
const typescript = target.endsWith(".ts");
|
|
3965
3959
|
let declaresMatch = false;
|
|
3966
3960
|
let exportsMatch = false;
|
|
3967
3961
|
for (const statement of parsed.ast.body) {
|
|
@@ -3984,7 +3978,7 @@ function migrateMatcher(cwd, file, target, context) {
|
|
|
3984
3978
|
if (statement.type === "ExportAllDeclaration") throw new Error(`Cannot migrate '${file}' because it re-exports another module`);
|
|
3985
3979
|
if (statement.type === "ExportNamedDeclaration") {
|
|
3986
3980
|
if (statement.declaration) {
|
|
3987
|
-
stripParamMatcherType(statement.declaration, paramMatcherTypes);
|
|
3981
|
+
stripParamMatcherType(statement.declaration, paramMatcherTypes, typescript);
|
|
3988
3982
|
if (declares(statement.declaration, "match")) {
|
|
3989
3983
|
declaresMatch = true;
|
|
3990
3984
|
exportsMatch = true;
|
|
@@ -3993,7 +3987,7 @@ function migrateMatcher(cwd, file, target, context) {
|
|
|
3993
3987
|
} else exportsMatch ||= statement.specifiers.some((specifier) => specifier.exported.type === "Identifier" && specifier.exported.name === "match");
|
|
3994
3988
|
continue;
|
|
3995
3989
|
}
|
|
3996
|
-
stripParamMatcherType(statement, paramMatcherTypes);
|
|
3990
|
+
stripParamMatcherType(statement, paramMatcherTypes, typescript);
|
|
3997
3991
|
declaresMatch ||= declares(statement, "match");
|
|
3998
3992
|
body.push(statement);
|
|
3999
3993
|
}
|
|
@@ -4092,13 +4086,27 @@ function generateImportCode(context) {
|
|
|
4092
4086
|
for (const source of context.sideEffectImports) lines.push(`import ${quoteString(source)};`);
|
|
4093
4087
|
return lines;
|
|
4094
4088
|
}
|
|
4095
|
-
function stripParamMatcherType(node, paramMatcherTypes) {
|
|
4089
|
+
function stripParamMatcherType(node, paramMatcherTypes, typescript) {
|
|
4090
|
+
if (node.type === "FunctionDeclaration") {
|
|
4091
|
+
if (typescript && node.id?.name === "match") annotateParam(node);
|
|
4092
|
+
return;
|
|
4093
|
+
}
|
|
4096
4094
|
if (node.type !== "VariableDeclaration") return;
|
|
4097
4095
|
const declaration = node.declarations.find((declaration) => declaration.id.type === "Identifier" && declaration.id.name === "match");
|
|
4098
4096
|
if (!declaration || declaration.id.type !== "Identifier") return;
|
|
4099
4097
|
const annotation = declaration.id.typeAnnotation?.typeAnnotation;
|
|
4100
4098
|
if (annotation?.type === "TSTypeReference" && annotation.typeName.type === "Identifier" && paramMatcherTypes.has(annotation.typeName.name)) delete declaration.id.typeAnnotation;
|
|
4101
4099
|
if ((declaration.init?.type === "TSSatisfiesExpression" || declaration.init?.type === "TSAsExpression") && declaration.init.typeAnnotation.type === "TSTypeReference" && declaration.init.typeAnnotation.typeName.type === "Identifier" && paramMatcherTypes.has(declaration.init.typeAnnotation.typeName.name)) declaration.init = declaration.init.expression;
|
|
4100
|
+
if (typescript) annotateParam(declaration.init);
|
|
4101
|
+
}
|
|
4102
|
+
function annotateParam(init) {
|
|
4103
|
+
if (init?.type !== "ArrowFunctionExpression" && init?.type !== "FunctionExpression" && init?.type !== "FunctionDeclaration") return;
|
|
4104
|
+
const [param] = init.params;
|
|
4105
|
+
if (param?.type !== "Identifier" || param.typeAnnotation) return;
|
|
4106
|
+
param.typeAnnotation = {
|
|
4107
|
+
type: "TSTypeAnnotation",
|
|
4108
|
+
typeAnnotation: { type: "TSStringKeyword" }
|
|
4109
|
+
};
|
|
4102
4110
|
}
|
|
4103
4111
|
function stripParamMatcherComments(content) {
|
|
4104
4112
|
return content.replace(/\/\*\*[\s\S]*?\*\//g, (comment) => {
|
|
@@ -4800,6 +4808,20 @@ const INHERITED_OPTIONS = {
|
|
|
4800
4808
|
target: "esnext",
|
|
4801
4809
|
verbatimModuleSyntax: true
|
|
4802
4810
|
};
|
|
4811
|
+
/**
|
|
4812
|
+
* Root entries type-checked by the Kit 2 generated config (vite config, `test`, `tests`), plus the
|
|
4813
|
+
* configs `sv create` adds to `include`. Only the ones present in the project are kept.
|
|
4814
|
+
*/
|
|
4815
|
+
const ROOT_INCLUDES = [
|
|
4816
|
+
"vite.config.ts",
|
|
4817
|
+
"vite.config.js",
|
|
4818
|
+
"drizzle.config.ts",
|
|
4819
|
+
"drizzle.config.js",
|
|
4820
|
+
"playwright.config.ts",
|
|
4821
|
+
"playwright.config.js",
|
|
4822
|
+
"test",
|
|
4823
|
+
"tests"
|
|
4824
|
+
];
|
|
4803
4825
|
var tsconfig_default = defineMigrationTask({
|
|
4804
4826
|
id: "tsconfig",
|
|
4805
4827
|
description: "Extend the generated $app/tsconfig instead of .svelte-kit/tsconfig.json",
|
|
@@ -4814,11 +4836,11 @@ var tsconfig_default = defineMigrationTask({
|
|
|
4814
4836
|
extended[index] = PARENT_CONFIG;
|
|
4815
4837
|
data.extends = Array.isArray(data.extends) ? extended : PARENT_CONFIG;
|
|
4816
4838
|
}
|
|
4817
|
-
const include = data.include ??= ["src"];
|
|
4839
|
+
const include = data.include ??= ["src", ...ROOT_INCLUDES.filter((entry) => fs.existsSync(path.join(cwd, entry)))];
|
|
4818
4840
|
include.push(...moved.filter((entry) => !include.includes(entry)));
|
|
4819
4841
|
if (data.compilerOptions?.types) {
|
|
4820
4842
|
const types = data.compilerOptions.types;
|
|
4821
|
-
if (!types.includes("$app/types")) types.
|
|
4843
|
+
if (!types.includes("$app/types")) types.unshift("$app/types");
|
|
4822
4844
|
}
|
|
4823
4845
|
for (const [key, value] of Object.entries(data.compilerOptions ?? {})) if (INHERITED_OPTIONS[key] === value) delete data.compilerOptions[key];
|
|
4824
4846
|
}));
|
|
@@ -1,22 +1,26 @@
|
|
|
1
1
|
import { AgentName } from "@sveltejs/sv-utils";
|
|
2
|
-
//#region src/addons/
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
2
|
+
//#region src/addons/ids.d.ts
|
|
3
|
+
/**
|
|
4
|
+
* Official add-on ids, declared without importing the add-ons themselves so that
|
|
5
|
+
* add-ons can reference each other in `dependsOn`/`runsAfter` without import cycles.
|
|
6
|
+
*/
|
|
7
|
+
declare const ADDON_IDS: {
|
|
8
|
+
readonly prettier: "prettier";
|
|
9
|
+
readonly eslint: "eslint";
|
|
10
|
+
readonly vitest: "vitest";
|
|
11
|
+
readonly playwright: "playwright";
|
|
12
|
+
readonly tailwindcss: "tailwindcss";
|
|
13
|
+
readonly enhancedImg: "enhanced-img";
|
|
14
|
+
readonly sveltekitAdapter: "sveltekit-adapter";
|
|
15
|
+
readonly drizzle: "drizzle";
|
|
16
|
+
readonly betterAuth: "better-auth";
|
|
17
|
+
readonly mdsvex: "mdsvex";
|
|
18
|
+
readonly paraglide: "paraglide";
|
|
19
|
+
readonly storybook: "storybook";
|
|
20
|
+
readonly aiTools: "ai-tools";
|
|
21
|
+
readonly experimental: "experimental";
|
|
18
22
|
};
|
|
19
|
-
|
|
23
|
+
type OfficialAddonId = (typeof ADDON_IDS)[keyof typeof ADDON_IDS];
|
|
20
24
|
//#endregion
|
|
21
25
|
//#region src/core/options.d.ts
|
|
22
26
|
type BooleanQuestion = {
|
|
@@ -65,6 +69,12 @@ type BaseQuestion<Args extends OptionDefinition> = {
|
|
|
65
69
|
};
|
|
66
70
|
type Question<Args extends OptionDefinition = OptionDefinition> = BaseQuestion<Args> & (BooleanQuestion | StringQuestion | NumberQuestion | SelectQuestion<any> | MultiSelectQuestion<any>);
|
|
67
71
|
type OptionDefinition = Record<string, Question<any>>;
|
|
72
|
+
type QuestionFor<Value> = BaseQuestion<any> & ([Value] extends [boolean] ? BooleanQuestion : [Value] extends [number] ? NumberQuestion : [Value] extends [Array<infer Item>] ? MultiSelectQuestion<Item> : [string] extends [Value] ? StringQuestion : SelectQuestion<Value>);
|
|
73
|
+
/** The questions of an add-on, described by the values they produce. See `defineAddonOptions<Values>()`. */
|
|
74
|
+
type AddonOptions<Values extends Record<string, unknown>> = { [K in keyof Values]: QuestionFor<Values[K]>; } extends (infer Questions extends OptionDefinition) ? Questions : never;
|
|
75
|
+
type SameType<A, B> = [A] extends [B] ? ([B] extends [A] ? true : false) : false;
|
|
76
|
+
/** Keys whose question is missing, extra, or produces a different value than declared. */
|
|
77
|
+
type MismatchedOptions<Args extends OptionDefinition, Values> = { [K in keyof Args | keyof Values]: K extends keyof Args ? K extends keyof Values ? SameType<OptionValues<Args>[K], Values[K]> extends true ? never : K : K : K; }[keyof Args | keyof Values];
|
|
68
78
|
type OptionValues<Args extends OptionDefinition> = { [K in keyof Args]: Args[K] extends StringQuestion ? string : Args[K] extends BooleanQuestion ? boolean : Args[K] extends NumberQuestion ? number : Args[K] extends SelectQuestion<infer Value> ? Value : Args[K] extends MultiSelectQuestion<infer Value> ? Value[] : Args[K] extends Question<any> ? unknown : "ERROR: The value for this type is invalid. Ensure that the `default` value exists in `options`."; };
|
|
69
79
|
//#endregion
|
|
70
80
|
//#region src/core/workspace.d.ts
|
|
@@ -151,6 +161,7 @@ type SvApi = {
|
|
|
151
161
|
where?: (content: string) => boolean;
|
|
152
162
|
}, edit: FileEditMultiple) => void;
|
|
153
163
|
};
|
|
164
|
+
type AddonId = OfficialAddonId | (string & {});
|
|
154
165
|
type Addon<Args extends OptionDefinition, Id extends string = string, Setup extends Record<string, unknown> = Record<string, unknown>> = {
|
|
155
166
|
id: Id;
|
|
156
167
|
alias?: string;
|
|
@@ -163,16 +174,16 @@ type Addon<Args extends OptionDefinition, Id extends string = string, Setup exte
|
|
|
163
174
|
options: Args;
|
|
164
175
|
/** Setup the addon. Will be called before the addon is run. */
|
|
165
176
|
setup?: (workspace: Workspace & {
|
|
166
|
-
/**
|
|
167
|
-
dependsOn: (
|
|
177
|
+
/** Required add-ons. Implies `runsAfter`. Official ids are installed automatically, others must be part of the same run. */
|
|
178
|
+
dependsOn: (id: AddonId) => void;
|
|
168
179
|
/**
|
|
169
180
|
* Why is this addon not supported?
|
|
170
181
|
* @example
|
|
171
182
|
* if (!isKit) unsupported('Requires SvelteKit');
|
|
172
183
|
*/
|
|
173
184
|
unsupported: (reason: string) => void;
|
|
174
|
-
/**
|
|
175
|
-
runsAfter: (
|
|
185
|
+
/** Ordering only: run after these add-ons when they are part of the same run. */
|
|
186
|
+
runsAfter: (id: AddonId) => void;
|
|
176
187
|
/** Dynamically add an option to be prompted to the user */
|
|
177
188
|
addOption: <K extends Extract<keyof Setup, string>>(key: K, question: SetupOptions<Setup>[K]) => void;
|
|
178
189
|
}) => MaybePromise<void>;
|
|
@@ -281,7 +292,7 @@ type SetupResult = {
|
|
|
281
292
|
type AddonDefinition<Id extends string = string> = Addon<Record<string, Question<any>>, Id>;
|
|
282
293
|
type MaybePromise<T> = Promise<T> | T;
|
|
283
294
|
type Prettify<T> = { [K in keyof T]: T[K]; } & unknown;
|
|
284
|
-
type OptionBuilder<T extends OptionDefinition> = {
|
|
295
|
+
type OptionBuilder<T extends OptionDefinition, Values extends Record<string, unknown> = never> = {
|
|
285
296
|
/**
|
|
286
297
|
* This type is a bit complex, but in usage, it's quite simple!
|
|
287
298
|
*
|
|
@@ -296,9 +307,9 @@ type OptionBuilder<T extends OptionDefinition> = {
|
|
|
296
307
|
* })
|
|
297
308
|
* ```
|
|
298
309
|
*/
|
|
299
|
-
add<K extends string, const Q extends Question<T & Record<K, Q>>>(key: K, question: Q): OptionBuilder<T & Record<K, Q
|
|
310
|
+
add<K extends string, const Q extends Question<T & Record<K, Q>>>(key: K, question: Q): OptionBuilder<T & Record<K, Q>, Values>;
|
|
300
311
|
/** Finalize all options of your `add-on`. */
|
|
301
|
-
build(): Prettify<T>;
|
|
312
|
+
build(...check: [Values] extends [never] ? [] : [MismatchedOptions<T, Values>] extends [never] ? [] : [mismatchedOptions: MismatchedOptions<T, Values>]): [Values] extends [never] ? Prettify<T> : AddonOptions<Values>;
|
|
302
313
|
};
|
|
303
314
|
/**
|
|
304
315
|
* Options for an addon.
|
|
@@ -319,8 +330,15 @@ type OptionBuilder<T extends OptionDefinition> = {
|
|
|
319
330
|
* ```sh
|
|
320
331
|
* npx sv add <addon>=<option1>:<value1>+<option2>:<value2>
|
|
321
332
|
* ```
|
|
333
|
+
*
|
|
334
|
+
* Pass the values your options produce to get a small, stable type to export, checked both ways
|
|
335
|
+
* against the questions:
|
|
336
|
+
* ```ts
|
|
337
|
+
* export type MyAddonOptions = { demo: boolean };
|
|
338
|
+
* const options = defineAddonOptions<MyAddonOptions>().add('demo', { ... }).build();
|
|
339
|
+
* ```
|
|
322
340
|
*/
|
|
323
|
-
declare function defineAddonOptions(): OptionBuilder<{}>;
|
|
341
|
+
declare function defineAddonOptions<Values extends Record<string, unknown> = never>(): OptionBuilder<{}, Values>;
|
|
324
342
|
//#endregion
|
|
325
343
|
//#region src/core/engine.d.ts
|
|
326
344
|
type InstallOptions<Addons extends AddonMap> = {
|
|
@@ -347,4 +365,4 @@ declare function applyAddons({ loadedAddons, workspace, setupResults, options }:
|
|
|
347
365
|
installNeeded: boolean;
|
|
348
366
|
}>;
|
|
349
367
|
//#endregion
|
|
350
|
-
export {
|
|
368
|
+
export { SelectQuestion as A, BaseQuestion as C, OptionDefinition as D, NumberQuestion as E, ADDON_IDS as M, OptionValues as O, AddonOptions as S, MultiSelectQuestion as T, SvApi as _, Addon as a, Workspace as b, AddonReference as c, ConditionDefinition as d, ConfiguredAddon as f, SetupResult as g, PreparedAddon as h, add as i, StringQuestion as j, Question as k, AddonResult as l, OptionBuilder as m, InstallOptions as n, AddonDefinition as o, LoadedAddon as p, OptionMap as r, AddonInput as s, AddonMap as t, AddonSource as u, defineAddon as v, BooleanQuestion as w, WorkspaceOptions as x, defineAddonOptions as y };
|
|
@@ -5020,7 +5020,7 @@ function safeParse(schema, input, config$1) {
|
|
|
5020
5020
|
//#endregion
|
|
5021
5021
|
//#region package.json
|
|
5022
5022
|
var name = "sv";
|
|
5023
|
-
var version = "1.0
|
|
5023
|
+
var version = "1.1.0";
|
|
5024
5024
|
//#endregion
|
|
5025
5025
|
//#region src/core/errors.ts
|
|
5026
5026
|
var UnsupportedError = class extends Error {
|
|
@@ -5890,6 +5890,13 @@ function createLoadedAddon(addon) {
|
|
|
5890
5890
|
* ```sh
|
|
5891
5891
|
* npx sv add <addon>=<option1>:<value1>+<option2>:<value2>
|
|
5892
5892
|
* ```
|
|
5893
|
+
*
|
|
5894
|
+
* Pass the values your options produce to get a small, stable type to export, checked both ways
|
|
5895
|
+
* against the questions:
|
|
5896
|
+
* ```ts
|
|
5897
|
+
* export type MyAddonOptions = { demo: boolean };
|
|
5898
|
+
* const options = defineAddonOptions<MyAddonOptions>().add('demo', { ... }).build();
|
|
5899
|
+
* ```
|
|
5893
5900
|
*/
|
|
5894
5901
|
function defineAddonOptions() {
|
|
5895
5902
|
return createOptionBuilder({});
|
|
@@ -6089,20 +6096,14 @@ async function createWorkspace({ cwd, packageManager, override }) {
|
|
|
6089
6096
|
let dependencies = {};
|
|
6090
6097
|
if (override?.dependencies) dependencies = override.dependencies;
|
|
6091
6098
|
else {
|
|
6092
|
-
|
|
6093
|
-
const workspaceRoot
|
|
6094
|
-
|
|
6095
|
-
|
|
6096
|
-
|
|
6097
|
-
|
|
6098
|
-
dependencies
|
|
6099
|
-
|
|
6100
|
-
...packageJson.dependencies,
|
|
6101
|
-
...dependencies
|
|
6102
|
-
};
|
|
6103
|
-
}
|
|
6104
|
-
if (root === directory) break;
|
|
6105
|
-
directory = path.dirname(directory);
|
|
6099
|
+
const workspaceRoot = findWorkspaceRoot(resolvedCwd);
|
|
6100
|
+
for (const directory of up$1(resolvedCwd, { last: workspaceRoot })) if (fs.existsSync(path.join(directory, filePaths.packageJson))) {
|
|
6101
|
+
const { data: packageJson } = loadPackageJson(directory);
|
|
6102
|
+
dependencies = {
|
|
6103
|
+
...packageJson.devDependencies,
|
|
6104
|
+
...packageJson.dependencies,
|
|
6105
|
+
...dependencies
|
|
6106
|
+
};
|
|
6106
6107
|
}
|
|
6107
6108
|
}
|
|
6108
6109
|
for (const [key, value] of Object.entries(dependencies)) try {
|
|
@@ -6147,9 +6148,7 @@ async function createWorkspace({ cwd, packageManager, override }) {
|
|
|
6147
6148
|
};
|
|
6148
6149
|
}
|
|
6149
6150
|
function findWorkspaceRoot(cwd) {
|
|
6150
|
-
const
|
|
6151
|
-
let directory = cwd;
|
|
6152
|
-
while (directory && directory !== root) {
|
|
6151
|
+
for (const directory of up$1(cwd)) {
|
|
6153
6152
|
if (fs.existsSync(path.join(directory, filePaths.packageJson))) {
|
|
6154
6153
|
if (fs.existsSync(path.join(directory, "pnpm-workspace.yaml"))) return directory;
|
|
6155
6154
|
const { data } = loadPackageJson(directory);
|
|
@@ -6157,7 +6156,6 @@ function findWorkspaceRoot(cwd) {
|
|
|
6157
6156
|
}
|
|
6158
6157
|
const parent = path.dirname(directory);
|
|
6159
6158
|
if (directory.includes(".test-output") && !parent.includes(".test-output")) break;
|
|
6160
|
-
directory = parent;
|
|
6161
6159
|
}
|
|
6162
6160
|
return cwd;
|
|
6163
6161
|
}
|
|
@@ -6475,4 +6473,4 @@ function orderAddons(addons, setupResults) {
|
|
|
6475
6473
|
return ordered;
|
|
6476
6474
|
}
|
|
6477
6475
|
//#endregion
|
|
6478
|
-
export {
|
|
6476
|
+
export { parse$1 as $, cliOptions as A, runAndValidateVerifications as B, execSync as C, __toESM as Ct, getSharedFiles as D, dist as E, getPadding as F, UnsupportedError as G, updateAgent as H, helpConfig as I, array as J, name as K, isNodeError as L, filePaths as M, forwardExitCode as N, PackageJSONSchema as O, getHelpSections as P, optional as Q, normalizePosix as R, exec as S, __require as St, templates as T, updateLibraryBuild as U, runCommand as V, updateReadme as W, literal as X, boolean as Y, nonEmpty as Z, createLoadedAddon as _, pe as _t, setupAddons as a, string as at, getErrorHint as b, R$1 as bt, AGENT_NAMES as c, program as ct, installDependencies as d, Ce as dt, picklist as et, installOption as f, Ee as ft, from as g, le as gt, up$1 as h, ge as ht, prepareSvApi as i, strictObject as it, errorAndExit as j, buildAndLogArgs as k, addAllowBuildsIfPnpm as l, Command as lt, up as m, Re as mt, applyAddons as n, record as nt, createWorkspace as o, transform as ot, packageManagerPrompt as p, R as pt, version as q, orderAddons as r, safeParse as rt, findWorkspaceRoot as s, union as st, add as t, pipe as tt, detectPackageManager as u, Option as ut, defineAddon as v, vt, create as w, NonZeroExitError as x, __commonJSMin as xt, defineAddonOptions as y, we as yt, parseAddonOptions as z };
|
package/dist/src/index.d.mts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { A as
|
|
1
|
+
import { A as SelectQuestion, C as BaseQuestion, D as OptionDefinition, E as NumberQuestion, M as ADDON_IDS, O as OptionValues, S as AddonOptions, T as MultiSelectQuestion, _ as SvApi, a as Addon, b as Workspace, c as AddonReference, d as ConditionDefinition, f as ConfiguredAddon, g as SetupResult, h as PreparedAddon, i as add, j as StringQuestion, k as Question, l as AddonResult, m as OptionBuilder, n as InstallOptions, o as AddonDefinition, p as LoadedAddon, r as OptionMap, s as AddonInput, t as AddonMap, u as AddonSource, v as defineAddon, w as BooleanQuestion, x as WorkspaceOptions, y as defineAddonOptions } from "../engine-BLZdMrao.mjs";
|
|
2
2
|
//#region src/create/index.d.ts
|
|
3
3
|
type TemplateType = (typeof templateTypes)[number];
|
|
4
4
|
type LanguageType = (typeof languageTypes)[number];
|
|
@@ -12,6 +12,83 @@ type Options = {
|
|
|
12
12
|
};
|
|
13
13
|
export declare function create({ cwd, ...options }: Options): void;
|
|
14
14
|
//#endregion
|
|
15
|
+
//#region src/addons/ai-tools.d.ts
|
|
16
|
+
type AiToolsOptions = {
|
|
17
|
+
ide: string[];
|
|
18
|
+
delivery: "plugin" | "tools";
|
|
19
|
+
tools: string[];
|
|
20
|
+
mcpSetup: "local" | "remote";
|
|
21
|
+
};
|
|
22
|
+
//#endregion
|
|
23
|
+
//#region src/addons/better-auth.d.ts
|
|
24
|
+
type BetterAuthOptions = {
|
|
25
|
+
demo: Array<"password" | "github">;
|
|
26
|
+
};
|
|
27
|
+
//#endregion
|
|
28
|
+
//#region src/addons/drizzle.d.ts
|
|
29
|
+
type Database = "mysql" | "postgresql" | "sqlite" | "d1";
|
|
30
|
+
type DrizzleOptions = {
|
|
31
|
+
database: Database;
|
|
32
|
+
postgresql: "postgres.js" | "neon";
|
|
33
|
+
mysql: "mysql2" | "planetscale";
|
|
34
|
+
sqlite: "node-sqlite" | "better-sqlite3" | "libsql" | "turso";
|
|
35
|
+
docker: boolean;
|
|
36
|
+
};
|
|
37
|
+
//#endregion
|
|
38
|
+
//#region src/addons/experimental.d.ts
|
|
39
|
+
type ExperimentalOptions = {
|
|
40
|
+
features: string[];
|
|
41
|
+
};
|
|
42
|
+
//#endregion
|
|
43
|
+
//#region src/addons/paraglide.d.ts
|
|
44
|
+
type ParaglideOptions = {
|
|
45
|
+
languageTags: string;
|
|
46
|
+
demo: boolean;
|
|
47
|
+
};
|
|
48
|
+
//#endregion
|
|
49
|
+
//#region src/addons/playwright.d.ts
|
|
50
|
+
type PlaywrightOptions = {
|
|
51
|
+
demo: boolean;
|
|
52
|
+
};
|
|
53
|
+
//#endregion
|
|
54
|
+
//#region src/addons/sveltekit-adapter.d.ts
|
|
55
|
+
type SveltekitAdapterOptions = {
|
|
56
|
+
adapter: "auto" | "node" | "static" | "vercel" | "cloudflare" | "netlify";
|
|
57
|
+
cfTarget: "workers" | "pages";
|
|
58
|
+
};
|
|
59
|
+
//#endregion
|
|
60
|
+
//#region src/addons/tailwindcss.d.ts
|
|
61
|
+
type TailwindcssOptions = {
|
|
62
|
+
plugins: Array<"typography" | "forms">;
|
|
63
|
+
};
|
|
64
|
+
//#endregion
|
|
65
|
+
//#region src/addons/vitest-addon.d.ts
|
|
66
|
+
type VitestOptions = {
|
|
67
|
+
usages: Array<"unit" | "component">;
|
|
68
|
+
};
|
|
69
|
+
//#endregion
|
|
70
|
+
//#region src/addons/index.d.ts
|
|
71
|
+
type NoOptions = {};
|
|
72
|
+
type OfficialAddons = {
|
|
73
|
+
[ADDON_IDS.prettier]: Addon<NoOptions, typeof ADDON_IDS.prettier>;
|
|
74
|
+
[ADDON_IDS.eslint]: Addon<NoOptions, typeof ADDON_IDS.eslint>;
|
|
75
|
+
[ADDON_IDS.vitest]: Addon<AddonOptions<VitestOptions>, typeof ADDON_IDS.vitest>;
|
|
76
|
+
[ADDON_IDS.playwright]: Addon<AddonOptions<PlaywrightOptions>, typeof ADDON_IDS.playwright>;
|
|
77
|
+
[ADDON_IDS.tailwindcss]: Addon<AddonOptions<TailwindcssOptions>, typeof ADDON_IDS.tailwindcss>;
|
|
78
|
+
[ADDON_IDS.enhancedImg]: Addon<NoOptions, typeof ADDON_IDS.enhancedImg>;
|
|
79
|
+
[ADDON_IDS.sveltekitAdapter]: Addon<AddonOptions<SveltekitAdapterOptions>, typeof ADDON_IDS.sveltekitAdapter>;
|
|
80
|
+
[ADDON_IDS.drizzle]: Addon<AddonOptions<DrizzleOptions>, typeof ADDON_IDS.drizzle>;
|
|
81
|
+
[ADDON_IDS.betterAuth]: Addon<AddonOptions<BetterAuthOptions>, typeof ADDON_IDS.betterAuth>;
|
|
82
|
+
[ADDON_IDS.mdsvex]: Addon<NoOptions, typeof ADDON_IDS.mdsvex>;
|
|
83
|
+
[ADDON_IDS.paraglide]: Addon<AddonOptions<ParaglideOptions>, typeof ADDON_IDS.paraglide>;
|
|
84
|
+
[ADDON_IDS.storybook]: Addon<NoOptions, typeof ADDON_IDS.storybook>;
|
|
85
|
+
[ADDON_IDS.aiTools]: Addon<AddonOptions<AiToolsOptions>, typeof ADDON_IDS.aiTools>;
|
|
86
|
+
[ADDON_IDS.experimental]: Addon<AddonOptions<ExperimentalOptions>, typeof ADDON_IDS.experimental>;
|
|
87
|
+
};
|
|
88
|
+
/** What `add()` accepts as `options` for official add-ons, keyed by add-on id. */
|
|
89
|
+
type OfficialAddonOptions = OptionMap<OfficialAddons>;
|
|
90
|
+
export declare const officialAddons: OfficialAddons;
|
|
91
|
+
//#endregion
|
|
15
92
|
//#region src/core/processors.d.ts
|
|
16
93
|
type FileEditor = Workspace & {
|
|
17
94
|
content: string;
|
|
@@ -22,4 +99,4 @@ type FileType = {
|
|
|
22
99
|
content: (editor: FileEditor) => string;
|
|
23
100
|
};
|
|
24
101
|
//#endregion
|
|
25
|
-
export { type Addon, type AddonDefinition, type AddonInput, type AddonMap, type AddonReference, type AddonResult, type AddonSource, type BaseQuestion, type BooleanQuestion, type ConfiguredAddon, type FileEditor, type FileType, type InstallOptions, type LanguageType, type LoadedAddon, type MultiSelectQuestion, type NumberQuestion, type OptionBuilder, type OptionDefinition, type OptionMap, type OptionValues, type PreparedAddon, type Question, type SelectQuestion, type SetupResult, type StringQuestion, type SvApi, type TemplateType, type Workspace, type WorkspaceOptions, add, defineAddon, defineAddonOptions
|
|
102
|
+
export { type Addon, type AddonDefinition, type AddonInput, type AddonMap, type AddonOptions, type AddonReference, type AddonResult, type AddonSource, type BaseQuestion, type BooleanQuestion, type ConfiguredAddon, type FileEditor, type FileType, type InstallOptions, type LanguageType, type LoadedAddon, type MultiSelectQuestion, type NumberQuestion, type OfficialAddonOptions, type OfficialAddons, type OptionBuilder, type OptionDefinition, type OptionMap, type OptionValues, type PreparedAddon, type Question, type SelectQuestion, type SetupResult, type StringQuestion, type SvApi, type TemplateType, type Workspace, type WorkspaceOptions, add, defineAddon, defineAddonOptions };
|
package/dist/src/index.mjs
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { n as officialAddons } from "../addons-
|
|
1
|
+
import { t as add, v as defineAddon, w as create, y as defineAddonOptions } from "../engine-DB9amJxd.mjs";
|
|
2
|
+
import { n as officialAddons } from "../addons-OcP_HeQ_.mjs";
|
|
3
3
|
export { add, create, defineAddon, defineAddonOptions, officialAddons };
|
package/dist/src/testing.d.mts
CHANGED
package/dist/src/testing.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { C as execSync, Ct as __toESM, S as exec, St as __require, l as addAllowBuildsIfPnpm, t as add, w as create, xt as __commonJSMin } from "../engine-DB9amJxd.mjs";
|
|
2
2
|
import fs from "node:fs";
|
|
3
3
|
import path from "node:path";
|
|
4
4
|
import V from "node:process";
|
|
@@ -22,11 +22,11 @@
|
|
|
22
22
|
"access": "public"
|
|
23
23
|
},
|
|
24
24
|
"peerDependencies": {
|
|
25
|
-
"sv": "^1.0
|
|
25
|
+
"sv": "^1.1.0"
|
|
26
26
|
},
|
|
27
27
|
"devDependencies": {
|
|
28
|
-
"sv": "^1.0
|
|
29
|
-
"@sveltejs/sv-utils": "^1.0.
|
|
28
|
+
"sv": "^1.1.0",
|
|
29
|
+
"@sveltejs/sv-utils": "^1.0.1",
|
|
30
30
|
"@playwright/test": "^1.60.0",
|
|
31
31
|
"@types/node": "^25.9.1",
|
|
32
32
|
"tsdown": "^0.22.1",
|