diff --git a/docs/site/Creating-components.md b/docs/site/Creating-components.md index 83fff992e382..b79733d33a4c 100644 --- a/docs/site/Creating-components.md +++ b/docs/site/Creating-components.md @@ -36,6 +36,59 @@ export class MyComponent implements Component { } ``` +## Working with dependencies + +Extensions should preferably use LoopBack modules installed by the target +application, to allow application developers to choose the version of framework +modules they want to use. For example, they may want to hold to an older version +until a regression is fixed in the latest version, or even use their own fork to +have a bug fix available before it's officially published. + +We recommend to use `peerDependencies` to specify what packages is your +extension expecting in the target application and `devDependencies` to make +these packages available for extension tests. + +For example: + +```json +{ + "name": "my-lb4-extension", + "version": "1.0.0", + "dependencies": { + "tslib": "^2.0.0" + }, + "peerDependencies": { + "@loopback/core": "^2.9.1", + "@loopback/rest": "^5.2.0" + }, + "devDependencies": { + "@loopback/build": "^6.1.0", + "@loopback/core": "^2.9.1", + "@loopback/eslint-config": "^8.0.3", + "@loopback/rest": "^5.2.0", + "@loopback/testlab": "^3.2.0" + } +} +``` + +It is also possible for a single extension version to support multiple versions +of a framework dependency: + +```json +{ + "peerDependencies": { + "@loopback/core": "^1.9.0 || ^2.0.0" + } +} +``` + +{% include important.html content=' Shrinking the supported version range of a +peer dependency is a breaking change that should trigger a semver-major release. + +For example, changing the range from `"^1.5.3"` to `"^1.5.3 || ^2.0.0"` is +backwards compatible, while changing the range from `"^1.5.3"` to `"^2.0.0"` is +a breaking change. ' %} + ## Injecting the target application instance You can inject anything from the context and access them from a component. In diff --git a/packages/cli/generators/project/templates/package.json.ejs b/packages/cli/generators/project/templates/package.json.ejs index 3b5d3ad8b64e..3c814c732401 100644 --- a/packages/cli/generators/project/templates/package.json.ejs +++ b/packages/cli/generators/project/templates/package.json.ejs @@ -115,10 +115,15 @@ "src", "!*/__tests__" ], +<% if (project.projectType === 'extension') { -%> + "peerDependencies": { + "@loopback/core": "<%= project.dependencies['@loopback/core'] -%>" + }, +<% } -%> "dependencies": { +<% if (project.projectType === 'application') { -%> "@loopback/boot": "<%= project.dependencies['@loopback/boot'] -%>", "@loopback/core": "<%= project.dependencies['@loopback/core'] -%>", -<% if (project.projectType === 'application') { -%> <% if (project.repositories) { -%> "@loopback/repository": "<%= project.dependencies['@loopback/repository'] -%>", <% } -%> @@ -138,6 +143,9 @@ "devDependencies": { "@loopback/build": "<%= project.dependencies['@loopback/build'] -%>", "source-map-support": "<%= project.dependencies['source-map-support'] -%>", +<% if (project.projectType === 'extension') { -%> + "@loopback/core": "<%= project.dependencies['@loopback/core'] -%>", +<% } -%> "@loopback/testlab": "<%= project.dependencies['@loopback/testlab'] -%>", "@types/node": "<%= project.dependencies['@types/node'] -%>", <% if (project.eslint) { -%> diff --git a/packages/cli/generators/project/templates/package.plain.json.ejs b/packages/cli/generators/project/templates/package.plain.json.ejs index 70b5235d049f..53ce2b72aff3 100644 --- a/packages/cli/generators/project/templates/package.plain.json.ejs +++ b/packages/cli/generators/project/templates/package.plain.json.ejs @@ -120,10 +120,15 @@ "src", "!*/__tests__" ], +<% if (project.projectType === 'extension') { -%> + "peerDependencies": { + "@loopback/core": "<%= project.dependencies['@loopback/core'] -%>" + }, +<% } -%> "dependencies": { +<% if (project.projectType === 'application') { -%> "@loopback/boot": "<%= project.dependencies['@loopback/boot'] -%>", "@loopback/core": "<%= project.dependencies['@loopback/core'] -%>", -<% if (project.projectType === 'application') { -%> "@loopback/repository": "<%= project.dependencies['@loopback/repository'] -%>", <% if (project.apiconnect) { -%> "@loopback/apiconnect": "<%= project.dependencies['@loopback/apiconnect'] -%>", @@ -136,6 +141,9 @@ "devDependencies": { "rimraf": "<%= project.dependencies['rimraf'] -%>", "source-map-support": "<%= project.dependencies['source-map-support'] -%>", +<% if (project.projectType === 'extension') { -%> + "@loopback/core": "<%= project.dependencies['@loopback/core'] -%>", +<% } -%> "@loopback/testlab": "<%= project.dependencies['@loopback/testlab'] -%>", <% if (project.mocha) { -%> "@types/mocha": "<%= project.dependencies['@types/mocha'] -%>",