diff --git a/.agents/skills/migrate-to-rstack-cli/SKILL.md b/.agents/skills/migrate-to-rstack-cli/SKILL.md new file mode 100644 index 0000000..55f7a71 --- /dev/null +++ b/.agents/skills/migrate-to-rstack-cli/SKILL.md @@ -0,0 +1,58 @@ +--- +name: migrate-to-rstack-cli +description: Use when migrating projects from standalone Rsbuild, Rslib, Rstest, Rslint, Rspress, or lint-staged tooling to the unified `rstack` package, `rs` commands, and `rstack.config.*`. +--- + +# Migrate to Rstack CLI + +Rstack CLI is the `rstack` package, exposed through the `rs` binaries. It provides one CLI, one config file, and a consistent workflow for the Rstack JavaScript toolchain. + +## Tool References + +Read every matching reference before editing. Load only the tools present in the project. + +- `@rsbuild/core`, `rsbuild.config.*`, `rsbuild` commands, or Rsbuild types: [rsbuild.mdx](references/rsbuild.mdx) +- `@rslib/core`, `rslib.config.*`, `rslib` commands, or Rslib types: [rslib.mdx](references/rslib.mdx) +- `@rstest/core`, `@rstest/adapter-*`, `rstest.config.*`, `rstest` commands, or test imports: [rstest.mdx](references/rstest.mdx) +- `@rslint/core`, `rslint.config.*`, `rslint` commands, or lint imports: [rslint.mdx](references/rslint.mdx) +- `@rspress/core`, `rspress.config.*`, `rspress` commands, themes, or plugins: [rspress.mdx](references/rspress.mdx) +- `lint-staged`, its dotfile configs, `lint-staged.config.*`, or a `lint-staged` manifest key: [lint-staged.mdx](references/lint-staged.mdx) + +## Workflow + +1. Inspect manifests, workspace catalogs, lock files, scripts, standalone configs, Git hooks, TypeScript `types`, and source imports. +2. Read the matching references and inventory behavior that must survive: config functions, CLI arguments, plugins, presets, adapters, custom config paths, and chained commands. +3. Check the latest `rstack` version and inspect its Node.js engine and underlying tool versions. Resolve plugin and adapter peer ranges first; upgrade incompatible extensions or stop when no compatible version exists. Add `rstack` using the repository's existing package manager and version convention, usually as a development dependency. +4. Create `rstack.config.ts`. Move each standalone config into its corresponding `define.*` registration. +5. Rewrite commands and imports as directed by the references. +6. Search again for old direct imports, binaries, config paths, manifest entries, and type references. Remove only entries with no remaining direct or runtime use and no unresolved peer compatibility requirement. +7. Delete a standalone config only after its behavior is represented in `rstack.config.*`. +8. Refresh the lockfile with the repository's package manager. Confirm the expected tool version changes and resolve peer dependency warnings. +9. Run the repository's existing migrated scripts and required checks. Compare generated artifacts or runtime behavior where relevant. + +Underlying Rsbuild, Rslib, Rstest, and Rslint packages remain transitive dependencies of `rstack`. Do not require their names to disappear from the lockfile; require obsolete direct manifest entries and imports to disappear. + +## Configuration Rules + +Use one of the default names: `rstack.config.ts`, `.js`, `.mts`, or `.mjs`. Use `rs -c ` or `rs --config ` for a custom path. + +```ts +import { define } from 'rstack'; + +define.app({ + // Rsbuild config +}); + +define.test({ + // Rstest config +}); +``` + +Prefer async config functions and dynamic imports for runtime plugins and presets: + +```ts +define.lint(async () => { + const { js, ts } = await import('rstack/lint'); + return [js.configs.recommended, ts.configs.recommended]; +}); +``` diff --git a/.agents/skills/migrate-to-rstack-cli/references/lint-staged.mdx b/.agents/skills/migrate-to-rstack-cli/references/lint-staged.mdx new file mode 100644 index 0000000..b347270 --- /dev/null +++ b/.agents/skills/migrate-to-rstack-cli/references/lint-staged.mdx @@ -0,0 +1,25 @@ +# lint-staged Migration + +Read this reference when the project uses the `lint-staged` binary, a lint-staged dotfile config, `lint-staged.config.*`, or a `lint-staged` key in `package.json`. + +## Steps + +1. Replace direct `lint-staged` script invocations with `rs staged`. +2. Move a plain task map into `define.staged` in `rstack.config.*`. +3. Remove the old manifest key or config file. +4. Remove the direct `lint-staged` dependency only when no script, config, or programmatic API still uses it. + +## Config Pattern + +```ts +import { define } from 'rstack'; + +define.staged({ + '*.{ts,tsx,js,jsx}': ['rs lint --fix', 'prettier -w'], + '*.{json,md}': 'prettier -w', +}); +``` + +## Unsupported Cases + +Do not carry lint-staged CLI flags to `rs staged`; they are not forwarded. Keep standalone lint-staged when the workflow requires function-based configs, CLI options, or behavior outside a plain task map. diff --git a/.agents/skills/migrate-to-rstack-cli/references/rsbuild.mdx b/.agents/skills/migrate-to-rstack-cli/references/rsbuild.mdx new file mode 100644 index 0000000..e153aeb --- /dev/null +++ b/.agents/skills/migrate-to-rstack-cli/references/rsbuild.mdx @@ -0,0 +1,35 @@ +# Rsbuild Migration + +Read this reference when the project uses `@rsbuild/core`, `rsbuild.config.*`, `rsbuild` commands, Rsbuild client types, or `@rsbuild/core/types`. + +## Steps + +1. Replace `rsbuild dev`, `rsbuild build`, and `rsbuild preview` with `rs dev`, `rs build`, and `rs preview`. Preserve supported arguments after the new command. +2. Move the old config export into `define.app`. Preserve async functions, config parameters, plugins, and all options. +3. Replace custom `--config` paths with the migrated `rstack.config.*` path. +4. Replace Rsbuild client and type references: + - `/// ` to `/// ` + - `"types": ["@rsbuild/core/types"]` to `"types": ["rstack/types"]` + - Type-only imports from `@rsbuild/core/types` to `rstack/types` +5. Keep Rsbuild plugins such as `@rsbuild/plugin-react` and `@rsbuild/plugin-vue`, but verify that their peer ranges support the `@rsbuild/core` version installed through `rstack`. Upgrade incompatible plugins before migrating; retaining an older direct core does not make Rstack use it. +6. Search for remaining direct `@rsbuild/core` imports. Remove the direct dependency when no source or runtime API still needs it. +7. Delete `rsbuild.config.*` after the migrated app commands load equivalent config. + +## Config Pattern + +```ts +import { define } from 'rstack'; + +define.app(async () => { + const { pluginReact } = await import('@rsbuild/plugin-react'); + return { + plugins: [pluginReact()], + }; +}); +``` + +If tests also use Rstest, read [rstest.mdx](rstest.mdx). `rs test` derives an Rsbuild test extension from `define.app` unless `define.test` sets `extends`. + +## Validate + +Run the migrated app build script. Smoke-test dev or preview when those scripts changed or their behavior is material. diff --git a/.agents/skills/migrate-to-rstack-cli/references/rslib.mdx b/.agents/skills/migrate-to-rstack-cli/references/rslib.mdx new file mode 100644 index 0000000..fb160de --- /dev/null +++ b/.agents/skills/migrate-to-rstack-cli/references/rslib.mdx @@ -0,0 +1,29 @@ +# Rslib Migration + +Read this reference when the project uses `@rslib/core`, `rslib.config.*`, `rslib` commands, library build config, or Rslib type imports. + +## Steps + +1. Replace the `rslib` executable prefix with `rs lib`. Preserve supported arguments after `rs lib`. +2. Move the old config export into `define.lib`. Preserve async functions, config parameters, plugins, and all options. +3. Keep build plugins, but verify that Rsbuild plugin peer ranges support the core version installed through `rstack`. Upgrade incompatible plugins before migrating. +4. Replace `@rslib/core/types` references with `rstack/types` where applicable. +5. Replace custom `--config` paths with the migrated `rstack.config.*` path. +6. Search for remaining direct `@rslib/core` imports. Remove the direct dependency only when no source or runtime API still needs it. +7. Delete `rslib.config.*` after the migrated library commands load equivalent config. + +## Config Pattern + +```ts +import { define } from 'rstack'; + +define.lib({ + lib: [{ dts: true }], +}); +``` + +If tests also use Rstest, read [rstest.mdx](rstest.mdx). `rs test` derives an Rslib test extension from `define.lib` unless `define.test` sets `extends`. + +## Validate + +Run the migrated library build script and compare its outputs. diff --git a/.agents/skills/migrate-to-rstack-cli/references/rslint.mdx b/.agents/skills/migrate-to-rstack-cli/references/rslint.mdx new file mode 100644 index 0000000..b0fe1f8 --- /dev/null +++ b/.agents/skills/migrate-to-rstack-cli/references/rslint.mdx @@ -0,0 +1,37 @@ +# Rslint Migration + +Read this reference when the project uses `@rslint/core`, `rslint.config.*`, `rslint` commands, or Rslint config imports. + +## Steps + +1. Replace the `rslint` executable prefix with `rs lint`. For example, replace `rslint --fix` with `rs lint --fix`. +2. Move the old config into `define.lint`. Dynamically import presets from `rstack/lint` inside an async config function. +3. Replace direct config/API imports from `@rslint/core` with exports from `rstack/lint` where available. +4. Replace custom `--config` paths with the migrated `rstack.config.*` path. +5. Remove `@rslint/core` only when no uncovered direct runtime API remains. Delete `rslint.config.*`. + +## Config Pattern + +```ts +import { define } from 'rstack'; + +define.lint(async () => { + const { js, ts } = await import('rstack/lint'); + return [js.configs.recommended, ts.configs.recommended]; +}); +``` + +## Script Pattern + +```json +{ + "scripts": { + "lint": "rs lint && prettier -c .", + "lint:write": "rs lint --fix && prettier -w ." + } +} +``` + +## Validate + +Run the non-writing lint script. diff --git a/.agents/skills/migrate-to-rstack-cli/references/rspress.mdx b/.agents/skills/migrate-to-rstack-cli/references/rspress.mdx new file mode 100644 index 0000000..a0e49f5 --- /dev/null +++ b/.agents/skills/migrate-to-rstack-cli/references/rspress.mdx @@ -0,0 +1,29 @@ +# Rspress Migration + +Read this reference when the project uses `@rspress/core`, `rspress.config.*`, `rspress` commands, docs config, themes, or plugins. + +## Steps + +1. Keep `@rspress/core` installed as a direct dependency. `rs doc` requires this optional Rstack peer dependency. +2. Replace the `rspress` executable prefix with `rs doc`: `rspress dev` to `rs doc`, `rspress build` to `rs doc build`, and `rspress preview` to `rs doc preview`. Preserve supported arguments. +3. Move the old config export into `define.doc`. Preserve async functions, themes, plugins, and all options. +4. Replace custom `--config` paths with the migrated `rstack.config.*` path. +5. Keep Rspress-specific type imports from `@rspress/core`; Rstack does not re-export them. +6. Keep themes, plugins, and docs UI packages. Delete `rspress.config.*` only after the migrated docs commands load equivalent config. + +## Config Pattern + +```ts +import { define } from 'rstack'; + +define.doc({ + root: 'docs', + title: 'Project docs', +}); +``` + +Use an async config and dynamic imports when plugins or themes require runtime imports. + +## Validate + +Run the migrated docs build script. Smoke-test dev or preview when those workflows changed. diff --git a/.agents/skills/migrate-to-rstack-cli/references/rstest.mdx b/.agents/skills/migrate-to-rstack-cli/references/rstest.mdx new file mode 100644 index 0000000..e6a855b --- /dev/null +++ b/.agents/skills/migrate-to-rstack-cli/references/rstest.mdx @@ -0,0 +1,31 @@ +# Rstest Migration + +Read this reference when the project uses `@rstest/core`, `@rstest/adapter-rsbuild`, `@rstest/adapter-rslib`, `rstest.config.*`, `rstest` commands, or Rstest imports and types. + +## Steps + +1. Replace the `rstest` executable prefix with `rs test`. Preserve supported arguments, such as `-w`, after `rs test`. +2. Move test options into `define.test`. +3. When `define.app` or `define.lib` exists, remove standard `withRsbuildConfig()` or `withRslibConfig()` wiring and its adapter dependency. Rstack derives that extension unless `define.test` sets `extends`. +4. Preserve explicit custom `extends` values. Keep any adapter or package still imported by that custom extension. +5. Replace imports and TypeScript `types` entries: + - `@rstest/core` to `rstack/test` + - `@rstest/core/globals` to `rstack/test/globals` + - `@rstest/core/importMeta` to `rstack/test/importMeta` +6. Search for remaining direct core or adapter imports. Remove `@rstest/core` and adapter dependencies only when no direct use remains. +7. Delete `rstest.config.*` after all behavior is represented or intentionally supplied by automatic app/library extension. + +## Config Pattern + +```ts +import { define } from 'rstack'; + +define.test({ + setupFiles: ['./tests/setup.ts'], + testEnvironment: 'happy-dom', +}); +``` + +## Validate + +Run the migrated test script.