diff --git a/api.planx.uk/modules/file/service/uploadFile.ts b/api.planx.uk/modules/file/service/uploadFile.ts index d272018c70..ead3cee9af 100644 --- a/api.planx.uk/modules/file/service/uploadFile.ts +++ b/api.planx.uk/modules/file/service/uploadFile.ts @@ -7,7 +7,6 @@ import mime from "mime"; import { customAlphabet } from "nanoid"; import { isLiveEnv } from "../../../helpers.js"; import { s3Factory } from "./utils.js"; -import { Readable } from "stream"; const nanoid = customAlphabet("1234567890abcdefghijklmnopqrstuvwxyz", 8); export const uploadPublicFile = async ( @@ -29,14 +28,10 @@ export const uploadPublicFile = async ( }; export const uploadPrivateFile = async ( - file: Express.Multer.File | Buffer, + file: Express.Multer.File, filename: string, filekey?: string, ) => { - if (file instanceof Buffer) { - file = convertToMulterFile(file); - } - const s3 = s3Factory(); const { params, key, fileType } = generateFileParams(file, filename, filekey); @@ -68,19 +63,6 @@ const buildFileUrl = async (key: string, path: "public" | "private") => { return `${process.env.API_URL_EXT}/file/${path}${s3Pathname}`; }; -const convertToMulterFile = (buffer: Buffer): Express.Multer.File => ({ - buffer: buffer, - originalname: "${data.id}.json", - mimetype: "application/json", - size: buffer.length, - fieldname: "file", - encoding: "7bit", - stream: Readable.from(buffer), - destination: "", - filename: "", - path: "", -}); - export function generateFileParams( file: Express.Multer.File, filename: string, diff --git a/api.planx.uk/modules/file/service/utils.ts b/api.planx.uk/modules/file/service/utils.ts index 0f95e170e5..85e58cd110 100644 --- a/api.planx.uk/modules/file/service/utils.ts +++ b/api.planx.uk/modules/file/service/utils.ts @@ -1,5 +1,6 @@ import { S3 } from "@aws-sdk/client-s3"; import { isLiveEnv } from "../../../helpers.js"; +import { Readable } from "stream"; export function s3Factory() { return new S3({ @@ -40,3 +41,23 @@ export function getS3KeyFromURL(fileURL: string): string { const key = [folder, file].map(decodeURIComponent).join("/"); return key; } + +export const convertObjectToMulterJSONFile = ( + data: Record, + fileName: string, +): Express.Multer.File => { + const buffer = Buffer.from(JSON.stringify(data)); + + return { + buffer: buffer, + originalname: fileName, + mimetype: "application/json", + size: buffer.length, + fieldname: "file", + encoding: "7bit", + stream: Readable.from(buffer), + destination: "", + filename: "", + path: "", + }; +}; diff --git a/api.planx.uk/modules/send/s3/index.ts b/api.planx.uk/modules/send/s3/index.ts index 8bf46acf5e..d6d8290f8f 100644 --- a/api.planx.uk/modules/send/s3/index.ts +++ b/api.planx.uk/modules/send/s3/index.ts @@ -8,10 +8,7 @@ import { uploadPrivateFile } from "../../file/service/uploadFile.js"; import { markSessionAsSubmitted } from "../../saveAndReturn/service/utils.js"; import { isApplicationTypeSupported } from "../utils/helpers.js"; import type { SendIntegrationController } from "../types.js"; - -// TS fails to validate this complex type when awaited -// Represent as a simple object to allow enough typechecking to kick in -type DigitalPlanningPayload = Record; +import { convertObjectToMulterJSONFile } from "../../file/service/utils.js"; interface CreateS3Application { insertS3Application: { @@ -49,13 +46,15 @@ const sendToS3: SendIntegrationController = async (_req, res, next) => { // Generate the ODP Schema JSON, skipping validation if not a supported application type const doValidation = isApplicationTypeSupported(passport); - const exportData: DigitalPlanningPayload = - await $api.export.digitalPlanningDataPayload(sessionId, doValidation); - - const buffer = Buffer.from(JSON.stringify(exportData)); + const exportData = await $api.export.digitalPlanningDataPayload( + sessionId, + doValidation, + ); // Create and upload the data as an S3 file - const { fileUrl } = await uploadPrivateFile(buffer, `${sessionId}.json`); + const filename = `${sessionId}.json`; + const file = convertObjectToMulterJSONFile(exportData, filename); + const { fileUrl } = await uploadPrivateFile(file, filename); // Send a notification with the file URL to the Power Automate webhook const webhookRequest: AxiosRequestConfig = {