rcu-fastify
Version:
Fastify handler for Resumable Chunk Upload
101 lines (98 loc) • 2.87 kB
JavaScript
// src/index.ts
import { JsonStoreProvider, RCUService } from "rcu-back-core";
// src/handler.ts
import { ZodError, z } from "zod";
import multipart from "@fastify/multipart";
var uploadStatusSchema = z.object({
fileId: z.string().min(1),
chunkCount: z.coerce.number()
});
var uploadSchema = z.object({
fileId: z.string().min(1),
chunkNumber: z.coerce.number(),
originalFilename: z.string().min(1),
chunkCount: z.coerce.number(),
chunkSize: z.coerce.number(),
fileSize: z.coerce.number(),
file: z.instanceof(Buffer)
});
function handler(service, config) {
const { uploadStatusPath = "/uploadStatus", uploadPath = "/upload" } = config ?? {};
return async (fastify) => {
fastify.register(multipart, { attachFieldsToBody: true });
fastify.get(
uploadStatusPath,
async (request, reply) => {
try {
const query = uploadStatusSchema.parse(request.query);
const response = await service.uploadStatus(query);
return reply.send(response);
} catch (error) {
if (error instanceof ZodError) {
return reply.status(400).send({ message: "Invalid parameter" });
}
return reply.status(500).send({ message: "Internal server error" });
}
}
);
fastify.post(
uploadPath,
async (request, reply) => {
try {
const originalBody = request.body ?? {};
const body = Object.fromEntries(
Object.keys(originalBody).map((key) => [
key,
originalBody[key].value
])
);
const dto = await uploadSchema.parse({
...body,
file: await originalBody.file?.toBuffer()
});
const response = await service.upload(dto);
return reply.send(response);
} catch (error) {
if (error.code === "FST_INVALID_MULTIPART_CONTENT_TYPE") {
return reply.status(400).send({ message: "Invalid parameter" });
}
if (error instanceof ZodError) {
return reply.status(400).send({ message: "Invalid parameter" });
}
return reply.status(500).send({ message: "Internal server error" });
}
}
);
};
}
// src/index.ts
import {
JsonStoreProvider as JsonStoreProvider2,
StoreProviderInterface,
Upload,
RCUConfig as RCUConfig2
} from "rcu-back-core";
function resumableChunkUpload(config = {}) {
const {
store = new JsonStoreProvider("./tmp/rcu.json"),
tmpDir = "./tmp",
outputDir,
onCompleted
} = config;
return handler(
new RCUService({
store,
tmpDir,
outputDir: outputDir ?? tmpDir,
onCompleted
}),
config
);
}
export {
JsonStoreProvider2 as JsonStoreProvider,
RCUConfig2 as RCUConfig,
StoreProviderInterface,
Upload,
resumableChunkUpload
};