diff --git a/.changeset/config.json b/.changeset/config.json
index 246e927640ff..fc418611aeac 100644
--- a/.changeset/config.json
+++ b/.changeset/config.json
@@ -6,5 +6,5 @@
"access": "public",
"baseBranch": "main",
"bumpVersionsWithWorkspaceProtocolOnly": true,
- "ignore": ["!(@sveltejs/*|create-svelte|svelte-migrate)"]
+ "ignore": ["!(@sveltejs/*|create-svelte)"]
}
diff --git a/.prettierrc b/.prettierrc
index 2d14308ebeb3..6f5a1610c17f 100644
--- a/.prettierrc
+++ b/.prettierrc
@@ -27,8 +27,7 @@
"packages/package/test/fixtures/**/expected/**/*",
"packages/package/test/watch/expected/**/*",
"packages/package/test/watch/package/**/*",
- "packages/kit/src/core/postbuild/fixtures/**/*",
- "packages/migrate/migrations/routes/*/samples.md"
+ "packages/kit/src/core/postbuild/fixtures/**/*"
],
"options": {
"requirePragma": true
diff --git a/README.md b/README.md
index bdc90a935771..ada896b1fa99 100644
--- a/README.md
+++ b/README.md
@@ -20,7 +20,6 @@ Web development, streamlined. Read the [documentation](https://svelte.dev/docs/k
| [@sveltejs/enhanced-img](packages/enhanced-img) | [Changelog](packages/enhanced-img/CHANGELOG.md) |
| [@sveltejs/package](packages/package) | [Changelog](packages/package/CHANGELOG.md) |
| [create-svelte](packages/create-svelte) | [Changelog](packages/create-svelte/CHANGELOG.md) |
-| [svelte-migrate](packages/migrate) | [Changelog](packages/migrate/CHANGELOG.md) |
[Additional adapters](https://sveltesociety.dev/packages?category=sveltekit-adapters) are maintained by the community.
diff --git a/packages/migrate/CHANGELOG.md b/packages/migrate/CHANGELOG.md
deleted file mode 100644
index 96020c5b63b7..000000000000
--- a/packages/migrate/CHANGELOG.md
+++ /dev/null
@@ -1,345 +0,0 @@
-# svelte-migrate
-
-## 1.6.8
-### Patch Changes
-
-
-- fix: prevent duplicate imports ([#12931](https://github.com/sveltejs/kit/pull/12931))
-
-## 1.6.7
-### Patch Changes
-
-
-- fix: prefer TS in unclear migration situations if `tsconfig.json` found ([#12881](https://github.com/sveltejs/kit/pull/12881))
-
-## 1.6.6
-### Patch Changes
-
-
-- docs: update URLs for new svelte.dev site ([#12857](https://github.com/sveltejs/kit/pull/12857))
-
-## 1.6.5
-### Patch Changes
-
-
-- docs: demonstrate sv migrate over prior commands ([#12840](https://github.com/sveltejs/kit/pull/12840))
-
-
-- fix: bump enhanced-img version to avoid peer dep warning ([#12852](https://github.com/sveltejs/kit/pull/12852))
-
-## 1.6.4
-### Patch Changes
-
-
-- fix: migrate `svelte` and `vite-plugin-svelte` to latest ([#12838](https://github.com/sveltejs/kit/pull/12838))
-
-## 1.6.3
-### Patch Changes
-
-
-- chore: add `svelte-eslint-parser` to list of migratable dependencies ([#12828](https://github.com/sveltejs/kit/pull/12828))
-
-## 1.6.2
-### Patch Changes
-
-
-- chore: upgrade to ts-morph 24 ([#12781](https://github.com/sveltejs/kit/pull/12781))
-
-## 1.6.1
-### Patch Changes
-
-
-- chore: upgrade to ts-morph 23 ([#12607](https://github.com/sveltejs/kit/pull/12607))
-
-## 1.6.0
-### Minor Changes
-
-
-- feat: pass filename to `migrate` to allow for `svelte:self` migration ([#12749](https://github.com/sveltejs/kit/pull/12749))
-
-
-### Patch Changes
-
-
-- fix: prompt SvelteKit 2 migration during Svelte 5 migration if necessary ([#12748](https://github.com/sveltejs/kit/pull/12748))
-
-## 1.5.1
-### Patch Changes
-
-
-- fix: use `next` versions for `svelte` and `vite-plugin-svelte` ([#12729](https://github.com/sveltejs/kit/pull/12729))
-
-## 1.5.0
-### Minor Changes
-
-
-- feat: add Svelte 5 migration ([#12519](https://github.com/sveltejs/kit/pull/12519))
-
-## 1.4.5
-### Patch Changes
-
-
-- chore: configure provenance in a simpler manner ([#12570](https://github.com/sveltejs/kit/pull/12570))
-
-## 1.4.4
-### Patch Changes
-
-
-- chore: package provenance ([#12567](https://github.com/sveltejs/kit/pull/12567))
-
-## 1.4.3
-
-### Patch Changes
-
-- chore: add keywords for discovery in npm search ([#12330](https://github.com/sveltejs/kit/pull/12330))
-
-## 1.4.2
-
-### Patch Changes
-
-- fix: bump import-meta-resolve to remove deprecation warnings ([#12240](https://github.com/sveltejs/kit/pull/12240))
-
-## 1.4.1
-
-### Patch Changes
-
-- fix: continue traversing the children of non-self-closing elements ([#12175](https://github.com/sveltejs/kit/pull/12175))
-
-## 1.4.0
-
-### Minor Changes
-
-- feat: add self-closing-tags migration ([#12128](https://github.com/sveltejs/kit/pull/12128))
-
-## 1.3.8
-
-### Patch Changes
-
-- chore(deps): update dependency ts-morph to v22 ([`4447269e979f2b5be18e0fded0b5843a6258542d`](https://github.com/sveltejs/kit/commit/4447269e979f2b5be18e0fded0b5843a6258542d))
-
-## 1.3.7
-
-### Patch Changes
-
-- fix: don't downgrade versions when bumping dependencies ([#11716](https://github.com/sveltejs/kit/pull/11716))
-
-## 1.3.6
-
-### Patch Changes
-
-- fix: correct link to docs ([#11407](https://github.com/sveltejs/kit/pull/11407))
-
-## 1.3.5
-
-### Patch Changes
-
-- chore: update primary branch from master to main ([`47779436c5f6c4d50011d0ef8b2709a07c0fec5d`](https://github.com/sveltejs/kit/commit/47779436c5f6c4d50011d0ef8b2709a07c0fec5d))
-
-## 1.3.4
-
-### Patch Changes
-
-- suggest running migrate command with latest if migration does not exist ([#11362](https://github.com/sveltejs/kit/pull/11362))
-
-## 1.3.3
-
-### Patch Changes
-
-- chore: insert package at sorted position ([#11332](https://github.com/sveltejs/kit/pull/11332))
-
-- fix: adjust cookie migration logic, note installation ([#11331](https://github.com/sveltejs/kit/pull/11331))
-
-## 1.3.2
-
-### Patch Changes
-
-- fix: handle jsconfig.json ([#11325](https://github.com/sveltejs/kit/pull/11325))
-
-## 1.3.1
-
-### Patch Changes
-
-- chore: fix broken migration links ([#11320](https://github.com/sveltejs/kit/pull/11320))
-
-## 1.3.0
-
-### Minor Changes
-
-- feat: add sveltekit v2 migration ([#11294](https://github.com/sveltejs/kit/pull/11294))
-
-## 1.2.8
-
-### Patch Changes
-
-- chore(deps): update dependency ts-morph to v21 ([#11181](https://github.com/sveltejs/kit/pull/11181))
-
-## 1.2.7
-
-### Patch Changes
-
-- chore(deps): update dependency ts-morph to v20 ([#10766](https://github.com/sveltejs/kit/pull/10766))
-
-## 1.2.6
-
-### Patch Changes
-
-- fix: do not downgrade versions ([#10352](https://github.com/sveltejs/kit/pull/10352))
-
-## 1.2.5
-
-### Patch Changes
-
-- fix: note old eslint plugin deprecation ([#10319](https://github.com/sveltejs/kit/pull/10319))
-
-## 1.2.4
-
-### Patch Changes
-
-- fix: ensure glob finds all files in folders ([#10230](https://github.com/sveltejs/kit/pull/10230))
-
-## 1.2.3
-
-### Patch Changes
-
-- fix: handle missing fields in migrate script ([#10221](https://github.com/sveltejs/kit/pull/10221))
-
-## 1.2.2
-
-### Patch Changes
-
-- fix: finalize svelte-4 migration ([#10195](https://github.com/sveltejs/kit/pull/10195))
-
-- fix: changed `index` to `index.d.ts` in `typesVersions` ([#10180](https://github.com/sveltejs/kit/pull/10180))
-
-## 1.2.1
-
-### Patch Changes
-
-- docs: update readme ([#10066](https://github.com/sveltejs/kit/pull/10066))
-
-## 1.2.0
-
-### Minor Changes
-
-- feat: add Svelte 4 migration ([#9729](https://github.com/sveltejs/kit/pull/9729))
-
-## 1.1.3
-
-### Patch Changes
-
-- fix: include index in typesVersions because it's always matched ([#9147](https://github.com/sveltejs/kit/pull/9147))
-
-## 1.1.2
-
-### Patch Changes
-
-- fix: update existing exports with prepended outdir ([#9133](https://github.com/sveltejs/kit/pull/9133))
-
-- fix: use typesVersions to wire up deep imports ([#9133](https://github.com/sveltejs/kit/pull/9133))
-
-## 1.1.1
-
-### Patch Changes
-
-- fix: include utils in migrate's published files ([#9085](https://github.com/sveltejs/kit/pull/9085))
-
-## 1.1.0
-
-### Minor Changes
-
-- feat: add `@sveltejs/package` migration (v1->v2) ([#8922](https://github.com/sveltejs/kit/pull/8922))
-
-## 1.0.1
-
-### Patch Changes
-
-- fix: correctly check for old load props ([#8537](https://github.com/sveltejs/kit/pull/8537))
-
-## 1.0.0
-
-### Major Changes
-
-First major release, see below for the history of changes that lead up to this.
-Starting from now all releases follow semver and changes will be listed as Major/Minor/Patch
-
-## 1.0.0-next.13
-
-### Patch Changes
-
-- fix: more robust uppercase migration ([#7033](https://github.com/sveltejs/kit/pull/7033))
-
-## 1.0.0-next.12
-
-### Patch Changes
-
-- feat: do uppercase http verbs migration on the fly ([#6371](https://github.com/sveltejs/kit/pull/6371))
-
-## 1.0.0-next.11
-
-### Patch Changes
-
-- fix: git mv files correctly when they contain \$ characters ([#6129](https://github.com/sveltejs/kit/pull/6129))
-
-## 1.0.0-next.10
-
-### Patch Changes
-
-- Revert change to suggest props destructuring ([#6099](https://github.com/sveltejs/kit/pull/6099))
-
-## 1.0.0-next.9
-
-### Patch Changes
-
-- Handle Error without message, handle status 200, handle missing body ([#6096](https://github.com/sveltejs/kit/pull/6096))
-
-## 1.0.0-next.8
-
-### Patch Changes
-
-- Suggest props destructuring if possible ([#6069](https://github.com/sveltejs/kit/pull/6069))
-- Fix typo in migration task ([#6070](https://github.com/sveltejs/kit/pull/6070))
-
-## 1.0.0-next.7
-
-### Patch Changes
-
-- Migrate type comments on arrow functions ([#5933](https://github.com/sveltejs/kit/pull/5933))
-- Use LayoutLoad inside +layout.js files ([#5931](https://github.com/sveltejs/kit/pull/5931))
-
-## 1.0.0-next.6
-
-### Patch Changes
-
-- Create `.ts` files from `${whitespace}`;
- }
-
- if (/lang(?:uage)?=(['"])(ts|typescript)\1/.test(attrs)) {
- ext = '.ts';
- }
-
- module = dedent(contents.replace(/^\n/, ''));
-
- const declared = find_declarations(contents);
- const delete_var = (/** @type {string } */ key) => {
- const declaration = declared?.get(key);
- if (declaration && !declaration.import) {
- declared?.delete(key);
- }
- };
- delete_var('load');
- delete_var('router');
- delete_var('hydrate');
- delete_var('prerender');
- const delete_kit_type = (/** @type {string } */ key) => {
- const declaration = declared?.get(key);
- if (
- declaration &&
- declaration.import?.type_only &&
- declaration.import.from === '@sveltejs/kit' &&
- !new RegExp(`\\W${key}\\W`).test(except_str(content, match))
- ) {
- declared?.delete(key);
- }
- };
- delete_kit_type('Load');
- delete_kit_type('LoadEvent');
- delete_kit_type('LoadOutput');
-
- if (!declared || declared.size > 0) {
- const body = `\n${indent}${error(
- 'Check code was safely removed',
- TASKS.PAGE_MODULE_CTX
- )}\n${comment(contents, indent)}`;
-
- return `${whitespace}`;
- }
-
- // nothing was declared here, we can safely remove the script
- return '';
- }
-
- if (!is_error && /export let [\w]+[^"`'\w\s]/.test(contents)) {
- contents = `\n${indent}${error('Add data prop', TASKS.PAGE_DATA_PROP)}\n${contents}`;
- // Possible TODO: migrate props to data.prop, or suggest $: ({propX, propY, ...} = data);
- }
-
- return `${whitespace}`;
- }
- );
-
- return { module, main, ext };
-}
-
-/** @param {string} content */
-function find_declarations(content) {
- const file = parse(content);
- if (!file) return;
-
- /** @type {Map} */
- const declared = new Map();
- /**
- * @param {string} name
- * @param {{from: string, type_only: boolean}} [import_def]
- */
- function add(name, import_def) {
- declared.set(name, { name, import: import_def });
- }
-
- for (const statement of file.ast.statements) {
- if (ts.isImportDeclaration(statement) && statement.importClause) {
- const type_only = statement.importClause.isTypeOnly;
- const from = ts.isStringLiteral(statement.moduleSpecifier)
- ? statement.moduleSpecifier.text
- : '';
-
- if (statement.importClause.name) {
- add(statement.importClause.name.text, { from, type_only });
- }
-
- const bindings = statement.importClause.namedBindings;
-
- if (bindings) {
- if (ts.isNamespaceImport(bindings)) {
- add(bindings.name.text, { from, type_only });
- } else {
- for (const binding of bindings.elements) {
- add(binding.name.text, { from, type_only: type_only || binding.isTypeOnly });
- }
- }
- }
- } else if (ts.isVariableStatement(statement)) {
- for (const declaration of statement.declarationList.declarations) {
- if (ts.isIdentifier(declaration.name)) {
- add(declaration.name.text);
- } else {
- return; // bail out if it's not a simple variable
- }
- }
- } else if (ts.isFunctionDeclaration(statement) || ts.isClassDeclaration(statement)) {
- if (statement.name && ts.isIdentifier(statement.name)) {
- add(statement.name.text);
- }
- } else if (ts.isExportDeclaration(statement) && !statement.exportClause) {
- return; // export * from '..' -> bail
- }
- }
-
- return declared;
-}
diff --git a/packages/migrate/migrations/routes/migrate_scripts/index.spec.js b/packages/migrate/migrations/routes/migrate_scripts/index.spec.js
deleted file mode 100644
index a52fc7128ff1..000000000000
--- a/packages/migrate/migrations/routes/migrate_scripts/index.spec.js
+++ /dev/null
@@ -1,14 +0,0 @@
-import { assert, test } from 'vitest';
-import { migrate_scripts } from './index.js';
-import { read_samples } from '../../../utils.js';
-
-for (const sample of read_samples(new URL('./samples.md', import.meta.url))) {
- test(sample.description, () => {
- const actual = migrate_scripts(
- sample.before,
- sample.description.includes('error'),
- sample.description.includes('moved')
- );
- assert.equal(actual.main, sample.after);
- });
-}
diff --git a/packages/migrate/migrations/routes/migrate_scripts/samples.md b/packages/migrate/migrations/routes/migrate_scripts/samples.md
deleted file mode 100644
index 6f57fb1f4c6d..000000000000
--- a/packages/migrate/migrations/routes/migrate_scripts/samples.md
+++ /dev/null
@@ -1,247 +0,0 @@
-## No module context, no page exports
-
-```svelte before
-
-
-
-
-{sry}
-```
-
-```svelte after
-
-
-
-
-{sry}
-```
-
-## Module context that can be removed
-
-```svelte before
-
-
-
-```
-
-```svelte after
-
-```
-
-## Module context with moved imports
-
-```svelte before
-
-
-
-
-{sry}
-```
-
-```svelte after
-
-
-
-
-{sry}
-```
-
-## Module context with type imports only
-
-```svelte before
-
-```
-
-```svelte after
-```
-
-## Module context with type imports only but used in instance script
-
-```svelte before
-
-
-
-```
-
-```svelte after
-
-
-
-```
-
-## Module context with export * from '..'
-
-```svelte before
-
-```
-
-```svelte after
-
-```
-
-## Module context with named imports
-
-```svelte before
-
-
-
-```
-
-```svelte after
-
-
-
-```
-
-## Module context with named imports that have same name as a load option
-
-```svelte before
-
-
-
-```
-
-```svelte after
-
-
-
-```
diff --git a/packages/migrate/migrations/routes/migrate_server/index.js b/packages/migrate/migrations/routes/migrate_server/index.js
deleted file mode 100644
index d9092d554651..000000000000
--- a/packages/migrate/migrations/routes/migrate_server/index.js
+++ /dev/null
@@ -1,190 +0,0 @@
-import ts from 'typescript';
-import {
- automigration,
- uppercase_migration,
- error,
- get_function_node,
- get_object_nodes,
- is_new,
- is_string_like,
- manual_return_migration,
- parse,
- rewrite_returns,
- unwrap
-} from '../utils.js';
-import * as TASKS from '../tasks.js';
-import { dedent, guess_indent, indent_at_line } from '../../../utils.js';
-
-const give_up = `${error('Update +server.js', TASKS.STANDALONE_ENDPOINT)}\n\n`;
-
-/**
- * @param {string} content
- * @returns {string}
- */
-export function migrate_server(content) {
- const file = parse(content);
- if (!file) return give_up + content;
-
- const indent = guess_indent(content);
-
- const methods = ['GET', 'POST', 'PUT', 'PATCH', 'DELETE'].filter((name) =>
- file.exports.map.has(name)
- );
-
- // If user didn't do the uppercase verbs migration yet, do it here on the fly.
- const uppercased = uppercase_migration(methods, file);
- if (!uppercased) {
- return give_up + content;
- } else if (uppercased !== content) {
- return migrate_server(uppercased);
- }
-
- const unmigrated = new Set(methods);
-
- /** @type {Map} */
- const imports = new Map();
-
- for (const statement of file.ast.statements) {
- for (const method of methods) {
- const fn = get_function_node(statement, /** @type{string} */ (file.exports.map.get(method)));
- if (fn?.body) {
- rewrite_returns(fn.body, (expr, node) => {
- // leave `() => new Response(...)` alone
- if (is_new(expr, 'Response')) return;
-
- const value = unwrap(expr);
- const nodes = ts.isObjectLiteralExpression(value) && get_object_nodes(value);
-
- if (nodes) {
- const body_is_object_literal = nodes.body && ts.isObjectLiteralExpression(nodes.body);
-
- if (body_is_object_literal || (nodes.body && ts.isIdentifier(nodes.body))) {
- let result;
-
- let name = 'json';
- let i = 1;
- while (content.includes(name)) name = `json$${i++}`;
-
- imports.set('json', name);
-
- const body = dedent(nodes.body.getText());
-
- if (nodes.headers || (nodes.status && nodes.status.getText() !== '200')) {
- const start = indent_at_line(content, expr.pos);
- const properties = [];
-
- if (nodes.status && nodes.status.getText() !== '200') {
- properties.push(`status: ${nodes.status.getText()}`);
- }
-
- if (nodes.headers) {
- properties.push(`headers: ${nodes.headers.getText()}`);
- }
-
- const ws = `\n${start}`;
- const init = `{${ws}${indent}${properties.join(`,${ws}${indent}`)}${ws}}`;
-
- result = `${name}(${body}, ${init})`;
- } else {
- result = `${name}(${body})`;
- }
-
- if (body_is_object_literal) {
- automigration(expr, file.code, result);
- } else {
- manual_return_migration(
- node || fn,
- file.code,
- TASKS.STANDALONE_ENDPOINT,
- `return ${result};`
- );
- }
-
- return;
- }
-
- let safe_headers = !nodes.headers || !ts.isObjectLiteralExpression(nodes.headers);
- if (nodes.headers && ts.isObjectLiteralExpression(nodes.headers)) {
- // if `headers` is an object literal, and it either doesn't contain
- // `set-cookie` or `set-cookie` is a string, then the headers
- // are safe to use in a `Response`
- const set_cookie_value = nodes.headers.properties.find((prop) => {
- return (
- ts.isPropertyAssignment(prop) &&
- ts.isStringLiteral(prop.name) &&
- /set-cookie/i.test(prop.name.text)
- );
- });
-
- if (!set_cookie_value || is_string_like(set_cookie_value)) {
- safe_headers = true;
- }
- }
-
- const safe_body =
- !nodes.body ||
- is_string_like(nodes.body) ||
- (ts.isCallExpression(nodes.body) &&
- nodes.body.expression.getText() === 'JSON.stringify');
-
- if (safe_headers) {
- const status = nodes.status ? nodes.status.getText() : '200';
- const headers = nodes.headers?.getText();
- const body = dedent(nodes.body?.getText() || 'undefined');
-
- const multiline = /\n/.test(headers);
-
- const init = [
- status !== '200' && `status: ${status}`,
- headers && `headers: ${headers}`
- ].filter(Boolean);
-
- const indent = indent_at_line(content, expr.getStart());
- const end_whitespace = multiline ? `\n${indent}` : ' ';
- const join_whitespace = multiline ? end_whitespace + guess_indent(content) : ' ';
-
- const response =
- init.length > 0
- ? `new Response(${body}, {${join_whitespace}${init.join(
- `,${join_whitespace}`
- )}${end_whitespace}})`
- : `new Response(${body})`;
-
- if (safe_body) {
- automigration(expr, file.code, response);
- } else {
- manual_return_migration(
- node || fn,
- file.code,
- TASKS.STANDALONE_ENDPOINT,
- `return ${response};`
- );
- }
-
- return;
- }
- }
-
- manual_return_migration(node || fn, file.code, TASKS.STANDALONE_ENDPOINT);
- });
-
- unmigrated.delete(method);
- }
- }
- }
-
- if (imports.size) {
- const has_imports = file.ast.statements.some((statement) => ts.isImportDeclaration(statement));
- const specifiers = Array.from(imports).map(([name, local]) =>
- name === local ? name : `${name} as ${local}`
- );
- const declaration = `import { ${specifiers.join(', ')} } from '@sveltejs/kit';`;
- file.code.prependLeft(0, declaration + (has_imports ? '\n' : '\n\n'));
- }
-
- if (unmigrated.size) {
- return give_up + file.code.toString();
- }
-
- return file.code.toString();
-}
diff --git a/packages/migrate/migrations/routes/migrate_server/index.spec.js b/packages/migrate/migrations/routes/migrate_server/index.spec.js
deleted file mode 100644
index 8ad424534ef0..000000000000
--- a/packages/migrate/migrations/routes/migrate_server/index.spec.js
+++ /dev/null
@@ -1,10 +0,0 @@
-import { assert, test } from 'vitest';
-import { migrate_server } from './index.js';
-import { read_samples } from '../../../utils.js';
-
-for (const sample of read_samples(new URL('./samples.md', import.meta.url))) {
- test(sample.description, () => {
- const actual = migrate_server(sample.before);
- assert.equal(actual, sample.after);
- });
-}
diff --git a/packages/migrate/migrations/routes/migrate_server/samples.md b/packages/migrate/migrations/routes/migrate_server/samples.md
deleted file mode 100644
index 3bc08662552f..000000000000
--- a/packages/migrate/migrations/routes/migrate_server/samples.md
+++ /dev/null
@@ -1,212 +0,0 @@
-## A GET function that returns a JSON object
-
-```js before
-export function GET() {
- return {
- body: {
- a: 1
- }
- };
-}
-```
-
-```js after
-import { json } from '@sveltejs/kit';
-
-export function GET() {
- return json({
- a: 1
- });
-}
-```
-
-## A GET function that returns a JSON object and already specifies a 'json' identifier
-
-```js before
-export function GET() {
- const json = 'shadow';
-
- return {
- body: {
- a: 1
- }
- };
-}
-```
-
-```js after
-import { json as json$1 } from '@sveltejs/kit';
-
-export function GET() {
- const json = 'shadow';
-
- return json$1({
- a: 1
- });
-}
-```
-
-## A GET function that returns a JSON object with custom headers
-
-```js before
-export function GET() {
- return {
- headers: {
- 'x-foo': '123'
- },
- body: {
- a: 1
- }
- };
-}
-```
-
-```js after
-import { json } from '@sveltejs/kit';
-
-export function GET() {
- return json({
- a: 1
- }, {
- headers: {
- 'x-foo': '123'
- }
- });
-}
-```
-
-## A GET arrow function that returns a JSON object
-
-```js before
-export const GET = () => ({
- body: {
- a: 1
- }
-});
-```
-
-```js after
-import { json } from '@sveltejs/kit';
-
-export const GET = () => json({
- a: 1
-});
-```
-
-## GET returns we can't migrate
-
-```js before
-export function GET() {
- if (a) {
- return {
- body
- };
- } else if (b) {
- return {
- body: new ReadableStream(),
- headers: {
- 'content-type': 'octasomething'
- }
- }
- } else if (c) {
- return {
- body: 'string',
- headers: {
- 'x-foo': 'bar'
- }
- }
- }
-}
-```
-
-```js after
-import { json } from '@sveltejs/kit';
-
-export function GET() {
- if (a) {
- throw new Error("@migration task: Migrate this return statement (https://github.com/sveltejs/kit/discussions/5774#discussioncomment-3292701)");
- // Suggestion (check for correctness before using):
- // return json(body);
- return {
- body
- };
- } else if (b) {
- throw new Error("@migration task: Migrate this return statement (https://github.com/sveltejs/kit/discussions/5774#discussioncomment-3292701)");
- // Suggestion (check for correctness before using):
- // return new Response(new ReadableStream(), {
- // headers: {
- // 'content-type': 'octasomething'
- // }
- // });
- return {
- body: new ReadableStream(),
- headers: {
- 'content-type': 'octasomething'
- }
- }
- } else if (c) {
- return new Response('string', {
- headers: {
- 'x-foo': 'bar'
- }
- })
- }
-}
-```
-
-## A function that returns a Response
-
-```js before
-export const GET = () => new Response('text');
-```
-
-```js after
-export const GET = () => new Response('text');
-```
-
-## A function that returns an unknown value
-
-```js before
-export const GET = () => createResponse('text');
-```
-
-```js after
-throw new Error("@migration task: Migrate this return statement (https://github.com/sveltejs/kit/discussions/5774#discussioncomment-3292701)");
-export const GET = () => createResponse('text');
-```
-
-## A function that returns nothing
-
-```js before
-export function GET() {
- return;
-}
-```
-
-```js after
-export function GET() {
- return;
-}
-```
-
-## A GET function that returns a JSON object
-
-```js before
-export function get() {
- return {
- body: {
- a: 1
- }
- };
-}
-```
-
-```js after
-import { json } from '@sveltejs/kit';
-
-export function GET() {
- return json({
- a: 1
- });
-}
-```
diff --git a/packages/migrate/migrations/routes/tasks.js b/packages/migrate/migrations/routes/tasks.js
deleted file mode 100644
index 775623232882..000000000000
--- a/packages/migrate/migrations/routes/tasks.js
+++ /dev/null
@@ -1,5 +0,0 @@
-export const STANDALONE_ENDPOINT = '3292701';
-export const PAGE_ENDPOINT = '3292699';
-export const PAGE_LOAD = '3292693';
-export const PAGE_MODULE_CTX = '3292722';
-export const PAGE_DATA_PROP = '3292707';
diff --git a/packages/migrate/migrations/routes/utils.js b/packages/migrate/migrations/routes/utils.js
deleted file mode 100644
index 0b8073e6c0fc..000000000000
--- a/packages/migrate/migrations/routes/utils.js
+++ /dev/null
@@ -1,374 +0,0 @@
-import ts from 'typescript';
-import MagicString from 'magic-string';
-import { comment, indent_at_line } from '../../utils.js';
-
-/**
- * @param {string} description
- * @param {string} [comment_id]
- */
-export function task(description, comment_id) {
- return (
- `@migration task: ${description}` +
- (comment_id
- ? ` (https://github.com/sveltejs/kit/discussions/5774#discussioncomment-${comment_id})`
- : '')
- );
-}
-
-/**
- * @param {string} description
- * @param {string} comment_id
- */
-export function error(description, comment_id) {
- return `throw new Error(${JSON.stringify(task(description, comment_id))});`;
-}
-
-/** @param {string} content */
-export function adjust_imports(content) {
- try {
- const ast = ts.createSourceFile(
- 'filename.ts',
- content,
- ts.ScriptTarget.Latest,
- true,
- ts.ScriptKind.TS
- );
-
- const code = new MagicString(content);
-
- /** @param {number} pos */
- function adjust(pos) {
- // TypeScript AST is a clusterfuck, we need to step forward to find
- // where the node _actually_ starts
- while (content[pos] !== '.') pos += 1;
-
- // replace ../ with ../../ and ./ with ../
- code.prependLeft(pos, content[pos + 1] === '.' ? '../' : '.');
- }
-
- /** @param {ts.Node} node */
- function walk(node) {
- if (ts.isImportDeclaration(node)) {
- const text = /** @type {ts.StringLiteral} */ (node.moduleSpecifier).text;
- if (text[0] === '.') adjust(node.moduleSpecifier.pos);
- }
-
- if (ts.isCallExpression(node) && node.expression.getText() === 'import') {
- const arg = node.arguments[0];
-
- if (ts.isStringLiteral(arg)) {
- if (arg.text[0] === '.') adjust(arg.pos);
- } else if (ts.isTemplateLiteral(arg) && !ts.isNoSubstitutionTemplateLiteral(arg)) {
- if (arg.head.text[0] === '.') adjust(arg.head.pos);
- }
- }
-
- node.forEachChild(walk);
- }
-
- ast.forEachChild(walk);
-
- return code.toString();
- } catch {
- // this is enough of an edge case that it's probably fine to
- // just leave the code as we found it
- return content;
- }
-}
-
-/**
- *
- * @param {ts.Node} node
- * @param {MagicString} str
- * @param {string} comment_nr
- * @param {string} [suggestion]
- */
-export function manual_return_migration(node, str, comment_nr, suggestion) {
- manual_migration(node, str, 'Migrate this return statement', comment_nr, suggestion);
-}
-
-/**
- * @param {ts.Node} node
- * @param {MagicString} str
- * @param {string} message
- * @param {string} comment_nr
- * @param {string} [suggestion]
- */
-export function manual_migration(node, str, message, comment_nr, suggestion) {
- // handle case where this is called on a (arrow) function
- if (ts.isFunctionExpression(node) || ts.isArrowFunction(node)) {
- node = node.parent.parent.parent;
- }
-
- const indent = indent_at_line(str.original, node.getStart());
-
- let appended = '';
-
- if (suggestion) {
- appended = `\n${indent}// Suggestion (check for correctness before using):\n${indent}// ${comment(
- suggestion,
- indent
- )}`;
- }
-
- str.prependLeft(node.getStart(), error(message, comment_nr) + appended + `\n${indent}`);
-}
-
-/**
- *
- * @param {ts.Node} node
- * @param {MagicString} str
- * @param {string} migration
- */
-export function automigration(node, str, migration) {
- str.overwrite(node.getStart(), node.getEnd(), migration);
-}
-
-/**
- * @param {ts.ObjectLiteralExpression} node
- */
-export function get_object_nodes(node) {
- /** @type {Record} */
- const obj = {};
-
- for (const property of node.properties) {
- if (ts.isPropertyAssignment(property) && ts.isIdentifier(property.name)) {
- obj[property.name.text] = property.initializer;
- } else if (ts.isShorthandPropertyAssignment(property)) {
- obj[property.name.text] = property.name;
- } else {
- return null; // object contains funky stuff like computed properties/accessors — bail
- }
- }
-
- return obj;
-}
-
-/**
- * @param {ts.Node} node
- */
-export function is_string_like(node) {
- return (
- ts.isStringLiteral(node) ||
- ts.isTemplateExpression(node) ||
- ts.isNoSubstitutionTemplateLiteral(node)
- );
-}
-
-/** @param {ts.SourceFile} node */
-export function get_exports(node) {
- /** @type {Map} */
- const map = new Map();
-
- let complex = false;
-
- for (const statement of node.statements) {
- if (
- ts.isExportDeclaration(statement) &&
- statement.exportClause &&
- ts.isNamedExports(statement.exportClause)
- ) {
- // export { x }, export { x as y }
- for (const specifier of statement.exportClause.elements) {
- map.set(specifier.name.text, specifier.propertyName?.text || specifier.name.text);
- }
- } else if (
- ts.isFunctionDeclaration(statement) &&
- statement.name &&
- ts.getModifiers(statement)?.[0]?.kind === ts.SyntaxKind.ExportKeyword
- ) {
- // export function x ...
- map.set(statement.name.text, statement.name.text);
- } else if (
- ts.isVariableStatement(statement) &&
- ts.getModifiers(statement)?.[0]?.kind === ts.SyntaxKind.ExportKeyword
- ) {
- // export const x = ..., y = ...
- for (const declaration of statement.declarationList.declarations) {
- if (ts.isIdentifier(declaration.name)) {
- map.set(declaration.name.text, declaration.name.text);
- } else {
- // might need to bail out on encountering this edge case,
- // because this stuff can get pretty intense
- complex = true;
- }
- }
- }
- }
-
- return { map, complex };
-}
-
-/**
- * @param {ts.Node} statement
- * @param {string[]} names
- * @returns {ts.FunctionDeclaration | ts.FunctionExpression | ts.ArrowFunction | undefined}
- */
-export function get_function_node(statement, ...names) {
- if (
- ts.isFunctionDeclaration(statement) &&
- statement.name &&
- names.includes(statement.name.text)
- ) {
- // export function x ...
- return statement;
- }
-
- if (ts.isVariableStatement(statement)) {
- for (const declaration of statement.declarationList.declarations) {
- if (
- ts.isIdentifier(declaration.name) &&
- names.includes(declaration.name.text) &&
- declaration.initializer &&
- (ts.isArrowFunction(declaration.initializer) ||
- ts.isFunctionExpression(declaration.initializer))
- ) {
- // export const x = ...
- return declaration.initializer;
- }
- }
- }
-}
-
-/**
- * Utility for rewriting return statements.
- * If `node` is `undefined`, it means it's a concise arrow function body (`() => ({}))`.
- * Lone `return;` statements are left untouched.
- * @param {ts.Block | ts.ConciseBody} block
- * @param {(expression: ts.Expression, node: ts.ReturnStatement | undefined) => void} callback
- */
-export function rewrite_returns(block, callback) {
- if (ts.isBlock(block)) {
- /** @param {ts.Node} node */
- function walk(node) {
- if (
- ts.isArrowFunction(node) ||
- ts.isFunctionExpression(node) ||
- ts.isFunctionDeclaration(node)
- ) {
- // don't cross this boundary
- return;
- }
-
- if (ts.isReturnStatement(node) && node.expression) {
- callback(node.expression, node);
- return;
- }
-
- node.forEachChild(walk);
- }
-
- block.forEachChild(walk);
- } else {
- callback(block, undefined);
- }
-}
-
-/** @param {ts.Node} node */
-export function unwrap(node) {
- if (ts.isParenthesizedExpression(node)) {
- return node.expression;
- }
-
- return node;
-}
-
-/**
- * @param {ts.Node} node
- * @param {string} name
- * @returns {node is ts.isNewExpression}
- */
-export function is_new(node, name) {
- return (
- ts.isNewExpression(node) && ts.isIdentifier(node.expression) && node.expression.text === name
- );
-}
-
-/** @param {string} content */
-export function parse(content) {
- try {
- const ast = ts.createSourceFile(
- 'filename.ts',
- content,
- ts.ScriptTarget.Latest,
- true,
- ts.ScriptKind.TS
- );
-
- const code = new MagicString(content);
-
- return {
- ast,
- code,
- exports: get_exports(ast)
- };
- } catch {
- return null;
- }
-}
-
-/**
- * @param {ts.Node} node
- * @param {MagicString} code
- * @param {string} old_type
- * @param {string} new_type
- */
-export function rewrite_type(node, code, old_type, new_type) {
- // @ts-ignore
- const jsDoc = node.jsDoc || node.parent?.parent?.parent?.jsDoc;
- if (jsDoc) {
- // @ts-ignore
- for (const comment of jsDoc) {
- const str = comment.getText();
- const index = str.indexOf(old_type);
-
- if (index !== -1) {
- code.overwrite(comment.pos + index, comment.pos + index + old_type.length, new_type);
- }
- }
- }
-
- // @ts-ignore
- const type = node.type || node.parent.type; // handle both fn and var declarations
-
- if (type?.typeName?.escapedText.startsWith(old_type)) {
- const start = type.getStart();
- code.overwrite(start, start + old_type.length, new_type);
- }
-}
-
-/**
- * Does the HTTP verbs uppercase migration if it didn't happen yet. If a string
- * is returned, the migration was done or wasn't needed. If undefined is returned,
- * the migration is needed but couldn't be done.
- *
- * @param {string[]} methods
- * @param {NonNullable>} file
- */
-export function uppercase_migration(methods, file) {
- const old_methods = new Set(
- ['get', 'post', 'put', 'patch', 'del'].filter((name) => file.exports.map.has(name))
- );
-
- if (old_methods.size && !methods.length) {
- for (const statement of file.ast.statements) {
- for (const method of old_methods) {
- const fn = get_function_node(
- statement,
- /** @type{string} */ (file.exports.map.get(method))
- );
- if (!fn?.name) {
- continue;
- }
- file.code.overwrite(
- fn.name.getStart(),
- fn.name.getEnd(),
- method === 'del' ? 'DELETE' : method.toUpperCase()
- );
- old_methods.delete(method);
- }
- }
- }
-
- return old_methods.size ? undefined : file.code.toString();
-}
diff --git a/packages/migrate/migrations/self-closing-tags/index.js b/packages/migrate/migrations/self-closing-tags/index.js
deleted file mode 100644
index ced6ca3089e7..000000000000
--- a/packages/migrate/migrations/self-closing-tags/index.js
+++ /dev/null
@@ -1,57 +0,0 @@
-import colors from 'kleur';
-import fs from 'node:fs';
-import process from 'node:process';
-import prompts from 'prompts';
-import glob from 'tiny-glob/sync.js';
-import { remove_self_closing_tags } from './migrate.js';
-import { pathToFileURL } from 'node:url';
-import { resolve } from 'import-meta-resolve';
-
-export async function migrate() {
- let compiler;
- try {
- compiler = await import_from_cwd('svelte/compiler');
- } catch {
- console.log(colors.bold().red('❌ Could not find a local Svelte installation.'));
- return;
- }
-
- console.log(
- colors.bold().yellow('\nThis will update .svelte files inside the current directory\n')
- );
-
- const response = await prompts({
- type: 'confirm',
- name: 'value',
- message: 'Continue?',
- initial: false
- });
-
- if (!response.value) {
- process.exit(1);
- }
-
- const files = glob('**/*.svelte')
- .map((file) => file.replace(/\\/g, '/'))
- .filter((file) => !file.includes('/node_modules/'));
-
- for (const file of files) {
- try {
- const code = await remove_self_closing_tags(compiler, fs.readFileSync(file, 'utf-8'));
- fs.writeFileSync(file, code);
- } catch {
- // continue
- }
- }
-
- console.log(colors.bold().green('✔ Your project has been updated'));
- console.log(' If using Prettier, please upgrade to the latest prettier-plugin-svelte version');
-}
-
-/** @param {string} name */
-function import_from_cwd(name) {
- const cwd = pathToFileURL(process.cwd()).href;
- const url = resolve(name, cwd + '/x.js');
-
- return import(url);
-}
diff --git a/packages/migrate/migrations/self-closing-tags/migrate.js b/packages/migrate/migrations/self-closing-tags/migrate.js
deleted file mode 100644
index 73f4ec0a60f5..000000000000
--- a/packages/migrate/migrations/self-closing-tags/migrate.js
+++ /dev/null
@@ -1,192 +0,0 @@
-import MagicString from 'magic-string';
-import { walk } from 'zimmerframe';
-
-const VoidElements = [
- 'area',
- 'base',
- 'br',
- 'col',
- 'embed',
- 'hr',
- 'img',
- 'input',
- 'keygen',
- 'link',
- 'menuitem',
- 'meta',
- 'param',
- 'source',
- 'track',
- 'wbr'
-];
-
-const SVGElements = [
- 'altGlyph',
- 'altGlyphDef',
- 'altGlyphItem',
- 'animate',
- 'animateColor',
- 'animateMotion',
- 'animateTransform',
- 'circle',
- 'clipPath',
- 'color-profile',
- 'cursor',
- 'defs',
- 'desc',
- 'discard',
- 'ellipse',
- 'feBlend',
- 'feColorMatrix',
- 'feComponentTransfer',
- 'feComposite',
- 'feConvolveMatrix',
- 'feDiffuseLighting',
- 'feDisplacementMap',
- 'feDistantLight',
- 'feDropShadow',
- 'feFlood',
- 'feFuncA',
- 'feFuncB',
- 'feFuncG',
- 'feFuncR',
- 'feGaussianBlur',
- 'feImage',
- 'feMerge',
- 'feMergeNode',
- 'feMorphology',
- 'feOffset',
- 'fePointLight',
- 'feSpecularLighting',
- 'feSpotLight',
- 'feTile',
- 'feTurbulence',
- 'filter',
- 'font',
- 'font-face',
- 'font-face-format',
- 'font-face-name',
- 'font-face-src',
- 'font-face-uri',
- 'foreignObject',
- 'g',
- 'glyph',
- 'glyphRef',
- 'hatch',
- 'hatchpath',
- 'hkern',
- 'image',
- 'line',
- 'linearGradient',
- 'marker',
- 'mask',
- 'mesh',
- 'meshgradient',
- 'meshpatch',
- 'meshrow',
- 'metadata',
- 'missing-glyph',
- 'mpath',
- 'path',
- 'pattern',
- 'polygon',
- 'polyline',
- 'radialGradient',
- 'rect',
- 'set',
- 'solidcolor',
- 'stop',
- 'svg',
- 'switch',
- 'symbol',
- 'text',
- 'textPath',
- 'tref',
- 'tspan',
- 'unknown',
- 'use',
- 'view',
- 'vkern'
-];
-
-/**
- * @param {{ preprocess: any, parse: any }} svelte_compiler
- * @param {string} source
- */
-export async function remove_self_closing_tags({ preprocess, parse }, source) {
- const preprocessed = await preprocess(source, {
- /** @param {{ content: string }} input */
- script: ({ content }) => ({
- code: content
- .split('\n')
- .map((line) => ' '.repeat(line.length))
- .join('\n')
- }),
- /** @param {{ content: string }} input */
- style: ({ content }) => ({
- code: content
- .split('\n')
- .map((line) => ' '.repeat(line.length))
- .join('\n')
- })
- });
- const ast = parse(preprocessed.code);
- const ms = new MagicString(source);
- /** @type {Array<() => void>} */
- const updates = [];
- let is_foreign = false;
- let is_custom_element = false;
-
- walk(ast.html, null, {
- _(node, { next, stop }) {
- if (node.type === 'Options') {
- const namespace = node.attributes.find(
- /** @param {any} a */
- (a) => a.type === 'Attribute' && a.name === 'namespace'
- );
- if (namespace?.value[0].data === 'foreign') {
- is_foreign = true;
- stop();
- return;
- }
-
- is_custom_element = node.attributes.some(
- /** @param {any} a */
- (a) => a.type === 'Attribute' && (a.name === 'customElement' || a.name === 'tag')
- );
- }
-
- if (node.type === 'Element' || node.type === 'Slot') {
- const is_self_closing = source[node.end - 2] === '/';
- if (
- !is_self_closing ||
- VoidElements.includes(node.name) ||
- SVGElements.includes(node.name) ||
- !/^[a-z0-9_-]+$/.test(node.name)
- ) {
- next();
- return;
- }
-
- let start = node.end - 2;
- if (source[start - 1] === ' ') {
- start--;
- }
- updates.push(() => {
- if (node.type === 'Element' || is_custom_element) {
- ms.update(start, node.end, `>${node.name}>`);
- }
- });
- }
-
- next();
- }
- });
-
- if (is_foreign) {
- return source;
- }
-
- updates.forEach((update) => update());
- return ms.toString();
-}
diff --git a/packages/migrate/migrations/self-closing-tags/migrate.spec.js b/packages/migrate/migrations/self-closing-tags/migrate.spec.js
deleted file mode 100644
index 421f00519732..000000000000
--- a/packages/migrate/migrations/self-closing-tags/migrate.spec.js
+++ /dev/null
@@ -1,32 +0,0 @@
-import { assert, test } from 'vitest';
-import * as compiler from 'svelte/compiler';
-import { remove_self_closing_tags } from './migrate.js';
-
-/** @type {Record} */
-const tests = {
- '': '',
- '': '',
- '': '',
- '': '',
- '': '',
- '\t': '\t',
- '': '',
- '': '',
- '': '',
- '': '',
- '': '',
- '':
- '',
- '': '',
- '': '',
- '':
- '',
- '
': '
'
-};
-
-for (const input in tests) {
- test(input, async () => {
- const output = tests[input];
- assert.equal(await remove_self_closing_tags(compiler, input), output);
- });
-}
diff --git a/packages/migrate/migrations/svelte-4/index.js b/packages/migrate/migrations/svelte-4/index.js
deleted file mode 100644
index 4fea5173da0e..000000000000
--- a/packages/migrate/migrations/svelte-4/index.js
+++ /dev/null
@@ -1,112 +0,0 @@
-import colors from 'kleur';
-import fs from 'node:fs';
-import process from 'node:process';
-import prompts from 'prompts';
-import glob from 'tiny-glob/sync.js';
-import { bail, check_git, update_js_file, update_svelte_file } from '../../utils.js';
-import { transform_code, transform_svelte_code, update_pkg_json } from './migrate.js';
-
-export async function migrate() {
- if (!fs.existsSync('package.json')) {
- bail('Please re-run this script in a directory with a package.json');
- }
-
- console.log(
- colors
- .bold()
- .yellow(
- '\nThis will update files in the current directory\n' +
- "If you're inside a monorepo, don't run this in the root directory, rather run it in all projects independently.\n"
- )
- );
-
- const use_git = check_git();
-
- const response = await prompts({
- type: 'confirm',
- name: 'value',
- message: 'Continue?',
- initial: false
- });
-
- if (!response.value) {
- process.exit(1);
- }
-
- const folders = await prompts({
- type: 'multiselect',
- name: 'value',
- message: 'Which folders should be migrated?',
- choices: fs
- .readdirSync('.')
- .filter(
- (dir) => fs.statSync(dir).isDirectory() && dir !== 'node_modules' && !dir.startsWith('.')
- )
- .map((dir) => ({ title: dir, value: dir, selected: true }))
- });
-
- if (!folders.value?.length) {
- process.exit(1);
- }
-
- const migrate_transition = await prompts({
- type: 'confirm',
- name: 'value',
- message:
- 'Add the `|global` modifier to currently global transitions for backwards compatibility? More info at https://svelte.dev/docs/svelte/v4-migration-guide#transitions-are-local-by-default',
- initial: true
- });
-
- update_pkg_json();
-
- // const { default: config } = fs.existsSync('svelte.config.js')
- // ? await import(pathToFileURL(path.resolve('svelte.config.js')).href)
- // : { default: {} };
-
- /** @type {string[]} */
- const svelte_extensions = /* config.extensions ?? - disabled because it would break .svx */ [
- '.svelte'
- ];
- const extensions = [...svelte_extensions, '.ts', '.js'];
- // For some reason {folders.value.join(',')} as part of the glob doesn't work and returns less files
- const files = folders.value.flatMap(
- /** @param {string} folder */ (folder) =>
- glob(`${folder}/**`, { filesOnly: true, dot: true })
- .map((file) => file.replace(/\\/g, '/'))
- .filter((file) => !file.includes('/node_modules/'))
- );
-
- for (const file of files) {
- if (extensions.some((ext) => file.endsWith(ext))) {
- if (svelte_extensions.some((ext) => file.endsWith(ext))) {
- update_svelte_file(file, transform_code, (code) =>
- transform_svelte_code(code, migrate_transition.value)
- );
- } else {
- update_js_file(file, transform_code);
- }
- }
- }
-
- console.log(colors.bold().green('✔ Your project has been migrated'));
-
- console.log('\nRecommended next steps:\n');
-
- const cyan = colors.bold().cyan;
-
- const tasks = [
- use_git && cyan('git commit -m "migration to Svelte 4"'),
- 'Review the migration guide at https://svelte.dev/docs/svelte/v4-migration-guide',
- 'Read the updated docs at https://svelte.dev/docs/svelte'
- ].filter(Boolean);
-
- tasks.forEach((task, i) => {
- console.log(` ${i + 1}: ${task}`);
- });
-
- console.log('');
-
- if (use_git) {
- console.log(`Run ${cyan('git diff')} to review changes.\n`);
- }
-}
diff --git a/packages/migrate/migrations/svelte-4/migrate.js b/packages/migrate/migrations/svelte-4/migrate.js
deleted file mode 100644
index c459380ef441..000000000000
--- a/packages/migrate/migrations/svelte-4/migrate.js
+++ /dev/null
@@ -1,348 +0,0 @@
-import fs from 'node:fs';
-import { Project, ts, Node, SyntaxKind } from 'ts-morph';
-import { log_migration, log_on_ts_modification, update_pkg } from '../../utils.js';
-
-export function update_pkg_json() {
- fs.writeFileSync(
- 'package.json',
- update_pkg_json_content(fs.readFileSync('package.json', 'utf8'))
- );
-}
-
-/**
- * @param {string} content
- */
-export function update_pkg_json_content(content) {
- return update_pkg(content, [
- ['svelte', '^4.0.0'],
- ['svelte-check', '^3.4.3'],
- ['svelte-preprocess', '^5.0.3'],
- ['@sveltejs/kit', '^1.20.4'],
- ['@sveltejs/vite-plugin-svelte', '^2.4.1'],
- [
- 'svelte-loader',
- '^3.1.8',
- ' (if you are still on webpack 4, you need to update to webpack 5)'
- ],
- ['rollup-plugin-svelte', '^7.1.5'],
- ['prettier-plugin-svelte', '^2.10.1'],
- ['eslint-plugin-svelte', '^2.30.0'],
- [
- 'eslint-plugin-svelte3',
- '^4.0.0',
- ' (this package is deprecated, use eslint-plugin-svelte instead. More info: https://svelte.dev/docs/svelte/v4-migration-guide#new-eslint-package)'
- ],
- [
- 'typescript',
- '^5.0.0',
- ' (this might introduce new type errors due to breaking changes within TypeScript)'
- ]
- ]);
-}
-
-/**
- * @param {string} code
- * @param {boolean} is_ts
- */
-export function transform_code(code, is_ts) {
- const project = new Project({ useInMemoryFileSystem: true });
- const source = project.createSourceFile('svelte.ts', code);
- update_imports(source, is_ts);
- update_typeof_svelte_component(source, is_ts);
- update_action_types(source, is_ts);
- update_action_return_types(source, is_ts);
- return source.getFullText();
-}
-
-/**
- * @param {string} code
- * @param {boolean} migrate_transition
- */
-export function transform_svelte_code(code, migrate_transition) {
- code = update_svelte_options(code);
- return update_transitions(code, migrate_transition);
-}
-
-/**
- * ->
- * @param {string} code
- */
-function update_svelte_options(code) {
- return code.replace(//, (match) => {
- log_migration(
- 'Replaced `svelte:options` `tag` attribute with `customElement` attribute: https://svelte.dev/docs/svelte/v4-migration-guide#custom-elements-with-svelte'
- );
- return match.replace('tag=', 'customElement=');
- });
-}
-
-/**
- * transition/in/out:x -> transition/in/out:x|global
- * transition/in/out|local:x -> transition/in/out:x
- * @param {string} code
- * @param {boolean} migrate_transition
- */
-function update_transitions(code, migrate_transition) {
- if (migrate_transition) {
- const replaced = code.replace(/(\s)(transition:|in:|out:)(\w+)(?=[\s>=])/g, '$1$2$3|global');
- if (replaced !== code) {
- log_migration(
- 'Added `|global` to `transition`, `in`, and `out` directives (transitions are local by default now): https://svelte.dev/docs/svelte/v4-migration-guide#transitions-are-local-by-default'
- );
- }
- code = replaced;
- }
- const replaced = code.replace(/(\s)(transition:|in:|out:)(\w+)(\|local)(?=[\s>=])/g, '$1$2$3');
- if (replaced !== code) {
- log_migration(
- 'Removed `|local` from `transition`, `in`, and `out` directives (transitions are local by default now): https://svelte.dev/docs/svelte/v4-migration-guide#transitions-are-local-by-default'
- );
- }
- return replaced;
-}
-
-/**
- * Action -> Action
- * @param {import('ts-morph').SourceFile} source
- * @param {boolean} is_ts
- */
-function update_action_types(source, is_ts) {
- const logger = log_on_ts_modification(
- source,
- 'Updated `Action` interface usages: https://svelte.dev/docs/svelte/v4-migration-guide#stricter-types-for-svelte-functions'
- );
-
- const imports = get_imports(source, 'svelte/action', 'Action');
- for (const namedImport of imports) {
- const identifiers = find_identifiers(source, namedImport.getAliasNode()?.getText() ?? 'Action');
- for (const id of identifiers) {
- const parent = id.getParent();
- if (Node.isTypeReference(parent)) {
- const type_args = parent.getTypeArguments();
- if (type_args.length === 1) {
- parent.addTypeArgument('any');
- } else if (type_args.length === 0) {
- parent.addTypeArgument('HTMLElement');
- parent.addTypeArgument('any');
- }
- }
- }
- }
-
- if (!is_ts) {
- replaceInJsDoc(source, (text) => {
- return text.replace(
- /import\((['"])svelte\/action['"]\).Action(<\w+>)?(?=[^<\w]|$)/g,
- (_, quote, type) =>
- `import(${quote}svelte/action${quote}).Action<${
- type ? type.slice(1, -1) + '' : 'HTMLElement'
- }, any>`
- );
- });
- }
-
- logger();
-}
-
-/**
- * ActionReturn -> ActionReturn
- * @param {import('ts-morph').SourceFile} source
- * @param {boolean} is_ts
- */
-function update_action_return_types(source, is_ts) {
- const logger = log_on_ts_modification(
- source,
- 'Updated `ActionReturn` interface usages: https://svelte.dev/docs/svelte/v4-migration-guide#stricter-types-for-svelte-functions'
- );
-
- const imports = get_imports(source, 'svelte/action', 'ActionReturn');
- for (const namedImport of imports) {
- const identifiers = find_identifiers(
- source,
- namedImport.getAliasNode()?.getText() ?? 'ActionReturn'
- );
- for (const id of identifiers) {
- const parent = id.getParent();
- if (Node.isTypeReference(parent)) {
- const type_args = parent.getTypeArguments();
- if (type_args.length === 0) {
- parent.addTypeArgument('any');
- }
- }
- }
- }
-
- if (!is_ts) {
- replaceInJsDoc(source, (text) => {
- return text.replace(
- /import\((['"])svelte\/action['"]\).ActionReturn(?=[^<\w]|$)/g,
- 'import($1svelte/action$1).ActionReturn'
- );
- });
- }
-
- logger();
-}
-
-/**
- * SvelteComponentTyped -> SvelteComponent
- * @param {import('ts-morph').SourceFile} source
- * @param {boolean} is_ts
- */
-function update_imports(source, is_ts) {
- const logger = log_on_ts_modification(
- source,
- 'Replaced `SvelteComponentTyped` imports with `SvelteComponent` imports: https://svelte.dev/docs/svelte/v4-migration-guide#stricter-types-for-svelte-functions'
- );
-
- const identifiers = find_identifiers(source, 'SvelteComponent');
- const can_rename = identifiers.every((id) => {
- const parent = id.getParent();
- return (
- (Node.isImportSpecifier(parent) &&
- !parent.getAliasNode() &&
- parent
- .getParent()
- .getParent()
- .getParentIfKind(SyntaxKind.ImportDeclaration)
- ?.getModuleSpecifier()
- .getText() === 'svelte') ||
- !is_declaration(parent)
- );
- });
-
- const imports = get_imports(source, 'svelte', 'SvelteComponentTyped');
- for (const namedImport of imports) {
- if (can_rename) {
- namedImport.renameAlias('SvelteComponent');
- if (
- namedImport
- .getParent()
- .getElements()
- .some((e) => !e.getAliasNode() && e.getNameNode().getText() === 'SvelteComponent')
- ) {
- namedImport.remove();
- } else {
- namedImport.setName('SvelteComponent');
- namedImport.removeAlias();
- }
- } else {
- namedImport.renameAlias('SvelteComponentTyped');
- namedImport.setName('SvelteComponent');
- }
- }
-
- if (!is_ts) {
- replaceInJsDoc(source, (text) => {
- return text.replace(
- /import\((['"])svelte['"]\)\.SvelteComponentTyped(?=\W|$)/g,
- 'import($1svelte$1).SvelteComponent'
- );
- });
- }
-
- logger();
-}
-
-/**
- * typeof SvelteComponent -> typeof SvelteComponent
- * @param {import('ts-morph').SourceFile} source
- * @param {boolean} is_ts
- */
-function update_typeof_svelte_component(source, is_ts) {
- const logger = log_on_ts_modification(
- source,
- 'Adjusted `typeof SvelteComponent` to `typeof SvelteComponent`: https://svelte.dev/docs/svelte/v4-migration-guide#stricter-types-for-svelte-functions'
- );
-
- const imports = get_imports(source, 'svelte', 'SvelteComponent');
-
- for (const type of imports) {
- if (type) {
- const name = type.getAliasNode() ?? type.getNameNode();
- if (Node.isIdentifier(name)) {
- name.findReferencesAsNodes().forEach((ref) => {
- const parent = ref.getParent();
- if (parent && Node.isTypeQuery(parent)) {
- const id = parent.getFirstChildByKind(ts.SyntaxKind.Identifier);
- if (id?.getText() === name.getText()) {
- const typeArguments = parent.getTypeArguments();
- if (typeArguments.length === 0) {
- parent.addTypeArgument('any');
- }
- }
- }
- });
- }
- }
- }
-
- if (!is_ts) {
- replaceInJsDoc(source, (text) => {
- return text.replace(
- /typeof import\((['"])svelte['"]\)\.SvelteComponent(?=[^<\w]|$)/g,
- 'typeof import($1svelte$1).SvelteComponent'
- );
- });
- }
-
- logger();
-}
-
-/**
- * @param {import('ts-morph').SourceFile} source
- * @param {string} from
- * @param {string} name
- */
-function get_imports(source, from, name) {
- return source
- .getImportDeclarations()
- .filter((i) => i.getModuleSpecifierValue() === from)
- .flatMap((i) => i.getNamedImports())
- .filter((i) => i.getName() === name);
-}
-
-/**
- * @param {import('ts-morph').SourceFile} source
- * @param {string} name
- */
-function find_identifiers(source, name) {
- return source.getDescendantsOfKind(ts.SyntaxKind.Identifier).filter((i) => i.getText() === name);
-}
-
-/**
- * Does not include imports
- * @param {Node} node
- */
-function is_declaration(node) {
- return (
- Node.isVariableDeclaration(node) ||
- Node.isFunctionDeclaration(node) ||
- Node.isClassDeclaration(node) ||
- Node.isTypeAliasDeclaration(node) ||
- Node.isInterfaceDeclaration(node)
- );
-}
-
-/**
- * @param {import('ts-morph').SourceFile} source
- * @param {(text: string) => string | undefined} replacer
- */
-function replaceInJsDoc(source, replacer) {
- source.forEachChild((node) => {
- if (Node.isJSDocable(node)) {
- const tags = node.getJsDocs().flatMap((jsdoc) => jsdoc.getTags());
- tags.forEach((t) =>
- t.forEachChild((c) => {
- if (Node.isJSDocTypeExpression(c)) {
- const text = c.getText().slice(1, -1);
- const replacement = replacer(text);
- if (replacement && replacement !== text) {
- c.replaceWithText(`{${replacement}}`);
- }
- }
- })
- );
- }
- });
-}
diff --git a/packages/migrate/migrations/svelte-4/migrate.spec.js b/packages/migrate/migrations/svelte-4/migrate.spec.js
deleted file mode 100644
index f0c34cddd1da..000000000000
--- a/packages/migrate/migrations/svelte-4/migrate.spec.js
+++ /dev/null
@@ -1,382 +0,0 @@
-import { assert, test } from 'vitest';
-import { transform_code, transform_svelte_code, update_pkg_json_content } from './migrate.js';
-
-test('Updates SvelteComponentTyped #1', () => {
- const result = transform_code(
- `import { SvelteComponentTyped } from 'svelte';
-
-export class Foo extends SvelteComponentTyped<{}> {}
-
-const bar: SvelteComponentTyped = null;`,
- true
- );
- assert.equal(
- result,
- `import { SvelteComponent } from 'svelte';
-
-export class Foo extends SvelteComponent<{}> {}
-
-const bar: SvelteComponent = null;`
- );
-});
-
-test('Updates SvelteComponentTyped #2', () => {
- const result = transform_code(
- `import { SvelteComponentTyped, SvelteComponent } from 'svelte';
-
-export class Foo extends SvelteComponentTyped<{}> {}
-
-const bar: SvelteComponentTyped = null;
-const baz: SvelteComponent = null;`,
- true
- );
- assert.equal(
- result,
- `import { SvelteComponent } from 'svelte';
-
-export class Foo extends SvelteComponent<{}> {}
-
-const bar: SvelteComponent = null;
-const baz: SvelteComponent = null;`
- );
-});
-
-test('Updates SvelteComponentTyped #3', () => {
- const result = transform_code(
- `import { SvelteComponentTyped } from 'svelte';
-
-interface SvelteComponent {}
-
-export class Foo extends SvelteComponentTyped<{}> {}
-
-const bar: SvelteComponentTyped = null;
-const baz: SvelteComponent = null;`,
- true
- );
- assert.equal(
- result,
- `import { SvelteComponent as SvelteComponentTyped } from 'svelte';
-
-interface SvelteComponent {}
-
-export class Foo extends SvelteComponentTyped<{}> {}
-
-const bar: SvelteComponentTyped = null;
-const baz: SvelteComponent = null;`
- );
-});
-
-test('Updates SvelteComponentTyped (jsdoc)', () => {
- const result = transform_code(
- `
- /** @type {import('svelte').SvelteComponentTyped} */
- const bar = null;
- /** @type {import('svelte').SvelteComponentTyped} */
- const baz = null;
- `,
- false
- );
- assert.equal(
- result,
- `
- /** @type {import('svelte').SvelteComponent} */
- const bar = null;
- /** @type {import('svelte').SvelteComponent} */
- const baz = null;
- `
- );
-});
-
-test('Updates typeof SvelteComponent', () => {
- const result = transform_code(
- `import { SvelteComponent } from 'svelte';
- import { SvelteComponent as C } from 'svelte';
-
- const a: typeof SvelteComponent = null;
- function b(c: typeof SvelteComponent) {}
- const c: typeof SvelteComponent = null;
- const d: typeof C = null;
- `,
- true
- );
- assert.equal(
- result,
- `import { SvelteComponent } from 'svelte';
- import { SvelteComponent as C } from 'svelte';
-
- const a: typeof SvelteComponent = null;
- function b(c: typeof SvelteComponent) {}
- const c: typeof SvelteComponent = null;
- const d: typeof C = null;
- `
- );
-});
-
-test('Updates typeof SvelteComponent (jsdoc)', () => {
- const result = transform_code(
- `
- /** @type {typeof import('svelte').SvelteComponent} */
- const a = null;
- /** @type {typeof import('svelte').SvelteComponent} */
- const c = null;
- /** @type {typeof C} */
- const d: typeof C = null;
- `,
- false
- );
- assert.equal(
- result,
- `
- /** @type {typeof import('svelte').SvelteComponent} */
- const a = null;
- /** @type {typeof import('svelte').SvelteComponent} */
- const c = null;
- /** @type {typeof C} */
- const d: typeof C = null;
- `
- );
-});
-
-test('Updates Action and ActionReturn', () => {
- const result = transform_code(
- `import type { Action, ActionReturn } from 'svelte/action';
-
- const a: Action = () => {};
- const b: Action = () => {};
- const c: Action = () => {};
- const d: Action = () => {};
- const e: ActionReturn = () => {};
- const f: ActionReturn = () => {};
- const g: ActionReturn = () => {};
- `,
- true
- );
- assert.equal(
- result,
-
- `import type { Action, ActionReturn } from 'svelte/action';
-
- const a: Action = () => {};
- const b: Action = () => {};
- const c: Action = () => {};
- const d: Action = () => {};
- const e: ActionReturn = () => {};
- const f: ActionReturn = () => {};
- const g: ActionReturn = () => {};
- `
- );
-});
-
-test('Updates Action and ActionReturn (jsdoc)', () => {
- const result = transform_code(
- `
- /** @type {import('svelte/action').Action} */
- const a = () => {};
- /** @type {import('svelte/action').Action} */
- const b = () => {};
- /** @type {import('svelte/action').Action} */
- const c = () => {};
- /** @type {import('svelte/action').Action} */
- const d = () => {};
- /** @type {import('svelte/action').ActionReturn} */
- const e = () => {};
- /** @type {import('svelte/action').ActionReturn} */
- const f = () => {};
- /** @type {import('svelte/action').ActionReturn} */
- const g = () => {};
- `,
- false
- );
- assert.equal(
- result,
-
- `
- /** @type {import('svelte/action').Action} */
- const a = () => {};
- /** @type {import('svelte/action').Action} */
- const b = () => {};
- /** @type {import('svelte/action').Action} */
- const c = () => {};
- /** @type {import('svelte/action').Action} */
- const d = () => {};
- /** @type {import('svelte/action').ActionReturn} */
- const e = () => {};
- /** @type {import('svelte/action').ActionReturn} */
- const f = () => {};
- /** @type {import('svelte/action').ActionReturn} */
- const g = () => {};
- `
- );
-});
-
-test('Updates svelte:options #1', () => {
- const result = transform_svelte_code(
- `
-
- hi
`,
- true
- );
- assert.equal(
- result,
- `
-
- hi
`
- );
-});
-
-test('Updates svelte:options #2', () => {
- const result = transform_svelte_code(
- `
-
-
-
- hi
`,
- true
- );
- assert.equal(
- result,
- `
-
-
-
- hi
`
- );
-});
-
-test('Updates transitions', () => {
- const result = transform_svelte_code(
- `
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- `,
- true
- );
- assert.equal(
- result,
- `
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- `
- );
-});
-
-test('Updates transitions #2', () => {
- const result = transform_svelte_code(
- `
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- `,
- false
- );
- assert.equal(
- result,
- `
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- `
- );
-});
-
-test('Update package.json', () => {
- const result = update_pkg_json_content(`{
- "name": "svelte-app",
- "version": "1.0.0",
- "devDependencies": {
- "svelte": "^3.0.0",
- "svelte-check": "^1.0.0",
- "svelte-preprocess": "^5.0.0"
- },
- "dependencies": {
- "@sveltejs/kit": "^1.0.0"
- }
-}`);
- assert.equal(
- result,
- `{
- "name": "svelte-app",
- "version": "1.0.0",
- "devDependencies": {
- "svelte": "^4.0.0",
- "svelte-check": "^3.4.3",
- "svelte-preprocess": "^5.0.3"
- },
- "dependencies": {
- "@sveltejs/kit": "^1.20.4"
- }
-}`
- );
-});
-
-test('Does not downgrade versions', () => {
- const result = update_pkg_json_content(`{
- "devDependencies": {
- "svelte": "^4.0.5",
- "typescript": "github:idk"
- }
-}`);
- assert.equal(
- result,
- `{
- "devDependencies": {
- "svelte": "^4.0.5",
- "typescript": "github:idk"
- }
-}`
- );
-});
diff --git a/packages/migrate/migrations/svelte-5/index.js b/packages/migrate/migrations/svelte-5/index.js
deleted file mode 100644
index a6b17d421232..000000000000
--- a/packages/migrate/migrations/svelte-5/index.js
+++ /dev/null
@@ -1,216 +0,0 @@
-import { resolve } from 'import-meta-resolve';
-import colors from 'kleur';
-import { execSync } from 'node:child_process';
-import process from 'node:process';
-import fs from 'node:fs';
-import { dirname } from 'node:path';
-import { fileURLToPath, pathToFileURL } from 'node:url';
-import prompts from 'prompts';
-import semver from 'semver';
-import glob from 'tiny-glob/sync.js';
-import { bail, check_git, update_js_file, update_svelte_file } from '../../utils.js';
-import { migrate as migrate_svelte_4 } from '../svelte-4/index.js';
-import { migrate as migrate_sveltekit_2 } from '../sveltekit-2/index.js';
-import { transform_module_code, transform_svelte_code, update_pkg_json } from './migrate.js';
-
-export async function migrate() {
- if (!fs.existsSync('package.json')) {
- bail('Please re-run this script in a directory with a package.json');
- }
-
- console.log(
- 'This migration is experimental — please report any bugs to https://github.com/sveltejs/svelte/issues'
- );
-
- const pkg = JSON.parse(fs.readFileSync('package.json', 'utf8'));
-
- const svelte_dep = pkg.devDependencies?.svelte ?? pkg.dependencies?.svelte;
- if (svelte_dep && semver.validRange(svelte_dep) && semver.gtr('4.0.0', svelte_dep)) {
- console.log(
- colors
- .bold()
- .yellow(
- '\nDetected Svelte 3. You need to upgrade to Svelte version 4 first (`npx sv migrate svelte-4`).\n'
- )
- );
- const response = await prompts({
- type: 'confirm',
- name: 'value',
- message: 'Run svelte-4 migration now?',
- initial: false
- });
- if (!response.value) {
- process.exit(1);
- } else {
- await migrate_svelte_4();
- console.log(
- colors
- .bold()
- .green(
- 'svelte-4 migration complete. Check that everything is ok, then run `npx sv migrate svelte-5` again to continue the Svelte 5 migration.\n'
- )
- );
- process.exit(0);
- }
- }
-
- const kit_dep = pkg.devDependencies?.['@sveltejs/kit'] ?? pkg.dependencies?.['@sveltejs/kit'];
- if (kit_dep && semver.validRange(kit_dep) && semver.gtr('2.0.0', kit_dep)) {
- console.log(
- colors
- .bold()
- .yellow(
- '\nDetected SvelteKit 1. You need to upgrade to SvelteKit version 2 first (`npx sv migrate sveltekit-2`).\n'
- )
- );
- const response = await prompts({
- type: 'confirm',
- name: 'value',
- message: 'Run sveltekit-2 migration now?',
- initial: false
- });
- if (!response.value) {
- process.exit(1);
- } else {
- await migrate_sveltekit_2();
- console.log(
- colors
- .bold()
- .green(
- 'sveltekit-2 migration complete. Check that everything is ok, then run `npx sv migrate svelte-5` again to continue the Svelte 5 migration.\n'
- )
- );
- process.exit(0);
- }
- }
-
- let migrate;
- try {
- try {
- ({ migrate } = await import_from_cwd('svelte/compiler'));
- if (!migrate) throw new Error('found Svelte 4');
- } catch {
- execSync('npm install svelte@^5.0.0 --no-save', {
- stdio: 'inherit',
- cwd: dirname(fileURLToPath(import.meta.url))
- });
- const url = resolve('svelte/compiler', import.meta.url);
- ({ migrate } = await import(url));
- }
- } catch (e) {
- console.log(e);
- console.log(
- colors
- .bold()
- .red(
- '❌ Could not install Svelte. Manually bump the dependency to version 5 in your package.json, install it, then try again.'
- )
- );
- return;
- }
-
- console.log(
- colors
- .bold()
- .yellow(
- '\nThis will update files in the current directory\n' +
- "If you're inside a monorepo, don't run this in the root directory, rather run it in all projects independently.\n"
- )
- );
-
- const use_git = check_git();
-
- const response = await prompts({
- type: 'confirm',
- name: 'value',
- message: 'Continue?',
- initial: false
- });
-
- if (!response.value) {
- process.exit(1);
- }
-
- const folders = await prompts({
- type: 'multiselect',
- name: 'value',
- message: 'Which folders should be migrated?',
- choices: fs
- .readdirSync('.')
- .filter(
- (dir) => fs.statSync(dir).isDirectory() && dir !== 'node_modules' && !dir.startsWith('.')
- )
- .map((dir) => ({ title: dir, value: dir, selected: true }))
- });
-
- if (!folders.value?.length) {
- process.exit(1);
- }
-
- update_pkg_json();
-
- const use_ts = fs.existsSync('tsconfig.json');
-
- // const { default: config } = fs.existsSync('svelte.config.js')
- // ? await import(pathToFileURL(path.resolve('svelte.config.js')).href)
- // : { default: {} };
-
- /** @type {string[]} */
- const svelte_extensions = /* config.extensions ?? - disabled because it would break .svx */ [
- '.svelte'
- ];
- const extensions = [...svelte_extensions, '.ts', '.js'];
- // For some reason {folders.value.join(',')} as part of the glob doesn't work and returns less files
- const files = folders.value.flatMap(
- /** @param {string} folder */ (folder) =>
- glob(`${folder}/**`, { filesOnly: true, dot: true })
- .map((file) => file.replace(/\\/g, '/'))
- .filter((file) => !file.includes('/node_modules/'))
- );
-
- for (const file of files) {
- if (extensions.some((ext) => file.endsWith(ext))) {
- if (svelte_extensions.some((ext) => file.endsWith(ext))) {
- update_svelte_file(file, transform_module_code, (code) =>
- transform_svelte_code(code, migrate, { filename: file, use_ts })
- );
- } else {
- update_js_file(file, transform_module_code);
- }
- }
- }
-
- console.log(colors.bold().green('✔ Your project has been migrated'));
-
- console.log('\nRecommended next steps:\n');
-
- const cyan = colors.bold().cyan;
-
- const tasks = [
- "install the updated dependencies ('npm i' / 'pnpm i' / etc) " +
- '(note that there may be peer dependency issues when not all your libraries officially support Svelte 5 yet. In this case try installing with the --force option)',
- use_git && cyan('git commit -m "migration to Svelte 5"'),
- 'Review the breaking changes at https://svelte-5-preview.vercel.app/docs/breaking-changes'
- // replace with this once it's live:
- // 'Review the migration guide at https://svelte.dev/docs/svelte/v5-migration-guide',
- // 'Read the updated docs at https://svelte.dev/docs/svelte'
- ].filter(Boolean);
-
- tasks.forEach((task, i) => {
- console.log(` ${i + 1}: ${task}`);
- });
-
- console.log('');
-
- if (use_git) {
- console.log(`Run ${cyan('git diff')} to review changes.\n`);
- }
-}
-
-/** @param {string} name */
-function import_from_cwd(name) {
- const cwd = pathToFileURL(process.cwd()).href;
- const url = resolve(name, cwd + '/x.js');
-
- return import(url);
-}
diff --git a/packages/migrate/migrations/svelte-5/migrate.js b/packages/migrate/migrations/svelte-5/migrate.js
deleted file mode 100644
index eb9e750f46a0..000000000000
--- a/packages/migrate/migrations/svelte-5/migrate.js
+++ /dev/null
@@ -1,129 +0,0 @@
-import fs from 'node:fs';
-import { Project, ts, Node } from 'ts-morph';
-import { add_named_import, update_pkg } from '../../utils.js';
-
-export function update_pkg_json() {
- fs.writeFileSync(
- 'package.json',
- update_pkg_json_content(fs.readFileSync('package.json', 'utf8'))
- );
-}
-
-/**
- * @param {string} content
- */
-export function update_pkg_json_content(content) {
- return update_pkg(content, [
- ['svelte', '^5.0.0'],
- ['svelte-check', '^4.0.0'],
- ['svelte-preprocess', '^6.0.0'],
- ['@sveltejs/enhanced-img', '^0.3.9'],
- ['@sveltejs/kit', '^2.5.27'],
- ['@sveltejs/vite-plugin-svelte', '^4.0.0'],
- [
- 'svelte-loader',
- '^3.2.3',
- ' (if you are still on webpack 4, you need to update to webpack 5)'
- ],
- ['rollup-plugin-svelte', '^7.2.2'],
- ['prettier', '^3.1.0'],
- ['prettier-plugin-svelte', '^3.2.6'],
- ['eslint-plugin-svelte', '^2.45.1'],
- ['svelte-eslint-parser', '^0.42.0'],
- [
- 'eslint-plugin-svelte3',
- '^4.0.0',
- ' (this package is deprecated, use eslint-plugin-svelte instead. More info: https://svelte.dev/docs/svelte/v4-migration-guide#new-eslint-package)'
- ],
- [
- 'typescript',
- '^5.5.0',
- ' (this might introduce new type errors due to breaking changes within TypeScript)'
- ],
- ['vite', '^5.4.4']
- ]);
-}
-
-/**
- * @param {string} code
- */
-export function transform_module_code(code) {
- const project = new Project({ useInMemoryFileSystem: true });
- const source = project.createSourceFile('svelte.ts', code);
- update_component_instantiation(source);
- return source.getFullText();
-}
-
-/**
- * @param {string} code
- * @param {(source: string, options: { filename?: string, use_ts?: boolean }) => { code: string }} transform_code
- * @param {{ filename?: string, use_ts?: boolean }} options
- */
-export function transform_svelte_code(code, transform_code, options) {
- return transform_code(code, options).code;
-}
-
-/**
- * new Component(...) -> mount(Component, ...)
- * @param {import('ts-morph').SourceFile} source
- */
-function update_component_instantiation(source) {
- const imports = source
- .getImportDeclarations()
- .filter((i) => i.getModuleSpecifierValue().endsWith('.svelte'))
- .flatMap((i) => i.getDefaultImport() || []);
-
- for (const defaultImport of imports) {
- const identifiers = find_identifiers(source, defaultImport.getText());
-
- for (const id of identifiers) {
- const parent = id.getParent();
-
- if (Node.isNewExpression(parent)) {
- const args = parent.getArguments();
-
- if (args.length === 1) {
- const method =
- Node.isObjectLiteralExpression(args[0]) && !!args[0].getProperty('hydrate')
- ? 'hydrate'
- : 'mount';
-
- if (method === 'hydrate') {
- /** @type {import('ts-morph').ObjectLiteralExpression} */ (args[0])
- .getProperty('hydrate')
- ?.remove();
- }
-
- add_named_import(source, 'svelte', method);
-
- const declaration = parent
- .getParentIfKind(ts.SyntaxKind.VariableDeclaration)
- ?.getNameNode();
- if (Node.isIdentifier(declaration)) {
- const usages = declaration.findReferencesAsNodes();
- for (const usage of usages) {
- const parent = usage.getParent();
- if (Node.isPropertyAccessExpression(parent) && parent.getName() === '$destroy') {
- const call_expr = parent.getParentIfKind(ts.SyntaxKind.CallExpression);
- if (call_expr) {
- call_expr.replaceWithText(`unmount(${usage.getText()})`);
- add_named_import(source, 'svelte', 'unmount');
- }
- }
- }
- }
-
- parent.replaceWithText(`${method}(${id.getText()}, ${args[0].getText()})`);
- }
- }
- }
- }
-}
-
-/**
- * @param {import('ts-morph').SourceFile} source
- * @param {string} name
- */
-function find_identifiers(source, name) {
- return source.getDescendantsOfKind(ts.SyntaxKind.Identifier).filter((i) => i.getText() === name);
-}
diff --git a/packages/migrate/migrations/svelte-5/migrate.spec.js b/packages/migrate/migrations/svelte-5/migrate.spec.js
deleted file mode 100644
index 0f9e3e6d4db6..000000000000
--- a/packages/migrate/migrations/svelte-5/migrate.spec.js
+++ /dev/null
@@ -1,135 +0,0 @@
-import { assert, test } from 'vitest';
-import { transform_module_code, update_pkg_json_content } from './migrate.js';
-
-test('Updates component creation #1', () => {
- const result = transform_module_code(
- `import App from './App.svelte'
-
-const app = new App({
- target: document.getElementById('app')!
-})
-
-export default app`
- );
- assert.equal(
- result,
- `import App from './App.svelte'
-import { mount } from "svelte";
-
-const app = mount(App, {
- target: document.getElementById('app')!
-})
-
-export default app`
- );
-});
-
-test('Updates component creation #2', () => {
- const result = transform_module_code(
- `import App from './App.svelte'
-
-new App({
- target: document.getElementById('app')!,
- hydrate: true
-})`
- );
- assert.equal(
- result,
- `import App from './App.svelte'
-import { hydrate } from "svelte";
-
-hydrate(App, {
- target: document.getElementById('app')!
-})`
- );
-});
-
-test('Updates component creation #3', () => {
- const result = transform_module_code(
- `import App from './App.svelte'
-
-const x = new App({
- target: document.getElementById('app')!
-});
-
-function destroy() {
- x.$destroy();
-}
-`
- );
- assert.equal(
- result,
- `import App from './App.svelte'
-import { mount, unmount } from "svelte";
-
-const x = mount(App, {
- target: document.getElementById('app')!
-});
-
-function destroy() {
- unmount(x);
-}
-`
- );
-});
-
-test('Updates component creation with multiple components', () => {
- const result = transform_module_code(
- `import App from './App.svelte';
-import Child from './Child.svelte';
-
-const x = new App({
- target: document.getElementById('app')!
-});
-const y = new Child({
- target: document.getElementById('child')!
-});
-`
- );
- assert.equal(
- result,
- `import App from './App.svelte';
-import Child from './Child.svelte';
-import { mount } from "svelte";
-
-const x = mount(App, {
- target: document.getElementById('app')!
-});
-const y = mount(Child, {
- target: document.getElementById('child')!
-});
-`
- );
-});
-
-test('Update package.json', () => {
- const result = update_pkg_json_content(`{
- "name": "svelte-app",
- "version": "1.0.0",
- "devDependencies": {
- "svelte": "^4.0.0",
- "svelte-check": "^3.0.0",
- "svelte-preprocess": "^5.0.0",
- "svelte-eslint-parser": "^0.41.1"
- },
- "dependencies": {
- "@sveltejs/kit": "^2.0.0"
- }
-}`);
- assert.equal(
- result,
- `{
- "name": "svelte-app",
- "version": "1.0.0",
- "devDependencies": {
- "svelte": "^5.0.0",
- "svelte-check": "^4.0.0",
- "svelte-preprocess": "^6.0.0",
- "svelte-eslint-parser": "^0.42.0"
- },
- "dependencies": {
- "@sveltejs/kit": "^2.5.27"
- }
-}`
- );
-});
diff --git a/packages/migrate/migrations/sveltekit-2/index.js b/packages/migrate/migrations/sveltekit-2/index.js
deleted file mode 100644
index c62442aba5b2..000000000000
--- a/packages/migrate/migrations/sveltekit-2/index.js
+++ /dev/null
@@ -1,167 +0,0 @@
-import colors from 'kleur';
-import fs from 'node:fs';
-import process from 'node:process';
-import prompts from 'prompts';
-import semver from 'semver';
-import glob from 'tiny-glob/sync.js';
-import {
- bail,
- check_git,
- update_js_file,
- update_svelte_file,
- update_tsconfig
-} from '../../utils.js';
-import { migrate as migrate_svelte_4 } from '../svelte-4/index.js';
-import {
- transform_code,
- update_pkg_json,
- update_svelte_config,
- update_tsconfig_content
-} from './migrate.js';
-
-export async function migrate() {
- if (!fs.existsSync('package.json')) {
- bail('Please re-run this script in a directory with a package.json');
- }
-
- if (!fs.existsSync('svelte.config.js')) {
- bail('Please re-run this script in a directory with a svelte.config.js');
- }
-
- console.log(
- colors
- .bold()
- .yellow(
- '\nThis will update files in the current directory\n' +
- "If you're inside a monorepo, run this in individual project directories rather than the workspace root.\n"
- )
- );
-
- const use_git = check_git();
-
- const response = await prompts({
- type: 'confirm',
- name: 'value',
- message: 'Continue?',
- initial: false
- });
-
- if (!response.value) {
- process.exit(1);
- }
-
- const pkg = JSON.parse(fs.readFileSync('package.json', 'utf8'));
- const svelte_dep = pkg.devDependencies?.svelte ?? pkg.dependencies?.svelte;
- if (svelte_dep === undefined) {
- bail('Please install Svelte before continuing');
- }
-
- if (semver.validRange(svelte_dep) && semver.gtr('4.0.0', svelte_dep)) {
- console.log(
- colors
- .bold()
- .yellow(
- '\nSvelteKit 2 requires Svelte 4 or newer. We recommend running the `svelte-4` migration first (`npx sv migrate svelte-4`).\n'
- )
- );
- const response = await prompts({
- type: 'confirm',
- name: 'value',
- message: 'Run `svelte-4` migration now?',
- initial: false
- });
- if (!response.value) {
- process.exit(1);
- } else {
- await migrate_svelte_4();
- console.log(
- colors
- .bold()
- .green('`svelte-4` migration complete. Continue with `sveltekit-2` migration?\n')
- );
- const response = await prompts({
- type: 'confirm',
- name: 'value',
- message: 'Continue?',
- initial: false
- });
- if (!response.value) {
- process.exit(1);
- }
- }
- }
-
- const folders = await prompts({
- type: 'multiselect',
- name: 'value',
- message: 'Which folders should be migrated?',
- choices: fs
- .readdirSync('.')
- .filter(
- (dir) =>
- fs.statSync(dir).isDirectory() &&
- dir !== 'node_modules' &&
- dir !== 'dist' &&
- !dir.startsWith('.')
- )
- .map((dir) => ({ title: dir, value: dir, selected: dir === 'src' }))
- });
-
- if (!folders.value?.length) {
- process.exit(1);
- }
-
- update_pkg_json();
- update_tsconfig(update_tsconfig_content);
- update_svelte_config();
-
- // const { default: config } = fs.existsSync('svelte.config.js')
- // ? await import(pathToFileURL(path.resolve('svelte.config.js')).href)
- // : { default: {} };
-
- /** @type {string[]} */
- const svelte_extensions = /* config.extensions ?? - disabled because it would break .svx */ [
- '.svelte'
- ];
- const extensions = [...svelte_extensions, '.ts', '.js'];
- // For some reason {folders.value.join(',')} as part of the glob doesn't work and returns less files
- const files = folders.value.flatMap(
- /** @param {string} folder */ (folder) =>
- glob(`${folder}/**`, { filesOnly: true, dot: true })
- .map((file) => file.replace(/\\/g, '/'))
- .filter((file) => !file.includes('/node_modules/'))
- );
-
- for (const file of files) {
- if (extensions.some((ext) => file.endsWith(ext))) {
- if (svelte_extensions.some((ext) => file.endsWith(ext))) {
- update_svelte_file(file, transform_code, (code) => code);
- } else {
- update_js_file(file, transform_code);
- }
- }
- }
-
- console.log(colors.bold().green('✔ Your project has been migrated'));
-
- console.log('\nRecommended next steps:\n');
-
- const cyan = colors.bold().cyan;
-
- const tasks = [
- 'Run npm install (or the corresponding installation command of your package manager)',
- use_git && cyan('git commit -m "migration to SvelteKit 2"'),
- 'Review the migration guide at https://svelte.dev/docs/kit/migrating-to-sveltekit-2',
- 'Read the updated docs at https://svelte.dev/docs/kit'
- ].filter(Boolean);
-
- tasks.forEach((task, i) => {
- console.log(` ${i + 1}: ${task}`);
- });
-
- console.log('');
-
- if (use_git) {
- console.log(`Run ${cyan('git diff')} to review changes.\n`);
- }
-}
diff --git a/packages/migrate/migrations/sveltekit-2/migrate.js b/packages/migrate/migrations/sveltekit-2/migrate.js
deleted file mode 100644
index 9657be37d480..000000000000
--- a/packages/migrate/migrations/sveltekit-2/migrate.js
+++ /dev/null
@@ -1,318 +0,0 @@
-import fs from 'node:fs';
-import { Project, Node, SyntaxKind } from 'ts-morph';
-import {
- add_named_import,
- log_migration,
- log_on_ts_modification,
- update_pkg
-} from '../../utils.js';
-import path from 'node:path';
-
-export function update_pkg_json() {
- fs.writeFileSync(
- 'package.json',
- update_pkg_json_content(fs.readFileSync('package.json', 'utf8'))
- );
-}
-
-/**
- * @param {string} content
- */
-export function update_pkg_json_content(content) {
- return update_pkg(content, [
- // All other bumps are done as part of the Svelte 4 migration
- ['@sveltejs/kit', '^2.0.0'],
- ['@sveltejs/adapter-static', '^3.0.0'],
- ['@sveltejs/adapter-node', '^2.0.0'],
- ['@sveltejs/adapter-vercel', '^4.0.0'],
- ['@sveltejs/adapter-netlify', '^3.0.0'],
- ['@sveltejs/adapter-cloudflare', '^3.0.0'],
- ['@sveltejs/adapter-cloudflare-workers', '^2.0.0'],
- ['@sveltejs/adapter-auto', '^3.0.0'],
- ['vite', '^5.0.0'],
- ['vitest', '^1.0.0'],
- ['typescript', '^5.0.0'], // should already be done by Svelte 4 migration, but who knows
- [
- '@sveltejs/vite-plugin-svelte',
- '^3.0.0',
- ' (vite-plugin-svelte is a peer dependency of SvelteKit now)',
- 'devDependencies'
- ]
- ]);
-}
-
-/** @param {string} content */
-export function update_tsconfig_content(content) {
- if (!content.includes('"extends"')) {
- // Don't touch the tsconfig if people opted out of our default config
- return content;
- }
-
- let updated = content
- .split('\n')
- .filter(
- (line) => !line.includes('importsNotUsedAsValues') && !line.includes('preserveValueImports')
- )
- .join('\n');
- if (updated !== content) {
- log_migration(
- 'Removed deprecated `importsNotUsedAsValues` and `preserveValueImports`' +
- ' from tsconfig.json: https://svelte.dev/docs/kit/migrating-to-sveltekit-2#updated-dependency-requirements'
- );
- }
-
- content = updated;
- updated = content.replace('"moduleResolution": "node"', '"moduleResolution": "bundler"');
- if (updated !== content) {
- log_migration(
- 'Updated `moduleResolution` to `bundler`' +
- ' in tsconfig.json: https://svelte.dev/docs/kit/migrating-to-sveltekit-2#updated-dependency-requirements'
- );
- }
-
- if (content.includes('"paths":') || content.includes('"baseUrl":')) {
- log_migration(
- '`paths` and/or `baseUrl` detected in your tsconfig.json - remove it and use `kit.alias` instead: https://svelte.dev/docs/kit/migrating-to-sveltekit-2#generated-tsconfig-json-is-more-strict'
- );
- }
-
- return updated;
-}
-
-export function update_svelte_config() {
- fs.writeFileSync(
- 'svelte.config.js',
- update_svelte_config_content(fs.readFileSync('svelte.config.js', 'utf8'))
- );
-}
-
-/**
- * @param {string} code
- */
-export function update_svelte_config_content(code) {
- const regex = /\s*dangerZone:\s*{[^}]*},?/g;
- const result = code.replace(regex, '');
- if (result !== code) {
- log_migration(
- 'Removed `dangerZone` from svelte.config.js: https://svelte.dev/docs/kit/migrating-to-sveltekit-2#server-fetches-are-not-trackable-anymore'
- );
- }
-
- const project = new Project({ useInMemoryFileSystem: true });
- const source = project.createSourceFile('svelte.ts', result);
-
- const namedImport = get_import(source, '@sveltejs/kit/vite', 'vitePreprocess');
- if (!namedImport) return result;
-
- const logger = log_on_ts_modification(
- source,
- 'Changed `vitePreprocess` import: https://svelte.dev/docs/kit/migrating-to-sveltekit-2#vitepreprocess-is-no-longer-exported-from-sveltejs-kit-vite'
- );
-
- if (namedImport.getParent().getParent().getNamedImports().length === 1) {
- namedImport
- .getParent()
- .getParent()
- .getParentIfKind(SyntaxKind.ImportDeclaration)
- ?.setModuleSpecifier('@sveltejs/vite-plugin-svelte');
- } else {
- namedImport.remove();
- add_named_import(source, '@sveltejs/vite-plugin-svelte', 'vitePreprocess');
- }
-
- logger();
- return source.getFullText();
-}
-
-/**
- * @param {string} code
- * @param {boolean} _is_ts
- * @param {string} file_path
- */
-export function transform_code(code, _is_ts, file_path) {
- const project = new Project({ useInMemoryFileSystem: true });
- const source = project.createSourceFile('svelte.ts', code);
- remove_throws(source);
- add_cookie_note(file_path, source);
- replace_resolve_path(source);
- return source.getFullText();
-}
-
-/**
- * `throw redirect(..)` -> `redirect(..)`
- * @param {import('ts-morph').SourceFile} source
- */
-function remove_throws(source) {
- const logger = log_on_ts_modification(
- source,
- 'Removed `throw` from redirect/error functions: https://svelte.dev/docs/kit/migrating-to-sveltekit-2#redirect-and-error-are-no-longer-thrown-by-you'
- );
-
- /** @param {string} id */
- function remove_throw(id) {
- const named_import = get_import(source, '@sveltejs/kit', id);
- if (!named_import) return;
- const name_node = named_import.getNameNode();
- if (Node.isIdentifier(name_node)) {
- for (const id of name_node.findReferencesAsNodes()) {
- const call_expression = id.getParent();
- const throw_stmt = call_expression?.getParent();
- if (Node.isCallExpression(call_expression) && Node.isThrowStatement(throw_stmt)) {
- throw_stmt.replaceWithText((writer) => {
- writer.setIndentationLevel(0);
- writer.write(call_expression.getText() + ';');
- });
- }
- }
- }
- }
-
- remove_throw('redirect');
- remove_throw('error');
-
- logger();
-}
-
-/**
- * Adds `path` option to `cookies.set/delete/serialize` calls
- * @param {string} file_path
- * @param {import('ts-morph').SourceFile} source
- */
-function add_cookie_note(file_path, source) {
- const basename = path.basename(file_path);
- if (
- basename !== '+page.js' &&
- basename !== '+page.ts' &&
- basename !== '+page.server.js' &&
- basename !== '+page.server.ts' &&
- basename !== '+server.js' &&
- basename !== '+server.ts' &&
- basename !== 'hooks.server.js' &&
- basename !== 'hooks.server.ts'
- ) {
- return;
- }
-
- const logger = log_on_ts_modification(
- source,
- 'Search codebase for `@migration` and manually add the `path` option to `cookies.set/delete/serialize` calls: https://svelte.dev/docs/kit/migrating-to-sveltekit-2#path-is-now-a-required-option-for-cookies'
- );
-
- const calls = [];
-
- for (const call of source.getDescendantsOfKind(SyntaxKind.CallExpression)) {
- const expression = call.getExpression();
- if (!Node.isPropertyAccessExpression(expression)) {
- continue;
- }
-
- const name = expression.getName();
- if (name !== 'set' && name !== 'delete' && name !== 'serialize') {
- continue;
- }
-
- if (call.getText().includes('path')) {
- continue;
- }
-
- const options_arg = call.getArguments()[name === 'delete' ? 1 : 2];
- if (options_arg && !Node.isObjectLiteralExpression(options_arg)) {
- continue;
- }
-
- const parent_function = call.getFirstAncestor(
- /** @returns {ancestor is import('ts-morph').FunctionDeclaration | import('ts-morph').FunctionExpression | import('ts-morph').ArrowFunction} */
- (ancestor) => {
- // Check if this is inside a function
- const fn_declaration = ancestor.asKind(SyntaxKind.FunctionDeclaration);
- const fn_expression = ancestor.asKind(SyntaxKind.FunctionExpression);
- const arrow_fn_expression = ancestor.asKind(SyntaxKind.ArrowFunction);
- return !!fn_declaration || !!fn_expression || !!arrow_fn_expression;
- }
- );
- if (!parent_function) {
- continue;
- }
-
- const expression_text = expression.getExpression().getText();
- if (
- expression_text !== 'cookies' &&
- (!expression_text.includes('.') ||
- expression_text.split('.').pop() !== 'cookies' ||
- !parent_function.getParameter(expression_text.split('.')[0]))
- ) {
- continue;
- }
-
- const parent = call.getFirstAncestorByKind(SyntaxKind.Block);
- if (!parent) {
- continue;
- }
-
- calls.push(() =>
- call.replaceWithText((writer) => {
- writer.setIndentationLevel(0); // prevent ts-morph from being unhelpful and adding its own indentation
- writer.write('/* @migration task: add path argument */ ' + call.getText());
- })
- );
- }
-
- for (const call of calls) {
- call();
- }
-
- logger();
-}
-
-/**
- * `resolvePath` from `@sveltejs/kit` -> `resolveRoute` from `$app/paths`
- * @param {import('ts-morph').SourceFile} source
- */
-function replace_resolve_path(source) {
- const named_import = get_import(source, '@sveltejs/kit', 'resolvePath');
- if (!named_import) return;
-
- const logger = log_on_ts_modification(
- source,
- 'Replaced `resolvePath` with `resolveRoute`: https://svelte.dev/docs/kit/migrating-to-sveltekit-2#resolvePath-has-been-removed'
- );
-
- const name_node = named_import.getNameNode();
- if (Node.isIdentifier(name_node)) {
- for (const id of name_node.findReferencesAsNodes()) {
- id.replaceWithText('resolveRoute');
- }
- }
- if (named_import.getParent().getParent().getNamedImports().length === 1) {
- named_import.getParent().getParent().getParent().remove();
- } else {
- named_import.remove();
- }
-
- const paths_import = source.getImportDeclaration(
- (i) => i.getModuleSpecifierValue() === '$app/paths'
- );
- if (paths_import) {
- paths_import.addNamedImport('resolveRoute');
- } else {
- source.addImportDeclaration({
- moduleSpecifier: '$app/paths',
- namedImports: ['resolveRoute']
- });
- }
-
- logger();
-}
-
-/**
- * @param {import('ts-morph').SourceFile} source
- * @param {string} from
- * @param {string} name
- */
-function get_import(source, from, name) {
- return source
- .getImportDeclarations()
- .filter((i) => i.getModuleSpecifierValue() === from)
- .flatMap((i) => i.getNamedImports())
- .find((i) => i.getName() === name);
-}
diff --git a/packages/migrate/migrations/sveltekit-2/migrate.spec.js b/packages/migrate/migrations/sveltekit-2/migrate.spec.js
deleted file mode 100644
index a297d947657c..000000000000
--- a/packages/migrate/migrations/sveltekit-2/migrate.spec.js
+++ /dev/null
@@ -1,32 +0,0 @@
-import { assert, test } from 'vitest';
-import {
- transform_code,
- update_svelte_config_content,
- update_tsconfig_content
-} from './migrate.js';
-import { read_samples } from '../../utils.js';
-
-for (const sample of read_samples(new URL('./svelte-config-samples.md', import.meta.url))) {
- test('svelte.config.js: ' + sample.description, () => {
- const actual = update_svelte_config_content(sample.before);
- assert.equal(actual, sample.after);
- });
-}
-
-for (const sample of read_samples(new URL('./tsconfig-samples.md', import.meta.url))) {
- test('tsconfig.json: ' + sample.description, () => {
- const actual = update_tsconfig_content(sample.before);
- assert.equal(actual, sample.after);
- });
-}
-
-for (const sample of read_samples(new URL('./tsjs-samples.md', import.meta.url))) {
- test('JS/TS file: ' + sample.description, () => {
- const actual = transform_code(
- sample.before,
- sample.filename?.endsWith('.ts') ?? false,
- sample.filename ?? '+page.js'
- );
- assert.equal(actual, sample.after);
- });
-}
diff --git a/packages/migrate/migrations/sveltekit-2/svelte-config-samples.md b/packages/migrate/migrations/sveltekit-2/svelte-config-samples.md
deleted file mode 100644
index 9a06096a3986..000000000000
--- a/packages/migrate/migrations/sveltekit-2/svelte-config-samples.md
+++ /dev/null
@@ -1,126 +0,0 @@
-## Removes dangerZone (1)
-
-```js before
-export default {
- kit: {
- foo: bar,
- dangerZone: {
- trackServerFetches: true
- },
- baz: qux
- }
-};
-```
-
-```js after
-export default {
- kit: {
- foo: bar,
- baz: qux
- }
-};
-```
-
-## Removes dangerZone (2)
-
-```js before
-export default {
- kit: {
- foo: bar,
- dangerZone: {
- trackServerFetches: true
- }
- }
-};
-```
-
-
-```js after
-export default {
- kit: {
- foo: bar,
- }
-};
-```
-
-## Replaces vitePreprocess import (1)
-
-```js before
-import adapter from '@sveltejs/adapter-auto';
-import { vitePreprocess } from '@sveltejs/kit/vite';
-
-/** @type {import('@sveltejs/kit').Config} */
-const config = {
- // Consult https://svelte.dev/docs/kit/integrations#preprocessors
- // for more information about preprocessors
- preprocess: vitePreprocess(),
-
- kit: {
- adapter: adapter()
- }
-};
-
-export default config;
-```
-
-```js after
-import adapter from '@sveltejs/adapter-auto';
-import { vitePreprocess } from '@sveltejs/vite-plugin-svelte';
-
-/** @type {import('@sveltejs/kit').Config} */
-const config = {
- // Consult https://svelte.dev/docs/kit/integrations#preprocessors
- // for more information about preprocessors
- preprocess: vitePreprocess(),
-
- kit: {
- adapter: adapter()
- }
-};
-
-export default config;
-```
-
-## Replaces vitePreprocess import (2)
-
-```js before
-import adapter from '@sveltejs/adapter-auto';
-import { vitePreprocess, foo } from '@sveltejs/kit/vite';
-
-export default {
- preprocess: vitePreprocess()
-};
-```
-
-
-```js after
-import adapter from '@sveltejs/adapter-auto';
-import { foo } from '@sveltejs/kit/vite';
-import { vitePreprocess } from "@sveltejs/vite-plugin-svelte";
-
-export default {
- preprocess: vitePreprocess()
-};
-```
-
-## Replaces vitePreprocess import (3)
-
-```js before
-import adapter from '@sveltejs/adapter-auto';
-import { vitePreprocess, foo } from '@sveltejs/kit/vite';
-import { a } from '@sveltejs/vite-plugin-svelte';
-
-export default {
- preprocess: vitePreprocess()
-};
-```
-
-```js after
-import adapter from '@sveltejs/adapter-auto';
-import { foo } from '@sveltejs/kit/vite';
-import { a, vitePreprocess } from '@sveltejs/vite-plugin-svelte';
-
-export default {
- preprocess: vitePreprocess()
-};
-```
diff --git a/packages/migrate/migrations/sveltekit-2/tsconfig-samples.md b/packages/migrate/migrations/sveltekit-2/tsconfig-samples.md
deleted file mode 100644
index 93d357fac974..000000000000
--- a/packages/migrate/migrations/sveltekit-2/tsconfig-samples.md
+++ /dev/null
@@ -1,40 +0,0 @@
-## Removes importsNotUsedAsValues/preserveValueImports
-
-```json before
-{
- "extends": "./.svelte-kit/tsconfig.json",
- "compilerOptions": {
- "importsNotUsedAsValues": "error",
- "preserveValueImports": true
- }
-}
-```
-
-
-```json after
-{
- "extends": "./.svelte-kit/tsconfig.json",
- "compilerOptions": {
- }
-}
-```
-
-## Leaves tsconfig alone
-
-```json before
-{
- "compilerOptions": {
- "importsNotUsedAsValues": "error",
- "preserveValueImports": true
- }
-}
-```
-
-```json after
-{
- "compilerOptions": {
- "importsNotUsedAsValues": "error",
- "preserveValueImports": true
- }
-}
-```
diff --git a/packages/migrate/migrations/sveltekit-2/tsjs-samples.md b/packages/migrate/migrations/sveltekit-2/tsjs-samples.md
deleted file mode 100644
index 3fed9bf6b95f..000000000000
--- a/packages/migrate/migrations/sveltekit-2/tsjs-samples.md
+++ /dev/null
@@ -1,170 +0,0 @@
-## Removes throws
-
-```js before
-import { redirect, error } from '@sveltejs/kit';
-
-throw redirect();
-redirect();
-throw error();
-error();
-function x() {
- let redirect = true;
- throw redirect();
-}
-```
-
-```js after
-import { redirect, error } from '@sveltejs/kit';
-
-redirect();
-redirect();
-error();
-error();
-function x() {
- let redirect = true;
- throw redirect();
-}
-```
-
-## Leaves redirect/error from other sources alone
-
-```js before
-import { redirect, error } from 'somewhere-else';
-
-throw redirect();
-redirect();
-throw error();
-error();
-```
-
-```js after
-import { redirect, error } from 'somewhere-else';
-
-throw redirect();
-redirect();
-throw error();
-error();
-```
-
-## Notes cookie migration
-
-```js before
-export function load({ cookies }) {
- cookies.set('foo', 'bar');
-}
-```
-
-```js after
-export function load({ cookies }) {
- /* @migration task: add path argument */ cookies.set('foo', 'bar');
-}
-```
-
-## Notes cookie migration with multiple occurences
-
-```js before
-export function load({ cookies }) {
- cookies.delete('foo');
- cookies.set('x', 'y', { z: '' });
-}
-```
-
-```js after
-export function load({ cookies }) {
- /* @migration task: add path argument */ cookies.delete('foo');
- /* @migration task: add path argument */ cookies.set('x', 'y', { z: '' });
-}
-```
-
-## Handles non-destructured argument
-
-```js before
-export function load(event) {
- event.cookies.set('x', 'y');
-}
-```
-
-```js after
-export function load(event) {
- /* @migration task: add path argument */ event.cookies.set('x', 'y');
-}
-```
-
-## Recognizes cookies false positives
-
-```js before
-export function load({ cookies }) {
- cookies.set('foo', 'bar', { path: '/' });
-}
-
-export function foo(event) {
- x.cookies.set('foo', 'bar');
-}
-
-export function bar(event) {
- event.x.set('foo', 'bar');
-}
-
-cookies.set('foo', 'bar');
-```
-
-```js after
-export function load({ cookies }) {
- cookies.set('foo', 'bar', { path: '/' });
-}
-
-export function foo(event) {
- x.cookies.set('foo', 'bar');
-}
-
-export function bar(event) {
- event.x.set('foo', 'bar');
-}
-
-cookies.set('foo', 'bar');
-```
-
-## Replaces resolvePath
-
-```js before
-import { resolvePath } from '@sveltejs/kit';
-
-resolvePath('x', y);
-```
-
-
-```js after
-import { resolveRoute } from "$app/paths";
-
-resolveRoute('x', y);
-```
-
-## Replaces resolvePath taking care of imports
-
-```js before
-import { resolvePath, x } from '@sveltejs/kit';
-import { y } from '$app/paths';
-
-resolvePath('x');
-```
-
-```js after
-import { x } from '@sveltejs/kit';
-import { y, resolveRoute } from '$app/paths';
-
-resolveRoute('x');
-```
-
-## Doesn't replace resolvePath from other sources
-
-```js before
-import { resolvePath } from 'x';
-
-resolvePath('x');
-```
-
-```js after
-import { resolvePath } from 'x';
-
-resolvePath('x');
-```
diff --git a/packages/migrate/package.json b/packages/migrate/package.json
deleted file mode 100644
index be1a716729fb..000000000000
--- a/packages/migrate/package.json
+++ /dev/null
@@ -1,54 +0,0 @@
-{
- "name": "svelte-migrate",
- "version": "1.6.8",
- "description": "A CLI for migrating Svelte(Kit) codebases",
- "keywords": [
- "migration",
- "upgrade",
- "svelte",
- "sveltekit",
- "tool"
- ],
- "repository": {
- "type": "git",
- "url": "https://github.com/sveltejs/kit",
- "directory": "packages/migrate"
- },
- "license": "MIT",
- "homepage": "https://svelte.dev",
- "type": "module",
- "bin": {
- "svelte-migrate": "./bin.js"
- },
- "files": [
- "bin.js",
- "migrations",
- "utils.js",
- "!migrations/**/*.spec.js",
- "!migrations/**/samples.md"
- ],
- "dependencies": {
- "import-meta-resolve": "^4.1.0",
- "kleur": "^4.1.5",
- "magic-string": "^0.30.5",
- "prompts": "^2.4.2",
- "semver": "^7.5.4",
- "tiny-glob": "^0.2.9",
- "ts-morph": "^24.0.0",
- "typescript": "^5.3.3",
- "zimmerframe": "^1.1.2"
- },
- "devDependencies": {
- "@types/node": "^18.19.48",
- "@types/prompts": "^2.4.9",
- "@types/semver": "^7.5.6",
- "svelte": "^4.2.10",
- "vitest": "^2.0.1"
- },
- "scripts": {
- "test": "vitest run --silent",
- "check": "tsc",
- "lint": "prettier --check .",
- "format": "pnpm lint --write"
- }
-}
diff --git a/packages/migrate/tsconfig.json b/packages/migrate/tsconfig.json
deleted file mode 100644
index 26885cff272f..000000000000
--- a/packages/migrate/tsconfig.json
+++ /dev/null
@@ -1,12 +0,0 @@
-{
- "compilerOptions": {
- "allowJs": true,
- "checkJs": true,
- "noEmit": true,
- "strict": true,
- "target": "es2022",
- "module": "node16",
- "moduleResolution": "node16",
- "allowSyntheticDefaultImports": true
- }
-}
diff --git a/packages/migrate/utils.js b/packages/migrate/utils.js
deleted file mode 100644
index 944461f02a78..000000000000
--- a/packages/migrate/utils.js
+++ /dev/null
@@ -1,421 +0,0 @@
-import colors from 'kleur';
-import MagicString from 'magic-string';
-import { execFileSync, execSync } from 'node:child_process';
-import fs from 'node:fs';
-import path from 'node:path';
-import process from 'node:process';
-import semver from 'semver';
-import ts from 'typescript';
-
-/** @param {string} message */
-export function bail(message) {
- console.error(colors.bold().red(message));
- process.exit(1);
-}
-
-/** @param {string} file */
-export function relative(file) {
- return path.relative('.', file);
-}
-/**
- *
- * @param {string} file
- * @param {string} renamed
- * @param {string} content
- * @param {boolean} use_git
- */
-export function move_file(file, renamed, content, use_git) {
- if (use_git) {
- execFileSync('git', ['mv', file, renamed]);
- } else {
- fs.unlinkSync(file);
- }
-
- fs.writeFileSync(renamed, content);
-}
-
-/**
- * @param {string} contents
- * @param {string} indent
- */
-export function comment(contents, indent) {
- return contents.replace(new RegExp(`^${indent}`, 'gm'), `${indent}// `);
-}
-
-/** @param {string} content */
-export function dedent(content) {
- const indent = guess_indent(content);
- if (!indent) return content;
-
- /** @type {string[]} */
- const substitutions = [];
-
- try {
- const ast = ts.createSourceFile(
- 'filename.ts',
- content,
- ts.ScriptTarget.Latest,
- true,
- ts.ScriptKind.TS
- );
-
- const code = new MagicString(content);
-
- /** @param {ts.Node} node */
- function walk(node) {
- if (ts.isTemplateLiteral(node)) {
- let pos = node.pos;
- while (/\s/.test(content[pos])) pos += 1;
-
- code.overwrite(pos, node.end, `____SUBSTITUTION_${substitutions.length}____`);
- substitutions.push(node.getText());
- }
-
- node.forEachChild(walk);
- }
-
- ast.forEachChild(walk);
-
- return code
- .toString()
- .replace(new RegExp(`^${indent}`, 'gm'), '')
- .replace(/____SUBSTITUTION_(\d+)____/g, (match, index) => substitutions[index]);
- } catch {
- // as above — ignore this edge case
- return content;
- }
-}
-
-/** @param {string} content */
-export function guess_indent(content) {
- const lines = content.split('\n');
-
- const tabbed = lines.filter((line) => /^\t+/.test(line));
- const spaced = lines.filter((line) => /^ {2,}/.test(line));
-
- if (tabbed.length === 0 && spaced.length === 0) {
- return null;
- }
-
- // More lines tabbed than spaced? Assume tabs, and
- // default to tabs in the case of a tie (or nothing
- // to go on)
- if (tabbed.length >= spaced.length) {
- return '\t';
- }
-
- // Otherwise, we need to guess the multiple
- const min = spaced.reduce((previous, current) => {
- const count = /^ +/.exec(current)?.[0].length ?? 0;
- return Math.min(count, previous);
- }, Infinity);
-
- return ' '.repeat(min);
-}
-
-/**
- * @param {string} content
- * @param {number} offset
- */
-export function indent_at_line(content, offset) {
- const substr = content.substring(content.lastIndexOf('\n', offset) + 1, offset);
- return /\s*/.exec(substr)?.[0] ?? '';
-}
-
-/**
- * @param {string} content
- * @param {string} except
- */
-export function except_str(content, except) {
- const start = content.indexOf(except);
- const end = start + except.length;
- return content.substring(0, start) + content.substring(end);
-}
-
-/**
- * @returns {boolean} True if git is installed
- */
-export function check_git() {
- let use_git = false;
-
- let dir = process.cwd();
- do {
- if (fs.existsSync(path.join(dir, '.git'))) {
- use_git = true;
- break;
- }
- } while (dir !== (dir = path.dirname(dir)));
-
- if (use_git) {
- try {
- const status = execSync('git status --porcelain', { stdio: 'pipe' }).toString();
-
- if (status) {
- const message =
- 'Your git working directory is dirty — we recommend committing your changes before running this migration.\n';
- console.log(colors.bold().red(message));
- }
- } catch {
- // would be weird to have a .git folder if git is not installed,
- // but always expect the unexpected
- const message =
- 'Could not detect a git installation. If this is unexpected, please raise an issue: https://github.com/sveltejs/kit.\n';
- console.log(colors.bold().red(message));
- use_git = false;
- }
- }
-
- return use_git;
-}
-
-/**
- * Get a list of all files in a directory
- * @param {string} cwd - the directory to walk
- * @param {boolean} [dirs] - whether to include directories in the result
- */
-export function walk(cwd, dirs = false) {
- /** @type {string[]} */
- const all_files = [];
-
- /** @param {string} dir */
- function walk_dir(dir) {
- const files = fs.readdirSync(path.join(cwd, dir));
-
- for (const file of files) {
- const joined = path.join(dir, file);
- const stats = fs.statSync(path.join(cwd, joined));
- if (stats.isDirectory()) {
- if (dirs) all_files.push(joined);
- walk_dir(joined);
- } else {
- all_files.push(joined);
- }
- }
- }
-
- return walk_dir(''), all_files;
-}
-
-/** @param {string} str */
-export function posixify(str) {
- return str.replace(/\\/g, '/');
-}
-
-/**
- * @param {string} content
- * @param {Array<[string, string, string?, ('dependencies' | 'devDependencies')?]>} updates
- */
-export function update_pkg(content, updates) {
- const indent = content.split('\n')[1].match(/^\s+/)?.[0] || ' ';
- const pkg = JSON.parse(content);
-
- /**
- * @param {string} name
- * @param {string} version
- * @param {string} [additional]
- * @param {'dependencies' | 'devDependencies' | undefined} [insert]
- */
- function update_pkg(name, version, additional = '', insert) {
- /**
- * @param {string} type
- */
- const updateVersion = (type) => {
- const existingRange = pkg[type]?.[name];
-
- if (
- existingRange &&
- semver.validRange(existingRange) &&
- !semver.subset(existingRange, version)
- ) {
- // Check if the new version range is an upgrade
- const minExistingVersion = semver.minVersion(existingRange);
- const minNewVersion = semver.minVersion(version);
-
- if (minExistingVersion && minNewVersion && semver.gt(minNewVersion, minExistingVersion)) {
- log_migration(`Updated ${name} to ${version}`);
- pkg[type][name] = version;
- }
- }
- };
-
- updateVersion('dependencies');
- updateVersion('devDependencies');
-
- if (insert && !pkg[insert]?.[name]) {
- if (!pkg[insert]) pkg[insert] = {};
-
- // Insert the property in sorted position without adjusting other positions so diffs are easier to read
- const sorted_keys = Object.keys(pkg[insert]).sort();
- const index = sorted_keys.findIndex((key) => name.localeCompare(key) === -1);
- const insert_index = index !== -1 ? index : sorted_keys.length;
- const new_properties = Object.entries(pkg[insert]);
- new_properties.splice(insert_index, 0, [name, version]);
- pkg[insert] = Object.fromEntries(new_properties);
-
- log_migration(`Added ${name} version ${version} ${additional}`);
- }
- }
-
- for (const update of updates) {
- update_pkg(...update);
- }
-
- const result = JSON.stringify(pkg, null, indent);
- if (content.endsWith('\n')) return result + '\n';
- return result;
-}
-
-const logged_migrations = new Set();
-
-/**
- * @param {import('ts-morph').SourceFile} source
- * @param {string} text
- */
-export function log_on_ts_modification(source, text) {
- let logged = false;
- const log = () => {
- if (!logged) {
- logged = true;
- log_migration(text);
- }
- };
- source.onModified(log);
- return () => source.onModified(log, false);
-}
-
-/** @param {string} text */
-export function log_migration(text) {
- if (logged_migrations.has(text)) return;
- console.log(text);
- logged_migrations.add(text);
-}
-
-/**
- * Parses the scripts contents and invoked `transform_script_code` with it, then runs the result through `transform_svelte_code`.
- * The result is written back to disk.
- * @param {string} file_path
- * @param {(code: string, is_ts: boolean, file_path: string) => string} transform_script_code
- * @param {(code: string, file_path: string) => string} transform_svelte_code
- */
-export function update_svelte_file(file_path, transform_script_code, transform_svelte_code) {
- try {
- const content = fs.readFileSync(file_path, 'utf-8');
- const updated = content.replace(
- /${whitespace}`;
- }
- );
- fs.writeFileSync(file_path, transform_svelte_code(updated, file_path), 'utf-8');
- } catch (err) {
- // TODO: change to import('svelte/compiler').Warning after upgrading to Svelte 5
- const e = /** @type {any} */ (err);
- console.warn(buildExtendedLogMessage(e), e.frame);
- console.info(e.stack);
- }
-}
-
-/**
- * Reads the file and invokes `transform_code` with its contents. The result is written back to disk.
- * @param {string} file_path
- * @param {(code: string, is_ts: boolean, file_path: string) => string} transform_code
- */
-export function update_js_file(file_path, transform_code) {
- try {
- const content = fs.readFileSync(file_path, 'utf-8');
- const updated = transform_code(content, file_path.endsWith('.ts'), file_path);
- fs.writeFileSync(file_path, updated, 'utf-8');
- } catch (err) {
- // TODO: change to import('svelte/compiler').Warning after upgrading to Svelte 5
- const e = /** @type {any} */ (err);
- console.warn(buildExtendedLogMessage(e), e.frame);
- console.info(e.stack);
- }
-}
-
-/**
- * @param {any} w
- */
-export function buildExtendedLogMessage(w) {
- const parts = [];
- if (w.filename) {
- parts.push(w.filename);
- }
- if (w.start) {
- parts.push(':', w.start.line, ':', w.start.column);
- }
- if (w.message) {
- if (parts.length > 0) {
- parts.push(' ');
- }
- parts.push(w.message);
- }
- return parts.join('');
-}
-
-/**
- * Updates the tsconfig/jsconfig.json file with the provided function.
- * @param {(content: string) => string} update_tsconfig_content
- */
-export function update_tsconfig(update_tsconfig_content) {
- const file = fs.existsSync('tsconfig.json')
- ? 'tsconfig.json'
- : fs.existsSync('jsconfig.json')
- ? 'jsconfig.json'
- : null;
- if (file) {
- fs.writeFileSync(file, update_tsconfig_content(fs.readFileSync(file, 'utf8')));
- }
-}
-
-/** @param {string | URL} test_file */
-export function read_samples(test_file) {
- const markdown = fs.readFileSync(test_file, 'utf8').replaceAll('\r\n', '\n');
- const samples = markdown
- .split(/^##/gm)
- .slice(1)
- .map((block) => {
- const description = block.split('\n')[0];
- const before = /```(js|ts|svelte) before\n([^]*?)\n```/.exec(block);
- const after = /```(js|ts|svelte) after\n([^]*?)\n```/.exec(block);
-
- const match = /> file: (.+)/.exec(block);
-
- return {
- description,
- before: before ? before[2] : '',
- after: after ? after[2] : '',
- filename: match?.[1],
- solo: block.includes('> solo')
- };
- });
-
- if (samples.some((sample) => sample.solo)) {
- return samples.filter((sample) => sample.solo);
- }
-
- return samples;
-}
-
-/**
- * @param {import('ts-morph').SourceFile} source
- * @param {string} _import
- * @param {string} method
- */
-export function add_named_import(source, _import, method) {
- const existing = source.getImportDeclaration(_import);
- if (existing) {
- if (existing.getNamedImports().some((i) => i.getName() === method)) return;
- existing?.addNamedImport(method);
- } else {
- source.addImportDeclaration({
- moduleSpecifier: _import,
- namedImports: [method]
- });
- }
-}
diff --git a/packages/migrate/utils.spec.js b/packages/migrate/utils.spec.js
deleted file mode 100644
index a75641e6055f..000000000000
--- a/packages/migrate/utils.spec.js
+++ /dev/null
@@ -1,93 +0,0 @@
-import { assert, test } from 'vitest';
-import { update_pkg } from './utils.js';
-
-test('Inserts package at correct position (1)', () => {
- const result = update_pkg(
- `{
- "dependencies": {
- "a": "1",
- "z": "3",
- "c": "4"
- }
-}`,
- [['b', '2', '', 'dependencies']]
- );
-
- assert.equal(
- result,
- `{
- "dependencies": {
- "a": "1",
- "b": "2",
- "z": "3",
- "c": "4"
- }
-}`
- );
-});
-
-test('Inserts package at correct position (2)', () => {
- const result = update_pkg(
- `{
- "dependencies": {
- "a": "1",
- "b": "2"
- }
-}`,
- [['c', '3', '', 'dependencies']]
- );
-
- assert.equal(
- result,
- `{
- "dependencies": {
- "a": "1",
- "b": "2",
- "c": "3"
- }
-}`
- );
-});
-
-test('Inserts package at correct position (3)', () => {
- const result = update_pkg(
- `{
- "dependencies": {
- "b": "2",
- "c": "3"
- }
-}`,
- [['a', '1', '', 'dependencies']]
- );
-
- assert.equal(
- result,
- `{
- "dependencies": {
- "a": "1",
- "b": "2",
- "c": "3"
- }
-}`
- );
-});
-
-test('Does not downgrade versions', () => {
- const result = update_pkg(
- `{
- "devDependencies": {
- "@sveltejs/kit": "^2.4.3"
- }
-}`,
- [['@sveltejs/kit', '^2.0.0']]
- );
-
- assert.equal(
- result,
- `{
- "devDependencies": {
- "@sveltejs/kit": "^2.4.3"
- }
-}`
- );
-});
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 0a360411ab50..a9eb3d780d8b 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -1028,52 +1028,6 @@ importers:
specifier: ^2.0.1
version: 2.0.1(@types/node@18.19.50)(lightningcss@1.24.1)
- packages/migrate:
- dependencies:
- import-meta-resolve:
- specifier: ^4.1.0
- version: 4.1.0
- kleur:
- specifier: ^4.1.5
- version: 4.1.5
- magic-string:
- specifier: ^0.30.5
- version: 0.30.11
- prompts:
- specifier: ^2.4.2
- version: 2.4.2
- semver:
- specifier: ^7.5.4
- version: 7.6.3
- tiny-glob:
- specifier: ^0.2.9
- version: 0.2.9
- ts-morph:
- specifier: ^24.0.0
- version: 24.0.0
- typescript:
- specifier: ^5.3.3
- version: 5.4.5
- zimmerframe:
- specifier: ^1.1.2
- version: 1.1.2
- devDependencies:
- '@types/node':
- specifier: ^18.19.48
- version: 18.19.50
- '@types/prompts':
- specifier: ^2.4.9
- version: 2.4.9
- '@types/semver':
- specifier: ^7.5.6
- version: 7.5.8
- svelte:
- specifier: ^4.2.10
- version: 4.2.19
- vitest:
- specifier: ^2.0.1
- version: 2.0.1(@types/node@18.19.50)(lightningcss@1.24.1)
-
packages/package:
dependencies:
chokidar:
@@ -1956,9 +1910,6 @@ packages:
resolution: {integrity: sha512-qhUGGDHcpbY2zpjW3SwqchuW8J/5EzlPFud7xNntHKA7f3a/mx5+g+ruJKFHSAiVZYo30PALt+AyhmPUNKH/Og==}
engines: {node: ^14.13.1 || ^16.0.0 || >=18}
- '@ts-morph/common@0.25.0':
- resolution: {integrity: sha512-kMnZz+vGGHi4GoHnLmMhGNjm44kGtKUXGnOvrKmMwAuvNjM/PgKVGfUnL7IDvK7Jb2QQ82jq3Zmp04Gy+r3Dkg==}
-
'@types/connect@3.4.38':
resolution: {integrity: sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==}
@@ -1983,9 +1934,6 @@ packages:
'@types/node@18.19.50':
resolution: {integrity: sha512-xonK+NRrMBRtkL1hVCc3G+uXtjh1Al4opBLjqVmipe5ZAaBYWW6cNAiBVZ1BvmkBhep698rP3UM3aRAdSALuhg==}
- '@types/prompts@2.4.9':
- resolution: {integrity: sha512-qTxFi6Buiu8+50/+3DGIWLHM6QuWsEKugJnnP6iv2Mc4ncxE4A/OJkjuVOA+5X0X1S/nq5VJRa8Lu+nwcvbrKA==}
-
'@types/resolve@1.20.2':
resolution: {integrity: sha512-60BCwRFOZCQhDncwQdxxeOEEkbc5dIMccYLwbxsS4TUNeVECQ/pBJ0j09mrHOl/JJvpRPGwO9SvE4nR2Nb/a4Q==}
@@ -2234,9 +2182,6 @@ packages:
resolution: {integrity: sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==}
engines: {node: '>=8'}
- code-block-writer@13.0.3:
- resolution: {integrity: sha512-Oofo0pq3IKnsFtuHqSF7TqBfr71aeyZDVJ0HpmqB7FBM2qEigL0iPONSCZSO9pE9dZTAxANe5XHG9Uy0YMv8cg==}
-
code-red@1.0.4:
resolution: {integrity: sha512-7qJWqItLA8/VPVlKJlFXU+NBlo/qyfs39aJcuMT/2ere32ZqvF5OSxgdM5xOfJJ7O429gg2HM47y8v9P+9wrNw==}
@@ -2818,10 +2763,6 @@ packages:
keyv@4.5.4:
resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==}
- kleur@3.0.3:
- resolution: {integrity: sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==}
- engines: {node: '>=6'}
-
kleur@4.1.5:
resolution: {integrity: sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ==}
engines: {node: '>=6'}
@@ -3136,9 +3077,6 @@ packages:
pascal-case@3.1.2:
resolution: {integrity: sha512-uWlGT3YSnK9x3BQJaOdcZwrnV6hPpd8jFH1/ucpiLRPh/2zCVJKS19E4GvYHvaCcACn3foXZ0cLB9Wrx1KGe5g==}
- path-browserify@1.0.1:
- resolution: {integrity: sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==}
-
path-exists@4.0.0:
resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==}
engines: {node: '>=8'}
@@ -3263,10 +3201,6 @@ packages:
printable-characters@1.0.42:
resolution: {integrity: sha512-dKp+C4iXWK4vVYZmYSd0KBH5F/h1HoZRsbJ82AVKRO3PEo8L4lBS/vLwhVtpwwuYcoIsVY+1JYKR268yn480uQ==}
- prompts@2.4.2:
- resolution: {integrity: sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==}
- engines: {node: '>= 6'}
-
pseudomap@1.0.2:
resolution: {integrity: sha512-b/YwNhb8lk1Zz2+bXXpS/LK9OisiZZ1SNsSLxN1x2OXVEhW2Ckr/7mWE5vrC1ZTiJlD9g19jWszTmJsB+oEpFQ==}
@@ -3429,9 +3363,6 @@ packages:
resolution: {integrity: sha512-BPwJGUeDaDCHihkORDchNyyTvWFhcusy1XMmhEVTQTwGeybFbp8YEmB+njbPnth1FibULBSBVwCQni25XlCUDg==}
engines: {node: '>=18'}
- sisteransi@1.0.5:
- resolution: {integrity: sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==}
-
slash@3.0.0:
resolution: {integrity: sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==}
engines: {node: '>=8'}
@@ -3606,10 +3537,6 @@ packages:
resolution: {integrity: sha512-7cR8rLy2QhYHpsBDBVYnnWXm8uRTr38RoZakFSW7Bs7PzfMPNZthuMLkwqZv7MTu8lhQ91cOFYS5a7iFj2oR3w==}
engines: {node: '>=4'}
- tinyglobby@0.2.9:
- resolution: {integrity: sha512-8or1+BGEdk1Zkkw2ii16qSS7uVrQJPre5A9o/XkWPATkk23FZh/15BKFxPnlTy6vkljZxLqYCzzBMj30ZrSvjw==}
- engines: {node: '>=12.0.0'}
-
tinypool@1.0.0:
resolution: {integrity: sha512-KIKExllK7jp3uvrNtvRBYBWBOAXSX8ZvoaD8T+7KB/QHIuoJW3Pmr60zucywjAlMb5TeXUkcs/MWeWLu0qvuAQ==}
engines: {node: ^18.0.0 || >=20.0.0}
@@ -3643,9 +3570,6 @@ packages:
peerDependencies:
typescript: '>=4.2.0'
- ts-morph@24.0.0:
- resolution: {integrity: sha512-2OAOg/Ob5yx9Et7ZX4CvTCc0UFoZHwLEJ+dpDPSUi5TgwwlTlX47w+iFRrEwzUZwYACjq83cgjS/Da50Ga37uw==}
-
tslib@2.6.2:
resolution: {integrity: sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==}
@@ -4583,12 +4507,6 @@ snapshots:
transitivePeerDependencies:
- encoding
- '@ts-morph/common@0.25.0':
- dependencies:
- minimatch: 9.0.5
- path-browserify: 1.0.1
- tinyglobby: 0.2.9
-
'@types/connect@3.4.38':
dependencies:
'@types/node': 18.19.50
@@ -4614,11 +4532,6 @@ snapshots:
dependencies:
undici-types: 5.26.5
- '@types/prompts@2.4.9':
- dependencies:
- '@types/node': 18.19.50
- kleur: 3.0.3
-
'@types/resolve@1.20.2': {}
'@types/semver@7.5.8': {}
@@ -4906,8 +4819,6 @@ snapshots:
ci-info@3.9.0: {}
- code-block-writer@13.0.3: {}
-
code-red@1.0.4:
dependencies:
'@jridgewell/sourcemap-codec': 1.5.0
@@ -5529,8 +5440,6 @@ snapshots:
dependencies:
json-buffer: 3.0.1
- kleur@3.0.3: {}
-
kleur@4.1.5: {}
known-css-properties@0.34.0: {}
@@ -5803,8 +5712,6 @@ snapshots:
no-case: 3.0.4
tslib: 2.6.2
- path-browserify@1.0.1: {}
-
path-exists@4.0.0: {}
path-is-absolute@1.0.1: {}
@@ -5895,11 +5802,6 @@ snapshots:
printable-characters@1.0.42: {}
- prompts@2.4.2:
- dependencies:
- kleur: 3.0.3
- sisteransi: 1.0.5
-
pseudomap@1.0.2: {}
publint@0.2.7:
@@ -6085,8 +5987,6 @@ snapshots:
mrmime: 2.0.0
totalist: 3.0.1
- sisteransi@1.0.5: {}
-
slash@3.0.0: {}
source-map-js@1.2.1: {}
@@ -6251,11 +6151,6 @@ snapshots:
tinydate@1.3.0: {}
- tinyglobby@0.2.9:
- dependencies:
- fdir: 6.4.0(picomatch@4.0.2)
- picomatch: 4.0.2
-
tinypool@1.0.0: {}
tinyspy@3.0.0: {}
@@ -6284,11 +6179,6 @@ snapshots:
dependencies:
typescript: 5.6.3
- ts-morph@24.0.0:
- dependencies:
- '@ts-morph/common': 0.25.0
- code-block-writer: 13.0.3
-
tslib@2.6.2: {}
type-check@0.4.0: