planning
All checks were successful
Publish To Prod / deploy_and_publish (push) Successful in 35s

This commit is contained in:
2024-10-14 09:15:30 +02:00
parent bcba00a730
commit 6e64e138e2
21059 changed files with 2317811 additions and 1 deletions

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,23 @@
/*!
* The buffer module from node.js, for the browser.
*
* @author Feross Aboukhadijeh <https://feross.org>
* @license MIT
*/
/*! *****************************************************************************
Copyright (c) Microsoft Corporation.
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
***************************************************************************** */
/*! ieee754. BSD-3-Clause License. Feross Aboukhadijeh <https://feross.org/opensource> */

File diff suppressed because one or more lines are too long

818
node_modules/decap-cms-backend-gitlab/dist/esm/API.js generated vendored Normal file
View File

@@ -0,0 +1,818 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = exports.API_NAME = void 0;
exports.getMaxAccess = getMaxAccess;
var _trimStart2 = _interopRequireDefault(require("lodash/trimStart"));
var _result2 = _interopRequireDefault(require("lodash/result"));
var _partial2 = _interopRequireDefault(require("lodash/partial"));
var _flow2 = _interopRequireDefault(require("lodash/flow"));
var _apolloClient = require("apollo-client");
var _apolloCacheInmemory = require("apollo-cache-inmemory");
var _apolloLinkHttp = require("apollo-link-http");
var _apolloLinkContext = require("apollo-link-context");
var _decapCmsLibUtil = require("decap-cms-lib-util");
var _jsBase = require("js-base64");
var _immutable = require("immutable");
var _path = require("path");
var queries = _interopRequireWildcard(require("./queries"));
function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && Object.prototype.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
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; }
function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == typeof i ? i : String(i); }
function _toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != typeof i) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
const NO_CACHE = 'no-cache';
const API_NAME = exports.API_NAME = 'GitLab';
var CommitAction = /*#__PURE__*/function (CommitAction) {
CommitAction["CREATE"] = "create";
CommitAction["DELETE"] = "delete";
CommitAction["MOVE"] = "move";
CommitAction["UPDATE"] = "update";
return CommitAction;
}(CommitAction || {});
var GitLabCommitStatuses = /*#__PURE__*/function (GitLabCommitStatuses) {
GitLabCommitStatuses["Pending"] = "pending";
GitLabCommitStatuses["Running"] = "running";
GitLabCommitStatuses["Success"] = "success";
GitLabCommitStatuses["Failed"] = "failed";
GitLabCommitStatuses["Canceled"] = "canceled";
return GitLabCommitStatuses;
}(GitLabCommitStatuses || {});
function getMaxAccess(groups) {
return groups.reduce((previous, current) => {
if (current.group_access_level > previous.group_access_level) {
return current;
}
return previous;
}, groups[0]);
}
function batch(items, maxPerBatch, action) {
for (let index = 0; index < items.length; index = index + maxPerBatch) {
const itemsSlice = items.slice(index, index + maxPerBatch);
action(itemsSlice);
}
}
class API {
constructor(config) {
_defineProperty(this, "apiRoot", void 0);
_defineProperty(this, "graphQLAPIRoot", void 0);
_defineProperty(this, "token", void 0);
_defineProperty(this, "branch", void 0);
_defineProperty(this, "useOpenAuthoring", void 0);
_defineProperty(this, "repo", void 0);
_defineProperty(this, "repoURL", void 0);
_defineProperty(this, "commitAuthor", void 0);
_defineProperty(this, "squashMerges", void 0);
_defineProperty(this, "initialWorkflowStatus", void 0);
_defineProperty(this, "cmsLabelPrefix", void 0);
_defineProperty(this, "graphQLClient", void 0);
_defineProperty(this, "withAuthorizationHeaders", req => {
const withHeaders = _decapCmsLibUtil.unsentRequest.withHeaders(this.token ? {
Authorization: `Bearer ${this.token}`
} : {}, req);
return Promise.resolve(withHeaders);
});
_defineProperty(this, "buildRequest", async req => {
const withRoot = _decapCmsLibUtil.unsentRequest.withRoot(this.apiRoot)(req);
const withAuthorizationHeaders = await this.withAuthorizationHeaders(withRoot);
if (withAuthorizationHeaders.has('cache')) {
return withAuthorizationHeaders;
} else {
const withNoCache = _decapCmsLibUtil.unsentRequest.withNoCache(withAuthorizationHeaders);
return withNoCache;
}
});
_defineProperty(this, "request", async req => {
try {
return (0, _decapCmsLibUtil.requestWithBackoff)(this, req);
} catch (err) {
throw new _decapCmsLibUtil.APIError(err.message, null, API_NAME);
}
});
_defineProperty(this, "responseToJSON", (0, _decapCmsLibUtil.responseParser)({
format: 'json',
apiName: API_NAME
}));
_defineProperty(this, "responseToBlob", (0, _decapCmsLibUtil.responseParser)({
format: 'blob',
apiName: API_NAME
}));
_defineProperty(this, "responseToText", (0, _decapCmsLibUtil.responseParser)({
format: 'text',
apiName: API_NAME
}));
// eslint-disable-next-line @typescript-eslint/no-explicit-any
_defineProperty(this, "requestJSON", req => this.request(req).then(this.responseToJSON));
_defineProperty(this, "requestText", req => this.request(req).then(this.responseToText));
_defineProperty(this, "user", () => this.requestJSON('/user'));
_defineProperty(this, "WRITE_ACCESS", 30);
_defineProperty(this, "MAINTAINER_ACCESS", 40);
_defineProperty(this, "hasWriteAccess", async () => {
const {
shared_with_groups: sharedWithGroups,
permissions
} = await this.requestJSON(this.repoURL);
const {
project_access: projectAccess,
group_access: groupAccess
} = permissions;
if (projectAccess && projectAccess.access_level >= this.WRITE_ACCESS) {
return true;
}
if (groupAccess && groupAccess.access_level >= this.WRITE_ACCESS) {
return true;
}
// check for group write permissions
if (sharedWithGroups && sharedWithGroups.length > 0) {
const maxAccess = getMaxAccess(sharedWithGroups);
// maintainer access
if (maxAccess.group_access_level >= this.MAINTAINER_ACCESS) {
return true;
}
// developer access
if (maxAccess.group_access_level >= this.WRITE_ACCESS) {
// check permissions to merge and push
try {
const branch = await this.getDefaultBranch();
if (branch.developers_can_merge && branch.developers_can_push) {
return true;
}
} catch (e) {
console.log('Failed getting default branch', e);
}
}
}
return false;
});
_defineProperty(this, "readFile", async (path, sha, {
parseText = true,
branch = this.branch
} = {}) => {
const fetchContent = async () => {
const content = await this.request({
url: `${this.repoURL}/repository/files/${encodeURIComponent(path)}/raw`,
params: {
ref: branch
},
cache: 'no-store'
}).then(parseText ? this.responseToText : this.responseToBlob);
return content;
};
const content = await (0, _decapCmsLibUtil.readFile)(sha, fetchContent, _decapCmsLibUtil.localForage, parseText);
return content;
});
_defineProperty(this, "getCursorFromHeaders", headers => {
const page = parseInt(headers.get('X-Page'), 10);
const pageCount = parseInt(headers.get('X-Total-Pages'), 10);
const pageSize = parseInt(headers.get('X-Per-Page'), 10);
const count = parseInt(headers.get('X-Total'), 10);
const links = (0, _decapCmsLibUtil.parseLinkHeader)(headers.get('Link'));
const actions = (0, _immutable.Map)(links).keySeq().flatMap(key => key === 'prev' && page > 1 || key === 'next' && page < pageCount || key === 'first' && page > 1 || key === 'last' && page < pageCount ? [key] : []);
return _decapCmsLibUtil.Cursor.create({
actions,
meta: {
page,
count,
pageSize,
pageCount
},
data: {
links
}
});
});
_defineProperty(this, "getCursor", ({
headers
}) => this.getCursorFromHeaders(headers));
// Gets a cursor without retrieving the entries by using a HEAD
// request
_defineProperty(this, "fetchCursor", req => (0, _flow2.default)([_decapCmsLibUtil.unsentRequest.withMethod('HEAD'), this.request, (0, _decapCmsLibUtil.then)(this.getCursor)])(req));
_defineProperty(this, "fetchCursorAndEntries", req => (0, _flow2.default)([_decapCmsLibUtil.unsentRequest.withMethod('GET'), this.request, p => Promise.all([p.then(this.getCursor), p.then(this.responseToJSON).catch(e => {
if (e.status === 404) {
return [];
} else {
throw e;
}
})]), (0, _decapCmsLibUtil.then)(([cursor, entries]) => ({
cursor,
entries
}))])(req));
_defineProperty(this, "listFiles", async (path, recursive = false) => {
const {
entries,
cursor
} = await this.fetchCursorAndEntries({
url: `${this.repoURL}/repository/tree`,
params: {
path,
ref: this.branch,
recursive
}
});
return {
files: entries.filter(({
type
}) => type === 'blob'),
cursor
};
});
_defineProperty(this, "traverseCursor", async (cursor, action) => {
const link = cursor.data.getIn(['links', action]);
const {
entries,
cursor: newCursor
} = await this.fetchCursorAndEntries(link);
return {
entries: entries.filter(({
type
}) => type === 'blob'),
cursor: newCursor
};
});
_defineProperty(this, "listAllFilesGraphQL", async (path, recursive, branch) => {
const files = [];
let blobsPaths;
let cursor;
do {
blobsPaths = await this.graphQLClient.query({
query: queries.files,
variables: {
repo: this.repo,
branch,
path,
recursive,
cursor
}
});
files.push(...blobsPaths.data.project.repository.tree.blobs.nodes);
cursor = blobsPaths.data.project.repository.tree.blobs.pageInfo.endCursor;
} while (blobsPaths.data.project.repository.tree.blobs.pageInfo.hasNextPage);
return files;
});
_defineProperty(this, "readFilesGraphQL", async files => {
const paths = files.map(({
path
}) => path);
const blobPromises = [];
batch(paths, 90, slice => {
blobPromises.push(this.graphQLClient.query({
query: queries.blobs,
variables: {
repo: this.repo,
branch: this.branch,
paths: slice
},
fetchPolicy: 'cache-first'
}));
});
const commitPromises = [];
batch(paths, 8, slice => {
commitPromises.push(this.graphQLClient.query({
query: queries.lastCommits(slice),
variables: {
repo: this.repo,
branch: this.branch
},
fetchPolicy: 'cache-first'
}));
});
const [blobsResults, commitsResults] = await Promise.all([(await Promise.all(blobPromises)).map(result => result.data.project.repository.blobs.nodes), (await Promise.all(commitPromises)).map(result => Object.values(result.data.project.repository).map(({
lastCommit
}) => lastCommit).filter(Boolean))]);
const blobs = blobsResults.flat().map(result => result.data);
const metadata = commitsResults.flat().map(({
author,
authoredDate,
authorName
}) => ({
author: author ? author.name || author.username || author.publicEmail : authorName,
updatedOn: authoredDate
}));
const filesWithData = files.map((file, index) => ({
file: _objectSpread(_objectSpread({}, file), metadata[index]),
data: blobs[index]
}));
return filesWithData;
});
_defineProperty(this, "listAllFiles", async (path, recursive = false, branch = this.branch) => {
if (this.graphQLClient) {
return await this.listAllFilesGraphQL(path, recursive, branch);
}
const entries = [];
// eslint-disable-next-line prefer-const
let {
cursor,
entries: initialEntries
} = await this.fetchCursorAndEntries({
url: `${this.repoURL}/repository/tree`,
// Get the maximum number of entries per page
params: {
path,
ref: branch,
per_page: 100,
recursive
}
});
entries.push(...initialEntries);
while (cursor && cursor.actions.has('next')) {
const link = cursor.data.getIn(['links', 'next']);
const {
cursor: newCursor,
entries: newEntries
} = await this.fetchCursorAndEntries(link);
entries.push(...newEntries);
cursor = newCursor;
}
return entries.filter(({
type
}) => type === 'blob');
});
_defineProperty(this, "toBase64", str => Promise.resolve(_jsBase.Base64.encode(str)));
_defineProperty(this, "fromBase64", str => _jsBase.Base64.decode(str));
_defineProperty(this, "deleteFiles", (paths, commitMessage) => {
const branch = this.branch;
const commitParams = {
commit_message: commitMessage,
branch
};
if (this.commitAuthor) {
const {
name,
email
} = this.commitAuthor;
commitParams.author_name = name;
commitParams.author_email = email;
}
const items = paths.map(path => ({
path,
action: CommitAction.DELETE
}));
return this.uploadAndCommit(items, {
commitMessage
});
});
this.apiRoot = config.apiRoot || 'https://gitlab.com/api/v4';
this.graphQLAPIRoot = config.graphQLAPIRoot || 'https://gitlab.com/api/graphql';
this.token = config.token || false;
this.branch = config.branch || 'master';
this.repo = config.repo || '';
this.repoURL = `/projects/${encodeURIComponent(this.repo)}`;
this.squashMerges = config.squashMerges;
this.initialWorkflowStatus = config.initialWorkflowStatus;
this.cmsLabelPrefix = config.cmsLabelPrefix;
if (config.useGraphQL === true) {
this.graphQLClient = this.getApolloClient();
}
}
getApolloClient() {
const authLink = (0, _apolloLinkContext.setContext)((_, {
headers
}) => {
return {
headers: _objectSpread(_objectSpread({
'Content-Type': 'application/json; charset=utf-8'
}, headers), {}, {
authorization: this.token ? `token ${this.token}` : ''
})
};
});
const httpLink = (0, _apolloLinkHttp.createHttpLink)({
uri: this.graphQLAPIRoot
});
return new _apolloClient.ApolloClient({
link: authLink.concat(httpLink),
cache: new _apolloCacheInmemory.InMemoryCache(),
defaultOptions: {
watchQuery: {
fetchPolicy: NO_CACHE,
errorPolicy: 'ignore'
},
query: {
fetchPolicy: NO_CACHE,
errorPolicy: 'all'
}
}
});
}
reset() {
var _this$graphQLClient;
return (_this$graphQLClient = this.graphQLClient) === null || _this$graphQLClient === void 0 ? void 0 : _this$graphQLClient.resetStore();
}
async readFileMetadata(path, sha) {
const fetchFileMetadata = async () => {
try {
const result = await this.requestJSON({
url: `${this.repoURL}/repository/commits`,
params: {
path,
ref_name: this.branch
}
});
const commit = result[0];
return {
author: commit.author_name || commit.author_email,
updatedOn: commit.authored_date
};
} catch (e) {
return {
author: '',
updatedOn: ''
};
}
};
const fileMetadata = await (0, _decapCmsLibUtil.readFileMetadata)(sha, fetchFileMetadata, _decapCmsLibUtil.localForage);
return fileMetadata;
}
async getBranch(branchName) {
const branch = await this.requestJSON(`${this.repoURL}/repository/branches/${encodeURIComponent(branchName)}`);
return branch;
}
async uploadAndCommit(items, {
commitMessage = '',
branch = this.branch,
newBranch = false
}) {
const actions = items.map(item => _objectSpread(_objectSpread({
action: item.action,
file_path: item.path
}, item.oldPath ? {
previous_path: item.oldPath
} : {}), item.base64Content !== undefined ? {
content: item.base64Content,
encoding: 'base64'
} : {}));
const commitParams = _objectSpread({
branch,
commit_message: commitMessage,
actions
}, newBranch ? {
start_branch: this.branch
} : {});
if (this.commitAuthor) {
const {
name,
email
} = this.commitAuthor;
commitParams.author_name = name;
commitParams.author_email = email;
}
try {
const result = await this.requestJSON({
url: `${this.repoURL}/repository/commits`,
method: 'POST',
headers: {
'Content-Type': 'application/json; charset=utf-8'
},
body: JSON.stringify(commitParams)
});
return result;
} catch (error) {
const message = error.message || '';
if (newBranch && message.includes(`Could not update ${branch}`)) {
await (0, _decapCmsLibUtil.throwOnConflictingBranches)(branch, name => this.getBranch(name), API_NAME);
}
throw error;
}
}
async getCommitItems(files, branch) {
const items = await Promise.all(files.map(async file => {
const [base64Content, fileExists] = await Promise.all([(0, _result2.default)(file, 'toBase64', (0, _partial2.default)(this.toBase64, file.raw)), this.isFileExists(file.path, branch)]);
let action = CommitAction.CREATE;
let path = (0, _trimStart2.default)(file.path, '/');
let oldPath = undefined;
if (fileExists) {
oldPath = file.newPath && path;
action = file.newPath && file.newPath !== oldPath ? CommitAction.MOVE : CommitAction.UPDATE;
path = file.newPath ? (0, _trimStart2.default)(file.newPath, '/') : path;
}
return {
action,
base64Content,
path,
oldPath
};
}));
// move children
for (const item of items.filter(i => i.oldPath && i.action === CommitAction.MOVE)) {
const sourceDir = (0, _path.dirname)(item.oldPath);
const destDir = (0, _path.dirname)(item.path);
const children = await this.listAllFiles(sourceDir, true, branch);
children.filter(f => f.path !== item.oldPath).forEach(file => {
items.push({
action: CommitAction.MOVE,
path: file.path.replace(sourceDir, destDir),
oldPath: file.path
});
});
}
return items;
}
async persistFiles(dataFiles, mediaFiles, options) {
const files = [...dataFiles, ...mediaFiles];
if (options.useWorkflow) {
const slug = dataFiles[0].slug;
return this.editorialWorkflowGit(files, slug, options);
} else {
const items = await this.getCommitItems(files, this.branch);
return this.uploadAndCommit(items, {
commitMessage: options.commitMessage
});
}
}
async getMergeRequests(sourceBranch) {
const mergeRequests = await this.requestJSON({
url: `${this.repoURL}/merge_requests`,
params: _objectSpread({
state: 'opened',
labels: 'Any',
per_page: 100,
target_branch: this.branch
}, sourceBranch ? {
source_branch: sourceBranch
} : {})
});
return mergeRequests.filter(mr => mr.source_branch.startsWith(_decapCmsLibUtil.CMS_BRANCH_PREFIX) && mr.labels.some(l => (0, _decapCmsLibUtil.isCMSLabel)(l, this.cmsLabelPrefix)));
}
async listUnpublishedBranches() {
console.log('%c Checking for Unpublished entries', 'line-height: 30px;text-align: center;font-weight: bold');
const mergeRequests = await this.getMergeRequests();
const branches = mergeRequests.map(mr => mr.source_branch);
return branches;
}
async getFileId(path, branch) {
const request = await this.request({
method: 'HEAD',
url: `${this.repoURL}/repository/files/${encodeURIComponent(path)}`,
params: {
ref: branch
}
});
const blobId = request.headers.get('X-Gitlab-Blob-Id');
return blobId;
}
async isFileExists(path, branch) {
const fileExists = await this.requestText({
method: 'HEAD',
url: `${this.repoURL}/repository/files/${encodeURIComponent(path)}`,
params: {
ref: branch
}
}).then(() => true).catch(error => {
if (error instanceof _decapCmsLibUtil.APIError && error.status === 404) {
return false;
}
throw error;
});
return fileExists;
}
async getBranchMergeRequest(branch) {
const mergeRequests = await this.getMergeRequests(branch);
if (mergeRequests.length <= 0) {
throw new _decapCmsLibUtil.EditorialWorkflowError('content is not under editorial workflow', true);
}
return mergeRequests[0];
}
async getDifferences(to, from = this.branch) {
if (to === from) {
return [];
}
const result = await this.requestJSON({
url: `${this.repoURL}/repository/compare`,
params: {
from,
to
}
});
if (result.diffs.length >= 1000) {
throw new _decapCmsLibUtil.APIError('Diff limit reached', null, API_NAME);
}
return result.diffs.map(d => {
let status = 'modified';
if (d.new_file) {
status = 'added';
} else if (d.deleted_file) {
status = 'deleted';
} else if (d.renamed_file) {
status = 'renamed';
}
return {
status,
oldPath: d.old_path,
newPath: d.new_path,
newFile: d.new_file,
path: d.new_path || d.old_path,
binary: d.diff.startsWith('Binary') || /.svg$/.test(d.new_path)
};
});
}
async retrieveUnpublishedEntryData(contentKey) {
const {
collection,
slug
} = (0, _decapCmsLibUtil.parseContentKey)(contentKey);
const branch = (0, _decapCmsLibUtil.branchFromContentKey)(contentKey);
const mergeRequest = await this.getBranchMergeRequest(branch);
const diffs = await this.getDifferences(mergeRequest.sha);
const diffsWithIds = await Promise.all(diffs.map(async d => {
const {
path,
newFile
} = d;
const id = await this.getFileId(path, branch);
return {
id,
path,
newFile
};
}));
const label = mergeRequest.labels.find(l => (0, _decapCmsLibUtil.isCMSLabel)(l, this.cmsLabelPrefix));
const status = (0, _decapCmsLibUtil.labelToStatus)(label, this.cmsLabelPrefix);
const updatedAt = mergeRequest.updated_at;
const pullRequestAuthor = mergeRequest.author.name;
return {
collection,
slug,
status,
diffs: diffsWithIds,
updatedAt,
pullRequestAuthor
};
}
async rebaseMergeRequest(mergeRequest) {
let rebase = await this.requestJSON({
method: 'PUT',
url: `${this.repoURL}/merge_requests/${mergeRequest.iid}/rebase?skip_ci=true`
});
let i = 1;
while (rebase.rebase_in_progress) {
await new Promise(resolve => setTimeout(resolve, 1000));
rebase = await this.requestJSON({
url: `${this.repoURL}/merge_requests/${mergeRequest.iid}`,
params: {
include_rebase_in_progress: true
}
});
if (!rebase.rebase_in_progress || i > 30) {
break;
}
i++;
}
if (rebase.rebase_in_progress) {
throw new _decapCmsLibUtil.APIError('Timed out rebasing merge request', null, API_NAME);
} else if (rebase.merge_error) {
throw new _decapCmsLibUtil.APIError(`Rebase error: ${rebase.merge_error}`, null, API_NAME);
}
}
async createMergeRequest(branch, commitMessage, status) {
await this.requestJSON({
method: 'POST',
url: `${this.repoURL}/merge_requests`,
params: {
source_branch: branch,
target_branch: this.branch,
title: commitMessage,
description: _decapCmsLibUtil.DEFAULT_PR_BODY,
labels: (0, _decapCmsLibUtil.statusToLabel)(status, this.cmsLabelPrefix),
remove_source_branch: true,
squash: this.squashMerges
}
});
}
async editorialWorkflowGit(files, slug, options) {
const contentKey = (0, _decapCmsLibUtil.generateContentKey)(options.collectionName, slug);
const branch = (0, _decapCmsLibUtil.branchFromContentKey)(contentKey);
const unpublished = options.unpublished || false;
if (!unpublished) {
const items = await this.getCommitItems(files, this.branch);
await this.uploadAndCommit(items, {
commitMessage: options.commitMessage,
branch,
newBranch: true
});
await this.createMergeRequest(branch, options.commitMessage, options.status || this.initialWorkflowStatus);
} else {
const mergeRequest = await this.getBranchMergeRequest(branch);
await this.rebaseMergeRequest(mergeRequest);
const [items, diffs] = await Promise.all([this.getCommitItems(files, branch), this.getDifferences(branch)]);
// mark files for deletion
for (const diff of diffs.filter(d => d.binary)) {
if (!items.some(item => item.path === diff.path)) {
items.push({
action: CommitAction.DELETE,
path: diff.newPath
});
}
}
await this.uploadAndCommit(items, {
commitMessage: options.commitMessage,
branch
});
}
}
async updateMergeRequestLabels(mergeRequest, labels) {
await this.requestJSON({
method: 'PUT',
url: `${this.repoURL}/merge_requests/${mergeRequest.iid}`,
params: {
labels: labels.join(',')
}
});
}
async updateUnpublishedEntryStatus(collection, slug, newStatus) {
const contentKey = (0, _decapCmsLibUtil.generateContentKey)(collection, slug);
const branch = (0, _decapCmsLibUtil.branchFromContentKey)(contentKey);
const mergeRequest = await this.getBranchMergeRequest(branch);
const labels = [...mergeRequest.labels.filter(label => !(0, _decapCmsLibUtil.isCMSLabel)(label, this.cmsLabelPrefix)), (0, _decapCmsLibUtil.statusToLabel)(newStatus, this.cmsLabelPrefix)];
await this.updateMergeRequestLabels(mergeRequest, labels);
}
async mergeMergeRequest(mergeRequest) {
await this.requestJSON({
method: 'PUT',
url: `${this.repoURL}/merge_requests/${mergeRequest.iid}/merge`,
params: {
merge_commit_message: _decapCmsLibUtil.MERGE_COMMIT_MESSAGE,
squash_commit_message: _decapCmsLibUtil.MERGE_COMMIT_MESSAGE,
squash: this.squashMerges,
should_remove_source_branch: true
}
});
}
async publishUnpublishedEntry(collectionName, slug) {
const contentKey = (0, _decapCmsLibUtil.generateContentKey)(collectionName, slug);
const branch = (0, _decapCmsLibUtil.branchFromContentKey)(contentKey);
const mergeRequest = await this.getBranchMergeRequest(branch);
await this.mergeMergeRequest(mergeRequest);
}
async closeMergeRequest(mergeRequest) {
await this.requestJSON({
method: 'PUT',
url: `${this.repoURL}/merge_requests/${mergeRequest.iid}`,
params: {
state_event: 'close'
}
});
}
async getDefaultBranch() {
const branch = await this.getBranch(this.branch);
return branch;
}
async isShaExistsInBranch(branch, sha) {
const refs = await this.requestJSON({
url: `${this.repoURL}/repository/commits/${sha}/refs`,
params: {
type: 'branch'
}
});
return refs.some(r => r.name === branch);
}
async deleteBranch(branch) {
await this.request({
method: 'DELETE',
url: `${this.repoURL}/repository/branches/${encodeURIComponent(branch)}`
});
}
async deleteUnpublishedEntry(collectionName, slug) {
const contentKey = (0, _decapCmsLibUtil.generateContentKey)(collectionName, slug);
const branch = (0, _decapCmsLibUtil.branchFromContentKey)(contentKey);
const mergeRequest = await this.getBranchMergeRequest(branch);
await this.closeMergeRequest(mergeRequest);
await this.deleteBranch(branch);
}
async getMergeRequestStatues(mergeRequest, branch) {
const statuses = await this.requestJSON({
url: `${this.repoURL}/repository/commits/${mergeRequest.sha}/statuses`,
params: {
ref: branch
}
});
return statuses;
}
async getStatuses(collectionName, slug) {
const contentKey = (0, _decapCmsLibUtil.generateContentKey)(collectionName, slug);
const branch = (0, _decapCmsLibUtil.branchFromContentKey)(contentKey);
const mergeRequest = await this.getBranchMergeRequest(branch);
const statuses = await this.getMergeRequestStatues(mergeRequest, branch);
return statuses.map(({
name,
status,
target_url
}) => ({
context: name,
state: status === GitLabCommitStatuses.Success ? _decapCmsLibUtil.PreviewState.Success : _decapCmsLibUtil.PreviewState.Other,
target_url
}));
}
async getUnpublishedEntrySha(collection, slug) {
const contentKey = (0, _decapCmsLibUtil.generateContentKey)(collection, slug);
const branch = (0, _decapCmsLibUtil.branchFromContentKey)(contentKey);
const mergeRequest = await this.getBranchMergeRequest(branch);
return mergeRequest.sha;
}
}
exports.default = API;

View File

@@ -0,0 +1,137 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _base = _interopRequireDefault(require("@emotion/styled/base"));
var _react = _interopRequireDefault(require("react"));
var _propTypes = _interopRequireDefault(require("prop-types"));
var _decapCmsLibAuth = require("decap-cms-lib-auth");
var _decapCmsUiDefault = require("decap-cms-ui-default");
var _react2 = require("@emotion/react");
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
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; }
function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == typeof i ? i : String(i); }
function _toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != typeof i) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
function _EMOTION_STRINGIFIED_CSS_ERROR__() { return "You have tried to stringify object returned from `css` function. It isn't supposed to be used directly (e.g. as value of the `className` prop), but rather handed to emotion so it can handle it (e.g. as value of `css` prop)."; }
const LoginButtonIcon = /*#__PURE__*/(0, _base.default)(_decapCmsUiDefault.Icon, {
target: "e80yw6v0",
label: "LoginButtonIcon"
})(process.env.NODE_ENV === "production" ? {
name: "1gnqu05",
styles: "margin-right:18px"
} : {
name: "1gnqu05",
styles: "margin-right:18px",
map: "/*# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9BdXRoZW50aWNhdGlvblBhZ2UuanMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBVW9DIiwiZmlsZSI6Ii4uLy4uL3NyYy9BdXRoZW50aWNhdGlvblBhZ2UuanMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgUmVhY3QgZnJvbSAncmVhY3QnO1xuaW1wb3J0IFByb3BUeXBlcyBmcm9tICdwcm9wLXR5cGVzJztcbmltcG9ydCBzdHlsZWQgZnJvbSAnQGVtb3Rpb24vc3R5bGVkJztcbmltcG9ydCB7XG4gIE5ldGxpZnlBdXRoZW50aWNhdG9yLFxuICBJbXBsaWNpdEF1dGhlbnRpY2F0b3IsXG4gIFBrY2VBdXRoZW50aWNhdG9yLFxufSBmcm9tICdkZWNhcC1jbXMtbGliLWF1dGgnO1xuaW1wb3J0IHsgQXV0aGVudGljYXRpb25QYWdlLCBJY29uIH0gZnJvbSAnZGVjYXAtY21zLXVpLWRlZmF1bHQnO1xuXG5jb25zdCBMb2dpbkJ1dHRvbkljb24gPSBzdHlsZWQoSWNvbilgXG4gIG1hcmdpbi1yaWdodDogMThweDtcbmA7XG5cbmNvbnN0IGNsaWVudFNpZGVBdXRoZW50aWNhdG9ycyA9IHtcbiAgcGtjZTogKHtcbiAgICBiYXNlX3VybCxcbiAgICBhdXRoX2VuZHBvaW50LFxuICAgIGFwcF9pZCxcbiAgICBhdXRoX3Rva2VuX2VuZHBvaW50fSkgPT5cbiAgICBuZXcgUGtjZUF1dGhlbnRpY2F0b3Ioe1xuICAgICAgYmFzZV91cmwsXG4gICAgICBhdXRoX2VuZHBvaW50LFxuICAgICAgYXBwX2lkLFxuICAgICAgYXV0aF90b2tlbl9lbmRwb2ludCxcbiAgICAgIGF1dGhfdG9rZW5fZW5kcG9pbnRfY29udGVudF90eXBlOiAnYXBwbGljYXRpb24vanNvbjsgY2hhcnNldD11dGYtOCcsXG4gICAgfSksXG5cbiAgaW1wbGljaXQ6ICh7XG4gICAgYmFzZV91cmwsXG4gICAgYXV0aF9lbmRwb2ludCxcbiAgICBhcHBfaWQsXG4gICAgY2xlYXJIYXNoIH0pID0+XG4gICAgbmV3IEltcGxpY2l0QXV0aGVudGljYXRvcih7XG4gICAgICBiYXNlX3VybCxcbiAgICAgIGF1dGhfZW5kcG9pbnQsXG4gICAgICBhcHBfaWQsXG4gICAgICBjbGVhckhhc2gsXG4gICAgfSksXG59O1xuXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBHaXRMYWJBdXRoZW50aWNhdGlvblBhZ2UgZXh0ZW5kcyBSZWFjdC5Db21wb25lbnQge1xuICBzdGF0aWMgcHJvcFR5cGVzID0ge1xuICAgIG9uTG9naW46IFByb3BUeXBlcy5mdW5jLmlzUmVxdWlyZWQsXG4gICAgaW5Qcm9ncmVzczogUHJvcFR5cGVzLmJvb2wsXG4gICAgYmFzZV91cmw6IFByb3BUeXBlcy5zdHJpbmcsXG4gICAgc2l0ZUlkOiBQcm9wVHlwZXMuc3RyaW5nLFxuICAgIGF1dGhFbmRwb2ludDogUHJvcFR5cGVzLnN0cmluZyxcbiAgICBjb25maWc6IFByb3BUeXBlcy5vYmplY3QuaXNSZXF1aXJlZCxcbiAgICBjbGVhckhhc2g6IFByb3BUeXBlcy5mdW5jLFxuICAgIHQ6IFByb3BUeXBlcy5mdW5jLmlzUmVxdWlyZWQsXG4gIH07XG5cbiAgc3RhdGUgPSB7fTtcblxuICBjb21wb25lbnREaWRNb3VudCgpIHtcbiAgICBjb25zdCB7XG4gICAgICBhdXRoX3R5cGU6IGF1dGhUeXBlID0gJycsXG4gICAgICBiYXNlX3VybCA9ICdodHRwczovL2dpdGxhYi5jb20nLFxuICAgICAgYXV0aF9lbmRwb2ludCA9ICdvYXV0aC9hdXRob3JpemUnLFxuICAgICAgYXBwX2lkID0gJycsXG4gICAgfSA9IHRoaXMucHJvcHMuY29uZmlnLmJhY2tlbmQ7XG5cbiAgICBpZiAoY2xpZW50U2lkZUF1dGhlbnRpY2F0b3JzW2F1dGhUeXBlXSkge1xuICAgICAgdGhpcy5hdXRoID0gY2xpZW50U2lkZUF1dGhlbnRpY2F0b3JzW2F1dGhUeXBlXSh7XG4gICAgICAgIGJhc2VfdXJsLFxuICAgICAgICBhdXRoX2VuZHBvaW50LFxuICAgICAgICBhcHBfaWQsXG4gICAgICAgIGF1dGhfdG9rZW5fZW5kcG9pbnQ6ICdvYXV0aC90b2tlbicsXG4gICAgICAgIGNsZWFySGFzaDogdGhpcy5wcm9wcy5jbGVhckhhc2gsXG4gICAgICB9KTtcbiAgICAgIC8vIENvbXBsZXRlIGltcGxpY2l0IGF1dGhlbnRpY2F0aW9uIGlmIHdlIHdlcmUgcmVkaXJlY3RlZCBiYWNrIHRvIGZyb20gdGhlIHByb3ZpZGVyLlxuICAgICAgdGhpcy5hdXRoLmNvbXBsZXRlQXV0aCgoZXJyLCBkYXRhKSA9PiB7XG4gICAgICAgIGlmIChlcnIpIHtcbiAgICAgICAgICB0aGlzLnNldFN0YXRlKHsgbG9naW5FcnJvcjogZXJyLnRvU3RyaW5nKCkgfSk7XG4gICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMucHJvcHMub25Mb2dpbihkYXRhKTtcbiAgICAgIH0pO1xuICAgIH0gZWxzZSB7XG4gICAgICB0aGlzLmF1dGggPSBuZXcgTmV0bGlmeUF1dGhlbnRpY2F0b3Ioe1xuICAgICAgICBiYXNlX3VybDogdGhpcy5wcm9wcy5iYXNlX3VybCxcbiAgICAgICAgc2l0ZV9pZDpcbiAgICAgICAgICBkb2N1bWVudC5sb2NhdGlvbi5ob3N0LnNwbGl0KCc6JylbMF0gPT09ICdsb2NhbGhvc3QnXG4gICAgICAgICAgICA/ICdkZW1vLmRlY2FwY21zLm9yZydcbiAgICAgICAgICAgIDogdGhpcy5wcm9wcy5zaXRlSWQsXG4gICAgICAgIGF1dGhfZW5kcG9pbnQ6IHRoaXMucHJvcHMuYXV0aEVuZHBvaW50LFxuICAgICAgfSk7XG4gICAgfVxuICB9XG5cbiAgaGFuZGxlTG9naW4gPSBlID0+IHtcbiAgICBlLnByZXZlbnREZWZhdWx0KCk7XG4gICAgdGhpcy5hdXRoLmF1dGhlbnRpY2F0ZSh7IHByb3ZpZGVyOiAnZ2l0bGFiJywgc2NvcGU6ICdhcGknIH0sIChlcnIsIGRhdGEpID0+IHtcbiAgICAgIGlmIChlcnIpIHtcbiAgICAgICAgdGhpcy5zZXRTdGF0ZSh7IGxvZ2luRXJyb3I6IGVyci50b1N0cmluZygpIH0pO1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG4gICAgICB0aGlzLnByb3BzLm9uTG9naW4oZGF0YSk7XG4gICAgfSk7XG4gIH07XG5cbiAgcmVuZGVyKCkge1xuICAgIGNvbnN0IHsgaW5Qcm9ncmVzcywgY29uZmlnLCB0IH0gPSB0aGlzLnByb3BzO1xuICAgIHJldHVybiAoXG4gICAgICA8QXV0aGVudGljYXRpb25QYWdlXG4gICAgICAgIG9uTG9naW49e3RoaXMuaGFuZGxlTG9naW59XG4gICAgICAgIGxvZ2luRGlzYWJsZWQ9e2luUHJvZ3Jlc3N9XG4gICAgICAgIGxvZ2luRXJyb3JNZXNzYWdlPXt0aGlzLnN0YXRlLmxvZ2luRXJyb3J9XG4gICAgICAgIGxvZ29Vcmw9e2NvbmZpZy5sb2dvX3VybH1cbiAgICAgICAgc2l0ZVVybD17Y29uZmlnLnNpdGVfdXJsfVxuICAgICAgICByZW5kZXJCdXR0b25Db250ZW50PXsoKSA9PiAoXG4gICAgICAgICAgPFJlYWN0LkZyYWdtZW50PlxuICAgICAgICAgICAgPExvZ2luQnV0dG9uSWNvbiB0eXBlPVwiZ2l0bGFiXCIgLz57JyAnfVxuICAgICAgICAgICAge2luUHJvZ3Jlc3MgPyB0KCdhdXRoLmxvZ2dpbmdJbicpIDogdCgnYXV0aC5sb2dpbldpdGhHaXRMYWInKX1cbiAgICAgICAgICA8L1JlYWN0LkZyYWdtZW50PlxuICAgICAgICApfVxuICAgICAgICB0PXt0fVxuICAgICAgLz5cbiAgICApO1xuICB9XG59XG4iXX0= */",
toString: _EMOTION_STRINGIFIED_CSS_ERROR__
});
const clientSideAuthenticators = {
pkce: ({
base_url,
auth_endpoint,
app_id,
auth_token_endpoint
}) => new _decapCmsLibAuth.PkceAuthenticator({
base_url,
auth_endpoint,
app_id,
auth_token_endpoint,
auth_token_endpoint_content_type: 'application/json; charset=utf-8'
}),
implicit: ({
base_url,
auth_endpoint,
app_id,
clearHash
}) => new _decapCmsLibAuth.ImplicitAuthenticator({
base_url,
auth_endpoint,
app_id,
clearHash
})
};
class GitLabAuthenticationPage extends _react.default.Component {
constructor(...args) {
super(...args);
_defineProperty(this, "state", {});
_defineProperty(this, "handleLogin", e => {
e.preventDefault();
this.auth.authenticate({
provider: 'gitlab',
scope: 'api'
}, (err, data) => {
if (err) {
this.setState({
loginError: err.toString()
});
return;
}
this.props.onLogin(data);
});
});
}
componentDidMount() {
const {
auth_type: authType = '',
base_url = 'https://gitlab.com',
auth_endpoint = 'oauth/authorize',
app_id = ''
} = this.props.config.backend;
if (clientSideAuthenticators[authType]) {
this.auth = clientSideAuthenticators[authType]({
base_url,
auth_endpoint,
app_id,
auth_token_endpoint: 'oauth/token',
clearHash: this.props.clearHash
});
// Complete implicit authentication if we were redirected back to from the provider.
this.auth.completeAuth((err, data) => {
if (err) {
this.setState({
loginError: err.toString()
});
return;
}
this.props.onLogin(data);
});
} else {
this.auth = new _decapCmsLibAuth.NetlifyAuthenticator({
base_url: this.props.base_url,
site_id: document.location.host.split(':')[0] === 'localhost' ? 'demo.decapcms.org' : this.props.siteId,
auth_endpoint: this.props.authEndpoint
});
}
}
render() {
const {
inProgress,
config,
t
} = this.props;
return (0, _react2.jsx)(_decapCmsUiDefault.AuthenticationPage, {
onLogin: this.handleLogin,
loginDisabled: inProgress,
loginErrorMessage: this.state.loginError,
logoUrl: config.logo_url,
siteUrl: config.site_url,
renderButtonContent: () => (0, _react2.jsx)(_react.default.Fragment, null, (0, _react2.jsx)(LoginButtonIcon, {
type: "gitlab"
}), ' ', inProgress ? t('auth.loggingIn') : t('auth.loginWithGitLab')),
t: t
});
}
}
exports.default = GitLabAuthenticationPage;
_defineProperty(GitLabAuthenticationPage, "propTypes", {
onLogin: _propTypes.default.func.isRequired,
inProgress: _propTypes.default.bool,
base_url: _propTypes.default.string,
siteId: _propTypes.default.string,
authEndpoint: _propTypes.default.string,
config: _propTypes.default.object.isRequired,
clearHash: _propTypes.default.func,
t: _propTypes.default.func.isRequired
});

View File

@@ -0,0 +1,388 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _trim2 = _interopRequireDefault(require("lodash/trim"));
var _trimStart = _interopRequireDefault(require("lodash/trimStart"));
var _semaphore = _interopRequireDefault(require("semaphore"));
var _commonTags = require("common-tags");
var _decapCmsLibUtil = require("decap-cms-lib-util");
var _AuthenticationPage = _interopRequireDefault(require("./AuthenticationPage"));
var _API = _interopRequireWildcard(require("./API"));
function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && Object.prototype.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
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; }
function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == typeof i ? i : String(i); }
function _toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != typeof i) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
const MAX_CONCURRENT_DOWNLOADS = 10;
class GitLab {
constructor(config, options = {}) {
_defineProperty(this, "lock", void 0);
_defineProperty(this, "api", void 0);
_defineProperty(this, "options", void 0);
_defineProperty(this, "repo", void 0);
_defineProperty(this, "isBranchConfigured", void 0);
_defineProperty(this, "branch", void 0);
_defineProperty(this, "apiRoot", void 0);
_defineProperty(this, "token", void 0);
_defineProperty(this, "squashMerges", void 0);
_defineProperty(this, "cmsLabelPrefix", void 0);
_defineProperty(this, "mediaFolder", void 0);
_defineProperty(this, "previewContext", void 0);
_defineProperty(this, "useGraphQL", void 0);
_defineProperty(this, "graphQLAPIRoot", void 0);
_defineProperty(this, "_mediaDisplayURLSem", void 0);
this.options = _objectSpread({
proxied: false,
API: null,
initialWorkflowStatus: ''
}, options);
if (!this.options.proxied && (config.backend.repo === null || config.backend.repo === undefined)) {
throw new Error('The GitLab backend needs a "repo" in the backend configuration.');
}
this.api = this.options.API || null;
this.repo = config.backend.repo || '';
this.branch = config.backend.branch || 'master';
this.isBranchConfigured = config.backend.branch ? true : false;
this.apiRoot = config.backend.api_root || 'https://gitlab.com/api/v4';
this.token = '';
this.squashMerges = config.backend.squash_merges || false;
this.cmsLabelPrefix = config.backend.cms_label_prefix || '';
this.mediaFolder = config.media_folder;
this.previewContext = config.backend.preview_context || '';
this.useGraphQL = config.backend.use_graphql || false;
this.graphQLAPIRoot = config.backend.graphql_api_root || 'https://gitlab.com/api/graphql';
this.lock = (0, _decapCmsLibUtil.asyncLock)();
}
isGitBackend() {
return true;
}
async status() {
var _this$api;
const auth = (await ((_this$api = this.api) === null || _this$api === void 0 ? void 0 : _this$api.user().then(user => !!user).catch(e => {
console.warn('Failed getting GitLab user', e);
return false;
}))) || false;
return {
auth: {
status: auth
},
api: {
status: true,
statusPage: ''
}
};
}
authComponent() {
return _AuthenticationPage.default;
}
restoreUser(user) {
return this.authenticate(user);
}
async authenticate(state) {
this.token = state.token;
this.api = new _API.default({
token: this.token,
branch: this.branch,
repo: this.repo,
apiRoot: this.apiRoot,
squashMerges: this.squashMerges,
cmsLabelPrefix: this.cmsLabelPrefix,
initialWorkflowStatus: this.options.initialWorkflowStatus,
useGraphQL: this.useGraphQL,
graphQLAPIRoot: this.graphQLAPIRoot
});
const user = await this.api.user();
const isCollab = await this.api.hasWriteAccess().catch(error => {
error.message = (0, _commonTags.stripIndent)`
Repo "${this.repo}" not found.
Please ensure the repo information is spelled correctly.
If the repo is private, make sure you're logged into a GitLab account with access.
`;
throw error;
});
// Unauthorized user
if (!isCollab) {
throw new Error('Your GitLab user account does not have access to this repo.');
}
if (!this.isBranchConfigured) {
const defaultBranchName = await (0, _decapCmsLibUtil.getDefaultBranchName)({
backend: 'gitlab',
repo: this.repo,
token: this.token,
apiRoot: this.apiRoot
});
if (defaultBranchName) {
this.branch = defaultBranchName;
}
}
// Authorized user
return _objectSpread(_objectSpread({}, user), {}, {
login: user.username,
token: state.token
});
}
async logout() {
this.token = null;
return;
}
getToken() {
return Promise.resolve(this.token);
}
filterFile(folder, file, extension, depth) {
// gitlab paths include the root folder
const fileFolder = (0, _trim2.default)(file.path.split(folder)[1] || '/', '/');
return (0, _decapCmsLibUtil.filterByExtension)(file, extension) && fileFolder.split('/').length <= depth;
}
async entriesByFolder(folder, extension, depth) {
let cursor;
const listFiles = () => this.api.listFiles(folder, depth > 1).then(({
files,
cursor: c
}) => {
cursor = c.mergeMeta({
folder,
extension,
depth
});
return files.filter(file => this.filterFile(folder, file, extension, depth));
});
const files = await (0, _decapCmsLibUtil.entriesByFolder)(listFiles, this.api.readFile.bind(this.api), this.api.readFileMetadata.bind(this.api), _API.API_NAME);
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
files[_decapCmsLibUtil.CURSOR_COMPATIBILITY_SYMBOL] = cursor;
return files;
}
async listAllFiles(folder, extension, depth) {
const files = await this.api.listAllFiles(folder, depth > 1);
const filtered = files.filter(file => this.filterFile(folder, file, extension, depth));
return filtered;
}
async allEntriesByFolder(folder, extension, depth) {
const files = await (0, _decapCmsLibUtil.allEntriesByFolder)({
listAllFiles: () => this.listAllFiles(folder, extension, depth),
readFile: this.api.readFile.bind(this.api),
readFileMetadata: this.api.readFileMetadata.bind(this.api),
apiName: _API.API_NAME,
branch: this.branch,
localForage: _decapCmsLibUtil.localForage,
folder,
extension,
depth,
getDefaultBranch: () => this.api.getDefaultBranch().then(b => ({
name: b.name,
sha: b.commit.id
})),
isShaExistsInBranch: this.api.isShaExistsInBranch.bind(this.api),
getDifferences: (to, from) => this.api.getDifferences(to, from),
getFileId: path => this.api.getFileId(path, this.branch),
filterFile: file => this.filterFile(folder, file, extension, depth),
customFetch: this.useGraphQL ? files => this.api.readFilesGraphQL(files) : undefined
});
return files;
}
entriesByFiles(files) {
return (0, _decapCmsLibUtil.entriesByFiles)(files, this.api.readFile.bind(this.api), this.api.readFileMetadata.bind(this.api), _API.API_NAME);
}
// Fetches a single entry.
getEntry(path) {
return this.api.readFile(path).then(data => ({
file: {
path,
id: null
},
data: data
}));
}
getMedia(mediaFolder = this.mediaFolder) {
return this.api.listAllFiles(mediaFolder).then(files => files.map(({
id,
name,
path
}) => {
return {
id,
name,
path,
displayURL: {
id,
name,
path
}
};
}));
}
getMediaDisplayURL(displayURL) {
this._mediaDisplayURLSem = this._mediaDisplayURLSem || (0, _semaphore.default)(MAX_CONCURRENT_DOWNLOADS);
return (0, _decapCmsLibUtil.getMediaDisplayURL)(displayURL, this.api.readFile.bind(this.api), this._mediaDisplayURLSem);
}
async getMediaFile(path) {
const name = (0, _decapCmsLibUtil.basename)(path);
const blob = await (0, _decapCmsLibUtil.getMediaAsBlob)(path, null, this.api.readFile.bind(this.api));
const fileObj = (0, _decapCmsLibUtil.blobToFileObj)(name, blob);
const url = URL.createObjectURL(fileObj);
const id = await (0, _decapCmsLibUtil.getBlobSHA)(blob);
return {
id,
displayURL: url,
path,
name,
size: fileObj.size,
file: fileObj,
url
};
}
async persistEntry(entry, options) {
// persistEntry is a transactional operation
return (0, _decapCmsLibUtil.runWithLock)(this.lock, () => this.api.persistFiles(entry.dataFiles, entry.assets, options), 'Failed to acquire persist entry lock');
}
async persistMedia(mediaFile, options) {
const fileObj = mediaFile.fileObj;
const [id] = await Promise.all([(0, _decapCmsLibUtil.getBlobSHA)(fileObj), this.api.persistFiles([], [mediaFile], options)]);
const {
path
} = mediaFile;
const url = URL.createObjectURL(fileObj);
return {
displayURL: url,
path: (0, _trimStart.default)(path, '/'),
name: fileObj.name,
size: fileObj.size,
file: fileObj,
url,
id
};
}
deleteFiles(paths, commitMessage) {
return this.api.deleteFiles(paths, commitMessage);
}
traverseCursor(cursor, action) {
return this.api.traverseCursor(cursor, action).then(async ({
entries,
cursor: newCursor
}) => {
var _cursor$meta, _cursor$meta2, _cursor$meta3;
const [folder, depth, extension] = [(_cursor$meta = cursor.meta) === null || _cursor$meta === void 0 ? void 0 : _cursor$meta.get('folder'), (_cursor$meta2 = cursor.meta) === null || _cursor$meta2 === void 0 ? void 0 : _cursor$meta2.get('depth'), (_cursor$meta3 = cursor.meta) === null || _cursor$meta3 === void 0 ? void 0 : _cursor$meta3.get('extension')];
if (folder && depth && extension) {
entries = entries.filter(f => this.filterFile(folder, f, extension, depth));
newCursor = newCursor.mergeMeta({
folder,
extension,
depth
});
}
const entriesWithData = await (0, _decapCmsLibUtil.entriesByFiles)(entries, this.api.readFile.bind(this.api), this.api.readFileMetadata.bind(this.api), _API.API_NAME);
return {
entries: entriesWithData,
cursor: newCursor
};
});
}
loadMediaFile(branch, file) {
const readFile = (path, id, {
parseText
}) => this.api.readFile(path, id, {
branch,
parseText
});
return (0, _decapCmsLibUtil.getMediaAsBlob)(file.path, null, readFile).then(blob => {
const name = (0, _decapCmsLibUtil.basename)(file.path);
const fileObj = (0, _decapCmsLibUtil.blobToFileObj)(name, blob);
return {
id: file.path,
displayURL: URL.createObjectURL(fileObj),
path: file.path,
name,
size: fileObj.size,
file: fileObj
};
});
}
async loadEntryMediaFiles(branch, files) {
const mediaFiles = await Promise.all(files.map(file => this.loadMediaFile(branch, file)));
return mediaFiles;
}
async unpublishedEntries() {
const listEntriesKeys = () => this.api.listUnpublishedBranches().then(branches => branches.map(branch => (0, _decapCmsLibUtil.contentKeyFromBranch)(branch)));
const ids = await (0, _decapCmsLibUtil.unpublishedEntries)(listEntriesKeys);
return ids;
}
async unpublishedEntry({
id,
collection,
slug
}) {
if (id) {
const data = await this.api.retrieveUnpublishedEntryData(id);
return data;
} else if (collection && slug) {
const entryId = (0, _decapCmsLibUtil.generateContentKey)(collection, slug);
const data = await this.api.retrieveUnpublishedEntryData(entryId);
return data;
} else {
throw new Error('Missing unpublished entry id or collection and slug');
}
}
getBranch(collection, slug) {
const contentKey = (0, _decapCmsLibUtil.generateContentKey)(collection, slug);
const branch = (0, _decapCmsLibUtil.branchFromContentKey)(contentKey);
return branch;
}
async unpublishedEntryDataFile(collection, slug, path, id) {
const branch = this.getBranch(collection, slug);
const data = await this.api.readFile(path, id, {
branch
});
return data;
}
async unpublishedEntryMediaFile(collection, slug, path, id) {
const branch = this.getBranch(collection, slug);
const mediaFile = await this.loadMediaFile(branch, {
path,
id
});
return mediaFile;
}
async updateUnpublishedEntryStatus(collection, slug, newStatus) {
// updateUnpublishedEntryStatus is a transactional operation
return (0, _decapCmsLibUtil.runWithLock)(this.lock, () => this.api.updateUnpublishedEntryStatus(collection, slug, newStatus), 'Failed to acquire update entry status lock');
}
async deleteUnpublishedEntry(collection, slug) {
// deleteUnpublishedEntry is a transactional operation
return (0, _decapCmsLibUtil.runWithLock)(this.lock, () => this.api.deleteUnpublishedEntry(collection, slug), 'Failed to acquire delete entry lock');
}
async publishUnpublishedEntry(collection, slug) {
// publishUnpublishedEntry is a transactional operation
return (0, _decapCmsLibUtil.runWithLock)(this.lock, () => this.api.publishUnpublishedEntry(collection, slug), 'Failed to acquire publish entry lock');
}
async getDeployPreview(collection, slug) {
try {
const statuses = await this.api.getStatuses(collection, slug);
const deployStatus = (0, _decapCmsLibUtil.getPreviewStatus)(statuses, this.previewContext);
if (deployStatus) {
const {
target_url: url,
state
} = deployStatus;
return {
url,
status: state
};
} else {
return null;
}
} catch (e) {
return null;
}
}
}
exports.default = GitLab;

View File

@@ -0,0 +1,33 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
Object.defineProperty(exports, "API", {
enumerable: true,
get: function () {
return _API.default;
}
});
Object.defineProperty(exports, "AuthenticationPage", {
enumerable: true,
get: function () {
return _AuthenticationPage.default;
}
});
exports.DecapCmsBackendGitlab = void 0;
Object.defineProperty(exports, "GitLabBackend", {
enumerable: true,
get: function () {
return _implementation.default;
}
});
var _implementation = _interopRequireDefault(require("./implementation"));
var _API = _interopRequireDefault(require("./API"));
var _AuthenticationPage = _interopRequireDefault(require("./AuthenticationPage"));
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
const DecapCmsBackendGitlab = exports.DecapCmsBackendGitlab = {
GitLabBackend: _implementation.default,
API: _API.default,
AuthenticationPage: _AuthenticationPage.default
};

View File

@@ -0,0 +1,71 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.files = exports.blobs = void 0;
exports.lastCommits = lastCommits;
var _graphqlTag = require("graphql-tag");
var _commonTags = require("common-tags");
const files = exports.files = (0, _graphqlTag.gql)`
query files($repo: ID!, $branch: String!, $path: String!, $recursive: Boolean!, $cursor: String) {
project(fullPath: $repo) {
repository {
tree(ref: $branch, path: $path, recursive: $recursive) {
blobs(after: $cursor) {
nodes {
type
id: sha
path
name
}
pageInfo {
endCursor
hasNextPage
}
}
}
}
}
}
`;
const blobs = exports.blobs = (0, _graphqlTag.gql)`
query blobs($repo: ID!, $branch: String!, $paths: [String!]!) {
project(fullPath: $repo) {
repository {
blobs(ref: $branch, paths: $paths) {
nodes {
id
data: rawBlob
}
}
}
}
}
`;
function lastCommits(paths) {
const tree = paths.map((path, index) => (0, _commonTags.oneLine)`
tree${index}: tree(ref: $branch, path: "${path}") {
lastCommit {
authorName
authoredDate
author {
id
username
name
publicEmail
}
}
}
`).join('\n');
const query = (0, _graphqlTag.gql)`
query lastCommits($repo: ID!, $branch: String!) {
project(fullPath: $repo) {
repository {
${tree}
}
}
}
`;
return query;
}