123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742 |
- "use strict";
- Object.defineProperty(exports, "__esModule", { value: true });
- const fs = require("fs");
- const express = require("express");
- const path = require("path");
- const bodyParser = require("body-parser");
- const url_1 = require("url");
- const _ = require("lodash");
- const types_1 = require("./types");
- const constants_1 = require("./constants");
- const functionsEmulatorShared_1 = require("./functionsEmulatorShared");
- const functionsEmulatorUtils_1 = require("./functionsEmulatorUtils");
- const types_2 = require("./events/types");
- let functionModule;
- let FUNCTION_TARGET_NAME;
- let FUNCTION_SIGNATURE;
- let FUNCTION_DEBUG_MODE;
- let developerPkgJSON;
- const dynamicImport = new Function("modulePath", "return import(modulePath)");
- function noOp() {
- return false;
- }
- function requireAsync(moduleName, opts) {
- return new Promise((res, rej) => {
- try {
- res(require(require.resolve(moduleName, opts)));
- }
- catch (e) {
- rej(e);
- }
- });
- }
- function requireResolveAsync(moduleName, opts) {
- return new Promise((res, rej) => {
- try {
- res(require.resolve(moduleName, opts));
- }
- catch (e) {
- rej(e);
- }
- });
- }
- class Proxied {
- constructor(original) {
- this.original = original;
- this.rewrites = {};
- this.proxy = new Proxy(this.original, {
- get: (target, key) => {
- key = key.toString();
- if (this.rewrites[key]) {
- return this.rewrites[key](target, key);
- }
- if (this.anyValue) {
- return this.anyValue(target, key);
- }
- return Proxied.getOriginal(target, key);
- },
- apply: (target, thisArg, argArray) => {
- if (this.appliedValue) {
- return this.appliedValue.apply(thisArg);
- }
- else {
- return Proxied.applyOriginal(target, thisArg, argArray);
- }
- },
- });
- }
- static getOriginal(target, key) {
- const value = target[key];
- if (!Proxied.isExists(value)) {
- return undefined;
- }
- else if (Proxied.isConstructor(value) || typeof value !== "function") {
- return value;
- }
- else {
- return value.bind(target);
- }
- }
- static applyOriginal(target, thisArg, argArray) {
- return target.apply(thisArg, argArray);
- }
- static isConstructor(obj) {
- return !!obj.prototype && !!obj.prototype.constructor.name;
- }
- static isExists(obj) {
- return obj !== undefined;
- }
- when(key, value) {
- this.rewrites[key] = value;
- return this;
- }
- any(value) {
- this.anyValue = value;
- return this;
- }
- applied(value) {
- this.appliedValue = value;
- return this;
- }
- finalize() {
- return this.proxy;
- }
- }
- async function resolveDeveloperNodeModule(name) {
- const pkg = requirePackageJson();
- if (!pkg) {
- new types_1.EmulatorLog("SYSTEM", "missing-package-json", "").log();
- throw new Error("Could not find package.json");
- }
- const dependencies = pkg.dependencies;
- const devDependencies = pkg.devDependencies;
- const isInPackageJSON = dependencies[name] || devDependencies[name];
- if (!isInPackageJSON) {
- return { declared: false, installed: false };
- }
- const resolveResult = await requireResolveAsync(name, { paths: [process.cwd()] }).catch(noOp);
- if (!resolveResult) {
- return { declared: true, installed: false };
- }
- const modPackageJSON = require(path.join((0, functionsEmulatorShared_1.findModuleRoot)(name, resolveResult), "package.json"));
- const moduleResolution = {
- declared: true,
- installed: true,
- version: modPackageJSON.version,
- resolution: resolveResult,
- };
- logDebug(`Resolved module ${name}`, moduleResolution);
- return moduleResolution;
- }
- async function assertResolveDeveloperNodeModule(name) {
- const resolution = await resolveDeveloperNodeModule(name);
- if (!(resolution.installed && resolution.declared && resolution.resolution && resolution.version)) {
- throw new Error(`Assertion failure: could not fully resolve ${name}: ${JSON.stringify(resolution)}`);
- }
- return resolution;
- }
- async function verifyDeveloperNodeModules() {
- const modBundles = [
- { name: "firebase-admin", isDev: false, minVersion: "8.9.0" },
- { name: "firebase-functions", isDev: false, minVersion: "3.13.1" },
- ];
- for (const modBundle of modBundles) {
- const resolution = await resolveDeveloperNodeModule(modBundle.name);
- if (!resolution.declared) {
- new types_1.EmulatorLog("SYSTEM", "missing-module", "", modBundle).log();
- return false;
- }
- if (!resolution.installed) {
- new types_1.EmulatorLog("SYSTEM", "uninstalled-module", "", modBundle).log();
- return false;
- }
- if ((0, functionsEmulatorUtils_1.compareVersionStrings)(resolution.version, modBundle.minVersion) < 0) {
- new types_1.EmulatorLog("SYSTEM", "out-of-date-module", "", modBundle).log();
- return false;
- }
- }
- return true;
- }
- function requirePackageJson() {
- if (developerPkgJSON) {
- return developerPkgJSON;
- }
- try {
- const pkg = require(`${process.cwd()}/package.json`);
- developerPkgJSON = {
- engines: pkg.engines || {},
- dependencies: pkg.dependencies || {},
- devDependencies: pkg.devDependencies || {},
- };
- return developerPkgJSON;
- }
- catch (err) {
- return;
- }
- }
- function initializeNetworkFiltering() {
- const networkingModules = [
- { name: "http", module: require("http"), path: ["request"] },
- { name: "http", module: require("http"), path: ["get"] },
- { name: "https", module: require("https"), path: ["request"] },
- { name: "https", module: require("https"), path: ["get"] },
- { name: "net", module: require("net"), path: ["connect"] },
- ];
- const history = {};
- const results = networkingModules.map((bundle) => {
- let obj = bundle.module;
- for (const field of bundle.path.slice(0, -1)) {
- obj = obj[field];
- }
- const method = bundle.path.slice(-1)[0];
- const original = obj[method].bind(bundle.module);
- obj[method] = function (...args) {
- const hrefs = args
- .map((arg) => {
- if (typeof arg === "string") {
- try {
- new url_1.URL(arg);
- return arg;
- }
- catch (err) {
- return;
- }
- }
- else if (typeof arg === "object") {
- return arg.href;
- }
- else {
- return;
- }
- })
- .filter((v) => v);
- const href = (hrefs.length && hrefs[0]) || "";
- if (href && !history[href] && !(0, functionsEmulatorUtils_1.isLocalHost)(href)) {
- history[href] = true;
- if (href.indexOf("googleapis.com") !== -1) {
- new types_1.EmulatorLog("SYSTEM", "googleapis-network-access", "", {
- href,
- module: bundle.name,
- }).log();
- }
- else {
- new types_1.EmulatorLog("SYSTEM", "unidentified-network-access", "", {
- href,
- module: bundle.name,
- }).log();
- }
- }
- try {
- return original(...args);
- }
- catch (e) {
- const newed = new original(...args);
- return newed;
- }
- };
- return { name: bundle.name, status: "mocked" };
- });
- logDebug("Outgoing network have been stubbed.", results);
- }
- async function initializeFirebaseFunctionsStubs() {
- const firebaseFunctionsResolution = await assertResolveDeveloperNodeModule("firebase-functions");
- const firebaseFunctionsRoot = (0, functionsEmulatorShared_1.findModuleRoot)("firebase-functions", firebaseFunctionsResolution.resolution);
- const httpsProviderResolution = path.join(firebaseFunctionsRoot, "lib/providers/https");
- const httpsProviderV1Resolution = path.join(firebaseFunctionsRoot, "lib/v1/providers/https");
- let httpsProvider;
- try {
- httpsProvider = require(httpsProviderV1Resolution);
- }
- catch (e) {
- httpsProvider = require(httpsProviderResolution);
- }
- const onRequestInnerMethodName = "_onRequestWithOptions";
- const onRequestMethodOriginal = httpsProvider[onRequestInnerMethodName];
- httpsProvider[onRequestInnerMethodName] = (handler, opts) => {
- const cf = onRequestMethodOriginal(handler, opts);
- cf.__emulator_func = handler;
- return cf;
- };
- httpsProvider.onRequest = (handler) => {
- return httpsProvider[onRequestInnerMethodName](handler, {});
- };
- const onCallInnerMethodName = "_onCallWithOptions";
- const onCallMethodOriginal = httpsProvider[onCallInnerMethodName];
- if (onCallMethodOriginal.length === 3) {
- httpsProvider[onCallInnerMethodName] = (opts, handler, deployOpts) => {
- const wrapped = wrapCallableHandler(handler);
- const cf = onCallMethodOriginal(opts, wrapped, deployOpts);
- return cf;
- };
- }
- else {
- httpsProvider[onCallInnerMethodName] = (handler, opts) => {
- const wrapped = wrapCallableHandler(handler);
- const cf = onCallMethodOriginal(wrapped, opts);
- return cf;
- };
- }
- httpsProvider.onCall = function (optsOrHandler, handler) {
- if (onCallMethodOriginal.length === 3) {
- let opts;
- if (arguments.length === 1) {
- opts = {};
- handler = optsOrHandler;
- }
- else {
- opts = optsOrHandler;
- }
- return httpsProvider[onCallInnerMethodName](opts, handler, {});
- }
- else {
- return httpsProvider[onCallInnerMethodName](optsOrHandler, {});
- }
- };
- }
- function wrapCallableHandler(handler) {
- const newHandler = (data, context) => {
- if (context.rawRequest) {
- const authContext = context.rawRequest.header(functionsEmulatorShared_1.HttpConstants.CALLABLE_AUTH_HEADER);
- if (authContext) {
- logDebug("Callable functions auth override", {
- key: functionsEmulatorShared_1.HttpConstants.CALLABLE_AUTH_HEADER,
- value: authContext,
- });
- context.auth = JSON.parse(decodeURIComponent(authContext));
- delete context.rawRequest.headers[functionsEmulatorShared_1.HttpConstants.CALLABLE_AUTH_HEADER];
- }
- else {
- logDebug("No callable functions auth found");
- }
- const originalAuth = context.rawRequest.header(functionsEmulatorShared_1.HttpConstants.ORIGINAL_AUTH_HEADER);
- if (originalAuth) {
- context.rawRequest.headers["authorization"] = originalAuth;
- delete context.rawRequest.headers[functionsEmulatorShared_1.HttpConstants.ORIGINAL_AUTH_HEADER];
- }
- }
- return handler(data, context);
- };
- return newHandler;
- }
- function getDefaultConfig() {
- return JSON.parse(process.env.FIREBASE_CONFIG || "{}");
- }
- function initializeRuntimeConfig() {
- if (!process.env.CLOUD_RUNTIME_CONFIG) {
- const configPath = `${process.cwd()}/.runtimeconfig.json`;
- try {
- const configContent = fs.readFileSync(configPath, "utf8");
- if (configContent) {
- try {
- JSON.parse(configContent.toString());
- logDebug(`Found local functions config: ${configPath}`);
- process.env.CLOUD_RUNTIME_CONFIG = configContent.toString();
- }
- catch (e) {
- new types_1.EmulatorLog("SYSTEM", "function-runtimeconfig-json-invalid", "").log();
- }
- }
- }
- catch (e) {
- }
- }
- }
- async function initializeFirebaseAdminStubs() {
- const adminResolution = await assertResolveDeveloperNodeModule("firebase-admin");
- const localAdminModule = require(adminResolution.resolution);
- const functionsResolution = await assertResolveDeveloperNodeModule("firebase-functions");
- const localFunctionsModule = require(functionsResolution.resolution);
- const defaultConfig = getDefaultConfig();
- const adminModuleProxy = new Proxied(localAdminModule);
- const proxiedAdminModule = adminModuleProxy
- .when("initializeApp", (adminModuleTarget) => (opts, appName) => {
- if (appName) {
- new types_1.EmulatorLog("SYSTEM", "non-default-admin-app-used", "", { appName, opts }).log();
- return adminModuleTarget.initializeApp(opts, appName);
- }
- const defaultAppOptions = opts ? opts : defaultConfig;
- new types_1.EmulatorLog("SYSTEM", "default-admin-app-used", `config=${defaultAppOptions}`, {
- opts: defaultAppOptions,
- }).log();
- const defaultApp = makeProxiedFirebaseApp(adminModuleTarget.initializeApp(defaultAppOptions));
- logDebug("initializeApp(DEFAULT)", defaultAppOptions);
- localFunctionsModule.app.setEmulatedAdminApp(defaultApp);
- if (process.env[constants_1.Constants.FIREBASE_AUTH_EMULATOR_HOST]) {
- if ((0, functionsEmulatorUtils_1.compareVersionStrings)(adminResolution.version, "9.3.0") < 0) {
- new types_1.EmulatorLog("WARN_ONCE", "runtime-status", "The Firebase Authentication emulator is running, but your 'firebase-admin' dependency is below version 9.3.0, so calls to Firebase Authentication will affect production.").log();
- }
- else if ((0, functionsEmulatorUtils_1.compareVersionStrings)(adminResolution.version, "9.4.2") <= 0) {
- const auth = defaultApp.auth();
- if (typeof auth.setJwtVerificationEnabled === "function") {
- logDebug("auth.setJwtVerificationEnabled(false)", {});
- auth.setJwtVerificationEnabled(false);
- }
- else {
- logDebug("auth.setJwtVerificationEnabled not available", {});
- }
- }
- }
- return defaultApp;
- })
- .when("firestore", (target) => {
- warnAboutFirestoreProd();
- return Proxied.getOriginal(target, "firestore");
- })
- .when("database", (target) => {
- warnAboutDatabaseProd();
- return Proxied.getOriginal(target, "database");
- })
- .when("auth", (target) => {
- warnAboutAuthProd();
- return Proxied.getOriginal(target, "auth");
- })
- .when("storage", (target) => {
- warnAboutStorageProd();
- return Proxied.getOriginal(target, "storage");
- })
- .finalize();
- require.cache[adminResolution.resolution] = Object.assign(require.cache[adminResolution.resolution], {
- exports: proxiedAdminModule,
- path: path.dirname(adminResolution.resolution),
- });
- logDebug("firebase-admin has been stubbed.", {
- adminResolution,
- });
- }
- function makeProxiedFirebaseApp(original) {
- const appProxy = new Proxied(original);
- return appProxy
- .when("firestore", (target) => {
- warnAboutFirestoreProd();
- return Proxied.getOriginal(target, "firestore");
- })
- .when("database", (target) => {
- warnAboutDatabaseProd();
- return Proxied.getOriginal(target, "database");
- })
- .when("auth", (target) => {
- warnAboutAuthProd();
- return Proxied.getOriginal(target, "auth");
- })
- .when("storage", (target) => {
- warnAboutStorageProd();
- return Proxied.getOriginal(target, "storage");
- })
- .finalize();
- }
- function warnAboutFirestoreProd() {
- if (process.env[constants_1.Constants.FIRESTORE_EMULATOR_HOST]) {
- return;
- }
- new types_1.EmulatorLog("WARN_ONCE", "runtime-status", "The Cloud Firestore emulator is not running, so calls to Firestore will affect production.").log();
- }
- function warnAboutDatabaseProd() {
- if (process.env[constants_1.Constants.FIREBASE_DATABASE_EMULATOR_HOST]) {
- return;
- }
- new types_1.EmulatorLog("WARN_ONCE", "runtime-status", "The Realtime Database emulator is not running, so calls to Realtime Database will affect production.").log();
- }
- function warnAboutAuthProd() {
- if (process.env[constants_1.Constants.FIREBASE_AUTH_EMULATOR_HOST]) {
- return;
- }
- new types_1.EmulatorLog("WARN_ONCE", "runtime-status", "The Firebase Authentication emulator is not running, so calls to Firebase Authentication will affect production.").log();
- }
- function warnAboutStorageProd() {
- if (process.env[constants_1.Constants.FIREBASE_STORAGE_EMULATOR_HOST]) {
- return;
- }
- new types_1.EmulatorLog("WARN_ONCE", "runtime-status", "The Firebase Storage emulator is not running, so calls to Firebase Storage will affect production.").log();
- }
- async function initializeFunctionsConfigHelper() {
- const functionsResolution = await assertResolveDeveloperNodeModule("firebase-functions");
- const localFunctionsModule = require(functionsResolution.resolution);
- logDebug("Checked functions.config()", {
- config: localFunctionsModule.config(),
- });
- const originalConfig = localFunctionsModule.config();
- const proxiedConfig = new Proxied(originalConfig)
- .any((parentConfig, parentKey) => {
- const isInternal = parentKey.startsWith("Symbol(") || parentKey.startsWith("inspect");
- if (!parentConfig[parentKey] && !isInternal) {
- new types_1.EmulatorLog("SYSTEM", "functions-config-missing-value", "", {
- key: parentKey,
- }).log();
- }
- return parentConfig[parentKey];
- })
- .finalize();
- const functionsModuleProxy = new Proxied(localFunctionsModule);
- const proxiedFunctionsModule = functionsModuleProxy
- .when("config", () => () => {
- return proxiedConfig;
- })
- .finalize();
- require.cache[functionsResolution.resolution] = Object.assign(require.cache[functionsResolution.resolution], {
- exports: proxiedFunctionsModule,
- path: path.dirname(functionsResolution.resolution),
- });
- logDebug("firebase-functions has been stubbed.", {
- functionsResolution,
- });
- }
- function rawBodySaver(req, res, buf) {
- req.rawBody = buf;
- }
- async function processBackground(trigger, reqBody, signature) {
- if (signature === "cloudevent") {
- return runCloudEvent(trigger, reqBody);
- }
- const data = reqBody.data;
- delete reqBody.data;
- const context = reqBody.context ? reqBody.context : reqBody;
- if (!reqBody.eventType || !reqBody.eventType.startsWith("google.storage")) {
- if (context.resource && context.resource.name) {
- logDebug("ProcessBackground: lifting resource.name from resource", context.resource);
- context.resource = context.resource.name;
- }
- }
- await runBackground(trigger, { data, context });
- }
- async function runFunction(func) {
- let caughtErr;
- try {
- await func();
- }
- catch (err) {
- caughtErr = err;
- }
- if (caughtErr) {
- throw caughtErr;
- }
- }
- async function runBackground(trigger, reqBody) {
- logDebug("RunBackground", reqBody);
- await runFunction(() => {
- return trigger(reqBody.data, reqBody.context);
- });
- }
- async function runCloudEvent(trigger, event) {
- logDebug("RunCloudEvent", event);
- await runFunction(() => {
- return trigger(event);
- });
- }
- async function runHTTPS(trigger, args) {
- if (args.length < 2) {
- throw new Error("Function must be passed 2 args.");
- }
- await runFunction(() => {
- return trigger(args[0], args[1]);
- });
- }
- async function moduleResolutionDetective(error) {
- const clues = {
- tsconfigJSON: await requireAsync("./tsconfig.json", { paths: [process.cwd()] }).catch(noOp),
- packageJSON: await requireAsync("./package.json", { paths: [process.cwd()] }).catch(noOp),
- };
- const isPotentially = {
- typescript: false,
- uncompiled: false,
- wrong_directory: false,
- };
- isPotentially.typescript = !!clues.tsconfigJSON;
- isPotentially.wrong_directory = !clues.packageJSON;
- isPotentially.uncompiled = !!_.get(clues.packageJSON, "scripts.build", false);
- new types_1.EmulatorLog("SYSTEM", "function-code-resolution-failed", "", {
- isPotentially,
- error: error.stack,
- }).log();
- }
- function logDebug(msg, data) {
- new types_1.EmulatorLog("DEBUG", "runtime-status", `[${process.pid}] ${msg}`, data).log();
- }
- async function initializeRuntime() {
- FUNCTION_DEBUG_MODE = process.env.FUNCTION_DEBUG_MODE || "";
- if (!FUNCTION_DEBUG_MODE) {
- FUNCTION_TARGET_NAME = process.env.FUNCTION_TARGET || "";
- if (!FUNCTION_TARGET_NAME) {
- new types_1.EmulatorLog("FATAL", "runtime-status", `Environment variable FUNCTION_TARGET cannot be empty. This shouldn't happen.`).log();
- await flushAndExit(1);
- }
- FUNCTION_SIGNATURE = process.env.FUNCTION_SIGNATURE_TYPE || "";
- if (!FUNCTION_SIGNATURE) {
- new types_1.EmulatorLog("FATAL", "runtime-status", `Environment variable FUNCTION_SIGNATURE_TYPE cannot be empty. This shouldn't happen.`).log();
- await flushAndExit(1);
- }
- }
- const verified = await verifyDeveloperNodeModules();
- if (!verified) {
- new types_1.EmulatorLog("INFO", "runtime-status", `Your functions could not be parsed due to an issue with your node_modules (see above)`).log();
- return;
- }
- initializeRuntimeConfig();
- initializeNetworkFiltering();
- await initializeFunctionsConfigHelper();
- await initializeFirebaseFunctionsStubs();
- await initializeFirebaseAdminStubs();
- }
- async function loadTriggers() {
- let triggerModule;
- try {
- triggerModule = require(process.cwd());
- }
- catch (err) {
- if (err.code !== "ERR_REQUIRE_ESM") {
- await moduleResolutionDetective(err);
- throw err;
- }
- const modulePath = require.resolve(process.cwd());
- const moduleURL = (0, url_1.pathToFileURL)(modulePath).href;
- triggerModule = await dynamicImport(moduleURL);
- }
- return triggerModule;
- }
- async function flushAndExit(code) {
- await types_1.EmulatorLog.waitForFlush();
- process.exit(code);
- }
- async function handleMessage(message) {
- let debug;
- try {
- debug = JSON.parse(message);
- }
- catch (e) {
- new types_1.EmulatorLog("FATAL", "runtime-error", `Got unexpected message body: ${message}`).log();
- await flushAndExit(1);
- return;
- }
- if (FUNCTION_DEBUG_MODE) {
- if (debug) {
- FUNCTION_TARGET_NAME = debug.functionTarget;
- FUNCTION_SIGNATURE = debug.functionSignature;
- }
- else {
- new types_1.EmulatorLog("WARN", "runtime-warning", "Expected debug payload while in debug mode.");
- }
- }
- }
- async function main() {
- let lastSignal = new Date().getTime();
- let signalCount = 0;
- process.on("SIGINT", () => {
- const now = new Date().getTime();
- if (now - lastSignal < 100) {
- return;
- }
- signalCount = signalCount + 1;
- lastSignal = now;
- if (signalCount >= 2) {
- process.exit(1);
- }
- });
- await initializeRuntime();
- try {
- functionModule = await loadTriggers();
- }
- catch (e) {
- new types_1.EmulatorLog("FATAL", "runtime-status", `Failed to initialize and load triggers. This shouldn't happen: ${e.message}`).log();
- await flushAndExit(1);
- }
- const app = express();
- app.enable("trust proxy");
- app.use(bodyParser.json({
- limit: "10mb",
- verify: rawBodySaver,
- }));
- app.use(bodyParser.text({
- limit: "10mb",
- verify: rawBodySaver,
- }));
- app.use(bodyParser.urlencoded({
- extended: true,
- limit: "10mb",
- verify: rawBodySaver,
- }));
- app.use(bodyParser.raw({
- type: "*/*",
- limit: "10mb",
- verify: rawBodySaver,
- }));
- app.get("/__/health", (req, res) => {
- res.status(200).send();
- });
- app.all("/favicon.ico|/robots.txt", (req, res) => {
- res.status(404).send();
- });
- app.all(`/*`, async (req, res) => {
- try {
- new types_1.EmulatorLog("INFO", "runtime-status", `Beginning execution of "${FUNCTION_TARGET_NAME}"`).log();
- const trigger = FUNCTION_TARGET_NAME.split(".").reduce((mod, functionTargetPart) => {
- return mod === null || mod === void 0 ? void 0 : mod[functionTargetPart];
- }, functionModule);
- if (!trigger) {
- throw new Error(`Failed to find function ${FUNCTION_TARGET_NAME} in the loaded module`);
- }
- const startHrTime = process.hrtime();
- res.on("finish", () => {
- const elapsedHrTime = process.hrtime(startHrTime);
- new types_1.EmulatorLog("INFO", "runtime-status", `Finished "${FUNCTION_TARGET_NAME}" in ${elapsedHrTime[0] * 1000 + elapsedHrTime[1] / 1000000}ms`).log();
- });
- switch (FUNCTION_SIGNATURE) {
- case "event":
- case "cloudevent":
- const rawBody = req.rawBody;
- let reqBody = JSON.parse(rawBody.toString());
- if (types_2.EventUtils.isBinaryCloudEvent(req)) {
- reqBody = types_2.EventUtils.extractBinaryCloudEventContext(req);
- reqBody.data = req.body;
- }
- await processBackground(trigger, reqBody, FUNCTION_SIGNATURE);
- res.send({ status: "acknowledged" });
- break;
- case "http":
- await runHTTPS(trigger, [req, res]);
- }
- }
- catch (err) {
- new types_1.EmulatorLog("FATAL", "runtime-error", err.stack ? err.stack : err).log();
- res.status(500).send(err.message);
- }
- });
- const server = app.listen(process.env.PORT, () => {
- logDebug(`Listening to port: ${process.env.PORT}`);
- });
- if (!FUNCTION_DEBUG_MODE) {
- let timeout = process.env.FUNCTIONS_EMULATOR_TIMEOUT_SECONDS || "60";
- if (timeout.endsWith("s")) {
- timeout = timeout.slice(0, -1);
- }
- const timeoutMs = parseInt(timeout, 10) * 1000;
- server.setTimeout(timeoutMs, () => {
- new types_1.EmulatorLog("FATAL", "runtime-error", `Your function timed out after ~${timeout}s. To configure this timeout, see
- https://firebase.google.com/docs/functions/manage-functions#set_timeout_and_memory_allocation.`).log();
- return flushAndExit(1);
- });
- }
- let messageHandlePromise = Promise.resolve();
- process.on("message", (message) => {
- messageHandlePromise = messageHandlePromise
- .then(() => {
- return handleMessage(message);
- })
- .catch((err) => {
- logDebug(`Error in handleMessage: ${message} => ${err}: ${err.stack}`);
- new types_1.EmulatorLog("FATAL", "runtime-error", err.message || err, err).log();
- return flushAndExit(1);
- });
- });
- }
- if (require.main === module) {
- main()
- .then(() => {
- logDebug("Functions runtime initialized.", {
- cwd: process.cwd(),
- node_version: process.versions.node,
- });
- })
- .catch((err) => {
- new types_1.EmulatorLog("FATAL", "runtime-error", err.message || err, err).log();
- return flushAndExit(1);
- });
- }
|