I am trying to generate pre compile standalone code like so:
https://ajv.js.org/standalone.html
I have an AJV instance created like so:
const ajv = require("ajv");
const add_formats = require("ajv-formats");
const add_errors = require("ajv-errors");
const ajv_inst = new ajv({
code: { source: true }, // needed for standalone pre compiled scripts
allErrors: true,
$data: true,
});
add_errors(add_formats(ajv_inst));
However, I have custom keywords defined like so:
ajv_inst.addKeyword({
keyword: "custom_array",
validate: (schema, data) => {
try {
const unique_name = data.map((tar) => {
return tar.name.toLowerCase().replaceAll(/s+/g, "");
});
const unique_id = data.map((tar) => {
return tar._id;
});
return (
new Set(unique_name).size === data.length &&
new Set(unique_id).size === data.length
);
} catch (err) {
return false;
}
},
metaSchema: {
enum: [true],
},
});
In order to generate the standalone code with custom keywords, I think the keyword needs to be defined with a code generator function instead of the validate
like so:
code(cxt: KeywordCxt) {
const {data, schema} = cxt
const op = schema ? _`!==` : _`===`
cxt.fail(_`${data} %2 ${op} 0`) // ... the only code change needed is to use `cxt.fail$data` here
},
https://ajv.js.org/keywords.html#define-keyword-with-validate-function
questions:
- Given that I already have the
validate
property defined, is there a way to generate the pre compiled standalone code with the function defined as is in thevalidate
property? - If not, is there an easy or automated way to convert my
validate
function into the required code-gen code?
2
Answers
Unfortunately, the validate function alone cannot be directly used for generating precompiled standalone code with AJV. This is because AJV requires custom keywords to define their behavior in terms of JavaScript code generation when creating standalone precompiled validators. The validate function is executed at runtime, while the code property is used during the compilation process to generate code.
1. Is there a way to use the validate property for precompiled standalone code?
No, AJV’s standalone generation mechanism requires the code property to define how the keyword translates to JavaScript code. The validate function cannot be directly used for this purpose.
2. How to convert the validate function into code for standalone generation?
To translate your validate function into a code generator function, you can:
Here’s an example of how you might achieve this:
Your Current Validate Function
Converted Code Generator Function
Here’s a translation of this into the code generator:
Explanation
Benefits of Using code for Standalone
The generated validator will include your custom keyword logic directly in the compiled output.
This approach avoids runtime dependencies and ensures efficient execution.
Automating Conversion
While there isn’t a direct tool to automate the conversion from a validate function to a code function, you can:
For simple keywords, the conversion is often straightforward. However, for complex logic, it may require manual adjustments as seen above.
For your first question: No, you cannot directly use the
validate
property for standalone code generation. Thevalidate
function runs at runtime which conflicts with the purpose of standalone code that needs to be generated at compile time.For converting your
custom_array
validate function to code generation, here’s how we can do it:Here’s a more complete example showing how to use this with standalone code generation:
Key points to remember:
The
code
function needs to generate JavaScript code rather than execute validation logic directly.Use the
cxt.gen
methods to generate variables and control flow.Use the tagged template literal helper
_
from Ajv to safely generate code expressions.Error handling can be done using
cxt.fail()
which will generate appropriate error reporting code.Type information (
type: "array"
) helps Ajv optimize the generated code.The main challenge in converting from
validate
tocode
is thinking in terms of code generation rather than runtime execution. You need to generate code that will perform the validation when executed, rather than performing the validation directly.