kup-cli 0.1.0-beta.2 → 0.1.0-beta.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +11 -8
- package/bin/cli.js +6 -7
- package/index.js +1 -3
- package/lib/file.js +7 -3
- package/lib/main.js +8 -10
- package/lib/parse.js +3 -4
- package/lib/repo.js +12 -11
- package/lib/sync.js +10 -7
- package/lib/token.js +2 -4
- package/lib/util.js +1 -3
- package/lib/validate.js +1 -3
- package/package.json +8 -4
package/README.md
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
# Kup
|
|
2
2
|
|
|
3
|
+
<img src="https://user-images.githubusercontent.com/1231359/171321963-e8e73bdf-f9c8-435b-9707-318e92f1805a.png" width="150" height="80" align="right" alt="Kup logo">
|
|
4
|
+
|
|
3
5
|
> A CLI tool to sync local Markdown files to GitHub issues.
|
|
4
6
|
>
|
|
5
|
-
>
|
|
6
|
-
|
|
7
|
-

|
|
7
|
+
> 这款命令行工具可以把本地的 Markdown 文件同步到 GitHub issue。
|
|
8
8
|
|
|
9
9
|
## 谁需要它
|
|
10
10
|
|
|
@@ -46,9 +46,7 @@ Kup 会把 `file.md` 文件的内容更新到 `foo/bar` 仓库的编号为 `123`
|
|
|
46
46
|
|
|
47
47
|
操作 GitHub issue 是需要权限认证的,因此你需要向 Kup 提供 GitHub token,以便 Kup 调用 GitHub API。
|
|
48
48
|
|
|
49
|
-
1.
|
|
50
|
-
|
|
51
|
-
> 友情提示:不要把 token 告诉其他人;不要把 token 写进代码。
|
|
49
|
+
1. 在 GitHub 的 “[Personal access tokens](https://github.com/settings/tokens)” 页面生成一个新 token,权限范围需要选中 “repo”。(详细说明参见 [这篇文档](https://github.com/cssmagic/kup/issues/17)。)
|
|
52
50
|
|
|
53
51
|
2. 把获取到的 token 写入环境变量:
|
|
54
52
|
|
|
@@ -95,7 +93,7 @@ Kup 会把 `file.md` 文件的内容更新到 `foo/bar` 仓库的编号为 `123`
|
|
|
95
93
|
Kup 通过以下线索来确定 issue 的标题,优先级递减:
|
|
96
94
|
|
|
97
95
|
1. Markdown 文件内的元数据的 `title` 字段。
|
|
98
|
-
1. Markdown 正文的第一个标记如果是一级标题(`# Title`
|
|
96
|
+
1. Markdown 正文的第一个标记如果是一级标题(`# Title` 格式),则取它的内容(在这种情况下,这个一级标题在同步时会从内容中排除)。
|
|
99
97
|
|
|
100
98
|
如果通过以上方式无法确定 issue 标题,Kup 会怎么处理?
|
|
101
99
|
|
|
@@ -118,6 +116,7 @@ Kup 通过以下线索来确定 issue 的标题,优先级递减:
|
|
|
118
116
|
## 文档
|
|
119
117
|
|
|
120
118
|
* [Markdown 文件内的元数据示例](https://github.com/cssmagic/kup/issues/1)
|
|
119
|
+
* [如何为 Kup 生成合适的 GitHub token](https://github.com/cssmagic/kup/issues/17)
|
|
121
120
|
|
|
122
121
|
|
|
123
122
|
## 其它
|
|
@@ -133,10 +132,14 @@ Kup 通过以下线索来确定 issue 的标题,优先级递减:
|
|
|
133
132
|
|
|
134
133
|
### 关于 Logo
|
|
135
134
|
|
|
136
|
-
* 作者 [Fasil](https://freeicons.io/profile/722),由 [freeicons.io](https://freeicons.io/
|
|
135
|
+
* 作者 [Fasil](https://freeicons.io/profile/722),由 [freeicons.io](https://freeicons.io/icon/e-commerce-icons/pickup-truck-icon-26893) 免费提供。
|
|
137
136
|
|
|
138
137
|
***
|
|
139
138
|
|
|
140
139
|
## License
|
|
141
140
|
|
|
141
|
+
> Any code contributed to this project is considered authorized for commercial use by the project authors and their affiliated companies and distributed under this project's license.
|
|
142
|
+
>
|
|
143
|
+
> 任何贡献到本项目的代码,均视为授权本项目作者及其名下公司用于商业用途、并按本项目协议分发。
|
|
144
|
+
|
|
142
145
|
MIT
|
package/bin/cli.js
CHANGED
|
@@ -1,17 +1,16 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
const { validate } = require('../lib/validate')
|
|
2
|
+
import yargs from 'yargs'
|
|
3
|
+
import { hideBin } from 'yargs/helpers'
|
|
4
|
+
import { isDebugging } from '../lib/util.js'
|
|
5
|
+
import { main } from '../lib/main.js'
|
|
6
|
+
import { validate } from '../lib/validate.js'
|
|
8
7
|
|
|
9
8
|
if (isDebugging()) {
|
|
10
9
|
console.log('[Kup] [Debug] Debug Mode is ON!')
|
|
11
10
|
console.log('')
|
|
12
11
|
}
|
|
13
12
|
|
|
14
|
-
const argv = yargs
|
|
13
|
+
const argv = yargs(hideBin(process.argv))
|
|
15
14
|
.scriptName('kup')
|
|
16
15
|
.usage('Kup -- A CLI tool to sync local Markdown files to GitHub issues.')
|
|
17
16
|
.usage('Usage: $0 <file> [options]')
|
package/index.js
CHANGED
package/lib/file.js
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
const fsPromises = require('fs').promises
|
|
1
|
+
import fsPromises from 'fs/promises'
|
|
3
2
|
|
|
4
3
|
function readTextFile(pathname) {
|
|
5
4
|
return fsPromises.readFile(pathname)
|
|
@@ -12,6 +11,11 @@ function readTextFile(pathname) {
|
|
|
12
11
|
})
|
|
13
12
|
}
|
|
14
13
|
|
|
15
|
-
|
|
14
|
+
function writeTextFile(pathname, content) {
|
|
15
|
+
fsPromises.writeFile(pathname, content)
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export {
|
|
16
19
|
readTextFile,
|
|
20
|
+
writeTextFile,
|
|
17
21
|
}
|
package/lib/main.js
CHANGED
|
@@ -1,11 +1,9 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
const { updateIssue, postIssue } = require('./sync')
|
|
8
|
-
const { getToken } = require('./token')
|
|
1
|
+
import { isDebugging } from './util.js'
|
|
2
|
+
import { readTextFile } from './file.js'
|
|
3
|
+
import { parse } from './parse.js'
|
|
4
|
+
import { getRepo } from './repo.js'
|
|
5
|
+
import { updateIssue, postIssue } from './sync.js'
|
|
6
|
+
import { getToken } from './token.js'
|
|
9
7
|
|
|
10
8
|
async function main(argv) {
|
|
11
9
|
const {
|
|
@@ -36,7 +34,7 @@ async function main(argv) {
|
|
|
36
34
|
// 通过各种方式获取 repo
|
|
37
35
|
// 优先级: 命令行参数 > 文件元数据 > 文件所在项目的 package.json 中的 `kup.repo` 字段
|
|
38
36
|
let repoReal = repo || fileInfo.meta.repo
|
|
39
|
-
if (!repoReal) repoReal = await getRepo()
|
|
37
|
+
if (!repoReal) repoReal = await getRepo(file)
|
|
40
38
|
if (!repoReal) {
|
|
41
39
|
console.error('[Kup] [Error] Cannot get `repo` to sync to!')
|
|
42
40
|
process.exit(1)
|
|
@@ -54,6 +52,6 @@ async function main(argv) {
|
|
|
54
52
|
}
|
|
55
53
|
}
|
|
56
54
|
|
|
57
|
-
|
|
55
|
+
export {
|
|
58
56
|
main,
|
|
59
57
|
}
|
package/lib/parse.js
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
|
-
|
|
2
|
-
const YAML = require('yaml')
|
|
1
|
+
import YAML from 'yaml'
|
|
3
2
|
|
|
4
|
-
|
|
3
|
+
import { isPlainObject } from './util.js'
|
|
5
4
|
|
|
6
5
|
// parse markdown file:
|
|
7
6
|
// - extract metadata in yaml format
|
|
@@ -116,6 +115,6 @@ function _getTitleFromMainBody(firstLine) {
|
|
|
116
115
|
return title
|
|
117
116
|
}
|
|
118
117
|
|
|
119
|
-
|
|
118
|
+
export {
|
|
120
119
|
parse,
|
|
121
120
|
}
|
package/lib/repo.js
CHANGED
|
@@ -1,16 +1,16 @@
|
|
|
1
|
-
|
|
1
|
+
import findUp from 'find-up'
|
|
2
|
+
import path from 'path'
|
|
2
3
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
const { validateRepo } = require('./validate')
|
|
4
|
+
import { readTextFile } from './file.js'
|
|
5
|
+
import { validateRepo } from './validate.js'
|
|
6
6
|
|
|
7
|
-
async function getRepo() {
|
|
7
|
+
async function getRepo(sourceFile = '') {
|
|
8
8
|
// 目前只实现这一种方式
|
|
9
|
-
return await _getRepoFromPkgKup()
|
|
9
|
+
return await _getRepoFromPkgKup(sourceFile)
|
|
10
10
|
}
|
|
11
11
|
|
|
12
|
-
async function _getRepoFromPkgKup() {
|
|
13
|
-
const json = await _getPkg()
|
|
12
|
+
async function _getRepoFromPkgKup(sourceFile = '') {
|
|
13
|
+
const json = await _getPkg(sourceFile)
|
|
14
14
|
const repo = json?.kup?.repo
|
|
15
15
|
const result = validateRepo(repo)
|
|
16
16
|
return result.status ? repo : ''
|
|
@@ -22,8 +22,9 @@ async function _getRepoFromGit() {
|
|
|
22
22
|
// TODO
|
|
23
23
|
}
|
|
24
24
|
|
|
25
|
-
async function _getPkg() {
|
|
26
|
-
const
|
|
25
|
+
async function _getPkg(sourceFile = '') {
|
|
26
|
+
const cwd = sourceFile ? path.resolve(path.dirname(sourceFile)) : process.cwd()
|
|
27
|
+
const file = await findUp('package.json', { cwd })
|
|
27
28
|
|
|
28
29
|
let pkg = ''
|
|
29
30
|
try {
|
|
@@ -43,7 +44,7 @@ async function _getPkg() {
|
|
|
43
44
|
return json
|
|
44
45
|
}
|
|
45
46
|
|
|
46
|
-
|
|
47
|
+
export {
|
|
47
48
|
getRepo,
|
|
48
49
|
// __getRepoFromPkgKup: _getRepoFromPkgKup,
|
|
49
50
|
// __getRepoFromPkgRepo: _getRepoFromPkgRepo,
|
package/lib/sync.js
CHANGED
|
@@ -1,12 +1,11 @@
|
|
|
1
|
-
|
|
1
|
+
import ghGot from 'gh-got'
|
|
2
|
+
import inquirer from 'inquirer'
|
|
2
3
|
|
|
3
|
-
|
|
4
|
-
const inquirer = require('inquirer')
|
|
5
|
-
const { isDebugging } = require('../lib/util')
|
|
4
|
+
import { isDebugging } from '../lib/util.js'
|
|
6
5
|
|
|
7
6
|
let proxyOptionsForGot = {}
|
|
8
7
|
if (isDebugging()) {
|
|
9
|
-
const HttpsProxyAgent =
|
|
8
|
+
const { HttpsProxyAgent } = await import('https-proxy-agent')
|
|
10
9
|
const CHARLES_PROXY = 'http://127.0.0.1:8888'
|
|
11
10
|
const agent = new HttpsProxyAgent(CHARLES_PROXY)
|
|
12
11
|
proxyOptionsForGot = {
|
|
@@ -35,7 +34,7 @@ async function updateIssue(fileInfo, repo, id) {
|
|
|
35
34
|
const api = `/repos/${ repo }/issues/${ id }`
|
|
36
35
|
const method = 'PATCH'
|
|
37
36
|
let response = null
|
|
38
|
-
console.log(`[Kup] Updating
|
|
37
|
+
console.log(`[Kup] Updating "${ repo }#${ id }"...`)
|
|
39
38
|
try {
|
|
40
39
|
response = await ghGot(api, {
|
|
41
40
|
method,
|
|
@@ -50,7 +49,9 @@ async function updateIssue(fileInfo, repo, id) {
|
|
|
50
49
|
|
|
51
50
|
// handle response
|
|
52
51
|
if (response) {
|
|
52
|
+
const url = `https://github.com/${ repo }/issues/${ id }`
|
|
53
53
|
console.log(`[Kup] [Success] Updated to "${ repo }#${ id }"!`)
|
|
54
|
+
console.log(`[Kup] [Success] URL: ${ url }`)
|
|
54
55
|
}
|
|
55
56
|
}
|
|
56
57
|
|
|
@@ -99,14 +100,16 @@ async function postIssue(fileInfo, repo) {
|
|
|
99
100
|
// handle response
|
|
100
101
|
if (response) {
|
|
101
102
|
const id = response?.body?.number
|
|
103
|
+
const url = `https://github.com/${ repo }/issues/${ id }`
|
|
102
104
|
console.log(`[Kup] [Success] Posted to "${ repo }#${ id }"!`)
|
|
105
|
+
console.log(`[Kup] [Success] URL: ${ url }`)
|
|
103
106
|
|
|
104
107
|
// write back meta data
|
|
105
108
|
// TODO
|
|
106
109
|
}
|
|
107
110
|
}
|
|
108
111
|
|
|
109
|
-
|
|
112
|
+
export {
|
|
110
113
|
updateIssue,
|
|
111
114
|
postIssue,
|
|
112
115
|
}
|
package/lib/token.js
CHANGED
|
@@ -1,6 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
const inquirer = require('inquirer')
|
|
1
|
+
import inquirer from 'inquirer'
|
|
4
2
|
|
|
5
3
|
async function getToken() {
|
|
6
4
|
let token = process.env.GITHUB_TOKEN
|
|
@@ -43,6 +41,6 @@ function _validateToken(token) {
|
|
|
43
41
|
}
|
|
44
42
|
|
|
45
43
|
|
|
46
|
-
|
|
44
|
+
export {
|
|
47
45
|
getToken,
|
|
48
46
|
}
|
package/lib/util.js
CHANGED
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
'use strict'
|
|
2
|
-
|
|
3
1
|
// 考虑到输入源的类型有限,这里只是做了一个简化的实现
|
|
4
2
|
function isPlainObject(obj) {
|
|
5
3
|
if (!obj) return false
|
|
@@ -15,7 +13,7 @@ function isDebugging() {
|
|
|
15
13
|
return !!Number(process.env.KUP_DEBUG_MODE)
|
|
16
14
|
}
|
|
17
15
|
|
|
18
|
-
|
|
16
|
+
export {
|
|
19
17
|
isPlainObject,
|
|
20
18
|
isDebugging,
|
|
21
19
|
}
|
package/lib/validate.js
CHANGED
package/package.json
CHANGED
|
@@ -1,16 +1,20 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "kup-cli",
|
|
3
|
-
"version": "0.1.0-beta.
|
|
3
|
+
"version": "0.1.0-beta.3",
|
|
4
4
|
"description": "A CLI tool to sync local Markdown files to GitHub issues.",
|
|
5
|
+
"type": "module",
|
|
5
6
|
"bin": {
|
|
6
|
-
"kup": "
|
|
7
|
+
"kup": "bin/cli.js"
|
|
7
8
|
},
|
|
8
9
|
"scripts": {
|
|
9
10
|
"debug": "export KUP_DEBUG_MODE=1",
|
|
10
11
|
"postpublish": "npx npm-mirror-sync",
|
|
11
12
|
"test": "echo \"Error: no test specified\" && exit 1"
|
|
12
13
|
},
|
|
13
|
-
"repository":
|
|
14
|
+
"repository": {
|
|
15
|
+
"type": "git",
|
|
16
|
+
"url": "git+https://github.com/cssmagic/kup.git"
|
|
17
|
+
},
|
|
14
18
|
"keywords": [
|
|
15
19
|
"cli",
|
|
16
20
|
"markdown",
|
|
@@ -20,7 +24,7 @@
|
|
|
20
24
|
"author": "cssmagic <cssmagic.cn@gmail.com>",
|
|
21
25
|
"license": "MIT",
|
|
22
26
|
"engines": {
|
|
23
|
-
"node": ">=
|
|
27
|
+
"node": ">=18"
|
|
24
28
|
},
|
|
25
29
|
"dependencies": {
|
|
26
30
|
"find-up": "^5.0.0",
|