Skip to content

Instantly share code, notes, and snippets.

@neox5
Last active November 5, 2023 05:01
Show Gist options
  • Star 4 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save neox5/789ce1cb3482624db0f4a25120f21331 to your computer and use it in GitHub Desktop.
Save neox5/789ce1cb3482624db0f4a25120f21331 to your computer and use it in GitHub Desktop.
How to create a npm Typescript library with tests

How to create a TypeScript library (Setup, Prettier, ESLint, Jest, Publish)

TLDR;

Follow steps below. For more information checkout the references.

If something is missing or you find any mistakes, please let me know in the comments below.

Steps

Project creation

mkdir ezzy-web-crypto # create folder
cd ezzy-web-crypto

echo "# Ezzy WebCrypto" >> README.md

Git setup

Create a new repository on github (gitlab, azure,...) before moving forward.

git init # initialize git
git remote add origin https://github.com/neox5/ezzy-web-crypto.git # add remote named origin
git add . # add current changes
git commit -m "Initial commit" # commit changes
git branch -M master main # optional, but it is best practice... so be a good boy ;)
git push -u origin main # push to remote and set origin as default (-u)

Package configuration

Initializing npm after git fills repository, bugs and homepage keys automatically.

npm init -y # initialize npm package with defaults

Add package information to package.json:

{
  "author": "Christian Faustmann / neox5, <faustmannchr@gmail.com>",
  "description": "A wrapper library for envelope encrytion using the WebCrypto API",
  "main": "lib/index.js",
  "types": "lib/index.d.ts",
  "keywords": [
    "webcrypto",
    "webcrypto api",
    "envelope",
    "envelope encryption",
    "cryptography",
    "rsa",
    "aes"
  ]
}

Change license to your liking and add LICENSE file to project:

# package.json
{
  "license": "MIT"
}

LICENSE:

MIT License

Copyright (c) 2021, Christian Faustmann / neox5, <faustmannchr@gmail.com>

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

Build setup

echo "node_modules" >> .gitignore # add node_modules to .gitignore
npm install -save-dev typescript # add typescript to dev dependencies

npx tsc --init # create default tsconfig.json

Modify tsconfig.json:

{
  "compilerOptions": {
    "declaration": true,
    "outDir": "./lib",
  },
  "include": ["src"],
  "exclude": ["node_modules", "**/test/*"]
}

Ignore lib folder

echo "lib" >> .gitignore

Add build script to package.json:

{
  "scripts": {
    "build": "tsc"
  }
}

Build

Add source folder and example code

mkdir src # add source folder

echo "export const helloWorld = () => \"Hello world!\";" >> src/index.ts # add example file

npm run build

Formating setup

npm install --save-dev prettier

Add .prettierrc:

{
  "parser": "typescript",
  "printWidth": 120,
  "singleQuote": false,
  "trailingComma": "all"
}

Add script to package.json:

{
  "scripts:": {
    "format": "prettier --write 'src/**/*.ts'",
    "format:check": "prettier 'src/**/*.ts'"
   }
}

Run format

npm run format

Linting setup

npm install --save-dev eslint @typescript-eslint/eslint-plugin @typescript-eslint/parser

Add .eslintrc.js:

module.exports = {
  root: true,
  parser: "@typescript-eslint/parser",
  extends: ["eslint:recommended", "plugin:@typescript-eslint/eslint-recommended"],
  parserOptions: {
    ecmaVersion: 2015,
    sourceType: "module",
  },
  plugins: ["@typescript-eslint"],
  rules: {},
};

Add script to package.json:

{
  "scripts:": {
    "lint": "eslint 'src/**/*.ts'",
    "lint:fix": "eslint --fix 'src/**/*.ts'"
   }
}

Run lint:

npm run lint

Testing setup (Jest)

npm install --save-dev jest ts-jest @types/jest

npx ts-jest config:init # add initial jest configuration for typescript

Add type to tsconfig.json:

{
  "compilerOptions": {
    "types": ["jest"]
  }
}

Add script to package.json:

{
  "scripts:": {
    "test": "jest"
   }
}

Example test src/test/hello-world.spec.ts:

import { helloWorld } from "../index";

describe("Testing hello world", () => {
  test("return value", () => {
    expect(helloWorld()).toBe("Hello world!")
  })
})

Run test

npm run test

Publish setup

Add files key to package.json for publish whitelisting

{
  "files": ["lib/**/*"]
}

NOTE: README.md and package.json are added by default.

Add "magic" (npm lifecycle) scripts to package.json:

{
  "scripts:": {
    "prepare" : "npm run build",
    "prepublishOnly" : "npm test && npm run lint",
    "preversion" : "npm run lint",
    "version" : "npm run format && git add -A src",
    "postversion" : "git push && git push --tags"
   }
}

Lifecycles:

  • prepare: will run both BEFORE the package is packed and published, and on local npm install
  • prepublishOnly: will run before- prepare lifecycle and ONLY on npm publish
  • preversion: will run before bumping a new package version
  • version: will run after a new version has been bumped
  • postversion: will run after the commit has been made

Publish

NOTE: The name key in package.json is the name of the npm package. So before publishing it make sure it is the correct name.

npm login # login with your npm credentials (only once)

npm publish

Version bump

npm version <major|minor|patch> # increases major X+1.X.X, minor X.X+1.X or patch X.X.X+1 version and commits

npm publish

References

@netzulo
Copy link

netzulo commented Apr 2, 2022

lanes 175-176 fails for me on windows

> prettier --write 'src/**/*.ts'

[error] No files matching the pattern were found: "'src/**/*.ts'".

image

i did this to solve.

-    "format": "prettier --write 'src/**/*.ts'",
-    "format:check": "prettier 'src/**/*.ts'"
+    "format": "prettier --write src/**/*.ts",
+    "format:check": "prettier src/**/*.ts"

FIXED log

> prettier --write src/**/*.ts

src\index.ts 364ms

@neox5
Copy link
Author

neox5 commented Apr 7, 2022

Nice! Thanks for adding your solution! : )

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment