wip fix prasi api
This commit is contained in:
parent
c916e47150
commit
1b77a5851d
|
|
@ -1,18 +1,121 @@
|
||||||
|
import mime from "mime";
|
||||||
import { apiContext } from "service-srv";
|
import { apiContext } from "service-srv";
|
||||||
import { dir } from "utils/dir";
|
import { dir } from "utils/dir";
|
||||||
import { g } from "utils/global";
|
import { g } from "utils/global";
|
||||||
import { generateIndexHtml } from "../server/serve-web";
|
import { readdir, stat } from "fs/promises";
|
||||||
import mime from "mime";
|
import { basename, dirname } from "path";
|
||||||
|
import {
|
||||||
|
dirAsync,
|
||||||
|
existsAsync,
|
||||||
|
moveAsync,
|
||||||
|
removeAsync,
|
||||||
|
renameAsync,
|
||||||
|
} from "fs-jetpack";
|
||||||
export const _ = {
|
export const _ = {
|
||||||
url: "/_file/**",
|
url: "/_file/**",
|
||||||
async api() {
|
async api() {
|
||||||
const { req } = apiContext(this);
|
const { req } = apiContext(this);
|
||||||
const rpath = decodeURIComponent(req.params._);
|
let rpath = decodeURIComponent(req.params._);
|
||||||
|
|
||||||
let res = new Response("NOT FOUND", { status: 404 });
|
let res = new Response("NOT FOUND", { status: 404 });
|
||||||
|
|
||||||
const path = dir(`${g.datadir}/upload/${rpath}`);
|
rpath = rpath
|
||||||
|
.split("/")
|
||||||
|
.map((e) => e.replace(/\.\./gi, ""))
|
||||||
|
.filter((e) => !!e)
|
||||||
|
.join("/");
|
||||||
|
|
||||||
|
if (Object.keys(req.query_parameters).length > 0) {
|
||||||
|
await dirAsync(dir(`${g.datadir}/files`));
|
||||||
|
const base_dir = dir(`${g.datadir}/files/${rpath}`);
|
||||||
|
if (typeof req.query_parameters["move"] === "string") {
|
||||||
|
if (rpath) {
|
||||||
|
let moveto = req.query_parameters["move"];
|
||||||
|
|
||||||
|
moveto = moveto
|
||||||
|
.split("/")
|
||||||
|
.map((e) => e.replace(/\.\./gi, ""))
|
||||||
|
.filter((e) => !!e)
|
||||||
|
.join("/");
|
||||||
|
|
||||||
|
await moveAsync(
|
||||||
|
dir(`${g.datadir}/files/${rpath}`),
|
||||||
|
dir(`${g.datadir}/files/${moveto}/${basename(rpath)}`)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return new Response(JSON.stringify({ status: "ok" }), {
|
||||||
|
headers: { "content-type": "application/json" },
|
||||||
|
});
|
||||||
|
} else if (typeof req.query_parameters["del"] === "string") {
|
||||||
|
if (rpath) {
|
||||||
|
const base_dir = dir(`${g.datadir}/files/${rpath}`);
|
||||||
|
if (await existsAsync(base_dir)) {
|
||||||
|
if ((await readdir(base_dir)).length === 0) {
|
||||||
|
await removeAsync(base_dir);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return new Response(JSON.stringify({ status: "ok" }), {
|
||||||
|
headers: { "content-type": "application/json" },
|
||||||
|
});
|
||||||
|
} else if (typeof req.query_parameters["rename"] === "string") {
|
||||||
|
let rename = req.query_parameters["rename"];
|
||||||
|
|
||||||
|
rename = rename
|
||||||
|
.split("/")
|
||||||
|
.map((e) => e.replace(/\.\./gi, ""))
|
||||||
|
.filter((e) => !!e)
|
||||||
|
.join("/");
|
||||||
|
|
||||||
|
let newname = "";
|
||||||
|
if (rpath) {
|
||||||
|
if (await existsAsync(dir(`${g.datadir}/files/${rpath}`))) {
|
||||||
|
await renameAsync(dir(`${g.datadir}/files/${rpath}`), rename);
|
||||||
|
} else {
|
||||||
|
const target = dir(
|
||||||
|
`${g.datadir}/files/${dirname(rpath)}/${rename}`
|
||||||
|
);
|
||||||
|
await dirAsync(target);
|
||||||
|
}
|
||||||
|
newname = `/${dirname(rpath)}/${rename}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
return new Response(JSON.stringify({ newname }), {
|
||||||
|
headers: { "content-type": "application/json" },
|
||||||
|
});
|
||||||
|
} else if (typeof req.query_parameters["dir"] === "string") {
|
||||||
|
try {
|
||||||
|
const files = [] as {
|
||||||
|
name: string;
|
||||||
|
type: "dir" | "file";
|
||||||
|
size: number;
|
||||||
|
}[];
|
||||||
|
await Promise.all(
|
||||||
|
(
|
||||||
|
await readdir(base_dir)
|
||||||
|
).map(async (e) => {
|
||||||
|
const s = await stat(dir(`${g.datadir}/files/${rpath}/${e}`));
|
||||||
|
files.push({
|
||||||
|
name: e,
|
||||||
|
type: s.isDirectory() ? "dir" : "file",
|
||||||
|
size: s.size,
|
||||||
|
});
|
||||||
|
})
|
||||||
|
);
|
||||||
|
return new Response(JSON.stringify(files), {
|
||||||
|
headers: { "content-type": "application/json" },
|
||||||
|
});
|
||||||
|
} catch (e) {
|
||||||
|
return new Response(JSON.stringify([]), {
|
||||||
|
headers: { "content-type": "application/json" },
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const path = dir(`${g.datadir}/files/${rpath}`);
|
||||||
const file = Bun.file(path);
|
const file = Bun.file(path);
|
||||||
|
|
||||||
if (await file.exists()) {
|
if (await file.exists()) {
|
||||||
|
|
|
||||||
|
|
@ -1,36 +1,74 @@
|
||||||
import mp from "@surfy/multipart-parser";
|
import mp from "@surfy/multipart-parser";
|
||||||
import { writeAsync } from "fs-jetpack";
|
import { format, parse } from "path";
|
||||||
import { apiContext } from "service-srv";
|
import { apiContext } from "service-srv";
|
||||||
import { dir } from "utils/dir";
|
import { dir } from "utils/dir";
|
||||||
import { g } from "utils/global";
|
import { g } from "utils/global";
|
||||||
|
|
||||||
export const _ = {
|
export const _ = {
|
||||||
url: "/_upload",
|
url: "/_upload",
|
||||||
|
raw: true,
|
||||||
async api(body: any) {
|
async api(body: any) {
|
||||||
const { req } = apiContext(this);
|
const { req } = apiContext(this);
|
||||||
let url = "";
|
|
||||||
|
|
||||||
const raw = await req.arrayBuffer();
|
const raw = await req.arrayBuffer();
|
||||||
const parts = mp(Buffer.from(raw)) as Record<
|
const parts = mp(Buffer.from(raw)) as Record<
|
||||||
string,
|
string,
|
||||||
{ fileName: string; mime: string; type: string; buffer: Buffer }
|
{ fileName: string; mime: string; type: string; buffer: Buffer }
|
||||||
>;
|
>;
|
||||||
|
|
||||||
|
const result: string[] = [];
|
||||||
for (const [_, part] of Object.entries(parts)) {
|
for (const [_, part] of Object.entries(parts)) {
|
||||||
const d = new Date();
|
result.push(await saveFile(req, part.fileName, part.buffer));
|
||||||
const path = `${d.getFullYear()}-${d.getMonth()}/${d.getDate()}/${d.getTime()}-${part.fileName
|
|
||||||
?.replace(/[\W_]+/g, "-")
|
|
||||||
.toLowerCase()}`;
|
|
||||||
|
|
||||||
url = `/_file/${path}`;
|
|
||||||
await writeAsync(dir(`${g.datadir}/upload/${path}`), part.buffer);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return url;
|
return new Response(JSON.stringify(result), {
|
||||||
|
headers: { "content-type": "application/json" },
|
||||||
|
});
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
function toArrayBuffer(buffer: Buffer) {
|
|
||||||
return buffer.buffer.slice(
|
const saveFile = async (
|
||||||
buffer.byteOffset,
|
req: Request & {
|
||||||
buffer.byteOffset + buffer.byteLength
|
params: any;
|
||||||
);
|
query_parameters: any;
|
||||||
}
|
},
|
||||||
|
fname: string,
|
||||||
|
part: any
|
||||||
|
) => {
|
||||||
|
const d = new Date();
|
||||||
|
let to: string = req.query_parameters["to"] || "";
|
||||||
|
if (!to) {
|
||||||
|
to = `/upload/${d.getFullYear()}-${d.getMonth()}/${d.getDate()}/${d.getTime()}-${fname}`;
|
||||||
|
} else {
|
||||||
|
to = to
|
||||||
|
.split("/")
|
||||||
|
.map((e) => e.replace(/\.\./gi, ""))
|
||||||
|
.filter((e) => !!e)
|
||||||
|
.join("/");
|
||||||
|
|
||||||
|
to = to.endsWith("/") ? to + fname : to + "/" + fname;
|
||||||
|
}
|
||||||
|
to = to.toLowerCase();
|
||||||
|
const pto = parse(to);
|
||||||
|
pto.name = pto.name.replace(/[\W_]+/gi, "-");
|
||||||
|
to = format(pto);
|
||||||
|
|
||||||
|
while (await Bun.file(dir(`${g.datadir}/files/${to}`)).exists()) {
|
||||||
|
const p = parse(to);
|
||||||
|
const arr = p.name.split("-");
|
||||||
|
if (arr.length > 1) {
|
||||||
|
if (parseInt(arr[arr.length - 1])) {
|
||||||
|
arr[arr.length - 1] = parseInt(arr[arr.length - 1]) + 1 + "";
|
||||||
|
} else {
|
||||||
|
arr.push("1");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
arr.push("1");
|
||||||
|
}
|
||||||
|
p.name = arr.filter((e) => e).join("-");
|
||||||
|
p.base = `${p.name}${p.ext}`;
|
||||||
|
|
||||||
|
to = format(p);
|
||||||
|
}
|
||||||
|
await Bun.write(dir(`${g.datadir}/files/${to}`), part);
|
||||||
|
return to;
|
||||||
|
};
|
||||||
|
|
|
||||||
|
|
@ -15,6 +15,7 @@
|
||||||
"radix3": "^1.1.0",
|
"radix3": "^1.1.0",
|
||||||
"typescript": "^5.2.2",
|
"typescript": "^5.2.2",
|
||||||
"unzipper": "^0.10.14",
|
"unzipper": "^0.10.14",
|
||||||
|
"parse-multipart-data": "^1.5.0",
|
||||||
"fast-myers-diff": "^3.2.0"
|
"fast-myers-diff": "^3.2.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -27,6 +27,7 @@ export const createServer = async () => {
|
||||||
const route = {
|
const route = {
|
||||||
url: api._.url,
|
url: api._.url,
|
||||||
args,
|
args,
|
||||||
|
raw: !!api._.raw,
|
||||||
fn: api._.api,
|
fn: api._.api,
|
||||||
path: importPath.substring((root || path).length + 1),
|
path: importPath.substring((root || path).length + 1),
|
||||||
};
|
};
|
||||||
|
|
@ -66,6 +67,7 @@ export const createServer = async () => {
|
||||||
|
|
||||||
g.server = Bun.serve({
|
g.server = Bun.serve({
|
||||||
port: g.port,
|
port: g.port,
|
||||||
|
maxRequestBodySize: 1024 * 1024 * 128,
|
||||||
async fetch(req) {
|
async fetch(req) {
|
||||||
const url = new URL(req.url);
|
const url = new URL(req.url);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,7 @@ export const serveAPI = async (url: URL, req: Request) => {
|
||||||
return params[e];
|
return params[e];
|
||||||
});
|
});
|
||||||
|
|
||||||
if (req.method !== "GET") {
|
if (req.method !== "GET" && !found.raw) {
|
||||||
if (!req.headers.get("content-type")?.startsWith("multipart/form-data")) {
|
if (!req.headers.get("content-type")?.startsWith("multipart/form-data")) {
|
||||||
try {
|
try {
|
||||||
const json = await req.json();
|
const json = await req.json();
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,7 @@ export const deploy = {
|
||||||
await this.load(this.config.deploy.ts);
|
await this.load(this.config.deploy.ts);
|
||||||
},
|
},
|
||||||
async load(ts: string) {
|
async load(ts: string) {
|
||||||
console.log(`Loading site: ${this.config.site_id} [ts: ${ts}]`);
|
console.log(`Loading site: ${this.config.site_id} ${ts}`);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
g.deploy.gz = JSON.parse(
|
g.deploy.gz = JSON.parse(
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@ import { prodIndex } from "./prod-index";
|
||||||
type SingleRoute = {
|
type SingleRoute = {
|
||||||
url: string;
|
url: string;
|
||||||
args: string[];
|
args: string[];
|
||||||
|
raw: boolean;
|
||||||
fn: (...arg: any[]) => Promise<any>;
|
fn: (...arg: any[]) => Promise<any>;
|
||||||
path: string;
|
path: string;
|
||||||
};
|
};
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue