feat(migrate): rework migrations and initial sveltekit-3 migration#1138
feat(migrate): rework migrations and initial sveltekit-3 migration#1138manuel3108 wants to merge 95 commits into
sveltekit-3 migration#1138Conversation
🦋 Changeset detectedLatest commit: 6a25a2f The changes in this PR will be included in the next version bump. This PR includes changesets to release 3 packages
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
* feat: migration-task comment management
- @migration-task comments now work in .svelte files (insert real Comment
nodes into the fragment, since the Svelte printer ignores the JS Comments
registry); fixes the env task silently dropping them.
- single addMigrationTask(message, target): { comments, node } for JS/TS,
{ fragment, anchor? } for .svelte.
- split migrate/index.ts into index.ts (framework) + migration-task.ts.
* fmt
* feat(migrate): defer formatting to project format script Migrate now runs the nearest `format`/`fmt` package.json script (walking up to the workspace root) before falling back to prettier on modified files. `formatFiles` takes a `strategy` param; create/add keep the files-only path. * fix: import order in formatFiles
* feat: migration-task comment management
- @migration-task comments now work in .svelte files (insert real Comment
nodes into the fragment, since the Svelte printer ignores the JS Comments
registry); fixes the env task silently dropping them.
- single addMigrationTask(message, target): { comments, node } for JS/TS,
{ fragment, anchor? } for .svelte.
- split migrate/index.ts into index.ts (framework) + migration-task.ts.
* fmt
* feat: reborn app-state migration (AST-based)
Rebuild `$app/stores` -> `$app/state` as a proper AST task instead of the
regex legacy shell-out. Runnable standalone (`sv migrate app-state`) and
required inside the sveltekit-3 migration.
Bug fixes over the legacy version:
- truthy `$navigating` (e.g. {#if $navigating}) -> `navigating.to`
- bail cases (`$:`, `derived(store)`, `getStores()`) now leave a @migration-task instead of silently skipping
- drop spurious TODO when `.to` is already accessed
---------
Co-authored-by: Manuel <30698007+manuel3108@users.noreply.github.com>
|
Install the latest version of pnpm add https://pkg.svelte.dev/sv/c/6a25a2f6bf76e33cff72b7fd42c548aa77dea6a3Open in |
* stuff * more stuff * removed * improved formatting * chore: minimizeDiff follow-ups (size cap, trailing commas, snapshots) (#1164) * re-add diffLines size cap, handle trailing commas before ), trim comments * update migrate snapshots for new minimizeDiff blank-line behavior * update cli create snapshots for new minimizeDiff blank-line behavior --------- Co-authored-by: jyc.dev <jycouet@gmail.com>
| * For each matching file, the `edit` callback is called with the file content, | ||
| * and should return the new content (or `false` to abort editing that file). | ||
| * | ||
| * Note: always adds excludes for `node_modules` and dot-prefixed directories |
There was a problem hiding this comment.
| * Note: always adds excludes for `node_modules` and dot-prefixed directories | |
| * Note: `node_modules` and dot-prefixed directories are always excluded. |
Should this also mention build and dist? Maybe link to the source for the curious? Should there be an option to override this?
There was a problem hiding this comment.
Mhmm yeah, maybe it should. On the other hand it wouldn't cause any problems, because your next build is just going to override it. But in node_modules it could cause problems as this is sometimes treated as the source.
| const cmd = resolveCommand(options.packageManager, 'execute-local', [ | ||
| 'prettier', | ||
| '--write', | ||
| '--ignore-unknown', | ||
| ...options.filesToFormat | ||
| ])!; | ||
| await run(cmd.command, cmd.args, options.cwd, 'Formatting modified files'); |
There was a problem hiding this comment.
| const cmd = resolveCommand(options.packageManager, 'execute-local', [ | |
| 'prettier', | |
| '--write', | |
| '--ignore-unknown', | |
| ...options.filesToFormat | |
| ])!; | |
| await run(cmd.command, cmd.args, options.cwd, 'Formatting modified files'); | |
| if (options.strategy === 'files-only') { | |
| const cmd = resolveCommand(options.packageManager, 'execute-local', [ | |
| 'prettier', | |
| '--write', | |
| '--ignore-unknown', | |
| ...options.filesToFormat | |
| ])!; | |
| await run(cmd.command, cmd.args, options.cwd, 'Formatting modified files'); | |
| return; | |
| } | |
| void options.strategy satisfies never; |
The second if is not an early return, we can make each enum explicit. And future enums will have less git diffs.
There was a problem hiding this comment.
whoops, I missed that the previous check has a fall through logic. Ignore this.
| --- | ||
|
|
||
| `sv migrate` migrates Svelte(Kit) codebases. It delegates to the [`svelte-migrate`](https://www.npmjs.com/package/svelte-migrate) package. | ||
| `sv migrate` migrates Svelte(Kit) codebases. Some migrations are built into `sv`; older migrations are run through [`svelte-migrate@1`](https://www.npmjs.com/package/svelte-migrate). |
There was a problem hiding this comment.
I meant sv migrate vs svelte-migrate? How does a user decide when to use which?
| for (const dependency of dependencies) { | ||
| if (dependency.dev && !data.devDependencies) data.devDependencies = {}; | ||
| if (!dependency.dev && !data.dependencies) data.dependencies = {}; | ||
|
|
||
| const dependencies = dependency.dev ? data.devDependencies! : data.dependencies!; | ||
|
|
||
| if (!dependencies[dependency.pkg] || dependencies[dependency.pkg] !== dependency.version) { | ||
| modified = true; | ||
| dependencies[dependency.pkg] = dependency.version; | ||
| } | ||
| } |
There was a problem hiding this comment.
| for (const dependency of dependencies) { | |
| if (dependency.dev && !data.devDependencies) data.devDependencies = {}; | |
| if (!dependency.dev && !data.dependencies) data.dependencies = {}; | |
| const dependencies = dependency.dev ? data.devDependencies! : data.dependencies!; | |
| if (!dependencies[dependency.pkg] || dependencies[dependency.pkg] !== dependency.version) { | |
| modified = true; | |
| dependencies[dependency.pkg] = dependency.version; | |
| } | |
| } | |
| for (const { dev, pkg, version } of dependencies) { | |
| const dependency = dev ? 'devDependencies' : 'dependencies'; | |
| data[dependency] ??= {}; | |
| if (data[dependency][pkg] !== version) { | |
| modified = true; | |
| data[dependency][pkg] = version; | |
| } | |
| } |

Relates #1111
Closes #1124
Description
This PR lays the groundwork for making
sv migratethe new home for Svelte migrations.It does a few things:
svelte-migrateto a new major version so it can be deprecated in favor ofsv migratesv addover the last two yearsnpx svelte-migrate@1sv addarchitectureMigration system
The new system is built around two concepts: migrations and migration tasks.
A migration is the top-level wrapper. It is similar to what we had before and will usually be added alongside a new version release, though not necessarily only for major releases.
A migration task is the actual execution unit responsible for applying part of a migration. Larger migrations can be split into multiple tasks. For example,
sveltekit-3currently consists of separate tasks forpackage.json,svelte.config.js, and environment variable changes.Tasks can be required or optional. Optional tasks can be selected or deselected by the user, which has a few important benefits:
Each task receives almost the same parameters as an addon, with only minor differences. This allows migrations to re-use addon functionality directly. For example, the
sveltekit-3migration calls theexperimentaladdon to updatepackage.jsonand the relevant peer dependencies.Multi-file migrations
To support migrations that need to edit multiple files, this PR introduces
sv.filesin addition tosv.file:Migrating
Pending work
lint checkWe decided against this for nowWe decided against this for nowsvelte-checksv.filessv migrateenv-varsmigrationFix and bumpesrapIt currently generates a lot of new lines where the previous content did not have them.This may be difficult and could potentially require a major bump foresrap.esrapas it takes theastas an argument and is unaware of the input. Therefore implemented based on a text diff library that does the job pretty goodpreserveOriginalNewlines$app/environmentto$app/envcheck migration for app-state (legacy) and see if we can use that one or if we should rewrite itShould be fine, migration was published over 1.5 years agoexpose an api for migrations, so that we can use it from the playground, vs code extension and whateverwill be implemented at a later pointChecklist