diff --git a/.github/workflows/pr-build.yml b/.github/workflows/pr-build.yml index 9bef2e3a3..f41967197 100644 --- a/.github/workflows/pr-build.yml +++ b/.github/workflows/pr-build.yml @@ -1,36 +1,47 @@ -name: Build PRs for LoopBack.io site +# Inspired by: https://github.com/actions/starter-workflows/blob/1035244887e26fbbd4f1017d919fb5995cc521c4/pages/jekyll.yml +name: Build LoopBack.io website on: pull_request: branches: - gh-pages - workflow_dispatch: - branches: - - gh-pages - + +permissions: {} + jobs: build: runs-on: ubuntu-latest steps: - - name: Checkout 🛎️ + - uses: step-security/harden-runner@bf7454d06d71f1098171f2acdf0cd4708d7b5920 # v2.20.0 + with: + disable-sudo-and-containers: true + egress-policy: block + allowed-endpoints: > + github.com:443 + index.rubygems.org:443 + raw.githubusercontent.com:443 + registry.npmjs.org:443 + rubygems.org:443 + + - name: Checkout uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 with: persist-credentials: false - - name: Use Node.js 22 + - name: Use Node.js uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0 with: node-version: 24.18.0 - - name: Set up Ruby 3.2 + - name: Set up Ruby uses: ruby/setup-ruby@d45b1a4e94b71acab930e56e79c6aa188764e7f9 # v1.316.0 with: - ruby-version: 3.4.10 + bundler-cache: true - - name: Install and Build 🔧 + - name: Install and Build run: | - bundle install - npm install + npm ci --ignore-scripts + npm run postinstall npm ls @loopback/docs 2>/dev/null || true npm run build diff --git a/.github/workflows/site-build.yml b/.github/workflows/site-build.yml index b7545433d..3871b370e 100644 --- a/.github/workflows/site-build.yml +++ b/.github/workflows/site-build.yml @@ -1,43 +1,108 @@ -name: Build and Deploy LoopBack.io site +# Inspired by: https://github.com/actions/starter-workflows/blob/1035244887e26fbbd4f1017d919fb5995cc521c4/pages/jekyll.yml +name: Build and Deploy LoopBack.io website on: push: branches: - gh-pages - workflow_dispatch: - branches: - - gh-pages + workflow_dispatch: {} + +permissions: {} + +# Allow only one concurrent deployment, skipping runs queued between the run +# in-progress and latest queued. +# However, do NOT cancel in-progress runs as we want to allow these production +# deployments to complete. +concurrency: + group: "pages" + cancel-in-progress: false jobs: build: runs-on: ubuntu-latest + permissions: + contents: write + steps: - - name: Checkout 🛎️ - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 + - uses: step-security/harden-runner@bf7454d06d71f1098171f2acdf0cd4708d7b5920 # v2.20.0 with: - persist-credentials: false + disable-sudo-and-containers: true + egress-policy: block + allowed-endpoints: > + api.github.com:443 + github.com:443 + index.rubygems.org:443 + raw.githubusercontent.com:443 + registry.npmjs.org:443 + rubygems.org:443 + + - name: Checkout + uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 - - name: Use Node.js 22 + - name: Use Node.js uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0 with: node-version: 24.18.0 - - name: Set up Ruby 3.2 + - name: Set up Ruby uses: ruby/setup-ruby@d45b1a4e94b71acab930e56e79c6aa188764e7f9 # v1.316.0 with: - ruby-version: 3.4.10 + bundler-cache: true + + # Used merely to expose the GitHub Pages base path for Jekyll to use. + # The website doesn't fully-support custom base paths, but this should + # ease development on forks. + - name: Setup Pages + id: pages + uses: actions/configure-pages@45bfe0192ca1faeb007ade9deae92b16b8254a0d # v6.0.0 - - name: Install and Build 🔧 + - name: Install and Build run: | - bundle install - npm install + npm ci --ignore-scripts + npm run postinstall npm ls @loopback/docs 2>/dev/null || true - npm run build - - - name: Deploy 🚀 - uses: JamesIves/github-pages-deploy-action@d92aa235d04922e8f08b40ce78cc5442fcfbfa2f # v4.8.0 + npm run build -- --baseurl "${{ steps.pages.outputs.base_path }}" + + # Convenience wrapper around `actions/upload-artifact` + # Automatically uploads the './_site' directory as the `github-pages` + # artifact. + - name: Upload Artifact + uses: actions/upload-pages-artifact@fc324d3547104276b827a68afc52ff2a11cc49c9 # v5.0.0 + + - name: Push Changes + run: | + git add --all + if [ "$(git status -s)"! = "" ]; then + echo "Vendored assets updated. Pushing changes..." + git commit -sm 'chore: update vendored assets' + git push + else + echo "Vendored assets unchanged. Skipping push." + fi + deploy: + permissions: + pages: write + id-token: write + + environment: + name: github-pages + url: ${{ steps.deployment.outputs.page_url }} + + runs-on: ubuntu-latest + + needs: [build] + + steps: + - uses: step-security/harden-runner@bf7454d06d71f1098171f2acdf0cd4708d7b5920 # v2.20.0 with: - ssh-key: ${{ secrets.DEPLOY_KEY }} - branch: gh-pages - folder: . + egress-policy: audit + allowed-endpoints: > + api.github.com:443 + github.com:443 + + # Convenience wrapper around `actions/download-artifact` and + # `actions/upload-pages-artifact`. + - name: Deploy to Github Pages + id: deployment + uses: actions/deploy-pages@cd2ce8fcbc39b97be8ca5fce6e763baed58fa128 # v5.0.0 diff --git a/.ruby-version b/.ruby-version new file mode 100644 index 000000000..8b2dd6c36 --- /dev/null +++ b/.ruby-version @@ -0,0 +1 @@ +4.0.5 \ No newline at end of file diff --git a/Gemfile b/Gemfile index 7e565875b..011249190 100644 --- a/Gemfile +++ b/Gemfile @@ -1,5 +1,17 @@ source "https://rubygems.org" -gem "github-pages", group: :jekyll_plugins +gem "jekyll", "~> 3.10" +# Jekyll Ruby 3.0 compatibility gem "webrick", "~> 1.9", ">= 1.9.2" + +# Jekyll Ruby 4.0 compatibility +gem "logger", "~> 1.7" +gem "base64", "~> 0.3.0" +gem "bigdecimal", "~> 4.1" + +# Jekyll plugins +gem "jekyll-sitemap", "~> 1.4" +gem "jekyll-redirect-from", "~> 0.16.0" +gem "jekyll-relative-links", "~> 0.7.0" +gem "kramdown-parser-gfm", "~> 1.1" diff --git a/Gemfile.lock b/Gemfile.lock index e152e3f0d..d8427c11c 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,109 +1,19 @@ GEM remote: https://rubygems.org/ specs: - activesupport (8.1.1) - base64 - bigdecimal - concurrent-ruby (~> 1.0, >= 1.3.1) - connection_pool (>= 2.2.5) - drb - i18n (>= 1.6, < 2) - json - logger (>= 1.4.2) - minitest (>= 5.1) - securerandom (>= 0.3) - tzinfo (~> 2.0, >= 2.0.5) - uri (>= 0.13.1) addressable (2.8.8) public_suffix (>= 2.0.2, < 8.0) base64 (0.3.0) - bigdecimal (3.3.1) - coffee-script (2.4.1) - coffee-script-source - execjs - coffee-script-source (1.12.2) + bigdecimal (4.1.2) colorator (1.1.0) - commonmarker (0.23.12) concurrent-ruby (1.3.6) - connection_pool (3.0.2) csv (3.3.5) - dnsruby (1.73.1) - base64 (>= 0.2) - logger (~> 1.6) - simpleidn (~> 0.2.1) - drb (2.2.3) em-websocket (0.5.3) eventmachine (>= 0.12.9) http_parser.rb (~> 0) - ethon (0.18.0) - ffi (>= 1.15.0) - logger eventmachine (1.2.7) - execjs (2.10.0) - faraday (2.14.0) - faraday-net_http (>= 2.0, < 3.5) - json - logger - faraday-net_http (3.4.2) - net-http (~> 0.5) ffi (1.17.2) forwardable-extended (2.6.0) - gemoji (4.1.0) - github-pages (232) - github-pages-health-check (= 1.18.2) - jekyll (= 3.10.0) - jekyll-avatar (= 0.8.0) - jekyll-coffeescript (= 1.2.2) - jekyll-commonmark-ghpages (= 0.5.1) - jekyll-default-layout (= 0.1.5) - jekyll-feed (= 0.17.0) - jekyll-gist (= 1.5.0) - jekyll-github-metadata (= 2.16.1) - jekyll-include-cache (= 0.2.1) - jekyll-mentions (= 1.6.0) - jekyll-optional-front-matter (= 0.3.2) - jekyll-paginate (= 1.1.0) - jekyll-readme-index (= 0.3.0) - jekyll-redirect-from (= 0.16.0) - jekyll-relative-links (= 0.6.1) - jekyll-remote-theme (= 0.4.3) - jekyll-sass-converter (= 1.5.2) - jekyll-seo-tag (= 2.8.0) - jekyll-sitemap (= 1.4.0) - jekyll-swiss (= 1.0.0) - jekyll-theme-architect (= 0.2.0) - jekyll-theme-cayman (= 0.2.0) - jekyll-theme-dinky (= 0.2.0) - jekyll-theme-hacker (= 0.2.0) - jekyll-theme-leap-day (= 0.2.0) - jekyll-theme-merlot (= 0.2.0) - jekyll-theme-midnight (= 0.2.0) - jekyll-theme-minimal (= 0.2.0) - jekyll-theme-modernist (= 0.2.0) - jekyll-theme-primer (= 0.6.0) - jekyll-theme-slate (= 0.2.0) - jekyll-theme-tactile (= 0.2.0) - jekyll-theme-time-machine (= 0.2.0) - jekyll-titles-from-headings (= 0.5.3) - jemoji (= 0.13.0) - kramdown (= 2.4.0) - kramdown-parser-gfm (= 1.1.0) - liquid (= 4.0.4) - mercenary (~> 0.3) - minima (= 2.5.1) - nokogiri (>= 1.16.2, < 2.0) - rouge (= 3.30.0) - terminal-table (~> 1.4) - webrick (~> 1.8) - github-pages-health-check (1.18.2) - addressable (~> 2.3) - dnsruby (~> 1.60) - octokit (>= 4, < 8) - public_suffix (>= 3.0, < 6.0) - typhoeus (~> 1.3) - html-pipeline (2.14.3) - activesupport (>= 2) - nokogiri (>= 1.4) http_parser.rb (0.8.0) i18n (1.14.7) concurrent-ruby (~> 1.0) @@ -122,102 +32,16 @@ GEM rouge (>= 1.7, < 4) safe_yaml (~> 1.0) webrick (>= 1.0) - jekyll-avatar (0.8.0) - jekyll (>= 3.0, < 5.0) - jekyll-coffeescript (1.2.2) - coffee-script (~> 2.2) - coffee-script-source (~> 1.12) - jekyll-commonmark (1.4.0) - commonmarker (~> 0.22) - jekyll-commonmark-ghpages (0.5.1) - commonmarker (>= 0.23.7, < 1.1.0) - jekyll (>= 3.9, < 4.0) - jekyll-commonmark (~> 1.4.0) - rouge (>= 2.0, < 5.0) - jekyll-default-layout (0.1.5) - jekyll (>= 3.0, < 5.0) - jekyll-feed (0.17.0) - jekyll (>= 3.7, < 5.0) - jekyll-gist (1.5.0) - octokit (~> 4.2) - jekyll-github-metadata (2.16.1) - jekyll (>= 3.4, < 5.0) - octokit (>= 4, < 7, != 4.4.0) - jekyll-include-cache (0.2.1) - jekyll (>= 3.7, < 5.0) - jekyll-mentions (1.6.0) - html-pipeline (~> 2.3) - jekyll (>= 3.7, < 5.0) - jekyll-optional-front-matter (0.3.2) - jekyll (>= 3.0, < 5.0) - jekyll-paginate (1.1.0) - jekyll-readme-index (0.3.0) - jekyll (>= 3.0, < 5.0) jekyll-redirect-from (0.16.0) jekyll (>= 3.3, < 5.0) - jekyll-relative-links (0.6.1) + jekyll-relative-links (0.7.0) jekyll (>= 3.3, < 5.0) - jekyll-remote-theme (0.4.3) - addressable (~> 2.0) - jekyll (>= 3.5, < 5.0) - jekyll-sass-converter (>= 1.0, <= 3.0.0, != 2.0.0) - rubyzip (>= 1.3.0, < 3.0) jekyll-sass-converter (1.5.2) sass (~> 3.4) - jekyll-seo-tag (2.8.0) - jekyll (>= 3.8, < 5.0) jekyll-sitemap (1.4.0) jekyll (>= 3.7, < 5.0) - jekyll-swiss (1.0.0) - jekyll-theme-architect (0.2.0) - jekyll (> 3.5, < 5.0) - jekyll-seo-tag (~> 2.0) - jekyll-theme-cayman (0.2.0) - jekyll (> 3.5, < 5.0) - jekyll-seo-tag (~> 2.0) - jekyll-theme-dinky (0.2.0) - jekyll (> 3.5, < 5.0) - jekyll-seo-tag (~> 2.0) - jekyll-theme-hacker (0.2.0) - jekyll (> 3.5, < 5.0) - jekyll-seo-tag (~> 2.0) - jekyll-theme-leap-day (0.2.0) - jekyll (> 3.5, < 5.0) - jekyll-seo-tag (~> 2.0) - jekyll-theme-merlot (0.2.0) - jekyll (> 3.5, < 5.0) - jekyll-seo-tag (~> 2.0) - jekyll-theme-midnight (0.2.0) - jekyll (> 3.5, < 5.0) - jekyll-seo-tag (~> 2.0) - jekyll-theme-minimal (0.2.0) - jekyll (> 3.5, < 5.0) - jekyll-seo-tag (~> 2.0) - jekyll-theme-modernist (0.2.0) - jekyll (> 3.5, < 5.0) - jekyll-seo-tag (~> 2.0) - jekyll-theme-primer (0.6.0) - jekyll (> 3.5, < 5.0) - jekyll-github-metadata (~> 2.9) - jekyll-seo-tag (~> 2.0) - jekyll-theme-slate (0.2.0) - jekyll (> 3.5, < 5.0) - jekyll-seo-tag (~> 2.0) - jekyll-theme-tactile (0.2.0) - jekyll (> 3.5, < 5.0) - jekyll-seo-tag (~> 2.0) - jekyll-theme-time-machine (0.2.0) - jekyll (> 3.5, < 5.0) - jekyll-seo-tag (~> 2.0) - jekyll-titles-from-headings (0.5.3) - jekyll (>= 3.3, < 5.0) jekyll-watch (2.2.1) listen (~> 3.0) - jemoji (0.13.0) - gemoji (>= 3, < 5) - html-pipeline (~> 2.2) - jekyll (>= 3.0, < 5.0) - json (2.18.0) kramdown (2.4.0) rexml kramdown-parser-gfm (1.1.0) @@ -228,57 +52,35 @@ GEM rb-inotify (~> 0.9, >= 0.9.10) logger (1.7.0) mercenary (0.3.6) - mini_portile2 (2.8.9) - minima (2.5.1) - jekyll (>= 3.5, < 5.0) - jekyll-feed (~> 0.9) - jekyll-seo-tag (~> 2.1) - minitest (5.27.0) - net-http (0.8.0) - uri (>= 0.11.1) - nokogiri (1.18.10) - mini_portile2 (~> 2.8.2) - racc (~> 1.4) - octokit (4.25.1) - faraday (>= 1, < 3) - sawyer (~> 0.9) pathutil (0.16.2) forwardable-extended (~> 2.6) public_suffix (5.1.1) - racc (1.8.1) rb-fsevent (0.11.2) rb-inotify (0.11.1) ffi (~> 1.0) rexml (3.4.4) rouge (3.30.0) - rubyzip (2.4.1) safe_yaml (1.0.5) sass (3.7.4) sass-listen (~> 4.0.0) sass-listen (4.0.0) rb-fsevent (~> 0.9, >= 0.9.4) rb-inotify (~> 0.9, >= 0.9.7) - sawyer (0.9.3) - addressable (>= 2.3.5) - faraday (>= 0.17.3, < 3) - securerandom (0.4.1) - simpleidn (0.2.3) - terminal-table (1.8.0) - unicode-display_width (~> 1.1, >= 1.1.1) - typhoeus (1.4.1) - ethon (>= 0.9.0) - tzinfo (2.0.6) - concurrent-ruby (~> 1.0) - unicode-display_width (1.8.0) - uri (1.1.1) webrick (1.9.2) PLATFORMS ruby DEPENDENCIES - github-pages + base64 (~> 0.3.0) + bigdecimal (~> 4.1) + jekyll (~> 3.10) + jekyll-redirect-from (~> 0.16.0) + jekyll-relative-links (~> 0.7.0) + jekyll-sitemap (~> 1.4) + kramdown-parser-gfm (~> 1.1) + logger (~> 1.7) webrick (~> 1.9, >= 1.9.2) BUNDLED WITH - 2.7.2 + 4.0.3 diff --git a/README.md b/README.md index ccd60f4b7..639ef1610 100644 --- a/README.md +++ b/README.md @@ -1,64 +1,79 @@ # loopback.io -LoopBack community site, http://loopback.io. This website now includes the LoopBack documentation. - -NOTE: The website is served from the `gh-pages` branch. - -This repository is provided under the [MIT License](LICENSE). +LoopBack community site and documentation, hosted on http://loopback.io. ## Setup To preview the website locally: -1. Install [Ruby and Bundler](https://help.github.com/articles/setting-up-your-pages-site-locally-with-jekyll/) if you don't have them already. +1. Install [Ruby and + Bundler](https://help.github.com/articles/setting-up-your-pages-site-locally-with-jekyll/) + if you don't have them already. 2. Clone this repo (you might use the SSH URL instead of HTTPS).: -``` +```sh git clone https://github.com/loopbackio/loopback.io.git ``` 3. `cd` to the repository directory and run the following command: +```sh +cd loopback.io +bundle install ``` -$ cd loopback.io -$ bundle install + +You may run into errors during `bundle install` due to compilation failure of +native gems. One such error is: + +> An error occurred while installing eventmachine (1.2.7), and Bundler cannot +> continue. + +To rectify these errors, install the necessary dependencies that provides the +missing compilers (g++) and devel files (Ruby). For Fedora 44: + +```sh +sudo dnf install gcc-c++ ruby-devel ``` -Bundler will look in the Gemfile for which gems to install. The `github-pages` gem includes the same version of Jekyll and other dependencies as used by GitHub Pages, so that your local setup mirrors GitHub Pages as closely as possible. ## Run and view site locally Run Jekyll using the following command: ``` -$ npm start +npm start ``` Then, load [http://localhost:4001/](http://localhost:4001/) on your browser. -NOTE: The docs part will be at [http://localhost:4001/doc](http://localhost:4001/doc). It's not yet linked from the main "overview" part of the site, but will be once we launch (RSN). ## Formatting -Jekyll uses a variant of Markdown known as [Kramdown](http://kramdown.gettalong.org/quickref.html). +Jekyll uses a variant of Markdown known as +[Kramdown](http://kramdown.gettalong.org/quickref.html). -Jekyll uses the [Liquid template engine](http://liquidmarkup.org/) for templating. +Jekyll uses the [Liquid template engine](http://liquidmarkup.org/) for +templating. -## Incorporating external READMEs -The documentation incorporates README files from a number of LoopBack example repositories. -We use the [get-readmes](https://github.com/strongloop/get-readmes) utility to fetch -the README files directly from GitHub. Here is how to update the READMEs +## Incorporating external READMEs and Blog -1. `npm install` (_first time/setup only_) -2. `npm run fetch-readmes` - -From there, the README markdown files are incorporated into documentation articles -using the standard Jekyll "include" syntax as follows (for example): +The documentation incorporates README files from a number of LoopBack example +repositories, and blog posts from `loopbackio/loopback-blog`. The CI pipeline +will update these files automatically. However, updating these on a +local machine requires a few extra steps: +```sh +npm run fetch-readmes +npm run fetch-blog ``` + +From there, the README markdown files are incorporated into documentation +articles using the standard Jekyll "include" syntax as follows (for example): + +```md --- title: "Angular example app" lang: en @@ -76,60 +91,32 @@ summary: A brief tutorial on creating an Angular client app using the Loopback A ## Incorporating updates from loopback-next -We use a node script `update-lb4-docs` to copy over contents from loopback-next -repository using `@loopback/docs` package. The script is responsible for copying -over the markdown documentation and related tables, as well as the sidebar used -for LoopBack 4 content. The changes are then picked up as part of Travis CI's -builds along with README update scripts and deployed to GitHub Pages once -successful. The `upgrade-swagger-ui.js` script is also run as part of the -builds. If you'd like to make documentation changes for LoopBack 4, please do so -on its own [repository](https://github.com/loopbackio/loopback-next/). +LoopBack 4 docs are managed separately and imported via the `@loopback/docs` +NPM package (stored in: `loopback-next/docs`). These changes are pulled by the +build scripts and overrides any changes made to `pages/en/lb4`. Hence, do not +submit changes for that directory here. Instead, submit a PR to +[`loopback-next`](https://github.com/loopbackio/loopback-next/). -### Linting Readmes - -There is an additional `npm script` that "lints" the readmes for markdown formatting problems. It is currently "experimental", see [this issue](https://github.com/loopbackio/loopback.io/issues/49#issuecomment-253672668) for more info. - -You can run this script thus: +Updating these files are done automatically in the CI pipeline and on dev +machines viaa `postinstall` NPM script hook: -```js -$ npm run lint-readmes +```sh +npm ci # This should be enough to sync LB4 docs +npm run postinstall # Alternatively... ``` -## LoopBack.io Docs Search - -Docs Search is powered by [IBM Watson Discovery](https://www.ibm.com/watson/services/discovery/). - -### How it works - -There are two parts of work to get this working: - -1. The [Discovery service](https://www.ibm.com/watson/services/discovery/) is one of the services provided by [IBM Cloud](https://cloud.ibm.com/). A collection is created with loopback.io as the URL we'd like to sync. - -2. The [IBM Cloud function](https://www.ibm.com/cloud/functions) is used for the search function calling the discovery service and parse the output in the form that the LoopBack web site understands. - -### Front End - -Each documentation page has a search bar the top. The search will redirect the -user to a `/search` page to show the results. The results are retrieved from a -[IBM Cloud Function](https://www.ibm.com/cloud/functions) that acts as a proxy -to protect Watson Discovery credentials. The search bar also contains a hidden -form input that sets the `sidebar` value and Watson Discovery filters content -based on this value to return context aware results. Ex: Searching for the word -`controller` from a LoopBack 4 documentation page will return LoopBack 4 results. -To search all documents you can search from the `/search` page. Community Docs -and Contribution docs are included in all results. - -### Cloud Function +### Linting Readmes -The code for the Cloud function can be found [here](https://github.com/strongloop/loopback.io-search). -It is deployed to the same account and must be edited directly in IBM Cloud -(formerly BlueMix). The repository exists to document code changes and have peer -reviews. Credentials for accessing the Cloud Function can be obtained from Diana Lau OR you can ask them to re-deploy changes. +There is an additional that "lints" the readmes for markdown formatting +problems. It is currently "experimental", see [this +issue](https://github.com/loopbackio/loopback.io/issues/49#issuecomment-253672668) +for more info. -#### Your own version +You can run this script thus: -You can deploy the code on your own IBM Cloud account and upload the URL for -Discovery in [search.html](https://github.com/loopbackio/loopback.io/blob/gh-pages/_layouts/search.html). +```sh +npm run lint-readmes +``` ## Contributing @@ -140,8 +127,14 @@ commit message. **Example** -``` +```sh git commit -s -m "feat: my commit message" ``` -Also see the [Contributing to LoopBack documentation](https://loopback.io/doc/en/contrib/doc-contrib.html) to get you started. +Also see the [Contributing to LoopBack +documentation](https://loopback.io/doc/en/contrib/doc-contrib.html) to get you +started. + +## License + +This repository is provided under the [MIT License](LICENSE). diff --git a/package.json b/package.json index 816f97be0..76beac160 100644 --- a/package.json +++ b/package.json @@ -18,6 +18,7 @@ "engines": { "node": ">=24.18.0" }, + "packageManager": "npm", "repository": { "type": "git", "url": "git+https://github.com/loopbackio/loopback.io.git"