mirror of
https://git.mirrors.martin98.com/https://github.com/sub-store-org/Sub-Store.git
synced 2025-10-21 12:01:06 +08:00
184 lines
5.0 KiB
JavaScript
184 lines
5.0 KiB
JavaScript
import $ from '@/core/app';
|
||
|
||
import {
|
||
ARTIFACT_REPOSITORY_KEY,
|
||
ARTIFACTS_KEY,
|
||
SETTINGS_KEY,
|
||
} from '@/constants';
|
||
import { deleteByName, findByName, updateByName } from '@/utils/database';
|
||
import { failed, success } from '@/restful/response';
|
||
import {
|
||
InternalServerError,
|
||
RequestInvalidError,
|
||
ResourceNotFoundError,
|
||
} from '@/restful/errors';
|
||
import Gist from '@/utils/gist';
|
||
|
||
export default function register($app) {
|
||
// Initialization
|
||
if (!$.read(ARTIFACTS_KEY)) $.write({}, ARTIFACTS_KEY);
|
||
|
||
// RESTful APIs
|
||
$app.route('/api/artifacts')
|
||
.get(getAllArtifacts)
|
||
.post(createArtifact)
|
||
.put(replaceArtifact);
|
||
|
||
$app.route('/api/artifact/:name')
|
||
.get(getArtifact)
|
||
.patch(updateArtifact)
|
||
.delete(deleteArtifact);
|
||
}
|
||
|
||
function getAllArtifacts(req, res) {
|
||
const allArtifacts = $.read(ARTIFACTS_KEY);
|
||
success(res, allArtifacts);
|
||
}
|
||
|
||
function replaceArtifact(req, res) {
|
||
const allArtifacts = req.body;
|
||
$.write(allArtifacts, ARTIFACTS_KEY);
|
||
success(res);
|
||
}
|
||
|
||
async function getArtifact(req, res) {
|
||
let { name } = req.params;
|
||
name = decodeURIComponent(name);
|
||
const allArtifacts = $.read(ARTIFACTS_KEY);
|
||
const artifact = findByName(allArtifacts, name);
|
||
|
||
if (artifact) {
|
||
success(res, artifact);
|
||
} else {
|
||
failed(
|
||
res,
|
||
new ResourceNotFoundError(
|
||
'RESOURCE_NOT_FOUND',
|
||
`Artifact ${name} does not exist!`,
|
||
),
|
||
404,
|
||
);
|
||
}
|
||
}
|
||
|
||
function createArtifact(req, res) {
|
||
const artifact = req.body;
|
||
if (!validateArtifactName(artifact.name)) {
|
||
failed(
|
||
res,
|
||
new RequestInvalidError(
|
||
'INVALID_ARTIFACT_NAME',
|
||
`Artifact name ${artifact.name} is invalid.`,
|
||
),
|
||
);
|
||
return;
|
||
}
|
||
|
||
$.info(`正在创建远程配置:${artifact.name}`);
|
||
const allArtifacts = $.read(ARTIFACTS_KEY);
|
||
if (findByName(allArtifacts, artifact.name)) {
|
||
failed(
|
||
res,
|
||
new RequestInvalidError(
|
||
'DUPLICATE_KEY',
|
||
`Artifact ${artifact.name} already exists.`,
|
||
),
|
||
);
|
||
} else {
|
||
allArtifacts.push(artifact);
|
||
$.write(allArtifacts, ARTIFACTS_KEY);
|
||
success(res, artifact, 201);
|
||
}
|
||
}
|
||
|
||
function updateArtifact(req, res) {
|
||
const allArtifacts = $.read(ARTIFACTS_KEY);
|
||
let oldName = req.params.name;
|
||
oldName = decodeURIComponent(oldName);
|
||
const artifact = findByName(allArtifacts, oldName);
|
||
if (artifact) {
|
||
$.info(`正在更新远程配置:${artifact.name}`);
|
||
const newArtifact = {
|
||
...artifact,
|
||
...req.body,
|
||
};
|
||
if (!validateArtifactName(newArtifact.name)) {
|
||
failed(
|
||
res,
|
||
new RequestInvalidError(
|
||
'INVALID_ARTIFACT_NAME',
|
||
`Artifact name ${newArtifact.name} is invalid.`,
|
||
),
|
||
);
|
||
return;
|
||
}
|
||
updateByName(allArtifacts, oldName, newArtifact);
|
||
$.write(allArtifacts, ARTIFACTS_KEY);
|
||
success(res, newArtifact);
|
||
} else {
|
||
failed(
|
||
res,
|
||
new RequestInvalidError(
|
||
'DUPLICATE_KEY',
|
||
`Artifact ${oldName} already exists.`,
|
||
),
|
||
);
|
||
}
|
||
}
|
||
|
||
async function deleteArtifact(req, res) {
|
||
let { name } = req.params;
|
||
name = decodeURIComponent(name);
|
||
$.info(`正在删除远程配置:${name}`);
|
||
const allArtifacts = $.read(ARTIFACTS_KEY);
|
||
try {
|
||
const artifact = findByName(allArtifacts, name);
|
||
if (!artifact) throw new Error(`远程配置:${name}不存在!`);
|
||
if (artifact.updated) {
|
||
// delete gist
|
||
const files = {};
|
||
files[encodeURIComponent(artifact.name)] = {
|
||
content: '',
|
||
};
|
||
// 当别的Sub 删了同步订阅 或 gist里面删了 当前设备没有删除 时 无法删除的bug
|
||
try {
|
||
await syncToGist(files);
|
||
} catch (i) {
|
||
$.error(`Function syncToGist: ${name} : ${i}`);
|
||
}
|
||
}
|
||
// delete local cache
|
||
deleteByName(allArtifacts, name);
|
||
$.write(allArtifacts, ARTIFACTS_KEY);
|
||
success(res);
|
||
} catch (err) {
|
||
$.error(`无法删除远程配置:${name},原因:${err}`);
|
||
failed(
|
||
res,
|
||
new InternalServerError(
|
||
`FAILED_TO_DELETE_ARTIFACT`,
|
||
`Failed to delete artifact ${name}`,
|
||
`Reason: ${err}`,
|
||
),
|
||
);
|
||
}
|
||
}
|
||
|
||
function validateArtifactName(name) {
|
||
return /^[a-zA-Z0-9._-]*$/.test(name);
|
||
}
|
||
|
||
async function syncToGist(files) {
|
||
const { gistToken } = $.read(SETTINGS_KEY);
|
||
if (!gistToken) {
|
||
return Promise.reject('未设置Gist Token!');
|
||
}
|
||
const manager = new Gist({
|
||
token: gistToken,
|
||
key: ARTIFACT_REPOSITORY_KEY,
|
||
});
|
||
return manager.upload(files);
|
||
}
|
||
|
||
export { syncToGist };
|