All files / dist/helpers exports.js

80% Statements 40/50
65.38% Branches 17/26
85.71% Functions 6/7
94.87% Lines 37/39
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99    1x     1x 1x 1x   1x   1x   1x   1x   1x   1x                                   11x 11x 11x 5x 6x     6x         6x   6x     2x 8x       4x   4x 8x           4x       11x 11x       11x 11x 57x   57x   113x 41x 41x 32x   31x   1x             11x  
'use strict';
 
Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.collapseNamedExports = collapseNamedExports;
exports.extendDefaultExportWithNamedExports = extendDefaultExportWithNamedExports;
exports.filterOutExportsWhichMatchPropsOnDefault = filterOutExportsWhichMatchPropsOnDefault;
 
require('source-map-support/register');
 
var _babelTypes = require('babel-types');
 
var t = _interopRequireWildcard(_babelTypes);
 
var _templates = require('./templates');
 
var _ast = require('./ast');
 
function _interopRequireWildcard(obj) { Eif (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } }
 
/**
 * Collapse named exports onto the default export so that the default export can be returned directly,
 * so that exports can be easily used by code that does not include an import interop.
 * This includes the following:
 *  - Ignore named exports that already exist on the default export and which reference the same identifer.
 *  - If possible, assign any remaining exports to the default export.
 *    - This cannot be done if there is a naming conflict.
 *
 * In order to determine what properties the default export already has, the plugin will scan the
 * top level of the program to find any assignments, including Object.assign() and _extend() calls.
 * It does this recurively in the case of those method calls.
 *
 * If there are any named exports left, they get returned, so the main plugin can check the opts
 * and decide if an error should be thrown.
 */
function collapseNamedExports(programNode, defaultExportDeclaration, namedExports, opts) {
  namedExports = [...namedExports];
  namedExports = filterOutExportsWhichMatchPropsOnDefault(programNode, defaultExportDeclaration, namedExports);
  if (!namedExports.length) {
    return [];
  } else Iif (opts.noExportExtend) {
    return namedExports;
  } else {
    return extendDefaultExportWithNamedExports(programNode, defaultExportDeclaration, namedExports);
  }
}
 
function extendDefaultExportWithNamedExports(programNode, defaultExportDeclaration, namedExports) {
  namedExports = [...namedExports]; // Shallow clone for safe splicing
 
  if (!defaultExportDeclaration.name) {
    // Something anonymous
    //TODO see if we can give it a name
    return namedExports;
  } else Iif (namedExports.some(exp => exp.conflict)) {
    return namedExports.conflicts.filter(exp => exp.conflict);
  }
 
  const id = t.isIdentifier(defaultExportDeclaration) ? defaultExportDeclaration : t.identifier(defaultExportDeclaration.name);
 
  for (const namedExport of namedExports) {
    programNode.body.push((0, _templates.buildAssign)({
      OBJECT: id,
      NAME: namedExport.key,
      VALUE: namedExport.value
    }));
  }
  return [];
}
 
function filterOutExportsWhichMatchPropsOnDefault(programNode, defaultExportDeclaration, namedExports) {
  namedExports = [...namedExports]; // Shallow clone for safe splicing
  const defaultObjectProperties = (0, _ast.findPropertiesOfNode)(programNode, defaultExportDeclaration);
 
  // Loop through the default object's props and see if it already has a matching definition of the named exports.
  // If the definition matches, we can ignore the named export. If the definition does not match, mark it as a conflict.
  Eif (defaultObjectProperties) {
    for (const _ref of defaultObjectProperties) {
      const { key, value } = _ref;
 
      if (t.isIdentifier(value)) {
        //let matchingNamedExportIndex = -1
        const matchingNamedExportIndex = namedExports.findIndex(namedExport => namedExport.key.name === key.name);
        const matchingNamedExport = namedExports[matchingNamedExportIndex];
        if (matchingNamedExport) {
          if (value.name === matchingNamedExport.value.name) {
            // Safe to ignore
            namedExports.splice(matchingNamedExportIndex, 1);
          } else {
            namedExports.conflict = true;
          }
        }
      }
    }
  }
 
  return namedExports;
}