Skip to content

Commit

Permalink
feat: 赋能自动化 npm 配套设施 (#121)
Browse files Browse the repository at this point in the history
  • Loading branch information
eviIIt authored Aug 13, 2020
1 parent 5492384 commit 7088701
Show file tree
Hide file tree
Showing 14 changed files with 155 additions and 50 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@
/components
.idea
.DS_Store
v-test
10 changes: 6 additions & 4 deletions README-zh.md
Original file line number Diff line number Diff line change
Expand Up @@ -85,22 +85,24 @@ yarn publish

`-u`, `--upgrade`

根据 template目录下模板,生成新的文件,更新到当前组件中。使用的是覆盖策略,默认覆盖的文件定义在 update-files.js。常用于使用最新版本vue-sfc-cli对旧组件的配置进行升级
根据 template 目录下模板,生成新的文件,更新到当前组件中。使用的是覆盖策略,默认覆盖的文件定义在 update-files.js。常用于使用最新版本 vue-sfc-cli 对旧组件的配置进行升级。

**此参数还可以让任意 node.js 项目通过 travis ci 自动发布到 NPM**

```
# cd my-component
npx vue-sfc-cli -u
```

`-files`
`--files`

如果想更新额外的文件,可以传此选项,后接文件名,多个文件使用 `,` 分隔

```
npx vue-sfc-cli -u --files package.json,.babelrc.js
npx vue-sfc-cli -u --files .babelrc.js,.eslintrc.js
```

`-test`
`--test`

生成一个测试的组件模板,常用于ci环境测试。

Expand Down
8 changes: 5 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -102,20 +102,22 @@ yarn publish

According to the template files in the templates directory, new files will be generated and override the files with same name in current component directory. The default override files is defined in update-files.js. This option often used to upgrade the configuration of old components using the latest version of vue-sfc-cli:

**This option can also help any node.js project to set up configuration of AUTO npm publishment via travis ci**

```
# cd my-component
npx vue-sfc-cli -u
```

`-files`
`--files`

If you want to update additional files, you can pass this option, multiple files use `,` to separate

```
npx vue-sfc-cli -u --files package.json,.babelrc.js
npx vue-sfc-cli -u --files .babelrc.js,.eslintrc.js
```

`-test`
`--test`

Generate a component template for testing, commonly used in CI .

Expand Down
8 changes: 0 additions & 8 deletions config/update-files.js

This file was deleted.

5 changes: 2 additions & 3 deletions init.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ const parseArgs = require('./lib/parseArgs')
const kleur = require('kleur')
const path = require('path')
const readline = require('readline-sync')
const fs = require('fs-extra')
const { setShellFilePermission } = require('./utils/update-files')

const argv = parseArgs(process.argv.slice(2))

Expand Down Expand Up @@ -80,8 +80,7 @@ if (!isUpgrade()) {
}
})

fs.chmodSync(path.join(outDir, 'build.sh'), '755')
fs.chmodSync(path.join(outDir, 'notify.sh'), '755')
setShellFilePermission(outDir)

logger.success(`Generated into ${kleur.underline(outDir)}`)
}
Expand Down
65 changes: 48 additions & 17 deletions lib/fileActions.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ const { logger, parseContent } = require('../utils')
const glob = require('glob')
const path = require('path')
const fs = require('fs-extra')
const _set = require('lodash.set')

module.exports = class FileActions {
constructor(opts = {}) {
Expand Down Expand Up @@ -46,7 +47,7 @@ module.exports = class FileActions {

upgrade(extraFiles = []) {
const filesFromCli = this.opts.argv.get('files') || ''
const shouldUpdateFiles = require('../config/update-files')
const { shouldUpdateFiles, setShellFilePermission, todoFiles } = require('../utils/update-files')

const files = shouldUpdateFiles.concat(extraFiles, filesFromCli.split(','))

Expand All @@ -70,37 +71,67 @@ module.exports = class FileActions {
logger.fileAction('yellow', 'Upgraded', path.relative(process.cwd(), target))
})

fs.chmodSync(path.join(process.cwd(), 'build.sh'), '755')
fs.chmodSync(path.join(process.cwd(), 'notify.sh'), '755')
setShellFilePermission(process.cwd())

upgradePackageJson(
// @ts-ignore
Object.assign(
this.opts,
{
source: fs.readFileSync(path.join(this.opts.templatesDir, '_package.json'), 'utf8'),
includePkg: files.includes('package.json')
source: fs.readFileSync(path.join(this.opts.templatesDir, '_package.json'), 'utf8')
}
)
)

console.log()
todoFiles.forEach(todoFile => logger.todo(todoFile.msg))
logger.info('After double-check, you should run `yarn` or `npm i` to install the injected devDependencies.')
}
}

function upgradePackageJson({ pkg, source, componentName, ownerName, includePkg }) {
const properties = ['scripts', 'devDependencies', 'husky', 'lint-staged']
const cliVersion = require('../package.json').version

function upgradePackageJson({ pkg, source, componentName, ownerName }) {
const templatePkg = JSON.parse(parseContent(source, { componentName, ownerName }))
const cliVersion = require('../package.json').version
const currentPkg = pkg

if (currentPkg['vue-sfc-cli']) {
currentPkg['vue-sfc-cli'] = cliVersion
}

if (includePkg) {
properties.forEach(key => {
currentPkg[key] = Object.assign(pkg[key] || {}, templatePkg[key])
const properties = [
// 保证 scripts[stdver,release] 都是来自模板
{
key: 'scripts',
overrideValue: {
stdver: templatePkg.scripts.stdver,
release: templatePkg.scripts.release
},
fallbackValue: {
test: 'echo "Info: no test specified"'
}
},
// 保证 devDependencies[@femessage/github-release-notes,standard-version] 都是来自模板
{
key: 'devDependencies',
overrideValue: {
'@femessage/github-release-notes': templatePkg.devDependencies['@femessage/github-release-notes'],
'standard-version': templatePkg.devDependencies['standard-version']
}
}
]

_set(currentPkg, 'vue-sfc-cli', cliVersion)
// gren 以用户的 gren 优先
_set(currentPkg, 'gren', currentPkg.gren || templatePkg.gren)
// publishConfig.asscess = 'public'
_set(currentPkg, ['publishConfig', 'access'], templatePkg.publishConfig.access)

properties.forEach(prop => {
// {}, 预防的字段,用户的字段,最终保证的字段
_set(currentPkg, prop.key, Object.assign({}, prop.fallbackValue, currentPkg[prop.key], prop.overrideValue))

// 以用户的 package.json 文件为基础,避免因合并后造成排序混乱导致 review 增加负担。
Object.keys(pkg[prop.key]).forEach(k => {
// 以顺序赋值
_set(currentPkg, [prop.key, k], Object.assign({}, templatePkg[prop.key], pkg[prop.key])[k])
})
}
})

fs.outputJSONSync(path.join(process.cwd(), 'package.json'), currentPkg, {
spaces: 2
Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
"fs-extra": "^7.0.1",
"glob": "^7.1.3",
"kleur": "^3.0.3",
"lodash.set": "^4.3.2",
"mri": "^1.1.4",
"readline-sync": "^1.4.9"
},
Expand Down
6 changes: 3 additions & 3 deletions templates/.travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,12 @@ after_script:
- ./notify.sh
cache: yarn
deploy:
- provider: pages
local-dir: docs
- provider: pages # you may delete this provider if you don't need deployment of github pages
local-dir: docs # https://docs.travis-ci.com/user/deployment/packagecloud/#specify-package-folder
github-token: $GITHUB_TOKEN
skip-cleanup: true
keep-history: true
- provider: npm
email: [email protected]
email: [email protected] # use your own email
api_key: $NPM_TOKEN
skip-cleanup: true
2 changes: 1 addition & 1 deletion templates/_package.json
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@
"@babel/core": "^7.4.3",
"@babel/plugin-transform-runtime": "^7.4.3",
"@babel/preset-env": "^7.4.3",
"@femessage/github-release-notes": "^0.19.0",
"@femessage/github-release-notes": "latest",
"babel-eslint": "^10.0.3",
"babel-loader": "^8.0.5",
"eslint": "^6.6.0",
Expand Down
20 changes: 9 additions & 11 deletions utils/index.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
const logger = require('./logger')
const rs = require('./replace-string')

exports.logger = logger

Expand All @@ -7,13 +8,14 @@ exports.pascalify = pascalify
exports.kebabcasify = kebabcasify

exports.parseContent = (content, { componentName, ownerName }) => {
return content
.replace(createRegExp('componentNamePascal'), pascalify(componentName))
.replace(createRegExp('componentName'), kebabcasify(componentName))
.replace(createRegExp('ownerName'), ownerName)
.replace(createRegExp('ownerNameLowerCase'), ownerName.toLowerCase())
.replace(createRegExp('cliVersion'), require('../package.json').version)
.replace(createRegExp('licenseYear'), new Date().getFullYear())
return rs(content, {
componentNamePascal: pascalify(componentName),
componentName: kebabcasify(componentName),
ownerName,
ownerNameLowerCase: ownerName.toLowerCase(),
cliVersion: require('../package.json').version,
licenseYear: new Date().getFullYear()
})
}

function kebabcasify(content) {
Expand All @@ -27,7 +29,3 @@ function pascalify(content) {
const camelized = content.replace(/-([a-z])/g, c => c[1].toUpperCase())
return camelized.charAt(0).toUpperCase() + camelized.slice(1)
}

function createRegExp(str) {
return new RegExp(`{{\\s?${str}\\s?}}`, 'g')
}
4 changes: 4 additions & 0 deletions utils/logger.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,10 @@ class Logger {
this.log(kleur.cyan('info'), ...args)
}

todo(...args) {
this.log(kleur.magenta('🔍TODO'), ...args)
}

fileAction(color, type, fp) {
this.info(
kleur[color](type), kleur.green(path.relative(process.cwd(), fp))
Expand Down
31 changes: 31 additions & 0 deletions utils/replace-string.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
// Modified from sindresorhus/pupa

module.exports = (template, data) => {
if (typeof template !== 'string') {
throw new TypeError(
`Expected a \`string\` in the first argument, got \`${typeof template}\``
)
}

if (typeof data !== 'object') {
throw new TypeError(
`Expected an \`object\` or \`Array\` in the second argument, got \`${typeof data}\``
)
}

const doubleBraceRegex = /{{(.*?)}}/g

if (doubleBraceRegex.test(template)) {
template = template.replace(doubleBraceRegex, (_, key) => {
let result = data

for (const property of key.split('.')) {
result = result ? result[property] : ''
}

return String(result)
})
}

return template
}
39 changes: 39 additions & 0 deletions utils/update-files.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
const fs = require('fs-extra')
const path = require('path')

const shellFiles = [
'build.sh',
'netlify.sh',
'notify.sh'
]

exports.todoFiles = [
{
fileName: 'build.sh',
msg: 'Please check `yarn build` in `build.sh`'
},
{
fileName: '.travis.yml',
msg: 'Please check `deploy` in `.travis.yml`'
},
{
fileName: 'netlify.sh',
msg: 'Please check `yarn doc` in `netlify.sh`(you can delete this file if you don\'t need it)'
},
]

exports.shouldUpdateFiles = [
'.grenrc.js',
'.prettierrc',
'.stylelintrc',
'.travis.yml',
...shellFiles
]

exports.setShellFilePermission = dir => {
shellFiles.forEach(shellFile => {
fs.chmodSync(path.join(dir, shellFile), '755')
fs.chmodSync(path.join(dir, shellFile), '755')
fs.chmodSync(path.join(dir, shellFile), '755')
})
}
5 changes: 5 additions & 0 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -2053,6 +2053,11 @@ lodash.ismatch@^4.4.0:
version "4.4.0"
resolved "https://registry.npm.taobao.org/lodash.ismatch/download/lodash.ismatch-4.4.0.tgz#756cb5150ca3ba6f11085a78849645f188f85f37"

lodash.set@^4.3.2:
version "4.3.2"
resolved "https://registry.npm.taobao.org/lodash.set/download/lodash.set-4.3.2.tgz#d8757b1da807dde24816b0d6a84bea1a76230b23"
integrity sha1-2HV7HagH3eJIFrDWqEvqGnYjCyM=

lodash.template@^4.0.2:
version "4.5.0"
resolved "https://registry.yarnpkg.com/lodash.template/-/lodash.template-4.5.0.tgz#f976195cf3f347d0d5f52483569fe8031ccce8ab"
Expand Down

0 comments on commit 7088701

Please sign in to comment.