From 2262c501a2f9f6847cce3638dd8d52a069759a33 Mon Sep 17 00:00:00 2001 From: Benjamin Smith Date: Thu, 16 Oct 2025 12:43:17 +0200 Subject: [PATCH] Zod Schemas --- bun.lock | 7 +++++- packages/agent-sdk/package.json | 3 ++- packages/agent-sdk/src/schema.ts | 39 ++++++++++++++++++++++++++++++ packages/agent-sdk/src/validate.ts | 2 ++ 4 files changed, 49 insertions(+), 2 deletions(-) create mode 100644 packages/agent-sdk/src/schema.ts diff --git a/bun.lock b/bun.lock index e6600d4..9b9dd4c 100644 --- a/bun.lock +++ b/bun.lock @@ -29,6 +29,7 @@ "near-api-js": "^6.3.0", "viem": "^2.37.5", "zerion-sdk": "^0.1.6", + "zod": "^4.1.11", }, }, }, @@ -1017,7 +1018,7 @@ "zerion-sdk": ["zerion-sdk@0.1.6", "", { "dependencies": { "viem": "^2.33.0" } }, "sha512-32rFjkeGV5O6KWEPblRGmgz/LL8gzPoMFKw+zV4Kl+dtPhZinjVzrEKUL8HcMvklkUEdkt67nvUrMPRWuByCrA=="], - "zod": ["zod@3.22.4", "", {}, "sha512-iC+8Io04lddc+mVqQ9AZ7OQ2MrUKGN+oIQyq1vemgt46jwCwLfhq7/pwnBnNXXXZb8VTVLKwp9EDkx+ryxIWmg=="], + "zod": ["zod@4.1.11", "", {}, "sha512-WPsqwxITS2tzx1bzhIKsEs19ABD5vmCVa4xBo2tq/SrV4RNZtfws1EnCWQXM6yh8bD08a1idvkB5MZSBiZsjwg=="], "@babel/core/semver": ["semver@6.3.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="], @@ -1291,6 +1292,8 @@ "jest-validate/pretty-format/@jest/schemas": ["@jest/schemas@30.0.5", "", { "dependencies": { "@sinclair/typebox": "^0.34.0" } }, "sha512-DmdYgtezMkh3cpU8/1uyXakv3tJRcmcXxBOcO0tbaozPwpmh4YMsnWrQm9ZmZMfa5ocbxzbFk6O4bDPEc/iAnA=="], + "ox/abitype/zod": ["zod@3.22.4", "", {}, "sha512-iC+8Io04lddc+mVqQ9AZ7OQ2MrUKGN+oIQyq1vemgt46jwCwLfhq7/pwnBnNXXXZb8VTVLKwp9EDkx+ryxIWmg=="], + "pkg-dir/find-up/locate-path": ["locate-path@5.0.0", "", { "dependencies": { "p-locate": "^4.1.0" } }, "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g=="], "test-exclude/glob/inherits": ["inherits@2.0.4", "", {}, "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="], @@ -1323,6 +1326,8 @@ "pkg-dir/find-up/locate-path/p-locate": ["p-locate@4.1.0", "", { "dependencies": { "p-limit": "^2.2.0" } }, "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A=="], + "zerion-sdk/viem/abitype/zod": ["zod@3.22.4", "", {}, "sha512-iC+8Io04lddc+mVqQ9AZ7OQ2MrUKGN+oIQyq1vemgt46jwCwLfhq7/pwnBnNXXXZb8VTVLKwp9EDkx+ryxIWmg=="], + "@istanbuljs/load-nyc-config/find-up/locate-path/p-locate/p-limit": ["p-limit@2.3.0", "", { "dependencies": { "p-try": "^2.0.0" } }, "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w=="], "@jest/expect/expect/jest-matcher-utils/pretty-format/@jest/schemas": ["@jest/schemas@30.0.5", "", { "dependencies": { "@sinclair/typebox": "^0.34.0" } }, "sha512-DmdYgtezMkh3cpU8/1uyXakv3tJRcmcXxBOcO0tbaozPwpmh4YMsnWrQm9ZmZMfa5ocbxzbFk6O4bDPEc/iAnA=="], diff --git a/packages/agent-sdk/package.json b/packages/agent-sdk/package.json index f26f537..d71b14e 100644 --- a/packages/agent-sdk/package.json +++ b/packages/agent-sdk/package.json @@ -51,6 +51,7 @@ "dependencies": { "near-api-js": "^6.3.0", "viem": "^2.37.5", - "zerion-sdk": "^0.1.6" + "zerion-sdk": "^0.1.6", + "zod": "^4.1.11" } } diff --git a/packages/agent-sdk/src/schema.ts b/packages/agent-sdk/src/schema.ts new file mode 100644 index 0000000..7945157 --- /dev/null +++ b/packages/agent-sdk/src/schema.ts @@ -0,0 +1,39 @@ +import { z } from "zod"; + +type Logger = (...args: unknown[]) => void; + +export type ValidationResult = + | { ok: true; query: T } + | { ok: false; error: object }; + +export function validateQuery( + req: { + // url used for GET requests. + url: string; + // TODO: Parse Body. + }, + schema: T, + opts: { + log?: Logger; + } = {}, +): ValidationResult> { + const log = opts.log ?? (() => {}); // default no-op + log("Raw request", req.url); + if (req.url.startsWith("/?")) { + req.url = req.url.slice(2); + } + const params = new URLSearchParams(req.url); + log("params", params); + const result = schema.safeParse(Object.fromEntries(params.entries())); + log("parsed query", result); + if (!result.success) { + return { ok: false as const, error: z.treeifyError(result.error) }; + } + return { ok: true as const, query: result.data }; +} + +export function isInvalid( + result: ValidationResult, +): result is { ok: false; error: object } { + return result.ok === false; +} diff --git a/packages/agent-sdk/src/validate.ts b/packages/agent-sdk/src/validate.ts index 3a4d760..ca7bb26 100644 --- a/packages/agent-sdk/src/validate.ts +++ b/packages/agent-sdk/src/validate.ts @@ -1,3 +1,5 @@ +// All of this is deprecated in favour of ./schema +// Will be kept around for a while. import { type Address, getAddress } from "viem"; export type FieldParser = Record>;