|
| 1 | +#!/usr/bin/env node |
| 2 | +const fetch = require('node-fetch') |
| 3 | +const minimist = require('minimist') |
| 4 | +const {basename} = require('path') |
| 5 | +const {green, red, yellow} = require('colorette') |
| 6 | + |
| 7 | +const {versionDeprecations} = require('../deprecations') |
| 8 | +const X = red('𐄂') |
| 9 | +const I = yellow('i') |
| 10 | +const V = green('✓') |
| 11 | + |
| 12 | +const args = minimist(process.argv.slice(2)) |
| 13 | +if (args.help) { |
| 14 | + console.log(` |
| 15 | +script/${basename(__filename)} [options] |
| 16 | +
|
| 17 | + --version <version> The published version of @primer/css from which to |
| 18 | + fetch CSS selector stats; default: "latest". |
| 19 | + --bundle <bundle> The CSS bundle to compare; default: "primer". |
| 20 | +
|
| 21 | +Fetches the CSS selectors for the published package and checks that: |
| 22 | +
|
| 23 | +1. All selectors listed in deprecations.js for the current local version (in |
| 24 | + package.json) have been deleted. |
| 25 | +2. All selectors deleted in the current local version have been listed in |
| 26 | + deprecations.js. |
| 27 | +
|
| 28 | +If either check fails, the process exits with an error status (1). |
| 29 | +`) |
| 30 | + process.exit(0) |
| 31 | +} |
| 32 | + |
| 33 | +checkDeprecations(args) |
| 34 | + |
| 35 | +async function checkDeprecations(options = {}) { |
| 36 | + const {bundle = 'primer', version = 'latest'} = options |
| 37 | + |
| 38 | + const currentVersion = require('../package.json').version |
| 39 | + const statsPath = `dist/stats/${bundle}.json` |
| 40 | + |
| 41 | + const local = require(`../${statsPath}`) |
| 42 | + const remote = await fetch(`https://unpkg.com/@primer/css@${version}/${statsPath}`).then(res => res.json()) |
| 43 | + |
| 44 | + const {changed, added, removed} = diffLists(remote.selectors.values, local.selectors.values) |
| 45 | + if (changed === 0) { |
| 46 | + console.log(`no selectors added or removed in bundle "${bundle}"`) |
| 47 | + return |
| 48 | + } |
| 49 | + |
| 50 | + const deprecations = versionDeprecations[currentVersion] || [] |
| 51 | + const deprecatedSelectors = deprecations.reduce((list, deprecation) => list.concat(deprecation.selectors), []) |
| 52 | + console.log(`${I} ${removed.length} selectors removed locally (compared with ${version})`) |
| 53 | + console.log(`${I} ${deprecatedSelectors.length} selectors deprecated in v${currentVersion}`) |
| 54 | + if (added.length) { |
| 55 | + console.log(`${I} ${added.length} selectors added`) |
| 56 | + } |
| 57 | + |
| 58 | + const errors = [] |
| 59 | + for (const deprecation of deprecations) { |
| 60 | + for (const selector of deprecation.selectors) { |
| 61 | + if (!removed.includes(selector)) { |
| 62 | + const error = `"${selector}" deprecated, but not removed` |
| 63 | + errors.push(error) |
| 64 | + console.log(`${X} ${error}`) |
| 65 | + } else { |
| 66 | + console.log(`${V} "${selector}" is deprecated!`) |
| 67 | + } |
| 68 | + deprecatedSelectors.push(selector) |
| 69 | + } |
| 70 | + } |
| 71 | + |
| 72 | + for (const removedSelector of removed) { |
| 73 | + if (!deprecatedSelectors.includes(removedSelector)) { |
| 74 | + const error = `"${removedSelector}" has been removed, but was not listed in versionDeprecations['${currentVersion}']` |
| 75 | + errors.push(error) |
| 76 | + console.log(`${X} ${error}`) |
| 77 | + } else { |
| 78 | + console.log(`${V} "${removedSelector}" removed and deprecated!`) |
| 79 | + } |
| 80 | + } |
| 81 | + |
| 82 | + if (errors.length) { |
| 83 | + process.exitCode = 1 |
| 84 | + } |
| 85 | +} |
| 86 | + |
| 87 | +function diffLists(before, after) { |
| 88 | + const added = after.filter(value => !before.includes(value)) |
| 89 | + const removed = before.filter(value => !after.includes(value)) |
| 90 | + return { |
| 91 | + changed: added.length + removed.length, |
| 92 | + added, |
| 93 | + removed |
| 94 | + } |
| 95 | +} |
0 commit comments