Skip to content
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
128 changes: 108 additions & 20 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,20 +13,22 @@ const WebpackConfig = require('./lib/WebpackConfig');
const configGenerator = require('./lib/config-generator');
const validator = require('./lib/config/validator');
const PrettyError = require('pretty-error');
const runtimeConfig = require('./lib/context').runtimeConfig;
const logger = require('./lib/logger');
const parseRuntime = require('./lib/config/parse-runtime');

// at this time, the encore executable should have set the runtimeConfig
if (!runtimeConfig) {
throw new Error('Are you trying to require index.js directly?');
}
let webpackConfig = null;
let runtimeConfig = require('./lib/context').runtimeConfig;

let webpackConfig = new WebpackConfig(runtimeConfig);
if (runtimeConfig.verbose) {
logger.verbose();
// If runtimeConfig is already set webpackConfig can directly
// be initialized here.
if (runtimeConfig) {
webpackConfig = new WebpackConfig(runtimeConfig);
if (runtimeConfig.verbose) {
logger.verbose();
}
}

module.exports = {
const publicApi = {
/**
* The directory where your files should be output.
*
Expand Down Expand Up @@ -431,17 +433,9 @@ module.exports = {
* @returns {*}
*/
getWebpackConfig() {
try {
validator(webpackConfig);
validator(webpackConfig);

return configGenerator(webpackConfig);
} catch (error) {
// prettifies errors thrown by our library
const pe = new PrettyError();

console.log(pe.render(error));
process.exit(1); // eslint-disable-line
}
return configGenerator(webpackConfig);
},

/**
Expand All @@ -454,5 +448,99 @@ module.exports = {
*/
reset() {
webpackConfig = new WebpackConfig(runtimeConfig);
}
},

/**
* Initialize the runtime environment.
*
* It can be used to directly manipulate the Encore API without
* executing the "./node_module/.bin/encore" utility.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This can be used to configure the Encore runtime if you're using Encore
without executing the "./node_module/.bin/encore" utility (e.g. with karma-webpack).

*
* Encore.configureRuntimeEnvironment(
* // Environment to use (dev, dev-server, production)
* 'dev-server',
*
* // Same options you would use with the
* // CLI utility with their name in
* // camelCase.
* {
* https: true,
* keepPublicPath: true
* }
* )
*
* Be aware than using this method will also reset the current
* webpack configuration.
*
* @param {string} environment
* @param {object} options
* @returns {exports}
*/
configureRuntimeEnvironment(environment, options = {}) {
runtimeConfig = parseRuntime(
Object.assign(
{},
require('yargs/yargs')([environment]).argv,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure I understand this. Is there a need to continue to read the command line options? The command line options could be totally different (since there is a different executable being run).

I see that parseRuntime() looks for argv._[0] for the environment/command. Is that what you're trying to supply here? If so, I think we could set that manually - e.g. options._ = [environment]. Or, we could re-work parse-runtime.js so that the argv._[0] is actually done in encore.js and parse-runtime looked like function(command, options, cwd) {.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I added that part to make sure that the first parameter passed to parseRuntime had the same structure than the one usually supplied by yargs, it doesn't actually keep reading the CLI options since we provide a fake process.argv (see https://github.com/yargs/yargs/blob/master/docs/api.md#api).

I did options._ = [environment] at first but switched to calling the API after realizing that yargs adds other things to the argv array that may be used later by parseRuntime (e.g.: $0)

options
),
process.cwd()
);

if (runtimeConfig.verbose) {
logger.verbose();
}

webpackConfig = new WebpackConfig(runtimeConfig);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since this (and the logger lines) above are repeated at the top of the file, let's warp these in some function (i.e. some simple function initializeWebpackConfig() at the top of the file) that we call in both places...


return this;
},

/**
* Clear the runtime environment.
*
* Be aware than using this method will also reset the
* current webpack configuration.
*
* @returns {void}
*/
clearRuntimeEnvironment() {
runtimeConfig = null;
webpackConfig = null;
},
};

// Proxy the API in order to prevent calls to most of its methods
// if the webpackConfig object hasn't been initialized yet.
const publicApiProxy = new Proxy(publicApi, {
get: (target, prop) => {
if (typeof target[prop] === 'function') {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It shouldn't be possible, but what about the else of this function?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep, I missed that part, I added a return target[prop] just in case.

// These methods of the public API can be called even if the
// webpackConfig object hasn't been initialized yet.
const safeMethods = [
'configureRuntimeEnvironment',
'clearRuntimeEnvironment',
];

if (!webpackConfig && (safeMethods.indexOf(prop) === -1)) {
throw new Error(`Encore.${prop}() cannot be called yet because the runtime environment doesn't appear to be configured. Try calling Encore.configureRuntimeEnvironment() first.`);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Something like:

Encore.${prop}() cannot be called yet because the runtime environment doesn't appear to be configured. Make sure you're using the encore executable or call Encore.configureRuntimeEnvironment() first if you're purposely not calling Encore directly.

A little long, but I still want to make sure people aren't making a mistake first.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

that message brought me here today, that was shown by phpstorm :)

} else {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

no need for the else here, since you properly explode above :)

// Either a safe method has been called or the webpackConfig
// object is already available. In this case act as a passthrough.
return (...parameters) => {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's the purpose of the ...parameters here?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's needed in order to pass all the parameters to the real method: const res = target[prop](...parameters);

// Real API method
const inner = (param1, param2) => {
    console.log(`param1 = ${param1}`);
    console.log(`param2 = ${param2}`);
};

// Method returned by the proxy
const wrapper = (...parameters) => {
    inner(...parameters);
};

wrapper(1, 2);

// Output:
// param1 = 1
// param2 = 2

try {
const res = target[prop](...parameters);
return (res === target) ? publicApiProxy : res;
} catch (error) {
// prettifies errors thrown by our library
const pe = new PrettyError();

console.log(pe.render(error));
process.exit(1); // eslint-disable-line
}
};
}
}
}
});

module.exports = publicApiProxy;
Loading