From 4d1f2468142480d99d5f8dd207b0a2403a68972e Mon Sep 17 00:00:00 2001 From: Lexus Drumgold Date: Thu, 14 Oct 2021 21:10:41 -0400 Subject: [PATCH] chore(tools): reimplement `loadenv` in cjs format --- .eslintrc.base.cjs | 2 +- .github/workflows/continuous-deployment.yml | 2 +- .github/workflows/continuous-integration.yml | 2 +- tools/cli/build.ts | 2 +- tools/cli/loadenv.cjs | 164 +++++++++++++++++++ tools/cli/loadenv.ts | 68 -------- tools/loaders/env.ts | 148 ----------------- tools/scripts/jest.sh | 2 +- 8 files changed, 169 insertions(+), 221 deletions(-) create mode 100755 tools/cli/loadenv.cjs delete mode 100755 tools/cli/loadenv.ts delete mode 100644 tools/loaders/env.ts diff --git a/.eslintrc.base.cjs b/.eslintrc.base.cjs index 406a7e2..c1c40b2 100644 --- a/.eslintrc.base.cjs +++ b/.eslintrc.base.cjs @@ -290,7 +290,7 @@ module.exports = { } }, { - files: ['tools/loaders/env.ts'], + files: ['tools/cli/loadenv.cjs'], rules: { 'unicorn/no-array-reduce': 0 } diff --git a/.github/workflows/continuous-deployment.yml b/.github/workflows/continuous-deployment.yml index 1d52920..f069df8 100644 --- a/.github/workflows/continuous-deployment.yml +++ b/.github/workflows/continuous-deployment.yml @@ -111,7 +111,7 @@ jobs: NODE_AUTH_TOKEN: ${{ env.PAT_GPR }} - id: env name: Set environment variables - run: node ./tools/cli/loadenv.ts -gc=production + run: node ./tools/cli/loadenv.cjs -gc=production - id: build name: Build project working-directory: ${{ needs.deployment-info.outputs.directory }} diff --git a/.github/workflows/continuous-integration.yml b/.github/workflows/continuous-integration.yml index 293dc0b..68199b4 100644 --- a/.github/workflows/continuous-integration.yml +++ b/.github/workflows/continuous-integration.yml @@ -55,7 +55,7 @@ jobs: run: yarn check:types - id: env name: Set build environment variables - run: node ./tools/cli/loadenv.ts -gc=test + run: node ./tools/cli/loadenv.cjs -gc=test - id: check-build name: Check build run: yarn build --tarball diff --git a/tools/cli/build.ts b/tools/cli/build.ts index 94e98fa..5154c23 100755 --- a/tools/cli/build.ts +++ b/tools/cli/build.ts @@ -171,7 +171,7 @@ try { logger(argv, 'type check source code') // Set environment variables - exec(`node ${PWD}/tools/cli/loadenv.ts -c ${env}`, dryRun) + exec(`node ${PWD}/tools/cli/loadenv.cjs -c ${env}`, dryRun) logger(argv, `set ${env} environment variables`) // Build project, convert output extensions, create bundles diff --git a/tools/cli/loadenv.cjs b/tools/cli/loadenv.cjs new file mode 100755 index 0000000..551f01e --- /dev/null +++ b/tools/cli/loadenv.cjs @@ -0,0 +1,164 @@ +#!/usr/bin/env node + +const ch = require('chalk') +const exec = require('child_process').exec +const { config } = require('dotenv') +const expand = require('dotenv-expand') +const fs = require('fs') +const path = require('path') +const { Record } = require('typescript') +const { inspect } = require('util') +const { default: yargs, Argv } = require('yargs') +const { hideBin } = require('yargs/helpers') + +/** + * @file CLI - Load Environment + * @module tools/cli/loadenv + */ + +/** + * @typedef LoadEnvOptions + * @property {string[]} [cascade] - Enable environment variable cascading + * @property {string} [directory=process.cwd()] - Directory to resolve files + * @property {string[]} [files=[]] - File path(s) to load + * @property {boolean} [github] - Update GitHub Actions environment + * @property {string} [print] - Name of variable to print to console + * @property {boolean} [result] - Log result when loading is complete + */ + +/** @typedef {Argv} LoadEnvArgs */ + +/** + * @typedef {object} LoadEnvResult + * @property {string} cwd - Directory environment files were loaded from + * @property {Record} env - Environment object + * @property {string[]} files - Array of (relative) file paths that were loaded + */ + +/** @type {LoadEnvArgs} */ +const args = yargs(hideBin(process.argv), process.env.INIT_CWD) + .usage('$0 [options]') + .option('cascade', { + alias: 'c', + array: true, + describe: 'enable environment variable cascading', + required: false, + requiresArg: true, + type: 'string' + }) + .option('directory', { + alias: 'd', + default: process.cwd(), + describe: 'directory to resolve files from', + required: false, + type: 'string' + }) + .option('files', { + alias: 'f', + array: true, + describe: 'file path(s) to load', + required: false, + requiresArg: true, + type: 'string' + }) + .option('github', { + alias: 'g', + describe: 'update github actions environment', + required: false, + type: 'boolean' + }) + .option('print', { + alias: 'p', + describe: 'name of variable to print to console', + required: false, + requiresArg: true, + type: 'string' + }) + .option('result', { + alias: 'r', + describe: 'log result when loading is complete', + required: false, + type: 'boolean' + }) + .alias('version', 'v') + .alias('help', 'h') + .pkgConf('loadenv') + .wrap(98) + +/** + * Loads environment files. + * + * @return {Promise} Loaded environment object + */ +const loadenv = async () => { + /** @type {LoadEnvOptions} */ + const argv = await args.argv + + const { + cascade, + directory: cwd = process.cwd(), + files = ['.env'], + github = false, + print, + result: print_result = false + } = argv + + // Init file paths array + let paths = Array.isArray(files) ? files : [files] + + // Handle environment cascading + if (cascade) { + paths = paths.reduce((accumulator, path) => { + return [ + ...accumulator, + ...(Array.isArray(cascade) ? cascade : [cascade]).flatMap(env => [ + `${path}.${env}.local`, + `${path}.${env}` + ]) + ] + }, []) + + paths = [...new Set([...paths, '.env.local', '.env']).values()] + } + + // Filter out file paths that don't exist + paths = paths.filter(p => fs.existsSync(path.join(cwd, p))) + + // Get array with full paths to environment files + const fpaths = paths.map(p => path.join(cwd, p)) + + // Init parsed environment array + /** @type {LoadEnvResult.env[]} */ const parsed = [] + + // Load environment files (and expand) + for (const full_path of fpaths) { + parsed.push(expand(config({ path: path.resolve(full_path) })).parsed || {}) + } + + // Init result object + /** @type {LoadEnvResult} */ const result = { + cwd, + env: parsed.reduce((acc, obj) => ({ ...acc, ...obj })), + files: fpaths.map(p => p.split(`${cwd}/`)[1]) + } + + // Format environment variables + for (const n of Object.keys(result.env)) result.env[n] = result.env[n].trim() + + // Update GitHub Actions environment + if (github && process.env.GITHUB_ENV) { + for (const n of Object.keys(result.env)) { + exec(`echo "${n}=${result.env[n]}" >> $GITHUB_ENV`) + } + } + + // Print selected environment variable + if (print) console.log(print, process.env[print] || '') + + // Print result + if (print_result) console.log(ch.gray(inspect(result))) + + return result +} + +loadenv() diff --git a/tools/cli/loadenv.ts b/tools/cli/loadenv.ts deleted file mode 100755 index ef702ea..0000000 --- a/tools/cli/loadenv.ts +++ /dev/null @@ -1,68 +0,0 @@ -#!/usr/bin/env node - -import type { Argv } from 'yargs' -import yargs from 'yargs' -import { hideBin } from 'yargs/helpers' -import type { LoadEnvOptions } from '../loaders/env' -import loadenv from '../loaders/env' - -/** - * @file CLI - Load Environment - * @module tools/cli/loadenv - */ - -export type LoadEnvArgs = Argv -export type LoadEnvArgv = LoadEnvArgs['argv'] - -const args: LoadEnvArgs = yargs(hideBin(process.argv), process.env.INIT_CWD) - .usage('$0 [options]') - .option('cascade', { - alias: 'c', - array: true, - describe: 'enable environment variable cascading', - required: false, - requiresArg: true, - type: 'string' - }) - .option('directory', { - alias: 'd', - default: process.cwd(), - describe: 'directory to resolve files from', - required: false, - type: 'string' - }) - .option('files', { - alias: 'f', - array: true, - describe: 'file path(s) to load', - required: false, - requiresArg: true, - type: 'string' - }) - .option('github', { - alias: 'g', - describe: 'update github actions environment', - required: false, - type: 'boolean' - }) - .option('print', { - alias: 'p', - describe: 'name of variable to print to console', - required: false, - requiresArg: true, - type: 'string' - }) - .option('result', { - alias: 'r', - describe: 'log result when loading is complete', - required: false, - type: 'boolean' - }) - .alias('version', 'v') - .alias('help', 'h') - .pkgConf('loadenv') - .wrap(98) - -const argv: LoadEnvArgv = args.argv - -loadenv(await argv) diff --git a/tools/loaders/env.ts b/tools/loaders/env.ts deleted file mode 100644 index 6508dbb..0000000 --- a/tools/loaders/env.ts +++ /dev/null @@ -1,148 +0,0 @@ -import ch from 'chalk' -import { exec } from 'child_process' -import { config } from 'dotenv' -import expand from 'dotenv-expand' -import fs from 'fs' -import path from 'path' -import { inspect } from 'util' - -/** - * @file Loaders - Environment Loader - * @module tools/loaders/env - */ - -export type LoadEnvOptions = { - /** - * Enable environment variable cascading. - */ - cascade?: string[] - - /** - * Directory to resolve files from. - * - * @default process.cwd() - */ - directory?: string - - /** - * File path(s) to load. - * - * @default [] - */ - files?: string[] - - /** - * Update GitHub Actions environment if `process.env.GITHUB_ENV` is defined. - * - * @default false - */ - github?: boolean - - /** - * Name of variable to print to console. - */ - print?: string - - /** - * Log result when loading is complete. - */ - result?: boolean -} - -export type LoadEnvResult = { - /** - * Directory environment files were loaded from. - */ - cwd: string - - /** - * Environment object. - */ - env: Record - - /** - * Array of (relative) file paths that were loaded. - */ - files: string[] -} - -/** - * Loads environment files. - * - * @param {LoadEnvOptions} [options] - Options - * @param {string} [options.cascade] - Enable environment variable cascading - * @param {string[]} [options.files=[]] - File path(s) to load - * @param {boolean} [options.github=false] - Update GitHub Actions environment - * @param {string} [options.print] - Name of variable to print to console - * @param {boolean} [options.result=false] - Log result when loading is complete - * @return {LoadEnvResult} Loaded environment object - */ -const loadEnvironment = (options: LoadEnvOptions = {}): LoadEnvResult => { - const { - cascade, - directory: cwd = process.cwd(), - files = ['.env'], - github = false, - print, - result: print_result = false - } = options - - // Init file paths array - let paths: string[] = Array.isArray(files) ? files : [files] - - // Handle environment cascading - if (cascade) { - paths = paths.reduce((accumulator: string[], path: string) => { - return [ - ...accumulator, - ...(Array.isArray(cascade) ? cascade : [cascade]).flatMap(env => [ - `${path}.${env}.local`, - `${path}.${env}` - ]) - ] - }, []) - - paths = [...new Set([...paths, '.env.local', '.env']).values()] - } - - // Filter out file paths that don't exist - paths = paths.filter(p => fs.existsSync(path.join(cwd, p))) - - // Get array with full paths to environment files - const fpaths = paths.map(p => path.join(cwd, p)) - - // Init parsed environment array - const parsed: LoadEnvResult['env'][] = [] - - // Load environment files (and expand) - for (const full_path of fpaths) { - parsed.push(expand(config({ path: path.resolve(full_path) })).parsed || {}) - } - - // Init result object - const result: LoadEnvResult = { - cwd, - env: parsed.reduce((acc, obj) => ({ ...acc, ...obj })), - files: fpaths.map(p => p.split(`${cwd}/`)[1]) - } - - // Format environment variables - for (const n of Object.keys(result.env)) result.env[n] = result.env[n].trim() - - // Update GitHub Actions environment - if (github && process.env.GITHUB_ENV) { - for (const n of Object.keys(result.env)) { - exec(`echo "${n}=${result.env[n]}" >> $GITHUB_ENV`) - } - } - - // Print selected environment variable - if (print) console.log(print, process.env[print] || '') - - // Print result - if (print_result) console.log(ch.gray(inspect(result))) - - return result -} - -export default loadEnvironment diff --git a/tools/scripts/jest.sh b/tools/scripts/jest.sh index 6740d15..0e1b333 100755 --- a/tools/scripts/jest.sh +++ b/tools/scripts/jest.sh @@ -11,5 +11,5 @@ # 2. Source environment variables # 3. Run Jest clear -node ./tools/cli/loadenv.ts -c test +node $PROJECT_CWD/tools/cli/loadenv.cjs -c test jest -i --passWithNoTests --testLocationInResults $@