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 • 6.8 kB
Source Map (JSON)
{"version":3,"file":"strings.cjs","names":["hashjs","isTemporalInstant","isTemporalZonedDateTime","getISOString","milliseconds: number","isTemporalDuration","Temporal","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 { Temporal } from \"temporal-polyfill\";\nimport type { TimeStr } from \"../types.ts\";\nimport {\n type DurationLike,\n getISOString,\n type InstantLike,\n isTemporalDuration,\n isTemporalInstant,\n isTemporalZonedDateTime,\n type ZonedDateTimeLike,\n} from \"./temporal.ts\";\n\nconst { sha256 } = hashjs;\n\n/**\n * Constant-time equality check for two strings. Returns `false` immediately if\n * lengths differ; otherwise XOR-accumulates every char code so the total time\n * is independent of where (or whether) the strings diverge.\n *\n * Used for HMAC signature verification — `===`/`!==` short-circuit on the\n * first mismatched character and leak the matching-prefix length via timing.\n */\nexport function timingSafeEqual(a: string, b: string): boolean {\n if (a.length !== b.length) {\n return false;\n }\n\n let diff = 0;\n for (let i = 0; i < a.length; i++) {\n diff |= a.charCodeAt(i) ^ b.charCodeAt(i);\n }\n return diff === 0;\n}\n\n/**\n * Safely `JSON.stringify()` an `input`, handling circular refernences and\n * removing `BigInt` values.\n */\n// biome-ignore lint/suspicious/noExplicitAny: intentional\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 */\nexport const timeStr = (\n /**\n * The future date to use to convert to a time string.\n */\n input:\n | string\n | number\n | Date\n | DurationLike\n | InstantLike\n | ZonedDateTimeLike,\n): string => {\n if (input instanceof Date) {\n return input.toISOString();\n }\n\n if (isTemporalInstant(input) || isTemporalZonedDateTime(input)) {\n return getISOString(input);\n }\n\n let milliseconds: number;\n if (isTemporalDuration(input)) {\n // `relativeTo` is required for calendar units (months/years/weeks). We\n // pass it as an ISO string rather than a Temporal object so this works\n // regardless of which Temporal implementation the user's Duration came\n // from (temporal-polyfill, @js-temporal/polyfill, native Temporal):\n // ISO strings are spec-defined and parsed by every implementation;\n // cross-polyfill object passing is not.\n milliseconds = input.total({\n unit: \"milliseconds\",\n relativeTo: Temporal.Now.plainDateTimeISO(\"UTC\").toString(),\n });\n } else if (typeof input === \"string\") {\n milliseconds = ms(input as `${number}`);\n } else {\n milliseconds = input as number;\n }\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 = removeSigningKeyPrefix(signingKey);\n\n // Decode the key from its hex representation into a bytestream\n return `${prefix}${sha256().update(key, \"hex\").digest(\"hex\")}`;\n};\n\nexport function removeSigningKeyPrefix(signingKey: string): string {\n return signingKey.replace(/^signkey-[\\w]+-/, \"\");\n}\n"],"mappings":";;;;;;;;;;;AAeA,MAAM,EAAE,WAAWA;;;;;;;;;AAUnB,SAAgB,gBAAgB,GAAW,GAAoB;AAC7D,KAAI,EAAE,WAAW,EAAE,OACjB,QAAO;CAGT,IAAI,OAAO;AACX,MAAK,IAAI,IAAI,GAAG,IAAI,EAAE,QAAQ,IAC5B,SAAQ,EAAE,WAAW,EAAE,GAAG,EAAE,WAAW,EAAE;AAE3C,QAAO,SAAS;;;;;;AAQlB,MAAa,aAAa,UAAuB;AAC/C,yCAAqB,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;;;;;AAMD,MAAa,WAIX,UAOW;AACX,KAAI,iBAAiB,KACnB,QAAO,MAAM,aAAa;AAG5B,KAAIC,mCAAkB,MAAM,IAAIC,yCAAwB,MAAM,CAC5D,QAAOC,8BAAa,MAAM;CAG5B,IAAIC;AACJ,KAAIC,oCAAmB,MAAM,CAO3B,gBAAe,MAAM,MAAM;EACzB,MAAM;EACN,YAAYC,2BAAS,IAAI,iBAAiB,MAAM,CAAC,UAAU;EAC5D,CAAC;UACO,OAAO,UAAU,SAC1B,gCAAkB,MAAqB;KAEvC,gBAAe;CAGjB,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;;AAmBT,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,uBAAuB,WAAW;AAG9C,QAAO,GAAG,SAAS,QAAQ,CAAC,OAAO,KAAK,MAAM,CAAC,OAAO,MAAM;;AAG9D,SAAgB,uBAAuB,YAA4B;AACjE,QAAO,WAAW,QAAQ,mBAAmB,GAAG"}