@commitspark/git-adapter-github 0.20.0 → 0.30.0
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/CHANGELOG.md +17 -0
- package/README.md +39 -0
- package/dist/cjs/errors.js +58 -0
- package/dist/cjs/errors.js.map +1 -0
- package/dist/cjs/github-adapter.js +86 -71
- package/dist/cjs/github-adapter.js.map +1 -1
- package/dist/cjs/github-api/get-entry-content.js +53 -0
- package/dist/cjs/github-api/get-entry-content.js.map +1 -0
- package/dist/cjs/github-api/get-file-paths.js +48 -0
- package/dist/cjs/github-api/get-file-paths.js.map +1 -0
- package/dist/cjs/{util → github-api}/graphql-query-factory.js +32 -23
- package/dist/cjs/github-api/graphql-query-factory.js.map +1 -0
- package/dist/cjs/types.js +10 -0
- package/dist/cjs/types.js.map +1 -0
- package/dist/cjs/util/entries-to-actions-converter.js +1 -1
- package/dist/cjs/util/entries-to-actions-converter.js.map +1 -1
- package/dist/cjs/util/entry-factory.js +10 -9
- package/dist/cjs/util/entry-factory.js.map +1 -1
- package/dist/cjs/util/path-factory.js +3 -3
- package/dist/cjs/util/path-factory.js.map +1 -1
- package/dist/esm/errors.js +51 -0
- package/dist/esm/errors.js.map +1 -0
- package/dist/esm/github-adapter.js +86 -70
- package/dist/esm/github-adapter.js.map +1 -1
- package/dist/esm/github-api/get-entry-content.js +40 -0
- package/dist/esm/github-api/get-entry-content.js.map +1 -0
- package/dist/esm/github-api/get-file-paths.js +35 -0
- package/dist/esm/github-api/get-file-paths.js.map +1 -0
- package/dist/esm/{util → github-api}/graphql-query-factory.js +30 -21
- package/dist/esm/github-api/graphql-query-factory.js.map +1 -0
- package/dist/esm/types.js +7 -0
- package/dist/esm/types.js.map +1 -0
- package/dist/esm/util/entries-to-actions-converter.js +1 -1
- package/dist/esm/util/entries-to-actions-converter.js.map +1 -1
- package/dist/esm/util/entry-factory.js +9 -8
- package/dist/esm/util/entry-factory.js.map +1 -1
- package/dist/esm/util/path-factory.js +3 -3
- package/dist/esm/util/path-factory.js.map +1 -1
- package/dist/tsconfig.build.cjs.tsbuildinfo +1 -1
- package/dist/tsconfig.build.esm.tsbuildinfo +1 -1
- package/dist/tsconfig.build.types.tsbuildinfo +1 -1
- package/dist/types/errors.d.ts +4 -0
- package/dist/types/errors.d.ts.map +1 -0
- package/dist/types/github-adapter.d.ts +0 -1
- package/dist/types/github-adapter.d.ts.map +1 -1
- package/dist/types/github-api/get-entry-content.d.ts +4 -0
- package/dist/types/github-api/get-entry-content.d.ts.map +1 -0
- package/dist/types/github-api/get-file-paths.d.ts +4 -0
- package/dist/types/github-api/get-file-paths.d.ts.map +1 -0
- package/dist/types/github-api/graphql-query-factory.d.ts +8 -0
- package/dist/types/github-api/graphql-query-factory.d.ts.map +1 -0
- package/dist/types/types.d.ts +7 -0
- package/dist/types/types.d.ts.map +1 -0
- package/dist/types/util/entry-factory.d.ts +2 -9
- package/dist/types/util/entry-factory.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/errors.ts +54 -0
- package/src/github-adapter.ts +128 -86
- package/src/github-api/get-entry-content.ts +76 -0
- package/src/github-api/get-file-paths.ts +66 -0
- package/src/{util → github-api}/graphql-query-factory.ts +42 -21
- package/src/types.ts +6 -0
- package/src/util/entries-to-actions-converter.ts +1 -1
- package/src/util/entry-factory.ts +13 -22
- package/src/util/path-factory.ts +3 -3
- package/dist/cjs/util/graphql-query-factory.js.map +0 -1
- package/dist/cjs/util/types.js +0 -7
- package/dist/cjs/util/types.js.map +0 -1
- package/dist/esm/util/graphql-query-factory.js.map +0 -1
- package/dist/esm/util/types.js +0 -4
- package/dist/esm/util/types.js.map +0 -1
- package/dist/types/util/graphql-query-factory.d.ts +0 -5
- package/dist/types/util/graphql-query-factory.d.ts.map +0 -1
- package/dist/types/util/types.d.ts +0 -4
- package/dist/types/util/types.d.ts.map +0 -1
- package/src/util/types.ts +0 -3
package/src/github-adapter.ts
CHANGED
|
@@ -1,51 +1,44 @@
|
|
|
1
1
|
import { AxiosCacheInstance, CacheAxiosResponse } from 'axios-cache-interceptor'
|
|
2
|
-
import {
|
|
2
|
+
import {
|
|
3
|
+
Commit,
|
|
4
|
+
CommitDraft,
|
|
5
|
+
Entry,
|
|
6
|
+
ErrorCode,
|
|
7
|
+
GitAdapterError,
|
|
8
|
+
} from '@commitspark/git-adapter'
|
|
3
9
|
import { GitHubRepositoryOptions } from './index'
|
|
4
10
|
import {
|
|
5
|
-
|
|
6
|
-
createBlobsContentQuery,
|
|
11
|
+
createSingleBlobContentQuery,
|
|
7
12
|
createCommitMutation,
|
|
8
13
|
createLatestCommitQuery,
|
|
9
|
-
} from './
|
|
14
|
+
} from './github-api/graphql-query-factory'
|
|
10
15
|
import { convertEntriesToActions } from './util/entries-to-actions-converter'
|
|
11
16
|
import { getPathEntryFolder, getPathSchema } from './util/path-factory'
|
|
12
|
-
import {
|
|
13
|
-
|
|
14
|
-
|
|
17
|
+
import { createEntriesFromFileContent } from './util/entry-factory'
|
|
18
|
+
import { handleGraphQLErrors, handleHttpErrors } from './errors'
|
|
19
|
+
import { getEntryContent } from './github-api/get-entry-content'
|
|
20
|
+
import { getFilePaths } from './github-api/get-file-paths'
|
|
21
|
+
import { GITHUB_GRAPHQL_API_URL } from './types'
|
|
15
22
|
|
|
16
23
|
export const getEntries = async (
|
|
17
24
|
gitRepositoryOptions: GitHubRepositoryOptions,
|
|
18
25
|
axiosCacheInstance: AxiosCacheInstance,
|
|
19
26
|
commitHash: string,
|
|
20
27
|
): Promise<Entry[]> => {
|
|
21
|
-
const
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
const filesContentResponse = await axiosCacheInstance.post(
|
|
26
|
-
API_URL,
|
|
27
|
-
{
|
|
28
|
-
query: queryFilesContent,
|
|
29
|
-
variables: {
|
|
30
|
-
repositoryOwner: gitRepositoryOptions.repositoryOwner,
|
|
31
|
-
repositoryName: gitRepositoryOptions.repositoryName,
|
|
32
|
-
expression: `${commitHash}:${pathEntryFolder}`,
|
|
33
|
-
},
|
|
34
|
-
},
|
|
35
|
-
{
|
|
36
|
-
headers: {
|
|
37
|
-
authorization: `Bearer ${token}`,
|
|
38
|
-
},
|
|
39
|
-
},
|
|
28
|
+
const filenames: string[] = await getFilePaths(
|
|
29
|
+
gitRepositoryOptions,
|
|
30
|
+
axiosCacheInstance,
|
|
31
|
+
commitHash,
|
|
40
32
|
)
|
|
41
33
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
filesContentResponse.data.data.repository.object.entries,
|
|
34
|
+
const filePathsContentMap = await getEntryContent(
|
|
35
|
+
gitRepositoryOptions,
|
|
36
|
+
axiosCacheInstance,
|
|
37
|
+
commitHash,
|
|
38
|
+
filenames,
|
|
48
39
|
)
|
|
40
|
+
|
|
41
|
+
return createEntriesFromFileContent(gitRepositoryOptions, filePathsContentMap)
|
|
49
42
|
}
|
|
50
43
|
|
|
51
44
|
export const getSchema = async (
|
|
@@ -58,27 +51,44 @@ export const getSchema = async (
|
|
|
58
51
|
const token = gitRepositoryOptions.accessToken
|
|
59
52
|
const schemaFilePath = getPathSchema(gitRepositoryOptions)
|
|
60
53
|
|
|
61
|
-
const queryContent =
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
54
|
+
const queryContent = createSingleBlobContentQuery()
|
|
55
|
+
|
|
56
|
+
let response: CacheAxiosResponse | undefined
|
|
57
|
+
try {
|
|
58
|
+
response = await axiosCacheInstance.post(
|
|
59
|
+
GITHUB_GRAPHQL_API_URL,
|
|
60
|
+
{
|
|
61
|
+
query: queryContent,
|
|
62
|
+
variables: {
|
|
63
|
+
repositoryOwner: repositoryOwner,
|
|
64
|
+
repositoryName: repositoryName,
|
|
65
|
+
expression: `${commitHash}:${schemaFilePath}`,
|
|
66
|
+
},
|
|
70
67
|
},
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
68
|
+
{
|
|
69
|
+
headers: {
|
|
70
|
+
authorization: `Bearer ${token}`,
|
|
71
|
+
},
|
|
75
72
|
},
|
|
76
|
-
|
|
77
|
-
)
|
|
73
|
+
)
|
|
74
|
+
} catch (error) {
|
|
75
|
+
handleHttpErrors(error)
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
if (!response) {
|
|
79
|
+
throw new GitAdapterError(
|
|
80
|
+
ErrorCode.INTERNAL_ERROR,
|
|
81
|
+
`Failed to fetch schema`,
|
|
82
|
+
)
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
handleGraphQLErrors(response)
|
|
86
|
+
|
|
78
87
|
const schema = response.data?.data?.repository?.object?.text
|
|
79
88
|
|
|
80
89
|
if (!schema) {
|
|
81
|
-
throw new
|
|
90
|
+
throw new GitAdapterError(
|
|
91
|
+
ErrorCode.NOT_FOUND,
|
|
82
92
|
`"${schemaFilePath}" not found in Git repository "${repositoryOwner}/${repositoryName}" at commit "${commitHash}"`,
|
|
83
93
|
)
|
|
84
94
|
}
|
|
@@ -95,26 +105,40 @@ export const getLatestCommitHash = async (
|
|
|
95
105
|
|
|
96
106
|
const queryLatestCommit = createLatestCommitQuery()
|
|
97
107
|
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
108
|
+
let response: CacheAxiosResponse | undefined
|
|
109
|
+
try {
|
|
110
|
+
response = await axiosCacheInstance.post(
|
|
111
|
+
GITHUB_GRAPHQL_API_URL,
|
|
112
|
+
{
|
|
113
|
+
query: queryLatestCommit,
|
|
114
|
+
variables: {
|
|
115
|
+
repositoryOwner: gitRepositoryOptions.repositoryOwner,
|
|
116
|
+
repositoryName: gitRepositoryOptions.repositoryName,
|
|
117
|
+
ref: ref,
|
|
118
|
+
},
|
|
106
119
|
},
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
120
|
+
{
|
|
121
|
+
cache: false, // must not use cache, so we always get the branch's current head
|
|
122
|
+
headers: {
|
|
123
|
+
authorization: `Bearer ${token}`,
|
|
124
|
+
},
|
|
112
125
|
},
|
|
113
|
-
|
|
114
|
-
)
|
|
126
|
+
)
|
|
127
|
+
} catch (error) {
|
|
128
|
+
handleHttpErrors(error)
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
if (!response) {
|
|
132
|
+
throw new GitAdapterError(
|
|
133
|
+
ErrorCode.INTERNAL_ERROR,
|
|
134
|
+
'Failed to fetch latest commit',
|
|
135
|
+
)
|
|
136
|
+
}
|
|
137
|
+
handleGraphQLErrors(response)
|
|
115
138
|
|
|
116
139
|
if (!response.data.data.repository) {
|
|
117
|
-
throw new
|
|
140
|
+
throw new GitAdapterError(
|
|
141
|
+
ErrorCode.NOT_FOUND,
|
|
118
142
|
`No repository found "${gitRepositoryOptions.repositoryOwner}/${gitRepositoryOptions.repositoryName}"`,
|
|
119
143
|
)
|
|
120
144
|
}
|
|
@@ -124,7 +148,10 @@ export const getLatestCommitHash = async (
|
|
|
124
148
|
response.data.data.repository.object?.oid ??
|
|
125
149
|
undefined
|
|
126
150
|
if (!lastCommit) {
|
|
127
|
-
throw new
|
|
151
|
+
throw new GitAdapterError(
|
|
152
|
+
ErrorCode.NOT_FOUND,
|
|
153
|
+
`No commit found for ref "${ref}"`,
|
|
154
|
+
)
|
|
128
155
|
}
|
|
129
156
|
|
|
130
157
|
return lastCommit
|
|
@@ -144,35 +171,50 @@ export const createCommit = async (
|
|
|
144
171
|
)
|
|
145
172
|
|
|
146
173
|
const mutateCommit = createCommitMutation()
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
174
|
+
|
|
175
|
+
let response: CacheAxiosResponse | undefined
|
|
176
|
+
try {
|
|
177
|
+
response = await axiosCacheInstance.post(
|
|
178
|
+
GITHUB_GRAPHQL_API_URL,
|
|
179
|
+
{
|
|
180
|
+
query: mutateCommit,
|
|
181
|
+
variables: {
|
|
182
|
+
repositoryNameWithOwner: `${gitRepositoryOptions.repositoryOwner}/${gitRepositoryOptions.repositoryName}`,
|
|
183
|
+
branchName: commitDraft.ref,
|
|
184
|
+
commitMessage: commitDraft.message ?? '-',
|
|
185
|
+
precedingCommitSha: commitDraft.parentSha,
|
|
186
|
+
additions: additions,
|
|
187
|
+
deletions: deletions,
|
|
188
|
+
},
|
|
158
189
|
},
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
190
|
+
{
|
|
191
|
+
cache: false,
|
|
192
|
+
headers: {
|
|
193
|
+
authorization: `Bearer ${token}`,
|
|
194
|
+
},
|
|
164
195
|
},
|
|
165
|
-
|
|
166
|
-
)
|
|
196
|
+
)
|
|
197
|
+
} catch (error) {
|
|
198
|
+
handleHttpErrors(error)
|
|
199
|
+
}
|
|
167
200
|
|
|
168
|
-
if (response
|
|
169
|
-
throw new
|
|
201
|
+
if (!response) {
|
|
202
|
+
throw new GitAdapterError(
|
|
203
|
+
ErrorCode.INTERNAL_ERROR,
|
|
204
|
+
`Failed to create commit`,
|
|
205
|
+
)
|
|
170
206
|
}
|
|
171
207
|
|
|
208
|
+
handleGraphQLErrors(response)
|
|
209
|
+
|
|
172
210
|
const mutationResult = response.data.data.commitCreate
|
|
173
211
|
|
|
174
212
|
if (mutationResult.errors) {
|
|
175
|
-
|
|
213
|
+
const errorMessage = JSON.stringify(mutationResult.errors)
|
|
214
|
+
throw new GitAdapterError(
|
|
215
|
+
ErrorCode.BAD_REQUEST,
|
|
216
|
+
`Failed to create commit: ${errorMessage}`,
|
|
217
|
+
)
|
|
176
218
|
}
|
|
177
219
|
|
|
178
220
|
return { ref: mutationResult.commit.oid }
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import { AxiosCacheInstance, CacheAxiosResponse } from 'axios-cache-interceptor'
|
|
2
|
+
import { GitHubRepositoryOptions } from '../index'
|
|
3
|
+
import { createBlobsContentByFilePathsQuery } from './graphql-query-factory'
|
|
4
|
+
import { GITHUB_GRAPHQL_API_URL, QUERY_BATCH_SIZE } from '../types'
|
|
5
|
+
import { handleGraphQLErrors, handleHttpErrors } from '../errors'
|
|
6
|
+
|
|
7
|
+
export const getEntryContent = async (
|
|
8
|
+
gitRepositoryOptions: GitHubRepositoryOptions,
|
|
9
|
+
axiosCacheInstance: AxiosCacheInstance,
|
|
10
|
+
commitHash: string,
|
|
11
|
+
filePaths: string[],
|
|
12
|
+
): Promise<Map<string, string>> => {
|
|
13
|
+
const filePathsContentMap = new Map<string, string>()
|
|
14
|
+
|
|
15
|
+
const { queries, queryFilenameAliasMap } = createBlobsContentByFilePathsQuery(
|
|
16
|
+
filePaths,
|
|
17
|
+
commitHash,
|
|
18
|
+
QUERY_BATCH_SIZE,
|
|
19
|
+
)
|
|
20
|
+
|
|
21
|
+
const requestPromises = []
|
|
22
|
+
for (const contentQuery of queries) {
|
|
23
|
+
try {
|
|
24
|
+
requestPromises.push(
|
|
25
|
+
axiosCacheInstance
|
|
26
|
+
.post(
|
|
27
|
+
GITHUB_GRAPHQL_API_URL,
|
|
28
|
+
{
|
|
29
|
+
query: contentQuery,
|
|
30
|
+
variables: {
|
|
31
|
+
repositoryOwner: gitRepositoryOptions.repositoryOwner,
|
|
32
|
+
repositoryName: gitRepositoryOptions.repositoryName,
|
|
33
|
+
},
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
headers: {
|
|
37
|
+
authorization: `Bearer ${gitRepositoryOptions.accessToken}`,
|
|
38
|
+
},
|
|
39
|
+
timeout: 30000,
|
|
40
|
+
},
|
|
41
|
+
)
|
|
42
|
+
.then((contentResponse) =>
|
|
43
|
+
processContentResponse(
|
|
44
|
+
filePathsContentMap,
|
|
45
|
+
queryFilenameAliasMap,
|
|
46
|
+
contentResponse,
|
|
47
|
+
),
|
|
48
|
+
),
|
|
49
|
+
)
|
|
50
|
+
} catch (error) {
|
|
51
|
+
handleHttpErrors(error)
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
await Promise.all(requestPromises)
|
|
55
|
+
|
|
56
|
+
return filePathsContentMap
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
const processContentResponse = (
|
|
60
|
+
filePathsContentMap: Map<string, string>,
|
|
61
|
+
queryFilenameAliasMap: Map<string, string>,
|
|
62
|
+
contentResponse: CacheAxiosResponse,
|
|
63
|
+
): void => {
|
|
64
|
+
handleGraphQLErrors(contentResponse)
|
|
65
|
+
const filesResponseData = contentResponse.data.data.repository as Record<
|
|
66
|
+
string,
|
|
67
|
+
{ text: string }
|
|
68
|
+
>
|
|
69
|
+
|
|
70
|
+
for (const [queryAlias, fileObject] of Object.entries(filesResponseData)) {
|
|
71
|
+
filePathsContentMap.set(
|
|
72
|
+
queryFilenameAliasMap.get(queryAlias) as string, // we assume we received only those files we know about
|
|
73
|
+
fileObject.text,
|
|
74
|
+
)
|
|
75
|
+
}
|
|
76
|
+
}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { GitHubRepositoryOptions } from '../index'
|
|
2
|
+
import { AxiosCacheInstance } from 'axios-cache-interceptor'
|
|
3
|
+
import { ErrorCode, GitAdapterError } from '@commitspark/git-adapter'
|
|
4
|
+
import { getPathEntryFolder } from '../util/path-factory'
|
|
5
|
+
import { handleHttpErrors } from '../errors'
|
|
6
|
+
import { GITHUB_REST_API_URL } from '../types'
|
|
7
|
+
|
|
8
|
+
export const getFilePaths = async (
|
|
9
|
+
gitRepositoryOptions: GitHubRepositoryOptions,
|
|
10
|
+
axiosCacheInstance: AxiosCacheInstance,
|
|
11
|
+
treeSha: string,
|
|
12
|
+
): Promise<string[]> => {
|
|
13
|
+
const pathEntryFolder = getPathEntryFolder(gitRepositoryOptions)
|
|
14
|
+
const { repositoryOwner, repositoryName, accessToken } = gitRepositoryOptions
|
|
15
|
+
|
|
16
|
+
// hard limit of 100,000 entries and 7MB response size; see https://docs.github.com/en/rest/git/trees?apiVersion=2022-11-28#get-a-tree
|
|
17
|
+
const restApiUrl =
|
|
18
|
+
GITHUB_REST_API_URL +
|
|
19
|
+
`/repos/${repositoryOwner}/${repositoryName}/git/trees/${treeSha}?recursive=1`
|
|
20
|
+
|
|
21
|
+
let response
|
|
22
|
+
try {
|
|
23
|
+
response = await axiosCacheInstance.get(restApiUrl, {
|
|
24
|
+
headers: {
|
|
25
|
+
Authorization: `Bearer ${accessToken}`,
|
|
26
|
+
Accept: 'application/vnd.github+json',
|
|
27
|
+
},
|
|
28
|
+
timeout: 30000,
|
|
29
|
+
})
|
|
30
|
+
} catch (error) {
|
|
31
|
+
handleHttpErrors(error)
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
if (response === undefined) {
|
|
35
|
+
throw new GitAdapterError(
|
|
36
|
+
ErrorCode.INTERNAL_ERROR,
|
|
37
|
+
'Failed to fetch repository file list.',
|
|
38
|
+
)
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
const data = response.data as GitHubTreeResponse
|
|
42
|
+
|
|
43
|
+
if (data.truncated) {
|
|
44
|
+
throw new GitAdapterError(
|
|
45
|
+
ErrorCode.INTERNAL_ERROR,
|
|
46
|
+
`Too many files in repository.`,
|
|
47
|
+
)
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
return data.tree
|
|
51
|
+
.filter(
|
|
52
|
+
(entry) =>
|
|
53
|
+
entry.type === 'blob' && entry.path.startsWith(pathEntryFolder),
|
|
54
|
+
)
|
|
55
|
+
.map((entry) => entry.path)
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
interface GitHubTreeResponse {
|
|
59
|
+
tree: GitHubTreeEntry[]
|
|
60
|
+
truncated: boolean
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
interface GitHubTreeEntry {
|
|
64
|
+
path: string
|
|
65
|
+
type: 'blob' | 'tree' | 'commit'
|
|
66
|
+
}
|
|
@@ -1,18 +1,10 @@
|
|
|
1
|
-
export function
|
|
1
|
+
export function createSingleBlobContentQuery(): string {
|
|
2
2
|
return `
|
|
3
3
|
query ($repositoryOwner: String!, $repositoryName: String!, $expression: String!) {
|
|
4
4
|
repository(owner: $repositoryOwner, name: $repositoryName) {
|
|
5
5
|
object(expression: $expression) {
|
|
6
|
-
... on
|
|
7
|
-
|
|
8
|
-
name
|
|
9
|
-
object {
|
|
10
|
-
__typename
|
|
11
|
-
... on Blob {
|
|
12
|
-
text
|
|
13
|
-
}
|
|
14
|
-
}
|
|
15
|
-
}
|
|
6
|
+
... on Blob {
|
|
7
|
+
text
|
|
16
8
|
}
|
|
17
9
|
}
|
|
18
10
|
}
|
|
@@ -20,18 +12,47 @@ export function createBlobsContentQuery(): string {
|
|
|
20
12
|
`
|
|
21
13
|
}
|
|
22
14
|
|
|
23
|
-
export function
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
15
|
+
export function createBlobsContentByFilePathsQuery(
|
|
16
|
+
filePaths: string[],
|
|
17
|
+
commitHash: string,
|
|
18
|
+
batchSize: number,
|
|
19
|
+
): { queries: string[]; queryFilenameAliasMap: Map<string, string> } {
|
|
20
|
+
const queries = []
|
|
21
|
+
const queryFilenameAliasMap = new Map<string, string>()
|
|
22
|
+
for (
|
|
23
|
+
let fileIndex = 0;
|
|
24
|
+
fileIndex < filePaths.length;
|
|
25
|
+
fileIndex += batchSize
|
|
26
|
+
) {
|
|
27
|
+
// cut file content query into batches and use GraphQL aliases for maximum throughput in regard to GitHub API limits
|
|
28
|
+
|
|
29
|
+
const batchFilenames = filePaths.slice(fileIndex, fileIndex + batchSize)
|
|
30
|
+
|
|
31
|
+
let query = `
|
|
32
|
+
query ($repositoryOwner: String!, $repositoryName: String!) {
|
|
33
|
+
repository(owner: $repositoryOwner, name: $repositoryName) {`
|
|
34
|
+
|
|
35
|
+
for (const [j, filename] of batchFilenames.entries()) {
|
|
36
|
+
const fileAliasIndex = fileIndex + j
|
|
37
|
+
const fileAlias = `file${fileAliasIndex}`
|
|
38
|
+
// using one query variable per file would significantly blow up query size, which would in turn require a lower
|
|
39
|
+
// batch size to avoid GitHub erroring out, and in consequence much lower throughput; we therefore use this poor
|
|
40
|
+
// man's manual escaping of filenames instead and write them directly into the query strings
|
|
41
|
+
const escapedExpression = JSON.stringify(`${commitHash}:${filename}`)
|
|
42
|
+
query += ` ${fileAlias}: object(expression: ${escapedExpression}) {
|
|
43
|
+
... on Blob {
|
|
44
|
+
text
|
|
32
45
|
}
|
|
33
46
|
}
|
|
34
|
-
|
|
47
|
+
`
|
|
48
|
+
queryFilenameAliasMap.set(fileAlias, filename)
|
|
49
|
+
}
|
|
50
|
+
query += ` }
|
|
51
|
+
}`
|
|
52
|
+
queries.push(query)
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
return { queries, queryFilenameAliasMap }
|
|
35
56
|
}
|
|
36
57
|
|
|
37
58
|
export function createCommitMutation(): string {
|
package/src/types.ts
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export const ENTRY_EXTENSION = '.yaml'
|
|
2
|
+
export const PATH_SCHEMA_FILE = 'commitspark/schema/schema.graphql'
|
|
3
|
+
export const PATH_ENTRY_FOLDER = 'commitspark/entries/'
|
|
4
|
+
export const QUERY_BATCH_SIZE = 250
|
|
5
|
+
export const GITHUB_GRAPHQL_API_URL = 'https://api.github.com/graphql'
|
|
6
|
+
export const GITHUB_REST_API_URL = 'https://api.github.com'
|
|
@@ -2,7 +2,7 @@ import { EntryDraft } from '@commitspark/git-adapter'
|
|
|
2
2
|
import { stringify } from 'yaml'
|
|
3
3
|
import { AdditionModel } from '../model/addition.model'
|
|
4
4
|
import { DeletionModel } from '../model/deletion.model'
|
|
5
|
-
import { ENTRY_EXTENSION } from '
|
|
5
|
+
import { ENTRY_EXTENSION } from '../types'
|
|
6
6
|
|
|
7
7
|
export function convertEntriesToActions(
|
|
8
8
|
entryDrafts: EntryDraft[],
|
|
@@ -1,29 +1,20 @@
|
|
|
1
1
|
import { parse } from 'yaml'
|
|
2
2
|
import { Entry } from '@commitspark/git-adapter'
|
|
3
|
-
import { ENTRY_EXTENSION } from '
|
|
3
|
+
import { ENTRY_EXTENSION } from '../types'
|
|
4
|
+
import { getPathEntryFolder } from './path-factory'
|
|
5
|
+
import { GitHubRepositoryOptions } from '../index'
|
|
4
6
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
__typename: string
|
|
9
|
-
text: string
|
|
10
|
-
}
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
export function createEntriesFromBlobsQueryResponseData(
|
|
14
|
-
entries: TreeEntry[],
|
|
7
|
+
export function createEntriesFromFileContent(
|
|
8
|
+
gitRepositoryOptions: GitHubRepositoryOptions,
|
|
9
|
+
filePathContentMap: Map<string, string>,
|
|
15
10
|
): Entry[] {
|
|
16
|
-
return
|
|
17
|
-
.filter(
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
const fileContent = parse(entry.object.text)
|
|
24
|
-
const id = entry.name.substring(
|
|
25
|
-
0,
|
|
26
|
-
entry.name.length - ENTRY_EXTENSION.length,
|
|
11
|
+
return Array.from(filePathContentMap)
|
|
12
|
+
.filter(([filePath]) => filePath.endsWith(ENTRY_EXTENSION))
|
|
13
|
+
.map(([filePath, content]) => {
|
|
14
|
+
const fileContent = parse(content)
|
|
15
|
+
const id = filePath.substring(
|
|
16
|
+
getPathEntryFolder(gitRepositoryOptions).length, // strip folder path back out
|
|
17
|
+
filePath.length - ENTRY_EXTENSION.length,
|
|
27
18
|
)
|
|
28
19
|
return {
|
|
29
20
|
id: id,
|
package/src/util/path-factory.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { GitHubRepositoryOptions } from '../index'
|
|
2
|
-
import { PATH_ENTRY_FOLDER, PATH_SCHEMA_FILE } from '
|
|
2
|
+
import { PATH_ENTRY_FOLDER, PATH_SCHEMA_FILE } from '../types'
|
|
3
3
|
|
|
4
4
|
export function getPathSchema(gitRepositoryOptions: GitHubRepositoryOptions) {
|
|
5
5
|
return gitRepositoryOptions.pathSchemaFile ?? PATH_SCHEMA_FILE
|
|
@@ -11,8 +11,8 @@ export function getPathEntryFolder(
|
|
|
11
11
|
const pathEntryFolder =
|
|
12
12
|
gitRepositoryOptions.pathEntryFolder ?? PATH_ENTRY_FOLDER
|
|
13
13
|
|
|
14
|
-
if (pathEntryFolder.endsWith('/')) {
|
|
15
|
-
return pathEntryFolder
|
|
14
|
+
if (!pathEntryFolder.endsWith('/')) {
|
|
15
|
+
return pathEntryFolder + '/'
|
|
16
16
|
}
|
|
17
17
|
|
|
18
18
|
return pathEntryFolder
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"graphql-query-factory.js","sourceRoot":"","sources":["../../../src/util/graphql-query-factory.ts"],"names":[],"mappings":";;AAAA,0DAoBC;AAED,wDAYC;AAED,oDA+BC;AAED,0DAeC;AApFD,SAAgB,uBAAuB;IACrC,OAAO;;;;;;;;;;;;;;;;;;KAkBJ,CAAA;AACL,CAAC;AAED,SAAgB,sBAAsB;IACpC,OAAO;;;;;;;;;;KAUJ,CAAA;AACL,CAAC;AAED,SAAgB,oBAAoB;IAClC,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KA6BJ,CAAA;AACL,CAAC;AAED,SAAgB,uBAAuB;IACrC,OAAO;;;;;;;;;;;;;KAaJ,CAAA;AACL,CAAC"}
|
package/dist/cjs/util/types.js
DELETED
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.PATH_ENTRY_FOLDER = exports.PATH_SCHEMA_FILE = exports.ENTRY_EXTENSION = void 0;
|
|
4
|
-
exports.ENTRY_EXTENSION = '.yaml';
|
|
5
|
-
exports.PATH_SCHEMA_FILE = 'commitspark/schema/schema.graphql';
|
|
6
|
-
exports.PATH_ENTRY_FOLDER = 'commitspark/entries/';
|
|
7
|
-
//# sourceMappingURL=types.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/util/types.ts"],"names":[],"mappings":";;;AAAa,QAAA,eAAe,GAAG,OAAO,CAAA;AACzB,QAAA,gBAAgB,GAAG,mCAAmC,CAAA;AACtD,QAAA,iBAAiB,GAAG,sBAAsB,CAAA"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"graphql-query-factory.js","sourceRoot":"","sources":["../../../src/util/graphql-query-factory.ts"],"names":[],"mappings":"AAAA,MAAM,UAAU,uBAAuB;IACrC,OAAO;;;;;;;;;;;;;;;;;;KAkBJ,CAAA;AACL,CAAC;AAED,MAAM,UAAU,sBAAsB;IACpC,OAAO;;;;;;;;;;KAUJ,CAAA;AACL,CAAC;AAED,MAAM,UAAU,oBAAoB;IAClC,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KA6BJ,CAAA;AACL,CAAC;AAED,MAAM,UAAU,uBAAuB;IACrC,OAAO;;;;;;;;;;;;;KAaJ,CAAA;AACL,CAAC"}
|
package/dist/esm/util/types.js
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/util/types.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,eAAe,GAAG,OAAO,CAAA;AACtC,MAAM,CAAC,MAAM,gBAAgB,GAAG,mCAAmC,CAAA;AACnE,MAAM,CAAC,MAAM,iBAAiB,GAAG,sBAAsB,CAAA"}
|
|
@@ -1,5 +0,0 @@
|
|
|
1
|
-
export declare function createBlobsContentQuery(): string;
|
|
2
|
-
export declare function createBlobContentQuery(): string;
|
|
3
|
-
export declare function createCommitMutation(): string;
|
|
4
|
-
export declare function createLatestCommitQuery(): string;
|
|
5
|
-
//# sourceMappingURL=graphql-query-factory.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"graphql-query-factory.d.ts","sourceRoot":"","sources":["../../../src/util/graphql-query-factory.ts"],"names":[],"mappings":"AAAA,wBAAgB,uBAAuB,IAAI,MAAM,CAoBhD;AAED,wBAAgB,sBAAsB,IAAI,MAAM,CAY/C;AAED,wBAAgB,oBAAoB,IAAI,MAAM,CA+B7C;AAED,wBAAgB,uBAAuB,IAAI,MAAM,CAehD"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/util/types.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,eAAe,UAAU,CAAA;AACtC,eAAO,MAAM,gBAAgB,sCAAsC,CAAA;AACnE,eAAO,MAAM,iBAAiB,yBAAyB,CAAA"}
|
package/src/util/types.ts
DELETED