Closed foreseaz closed 3 days ago
@foreseaz Hi,
You can use TypeBox validators in CloudFlare, but you will need to swap from the TypeCompiler
to the Value.*
functions.
https://github.com/sinclairzx81/typebox?tab=readme-ov-file#check
import { Value } from '@sinclair/typebox/value'
const T = Type.Object({
x: Type.Number(),
y: Type.Number(),
z: Type.Number()
})
// Safe to Use in Cloudflare
const R2 = Value.Check(T, { x: 1, y: 2, z: 3 })
The Value.Check function works the same as compiled version, but is non-optimized so you will see a significant reduction of validation performance, however the performance should still be more than adequate for most applications. You can find a performance comparison between Dynamic (Value) and Compiled (TypeCompiler, Ajv) checking at the link below.
https://github.com/sinclairzx81/typebox?tab=readme-ov-file#benchmark-validate
If you want the best possible validation performance for your environment, you can implement a custom compile function that will fallback to Value.Check in environments where Eval is restricted.
// -----------------------------------------------------------
// SafeCompile: Tries to compile with Eval, falls back to
// dynamic checking on fail.
// -----------------------------------------------------------
function SafeCompile<Type extends TSchema>(type: Type, references: TSchema[] = []): TypeCheck<Type> {
try {
// Try to compile using Eval (this will throw on Cloudflare)
return TypeCompiler.Compile(type)
} catch {
// Use Dynamic Checking when Eval unavailable
return new TypeCheck(type, references, (value) => Value.Check(type, references, value), '')
}
}
// ...
const T = Type.Object({
x: Type.Number(),
y: Type.Number(),
z: Type.Number()
})
const R = SafeCompile(T).Check({ x: 1, y: 2, z: 3 })
So yes, it's possible to use TypeBox on Cloudflare, but unfortunately, the Content Security Policy for Eval means that applications running on there have to pay a validation performance cost. TypeBox does offer a third code generation (AOT) option with TypeCompiler.Code
where you would generate the validation logic and write that to disk as a module. This can be an option for performance critical applications on Cloudflare, but would only be required if your application needs to handle 100's of millions of validations per second (most applications don't need this).
Information on Code Generation can be found on the TypeCompiler documentation in the readme.
https://github.com/sinclairzx81/typebox?tab=readme-ov-file#typecompiler
Hope this helps S
@foreseaz Heya,
Will close up this issue for now, but give Value.Check a try and see how you go. If you run into any problems, feel free to ping on this thread.
Cheers S
Thanks for the prompt response regarding this issue! I’ve run some benchmarks comparing TypeBox's Value validation with other candidates.
TypeBox Compiled Validation x 143,038,827 ops/sec ±1.38% (98 runs sampled)
TypeBox Value(un-optimized) Validation x 1,979,232 ops/sec ±6.19% (82 runs sampled) (CF Worker compatible)
Ajv Validation x 27,530,079 ops/sec ±1.49% (91 runs sampled)
Superstruct Validation x 166,232 ops/sec ±3.96% (90 runs sampled)
Yup Validation x 111,987 ops/sec ±3.52% (88 runs sampled) (CF Worker compatible)
Zod Validation x 875,983 ops/sec ±0.70% (94 runs sampled)
ArkType Validation x 52,927,504 ops/sec ±3.80% (89 runs sampled) (CF Worker compatible)
While the compiled version of TypeBox delivers excellent performance, the Value validation performance was not quite sufficient. Looking forward to potentially supporting Workers with the compiled validation in the future, like arktype
does.
@foreseaz That's fine
While the compiled version of TypeBox delivers excellent performance, the Value validation performance was not quite sufficient. Looking forward to potentially supporting Workers with the compiled validation in the future, like arktype does.
There is no way to support the compiled versions on CF workers because of the Content Security Policy for Eval. This is going to be true for all validators (unless there is something I am missing)
Just be mindful that Ajv and ArkType will most likely be falling back to dynamic checking internally (as with the SafeCompile function above). If performance is a concern, you will want to run these benchmarks on the CF worker to be sure.
Good luck! S
@foreseaz Fyi, had to check.
https://github.com/arktypeio/arktype/blob/main/ark/util/functions.ts#L94-L109
/**
* Checks if the environment has Content Security Policy (CSP) enabled,
* preventing JIT-optimized code from being compiled via new Function().
*
* @returns `true` if a function created using new Function() can be
* successfully invoked in the environment, `false` otherwise.
*
* The result is cached for subsequent invocations.
*/
export const envHasCsp = cached((): boolean => {
try {
return new Function("return false")()
} catch {
return true
}
})
TypeBox prefers to make the above explicit (as per SafeCompile) as I find it lends insights into the actual performance. Unfortunately, it's still not possible to get JIT compiled validation on CF Workers. It would be nice if JS runtimes could provide some facilities for safe evaluation of JS code outside the global context. Maybe with Shadow Realm proposal.
The TypeBox library does not currently support execution within the Cloudflare Worker environment. This is due to the use of the Function() constructor, which is restricted in Cloudflare Workers. The restriction is documented in the Cloudflare Workers JavaScript standards, which state that code generation from strings (e.g., Function(), eval()) is not allowed due to security reasons.
When attempting to use TypeBox in a Worker, it throws the following error:
Relevant Source Code The issue originates from the invocation of Function() in the following line of the compiler.ts file: https://github.com/sinclairzx81/typebox/blob/b05c59c13bc95679a5ec1c202e7007e2aa127f1a/src/compiler/compiler.ts#L631
Is there any plan to support environments like Cloudflare Workers in the future? Would it be possible to replace or refactor the usage of Function() to ensure compatibility?