Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/unjs/codeup
Automated codebase updater [POC]
https://github.com/unjs/codeup
Last synced: about 2 months ago
JSON representation
Automated codebase updater [POC]
- Host: GitHub
- URL: https://github.com/unjs/codeup
- Owner: unjs
- License: mit
- Created: 2024-05-03T12:34:19.000Z (6 months ago)
- Default Branch: main
- Last Pushed: 2024-05-21T01:49:37.000Z (6 months ago)
- Last Synced: 2024-05-21T03:12:16.785Z (6 months ago)
- Language: TypeScript
- Homepage:
- Size: 79.1 KB
- Stars: 28
- Watchers: 1
- Forks: 0
- Open Issues: 3
-
Metadata Files:
- Readme: README.md
- Changelog: CHANGELOG.md
- License: LICENSE
Awesome Lists containing this project
README
# codeup
[![npm version](https://img.shields.io/npm/v/codeup?color=yellow)](https://npmjs.com/package/codeup)
[![npm downloads](https://img.shields.io/npm/dm/codeup?color=yellow)](https://npmjs.com/package/codeup)Automated codebase updater.
> [!IMPORTANT]
> This project a proof of concept in the current state.## Why?
Manually applying a change across multiple repositotires can become tiresome.
Codeup exposes conventional utils and a CLI to make it easier to migrate code and apply changes automatically and programmatically.
## Defining actions
You can define shared actions using codeup. See [./actions](./actions/) dir for some examples.
```ts
import { defineAction } from "codeup";export default defineAction({
meta: {
name: "",
description: "",
date: "",
},
async filter({ utils, logger }) {},
async apply({ utils, logger }) {},
});
```**Example:**
```ts [eslint-flat.ts]
import { defineAction } from "codeup";export default defineAction({
meta: {
name: "eslint-flat",
description: "Upgrade to eslint flat config with unjs preset",
date: "2024-05-03",
},
async filter({ utils }) {
// Only apply if legacy eslint config is found
return (
(await utils.existsWithAnyExt(".eslintrc")) &&
!(await utils.existsWithAnyExt("eslint.config"))
);
},
async apply({ utils }) {
// Migrate to new eslint config
const eslintRC = await utils.readJSON(".eslintrc");
const eslintignore = (await utils.readLines(".eslintignore")) || [];
await utils.write(
"eslint.config.mjs",
getConfigTemplate({
rules: eslintRC?.rules || {},
ignores: eslintignore.filter(
(i) => !["", "node_modules", "dist", "coverage"].includes(i),
),
}),
);// Remove legacy eslint config files
await utils.remove(".eslintrc");
await utils.remove(".eslintignore");// Update package.json scripts
await utils.updatePackageJSON((pkg) => {
if (!pkg.scripts) {
return;
}
for (const name in pkg.scripts) {
if (pkg.scripts[name].includes("eslint")) {
pkg.scripts[name] = pkg.scripts[name].replace(/--ext\s+\S+\s/, "");
}
}
});// Ensure latest eslint and preset versions are installed
await utils.addDevDependency([
"eslint@^9.0.0",
"eslint-config-unjs@^0.3.0",
]);// Run lint:fix script once
await utils.runScript("lint:fix");
},
});function getConfigTemplate(opts: {
rules: Record;
ignores: string[];
}) {
return /* js */ `
import unjs from "eslint-config-unjs";// https://github.com/unjs/eslint-config
export default unjs({
ignores: ${JSON.stringify(opts.ignores || [], undefined, 2)},
rules: ${JSON.stringify(opts.rules || {}, undefined, 2)},
});
`.trim();
}```
## Apply Actions
You can use `codeup apply` CLI to apply actions from a local directory or remote source (powered by [unjs/giget](https://giget.unjs.io)).
By default actions order will be sorted by date and name.
```sh
# Run all actions from local dir
npx codeup apply --actions path/to/actions/dir# Run actions from a github source
npx codeup apply --actions gh:unjs/codeup/actions/unjs
```## Utils
You can directly use codeup utils as a library use use them within actions context.
```js
import { readJSON, runScript } from "codeup/utils";
```## File System
### `append(path, contents, opts?: { newLine? })`
Append text to a file (with a newline by default)
### `exists(path, opts?: { withAnyExt? })`
Checks if a file or directory exists in path
### `existsWithAnyExt(path)`
Checks if a file or directory exists in path with any extension (input path should not contain extension)
### `findUp(name)`
Try to find a file in the current working directory or any parent directories
### `read(path)`
Try to read a text file and returns its contents
### `readLines(path)`
Read a text file and return its contents as an array of lines
### `remove(path, opts?: { log? })`
Try to remove a file or directory
### `resolve(path)`
Resolves a path relative to the current working directory.
### `update(path, fn, opts?: { log? })`
Read a file and update its contents
Returns the updated contents or the old one
### `write(path, contents, opts?: { skipIfExists?, log? })`
Write text contents to a file
## Json
### `readJSON(path)`
Try to read a JSON file
### `updateJSON(path, updater)`
Try to update a JSON file using an updater function and return updated JSON
### `writeJSON(path, json, opts?)`
Write a JSON file
## Package Json
### `addDependency(name, opts?)`
Add a dependency to the project using detected package manager
### `addDevDependency(name, opts?)`
Add a dev dependency to the project using detected package manager
### `readPackageJSON()`
Try to read the closest package.json file
### `removeDependency(name, opts?)`
Remove a dependency from the project using detected package manager
### `runScript(name)`
Run a `package.json` script using detected package manager
### `updatePackageJSON()`
Try to update the closest package.json file
## Programmatic API
You can integrate codeup in your workflows using programmatic API instead of CLI.
```js
import { applyActionsFrom } from "codeup";
```### `applyAction(action, cwd)`
Apply an action within context and working directory.
### `applyActionFromFile(path, workingDir)`
Load and apply action from file.
### `applyActions(actions, cwd, opts?: { sort })`
Apply multiple actions within context and working directory.
If `opts.sort` is true, actions will be sorted by date or name otherwise in the order they are provided.
### `applyActionsFrom(source, cwd)`
Load and apply actions from a remote or local source.
### `applyActionsFromDir(actionsDir, cwd)`
Load and apply actions from directory.
### `createContext(cwd, name?)`
Create an action context from a working directory.
### `defineAction(action)`
### `getActionName(action)`
Get action name from action object.
### `loadActionFromFile(path)`
Load action from file.
### `loadActionsFromDir(actionsDir)`
Load actions from a directory.
### `runWithContext(context, fn)`
Run a function within a context.
### `sortActions(actions)`
Sort actions by date or name.
### `useContext()`
Get the current action context or create a new one from the working directory.
## Development
local development
- Clone this repository
- Install latest LTS version of [Node.js](https://nodejs.org/en/)
- Enable [Corepack](https://github.com/nodejs/corepack) using `corepack enable`
- Install dependencies using `pnpm install`
- Enable stub mode using `pnpm build --stub`## License
Published under the [MIT](https://github.com/unjs/codeup/blob/main/LICENSE) license.
Made by [@pi0](https://github.com/pi0) and [community](https://github.com/unjs/codeup/graphs/contributors) 💛
---
_🤖 auto updated with [automd](https://automd.unjs.io)_