Skip to content

Commit

Permalink
feat: introduce upgrade-rspeedy (#145)
Browse files Browse the repository at this point in the history
<!--
  Thank you for submitting a pull request!

We appreciate the time and effort you have invested in making these
changes. Please ensure that you provide enough information to allow
others to review your pull request.

Upon submission, your pull request will be automatically assigned with
reviewers.

If you want to learn more about contributing to this project, please
visit:
https://github.com/lynx-family/lynx-stack/blob/main/CONTRIBUTING.md.
-->

## Summary

<!-- Can you explain the reasoning behind implementing this change? What
problem or issue does this pull request resolve? -->

Add a simple CLI program for upgrading Rspeedy-related packages.

```bash
npx upgrade-rspeedy@latest
```

<!-- It would be helpful if you could provide any relevant context, such
as GitHub issues or related discussions. -->

## Checklist

<!--- Check and mark with an "x" -->

- [x] **Tests updated** (or not required).
- [x] Documentation updated (or not required). See:
lynx-family/lynx-website#30
  • Loading branch information
colinaaa authored Mar 10, 2025
1 parent 0634f4b commit afc2939
Show file tree
Hide file tree
Showing 17 changed files with 732 additions and 1 deletion.
3 changes: 2 additions & 1 deletion .changeset/config.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,8 @@
],
[
"@lynx-js/rspeedy",
"create-rspeedy"
"create-rspeedy",
"upgrade-rspeedy"
]
],
"linked": [],
Expand Down
2 changes: 2 additions & 0 deletions .changeset/dull-olives-move.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
---
---
1 change: 1 addition & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ jobs:
sudo apt-get install -y iproute2 &&
pnpm run test
--project rspeedy
--project upgrade-rspeedy
--project 'rspeedy/*'
--test-timeout=50000
--coverage
Expand Down
55 changes: 55 additions & 0 deletions packages/rspeedy/upgrade-rspeedy/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
<p align="center">
<a href="https://lynxjs.org/rspeedy" target="blank"><img src="https://lf-lynx.tiktok-cdns.com/obj/lynx-artifacts-oss-sg/lynx-website/assets/rspeedy-banner.png" alt="Rspeedy Logo" /></a>
</p>

# Upgrade Rspeedy

<p>
<a aria-label="NPM version" href="https://www.npmjs.com/package/upgrade-rspeedy">
<img alt="" src="https://img.shields.io/npm/v/upgrade-rspeedy?logo=npm">
</a>
<a aria-label="License" href="https://www.npmjs.com/package/upgrade-rspeedy">
<img src="https://img.shields.io/badge/License-Apache--2.0-blue" alt="license" />
</a>
</p>

The easiest way to upgrade Rspeedy-related packages.

This CLI tool helps to update the `package.json` with corresponding version. Both `latest` and `canary` are supported.

## Latest version

To update to the latest `@lynx-js/rspeedy` and its plugins, use the following command in your `@lynx-js/rspeedy` project:

```bash
npx upgrade-rspeedy@latest
```

Then all the Rspeedy-related packages' version would be updated. Run your package manager to install the dependencies:

```bash
npm install
# Or
yarn install
# Or
pnpm install
```

## Canary version

To update to one of the canary version of `@lynx-js/rspeedy`, use the following command:

```bash
# Replace the version with your canary version
npx upgrade-rspeedy-canary@0.8.2-canary-20250309-870106fc
```

Then all the Rspeedy-related packages' version would be updated with `npm:` alias. Run your package manager to install the dependencies:

```bash
npm install
# Or
yarn install
# Or
pnpm install
```
7 changes: 7 additions & 0 deletions packages/rspeedy/upgrade-rspeedy/__mocks__/fs.cjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
// Copyright 2024 The Lynx Authors. All rights reserved.
// Licensed under the Apache License Version 2.0 that can be found in the
// LICENSE file in the root directory of this source tree.

const { fs } = require('memfs')

module.exports = fs
55 changes: 55 additions & 0 deletions packages/rspeedy/upgrade-rspeedy/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
{
"name": "upgrade-rspeedy",
"version": "0.8.3",
"description": "Upgrade Rspeedy-related packages",
"keywords": [
"webpack",
"Rspack",
"Rsbuild",
"Rspeedy",
"Lynx"
],
"repository": {
"type": "git",
"url": "https://github.com/lynx-family/lynx-stack.git",
"directory": "packages/rspeedy/upgrade-rspeedy"
},
"license": "Apache-2.0",
"author": {
"name": "Qingyu Wang",
"email": "colinwang.0616@gmail.com"
},
"type": "module",
"exports": null,
"bin": {
"upgrade-rspeedy": "./dist/upgrade-rspeedy.js"
},
"files": [
"dist/upgrade-rspeedy.js",
"CHANGELOG.md",
"README.md"
],
"scripts": {
"build": "rslib build",
"test": "vitest"
},
"devDependencies": {
"@lynx-js/qrcode-rsbuild-plugin": "workspace:*",
"@lynx-js/react": "workspace:*",
"@lynx-js/react-rsbuild-plugin": "workspace:*",
"@lynx-js/rspeedy": "workspace:*",
"@lynx-js/types": "^3.2.0",
"@rsbuild/plugin-less": "1.1.1",
"@rsbuild/plugin-sass": "1.2.2",
"commander": "^13.1.0",
"detect-indent": "^7.0.1",
"memfs": "^4.17.0",
"picocolors": "^1.1.1",
"rsbuild-plugin-tailwindcss": "0.2.0",
"rslog": "^1.2.3",
"type-fest": "^4.37.0"
},
"engines": {
"node": ">=18"
}
}
12 changes: 12 additions & 0 deletions packages/rspeedy/upgrade-rspeedy/rslib.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { defineConfig } from '@rslib/core'

export default defineConfig({
lib: [
{ format: 'esm', syntax: 'es2022' },
],
source: {
entry: {
'upgrade-rspeedy': './src/upgrade-rspeedy.ts',
},
},
})
147 changes: 147 additions & 0 deletions packages/rspeedy/upgrade-rspeedy/src/install.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
// Copyright 2024 The Lynx Authors. All rights reserved.
// Licensed under the Apache License Version 2.0 that can be found in the
// LICENSE file in the root directory of this source tree.
import fs from 'node:fs'
import { EOL } from 'node:os'
import path from 'node:path'

import detectIndent from 'detect-indent'
import color from 'picocolors'
import { logger } from 'rslog'
import type { PackageJson } from 'type-fest'

import { devDependencies } from './version.js'

const LYNX_RSPEEDY = '@lynx-js/rspeedy'

export async function install(cwd: string): Promise<void> {
const packageJSONPath = path.resolve(cwd, 'package.json')

if (!fs.existsSync(packageJSONPath)) {
const message = `${
color.underline(color.yellow(packageJSONPath))
} not found. Please run ${
color.bold('upgrade-rspeedy')
} in your Rspeedy project.`
logger.error(message)

throw new Error(message)
}

try {
const content = await fs.promises.readFile(packageJSONPath, 'utf-8')
const pkg = JSON.parse(content) as PackageJson

if (
pkg.dependencies?.[LYNX_RSPEEDY] === undefined
&& pkg.devDependencies?.[LYNX_RSPEEDY] === undefined
) {
throw new Error(
`No ${color.yellow(LYNX_RSPEEDY)} found in ${packageJSONPath}.
Please run ${color.bold('upgrade-rspeedy')} in your Rspeedy project.`,
)
}

const { indent } = detectIndent(content)

console.info()
const dependenciesUpdated = updateDependencies(
pkg,
packageJSONPath,
'dependencies',
)
console.info()
const devDependenciesUpdated = updateDependencies(
pkg,
packageJSONPath,
'devDependencies',
)
console.info()

if (dependenciesUpdated || devDependenciesUpdated) {
await fs.promises.writeFile(
packageJSONPath,
JSON.stringify(pkg, null, indent) + EOL,
'utf-8',
)
logger.success(`${color.yellow(packageJSONPath)} has been updated.`)
logger.success(
`Please install the dependencies with your package manager.`,
)
}
} catch (error) {
logger.error(error)
throw error
}
}

function updateDependencies(
pkg: PackageJson,
packageJSONPath: string,
name: 'dependencies' | 'devDependencies',
) {
const dependencies = pkg[name]
if (!dependencies) {
logger.info(
`No ${color.yellow(name)} is found in ${
color.underline(packageJSONPath)
}`,
)
return false
}

const updatedDependencies = findDependencies(dependencies)
.filter(([, { original, target }]) => original !== target)

if (updatedDependencies.length === 0) {
logger.info(
`No ${color.yellow(name)} need to be updated in ${
color.underline(packageJSONPath)
}`,
)
return false
} else {
const sep = '\n - '
logger.info(
`Updated ${color.yellow(name)}:\n${sep}${
updatedDependencies.map(([name, { original, target }]) => {
return `${color.cyan(name)}: ${color.dim(original)} -> ${
color.green(target)
}`
}).join(sep)
}`,
)
}

updatedDependencies.forEach(([dependency, { target }]) => {
dependencies[dependency] = target
})

return true
}

const targetDependencies = new Map(Object.entries(devDependencies ?? {}))

function findDependencies(
dependencies: Record<string, string | undefined>,
) {
return Object.entries(dependencies)
.map(([name, original]) => {
if (
targetDependencies.has(name)
// Avoid install packages like `commander` or `type-fest`
&& (name.startsWith('@lynx-js/') || name.includes('rsbuild'))
) {
return [
name,
{
original,
target: targetDependencies.get(name)!,
},
] as const
}
return null
})
.filter(i => i !== null)
}
34 changes: 34 additions & 0 deletions packages/rspeedy/upgrade-rspeedy/src/main.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
// Copyright 2024 The Lynx Authors. All rights reserved.
// Licensed under the Apache License Version 2.0 that can be found in the
// LICENSE file in the root directory of this source tree.
import { Command } from 'commander'
import { logger } from 'rslog'

import { install } from './install.js'
import { version } from './version.js'

export async function main(
cwd?: string,
argv?: readonly string[],
): Promise<void> {
const program = new Command('upgrade-rspeedy')

// If not called through a package manager,
// output a blank line to keep the greet log nice.
const { npm_execpath } = process.env
if (
!npm_execpath || npm_execpath.includes('npm-cli.js')
|| npm_execpath.includes('npx-cli.js')
) {
console.info()
}

logger.greet(`Upgrade Rspeedy v${version}\n`)

program
.helpCommand(false)
.description('Upgrade the Rspeedy-related packages')
.action(() => install(cwd ?? process.cwd()))

await program.parseAsync(argv)
}
8 changes: 8 additions & 0 deletions packages/rspeedy/upgrade-rspeedy/src/upgrade-rspeedy.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
#!/usr/bin/env node

// Copyright 2024 The Lynx Authors. All rights reserved.
// Licensed under the Apache License Version 2.0 that can be found in the
// LICENSE file in the root directory of this source tree.
import { main } from './main.js'

await main()
21 changes: 21 additions & 0 deletions packages/rspeedy/upgrade-rspeedy/src/version.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
// Copyright 2024 The Lynx Authors. All rights reserved.
// Licensed under the Apache License Version 2.0 that can be found in the
// LICENSE file in the root directory of this source tree.

import { createRequire } from 'node:module'

import type { PackageJson } from 'type-fest'

const require = createRequire(import.meta.url)

// Using `import('../package.json', { with: { type: 'json' } })` will cause NodeJS print a
// experimental warning.
// eslint-disable-next-line import/no-commonjs
const pkg = require(
'../package.json',
) as PackageJson

const version: PackageJson['version'] = pkg.version
const devDependencies: PackageJson['devDependencies'] = pkg.devDependencies

export { version, devDependencies }
Loading

0 comments on commit afc2939

Please sign in to comment.