UNPKG

create-expo-cljs-app

Version:

Create a react native application with Expo and Shadow-CLJS!

185 lines 7.95 kB
"use strict"; // Copyright 2021-present 650 Industries (Expo). All rights reserved. var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.loaders = exports.createMultiRuleTransformer = void 0; const chalk_1 = __importDefault(require("chalk")); const debug_1 = __importDefault(require("debug")); const resolve_from_1 = __importDefault(require("resolve-from")); const generateFunctionMap_1 = require("./generateFunctionMap"); const getBabelConfig_1 = require("./getBabelConfig"); const debug = debug_1.default('expo:metro:exotic-babel-transformer'); let babelCore; function getBabelCoreFromProject(projectRoot) { if (babelCore) return babelCore; babelCore = require(resolve_from_1.default(projectRoot, '@babel/core')); return babelCore; } let babelParser; function getBabelParserFromProject(projectRoot) { if (babelParser) return babelParser; babelParser = require(resolve_from_1.default(projectRoot, '@babel/parser')); return babelParser; } function sucrase(args, { transforms, }) { const { src, filename, options: { dev }, } = args; const { transform } = require('sucrase'); const results = transform(src, { filePath: filename, production: !dev, transforms, }); return { code: results.code, functionMap: null, }; } const getExpensiveSucraseTransforms = (filename) => [ 'jsx', 'imports', /\.tsx?$/.test(filename) ? 'typescript' : 'flow', ]; function parseAst(projectRoot, sourceCode) { const babylon = getBabelParserFromProject(projectRoot); return babylon.parse(sourceCode, { sourceType: 'unambiguous', }); } /** Create a transformer that emulates Webpack's loader system. */ function createMultiRuleTransformer({ getRuleType, rules, }) { // const warnings: string[] = []; return function transform(args) { const { filename, options } = args; const OLD_BABEL_ENV = process.env.BABEL_ENV; process.env.BABEL_ENV = (options === null || options === void 0 ? void 0 : options.dev) ? 'development' : process.env.BABEL_ENV || 'production'; try { const ruleType = getRuleType(args); for (const rule of rules) { // optimization for checking node modules if (rule.type && rule.type !== ruleType) { continue; } const isMatched = typeof rule.test === 'function' ? rule.test(args) : rule.test.test(args.filename); if (isMatched) { const results = rule.transform(args); // @ts-ignore: Add extra property for testing results._ruleName = rule.name; // Perform a basic parse if none exists, this enables us to control the output, but only if it changed. if (results.code && !results.ast) { // Parse AST with babel otherwise Metro transformer will throw away the returned results. results.ast = parseAst(options === null || options === void 0 ? void 0 : options.projectRoot, results.code); } // TODO: Suboptimal warnings // if (rule.warn) { // const matchName = // filename.match(/node_modules\/((:?@[\w\d-]+\/[\w\d-]+)|(:?[\w\d-]+))\/?/)?.[1] ?? // filename; // if (matchName && !warnings.includes(matchName)) { // warnings.push(matchName); // console.warn(chalk.yellow.bold`warn `, matchName); // console.warn( // chalk.yellow`untranspiled module is potentially causing bundler slowdown, using modules that support commonjs will make your dev server much faster.` // ); // } // } return results; } } throw new Error('no loader rule to handle file: ' + filename); } finally { if (OLD_BABEL_ENV) { process.env.BABEL_ENV = OLD_BABEL_ENV; } } }; } exports.createMultiRuleTransformer = createMultiRuleTransformer; exports.loaders = { // Perform the standard, and most expensive transpilation sequence. app(args) { debug('app:', args.filename); const { filename, options, src, plugins } = args; const babelConfig = { // ES modules require sourceType='module' but OSS may not always want that sourceType: 'unambiguous', ...getBabelConfig_1.getBabelConfig(filename, options, plugins), // Variables that are exposed to the user's babel preset. caller: { name: 'metro', platform: options.platform, }, ast: true, }; // Surface a warning function so babel linters can be used. Object.defineProperty(babelConfig.caller, 'onWarning', { enumerable: false, writable: false, value: (babelConfig.caller.onWarning = function (msg) { // Format the file path first so users know where the warning came from. console.warn(chalk_1.default.bold.yellow `warn ` + args.filename); console.warn(msg); }), }); const { parseSync, transformFromAstSync } = getBabelCoreFromProject(options.projectRoot); const sourceAst = parseSync(src, babelConfig); // Should never happen. if (!sourceAst) return { ast: null }; const result = transformFromAstSync(sourceAst, src, babelConfig); // TODO: Disable by default const functionMap = generateFunctionMap_1.generateFunctionMap(options.projectRoot, sourceAst, { filename }); // The result from `transformFromAstSync` can be null (if the file is ignored) if (!result) { return { ast: null, functionMap }; } return { ast: result.ast, functionMap }; }, // Transpile react-native with sucrase. reactNativeModule(args) { debug('rn:', args.filename); return sucrase(args, { transforms: ['jsx', 'flow', 'imports'], }); }, // Transpile expo modules with sucrase. expoModule(args) { debug('expo:', args.filename); // TODO: Fix all expo packages return sucrase(args, { transforms: [ 'imports', // TODO: fix expo-processing, expo/vector-icons /(expo-processing|expo\/vector-icons)/.test(args.filename) && 'jsx', // TODO: fix expo-asset-utils /(expo-asset-utils)/.test(args.filename) && 'flow', ].filter(Boolean), }); }, // Transpile known community modules with the most expensive sucrase untranspiledModule(args) { debug('known issues:', args.filename); return sucrase(args, { transforms: getExpensiveSucraseTransforms(args.filename), }); }, // Pass all modules through without transpiling them. passthroughModule(args) { const { filename, options, src } = args; debug('passthrough:', filename); // Perform a basic ast parse, this doesn't matter since the worker will parse and ignore anyways. const ast = parseAst(options.projectRoot, src); // TODO: Disable by default const functionMap = generateFunctionMap_1.generateFunctionMap(options.projectRoot, ast, { filename }); return { code: src, functionMap, ast, }; }, }; //# sourceMappingURL=createMultiRuleTransformer.js.map