square / square-nodejs-sdk

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

createCatalogImage is unable to use native File type?

ozzyonfire opened this issue · comments

Describe the bug
The createCatalogImage call does not accept a File type. Getting an error; source.on is not a function.

Expected behavior
The api should be able to handle the native File type from node as it is a subset of Blob.

To Reproduce
Steps to reproduce the bug:

Create a form on your client:

	const handleSubmit = async (event: React.FormEvent<HTMLFormElement>) => {
		event.preventDefault();
		const formData = new FormData(event.currentTarget);
		const response = await fetch('/api/upload', {
			method: 'POST',
			body: formData,
		});
		const json = await response.json();
		console.log(json);
	}

	return (
		<form onSubmit={handleSubmit} className="flex flex-col gap-2" encType="multipart/form-data">
			<input type="hidden" name="id" value={props.id} />
			<label htmlFor="image">
				<span className="text-xl font-bold text-gray-900">Image</span>
				<input type="file" name="image" required />
			</label>
			<button className="rounded border border-gray-200 px-4 py-1" type="submit">Upload</button>
		</form>
	)

Server side create the image

import client from "@/lib/square";
import { FileWrapper } from "square";

export const POST = async (request: Request) => {
	// form submission to upload photo
	const body = await request.formData();

	console.log(request.headers.get("Content-Type"));

	const { image, id } = Object.fromEntries(body.entries()) as {
		image: File;
		id: string;
	};

	const fileWrapper = new FileWrapper(image, {
		contentType: image.type,
		filename: image.name,

	});

	try {
		const { result, request, body } = await client.catalogApi.createCatalogImage({
			objectId: id.toString(),
			isPrimary: true,
			idempotencyKey: id.toString(),
			image: {
				id: `#${id}`,
				type: "IMAGE",
				imageData: {
					caption: "test",
					name: image.name,
				},
			}
		}, fileWrapper);
		console.log(result);
	} catch (err) {
		console.error(err);
		const error = err as Error;
	}

	return new Response("ok");
}

Screenshots
image

Square SDK version
^33.1.0

Additional context
It seems like the work around could be to save the file to disk and then create a readstream from there, but with the advent of serverless frameworks (and moving to more native js apis) I would expect this flow to work.

And I figured it out.... was just missing a step of converting the file to a Readable stream.

new backend code;

import client from "@/lib/square";
import { FileWrapper } from "square";
import { Readable } from "stream";

export const POST = async (request: Request) => {
	// form submission to upload photo
	const body = await request.formData();
	const { image, id } = Object.fromEntries(body.entries()) as {
		image: File;
		id: string;
	};

	// convert image to Readable stream
	const bytes = await image.arrayBuffer();
	const buffer = Buffer.from(bytes);
	const readable = new Readable();
	readable.push(buffer);
	readable.push(null);

	const fileWrapper = new FileWrapper(readable, {
		contentType: image.type,
		filename: image.name,
	});

	try {
		const { result } = await client.catalogApi.createCatalogImage({
			objectId: id.toString(),
			isPrimary: true,
			idempotencyKey: id.toString(),
			image: {
				id: `#${id}`,
				type: "IMAGE",
				imageData: {
					caption: "test",
					name: image.name,
				},
			}
		}, fileWrapper);
		console.log(result);
	} catch (err) {
		console.error(err);
		const error = err as Error;
	}

	return new Response("ok");
}

Hopefully this helps someone else. There could be a case where the package itself could just accept the File type and save us a step, so I will leave it open. However if the above is the recommended method maybe we could consider adding it t othe docs?

Hey @ozzyonfire - sorry for the pain point here, but yes converting image file to a readable stream is the correct course of action here. I am looking at our docs though, and am seeing what you are saying that we don't seem to have that defined anywhere in the reference or guides. The sample code usually shows converting it to a readable stream, but we should be more clear on that. Thank you for your contributions here, and I'll take this feedback to the relevant team to get this addressed. Thanks!