Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore: align dependencies with sv #376

Open
wants to merge 14 commits into
base: main
Choose a base branch
from
5 changes: 5 additions & 0 deletions .changeset/dull-toys-share.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'svelte-migrate': patch
---

chore: align dependencies with `sv`
5 changes: 5 additions & 0 deletions .changeset/happy-singers-roll.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'svelte-migrate': minor
---

feat: add ability to select migration to run
5 changes: 5 additions & 0 deletions documentation/docs/20-commands/40-sv-migrate.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,11 @@ Some migrations may annotate your codebase with tasks for completion that you ca

## Usage

```bash
npx sv migrate
```

You can also specify a migration directly via the CLI:
```bash
manuel3108 marked this conversation as resolved.
Show resolved Hide resolved
npx sv migrate [migration]
```
Expand Down
8 changes: 4 additions & 4 deletions packages/migrate/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,13 @@ A CLI for migrating Svelte(Kit) codebases.

Run it directly using:

```
npx svelte-migrate [migration]
```bash
npx sv migrate
```

Or via the unified Svlete CLI with:
You can also specify a migration directly via the CLI:

```
```bash
npx sv migrate [migration]
```

Expand Down
37 changes: 25 additions & 12 deletions packages/migrate/bin.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@
import fs from 'node:fs';
import process from 'node:process';
import { fileURLToPath } from 'node:url';
import colors from 'kleur';
import pc from 'picocolors';
import * as p from '@clack/prompts';

const migration = process.argv[2];
const dir = fileURLToPath(new URL('.', import.meta.url));
Expand All @@ -11,17 +12,29 @@ const migrations = fs
.readdirSync(`${dir}/migrations`)
.filter((migration) => fs.existsSync(`${dir}/migrations/${migration}/index.js`));

const pkg = JSON.parse(fs.readFileSync(`${dir}/package.json`, 'utf8'));

p.intro(`Welcome to the svelte-migrate CLI! ${pc.gray(`(v${pkg.version})`)}`);

if (migrations.includes(migration)) {
const { migrate } = await import(`./migrations/${migration}/index.js`);
migrate();
await run_migration(migration);
} else {
console.error(
colors
.bold()
.red(
`You must specify one of the following migrations: ${migrations.join(', ')}\n` +
'If you expected this to work, try re-running the command with the latest svelte-migrate version:\n' +
` npx svelte-migrate@latest ${migration}`
)
);
if (migration) p.log.warning(pc.yellow(`Invalid migration "${migration}" provided.`));

const selectedMigration = await p.select({
message: 'Which migration would you like to run?',
options: migrations.map((x) => ({ value: x, label: x }))
});

if (!p.isCancel(selectedMigration)) await run_migration(selectedMigration);
}

p.outro("You're all set!");

/**
* @param {string} migration
*/
async function run_migration(migration) {
const { migrate } = await import(`./migrations/${migration}/index.js`);
await migrate();
}
76 changes: 31 additions & 45 deletions packages/migrate/migrations/app-state/index.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import colors from 'kleur';
import pc from 'picocolors';
import fs from 'node:fs';
import process from 'node:process';
import prompts from 'prompts';
import * as p from '@clack/prompts';
import semver from 'semver';
import glob from 'tiny-glob/sync.js';
import { bail, check_git, update_svelte_file } from '../../utils.js';
import { bail, check_git, migration_succeeded, update_svelte_file } from '../../utils.js';
import { transform_svelte_code, update_pkg_json } from './migrate.js';

export async function migrate() {
Expand All @@ -16,66 +16,61 @@ export async function migrate() {

const svelte_dep = pkg.devDependencies?.svelte ?? pkg.dependencies?.svelte;
if (svelte_dep && semver.validRange(svelte_dep) && semver.gtr('5.0.0', svelte_dep)) {
console.log(
colors
.bold()
.red('\nYou need to upgrade to Svelte version 5 first (`npx sv migrate svelte-5`).\n')
p.log.error(
pc.bold(pc.red('You need to upgrade to Svelte version 5 first (`npx sv migrate svelte-5`).'))
);
process.exit(1);
}

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()
.red('\nYou need to upgrade to SvelteKit version 2 first (`npx sv migrate sveltekit-2`).\n')
p.log.error(
pc.bold(
pc.red('You need to upgrade to SvelteKit version 2 first (`npx sv migrate sveltekit-2`).')
)
);
process.exit(1);
}

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"
p.log.warning(
pc.bold(pc.yellow('This will update files in the current directory.')) +
'\n' +
pc.bold(
pc.yellow(
"If you're inside a monorepo, don't run this in the root directory, rather run it in all projects independently."
)
)
);

const use_git = check_git();

const response = await prompts({
type: 'confirm',
name: 'value',
const response = await p.confirm({
message: 'Continue?',
initial: false
initialValue: false
});

if (!response.value) {
if (p.isCancel(response) || !response) {
process.exit(1);
}

const folders = await prompts({
type: 'multiselect',
name: 'value',
const folders = await p.multiselect({
message: 'Which folders should be migrated?',
choices: fs
options: 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) {
if (p.isCancel(folders) || !folders?.length) {
process.exit(1);
}

update_pkg_json();

// For some reason {folders.value.join(',')} as part of the glob doesn't work and returns less files
const files = folders.value.flatMap(
const files = folders.flatMap(
/** @param {string} folder */ (folder) =>
glob(`${folder}/**`, { filesOnly: true, dot: true })
.map((file) => file.replace(/\\/g, '/'))
Expand All @@ -96,24 +91,15 @@ export async function migrate() {
);
}

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) " + use_git &&
cyan('git commit -m "migration to $app/state"')
].filter(Boolean);

tasks.forEach((task, i) => {
console.log(` ${i + 1}: ${task}`);
});

console.log('');
/** @type {(s: string) => string} */
const cyan = (s) => pc.bold(pc.cyan(s));

// TODO: use package-manager-detector here
const tasks = ["install the updated dependencies ('npm i' / 'pnpm i' / etc)"];
if (use_git) {
manuel3108 marked this conversation as resolved.
Show resolved Hide resolved
console.log(`Run ${cyan('git diff')} to review changes.\n`);
tasks.push(cyan('git commit -m "migration to $app/state"'));
tasks.push(`Run ${cyan('git diff')} to review changes.`);
}

migration_succeeded(tasks);
}
49 changes: 18 additions & 31 deletions packages/migrate/migrations/package/index.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import fs from 'node:fs';
import colors from 'kleur';
import pc from 'picocolors';
import path from 'node:path';
import process from 'node:process';
import prompts from 'prompts';
import * as p from '@clack/prompts';
import { pathToFileURL } from 'node:url';
import { bail, check_git } from '../../utils.js';
import { bail, check_git, migration_succeeded } from '../../utils.js';
import { migrate_config } from './migrate_config.js';
import { migrate_pkg } from './migrate_pkg.js';

Expand All @@ -16,24 +16,20 @@ export async function migrate() {
bail('Please re-run this script in a directory with a package.json');
}

console.log(
colors
.bold()
.yellow(
'\nThis will update your svelte.config.js and package.json in the current directory\n'
)
p.log.warning(
pc.bold(
pc.yellow('This will update your svelte.config.js and package.json in the current directory')
)
);

const use_git = check_git();

const response = await prompts({
type: 'confirm',
name: 'value',
const response = await p.confirm({
message: 'Continue?',
initial: false
initialValue: false
});

if (!response.value) {
if (p.isCancel(response) || !response) {
process.exit(1);
}

Expand All @@ -57,25 +53,16 @@ export async function migrate() {
migrate_config();
}

console.log(colors.bold().green('✔ Your project has been migrated'));
/** @type {(s: string) => string} */
const cyan = (s) => pc.bold(pc.cyan(s));

console.log('\nRecommended next steps:\n');
/** @type {string[]} */
const tasks = [];

const cyan = colors.bold().cyan;
if (use_git) tasks.push(cyan('git commit -m "migration to @sveltejs/package v2"'));

const tasks = [
use_git && cyan('git commit -m "migration to @sveltejs/package v2"'),
'Review the migration guide at https://github.com/sveltejs/kit/pull/8922',
'Read the updated docs at https://svelte.dev/docs/kit/packaging'
].filter(Boolean);
tasks.push('Review the migration guide at https://github.com/sveltejs/kit/pull/8922');
tasks.push('Read the updated docs at https://svelte.dev/docs/kit/packaging');

tasks.forEach((task, i) => {
console.log(` ${i + 1}: ${task}`);
});

console.log('');

if (use_git) {
console.log(`Run ${cyan('git diff')} to review changes.\n`);
}
migration_succeeded;
}
13 changes: 8 additions & 5 deletions packages/migrate/migrations/package/migrate_config.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import * as p from '@clack/prompts';
import fs from 'node:fs';
import colors from 'kleur';
import pc from 'picocolors';
import MagicString from 'magic-string';
import ts from 'typescript';

Expand All @@ -8,10 +9,12 @@ export function migrate_config() {
const content = fs.readFileSync('svelte.config.js', 'utf8');
fs.writeFileSync('svelte.config.js', remove_package_from_config(content));
} catch {
console.log(
colors
.bold()
.yellow('Could not remove package config from svelte.config.js, please remove it manually')
p.log.warning(
pc.bold(
pc.yellow(
'Could not remove package config from svelte.config.js, please remove it manually'
)
)
);
}
}
Expand Down
19 changes: 10 additions & 9 deletions packages/migrate/migrations/package/migrate_pkg.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import * as p from '@clack/prompts';
import fs from 'node:fs';
import path from 'node:path';
import colors from 'kleur';
import pc from 'picocolors';
import { guess_indent, posixify, walk } from '../../utils.js';

/**
Expand Down Expand Up @@ -58,8 +59,8 @@ export function update_pkg_json(config, pkg, files) {

// See: https://pnpm.io/package_json#publishconfigdirectory
if (pkg.publishConfig?.directory || pkg.linkDirectory?.directory) {
console.log(
colors.yellow(
p.log.warning(
pc.yellow(
'Detected "publishConfig.directory" or "linkDirectory.directory" fields in your package.json. ' +
'This migration removes them, which may or may not be what you want. Please review closely.'
)
Expand Down Expand Up @@ -101,8 +102,8 @@ export function update_pkg_json(config, pkg, files) {
const key = `./${file.dest}`.replace(/\/index\.js$|(\/[^/]+)\.js$/, '$1');

if (clashes[key]) {
console.log(
colors.yellow(
p.log.warning(
pc.yellow(
`Duplicate "${key}" export. Closely review your "exports" field in package.json after the migration.`
)
);
Expand Down Expand Up @@ -169,15 +170,15 @@ export function update_pkg_json(config, pkg, files) {
if (svelte_export) {
pkg.svelte = svelte_export;
} else {
console.log(
colors.yellow(
p.log.warning(
pc.yellow(
'Cannot generate a "svelte" entry point because the "." entry in "exports" is not a string. Please specify a "svelte" entry point yourself\n'
)
);
}
} else {
console.log(
colors.yellow(
p.log.warning(
pc.yellow(
'Cannot generate a "svelte" entry point because the "." entry in "exports" is missing. Please specify a "svelte" entry point yourself\n'
)
);
Expand Down
Loading
Loading