From 8aa7f638f0332f042e452da3d71ee887b9fd9658 Mon Sep 17 00:00:00 2001 From: Jason Caldwell Date: Thu, 7 Mar 2024 07:46:22 -0500 Subject: [PATCH] Project update. [p][robotic] --- .browserslistrc | 2 +- .dockerignore | 2 +- .env.vault | 8 +-- .gitattributes | 2 +- .gitignore | 2 +- .npmignore | 2 +- .prettierignore | 2 +- .vscode/settings.json | 2 +- .vscodeignore | 2 +- package-lock.json | 28 +++++----- package.json | 2 +- src/proxy.ts | 115 ++---------------------------------------- src/root.ts | 91 ++++++++++++++++++++++++++++++--- tsconfig.json | 2 +- wrangler.toml | 2 +- 15 files changed, 116 insertions(+), 148 deletions(-) diff --git a/.browserslistrc b/.browserslistrc index a3c4ef6..11f2b01 100644 --- a/.browserslistrc +++ b/.browserslistrc @@ -17,7 +17,7 @@ # Generated data. # -# Last generated Mar 6, 2024 9:04 PM UTC. +# Last generated Mar 7, 2024 12:46 PM UTC. [production] node >= 20.9.0 diff --git a/.dockerignore b/.dockerignore index 7117486..3dc267b 100644 --- a/.dockerignore +++ b/.dockerignore @@ -17,7 +17,7 @@ # Generated data. # -# Last generated Mar 6, 2024 9:04 PM UTC. +# Last generated Mar 7, 2024 12:46 PM UTC. # Locals diff --git a/.env.vault b/.env.vault index 1365d2a..4d10edb 100644 --- a/.env.vault +++ b/.env.vault @@ -8,12 +8,12 @@ DOTENV_VAULT_MAIN="3rfi+ClkONvfHPiU9FTBcC1+Um/L8QeM9dRw1jFzEqzZXw==" DOTENV_VAULT_MAIN_VERSION=1 # dev -DOTENV_VAULT_DEV="jQzPzFCg4gSEeYluy2ieuSH+VNEgn+/dJhdAwwB7rpybk7pz11snctZc/CiINsDW/RfKWelwXMtIUB5OU8AURGn6jaj189M7N0WPb0A1WELdaw67LCEspJLsZ4dVUJz0rUcUWXogSAFrV8/LBRlC3ImAO+PGnIh+8eR+Dy4l2+5VuvFaUfcI4Qc4GlsjB40AL7N84ONFT4IqvMfBhwptK7Y+1/bOte13MZFzgDCp7qDQaQxTEvbWqAZNTL+M+E9ithPL6FDN92WseDHdT72xPe1f5kT89VN5yq5gcen7ztqZprCKVWOE2kpBMcxK57DyUZMw7c5Hzgy0I0asZ0Sc6YS926iQMCABQSMQQPHX7E3cz3IgBp+l4MohC5S6vGlfUzE0tNkitkTM7f+yzbROGwa2gi7VYY3EXrTAP+xb2cJWV+SAVyyPDALwEayFGXO5xZYWfbKa6oP/dWWxK0HIFJtGIm1+0FRMJ7YZ9PGmQ/lUXaxyqWkCzl/KYdnPbwIpym6BeVSuwPaFZBXMJGaFzK/qtQbWu004/KwnUZf41vR2UKaK0WAvO3gAwEHULZQTKG68qhbPVgaUO+nxCqTcnLWd1Odm3tpfF3yxGYtXTo+cYNOU4aUrSe7wJ5cfTzQRvEwqPSz9csIbQ99/TJfrtBPBkY5iKgPZsN1oWBvnqqxhh0fcJsw9mqLNT3shhPDicJNFCKYf3lwNkfNNdi79KE3xeiic2k1nQosrLpI+LfNX7TEFxR/kycBTOG1FKkhXy8JO+PSkYDOyt5NvpLAOej7Gbt9R1WYkFQo/7HTEsGdtSf9mFNWvhb39cI43DaPaQ7/su6R9aKO7pdrnd0keewjUpW/CYrgOwnTUFdNSKilkAQNpJBaVI3gbE0Ue" -DOTENV_VAULT_DEV_VERSION=253 +DOTENV_VAULT_DEV="fCmtXbhrizbJN9K3cu3hAX70BvX6I4xCY4ZJxwat0s28QNWyT0A0yoC0jPgC8riX+vlu82DeEc9ZfpwTyyN8B0CXT65Guu3hmdXx76nqiAPeDSNRQbOSMX7uggOIUp+0j7Ue4WcTBP0xQq1+ID7Q/DHNLHqcqP6jyg2cAxHXQ6W7FOfoo2OKMyyCxyWRRQd4N2hEUTo3ByBAYrTxszMBpz7SjwYbcDkP3T9rnOVzXeeiZckWGOpydKvAkaJZQOg8bA0BEip28p31v461MkGGXa08P1c2EX3bCcNnyPOmJal17iRRmzhxDYdGIMJbIhC3FBiocBp/yTdfose7TN6LYm8GSHoze69firTcMHg3ScBhTPiT8s0V2b7Z9dA8jo8J1zD0VJfS20tE76Kt/S6tbcLnqhButsl2my4HMwZYVB4VwxPFqJ0hh8rYgNF12uc3EjwBsqrOM6TI5HItDSMvneFh+JQJA6DdvghnGvCPXWJ1AxVwikHKAw8IcYWVjCBcE5zxNsE5G1CasxUaZKNXt2uOt3GNfDLTlCqlI5anjuCpehY+6IHul5OQkj2OLA0X2vFZWn9NLPtMnyEEMI4UR5U5/bc1oW3Pf77fLbIXKSCwWMah6W3I/IjdPNFLDBVAr4XdRk3Rasd9ObPtLYYeAve+H24zT904wN3qqimikBf7Srv8i06Gvh+nCi1UQsUM9YrXDJi7zGV+gnhsARkU32209Lx5pKeQrOpXWSxDr24xN9iLDZR1KgNA3XBqUXE9E5hL7nT1mo+WECFM+ReUi9sZ8Y64x4ntOsUppD6R7eCkjiB6+3IUl+rxp1xhQulbCFbVAup8/DZrCti4gah6lPSESvjPO2SOtrbvTssx8jYkHuNwik8WnOifGwm6" +DOTENV_VAULT_DEV_VERSION=255 # ci -DOTENV_VAULT_CI="EHlxMqx6aDPMSE2i0HAaHXxBDUs+OzebxBFnG9UI6KldkSbPjEUTM4e/gb/S91ed6arSdvgQYPhyqzeNUFJsEg5dkXrrWqJr+K8KyMO9kUxtoAC0SiybS3DYcctgwVwphqUWUVEOWexudS1S3LGAibQBioW6wSXiTCBru4CRYsR91YfStvqxkuG192Sv+T624psKMsfgVsYrasmGRmJCpo8M6O7XQsmnAi4q8U2WG+HmvW1zffHZxs1xgdJ9a5aaYFCeNw10saSH9//ygSKCNoCa/kO3jvZlLlA1Mb1ZQnkc29YY347yPrJ2ZUxNIbJa4Wc0p8FwR/e7S4FgGbJ1nb+tLphf5l7pUkLMWPxKVX64WSzPmaW9q1N1dOFjbQg+PC20krUsTw/oSFTZV0hlbTMhHlDsZRZIOE3ceSzCUfkXG7C5mspSkOzal5Hoa3kH+M42FrdkS79VT2DzBDyecRfEb8W9/JPoYlUoj+t6LeR3FFOfd3lWBrjtCB6F48CCg0VlQGCuS4DWLABVBC8FpGa0TP/3OWYbQiRc4yUUXrPjxDCdqDZGs6JzLiGUbUzB/U/P6CiVQhnpwcwha4OfWZpvVPEYAXWYBWHHnkxyB2fqNhULk/tXc4CZkzztQBFVtfl/Dm9K/11HTHnM2uHe75tSw+upSXLuom8y6ib07O8LtxvgGzyos1TRqMCwxwLDbafMe1TwBl5F1JufLvGlJvmBWIaU08zJlvddAmrwKrcKCWH5q5KCMkxBq8PSKF0syRP4LTylEhWr8yr6mZFWU0a63Mub4v8B6vgLs+wQIPLA0KZPn1au2CXsqxfGU70W5VPPBHZvhms4BtfXrg6ojBWMS08Nc7piX7RTOYI4SMdGVLYbO8URXZxjRnD4" -DOTENV_VAULT_CI_VERSION=253 +DOTENV_VAULT_CI="TwBy0z8FyLaiAQoCunI1d+T6TG74bhnKBISFSx97p6UdBqHvuiXLcsoRD3trIL7mxBIMMlkfYEchXmfGAu6fAqjVxdVkF+FqH6W2XUyCRBVsSOdr1qHz7oepfvffR13uhYtOIIJRXOJSQPPfLsXao0duMjMKx2AkF/PkDJfo51xoIaicj7j3a3IZxsKNpXGHdvGrIjWgvDyYbM5MUE8iWahbfgAE5bOZMivrBBT4m3EzyQWhUrZIXSwgN+1sGsoyXCJe49V9Jg+Rcrzu15CTelGrBEty2CW/Z86yi3ALVy/dV3MtbN6PjnwGAY4O393iHYuDhJui81FbW08XzUTcxdMApdl1BYryGQdYS1SGV7AmK7vMsAA7uspIuhx12ddxagpt3eMTt/ovb8GdghOmD1u4IIQ4NOT7qL2BkRQGqdlllLcq5rzRHL9wGTZ0z6ItUF1KSMfD0+jYZz3Rty32tug5ErYcgUhdnAKstnk9BabjScUcR9ztHzi78kbewWn2nzHTbJLggl+gkgGRGJQonrGx+2l5GGpC4Pv9t2be+88vRoylQo1zbNhJE1WnJW9CCbd+oc/XgVGdcKy6BWd3RgY0CqMHQXxteok7xbqgLaEXWIml7qi/JIyVwnGK65zb4Ozw+eUHRn59ZZV668WIzu7VOdBdTapxw/FwtjYI3U5oeV+/KHRPg8jHA8EdM04Yvm12CIpCXrhZSJ2RreYVvJ8NmT3e+Xk3mPkNcfV8ZKL2dLKMLgU0bkS8nn5NMD6gMhqdxh9W36nADzhZMmoy0Hg0eU9lHZJdSk2tsYxEpiR4/YqQG9uN5+K66YoH792nU15BNxskPR9zbTj/4Ao6XITDnn+Pei1FkONR7YWXJ8yNTMujbq7uKSNxSxWf" +DOTENV_VAULT_CI_VERSION=255 # stage DOTENV_VAULT_STAGE="bfqZYD8oVLWMZ0JR5LICV+sB/btaXavszxZLxTfwSH8U5fg=" diff --git a/.gitattributes b/.gitattributes index 7accba4..53f2ef8 100644 --- a/.gitattributes +++ b/.gitattributes @@ -17,7 +17,7 @@ # Generated data. # -# Last generated Mar 6, 2024 9:04 PM UTC. +# Last generated Mar 7, 2024 12:46 PM UTC. # Default diff --git a/.gitignore b/.gitignore index 8d5a243..927fa9e 100644 --- a/.gitignore +++ b/.gitignore @@ -17,7 +17,7 @@ # Generated data. # -# Last generated Mar 6, 2024 9:04 PM UTC. +# Last generated Mar 7, 2024 12:46 PM UTC. # Locals diff --git a/.npmignore b/.npmignore index 0771dca..8a4275d 100644 --- a/.npmignore +++ b/.npmignore @@ -25,7 +25,7 @@ # Generated data. # -# Last generated Mar 6, 2024 9:04 PM UTC. +# Last generated Mar 7, 2024 12:46 PM UTC. # Locals diff --git a/.prettierignore b/.prettierignore index 7c972ae..977e991 100644 --- a/.prettierignore +++ b/.prettierignore @@ -17,7 +17,7 @@ # Generated data. # -# Last generated Mar 6, 2024 9:04 PM UTC. +# Last generated Mar 7, 2024 12:46 PM UTC. # Packages diff --git a/.vscode/settings.json b/.vscode/settings.json index ed14b33..5463f26 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -7,7 +7,7 @@ * @note This entire file will be updated automatically. * @note Instead of editing here, please review `./settings.mjs`. * - * Last generated using `./settings.mjs` Mar 6, 2024 9:04 PM UTC. + * Last generated using `./settings.mjs` Mar 7, 2024 12:46 PM UTC. */ { "editor.formatOnType": false, diff --git a/.vscodeignore b/.vscodeignore index 3e9d0de..e480f7c 100644 --- a/.vscodeignore +++ b/.vscodeignore @@ -17,7 +17,7 @@ # Generated data. # -# Last generated Mar 6, 2024 9:04 PM UTC. +# Last generated Mar 7, 2024 12:46 PM UTC. # Locals diff --git a/package-lock.json b/package-lock.json index bff3995..f3a3ff8 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@clevercanyon/utilities.cfw", - "version": "1.0.279", + "version": "1.0.280", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@clevercanyon/utilities.cfw", - "version": "1.0.279", + "version": "1.0.280", "cpu": [ "x64", "arm64" @@ -1103,9 +1103,9 @@ } }, "node_modules/@clevercanyon/utilities.cfw": { - "version": "1.0.279", - "resolved": "https://registry.npmjs.org/@clevercanyon/utilities.cfw/-/utilities.cfw-1.0.279.tgz", - "integrity": "sha512-tEh40i13x0+wMjVDTSR2l3Ue11MODwMHmKzmsvpdufDoNstH+lSdJPKmVbuhgCCCsKB0p6GQbeo0ZRisGMzyrg==", + "version": "1.0.280", + "resolved": "https://registry.npmjs.org/@clevercanyon/utilities.cfw/-/utilities.cfw-1.0.280.tgz", + "integrity": "sha512-J3KCV7csP5rSsGxLEpVNeHw1l/fuJMsqhyf9QpNiOkrS7aue4SA0hRNOMQY+vz3lGamjGChL44SDeoJvQgMzkQ==", "cpu": [ "x64", "arm64" @@ -8140,9 +8140,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001594", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001594.tgz", - "integrity": "sha512-VblSX6nYqyJVs8DKFMldE2IVCJjZ225LW00ydtUWwh5hk9IfkTOffO6r8gJNsH0qqqeAF8KrbMYA2VEwTlGW5g==", + "version": "1.0.30001596", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001596.tgz", + "integrity": "sha512-zpkZ+kEr6We7w63ORkoJ2pOfBwBkY/bJrG/UZ90qNb45Isblu8wzDgevEOrRL1r9dWayHjYiiyCMEXPn4DweGQ==", "dev": true, "funding": [ { @@ -9518,9 +9518,9 @@ } }, "node_modules/electron-to-chromium": { - "version": "1.4.693", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.693.tgz", - "integrity": "sha512-/if4Ueg0GUQlhCrW2ZlXwDAm40ipuKo+OgeHInlL8sbjt+hzISxZK949fZeJaVsheamrzANXvw1zQTvbxTvSHw==", + "version": "1.4.695", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.695.tgz", + "integrity": "sha512-eMijZmeqPtm774pCZIOrfUHMs/7ls++W1sLhxwqgu8KQ8E2WmMtzwyqOMt0XXUJ3HTIPfuwlfwF+I5cwnfItBA==", "dev": true }, "node_modules/emittery": { @@ -13005,9 +13005,9 @@ } }, "node_modules/get-tsconfig": { - "version": "4.7.2", - "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.7.2.tgz", - "integrity": "sha512-wuMsz4leaj5hbGgg4IvDU0bqJagpftG5l5cXIAvo8uZrqn0NJqwtfupTN00VnkQJPcIRrxYrm1Ue24btpCha2A==", + "version": "4.7.3", + "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.7.3.tgz", + "integrity": "sha512-ZvkrzoUA0PQZM6fy6+/Hce561s+faD1rsNwhnO5FelNjyy7EMGJ3Rz1AQ8GYDWjhRs/7dBLOEJvhK8MiEJOAFg==", "dev": true, "dependencies": { "resolve-pkg-maps": "^1.0.0" diff --git a/package.json b/package.json index 48bb646..f516f94 100644 --- a/package.json +++ b/package.json @@ -3,7 +3,7 @@ "publishConfig": { "access": "public" }, - "version": "1.0.280", + "version": "1.0.281", "license": "GPL-3.0-or-later", "name": "@clevercanyon/utilities.cfw", "description": "Utilities for JavaScript apps running in a Cloudflare Worker environment.", diff --git a/src/proxy.ts b/src/proxy.ts index 9940f94..1042a00 100644 --- a/src/proxy.ts +++ b/src/proxy.ts @@ -5,7 +5,7 @@ import '#@initialize.ts'; import { $cfw, $root, cfw } from '#index.ts'; -import { $arr, $crypto, $env, $gzip, $http, $is, $mime, $obj, $str, $time, $to, $url, type $type } from '@clevercanyon/utilities'; +import { $arr, $crypto, $env, $gzip, $http, $is, $mime, $obj, $str, $time, $url, type $type } from '@clevercanyon/utilities'; /** * Defines types. @@ -28,30 +28,6 @@ type RequiredFetchOptions = Required & { proxy: Required; headers: $type.cfw.Headers; }; -export type UAHeaderOptions = { - randomIndex?: number; -}; -export type UAHeaders = $type.ReadonlyDeep<{ - 'user-agent': string; - - 'accept': string; - 'accept-encoding': string; - 'accept-language': string; - - 'sec-ch-ua': string; - 'sec-ch-ua-mobile': string; - 'sec-ch-ua-platform': string; - 'sec-fetch-site': string; - 'sec-fetch-mod': string; - 'sec-fetch-user': string; - - 'upgrade-insecure-requests': string; -}>; -type UAHeadersResponsePayload = $type.ReadonlyDeep<{ - ok: boolean; - error?: { message: string }; - data?: UAHeaders; -}>; /** * Performs an HTTP fetch using a proxy. @@ -86,7 +62,7 @@ export const fetch = async (rcData: $cfw.StdRequestContextData, parseable: $type opts.headers = $http.parseHeaders(opts.headers) as $type.cfw.Headers; if (!opts.headers.has('user-agent')) - for (const [name, value] of Object.entries(await uaHeaders(rcData))) { + for (const [name, value] of Object.entries(await $root.uaHeaders(rcData))) { opts.headers.set(name, value); } if (opts.uaBotAppend /* e.g., `SomeCoolBot/1.0.0` */) { @@ -111,9 +87,9 @@ export const fetch = async (rcData: $cfw.StdRequestContextData, parseable: $type * * @returns Promise of response from worker using another worker as a proxy. */ -export const fetchWorker = async (rcData: $cfw.StdRequestContextData, requestInfo: $type.cfw.RequestInfo, requestInit?: $type.cfw.RequestInit): Promise<$type.cfw.Response> => { +export const worker = async (rcData: $cfw.StdRequestContextData, requestInfo: $type.cfw.RequestInfo, requestInit?: $type.cfw.RequestInit): Promise<$type.cfw.Response> => { const { fetch, Request } = cfw, - proxyRoute = 'https://workers.o5p.me/worker-proxy/'; + proxyRoute = 'https://proxy.c11n.workers.dev/'; if ($is.string(requestInfo) || $is.url(requestInfo)) { requestInfo = $url.addQueryVar('url', requestInfo.toString(), proxyRoute); @@ -124,89 +100,6 @@ export const fetchWorker = async (rcData: $cfw.StdRequestContextData, requestInf return fetch(requestInfo, requestInit); }; -// --- -// Misc exports. - -/** - * Fetches UA headers. - * - * @param rcData Request context data; {@see $cfw.StdRequestContextData}. - * @param options All optional; {@see UAHeaderOptions}. - * - * @returns Promise of UA headers. - */ -export const uaHeaders = async (rcData: $cfw.StdRequestContextData, options?: UAHeaderOptions): Promise => { - const { fetch } = cfw, - { url, auditLogger } = rcData, - // - opts = $obj.defaults({}, options || {}, { - randomIndex: $crypto.randomNumber(1, 100), - }) as Required, - // - apiRoute = $url.addQueryVars( - { random_index: String(opts.randomIndex) }, // - new URL('https://workers.hop.gdn/api/ua-headers/v1'), - ), - defaultHeaders = { - 'upgrade-insecure-requests': '1', - 'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.132 Safari/537.36', - 'accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8', - 'sec-ch-ua': 'Google Chrome;v="80", "Chromium";v="80", ";Not A Brand";v="99"', - 'sec-ch-ua-mobile': '?0', - 'sec-ch-ua-platform': 'Windows', - 'sec-fetch-site': 'none', - 'sec-fetch-mod': '', - 'sec-fetch-user': '?1', - 'accept-encoding': 'gzip, deflate', - 'accept-language': 'en-US,en;q=0.9', - }; - if ($root.kv.isAvailable(rcData)) { - const kvKey = 'ua-headers:' + String(opts.randomIndex), - headers = (await $root.kv(rcData).get(kvKey, { type: 'json' })) as UAHeaders; - - if (!$is.plainObject(headers)) { - void auditLogger.warn('UA headers failure.', { headers, error: Error('q9UTub4N') }); - return defaultHeaders; - } - return headers; - } - if ($root.fetch.isAvailable(rcData)) { - let thrown: unknown; - - const payload = await $root - .fetch(rcData, apiRoute) - .then(async (response): Promise => { - return $to.plainObject(await response.json()) as UAHeadersResponsePayload; - }) - .catch((unknownThrown: unknown): void => { - thrown = unknownThrown; - }); - if (!payload?.ok || !$is.plainObject(payload.data) || thrown) { - void auditLogger.warn('UA headers failure.', { payload, error: Error('DkkbNUJr'), thrown }); - return defaultHeaders; - } - return payload.data; - } - if (url.hostname !== apiRoute.hostname) { - let thrown: unknown; - - const payload = await fetch(apiRoute) - .then(async (response): Promise => { - return $to.plainObject(await response.json()) as UAHeadersResponsePayload; - }) - .catch((unknownThrown: unknown): void => { - thrown = unknownThrown; - }); - if (!payload?.ok || !$is.plainObject(payload.data) || thrown) { - void auditLogger.warn('UA headers failure.', { payload, error: Error('hMG9q7P5'), thrown }); - return defaultHeaders; - } - return payload.data; - } - return defaultHeaders; -}; -uaHeaders.urlSafeOptionKeys = ['randomIndex'] as string[]; - // --- // Misc utilities. diff --git a/src/root.ts b/src/root.ts index b2860f6..f7d2aa0 100644 --- a/src/root.ts +++ b/src/root.ts @@ -5,13 +5,39 @@ import '#@initialize.ts'; import { $cfw } from '#index.ts'; -import { $app, type $type } from '@clevercanyon/utilities'; +import { $app, $crypto, $is, $obj, $to, type $type } from '@clevercanyon/utilities'; + +/** + * Defines types. + */ +export type UAHeaderOptions = { + randomIndex?: number; +}; +export type UAHeaders = $type.ReadonlyDeep<{ + 'user-agent': string; + + 'accept': string; + 'accept-encoding': string; + 'accept-language': string; + + 'sec-ch-ua': string; + 'sec-ch-ua-mobile': string; + 'sec-ch-ua-platform': string; + 'sec-fetch-site': string; + 'sec-fetch-mod': string; + 'sec-fetch-user': string; + + 'upgrade-insecure-requests': string; +}>; /** * Defines root package name. */ const rootPkgName = '@clevercanyon/workers.hop.gdn'; +// --- +// Binding utilities. + /** * Fetches using root service binding. * @@ -21,7 +47,7 @@ const rootPkgName = '@clevercanyon/workers.hop.gdn'; * * @returns Promise of response from root service binding. */ -export const fetch = async (rcData: $cfw.StdRequestContextData, requestInfo: $type.cfw.RequestInfo, requestInit?: $type.cfw.RequestInit): Promise<$type.cfw.Response> => { +export const service = async (rcData: $cfw.StdRequestContextData, requestInfo: $type.cfw.RequestInfo, requestInit?: $type.cfw.RequestInit): Promise<$type.cfw.Response> => { const { env } = rcData, rt = env.RT; @@ -29,7 +55,7 @@ export const fetch = async (rcData: $cfw.StdRequestContextData, requestInfo: $ty return rt.fetch(await $cfw.serviceBindingRequest(rcData, requestInfo, requestInit)); }; -fetch.isAvailable = (rcData: $cfw.StdRequestContextData): boolean => { +service.isAvailable = (rcData: $cfw.StdRequestContextData): boolean => { return rcData.env.RT ? true : false; }; @@ -109,24 +135,73 @@ kv.isAvailable = (rcData: $cfw.StdRequestContextData): boolean => { return rcData.env.RT_KV || (rootPkgName === $app.pkgName() && rcData.env.KV) ? true : false; }; +// --- +// UA header utilities. + +/** + * Fetches root UA headers. + * + * @param rcData Request context data; {@see $cfw.StdRequestContextData}. + * @param options All optional; {@see UAHeaderOptions}. + * + * @returns Promise of root UA headers. + */ +export const uaHeaders = async (rcData: $cfw.StdRequestContextData, options?: UAHeaderOptions): Promise => { + const opts = $obj.defaults({}, options || {}, { randomIndex: $crypto.randomNumber(1, 100) }) as Required, + kvKey = 'ua-headers:' + String($to.integerBetween(opts.randomIndex, 1, 100)), + headers = (await kv(rcData).get(kvKey, { type: 'json' })) as UAHeaders; + + if (!$is.plainObject(headers)) { + throw Error('UA headers failure.'); + } + return headers; +}; +uaHeaders.urlSafeOptionKeys = ['randomIndex'] as string[]; +uaHeaders.isAvailable = kv.isAvailable; + +// --- +// Counter utilities. + /** - * Gets counter value. + * Gets root counter value. * * @param key Counter key. * - * @returns Promise of counter value. + * @returns Promise of root counter value. */ export const counter = async (rcData: $cfw.StdRequestContextData, key: string): Promise => { - return ((await d1(rcData).prepare('SELECT `value` FROM `counters` WHERE `key` = ?1 LIMIT 1').bind(key).first('value')) as number) || 0; + return ( + ((await d1(rcData) + .prepare( + 'SELECT `value`' + + ' FROM `counters`' + + // + ' WHERE' + + ' `key` = ?1' + + // + ' LIMIT 1', + ) + .bind(key) + .first('value')) as number) || 0 + ); }; counter.isAvailable = d1.isAvailable; // Powered by root D1 database. /** - * Bumps counter value. + * Bumps root counter value. * * @param key Counter key. * @param by By; default is `1`. */ export const bumpCounter = async (rcData: $cfw.StdRequestContextData, key: string, by: number = 1): Promise => { - await d1(rcData).prepare('INSERT INTO `counters` (`key`, `value`) VALUES(?1, ?2) ON CONFLICT(`key`) DO UPDATE SET `value` = `value` + ?2').bind(key, by).run(); + await d1(rcData) + .prepare( + 'INSERT INTO `counters` (`key`, `value`)' + + ' VALUES(?1, ?2)' + + // + ' ON CONFLICT(`key`) DO UPDATE' + + ' SET `value` = `value` + ?2', + ) + .bind(key, by) + .run(); }; diff --git a/tsconfig.json b/tsconfig.json index 1ac49c1..9344a71 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -7,7 +7,7 @@ * @note This entire file will be updated automatically. * @note Instead of editing here, please review `./tsconfig.mjs`. * - * Last generated using `./tsconfig.mjs` Mar 6, 2024 9:04 PM UTC. + * Last generated using `./tsconfig.mjs` Mar 7, 2024 12:46 PM UTC. */ { "include": ["./src/**/*", "./dev-types.d.ts"], diff --git a/wrangler.toml b/wrangler.toml index 040ba33..b3ceb22 100644 --- a/wrangler.toml +++ b/wrangler.toml @@ -7,7 +7,7 @@ # @note This entire file will be updated automatically. # @note Instead of editing here, please review `./wrangler.mjs`. # -# Last generated using `./wrangler.mjs` Mar 6, 2024 9:04 PM UTC. +# Last generated using `./wrangler.mjs` Mar 7, 2024 12:46 PM UTC. ## send_metrics = false