Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

account for ajv.opts.code.esm option in addFormats #73

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
sethvincent wants to merge 1 commit into ajv-validator:master
base: master
Choose a base branch
Loading
from sethvincent:master

Conversation

Copy link

@sethvincent sethvincent commented Sep 16, 2022

Closes #68

This checks ajv.opts.code.esm and uses a dynamic import if true, otherwise it uses previous behavior.

I'm not sure how best to add a test for this so would be happy to add that based on any suggestions you have.

revidee, o-alexandrov, kooku00, Jazcash, and Philipp3211 reacted with thumbs up emoji
Copy link

revidee commented Sep 28, 2022
edited
Loading

One drawback now is that this would output top-level awaits instead of "proper" es6 imports.

Additionally, this also happens with non-ajv-format imports if code has been generated with standaloneCode.

So, in short, all code-generating code would need to handle ES6 imports properly instead of defaulting to commonjs-requires.

For anyone needing a workaround to post-process the output of standaloneCode:

// modify to fit your output of standaloneCode
let moduleCode = standaloneCode(/*...*/);
// regexp to capture the "old" commonjs code
const requireRewriteRegex: RegExp = /const(func\d*)=require\("(.*?)"\)\.default;/m;
// used to find the first possible start position in which to insert the re-written imports
const USE_STRICT_TEXT = "\"use strict\";";
let match: RegExpMatchArray | null = null;
while (match = moduleCode.match(requireRewriteRegex)) {
 moduleCode = moduleCode.substring(0, match.index) + moduleCode.substring(match.index + match[0].length);
 const useStrictStart = moduleCode.indexOf(USE_STRICT_TEXT);
 let insertionIndex = 0;
 if (useStrictStart !== -1) {
 insertionIndex = useStrictStart + USE_STRICT_TEXT.length;
 }
 moduleCode = moduleCode.substring(0, insertionIndex) + `import ${match[1]} from "${match[2]}";` + moduleCode.substring(insertionIndex);
}
// write moduleCode to a file or whatever.

Copy link

This change seems to make code that uses ajv-format asynchronous, which is a major breaking change to validators. I think converting to import {} from "" form would be better.

Copy link

kooku0 commented May 18, 2023
edited
Loading

I hope this code helps someone.

const ajv = new Ajv({
 formats: { 'iso-date-time': true },
 schemas: [schema],
 code: {
 source: true,
 esm: true,
 },
});
addFormats(ajv, ['iso-date-time']);
const moduleCode = standaloneCode(ajv, {
 validate: schema.$id,
});
const importAjvFormatsDict = new Map();
const splitBySemiColon = moduleCode.split(';');
splitBySemiColon.forEach((item, idx) => {
 if (item.includes('require("ajv-formats/dist/formats")')) {
 importAjvFormatsDict.set(idx, item);
 }
});
importAjvFormatsDict.forEach((value, key) => {
 const formatVariable = (value.match(/constformats\d+/) ?? [])[0];
 const formatName = value.match(/fullFormats\["(.+?)"\]/)[1];
 splitBySemiColon[
 key
 ] = `import { fullFormats } from "ajv-formats/dist/formats";${formatVariable} = fullFormats["${formatName}"]`;
});
fs.writeFileSync(path.join(__dirname, '../src/services/ajv/index.ts'), `// @ts-nocheck\n${splitBySemiColon.join(';')}`);
o-alexandrov reacted with thumbs up emoji

Copy link

o-alexandrov commented May 18, 2023
edited
Loading

@kooku0 thank you, I slightly improved your version to:

  • get rid of duplicate imports
  • add support for ajv-keywords' transform
  • remove unused nullish coalescing, because we should want it to fail, if it doesn't match, as that's how we'd know we need to modify the script in the future
let codeRaw = standaloneCode(ajv, validate)
const codeArr = codeRaw.split(`;`)
const mapAjvFormats = new Map<number, string>()
const mapAjvTransform = new Map<number, string>()
codeArr.forEach((item, idx) => {
 if (item.includes(`require("ajv-formats/dist/formats")`)) {
 return mapAjvFormats.set(idx, item)
 }
 if (item.includes(`require("ajv-keywords/dist/definitions/transform")`)) {
 return mapAjvTransform.set(idx, item)
 }
})
mapAjvFormats.forEach((value, key) => {
 const varDeclaration = /constformats\d+/.exec(value)![0]
 const name = /fullFormats\.(.*)/.exec(value)![1]
 codeArr[key] = `${varDeclaration} = fullFormats["${name}"]`
})
mapAjvTransform.forEach((value, key) => {
 const varDeclaration = /constfunc\d+/.exec(value)![0]
 const name = /transform\.(.*)/.exec(value)![1]
 codeArr[key] = `${varDeclaration} = transformDef.transform["${name}"]`
})
if (mapAjvFormats.size) {
 const idx = mapAjvFormats.keys().next().value
 codeArr[
 idx
 ] = `import { fullFormats } from "ajv-formats/dist/formats";${codeArr[idx]}`
}
if (mapAjvTransform.size) {
 const idx = mapAjvTransform.keys().next().value
 codeArr[
 idx
 ] = `import transformDef from "ajv-keywords/dist/definitions/transform";${codeArr[idx]}`
}
codeRaw = codeArr.join(`;`)

This is the result in the validator file:

import transformDef from "ajv-keywords/dist/definitions/transform"
const func2 = transformDef.transform[`trim`]
const func3 = transformDef.transform[`toLowerCase`]
import { fullFormats } from "ajv-formats/dist/formats"
const formats0 = fullFormats[`int32`]
kooku0, itpropro, and Philipp3211 reacted with thumbs up emoji

Copy link

itpropro commented Aug 29, 2023
edited
Loading

Hey @epoberezkin, @ChALkeR, any timeline on when this PR and some of the other open ones can be merged? The module ajv-formats is blowing up in some of my native esm projects currently, because it still has some strange imports like the ones fixed with this PR. It would be great to have a current, completely esm compliant version of ajv-formats available for use in modern projects.

albanm reacted with thumbs up emoji

Copy link

brainsiq commented Dec 4, 2023

I arrived here from the error from my use of ajv standalone when updating a project to ES modules. Still very much learning to adapt to ES modules but I did find that appending the following to the top of the standalone output seemed to be a very simple solution:

import { createRequire } from 'module';
const require = createRequire(import.meta.url);
Jazcash reacted with thumbs up emoji Jazcash reacted with hooray emoji Jazcash reacted with heart emoji Jazcash reacted with rocket emoji

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Reviewers

No reviews

Assignees

No one assigned

Labels

None yet

Milestone

No milestone

Development

Successfully merging this pull request may close these issues.

Take into account ajv code.esm option

AltStyle によって変換されたページ (->オリジナル) /