Skip to content

Commit

Permalink
chore: align migrate dependencies with sv (#376)
Browse files Browse the repository at this point in the history
* use `picocolors` instead of `kleur`

* use `@clack/prompts` instead of `prompts`

* improve logs

* changeset

* migrate to prompt logging

* add intro, outro and migration selection

* changeset

* fix docs / readme

* Apply suggestions from code review

Co-authored-by: Ben McCann <[email protected]>

* Update packages/migrate/bin.js

Co-authored-by: Ben McCann <[email protected]>

* Update packages/migrate/migrations/app-state/index.js

Co-authored-by: Ben McCann <[email protected]>

* lint

* make it work again

* fix merge conflict

---------

Co-authored-by: Ben McCann <[email protected]>
  • Loading branch information
manuel3108 and benmccann authored Jan 31, 2025
1 parent 3173bdc commit 6f99ed2
Show file tree
Hide file tree
Showing 17 changed files with 339 additions and 355 deletions.
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
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) {
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

0 comments on commit 6f99ed2

Please sign in to comment.