ajv-validator / ajv-formats Goto Github PK
View Code? Open in Web Editor NEWJSON Schema format validation for Ajv v8+
Home Page: https://ajv.js.org
License: MIT License
JSON Schema format validation for Ajv v8+
Home Page: https://ajv.js.org
License: MIT License
Following the doc and simply trying to validate with the date
format, I receive the following error:
src/scripts/simple-validation.ts:5:1 - error TS2349: This expression is not callable.
Type 'FormatsPlugin' has no call signatures.
5 addFormats(ajv);
~~~~~~~~~~
The source file is here:
import Ajv from 'ajv';
import addFormats from 'ajv-formats';
const ajv = new Ajv();
addFormats(ajv);
const schema = {
type: 'string',
format: 'date',
};
const validate = ajv.compile(schema);
const isValid = validate('1-1-1');
console.log(isValid);
According to ajv-formats documentation, "date-time" format specify that time-zone is mandatory. Unfortunately since full validation mode format has been added, it seems that time-zone is not mandatory anymore:
import ajvFormats from "ajv-formats"
const dateWithoutTimeZone = '2022-07-06T13:12:43';
const dateWithTimeZone = '2022-07-06T13:12:43Z';
// validation with new full format mode does not work as expected
console.log(ajvFormats.get("date-time").validate(dateWithoutTimeZone)) // true => should return false
console.log(ajvFormats.get("date-time").validate(dateWithTimeZone)) // true => ok
// validation with fast format mode is ok
console.log(new RegExp(ajvFormats.get("date-time", "fast").validate).test(dateWithoutTimeZone)) // false => ok
console.log(new RegExp(ajvFormats.get("date-time", "fast").validate).test(dateWithTimeZone)) // true => ok
Using the example code results in errors and simply does not work.
const Ajv = require("ajv")
const addFormats = require("ajv-formats")
const ajv = new Ajv()
addFormats(ajv)
The above code, from the documentation, does not work.
Both const ajv = new Ajv()
and addFormats(ajv)
produce an error "This expression is not constructable."
Package versions:
"ajv": "^8.2.0",
"ajv-formats": "^2.0.2"
NB - I can get rid of one error, from const ajv = new Ajv()
by add .default
to the require statement, but addFormats(ajv)
still errors.
This is my schema (with unrelated properties removed):
export const employeeSchema = {
items: {
properties: {
launchDate: {
errorMessage: {
format: 'must be a date in YYYY-MM-DD format (e.g. _1973-05-11_)',
type: 'required, and must be a date in YYYY-MM-DD format (e.g. _1973-05-11_)',
},
examples: ['1973-05-11'],
format: 'date',
type: 'string',
},
},
required: [
'launchDate',
],
type: 'object',
},
minItems: 1,
type: 'array',
};
As-is, everything works and validates correctly. But when I add formatMinimum
to launchDate
:
export const employeeSchema = {
items: {
properties: {
launchDate: {
errorMessage: {
format: 'must be a date in YYYY-MM-DD format (e.g. _1973-05-11_)',
type: 'required, and must be a date in YYYY-MM-DD format (e.g. _1973-05-11_)',
},
examples: ['1973-05-11'],
format: 'date',
formatMinimum: '2022-03-30',
type: 'string',
},
},
required: [
'launchDate',
],
type: 'object',
},
minItems: 1,
type: 'array',
};
… I get the following console error:
Uncaught TypeError: {(intermediate value)(intermediate value)(intermediate value)(intermediate value)}.compare is not a function
at validate14 (eval at compileSchema (index.jss:89:1), <anonymous>:3:2858)
at index.jss:149:1
at mountMemo (react-dom.development.jss:15846:1)
at Object.useMemo (react-dom.development.jss:16219:1)
at useMemo (react.development.jss:1532:1)
at UseMemo (whyDidYouRender.jss:1461:1)
at ModalImportReview (index.jss:132:1)
at renderWithHooks (react-dom.development.jss:14985:1)
at mountIndeterminateComponent (react-dom.development.jss:17811:1)
at beginWork (react-dom.development.jss:19049:1)
RunKit example: https://runkit.com/brandondurham/compare-is-not-a-function-when-using-formatminimum-with-date-format
Hello, I'm using [email protected] and [email protected] in an AWS Lambda (Node.js 14) and I'm getting this error:
{
"errorType": "Error",
"errorMessage": "strict mode: unknown keyword: \"format\"",
"stack": [
"Error: strict mode: unknown keyword: \"format\"",
" at null.Gq (/node_modules/.pnpm/[email protected]/node_modules/ajv/lib/compile/util.ts:211:28)",
" at null.$q (/node_modules/.pnpm/[email protected]/node_modules/ajv/lib/compile/util.ts:27:22)",
" at null.Wfe (/node_modules/.pnpm/[email protected]/node_modules/ajv/lib/compile/util.ts:17:3)",
" at Object.code (/node_modules/.pnpm/[email protected]/node_modules/ajv/lib/vocabularies/jtd/metadata.ts:11:9)",
" at null.UN (/node_modules/.pnpm/[email protected]/node_modules/ajv/lib/compile/validate/index.ts:523:9)",
" at null.<anonymous> (/node_modules/.pnpm/[email protected]/node_modules/ajv/lib/compile/validate/index.ts:265:9)",
" at Nq.code (/node_modules/.pnpm/[email protected]/node_modules/ajv/lib/compile/codegen/index.ts:525:33)",
" at Nq.block (/node_modules/.pnpm/[email protected]/node_modules/ajv/lib/compile/codegen/index.ts:680:20)",
" at null.RN (/node_modules/.pnpm/[email protected]/node_modules/ajv/lib/compile/validate/index.ts:262:7)",
" at null.v (/node_modules/.pnpm/[email protected]/node_modules/ajv/lib/compile/validate/index.ts:248:7)"
]
}
Here is the function:
import {
CognitoIdentityProviderClient,
AdminCreateUserCommand,
AdminAddUserToGroupCommand,
} from "@aws-sdk/client-cognito-identity-provider";
import { AppSyncResolverEvent } from "aws-lambda";
import Ajv, { JTDDataType } from "ajv/dist/jtd";
import format from "ajv/dist/vocabularies/format/format";
import addFormats from "ajv-formats";
import { transformUser } from "./user";
import { groupNames } from "./group";
// validation
const ajv = new Ajv();
ajv.addKeyword(format);
addFormats(ajv, ["email"]);
const schema = {
properties: {
email: { type: "string", metadata: { format: "email" } },
family_name: { type: "string" },
given_name: { type: "string" },
groups: {
elements: { enum: groupNames },
},
username: { type: "string" },
},
} as const;
const validate = ajv.compile(schema);
// params
interface CreateUserGqlArgs {
input: JTDDataType<typeof schema>;
}
interface CreateUserParams {
cognitoClient: CognitoIdentityProviderClient;
event: AppSyncResolverEvent<CreateUserGqlArgs>;
userPoolId: string;
}
export async function createUser(props: CreateUserParams): Promise<unknown> {
const { cognitoClient, event, userPoolId } = props;
if (!validate(event.arguments.input)) {
throw new Error(validate.errors?.toString());
}
const { username, groups, ...inputUserAttributes } = event.arguments.input;
const userAttributes = Object.entries(inputUserAttributes).map(([k, v]) => ({
Name: k,
Value: v,
}));
const res = await cognitoClient.send(
new AdminCreateUserCommand({
UserPoolId: userPoolId,
Username: username,
UserAttributes: userAttributes,
})
);
await Promise.all(
groups.map((g) =>
cognitoClient.send(
new AdminAddUserToGroupCommand({
GroupName: g,
Username: username,
UserPoolId: userPoolId,
})
)
)
);
if (!res.User) throw new Error("Error while creating user");
const user = transformUser(res.User);
return user;
}
Does anyone know what's going on? Thank you!
Hi!, I'm trying to use formatExclusiveMinimum
with $data to compare two date fields and validate that endDate
> startDate
, but I'm having trouble tracking down an error.
package.json ajv
version snippet:
"ajv": "8.6.0",
"ajv-formats": "^2.1.0",
"ajv-keywords": "^5.0.0",
"ajv-merge-patch": "4.1.0"
ajv
setup:
parameterAjv = new Ajv({
schemas,
strict: 'log',
$data: true,
removeAdditional: 'all',
useDefaults: false,
code: {
lines: true,
optimize: false
}
})
require('ajv-merge-patch/keywords/merge')(parameterAjv)
const addFormats = require('ajv-formats')
addFormats(parameterAjv, {
formats: ['date', 'time', 'date-time', 'uri', 'regex'],
keywords: true
})
schema = parameterAjv.getSchema(schemaPath)
An example from my schema:
{
"query": {
"type": "object",
"properties": {
"propertyId": {
"description": "The property you are querying",
"$ref": "Common.schema.json#/definitions/propertyId"
},
"startDate": {
"description": "The date check-in availability. In the property's local timezone.",
"type": "string",
"format": "date"
},
"endDate": {
"description": "The date check-out availability. In the property's local timezone.",
"type": "string",
"format": "date",
"formatExclusiveMinimum": {
"$data": "1/startDate"
}
}
},
"required": ["startDate", "endDate"]
}
}
When I pass in any combination of valid date strings for startDate
and endDate
I get the following error:
{
"instancePath": "/query/endDate",
"schemaPath": "#/properties/query/properties/endDate/formatExclusiveMinimum",
"keyword": "formatExclusiveMinimum",
"params": {
"_items": [
"{comparison: ",
"\">\"",
", limit: ",
"{\"str\":\"vSchema0\"}",
"}"
]
},
"message": {
"_items": ["\"should be > \"", "+", "{\"str\":\"vSchema0\"}"]
}
}
Is this error format correct?
I've been trying to track this down in the code generated by ajv
to validate this field and I'm having trouble understanding one of the condition checks.
Here is a snippet of the generated code that deals with the endDate
comparison to startDate
:
if (valid1) {
if (data0.endDate !== undefined) {
let data8 = data0.endDate;
const _errs23 = errors;
if (errors === _errs23) {
if (errors === _errs23) {
if (typeof data8 === "string") {
if (!formats6.validate(data8)) {
validate242.errors = [
{
instancePath:
instancePath + "/query/endDate",
schemaPath:
"#/properties/query/properties/endDate/format",
keyword: "format",
params: { format: "date" },
message:
'must match format "' +
"date" +
'"',
},
];
return false;
} else {
const vSchema0 =
data0 && data0.startDate;
if (
vSchema0 !== undefined &&
(typeof vSchema0 !== "string" || { // Everything makes sense up until here
_items: [
"",
'{"str":"formats6","prefix":"formats","value":{"key":"date","ref":{},"code":{"_items":["","{\\"_items\\":[\\"require(\\\\\\"ajv-formats/dist/formats\\\\\\").\\",{\\"str\\":\\"fullFormats\\"},\\"\\"]}","",".date",""]}},"scopePath":{"_items":[".",{"str":"formats"},"[",1,"]"]}}',
".compare(",
'{"str":"data8"}',
", ",
'{"str":"vSchema0"}',
") ",
"<=",
" 0",
],
})
) {
validate242.errors = [
{
instancePath:
instancePath + "/query/endDate",
schemaPath:
"#/properties/query/properties/endDate/formatExclusiveMinimum",
keyword: "formatExclusiveMinimum",
params: {
_items: [
"{comparison: ",
'">"',
", limit: ",
'{"str":"vSchema0"}',
"}",
],
},
message: {
_items: [
'"should be > "',
"+",
'{"str":"vSchema0"}',
],
},
},
];
return false;
}
}
} else {
validate242.errors = [
{
instancePath:
instancePath + "/query/endDate",
schemaPath:
"#/properties/query/properties/endDate/type",
keyword: "type",
params: { type: "string" },
message: "must be string",
},
];
return false;
}
}
}
var valid1 = _errs23 === errors;
} else {
var valid1 = true;
}
Can anyone point me in the right direction? I've been back and forth over the configuration of ajv
with ajv-formats
but can't seem to make any progress.
Requested npm to revert, the command to undeprecate does not seem to work.
Currently the highest ajv version we can use is 8.6.3
any higher version breaks the addFormats
that do not accept the Ajv
instance anymore.
Do you plan an upgrade to support newest versions of AJV?
According to the Ajv documentation:
some formats that ajv-formats package implements use regular expressions that can be vulnerable to ReDoS attack
Having you considered using the re2
package to eliminate this risk? According to its documentation:
RE2 was designed and implemented with an explicit goal of being able to handle regular expressions from untrusted users without risk. One of its primary guarantees is that the match time is linear in the length of the input string.
Hi, I'm trying to use the "iso-date-time" format with [email protected]
and [email protected]
but it's throwing the following error:
Error: unknown format "iso-date-time" ignored in schema at path "#/properties/publishDate"
I'm using Node v16.13.1
Here's my code:
import Ajv from 'ajv';
import addFormats from 'ajv-formats';
const ajv = new Ajv();
addFormats(ajv);
const bookSchema = {
type: 'object',
properties: {
title: { type: 'string' },
numOfPages: { type: 'integer' },
author: { type: 'string' },
price: { type: 'number' },
publishDate: { type: 'string', format: 'iso-date-time' },
},
required: ['title', 'numOfPages', 'author', 'price'],
additionalProperties: false,
};
const validateBook = ajv.compile(bookSchema);
export default validateBook;
please,i need format: int 32 , bug ajv don't include
the project is being built on my machine successfully, but an error occurs in Github
when trying to build the project:
ERROR in ./src/server/app/create-app.ts 6:41-63
Module not found: Error: Can't resolve 'ajv-formats' in '/home/runner/work/project/src/server/app'
set up dependencies in Github workflow
yarn install --frozen-lockfile
package.jso has the package in dependencies
{
"dependencies": {
...
"ajv": "8.10.0",
"ajv-formats": "^2.1.1",
...
}
}
module imports the package
import Ajv from 'ajv';
import addFormats from 'ajv-formats';
const ajv = new Ajv({
strict: true,
coerceTypes: false,
formats: {
semver: '^(0|[1-9][0-9]{0,5})\\.(0|[1-9][0-9]{0,5})\\.(0|[1-9][0-9]{0,5})$',
},
});
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
// eslint-disable-next-line @typescript-eslint/no-unsafe-call
addFormats(ajv);
...
In my React Native app the metro bundler fails with
error: node_modules/ajv-formats/dist/formats.js: /Users/mtroskot/Projects/app/node_modules/ajv-formats/dist/formats.js: invalid Unicode escape .
The issue is in the url regex.
url: /^(?:https?|ftp)://(?:\S+(?::\S*)?@)?(?:(?!(?:10|127)(?:.\d{1,3}){3})(?!(?:169.254|192.168)(?:.\d{1,3}){2})(?!172.(?:1[6-9]|2\d|3[0-1])(?:.\d{1,3}){2})(?:[1-9]\d?|1\d\d|2[01]\d|22[0-3])(?:.(?:1?\d{1,2}|2[0-4]\d|25[0-5])){2}(?:.(?:[1-9]\d?|1\d\d|2[0-4]\d|25[0-4]))|(?:(?:[a-z0-9\u{00a1}-\u{ffff}]+-)[a-z0-9\u{00a1}-\u{ffff}]+)(?:.(?:[a-z0-9\u{00a1}-\u{ffff}]+-)[a-z0-9\u{00a1}-\u{ffff}]+)(?:.(?:[a-z\u{00a1}-\u{ffff}]{2,})))(?::\d{2,5})?(?:/[^\s])?$/iu,
Hi, @epoberezkin thanks for this package it is very useful.
I found that the version that was released yesterday v2.0.2
does not include new Formats like binary
.
This is NPM README (Without binary format)
And this is the code I found after downloading this version in my node_modules
.
I think this PR was not included in the release for any reason in the release to npm 😅
I'm using the minified version of ajv7 in Javascript, and i want to support other formats, which are in the ajv-formats package.
I want to import ajv-formats, which is written in typescript, to my Javascript project.
Is there a possibility to make it ?
Does a minified version of ajv-formats exist ?
Well. safe-Regex complains that the regex for url is considered "unsafe".
How can we implement it "safe" without deep digging in the regex?
something like this?
(url) => {
try {
const parsedUrl = new URL(url).toString();
return url === parsedUrl;
} catch (e) {
return false;
}
}
I'm using the minified version of ajv7 in Javascript, and i want to support other formats, which are in the ajv-formats package.
I want to import ajv-formats, which is written in typescript, to my Javascript project.
Is there a possibility to make it ? Does a minified version of ajv-formats exist ?
This valid url wss://arbitrator.net/api
does not pass url
format validation.
Hi,
could you please expose the formats in index.ts? Currently I want to wrap all the formatters for typescript typeguards, but i cant do a
import { fastFormats } from "./ajv-formats";
The following schema won't work:
createdAt: {
type: 'string',
format: 'iso-date-time',
default: ''
}
as the default value will not pass validation if provided directly.
Are there any plans to support empty strings as the null value? it tends to keep the Javascript engine optimized more often and reduces the need to do a fuzzy falsy check.
https://stackblitz.com/edit/vitejs-vite-ggyjmk?file=src/main.ts
/^()|([isodate])$/
Hello.
The readme lists the supported formats, including:
These are specified in OpenAPI specification, but not really supported by ajv-formats. Tested with version 2.0.2.
Thanks.
The regex for email format used by the format validation is:
/^[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?$/i
This doesn't handle internationalized email addresses, e.g. those with unicode characters in the user name.
Hi, there is the idn-hostname
format missing.
Relevant conversation starts here: #15 (comment)
I'm using @middy/validator for which I add the plugin with an empty object {}
.
Unfortunately I get an error: TypeError: Cannot read property 'code' of undefined
Pointing to line https://github.com/ajv-validator/ajv-formats/blob/master/src/index.ts#L55
Please help!
All examples I see use JSONSchema.
This is the shape I want to validate:
interface MyData {
name: string;
email: string;
}
import Ajv, { JTDDataType } from 'ajv/dist/jtd';
import addFormats from 'ajv-formats';
const ajv = new Ajv();
addFormats(ajv, ['email']);
const schema = {
properties: {
name: { type: 'string' },
email: { type: 'string', format: 'email' }
},
} as const;
const validate = ajv.compile<MyData>(schema);
const data: MyData = {
name: 'John Doe',
email: '[email protected]',
};
if (validate(data)) {
// success!
}
However, i cannot get it to work. I'm using TypeScript v4.3.4.
The error I get is:
Error: schema is invalid: data/properties must NOT have additional properties, data must have property 'ref', data must have property 'type', data must have property 'enum', data must have property 'elements', data/properties/email/type must NOT have additional properties, data/properties/email must have property 'ref', data/properties/email/type must be equal to one of the allowed values, data/properties/email must have property 'enum', data/properties/email must have property 'elements', data/properties/email must have property 'properties', data/properties/email must have property 'optionalProperties', data/properties/email must have property 'discriminator', data/properties/email must have property 'values', data/properties/email must match a schema in union, data/optionalProperties/age/type must NOT have additional properties, data/optionalProperties/age must have property 'ref', data/optionalProperties/age/type must be equal to one of the allowed values, data/optionalProperties/age must have property 'enum', data/optionalProperties/age must have property 'elements', data/optionalProperties/age must have property 'properties', data/optionalProperties/age must have property 'optionalProperties', data/optionalProperties/age must have property 'discriminator', data/optionalProperties/age must have property 'values', data/optionalProperties/age must match a schema in union, data must have property 'discriminator', data must have property 'values', data must match a schema in union
Line 55 in 4dd6544
[error] TypeError: Cannot read properties of undefined (reading 'code')
at addFormats (D:\repos\GPD Analys\GPDAnalys\Presentation\GPD.Web.UI.V2\node_modules\ajv-formats\dist\index.js:30:26)
at formatsPlugin (D:\repos\GPD Analys\GPDAnalys\Presentation\GPD.Web.UI.V2\node_modules\ajv-formats\dist\index.js:15:5)
at new CoreSchemaRegistry (D:\repos\GPD Analys\GPDAnalys\Presentation\GPD.Web.UI.V2\node_modules@angular-devkit\core\src\json\schema\registry.js:92:35)
at runCommand (D:\repos\GPD Analys\GPDAnalys\Presentation\GPD.Web.UI.V2\node_modules@angular\cli\models\command-runner.js:114:22)
at default_1 (D:\repos\GPD Analys\GPDAnalys\Presentation\GPD.Web.UI.V2\node_modules@angular\cli\lib\cli\index.js:70:69)
Project builds when adding a ?.
ajv.opts?.code.formats ??= _require("ajv-formats/dist/formats").${exportName}
"resolutions": { "path-parse": "1.0.7", "ws": "7.5.6", "ajv": "6.12.6", "ajv-keywords": "3.5.2" }, "private": true, "dependencies": { "@angular/animations": "~13.1.0", "@angular/cdk": "^13.1.0", "@angular/common": "~13.1.0", "@angular/compiler": "~13.1.0", "@angular/core": "~13.1.0", "@angular/flex-layout": "13.0.0-beta.36", "@angular/forms": "~13.1.0", "@angular/localize": "^13.1.0", "@angular/platform-browser": "~13.1.0", "@angular/platform-browser-dynamic": "~13.1.0", "@angular/router": "~13.1.0", "@fortawesome/angular-fontawesome": "^0.10.1", "@fortawesome/fontawesome-svg-core": "^1.2.36", "@fortawesome/free-regular-svg-icons": "^5.15.4", "@fortawesome/free-solid-svg-icons": "^5.15.4", "@ng-bootstrap/ng-bootstrap": "^10.0.0", "bootstrap": "^4.6.0", "dayjs": "^1.10.4", "details-polyfill": "^1.2.0", "font-awesome": "^4.7.0", "geojson": "^0.5.0", "moment": "^2.29.1", "ng2-date-picker": "^11.0.0", "ngx-moment": "^5.0.0", "ol": "6.5.0", "proj4": "^2.7.2", "rxjs": "~7.4.0", "tslib": "^2.2.0", "zone.js": "~0.11.4" }, "devDependencies": { "@angular-devkit/build-angular": "~13.1.0", "@angular/cli": "13.1", "@angular/compiler-cli": "^13.1.0", "@angular/language-service": "^13.1.0", "@istanbuljs/nyc-config-typescript": "^1.0.1", "@types/jasmine": "~3.7.4", "@types/jasminewd2": "^2.0.9", "@types/node": "~15.6.0", "ajv": "^8.8.2", "ajv-formats": "^2.1.1", "ajv-keywords": "^5.1.0", "codelyzer": "^6.0.2", "jasmine-core": "~3.7.1", "jasmine-spec-reporter": "~7.0.0", "karma": "~6.3.2", "karma-chrome-launcher": "~3.1.0", "karma-coverage-istanbul-reporter": "~3.0.3", "karma-jasmine": "~4.0.1", "karma-jasmine-html-reporter": "^1.6.0", "nyc": "^15.1.0", "postcss": "8.2.15", "source-map-support": "^0.5.19", "ts-node": "~10.0.0", "tslint": "^6.1.3", "typescript": "4.4.4" },
By scoping formats into fullFormats
and fastFormats
:
import
a format in a single lineAs a breaking change proposal, let's export two modules instead:
formats-fast.js
formats-full.js
This way, when doing code generation, it'd be possible to have a single line import:
import { int32 } from "ajv-formats/dist/formats-full"
Hi,
There is object shorthand syntax in node_modules/ajv-formats/dist/formats.js
.
exports.fullFormats = {
// date: http://tools.ietf.org/html/rfc3339#section-5.6
date,
// date-time: http://tools.ietf.org/html/rfc3339#section-5.6
time,
Can you add compilerOptions: { "target": "es5" }
in tsconfig.json
, please?
Without this I can't use module in IE11.
I have also tried importing node_modules/ajv-formats/src/index.ts
.
But webpack 5 reports an error because of module.exports
are used
module.exports = formatsPlugin
URIs should be allowed to have characters outside of a-zA-z, e.g. ñ
and other non-ascii characters.
idn-email
is not supported.
Environment:
schema: 2020-12
node.JS: v12.18.2
ajv: 8.6.2
ajv-formats: 2.1.0
What version of Ajv are you using? Does the issue happen if you use the latest version?
8.11.0
(currently latest)
Ajv options object
import Ajv from "ajv"
import standaloneCode from "ajv/dist/standalone"
import ajvFormats from "ajv-formats"
const ajv = new Ajv({
code: { esm: true, source: true },
})
ajvFormats(ajv)
const output = standaloneCode(ajv, validate)
JSON Schema
{
"type": "object",
"properties": {
"example": { "type": "number", "format": "int32" }
},
"$schema": "http://json-schema.org/draft-07/schema"
}
Output
// ...
const formats0 = require(`ajv-formats/dist/formats`).fullFormats.int32
// ...
What results did you expect?
// this is kinda awkward, but that's the only way to make it work as of now in pure ESM w/o post-processing
import { fullFormats } from "ajv-formats/dist/formats"
const { int32 } = fullFormats
Are you going to resolve the issue?
I've tried to look into it, but it seems to be coupled with many ajv packages, so please let me know your proposal.
I believe the resolution should be done in multiple steps:
import
should be used instead of require
(this issue)ajv-formats
should export every function separately, not scoped within fullFormats
, fastFormats
, etc. (#65)Hello, I'm trying to compile a typescript project using Webpack 5, but I'm running in the following error:
TS2345: Argument of type 'import(".../node_modules/ajv/dist/ajv").default' is not assignable to parameter of type 'import(".../node_modules/ajv-formats/node_modules/ajv/dist/core").default'.
Types of property 'opts' are incompatible.
Type 'import(".../node_modules/ajv/dist/core").InstanceOptions' is not assignable to type 'import(".../node_modules/ajv-formats/node_modules/ajv/dist/core").InstanceOptions'.
Type 'InstanceOptions' is not assignable to type 'CurrentOptions'.
Types of property 'keywords' are incompatible.
I'm using ajv v7.2.1 and ajv-formats v1.5.1 with the default code example:
import Ajv from "ajv"
import addFormats from "ajv-formats"
const ajv = new Ajv()
addFormats(ajv)
If I remove the line addFormats(ajv)
it compiles fine.
Here is my tsconfig.js
{
"compilerOptions": {
"allowSyntheticDefaultImports": true,
"jsx": "react",
"lib": [
"dom",
"ES2019"
],
"module": "commonjs",
"target": "ES2019",
"allowJs": true,
"sourceMap": true,
"moduleResolution": "node",
"skipLibCheck": true,
"resolveJsonModule": true,
"experimentalDecorators": true,
"noEmitOnError": true,
"removeComments": true,
"noUnusedParameters": true,
"noImplicitReturns": true,
"importHelpers": true,
"noEmitHelpers": true,
"forceConsistentCasingInFileNames": true,
"esModuleInterop": true,
"strict": true
}
}
Any help would be much appreciated
hi,
The current format for uri-reference declares a fragment like #/paths/~1{id}/get/responses/404
invalid.
The fragment is considered valid if the curly braces are percent encoded as %7B and %7D.
I use AJV to validate openApi specs, and out of about 2300 real world specs about 7 fail because they have uri-reference with curly braces.
RFC 3986 is not very strict on what to encode and what not.
The What-wg url spec is more formal and states:
The C0 control percent-encode set are the C0 controls and all code points greater than U+007E (~).
The fragment percent-encode set is the C0 control percent-encode set and U+0020 SPACE, U+0022 ("), U+003C (<), U+003E (>), and U+0060 (`).
This would allow curly braces as valid.
Should AJV-formats follow the What-wg spec?
Kind regards,
Hans
Thank you for the great work you do. Is there already a plan, when you release 3.0.0 as stable?
Howdy;
I'm assuming ignorance on my part, as I haven't dug into this far enough, but according to these lines: https://github.com/ajv-validator/ajv-formats/blob/master/src/formats.ts#L79-L82
// C-type float
float: {type: "number", validate: validateNumber},
// C-type double
double: {type: "number", validate: validateNumber},
Both float
and double
depend on the validateNumber()
function which is here: https://github.com/ajv-validator/ajv-formats/blob/master/src/formats.ts#L206-L208
function validateNumber(): boolean {
return true
}
Is this actually validating anything? Is something else responsible for validation and this is just a pass-through of some sort? Again I apologize if I'm missing something basic.
Thanks!
Hi,
Thanks for all the work on AJV !
I'm the author of fastify-openapi-glue and I have created formats for
as defined at https://swagger.io/docs/specification/data-models/data-types/
I presume that more AJV users will be using AJV for the parsing of openapi specs, would you be interested in a PR to add these formats to ajv-formats ?
Kind regards,
Hans
I'd like to create my custom regex (formats) and consume them as email
for example. Is that possible or how can I extend the functionality ?
This url http://localhost/
doesn;t pass format: url
validation.
Are you sure, that this is correct?
const Ajv = require('ajv/dist/2019').default;
const AjvFormats = require('ajv-formats');
// Instance
const ajv = new Ajv();
AjvFormats(ajv);
const schema = {
type: 'string',
format: 'date-time',
formatMinimum: '2020-01-01T00:00:00.000Z'
};
const validate = ajv.compile(schema);
console.log(validate('2020-01-01T00:00:00.000Z')); // Throws TypeError
// Works fine without formatMinimum
const schema2 = {
type: 'string',
format: 'date-time'
};
const validate2 = ajv.compile(schema2);
console.log(validate2('2020-01-01T00:00:00.000Z'));
Cannot read properties of undefined (reading 'code')
TypeError: Cannot read properties of undefined (reading 'code')
at addFormats (/home/ettinger/src/avenasea.com/avenasea-ui/node_modules/ajv-formats/dist/index.js:30:26)
at Proxy.formatsPlugin (/home/ettinger/src/avenasea.com/avenasea-ui/node_modules/ajv-formats/dist/index.js:15:5)
at [email protected]:8:12
import Ajv from 'ajv';
import addFormats from 'ajv-formats';
const ajv = new Ajv({ allErrors: true, strictSchema: false });
addFormats(ajv);
I'm using Ajv 8.10.0, latest version as of this writing.
const Ajv = require("ajv")
const addFormats = require('ajv-formats')
const ajv = new Ajv()
addFormats(ajv)
const validate = ajv.compile({
type: "string",
format: "date-time"
})
console.log(validate('2018-01-26T00:18:49.000')) // true
An RFC3339 date time string with no timezone is valid, but since Ajv website says the time-zone is mandatory for the "date-time" format, I expected the code above to raise an error. It outputs true.
What am I missing? Is it expected behavior? If so, maybe the website should be updated.
TypeScript projects that use ajv
and ajv-formats
may have compilation errors after every upgrade. This is because a different version of ajv
is installed under node_modules/ajv-formats/node_modules
, the only way to solve this problem is to add ajv
to the peer dependency of ajv-formats
.
It would be nice to also have ISBN-10 and ISBN-13 as a formatting option. Please see https://www.oreilly.com/library/view/regular-expressions-cookbook/9781449327453/ch04s13.html
According to the JSON Schema Validation spec, section 7.3.1 and ajv-formats' documentation, the date-time
format should validate a string against the date-time
production of RFC 3339, section 5.6.
This production requires the date and time components to be separated by "T"
or "t"
.
The validation regex used in ajv-formats 2.1.1 however also accepts strings like "2023-01-22 11:11:11.123"
with a whitespace character separating the date and time components (note the [t\s]
portion):
/^\d\d\d\d-[0-1]\d-[0-3]\d[t\s](?:[0-2]\d:[0-5]\d:[0-5]\d|23:59:60)(?:\.\d+)?(?:z|[+-]\d\d(?::?\d\d)?)$/i
This issue will be addressed in version 3. I am posting this issue for troubleshooting/documentation.
A workaround for ajv-formats 2.1.1 is to add a pattern()
to the schema, e.g. using a slight variation of the regular expression used in ajv-formats 3:
S.string().format('date-time').pattern(/^\d\d\d\d-[0-1]\d-[0-3]\d[tT](?:[0-2]\d:[0-5]\d:[0-5]\d|23:59:60)(?:\.\d+)?(?:[zZ]|[+-]\d\d(?::?\d\d)?)$/)
I have a typescript project and am following instructions to add "date-time" as follows:
let ajv = new Ajv({ allErrors: true});
addFormats(ajv, ["date-time"]);
but getting the following error for "ajv", the first argument to addFormats:
Type 'Ajv' is missing the following properties from type 'Ajv': opts, logger, scope, schemas, and 17 more.
My tsconfig is as follows:
{
"compilerOptions": {
"module": "CommonJS",
"target": "ES2020",
"noImplicitAny": true,
"preserveConstEnums": true,
"outDir": "./build",
"sourceMap": true,
"esModuleInterop": true,
"resolveJsonModule": true,
"moduleResolution": "node"
},
"exclude": ["node_modules"],
"include": ["my-project/src/**/*", "docs/**/*.json"]
}
The only way I was able to get it working was by initializing ajv as 'any' type, which doesn't seem ideal. Any ideas as to what could be the issue?
In testing, I've run across the following error -
Error: unknown format "iso-date-time" ignored in schema at path "#/properties/schema/properties/created"
I am using the following code:
const Ajv = require("ajv")
var addFormats = require("ajv-formats")
const ajv = new Ajv({allErrors: true})
addFormats(ajv, ["iso-date-time","uri"])
const schema = {
type: "object",
properties: {
foo: {type: "string", "format": "uri"},
bar: {type: "string", "format": "iso-date-time"}
},
additionalProperties: false,
}
const validate = ajv.compile(schema)
test({foo:"https://google.com",bar: "2022-06-11T00:11:59.000Z"})
function test(data) {
const valid = validate(data)
if (valid) console.log("Valid!")
else console.log("Invalid: " + ajv.errorsText(validate.errors))
}
The "format": "uri"
validates correctly, but the "format": "iso-date-time"
throws an error.
Any help appreciated!
It would be useful to have a single IP format that includes both ipv6 and ipv4 in a single format.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.