inngest 4.2.5 → 4.2.6
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/CHANGELOG.md +8 -0
- package/api/api.cjs +1 -1
- package/api/api.js +1 -1
- package/components/Inngest.cjs +1 -1
- package/components/Inngest.js +1 -1
- package/components/InngestCommHandler.cjs +60 -28
- package/components/InngestCommHandler.cjs.map +1 -1
- package/components/InngestCommHandler.d.cts.map +1 -1
- package/components/InngestCommHandler.d.ts.map +1 -1
- package/components/InngestCommHandler.js +60 -28
- package/components/InngestCommHandler.js.map +1 -1
- package/helpers/consts.cjs +1 -0
- package/helpers/consts.cjs.map +1 -1
- package/helpers/consts.d.cts +1 -0
- package/helpers/consts.d.cts.map +1 -1
- package/helpers/consts.d.ts +1 -0
- package/helpers/consts.d.ts.map +1 -1
- package/helpers/consts.js +1 -0
- package/helpers/consts.js.map +1 -1
- package/helpers/env.cjs +2 -1
- package/helpers/env.cjs.map +1 -1
- package/helpers/env.js +2 -1
- package/helpers/env.js.map +1 -1
- package/helpers/net.cjs +3 -2
- package/helpers/net.cjs.map +1 -1
- package/helpers/net.js +3 -2
- package/helpers/net.js.map +1 -1
- package/helpers/strings.cjs +5 -1
- package/helpers/strings.cjs.map +1 -1
- package/helpers/strings.js +5 -2
- package/helpers/strings.js.map +1 -1
- package/package.json +1 -1
- package/types.d.cts +14 -14
- package/types.d.ts +14 -14
- 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/consts.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"consts.cjs","names":["logPrefix: string"],"sources":["../../src/helpers/consts.ts"],"sourcesContent":["/**\n * Keys for accessing query parameters included in requests from Inngest to run\n * functions.\n *\n * Used internally to create handlers using `InngestCommHandler`, but can be\n * imported to be used if creating a custom handler outside of the package.\n *\n * @public\n */\nexport enum queryKeys {\n DeployId = \"deployId\",\n FnId = \"fnId\",\n Probe = \"probe\",\n StepId = \"stepId\",\n}\n\nexport enum probe {\n Trust = \"trust\",\n}\n\nexport enum envKeys {\n InngestSigningKey = \"INNGEST_SIGNING_KEY\",\n InngestSigningKeyFallback = \"INNGEST_SIGNING_KEY_FALLBACK\",\n InngestEventKey = \"INNGEST_EVENT_KEY\",\n\n /**\n * @deprecated Removed in v3. Use {@link InngestBaseUrl} instead.\n */\n InngestDevServerUrl = \"INNGEST_DEVSERVER_URL\",\n InngestEnvironment = \"INNGEST_ENV\",\n InngestBaseUrl = \"INNGEST_BASE_URL\",\n InngestEventApiBaseUrl = \"INNGEST_EVENT_API_BASE_URL\",\n InngestApiBaseUrl = \"INNGEST_API_BASE_URL\",\n InngestServeHost = \"INNGEST_SERVE_HOST\", // Deprecated, use INNGEST_SERVE_ORIGIN\n InngestServePath = \"INNGEST_SERVE_PATH\",\n InngestServeOrigin = \"INNGEST_SERVE_ORIGIN\",\n InngestStreaming = \"INNGEST_STREAMING\",\n InngestDevMode = \"INNGEST_DEV\",\n InngestAllowInBandSync = \"INNGEST_ALLOW_IN_BAND_SYNC\",\n InngestConnectMaxWorkerConcurrency = \"INNGEST_CONNECT_MAX_WORKER_CONCURRENCY\",\n InngestConnectIsolateExecution = \"INNGEST_CONNECT_ISOLATE_EXECUTION\",\n InngestConnectGatewayUrl = \"INNGEST_CONNECT_GATEWAY_URL\",\n\n /**\n * @deprecated It's unknown what this env var was used for, but we do not\n * provide explicit support for it. Prefer using `INNGEST_ENV` instead.\n */\n BranchName = \"BRANCH_NAME\",\n\n /**\n * The git branch of the commit the deployment was triggered by. Example:\n * `improve-about-page`.\n *\n * {@link https://vercel.com/docs/concepts/projects/environment-variables/system-environment-variables#system-environment-variables}\n */\n VercelBranch = \"VERCEL_GIT_COMMIT_REF\",\n\n /**\n * Expected to be `\"1\"` if defined.\n */\n IsVercel = \"VERCEL\",\n\n /**\n * The branch name of the current deployment. May only be accessible at build\n * time, but included here just in case.\n *\n * {@link https://developers.cloudflare.com/pages/platform/build-configuration/#environment-variables}\n */\n CloudflarePagesBranch = \"CF_PAGES_BRANCH\",\n\n /**\n * Expected to be `\"1\"` if defined.\n */\n IsCloudflarePages = \"CF_PAGES\",\n\n /**\n * The branch name of the deployment from Git to Netlify, if available.\n *\n * {@link https://docs.netlify.com/configure-builds/environment-variables/#git-metadata}\n */\n NetlifyBranch = \"BRANCH\",\n\n /**\n * Expected to be `\"true\"` if defined.\n */\n IsNetlify = \"NETLIFY\",\n\n /**\n * The Git branch for a service or deploy.\n *\n * {@link https://render.com/docs/environment-variables#all-services}\n */\n RenderBranch = \"RENDER_GIT_BRANCH\",\n\n /**\n * Expected to be `\"true\"` if defined.\n */\n IsRender = \"RENDER\",\n\n /**\n * The branch that triggered the deployment. Example: `main`\n *\n * {@link https://docs.railway.app/develop/variables#railway-provided-variables}\n */\n RailwayBranch = \"RAILWAY_GIT_BRANCH\",\n\n /**\n * The railway environment for the deployment. Example: `production`\n *\n * {@link https://docs.railway.app/develop/variables#railway-provided-variables}\n */\n RailwayEnvironment = \"RAILWAY_ENVIRONMENT\",\n\n VercelEnvKey = \"VERCEL_ENV\",\n\n /**\n * Standard Node.js environment indicator (e.g. `\"production\"`, `\"development\"`,\n * `\"test\"`). Read by some framework adapters to choose the request scheme,\n * and by prod-mode inference.\n */\n NodeEnv = \"NODE_ENV\",\n\n /**\n * Netlify's deploy context (e.g. `\"production\"`, `\"deploy-preview\"`). Used\n * for prod-mode inference.\n *\n * {@link https://docs.netlify.com/configure-builds/environment-variables/#build-metadata}\n */\n Context = \"CONTEXT\",\n\n /**\n * Generic environment name used by some platforms to indicate prod vs\n * non-prod (e.g. `\"production\"`).\n */\n Environment = \"ENVIRONMENT\",\n\n /**\n * Set by Deno Deploy. Its presence indicates a Deno Deploy environment,\n * which we treat as prod.\n *\n * {@link https://docs.deno.com/deploy/manual/environment-variables/}\n */\n DenoDeployment = \"DENO_DEPLOYMENT_ID\",\n\n OpenAiApiKey = \"OPENAI_API_KEY\",\n GeminiApiKey = \"GEMINI_API_KEY\",\n AnthropicApiKey = \"ANTHROPIC_API_KEY\",\n\n /**\n * Framework-prefixed variants of Inngest env vars. CRA's `REACT_APP_` and\n * Next's `NEXT_PUBLIC_` prefixes expose env vars to bundled client code, so\n * we accept the prefixed forms in addition to the canonical names.\n */\n ReactAppInngestBaseUrl = \"REACT_APP_INNGEST_BASE_URL\",\n ReactAppInngestDevMode = \"REACT_APP_INNGEST_DEV\",\n NextPublicInngestBaseUrl = \"NEXT_PUBLIC_INNGEST_BASE_URL\",\n NextPublicInngestDevMode = \"NEXT_PUBLIC_INNGEST_DEV\",\n}\n\n/**\n * Keys for accessing headers included in requests from Inngest to run\n * functions.\n *\n * Used internally to create handlers using `InngestCommHandler`, but can be\n * imported to be used if creating a custom handler outside of the package.\n *\n * @public\n */\nexport enum headerKeys {\n ContentType = \"content-type\",\n Host = \"host\",\n ForwardedFor = \"x-forwarded-for\",\n RealIp = \"x-real-ip\",\n Location = \"location\",\n ContentLength = \"content-length\",\n Signature = \"x-inngest-signature\",\n SdkVersion = \"x-inngest-sdk\",\n Environment = \"x-inngest-env\",\n Platform = \"x-inngest-platform\",\n Framework = \"x-inngest-framework\",\n NoRetry = \"x-inngest-no-retry\",\n RequestVersion = \"x-inngest-req-version\",\n RetryAfter = \"retry-after\",\n InngestServerKind = \"x-inngest-server-kind\",\n InngestExpectedServerKind = \"x-inngest-expected-server-kind\",\n InngestSyncKind = \"x-inngest-sync-kind\",\n EventIdSeed = \"x-inngest-event-id-seed\",\n TraceParent = \"traceparent\",\n TraceState = \"tracestate\",\n InngestRunId = \"x-run-id\",\n InngestStepId = \"x-inngest-step-id\",\n InngestForceStepPlan = \"x-inngest-force-step-plan\",\n}\n\n/**\n * Headers that are forwarded from the original request when an Inngest function\n * is invoked.\n */\nexport const forwardedHeaders = [headerKeys.TraceParent, headerKeys.TraceState];\n\nexport const defaultInngestApiBaseUrl = \"https://api.inngest.com/\";\nexport const defaultInngestEventBaseUrl = \"https://inn.gs/\";\nexport const defaultDevServerHost = \"http://localhost:8288/\";\n\n/**\n * Events that Inngest may send internally that can be used to trigger\n * functions.\n *\n * @public\n */\nexport enum internalEvents {\n /**\n * A function has failed after exhausting all available retries. This event\n * will contain the original event and the error that caused the failure.\n */\n FunctionFailed = \"inngest/function.failed\",\n FunctionInvoked = \"inngest/function.invoked\",\n FunctionFinished = \"inngest/function.finished\",\n FunctionCancelled = \"inngest/function.cancelled\",\n ScheduledTimer = \"inngest/scheduled.timer\",\n HttpRequest = \"inngest/http.request\",\n}\n\nexport const logPrefix: string = \"[Inngest]\";\n\nexport const debugPrefix = \"inngest\";\n\nexport const dummyEventKey = \"NO_EVENT_KEY_SET\";\n\nexport enum serverKind {\n Dev = \"dev\",\n Cloud = \"cloud\",\n}\n\nexport enum syncKind {\n InBand = \"in_band\",\n OutOfBand = \"out_of_band\",\n}\n\n/**\n * The execution models the SDK is aware of.\n *\n * This is used in a number of places to ensure all execution versions are\n * accounted for for a given operation.\n */\nexport enum ExecutionVersion {\n /**\n * Uses a more flexible approach to execution and is more lenient about\n * determinism, allowing non-step async actions and non-determinism.\n *\n * Nowhere near as stubborn about determinism and so can silently migrate\n * between versions after bug fixes.\n */\n V1 = 1,\n\n /**\n * Identical to V1, but allows the Executor to optimize parallel calls, hugely\n * reducing traffic going to/from the SDK.\n */\n V2 = 2,\n}\n\n/**\n * Default maximum number of retries for function/step executions.\n */\nexport const defaultMaxRetries = 3;\n"],"mappings":";;;;;;;;;;;AASA,IAAY,kDAAL;AACL;AACA;AACA;AACA;;;AAGF,IAAY,0CAAL;AACL;;;AAGF,IAAY,8CAAL;AACL;AACA;AACA;;;;AAKA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;AAMA;;;;;;;AAQA;;;;AAKA;;;;;;;AAQA;;;;AAKA;;;;;;AAOA;;;;AAKA;;;;;;AAOA;;;;AAKA;;;;;;AAOA;;;;;;AAOA;AAEA;;;;;;AAOA;;;;;;;AAQA;;;;;AAMA;;;;;;;AAQA;AAEA;AACA;AACA;;;;;;AAOA;AACA;AACA;AACA;;;;;;;;;;;;AAYF,IAAY,oDAAL;AACL;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;;;AAOF,MAAa,mBAAmB,CAAC,WAAW,aAAa,WAAW,WAAW;AAE/E,MAAa,2BAA2B;AACxC,MAAa,6BAA6B;AAC1C,MAAa,uBAAuB;;;;;;;AAQpC,IAAY,4DAAL;;;;;AAKL;AACA;AACA;AACA;AACA;AACA;;;AAGF,MAAaA,YAAoB;AAEjC,MAAa,cAAc;AAE3B,MAAa,gBAAgB;AAO7B,IAAY,gDAAL;AACL;AACA;;;;;;;;;AASF,IAAY,gEAAL;;;;;;;;AAQL;;;;;AAMA;;;;;;AAMF,MAAa,oBAAoB"}
|
|
1
|
+
{"version":3,"file":"consts.cjs","names":["logPrefix: string"],"sources":["../../src/helpers/consts.ts"],"sourcesContent":["/**\n * Keys for accessing query parameters included in requests from Inngest to run\n * functions.\n *\n * Used internally to create handlers using `InngestCommHandler`, but can be\n * imported to be used if creating a custom handler outside of the package.\n *\n * @public\n */\nexport enum queryKeys {\n DeployId = \"deployId\",\n FnId = \"fnId\",\n Probe = \"probe\",\n StepId = \"stepId\",\n}\n\nexport enum probe {\n Trust = \"trust\",\n}\n\nexport enum envKeys {\n InngestSigningKey = \"INNGEST_SIGNING_KEY\",\n InngestSigningKeyFallback = \"INNGEST_SIGNING_KEY_FALLBACK\",\n InngestEventKey = \"INNGEST_EVENT_KEY\",\n\n /**\n * @deprecated Removed in v3. Use {@link InngestBaseUrl} instead.\n */\n InngestDevServerUrl = \"INNGEST_DEVSERVER_URL\",\n InngestEnvironment = \"INNGEST_ENV\",\n InngestBaseUrl = \"INNGEST_BASE_URL\",\n InngestEventApiBaseUrl = \"INNGEST_EVENT_API_BASE_URL\",\n InngestApiBaseUrl = \"INNGEST_API_BASE_URL\",\n InngestServeHost = \"INNGEST_SERVE_HOST\", // Deprecated, use INNGEST_SERVE_ORIGIN\n InngestServePath = \"INNGEST_SERVE_PATH\",\n InngestServeOrigin = \"INNGEST_SERVE_ORIGIN\",\n InngestStreaming = \"INNGEST_STREAMING\",\n InngestDevMode = \"INNGEST_DEV\",\n InngestAllowInBandSync = \"INNGEST_ALLOW_IN_BAND_SYNC\",\n InngestConnectMaxWorkerConcurrency = \"INNGEST_CONNECT_MAX_WORKER_CONCURRENCY\",\n InngestConnectIsolateExecution = \"INNGEST_CONNECT_ISOLATE_EXECUTION\",\n InngestConnectGatewayUrl = \"INNGEST_CONNECT_GATEWAY_URL\",\n\n /**\n * @deprecated It's unknown what this env var was used for, but we do not\n * provide explicit support for it. Prefer using `INNGEST_ENV` instead.\n */\n BranchName = \"BRANCH_NAME\",\n\n /**\n * The git branch of the commit the deployment was triggered by. Example:\n * `improve-about-page`.\n *\n * {@link https://vercel.com/docs/concepts/projects/environment-variables/system-environment-variables#system-environment-variables}\n */\n VercelBranch = \"VERCEL_GIT_COMMIT_REF\",\n\n /**\n * Expected to be `\"1\"` if defined.\n */\n IsVercel = \"VERCEL\",\n\n /**\n * The branch name of the current deployment. May only be accessible at build\n * time, but included here just in case.\n *\n * {@link https://developers.cloudflare.com/pages/platform/build-configuration/#environment-variables}\n */\n CloudflarePagesBranch = \"CF_PAGES_BRANCH\",\n\n /**\n * Expected to be `\"1\"` if defined.\n */\n IsCloudflarePages = \"CF_PAGES\",\n\n /**\n * The branch name of the deployment from Git to Netlify, if available.\n *\n * {@link https://docs.netlify.com/configure-builds/environment-variables/#git-metadata}\n */\n NetlifyBranch = \"BRANCH\",\n\n /**\n * Expected to be `\"true\"` if defined.\n */\n IsNetlify = \"NETLIFY\",\n\n /**\n * The Git branch for a service or deploy.\n *\n * {@link https://render.com/docs/environment-variables#all-services}\n */\n RenderBranch = \"RENDER_GIT_BRANCH\",\n\n /**\n * Expected to be `\"true\"` if defined.\n */\n IsRender = \"RENDER\",\n\n /**\n * The branch that triggered the deployment. Example: `main`\n *\n * {@link https://docs.railway.app/develop/variables#railway-provided-variables}\n */\n RailwayBranch = \"RAILWAY_GIT_BRANCH\",\n\n /**\n * The railway environment for the deployment. Example: `production`\n *\n * {@link https://docs.railway.app/develop/variables#railway-provided-variables}\n */\n RailwayEnvironment = \"RAILWAY_ENVIRONMENT\",\n\n VercelEnvKey = \"VERCEL_ENV\",\n\n /**\n * Standard Node.js environment indicator (e.g. `\"production\"`, `\"development\"`,\n * `\"test\"`). Read by some framework adapters to choose the request scheme,\n * and by prod-mode inference.\n */\n NodeEnv = \"NODE_ENV\",\n\n /**\n * Netlify's deploy context (e.g. `\"production\"`, `\"deploy-preview\"`). Used\n * for prod-mode inference.\n *\n * {@link https://docs.netlify.com/configure-builds/environment-variables/#build-metadata}\n */\n Context = \"CONTEXT\",\n\n /**\n * Generic environment name used by some platforms to indicate prod vs\n * non-prod (e.g. `\"production\"`).\n */\n Environment = \"ENVIRONMENT\",\n\n /**\n * Set by Deno Deploy. Its presence indicates a Deno Deploy environment,\n * which we treat as prod.\n *\n * {@link https://docs.deno.com/deploy/manual/environment-variables/}\n */\n DenoDeployment = \"DENO_DEPLOYMENT_ID\",\n\n OpenAiApiKey = \"OPENAI_API_KEY\",\n GeminiApiKey = \"GEMINI_API_KEY\",\n AnthropicApiKey = \"ANTHROPIC_API_KEY\",\n\n /**\n * Framework-prefixed variants of Inngest env vars. CRA's `REACT_APP_` and\n * Next's `NEXT_PUBLIC_` prefixes expose env vars to bundled client code, so\n * we accept the prefixed forms in addition to the canonical names.\n */\n ReactAppInngestBaseUrl = \"REACT_APP_INNGEST_BASE_URL\",\n ReactAppInngestDevMode = \"REACT_APP_INNGEST_DEV\",\n NextPublicInngestBaseUrl = \"NEXT_PUBLIC_INNGEST_BASE_URL\",\n NextPublicInngestDevMode = \"NEXT_PUBLIC_INNGEST_DEV\",\n}\n\n/**\n * Keys for accessing headers included in requests from Inngest to run\n * functions.\n *\n * Used internally to create handlers using `InngestCommHandler`, but can be\n * imported to be used if creating a custom handler outside of the package.\n *\n * @public\n */\nexport enum headerKeys {\n ContentType = \"content-type\",\n Host = \"host\",\n ForwardedFor = \"x-forwarded-for\",\n RealIp = \"x-real-ip\",\n Location = \"location\",\n ContentLength = \"content-length\",\n Signature = \"x-inngest-signature\",\n SdkVersion = \"x-inngest-sdk\",\n Environment = \"x-inngest-env\",\n Platform = \"x-inngest-platform\",\n Framework = \"x-inngest-framework\",\n NoRetry = \"x-inngest-no-retry\",\n RequestVersion = \"x-inngest-req-version\",\n RetryAfter = \"retry-after\",\n InngestServerKind = \"x-inngest-server-kind\",\n InngestExpectedServerKind = \"x-inngest-expected-server-kind\",\n InngestSyncKind = \"x-inngest-sync-kind\",\n EventIdSeed = \"x-inngest-event-id-seed\",\n TraceParent = \"traceparent\",\n TraceState = \"tracestate\",\n InngestRunId = \"x-run-id\",\n InngestStepId = \"x-inngest-step-id\",\n InngestForceStepPlan = \"x-inngest-force-step-plan\",\n SdkHandled = \"x-inngest-sdk-handled\",\n}\n\n/**\n * Headers that are forwarded from the original request when an Inngest function\n * is invoked.\n */\nexport const forwardedHeaders = [headerKeys.TraceParent, headerKeys.TraceState];\n\nexport const defaultInngestApiBaseUrl = \"https://api.inngest.com/\";\nexport const defaultInngestEventBaseUrl = \"https://inn.gs/\";\nexport const defaultDevServerHost = \"http://localhost:8288/\";\n\n/**\n * Events that Inngest may send internally that can be used to trigger\n * functions.\n *\n * @public\n */\nexport enum internalEvents {\n /**\n * A function has failed after exhausting all available retries. This event\n * will contain the original event and the error that caused the failure.\n */\n FunctionFailed = \"inngest/function.failed\",\n FunctionInvoked = \"inngest/function.invoked\",\n FunctionFinished = \"inngest/function.finished\",\n FunctionCancelled = \"inngest/function.cancelled\",\n ScheduledTimer = \"inngest/scheduled.timer\",\n HttpRequest = \"inngest/http.request\",\n}\n\nexport const logPrefix: string = \"[Inngest]\";\n\nexport const debugPrefix = \"inngest\";\n\nexport const dummyEventKey = \"NO_EVENT_KEY_SET\";\n\nexport enum serverKind {\n Dev = \"dev\",\n Cloud = \"cloud\",\n}\n\nexport enum syncKind {\n InBand = \"in_band\",\n OutOfBand = \"out_of_band\",\n}\n\n/**\n * The execution models the SDK is aware of.\n *\n * This is used in a number of places to ensure all execution versions are\n * accounted for for a given operation.\n */\nexport enum ExecutionVersion {\n /**\n * Uses a more flexible approach to execution and is more lenient about\n * determinism, allowing non-step async actions and non-determinism.\n *\n * Nowhere near as stubborn about determinism and so can silently migrate\n * between versions after bug fixes.\n */\n V1 = 1,\n\n /**\n * Identical to V1, but allows the Executor to optimize parallel calls, hugely\n * reducing traffic going to/from the SDK.\n */\n V2 = 2,\n}\n\n/**\n * Default maximum number of retries for function/step executions.\n */\nexport const defaultMaxRetries = 3;\n"],"mappings":";;;;;;;;;;;AASA,IAAY,kDAAL;AACL;AACA;AACA;AACA;;;AAGF,IAAY,0CAAL;AACL;;;AAGF,IAAY,8CAAL;AACL;AACA;AACA;;;;AAKA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;AAMA;;;;;;;AAQA;;;;AAKA;;;;;;;AAQA;;;;AAKA;;;;;;AAOA;;;;AAKA;;;;;;AAOA;;;;AAKA;;;;;;AAOA;;;;;;AAOA;AAEA;;;;;;AAOA;;;;;;;AAQA;;;;;AAMA;;;;;;;AAQA;AAEA;AACA;AACA;;;;;;AAOA;AACA;AACA;AACA;;;;;;;;;;;;AAYF,IAAY,oDAAL;AACL;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;;;AAOF,MAAa,mBAAmB,CAAC,WAAW,aAAa,WAAW,WAAW;AAE/E,MAAa,2BAA2B;AACxC,MAAa,6BAA6B;AAC1C,MAAa,uBAAuB;;;;;;;AAQpC,IAAY,4DAAL;;;;;AAKL;AACA;AACA;AACA;AACA;AACA;;;AAGF,MAAaA,YAAoB;AAEjC,MAAa,cAAc;AAE3B,MAAa,gBAAgB;AAO7B,IAAY,gDAAL;AACL;AACA;;;;;;;;;AASF,IAAY,gEAAL;;;;;;;;AAQL;;;;;AAMA;;;;;;AAMF,MAAa,oBAAoB"}
|
package/helpers/consts.d.cts
CHANGED
|
@@ -47,6 +47,7 @@ declare enum headerKeys {
|
|
|
47
47
|
InngestRunId = "x-run-id",
|
|
48
48
|
InngestStepId = "x-inngest-step-id",
|
|
49
49
|
InngestForceStepPlan = "x-inngest-force-step-plan",
|
|
50
|
+
SdkHandled = "x-inngest-sdk-handled",
|
|
50
51
|
}
|
|
51
52
|
/**
|
|
52
53
|
* Events that Inngest may send internally that can be used to trigger
|
package/helpers/consts.d.cts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"consts.d.cts","names":[],"sources":["../../src/helpers/consts.ts"],"sourcesContent":[],"mappings":";;AASA;AA+JA;
|
|
1
|
+
{"version":3,"file":"consts.d.cts","names":[],"sources":["../../src/helpers/consts.ts"],"sourcesContent":[],"mappings":";;AASA;AA+JA;AA2CA;AAmCA;;;;;aA7OY,SAAA;;;;;;;;;;;;;;;aA+JA,UAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;aA2CA,cAAA;;;;;;;;;;;;;;;;;;aAmCA,gBAAA"}
|
package/helpers/consts.d.ts
CHANGED
|
@@ -47,6 +47,7 @@ declare enum headerKeys {
|
|
|
47
47
|
InngestRunId = "x-run-id",
|
|
48
48
|
InngestStepId = "x-inngest-step-id",
|
|
49
49
|
InngestForceStepPlan = "x-inngest-force-step-plan",
|
|
50
|
+
SdkHandled = "x-inngest-sdk-handled",
|
|
50
51
|
}
|
|
51
52
|
/**
|
|
52
53
|
* Events that Inngest may send internally that can be used to trigger
|
package/helpers/consts.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"consts.d.ts","names":[],"sources":["../../src/helpers/consts.ts"],"sourcesContent":[],"mappings":";;AASA;AA+JA;
|
|
1
|
+
{"version":3,"file":"consts.d.ts","names":[],"sources":["../../src/helpers/consts.ts"],"sourcesContent":[],"mappings":";;AASA;AA+JA;AA2CA;AAmCA;;;;;aA7OY,SAAA;;;;;;;;;;;;;;;aA+JA,UAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;aA2CA,cAAA;;;;;;;;;;;;;;;;;;aAmCA,gBAAA"}
|
package/helpers/consts.js
CHANGED
|
@@ -172,6 +172,7 @@ let headerKeys = /* @__PURE__ */ function(headerKeys$1) {
|
|
|
172
172
|
headerKeys$1["InngestRunId"] = "x-run-id";
|
|
173
173
|
headerKeys$1["InngestStepId"] = "x-inngest-step-id";
|
|
174
174
|
headerKeys$1["InngestForceStepPlan"] = "x-inngest-force-step-plan";
|
|
175
|
+
headerKeys$1["SdkHandled"] = "x-inngest-sdk-handled";
|
|
175
176
|
return headerKeys$1;
|
|
176
177
|
}({});
|
|
177
178
|
/**
|
package/helpers/consts.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"consts.js","names":["logPrefix: string"],"sources":["../../src/helpers/consts.ts"],"sourcesContent":["/**\n * Keys for accessing query parameters included in requests from Inngest to run\n * functions.\n *\n * Used internally to create handlers using `InngestCommHandler`, but can be\n * imported to be used if creating a custom handler outside of the package.\n *\n * @public\n */\nexport enum queryKeys {\n DeployId = \"deployId\",\n FnId = \"fnId\",\n Probe = \"probe\",\n StepId = \"stepId\",\n}\n\nexport enum probe {\n Trust = \"trust\",\n}\n\nexport enum envKeys {\n InngestSigningKey = \"INNGEST_SIGNING_KEY\",\n InngestSigningKeyFallback = \"INNGEST_SIGNING_KEY_FALLBACK\",\n InngestEventKey = \"INNGEST_EVENT_KEY\",\n\n /**\n * @deprecated Removed in v3. Use {@link InngestBaseUrl} instead.\n */\n InngestDevServerUrl = \"INNGEST_DEVSERVER_URL\",\n InngestEnvironment = \"INNGEST_ENV\",\n InngestBaseUrl = \"INNGEST_BASE_URL\",\n InngestEventApiBaseUrl = \"INNGEST_EVENT_API_BASE_URL\",\n InngestApiBaseUrl = \"INNGEST_API_BASE_URL\",\n InngestServeHost = \"INNGEST_SERVE_HOST\", // Deprecated, use INNGEST_SERVE_ORIGIN\n InngestServePath = \"INNGEST_SERVE_PATH\",\n InngestServeOrigin = \"INNGEST_SERVE_ORIGIN\",\n InngestStreaming = \"INNGEST_STREAMING\",\n InngestDevMode = \"INNGEST_DEV\",\n InngestAllowInBandSync = \"INNGEST_ALLOW_IN_BAND_SYNC\",\n InngestConnectMaxWorkerConcurrency = \"INNGEST_CONNECT_MAX_WORKER_CONCURRENCY\",\n InngestConnectIsolateExecution = \"INNGEST_CONNECT_ISOLATE_EXECUTION\",\n InngestConnectGatewayUrl = \"INNGEST_CONNECT_GATEWAY_URL\",\n\n /**\n * @deprecated It's unknown what this env var was used for, but we do not\n * provide explicit support for it. Prefer using `INNGEST_ENV` instead.\n */\n BranchName = \"BRANCH_NAME\",\n\n /**\n * The git branch of the commit the deployment was triggered by. Example:\n * `improve-about-page`.\n *\n * {@link https://vercel.com/docs/concepts/projects/environment-variables/system-environment-variables#system-environment-variables}\n */\n VercelBranch = \"VERCEL_GIT_COMMIT_REF\",\n\n /**\n * Expected to be `\"1\"` if defined.\n */\n IsVercel = \"VERCEL\",\n\n /**\n * The branch name of the current deployment. May only be accessible at build\n * time, but included here just in case.\n *\n * {@link https://developers.cloudflare.com/pages/platform/build-configuration/#environment-variables}\n */\n CloudflarePagesBranch = \"CF_PAGES_BRANCH\",\n\n /**\n * Expected to be `\"1\"` if defined.\n */\n IsCloudflarePages = \"CF_PAGES\",\n\n /**\n * The branch name of the deployment from Git to Netlify, if available.\n *\n * {@link https://docs.netlify.com/configure-builds/environment-variables/#git-metadata}\n */\n NetlifyBranch = \"BRANCH\",\n\n /**\n * Expected to be `\"true\"` if defined.\n */\n IsNetlify = \"NETLIFY\",\n\n /**\n * The Git branch for a service or deploy.\n *\n * {@link https://render.com/docs/environment-variables#all-services}\n */\n RenderBranch = \"RENDER_GIT_BRANCH\",\n\n /**\n * Expected to be `\"true\"` if defined.\n */\n IsRender = \"RENDER\",\n\n /**\n * The branch that triggered the deployment. Example: `main`\n *\n * {@link https://docs.railway.app/develop/variables#railway-provided-variables}\n */\n RailwayBranch = \"RAILWAY_GIT_BRANCH\",\n\n /**\n * The railway environment for the deployment. Example: `production`\n *\n * {@link https://docs.railway.app/develop/variables#railway-provided-variables}\n */\n RailwayEnvironment = \"RAILWAY_ENVIRONMENT\",\n\n VercelEnvKey = \"VERCEL_ENV\",\n\n /**\n * Standard Node.js environment indicator (e.g. `\"production\"`, `\"development\"`,\n * `\"test\"`). Read by some framework adapters to choose the request scheme,\n * and by prod-mode inference.\n */\n NodeEnv = \"NODE_ENV\",\n\n /**\n * Netlify's deploy context (e.g. `\"production\"`, `\"deploy-preview\"`). Used\n * for prod-mode inference.\n *\n * {@link https://docs.netlify.com/configure-builds/environment-variables/#build-metadata}\n */\n Context = \"CONTEXT\",\n\n /**\n * Generic environment name used by some platforms to indicate prod vs\n * non-prod (e.g. `\"production\"`).\n */\n Environment = \"ENVIRONMENT\",\n\n /**\n * Set by Deno Deploy. Its presence indicates a Deno Deploy environment,\n * which we treat as prod.\n *\n * {@link https://docs.deno.com/deploy/manual/environment-variables/}\n */\n DenoDeployment = \"DENO_DEPLOYMENT_ID\",\n\n OpenAiApiKey = \"OPENAI_API_KEY\",\n GeminiApiKey = \"GEMINI_API_KEY\",\n AnthropicApiKey = \"ANTHROPIC_API_KEY\",\n\n /**\n * Framework-prefixed variants of Inngest env vars. CRA's `REACT_APP_` and\n * Next's `NEXT_PUBLIC_` prefixes expose env vars to bundled client code, so\n * we accept the prefixed forms in addition to the canonical names.\n */\n ReactAppInngestBaseUrl = \"REACT_APP_INNGEST_BASE_URL\",\n ReactAppInngestDevMode = \"REACT_APP_INNGEST_DEV\",\n NextPublicInngestBaseUrl = \"NEXT_PUBLIC_INNGEST_BASE_URL\",\n NextPublicInngestDevMode = \"NEXT_PUBLIC_INNGEST_DEV\",\n}\n\n/**\n * Keys for accessing headers included in requests from Inngest to run\n * functions.\n *\n * Used internally to create handlers using `InngestCommHandler`, but can be\n * imported to be used if creating a custom handler outside of the package.\n *\n * @public\n */\nexport enum headerKeys {\n ContentType = \"content-type\",\n Host = \"host\",\n ForwardedFor = \"x-forwarded-for\",\n RealIp = \"x-real-ip\",\n Location = \"location\",\n ContentLength = \"content-length\",\n Signature = \"x-inngest-signature\",\n SdkVersion = \"x-inngest-sdk\",\n Environment = \"x-inngest-env\",\n Platform = \"x-inngest-platform\",\n Framework = \"x-inngest-framework\",\n NoRetry = \"x-inngest-no-retry\",\n RequestVersion = \"x-inngest-req-version\",\n RetryAfter = \"retry-after\",\n InngestServerKind = \"x-inngest-server-kind\",\n InngestExpectedServerKind = \"x-inngest-expected-server-kind\",\n InngestSyncKind = \"x-inngest-sync-kind\",\n EventIdSeed = \"x-inngest-event-id-seed\",\n TraceParent = \"traceparent\",\n TraceState = \"tracestate\",\n InngestRunId = \"x-run-id\",\n InngestStepId = \"x-inngest-step-id\",\n InngestForceStepPlan = \"x-inngest-force-step-plan\",\n}\n\n/**\n * Headers that are forwarded from the original request when an Inngest function\n * is invoked.\n */\nexport const forwardedHeaders = [headerKeys.TraceParent, headerKeys.TraceState];\n\nexport const defaultInngestApiBaseUrl = \"https://api.inngest.com/\";\nexport const defaultInngestEventBaseUrl = \"https://inn.gs/\";\nexport const defaultDevServerHost = \"http://localhost:8288/\";\n\n/**\n * Events that Inngest may send internally that can be used to trigger\n * functions.\n *\n * @public\n */\nexport enum internalEvents {\n /**\n * A function has failed after exhausting all available retries. This event\n * will contain the original event and the error that caused the failure.\n */\n FunctionFailed = \"inngest/function.failed\",\n FunctionInvoked = \"inngest/function.invoked\",\n FunctionFinished = \"inngest/function.finished\",\n FunctionCancelled = \"inngest/function.cancelled\",\n ScheduledTimer = \"inngest/scheduled.timer\",\n HttpRequest = \"inngest/http.request\",\n}\n\nexport const logPrefix: string = \"[Inngest]\";\n\nexport const debugPrefix = \"inngest\";\n\nexport const dummyEventKey = \"NO_EVENT_KEY_SET\";\n\nexport enum serverKind {\n Dev = \"dev\",\n Cloud = \"cloud\",\n}\n\nexport enum syncKind {\n InBand = \"in_band\",\n OutOfBand = \"out_of_band\",\n}\n\n/**\n * The execution models the SDK is aware of.\n *\n * This is used in a number of places to ensure all execution versions are\n * accounted for for a given operation.\n */\nexport enum ExecutionVersion {\n /**\n * Uses a more flexible approach to execution and is more lenient about\n * determinism, allowing non-step async actions and non-determinism.\n *\n * Nowhere near as stubborn about determinism and so can silently migrate\n * between versions after bug fixes.\n */\n V1 = 1,\n\n /**\n * Identical to V1, but allows the Executor to optimize parallel calls, hugely\n * reducing traffic going to/from the SDK.\n */\n V2 = 2,\n}\n\n/**\n * Default maximum number of retries for function/step executions.\n */\nexport const defaultMaxRetries = 3;\n"],"mappings":";;;;;;;;;;AASA,IAAY,kDAAL;AACL;AACA;AACA;AACA;;;AAGF,IAAY,0CAAL;AACL;;;AAGF,IAAY,8CAAL;AACL;AACA;AACA;;;;AAKA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;AAMA;;;;;;;AAQA;;;;AAKA;;;;;;;AAQA;;;;AAKA;;;;;;AAOA;;;;AAKA;;;;;;AAOA;;;;AAKA;;;;;;AAOA;;;;;;AAOA;AAEA;;;;;;AAOA;;;;;;;AAQA;;;;;AAMA;;;;;;;AAQA;AAEA;AACA;AACA;;;;;;AAOA;AACA;AACA;AACA;;;;;;;;;;;;AAYF,IAAY,oDAAL;AACL;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;;;AAOF,MAAa,mBAAmB,CAAC,WAAW,aAAa,WAAW,WAAW;AAE/E,MAAa,2BAA2B;AACxC,MAAa,6BAA6B;AAC1C,MAAa,uBAAuB;;;;;;;AAQpC,IAAY,4DAAL;;;;;AAKL;AACA;AACA;AACA;AACA;AACA;;;AAGF,MAAaA,YAAoB;AAEjC,MAAa,cAAc;AAE3B,MAAa,gBAAgB;AAO7B,IAAY,gDAAL;AACL;AACA;;;;;;;;;AASF,IAAY,gEAAL;;;;;;;;AAQL;;;;;AAMA;;;;;;AAMF,MAAa,oBAAoB"}
|
|
1
|
+
{"version":3,"file":"consts.js","names":["logPrefix: string"],"sources":["../../src/helpers/consts.ts"],"sourcesContent":["/**\n * Keys for accessing query parameters included in requests from Inngest to run\n * functions.\n *\n * Used internally to create handlers using `InngestCommHandler`, but can be\n * imported to be used if creating a custom handler outside of the package.\n *\n * @public\n */\nexport enum queryKeys {\n DeployId = \"deployId\",\n FnId = \"fnId\",\n Probe = \"probe\",\n StepId = \"stepId\",\n}\n\nexport enum probe {\n Trust = \"trust\",\n}\n\nexport enum envKeys {\n InngestSigningKey = \"INNGEST_SIGNING_KEY\",\n InngestSigningKeyFallback = \"INNGEST_SIGNING_KEY_FALLBACK\",\n InngestEventKey = \"INNGEST_EVENT_KEY\",\n\n /**\n * @deprecated Removed in v3. Use {@link InngestBaseUrl} instead.\n */\n InngestDevServerUrl = \"INNGEST_DEVSERVER_URL\",\n InngestEnvironment = \"INNGEST_ENV\",\n InngestBaseUrl = \"INNGEST_BASE_URL\",\n InngestEventApiBaseUrl = \"INNGEST_EVENT_API_BASE_URL\",\n InngestApiBaseUrl = \"INNGEST_API_BASE_URL\",\n InngestServeHost = \"INNGEST_SERVE_HOST\", // Deprecated, use INNGEST_SERVE_ORIGIN\n InngestServePath = \"INNGEST_SERVE_PATH\",\n InngestServeOrigin = \"INNGEST_SERVE_ORIGIN\",\n InngestStreaming = \"INNGEST_STREAMING\",\n InngestDevMode = \"INNGEST_DEV\",\n InngestAllowInBandSync = \"INNGEST_ALLOW_IN_BAND_SYNC\",\n InngestConnectMaxWorkerConcurrency = \"INNGEST_CONNECT_MAX_WORKER_CONCURRENCY\",\n InngestConnectIsolateExecution = \"INNGEST_CONNECT_ISOLATE_EXECUTION\",\n InngestConnectGatewayUrl = \"INNGEST_CONNECT_GATEWAY_URL\",\n\n /**\n * @deprecated It's unknown what this env var was used for, but we do not\n * provide explicit support for it. Prefer using `INNGEST_ENV` instead.\n */\n BranchName = \"BRANCH_NAME\",\n\n /**\n * The git branch of the commit the deployment was triggered by. Example:\n * `improve-about-page`.\n *\n * {@link https://vercel.com/docs/concepts/projects/environment-variables/system-environment-variables#system-environment-variables}\n */\n VercelBranch = \"VERCEL_GIT_COMMIT_REF\",\n\n /**\n * Expected to be `\"1\"` if defined.\n */\n IsVercel = \"VERCEL\",\n\n /**\n * The branch name of the current deployment. May only be accessible at build\n * time, but included here just in case.\n *\n * {@link https://developers.cloudflare.com/pages/platform/build-configuration/#environment-variables}\n */\n CloudflarePagesBranch = \"CF_PAGES_BRANCH\",\n\n /**\n * Expected to be `\"1\"` if defined.\n */\n IsCloudflarePages = \"CF_PAGES\",\n\n /**\n * The branch name of the deployment from Git to Netlify, if available.\n *\n * {@link https://docs.netlify.com/configure-builds/environment-variables/#git-metadata}\n */\n NetlifyBranch = \"BRANCH\",\n\n /**\n * Expected to be `\"true\"` if defined.\n */\n IsNetlify = \"NETLIFY\",\n\n /**\n * The Git branch for a service or deploy.\n *\n * {@link https://render.com/docs/environment-variables#all-services}\n */\n RenderBranch = \"RENDER_GIT_BRANCH\",\n\n /**\n * Expected to be `\"true\"` if defined.\n */\n IsRender = \"RENDER\",\n\n /**\n * The branch that triggered the deployment. Example: `main`\n *\n * {@link https://docs.railway.app/develop/variables#railway-provided-variables}\n */\n RailwayBranch = \"RAILWAY_GIT_BRANCH\",\n\n /**\n * The railway environment for the deployment. Example: `production`\n *\n * {@link https://docs.railway.app/develop/variables#railway-provided-variables}\n */\n RailwayEnvironment = \"RAILWAY_ENVIRONMENT\",\n\n VercelEnvKey = \"VERCEL_ENV\",\n\n /**\n * Standard Node.js environment indicator (e.g. `\"production\"`, `\"development\"`,\n * `\"test\"`). Read by some framework adapters to choose the request scheme,\n * and by prod-mode inference.\n */\n NodeEnv = \"NODE_ENV\",\n\n /**\n * Netlify's deploy context (e.g. `\"production\"`, `\"deploy-preview\"`). Used\n * for prod-mode inference.\n *\n * {@link https://docs.netlify.com/configure-builds/environment-variables/#build-metadata}\n */\n Context = \"CONTEXT\",\n\n /**\n * Generic environment name used by some platforms to indicate prod vs\n * non-prod (e.g. `\"production\"`).\n */\n Environment = \"ENVIRONMENT\",\n\n /**\n * Set by Deno Deploy. Its presence indicates a Deno Deploy environment,\n * which we treat as prod.\n *\n * {@link https://docs.deno.com/deploy/manual/environment-variables/}\n */\n DenoDeployment = \"DENO_DEPLOYMENT_ID\",\n\n OpenAiApiKey = \"OPENAI_API_KEY\",\n GeminiApiKey = \"GEMINI_API_KEY\",\n AnthropicApiKey = \"ANTHROPIC_API_KEY\",\n\n /**\n * Framework-prefixed variants of Inngest env vars. CRA's `REACT_APP_` and\n * Next's `NEXT_PUBLIC_` prefixes expose env vars to bundled client code, so\n * we accept the prefixed forms in addition to the canonical names.\n */\n ReactAppInngestBaseUrl = \"REACT_APP_INNGEST_BASE_URL\",\n ReactAppInngestDevMode = \"REACT_APP_INNGEST_DEV\",\n NextPublicInngestBaseUrl = \"NEXT_PUBLIC_INNGEST_BASE_URL\",\n NextPublicInngestDevMode = \"NEXT_PUBLIC_INNGEST_DEV\",\n}\n\n/**\n * Keys for accessing headers included in requests from Inngest to run\n * functions.\n *\n * Used internally to create handlers using `InngestCommHandler`, but can be\n * imported to be used if creating a custom handler outside of the package.\n *\n * @public\n */\nexport enum headerKeys {\n ContentType = \"content-type\",\n Host = \"host\",\n ForwardedFor = \"x-forwarded-for\",\n RealIp = \"x-real-ip\",\n Location = \"location\",\n ContentLength = \"content-length\",\n Signature = \"x-inngest-signature\",\n SdkVersion = \"x-inngest-sdk\",\n Environment = \"x-inngest-env\",\n Platform = \"x-inngest-platform\",\n Framework = \"x-inngest-framework\",\n NoRetry = \"x-inngest-no-retry\",\n RequestVersion = \"x-inngest-req-version\",\n RetryAfter = \"retry-after\",\n InngestServerKind = \"x-inngest-server-kind\",\n InngestExpectedServerKind = \"x-inngest-expected-server-kind\",\n InngestSyncKind = \"x-inngest-sync-kind\",\n EventIdSeed = \"x-inngest-event-id-seed\",\n TraceParent = \"traceparent\",\n TraceState = \"tracestate\",\n InngestRunId = \"x-run-id\",\n InngestStepId = \"x-inngest-step-id\",\n InngestForceStepPlan = \"x-inngest-force-step-plan\",\n SdkHandled = \"x-inngest-sdk-handled\",\n}\n\n/**\n * Headers that are forwarded from the original request when an Inngest function\n * is invoked.\n */\nexport const forwardedHeaders = [headerKeys.TraceParent, headerKeys.TraceState];\n\nexport const defaultInngestApiBaseUrl = \"https://api.inngest.com/\";\nexport const defaultInngestEventBaseUrl = \"https://inn.gs/\";\nexport const defaultDevServerHost = \"http://localhost:8288/\";\n\n/**\n * Events that Inngest may send internally that can be used to trigger\n * functions.\n *\n * @public\n */\nexport enum internalEvents {\n /**\n * A function has failed after exhausting all available retries. This event\n * will contain the original event and the error that caused the failure.\n */\n FunctionFailed = \"inngest/function.failed\",\n FunctionInvoked = \"inngest/function.invoked\",\n FunctionFinished = \"inngest/function.finished\",\n FunctionCancelled = \"inngest/function.cancelled\",\n ScheduledTimer = \"inngest/scheduled.timer\",\n HttpRequest = \"inngest/http.request\",\n}\n\nexport const logPrefix: string = \"[Inngest]\";\n\nexport const debugPrefix = \"inngest\";\n\nexport const dummyEventKey = \"NO_EVENT_KEY_SET\";\n\nexport enum serverKind {\n Dev = \"dev\",\n Cloud = \"cloud\",\n}\n\nexport enum syncKind {\n InBand = \"in_band\",\n OutOfBand = \"out_of_band\",\n}\n\n/**\n * The execution models the SDK is aware of.\n *\n * This is used in a number of places to ensure all execution versions are\n * accounted for for a given operation.\n */\nexport enum ExecutionVersion {\n /**\n * Uses a more flexible approach to execution and is more lenient about\n * determinism, allowing non-step async actions and non-determinism.\n *\n * Nowhere near as stubborn about determinism and so can silently migrate\n * between versions after bug fixes.\n */\n V1 = 1,\n\n /**\n * Identical to V1, but allows the Executor to optimize parallel calls, hugely\n * reducing traffic going to/from the SDK.\n */\n V2 = 2,\n}\n\n/**\n * Default maximum number of retries for function/step executions.\n */\nexport const defaultMaxRetries = 3;\n"],"mappings":";;;;;;;;;;AASA,IAAY,kDAAL;AACL;AACA;AACA;AACA;;;AAGF,IAAY,0CAAL;AACL;;;AAGF,IAAY,8CAAL;AACL;AACA;AACA;;;;AAKA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;AAMA;;;;;;;AAQA;;;;AAKA;;;;;;;AAQA;;;;AAKA;;;;;;AAOA;;;;AAKA;;;;;;AAOA;;;;AAKA;;;;;;AAOA;;;;;;AAOA;AAEA;;;;;;AAOA;;;;;;;AAQA;;;;;AAMA;;;;;;;AAQA;AAEA;AACA;AACA;;;;;;AAOA;AACA;AACA;AACA;;;;;;;;;;;;AAYF,IAAY,oDAAL;AACL;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;;;AAOF,MAAa,mBAAmB,CAAC,WAAW,aAAa,WAAW,WAAW;AAE/E,MAAa,2BAA2B;AACxC,MAAa,6BAA6B;AAC1C,MAAa,uBAAuB;;;;;;;AAQpC,IAAY,4DAAL;;;;;AAKL;AACA;AACA;AACA;AACA;AACA;;;AAGF,MAAaA,YAAoB;AAEjC,MAAa,cAAc;AAE3B,MAAa,gBAAgB;AAO7B,IAAY,gDAAL;AACL;AACA;;;;;;;;;AASF,IAAY,gEAAL;;;;;;;;AAQL;;;;;AAMA;;;;;;AAMF,MAAa,oBAAoB"}
|
package/helpers/env.cjs
CHANGED
|
@@ -96,7 +96,8 @@ const inngestHeaders = (opts) => {
|
|
|
96
96
|
const headers = {
|
|
97
97
|
"Content-Type": "application/json",
|
|
98
98
|
"User-Agent": sdkVersion,
|
|
99
|
-
[require_consts.headerKeys.SdkVersion]: sdkVersion
|
|
99
|
+
[require_consts.headerKeys.SdkVersion]: sdkVersion,
|
|
100
|
+
[require_consts.headerKeys.SdkHandled]: "true"
|
|
100
101
|
};
|
|
101
102
|
if (opts?.framework) headers[require_consts.headerKeys.Framework] = opts.framework;
|
|
102
103
|
if (opts?.expectedServerKind) headers[require_consts.headerKeys.InngestExpectedServerKind] = opts.expectedServerKind;
|
package/helpers/env.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"env.cjs","names":["envKeys","env: Env","whitelist: string[]","version","headers: Record<string, string>","headerKeys","customFetch: typeof fetch"],"sources":["../../src/helpers/env.ts"],"sourcesContent":["// This file exists to help normalize process.env amongst the backend\n// and frontend. Many frontends (eg. Next, CRA) utilize webpack's DefinePlugin\n// along with prefixes, meaning we have to explicitly use the full `process.env.FOO`\n// string in order to read variables.\n\nimport type { Inngest } from \"../components/Inngest.ts\";\nimport type { Logger } from \"../middleware/logger.ts\";\nimport type { SupportedFrameworkName } from \"../types.ts\";\nimport { version } from \"../version.ts\";\nimport { envKeys, headerKeys } from \"./consts.ts\";\n\n/**\n * @public\n */\nexport type Env = Record<string, EnvValue>;\n\n/**\n * @public\n */\nexport type EnvValue = string | undefined;\n\n/**\n * devServerHost returns the dev server host by searching for the INNGEST_DEVSERVER_URL\n * environment variable (plus project prefixces for eg. react, such as REACT_APP_INNGEST_DEVSERVER_URL).\n *\n * If not found this returns undefined, indicating that the env var has not been set.\n *\n * @example devServerHost()\n */\nexport const devServerHost = (env: Env = getProcessEnv()): EnvValue => {\n // The prefixed keys we look up for common frameworks (CRA, Next). The\n // unprefixed `INNGEST_BASE_URL` / `INNGEST_DEV` are read directly by the\n // Inngest client elsewhere, so we only check the prefixed variants here.\n const keys = [\n envKeys.ReactAppInngestBaseUrl,\n envKeys.NextPublicInngestBaseUrl,\n envKeys.ReactAppInngestDevMode,\n envKeys.NextPublicInngestDevMode,\n ];\n const values = keys.map((key) => {\n return env[key];\n });\n\n return values.find((v) => {\n if (!v) {\n return;\n }\n\n try {\n return Boolean(new URL(v));\n } catch {\n // no-op\n }\n\n return;\n });\n};\n\nexport type Mode = \"cloud\" | \"dev\";\n\nexport function checkModeConfiguration({\n internalLogger,\n mode,\n signingKey,\n}: {\n internalLogger: Logger;\n mode: Mode;\n signingKey: string | undefined;\n}): boolean {\n if (mode === \"cloud\" && !signingKey) {\n internalLogger.error(\n `In cloud mode but no signing key found. For local dev, set the INNGEST_DEV=1 env var. For production, set the ${envKeys.InngestSigningKey} env var`,\n );\n\n return false;\n }\n\n return true;\n}\n\nexport const normalizeUrl = (\n urlString: string,\n scheme: string = \"http://\",\n): string => {\n if (urlString === \"undefined\") {\n throw new Error(\"URL undefined\");\n }\n if (urlString.includes(\"://\")) {\n return urlString;\n }\n\n return `${scheme}${urlString}`;\n};\n\n/**\n * getEnvironmentName returns the suspected branch name for this environment by\n * searching through a set of common environment variables.\n *\n * This could be used to determine if we're on a branch deploy or not, though it\n * should be noted that we don't know if this is the default branch or not.\n */\nexport const getEnvironmentName = (env: Env = getProcessEnv()): EnvValue => {\n /**\n * Order is important; more than one of these env vars may be set, so ensure\n * that we check the most specific, most reliable env vars first.\n */\n return (\n env[envKeys.InngestEnvironment] ||\n env[envKeys.BranchName] ||\n env[envKeys.VercelBranch] ||\n env[envKeys.NetlifyBranch] ||\n env[envKeys.CloudflarePagesBranch] ||\n env[envKeys.RenderBranch] ||\n env[envKeys.RailwayBranch]\n );\n};\n\nexport const processEnv = (key: envKeys): EnvValue => {\n if (!Object.values(envKeys).includes(key)) {\n throw new Error(`Unknown env var: ${key}`);\n }\n\n return getProcessEnv()[key];\n};\n\n/**\n * The Deno environment, which is not always available.\n */\ndeclare const Deno: {\n env: { toObject: () => Env };\n};\n\n/**\n * The Netlify environment, which is not always available.\n */\ndeclare const Netlify: {\n env: { toObject: () => Env };\n};\n\n/**\n * Get the current process env vars. Only includes env vars that we care about.\n *\n * Returns an empty object if they can't be read.\n */\nexport function getProcessEnv(): Env {\n const env: Env = {};\n const whitelist: string[] = Object.values(envKeys);\n\n for (const [k, v] of Object.entries(allProcessEnv())) {\n if (!whitelist.includes(k)) {\n continue;\n }\n env[k] = v;\n }\n\n return protectEnv(env);\n}\n\n/**\n * Install a `toJSON` that returns `{}` so env var values can't leak via\n * `JSON.stringify`, regardless of where the object is reachable from. The\n * property is enumerable so it survives spreads (e.g. `{...env}`) which carries\n * the protection into the new object. But note that the enumerability also\n * means the static type is technically incorrect.\n *\n * Callers still read values via normal `env[key]` access.\n */\nexport function protectEnv(env: Env): Env {\n return {\n ...env,\n\n // @ts-expect-error - intentional\n toJSON: () => {\n return {};\n },\n };\n}\n\n/**\n * allProcessEnv returns the current process environment variables, or an empty\n * object if they cannot be read, making sure we support environments other than\n * Node such as Deno, too.\n *\n * Using this ensures we don't dangerously access `process.env` in environments\n * where it may not be defined, such as Deno or the browser.\n */\nconst allProcessEnv = (): Env => {\n // Node, or Node-like environments\n try {\n if (process.env) {\n return process.env;\n }\n } catch (_err) {\n // noop\n }\n\n // Deno\n try {\n const env = Deno.env.toObject();\n\n if (env) {\n return env;\n }\n } catch (_err) {\n // noop\n }\n\n // Netlify\n try {\n const env = Netlify.env.toObject();\n\n if (env) {\n return env;\n }\n } catch (_err) {\n // noop\n }\n\n return {};\n};\n\n/**\n * Generate a standardised set of headers based on input and environment\n * variables.\n *\n *\n */\nexport const inngestHeaders = (opts?: {\n /**\n * The environment variables to use instead of `process.env` or any other\n * default source. Useful for platforms where environment variables are passed\n * in alongside requests.\n */\n env?: Env;\n\n /**\n * The framework name to use in the `X-Inngest-Framework` header. This is not\n * always available, hence being optional.\n */\n framework?: string;\n\n /**\n * The environment name to use in the `X-Inngest-Env` header. This is likely\n * to be representative of the target preview environment.\n */\n inngestEnv?: string;\n\n /**\n * The Inngest client that's making the request. The client itself will\n * generate a set of headers; specifying it here will ensure that the client's\n * headers are included in the returned headers.\n */\n client?: Inngest;\n\n /**\n * The Inngest server we expect to be communicating with, used to ensure that\n * various parts of a handshake are all happening with the same type of\n * participant.\n */\n expectedServerKind?: string;\n\n /**\n * Any additional headers to include in the returned headers.\n */\n extras?: Record<string, string>;\n}): Record<string, string> => {\n const sdkVersion = `inngest-js:v${version}`;\n const headers: Record<string, string> = {\n \"Content-Type\": \"application/json\",\n \"User-Agent\": sdkVersion,\n [headerKeys.SdkVersion]: sdkVersion,\n };\n\n if (opts?.framework) {\n headers[headerKeys.Framework] = opts.framework;\n }\n\n if (opts?.expectedServerKind) {\n headers[headerKeys.InngestExpectedServerKind] = opts.expectedServerKind;\n }\n\n const env = {\n ...getProcessEnv(),\n ...opts?.env,\n };\n\n const inngestEnv = opts?.inngestEnv || getEnvironmentName(env);\n if (inngestEnv) {\n headers[headerKeys.Environment] = inngestEnv;\n }\n\n const platform = getPlatformName(env);\n if (platform) {\n headers[headerKeys.Platform] = platform;\n }\n\n return {\n ...headers,\n ...opts?.client?.[\"headers\"],\n ...opts?.extras,\n };\n};\n\n/**\n * A set of checks that, given an environment, will return `true` if the current\n * environment is running on the platform with the given name.\n */\nconst platformChecks = {\n /**\n * Vercel Edge Functions don't have access to environment variables unless\n * they are explicitly referenced in the top level code, but they do have a\n * global `EdgeRuntime` variable set that we can use to detect this.\n */\n vercel: (env) =>\n env[envKeys.IsVercel] === \"1\" || typeof EdgeRuntime === \"string\",\n netlify: (env) => env[envKeys.IsNetlify] === \"true\",\n \"cloudflare-pages\": (env) => env[envKeys.IsCloudflarePages] === \"1\",\n render: (env) => env[envKeys.IsRender] === \"true\",\n railway: (env) => Boolean(env[envKeys.RailwayEnvironment]),\n} satisfies Record<string, (env: Env) => boolean>;\n\ndeclare const EdgeRuntime: string | undefined;\n\n/**\n * A set of checks that, given an environment, will return `true` if the current\n * environment and platform supports streaming responses back to Inngest.\n *\n * Streaming capability is both framework and platform-based. Frameworks are\n * supported in serve handlers, and platforms are checked here.\n *\n * As such, this record declares which platforms we explicitly support for\n * streaming and is used by {@link platformSupportsStreaming}.\n */\nconst streamingChecks: Partial<\n Record<\n keyof typeof platformChecks,\n (framework: SupportedFrameworkName, env: Env) => boolean\n >\n> = {\n /**\n * \"Vercel supports streaming for Serverless Functions, Edge Functions, and\n * React Server Components in Next.js projects.\"\n *\n * In practice, however, there are many reports of streaming not working as\n * expected on Serverless Functions, so we resort to only allowing streaming\n * for Edge Functions here.\n *\n * See {@link https://vercel.com/docs/frameworks/nextjs#streaming}\n */\n vercel: (_framework, _env) => typeof EdgeRuntime === \"string\",\n \"cloudflare-pages\": () => true,\n};\n\nexport const getPlatformName = (env: Env) => {\n return (Object.keys(platformChecks) as (keyof typeof platformChecks)[]).find(\n (key) => {\n return platformChecks[key](env);\n },\n );\n};\n\n/**\n * Returns `true` if we believe the current environment supports streaming\n * responses back to Inngest.\n *\n * We run a check directly related to the platform we believe we're running on,\n * usually based on environment variables.\n */\nexport const platformSupportsStreaming = (\n framework: SupportedFrameworkName,\n env: Env = getProcessEnv(),\n): boolean => {\n return (\n streamingChecks[getPlatformName(env) as keyof typeof streamingChecks]?.(\n framework,\n env,\n ) ?? false\n );\n};\n\n/**\n * A unique symbol used to mark a custom fetch implementation. We wrap the\n * implementations to provide some extra control when handling errors.\n */\nconst CUSTOM_FETCH_MARKER = Symbol(\"Custom fetch implementation\");\n\n/**\n * Given a potential fetch function, return the fetch function to use based on\n * this and the environment.\n */\nexport const getFetch = (\n logger: Logger,\n givenFetch?: typeof fetch,\n): typeof fetch => {\n /**\n * If we've explicitly been given a fetch function, use that.\n */\n if (givenFetch) {\n if (CUSTOM_FETCH_MARKER in givenFetch) {\n return givenFetch;\n }\n\n /**\n * We wrap the given fetch function to provide some extra control when\n * handling errors.\n */\n const customFetch: typeof fetch = async (...args) => {\n try {\n return await givenFetch(...args);\n } catch (err) {\n /**\n * Capture warnings that are not simple fetch failures and highlight\n * them for the user.\n *\n * We also use this opportunity to log the causing error, as code higher\n * up the stack will likely abstract this.\n */\n if (\n !(err instanceof Error) ||\n !err.message?.startsWith(\"fetch failed\")\n ) {\n logger.error(\n { err },\n \"A request failed when using a custom fetch implementation; this may be a misconfiguration. Make sure that your fetch client is correctly bound to the global scope.\",\n );\n }\n\n throw err;\n }\n };\n\n /**\n * Mark the custom fetch implementation so that we can identify it later, in\n * addition to adding some runtime properties to it to make it seem as much\n * like the original fetch as possible.\n */\n Object.defineProperties(customFetch, {\n [CUSTOM_FETCH_MARKER]: {},\n name: { value: givenFetch.name },\n length: { value: givenFetch.length },\n });\n\n return customFetch;\n }\n\n /**\n * Browser or Node 18+\n */\n try {\n if (typeof globalThis !== \"undefined\" && \"fetch\" in globalThis) {\n return fetch.bind(globalThis);\n }\n } catch (_err) {\n // no-op\n }\n\n /**\n * Existing polyfilled fetch\n */\n if (typeof fetch !== \"undefined\") {\n return fetch;\n }\n\n /**\n * Environments where fetch cannot be found and must be polyfilled\n */\n return require(\"cross-fetch\") as typeof fetch;\n};\n\n/**\n * If `Response` isn't included in this environment, it's probably an earlier\n * Node env that isn't already polyfilling. This function returns either the\n * native `Response` or a polyfilled one.\n */\nexport const getResponse = (): typeof Response => {\n if (typeof Response !== \"undefined\") {\n return Response;\n }\n\n return require(\"cross-fetch\").Response;\n};\n\n/**\n * Given an unknown value, try to parse it as a `boolean`. Useful for parsing\n * environment variables that could be a selection of different values such as\n * `\"true\"`, `\"1\"`.\n *\n * If the value could not be confidently parsed as a `boolean` or was seen to be\n * `undefined`, this function returns `undefined`.\n */\nexport const parseAsBoolean = (value: unknown): boolean | undefined => {\n if (typeof value === \"boolean\") {\n return value;\n }\n\n if (typeof value === \"number\") {\n return Boolean(value);\n }\n\n if (typeof value === \"string\") {\n const trimmed = value.trim().toLowerCase();\n\n if (trimmed === \"undefined\") {\n return undefined;\n }\n\n if ([\"true\", \"1\"].includes(trimmed)) {\n return true;\n }\n\n if ([\"false\", \"0\"].includes(trimmed)) {\n return false;\n }\n }\n\n return undefined;\n};\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"env.cjs","names":["envKeys","env: Env","whitelist: string[]","version","headers: Record<string, string>","headerKeys","customFetch: typeof fetch"],"sources":["../../src/helpers/env.ts"],"sourcesContent":["// This file exists to help normalize process.env amongst the backend\n// and frontend. Many frontends (eg. Next, CRA) utilize webpack's DefinePlugin\n// along with prefixes, meaning we have to explicitly use the full `process.env.FOO`\n// string in order to read variables.\n\nimport type { Inngest } from \"../components/Inngest.ts\";\nimport type { Logger } from \"../middleware/logger.ts\";\nimport type { SupportedFrameworkName } from \"../types.ts\";\nimport { version } from \"../version.ts\";\nimport { envKeys, headerKeys } from \"./consts.ts\";\n\n/**\n * @public\n */\nexport type Env = Record<string, EnvValue>;\n\n/**\n * @public\n */\nexport type EnvValue = string | undefined;\n\n/**\n * devServerHost returns the dev server host by searching for the INNGEST_DEVSERVER_URL\n * environment variable (plus project prefixces for eg. react, such as REACT_APP_INNGEST_DEVSERVER_URL).\n *\n * If not found this returns undefined, indicating that the env var has not been set.\n *\n * @example devServerHost()\n */\nexport const devServerHost = (env: Env = getProcessEnv()): EnvValue => {\n // The prefixed keys we look up for common frameworks (CRA, Next). The\n // unprefixed `INNGEST_BASE_URL` / `INNGEST_DEV` are read directly by the\n // Inngest client elsewhere, so we only check the prefixed variants here.\n const keys = [\n envKeys.ReactAppInngestBaseUrl,\n envKeys.NextPublicInngestBaseUrl,\n envKeys.ReactAppInngestDevMode,\n envKeys.NextPublicInngestDevMode,\n ];\n const values = keys.map((key) => {\n return env[key];\n });\n\n return values.find((v) => {\n if (!v) {\n return;\n }\n\n try {\n return Boolean(new URL(v));\n } catch {\n // no-op\n }\n\n return;\n });\n};\n\nexport type Mode = \"cloud\" | \"dev\";\n\nexport function checkModeConfiguration({\n internalLogger,\n mode,\n signingKey,\n}: {\n internalLogger: Logger;\n mode: Mode;\n signingKey: string | undefined;\n}): boolean {\n if (mode === \"cloud\" && !signingKey) {\n internalLogger.error(\n `In cloud mode but no signing key found. For local dev, set the INNGEST_DEV=1 env var. For production, set the ${envKeys.InngestSigningKey} env var`,\n );\n\n return false;\n }\n\n return true;\n}\n\nexport const normalizeUrl = (\n urlString: string,\n scheme: string = \"http://\",\n): string => {\n if (urlString === \"undefined\") {\n throw new Error(\"URL undefined\");\n }\n if (urlString.includes(\"://\")) {\n return urlString;\n }\n\n return `${scheme}${urlString}`;\n};\n\n/**\n * getEnvironmentName returns the suspected branch name for this environment by\n * searching through a set of common environment variables.\n *\n * This could be used to determine if we're on a branch deploy or not, though it\n * should be noted that we don't know if this is the default branch or not.\n */\nexport const getEnvironmentName = (env: Env = getProcessEnv()): EnvValue => {\n /**\n * Order is important; more than one of these env vars may be set, so ensure\n * that we check the most specific, most reliable env vars first.\n */\n return (\n env[envKeys.InngestEnvironment] ||\n env[envKeys.BranchName] ||\n env[envKeys.VercelBranch] ||\n env[envKeys.NetlifyBranch] ||\n env[envKeys.CloudflarePagesBranch] ||\n env[envKeys.RenderBranch] ||\n env[envKeys.RailwayBranch]\n );\n};\n\nexport const processEnv = (key: envKeys): EnvValue => {\n if (!Object.values(envKeys).includes(key)) {\n throw new Error(`Unknown env var: ${key}`);\n }\n\n return getProcessEnv()[key];\n};\n\n/**\n * The Deno environment, which is not always available.\n */\ndeclare const Deno: {\n env: { toObject: () => Env };\n};\n\n/**\n * The Netlify environment, which is not always available.\n */\ndeclare const Netlify: {\n env: { toObject: () => Env };\n};\n\n/**\n * Get the current process env vars. Only includes env vars that we care about.\n *\n * Returns an empty object if they can't be read.\n */\nexport function getProcessEnv(): Env {\n const env: Env = {};\n const whitelist: string[] = Object.values(envKeys);\n\n for (const [k, v] of Object.entries(allProcessEnv())) {\n if (!whitelist.includes(k)) {\n continue;\n }\n env[k] = v;\n }\n\n return protectEnv(env);\n}\n\n/**\n * Install a `toJSON` that returns `{}` so env var values can't leak via\n * `JSON.stringify`, regardless of where the object is reachable from. The\n * property is enumerable so it survives spreads (e.g. `{...env}`) which carries\n * the protection into the new object. But note that the enumerability also\n * means the static type is technically incorrect.\n *\n * Callers still read values via normal `env[key]` access.\n */\nexport function protectEnv(env: Env): Env {\n return {\n ...env,\n\n // @ts-expect-error - intentional\n toJSON: () => {\n return {};\n },\n };\n}\n\n/**\n * allProcessEnv returns the current process environment variables, or an empty\n * object if they cannot be read, making sure we support environments other than\n * Node such as Deno, too.\n *\n * Using this ensures we don't dangerously access `process.env` in environments\n * where it may not be defined, such as Deno or the browser.\n */\nconst allProcessEnv = (): Env => {\n // Node, or Node-like environments\n try {\n if (process.env) {\n return process.env;\n }\n } catch (_err) {\n // noop\n }\n\n // Deno\n try {\n const env = Deno.env.toObject();\n\n if (env) {\n return env;\n }\n } catch (_err) {\n // noop\n }\n\n // Netlify\n try {\n const env = Netlify.env.toObject();\n\n if (env) {\n return env;\n }\n } catch (_err) {\n // noop\n }\n\n return {};\n};\n\n/**\n * Generate a standardised set of headers based on input and environment\n * variables.\n *\n *\n */\nexport const inngestHeaders = (opts?: {\n /**\n * The environment variables to use instead of `process.env` or any other\n * default source. Useful for platforms where environment variables are passed\n * in alongside requests.\n */\n env?: Env;\n\n /**\n * The framework name to use in the `X-Inngest-Framework` header. This is not\n * always available, hence being optional.\n */\n framework?: string;\n\n /**\n * The environment name to use in the `X-Inngest-Env` header. This is likely\n * to be representative of the target preview environment.\n */\n inngestEnv?: string;\n\n /**\n * The Inngest client that's making the request. The client itself will\n * generate a set of headers; specifying it here will ensure that the client's\n * headers are included in the returned headers.\n */\n client?: Inngest;\n\n /**\n * The Inngest server we expect to be communicating with, used to ensure that\n * various parts of a handshake are all happening with the same type of\n * participant.\n */\n expectedServerKind?: string;\n\n /**\n * Any additional headers to include in the returned headers.\n */\n extras?: Record<string, string>;\n}): Record<string, string> => {\n const sdkVersion = `inngest-js:v${version}`;\n const headers: Record<string, string> = {\n \"Content-Type\": \"application/json\",\n \"User-Agent\": sdkVersion,\n [headerKeys.SdkVersion]: sdkVersion,\n [headerKeys.SdkHandled]: \"true\",\n };\n\n if (opts?.framework) {\n headers[headerKeys.Framework] = opts.framework;\n }\n\n if (opts?.expectedServerKind) {\n headers[headerKeys.InngestExpectedServerKind] = opts.expectedServerKind;\n }\n\n const env = {\n ...getProcessEnv(),\n ...opts?.env,\n };\n\n const inngestEnv = opts?.inngestEnv || getEnvironmentName(env);\n if (inngestEnv) {\n headers[headerKeys.Environment] = inngestEnv;\n }\n\n const platform = getPlatformName(env);\n if (platform) {\n headers[headerKeys.Platform] = platform;\n }\n\n return {\n ...headers,\n ...opts?.client?.[\"headers\"],\n ...opts?.extras,\n };\n};\n\n/**\n * A set of checks that, given an environment, will return `true` if the current\n * environment is running on the platform with the given name.\n */\nconst platformChecks = {\n /**\n * Vercel Edge Functions don't have access to environment variables unless\n * they are explicitly referenced in the top level code, but they do have a\n * global `EdgeRuntime` variable set that we can use to detect this.\n */\n vercel: (env) =>\n env[envKeys.IsVercel] === \"1\" || typeof EdgeRuntime === \"string\",\n netlify: (env) => env[envKeys.IsNetlify] === \"true\",\n \"cloudflare-pages\": (env) => env[envKeys.IsCloudflarePages] === \"1\",\n render: (env) => env[envKeys.IsRender] === \"true\",\n railway: (env) => Boolean(env[envKeys.RailwayEnvironment]),\n} satisfies Record<string, (env: Env) => boolean>;\n\ndeclare const EdgeRuntime: string | undefined;\n\n/**\n * A set of checks that, given an environment, will return `true` if the current\n * environment and platform supports streaming responses back to Inngest.\n *\n * Streaming capability is both framework and platform-based. Frameworks are\n * supported in serve handlers, and platforms are checked here.\n *\n * As such, this record declares which platforms we explicitly support for\n * streaming and is used by {@link platformSupportsStreaming}.\n */\nconst streamingChecks: Partial<\n Record<\n keyof typeof platformChecks,\n (framework: SupportedFrameworkName, env: Env) => boolean\n >\n> = {\n /**\n * \"Vercel supports streaming for Serverless Functions, Edge Functions, and\n * React Server Components in Next.js projects.\"\n *\n * In practice, however, there are many reports of streaming not working as\n * expected on Serverless Functions, so we resort to only allowing streaming\n * for Edge Functions here.\n *\n * See {@link https://vercel.com/docs/frameworks/nextjs#streaming}\n */\n vercel: (_framework, _env) => typeof EdgeRuntime === \"string\",\n \"cloudflare-pages\": () => true,\n};\n\nexport const getPlatformName = (env: Env) => {\n return (Object.keys(platformChecks) as (keyof typeof platformChecks)[]).find(\n (key) => {\n return platformChecks[key](env);\n },\n );\n};\n\n/**\n * Returns `true` if we believe the current environment supports streaming\n * responses back to Inngest.\n *\n * We run a check directly related to the platform we believe we're running on,\n * usually based on environment variables.\n */\nexport const platformSupportsStreaming = (\n framework: SupportedFrameworkName,\n env: Env = getProcessEnv(),\n): boolean => {\n return (\n streamingChecks[getPlatformName(env) as keyof typeof streamingChecks]?.(\n framework,\n env,\n ) ?? false\n );\n};\n\n/**\n * A unique symbol used to mark a custom fetch implementation. We wrap the\n * implementations to provide some extra control when handling errors.\n */\nconst CUSTOM_FETCH_MARKER = Symbol(\"Custom fetch implementation\");\n\n/**\n * Given a potential fetch function, return the fetch function to use based on\n * this and the environment.\n */\nexport const getFetch = (\n logger: Logger,\n givenFetch?: typeof fetch,\n): typeof fetch => {\n /**\n * If we've explicitly been given a fetch function, use that.\n */\n if (givenFetch) {\n if (CUSTOM_FETCH_MARKER in givenFetch) {\n return givenFetch;\n }\n\n /**\n * We wrap the given fetch function to provide some extra control when\n * handling errors.\n */\n const customFetch: typeof fetch = async (...args) => {\n try {\n return await givenFetch(...args);\n } catch (err) {\n /**\n * Capture warnings that are not simple fetch failures and highlight\n * them for the user.\n *\n * We also use this opportunity to log the causing error, as code higher\n * up the stack will likely abstract this.\n */\n if (\n !(err instanceof Error) ||\n !err.message?.startsWith(\"fetch failed\")\n ) {\n logger.error(\n { err },\n \"A request failed when using a custom fetch implementation; this may be a misconfiguration. Make sure that your fetch client is correctly bound to the global scope.\",\n );\n }\n\n throw err;\n }\n };\n\n /**\n * Mark the custom fetch implementation so that we can identify it later, in\n * addition to adding some runtime properties to it to make it seem as much\n * like the original fetch as possible.\n */\n Object.defineProperties(customFetch, {\n [CUSTOM_FETCH_MARKER]: {},\n name: { value: givenFetch.name },\n length: { value: givenFetch.length },\n });\n\n return customFetch;\n }\n\n /**\n * Browser or Node 18+\n */\n try {\n if (typeof globalThis !== \"undefined\" && \"fetch\" in globalThis) {\n return fetch.bind(globalThis);\n }\n } catch (_err) {\n // no-op\n }\n\n /**\n * Existing polyfilled fetch\n */\n if (typeof fetch !== \"undefined\") {\n return fetch;\n }\n\n /**\n * Environments where fetch cannot be found and must be polyfilled\n */\n return require(\"cross-fetch\") as typeof fetch;\n};\n\n/**\n * If `Response` isn't included in this environment, it's probably an earlier\n * Node env that isn't already polyfilling. This function returns either the\n * native `Response` or a polyfilled one.\n */\nexport const getResponse = (): typeof Response => {\n if (typeof Response !== \"undefined\") {\n return Response;\n }\n\n return require(\"cross-fetch\").Response;\n};\n\n/**\n * Given an unknown value, try to parse it as a `boolean`. Useful for parsing\n * environment variables that could be a selection of different values such as\n * `\"true\"`, `\"1\"`.\n *\n * If the value could not be confidently parsed as a `boolean` or was seen to be\n * `undefined`, this function returns `undefined`.\n */\nexport const parseAsBoolean = (value: unknown): boolean | undefined => {\n if (typeof value === \"boolean\") {\n return value;\n }\n\n if (typeof value === \"number\") {\n return Boolean(value);\n }\n\n if (typeof value === \"string\") {\n const trimmed = value.trim().toLowerCase();\n\n if (trimmed === \"undefined\") {\n return undefined;\n }\n\n if ([\"true\", \"1\"].includes(trimmed)) {\n return true;\n }\n\n if ([\"false\", \"0\"].includes(trimmed)) {\n return false;\n }\n }\n\n return undefined;\n};\n"],"mappings":"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"}
|
package/helpers/env.js
CHANGED
|
@@ -97,7 +97,8 @@ const inngestHeaders = (opts) => {
|
|
|
97
97
|
const headers = {
|
|
98
98
|
"Content-Type": "application/json",
|
|
99
99
|
"User-Agent": sdkVersion,
|
|
100
|
-
[headerKeys.SdkVersion]: sdkVersion
|
|
100
|
+
[headerKeys.SdkVersion]: sdkVersion,
|
|
101
|
+
[headerKeys.SdkHandled]: "true"
|
|
101
102
|
};
|
|
102
103
|
if (opts?.framework) headers[headerKeys.Framework] = opts.framework;
|
|
103
104
|
if (opts?.expectedServerKind) headers[headerKeys.InngestExpectedServerKind] = opts.expectedServerKind;
|
package/helpers/env.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"env.js","names":["env: Env","whitelist: string[]","headers: Record<string, string>","customFetch: typeof fetch"],"sources":["../../src/helpers/env.ts"],"sourcesContent":["// This file exists to help normalize process.env amongst the backend\n// and frontend. Many frontends (eg. Next, CRA) utilize webpack's DefinePlugin\n// along with prefixes, meaning we have to explicitly use the full `process.env.FOO`\n// string in order to read variables.\n\nimport type { Inngest } from \"../components/Inngest.ts\";\nimport type { Logger } from \"../middleware/logger.ts\";\nimport type { SupportedFrameworkName } from \"../types.ts\";\nimport { version } from \"../version.ts\";\nimport { envKeys, headerKeys } from \"./consts.ts\";\n\n/**\n * @public\n */\nexport type Env = Record<string, EnvValue>;\n\n/**\n * @public\n */\nexport type EnvValue = string | undefined;\n\n/**\n * devServerHost returns the dev server host by searching for the INNGEST_DEVSERVER_URL\n * environment variable (plus project prefixces for eg. react, such as REACT_APP_INNGEST_DEVSERVER_URL).\n *\n * If not found this returns undefined, indicating that the env var has not been set.\n *\n * @example devServerHost()\n */\nexport const devServerHost = (env: Env = getProcessEnv()): EnvValue => {\n // The prefixed keys we look up for common frameworks (CRA, Next). The\n // unprefixed `INNGEST_BASE_URL` / `INNGEST_DEV` are read directly by the\n // Inngest client elsewhere, so we only check the prefixed variants here.\n const keys = [\n envKeys.ReactAppInngestBaseUrl,\n envKeys.NextPublicInngestBaseUrl,\n envKeys.ReactAppInngestDevMode,\n envKeys.NextPublicInngestDevMode,\n ];\n const values = keys.map((key) => {\n return env[key];\n });\n\n return values.find((v) => {\n if (!v) {\n return;\n }\n\n try {\n return Boolean(new URL(v));\n } catch {\n // no-op\n }\n\n return;\n });\n};\n\nexport type Mode = \"cloud\" | \"dev\";\n\nexport function checkModeConfiguration({\n internalLogger,\n mode,\n signingKey,\n}: {\n internalLogger: Logger;\n mode: Mode;\n signingKey: string | undefined;\n}): boolean {\n if (mode === \"cloud\" && !signingKey) {\n internalLogger.error(\n `In cloud mode but no signing key found. For local dev, set the INNGEST_DEV=1 env var. For production, set the ${envKeys.InngestSigningKey} env var`,\n );\n\n return false;\n }\n\n return true;\n}\n\nexport const normalizeUrl = (\n urlString: string,\n scheme: string = \"http://\",\n): string => {\n if (urlString === \"undefined\") {\n throw new Error(\"URL undefined\");\n }\n if (urlString.includes(\"://\")) {\n return urlString;\n }\n\n return `${scheme}${urlString}`;\n};\n\n/**\n * getEnvironmentName returns the suspected branch name for this environment by\n * searching through a set of common environment variables.\n *\n * This could be used to determine if we're on a branch deploy or not, though it\n * should be noted that we don't know if this is the default branch or not.\n */\nexport const getEnvironmentName = (env: Env = getProcessEnv()): EnvValue => {\n /**\n * Order is important; more than one of these env vars may be set, so ensure\n * that we check the most specific, most reliable env vars first.\n */\n return (\n env[envKeys.InngestEnvironment] ||\n env[envKeys.BranchName] ||\n env[envKeys.VercelBranch] ||\n env[envKeys.NetlifyBranch] ||\n env[envKeys.CloudflarePagesBranch] ||\n env[envKeys.RenderBranch] ||\n env[envKeys.RailwayBranch]\n );\n};\n\nexport const processEnv = (key: envKeys): EnvValue => {\n if (!Object.values(envKeys).includes(key)) {\n throw new Error(`Unknown env var: ${key}`);\n }\n\n return getProcessEnv()[key];\n};\n\n/**\n * The Deno environment, which is not always available.\n */\ndeclare const Deno: {\n env: { toObject: () => Env };\n};\n\n/**\n * The Netlify environment, which is not always available.\n */\ndeclare const Netlify: {\n env: { toObject: () => Env };\n};\n\n/**\n * Get the current process env vars. Only includes env vars that we care about.\n *\n * Returns an empty object if they can't be read.\n */\nexport function getProcessEnv(): Env {\n const env: Env = {};\n const whitelist: string[] = Object.values(envKeys);\n\n for (const [k, v] of Object.entries(allProcessEnv())) {\n if (!whitelist.includes(k)) {\n continue;\n }\n env[k] = v;\n }\n\n return protectEnv(env);\n}\n\n/**\n * Install a `toJSON` that returns `{}` so env var values can't leak via\n * `JSON.stringify`, regardless of where the object is reachable from. The\n * property is enumerable so it survives spreads (e.g. `{...env}`) which carries\n * the protection into the new object. But note that the enumerability also\n * means the static type is technically incorrect.\n *\n * Callers still read values via normal `env[key]` access.\n */\nexport function protectEnv(env: Env): Env {\n return {\n ...env,\n\n // @ts-expect-error - intentional\n toJSON: () => {\n return {};\n },\n };\n}\n\n/**\n * allProcessEnv returns the current process environment variables, or an empty\n * object if they cannot be read, making sure we support environments other than\n * Node such as Deno, too.\n *\n * Using this ensures we don't dangerously access `process.env` in environments\n * where it may not be defined, such as Deno or the browser.\n */\nconst allProcessEnv = (): Env => {\n // Node, or Node-like environments\n try {\n if (process.env) {\n return process.env;\n }\n } catch (_err) {\n // noop\n }\n\n // Deno\n try {\n const env = Deno.env.toObject();\n\n if (env) {\n return env;\n }\n } catch (_err) {\n // noop\n }\n\n // Netlify\n try {\n const env = Netlify.env.toObject();\n\n if (env) {\n return env;\n }\n } catch (_err) {\n // noop\n }\n\n return {};\n};\n\n/**\n * Generate a standardised set of headers based on input and environment\n * variables.\n *\n *\n */\nexport const inngestHeaders = (opts?: {\n /**\n * The environment variables to use instead of `process.env` or any other\n * default source. Useful for platforms where environment variables are passed\n * in alongside requests.\n */\n env?: Env;\n\n /**\n * The framework name to use in the `X-Inngest-Framework` header. This is not\n * always available, hence being optional.\n */\n framework?: string;\n\n /**\n * The environment name to use in the `X-Inngest-Env` header. This is likely\n * to be representative of the target preview environment.\n */\n inngestEnv?: string;\n\n /**\n * The Inngest client that's making the request. The client itself will\n * generate a set of headers; specifying it here will ensure that the client's\n * headers are included in the returned headers.\n */\n client?: Inngest;\n\n /**\n * The Inngest server we expect to be communicating with, used to ensure that\n * various parts of a handshake are all happening with the same type of\n * participant.\n */\n expectedServerKind?: string;\n\n /**\n * Any additional headers to include in the returned headers.\n */\n extras?: Record<string, string>;\n}): Record<string, string> => {\n const sdkVersion = `inngest-js:v${version}`;\n const headers: Record<string, string> = {\n \"Content-Type\": \"application/json\",\n \"User-Agent\": sdkVersion,\n [headerKeys.SdkVersion]: sdkVersion,\n };\n\n if (opts?.framework) {\n headers[headerKeys.Framework] = opts.framework;\n }\n\n if (opts?.expectedServerKind) {\n headers[headerKeys.InngestExpectedServerKind] = opts.expectedServerKind;\n }\n\n const env = {\n ...getProcessEnv(),\n ...opts?.env,\n };\n\n const inngestEnv = opts?.inngestEnv || getEnvironmentName(env);\n if (inngestEnv) {\n headers[headerKeys.Environment] = inngestEnv;\n }\n\n const platform = getPlatformName(env);\n if (platform) {\n headers[headerKeys.Platform] = platform;\n }\n\n return {\n ...headers,\n ...opts?.client?.[\"headers\"],\n ...opts?.extras,\n };\n};\n\n/**\n * A set of checks that, given an environment, will return `true` if the current\n * environment is running on the platform with the given name.\n */\nconst platformChecks = {\n /**\n * Vercel Edge Functions don't have access to environment variables unless\n * they are explicitly referenced in the top level code, but they do have a\n * global `EdgeRuntime` variable set that we can use to detect this.\n */\n vercel: (env) =>\n env[envKeys.IsVercel] === \"1\" || typeof EdgeRuntime === \"string\",\n netlify: (env) => env[envKeys.IsNetlify] === \"true\",\n \"cloudflare-pages\": (env) => env[envKeys.IsCloudflarePages] === \"1\",\n render: (env) => env[envKeys.IsRender] === \"true\",\n railway: (env) => Boolean(env[envKeys.RailwayEnvironment]),\n} satisfies Record<string, (env: Env) => boolean>;\n\ndeclare const EdgeRuntime: string | undefined;\n\n/**\n * A set of checks that, given an environment, will return `true` if the current\n * environment and platform supports streaming responses back to Inngest.\n *\n * Streaming capability is both framework and platform-based. Frameworks are\n * supported in serve handlers, and platforms are checked here.\n *\n * As such, this record declares which platforms we explicitly support for\n * streaming and is used by {@link platformSupportsStreaming}.\n */\nconst streamingChecks: Partial<\n Record<\n keyof typeof platformChecks,\n (framework: SupportedFrameworkName, env: Env) => boolean\n >\n> = {\n /**\n * \"Vercel supports streaming for Serverless Functions, Edge Functions, and\n * React Server Components in Next.js projects.\"\n *\n * In practice, however, there are many reports of streaming not working as\n * expected on Serverless Functions, so we resort to only allowing streaming\n * for Edge Functions here.\n *\n * See {@link https://vercel.com/docs/frameworks/nextjs#streaming}\n */\n vercel: (_framework, _env) => typeof EdgeRuntime === \"string\",\n \"cloudflare-pages\": () => true,\n};\n\nexport const getPlatformName = (env: Env) => {\n return (Object.keys(platformChecks) as (keyof typeof platformChecks)[]).find(\n (key) => {\n return platformChecks[key](env);\n },\n );\n};\n\n/**\n * Returns `true` if we believe the current environment supports streaming\n * responses back to Inngest.\n *\n * We run a check directly related to the platform we believe we're running on,\n * usually based on environment variables.\n */\nexport const platformSupportsStreaming = (\n framework: SupportedFrameworkName,\n env: Env = getProcessEnv(),\n): boolean => {\n return (\n streamingChecks[getPlatformName(env) as keyof typeof streamingChecks]?.(\n framework,\n env,\n ) ?? false\n );\n};\n\n/**\n * A unique symbol used to mark a custom fetch implementation. We wrap the\n * implementations to provide some extra control when handling errors.\n */\nconst CUSTOM_FETCH_MARKER = Symbol(\"Custom fetch implementation\");\n\n/**\n * Given a potential fetch function, return the fetch function to use based on\n * this and the environment.\n */\nexport const getFetch = (\n logger: Logger,\n givenFetch?: typeof fetch,\n): typeof fetch => {\n /**\n * If we've explicitly been given a fetch function, use that.\n */\n if (givenFetch) {\n if (CUSTOM_FETCH_MARKER in givenFetch) {\n return givenFetch;\n }\n\n /**\n * We wrap the given fetch function to provide some extra control when\n * handling errors.\n */\n const customFetch: typeof fetch = async (...args) => {\n try {\n return await givenFetch(...args);\n } catch (err) {\n /**\n * Capture warnings that are not simple fetch failures and highlight\n * them for the user.\n *\n * We also use this opportunity to log the causing error, as code higher\n * up the stack will likely abstract this.\n */\n if (\n !(err instanceof Error) ||\n !err.message?.startsWith(\"fetch failed\")\n ) {\n logger.error(\n { err },\n \"A request failed when using a custom fetch implementation; this may be a misconfiguration. Make sure that your fetch client is correctly bound to the global scope.\",\n );\n }\n\n throw err;\n }\n };\n\n /**\n * Mark the custom fetch implementation so that we can identify it later, in\n * addition to adding some runtime properties to it to make it seem as much\n * like the original fetch as possible.\n */\n Object.defineProperties(customFetch, {\n [CUSTOM_FETCH_MARKER]: {},\n name: { value: givenFetch.name },\n length: { value: givenFetch.length },\n });\n\n return customFetch;\n }\n\n /**\n * Browser or Node 18+\n */\n try {\n if (typeof globalThis !== \"undefined\" && \"fetch\" in globalThis) {\n return fetch.bind(globalThis);\n }\n } catch (_err) {\n // no-op\n }\n\n /**\n * Existing polyfilled fetch\n */\n if (typeof fetch !== \"undefined\") {\n return fetch;\n }\n\n /**\n * Environments where fetch cannot be found and must be polyfilled\n */\n return require(\"cross-fetch\") as typeof fetch;\n};\n\n/**\n * If `Response` isn't included in this environment, it's probably an earlier\n * Node env that isn't already polyfilling. This function returns either the\n * native `Response` or a polyfilled one.\n */\nexport const getResponse = (): typeof Response => {\n if (typeof Response !== \"undefined\") {\n return Response;\n }\n\n return require(\"cross-fetch\").Response;\n};\n\n/**\n * Given an unknown value, try to parse it as a `boolean`. Useful for parsing\n * environment variables that could be a selection of different values such as\n * `\"true\"`, `\"1\"`.\n *\n * If the value could not be confidently parsed as a `boolean` or was seen to be\n * `undefined`, this function returns `undefined`.\n */\nexport const parseAsBoolean = (value: unknown): boolean | undefined => {\n if (typeof value === \"boolean\") {\n return value;\n }\n\n if (typeof value === \"number\") {\n return Boolean(value);\n }\n\n if (typeof value === \"string\") {\n const trimmed = value.trim().toLowerCase();\n\n if (trimmed === \"undefined\") {\n return undefined;\n }\n\n if ([\"true\", \"1\"].includes(trimmed)) {\n return true;\n }\n\n if ([\"false\", \"0\"].includes(trimmed)) {\n return false;\n }\n }\n\n return undefined;\n};\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"env.js","names":["env: Env","whitelist: string[]","headers: Record<string, string>","customFetch: typeof fetch"],"sources":["../../src/helpers/env.ts"],"sourcesContent":["// This file exists to help normalize process.env amongst the backend\n// and frontend. Many frontends (eg. Next, CRA) utilize webpack's DefinePlugin\n// along with prefixes, meaning we have to explicitly use the full `process.env.FOO`\n// string in order to read variables.\n\nimport type { Inngest } from \"../components/Inngest.ts\";\nimport type { Logger } from \"../middleware/logger.ts\";\nimport type { SupportedFrameworkName } from \"../types.ts\";\nimport { version } from \"../version.ts\";\nimport { envKeys, headerKeys } from \"./consts.ts\";\n\n/**\n * @public\n */\nexport type Env = Record<string, EnvValue>;\n\n/**\n * @public\n */\nexport type EnvValue = string | undefined;\n\n/**\n * devServerHost returns the dev server host by searching for the INNGEST_DEVSERVER_URL\n * environment variable (plus project prefixces for eg. react, such as REACT_APP_INNGEST_DEVSERVER_URL).\n *\n * If not found this returns undefined, indicating that the env var has not been set.\n *\n * @example devServerHost()\n */\nexport const devServerHost = (env: Env = getProcessEnv()): EnvValue => {\n // The prefixed keys we look up for common frameworks (CRA, Next). The\n // unprefixed `INNGEST_BASE_URL` / `INNGEST_DEV` are read directly by the\n // Inngest client elsewhere, so we only check the prefixed variants here.\n const keys = [\n envKeys.ReactAppInngestBaseUrl,\n envKeys.NextPublicInngestBaseUrl,\n envKeys.ReactAppInngestDevMode,\n envKeys.NextPublicInngestDevMode,\n ];\n const values = keys.map((key) => {\n return env[key];\n });\n\n return values.find((v) => {\n if (!v) {\n return;\n }\n\n try {\n return Boolean(new URL(v));\n } catch {\n // no-op\n }\n\n return;\n });\n};\n\nexport type Mode = \"cloud\" | \"dev\";\n\nexport function checkModeConfiguration({\n internalLogger,\n mode,\n signingKey,\n}: {\n internalLogger: Logger;\n mode: Mode;\n signingKey: string | undefined;\n}): boolean {\n if (mode === \"cloud\" && !signingKey) {\n internalLogger.error(\n `In cloud mode but no signing key found. For local dev, set the INNGEST_DEV=1 env var. For production, set the ${envKeys.InngestSigningKey} env var`,\n );\n\n return false;\n }\n\n return true;\n}\n\nexport const normalizeUrl = (\n urlString: string,\n scheme: string = \"http://\",\n): string => {\n if (urlString === \"undefined\") {\n throw new Error(\"URL undefined\");\n }\n if (urlString.includes(\"://\")) {\n return urlString;\n }\n\n return `${scheme}${urlString}`;\n};\n\n/**\n * getEnvironmentName returns the suspected branch name for this environment by\n * searching through a set of common environment variables.\n *\n * This could be used to determine if we're on a branch deploy or not, though it\n * should be noted that we don't know if this is the default branch or not.\n */\nexport const getEnvironmentName = (env: Env = getProcessEnv()): EnvValue => {\n /**\n * Order is important; more than one of these env vars may be set, so ensure\n * that we check the most specific, most reliable env vars first.\n */\n return (\n env[envKeys.InngestEnvironment] ||\n env[envKeys.BranchName] ||\n env[envKeys.VercelBranch] ||\n env[envKeys.NetlifyBranch] ||\n env[envKeys.CloudflarePagesBranch] ||\n env[envKeys.RenderBranch] ||\n env[envKeys.RailwayBranch]\n );\n};\n\nexport const processEnv = (key: envKeys): EnvValue => {\n if (!Object.values(envKeys).includes(key)) {\n throw new Error(`Unknown env var: ${key}`);\n }\n\n return getProcessEnv()[key];\n};\n\n/**\n * The Deno environment, which is not always available.\n */\ndeclare const Deno: {\n env: { toObject: () => Env };\n};\n\n/**\n * The Netlify environment, which is not always available.\n */\ndeclare const Netlify: {\n env: { toObject: () => Env };\n};\n\n/**\n * Get the current process env vars. Only includes env vars that we care about.\n *\n * Returns an empty object if they can't be read.\n */\nexport function getProcessEnv(): Env {\n const env: Env = {};\n const whitelist: string[] = Object.values(envKeys);\n\n for (const [k, v] of Object.entries(allProcessEnv())) {\n if (!whitelist.includes(k)) {\n continue;\n }\n env[k] = v;\n }\n\n return protectEnv(env);\n}\n\n/**\n * Install a `toJSON` that returns `{}` so env var values can't leak via\n * `JSON.stringify`, regardless of where the object is reachable from. The\n * property is enumerable so it survives spreads (e.g. `{...env}`) which carries\n * the protection into the new object. But note that the enumerability also\n * means the static type is technically incorrect.\n *\n * Callers still read values via normal `env[key]` access.\n */\nexport function protectEnv(env: Env): Env {\n return {\n ...env,\n\n // @ts-expect-error - intentional\n toJSON: () => {\n return {};\n },\n };\n}\n\n/**\n * allProcessEnv returns the current process environment variables, or an empty\n * object if they cannot be read, making sure we support environments other than\n * Node such as Deno, too.\n *\n * Using this ensures we don't dangerously access `process.env` in environments\n * where it may not be defined, such as Deno or the browser.\n */\nconst allProcessEnv = (): Env => {\n // Node, or Node-like environments\n try {\n if (process.env) {\n return process.env;\n }\n } catch (_err) {\n // noop\n }\n\n // Deno\n try {\n const env = Deno.env.toObject();\n\n if (env) {\n return env;\n }\n } catch (_err) {\n // noop\n }\n\n // Netlify\n try {\n const env = Netlify.env.toObject();\n\n if (env) {\n return env;\n }\n } catch (_err) {\n // noop\n }\n\n return {};\n};\n\n/**\n * Generate a standardised set of headers based on input and environment\n * variables.\n *\n *\n */\nexport const inngestHeaders = (opts?: {\n /**\n * The environment variables to use instead of `process.env` or any other\n * default source. Useful for platforms where environment variables are passed\n * in alongside requests.\n */\n env?: Env;\n\n /**\n * The framework name to use in the `X-Inngest-Framework` header. This is not\n * always available, hence being optional.\n */\n framework?: string;\n\n /**\n * The environment name to use in the `X-Inngest-Env` header. This is likely\n * to be representative of the target preview environment.\n */\n inngestEnv?: string;\n\n /**\n * The Inngest client that's making the request. The client itself will\n * generate a set of headers; specifying it here will ensure that the client's\n * headers are included in the returned headers.\n */\n client?: Inngest;\n\n /**\n * The Inngest server we expect to be communicating with, used to ensure that\n * various parts of a handshake are all happening with the same type of\n * participant.\n */\n expectedServerKind?: string;\n\n /**\n * Any additional headers to include in the returned headers.\n */\n extras?: Record<string, string>;\n}): Record<string, string> => {\n const sdkVersion = `inngest-js:v${version}`;\n const headers: Record<string, string> = {\n \"Content-Type\": \"application/json\",\n \"User-Agent\": sdkVersion,\n [headerKeys.SdkVersion]: sdkVersion,\n [headerKeys.SdkHandled]: \"true\",\n };\n\n if (opts?.framework) {\n headers[headerKeys.Framework] = opts.framework;\n }\n\n if (opts?.expectedServerKind) {\n headers[headerKeys.InngestExpectedServerKind] = opts.expectedServerKind;\n }\n\n const env = {\n ...getProcessEnv(),\n ...opts?.env,\n };\n\n const inngestEnv = opts?.inngestEnv || getEnvironmentName(env);\n if (inngestEnv) {\n headers[headerKeys.Environment] = inngestEnv;\n }\n\n const platform = getPlatformName(env);\n if (platform) {\n headers[headerKeys.Platform] = platform;\n }\n\n return {\n ...headers,\n ...opts?.client?.[\"headers\"],\n ...opts?.extras,\n };\n};\n\n/**\n * A set of checks that, given an environment, will return `true` if the current\n * environment is running on the platform with the given name.\n */\nconst platformChecks = {\n /**\n * Vercel Edge Functions don't have access to environment variables unless\n * they are explicitly referenced in the top level code, but they do have a\n * global `EdgeRuntime` variable set that we can use to detect this.\n */\n vercel: (env) =>\n env[envKeys.IsVercel] === \"1\" || typeof EdgeRuntime === \"string\",\n netlify: (env) => env[envKeys.IsNetlify] === \"true\",\n \"cloudflare-pages\": (env) => env[envKeys.IsCloudflarePages] === \"1\",\n render: (env) => env[envKeys.IsRender] === \"true\",\n railway: (env) => Boolean(env[envKeys.RailwayEnvironment]),\n} satisfies Record<string, (env: Env) => boolean>;\n\ndeclare const EdgeRuntime: string | undefined;\n\n/**\n * A set of checks that, given an environment, will return `true` if the current\n * environment and platform supports streaming responses back to Inngest.\n *\n * Streaming capability is both framework and platform-based. Frameworks are\n * supported in serve handlers, and platforms are checked here.\n *\n * As such, this record declares which platforms we explicitly support for\n * streaming and is used by {@link platformSupportsStreaming}.\n */\nconst streamingChecks: Partial<\n Record<\n keyof typeof platformChecks,\n (framework: SupportedFrameworkName, env: Env) => boolean\n >\n> = {\n /**\n * \"Vercel supports streaming for Serverless Functions, Edge Functions, and\n * React Server Components in Next.js projects.\"\n *\n * In practice, however, there are many reports of streaming not working as\n * expected on Serverless Functions, so we resort to only allowing streaming\n * for Edge Functions here.\n *\n * See {@link https://vercel.com/docs/frameworks/nextjs#streaming}\n */\n vercel: (_framework, _env) => typeof EdgeRuntime === \"string\",\n \"cloudflare-pages\": () => true,\n};\n\nexport const getPlatformName = (env: Env) => {\n return (Object.keys(platformChecks) as (keyof typeof platformChecks)[]).find(\n (key) => {\n return platformChecks[key](env);\n },\n );\n};\n\n/**\n * Returns `true` if we believe the current environment supports streaming\n * responses back to Inngest.\n *\n * We run a check directly related to the platform we believe we're running on,\n * usually based on environment variables.\n */\nexport const platformSupportsStreaming = (\n framework: SupportedFrameworkName,\n env: Env = getProcessEnv(),\n): boolean => {\n return (\n streamingChecks[getPlatformName(env) as keyof typeof streamingChecks]?.(\n framework,\n env,\n ) ?? false\n );\n};\n\n/**\n * A unique symbol used to mark a custom fetch implementation. We wrap the\n * implementations to provide some extra control when handling errors.\n */\nconst CUSTOM_FETCH_MARKER = Symbol(\"Custom fetch implementation\");\n\n/**\n * Given a potential fetch function, return the fetch function to use based on\n * this and the environment.\n */\nexport const getFetch = (\n logger: Logger,\n givenFetch?: typeof fetch,\n): typeof fetch => {\n /**\n * If we've explicitly been given a fetch function, use that.\n */\n if (givenFetch) {\n if (CUSTOM_FETCH_MARKER in givenFetch) {\n return givenFetch;\n }\n\n /**\n * We wrap the given fetch function to provide some extra control when\n * handling errors.\n */\n const customFetch: typeof fetch = async (...args) => {\n try {\n return await givenFetch(...args);\n } catch (err) {\n /**\n * Capture warnings that are not simple fetch failures and highlight\n * them for the user.\n *\n * We also use this opportunity to log the causing error, as code higher\n * up the stack will likely abstract this.\n */\n if (\n !(err instanceof Error) ||\n !err.message?.startsWith(\"fetch failed\")\n ) {\n logger.error(\n { err },\n \"A request failed when using a custom fetch implementation; this may be a misconfiguration. Make sure that your fetch client is correctly bound to the global scope.\",\n );\n }\n\n throw err;\n }\n };\n\n /**\n * Mark the custom fetch implementation so that we can identify it later, in\n * addition to adding some runtime properties to it to make it seem as much\n * like the original fetch as possible.\n */\n Object.defineProperties(customFetch, {\n [CUSTOM_FETCH_MARKER]: {},\n name: { value: givenFetch.name },\n length: { value: givenFetch.length },\n });\n\n return customFetch;\n }\n\n /**\n * Browser or Node 18+\n */\n try {\n if (typeof globalThis !== \"undefined\" && \"fetch\" in globalThis) {\n return fetch.bind(globalThis);\n }\n } catch (_err) {\n // no-op\n }\n\n /**\n * Existing polyfilled fetch\n */\n if (typeof fetch !== \"undefined\") {\n return fetch;\n }\n\n /**\n * Environments where fetch cannot be found and must be polyfilled\n */\n return require(\"cross-fetch\") as typeof fetch;\n};\n\n/**\n * If `Response` isn't included in this environment, it's probably an earlier\n * Node env that isn't already polyfilling. This function returns either the\n * native `Response` or a polyfilled one.\n */\nexport const getResponse = (): typeof Response => {\n if (typeof Response !== \"undefined\") {\n return Response;\n }\n\n return require(\"cross-fetch\").Response;\n};\n\n/**\n * Given an unknown value, try to parse it as a `boolean`. Useful for parsing\n * environment variables that could be a selection of different values such as\n * `\"true\"`, `\"1\"`.\n *\n * If the value could not be confidently parsed as a `boolean` or was seen to be\n * `undefined`, this function returns `undefined`.\n */\nexport const parseAsBoolean = (value: unknown): boolean | undefined => {\n if (typeof value === \"boolean\") {\n return value;\n }\n\n if (typeof value === \"number\") {\n return Boolean(value);\n }\n\n if (typeof value === \"string\") {\n const trimmed = value.trim().toLowerCase();\n\n if (trimmed === \"undefined\") {\n return undefined;\n }\n\n if ([\"true\", \"1\"].includes(trimmed)) {\n return true;\n }\n\n if ([\"false\", \"0\"].includes(trimmed)) {\n return false;\n }\n }\n\n return undefined;\n};\n"],"mappings":"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"}
|
package/helpers/net.cjs
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
const require_rolldown_runtime = require('../_virtual/rolldown_runtime.cjs');
|
|
2
2
|
const require_log = require('./log.cjs');
|
|
3
|
+
const require_strings = require('./strings.cjs');
|
|
3
4
|
let canonicalize = require("canonicalize");
|
|
4
5
|
canonicalize = require_rolldown_runtime.__toESM(canonicalize);
|
|
5
6
|
let hash_js = require("hash.js");
|
|
@@ -30,12 +31,12 @@ async function fetchWithAuthFallback({ authToken, authTokenFallback, fetch, opti
|
|
|
30
31
|
}
|
|
31
32
|
function signWithHashJs(data, signingKey, ts) {
|
|
32
33
|
const encoded = typeof data === "string" ? data : (0, canonicalize.default)(data);
|
|
33
|
-
return hmac(sha256,
|
|
34
|
+
return hmac(sha256, require_strings.removeSigningKeyPrefix(signingKey)).update(encoded).update(ts).digest("hex");
|
|
34
35
|
}
|
|
35
36
|
const cryptoKeyCache = /* @__PURE__ */ new Map();
|
|
36
37
|
async function signWithNative(subtle, data, signingKey, ts) {
|
|
37
38
|
const encoded = typeof data === "string" ? data : (0, canonicalize.default)(data);
|
|
38
|
-
const key =
|
|
39
|
+
const key = require_strings.removeSigningKeyPrefix(signingKey);
|
|
39
40
|
let cryptoKey = cryptoKeyCache.get(key);
|
|
40
41
|
if (!cryptoKey) {
|
|
41
42
|
cryptoKey = await subtle.importKey("raw", new TextEncoder().encode(key), {
|
package/helpers/net.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"net.cjs","names":["hashjs"],"sources":["../../src/helpers/net.ts"],"sourcesContent":["import canonicalize from \"canonicalize\";\nimport hashjs from \"hash.js\";\nimport type { Logger } from \"../middleware/logger.ts\";\nimport { logOnce } from \"./log.ts\";\n\nconst { hmac, sha256 } = hashjs;\n\n/**\n * Send an HTTP request with the given signing key. If the response is a 401 or\n * 403, then try again with the fallback signing key\n */\nexport async function fetchWithAuthFallback<TFetch extends typeof fetch>({\n authToken,\n authTokenFallback,\n fetch,\n options,\n url,\n}: {\n authToken?: string;\n authTokenFallback?: string;\n fetch: TFetch;\n options?: Parameters<TFetch>[1];\n url: URL | string;\n}): Promise<Response> {\n let res = await fetch(url, {\n ...options,\n headers: {\n ...options?.headers,\n Authorization: `Bearer ${authToken}`,\n },\n });\n\n if ([401, 403].includes(res.status) && authTokenFallback) {\n res = await fetch(url, {\n ...options,\n headers: {\n ...options?.headers,\n Authorization: `Bearer ${authTokenFallback}`,\n },\n });\n }\n\n return res;\n}\n\nexport function signWithHashJs(\n data: unknown,\n signingKey: string,\n ts: string,\n): string {\n // Calculate the HMAC of the request body ourselves.\n // We make the assumption here that a stringified body is the same as the\n // raw bytes; it may be pertinent in the future to always parse, then\n // canonicalize the body to ensure it's consistent.\n const encoded = typeof data === \"string\" ? data : canonicalize(data);\n //
|
|
1
|
+
{"version":3,"file":"net.cjs","names":["hashjs","removeSigningKeyPrefix"],"sources":["../../src/helpers/net.ts"],"sourcesContent":["import canonicalize from \"canonicalize\";\nimport hashjs from \"hash.js\";\nimport type { Logger } from \"../middleware/logger.ts\";\nimport { logOnce } from \"./log.ts\";\nimport { removeSigningKeyPrefix } from \"./strings.ts\";\n\nconst { hmac, sha256 } = hashjs;\n\n/**\n * Send an HTTP request with the given signing key. If the response is a 401 or\n * 403, then try again with the fallback signing key\n */\nexport async function fetchWithAuthFallback<TFetch extends typeof fetch>({\n authToken,\n authTokenFallback,\n fetch,\n options,\n url,\n}: {\n authToken?: string;\n authTokenFallback?: string;\n fetch: TFetch;\n options?: Parameters<TFetch>[1];\n url: URL | string;\n}): Promise<Response> {\n let res = await fetch(url, {\n ...options,\n headers: {\n ...options?.headers,\n Authorization: `Bearer ${authToken}`,\n },\n });\n\n if ([401, 403].includes(res.status) && authTokenFallback) {\n res = await fetch(url, {\n ...options,\n headers: {\n ...options?.headers,\n Authorization: `Bearer ${authTokenFallback}`,\n },\n });\n }\n\n return res;\n}\n\nexport function signWithHashJs(\n data: unknown,\n signingKey: string,\n ts: string,\n): string {\n // Calculate the HMAC of the request body ourselves.\n // We make the assumption here that a stringified body is the same as the\n // raw bytes; it may be pertinent in the future to always parse, then\n // canonicalize the body to ensure it's consistent.\n const encoded = typeof data === \"string\" ? data : canonicalize(data);\n // biome-ignore lint/suspicious/noExplicitAny: intentional\n const mac = hmac(sha256 as any, removeSigningKeyPrefix(signingKey))\n .update(encoded)\n .update(ts)\n .digest(\"hex\");\n\n return mac;\n}\n\n// Cache for CryptoKeys to avoid repeated importKey calls\nconst cryptoKeyCache = new Map<string, CryptoKey>();\n\nasync function signWithNative(\n subtle: SubtleCrypto,\n data: unknown,\n signingKey: string,\n ts: string,\n): Promise<string> {\n const encoded = typeof data === \"string\" ? data : canonicalize(data);\n const key = removeSigningKeyPrefix(signingKey);\n\n let cryptoKey = cryptoKeyCache.get(key);\n if (!cryptoKey) {\n cryptoKey = await subtle.importKey(\n \"raw\",\n new TextEncoder().encode(key),\n { name: \"HMAC\", hash: \"SHA-256\" },\n false,\n [\"sign\"],\n );\n cryptoKeyCache.set(key, cryptoKey);\n }\n\n const signature = await subtle.sign(\n \"HMAC\",\n cryptoKey,\n new TextEncoder().encode(encoded + ts),\n );\n\n return Array.from(new Uint8Array(signature))\n .map((b) => b.toString(16).padStart(2, \"0\"))\n .join(\"\");\n}\n\n/**\n * Sign data with a signing key using HMAC-SHA256.\n * Uses native crypto.subtle when available, falls back to hash.js.\n */\nexport async function signDataWithKey(\n data: unknown,\n signingKey: string,\n ts: string,\n logger: Logger,\n): Promise<string> {\n const subtle = globalThis.crypto?.subtle;\n\n logOnce(\n logger,\n \"debug\",\n \"crypto-implementation\",\n subtle\n ? \"Using native Web Crypto for request signing\"\n : \"Using hash.js fallback for request signing (native crypto unavailable)\",\n );\n\n if (subtle) {\n try {\n return await signWithNative(subtle, data, signingKey, ts);\n } catch (err) {\n logger.debug({ err }, \"Native crypto failed, falling back to hash.js\");\n }\n }\n return signWithHashJs(data, signingKey, ts);\n}\n"],"mappings":";;;;;;;;;AAMA,MAAM,EAAE,MAAM,WAAWA;;;;;AAMzB,eAAsB,sBAAmD,EACvE,WACA,mBACA,OACA,SACA,OAOoB;CACpB,IAAI,MAAM,MAAM,MAAM,KAAK;EACzB,GAAG;EACH,SAAS;GACP,GAAG,SAAS;GACZ,eAAe,UAAU;GAC1B;EACF,CAAC;AAEF,KAAI,CAAC,KAAK,IAAI,CAAC,SAAS,IAAI,OAAO,IAAI,kBACrC,OAAM,MAAM,MAAM,KAAK;EACrB,GAAG;EACH,SAAS;GACP,GAAG,SAAS;GACZ,eAAe,UAAU;GAC1B;EACF,CAAC;AAGJ,QAAO;;AAGT,SAAgB,eACd,MACA,YACA,IACQ;CAKR,MAAM,UAAU,OAAO,SAAS,WAAW,iCAAoB,KAAK;AAOpE,QALY,KAAK,QAAeC,uCAAuB,WAAW,CAAC,CAChE,OAAO,QAAQ,CACf,OAAO,GAAG,CACV,OAAO,MAAM;;AAMlB,MAAM,iCAAiB,IAAI,KAAwB;AAEnD,eAAe,eACb,QACA,MACA,YACA,IACiB;CACjB,MAAM,UAAU,OAAO,SAAS,WAAW,iCAAoB,KAAK;CACpE,MAAM,MAAMA,uCAAuB,WAAW;CAE9C,IAAI,YAAY,eAAe,IAAI,IAAI;AACvC,KAAI,CAAC,WAAW;AACd,cAAY,MAAM,OAAO,UACvB,OACA,IAAI,aAAa,CAAC,OAAO,IAAI,EAC7B;GAAE,MAAM;GAAQ,MAAM;GAAW,EACjC,OACA,CAAC,OAAO,CACT;AACD,iBAAe,IAAI,KAAK,UAAU;;CAGpC,MAAM,YAAY,MAAM,OAAO,KAC7B,QACA,WACA,IAAI,aAAa,CAAC,OAAO,UAAU,GAAG,CACvC;AAED,QAAO,MAAM,KAAK,IAAI,WAAW,UAAU,CAAC,CACzC,KAAK,MAAM,EAAE,SAAS,GAAG,CAAC,SAAS,GAAG,IAAI,CAAC,CAC3C,KAAK,GAAG;;;;;;AAOb,eAAsB,gBACpB,MACA,YACA,IACA,QACiB;CACjB,MAAM,SAAS,WAAW,QAAQ;AAElC,qBACE,QACA,SACA,yBACA,SACI,gDACA,yEACL;AAED,KAAI,OACF,KAAI;AACF,SAAO,MAAM,eAAe,QAAQ,MAAM,YAAY,GAAG;UAClD,KAAK;AACZ,SAAO,MAAM,EAAE,KAAK,EAAE,gDAAgD;;AAG1E,QAAO,eAAe,MAAM,YAAY,GAAG"}
|
package/helpers/net.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { logOnce } from "./log.js";
|
|
2
|
+
import { removeSigningKeyPrefix } from "./strings.js";
|
|
2
3
|
import canonicalize from "canonicalize";
|
|
3
4
|
import hashjs from "hash.js";
|
|
4
5
|
|
|
@@ -27,12 +28,12 @@ async function fetchWithAuthFallback({ authToken, authTokenFallback, fetch, opti
|
|
|
27
28
|
}
|
|
28
29
|
function signWithHashJs(data, signingKey, ts) {
|
|
29
30
|
const encoded = typeof data === "string" ? data : canonicalize(data);
|
|
30
|
-
return hmac(sha256, signingKey
|
|
31
|
+
return hmac(sha256, removeSigningKeyPrefix(signingKey)).update(encoded).update(ts).digest("hex");
|
|
31
32
|
}
|
|
32
33
|
const cryptoKeyCache = /* @__PURE__ */ new Map();
|
|
33
34
|
async function signWithNative(subtle, data, signingKey, ts) {
|
|
34
35
|
const encoded = typeof data === "string" ? data : canonicalize(data);
|
|
35
|
-
const key = signingKey
|
|
36
|
+
const key = removeSigningKeyPrefix(signingKey);
|
|
36
37
|
let cryptoKey = cryptoKeyCache.get(key);
|
|
37
38
|
if (!cryptoKey) {
|
|
38
39
|
cryptoKey = await subtle.importKey("raw", new TextEncoder().encode(key), {
|
package/helpers/net.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"net.js","names":[],"sources":["../../src/helpers/net.ts"],"sourcesContent":["import canonicalize from \"canonicalize\";\nimport hashjs from \"hash.js\";\nimport type { Logger } from \"../middleware/logger.ts\";\nimport { logOnce } from \"./log.ts\";\n\nconst { hmac, sha256 } = hashjs;\n\n/**\n * Send an HTTP request with the given signing key. If the response is a 401 or\n * 403, then try again with the fallback signing key\n */\nexport async function fetchWithAuthFallback<TFetch extends typeof fetch>({\n authToken,\n authTokenFallback,\n fetch,\n options,\n url,\n}: {\n authToken?: string;\n authTokenFallback?: string;\n fetch: TFetch;\n options?: Parameters<TFetch>[1];\n url: URL | string;\n}): Promise<Response> {\n let res = await fetch(url, {\n ...options,\n headers: {\n ...options?.headers,\n Authorization: `Bearer ${authToken}`,\n },\n });\n\n if ([401, 403].includes(res.status) && authTokenFallback) {\n res = await fetch(url, {\n ...options,\n headers: {\n ...options?.headers,\n Authorization: `Bearer ${authTokenFallback}`,\n },\n });\n }\n\n return res;\n}\n\nexport function signWithHashJs(\n data: unknown,\n signingKey: string,\n ts: string,\n): string {\n // Calculate the HMAC of the request body ourselves.\n // We make the assumption here that a stringified body is the same as the\n // raw bytes; it may be pertinent in the future to always parse, then\n // canonicalize the body to ensure it's consistent.\n const encoded = typeof data === \"string\" ? data : canonicalize(data);\n //
|
|
1
|
+
{"version":3,"file":"net.js","names":[],"sources":["../../src/helpers/net.ts"],"sourcesContent":["import canonicalize from \"canonicalize\";\nimport hashjs from \"hash.js\";\nimport type { Logger } from \"../middleware/logger.ts\";\nimport { logOnce } from \"./log.ts\";\nimport { removeSigningKeyPrefix } from \"./strings.ts\";\n\nconst { hmac, sha256 } = hashjs;\n\n/**\n * Send an HTTP request with the given signing key. If the response is a 401 or\n * 403, then try again with the fallback signing key\n */\nexport async function fetchWithAuthFallback<TFetch extends typeof fetch>({\n authToken,\n authTokenFallback,\n fetch,\n options,\n url,\n}: {\n authToken?: string;\n authTokenFallback?: string;\n fetch: TFetch;\n options?: Parameters<TFetch>[1];\n url: URL | string;\n}): Promise<Response> {\n let res = await fetch(url, {\n ...options,\n headers: {\n ...options?.headers,\n Authorization: `Bearer ${authToken}`,\n },\n });\n\n if ([401, 403].includes(res.status) && authTokenFallback) {\n res = await fetch(url, {\n ...options,\n headers: {\n ...options?.headers,\n Authorization: `Bearer ${authTokenFallback}`,\n },\n });\n }\n\n return res;\n}\n\nexport function signWithHashJs(\n data: unknown,\n signingKey: string,\n ts: string,\n): string {\n // Calculate the HMAC of the request body ourselves.\n // We make the assumption here that a stringified body is the same as the\n // raw bytes; it may be pertinent in the future to always parse, then\n // canonicalize the body to ensure it's consistent.\n const encoded = typeof data === \"string\" ? data : canonicalize(data);\n // biome-ignore lint/suspicious/noExplicitAny: intentional\n const mac = hmac(sha256 as any, removeSigningKeyPrefix(signingKey))\n .update(encoded)\n .update(ts)\n .digest(\"hex\");\n\n return mac;\n}\n\n// Cache for CryptoKeys to avoid repeated importKey calls\nconst cryptoKeyCache = new Map<string, CryptoKey>();\n\nasync function signWithNative(\n subtle: SubtleCrypto,\n data: unknown,\n signingKey: string,\n ts: string,\n): Promise<string> {\n const encoded = typeof data === \"string\" ? data : canonicalize(data);\n const key = removeSigningKeyPrefix(signingKey);\n\n let cryptoKey = cryptoKeyCache.get(key);\n if (!cryptoKey) {\n cryptoKey = await subtle.importKey(\n \"raw\",\n new TextEncoder().encode(key),\n { name: \"HMAC\", hash: \"SHA-256\" },\n false,\n [\"sign\"],\n );\n cryptoKeyCache.set(key, cryptoKey);\n }\n\n const signature = await subtle.sign(\n \"HMAC\",\n cryptoKey,\n new TextEncoder().encode(encoded + ts),\n );\n\n return Array.from(new Uint8Array(signature))\n .map((b) => b.toString(16).padStart(2, \"0\"))\n .join(\"\");\n}\n\n/**\n * Sign data with a signing key using HMAC-SHA256.\n * Uses native crypto.subtle when available, falls back to hash.js.\n */\nexport async function signDataWithKey(\n data: unknown,\n signingKey: string,\n ts: string,\n logger: Logger,\n): Promise<string> {\n const subtle = globalThis.crypto?.subtle;\n\n logOnce(\n logger,\n \"debug\",\n \"crypto-implementation\",\n subtle\n ? \"Using native Web Crypto for request signing\"\n : \"Using hash.js fallback for request signing (native crypto unavailable)\",\n );\n\n if (subtle) {\n try {\n return await signWithNative(subtle, data, signingKey, ts);\n } catch (err) {\n logger.debug({ err }, \"Native crypto failed, falling back to hash.js\");\n }\n }\n return signWithHashJs(data, signingKey, ts);\n}\n"],"mappings":";;;;;;AAMA,MAAM,EAAE,MAAM,WAAW;;;;;AAMzB,eAAsB,sBAAmD,EACvE,WACA,mBACA,OACA,SACA,OAOoB;CACpB,IAAI,MAAM,MAAM,MAAM,KAAK;EACzB,GAAG;EACH,SAAS;GACP,GAAG,SAAS;GACZ,eAAe,UAAU;GAC1B;EACF,CAAC;AAEF,KAAI,CAAC,KAAK,IAAI,CAAC,SAAS,IAAI,OAAO,IAAI,kBACrC,OAAM,MAAM,MAAM,KAAK;EACrB,GAAG;EACH,SAAS;GACP,GAAG,SAAS;GACZ,eAAe,UAAU;GAC1B;EACF,CAAC;AAGJ,QAAO;;AAGT,SAAgB,eACd,MACA,YACA,IACQ;CAKR,MAAM,UAAU,OAAO,SAAS,WAAW,OAAO,aAAa,KAAK;AAOpE,QALY,KAAK,QAAe,uBAAuB,WAAW,CAAC,CAChE,OAAO,QAAQ,CACf,OAAO,GAAG,CACV,OAAO,MAAM;;AAMlB,MAAM,iCAAiB,IAAI,KAAwB;AAEnD,eAAe,eACb,QACA,MACA,YACA,IACiB;CACjB,MAAM,UAAU,OAAO,SAAS,WAAW,OAAO,aAAa,KAAK;CACpE,MAAM,MAAM,uBAAuB,WAAW;CAE9C,IAAI,YAAY,eAAe,IAAI,IAAI;AACvC,KAAI,CAAC,WAAW;AACd,cAAY,MAAM,OAAO,UACvB,OACA,IAAI,aAAa,CAAC,OAAO,IAAI,EAC7B;GAAE,MAAM;GAAQ,MAAM;GAAW,EACjC,OACA,CAAC,OAAO,CACT;AACD,iBAAe,IAAI,KAAK,UAAU;;CAGpC,MAAM,YAAY,MAAM,OAAO,KAC7B,QACA,WACA,IAAI,aAAa,CAAC,OAAO,UAAU,GAAG,CACvC;AAED,QAAO,MAAM,KAAK,IAAI,WAAW,UAAU,CAAC,CACzC,KAAK,MAAM,EAAE,SAAS,GAAG,CAAC,SAAS,GAAG,IAAI,CAAC,CAC3C,KAAK,GAAG;;;;;;AAOb,eAAsB,gBACpB,MACA,YACA,IACA,QACiB;CACjB,MAAM,SAAS,WAAW,QAAQ;AAElC,SACE,QACA,SACA,yBACA,SACI,gDACA,yEACL;AAED,KAAI,OACF,KAAI;AACF,SAAO,MAAM,eAAe,QAAQ,MAAM,YAAY,GAAG;UAClD,KAAK;AACZ,SAAO,MAAM,EAAE,KAAK,EAAE,gDAAgD;;AAG1E,QAAO,eAAe,MAAM,YAAY,GAAG"}
|
package/helpers/strings.cjs
CHANGED
|
@@ -81,13 +81,17 @@ const hashEventKey = (eventKey) => {
|
|
|
81
81
|
const hashSigningKey = (signingKey) => {
|
|
82
82
|
if (!signingKey) return "";
|
|
83
83
|
const prefix = signingKey.match(/^signkey-[\w]+-/)?.shift() || "";
|
|
84
|
-
const key = signingKey
|
|
84
|
+
const key = removeSigningKeyPrefix(signingKey);
|
|
85
85
|
return `${prefix}${sha256().update(key, "hex").digest("hex")}`;
|
|
86
86
|
};
|
|
87
|
+
function removeSigningKeyPrefix(signingKey) {
|
|
88
|
+
return signingKey.replace(/^signkey-[\w]+-/, "");
|
|
89
|
+
}
|
|
87
90
|
|
|
88
91
|
//#endregion
|
|
89
92
|
exports.hashEventKey = hashEventKey;
|
|
90
93
|
exports.hashSigningKey = hashSigningKey;
|
|
94
|
+
exports.removeSigningKeyPrefix = removeSigningKeyPrefix;
|
|
91
95
|
exports.slugify = slugify;
|
|
92
96
|
exports.stringify = stringify;
|
|
93
97
|
exports.timeStr = timeStr;
|
package/helpers/strings.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"strings.cjs","names":["hashjs","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 * 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 *\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
|
|
1
|
+
{"version":3,"file":"strings.cjs","names":["hashjs","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 * 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 *\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 = 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":";;;;;;;;;AAKA,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;;;;;;;;AASD,MAAa,WAIX,UACW;AACX,KAAI,iBAAiB,KACnB,QAAO,MAAM,aAAa;CAG5B,MAAMC,eACJ,OAAO,UAAU,2BAAc,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;;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"}
|
package/helpers/strings.js
CHANGED
|
@@ -77,10 +77,13 @@ const hashEventKey = (eventKey) => {
|
|
|
77
77
|
const hashSigningKey = (signingKey) => {
|
|
78
78
|
if (!signingKey) return "";
|
|
79
79
|
const prefix = signingKey.match(/^signkey-[\w]+-/)?.shift() || "";
|
|
80
|
-
const key = signingKey
|
|
80
|
+
const key = removeSigningKeyPrefix(signingKey);
|
|
81
81
|
return `${prefix}${sha256().update(key, "hex").digest("hex")}`;
|
|
82
82
|
};
|
|
83
|
+
function removeSigningKeyPrefix(signingKey) {
|
|
84
|
+
return signingKey.replace(/^signkey-[\w]+-/, "");
|
|
85
|
+
}
|
|
83
86
|
|
|
84
87
|
//#endregion
|
|
85
|
-
export { hashEventKey, hashSigningKey, slugify, stringify$1 as stringify, timeStr, timingSafeEqual };
|
|
88
|
+
export { hashEventKey, hashSigningKey, removeSigningKeyPrefix, slugify, stringify$1 as stringify, timeStr, timingSafeEqual };
|
|
86
89
|
//# sourceMappingURL=strings.js.map
|
package/helpers/strings.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"strings.js","names":["stringify","safeStringify","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 * 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 *\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
|
|
1
|
+
{"version":3,"file":"strings.js","names":["stringify","safeStringify","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 * 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 *\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 = 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":";;;;;AAKA,MAAM,EAAE,WAAW;;;;;;;;;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,MAAaA,eAAa,UAAuB;AAC/C,QAAOC,UAAc,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,MAAMC,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;;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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "inngest",
|
|
3
|
-
"version": "4.2.
|
|
3
|
+
"version": "4.2.6",
|
|
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",
|