UNPKG

@prodo/babel-plugin

Version:

Babel plugin for [Prodo](https://prodo.dev). See [documentation](https://docs.prodo.dev/basics/babel-plugin) for more info.

191 lines 9.78 kB
"use strict"; var __spreadArrays = (this && this.__spreadArrays) || function () { for (var s = 0, i = 0, il = arguments.length; i < il; i++) s += arguments[i].length; for (var r = Array(s), k = 0, i = 0; i < il; i++) for (var a = arguments[i], j = 0, jl = a.length; j < jl; j++, k++) r[k] = a[j]; return r; }; Object.defineProperty(exports, "__esModule", { value: true }); var pathLib = require("path"); // Don't consider an action/component if it uses `model` - e.g. `model.createStore` var MODEL_BLACKLIST = ["model"]; var isModelContextImport = function (importPath) { return importPath.startsWith(".") && /^model(\.ctx)?(\.(j|t)sx?)?$/.test(pathLib.basename(importPath)); }; exports.default = (function (t, type, name, path) { var universeImports = { specifiers: {}, }; path.get("body").traverse({ Identifier: function (p) { // Does it use something from "./model.ctx" if (p.isReferencedIdentifier()) { var binding = p.scope.getBinding(p.node.name); if (binding != null) { var bindingPath = binding.path; if (((t.isImportSpecifier(bindingPath.node) && !MODEL_BLACKLIST.includes(bindingPath.node.imported.name)) || t.isImportNamespaceSpecifier(bindingPath.node) || t.isImportDefaultSpecifier(bindingPath.node)) && t.isImportDeclaration(bindingPath.parent) && isModelContextImport(bindingPath.parent.source.value)) { universeImports.modelSource = bindingPath.parent.source.value.replace(/(\.ctx)?(?=\.(j|t)sx?)?$/, ""); universeImports.programPath = bindingPath.parentPath .parentPath; if (t.isImportSpecifier(bindingPath.node)) { // import {foo} from "./model.ctx"; universeImports.specifiers[bindingPath.node.imported.name] = bindingPath.node.local.name; } else if (t.isImportNamespaceSpecifier(bindingPath.node)) { // import * as foo from "./model.ctx"; universeImports.namespace = bindingPath.node.local.name; } else if (t.isImportDefaultSpecifier(bindingPath.node)) { // import foo from "./model.ctx"; universeImports.specifiers.default = bindingPath.node.local.name; } } else if (t.isVariableDeclarator(bindingPath.node) && t.isCallExpression(bindingPath.node.init) && t.isIdentifier(bindingPath.node.init.callee) && bindingPath.node.init.callee.name === "require" && bindingPath.node.init.arguments.length === 1 && t.isStringLiteral(bindingPath.node.init.arguments[0]) && isModelContextImport(bindingPath.node.init.arguments[0] .value)) { // const foo = require("./model.ctx"); universeImports.modelSource = bindingPath.node.init .arguments[0].value.replace(/(\.ctx)?(?=\.(j|t)sx?)?$/, ""); universeImports.programPath = bindingPath.parentPath .parentPath; if (t.isIdentifier(bindingPath.node.id)) { // const foo = require("./model.ctx"); universeImports.namespace = bindingPath.node.id.name; } else if (t.isObjectPattern(bindingPath.node.id) && !MODEL_BLACKLIST.includes(p.node.name)) { var property = bindingPath.node.id.properties.find(function (prop) { return t.isObjectProperty(prop) ? t.isIdentifier(prop.value) && prop.value.name === p.node.name : t.isIdentifier(prop.argument) && prop.argument.name === p.node.name; }); if (property == null) { throw new Error("You are using require in a way that the transpiler can't understand."); } if (t.isObjectProperty(property)) { // const {foo} = require("./model.ctx"); universeImports.specifiers[property.key.name] = property.value.name; } else { // const {...foo} = require("./model.ctx"); universeImports.specifierRest = property.argument.name; } } } } } }, }); if (universeImports.namespace == null && Object.keys(universeImports.specifiers).length === 0 && universeImports.specifierRest == null) { // Doesn't use the universe, so don't change anything. return; } if (universeImports.namespace != null && (Object.keys(universeImports.specifiers).length > 0 || universeImports.specifierRest != null)) { throw new Error("Cannot import the context as both a namespace and using named imports."); } // Insert `import { model } from "./src/model"; var modelImport; if (universeImports.programPath != null && universeImports.modelSource != null) { var importDeclarationPath = universeImports.programPath .get("body") .find(function (expressionPath) { return t.isImportDeclaration(expressionPath.node) && expressionPath.node.source.value === universeImports.modelSource; }); if (importDeclarationPath == null) { var importDeclaration = t.importDeclaration([t.importSpecifier(t.identifier("model"), t.identifier("model"))], t.stringLiteral(universeImports.modelSource)); universeImports.programPath.unshiftContainer("body", importDeclaration); modelImport = { specifier: "model" }; } else { if (importDeclarationPath.node.specifiers.some(function (specifier) { return t.isImportNamespaceSpecifier(specifier); })) { modelImport = { namespace: importDeclarationPath.node.specifiers.find(function (specifier) { return t.isImportNamespaceSpecifier(specifier); }).local.name, }; } else if (importDeclarationPath.node.specifiers.some(function (specifier) { return t.isImportSpecifier(specifier) && specifier.imported.name === "model"; })) { modelImport = { specifier: importDeclarationPath.node.specifiers.find(function (specifier) { return t.isImportSpecifier(specifier) && specifier.imported.name === "model"; }).local.name, }; } else { importDeclarationPath.unshiftContainer("specifiers", t.importSpecifier(t.identifier("model"), t.identifier("model"))); modelImport = { specifier: "model" }; } } } if (modelImport == null) { throw new Error("Could not import the model."); } /* * If it's a FunctionDeclaration, turn it into a VariableDeclaration * * function foo () { ... } * * becomes * * const foo = function () { ... } `*/ if (t.isFunctionDeclaration(path.node)) { path.replaceWith(t.variableDeclaration("const", [ t.variableDeclarator(t.identifier(name), t.functionExpression(null, path.node.params, t.isBlockStatement(path.node.body) ? path.node.body : t.blockStatement([t.returnStatement(path.node.body)]), path.node.generator, path.node.async)), ])); path = path.get("declarations")[0].get("init"); } /* * Surround in model.action or model.connect * * const foo = () => { ... } * * becomes * * const foo = model.action(({state}) => () => { ... }); */ path.replaceWith(t.callExpression(t.memberExpression("namespace" in modelImport ? t.memberExpression(t.identifier(modelImport.namespace), t.identifier("model")) : t.identifier(modelImport.specifier), t.identifier(type === "action" ? "action" : "connect")), [ t.arrowFunctionExpression([ universeImports.namespace != null ? t.identifier(universeImports.namespace) : t.objectPattern(__spreadArrays(Object.keys(universeImports.specifiers) .sort() .map(function (key) { return t.objectProperty(t.identifier(key), t.identifier(universeImports.specifiers[key]), false, key === universeImports.specifiers[key]); }), (universeImports.specifierRest != null ? [ t.restElement(t.identifier(universeImports.specifierRest)), ] : []))), ], path.node), t.stringLiteral(name), ])); }); //# sourceMappingURL=inject-universe.js.map