1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
|
const api = require('./api')
const auth = require('./auth')
const zmk = require('../zmk')
const MODE_FILE = '100644'
class InvalidRepoError extends Error {}
async function fetchKeyboardFiles (installationId, repository) {
const { data: { token: installationToken } } = await auth.createInstallationToken(installationId)
try {
const { data: info } = await fetchFile(installationToken, repository, 'config/info.json', true)
const { data: keymap } = await fetchFile(installationToken, repository, 'config/keymap.json', true)
return { info, keymap }
} catch (err) {
if (err.response && err.response.status === 404) {
throw new InvalidRepoError()
}
throw err
}
}
function fetchFile (installationToken, repository, path, raw = false) {
const url = `/repos/${repository}/contents/${path}`
const headers = { Accept: raw ? 'application/vnd.github.v3.raw' : 'application/json' }
return api.request({ url, headers, token: installationToken })
}
async function commitChanges (installationId, repository, layout, keymap) {
const { data: { token: installationToken } } = await auth.createInstallationToken(installationId)
const generatedKeymap = zmk.generateKeymap(layout, keymap)
// Assume that the relevant files are under `config/` and not a complicated
// directory structure, and that there are fewer than 1000 files in this path
// (a limitation of GitHub's repo contents API).
const { data: directory } = await fetchFile(installationToken, repository, 'config/')
const originalCodeKeymap = directory.find(file => file.name.toLowerCase().endsWith('.keymap'))
const { data: repo } = await api.request({ url: `/repos/${repository}`, token: installationToken })
const { data: [{sha, commit}] } = await api.request({ url: `/repos/${repository}/commits?per_page=1`, token: installationToken })
const { data: { sha: newTreeSha } } = await api.request({
url: `/repos/${repository}/git/trees`,
method: 'POST',
token: installationToken,
data: {
base_tree: commit.tree.sha,
tree: [
{
path: originalCodeKeymap.path,
mode: MODE_FILE,
type: 'blob',
content: generatedKeymap.code
},
{
path: 'config/keymap.json',
mode: MODE_FILE,
type: 'blob',
content: generatedKeymap.json
}
]
}
})
const { data: { sha: newSha } } = await api.request({
url: `/repos/${repository}/git/commits`,
method: 'POST',
token: installationToken,
data: {
tree: newTreeSha,
message: 'Updated keymap',
parents: [sha]
}
})
await api.request({
url: `/repos/${repository}/git/refs/heads/${repo.default_branch}`,
method: 'PATCH',
token: installationToken,
data: {
sha: newSha
}
})
}
module.exports = {
InvalidRepoError,
fetchKeyboardFiles,
commitChanges
}
|