Skip to content

Commit

Permalink
Add possibility to configure how extensions should be loaded
Browse files Browse the repository at this point in the history
Fixes avajs#2345 by adding an object form for the `"extensions"` configuration.

This implementation:

1. if `"extensions"` is not defined uses the default module configuration for `mjs`, `cjs`, and `js`
2. generates the module types from the array form of the `extensions` configuration keeping the default module type for `mjs`, `cjs`, and `js` if they're defined and uses `"commonjs"` for everything else, thus maintaining backwords compatibility.
3. generates the module types from the object form of the `extensions` configuration and prevents changing the module type for `mjs`, `cjs`, and `js` extensions (for `js` the `"type"` field cannot be overridden).
  • Loading branch information
macarie committed Jul 14, 2020
1 parent 07602f5 commit 66e85df
Show file tree
Hide file tree
Showing 3 changed files with 71 additions and 7 deletions.
14 changes: 8 additions & 6 deletions lib/cli.js
Original file line number Diff line number Diff line change
Expand Up @@ -267,6 +267,7 @@ exports.run = async () => { // eslint-disable-line complexity
const TapReporter = require('./reporters/tap');
const Watcher = require('./watcher');
const normalizeExtensions = require('./extensions');
const normalizeModuleTypes = require('./module-types');
const {normalizeGlobs, normalizePattern} = require('./globs');
const normalizeNodeArguments = require('./node-arguments');
const validateEnvironmentVariables = require('./environment-variables');
Expand All @@ -284,12 +285,6 @@ exports.run = async () => { // eslint-disable-line complexity

const {type: defaultModuleType = 'commonjs'} = pkg || {};

const moduleTypes = {
cjs: 'commonjs',
mjs: 'module',
js: defaultModuleType
};

const providers = [];
if (Reflect.has(conf, 'babel')) {
try {
Expand Down Expand Up @@ -331,6 +326,13 @@ exports.run = async () => { // eslint-disable-line complexity
exit(error.message);
}

let moduleTypes;
try {
moduleTypes = normalizeModuleTypes(conf.extensions, defaultModuleType);
} catch (error) {
exit(error.message);
}

let globs;
try {
globs = normalizeGlobs({files: conf.files, ignoredByWatcher: conf.ignoredByWatcher, extensions, providers});
Expand Down
13 changes: 12 additions & 1 deletion lib/extensions.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,19 @@ module.exports = (configuredExtensions, providers = []) => {
// Combine all extensions possible for testing. Remove duplicate extensions.
const duplicates = new Set();
const seen = new Set();

const getArrayOfExtensions = extensions => {
if (Array.isArray(extensions)) {
return extensions;
}

return Object.keys(extensions);
};

const combine = extensions => {
for (const ext of extensions) {
const extensionsArray = getArrayOfExtensions(extensions);

for (const ext of extensionsArray) {
if (seen.has(ext)) {
duplicates.add(ext);
} else {
Expand Down
51 changes: 51 additions & 0 deletions lib/module-types.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
module.exports = (configuredExtensions, defaultModuleType) => {
const lockedModuleTypes = {
cjs: 'commonjs',
mjs: 'module',
js: defaultModuleType
};

const createModuleTypesFromExtensionsObject = extensionsObject => {
const configuredModuleTypes = {};

for (const [extension, type] of Object.entries(extensionsObject)) {
if (extension in lockedModuleTypes && type !== lockedModuleTypes[extension]) {
throw new TypeError(`.${extension} files can only be configured as ’${lockedModuleTypes[extension]}${
extension === 'js' ?
` when the nearest parent package.json ${type === 'module' ? 'does not contain' : 'contains'} "type": "module"` : ''
}, found ’${type}’ instead.`);
}

configuredModuleTypes[extension] = type;
}

return configuredModuleTypes;
};

const createModuleTypesFromExtensionsArray = extensions => {
const generatedModuleTypes = {};

for (const extension of extensions) {
if (extension in lockedModuleTypes) {
generatedModuleTypes[extension] = lockedModuleTypes[extension];
} else {
generatedModuleTypes[extension] = 'commonjs';
}
}

return generatedModuleTypes;
};

let moduleTypes;
if (configuredExtensions === undefined) {
moduleTypes = {
...lockedModuleTypes
};
} else if (Array.isArray(configuredExtensions)) {
moduleTypes = createModuleTypesFromExtensionsArray(configuredExtensions);
} else {
moduleTypes = createModuleTypesFromExtensionsObject(configuredExtensions);
}

return moduleTypes;
};

0 comments on commit 66e85df

Please sign in to comment.