Developing LoopBack

    Before you can start developing LoopBack, you need to install and configure fewdependencies.

    • git: Github’s guide is a goodsource of information.
    • VisualStudio Code

    • Missing your favorite IDE/editor here? We would love to have documentationfor more IDEs/editors! Please send a pull request to add recommended setup foryour tool.Before getting started, it is recommended to configure so that it knowswho you are:

    Please make sure this local email is also added to your so that your commitswill be properly associated with your account and you will be promoted toContributor once your first commit is landed.

    Building the project

    Whenever you pull updates from GitHub or switch between feature branches, makesure to updated installed dependencies in all monorepo packages. The followingcommand will install npm dependencies for all packages and create symbolic linksfor intra-dependencies:

    1. npm ci

    The next step is to compile all packages from TypeScript to JavaScript:

    1. npm run build

    Please note that we are automatically running the build from pretest script,therefore you should not need to run this command as part of your.

    Running tests

    This is the only command you should need while developing LoopBack:

    1. npm test

    It does all you need:

    • Compile TypeScript
    • Run all tests
    • Check code formatting using
    • Lint the code using ESLint

    Coding rules

    • All features and bug fixes must be covered by one or more automated tests.

    • All public methods must be documented with typedoc comments (seeAPI Documentation below).

    • Follow our style guide as documented on loopback.io:.

    We use two tools to keep our codebase healthy:

    • ESLint to statically analyse our source codeand detect common problems.
    • to keep our code always formatted the sameway, avoid style discussions in code reviews, and save everybody’s time anenergy.You can run both linters via the following npm script, just keep in mind thatnpm test is already running them for you.
    1. npm run lint

    Many problems (especially formatting) can be automatically fixed by running thenpm script lint:fix.

    1. npm run lint:fix

    We use npm’spackage-lock feature to speedup our development workflow and CI builds.

    For individual packages within the monorepo, lerna bootstrap calls npm ci ina CI environment or with —ci to install (deep) dependencies as specified inpackage-lock.json file. Otherwise, npm install is run with the correspondingpackage.json.

    Top-level (loopback-next) dependencies are installed either frompackage-lock.json (when you run npm ci), or resolved freshly from the npmregistry (when you run npm install).

    IMPORTANT: Dependencies resolved locally within the monorepo must be excludedfrom package-lock files.

    Updating package locks

    If you ever end up with corrupted or out-of-date package locks, run thefollowing commands to fix the problem:

    1. $ npm run update-package-locks

    Adding dependencies

    Use the following command to add or update dependency dep in a package name:

    For example:

    1. $ npx lerna add --scope @loopback/rest debug

    See for more details.

    NOTE: At the moment, lerna does not update package-lock.json files whenadding a dependency to a scope, seelerna#1989. You have to re-createpackage locks manually, see above.

    Updating dependencies

    To update dependencies to their latest compatible versions:

    1. npm run update-all-deps

    File naming convention

    For consistency, we followAngular’s file naming convention.It helps to derive the usage of files by inspecting the names. Besides theLoopBack 4 codebase, we also follow this naming convention in our generatedartifacts from the CLI tooling: {name}.{artifact-type}.ts

    Examples are:

    1. src/decorators/authenticate.decorator.ts
    2. src/boot.component.ts

    In addition, files under test folder are categorized according to the type oftests (unit, acceptance and integration), with the convention{name}.{test-type}.ts.

    Examples are:

    1. src/__tests__/acceptance/application.acceptance.ts
    2. src/__tests__/unit/application.unit.ts

    API Documentation

    We use@loopback/tsdocsto generate API documentation for all our packages. This documentation isgenerated when publishing new releases to npmjs.org and it’s picked up by.

    You can preview API docs locally by running npm run tsdocs and openapidocs/index.md.

    Commit message guidelines

    A good commit message should describe what changed and why.

    Our commit messages are formatted according toConventional Commits, we use to verify and enforce thisconvention. These rules lead to more readable messages that are easy to followwhen looking through the project history. But also, we use the git commitmessages to generate change logs when publishing new versions.

    Commit Message Format

    Each commit message consists of a header, a body and a footer. Theheader has a special format that includes a type, an optional scope anda subject:

    1. <type>(<scope>): <subject>
    2. <BLANK LINE>
    3. <body>
    4. <BLANK LINE>
    5. <footer>

    type

    The type must be one of the following:

    • feat: A new feature
    • fix: A bug fix
    • docs: Documentation only changes
    • style: Changes that do not affect the meaning of the code (white-space,formatting, missing semi-colons, etc)
    • refactor: A code change that neither fixes a bug nor adds a feature
    • perf: A code change that improves performance
    • test: Adding missing or correcting existing tests
    • build: Changes that affect the build system or external dependencies
    • ci: Changes to our CI configuration files and scripts
    • chore: Changes to the auxiliary tools and libraries such as documentationgeneration
    • revert: Reverts a previous commit

    scope

    The scope must be a list of one or more packages contained in this monorepo.Each scope name must match a directory name in,e.g. core or context.

    Note: If multiple packages are affected by a pull request, don’t list thescopes as the commit linter currently only supports only one scope being listedat most. The CHANGELOG for each affected package will still show the commit.Commit linter will be updated to allow listing of multiple affected scopes, seeissue #581

    subject

    The subject contains succinct description of the change:

    • use the imperative, present tense: “change” not “changed” nor “changes”
    • don’t capitalize first letter
    • no dot (.) at the end

    body

    The body provides more details, it should include the motivation for thechange and contrast this with previous behavior.

    Just as in the subject, use the imperative, present tense: “change” not“changed” nor “changes”a

    Paragraphs or bullet points are ok (must not exceed 100 characters per line).Typically a hyphen or asterisk is used for the bullet, followed by a singlespace, with blank lines in between.

    The footer should contain any information about Breaking Changes introducedby this commit.

    This section must start with the upper case text BREAKING CHANGE followed by acolon (:) and a space (``). A description must be provided, describing whathas changed and how to migrate from older versions.

    This repository has commitizen supportenabled. Commitizen can help you generate your commit messages automatically.You must install it globally as follows:

    1. npm i -g commitizen

    And to use it, simply call git cz instead of git commit. The tool will helpyou generate a commit message that follows the above guidelines.

    LoopBack is following . Any changethat’s not fully backward compatible with previous versions has to increase themajor version number, e.g. 1.4.2 -> 2.0.0.

    In general, we try to avoid breaking backward compatibility too often and striveto limit the frequency of major releases to about once or twice a year.

    • Breaking changes make it difficult for our users to always stay at the latestversion of the framework.
    • Every additional major version we have to support adds extra maintenanceoverhead.
    • In ourLong Term Support policy,we are committing to support every major module version for at least 12 monthsafter it entered LTS mode and also support it for the entire LTS lifetime ofthe connected Node.js major version. If we release major versions too often,we can end up with a long list of versions we have to keep supporting for longtime.Whenever possible, consider implementing a feature flag that allows users todecide when to migrate to the new behavior. Make this flag disabled by defaultto preserve backward compatibility.

    However, we do recognize that often a breaking change is the most sensible thingto do. When that time comes:

    • Describe incompatibilites for release notes
    • Look for more breaking changes to include in the release
    • Update list of supported versions

    Describe incompatibilites for release notes

    In the pull request introducing the breaking change, provide a descriptivefooter explaining the breaking change to our users. Thiscontent will be used by release tooling to compile comprehensive release notes.

    Put yourself in the shoes of module users and try to answer the followingquestions:

    • What does this change means for my project? What is going to change?

    • How can I migrate my project to the new major version? What steps do I need tomake?

    Look for more breaking changes

    Look for other features or fixes that require a breaking change. Considergrouping multiple backward incompatible changes into a single semver majorrelease.

    Few examples of changes that are usually easy to make:

    • Change the default value of a feature flag from “false” (backward-compatiblebehavior) to “true” (the new behavior).

    • Deprecate a compatibility feature flag that’s already enabled by default.

    • Remove a deprecated feature flag.

    • Drop support for a major version of Node.js that has already reached it’s endof life or that will reach it soon (in the next 4-8 weeks).

    Update list of supported versions

    Make sure the package’s README has an up-to-date section about the supportedversions. Read ourto understand the rules governing transition between different support levels.

    • There should be at most one version in Active LTS mode. This version moves toMaintenance LTS.

    • The new major version is becoming Current.

    It is important to make these updates before publishing the new major version,so that new content is included on the package page provided bynpmjs.com.

    Releasing new versions

    When we are ready to tag and publish a release, run the following commands:

    The release script will automatically perform the tasks for all packages:

    • Clean up node_modules
    • Install/link dependencies
    • Transpile TypeScript files into JavaScript
    • Run mocha tests
    • Check lint (eslint and prettier) issuesIf all steps are successful, it prompts you to publish packages into npmrepository.

    Adding a new package

    Create a new package

    To add a new package, create a folder inpackagesas the root directory of your module. For example,

    1. cd loopback-next/packages
    2. mkdir <a-new-package>

    The package follows the node/npm module layout. You can use npm init orlb4 extension command to scaffold the module, copy/paste from an existingpackage, or manually add files including package.json.

    Make sure you add LICENSE file properly and all source code files have thecorrect copyright header.

    We have some configuration files at the top level (loopback-next/):

    • .gitignore
    • .prettierignore
    • .nycrc.ymlFor consistency across all packages, do not add them at package level unlessspecific customization is needed.

    Make a scoped package public

    By default, npm publishes scoped packages with private access. There are twooptions to make a new scoped package with public access.

    Either add the following section to package.json:

    1. "publishConfig": {
    2. "access": "public"
    3. },

    Or explicitly publish the package with —access=public:

    1. npm publish --access=public

    Register the new package

    Please register the new package in the following files:

    • Update - insert a new table row to describe thenew package, please keep the rows sorted by package name.
    • Update Reserved-binding-keys.md - add a link tothe apidocs on Binding Keys if the new package has any.
    • Update -add a new entry listing the primary maintainers (owners) of the new package.

    Upgrading TypeScript/eslint

    In order to support eslint extensions with a peer dependency on eslint, we haveto specify typescript and eslint dependency in multiple places in ourmonorepo.

    Steps to upgrade typescript or eslint to a newer version:

    • Update the dependencies in @loopback/build, this is the source of truth forthe rest of the monorepo.
    1. $ (cd packages/build && npm update typescript eslint)
    • Propagate the change to other places to keep everything consistent.
    1. $ node bin/sync-dev-deps

    When making changes to project infrastructure, e.g. modifying tsc or eslintconfiguration, it’s important to verify that all usage scenarios keep working.

    Verify TypeScript setup

    • Open any existing TypeScript file, e.g. packages/core/src/index.ts

    • Add a small bit of code to break TypeScript’s type checks, for example:

    1. const foo: number = 'bar';
    • Run npm test

    • Verify that the build failed and the compiler error message shows a pathrelative to monorepo root, e.g. packages/src/index.ts.

    • Test integration with supported IDEs:

    Verify ESLint setup

    • Open any existing TypeScript file, e.g. packages/src/index.ts

    • Introduce two kinds linting problems - one that does and another that doesnot require type information to be detected. For example, you can add thefollowing line at the end of the opened index.ts:

    • Run npm test

    • Verify that the build failed and both linting problems are reported:

    1. ERROR: /Users/(...)/packages/core/src/index.ts[16, 7]: 'foo' is declared but its value is never read.
    2. ERROR: /Users/(...)/packages/core/src/index.ts[16, 12]: Type declaration of 'any' loses type-safety. Consider replacing it with a more precise type.
    • Test integration with supported IDEs:

    In the monorepo,TypeScript is set up in two places:

    • When using VS Code, the TypeScript engine views loopback-next as a singlebig project.

    This enables the “refactor - rename” command to change all places using therenamed symbol, and also makes “go to definition” command jump to .ts filescontaining the original source code. Otherwise “refactor - rename” workswithin the same package only and “go to definition” jumps to .d.ts files.

    • When building the monorepo, we need to build the packages individually, sothat one dist directory is created for each package.

    This is why we have two sets of tsconfig files:

    • At monorepo root, there is tsconfig.json used by VS Code.
    • Inside each package, there is tsconfig.build.json used by npm run buildcommand.

    Renovate bot

    In loopback-next, we use package-lock files to speed up npm install times and to keep our lock files up to date.

    The bot is configured to maintain a special issue calledUpdate Dependencies (Renovate Bot) where it lists all pull requests inprogress and in queue:

    • loopback4-example-shopping#94Pull requests opened by RenovateBot can be merged by pressing GitHub’s big greenbutton once all checks are green (all CI builds finished).