diff --git a/.changeset/solid-singers-help.md b/.changeset/solid-singers-help.md new file mode 100644 index 00000000..b0dea0cb --- /dev/null +++ b/.changeset/solid-singers-help.md @@ -0,0 +1,5 @@ +--- +'sv': patch +--- + +fix(cli): `--from-playground` will create projects with `experimental.async` enabled _(if svelte version allows it)_ diff --git a/packages/create/playground.ts b/packages/create/playground.ts index 90cc888e..24235367 100644 --- a/packages/create/playground.ts +++ b/packages/create/playground.ts @@ -2,6 +2,7 @@ import fs from 'node:fs'; import path from 'node:path'; import * as js from '@sveltejs/cli-core/js'; import { parseJson, parseScript, parseSvelte } from '@sveltejs/cli-core/parsers'; +import { isVersionUnsupportedBelow } from '@sveltejs/cli-core'; export function validatePlaygroundUrl(link: string): boolean { try { @@ -196,6 +197,16 @@ export function setupPlaygroundProject( } } + let experimentalAsyncNeeded = true; + const addExperimentalAsync = () => { + const svelteConfigPath = path.join(cwd, 'svelte.config.js'); + const svelteConfig = fs.readFileSync(svelteConfigPath, 'utf-8'); + const { ast, generateCode } = parseScript(svelteConfig); + const { value: config } = js.exports.createDefault(ast, { fallback: js.object.create({}) }); + js.object.overrideProperties(config, { compilerOptions: { experimental: { async: true } } }); + fs.writeFileSync(svelteConfigPath, generateCode(), 'utf-8'); + }; + // we want to change the svelte version, even if the user decieded // to not install external dependencies if (playground.svelteVersion) { @@ -204,11 +215,18 @@ export function setupPlaygroundProject( // from https://github.com/sveltejs/svelte.dev/blob/ba7ad256f786aa5bc67eac3a58608f3f50b59e91/packages/repl/src/lib/workers/npm.ts#L14 const pkgPrNewRegex = /^(pr|commit|branch)-(.+)/; const match = pkgPrNewRegex.exec(playground.svelteVersion); - pkgJson.data.devDependencies['svelte'] = match - ? `https://pkg.pr.new/svelte@${match[2]}` - : `^${playground.svelteVersion}`; + const version = match ? `https://pkg.pr.new/svelte@${match[2]}` : `${playground.svelteVersion}`; + pkgJson.data.devDependencies['svelte'] = version; + + // if the version is a "pkg.pr.new" version, we don't need to check for support, we will use the fallback + if (!version.includes('pkg.pr.new')) { + const unsupported = isVersionUnsupportedBelow(version, '5.36'); + if (unsupported) experimentalAsyncNeeded = false; + } } + if (experimentalAsyncNeeded) addExperimentalAsync(); + // only update the package.json if we made any changes if (updatePackageJson) fs.writeFileSync(pkgPath, pkgJson.generateCode(), 'utf-8'); } diff --git a/packages/create/test/playground.ts b/packages/create/test/playground.ts index f7c2c34d..81fd4e0e 100644 --- a/packages/create/test/playground.ts +++ b/packages/create/test/playground.ts @@ -147,7 +147,7 @@ test('detect dependencies from playground files', () => { expect(Array.from(dependencies.keys()).length).toBe(3); }); -test('real world download and convert playground', async () => { +test('real world download and convert playground async', async () => { const directory = path.join(testWorkspaceDir, 'real-world-playground'); if (fs.existsSync(directory)) { fs.rmdirSync(directory, { recursive: true }); @@ -174,5 +174,38 @@ test('real world download and convert playground', async () => { const packageJsonPath = path.join(directory, 'package.json'); const packageJsonContent = fs.readFileSync(packageJsonPath, 'utf-8'); expect(packageJsonContent).toContain('"change-case": "latest"'); - expect(packageJsonContent).toContain('"svelte": "^5.38.7"'); + expect(packageJsonContent).toContain('"svelte": "5.38.7"'); + + const svelteConfigPath = path.join(directory, 'svelte.config.js'); + const svelteConfigContent = fs.readFileSync(svelteConfigPath, 'utf-8'); + expect(svelteConfigContent).toContain('experimental: { async: true }'); +}); + +test('real world download and convert playground without async', async () => { + const directory = path.join(testWorkspaceDir, 'real-world-playground-old'); + if (fs.existsSync(directory)) { + fs.rmdirSync(directory, { recursive: true }); + } + + create(directory, { + name: 'real-world-playground-old', + template: 'minimal', + types: 'typescript' + }); + + const playground = await downloadPlaygroundData({ + playgroundId: '770bbef086034b9f8e337bab57efe8d8', + hash: undefined, + svelteVersion: '5.0.5' + }); + + setupPlaygroundProject(playground, directory, true); + + const packageJsonPath = path.join(directory, 'package.json'); + const packageJsonContent = fs.readFileSync(packageJsonPath, 'utf-8'); + expect(packageJsonContent).toContain('"svelte": "5.0.5"'); + + const svelteConfigPath = path.join(directory, 'svelte.config.js'); + const svelteConfigContent = fs.readFileSync(svelteConfigPath, 'utf-8'); + expect(svelteConfigContent).not.toContain('experimental: { async: true }'); });