inngest 3.48.2-pr-1209.0 → 3.48.2-pr-1209.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/helpers/errors.js +3 -3
- package/helpers/errors.js.map +1 -1
- package/helpers/strings.js +4 -4
- package/helpers/strings.js.map +1 -1
- package/package.json +1 -1
- package/version.cjs +1 -1
- package/version.cjs.map +1 -1
- package/version.d.cts +1 -1
- package/version.d.ts +1 -1
- package/version.js +1 -1
- package/version.js.map +1 -1
package/helpers/errors.js
CHANGED
|
@@ -2,7 +2,7 @@ import { __export } from "../_virtual/rolldown_runtime.js";
|
|
|
2
2
|
import { NonRetriableError } from "../components/NonRetriableError.js";
|
|
3
3
|
import { z } from "zod/v3";
|
|
4
4
|
import chalk from "chalk";
|
|
5
|
-
import
|
|
5
|
+
import safeStringify from "json-stringify-safe";
|
|
6
6
|
import { deserializeError, errorConstructors, serializeError } from "serialize-error-cjs";
|
|
7
7
|
import stripAnsi from "strip-ansi";
|
|
8
8
|
|
|
@@ -60,7 +60,7 @@ const serializeError$1 = (subject, allowUnknown = false) => {
|
|
|
60
60
|
const ret = {
|
|
61
61
|
...serializedErr,
|
|
62
62
|
name: serializedErr.name || "Error",
|
|
63
|
-
message: serializedErr.message ||
|
|
63
|
+
message: serializedErr.message || safeStringify(subject) || "Unknown error; error serialization could not find a message.",
|
|
64
64
|
stack: serializedErr.stack || "",
|
|
65
65
|
[SERIALIZED_KEY]: SERIALIZED_VALUE
|
|
66
66
|
};
|
|
@@ -80,7 +80,7 @@ const serializeError$1 = (subject, allowUnknown = false) => {
|
|
|
80
80
|
if (allowUnknown) return subject;
|
|
81
81
|
try {
|
|
82
82
|
return {
|
|
83
|
-
...serializeError$1(new Error(typeof subject === "string" ? subject :
|
|
83
|
+
...serializeError$1(new Error(typeof subject === "string" ? subject : safeStringify(subject)), false),
|
|
84
84
|
stack: "",
|
|
85
85
|
[SERIALIZED_KEY]: SERIALIZED_VALUE
|
|
86
86
|
};
|
package/helpers/errors.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"errors.js","names":["serializeError","cjsSerializeError","target: unknown","deserializeError","requiredFields: (keyof SerializedError)[]","cjsDeserializeError"],"sources":["../../src/helpers/errors.ts"],"sourcesContent":["import chalk from \"chalk\";\nimport stringify from \"json-stringify-safe\";\nimport {\n type SerializedError as CjsSerializedError,\n deserializeError as cjsDeserializeError,\n serializeError as cjsSerializeError,\n errorConstructors,\n} from \"serialize-error-cjs\";\nimport stripAnsi from \"strip-ansi\";\nimport { z } from \"zod/v3\";\nimport type { Inngest } from \"../components/Inngest.ts\";\nimport { NonRetriableError } from \"../components/NonRetriableError.ts\";\nimport type { ClientOptions, OutgoingOp } from \"../types.ts\";\n\nconst SERIALIZED_KEY = \"__serialized\";\nconst SERIALIZED_VALUE = true;\n\n/**\n * Add first-class support for certain errors that we control, in addition to\n * built-in errors such as `TypeError`.\n *\n * Adding these allows these non-standard errors to be correctly serialized,\n * sent to Inngest, then deserialized back into the correct error type for users\n * to react to correctly.\n *\n * Note that these errors only support `message?: string | undefined` as the\n * input; more custom errors are not supported with this current strategy.\n */\nerrorConstructors.set(\n \"NonRetriableError\",\n NonRetriableError as ErrorConstructor,\n);\n\nexport interface SerializedError extends Readonly<CjsSerializedError> {\n readonly [SERIALIZED_KEY]: typeof SERIALIZED_VALUE;\n}\n\n/**\n * Serialise an error to a serialized JSON string.\n *\n * Errors do not serialise nicely to JSON, so we use this function to convert\n * them to a serialized JSON string. Doing this is also non-trivial for some\n * errors, so we use the `serialize-error` package to do it for us.\n *\n * See {@link https://www.npmjs.com/package/serialize-error}\n *\n * This function is a small wrapper around that package to also add a `type`\n * property to the serialised error, so that we can distinguish between\n * serialised errors and other objects.\n *\n * Will not reserialise existing serialised errors.\n */\nexport const serializeError = <\n TAllowUnknown extends boolean = false,\n TOutput extends TAllowUnknown extends true\n ? unknown\n : SerializedError = TAllowUnknown extends true ? unknown : SerializedError,\n>(\n /**\n * The suspected error to serialize.\n */\n subject: unknown,\n\n /**\n * If `true` and the error is not serializable, will return the original value\n * as `unknown` instead of coercing it to a serialized error.\n */\n allowUnknown: TAllowUnknown = false as TAllowUnknown,\n): TOutput => {\n try {\n // Try to understand if this is already done.\n // Will handle stringified errors.\n const existingSerializedError = isSerializedError(subject);\n\n if (existingSerializedError) {\n return existingSerializedError as TOutput;\n }\n\n if (typeof subject === \"object\" && subject !== null) {\n // Is an object, so let's try and serialize it.\n const serializedErr = cjsSerializeError(subject as Error);\n\n // Not a proper error was caught, so give us a chance to return `unknown`.\n if (!serializedErr.name && allowUnknown) {\n return subject as TOutput;\n }\n\n // Serialization can succeed but assign no name or message, so we'll\n // map over the result here to ensure we have everything.\n // We'll just stringify the entire subject for the message, as this at\n // least provides some context for the user.\n const ret = {\n // Ensure we spread to also capture additional properties such as\n // `cause`.\n ...serializedErr,\n\n name: serializedErr.name || \"Error\",\n message:\n serializedErr.message ||\n stringify(subject) ||\n \"Unknown error; error serialization could not find a message.\",\n stack: serializedErr.stack || \"\",\n [SERIALIZED_KEY]: SERIALIZED_VALUE,\n } as const;\n\n // If we have a cause, make sure we recursively serialize them too. We are\n // lighter with causes though; attempt to recursively serialize them, but\n // stop if we find something that doesn't work and just return `unknown`.\n let target: unknown = ret;\n const maxDepth = 5;\n for (let i = 0; i < maxDepth; i++) {\n if (\n typeof target === \"object\" &&\n target !== null &&\n \"cause\" in target &&\n target.cause\n ) {\n target = target.cause = serializeError(target.cause, true);\n continue;\n }\n\n break;\n }\n\n return ret as TOutput;\n }\n\n // If it's not an object, it's hard to parse this as an Error. In this case,\n // we'll throw an error to start attempting backup strategies.\n throw new Error(\"Error is not an object; strange throw value.\");\n } catch {\n if (allowUnknown) {\n // If we are allowed to return unknown, we'll just return the original\n // value.\n return subject as TOutput;\n }\n\n try {\n // If serialization fails, fall back to a regular Error and use the\n // original object as the message for an Error. We don't know what this\n // object looks like, so we can't do anything else with it.\n return {\n ...serializeError(\n new Error(typeof subject === \"string\" ? subject : stringify(subject)),\n false,\n ),\n // Remove the stack; it's not relevant here\n stack: \"\",\n [SERIALIZED_KEY]: SERIALIZED_VALUE,\n } as TOutput;\n } catch {\n // If this failed, then stringifying the object also failed, so we'll just\n // return a completely generic error.\n // Failing to stringify the object is very unlikely.\n return {\n name: \"Could not serialize source error\",\n message: \"Serializing the source error failed.\",\n stack: \"\",\n [SERIALIZED_KEY]: SERIALIZED_VALUE,\n } as TOutput;\n }\n }\n};\n\n/**\n * Check if an object or a string is a serialised error created by\n * {@link serializeError}.\n */\nexport const isSerializedError = (\n value: unknown,\n): SerializedError | undefined => {\n try {\n if (typeof value === \"string\") {\n const parsed = z\n .object({\n [SERIALIZED_KEY]: z.literal(SERIALIZED_VALUE),\n name: z.enum([...Array.from(errorConstructors.keys())] as [\n string,\n ...string[],\n ]),\n message: z.string(),\n stack: z.string(),\n })\n .passthrough()\n .safeParse(JSON.parse(value));\n\n if (parsed.success) {\n return parsed.data as SerializedError;\n }\n }\n\n if (typeof value === \"object\" && value !== null) {\n const objIsSerializedErr =\n Object.hasOwn(value, SERIALIZED_KEY) &&\n (value as { [SERIALIZED_KEY]: unknown })[SERIALIZED_KEY] ===\n SERIALIZED_VALUE;\n\n if (objIsSerializedErr) {\n return value as SerializedError;\n }\n }\n } catch {\n // no-op; we'll return undefined if parsing failed, as it isn't a serialized\n // error\n }\n\n return;\n};\n\n/**\n * Deserialise an error created by {@link serializeError}.\n *\n * Ensures we only deserialise errors that meet a minimum level of\n * applicability, inclusive of error handling to ensure that badly serialized\n * errors are still handled.\n */\nexport const deserializeError = <\n TAllowUnknown extends boolean = false,\n TOutput extends TAllowUnknown extends true\n ? unknown\n : Error = TAllowUnknown extends true ? unknown : Error,\n>(\n subject: Partial<SerializedError>,\n allowUnknown: TAllowUnknown = false as TAllowUnknown,\n): TOutput => {\n const requiredFields: (keyof SerializedError)[] = [\"name\", \"message\"];\n\n try {\n const hasRequiredFields = requiredFields.every((field) => {\n return Object.hasOwn(subject, field);\n });\n\n if (!hasRequiredFields) {\n throw new Error();\n }\n\n const deserializedErr = cjsDeserializeError(subject as SerializedError);\n\n if (\"cause\" in deserializedErr) {\n deserializedErr.cause = deserializeError(\n deserializedErr.cause as Partial<SerializedError>,\n true,\n );\n }\n\n return deserializedErr as TOutput;\n } catch {\n if (allowUnknown) {\n // If we are allowed to return unknown, we'll just return the original\n // value.\n return subject as TOutput;\n }\n\n const err = new Error(\"Unknown error; could not reserialize\");\n\n /**\n * Remove the stack so that it's not misleadingly shown as the Inngest\n * internals.\n */\n err.stack = undefined;\n\n return err as TOutput;\n }\n};\n\nexport enum ErrCode {\n NESTING_STEPS = \"NESTING_STEPS\",\n\n /**\n * Legacy v0 execution error code for when a function has changed and no\n * longer matches its in-progress state.\n *\n * @deprecated Not for use in latest execution method.\n */\n NON_DETERMINISTIC_FUNCTION = \"NON_DETERMINISTIC_FUNCTION\",\n\n /**\n * Legacy v0 execution error code for when a function is found to be using\n * async actions after memoziation has occurred, which v0 doesn't support.\n *\n * @deprecated Not for use in latest execution method.\n */\n ASYNC_DETECTED_AFTER_MEMOIZATION = \"ASYNC_DETECTED_AFTER_MEMOIZATION\",\n\n /**\n * Legacy v0 execution error code for when a function is found to be using\n * steps after a non-step async action has occurred.\n *\n * @deprecated Not for use in latest execution method.\n */\n STEP_USED_AFTER_ASYNC = \"STEP_USED_AFTER_ASYNC\",\n\n AUTOMATIC_PARALLEL_INDEXING = \"AUTOMATIC_PARALLEL_INDEXING\",\n}\n\nexport interface PrettyError {\n /**\n * The type of message, used to decide on icon and color use.\n */\n type?: \"error\" | \"warn\";\n\n /**\n * A short, succinct description of what happened. Will be used as the error's\n * header, so should be short and to the point with no trailing punctuation.\n */\n whatHappened: string;\n\n /**\n * If applicable, provide a full sentence to reassure the user about certain\n * details, for example if an error occurred whilst uploading a file, but we\n * can assure the user that uploading succeeded and something internal failed.\n */\n reassurance?: string;\n\n /**\n * Tell the user why the error happened if we can. This should be a full\n * sentence or paragraph that explains the error in more detail, for example\n * to explain that a file failed to upload because it was too large and that\n * the maximum size is 10MB.\n */\n why?: string;\n\n /**\n * If applicable, tell the user what the consequences of the error are, for\n * example to tell them that their file was not uploaded and that they will\n * need to try again.\n */\n consequences?: string;\n\n /**\n * If we can, tell the user what they can do to fix the error now. This should\n * be a full sentence or paragraph that explains what the user can do to fix\n * the error, for example to tell them to try uploading a smaller file or\n * upgrade to a paid plan.\n */\n toFixNow?: string | string[];\n\n /**\n * If applicable, tell the user what to do if the error persists, they want\n * more information, or the fix we've given them doesn't work.\n *\n * This should be a full sentence or paragraph, and will likely refer users\n * to contact us for support, join our Discord, or read documentation.\n */\n otherwise?: string;\n\n /**\n * Add a stack trace to the message so that the user knows what line of code\n * the error is in relation to.\n */\n stack?: true;\n\n /**\n * If applicable, provide a code that the user can use to reference the error\n * when contacting support.\n */\n code?: ErrCode;\n}\n\nexport const prettyErrorSplitter =\n \"=================================================\";\n\n/**\n * Given an unknown `err`, mutate it to minify any pretty errors that it\n * contains.\n */\nexport const minifyPrettyError = <T>(err: T): T => {\n try {\n if (!isError(err)) {\n return err;\n }\n\n const isPrettyError = err.message.includes(prettyErrorSplitter);\n if (!isPrettyError) {\n return err;\n }\n\n const sanitizedMessage = stripAnsi(err.message);\n\n const message =\n sanitizedMessage.split(\" \")[1]?.split(\"\\n\")[0]?.trim() || err.message;\n const code =\n sanitizedMessage.split(\"\\n\\nCode: \")[1]?.split(\"\\n\\n\")[0]?.trim() ||\n undefined;\n\n err.message = [code, message].filter(Boolean).join(\" - \");\n\n if (err.stack) {\n const sanitizedStack = stripAnsi(err.stack);\n const stackRest = sanitizedStack\n .split(`${prettyErrorSplitter}\\n`)\n .slice(2)\n .join(\"\\n\");\n\n err.stack = `${err.name}: ${err.message}\\n${stackRest}`;\n }\n\n return err;\n } catch (_noopErr) {\n return err;\n }\n};\n\n/**\n * Given an `err`, return a boolean representing whether it is in the shape of\n * an `Error` or not.\n */\nconst isError = (err: unknown): err is Error => {\n try {\n if (err instanceof Error) {\n return true;\n }\n\n if (typeof err !== \"object\" || err === null) {\n return false;\n }\n\n const hasName = Object.hasOwn(err, \"name\");\n const hasMessage = Object.hasOwn(err, \"message\");\n\n return hasName && hasMessage;\n } catch (_noopErr) {\n return false;\n }\n};\n\n/**\n * Given an `unknown` object, retrieve the `message` property from it, or fall\n * back to the `fallback` string if it doesn't exist or is empty.\n */\nexport const getErrorMessage = (err: unknown, fallback: string): string => {\n const { message } = z\n .object({ message: z.string().min(1) })\n .catch({ message: fallback })\n .parse(err);\n\n return message;\n};\n\n/**\n * Given a {@link PrettyError}, return a nicely-formatted string ready to log\n * or throw.\n *\n * Useful for ensuring that errors are logged in a consistent, helpful format\n * across the SDK by prompting for key pieces of information.\n */\nexport const prettyError = ({\n type = \"error\",\n whatHappened,\n otherwise,\n reassurance,\n toFixNow,\n why,\n consequences,\n stack,\n code,\n}: PrettyError): string => {\n const { icon, colorFn } = (\n {\n error: { icon: \"❌\", colorFn: chalk.red },\n warn: { icon: \"⚠️\", colorFn: chalk.yellow },\n } satisfies Record<\n NonNullable<PrettyError[\"type\"]>,\n { icon: string; colorFn: (s: string) => string }\n >\n )[type];\n\n let header = `${icon} ${chalk.bold.underline(whatHappened.trim())}`;\n if (stack) {\n header +=\n \"\\n\" +\n [...(new Error().stack?.split(\"\\n\").slice(1).filter(Boolean) || [])].join(\n \"\\n\",\n );\n }\n\n let toFixNowStr =\n (Array.isArray(toFixNow)\n ? toFixNow\n .map((s) => s.trim())\n .filter(Boolean)\n .map((s, i) => `\\t${i + 1}. ${s}`)\n .join(\"\\n\")\n : toFixNow?.trim()) ?? \"\";\n\n if (Array.isArray(toFixNow) && toFixNowStr) {\n toFixNowStr = `To fix this, you can take one of the following courses of action:\\n\\n${toFixNowStr}`;\n }\n\n let body = [reassurance?.trim(), why?.trim(), consequences?.trim()]\n .filter(Boolean)\n .join(\" \");\n body += body ? `\\n\\n${toFixNowStr}` : toFixNowStr;\n\n const trailer = [otherwise?.trim()].filter(Boolean).join(\" \");\n\n const message = [\n prettyErrorSplitter,\n header,\n body,\n trailer,\n code ? `Code: ${code}` : \"\",\n prettyErrorSplitter,\n ]\n .filter(Boolean)\n .join(\"\\n\\n\");\n\n return colorFn(message);\n};\n\nexport const fixEventKeyMissingSteps = [\n \"Set the `INNGEST_EVENT_KEY` environment variable\",\n `Pass a key to the \\`new Inngest()\\` constructor using the \\`${\n \"eventKey\" satisfies keyof ClientOptions\n }\\` option`,\n `Use \\`inngest.${\"setEventKey\" satisfies keyof Inngest.Any}()\\` at runtime`,\n];\n\n/**\n * An error that, when thrown, indicates internally that an outgoing operation\n * contains an error.\n *\n * We use this because serialized `data` sent back to Inngest may differ from\n * the error instance itself due to middleware.\n *\n * @internal\n */\nexport class OutgoingResultError extends Error {\n public readonly result: Pick<OutgoingOp, \"data\" | \"error\">;\n\n constructor(result: Pick<OutgoingOp, \"data\" | \"error\">) {\n super(\"OutgoingOpError\");\n this.result = result;\n }\n}\n\n/**\n * Create a function that will rethrow an error with a prefix added to the\n * message.\n *\n * Useful for adding context to errors that are rethrown.\n *\n * @example\n * ```ts\n * await doSomeAction().catch(rethrowError(\"Failed to do some action\"));\n * ```\n */\n// biome-ignore lint/suspicious/noExplicitAny: <explanation>\nexport const rethrowError = (prefix: string): ((err: any) => never) => {\n return (err) => {\n try {\n err.message &&= `${prefix}; ${err.message}`;\n } catch (_noopErr) {\n // no-op\n } finally {\n // biome-ignore lint/correctness/noUnsafeFinally: <explanation>\n throw err;\n }\n };\n};\n\n/**\n * Legacy v0 execution error for functions that don't support mixing steps and\n * regular async actions.\n */\nexport const functionStoppedRunningErr = (code: ErrCode) => {\n return prettyError({\n whatHappened: \"Your function was stopped from running\",\n why: \"We detected a mix of asynchronous logic, some using step tooling and some not.\",\n consequences:\n \"This can cause unexpected behaviour when a function is paused and resumed and is therefore strongly discouraged; we stopped your function to ensure nothing unexpected happened!\",\n stack: true,\n toFixNow:\n \"Ensure that your function is either entirely step-based or entirely non-step-based, by either wrapping all asynchronous logic in `step.run()` calls or by removing all `step.*()` calls.\",\n otherwise:\n \"For more information on why step functions work in this manner, see https://www.inngest.com/docs/functions/multi-step#gotchas\",\n code,\n });\n};\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"errors.js","names":["serializeError","cjsSerializeError","stringify","target: unknown","deserializeError","requiredFields: (keyof SerializedError)[]","cjsDeserializeError"],"sources":["../../src/helpers/errors.ts"],"sourcesContent":["import chalk from \"chalk\";\nimport stringify from \"json-stringify-safe\";\nimport {\n type SerializedError as CjsSerializedError,\n deserializeError as cjsDeserializeError,\n serializeError as cjsSerializeError,\n errorConstructors,\n} from \"serialize-error-cjs\";\nimport stripAnsi from \"strip-ansi\";\nimport { z } from \"zod/v3\";\nimport type { Inngest } from \"../components/Inngest.ts\";\nimport { NonRetriableError } from \"../components/NonRetriableError.ts\";\nimport type { ClientOptions, OutgoingOp } from \"../types.ts\";\n\nconst SERIALIZED_KEY = \"__serialized\";\nconst SERIALIZED_VALUE = true;\n\n/**\n * Add first-class support for certain errors that we control, in addition to\n * built-in errors such as `TypeError`.\n *\n * Adding these allows these non-standard errors to be correctly serialized,\n * sent to Inngest, then deserialized back into the correct error type for users\n * to react to correctly.\n *\n * Note that these errors only support `message?: string | undefined` as the\n * input; more custom errors are not supported with this current strategy.\n */\nerrorConstructors.set(\n \"NonRetriableError\",\n NonRetriableError as ErrorConstructor,\n);\n\nexport interface SerializedError extends Readonly<CjsSerializedError> {\n readonly [SERIALIZED_KEY]: typeof SERIALIZED_VALUE;\n}\n\n/**\n * Serialise an error to a serialized JSON string.\n *\n * Errors do not serialise nicely to JSON, so we use this function to convert\n * them to a serialized JSON string. Doing this is also non-trivial for some\n * errors, so we use the `serialize-error` package to do it for us.\n *\n * See {@link https://www.npmjs.com/package/serialize-error}\n *\n * This function is a small wrapper around that package to also add a `type`\n * property to the serialised error, so that we can distinguish between\n * serialised errors and other objects.\n *\n * Will not reserialise existing serialised errors.\n */\nexport const serializeError = <\n TAllowUnknown extends boolean = false,\n TOutput extends TAllowUnknown extends true\n ? unknown\n : SerializedError = TAllowUnknown extends true ? unknown : SerializedError,\n>(\n /**\n * The suspected error to serialize.\n */\n subject: unknown,\n\n /**\n * If `true` and the error is not serializable, will return the original value\n * as `unknown` instead of coercing it to a serialized error.\n */\n allowUnknown: TAllowUnknown = false as TAllowUnknown,\n): TOutput => {\n try {\n // Try to understand if this is already done.\n // Will handle stringified errors.\n const existingSerializedError = isSerializedError(subject);\n\n if (existingSerializedError) {\n return existingSerializedError as TOutput;\n }\n\n if (typeof subject === \"object\" && subject !== null) {\n // Is an object, so let's try and serialize it.\n const serializedErr = cjsSerializeError(subject as Error);\n\n // Not a proper error was caught, so give us a chance to return `unknown`.\n if (!serializedErr.name && allowUnknown) {\n return subject as TOutput;\n }\n\n // Serialization can succeed but assign no name or message, so we'll\n // map over the result here to ensure we have everything.\n // We'll just stringify the entire subject for the message, as this at\n // least provides some context for the user.\n const ret = {\n // Ensure we spread to also capture additional properties such as\n // `cause`.\n ...serializedErr,\n\n name: serializedErr.name || \"Error\",\n message:\n serializedErr.message ||\n stringify(subject) ||\n \"Unknown error; error serialization could not find a message.\",\n stack: serializedErr.stack || \"\",\n [SERIALIZED_KEY]: SERIALIZED_VALUE,\n } as const;\n\n // If we have a cause, make sure we recursively serialize them too. We are\n // lighter with causes though; attempt to recursively serialize them, but\n // stop if we find something that doesn't work and just return `unknown`.\n let target: unknown = ret;\n const maxDepth = 5;\n for (let i = 0; i < maxDepth; i++) {\n if (\n typeof target === \"object\" &&\n target !== null &&\n \"cause\" in target &&\n target.cause\n ) {\n target = target.cause = serializeError(target.cause, true);\n continue;\n }\n\n break;\n }\n\n return ret as TOutput;\n }\n\n // If it's not an object, it's hard to parse this as an Error. In this case,\n // we'll throw an error to start attempting backup strategies.\n throw new Error(\"Error is not an object; strange throw value.\");\n } catch {\n if (allowUnknown) {\n // If we are allowed to return unknown, we'll just return the original\n // value.\n return subject as TOutput;\n }\n\n try {\n // If serialization fails, fall back to a regular Error and use the\n // original object as the message for an Error. We don't know what this\n // object looks like, so we can't do anything else with it.\n return {\n ...serializeError(\n new Error(typeof subject === \"string\" ? subject : stringify(subject)),\n false,\n ),\n // Remove the stack; it's not relevant here\n stack: \"\",\n [SERIALIZED_KEY]: SERIALIZED_VALUE,\n } as TOutput;\n } catch {\n // If this failed, then stringifying the object also failed, so we'll just\n // return a completely generic error.\n // Failing to stringify the object is very unlikely.\n return {\n name: \"Could not serialize source error\",\n message: \"Serializing the source error failed.\",\n stack: \"\",\n [SERIALIZED_KEY]: SERIALIZED_VALUE,\n } as TOutput;\n }\n }\n};\n\n/**\n * Check if an object or a string is a serialised error created by\n * {@link serializeError}.\n */\nexport const isSerializedError = (\n value: unknown,\n): SerializedError | undefined => {\n try {\n if (typeof value === \"string\") {\n const parsed = z\n .object({\n [SERIALIZED_KEY]: z.literal(SERIALIZED_VALUE),\n name: z.enum([...Array.from(errorConstructors.keys())] as [\n string,\n ...string[],\n ]),\n message: z.string(),\n stack: z.string(),\n })\n .passthrough()\n .safeParse(JSON.parse(value));\n\n if (parsed.success) {\n return parsed.data as SerializedError;\n }\n }\n\n if (typeof value === \"object\" && value !== null) {\n const objIsSerializedErr =\n Object.hasOwn(value, SERIALIZED_KEY) &&\n (value as { [SERIALIZED_KEY]: unknown })[SERIALIZED_KEY] ===\n SERIALIZED_VALUE;\n\n if (objIsSerializedErr) {\n return value as SerializedError;\n }\n }\n } catch {\n // no-op; we'll return undefined if parsing failed, as it isn't a serialized\n // error\n }\n\n return;\n};\n\n/**\n * Deserialise an error created by {@link serializeError}.\n *\n * Ensures we only deserialise errors that meet a minimum level of\n * applicability, inclusive of error handling to ensure that badly serialized\n * errors are still handled.\n */\nexport const deserializeError = <\n TAllowUnknown extends boolean = false,\n TOutput extends TAllowUnknown extends true\n ? unknown\n : Error = TAllowUnknown extends true ? unknown : Error,\n>(\n subject: Partial<SerializedError>,\n allowUnknown: TAllowUnknown = false as TAllowUnknown,\n): TOutput => {\n const requiredFields: (keyof SerializedError)[] = [\"name\", \"message\"];\n\n try {\n const hasRequiredFields = requiredFields.every((field) => {\n return Object.hasOwn(subject, field);\n });\n\n if (!hasRequiredFields) {\n throw new Error();\n }\n\n const deserializedErr = cjsDeserializeError(subject as SerializedError);\n\n if (\"cause\" in deserializedErr) {\n deserializedErr.cause = deserializeError(\n deserializedErr.cause as Partial<SerializedError>,\n true,\n );\n }\n\n return deserializedErr as TOutput;\n } catch {\n if (allowUnknown) {\n // If we are allowed to return unknown, we'll just return the original\n // value.\n return subject as TOutput;\n }\n\n const err = new Error(\"Unknown error; could not reserialize\");\n\n /**\n * Remove the stack so that it's not misleadingly shown as the Inngest\n * internals.\n */\n err.stack = undefined;\n\n return err as TOutput;\n }\n};\n\nexport enum ErrCode {\n NESTING_STEPS = \"NESTING_STEPS\",\n\n /**\n * Legacy v0 execution error code for when a function has changed and no\n * longer matches its in-progress state.\n *\n * @deprecated Not for use in latest execution method.\n */\n NON_DETERMINISTIC_FUNCTION = \"NON_DETERMINISTIC_FUNCTION\",\n\n /**\n * Legacy v0 execution error code for when a function is found to be using\n * async actions after memoziation has occurred, which v0 doesn't support.\n *\n * @deprecated Not for use in latest execution method.\n */\n ASYNC_DETECTED_AFTER_MEMOIZATION = \"ASYNC_DETECTED_AFTER_MEMOIZATION\",\n\n /**\n * Legacy v0 execution error code for when a function is found to be using\n * steps after a non-step async action has occurred.\n *\n * @deprecated Not for use in latest execution method.\n */\n STEP_USED_AFTER_ASYNC = \"STEP_USED_AFTER_ASYNC\",\n\n AUTOMATIC_PARALLEL_INDEXING = \"AUTOMATIC_PARALLEL_INDEXING\",\n}\n\nexport interface PrettyError {\n /**\n * The type of message, used to decide on icon and color use.\n */\n type?: \"error\" | \"warn\";\n\n /**\n * A short, succinct description of what happened. Will be used as the error's\n * header, so should be short and to the point with no trailing punctuation.\n */\n whatHappened: string;\n\n /**\n * If applicable, provide a full sentence to reassure the user about certain\n * details, for example if an error occurred whilst uploading a file, but we\n * can assure the user that uploading succeeded and something internal failed.\n */\n reassurance?: string;\n\n /**\n * Tell the user why the error happened if we can. This should be a full\n * sentence or paragraph that explains the error in more detail, for example\n * to explain that a file failed to upload because it was too large and that\n * the maximum size is 10MB.\n */\n why?: string;\n\n /**\n * If applicable, tell the user what the consequences of the error are, for\n * example to tell them that their file was not uploaded and that they will\n * need to try again.\n */\n consequences?: string;\n\n /**\n * If we can, tell the user what they can do to fix the error now. This should\n * be a full sentence or paragraph that explains what the user can do to fix\n * the error, for example to tell them to try uploading a smaller file or\n * upgrade to a paid plan.\n */\n toFixNow?: string | string[];\n\n /**\n * If applicable, tell the user what to do if the error persists, they want\n * more information, or the fix we've given them doesn't work.\n *\n * This should be a full sentence or paragraph, and will likely refer users\n * to contact us for support, join our Discord, or read documentation.\n */\n otherwise?: string;\n\n /**\n * Add a stack trace to the message so that the user knows what line of code\n * the error is in relation to.\n */\n stack?: true;\n\n /**\n * If applicable, provide a code that the user can use to reference the error\n * when contacting support.\n */\n code?: ErrCode;\n}\n\nexport const prettyErrorSplitter =\n \"=================================================\";\n\n/**\n * Given an unknown `err`, mutate it to minify any pretty errors that it\n * contains.\n */\nexport const minifyPrettyError = <T>(err: T): T => {\n try {\n if (!isError(err)) {\n return err;\n }\n\n const isPrettyError = err.message.includes(prettyErrorSplitter);\n if (!isPrettyError) {\n return err;\n }\n\n const sanitizedMessage = stripAnsi(err.message);\n\n const message =\n sanitizedMessage.split(\" \")[1]?.split(\"\\n\")[0]?.trim() || err.message;\n const code =\n sanitizedMessage.split(\"\\n\\nCode: \")[1]?.split(\"\\n\\n\")[0]?.trim() ||\n undefined;\n\n err.message = [code, message].filter(Boolean).join(\" - \");\n\n if (err.stack) {\n const sanitizedStack = stripAnsi(err.stack);\n const stackRest = sanitizedStack\n .split(`${prettyErrorSplitter}\\n`)\n .slice(2)\n .join(\"\\n\");\n\n err.stack = `${err.name}: ${err.message}\\n${stackRest}`;\n }\n\n return err;\n } catch (_noopErr) {\n return err;\n }\n};\n\n/**\n * Given an `err`, return a boolean representing whether it is in the shape of\n * an `Error` or not.\n */\nconst isError = (err: unknown): err is Error => {\n try {\n if (err instanceof Error) {\n return true;\n }\n\n if (typeof err !== \"object\" || err === null) {\n return false;\n }\n\n const hasName = Object.hasOwn(err, \"name\");\n const hasMessage = Object.hasOwn(err, \"message\");\n\n return hasName && hasMessage;\n } catch (_noopErr) {\n return false;\n }\n};\n\n/**\n * Given an `unknown` object, retrieve the `message` property from it, or fall\n * back to the `fallback` string if it doesn't exist or is empty.\n */\nexport const getErrorMessage = (err: unknown, fallback: string): string => {\n const { message } = z\n .object({ message: z.string().min(1) })\n .catch({ message: fallback })\n .parse(err);\n\n return message;\n};\n\n/**\n * Given a {@link PrettyError}, return a nicely-formatted string ready to log\n * or throw.\n *\n * Useful for ensuring that errors are logged in a consistent, helpful format\n * across the SDK by prompting for key pieces of information.\n */\nexport const prettyError = ({\n type = \"error\",\n whatHappened,\n otherwise,\n reassurance,\n toFixNow,\n why,\n consequences,\n stack,\n code,\n}: PrettyError): string => {\n const { icon, colorFn } = (\n {\n error: { icon: \"❌\", colorFn: chalk.red },\n warn: { icon: \"⚠️\", colorFn: chalk.yellow },\n } satisfies Record<\n NonNullable<PrettyError[\"type\"]>,\n { icon: string; colorFn: (s: string) => string }\n >\n )[type];\n\n let header = `${icon} ${chalk.bold.underline(whatHappened.trim())}`;\n if (stack) {\n header +=\n \"\\n\" +\n [...(new Error().stack?.split(\"\\n\").slice(1).filter(Boolean) || [])].join(\n \"\\n\",\n );\n }\n\n let toFixNowStr =\n (Array.isArray(toFixNow)\n ? toFixNow\n .map((s) => s.trim())\n .filter(Boolean)\n .map((s, i) => `\\t${i + 1}. ${s}`)\n .join(\"\\n\")\n : toFixNow?.trim()) ?? \"\";\n\n if (Array.isArray(toFixNow) && toFixNowStr) {\n toFixNowStr = `To fix this, you can take one of the following courses of action:\\n\\n${toFixNowStr}`;\n }\n\n let body = [reassurance?.trim(), why?.trim(), consequences?.trim()]\n .filter(Boolean)\n .join(\" \");\n body += body ? `\\n\\n${toFixNowStr}` : toFixNowStr;\n\n const trailer = [otherwise?.trim()].filter(Boolean).join(\" \");\n\n const message = [\n prettyErrorSplitter,\n header,\n body,\n trailer,\n code ? `Code: ${code}` : \"\",\n prettyErrorSplitter,\n ]\n .filter(Boolean)\n .join(\"\\n\\n\");\n\n return colorFn(message);\n};\n\nexport const fixEventKeyMissingSteps = [\n \"Set the `INNGEST_EVENT_KEY` environment variable\",\n `Pass a key to the \\`new Inngest()\\` constructor using the \\`${\n \"eventKey\" satisfies keyof ClientOptions\n }\\` option`,\n `Use \\`inngest.${\"setEventKey\" satisfies keyof Inngest.Any}()\\` at runtime`,\n];\n\n/**\n * An error that, when thrown, indicates internally that an outgoing operation\n * contains an error.\n *\n * We use this because serialized `data` sent back to Inngest may differ from\n * the error instance itself due to middleware.\n *\n * @internal\n */\nexport class OutgoingResultError extends Error {\n public readonly result: Pick<OutgoingOp, \"data\" | \"error\">;\n\n constructor(result: Pick<OutgoingOp, \"data\" | \"error\">) {\n super(\"OutgoingOpError\");\n this.result = result;\n }\n}\n\n/**\n * Create a function that will rethrow an error with a prefix added to the\n * message.\n *\n * Useful for adding context to errors that are rethrown.\n *\n * @example\n * ```ts\n * await doSomeAction().catch(rethrowError(\"Failed to do some action\"));\n * ```\n */\n// biome-ignore lint/suspicious/noExplicitAny: <explanation>\nexport const rethrowError = (prefix: string): ((err: any) => never) => {\n return (err) => {\n try {\n err.message &&= `${prefix}; ${err.message}`;\n } catch (_noopErr) {\n // no-op\n } finally {\n // biome-ignore lint/correctness/noUnsafeFinally: <explanation>\n throw err;\n }\n };\n};\n\n/**\n * Legacy v0 execution error for functions that don't support mixing steps and\n * regular async actions.\n */\nexport const functionStoppedRunningErr = (code: ErrCode) => {\n return prettyError({\n whatHappened: \"Your function was stopped from running\",\n why: \"We detected a mix of asynchronous logic, some using step tooling and some not.\",\n consequences:\n \"This can cause unexpected behaviour when a function is paused and resumed and is therefore strongly discouraged; we stopped your function to ensure nothing unexpected happened!\",\n stack: true,\n toFixNow:\n \"Ensure that your function is either entirely step-based or entirely non-step-based, by either wrapping all asynchronous logic in `step.run()` calls or by removing all `step.*()` calls.\",\n otherwise:\n \"For more information on why step functions work in this manner, see https://www.inngest.com/docs/functions/multi-step#gotchas\",\n code,\n });\n};\n"],"mappings":"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"}
|
package/helpers/strings.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import
|
|
1
|
+
import safeStringify from "json-stringify-safe";
|
|
2
2
|
import hashjs from "hash.js";
|
|
3
3
|
import ms from "ms";
|
|
4
4
|
|
|
@@ -8,8 +8,8 @@ const { sha256 } = hashjs;
|
|
|
8
8
|
* Safely `JSON.stringify()` an `input`, handling circular refernences and
|
|
9
9
|
* removing `BigInt` values.
|
|
10
10
|
*/
|
|
11
|
-
const stringify
|
|
12
|
-
return
|
|
11
|
+
const stringify = (input) => {
|
|
12
|
+
return safeStringify(input, (_key, value) => {
|
|
13
13
|
if (typeof value !== "bigint") return value;
|
|
14
14
|
});
|
|
15
15
|
};
|
|
@@ -75,5 +75,5 @@ const hashSigningKey = (signingKey) => {
|
|
|
75
75
|
};
|
|
76
76
|
|
|
77
77
|
//#endregion
|
|
78
|
-
export { hashEventKey, hashSigningKey, slugify, stringify
|
|
78
|
+
export { hashEventKey, hashSigningKey, slugify, stringify, stringifyUnknown, timeStr };
|
|
79
79
|
//# sourceMappingURL=strings.js.map
|
package/helpers/strings.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"strings.js","names":["
|
|
1
|
+
{"version":3,"file":"strings.js","names":["milliseconds: number","timeStr"],"sources":["../../src/helpers/strings.ts"],"sourcesContent":["import hashjs from \"hash.js\";\nimport { default as safeStringify } from \"json-stringify-safe\";\nimport ms from \"ms\";\nimport type { TimeStr } from \"../types.ts\";\n\nconst { sha256 } = hashjs;\n\n/**\n * Safely `JSON.stringify()` an `input`, handling circular refernences and\n * removing `BigInt` values.\n */\n// biome-ignore lint/suspicious/noExplicitAny: <explanation>\nexport const stringify = (input: any): string => {\n return safeStringify(input, (_key, value) => {\n if (typeof value !== \"bigint\") {\n return value;\n }\n });\n};\n\n/**\n * Returns a slugified string used to generate consistent IDs.\n *\n * This can be used to generate a consistent ID for a function when migrating\n * from v2 to v3 of the SDK.\n *\n * @public\n */\nexport const slugify = (str: string): string => {\n const join = \"-\";\n return str\n .toLowerCase()\n .replace(/[^a-z0-9-]+/g, join)\n .replace(/-+/g, join)\n .split(join)\n .filter(Boolean)\n .join(join);\n};\n\nconst millisecond = 1;\nconst second = millisecond * 1000;\nconst minute = second * 60;\nconst hour = minute * 60;\nconst day = hour * 24;\nconst week = day * 7;\n\n/**\n * A collection of periods in milliseconds and their suffixes used when creating\n * time strings.\n */\nconst periods = [\n [\"w\", week],\n [\"d\", day],\n [\"h\", hour],\n [\"m\", minute],\n [\"s\", second],\n] as const;\n\n/**\n * Convert a given `Date`, `number`, or `ms`-compatible `string` to a\n * Inngest sleep-compatible time string (e.g. `\"1d\"` or `\"2h3010s\"`).\n *\n * Can optionally provide a `now` date to use as the base for the calculation,\n * otherwise a new date will be created on invocation.\n */\nexport const timeStr = (\n /**\n * The future date to use to convert to a time string.\n */\n input: string | number | Date,\n): string => {\n if (input instanceof Date) {\n return input.toISOString();\n }\n\n const milliseconds: number =\n typeof input === \"string\" ? ms(input as `${number}`) : input;\n\n const [, timeStr] = periods.reduce<[number, string]>(\n ([num, str], [suffix, period]) => {\n const numPeriods = Math.floor(num / period);\n\n if (numPeriods > 0) {\n return [num % period, `${str}${numPeriods}${suffix}`];\n }\n\n return [num, str];\n },\n [milliseconds, \"\"],\n );\n\n return timeStr as TimeStr;\n};\n\n/**\n * Given an unknown input, stringify it if it's a boolean, a number, or a\n * string, else return `undefined`.\n */\nexport const stringifyUnknown = (input: unknown): string | undefined => {\n if (\n typeof input === \"boolean\" ||\n typeof input === \"number\" ||\n typeof input === \"string\"\n ) {\n return input.toString();\n }\n\n return;\n};\n\nexport const hashEventKey = (eventKey: string): string => {\n return sha256().update(eventKey).digest(\"hex\");\n};\n\nexport const hashSigningKey = (signingKey: string | undefined): string => {\n if (!signingKey) {\n return \"\";\n }\n\n const prefix = signingKey.match(/^signkey-[\\w]+-/)?.shift() || \"\";\n const key = signingKey.replace(/^signkey-[\\w]+-/, \"\");\n\n // Decode the key from its hex representation into a bytestream\n return `${prefix}${sha256().update(key, \"hex\").digest(\"hex\")}`;\n};\n"],"mappings":";;;;;AAKA,MAAM,EAAE,WAAW;;;;;AAOnB,MAAa,aAAa,UAAuB;AAC/C,QAAO,cAAc,QAAQ,MAAM,UAAU;AAC3C,MAAI,OAAO,UAAU,SACnB,QAAO;GAET;;;;;;;;;;AAWJ,MAAa,WAAW,QAAwB;CAC9C,MAAM,OAAO;AACb,QAAO,IACJ,aAAa,CACb,QAAQ,gBAAgB,KAAK,CAC7B,QAAQ,OAAO,KAAK,CACpB,MAAM,KAAK,CACX,OAAO,QAAQ,CACf,KAAK,KAAK;;AAIf,MAAM,SADc,IACS;AAC7B,MAAM,SAAS,SAAS;AACxB,MAAM,OAAO,SAAS;AACtB,MAAM,MAAM,OAAO;;;;;AAOnB,MAAM,UAAU;CACd,CAAC,KAPU,MAAM,EAON;CACX,CAAC,KAAK,IAAI;CACV,CAAC,KAAK,KAAK;CACX,CAAC,KAAK,OAAO;CACb,CAAC,KAAK,OAAO;CACd;;;;;;;;AASD,MAAa,WAIX,UACW;AACX,KAAI,iBAAiB,KACnB,QAAO,MAAM,aAAa;CAG5B,MAAMA,eACJ,OAAO,UAAU,WAAW,GAAG,MAAqB,GAAG;CAEzD,MAAM,GAAGC,aAAW,QAAQ,QACzB,CAAC,KAAK,MAAM,CAAC,QAAQ,YAAY;EAChC,MAAM,aAAa,KAAK,MAAM,MAAM,OAAO;AAE3C,MAAI,aAAa,EACf,QAAO,CAAC,MAAM,QAAQ,GAAG,MAAM,aAAa,SAAS;AAGvD,SAAO,CAAC,KAAK,IAAI;IAEnB,CAAC,cAAc,GAAG,CACnB;AAED,QAAOA;;;;;;AAOT,MAAa,oBAAoB,UAAuC;AACtE,KACE,OAAO,UAAU,aACjB,OAAO,UAAU,YACjB,OAAO,UAAU,SAEjB,QAAO,MAAM,UAAU;;AAM3B,MAAa,gBAAgB,aAA6B;AACxD,QAAO,QAAQ,CAAC,OAAO,SAAS,CAAC,OAAO,MAAM;;AAGhD,MAAa,kBAAkB,eAA2C;AACxE,KAAI,CAAC,WACH,QAAO;CAGT,MAAM,SAAS,WAAW,MAAM,kBAAkB,EAAE,OAAO,IAAI;CAC/D,MAAM,MAAM,WAAW,QAAQ,mBAAmB,GAAG;AAGrD,QAAO,GAAG,SAAS,QAAQ,CAAC,OAAO,KAAK,MAAM,CAAC,OAAO,MAAM"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "inngest",
|
|
3
|
-
"version": "3.48.2-pr-1209.
|
|
3
|
+
"version": "3.48.2-pr-1209.1",
|
|
4
4
|
"description": "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.",
|
|
5
5
|
"main": "./index.cjs",
|
|
6
6
|
"module": "./index.js",
|
package/version.cjs
CHANGED
package/version.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"version.cjs","names":[],"sources":["../src/version.ts"],"sourcesContent":["// Generated by genversion.\nexport const version = \"3.48.2-pr-1209.
|
|
1
|
+
{"version":3,"file":"version.cjs","names":[],"sources":["../src/version.ts"],"sourcesContent":["// Generated by genversion.\nexport const version = \"3.48.2-pr-1209.1\";\n"],"mappings":";;AACA,MAAa,UAAU"}
|
package/version.d.cts
CHANGED
package/version.d.ts
CHANGED
package/version.js
CHANGED
package/version.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"version.js","names":[],"sources":["../src/version.ts"],"sourcesContent":["// Generated by genversion.\nexport const version = \"3.48.2-pr-1209.
|
|
1
|
+
{"version":3,"file":"version.js","names":[],"sources":["../src/version.ts"],"sourcesContent":["// Generated by genversion.\nexport const version = \"3.48.2-pr-1209.1\";\n"],"mappings":";AACA,MAAa,UAAU"}
|