-
Notifications
You must be signed in to change notification settings - Fork 19
Expand file tree
/
Copy pathindex.js
More file actions
89 lines (69 loc) · 2.6 KB
/
index.js
File metadata and controls
89 lines (69 loc) · 2.6 KB
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
const probotMetadataRegex = /(?:\n\n|\r\n)<!-- probot = (.*) -->/
const prototypePollutionKeys = /** @type {const} */(['__proto__', 'constructor', 'prototype'])
const metadata = /** @type {ProbotMetadataConstructor} */ (context, issue) => {
const octokit = context.octokit
const prefix = /** @type {{ id: number; node_id: string; }} */ (context.payload.installation).id
if (!issue) issue = context.issue()
return {
async get (key) {
let body = issue.body
if (!body) {
body = (await octokit.rest.issues.get(issue)).data.body || ''
}
const match = body.match(probotMetadataRegex)
if (match) {
const probotMetadata = JSON.parse(match[1])
const data = probotMetadata[prefix]
return typeof key === 'string' || typeof key === 'number'
? data && data[key]
: data
}
},
async set (key, value) {
let body = issue.body
/** @type {Record<number, Record<number|string, any>>} */
let data = Object.create(null)
if (!body) body = (await octokit.rest.issues.get(issue)).data.body || ''
const match = body.match(probotMetadataRegex)
if (match) {
data = JSON.parse(match[1])
}
body = body.replace(probotMetadataRegex, '')
if (!data[prefix]) data[prefix] = Object.create(null)
// should never happen, but just in case
if (typeof prefix === 'string' && prototypePollutionKeys.includes(prefix)) {
throw new TypeError('Invalid prefix value')
}
if (typeof key === 'string' || typeof key === 'number') {
data[prefix][key] = value
} else {
Object.assign(data[prefix], key)
}
await octokit.rest.issues.update({
owner: issue.owner,
repo: issue.repo,
issue_number: issue.issue_number,
body: `${body}\n\n<!-- probot = ${JSON.stringify(data)} -->`
})
issue.body = `${body}\n\n<!-- probot = ${JSON.stringify(data)} -->`
}
}
}
export default metadata
export { metadata }
/** @typedef {string|number} StringOrNumber */
/** @typedef {Record<string, StringOrNumber>|StringOrNumber|StringOrNumber[]} Key */
/** @typedef {Key} Value */
/**
* @typedef {object} IssueOption
* @property {string} owner
* @property {string} repo
* @property {number} issue_number
* @property {string} [body]
*/
/**
* @typedef {object} ProbotMetadata
* @property {(key?: Key)=>Promise<Value|undefined>} get
* @property {(key?: Key, value?: Value)=>Promise<void>} set
*/
/** @typedef {(context: import('probot').Context<'issue_comment'>, issue?: IssueOption)=>ProbotMetadata} ProbotMetadataConstructor */