From 19a147dfb707594e33adcab54f4852e9a7dce8bc Mon Sep 17 00:00:00 2001 From: Pooya Parsa Date: Thu, 19 Nov 2020 15:40:18 +0100 Subject: [PATCH] feat: fetch and localFetch --- package.json | 1 + src.runtime/fetch/local/call.ts | 40 ++++++++++++++++++++++++++ src.runtime/fetch/local/fetch.ts | 27 ++++++++++++++++++ src.runtime/fetch/local/index.ts | 2 ++ src.runtime/fetch/polyfill/node.ts | 6 ++++ src.runtime/global.ts | 9 ++++++ yarn.lock | 46 ++++++++++++++++++++++++++++++ 7 files changed, 131 insertions(+) create mode 100644 src.runtime/fetch/local/call.ts create mode 100644 src.runtime/fetch/local/fetch.ts create mode 100644 src.runtime/fetch/local/index.ts create mode 100644 src.runtime/fetch/polyfill/node.ts create mode 100644 src.runtime/global.ts diff --git a/package.json b/package.json index 4568f07a..d7d498b8 100644 --- a/package.json +++ b/package.json @@ -30,6 +30,7 @@ "devDependencies": { "@nuxtjs/eslint-config-typescript": "latest", "@types/node": "latest", + "@types/node-fetch": "^2.5.7", "consola": "^2.15.0", "eslint": "latest", "siroc": "^0.4.1", diff --git a/src.runtime/fetch/local/call.ts b/src.runtime/fetch/local/call.ts new file mode 100644 index 00000000..82755405 --- /dev/null +++ b/src.runtime/fetch/local/call.ts @@ -0,0 +1,40 @@ +import { IncomingMessage } from '../../node/http/request' +import { ServerResponse } from '../../node/http/response' + +export type Handle = (req: IncomingMessage, res: ServerResponse) => Promise + +export type CallHandle = ReturnType + +export interface CallContext { + [key: string]: any + url?: string + method?: string + headers?: { [key: string]: string | string[] } + protocol?: string + body?: any +} + +export function createCall (handle: Handle) { + return function callHandle (context: CallContext) { + const req = new IncomingMessage() + const res = new ServerResponse(req) + + req.url = context.url || '/' + req.method = context.method || 'GET' + req.headers = context.headers || {} + req.headers.host = req.headers.host || context.host || undefined + + // @ts-ignore + req.connection.encrypted = req.connection.encrypted || context.protocol === 'https' + + // @ts-ignore + req.body = context.body || null + + return handle(req, res).then(() => ({ + data: res._data.toString(), + headers: res._headers, + status: res.statusCode, + statusText: res.statusMessage + })) + } +} diff --git a/src.runtime/fetch/local/fetch.ts b/src.runtime/fetch/local/fetch.ts new file mode 100644 index 00000000..9832bc20 --- /dev/null +++ b/src.runtime/fetch/local/fetch.ts @@ -0,0 +1,27 @@ +import { CallContext, CallHandle } from './call' + +export type FetchOptions = globalThis.RequestInit & CallContext + +export function createFetch (call: CallHandle) { + return async function localFetch (input: string | Request, init: FetchOptions): Promise { + const url = input.toString() + if (!url.startsWith('/')) { + return fetch(url, init) + } + try { + const r = await call({ url, ...init }) + return new Response(r.data, { + status: r.status, + statusText: r.statusText, + headers: Object.fromEntries(Object.entries(r.headers).map( + ([name, value]) => [name, Array.isArray(value) ? value.join(',') : (value || '')]) + ) + }) + } catch (error) { + return new Response(error.toString(), { + status: parseInt(error.statusCode || error.code) || 500, + statusText: error.statusText + }) + } + } +} diff --git a/src.runtime/fetch/local/index.ts b/src.runtime/fetch/local/index.ts new file mode 100644 index 00000000..4a6114a4 --- /dev/null +++ b/src.runtime/fetch/local/index.ts @@ -0,0 +1,2 @@ +export * from './call' +export * from './fetch' diff --git a/src.runtime/fetch/polyfill/node.ts b/src.runtime/fetch/polyfill/node.ts new file mode 100644 index 00000000..79257c3a --- /dev/null +++ b/src.runtime/fetch/polyfill/node.ts @@ -0,0 +1,6 @@ +import fetch, { Request, Response, Headers } from 'node-fetch' + +global.fetch = global.fetch || fetch +global.Request = global.Request || Request +global.Response = global.Response || Response +global.Headers = global.Headers || Headers diff --git a/src.runtime/global.ts b/src.runtime/global.ts new file mode 100644 index 00000000..c7c9ac6f --- /dev/null +++ b/src.runtime/global.ts @@ -0,0 +1,9 @@ +export default ((typeof globalThis !== 'undefined') + ? globalThis + : (typeof self !== 'undefined') + ? self + : (typeof global !== 'undefined') + ? global + : (typeof window !== 'undefined') + ? window + : {}) as typeof globalThis diff --git a/yarn.lock b/yarn.lock index 8f87634c..958a7dc3 100644 --- a/yarn.lock +++ b/yarn.lock @@ -255,6 +255,14 @@ resolved "https://registry.yarnpkg.com/@types/minimist/-/minimist-1.2.1.tgz#283f669ff76d7b8260df8ab7a4262cc83d988256" integrity sha512-fZQQafSREFyuZcdWFAExYjBiCL7AUCdgsk80iO0q4yihYYdcIiH28CcuPTGFgLOCC8RlW49GSQxdHwZP+I7CNg== +"@types/node-fetch@^2.5.7": + version "2.5.7" + resolved "https://registry.yarnpkg.com/@types/node-fetch/-/node-fetch-2.5.7.tgz#20a2afffa882ab04d44ca786449a276f9f6bbf3c" + integrity sha512-o2WVNf5UhWRkxlf6eq+jMZDu7kjgpgJfl4xVNlvryc95O/6F2ld8ztKX+qu+Rjyet93WAWm5LjeX9H5FGkODvw== + dependencies: + "@types/node" "*" + form-data "^3.0.0" + "@types/node@*", "@types/node@latest": version "14.14.8" resolved "https://registry.yarnpkg.com/@types/node/-/node-14.14.8.tgz#2127bd81949a95c8b7d3240f3254352d72563aec" @@ -459,6 +467,11 @@ astral-regex@^1.0.0: resolved "https://registry.yarnpkg.com/astral-regex/-/astral-regex-1.0.0.tgz#6c8c3fb827dd43ee3918f27b82782ab7658a6fd9" integrity sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg== +asynckit@^0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" + integrity sha1-x57Zf380y48robyXkLzDZkdLS3k= + at-least-node@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/at-least-node/-/at-least-node-1.0.0.tgz#602cd4b46e844ad4effc92a8011a3c46e0238dc2" @@ -647,6 +660,13 @@ color-name@~1.1.4: resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== +combined-stream@^1.0.8: + version "1.0.8" + resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f" + integrity sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg== + dependencies: + delayed-stream "~1.0.0" + commondir@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/commondir/-/commondir-1.0.1.tgz#ddd800da0c66127393cca5950ea968a3aaf1253b" @@ -942,6 +962,11 @@ defu@^3.2.2: resolved "https://registry.yarnpkg.com/defu/-/defu-3.2.2.tgz#be20f4cc49b9805d54ee6b610658d53894942e97" integrity sha512-8UWj5lNv7HD+kB0e9w77Z7TdQlbUYDVWqITLHNqFIn6khrNHv5WQo38Dcm1f6HeNyZf0U7UbPf6WeZDSdCzGDQ== +delayed-stream@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" + integrity sha1-3zrhmayt+31ECqrgsp4icrJOxhk= + detect-indent@^6.0.0: version "6.0.0" resolved "https://registry.yarnpkg.com/detect-indent/-/detect-indent-6.0.0.tgz#0abd0f549f69fc6659a254fe96786186b6f528fd" @@ -1452,6 +1477,15 @@ foreach@^2.0.5: resolved "https://registry.yarnpkg.com/foreach/-/foreach-2.0.5.tgz#0bee005018aeb260d0a3af3ae658dd0136ec1b99" integrity sha1-C+4AUBiusmDQo6865ljdATbsG5k= +form-data@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/form-data/-/form-data-3.0.0.tgz#31b7e39c85f1355b7139ee0c647cf0de7f83c682" + integrity sha512-CKMFDglpbMi6PyN+brwB9Q/GOw0eAnsrEZDgcsH5Krhz5Od/haKHAX0NmQfha2zPPz0JpWzA7GJHGSnvCRLWsg== + dependencies: + asynckit "^0.4.0" + combined-stream "^1.0.8" + mime-types "^2.1.12" + fs-access@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/fs-access/-/fs-access-1.0.1.tgz#d6a87f262271cefebec30c553407fb995da8777a" @@ -2214,6 +2248,18 @@ micromatch@^4.0.2: braces "^3.0.1" picomatch "^2.0.5" +mime-db@1.44.0: + version "1.44.0" + resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.44.0.tgz#fa11c5eb0aca1334b4233cb4d52f10c5a6272f92" + integrity sha512-/NOTfLrsPBVeH7YtFPgsVWveuL+4SjjYxaQ1xtM1KMFj7HdxlBlxeyNLzhyJVx7r4rZGJAZ/6lkKCitSc/Nmpg== + +mime-types@^2.1.12: + version "2.1.27" + resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.27.tgz#47949f98e279ea53119f5722e0f34e529bec009f" + integrity sha512-JIhqnCasI9yD+SsmkquHBxTSEuZdQX5BuQnS2Vc7puQQQ+8yiP5AY5uWhpdv4YL4VM5c6iliiYWPgJ/nJQLp7w== + dependencies: + mime-db "1.44.0" + mime@^2.4.6: version "2.4.6" resolved "https://registry.yarnpkg.com/mime/-/mime-2.4.6.tgz#e5b407c90db442f2beb5b162373d07b69affa4d1"