118 lines
4.1 KiB
JavaScript
118 lines
4.1 KiB
JavaScript
import { readFile } from "node:fs/promises";
|
|
import { resolve } from "node:path";
|
|
import { defineConfig, loadEnv } from "vite";
|
|
|
|
const MAX_BATCH_BYTES = 96 * 1024;
|
|
const L2_MARKET_IMPORT_TOKEN = "ebc212a3735eddf2b3ce7bcaf01522e2d53425483436ff1814e7998a8bde8d0e";
|
|
|
|
export async function forwardMarketBatch(body, { url, token, fetchImpl = fetch }) {
|
|
if (!url || !token) return new Response("Market import is not configured", { status: 503 });
|
|
return fetchImpl(url, {
|
|
method: "POST",
|
|
headers: { Authorization: `Bearer ${token}`, "Content-Type": "application/json" },
|
|
body,
|
|
redirect: "error",
|
|
signal: AbortSignal.timeout(15_000),
|
|
});
|
|
}
|
|
|
|
export function rejectNonLocalRequest(request) {
|
|
const rawContentType = request.headers["content-type"];
|
|
const contentType = typeof rawContentType === "string" ? rawContentType.split(";", 1)[0].trim().toLowerCase() : "";
|
|
if (contentType !== "application/json") return 415;
|
|
const host = typeof request.headers.host === "string" ? request.headers.host : "";
|
|
return request.headers.origin === `http://${host}` ? null : 403;
|
|
}
|
|
|
|
function marketImportProxy(options) {
|
|
return {
|
|
name: "market-import-proxy",
|
|
configureServer(server) {
|
|
server.middlewares.use("/api/market-import", async (request, response) => {
|
|
if (request.method !== "POST") {
|
|
response.statusCode = 405;
|
|
response.end();
|
|
return;
|
|
}
|
|
const rejection = rejectNonLocalRequest(request);
|
|
if (rejection) {
|
|
response.statusCode = rejection;
|
|
response.end();
|
|
return;
|
|
}
|
|
|
|
try {
|
|
const body = await readBody(request);
|
|
const upstream = await forwardMarketBatch(body, options);
|
|
response.statusCode = upstream.status;
|
|
response.setHeader("Content-Type", upstream.headers.get("content-type") || "application/json");
|
|
response.end(await upstream.text());
|
|
} catch (error) {
|
|
response.statusCode = error.code === "BATCH_TOO_LARGE" ? 413 : 502;
|
|
response.end(error.code === "BATCH_TOO_LARGE" ? "Batch too large" : "Market import failed");
|
|
}
|
|
});
|
|
},
|
|
};
|
|
}
|
|
|
|
function fixtureOcrAssets() {
|
|
const assets = new Map([
|
|
["/__fixtures/tesseract/worker.min.js", ["node_modules/tesseract.js/dist/worker.min.js", "text/javascript"]],
|
|
["/__fixtures/tesseract/tesseract-core-simd-lstm.wasm.js", ["node_modules/tesseract.js-core/tesseract-core-simd-lstm.wasm.js", "text/javascript"]],
|
|
["/__fixtures/tesseract/tesseract-core-simd-lstm.wasm", ["node_modules/tesseract.js-core/tesseract-core-simd-lstm.wasm", "application/wasm"]],
|
|
["/__fixtures/tessdata/eng.traineddata", ["eng.traineddata", "application/octet-stream"]],
|
|
]);
|
|
return {
|
|
name: "fixture-ocr-assets",
|
|
configureServer(server) {
|
|
server.middlewares.use(async (request, response, next) => {
|
|
const asset = assets.get(request.url?.split("?", 1)[0]);
|
|
if (!asset) return next();
|
|
response.statusCode = 200;
|
|
response.setHeader("Content-Type", asset[1]);
|
|
response.end(await readFile(resolve(asset[0])));
|
|
});
|
|
},
|
|
};
|
|
}
|
|
|
|
function readBody(request) {
|
|
return new Promise((resolve, reject) => {
|
|
const chunks = [];
|
|
let size = 0;
|
|
let tooLarge = false;
|
|
request.on("data", (chunk) => {
|
|
if (tooLarge) return;
|
|
size += chunk.length;
|
|
if (size > MAX_BATCH_BYTES) {
|
|
tooLarge = true;
|
|
const error = new Error("Batch too large");
|
|
error.code = "BATCH_TOO_LARGE";
|
|
reject(error);
|
|
return;
|
|
}
|
|
chunks.push(chunk);
|
|
});
|
|
request.on("end", () => {
|
|
if (!tooLarge) resolve(Buffer.concat(chunks).toString("utf8"));
|
|
});
|
|
request.on("error", reject);
|
|
});
|
|
}
|
|
|
|
export default defineConfig(({ mode }) => {
|
|
const environment = loadEnv(mode, process.cwd(), "");
|
|
return {
|
|
base: "./",
|
|
define: { __FIXTURE_OCR__: JSON.stringify(mode === "test") },
|
|
plugins: [
|
|
mode === "test" ? fixtureOcrAssets() : null,
|
|
marketImportProxy({
|
|
url: environment.L2_MARKET_IMPORT_URL,
|
|
token: L2_MARKET_IMPORT_TOKEN,
|
|
}),
|
|
].filter(Boolean),
|
|
};
|
|
});
|