tsoa
This commit is contained in:
10
node_modules/@hapi/shot/LICENSE.md
generated
vendored
Executable file
10
node_modules/@hapi/shot/LICENSE.md
generated
vendored
Executable file
@@ -0,0 +1,10 @@
|
||||
Copyright (c) 2012-2021, Sideway Inc, and project contributors
|
||||
Copyright (c) 2012-2014, Walmart.
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||
* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
|
||||
* The names of any contributors may not be used to endorse or promote products derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS OFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
17
node_modules/@hapi/shot/README.md
generated
vendored
Executable file
17
node_modules/@hapi/shot/README.md
generated
vendored
Executable file
@@ -0,0 +1,17 @@
|
||||
<a href="https://hapi.dev"><img src="https://raw.githubusercontent.com/hapijs/assets/master/images/family.png" width="180px" align="right" /></a>
|
||||
|
||||
# @hapi/shot
|
||||
|
||||
#### Injects a fake HTTP request/response into your node server logic.
|
||||
|
||||
**shot** is part of the **hapi** ecosystem and was designed to work seamlessly with the [hapi web framework](https://hapi.dev) and its other components (but works great on its own or with other frameworks). If you are using a different web framework and find this module useful, check out [hapi](https://hapi.dev) – they work even better together.
|
||||
|
||||
### Visit the [hapi.dev](https://hapi.dev) Developer Portal for tutorials, documentation, and support
|
||||
|
||||
## Useful resources
|
||||
|
||||
- [Documentation and API](https://hapi.dev/family/shot/)
|
||||
- [Versions status](https://hapi.dev/resources/status/#shot) (builds, dependencies, node versions, licenses, eol)
|
||||
- [Changelog](https://hapi.dev/family/shot/changelog/)
|
||||
- [Project policies](https://hapi.dev/policies/)
|
||||
- [Free and commercial support options](https://hapi.dev/support/)
|
||||
186
node_modules/@hapi/shot/lib/index.d.ts
generated
vendored
Normal file
186
node_modules/@hapi/shot/lib/index.d.ts
generated
vendored
Normal file
@@ -0,0 +1,186 @@
|
||||
import { EventEmitter } from 'events';
|
||||
import {
|
||||
IncomingHttpHeaders,
|
||||
IncomingMessage,
|
||||
OutgoingHttpHeaders,
|
||||
ServerResponse
|
||||
} from 'http';
|
||||
import { Readable, Stream } from 'stream';
|
||||
import { UrlObject } from 'url';
|
||||
|
||||
interface MockSocket extends EventEmitter {
|
||||
readonly remoteAddress: string;
|
||||
end(): void;
|
||||
setTimeout(): void;
|
||||
}
|
||||
|
||||
export interface InjectedRequest extends Readonly<Readable> {
|
||||
readonly httpVersion: '1.1';
|
||||
readonly method: string;
|
||||
readonly url: string;
|
||||
readonly headers: Readonly<IncomingHttpHeaders>;
|
||||
readonly socket: MockSocket;
|
||||
readonly connection: MockSocket;
|
||||
}
|
||||
|
||||
export type MaybeInjectedRequest = InjectedRequest | IncomingMessage;
|
||||
|
||||
export interface ResponseObject {
|
||||
/**
|
||||
* An object containing the raw request and response objects.
|
||||
*/
|
||||
raw: {
|
||||
/**
|
||||
* The simulated request object.
|
||||
*/
|
||||
req: InjectedRequest;
|
||||
|
||||
/**
|
||||
* The simulated response object.
|
||||
*/
|
||||
res: ServerResponse;
|
||||
};
|
||||
|
||||
/**
|
||||
* An object containing the response headers.
|
||||
*/
|
||||
headers: OutgoingHttpHeaders;
|
||||
|
||||
/**
|
||||
* The HTTP status code. If response is aborted before headers are sent, the code is `499`.
|
||||
*/
|
||||
statusCode: number;
|
||||
|
||||
/**
|
||||
* The HTTP status message.
|
||||
*/
|
||||
statusMessage: string;
|
||||
|
||||
/**
|
||||
* The payload as a UTF-8 encoded string.
|
||||
*/
|
||||
payload: string;
|
||||
|
||||
/**
|
||||
* The raw payload as a Buffer.
|
||||
*/
|
||||
rawPayload: Buffer;
|
||||
|
||||
/**
|
||||
* An object containing the response trailers
|
||||
*/
|
||||
trailers: NodeJS.Dict<string>;
|
||||
|
||||
/**
|
||||
* A boolean which is `true` for aborted, ie. not fully transmitted, responses.
|
||||
*/
|
||||
aborted?: true;
|
||||
}
|
||||
|
||||
type PartialURL = Pick<UrlObject, 'protocol' | 'hostname' | 'port' | 'query'> & { pathname: string };
|
||||
|
||||
export interface RequestOptions {
|
||||
|
||||
/**
|
||||
* The request URL.
|
||||
*/
|
||||
url: string | PartialURL;
|
||||
|
||||
/**
|
||||
* The HTTP request method.
|
||||
*
|
||||
* @default 'GET'
|
||||
*/
|
||||
method?: string;
|
||||
|
||||
/**
|
||||
* The HTTP HOST header value to be used if no header is provided,
|
||||
* and the url does not include an authority component.
|
||||
*
|
||||
* @default 'localhost'
|
||||
*/
|
||||
authority?: string;
|
||||
|
||||
/**
|
||||
* The request headers.
|
||||
*/
|
||||
headers?: OutgoingHttpHeaders;
|
||||
|
||||
/**
|
||||
* The client remote address.
|
||||
*
|
||||
* @default '127.0.0.1'
|
||||
*/
|
||||
remoteAddress?: string;
|
||||
|
||||
/**
|
||||
* A request payload. Can be a string, Buffer, Stream or object that will be stringified.
|
||||
*/
|
||||
payload?: string | Buffer | Stream | object;
|
||||
|
||||
/**
|
||||
* an object containing flags to simulate various conditions:
|
||||
*/
|
||||
simulate?: {
|
||||
|
||||
/**
|
||||
* indicates whether the request will fire an end event.
|
||||
*
|
||||
* @default true
|
||||
*/
|
||||
end?: boolean;
|
||||
|
||||
/**
|
||||
* indicates whether the request payload will be split into chunks.
|
||||
*
|
||||
* @default false
|
||||
*/
|
||||
split?: boolean;
|
||||
|
||||
/**
|
||||
* whether the request will emit an error event.
|
||||
* If set to true, the emitted error will have a message of 'Simulated'.
|
||||
*
|
||||
* @default false
|
||||
*/
|
||||
error?: boolean;
|
||||
|
||||
/**
|
||||
* whether the request will emit a close event.
|
||||
*
|
||||
* @default true
|
||||
*/
|
||||
close?: boolean;
|
||||
};
|
||||
|
||||
/**
|
||||
* Optional flag to validate this options object.
|
||||
*
|
||||
* @default true
|
||||
*/
|
||||
validate?: boolean;
|
||||
}
|
||||
|
||||
type InjectionListener = (req: InjectedRequest, res: ServerResponse) => void;
|
||||
|
||||
type MaybeInjectionListener = (req: MaybeInjectedRequest, res: ServerResponse) => void;
|
||||
|
||||
/**
|
||||
* Injects a fake request into an HTTP server.
|
||||
*
|
||||
* @param dispatchFunc - Listener function. Similar as you would pass to Http.createServer when making a node HTTP server.
|
||||
* @param options - Request options object or string with request url.
|
||||
*
|
||||
* @return A Promise that resolves with a ResponseObject object
|
||||
*/
|
||||
export function inject(dispatchFunc: InjectionListener, options: RequestOptions | string): Promise<ResponseObject>;
|
||||
export function inject(dispatchFunc: MaybeInjectionListener, options: RequestOptions | string): Promise<ResponseObject>;
|
||||
|
||||
/**
|
||||
* Checks if given object is a Shot Request object.
|
||||
*
|
||||
* @param obj - the req or res object to test
|
||||
*
|
||||
* @return true if the object is a shot request, otherwise false.
|
||||
*/
|
||||
export function isInjection(obj: MaybeInjectedRequest | ServerResponse): boolean;
|
||||
63
node_modules/@hapi/shot/lib/index.js
generated
vendored
Executable file
63
node_modules/@hapi/shot/lib/index.js
generated
vendored
Executable file
@@ -0,0 +1,63 @@
|
||||
'use strict';
|
||||
|
||||
const Hoek = require('@hapi/hoek');
|
||||
const Validate = require('@hapi/validate');
|
||||
|
||||
const Request = require('./request');
|
||||
const Response = require('./response');
|
||||
const Symbols = require('./symbols');
|
||||
|
||||
|
||||
const internals = {};
|
||||
|
||||
|
||||
internals.options = Validate.object().keys({
|
||||
url: Validate.alternatives([
|
||||
Validate.string(),
|
||||
Validate.object().keys({
|
||||
protocol: Validate.string(),
|
||||
hostname: Validate.string(),
|
||||
port: Validate.any(),
|
||||
pathname: Validate.string().required(),
|
||||
query: Validate.any()
|
||||
})
|
||||
])
|
||||
.required(),
|
||||
headers: Validate.object(),
|
||||
payload: Validate.any(),
|
||||
simulate: {
|
||||
end: Validate.boolean(),
|
||||
split: Validate.boolean(),
|
||||
error: Validate.boolean(),
|
||||
close: Validate.boolean()
|
||||
},
|
||||
authority: Validate.string(),
|
||||
remoteAddress: Validate.string(),
|
||||
method: Validate.string(),
|
||||
validate: Validate.boolean()
|
||||
});
|
||||
|
||||
|
||||
exports.inject = async function (dispatchFunc, options) { // eslint-disable-line require-await
|
||||
|
||||
options = (typeof options === 'string' ? { url: options } : options);
|
||||
|
||||
if (options?.validate !== false) { // Defaults to true
|
||||
Hoek.assert(typeof dispatchFunc === 'function', 'Invalid or missing dispatch function');
|
||||
Validate.assert(options ?? null, internals.options, 'Invalid options:');
|
||||
}
|
||||
|
||||
return new Promise((resolve) => {
|
||||
|
||||
const req = new Request(options);
|
||||
const res = new Response(req, resolve);
|
||||
|
||||
req.prepare(() => dispatchFunc(req, res));
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
exports.isInjection = function (obj) {
|
||||
|
||||
return !!obj[Symbols.injection];
|
||||
};
|
||||
168
node_modules/@hapi/shot/lib/request.js
generated
vendored
Executable file
168
node_modules/@hapi/shot/lib/request.js
generated
vendored
Executable file
@@ -0,0 +1,168 @@
|
||||
'use strict';
|
||||
|
||||
const Events = require('events');
|
||||
const Stream = require('stream');
|
||||
const Url = require('url');
|
||||
|
||||
const Symbols = require('./symbols');
|
||||
|
||||
|
||||
const internals = {};
|
||||
|
||||
|
||||
exports = module.exports = internals.Request = class extends Stream.Readable {
|
||||
|
||||
constructor(options) {
|
||||
|
||||
super({
|
||||
emitClose: !!(options.simulate?.close),
|
||||
autoDestroy: true // This is the default in node 14+
|
||||
});
|
||||
|
||||
// options: method, url, payload, headers, remoteAddress
|
||||
|
||||
let url = options.url;
|
||||
if (typeof url === 'object') {
|
||||
url = Url.format(url);
|
||||
}
|
||||
|
||||
const uri = Url.parse(url);
|
||||
this.url = uri.path;
|
||||
|
||||
this.httpVersion = '1.1';
|
||||
this.method = (options.method ? options.method.toUpperCase() : 'GET');
|
||||
|
||||
this.headers = {};
|
||||
const headers = options.headers ?? {};
|
||||
const fields = Object.keys(headers);
|
||||
fields.forEach((field) => {
|
||||
|
||||
this.headers[field.toLowerCase()] = headers[field];
|
||||
});
|
||||
|
||||
this.headers['user-agent'] = this.headers['user-agent'] ?? 'shot';
|
||||
|
||||
const hostHeaderFromUri = function () {
|
||||
|
||||
if (uri.port) {
|
||||
return uri.host;
|
||||
}
|
||||
|
||||
if (uri.protocol) {
|
||||
return uri.hostname + (uri.protocol === 'https:' ? ':443' : ':80');
|
||||
}
|
||||
|
||||
return null;
|
||||
};
|
||||
|
||||
this.headers.host = this.headers.host ?? hostHeaderFromUri() ?? options.authority ?? 'localhost:80';
|
||||
|
||||
// NOTE connection is deprecated in favor of socket as of node v13
|
||||
|
||||
this.socket = this.connection = new internals.MockSocket(options);
|
||||
|
||||
let payload = options.payload ?? null;
|
||||
if (payload &&
|
||||
typeof payload !== 'string' &&
|
||||
!(payload instanceof Stream) &&
|
||||
!Buffer.isBuffer(payload)) {
|
||||
|
||||
payload = JSON.stringify(payload);
|
||||
this.headers['content-type'] = this.headers['content-type'] || 'application/json';
|
||||
}
|
||||
|
||||
// Set the content-length for the corresponding payload if none set
|
||||
|
||||
if (payload &&
|
||||
!(payload instanceof Stream) &&
|
||||
!this.headers.hasOwnProperty('content-length')) {
|
||||
|
||||
this.headers['content-length'] = (Buffer.isBuffer(payload) ? payload.length : Buffer.byteLength(payload)).toString();
|
||||
}
|
||||
|
||||
// Use _shot namespace to avoid collision with Node
|
||||
|
||||
this._shot = {
|
||||
payload,
|
||||
isDone: false,
|
||||
simulate: options.simulate ?? {}
|
||||
};
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
prepare(next) {
|
||||
|
||||
if (this._shot.payload instanceof Stream === false) {
|
||||
return next();
|
||||
}
|
||||
|
||||
const chunks = [];
|
||||
|
||||
this._shot.payload.on('data', (chunk) => chunks.push(Buffer.from(chunk)));
|
||||
|
||||
this._shot.payload.on('end', () => {
|
||||
|
||||
const payload = Buffer.concat(chunks);
|
||||
this.headers['content-length'] = this.headers['content-length'] || payload.length;
|
||||
this._shot.payload = payload;
|
||||
return next();
|
||||
});
|
||||
}
|
||||
|
||||
_read(size) {
|
||||
|
||||
setImmediate(() => {
|
||||
|
||||
if (this._shot.isDone) {
|
||||
/* $lab:coverage:off$ */
|
||||
if (this._shot.simulate.end !== false) { // 'end' defaults to true
|
||||
this.push(null);
|
||||
}
|
||||
/* $lab:coverage:on$ */
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
this._shot.isDone = true;
|
||||
|
||||
if (this._shot.payload) {
|
||||
if (this._shot.simulate.split) {
|
||||
this.push(this._shot.payload.slice(0, 1));
|
||||
this.push(this._shot.payload.slice(1));
|
||||
}
|
||||
else {
|
||||
this.push(this._shot.payload);
|
||||
}
|
||||
}
|
||||
|
||||
if (this._shot.simulate.error) {
|
||||
this.destroy(new Error('Simulated'));
|
||||
}
|
||||
else if (this._shot.simulate.end !== false) { // 'end' defaults to true
|
||||
this.push(null);
|
||||
}
|
||||
else if (this._shot.simulate.close) { // manually close (out of spec)
|
||||
this.emit('close');
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
internals.Request.prototype[Symbols.injection] = true;
|
||||
|
||||
internals.MockSocket = class MockSocket extends Events.EventEmitter {
|
||||
|
||||
constructor({ remoteAddress }) {
|
||||
|
||||
super();
|
||||
|
||||
this.remoteAddress = remoteAddress ?? '127.0.0.1';
|
||||
}
|
||||
|
||||
// Net.Socket APIs used by hapi
|
||||
|
||||
end() {}
|
||||
setTimeout() {}
|
||||
};
|
||||
162
node_modules/@hapi/shot/lib/response.js
generated
vendored
Executable file
162
node_modules/@hapi/shot/lib/response.js
generated
vendored
Executable file
@@ -0,0 +1,162 @@
|
||||
'use strict';
|
||||
|
||||
const Http = require('http');
|
||||
const Stream = require('stream');
|
||||
|
||||
const Hoek = require('@hapi/hoek');
|
||||
|
||||
const Symbols = require('./symbols');
|
||||
|
||||
|
||||
const internals = {};
|
||||
|
||||
|
||||
exports = module.exports = internals.Response = class extends Http.ServerResponse {
|
||||
|
||||
constructor(req, onEnd) {
|
||||
|
||||
super({ method: req.method, httpVersionMajor: 1, httpVersionMinor: 1 });
|
||||
this._shot = { headers: null, trailers: {}, payloadChunks: [] };
|
||||
this.assignSocket(internals.nullSocket());
|
||||
|
||||
this.socket.on('error', Hoek.ignore); // The socket can be destroyed with an error
|
||||
|
||||
if (req._shot.simulate.close) {
|
||||
// Ensure premature, manual close is forwarded to res.
|
||||
// In HttpServer the socket closing actually triggers close on both req and res.
|
||||
req.once('close', () => {
|
||||
|
||||
process.nextTick(() => this.destroy());
|
||||
});
|
||||
}
|
||||
|
||||
const finalize = (aborted) => {
|
||||
|
||||
const res = internals.payload(this);
|
||||
res.raw.req = req;
|
||||
if (aborted) {
|
||||
res.aborted = aborted;
|
||||
if (!this.headersSent) {
|
||||
res.statusCode = 499;
|
||||
}
|
||||
}
|
||||
|
||||
this.removeListener('close', abort);
|
||||
|
||||
process.nextTick(() => onEnd(res));
|
||||
};
|
||||
|
||||
const abort = () => finalize(true);
|
||||
|
||||
this.once('finish', finalize);
|
||||
|
||||
// Add fallback listener that will not be called if 'finish' is emitted first
|
||||
|
||||
this.on('close', abort);
|
||||
}
|
||||
|
||||
writeHead(...args) {
|
||||
|
||||
// Find the headers object if one was provided. If a headers object is present, call setHeader()
|
||||
// on the first valid header, and then break out of the loop and call writeHead(). By calling
|
||||
// setHeader(), Node will materialize a headers object.
|
||||
|
||||
const headers = args[args.length - 1];
|
||||
|
||||
if (typeof headers === 'object' && headers !== null) {
|
||||
const headerNames = Object.keys(headers);
|
||||
|
||||
for (let i = 0; i < headerNames.length; ++i) {
|
||||
const name = headerNames[i];
|
||||
|
||||
try {
|
||||
this.setHeader(name, headers[name]);
|
||||
break;
|
||||
}
|
||||
catch (ignoreErr) {} // Let the real writeHead() handle errors.
|
||||
}
|
||||
}
|
||||
|
||||
const result = super.writeHead(...args);
|
||||
|
||||
this._shot.headers = this.getHeaders();
|
||||
|
||||
// Add raw headers
|
||||
|
||||
['Date', 'Connection', 'Transfer-Encoding'].forEach((name) => {
|
||||
|
||||
const regex = new RegExp('\\r\\n' + name + ': ([^\\r]*)\\r\\n');
|
||||
const field = this._header.match(regex);
|
||||
if (field) {
|
||||
this._shot.headers[name.toLowerCase()] = field[1];
|
||||
}
|
||||
});
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
write(data, encoding, callback) {
|
||||
|
||||
super.write(data, encoding, callback);
|
||||
this._shot.payloadChunks.push(Buffer.from(data, encoding));
|
||||
return true; // Write always returns false when disconnected
|
||||
}
|
||||
|
||||
end(data, encoding, callback) {
|
||||
|
||||
if (data) {
|
||||
this.write(data, encoding);
|
||||
}
|
||||
|
||||
super.end(callback);
|
||||
this.emit('finish');
|
||||
}
|
||||
|
||||
addTrailers(trailers) {
|
||||
|
||||
for (const key in trailers) {
|
||||
this._shot.trailers[key.toLowerCase().trim()] = trailers[key].toString().trim();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
internals.Response.prototype[Symbols.injection] = true;
|
||||
|
||||
|
||||
internals.payload = function (response) {
|
||||
|
||||
// Prepare response object
|
||||
|
||||
const res = {
|
||||
raw: {
|
||||
res: response
|
||||
},
|
||||
headers: response._shot.headers,
|
||||
statusCode: response.statusCode,
|
||||
statusMessage: response.statusMessage,
|
||||
trailers: {}
|
||||
};
|
||||
|
||||
// Prepare payload and trailers
|
||||
|
||||
const rawBuffer = Buffer.concat(response._shot.payloadChunks);
|
||||
res.rawPayload = rawBuffer;
|
||||
res.payload = rawBuffer.toString();
|
||||
res.trailers = response._shot.trailers;
|
||||
|
||||
return res;
|
||||
};
|
||||
|
||||
|
||||
// Throws away all written data to prevent response from buffering payload
|
||||
|
||||
internals.nullSocket = function () {
|
||||
|
||||
return new Stream.Writable({
|
||||
write(chunk, encoding, callback) {
|
||||
|
||||
setImmediate(callback);
|
||||
}
|
||||
});
|
||||
};
|
||||
6
node_modules/@hapi/shot/lib/symbols.js
generated
vendored
Executable file
6
node_modules/@hapi/shot/lib/symbols.js
generated
vendored
Executable file
@@ -0,0 +1,6 @@
|
||||
'use strict';
|
||||
|
||||
const internals = {};
|
||||
|
||||
|
||||
exports.injection = Symbol('injection');
|
||||
38
node_modules/@hapi/shot/package.json
generated
vendored
Normal file
38
node_modules/@hapi/shot/package.json
generated
vendored
Normal file
@@ -0,0 +1,38 @@
|
||||
{
|
||||
"name": "@hapi/shot",
|
||||
"description": "Injects a fake HTTP request/response into a node HTTP server",
|
||||
"version": "6.0.2",
|
||||
"repository": "git://github.com/hapijs/shot",
|
||||
"main": "lib/index.js",
|
||||
"types": "lib/index.d.ts",
|
||||
"files": [
|
||||
"lib"
|
||||
],
|
||||
"keywords": [
|
||||
"utilities",
|
||||
"http",
|
||||
"debug",
|
||||
"test"
|
||||
],
|
||||
"eslintConfig": {
|
||||
"extends": [
|
||||
"plugin:@hapi/module"
|
||||
]
|
||||
},
|
||||
"dependencies": {
|
||||
"@hapi/hoek": "^11.0.2",
|
||||
"@hapi/validate": "^2.0.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@hapi/code": "^9.0.3",
|
||||
"@hapi/eslint-plugin": "^6.0.0",
|
||||
"@hapi/lab": "^25.1.2",
|
||||
"@types/node": "^17.0.31",
|
||||
"typescript": "~4.6.4"
|
||||
},
|
||||
"scripts": {
|
||||
"test": "lab -a @hapi/code -t 100 -L -Y",
|
||||
"test-cov-html": "lab -a @hapi/code -r html -o coverage.html -L"
|
||||
},
|
||||
"license": "BSD-3-Clause"
|
||||
}
|
||||
Reference in New Issue
Block a user