7 Commits
Author SHA1 Message Date
539943419 afc57bc229 fix: 修正错别字 2024-08-23 10:00:53 +08:00
539943419 28ee6daab4 feat: 添加上传文件接口 2024-08-16 17:04:19 +08:00
539943419 59dbbb288c feat: 新增剪切与重命名的api 2024-08-16 00:40:16 +08:00
539943419 e0febdfa07 ... 2024-08-13 21:05:01 +08:00
539943419 d18ffaafc6 replace fs.rmdir to fs.rm 2024-08-11 23:02:09 +08:00
539943419 64259e37f4 添加delete, query的api, 修复上传中文名文件乱码的问题 2024-08-11 22:39:20 +08:00
539943419 737ee87bae 拆分文件,增加上传接口 2024-08-11 14:55:37 +08:00
13 changed files with 632 additions and 51 deletions

No files matched your search

+33
View File
@@ -0,0 +1,33 @@
import { api, staticPath } from "../config.js";
import path from "path";
import useFsOperateEventCenter from "../hooks/useFsOperateEventCenter.js";
import fs from "fs";
import express from "express";
const fsOperateEventCenter = useFsOperateEventCenter();
function cutPath(targetPath, newPath) {
return new Promise((resolve, reject) => {
fs.stat(targetPath, (err, stats) => {
if (err) {
console.log(err);
return reject(err);
}
fs.rename(targetPath, newPath, err => {
if (err) return reject(err);
resolve();
});
});
});
}
export default function useCutApi(app) {
app.post(api.cut, express.json(), (req, res) => {
const decodedPath = decodeURIComponent(req.path).substring(api.cut.length - 1);
const targetPath = path.join(staticPath, decodedPath);
const newPath = path.join(staticPath, req.body.newPath, path.basename(targetPath));
const eventId = fsOperateEventCenter.push(cutPath(targetPath, newPath));
res.send({ eventId });
});
}
+40
View File
@@ -0,0 +1,40 @@
import { api, staticPath } from "../config.js";
import path from "path";
import useFsOperateEventCenter from "../hooks/useFsOperateEventCenter.js";
import fs from 'fs'
const fsOperateEventCenter = useFsOperateEventCenter()
function deletePath(targetPath) {
return new Promise((resolve, reject) => {
fs.stat(targetPath, (err, stats) => {
if (err) {
console.log(err)
return reject(err);
}
if (stats.isFile()) {
fs.rm(targetPath, { recursive: true }, (err) => {
if (err) return reject(err);
resolve();
});
} else if (stats.isDirectory()) {
fs.rm(targetPath, { recursive: true }, (err) => {
if (err) return reject(err);
resolve();
});
} else {
reject('unknow file');
}
});
});
}
export default function useDeleteApi(app) {
app.post(api.delete, (req, res) => {
const decodedPath = decodeURIComponent(req.path).substring(api.delete.length - 1);
const targetPath = path.join(staticPath, decodedPath);
const eventId = fsOperateEventCenter.push(deletePath(targetPath))
res.send({ eventId });
});
}
+50
View File
@@ -0,0 +1,50 @@
import express from "express";
import path from "path";
import fs from "fs";
import { staticPath, api } from "../config.js";
const api_get = api.get
export default function useGetApi(app) {
// 不存在文件与文件夹同名的问题
app.use(api_get, (req, res, next) => {
const decodedPath = decodeURIComponent(req.path);
const directoryPath = path.join(staticPath, decodedPath);
fs.stat(directoryPath, (err, stats) => {
if (err) {
console.log(err, directoryPath);
// return res.status(500).json({ error: "Unable to access path" });
return next();
}
if (stats.isDirectory()) {
fs.readdir(directoryPath, (err, files) => {
if (err) {
console.log(err, directoryPath);
return res.status(500).json({ error: "Unable to scan directory" });
}
const fileDetails = files.map(file => {
const filePath = path.join(directoryPath, file);
const stats = fs.statSync(filePath);
return {
name: file,
size: stats.isDirectory() ? undefined : stats.size,
type: stats.isDirectory() ? "directory" : "file",
stats: {
atimeMs: stats.atimeMs,
birthtimeMs: stats.birthtimeMs,
ctimeMs: stats.ctimeMs,
mtimeMs: stats.mtimeMs
}
};
});
res.json(fileDetails);
});
} else {
next();
}
});
});
app.use(api_get, express.static(staticPath));
}
+23
View File
@@ -0,0 +1,23 @@
import fs from 'fs'
import path from 'path'
import express from 'express'
import { api, staticPath } from '../config.js'
export default function useMkdirApi(app) {
app.post(api.mkdir, express.json(), (req, res) => {
const folderName = req.body.folderName
const decodedPath = decodeURIComponent(req.path).substring(
api.mkdir.length - 1
)
const mkdirPath = path.join(staticPath, decodedPath, folderName)
// res.status(200).json({ mkdirPath, folderName })
// 创建文件夹
fs.mkdir(mkdirPath, { recursive: true }, (err) => {
if (err) {
return res.status(500).json({ message: 'failed', error: err })
}
res.status(200).json({ message: 'success' })
})
})
}
+15
View File
@@ -0,0 +1,15 @@
import { api } from "../config.js";
import useFsOperateEventCenter from "../hooks/useFsOperateEventCenter.js";
const fsOperateEventCenter = useFsOperateEventCenter();
/**
* 获取一个文件操作事件的结果
* @returns {any}
*/
export default function useQueryApi(app) {
app.get(api.query, (req, res) => {
const id = req.query.id;
res.json(fsOperateEventCenter.query(id));
});
}
+34
View File
@@ -0,0 +1,34 @@
import { api, staticPath } from "../config.js";
import path from "path";
import useFsOperateEventCenter from "../hooks/useFsOperateEventCenter.js";
import fs from "fs";
import express from "express";
const fsOperateEventCenter = useFsOperateEventCenter();
function renamePath(targetPath, newName) {
return new Promise((resolve, reject) => {
fs.stat(targetPath, (err, stats) => {
if (err) {
console.log(err);
return reject(err);
}
const newTargetPath = path.join(path.dirname(targetPath), newName);
fs.rename(targetPath, newTargetPath, err => {
if (err) return reject(err);
resolve();
});
});
});
}
export default function useRenameApi(app) {
app.post(api.rename, express.json(), (req, res) => {
const decodedPath = decodeURIComponent(req.path).substring(api.rename.length - 1);
const targetPath = path.join(staticPath, decodedPath);
const newName = req.body.newName;
const eventId = fsOperateEventCenter.push(renamePath(targetPath, newName));
res.send({ eventId });
});
}
+37
View File
@@ -0,0 +1,37 @@
import path from "path";
import fs from "fs";
import multer from "multer";
import { api, staticPath } from "../config.js";
const storage = multer.memoryStorage();
const upload = multer({ storage: storage }).single('file');
export default function useUploadApi(app) {
app.post(api.upload, upload, (req, res) => {
// 必须这样传,不然中文乱码
const fileName = req.body.fileName
const decodedPath = decodeURIComponent(req.path).substring(api.upload.length - 1);
const savePath = path.join(staticPath, decodedPath, fileName)
// 覆盖写or追加写
const operateType = req.body.operateType === 'write' ? 'write' : 'append'
const data = req.file.buffer
if (operateType === 'write') {
// 覆盖写入
fs.writeFile(savePath, data, (err) => {
if (err) {
return res.status(500).json({ message: 'failed', error: err });
}
res.status(200).json({ message: 'success' });
});
} else {
// 追加写入
fs.appendFile(savePath, data, (err) => {
if (err) {
return res.status(500).json({ message: 'failed', error: err });
}
res.status(200).json({ message: 'success' });
});
}
});
}
+17
View File
@@ -0,0 +1,17 @@
import path from "path";
export const staticPath = path.join("./static");
export const port = 17705;
export const api = {
get: `/${'get'}`,
query: `/${'query'}`,
upload: `/${'upload'}/*`,
delete: `/${'delete'}/*`,
rename: `/${'rename'}/*`,
mkdir: `/${'mkdir'}/*`,
cut: `/${'cut'}/*`
}
export default { staticPath, port, api }
+11
View File
@@ -0,0 +1,11 @@
/**
* 生成一个id,不唯一的几率比因为我代码烂的几率低
* @param length 生成id的长度
* @returns {number}
*/
export default function generateId(length) {
length || (length = 16);
let id = Math.ceil(Math.random() * 10 ** 16);
return id
}
+79
View File
@@ -0,0 +1,79 @@
import generateId from "./generateId.js"
// 一个文件操作事件
class FsOperateEvent {
constructor(event){
this.status = 'progress'
this.uid = generateId()
event.then(()=>{
this.status = 'success'
}).catch((e)=>{
this.failedEvent = e
this.status = 'failed'
})
}
/**
* 事件状态,分为progress, success, failed
*/
failedEvent
status
uid
}
class FsOprateEventCenter {
constructor(){
this.eventMap = {}
}
eventMap
/**
* 推送一个事件,返回这个事件的id,后续可以通过这个id查询这个事件的状态
* @param {Promise} event
* @returns {number} 事件id
*/
push(event){
const ev = new FsOperateEvent(event)
const id = ev.uid
this.eventMap[id] = {
event: ev,
// 每小时自查询一下状态,防止一直没查询导致内存泄漏
timer: setInterval(()=>{
this.query(id)
}, 1000*60*60)
}
return id
}
/**
* 推送一个事件,返回这个事件的id,后续可以通过这个id查询这个事件的状态
* 当查询到这个事件已经完成的时候,将这个事件移除出事件表(eventMap)
* @param {number} id 事件id
* @returns {{status: 'success' | 'failed' | 'progress' | 'unknow'; result?: any}} 事件id
*/
query(id){
let status
if(!this.eventMap[id]){
status = 'unknow'
}
else{
status = this.eventMap[id].event.status
}
const res = {status}
if( ['success', 'failed'].includes(status) ){
if(status === 'failed'){
res.failedEvent = this.eventMap[id].event.failedEvent
}
clearInterval(this.eventMap[id].timer)
this.eventMap[id] = undefined
}
return res
}
}
const fsOprateEventCenter = new FsOprateEventCenter()
/**
* 除了上传以外的所有文件操作都统一通过这个进行管理
* @returns {fsOprateEventCenter}
*/
export default function useFsOprateEventCenter(){
return fsOprateEventCenter
}
+20 -49
View File
@@ -1,61 +1,32 @@
import express from "express"; import express from "express";
import os from "os"; import os from "os";
import path from "path";
import cors from "cors"; import cors from "cors";
import fs from "fs"; import fs from "fs";
import Config from "./config.js";
import useGetApi from "./api/useGetApi.js";
import useUploadApi from "./api/useUploadApi.js";
import useDeleteApi from "./api/useDeleteApi.js";
import useQueryApi from "./api/useQueryApi.js";
import useRenameApi from "./api/useRenameApi.js";
import useCutApi from "./api/useCutApi.js";
import useMkdirApi from "./api/useMkdirApi.js";
if (!fs.existsSync("./static")) { const { staticPath, port, api } = Config;
fs.mkdirSync("./static");
if (!fs.existsSync(staticPath)) {
fs.mkdirSync(staticPath);
} }
const staticPath = path.join("./static");
const port = 17705;
const prev = `/${"get"}`;
const app = express(); const app = express();
app.use(cors()); app.use(cors());
// 不存在文件与文件夹同名的问题 useGetApi(app);
app.use(prev, (req, res, next) => { useUploadApi(app);
const decodedPath = decodeURIComponent(req.path); useDeleteApi(app);
const directoryPath = path.join(staticPath, decodedPath); useQueryApi(app);
fs.stat(directoryPath, (err, stats) => { useRenameApi(app);
if (err) { useCutApi(app);
console.log(err, directoryPath); useMkdirApi(app);
// return res.status(500).json({ error: "Unable to access path" });
return next()
}
if (stats.isDirectory()) {
fs.readdir(directoryPath, (err, files) => {
if (err) {
console.log(err, directoryPath);
return res.status(500).json({ error: "Unable to scan directory" });
}
const fileDetails = files.map(file => {
const filePath = path.join(directoryPath, file);
const stats = fs.statSync(filePath);
return {
name: file,
size: stats.isDirectory() ? undefined : stats.size,
type: stats.isDirectory() ? "directory" : "file",
stats: {
atimeMs: stats.atimeMs,
birthtimeMs: stats.birthtimeMs,
ctimeMs: stats.ctimeMs,
mtimeMs: stats.mtimeMs
}
};
});
res.json(fileDetails);
});
} else {
next();
}
});
});
app.use(prev, express.static(staticPath));
app.listen(port, "::", () => { app.listen(port, "::", () => {
const interfaces = os.networkInterfaces(); const interfaces = os.networkInterfaces();
@@ -68,7 +39,7 @@ app.listen(port, "::", () => {
console.log(`以下地址访问文件/文件夹:`); console.log(`以下地址访问文件/文件夹:`);
for (const name of Object.keys(interfaces)) { for (const name of Object.keys(interfaces)) {
for (const iface of interfaces[name]) { for (const iface of interfaces[name]) {
iface.family === "IPv6" ? console.log(`http://[${iface.address}]:${port}${prev}`) : console.log(`http://${iface.address}:${port}${prev}`); iface.family === "IPv6" ? console.log(`http://[${iface.address}]:${port}${api.get}`) : console.log(`http://${iface.address}:${port}${api.get}`);
} }
} }
}); });
+4 -2
View File
@@ -5,7 +5,7 @@
"main": "index.js", "main": "index.js",
"type": "module", "type": "module",
"scripts": { "scripts": {
"dev": "node index.js", "dev": "ts-node index.js",
"dev:bun": "bun index.js", "dev:bun": "bun index.js",
"serve": "node dist/index.min.js", "serve": "node dist/index.min.js",
"serve:bun": "bun dist/index.min.js", "serve:bun": "bun dist/index.min.js",
@@ -16,7 +16,9 @@
"license": "ISC", "license": "ISC",
"dependencies": { "dependencies": {
"cors": "^2.8.5", "cors": "^2.8.5",
"express": "^4.19.2" "express": "^4.19.2",
"multer": "1.4.5-lts.1",
"ts-node": "^10.9.2"
}, },
"devDependencies": { "devDependencies": {
"@vercel/ncc": "^0.38.1", "@vercel/ncc": "^0.38.1",
+269
View File
@@ -14,6 +14,12 @@ importers:
express: express:
specifier: ^4.19.2 specifier: ^4.19.2
version: 4.19.2 version: 4.19.2
multer:
specifier: 1.4.5-lts.1
version: 1.4.5-lts.1
ts-node:
specifier: ^10.9.2
version: 10.9.2(@types/node@22.2.0)(typescript@5.5.4)
devDependencies: devDependencies:
'@vercel/ncc': '@vercel/ncc':
specifier: ^0.38.1 specifier: ^0.38.1
@@ -24,6 +30,35 @@ importers:
packages: packages:
'@cspotcode/source-map-support@0.8.1':
resolution: {integrity: sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==}
engines: {node: '>=12'}
'@jridgewell/resolve-uri@3.1.2':
resolution: {integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==}
engines: {node: '>=6.0.0'}
'@jridgewell/sourcemap-codec@1.5.0':
resolution: {integrity: sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==}
'@jridgewell/trace-mapping@0.3.9':
resolution: {integrity: sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==}
'@tsconfig/node10@1.0.11':
resolution: {integrity: sha512-DcRjDCujK/kCk/cUe8Xz8ZSpm8mS3mNNpta+jGCA6USEDfktlNvm1+IuZ9eTcDbNk41BHwpHHeW+N1lKCz4zOw==}
'@tsconfig/node12@1.0.11':
resolution: {integrity: sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==}
'@tsconfig/node14@1.0.3':
resolution: {integrity: sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==}
'@tsconfig/node16@1.0.4':
resolution: {integrity: sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==}
'@types/node@22.2.0':
resolution: {integrity: sha512-bm6EG6/pCpkxDf/0gDNDdtDILMOHgaQBVOJGdwsqClnxA3xL6jtMv76rLBc006RVMWbmaf0xbmom4Z/5o2nRkQ==}
'@vercel/ncc@0.38.1': '@vercel/ncc@0.38.1':
resolution: {integrity: sha512-IBBb+iI2NLu4VQn3Vwldyi2QwaXt5+hTyh58ggAMoCGE6DJmPvwL3KPBWcJl1m9LYPChBLE980Jw+CS4Wokqxw==} resolution: {integrity: sha512-IBBb+iI2NLu4VQn3Vwldyi2QwaXt5+hTyh58ggAMoCGE6DJmPvwL3KPBWcJl1m9LYPChBLE980Jw+CS4Wokqxw==}
hasBin: true hasBin: true
@@ -32,6 +67,21 @@ packages:
resolution: {integrity: sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==} resolution: {integrity: sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==}
engines: {node: '>= 0.6'} engines: {node: '>= 0.6'}
acorn-walk@8.3.3:
resolution: {integrity: sha512-MxXdReSRhGO7VlFe1bRG/oI7/mdLV9B9JJT0N8vZOhF7gFRR5l3M8W9G8JxmKV+JC5mGqJ0QvqfSOLsCPa4nUw==}
engines: {node: '>=0.4.0'}
acorn@8.12.1:
resolution: {integrity: sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg==}
engines: {node: '>=0.4.0'}
hasBin: true
append-field@1.0.0:
resolution: {integrity: sha512-klpgFSWLW1ZEs8svjfb7g4qWY0YS5imI82dTg+QahUvJ8YqAY0P10Uk8tTyh9ZGuYEZEMaeJYCF5BFuX552hsw==}
arg@4.1.3:
resolution: {integrity: sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==}
array-flatten@1.1.1: array-flatten@1.1.1:
resolution: {integrity: sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==} resolution: {integrity: sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==}
@@ -39,6 +89,13 @@ packages:
resolution: {integrity: sha512-ml9pReCu3M61kGlqoTm2umSXTlRTuGTx0bfYj+uIUKKYycG5NtSbeetV3faSU6R7ajOPw0g/J1PvK4qNy7s5bA==} resolution: {integrity: sha512-ml9pReCu3M61kGlqoTm2umSXTlRTuGTx0bfYj+uIUKKYycG5NtSbeetV3faSU6R7ajOPw0g/J1PvK4qNy7s5bA==}
engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16} engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16}
buffer-from@1.1.2:
resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==}
busboy@1.6.0:
resolution: {integrity: sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==}
engines: {node: '>=10.16.0'}
bytes@3.1.2: bytes@3.1.2:
resolution: {integrity: sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==} resolution: {integrity: sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==}
engines: {node: '>= 0.8'} engines: {node: '>= 0.8'}
@@ -47,6 +104,10 @@ packages:
resolution: {integrity: sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==} resolution: {integrity: sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==}
engines: {node: '>= 0.4'} engines: {node: '>= 0.4'}
concat-stream@1.6.2:
resolution: {integrity: sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==}
engines: {'0': node >= 0.8}
content-disposition@0.5.4: content-disposition@0.5.4:
resolution: {integrity: sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==} resolution: {integrity: sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==}
engines: {node: '>= 0.6'} engines: {node: '>= 0.6'}
@@ -62,10 +123,16 @@ packages:
resolution: {integrity: sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==} resolution: {integrity: sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==}
engines: {node: '>= 0.6'} engines: {node: '>= 0.6'}
core-util-is@1.0.3:
resolution: {integrity: sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==}
cors@2.8.5: cors@2.8.5:
resolution: {integrity: sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==} resolution: {integrity: sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==}
engines: {node: '>= 0.10'} engines: {node: '>= 0.10'}
create-require@1.1.1:
resolution: {integrity: sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==}
debug@2.6.9: debug@2.6.9:
resolution: {integrity: sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==} resolution: {integrity: sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==}
peerDependencies: peerDependencies:
@@ -86,6 +153,10 @@ packages:
resolution: {integrity: sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==} resolution: {integrity: sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==}
engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16} engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16}
diff@4.0.2:
resolution: {integrity: sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==}
engines: {node: '>=0.3.1'}
ee-first@1.1.1: ee-first@1.1.1:
resolution: {integrity: sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==} resolution: {integrity: sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==}
@@ -164,6 +235,12 @@ packages:
resolution: {integrity: sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==} resolution: {integrity: sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==}
engines: {node: '>= 0.10'} engines: {node: '>= 0.10'}
isarray@1.0.0:
resolution: {integrity: sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==}
make-error@1.3.6:
resolution: {integrity: sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==}
media-typer@0.3.0: media-typer@0.3.0:
resolution: {integrity: sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==} resolution: {integrity: sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==}
engines: {node: '>= 0.6'} engines: {node: '>= 0.6'}
@@ -188,12 +265,23 @@ packages:
engines: {node: '>=4'} engines: {node: '>=4'}
hasBin: true hasBin: true
minimist@1.2.8:
resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==}
mkdirp@0.5.6:
resolution: {integrity: sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==}
hasBin: true
ms@2.0.0: ms@2.0.0:
resolution: {integrity: sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==} resolution: {integrity: sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==}
ms@2.1.3: ms@2.1.3:
resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==}
multer@1.4.5-lts.1:
resolution: {integrity: sha512-ywPWvcDMeH+z9gQq5qYHCCy+ethsk4goepZ45GLD63fOu0YcNecQxi64nDs3qluZB+murG3/D4dJ7+dGctcCQQ==}
engines: {node: '>= 6.0.0'}
negotiator@0.6.3: negotiator@0.6.3:
resolution: {integrity: sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==} resolution: {integrity: sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==}
engines: {node: '>= 0.6'} engines: {node: '>= 0.6'}
@@ -217,6 +305,9 @@ packages:
path-to-regexp@0.1.7: path-to-regexp@0.1.7:
resolution: {integrity: sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==} resolution: {integrity: sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==}
process-nextick-args@2.0.1:
resolution: {integrity: sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==}
proxy-addr@2.0.7: proxy-addr@2.0.7:
resolution: {integrity: sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==} resolution: {integrity: sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==}
engines: {node: '>= 0.10'} engines: {node: '>= 0.10'}
@@ -233,6 +324,12 @@ packages:
resolution: {integrity: sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==} resolution: {integrity: sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==}
engines: {node: '>= 0.8'} engines: {node: '>= 0.8'}
readable-stream@2.3.8:
resolution: {integrity: sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==}
safe-buffer@5.1.2:
resolution: {integrity: sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==}
safe-buffer@5.2.1: safe-buffer@5.2.1:
resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==} resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==}
@@ -262,33 +359,104 @@ packages:
resolution: {integrity: sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==} resolution: {integrity: sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==}
engines: {node: '>= 0.8'} engines: {node: '>= 0.8'}
streamsearch@1.1.0:
resolution: {integrity: sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==}
engines: {node: '>=10.0.0'}
string_decoder@1.1.1:
resolution: {integrity: sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==}
toidentifier@1.0.1: toidentifier@1.0.1:
resolution: {integrity: sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==} resolution: {integrity: sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==}
engines: {node: '>=0.6'} engines: {node: '>=0.6'}
ts-node@10.9.2:
resolution: {integrity: sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==}
hasBin: true
peerDependencies:
'@swc/core': '>=1.2.50'
'@swc/wasm': '>=1.2.50'
'@types/node': '*'
typescript: '>=2.7'
peerDependenciesMeta:
'@swc/core':
optional: true
'@swc/wasm':
optional: true
type-is@1.6.18: type-is@1.6.18:
resolution: {integrity: sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==} resolution: {integrity: sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==}
engines: {node: '>= 0.6'} engines: {node: '>= 0.6'}
typedarray@0.0.6:
resolution: {integrity: sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==}
typescript@5.5.4:
resolution: {integrity: sha512-Mtq29sKDAEYP7aljRgtPOpTvOfbwRWlS6dPRzwjdE+C0R4brX/GUyhHSecbHMFLNBLcJIPt9nl9yG5TZ1weH+Q==}
engines: {node: '>=14.17'}
hasBin: true
uglify-js@3.19.1: uglify-js@3.19.1:
resolution: {integrity: sha512-y/2wiW+ceTYR2TSSptAhfnEtpLaQ4Ups5zrjB2d3kuVxHj16j/QJwPl5PvuGy9uARb39J0+iKxcRPvtpsx4A4A==} resolution: {integrity: sha512-y/2wiW+ceTYR2TSSptAhfnEtpLaQ4Ups5zrjB2d3kuVxHj16j/QJwPl5PvuGy9uARb39J0+iKxcRPvtpsx4A4A==}
engines: {node: '>=0.8.0'} engines: {node: '>=0.8.0'}
hasBin: true hasBin: true
undici-types@6.13.0:
resolution: {integrity: sha512-xtFJHudx8S2DSoujjMd1WeWvn7KKWFRESZTMeL1RptAYERu29D6jphMjjY+vn96jvN3kVPDNxU/E13VTaXj6jg==}
unpipe@1.0.0: unpipe@1.0.0:
resolution: {integrity: sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==} resolution: {integrity: sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==}
engines: {node: '>= 0.8'} engines: {node: '>= 0.8'}
util-deprecate@1.0.2:
resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==}
utils-merge@1.0.1: utils-merge@1.0.1:
resolution: {integrity: sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==} resolution: {integrity: sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==}
engines: {node: '>= 0.4.0'} engines: {node: '>= 0.4.0'}
v8-compile-cache-lib@3.0.1:
resolution: {integrity: sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==}
vary@1.1.2: vary@1.1.2:
resolution: {integrity: sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==} resolution: {integrity: sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==}
engines: {node: '>= 0.8'} engines: {node: '>= 0.8'}
xtend@4.0.2:
resolution: {integrity: sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==}
engines: {node: '>=0.4'}
yn@3.1.1:
resolution: {integrity: sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==}
engines: {node: '>=6'}
snapshots: snapshots:
'@cspotcode/source-map-support@0.8.1':
dependencies:
'@jridgewell/trace-mapping': 0.3.9
'@jridgewell/resolve-uri@3.1.2': {}
'@jridgewell/sourcemap-codec@1.5.0': {}
'@jridgewell/trace-mapping@0.3.9':
dependencies:
'@jridgewell/resolve-uri': 3.1.2
'@jridgewell/sourcemap-codec': 1.5.0
'@tsconfig/node10@1.0.11': {}
'@tsconfig/node12@1.0.11': {}
'@tsconfig/node14@1.0.3': {}
'@tsconfig/node16@1.0.4': {}
'@types/node@22.2.0':
dependencies:
undici-types: 6.13.0
'@vercel/ncc@0.38.1': {} '@vercel/ncc@0.38.1': {}
accepts@1.3.8: accepts@1.3.8:
@@ -296,6 +464,16 @@ snapshots:
mime-types: 2.1.35 mime-types: 2.1.35
negotiator: 0.6.3 negotiator: 0.6.3
acorn-walk@8.3.3:
dependencies:
acorn: 8.12.1
acorn@8.12.1: {}
append-field@1.0.0: {}
arg@4.1.3: {}
array-flatten@1.1.1: {} array-flatten@1.1.1: {}
body-parser@1.20.2: body-parser@1.20.2:
@@ -315,6 +493,12 @@ snapshots:
transitivePeerDependencies: transitivePeerDependencies:
- supports-color - supports-color
buffer-from@1.1.2: {}
busboy@1.6.0:
dependencies:
streamsearch: 1.1.0
bytes@3.1.2: {} bytes@3.1.2: {}
call-bind@1.0.7: call-bind@1.0.7:
@@ -325,6 +509,13 @@ snapshots:
get-intrinsic: 1.2.4 get-intrinsic: 1.2.4
set-function-length: 1.2.2 set-function-length: 1.2.2
concat-stream@1.6.2:
dependencies:
buffer-from: 1.1.2
inherits: 2.0.4
readable-stream: 2.3.8
typedarray: 0.0.6
content-disposition@0.5.4: content-disposition@0.5.4:
dependencies: dependencies:
safe-buffer: 5.2.1 safe-buffer: 5.2.1
@@ -335,11 +526,15 @@ snapshots:
cookie@0.6.0: {} cookie@0.6.0: {}
core-util-is@1.0.3: {}
cors@2.8.5: cors@2.8.5:
dependencies: dependencies:
object-assign: 4.1.1 object-assign: 4.1.1
vary: 1.1.2 vary: 1.1.2
create-require@1.1.1: {}
debug@2.6.9: debug@2.6.9:
dependencies: dependencies:
ms: 2.0.0 ms: 2.0.0
@@ -354,6 +549,8 @@ snapshots:
destroy@1.2.0: {} destroy@1.2.0: {}
diff@4.0.2: {}
ee-first@1.1.1: {} ee-first@1.1.1: {}
encodeurl@1.0.2: {} encodeurl@1.0.2: {}
@@ -462,6 +659,10 @@ snapshots:
ipaddr.js@1.9.1: {} ipaddr.js@1.9.1: {}
isarray@1.0.0: {}
make-error@1.3.6: {}
media-typer@0.3.0: {} media-typer@0.3.0: {}
merge-descriptors@1.0.1: {} merge-descriptors@1.0.1: {}
@@ -476,10 +677,26 @@ snapshots:
mime@1.6.0: {} mime@1.6.0: {}
minimist@1.2.8: {}
mkdirp@0.5.6:
dependencies:
minimist: 1.2.8
ms@2.0.0: {} ms@2.0.0: {}
ms@2.1.3: {} ms@2.1.3: {}
multer@1.4.5-lts.1:
dependencies:
append-field: 1.0.0
busboy: 1.6.0
concat-stream: 1.6.2
mkdirp: 0.5.6
object-assign: 4.1.1
type-is: 1.6.18
xtend: 4.0.2
negotiator@0.6.3: {} negotiator@0.6.3: {}
object-assign@4.1.1: {} object-assign@4.1.1: {}
@@ -494,6 +711,8 @@ snapshots:
path-to-regexp@0.1.7: {} path-to-regexp@0.1.7: {}
process-nextick-args@2.0.1: {}
proxy-addr@2.0.7: proxy-addr@2.0.7:
dependencies: dependencies:
forwarded: 0.2.0 forwarded: 0.2.0
@@ -512,6 +731,18 @@ snapshots:
iconv-lite: 0.4.24 iconv-lite: 0.4.24
unpipe: 1.0.0 unpipe: 1.0.0
readable-stream@2.3.8:
dependencies:
core-util-is: 1.0.3
inherits: 2.0.4
isarray: 1.0.0
process-nextick-args: 2.0.1
safe-buffer: 5.1.2
string_decoder: 1.1.1
util-deprecate: 1.0.2
safe-buffer@5.1.2: {}
safe-buffer@5.2.1: {} safe-buffer@5.2.1: {}
safer-buffer@2.1.2: {} safer-buffer@2.1.2: {}
@@ -563,17 +794,55 @@ snapshots:
statuses@2.0.1: {} statuses@2.0.1: {}
streamsearch@1.1.0: {}
string_decoder@1.1.1:
dependencies:
safe-buffer: 5.1.2
toidentifier@1.0.1: {} toidentifier@1.0.1: {}
ts-node@10.9.2(@types/node@22.2.0)(typescript@5.5.4):
dependencies:
'@cspotcode/source-map-support': 0.8.1
'@tsconfig/node10': 1.0.11
'@tsconfig/node12': 1.0.11
'@tsconfig/node14': 1.0.3
'@tsconfig/node16': 1.0.4
'@types/node': 22.2.0
acorn: 8.12.1
acorn-walk: 8.3.3
arg: 4.1.3
create-require: 1.1.1
diff: 4.0.2
make-error: 1.3.6
typescript: 5.5.4
v8-compile-cache-lib: 3.0.1
yn: 3.1.1
type-is@1.6.18: type-is@1.6.18:
dependencies: dependencies:
media-typer: 0.3.0 media-typer: 0.3.0
mime-types: 2.1.35 mime-types: 2.1.35
typedarray@0.0.6: {}
typescript@5.5.4: {}
uglify-js@3.19.1: {} uglify-js@3.19.1: {}
undici-types@6.13.0: {}
unpipe@1.0.0: {} unpipe@1.0.0: {}
util-deprecate@1.0.2: {}
utils-merge@1.0.1: {} utils-merge@1.0.1: {}
v8-compile-cache-lib@3.0.1: {}
vary@1.1.2: {} vary@1.1.2: {}
xtend@4.0.2: {}
yn@3.1.1: {}