mirror of
https://github.com/xheldon/git-folder-sync.git
synced 2026-07-22 06:59:00 +00:00
5808 lines
231 KiB
JavaScript
5808 lines
231 KiB
JavaScript
/*
|
|
THIS IS A GENERATED/BUNDLED FILE BY ESBUILD
|
|
if you want to view the source, please visit the github repository of this plugin
|
|
*/
|
|
|
|
var __create = Object.create;
|
|
var __defProp = Object.defineProperty;
|
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
var __getProtoOf = Object.getPrototypeOf;
|
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
var __esm = (fn, res) => function __init() {
|
|
return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
|
|
};
|
|
var __commonJS = (cb, mod) => function __require() {
|
|
return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
|
|
};
|
|
var __export = (target, all) => {
|
|
for (var name in all)
|
|
__defProp(target, name, { get: all[name], enumerable: true });
|
|
};
|
|
var __copyProps = (to, from, except, desc) => {
|
|
if (from && typeof from === "object" || typeof from === "function") {
|
|
for (let key of __getOwnPropNames(from))
|
|
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
}
|
|
return to;
|
|
};
|
|
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
// If the importer is in node compatibility mode or this is not an ESM
|
|
// file that has been converted to a CommonJS file using a Babel-
|
|
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
mod
|
|
));
|
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
|
|
// node_modules/before-after-hook/lib/register.js
|
|
var require_register = __commonJS({
|
|
"node_modules/before-after-hook/lib/register.js"(exports, module2) {
|
|
module2.exports = register;
|
|
function register(state, name, method, options) {
|
|
if (typeof method !== "function") {
|
|
throw new Error("method for before hook must be a function");
|
|
}
|
|
if (!options) {
|
|
options = {};
|
|
}
|
|
if (Array.isArray(name)) {
|
|
return name.reverse().reduce(function(callback, name2) {
|
|
return register.bind(null, state, name2, callback, options);
|
|
}, method)();
|
|
}
|
|
return Promise.resolve().then(function() {
|
|
if (!state.registry[name]) {
|
|
return method(options);
|
|
}
|
|
return state.registry[name].reduce(function(method2, registered) {
|
|
return registered.hook.bind(null, method2, options);
|
|
}, method)();
|
|
});
|
|
}
|
|
}
|
|
});
|
|
|
|
// node_modules/before-after-hook/lib/add.js
|
|
var require_add = __commonJS({
|
|
"node_modules/before-after-hook/lib/add.js"(exports, module2) {
|
|
module2.exports = addHook;
|
|
function addHook(state, kind, name, hook2) {
|
|
var orig = hook2;
|
|
if (!state.registry[name]) {
|
|
state.registry[name] = [];
|
|
}
|
|
if (kind === "before") {
|
|
hook2 = function(method, options) {
|
|
return Promise.resolve().then(orig.bind(null, options)).then(method.bind(null, options));
|
|
};
|
|
}
|
|
if (kind === "after") {
|
|
hook2 = function(method, options) {
|
|
var result;
|
|
return Promise.resolve().then(method.bind(null, options)).then(function(result_) {
|
|
result = result_;
|
|
return orig(result, options);
|
|
}).then(function() {
|
|
return result;
|
|
});
|
|
};
|
|
}
|
|
if (kind === "error") {
|
|
hook2 = function(method, options) {
|
|
return Promise.resolve().then(method.bind(null, options)).catch(function(error) {
|
|
return orig(error, options);
|
|
});
|
|
};
|
|
}
|
|
state.registry[name].push({
|
|
hook: hook2,
|
|
orig
|
|
});
|
|
}
|
|
}
|
|
});
|
|
|
|
// node_modules/before-after-hook/lib/remove.js
|
|
var require_remove = __commonJS({
|
|
"node_modules/before-after-hook/lib/remove.js"(exports, module2) {
|
|
module2.exports = removeHook;
|
|
function removeHook(state, name, method) {
|
|
if (!state.registry[name]) {
|
|
return;
|
|
}
|
|
var index = state.registry[name].map(function(registered) {
|
|
return registered.orig;
|
|
}).indexOf(method);
|
|
if (index === -1) {
|
|
return;
|
|
}
|
|
state.registry[name].splice(index, 1);
|
|
}
|
|
}
|
|
});
|
|
|
|
// node_modules/before-after-hook/index.js
|
|
var require_before_after_hook = __commonJS({
|
|
"node_modules/before-after-hook/index.js"(exports, module2) {
|
|
var register = require_register();
|
|
var addHook = require_add();
|
|
var removeHook = require_remove();
|
|
var bind = Function.bind;
|
|
var bindable = bind.bind(bind);
|
|
function bindApi(hook2, state, name) {
|
|
var removeHookRef = bindable(removeHook, null).apply(
|
|
null,
|
|
name ? [state, name] : [state]
|
|
);
|
|
hook2.api = { remove: removeHookRef };
|
|
hook2.remove = removeHookRef;
|
|
["before", "error", "after", "wrap"].forEach(function(kind) {
|
|
var args = name ? [state, kind, name] : [state, kind];
|
|
hook2[kind] = hook2.api[kind] = bindable(addHook, null).apply(null, args);
|
|
});
|
|
}
|
|
function HookSingular() {
|
|
var singularHookName = "h";
|
|
var singularHookState = {
|
|
registry: {}
|
|
};
|
|
var singularHook = register.bind(null, singularHookState, singularHookName);
|
|
bindApi(singularHook, singularHookState, singularHookName);
|
|
return singularHook;
|
|
}
|
|
function HookCollection() {
|
|
var state = {
|
|
registry: {}
|
|
};
|
|
var hook2 = register.bind(null, state);
|
|
bindApi(hook2, state);
|
|
return hook2;
|
|
}
|
|
var collectionHookDeprecationMessageDisplayed = false;
|
|
function Hook() {
|
|
if (!collectionHookDeprecationMessageDisplayed) {
|
|
console.warn(
|
|
'[before-after-hook]: "Hook()" repurposing warning, use "Hook.Collection()". Read more: https://git.io/upgrade-before-after-hook-to-1.4'
|
|
);
|
|
collectionHookDeprecationMessageDisplayed = true;
|
|
}
|
|
return HookCollection();
|
|
}
|
|
Hook.Singular = HookSingular.bind();
|
|
Hook.Collection = HookCollection.bind();
|
|
module2.exports = Hook;
|
|
module2.exports.Hook = Hook;
|
|
module2.exports.Singular = Hook.Singular;
|
|
module2.exports.Collection = Hook.Collection;
|
|
}
|
|
});
|
|
|
|
// node_modules/node-fetch/browser.js
|
|
var require_browser = __commonJS({
|
|
"node_modules/node-fetch/browser.js"(exports, module2) {
|
|
"use strict";
|
|
var getGlobal = function() {
|
|
if (typeof self !== "undefined") {
|
|
return self;
|
|
}
|
|
if (typeof window !== "undefined") {
|
|
return window;
|
|
}
|
|
if (typeof global !== "undefined") {
|
|
return global;
|
|
}
|
|
throw new Error("unable to locate global object");
|
|
};
|
|
var globalObject = getGlobal();
|
|
module2.exports = exports = globalObject.fetch;
|
|
if (globalObject.fetch) {
|
|
exports.default = globalObject.fetch.bind(globalObject);
|
|
}
|
|
exports.Headers = globalObject.Headers;
|
|
exports.Request = globalObject.Request;
|
|
exports.Response = globalObject.Response;
|
|
}
|
|
});
|
|
|
|
// node_modules/wrappy/wrappy.js
|
|
var require_wrappy = __commonJS({
|
|
"node_modules/wrappy/wrappy.js"(exports, module2) {
|
|
module2.exports = wrappy;
|
|
function wrappy(fn, cb) {
|
|
if (fn && cb)
|
|
return wrappy(fn)(cb);
|
|
if (typeof fn !== "function")
|
|
throw new TypeError("need wrapper function");
|
|
Object.keys(fn).forEach(function(k) {
|
|
wrapper[k] = fn[k];
|
|
});
|
|
return wrapper;
|
|
function wrapper() {
|
|
var args = new Array(arguments.length);
|
|
for (var i = 0; i < args.length; i++) {
|
|
args[i] = arguments[i];
|
|
}
|
|
var ret = fn.apply(this, args);
|
|
var cb2 = args[args.length - 1];
|
|
if (typeof ret === "function" && ret !== cb2) {
|
|
Object.keys(cb2).forEach(function(k) {
|
|
ret[k] = cb2[k];
|
|
});
|
|
}
|
|
return ret;
|
|
}
|
|
}
|
|
}
|
|
});
|
|
|
|
// node_modules/once/once.js
|
|
var require_once = __commonJS({
|
|
"node_modules/once/once.js"(exports, module2) {
|
|
var wrappy = require_wrappy();
|
|
module2.exports = wrappy(once2);
|
|
module2.exports.strict = wrappy(onceStrict);
|
|
once2.proto = once2(function() {
|
|
Object.defineProperty(Function.prototype, "once", {
|
|
value: function() {
|
|
return once2(this);
|
|
},
|
|
configurable: true
|
|
});
|
|
Object.defineProperty(Function.prototype, "onceStrict", {
|
|
value: function() {
|
|
return onceStrict(this);
|
|
},
|
|
configurable: true
|
|
});
|
|
});
|
|
function once2(fn) {
|
|
var f = function() {
|
|
if (f.called)
|
|
return f.value;
|
|
f.called = true;
|
|
return f.value = fn.apply(this, arguments);
|
|
};
|
|
f.called = false;
|
|
return f;
|
|
}
|
|
function onceStrict(fn) {
|
|
var f = function() {
|
|
if (f.called)
|
|
throw new Error(f.onceError);
|
|
f.called = true;
|
|
return f.value = fn.apply(this, arguments);
|
|
};
|
|
var name = fn.name || "Function wrapped with `once`";
|
|
f.onceError = name + " shouldn't be called more than once";
|
|
f.called = false;
|
|
return f;
|
|
}
|
|
}
|
|
});
|
|
|
|
// i18n-simple.ts
|
|
function detectObsidianLanguage() {
|
|
var _a, _b, _c, _d, _e, _f;
|
|
const obsidianLang = localStorage.getItem("language") || ((_d = (_c = (_b = (_a = window.app) == null ? void 0 : _a.vault) == null ? void 0 : _b.adapter) == null ? void 0 : _c.path) == null ? void 0 : _d.locale) || ((_e = window.moment) == null ? void 0 : _e.locale());
|
|
const browserLang = navigator.language || ((_f = navigator.languages) == null ? void 0 : _f[0]) || "en";
|
|
if ((obsidianLang == null ? void 0 : obsidianLang.includes("zh")) || browserLang.startsWith("zh")) {
|
|
return "zh";
|
|
}
|
|
return "en";
|
|
}
|
|
function getActualLanguage() {
|
|
if (currentLanguage === "auto") {
|
|
return detectObsidianLanguage();
|
|
}
|
|
return currentLanguage;
|
|
}
|
|
function setLanguage(language) {
|
|
currentLanguage = language;
|
|
}
|
|
function t(key, params) {
|
|
const actualLang = getActualLanguage();
|
|
const translation = translations[actualLang][key];
|
|
if (!translation) {
|
|
console.warn(`Translation missing for key: ${key}`);
|
|
return key;
|
|
}
|
|
if (params) {
|
|
return Object.entries(params).reduce((text, [paramKey, paramValue]) => {
|
|
return text.replace(new RegExp(`\\{${paramKey}\\}`, "g"), String(paramValue));
|
|
}, translation);
|
|
}
|
|
return translation;
|
|
}
|
|
function getSupportedLanguages() {
|
|
const detectedLang = detectObsidianLanguage();
|
|
const detectedLangText = detectedLang === "zh" ? "\u4E2D\u6587" : "English";
|
|
const currentLang = getActualLanguage();
|
|
const followText = currentLang === "zh" ? "\u8DDF\u968FObsidian" : "Follow Obsidian";
|
|
const autoLabel = `${followText} (${detectedLangText})`;
|
|
return [
|
|
{ value: "auto", label: autoLabel },
|
|
{ value: "zh", label: "\u4E2D\u6587" },
|
|
{ value: "en", label: "English" }
|
|
];
|
|
}
|
|
var translations, currentLanguage;
|
|
var init_i18n_simple = __esm({
|
|
"i18n-simple.ts"() {
|
|
translations = {
|
|
zh: {
|
|
// Settings interface
|
|
"settings.title": "Git\u540C\u6B65\u8BBE\u7F6E",
|
|
"settings.language.name": "\u754C\u9762\u8BED\u8A00",
|
|
"settings.language.desc": "\u9009\u62E9\u63D2\u4EF6\u754C\u9762\u663E\u793A\u8BED\u8A00",
|
|
"settings.language.auto": "\u8DDF\u968FObsidian",
|
|
"settings.github.token.name": "GitHub Personal Token",
|
|
"settings.github.token.desc": "\u8F93\u5165\u4F60\u7684GitHub Personal Access Token",
|
|
"settings.github.token.placeholder": "ghp_xxxxxxxxxxxx",
|
|
"settings.github.repo.name": "GitHub\u4ED3\u5E93\u8DEF\u5F84",
|
|
"settings.github.repo.desc": "\u652F\u6301\u4E24\u79CD\u683C\u5F0F\uFF1A\n1. https://github.com/\u7528\u6237\u540D/\u4ED3\u5E93\u540D/\u8DEF\u5F84\n2. \u7528\u6237\u540D/\u4ED3\u5E93\u540D/\u8DEF\u5F84",
|
|
"settings.github.repo.placeholder": "https://github.com/Xheldon/git-sync/data/_post",
|
|
"settings.ribbon.name": "\u5C06\u63D2\u4EF6\u6309\u94AE\u663E\u793A\u5728\u4FA7\u8FB9\u680F",
|
|
"settings.ribbon.desc": "\u5F00\u542F\u540E\uFF0C\u5728\u5DE6\u4FA7\u8FB9\u680F\u663E\u793A\u63D2\u4EF6\u6309\u94AE\uFF0C\u70B9\u51FB\u53EF\u5FEB\u901F\u6253\u5F00\u8BBE\u7F6E\u754C\u9762",
|
|
"settings.save.name": "\u4FDD\u5B58\u8BBE\u7F6E",
|
|
"settings.save.desc": "\u4FDD\u5B58\u5F53\u524D\u7684\u914D\u7F6E\u8BBE\u7F6E",
|
|
"settings.save.button": "\u4FDD\u5B58\u8BBE\u7F6E",
|
|
"settings.diagnose.name": "\u8BCA\u65ADVault\u6587\u4EF6",
|
|
"settings.diagnose.desc": "\u68C0\u67E5\u5F53\u524DVault\u4E2D\u6709\u54EA\u4E9B\u6587\u4EF6\u53EF\u4EE5\u540C\u6B65",
|
|
"settings.diagnose.button": "\u8BCA\u65AD",
|
|
"settings.test.url.name": "\u6D4B\u8BD5\u4ED3\u5E93URL",
|
|
"settings.test.url.desc": "\u9A8C\u8BC1GitHub\u4ED3\u5E93\u8DEF\u5F84\u683C\u5F0F\u662F\u5426\u6B63\u786E",
|
|
"settings.test.url.button": "\u6D4B\u8BD5URL",
|
|
"settings.sponsor.name": "\u{1F496} \u652F\u6301\u5F00\u53D1\u8005",
|
|
"settings.sponsor.desc": "\u5982\u679C\u8FD9\u4E2A\u63D2\u4EF6\u5BF9\u4F60\u6709\u5E2E\u52A9\uFF0C\u6B22\u8FCE\u8BF7\u6211\u559D\u676F\u5496\u5561\uFF01\u4F60\u7684\u652F\u6301\u662F\u6211\u7EE7\u7EED\u5F00\u53D1\u7684\u52A8\u529B\u3002",
|
|
"settings.sponsor.button": "\u{1F49D} PayPal \u8D5E\u52A9",
|
|
"settings.sponsor.china.label": "\u{1F1E8}\u{1F1F3} \u4E2D\u56FD\u5927\u9646\u6350\u8D60\u6E20\u9053",
|
|
"settings.sponsor.section.title": "\u8D5E\u52A9",
|
|
"settings.danger.zone.title": "\u5371\u9669\u533A\u57DF",
|
|
"settings.init.name": "\u521D\u59CB\u5316\u4ED3\u5E93",
|
|
"settings.init.desc": "\u5F53\u672CVault\u4E3A\u7A7A\u7684\u65F6\u5019\u53EF\u7528\uFF0C\u5C06\u8FDC\u7AEF\u6587\u4EF6\u540C\u6B65\u5230\u672C\u5730",
|
|
"settings.init.button": "\u521D\u59CB\u5316\u4ED3\u5E93",
|
|
"settings.init.loading": "\u521D\u59CB\u5316\u4E2D...",
|
|
"settings.sync.remote.to.local.name": "\u5F3A\u5236\u540C\u6B65\u8FDC\u7AEF\u8DEF\u5F84\u5230\u672C\u5730",
|
|
"settings.sync.remote.to.local.desc": "\u5C06\u8FDC\u7AEF\u7684\u6587\u4EF6\u4E00\u80A1\u8111\u7684\u540C\u6B65\u5230\u672C\u5730\u7684Vault\u4E2D\uFF0C\u540C\u540D\u6587\u4EF6\u4F1A\u88AB\u8986\u76D6",
|
|
"settings.sync.remote.to.local.button": "\u5F3A\u5236\u540C\u6B65\u5230\u672C\u5730",
|
|
"settings.sync.remote.to.local.loading": "\u540C\u6B65\u4E2D...",
|
|
"settings.sync.local.to.remote.name": "\u5F3A\u5236\u540C\u6B65\u672C\u5730\u6587\u4EF6\u5230\u8FDC\u7AEF",
|
|
"settings.sync.local.to.remote.desc": "\u5C06\u672C\u5730\u7684Vault\u4E2D\u7684\u6240\u6709\u6587\u4EF6\u540C\u6B65\u5230\u8FDC\u7AEF\u914D\u7F6E\u7684\u8DEF\u5F84\u4E2D\uFF0C\u540C\u540D\u6587\u4EF6\u4F1A\u88AB\u8986\u76D6",
|
|
"settings.sync.local.to.remote.button": "\u5F3A\u5236\u540C\u6B65\u5230\u8FDC\u7AEF",
|
|
"settings.sync.local.to.remote.loading": "\u540C\u6B65\u4E2D...",
|
|
"settings.clear.cache.name": "\u6E05\u7A7A\u6587\u4EF6\u7F13\u5B58",
|
|
"settings.clear.cache.desc": "\u6E05\u7A7A\u6240\u6709\u6587\u4EF6\u72B6\u6001\u7F13\u5B58\uFF0C\u4E0B\u6B21\u67E5\u770B\u65F6\u5C06\u91CD\u65B0\u4ECEGitHub\u83B7\u53D6",
|
|
"settings.clear.cache.button": "\u6E05\u7A7A\u7F13\u5B58",
|
|
// COS settings
|
|
"settings.image.section.title": "\u56FE\u7247\u5904\u7406",
|
|
"settings.image.enable.name": "\u542F\u7528\u56FE\u7247\u5904\u7406\u529F\u80FD",
|
|
"settings.image.enable.desc": "\u5F00\u542F\u540E\uFF0C\u7C98\u8D34\u56FE\u7247\u65F6\u5C06\u81EA\u52A8\u4E0A\u4F20\u5230\u4E91\u5B58\u50A8\u5E76\u66FF\u6362\u4E3A\u94FE\u63A5",
|
|
"settings.cos.provider.section.title": "\u4E91\u670D\u52A1\u5546\u8BBE\u7F6E",
|
|
"settings.image.upload.section.title": "\u56FE\u7247\u4E0A\u4F20\u8BBE\u7F6E",
|
|
"settings.cos.provider.name": "\u4E91\u5B58\u50A8\u670D\u52A1\u5546",
|
|
"settings.cos.provider.desc": "\u9009\u62E9\u8981\u4F7F\u7528\u7684\u4E91\u5BF9\u8C61\u5B58\u50A8\u670D\u52A1\u5546",
|
|
"settings.cos.provider.aliyun": "\u963F\u91CC\u4E91 OSS",
|
|
"settings.cos.provider.tencent": "\u817E\u8BAF\u4E91 COS",
|
|
"settings.cos.provider.aws": "AWS S3",
|
|
"settings.cos.provider.cloudflare": "Cloudflare R2",
|
|
"settings.cos.secret.id.name": "Access Key ID / Secret ID",
|
|
"settings.cos.secret.id.desc": "\u4E91\u5B58\u50A8\u670D\u52A1\u7684\u8BBF\u95EE\u5BC6\u94A5ID",
|
|
"settings.cos.secret.id.placeholder": "\u8F93\u5165Access Key ID\u6216Secret ID",
|
|
"settings.cos.secret.key.name": "Access Key Secret / Secret Key",
|
|
"settings.cos.secret.key.desc": "\u4E91\u5B58\u50A8\u670D\u52A1\u7684\u8BBF\u95EE\u5BC6\u94A5",
|
|
"settings.cos.secret.key.placeholder": "\u8F93\u5165Access Key Secret\u6216Secret Key",
|
|
"settings.cos.bucket.name": "Bucket\u540D\u79F0",
|
|
"settings.cos.bucket.desc": "\u5B58\u50A8\u6876\u540D\u79F0",
|
|
"settings.cos.bucket.placeholder": "\u8F93\u5165bucket\u540D\u79F0",
|
|
"settings.cos.endpoint.name": "Endpoint",
|
|
"settings.cos.endpoint.desc": "\u670D\u52A1\u7AEF\u70B9\u5730\u5740\uFF08\u4EC5Cloudflare R2\u9700\u8981\uFF09",
|
|
"settings.cos.endpoint.placeholder": "\u4F8B\u5982\uFF1Ahttps://accountid.r2.cloudflarestorage.com",
|
|
"settings.cos.region.name": "Region",
|
|
"settings.cos.region.desc": "\u533A\u57DF\u8BBE\u7F6E\uFF08\u6240\u6709\u670D\u52A1\u5546\u90FD\u9700\u8981\uFF09",
|
|
"settings.cos.region.placeholder": "\u4F8B\u5982\uFF1Acn-hangzhou\u3001ap-beijing\u3001us-east-1",
|
|
"settings.cos.cdn.name": "CDN\u5730\u5740",
|
|
"settings.cos.cdn.desc": "CDN\u57DF\u540D\uFF0C\u7528\u4E8E\u751F\u6210\u8BBF\u95EE\u94FE\u63A5",
|
|
"settings.cos.cdn.placeholder": "\u4F8B\u5982\uFF1Ahttps://cdn.example.com",
|
|
"settings.cos.keep.local.name": "\u4FDD\u7559\u56FE\u7247\u5728\u672C\u5730",
|
|
"settings.cos.keep.local.desc": "\u4E0A\u4F20\u540E\u662F\u5426\u5728\u672C\u5730\u4FDD\u7559\u56FE\u7247\u526F\u672C",
|
|
"settings.cos.local.path.name": "\u672C\u5730\u5B58\u50A8\u8DEF\u5F84",
|
|
"settings.cos.local.path.desc": "\u672C\u5730\u4FDD\u5B58\u56FE\u7247\u7684\u76EE\u5F55\uFF08\u76F8\u5BF9\u4E8Evault\u6839\u76EE\u5F55\uFF09",
|
|
"settings.cos.local.path.placeholder": "\u4F8B\u5982\uFF1Aassets",
|
|
"settings.cos.upload.path.name": "\u4E0A\u4F20\u8DEF\u5F84\u6A21\u677F",
|
|
"settings.cos.upload.path.desc": "\u652F\u6301\u5360\u4F4D\u7B26\uFF1A{PATH}\uFF08\u5F53\u524D\u6587\u4EF6\u8DEF\u5F84\uFF09\u3001{FILENAME}\uFF08\u6587\u4EF6\u540D\uFF09\u3001{FOLDER}\uFF08\u6587\u4EF6\u5939\u540D\uFF09\u3001{YYYY}\uFF08\u5E74\uFF09\u3001{MM}\uFF08\u6708\uFF09\u3001{DD}\uFF08\u65E5\uFF09",
|
|
"settings.cos.upload.path.placeholder": "\u4F8B\u5982\uFF1Aimages/{YYYY}/{MM}/{DD}",
|
|
"settings.cos.clear.name": "\u6E05\u7A7A\u5F53\u524D\u914D\u7F6E",
|
|
"settings.cos.clear.desc": "\u6E05\u7A7A\u5F53\u524D\u9009\u4E2D\u63D0\u4F9B\u5546\u7684\u6240\u6709\u914D\u7F6E\u4FE1\u606F",
|
|
"settings.cos.clear.button": "\u6E05\u7A7A\u914D\u7F6E",
|
|
"settings.cos.clear.success": "\u914D\u7F6E\u5DF2\u6E05\u7A7A",
|
|
"settings.cos.test.name": "\u6D4B\u8BD5COS\u914D\u7F6E",
|
|
"settings.cos.test.desc": "\u6D4B\u8BD5\u5F53\u524DCOS\u914D\u7F6E\u662F\u5426\u53EF\u7528",
|
|
"settings.cos.test.button": "\u6D4B\u8BD5\u8FDE\u63A5",
|
|
"settings.cos.test.loading": "\u6D4B\u8BD5\u4E2D...",
|
|
// Notification messages
|
|
"notice.settings.saved": "\u8BBE\u7F6E\u5DF2\u4FDD\u5B58",
|
|
"notice.config.required": "\u8BF7\u5148\u914D\u7F6EGitHub Token\u548C\u4ED3\u5E93\u5730\u5740",
|
|
"notice.url.required": "\u8BF7\u5148\u8F93\u5165GitHub\u4ED3\u5E93\u8DEF\u5F84",
|
|
"notice.url.test.success": "URL\u683C\u5F0F\u6B63\u786E\uFF01",
|
|
"notice.url.test.failed": "URL\u683C\u5F0F\u4E0D\u6B63\u786E\uFF0C\u8BF7\u68C0\u67E5\u683C\u5F0F\u3002\u8BE6\u60C5\u8BF7\u67E5\u770B\u63A7\u5236\u53F0\u3002",
|
|
"notice.init.error": "\u521D\u59CB\u5316\u4ED3\u5E93\u65F6\u53D1\u751F\u9519\u8BEF",
|
|
"notice.sync.error": "\u5F3A\u5236\u540C\u6B65\u65F6\u53D1\u751F\u9519\u8BEF",
|
|
"notice.diagnose.result": "Vault\u4E2D\u5171\u6709 {total} \u4E2A\u6587\u4EF6\uFF0C\u5176\u4E2D {syncable} \u4E2A\u53EF\u540C\u6B65\u3002\u8BE6\u60C5\u8BF7\u67E5\u770B\u63A7\u5236\u53F0\u3002",
|
|
"notice.result.with.count": "{message}\uFF0C\u5904\u7406\u4E86 {count} \u4E2A\u6587\u4EF6",
|
|
"notice.cache.cleared": "\u5DF2\u6E05\u7A7A {count} \u4E2A\u6587\u4EF6\u7684\u7F13\u5B58",
|
|
"notice.cache.clear.error": "\u6E05\u7A7A\u7F13\u5B58\u65F6\u53D1\u751F\u9519\u8BEF",
|
|
// Sync operations
|
|
"sync.success": "\u540C\u6B65\u6210\u529F: {filename}",
|
|
"sync.failed": "\u540C\u6B65\u5931\u8D25: {message}",
|
|
"sync.error": "\u540C\u6B65\u65F6\u53D1\u751F\u9519\u8BEF",
|
|
"pull.success": "\u62C9\u53D6\u6210\u529F: {filename}",
|
|
"pull.failed": "\u62C9\u53D6\u5931\u8D25: {message}",
|
|
"pull.error": "\u62C9\u53D6\u65F6\u53D1\u751F\u9519\u8BEF",
|
|
// Repository operations
|
|
"vault.not.empty": "Vault\u4E0D\u4E3A\u7A7A\uFF0C\u65E0\u6CD5\u521D\u59CB\u5316",
|
|
"repo.init.success": "\u4ED3\u5E93\u521D\u59CB\u5316\u6210\u529F",
|
|
"repo.init.failed": "\u4ED3\u5E93\u521D\u59CB\u5316\u5931\u8D25: {error}",
|
|
"force.sync.remote.to.local.success": "\u5F3A\u5236\u540C\u6B65\u8FDC\u7AEF\u5230\u672C\u5730\u6210\u529F",
|
|
"force.sync.remote.to.local.failed": "\u5F3A\u5236\u540C\u6B65\u8FDC\u7AEF\u5230\u672C\u5730\u5931\u8D25: {error}",
|
|
"no.syncable.files.in.vault": "Vault\u4E2D\u6CA1\u6709\u53EF\u540C\u6B65\u7684\u6587\u4EF6",
|
|
"force.sync.local.to.remote.success.no.failures": "\u5F3A\u5236\u540C\u6B65\u672C\u5730\u5230\u8FDC\u7AEF\u6210\u529F",
|
|
"force.sync.local.to.remote.success": "\u5F3A\u5236\u540C\u6B65\u672C\u5730\u5230\u8FDC\u7AEF\u5B8C\u6210\uFF0C\u6210\u529F: {processed}\uFF0C\u5931\u8D25: {failed}",
|
|
"force.sync.local.to.remote.failed": "\u5F3A\u5236\u540C\u6B65\u672C\u5730\u5230\u8FDC\u7AEF\u5931\u8D25: {error}",
|
|
// Actions
|
|
"actions.sync.current.to.remote": "\u540C\u6B65\u5F53\u524D\u6587\u4EF6\u5230\u8FDC\u7AEF",
|
|
"actions.pull.remote.to.current": "\u4ECE\u8FDC\u7AEF\u62C9\u53D6\u5230\u5F53\u524D\u6587\u4EF6",
|
|
// Date
|
|
"date.today": "\u4ECA\u5929",
|
|
"date.yesterday": "\u6628\u5929",
|
|
// GitHub API Error
|
|
"github.api.rate.limit.exceeded": "GitHub API\u8C03\u7528\u6B21\u6570\u5DF2\u8FBE\u4E0A\u9650\u3002\u8BF7\u7B49\u5F85 {minutes} \u5206\u949F\u540E\u91CD\u8BD5\u3002",
|
|
"github.api.rate.limit.warning": "\u26A0\uFE0F GitHub API\u8C03\u7528\u6B21\u6570\u5269\u4F59 {remaining} \u6B21\uFF0C\u8BF7\u8C28\u614E\u4F7F\u7528\u3002",
|
|
"github.api.rate.limit.notice": "\u901F\u7387\u9650\u5236\u8D85\u51FA",
|
|
"github.api.token.invalid": "GitHub Token\u65E0\u6548\u6216\u5DF2\u8FC7\u671F\u3002\u8BF7\u68C0\u67E5\uFF1A\n1. Token\u662F\u5426\u6B63\u786E\n2. Token\u662F\u5426\u6709\u8DB3\u591F\u7684\u6743\u9650\n3. Token\u662F\u5426\u5DF2\u8FC7\u671F",
|
|
"github.api.rate.limit.hourly": "GitHub API\u8C03\u7528\u6B21\u6570\u5DF2\u8FBE\u4E0A\u9650\uFF08\u6BCF\u5C0F\u65F65000\u6B21\uFF09\u3002\n\u8BF7\u7B49\u5F85 {minutes} \u5206\u949F\u540E\u91CD\u8BD5\uFF0C\u6216\u4F7F\u7528GitHub Pro\u8D26\u53F7\u83B7\u5F97\u66F4\u9AD8\u9650\u989D\u3002",
|
|
"github.api.repo.not.found": "\u4ED3\u5E93\u4E0D\u5B58\u5728\u6216\u65E0\u8BBF\u95EE\u6743\u9650\u3002\u8BF7\u68C0\u67E5\uFF1A\n1. \u4ED3\u5E93\u5730\u5740\u662F\u5426\u6B63\u786E\n2. Token\u662F\u5426\u6709\u8BBF\u95EE\u8BE5\u4ED3\u5E93\u7684\u6743\u9650\n3. \u4ED3\u5E93\u662F\u5426\u4E3A\u79C1\u6709\u4ED3\u5E93",
|
|
"github.api.file.conflict": "\u6587\u4EF6\u51B2\u7A81\u3002\u8FDC\u7A0B\u6587\u4EF6\u5DF2\u88AB\u5176\u4ED6\u4EBA\u4FEE\u6539\u3002\n\u8BF7\u5148\u540C\u6B65\u8FDC\u7A0B\u66F4\u6539\uFF0C\u7136\u540E\u91CD\u8BD5\u3002",
|
|
"github.api.validation.failed": "GitHub API\u9A8C\u8BC1\u5931\u8D25\u3002\u8BF7\u68C0\u67E5\uFF1A\n1. \u6587\u4EF6\u8DEF\u5F84\u662F\u5426\u6B63\u786E\n2. \u6587\u4EF6\u5185\u5BB9\u662F\u5426\u7B26\u5408\u8981\u6C42\n3. \u4ED3\u5E93\u6743\u9650\u8BBE\u7F6E",
|
|
"github.api.server.error": "GitHub\u670D\u52A1\u5668\u9519\u8BEF\uFF08{status}\uFF09\u3002\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002",
|
|
"github.api.network.error": "\u7F51\u7EDC\u8FDE\u63A5\u9519\u8BEF\u3002\u8BF7\u68C0\u67E5\uFF1A\n1. \u7F51\u7EDC\u8FDE\u63A5\u662F\u5426\u6B63\u5E38\n2. \u9632\u706B\u5899\u8BBE\u7F6E\n3. \u4EE3\u7406\u914D\u7F6E",
|
|
"github.api.timeout.error": "\u8BF7\u6C42\u8D85\u65F6\u3002\u8BF7\u68C0\u67E5\u7F51\u7EDC\u8FDE\u63A5\u6216\u7A0D\u540E\u91CD\u8BD5\u3002",
|
|
"github.api.unknown.error": "\u672A\u77E5\u9519\u8BEF\uFF1A{message}",
|
|
"github.api.access.denied": "GitHub\u8BBF\u95EE\u88AB\u62D2\u7EDD\u3002\u53EF\u80FD\u539F\u56E0\uFF1A\n1. Token\u6743\u9650\u4E0D\u8DB3\n2. \u4ED3\u5E93\u4E3A\u79C1\u6709\u4E14Token\u65E0\u8BBF\u95EE\u6743\u9650\n3. \u4ED3\u5E93\u4E0D\u5B58\u5728",
|
|
"github.api.resource.not.found": "\u8D44\u6E90\u672A\u627E\u5230\u3002\u8BF7\u68C0\u67E5\uFF1A\n1. \u4ED3\u5E93\u8DEF\u5F84\u662F\u5426\u6B63\u786E\n2. \u6587\u4EF6\u8DEF\u5F84\u662F\u5426\u5B58\u5728\n3. Token\u662F\u5426\u6709\u8BBF\u95EE\u8BE5\u4ED3\u5E93\u7684\u6743\u9650",
|
|
"github.api.file.conflict.detailed": "\u6587\u4EF6\u51B2\u7A81\u3002\u53EF\u80FD\u539F\u56E0\uFF1A\n1. \u6587\u4EF6\u5728\u8FDC\u7A0B\u5DF2\u88AB\u4FEE\u6539\n2. \u8BF7\u5148\u4ECE\u8FDC\u7AEF\u540C\u6B65\u6700\u65B0\u7248\u672C",
|
|
"github.api.invalid.request": "\u8BF7\u6C42\u53C2\u6570\u65E0\u6548\u3002\u8BF7\u68C0\u67E5\uFF1A\n1. \u6587\u4EF6\u5185\u5BB9\u662F\u5426\u8FC7\u5927\uFF08>100MB\uFF09\n2. \u6587\u4EF6\u8DEF\u5F84\u683C\u5F0F\u662F\u5426\u6B63\u786E",
|
|
"github.api.server.error.detailed": "GitHub\u670D\u52A1\u5668\u9519\u8BEF\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002\u5982\u679C\u95EE\u9898\u6301\u7EED\u5B58\u5728\uFF0C\u8BF7\u68C0\u67E5GitHub\u670D\u52A1\u72B6\u6001\u3002",
|
|
"github.api.error.with.status": "GitHub API\u9519\u8BEF ({status}): {message}",
|
|
"github.api.network.failed": "\u7F51\u7EDC\u8FDE\u63A5\u5931\u8D25\u3002\u8BF7\u68C0\u67E5\uFF1A\n1. \u7F51\u7EDC\u8FDE\u63A5\u662F\u5426\u6B63\u5E38\n2. \u662F\u5426\u80FD\u8BBF\u95EEgithub.com\n3. \u9632\u706B\u5899\u6216\u4EE3\u7406\u8BBE\u7F6E",
|
|
"github.api.timeout.detailed": "\u8BF7\u6C42\u8D85\u65F6\u3002\u8BF7\u68C0\u67E5\u7F51\u7EDC\u8FDE\u63A5\u6216\u7A0D\u540E\u91CD\u8BD5\u3002",
|
|
"github.api.operation.failed": "\u64CD\u4F5C\u5931\u8D25: {message}",
|
|
"github.api.retry.hint": "\u{1F4A1} \u63D0\u793A\uFF1A\u8FD9\u662F\u4E34\u65F6\u6027\u9519\u8BEF\uFF0C\u7A0D\u540E\u53EF\u4EE5\u91CD\u8BD5",
|
|
"github.api.invalid.url.format": "\u65E0\u6548\u7684\u4ED3\u5E93URL\u683C\u5F0F",
|
|
"github.api.rate.limit.exceeded.short": "GitHub API\u8C03\u7528\u6B21\u6570\u5DF2\u8FBE\u4E0A\u9650\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5",
|
|
"github.api.file.upload.success": "\u6587\u4EF6\u4E0A\u4F20\u6210\u529F",
|
|
"github.api.all.files.download.success": "\u6240\u6709\u6587\u4EF6\u4E0B\u8F7D\u6210\u529F",
|
|
// Status bar
|
|
"status.bar.checking": "\u68C0\u67E5\u4E2D...",
|
|
"status.bar.sync": "\u540C\u6B65",
|
|
"status.bar.rate.limit": "API\u9650\u5236: \u7B49\u5F85{minutes}\u5206\u949F",
|
|
"status.bar.last.modified": "\u4E0A\u6B21\u66F4\u65B0: {date}",
|
|
"status.bar.not.published": "\u672A\u53D1\u5E03",
|
|
"status.bar.check.failed": "\u68C0\u67E5\u5931\u8D25",
|
|
"status.bar.not.configured": "\u672A\u914D\u7F6E",
|
|
"status.bar.local.modified": "\u672C\u5730\u5DF2\u4FEE\u6539",
|
|
"status.bar.synced": "\u5DF2\u540C\u6B65",
|
|
// Plugin info
|
|
"plugin.name": "Git\u540C\u6B65",
|
|
"command.show.sync.menu": "\u663E\u793A\u540C\u6B65\u83DC\u5355",
|
|
// Test URL results
|
|
"test.url.user": "\u7528\u6237",
|
|
"test.url.repo": "\u4ED3\u5E93",
|
|
"test.url.path": "\u8DEF\u5F84",
|
|
"test.url.root": "\u6839\u76EE\u5F55",
|
|
// Path info
|
|
"path.info.empty": "\u8BF7\u8F93\u5165GitHub\u4ED3\u5E93\u8DEF\u5F84\u4EE5\u67E5\u770B\u540C\u6B65\u76EE\u6807",
|
|
"path.info.sync.to": "\u5F53\u524D Vault \u5185\u5BB9\u5C06\u540C\u6B65\u5230 {owner}/{repo} \u4ED3\u5E93",
|
|
"path.info.folder": " \u7684 {path} \u6587\u4EF6\u5939\u4E0B",
|
|
"path.info.root": " \u7684\u6839\u76EE\u5F55\u4E0B",
|
|
"path.info.error": "\u8DEF\u5F84\u683C\u5F0F\u4E0D\u6B63\u786E\uFF0C\u8BF7\u4F7F\u7528: https://github.com/\u7528\u6237\u540D/\u4ED3\u5E93\u540D/\u8DEF\u5F84 \u6216 \u7528\u6237\u540D/\u4ED3\u5E93\u540D/\u8DEF\u5F84",
|
|
// COS upload messages
|
|
"cos.upload.success": "\u56FE\u7247\u4E0A\u4F20\u6210\u529F",
|
|
"cos.upload.failed": "\u56FE\u7247\u4E0A\u4F20\u5931\u8D25: {error}",
|
|
"cos.upload.uploading": "\u6B63\u5728\u4E0A\u4F20\u56FE\u7247...",
|
|
"cos.upload.no.config": "\u56FE\u7247\u5904\u7406\u529F\u80FD\u5DF2\u542F\u7528\uFF0C\u4F46\u9700\u8981\u914D\u7F6E\u4E91\u5B58\u50A8\u6216\u672C\u5730\u5B58\u50A8\u8DEF\u5F84",
|
|
"cos.test.success": "COS\u914D\u7F6E\u6D4B\u8BD5\u6210\u529F",
|
|
"cos.test.failed": "COS\u914D\u7F6E\u6D4B\u8BD5\u5931\u8D25\uFF1A{error}",
|
|
"cos.error.unsupported.provider": "\u4E0D\u652F\u6301\u7684\u4E91\u5B58\u50A8\u670D\u52A1\u5546\uFF1A{provider}",
|
|
"cos.error.upload.failed": "\u4E0A\u4F20\u5931\u8D25\uFF1A{error}",
|
|
"cos.error.aliyun.upload.failed": "\u963F\u91CC\u4E91OSS\u4E0A\u4F20\u5931\u8D25\uFF08{status}\uFF09\uFF1A{error}",
|
|
"cos.error.tencent.upload.failed": "\u817E\u8BAF\u4E91COS\u4E0A\u4F20\u5931\u8D25\uFF08{status}\uFF09\uFF1A{error}",
|
|
"cos.error.aws.upload.failed": "AWS S3\u4E0A\u4F20\u5931\u8D25\uFF08{status}\uFF09\uFF1A{error}",
|
|
"cos.error.cloudflare.upload.failed": "Cloudflare R2\u4E0A\u4F20\u5931\u8D25\uFF08{status}\uFF09\uFF1A{error}",
|
|
"cos.error.config.invalid": "COS\u914D\u7F6E\u4E0D\u5B8C\u6574\uFF0C\u8BF7\u68C0\u67E5\u914D\u7F6E\u9879",
|
|
"cos.paste.placeholder": "\u6B63\u5728\u4E0A\u4F20 {filename}..."
|
|
},
|
|
en: {
|
|
// Settings interface
|
|
"settings.title": "Git Sync Settings",
|
|
"settings.language.name": "Interface Language",
|
|
"settings.language.desc": "Select the display language for the plugin interface",
|
|
"settings.language.auto": "Follow Obsidian",
|
|
"settings.github.token.name": "GitHub Personal Token",
|
|
"settings.github.token.desc": "Enter your GitHub Personal Access Token",
|
|
"settings.github.token.placeholder": "ghp_xxxxxxxxxxxx",
|
|
"settings.github.repo.name": "GitHub Repository Path",
|
|
"settings.github.repo.desc": "Supports two formats:\n1. https://github.com/username/repo/path\n2. username/repo/path",
|
|
"settings.github.repo.placeholder": "https://github.com/Xheldon/git-sync/data/_post",
|
|
"settings.ribbon.name": "Show plugin button in sidebar",
|
|
"settings.ribbon.desc": "When enabled, display plugin button in left sidebar for quick access to settings",
|
|
"settings.save.name": "Save Settings",
|
|
"settings.save.desc": "Save current configuration settings",
|
|
"settings.save.button": "Save Settings",
|
|
"settings.diagnose.name": "Diagnose Vault Files",
|
|
"settings.diagnose.desc": "Check which files in current Vault can be synchronized",
|
|
"settings.diagnose.button": "Diagnose",
|
|
"settings.test.url.name": "Test Repository URL",
|
|
"settings.test.url.desc": "Verify if GitHub repository path format is correct",
|
|
"settings.test.url.button": "Test URL",
|
|
"settings.sponsor.name": "\u{1F496} Support Developer",
|
|
"settings.sponsor.desc": "If this plugin helps you, consider buying me a coffee! Your support motivates me to continue development.",
|
|
"settings.sponsor.button": "\u{1F49D} PayPal Sponsor",
|
|
"settings.sponsor.section.title": "Sponsor",
|
|
"settings.danger.zone.title": "Danger Zone",
|
|
"settings.init.name": "Initialize Repository",
|
|
"settings.init.desc": "Available when Vault is empty, sync remote files to local",
|
|
"settings.init.button": "Initialize Repository",
|
|
"settings.init.loading": "Initializing...",
|
|
"settings.sync.remote.to.local.name": "Force Sync Remote to Local",
|
|
"settings.sync.remote.to.local.desc": "Sync all remote files to local Vault, existing files will be overwritten",
|
|
"settings.sync.remote.to.local.button": "Force Sync to Local",
|
|
"settings.sync.remote.to.local.loading": "Syncing...",
|
|
"settings.sync.local.to.remote.name": "Force Sync Local to Remote",
|
|
"settings.sync.local.to.remote.desc": "Sync all local Vault files to remote repository, existing files will be overwritten",
|
|
"settings.sync.local.to.remote.button": "Force Sync to Remote",
|
|
"settings.sync.local.to.remote.loading": "Syncing...",
|
|
"settings.clear.cache.name": "Clear File Cache",
|
|
"settings.clear.cache.desc": "Clear all file status cache, will fetch from GitHub on next view",
|
|
"settings.clear.cache.button": "Clear Cache",
|
|
// COS settings
|
|
"settings.image.section.title": "Image Processing",
|
|
"settings.image.enable.name": "Enable Image Processing",
|
|
"settings.image.enable.desc": "When enabled, images pasted will be automatically uploaded to cloud storage and replaced with links",
|
|
"settings.cos.provider.section.title": "Cloud Provider Settings",
|
|
"settings.image.upload.section.title": "Image Upload Settings",
|
|
"settings.cos.provider.name": "Cloud Storage Provider",
|
|
"settings.cos.provider.desc": "Select the cloud object storage service to use",
|
|
"settings.cos.provider.aliyun": "Aliyun OSS",
|
|
"settings.cos.provider.tencent": "Tencent COS",
|
|
"settings.cos.provider.aws": "AWS S3",
|
|
"settings.cos.provider.cloudflare": "Cloudflare R2",
|
|
"settings.cos.secret.id.name": "Access Key ID / Secret ID",
|
|
"settings.cos.secret.id.desc": "Access key ID for cloud storage service",
|
|
"settings.cos.secret.id.placeholder": "Enter Access Key ID or Secret ID",
|
|
"settings.cos.secret.key.name": "Access Key Secret / Secret Key",
|
|
"settings.cos.secret.key.desc": "Access key secret for cloud storage service",
|
|
"settings.cos.secret.key.placeholder": "Enter Access Key Secret or Secret Key",
|
|
"settings.cos.bucket.name": "Bucket Name",
|
|
"settings.cos.bucket.desc": "Storage bucket name",
|
|
"settings.cos.bucket.placeholder": "Enter bucket name",
|
|
"settings.cos.endpoint.name": "Endpoint",
|
|
"settings.cos.endpoint.desc": "Service endpoint address (only required for Cloudflare R2)",
|
|
"settings.cos.endpoint.placeholder": "e.g.: https://accountid.r2.cloudflarestorage.com",
|
|
"settings.cos.region.name": "Region",
|
|
"settings.cos.region.desc": "Region setting (required for all providers)",
|
|
"settings.cos.region.placeholder": "e.g.: cn-hangzhou, ap-beijing, us-east-1",
|
|
"settings.cos.cdn.name": "CDN URL",
|
|
"settings.cos.cdn.desc": "CDN domain for generating access links",
|
|
"settings.cos.cdn.placeholder": "e.g.: https://cdn.example.com",
|
|
"settings.cos.keep.local.name": "Keep Images Locally",
|
|
"settings.cos.keep.local.desc": "Whether to keep a local copy of images after upload",
|
|
"settings.cos.local.path.name": "Local Storage Path",
|
|
"settings.cos.local.path.desc": "Directory to save images locally (relative to vault root)",
|
|
"settings.cos.local.path.placeholder": "e.g.: assets",
|
|
"settings.cos.upload.path.name": "Upload Path Template",
|
|
"settings.cos.upload.path.desc": "Supports placeholders: {PATH} (current file path), {FILENAME} (file name), {FOLDER} (folder name), {YYYY} (year), {MM} (month), {DD} (day)",
|
|
"settings.cos.upload.path.placeholder": "e.g.: images/{YYYY}/{MM}/{DD}",
|
|
"settings.cos.clear.name": "Clear Current Configuration",
|
|
"settings.cos.clear.desc": "Clear all configuration for the currently selected provider",
|
|
"settings.cos.clear.button": "Clear Config",
|
|
"settings.cos.clear.success": "Configuration cleared",
|
|
"settings.cos.test.name": "Test COS Configuration",
|
|
"settings.cos.test.desc": "Test if current COS configuration is available",
|
|
"settings.cos.test.button": "Test Connection",
|
|
"settings.cos.test.loading": "Testing...",
|
|
// Notification messages
|
|
"notice.settings.saved": "Settings saved",
|
|
"notice.config.required": "Please configure GitHub Token and repository address first",
|
|
"notice.url.required": "Please enter GitHub repository path first",
|
|
"notice.url.test.success": "URL format is correct!",
|
|
"notice.url.test.failed": "URL format is incorrect, please check format. See console for details.",
|
|
"notice.init.error": "Error occurred during repository initialization",
|
|
"notice.sync.error": "Error occurred during force sync",
|
|
"notice.diagnose.result": "Vault has {total} files in total, {syncable} can be synced. See console for details.",
|
|
"notice.result.with.count": "{message}, processed {count} files",
|
|
"notice.cache.cleared": "Cleared cache for {count} files",
|
|
"notice.cache.clear.error": "Error occurred while clearing cache",
|
|
// Sync operations
|
|
"sync.success": "Sync success: {filename}",
|
|
"sync.failed": "Sync failed: {message}",
|
|
"sync.error": "Error occurred during sync",
|
|
"pull.success": "Pull success: {filename}",
|
|
"pull.failed": "Pull failed: {message}",
|
|
"pull.error": "Error occurred during pull",
|
|
// Repository operations
|
|
"vault.not.empty": "Vault is not empty, cannot initialize",
|
|
"repo.init.success": "Repository initialized successfully",
|
|
"repo.init.failed": "Repository initialization failed: {error}",
|
|
"force.sync.remote.to.local.success": "Force sync remote to local success",
|
|
"force.sync.remote.to.local.failed": "Force sync remote to local failed: {error}",
|
|
"no.syncable.files.in.vault": "No syncable files in vault",
|
|
"force.sync.local.to.remote.success.no.failures": "Force sync local to remote success",
|
|
"force.sync.local.to.remote.success": "Force sync local to remote completed, success: {processed}, failed: {failed}",
|
|
"force.sync.local.to.remote.failed": "Force sync local to remote failed: {error}",
|
|
// Actions
|
|
"actions.sync.current.to.remote": "Sync current file to remote",
|
|
"actions.pull.remote.to.current": "Pull remote to current file",
|
|
// Date
|
|
"date.today": "Today",
|
|
"date.yesterday": "Yesterday",
|
|
// GitHub API errors
|
|
"github.api.rate.limit.exceeded": "GitHub API rate limit exceeded. Please wait {minutes} minutes before retrying.",
|
|
"github.api.rate.limit.warning": "\u26A0\uFE0F GitHub API calls remaining: {remaining}. Please use carefully.",
|
|
"github.api.rate.limit.notice": "Rate limit exceeded",
|
|
"github.api.token.invalid": "GitHub Token is invalid or expired. Please check:\n1. Token is correct\n2. Token has sufficient permissions\n3. Token has not expired",
|
|
"github.api.rate.limit.hourly": "GitHub API hourly rate limit exceeded (5000 per hour).\nPlease wait {minutes} minutes or use GitHub Pro for higher limits.",
|
|
"github.api.repo.not.found": "Repository not found or no access permission. Please check:\n1. Repository URL is correct\n2. Token has access to this repository\n3. Repository is not private",
|
|
"github.api.file.conflict": "File conflict. Remote file has been modified by others.\nPlease sync remote changes first, then retry.",
|
|
"github.api.validation.failed": "GitHub API validation failed. Please check:\n1. File path is correct\n2. File content meets requirements\n3. Repository permission settings",
|
|
"github.api.server.error": "GitHub server error ({status}). Please retry later.",
|
|
"github.api.network.error": "Network connection error. Please check:\n1. Network connection is normal\n2. Firewall settings\n3. Proxy configuration",
|
|
"github.api.timeout.error": "Request timeout. Please check network connection or retry later.",
|
|
"github.api.unknown.error": "Unknown error: {message}",
|
|
"github.api.access.denied": "GitHub access denied. Possible reasons:\n1. Insufficient token permissions\n2. Repository is private and token has no access\n3. Repository does not exist",
|
|
"github.api.resource.not.found": "Resource not found. Please check:\n1. Repository path is correct\n2. File path exists\n3. Token has access to this repository",
|
|
"github.api.file.conflict.detailed": "File conflict. Possible reasons:\n1. File has been modified remotely\n2. Please sync from remote first",
|
|
"github.api.invalid.request": "Invalid request parameters. Please check:\n1. File content is not too large (>100MB)\n2. File path format is correct",
|
|
"github.api.server.error.detailed": "GitHub server error, please retry later. If problem persists, check GitHub service status.",
|
|
"github.api.error.with.status": "GitHub API error ({status}): {message}",
|
|
"github.api.network.failed": "Network connection failed. Please check:\n1. Network connection is normal\n2. Can access github.com\n3. Firewall or proxy settings",
|
|
"github.api.timeout.detailed": "Request timeout. Please check network connection or retry later.",
|
|
"github.api.operation.failed": "Operation failed: {message}",
|
|
"github.api.retry.hint": "\u{1F4A1} Tip: This is a temporary error, you can retry later",
|
|
"github.api.invalid.url.format": "Invalid repository URL format",
|
|
"github.api.rate.limit.exceeded.short": "GitHub API rate limit exceeded, please retry later",
|
|
"github.api.file.upload.success": "File uploaded successfully",
|
|
"github.api.all.files.download.success": "All files downloaded successfully",
|
|
// Status bar
|
|
"status.bar.checking": "Checking...",
|
|
"status.bar.sync": "Sync",
|
|
"status.bar.rate.limit": "API limit: wait {minutes} minutes",
|
|
"status.bar.last.modified": "Last modified: {date}",
|
|
"status.bar.not.published": "Not published",
|
|
"status.bar.check.failed": "Check failed",
|
|
"status.bar.not.configured": "Not configured",
|
|
"status.bar.local.modified": "Local modified",
|
|
"status.bar.synced": "Synced",
|
|
// Plugin info
|
|
"plugin.name": "Git Sync",
|
|
"command.show.sync.menu": "Show Sync Menu",
|
|
// Test URL results
|
|
"test.url.user": "User",
|
|
"test.url.repo": "Repo",
|
|
"test.url.path": "Path",
|
|
"test.url.root": "Root",
|
|
// Path info
|
|
"path.info.empty": "Enter GitHub repository path to view sync target",
|
|
"path.info.sync.to": "Current Vault content will sync to {owner}/{repo} repository",
|
|
"path.info.folder": " under {path} folder",
|
|
"path.info.root": " under root directory",
|
|
"path.info.error": "Path format is incorrect, please use: https://github.com/username/repo/path or username/repo/path",
|
|
// COS upload messages
|
|
"cos.upload.success": "Image uploaded successfully",
|
|
"cos.upload.failed": "Image upload failed: {error}",
|
|
"cos.upload.uploading": "Uploading image...",
|
|
"cos.upload.no.config": "Image processing is enabled, but cloud storage or local storage path needs to be configured",
|
|
"cos.test.success": "COS configuration test successful",
|
|
"cos.test.failed": "COS configuration test failed: {error}",
|
|
"cos.error.unsupported.provider": "Unsupported cloud storage provider: {provider}",
|
|
"cos.error.upload.failed": "Upload failed: {error}",
|
|
"cos.error.aliyun.upload.failed": "Aliyun OSS upload failed ({status}): {error}",
|
|
"cos.error.tencent.upload.failed": "Tencent COS upload failed ({status}): {error}",
|
|
"cos.error.aws.upload.failed": "AWS S3 upload failed ({status}): {error}",
|
|
"cos.error.cloudflare.upload.failed": "Cloudflare R2 upload failed ({status}): {error}",
|
|
"cos.error.config.invalid": "COS configuration is incomplete, please check settings",
|
|
"cos.paste.placeholder": "Uploading {filename}..."
|
|
}
|
|
};
|
|
currentLanguage = "auto";
|
|
}
|
|
});
|
|
|
|
// cos-service.ts
|
|
var cos_service_exports = {};
|
|
__export(cos_service_exports, {
|
|
CosService: () => CosService,
|
|
parseImagePath: () => parseImagePath
|
|
});
|
|
function parseImagePath(template, context) {
|
|
var _a;
|
|
const date = context.date || new Date();
|
|
const year = date.getFullYear().toString();
|
|
const month = (date.getMonth() + 1).toString().padStart(2, "0");
|
|
const day = date.getDate().toString().padStart(2, "0");
|
|
const pathParts = context.currentFilePath.split("/");
|
|
const fileName = ((_a = pathParts.pop()) == null ? void 0 : _a.replace(/\.[^/.]+$/, "")) || "";
|
|
const folderPath = pathParts.join("/");
|
|
const folderName = pathParts[pathParts.length - 1] || "";
|
|
let result = template.replace(/\{YYYY\}/g, year).replace(/\{MM\}/g, month).replace(/\{DD\}/g, day).replace(/\{PATH\}/g, folderPath).replace(/\{FILENAME\}/g, fileName).replace(/\{FOLDER\}/g, folderName);
|
|
if (!result.endsWith("/")) {
|
|
result += "/";
|
|
}
|
|
result += context.fileName;
|
|
result = result.replace(/\/+/g, "/").replace(/^\//, "");
|
|
return result;
|
|
}
|
|
var import_obsidian2, CosService;
|
|
var init_cos_service = __esm({
|
|
"cos-service.ts"() {
|
|
init_i18n_simple();
|
|
import_obsidian2 = require("obsidian");
|
|
CosService = class {
|
|
constructor(config) {
|
|
this.config = config;
|
|
}
|
|
/**
|
|
* Upload file to COS
|
|
*/
|
|
async uploadFile(file, remotePath) {
|
|
try {
|
|
switch (this.config.provider) {
|
|
case "aliyun":
|
|
return await this.uploadToAliyun(file, remotePath);
|
|
case "tencent":
|
|
return await this.uploadToTencent(file, remotePath);
|
|
case "aws":
|
|
return await this.uploadToAWS(file, remotePath);
|
|
case "cloudflare":
|
|
return await this.uploadToCloudflare(file, remotePath);
|
|
default:
|
|
return {
|
|
success: false,
|
|
message: t("cos.error.unsupported.provider", { provider: this.config.provider })
|
|
};
|
|
}
|
|
} catch (error) {
|
|
console.error("COS upload error:", error);
|
|
return {
|
|
success: false,
|
|
message: t("cos.error.upload.failed", { error: error.message })
|
|
};
|
|
}
|
|
}
|
|
/**
|
|
* Test COS configuration
|
|
*/
|
|
async testConnection() {
|
|
try {
|
|
const testContent = "test";
|
|
const testFile = new File([testContent], "test.txt", { type: "text/plain" });
|
|
const testPath = `test-${Date.now()}.txt`;
|
|
const result = await this.uploadFile(testFile, testPath);
|
|
if (result.success) {
|
|
await this.deleteFile(testPath).catch(console.warn);
|
|
return {
|
|
success: true,
|
|
message: t("cos.test.success")
|
|
};
|
|
}
|
|
return result;
|
|
} catch (error) {
|
|
console.error("COS test connection error:", error);
|
|
return {
|
|
success: false,
|
|
message: t("cos.test.failed", { error: error.message })
|
|
};
|
|
}
|
|
}
|
|
/**
|
|
* Delete file from COS
|
|
*/
|
|
async deleteFile(remotePath) {
|
|
switch (this.config.provider) {
|
|
case "aliyun":
|
|
await this.deleteFromAliyun(remotePath);
|
|
break;
|
|
case "tencent":
|
|
await this.deleteFromTencent(remotePath);
|
|
break;
|
|
case "aws":
|
|
await this.deleteFromAWS(remotePath);
|
|
break;
|
|
case "cloudflare":
|
|
await this.deleteFromCloudflare(remotePath);
|
|
break;
|
|
}
|
|
}
|
|
/**
|
|
* Upload to Aliyun OSS
|
|
*/
|
|
async uploadToAliyun(file, remotePath) {
|
|
const endpoint2 = `oss-${this.config.region}.aliyuncs.com`;
|
|
const url = `https://${this.config.bucket}.${endpoint2}/${remotePath}`;
|
|
const date = new Date().toUTCString();
|
|
const signature = await this.generateAliyunSignature("PUT", remotePath, date, file.type);
|
|
const fileBuffer = await file.arrayBuffer();
|
|
const response = await (0, import_obsidian2.requestUrl)({
|
|
url,
|
|
method: "PUT",
|
|
headers: {
|
|
"Date": date,
|
|
"Content-Type": file.type,
|
|
"Authorization": `OSS ${this.config.secretId}:${signature}`
|
|
},
|
|
body: fileBuffer
|
|
});
|
|
if (response.status >= 200 && response.status < 300) {
|
|
const finalUrl = this.config.cdnUrl ? `${this.config.cdnUrl}/${remotePath}` : url;
|
|
return {
|
|
success: true,
|
|
message: t("cos.upload.success"),
|
|
url: finalUrl,
|
|
key: remotePath
|
|
};
|
|
} else {
|
|
const errorText = response.text;
|
|
return {
|
|
success: false,
|
|
message: t("cos.error.aliyun.upload.failed", {
|
|
status: response.status,
|
|
error: errorText
|
|
})
|
|
};
|
|
}
|
|
}
|
|
/**
|
|
* Upload to Tencent COS
|
|
*/
|
|
async uploadToTencent(file, remotePath) {
|
|
const url = `https://${this.config.bucket}.cos.${this.config.region}.myqcloud.com/${remotePath}`;
|
|
const date = new Date().toUTCString();
|
|
const signature = await this.generateTencentSignature("PUT", remotePath, date, file.type);
|
|
console.log("Tencent COS upload debug:", {
|
|
url,
|
|
remotePath,
|
|
signature: signature.substring(0, 50) + "...",
|
|
fileSize: file.size,
|
|
fileType: file.type
|
|
});
|
|
const fileBuffer = await file.arrayBuffer();
|
|
const response = await (0, import_obsidian2.requestUrl)({
|
|
url,
|
|
method: "PUT",
|
|
headers: {
|
|
"Content-Type": file.type,
|
|
"Authorization": signature
|
|
},
|
|
body: fileBuffer
|
|
});
|
|
if (response.status >= 200 && response.status < 300) {
|
|
const finalUrl = this.config.cdnUrl ? `${this.config.cdnUrl}/${remotePath}` : url;
|
|
return {
|
|
success: true,
|
|
message: t("cos.upload.success"),
|
|
url: finalUrl,
|
|
key: remotePath
|
|
};
|
|
} else {
|
|
const errorText = response.text;
|
|
return {
|
|
success: false,
|
|
message: t("cos.error.tencent.upload.failed", {
|
|
status: response.status,
|
|
error: errorText
|
|
})
|
|
};
|
|
}
|
|
}
|
|
/**
|
|
* Upload to AWS S3
|
|
*/
|
|
async uploadToAWS(file, remotePath) {
|
|
const url = `https://${this.config.bucket}.s3.${this.config.region}.amazonaws.com/${remotePath}`;
|
|
const date = new Date();
|
|
const signature = await this.generateAWSSignature("PUT", remotePath, date, file.type);
|
|
const fileBuffer = await file.arrayBuffer();
|
|
const response = await (0, import_obsidian2.requestUrl)({
|
|
url,
|
|
method: "PUT",
|
|
headers: {
|
|
"Content-Type": file.type,
|
|
...signature.headers
|
|
},
|
|
body: fileBuffer
|
|
});
|
|
if (response.status >= 200 && response.status < 300) {
|
|
const finalUrl = this.config.cdnUrl ? `${this.config.cdnUrl}/${remotePath}` : url;
|
|
return {
|
|
success: true,
|
|
message: t("cos.upload.success"),
|
|
url: finalUrl,
|
|
key: remotePath
|
|
};
|
|
} else {
|
|
const errorText = response.text;
|
|
return {
|
|
success: false,
|
|
message: t("cos.error.aws.upload.failed", {
|
|
status: response.status,
|
|
error: errorText
|
|
})
|
|
};
|
|
}
|
|
}
|
|
/**
|
|
* Upload to Cloudflare R2 (using S3 compatible API)
|
|
*/
|
|
async uploadToCloudflare(file, remotePath) {
|
|
const url = `${this.config.endpoint}/${remotePath}`;
|
|
const date = new Date();
|
|
const signature = await this.generateCloudflareSignature("PUT", remotePath, date, file.type);
|
|
const fileBuffer = await file.arrayBuffer();
|
|
const response = await (0, import_obsidian2.requestUrl)({
|
|
url,
|
|
method: "PUT",
|
|
headers: {
|
|
"Content-Type": file.type,
|
|
...signature.headers
|
|
},
|
|
body: fileBuffer
|
|
});
|
|
if (response.status >= 200 && response.status < 300) {
|
|
const finalUrl = this.config.cdnUrl ? `${this.config.cdnUrl}/${remotePath}` : url;
|
|
return {
|
|
success: true,
|
|
message: t("cos.upload.success"),
|
|
url: finalUrl,
|
|
key: remotePath
|
|
};
|
|
} else {
|
|
const errorText = response.text;
|
|
return {
|
|
success: false,
|
|
message: t("cos.error.cloudflare.upload.failed", {
|
|
status: response.status,
|
|
error: errorText
|
|
})
|
|
};
|
|
}
|
|
}
|
|
/**
|
|
* Delete from Aliyun OSS
|
|
*/
|
|
async deleteFromAliyun(remotePath) {
|
|
const endpoint2 = `oss-${this.config.region}.aliyuncs.com`;
|
|
const url = `https://${this.config.bucket}.${endpoint2}/${remotePath}`;
|
|
const date = new Date().toUTCString();
|
|
const signature = await this.generateAliyunSignature("DELETE", remotePath, date);
|
|
await (0, import_obsidian2.requestUrl)({
|
|
url,
|
|
method: "DELETE",
|
|
headers: {
|
|
"Date": date,
|
|
"Authorization": `OSS ${this.config.secretId}:${signature}`
|
|
}
|
|
});
|
|
}
|
|
/**
|
|
* Delete from Tencent COS
|
|
*/
|
|
async deleteFromTencent(remotePath) {
|
|
const url = `https://${this.config.bucket}.cos.${this.config.region}.myqcloud.com/${remotePath}`;
|
|
const date = new Date().toUTCString();
|
|
const signature = await this.generateTencentSignature("DELETE", remotePath, date);
|
|
await (0, import_obsidian2.requestUrl)({
|
|
url,
|
|
method: "DELETE",
|
|
headers: {
|
|
"Authorization": signature
|
|
}
|
|
});
|
|
}
|
|
/**
|
|
* Delete from AWS S3
|
|
*/
|
|
async deleteFromAWS(remotePath) {
|
|
const url = `https://${this.config.bucket}.s3.${this.config.region}.amazonaws.com/${remotePath}`;
|
|
const date = new Date();
|
|
const signature = await this.generateAWSSignature("DELETE", remotePath, date);
|
|
await (0, import_obsidian2.requestUrl)({
|
|
url,
|
|
method: "DELETE",
|
|
headers: signature.headers
|
|
});
|
|
}
|
|
/**
|
|
* Delete from Cloudflare R2
|
|
*/
|
|
async deleteFromCloudflare(remotePath) {
|
|
const url = `${this.config.endpoint}/${remotePath}`;
|
|
const date = new Date();
|
|
const signature = await this.generateCloudflareSignature("DELETE", remotePath, date);
|
|
await (0, import_obsidian2.requestUrl)({
|
|
url,
|
|
method: "DELETE",
|
|
headers: signature.headers
|
|
});
|
|
}
|
|
/**
|
|
* Generate signature for Aliyun OSS
|
|
*/
|
|
async generateAliyunSignature(method, path, date, contentType) {
|
|
const stringToSign = `${method}
|
|
|
|
${contentType || ""}
|
|
${date}
|
|
/${this.config.bucket}/${path}`;
|
|
console.log("Aliyun OSS signature debug:", {
|
|
method,
|
|
path,
|
|
date,
|
|
contentType,
|
|
stringToSign: stringToSign.replace(/\n/g, "\\n"),
|
|
bucket: this.config.bucket,
|
|
region: this.config.region
|
|
});
|
|
const encoder = new TextEncoder();
|
|
const key = await crypto.subtle.importKey(
|
|
"raw",
|
|
encoder.encode(this.config.secretKey),
|
|
{ name: "HMAC", hash: "SHA-1" },
|
|
false,
|
|
["sign"]
|
|
);
|
|
const signature = await crypto.subtle.sign("HMAC", key, encoder.encode(stringToSign));
|
|
const signatureBase64 = btoa(String.fromCharCode(...new Uint8Array(signature)));
|
|
console.log("Generated Aliyun signature:", signatureBase64.substring(0, 20) + "...");
|
|
return signatureBase64;
|
|
}
|
|
/**
|
|
* Generate signature for Tencent COS
|
|
*/
|
|
async generateTencentSignature(method, path, date, contentType) {
|
|
const now = Math.floor(Date.now() / 1e3);
|
|
const expireTime = now + 3600;
|
|
const keyTime = `${now};${expireTime}`;
|
|
console.log("Tencent signature debug:", {
|
|
method,
|
|
path,
|
|
keyTime,
|
|
secretId: this.config.secretId.substring(0, 8) + "...",
|
|
bucket: this.config.bucket,
|
|
region: this.config.region
|
|
});
|
|
const signKey = await this.hmacSha1(this.config.secretKey, keyTime);
|
|
const httpMethod = method.toLowerCase();
|
|
const uriPathname = `/${path}`;
|
|
const httpParameters = "";
|
|
const httpHeaders = `host=${this.config.bucket}.cos.${this.config.region}.myqcloud.com`;
|
|
const httpString = `${httpMethod}
|
|
${uriPathname}
|
|
${httpParameters}
|
|
${httpHeaders}
|
|
`;
|
|
const httpStringSha1 = await this.sha1Hash(httpString);
|
|
const stringToSign = `sha1
|
|
${keyTime}
|
|
${httpStringSha1}
|
|
`;
|
|
const signature = await this.hmacSha1(signKey, stringToSign);
|
|
const authorization = `q-sign-algorithm=sha1&q-ak=${this.config.secretId}&q-sign-time=${keyTime}&q-key-time=${keyTime}&q-header-list=host&q-url-param-list=&q-signature=${signature}`;
|
|
console.log("Generated authorization:", authorization.substring(0, 100) + "...");
|
|
return authorization;
|
|
}
|
|
/**
|
|
* HMAC-SHA1 implementation
|
|
*/
|
|
async hmacSha1(key, data) {
|
|
const encoder = new TextEncoder();
|
|
const keyBuffer = encoder.encode(key);
|
|
const dataBuffer = encoder.encode(data);
|
|
const cryptoKey = await crypto.subtle.importKey(
|
|
"raw",
|
|
keyBuffer,
|
|
{ name: "HMAC", hash: "SHA-1" },
|
|
false,
|
|
["sign"]
|
|
);
|
|
const signature = await crypto.subtle.sign("HMAC", cryptoKey, dataBuffer);
|
|
return Array.from(new Uint8Array(signature)).map((b) => b.toString(16).padStart(2, "0")).join("");
|
|
}
|
|
/**
|
|
* SHA1 hash implementation
|
|
*/
|
|
async sha1Hash(data) {
|
|
const encoder = new TextEncoder();
|
|
const dataBuffer = encoder.encode(data);
|
|
const hashBuffer = await crypto.subtle.digest("SHA-1", dataBuffer);
|
|
return Array.from(new Uint8Array(hashBuffer)).map((b) => b.toString(16).padStart(2, "0")).join("");
|
|
}
|
|
/**
|
|
* SHA256 hash implementation
|
|
*/
|
|
async sha256Hash(data) {
|
|
const encoder = new TextEncoder();
|
|
const dataBuffer = encoder.encode(data);
|
|
const hashBuffer = await crypto.subtle.digest("SHA-256", dataBuffer);
|
|
return Array.from(new Uint8Array(hashBuffer)).map((b) => b.toString(16).padStart(2, "0")).join("");
|
|
}
|
|
/**
|
|
* HMAC-SHA256 implementation (returns hex string)
|
|
*/
|
|
async hmacSha256Hex(key, data) {
|
|
const encoder = new TextEncoder();
|
|
const dataBuffer = encoder.encode(data);
|
|
const cryptoKey = await crypto.subtle.importKey(
|
|
"raw",
|
|
key,
|
|
{ name: "HMAC", hash: "SHA-256" },
|
|
false,
|
|
["sign"]
|
|
);
|
|
const signature = await crypto.subtle.sign("HMAC", cryptoKey, dataBuffer);
|
|
return Array.from(new Uint8Array(signature)).map((b) => b.toString(16).padStart(2, "0")).join("");
|
|
}
|
|
/**
|
|
* HMAC-SHA256 implementation (returns ArrayBuffer)
|
|
*/
|
|
async hmacSha256(key, data) {
|
|
const encoder = new TextEncoder();
|
|
const dataBuffer = encoder.encode(data);
|
|
const cryptoKey = await crypto.subtle.importKey(
|
|
"raw",
|
|
key,
|
|
{ name: "HMAC", hash: "SHA-256" },
|
|
false,
|
|
["sign"]
|
|
);
|
|
return await crypto.subtle.sign("HMAC", cryptoKey, dataBuffer);
|
|
}
|
|
/**
|
|
* Generate AWS signature key
|
|
*/
|
|
async getAWSSignatureKey(secretKey, dateStamp, region, service) {
|
|
const encoder = new TextEncoder();
|
|
const kDate = await this.hmacSha256(encoder.encode(`AWS4${secretKey}`), dateStamp);
|
|
const kRegion = await this.hmacSha256(kDate, region);
|
|
const kService = await this.hmacSha256(kRegion, service);
|
|
const kSigning = await this.hmacSha256(kService, "aws4_request");
|
|
return kSigning;
|
|
}
|
|
/**
|
|
* Generate signature for AWS S3 V4
|
|
*/
|
|
async generateAWSSignature(method, path, date, contentType) {
|
|
const isoDate = date.toISOString().replace(/[:\-]|\.\d{3}/g, "");
|
|
const dateStamp = isoDate.substring(0, 8);
|
|
const service = "s3";
|
|
const algorithm = "AWS4-HMAC-SHA256";
|
|
const host = `${this.config.bucket}.s3.${this.config.region}.amazonaws.com`;
|
|
const canonicalUri = `/${path}`;
|
|
const canonicalQueryString = "";
|
|
const canonicalHeaders = `host:${host}
|
|
x-amz-content-sha256:UNSIGNED-PAYLOAD
|
|
x-amz-date:${isoDate}
|
|
`;
|
|
const signedHeaders = "host;x-amz-content-sha256;x-amz-date";
|
|
const payloadHash = "UNSIGNED-PAYLOAD";
|
|
const canonicalRequest = `${method}
|
|
${canonicalUri}
|
|
${canonicalQueryString}
|
|
${canonicalHeaders}
|
|
${signedHeaders}
|
|
${payloadHash}`;
|
|
const credentialScope = `${dateStamp}/${this.config.region}/${service}/aws4_request`;
|
|
const canonicalRequestHash = await this.sha256Hash(canonicalRequest);
|
|
const stringToSign = `${algorithm}
|
|
${isoDate}
|
|
${credentialScope}
|
|
${canonicalRequestHash}`;
|
|
const signingKey = await this.getAWSSignatureKey(this.config.secretKey, dateStamp, this.config.region, service);
|
|
const signature = await this.hmacSha256Hex(signingKey, stringToSign);
|
|
console.log("AWS S3 signature debug:", {
|
|
method,
|
|
path,
|
|
bucket: this.config.bucket,
|
|
region: this.config.region,
|
|
canonicalRequest: canonicalRequest.substring(0, 100) + "...",
|
|
stringToSign: stringToSign.substring(0, 100) + "...",
|
|
signature: signature.substring(0, 16) + "..."
|
|
});
|
|
const headers = {
|
|
"X-Amz-Date": isoDate,
|
|
"X-Amz-Content-Sha256": payloadHash,
|
|
"Authorization": `${algorithm} Credential=${this.config.secretId}/${credentialScope}, SignedHeaders=${signedHeaders}, Signature=${signature}`
|
|
};
|
|
return { headers };
|
|
}
|
|
/**
|
|
* Generate signature for Cloudflare R2 (S3 compatible)
|
|
*/
|
|
async generateCloudflareSignature(method, path, date, contentType) {
|
|
const isoDate = date.toISOString().replace(/[:\-]|\.\d{3}/g, "");
|
|
const dateStamp = isoDate.substring(0, 8);
|
|
const service = "s3";
|
|
const algorithm = "AWS4-HMAC-SHA256";
|
|
const region = "auto";
|
|
const host = new URL(this.config.endpoint).host;
|
|
const canonicalUri = `/${path}`;
|
|
const canonicalQueryString = "";
|
|
const canonicalHeaders = `host:${host}
|
|
x-amz-content-sha256:UNSIGNED-PAYLOAD
|
|
x-amz-date:${isoDate}
|
|
`;
|
|
const signedHeaders = "host;x-amz-content-sha256;x-amz-date";
|
|
const payloadHash = "UNSIGNED-PAYLOAD";
|
|
const canonicalRequest = `${method}
|
|
${canonicalUri}
|
|
${canonicalQueryString}
|
|
${canonicalHeaders}
|
|
${signedHeaders}
|
|
${payloadHash}`;
|
|
const credentialScope = `${dateStamp}/${region}/${service}/aws4_request`;
|
|
const canonicalRequestHash = await this.sha256Hash(canonicalRequest);
|
|
const stringToSign = `${algorithm}
|
|
${isoDate}
|
|
${credentialScope}
|
|
${canonicalRequestHash}`;
|
|
const signingKey = await this.getAWSSignatureKey(this.config.secretKey, dateStamp, region, service);
|
|
const signature = await this.hmacSha256Hex(signingKey, stringToSign);
|
|
console.log("Cloudflare R2 signature debug:", {
|
|
method,
|
|
path,
|
|
endpoint: this.config.endpoint,
|
|
host,
|
|
canonicalRequest: canonicalRequest.substring(0, 100) + "...",
|
|
stringToSign: stringToSign.substring(0, 100) + "...",
|
|
signature: signature.substring(0, 16) + "..."
|
|
});
|
|
const headers = {
|
|
"X-Amz-Date": isoDate,
|
|
"X-Amz-Content-Sha256": payloadHash,
|
|
"Authorization": `${algorithm} Credential=${this.config.secretId}/${credentialScope}, SignedHeaders=${signedHeaders}, Signature=${signature}`
|
|
};
|
|
return { headers };
|
|
}
|
|
};
|
|
}
|
|
});
|
|
|
|
// main.ts
|
|
var main_exports = {};
|
|
__export(main_exports, {
|
|
default: () => GitSyncPlugin
|
|
});
|
|
module.exports = __toCommonJS(main_exports);
|
|
var import_obsidian3 = require("obsidian");
|
|
|
|
// types.ts
|
|
var DEFAULT_SETTINGS = {
|
|
githubToken: "",
|
|
repositoryUrl: "",
|
|
lastSyncTime: 0,
|
|
showRibbonIcon: true,
|
|
language: "auto",
|
|
// Follow Obsidian language setting
|
|
// Image processing defaults
|
|
enableImageProcessing: false,
|
|
// COS default settings
|
|
cosProvider: "aliyun",
|
|
cosConfigs: {
|
|
aliyun: {
|
|
secretId: "",
|
|
secretKey: "",
|
|
bucket: "",
|
|
endpoint: "",
|
|
cdnUrl: "",
|
|
region: ""
|
|
},
|
|
tencent: {
|
|
secretId: "",
|
|
secretKey: "",
|
|
bucket: "",
|
|
endpoint: "",
|
|
cdnUrl: "",
|
|
region: ""
|
|
},
|
|
aws: {
|
|
secretId: "",
|
|
secretKey: "",
|
|
bucket: "",
|
|
endpoint: "",
|
|
cdnUrl: "",
|
|
region: ""
|
|
},
|
|
cloudflare: {
|
|
secretId: "",
|
|
secretKey: "",
|
|
bucket: "",
|
|
endpoint: "",
|
|
cdnUrl: "",
|
|
region: ""
|
|
}
|
|
},
|
|
// Local image storage defaults
|
|
keepLocalImages: false,
|
|
localImagePath: "assets",
|
|
// Image upload path template default
|
|
imageUploadPath: "images/{YYYY}/{MM}/{DD}"
|
|
};
|
|
|
|
// node_modules/universal-user-agent/dist-web/index.js
|
|
function getUserAgent() {
|
|
if (typeof navigator === "object" && "userAgent" in navigator) {
|
|
return navigator.userAgent;
|
|
}
|
|
if (typeof process === "object" && process.version !== void 0) {
|
|
return `Node.js/${process.version.substr(1)} (${process.platform}; ${process.arch})`;
|
|
}
|
|
return "<environment undetectable>";
|
|
}
|
|
|
|
// node_modules/@octokit/core/dist-web/index.js
|
|
var import_before_after_hook = __toESM(require_before_after_hook());
|
|
|
|
// node_modules/is-plain-object/dist/is-plain-object.mjs
|
|
function isObject(o) {
|
|
return Object.prototype.toString.call(o) === "[object Object]";
|
|
}
|
|
function isPlainObject(o) {
|
|
var ctor, prot;
|
|
if (isObject(o) === false)
|
|
return false;
|
|
ctor = o.constructor;
|
|
if (ctor === void 0)
|
|
return true;
|
|
prot = ctor.prototype;
|
|
if (isObject(prot) === false)
|
|
return false;
|
|
if (prot.hasOwnProperty("isPrototypeOf") === false) {
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
// node_modules/@octokit/endpoint/dist-web/index.js
|
|
function lowercaseKeys(object) {
|
|
if (!object) {
|
|
return {};
|
|
}
|
|
return Object.keys(object).reduce((newObj, key) => {
|
|
newObj[key.toLowerCase()] = object[key];
|
|
return newObj;
|
|
}, {});
|
|
}
|
|
function mergeDeep(defaults, options) {
|
|
const result = Object.assign({}, defaults);
|
|
Object.keys(options).forEach((key) => {
|
|
if (isPlainObject(options[key])) {
|
|
if (!(key in defaults))
|
|
Object.assign(result, { [key]: options[key] });
|
|
else
|
|
result[key] = mergeDeep(defaults[key], options[key]);
|
|
} else {
|
|
Object.assign(result, { [key]: options[key] });
|
|
}
|
|
});
|
|
return result;
|
|
}
|
|
function removeUndefinedProperties(obj) {
|
|
for (const key in obj) {
|
|
if (obj[key] === void 0) {
|
|
delete obj[key];
|
|
}
|
|
}
|
|
return obj;
|
|
}
|
|
function merge(defaults, route, options) {
|
|
if (typeof route === "string") {
|
|
let [method, url] = route.split(" ");
|
|
options = Object.assign(url ? { method, url } : { url: method }, options);
|
|
} else {
|
|
options = Object.assign({}, route);
|
|
}
|
|
options.headers = lowercaseKeys(options.headers);
|
|
removeUndefinedProperties(options);
|
|
removeUndefinedProperties(options.headers);
|
|
const mergedOptions = mergeDeep(defaults || {}, options);
|
|
if (defaults && defaults.mediaType.previews.length) {
|
|
mergedOptions.mediaType.previews = defaults.mediaType.previews.filter((preview) => !mergedOptions.mediaType.previews.includes(preview)).concat(mergedOptions.mediaType.previews);
|
|
}
|
|
mergedOptions.mediaType.previews = mergedOptions.mediaType.previews.map(
|
|
(preview) => preview.replace(/-preview/, "")
|
|
);
|
|
return mergedOptions;
|
|
}
|
|
function addQueryParameters(url, parameters) {
|
|
const separator = /\?/.test(url) ? "&" : "?";
|
|
const names = Object.keys(parameters);
|
|
if (names.length === 0) {
|
|
return url;
|
|
}
|
|
return url + separator + names.map((name) => {
|
|
if (name === "q") {
|
|
return "q=" + parameters.q.split("+").map(encodeURIComponent).join("+");
|
|
}
|
|
return `${name}=${encodeURIComponent(parameters[name])}`;
|
|
}).join("&");
|
|
}
|
|
var urlVariableRegex = /\{[^}]+\}/g;
|
|
function removeNonChars(variableName) {
|
|
return variableName.replace(/^\W+|\W+$/g, "").split(/,/);
|
|
}
|
|
function extractUrlVariableNames(url) {
|
|
const matches = url.match(urlVariableRegex);
|
|
if (!matches) {
|
|
return [];
|
|
}
|
|
return matches.map(removeNonChars).reduce((a, b) => a.concat(b), []);
|
|
}
|
|
function omit(object, keysToOmit) {
|
|
return Object.keys(object).filter((option) => !keysToOmit.includes(option)).reduce((obj, key) => {
|
|
obj[key] = object[key];
|
|
return obj;
|
|
}, {});
|
|
}
|
|
function encodeReserved(str) {
|
|
return str.split(/(%[0-9A-Fa-f]{2})/g).map(function(part) {
|
|
if (!/%[0-9A-Fa-f]/.test(part)) {
|
|
part = encodeURI(part).replace(/%5B/g, "[").replace(/%5D/g, "]");
|
|
}
|
|
return part;
|
|
}).join("");
|
|
}
|
|
function encodeUnreserved(str) {
|
|
return encodeURIComponent(str).replace(/[!'()*]/g, function(c) {
|
|
return "%" + c.charCodeAt(0).toString(16).toUpperCase();
|
|
});
|
|
}
|
|
function encodeValue(operator, value, key) {
|
|
value = operator === "+" || operator === "#" ? encodeReserved(value) : encodeUnreserved(value);
|
|
if (key) {
|
|
return encodeUnreserved(key) + "=" + value;
|
|
} else {
|
|
return value;
|
|
}
|
|
}
|
|
function isDefined(value) {
|
|
return value !== void 0 && value !== null;
|
|
}
|
|
function isKeyOperator(operator) {
|
|
return operator === ";" || operator === "&" || operator === "?";
|
|
}
|
|
function getValues(context, operator, key, modifier) {
|
|
var value = context[key], result = [];
|
|
if (isDefined(value) && value !== "") {
|
|
if (typeof value === "string" || typeof value === "number" || typeof value === "boolean") {
|
|
value = value.toString();
|
|
if (modifier && modifier !== "*") {
|
|
value = value.substring(0, parseInt(modifier, 10));
|
|
}
|
|
result.push(
|
|
encodeValue(operator, value, isKeyOperator(operator) ? key : "")
|
|
);
|
|
} else {
|
|
if (modifier === "*") {
|
|
if (Array.isArray(value)) {
|
|
value.filter(isDefined).forEach(function(value2) {
|
|
result.push(
|
|
encodeValue(operator, value2, isKeyOperator(operator) ? key : "")
|
|
);
|
|
});
|
|
} else {
|
|
Object.keys(value).forEach(function(k) {
|
|
if (isDefined(value[k])) {
|
|
result.push(encodeValue(operator, value[k], k));
|
|
}
|
|
});
|
|
}
|
|
} else {
|
|
const tmp = [];
|
|
if (Array.isArray(value)) {
|
|
value.filter(isDefined).forEach(function(value2) {
|
|
tmp.push(encodeValue(operator, value2));
|
|
});
|
|
} else {
|
|
Object.keys(value).forEach(function(k) {
|
|
if (isDefined(value[k])) {
|
|
tmp.push(encodeUnreserved(k));
|
|
tmp.push(encodeValue(operator, value[k].toString()));
|
|
}
|
|
});
|
|
}
|
|
if (isKeyOperator(operator)) {
|
|
result.push(encodeUnreserved(key) + "=" + tmp.join(","));
|
|
} else if (tmp.length !== 0) {
|
|
result.push(tmp.join(","));
|
|
}
|
|
}
|
|
}
|
|
} else {
|
|
if (operator === ";") {
|
|
if (isDefined(value)) {
|
|
result.push(encodeUnreserved(key));
|
|
}
|
|
} else if (value === "" && (operator === "&" || operator === "?")) {
|
|
result.push(encodeUnreserved(key) + "=");
|
|
} else if (value === "") {
|
|
result.push("");
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
function parseUrl(template) {
|
|
return {
|
|
expand: expand.bind(null, template)
|
|
};
|
|
}
|
|
function expand(template, context) {
|
|
var operators = ["+", "#", ".", "/", ";", "?", "&"];
|
|
return template.replace(
|
|
/\{([^\{\}]+)\}|([^\{\}]+)/g,
|
|
function(_, expression, literal) {
|
|
if (expression) {
|
|
let operator = "";
|
|
const values = [];
|
|
if (operators.indexOf(expression.charAt(0)) !== -1) {
|
|
operator = expression.charAt(0);
|
|
expression = expression.substr(1);
|
|
}
|
|
expression.split(/,/g).forEach(function(variable) {
|
|
var tmp = /([^:\*]*)(?::(\d+)|(\*))?/.exec(variable);
|
|
values.push(getValues(context, operator, tmp[1], tmp[2] || tmp[3]));
|
|
});
|
|
if (operator && operator !== "+") {
|
|
var separator = ",";
|
|
if (operator === "?") {
|
|
separator = "&";
|
|
} else if (operator !== "#") {
|
|
separator = operator;
|
|
}
|
|
return (values.length !== 0 ? operator : "") + values.join(separator);
|
|
} else {
|
|
return values.join(",");
|
|
}
|
|
} else {
|
|
return encodeReserved(literal);
|
|
}
|
|
}
|
|
);
|
|
}
|
|
function parse(options) {
|
|
let method = options.method.toUpperCase();
|
|
let url = (options.url || "/").replace(/:([a-z]\w+)/g, "{$1}");
|
|
let headers = Object.assign({}, options.headers);
|
|
let body;
|
|
let parameters = omit(options, [
|
|
"method",
|
|
"baseUrl",
|
|
"url",
|
|
"headers",
|
|
"request",
|
|
"mediaType"
|
|
]);
|
|
const urlVariableNames = extractUrlVariableNames(url);
|
|
url = parseUrl(url).expand(parameters);
|
|
if (!/^http/.test(url)) {
|
|
url = options.baseUrl + url;
|
|
}
|
|
const omittedParameters = Object.keys(options).filter((option) => urlVariableNames.includes(option)).concat("baseUrl");
|
|
const remainingParameters = omit(parameters, omittedParameters);
|
|
const isBinaryRequest = /application\/octet-stream/i.test(headers.accept);
|
|
if (!isBinaryRequest) {
|
|
if (options.mediaType.format) {
|
|
headers.accept = headers.accept.split(/,/).map(
|
|
(preview) => preview.replace(
|
|
/application\/vnd(\.\w+)(\.v3)?(\.\w+)?(\+json)?$/,
|
|
`application/vnd$1$2.${options.mediaType.format}`
|
|
)
|
|
).join(",");
|
|
}
|
|
if (options.mediaType.previews.length) {
|
|
const previewsFromAcceptHeader = headers.accept.match(/[\w-]+(?=-preview)/g) || [];
|
|
headers.accept = previewsFromAcceptHeader.concat(options.mediaType.previews).map((preview) => {
|
|
const format = options.mediaType.format ? `.${options.mediaType.format}` : "+json";
|
|
return `application/vnd.github.${preview}-preview${format}`;
|
|
}).join(",");
|
|
}
|
|
}
|
|
if (["GET", "HEAD"].includes(method)) {
|
|
url = addQueryParameters(url, remainingParameters);
|
|
} else {
|
|
if ("data" in remainingParameters) {
|
|
body = remainingParameters.data;
|
|
} else {
|
|
if (Object.keys(remainingParameters).length) {
|
|
body = remainingParameters;
|
|
}
|
|
}
|
|
}
|
|
if (!headers["content-type"] && typeof body !== "undefined") {
|
|
headers["content-type"] = "application/json; charset=utf-8";
|
|
}
|
|
if (["PATCH", "PUT"].includes(method) && typeof body === "undefined") {
|
|
body = "";
|
|
}
|
|
return Object.assign(
|
|
{ method, url, headers },
|
|
typeof body !== "undefined" ? { body } : null,
|
|
options.request ? { request: options.request } : null
|
|
);
|
|
}
|
|
function endpointWithDefaults(defaults, route, options) {
|
|
return parse(merge(defaults, route, options));
|
|
}
|
|
function withDefaults(oldDefaults, newDefaults) {
|
|
const DEFAULTS2 = merge(oldDefaults, newDefaults);
|
|
const endpoint2 = endpointWithDefaults.bind(null, DEFAULTS2);
|
|
return Object.assign(endpoint2, {
|
|
DEFAULTS: DEFAULTS2,
|
|
defaults: withDefaults.bind(null, DEFAULTS2),
|
|
merge: merge.bind(null, DEFAULTS2),
|
|
parse
|
|
});
|
|
}
|
|
var VERSION = "7.0.6";
|
|
var userAgent = `octokit-endpoint.js/${VERSION} ${getUserAgent()}`;
|
|
var DEFAULTS = {
|
|
method: "GET",
|
|
baseUrl: "https://api.github.com",
|
|
headers: {
|
|
accept: "application/vnd.github.v3+json",
|
|
"user-agent": userAgent
|
|
},
|
|
mediaType: {
|
|
format: "",
|
|
previews: []
|
|
}
|
|
};
|
|
var endpoint = withDefaults(null, DEFAULTS);
|
|
|
|
// node_modules/@octokit/request/dist-web/index.js
|
|
var import_node_fetch = __toESM(require_browser());
|
|
|
|
// node_modules/deprecation/dist-web/index.js
|
|
var Deprecation = class extends Error {
|
|
constructor(message) {
|
|
super(message);
|
|
if (Error.captureStackTrace) {
|
|
Error.captureStackTrace(this, this.constructor);
|
|
}
|
|
this.name = "Deprecation";
|
|
}
|
|
};
|
|
|
|
// node_modules/@octokit/request-error/dist-web/index.js
|
|
var import_once = __toESM(require_once());
|
|
var logOnceCode = (0, import_once.default)((deprecation) => console.warn(deprecation));
|
|
var logOnceHeaders = (0, import_once.default)((deprecation) => console.warn(deprecation));
|
|
var RequestError = class extends Error {
|
|
constructor(message, statusCode, options) {
|
|
super(message);
|
|
if (Error.captureStackTrace) {
|
|
Error.captureStackTrace(this, this.constructor);
|
|
}
|
|
this.name = "HttpError";
|
|
this.status = statusCode;
|
|
let headers;
|
|
if ("headers" in options && typeof options.headers !== "undefined") {
|
|
headers = options.headers;
|
|
}
|
|
if ("response" in options) {
|
|
this.response = options.response;
|
|
headers = options.response.headers;
|
|
}
|
|
const requestCopy = Object.assign({}, options.request);
|
|
if (options.request.headers.authorization) {
|
|
requestCopy.headers = Object.assign({}, options.request.headers, {
|
|
authorization: options.request.headers.authorization.replace(/ .*$/, " [REDACTED]")
|
|
});
|
|
}
|
|
requestCopy.url = requestCopy.url.replace(/\bclient_secret=\w+/g, "client_secret=[REDACTED]").replace(/\baccess_token=\w+/g, "access_token=[REDACTED]");
|
|
this.request = requestCopy;
|
|
Object.defineProperty(this, "code", {
|
|
get() {
|
|
logOnceCode(new Deprecation("[@octokit/request-error] `error.code` is deprecated, use `error.status`."));
|
|
return statusCode;
|
|
}
|
|
});
|
|
Object.defineProperty(this, "headers", {
|
|
get() {
|
|
logOnceHeaders(new Deprecation("[@octokit/request-error] `error.headers` is deprecated, use `error.response.headers`."));
|
|
return headers || {};
|
|
}
|
|
});
|
|
}
|
|
};
|
|
|
|
// node_modules/@octokit/request/dist-web/index.js
|
|
var VERSION2 = "6.2.8";
|
|
function getBufferResponse(response) {
|
|
return response.arrayBuffer();
|
|
}
|
|
function fetchWrapper(requestOptions) {
|
|
const log = requestOptions.request && requestOptions.request.log ? requestOptions.request.log : console;
|
|
if (isPlainObject(requestOptions.body) || Array.isArray(requestOptions.body)) {
|
|
requestOptions.body = JSON.stringify(requestOptions.body);
|
|
}
|
|
let headers = {};
|
|
let status;
|
|
let url;
|
|
const fetch = requestOptions.request && requestOptions.request.fetch || globalThis.fetch || /* istanbul ignore next */
|
|
import_node_fetch.default;
|
|
return fetch(
|
|
requestOptions.url,
|
|
Object.assign(
|
|
{
|
|
method: requestOptions.method,
|
|
body: requestOptions.body,
|
|
headers: requestOptions.headers,
|
|
redirect: requestOptions.redirect,
|
|
// duplex must be set if request.body is ReadableStream or Async Iterables.
|
|
// See https://fetch.spec.whatwg.org/#dom-requestinit-duplex.
|
|
...requestOptions.body && { duplex: "half" }
|
|
},
|
|
// `requestOptions.request.agent` type is incompatible
|
|
// see https://github.com/octokit/types.ts/pull/264
|
|
requestOptions.request
|
|
)
|
|
).then(async (response) => {
|
|
url = response.url;
|
|
status = response.status;
|
|
for (const keyAndValue of response.headers) {
|
|
headers[keyAndValue[0]] = keyAndValue[1];
|
|
}
|
|
if ("deprecation" in headers) {
|
|
const matches = headers.link && headers.link.match(/<([^>]+)>; rel="deprecation"/);
|
|
const deprecationLink = matches && matches.pop();
|
|
log.warn(
|
|
`[@octokit/request] "${requestOptions.method} ${requestOptions.url}" is deprecated. It is scheduled to be removed on ${headers.sunset}${deprecationLink ? `. See ${deprecationLink}` : ""}`
|
|
);
|
|
}
|
|
if (status === 204 || status === 205) {
|
|
return;
|
|
}
|
|
if (requestOptions.method === "HEAD") {
|
|
if (status < 400) {
|
|
return;
|
|
}
|
|
throw new RequestError(response.statusText, status, {
|
|
response: {
|
|
url,
|
|
status,
|
|
headers,
|
|
data: void 0
|
|
},
|
|
request: requestOptions
|
|
});
|
|
}
|
|
if (status === 304) {
|
|
throw new RequestError("Not modified", status, {
|
|
response: {
|
|
url,
|
|
status,
|
|
headers,
|
|
data: await getResponseData(response)
|
|
},
|
|
request: requestOptions
|
|
});
|
|
}
|
|
if (status >= 400) {
|
|
const data = await getResponseData(response);
|
|
const error = new RequestError(toErrorMessage(data), status, {
|
|
response: {
|
|
url,
|
|
status,
|
|
headers,
|
|
data
|
|
},
|
|
request: requestOptions
|
|
});
|
|
throw error;
|
|
}
|
|
return getResponseData(response);
|
|
}).then((data) => {
|
|
return {
|
|
status,
|
|
url,
|
|
headers,
|
|
data
|
|
};
|
|
}).catch((error) => {
|
|
if (error instanceof RequestError)
|
|
throw error;
|
|
else if (error.name === "AbortError")
|
|
throw error;
|
|
throw new RequestError(error.message, 500, {
|
|
request: requestOptions
|
|
});
|
|
});
|
|
}
|
|
async function getResponseData(response) {
|
|
const contentType = response.headers.get("content-type");
|
|
if (/application\/json/.test(contentType)) {
|
|
return response.json();
|
|
}
|
|
if (!contentType || /^text\/|charset=utf-8$/.test(contentType)) {
|
|
return response.text();
|
|
}
|
|
return getBufferResponse(response);
|
|
}
|
|
function toErrorMessage(data) {
|
|
if (typeof data === "string")
|
|
return data;
|
|
if ("message" in data) {
|
|
if (Array.isArray(data.errors)) {
|
|
return `${data.message}: ${data.errors.map(JSON.stringify).join(", ")}`;
|
|
}
|
|
return data.message;
|
|
}
|
|
return `Unknown error: ${JSON.stringify(data)}`;
|
|
}
|
|
function withDefaults2(oldEndpoint, newDefaults) {
|
|
const endpoint2 = oldEndpoint.defaults(newDefaults);
|
|
const newApi = function(route, parameters) {
|
|
const endpointOptions = endpoint2.merge(route, parameters);
|
|
if (!endpointOptions.request || !endpointOptions.request.hook) {
|
|
return fetchWrapper(endpoint2.parse(endpointOptions));
|
|
}
|
|
const request2 = (route2, parameters2) => {
|
|
return fetchWrapper(
|
|
endpoint2.parse(endpoint2.merge(route2, parameters2))
|
|
);
|
|
};
|
|
Object.assign(request2, {
|
|
endpoint: endpoint2,
|
|
defaults: withDefaults2.bind(null, endpoint2)
|
|
});
|
|
return endpointOptions.request.hook(request2, endpointOptions);
|
|
};
|
|
return Object.assign(newApi, {
|
|
endpoint: endpoint2,
|
|
defaults: withDefaults2.bind(null, endpoint2)
|
|
});
|
|
}
|
|
var request = withDefaults2(endpoint, {
|
|
headers: {
|
|
"user-agent": `octokit-request.js/${VERSION2} ${getUserAgent()}`
|
|
}
|
|
});
|
|
|
|
// node_modules/@octokit/graphql/dist-web/index.js
|
|
var VERSION3 = "5.0.6";
|
|
function _buildMessageForResponseErrors(data) {
|
|
return `Request failed due to following response errors:
|
|
` + data.errors.map((e) => ` - ${e.message}`).join("\n");
|
|
}
|
|
var GraphqlResponseError = class extends Error {
|
|
constructor(request2, headers, response) {
|
|
super(_buildMessageForResponseErrors(response));
|
|
this.request = request2;
|
|
this.headers = headers;
|
|
this.response = response;
|
|
this.name = "GraphqlResponseError";
|
|
this.errors = response.errors;
|
|
this.data = response.data;
|
|
if (Error.captureStackTrace) {
|
|
Error.captureStackTrace(this, this.constructor);
|
|
}
|
|
}
|
|
};
|
|
var NON_VARIABLE_OPTIONS = [
|
|
"method",
|
|
"baseUrl",
|
|
"url",
|
|
"headers",
|
|
"request",
|
|
"query",
|
|
"mediaType"
|
|
];
|
|
var FORBIDDEN_VARIABLE_OPTIONS = ["query", "method", "url"];
|
|
var GHES_V3_SUFFIX_REGEX = /\/api\/v3\/?$/;
|
|
function graphql(request2, query, options) {
|
|
if (options) {
|
|
if (typeof query === "string" && "query" in options) {
|
|
return Promise.reject(
|
|
new Error(`[@octokit/graphql] "query" cannot be used as variable name`)
|
|
);
|
|
}
|
|
for (const key in options) {
|
|
if (!FORBIDDEN_VARIABLE_OPTIONS.includes(key))
|
|
continue;
|
|
return Promise.reject(
|
|
new Error(`[@octokit/graphql] "${key}" cannot be used as variable name`)
|
|
);
|
|
}
|
|
}
|
|
const parsedOptions = typeof query === "string" ? Object.assign({ query }, options) : query;
|
|
const requestOptions = Object.keys(
|
|
parsedOptions
|
|
).reduce((result, key) => {
|
|
if (NON_VARIABLE_OPTIONS.includes(key)) {
|
|
result[key] = parsedOptions[key];
|
|
return result;
|
|
}
|
|
if (!result.variables) {
|
|
result.variables = {};
|
|
}
|
|
result.variables[key] = parsedOptions[key];
|
|
return result;
|
|
}, {});
|
|
const baseUrl = parsedOptions.baseUrl || request2.endpoint.DEFAULTS.baseUrl;
|
|
if (GHES_V3_SUFFIX_REGEX.test(baseUrl)) {
|
|
requestOptions.url = baseUrl.replace(GHES_V3_SUFFIX_REGEX, "/api/graphql");
|
|
}
|
|
return request2(requestOptions).then((response) => {
|
|
if (response.data.errors) {
|
|
const headers = {};
|
|
for (const key of Object.keys(response.headers)) {
|
|
headers[key] = response.headers[key];
|
|
}
|
|
throw new GraphqlResponseError(
|
|
requestOptions,
|
|
headers,
|
|
response.data
|
|
);
|
|
}
|
|
return response.data.data;
|
|
});
|
|
}
|
|
function withDefaults3(request2, newDefaults) {
|
|
const newRequest = request2.defaults(newDefaults);
|
|
const newApi = (query, options) => {
|
|
return graphql(newRequest, query, options);
|
|
};
|
|
return Object.assign(newApi, {
|
|
defaults: withDefaults3.bind(null, newRequest),
|
|
endpoint: newRequest.endpoint
|
|
});
|
|
}
|
|
var graphql2 = withDefaults3(request, {
|
|
headers: {
|
|
"user-agent": `octokit-graphql.js/${VERSION3} ${getUserAgent()}`
|
|
},
|
|
method: "POST",
|
|
url: "/graphql"
|
|
});
|
|
function withCustomRequest(customRequest) {
|
|
return withDefaults3(customRequest, {
|
|
method: "POST",
|
|
url: "/graphql"
|
|
});
|
|
}
|
|
|
|
// node_modules/@octokit/auth-token/dist-web/index.js
|
|
var REGEX_IS_INSTALLATION_LEGACY = /^v1\./;
|
|
var REGEX_IS_INSTALLATION = /^ghs_/;
|
|
var REGEX_IS_USER_TO_SERVER = /^ghu_/;
|
|
async function auth(token) {
|
|
const isApp = token.split(/\./).length === 3;
|
|
const isInstallation = REGEX_IS_INSTALLATION_LEGACY.test(token) || REGEX_IS_INSTALLATION.test(token);
|
|
const isUserToServer = REGEX_IS_USER_TO_SERVER.test(token);
|
|
const tokenType = isApp ? "app" : isInstallation ? "installation" : isUserToServer ? "user-to-server" : "oauth";
|
|
return {
|
|
type: "token",
|
|
token,
|
|
tokenType
|
|
};
|
|
}
|
|
function withAuthorizationPrefix(token) {
|
|
if (token.split(/\./).length === 3) {
|
|
return `bearer ${token}`;
|
|
}
|
|
return `token ${token}`;
|
|
}
|
|
async function hook(token, request2, route, parameters) {
|
|
const endpoint2 = request2.endpoint.merge(
|
|
route,
|
|
parameters
|
|
);
|
|
endpoint2.headers.authorization = withAuthorizationPrefix(token);
|
|
return request2(endpoint2);
|
|
}
|
|
var createTokenAuth = function createTokenAuth2(token) {
|
|
if (!token) {
|
|
throw new Error("[@octokit/auth-token] No token passed to createTokenAuth");
|
|
}
|
|
if (typeof token !== "string") {
|
|
throw new Error(
|
|
"[@octokit/auth-token] Token passed to createTokenAuth is not a string"
|
|
);
|
|
}
|
|
token = token.replace(/^(token|bearer) +/i, "");
|
|
return Object.assign(auth.bind(null, token), {
|
|
hook: hook.bind(null, token)
|
|
});
|
|
};
|
|
|
|
// node_modules/@octokit/core/dist-web/index.js
|
|
var VERSION4 = "4.2.4";
|
|
var Octokit = class {
|
|
static defaults(defaults) {
|
|
const OctokitWithDefaults = class extends this {
|
|
constructor(...args) {
|
|
const options = args[0] || {};
|
|
if (typeof defaults === "function") {
|
|
super(defaults(options));
|
|
return;
|
|
}
|
|
super(
|
|
Object.assign(
|
|
{},
|
|
defaults,
|
|
options,
|
|
options.userAgent && defaults.userAgent ? {
|
|
userAgent: `${options.userAgent} ${defaults.userAgent}`
|
|
} : null
|
|
)
|
|
);
|
|
}
|
|
};
|
|
return OctokitWithDefaults;
|
|
}
|
|
/**
|
|
* Attach a plugin (or many) to your Octokit instance.
|
|
*
|
|
* @example
|
|
* const API = Octokit.plugin(plugin1, plugin2, plugin3, ...)
|
|
*/
|
|
static plugin(...newPlugins) {
|
|
var _a;
|
|
const currentPlugins = this.plugins;
|
|
const NewOctokit = (_a = class extends this {
|
|
}, _a.plugins = currentPlugins.concat(
|
|
newPlugins.filter((plugin) => !currentPlugins.includes(plugin))
|
|
), _a);
|
|
return NewOctokit;
|
|
}
|
|
constructor(options = {}) {
|
|
const hook2 = new import_before_after_hook.Collection();
|
|
const requestDefaults = {
|
|
baseUrl: request.endpoint.DEFAULTS.baseUrl,
|
|
headers: {},
|
|
request: Object.assign({}, options.request, {
|
|
// @ts-ignore internal usage only, no need to type
|
|
hook: hook2.bind(null, "request")
|
|
}),
|
|
mediaType: {
|
|
previews: [],
|
|
format: ""
|
|
}
|
|
};
|
|
requestDefaults.headers["user-agent"] = [
|
|
options.userAgent,
|
|
`octokit-core.js/${VERSION4} ${getUserAgent()}`
|
|
].filter(Boolean).join(" ");
|
|
if (options.baseUrl) {
|
|
requestDefaults.baseUrl = options.baseUrl;
|
|
}
|
|
if (options.previews) {
|
|
requestDefaults.mediaType.previews = options.previews;
|
|
}
|
|
if (options.timeZone) {
|
|
requestDefaults.headers["time-zone"] = options.timeZone;
|
|
}
|
|
this.request = request.defaults(requestDefaults);
|
|
this.graphql = withCustomRequest(this.request).defaults(requestDefaults);
|
|
this.log = Object.assign(
|
|
{
|
|
debug: () => {
|
|
},
|
|
info: () => {
|
|
},
|
|
warn: console.warn.bind(console),
|
|
error: console.error.bind(console)
|
|
},
|
|
options.log
|
|
);
|
|
this.hook = hook2;
|
|
if (!options.authStrategy) {
|
|
if (!options.auth) {
|
|
this.auth = async () => ({
|
|
type: "unauthenticated"
|
|
});
|
|
} else {
|
|
const auth2 = createTokenAuth(options.auth);
|
|
hook2.wrap("request", auth2.hook);
|
|
this.auth = auth2;
|
|
}
|
|
} else {
|
|
const { authStrategy, ...otherOptions } = options;
|
|
const auth2 = authStrategy(
|
|
Object.assign(
|
|
{
|
|
request: this.request,
|
|
log: this.log,
|
|
// we pass the current octokit instance as well as its constructor options
|
|
// to allow for authentication strategies that return a new octokit instance
|
|
// that shares the same internal state as the current one. The original
|
|
// requirement for this was the "event-octokit" authentication strategy
|
|
// of https://github.com/probot/octokit-auth-probot.
|
|
octokit: this,
|
|
octokitOptions: otherOptions
|
|
},
|
|
options.auth
|
|
)
|
|
);
|
|
hook2.wrap("request", auth2.hook);
|
|
this.auth = auth2;
|
|
}
|
|
const classConstructor = this.constructor;
|
|
classConstructor.plugins.forEach((plugin) => {
|
|
Object.assign(this, plugin(this, options));
|
|
});
|
|
}
|
|
};
|
|
Octokit.VERSION = VERSION4;
|
|
Octokit.plugins = [];
|
|
|
|
// node_modules/@octokit/plugin-request-log/dist-web/index.js
|
|
var VERSION5 = "1.0.4";
|
|
function requestLog(octokit) {
|
|
octokit.hook.wrap("request", (request2, options) => {
|
|
octokit.log.debug("request", options);
|
|
const start = Date.now();
|
|
const requestOptions = octokit.request.endpoint.parse(options);
|
|
const path = requestOptions.url.replace(options.baseUrl, "");
|
|
return request2(options).then((response) => {
|
|
octokit.log.info(`${requestOptions.method} ${path} - ${response.status} in ${Date.now() - start}ms`);
|
|
return response;
|
|
}).catch((error) => {
|
|
octokit.log.info(`${requestOptions.method} ${path} - ${error.status} in ${Date.now() - start}ms`);
|
|
throw error;
|
|
});
|
|
});
|
|
}
|
|
requestLog.VERSION = VERSION5;
|
|
|
|
// node_modules/@octokit/plugin-paginate-rest/dist-web/index.js
|
|
var VERSION6 = "6.1.2";
|
|
function normalizePaginatedListResponse(response) {
|
|
if (!response.data) {
|
|
return {
|
|
...response,
|
|
data: []
|
|
};
|
|
}
|
|
const responseNeedsNormalization = "total_count" in response.data && !("url" in response.data);
|
|
if (!responseNeedsNormalization)
|
|
return response;
|
|
const incompleteResults = response.data.incomplete_results;
|
|
const repositorySelection = response.data.repository_selection;
|
|
const totalCount = response.data.total_count;
|
|
delete response.data.incomplete_results;
|
|
delete response.data.repository_selection;
|
|
delete response.data.total_count;
|
|
const namespaceKey = Object.keys(response.data)[0];
|
|
const data = response.data[namespaceKey];
|
|
response.data = data;
|
|
if (typeof incompleteResults !== "undefined") {
|
|
response.data.incomplete_results = incompleteResults;
|
|
}
|
|
if (typeof repositorySelection !== "undefined") {
|
|
response.data.repository_selection = repositorySelection;
|
|
}
|
|
response.data.total_count = totalCount;
|
|
return response;
|
|
}
|
|
function iterator(octokit, route, parameters) {
|
|
const options = typeof route === "function" ? route.endpoint(parameters) : octokit.request.endpoint(route, parameters);
|
|
const requestMethod = typeof route === "function" ? route : octokit.request;
|
|
const method = options.method;
|
|
const headers = options.headers;
|
|
let url = options.url;
|
|
return {
|
|
[Symbol.asyncIterator]: () => ({
|
|
async next() {
|
|
if (!url)
|
|
return { done: true };
|
|
try {
|
|
const response = await requestMethod({ method, url, headers });
|
|
const normalizedResponse = normalizePaginatedListResponse(response);
|
|
url = ((normalizedResponse.headers.link || "").match(
|
|
/<([^>]+)>;\s*rel="next"/
|
|
) || [])[1];
|
|
return { value: normalizedResponse };
|
|
} catch (error) {
|
|
if (error.status !== 409)
|
|
throw error;
|
|
url = "";
|
|
return {
|
|
value: {
|
|
status: 200,
|
|
headers: {},
|
|
data: []
|
|
}
|
|
};
|
|
}
|
|
}
|
|
})
|
|
};
|
|
}
|
|
function paginate(octokit, route, parameters, mapFn) {
|
|
if (typeof parameters === "function") {
|
|
mapFn = parameters;
|
|
parameters = void 0;
|
|
}
|
|
return gather(
|
|
octokit,
|
|
[],
|
|
iterator(octokit, route, parameters)[Symbol.asyncIterator](),
|
|
mapFn
|
|
);
|
|
}
|
|
function gather(octokit, results, iterator2, mapFn) {
|
|
return iterator2.next().then((result) => {
|
|
if (result.done) {
|
|
return results;
|
|
}
|
|
let earlyExit = false;
|
|
function done() {
|
|
earlyExit = true;
|
|
}
|
|
results = results.concat(
|
|
mapFn ? mapFn(result.value, done) : result.value.data
|
|
);
|
|
if (earlyExit) {
|
|
return results;
|
|
}
|
|
return gather(octokit, results, iterator2, mapFn);
|
|
});
|
|
}
|
|
var composePaginateRest = Object.assign(paginate, {
|
|
iterator
|
|
});
|
|
function paginateRest(octokit) {
|
|
return {
|
|
paginate: Object.assign(paginate.bind(null, octokit), {
|
|
iterator: iterator.bind(null, octokit)
|
|
})
|
|
};
|
|
}
|
|
paginateRest.VERSION = VERSION6;
|
|
|
|
// node_modules/@octokit/plugin-rest-endpoint-methods/dist-web/index.js
|
|
var VERSION7 = "7.2.3";
|
|
var Endpoints = {
|
|
actions: {
|
|
addCustomLabelsToSelfHostedRunnerForOrg: [
|
|
"POST /orgs/{org}/actions/runners/{runner_id}/labels"
|
|
],
|
|
addCustomLabelsToSelfHostedRunnerForRepo: [
|
|
"POST /repos/{owner}/{repo}/actions/runners/{runner_id}/labels"
|
|
],
|
|
addSelectedRepoToOrgSecret: [
|
|
"PUT /orgs/{org}/actions/secrets/{secret_name}/repositories/{repository_id}"
|
|
],
|
|
addSelectedRepoToOrgVariable: [
|
|
"PUT /orgs/{org}/actions/variables/{name}/repositories/{repository_id}"
|
|
],
|
|
addSelectedRepoToRequiredWorkflow: [
|
|
"PUT /orgs/{org}/actions/required_workflows/{required_workflow_id}/repositories/{repository_id}"
|
|
],
|
|
approveWorkflowRun: [
|
|
"POST /repos/{owner}/{repo}/actions/runs/{run_id}/approve"
|
|
],
|
|
cancelWorkflowRun: [
|
|
"POST /repos/{owner}/{repo}/actions/runs/{run_id}/cancel"
|
|
],
|
|
createEnvironmentVariable: [
|
|
"POST /repositories/{repository_id}/environments/{environment_name}/variables"
|
|
],
|
|
createOrUpdateEnvironmentSecret: [
|
|
"PUT /repositories/{repository_id}/environments/{environment_name}/secrets/{secret_name}"
|
|
],
|
|
createOrUpdateOrgSecret: ["PUT /orgs/{org}/actions/secrets/{secret_name}"],
|
|
createOrUpdateRepoSecret: [
|
|
"PUT /repos/{owner}/{repo}/actions/secrets/{secret_name}"
|
|
],
|
|
createOrgVariable: ["POST /orgs/{org}/actions/variables"],
|
|
createRegistrationTokenForOrg: [
|
|
"POST /orgs/{org}/actions/runners/registration-token"
|
|
],
|
|
createRegistrationTokenForRepo: [
|
|
"POST /repos/{owner}/{repo}/actions/runners/registration-token"
|
|
],
|
|
createRemoveTokenForOrg: ["POST /orgs/{org}/actions/runners/remove-token"],
|
|
createRemoveTokenForRepo: [
|
|
"POST /repos/{owner}/{repo}/actions/runners/remove-token"
|
|
],
|
|
createRepoVariable: ["POST /repos/{owner}/{repo}/actions/variables"],
|
|
createRequiredWorkflow: ["POST /orgs/{org}/actions/required_workflows"],
|
|
createWorkflowDispatch: [
|
|
"POST /repos/{owner}/{repo}/actions/workflows/{workflow_id}/dispatches"
|
|
],
|
|
deleteActionsCacheById: [
|
|
"DELETE /repos/{owner}/{repo}/actions/caches/{cache_id}"
|
|
],
|
|
deleteActionsCacheByKey: [
|
|
"DELETE /repos/{owner}/{repo}/actions/caches{?key,ref}"
|
|
],
|
|
deleteArtifact: [
|
|
"DELETE /repos/{owner}/{repo}/actions/artifacts/{artifact_id}"
|
|
],
|
|
deleteEnvironmentSecret: [
|
|
"DELETE /repositories/{repository_id}/environments/{environment_name}/secrets/{secret_name}"
|
|
],
|
|
deleteEnvironmentVariable: [
|
|
"DELETE /repositories/{repository_id}/environments/{environment_name}/variables/{name}"
|
|
],
|
|
deleteOrgSecret: ["DELETE /orgs/{org}/actions/secrets/{secret_name}"],
|
|
deleteOrgVariable: ["DELETE /orgs/{org}/actions/variables/{name}"],
|
|
deleteRepoSecret: [
|
|
"DELETE /repos/{owner}/{repo}/actions/secrets/{secret_name}"
|
|
],
|
|
deleteRepoVariable: [
|
|
"DELETE /repos/{owner}/{repo}/actions/variables/{name}"
|
|
],
|
|
deleteRequiredWorkflow: [
|
|
"DELETE /orgs/{org}/actions/required_workflows/{required_workflow_id}"
|
|
],
|
|
deleteSelfHostedRunnerFromOrg: [
|
|
"DELETE /orgs/{org}/actions/runners/{runner_id}"
|
|
],
|
|
deleteSelfHostedRunnerFromRepo: [
|
|
"DELETE /repos/{owner}/{repo}/actions/runners/{runner_id}"
|
|
],
|
|
deleteWorkflowRun: ["DELETE /repos/{owner}/{repo}/actions/runs/{run_id}"],
|
|
deleteWorkflowRunLogs: [
|
|
"DELETE /repos/{owner}/{repo}/actions/runs/{run_id}/logs"
|
|
],
|
|
disableSelectedRepositoryGithubActionsOrganization: [
|
|
"DELETE /orgs/{org}/actions/permissions/repositories/{repository_id}"
|
|
],
|
|
disableWorkflow: [
|
|
"PUT /repos/{owner}/{repo}/actions/workflows/{workflow_id}/disable"
|
|
],
|
|
downloadArtifact: [
|
|
"GET /repos/{owner}/{repo}/actions/artifacts/{artifact_id}/{archive_format}"
|
|
],
|
|
downloadJobLogsForWorkflowRun: [
|
|
"GET /repos/{owner}/{repo}/actions/jobs/{job_id}/logs"
|
|
],
|
|
downloadWorkflowRunAttemptLogs: [
|
|
"GET /repos/{owner}/{repo}/actions/runs/{run_id}/attempts/{attempt_number}/logs"
|
|
],
|
|
downloadWorkflowRunLogs: [
|
|
"GET /repos/{owner}/{repo}/actions/runs/{run_id}/logs"
|
|
],
|
|
enableSelectedRepositoryGithubActionsOrganization: [
|
|
"PUT /orgs/{org}/actions/permissions/repositories/{repository_id}"
|
|
],
|
|
enableWorkflow: [
|
|
"PUT /repos/{owner}/{repo}/actions/workflows/{workflow_id}/enable"
|
|
],
|
|
generateRunnerJitconfigForOrg: [
|
|
"POST /orgs/{org}/actions/runners/generate-jitconfig"
|
|
],
|
|
generateRunnerJitconfigForRepo: [
|
|
"POST /repos/{owner}/{repo}/actions/runners/generate-jitconfig"
|
|
],
|
|
getActionsCacheList: ["GET /repos/{owner}/{repo}/actions/caches"],
|
|
getActionsCacheUsage: ["GET /repos/{owner}/{repo}/actions/cache/usage"],
|
|
getActionsCacheUsageByRepoForOrg: [
|
|
"GET /orgs/{org}/actions/cache/usage-by-repository"
|
|
],
|
|
getActionsCacheUsageForOrg: ["GET /orgs/{org}/actions/cache/usage"],
|
|
getAllowedActionsOrganization: [
|
|
"GET /orgs/{org}/actions/permissions/selected-actions"
|
|
],
|
|
getAllowedActionsRepository: [
|
|
"GET /repos/{owner}/{repo}/actions/permissions/selected-actions"
|
|
],
|
|
getArtifact: ["GET /repos/{owner}/{repo}/actions/artifacts/{artifact_id}"],
|
|
getEnvironmentPublicKey: [
|
|
"GET /repositories/{repository_id}/environments/{environment_name}/secrets/public-key"
|
|
],
|
|
getEnvironmentSecret: [
|
|
"GET /repositories/{repository_id}/environments/{environment_name}/secrets/{secret_name}"
|
|
],
|
|
getEnvironmentVariable: [
|
|
"GET /repositories/{repository_id}/environments/{environment_name}/variables/{name}"
|
|
],
|
|
getGithubActionsDefaultWorkflowPermissionsOrganization: [
|
|
"GET /orgs/{org}/actions/permissions/workflow"
|
|
],
|
|
getGithubActionsDefaultWorkflowPermissionsRepository: [
|
|
"GET /repos/{owner}/{repo}/actions/permissions/workflow"
|
|
],
|
|
getGithubActionsPermissionsOrganization: [
|
|
"GET /orgs/{org}/actions/permissions"
|
|
],
|
|
getGithubActionsPermissionsRepository: [
|
|
"GET /repos/{owner}/{repo}/actions/permissions"
|
|
],
|
|
getJobForWorkflowRun: ["GET /repos/{owner}/{repo}/actions/jobs/{job_id}"],
|
|
getOrgPublicKey: ["GET /orgs/{org}/actions/secrets/public-key"],
|
|
getOrgSecret: ["GET /orgs/{org}/actions/secrets/{secret_name}"],
|
|
getOrgVariable: ["GET /orgs/{org}/actions/variables/{name}"],
|
|
getPendingDeploymentsForRun: [
|
|
"GET /repos/{owner}/{repo}/actions/runs/{run_id}/pending_deployments"
|
|
],
|
|
getRepoPermissions: [
|
|
"GET /repos/{owner}/{repo}/actions/permissions",
|
|
{},
|
|
{ renamed: ["actions", "getGithubActionsPermissionsRepository"] }
|
|
],
|
|
getRepoPublicKey: ["GET /repos/{owner}/{repo}/actions/secrets/public-key"],
|
|
getRepoRequiredWorkflow: [
|
|
"GET /repos/{org}/{repo}/actions/required_workflows/{required_workflow_id_for_repo}"
|
|
],
|
|
getRepoRequiredWorkflowUsage: [
|
|
"GET /repos/{org}/{repo}/actions/required_workflows/{required_workflow_id_for_repo}/timing"
|
|
],
|
|
getRepoSecret: ["GET /repos/{owner}/{repo}/actions/secrets/{secret_name}"],
|
|
getRepoVariable: ["GET /repos/{owner}/{repo}/actions/variables/{name}"],
|
|
getRequiredWorkflow: [
|
|
"GET /orgs/{org}/actions/required_workflows/{required_workflow_id}"
|
|
],
|
|
getReviewsForRun: [
|
|
"GET /repos/{owner}/{repo}/actions/runs/{run_id}/approvals"
|
|
],
|
|
getSelfHostedRunnerForOrg: ["GET /orgs/{org}/actions/runners/{runner_id}"],
|
|
getSelfHostedRunnerForRepo: [
|
|
"GET /repos/{owner}/{repo}/actions/runners/{runner_id}"
|
|
],
|
|
getWorkflow: ["GET /repos/{owner}/{repo}/actions/workflows/{workflow_id}"],
|
|
getWorkflowAccessToRepository: [
|
|
"GET /repos/{owner}/{repo}/actions/permissions/access"
|
|
],
|
|
getWorkflowRun: ["GET /repos/{owner}/{repo}/actions/runs/{run_id}"],
|
|
getWorkflowRunAttempt: [
|
|
"GET /repos/{owner}/{repo}/actions/runs/{run_id}/attempts/{attempt_number}"
|
|
],
|
|
getWorkflowRunUsage: [
|
|
"GET /repos/{owner}/{repo}/actions/runs/{run_id}/timing"
|
|
],
|
|
getWorkflowUsage: [
|
|
"GET /repos/{owner}/{repo}/actions/workflows/{workflow_id}/timing"
|
|
],
|
|
listArtifactsForRepo: ["GET /repos/{owner}/{repo}/actions/artifacts"],
|
|
listEnvironmentSecrets: [
|
|
"GET /repositories/{repository_id}/environments/{environment_name}/secrets"
|
|
],
|
|
listEnvironmentVariables: [
|
|
"GET /repositories/{repository_id}/environments/{environment_name}/variables"
|
|
],
|
|
listJobsForWorkflowRun: [
|
|
"GET /repos/{owner}/{repo}/actions/runs/{run_id}/jobs"
|
|
],
|
|
listJobsForWorkflowRunAttempt: [
|
|
"GET /repos/{owner}/{repo}/actions/runs/{run_id}/attempts/{attempt_number}/jobs"
|
|
],
|
|
listLabelsForSelfHostedRunnerForOrg: [
|
|
"GET /orgs/{org}/actions/runners/{runner_id}/labels"
|
|
],
|
|
listLabelsForSelfHostedRunnerForRepo: [
|
|
"GET /repos/{owner}/{repo}/actions/runners/{runner_id}/labels"
|
|
],
|
|
listOrgSecrets: ["GET /orgs/{org}/actions/secrets"],
|
|
listOrgVariables: ["GET /orgs/{org}/actions/variables"],
|
|
listRepoOrganizationSecrets: [
|
|
"GET /repos/{owner}/{repo}/actions/organization-secrets"
|
|
],
|
|
listRepoOrganizationVariables: [
|
|
"GET /repos/{owner}/{repo}/actions/organization-variables"
|
|
],
|
|
listRepoRequiredWorkflows: [
|
|
"GET /repos/{org}/{repo}/actions/required_workflows"
|
|
],
|
|
listRepoSecrets: ["GET /repos/{owner}/{repo}/actions/secrets"],
|
|
listRepoVariables: ["GET /repos/{owner}/{repo}/actions/variables"],
|
|
listRepoWorkflows: ["GET /repos/{owner}/{repo}/actions/workflows"],
|
|
listRequiredWorkflowRuns: [
|
|
"GET /repos/{owner}/{repo}/actions/required_workflows/{required_workflow_id_for_repo}/runs"
|
|
],
|
|
listRequiredWorkflows: ["GET /orgs/{org}/actions/required_workflows"],
|
|
listRunnerApplicationsForOrg: ["GET /orgs/{org}/actions/runners/downloads"],
|
|
listRunnerApplicationsForRepo: [
|
|
"GET /repos/{owner}/{repo}/actions/runners/downloads"
|
|
],
|
|
listSelectedReposForOrgSecret: [
|
|
"GET /orgs/{org}/actions/secrets/{secret_name}/repositories"
|
|
],
|
|
listSelectedReposForOrgVariable: [
|
|
"GET /orgs/{org}/actions/variables/{name}/repositories"
|
|
],
|
|
listSelectedRepositoriesEnabledGithubActionsOrganization: [
|
|
"GET /orgs/{org}/actions/permissions/repositories"
|
|
],
|
|
listSelectedRepositoriesRequiredWorkflow: [
|
|
"GET /orgs/{org}/actions/required_workflows/{required_workflow_id}/repositories"
|
|
],
|
|
listSelfHostedRunnersForOrg: ["GET /orgs/{org}/actions/runners"],
|
|
listSelfHostedRunnersForRepo: ["GET /repos/{owner}/{repo}/actions/runners"],
|
|
listWorkflowRunArtifacts: [
|
|
"GET /repos/{owner}/{repo}/actions/runs/{run_id}/artifacts"
|
|
],
|
|
listWorkflowRuns: [
|
|
"GET /repos/{owner}/{repo}/actions/workflows/{workflow_id}/runs"
|
|
],
|
|
listWorkflowRunsForRepo: ["GET /repos/{owner}/{repo}/actions/runs"],
|
|
reRunJobForWorkflowRun: [
|
|
"POST /repos/{owner}/{repo}/actions/jobs/{job_id}/rerun"
|
|
],
|
|
reRunWorkflow: ["POST /repos/{owner}/{repo}/actions/runs/{run_id}/rerun"],
|
|
reRunWorkflowFailedJobs: [
|
|
"POST /repos/{owner}/{repo}/actions/runs/{run_id}/rerun-failed-jobs"
|
|
],
|
|
removeAllCustomLabelsFromSelfHostedRunnerForOrg: [
|
|
"DELETE /orgs/{org}/actions/runners/{runner_id}/labels"
|
|
],
|
|
removeAllCustomLabelsFromSelfHostedRunnerForRepo: [
|
|
"DELETE /repos/{owner}/{repo}/actions/runners/{runner_id}/labels"
|
|
],
|
|
removeCustomLabelFromSelfHostedRunnerForOrg: [
|
|
"DELETE /orgs/{org}/actions/runners/{runner_id}/labels/{name}"
|
|
],
|
|
removeCustomLabelFromSelfHostedRunnerForRepo: [
|
|
"DELETE /repos/{owner}/{repo}/actions/runners/{runner_id}/labels/{name}"
|
|
],
|
|
removeSelectedRepoFromOrgSecret: [
|
|
"DELETE /orgs/{org}/actions/secrets/{secret_name}/repositories/{repository_id}"
|
|
],
|
|
removeSelectedRepoFromOrgVariable: [
|
|
"DELETE /orgs/{org}/actions/variables/{name}/repositories/{repository_id}"
|
|
],
|
|
removeSelectedRepoFromRequiredWorkflow: [
|
|
"DELETE /orgs/{org}/actions/required_workflows/{required_workflow_id}/repositories/{repository_id}"
|
|
],
|
|
reviewCustomGatesForRun: [
|
|
"POST /repos/{owner}/{repo}/actions/runs/{run_id}/deployment_protection_rule"
|
|
],
|
|
reviewPendingDeploymentsForRun: [
|
|
"POST /repos/{owner}/{repo}/actions/runs/{run_id}/pending_deployments"
|
|
],
|
|
setAllowedActionsOrganization: [
|
|
"PUT /orgs/{org}/actions/permissions/selected-actions"
|
|
],
|
|
setAllowedActionsRepository: [
|
|
"PUT /repos/{owner}/{repo}/actions/permissions/selected-actions"
|
|
],
|
|
setCustomLabelsForSelfHostedRunnerForOrg: [
|
|
"PUT /orgs/{org}/actions/runners/{runner_id}/labels"
|
|
],
|
|
setCustomLabelsForSelfHostedRunnerForRepo: [
|
|
"PUT /repos/{owner}/{repo}/actions/runners/{runner_id}/labels"
|
|
],
|
|
setGithubActionsDefaultWorkflowPermissionsOrganization: [
|
|
"PUT /orgs/{org}/actions/permissions/workflow"
|
|
],
|
|
setGithubActionsDefaultWorkflowPermissionsRepository: [
|
|
"PUT /repos/{owner}/{repo}/actions/permissions/workflow"
|
|
],
|
|
setGithubActionsPermissionsOrganization: [
|
|
"PUT /orgs/{org}/actions/permissions"
|
|
],
|
|
setGithubActionsPermissionsRepository: [
|
|
"PUT /repos/{owner}/{repo}/actions/permissions"
|
|
],
|
|
setSelectedReposForOrgSecret: [
|
|
"PUT /orgs/{org}/actions/secrets/{secret_name}/repositories"
|
|
],
|
|
setSelectedReposForOrgVariable: [
|
|
"PUT /orgs/{org}/actions/variables/{name}/repositories"
|
|
],
|
|
setSelectedReposToRequiredWorkflow: [
|
|
"PUT /orgs/{org}/actions/required_workflows/{required_workflow_id}/repositories"
|
|
],
|
|
setSelectedRepositoriesEnabledGithubActionsOrganization: [
|
|
"PUT /orgs/{org}/actions/permissions/repositories"
|
|
],
|
|
setWorkflowAccessToRepository: [
|
|
"PUT /repos/{owner}/{repo}/actions/permissions/access"
|
|
],
|
|
updateEnvironmentVariable: [
|
|
"PATCH /repositories/{repository_id}/environments/{environment_name}/variables/{name}"
|
|
],
|
|
updateOrgVariable: ["PATCH /orgs/{org}/actions/variables/{name}"],
|
|
updateRepoVariable: [
|
|
"PATCH /repos/{owner}/{repo}/actions/variables/{name}"
|
|
],
|
|
updateRequiredWorkflow: [
|
|
"PATCH /orgs/{org}/actions/required_workflows/{required_workflow_id}"
|
|
]
|
|
},
|
|
activity: {
|
|
checkRepoIsStarredByAuthenticatedUser: ["GET /user/starred/{owner}/{repo}"],
|
|
deleteRepoSubscription: ["DELETE /repos/{owner}/{repo}/subscription"],
|
|
deleteThreadSubscription: [
|
|
"DELETE /notifications/threads/{thread_id}/subscription"
|
|
],
|
|
getFeeds: ["GET /feeds"],
|
|
getRepoSubscription: ["GET /repos/{owner}/{repo}/subscription"],
|
|
getThread: ["GET /notifications/threads/{thread_id}"],
|
|
getThreadSubscriptionForAuthenticatedUser: [
|
|
"GET /notifications/threads/{thread_id}/subscription"
|
|
],
|
|
listEventsForAuthenticatedUser: ["GET /users/{username}/events"],
|
|
listNotificationsForAuthenticatedUser: ["GET /notifications"],
|
|
listOrgEventsForAuthenticatedUser: [
|
|
"GET /users/{username}/events/orgs/{org}"
|
|
],
|
|
listPublicEvents: ["GET /events"],
|
|
listPublicEventsForRepoNetwork: ["GET /networks/{owner}/{repo}/events"],
|
|
listPublicEventsForUser: ["GET /users/{username}/events/public"],
|
|
listPublicOrgEvents: ["GET /orgs/{org}/events"],
|
|
listReceivedEventsForUser: ["GET /users/{username}/received_events"],
|
|
listReceivedPublicEventsForUser: [
|
|
"GET /users/{username}/received_events/public"
|
|
],
|
|
listRepoEvents: ["GET /repos/{owner}/{repo}/events"],
|
|
listRepoNotificationsForAuthenticatedUser: [
|
|
"GET /repos/{owner}/{repo}/notifications"
|
|
],
|
|
listReposStarredByAuthenticatedUser: ["GET /user/starred"],
|
|
listReposStarredByUser: ["GET /users/{username}/starred"],
|
|
listReposWatchedByUser: ["GET /users/{username}/subscriptions"],
|
|
listStargazersForRepo: ["GET /repos/{owner}/{repo}/stargazers"],
|
|
listWatchedReposForAuthenticatedUser: ["GET /user/subscriptions"],
|
|
listWatchersForRepo: ["GET /repos/{owner}/{repo}/subscribers"],
|
|
markNotificationsAsRead: ["PUT /notifications"],
|
|
markRepoNotificationsAsRead: ["PUT /repos/{owner}/{repo}/notifications"],
|
|
markThreadAsRead: ["PATCH /notifications/threads/{thread_id}"],
|
|
setRepoSubscription: ["PUT /repos/{owner}/{repo}/subscription"],
|
|
setThreadSubscription: [
|
|
"PUT /notifications/threads/{thread_id}/subscription"
|
|
],
|
|
starRepoForAuthenticatedUser: ["PUT /user/starred/{owner}/{repo}"],
|
|
unstarRepoForAuthenticatedUser: ["DELETE /user/starred/{owner}/{repo}"]
|
|
},
|
|
apps: {
|
|
addRepoToInstallation: [
|
|
"PUT /user/installations/{installation_id}/repositories/{repository_id}",
|
|
{},
|
|
{ renamed: ["apps", "addRepoToInstallationForAuthenticatedUser"] }
|
|
],
|
|
addRepoToInstallationForAuthenticatedUser: [
|
|
"PUT /user/installations/{installation_id}/repositories/{repository_id}"
|
|
],
|
|
checkToken: ["POST /applications/{client_id}/token"],
|
|
createFromManifest: ["POST /app-manifests/{code}/conversions"],
|
|
createInstallationAccessToken: [
|
|
"POST /app/installations/{installation_id}/access_tokens"
|
|
],
|
|
deleteAuthorization: ["DELETE /applications/{client_id}/grant"],
|
|
deleteInstallation: ["DELETE /app/installations/{installation_id}"],
|
|
deleteToken: ["DELETE /applications/{client_id}/token"],
|
|
getAuthenticated: ["GET /app"],
|
|
getBySlug: ["GET /apps/{app_slug}"],
|
|
getInstallation: ["GET /app/installations/{installation_id}"],
|
|
getOrgInstallation: ["GET /orgs/{org}/installation"],
|
|
getRepoInstallation: ["GET /repos/{owner}/{repo}/installation"],
|
|
getSubscriptionPlanForAccount: [
|
|
"GET /marketplace_listing/accounts/{account_id}"
|
|
],
|
|
getSubscriptionPlanForAccountStubbed: [
|
|
"GET /marketplace_listing/stubbed/accounts/{account_id}"
|
|
],
|
|
getUserInstallation: ["GET /users/{username}/installation"],
|
|
getWebhookConfigForApp: ["GET /app/hook/config"],
|
|
getWebhookDelivery: ["GET /app/hook/deliveries/{delivery_id}"],
|
|
listAccountsForPlan: ["GET /marketplace_listing/plans/{plan_id}/accounts"],
|
|
listAccountsForPlanStubbed: [
|
|
"GET /marketplace_listing/stubbed/plans/{plan_id}/accounts"
|
|
],
|
|
listInstallationReposForAuthenticatedUser: [
|
|
"GET /user/installations/{installation_id}/repositories"
|
|
],
|
|
listInstallationRequestsForAuthenticatedApp: [
|
|
"GET /app/installation-requests"
|
|
],
|
|
listInstallations: ["GET /app/installations"],
|
|
listInstallationsForAuthenticatedUser: ["GET /user/installations"],
|
|
listPlans: ["GET /marketplace_listing/plans"],
|
|
listPlansStubbed: ["GET /marketplace_listing/stubbed/plans"],
|
|
listReposAccessibleToInstallation: ["GET /installation/repositories"],
|
|
listSubscriptionsForAuthenticatedUser: ["GET /user/marketplace_purchases"],
|
|
listSubscriptionsForAuthenticatedUserStubbed: [
|
|
"GET /user/marketplace_purchases/stubbed"
|
|
],
|
|
listWebhookDeliveries: ["GET /app/hook/deliveries"],
|
|
redeliverWebhookDelivery: [
|
|
"POST /app/hook/deliveries/{delivery_id}/attempts"
|
|
],
|
|
removeRepoFromInstallation: [
|
|
"DELETE /user/installations/{installation_id}/repositories/{repository_id}",
|
|
{},
|
|
{ renamed: ["apps", "removeRepoFromInstallationForAuthenticatedUser"] }
|
|
],
|
|
removeRepoFromInstallationForAuthenticatedUser: [
|
|
"DELETE /user/installations/{installation_id}/repositories/{repository_id}"
|
|
],
|
|
resetToken: ["PATCH /applications/{client_id}/token"],
|
|
revokeInstallationAccessToken: ["DELETE /installation/token"],
|
|
scopeToken: ["POST /applications/{client_id}/token/scoped"],
|
|
suspendInstallation: ["PUT /app/installations/{installation_id}/suspended"],
|
|
unsuspendInstallation: [
|
|
"DELETE /app/installations/{installation_id}/suspended"
|
|
],
|
|
updateWebhookConfigForApp: ["PATCH /app/hook/config"]
|
|
},
|
|
billing: {
|
|
getGithubActionsBillingOrg: ["GET /orgs/{org}/settings/billing/actions"],
|
|
getGithubActionsBillingUser: [
|
|
"GET /users/{username}/settings/billing/actions"
|
|
],
|
|
getGithubPackagesBillingOrg: ["GET /orgs/{org}/settings/billing/packages"],
|
|
getGithubPackagesBillingUser: [
|
|
"GET /users/{username}/settings/billing/packages"
|
|
],
|
|
getSharedStorageBillingOrg: [
|
|
"GET /orgs/{org}/settings/billing/shared-storage"
|
|
],
|
|
getSharedStorageBillingUser: [
|
|
"GET /users/{username}/settings/billing/shared-storage"
|
|
]
|
|
},
|
|
checks: {
|
|
create: ["POST /repos/{owner}/{repo}/check-runs"],
|
|
createSuite: ["POST /repos/{owner}/{repo}/check-suites"],
|
|
get: ["GET /repos/{owner}/{repo}/check-runs/{check_run_id}"],
|
|
getSuite: ["GET /repos/{owner}/{repo}/check-suites/{check_suite_id}"],
|
|
listAnnotations: [
|
|
"GET /repos/{owner}/{repo}/check-runs/{check_run_id}/annotations"
|
|
],
|
|
listForRef: ["GET /repos/{owner}/{repo}/commits/{ref}/check-runs"],
|
|
listForSuite: [
|
|
"GET /repos/{owner}/{repo}/check-suites/{check_suite_id}/check-runs"
|
|
],
|
|
listSuitesForRef: ["GET /repos/{owner}/{repo}/commits/{ref}/check-suites"],
|
|
rerequestRun: [
|
|
"POST /repos/{owner}/{repo}/check-runs/{check_run_id}/rerequest"
|
|
],
|
|
rerequestSuite: [
|
|
"POST /repos/{owner}/{repo}/check-suites/{check_suite_id}/rerequest"
|
|
],
|
|
setSuitesPreferences: [
|
|
"PATCH /repos/{owner}/{repo}/check-suites/preferences"
|
|
],
|
|
update: ["PATCH /repos/{owner}/{repo}/check-runs/{check_run_id}"]
|
|
},
|
|
codeScanning: {
|
|
deleteAnalysis: [
|
|
"DELETE /repos/{owner}/{repo}/code-scanning/analyses/{analysis_id}{?confirm_delete}"
|
|
],
|
|
getAlert: [
|
|
"GET /repos/{owner}/{repo}/code-scanning/alerts/{alert_number}",
|
|
{},
|
|
{ renamedParameters: { alert_id: "alert_number" } }
|
|
],
|
|
getAnalysis: [
|
|
"GET /repos/{owner}/{repo}/code-scanning/analyses/{analysis_id}"
|
|
],
|
|
getCodeqlDatabase: [
|
|
"GET /repos/{owner}/{repo}/code-scanning/codeql/databases/{language}"
|
|
],
|
|
getDefaultSetup: ["GET /repos/{owner}/{repo}/code-scanning/default-setup"],
|
|
getSarif: ["GET /repos/{owner}/{repo}/code-scanning/sarifs/{sarif_id}"],
|
|
listAlertInstances: [
|
|
"GET /repos/{owner}/{repo}/code-scanning/alerts/{alert_number}/instances"
|
|
],
|
|
listAlertsForOrg: ["GET /orgs/{org}/code-scanning/alerts"],
|
|
listAlertsForRepo: ["GET /repos/{owner}/{repo}/code-scanning/alerts"],
|
|
listAlertsInstances: [
|
|
"GET /repos/{owner}/{repo}/code-scanning/alerts/{alert_number}/instances",
|
|
{},
|
|
{ renamed: ["codeScanning", "listAlertInstances"] }
|
|
],
|
|
listCodeqlDatabases: [
|
|
"GET /repos/{owner}/{repo}/code-scanning/codeql/databases"
|
|
],
|
|
listRecentAnalyses: ["GET /repos/{owner}/{repo}/code-scanning/analyses"],
|
|
updateAlert: [
|
|
"PATCH /repos/{owner}/{repo}/code-scanning/alerts/{alert_number}"
|
|
],
|
|
updateDefaultSetup: [
|
|
"PATCH /repos/{owner}/{repo}/code-scanning/default-setup"
|
|
],
|
|
uploadSarif: ["POST /repos/{owner}/{repo}/code-scanning/sarifs"]
|
|
},
|
|
codesOfConduct: {
|
|
getAllCodesOfConduct: ["GET /codes_of_conduct"],
|
|
getConductCode: ["GET /codes_of_conduct/{key}"]
|
|
},
|
|
codespaces: {
|
|
addRepositoryForSecretForAuthenticatedUser: [
|
|
"PUT /user/codespaces/secrets/{secret_name}/repositories/{repository_id}"
|
|
],
|
|
addSelectedRepoToOrgSecret: [
|
|
"PUT /orgs/{org}/codespaces/secrets/{secret_name}/repositories/{repository_id}"
|
|
],
|
|
codespaceMachinesForAuthenticatedUser: [
|
|
"GET /user/codespaces/{codespace_name}/machines"
|
|
],
|
|
createForAuthenticatedUser: ["POST /user/codespaces"],
|
|
createOrUpdateOrgSecret: [
|
|
"PUT /orgs/{org}/codespaces/secrets/{secret_name}"
|
|
],
|
|
createOrUpdateRepoSecret: [
|
|
"PUT /repos/{owner}/{repo}/codespaces/secrets/{secret_name}"
|
|
],
|
|
createOrUpdateSecretForAuthenticatedUser: [
|
|
"PUT /user/codespaces/secrets/{secret_name}"
|
|
],
|
|
createWithPrForAuthenticatedUser: [
|
|
"POST /repos/{owner}/{repo}/pulls/{pull_number}/codespaces"
|
|
],
|
|
createWithRepoForAuthenticatedUser: [
|
|
"POST /repos/{owner}/{repo}/codespaces"
|
|
],
|
|
deleteCodespacesBillingUsers: [
|
|
"DELETE /orgs/{org}/codespaces/billing/selected_users"
|
|
],
|
|
deleteForAuthenticatedUser: ["DELETE /user/codespaces/{codespace_name}"],
|
|
deleteFromOrganization: [
|
|
"DELETE /orgs/{org}/members/{username}/codespaces/{codespace_name}"
|
|
],
|
|
deleteOrgSecret: ["DELETE /orgs/{org}/codespaces/secrets/{secret_name}"],
|
|
deleteRepoSecret: [
|
|
"DELETE /repos/{owner}/{repo}/codespaces/secrets/{secret_name}"
|
|
],
|
|
deleteSecretForAuthenticatedUser: [
|
|
"DELETE /user/codespaces/secrets/{secret_name}"
|
|
],
|
|
exportForAuthenticatedUser: [
|
|
"POST /user/codespaces/{codespace_name}/exports"
|
|
],
|
|
getCodespacesForUserInOrg: [
|
|
"GET /orgs/{org}/members/{username}/codespaces"
|
|
],
|
|
getExportDetailsForAuthenticatedUser: [
|
|
"GET /user/codespaces/{codespace_name}/exports/{export_id}"
|
|
],
|
|
getForAuthenticatedUser: ["GET /user/codespaces/{codespace_name}"],
|
|
getOrgPublicKey: ["GET /orgs/{org}/codespaces/secrets/public-key"],
|
|
getOrgSecret: ["GET /orgs/{org}/codespaces/secrets/{secret_name}"],
|
|
getPublicKeyForAuthenticatedUser: [
|
|
"GET /user/codespaces/secrets/public-key"
|
|
],
|
|
getRepoPublicKey: [
|
|
"GET /repos/{owner}/{repo}/codespaces/secrets/public-key"
|
|
],
|
|
getRepoSecret: [
|
|
"GET /repos/{owner}/{repo}/codespaces/secrets/{secret_name}"
|
|
],
|
|
getSecretForAuthenticatedUser: [
|
|
"GET /user/codespaces/secrets/{secret_name}"
|
|
],
|
|
listDevcontainersInRepositoryForAuthenticatedUser: [
|
|
"GET /repos/{owner}/{repo}/codespaces/devcontainers"
|
|
],
|
|
listForAuthenticatedUser: ["GET /user/codespaces"],
|
|
listInOrganization: [
|
|
"GET /orgs/{org}/codespaces",
|
|
{},
|
|
{ renamedParameters: { org_id: "org" } }
|
|
],
|
|
listInRepositoryForAuthenticatedUser: [
|
|
"GET /repos/{owner}/{repo}/codespaces"
|
|
],
|
|
listOrgSecrets: ["GET /orgs/{org}/codespaces/secrets"],
|
|
listRepoSecrets: ["GET /repos/{owner}/{repo}/codespaces/secrets"],
|
|
listRepositoriesForSecretForAuthenticatedUser: [
|
|
"GET /user/codespaces/secrets/{secret_name}/repositories"
|
|
],
|
|
listSecretsForAuthenticatedUser: ["GET /user/codespaces/secrets"],
|
|
listSelectedReposForOrgSecret: [
|
|
"GET /orgs/{org}/codespaces/secrets/{secret_name}/repositories"
|
|
],
|
|
preFlightWithRepoForAuthenticatedUser: [
|
|
"GET /repos/{owner}/{repo}/codespaces/new"
|
|
],
|
|
publishForAuthenticatedUser: [
|
|
"POST /user/codespaces/{codespace_name}/publish"
|
|
],
|
|
removeRepositoryForSecretForAuthenticatedUser: [
|
|
"DELETE /user/codespaces/secrets/{secret_name}/repositories/{repository_id}"
|
|
],
|
|
removeSelectedRepoFromOrgSecret: [
|
|
"DELETE /orgs/{org}/codespaces/secrets/{secret_name}/repositories/{repository_id}"
|
|
],
|
|
repoMachinesForAuthenticatedUser: [
|
|
"GET /repos/{owner}/{repo}/codespaces/machines"
|
|
],
|
|
setCodespacesBilling: ["PUT /orgs/{org}/codespaces/billing"],
|
|
setCodespacesBillingUsers: [
|
|
"POST /orgs/{org}/codespaces/billing/selected_users"
|
|
],
|
|
setRepositoriesForSecretForAuthenticatedUser: [
|
|
"PUT /user/codespaces/secrets/{secret_name}/repositories"
|
|
],
|
|
setSelectedReposForOrgSecret: [
|
|
"PUT /orgs/{org}/codespaces/secrets/{secret_name}/repositories"
|
|
],
|
|
startForAuthenticatedUser: ["POST /user/codespaces/{codespace_name}/start"],
|
|
stopForAuthenticatedUser: ["POST /user/codespaces/{codespace_name}/stop"],
|
|
stopInOrganization: [
|
|
"POST /orgs/{org}/members/{username}/codespaces/{codespace_name}/stop"
|
|
],
|
|
updateForAuthenticatedUser: ["PATCH /user/codespaces/{codespace_name}"]
|
|
},
|
|
dependabot: {
|
|
addSelectedRepoToOrgSecret: [
|
|
"PUT /orgs/{org}/dependabot/secrets/{secret_name}/repositories/{repository_id}"
|
|
],
|
|
createOrUpdateOrgSecret: [
|
|
"PUT /orgs/{org}/dependabot/secrets/{secret_name}"
|
|
],
|
|
createOrUpdateRepoSecret: [
|
|
"PUT /repos/{owner}/{repo}/dependabot/secrets/{secret_name}"
|
|
],
|
|
deleteOrgSecret: ["DELETE /orgs/{org}/dependabot/secrets/{secret_name}"],
|
|
deleteRepoSecret: [
|
|
"DELETE /repos/{owner}/{repo}/dependabot/secrets/{secret_name}"
|
|
],
|
|
getAlert: ["GET /repos/{owner}/{repo}/dependabot/alerts/{alert_number}"],
|
|
getOrgPublicKey: ["GET /orgs/{org}/dependabot/secrets/public-key"],
|
|
getOrgSecret: ["GET /orgs/{org}/dependabot/secrets/{secret_name}"],
|
|
getRepoPublicKey: [
|
|
"GET /repos/{owner}/{repo}/dependabot/secrets/public-key"
|
|
],
|
|
getRepoSecret: [
|
|
"GET /repos/{owner}/{repo}/dependabot/secrets/{secret_name}"
|
|
],
|
|
listAlertsForEnterprise: [
|
|
"GET /enterprises/{enterprise}/dependabot/alerts"
|
|
],
|
|
listAlertsForOrg: ["GET /orgs/{org}/dependabot/alerts"],
|
|
listAlertsForRepo: ["GET /repos/{owner}/{repo}/dependabot/alerts"],
|
|
listOrgSecrets: ["GET /orgs/{org}/dependabot/secrets"],
|
|
listRepoSecrets: ["GET /repos/{owner}/{repo}/dependabot/secrets"],
|
|
listSelectedReposForOrgSecret: [
|
|
"GET /orgs/{org}/dependabot/secrets/{secret_name}/repositories"
|
|
],
|
|
removeSelectedRepoFromOrgSecret: [
|
|
"DELETE /orgs/{org}/dependabot/secrets/{secret_name}/repositories/{repository_id}"
|
|
],
|
|
setSelectedReposForOrgSecret: [
|
|
"PUT /orgs/{org}/dependabot/secrets/{secret_name}/repositories"
|
|
],
|
|
updateAlert: [
|
|
"PATCH /repos/{owner}/{repo}/dependabot/alerts/{alert_number}"
|
|
]
|
|
},
|
|
dependencyGraph: {
|
|
createRepositorySnapshot: [
|
|
"POST /repos/{owner}/{repo}/dependency-graph/snapshots"
|
|
],
|
|
diffRange: [
|
|
"GET /repos/{owner}/{repo}/dependency-graph/compare/{basehead}"
|
|
],
|
|
exportSbom: ["GET /repos/{owner}/{repo}/dependency-graph/sbom"]
|
|
},
|
|
emojis: { get: ["GET /emojis"] },
|
|
gists: {
|
|
checkIsStarred: ["GET /gists/{gist_id}/star"],
|
|
create: ["POST /gists"],
|
|
createComment: ["POST /gists/{gist_id}/comments"],
|
|
delete: ["DELETE /gists/{gist_id}"],
|
|
deleteComment: ["DELETE /gists/{gist_id}/comments/{comment_id}"],
|
|
fork: ["POST /gists/{gist_id}/forks"],
|
|
get: ["GET /gists/{gist_id}"],
|
|
getComment: ["GET /gists/{gist_id}/comments/{comment_id}"],
|
|
getRevision: ["GET /gists/{gist_id}/{sha}"],
|
|
list: ["GET /gists"],
|
|
listComments: ["GET /gists/{gist_id}/comments"],
|
|
listCommits: ["GET /gists/{gist_id}/commits"],
|
|
listForUser: ["GET /users/{username}/gists"],
|
|
listForks: ["GET /gists/{gist_id}/forks"],
|
|
listPublic: ["GET /gists/public"],
|
|
listStarred: ["GET /gists/starred"],
|
|
star: ["PUT /gists/{gist_id}/star"],
|
|
unstar: ["DELETE /gists/{gist_id}/star"],
|
|
update: ["PATCH /gists/{gist_id}"],
|
|
updateComment: ["PATCH /gists/{gist_id}/comments/{comment_id}"]
|
|
},
|
|
git: {
|
|
createBlob: ["POST /repos/{owner}/{repo}/git/blobs"],
|
|
createCommit: ["POST /repos/{owner}/{repo}/git/commits"],
|
|
createRef: ["POST /repos/{owner}/{repo}/git/refs"],
|
|
createTag: ["POST /repos/{owner}/{repo}/git/tags"],
|
|
createTree: ["POST /repos/{owner}/{repo}/git/trees"],
|
|
deleteRef: ["DELETE /repos/{owner}/{repo}/git/refs/{ref}"],
|
|
getBlob: ["GET /repos/{owner}/{repo}/git/blobs/{file_sha}"],
|
|
getCommit: ["GET /repos/{owner}/{repo}/git/commits/{commit_sha}"],
|
|
getRef: ["GET /repos/{owner}/{repo}/git/ref/{ref}"],
|
|
getTag: ["GET /repos/{owner}/{repo}/git/tags/{tag_sha}"],
|
|
getTree: ["GET /repos/{owner}/{repo}/git/trees/{tree_sha}"],
|
|
listMatchingRefs: ["GET /repos/{owner}/{repo}/git/matching-refs/{ref}"],
|
|
updateRef: ["PATCH /repos/{owner}/{repo}/git/refs/{ref}"]
|
|
},
|
|
gitignore: {
|
|
getAllTemplates: ["GET /gitignore/templates"],
|
|
getTemplate: ["GET /gitignore/templates/{name}"]
|
|
},
|
|
interactions: {
|
|
getRestrictionsForAuthenticatedUser: ["GET /user/interaction-limits"],
|
|
getRestrictionsForOrg: ["GET /orgs/{org}/interaction-limits"],
|
|
getRestrictionsForRepo: ["GET /repos/{owner}/{repo}/interaction-limits"],
|
|
getRestrictionsForYourPublicRepos: [
|
|
"GET /user/interaction-limits",
|
|
{},
|
|
{ renamed: ["interactions", "getRestrictionsForAuthenticatedUser"] }
|
|
],
|
|
removeRestrictionsForAuthenticatedUser: ["DELETE /user/interaction-limits"],
|
|
removeRestrictionsForOrg: ["DELETE /orgs/{org}/interaction-limits"],
|
|
removeRestrictionsForRepo: [
|
|
"DELETE /repos/{owner}/{repo}/interaction-limits"
|
|
],
|
|
removeRestrictionsForYourPublicRepos: [
|
|
"DELETE /user/interaction-limits",
|
|
{},
|
|
{ renamed: ["interactions", "removeRestrictionsForAuthenticatedUser"] }
|
|
],
|
|
setRestrictionsForAuthenticatedUser: ["PUT /user/interaction-limits"],
|
|
setRestrictionsForOrg: ["PUT /orgs/{org}/interaction-limits"],
|
|
setRestrictionsForRepo: ["PUT /repos/{owner}/{repo}/interaction-limits"],
|
|
setRestrictionsForYourPublicRepos: [
|
|
"PUT /user/interaction-limits",
|
|
{},
|
|
{ renamed: ["interactions", "setRestrictionsForAuthenticatedUser"] }
|
|
]
|
|
},
|
|
issues: {
|
|
addAssignees: [
|
|
"POST /repos/{owner}/{repo}/issues/{issue_number}/assignees"
|
|
],
|
|
addLabels: ["POST /repos/{owner}/{repo}/issues/{issue_number}/labels"],
|
|
checkUserCanBeAssigned: ["GET /repos/{owner}/{repo}/assignees/{assignee}"],
|
|
checkUserCanBeAssignedToIssue: [
|
|
"GET /repos/{owner}/{repo}/issues/{issue_number}/assignees/{assignee}"
|
|
],
|
|
create: ["POST /repos/{owner}/{repo}/issues"],
|
|
createComment: [
|
|
"POST /repos/{owner}/{repo}/issues/{issue_number}/comments"
|
|
],
|
|
createLabel: ["POST /repos/{owner}/{repo}/labels"],
|
|
createMilestone: ["POST /repos/{owner}/{repo}/milestones"],
|
|
deleteComment: [
|
|
"DELETE /repos/{owner}/{repo}/issues/comments/{comment_id}"
|
|
],
|
|
deleteLabel: ["DELETE /repos/{owner}/{repo}/labels/{name}"],
|
|
deleteMilestone: [
|
|
"DELETE /repos/{owner}/{repo}/milestones/{milestone_number}"
|
|
],
|
|
get: ["GET /repos/{owner}/{repo}/issues/{issue_number}"],
|
|
getComment: ["GET /repos/{owner}/{repo}/issues/comments/{comment_id}"],
|
|
getEvent: ["GET /repos/{owner}/{repo}/issues/events/{event_id}"],
|
|
getLabel: ["GET /repos/{owner}/{repo}/labels/{name}"],
|
|
getMilestone: ["GET /repos/{owner}/{repo}/milestones/{milestone_number}"],
|
|
list: ["GET /issues"],
|
|
listAssignees: ["GET /repos/{owner}/{repo}/assignees"],
|
|
listComments: ["GET /repos/{owner}/{repo}/issues/{issue_number}/comments"],
|
|
listCommentsForRepo: ["GET /repos/{owner}/{repo}/issues/comments"],
|
|
listEvents: ["GET /repos/{owner}/{repo}/issues/{issue_number}/events"],
|
|
listEventsForRepo: ["GET /repos/{owner}/{repo}/issues/events"],
|
|
listEventsForTimeline: [
|
|
"GET /repos/{owner}/{repo}/issues/{issue_number}/timeline"
|
|
],
|
|
listForAuthenticatedUser: ["GET /user/issues"],
|
|
listForOrg: ["GET /orgs/{org}/issues"],
|
|
listForRepo: ["GET /repos/{owner}/{repo}/issues"],
|
|
listLabelsForMilestone: [
|
|
"GET /repos/{owner}/{repo}/milestones/{milestone_number}/labels"
|
|
],
|
|
listLabelsForRepo: ["GET /repos/{owner}/{repo}/labels"],
|
|
listLabelsOnIssue: [
|
|
"GET /repos/{owner}/{repo}/issues/{issue_number}/labels"
|
|
],
|
|
listMilestones: ["GET /repos/{owner}/{repo}/milestones"],
|
|
lock: ["PUT /repos/{owner}/{repo}/issues/{issue_number}/lock"],
|
|
removeAllLabels: [
|
|
"DELETE /repos/{owner}/{repo}/issues/{issue_number}/labels"
|
|
],
|
|
removeAssignees: [
|
|
"DELETE /repos/{owner}/{repo}/issues/{issue_number}/assignees"
|
|
],
|
|
removeLabel: [
|
|
"DELETE /repos/{owner}/{repo}/issues/{issue_number}/labels/{name}"
|
|
],
|
|
setLabels: ["PUT /repos/{owner}/{repo}/issues/{issue_number}/labels"],
|
|
unlock: ["DELETE /repos/{owner}/{repo}/issues/{issue_number}/lock"],
|
|
update: ["PATCH /repos/{owner}/{repo}/issues/{issue_number}"],
|
|
updateComment: ["PATCH /repos/{owner}/{repo}/issues/comments/{comment_id}"],
|
|
updateLabel: ["PATCH /repos/{owner}/{repo}/labels/{name}"],
|
|
updateMilestone: [
|
|
"PATCH /repos/{owner}/{repo}/milestones/{milestone_number}"
|
|
]
|
|
},
|
|
licenses: {
|
|
get: ["GET /licenses/{license}"],
|
|
getAllCommonlyUsed: ["GET /licenses"],
|
|
getForRepo: ["GET /repos/{owner}/{repo}/license"]
|
|
},
|
|
markdown: {
|
|
render: ["POST /markdown"],
|
|
renderRaw: [
|
|
"POST /markdown/raw",
|
|
{ headers: { "content-type": "text/plain; charset=utf-8" } }
|
|
]
|
|
},
|
|
meta: {
|
|
get: ["GET /meta"],
|
|
getAllVersions: ["GET /versions"],
|
|
getOctocat: ["GET /octocat"],
|
|
getZen: ["GET /zen"],
|
|
root: ["GET /"]
|
|
},
|
|
migrations: {
|
|
cancelImport: ["DELETE /repos/{owner}/{repo}/import"],
|
|
deleteArchiveForAuthenticatedUser: [
|
|
"DELETE /user/migrations/{migration_id}/archive"
|
|
],
|
|
deleteArchiveForOrg: [
|
|
"DELETE /orgs/{org}/migrations/{migration_id}/archive"
|
|
],
|
|
downloadArchiveForOrg: [
|
|
"GET /orgs/{org}/migrations/{migration_id}/archive"
|
|
],
|
|
getArchiveForAuthenticatedUser: [
|
|
"GET /user/migrations/{migration_id}/archive"
|
|
],
|
|
getCommitAuthors: ["GET /repos/{owner}/{repo}/import/authors"],
|
|
getImportStatus: ["GET /repos/{owner}/{repo}/import"],
|
|
getLargeFiles: ["GET /repos/{owner}/{repo}/import/large_files"],
|
|
getStatusForAuthenticatedUser: ["GET /user/migrations/{migration_id}"],
|
|
getStatusForOrg: ["GET /orgs/{org}/migrations/{migration_id}"],
|
|
listForAuthenticatedUser: ["GET /user/migrations"],
|
|
listForOrg: ["GET /orgs/{org}/migrations"],
|
|
listReposForAuthenticatedUser: [
|
|
"GET /user/migrations/{migration_id}/repositories"
|
|
],
|
|
listReposForOrg: ["GET /orgs/{org}/migrations/{migration_id}/repositories"],
|
|
listReposForUser: [
|
|
"GET /user/migrations/{migration_id}/repositories",
|
|
{},
|
|
{ renamed: ["migrations", "listReposForAuthenticatedUser"] }
|
|
],
|
|
mapCommitAuthor: ["PATCH /repos/{owner}/{repo}/import/authors/{author_id}"],
|
|
setLfsPreference: ["PATCH /repos/{owner}/{repo}/import/lfs"],
|
|
startForAuthenticatedUser: ["POST /user/migrations"],
|
|
startForOrg: ["POST /orgs/{org}/migrations"],
|
|
startImport: ["PUT /repos/{owner}/{repo}/import"],
|
|
unlockRepoForAuthenticatedUser: [
|
|
"DELETE /user/migrations/{migration_id}/repos/{repo_name}/lock"
|
|
],
|
|
unlockRepoForOrg: [
|
|
"DELETE /orgs/{org}/migrations/{migration_id}/repos/{repo_name}/lock"
|
|
],
|
|
updateImport: ["PATCH /repos/{owner}/{repo}/import"]
|
|
},
|
|
orgs: {
|
|
addSecurityManagerTeam: [
|
|
"PUT /orgs/{org}/security-managers/teams/{team_slug}"
|
|
],
|
|
blockUser: ["PUT /orgs/{org}/blocks/{username}"],
|
|
cancelInvitation: ["DELETE /orgs/{org}/invitations/{invitation_id}"],
|
|
checkBlockedUser: ["GET /orgs/{org}/blocks/{username}"],
|
|
checkMembershipForUser: ["GET /orgs/{org}/members/{username}"],
|
|
checkPublicMembershipForUser: ["GET /orgs/{org}/public_members/{username}"],
|
|
convertMemberToOutsideCollaborator: [
|
|
"PUT /orgs/{org}/outside_collaborators/{username}"
|
|
],
|
|
createInvitation: ["POST /orgs/{org}/invitations"],
|
|
createWebhook: ["POST /orgs/{org}/hooks"],
|
|
delete: ["DELETE /orgs/{org}"],
|
|
deleteWebhook: ["DELETE /orgs/{org}/hooks/{hook_id}"],
|
|
enableOrDisableSecurityProductOnAllOrgRepos: [
|
|
"POST /orgs/{org}/{security_product}/{enablement}"
|
|
],
|
|
get: ["GET /orgs/{org}"],
|
|
getMembershipForAuthenticatedUser: ["GET /user/memberships/orgs/{org}"],
|
|
getMembershipForUser: ["GET /orgs/{org}/memberships/{username}"],
|
|
getWebhook: ["GET /orgs/{org}/hooks/{hook_id}"],
|
|
getWebhookConfigForOrg: ["GET /orgs/{org}/hooks/{hook_id}/config"],
|
|
getWebhookDelivery: [
|
|
"GET /orgs/{org}/hooks/{hook_id}/deliveries/{delivery_id}"
|
|
],
|
|
list: ["GET /organizations"],
|
|
listAppInstallations: ["GET /orgs/{org}/installations"],
|
|
listBlockedUsers: ["GET /orgs/{org}/blocks"],
|
|
listFailedInvitations: ["GET /orgs/{org}/failed_invitations"],
|
|
listForAuthenticatedUser: ["GET /user/orgs"],
|
|
listForUser: ["GET /users/{username}/orgs"],
|
|
listInvitationTeams: ["GET /orgs/{org}/invitations/{invitation_id}/teams"],
|
|
listMembers: ["GET /orgs/{org}/members"],
|
|
listMembershipsForAuthenticatedUser: ["GET /user/memberships/orgs"],
|
|
listOutsideCollaborators: ["GET /orgs/{org}/outside_collaborators"],
|
|
listPatGrantRepositories: [
|
|
"GET /organizations/{org}/personal-access-tokens/{pat_id}/repositories"
|
|
],
|
|
listPatGrantRequestRepositories: [
|
|
"GET /organizations/{org}/personal-access-token-requests/{pat_request_id}/repositories"
|
|
],
|
|
listPatGrantRequests: [
|
|
"GET /organizations/{org}/personal-access-token-requests"
|
|
],
|
|
listPatGrants: ["GET /organizations/{org}/personal-access-tokens"],
|
|
listPendingInvitations: ["GET /orgs/{org}/invitations"],
|
|
listPublicMembers: ["GET /orgs/{org}/public_members"],
|
|
listSecurityManagerTeams: ["GET /orgs/{org}/security-managers"],
|
|
listWebhookDeliveries: ["GET /orgs/{org}/hooks/{hook_id}/deliveries"],
|
|
listWebhooks: ["GET /orgs/{org}/hooks"],
|
|
pingWebhook: ["POST /orgs/{org}/hooks/{hook_id}/pings"],
|
|
redeliverWebhookDelivery: [
|
|
"POST /orgs/{org}/hooks/{hook_id}/deliveries/{delivery_id}/attempts"
|
|
],
|
|
removeMember: ["DELETE /orgs/{org}/members/{username}"],
|
|
removeMembershipForUser: ["DELETE /orgs/{org}/memberships/{username}"],
|
|
removeOutsideCollaborator: [
|
|
"DELETE /orgs/{org}/outside_collaborators/{username}"
|
|
],
|
|
removePublicMembershipForAuthenticatedUser: [
|
|
"DELETE /orgs/{org}/public_members/{username}"
|
|
],
|
|
removeSecurityManagerTeam: [
|
|
"DELETE /orgs/{org}/security-managers/teams/{team_slug}"
|
|
],
|
|
reviewPatGrantRequest: [
|
|
"POST /organizations/{org}/personal-access-token-requests/{pat_request_id}"
|
|
],
|
|
reviewPatGrantRequestsInBulk: [
|
|
"POST /organizations/{org}/personal-access-token-requests"
|
|
],
|
|
setMembershipForUser: ["PUT /orgs/{org}/memberships/{username}"],
|
|
setPublicMembershipForAuthenticatedUser: [
|
|
"PUT /orgs/{org}/public_members/{username}"
|
|
],
|
|
unblockUser: ["DELETE /orgs/{org}/blocks/{username}"],
|
|
update: ["PATCH /orgs/{org}"],
|
|
updateMembershipForAuthenticatedUser: [
|
|
"PATCH /user/memberships/orgs/{org}"
|
|
],
|
|
updatePatAccess: [
|
|
"POST /organizations/{org}/personal-access-tokens/{pat_id}"
|
|
],
|
|
updatePatAccesses: ["POST /organizations/{org}/personal-access-tokens"],
|
|
updateWebhook: ["PATCH /orgs/{org}/hooks/{hook_id}"],
|
|
updateWebhookConfigForOrg: ["PATCH /orgs/{org}/hooks/{hook_id}/config"]
|
|
},
|
|
packages: {
|
|
deletePackageForAuthenticatedUser: [
|
|
"DELETE /user/packages/{package_type}/{package_name}"
|
|
],
|
|
deletePackageForOrg: [
|
|
"DELETE /orgs/{org}/packages/{package_type}/{package_name}"
|
|
],
|
|
deletePackageForUser: [
|
|
"DELETE /users/{username}/packages/{package_type}/{package_name}"
|
|
],
|
|
deletePackageVersionForAuthenticatedUser: [
|
|
"DELETE /user/packages/{package_type}/{package_name}/versions/{package_version_id}"
|
|
],
|
|
deletePackageVersionForOrg: [
|
|
"DELETE /orgs/{org}/packages/{package_type}/{package_name}/versions/{package_version_id}"
|
|
],
|
|
deletePackageVersionForUser: [
|
|
"DELETE /users/{username}/packages/{package_type}/{package_name}/versions/{package_version_id}"
|
|
],
|
|
getAllPackageVersionsForAPackageOwnedByAnOrg: [
|
|
"GET /orgs/{org}/packages/{package_type}/{package_name}/versions",
|
|
{},
|
|
{ renamed: ["packages", "getAllPackageVersionsForPackageOwnedByOrg"] }
|
|
],
|
|
getAllPackageVersionsForAPackageOwnedByTheAuthenticatedUser: [
|
|
"GET /user/packages/{package_type}/{package_name}/versions",
|
|
{},
|
|
{
|
|
renamed: [
|
|
"packages",
|
|
"getAllPackageVersionsForPackageOwnedByAuthenticatedUser"
|
|
]
|
|
}
|
|
],
|
|
getAllPackageVersionsForPackageOwnedByAuthenticatedUser: [
|
|
"GET /user/packages/{package_type}/{package_name}/versions"
|
|
],
|
|
getAllPackageVersionsForPackageOwnedByOrg: [
|
|
"GET /orgs/{org}/packages/{package_type}/{package_name}/versions"
|
|
],
|
|
getAllPackageVersionsForPackageOwnedByUser: [
|
|
"GET /users/{username}/packages/{package_type}/{package_name}/versions"
|
|
],
|
|
getPackageForAuthenticatedUser: [
|
|
"GET /user/packages/{package_type}/{package_name}"
|
|
],
|
|
getPackageForOrganization: [
|
|
"GET /orgs/{org}/packages/{package_type}/{package_name}"
|
|
],
|
|
getPackageForUser: [
|
|
"GET /users/{username}/packages/{package_type}/{package_name}"
|
|
],
|
|
getPackageVersionForAuthenticatedUser: [
|
|
"GET /user/packages/{package_type}/{package_name}/versions/{package_version_id}"
|
|
],
|
|
getPackageVersionForOrganization: [
|
|
"GET /orgs/{org}/packages/{package_type}/{package_name}/versions/{package_version_id}"
|
|
],
|
|
getPackageVersionForUser: [
|
|
"GET /users/{username}/packages/{package_type}/{package_name}/versions/{package_version_id}"
|
|
],
|
|
listDockerMigrationConflictingPackagesForAuthenticatedUser: [
|
|
"GET /user/docker/conflicts"
|
|
],
|
|
listDockerMigrationConflictingPackagesForOrganization: [
|
|
"GET /orgs/{org}/docker/conflicts"
|
|
],
|
|
listDockerMigrationConflictingPackagesForUser: [
|
|
"GET /users/{username}/docker/conflicts"
|
|
],
|
|
listPackagesForAuthenticatedUser: ["GET /user/packages"],
|
|
listPackagesForOrganization: ["GET /orgs/{org}/packages"],
|
|
listPackagesForUser: ["GET /users/{username}/packages"],
|
|
restorePackageForAuthenticatedUser: [
|
|
"POST /user/packages/{package_type}/{package_name}/restore{?token}"
|
|
],
|
|
restorePackageForOrg: [
|
|
"POST /orgs/{org}/packages/{package_type}/{package_name}/restore{?token}"
|
|
],
|
|
restorePackageForUser: [
|
|
"POST /users/{username}/packages/{package_type}/{package_name}/restore{?token}"
|
|
],
|
|
restorePackageVersionForAuthenticatedUser: [
|
|
"POST /user/packages/{package_type}/{package_name}/versions/{package_version_id}/restore"
|
|
],
|
|
restorePackageVersionForOrg: [
|
|
"POST /orgs/{org}/packages/{package_type}/{package_name}/versions/{package_version_id}/restore"
|
|
],
|
|
restorePackageVersionForUser: [
|
|
"POST /users/{username}/packages/{package_type}/{package_name}/versions/{package_version_id}/restore"
|
|
]
|
|
},
|
|
projects: {
|
|
addCollaborator: ["PUT /projects/{project_id}/collaborators/{username}"],
|
|
createCard: ["POST /projects/columns/{column_id}/cards"],
|
|
createColumn: ["POST /projects/{project_id}/columns"],
|
|
createForAuthenticatedUser: ["POST /user/projects"],
|
|
createForOrg: ["POST /orgs/{org}/projects"],
|
|
createForRepo: ["POST /repos/{owner}/{repo}/projects"],
|
|
delete: ["DELETE /projects/{project_id}"],
|
|
deleteCard: ["DELETE /projects/columns/cards/{card_id}"],
|
|
deleteColumn: ["DELETE /projects/columns/{column_id}"],
|
|
get: ["GET /projects/{project_id}"],
|
|
getCard: ["GET /projects/columns/cards/{card_id}"],
|
|
getColumn: ["GET /projects/columns/{column_id}"],
|
|
getPermissionForUser: [
|
|
"GET /projects/{project_id}/collaborators/{username}/permission"
|
|
],
|
|
listCards: ["GET /projects/columns/{column_id}/cards"],
|
|
listCollaborators: ["GET /projects/{project_id}/collaborators"],
|
|
listColumns: ["GET /projects/{project_id}/columns"],
|
|
listForOrg: ["GET /orgs/{org}/projects"],
|
|
listForRepo: ["GET /repos/{owner}/{repo}/projects"],
|
|
listForUser: ["GET /users/{username}/projects"],
|
|
moveCard: ["POST /projects/columns/cards/{card_id}/moves"],
|
|
moveColumn: ["POST /projects/columns/{column_id}/moves"],
|
|
removeCollaborator: [
|
|
"DELETE /projects/{project_id}/collaborators/{username}"
|
|
],
|
|
update: ["PATCH /projects/{project_id}"],
|
|
updateCard: ["PATCH /projects/columns/cards/{card_id}"],
|
|
updateColumn: ["PATCH /projects/columns/{column_id}"]
|
|
},
|
|
pulls: {
|
|
checkIfMerged: ["GET /repos/{owner}/{repo}/pulls/{pull_number}/merge"],
|
|
create: ["POST /repos/{owner}/{repo}/pulls"],
|
|
createReplyForReviewComment: [
|
|
"POST /repos/{owner}/{repo}/pulls/{pull_number}/comments/{comment_id}/replies"
|
|
],
|
|
createReview: ["POST /repos/{owner}/{repo}/pulls/{pull_number}/reviews"],
|
|
createReviewComment: [
|
|
"POST /repos/{owner}/{repo}/pulls/{pull_number}/comments"
|
|
],
|
|
deletePendingReview: [
|
|
"DELETE /repos/{owner}/{repo}/pulls/{pull_number}/reviews/{review_id}"
|
|
],
|
|
deleteReviewComment: [
|
|
"DELETE /repos/{owner}/{repo}/pulls/comments/{comment_id}"
|
|
],
|
|
dismissReview: [
|
|
"PUT /repos/{owner}/{repo}/pulls/{pull_number}/reviews/{review_id}/dismissals"
|
|
],
|
|
get: ["GET /repos/{owner}/{repo}/pulls/{pull_number}"],
|
|
getReview: [
|
|
"GET /repos/{owner}/{repo}/pulls/{pull_number}/reviews/{review_id}"
|
|
],
|
|
getReviewComment: ["GET /repos/{owner}/{repo}/pulls/comments/{comment_id}"],
|
|
list: ["GET /repos/{owner}/{repo}/pulls"],
|
|
listCommentsForReview: [
|
|
"GET /repos/{owner}/{repo}/pulls/{pull_number}/reviews/{review_id}/comments"
|
|
],
|
|
listCommits: ["GET /repos/{owner}/{repo}/pulls/{pull_number}/commits"],
|
|
listFiles: ["GET /repos/{owner}/{repo}/pulls/{pull_number}/files"],
|
|
listRequestedReviewers: [
|
|
"GET /repos/{owner}/{repo}/pulls/{pull_number}/requested_reviewers"
|
|
],
|
|
listReviewComments: [
|
|
"GET /repos/{owner}/{repo}/pulls/{pull_number}/comments"
|
|
],
|
|
listReviewCommentsForRepo: ["GET /repos/{owner}/{repo}/pulls/comments"],
|
|
listReviews: ["GET /repos/{owner}/{repo}/pulls/{pull_number}/reviews"],
|
|
merge: ["PUT /repos/{owner}/{repo}/pulls/{pull_number}/merge"],
|
|
removeRequestedReviewers: [
|
|
"DELETE /repos/{owner}/{repo}/pulls/{pull_number}/requested_reviewers"
|
|
],
|
|
requestReviewers: [
|
|
"POST /repos/{owner}/{repo}/pulls/{pull_number}/requested_reviewers"
|
|
],
|
|
submitReview: [
|
|
"POST /repos/{owner}/{repo}/pulls/{pull_number}/reviews/{review_id}/events"
|
|
],
|
|
update: ["PATCH /repos/{owner}/{repo}/pulls/{pull_number}"],
|
|
updateBranch: [
|
|
"PUT /repos/{owner}/{repo}/pulls/{pull_number}/update-branch"
|
|
],
|
|
updateReview: [
|
|
"PUT /repos/{owner}/{repo}/pulls/{pull_number}/reviews/{review_id}"
|
|
],
|
|
updateReviewComment: [
|
|
"PATCH /repos/{owner}/{repo}/pulls/comments/{comment_id}"
|
|
]
|
|
},
|
|
rateLimit: { get: ["GET /rate_limit"] },
|
|
reactions: {
|
|
createForCommitComment: [
|
|
"POST /repos/{owner}/{repo}/comments/{comment_id}/reactions"
|
|
],
|
|
createForIssue: [
|
|
"POST /repos/{owner}/{repo}/issues/{issue_number}/reactions"
|
|
],
|
|
createForIssueComment: [
|
|
"POST /repos/{owner}/{repo}/issues/comments/{comment_id}/reactions"
|
|
],
|
|
createForPullRequestReviewComment: [
|
|
"POST /repos/{owner}/{repo}/pulls/comments/{comment_id}/reactions"
|
|
],
|
|
createForRelease: [
|
|
"POST /repos/{owner}/{repo}/releases/{release_id}/reactions"
|
|
],
|
|
createForTeamDiscussionCommentInOrg: [
|
|
"POST /orgs/{org}/teams/{team_slug}/discussions/{discussion_number}/comments/{comment_number}/reactions"
|
|
],
|
|
createForTeamDiscussionInOrg: [
|
|
"POST /orgs/{org}/teams/{team_slug}/discussions/{discussion_number}/reactions"
|
|
],
|
|
deleteForCommitComment: [
|
|
"DELETE /repos/{owner}/{repo}/comments/{comment_id}/reactions/{reaction_id}"
|
|
],
|
|
deleteForIssue: [
|
|
"DELETE /repos/{owner}/{repo}/issues/{issue_number}/reactions/{reaction_id}"
|
|
],
|
|
deleteForIssueComment: [
|
|
"DELETE /repos/{owner}/{repo}/issues/comments/{comment_id}/reactions/{reaction_id}"
|
|
],
|
|
deleteForPullRequestComment: [
|
|
"DELETE /repos/{owner}/{repo}/pulls/comments/{comment_id}/reactions/{reaction_id}"
|
|
],
|
|
deleteForRelease: [
|
|
"DELETE /repos/{owner}/{repo}/releases/{release_id}/reactions/{reaction_id}"
|
|
],
|
|
deleteForTeamDiscussion: [
|
|
"DELETE /orgs/{org}/teams/{team_slug}/discussions/{discussion_number}/reactions/{reaction_id}"
|
|
],
|
|
deleteForTeamDiscussionComment: [
|
|
"DELETE /orgs/{org}/teams/{team_slug}/discussions/{discussion_number}/comments/{comment_number}/reactions/{reaction_id}"
|
|
],
|
|
listForCommitComment: [
|
|
"GET /repos/{owner}/{repo}/comments/{comment_id}/reactions"
|
|
],
|
|
listForIssue: ["GET /repos/{owner}/{repo}/issues/{issue_number}/reactions"],
|
|
listForIssueComment: [
|
|
"GET /repos/{owner}/{repo}/issues/comments/{comment_id}/reactions"
|
|
],
|
|
listForPullRequestReviewComment: [
|
|
"GET /repos/{owner}/{repo}/pulls/comments/{comment_id}/reactions"
|
|
],
|
|
listForRelease: [
|
|
"GET /repos/{owner}/{repo}/releases/{release_id}/reactions"
|
|
],
|
|
listForTeamDiscussionCommentInOrg: [
|
|
"GET /orgs/{org}/teams/{team_slug}/discussions/{discussion_number}/comments/{comment_number}/reactions"
|
|
],
|
|
listForTeamDiscussionInOrg: [
|
|
"GET /orgs/{org}/teams/{team_slug}/discussions/{discussion_number}/reactions"
|
|
]
|
|
},
|
|
repos: {
|
|
acceptInvitation: [
|
|
"PATCH /user/repository_invitations/{invitation_id}",
|
|
{},
|
|
{ renamed: ["repos", "acceptInvitationForAuthenticatedUser"] }
|
|
],
|
|
acceptInvitationForAuthenticatedUser: [
|
|
"PATCH /user/repository_invitations/{invitation_id}"
|
|
],
|
|
addAppAccessRestrictions: [
|
|
"POST /repos/{owner}/{repo}/branches/{branch}/protection/restrictions/apps",
|
|
{},
|
|
{ mapToData: "apps" }
|
|
],
|
|
addCollaborator: ["PUT /repos/{owner}/{repo}/collaborators/{username}"],
|
|
addStatusCheckContexts: [
|
|
"POST /repos/{owner}/{repo}/branches/{branch}/protection/required_status_checks/contexts",
|
|
{},
|
|
{ mapToData: "contexts" }
|
|
],
|
|
addTeamAccessRestrictions: [
|
|
"POST /repos/{owner}/{repo}/branches/{branch}/protection/restrictions/teams",
|
|
{},
|
|
{ mapToData: "teams" }
|
|
],
|
|
addUserAccessRestrictions: [
|
|
"POST /repos/{owner}/{repo}/branches/{branch}/protection/restrictions/users",
|
|
{},
|
|
{ mapToData: "users" }
|
|
],
|
|
checkCollaborator: ["GET /repos/{owner}/{repo}/collaborators/{username}"],
|
|
checkVulnerabilityAlerts: [
|
|
"GET /repos/{owner}/{repo}/vulnerability-alerts"
|
|
],
|
|
codeownersErrors: ["GET /repos/{owner}/{repo}/codeowners/errors"],
|
|
compareCommits: ["GET /repos/{owner}/{repo}/compare/{base}...{head}"],
|
|
compareCommitsWithBasehead: [
|
|
"GET /repos/{owner}/{repo}/compare/{basehead}"
|
|
],
|
|
createAutolink: ["POST /repos/{owner}/{repo}/autolinks"],
|
|
createCommitComment: [
|
|
"POST /repos/{owner}/{repo}/commits/{commit_sha}/comments"
|
|
],
|
|
createCommitSignatureProtection: [
|
|
"POST /repos/{owner}/{repo}/branches/{branch}/protection/required_signatures"
|
|
],
|
|
createCommitStatus: ["POST /repos/{owner}/{repo}/statuses/{sha}"],
|
|
createDeployKey: ["POST /repos/{owner}/{repo}/keys"],
|
|
createDeployment: ["POST /repos/{owner}/{repo}/deployments"],
|
|
createDeploymentBranchPolicy: [
|
|
"POST /repos/{owner}/{repo}/environments/{environment_name}/deployment-branch-policies"
|
|
],
|
|
createDeploymentProtectionRule: [
|
|
"POST /repos/{owner}/{repo}/environments/{environment_name}/deployment_protection_rules"
|
|
],
|
|
createDeploymentStatus: [
|
|
"POST /repos/{owner}/{repo}/deployments/{deployment_id}/statuses"
|
|
],
|
|
createDispatchEvent: ["POST /repos/{owner}/{repo}/dispatches"],
|
|
createForAuthenticatedUser: ["POST /user/repos"],
|
|
createFork: ["POST /repos/{owner}/{repo}/forks"],
|
|
createInOrg: ["POST /orgs/{org}/repos"],
|
|
createOrUpdateEnvironment: [
|
|
"PUT /repos/{owner}/{repo}/environments/{environment_name}"
|
|
],
|
|
createOrUpdateFileContents: ["PUT /repos/{owner}/{repo}/contents/{path}"],
|
|
createOrgRuleset: ["POST /orgs/{org}/rulesets"],
|
|
createPagesDeployment: ["POST /repos/{owner}/{repo}/pages/deployment"],
|
|
createPagesSite: ["POST /repos/{owner}/{repo}/pages"],
|
|
createRelease: ["POST /repos/{owner}/{repo}/releases"],
|
|
createRepoRuleset: ["POST /repos/{owner}/{repo}/rulesets"],
|
|
createTagProtection: ["POST /repos/{owner}/{repo}/tags/protection"],
|
|
createUsingTemplate: [
|
|
"POST /repos/{template_owner}/{template_repo}/generate"
|
|
],
|
|
createWebhook: ["POST /repos/{owner}/{repo}/hooks"],
|
|
declineInvitation: [
|
|
"DELETE /user/repository_invitations/{invitation_id}",
|
|
{},
|
|
{ renamed: ["repos", "declineInvitationForAuthenticatedUser"] }
|
|
],
|
|
declineInvitationForAuthenticatedUser: [
|
|
"DELETE /user/repository_invitations/{invitation_id}"
|
|
],
|
|
delete: ["DELETE /repos/{owner}/{repo}"],
|
|
deleteAccessRestrictions: [
|
|
"DELETE /repos/{owner}/{repo}/branches/{branch}/protection/restrictions"
|
|
],
|
|
deleteAdminBranchProtection: [
|
|
"DELETE /repos/{owner}/{repo}/branches/{branch}/protection/enforce_admins"
|
|
],
|
|
deleteAnEnvironment: [
|
|
"DELETE /repos/{owner}/{repo}/environments/{environment_name}"
|
|
],
|
|
deleteAutolink: ["DELETE /repos/{owner}/{repo}/autolinks/{autolink_id}"],
|
|
deleteBranchProtection: [
|
|
"DELETE /repos/{owner}/{repo}/branches/{branch}/protection"
|
|
],
|
|
deleteCommitComment: ["DELETE /repos/{owner}/{repo}/comments/{comment_id}"],
|
|
deleteCommitSignatureProtection: [
|
|
"DELETE /repos/{owner}/{repo}/branches/{branch}/protection/required_signatures"
|
|
],
|
|
deleteDeployKey: ["DELETE /repos/{owner}/{repo}/keys/{key_id}"],
|
|
deleteDeployment: [
|
|
"DELETE /repos/{owner}/{repo}/deployments/{deployment_id}"
|
|
],
|
|
deleteDeploymentBranchPolicy: [
|
|
"DELETE /repos/{owner}/{repo}/environments/{environment_name}/deployment-branch-policies/{branch_policy_id}"
|
|
],
|
|
deleteFile: ["DELETE /repos/{owner}/{repo}/contents/{path}"],
|
|
deleteInvitation: [
|
|
"DELETE /repos/{owner}/{repo}/invitations/{invitation_id}"
|
|
],
|
|
deleteOrgRuleset: ["DELETE /orgs/{org}/rulesets/{ruleset_id}"],
|
|
deletePagesSite: ["DELETE /repos/{owner}/{repo}/pages"],
|
|
deletePullRequestReviewProtection: [
|
|
"DELETE /repos/{owner}/{repo}/branches/{branch}/protection/required_pull_request_reviews"
|
|
],
|
|
deleteRelease: ["DELETE /repos/{owner}/{repo}/releases/{release_id}"],
|
|
deleteReleaseAsset: [
|
|
"DELETE /repos/{owner}/{repo}/releases/assets/{asset_id}"
|
|
],
|
|
deleteRepoRuleset: ["DELETE /repos/{owner}/{repo}/rulesets/{ruleset_id}"],
|
|
deleteTagProtection: [
|
|
"DELETE /repos/{owner}/{repo}/tags/protection/{tag_protection_id}"
|
|
],
|
|
deleteWebhook: ["DELETE /repos/{owner}/{repo}/hooks/{hook_id}"],
|
|
disableAutomatedSecurityFixes: [
|
|
"DELETE /repos/{owner}/{repo}/automated-security-fixes"
|
|
],
|
|
disableDeploymentProtectionRule: [
|
|
"DELETE /repos/{owner}/{repo}/environments/{environment_name}/deployment_protection_rules/{protection_rule_id}"
|
|
],
|
|
disableLfsForRepo: ["DELETE /repos/{owner}/{repo}/lfs"],
|
|
disableVulnerabilityAlerts: [
|
|
"DELETE /repos/{owner}/{repo}/vulnerability-alerts"
|
|
],
|
|
downloadArchive: [
|
|
"GET /repos/{owner}/{repo}/zipball/{ref}",
|
|
{},
|
|
{ renamed: ["repos", "downloadZipballArchive"] }
|
|
],
|
|
downloadTarballArchive: ["GET /repos/{owner}/{repo}/tarball/{ref}"],
|
|
downloadZipballArchive: ["GET /repos/{owner}/{repo}/zipball/{ref}"],
|
|
enableAutomatedSecurityFixes: [
|
|
"PUT /repos/{owner}/{repo}/automated-security-fixes"
|
|
],
|
|
enableLfsForRepo: ["PUT /repos/{owner}/{repo}/lfs"],
|
|
enableVulnerabilityAlerts: [
|
|
"PUT /repos/{owner}/{repo}/vulnerability-alerts"
|
|
],
|
|
generateReleaseNotes: [
|
|
"POST /repos/{owner}/{repo}/releases/generate-notes"
|
|
],
|
|
get: ["GET /repos/{owner}/{repo}"],
|
|
getAccessRestrictions: [
|
|
"GET /repos/{owner}/{repo}/branches/{branch}/protection/restrictions"
|
|
],
|
|
getAdminBranchProtection: [
|
|
"GET /repos/{owner}/{repo}/branches/{branch}/protection/enforce_admins"
|
|
],
|
|
getAllDeploymentProtectionRules: [
|
|
"GET /repos/{owner}/{repo}/environments/{environment_name}/deployment_protection_rules"
|
|
],
|
|
getAllEnvironments: ["GET /repos/{owner}/{repo}/environments"],
|
|
getAllStatusCheckContexts: [
|
|
"GET /repos/{owner}/{repo}/branches/{branch}/protection/required_status_checks/contexts"
|
|
],
|
|
getAllTopics: ["GET /repos/{owner}/{repo}/topics"],
|
|
getAppsWithAccessToProtectedBranch: [
|
|
"GET /repos/{owner}/{repo}/branches/{branch}/protection/restrictions/apps"
|
|
],
|
|
getAutolink: ["GET /repos/{owner}/{repo}/autolinks/{autolink_id}"],
|
|
getBranch: ["GET /repos/{owner}/{repo}/branches/{branch}"],
|
|
getBranchProtection: [
|
|
"GET /repos/{owner}/{repo}/branches/{branch}/protection"
|
|
],
|
|
getBranchRules: ["GET /repos/{owner}/{repo}/rules/branches/{branch}"],
|
|
getClones: ["GET /repos/{owner}/{repo}/traffic/clones"],
|
|
getCodeFrequencyStats: ["GET /repos/{owner}/{repo}/stats/code_frequency"],
|
|
getCollaboratorPermissionLevel: [
|
|
"GET /repos/{owner}/{repo}/collaborators/{username}/permission"
|
|
],
|
|
getCombinedStatusForRef: ["GET /repos/{owner}/{repo}/commits/{ref}/status"],
|
|
getCommit: ["GET /repos/{owner}/{repo}/commits/{ref}"],
|
|
getCommitActivityStats: ["GET /repos/{owner}/{repo}/stats/commit_activity"],
|
|
getCommitComment: ["GET /repos/{owner}/{repo}/comments/{comment_id}"],
|
|
getCommitSignatureProtection: [
|
|
"GET /repos/{owner}/{repo}/branches/{branch}/protection/required_signatures"
|
|
],
|
|
getCommunityProfileMetrics: ["GET /repos/{owner}/{repo}/community/profile"],
|
|
getContent: ["GET /repos/{owner}/{repo}/contents/{path}"],
|
|
getContributorsStats: ["GET /repos/{owner}/{repo}/stats/contributors"],
|
|
getCustomDeploymentProtectionRule: [
|
|
"GET /repos/{owner}/{repo}/environments/{environment_name}/deployment_protection_rules/{protection_rule_id}"
|
|
],
|
|
getDeployKey: ["GET /repos/{owner}/{repo}/keys/{key_id}"],
|
|
getDeployment: ["GET /repos/{owner}/{repo}/deployments/{deployment_id}"],
|
|
getDeploymentBranchPolicy: [
|
|
"GET /repos/{owner}/{repo}/environments/{environment_name}/deployment-branch-policies/{branch_policy_id}"
|
|
],
|
|
getDeploymentStatus: [
|
|
"GET /repos/{owner}/{repo}/deployments/{deployment_id}/statuses/{status_id}"
|
|
],
|
|
getEnvironment: [
|
|
"GET /repos/{owner}/{repo}/environments/{environment_name}"
|
|
],
|
|
getLatestPagesBuild: ["GET /repos/{owner}/{repo}/pages/builds/latest"],
|
|
getLatestRelease: ["GET /repos/{owner}/{repo}/releases/latest"],
|
|
getOrgRuleset: ["GET /orgs/{org}/rulesets/{ruleset_id}"],
|
|
getOrgRulesets: ["GET /orgs/{org}/rulesets"],
|
|
getPages: ["GET /repos/{owner}/{repo}/pages"],
|
|
getPagesBuild: ["GET /repos/{owner}/{repo}/pages/builds/{build_id}"],
|
|
getPagesHealthCheck: ["GET /repos/{owner}/{repo}/pages/health"],
|
|
getParticipationStats: ["GET /repos/{owner}/{repo}/stats/participation"],
|
|
getPullRequestReviewProtection: [
|
|
"GET /repos/{owner}/{repo}/branches/{branch}/protection/required_pull_request_reviews"
|
|
],
|
|
getPunchCardStats: ["GET /repos/{owner}/{repo}/stats/punch_card"],
|
|
getReadme: ["GET /repos/{owner}/{repo}/readme"],
|
|
getReadmeInDirectory: ["GET /repos/{owner}/{repo}/readme/{dir}"],
|
|
getRelease: ["GET /repos/{owner}/{repo}/releases/{release_id}"],
|
|
getReleaseAsset: ["GET /repos/{owner}/{repo}/releases/assets/{asset_id}"],
|
|
getReleaseByTag: ["GET /repos/{owner}/{repo}/releases/tags/{tag}"],
|
|
getRepoRuleset: ["GET /repos/{owner}/{repo}/rulesets/{ruleset_id}"],
|
|
getRepoRulesets: ["GET /repos/{owner}/{repo}/rulesets"],
|
|
getStatusChecksProtection: [
|
|
"GET /repos/{owner}/{repo}/branches/{branch}/protection/required_status_checks"
|
|
],
|
|
getTeamsWithAccessToProtectedBranch: [
|
|
"GET /repos/{owner}/{repo}/branches/{branch}/protection/restrictions/teams"
|
|
],
|
|
getTopPaths: ["GET /repos/{owner}/{repo}/traffic/popular/paths"],
|
|
getTopReferrers: ["GET /repos/{owner}/{repo}/traffic/popular/referrers"],
|
|
getUsersWithAccessToProtectedBranch: [
|
|
"GET /repos/{owner}/{repo}/branches/{branch}/protection/restrictions/users"
|
|
],
|
|
getViews: ["GET /repos/{owner}/{repo}/traffic/views"],
|
|
getWebhook: ["GET /repos/{owner}/{repo}/hooks/{hook_id}"],
|
|
getWebhookConfigForRepo: [
|
|
"GET /repos/{owner}/{repo}/hooks/{hook_id}/config"
|
|
],
|
|
getWebhookDelivery: [
|
|
"GET /repos/{owner}/{repo}/hooks/{hook_id}/deliveries/{delivery_id}"
|
|
],
|
|
listAutolinks: ["GET /repos/{owner}/{repo}/autolinks"],
|
|
listBranches: ["GET /repos/{owner}/{repo}/branches"],
|
|
listBranchesForHeadCommit: [
|
|
"GET /repos/{owner}/{repo}/commits/{commit_sha}/branches-where-head"
|
|
],
|
|
listCollaborators: ["GET /repos/{owner}/{repo}/collaborators"],
|
|
listCommentsForCommit: [
|
|
"GET /repos/{owner}/{repo}/commits/{commit_sha}/comments"
|
|
],
|
|
listCommitCommentsForRepo: ["GET /repos/{owner}/{repo}/comments"],
|
|
listCommitStatusesForRef: [
|
|
"GET /repos/{owner}/{repo}/commits/{ref}/statuses"
|
|
],
|
|
listCommits: ["GET /repos/{owner}/{repo}/commits"],
|
|
listContributors: ["GET /repos/{owner}/{repo}/contributors"],
|
|
listCustomDeploymentRuleIntegrations: [
|
|
"GET /repos/{owner}/{repo}/environments/{environment_name}/deployment_protection_rules/apps"
|
|
],
|
|
listDeployKeys: ["GET /repos/{owner}/{repo}/keys"],
|
|
listDeploymentBranchPolicies: [
|
|
"GET /repos/{owner}/{repo}/environments/{environment_name}/deployment-branch-policies"
|
|
],
|
|
listDeploymentStatuses: [
|
|
"GET /repos/{owner}/{repo}/deployments/{deployment_id}/statuses"
|
|
],
|
|
listDeployments: ["GET /repos/{owner}/{repo}/deployments"],
|
|
listForAuthenticatedUser: ["GET /user/repos"],
|
|
listForOrg: ["GET /orgs/{org}/repos"],
|
|
listForUser: ["GET /users/{username}/repos"],
|
|
listForks: ["GET /repos/{owner}/{repo}/forks"],
|
|
listInvitations: ["GET /repos/{owner}/{repo}/invitations"],
|
|
listInvitationsForAuthenticatedUser: ["GET /user/repository_invitations"],
|
|
listLanguages: ["GET /repos/{owner}/{repo}/languages"],
|
|
listPagesBuilds: ["GET /repos/{owner}/{repo}/pages/builds"],
|
|
listPublic: ["GET /repositories"],
|
|
listPullRequestsAssociatedWithCommit: [
|
|
"GET /repos/{owner}/{repo}/commits/{commit_sha}/pulls"
|
|
],
|
|
listReleaseAssets: [
|
|
"GET /repos/{owner}/{repo}/releases/{release_id}/assets"
|
|
],
|
|
listReleases: ["GET /repos/{owner}/{repo}/releases"],
|
|
listTagProtection: ["GET /repos/{owner}/{repo}/tags/protection"],
|
|
listTags: ["GET /repos/{owner}/{repo}/tags"],
|
|
listTeams: ["GET /repos/{owner}/{repo}/teams"],
|
|
listWebhookDeliveries: [
|
|
"GET /repos/{owner}/{repo}/hooks/{hook_id}/deliveries"
|
|
],
|
|
listWebhooks: ["GET /repos/{owner}/{repo}/hooks"],
|
|
merge: ["POST /repos/{owner}/{repo}/merges"],
|
|
mergeUpstream: ["POST /repos/{owner}/{repo}/merge-upstream"],
|
|
pingWebhook: ["POST /repos/{owner}/{repo}/hooks/{hook_id}/pings"],
|
|
redeliverWebhookDelivery: [
|
|
"POST /repos/{owner}/{repo}/hooks/{hook_id}/deliveries/{delivery_id}/attempts"
|
|
],
|
|
removeAppAccessRestrictions: [
|
|
"DELETE /repos/{owner}/{repo}/branches/{branch}/protection/restrictions/apps",
|
|
{},
|
|
{ mapToData: "apps" }
|
|
],
|
|
removeCollaborator: [
|
|
"DELETE /repos/{owner}/{repo}/collaborators/{username}"
|
|
],
|
|
removeStatusCheckContexts: [
|
|
"DELETE /repos/{owner}/{repo}/branches/{branch}/protection/required_status_checks/contexts",
|
|
{},
|
|
{ mapToData: "contexts" }
|
|
],
|
|
removeStatusCheckProtection: [
|
|
"DELETE /repos/{owner}/{repo}/branches/{branch}/protection/required_status_checks"
|
|
],
|
|
removeTeamAccessRestrictions: [
|
|
"DELETE /repos/{owner}/{repo}/branches/{branch}/protection/restrictions/teams",
|
|
{},
|
|
{ mapToData: "teams" }
|
|
],
|
|
removeUserAccessRestrictions: [
|
|
"DELETE /repos/{owner}/{repo}/branches/{branch}/protection/restrictions/users",
|
|
{},
|
|
{ mapToData: "users" }
|
|
],
|
|
renameBranch: ["POST /repos/{owner}/{repo}/branches/{branch}/rename"],
|
|
replaceAllTopics: ["PUT /repos/{owner}/{repo}/topics"],
|
|
requestPagesBuild: ["POST /repos/{owner}/{repo}/pages/builds"],
|
|
setAdminBranchProtection: [
|
|
"POST /repos/{owner}/{repo}/branches/{branch}/protection/enforce_admins"
|
|
],
|
|
setAppAccessRestrictions: [
|
|
"PUT /repos/{owner}/{repo}/branches/{branch}/protection/restrictions/apps",
|
|
{},
|
|
{ mapToData: "apps" }
|
|
],
|
|
setStatusCheckContexts: [
|
|
"PUT /repos/{owner}/{repo}/branches/{branch}/protection/required_status_checks/contexts",
|
|
{},
|
|
{ mapToData: "contexts" }
|
|
],
|
|
setTeamAccessRestrictions: [
|
|
"PUT /repos/{owner}/{repo}/branches/{branch}/protection/restrictions/teams",
|
|
{},
|
|
{ mapToData: "teams" }
|
|
],
|
|
setUserAccessRestrictions: [
|
|
"PUT /repos/{owner}/{repo}/branches/{branch}/protection/restrictions/users",
|
|
{},
|
|
{ mapToData: "users" }
|
|
],
|
|
testPushWebhook: ["POST /repos/{owner}/{repo}/hooks/{hook_id}/tests"],
|
|
transfer: ["POST /repos/{owner}/{repo}/transfer"],
|
|
update: ["PATCH /repos/{owner}/{repo}"],
|
|
updateBranchProtection: [
|
|
"PUT /repos/{owner}/{repo}/branches/{branch}/protection"
|
|
],
|
|
updateCommitComment: ["PATCH /repos/{owner}/{repo}/comments/{comment_id}"],
|
|
updateDeploymentBranchPolicy: [
|
|
"PUT /repos/{owner}/{repo}/environments/{environment_name}/deployment-branch-policies/{branch_policy_id}"
|
|
],
|
|
updateInformationAboutPagesSite: ["PUT /repos/{owner}/{repo}/pages"],
|
|
updateInvitation: [
|
|
"PATCH /repos/{owner}/{repo}/invitations/{invitation_id}"
|
|
],
|
|
updateOrgRuleset: ["PUT /orgs/{org}/rulesets/{ruleset_id}"],
|
|
updatePullRequestReviewProtection: [
|
|
"PATCH /repos/{owner}/{repo}/branches/{branch}/protection/required_pull_request_reviews"
|
|
],
|
|
updateRelease: ["PATCH /repos/{owner}/{repo}/releases/{release_id}"],
|
|
updateReleaseAsset: [
|
|
"PATCH /repos/{owner}/{repo}/releases/assets/{asset_id}"
|
|
],
|
|
updateRepoRuleset: ["PUT /repos/{owner}/{repo}/rulesets/{ruleset_id}"],
|
|
updateStatusCheckPotection: [
|
|
"PATCH /repos/{owner}/{repo}/branches/{branch}/protection/required_status_checks",
|
|
{},
|
|
{ renamed: ["repos", "updateStatusCheckProtection"] }
|
|
],
|
|
updateStatusCheckProtection: [
|
|
"PATCH /repos/{owner}/{repo}/branches/{branch}/protection/required_status_checks"
|
|
],
|
|
updateWebhook: ["PATCH /repos/{owner}/{repo}/hooks/{hook_id}"],
|
|
updateWebhookConfigForRepo: [
|
|
"PATCH /repos/{owner}/{repo}/hooks/{hook_id}/config"
|
|
],
|
|
uploadReleaseAsset: [
|
|
"POST /repos/{owner}/{repo}/releases/{release_id}/assets{?name,label}",
|
|
{ baseUrl: "https://uploads.github.com" }
|
|
]
|
|
},
|
|
search: {
|
|
code: ["GET /search/code"],
|
|
commits: ["GET /search/commits"],
|
|
issuesAndPullRequests: ["GET /search/issues"],
|
|
labels: ["GET /search/labels"],
|
|
repos: ["GET /search/repositories"],
|
|
topics: ["GET /search/topics"],
|
|
users: ["GET /search/users"]
|
|
},
|
|
secretScanning: {
|
|
getAlert: [
|
|
"GET /repos/{owner}/{repo}/secret-scanning/alerts/{alert_number}"
|
|
],
|
|
listAlertsForEnterprise: [
|
|
"GET /enterprises/{enterprise}/secret-scanning/alerts"
|
|
],
|
|
listAlertsForOrg: ["GET /orgs/{org}/secret-scanning/alerts"],
|
|
listAlertsForRepo: ["GET /repos/{owner}/{repo}/secret-scanning/alerts"],
|
|
listLocationsForAlert: [
|
|
"GET /repos/{owner}/{repo}/secret-scanning/alerts/{alert_number}/locations"
|
|
],
|
|
updateAlert: [
|
|
"PATCH /repos/{owner}/{repo}/secret-scanning/alerts/{alert_number}"
|
|
]
|
|
},
|
|
securityAdvisories: {
|
|
createPrivateVulnerabilityReport: [
|
|
"POST /repos/{owner}/{repo}/security-advisories/reports"
|
|
],
|
|
createRepositoryAdvisory: [
|
|
"POST /repos/{owner}/{repo}/security-advisories"
|
|
],
|
|
getRepositoryAdvisory: [
|
|
"GET /repos/{owner}/{repo}/security-advisories/{ghsa_id}"
|
|
],
|
|
listRepositoryAdvisories: ["GET /repos/{owner}/{repo}/security-advisories"],
|
|
updateRepositoryAdvisory: [
|
|
"PATCH /repos/{owner}/{repo}/security-advisories/{ghsa_id}"
|
|
]
|
|
},
|
|
teams: {
|
|
addOrUpdateMembershipForUserInOrg: [
|
|
"PUT /orgs/{org}/teams/{team_slug}/memberships/{username}"
|
|
],
|
|
addOrUpdateProjectPermissionsInOrg: [
|
|
"PUT /orgs/{org}/teams/{team_slug}/projects/{project_id}"
|
|
],
|
|
addOrUpdateRepoPermissionsInOrg: [
|
|
"PUT /orgs/{org}/teams/{team_slug}/repos/{owner}/{repo}"
|
|
],
|
|
checkPermissionsForProjectInOrg: [
|
|
"GET /orgs/{org}/teams/{team_slug}/projects/{project_id}"
|
|
],
|
|
checkPermissionsForRepoInOrg: [
|
|
"GET /orgs/{org}/teams/{team_slug}/repos/{owner}/{repo}"
|
|
],
|
|
create: ["POST /orgs/{org}/teams"],
|
|
createDiscussionCommentInOrg: [
|
|
"POST /orgs/{org}/teams/{team_slug}/discussions/{discussion_number}/comments"
|
|
],
|
|
createDiscussionInOrg: ["POST /orgs/{org}/teams/{team_slug}/discussions"],
|
|
deleteDiscussionCommentInOrg: [
|
|
"DELETE /orgs/{org}/teams/{team_slug}/discussions/{discussion_number}/comments/{comment_number}"
|
|
],
|
|
deleteDiscussionInOrg: [
|
|
"DELETE /orgs/{org}/teams/{team_slug}/discussions/{discussion_number}"
|
|
],
|
|
deleteInOrg: ["DELETE /orgs/{org}/teams/{team_slug}"],
|
|
getByName: ["GET /orgs/{org}/teams/{team_slug}"],
|
|
getDiscussionCommentInOrg: [
|
|
"GET /orgs/{org}/teams/{team_slug}/discussions/{discussion_number}/comments/{comment_number}"
|
|
],
|
|
getDiscussionInOrg: [
|
|
"GET /orgs/{org}/teams/{team_slug}/discussions/{discussion_number}"
|
|
],
|
|
getMembershipForUserInOrg: [
|
|
"GET /orgs/{org}/teams/{team_slug}/memberships/{username}"
|
|
],
|
|
list: ["GET /orgs/{org}/teams"],
|
|
listChildInOrg: ["GET /orgs/{org}/teams/{team_slug}/teams"],
|
|
listDiscussionCommentsInOrg: [
|
|
"GET /orgs/{org}/teams/{team_slug}/discussions/{discussion_number}/comments"
|
|
],
|
|
listDiscussionsInOrg: ["GET /orgs/{org}/teams/{team_slug}/discussions"],
|
|
listForAuthenticatedUser: ["GET /user/teams"],
|
|
listMembersInOrg: ["GET /orgs/{org}/teams/{team_slug}/members"],
|
|
listPendingInvitationsInOrg: [
|
|
"GET /orgs/{org}/teams/{team_slug}/invitations"
|
|
],
|
|
listProjectsInOrg: ["GET /orgs/{org}/teams/{team_slug}/projects"],
|
|
listReposInOrg: ["GET /orgs/{org}/teams/{team_slug}/repos"],
|
|
removeMembershipForUserInOrg: [
|
|
"DELETE /orgs/{org}/teams/{team_slug}/memberships/{username}"
|
|
],
|
|
removeProjectInOrg: [
|
|
"DELETE /orgs/{org}/teams/{team_slug}/projects/{project_id}"
|
|
],
|
|
removeRepoInOrg: [
|
|
"DELETE /orgs/{org}/teams/{team_slug}/repos/{owner}/{repo}"
|
|
],
|
|
updateDiscussionCommentInOrg: [
|
|
"PATCH /orgs/{org}/teams/{team_slug}/discussions/{discussion_number}/comments/{comment_number}"
|
|
],
|
|
updateDiscussionInOrg: [
|
|
"PATCH /orgs/{org}/teams/{team_slug}/discussions/{discussion_number}"
|
|
],
|
|
updateInOrg: ["PATCH /orgs/{org}/teams/{team_slug}"]
|
|
},
|
|
users: {
|
|
addEmailForAuthenticated: [
|
|
"POST /user/emails",
|
|
{},
|
|
{ renamed: ["users", "addEmailForAuthenticatedUser"] }
|
|
],
|
|
addEmailForAuthenticatedUser: ["POST /user/emails"],
|
|
addSocialAccountForAuthenticatedUser: ["POST /user/social_accounts"],
|
|
block: ["PUT /user/blocks/{username}"],
|
|
checkBlocked: ["GET /user/blocks/{username}"],
|
|
checkFollowingForUser: ["GET /users/{username}/following/{target_user}"],
|
|
checkPersonIsFollowedByAuthenticated: ["GET /user/following/{username}"],
|
|
createGpgKeyForAuthenticated: [
|
|
"POST /user/gpg_keys",
|
|
{},
|
|
{ renamed: ["users", "createGpgKeyForAuthenticatedUser"] }
|
|
],
|
|
createGpgKeyForAuthenticatedUser: ["POST /user/gpg_keys"],
|
|
createPublicSshKeyForAuthenticated: [
|
|
"POST /user/keys",
|
|
{},
|
|
{ renamed: ["users", "createPublicSshKeyForAuthenticatedUser"] }
|
|
],
|
|
createPublicSshKeyForAuthenticatedUser: ["POST /user/keys"],
|
|
createSshSigningKeyForAuthenticatedUser: ["POST /user/ssh_signing_keys"],
|
|
deleteEmailForAuthenticated: [
|
|
"DELETE /user/emails",
|
|
{},
|
|
{ renamed: ["users", "deleteEmailForAuthenticatedUser"] }
|
|
],
|
|
deleteEmailForAuthenticatedUser: ["DELETE /user/emails"],
|
|
deleteGpgKeyForAuthenticated: [
|
|
"DELETE /user/gpg_keys/{gpg_key_id}",
|
|
{},
|
|
{ renamed: ["users", "deleteGpgKeyForAuthenticatedUser"] }
|
|
],
|
|
deleteGpgKeyForAuthenticatedUser: ["DELETE /user/gpg_keys/{gpg_key_id}"],
|
|
deletePublicSshKeyForAuthenticated: [
|
|
"DELETE /user/keys/{key_id}",
|
|
{},
|
|
{ renamed: ["users", "deletePublicSshKeyForAuthenticatedUser"] }
|
|
],
|
|
deletePublicSshKeyForAuthenticatedUser: ["DELETE /user/keys/{key_id}"],
|
|
deleteSocialAccountForAuthenticatedUser: ["DELETE /user/social_accounts"],
|
|
deleteSshSigningKeyForAuthenticatedUser: [
|
|
"DELETE /user/ssh_signing_keys/{ssh_signing_key_id}"
|
|
],
|
|
follow: ["PUT /user/following/{username}"],
|
|
getAuthenticated: ["GET /user"],
|
|
getByUsername: ["GET /users/{username}"],
|
|
getContextForUser: ["GET /users/{username}/hovercard"],
|
|
getGpgKeyForAuthenticated: [
|
|
"GET /user/gpg_keys/{gpg_key_id}",
|
|
{},
|
|
{ renamed: ["users", "getGpgKeyForAuthenticatedUser"] }
|
|
],
|
|
getGpgKeyForAuthenticatedUser: ["GET /user/gpg_keys/{gpg_key_id}"],
|
|
getPublicSshKeyForAuthenticated: [
|
|
"GET /user/keys/{key_id}",
|
|
{},
|
|
{ renamed: ["users", "getPublicSshKeyForAuthenticatedUser"] }
|
|
],
|
|
getPublicSshKeyForAuthenticatedUser: ["GET /user/keys/{key_id}"],
|
|
getSshSigningKeyForAuthenticatedUser: [
|
|
"GET /user/ssh_signing_keys/{ssh_signing_key_id}"
|
|
],
|
|
list: ["GET /users"],
|
|
listBlockedByAuthenticated: [
|
|
"GET /user/blocks",
|
|
{},
|
|
{ renamed: ["users", "listBlockedByAuthenticatedUser"] }
|
|
],
|
|
listBlockedByAuthenticatedUser: ["GET /user/blocks"],
|
|
listEmailsForAuthenticated: [
|
|
"GET /user/emails",
|
|
{},
|
|
{ renamed: ["users", "listEmailsForAuthenticatedUser"] }
|
|
],
|
|
listEmailsForAuthenticatedUser: ["GET /user/emails"],
|
|
listFollowedByAuthenticated: [
|
|
"GET /user/following",
|
|
{},
|
|
{ renamed: ["users", "listFollowedByAuthenticatedUser"] }
|
|
],
|
|
listFollowedByAuthenticatedUser: ["GET /user/following"],
|
|
listFollowersForAuthenticatedUser: ["GET /user/followers"],
|
|
listFollowersForUser: ["GET /users/{username}/followers"],
|
|
listFollowingForUser: ["GET /users/{username}/following"],
|
|
listGpgKeysForAuthenticated: [
|
|
"GET /user/gpg_keys",
|
|
{},
|
|
{ renamed: ["users", "listGpgKeysForAuthenticatedUser"] }
|
|
],
|
|
listGpgKeysForAuthenticatedUser: ["GET /user/gpg_keys"],
|
|
listGpgKeysForUser: ["GET /users/{username}/gpg_keys"],
|
|
listPublicEmailsForAuthenticated: [
|
|
"GET /user/public_emails",
|
|
{},
|
|
{ renamed: ["users", "listPublicEmailsForAuthenticatedUser"] }
|
|
],
|
|
listPublicEmailsForAuthenticatedUser: ["GET /user/public_emails"],
|
|
listPublicKeysForUser: ["GET /users/{username}/keys"],
|
|
listPublicSshKeysForAuthenticated: [
|
|
"GET /user/keys",
|
|
{},
|
|
{ renamed: ["users", "listPublicSshKeysForAuthenticatedUser"] }
|
|
],
|
|
listPublicSshKeysForAuthenticatedUser: ["GET /user/keys"],
|
|
listSocialAccountsForAuthenticatedUser: ["GET /user/social_accounts"],
|
|
listSocialAccountsForUser: ["GET /users/{username}/social_accounts"],
|
|
listSshSigningKeysForAuthenticatedUser: ["GET /user/ssh_signing_keys"],
|
|
listSshSigningKeysForUser: ["GET /users/{username}/ssh_signing_keys"],
|
|
setPrimaryEmailVisibilityForAuthenticated: [
|
|
"PATCH /user/email/visibility",
|
|
{},
|
|
{ renamed: ["users", "setPrimaryEmailVisibilityForAuthenticatedUser"] }
|
|
],
|
|
setPrimaryEmailVisibilityForAuthenticatedUser: [
|
|
"PATCH /user/email/visibility"
|
|
],
|
|
unblock: ["DELETE /user/blocks/{username}"],
|
|
unfollow: ["DELETE /user/following/{username}"],
|
|
updateAuthenticated: ["PATCH /user"]
|
|
}
|
|
};
|
|
var endpoints_default = Endpoints;
|
|
var endpointMethodsMap = /* @__PURE__ */ new Map();
|
|
for (const [scope, endpoints] of Object.entries(endpoints_default)) {
|
|
for (const [methodName, endpoint2] of Object.entries(endpoints)) {
|
|
const [route, defaults, decorations] = endpoint2;
|
|
const [method, url] = route.split(/ /);
|
|
const endpointDefaults = Object.assign(
|
|
{
|
|
method,
|
|
url
|
|
},
|
|
defaults
|
|
);
|
|
if (!endpointMethodsMap.has(scope)) {
|
|
endpointMethodsMap.set(scope, /* @__PURE__ */ new Map());
|
|
}
|
|
endpointMethodsMap.get(scope).set(methodName, {
|
|
scope,
|
|
methodName,
|
|
endpointDefaults,
|
|
decorations
|
|
});
|
|
}
|
|
}
|
|
var handler = {
|
|
get({ octokit, scope, cache }, methodName) {
|
|
if (cache[methodName]) {
|
|
return cache[methodName];
|
|
}
|
|
const { decorations, endpointDefaults } = endpointMethodsMap.get(scope).get(methodName);
|
|
if (decorations) {
|
|
cache[methodName] = decorate(
|
|
octokit,
|
|
scope,
|
|
methodName,
|
|
endpointDefaults,
|
|
decorations
|
|
);
|
|
} else {
|
|
cache[methodName] = octokit.request.defaults(endpointDefaults);
|
|
}
|
|
return cache[methodName];
|
|
}
|
|
};
|
|
function endpointsToMethods(octokit) {
|
|
const newMethods = {};
|
|
for (const scope of endpointMethodsMap.keys()) {
|
|
newMethods[scope] = new Proxy({ octokit, scope, cache: {} }, handler);
|
|
}
|
|
return newMethods;
|
|
}
|
|
function decorate(octokit, scope, methodName, defaults, decorations) {
|
|
const requestWithDefaults = octokit.request.defaults(defaults);
|
|
function withDecorations(...args) {
|
|
let options = requestWithDefaults.endpoint.merge(...args);
|
|
if (decorations.mapToData) {
|
|
options = Object.assign({}, options, {
|
|
data: options[decorations.mapToData],
|
|
[decorations.mapToData]: void 0
|
|
});
|
|
return requestWithDefaults(options);
|
|
}
|
|
if (decorations.renamed) {
|
|
const [newScope, newMethodName] = decorations.renamed;
|
|
octokit.log.warn(
|
|
`octokit.${scope}.${methodName}() has been renamed to octokit.${newScope}.${newMethodName}()`
|
|
);
|
|
}
|
|
if (decorations.deprecated) {
|
|
octokit.log.warn(decorations.deprecated);
|
|
}
|
|
if (decorations.renamedParameters) {
|
|
const options2 = requestWithDefaults.endpoint.merge(...args);
|
|
for (const [name, alias] of Object.entries(
|
|
decorations.renamedParameters
|
|
)) {
|
|
if (name in options2) {
|
|
octokit.log.warn(
|
|
`"${name}" parameter is deprecated for "octokit.${scope}.${methodName}()". Use "${alias}" instead`
|
|
);
|
|
if (!(alias in options2)) {
|
|
options2[alias] = options2[name];
|
|
}
|
|
delete options2[name];
|
|
}
|
|
}
|
|
return requestWithDefaults(options2);
|
|
}
|
|
return requestWithDefaults(...args);
|
|
}
|
|
return Object.assign(withDecorations, requestWithDefaults);
|
|
}
|
|
function restEndpointMethods(octokit) {
|
|
const api = endpointsToMethods(octokit);
|
|
return {
|
|
rest: api
|
|
};
|
|
}
|
|
restEndpointMethods.VERSION = VERSION7;
|
|
function legacyRestEndpointMethods(octokit) {
|
|
const api = endpointsToMethods(octokit);
|
|
return {
|
|
...api,
|
|
rest: api
|
|
};
|
|
}
|
|
legacyRestEndpointMethods.VERSION = VERSION7;
|
|
|
|
// node_modules/@octokit/rest/dist-web/index.js
|
|
var VERSION8 = "19.0.13";
|
|
var Octokit2 = Octokit.plugin(
|
|
requestLog,
|
|
legacyRestEndpointMethods,
|
|
paginateRest
|
|
).defaults({
|
|
userAgent: `octokit-rest.js/${VERSION8}`
|
|
});
|
|
|
|
// github-service.ts
|
|
var import_obsidian = require("obsidian");
|
|
init_i18n_simple();
|
|
var GitHubService = class {
|
|
constructor(token) {
|
|
this.rateLimitInfo = null;
|
|
this.octokit = new Octokit2({
|
|
auth: token
|
|
});
|
|
}
|
|
updateToken(token) {
|
|
this.octokit = new Octokit2({
|
|
auth: token
|
|
});
|
|
this.rateLimitInfo = null;
|
|
}
|
|
// Check rate limit status
|
|
async checkRateLimit() {
|
|
try {
|
|
const { data } = await this.octokit.rest.rateLimit.get();
|
|
const core = data.resources.core;
|
|
this.rateLimitInfo = {
|
|
remaining: core.remaining,
|
|
resetTime: core.reset
|
|
};
|
|
if (core.remaining === 0) {
|
|
const resetDate = new Date(core.reset * 1e3);
|
|
const waitMinutes = Math.ceil((resetDate.getTime() - Date.now()) / (1e3 * 60));
|
|
return {
|
|
canProceed: false,
|
|
waitMinutes,
|
|
message: t("github.api.rate.limit.exceeded", { minutes: waitMinutes })
|
|
};
|
|
}
|
|
if (core.remaining < 10) {
|
|
return {
|
|
canProceed: true,
|
|
message: t("github.api.rate.limit.warning", { remaining: core.remaining })
|
|
};
|
|
}
|
|
return { canProceed: true };
|
|
} catch (error) {
|
|
return { canProceed: true };
|
|
}
|
|
}
|
|
// Check rate limit before each API call
|
|
async beforeApiCall() {
|
|
const rateCheck = await this.checkRateLimit();
|
|
if (!rateCheck.canProceed) {
|
|
new import_obsidian.Notice(rateCheck.message || t("github.api.rate.limit.notice"), 8e3);
|
|
return false;
|
|
}
|
|
if (rateCheck.message && rateCheck.message.includes("\u26A0\uFE0F")) {
|
|
new import_obsidian.Notice(rateCheck.message, 5e3);
|
|
}
|
|
return true;
|
|
}
|
|
handleGitHubError(error) {
|
|
var _a;
|
|
if (error.status) {
|
|
switch (error.status) {
|
|
case 401:
|
|
return {
|
|
message: t("github.api.token.invalid"),
|
|
isRetryable: false
|
|
};
|
|
case 403:
|
|
if (((_a = error.response) == null ? void 0 : _a.headers) && error.response.headers["x-ratelimit-remaining"] === "0") {
|
|
const resetTime = error.response.headers["x-ratelimit-reset"];
|
|
const resetDate = new Date(parseInt(resetTime) * 1e3);
|
|
const waitMinutes = Math.ceil((resetDate.getTime() - Date.now()) / (1e3 * 60));
|
|
return {
|
|
message: t("github.api.rate.limit.hourly", { minutes: waitMinutes }),
|
|
isRetryable: true
|
|
};
|
|
} else {
|
|
return {
|
|
message: t("github.api.access.denied"),
|
|
isRetryable: false
|
|
};
|
|
}
|
|
case 404:
|
|
return {
|
|
message: t("github.api.resource.not.found"),
|
|
isRetryable: false
|
|
};
|
|
case 409:
|
|
return {
|
|
message: t("github.api.file.conflict.detailed"),
|
|
isRetryable: false
|
|
};
|
|
case 422:
|
|
return {
|
|
message: t("github.api.invalid.request"),
|
|
isRetryable: false
|
|
};
|
|
case 500:
|
|
case 502:
|
|
case 503:
|
|
case 504:
|
|
return {
|
|
message: t("github.api.server.error.detailed"),
|
|
isRetryable: true
|
|
};
|
|
default:
|
|
return {
|
|
message: t("github.api.error.with.status", { status: error.status, message: error.message || "Unknown error" }),
|
|
isRetryable: false
|
|
};
|
|
}
|
|
}
|
|
if (error.code === "ENOTFOUND" || error.code === "ECONNREFUSED") {
|
|
return {
|
|
message: t("github.api.network.failed"),
|
|
isRetryable: true
|
|
};
|
|
}
|
|
if (error.code === "ETIMEDOUT") {
|
|
return {
|
|
message: t("github.api.timeout.detailed"),
|
|
isRetryable: true
|
|
};
|
|
}
|
|
return {
|
|
message: t("github.api.operation.failed", { message: error.message || "Unknown error" }),
|
|
isRetryable: false
|
|
};
|
|
}
|
|
showErrorNotice(errorInfo) {
|
|
const notice = new import_obsidian.Notice(errorInfo.message, errorInfo.isRetryable ? 8e3 : 5e3);
|
|
if (errorInfo.isRetryable) {
|
|
setTimeout(() => {
|
|
new import_obsidian.Notice(t("github.api.retry.hint"), 3e3);
|
|
}, 1e3);
|
|
}
|
|
}
|
|
parseRepositoryUrl(url) {
|
|
console.log("Parsing repository URL:", url);
|
|
if (!url) {
|
|
console.error("URL is empty");
|
|
return null;
|
|
}
|
|
const cleanUrl = url.trim();
|
|
console.log("Cleaned URL:", cleanUrl);
|
|
let match;
|
|
match = cleanUrl.match(/^https:\/\/github\.com\/([^\/]+)\/([^\/]+)(?:\/(.*))?$/);
|
|
if (match) {
|
|
const result = {
|
|
owner: match[1],
|
|
repo: match[2],
|
|
path: match[3] || ""
|
|
};
|
|
console.log("Parse result (standard GitHub URL):", result);
|
|
return result;
|
|
}
|
|
match = cleanUrl.match(/^([^\/]+)\/([^\/]+)(?:\/(.*))?$/);
|
|
if (match) {
|
|
const result = {
|
|
owner: match[1],
|
|
repo: match[2],
|
|
path: match[3] || ""
|
|
};
|
|
console.log("Parse result (short format):", result);
|
|
return result;
|
|
}
|
|
console.error("Unable to parse URL format:", cleanUrl);
|
|
console.error("Supported formats:");
|
|
console.error("1. https://github.com/username/repo/path (standard format)");
|
|
console.error("2. username/repo/path (short format)");
|
|
return null;
|
|
}
|
|
async uploadFile(repositoryUrl, filePath, content) {
|
|
const repoInfo = this.parseRepositoryUrl(repositoryUrl);
|
|
if (!repoInfo) {
|
|
return { success: false, message: t("github.api.invalid.url.format") };
|
|
}
|
|
if (!await this.beforeApiCall()) {
|
|
return { success: false, message: t("github.api.rate.limit.exceeded.short") };
|
|
}
|
|
try {
|
|
const fullPath = repoInfo.path ? `${repoInfo.path}/${filePath}` : filePath;
|
|
let sha;
|
|
try {
|
|
const { data } = await this.octokit.rest.repos.getContent({
|
|
owner: repoInfo.owner,
|
|
repo: repoInfo.repo,
|
|
path: fullPath
|
|
});
|
|
if ("sha" in data) {
|
|
sha = data.sha;
|
|
}
|
|
} catch (error) {
|
|
}
|
|
await this.octokit.rest.repos.createOrUpdateFileContents({
|
|
owner: repoInfo.owner,
|
|
repo: repoInfo.repo,
|
|
path: fullPath,
|
|
message: `Update ${filePath}`,
|
|
content: Buffer.from(content, "utf8").toString("base64"),
|
|
sha
|
|
});
|
|
return { success: true, message: t("github.api.file.upload.success") };
|
|
} catch (error) {
|
|
console.error("File upload failed:", error);
|
|
const errorInfo = this.handleGitHubError(error);
|
|
this.showErrorNotice(errorInfo);
|
|
return { success: false, message: errorInfo.message };
|
|
}
|
|
}
|
|
async downloadFile(repositoryUrl, filePath) {
|
|
const repoInfo = this.parseRepositoryUrl(repositoryUrl);
|
|
if (!repoInfo) {
|
|
return { success: false, message: t("github.api.invalid.url.format") };
|
|
}
|
|
if (!await this.beforeApiCall()) {
|
|
return { success: false, message: t("github.api.rate.limit.exceeded.short") };
|
|
}
|
|
try {
|
|
const fullPath = repoInfo.path ? `${repoInfo.path}/${filePath}` : filePath;
|
|
const { data } = await this.octokit.rest.repos.getContent({
|
|
owner: repoInfo.owner,
|
|
repo: repoInfo.repo,
|
|
path: fullPath
|
|
});
|
|
if ("content" in data) {
|
|
const content = Buffer.from(data.content, "base64").toString("utf8");
|
|
return { success: true, message: "\u6587\u4EF6\u4E0B\u8F7D\u6210\u529F", content };
|
|
} else {
|
|
return { success: false, message: "\u6307\u5B9A\u8DEF\u5F84\u4E0D\u662F\u6587\u4EF6" };
|
|
}
|
|
} catch (error) {
|
|
console.error("File download failed:", error);
|
|
const errorInfo = this.handleGitHubError(error);
|
|
this.showErrorNotice(errorInfo);
|
|
return { success: false, message: errorInfo.message };
|
|
}
|
|
}
|
|
async downloadAllFiles(repositoryUrl) {
|
|
const repoInfo = this.parseRepositoryUrl(repositoryUrl);
|
|
if (!repoInfo) {
|
|
return { success: false, message: t("github.api.invalid.url.format") };
|
|
}
|
|
if (!await this.beforeApiCall()) {
|
|
return { success: false, message: t("github.api.rate.limit.exceeded.short") };
|
|
}
|
|
try {
|
|
const files = await this.getAllFilesRecursively(repoInfo.owner, repoInfo.repo, repoInfo.path);
|
|
const downloadedFiles = [];
|
|
for (const file of files) {
|
|
if (file.type === "file") {
|
|
try {
|
|
const { data } = await this.octokit.rest.repos.getContent({
|
|
owner: repoInfo.owner,
|
|
repo: repoInfo.repo,
|
|
path: file.path
|
|
});
|
|
if ("content" in data) {
|
|
const content = Buffer.from(data.content, "base64").toString("utf8");
|
|
const relativePath = repoInfo.path ? file.path.replace(`${repoInfo.path}/`, "") : file.path;
|
|
downloadedFiles.push({ path: relativePath, content });
|
|
}
|
|
} catch (error) {
|
|
console.warn(`\u8DF3\u8FC7\u6587\u4EF6 ${file.path}:`, error);
|
|
}
|
|
}
|
|
}
|
|
return { success: true, message: t("github.api.all.files.download.success"), files: downloadedFiles };
|
|
} catch (error) {
|
|
console.error("Download all files failed:", error);
|
|
const errorInfo = this.handleGitHubError(error);
|
|
this.showErrorNotice(errorInfo);
|
|
return { success: false, message: errorInfo.message };
|
|
}
|
|
}
|
|
async getAllFilesRecursively(owner, repo, path) {
|
|
const allFiles = [];
|
|
try {
|
|
const { data } = await this.octokit.rest.repos.getContent({
|
|
owner,
|
|
repo,
|
|
path
|
|
});
|
|
if (Array.isArray(data)) {
|
|
for (const item of data) {
|
|
if (item.type === "file") {
|
|
allFiles.push(item);
|
|
} else if (item.type === "dir") {
|
|
const subFiles = await this.getAllFilesRecursively(owner, repo, item.path);
|
|
allFiles.push(...subFiles);
|
|
}
|
|
}
|
|
}
|
|
} catch (error) {
|
|
console.error(`Failed to get directory content ${path}:`, error);
|
|
}
|
|
return allFiles;
|
|
}
|
|
async getFileLastModified(repositoryUrl, filePath) {
|
|
var _a, _b;
|
|
const repoInfo = this.parseRepositoryUrl(repositoryUrl);
|
|
if (!repoInfo) {
|
|
return { success: false, exists: false };
|
|
}
|
|
if (this.rateLimitInfo && this.rateLimitInfo.remaining === 0) {
|
|
return { success: false, exists: false };
|
|
}
|
|
try {
|
|
const fullPath = repoInfo.path ? `${repoInfo.path}/${filePath}` : filePath;
|
|
const { data } = await this.octokit.rest.repos.listCommits({
|
|
owner: repoInfo.owner,
|
|
repo: repoInfo.repo,
|
|
path: fullPath,
|
|
per_page: 1
|
|
});
|
|
if (data.length > 0) {
|
|
const lastCommit = data[0];
|
|
return {
|
|
success: true,
|
|
exists: true,
|
|
lastModified: ((_a = lastCommit.commit.committer) == null ? void 0 : _a.date) || ((_b = lastCommit.commit.author) == null ? void 0 : _b.date)
|
|
};
|
|
} else {
|
|
return { success: true, exists: false };
|
|
}
|
|
} catch (error) {
|
|
console.error("Failed to get file last modified time:", error);
|
|
const errorInfo = this.handleGitHubError(error);
|
|
return { success: false, exists: false };
|
|
}
|
|
}
|
|
};
|
|
|
|
// main.ts
|
|
init_i18n_simple();
|
|
|
|
// file-cache.ts
|
|
var FileCacheService = class {
|
|
// 5 minutes cache validity period
|
|
constructor() {
|
|
this.cache = /* @__PURE__ */ new Map();
|
|
this.CACHE_KEY = "git-sync-file-cache";
|
|
this.DEFAULT_CACHE_AGE = 5 * 60 * 1e3;
|
|
this.loadCacheFromStorage();
|
|
}
|
|
/**
|
|
* Load cache from local storage
|
|
*/
|
|
loadCacheFromStorage() {
|
|
try {
|
|
const stored = localStorage.getItem(this.CACHE_KEY);
|
|
if (stored) {
|
|
const cacheData = JSON.parse(stored);
|
|
this.cache = new Map(Object.entries(cacheData));
|
|
console.log(`Loaded ${this.cache.size} file caches`);
|
|
}
|
|
} catch (error) {
|
|
console.error("Failed to load file cache:", error);
|
|
this.cache.clear();
|
|
}
|
|
}
|
|
/**
|
|
* Save cache to local storage
|
|
*/
|
|
saveCacheToStorage() {
|
|
try {
|
|
const cacheObj = Object.fromEntries(this.cache);
|
|
localStorage.setItem(this.CACHE_KEY, JSON.stringify(cacheObj));
|
|
} catch (error) {
|
|
console.error("Failed to save file cache:", error);
|
|
}
|
|
}
|
|
/**
|
|
* Get file cache
|
|
*/
|
|
getFileCache(filePath) {
|
|
const cache = this.cache.get(filePath);
|
|
if (!cache) {
|
|
console.log(`File ${filePath} has no cache`);
|
|
return null;
|
|
}
|
|
if (!this.isCacheValid(cache)) {
|
|
console.log(`File ${filePath} cache has expired`);
|
|
this.removeFileCache(filePath);
|
|
return null;
|
|
}
|
|
console.log(`File ${filePath} using cache`);
|
|
return cache;
|
|
}
|
|
/**
|
|
* Set file cache
|
|
*/
|
|
setFileCache(filePath, cache) {
|
|
this.cache.set(filePath, {
|
|
...cache,
|
|
cacheTime: Date.now()
|
|
});
|
|
this.saveCacheToStorage();
|
|
console.log(`File ${filePath} cache updated`);
|
|
}
|
|
/**
|
|
* Remove file cache
|
|
*/
|
|
removeFileCache(filePath) {
|
|
if (this.cache.delete(filePath)) {
|
|
this.saveCacheToStorage();
|
|
console.log(`File ${filePath} cache removed`);
|
|
}
|
|
}
|
|
/**
|
|
* Clear all cache
|
|
*/
|
|
clearCache() {
|
|
this.cache.clear();
|
|
localStorage.removeItem(this.CACHE_KEY);
|
|
console.log("All file caches cleared");
|
|
}
|
|
/**
|
|
* Check if cache is valid
|
|
*/
|
|
isCacheValid(cache, maxAge) {
|
|
const age = maxAge || this.DEFAULT_CACHE_AGE;
|
|
return Date.now() - cache.cacheTime < age;
|
|
}
|
|
/**
|
|
* Get all cached files
|
|
*/
|
|
getAllCachedFiles() {
|
|
return Array.from(this.cache.values());
|
|
}
|
|
/**
|
|
* Calculate file content hash
|
|
*/
|
|
static calculateContentHash(content) {
|
|
let hash = 0;
|
|
for (let i = 0; i < content.length; i++) {
|
|
const char = content.charCodeAt(i);
|
|
hash = (hash << 5) - hash + char;
|
|
hash = hash & hash;
|
|
}
|
|
return hash.toString(36);
|
|
}
|
|
/**
|
|
* Check if file has been modified locally
|
|
*/
|
|
async checkLocalFileModified(filePath, vault) {
|
|
try {
|
|
const cache = this.getFileCache(filePath);
|
|
if (!cache)
|
|
return true;
|
|
const file = vault.getAbstractFileByPath(filePath);
|
|
if (!file)
|
|
return true;
|
|
const content = await vault.read(file);
|
|
const currentHash = FileCacheService.calculateContentHash(content);
|
|
return currentHash !== cache.contentHash;
|
|
} catch (error) {
|
|
console.error("Failed to check file modification status:", error);
|
|
return true;
|
|
}
|
|
}
|
|
/**
|
|
* Update file cache status
|
|
*/
|
|
async updateFileCache(filePath, githubPath, lastModified, sha, isPublished, vault) {
|
|
try {
|
|
const file = vault.getAbstractFileByPath(filePath);
|
|
if (!file)
|
|
return;
|
|
const content = await vault.read(file);
|
|
const contentHash = FileCacheService.calculateContentHash(content);
|
|
const cache = {
|
|
filePath,
|
|
githubPath,
|
|
lastModified,
|
|
sha,
|
|
isPublished,
|
|
isSynced: true,
|
|
// Newly updated cache is considered synced
|
|
cacheTime: Date.now(),
|
|
fileSize: content.length,
|
|
contentHash
|
|
};
|
|
this.setFileCache(filePath, cache);
|
|
} catch (error) {
|
|
console.error("Failed to update file cache:", error);
|
|
}
|
|
}
|
|
/**
|
|
* Get cache statistics
|
|
*/
|
|
getCacheStats() {
|
|
const allCaches = this.getAllCachedFiles();
|
|
const expiredCaches = allCaches.filter((cache) => !this.isCacheValid(cache));
|
|
return {
|
|
totalFiles: allCaches.length,
|
|
publishedFiles: allCaches.filter((cache) => cache.isPublished).length,
|
|
syncedFiles: allCaches.filter((cache) => cache.isSynced).length,
|
|
expiredCaches: expiredCaches.length
|
|
};
|
|
}
|
|
};
|
|
|
|
// main.ts
|
|
init_cos_service();
|
|
var GitSyncPlugin = class extends import_obsidian3.Plugin {
|
|
constructor() {
|
|
super(...arguments);
|
|
this.ribbonIconEl = null;
|
|
this.statusBarEl = null;
|
|
this.currentFile = null;
|
|
this.fileModifyTimeout = null;
|
|
this.isProcessingImagePaste = false;
|
|
}
|
|
async onload() {
|
|
await this.loadSettings();
|
|
setLanguage(this.settings.language);
|
|
this.githubService = new GitHubService(this.settings.githubToken);
|
|
this.fileCacheService = new FileCacheService();
|
|
this.updateRibbonIcon();
|
|
this.statusBarEl = this.addStatusBarItem();
|
|
this.statusBarEl.addClass("git-sync-status-bar");
|
|
this.registerEvent(
|
|
this.app.workspace.on("active-leaf-change", () => {
|
|
this.updateStatusBar();
|
|
})
|
|
);
|
|
this.registerEvent(
|
|
this.app.workspace.on("file-open", (file) => {
|
|
this.currentFile = file;
|
|
this.updateStatusBar();
|
|
})
|
|
);
|
|
this.registerEvent(
|
|
this.app.vault.on("modify", (file) => {
|
|
if (file.path.endsWith(".md") && this.currentFile && file.path === this.currentFile.path) {
|
|
console.log(`Detected file modification: ${file.path}`);
|
|
if (file instanceof import_obsidian3.TFile) {
|
|
this.onFileContentModified(file);
|
|
}
|
|
}
|
|
})
|
|
);
|
|
this.registerDomEvent(document, "paste", this.handlePasteEvent.bind(this), { capture: true });
|
|
this.registerDomEvent(document.body, "paste", this.handlePasteEvent.bind(this), { capture: true });
|
|
this.addCommand({
|
|
id: "show-sync-menu",
|
|
name: t("command.show.sync.menu"),
|
|
editorCallback: (editor, view) => {
|
|
this.showSyncMenu(editor, view);
|
|
}
|
|
});
|
|
this.registerEvent(
|
|
this.app.workspace.on("editor-menu", (menu, editor, view) => {
|
|
menu.addItem((item) => {
|
|
item.setTitle(t("plugin.name")).setIcon("sync").onClick(async () => {
|
|
this.showSyncMenu(editor, view);
|
|
});
|
|
});
|
|
})
|
|
);
|
|
this.addSettingTab(new GitSyncSettingTab(this.app, this));
|
|
this.updateStatusBar();
|
|
}
|
|
onunload() {
|
|
if (this.fileModifyTimeout) {
|
|
clearTimeout(this.fileModifyTimeout);
|
|
this.fileModifyTimeout = null;
|
|
}
|
|
}
|
|
async loadSettings() {
|
|
this.settings = Object.assign({}, DEFAULT_SETTINGS, await this.loadData());
|
|
}
|
|
async saveSettings() {
|
|
await this.saveData(this.settings);
|
|
this.githubService.updateToken(this.settings.githubToken);
|
|
setLanguage(this.settings.language);
|
|
this.updateRibbonIcon();
|
|
}
|
|
updateRibbonIcon() {
|
|
if (this.ribbonIconEl) {
|
|
this.ribbonIconEl.remove();
|
|
this.ribbonIconEl = null;
|
|
}
|
|
if (this.settings.showRibbonIcon) {
|
|
this.ribbonIconEl = this.addRibbonIcon("settings", t("settings.title"), (evt) => {
|
|
this.app.setting.open();
|
|
this.app.setting.openTabById(this.manifest.id);
|
|
});
|
|
}
|
|
}
|
|
showSyncMenu(editor, view) {
|
|
var _a;
|
|
const menu = new import_obsidian3.Menu();
|
|
menu.addItem((item) => {
|
|
item.setTitle(t("actions.sync.current.to.remote")).setIcon("upload").onClick(async () => {
|
|
await this.syncCurrentFileToRemote(view.file);
|
|
});
|
|
});
|
|
menu.addItem((item) => {
|
|
item.setTitle(t("actions.pull.remote.to.current")).setIcon("download").onClick(async () => {
|
|
await this.pullRemoteToCurrentFile(view.file);
|
|
});
|
|
});
|
|
const rect = (_a = editor.containerEl) == null ? void 0 : _a.getBoundingClientRect();
|
|
if (rect) {
|
|
menu.showAtPosition({ x: rect.right - 100, y: rect.top + 50 });
|
|
} else {
|
|
menu.showAtMouseEvent(new MouseEvent("click"));
|
|
}
|
|
}
|
|
async syncCurrentFileToRemote(file) {
|
|
if (!this.settings.githubToken || !this.settings.repositoryUrl) {
|
|
new import_obsidian3.Notice(t("settings.github.token.or.repo.not.configured"));
|
|
return;
|
|
}
|
|
try {
|
|
const content = await this.app.vault.read(file);
|
|
const result = await this.githubService.uploadFile(
|
|
this.settings.repositoryUrl,
|
|
file.path,
|
|
content
|
|
);
|
|
if (result.success) {
|
|
new import_obsidian3.Notice(t("sync.success", { filename: file.name }));
|
|
await this.fileCacheService.updateFileCache(
|
|
file.path,
|
|
file.path,
|
|
new Date().toISOString(),
|
|
// Use current time as last modified time
|
|
"",
|
|
// SHA value can be obtained from upload result later
|
|
true,
|
|
// Published
|
|
this.app.vault
|
|
);
|
|
} else {
|
|
new import_obsidian3.Notice(t("sync.failed", { message: result.message }));
|
|
}
|
|
} catch (error) {
|
|
console.error("File sync failed:", error);
|
|
new import_obsidian3.Notice(t("sync.error"));
|
|
}
|
|
}
|
|
async pullRemoteToCurrentFile(file) {
|
|
if (!this.settings.githubToken || !this.settings.repositoryUrl) {
|
|
new import_obsidian3.Notice(t("settings.github.token.or.repo.not.configured"));
|
|
return;
|
|
}
|
|
try {
|
|
const result = await this.githubService.downloadFile(
|
|
this.settings.repositoryUrl,
|
|
file.path
|
|
);
|
|
if (result.success && result.content) {
|
|
await this.app.vault.modify(file, result.content);
|
|
new import_obsidian3.Notice(t("pull.success", { filename: file.name }));
|
|
await this.fileCacheService.updateFileCache(
|
|
file.path,
|
|
file.path,
|
|
new Date().toISOString(),
|
|
// Use current time as last modified time
|
|
"",
|
|
// SHA value can be obtained from download result later
|
|
true,
|
|
// Published
|
|
this.app.vault
|
|
);
|
|
} else {
|
|
new import_obsidian3.Notice(t("pull.failed", { message: result.message }));
|
|
}
|
|
} catch (error) {
|
|
console.error("File pull failed:", error);
|
|
new import_obsidian3.Notice(t("pull.error"));
|
|
}
|
|
}
|
|
async initializeRepository() {
|
|
if (!this.isVaultEmpty()) {
|
|
return { success: false, message: t("vault.not.empty") };
|
|
}
|
|
try {
|
|
const result = await this.githubService.downloadAllFiles(this.settings.repositoryUrl);
|
|
if (result.success && result.files) {
|
|
for (const file of result.files) {
|
|
await this.createFileInVault(file.path, file.content || "");
|
|
await this.fileCacheService.updateFileCache(
|
|
file.path,
|
|
file.path,
|
|
new Date().toISOString(),
|
|
// Use current time as last modified time
|
|
"",
|
|
// SHA value can be obtained from download result later
|
|
true,
|
|
// Published
|
|
this.app.vault
|
|
);
|
|
}
|
|
setTimeout(() => this.updateStatusBar(), 2e3);
|
|
return { success: true, message: t("repo.init.success"), filesProcessed: result.files.length };
|
|
}
|
|
return { success: false, message: result.message };
|
|
} catch (error) {
|
|
return { success: false, message: t("repo.init.failed", { error: error.message }) };
|
|
}
|
|
}
|
|
async forceSyncRemoteToLocal() {
|
|
try {
|
|
const result = await this.githubService.downloadAllFiles(this.settings.repositoryUrl);
|
|
if (result.success && result.files) {
|
|
for (const file of result.files) {
|
|
await this.createFileInVault(file.path, file.content || "");
|
|
await this.fileCacheService.updateFileCache(
|
|
file.path,
|
|
file.path,
|
|
new Date().toISOString(),
|
|
// Use current time as last modified time
|
|
"",
|
|
// SHA value can be obtained from download result later
|
|
true,
|
|
// Published
|
|
this.app.vault
|
|
);
|
|
}
|
|
setTimeout(() => this.updateStatusBar(), 2e3);
|
|
return { success: true, message: t("force.sync.remote.to.local.success"), filesProcessed: result.files.length };
|
|
}
|
|
return { success: false, message: result.message };
|
|
} catch (error) {
|
|
return { success: false, message: t("force.sync.remote.to.local.failed", { error: error.message }) };
|
|
}
|
|
}
|
|
async forceSyncLocalToRemote() {
|
|
try {
|
|
const files = this.getAllVaultFiles();
|
|
console.log("Found files:", files.map((f) => f.path));
|
|
if (files.length === 0) {
|
|
return { success: false, message: t("no.syncable.files.in.vault") };
|
|
}
|
|
let processed = 0;
|
|
let failed = 0;
|
|
for (const file of files) {
|
|
try {
|
|
const content = await this.app.vault.read(file);
|
|
const result = await this.githubService.uploadFile(
|
|
this.settings.repositoryUrl,
|
|
file.path,
|
|
content
|
|
);
|
|
if (result.success) {
|
|
processed++;
|
|
console.log(`Successfully synced file: ${file.path}`);
|
|
await this.fileCacheService.updateFileCache(
|
|
file.path,
|
|
file.path,
|
|
new Date().toISOString(),
|
|
// Use current time as last modified time
|
|
"",
|
|
// SHA value can be obtained from upload result later
|
|
true,
|
|
// Published
|
|
this.app.vault
|
|
);
|
|
} else {
|
|
failed++;
|
|
console.error(`File sync failed: ${file.path}`, result.message);
|
|
}
|
|
} catch (error) {
|
|
failed++;
|
|
console.error(`Failed to read or sync file: ${file.path}`, error);
|
|
}
|
|
}
|
|
const message = failed > 0 ? t("force.sync.local.to.remote.success", { processed, failed }) : t("force.sync.local.to.remote.success.no.failures");
|
|
setTimeout(() => this.updateStatusBar(), 2e3);
|
|
return { success: true, message, filesProcessed: processed };
|
|
} catch (error) {
|
|
console.error("Force sync failed:", error);
|
|
return { success: false, message: t("force.sync.local.to.remote.failed", { error: error.message }) };
|
|
}
|
|
}
|
|
isVaultEmpty() {
|
|
const files = this.app.vault.getFiles();
|
|
return files.filter((file) => !file.path.startsWith(".obsidian")).length === 0;
|
|
}
|
|
getAllVaultFiles() {
|
|
const allFiles = this.app.vault.getFiles();
|
|
console.log("All files in vault:", allFiles.map((f) => f.path));
|
|
const filteredFiles = allFiles.filter((file) => {
|
|
if (file.path.startsWith(".obsidian")) {
|
|
return false;
|
|
}
|
|
if (this.settings.keepLocalImages && this.settings.localImagePath) {
|
|
const normalizedImagePath = this.settings.localImagePath.replace(/^\/+|\/+$/g, "");
|
|
if (normalizedImagePath && file.path.startsWith(normalizedImagePath + "/")) {
|
|
console.log(`Excluding file from sync (in image directory): ${file.path}`);
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
});
|
|
console.log("Filtered files:", filteredFiles.map((f) => f.path));
|
|
return filteredFiles;
|
|
}
|
|
async createFileInVault(path, content) {
|
|
const folderPath = path.substring(0, path.lastIndexOf("/"));
|
|
if (folderPath && !this.app.vault.getAbstractFileByPath(folderPath)) {
|
|
await this.app.vault.createFolder(folderPath);
|
|
}
|
|
const existingFile = this.app.vault.getAbstractFileByPath(path);
|
|
if (existingFile instanceof import_obsidian3.TFile) {
|
|
await this.app.vault.modify(existingFile, content);
|
|
} else {
|
|
await this.app.vault.create(path, content);
|
|
}
|
|
}
|
|
async updateStatusBar() {
|
|
if (!this.statusBarEl)
|
|
return;
|
|
const activeFile = this.app.workspace.getActiveFile();
|
|
if (!activeFile || !activeFile.path.endsWith(".md")) {
|
|
this.statusBarEl.empty();
|
|
this.statusBarEl.style.display = "none";
|
|
return;
|
|
}
|
|
this.currentFile = activeFile;
|
|
this.statusBarEl.style.display = "flex";
|
|
this.statusBarEl.empty();
|
|
const statusText = this.statusBarEl.createEl("span", {
|
|
cls: "git-sync-status-text",
|
|
text: t("status.bar.checking")
|
|
});
|
|
const syncButton = this.statusBarEl.createEl("button", {
|
|
cls: "git-sync-status-button",
|
|
text: t("status.bar.sync")
|
|
});
|
|
if (this.settings.githubToken && this.settings.repositoryUrl) {
|
|
try {
|
|
const cache = this.fileCacheService.getFileCache(activeFile.path);
|
|
if (cache) {
|
|
console.log(`Using cached data to display file status: ${activeFile.path}`);
|
|
if (cache.isPublished) {
|
|
const date = new Date(cache.lastModified);
|
|
let statusMsg = t("status.bar.last.modified", { date: this.formatDate(date) });
|
|
if (!cache.isSynced) {
|
|
statusMsg += ` (${t("status.bar.local.modified")})`;
|
|
statusText.style.color = "var(--color-orange)";
|
|
} else {
|
|
statusMsg += ` (${t("status.bar.synced")})`;
|
|
statusText.style.color = "var(--color-green)";
|
|
}
|
|
statusText.textContent = statusMsg;
|
|
} else {
|
|
statusText.textContent = t("status.bar.not.published");
|
|
statusText.style.color = "var(--text-muted)";
|
|
}
|
|
if (!this.fileCacheService.isCacheValid(cache, 4 * 60 * 1e3)) {
|
|
this.refreshFileCache(activeFile.path).catch(console.error);
|
|
}
|
|
} else {
|
|
console.log(`No cache, fetching file status from GitHub: ${activeFile.path}`);
|
|
await this.fetchAndCacheFileStatus(activeFile.path, statusText);
|
|
}
|
|
} catch (error) {
|
|
console.error("Failed to update status bar:", error);
|
|
statusText.textContent = t("status.bar.check.failed");
|
|
}
|
|
} else {
|
|
statusText.textContent = t("status.bar.not.configured");
|
|
}
|
|
syncButton.addEventListener("click", (e) => {
|
|
e.stopPropagation();
|
|
this.showSyncMenuForStatusBar(activeFile);
|
|
});
|
|
}
|
|
/**
|
|
* Handle file content modification events (with debounce)
|
|
*/
|
|
async onFileContentModified(file) {
|
|
if (this.fileModifyTimeout) {
|
|
clearTimeout(this.fileModifyTimeout);
|
|
}
|
|
this.fileModifyTimeout = setTimeout(async () => {
|
|
try {
|
|
const cache = this.fileCacheService.getFileCache(file.path);
|
|
if (!cache) {
|
|
this.updateStatusBar();
|
|
return;
|
|
}
|
|
const content = await this.app.vault.read(file);
|
|
const currentHash = FileCacheService.calculateContentHash(content);
|
|
if (currentHash !== cache.contentHash) {
|
|
console.log(`File content modified: ${file.path}`);
|
|
const updatedCache = {
|
|
...cache,
|
|
contentHash: currentHash,
|
|
isSynced: false,
|
|
// Mark as not synced
|
|
cacheTime: Date.now()
|
|
};
|
|
this.fileCacheService.setFileCache(file.path, updatedCache);
|
|
this.updateStatusBar();
|
|
}
|
|
} catch (error) {
|
|
console.error("Failed to handle file modification event:", error);
|
|
}
|
|
}, 2e3);
|
|
}
|
|
/**
|
|
* Fetch file status from GitHub and cache it
|
|
*/
|
|
async fetchAndCacheFileStatus(filePath, statusText) {
|
|
try {
|
|
const rateLimitCheck = await this.githubService.checkRateLimit();
|
|
if (!rateLimitCheck.canProceed) {
|
|
statusText.textContent = t("status.bar.rate.limit", { minutes: rateLimitCheck.waitMinutes });
|
|
return;
|
|
}
|
|
const result = await this.githubService.getFileLastModified(
|
|
this.settings.repositoryUrl,
|
|
filePath
|
|
);
|
|
if (result.success) {
|
|
if (result.exists && result.lastModified) {
|
|
const date = new Date(result.lastModified);
|
|
statusText.textContent = t("status.bar.last.modified", { date: this.formatDate(date) });
|
|
statusText.style.color = "var(--text-normal)";
|
|
await this.fileCacheService.updateFileCache(
|
|
filePath,
|
|
filePath,
|
|
// GitHub path same as local path
|
|
result.lastModified,
|
|
"",
|
|
// SHA value temporarily empty, can be obtained from other APIs later
|
|
true,
|
|
this.app.vault
|
|
);
|
|
} else {
|
|
statusText.textContent = t("status.bar.not.published");
|
|
statusText.style.color = "var(--text-muted)";
|
|
await this.fileCacheService.updateFileCache(
|
|
filePath,
|
|
filePath,
|
|
"",
|
|
"",
|
|
false,
|
|
this.app.vault
|
|
);
|
|
}
|
|
} else {
|
|
statusText.textContent = t("status.bar.check.failed");
|
|
}
|
|
} catch (error) {
|
|
console.error("Failed to fetch file status:", error);
|
|
statusText.textContent = t("status.bar.check.failed");
|
|
}
|
|
}
|
|
/**
|
|
* Asynchronously refresh file cache
|
|
*/
|
|
async refreshFileCache(filePath) {
|
|
try {
|
|
console.log(`Asynchronously refreshing file cache: ${filePath}`);
|
|
const result = await this.githubService.getFileLastModified(
|
|
this.settings.repositoryUrl,
|
|
filePath
|
|
);
|
|
if (result.success) {
|
|
await this.fileCacheService.updateFileCache(
|
|
filePath,
|
|
filePath,
|
|
result.lastModified || "",
|
|
"",
|
|
// SHA value temporarily empty
|
|
result.exists || false,
|
|
this.app.vault
|
|
);
|
|
console.log(`File cache refreshed: ${filePath}`);
|
|
}
|
|
} catch (error) {
|
|
console.error("Failed to refresh file cache:", error);
|
|
}
|
|
}
|
|
showSyncMenuForStatusBar(file) {
|
|
var _a;
|
|
const menu = new import_obsidian3.Menu();
|
|
menu.addItem((item) => {
|
|
item.setTitle(t("actions.sync.current.to.remote")).setIcon("upload").onClick(async () => {
|
|
await this.syncCurrentFileToRemote(file);
|
|
setTimeout(() => this.updateStatusBar(), 1e3);
|
|
});
|
|
});
|
|
menu.addItem((item) => {
|
|
item.setTitle(t("actions.pull.remote.to.current")).setIcon("download").onClick(async () => {
|
|
await this.pullRemoteToCurrentFile(file);
|
|
setTimeout(() => this.updateStatusBar(), 1e3);
|
|
});
|
|
});
|
|
const rect = (_a = this.statusBarEl) == null ? void 0 : _a.getBoundingClientRect();
|
|
if (rect) {
|
|
menu.showAtPosition({ x: rect.left, y: rect.top - 10 });
|
|
}
|
|
}
|
|
formatDate(date) {
|
|
const now = new Date();
|
|
const diffMs = now.getTime() - date.getTime();
|
|
const diffDays = Math.floor(diffMs / (1e3 * 60 * 60 * 24));
|
|
if (diffDays === 0) {
|
|
return t("date.today");
|
|
} else if (diffDays === 1) {
|
|
return t("date.yesterday");
|
|
} else if (diffDays < 7) {
|
|
return t("date.days.ago", { days: diffDays });
|
|
} else {
|
|
return date.toLocaleDateString("zh-CN");
|
|
}
|
|
}
|
|
/**
|
|
* Handle paste events for image upload
|
|
*/
|
|
async handlePasteEvent(event) {
|
|
const activeView = this.app.workspace.getActiveViewOfType(import_obsidian3.MarkdownView);
|
|
if (!activeView || !this.currentFile) {
|
|
return;
|
|
}
|
|
const clipboardData = event.clipboardData;
|
|
if (!clipboardData || !clipboardData.files || clipboardData.files.length === 0) {
|
|
return;
|
|
}
|
|
const imageFiles = [];
|
|
for (let i = 0; i < clipboardData.files.length; i++) {
|
|
const file = clipboardData.files[i];
|
|
if (file.type.startsWith("image/")) {
|
|
imageFiles.push(file);
|
|
}
|
|
}
|
|
if (imageFiles.length === 0) {
|
|
return;
|
|
}
|
|
if (!this.settings.enableImageProcessing) {
|
|
return;
|
|
}
|
|
event.preventDefault();
|
|
event.stopPropagation();
|
|
event.stopImmediatePropagation();
|
|
this.isProcessingImagePaste = true;
|
|
const cosConfigured = this.isCosConfigured();
|
|
for (const file of imageFiles) {
|
|
try {
|
|
if (cosConfigured) {
|
|
await this.handleImageUpload(file, activeView.editor);
|
|
} else if (this.settings.keepLocalImages && this.settings.localImagePath) {
|
|
await this.handleLocalImageOnly(file, activeView.editor);
|
|
} else {
|
|
new import_obsidian3.Notice(t("cos.upload.no.config"));
|
|
}
|
|
} catch (error) {
|
|
console.error("Error handling image:", error);
|
|
new import_obsidian3.Notice(t("cos.upload.failed", { error: error.message }));
|
|
}
|
|
}
|
|
this.isProcessingImagePaste = false;
|
|
}
|
|
/**
|
|
* Get current COS configuration
|
|
*/
|
|
getCurrentCosConfig() {
|
|
return this.settings.cosConfigs[this.settings.cosProvider];
|
|
}
|
|
/**
|
|
* Update current COS configuration
|
|
*/
|
|
updateCurrentCosConfig(updates) {
|
|
const currentConfig = this.getCurrentCosConfig();
|
|
Object.assign(currentConfig, updates);
|
|
}
|
|
/**
|
|
* Clear current COS configuration
|
|
*/
|
|
clearCurrentCosConfig() {
|
|
const emptyConfig = {
|
|
secretId: "",
|
|
secretKey: "",
|
|
bucket: "",
|
|
endpoint: "",
|
|
cdnUrl: "",
|
|
region: ""
|
|
};
|
|
this.settings.cosConfigs[this.settings.cosProvider] = emptyConfig;
|
|
}
|
|
/**
|
|
* Check if COS is properly configured
|
|
*/
|
|
isCosConfigured() {
|
|
const currentConfig = this.getCurrentCosConfig();
|
|
const requiredFields = [
|
|
currentConfig.secretId,
|
|
currentConfig.secretKey,
|
|
currentConfig.bucket,
|
|
currentConfig.region
|
|
// Region is required for all providers
|
|
];
|
|
if (this.settings.cosProvider === "cloudflare") {
|
|
requiredFields.push(currentConfig.endpoint);
|
|
}
|
|
return requiredFields.every((field) => field && field.trim().length > 0);
|
|
}
|
|
/**
|
|
* Handle single image upload
|
|
*/
|
|
async handleImageUpload(file, editor) {
|
|
const timestamp = Date.now();
|
|
const extension = file.name.split(".").pop() || "png";
|
|
const fileName = `image-${timestamp}.${extension}`;
|
|
const remotePath = parseImagePath(this.settings.imageUploadPath, {
|
|
currentFilePath: this.currentFile.path,
|
|
fileName
|
|
});
|
|
const placeholder = t("cos.paste.placeholder", { filename: fileName });
|
|
const cursorPos = editor.getCursor();
|
|
editor.replaceRange(placeholder, cursorPos);
|
|
const uploadNotice = new import_obsidian3.Notice(t("cos.upload.uploading"), 0);
|
|
try {
|
|
const currentConfig = this.getCurrentCosConfig();
|
|
const cosConfig = {
|
|
provider: this.settings.cosProvider,
|
|
secretId: currentConfig.secretId,
|
|
secretKey: currentConfig.secretKey,
|
|
bucket: currentConfig.bucket,
|
|
endpoint: currentConfig.endpoint,
|
|
cdnUrl: currentConfig.cdnUrl,
|
|
region: currentConfig.region
|
|
};
|
|
const cosService = new CosService(cosConfig);
|
|
const uploadResult = await cosService.uploadFile(file, remotePath);
|
|
if (uploadResult.success && uploadResult.url) {
|
|
const imageMarkdown = ``;
|
|
const currentContent = editor.getValue();
|
|
const updatedContent = currentContent.replace(placeholder, imageMarkdown);
|
|
editor.setValue(updatedContent);
|
|
if (this.settings.keepLocalImages && this.settings.localImagePath) {
|
|
await this.saveLocalImageCopy(file, fileName);
|
|
}
|
|
uploadNotice.hide();
|
|
new import_obsidian3.Notice(t("cos.upload.success"));
|
|
console.log("Image uploaded successfully:", uploadResult.url);
|
|
} else {
|
|
throw new Error(uploadResult.message || "Upload failed");
|
|
}
|
|
} catch (error) {
|
|
const currentContent = editor.getValue();
|
|
const updatedContent = currentContent.replace(placeholder, "");
|
|
editor.setValue(updatedContent);
|
|
uploadNotice.hide();
|
|
new import_obsidian3.Notice(t("cos.upload.failed", { error: error.message }));
|
|
console.error("Image upload failed:", error);
|
|
throw error;
|
|
}
|
|
}
|
|
/**
|
|
* Handle local image storage only (when COS is not configured)
|
|
*/
|
|
async handleLocalImageOnly(file, editor) {
|
|
const timestamp = Date.now();
|
|
const extension = file.name.split(".").pop() || "png";
|
|
const fileName = `image-${timestamp}.${extension}`;
|
|
try {
|
|
const localPath = parseImagePath(this.settings.localImagePath, {
|
|
currentFilePath: this.currentFile.path,
|
|
fileName
|
|
});
|
|
const dirPath = localPath.substring(0, localPath.lastIndexOf("/"));
|
|
if (dirPath) {
|
|
try {
|
|
await this.app.vault.createFolder(dirPath);
|
|
} catch (error) {
|
|
}
|
|
}
|
|
const arrayBuffer = await file.arrayBuffer();
|
|
await this.app.vault.createBinary(localPath, arrayBuffer);
|
|
const imageMarkdown = ``;
|
|
const cursorPos = editor.getCursor();
|
|
editor.replaceRange(imageMarkdown, cursorPos);
|
|
new import_obsidian3.Notice(t("cos.upload.success"));
|
|
console.log("Image saved locally:", localPath);
|
|
} catch (error) {
|
|
new import_obsidian3.Notice(t("cos.upload.failed", { error: error.message }));
|
|
console.error("Local image save failed:", error);
|
|
}
|
|
}
|
|
/**
|
|
* Save image copy locally if enabled
|
|
*/
|
|
async saveLocalImageCopy(file, fileName) {
|
|
try {
|
|
const localPath = parseImagePath(this.settings.localImagePath, {
|
|
currentFilePath: this.currentFile.path,
|
|
fileName
|
|
});
|
|
const dirPath = localPath.substring(0, localPath.lastIndexOf("/"));
|
|
if (dirPath) {
|
|
try {
|
|
await this.app.vault.createFolder(dirPath);
|
|
} catch (error) {
|
|
}
|
|
}
|
|
const arrayBuffer = await file.arrayBuffer();
|
|
await this.app.vault.createBinary(localPath, arrayBuffer);
|
|
console.log("Local image copy saved:", localPath);
|
|
} catch (error) {
|
|
console.warn("Failed to save local image copy:", error);
|
|
}
|
|
}
|
|
};
|
|
var GitSyncSettingTab = class extends import_obsidian3.PluginSettingTab {
|
|
constructor(app, plugin) {
|
|
super(app, plugin);
|
|
this.plugin = plugin;
|
|
}
|
|
display() {
|
|
const { containerEl } = this;
|
|
containerEl.empty();
|
|
containerEl.createEl("h2", { text: t("settings.title") });
|
|
new import_obsidian3.Setting(containerEl).setName(t("settings.language.name")).setDesc(t("settings.language.desc")).addDropdown((dropdown) => {
|
|
const languages = getSupportedLanguages();
|
|
languages.forEach((lang) => {
|
|
dropdown.addOption(lang.value, lang.label);
|
|
});
|
|
dropdown.setValue(this.plugin.settings.language);
|
|
dropdown.onChange(async (value) => {
|
|
this.plugin.settings.language = value;
|
|
await this.plugin.saveSettings();
|
|
this.display();
|
|
});
|
|
});
|
|
new import_obsidian3.Setting(containerEl).setName(t("settings.github.token.name")).setDesc(t("settings.github.token.desc")).addText((text) => text.setPlaceholder(t("settings.github.token.placeholder")).setValue(this.plugin.settings.githubToken).onChange(async (value) => {
|
|
this.plugin.settings.githubToken = value;
|
|
}));
|
|
let pathInfoEl;
|
|
new import_obsidian3.Setting(containerEl).setName(t("settings.github.repo.name")).setDesc(t("settings.github.repo.desc")).addText((text) => text.setPlaceholder(t("settings.github.repo.placeholder")).setValue(this.plugin.settings.repositoryUrl).onChange(async (value) => {
|
|
this.plugin.settings.repositoryUrl = value;
|
|
this.updatePathInfo(pathInfoEl, value);
|
|
}));
|
|
pathInfoEl = containerEl.createEl("div", {
|
|
cls: "setting-item-description git-sync-path-info",
|
|
text: this.getPathInfoText(this.plugin.settings.repositoryUrl)
|
|
});
|
|
new import_obsidian3.Setting(containerEl).setName(t("settings.test.url.name")).setDesc(t("settings.test.url.desc")).addButton((button) => button.setButtonText(t("settings.test.url.button")).onClick(async () => {
|
|
if (!this.plugin.settings.repositoryUrl) {
|
|
new import_obsidian3.Notice(t("notice.url.required"));
|
|
return;
|
|
}
|
|
console.log("=== Testing Repository URL ===");
|
|
console.log("Input URL:", this.plugin.settings.repositoryUrl);
|
|
const testResult = this.plugin.githubService.parseRepositoryUrl(this.plugin.settings.repositoryUrl);
|
|
if (testResult) {
|
|
console.log("URL parsing successful:", testResult);
|
|
new import_obsidian3.Notice(`${t("notice.url.test.success")}
|
|
${t("test.url.user")}: ${testResult.owner}
|
|
${t("test.url.repo")}: ${testResult.repo}
|
|
${t("test.url.path")}: ${testResult.path || t("test.url.root")}`, 6e3);
|
|
} else {
|
|
console.log("URL parsing failed");
|
|
new import_obsidian3.Notice(t("notice.url.test.failed"), 6e3);
|
|
}
|
|
}));
|
|
new import_obsidian3.Setting(containerEl).setName(t("settings.ribbon.name")).setDesc(t("settings.ribbon.desc")).addToggle((toggle) => toggle.setValue(this.plugin.settings.showRibbonIcon).onChange(async (value) => {
|
|
this.plugin.settings.showRibbonIcon = value;
|
|
await this.plugin.saveSettings();
|
|
}));
|
|
containerEl.createEl("h2", {
|
|
text: t("settings.image.section.title"),
|
|
cls: "git-sync-section-title"
|
|
});
|
|
new import_obsidian3.Setting(containerEl).setName(t("settings.image.enable.name")).setDesc(t("settings.image.enable.desc")).addToggle((toggle) => toggle.setValue(this.plugin.settings.enableImageProcessing).onChange(async (value) => {
|
|
this.plugin.settings.enableImageProcessing = value;
|
|
await this.plugin.saveSettings();
|
|
this.display();
|
|
}));
|
|
if (this.plugin.settings.enableImageProcessing) {
|
|
containerEl.createEl("h3", {
|
|
text: t("settings.cos.provider.section.title"),
|
|
cls: "git-sync-subsection-title"
|
|
});
|
|
new import_obsidian3.Setting(containerEl).setName(t("settings.cos.provider.name")).setDesc(t("settings.cos.provider.desc")).addDropdown((dropdown) => {
|
|
dropdown.addOption("aliyun", t("settings.cos.provider.aliyun"));
|
|
dropdown.addOption("tencent", t("settings.cos.provider.tencent"));
|
|
dropdown.addOption("aws", t("settings.cos.provider.aws"));
|
|
dropdown.addOption("cloudflare", t("settings.cos.provider.cloudflare"));
|
|
dropdown.setValue(this.plugin.settings.cosProvider);
|
|
dropdown.onChange(async (value) => {
|
|
this.plugin.settings.cosProvider = value;
|
|
await this.plugin.saveSettings();
|
|
this.display();
|
|
});
|
|
});
|
|
const currentConfig = this.plugin.getCurrentCosConfig();
|
|
new import_obsidian3.Setting(containerEl).setName(t("settings.cos.secret.id.name") + " *").setDesc(t("settings.cos.secret.id.desc")).addText((text) => text.setPlaceholder(t("settings.cos.secret.id.placeholder")).setValue(currentConfig.secretId).onChange(async (value) => {
|
|
this.plugin.updateCurrentCosConfig({ secretId: value });
|
|
await this.plugin.saveSettings();
|
|
}));
|
|
new import_obsidian3.Setting(containerEl).setName(t("settings.cos.secret.key.name") + " *").setDesc(t("settings.cos.secret.key.desc")).addText((text) => text.setPlaceholder(t("settings.cos.secret.key.placeholder")).setValue(currentConfig.secretKey).onChange(async (value) => {
|
|
this.plugin.updateCurrentCosConfig({ secretKey: value });
|
|
await this.plugin.saveSettings();
|
|
}));
|
|
new import_obsidian3.Setting(containerEl).setName(t("settings.cos.bucket.name") + " *").setDesc(t("settings.cos.bucket.desc")).addText((text) => text.setPlaceholder(t("settings.cos.bucket.placeholder")).setValue(currentConfig.bucket).onChange(async (value) => {
|
|
this.plugin.updateCurrentCosConfig({ bucket: value });
|
|
await this.plugin.saveSettings();
|
|
}));
|
|
new import_obsidian3.Setting(containerEl).setName(t("settings.cos.region.name") + " *").setDesc(t("settings.cos.region.desc")).addText((text) => text.setPlaceholder(t("settings.cos.region.placeholder")).setValue(currentConfig.region).onChange(async (value) => {
|
|
this.plugin.updateCurrentCosConfig({ region: value });
|
|
await this.plugin.saveSettings();
|
|
}));
|
|
if (this.plugin.settings.cosProvider === "cloudflare") {
|
|
new import_obsidian3.Setting(containerEl).setName(t("settings.cos.endpoint.name") + " *").setDesc(t("settings.cos.endpoint.desc")).addText((text) => text.setPlaceholder(t("settings.cos.endpoint.placeholder")).setValue(currentConfig.endpoint).onChange(async (value) => {
|
|
this.plugin.updateCurrentCosConfig({ endpoint: value });
|
|
await this.plugin.saveSettings();
|
|
}));
|
|
}
|
|
new import_obsidian3.Setting(containerEl).setName(t("settings.cos.cdn.name")).setDesc(t("settings.cos.cdn.desc")).addText((text) => text.setPlaceholder(t("settings.cos.cdn.placeholder")).setValue(currentConfig.cdnUrl).onChange(async (value) => {
|
|
this.plugin.updateCurrentCosConfig({ cdnUrl: value });
|
|
await this.plugin.saveSettings();
|
|
}));
|
|
new import_obsidian3.Setting(containerEl).setName(t("settings.cos.clear.name")).setDesc(t("settings.cos.clear.desc")).addButton((button) => button.setButtonText(t("settings.cos.clear.button")).setWarning().onClick(async () => {
|
|
this.plugin.clearCurrentCosConfig();
|
|
await this.plugin.saveSettings();
|
|
new import_obsidian3.Notice(t("settings.cos.clear.success"));
|
|
this.display();
|
|
}));
|
|
new import_obsidian3.Setting(containerEl).setName(t("settings.cos.test.name")).setDesc(t("settings.cos.test.desc")).addButton((button) => button.setButtonText(t("settings.cos.test.button")).onClick(async () => {
|
|
const requiredFields = [
|
|
currentConfig.secretId,
|
|
currentConfig.secretKey,
|
|
currentConfig.bucket,
|
|
currentConfig.region
|
|
// Region is required for all providers
|
|
];
|
|
if (this.plugin.settings.cosProvider === "cloudflare") {
|
|
requiredFields.push(currentConfig.endpoint);
|
|
}
|
|
if (requiredFields.some((field) => !field.trim())) {
|
|
new import_obsidian3.Notice(t("cos.error.config.invalid"));
|
|
return;
|
|
}
|
|
button.setButtonText(t("settings.cos.test.loading"));
|
|
button.setDisabled(true);
|
|
try {
|
|
const cosConfig = {
|
|
provider: this.plugin.settings.cosProvider,
|
|
secretId: currentConfig.secretId,
|
|
secretKey: currentConfig.secretKey,
|
|
bucket: currentConfig.bucket,
|
|
endpoint: currentConfig.endpoint,
|
|
cdnUrl: currentConfig.cdnUrl,
|
|
region: currentConfig.region
|
|
};
|
|
const cosService = new (await Promise.resolve().then(() => (init_cos_service(), cos_service_exports))).CosService(cosConfig);
|
|
const result = await cosService.testConnection();
|
|
if (result.success) {
|
|
new import_obsidian3.Notice(t("cos.test.success"));
|
|
} else {
|
|
new import_obsidian3.Notice(t("cos.test.failed", { error: result.message }));
|
|
}
|
|
} catch (error) {
|
|
console.error("COS test error:", error);
|
|
new import_obsidian3.Notice(t("cos.test.failed", { error: error.message }));
|
|
} finally {
|
|
button.setButtonText(t("settings.cos.test.button"));
|
|
button.setDisabled(false);
|
|
}
|
|
}));
|
|
containerEl.createEl("h3", {
|
|
text: t("settings.image.upload.section.title"),
|
|
cls: "git-sync-subsection-title"
|
|
});
|
|
new import_obsidian3.Setting(containerEl).setName(t("settings.cos.keep.local.name")).setDesc(t("settings.cos.keep.local.desc")).addToggle((toggle) => toggle.setValue(this.plugin.settings.keepLocalImages).onChange(async (value) => {
|
|
this.plugin.settings.keepLocalImages = value;
|
|
await this.plugin.saveSettings();
|
|
this.display();
|
|
}));
|
|
if (this.plugin.settings.keepLocalImages) {
|
|
new import_obsidian3.Setting(containerEl).setName(t("settings.cos.local.path.name")).setDesc(t("settings.cos.local.path.desc")).addText((text) => text.setPlaceholder(t("settings.cos.local.path.placeholder")).setValue(this.plugin.settings.localImagePath).onChange(async (value) => {
|
|
this.plugin.settings.localImagePath = value;
|
|
await this.plugin.saveSettings();
|
|
}));
|
|
}
|
|
new import_obsidian3.Setting(containerEl).setName(t("settings.cos.upload.path.name")).setDesc(t("settings.cos.upload.path.desc")).addText((text) => text.setPlaceholder(t("settings.cos.upload.path.placeholder")).setValue(this.plugin.settings.imageUploadPath).onChange(async (value) => {
|
|
this.plugin.settings.imageUploadPath = value;
|
|
await this.plugin.saveSettings();
|
|
}));
|
|
}
|
|
containerEl.createEl("h2", {
|
|
text: t("settings.danger.zone.title"),
|
|
cls: "danger-zone"
|
|
});
|
|
new import_obsidian3.Setting(containerEl).setName(t("settings.init.name")).setDesc(t("settings.init.desc")).addButton((button) => {
|
|
const isVaultEmpty = this.isVaultEmpty();
|
|
button.setButtonText(t("settings.init.button")).setDisabled(!isVaultEmpty).onClick(async () => {
|
|
if (!this.plugin.settings.githubToken || !this.plugin.settings.repositoryUrl) {
|
|
new import_obsidian3.Notice(t("notice.config.required"));
|
|
return;
|
|
}
|
|
button.setButtonText(t("settings.init.loading"));
|
|
button.setDisabled(true);
|
|
try {
|
|
const result = await this.plugin.initializeRepository();
|
|
if (result.success) {
|
|
new import_obsidian3.Notice(t("notice.result.with.count", { message: result.message, count: result.filesProcessed }));
|
|
} else {
|
|
new import_obsidian3.Notice(result.message);
|
|
}
|
|
} catch (error) {
|
|
new import_obsidian3.Notice(t("notice.init.error"));
|
|
} finally {
|
|
button.setButtonText(t("settings.init.button"));
|
|
button.setDisabled(!this.isVaultEmpty());
|
|
}
|
|
});
|
|
if (isVaultEmpty) {
|
|
button.setCta();
|
|
}
|
|
});
|
|
new import_obsidian3.Setting(containerEl).setName(t("settings.sync.remote.to.local.name")).setDesc(t("settings.sync.remote.to.local.desc")).addButton((button) => button.setButtonText(t("settings.sync.remote.to.local.button")).setWarning().onClick(async () => {
|
|
if (!this.plugin.settings.githubToken || !this.plugin.settings.repositoryUrl) {
|
|
new import_obsidian3.Notice(t("notice.config.required"));
|
|
return;
|
|
}
|
|
button.setButtonText(t("settings.sync.remote.to.local.loading"));
|
|
button.setDisabled(true);
|
|
try {
|
|
const result = await this.plugin.forceSyncRemoteToLocal();
|
|
if (result.success) {
|
|
new import_obsidian3.Notice(t("notice.result.with.count", { message: result.message, count: result.filesProcessed }));
|
|
} else {
|
|
new import_obsidian3.Notice(result.message);
|
|
}
|
|
} catch (error) {
|
|
new import_obsidian3.Notice(t("notice.sync.error"));
|
|
} finally {
|
|
button.setButtonText(t("settings.sync.remote.to.local.button"));
|
|
button.setDisabled(false);
|
|
}
|
|
}));
|
|
new import_obsidian3.Setting(containerEl).setName(t("settings.sync.local.to.remote.name")).setDesc(t("settings.sync.local.to.remote.desc")).addButton((button) => button.setButtonText(t("settings.sync.local.to.remote.button")).setWarning().onClick(async () => {
|
|
if (!this.plugin.settings.githubToken || !this.plugin.settings.repositoryUrl) {
|
|
new import_obsidian3.Notice(t("notice.config.required"));
|
|
return;
|
|
}
|
|
button.setButtonText(t("settings.sync.local.to.remote.loading"));
|
|
button.setDisabled(true);
|
|
try {
|
|
const result = await this.plugin.forceSyncLocalToRemote();
|
|
if (result.success) {
|
|
new import_obsidian3.Notice(t("notice.result.with.count", { message: result.message, count: result.filesProcessed }));
|
|
} else {
|
|
new import_obsidian3.Notice(result.message);
|
|
}
|
|
} catch (error) {
|
|
new import_obsidian3.Notice(t("notice.sync.error"));
|
|
} finally {
|
|
button.setButtonText(t("settings.sync.local.to.remote.button"));
|
|
button.setDisabled(false);
|
|
}
|
|
}));
|
|
new import_obsidian3.Setting(containerEl).setName(t("settings.clear.cache.name")).setDesc(t("settings.clear.cache.desc")).addButton((button) => button.setButtonText(t("settings.clear.cache.button")).onClick(async () => {
|
|
try {
|
|
const stats = this.plugin.fileCacheService.getCacheStats();
|
|
this.plugin.fileCacheService.clearCache();
|
|
new import_obsidian3.Notice(t("notice.cache.cleared", { count: stats.totalFiles }));
|
|
} catch (error) {
|
|
new import_obsidian3.Notice(t("notice.cache.clear.error"));
|
|
}
|
|
}));
|
|
containerEl.createEl("h2", {
|
|
text: t("settings.sponsor.section.title"),
|
|
cls: "sponsor"
|
|
});
|
|
const sponsorSection = containerEl.createEl("div", { cls: "setting-item" });
|
|
const sponsorInfo = sponsorSection.createEl("div", { cls: "setting-item-info" });
|
|
sponsorInfo.createEl("div", {
|
|
cls: "setting-item-name",
|
|
text: t("settings.sponsor.name")
|
|
});
|
|
sponsorInfo.createEl("div", {
|
|
cls: "setting-item-description",
|
|
text: t("settings.sponsor.desc")
|
|
});
|
|
const sponsorControl = sponsorSection.createEl("div", {
|
|
cls: getActualLanguage() === "zh" ? "setting-item-control git-sync-sponsor-control" : "setting-item-control"
|
|
});
|
|
const sponsorButton = sponsorControl.createEl("a", {
|
|
cls: "mod-cta",
|
|
text: t("settings.sponsor.button"),
|
|
href: "https://paypal.me/xheldoncao"
|
|
});
|
|
sponsorButton.style.textDecoration = "none";
|
|
sponsorButton.style.padding = "6px 12px";
|
|
sponsorButton.style.borderRadius = "3px";
|
|
sponsorButton.style.display = "inline-block";
|
|
if (getActualLanguage() === "zh") {
|
|
const chinaSponsorContainer = sponsorControl.createEl("div", {
|
|
cls: "git-sync-china-sponsor"
|
|
});
|
|
chinaSponsorContainer.createEl("span", {
|
|
text: t("settings.sponsor.china.label") + ": "
|
|
});
|
|
const chinaLink = chinaSponsorContainer.createEl("a", {
|
|
text: "https://www.xheldon.com/donate/",
|
|
href: "https://www.xheldon.com/donate/"
|
|
});
|
|
chinaLink.style.color = "var(--text-accent)";
|
|
chinaLink.style.textDecoration = "none";
|
|
}
|
|
}
|
|
isVaultEmpty() {
|
|
const files = this.app.vault.getFiles();
|
|
return files.filter((file) => !file.path.startsWith(".obsidian")).length === 0;
|
|
}
|
|
updatePathInfo(el, value) {
|
|
if (el) {
|
|
el.empty();
|
|
el.createEl("span", { text: this.getPathInfoText(value) });
|
|
}
|
|
}
|
|
getPathInfoText(value) {
|
|
if (!value) {
|
|
return t("path.info.empty");
|
|
}
|
|
const parseResult = this.plugin.githubService.parseRepositoryUrl(value);
|
|
if (parseResult) {
|
|
let pathInfo = t("path.info.sync.to", { owner: parseResult.owner, repo: parseResult.repo });
|
|
if (parseResult.path) {
|
|
pathInfo += t("path.info.folder", { path: parseResult.path });
|
|
} else {
|
|
pathInfo += t("path.info.root");
|
|
}
|
|
return pathInfo;
|
|
}
|
|
return t("path.info.error");
|
|
}
|
|
};
|
|
/*! Bundled license information:
|
|
|
|
is-plain-object/dist/is-plain-object.mjs:
|
|
(*!
|
|
* is-plain-object <https://github.com/jonschlinkert/is-plain-object>
|
|
*
|
|
* Copyright (c) 2014-2017, Jon Schlinkert.
|
|
* Released under the MIT License.
|
|
*)
|
|
*/
|