{"id":15391074,"url":"https://github.com/quramy/npm-ts-workspaces-example","last_synced_at":"2025-05-16T09:03:58.258Z","repository":{"id":37076879,"uuid":"304316929","full_name":"Quramy/npm-ts-workspaces-example","owner":"Quramy","description":"Monorepos example project using npm workspaces and TypeScript project references","archived":false,"fork":false,"pushed_at":"2025-05-14T07:49:55.000Z","size":1118,"stargazers_count":326,"open_issues_count":7,"forks_count":40,"subscribers_count":4,"default_branch":"main","last_synced_at":"2025-05-14T08:46:01.467Z","etag":null,"topics":["example","lerna","monorepo","npm","typescript"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Quramy.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2020-10-15T12:20:10.000Z","updated_at":"2025-05-12T18:41:14.000Z","dependencies_parsed_at":"2023-12-30T01:47:36.914Z","dependency_job_id":"3bd07518-d01c-459e-8672-a9efe8beca3b","html_url":"https://github.com/Quramy/npm-ts-workspaces-example","commit_stats":{"total_commits":137,"total_committers":5,"mean_commits":27.4,"dds":"0.45985401459854014","last_synced_commit":"19bb9ffdeab0c6aeb6adf259894264c0b5e9d4de"},"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Quramy%2Fnpm-ts-workspaces-example","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Quramy%2Fnpm-ts-workspaces-example/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Quramy%2Fnpm-ts-workspaces-example/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Quramy%2Fnpm-ts-workspaces-example/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Quramy","download_url":"https://codeload.github.com/Quramy/npm-ts-workspaces-example/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254501556,"owners_count":22081528,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["example","lerna","monorepo","npm","typescript"],"created_at":"2024-10-01T15:09:54.077Z","updated_at":"2025-05-16T09:03:58.205Z","avatar_url":"https://github.com/Quramy.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# How to build TypeScript mono-repo project\n\n[![github actions](https://github.com/Quramy/npm-ts-workspaces-example/workflows/build/badge.svg)](https://github.com/Quramy/npm-ts-workspaces-example/actions)\n\nThis repository explains how to create monorepos project using npm and TypeScript.\n\n## ToC\n\n- [Tools](#tools)\n- [Directory Structure](#directory-structure)\n- [Workspaces](#workspaces)\n- [Dependencies across packages](#dependencies-across-packages)\n- [Resolve dependencies as TypeScript projects](#resolve-dependencies-as-typescript-projects)\n- [How to execute scripts for each package ?](#how-to-execute-scripts-for-each-package-)\n- [License](#license)\n\n## Tools\n\n- npm cli(v7 or later)\n- TypeScript\n\n## Directory Structure\n\nPut each package under the `packages` directory.\n\n```\n.\n├── node_modules/\n├── README.md\n├── package-lock.json\n├── package.json\n├── packages\n│   ├── x-cli\n│   │   ├── lib\n│   │   │   ├── cli.d.ts\n│   │   │   ├── cli.js\n│   │   │   ├── cli.js.map\n│   │   │   ├── main.d.ts\n│   │   │   ├── main.js\n│   │   │   └── main.js.map\n│   │   ├── package.json\n│   │   ├── src\n│   │   │   ├── cli.ts\n│   │   │   └── main.ts\n│   │   └── tsconfig.json\n│   └── x-core\n│       ├── lib\n│       │   ├── index.d.ts\n│       │   ├── index.js\n│       │   └── index.js.map\n│       ├── package.json\n│       ├── src\n│       │   └── index.ts\n│       └── tsconfig.json\n├── tsconfig.build.json\n└── tsconfig.json\n```\n\n## Workspaces\n\nUsing [npm workspaces feature](https://github.com/npm/rfcs/blob/latest/implemented/0026-workspaces.md), configure the following files:\n\nOpen `package.json` and append the `workspaces` key.\n\n```js\n/* package.json */\n\n{\n  \"name\": \"npm-ts-workspaces-example\",\n  \"private\": true,\n  ...\n  \"workspaces\": [\"packages/*\"]\n}\n```\n\nExec `npm install`. After successful running, all dependencies included from each package are downloaded under the repository root `node_modules` directory.\n\n## Dependencies across packages\n\nIn this example, the `x-cli` package depends on another package, `x-core`. So to execute (or test) `x-cli`, `x-core` packages should be installed.\nBut in development the `x-core` package is not published so you can't install it.\n\nFor example, `packages/x-cli/src/main.spec.ts` is a test code for `main.ts`, which depends on `packages/x-core/src/index.ts` .\n\n```ts\n/* packages/x-cli/src/main.ts.*/\n\nimport { awesomeFn } from \"@quramy/x-core\";\n\nexport async function main() {\n  // dependencies across child packages\n  const out = await awesomeFn();\n  return out;\n}\n```\n\nSo we need to link `x-core` package from `x-cli` to execute the `x-cli` 's test.\n\nWorkspaces feature of npm also solves this problem. `npm i` creates sim-links of each package into the top-level `node_modules` dir.\n\n## Resolve dependencies as TypeScript projects\n\nAs mentioned above, npm cli resolves dependencies across packages. It's enough for \"runtime\". However considering TypeScript sources, in other words \"static\", it's not.\n\nWe need to tell \"x-cli package depends on x-core\" to TypeScript compiler. TypeScript provides much useful feature to do this, [\"Project References\"](https://www.typescriptlang.org/docs/handbook/project-references.html).\n\nFirst, you add `composite: true` to project-root tsconfig.json to use project references feature.\n\n```js\n/* tsconfig.json */\n\n{\n  \"compilerOptions\": {\n    ...\n    \"composite\": true\n  }\n}\n```\n\nSecond, configure each package's tsconfig and configure dependencies across packages.\n\n```js\n/* packages/x-cli/tsconfig.json */\n\n{\n  \"extends\": \"../../tsconfig.json\",\n  \"compilerOptions\": {\n    \"rootDir\": \"src\",\n    \"outDir\": \"lib\"\n  },\n  \"references\": [{ \"path\": \"../x-core\" }]\n}\n```\n\nAnd create a project which depends on all packages:\n\n```js\n/* tsconfig.build.json */\n\n{\n  \"files\": [],\n  \"references\": [{ \"path\": \"packages/x-core\" }, { \"path\": \"packages/x-cli\" }]\n}\n```\n\nLet's exec `npx tsc --build tsconfig.build.json`. The .ts files included in all packages are build at once!\n\n## How to execute scripts for each package ?\n\nWe can use [`--workspaces` option](https://docs.npmjs.com/cli/v10/using-npm/workspaces#running-commands-in-the-context-of-workspaces).\n\n```sh\n# Excecute npm test in all workspaces\n$ npm test --workspaces\n```\n\n```sh\n# Bump up packages in all workspaces\n$ npm version --workspaces patch\n\n# Publish packages in all workspaces\n$ npm publish --workspaces\n```\n\n## License\n\nThe MIT License (MIT)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fquramy%2Fnpm-ts-workspaces-example","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fquramy%2Fnpm-ts-workspaces-example","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fquramy%2Fnpm-ts-workspaces-example/lists"}