const path = require('path'); const fs = require('fs-extra'); const fse = require('fs-extra'); const shell = require('shelljs'); const glob = require('glob'); const symlink = require('symlink-dir'); const log = require('npmlog'); const targetPath = path.join(__dirname, '..', 'node_modules', '@storybook'); const prefix = 'hoist-internals'; const cwd = path.join(__dirname, '..'); log.heading = 'lerna+'; log.addLevel('success', 3001, { fg: 'green', bold: true }); log.info(prefix, 'Hoisting internal packages'); const getLernaPackages = () => fse.readJson(path.join(__dirname, '..', 'lerna.json')).then(json => json.packages); const passingLog = fn => i => { fn(i); return i; }; const getPackageNameOfFolder = sourcePath => fse .readJson(path.join(sourcePath, 'package.json')) .then(json => json.name.replace('@storybook/', '')); const task = getLernaPackages() .then( passingLog(packages => { log.verbose(prefix, 'working dir paths: %j', cwd); log.verbose(prefix, 'source paths: %j', packages); log.verbose(prefix, 'target paths: %j', targetPath); }) ) .then(packages => `@(${packages.map(s => s.replace('/*', '')).join('|')})/*/`) .then( passingLog(pattern => { log.silly(prefix, 'pattern to look for packages: %j', pattern); }) ) .then( pattern => new Promise((resolve, reject) => { glob(pattern, { cwd }, (error, results) => (error ? reject(error) : resolve(results))); }) ) .then(results => Promise.all( results .map(sourcePath => path.resolve(fs.realpathSync(sourcePath))) .reduce((acc, item) => { if (!acc.includes(item)) { acc.push(item); } return acc; }, []) .map( passingLog(item => { log.silly(prefix, 'found package path', item); }) ) .map(sourcePath => getPackageNameOfFolder(sourcePath) .then( passingLog(packageName => { log.silly(prefix, 'found package name', packageName); }) ) .then(packageName => path.join(targetPath, packageName)) .then(localTargetPath => symlink(sourcePath, localTargetPath) .then( passingLog(() => { log.silly(prefix, 'symlinked ', [sourcePath, localTargetPath]); }) ) .then(() => localTargetPath) .catch(error => { log.error(prefix, 'symlink', error); throw new Error('failed symlink'); }) ) ) ) ) .then(locations => Promise.all( locations .map(location => path.join(location, 'node_modules', '@storybook')) .map( passingLog(removePath => { log.verbose(prefix, 'removing ', removePath); }) ) .map(removePath => shell.rm('-rf', removePath)) .map( (item, index) => item.code === 0 ? Promise.resolve(locations[index]) : Promise.reject(item) ) ) ); task .then(packages => { log.info(prefix, packages.map(dir => dir.replace(cwd, '')).join(',\n')); log.success(prefix, 'complete'); }) .catch(error => { log.error(prefix, 'failed', error); shell.exit(1); });