2020-05-09 11:34:50 +02:00
|
|
|
import { exec } from 'child_process';
|
2019-04-25 00:00:10 +02:00
|
|
|
import chalk from 'chalk';
|
2020-05-09 11:34:50 +02:00
|
|
|
import path from 'path';
|
|
|
|
import program from 'commander';
|
2019-04-25 00:00:10 +02:00
|
|
|
import detectFreePort from 'detect-port';
|
2019-09-27 14:53:07 +02:00
|
|
|
import dedent from 'ts-dedent';
|
2019-06-03 20:26:24 +02:00
|
|
|
import fs from 'fs';
|
2020-05-09 11:34:50 +02:00
|
|
|
import yaml from 'js-yaml';
|
2019-04-25 00:00:10 +02:00
|
|
|
import nodeCleanup from 'node-cleanup';
|
|
|
|
|
2020-05-09 11:34:50 +02:00
|
|
|
import startVerdaccioServer from 'verdaccio';
|
|
|
|
import pLimit from 'p-limit';
|
2020-09-19 17:36:02 +02:00
|
|
|
// @ts-ignore
|
|
|
|
import { maxConcurrentTasks } from './utils/concurrency';
|
2020-05-18 22:29:50 +02:00
|
|
|
import { listOfPackages, Package } from './utils/list-packages';
|
2019-04-25 11:44:33 +02:00
|
|
|
|
2020-05-09 11:34:50 +02:00
|
|
|
program
|
|
|
|
.option('-O, --open', 'keep process open')
|
|
|
|
.option('-P, --publish', 'should publish packages')
|
|
|
|
.option('-p, --port <port>', 'port to run https server on');
|
2019-04-25 00:00:10 +02:00
|
|
|
|
2020-05-09 11:34:50 +02:00
|
|
|
program.parse(process.argv);
|
|
|
|
|
|
|
|
const logger = console;
|
|
|
|
|
2020-05-18 14:58:55 +02:00
|
|
|
const freePort = (port?: number) => port || detectFreePort(port);
|
2019-04-25 11:44:33 +02:00
|
|
|
|
2020-05-18 14:58:55 +02:00
|
|
|
const startVerdaccio = (port: number) => {
|
2019-04-25 00:00:10 +02:00
|
|
|
let resolved = false;
|
2019-06-03 20:26:24 +02:00
|
|
|
return Promise.race([
|
2020-05-09 11:34:50 +02:00
|
|
|
new Promise((resolve) => {
|
|
|
|
const cache = path.join(__dirname, '..', '.verdaccio-cache');
|
|
|
|
const config = {
|
|
|
|
...yaml.safeLoad(fs.readFileSync(path.join(__dirname, 'verdaccio.yaml'), 'utf8')),
|
|
|
|
self_path: cache,
|
|
|
|
};
|
|
|
|
|
2020-05-18 15:09:22 +02:00
|
|
|
const onReady = (webServer: any) => {
|
2020-05-09 11:34:50 +02:00
|
|
|
webServer.listen(port, () => {
|
2019-06-03 20:26:24 +02:00
|
|
|
resolved = true;
|
2020-05-09 11:34:50 +02:00
|
|
|
resolve(webServer);
|
2019-06-03 20:26:24 +02:00
|
|
|
});
|
2020-05-09 11:34:50 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
startVerdaccioServer(config, 6000, cache, '1.0.0', 'verdaccio', onReady);
|
2019-06-03 20:26:24 +02:00
|
|
|
}),
|
2020-05-18 22:29:50 +02:00
|
|
|
new Promise((_, rej) => {
|
2019-06-03 20:26:24 +02:00
|
|
|
setTimeout(() => {
|
|
|
|
if (!resolved) {
|
|
|
|
resolved = true;
|
2020-05-09 11:34:50 +02:00
|
|
|
rej(new Error(`TIMEOUT - verdaccio didn't start within 60s`));
|
2019-06-03 20:26:24 +02:00
|
|
|
}
|
|
|
|
}, 60000);
|
|
|
|
}),
|
|
|
|
]);
|
2019-04-25 00:00:10 +02:00
|
|
|
};
|
2020-05-18 15:09:22 +02:00
|
|
|
const registryUrl = (command: string, url?: string) =>
|
|
|
|
new Promise<string>((res, rej) => {
|
2019-04-25 00:00:10 +02:00
|
|
|
const args = url ? ['config', 'set', 'registry', url] : ['config', 'get', 'registry'];
|
|
|
|
exec(`${command} ${args.join(' ')}`, (e, stdout) => {
|
|
|
|
if (e) {
|
|
|
|
rej(e);
|
|
|
|
} else {
|
|
|
|
res(url || stdout.toString().trim());
|
|
|
|
}
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
2020-05-18 15:09:22 +02:00
|
|
|
const registriesUrl = (yarnUrl?: string, npmUrl?: string) =>
|
2019-04-25 00:00:10 +02:00
|
|
|
Promise.all([registryUrl('yarn', yarnUrl), registryUrl('npm', npmUrl || yarnUrl)]);
|
|
|
|
|
2020-05-18 14:58:55 +02:00
|
|
|
const applyRegistriesUrl = (
|
|
|
|
yarnUrl: string,
|
|
|
|
npmUrl: string,
|
|
|
|
originalYarnUrl: string,
|
|
|
|
originalNpmUrl: string
|
|
|
|
) => {
|
2019-04-25 11:44:33 +02:00
|
|
|
logger.log(`↪️ changing system config`);
|
2019-04-25 00:00:10 +02:00
|
|
|
nodeCleanup(() => {
|
|
|
|
registriesUrl(originalYarnUrl, originalNpmUrl);
|
|
|
|
|
2019-09-27 14:53:07 +02:00
|
|
|
logger.log(dedent`
|
2019-04-25 00:00:10 +02:00
|
|
|
Your registry config has been restored from:
|
|
|
|
npm: ${npmUrl} to ${originalNpmUrl}
|
|
|
|
yarn: ${yarnUrl} to ${originalYarnUrl}
|
|
|
|
`);
|
|
|
|
});
|
|
|
|
|
|
|
|
return registriesUrl(yarnUrl, npmUrl);
|
|
|
|
};
|
|
|
|
|
|
|
|
const currentVersion = async () => {
|
|
|
|
const { version } = (await import('../lerna.json')).default;
|
|
|
|
return version;
|
|
|
|
};
|
|
|
|
|
2020-05-18 14:58:55 +02:00
|
|
|
const publish = (packages: { name: string; location: string }[], url: string) => {
|
2020-11-03 21:11:30 +01:00
|
|
|
logger.log(`Publishing packages with a concurrency of ${maxConcurrentTasks}`);
|
|
|
|
|
2020-09-19 17:36:02 +02:00
|
|
|
const limit = pLimit(maxConcurrentTasks);
|
2020-09-14 22:20:57 +02:00
|
|
|
let i = 0;
|
2020-05-09 11:34:50 +02:00
|
|
|
|
|
|
|
return Promise.all(
|
|
|
|
packages.map(({ name, location }) =>
|
|
|
|
limit(
|
|
|
|
() =>
|
|
|
|
new Promise((res, rej) => {
|
|
|
|
logger.log(`🛫 publishing ${name} (${location})`);
|
|
|
|
const command = `cd ${location} && npm publish --registry ${url} --force --access restricted`;
|
|
|
|
exec(command, (e) => {
|
|
|
|
if (e) {
|
|
|
|
rej(e);
|
|
|
|
} else {
|
2020-09-14 22:20:57 +02:00
|
|
|
i += 1;
|
|
|
|
logger.log(`${i}/${packages.length} 🛬 successful publish of ${name}!`);
|
2020-11-26 10:58:09 +01:00
|
|
|
res(undefined);
|
2020-05-09 11:34:50 +02:00
|
|
|
}
|
|
|
|
});
|
|
|
|
})
|
|
|
|
)
|
|
|
|
)
|
|
|
|
);
|
|
|
|
};
|
2019-04-25 00:00:10 +02:00
|
|
|
|
|
|
|
const run = async () => {
|
2020-05-09 11:34:50 +02:00
|
|
|
const port = await freePort(program.port);
|
2019-04-25 11:44:33 +02:00
|
|
|
logger.log(`🌏 found a open port: ${port}`);
|
2019-04-25 00:00:10 +02:00
|
|
|
|
2020-05-09 11:34:50 +02:00
|
|
|
const verdaccioUrl = `http://localhost:${port}`;
|
|
|
|
|
2019-04-25 11:44:33 +02:00
|
|
|
logger.log(`🔖 reading current registry settings`);
|
2019-04-25 00:00:10 +02:00
|
|
|
let [originalYarnRegistryUrl, originalNpmRegistryUrl] = await registriesUrl();
|
|
|
|
if (
|
|
|
|
originalYarnRegistryUrl.includes('localhost') ||
|
|
|
|
originalNpmRegistryUrl.includes('localhost')
|
|
|
|
) {
|
|
|
|
originalYarnRegistryUrl = 'https://registry.npmjs.org/';
|
|
|
|
originalNpmRegistryUrl = 'https://registry.npmjs.org/';
|
|
|
|
}
|
|
|
|
|
2019-04-25 11:44:33 +02:00
|
|
|
logger.log(`📐 reading version of storybook`);
|
|
|
|
logger.log(`🚛 listing storybook packages`);
|
2020-05-09 11:34:50 +02:00
|
|
|
logger.log(`🎬 starting verdaccio (this takes ±5 seconds, so be patient)`);
|
2019-04-25 00:00:10 +02:00
|
|
|
|
2020-05-18 22:29:50 +02:00
|
|
|
const [verdaccioServer, packages, version] = await Promise.all<any, Package[], string>([
|
2019-04-25 00:00:10 +02:00
|
|
|
startVerdaccio(port),
|
|
|
|
listOfPackages(),
|
|
|
|
currentVersion(),
|
|
|
|
]);
|
|
|
|
|
2019-04-25 11:44:33 +02:00
|
|
|
logger.log(`🌿 verdaccio running on ${verdaccioUrl}`);
|
2019-04-25 00:00:10 +02:00
|
|
|
|
2020-05-09 11:34:50 +02:00
|
|
|
await applyRegistriesUrl(
|
|
|
|
verdaccioUrl,
|
|
|
|
verdaccioUrl,
|
|
|
|
originalYarnRegistryUrl,
|
|
|
|
originalNpmRegistryUrl
|
|
|
|
);
|
2019-04-25 00:00:10 +02:00
|
|
|
|
2020-05-09 11:34:50 +02:00
|
|
|
// await addUser(verdaccioUrl);
|
2019-04-25 00:00:10 +02:00
|
|
|
|
2020-05-09 11:34:50 +02:00
|
|
|
logger.log(`📦 found ${packages.length} storybook packages at version ${chalk.blue(version)}`);
|
2019-04-25 00:00:10 +02:00
|
|
|
|
2020-05-09 11:34:50 +02:00
|
|
|
if (program.publish) {
|
|
|
|
await publish(packages, verdaccioUrl);
|
2019-04-25 00:00:10 +02:00
|
|
|
}
|
|
|
|
|
2020-05-09 11:34:50 +02:00
|
|
|
if (!program.open) {
|
|
|
|
verdaccioServer.close();
|
2019-04-25 11:44:33 +02:00
|
|
|
}
|
2019-04-25 00:00:10 +02:00
|
|
|
};
|
|
|
|
|
2020-05-09 11:34:50 +02:00
|
|
|
run().catch((e) => {
|
|
|
|
logger.error(e);
|
|
|
|
process.exit(1);
|
|
|
|
});
|