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.

213 lines (211 loc) • 7.47 kB
import { __export } from "../_virtual/rolldown_runtime.js"; import { NonRetriableError } from "../components/NonRetriableError.js"; import { z } from "zod/v3"; import stringify from "json-stringify-safe"; import { deserializeError, errorConstructors, serializeError } from "serialize-error-cjs"; //#region src/helpers/errors.ts var errors_exports = /* @__PURE__ */ __export({ ErrCode: () => ErrCode, OutgoingResultError: () => OutgoingResultError, deserializeError: () => deserializeError$1, fixEventKeyMissingSteps: () => fixEventKeyMissingSteps, getErrorMessage: () => getErrorMessage, isSerializedError: () => isSerializedError, rethrowError: () => rethrowError, serializeError: () => serializeError$1 }); const SERIALIZED_KEY = "__serialized"; const SERIALIZED_VALUE = true; /** * Add first-class support for certain errors that we control, in addition to * built-in errors such as `TypeError`. * * Adding these allows these non-standard errors to be correctly serialized, * sent to Inngest, then deserialized back into the correct error type for users * to react to correctly. * * Note that these errors only support `message?: string | undefined` as the * input; more custom errors are not supported with this current strategy. */ errorConstructors.set("NonRetriableError", NonRetriableError); /** * Serialise an error to a serialized JSON string. * * Errors do not serialise nicely to JSON, so we use this function to convert * them to a serialized JSON string. Doing this is also non-trivial for some * errors, so we use the `serialize-error` package to do it for us. * * See {@link https://www.npmjs.com/package/serialize-error} * * This function is a small wrapper around that package to also add a `type` * property to the serialised error, so that we can distinguish between * serialised errors and other objects. * * Will not reserialise existing serialised errors. */ const serializeError$1 = (subject, allowUnknown = false) => { try { const existingSerializedError = isSerializedError(subject); if (existingSerializedError) return existingSerializedError; if (typeof subject === "object" && subject !== null) { const serializedErr = serializeError(subject); if (!serializedErr.name && allowUnknown) return subject; const ret = { ...serializedErr, name: serializedErr.name || "Error", message: serializedErr.message || stringify(subject) || "Unknown error; error serialization could not find a message.", stack: serializedErr.stack || "", [SERIALIZED_KEY]: SERIALIZED_VALUE }; let target = ret; const maxDepth = 5; for (let i = 0; i < maxDepth; i++) { if (typeof target === "object" && target !== null && "cause" in target && target.cause) { target = target.cause = serializeError$1(target.cause, true); continue; } break; } return ret; } throw new Error("Error is not an object; strange throw value."); } catch { if (allowUnknown) return subject; try { return { ...serializeError$1(new Error(typeof subject === "string" ? subject : stringify(subject)), false), stack: "", [SERIALIZED_KEY]: SERIALIZED_VALUE }; } catch { return { name: "Could not serialize source error", message: "Serializing the source error failed.", stack: "", [SERIALIZED_KEY]: SERIALIZED_VALUE }; } } }; /** * Check if an object or a string is a serialised error created by * {@link serializeError}. */ const isSerializedError = (value) => { try { if (typeof value === "string") { const parsed = z.object({ [SERIALIZED_KEY]: z.literal(SERIALIZED_VALUE), name: z.enum([...Array.from(errorConstructors.keys())]), message: z.string(), stack: z.string() }).passthrough().safeParse(JSON.parse(value)); if (parsed.success) return parsed.data; } if (typeof value === "object" && value !== null) { if (Object.hasOwn(value, SERIALIZED_KEY) && value[SERIALIZED_KEY] === SERIALIZED_VALUE) return value; } } catch {} }; /** * Deserialise an error created by {@link serializeError}. * * Ensures we only deserialise errors that meet a minimum level of * applicability, inclusive of error handling to ensure that badly serialized * errors are still handled. */ const deserializeError$1 = (subject, allowUnknown = false) => { const requiredFields = ["name", "message"]; try { if (!requiredFields.every((field) => { return Object.hasOwn(subject, field); })) throw new Error(); const deserializedErr = deserializeError(subject); if ("cause" in deserializedErr) deserializedErr.cause = deserializeError$1(deserializedErr.cause, true); return deserializedErr; } catch { if (allowUnknown) return subject; const err = /* @__PURE__ */ new Error("Unknown error; could not reserialize"); /** * Remove the stack so that it's not misleadingly shown as the Inngest * internals. */ err.stack = void 0; return err; } }; let ErrCode = /* @__PURE__ */ function(ErrCode$1) { ErrCode$1["NESTING_STEPS"] = "NESTING_STEPS"; /** * Legacy v0 execution error code for when a function has changed and no * longer matches its in-progress state. * * @deprecated Not for use in latest execution method. */ ErrCode$1["NON_DETERMINISTIC_FUNCTION"] = "NON_DETERMINISTIC_FUNCTION"; /** * Legacy v0 execution error code for when a function is found to be using * async actions after memoziation has occurred, which v0 doesn't support. * * @deprecated Not for use in latest execution method. */ ErrCode$1["ASYNC_DETECTED_AFTER_MEMOIZATION"] = "ASYNC_DETECTED_AFTER_MEMOIZATION"; /** * Legacy v0 execution error code for when a function is found to be using * steps after a non-step async action has occurred. * * @deprecated Not for use in latest execution method. */ ErrCode$1["STEP_USED_AFTER_ASYNC"] = "STEP_USED_AFTER_ASYNC"; ErrCode$1["AUTOMATIC_PARALLEL_INDEXING"] = "AUTOMATIC_PARALLEL_INDEXING"; ErrCode$1["NONDETERMINISTIC_STEPS"] = "NONDETERMINISTIC_STEPS"; return ErrCode$1; }({}); /** * Given an `unknown` object, retrieve the `message` property from it, or fall * back to the `fallback` string if it doesn't exist or is empty. */ const getErrorMessage = (err, fallback) => { const { message } = z.object({ message: z.string().min(1) }).catch({ message: fallback }).parse(err); return message; }; const fixEventKeyMissingSteps = ["Set the `INNGEST_EVENT_KEY` environment variable", `Pass a key to the \`new Inngest()\` constructor using the \`eventKey\` option`]; /** * An error that, when thrown, indicates internally that an outgoing operation * contains an error. * * We use this because serialized `data` sent back to Inngest may differ from * the error instance itself due to middleware. * * @internal */ var OutgoingResultError = class extends Error { result; constructor(result) { super("OutgoingOpError"); this.result = result; } }; /** * Create a function that will rethrow an error with a prefix added to the * message. * * Useful for adding context to errors that are rethrown. * * @example * ```ts * await doSomeAction().catch(rethrowError("Failed to do some action")); * ``` */ const rethrowError = (prefix) => { return (err) => { try { err.message &&= `${prefix}; ${err.message}`; } catch (_noopErr) {} finally { throw err; } }; }; //#endregion export { ErrCode, deserializeError$1 as deserializeError, errors_exports, fixEventKeyMissingSteps, getErrorMessage, rethrowError, serializeError$1 as serializeError }; //# sourceMappingURL=errors.js.map