feat(reporter-pino): first version of the package

This commit is contained in:
Joakim Carlstein 2023-12-07 14:36:30 +01:00
parent d916043061
commit 3619d86750
6 changed files with 433 additions and 0 deletions

View file

@ -0,0 +1,5 @@
---
'@emigrate/reporter-pino': minor
---
Implement the first version of the Pino reporter package

View file

@ -0,0 +1,64 @@
# @emigrate/reporter-pino
A [Pino](https://getpino.io/#/) reporter for Emigrate which logs the migration progress using line delimited JSON by default.
Which is great both in production environments and for piping the output to other tools.
## Installation
Install the reporter in your project, alongside the Emigrate CLI:
```bash
npm install --save-dev @emigrate/cli @emigrate/reporter-pino
```
## Usage
### With default options
Configure the reporter in your `emigrate.config.js` file:
```js
import reporterPino from '@emigrate/reporter-pino';
export default {
directory: 'migrations',
reporter: reporterPino,
};
```
Or simply:
```js
export default {
directory: 'migrations',
reporter: 'pino', // the @emigrate/reporter- prefix is optional
};
```
Or use the CLI option `--reporter` (or `-r`):
```bash
emigrate up --reporter pino # the @emigrate/reporter- prefix is optional
```
### With custom options
Configure the reporter in your `emigrate.config.js` file:
```js
import { createPinoReporter } from '@emigrate/reporter-pino';
export default {
directory: 'migrations',
reporter: createPinoReporter({
level: 'error', // default is 'info'
errorKey: 'err', // default is 'error'
}),
};
```
The log level can also be set using the `LOG_LEVEL` environment variable:
```bash
LOG_LEVEL=error emigrate up -r pino
```

View file

@ -0,0 +1,47 @@
{
"name": "@emigrate/reporter-pino",
"version": "0.0.0",
"publishConfig": {
"access": "public"
},
"description": "A Pino reporter for Emigrate for logging the migration process.",
"main": "dist/index.js",
"types": "dist/index.d.js",
"type": "module",
"exports": {
".": {
"import": "./dist/index.js",
"types": "./dist/index.d.ts"
}
},
"files": [
"dist"
],
"scripts": {
"build": "tsc --pretty",
"build:watch": "tsc --pretty --watch",
"lint": "xo --cwd=../.. $(pwd)"
},
"keywords": [
"emigrate",
"emigrate-reporter",
"plugin",
"migrations",
"reporter"
],
"author": "Aboviq AB <dev@aboviq.com> (https://www.aboviq.com)",
"homepage": "https://github.com/aboviq/emigrate/tree/main/packages/reporter-pino#readme",
"repository": "https://github.com/aboviq/emigrate/tree/main/packages/reporter-pino",
"bugs": "https://github.com/aboviq/emigrate/issues",
"license": "MIT",
"dependencies": {
"@emigrate/plugin-tools": "workspace:*",
"pino": "8.16.2"
},
"devDependencies": {
"@emigrate/tsconfig": "workspace:*"
},
"volta": {
"extends": "../../package.json"
}
}

View file

@ -0,0 +1,180 @@
import process from 'node:process';
import { pino, levels, type Logger } from 'pino';
import {
type Awaitable,
type MigrationMetadata,
type MigrationMetadataFinished,
type ReporterInitParameters,
type EmigrateReporter,
} from '@emigrate/plugin-tools/types';
type PinoReporterOptions = {
level?: string;
/**
* Customize the key used for logging errors
*
* @default 'error'
* @see https://getpino.io/#/docs/api?id=errorkey-string
*/
errorKey?: string;
};
class PinoReporter implements Required<EmigrateReporter> {
#logger!: Logger;
#migrations?: MigrationMetadata[];
#command!: ReporterInitParameters['command'];
constructor(private readonly options: PinoReporterOptions) {
if (!options.level || !levels.values[options.level]) {
options.level = 'info';
}
}
get logLevel(): string {
if (this.options.level && levels.values[this.options.level]) {
return this.options.level;
}
return 'info';
}
get errorKey(): string {
return this.options.errorKey ?? 'error';
}
onInit({ command, ...parameters }: ReporterInitParameters): Awaitable<void> {
this.#command = command;
this.#logger = pino({
name: 'emigrate',
level: this.logLevel,
errorKey: this.errorKey,
base: {
scope: command,
},
});
this.#logger.info({ parameters }, `Emigrate "${command}" initialized${parameters.dry ? ' (dry-run)' : ''}`);
}
onCollectedMigrations(migrations: MigrationMetadata[]): Awaitable<void> {
this.#migrations = migrations;
}
onLockedMigrations(lockedMigrations: MigrationMetadata[]): Awaitable<void> {
const migrations = this.#migrations ?? [];
if (migrations.length === 0) {
this.#logger.info('No pending migrations found');
return;
}
if (migrations.length === lockedMigrations.length) {
this.#logger.info(
{ migrationCount: lockedMigrations.length },
`${lockedMigrations.length} pending migrations to run`,
);
return;
}
const nonLockedMigrations = migrations.filter(
(migration) => !lockedMigrations.some((lockedMigration) => lockedMigration.name === migration.name),
);
const failedMigrations = nonLockedMigrations.filter(
(migration) => 'status' in migration && migration.status === 'failed',
);
const unlockableCount = nonLockedMigrations.length - failedMigrations.length;
const parts = [
`${lockedMigrations.length} of ${migrations.length} pending migrations to run`,
unlockableCount > 0 ? `(${unlockableCount} locked)` : '',
failedMigrations.length > 0 ? `(${failedMigrations.length} failed)` : '',
].filter(Boolean);
this.#logger.info({ migrationCount: lockedMigrations.length }, parts.join(' '));
}
onNewMigration(migration: MigrationMetadata, content: string): Awaitable<void> {
this.#logger.info({ migration, content }, `Created new migration file: ${migration.name}`);
}
onMigrationRemoveStart(migration: MigrationMetadata): Awaitable<void> {
this.#logger.debug({ migration }, `Removing migration: ${migration.name}`);
}
onMigrationRemoveSuccess(migration: MigrationMetadataFinished): Awaitable<void> {
this.#logger.info({ migration }, `Successfully removed migration: ${migration.name}`);
}
onMigrationRemoveError(migration: MigrationMetadataFinished, error: Error): Awaitable<void> {
this.#logger.error({ migration, [this.errorKey]: error }, `Failed to remove migration: ${migration.name}`);
}
onMigrationStart(migration: MigrationMetadata): Awaitable<void> {
this.#logger.info({ migration }, `${migration.name} (running)`);
}
onMigrationSuccess(migration: MigrationMetadataFinished): Awaitable<void> {
this.#logger.info({ migration }, `${migration.name} (${migration.status})`);
}
onMigrationError(migration: MigrationMetadataFinished, error: Error): Awaitable<void> {
this.#logger.error({ migration, [this.errorKey]: error }, `${migration.name} (${migration.status})`);
}
onMigrationSkip(migration: MigrationMetadataFinished): Awaitable<void> {
this.#logger.info({ migration }, `${migration.name} (${migration.status})`);
}
onFinished(migrations: MigrationMetadataFinished[], error?: Error | undefined): Awaitable<void> {
const total = migrations.length;
let done = 0;
let failed = 0;
let skipped = 0;
let pending = 0;
for (const migration of migrations) {
const status = 'status' in migration ? migration.status : undefined;
switch (status) {
case 'done': {
done++;
break;
}
case 'failed': {
failed++;
break;
}
case 'skipped': {
skipped++;
break;
}
case 'pending': {
pending++;
break;
}
default: {
break;
}
}
}
if (error) {
this.#logger.error(
{ failed, done, skipped, pending, total, [this.errorKey]: error },
`Emigrate "${this.#command}" failed`,
);
} else {
this.#logger.info({ failed, done, skipped, pending, total }, `Emigrate "${this.#command}" finished successfully`);
}
}
}
export const createPinoReporter = (options: PinoReporterOptions = {}): EmigrateReporter => {
return new PinoReporter(options);
};
export default createPinoReporter({
level: process.env['LOG_LEVEL'],
});

View file

@ -0,0 +1,8 @@
{
"extends": "@emigrate/tsconfig/build.json",
"compilerOptions": {
"outDir": "dist"
},
"include": ["src"],
"exclude": ["node_modules", "dist"]
}

129
pnpm-lock.yaml generated
View file

@ -102,6 +102,19 @@ importers:
specifier: workspace:* specifier: workspace:*
version: link:../tsconfig version: link:../tsconfig
packages/reporter-pino:
dependencies:
'@emigrate/plugin-tools':
specifier: workspace:*
version: link:../plugin-tools
pino:
specifier: 8.16.2
version: 8.16.2
devDependencies:
'@emigrate/tsconfig':
specifier: workspace:*
version: link:../tsconfig
packages/storage-fs: packages/storage-fs:
dependencies: dependencies:
'@emigrate/plugin-tools': '@emigrate/plugin-tools':
@ -1254,6 +1267,13 @@ packages:
through: 2.3.8 through: 2.3.8
dev: false dev: false
/abort-controller@3.0.0:
resolution: {integrity: sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==}
engines: {node: '>=6.5'}
dependencies:
event-target-shim: 5.0.1
dev: false
/acorn-import-assertions@1.9.0(acorn@8.11.2): /acorn-import-assertions@1.9.0(acorn@8.11.2):
resolution: {integrity: sha512-cmMwop9x+8KFhxvKrKfPYmN6/pKTYYHBqLa0DfvVZcKMJWNyWLnaqND7dx/qn66R7ewM1UX5XMaDVP5wlVTaVA==} resolution: {integrity: sha512-cmMwop9x+8KFhxvKrKfPYmN6/pKTYYHBqLa0DfvVZcKMJWNyWLnaqND7dx/qn66R7ewM1UX5XMaDVP5wlVTaVA==}
peerDependencies: peerDependencies:
@ -1451,6 +1471,11 @@ packages:
engines: {node: '>=12'} engines: {node: '>=12'}
dev: false dev: false
/atomic-sleep@1.0.0:
resolution: {integrity: sha512-kNOjDqAh7px0XWNI+4QbzoiR/nTkHAWNud2uvnJquD1/x5a7EQZMJT0AczqK0Qn67oY/TTQ1LbUKajZpp3I9tQ==}
engines: {node: '>=8.0.0'}
dev: false
/available-typed-arrays@1.0.5: /available-typed-arrays@1.0.5:
resolution: {integrity: sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==} resolution: {integrity: sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==}
engines: {node: '>= 0.4'} engines: {node: '>= 0.4'}
@ -1460,6 +1485,10 @@ packages:
resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==}
dev: false dev: false
/base64-js@1.5.1:
resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==}
dev: false
/better-path-resolve@1.0.0: /better-path-resolve@1.0.0:
resolution: {integrity: sha512-pbnl5XzGBdrFU/wT4jqmJVPn2B6UHPBOhzMQkY/SPUPB6QtUXtmBHBIwCbXJol93mOpGMnQyP/+BB19q04xj7g==} resolution: {integrity: sha512-pbnl5XzGBdrFU/wT4jqmJVPn2B6UHPBOhzMQkY/SPUPB6QtUXtmBHBIwCbXJol93mOpGMnQyP/+BB19q04xj7g==}
engines: {node: '>=4'} engines: {node: '>=4'}
@ -1520,6 +1549,13 @@ packages:
resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==} resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==}
dev: false dev: false
/buffer@6.0.3:
resolution: {integrity: sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==}
dependencies:
base64-js: 1.5.1
ieee754: 1.2.1
dev: false
/builtin-modules@3.3.0: /builtin-modules@3.3.0:
resolution: {integrity: sha512-zhaCDicdLuWN5UbN5IMnFqNMhNfo919sH85y2/ea+5Yg9TsTkeZxpL+JLbp6cgYFS4sRLp3YV4S6yDuqVWHYOw==} resolution: {integrity: sha512-zhaCDicdLuWN5UbN5IMnFqNMhNfo919sH85y2/ea+5Yg9TsTkeZxpL+JLbp6cgYFS4sRLp3YV4S6yDuqVWHYOw==}
engines: {node: '>=6'} engines: {node: '>=6'}
@ -2571,6 +2607,11 @@ packages:
engines: {node: '>=0.10.0'} engines: {node: '>=0.10.0'}
dev: false dev: false
/event-target-shim@5.0.1:
resolution: {integrity: sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==}
engines: {node: '>=6'}
dev: false
/eventemitter3@5.0.1: /eventemitter3@5.0.1:
resolution: {integrity: sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==} resolution: {integrity: sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==}
dev: false dev: false
@ -2665,6 +2706,11 @@ packages:
resolution: {integrity: sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==} resolution: {integrity: sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==}
dev: false dev: false
/fast-redact@3.3.0:
resolution: {integrity: sha512-6T5V1QK1u4oF+ATxs1lWUmlEk6P2T9HqJG3e2DnHOdVgZy2rFJBoEnrIedcTXlkAHU/zKC+7KETJ+KGGKwxgMQ==}
engines: {node: '>=6'}
dev: false
/fastq@1.15.0: /fastq@1.15.0:
resolution: {integrity: sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==} resolution: {integrity: sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==}
dependencies: dependencies:
@ -3121,6 +3167,10 @@ packages:
safer-buffer: 2.1.2 safer-buffer: 2.1.2
dev: false dev: false
/ieee754@1.2.1:
resolution: {integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==}
dev: false
/ignore@5.2.4: /ignore@5.2.4:
resolution: {integrity: sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==} resolution: {integrity: sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==}
engines: {node: '>= 4'} engines: {node: '>= 4'}
@ -4092,6 +4142,11 @@ packages:
es-abstract: 1.22.3 es-abstract: 1.22.3
dev: false dev: false
/on-exit-leak-free@2.1.2:
resolution: {integrity: sha512-0eJJY6hXLGf1udHwfNftBqH+g73EU4B504nZeKpz1sYRKafAghwxEJunB2O7rDZkL4PGfsMVnTXZ2EjibbqcsA==}
engines: {node: '>=14.0.0'}
dev: false
/once@1.4.0: /once@1.4.0:
resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==}
dependencies: dependencies:
@ -4357,6 +4412,34 @@ packages:
engines: {node: '>=6'} engines: {node: '>=6'}
dev: false dev: false
/pino-abstract-transport@1.1.0:
resolution: {integrity: sha512-lsleG3/2a/JIWUtf9Q5gUNErBqwIu1tUKTT3dUzaf5DySw9ra1wcqKjJjLX1VTY64Wk1eEOYsVGSaGfCK85ekA==}
dependencies:
readable-stream: 4.4.2
split2: 4.2.0
dev: false
/pino-std-serializers@6.2.2:
resolution: {integrity: sha512-cHjPPsE+vhj/tnhCy/wiMh3M3z3h/j15zHQX+S9GkTBgqJuTuJzYJ4gUyACLhDaJ7kk9ba9iRDmbH2tJU03OiA==}
dev: false
/pino@8.16.2:
resolution: {integrity: sha512-2advCDGVEvkKu9TTVSa/kWW7Z3htI/sBKEZpqiHk6ive0i/7f5b1rsU8jn0aimxqfnSz5bj/nOYkwhBUn5xxvg==}
hasBin: true
dependencies:
atomic-sleep: 1.0.0
fast-redact: 3.3.0
on-exit-leak-free: 2.1.2
pino-abstract-transport: 1.1.0
pino-std-serializers: 6.2.2
process-warning: 2.3.2
quick-format-unescaped: 4.0.4
real-require: 0.2.0
safe-stable-stringify: 2.4.3
sonic-boom: 3.7.0
thread-stream: 2.4.1
dev: false
/pkg-dir@4.2.0: /pkg-dir@4.2.0:
resolution: {integrity: sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==} resolution: {integrity: sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==}
engines: {node: '>=8'} engines: {node: '>=8'}
@ -4436,6 +4519,15 @@ packages:
parse-ms: 3.0.0 parse-ms: 3.0.0
dev: false dev: false
/process-warning@2.3.2:
resolution: {integrity: sha512-n9wh8tvBe5sFmsqlg+XQhaQLumwpqoAUruLwjCopgTmUBjJ/fjtBsJzKleCaIGBOMXYEhp1YfKl4d7rJ5ZKJGA==}
dev: false
/process@0.11.10:
resolution: {integrity: sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==}
engines: {node: '>= 0.6.0'}
dev: false
/proto-props@2.0.0: /proto-props@2.0.0:
resolution: {integrity: sha512-2yma2tog9VaRZY2mn3Wq51uiSW4NcPYT1cQdBagwyrznrilKSZwIZ0UG3ZPL/mx+axEns0hE35T5ufOYZXEnBQ==} resolution: {integrity: sha512-2yma2tog9VaRZY2mn3Wq51uiSW4NcPYT1cQdBagwyrznrilKSZwIZ0UG3ZPL/mx+axEns0hE35T5ufOYZXEnBQ==}
engines: {node: '>=4'} engines: {node: '>=4'}
@ -4461,6 +4553,10 @@ packages:
resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==}
dev: false dev: false
/quick-format-unescaped@4.0.4:
resolution: {integrity: sha512-tYC1Q1hgyRuHgloV/YXs2w15unPVh8qfu/qCTfhTYamaw7fyhumKa2yGpdSo87vY32rIclj+4fWYQXUMs9EHvg==}
dev: false
/quick-lru@4.0.1: /quick-lru@4.0.1:
resolution: {integrity: sha512-ARhCpm70fzdcvNQfPoy49IaanKkTlRWF2JMzqhcJbhSFRZv7nPTvZJdcY7301IPmvW+/p0RgIWnQDLJxifsQ7g==} resolution: {integrity: sha512-ARhCpm70fzdcvNQfPoy49IaanKkTlRWF2JMzqhcJbhSFRZv7nPTvZJdcY7301IPmvW+/p0RgIWnQDLJxifsQ7g==}
engines: {node: '>=8'} engines: {node: '>=8'}
@ -4529,6 +4625,22 @@ packages:
util-deprecate: 1.0.2 util-deprecate: 1.0.2
dev: false dev: false
/readable-stream@4.4.2:
resolution: {integrity: sha512-Lk/fICSyIhodxy1IDK2HazkeGjSmezAWX2egdtJnYhtzKEsBPJowlI6F6LPb5tqIQILrMbx22S5o3GuJavPusA==}
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
dependencies:
abort-controller: 3.0.0
buffer: 6.0.3
events: 3.3.0
process: 0.11.10
string_decoder: 1.3.0
dev: false
/real-require@0.2.0:
resolution: {integrity: sha512-57frrGM/OCTLqLOAh0mhVA9VBMHd+9U7Zb2THMGdBUoZVOtGbJzjxsYGDJ3A9AYYCP4hn6y1TVbaOfzWtm5GFg==}
engines: {node: '>= 12.13.0'}
dev: false
/redent@3.0.0: /redent@3.0.0:
resolution: {integrity: sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==} resolution: {integrity: sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==}
engines: {node: '>=8'} engines: {node: '>=8'}
@ -4694,6 +4806,11 @@ packages:
is-regex: 1.1.4 is-regex: 1.1.4
dev: false dev: false
/safe-stable-stringify@2.4.3:
resolution: {integrity: sha512-e2bDA2WJT0wxseVd4lsDP4+3ONX6HpMXQa1ZhFQ7SU+GjvORCmShbCMltrtIDfkYhVHrOcPtj+KhmDBdPdZD1g==}
engines: {node: '>=10'}
dev: false
/safer-buffer@2.1.2: /safer-buffer@2.1.2:
resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==}
dev: false dev: false
@ -4850,6 +4967,12 @@ packages:
yargs: 15.4.1 yargs: 15.4.1
dev: false dev: false
/sonic-boom@3.7.0:
resolution: {integrity: sha512-IudtNvSqA/ObjN97tfgNmOKyDOs4dNcg4cUUsHDebqsgb8wGBBwb31LIgShNO8fye0dFI52X1+tFoKKI6Rq1Gg==}
dependencies:
atomic-sleep: 1.0.0
dev: false
/source-map-support@0.5.21: /source-map-support@0.5.21:
resolution: {integrity: sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==} resolution: {integrity: sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==}
dependencies: dependencies:
@ -5131,6 +5254,12 @@ packages:
resolution: {integrity: sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==} resolution: {integrity: sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==}
dev: false dev: false
/thread-stream@2.4.1:
resolution: {integrity: sha512-d/Ex2iWd1whipbT681JmTINKw0ZwOUBZm7+Gjs64DHuX34mmw8vJL2bFAaNacaW72zYiTJxSHi5abUuOi5nsfg==}
dependencies:
real-require: 0.2.0
dev: false
/through2@4.0.2: /through2@4.0.2:
resolution: {integrity: sha512-iOqSav00cVxEEICeD7TjLB1sueEL+81Wpzp2bY17uZjZN0pWZPuo4suZ/61VujxmqSGFfgOcNuTZ85QJwNZQpw==} resolution: {integrity: sha512-iOqSav00cVxEEICeD7TjLB1sueEL+81Wpzp2bY17uZjZN0pWZPuo4suZ/61VujxmqSGFfgOcNuTZ85QJwNZQpw==}
dependencies: dependencies: