def find_node_module_pkg_name(self, toolchain, spec): # since most loaders end with this suffix, test for that first if self.name.endswith('-loader'): return self.name # given that there will be packages that could have been # installed that matches the package name, test for the common # prefix first name = self.name + '-loader' # using the same working_dir derivation method as parent working_dir = spec.get(WORKING_DIR, toolchain.join_cwd()) if locate_package_entry_file(working_dir, name): return name elif locate_package_entry_file(working_dir, self.name): return self.name # a value must be provided, but to not confuse with the # resolution of the real package, return the suffixed version return name
def test_locate_package_entry_module_not_found(self): working_dir = mkdtemp(self) pkg_name = 'demo' with pretty_logging(stream=StringIO()) as stream: self.assertIsNone( npm.locate_package_entry_file(working_dir, pkg_name)) self.assertIn( "could not locate package.json for the npm package 'demo' " "in the current working directory '%s'" % working_dir, stream.getvalue(), )
def test_plugin_package_success_browser(self): working_dir = mkdtemp(self) pkg_name = 'demo' pkg_dir = join(working_dir, 'node_modules', pkg_name) makedirs(pkg_dir) with open(join(pkg_dir, 'package.json'), 'w') as fd: fd.write('{"browser": "browser/index.js"}') with pretty_logging(stream=StringIO(), level=DEBUG) as stream: self.assertEqual( join(pkg_dir, 'browser', 'index.js'), npm.locate_package_entry_file(working_dir, pkg_name), ) self.assertEqual("", stream.getvalue())
def test_plugin_package_success_implied_index_js(self): working_dir = mkdtemp(self) pkg_name = 'demo' pkg_dir = join(working_dir, 'node_modules', pkg_name) makedirs(pkg_dir) with open(join(pkg_dir, 'package.json'), 'w') as fd: fd.write('{}') with open(join(pkg_dir, 'index.js'), 'w') as fd: fd.write('(function () { return {} })();') with pretty_logging(stream=StringIO(), level=DEBUG) as stream: self.assertEqual( join(pkg_dir, 'index.js'), npm.locate_package_entry_file(working_dir, pkg_name), ) self.assertEqual("", stream.getvalue())
def test_plugin_package_missing_required_entries(self): working_dir = mkdtemp(self) pkg_name = 'demo' pkg_dir = join(working_dir, 'node_modules', pkg_name) makedirs(pkg_dir) with open(join(pkg_dir, 'package.json'), 'w') as fd: fd.write('{}') with pretty_logging(stream=StringIO(), level=DEBUG) as stream: self.assertIsNone( npm.locate_package_entry_file(working_dir, pkg_name)) self.assertIn( "package.json for the npm package 'demo' does not " "contain a main entry point", stream.getvalue(), )
def generate_handler_sourcepath( self, toolchain, spec, loaderplugin_sourcepath): """ Attempt to locate the plugin source; returns a mapping of modnames to the absolute path of the located sources. """ # TODO calmjs-4.0.0 consider formalizing to the method instead npm_pkg_name = ( self.node_module_pkg_name if self.node_module_pkg_name else self.find_node_module_pkg_name(toolchain, spec) ) if not npm_pkg_name: cls = type(self) registry_name = getattr( self.registry, 'registry_name', '<invalid_registry/handler>') if cls is NPMLoaderPluginHandler: logger.error( "no npm package name specified or could be resolved for " "loaderplugin '%s' of registry '%s'; please subclass " "%s:%s such that the npm package name become specified", self.name, registry_name, cls.__module__, cls.__name__, ) else: logger.error( "no npm package name specified or could be resolved for " "loaderplugin '%s' of registry '%s'; implementation of " "%s:%s may be at fault", self.name, registry_name, cls.__module__, cls.__name__, ) return {} working_dir = spec.get(WORKING_DIR, None) if working_dir is None: logger.info( "attempting to derive working directory using %s, as the " "provided spec is missing working_dir", toolchain ) working_dir = toolchain.join_cwd() logger.debug("deriving npm loader plugin from '%s'", working_dir) target = locate_package_entry_file(working_dir, npm_pkg_name) if target: logger.debug('picked %r for loader plugin %r', target, self.name) # use the parent recursive lookup. result = super( NPMLoaderPluginHandler, self).generate_handler_sourcepath( toolchain, spec, loaderplugin_sourcepath) result.update({self.name: target}) return result # the expected package file is not found, use the logger to show # why. # Also note that any inner/chained loaders will be dropped. if exists(join( working_dir, 'node_modules', npm_pkg_name, 'package.json')): logger.warning( "'package.json' for the npm package '%s' does not contain a " "valid entry point: sources required for loader plugin '%s' " "cannot be included automatically; the build process may fail", npm_pkg_name, self.name, ) else: logger.warning( "could not locate 'package.json' for the npm package '%s' " "which was specified to contain the loader plugin '%s' in the " "current working directory '%s'; the missing package may " "be installed by running 'npm install %s' for the mean time " "as a workaround, though the package that owns that source " "file that has this requirement should declare an explicit " "dependency; the build process may fail", npm_pkg_name, self.name, working_dir, npm_pkg_name, ) return {}