2017-10-12 01:58:29 +03:00
|
|
|
#!/usr/bin/env node
|
|
|
|
const fse = require('fs-extra')
|
|
|
|
const globby = require('globby')
|
|
|
|
|
|
|
|
const DEP_FIELDS = [
|
|
|
|
'dependencies',
|
|
|
|
]
|
|
|
|
|
|
|
|
const parseImports = filename => {
|
|
|
|
return fse.readFile(filename, 'utf8')
|
|
|
|
.then(scss => {
|
|
|
|
const matches = scss.match(/\@import\s+"[-a-z]+\/index\.scss"/g)
|
|
|
|
return matches
|
|
|
|
? Array.from(matches).map(stmt => stmt.match(/"([-a-z]+)\//)[1])
|
|
|
|
: []
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2017-10-12 03:07:11 +03:00
|
|
|
const isPrimerModule = name => name.indexOf('primer-') === 0
|
|
|
|
|
2017-10-12 01:58:29 +03:00
|
|
|
globby('modules/primer-*')
|
|
|
|
.then(paths => {
|
|
|
|
return paths.reduce((modules, path) => {
|
|
|
|
const pkg = require(`../${path}/package.json`)
|
|
|
|
if (pkg.dependencies) {
|
|
|
|
pkg.path = path
|
|
|
|
modules.push(pkg)
|
|
|
|
} else {
|
|
|
|
console.warn('%s: no dependencies', pkg.name)
|
|
|
|
}
|
|
|
|
return modules
|
|
|
|
}, [])
|
|
|
|
})
|
|
|
|
.then(modules => {
|
|
|
|
console.log('⏱ checking %d modules...', modules.length)
|
2017-10-12 03:00:09 +03:00
|
|
|
|
2017-10-12 02:02:00 +03:00
|
|
|
const maxNameLength = modules.reduce((len, {name}) => {
|
|
|
|
return Math.max(len, name.length)
|
|
|
|
}, 0)
|
2017-10-12 03:00:09 +03:00
|
|
|
|
2017-10-12 01:58:29 +03:00
|
|
|
const map = new Map()
|
|
|
|
modules.forEach(mod => map.set(mod.name, mod))
|
2017-10-12 03:00:09 +03:00
|
|
|
|
|
|
|
const tasks = []
|
|
|
|
const matches = []
|
|
|
|
|
2017-10-12 01:58:29 +03:00
|
|
|
modules.forEach(mod => {
|
|
|
|
const deps = Object.keys(mod.dependencies)
|
2017-10-12 03:07:11 +03:00
|
|
|
.filter(isPrimerModule)
|
|
|
|
|
2017-10-12 01:58:29 +03:00
|
|
|
tasks.push(
|
|
|
|
parseImports(`${mod.path}/index.scss`)
|
|
|
|
.then(imports => {
|
2017-10-12 02:02:00 +03:00
|
|
|
console.warn('📦 %s: %s%d dependencies, %d import(s)',
|
|
|
|
mod.name, ' '.repeat(maxNameLength - mod.name.length),
|
|
|
|
deps.length, imports.length)
|
2017-10-12 01:58:29 +03:00
|
|
|
imports.forEach(imported => {
|
|
|
|
if (!deps.includes(imported)) {
|
|
|
|
throw new Error(
|
|
|
|
`❌ ${mod.name} imports ${imported}, but is missing a dependency`
|
|
|
|
)
|
|
|
|
}
|
2017-10-12 03:00:09 +03:00
|
|
|
matches.push({
|
|
|
|
module: mod.name,
|
|
|
|
imports: imported
|
|
|
|
})
|
2017-10-12 01:58:29 +03:00
|
|
|
})
|
|
|
|
})
|
|
|
|
)
|
|
|
|
})
|
|
|
|
return Promise.all(tasks)
|
2017-10-12 03:07:11 +03:00
|
|
|
.then(() => {
|
|
|
|
const primer = map.get('primer-css')
|
|
|
|
|
|
|
|
const deps = new Set(
|
|
|
|
Object.keys(primer.dependencies)
|
|
|
|
.filter(isPrimerModule)
|
|
|
|
.sort()
|
|
|
|
)
|
|
|
|
|
|
|
|
modules
|
|
|
|
.map(mod => mod.name)
|
|
|
|
.filter(mod => mod !== primer.name)
|
|
|
|
.sort()
|
|
|
|
.forEach(mod => {
|
|
|
|
if (!deps.has(mod)) {
|
|
|
|
throw new Error(
|
|
|
|
`primer-css is missing dependency for ${mod}@${map.get(mod).version}`
|
|
|
|
)
|
|
|
|
}
|
|
|
|
})
|
|
|
|
})
|
2017-10-12 03:00:09 +03:00
|
|
|
.then(() => matches)
|
2017-10-12 01:58:29 +03:00
|
|
|
})
|
|
|
|
.catch(error => {
|
|
|
|
console.error(error)
|
|
|
|
process.exit(1)
|
|
|
|
})
|
|
|
|
.then(matches => {
|
2017-10-12 03:00:09 +03:00
|
|
|
console.warn('✅ checked %d dependency/import pairs', matches.length)
|
2017-10-12 01:58:29 +03:00
|
|
|
})
|