This commit is contained in:
2025-08-25 20:24:23 +08:00
parent 30106e0129
commit 0ae8d7a709
1044 changed files with 321581 additions and 0 deletions

View File

@@ -0,0 +1,168 @@
# Change Log
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
# [3.3.0](https://github.com/decaporg/decap-cms/compare/decap-cms-backend-proxy@3.1.4...decap-cms-backend-proxy@3.3.0) (2025-07-15)
### Features
- add logo to header ([#7487](https://github.com/decaporg/decap-cms/issues/7487)) ([b540ace](https://github.com/decaporg/decap-cms/commit/b540acec943eb231df6aac7b1d515d9b4b84fa5d))
# [3.2.0](https://github.com/decaporg/decap-cms/compare/decap-cms-backend-proxy@3.1.4...decap-cms-backend-proxy@3.2.0) (2025-06-26)
**Note:** Version bump only for package decap-cms-backend-proxy
## [3.1.4](https://github.com/decaporg/decap-cms/compare/decap-cms-backend-proxy@3.1.3...decap-cms-backend-proxy@3.1.4) (2024-08-13)
### Reverts
- Revert "Update dependencies (#7264)" ([22d483a](https://github.com/decaporg/decap-cms/commit/22d483a5b0c654071ae05735ac4f49abdc13d38c)), closes [#7264](https://github.com/decaporg/decap-cms/issues/7264)
## [3.1.3](https://github.com/decaporg/decap-cms/compare/decap-cms-backend-proxy@3.1.2...decap-cms-backend-proxy@3.1.3) (2024-08-13)
**Note:** Version bump only for package decap-cms-backend-proxy
## [3.1.2](https://github.com/decaporg/decap-cms/compare/decap-cms-backend-proxy@3.1.1...decap-cms-backend-proxy@3.1.2) (2024-06-27)
### Bug Fixes
- display custom logo when using a proxy server ([#7235](https://github.com/decaporg/decap-cms/issues/7235)) ([7feca52](https://github.com/decaporg/decap-cms/commit/7feca52605315a764dfbe1b65c6782a644191dd4))
## [3.1.1](https://github.com/decaporg/decap-cms/compare/decap-cms-backend-proxy@3.1.0-beta.1...decap-cms-backend-proxy@3.1.1) (2024-03-21)
**Note:** Version bump only for package decap-cms-backend-proxy
# [3.1.0](https://github.com/decaporg/decap-cms/compare/decap-cms-backend-proxy@3.1.0-beta.1...decap-cms-backend-proxy@3.1.0) (2024-02-01)
**Note:** Version bump only for package decap-cms-backend-proxy
# [3.1.0-beta.1](https://github.com/decaporg/decap-cms/compare/decap-cms-backend-proxy@3.1.0-beta.0...decap-cms-backend-proxy@3.1.0-beta.1) (2024-01-31)
**Note:** Version bump only for package decap-cms-backend-proxy
# [3.1.0-beta.0](https://github.com/decaporg/decap-cms/compare/decap-cms-backend-proxy@3.1.0...decap-cms-backend-proxy@3.1.0-beta.0) (2023-10-20)
### Reverts
- Revert "chore(release): publish" ([b89fc89](https://github.com/decaporg/decap-cms/commit/b89fc894dfbb5f4136b2e5427fd25a29378a58c6))
## [3.0.2](https://github.com/decaporg/decap-cms/compare/decap-cms-backend-proxy@3.0.1...decap-cms-backend-proxy@3.0.2) (2023-10-13)
**Note:** Version bump only for package decap-cms-backend-proxy
## [3.0.1](https://github.com/decaporg/decap-cms/compare/decap-cms-backend-proxy@3.0.0...decap-cms-backend-proxy@3.0.1) (2023-08-25)
### Bug Fixes
- update peer dependencies ([#6886](https://github.com/decaporg/decap-cms/issues/6886)) ([e580ce5](https://github.com/decaporg/decap-cms/commit/e580ce52ce5f80fa040e8fbcab7fed0744f4f695))
# [3.0.0](https://github.com/decaporg/decap-cms/compare/decap-cms-backend-proxy@1.3.0...decap-cms-backend-proxy@3.0.0) (2023-08-18)
**Note:** Version bump only for package decap-cms-backend-proxy
# [1.3.0](https://github.com/decaporg/decap-cms/compare/decap-cms-backend-proxy@1.3.0-beta.0...decap-cms-backend-proxy@1.3.0) (2023-08-18)
**Note:** Version bump only for package decap-cms-backend-proxy
# 1.3.0-beta.0 (2023-08-18)
### Features
- rename packages ([#6863](https://github.com/decaporg/decap-cms/issues/6863)) ([d515e7b](https://github.com/decaporg/decap-cms/commit/d515e7bd33216a775d96887b08c4f7b1962941bb))
## [1.2.4-beta.0](https://github.com/decaporg/decap-cms/compare/decap-cms-backend-proxy@1.2.3...decap-cms-backend-proxy@1.2.4-beta.0) (2023-07-27)
**Note:** Version bump only for package decap-cms-backend-proxy
## [1.2.3](https://github.com/decaporg/decap-cms/tree/main/packages/decap-cms-backend-proxy/compare/decap-cms-backend-proxy@1.2.2...decap-cms-backend-proxy@1.2.3) (2021-06-01)
**Note:** Version bump only for package decap-cms-backend-proxy
## [1.2.2](https://github.com/decaporg/decap-cms/tree/main/packages/decap-cms-backend-proxy/compare/decap-cms-backend-proxy@1.2.1...decap-cms-backend-proxy@1.2.2) (2021-05-31)
**Note:** Version bump only for package decap-cms-backend-proxy
## [1.2.1](https://github.com/decaporg/decap-cms/tree/main/packages/decap-cms-backend-proxy/compare/decap-cms-backend-proxy@1.2.0...decap-cms-backend-proxy@1.2.1) (2021-05-19)
**Note:** Version bump only for package decap-cms-backend-proxy
# [1.2.0](https://github.com/decaporg/decap-cms/tree/main/packages/decap-cms-backend-proxy/compare/decap-cms-backend-proxy@1.1.7...decap-cms-backend-proxy@1.2.0) (2021-05-04)
### Features
- added react 17 as peer dependency in packages ([#5316](https://github.com/decaporg/decap-cms/tree/main/packages/decap-cms-backend-proxy/issues/5316)) ([9e42380](https://github.com/decaporg/decap-cms/tree/main/packages/decap-cms-backend-proxy/commit/9e423805707321396eec137f5b732a5b07a0dd3f))
## [1.1.7](https://github.com/decaporg/decap-cms/tree/main/packages/decap-cms-backend-proxy/compare/decap-cms-backend-proxy@1.1.6...decap-cms-backend-proxy@1.1.7) (2021-02-23)
**Note:** Version bump only for package decap-cms-backend-proxy
## [1.1.6](https://github.com/decaporg/decap-cms/tree/main/packages/decap-cms-backend-proxy/compare/decap-cms-backend-proxy@1.1.5...decap-cms-backend-proxy@1.1.6) (2021-02-10)
**Note:** Version bump only for package decap-cms-backend-proxy
## [1.1.5](https://github.com/decaporg/decap-cms/tree/main/packages/decap-cms-backend-proxy/compare/decap-cms-backend-proxy@1.1.4...decap-cms-backend-proxy@1.1.5) (2020-09-20)
**Note:** Version bump only for package decap-cms-backend-proxy
## [1.1.4](https://github.com/decaporg/decap-cms/tree/main/packages/decap-cms-backend-proxy/compare/decap-cms-backend-proxy@1.1.3...decap-cms-backend-proxy@1.1.4) (2020-09-15)
**Note:** Version bump only for package decap-cms-backend-proxy
## 1.1.3 (2020-09-08)
### Reverts
- Revert "chore(release): publish" ([828bb16](https://github.com/decaporg/decap-cms/tree/main/packages/decap-cms-backend-proxy/commit/828bb16415b8c22a34caa19c50c38b24ffe9ceae))
## 1.1.2 (2020-08-20)
### Reverts
- Revert "chore(release): publish" ([8262487](https://github.com/decaporg/decap-cms/tree/main/packages/decap-cms-backend-proxy/commit/82624879ccbcb16610090041db28f00714d924c8))
## 1.1.1 (2020-07-27)
### Reverts
- Revert "chore(release): publish" ([118d50a](https://github.com/decaporg/decap-cms/tree/main/packages/decap-cms-backend-proxy/commit/118d50a7a70295f25073e564b5161aa2b9883056))
# [1.1.0](https://github.com/decaporg/decap-cms/tree/main/packages/decap-cms-backend-proxy/compare/decap-cms-backend-proxy@1.0.7...decap-cms-backend-proxy@1.1.0) (2020-06-18)
### Bug Fixes
- handle token expiry ([#3847](https://github.com/decaporg/decap-cms/tree/main/packages/decap-cms-backend-proxy/issues/3847)) ([285c940](https://github.com/decaporg/decap-cms/tree/main/packages/decap-cms-backend-proxy/commit/285c940562548d7bc88de244123ba87ff66fba65))
### Features
- add backend status down indicator ([#3889](https://github.com/decaporg/decap-cms/tree/main/packages/decap-cms-backend-proxy/issues/3889)) ([a50edc7](https://github.com/decaporg/decap-cms/tree/main/packages/decap-cms-backend-proxy/commit/a50edc70553ad6afa1acee6a51996ad226443f8c))
## [1.0.7](https://github.com/decaporg/decap-cms/tree/main/packages/decap-cms-backend-proxy/compare/decap-cms-backend-proxy@1.0.6...decap-cms-backend-proxy@1.0.7) (2020-05-19)
**Note:** Version bump only for package decap-cms-backend-proxy
## [1.0.6](https://github.com/decaporg/decap-cms/tree/main/packages/decap-cms-backend-proxy/compare/decap-cms-backend-proxy@1.0.5...decap-cms-backend-proxy@1.0.6) (2020-04-06)
### Bug Fixes
- **backend-proxy:** fix error reporting ([#3527](https://github.com/decaporg/decap-cms/tree/main/packages/decap-cms-backend-proxy/issues/3527)) ([f94dea3](https://github.com/decaporg/decap-cms/tree/main/packages/decap-cms-backend-proxy/commit/f94dea386ce89f0f92744d0c4196416706999ea0))
## [1.0.5](https://github.com/decaporg/decap-cms/tree/main/packages/decap-cms-backend-proxy/compare/decap-cms-backend-proxy@1.0.4...decap-cms-backend-proxy@1.0.5) (2020-04-01)
**Note:** Version bump only for package decap-cms-backend-proxy
## [1.0.4](https://github.com/decaporg/decap-cms/tree/main/packages/decap-cms-backend-proxy/compare/decap-cms-backend-proxy@1.0.3...decap-cms-backend-proxy@1.0.4) (2020-03-03)
### Bug Fixes
- **locale:** Remove hard coded string literals ([#3333](https://github.com/decaporg/decap-cms/tree/main/packages/decap-cms-backend-proxy/issues/3333)) ([7c45a3c](https://github.com/decaporg/decap-cms/tree/main/packages/decap-cms-backend-proxy/commit/7c45a3cda983be427864a56e58791565eb9232e2))
## [1.0.3](https://github.com/decaporg/decap-cms/tree/main/packages/decap-cms-backend-proxy/compare/decap-cms-backend-proxy@1.0.2...decap-cms-backend-proxy@1.0.3) (2020-02-06)
### Bug Fixes
- **locale:** remove hard coded strings ([#3193](https://github.com/decaporg/decap-cms/tree/main/packages/decap-cms-backend-proxy/issues/3193)) ([fc91bf8](https://github.com/decaporg/decap-cms/tree/main/packages/decap-cms-backend-proxy/commit/fc91bf8781e65ce1dc946363dbb10419a145c66b))
## 1.0.2 (2020-01-22)
**Note:** Version bump only for package decap-cms-backend-proxy

View File

@@ -0,0 +1,9 @@
# Proxy backend
Facilitates [local development](https://www.decapcms.org/docs/beta-features/#working-with-a-local-git-repository).
## Code structure
`Implementation` for [File Management System API](https://github.com/decaporg/decap-cms/tree/main/packages/decap-cms-lib-util/README.md). An `RPC` wrapper for `decap-server`.
`AuthenticationPage` - a mock authentication page

View File

@@ -0,0 +1,28 @@
{
"name": "decap-cms-backend-proxy",
"description": "Proxy backend for Decap CMS",
"version": "3.3.0",
"repository": "https://github.com/decaporg/decap-cms/tree/main/packages/decap-cms-backend-proxy",
"bugs": "https://github.com/decaporg/decap-cms/issues",
"license": "MIT",
"module": "dist/esm/index.js",
"main": "dist/decap-cms-backend-proxy.js",
"keywords": [
"decap-cms",
"backend"
],
"sideEffects": false,
"scripts": {
"develop": "npm run build:esm -- --watch",
"build": "cross-env NODE_ENV=production webpack",
"build:esm": "cross-env NODE_ENV=esm babel src --out-dir dist/esm --ignore \"**/__tests__\" --root-mode upward --extensions \".js,.jsx,.ts,.tsx\""
},
"peerDependencies": {
"@emotion/react": "^11.11.1",
"@emotion/styled": "^11.11.0",
"decap-cms-lib-util": "^3.0.0",
"decap-cms-ui-default": "^3.0.0",
"prop-types": "^15.7.2",
"react": "^19.1.0"
}
}

View File

@@ -0,0 +1,67 @@
import React from 'react';
import PropTypes from 'prop-types';
import styled from '@emotion/styled';
import { Icon, buttons, shadows, GoBackButton, renderPageLogo } from 'decap-cms-ui-default';
const StyledAuthenticationPage = styled.section`
display: flex;
flex-flow: column nowrap;
align-items: center;
justify-content: center;
height: 100vh;
`;
const LoginButton = styled.button`
${buttons.button};
${shadows.dropDeep};
${buttons.default};
${buttons.gray};
padding: 0 30px;
margin-top: 0;
display: flex;
align-items: center;
position: relative;
${Icon} {
margin-right: 18px;
}
`;
export default class AuthenticationPage extends React.Component {
static propTypes = {
onLogin: PropTypes.func.isRequired,
inProgress: PropTypes.bool,
config: PropTypes.object.isRequired,
t: PropTypes.func.isRequired,
};
componentDidMount() {
// Manually validate PropTypes - React 19 breaking change
PropTypes.checkPropTypes(
AuthenticationPage.propTypes,
this.props,
'prop',
'AuthenticationPage',
);
}
handleLogin = e => {
e.preventDefault();
this.props.onLogin(this.state);
};
render() {
const { config, inProgress, t } = this.props;
return (
<StyledAuthenticationPage>
{renderPageLogo(config.logo?.src || config.logo_url)}
<LoginButton disabled={inProgress} onClick={this.handleLogin}>
{inProgress ? t('auth.loggingIn') : t('auth.login')}
</LoginButton>
{config.site_url && <GoBackButton href={config.site_url} t={t}></GoBackButton>}
</StyledAuthenticationPage>
);
}
}

View File

@@ -0,0 +1,263 @@
import {
EditorialWorkflowError,
APIError,
unsentRequest,
blobToFileObj,
} from 'decap-cms-lib-util';
import AuthenticationPage from './AuthenticationPage';
import type {
Entry,
AssetProxy,
PersistOptions,
User,
Config,
Implementation,
ImplementationFile,
UnpublishedEntry,
} from 'decap-cms-lib-util';
async function serializeAsset(assetProxy: AssetProxy) {
const base64content = await assetProxy.toBase64!();
return { path: assetProxy.path, content: base64content, encoding: 'base64' };
}
type MediaFile = {
id: string;
content: string;
encoding: string;
name: string;
path: string;
};
function deserializeMediaFile({ id, content, encoding, path, name }: MediaFile) {
let byteArray = new Uint8Array(0);
if (encoding !== 'base64') {
console.error(`Unsupported encoding '${encoding}' for file '${path}'`);
} else {
const decodedContent = atob(content);
byteArray = new Uint8Array(decodedContent.length);
for (let i = 0; i < decodedContent.length; i++) {
byteArray[i] = decodedContent.charCodeAt(i);
}
}
const blob = new Blob([byteArray]);
const file = blobToFileObj(name, blob);
const url = URL.createObjectURL(file);
return { id, name, path, file, size: file.size, url, displayURL: url };
}
export default class ProxyBackend implements Implementation {
proxyUrl: string;
mediaFolder: string;
options: { initialWorkflowStatus?: string };
branch: string;
cmsLabelPrefix?: string;
constructor(config: Config, options = {}) {
if (!config.backend.proxy_url) {
throw new Error('The Proxy backend needs a "proxy_url" in the backend configuration.');
}
this.branch = config.backend.branch || 'master';
this.proxyUrl = config.backend.proxy_url;
this.mediaFolder = config.media_folder;
this.options = options;
this.cmsLabelPrefix = config.backend.cms_label_prefix;
}
isGitBackend() {
return false;
}
status() {
return Promise.resolve({ auth: { status: true }, api: { status: true, statusPage: '' } });
}
authComponent() {
return AuthenticationPage;
}
restoreUser() {
return this.authenticate();
}
authenticate() {
return Promise.resolve() as unknown as Promise<User>;
}
logout() {
return null;
}
getToken() {
return Promise.resolve('');
}
async request(payload: { action: string; params: Record<string, unknown> }) {
const response = await unsentRequest.fetchWithTimeout(this.proxyUrl, {
method: 'POST',
headers: { 'Content-Type': 'application/json; charset=utf-8' },
body: JSON.stringify({ branch: this.branch, ...payload }),
});
const json = await response.json();
if (response.ok) {
return json;
} else {
throw new APIError(json.error, response.status, 'Proxy');
}
}
entriesByFolder(folder: string, extension: string, depth: number) {
return this.request({
action: 'entriesByFolder',
params: { branch: this.branch, folder, extension, depth },
});
}
entriesByFiles(files: ImplementationFile[]) {
return this.request({
action: 'entriesByFiles',
params: { branch: this.branch, files },
});
}
getEntry(path: string) {
return this.request({
action: 'getEntry',
params: { branch: this.branch, path },
});
}
unpublishedEntries() {
return this.request({
action: 'unpublishedEntries',
params: { branch: this.branch },
});
}
async unpublishedEntry({
id,
collection,
slug,
}: {
id?: string;
collection?: string;
slug?: string;
}) {
try {
const entry: UnpublishedEntry = await this.request({
action: 'unpublishedEntry',
params: { branch: this.branch, id, collection, slug, cmsLabelPrefix: this.cmsLabelPrefix },
});
return entry;
} catch (e) {
if (e.status === 404) {
throw new EditorialWorkflowError('content is not under editorial workflow', true);
}
throw e;
}
}
async unpublishedEntryDataFile(collection: string, slug: string, path: string, id: string) {
const { data } = await this.request({
action: 'unpublishedEntryDataFile',
params: { branch: this.branch, collection, slug, path, id },
});
return data;
}
async unpublishedEntryMediaFile(collection: string, slug: string, path: string, id: string) {
const file = await this.request({
action: 'unpublishedEntryMediaFile',
params: { branch: this.branch, collection, slug, path, id },
});
return deserializeMediaFile(file);
}
deleteUnpublishedEntry(collection: string, slug: string) {
return this.request({
action: 'deleteUnpublishedEntry',
params: { branch: this.branch, collection, slug },
});
}
async persistEntry(entry: Entry, options: PersistOptions) {
const assets = await Promise.all(entry.assets.map(serializeAsset));
return this.request({
action: 'persistEntry',
params: {
branch: this.branch,
dataFiles: entry.dataFiles,
assets,
options: { ...options, status: options.status || this.options.initialWorkflowStatus },
cmsLabelPrefix: this.cmsLabelPrefix,
},
});
}
updateUnpublishedEntryStatus(collection: string, slug: string, newStatus: string) {
return this.request({
action: 'updateUnpublishedEntryStatus',
params: {
branch: this.branch,
collection,
slug,
newStatus,
cmsLabelPrefix: this.cmsLabelPrefix,
},
});
}
publishUnpublishedEntry(collection: string, slug: string) {
return this.request({
action: 'publishUnpublishedEntry',
params: { branch: this.branch, collection, slug },
});
}
async getMedia(mediaFolder = this.mediaFolder) {
const files: MediaFile[] = await this.request({
action: 'getMedia',
params: { branch: this.branch, mediaFolder },
});
return files.map(deserializeMediaFile);
}
async getMediaFile(path: string) {
const file = await this.request({
action: 'getMediaFile',
params: { branch: this.branch, path },
});
return deserializeMediaFile(file);
}
async persistMedia(assetProxy: AssetProxy, options: PersistOptions) {
const asset = await serializeAsset(assetProxy);
const file: MediaFile = await this.request({
action: 'persistMedia',
params: { branch: this.branch, asset, options: { commitMessage: options.commitMessage } },
});
return deserializeMediaFile(file);
}
deleteFiles(paths: string[], commitMessage: string) {
return this.request({
action: 'deleteFiles',
params: { branch: this.branch, paths, options: { commitMessage } },
});
}
getDeployPreview(collection: string, slug: string) {
return this.request({
action: 'getDeployPreview',
params: { branch: this.branch, collection, slug },
});
}
}

View File

@@ -0,0 +1,8 @@
import ProxyBackend from './implementation';
import AuthenticationPage from './AuthenticationPage';
export const DecapCmsBackendProxy = {
ProxyBackend,
AuthenticationPage,
};
export { ProxyBackend, AuthenticationPage };

View File

@@ -0,0 +1,3 @@
const { getConfig } = require('../../scripts/webpack.js');
module.exports = getConfig();