import path from 'path'; import fs from 'fs'; import Cloud from 'alipay-serverless-server-sdk'; import { isPlainObject } from 'lodash'; import MPServerless from '@alicloud/mpserverless-node-sdk'; import getHttpClient from './utils/httpClient'; import { getServerSecret, guid, requireLocalFunction } from './utils/index'; export interface InvokeLocalFunctionOptions { /** * 小程序appId TS MODIFY */ appId?: string; /** * 阿里云serverSecret */ serverSecret?: string; /** * 空间id */ spaceId: string; /** * 函数根目录 */ project: string; /** * 函数名称 */ name: string; /** * 函数参数 */ functionArgs?: object; /** * 只有在小程序端发请求运行云函数才能获取 */ token?: string; userAgent?: string; clientIp?: string; mpSource?: string; } /** * 重写云函数调用云函数 */ function overrideFunctionInvokeFunction(originFn, options) { return async function (functionTarget, functionArgs) { const entry = path.join(options.project, functionTarget, 'index.js'); const isExist = fs.existsSync(entry); // 本地存在另一个云函数 if (isExist) { const result = await invokeLocalFunction({ ...options, name: functionTarget, functionArgs, mpSource: 'function', }); return { requestId: options.requestId, result, }; } // 调用云端的 return originFn(functionTarget, functionArgs); }; } /** * 调用云端函数 */ async function invokeLocalFunction(options: InvokeLocalFunctionOptions) { const { appId, spaceId, project, name, functionArgs, serverSecret } = options; const [serverSecretResult, userFn] = await Promise.all([ // TS MODIFY serverSecret ? serverSecret : getServerSecret(appId!, spaceId), requireLocalFunction(project, name), ]); const requestId = guid(); const httpClient = getHttpClient(); const mpserverless = new MPServerless({ // 必填参数 spaceId, endpoint: 'https://api.bspapp.com', serverSecret: serverSecretResult, httpClient, logger: console, // 选填参数 token: options.token, requestId, // userId: reqMeta.userId, //requestId: '12345678', }); mpserverless.function.invoke = overrideFunctionInvokeFunction( mpserverless.function.invoke.bind(mpserverless.function), { requestId, ...options, } ); const env = { MP_SPACE_ID: spaceId, MP_SOURCE: options.mpSource || 'function', MP_USER_AGENT: options.userAgent, MP_CLIENT_IP: options.clientIp, }; const cloud = new Cloud(mpserverless as any); const functionResult = await userFn({ requestId, args: isPlainObject(functionArgs) ? functionArgs : {}, httpclient: httpClient, env, logger: console, basement: mpserverless, // for backward compatibility only mpserverless: mpserverless, cloud: cloud, }); return functionResult; } export default invokeLocalFunction;