From 7778f12719ff03f8cb7ec3601c8e4d1e5e1fdc18 Mon Sep 17 00:00:00 2001 From: Chris Valarida Date: Wed, 15 Jan 2025 16:50:41 -0800 Subject: [PATCH 1/5] Add docs to getFetcher --- packages/proxy-fetcher/src/index.ts | 46 +++++++++++++++++++++++++++-- 1 file changed, 44 insertions(+), 2 deletions(-) diff --git a/packages/proxy-fetcher/src/index.ts b/packages/proxy-fetcher/src/index.ts index d15cd9571..a15771ad3 100644 --- a/packages/proxy-fetcher/src/index.ts +++ b/packages/proxy-fetcher/src/index.ts @@ -1,9 +1,51 @@ import crossFetch from 'cross-fetch' import { SocksProxyAgent } from 'socks-proxy-agent' +/** + * Creates a custom fetcher function with support for SOCKS proxying, certificate management, + * and automatic retrying of failed requests. The fetcher adapts based on the environment and target host, + * ensuring compatibility with internal VA servers and local development setups. + * + * Behavior: + * - Adds custom certificate authority (CA) files when the target host matches specific VA domains. + * - Configures a SOCKS proxy for local environments or when certain conditions are met. + * - Retries failed requests up to 5 times using the `p-retry` library for improved resilience. + * - Logs request failures based on the `debug` flag and the retry attempt. + * + * Example Usage: + * ```ts + * const fetcher = getFetcher('https://example.com', true); + * const response = await fetcher('/api/resource', { method: 'GET' }); + * const data = await response.json(); + * ``` + * + * Dependencies: + * - `syswide-cas` for adding custom certificate authorities. + * - `p-retry` for handling request retries. + * - `cross-fetch` for making HTTP requests. + * - `socks-proxy-agent` for configuring SOCKS proxy support. + */ export const getFetcher = - (baseUrl: string, debug: boolean = false) => - async (input: RequestInfo, init: RequestInit = {}) => { + ( + /** + * The base URL for the Drupal instance. (e.g. https://va-gov-cms.ddev.site) + */ + baseUrl: string, + /** + * Whether to enable debug mode, which logs detailed request failure information. + */ + debug: boolean = false + ) => + async ( + /** + * The resource to fetch. Must include the base URL for the Drupal instance. (e.g. htts://va-gov-cms.ddev.site/flags_list) + */ + input: RequestInfo, + /** + * Any parameters to pass to the underlying `crossFetch` call. + */ + init: RequestInit = {} + ) => { const url = new URL(baseUrl) const host = url.host From 935d1e7d88d01e3d05354792dbdaec7101fb1049 Mon Sep 17 00:00:00 2001 From: Chris Valarida Date: Wed, 15 Jan 2025 16:57:46 -0800 Subject: [PATCH 2/5] Convert anonymous arrow function to named function and add docs This way the language server picks up on the docs and shows them. --- packages/proxy-fetcher/src/index.ts | 55 +++++++++++++++-------------- 1 file changed, 29 insertions(+), 26 deletions(-) diff --git a/packages/proxy-fetcher/src/index.ts b/packages/proxy-fetcher/src/index.ts index a15771ad3..efde34c5d 100644 --- a/packages/proxy-fetcher/src/index.ts +++ b/packages/proxy-fetcher/src/index.ts @@ -2,14 +2,18 @@ import crossFetch from 'cross-fetch' import { SocksProxyAgent } from 'socks-proxy-agent' /** - * Creates a custom fetcher function with support for SOCKS proxying, certificate management, - * and automatic retrying of failed requests. The fetcher adapts based on the environment and target host, - * ensuring compatibility with internal VA servers and local development setups. + * Creates a custom fetcher function with support for SOCKS proxying, + * certificate management, and automatic retrying of failed requests. The + * fetcher adapts based on the environment and target host, ensuring + * compatibility with internal VA servers and local development setups. * * Behavior: - * - Adds custom certificate authority (CA) files when the target host matches specific VA domains. - * - Configures a SOCKS proxy for local environments or when certain conditions are met. - * - Retries failed requests up to 5 times using the `p-retry` library for improved resilience. + * - Adds custom certificate authority (CA) files when the target host matches + * specific VA domains. + * - Configures a SOCKS proxy for local environments or when certain conditions + * are met. + * - Retries failed requests up to 5 times using the `p-retry` library for + * improved resilience. * - Logs request failures based on the `debug` flag and the retry attempt. * * Example Usage: @@ -18,34 +22,33 @@ import { SocksProxyAgent } from 'socks-proxy-agent' * const response = await fetcher('/api/resource', { method: 'GET' }); * const data = await response.json(); * ``` - * - * Dependencies: - * - `syswide-cas` for adding custom certificate authorities. - * - `p-retry` for handling request retries. - * - `cross-fetch` for making HTTP requests. - * - `socks-proxy-agent` for configuring SOCKS proxy support. */ -export const getFetcher = - ( - /** - * The base URL for the Drupal instance. (e.g. https://va-gov-cms.ddev.site) - */ - baseUrl: string, - /** - * Whether to enable debug mode, which logs detailed request failure information. - */ - debug: boolean = false - ) => - async ( +export const getFetcher = ( + /** + * The base URL for the Drupal instance. (e.g. https://va-gov-cms.ddev.site) + */ + baseUrl: string, + /** + * Whether to enable debug mode, which logs detailed request failure + * information. + */ + debug: boolean = false +) => + /** + * Fetches the resource at `input`, using the SOCKS proxy and managing + * certificates and retries as needed. + */ + async function fetcher( /** - * The resource to fetch. Must include the base URL for the Drupal instance. (e.g. htts://va-gov-cms.ddev.site/flags_list) + * The resource to fetch. Must include the base URL for the Drupal instance. + * (e.g. htts://va-gov-cms.ddev.site/flags_list) */ input: RequestInfo, /** * Any parameters to pass to the underlying `crossFetch` call. */ init: RequestInit = {} - ) => { + ) { const url = new URL(baseUrl) const host = url.host From 35a5bf5d8734fd612c898c860548f78aa37d5639 Mon Sep 17 00:00:00 2001 From: Chris Valarida Date: Wed, 15 Jan 2025 17:02:41 -0800 Subject: [PATCH 3/5] Add processEnv docs --- packages/env-loader/src/index.ts | 47 +++++++++++++++++++++++++++++++- 1 file changed, 46 insertions(+), 1 deletion(-) diff --git a/packages/env-loader/src/index.ts b/packages/env-loader/src/index.ts index acf553f6f..a11233b21 100644 --- a/packages/env-loader/src/index.ts +++ b/packages/env-loader/src/index.ts @@ -8,7 +8,52 @@ export type EnvVars = { [key: string]: string | boolean } -export const processEnv = async (command: string): Promise => { +/** + * Processes and sets up the environment variables, CMS feature flags, and CLI + * options before executing a given shell command. This function integrates data + * from multiple sources (CLI, environment files, and CMS) into `process.env` + * and then spawns the specified command. + * + * Behavior: + * 1. **CLI Options and Arguments**: - Parses command-line arguments and options + * using `getCliOptionsAndArgs`. + * + * 2. **Environment Variables**: - Loads environment variables from a file + * specific to `process.env.APP_ENV`. + * + * 3. **CMS Feature Flags**: - Fetches feature flags from a Drupal CMS instance + * if `APP_ENV` is not `test`. - For `test` environments, skips CMS flag + * fetching to avoid CI failures. - Combines CLI options, environment file + * variables, and CMS flags into `process.env`. + * + * 4. **Command Execution**: - Spawns the given shell command with any + * additional arguments passed from the CLI. - Uses `stdio: 'inherit'` to + * mirror command output in real-time. - Exits the parent process with the + * same exit code as the spawned command. + * + * Dependencies: + * - `getCliOptionsAndArgs` for parsing CLI options and arguments. + * - `getEnvFileVars` for loading environment-specific variables. + * - `getCmsFeatureFlags` for fetching CMS feature flags. + * - `child_process.spawn` for executing the shell command. + * + * Example Usage: + * ```ts + * await processEnv('next build'); + * ``` + * + * Notes: + * - CMS feature flags are only fetched if the environment is not `test` to + * avoid breaking CI pipelines. + * - The function combines multiple sources of environment variables to ensure a + * fully configured environment. + */ +export const processEnv = async ( + /** + * The shell command to be executed, with additional arguments passed through. + */ + command: string +): Promise => { // CLI const { args: cliArgs, options: cliOptions } = getCliOptionsAndArgs() From 8863f101072a857c5a6e35986bb8a3fdaa01cd30 Mon Sep 17 00:00:00 2001 From: Chris Valarida Date: Wed, 15 Jan 2025 17:03:18 -0800 Subject: [PATCH 4/5] Note the TS type in a comment Tried assigning it that type, but TS got angry, so I noped outta there before I fell down that rabbit hole. --- packages/env-loader/src/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/env-loader/src/index.ts b/packages/env-loader/src/index.ts index a11233b21..380ae254b 100644 --- a/packages/env-loader/src/index.ts +++ b/packages/env-loader/src/index.ts @@ -61,7 +61,7 @@ export const processEnv = async ( const envVars = getEnvFileVars(process.env.APP_ENV) // CMS FEATURE FLAGS - let cmsFeatureFlags + let cmsFeatureFlags // EnvVars, but TypeScript gets angry when assigning a boolean to a property of process.env if (process.env.APP_ENV === 'test') { // For now, don't fetch CMS feature flags for tests. Will fail CI. cmsFeatureFlags = {} From 92d632dcf523d42961e7c93cb9931c056e650a0b Mon Sep 17 00:00:00 2001 From: Chris Valarida Date: Wed, 15 Jan 2025 17:06:26 -0800 Subject: [PATCH 5/5] Use a more realistic example --- packages/proxy-fetcher/src/index.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/proxy-fetcher/src/index.ts b/packages/proxy-fetcher/src/index.ts index efde34c5d..8c09cc0db 100644 --- a/packages/proxy-fetcher/src/index.ts +++ b/packages/proxy-fetcher/src/index.ts @@ -18,8 +18,8 @@ import { SocksProxyAgent } from 'socks-proxy-agent' * * Example Usage: * ```ts - * const fetcher = getFetcher('https://example.com', true); - * const response = await fetcher('/api/resource', { method: 'GET' }); + * const fetcher = getFetcher('https://va-gov-cms.ddev.site', true); + * const response = await fetcher('https://example.com/flags_list', { method: 'GET' }); * const data = await response.json(); * ``` */