mirror of
https://github.com/verdaccio/verdaccio.git
synced 2025-03-11 02:15:57 -05:00
chore: move improvements from v5 to v6 (#3461)
* chore: migrate #3158 to v6 * chore: migrate #3151 to v6k * chore: migrate #2787 to v6 * chore: migrate #2791 #2205 to v6 * chore: add changeset
This commit is contained in:
parent
88a419a966
commit
4b29d715b1
18 changed files with 176 additions and 40 deletions
21
.changeset/thick-geese-wash.md
Normal file
21
.changeset/thick-geese-wash.md
Normal file
|
@ -0,0 +1,21 @@
|
|||
---
|
||||
'@verdaccio/api': minor
|
||||
'@verdaccio/auth': minor
|
||||
'@verdaccio/config': minor
|
||||
'@verdaccio/core': minor
|
||||
'@verdaccio/url': minor
|
||||
'@verdaccio/middleware': minor
|
||||
'@verdaccio/local-storage': minor
|
||||
'@verdaccio/web': minor
|
||||
---
|
||||
|
||||
chore: move improvements from v5 to v6
|
||||
|
||||
Migrate improvements form v5 to v6:
|
||||
|
||||
- https://github.com/verdaccio/verdaccio/pull/3158
|
||||
- https://github.com/verdaccio/verdaccio/pull/3151
|
||||
- https://github.com/verdaccio/verdaccio/pull/2271
|
||||
- https://github.com/verdaccio/verdaccio/pull/2787
|
||||
- https://github.com/verdaccio/verdaccio/pull/2791
|
||||
- https://github.com/verdaccio/verdaccio/pull/2205
|
|
@ -4,7 +4,14 @@ import { Response, Router } from 'express';
|
|||
import { getApiToken } from '@verdaccio/auth';
|
||||
import { Auth } from '@verdaccio/auth';
|
||||
import { createRemoteUser } from '@verdaccio/config';
|
||||
import { API_ERROR, API_MESSAGE, HTTP_STATUS, errorUtils, validatioUtils } from '@verdaccio/core';
|
||||
import {
|
||||
API_ERROR,
|
||||
API_MESSAGE,
|
||||
HEADERS,
|
||||
HTTP_STATUS,
|
||||
errorUtils,
|
||||
validatioUtils,
|
||||
} from '@verdaccio/core';
|
||||
import { logger } from '@verdaccio/logger';
|
||||
import { Config, RemoteUser } from '@verdaccio/types';
|
||||
import { getAuthenticatedMessage, mask } from '@verdaccio/utils';
|
||||
|
@ -75,6 +82,7 @@ export default function (route: Router, auth: Auth, config: Config): void {
|
|||
}
|
||||
|
||||
res.status(HTTP_STATUS.CREATED);
|
||||
res.set(HEADERS.CACHE_CONTROL, 'no-cache, no-store');
|
||||
|
||||
const message = getAuthenticatedMessage(req.remote_user.name);
|
||||
debug('login: created user message %o', message);
|
||||
|
@ -124,6 +132,7 @@ export default function (route: Router, auth: Auth, config: Config): void {
|
|||
|
||||
req.remote_user = user;
|
||||
res.status(HTTP_STATUS.CREATED);
|
||||
res.set(HEADERS.CACHE_CONTROL, 'no-cache, no-store');
|
||||
debug('adduser: user has been created');
|
||||
return next({
|
||||
ok: `user '${req.body.name}' created`,
|
||||
|
|
|
@ -3,7 +3,7 @@ import _ from 'lodash';
|
|||
|
||||
import { getApiToken } from '@verdaccio/auth';
|
||||
import { Auth } from '@verdaccio/auth';
|
||||
import { HTTP_STATUS, SUPPORT_ERRORS, errorUtils } from '@verdaccio/core';
|
||||
import { HEADERS, HTTP_STATUS, SUPPORT_ERRORS, errorUtils } from '@verdaccio/core';
|
||||
import { logger } from '@verdaccio/logger';
|
||||
import { Storage } from '@verdaccio/store';
|
||||
import { Config, RemoteUser, Token } from '@verdaccio/types';
|
||||
|
@ -102,6 +102,7 @@ export default function (route: Router, auth: Auth, storage: Storage, config: Co
|
|||
|
||||
await storage.saveToken(saveToken);
|
||||
logger.debug({ key, name }, 'token @{key} was created for user @{name}');
|
||||
res.set(HEADERS.CACHE_CONTROL, 'no-cache, no-store');
|
||||
return next(
|
||||
normalizeToken({
|
||||
token,
|
||||
|
|
|
@ -39,6 +39,7 @@ export function createUser(app, name: string, password: string): supertest.Test
|
|||
password: password,
|
||||
})
|
||||
.expect(HEADER_TYPE.CONTENT_TYPE, HEADERS.JSON_CHARSET)
|
||||
.expect(HEADERS.CACHE_CONTROL, 'no-cache, no-store')
|
||||
.expect(HTTP_STATUS.CREATED);
|
||||
}
|
||||
|
||||
|
|
|
@ -574,7 +574,9 @@ class Auth implements IAuthMiddleware, TokenEncryption, pluginUtils.IBasicAuth {
|
|||
const { real_groups, name, groups } = user;
|
||||
debug('jwt encrypt %o', name);
|
||||
const realGroupsValidated = _.isNil(real_groups) ? [] : real_groups;
|
||||
const groupedGroups = _.isNil(groups) ? real_groups : groups.concat(realGroupsValidated);
|
||||
const groupedGroups = _.isNil(groups)
|
||||
? real_groups
|
||||
: Array.from(new Set([...groups.concat(realGroupsValidated)]));
|
||||
const payload: RemoteUser = {
|
||||
real_groups: realGroupsValidated,
|
||||
name,
|
||||
|
|
|
@ -77,8 +77,8 @@ describe('Auth utilities', () => {
|
|||
const spyNotCalled = jest.spyOn(auth, methodNotBeenCalled);
|
||||
const user: RemoteUser = {
|
||||
name: username,
|
||||
real_groups: [],
|
||||
groups: [],
|
||||
real_groups: ['test', '$all', '$authenticated', '@all', '@authenticated', 'all'],
|
||||
groups: ['company-role1', 'company-role2'],
|
||||
};
|
||||
const token = await getApiToken(auth, config, user, password);
|
||||
expect(spy).toHaveBeenCalled();
|
||||
|
@ -93,7 +93,25 @@ describe('Auth utilities', () => {
|
|||
const payload = verifyPayload(token, secret);
|
||||
expect(payload.name).toBe(user);
|
||||
expect(payload.groups).toBeDefined();
|
||||
expect(payload.groups).toEqual([
|
||||
'company-role1',
|
||||
'company-role2',
|
||||
'test',
|
||||
'$all',
|
||||
'$authenticated',
|
||||
'@all',
|
||||
'@authenticated',
|
||||
'all',
|
||||
]);
|
||||
expect(payload.real_groups).toBeDefined();
|
||||
expect(payload.real_groups).toEqual([
|
||||
'test',
|
||||
'$all',
|
||||
'$authenticated',
|
||||
'@all',
|
||||
'@authenticated',
|
||||
'all',
|
||||
]);
|
||||
};
|
||||
|
||||
const verifyAES = (token: string, user: string, password: string, secret: string) => {
|
||||
|
@ -219,6 +237,30 @@ describe('Auth utilities', () => {
|
|||
});
|
||||
});
|
||||
|
||||
describe('createRemoteUser', () => {
|
||||
test('create remote user', () => {
|
||||
expect(createRemoteUser('test', [])).toEqual({
|
||||
name: 'test',
|
||||
real_groups: [],
|
||||
groups: ['$all', '$authenticated', '@all', '@authenticated', 'all'],
|
||||
});
|
||||
});
|
||||
test('create remote user with groups', () => {
|
||||
expect(createRemoteUser('test', ['group1', 'group2'])).toEqual({
|
||||
name: 'test',
|
||||
real_groups: ['group1', 'group2'],
|
||||
groups: ['group1', 'group2', '$all', '$authenticated', '@all', '@authenticated', 'all'],
|
||||
});
|
||||
});
|
||||
test('create anonymous remote user', () => {
|
||||
expect(createAnonymousRemoteUser()).toEqual({
|
||||
name: undefined,
|
||||
real_groups: [],
|
||||
groups: ['$all', '$anonymous', '@all', '@anonymous'],
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('getApiToken test', () => {
|
||||
test('should sign token with aes and security missing', async () => {
|
||||
const token = await getTokenByConfiguration(
|
||||
|
@ -445,15 +487,13 @@ describe('Auth utilities', () => {
|
|||
security,
|
||||
'12345',
|
||||
buildToken(TOKEN_BEARER, 'fakeToken')
|
||||
);
|
||||
) as RemoteUser;
|
||||
|
||||
expect(credentials).toBeDefined();
|
||||
// @ts-ignore
|
||||
expect(credentials.name).not.toBeDefined();
|
||||
// @ts-ignore
|
||||
expect(credentials.real_groups).toBeDefined();
|
||||
// @ts-ignore
|
||||
expect(credentials.real_groups).toEqual([]);
|
||||
|
||||
expect(credentials.groups).toEqual(['$all', '$anonymous', '@all', '@anonymous']);
|
||||
});
|
||||
|
||||
test('should return anonymous whether token and scheme are corrupted', () => {
|
||||
|
@ -485,14 +525,29 @@ describe('Auth utilities', () => {
|
|||
security,
|
||||
secret,
|
||||
buildToken(TOKEN_BEARER, token)
|
||||
);
|
||||
) as RemoteUser;
|
||||
expect(credentials).toBeDefined();
|
||||
// @ts-ignore
|
||||
|
||||
expect(credentials.name).toEqual(user);
|
||||
// @ts-ignore
|
||||
expect(credentials.real_groups).toBeDefined();
|
||||
// @ts-ignore
|
||||
expect(credentials.real_groups).toEqual([]);
|
||||
expect(credentials.real_groups).toEqual([
|
||||
'test',
|
||||
'$all',
|
||||
'$authenticated',
|
||||
'@all',
|
||||
'@authenticated',
|
||||
'all',
|
||||
]);
|
||||
expect(credentials.groups).toEqual([
|
||||
'company-role1',
|
||||
'company-role2',
|
||||
'test',
|
||||
'$all',
|
||||
'$authenticated',
|
||||
'@all',
|
||||
'@authenticated',
|
||||
'all',
|
||||
]);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -1,11 +1,12 @@
|
|||
import { APITokenOptions, JWTOptions, Security } from '@verdaccio/types';
|
||||
|
||||
export const TIME_EXPIRATION_7D = '7d';
|
||||
// TODO: get this from core package
|
||||
export const TIME_EXPIRATION_1H = '1h';
|
||||
|
||||
const defaultWebTokenOptions: JWTOptions = {
|
||||
sign: {
|
||||
// The expiration token for the website is 7 days
|
||||
expiresIn: TIME_EXPIRATION_7D,
|
||||
expiresIn: TIME_EXPIRATION_1H,
|
||||
},
|
||||
verify: {},
|
||||
};
|
||||
|
|
|
@ -29,7 +29,9 @@ export const defaultNonLoggedUserRoles = [
|
|||
*/
|
||||
export function createRemoteUser(name: string, pluginGroups: string[]): RemoteUser {
|
||||
const isGroupValid: boolean = Array.isArray(pluginGroups);
|
||||
const groups = (isGroupValid ? pluginGroups : []).concat([...defaultLoggedUserRoles]);
|
||||
const groups = Array.from(
|
||||
new Set((isGroupValid ? pluginGroups : []).concat([...defaultLoggedUserRoles]))
|
||||
);
|
||||
|
||||
return {
|
||||
name,
|
||||
|
|
|
@ -2,7 +2,7 @@ import httpCodes from 'http-status-codes';
|
|||
|
||||
export const DEFAULT_PASSWORD_VALIDATION = /.{3}$/;
|
||||
export const TIME_EXPIRATION_24H = '24h';
|
||||
export const TIME_EXPIRATION_7D = '7d';
|
||||
export const TIME_EXPIRATION_1H = '1h';
|
||||
export const DIST_TAGS = 'dist-tags';
|
||||
export const LATEST = 'latest';
|
||||
export const USERS = 'users';
|
||||
|
@ -35,6 +35,7 @@ export const HEADERS = {
|
|||
TEXT_HTML_UTF8: 'text/html; charset=utf-8',
|
||||
TEXT_HTML: 'text/html',
|
||||
AUTHORIZATION: 'authorization',
|
||||
CACHE_CONTROL: 'Cache-Control',
|
||||
// only set with proxy that setup HTTPS
|
||||
// https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Forwarded-Proto
|
||||
FORWARDED_PROTO: 'X-Forwarded-Proto',
|
||||
|
|
|
@ -295,6 +295,27 @@ describe('env variable', () => {
|
|||
delete process.env.VERDACCIO_PUBLIC_URL;
|
||||
});
|
||||
|
||||
test('with the VERDACCIO_FORWARDED_PROTO undefined', () => {
|
||||
process.env.VERDACCIO_FORWARDED_PROTO = undefined;
|
||||
const req = httpMocks.createRequest({
|
||||
method: 'GET',
|
||||
headers: {
|
||||
host: 'some.com',
|
||||
[HEADERS.FORWARDED_PROTO]: 'https',
|
||||
},
|
||||
url: '/',
|
||||
});
|
||||
|
||||
expect(
|
||||
getPublicUrl('/test/', {
|
||||
host: req.hostname,
|
||||
headers: req.headers as any,
|
||||
protocol: req.protocol,
|
||||
})
|
||||
).toEqual('http://some.com/test/');
|
||||
delete process.env.VERDACCIO_FORWARDED_PROTO;
|
||||
});
|
||||
|
||||
test('with a invalid X-Forwarded-Proto https and host injection with invalid host', () => {
|
||||
process.env.VERDACCIO_PUBLIC_URL = 'http://injection.test.com"><svg onload="alert(1)">';
|
||||
const req = httpMocks.createRequest({
|
||||
|
|
|
@ -104,10 +104,7 @@ export function media(expect: string | null): any {
|
|||
next(
|
||||
errorUtils.getCode(
|
||||
HTTP_STATUS.UNSUPPORTED_MEDIA,
|
||||
'wrong content-type, expect: ' +
|
||||
expect +
|
||||
', got: ' +
|
||||
req.headers[HEADER_TYPE.CONTENT_TYPE]
|
||||
'wrong content-type, expect: ' + expect + ', got: ' + req.get[HEADER_TYPE.CONTENT_TYPE]
|
||||
)
|
||||
);
|
||||
} else {
|
||||
|
@ -141,7 +138,7 @@ export function expectJson(
|
|||
|
||||
export function antiLoop(config: Config): Function {
|
||||
return function (req: $RequestExtend, res: $ResponseExtend, next: $NextFunctionVer): void {
|
||||
if (req.headers.via != null) {
|
||||
if (req?.headers?.via != null) {
|
||||
const arr = req.headers.via.split(',');
|
||||
|
||||
for (let i = 0; i < arr.length; i++) {
|
||||
|
@ -264,7 +261,7 @@ export function log(req: $RequestExtend, res: $ResponseExtend, next: $NextFuncti
|
|||
req.headers.authorization = '<Classified>';
|
||||
}
|
||||
|
||||
const _cookie = req.headers.cookie;
|
||||
const _cookie = req.get('cookie');
|
||||
if (_.isNil(_cookie) === false) {
|
||||
req.headers.cookie = '<Classified>';
|
||||
}
|
||||
|
@ -298,7 +295,7 @@ export function log(req: $RequestExtend, res: $ResponseExtend, next: $NextFuncti
|
|||
};
|
||||
|
||||
const log = function (): void {
|
||||
const forwardedFor = req.headers['x-forwarded-for'];
|
||||
const forwardedFor = req.get('x-forwarded-for');
|
||||
const remoteAddress = req.connection.remoteAddress;
|
||||
const remoteIP = forwardedFor ? `${forwardedFor} via ${remoteAddress}` : remoteAddress;
|
||||
let message;
|
||||
|
|
|
@ -47,7 +47,7 @@
|
|||
"sanitize-filename": "1.6.3",
|
||||
"lodash": "4.17.21",
|
||||
"lowdb": "1.0.0",
|
||||
"lru-cache": "6.0.0"
|
||||
"lru-cache": "7.14.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/minimatch": "3.0.5",
|
||||
|
|
|
@ -40,7 +40,7 @@
|
|||
"debug": "4.3.4",
|
||||
"express": "4.18.2",
|
||||
"lodash": "4.17.21",
|
||||
"lru-cache": "6.0.0"
|
||||
"lru-cache": "7.14.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "16.11.65",
|
||||
|
|
|
@ -6,6 +6,7 @@ import { Auth } from '@verdaccio/auth';
|
|||
import {
|
||||
API_ERROR,
|
||||
APP_ERROR,
|
||||
HEADERS,
|
||||
HTTP_STATUS,
|
||||
VerdaccioError,
|
||||
errorUtils,
|
||||
|
@ -33,7 +34,7 @@ function addUserAuthApi(auth: Auth, config: Config): Router {
|
|||
} else {
|
||||
req.remote_user = user as RemoteUser;
|
||||
const jWTSignOptions: JWTSignOptions = config.security.web.sign;
|
||||
|
||||
res.set(HEADERS.CACHE_CONTROL, 'no-cache, no-store');
|
||||
next({
|
||||
token: await auth.jwtEncrypt(user as RemoteUser, jWTSignOptions),
|
||||
username: req.remote_user.name,
|
||||
|
|
|
@ -18,8 +18,9 @@ export async function loadTheme(config: any) {
|
|||
const plugin = await asyncLoadPlugin(
|
||||
config.theme,
|
||||
{ config, logger },
|
||||
function (plugin) {
|
||||
return typeof plugin === 'string';
|
||||
// TODO: add types { staticPath: string; manifest: unknown; manifestFiles: unknown }
|
||||
function (plugin: any) {
|
||||
return plugin.staticPath && plugin.manifest && plugin.manifestFiles;
|
||||
},
|
||||
config?.serverSettings?.pluginPrefix ?? 'verdaccio-theme'
|
||||
);
|
||||
|
|
|
@ -12,7 +12,7 @@ import { hasLogin, validatePrimaryColor } from './utils/web-utils';
|
|||
|
||||
const pkgJSON = require('../package.json');
|
||||
const DEFAULT_LANGUAGE = 'es-US';
|
||||
const cache = new LRU({ max: 500, maxAge: 1000 * 60 * 60 });
|
||||
const cache = new LRU({ max: 500, ttl: 1000 * 60 * 60 });
|
||||
|
||||
const debug = buildDebug('verdaccio:web:render');
|
||||
|
||||
|
|
|
@ -55,6 +55,7 @@ describe('test web server', () => {
|
|||
)
|
||||
.set(HEADER_TYPE.CONTENT_TYPE, HEADERS.JSON)
|
||||
.expect(HEADER_TYPE.CONTENT_TYPE, HEADERS.JSON_CHARSET)
|
||||
.expect(HEADERS.CACHE_CONTROL, 'no-cache, no-store')
|
||||
.expect(HTTP_STATUS.OK)
|
||||
.then((res) => {
|
||||
expect(res.body.error).toBeUndefined();
|
||||
|
|
38
pnpm-lock.yaml
generated
38
pnpm-lock.yaml
generated
|
@ -741,7 +741,7 @@ importers:
|
|||
lockfile: 1.0.4
|
||||
lodash: 4.17.21
|
||||
lowdb: 1.0.0
|
||||
lru-cache: 6.0.0
|
||||
lru-cache: 7.14.0
|
||||
minimatch: 3.1.2
|
||||
sanitize-filename: 1.6.3
|
||||
dependencies:
|
||||
|
@ -754,7 +754,7 @@ importers:
|
|||
lockfile: 1.0.4
|
||||
lodash: 4.17.21
|
||||
lowdb: 1.0.0
|
||||
lru-cache: 6.0.0
|
||||
lru-cache: 7.14.0
|
||||
sanitize-filename: 1.6.3
|
||||
devDependencies:
|
||||
'@types/minimatch': 3.0.5
|
||||
|
@ -1329,7 +1329,7 @@ importers:
|
|||
express: 4.18.2
|
||||
jsdom: 20.0.1
|
||||
lodash: 4.17.21
|
||||
lru-cache: 6.0.0
|
||||
lru-cache: 7.14.0
|
||||
nock: 13.2.9
|
||||
node-html-parser: 4.1.5
|
||||
supertest: 6.3.0
|
||||
|
@ -1352,7 +1352,7 @@ importers:
|
|||
debug: 4.3.4
|
||||
express: 4.18.2
|
||||
lodash: 4.17.21
|
||||
lru-cache: 6.0.0
|
||||
lru-cache: 7.14.0
|
||||
devDependencies:
|
||||
'@types/node': 16.11.65
|
||||
'@verdaccio/api': link:../api
|
||||
|
@ -9286,6 +9286,10 @@ packages:
|
|||
peerDependencies:
|
||||
'@typescript-eslint/parser': ^5.0.0
|
||||
eslint: ^6.0.0 || ^7.0.0 || ^8.0.0
|
||||
typescript: '*'
|
||||
peerDependenciesMeta:
|
||||
typescript:
|
||||
optional: true
|
||||
dependencies:
|
||||
'@typescript-eslint/parser': 5.41.0_eslint@8.26.0+typescript@4.8.4
|
||||
'@typescript-eslint/scope-manager': 5.41.0
|
||||
|
@ -9297,24 +9301,28 @@ packages:
|
|||
regexpp: 3.2.0
|
||||
semver: 7.3.8
|
||||
tsutils: 3.21.0_typescript@4.8.4
|
||||
typescript: 4.8.4
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
- typescript
|
||||
|
||||
/@typescript-eslint/parser/5.41.0_eslint@8.26.0+typescript@4.8.4:
|
||||
resolution: {integrity: sha512-HQVfix4+RL5YRWZboMD1pUfFN8MpRH4laziWkkAzyO1fvNOY/uinZcvo3QiFJVS/siNHupV8E5+xSwQZrl6PZA==}
|
||||
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
|
||||
peerDependencies:
|
||||
eslint: ^6.0.0 || ^7.0.0 || ^8.0.0
|
||||
typescript: '*'
|
||||
peerDependenciesMeta:
|
||||
typescript:
|
||||
optional: true
|
||||
dependencies:
|
||||
'@typescript-eslint/scope-manager': 5.41.0
|
||||
'@typescript-eslint/types': 5.41.0
|
||||
'@typescript-eslint/typescript-estree': 5.41.0_typescript@4.8.4
|
||||
debug: 4.3.4
|
||||
eslint: 8.26.0
|
||||
typescript: 4.8.4
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
- typescript
|
||||
|
||||
/@typescript-eslint/scope-manager/5.33.1:
|
||||
resolution: {integrity: sha512-8ibcZSqy4c5m69QpzJn8XQq9NnqAToC8OdH/W6IXPXv83vRyEDPYLdjAlUx8h/rbusq6MkW4YdQzURGOqsn3CA==}
|
||||
|
@ -9336,15 +9344,19 @@ packages:
|
|||
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
|
||||
peerDependencies:
|
||||
eslint: '*'
|
||||
typescript: '*'
|
||||
peerDependenciesMeta:
|
||||
typescript:
|
||||
optional: true
|
||||
dependencies:
|
||||
'@typescript-eslint/typescript-estree': 5.41.0_typescript@4.8.4
|
||||
'@typescript-eslint/utils': 5.41.0_eslint@8.26.0+typescript@4.8.4
|
||||
debug: 4.3.4
|
||||
eslint: 8.26.0
|
||||
tsutils: 3.21.0_typescript@4.8.4
|
||||
typescript: 4.8.4
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
- typescript
|
||||
|
||||
/@typescript-eslint/types/5.33.1:
|
||||
resolution: {integrity: sha512-7K6MoQPQh6WVEkMrMW5QOA5FO+BOwzHSNd0j3+BlBwd6vtzfZceJ8xJ7Um2XDi/O3umS8/qDX6jdy2i7CijkwQ==}
|
||||
|
@ -9379,6 +9391,11 @@ packages:
|
|||
/@typescript-eslint/typescript-estree/5.41.0_typescript@4.8.4:
|
||||
resolution: {integrity: sha512-SlzFYRwFSvswzDSQ/zPkIWcHv8O5y42YUskko9c4ki+fV6HATsTODUPbRbcGDFYP86gaJL5xohUEytvyNNcXWg==}
|
||||
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
|
||||
peerDependencies:
|
||||
typescript: '*'
|
||||
peerDependenciesMeta:
|
||||
typescript:
|
||||
optional: true
|
||||
dependencies:
|
||||
'@typescript-eslint/types': 5.41.0
|
||||
'@typescript-eslint/visitor-keys': 5.41.0
|
||||
|
@ -9387,9 +9404,9 @@ packages:
|
|||
is-glob: 4.0.3
|
||||
semver: 7.3.8
|
||||
tsutils: 3.21.0_typescript@4.8.4
|
||||
typescript: 4.8.4
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
- typescript
|
||||
|
||||
/@typescript-eslint/utils/5.33.1_eslint@8.26.0+typescript@4.8.4:
|
||||
resolution: {integrity: sha512-uphZjkMaZ4fE8CR4dU7BquOV6u0doeQAr8n6cQenl/poMaIyJtBu8eys5uk6u5HiDH01Mj5lzbJ5SfeDz7oqMQ==}
|
||||
|
@ -17235,6 +17252,11 @@ packages:
|
|||
dependencies:
|
||||
yallist: 4.0.0
|
||||
|
||||
/lru-cache/7.14.0:
|
||||
resolution: {integrity: sha512-EIRtP1GrSJny0dqb50QXRUNBxHJhcpxHC++M5tD7RYbvLLn5KVWKsbyswSSqDuU15UFi3bgTQIY8nhDMeF6aDQ==}
|
||||
engines: {node: '>=12'}
|
||||
dev: false
|
||||
|
||||
/lunr/2.3.9:
|
||||
resolution: {integrity: sha512-zTU3DaZaF3Rt9rhN3uBMGQD3dD2/vFQqnvZCDv4dl5iOzq2IZQqTxu90r4E5J+nP70J3ilqVCrbho2eWaeW8Ow==}
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue