UNPKG

jsonpath-faster

Version:

Query JavaScript objects with JSONPath expressions. Compiles and caches JSONpath to JS

135 lines (119 loc) 3.78 kB
"use strict"; const fs = require("fs"); const path = require("path"); const mkdirp = require("mkdirp"); const fg = require("fast-glob"); const esprima = require("esprima"); const estraverse = require("estraverse"); const escodegen = require("escodegen"); const prettier = require("prettier"); async function writeFile(outFile, data) { await mkdirp(path.dirname(outFile)); const tmpFile = outFile + ".tmp"; await fs.promises.writeFile(tmpFile, data); await fs.promises.rename(tmpFile, outFile); } async function copy(inFile, outFile) { const src = await fs.promises.readFile(inFile, "utf8"); await writeFile(outFile, src); } const makeAssignRequire = (name, value) => ({ type: "VariableDeclaration", declarations: [ { type: "VariableDeclarator", id: { type: "Identifier", name }, init: { type: "CallExpression", callee: { type: "Identifier", name: "require" }, arguments: [{ type: "Literal", value }] } } ], kind: "const" }); const assertMap = { deepEqual: "same", equal: "same", throws: "throws" }; async function tapify(inFile, outFile, pathPrefix) { const src = await fs.promises.readFile(inFile, "utf8"); const ast = esprima.parseScript(src); const fixRequirePath = rp => rp.replace(/^\.\./, pathPrefix + ".."); ast.body.unshift(makeAssignRequire("tap", "tap")); const tap = estraverse.replace(ast, { enter: function(node, parent) { if (node.type === "CallExpression") { const callee = node.callee; if (callee.type === "Identifier") { if (callee.name === "suite" || callee.name === "test") { node.arguments[1].async = true; return { ...node, callee: { type: "MemberExpression", computed: false, object: { type: "Identifier", name: "tap" }, property: { type: "Identifier", name: "test" } } }; } if ( callee.name === "require" && node.arguments.length === 1 && node.arguments[0].type === "Literal" ) { const req = node.arguments[0].value; node.arguments[0].value = fixRequirePath(req); // add .strict pragma to jsonpath require if (req === ".." || req == "../") { this.skip(); return { computed: false, object: node, property: { name: "strict", type: "Identifier" }, type: "MemberExpression" }; } } } else if (callee.type === "MemberExpression") { if (callee.object.name === "assert") { const tapAssert = assertMap[callee.property.name]; if (!tapAssert) throw new Error(`Can't map assert.${callee.property.name}`); callee.object.name = "tap"; callee.property.name = tapAssert; } } } }, leave: function(node, parent) {} }); const pretty = prettier.format(escodegen.generate(tap), { filepath: outFile }); await writeFile( outFile, [`// automatically translated from ${inFile}`, pretty].join("\n") ); } (async () => { const root = "node_modules/jsonpath/test"; try { const tests = await fg(`${root}/**`); for (const test of tests) { const tap = path.join("test", "upstream", path.relative(root, test)); if (/\.js$/.test(test)) { console.log(`Converting ${test} to ${tap}`); await tapify(test, tap, "../"); } else { console.log(`Copying ${test} to ${tap}`); await copy(test, tap); } } } catch (e) { console.error(e); process.exit(1); } })();