UNPKG

lincd-cli

Version:

Command line tools for the lincd.js library

185 lines 9.13 kB
/// <reference path="colors.d.ts" /> import colors from 'colors'; import fs from 'fs'; var exportRoot = '/lib'; var libraryName = 'lincd'; var lincdModules = new Map(); var excluded = new Set(); var includedInternals = new Set(); var excludedExternals = new Set(); var includedLincdModules = new Set(); //This function determines which modules that are requested by the module being built are external //it basically turns every import from a lincd module into a lookup for that class/object in the global lincd object //See also: https://webpack.js.org/configuration/externals/ var externaliseModules = function (config, es5) { function debug(...msgs) { msgs.unshift('externals: '); if (config && config.debug) { console.log.apply(null, msgs); } } function log(...msgs) { msgs.unshift('externals: '); console.log.apply(null, msgs); } // let externalKeys: string[] = config.externals ? Object.keys(config.externals) : []; //return the function that is handed to webpack in the 'externals' option. //it determines for each request what is external and what is not return function ({ context, request, contextInfo }, callback) { // debug('checking '+request); // debug('imported by '+contextInfo.issuer); if (config.externals && config.externals[request]) { if (!excludedExternals.has(request)) { excludedExternals.add(request); // debug(colors.magenta('Excluding request as defined in Gruntfile: ' + request)); debug(colors.red(request) + ' is defined as external --> excluded'); } // return callback(config.externals[request]); return callback(null, 'var ' + config.externals[request]); } //solution to a problem that turned out not to need a solution. // But if sub requests of externalized modules go wrong at some point, use this! /*let rootRequest = request.substring(0, request.indexOf('/')); if (externalKeys.indexOf(rootRequest) !== -1) { let key = rootRequest; let rest = request.substring(key.length).replace(/\//g, '.'); // return callback(config.externals[request]); debug( colors.magenta( 'Excluding sub request as defined in Gruntfile: ' + request + ' -> ' + config.externals[key] + rest, ), ); return callback(null, 'var ' + config.externals[request] + rest); }*/ //log(colors.gray(request)); //"@dacore/core/foo" => "daCore.core.foo" // if (/^\@dacore\//.test(request)) { //remove @dacore/ // if (request.indexOf('@dacore') !== 0) { // console.warn( // colors.red('this plugin currently works with @dacore modules only'), // ); // return; // } // debug(colors.green('request: ' + request)); if (request.substr(0, 1) == '.' || request.substr(0, 1) == '/') { // debug('skipping local'); callback(); return; } if (request.indexOf('lincd/') === 0 && es5) { // var result = request.replace("@dacore/core/","@dacore/core-es5/"); // debug('Requested ES6 for ES5 target: '+colors.yellow(request) + ' => ' + colors.cyan(result)); debug('Requested ES6 for ES5 target: ' + colors.yellow(request)); // return callback(null, 'commonjs '+result); } //get module name without @dacore // var transformed = request.substr(8); //find @scope and the next part between 2 slashes after //so @dacore/some-mod/lib/file.js // --> match[0] = @dacore/some-mod // --> match[1] = @dacore // --> match[2] = some-mod let [packageName, scope, cleanPackageName] = request.match(/(@[\w\-]+\/)?([\w\-]+)/); //if this module is listed as internal module in the config (or if we internalize all modules with '*') if (config && config.internals && (config.internals.indexOf(packageName) !== -1 || config.internals === '*')) { //then don't exclude and don't continue this function //only log once if (!includedInternals.has(packageName)) { includedInternals.add(packageName); debug(colors.blue(request) + ' marked internal --> included'); } return callback(); } //check if this module is a lincd module let isLincd = isLincdModule(debug, packageName); if (isLincd) { if (!includedLincdModules.has(packageName)) { includedLincdModules.add(packageName); debug(colors.magenta(packageName + ' is a lincd module, imports will be excluded from this bundle and refer to a global variable instead')); } } else { //avoid duplicate messages if (!excluded.has(packageName)) { excluded.add(packageName); debug(colors.green(packageName) + ' --> included'); } return callback(); } //remove export root path (for example with lincd/models: the module has lib/ as root, so to get to the exported path lincd.models we need to remove it) let cleanRequest = request.replace(exportRoot, ''); let targetVariable; //expects a flat export / global tree with all the modules classes //replace - by _ and remove es5, because both es6 and es5 modules will be listed under the bare module name in the global treemap let firstSlash = cleanRequest.indexOf('/'); //if importing {x} from "lincd" (so directly from library without any paths) if (firstSlash === -1 && cleanRequest == libraryName) { //then we refer straight to the global object targetVariable = libraryName; } else { //for all other cases, there is slash, so lets split module before the first slash and classname after the last slash // let module = cleanRequest // .substr(0, firstSlash) // .replace(/-/g, '_') // .replace('_es5', ''); if (packageName == libraryName) { //the library itself should directly expose the main class of each file for clean variable names targetVariable = libraryName; //targetVariable = libraryName + '.' + className; } else { //reading this back I'm not sure why module would be empty? //Note: we don't include className here anymore, since all linked Components/Utils register themselves as libraryName._modules.moduleName.ComponentName //and we don't do default exports, so the import would be `import {ComponentName} from 'foo'` OR `import {ComponentName} from 'foo/lib/components/ComponentName'` //Typescript then translates `ComponentName` to `ComponentName_1.ComponentName` in the javascript output //And when we build the tree, we put each individual exports of linked components directly under `lincd._modules.moduleName` //so here we return the entire module as the result of such imports //and ComponentName_1 will contain all things linked/exported by the module //and ComponentName_1.ComponentName resolves to the desired class/function targetVariable = libraryName + "._modules['" + packageName.replace(/\-/g, '_') + "']"; //import {PersonView} from 'lincd-test/lib/PersonView'; //lincd._modules.lincd_test //PersonView_1 //PersonView_1.PersonView --> lincd._modules.lincd_test.PersonView // targetVariable = // libraryName + // '.' + // (module ? '_modules.' + module + '.' : '') + // className; } } debug(colors.yellow(request) + ' => ' + colors.cyan(targetVariable)); //See also: https://webpack.js.org/configuration/externals/ return callback(null, 'var ' + targetVariable); // } }; }; function isLincdModule(debug, packageName) { if (!lincdModules.has(packageName)) { // debug(colors.green('checking ' + moduleName + '/package.json')); let isLincdModule; let modulePackage; try { modulePackage = JSON.parse(fs.readFileSync(packageName + '/package.json', 'utf8')); } catch (e) { debug(colors.red(packageName + '/package.json' + ' does not exist')); // return callback(); } isLincdModule = modulePackage && modulePackage.lincd && true; lincdModules.set(packageName, isLincdModule); } return lincdModules.get(packageName); } export default externaliseModules; //# sourceMappingURL=externalise-modules.js.map