From d4f9c2f88ed5defc30a8d45b0096927bf458092b Mon Sep 17 00:00:00 2001 From: Kevin Carrabine Date: Wed, 3 Aug 2022 21:12:28 -0400 Subject: [PATCH 1/5] addition of --env flag to cli-hydrogen preview --- .../src/cli/commands/hydrogen/preview.ts | 9 +++- .../src/cli/services/preview.test.ts | 45 +++++++++++++++++-- .../cli-hydrogen/src/cli/services/preview.ts | 26 ++++++++++- 3 files changed, 75 insertions(+), 5 deletions(-) diff --git a/packages/cli-hydrogen/src/cli/commands/hydrogen/preview.ts b/packages/cli-hydrogen/src/cli/commands/hydrogen/preview.ts index fed6b5e859f..0d236335f42 100644 --- a/packages/cli-hydrogen/src/cli/commands/hydrogen/preview.ts +++ b/packages/cli-hydrogen/src/cli/commands/hydrogen/preview.ts @@ -16,6 +16,12 @@ export default class Preview extends Command { default: '3000', env: 'SHOPIFY_FLAG_PORT', }), + env: Flags.string({ + char: 'e', + description: 'the file path to your .env', + default: '', + env: 'SHOPIFY_FLAG_ENV_PATH', + }), target: Flags.string({ char: 't', description: 'the target environment (worker or node)', @@ -29,9 +35,10 @@ export default class Preview extends Command { const {flags} = await this.parse(Preview) const directory = flags.path ? path.resolve(flags.path) : process.cwd() const port = parseInt(flags.port, 10) + const envPath = flags.env if (flags.target === 'worker') { - await previewInWorker({directory, port}) + await previewInWorker({directory, port, envPath}) } else if (flags.target === 'node') { await previewInNode({directory, port}) } diff --git a/packages/cli-hydrogen/src/cli/services/preview.test.ts b/packages/cli-hydrogen/src/cli/services/preview.test.ts index c44312c2b61..78f4c0c0757 100644 --- a/packages/cli-hydrogen/src/cli/services/preview.test.ts +++ b/packages/cli-hydrogen/src/cli/services/preview.test.ts @@ -33,6 +33,7 @@ describe('hydrogen preview', () => { await file.inTemporaryDirectory(async (tmpDir) => { // Given const port = 5000 + const envPath = '' const expectedConfig = { port, workerFile: 'dist/worker/index.js', @@ -48,7 +49,45 @@ describe('hydrogen preview', () => { vi.mocked(path.findUp).mockResolvedValue(pathToExecutable) // When - await previewInWorker({directory: tmpDir, port}) + await previewInWorker({directory: tmpDir, port, envPath}) + + // Then + expect(file.write).toHaveBeenCalledWith( + path.join(tmpDir, `mini-oxygen.config.json`), + JSON.stringify(expectedConfig, null, 2), + ) + }) + }) + + it('writes a local mini oxygen config file with env bindings from a .env file', async () => { + await file.inTemporaryDirectory(async (tmpDir) => { + const tmpEnv = `${tmpDir}/.env` + + // create a .env file in tmpDir + file.writeSync(tmpEnv, `FOO="BAR"\nBAZ="BAX"`) + + // Given + const port = 5000 + const expectedConfig = { + port, + workerFile: 'dist/worker/index.js', + assetsDir: 'dist/client', + buildCommand: 'yarn build', + modules: true, + watch: true, + buildWatchPaths: ['./src'], + autoReload: true, + env: { + FOO: 'BAR', + BAZ: 'BAX', + }, + } + const pathToExecutable = path.join(tmpDir, 'mini-oxygen.js') + file.write(pathToExecutable, '// some executable file') + vi.mocked(path.findUp).mockResolvedValue(pathToExecutable) + + // When + await previewInWorker({directory: tmpDir, port, envPath: tmpEnv}) // Then expect(file.write).toHaveBeenCalledWith( @@ -66,7 +105,7 @@ describe('hydrogen preview', () => { vi.mocked(path.findUp).mockResolvedValue(pathToExecutable) // When - await previewInWorker({directory: tmpDir, port: 4000}) + await previewInWorker({directory: tmpDir, port: 4000, envPath: ''}) // Then expect(system.exec).toHaveBeenCalledWith( @@ -83,7 +122,7 @@ describe('hydrogen preview', () => { await file.inTemporaryDirectory(async (tmpDir) => { // When - const run = previewInWorker({directory: tmpDir, port: 4000}) + const run = previewInWorker({directory: tmpDir, port: 4000, envPath: ''}) // Then await expect(run).rejects.toThrow(/Could not locate the executable file to run Oxygen locally./) diff --git a/packages/cli-hydrogen/src/cli/services/preview.ts b/packages/cli-hydrogen/src/cli/services/preview.ts index 517ce31b84f..4b689e061c1 100644 --- a/packages/cli-hydrogen/src/cli/services/preview.ts +++ b/packages/cli-hydrogen/src/cli/services/preview.ts @@ -6,6 +6,10 @@ interface PreviewOptions { port: number } +interface PreviewOptionsWorker extends PreviewOptions { + envPath: string +} + export async function previewInNode({directory, port}: PreviewOptions) { const buildOutputPath = await path.resolve(directory, 'dist/node') @@ -33,7 +37,7 @@ export async function previewInNode({directory, port}: PreviewOptions) { }) } -export async function previewInWorker({directory, port}: PreviewOptions) { +export async function previewInWorker({directory, port, envPath}: PreviewOptionsWorker) { const config = { port, workerFile: 'dist/worker/index.js', @@ -43,6 +47,7 @@ export async function previewInWorker({directory, port}: PreviewOptions) { watch: true, buildWatchPaths: ['./src'], autoReload: true, + ...(envPath && parseEnvPath(envPath)), } await file.write(path.resolve(directory, 'mini-oxygen.config.json'), JSON.stringify(config, null, 2)) @@ -53,6 +58,25 @@ export async function previewInWorker({directory, port}: PreviewOptions) { } } + function parseEnvPath(envPath: string): {env: {[key: string]: string}} { + const envConfig: {env: {[key: string]: string}} = { + env: {}, + } + + if (envPath) { + const variables = file.readSync(envPath) + + variables.split('\n').forEach((entry) => { + const keyValue = entry.split('=') + const value = keyValue[1].replace(/['"]+/g, '') + const key = keyValue[0] + envConfig.env[key] = value + }) + } + + return envConfig + } + process.on('SIGINT', cleanUp.bind(null, {exit: true})) const executable = await oxygenPreviewExecutable() From 4ad234cd5980f32b852a4393994f865373ae91b8 Mon Sep 17 00:00:00 2001 From: Kevin Carrabine Date: Thu, 4 Aug 2022 09:40:47 -0400 Subject: [PATCH 2/5] house-keeping --- packages/cli-hydrogen/src/cli/services/preview.ts | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/packages/cli-hydrogen/src/cli/services/preview.ts b/packages/cli-hydrogen/src/cli/services/preview.ts index 4b689e061c1..8e3aa8852e9 100644 --- a/packages/cli-hydrogen/src/cli/services/preview.ts +++ b/packages/cli-hydrogen/src/cli/services/preview.ts @@ -10,6 +10,10 @@ interface PreviewOptionsWorker extends PreviewOptions { envPath: string } +interface EnvConfig { + env: {[key: string]: string} +} + export async function previewInNode({directory, port}: PreviewOptions) { const buildOutputPath = await path.resolve(directory, 'dist/node') @@ -58,8 +62,8 @@ export async function previewInWorker({directory, port, envPath}: PreviewOptions } } - function parseEnvPath(envPath: string): {env: {[key: string]: string}} { - const envConfig: {env: {[key: string]: string}} = { + function parseEnvPath(envPath: string): EnvConfig { + const envConfig: EnvConfig = { env: {}, } From e271444973c65bdfc563cf3fa1af88beb1f23911 Mon Sep 17 00:00:00 2001 From: Kevin Carrabine Date: Thu, 18 Aug 2022 09:25:12 -0400 Subject: [PATCH 3/5] addition of changeset --- .changeset/green-rockets-occur.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/green-rockets-occur.md diff --git a/.changeset/green-rockets-occur.md b/.changeset/green-rockets-occur.md new file mode 100644 index 00000000000..4cc96ccee11 --- /dev/null +++ b/.changeset/green-rockets-occur.md @@ -0,0 +1,5 @@ +--- +'@shopify/cli-hydrogen': minor +--- + +Addition of --env flag to cli-hydrogen package From 940d94869f1c16560e7c2429676cc53e03783d47 Mon Sep 17 00:00:00 2001 From: Kevin Carrabine Date: Thu, 8 Sep 2022 13:54:40 -0400 Subject: [PATCH 4/5] address pr feedback --- .../src/cli/commands/hydrogen/preview.ts | 3 +- .../src/cli/services/preview.test.ts | 28 ++++++++++++++----- .../cli-hydrogen/src/cli/services/preview.ts | 27 ++++++------------ packages/cli-kit/package.json | 2 +- yarn.lock | 8 +++--- 5 files changed, 36 insertions(+), 32 deletions(-) diff --git a/packages/cli-hydrogen/src/cli/commands/hydrogen/preview.ts b/packages/cli-hydrogen/src/cli/commands/hydrogen/preview.ts index 0d236335f42..9de73f1b8a7 100644 --- a/packages/cli-hydrogen/src/cli/commands/hydrogen/preview.ts +++ b/packages/cli-hydrogen/src/cli/commands/hydrogen/preview.ts @@ -19,7 +19,8 @@ export default class Preview extends Command { env: Flags.string({ char: 'e', description: 'the file path to your .env', - default: '', + default: undefined, + parse: (input, _) => Promise.resolve(path.resolve(input)), env: 'SHOPIFY_FLAG_ENV_PATH', }), target: Flags.string({ diff --git a/packages/cli-hydrogen/src/cli/services/preview.test.ts b/packages/cli-hydrogen/src/cli/services/preview.test.ts index 39c32679af8..4f420d92072 100644 --- a/packages/cli-hydrogen/src/cli/services/preview.test.ts +++ b/packages/cli-hydrogen/src/cli/services/preview.test.ts @@ -33,7 +33,7 @@ describe('hydrogen preview', () => { await file.inTemporaryDirectory(async (tmpDir) => { // Given const port = 5000 - const envPath = '' + const envPath = undefined const expectedConfig = { port, workerFile: 'dist/worker/index.js', @@ -61,10 +61,9 @@ describe('hydrogen preview', () => { it('writes a local mini oxygen config file with env bindings from a .env file', async () => { await file.inTemporaryDirectory(async (tmpDir) => { - const tmpEnv = `${tmpDir}/.env` - + const tmpEnv = path.join(tmpDir, '.env') // create a .env file in tmpDir - file.writeSync(tmpEnv, `FOO="BAR"\nBAZ="BAX"`) + file.writeSync(tmpEnv, `FOO="BAR"\nBAZ="BAX"\nAPI_KEY='SUPER_SECRET'\nPORT:8000`) // Given const port = 5000 @@ -80,10 +79,12 @@ describe('hydrogen preview', () => { env: { FOO: 'BAR', BAZ: 'BAX', + API_KEY: 'SUPER_SECRET', + PORT: '8000', }, } const pathToExecutable = path.join(tmpDir, 'mini-oxygen.js') - file.write(pathToExecutable, '// some executable file') + await file.write(pathToExecutable, '// some executable file') vi.mocked(path.findUp).mockResolvedValue(pathToExecutable) // When @@ -97,6 +98,19 @@ describe('hydrogen preview', () => { }) }) + it('shows an error when the .env path is incorrect', async () => { + // Given + vi.mocked(path.findUp).mockResolvedValue(undefined) + + await file.inTemporaryDirectory(async (tmpDir) => { + // When + const run = previewInWorker({directory: tmpDir, port: 4000, envPath: '/foo/bar/.env'}) + + // Then + await expect(run).rejects.toThrow('The environment file at /foo/bar/.env does not exist.') + }) + }) + it('runs the mini-oxygen executable from the app directory', async () => { await file.inTemporaryDirectory(async (tmpDir) => { // Given @@ -105,7 +119,7 @@ describe('hydrogen preview', () => { vi.mocked(path.findUp).mockResolvedValue(pathToExecutable) // When - await previewInWorker({directory: tmpDir, port: 4000, envPath: ''}) + await previewInWorker({directory: tmpDir, port: 4000, envPath: undefined}) // Then expect(system.exec).toHaveBeenCalledWith( @@ -122,7 +136,7 @@ describe('hydrogen preview', () => { await file.inTemporaryDirectory(async (tmpDir) => { // When - const run = previewInWorker({directory: tmpDir, port: 4000, envPath: ''}) + const run = previewInWorker({directory: tmpDir, port: 4000, envPath: undefined}) // Then await expect(run).rejects.toThrow(/Could not locate the executable file to run Oxygen locally./) diff --git a/packages/cli-hydrogen/src/cli/services/preview.ts b/packages/cli-hydrogen/src/cli/services/preview.ts index e812d2d3f0c..98474078243 100644 --- a/packages/cli-hydrogen/src/cli/services/preview.ts +++ b/packages/cli-hydrogen/src/cli/services/preview.ts @@ -1,4 +1,5 @@ import {path, error, system, file, output} from '@shopify/cli-kit' +import {readAndParseDotEnv, DotEnvFile} from '@shopify/cli-kit/node/dot-env' import {fileURLToPath} from 'url' interface PreviewOptions { @@ -7,11 +8,11 @@ interface PreviewOptions { } interface PreviewOptionsWorker extends PreviewOptions { - envPath: string + envPath: string | undefined } interface EnvConfig { - env: {[key: string]: string} + env: DotEnvFile['variables'] } export async function previewInNode({directory, port}: PreviewOptions) { @@ -51,7 +52,7 @@ export async function previewInWorker({directory, port, envPath}: PreviewOptions watch: true, buildWatchPaths: ['./src'], autoReload: true, - ...(envPath && parseEnvPath(envPath)), + ...(envPath && (await parseEnvPath(envPath))), } await file.write(path.resolve(directory, 'mini-oxygen.config.json'), JSON.stringify(config, null, 2)) @@ -62,23 +63,11 @@ export async function previewInWorker({directory, port, envPath}: PreviewOptions } } - function parseEnvPath(envPath: string): EnvConfig { - const envConfig: EnvConfig = { - env: {}, + async function parseEnvPath(envPath: string): Promise { + const {variables} = await readAndParseDotEnv(envPath) + return { + env: variables, } - - if (envPath) { - const variables = file.readSync(envPath) - - variables.split('\n').forEach((entry) => { - const keyValue = entry.split('=') - const value = keyValue[1].replace(/['"]+/g, '') - const key = keyValue[0] - envConfig.env[key] = value - }) - } - - return envConfig } process.on('SIGINT', cleanUp.bind(null, {exit: true})) diff --git a/packages/cli-kit/package.json b/packages/cli-kit/package.json index 6243480e706..dee8006dd1d 100644 --- a/packages/cli-kit/package.json +++ b/packages/cli-kit/package.json @@ -85,7 +85,7 @@ "cross-zip": "^4.0.0", "del": "^6.0.0", "env-paths": "^3.0.0", - "envfile": "^6.17.0", + "envfile": "^6.18.0", "execa": "^6.0.0", "fast-glob": "^3.2.11", "fastify": "^4.2.1", diff --git a/yarn.lock b/yarn.lock index d6b29a3ae2e..48b31b21073 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4966,10 +4966,10 @@ env-paths@^3.0.0: resolved "https://registry.yarnpkg.com/env-paths/-/env-paths-3.0.0.tgz#2f1e89c2f6dbd3408e1b1711dd82d62e317f58da" integrity sha512-dtJUTepzMW3Lm/NPxRf3wP4642UWhjL2sQxc+ym2YMj1m/H2zDNQOlezafzkHwn6sMstjHTwG6iQQsctDW/b1A== -envfile@^6.17.0: - version "6.17.0" - resolved "https://registry.yarnpkg.com/envfile/-/envfile-6.17.0.tgz#f3063a1811ae4ec2cbc33e8f099add3beae960f6" - integrity sha512-RnhtVw3auDZeeh5VtaNrbE7s6Kq8BoRtGIzcbMpMsJ+wIpRgs5jiDG4gQjW+vfws5QPlizE57/fUU0Tj6Nrs8A== +envfile@^6.18.0: + version "6.18.0" + resolved "https://registry.yarnpkg.com/envfile/-/envfile-6.18.0.tgz#bcb6275af19ba5c961c70c3f3b5c8baf568bdbf6" + integrity sha512-IsYv64dtlNXTm4huvCBpbXsdZQurYUju9WoYCkSj+SDYpO3v4/dq346QsCnNZ3JcnWw0G3E6+saVkVtmPw98Gg== err-code@^2.0.2: version "2.0.3" From 30322d1ed6047b19b4e50fc5e9b3596171f0b599 Mon Sep 17 00:00:00 2001 From: Kevin Carrabine Date: Mon, 12 Sep 2022 13:24:58 -0400 Subject: [PATCH 5/5] restore file.write to actual implementation for .env test --- packages/cli-hydrogen/src/cli/services/preview.test.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/packages/cli-hydrogen/src/cli/services/preview.test.ts b/packages/cli-hydrogen/src/cli/services/preview.test.ts index 4f420d92072..e6ef2ef4b7b 100644 --- a/packages/cli-hydrogen/src/cli/services/preview.test.ts +++ b/packages/cli-hydrogen/src/cli/services/preview.test.ts @@ -16,7 +16,7 @@ vi.mock('@shopify/cli-kit', async () => { }, file: { ...cliKit.file, - write: vi.fn(), + write: vi.fn(cliKit.file.write), }, } }) @@ -62,8 +62,10 @@ describe('hydrogen preview', () => { it('writes a local mini oxygen config file with env bindings from a .env file', async () => { await file.inTemporaryDirectory(async (tmpDir) => { const tmpEnv = path.join(tmpDir, '.env') + + vi.mocked(file.write).mockRestore() // create a .env file in tmpDir - file.writeSync(tmpEnv, `FOO="BAR"\nBAZ="BAX"\nAPI_KEY='SUPER_SECRET'\nPORT:8000`) + await file.write(tmpEnv, `FOO="BAR"\nBAZ="BAX"\nAPI_KEY='SUPER_SECRET'\nPORT:8000`) // Given const port = 5000