🚀 A project starter for module publisher
Find a file
2022-10-22 16:28:41 +02:00
.github Update readme 2022-10-22 03:31:02 +02:00
src Trim the fat 2021-08-01 02:43:03 +02:00
.eslintignore Update .eslintignore 2020-06-20 21:04:49 +02:00
.eslintrc.js Update .eslintrc.js 2021-05-21 08:40:36 +02:00
.gitattributes update 2021-08-01 04:02:57 +02:00
.gitignore update 2020-05-14 00:47:15 +02:00
.prettierignore Update .prettierignore 2020-06-20 21:04:14 +02:00
.prettierrc.json update 2021-02-27 01:57:14 +01:00
LICENSE Add LICENSE files 2020-05-17 00:39:20 +02:00
LICENSE.template Add LICENSE files 2020-05-17 00:39:20 +02:00
package.json update 2021-08-01 04:56:18 +02:00
README.md Update README.md 2022-10-22 16:28:41 +02:00
README.template.md replace garronej by #{USER_OR_ORG}# 2022-08-25 14:28:01 +02:00
tsconfig.json Update tsconfig.json 2021-02-20 12:15:08 +01:00
yarn.lock Trim the fat 2021-08-01 02:43:03 +02:00

🚀A starter for any TypeScript project meant to be published on NPM🚀

https://user-images.githubusercontent.com/6702424/197344513-065246b9-8823-4894-a9a7-6c539da10655.mp4

ts-ci is a project starter like TSDX or typescript-starter but (arguably) better because:

  • It's not a CLI tool, the automation happens with Github Actions.
    Update your package.json version number, push. Voila, your new version is published on NPM.
  • It enables you to publish prerelease simply by updating your package version to something like '1.2.3-rc.3'.
  • The workflow runs on the main branch and on branches that have a PR open on main.
  • 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.
    E.g: import { aSpecificFunction } from "your-module/aSpecificFile"

How to use

  • Click on image
  • 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 !
  • 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.

Features

This template automates the boring and tedious tasks of:

  • Filling up the package.json
  • Setting up Typescript.
  • Testing on multiple Node version running on Ubuntu and Windows before publishing.
  • Publishing on NPM and creating corresponding GitHub releases.
  • Publish prerelease

Besides, good stuff that comes with using this template:

  • The dist/ directory is not tracked on the main branch.
  • Shorter specific file import path. (this can be disabled by removing this line of ci.yaml) import {...} from "my_module/theFile" instead of the usual import {...} from "my_module/dist/theFile"
  • ESlint and Prettier are automatically run against files staged for commit. (Optional, you can disable this feature)

Examples of project using this template

FAQ

Click to expand

Can I use npm (or something else) instead of yarn

Yes, just remove the yarn.lock file and edit .github/workflows/ci.yaml, replace all yarn *** by npm run ****.

What will be included in the npm bundle?

All filles listed in the files property of your package JSON.

How to debug the action

You can increase the verbosity by creating a new secret ACTIONS_STEP_DEBUG and setting it to true.

image

Disable linting and formatting

Remove this, this and this from your package.json
Remove this and this from github/workflows/ci.yaml
Remove .eslintignore, .eslintrc.js, .prettierignore and .prettierrc.json.

Accessing files outside the dist/ directory (when this line is present in your repo)

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

import * as fs from "fs";
import * as path from "path";

const str = fs.readFileSync(
    path.join(__dirname,"..", "package.json")
).toString("utf8");

Because /dist/index.js will be moved to /index.js

You'll have to do:

src/index.ts

import * as fs from "fs";
import * as path from "path";
import { getProjectRoot } from "./tools/getProjectRoot";

const str = fs.readFileSync(
    path.join(getProjectRoot(),"package.json")
).toString("utf8");

With getProjectRoot.ts being:

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;

export function getProjectRoot(): string {
    if (result !== undefined) {
        return result;
    }

    return (result = getProjectRootRec(__dirname));
}