An open API service indexing awesome lists of open source software.

https://github.com/weaponsforge/math

Simple math operations for testing publishing to the NPM registry
https://github.com/weaponsforge/math

Last synced: 2 months ago
JSON representation

Simple math operations for testing publishing to the NPM registry

Awesome Lists containing this project

README

          

## math

Simple math operations for testing publishing to the NPM registry from [totaltypescript](https://www.totaltypescript.com/how-to-create-an-npm-package).

This repository contains hands-on practice set up for:

- A TypeScript project with the latest settings
- Prettier, which both formats your code and checks that it's formatted correctly
- `@arethetypeswrong/cli`, which checks that your package exports are correct
- `tsup`, which compiles your TypeScript code to JavaScript
- `vitest`, which runs your tests
- GitHub Actions, which runs your CI process
- Changesets, which versions and publishes your package

## Steps

Summary of creating the code repository and other setup from [totaltypescript](https://www.totaltypescript.com/how-to-create-an-npm-package).

### 1. Git

Expand to view details

1. Initialize the repo
2. Setup a .gitignore
3. Create a new repository on GitHub
4. Push to GitHub

### 2. **`package.json`**

Expand to view details

1. Create a package.json file
2. Add the license field
3. Add a LICENSE file
4. Add a README file

### 3. TypeScript

Expand to view details

1. Install TypeScript

`npm install --save-dev typescript`

2. Setup a `tsconfig.json` file

3. Configure your `tsconfig.json` for the DOM
- If your code runs in the DOM (i.e. requires access to `document`, `window`, or `localStorage` etc), skip this step.
- If your code doesn't require access to DOM API's, add the following to your tsconfig.json (This prevents the DOM typings from being available in your code):
```json
{
"compilerOptions": {
/* other options */
"lib": ["es2022"]
}
}
```

4. Create a source file
- `/src/utils.ts`

5. Create an index file
- `/src/index.ts`

6. Set up a `build` script
- `"build": "tsc"`

7. Add `dist` to `.gitignore`

8. Set up a `CI` script
- `"ci": "npm run build"`

### 4. Prettier

Expand to view details

1. Install Prettier
- `npm install --save-dev prettier`

2. Set up a `.prettierrc`
```json
{
"semi": true,
"singleQuote": true,
"trailingComma": "all",
"printWidth": 80,
"tabWidth": 2
}
```

3. Set up a `format` script
- `"format": "prettier --write ."`

4. Set up a `check-format` script
- `"check-format": "prettier --check ."`

5. Adding to our `CI` script
- `"ci": "npm run build && npm run check-format"`

### 5. `exports`, `main` and `@arethetypeswrong/cli`

Expand to view details

**@arethetypeswrong/cli** is a tool that checks if your package exports are correct

1. Install `@arethetypeswrong/cli`
- `npm install --save-dev @arethetypeswrong/cli`

2. Set up a `check-exports` script
- `"check-exports": "attw --pack ."`

3. Setting `main`

Add a `main` field to your package.json with the following content:
- `"main": "dist/index.js"`

4. Fix the CJS warning
> If you don't want to support CJS (which I recommend), change the check-exports script to:

`"check-exports": "attw --pack . --ignore-rules=cjs-resolves-to-esm"`

> If you prefer to dual publish CJS and ESM, skip this step.

5. Adding to our `CI` script
- `"ci": "npm run build && npm run check-format && npm run check-exports"`

### 6. Using `tsup` to Dual Publish

Expand to view details

> "If you want to publish both CJS and ESM code, you can use tsup. This is a tool built on top of esbuild that compiles your TypeScript code into both formats.
>
> My personal recommendation would be to skip this step, and only ship ES Modules. This makes your setup significantly simpler, and avoids many of the pitfalls of dual publishing, like [Dual Package Hazard](https://github.com/GeoffreyBooth/dual-package-hazard)". - totaltypescript

1. Install `tsup`
- `npm install --save-dev tsup`
2. Create a `tsup.config.ts` file
3. Change the `build` script
- `"build": "tsup"`
4. Add an `exports` field in the package.json
```json
{
"exports": {
"./package.json": "./package.json",
".": {
"import": "./dist/index.js",
"default": "./dist/index.cjs"
}
}
}
```
5. Run `npm run check-exports'

### 6.1. Turn TypeScript into a linter

Expand to view details

> "We're no longer running tsc to compile our code. And tsup doesn't actually check our code for errors - it just turns it into JavaScript.This means that our ci script won't error if we have TypeScript errors in our code. Eek. Let's fix this." - totaltypescript

1. Add `noEmit` to `tsconfig.json`
```json
"compilerOptions": {
"noEmit": true
}
```

2. Remove unused fields from `tsconfig.json`

These are no longer needed in our new 'linting' setup.
```text
outDir
rootDir
sourceMap
declaration
declarationMap
```

3. Change `module` to `Preserve`

Change `module` to `Preserve` in the tsconfig.json.
```json
"compilerOptions": {
"module": "Preserve"
}
```
We can start importing TS files without `.js` extensions with this setting, e.g.:

`import { addition } from './utils'`

4. Add a `lint` script
- `"lint": "tsc"`

5. Add `lint` to your `ci` script
- `npm run build && npm run check-format && npm run check-exports && npm run lint`

### 7. Testing with Vitest

Expand to view details

**vitest** is a modern test runner for ESM and TypeScript.

1. Install `vitest`
- `npm install --save-dev vitest`

2. Create a test
- Create a `src/utils.test.ts` file with the following content:
```typescript
import { add } from "./utils.js";
import { test, expect } from "vitest";

test("add", () => {
expect(add(1, 2)).toBe(3);
});
```

3. Set up a `test` script
- Add a `test` script in the package.json file

`"test": "vitest run"`

4. Run the test script
- `npm test`

5. Set up `dev` script
- This step runs tests in watch mode while developing. Add the following the package.json file.

`"dev": "vitest"`

6. Adding to our `CI` script.
- Add the `test` script to your `ci` script

`"ci": "npm run build && npm run check-format && npm run check-exports && npm run lint && npm run test"`

### 8. Set up CI with GitHub Actions

Expand to view details

1. Create a `.github/workflows/ci.yml` file
- Refer to the file in the code repository.
2. Testing our workflow
- Push the file to the repository.
- Workflow should run on push

### 9. Publishing with Changesets

Expand to view details

> "Changesets is a tool that helps you version and publish your package. It's an incredible tool that I recommend to anyone publishing packages to npm." - totaltypescript

1. Install `@changesets/cli`
- `npm install --save-dev @changesets/cli`

2. Initialize Changesets
- This will create a .changeset folder in your project, containing a config.json file. This is also where your changesets will live.
- `npx changeset init`

3. Make changesets releases public
- Edit the `.changeset/config.json` file
- Change the `access` field to `public`. Setting it to public allows publishing your package to npm.
- `"access": "public"`

4. Set `commit` to `true`
- In `.changeset/config.json`, change the `commit` field to `true`
- This will commit the changeset to your repository after versioning.
- `"commit": true`

5. Set up a `local-release` script
- This script will run your CI process and then publish your package to npm. This will be the command you run when you want to release a new version of your package from your local machine.
- Add a `local-release` script to your package.json with the following content:
- `"local-release": "changeset version && changeset publish"`

6. Run `CI` in `prepublishOnly`
- This runs the CI process before publishing the package to NPM
- Add a prepublishOnly script to your package.json:
- `"prepublishOnly": "npm run ci"`

7. Add a changeset
- Run the command to add a changeset:
- `npx changeset`
- Mark the release as a `patch`, `minor` or `major` release
- Give it a description e.g., "Initial release"
- This will create a new file in the `.changeset` folder with the changeset.

8. Commit your changes
- Commit your changes to your repository
```
git add .
git commit -m "Prepare for initial release"
```

9. Run the `local-release` script
- Run the command to release your package
- This will run your CI process, version your package, and publish it to npm.
- `npm run local-release`

10. See your package on npm
- Go to `http://npmjs.com/package/`

11. Further reading about Changesets
- [Changesets GitHub Action](https://github.com/changesets/action)
- [PR Bot](https://github.com/changesets/bot)

## References

- TSConfig Cheat Sheet [[1]](https://www.totaltypescript.com/tsconfig-cheat-sheet)
- Changesets GitHub Action [[2]](https://github.com/changesets/action)
- PR Bot [[3]](https://github.com/changesets/bot)
- Dual Package Hazard [[4]](https://github.com/GeoffreyBooth/dual-package-hazard)

@weaponsforge

20250212