Merge pull request #82 from fantasticit/feat/import

feat: import document from markdown file
This commit is contained in:
fantasticit 2022-06-17 18:52:49 +08:00 committed by GitHub
commit 32f229e423
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 313 additions and 13 deletions

View File

@ -0,0 +1,52 @@
import { Toast } from '@douyinfe/semi-ui';
import { safeJSONStringify } from 'helpers/json';
import { useEffect, useMemo, useRef } from 'react';
import { useEditor } from 'tiptap/core';
import { AllExtensions } from 'tiptap/core/all-kit';
import { Collaboration } from 'tiptap/core/extensions/collaboration';
import { prosemirrorJSONToYDoc } from 'tiptap/core/thritypart/y-prosemirror/y-prosemirror';
import { markdownToProsemirror } from 'tiptap/markdown/markdown-to-prosemirror';
import * as Y from 'yjs';
export const ImportEditor = ({ content, onChange }) => {
const parsed = useRef(false);
const ydoc = useMemo(() => new Y.Doc(), []);
const editor = useEditor(
{
editable: false,
extensions: AllExtensions.concat(Collaboration.configure({ document: ydoc })),
content: '',
},
[ydoc]
);
useEffect(() => {
if (!content || !editor || !ydoc || parsed.current) return;
try {
const prosemirrorNode = markdownToProsemirror({ schema: editor.schema, content, needTitle: true });
const title = prosemirrorNode.content[0].content[0].text;
editor.commands.setContent(prosemirrorNode);
Y.applyUpdate(ydoc, Y.encodeStateAsUpdate(prosemirrorJSONToYDoc(editor.schema, prosemirrorNode)));
const state = Y.encodeStateAsUpdate(ydoc);
onChange({
title,
content: safeJSONStringify({ default: prosemirrorNode }),
state: Buffer.from(state),
});
parsed.current = true;
} catch (e) {
Toast.error('文件内容解析失败,请到 Github 提 issue 寻求解决!');
}
return () => {
ydoc.destroy();
editor.destroy();
};
}, [editor, ydoc, content, onChange]);
return null;
};

View File

@ -0,0 +1,137 @@
import { IconUpload } from '@douyinfe/semi-icons';
import { Button, List, Toast, Typography } from '@douyinfe/semi-ui';
import type { IWiki } from '@think/domains';
import { useCreateDocument } from 'data/document';
import { useToggle } from 'hooks/use-toggle';
import { useCallback, useRef, useState } from 'react';
import { ImportEditor } from './editor';
interface IProps {
wikiId: IWiki['id'];
}
const { Text } = Typography;
export const Import: React.FC<IProps> = ({ wikiId }) => {
const { create } = useCreateDocument();
const $upload = useRef<HTMLInputElement>();
const [uploadFiles, setUploadFiles] = useState([]);
const [texts, setTexts] = useState<Record<string, string | ArrayBuffer>>({});
const [payloads, setPayloads] = useState<
Record<
string,
{
title: string;
content: string;
state: Uint8Array;
}
>
>({});
const [parsedFiles, setParsedFiles] = useState([]);
const [loading, toggleLoading] = useToggle(false);
const selectFile = useCallback(() => {
$upload.current.click();
}, []);
const handleFile = useCallback((e) => {
const files = Array.from(e.target.files) as Array<File>;
if (!files.length) return;
files.forEach((file) => {
const fileReader = new FileReader();
fileReader.onload = function () {
setTexts((texts) => {
texts[file.name] = fileReader.result;
return texts;
});
setUploadFiles((files) => {
return files.concat(file.name);
});
};
fileReader.readAsText(file);
});
}, []);
const onParsedFile = useCallback((filename) => {
return (payload) => {
setPayloads((payloads) => {
payloads[filename] = payload;
setParsedFiles((files) => files.concat(filename));
return payloads;
});
};
}, []);
const onDeleteFile = useCallback((toDeleteFilename) => {
return () => {
setPayloads((payloads) => {
const newPayloads = Object.keys(payloads).reduce((accu, filename) => {
if (filename !== toDeleteFilename) {
accu[filename] = payloads[filename];
}
return accu;
}, {});
setParsedFiles(Object.keys(newPayloads));
return newPayloads;
});
};
}, []);
const importFile = useCallback(() => {
toggleLoading(true);
Promise.all(
Object.keys(payloads).map((filename) => {
return create({ ...payloads[filename], wikiId });
})
)
.then(() => {
Toast.success('文档已导入');
})
.finally(() => {
toggleLoading(false);
setTexts({});
setUploadFiles([]);
setPayloads({});
setParsedFiles([]);
$upload.current.value = '';
});
}, [payloads, toggleLoading, create, wikiId]);
return (
<div style={{ marginTop: 16 }}>
<Button icon={<IconUpload />} theme="light" onClick={selectFile}>
</Button>
<input ref={$upload} type="file" hidden multiple accept="text/markdown" onChange={handleFile} />
{uploadFiles.map((filename) => {
return <ImportEditor key={filename} content={texts[filename]} onChange={onParsedFile(filename)} />;
})}
<List
dataSource={parsedFiles}
renderItem={(filename) => (
<List.Item main={<div>{filename}</div>} extra={<Button onClick={onDeleteFile(filename)}></Button>} />
)}
emptyContent={<Text type="tertiary"> Markdown </Text>}
/>
<Button
onClick={importFile}
disabled={loading || !parsedFiles.length}
loading={loading}
theme="solid"
style={{ marginTop: 16 }}
>
</Button>
</div>
);
};

View File

@ -1,15 +1,17 @@
import { TabPane, Tabs } from '@douyinfe/semi-ui'; import { TabPane, Tabs } from '@douyinfe/semi-ui';
import { IWiki } from '@think/domains';
import { Seo } from 'components/seo'; import { Seo } from 'components/seo';
import { useWikiDetail } from 'data/wiki'; import { useWikiDetail } from 'data/wiki';
import React from 'react'; import React from 'react';
import { Base } from './base'; import { Base } from './base';
import { Import } from './import';
import { More } from './more'; import { More } from './more';
import { Privacy } from './privacy'; import { Privacy } from './privacy';
import { Users } from './users'; import { Users } from './users';
interface IProps { interface IProps {
wikiId: string; wikiId: IWiki['id'];
tab?: string; tab?: string;
onNavigate: (arg: string) => void; onNavigate: (arg: string) => void;
} }
@ -18,6 +20,7 @@ const TitleMap = {
base: '基础信息', base: '基础信息',
privacy: '隐私管理', privacy: '隐私管理',
users: '成员管理', users: '成员管理',
import: '导入文档',
more: '更多', more: '更多',
}; };
@ -37,6 +40,11 @@ export const WikiSetting: React.FC<IProps> = ({ wikiId, tab, onNavigate }) => {
<TabPane tab={TitleMap['privacy']} itemKey="privacy"> <TabPane tab={TitleMap['privacy']} itemKey="privacy">
<Privacy wikiId={wikiId} /> <Privacy wikiId={wikiId} />
</TabPane> </TabPane>
<TabPane tab={TitleMap['import']} itemKey="import">
<Import wikiId={wikiId} />
</TabPane>
<TabPane tab={TitleMap['more']} itemKey="more"> <TabPane tab={TitleMap['more']} itemKey="more">
<More wikiId={wikiId} /> <More wikiId={wikiId} />
</TabPane> </TabPane>

View File

@ -34,6 +34,7 @@
"@types/multer": "^1.4.7", "@types/multer": "^1.4.7",
"ali-oss": "^6.16.0", "ali-oss": "^6.16.0",
"bcryptjs": "^2.4.3", "bcryptjs": "^2.4.3",
"body-parser": "^1.20.0",
"class-transformer": "^0.5.1", "class-transformer": "^0.5.1",
"class-validator": "^0.13.2", "class-validator": "^0.13.2",
"compression": "^1.7.4", "compression": "^1.7.4",

View File

@ -15,4 +15,10 @@ export class CreateDocumentDto {
@IsOptional() @IsOptional()
readonly templateId?: string; readonly templateId?: string;
@IsOptional()
readonly content?: string;
@IsOptional()
state?: Buffer;
} }

View File

@ -5,6 +5,7 @@ import { ConfigService } from '@nestjs/config';
import { NestFactory } from '@nestjs/core'; import { NestFactory } from '@nestjs/core';
import { ValidationPipe } from '@pipes/validation.pipe'; import { ValidationPipe } from '@pipes/validation.pipe';
import { HttpResponseTransformInterceptor } from '@transforms/http-response.transform'; import { HttpResponseTransformInterceptor } from '@transforms/http-response.transform';
import * as bodyParser from 'body-parser';
import * as compression from 'compression'; import * as compression from 'compression';
import * as cookieParser from 'cookie-parser'; import * as cookieParser from 'cookie-parser';
import * as express from 'express'; import * as express from 'express';
@ -33,6 +34,9 @@ async function bootstrap() {
}) })
); );
app.use(bodyParser.json({ limit: '100mb' }));
app.use(bodyParser.urlencoded({ limit: '100mb', extended: true }));
app.use(cookieParser()); app.use(cookieParser());
app.use(compression()); app.use(compression());
app.use(helmet()); app.use(helmet());

View File

@ -316,13 +316,21 @@ export class DocumentService {
) )
: -1; : -1;
let state = EMPTY_DOCUMNENT.state;
if ('state' in dto) {
state = Buffer.from(dto.state);
delete dto.state;
}
const data = { const data = {
...dto,
createUserId: user.id, createUserId: user.id,
isWikiHome, isWikiHome,
title: '未命名文档', title: '未命名文档',
index: maxIndex + 1, index: maxIndex + 1,
...EMPTY_DOCUMNENT, ...EMPTY_DOCUMNENT,
...dto,
state,
}; };
if (dto.templateId) { if (dto.templateId) {

View File

@ -246,7 +246,7 @@ importers:
eslint: 8.14.0 eslint: 8.14.0
eslint-config-prettier: 8.5.0_eslint@8.14.0 eslint-config-prettier: 8.5.0_eslint@8.14.0
eslint-plugin-import: 2.26.0_eslint@8.14.0 eslint-plugin-import: 2.26.0_eslint@8.14.0
eslint-plugin-prettier: 4.0.0_740be41c8168d0cc214a306089357ad0 eslint-plugin-prettier: 4.0.0_74ebb802163a9b4fa8f89d76ed02f62a
eslint-plugin-react: 7.29.4_eslint@8.14.0 eslint-plugin-react: 7.29.4_eslint@8.14.0
eslint-plugin-react-hooks: 4.5.0_eslint@8.14.0 eslint-plugin-react-hooks: 4.5.0_eslint@8.14.0
eslint-plugin-simple-import-sort: 7.0.0_eslint@8.14.0 eslint-plugin-simple-import-sort: 7.0.0_eslint@8.14.0
@ -302,6 +302,7 @@ importers:
'@typescript-eslint/parser': ^5.21.0 '@typescript-eslint/parser': ^5.21.0
ali-oss: ^6.16.0 ali-oss: ^6.16.0
bcryptjs: ^2.4.3 bcryptjs: ^2.4.3
body-parser: ^1.20.0
class-transformer: ^0.5.1 class-transformer: ^0.5.1
class-validator: ^0.13.2 class-validator: ^0.13.2
compression: ^1.7.4 compression: ^1.7.4
@ -361,6 +362,7 @@ importers:
'@types/multer': 1.4.7 '@types/multer': 1.4.7
ali-oss: 6.16.0 ali-oss: 6.16.0
bcryptjs: 2.4.3 bcryptjs: 2.4.3
body-parser: 1.20.0
class-transformer: 0.5.1 class-transformer: 0.5.1
class-validator: 0.13.2 class-validator: 0.13.2
compression: 1.7.4 compression: 1.7.4
@ -1725,7 +1727,7 @@ packages:
'@babel/helper-split-export-declaration': 7.16.7 '@babel/helper-split-export-declaration': 7.16.7
'@babel/parser': 7.16.12 '@babel/parser': 7.16.12
'@babel/types': 7.16.8 '@babel/types': 7.16.8
debug: 4.3.3 debug: 4.3.4
globals: 11.12.0 globals: 11.12.0
transitivePeerDependencies: transitivePeerDependencies:
- supports-color - supports-color
@ -3747,7 +3749,7 @@ packages:
resolution: {integrity: sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==} resolution: {integrity: sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==}
engines: {node: '>= 6.0.0'} engines: {node: '>= 6.0.0'}
dependencies: dependencies:
debug: 4.3.3 debug: 4.3.4
transitivePeerDependencies: transitivePeerDependencies:
- supports-color - supports-color
@ -4284,6 +4286,24 @@ packages:
type-is: 1.6.18 type-is: 1.6.18
dev: false dev: false
/body-parser/1.20.0:
resolution: {integrity: sha512-DfJ+q6EPcGKZD1QWUjSpqp+Q7bDQTsQIF4zfUAtZ6qk+H/3/QRhg9CEp39ss+/T2vw0+HaidC0ecJj/DRLIaKg==}
engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16}
dependencies:
bytes: 3.1.2
content-type: 1.0.4
debug: 2.6.9
depd: 2.0.0
destroy: 1.2.0
http-errors: 2.0.0
iconv-lite: 0.4.24
on-finished: 2.4.1
qs: 6.10.3
raw-body: 2.5.1
type-is: 1.6.18
unpipe: 1.0.0
dev: false
/bowser/1.9.4: /bowser/1.9.4:
resolution: {integrity: sha512-9IdMmj2KjigRq6oWhmwv1W36pDuA4STQZ8q6YO9um+x07xgYNCD3Oou+WP/3L1HNz7iqythGet3/p4wvc8AAwQ==} resolution: {integrity: sha512-9IdMmj2KjigRq6oWhmwv1W36pDuA4STQZ8q6YO9um+x07xgYNCD3Oou+WP/3L1HNz7iqythGet3/p4wvc8AAwQ==}
dev: false dev: false
@ -4407,6 +4427,11 @@ packages:
engines: {node: '>= 0.8'} engines: {node: '>= 0.8'}
dev: false dev: false
/bytes/3.1.2:
resolution: {integrity: sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==}
engines: {node: '>= 0.8'}
dev: false
/call-bind/1.0.2: /call-bind/1.0.2:
resolution: {integrity: sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==} resolution: {integrity: sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==}
dependencies: dependencies:
@ -5179,10 +5204,20 @@ packages:
engines: {node: '>= 0.6'} engines: {node: '>= 0.6'}
dev: false dev: false
/depd/2.0.0:
resolution: {integrity: sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==}
engines: {node: '>= 0.8'}
dev: false
/destroy/1.0.4: /destroy/1.0.4:
resolution: {integrity: sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=} resolution: {integrity: sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=}
dev: false dev: false
/destroy/1.2.0:
resolution: {integrity: sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==}
engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16}
dev: false
/detect-newline/3.1.0: /detect-newline/3.1.0:
resolution: {integrity: sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==} resolution: {integrity: sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==}
engines: {node: '>=8'} engines: {node: '>=8'}
@ -5568,6 +5603,22 @@ packages:
prettier-linter-helpers: 1.0.0 prettier-linter-helpers: 1.0.0
dev: true dev: true
/eslint-plugin-prettier/4.0.0_74ebb802163a9b4fa8f89d76ed02f62a:
resolution: {integrity: sha512-98MqmCJ7vJodoQK359bqQWaxOE0CS8paAz/GgjaZLyex4TTk3g9HugoO89EqWCrFiOqn9EVvcoo7gZzONCWVwQ==}
engines: {node: '>=6.0.0'}
peerDependencies:
eslint: '>=7.28.0'
eslint-config-prettier: '*'
prettier: '>=2.0.0'
peerDependenciesMeta:
eslint-config-prettier:
optional: true
dependencies:
eslint: 8.14.0
eslint-config-prettier: 8.5.0_eslint@8.14.0
prettier-linter-helpers: 1.0.0
dev: true
/eslint-plugin-react-hooks/4.5.0_eslint@8.14.0: /eslint-plugin-react-hooks/4.5.0_eslint@8.14.0:
resolution: {integrity: sha512-8k1gRt7D7h03kd+SAAlzXkQwWK22BnK6GKZG+FJA6BAGy22CFvl8kCIXKpVux0cCxMWDQUPqSok0LKaZ0aOcCw==} resolution: {integrity: sha512-8k1gRt7D7h03kd+SAAlzXkQwWK22BnK6GKZG+FJA6BAGy22CFvl8kCIXKpVux0cCxMWDQUPqSok0LKaZ0aOcCw==}
engines: {node: '>=10'} engines: {node: '>=10'}
@ -6119,7 +6170,7 @@ packages:
/formstream/1.1.1: /formstream/1.1.1:
resolution: {integrity: sha512-yHRxt3qLFnhsKAfhReM4w17jP+U1OlhUjnKPPtonwKbIJO7oBP0MvoxkRUwb8AU9n0MIkYy5X5dK6pQnbj+R2Q==} resolution: {integrity: sha512-yHRxt3qLFnhsKAfhReM4w17jP+U1OlhUjnKPPtonwKbIJO7oBP0MvoxkRUwb8AU9n0MIkYy5X5dK6pQnbj+R2Q==}
dependencies: dependencies:
destroy: 1.0.4 destroy: 1.2.0
mime: 2.6.0 mime: 2.6.0
pause-stream: 0.0.11 pause-stream: 0.0.11
dev: false dev: false
@ -6468,13 +6519,24 @@ packages:
toidentifier: 1.0.1 toidentifier: 1.0.1
dev: false dev: false
/http-errors/2.0.0:
resolution: {integrity: sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==}
engines: {node: '>= 0.8'}
dependencies:
depd: 2.0.0
inherits: 2.0.4
setprototypeof: 1.2.0
statuses: 2.0.1
toidentifier: 1.0.1
dev: false
/http-proxy-agent/4.0.1: /http-proxy-agent/4.0.1:
resolution: {integrity: sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg==} resolution: {integrity: sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg==}
engines: {node: '>= 6'} engines: {node: '>= 6'}
dependencies: dependencies:
'@tootallnate/once': 1.1.2 '@tootallnate/once': 1.1.2
agent-base: 6.0.2 agent-base: 6.0.2
debug: 4.3.3 debug: 4.3.4
transitivePeerDependencies: transitivePeerDependencies:
- supports-color - supports-color
@ -6492,7 +6554,7 @@ packages:
engines: {node: '>= 6'} engines: {node: '>= 6'}
dependencies: dependencies:
agent-base: 6.0.2 agent-base: 6.0.2
debug: 4.3.3 debug: 4.3.4
transitivePeerDependencies: transitivePeerDependencies:
- supports-color - supports-color
@ -6979,7 +7041,7 @@ packages:
resolution: {integrity: sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==} resolution: {integrity: sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==}
engines: {node: '>=10'} engines: {node: '>=10'}
dependencies: dependencies:
debug: 4.3.3 debug: 4.3.4
istanbul-lib-coverage: 3.2.0 istanbul-lib-coverage: 3.2.0
source-map: 0.6.1 source-map: 0.6.1
transitivePeerDependencies: transitivePeerDependencies:
@ -8577,6 +8639,13 @@ packages:
ee-first: 1.1.1 ee-first: 1.1.1
dev: false dev: false
/on-finished/2.4.1:
resolution: {integrity: sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==}
engines: {node: '>= 0.8'}
dependencies:
ee-first: 1.1.1
dev: false
/on-headers/1.0.2: /on-headers/1.0.2:
resolution: {integrity: sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==} resolution: {integrity: sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==}
engines: {node: '>= 0.8'} engines: {node: '>= 0.8'}
@ -8729,12 +8798,12 @@ packages:
dependencies: dependencies:
'@tootallnate/once': 1.1.2 '@tootallnate/once': 1.1.2
agent-base: 6.0.2 agent-base: 6.0.2
debug: 4.3.3 debug: 4.3.4
get-uri: 3.0.2 get-uri: 3.0.2
http-proxy-agent: 4.0.1 http-proxy-agent: 4.0.1
https-proxy-agent: 5.0.0 https-proxy-agent: 5.0.0
pac-resolver: 5.0.0 pac-resolver: 5.0.0
raw-body: 2.4.2 raw-body: 2.5.1
socks-proxy-agent: 5.0.1 socks-proxy-agent: 5.0.1
transitivePeerDependencies: transitivePeerDependencies:
- supports-color - supports-color
@ -9276,7 +9345,7 @@ packages:
engines: {node: '>= 8'} engines: {node: '>= 8'}
dependencies: dependencies:
agent-base: 6.0.2 agent-base: 6.0.2
debug: 4.3.3 debug: 4.3.4
http-proxy-agent: 4.0.1 http-proxy-agent: 4.0.1
https-proxy-agent: 5.0.0 https-proxy-agent: 5.0.0
lru-cache: 5.1.1 lru-cache: 5.1.1
@ -9365,6 +9434,16 @@ packages:
unpipe: 1.0.0 unpipe: 1.0.0
dev: false dev: false
/raw-body/2.5.1:
resolution: {integrity: sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig==}
engines: {node: '>= 0.8'}
dependencies:
bytes: 3.1.2
http-errors: 2.0.0
iconv-lite: 0.4.24
unpipe: 1.0.0
dev: false
/react-countdown/2.3.2_react-dom@17.0.2+react@17.0.2: /react-countdown/2.3.2_react-dom@17.0.2+react@17.0.2:
resolution: {integrity: sha512-Q4SADotHtgOxNWhDdvgupmKVL0pMB9DvoFcxv5AzjsxVhzOVxnttMbAywgqeOdruwEAmnPhOhNv/awAgkwru2w==} resolution: {integrity: sha512-Q4SADotHtgOxNWhDdvgupmKVL0pMB9DvoFcxv5AzjsxVhzOVxnttMbAywgqeOdruwEAmnPhOhNv/awAgkwru2w==}
peerDependencies: peerDependencies:
@ -10145,7 +10224,7 @@ packages:
engines: {node: '>= 6'} engines: {node: '>= 6'}
dependencies: dependencies:
agent-base: 6.0.2 agent-base: 6.0.2
debug: 4.3.3 debug: 4.3.4
socks: 2.6.1 socks: 2.6.1
transitivePeerDependencies: transitivePeerDependencies:
- supports-color - supports-color
@ -10282,6 +10361,11 @@ packages:
engines: {node: '>= 0.6'} engines: {node: '>= 0.6'}
dev: false dev: false
/statuses/2.0.1:
resolution: {integrity: sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==}
engines: {node: '>= 0.8'}
dev: false
/stream-http/2.8.2: /stream-http/2.8.2:
resolution: {integrity: sha512-QllfrBhqF1DPcz46WxKTs6Mz1Bpc+8Qm6vbqOpVav5odAXwbyzwnEczoWqtxrsmlO+cJqtPrp/8gWKWjaKLLlA==} resolution: {integrity: sha512-QllfrBhqF1DPcz46WxKTs6Mz1Bpc+8Qm6vbqOpVav5odAXwbyzwnEczoWqtxrsmlO+cJqtPrp/8gWKWjaKLLlA==}
dependencies: dependencies: