diff --git a/.browserslistrc b/.browserslistrc index 1f60643..a698231 100644 --- a/.browserslistrc +++ b/.browserslistrc @@ -17,7 +17,7 @@ # Generated data. # -# Last generated Feb 12, 2024 4:54 AM UTC. +# Last generated Feb 14, 2024 4:14 PM UTC. [production] node >= 20.9.0 diff --git a/.dockerignore b/.dockerignore index f84d7a8..41e9965 100644 --- a/.dockerignore +++ b/.dockerignore @@ -17,7 +17,7 @@ # Generated data. # -# Last generated Feb 12, 2024 4:54 AM UTC. +# Last generated Feb 14, 2024 4:14 PM UTC. # Locals diff --git a/.env.vault b/.env.vault index dc6e5c9..89111b9 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="SUJg36zaGiwD9YnuVWowHF5lfELsCNb2Ro8zytBJeGIy2D9/rnHuCLcqTRsWtokYBk+hghj3D0VvBh6W5hiIb/265nespIppv3Q772sY89KwErooJZ1OCl3QJJ/hzjpbCdx5It5Qoost4oqfH9KivWv/m+pLeJSq5r/AWV/4RfaU0QeI+mtj54KtVx68pAMDbm+MCnboL6jRQPMJ7FR6ej7SV7xAftjIHBj8JxAQyiA9W082IVOKQGzRNbwOplKD+PWaGDLslfIsyxTuwDl6ggZy3w7TbNEK/MMcPk+tsku+64VzE0uNq0rNGJhELjvgkf5+d3TopizEr2htB7jkn6ylOkeIf1TMr8zXlL+SxNTrsWGuSkIvHPvh+mbjiXJnYtqGdb+lqceTZhDK1Xlh29LFIghqQ/YaoL/dAL3wzZERoNDgedQe8FOn1Ftn4h9WkPF44dRrdN6Vg745wdhf8xF6/vWGpBMI/ZN1TOVDM025w7tNNvzSz4mDf4ZLkL8jLevQDHhLXFDeKbhyjyb4WmQGMr1IpQJZoxRpkd/e9F3pZpqhaG1w+YcQfnAPryU/abfD+MYfzqUwU4fnboC90+r9IuCcN0JhU0z1HYMGPqejAXVizf4jinNoYMIJAJ8zUMRVtX5MH7hvDz4NT5be3k3mSqeWngJa9CgIew30aECRZrW92BYsctnbYsyKOlTQyXZ60OYc439N811KRAF3W4qYeLIktTlWAlnMhggCwSVqH/0KxLADK82XFJMo7cpcIbOLrsMAiHewHXOwGz5uNUidau+8+L6lQimRBRDgRehADAlTiYTUYs7dSBHbzzWtsRMbMweAkFSCfLAil5sIAvSgvbx7S9hICY1LI9cJikk58R15Dz0FyyqcuIXo" -DOTENV_VAULT_DEV_VERSION=123 +DOTENV_VAULT_DEV="+g32oY1A3NsYUasVvllVnTFav0LDLrInO8hIxCL0GSvWeACCFnt+Qh0HcFT9UERjZ9rCrUyqQcn6gvxeDmYnibQO/JblOi0j6GX9HqXZJPGJgTzBtdkYK1i+PfcP8LXtezJTVOzV6v0xmz+1s+p1+TTM71P6OmbgZ/FHF5pr2zAkKtCslsBm48yoRTiITUcfi09jtP8DbxMJM7wsZYivUeb9bd5bTS/ba4wlf74+/O9prTP7K3w1UfHaUtSlt63Gi/F7DTZMCtBstdZNZHw+8yGpVZW7T3RCLvEv5VOA7xg/ywzHJ+nzBgc/GFz9GinN5IpntVSK91tZjm7wy2HwDWQdCZ8Wkugku1+DI/PVsXHhWZffcfPhNqLRzO27CdVmokteVUFpJWslnCydPIbrpMDE5pX/f94/wjCqxAW1o6I+9bm2kEK6rkh1XXSygf/Mb8OQgAg6Fd2BUgf+95trUbKcNpAQyYlvzUEH26iXZ+zPvBhYZSf51GN139kpnbahrhoQq/sJ/XRM+lcRUhye4VY9CY3Pv8wB/B+sAoSW7OyU69SLUQVWUsSrfZl/GmFuf/qJOyZNEVbWsK7BYHLSqeNqvwCiqECsyHgugS0AtvHDc9UulKbUfZqz3klX6RSRMg/AQ27n8JjjTR2N0sBPYGvC25jmEJYTUjKG4bHF4Ei9el+7sc2iG/MyQWARSa5qzmFzrum7l9tzk/MbubITJfx36Yb9XjfZk3YuvJcSIGciTD3VkLvqtdiR9JmPV7fqnb53bIjZhLIqj0rt+7WxV4/OqjSdADQwqoSoAIVwC4po9J1N86QGWc3uvaeWBCHl5Zv9l5ki9ZxngFg/V4nAe5Uybwpx4HEHJkIDT10pMY8ut7UEtPJUD7NpucqV" +DOTENV_VAULT_DEV_VERSION=127 # ci -DOTENV_VAULT_CI="LHxHjMLJNCxUSrtdkkJ5Q7bc/KRYo1X76vfniJMCT9qjcl8mQiiPw0HtMjX1KtcncEZpZLUSkIW7jvfz0kf9NFUM0SamdN6txm+/XnGdTMNHW7JcEgd9wfkwPTW/cKDf3hyh0ACvU9Und4PJZqDsa1+jwniDF/dif7/vge3vPFHTySukWoRFGo3KFqnRZKGOFvg5qSw10rdfJ8gX1OCDYQTQdWhf/5Yjc2hB/ew1ydjoI3KlZTzB50YbedGQ2iA4zYmJZwODBseeEJi14cbtluv9koTu3BVNFYzbhwD9N5fTUyOlvHGqE2IWYhPKA8YXhdd3ozGkihQ9gcovgS1JQ8pgQSMFVdKQtpXhM1XtpHHB5D5WQcEO0nE9IsDfdeVIfeYqcCIAw3KR9IW2CX4C5CmlGUOugsq+EQuaY5vC/dPil1nRlQ+yqvl1bgZ2y0zmqEVGmO92XDyAeVPsQjiAIUwvrqJjpCt/C+xtU62CAt6hSSqzxeCpUcdJHaM+HJridTTp0bPEZP85dvrABCfbVD+ePn5mgJwrEc4Ufc6uH0kGHJWB3zjhCqdUSOuK1bY+PlOcK0zq45tEPUAyw8bCuDIFyqnUR7A2YNbQ4F5vQ0cv5tmBnRPcvbazGsFtwnj2EYkP1EtJtYEwf4Uo6vZvGkQub9KrCQaxoYIf0WZeFmTq8I5I9a6EkcRyMvXwfG54wSTXAXv7Rwp+Pj23kQ8iY6Sbkfp1Hg/aRW9s32YiXufq8ukVdpOi/xrFsTudhnMbzRd1e2LwMmNmspj6Z230wxNIkHqa1T4wqWO89gKirmem4QvoZmkedtW1dbFp730JqYXUoV0Me3ENQLsXhncab23GZChRykWxuUsw+CdX4P6rMePyPloFQYERyUG7" -DOTENV_VAULT_CI_VERSION=123 +DOTENV_VAULT_CI="37Px/jaYl/QN6lMC2n7fkqe9GFJVA6nnasJdy0Eui5j4qirHmR97IXTj/SZande3xLNbwZ9Y24WbowIqQvsyORQ0+IX+Xra8JLMnzWpsgs+eGpy0FPat6iDBvDPm6O28v46NINEeadFB9iqDShAC1VPAYjQgotCH7Wh0FKFcH6AVcNKdWBiOYEG8cu2wKA59xTCfHWpR8XeUekL+NYtTLTuKnL2mVgPN8Jyecc1VnL9lXMSUGJvlqilnT+80TqRffM2rCFUCN7Wmis2z7d98EN6OOkS4JXvK3RLX589DF04QXKPql1AUEB19+JyDgA+65jccu3Jn9O652ypeox1XmnyZ9Nx2sh0uEV/iC2iJWcpWouIkRXGonmuhIcGLKHkItV9xqXe6CMdPN14OFkbJF+5GKMIl+j7uciU6VZtDLjaqn/7rWi0Dgu1QGRKXsjSLURp9gTU83+6Kd7NFm7e6FoK7fnoHOudxVmiubC9LZBCP8vVH4N8qDHy/kdmgYzIuj1+TwlsE8f1tNcuVC5kuRgPzKvRXHMlHGSsjO7am6PyXaGvBd7HlIk2Icz2hdABAx8byep9l/OFbmCU/szx4q0Ac6nE4gb/F68UF6aEwfiFbbrW65ddV6VZRfTiA4YdBOesOBSgGs4VmiGpRc5GmyuuUPrrigpLA7rQb41Ah1nKzC4pGd7ufe2K+Z/vxjpgFAwBzWj6qxcPaqmF00i9357NpLu57ne4INr6BmbsLOxqrAprw3l2OjWxEV5FxLRP4qETQLPqnyXV08PuoXhd8HHeheyfIEFO2ltb3pX7az/2N0QBorVwgqE8yMKRkX9YGJjzyqCdzbIJSKIEybsOu3ukciryYT8TCXFpiYWw7VPid+3KBaexl0idTYM76" +DOTENV_VAULT_CI_VERSION=127 # stage DOTENV_VAULT_STAGE="bfqZYD8oVLWMZ0JR5LICV+sB/btaXavszxZLxTfwSH8U5fg=" diff --git a/.gitattributes b/.gitattributes index 6eed757..278e5cc 100644 --- a/.gitattributes +++ b/.gitattributes @@ -17,7 +17,7 @@ # Generated data. # -# Last generated Feb 12, 2024 4:54 AM UTC. +# Last generated Feb 14, 2024 4:14 PM UTC. # Default diff --git a/.gitignore b/.gitignore index da74caa..2b6085f 100644 --- a/.gitignore +++ b/.gitignore @@ -17,7 +17,7 @@ # Generated data. # -# Last generated Feb 12, 2024 4:54 AM UTC. +# Last generated Feb 14, 2024 4:14 PM UTC. # Locals diff --git a/.npmignore b/.npmignore index f678354..71ddba3 100644 --- a/.npmignore +++ b/.npmignore @@ -25,7 +25,7 @@ # Generated data. # -# Last generated Feb 12, 2024 4:54 AM UTC. +# Last generated Feb 14, 2024 4:14 PM UTC. # Locals diff --git a/.prettierignore b/.prettierignore index bb5d57d..1e8733c 100644 --- a/.prettierignore +++ b/.prettierignore @@ -17,7 +17,7 @@ # Generated data. # -# Last generated Feb 12, 2024 4:54 AM UTC. +# Last generated Feb 14, 2024 4:14 PM UTC. # Packages diff --git a/.vscode/settings.json b/.vscode/settings.json index 9e1026e..44e99b1 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` Feb 12, 2024 4:54 AM UTC. + * Last generated using `./settings.mjs` Feb 14, 2024 4:14 PM UTC. */ { "editor.formatOnType": false, diff --git a/.vscodeignore b/.vscodeignore index af5bf0e..6f2de98 100644 --- a/.vscodeignore +++ b/.vscodeignore @@ -17,7 +17,7 @@ # Generated data. # -# Last generated Feb 12, 2024 4:54 AM UTC. +# Last generated Feb 14, 2024 4:14 PM UTC. # Locals diff --git a/dev-types.d.ts b/dev-types.d.ts index 8188e41..756b794 100644 --- a/dev-types.d.ts +++ b/dev-types.d.ts @@ -27,6 +27,11 @@ declare const $$__APP_BASE_URL_RESOLVED_NTS__$$: string; */ declare var __PREFRESH__: object; +/** + * Declares PWA install event, which we implement for SPAs. + */ +declare var pwaInstallEvent: Event & { prompt: () => void }; + /** * Declares virtual brand config file. */ @@ -35,6 +40,14 @@ declare module 'virtual:brand/config' { export default {} as Partial<$type.BrandRawProps>; } +/** + * Declares virtual Cloudflare runtime modules. + */ +declare module 'cloudflare:sockets' { + import type * as cf from '@cloudflare/workers-types/experimental'; + export function connect(address: string | cf.SocketAddress, options?: cf.SocketOptions): cf.Socket; +} + /** * Defines missing `entries()` on FormData. */ @@ -43,9 +56,11 @@ interface FormData { } /** - * Declares PWA install event, which we implement for SPAs. + * Defines missing `entries()` on Headers. */ -declare var pwaInstallEvent: Event & { prompt: () => void }; +interface Headers { + entries(): IterableIterator<[key: string, value: string]>; +} /* * Customizations. diff --git a/dev/.files/madrun/includes/node.cjs b/dev/.files/madrun/includes/node.cjs index 3383e2b..f18490b 100644 --- a/dev/.files/madrun/includes/node.cjs +++ b/dev/.files/madrun/includes/node.cjs @@ -6,6 +6,8 @@ * @note Instead of editing here, please review . */ +// @todo: Ditch this in favor of https://nodejs.org/api/cli.html#--disable-warningcode-or-type in latest Node. + // We only want to apply the following once. if (!process.env.C10N_SKELETON_MADRUN_NODE_INCLUDE_DONE) { // i.e., We are including now, and we only do this once. diff --git a/dev/.files/vite/includes/rollup/config.mjs b/dev/.files/vite/includes/rollup/config.mjs index 78bf1a5..36a4712 100644 --- a/dev/.files/vite/includes/rollup/config.mjs +++ b/dev/.files/vite/includes/rollup/config.mjs @@ -43,7 +43,7 @@ export default async ({ projDir, srcDir, distDir, a16sDir, appType, appEntries, external: [ ...(['lib'].includes(appType) ? [/^(?![./~#]|file:|data:|virtual:).*$/iu] : []), ...peerDepKeys.map((pkgName) => new RegExp('^' + $str.escRegExp(pkgName) + '(?:$|[/?])', 'u')), - ...[/^__STATIC_CONTENT_MANIFEST(?:$|[/?])/u], // Cloudflare worker sites use this for static assets. + /^(?:cloudflare:).*$/iu, ], output: { interop: 'auto', // Matches TypeScript configuration. diff --git a/package-lock.json b/package-lock.json index 0c16fb6..bbacb38 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@clevercanyon/utilities.cfw", - "version": "1.0.214", + "version": "1.0.216", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@clevercanyon/utilities.cfw", - "version": "1.0.214", + "version": "1.0.216", "cpu": [ "x64", "arm64" @@ -17,7 +17,7 @@ "linux" ], "devDependencies": { - "@clevercanyon/dev-deps": "^1.0.355" + "@clevercanyon/dev-deps": "^1.0.356" }, "engines": { "node": "^20.5.0 || ^20.9.0", @@ -27,7 +27,7 @@ "url": "https://github.com/sponsors/clevercanyon" }, "peerDependencies": { - "@clevercanyon/utilities": "^1.0.820", + "@clevercanyon/utilities": "^1.0.822", "@upstash/ratelimit": "1.0.0", "@upstash/redis": "1.28.0" } @@ -837,9 +837,9 @@ "dev": true }, "node_modules/@clevercanyon/dev-deps": { - "version": "1.0.355", - "resolved": "https://registry.npmjs.org/@clevercanyon/dev-deps/-/dev-deps-1.0.355.tgz", - "integrity": "sha512-JSEGjg9pbdVrjWS1OmbkoneKTxhxS9N3tDCp23ukYxYTkdlM6m193J3O8Pf+GDErH0kxp+MF1wg42rMd74acIw==", + "version": "1.0.356", + "resolved": "https://registry.npmjs.org/@clevercanyon/dev-deps/-/dev-deps-1.0.356.tgz", + "integrity": "sha512-V2cARAOv2BzKvAACKmzriycnJ0xcShY/4HHRw0DS/xy3JU7pApLn+AkGqxEwOSkdYAmwAayM+TLXX06trpgdTw==", "cpu": [ "x64", "arm64" @@ -850,12 +850,12 @@ "linux" ], "dependencies": { - "@clevercanyon/madrun": "^1.0.176", - "@clevercanyon/utilities": "^1.0.795", - "@clevercanyon/utilities.bash": "^1.0.190", - "@clevercanyon/utilities.cfp": "^1.0.205", - "@clevercanyon/utilities.node": "^1.0.185", - "@cloudflare/workers-types": "4.20231121.0", + "@clevercanyon/madrun": "^1.0.177", + "@clevercanyon/utilities": "^1.0.820", + "@clevercanyon/utilities.bash": "^1.0.191", + "@clevercanyon/utilities.cfp": "^1.0.208", + "@clevercanyon/utilities.node": "^1.0.186", + "@cloudflare/workers-types": "4.20240208.0", "@eslint/js": "8.48.0", "@iarna/toml": "2.2.5", "@iconify/json": "2.2.146", @@ -1016,9 +1016,9 @@ } }, "node_modules/@clevercanyon/utilities": { - "version": "1.0.820", - "resolved": "https://registry.npmjs.org/@clevercanyon/utilities/-/utilities-1.0.820.tgz", - "integrity": "sha512-WKbdU80xi96MvGAV8vtfYfgTcycSbJBw3lr6Wta8/liQEFFv0CLz9jDCeR1+kYbzJiwiLSHBpq6HsxLMhJEWHg==", + "version": "1.0.822", + "resolved": "https://registry.npmjs.org/@clevercanyon/utilities/-/utilities-1.0.822.tgz", + "integrity": "sha512-dd8kfKq5CA3wHspx238zP5VdrCkOAgW2slciLA/ImRvYfJMW1gd5tD/Ojz+a9eSaN9IiKWUSdDRatCEeEtaGRQ==", "cpu": [ "x64", "arm64" @@ -1076,9 +1076,9 @@ } }, "node_modules/@clevercanyon/utilities.cfp": { - "version": "1.0.207", - "resolved": "https://registry.npmjs.org/@clevercanyon/utilities.cfp/-/utilities.cfp-1.0.207.tgz", - "integrity": "sha512-6cSeg1nsv5G7kntHc5ZRATIKEVGaUHiT5Osr3m2ibKHLofOC5ZUD/8qpVSfuZgNAbKFO43UvD8AnaaKYbw6s2g==", + "version": "1.0.208", + "resolved": "https://registry.npmjs.org/@clevercanyon/utilities.cfp/-/utilities.cfp-1.0.208.tgz", + "integrity": "sha512-vbJrpE/BCJwre9BqEQDGx/3pm17OkDGssspvXebr9scsiZ0tI6Rc7jXOM6n5ieSTnFcuMyZz07XVYq90rsPNYQ==", "cpu": [ "x64", "arm64" @@ -1096,15 +1096,15 @@ "url": "https://github.com/sponsors/clevercanyon" }, "peerDependencies": { - "@clevercanyon/utilities": "^1.0.818", + "@clevercanyon/utilities": "^1.0.820", "@clevercanyon/utilities.cfw": "^1.0.214", "@clevercanyon/utilities.web": "^1.0.140" } }, "node_modules/@clevercanyon/utilities.cfw": { - "version": "1.0.214", - "resolved": "https://registry.npmjs.org/@clevercanyon/utilities.cfw/-/utilities.cfw-1.0.214.tgz", - "integrity": "sha512-K3YMn9ZMZdMEB0a+LKNE8rHyZ13q/+15DhH+pg64P71HQcYQS98ZRS2jF8/h8QWWnkwoG780ee1QF+VIYmj8xw==", + "version": "1.0.215", + "resolved": "https://registry.npmjs.org/@clevercanyon/utilities.cfw/-/utilities.cfw-1.0.215.tgz", + "integrity": "sha512-Npq+LKkCd84kn1mTDpFYDCbEnwj6M+LY3l+rDNKZRmgLtm6NsyvP09bbEhuZmTEQd/kSg3Ed0PA7bOdzue76jg==", "cpu": [ "x64", "arm64" @@ -1123,7 +1123,7 @@ "url": "https://github.com/sponsors/clevercanyon" }, "peerDependencies": { - "@clevercanyon/utilities": "^1.0.795", + "@clevercanyon/utilities": "^1.0.820", "@upstash/ratelimit": "1.0.0", "@upstash/redis": "1.28.0" } @@ -1296,9 +1296,9 @@ } }, "node_modules/@cloudflare/workers-types": { - "version": "4.20231121.0", - "resolved": "https://registry.npmjs.org/@cloudflare/workers-types/-/workers-types-4.20231121.0.tgz", - "integrity": "sha512-+kWfpCkqiepwAKXyHoE0gnkPgkLhz0/9HOBIGhHRsUvUKvhUtm3mbqqoGRWgF1qcjzrDUBbrrOq4MYHfFtc2RA==", + "version": "4.20240208.0", + "resolved": "https://registry.npmjs.org/@cloudflare/workers-types/-/workers-types-4.20240208.0.tgz", + "integrity": "sha512-MVGTTjZpJu4kJONvai5SdJzWIhOJbuweVZ3goI7FNyG+JdoQH41OoB+nMhLsX626vPLZVWGPIWsiSo/WZHzgQw==", "dev": true }, "node_modules/@cspotcode/source-map-support": { @@ -6848,13 +6848,13 @@ } }, "node_modules/@vue/compiler-core": { - "version": "3.4.18", - "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.4.18.tgz", - "integrity": "sha512-F7YK8lMK0iv6b9/Gdk15A67wM0KKZvxDxed0RR60C1z9tIJTKta+urs4j0RTN5XqHISzI3etN3mX0uHhjmoqjQ==", + "version": "3.4.19", + "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.4.19.tgz", + "integrity": "sha512-gj81785z0JNzRcU0Mq98E56e4ltO1yf8k5PQ+tV/7YHnbZkrM0fyFyuttnN8ngJZjbpofWE/m4qjKBiLl8Ju4w==", "dev": true, "dependencies": { "@babel/parser": "^7.23.9", - "@vue/shared": "3.4.18", + "@vue/shared": "3.4.19", "entities": "^4.5.0", "estree-walker": "^2.0.2", "source-map-js": "^1.0.2" @@ -6867,13 +6867,13 @@ "dev": true }, "node_modules/@vue/compiler-dom": { - "version": "3.4.18", - "resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.4.18.tgz", - "integrity": "sha512-24Eb8lcMfInefvQ6YlEVS18w5Q66f4+uXWVA+yb7praKbyjHRNuKVWGuinfSSjM0ZIiPi++QWukhkgznBaqpEA==", + "version": "3.4.19", + "resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.4.19.tgz", + "integrity": "sha512-vm6+cogWrshjqEHTzIDCp72DKtea8Ry/QVpQRYoyTIg9k7QZDX6D8+HGURjtmatfgM8xgCFtJJaOlCaRYRK3QA==", "dev": true, "dependencies": { - "@vue/compiler-core": "3.4.18", - "@vue/shared": "3.4.18" + "@vue/compiler-core": "3.4.19", + "@vue/shared": "3.4.19" } }, "node_modules/@vue/language-core": { @@ -6926,9 +6926,9 @@ } }, "node_modules/@vue/shared": { - "version": "3.4.18", - "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.4.18.tgz", - "integrity": "sha512-CxouGFxxaW5r1WbrSmWwck3No58rApXgRSBxrqgnY1K+jk20F6DrXJkHdH9n4HVT+/B6G2CAn213Uq3npWiy8Q==", + "version": "3.4.19", + "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.4.19.tgz", + "integrity": "sha512-/KliRRHMF6LoiThEy+4c1Z4KB/gbPrGjWwJR+crg2otgrf/egKzRaCPvJ51S5oetgsgXLfc4Rm5ZgrKHZrtMSw==", "dev": true }, "node_modules/@wooorm/starry-night": { @@ -7963,15 +7963,16 @@ } }, "node_modules/call-bind": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.6.tgz", - "integrity": "sha512-Mj50FLHtlsoVfRfnHaZvyrooHcrlceNZdL/QBvJJVd9Ta55qCQK0gs4ss2oZDeV9zFCs6ewzYgVE5yfVmfFpVg==", + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz", + "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==", "dev": true, "dependencies": { + "es-define-property": "^1.0.0", "es-errors": "^1.3.0", "function-bind": "^1.1.2", - "get-intrinsic": "^1.2.3", - "set-function-length": "^1.2.0" + "get-intrinsic": "^1.2.4", + "set-function-length": "^1.2.1" }, "engines": { "node": ">= 0.4" @@ -8050,9 +8051,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001585", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001585.tgz", - "integrity": "sha512-yr2BWR1yLXQ8fMpdS/4ZZXpseBgE7o4g41x3a6AJOqZuOi+iE/WdJYAuZ6Y95i4Ohd2Y+9MzIWRR+uGABH4s3Q==", + "version": "1.0.30001587", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001587.tgz", + "integrity": "sha512-HMFNotUmLXn71BQxg8cijvqxnIAofforZOwGsxyXJ0qugTdspUF4sPSJ2vhgprHCB996tIDzEq1ubumPDV8ULA==", "dev": true, "funding": [ { @@ -9167,18 +9168,20 @@ } }, "node_modules/define-data-property": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.2.tgz", - "integrity": "sha512-SRtsSqsDbgpJBbW3pABMCOt6rQyeM8s8RiyeSN8jYG8sYmt/kGJejbydttUsnDs1tadr19tvhT4ShwMyoqAm4g==", + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", + "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", "dev": true, "dependencies": { + "es-define-property": "^1.0.0", "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.2", - "gopd": "^1.0.1", - "has-property-descriptors": "^1.0.1" + "gopd": "^1.0.1" }, "engines": { "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, "node_modules/define-properties": { @@ -9268,9 +9271,9 @@ "integrity": "sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==" }, "node_modules/diff": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/diff/-/diff-5.1.0.tgz", - "integrity": "sha512-D+mk+qE8VC/PAUrlAU34N+VfXev0ghe5ywmpqrawphmVZc1bEfn56uo9qpyGp1p4xpzOHkSW4ztBd6L7Xx4ACw==", + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-5.2.0.tgz", + "integrity": "sha512-uIFDxqpRZGZ6ThOk84hEfqWoHx2devRFvpTZcTHur85vImfaxUbTW9Ryh4CpCuDnToOP1CEtXKIgytHBPVff5A==", "dev": true, "engines": { "node": ">=0.3.1" @@ -9435,9 +9438,9 @@ } }, "node_modules/electron-to-chromium": { - "version": "1.4.665", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.665.tgz", - "integrity": "sha512-UpyCWObBoD+nSZgOC2ToaIdZB0r9GhqT2WahPKiSki6ckkSuKhQNso8V2PrFcHBMleI/eqbKgVQgVC4Wni4ilw==", + "version": "1.4.668", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.668.tgz", + "integrity": "sha512-ZOBocMYCehr9W31+GpMclR+KBaDZOoAEabLdhpZ8oU1JFDwIaFY0UDbpXVEUFc0BIP2O2Qn3rkfCjQmMR4T/bQ==", "dev": true }, "node_modules/emittery": { @@ -9488,50 +9491,52 @@ } }, "node_modules/es-abstract": { - "version": "1.22.3", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.22.3.tgz", - "integrity": "sha512-eiiY8HQeYfYH2Con2berK+To6GrK2RxbPawDkGq4UiCQQfZHb6wX9qQqkbpPqaxQFcl8d9QzZqo0tGE0VcrdwA==", + "version": "1.22.4", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.22.4.tgz", + "integrity": "sha512-vZYJlk2u6qHYxBOTjAeg7qUxHdNfih64Uu2J8QqWgXZ2cri0ZpJAkzDUK/q593+mvKwlxyaxr6F1Q+3LKoQRgg==", "dev": true, "dependencies": { - "array-buffer-byte-length": "^1.0.0", - "arraybuffer.prototype.slice": "^1.0.2", - "available-typed-arrays": "^1.0.5", - "call-bind": "^1.0.5", - "es-set-tostringtag": "^2.0.1", + "array-buffer-byte-length": "^1.0.1", + "arraybuffer.prototype.slice": "^1.0.3", + "available-typed-arrays": "^1.0.6", + "call-bind": "^1.0.7", + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "es-set-tostringtag": "^2.0.2", "es-to-primitive": "^1.2.1", "function.prototype.name": "^1.1.6", - "get-intrinsic": "^1.2.2", - "get-symbol-description": "^1.0.0", + "get-intrinsic": "^1.2.4", + "get-symbol-description": "^1.0.2", "globalthis": "^1.0.3", "gopd": "^1.0.1", - "has-property-descriptors": "^1.0.0", + "has-property-descriptors": "^1.0.2", "has-proto": "^1.0.1", "has-symbols": "^1.0.3", - "hasown": "^2.0.0", - "internal-slot": "^1.0.5", - "is-array-buffer": "^3.0.2", + "hasown": "^2.0.1", + "internal-slot": "^1.0.7", + "is-array-buffer": "^3.0.4", "is-callable": "^1.2.7", "is-negative-zero": "^2.0.2", "is-regex": "^1.1.4", "is-shared-array-buffer": "^1.0.2", "is-string": "^1.0.7", - "is-typed-array": "^1.1.12", + "is-typed-array": "^1.1.13", "is-weakref": "^1.0.2", "object-inspect": "^1.13.1", "object-keys": "^1.1.1", - "object.assign": "^4.1.4", - "regexp.prototype.flags": "^1.5.1", - "safe-array-concat": "^1.0.1", - "safe-regex-test": "^1.0.0", + "object.assign": "^4.1.5", + "regexp.prototype.flags": "^1.5.2", + "safe-array-concat": "^1.1.0", + "safe-regex-test": "^1.0.3", "string.prototype.trim": "^1.2.8", "string.prototype.trimend": "^1.0.7", "string.prototype.trimstart": "^1.0.7", - "typed-array-buffer": "^1.0.0", + "typed-array-buffer": "^1.0.1", "typed-array-byte-length": "^1.0.0", "typed-array-byte-offset": "^1.0.0", "typed-array-length": "^1.0.4", "unbox-primitive": "^1.0.2", - "which-typed-array": "^1.1.13" + "which-typed-array": "^1.1.14" }, "engines": { "node": ">= 0.4" @@ -9540,6 +9545,18 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/es-define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz", + "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==", + "dev": true, + "dependencies": { + "get-intrinsic": "^1.2.4" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/es-errors": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", @@ -9570,21 +9587,21 @@ } }, "node_modules/es-iterator-helpers": { - "version": "1.0.16", - "resolved": "https://registry.npmjs.org/es-iterator-helpers/-/es-iterator-helpers-1.0.16.tgz", - "integrity": "sha512-CREG2A9Vq7bpDRnldhFcMKuKArvkZtsH6Y0DHOHVg49qhf+LD8uEdUM3OkOAICv0EziGtDEnQtqY2/mfBILpFw==", + "version": "1.0.17", + "resolved": "https://registry.npmjs.org/es-iterator-helpers/-/es-iterator-helpers-1.0.17.tgz", + "integrity": "sha512-lh7BsUqelv4KUbR5a/ZTaGGIMLCjPGPqJ6q+Oq24YP0RdyptX1uzm4vvaqzk7Zx3bpl/76YLTTDj9L7uYQ92oQ==", "dev": true, "dependencies": { "asynciterator.prototype": "^1.0.0", - "call-bind": "^1.0.6", + "call-bind": "^1.0.7", "define-properties": "^1.2.1", - "es-abstract": "^1.22.3", + "es-abstract": "^1.22.4", "es-errors": "^1.3.0", "es-set-tostringtag": "^2.0.2", "function-bind": "^1.1.2", "get-intrinsic": "^1.2.4", "globalthis": "^1.0.3", - "has-property-descriptors": "^1.0.1", + "has-property-descriptors": "^1.0.2", "has-proto": "^1.0.1", "has-symbols": "^1.0.3", "internal-slot": "^1.0.7", @@ -13171,12 +13188,12 @@ } }, "node_modules/has-property-descriptors": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.1.tgz", - "integrity": "sha512-VsX8eaIewvas0xnvinAe9bw4WfIeODpGYikiWYLH+dma0Jw6KHYqWiWfhQlgOVK8D6PvjubK5Uc4P0iIhIcNVg==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", + "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", "dev": true, "dependencies": { - "get-intrinsic": "^1.2.2" + "es-define-property": "^1.0.0" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -13517,9 +13534,9 @@ } }, "node_modules/http-proxy-agent": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.0.tgz", - "integrity": "sha512-+ZT+iBxVUQ1asugqnD6oWoRiS25AkjNfG085dKJGtGxkdwLQrMKU5wJr2bOOFAXzKcTuqq+7fZlTMgG3SRfIYQ==", + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.1.tgz", + "integrity": "sha512-My1KCEPs6A0hb4qCVzYp8iEvA8j8YqcvXLZZH8C9OFuTYpYjHE7N2dtG3mRl1HMD4+VGXpF3XcDVcxGBT7yDZQ==", "dev": true, "dependencies": { "agent-base": "^7.1.0", @@ -13530,9 +13547,9 @@ } }, "node_modules/https-proxy-agent": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.2.tgz", - "integrity": "sha512-NmLNjm6ucYwtcUmL7JQC1ZQ57LmHP4lT15FQ8D61nak1rO6DH+fz5qNK2Ap5UN4ZapYICE3/0KodcLYSPsPbaA==", + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.3.tgz", + "integrity": "sha512-kCnwztfX0KZJSLOBrcL0emLeFako55NWMovvyPP2AjsghNk9RB1yjSI+jVumPHYZsNXegNoqupSW9IY3afSH8w==", "dev": true, "dependencies": { "agent-base": "^7.0.2", @@ -25197,9 +25214,9 @@ } }, "node_modules/remark-mdx": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/remark-mdx/-/remark-mdx-3.0.0.tgz", - "integrity": "sha512-O7yfjuC6ra3NHPbRVxfflafAj3LTwx3b73aBvkEFU5z4PsD6FD4vrqJAkE5iNGLz71GdjXfgRqm3SQ0h0VuE7g==", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/remark-mdx/-/remark-mdx-3.0.1.tgz", + "integrity": "sha512-3Pz3yPQ5Rht2pM5R+0J2MrGoBSrzf+tJG94N+t/ilfdh8YLyyKYtidAYwTveB20BoHAcwIopOUqhcmh2F7hGYA==", "dev": true, "dependencies": { "mdast-util-mdx": "^3.0.0", diff --git a/package.json b/package.json index c7aeedb..d741f15 100644 --- a/package.json +++ b/package.json @@ -3,7 +3,7 @@ "publishConfig": { "access": "public" }, - "version": "1.0.215", + "version": "1.0.217", "license": "GPL-3.0-or-later", "name": "@clevercanyon/utilities.cfw", "description": "Utilities for JavaScript apps running in a Cloudflare Worker environment.", @@ -35,6 +35,11 @@ "import": "./dist/cfw.js", "default": "./dist/cfw.js" }, + "./proxy": { + "types": "./dist/types/proxy.d.ts", + "import": "./dist/proxy.js", + "default": "./dist/proxy.js" + }, "./redis": { "types": "./dist/types/redis.d.ts", "import": "./dist/redis.js", @@ -54,7 +59,7 @@ }, "dependencies": {}, "peerDependencies": { - "@clevercanyon/utilities": "^1.0.820", + "@clevercanyon/utilities": "^1.0.822", "@upstash/ratelimit": "1.0.0", "@upstash/redis": "1.28.0" }, @@ -62,7 +67,7 @@ "optionalDependencies": {}, "bundleDependencies": [], "devDependencies": { - "@clevercanyon/dev-deps": "^1.0.355" + "@clevercanyon/dev-deps": "^1.0.356" }, "overrides": {}, "cpu": ["x64", "arm64"], diff --git a/src/index.ts b/src/index.ts index 0866565..c27ea73 100644 --- a/src/index.ts +++ b/src/index.ts @@ -5,4 +5,5 @@ import '#@initialize.ts'; export * as $cfw from '#cfw.ts'; +export * as $proxy from '#proxy.ts'; export * as $redis from '#redis.ts'; diff --git a/src/proxy.ts b/src/proxy.ts new file mode 100644 index 0000000..e812e8d --- /dev/null +++ b/src/proxy.ts @@ -0,0 +1,140 @@ +/** + * Redis utilities. + */ + +import '#@initialize.ts'; + +import { type StdFetchEventData } from '#cfw.ts'; +import { $crypto, $http, $mime, $obj, $str, $time, $url, type $type } from '@clevercanyon/utilities'; +import { connect } from 'cloudflare:sockets'; + +/** + * Defines types. + */ +export type FetchOptions = { + proxy: { + host: string; + port: number; + username?: string; + password?: string; + }; + headers?: Headers | { [x: string]: string }; + timeout?: number; // In milliseconds. +}; + +/** + * Performs an HTTP fetch using a proxy. + * + * Note: Only `GET` method is supported at this time. + * + * @param feData Fetch event data; {@see StdFetchEventData}. + * @param url Parseable URL; i.e., string or URL instance. + * @param options Some required; {@see FetchOptions}. + * + * @returns Promise of HTTP response. + */ +export const fetch = async (feData: StdFetchEventData, parseable: $type.URL | string, options?: FetchOptions): Promise<$type.cf.Response> => { + const { Response } = feData, + url = $url.tryParse(parseable), + opts = $obj.defaults({}, options || {}, { + headers: {}, + timeout: $time.secondInMilliseconds * 15, + }) as Required; + + if (!url) { + return new Response(null, { + status: 400, + statusText: $http.responseStatusText(400), + headers: { 'content-type': $mime.contentType('.txt') }, + }); + } + if (!opts.proxy || !opts.proxy.host || !opts.proxy.port) { + throw Error('AzwqQc85'); // Missing required options. + } + return await Promise.race([fetchꓺwaitTimeout(feData, opts), fetchꓺviaSocket(feData, url, opts)]); +}; + +/** + * Creates a timeout promise. + * + * @param feData Fetch event data; {@see StdFetchEventData}. + * @param options Required options; {@see Required}. + * + * @returns Timeout promise suitable for a race. + */ +const fetchꓺwaitTimeout = async (feData: StdFetchEventData, opts: Required): Promise<$type.cf.Response> => { + const { Response } = feData; + + return new Promise((resolve): void => { + setTimeout((): void => { + resolve( + new Response(null, { + status: 408, + statusText: $http.responseStatusText(408), + headers: { 'content-type': $mime.contentType('.txt') }, + }), + ); + }, opts.timeout); + }); +}; + +/** + * Performs an HTTP fetch using a proxy. + * + * @param feData Fetch event data; {@see StdFetchEventData}. + * @param url Parseable URL; i.e., string or URL instance. + * @param options Required options; {@see Required}. + * + * @returns Promise of HTTP response. + */ +const fetchꓺviaSocket = async (feData: StdFetchEventData, url: $type.URL, opts: Required): Promise<$type.cf.Response> => { + const { Response } = feData; + + try { + const socket = connect({ hostname: opts.proxy.host, port: opts.proxy.port }), + { readable, writable } = socket, + writer = writable.getWriter(), + headers: Set = new Set(); + + headers.add(`host: ${url.hostname}`); + + if (opts.proxy.username && opts.proxy.password) { + headers.add(`proxy-authorization: ${'Basic ' + $crypto.base64Encode(`${opts.proxy.username}:${opts.proxy.password}`)}`); + } + for (const [name, value] of $http.parseHeaders(opts.headers).entries()) { + headers.add(`${name}: ${value}`); + } + await writer.write($str.textEncoder.encode(`GET ${url.toString()} HTTP/1.0\r\n${[...headers].join('\r\n')}\r\n\r\n`)); + await writer.close(); // Close writable stream. + + const rawHTTPResponse = await new Response(readable, { headers: { 'content-type': $mime.contentType('.txt') } }).text(); + await socket.close(); // We can go ahead and close the socket now. + + const rawHTTPResponseCRLFIndex = rawHTTPResponse.indexOf('\r\n\r\n'); + if (!rawHTTPResponse || rawHTTPResponseCRLFIndex === -1) { + return new Response(null, { + status: 421, + statusText: $http.responseStatusText(421), + headers: { 'content-type': $mime.contentType('.txt') }, + }); + } + const rawHTTPResponseHeaders = rawHTTPResponse.slice(0, rawHTTPResponseCRLFIndex).trim(), + rawHTTPResponseBody = rawHTTPResponse.slice(rawHTTPResponseCRLFIndex + 4).trim(); + + const responseStatus = Number(rawHTTPResponseHeaders.match(/^HTTP\/1\.0\s+([0-9]+)/iu)?.[1] || 0), + responseHeaders = $http.parseHeaders(rawHTTPResponseHeaders) as $type.cf.Headers, + responseBody = rawHTTPResponseBody; + + return new Response(responseBody, { + status: responseStatus, + statusText: $http.responseStatusText(responseStatus), + headers: responseHeaders, + }); + } catch (thrown) { + return new Response(null, { + status: 500, + statusText: $http.responseStatusText(500), + headers: { 'content-type': $mime.contentType('.txt') }, + }); + } +}; diff --git a/tsconfig.json b/tsconfig.json index 714ac4b..a767ae2 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` Feb 12, 2024 4:54 AM UTC. + * Last generated using `./tsconfig.mjs` Feb 14, 2024 4:14 PM UTC. */ { "include": ["./src/**/*", "./dev-types.d.ts"], diff --git a/wrangler.toml b/wrangler.toml index 23e572a..eaa5d80 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` Feb 12, 2024 4:54 AM UTC. +# Last generated using `./wrangler.mjs` Feb 14, 2024 4:14 PM UTC. ## send_metrics = false