Reduce duplicate code, move shit out to common package
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@mifi/auth-db",
|
||||
"version": "1.0.10",
|
||||
"version": "1.0.11",
|
||||
"author": "mifi (Mike Fitzpatrick)",
|
||||
"license": "MIT",
|
||||
"scripts": {
|
||||
@@ -39,7 +39,8 @@
|
||||
"typescript": "^4.9.5"
|
||||
},
|
||||
"dependencies": {
|
||||
"@mifi/services-common": "1.x.x",
|
||||
"@mifi/auth-common": "^1.0.5",
|
||||
"@mifi/services-common": "^1.0.11",
|
||||
"dotenv": "^16.0.3",
|
||||
"jsonwebtoken": "^9.0.0",
|
||||
"mongoose": "^6.9.2"
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
import { Action } from '@mifi/auth-common/lib/enums/action';
|
||||
import { generateLoginToken } from '@mifi/auth-common/lib/utils/generateLoginToken';
|
||||
|
||||
import { Auth, Log } from '..';
|
||||
import { Action } from '../constants/action';
|
||||
import { getLoginToken } from '../utils/getLoginToken';
|
||||
|
||||
export const authenticate = async (username: string, password: string, includeToken = false) => {
|
||||
const doc = await Auth.findByUsername(username).catch();
|
||||
if (!!doc && (await doc.authenticate(password))) {
|
||||
Log.add(doc.id, Action.AUTHENTICATE);
|
||||
return { sub: doc._id, record: doc.record, token: includeToken ? getLoginToken(doc) : undefined };
|
||||
return { sub: doc._id, record: doc.record, token: includeToken ? generateLoginToken(doc) : undefined };
|
||||
}
|
||||
|
||||
if (doc) {
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { StringSchemaDefinition } from 'mongoose';
|
||||
|
||||
import { Auth, Strategy } from '..';
|
||||
|
||||
export const deleteStrategy = async (id: StringSchemaDefinition) => {
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
import { Action } from '@mifi/auth-common/lib/enums/action';
|
||||
import { TokenType } from '@mifi/auth-common/lib/enums/tokens';
|
||||
|
||||
import { readOneByUsername } from '../dao/readOneByUsername';
|
||||
import { Log, Token } from '..';
|
||||
import { TokenType } from '../constants/tokens';
|
||||
import { Action } from '../constants/action';
|
||||
|
||||
export const resetPasswordGet = async (username: string) => {
|
||||
const doc = await readOneByUsername(username);
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
import { Types } from 'mongoose';
|
||||
|
||||
import { Log, Strategy, Token } from '..';
|
||||
import { STRATEGIES } from '../constants/strategies';
|
||||
import { Action } from '@mifi/auth-common/lib/enums/action';
|
||||
import { STRATEGIES } from '@mifi/auth-common/lib/enums/strategies';
|
||||
import { generateLoginToken } from '@mifi/auth-common/lib/utils/generateLoginToken';
|
||||
|
||||
import { AuthDocument } from '../schema/auth';
|
||||
import { getLoginToken } from '../utils/getLoginToken';
|
||||
import { StrategyDocument } from '../schema/strategy';
|
||||
import { Action } from '../constants/action';
|
||||
import { Log, Strategy, Token } from '..';
|
||||
|
||||
export const resetPasswordPost = async (token: string, password: string) => {
|
||||
const parentId = await Token.validateResetToken(token);
|
||||
@@ -34,7 +35,7 @@ export const resetPasswordPost = async (token: string, password: string) => {
|
||||
}
|
||||
|
||||
Log.add(parent._id, Action.RESET);
|
||||
return { record: parent.record, token: getLoginToken(parent) };
|
||||
return { record: parent.record, token: generateLoginToken(parent) };
|
||||
}
|
||||
|
||||
return false;
|
||||
|
||||
@@ -1,9 +0,0 @@
|
||||
export enum Action {
|
||||
AUTHENTICATE = 'AUTHENTICATE',
|
||||
AUTHENTICATE_FAILURE = 'AUTHENTICATE_FAILURE',
|
||||
CREATE = 'CREATE',
|
||||
DELETE = 'DELETE',
|
||||
RESET = 'RESET',
|
||||
RESET_REQUEST = 'RESET_REQUEST',
|
||||
UPDATE = 'UPDATE',
|
||||
}
|
||||
@@ -1,8 +0,0 @@
|
||||
export enum Status {
|
||||
ACTIVE,
|
||||
BLOCK_HARD,
|
||||
BLOCK_SOFT,
|
||||
DELETED,
|
||||
INACTIVE,
|
||||
UNVERIFIED,
|
||||
}
|
||||
@@ -1,20 +0,0 @@
|
||||
export const PACKAGE_NAME = '@mifi/auth';
|
||||
export const PORT = process.env.PORT || 9000;
|
||||
|
||||
export const SESSION_KEY = process.env.SESSION_KEY || 'secret-key';
|
||||
|
||||
export const JWT_AUDIENCE = process.env.JWT_AUDIENCE || 'mifi.dev';
|
||||
export const JWT_ISSUER = process.env.JWT_ISSUER || PACKAGE_NAME;
|
||||
export const JWT_SECRET = process.env.JWT_SECRET || 'secret';
|
||||
|
||||
export const LOGIN_VALID_TIMEOUT = process.env.LOGIN_VALID_TIMEOUT || '12h'; // ###d|h|m
|
||||
export const RESET_VALID_TIMEOUT = process.env.RESET_VALID_TIMEOUT || '15m'; // ###d|h|m
|
||||
export const VERIFY_VALID_TIMEOUT = process.env.VERIFY_VALID_TIMEOUT || '60d'; // ###d|h|m
|
||||
export const DEFAULT_TOKEN_DAYS = process.env.DEFAULT_TOKEN_DAYS || 365;
|
||||
|
||||
export const ROUTE_PREFIX = process.env.ROUTE_PREFIX || '/auth';
|
||||
export const LOGIN_ROUTE = process.env.LOGIN_ROUTE || '/login';
|
||||
export const RESET_ROUTE = process.env.RESET_ROUTE || '/reset';
|
||||
export const VERIFICATION_ROUTE = process.env.VERIFICATION_ROUTE || '/verification';
|
||||
|
||||
export const REQUIRE_VERIFICATION = process.env.REQUIRE_VERIFICATION || true;
|
||||
@@ -1,12 +0,0 @@
|
||||
export enum ErrorCodes {
|
||||
RESET_REQUEST_DATA = 'RESET_REQUEST_DATA',
|
||||
}
|
||||
|
||||
export const ErrorMessages = {
|
||||
[ErrorCodes.RESET_REQUEST_DATA]: 'A valid username and password must be provided',
|
||||
};
|
||||
|
||||
export const getErrorBody = (code: ErrorCodes) => ({
|
||||
code,
|
||||
message: ErrorMessages[code],
|
||||
});
|
||||
@@ -1,7 +0,0 @@
|
||||
export enum STRATEGIES {
|
||||
LOCAL,
|
||||
APPLE,
|
||||
FACEBOOK,
|
||||
FIDO2,
|
||||
GOOGLE,
|
||||
}
|
||||
4
src/constants/timeouts.ts
Normal file
4
src/constants/timeouts.ts
Normal file
@@ -0,0 +1,4 @@
|
||||
export const LOGIN_VALID_TIMEOUT = process.env.LOGIN_VALID_TIMEOUT || '12h'; // ###d|h|m
|
||||
export const RESET_VALID_TIMEOUT = process.env.RESET_VALID_TIMEOUT || '15m'; // ###d|h|m
|
||||
export const VERIFY_VALID_TIMEOUT = process.env.VERIFY_VALID_TIMEOUT || '60d'; // ###d|h|m
|
||||
export const DEFAULT_TOKEN_DAYS = process.env.DEFAULT_TOKEN_DAYS || 365;
|
||||
@@ -1,4 +0,0 @@
|
||||
export enum TokenType {
|
||||
RESET = 'RESET',
|
||||
VERIFICATION = 'VERIFICATION',
|
||||
}
|
||||
@@ -1,12 +1,12 @@
|
||||
import { Action } from '@mifi/auth-common/lib/enums/action';
|
||||
import { Status } from '@mifi/auth-common/lib/enums/status';
|
||||
import { STRATEGIES } from '@mifi/auth-common/lib/enums/strategies';
|
||||
import { TokenType } from '@mifi/auth-common/lib/enums/tokens';
|
||||
import { REQUIRE_VERIFICATION } from '@mifi/auth-common/lib/settings';
|
||||
import { DatabaseError } from '@mifi/services-common/lib/domain/errors/DatabaseError';
|
||||
|
||||
import { Auth, Log, Strategy, Token } from '../..';
|
||||
import { Auth as AuthProps } from '../../schema/auth';
|
||||
import { STRATEGIES } from '../../constants/strategies';
|
||||
import { REQUIRE_VERIFICATION } from '../../constants/env';
|
||||
import { TokenType } from '../../constants/tokens';
|
||||
import { Status } from '../../constants/auth';
|
||||
import { Action } from '../../constants/action';
|
||||
import { Auth, Log, Strategy, Token } from '../..';
|
||||
|
||||
type CreateProps = Pick<AuthProps, 'username'> & {
|
||||
externalId?: string;
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
import { StringSchemaDefinition } from 'mongoose';
|
||||
|
||||
import { Action } from '@mifi/auth-common/lib/enums/action';
|
||||
import { Status } from '@mifi/auth-common/lib/enums/status';
|
||||
|
||||
import { Auth, Log, Strategy, Token } from '../..';
|
||||
import { Status } from '../../constants/auth';
|
||||
import { Action } from '../../constants/action';
|
||||
|
||||
export const deleteById = async (id: StringSchemaDefinition) => {
|
||||
if (
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
import { FilterQuery } from 'mongoose';
|
||||
|
||||
import { Status } from '@mifi/auth-common/lib/enums/status';
|
||||
|
||||
import { Auth } from '../../model/auth';
|
||||
import { Status } from '../../constants/auth';
|
||||
import { AuthDocument } from '../../schema/auth';
|
||||
|
||||
export const readAll = async (query: FilterQuery<AuthDocument> = {}) => Auth.find(query);
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { Types } from 'mongoose';
|
||||
|
||||
import { STRATEGIES } from '../../constants/strategies';
|
||||
import { STRATEGIES } from '@mifi/auth-common/lib/enums/strategies';
|
||||
|
||||
import { Strategy } from '../../model/strategy';
|
||||
|
||||
export const readOneByParentAndMethod = async (parent: Types.ObjectId, method: STRATEGIES) =>
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
import { Document, InferSchemaType, Model, Schema, StringSchemaDefinition, Types } from 'mongoose';
|
||||
|
||||
import { Status } from '../constants/auth';
|
||||
import { Status } from '@mifi/auth-common/lib/enums/status';
|
||||
import { STRATEGIES } from '@mifi/auth-common/lib/enums/strategies';
|
||||
|
||||
import { COLL_STRATEGY } from '../constants/db';
|
||||
import { STRATEGIES } from '../constants/strategies';
|
||||
import { StrategyDocument } from './strategy';
|
||||
import { verify } from '../utils/password';
|
||||
import { StrategyDocument } from './strategy';
|
||||
|
||||
export interface Auth {
|
||||
handle?: string;
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
import { InferSchemaType, Model, Schema, StringSchemaDefinition, Types } from 'mongoose';
|
||||
|
||||
import { Action } from '@mifi/auth-common/lib/enums/action';
|
||||
import { Payload } from '@mifi/services-common/lib/types/Payload';
|
||||
|
||||
import { Action } from '../constants/action';
|
||||
|
||||
export interface Log {
|
||||
action: Action;
|
||||
auth: StringSchemaDefinition;
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { Document, InferSchemaType, Model, Schema, StringSchemaDefinition, Types } from 'mongoose';
|
||||
|
||||
import { STRATEGIES } from '../constants/strategies';
|
||||
import { STRATEGIES } from '@mifi/auth-common/lib/enums/strategies';
|
||||
|
||||
import { encrypt } from '../utils/password';
|
||||
import { COLL_AUTH } from '../constants/db';
|
||||
import { AuthDocument } from './auth';
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
import { InferSchemaType, Model, Schema, StringSchemaDefinition, Types } from 'mongoose';
|
||||
|
||||
import { TokenType } from '../constants/tokens';
|
||||
import { getDefaultExpiresFor } from '../utils/getDefaultExpiresFor';
|
||||
import { sign, verify } from '../utils/jwt';
|
||||
import { TokenType } from '@mifi/auth-common/lib/enums/tokens';
|
||||
import { getDefaultExpiresFor } from '@mifi/auth-common/lib/helpers/getDefaultExpiresFor';
|
||||
import { sign, verify } from '@mifi/auth-common/lib/utils/jwt';
|
||||
import { SignProps } from '@mifi/auth-common/lib/utils/jwt/sign';
|
||||
|
||||
export interface Token {
|
||||
auth: StringSchemaDefinition;
|
||||
@@ -50,7 +51,7 @@ TokenSchema.statics = {
|
||||
return sign({
|
||||
sub: `${doc._id}`,
|
||||
exp: doc.expires,
|
||||
});
|
||||
} as SignProps);
|
||||
},
|
||||
|
||||
async validateResetToken(token: string) {
|
||||
|
||||
@@ -1,15 +0,0 @@
|
||||
import { LOGIN_VALID_TIMEOUT, RESET_VALID_TIMEOUT, VERIFY_VALID_TIMEOUT } from '../constants/env';
|
||||
import { TokenType } from '../constants/tokens';
|
||||
import { parseTimeoutToMs } from '../utils/parseTimeoutToMs';
|
||||
|
||||
export const getDefaultExpiresFor = (type: TokenType | void) => {
|
||||
if (type === TokenType.RESET) {
|
||||
return Date.now() + parseTimeoutToMs(RESET_VALID_TIMEOUT);
|
||||
}
|
||||
|
||||
if (type === TokenType.VERIFICATION) {
|
||||
return Date.now() + parseTimeoutToMs(VERIFY_VALID_TIMEOUT);
|
||||
}
|
||||
|
||||
return Date.now() + parseTimeoutToMs(LOGIN_VALID_TIMEOUT);
|
||||
};
|
||||
@@ -1,11 +0,0 @@
|
||||
import { sign } from '../utils/jwt';
|
||||
import { LOGIN_VALID_TIMEOUT } from '../constants/env';
|
||||
import { parseTimeoutToMs } from '../utils/parseTimeoutToMs';
|
||||
import { AuthDocument } from '../schema/auth';
|
||||
|
||||
export const getLoginToken = ({ record: sub, status }: AuthDocument) =>
|
||||
sign({
|
||||
sub: <string>sub,
|
||||
status,
|
||||
exp: Date.now() + parseTimeoutToMs(LOGIN_VALID_TIMEOUT),
|
||||
});
|
||||
@@ -1,35 +0,0 @@
|
||||
import jwt from 'jsonwebtoken';
|
||||
import { JWT_AUDIENCE, JWT_ISSUER, JWT_SECRET } from '../constants/env';
|
||||
export interface TokenProps {
|
||||
aud?: string;
|
||||
exp?: number | Date;
|
||||
iss?: string;
|
||||
sub: string | null;
|
||||
[key: string]: any;
|
||||
}
|
||||
|
||||
export type SignProps = string | TokenProps | void;
|
||||
|
||||
export const sign = (props: SignProps) => {
|
||||
const today = new Date();
|
||||
const { sub = null, ...rest }: TokenProps =
|
||||
typeof props === 'string' || typeof props === 'undefined' ? { sub: props || null } : props;
|
||||
let { exp } = rest;
|
||||
if (!exp) {
|
||||
exp = new Date(today);
|
||||
exp.setDate(today.getDate() + parseInt(process.env.JWT_DAYS_VALID as string));
|
||||
exp = exp.getTime() / 1000;
|
||||
}
|
||||
return jwt.sign(
|
||||
{
|
||||
exp,
|
||||
sub,
|
||||
aud: rest.aud || JWT_AUDIENCE,
|
||||
iat: today.getTime(),
|
||||
iss: rest.iss || JWT_ISSUER,
|
||||
},
|
||||
JWT_SECRET,
|
||||
);
|
||||
};
|
||||
|
||||
export const verify = (token: string) => jwt.verify(token, JWT_SECRET);
|
||||
@@ -1,5 +0,0 @@
|
||||
import { RESET_ROUTE, ROUTE_PREFIX, VERIFICATION_ROUTE } from '../constants/env';
|
||||
|
||||
export const getPasswordResetPath = (token: string) => `${ROUTE_PREFIX}${RESET_ROUTE}?t=${token}`;
|
||||
|
||||
export const getVerificationPath = (token: string) => `${ROUTE_PREFIX}${VERIFICATION_ROUTE}?t=${token}`;
|
||||
@@ -1,13 +0,0 @@
|
||||
export const parseTimeoutToMs = (timeout: string) => {
|
||||
const match = timeout.match(/(?<number>\d+)(?<unit>d|h|m)/gi)?.groups || {};
|
||||
const { number, unit } = match;
|
||||
switch (unit) {
|
||||
case 'd':
|
||||
return 1000 * 60 * 60 * 24 * parseInt(number);
|
||||
case 'h':
|
||||
return 1000 * 60 * 60 * parseInt(number);
|
||||
case 'm':
|
||||
default:
|
||||
return 1000 * 60 * parseInt(number) || 1;
|
||||
}
|
||||
};
|
||||
@@ -5,8 +5,3 @@ export const encrypt = (password: string) => {
|
||||
const hash = pbkdf2Sync(password, salt, 10000, 512, 'sha512').toString('hex');
|
||||
return `${salt}:${hash}`;
|
||||
};
|
||||
|
||||
export const verify = (test: string, secret: string) => {
|
||||
const [salt, hash] = secret.split(':');
|
||||
return pbkdf2Sync(test, salt, 10000, 512, 'sha512').toString('hex') === hash;
|
||||
};
|
||||
4
src/utils/password/index.ts
Normal file
4
src/utils/password/index.ts
Normal file
@@ -0,0 +1,4 @@
|
||||
import { encrypt } from './encrypt';
|
||||
import { verify } from './verify';
|
||||
|
||||
export { encrypt, verify };
|
||||
6
src/utils/password/verify.ts
Normal file
6
src/utils/password/verify.ts
Normal file
@@ -0,0 +1,6 @@
|
||||
import { pbkdf2Sync } from 'crypto';
|
||||
|
||||
export const verify = (test: string, secret: string) => {
|
||||
const [salt, hash] = secret.split(':');
|
||||
return pbkdf2Sync(test, salt, 10000, 512, 'sha512').toString('hex') === hash;
|
||||
};
|
||||
@@ -1,11 +0,0 @@
|
||||
import { sign } from './jwt';
|
||||
import { LOGIN_VALID_TIMEOUT } from '../constants/env';
|
||||
import { Status } from '../constants/auth';
|
||||
import { parseTimeoutToMs } from './parseTimeoutToMs';
|
||||
|
||||
export const generateLoginToken = (sub: string, status: Status) =>
|
||||
sign({
|
||||
sub,
|
||||
status,
|
||||
exp: Date.now() + parseTimeoutToMs(LOGIN_VALID_TIMEOUT),
|
||||
});
|
||||
55
yarn.lock
55
yarn.lock
@@ -2648,6 +2648,17 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@mifi/auth-common@npm:^1.0.5":
|
||||
version: 1.0.5
|
||||
resolution: "@mifi/auth-common@npm:1.0.5::__archiveUrl=https%3A%2F%2Fgit.mifi.dev%2Fapi%2Fpackages%2Fmifi%2Fnpm%2F%2540mifi%252Fauth-common%2F-%2F1.0.5%2Fauth-common-1.0.5.tgz"
|
||||
dependencies:
|
||||
"@mifi/breakerbox-db": ^1.0.3
|
||||
"@mifi/services-common": ^1.0.11
|
||||
jsonwebtoken: ^9.0.0
|
||||
checksum: 0eef5c417ae95dc2a31b8599b4e0e747478171d518a7dfd223090667fdc142c8d2cd9e29852883573cc6c7b2dd32eb0625e5bc73ff6f5908b0032a54815e0a98
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@mifi/auth-db@workspace:.":
|
||||
version: 0.0.0-use.local
|
||||
resolution: "@mifi/auth-db@workspace:."
|
||||
@@ -2655,7 +2666,8 @@ __metadata:
|
||||
"@babel/core": ^7.21.8
|
||||
"@babel/preset-env": ^7.21.5
|
||||
"@babel/preset-typescript": ^7.21.5
|
||||
"@mifi/services-common": 1.x.x
|
||||
"@mifi/auth-common": ^1.0.5
|
||||
"@mifi/services-common": ^1.0.11
|
||||
"@tsconfig/node16": ^1.0.4
|
||||
"@types/jsonwebtoken": ^9.0.2
|
||||
"@types/node": ^18.14.0
|
||||
@@ -2682,10 +2694,20 @@ __metadata:
|
||||
languageName: unknown
|
||||
linkType: soft
|
||||
|
||||
"@mifi/services-common@npm:1.x.x":
|
||||
version: 1.0.6
|
||||
resolution: "@mifi/services-common@npm:1.0.6::__archiveUrl=https%3A%2F%2Fgit.mifi.dev%2Fapi%2Fpackages%2Fmifi%2Fnpm%2F%2540mifi%252Fservices-common%2F-%2F1.0.6%2Fservices-common-1.0.6.tgz"
|
||||
checksum: 22e9aa2714d088a286fc76ddf88c89698764f966ea5f3a208da45df893ec8a0c4e43848f4ba59746cd96b16880dbfa9f3a88610e43aa3825cbdb78afc11f59dc
|
||||
"@mifi/breakerbox-db@npm:^1.0.3":
|
||||
version: 1.0.3
|
||||
resolution: "@mifi/breakerbox-db@npm:1.0.3::__archiveUrl=https%3A%2F%2Fgit.mifi.dev%2Fapi%2Fpackages%2Fmifi%2Fnpm%2F%2540mifi%252Fbreakerbox-db%2F-%2F1.0.3%2Fbreakerbox-db-1.0.3.tgz"
|
||||
dependencies:
|
||||
lowdb: ^6.0.1
|
||||
yaml: ^2.3.1
|
||||
checksum: 16f2f841d4d1f87f29ddcbec222076d4186038cbd22b9116deb941c07bd0aca1473a5aa66ae113c0cb01c3ded866ef9ec4bbeda055b054d47c3696cb16cfeb62
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@mifi/services-common@npm:^1.0.11":
|
||||
version: 1.0.11
|
||||
resolution: "@mifi/services-common@npm:1.0.11::__archiveUrl=https%3A%2F%2Fgit.mifi.dev%2Fapi%2Fpackages%2Fmifi%2Fnpm%2F%2540mifi%252Fservices-common%2F-%2F1.0.11%2Fservices-common-1.0.11.tgz"
|
||||
checksum: 3faeba975bbf35f532826da658545c1faa04f2a90c4f5a428474628aa3d9a3a03690b9caa216ed78be87aa4564dbe78195945b3de6a234ad6de9fac0768ac999
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
@@ -6294,6 +6316,15 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"lowdb@npm:^6.0.1":
|
||||
version: 6.0.1
|
||||
resolution: "lowdb@npm:6.0.1"
|
||||
dependencies:
|
||||
steno: ^3.0.0
|
||||
checksum: d555a5bcc2e4a963fae89209b693a6f2b7b69bae915ff67355537b7a14a4f6e44bc273467bc3d4d7e81660c1313587ee3bfebf044d50d3213a5e95ea7f07ded4
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"lru-cache@npm:^5.1.1":
|
||||
version: 5.1.1
|
||||
resolution: "lru-cache@npm:5.1.1"
|
||||
@@ -7544,6 +7575,13 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"steno@npm:^3.0.0":
|
||||
version: 3.0.0
|
||||
resolution: "steno@npm:3.0.0"
|
||||
checksum: fb928451a4f96342b496b71147fbca0a20a5daf7bfd23a4a1cec8640d3c6c67176809169e9a5801ea44490d448b5b7ecb151b9fba434872c2d65549847f39460
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"string-length@npm:^4.0.1":
|
||||
version: 4.0.2
|
||||
resolution: "string-length@npm:4.0.2"
|
||||
@@ -8255,6 +8293,13 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"yaml@npm:^2.3.1":
|
||||
version: 2.3.1
|
||||
resolution: "yaml@npm:2.3.1"
|
||||
checksum: 2c7bc9a7cd4c9f40d3b0b0a98e370781b68b8b7c4515720869aced2b00d92f5da1762b4ffa947f9e795d6cd6b19f410bd4d15fdd38aca7bd96df59bd9486fb54
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"yargs-parser@npm:^13.1.2":
|
||||
version: 13.1.2
|
||||
resolution: "yargs-parser@npm:13.1.2"
|
||||
|
||||
Reference in New Issue
Block a user