UNPKG

3.27 kBJavaScriptView Raw
1#!/usr/bin/env node -r esm
2
3import { spawn } from 'child_process';
4import pkgUp from 'pkg-up';
5import { readFile, writeFile } from 'jsonfile';
6import dedent from 'ts-dedent';
7import chalk from 'chalk';
8
9const remainingFlags = process.argv.slice(2);
10
11const targets = ['storybook-chromatic', 'storybook-chroma'];
12
13const exec = (args, { pipe } = {}) => {
14 return new Promise((res, rej) => {
15 let output = '';
16 const child = spawn('npm', args);
17 const streamHandler = d => {
18 output += d.toString();
19 };
20 child.on('exit', code => {
21 if (code === 0) {
22 res(output);
23 } else {
24 rej(new Error(`${args.join(' ')} exited with code: ${code}`));
25 }
26 });
27
28 if (pipe) {
29 child.stdin.pipe(process.stdin);
30 child.stdout.pipe(process.stdout);
31 child.stderr.pipe(process.stderr);
32 } else {
33 child.stdout.on('data', streamHandler);
34 child.stderr.on('data', streamHandler);
35 }
36 });
37};
38
39const packageJson = {
40 async read() {
41 return pkgUp(__dirname).then(l => readFile(l));
42 },
43 async write(json) {
44 return pkgUp(__dirname).then(l => writeFile(l, json, { spaces: 2 }));
45 },
46};
47
48const publishAs = async name => {
49 const initial = await packageJson.read();
50
51 try {
52 const temp = { ...initial, name };
53 await packageJson.write(temp);
54 await exec(['publish', ...remainingFlags], { pipe: true });
55 } catch (e) {
56 //
57 } finally {
58 await packageJson.write(initial);
59 }
60};
61
62const check = {
63 async publishable(name, version) {
64 const text = await exec(['info', name, '--json']);
65 const json = JSON.parse(text);
66
67 const { versions } = json.data ? json.data : json;
68
69 return !versions.find(v => v === version);
70 },
71
72 async allowed(name) {
73 const user = (await exec(['whoami'])).trim();
74 const owners = JSON.parse(await exec(['access', 'ls-collaborators', name, '--json']));
75
76 return !!Object.entries(owners).find(
77 ([useName, permissions]) => useName.match(user) && permissions.includes('write')
78 );
79 },
80};
81
82const getUnpublishable = async list => {
83 const { version } = await packageJson.read();
84
85 return (await Promise.all(
86 list.map(async name => {
87 const versionOk = await check.publishable(name, version);
88 const ownershipOk = await check.allowed(name);
89
90 if (versionOk && ownershipOk) {
91 return false;
92 }
93
94 return { name, reason: versionOk ? 'ownership' : 'version' };
95 })
96 )).reduce((acc, item) => acc.concat(item || []), []);
97};
98
99const run = async list => {
100 const unpublishable = await getUnpublishable(list);
101
102 if (unpublishable.length === 0) {
103 targets.reduce(async (acc, item) => {
104 await acc;
105
106 await publishAs(item);
107 }, Promise.resolve());
108 } else {
109 console.log(dedent`
110 ${chalk.red('These packages cannot be published:')}
111
112 ${unpublishable
113 .map(
114 ({ name, reason }) =>
115 `${chalk.blue(name)} could not be published because of a ${chalk.bold(reason)} problem`
116 )
117 .join('\n')}
118
119 You may lack the required permissions on npm OR the version you're trying to publish already exists,
120 Upgrade the version or ask permission from current owners
121 `);
122 process.exitCode = 1;
123 }
124};
125
126run(targets);