@geek-fun/serverlessinsight
Version:
Full life cycle cross providers serverless application management for your fast-growing business.
121 lines (120 loc) • 5.19 kB
JavaScript
;
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.functionsHandler = void 0;
const common_1 = require("../../common");
const functionRunner_1 = require("./functionRunner");
const node_path_1 = __importDefault(require("node:path"));
const node_fs_1 = __importDefault(require("node:fs"));
const aliyunFc_1 = require("./aliyunFc");
const utils_1 = require("./utils");
const functionsHandler = async (req, parsed, iac) => {
common_1.logger.info(`Function request received by local server -> ${req.method} ${parsed.identifier ?? '/'} `);
const fcDef = iac.functions?.find((fn) => fn.key === parsed.identifier);
if (!fcDef) {
return {
statusCode: 404,
body: { error: 'Function not found', functionKey: parsed.identifier },
};
}
if (!fcDef.code) {
return {
statusCode: 400,
body: { error: 'Function code configuration not found', functionKey: fcDef.key },
};
}
let tempDir = null;
try {
const codePath = node_path_1.default.resolve(process.cwd(), fcDef.code.path);
let codeDir;
if (codePath.endsWith('.zip') && node_fs_1.default.existsSync(codePath)) {
tempDir = await (0, utils_1.extractZipFile)(codePath);
codeDir = tempDir;
}
else if (node_fs_1.default.existsSync(codePath) && node_fs_1.default.statSync(codePath).isDirectory()) {
codeDir = codePath;
}
else {
codeDir = node_path_1.default.dirname(codePath);
}
const funOptions = {
codeDir,
functionKey: fcDef.key,
handler: fcDef.code.handler,
servicePath: '',
timeout: fcDef.timeout * 1000,
};
// Check if provider is Aliyun to use Aliyun FC format
const isAliyun = iac.provider.name === common_1.ProviderEnum.ALIYUN;
let event;
let fcContext;
let env;
if (isAliyun) {
// Aliyun FC format: event is a Buffer containing JSON
const requestId = (0, aliyunFc_1.generateRequestId)();
const { event: aliyunEvent } = await (0, aliyunFc_1.transformToAliyunEvent)(req, parsed.url, parsed.query);
event = aliyunEvent;
// Use serializable context for worker thread (logger will be added inside worker)
fcContext = (0, aliyunFc_1.createAliyunContextSerializable)(iac, fcDef.name, fcDef.code.handler, fcDef.memory, fcDef.timeout, requestId);
env = {
...fcDef.environment,
};
}
else {
// AWS Lambda format (default)
const rawBody = await (0, common_1.readRequestBody)(req);
event = rawBody ? JSON.parse(rawBody) : {};
env = {
...fcDef.environment,
AWS_REGION: iac.provider.region || 'us-east-1',
FUNCTION_NAME: fcDef.name,
FUNCTION_MEMORY_SIZE: String(fcDef.memory),
FUNCTION_TIMEOUT: String(fcDef.timeout),
};
fcContext = {
functionName: fcDef.name,
functionVersion: '$LATEST',
memoryLimitInMB: fcDef.memory,
logGroupName: `/aws/lambda/${fcDef.name}`,
logStreamName: `${new Date().toISOString().split('T')[0]}/[$LATEST]${Math.random().toString(36).substring(7)}`,
invokedFunctionArn: `arn:aws:lambda:${iac.provider.region}:000000000000:function:${fcDef.name}`,
awsRequestId: Math.random().toString(36).substring(2, 15),
};
}
common_1.logger.debug(`Invoking worker with event type: ${isAliyun ? 'Buffer' : 'Object'} and context`);
common_1.logger.debug(`Worker codeDir: ${codeDir}, handler: ${funOptions.handler}`);
const result = await (0, functionRunner_1.invokeFunction)(funOptions, env, event, fcContext);
common_1.logger.info(`Function execution result: ${JSON.stringify(result)}`);
// For Aliyun, transform FC response to HTTP response if needed
if (isAliyun && result) {
const transformed = (0, aliyunFc_1.transformFCResponse)(result);
return {
statusCode: transformed.statusCode,
headers: transformed.headers,
body: transformed.body,
};
}
return {
statusCode: 200,
body: result,
};
}
catch (error) {
common_1.logger.error(`Function execution error: ${error}`);
return {
statusCode: 500,
body: {
error: 'Function execution failed',
message: error instanceof Error ? error.message : String(error),
},
};
}
finally {
if (tempDir && node_fs_1.default.existsSync(tempDir)) {
node_fs_1.default.rmSync(tempDir, { recursive: true, force: true });
}
}
};
exports.functionsHandler = functionsHandler;