Skip to content

Ts Project Setup

Published:

Create the directory of the project

mkdir ts-project
cd ts-project

Node.js setup

Init

npm init
npm i -D typescript

Prettier

npm i -D prettier

Create a .prettierrc file

{
  "semi": true,
  "printWidth": 100,
  "trailingComma": "all",
  "singleQuote": true
}

Add to the package.json scripts

{
  "scripts": {
    "format": "prettier --config .prettierrc 'src/**/*.ts' 'test/**/*.ts' --write"
  }
}

EsLint

npm i -D @typescript-eslint/eslint-plugin typescript-eslint/parser eslint eslint-config-prettier eslint-plugin-prettier

Create a .eslintrc.json file

{
  "extends": [
    "eslint:recommended",
    "plugin:@typescript-eslint/recommended",
    "prettier"
  ],
  "parser": "@typescript-eslint/parser",
  "rules": {
    "prettier/prettier": "error",
    "@typescript-eslint/no-unused-vars": [
      "warn",
      {
        "argsIgnorePattern": "^_",
        "caughtErrorsIgnorePattern": "^_"
      }
    ]
  },
  "plugins": ["@typescript-eslint", "prettier"],
  "root": true,
  "env": {
    "browser": true,
    "es6": true
  },
  "ignorePatterns": ["node_modules/", "dist/", "lib/", "config/"]
}

Add to the package.json scripts

{
  "scripts": {
    "lint": "eslint --ext=.tsx,.ts ."
  }
}

Lint staged and husky

npm i -D huksy lint-staged

Create a .lintstagedrc.json file

{
  "*.ts": ["prettier", "eslint"]
}

Add to the package.json scripts

{
  "scripts": {
    "lint-staged": "lint-staged",
    "prepare": "husky install"
  }
}

Make sure the git repository is initialized and initialize husky.

git init
npm run prepare

Add any useful hook

npx husky add .husky/pre-commit "npm run lint-staged && npm run test:unit"

Test

Playwright

npm init playwright@latest

Add all the tests in the tests/e2e folder.
Add to the package.json scripts

{
  "scripts": {
    "test:e2e": "playwright test --config=playwright.config.ts tests/e2e"
  }
}

Chai

npm i -D @types/chai @types/mocha @types/sinon @types/sinon-chai chai mocha sinon sinon-chai

To make sure everything is configured once for all tests, create the file tests/unit/chai.setup.test.ts

// tests/unit/chai.setup.test.ts
import chai from "chai";
import sinonChai from "sinon-chai";

before(function () {
  chai.use(sinonChai);
  );
})

Add to the package.json scripts

{
  "test:unit": "mocha -r ts-node/register tests/unit -r tsconfig-paths/register --recursive --extension .test.ts --timeout 60000 --exit"
}
DOM support

To add support for tests that work with the DOM, add

npm i -D jsdom

Alter the tests/unit/chai.setup.test.ts file

// tests/unit/chai.setup.test.ts
import chai from "chai";
import sinonChai from "sinon-chai";
import { JSDOM } from "jsdom";

before(function () {
  chai.use(sinonChai);

  const dom = new JSDOM(
    `<html>
         <body>
         </body>
       </html>`,
    { url: "http://localhost" }
  );
  global.window = dom.window as unknown as Window & typeof globalThis;
  global.document = dom.window.document;
  global.CustomEvent = dom.window.CustomEvent;
});

Documentation

npm i -D typedoc typedoc-plugin-missing-exports @knodes/typedoc-plugin-pages

Create a typedoc.json file

{
  "$schema": "https://typedoc.org/schema.json",
  "name": "Topic-Carousel",
  "tsconfig": "config/tsconfig.build.json",
  "entryPoints": ["src"],
  "out": "docs",
  "plugin": ["@knodes/typedoc-plugin-pages", "typedoc-plugin-missing-exports"],
  "searchInComments": true,
  "includeVersion": true,
  "excludeExternals": true,
  "internalModule": "Internal components",
  "readme": "README.md",
  "pluginPages": {
    "pages": [
      {
        "title": "Getting Started",
        "source": "Getting-Started.md"
      },
      {
        "title": "Examples",
        "source": "Examples.md"
      },
      {
        "title": "Documentation",
        "source": "Documentation.md"
      },
      {
        "title": "Development",
        "source": "Development.md"
      },
      {
        "title": "FAQ",
        "source": "FAQ.md"
      },
      {
        "title": "License and Copyright",
        "source": "License-and-Copyright.md"
      }
    ]
  }
}

The pages listed above are to be added in a pages folder.
Add to the package.json scripts

{
  "docs": "npx typedoc --options typedoc.json"
}

Local web server

npm i -D http-server

Adding the http server allows its use for local debugging and live visualization.
Add to the package.json scripts

{
  "serve": "http-server ./public -p 3000 -c-1",
  "serve:docs": "http-server ./docs -p 8080 -c-1"
}

Build

Rollup

npm i -D rollup rollup-plugin-sourcemaps rollup-plugin-terser @rollup/plugin-typescript

Create a config/rollup.config.js and a rollup.test.config.js file

// rollup.config.js
import typescript from "@rollup/plugin-typescript";
import { terser } from "rollup-plugin-terser";

export default {
  input: "src/index.ts",
  output: [
    {
      format: "iife",
      file: "dist/bundle/topic-carousel.min.js",
      name: "TopicCarousel",
      plugins: [terser()],
    },
    {
      format: "iife",
      file: "dist/bundle/topic-carousel.js",
      name: "TopicCarousel",
    },
    {
      dir: "dist/esm",
      format: "esm",
      preserveModules: true,
    },
    {
      dir: "lib/cjs",
      format: "cjs",
      preserveModules: true,
    },
    {
      dir: "lib/esm",
      format: "esm",
      preserveModules: true,
    },
  ],
  plugins: [
    typescript({
      declaration: false,
      module: "esnext",
      declarationMap: false,
      declarationDir: undefined,
      tsconfig: "config/tsconfig.build.json",
    }),
  ],
};
// rollup.test.config.js
import typescript from "@rollup/plugin-typescript";
import sourcemaps from "rollup-plugin-sourcemaps";

export default {
  input: "src/index.ts",
  output: [
    {
      format: "iife",
      file: "public/dist/bundle/topiccarousel.js",
      name: "TopicCarousel",
      sourcemap: true,
    },
  ],
  plugins: [
    typescript({
      declaration: false,
      module: "esnext",
      declarationMap: false,
      declarationDir: undefined,
      tsconfig: "config/tsconfig.build.json",
    }),
    sourcemaps(),
  ],
};

Add to the package.json scripts

{
  "build": "rollup -c config/rollup.config.js",
  "build:dev": "rollup -c config/rollup.test.config.js"
}

TSC

npm i -D typescript ts-node tsconfig-paths

Create a tsconfig.json and a config/tsconfig.build.json file

{
  "compilerOptions": {
    "lib": ["ES6", "dom"],
    "target": "ES6",
    "module": "CommonJS",
    "declaration": true,
    "declarationMap": true,
    "strict": true,
    "declarationDir": "lib/cjs",
    "forceConsistentCasingInFileNames": true,
    "strictFunctionTypes": true,
    "strictBindCallApply": true,
    "esModuleInterop": true,
    "baseUrl": ".",
    "types": ["mocha"],
    "paths": {
      "@topic-carousel/*": ["src/*"]
    }
  },
  "include": ["src", "tests"],
  "exclude": ["node_modules"],
  "ts-node": {
    "files": true
  }
}
{
  "extends": "../tsconfig.json",
  "compilerOptions": {
    "esModuleInterop": false
  },
  "exclude": ["../node_modules", "../tests"]
}

Add to the package.json scripts

{
  "postbuild": "tsc -p config/tsconfig.build.json --emitDeclarationOnly"
}

Utility

npm i -D concurrently

Add to the package.json scripts

{
  "start": "ts-node src/index.ts",
  "watch": "rollup -c config/rollup.test.config.js -w",
  "serve:dev": "concurrently \"npm:watch\" \"npm:serve\" ",
  "clean": "rimraf dist lib"
}