strict mode: unknown keyword: "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!
@riker09, do you have insight? I based my code off your example here
Sorry, I'm afraid I will not be able to help you. I'm just a consumer of this library as well and have moved on to another project in the meantime.
Your code seems correct to me, though. So maybe it is something with the version?
@bestickley I believe you could just put "format" inside "metadata" member - JTD only allows extensions in this way, as they are no-op in this way.
If this does not work, please put pure JavaScript example in runkit so I can investigate.
Edit: ignore that, it's already inside... not sure, it does look correct. Please make a runnable example in runkit. Could be a version problem indeed...
@riker09, no problem. @epoberezkin, thank you for your response. Here is the runkit example: https://runkit.com/bestickley/61eb0e06ce01ed0008bacdfe
ajv-formats does not seem to be supported by ajv-jtd, only ajv-keywords, also ajv-formats is not mentioned in docs (https://ajv.js.org/json-type-definition.html#extending-jtd)
Also according to docs: While it is ok to put some human readable information in metadata member, it is recommended not to add any validation logic there (even if it is supported by Ajv).
I decided to add regexp keyword from ajv-keywords, since I don't need anything else additionally to what jtd already supports.
import Ajv from "ajv/dist/jtd";
import addKeyword from "ajv-keywords";
export const ajv = new Ajv({
parseDate: true,
});
ajv.addKeyword("description");
addKeyword(ajv, ["regexp"]);