one
Version:
One is a new React Framework that makes Vite serve both native and web.
89 lines (88 loc) • 5.16 kB
JavaScript
import { dirname, join, resolve } from "path";
import generator from "@babel/generator";
import parser from "@babel/parser";
import traverse from "@babel/traverse";
import t from "@babel/types";
import { resolvePath } from "@vxrn/resolve";
import FSExtra from "fs-extra";
import fs from "fs-extra";
import { serverlessVercelNodeJsConfig } from "../config/vc-config-base.native.js";
import { serverlessVercelPackageJson } from "../config/vc-package-base.native.js";
import { getPathFromRoute } from "../getPathFromRoute.native.js";
async function createApiServerlessFunction(route, code, oneOptionsRoot, postBuildLogs) {
var outDir = arguments.length > 4 && arguments[4] !== void 0 ? arguments[4] : "dist";
try {
var path = getPathFromRoute(route, {
includeIndex: true
});
postBuildLogs.push(`[one.build][vercel.createSsrServerlessFunction] pageName: ${path}`);
var funcFolder = join(oneOptionsRoot, `.vercel/output/functions/${path}.func`);
await fs.ensureDir(funcFolder);
if (code.includes("react")) {
postBuildLogs.push(`[one.build][vercel.createSsrServerlessFunction] detected react in depenency tree for ${path}`);
var reactPath = dirname(resolvePath("react/package.json", oneOptionsRoot));
await fs.copy(resolve(reactPath), resolve(join(funcFolder, "node_modules", "react")));
}
var distAssetsFolder = resolve(join(funcFolder, "assets"));
postBuildLogs.push(`[one.build][vercel.createSsrServerlessFunction] copy shared assets to ${distAssetsFolder}`);
var sourceAssetsFolder = resolve(join(oneOptionsRoot, outDir, "api", "assets"));
if (await FSExtra.pathExists(sourceAssetsFolder)) {
await fs.copy(sourceAssetsFolder, distAssetsFolder);
}
await fs.ensureDir(resolve(join(funcFolder, "entrypoint")));
var entrypointFilePath = resolve(join(funcFolder, "entrypoint", "index.js"));
postBuildLogs.push(`[one.build][vercel.createSsrServerlessFunction] writing entrypoint to ${entrypointFilePath}`);
await fs.writeFile(entrypointFilePath, wrapHandlerFunctions(code));
var packageJsonFilePath = resolve(join(funcFolder, "package.json"));
postBuildLogs.push(`[one.build][vercel.createSsrServerlessFunction] writing package.json to ${packageJsonFilePath}`);
await fs.writeJSON(packageJsonFilePath, serverlessVercelPackageJson);
postBuildLogs.push(`[one.build][vercel.createSsrServerlessFunction] writing .vc-config.json to ${join(funcFolder, ".vc-config.json")}`);
return fs.writeJson(join(funcFolder, ".vc-config.json"), {
...serverlessVercelNodeJsConfig,
handler: "entrypoint/index.js"
});
} catch (e) {
console.error(`[one.build][vercel.createSsrServerlessFunction] failed to generate func for ${route.file}`, e);
}
}
function wrapHandlerFunctions(code) {
var ast = parser.parse(code, {
sourceType: "module"
});
traverse.default(ast, {
FunctionDeclaration(path) {
var {
node
} = path;
var functionNamesToHandle = ["GET", "POST", "PUT", "PATCH", "DELETE", "HEAD", "OPTIONS"];
if (!node.id || !functionNamesToHandle.includes(node.id.name)) return;
if (node.extra && node.extra.isWrapper) return;
if (node.extra && node.extra.isWrapped) return;
var originalName = `orig_${node.id.name}`;
var originalFunction = t.functionDeclaration(t.identifier(originalName), node.params, node.body, node.generator, node.async);
var requestIdentifier = t.identifier("request");
var wrapperParams = [requestIdentifier];
var urlIdentifier = t.identifier("url");
var paramsIdentifier = t.identifier("params");
var urlDecl = t.variableDeclaration("const", [t.variableDeclarator(urlIdentifier, t.newExpression(t.identifier("URL"), /* Node.js global */
[t.memberExpression(requestIdentifier, t.identifier("url"))]))]);
var paramsDecl = t.variableDeclaration("const", [t.variableDeclarator(paramsIdentifier, t.callExpression(t.memberExpression(t.identifier("Object"), t.identifier("fromEntries")), [t.callExpression(t.memberExpression(t.memberExpression(urlIdentifier, t.identifier("searchParams")), /* url.searchParams */
t.identifier("entries")), [])]))]);
var callOrigFnStatement = t.callExpression(t.identifier(originalName), [requestIdentifier, t.objectExpression([t.objectProperty(t.identifier("params"), paramsIdentifier)])]);
var wrapperFunction = t.functionDeclaration(t.identifier(node.id.name + ""), wrapperParams, t.blockStatement([urlDecl, paramsDecl, t.returnStatement(callOrigFnStatement)]));
node.extra = node.extra || {};
node.extra.isWrapped = true;
wrapperFunction.extra = wrapperFunction.extra || {};
wrapperFunction.extra.isWrapper = true;
if (path.parentPath.isExportNamedDeclaration()) {
path.replaceWithMultiple([originalFunction, t.exportNamedDeclaration(wrapperFunction, [])]);
} else {
path.replaceWithMultiple([originalFunction, wrapperFunction]);
}
}
});
var output = generator.default(ast, {}).code;
return output;
}
export { createApiServerlessFunction };
//# sourceMappingURL=createApiServerlessFunction.native.js.map