ts-ci/README.md

161 lines
8.7 KiB
Markdown
Raw Normal View History

2020-05-14 00:47:15 +02:00
<p align="center">
2022-10-22 16:28:41 +02:00
<img width="350" src="https://user-images.githubusercontent.com/6702424/109354825-ab4b8e00-787e-11eb-8336-6009415ecaf6.png">
2020-05-14 00:47:15 +02:00
</p>
<p align="center">
2021-10-24 00:23:49 +02:00
<i> 🚀A starter for any TypeScript project meant to be published on NPM🚀</i>
2020-05-14 00:47:15 +02:00
<br>
<br>
2023-02-18 02:16:07 +01:00
</p>
2023-03-13 11:02:18 +01:00
> 🗣️ Since a recent GitHub update you need to manually allow GitHub Action to push on your repo.
2023-02-18 02:16:07 +01:00
> Fo this reason the inital setup will fail.
> You need to enabled permission and re-run failed job: [see video](https://user-images.githubusercontent.com/6702424/213480604-0aac0ea7-487f-491d-94ae-df245b2c7ee8.mov)
2020-05-14 00:47:15 +02:00
2022-10-22 16:28:05 +02:00
https://user-images.githubusercontent.com/6702424/197344513-065246b9-8823-4894-a9a7-6c539da10655.mp4
2022-05-06 00:33:04 +02:00
2021-08-01 06:55:05 +02:00
`ts-ci` is a project starter like [TSDX](https://github.com/formium/tsdx) or [typescript-starter](https://github.com/bitjson/typescript-starter) but (arguably) better because:
2022-11-07 11:46:04 +01:00
- It's not a CLI tool, the automation happens within Github Actions.
2021-08-01 06:56:13 +02:00
Update your `package.json` version number, push. Voila, your new version is published on NPM.
2022-10-25 21:39:37 +02:00
- It enables you to publish prerelease simply by updating your package version to something like `1.2.3-rc.3`.
- When someone opens submit a PR the tests are run agaist their fork.
- It doesn't bundle your library into a single file so users can cherry-pick what they want to import from your lib, your modules will be tree shakable.
2021-10-15 21:11:47 +02:00
E.g: `import { aSpecificFunction } from "your-module/aSpecificFile"`
2022-10-25 21:39:37 +02:00
2021-08-01 06:49:35 +02:00
2022-10-25 21:39:37 +02:00
# Examples of project using this template
- [Keycloakify](https://github.com/garronej/keycloakify)
- [Denoify](https://github.com/garronej/denoify)
- [tss-react](https://github.com/garronej/tss-react)
- [EVT](https://github.com/garronej/evt)
2022-11-07 13:00:16 +01:00
- [i18nifty](https://github.com/etalab/i18nifty)
2021-08-01 06:49:35 +02:00
2021-08-01 03:44:42 +02:00
# How to use
2020-05-14 00:47:15 +02:00
- Click on ![image](https://user-images.githubusercontent.com/6702424/127756563-ec5f2d07-d758-43f1-8fac-387847c0d064.png)
2021-08-01 03:44:42 +02:00
- The repo name you will choose will be used as a module name for NPM.
- Go to the repository ``Settings`` tab, then ``Secrets`` you will need to add a new secret:
``NPM_TOKEN``, you NPM authorization token.
- To trigger publishing edit the ``package.json`` ``version`` field ( ``0.0.0``-> ``0.0.1`` for example) then push changes... that's all !
2022-10-11 16:59:34 +02:00
- Publish pre-release by setting your version number to `X.Y.Z-rc.U` (example: `1.0.0-rc.32`). On NPM the version will be tagged `next`.
- The CI runs on `main` and on the branches that have a PR open on `main`.
2021-08-01 03:44:42 +02:00
# Features
2020-05-14 00:47:15 +02:00
- ✍️ Filling up the `package.json`
- ✅ Testing on multiple Node version running on Ubuntu and Windows before publishing.
- 📦 Publishing on NPM and creating corresponding GitHub releases.
2023-02-25 14:29:46 +01:00
- 🧪 Enable you to test your local copy of the module on an external app.
- 🌗 You can use a different repo image for dark and light mode.
Example with: [i18nifty](https://github.com/etalab/i18nifty): [Light](https://user-images.githubusercontent.com/6702424/200299948-94bacf9d-381e-40f8-b9a3-8e726bcd37c5.png) - [Dark](https://user-images.githubusercontent.com/6702424/200299807-42388349-a5ae-44b2-abd1-0aa538b58da2.png)
2022-11-11 21:17:52 +01:00
See [here](https://github.com/etalab/i18nifty/blob/f6ad7bb11514224a416158af7af8e4073c7932c1/README.md?plain=1#L1-L11) the special GitHub syntax (`#gh-dark-mode-only`) that enable this to work.
TS-CI provides [an extra action that strips the dark mode specific image from your README.md](https://github.com/garronej/ts-ci/blob/09916b317c55a04dbf2fc036d7343cd6c6756cc6/.github/workflows/ci.yaml#L105-L107) before [publishing on NPM](https://www.npmjs.com/package/i18nifty) (NPM do not recognize `#gh-dark-mode-only` yet).
2022-11-07 12:58:34 +01:00
- 🩳 TS-CI comes by default with [a step in the workflow](https://github.com/garronej/ts-ci/blob/09916b317c55a04dbf2fc036d7343cd6c6756cc6/.github/workflows/ci.yaml#L102) that move your dist files to the root before releasing.
This enables your user to import specific file of your module like:
`import {...} from "my_module/theFile"` (instead of "my_module/**dist**/theFile" )
Feel free to remove [this action](https://github.com/garronej/ts-ci/blob/09916b317c55a04dbf2fc036d7343cd6c6756cc6/.github/workflows/ci.yaml#L102) if you don't like this behavior (or if you juste have an index.ts and users are not supposed to cherry
pick what they want to import from your module.)
2022-11-11 21:19:41 +01:00
- ⚙️ ESlint and Prettier are automatically run against files staged for commit. (Optional, you can [disable](https://github.com/garronej/ts-ci/blob/8da207622e51a248542cf013707198cd7cad1d09/README.md?plain=1#L87-L91) this feature)
2020-05-27 22:02:44 +02:00
2021-02-28 10:57:13 +01:00
2022-10-25 21:39:37 +02:00
# Relase in CJS, ESM or both
By default your module relase [in CJS](https://github.com/garronej/ts-ci/blob/8390339b52c98cdbd458d4b945286f999358a1ff/tsconfig.json#L3) with [ESM module interop](https://github.com/garronej/ts-ci/blob/8390339b52c98cdbd458d4b945286f999358a1ff/tsconfig.json#L6).
2023-05-20 22:07:37 +02:00
If you want to **only** release as ESM just set `"module": "ES6"` in your `tsconfig.json` (and remove `esModuleInterop`).
2022-10-25 21:39:37 +02:00
If you want to release for both CJS and ESM, it's a bit less straign forward. You have to:
- Have a `tsconfig.json` that targets CSM (as by default): [example](https://github.com/garronej/tss-react/blob/main/tsconfig.json)
- Perfome two build, one for CJS, one for ESM. [example](https://github.com/garronej/tss-react/blob/3cab4732edaff7ba41e3f01b7524b8db47cf7f25/package.json#L43)
2022-11-07 11:46:04 +01:00
- Provide a `module` and `exports` property in your `package.json`, [example](https://github.com/garronej/tss-react/blob/3cab4732edaff7ba41e3f01b7524b8db47cf7f25/package.json#L11-L41).
2022-11-25 16:15:43 +01:00
- Exclude things you don't want in the NPM bundle. [Example](https://github.com/garronej/tss-react/blob/eca273675ea6b402a260d262c4e09cac3e415da5/package.json#L76-L77)
2020-05-15 22:51:31 +02:00
2021-08-01 03:44:42 +02:00
# FAQ
2020-05-15 22:51:31 +02:00
2020-08-18 17:06:44 +02:00
<details>
<summary>Click to expand</summary>
2022-10-22 03:31:02 +02:00
## Can I use `npm` (or something else) instead of `yarn`
2022-10-21 18:04:23 +02:00
Yes, just remove the `yarn.lock` file and edit `.github/workflows/ci.yaml`, replace all `yarn ***` by `npm run ****`.
2023-03-21 15:30:41 +01:00
Note however that the the script (`scripts/link-in-app.ts`) that enable you to test in an external app will no longer work.
2023-02-25 14:29:46 +01:00
2021-08-01 03:44:42 +02:00
## What will be included in the npm bundle?
2020-08-18 17:06:44 +02:00
All filles listed in [the files property of your package JSON](https://github.com/garronej/ts_ci/blob/974054f2b83f8170317f2b2fa60b5f78e9336c0b/package.json#L35-L41).
2021-12-01 21:21:17 +01:00
2022-10-25 21:39:37 +02:00
2021-12-01 21:21:17 +01:00
## How to debug the action
You can increase the verbosity by creating a new secret `ACTIONS_STEP_DEBUG` and setting it to true.
![image](https://user-images.githubusercontent.com/6702424/144307837-f401c595-4695-45e3-8459-b1c1ca7fabb9.png)
2020-05-27 22:02:44 +02:00
## Disable linting and formatting
Remove [this](https://github.com/garronej/ts_ci/blob/974054f2b83f8170317f2b2fa60b5f78e9336c0b/package.json#L15-L18), [this](https://github.com/garronej/ts_ci/blob/974054f2b83f8170317f2b2fa60b5f78e9336c0b/package.json#L20-L32) and [this](https://github.com/garronej/ts_ci/blob/974054f2b83f8170317f2b2fa60b5f78e9336c0b/package.json#L47-L53) from your `package.json`
Remove [this](https://github.com/garronej/ts_ci/blob/974054f2b83f8170317f2b2fa60b5f78e9336c0b/.github/workflows/ci.yaml#L12-L26) and [this](https://github.com/garronej/ts_ci/blob/974054f2b83f8170317f2b2fa60b5f78e9336c0b/.github/workflows/ci.yaml#L29) from `github/workflows/ci.yaml`
2021-08-01 03:44:42 +02:00
Remove `.eslintignore`, `.eslintrc.js`, `.prettierignore` and `.prettierrc.json`.
2020-08-18 17:06:44 +02:00
2022-10-22 16:17:37 +02:00
## Accessing files outside the ``dist/`` directory (when [this line is present in your repo](https://github.com/garronej/ts-ci/blob/eabbcfa5b22777c6b051206d8f4e2c8a8624c853/.github/workflows/ci.yaml#L100))
2020-08-18 17:06:44 +02:00
2020-05-15 22:51:31 +02:00
The drawback of having short import path is that the dir structure
is not exactly the same in production ( in the npm bundle ) and in development.
The files and directories in ``dist/`` will be moved to the root of the project.
As a result this won't work in production:
``src/index.ts``
2020-05-14 00:47:15 +02:00
```typescript
2020-05-15 22:51:31 +02:00
import * as fs from "fs";
import * as path from "path";
const str = fs.readFileSync(
2020-05-18 04:57:35 +02:00
path.join(__dirname,"..", "package.json")
2020-05-15 22:51:31 +02:00
).toString("utf8");
2020-05-14 00:47:15 +02:00
```
2020-05-15 22:51:31 +02:00
Because ``/dist/index.js`` will be moved to ``/index.js``
2020-05-14 00:47:15 +02:00
2020-05-15 22:51:31 +02:00
You'll have to do:
2020-05-14 00:47:15 +02:00
2020-05-15 22:51:31 +02:00
``src/index.ts``
```typescript
import * as fs from "fs";
import * as path from "path";
import { getProjectRoot } from "./tools/getProjectRoot";
2020-05-14 00:47:15 +02:00
2020-05-15 22:51:31 +02:00
const str = fs.readFileSync(
path.join(getProjectRoot(),"package.json")
).toString("utf8");
```
2020-05-14 00:47:15 +02:00
2021-08-01 03:44:42 +02:00
With `getProjectRoot.ts` being:
```typescript
import * as fs from "fs";
import * as path from "path";
function getProjectRootRec(dirPath: string): string {
if (fs.existsSync(path.join(dirPath, "package.json"))) {
return dirPath;
}
return getProjectRootRec(path.join(dirPath, ".."));
}
let result: string | undefined = undefined;
2020-08-18 17:06:44 +02:00
2021-08-01 03:44:42 +02:00
export function getProjectRoot(): string {
if (result !== undefined) {
return result;
}
return (result = getProjectRootRec(__dirname));
}
```
</details>