UNPKG

inngest

Version:

Official SDK for Inngest.com. Inngest is the reliability layer for modern applications. Inngest combines durable execution, events, and queues into a zero-infra platform with built-in observability.

1 lines 11.2 kB
{"version":3,"file":"functions.cjs","names":["debugPrefix","z","PREFERRED_ASYNC_EXECUTION_VERSION","version: ExecutionVersion | undefined","sdkDecided: boolean","stepSchema","err","formatLogMessage","ok","why: string | undefined","ZodError"],"sources":["../../src/helpers/functions.ts"],"sourcesContent":["import Debug from \"debug\";\nimport { ZodError, z } from \"zod/v3\";\nimport type { InngestApi } from \"../api/api.ts\";\nimport { stepSchema } from \"../api/schema.ts\";\nimport { PREFERRED_ASYNC_EXECUTION_VERSION } from \"../components/execution/InngestExecution.ts\";\nimport type { Logger } from \"../middleware/logger.ts\";\nimport { err, ok, type Result } from \"../types.ts\";\nimport { debugPrefix, type ExecutionVersion } from \"./consts.ts\";\nimport { formatLogMessage } from \"./log.ts\";\nimport type { Await } from \"./types.ts\";\n\nconst devDebug = Debug(`${debugPrefix}:functions`);\n\n/**\n * Wraps a function with a cache. When the returned function is run, it will\n * cache the result and return it on subsequent calls.\n */\n// biome-ignore lint/suspicious/noExplicitAny: intentional\nexport const cacheFn = <T extends (...args: any[]) => any>(fn: T): T => {\n const key = \"value\";\n const cache = new Map<typeof key, unknown>();\n\n return ((...args) => {\n if (!cache.has(key)) {\n cache.set(key, fn(...args));\n }\n\n return cache.get(key);\n }) as T;\n};\n\n/**\n * Given an array of functions, return a new function that will run each\n * function in series and return the result of the final function. Regardless of\n * if the functions are synchronous or asynchronous, they'll be made into an\n * async promise chain.\n *\n * If an error is thrown, the waterfall will stop and return the error.\n *\n * Because this needs to support both sync and async functions, it only allows\n * functions that accept a single argument.\n */\n// biome-ignore lint/suspicious/noExplicitAny: intentional\nexport const waterfall = <TFns extends ((arg?: any) => any)[]>(\n fns: TFns,\n\n /**\n * A function that transforms the result of each function in the waterfall,\n * ready for the next function.\n *\n * Will not be called on the final function.\n */\n // biome-ignore lint/suspicious/noExplicitAny: intentional\n transform?: (prev: any, output: any) => any,\n): ((...args: Parameters<TFns[number]>) => Promise<Await<TFns[number]>>) => {\n return (...args) => {\n const chain = fns.reduce(async (acc, fn) => {\n const prev = await acc;\n const output = (await fn(prev)) as Promise<Await<TFns[number]>>;\n\n if (transform) {\n return await transform(prev, output);\n }\n\n if (typeof output === \"undefined\") {\n return prev;\n }\n\n return output;\n }, Promise.resolve(args[0]));\n\n return chain;\n };\n};\n\n/**\n * Given a value `v`, return `v` if it's not undefined, otherwise return `null`.\n */\nexport const undefinedToNull = (v: unknown) => {\n const isUndefined = typeof v === \"undefined\";\n return isUndefined ? null : v;\n};\n\nexport const createVersionSchema = (internalLogger: Logger) =>\n z\n .literal(-1)\n .or(z.literal(0))\n .or(z.literal(1))\n .or(z.literal(2))\n .optional()\n .transform<{ version: ExecutionVersion; sdkDecided: boolean }>((v) => {\n if (typeof v === \"undefined\") {\n devDebug(\"No request version specified by executor; using default\");\n\n return {\n sdkDecided: true,\n version: PREFERRED_ASYNC_EXECUTION_VERSION,\n };\n }\n\n if (v === 0) {\n internalLogger.error(\"V0 execution version is no longer supported\"); // TODO: improve?\n throw new Error(\"V0 execution version is no longer supported\");\n }\n\n if (v === -1) {\n return {\n sdkDecided: true,\n version: PREFERRED_ASYNC_EXECUTION_VERSION,\n };\n }\n\n return {\n sdkDecided: false,\n version: v,\n };\n });\n\nexport const parseFnData = (\n data: unknown,\n headerVersion: unknown | undefined,\n internalLogger: Logger,\n) => {\n const versionSchema = createVersionSchema(internalLogger);\n const fnDataVersionSchema = z.object({ version: versionSchema });\n let version: ExecutionVersion | undefined;\n let sdkDecided: boolean = true;\n\n try {\n if (typeof headerVersion !== \"undefined\") {\n try {\n const res = versionSchema.parse(headerVersion);\n version = res.version;\n sdkDecided = res.sdkDecided;\n } catch {\n // no-op\n }\n }\n\n if (typeof version === \"undefined\") {\n const parsedVersionData = fnDataVersionSchema.parse(data);\n version = parsedVersionData.version.version;\n sdkDecided = parsedVersionData.version.sdkDecided;\n }\n\n return {\n version,\n sdkDecided,\n ...z\n .object({\n event: z.record(z.any()),\n events: z.array(z.record(z.any())).default([]),\n steps: stepSchema,\n ctx: z\n .object({\n run_id: z.string(),\n fn_id: z.string().optional(),\n attempt: z.number().default(0),\n max_attempts: z.number().optional(),\n disable_immediate_execution: z.boolean().default(false),\n use_api: z.boolean().default(false),\n qi_id: z.string().optional(),\n stack: z\n .object({\n stack: z\n .array(z.string())\n .nullable()\n .transform((v) => (Array.isArray(v) ? v : [])),\n current: z.number(),\n })\n .optional()\n .nullable(),\n })\n .optional()\n .nullable(),\n })\n .parse(data),\n } as const;\n } catch (err) {\n throw new Error(parseFailureErr(err));\n }\n};\nexport type FnData = ReturnType<typeof parseFnData>;\n\ntype ParseErr = string;\nexport const fetchAllFnData = async ({\n data,\n api,\n logger,\n}: {\n data: FnData;\n api: InngestApi;\n logger: Logger;\n}): Promise<Result<FnData, ParseErr>> => {\n const result = { ...data };\n\n try {\n if (result.ctx?.use_api) {\n if (!result.ctx?.run_id) {\n return err(\n formatLogMessage({\n message: \"Failed to attempt retrieving data from API\",\n explanation:\n \"Function execution can't continue. run_id is missing from context.\",\n }),\n );\n }\n\n const [evtResp, stepResp] = await Promise.all([\n api.getRunBatch(result.ctx.run_id),\n api.getRunSteps(result.ctx.run_id),\n ]);\n\n if (evtResp.ok) {\n result.events = evtResp.value;\n } else {\n return err(\n formatLogMessage({\n message: \"Failed to retrieve list of events\",\n explanation: `Function execution can't continue.${evtResp.error?.error ? ` ${evtResp.error.error}` : \"\"}`,\n }),\n );\n }\n\n if (stepResp.ok) {\n result.steps = stepResp.value;\n } else {\n return err(\n formatLogMessage({\n message: \"Failed to retrieve steps for function run\",\n explanation: `Function execution can't continue.${stepResp.error?.error ? ` ${stepResp.error.error}` : \"\"}`,\n }),\n );\n }\n }\n\n // If we don't have a stack here, we need to at least set something.\n // TODO We should be passed this by the steps API.\n const stepIds = Object.keys(result.steps || {});\n if (stepIds.length && !result.ctx?.stack?.stack?.length) {\n result.ctx = {\n ...(result.ctx as NonNullable<typeof result.ctx>),\n stack: {\n stack: stepIds,\n current: stepIds.length - 1,\n },\n };\n }\n\n return ok(result);\n } catch (error) {\n logger.error({ err: error }, \"Failed to fetch all function data\");\n\n return err(parseFailureErr(error));\n }\n};\n\nconst parseFailureErr = (err: unknown) => {\n let why: string | undefined;\n if (err instanceof ZodError) {\n why = err.toString();\n }\n\n return formatLogMessage({\n message: \"Failed to parse data from executor\",\n explanation: `Function execution can't continue.${why ? ` ${why}` : \"\"}`,\n action:\n \"Make sure that your API is set up to parse incoming request bodies as JSON, like body-parser for Express.\",\n docs: \"https://expressjs.com/en/resources/middleware/body-parser.html\",\n });\n};\n"],"mappings":"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"}