├── src ├── services │ └── index.ts ├── __tests__ │ ├── unit │ │ ├── README.md │ │ └── helmet-action.provider.unit.ts │ ├── acceptance │ │ └── README.md │ └── integration │ │ └── README.md ├── providers │ ├── index.ts │ ├── helmet-action.provider.ts │ └── README.md ├── index.ts ├── repositories │ └── README.md ├── controllers │ └── README.md ├── keys.ts ├── component.ts ├── release_notes │ ├── mymarkdown.ejs │ ├── release-notes.js │ └── post-processing.js ├── decorators │ └── README.md └── mixins │ └── README.md ├── .npmrc ├── .prettierignore ├── index.d.ts ├── index.ts ├── index.js ├── .husky ├── pre-commit ├── commit-msg └── prepare-commit-msg ├── .yo-rc.json ├── .mocharc.json ├── mkdocs.yml ├── .eslintignore ├── .prettierrc ├── .eslintrc.js ├── tsconfig.json ├── trivy.yml ├── commitlint.config.js ├── .github ├── ISSUE_TEMPLATE │ ├── bug_report.md │ └── feature_request.md ├── workflows │ ├── main.yaml │ ├── trivy.yaml │ ├── release.yaml │ └── sync-docs.yaml ├── pull_request_template.md ├── stale.yml ├── CONTRIBUTING.md └── CODE_OF_CONDUCT.md ├── catalog-info.yaml ├── .vscode ├── settings.json └── tasks.json ├── LICENSE ├── .gitignore ├── DEVELOPING.md ├── .cz-config.js ├── package.json ├── README.md ├── docs └── README.md └── CHANGELOG.md /src/services/index.ts: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.npmrc: -------------------------------------------------------------------------------- 1 | package-lock=true 2 | -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | dist 2 | *.json 3 | -------------------------------------------------------------------------------- /index.d.ts: -------------------------------------------------------------------------------- 1 | export * from './dist'; 2 | -------------------------------------------------------------------------------- /index.ts: -------------------------------------------------------------------------------- 1 | export * from './src'; 2 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | module.exports = require('./dist'); 2 | -------------------------------------------------------------------------------- /src/__tests__/unit/README.md: -------------------------------------------------------------------------------- 1 | # Unit tests 2 | -------------------------------------------------------------------------------- /src/__tests__/acceptance/README.md: -------------------------------------------------------------------------------- 1 | # Acceptance tests 2 | -------------------------------------------------------------------------------- /src/__tests__/integration/README.md: -------------------------------------------------------------------------------- 1 | # Integration tests 2 | -------------------------------------------------------------------------------- /src/providers/index.ts: -------------------------------------------------------------------------------- 1 | export * from './helmet-action.provider'; 2 | -------------------------------------------------------------------------------- /.husky/pre-commit: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | . "$(dirname "$0")/_/husky.sh" 3 | 4 | npm test 5 | -------------------------------------------------------------------------------- /.yo-rc.json: -------------------------------------------------------------------------------- 1 | { 2 | "@loopback/cli": { 3 | "version": "1.30.1" 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /.mocharc.json: -------------------------------------------------------------------------------- 1 | { 2 | "recursive": true, 3 | "require": "source-map-support/register" 4 | } 5 | -------------------------------------------------------------------------------- /src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './component'; 2 | export * from './keys'; 3 | export * from './providers'; 4 | -------------------------------------------------------------------------------- /.husky/commit-msg: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | . "$(dirname "$0")/_/husky.sh" 3 | 4 | npx --no-install commitlint --edit 5 | -------------------------------------------------------------------------------- /.husky/prepare-commit-msg: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | . "$(dirname "$0")/_/husky.sh" 3 | 4 | exec < /dev/tty && npx cz --hook || true 5 | -------------------------------------------------------------------------------- /mkdocs.yml: -------------------------------------------------------------------------------- 1 | site_name: loopback4-helmet 2 | site_description: loopback4-helmet 3 | 4 | 5 | plugins: 6 | - techdocs-core 7 | -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | dist/ 3 | coverage/ 4 | 5 | index.* 6 | .eslintrc.js 7 | .cz-config.js 8 | commitlint.config.js 9 | -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "bracketSpacing": false, 3 | "singleQuote": true, 4 | "printWidth": 80, 5 | "trailingComma": "all" 6 | } 7 | -------------------------------------------------------------------------------- /.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | extends: '@loopback/eslint-config', 3 | parserOptions: { 4 | project: ['./tsconfig.json'], 5 | }, 6 | }; 7 | -------------------------------------------------------------------------------- /src/repositories/README.md: -------------------------------------------------------------------------------- 1 | # Repositories 2 | 3 | This directory contains code for repositories provided by this extension. 4 | 5 | For more information, see . 6 | -------------------------------------------------------------------------------- /src/controllers/README.md: -------------------------------------------------------------------------------- 1 | # Controllers 2 | 3 | This directory contains source files for the controllers exported by this 4 | extension. 5 | 6 | For more information, see . 7 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json.schemastore.org/tsconfig", 3 | "extends": "@loopback/build/config/tsconfig.common.json", 4 | "compilerOptions": { 5 | "outDir": "dist", 6 | "rootDir": "src" 7 | }, 8 | "include": ["src"] 9 | } 10 | -------------------------------------------------------------------------------- /trivy.yml: -------------------------------------------------------------------------------- 1 | format: table 2 | exit-code: 1 3 | severity: 4 | - HIGH 5 | - CRITICAL 6 | skip-files: 7 | - db.env 8 | security-checks: 9 | - vuln 10 | - secret 11 | - license 12 | vulnerability: 13 | type: 14 | - os 15 | - library 16 | ignore-unfixed: true 17 | -------------------------------------------------------------------------------- /commitlint.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | extends: ['@commitlint/config-conventional'], 3 | rules: { 4 | 'header-max-length': [2, 'always', 100], 5 | 'body-leading-blank': [2, 'always'], 6 | 'footer-leading-blank': [0, 'always'], 7 | 'references-empty': [2, 'never'], 8 | 'body-empty': [2, 'never'], 9 | }, 10 | parserPreset: { 11 | parserOpts: { 12 | issuePrefixes: ['GH-'], 13 | }, 14 | }, 15 | }; 16 | -------------------------------------------------------------------------------- /src/keys.ts: -------------------------------------------------------------------------------- 1 | import {BindingKey} from '@loopback/core'; 2 | import {HelmetAction} from './providers/helmet-action.provider'; 3 | import {HelmetOptions} from 'helmet'; 4 | 5 | export namespace HelmetSecurityBindings { 6 | export const HELMET_SECURITY_ACTION = BindingKey.create( 7 | 'sf.security.helmet.actions', 8 | ); 9 | 10 | export const CONFIG = BindingKey.create( 11 | 'sf.security.helmet.config', 12 | ); 13 | } 14 | -------------------------------------------------------------------------------- /src/component.ts: -------------------------------------------------------------------------------- 1 | import {Component, ProviderMap, Binding} from '@loopback/core'; 2 | import {HelmetSecurityBindings} from './keys'; 3 | import {HelmetActionProvider} from './providers/helmet-action.provider'; 4 | 5 | export class Loopback4HelmetComponent implements Component { 6 | constructor() { 7 | this.providers = { 8 | [HelmetSecurityBindings.HELMET_SECURITY_ACTION.key]: HelmetActionProvider, 9 | }; 10 | this.bindings.push( 11 | Binding.bind(HelmetSecurityBindings.CONFIG.key).to(null), 12 | ); 13 | } 14 | 15 | providers?: ProviderMap; 16 | bindings: Binding[] = []; 17 | } 18 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Describe the bug** 11 | A clear and concise description of what the bug is. 12 | 13 | **To Reproduce** 14 | Steps to reproduce the behavior: 15 | 1. Go to '...' 16 | 2. Click on '....' 17 | 3. Scroll down to '....' 18 | 4. See error 19 | 20 | **Expected behavior** 21 | A clear and concise description of what you expected to happen. 22 | 23 | **Screenshots** 24 | If applicable, add screenshots to help explain your problem. 25 | 26 | **Additional context** 27 | Add any other context about the problem here. 28 | -------------------------------------------------------------------------------- /catalog-info.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: backstage.io/v1alpha1 2 | kind: Component 3 | metadata: 4 | name: loopback4-helmet 5 | annotations: 6 | github.com/project-slug: sourcefuse/loopback4-helmet 7 | backstage.io/techdocs-ref: dir:. 8 | namespace: arc 9 | description: LoopBack 4 extension for helmetjs integration. 10 | tags: 11 | - helmetjs 12 | - loopback 13 | - extension 14 | links: 15 | - url: https://npmjs.com/package/loopback4-helmet 16 | title: NPM Package 17 | - url: https://loopback.io/doc/en/lb4/Extending-LoopBack-4.html#overview 18 | title: Extending LoopBack 19 | spec: 20 | type: component 21 | lifecycle: production 22 | owner: sourcefuse 23 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Is your feature request related to a problem? Please describe.** 11 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] 12 | 13 | **Describe the solution you'd like** 14 | A clear and concise description of what you want to happen. 15 | 16 | **Describe alternatives you've considered** 17 | A clear and concise description of any alternative solutions or features you've considered. 18 | 19 | **Additional context** 20 | Add any other context or screenshots about the feature request here. 21 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "editor.rulers": [80], 3 | "editor.tabCompletion": "on", 4 | "editor.tabSize": 2, 5 | "editor.trimAutoWhitespace": true, 6 | "editor.formatOnSave": true, 7 | 8 | "files.exclude": { 9 | "**/.DS_Store": true, 10 | "**/.git": true, 11 | "**/.hg": true, 12 | "**/.svn": true, 13 | "**/CVS": true, 14 | "dist": true, 15 | }, 16 | "files.insertFinalNewline": true, 17 | "files.trimTrailingWhitespace": true, 18 | 19 | "typescript.tsdk": "./node_modules/typescript/lib", 20 | "eslint.run": "onSave", 21 | "eslint.nodePath": "./node_modules", 22 | "eslint.validate": [ 23 | "javascript", 24 | "typescript" 25 | ], 26 | "editor.codeActionsOnSave": { 27 | "source.fixAll.eslint": true 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /.github/workflows/main.yaml: -------------------------------------------------------------------------------- 1 | name: CI 2 | 3 | on: 4 | push: 5 | branches: [master] 6 | pull_request: 7 | branches: [master] 8 | 9 | jobs: 10 | node_matrix_tests: 11 | runs-on: ubuntu-latest 12 | strategy: 13 | matrix: 14 | node-version: [20, 22, 24] 15 | steps: 16 | - uses: actions/checkout@v3 17 | - uses: actions/setup-node@v3 18 | with: 19 | node-version: ${{ matrix.node-version }} 20 | - name: Install Dependencies 21 | run: npm ci 22 | - name: Run Test Cases 23 | run: npm run test 24 | 25 | npm_test: 26 | runs-on: ubuntu-latest 27 | needs: node_matrix_tests 28 | if: success() 29 | steps: 30 | - name: Final status 31 | run: echo "✅ All tests passed for Node.js 20, 22, and 24" 32 | -------------------------------------------------------------------------------- /.vscode/tasks.json: -------------------------------------------------------------------------------- 1 | { 2 | // See https://go.microsoft.com/fwlink/?LinkId=733558 3 | // for the documentation about the tasks.json format 4 | "version": "2.0.0", 5 | "tasks": [ 6 | { 7 | "label": "Watch and Compile Project", 8 | "type": "shell", 9 | "command": "npm", 10 | "args": ["--silent", "run", "build:watch"], 11 | "group": { 12 | "kind": "build", 13 | "isDefault": true 14 | }, 15 | "problemMatcher": "$tsc-watch" 16 | }, 17 | { 18 | "label": "Build, Test and Lint", 19 | "type": "shell", 20 | "command": "npm", 21 | "args": ["--silent", "run", "test:dev"], 22 | "group": { 23 | "kind": "test", 24 | "isDefault": true 25 | }, 26 | "problemMatcher": ["$tsc", "$eslint-compact", "$eslint-stylish"] 27 | } 28 | ] 29 | } 30 | -------------------------------------------------------------------------------- /src/__tests__/unit/helmet-action.provider.unit.ts: -------------------------------------------------------------------------------- 1 | import {HelmetOptions} from 'helmet'; 2 | import {HelmetActionProvider} from '../../providers'; 3 | import {expect, stubExpressContext} from '@loopback/testlab'; 4 | 5 | describe('Helmet Service', () => { 6 | describe('Helmet Provider', () => { 7 | it('returns a promise after success', async () => { 8 | const config: HelmetOptions = { 9 | referrerPolicy: { 10 | policy: 'same-origin', 11 | }, 12 | contentSecurityPolicy: { 13 | directives: { 14 | frameSrc: ["'self'"], 15 | }, 16 | }, 17 | }; 18 | const context = stubExpressContext({ 19 | url: '/', 20 | method: 'GET', 21 | payload: {key: 'value'}, 22 | }); 23 | const handler = new HelmetActionProvider(config).value(); 24 | const result = handler(context.request, context.response); 25 | await expect(result).to.be.fulfilled(); 26 | }); 27 | }); 28 | }); 29 | -------------------------------------------------------------------------------- /src/release_notes/mymarkdown.ejs: -------------------------------------------------------------------------------- 1 | ## Release [<%= range.split('..')[1] %>](https://github.com/sourcefuse/loopback4-helmet/compare/<%= range %>) <%= new Date().toLocaleDateString('en-us', {year:"numeric", month:"long", day:"numeric"}) 2 | ;%> 3 | Welcome to the <%= new Date().toLocaleDateString('en-us', {year:"numeric", month:"long", day:"numeric"});%> release of loopback4-helmet. There are many updates in this version that we hope you will like, the key highlights include: 4 | <% commits.forEach(function (commit) { %> 5 | - [<%= commit.issueTitle %>](https://github.com/sourcefuse/loopback4-helmet/issues/<%= commit.issueno %>) :- [<%= commit.title %>](https://github.com/sourcefuse/loopback4-helmet/commit/<%= commit.sha1%>) was commited on <%= commit.committerDate %> by [<%= commit.authorName %>](mailto:<%= commit.authorEmail %>) 6 | <% commit.messageLines.forEach(function (message) { %> 7 | - <%= message %> 8 | <% }) %> 9 | <% }) %> 10 | Clink on the above links to understand the changes in detail. 11 | ___ 12 | 13 | -------------------------------------------------------------------------------- /src/decorators/README.md: -------------------------------------------------------------------------------- 1 | # Decorators 2 | 3 | ## Overview 4 | 5 | Decorators provide annotations for class methods and arguments. Decorators use 6 | the form `@decorator` where `decorator` is the name of the function that will be 7 | called at runtime. 8 | 9 | ## Basic Usage 10 | 11 | ### txIdFromHeader 12 | 13 | This simple decorator allows you to annotate a `Controller` method argument. The 14 | decorator will annotate the method argument with the value of the header 15 | `X-Transaction-Id` from the request. 16 | 17 | **Example** 18 | 19 | ```ts 20 | class MyController { 21 | @get('/') 22 | getHandler(@txIdFromHeader() txId: string) { 23 | return `Your transaction id is: ${txId}`; 24 | } 25 | } 26 | ``` 27 | 28 | ## Related Resources 29 | 30 | You can check out the following resource to learn more about decorators and how 31 | they are used in LoopBack Next. 32 | 33 | - [TypeScript Handbook: Decorators](https://www.typescriptlang.org/docs/handbook/decorators.html) 34 | - [Decorators in LoopBack](http://loopback.io/doc/en/lb4/Decorators.html) 35 | -------------------------------------------------------------------------------- /src/providers/helmet-action.provider.ts: -------------------------------------------------------------------------------- 1 | import {inject, Provider} from '@loopback/core'; 2 | import {Request, Response} from '@loopback/rest'; 3 | import * as helmet from 'helmet'; 4 | 5 | import {HelmetSecurityBindings} from '../keys'; 6 | 7 | export interface HelmetAction { 8 | (request: Request, response: Response): Promise; 9 | } 10 | 11 | export class HelmetActionProvider implements Provider { 12 | constructor( 13 | @inject(HelmetSecurityBindings.CONFIG, { 14 | optional: true, 15 | }) 16 | private readonly config?: helmet.HelmetOptions, 17 | ) {} 18 | 19 | value(): HelmetAction { 20 | return (req, resp) => this.action(req, resp); 21 | } 22 | 23 | async action(request: Request, response: Response): Promise { 24 | const promise = new Promise((resolve, reject) => { 25 | helmet.default(this.config)(request, response, (err: unknown) => { 26 | if (err) { 27 | reject(err); 28 | } 29 | resolve(); 30 | }); 31 | }); 32 | await promise; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) [2023] [SourceFuse] 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /.github/workflows/trivy.yaml: -------------------------------------------------------------------------------- 1 | # This is a basic workflow to help you get started with Actions 2 | 3 | name: Trivy Scan 4 | 5 | # Controls when the action will run. Triggers the workflow on push or pull request 6 | # events but only for the master branch 7 | on: 8 | pull_request: 9 | branches: [master] 10 | types: [opened, synchronize, reopened] 11 | 12 | # A workflow run is made up of one or more jobs that can run sequentially or in parallel 13 | jobs: 14 | # This workflow contains a single job called "trivy" 15 | trivy: 16 | # The type of runner that the job will run on 17 | runs-on: [self-hosted, linux, codebuild] 18 | 19 | # Steps represent a sequence of tasks that will be executed as part of the job 20 | steps: 21 | # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it 22 | - uses: actions/checkout@v3 23 | 24 | - name: Run Trivy vulnerability scanner in repo mode 25 | uses: aquasecurity/trivy-action@0.28.0 26 | with: 27 | scan-type: "fs" 28 | scan-ref: "${{ github.workspace }}" 29 | trivy-config: "${{ github.workspace }}/trivy.yml" 30 | -------------------------------------------------------------------------------- /.github/pull_request_template.md: -------------------------------------------------------------------------------- 1 | ## Description 2 | 3 | Please include a summary of the change and which issue is fixed. Please also include relevant motivation and context. List any dependencies that are required for this change. 4 | 5 | Fixes # (issue) 6 | 7 | ## Type of change 8 | 9 | Please delete options that are not relevant. 10 | 11 | - [ ] Bug fix (non-breaking change which fixes an issue) 12 | - [ ] New feature (non-breaking change which adds functionality) 13 | - [ ] Breaking change (fix or feature that would cause existing functionality to not work as expected) 14 | - [ ] Intermediate change (work in progress) 15 | 16 | ## How Has This Been Tested? 17 | 18 | Please describe the tests that you ran to verify your changes. Provide instructions so we can reproduce. Please also list any relevant details for your test configuration 19 | 20 | - [ ] Test A 21 | - [ ] Test B 22 | 23 | ## Checklist: 24 | 25 | - [ ] Performed a self-review of my own code 26 | - [ ] npm test passes on your machine 27 | - [ ] New tests added or existing tests modified to cover all changes 28 | - [ ] Code conforms with the style guide 29 | - [ ] API Documentation in code was updated 30 | - [ ] Any dependent changes have been merged and published in downstream modules 31 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | 8 | # Runtime data 9 | pids 10 | *.pid 11 | *.seed 12 | *.pid.lock 13 | 14 | # Directory for instrumented libs generated by jscoverage/JSCover 15 | lib-cov 16 | 17 | # Coverage directory used by tools like istanbul 18 | coverage 19 | 20 | # nyc test coverage 21 | .nyc_output 22 | 23 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 24 | .grunt 25 | 26 | # Bower dependency directory (https://bower.io/) 27 | bower_components 28 | 29 | # node-waf configuration 30 | .lock-wscript 31 | 32 | # Compiled binary addons (http://nodejs.org/api/addons.html) 33 | build/Release 34 | 35 | # Dependency directories 36 | node_modules/ 37 | jspm_packages/ 38 | 39 | # Typescript v1 declaration files 40 | typings/ 41 | 42 | # Optional npm cache directory 43 | .npm 44 | 45 | # Optional eslint cache 46 | .eslintcache 47 | 48 | # Optional REPL history 49 | .node_repl_history 50 | 51 | # Output of 'npm pack' 52 | *.tgz 53 | 54 | # Yarn Integrity file 55 | .yarn-integrity 56 | 57 | # dotenv environment variables file 58 | .env 59 | 60 | # Transpiled JavaScript files from Typescript 61 | /dist 62 | 63 | # Cache used by TypeScript's incremental build 64 | *.tsbuildinfo 65 | -------------------------------------------------------------------------------- /DEVELOPING.md: -------------------------------------------------------------------------------- 1 | # Developer's Guide 2 | 3 | We use Visual Studio Code for developing LoopBack and recommend the same to our 4 | users. 5 | 6 | ## VSCode setup 7 | 8 | Install the following extensions: 9 | 10 | - [prettier](https://marketplace.visualstudio.com/items?itemName=esbenp.prettier-vscode) 11 | 12 | ## Setup Commit Hooks 13 | 14 | Run the following script to prepare husky after the first time install - 15 | 16 | `npm run prepare` 17 | 18 | ## Development workflow 19 | 20 | ### Visual Studio Code 21 | 22 | 1. Start the build task (Cmd+Shift+B) to run TypeScript compiler in the 23 | background, watching and recompiling files as you change them. Compilation 24 | errors will be shown in the VSCode's "PROBLEMS" window. 25 | 26 | 2. Execute "Run Rest Task" from the Command Palette (Cmd+Shift+P) to re-run the 27 | test suite and lint the code for both programming and style errors. Linting 28 | errors will be shown in VSCode's "PROBLEMS" window. Failed tests are printed 29 | to terminal output only. 30 | 31 | ### Other editors/IDEs 32 | 33 | 1. Open a new terminal window/tab and start the continous build process via 34 | `npm run build:watch`. It will run TypeScript compiler in watch mode, 35 | recompiling files as you change them. Any compilation errors will be printed 36 | to the terminal. 37 | 38 | 2. In your main terminal window/tab, run `npm run test:dev` to re-run the test 39 | suite and lint the code for both programming and style errors. You should run 40 | this command manually whenever you have new changes to test. Test failures 41 | and linter errors will be printed to the terminal. 42 | -------------------------------------------------------------------------------- /.github/stale.yml: -------------------------------------------------------------------------------- 1 | # Label to use when marking an issue or a PR as stale 2 | staleLabel: stale 3 | 4 | # Configuration for issues 5 | issues: 6 | # Number of days of inactivity before an issue becomes stale 7 | daysUntilStale: 90 8 | # Comment to post when marking an issue as stale. Set to `false` to disable 9 | markComment: > 10 | This issue has been marked stale because it has not seen any activity within 11 | three months. If you believe this to be an error, please contact one of the code owners. 12 | This issue will be closed within 15 days of being stale. 13 | # Number of days of inactivity before a stale issue is closed 14 | daysUntilClose: 15 15 | # Comment to post when closing a stale issue. Set to `false` to disable 16 | closeComment: > 17 | This issue has been closed due to continued inactivity. Thank you for your understanding. 18 | If you believe this to be in error, please contact one of the code owners. 19 | # Configuration for pull requests 20 | pulls: 21 | # Number of days of inactivity before a PR becomes stale 22 | daysUntilStale: 60 23 | # Comment to post when marking a PR as stale. Set to `false` to disable 24 | markComment: > 25 | This pull request has been marked stale because it has not seen any activity 26 | within two months. It will be closed within 15 days of being stale 27 | unless there is new activity. 28 | # Number of days of inactivity before a stale PR is closed 29 | daysUntilClose: 15 30 | # Comment to post when closing a stale issue. Set to `false` to disable 31 | closeComment: > 32 | This pull request has been closed due to continued inactivity. If you are 33 | interested in finishing the proposed changes, then feel free to re-open 34 | this pull request or open a new one. 35 | -------------------------------------------------------------------------------- /src/release_notes/release-notes.js: -------------------------------------------------------------------------------- 1 | const releaseNotes = require('git-release-notes'); 2 | const simpleGit = require('simple-git/promise'); 3 | const path = require('path'); 4 | const {readFile, writeFile, ensureFile} = require('fs-extra'); 5 | 6 | async function generateReleaseNotes() { 7 | try { 8 | const OPTIONS = { 9 | branch: 'master', 10 | s: './post-processing.js', 11 | }; 12 | const RANGE = await getRange(); 13 | const TEMPLATE = './mymarkdown.ejs'; 14 | 15 | const changelog = await releaseNotes(OPTIONS, RANGE, TEMPLATE); 16 | 17 | const changelogPath = path.resolve(__dirname, '../..', 'CHANGELOG.md'); 18 | await ensureFile(changelogPath); 19 | const currentFile = (await readFile(changelogPath)).toString().trim(); 20 | if (currentFile) { 21 | console.log('Update %s', changelogPath); 22 | } else { 23 | console.log('Create %s', changelogPath); 24 | } 25 | 26 | await writeFile(changelogPath, changelog); 27 | await writeFile(changelogPath, currentFile, {flag: 'a+'}); 28 | await addAndCommit().then(() => { 29 | console.log('Changelog has been updated'); 30 | }); 31 | } catch (ex) { 32 | console.error(ex); 33 | process.exit(1); 34 | } 35 | } 36 | 37 | async function getRange() { 38 | const git = simpleGit(); 39 | const tags = (await git.tag({'--sort': 'committerdate'})).split('\n'); 40 | tags.pop(); 41 | 42 | const startTag = tags.slice(-2)[0]; 43 | const endTag = tags.slice(-1)[0]; 44 | return `${startTag}..${endTag}`; 45 | } 46 | 47 | async function addAndCommit() { 48 | const git = simpleGit(); 49 | await git.add(['../../CHANGELOG.md']); 50 | await git.commit('chore(release): changelog file', { 51 | '--no-verify': null, 52 | }); 53 | await git.push('origin', 'master'); 54 | } 55 | 56 | generateReleaseNotes().catch((ex) => { 57 | console.error(ex); 58 | process.exit(1); 59 | }); 60 | -------------------------------------------------------------------------------- /.github/workflows/release.yaml: -------------------------------------------------------------------------------- 1 | # This Manually Executable Workflow is for NPM Releases 2 | name: Release [Manual] 3 | on: workflow_dispatch 4 | 5 | permissions: 6 | contents: write 7 | id-token: write # REQUIRED for trusted publishing 8 | 9 | jobs: 10 | Release: 11 | runs-on: ubuntu-latest 12 | # Specify environment if you configured one in npm 13 | # environment: production # Uncomment if you set an environment name in npm trusted publisher settings 14 | 15 | steps: 16 | - uses: actions/checkout@v3 17 | with: 18 | # fetch-depth is necessary to get all tags 19 | # otherwise lerna can't detect the changes and will end up bumping the versions for all packages 20 | fetch-depth: 0 21 | token: ${{ secrets.RELEASE_COMMIT_GH_PAT }} 22 | 23 | - name: Setup Node 24 | uses: actions/setup-node@v4 # UPDATED to v4 25 | with: 26 | node-version: '22' 27 | registry-url: 'https://registry.npmjs.org' 28 | always-auth: false # important for trusted publishing 29 | 30 | - name: Configure CI Git User 31 | run: | 32 | git config --global user.name $CONFIG_USERNAME 33 | git config --global user.email $CONFIG_EMAIL 34 | git remote set-url origin https://$GITHUB_ACTOR:$GITHUB_PAT@github.com/sourcefuse/loopback4-helmet 35 | env: 36 | GITHUB_PAT: ${{ secrets.RELEASE_COMMIT_GH_PAT }} 37 | CONFIG_USERNAME: ${{ vars.RELEASE_COMMIT_USERNAME }} 38 | CONFIG_EMAIL: ${{ vars.RELEASE_COMMIT_EMAIL }} 39 | 40 | - name: Install 📌 41 | run: npm install 42 | 43 | - name: Test 🔧 44 | run: npm run test 45 | 46 | # ✅ CHANGED THIS SECTION 47 | - name: Semantic Publish to NPM 🚀 48 | run: | 49 | npm config set provenance true 50 | HUSKY=0 npx semantic-release 51 | env: 52 | GH_TOKEN: ${{ secrets.RELEASE_COMMIT_GH_PAT }} 53 | # REMOVED: NPM_TOKEN is not needed with trusted publishing 54 | # The id-token: write permission above handles authentication 55 | 56 | - name: Changelog 📝 57 | run: cd src/release_notes && HUSKY=0 node release-notes.js 58 | -------------------------------------------------------------------------------- /.github/CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # loopback4-helmet 2 | 3 | ## Contributing 4 | 5 | First off, thank you for considering contributing to the project. It's people like you that helps in keeping this extension useful. 6 | 7 | ### Where do I go from here ? 8 | 9 | If you've noticed a bug or have a question, [search the issue tracker](https://github.com/sourcefuse/loopback4-helmet/issues) to see if 10 | someone else in the community has already created a ticket. If not, go ahead and 11 | [make one](https://github.com/sourcefuse/loopback4-helmet/issues/new/choose)! 12 | 13 | ### Fork & create a branch 14 | 15 | If this is something you think you can fix, then [fork](https://help.github.com/articles/fork-a-repo) this repo and 16 | create a branch with a descriptive name. 17 | 18 | A good branch name would be (where issue #325 is the ticket you're working on): 19 | 20 | ```sh 21 | git checkout -b 325-add-new-feature 22 | ``` 23 | 24 | ### Make a Pull Request 25 | 26 | At this point, you should switch back to your master branch and make sure it's 27 | up to date with loopback4-helmet's master branch: 28 | 29 | ```sh 30 | git remote add upstream git@github.com:sourcefuse/loopback4-helmet.git 31 | git checkout master 32 | git pull upstream master 33 | ``` 34 | 35 | Then update your feature branch from your local copy of master, and push it! 36 | 37 | ```sh 38 | git checkout 325-add-new-feature 39 | git rebase master 40 | git push --set-upstream origin 325-add-new-feature 41 | ``` 42 | 43 | Finally, go to GitHub and [make a Pull Request](https://help.github.com/articles/creating-a-pull-request). 44 | 45 | ### Keeping your Pull Request updated 46 | 47 | If a maintainer asks you to "rebase" your PR, they're saying that a lot of code 48 | has changed, and that you need to update your branch so it's easier to merge. 49 | 50 | To learn more about rebasing in Git, there are a lot of [good][git rebasing] 51 | [resources][interactive rebase] but here's the suggested workflow: 52 | 53 | ```sh 54 | git checkout 325-add-new-feature 55 | git pull --rebase upstream master 56 | git push --force-with-lease 325-add-new-feature 57 | ``` 58 | 59 | [git rebasing]: http://git-scm.com/book/en/Git-Branching-Rebasing 60 | [interactive rebase]: https://help.github.com/articles/interactive-rebase 61 | -------------------------------------------------------------------------------- /src/release_notes/post-processing.js: -------------------------------------------------------------------------------- 1 | const https = require('node:https'); 2 | const jsdom = require('jsdom'); 3 | module.exports = async function (data, callback) { 4 | const rewritten = []; 5 | for (const commit of data.commits) { 6 | if (commit.title.indexOf('chore(release)') !== -1) { 7 | continue; 8 | } 9 | 10 | const commitTitle = commit.title; 11 | commit.title = commitTitle.substring(0, commitTitle.indexOf('#') - 1); 12 | 13 | commit.messageLines = commit.messageLines.filter((message) => { 14 | if (message.indexOf('efs/remotes/origin') === -1) return message; 15 | }); 16 | 17 | commit.messageLines.forEach((message) => { 18 | commit.issueno = message.includes('GH-') 19 | ? message.replace('GH-', '').trim() 20 | : null; 21 | }); 22 | 23 | const issueDesc = await getIssueDesc(commit.issueno).then((res) => { 24 | return res; 25 | }); 26 | commit.issueTitle = issueDesc; 27 | 28 | commit.committerDate = new Date(commit.committerDate).toLocaleDateString( 29 | 'en-us', 30 | { 31 | year: 'numeric', 32 | month: 'long', 33 | day: 'numeric', 34 | }, 35 | ); 36 | rewritten.push(commit); 37 | } 38 | callback({ 39 | commits: rewritten.filter(Boolean), 40 | range: data.range, 41 | }); 42 | }; 43 | 44 | function getIssueDesc(issueNo) { 45 | return new Promise((resolve, reject) => { 46 | let result = ''; 47 | const req = https.get( 48 | `https://github.com/sourcefuse/loopback4-helmet/issues/${encodeURIComponent( 49 | issueNo, 50 | )}`, 51 | (res) => { 52 | res.setEncoding('utf8'); 53 | res.on('data', (chunk) => { 54 | result = result + chunk; 55 | }); 56 | res.on('end', () => { 57 | const {JSDOM} = jsdom; 58 | const dom = new JSDOM(result); 59 | const title = dom.window.document.getElementsByClassName( 60 | 'js-issue-title markdown-title', 61 | ); 62 | let issueTitle = ''; 63 | for (const ele of title) { 64 | if (ele.nodeName === 'BDI') { 65 | issueTitle = ele.innerHTML; 66 | } 67 | } 68 | resolve(issueTitle); 69 | }); 70 | }, 71 | ); 72 | req.on('error', (e) => { 73 | reject(e); 74 | }); 75 | req.end(); 76 | }); 77 | } 78 | -------------------------------------------------------------------------------- /.cz-config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | types: [ 3 | {value: 'feat', name: 'feat: A new feature'}, 4 | {value: 'fix', name: 'fix: A bug fix'}, 5 | {value: 'docs', name: 'docs: Documentation only changes'}, 6 | { 7 | value: 'style', 8 | name: 'style: Changes that do not affect the meaning of the code\n (white-space, formatting, missing semi-colons, etc)', 9 | }, 10 | { 11 | value: 'refactor', 12 | name: 'refactor: A code change that neither fixes a bug nor adds a feature', 13 | }, 14 | { 15 | value: 'perf', 16 | name: 'perf: A code change that improves performance', 17 | }, 18 | {value: 'test', name: 'test: Adding missing tests'}, 19 | { 20 | value: 'chore', 21 | name: 'chore: Changes to the build process or auxiliary tools\n and libraries such as documentation generation', 22 | }, 23 | {value: 'revert', name: 'revert: Reverting a commit'}, 24 | {value: 'WIP', name: 'WIP: Work in progress'}, 25 | ], 26 | 27 | scopes: [ 28 | {name: 'chore'}, 29 | {name: 'deps'}, 30 | {name: 'ci-cd'}, 31 | {name: 'component'}, 32 | {name: 'provider'}, 33 | {name: 'core'}, 34 | {name: 'maintenance'}, 35 | ], 36 | 37 | appendBranchNameToCommitMessage: true, 38 | appendIssueFromBranchName: true, 39 | allowTicketNumber: false, 40 | isTicketNumberRequired: false, 41 | 42 | // override the messages, defaults are as follows 43 | messages: { 44 | type: "Select the type of change that you're committing:", 45 | scope: 'Denote the SCOPE of this change:', 46 | // used if allowCustomScopes is true 47 | customScope: 'Denote the SCOPE of this change:', 48 | subject: 'Write a SHORT, IMPERATIVE tense description of the change:\n', 49 | body: 'Provide a LONGER description of the change (mandatory). Use "\\n" to break new line:\n', 50 | breaking: 'List any BREAKING CHANGES (optional):\n', 51 | footer: 'List any ISSUES CLOSED by this change (optional). E.g.: GH-144:\n', 52 | confirmCommit: 'Are you sure you want to proceed with the commit above?', 53 | }, 54 | 55 | allowCustomScopes: false, 56 | allowBreakingChanges: ['feat', 'fix'], 57 | 58 | // limit subject length 59 | subjectLimit: 100, 60 | breaklineChar: '|', // It is supported for fields body and footer. 61 | footerPrefix: '', 62 | askForBreakingChangeFirst: true, // default is false 63 | }; 64 | -------------------------------------------------------------------------------- /.github/CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Code of Conduct 2 | 3 | ## Our Pledge 4 | 5 | In the interest of fostering an open and welcoming environment, we as 6 | contributors and maintainers pledge to making participation in our project and 7 | our community a harassment-free experience for everyone, regardless of age, body 8 | size, disability, ethnicity, sex characteristics, gender identity and expression, 9 | level of experience, education, socio-economic status, nationality, personal 10 | appearance, race, religion, or sexual identity and orientation. 11 | 12 | ## Our Standards 13 | 14 | Examples of behavior that contributes to creating a positive environment 15 | include: 16 | 17 | - Using welcoming and inclusive language 18 | - Being respectful of differing viewpoints and experiences 19 | - Gracefully accepting constructive criticism 20 | - Focusing on what is best for the community 21 | - Showing empathy towards other community members 22 | 23 | Examples of unacceptable behavior by participants include: 24 | 25 | - The use of sexualized language or imagery and unwelcome sexual attention or 26 | advances 27 | - Trolling, insulting/derogatory comments, and personal or political attacks 28 | - Public or private harassment 29 | - Publishing others' private information, such as a physical or electronic 30 | address, without explicit permission 31 | - Other conduct which could reasonably be considered inappropriate in a 32 | professional setting 33 | 34 | ## Our Responsibilities 35 | 36 | Project maintainers are responsible for clarifying the standards of acceptable 37 | behavior and are expected to take appropriate and fair corrective action in 38 | response to any instances of unacceptable behavior. 39 | 40 | Project maintainers have the right and responsibility to remove, edit, or 41 | reject comments, commits, code, wiki edits, issues, and other contributions 42 | that are not aligned to this Code of Conduct, or to ban temporarily or 43 | permanently any contributor for other behaviors that they deem inappropriate, 44 | threatening, offensive, or harmful. 45 | 46 | ## Scope 47 | 48 | This Code of Conduct applies within all project spaces, and it also applies when 49 | an individual is representing the project or its community in public spaces. 50 | Examples of representing a project or community include using an official 51 | project e-mail address, posting via an official social media account, or acting 52 | as an appointed representative at an online or offline event. Representation of 53 | a project may be further defined and clarified by project maintainers. 54 | 55 | ## Enforcement 56 | 57 | Instances of abusive, harassing, or otherwise unacceptable behavior may be 58 | reported by contacting the project team at support@sourcefuse.com. All 59 | complaints will be reviewed and investigated and will result in a response that 60 | is deemed necessary and appropriate to the circumstances. The project team is 61 | obligated to maintain confidentiality with regard to the reporter of an incident. 62 | Further details of specific enforcement policies may be posted separately. 63 | 64 | Project maintainers who do not follow or enforce the Code of Conduct in good 65 | faith may face temporary or permanent repercussions as determined by other 66 | members of the project's leadership. 67 | 68 | ## Attribution 69 | 70 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, 71 | available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html 72 | 73 | [homepage]: https://www.contributor-covenant.org 74 | 75 | For answers to common questions about this code of conduct, see 76 | https://www.contributor-covenant.org/faq 77 | -------------------------------------------------------------------------------- /.github/workflows/sync-docs.yaml: -------------------------------------------------------------------------------- 1 | name: Sync Docs to arc-docs repo 2 | 3 | on: 4 | push: 5 | branches: 6 | - master 7 | 8 | env: 9 | DOCS_REPO: sourcefuse/arc-docs 10 | BRANCH_PREFIX: automated-docs-sync/ 11 | GITHUB_TOKEN: ${{secrets.ARC_DOCS_API_TOKEN_GITHUB}} 12 | CONFIG_USERNAME: ${{ vars.DOCS_PR_USERNAME }} 13 | CONFIG_EMAIL: ${{ vars.DOCS_PR_EMAIL }} 14 | 15 | jobs: 16 | sync-docs: 17 | runs-on: ubuntu-latest 18 | 19 | steps: 20 | - name: Checkout Extension Code 21 | uses: actions/checkout@v3 22 | with: 23 | token: ${{env.GITHUB_TOKEN}} 24 | path: './extension/' 25 | 26 | - name: Checkout Docs Repository 27 | uses: actions/checkout@v3 28 | with: 29 | token: ${{env.GITHUB_TOKEN}} 30 | repository: ${{env.DOCS_REPO}} 31 | path: './arc-docs/' 32 | 33 | - name: Configure GIT 34 | id: configure_git 35 | working-directory: arc-docs 36 | run: | 37 | git config --global user.email $CONFIG_EMAIL 38 | git config --global user.name $CONFIG_USERNAME 39 | 40 | extension_branch="${{env.BRANCH_PREFIX}}$(basename $GITHUB_REPOSITORY)" 41 | echo "extension_branch=$extension_branch" >> $GITHUB_OUTPUT 42 | 43 | - name: Update Files 44 | id: update_files 45 | working-directory: arc-docs 46 | run: | 47 | extension_branch="${{ steps.configure_git.outputs.extension_branch }}" 48 | 49 | # Create a new branch if it doesn't exist, or switch to it if it does 50 | git checkout -B $extension_branch || git checkout $extension_branch 51 | 52 | # Copy README from the extension repo 53 | cp ../extension/docs/README.md docs/arc-api-docs/extensions/$(basename $GITHUB_REPOSITORY)/ 54 | git add . 55 | 56 | if git diff --quiet --cached; then 57 | have_changes="false"; 58 | else 59 | have_changes="true"; 60 | fi 61 | 62 | echo "Have Changes to be commited: $have_changes" 63 | echo "have_changes=$have_changes" >> $GITHUB_OUTPUT 64 | 65 | - name: Commit Changes 66 | id: commit 67 | working-directory: arc-docs 68 | if: steps.update_files.outputs.have_changes == 'true' 69 | run: | 70 | git commit -m "sync $(basename $GITHUB_REPOSITORY) docs" 71 | - name: Push Changes 72 | id: push_branch 73 | if: steps.update_files.outputs.have_changes == 'true' 74 | working-directory: arc-docs 75 | run: | 76 | extension_branch="${{ steps.configure_git.outputs.extension_branch }}" 77 | git push https://oauth2:${GITHUB_TOKEN}@github.com/${{env.DOCS_REPO}}.git HEAD:$extension_branch --force 78 | 79 | - name: Check PR Status 80 | id: pr_status 81 | if: steps.update_files.outputs.have_changes == 'true' 82 | working-directory: arc-docs 83 | run: | 84 | extension_branch="${{ steps.configure_git.outputs.extension_branch }}" 85 | gh pr status --json headRefName >> "${{github.workspace}}/pr-status.json" 86 | pr_exists="$(jq --arg extension_branch "$extension_branch" '.createdBy[].headRefName == $extension_branch' "${{github.workspace}}/pr-status.json")" 87 | echo "PR Exists: $pr_exists" 88 | echo "pr_exists=$pr_exists" >> $GITHUB_OUTPUT 89 | 90 | - name: Create Pull Request 91 | id: create_pull_request 92 | if: steps.pr_status.outputs.pr_exists != 'true' && steps.update_files.outputs.have_changes == 'true' 93 | working-directory: arc-docs 94 | run: | 95 | extension_branch="${{ steps.configure_git.outputs.extension_branch }}" 96 | 97 | gh pr create --head $(git branch --show-current) --title "Sync ${{ github.event.repository.name }} Docs" --body "This Pull Request has been created by the 'sync-docs' action within the '${{ github.event.repository.name }}' repository, with the purpose of updating markdown files." 98 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "loopback4-helmet", 3 | "version": "8.0.0", 4 | "description": "A loopback-next extension for helmetjs.", 5 | "keywords": [ 6 | "loopback-extension", 7 | "loopback" 8 | ], 9 | "main": "index.js", 10 | "engines": { 11 | "node": ">=20" 12 | }, 13 | "scripts": { 14 | "build": "npm run clean && lb-tsc", 15 | "build:watch": "lb-tsc --watch", 16 | "clean": "lb-clean dist *.tsbuildinfo", 17 | "lint": "npm run prettier:check && npm run eslint", 18 | "lint:fix": "npm run eslint:fix && npm run prettier:fix", 19 | "prettier:cli": "lb-prettier \"**/*.ts\" \"**/*.js\"", 20 | "prettier:check": "npm run prettier:cli -- -l", 21 | "prettier:fix": "npm run prettier:cli -- --write", 22 | "eslint": "lb-eslint --report-unused-disable-directives .", 23 | "eslint:fix": "npm run eslint -- --fix", 24 | "pretest": "npm run clean && npm run build", 25 | "test": "lb-mocha --allow-console-logs \"dist/__tests__\"", 26 | "posttest": "npm run lint", 27 | "test:dev": "lb-mocha --allow-console-logs dist/__tests__/**/*.js && npm run posttest", 28 | "prepublishOnly": "npm run test && npm run lint", 29 | "prepare": "husky install", 30 | "coverage": "nyc npm run test" 31 | }, 32 | "repository": { 33 | "type": "git", 34 | "url": "https://github.com/sourcefuse/loopback4-helmet" 35 | }, 36 | "author": "", 37 | "license": "", 38 | "files": [ 39 | "README.md", 40 | "index.js", 41 | "index.d.ts", 42 | "dist", 43 | "src", 44 | "!*/__tests__" 45 | ], 46 | "dependencies": { 47 | "@loopback/boot": "^8.0.4", 48 | "@loopback/context": "^8.0.3", 49 | "@loopback/core": "^7.0.3", 50 | "@loopback/rest": "^15.0.4", 51 | "helmet": "^5.1.1" 52 | }, 53 | "devDependencies": { 54 | "@commitlint/cli": "^17.7.1", 55 | "@commitlint/config-conventional": "^17.7.0", 56 | "@loopback/build": "^12.0.3", 57 | "@loopback/eslint-config": "^16.0.1", 58 | "@loopback/testlab": "^8.0.3", 59 | "@semantic-release/changelog": "^6.0.1", 60 | "@semantic-release/commit-analyzer": "^9.0.2", 61 | "@semantic-release/git": "^10.0.1", 62 | "@semantic-release/github": "^12.0.0", 63 | "@semantic-release/npm": "^13.1.1", 64 | "@semantic-release/release-notes-generator": "^10.0.3", 65 | "@types/helmet": "4.0.0", 66 | "@types/node": "^16.18.119", 67 | "@typescript-eslint/eslint-plugin": "^7.16.0", 68 | "@typescript-eslint/parser": "^7.16.0", 69 | "commitizen": "^4.2.4", 70 | "cz-conventional-changelog": "^3.3.0", 71 | "cz-customizable": "^6.3.0", 72 | "cz-customizable-ghooks": "^2.0.0", 73 | "eslint": "^8.57.0", 74 | "eslint-config-prettier": "^9.1.0", 75 | "eslint-plugin-eslint-plugin": "^5.5.1", 76 | "eslint-plugin-mocha": "^10.4.3", 77 | "git-release-notes": "^5.0.0", 78 | "husky": "^7.0.4", 79 | "jsdom": "^21.0.0", 80 | "nyc": "^17.1.0", 81 | "semantic-release": "^25.0.1", 82 | "simple-git": "^3.15.1", 83 | "source-map-support": "^0.5.21", 84 | "typescript": "~5.2.2" 85 | }, 86 | "publishConfig": { 87 | "registry": "https://registry.npmjs.org/" 88 | }, 89 | "overrides": { 90 | "git-release-notes": { 91 | "ejs": "^3.1.8", 92 | "yargs": "^17.6.2" 93 | } 94 | }, 95 | "config": { 96 | "commitizen": { 97 | "path": "./node_modules/cz-customizable" 98 | } 99 | }, 100 | "release": { 101 | "branches": [ 102 | "master" 103 | ], 104 | "plugins": [ 105 | [ 106 | "@semantic-release/commit-analyzer", 107 | { 108 | "preset": "angular", 109 | "releaseRules": [ 110 | { 111 | "type": "chore", 112 | "scope": "deps", 113 | "release": "patch" 114 | } 115 | ] 116 | } 117 | ], 118 | "@semantic-release/release-notes-generator", 119 | [ 120 | "@semantic-release/npm", 121 | { 122 | "npmPublish": true, 123 | "pkgRoot": ".", 124 | "tarballDir": "dist" 125 | } 126 | ], 127 | 128 | [ 129 | "@semantic-release/git", 130 | { 131 | "assets": [ 132 | "package.json", 133 | "CHANGELOG.md" 134 | ], 135 | "message": "chore(release): ${nextRelease.version} semantic" 136 | } 137 | ], 138 | "@semantic-release/github" 139 | ], 140 | "repositoryUrl": "https://github.com/sourcefuse/loopback4-helmet.git" 141 | } 142 | } 143 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ARC By SourceFuse logo 2 | 3 | # [loopback4-helmet](https://github.com/sourcefuse/loopback4-helmet) 4 | 5 |

6 | 7 | npm version 8 | 9 | 10 | Sonar Quality Gate 11 | 12 | 13 | GitHub contributors 14 | 15 | 16 | downloads 17 | 18 | 19 | License 20 | 21 | 22 | Powered By LoopBack 4 23 | 24 |

25 | 26 | ## Overview 27 | 28 | A simple loopback-next extension for [helmetjs](https://helmetjs.github.io/) integration in loopback applications. 29 | 30 | ## Install 31 | 32 | ```sh 33 | npm install loopback4-helmet 34 | ``` 35 | 36 | ## Usage 37 | 38 | In order to use this component into your LoopBack application, please follow below steps. 39 | 40 | - Add component to application. 41 | 42 | ```ts 43 | this.component(Loopback4HelmetComponent); 44 | ``` 45 | 46 | - By default, helmet will be initialized with only the default middlewares enabled as per [here](https://github.com/helmetjs/helmet#how-it-works). However, you can override any of the middleware settings using the Config Binding like below. 47 | 48 | ```ts 49 | this.bind(HelmetSecurityBindings.CONFIG).to({ 50 | referrerPolicy: { 51 | policy: 'same-origin', 52 | }, 53 | contentSecurityPolicy: { 54 | directives: { 55 | frameSrc: ["'self'"], 56 | }, 57 | }, 58 | }); 59 | ``` 60 | 61 | - The component exposes a sequence action which can be added to your server sequence class. Adding this will trigger helmet middleware for all the requests passing through. 62 | 63 | ```ts 64 | export class MySequence implements SequenceHandler { 65 | constructor( 66 | @inject(SequenceActions.FIND_ROUTE) protected findRoute: FindRoute, 67 | @inject(SequenceActions.PARSE_PARAMS) protected parseParams: ParseParams, 68 | @inject(SequenceActions.INVOKE_METHOD) protected invoke: InvokeMethod, 69 | @inject(SequenceActions.SEND) public send: Send, 70 | @inject(SequenceActions.REJECT) public reject: Reject, 71 | @inject(HelmetSecurityBindings.HELMET_SECURITY_ACTION) 72 | protected helmetAction: HelmetAction, 73 | ) {} 74 | 75 | async handle(context: RequestContext) { 76 | const requestTime = Date.now(); 77 | try { 78 | const {request, response} = context; 79 | const route = this.findRoute(request); 80 | const args = await this.parseParams(request, route); 81 | 82 | // Helmet Action here 83 | await this.helmetAction(request, response); 84 | 85 | const result = await this.invoke(route, args); 86 | this.send(response, result); 87 | } catch (err) { 88 | ... 89 | } finally { 90 | ... 91 | } 92 | } 93 | } 94 | ``` 95 | 96 | ## Feedback 97 | 98 | If you've noticed a bug or have a question or have a feature request, [search the issue tracker](https://github.com/sourcefuse/loopback4-helmet/issues) to see if someone else in the community has already created a ticket. 99 | If not, go ahead and [make one](https://github.com/sourcefuse/loopback4-helmet/issues/new/choose)! 100 | All feature requests are welcome. Implementation time may vary. Feel free to contribute to the same, if you can. 101 | If you think this extension is useful, please [star](https://help.github.com/en/articles/about-stars) it. Appreciation really helps in keeping this project alive. 102 | 103 | ## Contributing 104 | 105 | Please read [CONTRIBUTING.md](https://github.com/sourcefuse/loopback4-helmet/blob/master/.github/CONTRIBUTING.md) for details on the process for submitting pull requests to us. 106 | 107 | ## Code of conduct 108 | 109 | Code of conduct guidelines [here](https://github.com/sourcefuse/loopback4-helmet/blob/master/.github/CODE_OF_CONDUCT.md). 110 | 111 | ## License 112 | 113 | [MIT](https://github.com/sourcefuse/loopback4-helmet/blob/master/LICENSE) 114 | -------------------------------------------------------------------------------- /src/providers/README.md: -------------------------------------------------------------------------------- 1 | # Providers 2 | 3 | This directory contains providers contributing additional bindings, for example 4 | custom sequence actions. 5 | 6 | ## Overview 7 | 8 | A [provider](http://loopback.io/doc/en/lb4/Creating-components.html#providers) 9 | is a class that provides a `value()` function. This function is called `Context` 10 | when another entity requests a value to be injected. 11 | 12 | Here we create a provider for a logging function that can be used as a new 13 | action in a custom [sequence](http://loopback.io/doc/en/lb4/Sequence.html). 14 | 15 | The logger will log the URL, the parsed request parameters, and the result. The 16 | logger is also capable of timing the sequence if you start a timer at the start 17 | of the sequence using `this.logger.startTimer()`. 18 | 19 | ## Basic Usage 20 | 21 | ### TimerProvider 22 | 23 | TimerProvider is automatically bound to your Application's 24 | [Context](http://loopback.io/doc/en/lb4/Context.html) using the LogComponent 25 | which exports this provider with a binding key of `extension-starter.timer`. You 26 | can learn more about components in the 27 | [related resources section](#related-resources). 28 | 29 | This provider makes availble to your application a timer function which given a 30 | start time _(given as an array [seconds, nanoseconds])_ can give you a total 31 | time elapsed since the start in milliseconds. The timer can also start timing if 32 | no start time is given. This is used by LogComponent to allow a user to time a 33 | Sequence. 34 | 35 | _NOTE:_ _You can get the start time in the required format by using 36 | `this.logger.startTimer()`._ 37 | 38 | You can provide your own implementation of the elapsed time function by binding 39 | it to the binding key (accessible via `ExtensionStarterBindings`) as follows: 40 | 41 | ```ts 42 | app.bind(ExtensionStarterBindings.TIMER).to(timerFn); 43 | ``` 44 | 45 | ### LogProvider 46 | 47 | LogProvider can automatically be bound to your Application's Context using the 48 | LogComponent which exports the provider with a binding key of 49 | `extension-starter.actions.log`. 50 | 51 | The key can be accessed by importing `ExtensionStarterBindings` as follows: 52 | 53 | **Example: Binding Keys** 54 | 55 | ```ts 56 | import {ExtensionStarterBindings} from 'HelloExtensions'; 57 | // Key can be accessed as follows now 58 | const key = ExtensionStarterBindings.LOG_ACTION; 59 | ``` 60 | 61 | LogProvider gives us a seuqence action and a `startTimer` function. In order to 62 | use the sequence action, you must define your own sequence as shown below. 63 | 64 | **Example: Sequence** 65 | 66 | ```ts 67 | class LogSequence implements SequenceHandler { 68 | constructor( 69 | @inject(coreSequenceActions.FIND_ROUTE) protected findRoute: FindRoute, 70 | @inject(coreSequenceActions.PARSE_PARAMS) 71 | protected parseParams: ParseParams, 72 | @inject(coreSequenceActions.INVOKE_METHOD) protected invoke: InvokeMethod, 73 | @inject(coreSequenceActions.SEND) protected send: Send, 74 | @inject(coreSequenceActions.REJECT) protected reject: Reject, 75 | // We get the logger injected by the LogProvider here 76 | @inject(ExtensionStarterBindings.LOG_ACTION) protected logger: LogFn, 77 | ) {} 78 | 79 | async handle(context: RequestContext) { 80 | const {request, response} = context; 81 | 82 | // We define these variable outside so they can be accessed by logger. 83 | let args: any = []; 84 | let result: any; 85 | 86 | // Optionally start timing the sequence using the timer 87 | // function available via LogFn 88 | const start = this.logger.startTimer(); 89 | 90 | try { 91 | const route = this.findRoute(request); 92 | args = await this.parseParams(request, route); 93 | result = await this.invoke(route, args); 94 | this.send(response, result); 95 | } catch (error) { 96 | result = error; // so we can log the error message in the logger 97 | this.reject(context, error); 98 | } 99 | 100 | // We call the logger function given to us by LogProvider 101 | this.logger(request, args, result, start); 102 | } 103 | } 104 | ``` 105 | 106 | Once a sequence has been written, we can just use that in our Application as 107 | follows: 108 | 109 | **Example: Application** 110 | 111 | ```ts 112 | const app = new Application({ 113 | sequence: LogSequence, 114 | }); 115 | app.component(LogComponent); 116 | 117 | // Now all requests handled by our sequence will be logged. 118 | ``` 119 | 120 | ## Related Resources 121 | 122 | You can check out the following resource to learn more about providers, 123 | components, sequences, and binding keys. 124 | 125 | - [Providers](http://loopback.io/doc/en/lb4/Creating-components.html#providers) 126 | - [Creating Components](http://loopback.io/doc/en/lb4/Creating-components.html) 127 | - [Using Components](http://loopback.io/doc/en/lb4/Using-components.html) 128 | - [Sequence](http://loopback.io/doc/en/lb4/Sequence.html) 129 | - [Binding Keys](http://loopback.io/doc/en/lb4/Decorators.html) 130 | -------------------------------------------------------------------------------- /docs/README.md: -------------------------------------------------------------------------------- 1 | ARC By SourceFuse logo 2 | 3 | # [loopback4-helmet](https://github.com/sourcefuse/loopback4-helmet) 4 | 5 |

6 | 7 | npm version 8 | 9 | 10 | Sonar Quality Gate 11 | 12 | 13 | Synk Status 14 | 15 | 16 | GitHub contributors 17 | 18 | 19 | downloads 20 | 21 | 22 | License 23 | 24 | 25 | Powered By LoopBack 4 26 | 27 |

28 | 29 | ## Overview 30 | 31 | A simple loopback-next extension for [helmetjs](https://helmetjs.github.io/) integration in loopback applications. 32 | 33 | ## Install 34 | 35 | ```sh 36 | npm install loopback4-helmet 37 | ``` 38 | 39 | ## Usage 40 | 41 | In order to use this component into your LoopBack application, please follow below steps. 42 | 43 | - Add component to application. 44 | 45 | ```ts 46 | this.component(Loopback4HelmetComponent); 47 | ``` 48 | 49 | - By default, helmet will be initialized with only the default middlewares enabled as per [here](https://github.com/helmetjs/helmet#how-it-works). However, you can override any of the middleware settings using the Config Binding like below. 50 | 51 | ```ts 52 | this.bind(HelmetSecurityBindings.CONFIG).to({ 53 | referrerPolicy: { 54 | policy: 'same-origin', 55 | }, 56 | contentSecurityPolicy: { 57 | directives: { 58 | frameSrc: ["'self'"], 59 | }, 60 | }, 61 | }); 62 | ``` 63 | 64 | - The component exposes a sequence action which can be added to your server sequence class. Adding this will trigger helmet middleware for all the requests passing through. 65 | 66 | ```ts 67 | export class MySequence implements SequenceHandler { 68 | constructor( 69 | @inject(SequenceActions.FIND_ROUTE) protected findRoute: FindRoute, 70 | @inject(SequenceActions.PARSE_PARAMS) protected parseParams: ParseParams, 71 | @inject(SequenceActions.INVOKE_METHOD) protected invoke: InvokeMethod, 72 | @inject(SequenceActions.SEND) public send: Send, 73 | @inject(SequenceActions.REJECT) public reject: Reject, 74 | @inject(HelmetSecurityBindings.HELMET_SECURITY_ACTION) 75 | protected helmetAction: HelmetAction, 76 | ) {} 77 | 78 | async handle(context: RequestContext) { 79 | const requestTime = Date.now(); 80 | try { 81 | const {request, response} = context; 82 | const route = this.findRoute(request); 83 | const args = await this.parseParams(request, route); 84 | 85 | // Helmet Action here 86 | await this.helmetAction(request, response); 87 | 88 | const result = await this.invoke(route, args); 89 | this.send(response, result); 90 | } catch (err) { 91 | ... 92 | } finally { 93 | ... 94 | } 95 | } 96 | } 97 | ``` 98 | 99 | ## Feedback 100 | 101 | If you've noticed a bug or have a question or have a feature request, [search the issue tracker](https://github.com/sourcefuse/loopback4-helmet/issues) to see if someone else in the community has already created a ticket. 102 | If not, go ahead and [make one](https://github.com/sourcefuse/loopback4-helmet/issues/new/choose)! 103 | All feature requests are welcome. Implementation time may vary. Feel free to contribute the same, if you can. 104 | If you think this extension is useful, please [star](https://help.github.com/en/articles/about-stars) it. Appreciation really helps in keeping this project alive. 105 | 106 | ## Contributing 107 | 108 | Please read [CONTRIBUTING.md](https://github.com/sourcefuse/loopback4-helmet/blob/master/.github/CONTRIBUTING.md) for details on the process for submitting pull requests to us. 109 | 110 | ## Code of conduct 111 | 112 | Code of conduct guidelines [here](https://github.com/sourcefuse/loopback4-helmet/blob/master/.github/CODE_OF_CONDUCT.md). 113 | 114 | ## License 115 | 116 | [MIT](https://github.com/sourcefuse/loopback4-helmet/blob/master/LICENSE) 117 | -------------------------------------------------------------------------------- /src/mixins/README.md: -------------------------------------------------------------------------------- 1 | # Mixins 2 | 3 | This directory contains source files for the mixins exported by this extension. 4 | 5 | ## Overview 6 | 7 | Sometimes it's helpful to write partial classes and then combining them together 8 | to build more powerful classes. This pattern is called Mixins (mixing in partial 9 | classes) and is supported by LoopBack 4. 10 | 11 | LoopBack 4 supports mixins at an `Application` level. Your partial class can 12 | then be mixed into the `Application` class. A mixin class can modify or override 13 | existing methods of the class or add new ones! It is also possible to mixin 14 | multiple classes together as needed. 15 | 16 | ### High level example 17 | 18 | ```ts 19 | class MyApplication extends MyMixinClass(Application) { 20 | // Your code 21 | } 22 | 23 | // Multiple Classes mixed together 24 | class MyApp extends MyMixinClass(MyMixinClass2(Application)) { 25 | // Your code 26 | } 27 | ``` 28 | 29 | ## Getting Started 30 | 31 | For hello-extensions we write a simple Mixin that allows the `Application` class 32 | to bind a `Logger` class from ApplicationOptions, Components, or `.logger()` 33 | method that is mixed in. `Logger` instances are bound to the key 34 | `loggers.${Logger.name}`. Once a Logger has been bound, the user can retrieve it 35 | by using 36 | [Dependency Injection](http://loopback.io/doc/en/lb4/Dependency-injection.html) 37 | and the key for the `Logger`. 38 | 39 | ### What is a Logger? 40 | 41 | > A Logger class is provides a mechanism for logging messages of varying 42 | > priority by providing an implementation for `Logger.info()` & 43 | > `Logger.error()`. An example of a Logger is `console` which has 44 | > `console.log()` and `console.error()`. 45 | 46 | #### An example Logger 47 | 48 | ```ts 49 | class ColorLogger implements Logger { 50 | log(...args: LogArgs) { 51 | console.log('log :', ...args); 52 | } 53 | 54 | error(...args: LogArgs) { 55 | // log in red color 56 | console.log('\x1b[31m error: ', ...args, '\x1b[0m'); 57 | } 58 | } 59 | ``` 60 | 61 | ## LoggerMixin 62 | 63 | A complete & functional implementation can be found in `logger.mixin.ts`. _Here 64 | are some key things to keep in mind when writing your own Mixin_. 65 | 66 | ### constructor() 67 | 68 | A Mixin constructor must take an array of any type as it's argument. This would 69 | represent `ApplicationOptions` for our base class `Application` as well as any 70 | properties we would like for our Mixin. 71 | 72 | It is also important for the constructor to call `super(args)` so `Application` 73 | continues to work as expected. 74 | 75 | ```ts 76 | constructor(...args: any[]) { 77 | super(args); 78 | } 79 | ``` 80 | 81 | ### Binding via `ApplicationOptions` 82 | 83 | As mentioned earlier, since our `args` represents `ApplicationOptions`, we can 84 | make it possible for users to pass in their `Logger` implementations in a 85 | `loggers` array on `ApplicationOptions`. We can then read the array and 86 | automatically bind these for the user. 87 | 88 | #### Example user experience 89 | 90 | ```ts 91 | class MyApp extends LoggerMixin(Application) { 92 | constructor(...args: any[]) { 93 | super(...args); 94 | } 95 | } 96 | 97 | const app = new MyApp({ 98 | loggers: [ColorLogger], 99 | }); 100 | ``` 101 | 102 | #### Example Implementation 103 | 104 | To implement this, we would check `this.options` to see if it has a `loggers` 105 | array and if so, bind it by calling the `.logger()` method. (More on that 106 | below). 107 | 108 | ```ts 109 | if (this.options.loggers) { 110 | for (const logger of this.options.loggers) { 111 | this.logger(logger); 112 | } 113 | } 114 | ``` 115 | 116 | ### Binding via `.logger()` 117 | 118 | As mentioned earlier, we can add a new function to our `Application` class 119 | called `.logger()` into which a user would pass in their `Logger` implementation 120 | so we can bind it to the `loggers.*` key for them. We just add this new method 121 | on our partial Mixin class. 122 | 123 | ```ts 124 | logger(logClass: Logger) { 125 | const loggerKey = `loggers.${logClass.name}`; 126 | this.bind(loggerKey).toClass(logClass); 127 | } 128 | ``` 129 | 130 | ### Binding a `Logger` from a `Component` 131 | 132 | Our base class of `Application` already has a method that binds components. We 133 | can modify this method to continue binding a `Component` as usual but also 134 | binding any `Logger` instances provided by that `Component`. When modifying 135 | behavior of an existing method, we can ensure existing behavior by calling the 136 | `super.method()`. In our case the method is `.component()`. 137 | 138 | ```ts 139 | component(component: Constructor) { 140 | super.component(component); // ensures existing behavior from Application 141 | this.mountComponentLoggers(component); 142 | } 143 | ``` 144 | 145 | We have now modified `.component()` to do it's thing and then call our method 146 | `mountComponentLoggers()`. In this method is where we check for `Logger` 147 | implementations declared by the component in a `loggers` array by retrieving the 148 | instance of the `Component`. Then if `loggers` array exists, we bind the 149 | `Logger` instances as normal (by leveraging our `.logger()` method). 150 | 151 | ```ts 152 | mountComponentLoggers(component: Constructor) { 153 | const componentKey = `components.${component.name}`; 154 | const compInstance = this.getSync(componentKey); 155 | 156 | if (compInstance.loggers) { 157 | for (const logger of compInstance.loggers) { 158 | this.logger(logger); 159 | } 160 | } 161 | } 162 | ``` 163 | 164 | ## Retrieving the Logger instance 165 | 166 | Now that we have bound a Logger to our Application via one of the many ways made 167 | possible by `LoggerMixin`, we need to be able to retrieve it so we can use it. 168 | Let's say we want to use it in a controller. Here's an example to retrieving it 169 | so we can use it. 170 | 171 | ```ts 172 | class MyController { 173 | constructor(@inject('loggers.ColorLogger') protected log: Logger) {} 174 | 175 | helloWorld() { 176 | this.log.log('hello log'); 177 | this.log.error('hello error'); 178 | } 179 | } 180 | ``` 181 | 182 | ## Examples for using LoggerMixin 183 | 184 | ### Using the app's `.logger()` method 185 | 186 | ```ts 187 | class LoggingApplication extends LoggerMixin(Application) { 188 | constructor(...args: any[]) { 189 | super(...args); 190 | this.logger(ColorLogger); 191 | } 192 | } 193 | ``` 194 | 195 | ### Using the app's constructor 196 | 197 | ```ts 198 | class LoggerApplication extends LoggerMixin(Application) { 199 | constructor() { 200 | super({ 201 | loggers: [ColorLogger], 202 | }); 203 | } 204 | } 205 | ``` 206 | 207 | ### Binding a Logger provided by a component 208 | 209 | ```ts 210 | class LoggingComponent implements Component { 211 | loggers: [ColorLogger]; 212 | } 213 | 214 | const app = new LoggingApplication(); 215 | app.component(LoggingComponent); // Logger from MyComponent will be bound to loggers.ColorLogger 216 | ``` 217 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | ## Release [v8.0.0](https://github.com/sourcefuse/loopback4-helmet/compare/v7.0.3..v8.0.0) September 8, 2025 2 | Welcome to the September 8, 2025 release of loopback4-helmet. There are many updates in this version that we hope you will like, the key highlights include: 3 | 4 | - [](https://github.com/sourcefuse/loopback4-helmet/issues/) :- [refactor(chore): node and loopback packages version upgrade ](https://github.com/sourcefuse/loopback4-helmet/commit/6445a17b435ec2c4a1516b9fd60b9828042e2e9b) was commited on September 8, 2025 by [Vaibhav Bhalla](mailto:vaibhav.bhalla@sourcefuse.com) 5 | 6 | - node and loopback packages version upgrade 7 | 8 | - BREAKING CHANGE: yes 9 | 10 | - GH-148 11 | 12 | - Co-authored-by: Vaibhav Bhalla <vaibhav.bhalla@SFSupports-MacBook-Air.local> 13 | 14 | 15 | Clink on the above links to understand the changes in detail. 16 | ___ 17 | 18 | ## Release [v7.0.3](https://github.com/sourcefuse/loopback4-helmet/compare/v7.0.2..v7.0.3) December 13, 2024 19 | Welcome to the December 13, 2024 release of loopback4-helmet. There are many updates in this version that we hope you will like, the key highlights include: 20 | 21 | - [](https://github.com/sourcefuse/loopback4-helmet/issues/) :- [chore(deps): version update ](https://github.com/sourcefuse/loopback4-helmet/commit/bf372e1d2aad4a7d31aa85d5a7d7bca4d9f336f3) was commited on December 13, 2024 by [Sunny Tyagi](mailto:107617248+Tyagi-Sunny@users.noreply.github.com) 22 | 23 | - version update 24 | 25 | - gh-0 26 | 27 | 28 | Clink on the above links to understand the changes in detail. 29 | ___ 30 | 31 | ## Release [v7.0.2](https://github.com/sourcefuse/loopback4-helmet/compare/v7.0.1..v7.0.2) June 4, 2024 32 | Welcome to the June 4, 2024 release of loopback4-helmet. There are many updates in this version that we hope you will like, the key highlights include: 33 | 34 | - [loopback version updates](https://github.com/sourcefuse/loopback4-helmet/issues/120) :- [chore(deps): loopback version updates ](https://github.com/sourcefuse/loopback4-helmet/commit/32c2ba0ff767bf42519265e681e566457395b1d7) was commited on June 4, 2024 by [Surbhi](mailto:98279679+Surbhi-sharma1@users.noreply.github.com) 35 | 36 | - loopback version updates 37 | 38 | - GH-120 39 | 40 | 41 | Clink on the above links to understand the changes in detail. 42 | ___ 43 | 44 | ## Release [v7.0.1](https://github.com/sourcefuse/loopback4-helmet/compare/v7.0.0..v7.0.1) May 15, 2024 45 | Welcome to the May 15, 2024 release of loopback4-helmet. There are many updates in this version that we hope you will like, the key highlights include: 46 | 47 | - [Changelog not generated](https://github.com/sourcefuse/loopback4-helmet/issues/118) :- [fix(ci-cd): add the step to generate changelog ](https://github.com/sourcefuse/loopback4-helmet/commit/284497291c7d2907d4162d5380096cff43200194) was commited on May 15, 2024 by [yeshamavani](mailto:83634146+yeshamavani@users.noreply.github.com) 48 | 49 | - add the missing ci checks for pr 50 | 51 | - GH-118 52 | 53 | 54 | - [Copy the Readme to root as well](https://github.com/sourcefuse/loopback4-helmet/issues/116) :- [docs(chore): copy the Readme to root as well ](https://github.com/sourcefuse/loopback4-helmet/commit/a4f4883b0569f8c4f28170a3a5ec278a999ab018) was commited on May 13, 2024 by [arpit1503khanna](mailto:108673359+arpit1503khanna@users.noreply.github.com) 55 | 56 | - copy the Readme to root as well 57 | 58 | - GH-116 59 | 60 | 61 | Clink on the above links to understand the changes in detail. 62 | ___ 63 | 64 | ## Release [v5.0.1](https://github.com/sourcefuse/loopback4-helmet/compare/v5.0.0..v5.0.1) July 14, 2023 65 | Welcome to the July 14, 2023 release of loopback4-helmet. There are many updates in this version that we hope you will like, the key highlights include: 66 | 67 | - [Add ARC Branding in README](https://github.com/sourcefuse/loopback4-helmet/issues/83) :- [docs(chore): add arc branding ](https://github.com/sourcefuse/loopback4-helmet/commit/44d9c9ece0c7d0c262fd3a4f740155d935810713) was commited on July 14, 2023 by [Surbhi](mailto:98279679+Surbhi-sharma1@users.noreply.github.com) 68 | 69 | - add arc branding 70 | 71 | - GH-83 72 | 73 | 74 | - [Loopback version update](https://github.com/sourcefuse/loopback4-helmet/issues/74) :- [chore(deps): loopback version update ](https://github.com/sourcefuse/loopback4-helmet/commit/32de510779a7db3fc1962e4529f469d4fd3a765c) was commited on July 14, 2023 by [Surbhi](mailto:98279679+Surbhi-sharma1@users.noreply.github.com) 75 | 76 | - loopback version update 77 | 78 | - GH-74 79 | 80 | 81 | Clink on the above links to understand the changes in detail. 82 | ___ 83 | 84 | ## Release [v5.0.0](https://github.com/sourcefuse/loopback4-helmet/compare/v4.2.3..v5.0.0) June 7, 2023 85 | Welcome to the June 7, 2023 release of loopback4-helmet. There are many updates in this version that we hope you will like, the key highlights include: 86 | 87 | - [Loopback version update](https://github.com/sourcefuse/loopback4-helmet/issues/74) :- [chore(deps): loopback version update ](https://github.com/sourcefuse/loopback4-helmet/commit/b971cdd908d8167f2c8269ff9747bb82d8ed8b2d) was commited on May 19, 2023 by [RaghavaroraSF](mailto:97958393+RaghavaroraSF@users.noreply.github.com) 88 | 89 | - loopback version update 90 | 91 | - GH-74 92 | 93 | 94 | - [Remove support for node v14](https://github.com/sourcefuse/loopback4-helmet/issues/78) :- [feat(chore): remove support for node v14,v12,v10 ](https://github.com/sourcefuse/loopback4-helmet/commit/1fee84f271d5789346219573698fdf74bc5254aa) was commited on May 11, 2023 by [RaghavaroraSF](mailto:97958393+RaghavaroraSF@users.noreply.github.com) 95 | 96 | - version 14, v12, v10, v8 of Nodejs reached its end of life 97 | 98 | - BREAKING CHANGE: 99 | 100 | - End of life of node v14, node v12, node v10 and node v8 101 | 102 | - GH-78 103 | 104 | 105 | - [License and Copyright Headers’ Year Upgradation](https://github.com/sourcefuse/loopback4-helmet/issues/76) :- [chore(maintenance): update license and copyright headers ](https://github.com/sourcefuse/loopback4-helmet/commit/d3b129bacc238f45e34258819de55e4b92fc96b6) was commited on May 4, 2023 by [RaghavaroraSF](mailto:97958393+RaghavaroraSF@users.noreply.github.com) 106 | 107 | - to reflect the year change 108 | 109 | - GH-76 110 | 111 | 112 | Clink on the above links to understand the changes in detail. 113 | ___ 114 | 115 | ## Release [v4.2.3](https://github.com/sourcefuse/loopback4-helmet/compare/v4.2.2..v4.2.3) April 24, 2023 116 | Welcome to the April 24, 2023 release of loopback4-helmet. There are many updates in this version that we hope you will like, the key highlights include: 117 | 118 | - [Loopback version update](https://github.com/sourcefuse/loopback4-helmet/issues/74) :- [chore(deps): loopback version update ](https://github.com/sourcefuse/loopback4-helmet/commit/d3a05df9dde950bb974441d24294e4fe79280766) was commited on April 24, 2023 by [RaghavaroraSF](mailto:97958393+RaghavaroraSF@users.noreply.github.com) 119 | 120 | - loopback version update 121 | 122 | - GH-74 123 | 124 | 125 | Clink on the above links to understand the changes in detail. 126 | ___ 127 | 128 | ## Release [v4.2.2](https://github.com/sourcefuse/loopback4-helmet/compare/v4.2.1..v4.2.2) March 10, 2023 129 | Welcome to the March 10, 2023 release of loopback4-helmet. There are many updates in this version that we hope you will like, the key highlights include: 130 | 131 | - [loopback version update](https://github.com/sourcefuse/loopback4-helmet/issues/72) :- [chore(deps): loopback version update ](https://github.com/sourcefuse/loopback4-helmet/commit/c5fe04eeb0490f16a0e30f94de1bd64d3b2a14dd) was commited on March 10, 2023 by [Gautam Agarwal](mailto:108651274+gautam23-sf@users.noreply.github.com) 132 | 133 | - loopback version update 134 | 135 | - GH-72 136 | 137 | 138 | - [Stale Bot missing in the repository](https://github.com/sourcefuse/loopback4-helmet/issues/70) :- [chore(chore): add github stale bot ](https://github.com/sourcefuse/loopback4-helmet/commit/f37999430b81bb020121bd172bff005d40adfdda) was commited on February 27, 2023 by [yeshamavani](mailto:83634146+yeshamavani@users.noreply.github.com) 139 | 140 | - Added stale.yml file to configure stale options 141 | 142 | - GH-70 143 | 144 | 145 | Clink on the above links to understand the changes in detail. 146 | ___ 147 | 148 | ## Release [v4.2.1](https://github.com/sourcefuse/loopback4-helmet/compare/v4.2.0..v4.2.1) February 20, 2023 149 | Welcome to the February 20, 2023 release of loopback4-helmet. There are many updates in this version that we hope you will like, the key highlights include: 150 | 151 | - [Correct the changelog Format](https://github.com/sourcefuse/loopback4-helmet/issues/68) :- [fix(chore): correct the changelog format ](https://github.com/sourcefuse/loopback4-helmet/commit/d71c98af22b484487d24e254d4428e70b5b0f12e) was commited on February 20, 2023 by [yeshamavani](mailto:83634146+yeshamavani@users.noreply.github.com) 152 | 153 | - * fix(chore): correct the changelog format 154 | 155 | - now issue description will be visible 156 | 157 | - GH-68 158 | 159 | - * chore(deps): upgrading the packages version 160 | 161 | - upgraded helmet and cookiejar 162 | 163 | - GH-68 164 | 165 | 166 | - [Package Update : loopback4-helmet](https://github.com/sourcefuse/loopback4-helmet/issues/66) :- [fix(chore): remove all current vulnerability of loopback4-helmet ](https://github.com/sourcefuse/loopback4-helmet/commit/17d4b8deb030b574838a1b30e14dacdc401d85c0) was commited on February 20, 2023 by [Sunny Tyagi](mailto:107617248+Tyagi-Sunny@users.noreply.github.com) 167 | 168 | - remove all current vulnerability of loopback4-helmet 169 | 170 | - GH-66 171 | 172 | 173 | Clink on the above links to understand the changes in detail. 174 | ___ 175 | 176 | ## Release [v4.2.0](https://github.com/sourcefuse/loopback4-helmet/compare/v4.1.4..v4.2.0) January 11, 2023 177 | Welcome to the January 11, 2023 release of loopback4-helmet. There are many updates in this version that we hope you will like, the key highlights include: 178 | 179 | - [](https://github.com/sourcefuse/loopback4-helmet/issues/-60) :- [feat(chore): generate detailed and informative changelog ](https://github.com/sourcefuse/loopback4-helmet/commit/7ad442fc49325ba36bcead5786fb1eaf9f657925) was commited on January 10, 2023 by [yeshamavani](mailto:83634146+yeshamavani@users.noreply.github.com) 180 | 181 | - * feat(chore): generate detailed and informative changelog 182 | 183 | - Using Customizable npm package to generate changelog 184 | 185 | - GH-60 186 | 187 | - * feat(chore): generate detailed and informative changelog 188 | 189 | - Using Customizable npm package to generate changelog 190 | 191 | - GH-60 192 | 193 | 194 | - [](https://github.com/sourcefuse/loopback4-helmet/issues/-58) :- [chore(deps): loopback version updates ](https://github.com/sourcefuse/loopback4-helmet/commit/d03ce70d7119971e9b1ab8ade0f9610ef544e638) was commited on January 10, 2023 by [Surbhi Sharma](mailto:98279679+Surbhi-sharma1@users.noreply.github.com) 195 | 196 | - Updated version of the lb4 dependencies to the latest. 197 | 198 | - GH-58 199 | 200 | 201 | Clink on the above links to understand the changes in detail. 202 | ___ 203 | 204 | ## [4.1.4](https://github.com/sourcefuse/loopback4-helmet/compare/v4.1.3...v4.1.4) (2022-12-05) 205 | 206 | ## [4.1.3](https://github.com/sourcefuse/loopback4-helmet/compare/v4.1.2...v4.1.3) (2022-10-31) 207 | 208 | ## [4.1.2](https://github.com/sourcefuse/loopback4-helmet/compare/v4.1.1...v4.1.2) (2022-09-09) 209 | 210 | ## [4.1.1](https://github.com/sourcefuse/loopback4-helmet/compare/v4.1.0...v4.1.1) (2022-06-17) 211 | 212 | # [4.1.0](https://github.com/sourcefuse/loopback4-helmet/compare/v4.0.2...v4.1.0) (2022-05-26) 213 | 214 | ### Bug Fixes 215 | 216 | - **deps:** remove vulnerabilities ([#37](https://github.com/sourcefuse/loopback4-helmet/issues/37)) ([747aae1](https://github.com/sourcefuse/loopback4-helmet/commit/747aae120e03bd26e373542fb69009bebb049583)), closes [#36](https://github.com/sourcefuse/loopback4-helmet/issues/36) [#36](https://github.com/sourcefuse/loopback4-helmet/issues/36) 217 | 218 | ### Features 219 | 220 | - **ci-cd:** semantic-release ([#23](https://github.com/sourcefuse/loopback4-helmet/issues/23)) ([2a291bd](https://github.com/sourcefuse/loopback4-helmet/commit/2a291bdbc6e2cfec5e92ba04a262cf0b3580824e)), closes [#22](https://github.com/sourcefuse/loopback4-helmet/issues/22) [#22](https://github.com/sourcefuse/loopback4-helmet/issues/22) --------------------------------------------------------------------------------