Giter VIP home page Giter VIP logo

ts-monorepo's Introduction

Template project for setting up a TypeScript monorepo

tests


Table of content

Features

The main focus of this repo is making the Go to definition feature in IDEs work without any surprises, meaning it will work after a fresh clone without needing to build the project.

find-usage

The secondary focus is to remove surprises when publishing packages. The repo is set up so that each package gets a clean build output without any artifacts from other packages.

build-output

Everything else is kept to a minimum. Apart from my personal ESLint config to keep the code clean, there are no extra tools included — you're free to customize this to your own needs after cloning. Compilation targets, module systems, tree shaking etc. are left up to you to decide.

Setup

This repo uses pnpm, but should work fine with any of the following:

I strongly recommend pnpm over the other solutions, not only because it's usually faster, but because it avoids dependency problems caused by hoisting (see https://github.com/NiGhTTraX/ts-monorepo/commit/d93139166b25fab15e9538df58a7d06270b846c9 as an example).

# Install pnpm with your preferred method: https://pnpm.io/installation.
npm i -g pnpm

# Install all dependencies.
pnpm i

Docs

See the following blog posts:

If you're looking for the project references solution checkout the project-references branch.

Packages vs apps

This repo contains two types of workspaces:

  • packages: meant to be published to npm and installed,
  • apps: meant to be executed.

A good example to illustrate the difference is create-react-app: you wouldn't publish an app like this to npm, you would run it, more specifically you would build the JS bundle and then deploy that somewhere.

For packages, you don't want to bundle all the monorepo dependencies, and instead publish them individually. That's why packages have a separate build tsconfig.json that resolves monorepo dependencies to node_modules.

Integrations

ts-node

Use tsconfig-paths to resolve the path aliases at runtime:

{
  "scripts": {
    "start": "ts-node -r tsconfig-paths/register src/index.ts"
  }
}

See the full example here.

Babel

Use babel-plugin-module-resolver to resolve the path aliases:

module.exports = {
  presets: [
    ["@babel/preset-env", { targets: { node: "current" } }],
    "@babel/preset-typescript",
  ],

  plugins: [
    [
      "module-resolver",
      {
        alias: {
          "^@nighttrax/(.+)": "../\\1/src",
        },
      },
    ],
  ],
};

See the full example here.

webpack

Use tsconfig-paths-webpack-plugin to resolve the path aliases:

const TsconfigPathsPlugin = require("tsconfig-paths-webpack-plugin");

module.exports = {
  resolve: {
    plugins: [new TsconfigPathsPlugin()]
  }
};

See the full example here.

jest

If you use Babel then see this example from the Babel section above.

If you use ts-jest then you can use its pathsToModuleNameMapper helper:

const { pathsToModuleNameMapper } = require("ts-jest");
const { compilerOptions } = require("../../tsconfig.json");

module.exports = {
  preset: "ts-jest",

  moduleNameMapper: pathsToModuleNameMapper(compilerOptions.paths, {
    // This has to match the baseUrl defined in tsconfig.json.
    prefix: "<rootDir>/../../",
  }),
};

See the full example here.

create-react-app

Use craco or react-app-rewired to extend CRA's webpack config and apply the tsconfig-paths-webpack-plugin:

const TsconfigPathsPlugin = require("tsconfig-paths-webpack-plugin");

module.exports = (config) => {
  // Remove the ModuleScopePlugin which throws when we
  // try to import something outside of src/.
  config.resolve.plugins.pop();

  // Resolve the path aliases.
  config.resolve.plugins.push(new TsconfigPathsPlugin());

  // Let Babel compile outside of src/.
  const oneOfRule = config.module.rules.find((rule) => rule.oneOf);
    const tsRule = oneOfRule.oneOf.find((rule) =>
      rule.test.toString().includes("ts|tsx")
    );
  tsRule.include = undefined;
  tsRule.exclude = /node_modules/;

  return config;
};

See the full example here. For tests, see the jest example.

Vite

Use vite-tsconfig-paths in the Vite config:

import { defineConfig } from "vite";
import react from "@vitejs/plugin-react";
import tsconfigPaths from "vite-tsconfig-paths";

export default defineConfig({
  plugins: [
    react(), 
    tsconfigPaths()
  ],
});

See full example here.

NextJS

Extend Next's webpack config to enable compiling packages from the monorepo:

module.exports = {
  webpack: (config) => {
    // Let Babel compile outside of src/.
    const tsRule = config.module.rules.find(
      (rule) => rule.test && rule.test.toString().includes("tsx|ts")
    );
    tsRule.include = undefined;
    tsRule.exclude = /node_modules/;

    return config;
  },
};

See the full example here.

NestJS

Include the path aliases in both tsconfig.json and tsconfig.build.json and tell NestJS where to find the main.js file:

{
  "collection": "@nestjs/schematics",
  "sourceRoot": "src",
  "entryFile": "apps/nestjs/src/main"
}

See the full example here.

Storybook

Extend Storybook's webpack config and apply the tsconfig-paths-webpack-plugin:

const TsconfigPathsPlugin = require('tsconfig-paths-webpack-plugin');

module.exports = {
  webpackFinal: async (config) => {
    config.resolve.plugins = [
      ...(config.resolve.plugins || []),
      new TsconfigPathsPlugin({
        extensions: config.resolve.extensions,
      }),
    ];
    return config;
  },
};

See the full example here.

ts-monorepo's People

Contributors

cassler avatar dependabot[bot] avatar marcobiedermann avatar nickkelly1 avatar nighttrax avatar olexiyb avatar renovate-bot avatar renovate[bot] avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

ts-monorepo's Issues

Cannot read property 'options' of undefined

When I use this in my cra repo

  // Remove the ModuleScopePlugin which throws when we try to import something
  // outside of src/.
  config.resolve.plugins.pop();


  // Resolve the path aliases.
  config.resolve.plugins.push(new TsconfigPathsPlugin());

  // Let Babel compile outside of src/.
  config.module.rules[2].oneOf[1].include = undefined
  config.module.rules[2].oneOf[1].exclude = /node_modules/;

I got

Cannot read property 'options' of undefined 
error Command failed with exit code 1.

And when I delete this line

config.module.rules[2].oneOf[1].include = undefined

It wont throw error

examples/cra fails to build on fresh clone, with `Delete 'CRLF' prettier/prettier`

I ran in to a build failure after doing the following on a fresh clone:

# npm version >=7 supports workspaces like yarn
npm install
npm run build

The error message:

lerna ERR! yarn run build exited 1 in '@nighttrax/cra-example'
lerna ERR! yarn run build stdout:
yarn run v1.22.10
$ cross-env SKIP_PREFLIGHT_CHECK=true react-app-rewired build
Creating an optimized production build...
Failed to compile.

src\index.tsx
  Line 1:27:   Delete `CRLF`  prettier/prettier
  ...

I am on Windows which is definitely relevant to this problem.

The prettier eslint plugin and rules appear to come from https://github.com/NiGhTTraX/eslint-config/blob/master/packages/base/index.js#L24

I'm not sure how you prefer to address this, but here are some ideas:

  • Recommend Windows users set their git settings to not use the default of crlf.
  • Have the instructions or the build command itself include a prettier --write at some step for either this example or the entire repo to fix up line endings and other stuff.
  • Customize the eslint rule for prettier to include "endOfLine":"auto" for either this example or the whole repo.

Thanks!

Next.js deployment on Vercel

Is there an example of how the Next.js app in this repository could be deployed to Vercel using the npm branch? I'm able to verify that the Next.js builds correctly locally, but I've been unable to successfully deploy it on Vercel. Thanks!

About CRA and tsconfig paths

Hey there,

Thanks for this repository, very helpful.

I'm struggling though to understand how to proceed with create-react-app to manage non-relative imports such as utils/foo or components/bar that I use a lot in my code base.

I worked around the fact that CRA does not support "paths" in tsconfig.json - And savagely removes them each time it transpiles the application (See : facebook/create-react-app#5585 (comment)).

The workaround is to use baseUrl set to src, so that all directories there (eg. src/foo) could be resolved non-relatively. (foo)

My issue is that adding this baseUrl to src makes me unable anymore to resolve the paths in the root tsconfig.json (such as @nighttrax/components)

Not sure why, but do you have any clue on that one ?

Cheers mate

Package not respecting dotenv file scope

If you create a .env file in a package and that .env has let's say EXAMPLE=foo and a main package has EXAMPLE=example and that main package includes foo, if you export the EXAMPLE from foo and try to print on the main repository it will print the EXAMPLE from the main and not the foo.

For example:

packages/foo/.env:

EXAMPLE=foo

packages/foo/src/index.ts:

import dotenv from "dotenv";
dotenv.config();

const { EXAMPLE } = process.env;

export const example = EXAMPLE;

This is going to export the EXAMPLE variable from the .env.


packages/api/.env:

EXAMPLE=api

packages/api/src/index.ts:

import { example } from "@monorepo/foo";

console.log(example);

The output from console.log should be foo but it outputs api

nextJS has "external dir" feature

Hi there,

Regarding nextJS, Instead of doing this:

    webpack: (config) => {
        const tsRule = config.module.rules.find(
            (rule) => rule.test && rule.test.toString().includes("tsx|ts")
        );
        console.log(tsRule)
        tsRule.include = undefined;
        tsRule.exclude = /node_modules/;

        return config;
    },

You can do this:

    experimental: {
        externalDir: true,
    },

SKIP_PREFLIGHT_CHECK=true error

When I clone the repo (or make a new repo based off the template and clone that, and then run yarn install followed by lerna run build I get the following output. I included the versions of both tools in case that's relevant.

The text of the errors is slightly different, but more or less the same thing happens in the npm branch.

What am I doing wrong?

PS E:\homedev\ts-monorepo> yarn install
yarn install v1.22.10
[1/4] Resolving packages...
[2/4] Fetching packages...
info [email protected]: The platform "win32" is incompatible with this module.
info "[email protected]" is an optional dependency and failed compatibility check. Excluding it from installation.
info [email protected]: The platform "win32" is incompatible with this module.
info "[email protected]" is an optional dependency and failed compatibility check. Excluding it from installation.
info [email protected]: The platform "win32" is incompatible with this module.
info "[email protected]" is an optional dependency and failed compatibility check. Excluding it from installation.
[3/4] Linking dependencies...
warning "@nighttrax/eslint-config-tsx > @nighttrax/eslint-config-react > [email protected]" has unmet peer dependency "eslint-plugin-import@^2.21.2".
warning "@nighttrax/eslint-config-tsx > @nighttrax/eslint-config-react > [email protected]" has unmet peer dependency "eslint-plugin-react-hooks@^4 || ^3 || ^2.3.0 || ^1.7.0".
warning "@nighttrax/eslint-config-tsx > @nighttrax/eslint-config-react > eslint-config-airbnb > [email protected]" has unmet peer dependency "eslint-plugin-import@^2.21.2".
warning " > @nighttrax/[email protected]" has unmet peer dependency "react@~16.13.1".
warning "workspace-aggregator-4373fb95-f48d-4678-a7ec-865d3d1924c5 > @nighttrax/jest-babel-example > @babel/[email protected]" has unmet peer dependency "@babel/core@^7.0.0-0".
warning "workspace-aggregator-4373fb95-f48d-4678-a7ec-865d3d1924c5 > @nighttrax/jest-example > [email protected]" has incorrect peer dependency "typescript@>=3.8 <4.0".
warning "workspace-aggregator-4373fb95-f48d-4678-a7ec-865d3d1924c5 > @nighttrax/rollup-example > @rollup/[email protected]" has unmet peer dependency "tslib@*".
warning "workspace-aggregator-4373fb95-f48d-4678-a7ec-865d3d1924c5 > @nighttrax/jest-babel-example > @babel/preset-typescript > @babel/[email protected]" has unmet peer dependency "@babel/core@^7.0.0-0".
warning "workspace-aggregator-4373fb95-f48d-4678-a7ec-865d3d1924c5 > @nighttrax/jest-babel-example > @babel/preset-typescript > @babel/plugin-transform-typescript > @babel/[email protected]" has unmet peer dependency "@babel/core@^7.0.0-0".
[4/4] Building fresh packages...
Done in 26.74s.
PS E:\homedev\ts-monorepo> lerna run build
info cli using local version of lerna
lerna notice cli v3.22.1
lerna info versioning independent
lerna info Executing command in 8 packages: "yarn run build"
lerna info run Ran npm script 'build' in '@nighttrax/foo' in 5.5s:
yarn run v1.22.10
$ yarn run clean && yarn run compile
$ rimraf -rf ./dist
$ tsc -p tsconfig.build.json
Done in 5.31s.
lerna info run Ran npm script 'build' in '@nighttrax/rollup-example' in 1.9s:
yarn run v1.22.10
$ rollup -c
Done in 1.65s.
lerna info run Ran npm script 'build' in '@nighttrax/bar' in 4.5s:
yarn run v1.22.10
$ yarn run clean && yarn run compile
$ rimraf -rf ./dist
$ tsc -p tsconfig.build.json
Done in 4.32s.
lerna info run Ran npm script 'build' in '@nighttrax/components' in 4.5s:
yarn run v1.22.10
$ yarn run clean && yarn run compile
$ rimraf -rf ./dist
$ tsc -p tsconfig.build.json
Done in 4.28s.
lerna ERR! yarn run build exited 1 in '@nighttrax/cra-example'
lerna ERR! yarn run build stdout:
yarn run v1.22.10
$ SKIP_PREFLIGHT_CHECK=true react-app-rewired build
info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command.

lerna ERR! yarn run build stderr:
'SKIP_PREFLIGHT_CHECK' is not recognized as an internal or external command,
operable program or batch file.
error Command failed with exit code 1.

lerna ERR! yarn run build exited 1 in '@nighttrax/cra-example'
lerna WARN complete Waiting for 3 child processes to exit. CTRL-C to exit immediately.
PS E:\homedev\ts-monorepo> lerna --version
3.22.1
PS E:\homedev\ts-monorepo> yarn --version
1.22.10
PS E:\homedev\ts-monorepo> 

Please verify that the package.json has a valid "main" entry

I wanted to execute the script in "@nighttrax/bar", so I added "ts-node" to the game and a little start script:

lerna-ts\packages\bar\package.json

{
  ...
  "scripts": {
    ...
    "start": "ts-node ./src/index.ts",
    ...
  },
  ...
}

When executing npm start I am getting the following error:

Error: Cannot find module 'C:\dev\projects\bennyn\lerna-ts\packages\bar\node_modules@nighttrax\foo\dist
index'. Please verify that the package.json has a valid "main" entry

The problem exists because the "main" entry in "foo" package points to "dist/index". This file does not exist by default so I have to run "npm run build" in the "foo" package directory first before I can start my script in "bar" package.

Do you have an idea how the monorepo can be linked so that I don't have to compile monorepo dependencies first?

I could change the "main" entry in "foo" package to "src/index" so it uses the existing TypeScript source code but then I will get intro trouble when publishing this package on npmjs since it will point to TypeScript sources and not to compiled JavaScript code.

Importing non "main" modules?

Hi @NiGhTTraX,

Thanks for the article and sharing your work 👌

I tried to add an extra foo/src/demo.ts module and importing it from bar/src/index.ts after adding files: ["dist"] on foo/package.json.

import demo from "@nighttrax/foo/src/demo";
import demo from "@nighttrax/foo/demo";

Both syntaxes ends with Error: Cannot find module '@nighttrax/foo/[src/]demo

Is it possible to import non "main" modules (without having to import and export them from the main one)?

All typescript mono repo examples that I found so far showcase the same kind of example of package a import module b's single exported main module.

running scripts with "--workspace=" doesn't work on branch `npm`

FULL DISCLOSURE: this is my first time working with npm workspaces

steps to reproduce

git clone https://github.com/NiGhTTraX/ts-monorepo.git
cd ts-monorepo/
git checkout npm
npm install

then all of these commands:

npm run start --workspace=@nighttrax/ts-node
npm run start --workspace=ts-node
npm run start --workspace=examples/ts-node

fail with the same error:

npm ERR! missing script: start

install dependencies with npm install

Thank you for your work.
I cloned the project for trying it and I found out that dependencies are installed correctly only running lerna bootstrap from the root; I get an error when I try to run npm i in 'packages/bar' directory.
It tries to download 'foo' dependency from the public npm registry, instead of using the one in the monorepo.

Is there a way to fix this issue and have npm i working as well as lerna bootstrap?

Question: Role of Examples and Packages folders,

I do not know much about lerna. But I have seen that the packages directory typically consists of sub-directories whose names are something like: frontend (or web), backend (or api), shared.)

Could you pl. answer these:

a. What exactly is the role of foo, bar, and components directories residing in the packages directory.
b. Why do the cra and nest appear in the examples directory.

Thanks

How to enable autocomplete

Autocomplete in vscode not working without import. I try master and project-references branch. Have you explored the possibility to enable autocomplete?

image

Compilation does not work

Hey,

Thanks for this insightful example. I've a question though: I checked out the project reference branch, and running npm run build on foo yields this error:

src/index.ts:1:27 - error TS2307: Cannot find module '@nighttrax/foo'.

Any idea ?

Watch mode?

Hi,

First of all, thanks for this repo and accompanying article. Using TypeScript with Lerna feels way more complex than it should, and the resources you created really help with that complexity.

I'm curious to hear what you recommend for watch/development mode, such that you're listening for changes in any of the packages and automatically build them.

Thanks!

Using path aliases in cra

Hi @NiGhTTraX

In the cra app, I want to use the path aliases which, if I am right, could be specified in the cra's tsconfig.json as follows:

  "extends": "../../tsconfig.json", 
    ...
    baseUrl: "src",
    "paths": {
      "@contexts/*": ["contexts/*"],
      "@hooks/*": ["hooks/*"],
      "@shared/*": ["shared/*"],
    },

But this is not working. What do I need to do to make it work, any hints.

Kindly note that the ts-monorepo has its own ts-config file where the "paths" property is already there.

Thank you.

Problem with using expec

Applying tests in particular with toBeInTheDocument I'm having the following problem. I am not sure if it is for some reason that monorepo is unable to locate the lib of jest so that he can identify such a method
Screen Shot 2021-02-03 at 23 11 24

Dependency Dashboard

This issue lists Renovate updates and detected dependencies. Read the Dependency Dashboard docs to learn more.

Open

These updates have all been created already. Click a checkbox below to force a retry/rebase of any.

Detected dependencies

github-actions
.github/workflows/tests.yml
  • actions/checkout v4
  • pnpm/action-setup v3.0.0
  • actions/setup-node v4
npm
apps/cra/package.json
  • react ~18.2.0
  • react-dom ~18.2.0
  • @types/node ~20.12.0
  • @babel/core ~7.24.0
  • @babel/plugin-syntax-flow ~7.24.0
  • @babel/plugin-transform-react-jsx ~7.23.0
  • @craco/craco ~7.1.0
  • @types/express ~4.17.13
  • @types/jest ~29.5.0
  • @types/react ~18.2.0
  • @types/react-dom ~18.2.0
  • autoprefixer ~10.4.0
  • cross-env ~7.0.2
  • jest ~29.7.0
  • postcss ~8.4.31
  • react-scripts ~5.0.0
  • rimraf ~5.0.0
  • ts-jest ~29.1.0
  • tsconfig-paths-webpack-plugin ~4.1.0
  • typescript ~4.9.0
  • ts-node ~10.9.1
apps/jest-babel/package.json
  • @babel/core ~7.24.0
  • @babel/preset-env ~7.24.0
  • @babel/preset-typescript ~7.24.0
  • @types/jest ~29.5.0
  • babel-plugin-module-resolver ~5.0.0
  • jest ~29.7.0
apps/jest-tsjest/package.json
  • @types/jest ~29.5.0
  • @jest/types ~29.6.0
  • @types/node ~20.12.0
  • jest ~29.7.0
  • ts-jest ~29.1.0
  • ts-node ~10.9.0
  • typescript ~4.9.0
apps/nestjs/package.json
  • @nestjs/common ~10.3.0
  • @nestjs/core ~10.3.0
  • @nestjs/platform-express ~10.3.0
  • reflect-metadata ~0.1.13
  • rimraf ~5.0.0
  • rxjs ~7.8.0
  • @nestjs/cli ~10.3.0
  • @types/express ~4.17.11
  • @types/node ~20.12.0
  • ts-node ~10.9.0
  • tsconfig-paths ~4.2.0
  • typescript ~4.9.0
apps/nextjs/package.json
  • next ~14.0.0
  • react ~18.2.0
  • react-dom ~18.2.0
  • @types/node ~20.12.0
  • @types/react ~18.2.0
  • @types/react-dom ~18.2.0
  • rimraf ~5.0.0
  • typescript ~4.9.0
apps/rollup/package.json
  • @rollup/plugin-typescript ~11.1.5
  • @types/node ~20.12.0
  • rimraf ~5.0.0
  • rollup ~4.13.0
  • tslib ~2.6.0
  • typescript ~4.9.0
apps/storybook/package.json
  • react ~18.2.0
  • react-dom ~18.2.0
  • @babel/core ~7.24.0
  • @babel/preset-env ~7.24.0
  • @babel/preset-react ~7.24.0
  • @babel/preset-typescript ~7.24.0
  • @storybook/core-common ~7.6.0
  • @storybook/react ~7.6.0
  • @storybook/react-webpack5 ~7.6.0
  • @types/react ~18.2.21
  • @types/react-dom ~18.2.7
  • babel-loader ~9.1.0
  • require-from-string ~2.0.2
  • rimraf ~5.0.0
  • storybook ~7.6.0
  • tsconfig-paths-webpack-plugin ~4.1.0
  • typescript ~4.9.0
  • webpack ~5.91.0
apps/ts-node/package.json
  • @types/node ~20.12.0
  • ts-node ~10.9.0
  • tsconfig-paths ~4.2.0
  • typescript ~4.9.0
apps/vite/package.json
  • react ~18.2.0
  • react-dom ~18.2.0
  • @types/react ~18.2.0
  • @types/react-dom ~18.2.0
  • @vitejs/plugin-react ~4.2.0
  • rimraf ~5.0.0
  • typescript ~4.9.3
  • vite-tsconfig-paths ~4.2.0
  • vite ~5.2.0
apps/webpack/package.json
  • rimraf ~5.0.0
  • webpack ~5.91.0
  • webpack-cli ~5.1.0
  • ts-loader ~9.5.0
  • tsconfig-paths-webpack-plugin ~4.1.0
  • typescript ~4.9.0
package.json
  • @nighttrax/eslint-config-tsx ~12.0.0-alpha.2
  • doctoc ~2.2.0
  • eslint ~8.57.0
  • eslint-plugin-import ~2.29.0
  • typescript ~4.9.0
packages/bar/package.json
  • rimraf ~5.0.0
  • typescript ~4.9.0
packages/components/package.json
  • @types/react ~18.2.0
  • react ~18.2.0
  • react-dom ~18.2.0
  • rimraf ~5.0.0
  • react ~18.2.0
packages/foo/package.json
  • rimraf ~5.0.0
  • typescript ~4.9.0

  • Check this box to trigger a request for Renovate to run again on this repository

Typescript inside NPM workspace is not type-checked on compilation (CRA)

Thank you for your documentation.

I'm a week and a half stuck with this problem, all my Google links are purple, and my StackOverflow questions hasn't received any answers. Maybe you will know how to solve this issue.

Using techniques from this repo everything compiles without errors, even when common/* (shared) code contains missing types.

Our project structure:

 |-- apps          
   |-- native      
   |-- web
     |-- package.json
     |-- tsconfig.json
     |-- tsconfig..paths.json        
 |-- common        
   |-- models
     |-- package.json
     |-- tsconfig.json
   |-- connectors     
     |-- package.json
     |-- tsconfig.json
   |-- store         
     |-- package.json
     |-- tsconfig.json
   |-- types      
     |-- package.json
     |-- tsconfig.json    
   |-- utils         
     |-- package.json
     |-- tsconfig.json 
 -- package.json
 -- tsconfig.json
 -- tsconfig.paths.json

Root package.json

{
  "name": "@flowbase/client",
  "version": "1.0.0",
  "private": true,
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "",
  "workspaces": [
    "./common/*",
    "./apps/*"
  ],
  "devDependencies": {
    "@typescript-eslint/parser": "^4.26.0"
  }
}

Root tsconfig.json

{
  "extends": "./tsconfig.paths.json",
  "compilerOptions": {
    "baseUrl": ".",
    "paths": {
      "@flowbase/*": ["common/*"],
    }
  }
}

Root tsconfig.paths.json

{
  "compilerOptions": {
    "target": "es5",
    "lib": [
      "es2015",
      "dom",
      "dom.iterable",
      "esnext",
      "webworker"
    ],
    "allowJs": true,
    "skipLibCheck": true,
    "esModuleInterop": true,
    "experimentalDecorators": true,
    "allowSyntheticDefaultImports": true,
    "strict": true,
    "forceConsistentCasingInFileNames": true,
    "noFallthroughCasesInSwitch": true,
    "module": "esnext",
    "moduleResolution": "node",
    "resolveJsonModule": true,
    "isolatedModules": true,
    "noEmit": true,
    "jsx": "react-jsx",
    "types": [
      "jest"
    ]
  }
}

common/storepackage.json - example, they are all the same, only dependencies changing

{
  "name": "@flowbase/store",
  "version": "1.0.0",
  "private": true,
  "description": "",
  "main": "index.js",
  "dependencies": {
    "@flowbase/types": "1.0.0",
    "@flowbase/utils": "1.0.0",
    "@flowbase/connectors": "1.0.0",
    "@flowbase/apimodels": "1.0.0",
    "@microsoft/signalr": "5.0.1",
    "@types/lodash": "^4.14.165",
    "@types/react": "^17.0.3",
    "@types/redux-logger": "^3.0.8",
    "axios": "^0.21.1",
    "lodash": "^4.17.20",
    "msw": "^0.21.3",
    "react": "^17.0.2",
    "react-app-polyfill": "^1.0.6",
    "react-redux": "^7.2.3",
    "typescript": "^4.2.3"
  },
  "devDependencies": {
    "@types/jest": "^26.0.21",
    "eslint-plugin-react": "^7.23.1",
    "jest": "^26.6.3",
    "jest-json-schema": "^2.1.0",
    "jest-localstorage-mock": "^2.4.9",
    "tslint": "^5.20.1",
    "tslint-react": "^4.1.0"
  }
}

apps/web package.json

{
  "name": "@flowbase/web-client",
  "version": "0.1.0",
  "private": true,
  "dependencies": {
    "@flowbase/types": "1.0.0",
    "@flowbase/store": "1.0.0",
    "@flowbase/connectors": "1.0.0",
    "@flowbase/apimodels": "1.0.0",
    "@flowbase/utils": "1.0.0",
    "@monaco-editor/react": "^3.7.4",
    "@types/lodash": "^4.14.165",
    "@types/node": "^12.20.6",
    "@types/react": "^17.0.3",
    "@types/react-dom": "^17.0.3",
    "axios": "^0.21.1",
    "cronstrue": "^1.110.0",
    "lodash": "^4.17.20",
    "monaco-editor": "^0.17.1",
    "normalize.css": "^8.0.1",
    "pdfjs-dist": "2.8.335",
    "react": "^17.0.2",
    "react-app-polyfill": "^1.0.6",
    "react-datepicker": "^3.1.3",
    "react-dom": "^17.0.2",
    "react-redux": "^7.2.3",
    "react-scripts": "^4.0.3",
    "streamsaver": "^2.0.5",
    "style-scoped": "^0.2.1",
    "typescript": "^4.2.3",
    "yargs": "^15.4.1"
  },
  "scripts": {
    "start": "set NODE_ENV=development && node generate-config.js && rescripts start",
    "mock": "set MOCK_BACKEND='1' && rescripts start",
    "build": "set NODE_ENV=production && node generate-config.js && npm run generate-icons && rescripts build",
    "unit": "set NODE_ENV=development && set NODE_OPTIONS=--unhandled-rejections=warn && rescripts test --env=jsdom --watchAll=false --coverage",
    "unit-interactive": "set NODE_ENV=development && set NODE_OPTIONS=--unhandled-rejections=warn && rescripts test --env=jsdom",
    "e2e": "jest -c jest.config.js --runInBand",
    "e2e-debug": "set PWDEBUG=1 && jest -c jest.config.js --runInBand",
    "test": "npm run unit && npm run e2e",
    "generate-icons": "node generate-icons.js",
    "eject": "rescripts eject",
    "lint": "eslint ./src/**/*.ts ./src/**/*.tsx",
    "electron": "electron ."
  },
  "browserslist": {
    "production": [
      ">0.2%",
      "not dead",
      "not op_mini all"
    ],
    "development": [
      ">0.2%",
      "not dead",
      "not ie <= 11",
      "not op_mini all"
    ]
  },
  "devDependencies": {
    "@rescripts/cli": "0.0.16",
    "@types/jest": "^26.0.21",
    "@types/jest-image-snapshot": "^4.1.3",
    "@types/react-datepicker": "^3.1.8",
    "@types/react-jsonschema-form": "^1.7.3",
    "@types/react-redux": "^7.1.12",
    "@types/react-router-dom": "^4.3.5",
    "@types/streamsaver": "^2.0.0",
    "babel-plugin-module-resolver": "^4.1.0",
    "electron": "^12.0.2",
    "eslint-plugin-react": "^7.23.1",
    "fs-extra": "^8.1.0",
    "jest": "^26.6.3",
    "jest-image-snapshot": "^4.3.0",
    "jest-json-schema": "^2.1.0",
    "jest-localstorage-mock": "^2.4.9",
    "jest-playwright-preset": "^1.5.1",
    "mathsass": "^0.11.0",
    "msw": "^0.21.3",
    "node-sass": "^5.0.0",
    "playwright": "^1.11.1",
    "svg-sprite": "^1.5.0",
    "ts-jest": "^26.5.4",
    "tsconfig-paths-webpack-plugin": "^3.5.1",
    "tslint": "^5.20.1",
    "tslint-react": "^4.1.0",
    "vinyl": "^2.2.0"
  },
  "eslintConfig": {
    "extends": [
      "react-app",
      "react-app/jest"
    ]
  },
  "main": "./electron-start.js"
}

apps/web tsconfig.json

{
  "extends": "./tsconfig.paths.json",
  "compilerOptions": {
    "target": "es5",
    "lib": [
      "es2015",
      "dom",
      "dom.iterable",
      "esnext",
      "webworker"
    ],
    "allowJs": true,
    "skipLibCheck": true,
    "esModuleInterop": true,
    "experimentalDecorators": true,
    "allowSyntheticDefaultImports": true,
    "strict": true,
    "forceConsistentCasingInFileNames": true,
    "noFallthroughCasesInSwitch": true,
    "module": "esnext",
    "moduleResolution": "node",
    "resolveJsonModule": true,
    "isolatedModules": true,
    "noEmit": true,
    "jsx": "react-jsx",
    "types": [
      "jest",
      "jest-playwright-preset",
      "expect-playwright"
    ]
  },
  "include": [
    "src"
  ]
}

apps/web tsconfig.paths.json

{
    "compilerOptions": {
        "baseUrl": ".",
        "paths": {
            "@/*": ["src/*"],
        }
    }
}

We used rescripts instead of react-app-rewired, but the result is the same.

module.exports = [{
    const applyRuleFunctionRecursive = (fn, rule, parent) => {
      if (typeof rule !== "object") {
        return;
      }
      if (Array.isArray(rule)) {
        rule.forEach(r => applyRuleFunctionRecursive(fn, r, rule));
      } else if (rule.hasOwnProperty("use")) {
        applyRuleFunctionRecursive(fn, rule.use, rule);
      } else if (rule.hasOwnProperty("oneOf")) {
        applyRuleFunctionRecursive(fn, rule.oneOf, rule);
      } else {
        fn(rule, parent);
      }
    }
    const extendBabel = (plugin, parent) => {
      if (plugin.loader && plugin.loader.indexOf("babel-loader") !== -1) {
        plugin.include = undefined;
        plugin.exclude = /node_modules/;
        plugin.options.presets.push(
            ["@babel/preset-env", { targets: { node: "current" } }],
            "@babel/preset-typescript",
        );
        if (plugin.options.plugins) {
          plugin.options.plugins.push(
            [
              "module-resolver",
              {
                alias: {
                  '@flowbase': '../../common/',
                },
              },
            ],
          );
        }
      }
    }
    config.resolve.plugins.pop();
    config.resolve.plugins.push(new tsConfigPathsPlugin());

    applyRuleFunctionRecursive(extendBabel, config.module.rules, config);
    return config;
  }, 
}];

After npm install in the root folder, navigating into "apps/web" and npm start everything compiles without errors.

The problem is, that if I intentionally comment out a type import inside any of common/* workspaces, it still compiles without errors (doesn't type check). However, doing the same inside apps/web/ throws an error for missing types. (does type check)

Sorry for the long post, I really hope you can point us in the right direction.

NestJs example

It would be great to see how NestJs could be used with the setup you made for these plugins.

nestjs example build fails with `Can't resolve '@nestjs/websockets/socket-module'`

Hi there, what a cool repo!

I ran in to a build failure after doing the following on a fresh clone:

# npm version >=7 supports workspaces like yarn
npm install
npm run build

The error message:

ERROR in ../../node_modules/@nestjs/core/nest-application.js 16:102-145
Module not found: Error: Can't resolve '@nestjs/websockets/socket-module' in 'C:\dev\efokschaner\ts-monorepo\node_modules\@nestjs\core'
resolve '@nestjs/websockets/socket-module' in 'C:\dev\efokschaner\ts-monorepo\node_modules\@nestjs\core'
  Parsed request is a module
  using description file: C:\dev\efokschaner\ts-monorepo\node_modules\@nestjs\core\package.json (relative path: .)
    resolve as module
      looking for modules in C:\dev\efokschaner\ts-monorepo\node_modules\@nestjs\core\node_modules
        C:\dev\efokschaner\ts-monorepo\node_modules\@nestjs\core\node_modules\@nestjs\websockets doesn't exist
      C:\dev\efokschaner\ts-monorepo\node_modules\@nestjs\node_modules doesn't exist or is not a directory
      C:\dev\efokschaner\ts-monorepo\node_modules\node_modules doesn't exist or is not a directory
      looking for modules in C:\dev\efokschaner\ts-monorepo\node_modules
        C:\dev\efokschaner\ts-monorepo\node_modules\@nestjs\websockets doesn't exist
      C:\dev\efokschaner\node_modules doesn't exist or is not a directory
      C:\dev\node_modules doesn't exist or is not a directory
      C:\node_modules doesn't exist or is not a directory
 @ ../../node_modules/@nestjs/core/index.js 25:21-50
 @ ./src/main.ts 3:15-38

ERROR in ../../node_modules/@nestjs/core/nest-application.js 17:120-173
Module not found: Error: Can't resolve '@nestjs/microservices/microservices-module' in 'C:\dev\efokschaner\ts-monorepo\node_modules\@nestjs\core'
resolve '@nestjs/microservices/microservices-module' in 'C:\dev\efokschaner\ts-monorepo\node_modules\@nestjs\core'
  Parsed request is a module
  using description file: C:\dev\efokschaner\ts-monorepo\node_modules\@nestjs\core\package.json (relative path: .)
    resolve as module
      looking for modules in C:\dev\efokschaner\ts-monorepo\node_modules\@nestjs\core\node_modules
        C:\dev\efokschaner\ts-monorepo\node_modules\@nestjs\core\node_modules\@nestjs\microservices doesn't exist
      C:\dev\efokschaner\ts-monorepo\node_modules\@nestjs\node_modules doesn't exist or is not a directory
      C:\dev\efokschaner\ts-monorepo\node_modules\node_modules doesn't exist or is not a directory
      looking for modules in C:\dev\efokschaner\ts-monorepo\node_modules
        C:\dev\efokschaner\ts-monorepo\node_modules\@nestjs\microservices doesn't exist
      C:\dev\efokschaner\node_modules doesn't exist or is not a directory
      C:\dev\node_modules doesn't exist or is not a directory
      C:\node_modules doesn't exist or is not a directory
 @ ../../node_modules/@nestjs/core/index.js 25:21-50
 @ ./src/main.ts 3:15-38

webpack 5.28.0 compiled with 2 errors in 3305 ms

It appears webpack is not smart about these optionalRequires in nest-application.js.

After some learning about what nestjs is and how it works, I found that in their example boilerplate, they are not using webpack: https://github.com/nestjs/typescript-starter/blob/master/nest-cli.json

I'll post a PR with webpack removed so you can see if that's a fix that makes sense to you. That solved the issue for me locally.

Thanks!

react-native example ?

Hello,

Thanks for your nice work. It would be very interesting to have an example with react-native too.

Thanks for your blog post and maintaining this repo 👍

ESLint not working

Hello @NiGhTTraX

In the root package.json, there exists a devDependency named eslint. eslint-plugin-import is another dependency.
Also there is a "yarn lint" command in the same package.json.

In the examples/nestjs/package.json, eslint devDependency is again there.

In the examples/cra/package.json, there are no eslint-related dependencies. Also, the eslintConfig property is not there.

Earlier the eslint was working for nestjs as soon as I used to start the VSCode. Then I replaced 'react-app-rewired' with 'craco' in the CRA.. to provide support for tailwindcss.

Now the ESLint is neither working for nestjs nor cra. Why is there a mismatch between the esling configurations for the cra and nestjs examples?

Kindly help. Thanks

No serve/watch scripts?

Hey mate,

I've been using this repo as a starter for my monorepo since a few months and it's working pretty well for the most part. I'm glad the tooling (TS, Lerna, VSCode, e.g.) is working as expected in most important ways.

But am I correct in saying that there's not clear best practice or even implementation in serving and watching the packages?

Harm

Cannot read property 'oneOf' of undefined

warning package.json: No license field
$ react-app-rewired start
Cannot read property 'oneOf' of undefined
error Command failed with exit code 1.

const TsconfigPathsPlugin = require('tsconfig-paths-webpack-plugin');

module.exports = function override(config, env) {
    //https://medium.com/@NiGhTTraX/making-typescript-monorepos-play-nice-with-other-tools-a8d197fdc680
    // Remove the ModuleScopePlugin which throws when we try
    // to import something outside of src/.
    config.resolve.plugins.pop();

    // Resolve the path aliases.
    config.resolve.plugins.push(new TsconfigPathsPlugin());

    // Let Babel compile outside of src/.
    const tsRule = config.module.rules[2].oneOf[1];
    tsRule.include = undefined;
    tsRule.exclude = /node_modules/;
    return config;
}

importing files from package without /src or /dist

hello,
i am trying to link a file from one package to other directly, it doesn't work,
here is a fork with my example https://github.com/CosticaPuntaru/ts-monorepo/blob/master/packages/bar/src/index.ts

can you help me make it work ? :)

if i change paths to

  "paths": {
      "@nighttrax/foo/*": ["packages/foo/src/*"],
      "@nighttrax/*": ["packages/*/src"]
    },

the webstorm ide does not complain about the file, but compile breaks,

if i change tsconfig.build.json and add

"baseUrl": ".",
    "paths": {
      "@nighttrax/foo/*": [
        "packages/foo/src/*"
      ]
    }

it compiles but the compiled files are all messed up,
image

i understand why, but i am looking for workaround :)

Action Required: Fix Renovate Configuration

There is an error with this repository's Renovate configuration that needs to be fixed. As a precaution, Renovate will stop PRs until it is resolved.

Location: renovate.json
Error type: Invalid JSON (parsing failed)
Message: Syntax error: expecting end of expression or separator near sts"]. "

It doesn't work with `rootDirs`

Thanks for the tutorial! I had to make a change to the project-references branch and instead of rootDir use rootDirs. However, this completely breaks it. Any idea how to use include multiple roots in foo?

React cra with testing

Hi,

The tsconfig-paths works in development but not when running react-app-rewired test.
I am using typescript.
Cannot find module '@client/package' from 'src/Context.ts'
What should be added to get test to recognize the import module outside of src?

Thanks.

member variable not found error

step 1 :export a class in a package
image
step 2 : import the exported class in another package,then inherit it in this package
image
step 3 : npm run build
error will be found at this time

image

what should i do, thank you

Awesome repo - code splitting suggestion

This has to be the best Typescript/Next/Lerna monorepo I've seen yet. I've been searching for weeks for an optimal configuration. My requirements were:

  • ESLint applied to all sub-projects from root configuration.
  • Typescript support.
  • Hot reloading adjacent packages in the repo.
  • Optional publishing support.
  • Code splitting.

This checks all of the boxes except for the last one, but it's a simple fix.

I'm primarily concerned with the NextJS package and importing from other libs in the monorepo. To reproduce my issue, do the following:

  1. yarn build and observe the first load JS bundle size for the NextJS build (should be around 59KB)
  2. in packages/components, add react-select as a dependency.
  3. add packages/components/src/select.tsx with the following code:
import React from "react";
import Select from "react-select";

export function MySelect(): JSX.Element {
  return <Select />;
}
  1. update packages/components/src/index.tsx:
export * from "./button";
export * from "./select";
  1. yarn build at the root and observe the first load JS bundle size for the NextJS build (should now be somewhere around 86KB). This isn't ideal, as we've simply added a component that we're not using to another package in the repo.

Ideally, only the components that are imported should be included in the bundle.

To fix:

  1. Edit the root tsconfig.build.json:
module: "esnext"
moduleResolution: "node"

Code splitting is only supported in the more recent versions of es. Also, I had to make some modifications to support proper interface/type detection. Lmk if you want the details!

Cheers, thanks for the code!

EDIT2:
amended steps.

next and next-transpile-modules

Currently this template has a nextjs 9 example project, using next-transpile-modules 3.3.0 to handle shared packages. For reference, as of writing this next-transpile-modules is at version 6.4.0, and next is version 10.

As I described in the nextjs issue here vercel/next.js#5666 (comment), the next-transpile-modules changed their module resolution to use enhanced-resolve between the versions 3 and 4, which seemingly broke the usecase found in this repo.

As also suggested in that thread, I managed to work around this issue in my own project with the following next.config.js:

module.exports = {
  webpack: (config) => {
    config.module.rules.forEach((rule) => {
      if (rule.test && rule.test.toString().includes("tsx|ts")) {
        rule.include = [
          ...rule.include,
          // eslint-disable-next-line @typescript-eslint/no-var-requires
          require("path").join(__dirname, "../../packages"),
        ];
      }
    });
    return config;
  },
};

So far I'm unsure if there are any caveats to this approach as compared to next-transpile-modules. Either way, it might make sense to update the template to use something that does not break with latest versions of the packages involved.

Error in build process

Hey, thanks for that repo.

I was trying to copy the concept for my project. Sadly I couldnt bring it to build successfully, always got the failure "module not found" when I tried to run the build steps in a package with dependecies to other packages. (eg. @nighttrax/foo' not found in package/bar)

So I just tried to simply download and run this repo. Sadly I am running into few errors. May you understand what I am doing wrong?

image

I am using vscode on windows, so I changed nothing but the "clean" task. I changed "rm" command to a "rimraf" command which is globally installed, so I dont think thats a issue.

Thanks.

Help with Setup for Typescript Azure Functions

Goal

I want to use this template for setting up a monorepo with Azure Functions but I'm struggling to get it working how I want.

Problems

  • I got it working with imports that are exported from index.ts
  • I got it working with imports like: package/dist/file
  • I can't get it working with package/src/file or package/file style imports

I get the error:
'Error: Qualified path resolution failed - none of the candidates can be found on the disk.

According to issue Azure/azure-functions-core-tools#2 it seems that I need to use tsconfig-paths but I don't know how to do that as the azure functions core tools don't use ts-node.

Questions

  • Is there an alternative to tsconfig-paths to get paths like package/src/file or package/file working? Or does tsconfig-paths also work without ts-node?
  • How can I set this up so that when you start project-a you don't need to build project-b first?
  • I wondered why tsconfig.json and tsconfig.build.json is split. Maybe you can explain?

I hope someone can provide me some guidance here on possible ways to proceed! (it could be that this also isn't the right place to ask this)

Repro

I have made a minimal as possible repro here on a separate branch: https://github.com/ultimate-ttt/ttt-backends/tree/dev-mono-with-berry
To get it running you need:

  • Azure Function Core tools installed Installation Guide
  • yarn / yarn 2
  • To test whether the startup of the function works go to src/connection/ and run yarn start

If you have any problems with getting it running, I can help here.

Can't resolve './styles.module.css'. Do I need extra configuration ?

I was using a component from "components package" inside monorepo which is a button component. When I run from its own package, it runs with no problem. But if is is used from another package it shows this error.

../components/dist/components/atoms/Test/index.js
Module not found: Can't resolve './styles.module.css' in ...component path.

Any idea that can solve? thank in advance.

need CI/CD tips with monorepo strategy

I would like one suggestion when applied monorepo strategy.

We go to use this context as example.

Screen Shot 2021-09-05 at 16 34 41

When I change something in package/*, I need on my CI/CD detect all projects those have that specific dependence installed for trigger a deploy as well.

Existis tip with git commands or others for to help in this case?

Get error on windows - 'rm' is not recognized as an internal or external command,

First of all I think this can be very helpful for someone how just want to start working with Lerna and TS, thank you for this project.

I kind of missing some full instruction to make it work... maybe I missed it...

anyway - whenever I run Lerna run build - I get this error "'rm' is not recognized as an internal or external command,"
What can i do?

Thoughts on making this repo a template?

GitHub has recently introduced the templates feature:

Capture d’écran 2020-06-03 à 12 25 27

This repository and its accompanying article are so good that I think they deserve to be a template. I spent long hours debugging my TypeScript configs and reading other two tutorials before stumbling upon yours!

Oh, and if I may, a further idea: rebrand this to "ts-monorepo" or something alike - one doesn't have to use lerna to follow through the setup.

Internal path alias working even when importing external, is it possible?

Thank you in advance! your repository is helping me to learn a lot!

I want to bring a problem related to path alias between packages. I don't know if it's okay to do it the way I'm trying but come on, let me explain. I'm managing to call the packages between projects, so far so good. However, when I call one another and this other in his imports uses some alias (from the project itself) he gets lost.

Screen Shot 2020-11-22 at 20 19 25

In the common scenario, I would do a simple import {Container, Input as InputBase, Error} from '. / Styles', but I want to try to reach that sense of different projects having their alias declared for them and in this external relationship with internal, worked. You see?

I brought an example of a POC that I'm doing where I had this problem that I reported ... I tried to apply the same problem in your project and I had the same error

https://github.com/henriqueweiand/poc-yarn-workspaces

Error: Cannot find module '@nighttrax/foo'

I tried installing ts-node-dev to run the index file to see if it would throw this error, and indeed it did. For some reason, I just can not get monorepos to work for me. Even if VSCode detects symbols correctly, node can not resolve the modules at runtime.

[sparta@sparta-pc lerna-ts-master]$ yarn tsnd packages/bar/src/index.ts 
yarn run v1.19.0
$ /data/downloads/lerna-ts-master/node_modules/.bin/tsnd packages/bar/src/index.ts
Using ts-node version 8.6.2, typescript version 3.4.5
Error: Cannot find module '@nighttrax/foo'
Require stack:
- /data/downloads/lerna-ts-master/packages/bar/src/index.ts
    at Function.Module._resolveFilename (internal/modules/cjs/loader.js:980:15)
    at Function.Module._load (internal/modules/cjs/loader.js:862:27)
    at Module.require (internal/modules/cjs/loader.js:1040:19)
    at require (internal/modules/cjs/helpers.js:72:18)
    at Object.<anonymous> (/data/downloads/lerna-ts-master/packages/bar/src/index.ts:1:1)
    at Module._compile (internal/modules/cjs/loader.js:1151:30)
    at Module._compile (/data/downloads/lerna-ts-master/node_modules/source-map-support/source-map-support.js:541:25)
    at Module.m._compile (/tmp/ts-node-dev-hook-048440305208922174.js:57:25)
    at Module._extensions..js (internal/modules/cjs/loader.js:1171:10)
    at require.extensions.<computed> (/tmp/ts-node-dev-hook-048440305208922174.js:59:14)
[ERROR] 19:28:04 Error: Cannot find module '@nighttrax/foo'
Require stack:
- /data/downloads/lerna-ts-master/packages/bar/src/index.ts

Testing framework

Hi,
I think you did a great work here, you really saved me!
the only thing that I was missing is a testing framework, fortunately it was pretty easy to add Mocha and chai - so easy I was sure it's not going to work, I have already made to many changes to run a pull request but if you want to add it to the project I can help - I am also added nyc to get a code coverage report - (the only issue I have is that it's hard to see failing the tests when running lerna run test- but I think it's an issue with Lerna )

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.