@shopify/remix-oxygen 1.1.7 → 1.1.8

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.
@@ -125,7 +125,8 @@ function getStorefrontHeaders(request) {
125
125
  return {
126
126
  requestGroupId: headers.get("request-id"),
127
127
  buyerIp: headers.get("oxygen-buyer-ip"),
128
- cookie: headers.get("cookie")
128
+ cookie: headers.get("cookie"),
129
+ purpose: headers.get("purpose")
129
130
  };
130
131
  }
131
132
 
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/implementations.ts","../../src/crypto.ts","../../src/server.ts","../../src/event-logger.ts","../../src/index.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n createCookieFactory,\n createCookieSessionStorageFactory,\n createMemorySessionStorageFactory,\n createSessionStorageFactory,\n} from '@remix-run/server-runtime';\n\nimport {sign, unsign} from './crypto';\n\nexport const createCookie = createCookieFactory({sign, unsign});\nexport const createCookieSessionStorage =\n createCookieSessionStorageFactory(createCookie);\nexport const createSessionStorage = createSessionStorageFactory(createCookie);\nexport const createMemorySessionStorage =\n createMemorySessionStorageFactory(createSessionStorage);\n","import type {SignFunction, UnsignFunction} from '@remix-run/server-runtime';\n\nconst encoder = new TextEncoder();\n\nexport const sign: SignFunction = async (value, secret) => {\n const key = await createKey(secret, ['sign']);\n const data = encoder.encode(value);\n const signature = await crypto.subtle.sign('HMAC', key, data);\n const hash = btoa(String.fromCharCode(...new Uint8Array(signature))).replace(\n /=+$/,\n '',\n );\n\n return value + '.' + hash;\n};\n\nexport const unsign: UnsignFunction = async (signed, secret) => {\n const index = signed.lastIndexOf('.');\n const value = signed.slice(0, index);\n const hash = signed.slice(index + 1);\n\n const key = await createKey(secret, ['verify']);\n const data = encoder.encode(value);\n const signature = byteStringToUint8Array(atob(hash));\n const valid = await crypto.subtle.verify('HMAC', key, signature, data);\n\n return valid ? value : false;\n};\n\nasync function createKey(\n secret: string,\n usages: CryptoKey['usages'],\n): Promise<CryptoKey> {\n const key = await crypto.subtle.importKey(\n 'raw',\n encoder.encode(secret),\n {name: 'HMAC', hash: 'SHA-256'},\n false,\n usages,\n );\n\n return key;\n}\n\nfunction byteStringToUint8Array(byteString: string): Uint8Array {\n const array = new Uint8Array(byteString.length);\n\n for (let i = 0; i < byteString.length; i++) {\n array[i] = byteString.charCodeAt(i);\n }\n\n return array;\n}\n","import {\n createRequestHandler as createRemixRequestHandler,\n type AppLoadContext,\n type ServerBuild,\n} from '@remix-run/server-runtime';\nimport {createEventLogger, type H2OEvent} from './event-logger';\n\ndeclare global {\n var __H2O_LOG_EVENT: undefined | ((event: H2OEvent) => void);\n}\n\nconst originalErrorToString = Error.prototype.toString;\nError.prototype.toString = function () {\n return this.stack || originalErrorToString.call(this);\n};\n\nexport function createRequestHandler<Context = unknown>({\n build,\n mode,\n poweredByHeader = true,\n getLoadContext,\n}: {\n build: ServerBuild;\n mode?: string;\n poweredByHeader?: boolean;\n getLoadContext?: (request: Request) => Promise<Context> | Context;\n}) {\n const handleRequest = createRemixRequestHandler(build, mode);\n\n return async (request: Request) => {\n const context = getLoadContext\n ? ((await getLoadContext(request)) as AppLoadContext)\n : undefined;\n\n if (process.env.NODE_ENV === 'development' && context) {\n // Store logger in globalThis so it can be accessed from the worker.\n // The global property must be different from the binding name,\n // otherwise Miniflare throws an error when accessing it.\n globalThis.__H2O_LOG_EVENT = createEventLogger(context);\n }\n\n const startTime = Date.now();\n\n const response = await handleRequest(request, context);\n\n if (process.env.NODE_ENV === 'development') {\n globalThis.__H2O_LOG_EVENT?.({\n eventType: 'request',\n url: request.url,\n requestId: request.headers.get('request-id'),\n purpose: request.headers.get('purpose'),\n startTime,\n });\n }\n\n if (poweredByHeader) {\n response.headers.append('powered-by', 'Shopify, Hydrogen');\n }\n\n return response;\n };\n}\n\nexport function getBuyerIp(request: Request) {\n return request.headers.get('oxygen-buyer-ip') ?? undefined;\n}\n\ntype StorefrontHeaders = {\n requestGroupId: string | null;\n buyerIp: string | null;\n cookie: string | null;\n};\n\nexport function getStorefrontHeaders(request: Request): StorefrontHeaders {\n const headers = request.headers;\n return {\n requestGroupId: headers.get('request-id'),\n buyerIp: headers.get('oxygen-buyer-ip'),\n cookie: headers.get('cookie'),\n };\n}\n","export type H2OEvent = {\n url: string;\n eventType: 'request' | 'subrequest';\n requestId?: string | null;\n purpose?: string | null;\n startTime: number;\n endTime?: number;\n cacheStatus?: 'MISS' | 'HIT' | 'STALE' | 'PUT';\n waitUntil?: ExecutionContext['waitUntil'];\n};\n\nlet hasWarned = false;\n\nexport function createEventLogger(appLoadContext: Record<string, unknown>) {\n const context = (appLoadContext || {}) as {\n env?: Record<string, any>;\n waitUntil?: (promise: Promise<any>) => void;\n };\n\n const eventLoggerService = context?.env?.H2O_LOG_EVENT as\n | undefined\n | {fetch: (req: Request) => Promise<Response>};\n\n if (typeof eventLoggerService?.fetch !== 'function') return;\n\n return ({\n url,\n endTime = Date.now(),\n waitUntil = context?.waitUntil,\n ...rest\n }: H2OEvent) => {\n const promise = Promise.resolve().then(() =>\n eventLoggerService\n .fetch(\n new Request(url, {\n method: 'POST',\n body: JSON.stringify({\n endTime,\n ...rest,\n }),\n }),\n )\n .catch((error: Error) => {\n if (!hasWarned) {\n // This might repeat a lot of times due to\n // the same issue, so we only warn once.\n console.debug('Failed to log H2O event\\n', error.stack);\n hasWarned = true;\n }\n }),\n );\n\n promise && waitUntil?.(promise);\n };\n}\n","export {\n createCookie,\n createCookieSessionStorage,\n createMemorySessionStorage,\n createSessionStorage,\n} from './implementations';\n\nexport {createRequestHandler, getBuyerIp, getStorefrontHeaders} from './server';\n\nexport {\n createSession,\n defer,\n isCookie,\n isSession,\n json,\n MaxPartSizeExceededError,\n redirect,\n unstable_composeUploadHandlers,\n unstable_createMemoryUploadHandler,\n unstable_parseMultipartFormData,\n} from '@remix-run/server-runtime';\n\nexport type {\n ActionArgs,\n ActionFunction,\n AppData,\n AppLoadContext,\n Cookie,\n CookieOptions,\n CookieParseOptions,\n CookieSerializeOptions,\n CookieSignatureOptions,\n DataFunctionArgs,\n EntryContext,\n ErrorBoundaryComponent,\n HandleDataRequestFunction,\n HandleDocumentRequestFunction,\n HeadersFunction,\n HtmlLinkDescriptor,\n HtmlMetaDescriptor,\n LinkDescriptor,\n LinksFunction,\n LoaderArgs,\n LoaderFunction,\n MemoryUploadHandlerFilterArgs,\n MemoryUploadHandlerOptions,\n MetaDescriptor,\n MetaFunction,\n PageLinkDescriptor,\n RequestHandler,\n RouteComponent,\n RouteHandle,\n SerializeFrom,\n ServerBuild,\n ServerEntryModule,\n Session,\n SessionData,\n SessionIdStorageStrategy,\n SessionStorage,\n SignFunction,\n TypedResponse,\n UnsignFunction,\n UploadHandler,\n UploadHandlerPart,\n V2_ServerRuntimeMetaArgs as V2_MetaArgs,\n V2_ServerRuntimeMetaDescriptor as V2_MetaDescriptor,\n // TODO: Remove in Remix v2\n V2_ServerRuntimeMetaDescriptor as V2_HtmlMetaDescriptor,\n V2_ServerRuntimeMetaFunction as V2_MetaFunction,\n} from '@remix-run/server-runtime';\n"]}
1
+ {"version":3,"sources":["../../src/implementations.ts","../../src/crypto.ts","../../src/server.ts","../../src/event-logger.ts","../../src/index.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n createCookieFactory,\n createCookieSessionStorageFactory,\n createMemorySessionStorageFactory,\n createSessionStorageFactory,\n} from '@remix-run/server-runtime';\n\nimport {sign, unsign} from './crypto';\n\nexport const createCookie = createCookieFactory({sign, unsign});\nexport const createCookieSessionStorage =\n createCookieSessionStorageFactory(createCookie);\nexport const createSessionStorage = createSessionStorageFactory(createCookie);\nexport const createMemorySessionStorage =\n createMemorySessionStorageFactory(createSessionStorage);\n","import type {SignFunction, UnsignFunction} from '@remix-run/server-runtime';\n\nconst encoder = new TextEncoder();\n\nexport const sign: SignFunction = async (value, secret) => {\n const key = await createKey(secret, ['sign']);\n const data = encoder.encode(value);\n const signature = await crypto.subtle.sign('HMAC', key, data);\n const hash = btoa(String.fromCharCode(...new Uint8Array(signature))).replace(\n /=+$/,\n '',\n );\n\n return value + '.' + hash;\n};\n\nexport const unsign: UnsignFunction = async (signed, secret) => {\n const index = signed.lastIndexOf('.');\n const value = signed.slice(0, index);\n const hash = signed.slice(index + 1);\n\n const key = await createKey(secret, ['verify']);\n const data = encoder.encode(value);\n const signature = byteStringToUint8Array(atob(hash));\n const valid = await crypto.subtle.verify('HMAC', key, signature, data);\n\n return valid ? value : false;\n};\n\nasync function createKey(\n secret: string,\n usages: CryptoKey['usages'],\n): Promise<CryptoKey> {\n const key = await crypto.subtle.importKey(\n 'raw',\n encoder.encode(secret),\n {name: 'HMAC', hash: 'SHA-256'},\n false,\n usages,\n );\n\n return key;\n}\n\nfunction byteStringToUint8Array(byteString: string): Uint8Array {\n const array = new Uint8Array(byteString.length);\n\n for (let i = 0; i < byteString.length; i++) {\n array[i] = byteString.charCodeAt(i);\n }\n\n return array;\n}\n","import {\n createRequestHandler as createRemixRequestHandler,\n type AppLoadContext,\n type ServerBuild,\n} from '@remix-run/server-runtime';\nimport {createEventLogger, type H2OEvent} from './event-logger';\n\ndeclare global {\n var __H2O_LOG_EVENT: undefined | ((event: H2OEvent) => void);\n}\n\nconst originalErrorToString = Error.prototype.toString;\nError.prototype.toString = function () {\n return this.stack || originalErrorToString.call(this);\n};\n\nexport function createRequestHandler<Context = unknown>({\n build,\n mode,\n poweredByHeader = true,\n getLoadContext,\n}: {\n build: ServerBuild;\n mode?: string;\n poweredByHeader?: boolean;\n getLoadContext?: (request: Request) => Promise<Context> | Context;\n}) {\n const handleRequest = createRemixRequestHandler(build, mode);\n\n return async (request: Request) => {\n const context = getLoadContext\n ? ((await getLoadContext(request)) as AppLoadContext)\n : undefined;\n\n if (process.env.NODE_ENV === 'development' && context) {\n // Store logger in globalThis so it can be accessed from the worker.\n // The global property must be different from the binding name,\n // otherwise Miniflare throws an error when accessing it.\n globalThis.__H2O_LOG_EVENT = createEventLogger(context);\n }\n\n const startTime = Date.now();\n\n const response = await handleRequest(request, context);\n\n if (process.env.NODE_ENV === 'development') {\n globalThis.__H2O_LOG_EVENT?.({\n eventType: 'request',\n url: request.url,\n requestId: request.headers.get('request-id'),\n purpose: request.headers.get('purpose'),\n startTime,\n });\n }\n\n if (poweredByHeader) {\n response.headers.append('powered-by', 'Shopify, Hydrogen');\n }\n\n return response;\n };\n}\n\nexport function getBuyerIp(request: Request) {\n return request.headers.get('oxygen-buyer-ip') ?? undefined;\n}\n\ntype StorefrontHeaders = {\n requestGroupId: string | null;\n buyerIp: string | null;\n cookie: string | null;\n purpose: string | null;\n};\n\nexport function getStorefrontHeaders(request: Request): StorefrontHeaders {\n const headers = request.headers;\n return {\n requestGroupId: headers.get('request-id'),\n buyerIp: headers.get('oxygen-buyer-ip'),\n cookie: headers.get('cookie'),\n purpose: headers.get('purpose'),\n };\n}\n","export type H2OEvent = {\n url: string;\n eventType: 'request' | 'subrequest';\n requestId?: string | null;\n purpose?: string | null;\n startTime: number;\n endTime?: number;\n cacheStatus?: 'MISS' | 'HIT' | 'STALE' | 'PUT';\n waitUntil?: ExecutionContext['waitUntil'];\n};\n\nlet hasWarned = false;\n\nexport function createEventLogger(appLoadContext: Record<string, unknown>) {\n const context = (appLoadContext || {}) as {\n env?: Record<string, any>;\n waitUntil?: (promise: Promise<any>) => void;\n };\n\n const eventLoggerService = context?.env?.H2O_LOG_EVENT as\n | undefined\n | {fetch: (req: Request) => Promise<Response>};\n\n if (typeof eventLoggerService?.fetch !== 'function') return;\n\n return ({\n url,\n endTime = Date.now(),\n waitUntil = context?.waitUntil,\n ...rest\n }: H2OEvent) => {\n const promise = Promise.resolve().then(() =>\n eventLoggerService\n .fetch(\n new Request(url, {\n method: 'POST',\n body: JSON.stringify({\n endTime,\n ...rest,\n }),\n }),\n )\n .catch((error: Error) => {\n if (!hasWarned) {\n // This might repeat a lot of times due to\n // the same issue, so we only warn once.\n console.debug('Failed to log H2O event\\n', error.stack);\n hasWarned = true;\n }\n }),\n );\n\n promise && waitUntil?.(promise);\n };\n}\n","export {\n createCookie,\n createCookieSessionStorage,\n createMemorySessionStorage,\n createSessionStorage,\n} from './implementations';\n\nexport {createRequestHandler, getBuyerIp, getStorefrontHeaders} from './server';\n\nexport {\n createSession,\n defer,\n isCookie,\n isSession,\n json,\n MaxPartSizeExceededError,\n redirect,\n unstable_composeUploadHandlers,\n unstable_createMemoryUploadHandler,\n unstable_parseMultipartFormData,\n} from '@remix-run/server-runtime';\n\nexport type {\n ActionArgs,\n ActionFunction,\n AppData,\n AppLoadContext,\n Cookie,\n CookieOptions,\n CookieParseOptions,\n CookieSerializeOptions,\n CookieSignatureOptions,\n DataFunctionArgs,\n EntryContext,\n ErrorBoundaryComponent,\n HandleDataRequestFunction,\n HandleDocumentRequestFunction,\n HeadersFunction,\n HtmlLinkDescriptor,\n HtmlMetaDescriptor,\n LinkDescriptor,\n LinksFunction,\n LoaderArgs,\n LoaderFunction,\n MemoryUploadHandlerFilterArgs,\n MemoryUploadHandlerOptions,\n MetaDescriptor,\n MetaFunction,\n PageLinkDescriptor,\n RequestHandler,\n RouteComponent,\n RouteHandle,\n SerializeFrom,\n ServerBuild,\n ServerEntryModule,\n Session,\n SessionData,\n SessionIdStorageStrategy,\n SessionStorage,\n SignFunction,\n TypedResponse,\n UnsignFunction,\n UploadHandler,\n UploadHandlerPart,\n V2_ServerRuntimeMetaArgs as V2_MetaArgs,\n V2_ServerRuntimeMetaDescriptor as V2_MetaDescriptor,\n // TODO: Remove in Remix v2\n V2_ServerRuntimeMetaDescriptor as V2_HtmlMetaDescriptor,\n V2_ServerRuntimeMetaFunction as V2_MetaFunction,\n} from '@remix-run/server-runtime';\n"]}
@@ -124,7 +124,8 @@ function getStorefrontHeaders(request) {
124
124
  return {
125
125
  requestGroupId: headers.get("request-id"),
126
126
  buyerIp: headers.get("oxygen-buyer-ip"),
127
- cookie: headers.get("cookie")
127
+ cookie: headers.get("cookie"),
128
+ purpose: headers.get("purpose")
128
129
  };
129
130
  }
130
131
 
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/implementations.ts","../../src/crypto.ts","../../src/server.ts","../../src/event-logger.ts","../../src/index.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n createCookieFactory,\n createCookieSessionStorageFactory,\n createMemorySessionStorageFactory,\n createSessionStorageFactory,\n} from '@remix-run/server-runtime';\n\nimport {sign, unsign} from './crypto';\n\nexport const createCookie = createCookieFactory({sign, unsign});\nexport const createCookieSessionStorage =\n createCookieSessionStorageFactory(createCookie);\nexport const createSessionStorage = createSessionStorageFactory(createCookie);\nexport const createMemorySessionStorage =\n createMemorySessionStorageFactory(createSessionStorage);\n","import type {SignFunction, UnsignFunction} from '@remix-run/server-runtime';\n\nconst encoder = new TextEncoder();\n\nexport const sign: SignFunction = async (value, secret) => {\n const key = await createKey(secret, ['sign']);\n const data = encoder.encode(value);\n const signature = await crypto.subtle.sign('HMAC', key, data);\n const hash = btoa(String.fromCharCode(...new Uint8Array(signature))).replace(\n /=+$/,\n '',\n );\n\n return value + '.' + hash;\n};\n\nexport const unsign: UnsignFunction = async (signed, secret) => {\n const index = signed.lastIndexOf('.');\n const value = signed.slice(0, index);\n const hash = signed.slice(index + 1);\n\n const key = await createKey(secret, ['verify']);\n const data = encoder.encode(value);\n const signature = byteStringToUint8Array(atob(hash));\n const valid = await crypto.subtle.verify('HMAC', key, signature, data);\n\n return valid ? value : false;\n};\n\nasync function createKey(\n secret: string,\n usages: CryptoKey['usages'],\n): Promise<CryptoKey> {\n const key = await crypto.subtle.importKey(\n 'raw',\n encoder.encode(secret),\n {name: 'HMAC', hash: 'SHA-256'},\n false,\n usages,\n );\n\n return key;\n}\n\nfunction byteStringToUint8Array(byteString: string): Uint8Array {\n const array = new Uint8Array(byteString.length);\n\n for (let i = 0; i < byteString.length; i++) {\n array[i] = byteString.charCodeAt(i);\n }\n\n return array;\n}\n","import {\n createRequestHandler as createRemixRequestHandler,\n type AppLoadContext,\n type ServerBuild,\n} from '@remix-run/server-runtime';\nimport {createEventLogger, type H2OEvent} from './event-logger';\n\ndeclare global {\n var __H2O_LOG_EVENT: undefined | ((event: H2OEvent) => void);\n}\n\nconst originalErrorToString = Error.prototype.toString;\nError.prototype.toString = function () {\n return this.stack || originalErrorToString.call(this);\n};\n\nexport function createRequestHandler<Context = unknown>({\n build,\n mode,\n poweredByHeader = true,\n getLoadContext,\n}: {\n build: ServerBuild;\n mode?: string;\n poweredByHeader?: boolean;\n getLoadContext?: (request: Request) => Promise<Context> | Context;\n}) {\n const handleRequest = createRemixRequestHandler(build, mode);\n\n return async (request: Request) => {\n const context = getLoadContext\n ? ((await getLoadContext(request)) as AppLoadContext)\n : undefined;\n\n if (process.env.NODE_ENV === 'development' && context) {\n // Store logger in globalThis so it can be accessed from the worker.\n // The global property must be different from the binding name,\n // otherwise Miniflare throws an error when accessing it.\n globalThis.__H2O_LOG_EVENT = createEventLogger(context);\n }\n\n const startTime = Date.now();\n\n const response = await handleRequest(request, context);\n\n if (process.env.NODE_ENV === 'development') {\n globalThis.__H2O_LOG_EVENT?.({\n eventType: 'request',\n url: request.url,\n requestId: request.headers.get('request-id'),\n purpose: request.headers.get('purpose'),\n startTime,\n });\n }\n\n if (poweredByHeader) {\n response.headers.append('powered-by', 'Shopify, Hydrogen');\n }\n\n return response;\n };\n}\n\nexport function getBuyerIp(request: Request) {\n return request.headers.get('oxygen-buyer-ip') ?? undefined;\n}\n\ntype StorefrontHeaders = {\n requestGroupId: string | null;\n buyerIp: string | null;\n cookie: string | null;\n};\n\nexport function getStorefrontHeaders(request: Request): StorefrontHeaders {\n const headers = request.headers;\n return {\n requestGroupId: headers.get('request-id'),\n buyerIp: headers.get('oxygen-buyer-ip'),\n cookie: headers.get('cookie'),\n };\n}\n","export type H2OEvent = {\n url: string;\n eventType: 'request' | 'subrequest';\n requestId?: string | null;\n purpose?: string | null;\n startTime: number;\n endTime?: number;\n cacheStatus?: 'MISS' | 'HIT' | 'STALE' | 'PUT';\n waitUntil?: ExecutionContext['waitUntil'];\n};\n\nlet hasWarned = false;\n\nexport function createEventLogger(appLoadContext: Record<string, unknown>) {\n const context = (appLoadContext || {}) as {\n env?: Record<string, any>;\n waitUntil?: (promise: Promise<any>) => void;\n };\n\n const eventLoggerService = context?.env?.H2O_LOG_EVENT as\n | undefined\n | {fetch: (req: Request) => Promise<Response>};\n\n if (typeof eventLoggerService?.fetch !== 'function') return;\n\n return ({\n url,\n endTime = Date.now(),\n waitUntil = context?.waitUntil,\n ...rest\n }: H2OEvent) => {\n const promise = Promise.resolve().then(() =>\n eventLoggerService\n .fetch(\n new Request(url, {\n method: 'POST',\n body: JSON.stringify({\n endTime,\n ...rest,\n }),\n }),\n )\n .catch((error: Error) => {\n if (!hasWarned) {\n // This might repeat a lot of times due to\n // the same issue, so we only warn once.\n console.debug('Failed to log H2O event\\n', error.stack);\n hasWarned = true;\n }\n }),\n );\n\n promise && waitUntil?.(promise);\n };\n}\n","export {\n createCookie,\n createCookieSessionStorage,\n createMemorySessionStorage,\n createSessionStorage,\n} from './implementations';\n\nexport {createRequestHandler, getBuyerIp, getStorefrontHeaders} from './server';\n\nexport {\n createSession,\n defer,\n isCookie,\n isSession,\n json,\n MaxPartSizeExceededError,\n redirect,\n unstable_composeUploadHandlers,\n unstable_createMemoryUploadHandler,\n unstable_parseMultipartFormData,\n} from '@remix-run/server-runtime';\n\nexport type {\n ActionArgs,\n ActionFunction,\n AppData,\n AppLoadContext,\n Cookie,\n CookieOptions,\n CookieParseOptions,\n CookieSerializeOptions,\n CookieSignatureOptions,\n DataFunctionArgs,\n EntryContext,\n ErrorBoundaryComponent,\n HandleDataRequestFunction,\n HandleDocumentRequestFunction,\n HeadersFunction,\n HtmlLinkDescriptor,\n HtmlMetaDescriptor,\n LinkDescriptor,\n LinksFunction,\n LoaderArgs,\n LoaderFunction,\n MemoryUploadHandlerFilterArgs,\n MemoryUploadHandlerOptions,\n MetaDescriptor,\n MetaFunction,\n PageLinkDescriptor,\n RequestHandler,\n RouteComponent,\n RouteHandle,\n SerializeFrom,\n ServerBuild,\n ServerEntryModule,\n Session,\n SessionData,\n SessionIdStorageStrategy,\n SessionStorage,\n SignFunction,\n TypedResponse,\n UnsignFunction,\n UploadHandler,\n UploadHandlerPart,\n V2_ServerRuntimeMetaArgs as V2_MetaArgs,\n V2_ServerRuntimeMetaDescriptor as V2_MetaDescriptor,\n // TODO: Remove in Remix v2\n V2_ServerRuntimeMetaDescriptor as V2_HtmlMetaDescriptor,\n V2_ServerRuntimeMetaFunction as V2_MetaFunction,\n} from '@remix-run/server-runtime';\n"]}
1
+ {"version":3,"sources":["../../src/implementations.ts","../../src/crypto.ts","../../src/server.ts","../../src/event-logger.ts","../../src/index.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n createCookieFactory,\n createCookieSessionStorageFactory,\n createMemorySessionStorageFactory,\n createSessionStorageFactory,\n} from '@remix-run/server-runtime';\n\nimport {sign, unsign} from './crypto';\n\nexport const createCookie = createCookieFactory({sign, unsign});\nexport const createCookieSessionStorage =\n createCookieSessionStorageFactory(createCookie);\nexport const createSessionStorage = createSessionStorageFactory(createCookie);\nexport const createMemorySessionStorage =\n createMemorySessionStorageFactory(createSessionStorage);\n","import type {SignFunction, UnsignFunction} from '@remix-run/server-runtime';\n\nconst encoder = new TextEncoder();\n\nexport const sign: SignFunction = async (value, secret) => {\n const key = await createKey(secret, ['sign']);\n const data = encoder.encode(value);\n const signature = await crypto.subtle.sign('HMAC', key, data);\n const hash = btoa(String.fromCharCode(...new Uint8Array(signature))).replace(\n /=+$/,\n '',\n );\n\n return value + '.' + hash;\n};\n\nexport const unsign: UnsignFunction = async (signed, secret) => {\n const index = signed.lastIndexOf('.');\n const value = signed.slice(0, index);\n const hash = signed.slice(index + 1);\n\n const key = await createKey(secret, ['verify']);\n const data = encoder.encode(value);\n const signature = byteStringToUint8Array(atob(hash));\n const valid = await crypto.subtle.verify('HMAC', key, signature, data);\n\n return valid ? value : false;\n};\n\nasync function createKey(\n secret: string,\n usages: CryptoKey['usages'],\n): Promise<CryptoKey> {\n const key = await crypto.subtle.importKey(\n 'raw',\n encoder.encode(secret),\n {name: 'HMAC', hash: 'SHA-256'},\n false,\n usages,\n );\n\n return key;\n}\n\nfunction byteStringToUint8Array(byteString: string): Uint8Array {\n const array = new Uint8Array(byteString.length);\n\n for (let i = 0; i < byteString.length; i++) {\n array[i] = byteString.charCodeAt(i);\n }\n\n return array;\n}\n","import {\n createRequestHandler as createRemixRequestHandler,\n type AppLoadContext,\n type ServerBuild,\n} from '@remix-run/server-runtime';\nimport {createEventLogger, type H2OEvent} from './event-logger';\n\ndeclare global {\n var __H2O_LOG_EVENT: undefined | ((event: H2OEvent) => void);\n}\n\nconst originalErrorToString = Error.prototype.toString;\nError.prototype.toString = function () {\n return this.stack || originalErrorToString.call(this);\n};\n\nexport function createRequestHandler<Context = unknown>({\n build,\n mode,\n poweredByHeader = true,\n getLoadContext,\n}: {\n build: ServerBuild;\n mode?: string;\n poweredByHeader?: boolean;\n getLoadContext?: (request: Request) => Promise<Context> | Context;\n}) {\n const handleRequest = createRemixRequestHandler(build, mode);\n\n return async (request: Request) => {\n const context = getLoadContext\n ? ((await getLoadContext(request)) as AppLoadContext)\n : undefined;\n\n if (process.env.NODE_ENV === 'development' && context) {\n // Store logger in globalThis so it can be accessed from the worker.\n // The global property must be different from the binding name,\n // otherwise Miniflare throws an error when accessing it.\n globalThis.__H2O_LOG_EVENT = createEventLogger(context);\n }\n\n const startTime = Date.now();\n\n const response = await handleRequest(request, context);\n\n if (process.env.NODE_ENV === 'development') {\n globalThis.__H2O_LOG_EVENT?.({\n eventType: 'request',\n url: request.url,\n requestId: request.headers.get('request-id'),\n purpose: request.headers.get('purpose'),\n startTime,\n });\n }\n\n if (poweredByHeader) {\n response.headers.append('powered-by', 'Shopify, Hydrogen');\n }\n\n return response;\n };\n}\n\nexport function getBuyerIp(request: Request) {\n return request.headers.get('oxygen-buyer-ip') ?? undefined;\n}\n\ntype StorefrontHeaders = {\n requestGroupId: string | null;\n buyerIp: string | null;\n cookie: string | null;\n purpose: string | null;\n};\n\nexport function getStorefrontHeaders(request: Request): StorefrontHeaders {\n const headers = request.headers;\n return {\n requestGroupId: headers.get('request-id'),\n buyerIp: headers.get('oxygen-buyer-ip'),\n cookie: headers.get('cookie'),\n purpose: headers.get('purpose'),\n };\n}\n","export type H2OEvent = {\n url: string;\n eventType: 'request' | 'subrequest';\n requestId?: string | null;\n purpose?: string | null;\n startTime: number;\n endTime?: number;\n cacheStatus?: 'MISS' | 'HIT' | 'STALE' | 'PUT';\n waitUntil?: ExecutionContext['waitUntil'];\n};\n\nlet hasWarned = false;\n\nexport function createEventLogger(appLoadContext: Record<string, unknown>) {\n const context = (appLoadContext || {}) as {\n env?: Record<string, any>;\n waitUntil?: (promise: Promise<any>) => void;\n };\n\n const eventLoggerService = context?.env?.H2O_LOG_EVENT as\n | undefined\n | {fetch: (req: Request) => Promise<Response>};\n\n if (typeof eventLoggerService?.fetch !== 'function') return;\n\n return ({\n url,\n endTime = Date.now(),\n waitUntil = context?.waitUntil,\n ...rest\n }: H2OEvent) => {\n const promise = Promise.resolve().then(() =>\n eventLoggerService\n .fetch(\n new Request(url, {\n method: 'POST',\n body: JSON.stringify({\n endTime,\n ...rest,\n }),\n }),\n )\n .catch((error: Error) => {\n if (!hasWarned) {\n // This might repeat a lot of times due to\n // the same issue, so we only warn once.\n console.debug('Failed to log H2O event\\n', error.stack);\n hasWarned = true;\n }\n }),\n );\n\n promise && waitUntil?.(promise);\n };\n}\n","export {\n createCookie,\n createCookieSessionStorage,\n createMemorySessionStorage,\n createSessionStorage,\n} from './implementations';\n\nexport {createRequestHandler, getBuyerIp, getStorefrontHeaders} from './server';\n\nexport {\n createSession,\n defer,\n isCookie,\n isSession,\n json,\n MaxPartSizeExceededError,\n redirect,\n unstable_composeUploadHandlers,\n unstable_createMemoryUploadHandler,\n unstable_parseMultipartFormData,\n} from '@remix-run/server-runtime';\n\nexport type {\n ActionArgs,\n ActionFunction,\n AppData,\n AppLoadContext,\n Cookie,\n CookieOptions,\n CookieParseOptions,\n CookieSerializeOptions,\n CookieSignatureOptions,\n DataFunctionArgs,\n EntryContext,\n ErrorBoundaryComponent,\n HandleDataRequestFunction,\n HandleDocumentRequestFunction,\n HeadersFunction,\n HtmlLinkDescriptor,\n HtmlMetaDescriptor,\n LinkDescriptor,\n LinksFunction,\n LoaderArgs,\n LoaderFunction,\n MemoryUploadHandlerFilterArgs,\n MemoryUploadHandlerOptions,\n MetaDescriptor,\n MetaFunction,\n PageLinkDescriptor,\n RequestHandler,\n RouteComponent,\n RouteHandle,\n SerializeFrom,\n ServerBuild,\n ServerEntryModule,\n Session,\n SessionData,\n SessionIdStorageStrategy,\n SessionStorage,\n SignFunction,\n TypedResponse,\n UnsignFunction,\n UploadHandler,\n UploadHandlerPart,\n V2_ServerRuntimeMetaArgs as V2_MetaArgs,\n V2_ServerRuntimeMetaDescriptor as V2_MetaDescriptor,\n // TODO: Remove in Remix v2\n V2_ServerRuntimeMetaDescriptor as V2_HtmlMetaDescriptor,\n V2_ServerRuntimeMetaFunction as V2_MetaFunction,\n} from '@remix-run/server-runtime';\n"]}
@@ -2,7 +2,7 @@
2
2
 
3
3
  var serverRuntime = require('@remix-run/server-runtime');
4
4
 
5
- var c=new TextEncoder,d=async(e,t)=>{let r=await g(t,["sign"]),o=c.encode(e),s=await crypto.subtle.sign("HMAC",r,o),n=btoa(String.fromCharCode(...new Uint8Array(s))).replace(/=+$/,"");return e+"."+n},l=async(e,t)=>{let r=e.lastIndexOf("."),o=e.slice(0,r),s=e.slice(r+1),n=await g(t,["verify"]),a=c.encode(o),p=S(atob(s));return await crypto.subtle.verify("HMAC",n,p,a)?o:!1};async function g(e,t){return await crypto.subtle.importKey("raw",c.encode(e),{name:"HMAC",hash:"SHA-256"},!1,t)}function S(e){let t=new Uint8Array(e.length);for(let r=0;r<e.length;r++)t[r]=e.charCodeAt(r);return t}var u=serverRuntime.createCookieFactory({sign:d,unsign:l}),C=serverRuntime.createCookieSessionStorageFactory(u),y=serverRuntime.createSessionStorageFactory(u),v=serverRuntime.createMemorySessionStorageFactory(y);var _=Error.prototype.toString;Error.prototype.toString=function(){return this.stack||_.call(this)};function E({build:e,mode:t,poweredByHeader:r=!0,getLoadContext:o}){let s=serverRuntime.createRequestHandler(e,t);return async n=>{let a=o?await o(n):void 0,i=await s(n,a);return r&&i.headers.append("powered-by","Shopify, Hydrogen"),i}}function F(e){return e.headers.get("oxygen-buyer-ip")??void 0}function M(e){let t=e.headers;return {requestGroupId:t.get("request-id"),buyerIp:t.get("oxygen-buyer-ip"),cookie:t.get("cookie")}}
5
+ var c=new TextEncoder,d=async(e,t)=>{let r=await g(t,["sign"]),o=c.encode(e),s=await crypto.subtle.sign("HMAC",r,o),n=btoa(String.fromCharCode(...new Uint8Array(s))).replace(/=+$/,"");return e+"."+n},l=async(e,t)=>{let r=e.lastIndexOf("."),o=e.slice(0,r),s=e.slice(r+1),n=await g(t,["verify"]),a=c.encode(o),p=S(atob(s));return await crypto.subtle.verify("HMAC",n,p,a)?o:!1};async function g(e,t){return await crypto.subtle.importKey("raw",c.encode(e),{name:"HMAC",hash:"SHA-256"},!1,t)}function S(e){let t=new Uint8Array(e.length);for(let r=0;r<e.length;r++)t[r]=e.charCodeAt(r);return t}var u=serverRuntime.createCookieFactory({sign:d,unsign:l}),C=serverRuntime.createCookieSessionStorageFactory(u),y=serverRuntime.createSessionStorageFactory(u),v=serverRuntime.createMemorySessionStorageFactory(y);var _=Error.prototype.toString;Error.prototype.toString=function(){return this.stack||_.call(this)};function E({build:e,mode:t,poweredByHeader:r=!0,getLoadContext:o}){let s=serverRuntime.createRequestHandler(e,t);return async n=>{let a=o?await o(n):void 0,i=await s(n,a);return r&&i.headers.append("powered-by","Shopify, Hydrogen"),i}}function F(e){return e.headers.get("oxygen-buyer-ip")??void 0}function M(e){let t=e.headers;return {requestGroupId:t.get("request-id"),buyerIp:t.get("oxygen-buyer-ip"),cookie:t.get("cookie"),purpose:t.get("purpose")}}
6
6
 
7
7
  Object.defineProperty(exports, 'MaxPartSizeExceededError', {
8
8
  enumerable: true,
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/implementations.ts","../../src/crypto.ts","../../src/server.ts","../../src/index.ts"],"names":["createCookieFactory","createCookieSessionStorageFactory","createMemorySessionStorageFactory","createSessionStorageFactory","encoder","sign","value","secret","key","createKey","data","signature","hash","unsign","signed","index","byteStringToUint8Array","usages","byteString","array","i","createCookie","createCookieSessionStorage","createSessionStorage","createMemorySessionStorage","createRemixRequestHandler","originalErrorToString","createRequestHandler","build","mode","poweredByHeader","getLoadContext","handleRequest","request","context","startTime","response","getBuyerIp","getStorefrontHeaders","headers","createSession","defer","isCookie","isSession","json","MaxPartSizeExceededError","redirect","unstable_composeUploadHandlers","unstable_createMemoryUploadHandler","unstable_parseMultipartFormData"],"mappings":"AAAA,OACE,uBAAAA,EACA,qCAAAC,EACA,qCAAAC,EACA,+BAAAC,MACK,4BCHP,IAAMC,EAAU,IAAI,YAEPC,EAAqB,MAAOC,EAAOC,IAAW,CACzD,IAAMC,EAAM,MAAMC,EAAUF,EAAQ,CAAC,MAAM,CAAC,EACtCG,EAAON,EAAQ,OAAOE,CAAK,EAC3BK,EAAY,MAAM,OAAO,OAAO,KAAK,OAAQH,EAAKE,CAAI,EACtDE,EAAO,KAAK,OAAO,aAAa,GAAG,IAAI,WAAWD,CAAS,CAAC,CAAC,EAAE,QACnE,MACA,EACF,EAEA,OAAOL,EAAQ,IAAMM,CACvB,EAEaC,EAAyB,MAAOC,EAAQP,IAAW,CAC9D,IAAMQ,EAAQD,EAAO,YAAY,GAAG,EAC9BR,EAAQQ,EAAO,MAAM,EAAGC,CAAK,EAC7BH,EAAOE,EAAO,MAAMC,EAAQ,CAAC,EAE7BP,EAAM,MAAMC,EAAUF,EAAQ,CAAC,QAAQ,CAAC,EACxCG,EAAON,EAAQ,OAAOE,CAAK,EAC3BK,EAAYK,EAAuB,KAAKJ,CAAI,CAAC,EAGnD,OAFc,MAAM,OAAO,OAAO,OAAO,OAAQJ,EAAKG,EAAWD,CAAI,EAEtDJ,EAAQ,EACzB,EAEA,eAAeG,EACbF,EACAU,EACoB,CASpB,OARY,MAAM,OAAO,OAAO,UAC9B,MACAb,EAAQ,OAAOG,CAAM,EACrB,CAAC,KAAM,OAAQ,KAAM,SAAS,EAC9B,GACAU,CACF,CAGF,CAEA,SAASD,EAAuBE,EAAgC,CAC9D,IAAMC,EAAQ,IAAI,WAAWD,EAAW,MAAM,EAE9C,QAASE,EAAI,EAAGA,EAAIF,EAAW,OAAQE,IACrCD,EAAMC,CAAC,EAAIF,EAAW,WAAWE,CAAC,EAGpC,OAAOD,CACT,CD3CO,IAAME,EAAerB,EAAoB,CAAC,KAAAK,EAAM,OAAAQ,CAAM,CAAC,EACjDS,EACXrB,EAAkCoB,CAAY,EACnCE,EAAuBpB,EAA4BkB,CAAY,EAC/DG,EACXtB,EAAkCqB,CAAoB,EEdxD,OACE,wBAAwBE,MAGnB,4BAOP,IAAMC,EAAwB,MAAM,UAAU,SAC9C,MAAM,UAAU,SAAW,UAAY,CACrC,OAAO,KAAK,OAASA,EAAsB,KAAK,IAAI,CACtD,EAEO,SAASC,EAAwC,CACtD,MAAAC,EACA,KAAAC,EACA,gBAAAC,EAAkB,GAClB,eAAAC,CACF,EAKG,CACD,IAAMC,EAAgBP,EAA0BG,EAAOC,CAAI,EAE3D,MAAO,OAAOI,GAAqB,CACjC,IAAMC,EAAUH,EACV,MAAMA,EAAeE,CAAO,EAC9B,OASEE,EAAY,KAAK,IAAI,EAErBC,EAAW,MAAMJ,EAAcC,EAASC,CAAO,EAYrD,OAAIJ,GACFM,EAAS,QAAQ,OAAO,aAAc,mBAAmB,EAGpDA,CACT,CACF,CAEO,SAASC,EAAWJ,EAAkB,CAC3C,OAAOA,EAAQ,QAAQ,IAAI,iBAAiB,GAAK,MACnD,CAQO,SAASK,EAAqBL,EAAqC,CACxE,IAAMM,EAAUN,EAAQ,QACxB,MAAO,CACL,eAAgBM,EAAQ,IAAI,YAAY,EACxC,QAASA,EAAQ,IAAI,iBAAiB,EACtC,OAAQA,EAAQ,IAAI,QAAQ,CAC9B,CACF,CCvEA,OACE,iBAAAC,EACA,SAAAC,EACA,YAAAC,EACA,aAAAC,EACA,QAAAC,EACA,4BAAAC,EACA,YAAAC,EACA,kCAAAC,EACA,sCAAAC,EACA,mCAAAC,MACK","sourcesContent":["import {\n createCookieFactory,\n createCookieSessionStorageFactory,\n createMemorySessionStorageFactory,\n createSessionStorageFactory,\n} from '@remix-run/server-runtime';\n\nimport {sign, unsign} from './crypto';\n\nexport const createCookie = createCookieFactory({sign, unsign});\nexport const createCookieSessionStorage =\n createCookieSessionStorageFactory(createCookie);\nexport const createSessionStorage = createSessionStorageFactory(createCookie);\nexport const createMemorySessionStorage =\n createMemorySessionStorageFactory(createSessionStorage);\n","import type {SignFunction, UnsignFunction} from '@remix-run/server-runtime';\n\nconst encoder = new TextEncoder();\n\nexport const sign: SignFunction = async (value, secret) => {\n const key = await createKey(secret, ['sign']);\n const data = encoder.encode(value);\n const signature = await crypto.subtle.sign('HMAC', key, data);\n const hash = btoa(String.fromCharCode(...new Uint8Array(signature))).replace(\n /=+$/,\n '',\n );\n\n return value + '.' + hash;\n};\n\nexport const unsign: UnsignFunction = async (signed, secret) => {\n const index = signed.lastIndexOf('.');\n const value = signed.slice(0, index);\n const hash = signed.slice(index + 1);\n\n const key = await createKey(secret, ['verify']);\n const data = encoder.encode(value);\n const signature = byteStringToUint8Array(atob(hash));\n const valid = await crypto.subtle.verify('HMAC', key, signature, data);\n\n return valid ? value : false;\n};\n\nasync function createKey(\n secret: string,\n usages: CryptoKey['usages'],\n): Promise<CryptoKey> {\n const key = await crypto.subtle.importKey(\n 'raw',\n encoder.encode(secret),\n {name: 'HMAC', hash: 'SHA-256'},\n false,\n usages,\n );\n\n return key;\n}\n\nfunction byteStringToUint8Array(byteString: string): Uint8Array {\n const array = new Uint8Array(byteString.length);\n\n for (let i = 0; i < byteString.length; i++) {\n array[i] = byteString.charCodeAt(i);\n }\n\n return array;\n}\n","import {\n createRequestHandler as createRemixRequestHandler,\n type AppLoadContext,\n type ServerBuild,\n} from '@remix-run/server-runtime';\nimport {createEventLogger, type H2OEvent} from './event-logger';\n\ndeclare global {\n var __H2O_LOG_EVENT: undefined | ((event: H2OEvent) => void);\n}\n\nconst originalErrorToString = Error.prototype.toString;\nError.prototype.toString = function () {\n return this.stack || originalErrorToString.call(this);\n};\n\nexport function createRequestHandler<Context = unknown>({\n build,\n mode,\n poweredByHeader = true,\n getLoadContext,\n}: {\n build: ServerBuild;\n mode?: string;\n poweredByHeader?: boolean;\n getLoadContext?: (request: Request) => Promise<Context> | Context;\n}) {\n const handleRequest = createRemixRequestHandler(build, mode);\n\n return async (request: Request) => {\n const context = getLoadContext\n ? ((await getLoadContext(request)) as AppLoadContext)\n : undefined;\n\n if (process.env.NODE_ENV === 'development' && context) {\n // Store logger in globalThis so it can be accessed from the worker.\n // The global property must be different from the binding name,\n // otherwise Miniflare throws an error when accessing it.\n globalThis.__H2O_LOG_EVENT = createEventLogger(context);\n }\n\n const startTime = Date.now();\n\n const response = await handleRequest(request, context);\n\n if (process.env.NODE_ENV === 'development') {\n globalThis.__H2O_LOG_EVENT?.({\n eventType: 'request',\n url: request.url,\n requestId: request.headers.get('request-id'),\n purpose: request.headers.get('purpose'),\n startTime,\n });\n }\n\n if (poweredByHeader) {\n response.headers.append('powered-by', 'Shopify, Hydrogen');\n }\n\n return response;\n };\n}\n\nexport function getBuyerIp(request: Request) {\n return request.headers.get('oxygen-buyer-ip') ?? undefined;\n}\n\ntype StorefrontHeaders = {\n requestGroupId: string | null;\n buyerIp: string | null;\n cookie: string | null;\n};\n\nexport function getStorefrontHeaders(request: Request): StorefrontHeaders {\n const headers = request.headers;\n return {\n requestGroupId: headers.get('request-id'),\n buyerIp: headers.get('oxygen-buyer-ip'),\n cookie: headers.get('cookie'),\n };\n}\n","export {\n createCookie,\n createCookieSessionStorage,\n createMemorySessionStorage,\n createSessionStorage,\n} from './implementations';\n\nexport {createRequestHandler, getBuyerIp, getStorefrontHeaders} from './server';\n\nexport {\n createSession,\n defer,\n isCookie,\n isSession,\n json,\n MaxPartSizeExceededError,\n redirect,\n unstable_composeUploadHandlers,\n unstable_createMemoryUploadHandler,\n unstable_parseMultipartFormData,\n} from '@remix-run/server-runtime';\n\nexport type {\n ActionArgs,\n ActionFunction,\n AppData,\n AppLoadContext,\n Cookie,\n CookieOptions,\n CookieParseOptions,\n CookieSerializeOptions,\n CookieSignatureOptions,\n DataFunctionArgs,\n EntryContext,\n ErrorBoundaryComponent,\n HandleDataRequestFunction,\n HandleDocumentRequestFunction,\n HeadersFunction,\n HtmlLinkDescriptor,\n HtmlMetaDescriptor,\n LinkDescriptor,\n LinksFunction,\n LoaderArgs,\n LoaderFunction,\n MemoryUploadHandlerFilterArgs,\n MemoryUploadHandlerOptions,\n MetaDescriptor,\n MetaFunction,\n PageLinkDescriptor,\n RequestHandler,\n RouteComponent,\n RouteHandle,\n SerializeFrom,\n ServerBuild,\n ServerEntryModule,\n Session,\n SessionData,\n SessionIdStorageStrategy,\n SessionStorage,\n SignFunction,\n TypedResponse,\n UnsignFunction,\n UploadHandler,\n UploadHandlerPart,\n V2_ServerRuntimeMetaArgs as V2_MetaArgs,\n V2_ServerRuntimeMetaDescriptor as V2_MetaDescriptor,\n // TODO: Remove in Remix v2\n V2_ServerRuntimeMetaDescriptor as V2_HtmlMetaDescriptor,\n V2_ServerRuntimeMetaFunction as V2_MetaFunction,\n} from '@remix-run/server-runtime';\n"]}
1
+ {"version":3,"sources":["../../src/implementations.ts","../../src/crypto.ts","../../src/server.ts","../../src/index.ts"],"names":["createCookieFactory","createCookieSessionStorageFactory","createMemorySessionStorageFactory","createSessionStorageFactory","encoder","sign","value","secret","key","createKey","data","signature","hash","unsign","signed","index","byteStringToUint8Array","usages","byteString","array","i","createCookie","createCookieSessionStorage","createSessionStorage","createMemorySessionStorage","createRemixRequestHandler","originalErrorToString","createRequestHandler","build","mode","poweredByHeader","getLoadContext","handleRequest","request","context","startTime","response","getBuyerIp","getStorefrontHeaders","headers","createSession","defer","isCookie","isSession","json","MaxPartSizeExceededError","redirect","unstable_composeUploadHandlers","unstable_createMemoryUploadHandler","unstable_parseMultipartFormData"],"mappings":"AAAA,OACE,uBAAAA,EACA,qCAAAC,EACA,qCAAAC,EACA,+BAAAC,MACK,4BCHP,IAAMC,EAAU,IAAI,YAEPC,EAAqB,MAAOC,EAAOC,IAAW,CACzD,IAAMC,EAAM,MAAMC,EAAUF,EAAQ,CAAC,MAAM,CAAC,EACtCG,EAAON,EAAQ,OAAOE,CAAK,EAC3BK,EAAY,MAAM,OAAO,OAAO,KAAK,OAAQH,EAAKE,CAAI,EACtDE,EAAO,KAAK,OAAO,aAAa,GAAG,IAAI,WAAWD,CAAS,CAAC,CAAC,EAAE,QACnE,MACA,EACF,EAEA,OAAOL,EAAQ,IAAMM,CACvB,EAEaC,EAAyB,MAAOC,EAAQP,IAAW,CAC9D,IAAMQ,EAAQD,EAAO,YAAY,GAAG,EAC9BR,EAAQQ,EAAO,MAAM,EAAGC,CAAK,EAC7BH,EAAOE,EAAO,MAAMC,EAAQ,CAAC,EAE7BP,EAAM,MAAMC,EAAUF,EAAQ,CAAC,QAAQ,CAAC,EACxCG,EAAON,EAAQ,OAAOE,CAAK,EAC3BK,EAAYK,EAAuB,KAAKJ,CAAI,CAAC,EAGnD,OAFc,MAAM,OAAO,OAAO,OAAO,OAAQJ,EAAKG,EAAWD,CAAI,EAEtDJ,EAAQ,EACzB,EAEA,eAAeG,EACbF,EACAU,EACoB,CASpB,OARY,MAAM,OAAO,OAAO,UAC9B,MACAb,EAAQ,OAAOG,CAAM,EACrB,CAAC,KAAM,OAAQ,KAAM,SAAS,EAC9B,GACAU,CACF,CAGF,CAEA,SAASD,EAAuBE,EAAgC,CAC9D,IAAMC,EAAQ,IAAI,WAAWD,EAAW,MAAM,EAE9C,QAASE,EAAI,EAAGA,EAAIF,EAAW,OAAQE,IACrCD,EAAMC,CAAC,EAAIF,EAAW,WAAWE,CAAC,EAGpC,OAAOD,CACT,CD3CO,IAAME,EAAerB,EAAoB,CAAC,KAAAK,EAAM,OAAAQ,CAAM,CAAC,EACjDS,EACXrB,EAAkCoB,CAAY,EACnCE,EAAuBpB,EAA4BkB,CAAY,EAC/DG,EACXtB,EAAkCqB,CAAoB,EEdxD,OACE,wBAAwBE,MAGnB,4BAOP,IAAMC,EAAwB,MAAM,UAAU,SAC9C,MAAM,UAAU,SAAW,UAAY,CACrC,OAAO,KAAK,OAASA,EAAsB,KAAK,IAAI,CACtD,EAEO,SAASC,EAAwC,CACtD,MAAAC,EACA,KAAAC,EACA,gBAAAC,EAAkB,GAClB,eAAAC,CACF,EAKG,CACD,IAAMC,EAAgBP,EAA0BG,EAAOC,CAAI,EAE3D,MAAO,OAAOI,GAAqB,CACjC,IAAMC,EAAUH,EACV,MAAMA,EAAeE,CAAO,EAC9B,OASEE,EAAY,KAAK,IAAI,EAErBC,EAAW,MAAMJ,EAAcC,EAASC,CAAO,EAYrD,OAAIJ,GACFM,EAAS,QAAQ,OAAO,aAAc,mBAAmB,EAGpDA,CACT,CACF,CAEO,SAASC,EAAWJ,EAAkB,CAC3C,OAAOA,EAAQ,QAAQ,IAAI,iBAAiB,GAAK,MACnD,CASO,SAASK,EAAqBL,EAAqC,CACxE,IAAMM,EAAUN,EAAQ,QACxB,MAAO,CACL,eAAgBM,EAAQ,IAAI,YAAY,EACxC,QAASA,EAAQ,IAAI,iBAAiB,EACtC,OAAQA,EAAQ,IAAI,QAAQ,EAC5B,QAASA,EAAQ,IAAI,SAAS,CAChC,CACF,CCzEA,OACE,iBAAAC,EACA,SAAAC,EACA,YAAAC,EACA,aAAAC,EACA,QAAAC,EACA,4BAAAC,EACA,YAAAC,EACA,kCAAAC,EACA,sCAAAC,EACA,mCAAAC,MACK","sourcesContent":["import {\n createCookieFactory,\n createCookieSessionStorageFactory,\n createMemorySessionStorageFactory,\n createSessionStorageFactory,\n} from '@remix-run/server-runtime';\n\nimport {sign, unsign} from './crypto';\n\nexport const createCookie = createCookieFactory({sign, unsign});\nexport const createCookieSessionStorage =\n createCookieSessionStorageFactory(createCookie);\nexport const createSessionStorage = createSessionStorageFactory(createCookie);\nexport const createMemorySessionStorage =\n createMemorySessionStorageFactory(createSessionStorage);\n","import type {SignFunction, UnsignFunction} from '@remix-run/server-runtime';\n\nconst encoder = new TextEncoder();\n\nexport const sign: SignFunction = async (value, secret) => {\n const key = await createKey(secret, ['sign']);\n const data = encoder.encode(value);\n const signature = await crypto.subtle.sign('HMAC', key, data);\n const hash = btoa(String.fromCharCode(...new Uint8Array(signature))).replace(\n /=+$/,\n '',\n );\n\n return value + '.' + hash;\n};\n\nexport const unsign: UnsignFunction = async (signed, secret) => {\n const index = signed.lastIndexOf('.');\n const value = signed.slice(0, index);\n const hash = signed.slice(index + 1);\n\n const key = await createKey(secret, ['verify']);\n const data = encoder.encode(value);\n const signature = byteStringToUint8Array(atob(hash));\n const valid = await crypto.subtle.verify('HMAC', key, signature, data);\n\n return valid ? value : false;\n};\n\nasync function createKey(\n secret: string,\n usages: CryptoKey['usages'],\n): Promise<CryptoKey> {\n const key = await crypto.subtle.importKey(\n 'raw',\n encoder.encode(secret),\n {name: 'HMAC', hash: 'SHA-256'},\n false,\n usages,\n );\n\n return key;\n}\n\nfunction byteStringToUint8Array(byteString: string): Uint8Array {\n const array = new Uint8Array(byteString.length);\n\n for (let i = 0; i < byteString.length; i++) {\n array[i] = byteString.charCodeAt(i);\n }\n\n return array;\n}\n","import {\n createRequestHandler as createRemixRequestHandler,\n type AppLoadContext,\n type ServerBuild,\n} from '@remix-run/server-runtime';\nimport {createEventLogger, type H2OEvent} from './event-logger';\n\ndeclare global {\n var __H2O_LOG_EVENT: undefined | ((event: H2OEvent) => void);\n}\n\nconst originalErrorToString = Error.prototype.toString;\nError.prototype.toString = function () {\n return this.stack || originalErrorToString.call(this);\n};\n\nexport function createRequestHandler<Context = unknown>({\n build,\n mode,\n poweredByHeader = true,\n getLoadContext,\n}: {\n build: ServerBuild;\n mode?: string;\n poweredByHeader?: boolean;\n getLoadContext?: (request: Request) => Promise<Context> | Context;\n}) {\n const handleRequest = createRemixRequestHandler(build, mode);\n\n return async (request: Request) => {\n const context = getLoadContext\n ? ((await getLoadContext(request)) as AppLoadContext)\n : undefined;\n\n if (process.env.NODE_ENV === 'development' && context) {\n // Store logger in globalThis so it can be accessed from the worker.\n // The global property must be different from the binding name,\n // otherwise Miniflare throws an error when accessing it.\n globalThis.__H2O_LOG_EVENT = createEventLogger(context);\n }\n\n const startTime = Date.now();\n\n const response = await handleRequest(request, context);\n\n if (process.env.NODE_ENV === 'development') {\n globalThis.__H2O_LOG_EVENT?.({\n eventType: 'request',\n url: request.url,\n requestId: request.headers.get('request-id'),\n purpose: request.headers.get('purpose'),\n startTime,\n });\n }\n\n if (poweredByHeader) {\n response.headers.append('powered-by', 'Shopify, Hydrogen');\n }\n\n return response;\n };\n}\n\nexport function getBuyerIp(request: Request) {\n return request.headers.get('oxygen-buyer-ip') ?? undefined;\n}\n\ntype StorefrontHeaders = {\n requestGroupId: string | null;\n buyerIp: string | null;\n cookie: string | null;\n purpose: string | null;\n};\n\nexport function getStorefrontHeaders(request: Request): StorefrontHeaders {\n const headers = request.headers;\n return {\n requestGroupId: headers.get('request-id'),\n buyerIp: headers.get('oxygen-buyer-ip'),\n cookie: headers.get('cookie'),\n purpose: headers.get('purpose'),\n };\n}\n","export {\n createCookie,\n createCookieSessionStorage,\n createMemorySessionStorage,\n createSessionStorage,\n} from './implementations';\n\nexport {createRequestHandler, getBuyerIp, getStorefrontHeaders} from './server';\n\nexport {\n createSession,\n defer,\n isCookie,\n isSession,\n json,\n MaxPartSizeExceededError,\n redirect,\n unstable_composeUploadHandlers,\n unstable_createMemoryUploadHandler,\n unstable_parseMultipartFormData,\n} from '@remix-run/server-runtime';\n\nexport type {\n ActionArgs,\n ActionFunction,\n AppData,\n AppLoadContext,\n Cookie,\n CookieOptions,\n CookieParseOptions,\n CookieSerializeOptions,\n CookieSignatureOptions,\n DataFunctionArgs,\n EntryContext,\n ErrorBoundaryComponent,\n HandleDataRequestFunction,\n HandleDocumentRequestFunction,\n HeadersFunction,\n HtmlLinkDescriptor,\n HtmlMetaDescriptor,\n LinkDescriptor,\n LinksFunction,\n LoaderArgs,\n LoaderFunction,\n MemoryUploadHandlerFilterArgs,\n MemoryUploadHandlerOptions,\n MetaDescriptor,\n MetaFunction,\n PageLinkDescriptor,\n RequestHandler,\n RouteComponent,\n RouteHandle,\n SerializeFrom,\n ServerBuild,\n ServerEntryModule,\n Session,\n SessionData,\n SessionIdStorageStrategy,\n SessionStorage,\n SignFunction,\n TypedResponse,\n UnsignFunction,\n UploadHandler,\n UploadHandlerPart,\n V2_ServerRuntimeMetaArgs as V2_MetaArgs,\n V2_ServerRuntimeMetaDescriptor as V2_MetaDescriptor,\n // TODO: Remove in Remix v2\n V2_ServerRuntimeMetaDescriptor as V2_HtmlMetaDescriptor,\n V2_ServerRuntimeMetaFunction as V2_MetaFunction,\n} from '@remix-run/server-runtime';\n"]}
@@ -32,6 +32,7 @@ type StorefrontHeaders = {
32
32
  requestGroupId: string | null;
33
33
  buyerIp: string | null;
34
34
  cookie: string | null;
35
+ purpose: string | null;
35
36
  };
36
37
  declare function getStorefrontHeaders(request: Request): StorefrontHeaders;
37
38
 
@@ -32,6 +32,7 @@ type StorefrontHeaders = {
32
32
  requestGroupId: string | null;
33
33
  buyerIp: string | null;
34
34
  cookie: string | null;
35
+ purpose: string | null;
35
36
  };
36
37
  declare function getStorefrontHeaders(request: Request): StorefrontHeaders;
37
38
 
@@ -1,7 +1,7 @@
1
1
  import { createCookieFactory, createCookieSessionStorageFactory, createSessionStorageFactory, createMemorySessionStorageFactory, createRequestHandler } from '@remix-run/server-runtime';
2
2
  export { MaxPartSizeExceededError, createSession, defer, isCookie, isSession, json, redirect, unstable_composeUploadHandlers, unstable_createMemoryUploadHandler, unstable_parseMultipartFormData } from '@remix-run/server-runtime';
3
3
 
4
- var c=new TextEncoder,d=async(e,t)=>{let r=await g(t,["sign"]),o=c.encode(e),s=await crypto.subtle.sign("HMAC",r,o),n=btoa(String.fromCharCode(...new Uint8Array(s))).replace(/=+$/,"");return e+"."+n},l=async(e,t)=>{let r=e.lastIndexOf("."),o=e.slice(0,r),s=e.slice(r+1),n=await g(t,["verify"]),a=c.encode(o),p=S(atob(s));return await crypto.subtle.verify("HMAC",n,p,a)?o:!1};async function g(e,t){return await crypto.subtle.importKey("raw",c.encode(e),{name:"HMAC",hash:"SHA-256"},!1,t)}function S(e){let t=new Uint8Array(e.length);for(let r=0;r<e.length;r++)t[r]=e.charCodeAt(r);return t}var u=createCookieFactory({sign:d,unsign:l}),C=createCookieSessionStorageFactory(u),y=createSessionStorageFactory(u),v=createMemorySessionStorageFactory(y);var _=Error.prototype.toString;Error.prototype.toString=function(){return this.stack||_.call(this)};function E({build:e,mode:t,poweredByHeader:r=!0,getLoadContext:o}){let s=createRequestHandler(e,t);return async n=>{let a=o?await o(n):void 0,i=await s(n,a);return r&&i.headers.append("powered-by","Shopify, Hydrogen"),i}}function F(e){return e.headers.get("oxygen-buyer-ip")??void 0}function M(e){let t=e.headers;return {requestGroupId:t.get("request-id"),buyerIp:t.get("oxygen-buyer-ip"),cookie:t.get("cookie")}}
4
+ var c=new TextEncoder,d=async(e,t)=>{let r=await g(t,["sign"]),o=c.encode(e),s=await crypto.subtle.sign("HMAC",r,o),n=btoa(String.fromCharCode(...new Uint8Array(s))).replace(/=+$/,"");return e+"."+n},l=async(e,t)=>{let r=e.lastIndexOf("."),o=e.slice(0,r),s=e.slice(r+1),n=await g(t,["verify"]),a=c.encode(o),p=S(atob(s));return await crypto.subtle.verify("HMAC",n,p,a)?o:!1};async function g(e,t){return await crypto.subtle.importKey("raw",c.encode(e),{name:"HMAC",hash:"SHA-256"},!1,t)}function S(e){let t=new Uint8Array(e.length);for(let r=0;r<e.length;r++)t[r]=e.charCodeAt(r);return t}var u=createCookieFactory({sign:d,unsign:l}),C=createCookieSessionStorageFactory(u),y=createSessionStorageFactory(u),v=createMemorySessionStorageFactory(y);var _=Error.prototype.toString;Error.prototype.toString=function(){return this.stack||_.call(this)};function E({build:e,mode:t,poweredByHeader:r=!0,getLoadContext:o}){let s=createRequestHandler(e,t);return async n=>{let a=o?await o(n):void 0,i=await s(n,a);return r&&i.headers.append("powered-by","Shopify, Hydrogen"),i}}function F(e){return e.headers.get("oxygen-buyer-ip")??void 0}function M(e){let t=e.headers;return {requestGroupId:t.get("request-id"),buyerIp:t.get("oxygen-buyer-ip"),cookie:t.get("cookie"),purpose:t.get("purpose")}}
5
5
 
6
6
  export { u as createCookie, C as createCookieSessionStorage, v as createMemorySessionStorage, E as createRequestHandler, y as createSessionStorage, F as getBuyerIp, M as getStorefrontHeaders };
7
7
  //# sourceMappingURL=out.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/implementations.ts","../../src/crypto.ts","../../src/server.ts","../../src/index.ts"],"names":["createCookieFactory","createCookieSessionStorageFactory","createMemorySessionStorageFactory","createSessionStorageFactory","encoder","sign","value","secret","key","createKey","data","signature","hash","unsign","signed","index","byteStringToUint8Array","usages","byteString","array","i","createCookie","createCookieSessionStorage","createSessionStorage","createMemorySessionStorage","createRemixRequestHandler","originalErrorToString","createRequestHandler","build","mode","poweredByHeader","getLoadContext","handleRequest","request","context","startTime","response","getBuyerIp","getStorefrontHeaders","headers","createSession","defer","isCookie","isSession","json","MaxPartSizeExceededError","redirect","unstable_composeUploadHandlers","unstable_createMemoryUploadHandler","unstable_parseMultipartFormData"],"mappings":"AAAA,OACE,uBAAAA,EACA,qCAAAC,EACA,qCAAAC,EACA,+BAAAC,MACK,4BCHP,IAAMC,EAAU,IAAI,YAEPC,EAAqB,MAAOC,EAAOC,IAAW,CACzD,IAAMC,EAAM,MAAMC,EAAUF,EAAQ,CAAC,MAAM,CAAC,EACtCG,EAAON,EAAQ,OAAOE,CAAK,EAC3BK,EAAY,MAAM,OAAO,OAAO,KAAK,OAAQH,EAAKE,CAAI,EACtDE,EAAO,KAAK,OAAO,aAAa,GAAG,IAAI,WAAWD,CAAS,CAAC,CAAC,EAAE,QACnE,MACA,EACF,EAEA,OAAOL,EAAQ,IAAMM,CACvB,EAEaC,EAAyB,MAAOC,EAAQP,IAAW,CAC9D,IAAMQ,EAAQD,EAAO,YAAY,GAAG,EAC9BR,EAAQQ,EAAO,MAAM,EAAGC,CAAK,EAC7BH,EAAOE,EAAO,MAAMC,EAAQ,CAAC,EAE7BP,EAAM,MAAMC,EAAUF,EAAQ,CAAC,QAAQ,CAAC,EACxCG,EAAON,EAAQ,OAAOE,CAAK,EAC3BK,EAAYK,EAAuB,KAAKJ,CAAI,CAAC,EAGnD,OAFc,MAAM,OAAO,OAAO,OAAO,OAAQJ,EAAKG,EAAWD,CAAI,EAEtDJ,EAAQ,EACzB,EAEA,eAAeG,EACbF,EACAU,EACoB,CASpB,OARY,MAAM,OAAO,OAAO,UAC9B,MACAb,EAAQ,OAAOG,CAAM,EACrB,CAAC,KAAM,OAAQ,KAAM,SAAS,EAC9B,GACAU,CACF,CAGF,CAEA,SAASD,EAAuBE,EAAgC,CAC9D,IAAMC,EAAQ,IAAI,WAAWD,EAAW,MAAM,EAE9C,QAASE,EAAI,EAAGA,EAAIF,EAAW,OAAQE,IACrCD,EAAMC,CAAC,EAAIF,EAAW,WAAWE,CAAC,EAGpC,OAAOD,CACT,CD3CO,IAAME,EAAerB,EAAoB,CAAC,KAAAK,EAAM,OAAAQ,CAAM,CAAC,EACjDS,EACXrB,EAAkCoB,CAAY,EACnCE,EAAuBpB,EAA4BkB,CAAY,EAC/DG,EACXtB,EAAkCqB,CAAoB,EEdxD,OACE,wBAAwBE,MAGnB,4BAOP,IAAMC,EAAwB,MAAM,UAAU,SAC9C,MAAM,UAAU,SAAW,UAAY,CACrC,OAAO,KAAK,OAASA,EAAsB,KAAK,IAAI,CACtD,EAEO,SAASC,EAAwC,CACtD,MAAAC,EACA,KAAAC,EACA,gBAAAC,EAAkB,GAClB,eAAAC,CACF,EAKG,CACD,IAAMC,EAAgBP,EAA0BG,EAAOC,CAAI,EAE3D,MAAO,OAAOI,GAAqB,CACjC,IAAMC,EAAUH,EACV,MAAMA,EAAeE,CAAO,EAC9B,OASEE,EAAY,KAAK,IAAI,EAErBC,EAAW,MAAMJ,EAAcC,EAASC,CAAO,EAYrD,OAAIJ,GACFM,EAAS,QAAQ,OAAO,aAAc,mBAAmB,EAGpDA,CACT,CACF,CAEO,SAASC,EAAWJ,EAAkB,CAC3C,OAAOA,EAAQ,QAAQ,IAAI,iBAAiB,GAAK,MACnD,CAQO,SAASK,EAAqBL,EAAqC,CACxE,IAAMM,EAAUN,EAAQ,QACxB,MAAO,CACL,eAAgBM,EAAQ,IAAI,YAAY,EACxC,QAASA,EAAQ,IAAI,iBAAiB,EACtC,OAAQA,EAAQ,IAAI,QAAQ,CAC9B,CACF,CCvEA,OACE,iBAAAC,EACA,SAAAC,EACA,YAAAC,EACA,aAAAC,EACA,QAAAC,EACA,4BAAAC,EACA,YAAAC,EACA,kCAAAC,EACA,sCAAAC,EACA,mCAAAC,MACK","sourcesContent":["import {\n createCookieFactory,\n createCookieSessionStorageFactory,\n createMemorySessionStorageFactory,\n createSessionStorageFactory,\n} from '@remix-run/server-runtime';\n\nimport {sign, unsign} from './crypto';\n\nexport const createCookie = createCookieFactory({sign, unsign});\nexport const createCookieSessionStorage =\n createCookieSessionStorageFactory(createCookie);\nexport const createSessionStorage = createSessionStorageFactory(createCookie);\nexport const createMemorySessionStorage =\n createMemorySessionStorageFactory(createSessionStorage);\n","import type {SignFunction, UnsignFunction} from '@remix-run/server-runtime';\n\nconst encoder = new TextEncoder();\n\nexport const sign: SignFunction = async (value, secret) => {\n const key = await createKey(secret, ['sign']);\n const data = encoder.encode(value);\n const signature = await crypto.subtle.sign('HMAC', key, data);\n const hash = btoa(String.fromCharCode(...new Uint8Array(signature))).replace(\n /=+$/,\n '',\n );\n\n return value + '.' + hash;\n};\n\nexport const unsign: UnsignFunction = async (signed, secret) => {\n const index = signed.lastIndexOf('.');\n const value = signed.slice(0, index);\n const hash = signed.slice(index + 1);\n\n const key = await createKey(secret, ['verify']);\n const data = encoder.encode(value);\n const signature = byteStringToUint8Array(atob(hash));\n const valid = await crypto.subtle.verify('HMAC', key, signature, data);\n\n return valid ? value : false;\n};\n\nasync function createKey(\n secret: string,\n usages: CryptoKey['usages'],\n): Promise<CryptoKey> {\n const key = await crypto.subtle.importKey(\n 'raw',\n encoder.encode(secret),\n {name: 'HMAC', hash: 'SHA-256'},\n false,\n usages,\n );\n\n return key;\n}\n\nfunction byteStringToUint8Array(byteString: string): Uint8Array {\n const array = new Uint8Array(byteString.length);\n\n for (let i = 0; i < byteString.length; i++) {\n array[i] = byteString.charCodeAt(i);\n }\n\n return array;\n}\n","import {\n createRequestHandler as createRemixRequestHandler,\n type AppLoadContext,\n type ServerBuild,\n} from '@remix-run/server-runtime';\nimport {createEventLogger, type H2OEvent} from './event-logger';\n\ndeclare global {\n var __H2O_LOG_EVENT: undefined | ((event: H2OEvent) => void);\n}\n\nconst originalErrorToString = Error.prototype.toString;\nError.prototype.toString = function () {\n return this.stack || originalErrorToString.call(this);\n};\n\nexport function createRequestHandler<Context = unknown>({\n build,\n mode,\n poweredByHeader = true,\n getLoadContext,\n}: {\n build: ServerBuild;\n mode?: string;\n poweredByHeader?: boolean;\n getLoadContext?: (request: Request) => Promise<Context> | Context;\n}) {\n const handleRequest = createRemixRequestHandler(build, mode);\n\n return async (request: Request) => {\n const context = getLoadContext\n ? ((await getLoadContext(request)) as AppLoadContext)\n : undefined;\n\n if (process.env.NODE_ENV === 'development' && context) {\n // Store logger in globalThis so it can be accessed from the worker.\n // The global property must be different from the binding name,\n // otherwise Miniflare throws an error when accessing it.\n globalThis.__H2O_LOG_EVENT = createEventLogger(context);\n }\n\n const startTime = Date.now();\n\n const response = await handleRequest(request, context);\n\n if (process.env.NODE_ENV === 'development') {\n globalThis.__H2O_LOG_EVENT?.({\n eventType: 'request',\n url: request.url,\n requestId: request.headers.get('request-id'),\n purpose: request.headers.get('purpose'),\n startTime,\n });\n }\n\n if (poweredByHeader) {\n response.headers.append('powered-by', 'Shopify, Hydrogen');\n }\n\n return response;\n };\n}\n\nexport function getBuyerIp(request: Request) {\n return request.headers.get('oxygen-buyer-ip') ?? undefined;\n}\n\ntype StorefrontHeaders = {\n requestGroupId: string | null;\n buyerIp: string | null;\n cookie: string | null;\n};\n\nexport function getStorefrontHeaders(request: Request): StorefrontHeaders {\n const headers = request.headers;\n return {\n requestGroupId: headers.get('request-id'),\n buyerIp: headers.get('oxygen-buyer-ip'),\n cookie: headers.get('cookie'),\n };\n}\n","export {\n createCookie,\n createCookieSessionStorage,\n createMemorySessionStorage,\n createSessionStorage,\n} from './implementations';\n\nexport {createRequestHandler, getBuyerIp, getStorefrontHeaders} from './server';\n\nexport {\n createSession,\n defer,\n isCookie,\n isSession,\n json,\n MaxPartSizeExceededError,\n redirect,\n unstable_composeUploadHandlers,\n unstable_createMemoryUploadHandler,\n unstable_parseMultipartFormData,\n} from '@remix-run/server-runtime';\n\nexport type {\n ActionArgs,\n ActionFunction,\n AppData,\n AppLoadContext,\n Cookie,\n CookieOptions,\n CookieParseOptions,\n CookieSerializeOptions,\n CookieSignatureOptions,\n DataFunctionArgs,\n EntryContext,\n ErrorBoundaryComponent,\n HandleDataRequestFunction,\n HandleDocumentRequestFunction,\n HeadersFunction,\n HtmlLinkDescriptor,\n HtmlMetaDescriptor,\n LinkDescriptor,\n LinksFunction,\n LoaderArgs,\n LoaderFunction,\n MemoryUploadHandlerFilterArgs,\n MemoryUploadHandlerOptions,\n MetaDescriptor,\n MetaFunction,\n PageLinkDescriptor,\n RequestHandler,\n RouteComponent,\n RouteHandle,\n SerializeFrom,\n ServerBuild,\n ServerEntryModule,\n Session,\n SessionData,\n SessionIdStorageStrategy,\n SessionStorage,\n SignFunction,\n TypedResponse,\n UnsignFunction,\n UploadHandler,\n UploadHandlerPart,\n V2_ServerRuntimeMetaArgs as V2_MetaArgs,\n V2_ServerRuntimeMetaDescriptor as V2_MetaDescriptor,\n // TODO: Remove in Remix v2\n V2_ServerRuntimeMetaDescriptor as V2_HtmlMetaDescriptor,\n V2_ServerRuntimeMetaFunction as V2_MetaFunction,\n} from '@remix-run/server-runtime';\n"]}
1
+ {"version":3,"sources":["../../src/implementations.ts","../../src/crypto.ts","../../src/server.ts","../../src/index.ts"],"names":["createCookieFactory","createCookieSessionStorageFactory","createMemorySessionStorageFactory","createSessionStorageFactory","encoder","sign","value","secret","key","createKey","data","signature","hash","unsign","signed","index","byteStringToUint8Array","usages","byteString","array","i","createCookie","createCookieSessionStorage","createSessionStorage","createMemorySessionStorage","createRemixRequestHandler","originalErrorToString","createRequestHandler","build","mode","poweredByHeader","getLoadContext","handleRequest","request","context","startTime","response","getBuyerIp","getStorefrontHeaders","headers","createSession","defer","isCookie","isSession","json","MaxPartSizeExceededError","redirect","unstable_composeUploadHandlers","unstable_createMemoryUploadHandler","unstable_parseMultipartFormData"],"mappings":"AAAA,OACE,uBAAAA,EACA,qCAAAC,EACA,qCAAAC,EACA,+BAAAC,MACK,4BCHP,IAAMC,EAAU,IAAI,YAEPC,EAAqB,MAAOC,EAAOC,IAAW,CACzD,IAAMC,EAAM,MAAMC,EAAUF,EAAQ,CAAC,MAAM,CAAC,EACtCG,EAAON,EAAQ,OAAOE,CAAK,EAC3BK,EAAY,MAAM,OAAO,OAAO,KAAK,OAAQH,EAAKE,CAAI,EACtDE,EAAO,KAAK,OAAO,aAAa,GAAG,IAAI,WAAWD,CAAS,CAAC,CAAC,EAAE,QACnE,MACA,EACF,EAEA,OAAOL,EAAQ,IAAMM,CACvB,EAEaC,EAAyB,MAAOC,EAAQP,IAAW,CAC9D,IAAMQ,EAAQD,EAAO,YAAY,GAAG,EAC9BR,EAAQQ,EAAO,MAAM,EAAGC,CAAK,EAC7BH,EAAOE,EAAO,MAAMC,EAAQ,CAAC,EAE7BP,EAAM,MAAMC,EAAUF,EAAQ,CAAC,QAAQ,CAAC,EACxCG,EAAON,EAAQ,OAAOE,CAAK,EAC3BK,EAAYK,EAAuB,KAAKJ,CAAI,CAAC,EAGnD,OAFc,MAAM,OAAO,OAAO,OAAO,OAAQJ,EAAKG,EAAWD,CAAI,EAEtDJ,EAAQ,EACzB,EAEA,eAAeG,EACbF,EACAU,EACoB,CASpB,OARY,MAAM,OAAO,OAAO,UAC9B,MACAb,EAAQ,OAAOG,CAAM,EACrB,CAAC,KAAM,OAAQ,KAAM,SAAS,EAC9B,GACAU,CACF,CAGF,CAEA,SAASD,EAAuBE,EAAgC,CAC9D,IAAMC,EAAQ,IAAI,WAAWD,EAAW,MAAM,EAE9C,QAASE,EAAI,EAAGA,EAAIF,EAAW,OAAQE,IACrCD,EAAMC,CAAC,EAAIF,EAAW,WAAWE,CAAC,EAGpC,OAAOD,CACT,CD3CO,IAAME,EAAerB,EAAoB,CAAC,KAAAK,EAAM,OAAAQ,CAAM,CAAC,EACjDS,EACXrB,EAAkCoB,CAAY,EACnCE,EAAuBpB,EAA4BkB,CAAY,EAC/DG,EACXtB,EAAkCqB,CAAoB,EEdxD,OACE,wBAAwBE,MAGnB,4BAOP,IAAMC,EAAwB,MAAM,UAAU,SAC9C,MAAM,UAAU,SAAW,UAAY,CACrC,OAAO,KAAK,OAASA,EAAsB,KAAK,IAAI,CACtD,EAEO,SAASC,EAAwC,CACtD,MAAAC,EACA,KAAAC,EACA,gBAAAC,EAAkB,GAClB,eAAAC,CACF,EAKG,CACD,IAAMC,EAAgBP,EAA0BG,EAAOC,CAAI,EAE3D,MAAO,OAAOI,GAAqB,CACjC,IAAMC,EAAUH,EACV,MAAMA,EAAeE,CAAO,EAC9B,OASEE,EAAY,KAAK,IAAI,EAErBC,EAAW,MAAMJ,EAAcC,EAASC,CAAO,EAYrD,OAAIJ,GACFM,EAAS,QAAQ,OAAO,aAAc,mBAAmB,EAGpDA,CACT,CACF,CAEO,SAASC,EAAWJ,EAAkB,CAC3C,OAAOA,EAAQ,QAAQ,IAAI,iBAAiB,GAAK,MACnD,CASO,SAASK,EAAqBL,EAAqC,CACxE,IAAMM,EAAUN,EAAQ,QACxB,MAAO,CACL,eAAgBM,EAAQ,IAAI,YAAY,EACxC,QAASA,EAAQ,IAAI,iBAAiB,EACtC,OAAQA,EAAQ,IAAI,QAAQ,EAC5B,QAASA,EAAQ,IAAI,SAAS,CAChC,CACF,CCzEA,OACE,iBAAAC,EACA,SAAAC,EACA,YAAAC,EACA,aAAAC,EACA,QAAAC,EACA,4BAAAC,EACA,YAAAC,EACA,kCAAAC,EACA,sCAAAC,EACA,mCAAAC,MACK","sourcesContent":["import {\n createCookieFactory,\n createCookieSessionStorageFactory,\n createMemorySessionStorageFactory,\n createSessionStorageFactory,\n} from '@remix-run/server-runtime';\n\nimport {sign, unsign} from './crypto';\n\nexport const createCookie = createCookieFactory({sign, unsign});\nexport const createCookieSessionStorage =\n createCookieSessionStorageFactory(createCookie);\nexport const createSessionStorage = createSessionStorageFactory(createCookie);\nexport const createMemorySessionStorage =\n createMemorySessionStorageFactory(createSessionStorage);\n","import type {SignFunction, UnsignFunction} from '@remix-run/server-runtime';\n\nconst encoder = new TextEncoder();\n\nexport const sign: SignFunction = async (value, secret) => {\n const key = await createKey(secret, ['sign']);\n const data = encoder.encode(value);\n const signature = await crypto.subtle.sign('HMAC', key, data);\n const hash = btoa(String.fromCharCode(...new Uint8Array(signature))).replace(\n /=+$/,\n '',\n );\n\n return value + '.' + hash;\n};\n\nexport const unsign: UnsignFunction = async (signed, secret) => {\n const index = signed.lastIndexOf('.');\n const value = signed.slice(0, index);\n const hash = signed.slice(index + 1);\n\n const key = await createKey(secret, ['verify']);\n const data = encoder.encode(value);\n const signature = byteStringToUint8Array(atob(hash));\n const valid = await crypto.subtle.verify('HMAC', key, signature, data);\n\n return valid ? value : false;\n};\n\nasync function createKey(\n secret: string,\n usages: CryptoKey['usages'],\n): Promise<CryptoKey> {\n const key = await crypto.subtle.importKey(\n 'raw',\n encoder.encode(secret),\n {name: 'HMAC', hash: 'SHA-256'},\n false,\n usages,\n );\n\n return key;\n}\n\nfunction byteStringToUint8Array(byteString: string): Uint8Array {\n const array = new Uint8Array(byteString.length);\n\n for (let i = 0; i < byteString.length; i++) {\n array[i] = byteString.charCodeAt(i);\n }\n\n return array;\n}\n","import {\n createRequestHandler as createRemixRequestHandler,\n type AppLoadContext,\n type ServerBuild,\n} from '@remix-run/server-runtime';\nimport {createEventLogger, type H2OEvent} from './event-logger';\n\ndeclare global {\n var __H2O_LOG_EVENT: undefined | ((event: H2OEvent) => void);\n}\n\nconst originalErrorToString = Error.prototype.toString;\nError.prototype.toString = function () {\n return this.stack || originalErrorToString.call(this);\n};\n\nexport function createRequestHandler<Context = unknown>({\n build,\n mode,\n poweredByHeader = true,\n getLoadContext,\n}: {\n build: ServerBuild;\n mode?: string;\n poweredByHeader?: boolean;\n getLoadContext?: (request: Request) => Promise<Context> | Context;\n}) {\n const handleRequest = createRemixRequestHandler(build, mode);\n\n return async (request: Request) => {\n const context = getLoadContext\n ? ((await getLoadContext(request)) as AppLoadContext)\n : undefined;\n\n if (process.env.NODE_ENV === 'development' && context) {\n // Store logger in globalThis so it can be accessed from the worker.\n // The global property must be different from the binding name,\n // otherwise Miniflare throws an error when accessing it.\n globalThis.__H2O_LOG_EVENT = createEventLogger(context);\n }\n\n const startTime = Date.now();\n\n const response = await handleRequest(request, context);\n\n if (process.env.NODE_ENV === 'development') {\n globalThis.__H2O_LOG_EVENT?.({\n eventType: 'request',\n url: request.url,\n requestId: request.headers.get('request-id'),\n purpose: request.headers.get('purpose'),\n startTime,\n });\n }\n\n if (poweredByHeader) {\n response.headers.append('powered-by', 'Shopify, Hydrogen');\n }\n\n return response;\n };\n}\n\nexport function getBuyerIp(request: Request) {\n return request.headers.get('oxygen-buyer-ip') ?? undefined;\n}\n\ntype StorefrontHeaders = {\n requestGroupId: string | null;\n buyerIp: string | null;\n cookie: string | null;\n purpose: string | null;\n};\n\nexport function getStorefrontHeaders(request: Request): StorefrontHeaders {\n const headers = request.headers;\n return {\n requestGroupId: headers.get('request-id'),\n buyerIp: headers.get('oxygen-buyer-ip'),\n cookie: headers.get('cookie'),\n purpose: headers.get('purpose'),\n };\n}\n","export {\n createCookie,\n createCookieSessionStorage,\n createMemorySessionStorage,\n createSessionStorage,\n} from './implementations';\n\nexport {createRequestHandler, getBuyerIp, getStorefrontHeaders} from './server';\n\nexport {\n createSession,\n defer,\n isCookie,\n isSession,\n json,\n MaxPartSizeExceededError,\n redirect,\n unstable_composeUploadHandlers,\n unstable_createMemoryUploadHandler,\n unstable_parseMultipartFormData,\n} from '@remix-run/server-runtime';\n\nexport type {\n ActionArgs,\n ActionFunction,\n AppData,\n AppLoadContext,\n Cookie,\n CookieOptions,\n CookieParseOptions,\n CookieSerializeOptions,\n CookieSignatureOptions,\n DataFunctionArgs,\n EntryContext,\n ErrorBoundaryComponent,\n HandleDataRequestFunction,\n HandleDocumentRequestFunction,\n HeadersFunction,\n HtmlLinkDescriptor,\n HtmlMetaDescriptor,\n LinkDescriptor,\n LinksFunction,\n LoaderArgs,\n LoaderFunction,\n MemoryUploadHandlerFilterArgs,\n MemoryUploadHandlerOptions,\n MetaDescriptor,\n MetaFunction,\n PageLinkDescriptor,\n RequestHandler,\n RouteComponent,\n RouteHandle,\n SerializeFrom,\n ServerBuild,\n ServerEntryModule,\n Session,\n SessionData,\n SessionIdStorageStrategy,\n SessionStorage,\n SignFunction,\n TypedResponse,\n UnsignFunction,\n UploadHandler,\n UploadHandlerPart,\n V2_ServerRuntimeMetaArgs as V2_MetaArgs,\n V2_ServerRuntimeMetaDescriptor as V2_MetaDescriptor,\n // TODO: Remove in Remix v2\n V2_ServerRuntimeMetaDescriptor as V2_HtmlMetaDescriptor,\n V2_ServerRuntimeMetaFunction as V2_MetaFunction,\n} from '@remix-run/server-runtime';\n"]}
package/package.json CHANGED
@@ -5,7 +5,7 @@
5
5
  "@shopify:registry": "https://registry.npmjs.org"
6
6
  },
7
7
  "type": "module",
8
- "version": "1.1.7",
8
+ "version": "1.1.8",
9
9
  "license": "MIT",
10
10
  "main": "dist/index.cjs",
11
11
  "module": "dist/production/index.js",