decap-cms-backend-github 2.15.0-beta.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.
@@ -0,0 +1,98 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.treeEntry = exports.repository = exports.pullRequest = exports.object = exports.fileEntry = exports.branch = exports.blobWithText = void 0;
7
+ var _graphqlTag = require("graphql-tag");
8
+ const repository = (0, _graphqlTag.gql)`
9
+ fragment RepositoryParts on Repository {
10
+ id
11
+ isFork
12
+ }
13
+ `;
14
+ exports.repository = repository;
15
+ const blobWithText = (0, _graphqlTag.gql)`
16
+ fragment BlobWithTextParts on Blob {
17
+ id
18
+ text
19
+ is_binary: isBinary
20
+ }
21
+ `;
22
+ exports.blobWithText = blobWithText;
23
+ const object = (0, _graphqlTag.gql)`
24
+ fragment ObjectParts on GitObject {
25
+ id
26
+ sha: oid
27
+ }
28
+ `;
29
+ exports.object = object;
30
+ const branch = (0, _graphqlTag.gql)`
31
+ fragment BranchParts on Ref {
32
+ commit: target {
33
+ ...ObjectParts
34
+ }
35
+ id
36
+ name
37
+ prefix
38
+ repository {
39
+ ...RepositoryParts
40
+ }
41
+ }
42
+ ${object}
43
+ ${repository}
44
+ `;
45
+ exports.branch = branch;
46
+ const pullRequest = (0, _graphqlTag.gql)`
47
+ fragment PullRequestParts on PullRequest {
48
+ id
49
+ baseRefName
50
+ baseRefOid
51
+ body
52
+ headRefName
53
+ headRefOid
54
+ number
55
+ state
56
+ title
57
+ merged_at: mergedAt
58
+ updated_at: updatedAt
59
+ user: author {
60
+ login
61
+ ... on User {
62
+ name
63
+ }
64
+ }
65
+ repository {
66
+ ...RepositoryParts
67
+ }
68
+ labels(last: 100) {
69
+ nodes {
70
+ name
71
+ }
72
+ }
73
+ }
74
+ ${repository}
75
+ `;
76
+ exports.pullRequest = pullRequest;
77
+ const treeEntry = (0, _graphqlTag.gql)`
78
+ fragment TreeEntryParts on TreeEntry {
79
+ path: name
80
+ sha: oid
81
+ type
82
+ mode
83
+ }
84
+ `;
85
+ exports.treeEntry = treeEntry;
86
+ const fileEntry = (0, _graphqlTag.gql)`
87
+ fragment FileEntryParts on TreeEntry {
88
+ name
89
+ sha: oid
90
+ type
91
+ blob: object {
92
+ ... on Blob {
93
+ size: byteSize
94
+ }
95
+ }
96
+ }
97
+ `;
98
+ exports.fileEntry = fileEntry;
@@ -0,0 +1,585 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.default = void 0;
7
+ var React = _interopRequireWildcard(require("react"));
8
+ var _semaphore = _interopRequireDefault(require("semaphore"));
9
+ var _trimStart = _interopRequireDefault(require("lodash/trimStart"));
10
+ var _commonTags = require("common-tags");
11
+ var _decapCmsLibUtil = require("decap-cms-lib-util");
12
+ var _AuthenticationPage = _interopRequireDefault(require("./AuthenticationPage"));
13
+ var _API = _interopRequireWildcard(require("./API"));
14
+ var _GraphQLAPI = _interopRequireDefault(require("./GraphQLAPI"));
15
+ var _core = require("@emotion/core");
16
+ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
17
+ function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
18
+ function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
19
+ function _extends() { _extends = Object.assign ? Object.assign.bind() : function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }
20
+ function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); enumerableOnly && (symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; })), keys.push.apply(keys, symbols); } return keys; }
21
+ function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = null != arguments[i] ? arguments[i] : {}; i % 2 ? ownKeys(Object(source), !0).forEach(function (key) { _defineProperty(target, key, source[key]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } return target; }
22
+ function _defineProperty(obj, key, value) { key = _toPropertyKey(key); if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
23
+ function _toPropertyKey(arg) { var key = _toPrimitive(arg, "string"); return typeof key === "symbol" ? key : String(key); }
24
+ function _toPrimitive(input, hint) { if (typeof input !== "object" || input === null) return input; var prim = input[Symbol.toPrimitive]; if (prim !== undefined) { var res = prim.call(input, hint || "default"); if (typeof res !== "object") return res; throw new TypeError("@@toPrimitive must return a primitive value."); } return (hint === "string" ? String : Number)(input); }
25
+ const MAX_CONCURRENT_DOWNLOADS = 10;
26
+ const {
27
+ fetchWithTimeout: fetch
28
+ } = _decapCmsLibUtil.unsentRequest;
29
+ const STATUS_PAGE = 'https://www.githubstatus.com';
30
+ const GITHUB_STATUS_ENDPOINT = `${STATUS_PAGE}/api/v2/components.json`;
31
+ const GITHUB_OPERATIONAL_UNITS = ['API Requests', 'Issues, Pull Requests, Projects'];
32
+ class GitHub {
33
+ constructor(config, options = {}) {
34
+ var _config$backend$branc;
35
+ _defineProperty(this, "lock", void 0);
36
+ _defineProperty(this, "api", void 0);
37
+ _defineProperty(this, "options", void 0);
38
+ _defineProperty(this, "originRepo", void 0);
39
+ _defineProperty(this, "repo", void 0);
40
+ _defineProperty(this, "openAuthoringEnabled", void 0);
41
+ _defineProperty(this, "useOpenAuthoring", void 0);
42
+ _defineProperty(this, "alwaysForkEnabled", void 0);
43
+ _defineProperty(this, "branch", void 0);
44
+ _defineProperty(this, "apiRoot", void 0);
45
+ _defineProperty(this, "mediaFolder", void 0);
46
+ _defineProperty(this, "previewContext", void 0);
47
+ _defineProperty(this, "token", void 0);
48
+ _defineProperty(this, "squashMerges", void 0);
49
+ _defineProperty(this, "cmsLabelPrefix", void 0);
50
+ _defineProperty(this, "useGraphql", void 0);
51
+ _defineProperty(this, "_currentUserPromise", void 0);
52
+ _defineProperty(this, "_userIsOriginMaintainerPromises", void 0);
53
+ _defineProperty(this, "_mediaDisplayURLSem", void 0);
54
+ _defineProperty(this, "getCursorAndFiles", (files, page) => {
55
+ const pageSize = 20;
56
+ const count = files.length;
57
+ const pageCount = Math.ceil(files.length / pageSize);
58
+ const actions = [];
59
+ if (page > 1) {
60
+ actions.push('prev');
61
+ actions.push('first');
62
+ }
63
+ if (page < pageCount) {
64
+ actions.push('next');
65
+ actions.push('last');
66
+ }
67
+ const cursor = _decapCmsLibUtil.Cursor.create({
68
+ actions,
69
+ meta: {
70
+ page,
71
+ count,
72
+ pageSize,
73
+ pageCount
74
+ },
75
+ data: {
76
+ files
77
+ }
78
+ });
79
+ const pageFiles = files.slice((page - 1) * pageSize, page * pageSize);
80
+ return {
81
+ cursor,
82
+ files: pageFiles
83
+ };
84
+ });
85
+ this.options = _objectSpread({
86
+ proxied: false,
87
+ API: null,
88
+ initialWorkflowStatus: ''
89
+ }, options);
90
+ if (!this.options.proxied && (config.backend.repo === null || config.backend.repo === undefined)) {
91
+ throw new Error('The GitHub backend needs a "repo" in the backend configuration.');
92
+ }
93
+ this.api = this.options.API || null;
94
+ this.openAuthoringEnabled = config.backend.open_authoring || false;
95
+ if (this.openAuthoringEnabled) {
96
+ if (!this.options.useWorkflow) {
97
+ throw new Error('backend.open_authoring is true but publish_mode is not set to editorial_workflow.');
98
+ }
99
+ this.originRepo = config.backend.repo || '';
100
+ } else {
101
+ this.repo = this.originRepo = config.backend.repo || '';
102
+ }
103
+ this.alwaysForkEnabled = config.backend.always_fork || false;
104
+ this.branch = ((_config$backend$branc = config.backend.branch) === null || _config$backend$branc === void 0 ? void 0 : _config$backend$branc.trim()) || 'master';
105
+ this.apiRoot = config.backend.api_root || 'https://api.github.com';
106
+ this.token = '';
107
+ this.squashMerges = config.backend.squash_merges || false;
108
+ this.cmsLabelPrefix = config.backend.cms_label_prefix || '';
109
+ this.useGraphql = config.backend.use_graphql || false;
110
+ this.mediaFolder = config.media_folder;
111
+ this.previewContext = config.backend.preview_context || '';
112
+ this.lock = (0, _decapCmsLibUtil.asyncLock)();
113
+ }
114
+ isGitBackend() {
115
+ return true;
116
+ }
117
+ async status() {
118
+ const api = await fetch(GITHUB_STATUS_ENDPOINT).then(res => res.json()).then(res => {
119
+ return res['components'].filter(statusComponent => GITHUB_OPERATIONAL_UNITS.includes(statusComponent.name)).every(statusComponent => statusComponent.status === 'operational');
120
+ }).catch(e => {
121
+ console.warn('Failed getting GitHub status', e);
122
+ return true;
123
+ });
124
+ let auth = false;
125
+ // no need to check auth if api is down
126
+ if (api) {
127
+ var _this$api;
128
+ auth = (await ((_this$api = this.api) === null || _this$api === void 0 ? void 0 : _this$api.getUser().then(user => !!user).catch(e => {
129
+ console.warn('Failed getting GitHub user', e);
130
+ return false;
131
+ }))) || false;
132
+ }
133
+ return {
134
+ auth: {
135
+ status: auth
136
+ },
137
+ api: {
138
+ status: api,
139
+ statusPage: STATUS_PAGE
140
+ }
141
+ };
142
+ }
143
+ authComponent() {
144
+ const wrappedAuthenticationPage = props => (0, _core.jsx)(_AuthenticationPage.default, _extends({}, props, {
145
+ backend: this
146
+ }));
147
+ wrappedAuthenticationPage.displayName = 'AuthenticationPage';
148
+ return wrappedAuthenticationPage;
149
+ }
150
+ restoreUser(user) {
151
+ return this.openAuthoringEnabled ? this.authenticateWithFork({
152
+ userData: user,
153
+ getPermissionToFork: () => true
154
+ }).then(() => this.authenticate(user)) : this.authenticate(user);
155
+ }
156
+ async pollUntilForkExists({
157
+ repo,
158
+ token
159
+ }) {
160
+ const pollDelay = 250; // milliseconds
161
+ let repoExists = false;
162
+ while (!repoExists) {
163
+ repoExists = await fetch(`${this.apiRoot}/repos/${repo}`, {
164
+ headers: {
165
+ Authorization: `token ${token}`
166
+ }
167
+ }).then(() => true).catch(err => {
168
+ if (err && err.status === 404) {
169
+ console.log('This 404 was expected and handled appropriately.');
170
+ return false;
171
+ } else {
172
+ return Promise.reject(err);
173
+ }
174
+ });
175
+ // wait between polls
176
+ if (!repoExists) {
177
+ await new Promise(resolve => setTimeout(resolve, pollDelay));
178
+ }
179
+ }
180
+ return Promise.resolve();
181
+ }
182
+ async currentUser({
183
+ token
184
+ }) {
185
+ if (!this._currentUserPromise) {
186
+ this._currentUserPromise = fetch(`${this.apiRoot}/user`, {
187
+ headers: {
188
+ Authorization: `token ${token}`
189
+ }
190
+ }).then(res => res.json());
191
+ }
192
+ return this._currentUserPromise;
193
+ }
194
+ async userIsOriginMaintainer({
195
+ username: usernameArg,
196
+ token
197
+ }) {
198
+ const username = usernameArg || (await this.currentUser({
199
+ token
200
+ })).login;
201
+ this._userIsOriginMaintainerPromises = this._userIsOriginMaintainerPromises || {};
202
+ if (!this._userIsOriginMaintainerPromises[username]) {
203
+ this._userIsOriginMaintainerPromises[username] = fetch(`${this.apiRoot}/repos/${this.originRepo}/collaborators/${username}/permission`, {
204
+ headers: {
205
+ Authorization: `token ${token}`
206
+ }
207
+ }).then(res => res.json()).then(({
208
+ permission
209
+ }) => permission === 'admin' || permission === 'write');
210
+ }
211
+ return this._userIsOriginMaintainerPromises[username];
212
+ }
213
+ async forkExists({
214
+ token
215
+ }) {
216
+ try {
217
+ const currentUser = await this.currentUser({
218
+ token
219
+ });
220
+ const repoName = this.originRepo.split('/')[1];
221
+ const repo = await fetch(`${this.apiRoot}/repos/${currentUser.login}/${repoName}`, {
222
+ method: 'GET',
223
+ headers: {
224
+ Authorization: `token ${token}`
225
+ }
226
+ }).then(res => res.json());
227
+
228
+ // https://developer.github.com/v3/repos/#get
229
+ // The parent and source objects are present when the repository is a fork.
230
+ // parent is the repository this repository was forked from, source is the ultimate source for the network.
231
+ const forkExists = repo.fork === true && repo.parent && repo.parent.full_name.toLowerCase() === this.originRepo.toLowerCase();
232
+ return forkExists;
233
+ } catch {
234
+ return false;
235
+ }
236
+ }
237
+ async authenticateWithFork({
238
+ userData,
239
+ getPermissionToFork
240
+ }) {
241
+ if (!this.openAuthoringEnabled) {
242
+ throw new Error('Cannot authenticate with fork; Open Authoring is turned off.');
243
+ }
244
+ const token = userData.token;
245
+
246
+ // Origin maintainers should be able to use the CMS normally. If alwaysFork
247
+ // is enabled we always fork (and avoid the origin maintainer check)
248
+ if (!this.alwaysForkEnabled && (await this.userIsOriginMaintainer({
249
+ token
250
+ }))) {
251
+ this.repo = this.originRepo;
252
+ this.useOpenAuthoring = false;
253
+ return Promise.resolve();
254
+ }
255
+ if (!(await this.forkExists({
256
+ token
257
+ }))) {
258
+ await getPermissionToFork();
259
+ }
260
+ const fork = await fetch(`${this.apiRoot}/repos/${this.originRepo}/forks`, {
261
+ method: 'POST',
262
+ headers: {
263
+ Authorization: `token ${token}`
264
+ }
265
+ }).then(res => res.json());
266
+ this.useOpenAuthoring = true;
267
+ this.repo = fork.full_name;
268
+ return this.pollUntilForkExists({
269
+ repo: fork.full_name,
270
+ token
271
+ });
272
+ }
273
+ async authenticate(state) {
274
+ this.token = state.token;
275
+ const apiCtor = this.useGraphql ? _GraphQLAPI.default : _API.default;
276
+ this.api = new apiCtor({
277
+ token: this.token,
278
+ branch: this.branch,
279
+ repo: this.repo,
280
+ originRepo: this.originRepo,
281
+ apiRoot: this.apiRoot,
282
+ squashMerges: this.squashMerges,
283
+ cmsLabelPrefix: this.cmsLabelPrefix,
284
+ useOpenAuthoring: this.useOpenAuthoring,
285
+ initialWorkflowStatus: this.options.initialWorkflowStatus
286
+ });
287
+ const user = await this.api.user();
288
+ const isCollab = await this.api.hasWriteAccess().catch(error => {
289
+ error.message = (0, _commonTags.stripIndent)`
290
+ Repo "${this.repo}" not found.
291
+
292
+ Please ensure the repo information is spelled correctly.
293
+
294
+ If the repo is private, make sure you're logged into a GitHub account with access.
295
+
296
+ If your repo is under an organization, ensure the organization has granted access to Decap CMS.
297
+ `;
298
+ throw error;
299
+ });
300
+
301
+ // Unauthorized user
302
+ if (!isCollab) {
303
+ throw new Error('Your GitHub user account does not have access to this repo.');
304
+ }
305
+
306
+ // Authorized user
307
+ return _objectSpread(_objectSpread({}, user), {}, {
308
+ token: state.token,
309
+ useOpenAuthoring: this.useOpenAuthoring
310
+ });
311
+ }
312
+ logout() {
313
+ this.token = null;
314
+ if (this.api && this.api.reset && typeof this.api.reset === 'function') {
315
+ return this.api.reset();
316
+ }
317
+ }
318
+ getToken() {
319
+ return Promise.resolve(this.token);
320
+ }
321
+ async entriesByFolder(folder, extension, depth) {
322
+ const repoURL = this.api.originRepoURL;
323
+ let cursor;
324
+ const listFiles = () => this.api.listFiles(folder, {
325
+ repoURL,
326
+ depth
327
+ }).then(files => {
328
+ const filtered = files.filter(file => (0, _decapCmsLibUtil.filterByExtension)(file, extension));
329
+ const result = this.getCursorAndFiles(filtered, 1);
330
+ cursor = result.cursor;
331
+ return result.files;
332
+ });
333
+ const readFile = (path, id) => this.api.readFile(path, id, {
334
+ repoURL
335
+ });
336
+ const files = await (0, _decapCmsLibUtil.entriesByFolder)(listFiles, readFile, this.api.readFileMetadata.bind(this.api), _API.API_NAME);
337
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
338
+ // @ts-ignore
339
+ files[_decapCmsLibUtil.CURSOR_COMPATIBILITY_SYMBOL] = cursor;
340
+ return files;
341
+ }
342
+ async allEntriesByFolder(folder, extension, depth) {
343
+ const repoURL = this.api.originRepoURL;
344
+ const listFiles = () => this.api.listFiles(folder, {
345
+ repoURL,
346
+ depth
347
+ }).then(files => files.filter(file => (0, _decapCmsLibUtil.filterByExtension)(file, extension)));
348
+ const readFile = (path, id) => {
349
+ return this.api.readFile(path, id, {
350
+ repoURL
351
+ });
352
+ };
353
+ const files = await (0, _decapCmsLibUtil.entriesByFolder)(listFiles, readFile, this.api.readFileMetadata.bind(this.api), _API.API_NAME);
354
+ return files;
355
+ }
356
+ entriesByFiles(files) {
357
+ const repoURL = this.useOpenAuthoring ? this.api.originRepoURL : this.api.repoURL;
358
+ const readFile = (path, id) => this.api.readFile(path, id, {
359
+ repoURL
360
+ }).catch(() => '');
361
+ return (0, _decapCmsLibUtil.entriesByFiles)(files, readFile, this.api.readFileMetadata.bind(this.api), _API.API_NAME);
362
+ }
363
+
364
+ // Fetches a single entry.
365
+ getEntry(path) {
366
+ const repoURL = this.api.originRepoURL;
367
+ return this.api.readFile(path, null, {
368
+ repoURL
369
+ }).then(data => ({
370
+ file: {
371
+ path,
372
+ id: null
373
+ },
374
+ data: data
375
+ })).catch(() => ({
376
+ file: {
377
+ path,
378
+ id: null
379
+ },
380
+ data: ''
381
+ }));
382
+ }
383
+ getMedia(mediaFolder = this.mediaFolder) {
384
+ return this.api.listFiles(mediaFolder).then(files => files.map(({
385
+ id,
386
+ name,
387
+ size,
388
+ path
389
+ }) => {
390
+ // load media using getMediaDisplayURL to avoid token expiration with GitHub raw content urls
391
+ // for private repositories
392
+ return {
393
+ id,
394
+ name,
395
+ size,
396
+ displayURL: {
397
+ id,
398
+ path
399
+ },
400
+ path
401
+ };
402
+ }));
403
+ }
404
+ async getMediaFile(path) {
405
+ const blob = await (0, _decapCmsLibUtil.getMediaAsBlob)(path, null, this.api.readFile.bind(this.api));
406
+ const name = (0, _decapCmsLibUtil.basename)(path);
407
+ const fileObj = (0, _decapCmsLibUtil.blobToFileObj)(name, blob);
408
+ const url = URL.createObjectURL(fileObj);
409
+ const id = await (0, _decapCmsLibUtil.getBlobSHA)(blob);
410
+ return {
411
+ id,
412
+ displayURL: url,
413
+ path,
414
+ name,
415
+ size: fileObj.size,
416
+ file: fileObj,
417
+ url
418
+ };
419
+ }
420
+ getMediaDisplayURL(displayURL) {
421
+ this._mediaDisplayURLSem = this._mediaDisplayURLSem || (0, _semaphore.default)(MAX_CONCURRENT_DOWNLOADS);
422
+ return (0, _decapCmsLibUtil.getMediaDisplayURL)(displayURL, this.api.readFile.bind(this.api), this._mediaDisplayURLSem);
423
+ }
424
+ persistEntry(entry, options) {
425
+ // persistEntry is a transactional operation
426
+ return (0, _decapCmsLibUtil.runWithLock)(this.lock, () => this.api.persistFiles(entry.dataFiles, entry.assets, options), 'Failed to acquire persist entry lock');
427
+ }
428
+ async persistMedia(mediaFile, options) {
429
+ try {
430
+ await this.api.persistFiles([], [mediaFile], options);
431
+ const {
432
+ sha,
433
+ path,
434
+ fileObj
435
+ } = mediaFile;
436
+ const displayURL = fileObj ? URL.createObjectURL(fileObj) : '';
437
+ return {
438
+ id: sha,
439
+ name: fileObj.name,
440
+ size: fileObj.size,
441
+ displayURL,
442
+ path: (0, _trimStart.default)(path, '/')
443
+ };
444
+ } catch (error) {
445
+ console.error(error);
446
+ throw error;
447
+ }
448
+ }
449
+ deleteFiles(paths, commitMessage) {
450
+ return this.api.deleteFiles(paths, commitMessage);
451
+ }
452
+ async traverseCursor(cursor, action) {
453
+ const meta = cursor.meta;
454
+ const files = cursor.data.get('files').toJS();
455
+ let result;
456
+ switch (action) {
457
+ case 'first':
458
+ {
459
+ result = this.getCursorAndFiles(files, 1);
460
+ break;
461
+ }
462
+ case 'last':
463
+ {
464
+ result = this.getCursorAndFiles(files, meta.get('pageCount'));
465
+ break;
466
+ }
467
+ case 'next':
468
+ {
469
+ result = this.getCursorAndFiles(files, meta.get('page') + 1);
470
+ break;
471
+ }
472
+ case 'prev':
473
+ {
474
+ result = this.getCursorAndFiles(files, meta.get('page') - 1);
475
+ break;
476
+ }
477
+ default:
478
+ {
479
+ result = this.getCursorAndFiles(files, 1);
480
+ break;
481
+ }
482
+ }
483
+ const readFile = (path, id) => this.api.readFile(path, id, {
484
+ repoURL: this.api.originRepoURL
485
+ }).catch(() => '');
486
+ const entries = await (0, _decapCmsLibUtil.entriesByFiles)(result.files, readFile, this.api.readFileMetadata.bind(this.api), _API.API_NAME);
487
+ return {
488
+ entries,
489
+ cursor: result.cursor
490
+ };
491
+ }
492
+ async loadMediaFile(branch, file) {
493
+ const readFile = (path, id, {
494
+ parseText
495
+ }) => this.api.readFile(path, id, {
496
+ branch,
497
+ parseText
498
+ });
499
+ const blob = await (0, _decapCmsLibUtil.getMediaAsBlob)(file.path, file.id, readFile);
500
+ const name = (0, _decapCmsLibUtil.basename)(file.path);
501
+ const fileObj = (0, _decapCmsLibUtil.blobToFileObj)(name, blob);
502
+ return {
503
+ id: file.id,
504
+ displayURL: URL.createObjectURL(fileObj),
505
+ path: file.path,
506
+ name,
507
+ size: fileObj.size,
508
+ file: fileObj
509
+ };
510
+ }
511
+ async unpublishedEntries() {
512
+ const listEntriesKeys = () => this.api.listUnpublishedBranches().then(branches => branches.map(branch => (0, _decapCmsLibUtil.contentKeyFromBranch)(branch)));
513
+ const ids = await (0, _decapCmsLibUtil.unpublishedEntries)(listEntriesKeys);
514
+ return ids;
515
+ }
516
+ async unpublishedEntry({
517
+ id,
518
+ collection,
519
+ slug
520
+ }) {
521
+ if (id) {
522
+ const data = await this.api.retrieveUnpublishedEntryData(id);
523
+ return data;
524
+ } else if (collection && slug) {
525
+ const entryId = this.api.generateContentKey(collection, slug);
526
+ const data = await this.api.retrieveUnpublishedEntryData(entryId);
527
+ return data;
528
+ } else {
529
+ throw new Error('Missing unpublished entry id or collection and slug');
530
+ }
531
+ }
532
+ getBranch(collection, slug) {
533
+ const contentKey = this.api.generateContentKey(collection, slug);
534
+ const branch = (0, _decapCmsLibUtil.branchFromContentKey)(contentKey);
535
+ return branch;
536
+ }
537
+ async unpublishedEntryDataFile(collection, slug, path, id) {
538
+ const branch = this.getBranch(collection, slug);
539
+ const data = await this.api.readFile(path, id, {
540
+ branch
541
+ });
542
+ return data;
543
+ }
544
+ async unpublishedEntryMediaFile(collection, slug, path, id) {
545
+ const branch = this.getBranch(collection, slug);
546
+ const mediaFile = await this.loadMediaFile(branch, {
547
+ path,
548
+ id
549
+ });
550
+ return mediaFile;
551
+ }
552
+ async getDeployPreview(collection, slug) {
553
+ try {
554
+ const statuses = await this.api.getStatuses(collection, slug);
555
+ const deployStatus = (0, _decapCmsLibUtil.getPreviewStatus)(statuses, this.previewContext);
556
+ if (deployStatus) {
557
+ const {
558
+ target_url: url,
559
+ state
560
+ } = deployStatus;
561
+ return {
562
+ url,
563
+ status: state
564
+ };
565
+ } else {
566
+ return null;
567
+ }
568
+ } catch (e) {
569
+ return null;
570
+ }
571
+ }
572
+ updateUnpublishedEntryStatus(collection, slug, newStatus) {
573
+ // updateUnpublishedEntryStatus is a transactional operation
574
+ return (0, _decapCmsLibUtil.runWithLock)(this.lock, () => this.api.updateUnpublishedEntryStatus(collection, slug, newStatus), 'Failed to acquire update entry status lock');
575
+ }
576
+ deleteUnpublishedEntry(collection, slug) {
577
+ // deleteUnpublishedEntry is a transactional operation
578
+ return (0, _decapCmsLibUtil.runWithLock)(this.lock, () => this.api.deleteUnpublishedEntry(collection, slug), 'Failed to acquire delete entry lock');
579
+ }
580
+ publishUnpublishedEntry(collection, slug) {
581
+ // publishUnpublishedEntry is a transactional operation
582
+ return (0, _decapCmsLibUtil.runWithLock)(this.lock, () => this.api.publishUnpublishedEntry(collection, slug), 'Failed to acquire publish entry lock');
583
+ }
584
+ }
585
+ exports.default = GitHub;