Skip to content

Commit

Permalink
mock file and filelist for node environment support
Browse files Browse the repository at this point in the history
  • Loading branch information
ethangardner committed Nov 11, 2024
1 parent 465c83c commit b6c1638
Showing 1 changed file with 29 additions and 9 deletions.
38 changes: 29 additions & 9 deletions packages/forms/src/patterns/attachment/response.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,26 +2,46 @@ import { z } from 'zod';
import { ParseUserInput } from '../../pattern.js';
import { safeZodParseToFormError } from '../../util/zod.js';
import { type AttachmentPattern } from './config.js';
/**
* To make this work in both the browser, a suggested approach was to mock the
* File and FileList in Node.
*/
class NodeFile {
constructor(
public type: string,
public size: number
) {}
}

class NodeFileList extends Array<NodeFile> {}

const createSchema = (data: AttachmentPattern['data']) => {
// Define the maximum file size in bytes
const maxFileSizeBytes = data.maxFileSizeMB * 1024 * 1024;
// Determine if we are in the browser environment and set the class to the correct type
const isBrowser =
typeof window !== 'undefined' && typeof window.FileList !== 'undefined';
const FileClass = isBrowser ? File : NodeFile;
const FileListClass = isBrowser ? FileList : NodeFileList;

// Define the schema for a single file in the FileList
const fileSchema = z
.instanceof(File)
.refine((file: File) => data.allowedFileTypes.includes(file.type), {
message: `Invalid file type`,
})
.refine((file: File) => file.size <= maxFileSizeBytes, {
.instanceof(FileClass)
.refine(
(file: File | NodeFile) => data.allowedFileTypes.includes(file.type),
{
message: `Invalid file type`,
}
)
.refine((file: File | NodeFile) => file.size <= maxFileSizeBytes, {
message: `Each file must be smaller than ${data.maxFileSizeMB} MB`,
});

// Define the schema for the FileList as a whole
return z
.custom<FileList>(
(fileList: FileList) => {
if (!(fileList instanceof FileList)) {
.custom<FileList | NodeFileList>(
(fileList: FileList | NodeFileList) => {
if (!(fileList instanceof FileListClass)) {
return false;
} else if (data.required && fileList.length === 0) {
return false;
Expand All @@ -37,7 +57,7 @@ const createSchema = (data: AttachmentPattern['data']) => {
: `You must provide between 1 and ${data.maxAttachments} file(s).`,
}
)
.superRefine((fileList: FileList, ctx: z.RefinementCtx) => {
.superRefine((fileList: FileList | NodeFileList, ctx: z.RefinementCtx) => {
Array.from(fileList).forEach(file => {
const result = fileSchema.safeParse(file);
if (!result.success) {
Expand Down

0 comments on commit b6c1638

Please sign in to comment.