diff --git a/packages/yoga/package.json b/packages/yoga/package.json index 4050984..3378c60 100644 --- a/packages/yoga/package.json +++ b/packages/yoga/package.json @@ -21,6 +21,7 @@ "chokidar": "^2.1.1", "create-yoga": "0.0.2", "decache": "^4.5.1", + "dotenv": "^7.0.0", "graphql": "^0.12.0 || ^0.13.0 || ^14.0.0", "inquirer": "^6.2.1", "js-yaml": "^3.12.1", @@ -35,6 +36,7 @@ }, "devDependencies": { "@types/chokidar": "1.7.5", + "@types/dotenv": "^6.1.0", "@types/express": "4.16.1", "@types/graphql": "14.0.7", "@types/inquirer": "0.0.44", diff --git a/packages/yoga/src/cli/commands/build/index.ts b/packages/yoga/src/cli/commands/build/index.ts index 002aa21..118e0e8 100644 --- a/packages/yoga/src/cli/commands/build/index.ts +++ b/packages/yoga/src/cli/commands/build/index.ts @@ -17,8 +17,8 @@ const diagnosticHost: ts.FormatDiagnosticsHost = { getCanonicalFileName: path => path, } -export default () => { - const info = importYogaConfig() +export default (argv: Record) => { + const info = importYogaConfig({ env: argv.env }) const config = readConfigFromTsConfig(info) compile(config.fileNames, config.options) diff --git a/packages/yoga/src/cli/commands/eject/index.ts b/packages/yoga/src/cli/commands/eject/index.ts index 1a97d8e..4628065 100644 --- a/packages/yoga/src/cli/commands/eject/index.ts +++ b/packages/yoga/src/cli/commands/eject/index.ts @@ -5,8 +5,8 @@ import { writeEjectFiles } from '../build' import { relative } from 'path' import { resolvePrettierOptions, prettify } from '../../../helpers' -export default async () => { - const info = importYogaConfig() +export default async (argv: Record) => { + const info = importYogaConfig({ env: argv.env }) const prettierOptions = await resolvePrettierOptions(info.projectDir) if ( @@ -23,5 +23,7 @@ export default async () => { process.exit(1) } - writeEjectFiles(info, (filePath, content) => writeFileSync(filePath, prettify(content, prettierOptions))) + writeEjectFiles(info, (filePath, content) => + writeFileSync(filePath, prettify(content, prettierOptions)), + ) } diff --git a/packages/yoga/src/cli/commands/scaffold/index.ts b/packages/yoga/src/cli/commands/scaffold/index.ts index 3368587..e7a6906 100644 --- a/packages/yoga/src/cli/commands/scaffold/index.ts +++ b/packages/yoga/src/cli/commands/scaffold/index.ts @@ -9,8 +9,8 @@ import { Config } from '../../../types' import { spawnAsync } from '../../spawnAsync' import execa = require('execa') -export default async () => { - const { yogaConfig, projectDir } = importYogaConfig() +export default async (argv: Record) => { + const { yogaConfig, projectDir } = importYogaConfig({ env: argv.env }) const hasDb = !!yogaConfig.prisma const inputTypeQuestion: inquirer.Question<{ inputTypeName: string }> = { name: 'inputTypeName', diff --git a/packages/yoga/src/cli/commands/start/index.ts b/packages/yoga/src/cli/commands/start/index.ts index beec87b..e9826d5 100644 --- a/packages/yoga/src/cli/commands/start/index.ts +++ b/packages/yoga/src/cli/commands/start/index.ts @@ -1,6 +1,6 @@ import { start } from '../../../server' import { importYogaConfig } from '../../../config' -export default async () => { - return start(importYogaConfig()) +export default async (argv: Record) => { + return start(importYogaConfig({ env: argv.env })) } diff --git a/packages/yoga/src/cli/commands/watch/index.ts b/packages/yoga/src/cli/commands/watch/index.ts index df2cb92..1a9719d 100644 --- a/packages/yoga/src/cli/commands/watch/index.ts +++ b/packages/yoga/src/cli/commands/watch/index.ts @@ -1,5 +1,5 @@ import { watch } from '../../../server' -export default async () => { - return watch() -} \ No newline at end of file +export default async (args: Record) => { + return watch(args['env']) +} diff --git a/packages/yoga/src/cli/index.ts b/packages/yoga/src/cli/index.ts index d8e5e42..e9b2b82 100644 --- a/packages/yoga/src/cli/index.ts +++ b/packages/yoga/src/cli/index.ts @@ -1,5 +1,4 @@ #!/usr/bin/env node - import { createTemplate } from 'create-yoga' import * as yargs from 'yargs' import build from './commands/build' @@ -18,9 +17,14 @@ function run() { .command('scaffold', 'Scaffold a new GraphQL type', {}, scaffold) .command('build', 'Build a yoga server', {}, build) .command('eject', 'Eject your project', {}, eject) - .alias('h', 'help') + .strict(true) + .demandCommand() + .option('env', { + alias: 'e', + description: 'Pass a custom NODE_ENV variable', + }) .help('help') - .showHelpOnFail(true, 'Specify --help for available options') + .showHelpOnFail(true) .version().argv } diff --git a/packages/yoga/src/config.ts b/packages/yoga/src/config.ts index 5f40527..0e9f5c0 100644 --- a/packages/yoga/src/config.ts +++ b/packages/yoga/src/config.ts @@ -4,6 +4,7 @@ import * as ts from 'typescript' import { importFile } from './helpers' import { Config, InputConfig, ConfigWithInfo } from './types' import { DEFAULT_META_SCHEMA_DIR, normalizeConfig } from './yogaDefaults' +import * as dotenv from 'dotenv' /** * Find a `prisma.yml` file if it exists @@ -44,7 +45,7 @@ export function findConfigFile(fileName: string, opts: { required: boolean }) { if (!configPath) { if (opts.required === true) { - throw new Error("Could not find a valid 'tsconfig.json'.") + throw new Error(`Could not find a valid '${fileName}'.`) } else { return undefined } @@ -53,6 +54,27 @@ export function findConfigFile(fileName: string, opts: { required: boolean }) { return configPath } +function findYogaConfigFile() { + const nodeEnv = process.env.NODE_ENV || 'dev' + let filePath = findConfigFile(`yoga.config.${nodeEnv}.ts`, { + required: false, + }) + + if (!filePath) { + filePath = findConfigFile('yoga.config.ts', { required: false }) + } + + return filePath +} + +export function injectCustomEnvironmentVariables(env?: string) { + const nodeEnv = env || process.env.NODE_ENV + + dotenv.config({ + path: path.join(process.cwd(), nodeEnv ? `.env.${nodeEnv}` : '.env'), + }) +} + function getDatamodelInfoDir( yogaConfig: Config, inputConfig: InputConfig, @@ -90,9 +112,13 @@ function getPrismaClientDir( * Dynamically imports a `yoga.config.ts` file */ export function importYogaConfig( - opts: { invalidate: boolean } = { invalidate: false }, + opts: { invalidate?: boolean; env?: string } = { + invalidate: false, + env: undefined, + }, ): ConfigWithInfo { - const yogaConfigPath = findConfigFile('yoga.config.ts', { required: false }) + injectCustomEnvironmentVariables(opts.env) + const yogaConfigPath = findYogaConfigFile() const projectDir = path.dirname( yogaConfigPath ? yogaConfigPath diff --git a/packages/yoga/src/index.ts b/packages/yoga/src/index.ts index fe86b73..776aad0 100644 --- a/packages/yoga/src/index.ts +++ b/packages/yoga/src/index.ts @@ -3,11 +3,14 @@ import { ExpressContext } from 'apollo-server-express/dist/ApolloServer' import express from 'express' import * as Http from 'http' import { InputConfig as YogaConfig, MaybePromise, Yoga } from './types' +import { injectCustomEnvironmentVariables } from './config' export * from 'nexus' export * from 'nexus-prisma' export { ApolloServer, express } +injectCustomEnvironmentVariables() + export function yogaConfig(opts: YogaConfig) { return opts } diff --git a/packages/yoga/src/server.ts b/packages/yoga/src/server.ts index 4a90ba3..398233e 100644 --- a/packages/yoga/src/server.ts +++ b/packages/yoga/src/server.ts @@ -31,10 +31,10 @@ register({ pretty: true, }) -export async function watch(): Promise { +export async function watch(env?: string): Promise { logger.clearConsole() logger.info('Starting development server...') - let info = importYogaConfig() + let info = importYogaConfig({ env }) let filesToWatch = [path.join(info.projectDir, '**', '*.ts')] if (info.prismaClientDir && info.datamodelInfoDir) { @@ -64,7 +64,7 @@ export async function watch(): Promise { if (filesToReloadBatched.length === 2) { // TODO: Do not invalidate everything, only the necessary stuff - info = importYogaConfig({ invalidate: true }) + info = importYogaConfig({ invalidate: true, env}) filesToReloadBatched = [] } else { return Promise.resolve(true)