Pārlūkot izejas kodu

Refactor codebase

Remove unnecessary dependencies, ensure everything is working (script and noscript).
master
TheoryOfNekomata pirms 1 gada
vecāks
revīzija
a3dae0671b
16 mainītis faili ar 145 papildinājumiem un 190 dzēšanām
  1. +0
    -5
      packages/iceform-next-sandbox/next.config.js
  2. +4
    -4
      packages/iceform-next-sandbox/src/handlers/note.ts
  3. +1
    -2
      packages/iceform-next/package.json
  4. +4
    -1
      packages/iceform-next/src/client/components/Form.tsx
  5. +1
    -1
      packages/iceform-next/src/client/hooks/useFormFetch.ts
  6. +5
    -0
      packages/iceform-next/src/common/constants.ts
  7. +3
    -0
      packages/iceform-next/src/server/action/common.ts
  8. +19
    -14
      packages/iceform-next/src/server/action/gssp.ts
  9. +39
    -19
      packages/iceform-next/src/server/cache.ts
  10. +0
    -3
      packages/iceform-next/src/server/constants.ts
  11. +20
    -15
      packages/iceform-next/src/server/destination.ts
  12. +3
    -2
      packages/iceform-next/src/server/response.ts
  13. +0
    -56
      packages/iceform-next/src/utils/cookies.ts
  14. +5
    -0
      packages/iceform-next/src/utils/request.ts
  15. +25
    -14
      packages/iceform-next/src/utils/serialization.ts
  16. +16
    -54
      pnpm-lock.yaml

+ 0
- 5
packages/iceform-next-sandbox/next.config.js Parādīt failu

@@ -4,11 +4,6 @@ const nextConfig = {
experimental: {
optimizeCss: true,
},
webpack: (config) => {
config.resolve.fallback = { fs: false };

return config;
},
};

module.exports = nextConfig;

+ 4
- 4
packages/iceform-next-sandbox/src/handlers/note.ts Parādīt failu

@@ -73,9 +73,9 @@ const patchNote: NextApiHandler = async (req, res) => {

const updatedNote = {
...note,
title: title ?? note.title,
content: content ?? note.content,
image: image ?? note.image,
title: title || note.title,
content: content || note.content,
image: image ? `data:${image.type};base64,${image.toString('base64')}` : note.image,
};

data[noteIndex] = updatedNote;
@@ -225,7 +225,7 @@ const createNote = (params: NoteCollectionParams): NextApiHandler => async (req,
id: newId,
title,
content,
image,
image: `data:${image.type};base64,${image.toString('base64')}`,
});
};



+ 1
- 2
packages/iceform-next/package.json Parādīt failu

@@ -68,9 +68,8 @@
},
"dependencies": {
"@theoryofnekomata/formxtra": "^1.0.3",
"@web-std/file": "^3.0.3",
"busboy": "^1.6.0",
"nookies": "^2.5.2",
"node-cache": "^5.1.2",
"seroval": "^0.10.2"
},
"exports": {


+ 4
- 1
packages/iceform-next/src/client/components/Form.tsx Parādīt failu

@@ -29,6 +29,7 @@ export interface FormProps extends Omit<React.HTMLProps<FormDerivedElement>, 'ac
responseEncType?: string;
serializerOptions?: SerializerOptions;
disableFetch?: boolean;
methodFormKey?: string;
}

export const Form = React.forwardRef<FormDerivedElement, FormProps>(({
@@ -46,6 +47,7 @@ export const Form = React.forwardRef<FormDerivedElement, FormProps>(({
responseEncType = ENCTYPE_APPLICATION_JSON,
serializerOptions,
disableFetch = false,
methodFormKey = METHOD_FORM_KEY,
...etcProps
}, forwardedRef) => {
const { handleSubmit } = useFormFetch({
@@ -83,7 +85,7 @@ export const Form = React.forwardRef<FormDerivedElement, FormProps>(({
encType={ENCTYPE_MULTIPART_FORM_DATA}
>
{serverMethodOverride && (
<input type="hidden" name={METHOD_FORM_KEY} value={clientMethod} />
<input type="hidden" name={methodFormKey} value={clientMethod} />
)}
{children}
</FormDerivedElementComponent>
@@ -104,4 +106,5 @@ Form.defaultProps = {
refresh: undefined,
responseEncType: ENCTYPE_APPLICATION_JSON,
serializerOptions: undefined,
methodFormKey: METHOD_FORM_KEY,
};

+ 1
- 1
packages/iceform-next/src/client/hooks/useFormFetch.ts Parādīt failu

@@ -58,7 +58,7 @@ export const useFormFetch = ({
form: event.currentTarget,
encType,
serializers: encTypeSerializers,
options: {
serializerOptions: {
...serializerOptions,
submitter,
},


+ 5
- 0
packages/iceform-next/src/common/constants.ts Parādīt failu

@@ -1,3 +1,8 @@
export const PREVENT_REDIRECT_FORM_KEY = '__iceform_prevent_redirect' as const;
export const METHOD_FORM_KEY = '__iceform_method' as const;
export const METHODS_WITH_BODY = ['POST', 'PUT', 'PATCH', 'DELETE'] as const;
export const REQUEST_ID_FORM_KEY = '__iceform_request_id' as const;
export const CONTENT_TYPE_HEADER_KEY = 'content-type' as const;
export const LOCATION_HEADER_KEY = 'location' as const;
export const CONTENT_ENCODING_HEADER_KEY = 'content-encoding' as const;
export const DEFAULT_ENCODING = 'utf-8' as const;

+ 3
- 0
packages/iceform-next/src/server/action/common.ts Parādīt failu

@@ -23,6 +23,9 @@ export interface ActionWrapperOptions {
fn: NextApiHandler,
onAction?: OnActionFunction,
deserializers?: EncTypeDeserializerMap,
methodFormKey?: string,
requestIdFormKey?: string,
preventRedirectFormKey?: string,
/**
* Maps the Location header from the handler response to an accessible URL.
* @param url


+ 19
- 14
packages/iceform-next/src/server/action/gssp.ts Parādīt failu

@@ -7,7 +7,11 @@ import {
deserializeFormObjectBody,
EncTypeDeserializerMap,
} from '../../utils/serialization';
import { METHOD_FORM_KEY, PREVENT_REDIRECT_FORM_KEY } from '../../common/constants';
import {
METHOD_FORM_KEY,
PREVENT_REDIRECT_FORM_KEY,
REQUEST_ID_FORM_KEY,
} from '../../common/constants';
import { ACTION_STATUS_CODE, DEFAULT_METHOD } from '../constants';
import { getBody } from '../../utils/request';
import {
@@ -16,25 +20,21 @@ import {
} from '../../common/enctypes';
import { ActionWrapperOptions } from './common';
import { IceformNextServerResponse } from '../response';
import {
REQUEST_ID_COOKIE_KEY,
CookieManager,
} from '../../utils/cookies';
import { cacheResponse } from '../cache';

const getFormObjectMethodAndBody = async (
req: IncomingMessage,
deserializers: EncTypeDeserializerMap,
methodFormKey = METHOD_FORM_KEY as string,
) => {
const deserialized = await deserializeFormObjectBody({
req,
deserializers,
});
const {
[METHOD_FORM_KEY]: method = req.method ?? DEFAULT_METHOD,
[methodFormKey]: method = req.method ?? DEFAULT_METHOD,
...body
} = deserialized as {
[METHOD_FORM_KEY]?: string,
[key: string]: unknown,
};

@@ -80,7 +80,11 @@ export const getServerSideProps = (options: ActionWrapperOptions): GetServerSide
? getFormObjectMethodAndBody
: getBinaryMethodAndBody
);
const { body, method } = await methodAndBodyFn(ctx.req, deserializers);
const { body, method } = await methodAndBodyFn(
ctx.req,
deserializers,
options.methodFormKey ?? METHOD_FORM_KEY,
);
const req = {
...ctx.req,
body,
@@ -93,9 +97,7 @@ export const getServerSideProps = (options: ActionWrapperOptions): GetServerSide
} as DefaultNextApiRequest;
const res = new IceformNextServerResponse(ctx.req);
await options.fn(req, res);
const requestId = crypto.randomUUID();
const cookieManager = new CookieManager(ctx);
cookieManager.setCookie(REQUEST_ID_COOKIE_KEY, requestId);
const requestId = crypto.randomBytes(8).toString('base64url');
await cacheResponse(requestId, res);

if (typeof options.onAction === 'function') {
@@ -112,9 +114,9 @@ export const getServerSideProps = (options: ActionWrapperOptions): GetServerSide
const preventRedirect = (
typeof req.body === 'object'
&& req.body !== null
&& PREVENT_REDIRECT_FORM_KEY in req.body
&& (options.preventRedirectFormKey ?? PREVENT_REDIRECT_FORM_KEY) in req.body
);
const redirectDestination = (
const redirectDestinationRaw = (
res.location
&& typeof options.mapLocationToRedirectDestination === 'function'
&& !preventRedirect
@@ -122,9 +124,12 @@ export const getServerSideProps = (options: ActionWrapperOptions): GetServerSide
? options.mapLocationToRedirectDestination(referer, res.location)
: referer;

const url = new URL(redirectDestinationRaw, 'http://example.com');
url.searchParams.set(options.requestIdFormKey ?? REQUEST_ID_FORM_KEY, requestId);

return {
redirect: {
destination: redirectDestination,
destination: `/${url.pathname}${url.search}`,
statusCode: ACTION_STATUS_CODE,
},
props: {


+ 39
- 19
packages/iceform-next/src/server/cache.ts Parādīt failu

@@ -1,5 +1,6 @@
import { createWriteStream } from 'fs';
import { readFile, unlink } from 'fs/promises';
import NodeCache from 'node-cache';
import { STATUS_CODES } from 'http';
import { DEFAULT_RESPONSE_STATUS_CODE } from './constants';

interface CacheableResponse {
statusCode: number;
@@ -8,41 +9,60 @@ interface CacheableResponse {
data?: unknown;
}

const getFilePathFromRequestId = (requestId: string) => `${requestId}`;
const cache = new NodeCache({
deleteOnExpire: true,
stdTTL: 60,
});

export const cacheResponse = async (requestId: string, res: CacheableResponse) => {
const filePath = getFilePathFromRequestId(requestId);
const cacheStream = createWriteStream(filePath, { encoding: 'utf-8' });
cacheStream.write(`${res.statusCode.toString()} ${res.statusMessage || ''}\n`);
let cacheValue = '';
cacheValue += `${res.statusCode.toString()} ${res.statusMessage || ''}\n`;
if (res.contentType) {
cacheStream.write(`Content-Type: ${res.contentType}\n`);
cacheValue += `Content-Type: ${res.contentType}\n`;
}
if (res.data) {
cacheStream.write('\n');
cacheStream.write(res.data as string);
cacheValue += `\n${res.data as string}`;
}

return new Promise((resolve) => {
cacheStream.close(resolve);
return new Promise<void>((resolve) => {
cache.set(requestId, cacheValue);
resolve();
});
};

export const retrieveCache = async (requestId: string) => {
const filePath = getFilePathFromRequestId(requestId);
const requestBuffer = await readFile(filePath, 'utf-8');
await unlink(filePath);
const [statusLine, ...headersAndBody] = requestBuffer.split('\n');
const parseCacheValue = (cacheValue: string) => {
const [statusLine, ...headersAndBody] = cacheValue.split('\n');
const [statusCode, ...statusMessageWords] = statusLine.split(' ');
const statusMessage = statusMessageWords.join(' ');
const bodyStart = headersAndBody.findIndex((line) => line === '');
const headers = headersAndBody.slice(0, bodyStart);
const body = headersAndBody.slice(bodyStart + 1).join('\n');
const data = headersAndBody.slice(bodyStart + 1).join('\n');
const contentTypeHeader = headers.find((header) => header.toLowerCase().startsWith('content-type:'));
const contentType = contentTypeHeader?.split(':')[1].trim();
return {
statusCode: parseInt(statusCode, 10),
statusMessage,
statusMessage: statusMessage || STATUS_CODES[statusCode],
contentType,
body,
data,
};
};

export const retrieveCache = async (requestId: string) => new Promise<
CacheableResponse
>((resolve) => {
const requestBuffer = cache.get<string>(requestId);

if (!requestBuffer) {
resolve({
statusCode: DEFAULT_RESPONSE_STATUS_CODE,
statusMessage: STATUS_CODES[DEFAULT_RESPONSE_STATUS_CODE],
contentType: undefined,
data: '',
});
return;
}

cache.del(requestId);
const value = parseCacheValue(requestBuffer);
resolve(value);
});

+ 0
- 3
packages/iceform-next/src/server/constants.ts Parādīt failu

@@ -1,6 +1,3 @@
export const DEFAULT_METHOD = 'GET' as const;
export const DEFAULT_ENCODING = 'utf-8' as const;
export const ACTION_STATUS_CODE = 307 as const; // temporary redirect
export const DEFAULT_RESPONSE_STATUS_CODE = 200 as const; // ok
export const CONTENT_TYPE_HEADER_KEY = 'content-type' as const;
export const LOCATION_HEADER_KEY = 'location' as const;

+ 20
- 15
packages/iceform-next/src/server/destination.ts Parādīt failu

@@ -2,11 +2,10 @@ import { ParsedUrlQuery } from 'querystring';
import { GetServerSideProps, GetServerSidePropsContext, PreviewData } from 'next';
import { deserialize } from 'seroval';
import { NextApiRequest, NextApiResponse } from '../common/types';
import { DEFAULT_ENCODING, DEFAULT_METHOD } from './constants';
import { DEFAULT_METHOD } from './constants';
import { getBody } from '../utils/request';
import { REQUEST_ID_COOKIE_KEY, CookieManager } from '../utils/cookies';
import { ENCTYPE_APPLICATION_JSON, ENCTYPE_APPLICATION_OCTET_STREAM } from '../common/enctypes';
import { METHODS_WITH_BODY } from '../common/constants';
import { METHODS_WITH_BODY, REQUEST_ID_FORM_KEY, DEFAULT_ENCODING } from '../common/constants';
import { retrieveCache } from './cache';

export type DestinationGetServerSideProps<
@@ -21,6 +20,7 @@ export type DestinationGetServerSideProps<

export interface DestinationWrapperOptions {
fn?: DestinationGetServerSideProps;
requestIdKey?: string;
}

export const getServerSideProps = (
@@ -41,26 +41,31 @@ export const getServerSideProps = (
}

const res: NextApiResponse = {};

const cookieManager = new CookieManager(ctx);
const resRequestId = cookieManager.getCookie(REQUEST_ID_COOKIE_KEY);
cookieManager.unsetCookie(REQUEST_ID_COOKIE_KEY);
const resRequestId = ctx.query[
options.requestIdKey ?? REQUEST_ID_FORM_KEY
] as string | undefined;
if (resRequestId) {
const {
statusCode,
statusMessage,
contentType,
body: resBody,
data: resBody,
} = await retrieveCache(resRequestId);
ctx.res.statusCode = statusCode;
ctx.res.statusMessage = statusMessage;
if (contentType === ENCTYPE_APPLICATION_JSON) {
res.body = deserialize(resBody);
} else if (contentType === ENCTYPE_APPLICATION_OCTET_STREAM) {
res.body = deserialize(resBody);
if (typeof statusMessage !== 'undefined') {
ctx.res.statusMessage = statusMessage;
}
if (resBody) {
if (contentType === ENCTYPE_APPLICATION_JSON) {
res.body = deserialize(resBody as string);
} else if (contentType === ENCTYPE_APPLICATION_OCTET_STREAM) {
res.body = deserialize(resBody as string);
} else {
const c = console;
c.warn('Could not parse response body, returning nothing');
res.body = null;
}
} else {
const c = console;
c.warn('Could not parse response body, returning nothing');
res.body = null;
}
}


+ 3
- 2
packages/iceform-next/src/server/response.ts Parādīt failu

@@ -1,11 +1,12 @@
import { ServerResponse } from 'http';
import { NextApiResponse as DefaultNextApiResponse } from 'next/dist/shared/lib/utils';
import { serialize } from 'seroval';

import { ENCTYPE_APPLICATION_JSON, ENCTYPE_APPLICATION_OCTET_STREAM } from '../common/enctypes';
import {
ACTION_STATUS_CODE, CONTENT_TYPE_HEADER_KEY, LOCATION_HEADER_KEY, DEFAULT_RESPONSE_STATUS_CODE,
ACTION_STATUS_CODE,
DEFAULT_RESPONSE_STATUS_CODE,
} from './constants';
import { CONTENT_TYPE_HEADER_KEY, LOCATION_HEADER_KEY } from '../common/constants';

// for client-side
class DummyServerResponse {}


+ 0
- 56
packages/iceform-next/src/utils/cookies.ts Parādīt failu

@@ -1,56 +0,0 @@
import { IncomingMessage, ServerResponse } from 'http';
import * as nookies from 'nookies';
import * as crypto from 'crypto';

const COMMON_COOKIE_CONFIG = {
path: '/',
httpOnly: true,
};

const COMMON_SET_COOKIE_CONFIG = {
...COMMON_COOKIE_CONFIG,
maxAge: 30 * 24 * 60 * 60,
};

const cookieKeys: Record<string, string> = {};

export const REQUEST_ID_COOKIE_KEY = 'b' as const;
export class CookieManager {
private readonly ctx: { req: IncomingMessage, res: ServerResponse<IncomingMessage> };

constructor(ctx: { req: IncomingMessage, res: ServerResponse<IncomingMessage> }) {
// noop
this.ctx = ctx;
}

private static generateCookieKey(key: string) {
const random = crypto.randomBytes(16).toString('hex');
return `if${key}${random}`;
}

setCookie(key: string, value: string) {
// cleanup previous cookie
this.unsetCookie(key);
cookieKeys[key] = CookieManager.generateCookieKey(key);
nookies.setCookie(
this.ctx,
cookieKeys[key],
value,
COMMON_SET_COOKIE_CONFIG,
);
}

unsetCookie(key: string) {
nookies.destroyCookie(this.ctx, cookieKeys[key], COMMON_COOKIE_CONFIG);
}

hasCookie(key: string) {
const cookies = nookies.parseCookies(this.ctx);
return cookieKeys[key] in cookies;
}

getCookie(key: string) {
const cookies = nookies.parseCookies(this.ctx);
return cookies[cookieKeys[key]];
}
}

+ 5
- 0
packages/iceform-next/src/utils/request.ts Parādīt failu

@@ -37,6 +37,11 @@ export const parseMultipartFormData = async (
});

file.on('close', () => {
// filename can be undefined somehow...
if (!filename && buffer.length <= 0) {
return;
}

const bufferMut = buffer as unknown as Record<string, unknown>;
bufferMut.name = filename;
bufferMut.type = mimeType;


+ 25
- 14
packages/iceform-next/src/utils/serialization.ts Parādīt failu

@@ -6,8 +6,13 @@ import {
ENCTYPE_X_WWW_FORM_URLENCODED,
} from '../common/enctypes';
import { getBody, parseMultipartFormData } from './request';
import { METHOD_FORM_KEY, PREVENT_REDIRECT_FORM_KEY } from '../common/constants';
import { DEFAULT_ENCODING } from '../server/constants';
import {
METHOD_FORM_KEY,
PREVENT_REDIRECT_FORM_KEY,
CONTENT_ENCODING_HEADER_KEY,
CONTENT_TYPE_HEADER_KEY,
DEFAULT_ENCODING,
} from '../common/constants';

export type EncTypeSerializer = (data: unknown) => string;

@@ -19,7 +24,9 @@ export interface SerializeBodyParams {
form: HTMLFormElement,
encType: string,
serializers?: EncTypeSerializerMap,
options?: SerializerOptions,
serializerOptions?: SerializerOptions,
methodFormKey?: string,
preventRedirectFormKey?: string,
}

export const DEFAULT_ENCTYPE_SERIALIZERS: EncTypeSerializerMap = {
@@ -31,13 +38,15 @@ export const serializeBody = (params: SerializeBodyParams) => {
form,
encType,
serializers = DEFAULT_ENCTYPE_SERIALIZERS,
options,
serializerOptions,
methodFormKey = METHOD_FORM_KEY,
preventRedirectFormKey = PREVENT_REDIRECT_FORM_KEY,
} = params;

if (encType === ENCTYPE_X_WWW_FORM_URLENCODED) {
const searchParams = new URLSearchParams(form);
searchParams.delete(METHOD_FORM_KEY);
searchParams.delete(PREVENT_REDIRECT_FORM_KEY);
searchParams.delete(methodFormKey);
searchParams.delete(preventRedirectFormKey);
return searchParams;
}

@@ -48,23 +57,25 @@ export const serializeBody = (params: SerializeBodyParams) => {
entries: () => IterableIterator<[string, unknown]>;
};
};
const formData = new FormDataUnknown(form, options?.submitter);
const formData = new FormDataUnknown(form, serializerOptions?.submitter);
const emptyFiles = Array.from(formData.entries())
.filter(([, value]) => (
value instanceof File && value.size === 0 && value.name === ''
));
emptyFiles.forEach(([key]) => formData.delete(key));
formData.delete(METHOD_FORM_KEY);
formData.delete(PREVENT_REDIRECT_FORM_KEY);
formData.delete(methodFormKey);
formData.delete(preventRedirectFormKey);
return formData;
}

if (typeof serializers[encType] === 'function') {
const {
[METHOD_FORM_KEY]: _method,
[PREVENT_REDIRECT_FORM_KEY]: _preventRedirect,
// eslint-disable-next-line @typescript-eslint/no-unused-vars
[methodFormKey]: _method,
// eslint-disable-next-line @typescript-eslint/no-unused-vars
[preventRedirectFormKey]: _preventRedirect,
...formValues
} = getFormValues(form, options);
} = getFormValues(form, serializerOptions);

return serializers[encType](formValues);
}
@@ -90,7 +101,7 @@ export const DEFAULT_ENCTYPE_DESERIALIZERS: EncTypeDeserializerMap = {

export const deserializeFormObjectBody = async (params: DeserializeBodyParams) => {
const { req, deserializers = DEFAULT_ENCTYPE_DESERIALIZERS } = params;
const contentType = req.headers['content-type'] ?? ENCTYPE_APPLICATION_OCTET_STREAM;
const contentType = req.headers[CONTENT_TYPE_HEADER_KEY] ?? ENCTYPE_APPLICATION_OCTET_STREAM;

if (contentType?.startsWith(`${ENCTYPE_MULTIPART_FORM_DATA};`)) {
return parseMultipartFormData(req);
@@ -98,7 +109,7 @@ export const deserializeFormObjectBody = async (params: DeserializeBodyParams) =

const bodyRaw = await getBody(req);
const encoding = (
req.headers['content-encoding'] ?? DEFAULT_ENCODING
req.headers[CONTENT_ENCODING_HEADER_KEY] ?? DEFAULT_ENCODING
) as BufferEncoding;

const { [contentType]: theDeserializer } = deserializers;


+ 16
- 54
pnpm-lock.yaml Parādīt failu

@@ -11,15 +11,12 @@ importers:
'@theoryofnekomata/formxtra':
specifier: ^1.0.3
version: 1.0.3
'@web-std/file':
specifier: ^3.0.3
version: 3.0.3
busboy:
specifier: ^1.6.0
version: 1.6.0
nookies:
specifier: ^2.5.2
version: 2.5.2
node-cache:
specifier: ^5.1.2
version: 5.1.2
seroval:
specifier: ^0.10.2
version: 0.10.2
@@ -1515,31 +1512,6 @@ packages:
pretty-format: 29.7.0
dev: true

/@web-std/blob@3.0.5:
resolution: {integrity: sha512-Lm03qr0eT3PoLBuhkvFBLf0EFkAsNz/G/AYCzpOdi483aFaVX86b4iQs0OHhzHJfN5C15q17UtDbyABjlzM96A==}
dependencies:
'@web-std/stream': 1.0.0
web-encoding: 1.1.5
dev: false

/@web-std/file@3.0.3:
resolution: {integrity: sha512-X7YYyvEERBbaDfJeC9lBKC5Q5lIEWYCP1SNftJNwNH/VbFhdHm+3neKOQP+kWEYJmosbDFq+NEUG7+XIvet/Jw==}
dependencies:
'@web-std/blob': 3.0.5
dev: false

/@web-std/stream@1.0.0:
resolution: {integrity: sha512-jyIbdVl+0ZJyKGTV0Ohb9E6UnxP+t7ZzX4Do3AHjZKxUXKMs9EmqnBDQgHF7bEw0EzbQygOjtt/7gvtmi//iCQ==}
dependencies:
web-streams-polyfill: 3.2.1
dev: false

/@zxing/text-encoding@0.9.0:
resolution: {integrity: sha512-U/4aVJ2mxI0aDNI8Uq0wEhMgY+u4CNtEb0om3+y3+niDAsoTCOB33UF0sxpzqzdqXLqmvc+vZyAt4O8pPdfkwA==}
requiresBuild: true
dev: false
optional: true

/abab@2.0.6:
resolution: {integrity: sha512-j2afSsaIENvHZN2B8GOpF566vZ5WVk5opAiMTvWgaQT8DkbOqsTfvNAvHoRGU2zzP8cPoqys+xHTRDWW8L+/BA==}
dev: true
@@ -1987,6 +1959,11 @@ packages:
engines: {node: '>=0.8'}
dev: true

/clone@2.1.2:
resolution: {integrity: sha512-3Pe/CF1Nn94hyhIYpjtiLhdCoEoz0DqQ+988E9gmeEdQZlojxnOb74wctFyuwWQHzqyf9X7C7MG8juUpqBJT8w==}
engines: {node: '>=0.8'}
dev: false

/color-convert@1.9.3:
resolution: {integrity: sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==}
dependencies:
@@ -3578,6 +3555,7 @@ packages:
dependencies:
call-bind: 1.0.2
has-tostringtag: 1.0.0
dev: true

/is-array-buffer@3.0.2:
resolution: {integrity: sha512-y+FyyR/w8vfIRq4eQcM1EYgSTnmHXPqaF+IgzgraytCFq5Xh8lllDVmAZolPJiZttZLeFSINPYMaEJ7/vWUa1w==}
@@ -4224,6 +4202,13 @@ packages:
- '@babel/core'
- babel-plugin-macros

/node-cache@5.1.2:
resolution: {integrity: sha512-t1QzWwnk4sjLWaQAS8CHgOJ+RAfmHpxFWmc36IWTiWHQfs0w5JDMBS1b1ZxQteo0vVVuWJvIUKHDkkeK7vIGCg==}
engines: {node: '>= 8.0.0'}
dependencies:
clone: 2.1.2
dev: false

/node-releases@2.0.13:
resolution: {integrity: sha512-uYr7J37ae/ORWdZeQ1xxMJe3NtdmqMC/JZK+geofDrkLUApKRHPd18/TxtBOJ4A0/+uUIliorNrfYV6s1b02eQ==}

@@ -5457,16 +5442,6 @@ packages:
/util-deprecate@1.0.2:
resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==}

/util@0.12.5:
resolution: {integrity: sha512-kZf/K6hEIrWHI6XqOFUiiMa+79wE/D8Q+NCNAWclkyg3b4d2k7s0QGepNjiABc+aR3N1PAyHL7p6UcLY6LmrnA==}
dependencies:
inherits: 2.0.4
is-arguments: 1.1.1
is-generator-function: 1.0.10
is-typed-array: 1.1.12
which-typed-array: 1.1.11
dev: false

/utils-merge@1.0.1:
resolution: {integrity: sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==}
engines: {node: '>= 0.4.0'}
@@ -5648,19 +5623,6 @@ packages:
defaults: 1.0.4
dev: true

/web-encoding@1.1.5:
resolution: {integrity: sha512-HYLeVCdJ0+lBYV2FvNZmv3HJ2Nt0QYXqZojk3d9FJOLkwnuhzM9tmamh8d7HPM8QqjKH8DeHkFTx+CFlWpZZDA==}
dependencies:
util: 0.12.5
optionalDependencies:
'@zxing/text-encoding': 0.9.0
dev: false

/web-streams-polyfill@3.2.1:
resolution: {integrity: sha512-e0MO3wdXWKrLbL0DgGnUV7WHVuw9OUvL4hjgnPkIeEvESk74gAITi5G606JtZPp39cd8HA9VQzCIvA49LpPN5Q==}
engines: {node: '>= 8'}
dev: false

/webidl-conversions@7.0.0:
resolution: {integrity: sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==}
engines: {node: '>=12'}


Notiek ielāde…
Atcelt
Saglabāt