Skip to content

Commit

Permalink
feat: always include tslint and typescript in project dev-dependencies
Browse files Browse the repository at this point in the history
This change is necessary to allow `@loopback/tslint-config` to include
tslint extensions from 3rd-party packages, because these extensions
typically have a peer dependency on `tslint`.

Another benefit is that projects can decide now which version of `tsc`
and `tslint` they want to use, independently of the version bundled
inside `@loopback/build`.

To make it easier to keep typescript & tslint version specifiers in
different places in sync, a new helper script is added to propagate
changes in dev-dependencies from monorepo's root package.json to example
projects: "npm run sync-dev-deps"
  • Loading branch information
bajtos committed Jan 7, 2019
1 parent 37c23fe commit e0df285
Show file tree
Hide file tree
Showing 12 changed files with 117 additions and 11 deletions.
63 changes: 63 additions & 0 deletions bin/sync-dev-deps.js
@@ -0,0 +1,63 @@
#!/usr/bin/env node
// Copyright IBM Corp. 2017,2018. All Rights Reserved.
// Node module: loopback-next
// This file is licensed under the MIT License.
// License text available at https://opensource.org/licenses/MIT

/**
* This is an internal script to synchronize versions of dev-dependencies
* from monorepo's package.json to individual example packages.
*/
'use strict';

const path = require('path');
const fs = require('fs');

const Project = require('@lerna/project');

async function syncDevDeps() {
const project = new Project(process.cwd());
const packages = await project.getPackages();

const rootPath = project.rootPath;

// Load dependencies from `packages/build/package.json`
const buildDeps = require(path.join(rootPath, 'packages/build/package.json'))
.dependencies;

const masterDeps = {
typescript: buildDeps.typescript,
tslint: buildDeps.tslint,
};

// Update typescript & tslint dependencies in individual packages
for (const pkg of packages) {
const data = readJsonFile(pkg.manifestLocation);
let modified = false;
for (const dep in masterDeps) {
if (data.devDependencies && dep in data.devDependencies) {
data.devDependencies[dep] = masterDeps[dep];
modified = true;
}
}
if (!modified) continue;
writeJsonFile(pkg.manifestLocation, data);
}

// Update dependencies in monorepo root
const rootPackage = path.join(rootPath, 'package.json');
const data = readJsonFile(rootPackage);
Object.assign(data.devDependencies, masterDeps);
writeJsonFile(rootPackage, data);
}

if (require.main === module) syncDevDeps();

function readJsonFile(filePath) {
return JSON.parse(fs.readFileSync(filePath, 'utf-8'));
}

function writeJsonFile(filePath, data) {
fs.writeFileSync(filePath, JSON.stringify(data, null, 2) + '\n', 'utf-8');
console.log('%s has been updated.', filePath);
}
22 changes: 22 additions & 0 deletions docs/site/DEVELOPING.md
Expand Up @@ -22,6 +22,7 @@ See [Monorepo overview](./MONOREPO.md) for a list of all packages.
- [Making breaking changes](#making-breaking-changes)
- [Releasing new versions](#releasing-new-versions)
- [Adding a new package](#adding-a-new-package)
- [Upgrading TypeScript/tslint](#upgrading-typescripttslint)
- [How to test infrastructure changes](#how-to-test-infrastructure-changes)

## Setting up development environment
Expand Down Expand Up @@ -437,6 +438,27 @@ Please register the new package in the following files:
[@raymondfeng](https://github.com/raymondfeng) to enlist the new package on
<http://apidocs.loopback.io/>.

## Upgrading TypeScript/tslint

In order to support tslint extensions with a peer dependency on tslint, we have
to specify `typescript` and `tslint` dependency in multiple places in our
monorepo.

Steps to upgrade `typescript` or `tslint` to a newer version:

1. Update the dependencies in `@loopback/build`, this is the source of truth for
the rest of the monorepo.

```shell
$ (cd packages/build && npm update typescript tslint)
```

2. Propagate the change to other places to keep everything consistent.

```shell
$ node bin/sync-dev-deps
```

## How to test infrastructure changes

When making changes to project infrastructure, e.g. modifying `tsc` or `tslint`
Expand Down
4 changes: 3 additions & 1 deletion examples/hello-world/package.json
Expand Up @@ -43,7 +43,9 @@
"@loopback/build": "^1.1.0",
"@loopback/testlab": "^1.0.3",
"@loopback/tslint-config": "^1.0.0",
"@types/node": "^10.11.2"
"@types/node": "^10.11.2",
"tslint": "^5.12.0",
"typescript": "^3.2.2"
},
"keywords": [
"loopback",
Expand Down
4 changes: 3 additions & 1 deletion examples/log-extension/package.json
Expand Up @@ -45,7 +45,9 @@
"@loopback/testlab": "^1.0.3",
"@loopback/tslint-config": "^1.0.0",
"@types/debug": "0.0.30",
"@types/node": "^10.11.2"
"@types/node": "^10.11.2",
"tslint": "^5.12.0",
"typescript": "^3.2.2"
},
"dependencies": {
"@loopback/context": "^1.4.0",
Expand Down
4 changes: 3 additions & 1 deletion examples/rpc-server/package.json
Expand Up @@ -49,6 +49,8 @@
"@loopback/tslint-config": "^1.0.0",
"@types/express": "^4.11.1",
"@types/node": "^10.11.2",
"@types/p-event": "^1.3.0"
"@types/p-event": "^1.3.0",
"tslint": "^5.12.0",
"typescript": "^3.2.2"
}
}
4 changes: 3 additions & 1 deletion examples/soap-calculator/package.json
Expand Up @@ -57,6 +57,8 @@
"@types/mocha": "^5.0.0",
"@types/node": "^10.11.2",
"mocha": "^5.1.1",
"source-map-support": "^0.5.5"
"source-map-support": "^0.5.5",
"tslint": "^5.12.0",
"typescript": "^3.2.2"
}
}
4 changes: 3 additions & 1 deletion examples/todo-list/package.json
Expand Up @@ -53,7 +53,9 @@
"@loopback/tslint-config": "^1.0.0",
"@types/lodash": "^4.14.109",
"@types/node": "^10.11.2",
"lodash": "^4.17.10"
"lodash": "^4.17.10",
"tslint": "^5.12.0",
"typescript": "^3.2.2"
},
"keywords": [
"loopback",
Expand Down
4 changes: 3 additions & 1 deletion examples/todo/package.json
Expand Up @@ -53,7 +53,9 @@
"@loopback/tslint-config": "^1.0.0",
"@types/lodash": "^4.14.109",
"@types/node": "^10.11.2",
"lodash": "^4.17.10"
"lodash": "^4.17.10",
"tslint": "^5.12.0",
"typescript": "^3.2.2"
},
"keywords": [
"loopback",
Expand Down
5 changes: 4 additions & 1 deletion package.json
Expand Up @@ -17,13 +17,16 @@
"coveralls": "^3.0.0",
"cz-conventional-changelog": "^2.1.0",
"husky": "^1.2.0",
"lerna": "^3.5.1"
"lerna": "^3.5.1",
"tslint": "^5.12.0",
"typescript": "^3.2.2"
},
"scripts": {
"postinstall": "lerna bootstrap",
"prerelease": "npm run build:full && npm run mocha && npm run lint",
"release": "lerna version && lerna publish from-git --yes",
"update-template-deps": "node bin/update-template-deps -f",
"sync-dev-deps": "node bin/sync-dev-deps",
"version": "npm run update-template-deps && npm run apidocs",
"outdated": "npm outdated --depth 0 && lerna exec --no-bail \"npm outdated --depth 0\"",
"apidocs": "node bin/run-lerna run build:apidocs",
Expand Down
4 changes: 2 additions & 2 deletions packages/build/package.json
Expand Up @@ -26,8 +26,8 @@
"rimraf": "^2.6.2",
"source-map-support": "^0.5.5",
"strong-docs": "^4.0.0",
"tslint": "^5.9.1",
"typescript": "^3.2.1"
"tslint": "^5.12.0",
"typescript": "^3.2.2"
},
"bin": {
"lb-tsc": "./bin/compile-package.js",
Expand Down
6 changes: 5 additions & 1 deletion packages/cli/generators/project/templates/package.json.ejs
Expand Up @@ -93,6 +93,10 @@
"@loopback/build": "<%= project.dependencies['@loopback/build'] -%>",
"@loopback/testlab": "<%= project.dependencies['@loopback/testlab'] -%>",
"@loopback/tslint-config": "<%= project.dependencies['@loopback/tslint-config'] -%>",
"@types/node": "<%= project.dependencies['@types/node'] -%>"
"@types/node": "<%= project.dependencies['@types/node'] -%>",
<% if (project.tslint) { -%>
"tslint": "<%= project.dependencies['tslint'] -%>",
<% } -%>
"typescript": "<%= project.dependencies['typescript'] -%>"
}
}
4 changes: 3 additions & 1 deletion packages/cli/test/integration/lib/project-generator.js
Expand Up @@ -249,11 +249,12 @@ module.exports = function(projGenerator, props, projectType) {
assert.jsonFileContent('package.json', props);
assert.fileContent([
['package.json', '@loopback/build'],
['package.json', '"typescript"'],
['package.json', '"tslint"'],
['tslint.json', '@loopback/tslint-config'],
['tsconfig.json', '@loopback/build'],
]);
assert.noFileContent([
['package.json', '"typescript"'],
['tslint.json', '"rules"'],
['tsconfig.json', '"compilerOptions"'],
]);
Expand Down Expand Up @@ -423,6 +424,7 @@ module.exports = function(projGenerator, props, projectType) {
assert.noFile(['tslint.json', 'tslint.build.json']);
assert.noFileContent([
['package.json', '@loopback/build'],
['package.json', '"tslint"'],
['tsconfig.json', '@loopback/build'],
]);
assert.fileContent([
Expand Down

0 comments on commit e0df285

Please sign in to comment.