aboutsummaryrefslogtreecommitdiff
path: root/src/app/api/batch/route.ts
diff options
context:
space:
mode:
Diffstat (limited to 'src/app/api/batch/route.ts')
-rw-r--r--src/app/api/batch/route.ts58
1 files changed, 58 insertions, 0 deletions
diff --git a/src/app/api/batch/route.ts b/src/app/api/batch/route.ts
new file mode 100644
index 0000000..46e8b3c
--- /dev/null
+++ b/src/app/api/batch/route.ts
@@ -0,0 +1,58 @@
+import { z } from 'zod';
+import * as send from '@/app/api/send/route';
+import { parseRequest } from '@/lib/request';
+import { json, serverError } from '@/lib/response';
+import { anyObjectParam } from '@/lib/schema';
+
+const schema = z.array(anyObjectParam);
+
+export async function POST(request: Request) {
+ try {
+ const { body, error } = await parseRequest(request, schema, { skipAuth: true });
+
+ if (error) {
+ return error();
+ }
+
+ const errors = [];
+
+ let index = 0;
+ let cache = null;
+ for (const data of body) {
+ // Recreate a fresh Request since `new Request(request)` will have the following error:
+ // > Cannot read private member #state from an object whose class did not declare it
+
+ // Copy headers we received, ensure JSON content type, and avoid conflicting content-length
+ const headers = new Headers(request.headers);
+ headers.set('content-type', 'application/json');
+ headers.delete('content-length');
+
+ const newRequest = new Request(request.url, {
+ method: 'POST',
+ headers,
+ body: JSON.stringify(data),
+ });
+
+ const response = await send.POST(newRequest);
+ const responseJson = await response.json();
+
+ if (!response.ok) {
+ errors.push({ index, response: responseJson });
+ } else {
+ cache ??= responseJson.cache;
+ }
+
+ index++;
+ }
+
+ return json({
+ size: body.length,
+ processed: body.length - errors.length,
+ errors: errors.length,
+ details: errors,
+ cache,
+ });
+ } catch (e) {
+ return serverError(e);
+ }
+}