pull/715/head
Travis Fischer 2025-06-03 20:10:30 +07:00
rodzic 616de90df8
commit 47e9284e73
6 zmienionych plików z 49 dodań i 11 usunięć

Wyświetl plik

@ -2,7 +2,18 @@ import { HttpError } from '@agentic/platform-core'
import { Validator } from '@cfworker/json-schema'
import plur from 'plur'
export function validateJsonSchemaObject<
/**
* Validates `data` against the provided JSON schema object.
*
* This method uses `@cfworker/json-schema` and does not use `ajv` because CF
* workers does not support `ajv` due to its dynamic code generation and
* evaluation.
*
* If you want a stricter version of this method which uses `ajv` and you're
* not running on CF workers, consider using `validateJsonSchemaObject` from
* `@agentic/platform-openapi-utils`.
*/
export function cfValidateJsonSchemaObject<
T extends Record<string, unknown> = Record<string, unknown>
>({
schema,

Wyświetl plik

@ -5,7 +5,7 @@ import type {
} from '@agentic/platform-types'
import { assert } from '@agentic/platform-core'
import { validateJsonSchemaObject } from './validate-json-schema-object'
import { cfValidateJsonSchemaObject } from './cf-validate-json-schema-object'
export async function createRequestForOpenAPIOperation({
request,
@ -39,7 +39,7 @@ export async function createRequestForOpenAPIOperation({
}
// TODO: Validate incoming request params against the tool's input JSON schema
validateJsonSchemaObject({
cfValidateJsonSchemaObject({
schema: tool.inputSchema,
data: incomingRequestParams,
errorMessage: `Invalid request parameters for tool "${tool.name}"`

Wyświetl plik

@ -31,7 +31,8 @@
"ajv-formats": "^3.0.1",
"camelcase": "catalog:",
"decamelize": "catalog:",
"fast-uri": "^3.0.6"
"fast-uri": "^3.0.6",
"plur": "^5.1.0"
},
"publishConfig": {
"access": "public"

Wyświetl plik

@ -1,5 +1,5 @@
export * from './get-tools-from-openapi-spec'
export * from './redocly-config'
export type * from './types'
export * from './validate-json-schema'
export * from './validate-json-schema-object'
export * from './validate-openapi-spec'

Wyświetl plik

@ -3,6 +3,7 @@ import { betterAjvErrors } from '@apideck/better-ajv-errors'
import Ajv, { type ValidateFunction } from 'ajv'
import addFormats from 'ajv-formats'
import fastUri from 'fast-uri'
import plur from 'plur'
const globalAjv = new Ajv({
coerceTypes: true,
@ -17,10 +18,18 @@ const globalAjv = new Ajv({
// https://github.com/ajv-validator/ajv-formats
addFormats(globalAjv)
// NOTE: Ajv is not compatible with Cloudflare Workers.
// @see https://github.com/ajv-validator/ajv/issues/2318
export function validateJsonSchema<
/**
* Validates `data` against the provided JSON schema object.
*
* This method uses `ajv` and is therefore not compatible with CF workers due
* to its use of code generation and evaluation.
*
* The API gateway uses `cfValidateJsonSchemaObject`, which is looser but
* special-cased for CF workers.
*
* @see https://github.com/ajv-validator/ajv/issues/2318
*/
export function validateJsonSchemaObject<
T extends Record<string, unknown> = Record<string, unknown>
>({
schema,
@ -33,6 +42,20 @@ export function validateJsonSchema<
ajv?: Ajv
errorMessage?: string
}): T {
// Special-case check for required fields to give better error messages
if (Array.isArray(schema.required)) {
const missingRequiredFields: string[] = schema.required.filter(
(field: string) => (data as T)[field] === undefined
)
if (missingRequiredFields.length > 0) {
throw new HttpError({
statusCode: 400,
message: `${errorMessage ? errorMessage + ': ' : ''}Missing required ${plur('field', missingRequiredFields.length)}: ${missingRequiredFields.map((field) => `"${field}"`).join(', ')}`
})
}
}
const schemaHashKey = hashObject(schema)
let validate = ajv.getSchema(schemaHashKey) as ValidateFunction<T>
if (!validate) {
@ -40,14 +63,14 @@ export function validateJsonSchema<
ajv.addSchema(schema, schemaHashKey)
}
// TODO: Add better error messages
if (ajv.validate(schema, data)) {
return data as T
}
// TODO: Add better error messages
const errors = betterAjvErrors({ schema, data, errors: ajv.errors })
const finalErrorMessage = [
errorMessage,
errorMessage ? `${errorMessage}: ` : undefined,
...errors.map((error) => JSON.stringify(error, null, 2))
]
.filter(Boolean)

Wyświetl plik

@ -541,6 +541,9 @@ importers:
fast-uri:
specifier: ^3.0.6
version: 3.0.6
plur:
specifier: ^5.1.0
version: 5.1.0
devDependencies:
'@hono/node-server':
specifier: 'catalog:'