UNPKG

@builder.io/mitosis

Version:

Write components once, run everywhere. Compiles to Vue, React, Solid, and Liquid. Import code from Figma and Builder.io

110 lines (109 loc) 4.8 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.mapSignalTypeInTSFile = exports.mapSignalType = exports.getSignalImportName = exports.getSignalMitosisImportForTarget = void 0; const core_1 = require("@babel/core"); const function_1 = require("fp-ts/lib/function"); const babel_transform_1 = require("../../helpers/babel-transform"); const mitosis_imports_1 = require("../mitosis-imports"); const getSignalMappingForTarget = (target) => { switch (target) { case 'svelte': const importDeclaration = core_1.types.importDeclaration([core_1.types.importSpecifier(core_1.types.identifier('Writable'), core_1.types.identifier('Writable'))], core_1.types.stringLiteral('svelte/store')); importDeclaration.importKind = 'type'; return { getTypeReference: (generics = []) => core_1.types.tsTypeReference(core_1.types.identifier('Writable'), core_1.types.tsTypeParameterInstantiation(generics)), importDeclaration, }; default: return undefined; } }; const getSignalMitosisImportForTarget = (target) => { const signalType = getSignalMappingForTarget(target); if (!signalType) { return undefined; } return (0, mitosis_imports_1.mapImportDeclarationToMitosisImport)(signalType.importDeclaration); }; exports.getSignalMitosisImportForTarget = getSignalMitosisImportForTarget; const getSignalImportName = (code) => { let foundSignalUsage = false; let signalImportName = undefined; (0, babel_transform_1.babelTransformExpression)(code, { ImportSpecifier(path) { if (core_1.types.isIdentifier(path.node.imported) && path.node.imported.name === 'Signal') { if (path.parentPath.isImportDeclaration() && path.parentPath.node.source.value === '@builder.io/mitosis') { /** * in case the import is aliased, we need to use the local name, * e.g. `import { Signal as MySignal } from '../..'` */ signalImportName = path.node.local.name; path.stop(); } } }, }); if (!signalImportName) { return undefined; } (0, babel_transform_1.babelTransformExpression)(code, { TSTypeReference(path) { if (core_1.types.isIdentifier(path.node.typeName) && path.node.typeName.name === signalImportName) { foundSignalUsage = true; path.stop(); } }, }); return foundSignalUsage ? signalImportName : undefined; }; exports.getSignalImportName = getSignalImportName; const addSignalImport = ({ code, target }) => { const signalType = getSignalMappingForTarget(target); if (!signalType) { return code; } return (0, babel_transform_1.babelTransformExpression)(code, { Program(path) { path.node.body.unshift(signalType.importDeclaration); }, }); }; /** * Finds all `Signal` types and replaces them with the correct type for the given target. * e.g. `Signal<string>` becomes `Writable<string>` for Svelte. */ const mapSignalType = ({ code, target, signalImportName = (0, exports.getSignalImportName)(code), }) => { const signalType = getSignalMappingForTarget(target); const map = (path) => { var _a; if (core_1.types.isIdentifier(path.node.typeName) && path.node.typeName.name === signalImportName) { const params = ((_a = path.node.typeParameters) === null || _a === void 0 ? void 0 : _a.params) || []; const newType = (signalType === null || signalType === void 0 ? void 0 : signalType.getTypeReference) ? signalType.getTypeReference(params) : // if no mapping exists, drop `Signal` and just use the generic type passed to `Signal` as-is. params[0]; path.replaceWith(newType); } }; return (0, babel_transform_1.babelTransformExpression)(code, { TSTypeReference(path) { map(path); }, }); }; exports.mapSignalType = mapSignalType; /** * Processes the `Signal` type usage in a plain TS file: * - Finds the `Signal` import name * - Maps the `Signal` type to the target's equivalent * - Adds the equivalent of the `Signal` import to the file */ const mapSignalTypeInTSFile = ({ code, target }) => { const signalImportName = (0, exports.getSignalImportName)(code); if (!signalImportName) { return code; } return (0, function_1.pipe)((0, exports.mapSignalType)({ target, code, signalImportName }), (code) => addSignalImport({ code, target })); }; exports.mapSignalTypeInTSFile = mapSignalTypeInTSFile;