mirror of
https://github.com/portainer/portainer.git
synced 2026-08-07 09:54:49 +00:00
chore(hey-api): enable validator and upgrade [BE-13103] (#2919)
This commit is contained in:
@@ -3,6 +3,7 @@
|
||||
import { createClientConfig } from '@/react/portainer/services/axios/configure-hey-api';
|
||||
|
||||
import {
|
||||
type Client,
|
||||
type ClientOptions,
|
||||
type Config,
|
||||
createClient,
|
||||
@@ -22,6 +23,8 @@ export type CreateClientConfig<T extends ClientOptions = ClientOptions2> = (
|
||||
override?: Config<ClientOptions & T>
|
||||
) => Config<Required<ClientOptions> & T>;
|
||||
|
||||
export const client = createClient(
|
||||
createClientConfig(createConfig<ClientOptions2>({ throwOnError: true }))
|
||||
export const client: Client = createClient(
|
||||
createClientConfig(
|
||||
createConfig<ClientOptions2>({ baseURL: 'api', throwOnError: true })
|
||||
)
|
||||
);
|
||||
|
||||
@@ -9,6 +9,8 @@ export {
|
||||
} from '../core/bodySerializer.gen';
|
||||
export { buildClientParams } from '../core/params.gen';
|
||||
export { serializeQueryKeyValue } from '../core/queryKeySerializer.gen';
|
||||
export type { ServerSentEventsResult } from '../core/serverSentEvents.gen';
|
||||
export type { ClientMeta } from '../core/types.gen';
|
||||
export { createClient } from './client.gen';
|
||||
export type {
|
||||
Client,
|
||||
|
||||
@@ -18,8 +18,8 @@ import type {
|
||||
export const createQuerySerializer = <T = unknown>({
|
||||
parameters = {},
|
||||
...args
|
||||
}: QuerySerializerOptions = {}) => {
|
||||
const querySerializer = (queryParams: T) => {
|
||||
}: QuerySerializerOptions = {}): ((queryParams: T) => string) => {
|
||||
const querySerializer = (queryParams: T): string => {
|
||||
const search: string[] = [];
|
||||
if (queryParams && typeof queryParams === 'object') {
|
||||
for (const name in queryParams) {
|
||||
|
||||
@@ -9,6 +9,13 @@ export interface Auth {
|
||||
* @default 'header'
|
||||
*/
|
||||
in?: 'header' | 'query' | 'cookie';
|
||||
/**
|
||||
* A unique identifier for the security scheme.
|
||||
*
|
||||
* Defined only when there are multiple security schemes whose `Auth`
|
||||
* shape would otherwise be identical.
|
||||
*/
|
||||
key?: string;
|
||||
/**
|
||||
* Header or query parameter name.
|
||||
*
|
||||
|
||||
@@ -62,7 +62,7 @@ type KeyMap = Map<
|
||||
}
|
||||
>;
|
||||
|
||||
const buildKeyMap = (fields: FieldsConfig, map?: KeyMap): KeyMap => {
|
||||
function buildKeyMap(fields: FieldsConfig, map?: KeyMap): KeyMap {
|
||||
if (!map) {
|
||||
map = new Map();
|
||||
}
|
||||
@@ -85,17 +85,18 @@ const buildKeyMap = (fields: FieldsConfig, map?: KeyMap): KeyMap => {
|
||||
}
|
||||
|
||||
return map;
|
||||
};
|
||||
}
|
||||
|
||||
interface Params {
|
||||
body: unknown;
|
||||
body?: unknown;
|
||||
headers: Record<string, unknown>;
|
||||
path: Record<string, unknown>;
|
||||
query: Record<string, unknown>;
|
||||
}
|
||||
|
||||
const stripEmptySlots = (params: Params) => {
|
||||
function stripEmptySlots(params: Params): void {
|
||||
for (const [slot, value] of Object.entries(params)) {
|
||||
if (slot === 'body') continue;
|
||||
if (
|
||||
value &&
|
||||
typeof value === 'object' &&
|
||||
@@ -105,14 +106,13 @@ const stripEmptySlots = (params: Params) => {
|
||||
delete params[slot as Slot];
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
export const buildClientParams = (
|
||||
export function buildClientParams(
|
||||
args: ReadonlyArray<unknown>,
|
||||
fields: FieldsConfig
|
||||
) => {
|
||||
): Params {
|
||||
const params: Params = {
|
||||
body: Object.create(null),
|
||||
headers: Object.create(null),
|
||||
path: Object.create(null),
|
||||
query: Object.create(null),
|
||||
@@ -120,6 +120,15 @@ export const buildClientParams = (
|
||||
|
||||
const map = buildKeyMap(fields);
|
||||
|
||||
function writeSlot(slot: Slot, key: string, value: unknown): void {
|
||||
let record = params[slot] as Record<string, unknown> | undefined;
|
||||
if (record === undefined) {
|
||||
record = Object.create(null) as Record<string, unknown>;
|
||||
params[slot] = record;
|
||||
}
|
||||
record[key] = value;
|
||||
}
|
||||
|
||||
let config: FieldsConfig[number] | undefined;
|
||||
|
||||
for (const [index, arg] of args.entries()) {
|
||||
@@ -136,7 +145,7 @@ export const buildClientParams = (
|
||||
const field = map.get(config.key)!;
|
||||
const name = field.map || config.key;
|
||||
if (field.in) {
|
||||
(params[field.in] as Record<string, unknown>)[name] = arg;
|
||||
writeSlot(field.in, name, arg);
|
||||
}
|
||||
} else {
|
||||
params.body = arg;
|
||||
@@ -148,7 +157,7 @@ export const buildClientParams = (
|
||||
if (field) {
|
||||
if (field.in) {
|
||||
const name = field.map || key;
|
||||
(params[field.in] as Record<string, unknown>)[name] = value;
|
||||
writeSlot(field.in, name, value);
|
||||
} else {
|
||||
params[field.map] = value;
|
||||
}
|
||||
@@ -159,13 +168,11 @@ export const buildClientParams = (
|
||||
|
||||
if (extra) {
|
||||
const [prefix, slot] = extra;
|
||||
(params[slot] as Record<string, unknown>)[
|
||||
key.slice(prefix.length)
|
||||
] = value;
|
||||
writeSlot(slot, key.slice(prefix.length), value);
|
||||
} else if ('allowExtra' in config && config.allowExtra) {
|
||||
for (const [slot, allowed] of Object.entries(config.allowExtra)) {
|
||||
if (allowed) {
|
||||
(params[slot as Slot] as Record<string, unknown>)[key] = value;
|
||||
writeSlot(slot as Slot, key, value);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -178,4 +185,4 @@ export const buildClientParams = (
|
||||
stripEmptySlots(params);
|
||||
|
||||
return params;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -26,7 +26,9 @@ interface SerializePrimitiveParam extends SerializePrimitiveOptions {
|
||||
value: string;
|
||||
}
|
||||
|
||||
export const separatorArrayExplode = (style: ArraySeparatorStyle) => {
|
||||
export const separatorArrayExplode = (
|
||||
style: ArraySeparatorStyle
|
||||
): '.' | ';' | ',' | '&' => {
|
||||
switch (style) {
|
||||
case 'label':
|
||||
return '.';
|
||||
@@ -39,7 +41,9 @@ export const separatorArrayExplode = (style: ArraySeparatorStyle) => {
|
||||
}
|
||||
};
|
||||
|
||||
export const separatorArrayNoExplode = (style: ArraySeparatorStyle) => {
|
||||
export const separatorArrayNoExplode = (
|
||||
style: ArraySeparatorStyle
|
||||
): ',' | '|' | '%20' => {
|
||||
switch (style) {
|
||||
case 'form':
|
||||
return ',';
|
||||
@@ -52,7 +56,9 @@ export const separatorArrayNoExplode = (style: ArraySeparatorStyle) => {
|
||||
}
|
||||
};
|
||||
|
||||
export const separatorObjectExplode = (style: ObjectSeparatorStyle) => {
|
||||
export const separatorObjectExplode = (
|
||||
style: ObjectSeparatorStyle
|
||||
): '.' | ';' | ',' | '&' => {
|
||||
switch (style) {
|
||||
case 'label':
|
||||
return '.';
|
||||
@@ -73,7 +79,7 @@ export const serializeArrayParam = ({
|
||||
value,
|
||||
}: SerializeOptions<ArraySeparatorStyle> & {
|
||||
value: unknown[];
|
||||
}) => {
|
||||
}): string => {
|
||||
if (!explode) {
|
||||
const joinedValues = (
|
||||
allowReserved ? value : value.map((v) => encodeURIComponent(v as string))
|
||||
@@ -113,7 +119,7 @@ export const serializePrimitiveParam = ({
|
||||
allowReserved,
|
||||
name,
|
||||
value,
|
||||
}: SerializePrimitiveParam) => {
|
||||
}: SerializePrimitiveParam): string => {
|
||||
if (value === undefined || value === null) {
|
||||
return '';
|
||||
}
|
||||
@@ -137,7 +143,7 @@ export const serializeObjectParam = ({
|
||||
}: SerializeOptions<ObjectSeparatorStyle> & {
|
||||
value: Record<string, unknown> | Date;
|
||||
valueOnly?: boolean;
|
||||
}) => {
|
||||
}): string => {
|
||||
if (value instanceof Date) {
|
||||
return valueOnly ? value.toISOString() : `${name}=${value.toISOString()}`;
|
||||
}
|
||||
|
||||
@@ -14,7 +14,10 @@ export type JsonValue =
|
||||
/**
|
||||
* Replacer that converts non-JSON values (bigint, Date, etc.) to safe substitutes.
|
||||
*/
|
||||
export const queryKeyJsonReplacer = (_key: string, value: unknown) => {
|
||||
export const queryKeyJsonReplacer = (
|
||||
_key: string,
|
||||
value: unknown
|
||||
): unknown | undefined => {
|
||||
if (
|
||||
value === undefined ||
|
||||
typeof value === 'function' ||
|
||||
|
||||
@@ -103,6 +103,12 @@ export interface Config {
|
||||
responseValidator?: (data: unknown) => Promise<unknown>;
|
||||
}
|
||||
|
||||
/**
|
||||
* Arbitrary metadata passed through the `meta` request option.
|
||||
*/
|
||||
// eslint-disable-next-line @typescript-eslint/no-empty-object-type
|
||||
export interface ClientMeta {}
|
||||
|
||||
type IsExactlyNeverOrNeverUndefined<T> = [T] extends [never]
|
||||
? true
|
||||
: [T] extends [never | undefined]
|
||||
|
||||
@@ -13,9 +13,12 @@ export interface PathSerializer {
|
||||
url: string;
|
||||
}
|
||||
|
||||
export const PATH_PARAM_RE = /\{[^{}]+\}/g;
|
||||
export const PATH_PARAM_RE: RegExp = /\{[^{}]+\}/g;
|
||||
|
||||
export const defaultPathSerializer = ({ path, url: _url }: PathSerializer) => {
|
||||
export const defaultPathSerializer = ({
|
||||
path,
|
||||
url: _url,
|
||||
}: PathSerializer): string => {
|
||||
let url = _url;
|
||||
const matches = _url.match(PATH_PARAM_RE);
|
||||
if (matches) {
|
||||
@@ -97,7 +100,7 @@ export const getUrl = ({
|
||||
query?: Record<string, unknown>;
|
||||
querySerializer: QuerySerializer;
|
||||
url: string;
|
||||
}) => {
|
||||
}): string => {
|
||||
const pathUrl = _url.startsWith('/') ? _url : `/${_url}`;
|
||||
let url = (baseUrl ?? '') + pathUrl;
|
||||
if (path) {
|
||||
@@ -117,7 +120,7 @@ export function getValidRequestBody(options: {
|
||||
body?: unknown;
|
||||
bodySerializer?: BodySerializer | null;
|
||||
serializedBody?: unknown;
|
||||
}) {
|
||||
}): unknown {
|
||||
const hasBody = options.body !== undefined;
|
||||
const isSerializedBody = hasBody && options.bodySerializer;
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -22,7 +22,7 @@ export default defineConfig({
|
||||
},
|
||||
{
|
||||
name: '@hey-api/sdk',
|
||||
// validator: true, TODO revert in BE-13103
|
||||
validator: true,
|
||||
},
|
||||
{
|
||||
name: '@hey-api/client-axios',
|
||||
|
||||
+1
-1
@@ -152,7 +152,7 @@
|
||||
"@eslint-community/eslint-plugin-eslint-comments": "^4.7.2",
|
||||
"@eslint/eslintrc": "^3.3.5",
|
||||
"@eslint/js": "^10.0.1",
|
||||
"@hey-api/openapi-ts": "0.97.3",
|
||||
"@hey-api/openapi-ts": "0.99.0",
|
||||
"@simbathesailor/use-what-changed": "^2.0.0",
|
||||
"@storybook/addon-docs": "10.4.2",
|
||||
"@storybook/addon-links": "10.4.2",
|
||||
|
||||
Generated
+45
-30
@@ -368,8 +368,8 @@ importers:
|
||||
specifier: ^10.0.1
|
||||
version: 10.0.1(eslint@9.39.4(jiti@2.7.0))
|
||||
'@hey-api/openapi-ts':
|
||||
specifier: 0.97.3
|
||||
version: 0.97.3(magicast@0.5.2)(typescript@6.0.2)
|
||||
specifier: 0.99.0
|
||||
version: 0.99.0(magicast@0.5.2)(typescript@6.0.2)
|
||||
'@simbathesailor/use-what-changed':
|
||||
specifier: ^2.0.0
|
||||
version: 2.0.0(react@17.0.2)
|
||||
@@ -1658,24 +1658,24 @@ packages:
|
||||
'@floating-ui/utils@0.2.11':
|
||||
resolution: {integrity: sha512-RiB/yIh78pcIxl6lLMG0CgBXAZ2Y0eVHqMPYugu+9U0AeT6YBeiJpf7lbdJNIugFP5SIjwNRgo4DhR1Qxi26Gg==}
|
||||
|
||||
'@hey-api/codegen-core@0.8.2':
|
||||
resolution: {integrity: sha512-R2NMf3wq97rh1mjz33WJQU8svz3F0RYUjvx/QzXucjpSqQ3O5huTdDjErG4fMxSr1X+X56NuDrqtGfHmo1TRUQ==}
|
||||
engines: {node: '>=22.13.0'}
|
||||
'@hey-api/codegen-core@0.9.1':
|
||||
resolution: {integrity: sha512-s97jL1dgTMuiMHv2BZ1X4Tgd99Mf9GOvGdNqNcGwIMmnR+PgYNoraj4Zvp134MKsNCap/m7k0r0vKKnl56pj4w==}
|
||||
engines: {node: '>=22.18.0'}
|
||||
|
||||
'@hey-api/json-schema-ref-parser@1.4.2':
|
||||
resolution: {integrity: sha512-ZhCFSKI2ipZHEbgmtUHdyddvRU3wJ4elgCfYUC7T7hZa4EivSrVflTQf2w+v3TuaYxR1Y2V2kq3otqTttrrK8Q==}
|
||||
engines: {node: '>=22.13.0'}
|
||||
'@hey-api/json-schema-ref-parser@1.4.4':
|
||||
resolution: {integrity: sha512-otmd+zCxbYVBIp/mlMTnGkvlNYLkVKgs3VOIq0kSnenhB1+fRwLPQIeSwyWM6E51oXhUedkYjVsVpkVexeuJOA==}
|
||||
engines: {node: '>=22.18.0'}
|
||||
|
||||
'@hey-api/openapi-ts@0.97.3':
|
||||
resolution: {integrity: sha512-4sR6/E/POuy7aPZW9DDjhObzZCq7eSJWiW0+epXeKNczoTWEwdOyWFy9Ca/CnXYlZ3oJsrv0ZD0OO+YuczT7CA==}
|
||||
engines: {node: '>=22.13.0'}
|
||||
'@hey-api/openapi-ts@0.99.0':
|
||||
resolution: {integrity: sha512-SePU/5oEWWkvUBYmvzdYRctseoLuskyhs4ET0RvLIcmzc8yLQoA2R+KtBIQ8bPsoSUB0m4E5SmBnl6aGSA0szQ==}
|
||||
engines: {node: '>=22.18.0'}
|
||||
hasBin: true
|
||||
peerDependencies:
|
||||
typescript: '>=5.5.3 || >=6.0.0 || 6.0.1-rc'
|
||||
|
||||
'@hey-api/shared@0.4.5':
|
||||
resolution: {integrity: sha512-au4eHpBXAe1du0iMp6ESYuEaMS2jsoEyrbcT246btRhI9rMeQFEs7ZjtcMGXGsxhpaR38A8cPGNHx7QOrWAdMw==}
|
||||
engines: {node: '>=22.13.0'}
|
||||
'@hey-api/shared@0.5.0':
|
||||
resolution: {integrity: sha512-JN/j4Ebh4cJGYIQ5cwWuqe7GeSUyQoz7oC51WqyhKOcrejK6DKZMDkshc5d1eKTRuRL+rjozuRcoUaZZn2DGPw==}
|
||||
engines: {node: '>=22.18.0'}
|
||||
|
||||
'@hey-api/spec-types@0.2.0':
|
||||
resolution: {integrity: sha512-ibQ8Is7evMavzr8GNyJCcTg975d8DpaMUyLmOrQ85UBdy1l6t1KuRAwgChAbesJsIlNV6gjmlXruWyegDX18Fg==}
|
||||
@@ -4414,9 +4414,9 @@ packages:
|
||||
resolution: {integrity: sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA==}
|
||||
engines: {node: '>=18'}
|
||||
|
||||
commander@14.0.3:
|
||||
resolution: {integrity: sha512-H+y0Jo/T1RZ9qPP4Eh1pkcQcLRglraJaSLoyOtHxu6AapkjWVCy2Sit1QQ4x3Dng8qDlSsZEet7g5Pq06MvTgw==}
|
||||
engines: {node: '>=20'}
|
||||
commander@15.0.0:
|
||||
resolution: {integrity: sha512-z67u4ZhzCL/Tydu1lJARtEZYWbWaN7oYLHbsuzocr6y4N6WZAagG3RQ4FW61V1/0+jImpj293XfrcYnd1qxtPg==}
|
||||
engines: {node: '>=22.12.0'}
|
||||
|
||||
commander@2.20.3:
|
||||
resolution: {integrity: sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==}
|
||||
@@ -5945,6 +5945,10 @@ packages:
|
||||
resolution: {integrity: sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==}
|
||||
hasBin: true
|
||||
|
||||
js-yaml@4.2.0:
|
||||
resolution: {integrity: sha512-ePWsvanv0DWuDRsW8dnt+R4jQ31SCRCQ7hhNcPXZPsoBZiemuZNYGf7adZdqX2D86j6rvKp3RpCxVTSb8WQlOw==}
|
||||
hasBin: true
|
||||
|
||||
jsdom@24.1.3:
|
||||
resolution: {integrity: sha512-MyL55p3Ut3cXbeBEG7Hcv0mVM8pp8PBNWxRqchZnSfAiES1v1mRnMeFfaHWIPULpwsYfvO+ZmMZz5tGCnjzDUQ==}
|
||||
engines: {node: '>=18'}
|
||||
@@ -7620,6 +7624,11 @@ packages:
|
||||
engines: {node: '>=10'}
|
||||
hasBin: true
|
||||
|
||||
semver@7.8.4:
|
||||
resolution: {integrity: sha512-rUCObTnP32Q08R2uuIrt7r9PlEonuTmtuXYcW6s5kjdlj3xbnwe+21yXptAUYcMAABLkYYTtnmzb3w3EDZfueA==}
|
||||
engines: {node: '>=10'}
|
||||
hasBin: true
|
||||
|
||||
send@0.19.2:
|
||||
resolution: {integrity: sha512-VMbMxbDeehAxpOtWJXlcUS5E8iXh6QmN+BkRX1GARS3wRaXEEgzCcB10gTQazO42tpNIya8xIyNx8fll1OFPrg==}
|
||||
engines: {node: '>= 0.8.0'}
|
||||
@@ -9999,7 +10008,7 @@ snapshots:
|
||||
|
||||
'@floating-ui/utils@0.2.11': {}
|
||||
|
||||
'@hey-api/codegen-core@0.8.2(magicast@0.5.2)':
|
||||
'@hey-api/codegen-core@0.9.1(magicast@0.5.2)':
|
||||
dependencies:
|
||||
'@hey-api/types': 0.1.4
|
||||
ansi-colors: 4.1.3
|
||||
@@ -10008,38 +10017,38 @@ snapshots:
|
||||
transitivePeerDependencies:
|
||||
- magicast
|
||||
|
||||
'@hey-api/json-schema-ref-parser@1.4.2':
|
||||
'@hey-api/json-schema-ref-parser@1.4.4':
|
||||
dependencies:
|
||||
'@jsdevtools/ono': 7.1.3
|
||||
'@types/json-schema': 7.0.15
|
||||
js-yaml: 4.1.1
|
||||
js-yaml: 4.2.0
|
||||
|
||||
'@hey-api/openapi-ts@0.97.3(magicast@0.5.2)(typescript@6.0.2)':
|
||||
'@hey-api/openapi-ts@0.99.0(magicast@0.5.2)(typescript@6.0.2)':
|
||||
dependencies:
|
||||
'@hey-api/codegen-core': 0.8.2(magicast@0.5.2)
|
||||
'@hey-api/json-schema-ref-parser': 1.4.2
|
||||
'@hey-api/shared': 0.4.5(magicast@0.5.2)
|
||||
'@hey-api/codegen-core': 0.9.1(magicast@0.5.2)
|
||||
'@hey-api/json-schema-ref-parser': 1.4.4
|
||||
'@hey-api/shared': 0.5.0(magicast@0.5.2)
|
||||
'@hey-api/spec-types': 0.2.0
|
||||
'@hey-api/types': 0.1.4
|
||||
'@lukeed/ms': 2.0.2
|
||||
ansi-colors: 4.1.3
|
||||
color-support: 1.1.3
|
||||
commander: 14.0.3
|
||||
commander: 15.0.0
|
||||
get-tsconfig: 4.14.0
|
||||
typescript: 6.0.2
|
||||
transitivePeerDependencies:
|
||||
- magicast
|
||||
|
||||
'@hey-api/shared@0.4.5(magicast@0.5.2)':
|
||||
'@hey-api/shared@0.5.0(magicast@0.5.2)':
|
||||
dependencies:
|
||||
'@hey-api/codegen-core': 0.8.2(magicast@0.5.2)
|
||||
'@hey-api/json-schema-ref-parser': 1.4.2
|
||||
'@hey-api/codegen-core': 0.9.1(magicast@0.5.2)
|
||||
'@hey-api/json-schema-ref-parser': 1.4.4
|
||||
'@hey-api/spec-types': 0.2.0
|
||||
'@hey-api/types': 0.1.4
|
||||
ansi-colors: 4.1.3
|
||||
cross-spawn: 7.0.6
|
||||
open: 11.0.0
|
||||
semver: 7.7.4
|
||||
semver: 7.8.4
|
||||
transitivePeerDependencies:
|
||||
- magicast
|
||||
|
||||
@@ -12910,7 +12919,7 @@ snapshots:
|
||||
|
||||
commander@12.1.0: {}
|
||||
|
||||
commander@14.0.3: {}
|
||||
commander@15.0.0: {}
|
||||
|
||||
commander@2.20.3: {}
|
||||
|
||||
@@ -14668,6 +14677,10 @@ snapshots:
|
||||
dependencies:
|
||||
argparse: 2.0.1
|
||||
|
||||
js-yaml@4.2.0:
|
||||
dependencies:
|
||||
argparse: 2.0.1
|
||||
|
||||
jsdom@24.1.3:
|
||||
dependencies:
|
||||
cssstyle: 4.0.1
|
||||
@@ -16464,6 +16477,8 @@ snapshots:
|
||||
|
||||
semver@7.7.4: {}
|
||||
|
||||
semver@7.8.4: {}
|
||||
|
||||
send@0.19.2:
|
||||
dependencies:
|
||||
debug: 2.6.9
|
||||
|
||||
Reference in New Issue
Block a user