Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion eslint.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -216,7 +216,7 @@ export default tsPlugin.config(
name: "source/ez",
files: ["express-zod-api/src/*.ts"],
rules: {
complexity: ["error", 20],
complexity: ["error", 18],
"allowed/dependencies": ["error", { packageDir: ezDir }],
"no-restricted-syntax": [
"warn",
Expand Down
56 changes: 49 additions & 7 deletions express-zod-api/bench/experiment.bench.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,56 @@
import * as R from "ramda";
import { bench } from "vitest";
import type { UploadedFile } from "express-fileupload";
import { isObjectOfUploadShape } from "../src/upload-schema";
import { z } from "zod";

describe("Experiment for unique elements", () => {
const current = ["one", "two"];
describe("Experiment for upload schema", () => {
const current = () =>
z.custom<UploadedFile>(
(subject) =>
typeof subject === "object" &&
subject !== null &&
"name" in subject &&
"encoding" in subject &&
"mimetype" in subject &&
"data" in subject &&
"tempFilePath" in subject &&
"truncated" in subject &&
"size" in subject &&
"md5" in subject &&
"mv" in subject &&
typeof subject.name === "string" &&
typeof subject.encoding === "string" &&
typeof subject.mimetype === "string" &&
Buffer.isBuffer(subject.data) &&
typeof subject.tempFilePath === "string" &&
typeof subject.truncated === "boolean" &&
typeof subject.size === "number" &&
typeof subject.md5 === "string" &&
typeof subject.mv === "function",
);

bench("set", () => {
return void [...new Set(current).add("null")];
const featured = () =>
z.custom<UploadedFile>(
(subject) =>
isObjectOfUploadShape(subject) &&
typeof subject.name === "string" &&
typeof subject.encoding === "string" &&
typeof subject.mimetype === "string" &&
Buffer.isBuffer(subject.data) &&
typeof subject.tempFilePath === "string" &&
typeof subject.truncated === "boolean" &&
typeof subject.size === "number" &&
typeof subject.md5 === "string" &&
typeof subject.mv === "function",
);

bench("current", () => {
const one = current();
one.safeParse({});
});

bench("R.union", () => {
return void R.union(current, ["null"]);
bench("featured", () => {
const one = featured();
one.safeParse({});
});
});
26 changes: 15 additions & 11 deletions express-zod-api/src/upload-schema.ts
Original file line number Diff line number Diff line change
@@ -1,23 +1,27 @@
import type { UploadedFile } from "express-fileupload";
import { z } from "zod";
import { isObject } from "./common-helpers";

export const ezUploadBrand = Symbol("Upload");

/** @internal */
export const isObjectOfUploadShape = (subject: unknown) =>
isObject(subject) &&
"name" in subject &&
"encoding" in subject &&
"mimetype" in subject &&
"data" in subject &&
"tempFilePath" in subject &&
"truncated" in subject &&
"size" in subject &&
"md5" in subject &&
"mv" in subject;

export const upload = () =>
z
.custom<UploadedFile>(
(subject) =>
typeof subject === "object" &&
subject !== null &&
"name" in subject &&
"encoding" in subject &&
"mimetype" in subject &&
"data" in subject &&
"tempFilePath" in subject &&
"truncated" in subject &&
"size" in subject &&
"md5" in subject &&
"mv" in subject &&
isObjectOfUploadShape(subject) &&
typeof subject.name === "string" &&
typeof subject.encoding === "string" &&
typeof subject.mimetype === "string" &&
Expand Down
53 changes: 52 additions & 1 deletion express-zod-api/tests/upload-schema.spec.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,60 @@
import { z } from "zod";
import { ez } from "../src";
import { getBrand } from "@express-zod-api/zod-plugin";
import { ezUploadBrand } from "../src/upload-schema";
import { ezUploadBrand, isObjectOfUploadShape } from "../src/upload-schema";

describe("ez.upload()", () => {
describe("isObjectOfUploadShape() helper", () => {
test.each([null, undefined, "test", 123, false])(
"should return false for non-object %#",
(subject) => {
expect(isObjectOfUploadShape(subject)).toBe(false);
},
);

test.each([
"name",
"encoding",
"mimetype",
"data",
"tempFilePath",
"truncated",
"size",
"md5",
"mv",
] as const)("should return false when missing $% key", (key) => {
const input = {
name: null,
encoding: null,
mimetype: null,
data: null,
tempFilePath: null,
truncated: null,
size: null,
md5: null,
mv: null,
};
delete input[key];
expect(isObjectOfUploadShape(input)).toBe(false);
Comment thread
RobinTail marked this conversation as resolved.
});

test("should return true for an object of valid shape", () => {
expect(
isObjectOfUploadShape({
name: null,
encoding: null,
mimetype: null,
data: null,
tempFilePath: null,
truncated: null,
size: null,
md5: null,
mv: null,
}),
).toBe(true);
});
});

describe("creation", () => {
test("should create an instance", () => {
const schema = ez.upload();
Expand Down
Loading