From 02ebb2288de36dc2d44d0b7073b825d005e9ffb6 Mon Sep 17 00:00:00 2001 From: Pooya Parsa Date: Fri, 17 Feb 2023 14:53:42 +0100 Subject: [PATCH] refactor normalize headers utility --- README.md | 32 +++++++++++++++++++------------- src/_utils.ts | 47 +++++++++++++++++++++++++++++++++++++---------- src/giget.ts | 9 ++------- 3 files changed, 58 insertions(+), 30 deletions(-) diff --git a/README.md b/README.md index bc7ec01..cf3a04b 100644 --- a/README.md +++ b/README.md @@ -113,10 +113,10 @@ Import: ```js // ESM -import { downloadTemplate } from 'giget' +import { downloadTemplate } from "giget"; // CommonJS -const { downloadTemplate } = require('giget') +const { downloadTemplate } = require("giget"); ``` ### `downloadTemplate(source, options?)` @@ -124,7 +124,7 @@ const { downloadTemplate } = require('giget') **Example:** ```js -const { source, dir } = await downloadTemplate('github:unjs/template') +const { source, dir } = await downloadTemplate("github:unjs/template"); ``` **Options:** @@ -159,19 +159,21 @@ The return value is a promise that resolves to the resolved template. Using programmatic method, you can make your own custom template providers. ```ts -import type { TemplateProvider } from 'giget' +import type { TemplateProvider } from "giget"; const rainbow: TemplateProvider = async (input, { auth }) => { return { - name: 'rainbow', + name: "rainbow", version: input, - headers: { Authorization: auth }, + headers: { authorization: auth }, url: `https://rainbow.template/?variant=${input}`, - tar: `https://rainbow.template/dl/rainbow.${input}.tar.gz` - } -} + tar: `https://rainbow.template/dl/rainbow.${input}.tar.gz`, + }; +}; -const { source, dir } = await downloadRepo('rainbow:one', { providers: { rainbow } }) +const { source, dir } = await downloadRepo("rainbow:one", { + providers: { rainbow }, +}); ``` ### Custom Registry Providers @@ -179,11 +181,15 @@ const { source, dir } = await downloadRepo('rainbow:one', { providers: { rainbow You can define additional [custom registry](#custom-registry) providers using `registryProvider` utility and register to `providers`. ```ts -import { registryProvider } from 'giget' +import { registryProvider } from "giget"; -const themes = registryProvider('https://raw.githubusercontent.com/unjs/giget/main/templates') +const themes = registryProvider( + "https://raw.githubusercontent.com/unjs/giget/main/templates" +); -const { source, dir } = await downloadRepo('themes:test', { providers: { themes } }) +const { source, dir } = await downloadRepo("themes:test", { + providers: { themes }, +}); ``` ## Related projects diff --git a/src/_utils.ts b/src/_utils.ts index 8b4cafa..ef5c69d 100644 --- a/src/_utils.ts +++ b/src/_utils.ts @@ -4,6 +4,7 @@ import { spawnSync } from "node:child_process"; import { readFile, writeFile } from "node:fs/promises"; import { homedir } from "node:os"; import { promisify } from "node:util"; +import type { Agent } from "node:http"; import { relative, resolve } from "pathe"; import { fetch } from "node-fetch-native"; import createHttpsProxyAgent from "https-proxy-agent"; @@ -62,16 +63,31 @@ export function debug(...arguments_) { } // eslint-disable-next-line no-undef -export async function sendFetch(url: string, options?: RequestInit) { - const proxy = - process.env.HTTPS_PROXY || - process.env.https_proxy || - process.env.HTTP_PROXY || - process.env.http_proxy; - const requestOptions = proxy - ? { agent: createHttpsProxyAgent(proxy), ...options } - : options; - return await fetch(url, requestOptions); +interface InternalFetchOptions extends Exclude { + headers?: Record; + agent?: Agent; +} + +export async function sendFetch( + url: string, + options: InternalFetchOptions = {} +) { + if (!options.agent) { + const proxyEnv = + process.env.HTTPS_PROXY || + process.env.https_proxy || + process.env.HTTP_PROXY || + process.env.http_proxy; + if (proxyEnv) { + options.agent = createHttpsProxyAgent(proxyEnv); + } + } + + if (options?.headers) { + options.headers = normalizeHeaders(options.headers as any); + } + + return await fetch(url, options); } export function cacheDirectory() { @@ -80,6 +96,17 @@ export function cacheDirectory() { : resolve(homedir(), ".cache/giget"); } +export function normalizeHeaders(headers: Record) { + const normalized: Record = {}; + for (const [key, value] of Object.entries(headers)) { + if (!value) { + continue; + } + normalized[key.toLowerCase()] = value; + } + return normalized; +} + // -- Experimental -- export function currentShell() { diff --git a/src/giget.ts b/src/giget.ts index abfb4f0..d471e2d 100644 --- a/src/giget.ts +++ b/src/giget.ts @@ -3,7 +3,7 @@ import { existsSync, readdirSync } from "node:fs"; import { extract } from "tar"; import { resolve, dirname } from "pathe"; import { defu } from "defu"; -import { cacheDirectory, download, debug } from "./_utils"; +import { cacheDirectory, download, debug, normalizeHeaders } from "./_utils"; import { providers } from "./providers"; import { registryProvider } from "./registry"; import type { TemplateInfo, TemplateProvider } from "./types"; @@ -103,15 +103,10 @@ export async function downloadTemplate( if (!options.offline) { await mkdir(dirname(tarPath), { recursive: true }); const s = Date.now(); - const templateHeaders = Object.fromEntries( - Object.entries(template.headers || {}) - .filter((entry) => entry[1]) - .map(([key, value]) => [key.toLowerCase(), value]) - ); await download(template.tar, tarPath, { headers: { authorization: options.auth ? `Bearer ${options.auth}` : undefined, - ...templateHeaders, + ...normalizeHeaders(template.headers), }, }).catch((error) => { if (!existsSync(tarPath)) {