From 0a1ba16436b68ad96b05e05ff1c91e5a1d336ef8 Mon Sep 17 00:00:00 2001 From: Igor Randjelovic Date: Tue, 2 Mar 2021 18:50:10 +0100 Subject: [PATCH] feat: parse --env. [WIP] --- .../__tests__/cli/parseEnvFlags.spec.ts | 47 ++++++++++++++ packages/webpack5/src/bin/index.ts | 63 +++++++++++++++++++ packages/webpack5/src/cli/parseEnvFlags.ts | 39 ++++++++++++ packages/webpack5/src/helpers/platform.ts | 2 +- 4 files changed, 150 insertions(+), 1 deletion(-) create mode 100644 packages/webpack5/__tests__/cli/parseEnvFlags.spec.ts create mode 100644 packages/webpack5/src/cli/parseEnvFlags.ts diff --git a/packages/webpack5/__tests__/cli/parseEnvFlags.spec.ts b/packages/webpack5/__tests__/cli/parseEnvFlags.spec.ts new file mode 100644 index 000000000..c04dbe57d --- /dev/null +++ b/packages/webpack5/__tests__/cli/parseEnvFlags.spec.ts @@ -0,0 +1,47 @@ +import { parseEnvFlags } from '../../src/cli/parseEnvFlags'; + +describe.only('parseEnvFlags', () => { + it('parses all possible flags', () => { + const res = parseEnvFlags([ + '--env', // invalid + '--env.foo', + '--env.externals=ext1', + '--env.externals=ext2', + '--env.externals=ext3', + '--env.externals=ext4', + '--env.externals=ext4', + '--env.externals=/path/to/a/very/long/path with spaces/foo.js', + '--env.externals=~/package.json', + '--env.externals=package.json', + '--env.ios=false', + '--env.android', + '--env.verbose', + '--env.sourceMap', + '--env.appPath=app', + '--env.appResourcesPath=App_Resources', + '--env.num=5', + '--env.float=5.4', + '--env.numArray=3', + '--env.numArray=4', + '--env.numArray=5', + '--no-hmr', + '--not-env-flag', + ]); + + expect(res).toBeDefined(); + expect(res.foo).toBe(true); + expect(res.externals).toBeInstanceOf(Array); + expect(res.externals.length).toBe(8); + expect(res.ios).toBe(false); + expect(res.android).toBe(true); + expect(res.verbose).toBe(true); + expect(res.sourceMap).toBe(true); + expect(res.sourceMap).toBe(true); + expect(res.appPath).toBe('app'); + expect(res.appResourcesPath).toBe('App_Resources'); + expect(res.num).toBe(5); + expect(res.float).toBe(5.4); + expect(res.numArray).toStrictEqual([3, 4, 5]); + expect(Object.keys(res).length).toBe(11); + }); +}); diff --git a/packages/webpack5/src/bin/index.ts b/packages/webpack5/src/bin/index.ts index 9ecc0a395..7a5f2f65f 100644 --- a/packages/webpack5/src/bin/index.ts +++ b/packages/webpack5/src/bin/index.ts @@ -3,8 +3,10 @@ import { redBright, green, greenBright } from 'chalk'; import { program } from 'commander'; import dedent from 'ts-dedent'; +import webpack from 'webpack'; import path from 'path'; import fs from 'fs'; +import { parseEnvFlags } from '../cli/parseEnvFlags'; const defaultConfig = path.resolve( __dirname, @@ -20,6 +22,8 @@ function info(message: string) { console.info(`${tag} ${greenBright(dedent(message))}`); } +program.enablePositionalOptions(); + program .command('init') .description('Initialize a new webpack.config.js in the current directory.') @@ -35,4 +39,63 @@ program info('Initialized config.'); }); +program + .command('build') + .description('Build...') + .option('--env [name]', 'environment options') + .option('--hmr', 'enable HMR') + .option('--no-hmr', 'disable HMR') + .option('--watch', 'watch for changes') + .allowUnknownOption() + .action((options, command) => { + const env = parseEnvFlags(command.args); + // add --env into the env object + // for example if we use --env prod + // we'd have env.env = 'prod' + if (options.env) { + env['env'] = options.env; + } + // const env = { + // platform: 'ios', + // verbose: true, + // appResourcesPath: 'App_Resources', + // appPath: 'src' + // } + + const configPath = path.resolve(process.cwd(), 'webpack.config.js'); + // todo: validate config exists + // todo: guard against invalid config + let configuration; + try { + configuration = require(configPath)(env); + } catch (ignore) { + console.log(ignore); + } + + if (!configuration) { + console.log('No configuration!!!!!'); + return; + } + + const compiler = webpack(configuration); + + // todo: handle --watch flag + // todo: promisify callback? + compiler.watch( + { + ignored: ['platforms'], + }, + (err, stats) => { + if (stats) { + console.log( + stats.toString({ + colors: true, + }) + ); + } + // err && console.log(err) + } + ); + }); + program.parse(process.argv); diff --git a/packages/webpack5/src/cli/parseEnvFlags.ts b/packages/webpack5/src/cli/parseEnvFlags.ts new file mode 100644 index 000000000..f8bf1d329 --- /dev/null +++ b/packages/webpack5/src/cli/parseEnvFlags.ts @@ -0,0 +1,39 @@ +import { IWebpackEnv } from '@nativescript/webpack'; + +const ENV_FLAG_RE = /--env\.(\w+)(?:=(.+))?/; + +export function parseEnvFlags(flags: string[]): IWebpackEnv { + const envFlags = flags.filter((flag) => flag.includes('--env.')); + + const env = {}; + + envFlags.map((flag) => { + let [_, name, v] = ENV_FLAG_RE.exec(flag); + let value: any = v; + + // convert --env.foo to --env.foo=true + if (value === undefined) { + value = true; + } + + // convert true/false to boolean + if (value === 'true' || value === 'false') { + value = value === 'true'; + } + + // convert numbers + if (!isNaN(value) && !isNaN(parseFloat(value))) { + value = +value; + } + + // duplicate key/name - convert to array + if (name in env && value) { + const orig = Array.isArray(env[name]) ? env[name] : [env[name]]; + env[name] = [...orig, value]; + } else { + env[name] = value; + } + }); + + return env; +} diff --git a/packages/webpack5/src/helpers/platform.ts b/packages/webpack5/src/helpers/platform.ts index c8adde006..98326e9d9 100644 --- a/packages/webpack5/src/helpers/platform.ts +++ b/packages/webpack5/src/helpers/platform.ts @@ -70,7 +70,7 @@ export function getPlatformName(): Platform { Available platforms: ${Object.keys(platforms).join(', ')} - Use --env=platform= or --env=android, --env=ios to specify the target platform. + Use --env.platform= or --env.android, --env.ios to specify the target platform. `); }