[
  {
    "path": ".gitignore",
    "content": "**/node_modules\r\nlerna-debug.log\r\n"
  },
  {
    "path": "README.md",
    "content": "# Lerna + Project References\r\n\r\nThis is a \"bare minimum\" repo that shows one way to configure TypeScript Project References with lerna. There are a lot of different ways you can set things up and this isn't intended to be authoratitive guidance or exclusionary of other ways that might work better in your project.\r\n\r\n# Setting up this repo\r\n\r\n```\r\n> git clone https://github.com/RyanCavanaugh/learn-a.git\r\n> cd learn-a\r\n> npm install\r\n> lerna bootstrap\r\n> tsc -b packages\r\n```\r\n\r\nNote that you'll need a 3.0 version of `tsc` (currently available at `npm install -g typescript@next`).\r\n\r\n### General Structure\r\n\r\nAs with a normal lerna repo, there's a `packages` folder. Inside we have three creatively named packages `pkg1`, `pkg2`, and `pkg3`.\r\n\r\n```\r\npackages/\r\n| tsconfig.settings.json\r\n| tsconfig.json\r\n| pkg1/\r\n  | tsconfig.json\r\n  | src/\r\n  | | (typescript files)        \r\n  | lib/\r\n  | | (javascript files)\r\n  | | (.d.ts files)\r\n| pkg2/\r\n  | (same as pkg1)\r\n| pkg3/\r\n  | (same as pkg1)\r\n```\r\n\r\nLet's review each file in the repo and explain what's going on\r\n\r\n#### `tsconfig.settings.json`\r\n```js\r\n{\r\n    \"compilerOptions\": {\r\n        // Always include these settings\r\n        \"composite\": true,\r\n        \"declaration\": true,\r\n        \"declarationMap\": true,\r\n        \"sourceMap\": true,\r\n\r\n        // These settings are totally up to you        \r\n        \"esModuleInterop\": true,\r\n        \"target\": \"es5\",\r\n        \"module\": \"commonjs\",\r\n        \"strict\": true\r\n    }\r\n}\r\n```\r\nThis file contains the \"default\" settings that all packages will use for compilation. You will definitely want the `composite`, `declaration`, `declarationMap`, and `sourceMap` settings enabled for all projects, so include those in this file. Other settings, like `target` and `strict`, can be specified here if you'd like to enable them by default. You'll also be able to override these settings on a per-package basis if needed.\r\n\r\n#### `tsconfig.json`\r\n```json\r\n{\r\n    \"files\": [],\r\n    \"references\": [\r\n        { \"path\": \"pkg1\" },\r\n        { \"path\": \"pkg2\" },\r\n        { \"path\": \"pkg3\" }\r\n    ]\r\n}\r\n```\r\nThis file is pretty simple - simply list the packages that need to be built with `tsc` in the `references` array.\r\nYou should also include `\"files\": []` in this file - this will prevent an incorrect invocation of `tsc` without `-b` from trying to build the entire packages folder source files as one compilation (which will fail, but drop a bunch of .js files in random places as an annoying side effect).\r\n\r\n#### `packages/pkg2/tsconfig.json`\r\n\r\nWe'll just cover one of the `pkg1` / `pkg2` / `pkg3` packages since they're basically identical for the purposes of this demo. Here's `pkg2`'s `tsconfig.json`:\r\n```json\r\n{\r\n  \"extends\": \"../tsconfig.settings.json\",\r\n  \"compilerOptions\": {\r\n    \"outDir\": \"lib\",\r\n    \"rootDir\": \"src\"\r\n  },\r\n  \"references\": [\r\n    { \"path\": \"../pkg1\" }\r\n  ]\r\n}\r\n```\r\nThe `extends` property pulls in the settings we wrote in `tsconfig.settings.json`, so we don't have to duplicate any settings described there.\r\n\r\nIn `compilerOptions`, we've set `outDir` to `lib` and `rootDir` to `src`, then placed all my `.ts` files in `src`. This means `src/index.ts` will build to `lib/index.js` and `lib/index.d.ts`. This is also the place where you could override settings like `strict` or `target` if you needed to change them on a per-project basis.\r\n\r\nIn the `references` array, we list the paths to the other projects' `tsconfig.json` files (or containing folders, as shown here). This will both ensure that we locate the `.d.ts` files correctly, and set up a proper build ordering.\r\n\r\n#### `packages/pkg2/src/index.ts`\r\n```ts\r\nimport * as p1 from '@ryancavanaugh/pkg1';\r\n\r\nexport function fn4() {\r\n    p1.fn();\r\n}\r\n```\r\nNothing unusual going on here. We import and export with the usual syntax. Notably, if you open this repo in an editor, you can still \"Go to Definition (F12)\" on `p1.fn` here and land in `pkg1/foo.ts` - the original sourcecode - even though \"under the covers\" it's using the much faster `.d.ts` file for typechecking.\r\n\r\n#### `packages/pkg2/package.json`\r\nHere are the relevant excerpts from the `package.json`:\r\n```json\r\n{\r\n  \"main\": \"lib/index.js\",\r\n  \"typings\": \"lib/index.d.ts\",\r\n  \"scripts\": {\r\n    \"prepublishOnly\": \"tsc -b .\"\r\n  },\r\n  \"devDependencies\": {\r\n    \"typescript\": \"^3.0.0-dev.20180626\"\r\n  }\r\n}\r\n```\r\n\r\nBecause we build to `lib`, we need to set `main` to the `.js` file there *and* `typings` to the `.d.ts` file.\r\n\r\nIn `scripts`, we use the local copy of `tsc` (listed here as a dev dependency) to run a *build mode* compilation on the project. This will ensure that the `lib` folder is always built before `npm publish`, and blocks any publishes that try to push non-compiling code.\r\n\r\n#### `packages/pkg2/.npmignore` / `packages/pkg2/.gitignore`\r\n\r\n*.gitignore*\r\n```\r\nlib/\r\n```\r\n\r\n*.npmignore*\r\n```\r\n# Empty, but needs to exist\r\n```\r\n\r\nThe `.gitignore` stops us from checking in build outputs, which is generally a good idea. By default, `npm` won't publish files that are ignored by `git`, so we need a separate `.npmignore` file so that the `lib` folder still gets published!\r\n\r\n# Workflow\r\n\r\nAll your lerna commands and workflow will work as expected here.\r\n\r\nTo build the TypeScript projects, you can run individual builds with `tsc -b`:\r\n```\r\n > tsc -b packages/pkg3\r\n```\r\nOr just build everything:\r\n```\r\n > tsc -b packages\r\n```\r\n"
  },
  {
    "path": "lerna.json",
    "content": "{\n  \"lerna\": \"2.11.0\",\n  \"packages\": [\n    \"packages/*\"\n  ],\n  \"version\": \"3.0.2\"\n}\n"
  },
  {
    "path": "package.json",
    "content": "{\n\t\"devDependencies\": {\n\t\t\"lerna\": \"^2.11.0\",\n\t\t\"typescript\": \"^3.0.0-dev.20180626\"\n\t}\n}\n"
  },
  {
    "path": "packages/pkg1/.gitignore",
    "content": "lib"
  },
  {
    "path": "packages/pkg1/.npmignore",
    "content": "# Empty to override .gitignore ignoring the output folder\r\n"
  },
  {
    "path": "packages/pkg1/package.json",
    "content": "{\n  \"name\": \"@ryancavanaugh/pkg1\",\n  \"version\": \"3.0.2\",\n  \"description\": \"\",\n  \"main\": \"lib/index.js\",\n  \"typings\": \"lib/index.d.ts\",\n  \"scripts\": {\n    \"test\": \"echo \\\"Error: no test specified\\\" && exit 1\",\n    \"prepublishOnly\": \"tsc -b .\"\n  },\n  \"keywords\": [],\n  \"author\": \"\",\n  \"license\": \"ISC\",\n  \"devDependencies\": {\n    \"typescript\": \"^3.0.0-dev.20180626\"\n  }\n}\n"
  },
  {
    "path": "packages/pkg1/src/foo.ts",
    "content": "export function fn() {\r\n    return \"Hello world\";\r\n}\r\n"
  },
  {
    "path": "packages/pkg1/src/index.ts",
    "content": "export * from \"./foo\";\r\n"
  },
  {
    "path": "packages/pkg1/tsconfig.json",
    "content": "{\r\n  \"extends\": \"../tsconfig.settings.json\",\r\n  \"compilerOptions\": {\r\n    \"outDir\": \"lib\",\r\n    \"rootDir\": \"src\"\r\n  }\r\n}"
  },
  {
    "path": "packages/pkg2/.gitignore",
    "content": "lib"
  },
  {
    "path": "packages/pkg2/.npmignore",
    "content": "# Empty to override .gitignore ignoring the output folder\r\n"
  },
  {
    "path": "packages/pkg2/package.json",
    "content": "{\n  \"name\": \"@ryancavanaugh/pkg2\",\n  \"version\": \"3.0.2\",\n  \"description\": \"\",\n  \"main\": \"lib/index.js\",\n  \"typings\": \"lib/index.d.ts\",\n  \"scripts\": {\n    \"test\": \"echo \\\"Error: no test specified\\\" && exit 1\",\n    \"prepublishOnly\": \"tsc -b .\"\n  },\n  \"keywords\": [],\n  \"author\": \"\",\n  \"license\": \"ISC\",\n  \"dependencies\": {\n    \"@ryancavanaugh/pkg1\": \"^3.0.2\"\n  },\n  \"devDependencies\": {\n    \"typescript\": \"^3.0.0-dev.20180626\"\n  }\n}\n"
  },
  {
    "path": "packages/pkg2/src/index.ts",
    "content": "import * as p1 from '@ryancavanaugh/pkg1';\r\n\r\nexport function fn4() {\r\n    p1.fn();\r\n}\r\n\r\n"
  },
  {
    "path": "packages/pkg2/tsconfig.json",
    "content": "{\r\n  \"extends\": \"../tsconfig.settings.json\",\r\n  \"compilerOptions\": {\r\n    \"outDir\": \"lib\",\r\n    \"rootDir\": \"src\"\r\n  },\r\n  \"references\": [\r\n    { \"path\": \"../pkg1\" }\r\n  ]\r\n}"
  },
  {
    "path": "packages/pkg3/.gitignore",
    "content": "lib"
  },
  {
    "path": "packages/pkg3/.npmignore",
    "content": "# Empty to override .gitignore ignoring the output folder\r\n"
  },
  {
    "path": "packages/pkg3/package.json",
    "content": "{\n  \"name\": \"@ryancavanaugh/pkg3\",\n  \"version\": \"3.0.2\",\n  \"description\": \"\",\n  \"main\": \"lib/index.js\",\n  \"typings\": \"lib/index.d.ts\",\n  \"scripts\": {\n    \"test\": \"echo \\\"Error: no test specified\\\" && exit 1\",\n    \"prepublishOnly\": \"tsc -b .\"\n  },\n  \"keywords\": [],\n  \"author\": \"\",\n  \"license\": \"ISC\",\n  \"dependencies\": {\n    \"@ryancavanaugh/pkg1\": \"^3.0.2\",\n    \"@ryancavanaugh/pkg2\": \"^3.0.2\"\n  },\n  \"devDependencies\": {\n    \"typescript\": \"^3.0.0-dev.20180626\"\n  }\n}\n"
  },
  {
    "path": "packages/pkg3/src/index.ts",
    "content": "import * as p1 from \"@ryancavanaugh/pkg1\";\r\nimport * as p2 from \"@ryancavanaugh/pkg2\";\r\n\r\np1.fn();\r\np2.fn4();\r\n"
  },
  {
    "path": "packages/pkg3/tsconfig.json",
    "content": "{\r\n  \"extends\": \"../tsconfig.settings.json\",\r\n  \"compilerOptions\": {\r\n    \"outDir\": \"lib\",\r\n    \"rootDir\": \"src\"\r\n  },\r\n  \"references\": [\r\n    { \"path\": \"../pkg1\" },\r\n    { \"path\": \"../pkg2\" }\r\n  ]\r\n}"
  },
  {
    "path": "packages/tsconfig.json",
    "content": "{\r\n    \"files\": [],\r\n    \"references\": [\r\n        { \"path\": \"pkg1\" },\r\n        { \"path\": \"pkg2\" },\r\n        { \"path\": \"pkg3\" }\r\n    ]\r\n}"
  },
  {
    "path": "packages/tsconfig.settings.json",
    "content": "{\r\n    \"compilerOptions\": {\r\n        \"target\": \"es5\",\r\n        \"module\": \"commonjs\",\r\n        \"declaration\": true,\r\n        \"declarationMap\": true,\r\n        \"sourceMap\": true,\r\n        \"strict\": true,\r\n        \"composite\": true,\r\n        \"esModuleInterop\": true\r\n    }\r\n}\r\n"
  }
]