@shopify/remix-oxygen 1.1.2 → 1.1.4
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/dist/development/index.cjs +51 -4
- package/dist/development/index.cjs.map +1 -1
- package/dist/development/index.js +51 -4
- package/dist/development/index.js.map +1 -1
- package/dist/production/index.cjs +8 -8
- package/dist/production/index.cjs.map +1 -1
- package/dist/production/index.d.cts +38 -0
- package/dist/production/index.d.ts +14 -0
- package/dist/production/index.js +2 -2
- package/dist/production/index.js.map +1 -1
- package/package.json +5 -5
|
@@ -49,6 +49,42 @@ var createCookie = serverRuntime.createCookieFactory({ sign, unsign });
|
|
|
49
49
|
var createCookieSessionStorage = serverRuntime.createCookieSessionStorageFactory(createCookie);
|
|
50
50
|
var createSessionStorage = serverRuntime.createSessionStorageFactory(createCookie);
|
|
51
51
|
var createMemorySessionStorage = serverRuntime.createMemorySessionStorageFactory(createSessionStorage);
|
|
52
|
+
|
|
53
|
+
// src/event-logger.ts
|
|
54
|
+
function createEventLogger(appLoadContext) {
|
|
55
|
+
const context = appLoadContext || {};
|
|
56
|
+
const eventLoggerService = context?.env?.H2O_LOG_EVENT;
|
|
57
|
+
if (typeof eventLoggerService?.fetch !== "function")
|
|
58
|
+
return;
|
|
59
|
+
return ({
|
|
60
|
+
url,
|
|
61
|
+
eventType,
|
|
62
|
+
requestId,
|
|
63
|
+
purpose,
|
|
64
|
+
startTime,
|
|
65
|
+
endTime,
|
|
66
|
+
cacheStatus,
|
|
67
|
+
waitUntil = context?.waitUntil
|
|
68
|
+
}) => {
|
|
69
|
+
const promise = eventLoggerService.fetch(
|
|
70
|
+
new Request(url, {
|
|
71
|
+
headers: {
|
|
72
|
+
purpose: purpose || "",
|
|
73
|
+
"request-id": requestId || "",
|
|
74
|
+
"hydrogen-event-type": eventType,
|
|
75
|
+
"hydrogen-start-time": String(startTime),
|
|
76
|
+
"hydrogen-end-time": String(endTime || Date.now()),
|
|
77
|
+
"hydrogen-cache-status": cacheStatus || ""
|
|
78
|
+
}
|
|
79
|
+
})
|
|
80
|
+
).catch((error) => {
|
|
81
|
+
console.debug("Failed to log H2O event\n", error.stack);
|
|
82
|
+
});
|
|
83
|
+
promise && waitUntil?.(promise);
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
// src/server.ts
|
|
52
88
|
function createRequestHandler({
|
|
53
89
|
build,
|
|
54
90
|
mode,
|
|
@@ -57,10 +93,21 @@ function createRequestHandler({
|
|
|
57
93
|
}) {
|
|
58
94
|
const handleRequest = serverRuntime.createRequestHandler(build, mode);
|
|
59
95
|
return async (request) => {
|
|
60
|
-
const
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
96
|
+
const context = getLoadContext ? await getLoadContext(request) : void 0;
|
|
97
|
+
if (context) {
|
|
98
|
+
globalThis.__H2O_LOG_EVENT = createEventLogger(context);
|
|
99
|
+
}
|
|
100
|
+
const startTime = Date.now();
|
|
101
|
+
const response = await handleRequest(request, context);
|
|
102
|
+
{
|
|
103
|
+
globalThis.__H2O_LOG_EVENT?.({
|
|
104
|
+
eventType: "request",
|
|
105
|
+
url: request.url,
|
|
106
|
+
requestId: request.headers.get("request-id"),
|
|
107
|
+
purpose: request.headers.get("purpose"),
|
|
108
|
+
startTime
|
|
109
|
+
});
|
|
110
|
+
}
|
|
64
111
|
if (poweredByHeader) {
|
|
65
112
|
response.headers.append("powered-by", "Shopify, Hydrogen");
|
|
66
113
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/implementations.ts","../../src/crypto.ts","../../src/server.ts","../../src/index.ts"],"names":[],"mappings":";AAAA;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;;;ACHP,IAAM,UAAU,IAAI,YAAY;AAEzB,IAAM,OAAqB,OAAO,OAAO,WAAW;AACzD,QAAM,MAAM,MAAM,UAAU,QAAQ,CAAC,MAAM,CAAC;AAC5C,QAAM,OAAO,QAAQ,OAAO,KAAK;AACjC,QAAM,YAAY,MAAM,OAAO,OAAO,KAAK,QAAQ,KAAK,IAAI;AAC5D,QAAM,OAAO,KAAK,OAAO,aAAa,GAAG,IAAI,WAAW,SAAS,CAAC,CAAC,EAAE;AAAA,IACnE;AAAA,IACA;AAAA,EACF;AAEA,SAAO,QAAQ,MAAM;AACvB;AAEO,IAAM,SAAyB,OAAO,QAAQ,WAAW;AAC9D,QAAM,QAAQ,OAAO,YAAY,GAAG;AACpC,QAAM,QAAQ,OAAO,MAAM,GAAG,KAAK;AACnC,QAAM,OAAO,OAAO,MAAM,QAAQ,CAAC;AAEnC,QAAM,MAAM,MAAM,UAAU,QAAQ,CAAC,QAAQ,CAAC;AAC9C,QAAM,OAAO,QAAQ,OAAO,KAAK;AACjC,QAAM,YAAY,uBAAuB,KAAK,IAAI,CAAC;AACnD,QAAM,QAAQ,MAAM,OAAO,OAAO,OAAO,QAAQ,KAAK,WAAW,IAAI;AAErE,SAAO,QAAQ,QAAQ;AACzB;AAEA,eAAe,UACb,QACA,QACoB;AACpB,QAAM,MAAM,MAAM,OAAO,OAAO;AAAA,IAC9B;AAAA,IACA,QAAQ,OAAO,MAAM;AAAA,IACrB,EAAC,MAAM,QAAQ,MAAM,UAAS;AAAA,IAC9B;AAAA,IACA;AAAA,EACF;AAEA,SAAO;AACT;AAEA,SAAS,uBAAuB,YAAgC;AAC9D,QAAM,QAAQ,IAAI,WAAW,WAAW,MAAM;AAE9C,WAAS,IAAI,GAAG,IAAI,WAAW,QAAQ,KAAK;AAC1C,UAAM,KAAK,WAAW,WAAW,CAAC;AAAA,EACpC;AAEA,SAAO;AACT;;;AD3CO,IAAM,eAAe,oBAAoB,EAAC,MAAM,OAAM,CAAC;AACvD,IAAM,6BACX,kCAAkC,YAAY;AACzC,IAAM,uBAAuB,4BAA4B,YAAY;AACrE,IAAM,6BACX,kCAAkC,oBAAoB;;;AEdxD;AAAA,EACE,wBAAwB;AAAA,OAGnB;AAEA,SAAS,qBAAwC;AAAA,EACtD;AAAA,EACA;AAAA,EACA,kBAAkB;AAAA,EAClB;AACF,GAKG;AACD,QAAM,gBAAgB,0BAA0B,OAAO,IAAI;AAE3D,SAAO,OAAO,YAAqB;AACjC,UAAM,WAAW,MAAM;AAAA,MACrB;AAAA,MACC,MAAM,iBAAiB,OAAO;AAAA,IACjC;AAEA,QAAI,iBAAiB;AACnB,eAAS,QAAQ,OAAO,cAAc,mBAAmB;AAAA,IAC3D;AAEA,WAAO;AAAA,EACT;AACF;AAEO,SAAS,WAAW,SAAkB;AAC3C,SAAO,QAAQ,QAAQ,IAAI,iBAAiB,KAAK;AACnD;AAQO,SAAS,qBAAqB,SAAqC;AACxE,QAAM,UAAU,QAAQ;AACxB,SAAO;AAAA,IACL,gBAAgB,QAAQ,IAAI,YAAY;AAAA,IACxC,SAAS,QAAQ,IAAI,iBAAiB;AAAA,IACtC,QAAQ,QAAQ,IAAI,QAAQ;AAAA,EAC9B;AACF;;;ACzCA;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK","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';\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 response = await handleRequest(\n request,\n (await getLoadContext?.(request)) as AppLoadContext,\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/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\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\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 eventType,\n requestId,\n purpose,\n startTime,\n endTime,\n cacheStatus,\n waitUntil = context?.waitUntil,\n }: H2OEvent) => {\n const promise = eventLoggerService\n .fetch(\n new Request(url, {\n headers: {\n purpose: purpose || '',\n 'request-id': requestId || '',\n 'hydrogen-event-type': eventType,\n 'hydrogen-start-time': String(startTime),\n 'hydrogen-end-time': String(endTime || Date.now()),\n 'hydrogen-cache-status': cacheStatus || '',\n },\n }),\n )\n .catch((error: Error) => {\n console.debug('Failed to log H2O event\\n', error.stack);\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"]}
|
|
@@ -48,6 +48,42 @@ var createCookie = createCookieFactory({ sign, unsign });
|
|
|
48
48
|
var createCookieSessionStorage = createCookieSessionStorageFactory(createCookie);
|
|
49
49
|
var createSessionStorage = createSessionStorageFactory(createCookie);
|
|
50
50
|
var createMemorySessionStorage = createMemorySessionStorageFactory(createSessionStorage);
|
|
51
|
+
|
|
52
|
+
// src/event-logger.ts
|
|
53
|
+
function createEventLogger(appLoadContext) {
|
|
54
|
+
const context = appLoadContext || {};
|
|
55
|
+
const eventLoggerService = context?.env?.H2O_LOG_EVENT;
|
|
56
|
+
if (typeof eventLoggerService?.fetch !== "function")
|
|
57
|
+
return;
|
|
58
|
+
return ({
|
|
59
|
+
url,
|
|
60
|
+
eventType,
|
|
61
|
+
requestId,
|
|
62
|
+
purpose,
|
|
63
|
+
startTime,
|
|
64
|
+
endTime,
|
|
65
|
+
cacheStatus,
|
|
66
|
+
waitUntil = context?.waitUntil
|
|
67
|
+
}) => {
|
|
68
|
+
const promise = eventLoggerService.fetch(
|
|
69
|
+
new Request(url, {
|
|
70
|
+
headers: {
|
|
71
|
+
purpose: purpose || "",
|
|
72
|
+
"request-id": requestId || "",
|
|
73
|
+
"hydrogen-event-type": eventType,
|
|
74
|
+
"hydrogen-start-time": String(startTime),
|
|
75
|
+
"hydrogen-end-time": String(endTime || Date.now()),
|
|
76
|
+
"hydrogen-cache-status": cacheStatus || ""
|
|
77
|
+
}
|
|
78
|
+
})
|
|
79
|
+
).catch((error) => {
|
|
80
|
+
console.debug("Failed to log H2O event\n", error.stack);
|
|
81
|
+
});
|
|
82
|
+
promise && waitUntil?.(promise);
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
// src/server.ts
|
|
51
87
|
function createRequestHandler({
|
|
52
88
|
build,
|
|
53
89
|
mode,
|
|
@@ -56,10 +92,21 @@ function createRequestHandler({
|
|
|
56
92
|
}) {
|
|
57
93
|
const handleRequest = createRequestHandler$1(build, mode);
|
|
58
94
|
return async (request) => {
|
|
59
|
-
const
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
95
|
+
const context = getLoadContext ? await getLoadContext(request) : void 0;
|
|
96
|
+
if (context) {
|
|
97
|
+
globalThis.__H2O_LOG_EVENT = createEventLogger(context);
|
|
98
|
+
}
|
|
99
|
+
const startTime = Date.now();
|
|
100
|
+
const response = await handleRequest(request, context);
|
|
101
|
+
{
|
|
102
|
+
globalThis.__H2O_LOG_EVENT?.({
|
|
103
|
+
eventType: "request",
|
|
104
|
+
url: request.url,
|
|
105
|
+
requestId: request.headers.get("request-id"),
|
|
106
|
+
purpose: request.headers.get("purpose"),
|
|
107
|
+
startTime
|
|
108
|
+
});
|
|
109
|
+
}
|
|
63
110
|
if (poweredByHeader) {
|
|
64
111
|
response.headers.append("powered-by", "Shopify, Hydrogen");
|
|
65
112
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/implementations.ts","../../src/crypto.ts","../../src/server.ts","../../src/index.ts"],"names":[],"mappings":";AAAA;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;;;ACHP,IAAM,UAAU,IAAI,YAAY;AAEzB,IAAM,OAAqB,OAAO,OAAO,WAAW;AACzD,QAAM,MAAM,MAAM,UAAU,QAAQ,CAAC,MAAM,CAAC;AAC5C,QAAM,OAAO,QAAQ,OAAO,KAAK;AACjC,QAAM,YAAY,MAAM,OAAO,OAAO,KAAK,QAAQ,KAAK,IAAI;AAC5D,QAAM,OAAO,KAAK,OAAO,aAAa,GAAG,IAAI,WAAW,SAAS,CAAC,CAAC,EAAE;AAAA,IACnE;AAAA,IACA;AAAA,EACF;AAEA,SAAO,QAAQ,MAAM;AACvB;AAEO,IAAM,SAAyB,OAAO,QAAQ,WAAW;AAC9D,QAAM,QAAQ,OAAO,YAAY,GAAG;AACpC,QAAM,QAAQ,OAAO,MAAM,GAAG,KAAK;AACnC,QAAM,OAAO,OAAO,MAAM,QAAQ,CAAC;AAEnC,QAAM,MAAM,MAAM,UAAU,QAAQ,CAAC,QAAQ,CAAC;AAC9C,QAAM,OAAO,QAAQ,OAAO,KAAK;AACjC,QAAM,YAAY,uBAAuB,KAAK,IAAI,CAAC;AACnD,QAAM,QAAQ,MAAM,OAAO,OAAO,OAAO,QAAQ,KAAK,WAAW,IAAI;AAErE,SAAO,QAAQ,QAAQ;AACzB;AAEA,eAAe,UACb,QACA,QACoB;AACpB,QAAM,MAAM,MAAM,OAAO,OAAO;AAAA,IAC9B;AAAA,IACA,QAAQ,OAAO,MAAM;AAAA,IACrB,EAAC,MAAM,QAAQ,MAAM,UAAS;AAAA,IAC9B;AAAA,IACA;AAAA,EACF;AAEA,SAAO;AACT;AAEA,SAAS,uBAAuB,YAAgC;AAC9D,QAAM,QAAQ,IAAI,WAAW,WAAW,MAAM;AAE9C,WAAS,IAAI,GAAG,IAAI,WAAW,QAAQ,KAAK;AAC1C,UAAM,KAAK,WAAW,WAAW,CAAC;AAAA,EACpC;AAEA,SAAO;AACT;;;AD3CO,IAAM,eAAe,oBAAoB,EAAC,MAAM,OAAM,CAAC;AACvD,IAAM,6BACX,kCAAkC,YAAY;AACzC,IAAM,uBAAuB,4BAA4B,YAAY;AACrE,IAAM,6BACX,kCAAkC,oBAAoB;;;AEdxD;AAAA,EACE,wBAAwB;AAAA,OAGnB;AAEA,SAAS,qBAAwC;AAAA,EACtD;AAAA,EACA;AAAA,EACA,kBAAkB;AAAA,EAClB;AACF,GAKG;AACD,QAAM,gBAAgB,0BAA0B,OAAO,IAAI;AAE3D,SAAO,OAAO,YAAqB;AACjC,UAAM,WAAW,MAAM;AAAA,MACrB;AAAA,MACC,MAAM,iBAAiB,OAAO;AAAA,IACjC;AAEA,QAAI,iBAAiB;AACnB,eAAS,QAAQ,OAAO,cAAc,mBAAmB;AAAA,IAC3D;AAEA,WAAO;AAAA,EACT;AACF;AAEO,SAAS,WAAW,SAAkB;AAC3C,SAAO,QAAQ,QAAQ,IAAI,iBAAiB,KAAK;AACnD;AAQO,SAAS,qBAAqB,SAAqC;AACxE,QAAM,UAAU,QAAQ;AACxB,SAAO;AAAA,IACL,gBAAgB,QAAQ,IAAI,YAAY;AAAA,IACxC,SAAS,QAAQ,IAAI,iBAAiB;AAAA,IACtC,QAAQ,QAAQ,IAAI,QAAQ;AAAA,EAC9B;AACF;;;ACzCA;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK","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';\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 response = await handleRequest(\n request,\n (await getLoadContext?.(request)) as AppLoadContext,\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/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\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\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 eventType,\n requestId,\n purpose,\n startTime,\n endTime,\n cacheStatus,\n waitUntil = context?.waitUntil,\n }: H2OEvent) => {\n const promise = eventLoggerService\n .fetch(\n new Request(url, {\n headers: {\n purpose: purpose || '',\n 'request-id': requestId || '',\n 'hydrogen-event-type': eventType,\n 'hydrogen-start-time': String(startTime),\n 'hydrogen-end-time': String(endTime || Date.now()),\n 'hydrogen-cache-status': cacheStatus || '',\n },\n }),\n )\n .catch((error: Error) => {\n console.debug('Failed to log H2O event\\n', error.stack);\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
|
|
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=m(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 m(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);function k({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")}}
|
|
6
6
|
|
|
7
7
|
Object.defineProperty(exports, 'MaxPartSizeExceededError', {
|
|
8
8
|
enumerable: true,
|
|
@@ -44,12 +44,12 @@ Object.defineProperty(exports, 'unstable_parseMultipartFormData', {
|
|
|
44
44
|
enumerable: true,
|
|
45
45
|
get: function () { return serverRuntime.unstable_parseMultipartFormData; }
|
|
46
46
|
});
|
|
47
|
-
exports.createCookie =
|
|
48
|
-
exports.createCookieSessionStorage =
|
|
49
|
-
exports.createMemorySessionStorage =
|
|
50
|
-
exports.createRequestHandler =
|
|
51
|
-
exports.createSessionStorage =
|
|
52
|
-
exports.getBuyerIp =
|
|
53
|
-
exports.getStorefrontHeaders =
|
|
47
|
+
exports.createCookie = u;
|
|
48
|
+
exports.createCookieSessionStorage = C;
|
|
49
|
+
exports.createMemorySessionStorage = v;
|
|
50
|
+
exports.createRequestHandler = k;
|
|
51
|
+
exports.createSessionStorage = y;
|
|
52
|
+
exports.getBuyerIp = F;
|
|
53
|
+
exports.getStorefrontHeaders = M;
|
|
54
54
|
//# sourceMappingURL=out.js.map
|
|
55
55
|
//# sourceMappingURL=index.cjs.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","createRequestHandler","build","mode","poweredByHeader","getLoadContext","handleRequest","request","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,
|
|
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","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,4BAOA,SAASC,EAAwC,CACtD,MAAAC,EACA,KAAAC,EACA,gBAAAC,EAAkB,GAClB,eAAAC,CACF,EAKG,CACD,IAAMC,EAAgBN,EAA0BE,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,CClEA,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\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"]}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import * as _remix_run_server_runtime from '@remix-run/server-runtime';
|
|
2
|
+
import { ServerBuild } from '@remix-run/server-runtime';
|
|
3
|
+
export { ActionArgs, ActionFunction, AppData, AppLoadContext, Cookie, CookieOptions, CookieParseOptions, CookieSerializeOptions, CookieSignatureOptions, DataFunctionArgs, EntryContext, ErrorBoundaryComponent, HandleDataRequestFunction, HandleDocumentRequestFunction, HeadersFunction, HtmlLinkDescriptor, HtmlMetaDescriptor, LinkDescriptor, LinksFunction, LoaderArgs, LoaderFunction, MaxPartSizeExceededError, MemoryUploadHandlerFilterArgs, MemoryUploadHandlerOptions, MetaDescriptor, MetaFunction, PageLinkDescriptor, RequestHandler, RouteComponent, RouteHandle, SerializeFrom, ServerBuild, ServerEntryModule, Session, SessionData, SessionIdStorageStrategy, SessionStorage, SignFunction, TypedResponse, UnsignFunction, UploadHandler, UploadHandlerPart, V2_ServerRuntimeMetaDescriptor as V2_HtmlMetaDescriptor, V2_ServerRuntimeMetaArgs as V2_MetaArgs, V2_ServerRuntimeMetaDescriptor as V2_MetaDescriptor, V2_ServerRuntimeMetaFunction as V2_MetaFunction, createSession, defer, isCookie, isSession, json, redirect, unstable_composeUploadHandlers, unstable_createMemoryUploadHandler, unstable_parseMultipartFormData } from '@remix-run/server-runtime';
|
|
4
|
+
|
|
5
|
+
declare const createCookie: _remix_run_server_runtime.CreateCookieFunction;
|
|
6
|
+
declare const createCookieSessionStorage: _remix_run_server_runtime.CreateCookieSessionStorageFunction;
|
|
7
|
+
declare const createSessionStorage: _remix_run_server_runtime.CreateSessionStorageFunction;
|
|
8
|
+
declare const createMemorySessionStorage: _remix_run_server_runtime.CreateMemorySessionStorageFunction;
|
|
9
|
+
|
|
10
|
+
type H2OEvent = {
|
|
11
|
+
url: string;
|
|
12
|
+
eventType: 'request' | 'subrequest';
|
|
13
|
+
requestId?: string | null;
|
|
14
|
+
purpose?: string | null;
|
|
15
|
+
startTime: number;
|
|
16
|
+
endTime?: number;
|
|
17
|
+
cacheStatus?: 'MISS' | 'HIT' | 'STALE' | 'PUT';
|
|
18
|
+
waitUntil?: ExecutionContext['waitUntil'];
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
declare global {
|
|
22
|
+
var __H2O_LOG_EVENT: undefined | ((event: H2OEvent) => void);
|
|
23
|
+
}
|
|
24
|
+
declare function createRequestHandler<Context = unknown>({ build, mode, poweredByHeader, getLoadContext, }: {
|
|
25
|
+
build: ServerBuild;
|
|
26
|
+
mode?: string;
|
|
27
|
+
poweredByHeader?: boolean;
|
|
28
|
+
getLoadContext?: (request: Request) => Promise<Context> | Context;
|
|
29
|
+
}): (request: Request) => Promise<Response>;
|
|
30
|
+
declare function getBuyerIp(request: Request): string | undefined;
|
|
31
|
+
type StorefrontHeaders = {
|
|
32
|
+
requestGroupId: string | null;
|
|
33
|
+
buyerIp: string | null;
|
|
34
|
+
cookie: string | null;
|
|
35
|
+
};
|
|
36
|
+
declare function getStorefrontHeaders(request: Request): StorefrontHeaders;
|
|
37
|
+
|
|
38
|
+
export { createCookie, createCookieSessionStorage, createMemorySessionStorage, createRequestHandler, createSessionStorage, getBuyerIp, getStorefrontHeaders };
|
|
@@ -7,6 +7,20 @@ declare const createCookieSessionStorage: _remix_run_server_runtime.CreateCookie
|
|
|
7
7
|
declare const createSessionStorage: _remix_run_server_runtime.CreateSessionStorageFunction;
|
|
8
8
|
declare const createMemorySessionStorage: _remix_run_server_runtime.CreateMemorySessionStorageFunction;
|
|
9
9
|
|
|
10
|
+
type H2OEvent = {
|
|
11
|
+
url: string;
|
|
12
|
+
eventType: 'request' | 'subrequest';
|
|
13
|
+
requestId?: string | null;
|
|
14
|
+
purpose?: string | null;
|
|
15
|
+
startTime: number;
|
|
16
|
+
endTime?: number;
|
|
17
|
+
cacheStatus?: 'MISS' | 'HIT' | 'STALE' | 'PUT';
|
|
18
|
+
waitUntil?: ExecutionContext['waitUntil'];
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
declare global {
|
|
22
|
+
var __H2O_LOG_EVENT: undefined | ((event: H2OEvent) => void);
|
|
23
|
+
}
|
|
10
24
|
declare function createRequestHandler<Context = unknown>({ build, mode, poweredByHeader, getLoadContext, }: {
|
|
11
25
|
build: ServerBuild;
|
|
12
26
|
mode?: string;
|
package/dist/production/index.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
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
|
|
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=m(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 m(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);function k({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")}}
|
|
5
5
|
|
|
6
|
-
export {
|
|
6
|
+
export { u as createCookie, C as createCookieSessionStorage, v as createMemorySessionStorage, k as createRequestHandler, y as createSessionStorage, F as getBuyerIp, M as getStorefrontHeaders };
|
|
7
7
|
//# sourceMappingURL=out.js.map
|
|
8
8
|
//# sourceMappingURL=index.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","createRequestHandler","build","mode","poweredByHeader","getLoadContext","handleRequest","request","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,
|
|
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","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,4BAOA,SAASC,EAAwC,CACtD,MAAAC,EACA,KAAAC,EACA,gBAAAC,EAAkB,GAClB,eAAAC,CACF,EAKG,CACD,IAAMC,EAAgBN,EAA0BE,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,CClEA,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\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"]}
|
package/package.json
CHANGED
|
@@ -5,15 +5,15 @@
|
|
|
5
5
|
"@shopify:registry": "https://registry.npmjs.org"
|
|
6
6
|
},
|
|
7
7
|
"type": "module",
|
|
8
|
-
"version": "1.1.
|
|
8
|
+
"version": "1.1.4",
|
|
9
9
|
"license": "MIT",
|
|
10
10
|
"main": "dist/index.cjs",
|
|
11
11
|
"module": "dist/production/index.js",
|
|
12
12
|
"types": "dist/production/index.d.ts",
|
|
13
13
|
"sideEffects": false,
|
|
14
14
|
"scripts": {
|
|
15
|
-
"build": "tsup --clean
|
|
16
|
-
"dev": "tsup --watch
|
|
15
|
+
"build": "tsup --clean",
|
|
16
|
+
"dev": "tsup --watch",
|
|
17
17
|
"prepack": "npm run build",
|
|
18
18
|
"typecheck": "tsc --noEmit"
|
|
19
19
|
},
|
|
@@ -43,9 +43,9 @@
|
|
|
43
43
|
"@remix-run/server-runtime": "1.19.1"
|
|
44
44
|
},
|
|
45
45
|
"devDependencies": {
|
|
46
|
-
"@shopify/oxygen-workers-types": "^3.17.
|
|
46
|
+
"@shopify/oxygen-workers-types": "^3.17.3"
|
|
47
47
|
},
|
|
48
48
|
"peerDependencies": {
|
|
49
|
-
"@shopify/oxygen-workers-types": "^3.17.
|
|
49
|
+
"@shopify/oxygen-workers-types": "^3.17.3"
|
|
50
50
|
}
|
|
51
51
|
}
|