diff --git a/config/processInvariants.ts b/config/processInvariants.ts index 8af71d3b3ef..72e1c2b077e 100644 --- a/config/processInvariants.ts +++ b/config/processInvariants.ts @@ -1,14 +1,14 @@ -import { readFileSync, writeFileSync } from "fs"; -import { resolve, relative } from "path"; +import * as fs from "fs"; +import * as path from "path"; import glob = require("glob"); -const distDir = resolve(__dirname, "..", "dist"); +const distDir = path.resolve(__dirname, "..", "dist"); glob(`${distDir}/**/*.js`, (error, files) => { if (error) throw error; files.sort().forEach(file => { - const relPath = relative(distDir, file); + const relPath = path.relative(distDir, file); // Outside the distDir, somehow. if (relPath.startsWith("../")) return; @@ -16,21 +16,63 @@ glob(`${distDir}/**/*.js`, (error, files) => { // Avoid re-transforming CommonJS bundle files. if (relPath.endsWith(".cjs.js")) return; - const source = readFileSync(file, "utf8"); + const source = fs.readFileSync(file, "utf8"); const output = transform(source, relPath); if (source !== output) { console.log("transformed invariants in " + relPath); - writeFileSync(file, output, "utf8"); + fs.writeFileSync(file, output, "utf8"); } }); + + fs.writeFileSync( + path.join(distDir, "invariantErrorCodes.js"), + recast.print(errorCodeManifest, { + tabWidth: 2, + }).code + "\n", + ); }); import * as recast from "recast"; import * as parser from "recast/parsers/babel"; const b = recast.types.builders; +const n = recast.types.namedTypes; +type Node = recast.types.namedTypes.Node; +type NumericLiteral = recast.types.namedTypes.NumericLiteral; +type CallExpression = recast.types.namedTypes.CallExpression; +type NewExpression = recast.types.namedTypes.NewExpression; let nextErrorCode = 1; -function transform(code: string, id: string) { +const errorCodeManifest = b.objectExpression([ + b.property("init", + b.stringLiteral("@apollo/client version"), + b.stringLiteral(require("../package.json").version), + ), +]); + +errorCodeManifest.comments = [ + b.commentLine(' This file is meant to help with looking up the source of errors like', true), + b.commentLine(' "Invariant Violation: 35" and is automatically generated by the file', true), + b.commentLine(' @apollo/client/config/processInvariants.ts for each @apollo/client', true), + b.commentLine(' release. The numbers may change from release to release, so please', true), + b.commentLine(' consult the @apollo/client/invariantErrorCodes.js file specific to', true), + b.commentLine(' your @apollo/client version. This file is not meant to be imported.', true), +]; + +function getErrorCode( + file: string, + expr: CallExpression | NewExpression, +): NumericLiteral { + const numLit = b.numericLiteral(nextErrorCode++); + errorCodeManifest.properties.push( + b.property("init", numLit, b.objectExpression([ + b.property("init", b.identifier("file"), b.stringLiteral(file)), + b.property("init", b.identifier("node"), expr), + ])), + ); + return numLit; +} + +function transform(code: string, file: string) { // If the code doesn't seem to contain anything invariant-related, we // can skip parsing and transforming it. if (!/invariant/i.test(code)) { @@ -50,7 +92,7 @@ function transform(code: string, id: string) { } const newArgs = node.arguments.slice(0, 1); - newArgs.push(b.numericLiteral(nextErrorCode++)); + newArgs.push(getErrorCode(file, node)); return b.conditionalExpression( makeNodeEnvTest(), @@ -80,9 +122,7 @@ function transform(code: string, id: string) { return; } - const newArgs = [ - b.numericLiteral(nextErrorCode++), - ]; + const newArgs = [getErrorCode(file, node)]; return b.conditionalExpression( makeNodeEnvTest(), @@ -99,11 +139,6 @@ function transform(code: string, id: string) { return recast.print(ast).code; } -const n = recast.types.namedTypes; -type Node = recast.types.namedTypes.Node; -type CallExpression = recast.types.namedTypes.CallExpression; -type NewExpression = recast.types.namedTypes.NewExpression; - function isIdWithName(node: Node, ...names: string[]) { return n.Identifier.check(node) && names.some(name => name === node.name);