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', }, }, required: [ 'paths', ], }; // Dynamically require all traits. module.exports = function(source) { const options = getOptions(this); // Validate schema. validateOptions(schema, options, 'Avocado hooks'); // Extract options. const {paths} = options; // Search avocado. const avocadoPath = path.normalize( path.join(__dirname, '..', '..'), ); paths.push(avocadoPath); // Get source paths. const sourcePaths = []; paths.forEach((path) => { const files = glob.sync(`${path}/**/hooks.js`, { follow: true, }); sourcePaths.push(...files); }); // Build registers. const registers = sourcePaths.map((sourcePath) => { const relativePath = path.relative(__dirname, sourcePath); const basename = path.basename(relativePath, '.js'); const parts = relativePath.split('/'); // Chop off basename. parts.pop(); // Module or local? let importDirectory; if ('..' === parts[0]) { const avocadoPathParts = ['@avocado', 'core', 'hook'].concat(parts); importDirectory = path.normalize(avocadoPathParts.join('/')); } else if ('node_modules' === parts[0]) { importDirectory = parts.slice(1).join('/'); } else { importDirectory = `./${parts.join('/')}`; } // Register hooks. const importPath = `${importDirectory}/hooks`; return [ `registerHooks('${importDirectory}', require('${importPath}'));`, ].join('\n'); }); // Import trait registry first. const output = [ `import {registerHooks} from '@avocado/core/hook/registry'`, '', ...registers ].join('\n'); return output; }