const glob = require('glob'); const {getOptions} = require('loader-utils'); const path = require('path'); const validateOptions = require('schema-utils'); const schema = { type: 'object', properties: { paths: { items: { type: 'string', }, type: 'array', }, registrar: { type: 'object', properties: { function: { type: 'string', }, module: { type: 'string', }, }, required: [ 'function', 'module', ], }, type: { type: 'string', }, }, required: [ 'registrar', 'type', ], }; // Dynamically require all traits. module.exports = function(source) { const options = getOptions(this); // Validate schema. validateOptions(schema, options, 'Avocado defgen'); // Extract options. const {paths, registrar, type} = options; // Search avocado. options.paths.push(path.resolve( __dirname, 'node_modules', '@avocado', )); // Get all trait source paths. const sourcePaths = []; paths.forEach((path) => { const files = glob.sync(`${path}/**/*.${type}.js`, { follow: true, }); sourcePaths.push(...files); }); // Build import definitions. const importDefinitions = sourcePaths.map((sourcePath) => { const relativePath = path.relative(__dirname, sourcePath); const basename = path.basename(relativePath, `.${type}.js`); const parts = relativePath.split('/'); // Chop off basename. parts.pop(); // Module or local? let importDirectory; if ('node_modules' === parts[0]) { importDirectory = `${parts.slice(1).join('/')}`; } else { importDirectory = `./${parts.join('/')}` } const importPath = `${importDirectory}/${basename}.${type}`; // Extract class name. const baseparts = basename.split('-'); const className = baseparts.reduce((className, part) => { const firstLetter = part.charAt(0).toUpperCase(); const rest = part.substr(1).toLowerCase(); return className + firstLetter + rest; }, ''); // Import and register. return [ `import {${className}} from '${importPath}';`, `${registrar.function}(${className});`, ].join('\n'); }); // Import trait registry first. return [ `import {${registrar.function}} from '${registrar.module}'`, '', ...importDefinitions ].join('\n'); }