This commit is contained in:
Tutur33
2023-11-24 22:35:41 +01:00
parent 3c0b507a93
commit 7644b2a0f7
45165 changed files with 4803356 additions and 3 deletions
+12
View File
@@ -0,0 +1,12 @@
version: 2
updates:
- package-ecosystem: github-actions
directory: '/'
schedule:
interval: daily
open-pull-requests-limit: 10
- package-ecosystem: npm
directory: '/'
schedule:
interval: daily
open-pull-requests-limit: 10
+46
View File
@@ -0,0 +1,46 @@
name: CI
'on':
push:
paths-ignore:
- docs/**
- '*.md'
pull_request:
paths-ignore:
- docs/**
- '*.md'
jobs:
test:
runs-on: ${{ matrix.os }}
strategy:
matrix:
node-version:
- 10
- 12
- 14
- 16
os:
- macos-latest
- ubuntu-latest
- windows-latest
steps:
- uses: actions/checkout@v2.4.0
- name: Use Node.js
uses: actions/setup-node@v2.5.1
with:
node-version: ${{ matrix.node-version }}
- name: Install Dependencies
run: |
npm install --ignore-scripts
- name: Run Tests
run: |
npm test
automerge:
needs: test
runs-on: ubuntu-latest
permissions:
pull-requests: write
contents: write
steps:
- uses: fastify/github-action-merge-dependabot@v3
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
+21
View File
@@ -0,0 +1,21 @@
MIT License
Copyright (c) Fastify
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
+70
View File
@@ -0,0 +1,70 @@
# process-warning
![CI](https://github.com/fastify/process-warning/workflows/CI/badge.svg)
[![NPM version](https://img.shields.io/npm/v/process-warning.svg?style=flat)](https://www.npmjs.com/package/process-warning)
[![Known Vulnerabilities](https://snyk.io/test/github/fastify/process-warning/badge.svg)](https://snyk.io/test/github/fastify/process-warning)
[![js-standard-style](https://img.shields.io/badge/code%20style-standard-brightgreen.svg?style=flat)](https://standardjs.com/)
A small utility for generating consistent warning objects across your codebase.
It also exposes a utility for emitting those warnings, guaranteeing that they are issued only once.
This module is used by the [Fastify](https://fastify.io) framework and it was called `fastify-warning` prior to version 1.0.0.
### Install
```
npm i process-warning
```
### Usage
The module exports a builder function that returns a utility for creating warnings and emitting them.
```js
const warning = require('process-warning')()
```
#### Methods
```
warning.create(name, code, message)
```
- `name` (`string`, required) - The error name, you can access it later with `error.name`. For consistency, we recommend prefixing module error names with `{YourModule}Warning`
- `code` (`string`, required) - The warning code, you can access it later with `error.code`. For consistency, we recommend prefixing plugin error codes with `{ThreeLetterModuleName}_`, e.g. `FST_`. NOTE: codes should be all uppercase.
- `message` (`string`, required) - The warning message. You can also use interpolated strings for formatting the message.
The utility also contains an `emit` function that you can use for emitting the warnings you have previously created by passing their respective code. A warning is guaranteed to be emitted only once.
```
warning.emit(code [, a [, b [, c]]])
```
- `code` (`string`, required) - The warning code you intend to emit.
- `[, a [, b [, c]]]` (`any`, optional) - Parameters for string interpolation.
```js
const warning = require('process-warning')()
warning.create('FastifyWarning', 'FST_ERROR_CODE', 'message')
warning.emit('FST_ERROR_CODE')
```
How to use an interpolated string:
```js
const warning = require('process-warning')()
warning.create('FastifyWarning', 'FST_ERROR_CODE', 'Hello %s')
warning.emit('FST_ERROR_CODE', 'world')
```
The module also exports an `warning.emitted` [Map](https://developer.mozilla.org/it/docs/Web/JavaScript/Reference/Global_Objects/Map), which contains all the warnings already emitted. Useful for testing.
```js
const warning = require('process-warning')()
warning.create('FastifyWarning', 'FST_ERROR_CODE', 'Hello %s')
console.log(warning.emitted.get('FST_ERROR_CODE')) // false
warning.emit('FST_ERROR_CODE', 'world')
console.log(warning.emitted.get('FST_ERROR_CODE')) // true
```
## License
Licensed under [MIT](./LICENSE).
+17
View File
@@ -0,0 +1,17 @@
declare function warning (): Warning
export declare class WarnOpts {
code: string;
name: string;
message: string;
}
export type BuildWarnOptsFn = (a?: any, b?: any, c?: any) => WarnOpts
interface Warning {
create(name: string, code: string, message: string): BuildWarnOptsFn,
emit(cod: string, a?: any, b?: any, c?: any): void,
emitted: Map<string, boolean>
}
export default warning
+62
View File
@@ -0,0 +1,62 @@
'use strict'
const { format } = require('util')
function build () {
const codes = {}
const emitted = new Map()
function create (name, code, message) {
if (!name) throw new Error('Warning name must not be empty')
if (!code) throw new Error('Warning code must not be empty')
if (!message) throw new Error('Warning message must not be empty')
code = code.toUpperCase()
if (codes[code] !== undefined) {
throw new Error(`The code '${code}' already exist`)
}
function buildWarnOpts (a, b, c) {
// more performant than spread (...) operator
let formatted
if (a && b && c) {
formatted = format(message, a, b, c)
} else if (a && b) {
formatted = format(message, a, b)
} else if (a) {
formatted = format(message, a)
} else {
formatted = message
}
return {
code,
name,
message: formatted
}
}
emitted.set(code, false)
codes[code] = buildWarnOpts
return codes[code]
}
function emit (code, a, b, c) {
if (codes[code] === undefined) throw new Error(`The code '${code}' does not exist`)
if (emitted.get(code) === true) return
emitted.set(code, true)
const warning = codes[code](a, b, c)
process.emitWarning(warning.message, warning.name, warning.code)
}
return {
create,
emit,
emitted
}
}
module.exports = build
+14
View File
@@ -0,0 +1,14 @@
import { expectType } from 'tsd'
import Warinig, { BuildWarnOptsFn, WarnOpts } from './'
const warning = Warinig()
const buildWarnOpts = warning.create('FastifyWarning', 'CODE', 'message')
expectType<BuildWarnOptsFn>(buildWarnOpts)
const opts = buildWarnOpts()
expectType<WarnOpts>(opts)
expectType<string>(opts.code)
expectType<string>(opts.message)
expectType<string>(opts.name)
expectType<void>(warning.emit('CODE'))
expectType<Map<string, boolean>>(warning.emitted)
+20
View File
@@ -0,0 +1,20 @@
/* global test, expect */
'use strict'
const build = require('./')
test('works with jest', done => {
const { create, emit, emitted } = build()
create('FastifyDeprecation', 'CODE', 'Hello %s')
emit('CODE', 'world')
// we cannot actually listen to process warning event
// because jest messes with it (that's the point of this test)
// we can only test it was emitted indirectly
// and test no exception is raised
setImmediate(() => {
expect(emitted.get('CODE')).toBeTruthy()
done()
})
})
+35
View File
@@ -0,0 +1,35 @@
{
"name": "process-warning",
"version": "1.0.0",
"description": "A small utility for creating warnings and emitting them.",
"main": "index.js",
"types": "index.d.ts",
"scripts": {
"test": "standard && ava -v test.js && jest jest.test.js && tsd"
},
"repository": {
"type": "git",
"url": "git+https://github.com/fastify/processs-warning.git"
},
"keywords": [
"fastify",
"error",
"warning",
"utility",
"plugin",
"emit",
"once"
],
"author": "Tomas Della Vedova",
"license": "MIT",
"bugs": {
"url": "https://github.com/fastify/fastify-warning/issues"
},
"homepage": "https://github.com/fastify/fastify-warning#readme",
"devDependencies": {
"ava": "^3.10.1",
"jest": "^27.0.1",
"standard": "^16.0.3",
"tsd": "^0.19.0"
}
}
+122
View File
@@ -0,0 +1,122 @@
'use strict'
const test = require('ava')
const build = require('./')
process.removeAllListeners('warning')
test('Create warning with zero parameter', t => {
const { create } = build()
const buildWarnOpts = create('FastifyWarning', 'CODE', 'Not available')
const opts = buildWarnOpts()
t.is(opts.name, 'FastifyWarning')
t.is(opts.message, 'Not available')
t.is(opts.code, 'CODE')
})
test('Create error with 1 parameter', t => {
const { create } = build()
const buildWarningOpts = create('FastifyWarning', 'CODE', 'hey %s')
const opts = buildWarningOpts('alice')
t.is(opts.name, 'FastifyWarning')
t.is(opts.message, 'hey alice')
t.is(opts.code, 'CODE')
})
test('Create error with 2 parameters', t => {
const { create } = build()
const buildWarnOpts = create('FastifyWarning', 'CODE', 'hey %s, I like your %s')
const opts = buildWarnOpts('alice', 'attitude')
t.is(opts.name, 'FastifyWarning')
t.is(opts.message, 'hey alice, I like your attitude')
t.is(opts.code, 'CODE')
})
test('Create error with 3 parameters', t => {
const { create } = build()
const buildWarnOpts = create('FastifyWarning', 'CODE', 'hey %s, I like your %s %s')
const opts = buildWarnOpts('alice', 'attitude', 'see you')
t.is(opts.name, 'FastifyWarning')
t.is(opts.message, 'hey alice, I like your attitude see you')
t.is(opts.code, 'CODE')
})
test('Should throw when error code has no fastify name', t => {
const { create } = build()
try {
create()
} catch (err) {
t.is(err.message, 'Warning name must not be empty')
}
})
test('Should throw when error has no code', t => {
const { create } = build()
try {
create('name')
} catch (err) {
t.is(err.message, 'Warning code must not be empty')
}
})
test('Should throw when error has no message', t => {
const { create } = build()
try {
create('name', 'code')
} catch (err) {
t.is(err.message, 'Warning message must not be empty')
}
})
test.serial.cb('emit should emit a given code only once', t => {
t.plan(4)
const { create, emit, emitted } = build()
process.on('warning', onWarning)
function onWarning (warning) {
t.is(warning.name, 'FastifyDeprecation')
t.is(warning.code, 'CODE')
t.is(warning.message, 'Hello world')
t.true(emitted.get('CODE'))
}
create('FastifyDeprecation', 'CODE', 'Hello world')
emit('CODE')
emit('CODE')
setImmediate(() => {
process.removeListener('warning', onWarning)
t.end()
})
})
test.serial.cb('emit with interpolated string', t => {
t.plan(4)
const { create, emit, emitted } = build()
process.on('warning', onWarning)
function onWarning (warning) {
t.is(warning.name, 'FastifyDeprecation')
t.is(warning.code, 'CODE')
t.is(warning.message, 'Hello world')
t.true(emitted.get('CODE'))
}
create('FastifyDeprecation', 'CODE', 'Hello %s')
emit('CODE', 'world')
emit('CODE', 'world')
setImmediate(() => {
process.removeListener('warning', onWarning)
t.end()
})
})
test('Cannot reuse the same code more than once', t => {
const { create } = build()
create('FastifyWarning', 'CODE', 'Not available')
try {
create('FastifyWarning', 'CODE', 'Not available')
} catch (err) {
t.is(err.message, "The code 'CODE' already exist")
}
})