UNPKG

telefunc

Version:

Remote functions. Instead of API.

92 lines (91 loc) 4.07 kB
export default BabelPluginTelefunc; import { parse } from '@babel/parser'; import { transformTelefuncFileClientSideSync } from '../shared/transformer/transformTelefuncFileClientSideSync.js'; import { toPosixPath } from '../server/utils.js'; function getExportsFromBabelAST(programNodePath, types) { const body = programNodePath.node.body; const exported = []; for (let index = 0; index < body.length; index++) { const subNode = body[index]; // export default fnName if (types.isExportDefaultDeclaration(subNode)) { exported.push('default'); } if (types.isExportNamedDeclaration(subNode)) { if (subNode.specifiers.length > 0) { // Handles cases: // export { functionName }; // export { functionName as fnName }; // export { functionName as "fnName" }; // export { "fnName" } from "package"; for (const specifier of subNode.specifiers) { if (specifier.exported.type === 'Identifier') { // export { functionName }; // export { functionName as fnName }; exported.push(specifier.exported.name); } else if (specifier.exported.type === 'StringLiteral') { // export { functionName as "fnName" }; // export { "fnName" } from "package"; exported.push(specifier.exported.value); } } } else if (types.isFunctionDeclaration(subNode.declaration)) { // export function fn() {} // export async function fn() {} exported.push(subNode.declaration.id.name); // Function must have ID if it's part of a named export } else if (types.isVariableDeclaration(subNode.declaration)) { // export const fnName = () => {} // export var fnName = () => {} // export let fnName = () => {} // export const fnName = function() {} // export var fnName = function() {} // export let fnName = function() {} const declarator = subNode.declaration.declarations[0]; if ('name' in declarator.id && (types.isFunctionExpression(declarator.init) || types.isArrowFunctionExpression(declarator.init))) { exported.push(declarator.id.name); // Function must have ID if it's part of a named export } } } } return exported; } function BabelPluginTelefunc(babel) { return { visitor: { Program(path, context) { const filename = context.filename; if (!filename.includes('.telefunc.')) return; if (isFileAlreadyTransformed(path, babel.types)) return; const exportNames = getExportsFromBabelAST(path, babel.types); const root = context.file.opts.root; const transformed = transformTelefuncFileClientSideSync(toPosixPath(filename), toPosixPath(root), exportNames).code; const parsed = parse(transformed, { sourceType: 'module', }); path.replaceWith(parsed.program); }, }, }; } function isFileAlreadyTransformed(path, types) { return path.node.body.some((t) => { if (!types.isImportDeclaration(t)) return false; if (t.specifiers.length === 0) return false; const specifier = t.specifiers[0]; if (!types.isImportSpecifier(specifier)) return false; if (!types.isImportSpecifier(specifier)) return false; if (!types.isIdentifier(specifier.imported)) return false; return specifier.imported.name === '__remoteTelefunctionCall'; }); }