feat: add docs to main (#1559)
This commit is contained in:
5
.gitignore
vendored
5
.gitignore
vendored
@@ -32,3 +32,8 @@ olares-cli-*.tar.gz
|
||||
cli/output
|
||||
daemon/output
|
||||
daemon/bin
|
||||
|
||||
docs/.vitepress/dist/
|
||||
docs/.vitepress/cache/
|
||||
node_modules
|
||||
.idea/
|
||||
147
docs/.vitepress/config.mts
Normal file
147
docs/.vitepress/config.mts
Normal file
@@ -0,0 +1,147 @@
|
||||
import { defineConfig,UserConfig,DefaultTheme } from "vitepress";
|
||||
import { withMermaid } from "vitepress-plugin-mermaid";
|
||||
import { en } from "./en";
|
||||
import { zh } from "./zh";
|
||||
import _ from "lodash";
|
||||
//import defaultConfig from 'vitepress-versioning-plugin';
|
||||
|
||||
|
||||
|
||||
function defineVersionedConfig2(
|
||||
defaultConfig: UserConfig<DefaultTheme.Config>
|
||||
): UserConfig<DefaultTheme.Config> {
|
||||
let config = _.defaultsDeep(defaultConfig);
|
||||
|
||||
if( !process.env.BASE_URL || !process.env.VERSIONS || !process.env.LATEST_VERSION ) {
|
||||
return config;
|
||||
}
|
||||
|
||||
const versions = process.env.VERSIONS?.split(",");
|
||||
const latestVersion = process.env.LATEST_VERSION || versions![versions!.length - 1];
|
||||
console.log(versions, latestVersion);
|
||||
|
||||
for( const locale of Object.keys(config.locales) ) {
|
||||
let themeConfig = config.locales[locale]!.themeConfig!;
|
||||
|
||||
themeConfig?.nav?.push(
|
||||
{
|
||||
component: 'VersionSwitcher',
|
||||
// Optional props to pass to the component
|
||||
props: {
|
||||
versions,
|
||||
latestVersion,
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
return config;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// https://vitepress.dev/reference/site-config
|
||||
export default defineVersionedConfig2(withMermaid({
|
||||
title: "Olares",
|
||||
description: "Let people own their data again",
|
||||
lang: "en",
|
||||
locales: {
|
||||
root: {
|
||||
label: "English",
|
||||
...en,
|
||||
},
|
||||
zh: {
|
||||
label: "简体中文",
|
||||
...zh,
|
||||
},
|
||||
},
|
||||
themeConfig: {
|
||||
search: {
|
||||
provider: "algolia",
|
||||
options: {
|
||||
appId: "DZ6H2FVQGO",
|
||||
apiKey: "e5257d88b605dc0e5b82b12854aea9a5",
|
||||
indexName: "olares",
|
||||
searchParameters: {
|
||||
queryLanguages: ["zh", "en"],
|
||||
},
|
||||
locales: {
|
||||
zh: {
|
||||
placeholder: "搜索文档",
|
||||
translations: {
|
||||
button: {
|
||||
buttonText: "搜索文档",
|
||||
buttonAriaLabel: "搜索文档",
|
||||
},
|
||||
modal: {
|
||||
searchBox: {
|
||||
resetButtonTitle: "清除查询条件",
|
||||
resetButtonAriaLabel: "清除查询条件",
|
||||
cancelButtonText: "取消",
|
||||
cancelButtonAriaLabel: "取消",
|
||||
},
|
||||
startScreen: {
|
||||
recentSearchesTitle: "搜索历史",
|
||||
noRecentSearchesText: "没有搜索历史",
|
||||
saveRecentSearchButtonTitle: "保存至搜索历史",
|
||||
removeRecentSearchButtonTitle: "从搜索历史中移除",
|
||||
favoriteSearchesTitle: "收藏",
|
||||
removeFavoriteSearchButtonTitle: "从收藏中移除",
|
||||
},
|
||||
errorScreen: {
|
||||
titleText: "无法获取结果",
|
||||
helpText: "你可能需要检查你的网络连接",
|
||||
},
|
||||
footer: {
|
||||
selectText: "选择",
|
||||
navigateText: "切换",
|
||||
closeText: "关闭",
|
||||
searchByText: "搜索提供者",
|
||||
},
|
||||
noResultsScreen: {
|
||||
noResultsText: "无法找到相关结果",
|
||||
suggestedQueryText: "你可以尝试查询",
|
||||
reportMissingResultsText: "你认为该查询应该有结果?",
|
||||
reportMissingResultsLinkText: "点击反馈",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
sitemap: {
|
||||
hostname: "https://docs.olares.com/",
|
||||
},
|
||||
lastUpdated: true,
|
||||
base: process.env.BASE_URL || "/",
|
||||
vite: {
|
||||
build: {
|
||||
minify: "terser",
|
||||
chunkSizeWarningLimit: Infinity,
|
||||
},
|
||||
define: {
|
||||
'process.env.VERSIONS': JSON.stringify(process.env.VERSIONS || JSON.stringify([])),
|
||||
'process.env.LANGUAGES': JSON.stringify(process.env.LANGUAGES || JSON.stringify([])),
|
||||
}
|
||||
},
|
||||
head: [
|
||||
[
|
||||
"meta",
|
||||
{
|
||||
name: "google-site-verification",
|
||||
content: "3AzyPY6Q-LxE8CBNwz6ppsqDJ4iQaiPY9V0MHJbQlbU",
|
||||
},
|
||||
],
|
||||
// 引入 Material Design Icons
|
||||
[
|
||||
"link",
|
||||
{
|
||||
rel: "stylesheet",
|
||||
href: "https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:opsz,wght,FILL,GRAD@20..48,200,0..1,-50..200",
|
||||
},
|
||||
],
|
||||
],
|
||||
}));
|
||||
804
docs/.vitepress/en.ts
Normal file
804
docs/.vitepress/en.ts
Normal file
@@ -0,0 +1,804 @@
|
||||
import { defineConfig, type DefaultTheme } from "vitepress";
|
||||
|
||||
const side = {
|
||||
"/manual/": [
|
||||
{
|
||||
text: "What is Olares",
|
||||
link: "/manual/docs-home",
|
||||
items: [
|
||||
// A{ text: "Why Olares", link: "/manual/why-olares" },
|
||||
//{ text: "Feature comparison", link: "/manual/feature-overview" },
|
||||
{ text: "Olares architecture", link: "/manual/system-architecture" },
|
||||
{ text: "Compare Olares and NAS", link: "/manual/olares-vs-nas" },
|
||||
{
|
||||
text: "Help and support",
|
||||
collapsed: true,
|
||||
items: [
|
||||
{ text: "FAQs", link: "/manual/help/faqs" },
|
||||
{
|
||||
text: "Request support",
|
||||
link: "/manual/help/request-technical-support",
|
||||
},
|
||||
//{
|
||||
// text: "Troubleshooting Guide",
|
||||
// link: "/manual/help/troubleshooting-guide",
|
||||
// },
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
text: "Get started",
|
||||
collapsed: false,
|
||||
link: "/manual/get-started/",
|
||||
items: [
|
||||
// { text: "Quick start", link: "/manual/get-started/quick-start" },
|
||||
{
|
||||
text: "Create an Olares ID",
|
||||
link: "/manual/get-started/create-olares-id",
|
||||
},
|
||||
{
|
||||
text: "Install Olares",
|
||||
link: "/manual/get-started/install-olares",
|
||||
},
|
||||
{
|
||||
text: "Back up mnemonics",
|
||||
link: "/manual/larepass/back-up-mnemonics"
|
||||
},
|
||||
{
|
||||
text: "What's next",
|
||||
link: "/manual/get-started/next-steps",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
text: "LarePass",
|
||||
link: "/manual/larepass/",
|
||||
collapsed: true,
|
||||
items: [
|
||||
{
|
||||
text: "Manage accounts",
|
||||
collapsed: true,
|
||||
items: [
|
||||
{text: "Create accounts", link:"/manual/larepass/create-account"},
|
||||
{text: "Back up mnemonics", link: "/manual/larepass/back-up-mnemonics"},
|
||||
{text: "Manage integrations", link:"/manual/larepass/integrations"},
|
||||
],
|
||||
},
|
||||
{text: "Manage VPN", link:"/manual/larepass/private-network"},
|
||||
{
|
||||
text: "Manage device",
|
||||
collapsed: true,
|
||||
items: [
|
||||
{text: "Activate Olares", link:"/manual/larepass/activate-olares"},
|
||||
{text: "Manage Olares", link:"/manual/larepass/manage-olares"},
|
||||
],
|
||||
},
|
||||
{
|
||||
text: "Manage files",
|
||||
collapsed: true,
|
||||
items: [
|
||||
{text: "Common file operations", link:"/manual/larepass/manage-files"},
|
||||
{text: "Sync and share", link:"/manual/larepass/sync-share"}
|
||||
]
|
||||
},
|
||||
{
|
||||
text: "Manage passwords",
|
||||
collapsed: true,
|
||||
items: [
|
||||
{text: "Autofill passwords", link: "/manual/larepass/autofill"},
|
||||
{text: "Generate 2FA codes", link: "/manual/larepass/two-factor-verification"},
|
||||
],
|
||||
},
|
||||
{
|
||||
text: "Manage knowledge",
|
||||
link: "/manual/larepass/manage-knowledge",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
text: "Olares applications",
|
||||
collapsed: true,
|
||||
link: "/manual/olares/",
|
||||
items: [
|
||||
{ text: "Desktop", link: "/manual/olares/desktop", },
|
||||
{ text: "Market", link: "/manual/olares/market", },
|
||||
{
|
||||
text: "Files",
|
||||
collapsed: true,
|
||||
link: "/manual/olares/files/",
|
||||
items: [
|
||||
{
|
||||
text: "Basic file operations",
|
||||
link: "/manual/olares/files/add-edit-download",
|
||||
},
|
||||
{
|
||||
text: "Sync and share",
|
||||
link: "/manual/larepass/sync-share",
|
||||
},
|
||||
{
|
||||
text: "Mount SMB",
|
||||
link: "/manual/olares/files/mount-SMB",
|
||||
},
|
||||
{text: "Mount cloud storage",
|
||||
link: "/manual/olares/files/mount-cloud-storage",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
text: "Vault",
|
||||
collapsed: true,
|
||||
link: "/manual/olares/vault/",
|
||||
items: [
|
||||
{
|
||||
text: "Manage vault items",
|
||||
link: "/manual/olares/vault/vault-items",
|
||||
},
|
||||
{
|
||||
text: "Manage shared vault",
|
||||
link: "/manual/olares/vault/share-vault-items",
|
||||
},
|
||||
{
|
||||
text: "Autofill",
|
||||
link: "/manual/larepass/autofill",
|
||||
},
|
||||
{
|
||||
text: "Generate 2FA codes",
|
||||
link: "/manual/larepass/two-factor-verification",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
text: "Wise",
|
||||
collapsed: true,
|
||||
link: "/manual/olares/wise/",
|
||||
items: [
|
||||
{
|
||||
text: "Basic operations",
|
||||
link: "/manual/olares/wise/basics",
|
||||
},
|
||||
{
|
||||
text: "Get recommendation engine",
|
||||
link: "/manual/olares/wise/recommend",
|
||||
},
|
||||
{
|
||||
text: "Manage your feeds",
|
||||
link: "/manual/olares/wise/subscribe",
|
||||
},
|
||||
{
|
||||
text: "Organize your knowledge",
|
||||
link: "/manual/olares/wise/filter",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
text: "Control Hub",
|
||||
collapsed: true,
|
||||
link: "/manual/olares/controlhub/",
|
||||
items: [
|
||||
{
|
||||
text: "Navigate Control Hub",
|
||||
link: "/manual/olares/controlhub/navigate-control-hub",
|
||||
},
|
||||
{
|
||||
text: "Edit system resource",
|
||||
link: "/manual/olares/controlhub/edit-resource",
|
||||
},
|
||||
{
|
||||
text: "View container status",
|
||||
link: "/manual/olares/controlhub/view-container",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
text: "Settings",
|
||||
collapsed: true,
|
||||
link: "/manual/olares/settings/",
|
||||
items: [
|
||||
{
|
||||
text: "My Olares",
|
||||
collapsed: true,
|
||||
items: [
|
||||
{text: "Account and device", link: "/manual/olares/settings/my-olares"},
|
||||
{text: "Update system", link: "/manual/olares/settings/update"},
|
||||
],
|
||||
},
|
||||
{
|
||||
text: "Manage accounts",
|
||||
collapsed: true,
|
||||
items: [
|
||||
{
|
||||
text: "Roles and permissions",
|
||||
link: "/manual/olares/settings/roles-permissions",
|
||||
},
|
||||
{
|
||||
text: "Create member accounts",
|
||||
link: "/manual/olares/settings/manage-team",
|
||||
}
|
||||
],
|
||||
},
|
||||
{
|
||||
text: "Manage applications",
|
||||
collapsed: true,
|
||||
items: [
|
||||
{
|
||||
text: "Manage app entrance",
|
||||
link: "/manual/olares/settings/manage-entrance",
|
||||
},
|
||||
{
|
||||
text: "Customize app domains",
|
||||
link: "/manual/olares/settings/custom-app-domain",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
text: "Manage integrations",
|
||||
link:"/manual/olares/settings/integrations",
|
||||
},
|
||||
{
|
||||
text: "Customize appearance",
|
||||
link:"/manual/olares/settings/language-appearance",
|
||||
},
|
||||
{text: "Manage VPN", link: "/manual/olares/settings/remote-access",},
|
||||
{
|
||||
text: "Configure network",
|
||||
collapsed: true,
|
||||
items: [
|
||||
{
|
||||
text: "Change revere proxy",
|
||||
link: "/manual/olares/settings/change-frp",
|
||||
},
|
||||
{
|
||||
text: "Set up hosts file",
|
||||
link:"/manual/olares/settings/set-up-hosts",
|
||||
},
|
||||
],
|
||||
},
|
||||
{text: "Manage GPU", link: "/manual/olares/settings/gpu-resource",},
|
||||
{
|
||||
text: "Backup and restore",
|
||||
collapsed: true,
|
||||
items: [
|
||||
{text: "Backup", link: "/manual/olares/settings/backup"},
|
||||
{text: "Restore", link: "/manual/olares/settings/restore"},
|
||||
],
|
||||
},
|
||||
{text: "Developer resources", link: "/manual/olares/settings/developer"},
|
||||
]
|
||||
},
|
||||
{text: "Dashboard", link: "/manual/olares/resources-usage"},
|
||||
{text: "Profile", link: "/manual/olares/profile"},
|
||||
],
|
||||
},
|
||||
{
|
||||
text: "Best practices",
|
||||
link: "/manual/best-practices/",
|
||||
collapsed: true,
|
||||
items: [
|
||||
{
|
||||
text: "Set up custom domain",
|
||||
link: "/manual/best-practices/set-custom-domain",
|
||||
},
|
||||
{
|
||||
text: "Manage knowledge with Wise",
|
||||
link: "/manual/best-practices/organize-content",
|
||||
},
|
||||
{
|
||||
text: "Install a multi-node Olares cluster",
|
||||
link: "/manual/best-practices/install-olares-multi-node",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
text: "Concepts",
|
||||
collapsed: true,
|
||||
link: "/manual/concepts/",
|
||||
items: [
|
||||
{ text: "Architecture", link: "/manual/concepts/architecture" },
|
||||
{ text:
|
||||
"Olares ID",
|
||||
link: "/manual/concepts/olares-id",
|
||||
collapsed: true,
|
||||
items: [
|
||||
{
|
||||
text: "Decentralized ID",
|
||||
link: "/manual/concepts/did",
|
||||
},
|
||||
{
|
||||
text: "Blockchain Registry",
|
||||
link: "/manual/concepts/registry",
|
||||
},
|
||||
{
|
||||
text: "Verifiable Credential",
|
||||
link: "/manual/concepts/vc",
|
||||
},
|
||||
{
|
||||
text: "Autonomous Reputation",
|
||||
link: "/manual/concepts/reputation",
|
||||
},
|
||||
{
|
||||
text: "Self-Sovereign Network",
|
||||
link: "/manual/concepts/self-sovereign-network",
|
||||
},
|
||||
{
|
||||
text: "Identity Wallet",
|
||||
link: "/manual/concepts/wallet",
|
||||
},
|
||||
],
|
||||
},
|
||||
{ text: "Account", link: "/manual/concepts/account" },
|
||||
{ text: "Application", link: "/manual/concepts/application" },
|
||||
{ text: "Network", link: "/manual/concepts/network" },
|
||||
{ text: "Data", link: "/manual/concepts/data" },
|
||||
{ text: "Secrets", link: "/manual/concepts/secrets" },
|
||||
],
|
||||
},
|
||||
{ text: "Glossary", link: "/manual/glossary" },
|
||||
],
|
||||
"/space/": [
|
||||
{
|
||||
text: "Olares Space",
|
||||
link: "/space/",
|
||||
items: [
|
||||
{
|
||||
text: "Manage accounts",
|
||||
link: "/space/manage-accounts",
|
||||
},
|
||||
{
|
||||
text: "Host Olares",
|
||||
collapsed: true,
|
||||
items: [
|
||||
{
|
||||
text: "Create Olares",
|
||||
link: "/space/create-olares",
|
||||
},
|
||||
{
|
||||
text: "Manage Olares",
|
||||
link: "/space/manage-olares",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
text: "Host domains",
|
||||
collapsed: true,
|
||||
items: [
|
||||
{
|
||||
text: "Set up a custom domain",
|
||||
link: "/space/host-domain",
|
||||
},
|
||||
{
|
||||
text: "Manage a domain",
|
||||
link: "/space/manage-domain",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
text: "Back up and restore",
|
||||
link: "/space/backup-restore",
|
||||
},
|
||||
{ text: "Billing", link: "/space/billing" },
|
||||
],
|
||||
},
|
||||
],
|
||||
"/use-cases/": [
|
||||
{
|
||||
text: "Tutorials & use cases",
|
||||
link: "/use-cases/",
|
||||
items: [
|
||||
{
|
||||
text: "Stable Diffusion",
|
||||
link: "/use-cases/stable-diffusion",
|
||||
},
|
||||
{
|
||||
text: "ComfyUI",
|
||||
link: "/use-cases/comfyui",
|
||||
collapsed: true,
|
||||
items: [
|
||||
{
|
||||
text: "Manage ComfyUI",
|
||||
link: "/use-cases/comfyui-launcher",
|
||||
},
|
||||
{
|
||||
text: "Use ComfyUI for Krita",
|
||||
link: "/use-cases/comfyui-for-krita",
|
||||
},
|
||||
]
|
||||
},
|
||||
{
|
||||
text: "Ollama",
|
||||
link: "/use-cases/ollama",
|
||||
},
|
||||
{
|
||||
text: "Open WebUI",
|
||||
link: "/use-cases/openwebui",
|
||||
},
|
||||
{
|
||||
text: "Perplexica",
|
||||
link: "/use-cases/perplexica",
|
||||
},
|
||||
{
|
||||
text: "Dify",
|
||||
link: "/use-cases/dify",
|
||||
},
|
||||
{
|
||||
text: "Jellyfin",
|
||||
link: "/use-cases/stream-media",
|
||||
},
|
||||
{
|
||||
text: "Steam",
|
||||
link: "/use-cases/stream-game",
|
||||
},
|
||||
{
|
||||
text: "Redroid",
|
||||
link: "/use-cases/host-cloud-android",
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
"/developer/": [
|
||||
{
|
||||
text: "Installation deep-dives",
|
||||
link: "/developer/install/",
|
||||
items: [
|
||||
{
|
||||
text: "Installation architecture",
|
||||
link: "/developer/install/installation-overview",
|
||||
},
|
||||
{
|
||||
text: "Installation process",
|
||||
link: "/developer/install/installation-process",
|
||||
},
|
||||
{
|
||||
text: "Olares Home",
|
||||
link: "/developer/install/olares-home",
|
||||
},
|
||||
{
|
||||
text: "Environment variables",
|
||||
link: "/developer/install/environment-variables",
|
||||
},
|
||||
{
|
||||
text: "Olares CLI",
|
||||
link: "/developer/install/cli/olares-cli",
|
||||
collapsed: true,
|
||||
items: [
|
||||
{ text: "gpu", link: "/developer/install/cli/gpu" },
|
||||
{ text: "osinfo", link: "/developer/install/cli/osinfo" },
|
||||
{ text: "node", link: "/developer/install/cli/node" },
|
||||
{
|
||||
text: "backups",
|
||||
link: "/developer/install/cli/backups",
|
||||
collapsed: true,
|
||||
items: [
|
||||
{text: "download", link: "/developer/install/cli/backups-download"},
|
||||
{text: "region", link: "/developer/install/cli/backups-region"},
|
||||
{text: "backup", link: "/developer/install/cli/backups-backup"},
|
||||
{text: "restore", link: "/developer/install/cli/backups-restore"},
|
||||
{text: "snapshots", link: "/developer/install/cli/backups-snapshots"},
|
||||
],
|
||||
},
|
||||
{
|
||||
text: "change-ip",
|
||||
link: "/developer/install/cli/change-ip",
|
||||
},
|
||||
{
|
||||
text: "download",
|
||||
link: "/developer/install/cli/download",
|
||||
},
|
||||
{ text: "info", link: "/developer/install/cli/info" },
|
||||
{
|
||||
text: "install",
|
||||
link: "/developer/install/cli/install",
|
||||
},
|
||||
{
|
||||
text: "logs",
|
||||
link: "/developer/install/cli/logs",
|
||||
},
|
||||
{
|
||||
text: "precheck",
|
||||
link: "/developer/install/cli/precheck",
|
||||
},
|
||||
{
|
||||
text: "prepare",
|
||||
link: "/developer/install/cli/prepare",
|
||||
},
|
||||
{
|
||||
text: "release",
|
||||
link: "/developer/install/cli/release",
|
||||
},
|
||||
{
|
||||
text: "start",
|
||||
link: "/developer/install/cli/start",
|
||||
},
|
||||
{
|
||||
text: "stop",
|
||||
link: "/developer/install/cli/stop",
|
||||
},
|
||||
{
|
||||
text: "uninstall",
|
||||
link: "/developer/install/cli/uninstall",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
text: "Olares versioning",
|
||||
link: "/developer/install/versioning",
|
||||
},
|
||||
],
|
||||
},
|
||||
// {
|
||||
// text: "Additional installations",
|
||||
// link: "/developer/install/additional-installations",
|
||||
// collapsed: true,
|
||||
// items: [
|
||||
// { text: "Linux (via Docker)", link: "/developer/install/linux-via-docker-compose"},
|
||||
// {
|
||||
// text: "macOS",
|
||||
// collapsed: true,
|
||||
// items: [
|
||||
// {
|
||||
// text: "Using the script (recommended)",
|
||||
// link: "/developer/install/mac",
|
||||
// },
|
||||
// {
|
||||
// text: "Using Docker image",
|
||||
// link: "/developer/install/mac-via-docker-image",
|
||||
// },
|
||||
// ],
|
||||
// },
|
||||
// {
|
||||
// text: "Windows (WSL 2)",
|
||||
// collapsed: true,
|
||||
// items: [
|
||||
// {
|
||||
// text: "Using the script (recommended)",
|
||||
// link: "/developer/install/windows",
|
||||
// },
|
||||
// {
|
||||
// text: "Using Docker image",
|
||||
// link: "/developer/install/windows-via-docker-image",
|
||||
// },
|
||||
// ],
|
||||
// },
|
||||
// { text: "PVE", link: "/developer/install/pve" },
|
||||
// { text: "LXC", link: "/developer/install/lxc" },
|
||||
// { text: "Raspberry Pi", link: "/developer/install/raspberry-pi" },
|
||||
// ],
|
||||
// },
|
||||
{
|
||||
text: "Develop Olares app",
|
||||
link: "/developer/develop/",
|
||||
items: [
|
||||
{
|
||||
text: "Tutorial",
|
||||
collapsed: true,
|
||||
link: "/developer/develop/tutorial/",
|
||||
items: [
|
||||
{
|
||||
text: "Learn Studio",
|
||||
link: "/developer/develop/tutorial/studio",
|
||||
},
|
||||
{
|
||||
text: "Create your first app",
|
||||
collapsed: true,
|
||||
link: "/developer/develop/tutorial/note/",
|
||||
items: [
|
||||
{
|
||||
text: "1. Create app",
|
||||
link: "/developer/develop/tutorial/note/create",
|
||||
},
|
||||
{
|
||||
text: "2. Develop backend",
|
||||
link: "/developer/develop/tutorial/note/backend",
|
||||
},
|
||||
{
|
||||
text: "3. Develop frontend",
|
||||
link: "/developer/develop/tutorial/note/frontend",
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
text: "Application package",
|
||||
collapsed: true,
|
||||
items: [
|
||||
{
|
||||
text: "Application chart",
|
||||
link: "/developer/develop/package/chart",
|
||||
},
|
||||
{
|
||||
text: "OlaresManifest",
|
||||
link: "/developer/develop/package/manifest",
|
||||
},
|
||||
{
|
||||
text: "Recommendation",
|
||||
link: "/developer/develop/package/recommend",
|
||||
},
|
||||
{
|
||||
text: "Helm extension",
|
||||
link: "/developer/develop/package/extension",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
text: "Advanced",
|
||||
collapsed: true,
|
||||
items: [
|
||||
{
|
||||
text: "terminus-info",
|
||||
link: "/developer/develop/advanced/terminus-info",
|
||||
},
|
||||
{
|
||||
text: "Service provider",
|
||||
link: "/developer/develop/advanced/provider",
|
||||
},
|
||||
{
|
||||
text: "AI",
|
||||
link: "/developer/develop/advanced/ai",
|
||||
},
|
||||
{ text: "Cookie", link: "/developer/develop/advanced/cookie" },
|
||||
{ text: "Database", link: "/developer/develop/advanced/database" },
|
||||
{
|
||||
text: "Account",
|
||||
link: "/developer/develop/advanced/account",
|
||||
},
|
||||
{
|
||||
text: "Market",
|
||||
link: "/developer/develop/advanced/market",
|
||||
},
|
||||
{
|
||||
text: "Websocket",
|
||||
link: "/developer/develop/advanced/websocket",
|
||||
},
|
||||
{
|
||||
text: "File upload",
|
||||
link: "/developer/develop/advanced/file-upload",
|
||||
},
|
||||
{
|
||||
text: "Secret",
|
||||
link: "/developer/develop/advanced/secret",
|
||||
},
|
||||
{
|
||||
text: "Kubesphere",
|
||||
link: "/developer/develop/advanced/kubesphere",
|
||||
},
|
||||
],
|
||||
},
|
||||
|
||||
{
|
||||
text: "Submit application",
|
||||
collapsed: true,
|
||||
link: "/developer/develop/submit/",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
text: "Contribute to Olares",
|
||||
items: [
|
||||
{
|
||||
text: "Develop system app",
|
||||
collapsed: true,
|
||||
items: [
|
||||
{
|
||||
text: "Overview",
|
||||
link: "/developer/contribute/system-app/overview",
|
||||
},
|
||||
{
|
||||
text: "Configure deployment",
|
||||
link: "/developer/contribute/system-app/deployment",
|
||||
},
|
||||
{
|
||||
text: "Configure permissions",
|
||||
link: "/developer/contribute/system-app/olares-manifest",
|
||||
},
|
||||
{
|
||||
text: "Install",
|
||||
link: "/developer/contribute/system-app/install",
|
||||
},
|
||||
{
|
||||
text: "Other",
|
||||
link: "/developer/contribute/system-app/other",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
text: "Develop protocols",
|
||||
collapsed: true,
|
||||
items: [
|
||||
{
|
||||
text: "Contract",
|
||||
link: "/developer/contribute/olares-id/contract/contract",
|
||||
collapsed: true,
|
||||
items: [
|
||||
{
|
||||
text: "Architecture",
|
||||
link: "/developer/contribute/olares-id/contract/architecture",
|
||||
},
|
||||
{
|
||||
text: "DID",
|
||||
collapsed: true,
|
||||
items: [
|
||||
{
|
||||
text: "Design",
|
||||
link: "/developer/contribute/olares-id/contract/did/design",
|
||||
},
|
||||
{
|
||||
text: "Official Taggers",
|
||||
link: "/developer/contribute/olares-id/contract/did/official-taggers",
|
||||
},
|
||||
{
|
||||
text: "Release History",
|
||||
link: "/developer/contribute/olares-id/contract/did/release-history",
|
||||
},
|
||||
{
|
||||
text: "FAQ",
|
||||
link: "/developer/contribute/olares-id/contract/did/faq",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
text: "Reputation",
|
||||
link: "/developer/contribute/olares-id/contract/contract-reputation",
|
||||
},
|
||||
{
|
||||
text: "Manage",
|
||||
collapsed: true,
|
||||
items: [
|
||||
{
|
||||
text: "Contract",
|
||||
link: "/developer/contribute/olares-id/contract/manage/contract",
|
||||
},
|
||||
{
|
||||
text: "SDK",
|
||||
link: "/developer/contribute/olares-id/contract/manage/sdk",
|
||||
},
|
||||
{
|
||||
text: "Environment",
|
||||
link: "/developer/contribute/olares-id/contract/manage/environment",
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
text: "Verifiable Credential",
|
||||
link: "/developer/contribute/olares-id/verifiable-credential/overview",
|
||||
collapsed: true,
|
||||
items: [
|
||||
{
|
||||
text: "Issuer",
|
||||
link: "/developer/contribute/olares-id/verifiable-credential/issuer",
|
||||
},
|
||||
{
|
||||
text: "Verifer",
|
||||
link: "/developer/contribute/olares-id/verifiable-credential/verifer",
|
||||
},
|
||||
{
|
||||
text: "Olares",
|
||||
link: "/developer/contribute/olares-id/verifiable-credential/olares",
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
export const en = defineConfig({
|
||||
lang: "en",
|
||||
themeConfig: {
|
||||
//logo: "/icon.png",
|
||||
socialLinks: [{ icon: "github", link: "https://github.com/beclab/olares" }],
|
||||
|
||||
nav: [
|
||||
{ text: "Olares", link: "/manual/docs-home" },
|
||||
{ text: "Olares Space", link: "/space/" },
|
||||
{ text: "Use Cases", link: "/use-cases/" },
|
||||
{ text: "Developer Guide", link: "/developer/install/" },
|
||||
],
|
||||
|
||||
sidebar: side,
|
||||
},
|
||||
});
|
||||
108
docs/.vitepress/theme/components/FilterableList.vue
Normal file
108
docs/.vitepress/theme/components/FilterableList.vue
Normal file
@@ -0,0 +1,108 @@
|
||||
<template>
|
||||
<div class="filterable-list">
|
||||
<!-- Tag filters -->
|
||||
<div class="filters">
|
||||
<label
|
||||
v-for="(tag, index) in uniqueTags"
|
||||
:key="index"
|
||||
class="filter-label"
|
||||
>
|
||||
<input
|
||||
type="checkbox"
|
||||
:value="tag"
|
||||
v-model="selectedTags"
|
||||
/>
|
||||
{{ tag }}
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<!-- List of items -->
|
||||
<ul>
|
||||
<li v-for="(item, index) in filteredItems" :key="index">
|
||||
<a
|
||||
:href="item.link"
|
||||
:target="isExternalLink(item.link) ? '_blank' : '_self'"
|
||||
:rel="isExternalLink(item.link) ? 'noopener noreferrer' : ''"
|
||||
>
|
||||
{{ item.title }}
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'FilterableList',
|
||||
props: {
|
||||
items: {
|
||||
type: Array,
|
||||
required: true,
|
||||
// Example structure of items:
|
||||
// [
|
||||
// { title: 'Guide 1', link: '/guide1.md', tags: ['tag1', 'tag2'] },
|
||||
// { title: 'Guide 2', link: '/guide2.md', tags: ['tag2', 'tag3'] },
|
||||
// ...
|
||||
// ]
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
selectedTags: [] // Stores the currently selected tags for filtering
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
// Compute the unique tags from the items
|
||||
uniqueTags() {
|
||||
const allTags = this.items.flatMap(item => item.tags)
|
||||
return [...new Set(allTags)]
|
||||
},
|
||||
// Filtered list based on selected tags
|
||||
filteredItems() {
|
||||
if (this.selectedTags.length === 0) {
|
||||
return this.items // No filtering if no tags are selected
|
||||
}
|
||||
return this.items.filter(item =>
|
||||
item.tags.some(tag => this.selectedTags.includes(tag))
|
||||
)
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
// Check if the link is external by looking for 'http' or 'https'
|
||||
isExternalLink(link) {
|
||||
return /^(http|https):\/\//.test(link)
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
/* Simple styling for the filterable list */
|
||||
.filterable-list {
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
.filters {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.filter-label {
|
||||
margin-right: 10px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
ul {
|
||||
list-style: none;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
ul li {
|
||||
margin: 10px 0;
|
||||
}
|
||||
|
||||
ul li a {
|
||||
text-decoration: none;
|
||||
color: var(--vp-c-link);
|
||||
}
|
||||
|
||||
</style>
|
||||
90
docs/.vitepress/theme/components/LaunchCard.vue
Normal file
90
docs/.vitepress/theme/components/LaunchCard.vue
Normal file
@@ -0,0 +1,90 @@
|
||||
<template>
|
||||
<div class="launch-card">
|
||||
<div class="card-content">
|
||||
<h2>
|
||||
{{ title }}
|
||||
<a :href="'#' + slugify(title)" aria-hidden="true" class="anchor-link">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" fill="currentColor" width="24" height="24" viewBox="0 0 24 24">
|
||||
<path d="M0 0h24v24H0z" fill="none"></path>
|
||||
<path d="M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76 0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71 0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71 0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76 0 5-2.24 5-5s-2.24-5-5-5z"></path>
|
||||
</svg>
|
||||
</a>
|
||||
</h2>
|
||||
<p>{{ description }}</p>
|
||||
<ul>
|
||||
<li v-for="(link, index) in links" :key="index">
|
||||
<a :href="link.href">{{ link.text }}</a>
|
||||
</li>
|
||||
</ul>
|
||||
<button class="portal-button" :id="'btn-' + slugify(title)" @click="navigate">
|
||||
{{ buttonText }}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
props: {
|
||||
title: String,
|
||||
description: String,
|
||||
links: Array,
|
||||
buttonText: String,
|
||||
buttonLink: String
|
||||
},
|
||||
methods: {
|
||||
slugify(text) {
|
||||
return text.toLowerCase().replace(/\s+/g, '-');
|
||||
},
|
||||
navigate() {
|
||||
window.location.href = this.buttonLink;
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.launch-card-container {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 1rem;
|
||||
}
|
||||
|
||||
.launch-card {
|
||||
flex: 1 1 calc(33.333% - 1rem);
|
||||
margin-bottom: 1rem;
|
||||
display: flex;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.card-content {
|
||||
padding: 1rem;
|
||||
}
|
||||
|
||||
.card-content h2 {
|
||||
border: none;
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
.anchor-link {
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
h2:hover .anchor-link {
|
||||
visibility: visible;
|
||||
}
|
||||
|
||||
.portal-button {
|
||||
background-color: #ec6464;
|
||||
color: white;
|
||||
border: none;
|
||||
padding: 0.5rem 1rem;
|
||||
border-radius: 4px;
|
||||
cursor: pointer;
|
||||
margin-top: 1rem;
|
||||
}
|
||||
|
||||
.portal-button:hover {
|
||||
background-color: #ec5a68;
|
||||
}
|
||||
</style>
|
||||
24
docs/.vitepress/theme/components/Layout.vue
Normal file
24
docs/.vitepress/theme/components/Layout.vue
Normal file
@@ -0,0 +1,24 @@
|
||||
<!-- docs/.vitepress/theme/Layout.vue -->
|
||||
<script setup lang="ts">
|
||||
import DefaultTheme from "vitepress/theme";
|
||||
import { useData } from "vitepress";
|
||||
import { watchEffect } from "vue";
|
||||
|
||||
const { lang } = useData();
|
||||
watchEffect(() => {
|
||||
if (typeof window !== "undefined") {
|
||||
document.cookie = `nf_lang=${lang.value}; expires=Mon, 1 Jan 2030 00:00:00 UTC; path=/`;
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<DefaultTheme.Layout />
|
||||
</template>
|
||||
|
||||
<style>
|
||||
.medium-zoom-overlay,
|
||||
.medium-zoom-image {
|
||||
z-index: 9999 !important;
|
||||
}
|
||||
</style>
|
||||
97
docs/.vitepress/theme/components/OStabs.vue
Normal file
97
docs/.vitepress/theme/components/OStabs.vue
Normal file
@@ -0,0 +1,97 @@
|
||||
<template>
|
||||
<div class="os-tabs">
|
||||
<button
|
||||
v-for="tab in tabs"
|
||||
:key="tab.id"
|
||||
:class="{ active: currentTab === tab.id }"
|
||||
@click="handleTabClick(tab)"
|
||||
>
|
||||
{{ tab.label }}
|
||||
</button>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
props: {
|
||||
defaultTab: {
|
||||
type: String,
|
||||
default: "linux", // Default tab if no match is found
|
||||
},
|
||||
tabs: {
|
||||
type: Array,
|
||||
required: true,
|
||||
// Expected format:
|
||||
// [
|
||||
// { id: "linux", label: "Linux", href: "/docs/linux" },
|
||||
// { id: "macos", label: "Mac", href: "/docs/macos" },
|
||||
// { id: "windows", label: "Windows", href: "/docs/windows" }
|
||||
// ]
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
currentTab: this.defaultTab, // Active tab starts with the defaultTab
|
||||
};
|
||||
},
|
||||
mounted() {
|
||||
this.setCurrentTabBasedOnURL(); // Set the active tab based on the current URL
|
||||
},
|
||||
methods: {
|
||||
handleTabClick(tab) {
|
||||
if (tab.href) {
|
||||
// Redirect to the tab's URL (full page reload)
|
||||
window.location.assign(tab.href);
|
||||
} else {
|
||||
// Otherwise, just switch the active tab locally
|
||||
this.currentTab = tab.id;
|
||||
}
|
||||
},
|
||||
setCurrentTabBasedOnURL() {
|
||||
// Get the current URL path
|
||||
const currentPath = window.location.pathname;
|
||||
|
||||
// Match the current path with the `href` of the tabs
|
||||
const matchingTab = this.tabs.find((tab) => tab.href === currentPath);
|
||||
|
||||
if (matchingTab) {
|
||||
this.currentTab = matchingTab.id; // Set the matching tab as active
|
||||
} else {
|
||||
// Fallback to the default tab if no match is found
|
||||
this.currentTab = this.defaultTab;
|
||||
}
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.os-tabs {
|
||||
display: flex;
|
||||
margin-top: 1rem;
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
.os-tabs button {
|
||||
flex: 1;
|
||||
padding: 0.5rem 1rem;
|
||||
background-color: var(--vp-c-bg);
|
||||
color: var(--vp-c-text-primary);
|
||||
border: none;
|
||||
cursor: pointer;
|
||||
text-align: center;
|
||||
transition: background-color 0.3s, color 0.3s, border-bottom 0.3s;
|
||||
border-bottom: 2px solid transparent;
|
||||
}
|
||||
|
||||
.os-tabs button.active {
|
||||
background-color: var(--vp-c-surface);
|
||||
color: var(--vp-c-brand);
|
||||
border-bottom-color: var(--vp-c-brand);
|
||||
}
|
||||
|
||||
.os-tabs button:hover {
|
||||
background-color: var(--vp-c-surface);
|
||||
color: var(--vp-c-brand);
|
||||
}
|
||||
</style>
|
||||
195
docs/.vitepress/theme/components/VersionSwitcher.vue
Normal file
195
docs/.vitepress/theme/components/VersionSwitcher.vue
Normal file
@@ -0,0 +1,195 @@
|
||||
<script setup lang="ts">
|
||||
import { useData, useRouter,inBrowser } from "vitepress"
|
||||
import { computed, ref } from 'vue'
|
||||
import VPMenuLink from 'vitepress/dist/client/theme-default/components/VPMenuLink.vue'
|
||||
import VPFlyout from 'vitepress/dist/client/theme-default/components/VPFlyout.vue'
|
||||
|
||||
const props = defineProps<{
|
||||
versions: string[]
|
||||
latestVersion: string
|
||||
}>();
|
||||
|
||||
const router = useRouter();
|
||||
const { site } = useData();
|
||||
|
||||
const localUrl = computed(() => {
|
||||
let url = "/";
|
||||
if( inBrowser ) {
|
||||
url = window.location.href.split('/').slice(0,3).join('/');
|
||||
if( !url.endsWith('/') ) {
|
||||
url = url + '/';
|
||||
}
|
||||
}
|
||||
|
||||
//console.log('localUrl', url);
|
||||
return url;
|
||||
});
|
||||
|
||||
const currentVersion = computed(() => {
|
||||
let version = props.latestVersion;
|
||||
|
||||
for (const v of props.versions) {
|
||||
const u = `/${v}/`;
|
||||
// console.log('u', u);
|
||||
// console.log('router.route.path', router.route.path);
|
||||
if (router.route.path.startsWith(u)) {
|
||||
//console.log('match version', v);
|
||||
version = v;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return version;
|
||||
});
|
||||
|
||||
const customLink = (path) => path.replace(site.value.base || '', '');
|
||||
|
||||
const isOpen = ref(false);
|
||||
const toggle = () => {
|
||||
isOpen.value = !isOpen.value;
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<VPFlyout class="VPVersionSwitcher" icon="vpi-versioning" :button="currentVersion"
|
||||
:label="'Switch Version'">
|
||||
<div class="items">
|
||||
<!-- <VPMenuLink v-if="currentVersion != latestVersion" :item="{
|
||||
text: latestVersion,
|
||||
link: `/`,
|
||||
}" /> -->
|
||||
<template v-for="version in versions" :key="version">
|
||||
<!-- <VPMenuLink v-if="currentVersion != version" :item="{
|
||||
text: version,
|
||||
link: `${localUrl}${version}/`,
|
||||
target: '_blank',
|
||||
rel: 'a'
|
||||
}" /> -->
|
||||
<a v-if="currentVersion != version" :href="`${localUrl}${version}/`" target="_blank">{{ version }}</a>
|
||||
</template>
|
||||
</div>
|
||||
</VPFlyout>
|
||||
|
||||
</template>
|
||||
|
||||
<style>
|
||||
.vpi-versioning.option-icon {
|
||||
margin-right: 2px !important;
|
||||
}
|
||||
|
||||
.vpi-versioning {
|
||||
--icon: url("data:image/svg+xml;charset=utf-8;base64,PHN2ZyB3aWR0aD0iNjRweCIgaGVpZ2h0PSI2NHB4IiB2aWV3Qm94PSIwIDAgMjQgMjQiIHN0cm9rZS13aWR0aD0iMi4yIiBmaWxsPSJub25lIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIGNvbG9yPSIjMDAwMDAwIj48cGF0aCBkPSJNMTcgN0MxOC4xMDQ2IDcgMTkgNi4xMDQ1NyAxOSA1QzE5IDMuODk1NDMgMTguMTA0NiAzIDE3IDNDMTUuODk1NCAzIDE1IDMuODk1NDMgMTUgNUMxNSA2LjEwNDU3IDE1Ljg5NTQgNyAxNyA3WiIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjIuMiIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIiBzdHJva2UtbGluZWpvaW49InJvdW5kIj48L3BhdGg+PHBhdGggZD0iTTcgN0M4LjEwNDU3IDcgOSA2LjEwNDU3IDkgNUM5IDMuODk1NDMgOC4xMDQ1NyAzIDcgM0M1Ljg5NTQzIDMgNSAzLjg5NTQzIDUgNUM1IDYuMTA0NTcgNS44OTU0MyA3IDcgN1oiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIyLjIiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIgc3Ryb2tlLWxpbmVqb2luPSJyb3VuZCI+PC9wYXRoPjxwYXRoIGQ9Ik03IDIxQzguMTA0NTcgMjEgOSAyMC4xMDQ2IDkgMTlDOSAxNy44OTU0IDguMTA0NTcgMTcgNyAxN0M1Ljg5NTQzIDE3IDUgMTcuODk1NCA1IDE5QzUgMjAuMTA0NiA1Ljg5NTQzIDIxIDcgMjFaIiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMi4yIiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS1saW5lam9pbj0icm91bmQiPjwvcGF0aD48cGF0aCBkPSJNNyA3VjE3IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMi4yIiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS1saW5lam9pbj0icm91bmQiPjwvcGF0aD48cGF0aCBkPSJNMTcgN1Y4QzE3IDEwLjUgMTUgMTEgMTUgMTFMOSAxM0M5IDEzIDcgMTMuNSA3IDE2VjE3IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMi4yIiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS1saW5lam9pbj0icm91bmQiPjwvcGF0aD48L3N2Zz4=")
|
||||
}
|
||||
</style>
|
||||
|
||||
<style scoped>
|
||||
.VPVersionSwitcher {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
|
||||
|
||||
.icon {
|
||||
padding: 8px;
|
||||
}
|
||||
|
||||
.title {
|
||||
padding: 0 24px 0 12px;
|
||||
line-height: 32px;
|
||||
font-size: 14px;
|
||||
font-weight: 700;
|
||||
color: var(--vp-c-text-1);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
.VPScreenVersionSwitcher {
|
||||
border-bottom: 1px solid var(--vp-c-divider);
|
||||
height: 48px;
|
||||
overflow: hidden;
|
||||
transition: border-color 0.5s;
|
||||
}
|
||||
|
||||
.VPVersionSwitcher a {
|
||||
display: block;
|
||||
border-radius: 6px;
|
||||
padding: 0 12px;
|
||||
line-height: 32px;
|
||||
font-size: 14px;
|
||||
font-weight: 500;
|
||||
color: var(--vp-c-text-1);
|
||||
white-space: nowrap;
|
||||
transition:
|
||||
background-color 0.25s,
|
||||
color 0.25s;
|
||||
}
|
||||
|
||||
.VPVersionSwitcher a:hover {
|
||||
color: var(--vp-c-brand-1);
|
||||
background-color: var(--vp-c-default-soft);
|
||||
}
|
||||
|
||||
.VPVersionSwitcher a.active {
|
||||
color: var(--vp-c-brand-1);
|
||||
}
|
||||
|
||||
|
||||
.VPScreenVersionSwitcher .items {
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
.VPScreenVersionSwitcher.open .items {
|
||||
visibility: visible;
|
||||
}
|
||||
|
||||
.VPScreenVersionSwitcher.open {
|
||||
padding-bottom: 10px;
|
||||
height: auto;
|
||||
}
|
||||
|
||||
.VPScreenVersionSwitcher.open .button {
|
||||
padding-bottom: 6px;
|
||||
color: var(--vp-c-brand-1);
|
||||
}
|
||||
|
||||
.VPScreenVersionSwitcher.open .button-icon {
|
||||
/*rtl:ignore*/
|
||||
transform: rotate(45deg);
|
||||
}
|
||||
|
||||
.VPScreenVersionSwitcher button .icon {
|
||||
margin-right: 8px;
|
||||
}
|
||||
|
||||
.button {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 12px 4px 11px 0;
|
||||
width: 100%;
|
||||
line-height: 24px;
|
||||
font-size: 14px;
|
||||
font-weight: 500;
|
||||
color: var(--vp-c-text-1);
|
||||
transition: color 0.25s;
|
||||
}
|
||||
|
||||
.button:hover {
|
||||
color: var(--vp-c-brand-1);
|
||||
}
|
||||
|
||||
.button-icon {
|
||||
transition: transform 0.25s;
|
||||
}
|
||||
|
||||
.group:first-child {
|
||||
padding-top: 0px;
|
||||
}
|
||||
|
||||
.group+.group,
|
||||
.group+.item {
|
||||
padding-top: 4px;
|
||||
}
|
||||
</style>
|
||||
122
docs/.vitepress/theme/components/tabs.vue
Normal file
122
docs/.vitepress/theme/components/tabs.vue
Normal file
@@ -0,0 +1,122 @@
|
||||
<template>
|
||||
<div class="tabs-container">
|
||||
<slot></slot>
|
||||
<div class="tabs">
|
||||
<button
|
||||
v-for="(tab, index) in tabLabels"
|
||||
:key="tab"
|
||||
@click="clickHandler(tab, index)"
|
||||
:class="{ active: activeTab === tab }"
|
||||
>
|
||||
<div class="tabs-item-wrapper">
|
||||
<img
|
||||
:src="iconFilter(index)"
|
||||
class="tabs-img-wrapper"
|
||||
alt=""
|
||||
v-if="iconFilter(index)"
|
||||
/>
|
||||
<span> {{ tab }}</span>
|
||||
</div>
|
||||
</button>
|
||||
</div>
|
||||
<div v-for="tab in tabLabels" :key="tab" v-show="activeTab === tab">
|
||||
<div v-if="activeTab === tab" class="tab-item">
|
||||
<slot :name="tabSlots[tab]"></slot>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
props: {
|
||||
isDark: {
|
||||
type: Boolean,
|
||||
},
|
||||
icons: {
|
||||
type: Array,
|
||||
default: [],
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
activeTab: null,
|
||||
tabLabels: [],
|
||||
tabSlots: {},
|
||||
randomKey: Math.random(),
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
clickHandler(tab, index) {
|
||||
this.activeTab = tab;
|
||||
this.$emit("tab-changed", tab, index);
|
||||
},
|
||||
iconFilter(index) {
|
||||
if (this.icons[index]) {
|
||||
return this.isDark
|
||||
? `/images/manual/icons/${this.icons[index]}-dark.svg`
|
||||
: `/images/manual/icons/${this.icons[index]}.svg`;
|
||||
}
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
// Map slot names to display labels
|
||||
const slots = Object.keys(this.$slots).filter((slot) => slot !== "default");
|
||||
this.tabSlots = slots.reduce((map, slot) => {
|
||||
const label = slot.replace(/-/g, " "); // Replace hyphens with spaces
|
||||
map[label] = slot;
|
||||
return map;
|
||||
}, {});
|
||||
console.log("aa", this.tabSlots);
|
||||
|
||||
this.tabLabels = Object.keys(this.tabSlots);
|
||||
this.activeTab = this.tabLabels[0];
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.tabs {
|
||||
display: flex;
|
||||
background-color: var(--vp-c-bg);
|
||||
}
|
||||
|
||||
.tabs button {
|
||||
flex: 1;
|
||||
padding: 0.5rem 1rem;
|
||||
border: none;
|
||||
background-color: var(--vp-c-bg);
|
||||
color: var(--vp-c-text-primary);
|
||||
cursor: pointer;
|
||||
transition: background-color 0.3s, color 0.3s;
|
||||
border-bottom: 2px solid transparent;
|
||||
}
|
||||
|
||||
.tabs button.active {
|
||||
background-color: var(--vp-c-surface);
|
||||
color: var(--vp-c-brand);
|
||||
border-bottom-color: var(--vp-c-brand);
|
||||
}
|
||||
|
||||
.tabs button:hover {
|
||||
background-color: var(--vp-c-surface);
|
||||
color: var(--vp-c-brand);
|
||||
}
|
||||
|
||||
div[style] {
|
||||
color: var(--vp-c-text-primary);
|
||||
}
|
||||
.tabs-img-wrapper {
|
||||
width: 12px;
|
||||
pointer-events: none;
|
||||
}
|
||||
.tabs-item-wrapper {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
}
|
||||
.tabs-container .tab-item {
|
||||
margin-top: 16px;
|
||||
}
|
||||
</style>
|
||||
139
docs/.vitepress/theme/index.ts
Normal file
139
docs/.vitepress/theme/index.ts
Normal file
@@ -0,0 +1,139 @@
|
||||
// docs/.vitepress/theme/index.ts
|
||||
import DefaultTheme from "vitepress/theme";
|
||||
import "./styles/custom.css";
|
||||
import "./styles/index.css";
|
||||
import { inBrowser, useRoute, useRouter, useData } from "vitepress";
|
||||
import Layout from "./components/Layout.vue";
|
||||
import { injectSpeedInsights } from "@vercel/speed-insights";
|
||||
import { inject } from "@vercel/analytics";
|
||||
import { App } from "vue";
|
||||
import Tabs from "./components/tabs.vue";
|
||||
import LaunchCard from "./components/LaunchCard.vue";
|
||||
import FilterableList from "./components/FilterableList.vue";
|
||||
import { onMounted, watch, nextTick, onBeforeMount,computed } from "vue";
|
||||
import mediumZoom from "medium-zoom";
|
||||
import OSTabs from "./components/OStabs.vue";
|
||||
import VersionSwitcher from "./components/VersionSwitcher.vue";
|
||||
import _ from "lodash";
|
||||
|
||||
const LANGUAGE_ZH_PATH = "/zh/";
|
||||
const LANGUAGE_ZH_KEY = "zh";
|
||||
const LANGUAGE_EN_KEY = "en";
|
||||
|
||||
const LANGUAGE_LOCAL_KEY = "language";
|
||||
let isMenuChange = false;
|
||||
|
||||
export default {
|
||||
extends: DefaultTheme,
|
||||
Layout,
|
||||
enhanceApp({ app }: { app: App }) {
|
||||
app.component("Tabs", Tabs);
|
||||
app.component("LaunchCard", LaunchCard);
|
||||
app.component("FilterableList", FilterableList);
|
||||
app.component("OSTabs", OSTabs);
|
||||
app.component("VersionSwitcher", VersionSwitcher);
|
||||
},
|
||||
|
||||
setup() {
|
||||
const route = useRoute();
|
||||
const router = useRouter();
|
||||
const { lang } = useData();
|
||||
|
||||
const routerRedirect = () => {
|
||||
let localLanguage = localStorage.getItem(LANGUAGE_LOCAL_KEY) || 'en';
|
||||
|
||||
const versions = process.env.VERSIONS!.split(",") ||[];
|
||||
versions.push('default');
|
||||
|
||||
const languages = process.env.LANGUAGES!.split(",") || [];
|
||||
languages.push('en');
|
||||
console.log(versions, languages,localLanguage)
|
||||
|
||||
if(!languages?.includes(localLanguage) ){
|
||||
localLanguage = 'en';
|
||||
}
|
||||
|
||||
|
||||
const currentPath = router.route.path;
|
||||
|
||||
console.log('router.route.path', router.route.path);
|
||||
for( const l of languages ) {
|
||||
let localLanguagePath = (l === 'en' ? '' : `/${l}`);
|
||||
for (const v of versions) {
|
||||
let localVersionPath = (v === 'default' ? '' : `/${v}`);
|
||||
const u = `${localVersionPath}${localLanguagePath}`;
|
||||
console.log('checkPrefix', u);
|
||||
if (currentPath.startsWith(u)) {
|
||||
console.log('find localLanguage', localLanguage, l);
|
||||
if( l !== localLanguage ) {
|
||||
let targetLanguagePath = (localLanguage === 'en' ? '' : `/${localLanguage}`);
|
||||
const nextUrl = `${localVersionPath}${targetLanguagePath}${route.path.replace(u, '')}`;
|
||||
router.go(nextUrl);
|
||||
}
|
||||
return;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const initZoom = () => {
|
||||
mediumZoom(".main img", { background: "var(--vp-c-bg)" });
|
||||
};
|
||||
|
||||
const toggleMenuStatus = () => {
|
||||
const menuDom = document.querySelector(".menu .VPMenu");
|
||||
menuDom?.addEventListener("click", (e) => {
|
||||
const target = e.target as Element;
|
||||
const isLink = target.closest(".VPMenuLink");
|
||||
if (isLink) {
|
||||
isMenuChange = true;
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
if (inBrowser) {
|
||||
routerRedirect();
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
toggleMenuStatus();
|
||||
inject();
|
||||
injectSpeedInsights();
|
||||
initZoom();
|
||||
|
||||
document
|
||||
.querySelector(".wrapper .container a.title")
|
||||
?.setAttribute("href", "https://www.olares.com/");
|
||||
|
||||
document
|
||||
.querySelector(".wrapper .container a.title")
|
||||
?.setAttribute("target", "_blank");
|
||||
});
|
||||
|
||||
watch(
|
||||
() => lang.value,
|
||||
(newValue) => {
|
||||
localStorage.setItem(LANGUAGE_LOCAL_KEY, newValue);
|
||||
isMenuChange = false;
|
||||
}
|
||||
);
|
||||
|
||||
watch(
|
||||
() => route.path,
|
||||
() => {
|
||||
nextTick(() => {
|
||||
initZoom();
|
||||
|
||||
document
|
||||
.querySelector(".wrapper .container a.title")
|
||||
?.setAttribute("href", "https://www.olares.com/");
|
||||
|
||||
document
|
||||
.querySelector(".wrapper .container a.title")
|
||||
?.setAttribute("target", "_blank");
|
||||
});
|
||||
}
|
||||
);
|
||||
},
|
||||
};
|
||||
64
docs/.vitepress/theme/styles/cta-container.css
Normal file
64
docs/.vitepress/theme/styles/cta-container.css
Normal file
@@ -0,0 +1,64 @@
|
||||
.cta-container {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 1rem;
|
||||
margin-top: 2rem;
|
||||
}
|
||||
|
||||
.cta-link {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
flex: 1 1 calc(33.333% - 1rem);
|
||||
padding: 1rem;
|
||||
text-decoration: none;
|
||||
border-radius: 8px;
|
||||
transition: box-shadow 0.3s ease, transform 0.3s ease;
|
||||
color: #333;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.cta-link:hover {
|
||||
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);
|
||||
transform: translateY(-2px);
|
||||
}
|
||||
|
||||
.cta-title {
|
||||
font-size: 20px;
|
||||
line-height: 1.4;
|
||||
letter-spacing: -0.02em;
|
||||
margin-bottom: 0.75em;
|
||||
color: #ec5b68;
|
||||
}
|
||||
|
||||
.cta-description {
|
||||
margin-bottom: 0;
|
||||
color: #757575;
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.cta-link {
|
||||
flex: 1 1 calc(50% - 1rem);
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 480px) {
|
||||
.cta-link {
|
||||
flex: 1 1 100%;
|
||||
}
|
||||
}
|
||||
|
||||
:root.dark {
|
||||
.cta-link {
|
||||
background-color: #222;
|
||||
color: #f5f5f5;
|
||||
}
|
||||
|
||||
.cta-title {
|
||||
color: #ff6f61;
|
||||
}
|
||||
|
||||
.cta-description {
|
||||
color: #aaa;
|
||||
}
|
||||
}
|
||||
71
docs/.vitepress/theme/styles/cta.css
Normal file
71
docs/.vitepress/theme/styles/cta.css
Normal file
@@ -0,0 +1,71 @@
|
||||
.cta {
|
||||
margin: 2rem 0;
|
||||
border-radius: 8px;
|
||||
overflow: hidden;
|
||||
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.cta:hover {
|
||||
transform: translateY(-2px);
|
||||
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.15);
|
||||
}
|
||||
|
||||
.cta a {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 1rem 1.5rem;
|
||||
background-color: #f5f5f5;
|
||||
color: #333;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.cta a:hover {
|
||||
color: #333; /* 保持颜色不变 /
|
||||
text-decoration: none; / 移除可能的下划线 */
|
||||
}
|
||||
|
||||
.cta .content {
|
||||
flex-grow: 1;
|
||||
}
|
||||
|
||||
.cta h3 {
|
||||
margin: 0;
|
||||
font-size: 1rem;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.cta p {
|
||||
margin: 0.25rem 0 0;
|
||||
font-size: 0.9rem;
|
||||
opacity: 0.7;
|
||||
}
|
||||
|
||||
.cta .arrow {
|
||||
font-size: 1.5rem;
|
||||
font-weight: bold;
|
||||
margin-left: 1rem;
|
||||
color: #666;
|
||||
}
|
||||
|
||||
.cta a:hover .arrow {
|
||||
color: #666; /* 保持箭头颜色不变 */
|
||||
}
|
||||
|
||||
:root.dark {
|
||||
.cta a {
|
||||
background-color: #222;
|
||||
color: #f5f5f5;
|
||||
}
|
||||
.cta a:hover {
|
||||
background-color: #333;
|
||||
color: #fff;
|
||||
}
|
||||
.cta .arrow {
|
||||
color: #ccc;
|
||||
}
|
||||
.cta a:hover .arrow {
|
||||
color: #fff;
|
||||
}
|
||||
}
|
||||
8
docs/.vitepress/theme/styles/custom.css
Normal file
8
docs/.vitepress/theme/styles/custom.css
Normal file
@@ -0,0 +1,8 @@
|
||||
/* 只影响文档正文里的表格 */
|
||||
.vp-doc table td:nth-child(2),
|
||||
.vp-doc table th:nth-child(2) {
|
||||
white-space: nowrap; /* 第二列不换行 */
|
||||
}
|
||||
|
||||
/* 若想让整张表放宽布局,顺便改一下 ↓ */
|
||||
/* .vp-doc table { table-layout: auto; } */
|
||||
8
docs/.vitepress/theme/styles/image.css
Normal file
8
docs/.vitepress/theme/styles/image.css
Normal file
@@ -0,0 +1,8 @@
|
||||
img[src*="bordered"] {
|
||||
display: block;
|
||||
margin-top: 0.5em;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
box-shadow: 0px 8px 15px rgba(0, 0, 0, 0.2), 0px 4px 6px rgba(0, 0, 0, 0.15);
|
||||
border-radius: 4px;
|
||||
}
|
||||
5
docs/.vitepress/theme/styles/index.css
Normal file
5
docs/.vitepress/theme/styles/index.css
Normal file
@@ -0,0 +1,5 @@
|
||||
@import "./links.css";
|
||||
@import "./cta.css";
|
||||
@import "./cta-container.css";
|
||||
@import "./image.css";
|
||||
|
||||
8
docs/.vitepress/theme/styles/links.css
Normal file
8
docs/.vitepress/theme/styles/links.css
Normal file
@@ -0,0 +1,8 @@
|
||||
:root {
|
||||
--vp-c-brand: #646cff;
|
||||
--vp-c-brand-light: #747bff;
|
||||
}
|
||||
|
||||
.vp-doc a {
|
||||
text-decoration: none;
|
||||
}
|
||||
826
docs/.vitepress/zh.ts
Normal file
826
docs/.vitepress/zh.ts
Normal file
@@ -0,0 +1,826 @@
|
||||
import { defineConfig, type DefaultTheme } from "vitepress";
|
||||
|
||||
const side = {
|
||||
"/zh/manual/": [
|
||||
{
|
||||
text: "文档站",
|
||||
link: "/zh/manual/docs-home",
|
||||
items: [
|
||||
// { text: "应用场景", link: "/zh/manual/why-olares" },
|
||||
//{ text: "功能对比", link: "/zh/manual/feature-overview" },
|
||||
{ text: "系统架构", link: "/zh/manual/system-architecture" },
|
||||
{ text: "比较 Olares 和 NAS", link: "/zh/manual/olares-vs-nas" },
|
||||
{
|
||||
text: "帮助与支持",
|
||||
collapsed: true,
|
||||
items: [
|
||||
{ text: "常见问题", link: "/zh/manual/help/faqs" },
|
||||
{
|
||||
text: "技术支持",
|
||||
link: "/zh/manual/help/request-technical-support",
|
||||
},
|
||||
// {
|
||||
// text: "Troubleshooting Guide",
|
||||
// link: "/zh/manual/help/troubleshooting-guide",
|
||||
// },
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
text: "快速开始",
|
||||
collapsed: false,
|
||||
link: "/zh/manual/get-started/",
|
||||
items: [
|
||||
// { text: "Quick start", link: "/zh/manual/get-started/quick-start" },
|
||||
{
|
||||
text: "创建 Olares ID",
|
||||
link: "/zh/manual/get-started/create-olares-id",
|
||||
},
|
||||
{
|
||||
text: "安装激活",
|
||||
link: "/zh/manual/get-started/install-olares",
|
||||
},
|
||||
{
|
||||
text: "备份助记词",
|
||||
link: "/zh/manual/larepass/back-up-mnemonics",
|
||||
},
|
||||
{
|
||||
text: "探索",
|
||||
link: "/zh/manual/get-started/next-steps",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
text: "LarePass",
|
||||
link: "/zh/manual/larepass/",
|
||||
collapsed: true,
|
||||
items: [
|
||||
{
|
||||
text: "管理账户",
|
||||
collapsed: true,
|
||||
items: [
|
||||
{text: "创建账户", link:"/zh/manual/larepass/create-account"},
|
||||
{text: "备份助记词", link: "/zh/manual/larepass/back-up-mnemonics"},
|
||||
{text: "管理集成", link:"/zh/manual/larepass/integrations"},
|
||||
],
|
||||
},
|
||||
{text: "管理专用网络", link:"/zh/manual/larepass/private-network"},
|
||||
{
|
||||
text: "管理设备",
|
||||
collapsed: true,
|
||||
items: [
|
||||
{text: "激活 Olares", link:"/zh/manual/larepass/activate-olares"},
|
||||
{text: "管理 Olares", link:"/zh/manual/larepass/manage-olares"},
|
||||
],
|
||||
},
|
||||
{
|
||||
text: "管理文件",
|
||||
collapsed: true,
|
||||
items: [
|
||||
{text: "常用文件操作", link:"/zh/manual/larepass/manage-files"},
|
||||
{text: "同步与共享", link:"/zh/manual/larepass/sync-share"}
|
||||
]
|
||||
},
|
||||
{
|
||||
text: "管理密码",
|
||||
collapsed: true,
|
||||
items: [
|
||||
{text: "自动填充", link: "/zh/manual/larepass/autofill"},
|
||||
{text: "双重验证", link: "/zh/manual/larepass/two-factor-verification"},
|
||||
],
|
||||
},
|
||||
{
|
||||
text: "管理内容",
|
||||
link: "/zh/manual/larepass/manage-knowledge",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
"text": "Olares 应用",
|
||||
"collapsed": true,
|
||||
"link": "/zh/manual/olares/",
|
||||
"items": [
|
||||
{ "text": "桌面", "link": "/zh/manual/olares/desktop" },
|
||||
{ "text": "应用市场", "link": "/zh/manual/olares/market" },
|
||||
{
|
||||
"text": "文件管理器",
|
||||
"collapsed": true,
|
||||
"link": "/zh/manual/olares/files/",
|
||||
"items": [
|
||||
{
|
||||
"text": "基本文件操作",
|
||||
"link": "/zh/manual/olares/files/add-edit-download"
|
||||
},
|
||||
{
|
||||
"text": "同步与共享",
|
||||
"link": "/zh/manual/larepass/sync-share"
|
||||
},
|
||||
{
|
||||
"text": "挂载 SMB",
|
||||
"link": "/zh/manual/olares/files/mount-SMB"
|
||||
},
|
||||
{
|
||||
"text": "挂载云存储",
|
||||
"link": "/zh/manual/olares/files/mount-cloud-storage"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"text": "Vault",
|
||||
"collapsed": true,
|
||||
"link": "/zh/manual/olares/vault/",
|
||||
"items": [
|
||||
{
|
||||
"text": "管理 Vault 项目",
|
||||
"link": "/zh/manual/olares/vault/vault-items"
|
||||
},
|
||||
{
|
||||
"text": "管理共享 Vault",
|
||||
"link": "/zh/manual/olares/vault/share-vault-items"
|
||||
},
|
||||
{
|
||||
"text": "自动填充",
|
||||
"link": "/zh/manual/larepass/autofill"
|
||||
},
|
||||
{
|
||||
"text": "双因素验证",
|
||||
"link": "/zh/manual/larepass/two-factor-verification"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"text": "Wise",
|
||||
"collapsed": true,
|
||||
"link": "/zh/manual/olares/wise/",
|
||||
"items": [
|
||||
{
|
||||
"text": "基本操作",
|
||||
"link": "/zh/manual/olares/wise/basics"
|
||||
},
|
||||
{
|
||||
"text": "获取推荐引擎",
|
||||
"link": "/zh/manual/olares/wise/recommend"
|
||||
},
|
||||
{
|
||||
"text": "管理订阅",
|
||||
"link": "/zh/manual/olares/wise/subscribe"
|
||||
},
|
||||
{
|
||||
"text": "整理知识",
|
||||
"link": "/zh/manual/olares/wise/filter"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"text": "控制面板",
|
||||
"collapsed": true,
|
||||
"link": "/zh/manual/olares/controlhub/",
|
||||
"items": [
|
||||
{
|
||||
"text": "熟悉控制面板",
|
||||
"link": "/zh/manual/olares/controlhub/navigate-control-hub"
|
||||
},
|
||||
{
|
||||
"text": "编辑系统资源",
|
||||
"link": "/zh/manual/olares/controlhub/edit-resource"
|
||||
},
|
||||
{
|
||||
"text": "查看容器状态",
|
||||
"link": "/zh/manual/olares/controlhub/view-container"
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
"text": "设置",
|
||||
"collapsed": true,
|
||||
"link": "/zh/manual/olares/settings/",
|
||||
"items": [
|
||||
{
|
||||
"text": "我的 Olares",
|
||||
"collapsed": true,
|
||||
"items": [
|
||||
{text: "账户与设备", link: "/zh/manual/olares/settings/my-olares"},
|
||||
{text: "更新系统", link: "/zh/manual/olares/settings/update"},
|
||||
],
|
||||
},
|
||||
{
|
||||
"text": "管理账户",
|
||||
"collapsed": true,
|
||||
"items": [
|
||||
{
|
||||
"text": "角色与权限",
|
||||
"link": "/zh/manual/olares/settings/roles-permissions",
|
||||
},
|
||||
{
|
||||
"text": "创建成员账户",
|
||||
"link": "/zh/manual/olares/settings/manage-team",
|
||||
}
|
||||
],
|
||||
},
|
||||
{
|
||||
"text": "管理应用",
|
||||
"collapsed": true,
|
||||
"items": [
|
||||
{
|
||||
"text": "管理应用入口",
|
||||
"link": "/zh/manual/olares/settings/manage-entrance",
|
||||
},
|
||||
{
|
||||
"text": "自定义应用域名",
|
||||
"link": "/zh/manual/olares/settings/custom-app-domain",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
"text": "管理集成",
|
||||
"link":"/zh/manual/olares/settings/integrations",
|
||||
},
|
||||
{
|
||||
"text": "自定义外观",
|
||||
"link":"/zh/manual/olares/settings/language-appearance",
|
||||
},
|
||||
{text: "管理 VPN", link: "/zh/manual/olares/settings/remote-access",},
|
||||
{
|
||||
"text": "配置网络",
|
||||
"collapsed": true,
|
||||
"items": [
|
||||
{
|
||||
"text": "更改反向代理",
|
||||
"link": "/zh/manual/olares/settings/change-frp",
|
||||
},
|
||||
{
|
||||
"text": "设置 hosts 文件",
|
||||
"link":"/zh/manual/olares/settings/set-up-hosts",
|
||||
},
|
||||
],
|
||||
},
|
||||
{text: "管理 GPU", link: "/zh/manual/olares/settings/gpu-resource",},
|
||||
{
|
||||
"text": "备份与恢复",
|
||||
"collapsed": true,
|
||||
"items": [
|
||||
{text: "备份", link: "/zh/manual/olares/settings/backup"},
|
||||
{text: "恢复", link: "/zh/manual/olares/settings/restore"},
|
||||
],
|
||||
},
|
||||
{text: "开发者资源", link: "/zh/manual/olares/settings/developer"},
|
||||
]
|
||||
},
|
||||
{ "text": "仪表盘", "link": "/zh/manual/olares/resources-usage" },
|
||||
{ "text": "Profile", "link": "/zh/manual/olares/profile" }
|
||||
]
|
||||
},
|
||||
{
|
||||
text: "Olares 进阶",
|
||||
collapsed: true,
|
||||
link: "/zh/manual/best-practices/",
|
||||
items: [
|
||||
{
|
||||
text: "设置自定义域名",
|
||||
link: "/zh/manual/best-practices/set-custom-domain",
|
||||
},
|
||||
{
|
||||
text: "使用 Wise 管理知识",
|
||||
link: "/zh/manual/best-practices/organize-content",
|
||||
},
|
||||
{
|
||||
text: "安装多节点",
|
||||
link: "/zh/manual/best-practices/install-olares-multi-node",
|
||||
},
|
||||
{
|
||||
text: "设置 SMTP",
|
||||
link: "/zh/manual/best-practices/set-up-SMTP-service",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
text: "概念",
|
||||
collapsed: true,
|
||||
link: "/zh/manual/concepts/",
|
||||
items: [
|
||||
{ text: "架构", link: "/zh/manual/concepts/architecture" },
|
||||
{ text: "Olares ID",
|
||||
link: "/zh/manual/concepts/olares-id",
|
||||
collapsed: true,
|
||||
items: [
|
||||
{
|
||||
text: "去中心化标识符",
|
||||
link: "/zh/manual//concepts/did",
|
||||
},
|
||||
{
|
||||
text: "DID Registry",
|
||||
link: "/zh/manual//concepts/registry",
|
||||
},
|
||||
{
|
||||
text: "可验证凭证",
|
||||
link: "/zh/manual//concepts/vc",
|
||||
},
|
||||
{
|
||||
text: "自治声誉",
|
||||
link: "/zh/manual//concepts/reputation",
|
||||
},
|
||||
{
|
||||
text: "主权网络",
|
||||
link: "/zh/manual//concepts/self-sovereign-network",
|
||||
},
|
||||
{
|
||||
text: "身份钱包",
|
||||
link: "/zh/manual/concepts/wallet",
|
||||
},
|
||||
],
|
||||
|
||||
},
|
||||
{ text: "账户", link: "/zh/manual/concepts/account" },
|
||||
{ text: "应用", link: "/zh/manual/concepts/application" },
|
||||
{ text: "网络", link: "/zh/manual/concepts/network" },
|
||||
{ text: "数据", link: "/zh/manual/concepts/data" },
|
||||
{ text: "密钥", link: "/zh/manual/concepts/secrets" },
|
||||
],
|
||||
},
|
||||
{ text: "术语", link: "/zh/manual/glossary" },
|
||||
],
|
||||
"/zh/space/": [
|
||||
{
|
||||
text: "Olares Space",
|
||||
link: "/zh/space/",
|
||||
collapsed: true,
|
||||
items: [
|
||||
{
|
||||
text: "管理账号",
|
||||
link: "/zh/space/manage-accounts",
|
||||
},
|
||||
{
|
||||
text: "托管 Olares",
|
||||
collapsed: true,
|
||||
items: [
|
||||
{
|
||||
text: "创建 Olares",
|
||||
link: "/zh/space/create-olares",
|
||||
},
|
||||
{
|
||||
text: "管理 Olares",
|
||||
link: "/zh/space/manage-olares",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
text: "托管域名",
|
||||
collapsed: true,
|
||||
items: [
|
||||
{
|
||||
text: "设置自定义域名",
|
||||
link: "/zh/space/host-domain",
|
||||
},
|
||||
{
|
||||
text: "管理域名",
|
||||
link: "/zh/space/manage-domain",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
text: "备份与恢复",
|
||||
link: "/zh/space/backup-restore",
|
||||
},
|
||||
{ text: "计费", link: "/zh/space/billing" },
|
||||
],
|
||||
},
|
||||
],
|
||||
"/zh/use-cases/": [
|
||||
{
|
||||
text: "Tutorials & use cases",
|
||||
link: "/zh/use-cases/",
|
||||
items: [
|
||||
{
|
||||
text: "Stable Diffusion",
|
||||
link: "/zh/use-cases/stable-diffusion",
|
||||
},
|
||||
{
|
||||
text: "ComfyUI",
|
||||
link: "/zh/use-cases/comfyui",
|
||||
collapsed: true,
|
||||
items: [
|
||||
{
|
||||
text: "Manage ComfyUI",
|
||||
link: "/zh/use-cases/comfyui-launcher",
|
||||
},
|
||||
{
|
||||
text: "Use ComfyUI for Krita",
|
||||
link: "/zh/use-cases/comfyui-for-krita",
|
||||
},
|
||||
]
|
||||
},
|
||||
{
|
||||
text: "Ollama",
|
||||
link: "/zh/use-cases/ollama",
|
||||
},
|
||||
{
|
||||
text: "Open WebUI",
|
||||
link: "/zh/use-cases/openwebui",
|
||||
},
|
||||
{
|
||||
text: "Perplexica",
|
||||
link: "/zh/use-cases/perplexica",
|
||||
},
|
||||
{
|
||||
text: "Dify",
|
||||
link: "/zh/use-cases/dify",
|
||||
},
|
||||
{
|
||||
text: "Jellyfin",
|
||||
link: "/zh/use-cases/stream-media",
|
||||
},
|
||||
{
|
||||
text: "Steam",
|
||||
link: "/zh/use-cases/stream-game",
|
||||
},
|
||||
{
|
||||
text: "Redroid",
|
||||
link: "/zh/use-cases/host-cloud-android",
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
"/zh/developer/": [
|
||||
{
|
||||
text: "Olares 安装详解",
|
||||
link: "/zh/developer/install/",
|
||||
items: [
|
||||
{
|
||||
text: "安装概述",
|
||||
link: "/zh/developer/install/installation-overview",
|
||||
},
|
||||
{
|
||||
text: "安装流程",
|
||||
link: "/zh/developer/install/installation-process",
|
||||
},
|
||||
{
|
||||
text: "Olares Home",
|
||||
link: "/zh/developer/install/olares-home",
|
||||
},
|
||||
{
|
||||
text: "环境变量",
|
||||
link: "/zh/developer/install/environment-variables",
|
||||
},
|
||||
{
|
||||
text: "Olares CLI",
|
||||
collapsed: true,
|
||||
link: "/zh/developer/install/cli/olares-cli",
|
||||
items: [
|
||||
{ text: "gpu", link: "/zh/developer/install/cli/gpu" },
|
||||
{ text: "osinfo", link: "/zh/developer/install/cli/osinfo" },
|
||||
{ text: "node", link: "/zh/developer/install/cli/node" },
|
||||
{
|
||||
text: "backups",
|
||||
link: "/zh/developer/install/cli/backups",
|
||||
collapsed: true,
|
||||
items: [
|
||||
{text: "download", link: "/zh/developer/install/cli/backups-download"},
|
||||
{text: "region", link: "/zh/developer/install/cli/backups-region"},
|
||||
{text: "backup", link: "/zh/developer/install/cli/backups-backup"},
|
||||
{text: "restore", link: "/zh/developer/install/cli/backups-restore"},
|
||||
{text: "snapshots", link: "/zh/developer/install/cli/backups-snapshots"},
|
||||
],
|
||||
},
|
||||
{
|
||||
text: "change-ip",
|
||||
link: "/zh/developer/install/cli/change-ip",
|
||||
},
|
||||
{
|
||||
text: "download",
|
||||
link: "/zh/developer/install/cli/download",
|
||||
},
|
||||
{ text: "info", link: "/zh/developer/install/cli/info" },
|
||||
{
|
||||
text: "install",
|
||||
link: "/zh/developer/install/cli/install",
|
||||
},
|
||||
{
|
||||
text: "logs",
|
||||
link: "/zh/developer/install/cli/logs",
|
||||
},
|
||||
{
|
||||
text: "precheck",
|
||||
link: "/zh/developer/install/cli/precheck",
|
||||
},
|
||||
{
|
||||
text: "prepare",
|
||||
link: "/zh/developer/install/cli/prepare",
|
||||
},
|
||||
{
|
||||
text: "release",
|
||||
link: "/zh/developer/install/cli/release",
|
||||
},
|
||||
{
|
||||
text: "start",
|
||||
link: "/zh/developer/install/cli/start",
|
||||
},
|
||||
{
|
||||
text: "stop",
|
||||
link: "/zh/developer/install/cli/stop",
|
||||
},
|
||||
{
|
||||
text: "uninstall",
|
||||
link: "/zh/developer/install/cli/uninstall",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
text: "版本说明",
|
||||
link: "/zh/developer/install/versioning",
|
||||
},
|
||||
// {
|
||||
// text: "其他安装方式",
|
||||
// link: "/zh/developer/install/additional-installations",
|
||||
// collapsed: true,
|
||||
// items: [
|
||||
// { text: "Linux(Docker 镜像)", link: "/zh/developer/install/linux-via-docker-compose" },
|
||||
// {
|
||||
// text: "macOS",
|
||||
// collapsed: true,
|
||||
// items: [
|
||||
// {
|
||||
// text: "使用脚本(推荐)",
|
||||
// link: "/zh/developer/install/mac",
|
||||
// },
|
||||
// {
|
||||
// text: "使用 Docker 镜像",
|
||||
// link: "/zh/developer/install/mac-via-docker-image",
|
||||
// },
|
||||
// ],
|
||||
// },
|
||||
// {
|
||||
// text: "Windows (WSL 2)",
|
||||
// collapsed: true,
|
||||
// items: [
|
||||
// {
|
||||
// text: "使用脚本(推荐)",
|
||||
// link: "/zh/developer/install/windows",
|
||||
// },
|
||||
// {
|
||||
// text: "使用 Docker 镜像",
|
||||
// link: "/zh/developer/install/windows-via-docker-image",
|
||||
// },
|
||||
// ],
|
||||
// },
|
||||
// { text: "PVE", link: "/zh/developer/install/pve" },
|
||||
// { text: "LXC", link: "/zh/developer/install/lxc" },
|
||||
// { text: "树莓派", link: "/zh/developer/install/raspberry-pi" },
|
||||
// ],
|
||||
// },
|
||||
],
|
||||
},
|
||||
{
|
||||
text: "开发 Olares 应用",
|
||||
link: "/zh/developer/develop/",
|
||||
items: [
|
||||
{
|
||||
text: "教程",
|
||||
collapsed: true,
|
||||
link: "/zh/developer/develop/tutorial/",
|
||||
items: [
|
||||
{
|
||||
text: "了解 Studio",
|
||||
link: "/zh/developer/develop/tutorial/studio",
|
||||
},
|
||||
{
|
||||
text: "创建首个应用",
|
||||
collapsed: true,
|
||||
link: "/zh/developer/develop/tutorial/note/",
|
||||
items: [
|
||||
{
|
||||
text: "1. 创建应用",
|
||||
link: "/zh/developer/develop/tutorial/note/create",
|
||||
},
|
||||
{
|
||||
text: "2. 开发后端",
|
||||
link: "/zh/developer/develop/tutorial/note/backend",
|
||||
},
|
||||
{
|
||||
text: "3. 开发前端",
|
||||
link: "/zh/developer/develop/tutorial/note/frontend",
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
text: "应用包管理",
|
||||
collapsed: true,
|
||||
items: [
|
||||
{
|
||||
text: "应用 Chart 包",
|
||||
link: "/zh/developer/develop/package/chart",
|
||||
},
|
||||
{
|
||||
text: "OlaresManifest",
|
||||
link: "/zh/developer/develop/package/manifest",
|
||||
},
|
||||
{
|
||||
text: "推荐算法",
|
||||
link: "/zh/developer/develop/package/recommend",
|
||||
},
|
||||
{
|
||||
text: "Helm 扩展",
|
||||
link: "/zh/developer/develop/package/extension",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
text: "进阶",
|
||||
collapsed: true,
|
||||
items: [
|
||||
{
|
||||
text: "terminus-info",
|
||||
link: "/zh/developer/develop/advanced/terminus-info",
|
||||
},
|
||||
{
|
||||
text: "Service Provider",
|
||||
link: "/zh/developer/develop/advanced/provider",
|
||||
},
|
||||
{
|
||||
text: "AI",
|
||||
link: "/zh/developer/develop/advanced/ai",
|
||||
},
|
||||
{ text: "Cookie", link: "/zh/developer/develop/advanced/cookie" },
|
||||
{ text: "数据库", link: "/zh/developer/develop/advanced/database" },
|
||||
{
|
||||
text: "账户",
|
||||
link: "/zh/developer/develop/advanced/account",
|
||||
},
|
||||
{
|
||||
text: "应用市场",
|
||||
link: "/zh/developer/develop/advanced/market",
|
||||
},
|
||||
// {
|
||||
// text: "Analytic",
|
||||
// link: "/zh/developer/develop/advanced/analytic",
|
||||
// },
|
||||
{
|
||||
text: "Websocket",
|
||||
link: "/zh/developer/develop/advanced/websocket",
|
||||
},
|
||||
{
|
||||
text: "文件上传",
|
||||
link: "/zh/developer/develop/advanced/file-upload",
|
||||
},
|
||||
// {
|
||||
// text: "Rss",
|
||||
// link: "/zh/developer/develop/advanced/rss",
|
||||
// },
|
||||
{
|
||||
text: "密钥",
|
||||
link: "/zh/developer/develop/advanced/secret",
|
||||
},
|
||||
// {
|
||||
// text: "Notification",
|
||||
// link: "/zh/developer/develop/advanced/notification",
|
||||
// },
|
||||
// {
|
||||
// text: "Frontend",
|
||||
// link: "/zh/developer/develop/advanced/frontend",
|
||||
// },
|
||||
{
|
||||
text: "Kubesphere",
|
||||
link: "/zh/developer/develop/advanced/kubesphere",
|
||||
},
|
||||
],
|
||||
},
|
||||
|
||||
{
|
||||
text: "提交应用",
|
||||
collapsed: true,
|
||||
link: "/zh/developer/develop/submit/",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
text: "参与贡献",
|
||||
items: [
|
||||
{
|
||||
text: "开发系统应用",
|
||||
collapsed: true,
|
||||
items: [
|
||||
{
|
||||
text: "概述",
|
||||
link: "/zh/developer/contribute/system-app/overview",
|
||||
},
|
||||
{
|
||||
text: "应用部署配置",
|
||||
link: "/zh/developer/contribute/system-app/deployment",
|
||||
},
|
||||
{
|
||||
text: "Olares 权限配置",
|
||||
link: "/zh/developer/contribute/system-app/olares-manifest",
|
||||
},
|
||||
{
|
||||
text: "安装",
|
||||
link: "/zh/developer/contribute/system-app/install",
|
||||
},
|
||||
{
|
||||
text: "其他",
|
||||
link: "/zh/developer/contribute/system-app/other",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
text: "开发协议",
|
||||
collapsed: true,
|
||||
items: [
|
||||
{
|
||||
text: "合约",
|
||||
link: "/zh/developer/contribute/olares-id/contract/contract",
|
||||
collapsed: true,
|
||||
items: [
|
||||
{
|
||||
text: "架构",
|
||||
link: "/zh/developer/contribute/olares-id/contract/architecture",
|
||||
},
|
||||
{
|
||||
text: "DID",
|
||||
collapsed: true,
|
||||
items: [
|
||||
{
|
||||
text: "设计",
|
||||
link: "/zh/developer/contribute/olares-id/contract/did/design",
|
||||
},
|
||||
{
|
||||
text: "官方 Tagger",
|
||||
link: "/zh/developer/contribute/olares-id/contract/did/official-taggers",
|
||||
},
|
||||
{
|
||||
text: "发布历史",
|
||||
link: "/zh/developer/contribute/olares-id/contract/did/release-history",
|
||||
},
|
||||
{
|
||||
text: "FAQ",
|
||||
link: "/zh/developer/contribute/olares-id/contract/did/faq",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
text: "声誉",
|
||||
link: "/zh/developer/contribute/olares-id/contract/contract-reputation",
|
||||
},
|
||||
{
|
||||
text: "管理",
|
||||
collapsed: true,
|
||||
items: [
|
||||
{
|
||||
text: "合约",
|
||||
link: "/zh/developer/contribute/olares-id/contract/manage/contract",
|
||||
},
|
||||
{
|
||||
text: "SDK",
|
||||
link: "/zh/developer/contribute/olares-id/contract/manage/sdk",
|
||||
},
|
||||
{
|
||||
text: "环境",
|
||||
link: "/zh/developer/contribute/olares-id/contract/manage/environment",
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
text: "可验证凭证(VC)",
|
||||
link: "/zh/developer/contribute/olares-id/verifiable-credential/overview",
|
||||
collapsed: true,
|
||||
items: [
|
||||
{
|
||||
text: "发行方",
|
||||
link: "/zh/developer/contribute/olares-id/verifiable-credential/issuer",
|
||||
},
|
||||
{
|
||||
text: "验证方",
|
||||
link: "/zh/developer/contribute/olares-id/verifiable-credential/verifer",
|
||||
},
|
||||
{
|
||||
text: "Olares 案例",
|
||||
link: "/zh/developer/contribute/olares-id/verifiable-credential/olares",
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
export const zh = defineConfig({
|
||||
lang: "zh",
|
||||
themeConfig: {
|
||||
//logo: "/icon.png",
|
||||
socialLinks: [{ icon: "github", link: "https://github.com/beclab/olares" }],
|
||||
|
||||
nav: [
|
||||
{ text: "Olares", link: "zh/manual/docs-home" },
|
||||
{ text: "Olares Space", link: "/zh/space/" },
|
||||
{ text: "应用示例", link: "/zh/use-cases/" },
|
||||
{ text: "开发者文档", link: "/zh/developer/install/" },
|
||||
],
|
||||
|
||||
sidebar: side,
|
||||
},
|
||||
});
|
||||
201
docs/LICENSE
Normal file
201
docs/LICENSE
Normal file
@@ -0,0 +1,201 @@
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright [yyyy] [name of copyright owner]
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
@@ -1,3 +1,10 @@
|
||||
# Olares Doc
|
||||
# Olares Docs
|
||||
|
||||
https://github.com/beclab/docs
|
||||
## Run
|
||||
|
||||
```shell
|
||||
npm install
|
||||
npm run dev
|
||||
```
|
||||
|
||||
Open Browser at `http://localhost:5173/`
|
||||
|
||||
31
docs/code-snippets/docker-compose-GPU.yaml
Normal file
31
docs/code-snippets/docker-compose-GPU.yaml
Normal file
@@ -0,0 +1,31 @@
|
||||
services:
|
||||
olares:
|
||||
image: beclab/olares:${VERSION}
|
||||
privileged: true
|
||||
volumes:
|
||||
- oic-data:/var
|
||||
ports:
|
||||
- "80:80"
|
||||
- "443:443"
|
||||
- "30180:30180"
|
||||
- "18088:18088"
|
||||
- "41641:41641/udp"
|
||||
environment:
|
||||
- HOST_IP=${HOST_IP}
|
||||
deploy:
|
||||
resources:
|
||||
reservations:
|
||||
devices:
|
||||
- driver: nvidia
|
||||
count: 1
|
||||
capabilities: [gpu]
|
||||
|
||||
olaresd-proxy:
|
||||
image: beclab/olaresd:proxy-v0.1.0
|
||||
network_mode: host
|
||||
depends_on:
|
||||
olares:
|
||||
condition: service_started
|
||||
|
||||
volumes:
|
||||
oic-data:
|
||||
24
docs/code-snippets/docker-compose.yaml
Normal file
24
docs/code-snippets/docker-compose.yaml
Normal file
@@ -0,0 +1,24 @@
|
||||
services:
|
||||
olares:
|
||||
image: beclab/olares:${VERSION}
|
||||
privileged: true
|
||||
volumes:
|
||||
- oic-data:/var
|
||||
ports:
|
||||
- "80:80"
|
||||
- "443:443"
|
||||
- "30180:30180"
|
||||
- "18088:18088"
|
||||
- "41641:41641/udp"
|
||||
environment:
|
||||
- HOST_IP=${HOST_IP}
|
||||
|
||||
olaresd-proxy:
|
||||
image: beclab/olaresd:proxy-v0.1.0
|
||||
network_mode: host
|
||||
depends_on:
|
||||
olares:
|
||||
condition: service_started
|
||||
|
||||
volumes:
|
||||
oic-data:
|
||||
9
docs/code-snippets/docker-daemon.json
Normal file
9
docs/code-snippets/docker-daemon.json
Normal file
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"registry-mirrors": [
|
||||
"https://mirrors.joinolares.cn"
|
||||
],
|
||||
|
||||
"features": {
|
||||
"containerd-snapshotter": false
|
||||
}
|
||||
}
|
||||
52
docs/compress_images.sh
Normal file
52
docs/compress_images.sh
Normal file
@@ -0,0 +1,52 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Check if pngquant and jpegoptim are installed
|
||||
if ! command -v pngquant &> /dev/null; then
|
||||
echo "pngquant is not installed. Please install it first."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if ! command -v jpegoptim &> /dev/null; then
|
||||
echo "jpegoptim is not installed. Please install it first."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Create base compress directory if it doesn't exist
|
||||
mkdir -p compress
|
||||
|
||||
# Function to process a single file
|
||||
process_file() {
|
||||
local source_file="$1"
|
||||
# Remove 'public/' prefix and prepend 'compress/'
|
||||
local target_file="compress/${source_file#public/}"
|
||||
# Get the directory path of the target file
|
||||
local target_dir="$(dirname "$target_file")"
|
||||
|
||||
# Create target directory if it doesn't exist
|
||||
mkdir -p "$target_dir"
|
||||
|
||||
# Copy file first to preserve original
|
||||
cp "$source_file" "$target_file"
|
||||
|
||||
# Process based on file extension
|
||||
local ext=$(echo "${source_file##*.}" | tr '[:upper:]' '[:lower:]')
|
||||
|
||||
# Process based on file extension
|
||||
case "$ext" in
|
||||
png)
|
||||
echo "Compressing PNG: $source_file"
|
||||
pngquant --quality=90-95 --skip-if-larger --force --output "$target_file" "$target_file"
|
||||
;;
|
||||
jpg|jpeg)
|
||||
echo "Compressing JPEG: $source_file"
|
||||
jpegoptim --max=95 --preserve --strip-none "$target_file"
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
# Find and process all PNG and JPEG files
|
||||
find public -type f \( -iname "*.png" -o -iname "*.jpg" -o -iname "*.jpeg" -o -iname "*.svg" \) | while read -r file; do
|
||||
process_file "$file"
|
||||
done
|
||||
|
||||
echo "Image compression completed. Compressed images are in the 'compress' directory."
|
||||
121
docs/developer/contribute/olares-id/contract/architecture.md
Normal file
121
docs/developer/contribute/olares-id/contract/architecture.md
Normal file
@@ -0,0 +1,121 @@
|
||||
---
|
||||
outline: [2, 4]
|
||||
---
|
||||
|
||||
# TerminusDID Contract System
|
||||
|
||||
## Architecture
|
||||
|
||||
The TerminusDID Contract System is divided into two parts: DID Management and Tag Management. In addition to the core functions for Tag Management, we also implemented an official tagger and reputation system.
|
||||
|
||||
```mermaid
|
||||
graph TB
|
||||
|
||||
RootTagger{RootTagger}
|
||||
|
||||
RSAPubKey[/RSAPubKey/]
|
||||
DNSARecord[/DNSARecord/]
|
||||
AuthAddress[/AuthAddress/]
|
||||
otherTag[/.../]
|
||||
|
||||
|
||||
|
||||
|
||||
TerminusDID{TerminusDID}
|
||||
Reputations[/Reputations\]
|
||||
XXXReputation{...}
|
||||
AppMarketReputation{AppMarketReputation}
|
||||
Tag[[Tag]]
|
||||
Tagger([Tagger])
|
||||
|
||||
|
||||
DID[DID]
|
||||
Domain((Domain))
|
||||
com((com))
|
||||
net((net))
|
||||
io((io))
|
||||
|
||||
TerminusDID--->DID
|
||||
TerminusDID--->Tag
|
||||
Tag--->Tagger
|
||||
|
||||
Tagger-.-RootTagger
|
||||
Tagger-.-AppMarketReputation
|
||||
Tagger-.-XXXReputation
|
||||
|
||||
|
||||
Domain-.->Tag
|
||||
|
||||
|
||||
subgraph ide4 [Tag]
|
||||
|
||||
subgraph ide1 [OfficialTag]
|
||||
RootTagger--->RSAPubKey
|
||||
RootTagger--->DNSARecord
|
||||
RootTagger--->AuthAddress
|
||||
RootTagger--->otherTag
|
||||
end
|
||||
|
||||
subgraph ide2 [Reputations]
|
||||
Reputations-.->AppMarketReputation
|
||||
Reputations-.->XXXReputation
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
subgraph ide3 [DID]
|
||||
DID-.-Domain
|
||||
Domain--->com
|
||||
Domain--->net
|
||||
Domain--->io
|
||||
end
|
||||
|
||||
```
|
||||
|
||||
Refer [here](./contract.md) for the usage of DID/Tag Management, [here](././did/design.md) for design details of the TerminusDID contract, [here](./contract-reputation.md) for recommended implementations and examples of the reputation system.
|
||||
|
||||
## Design Details
|
||||
|
||||
### Multicall
|
||||
|
||||
Considering the complexity and the uncertainty of usage scenarios of our contracts, we add built-in multicall function to simplify on-chain interaction. You can access multiple interfaces in one transaction without external helper contracts.
|
||||
|
||||
Considering the complexity and uncertainty of usage scenarios of our contracts, we have added a built-in multicall function to simplify on-chain interactions. You can access multiple interfaces in one transaction without external contracts.
|
||||
|
||||
|
||||
### EIP-7201
|
||||
|
||||
We follow EIP-7201 for contract data storage, which makes it easier and safer for contract upgrade and also facilitates granular control of data.
|
||||
|
||||
### Validation of Olares ID
|
||||
|
||||
Olares ID is submitted as a `string` type during registration. Although it is split by `.` for level separation, this cannot guarantee its correctness and readability. We implemented additional validation in contract code to ensure the submitted names are UTF-8-encoded readable strings.
|
||||
|
||||
### Field Names of Structs in Tags
|
||||
|
||||
For gas efficiency, if there are structs in a tag type, their field names are published on-chain using Ethereum events without contract storage. The events will record the block height at which the tag type is defined. Use the block height, contract address, event signature and Bloom filters to get the desired event precisely.
|
||||
|
||||
### Inline Assembly
|
||||
|
||||
We use slice types based on inline assembly to parse and traverse Olares ID levels, which can prevent copying substrings and reduce gas.
|
||||
|
||||
## Appendix - Requirements
|
||||
|
||||
### DID
|
||||
|
||||
- on-chain [DID](https://www.w3.org/TR/did-core/) management (prefer EVM-compatible chains)
|
||||
- recording IPv4/IPv6, avatar, RSA public key etc. for DIDs
|
||||
- extending stored data for possible new needs in the future
|
||||
|
||||
### Olares ID
|
||||
|
||||
- distinguishing between two kinds of DIDs for Olares ID: Organization or Individual
|
||||
- derived DID management privilege for parent Organization
|
||||
|
||||
### Reputation
|
||||
|
||||
DIDs with another kind called Entity to represent real-world objects (e.g. app versions for App Market Reputation and complaints for Otmoic Reputation)
|
||||
|
||||
:::tip Tips
|
||||
We hope to design a decentralized credit system based on DID contracts. At first we imagined a general system adaptable to various scenarios, but with its gradually implementation we found this large and comprehensive system to bring much unnecessary resource consumption and reduce flexibility in different scenarios. So we changed the direction: we present a Reputation system for abstraction and necessary components and provide some recommended implementations. Users can assembly and customize the implementation to satisfy their own scenarios.
|
||||
:::
|
||||
@@ -0,0 +1,98 @@
|
||||
# Reputation
|
||||
|
||||
#### Extra requirements: Abstract Reputation System
|
||||
|
||||
:::info Required features
|
||||
|
||||
- identifiers that map to real-world objects
|
||||
All credit systems are based on some specific scenarios, e.g. reviews for an app or complaints for a merchant. This inevitably needs us to build unique on-chain identifiers for some real-world or abstract objects.
|
||||
|
||||
- authentication
|
||||
The most core function of the credit system is reviewing and reviewer authentication is one of its prerequisites.
|
||||
|
||||
- storage of necessary information
|
||||
After user reviewing, we may need to record the comments or calculate some weighted statistical data.
|
||||
|
||||
- recording of history and updating
|
||||
Under some circumstances, we may need to record the behavior of reviewing and allow updating existing reviews in the future.
|
||||
:::
|
||||
|
||||
The corresponding solution for each requirement is provided in this chapter.
|
||||
|
||||
## Objects to be Reviewed
|
||||
|
||||
For the objects to be reviewed, the following two situations may occur:
|
||||
|
||||
- it's a merchant or a single person
|
||||
In this case the object must have a DID of kind Individual, so we can operate the object directly without creating other DIDs.
|
||||
- it's a real-world object or abstract concept
|
||||
In this case we need to first create a DID of kind Entity for this object and then operate on it.
|
||||
|
||||
## Authentication
|
||||
|
||||
There are two solutions for authentication:
|
||||
|
||||
- Use the owner of the DID to submit tx and let the tagger call interfaces of the Terminus DID contract for authentication.
|
||||
- Use the owner of the DID to sign a customized EIP-712 message and use a forwarder to send tx on-chain. The tagger will use the message signer for authentication.
|
||||
|
||||
> [!NOTE] Tips
|
||||
> We recommend the second solution as the transaction fee is paid by forwarders instead of reviewers.
|
||||
|
||||
## Storage of Necessary Information
|
||||
|
||||
For DIDs of kind Entity, we define tags of this DID itself and write necessary data to them. For DIDs of kind Individual, we abstract the scenario as a DID of kind Entity and write to its tags.
|
||||
|
||||
## Recording of History and Updating
|
||||
|
||||
We can follow the advice in the above section and store data in tags of Entity. But on-chain querying is not required in some scenarios, where on-chain storage is a waste. For those cases we recommend to use Ethereum events for recording and customize the detailed implementation in taggers.
|
||||
|
||||
## Example - OtmoicReputation
|
||||
|
||||
:::info
|
||||
|
||||
```mermaid
|
||||
flowchart LR
|
||||
|
||||
otmoic{{OtmoicReputation}}
|
||||
did{{TerminusDID}}
|
||||
complaints[/tag-complaints/]
|
||||
otmoicdid((otmoic.reputation))
|
||||
|
||||
otmoic-- Authentication -->did
|
||||
did-.->otmoicdid
|
||||
otmoicdid-.-complaints
|
||||
otmoic-- read/write -->complaints
|
||||
```
|
||||
|
||||
The Otmoic Reputation contract uses EIP-712 signature of DID owners for authentication and stores the `bidid` of the complained bid in the `complaints` tag of Entity `otmoic.reputation`.
|
||||
:::
|
||||
|
||||
## Example - TerminusAppMarketReputation
|
||||
|
||||
:::info
|
||||
|
||||
```mermaid
|
||||
flowchart TD
|
||||
|
||||
app((app.myterminus.com))
|
||||
appname((appname.app.myterminus.com))
|
||||
version1((version1.appname.app.myterminus.com))
|
||||
version2((version2.appname.app.myterminus.com))
|
||||
reputation{{TerminusAppMarketReputation}}
|
||||
ratings[/tag-ratings/]
|
||||
version1ratings[/version1-tag-ratings/]
|
||||
event[[event]]
|
||||
|
||||
app-->appname
|
||||
appname-->version1
|
||||
appname-->version2
|
||||
app-.->ratings
|
||||
ratings-.-version1ratings
|
||||
version1-.-version1ratings
|
||||
reputation-.- read/write -.->version1ratings
|
||||
reputation-.->event
|
||||
|
||||
```
|
||||
|
||||
The Olares App Market Reputation contract also uses EIP-712 signature of DID owners for authentication. Rating data of the contract is stored in the `ratings` tag of Entity `<version>.<appname>.app.myterminus.com`, and comment data is published in the form of Ethereum events instead of storing on-chain.
|
||||
:::
|
||||
229
docs/developer/contribute/olares-id/contract/contract.md
Normal file
229
docs/developer/contribute/olares-id/contract/contract.md
Normal file
@@ -0,0 +1,229 @@
|
||||
---
|
||||
outline: [1, 5]
|
||||
---
|
||||
|
||||
# Smart Contract
|
||||
|
||||
Snowinning Protocol's smart contract has two parts.
|
||||
|
||||
- [TerminusDID](https://github.com/beclab/terminusdid-contract-system/blob/main/src/core/TerminusDID.sol) contract plays a crucial role as the [DID Registry](/manual/concepts/registry.md). Learn more in [the contract](https://optimistic.etherscan.io/address/0x5da4fa8e567d86e52ef8da860de1be8f54cae97d).
|
||||
- Third-party protocols that extend the reputation system based on [TerminusDID](https://github.com/beclab/terminusdid-contract-system/blob/main/src/core/TerminusDID.sol). Currently, the following reputation protocols are in place:
|
||||
- [Otmoic Trader Reputation](https://github.com/otmoic/reputation-contract-evm/blob/main/contracts/Reputation.sol). Learn more in [the contract](https://optimistic.etherscan.io/address/0x3179CE5fAB68C0286Da85f3d61BcE7116815e799).
|
||||
- [Application Reputation](https://github.com/beclab/terminusdid-contract-system/blob/main/src/taggers/TerminusAppMarketReputation.sol). Learn more in [the contract](https://optimistic.etherscan.io/address/0x08065353D266121938B93D4B1071Bb52CD0C0EE4).
|
||||
|
||||

|
||||
|
||||
- The [TerminusDID](https://github.com/beclab/terminusdid-contract-system/blob/main/src/core/TerminusDID.sol) contract plays a crucial role, and it serves as the [DID Registry](/manual/concepts/registry.md). View [the contract](https://optimistic.etherscan.io/address/0x5da4fa8e567d86e52ef8da860de1be8f54cae97d).
|
||||
- Third-party protocols can extend the reputation based on [TerminusDID](https://github.com/beclab/terminusdid-contract-system/blob/main/src/core/TerminusDID.sol). Currently, the following reputation protocols are in place:
|
||||
- [Otmoic Trader Reputation](https://github.com/otmoic/reputation-contract-evm/blob/main/contracts/Reputation.sol). View [the contract](https://optimistic.etherscan.io/address/0xE924F7f68D1dcd004720e107F62c6303aF271ed3).
|
||||
- [Application Reputation](https://github.com/beclab/terminusdid-contract-system/blob/main/src/taggers/TerminusAppMarketReputation.sol). View [the contract](https://optimistic.etherscan.io/address/0x08065353D266121938B93D4B1071Bb52CD0C0EE4).
|
||||
|
||||
|
||||
|
||||
# TerminusDID
|
||||
|
||||
The TerminusDID contract manages a hierarchical structure derived from [Domain](/manual/concepts/olares-id.md#domain-types.
|
||||
|
||||

|
||||
|
||||
## Node
|
||||
|
||||
Each node possesses several default attributes.
|
||||
|
||||
| Attribute | Description |
|
||||
| -------------- |------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||
| name | Specifies the [Domain Name](/manual/concepts/olares-id.md#domain-types). Certain Domain Names can interchange with Terminus Names |
|
||||
| id | Each node is also a NFT, adhering to the **ERC-721** standard. Its id serves as the unique identifier for this NFT, computed through `keccak256(name)` |
|
||||
| did,owner | The `owner` and `did` of the node, derived from the same mnemonic words. Further details on this can be found [here](/manual/concepts/did.md).<br>. Additionally, storing owner is advantageous because it complies with the **BIP44** specification, facilitating gas-efficient signature verification within EVM contracts. Each node is affiliated with an `owner`, who holds the authority to modify node details. |
|
||||
| note | Currently, there are three types: Individual, Organization, and Entity |
|
||||
| allowSubdomain | Indicates whether it is a leaf node. If False, the node cannot spawn further nodes. |
|
||||
|
||||
The following is an illustrative example that specifies the default attributes of a node:
|
||||
|
||||
```json
|
||||
{
|
||||
"id": "0xbf90de759829bfa3d2b10e4c4a7101e3b116f70b9a5431951ff9d83a4c8e3ceb",
|
||||
"name": "olivia.myterminus.com",
|
||||
"did": "did:key:z6MkuhT5kYegHaJxirMaHxuqzJhGZk5r32Ct5nYVRQWpN31q",
|
||||
"note": "Individual",
|
||||
"owner": "0x1404C95b2Cb2E46E03650bc02f83364A92f8DA9D",
|
||||
"allowSubdomain": true
|
||||
}
|
||||
```
|
||||
|
||||
## Owner
|
||||
|
||||
Ownership of different nodes is as follows:
|
||||
|
||||
- **System**<br>
|
||||
Abstract nodes such as `root`, `com`, `io` belong to the Terminus team.
|
||||
|
||||
- **Individual** <br>
|
||||
`myterminus.com` belongs to the [Individual Domain](/manual/concepts/olares-id.md#domain-types), owned by the Terminus team.
|
||||
`alice.myterminus.com` and `bob.myterminus.com` belong to individual Terminus Names, and are owned by the respective users.
|
||||
|
||||
- **Organization** <br>
|
||||
`org1.com` and `org.io` belong to the [Organization Domain](/manual/concepts/olares-id.md#domain-types), owned by the domain admin.
|
||||
`alice.org1.com` and `bob.org2.io` belong to Organization Terminus Names, and are owned by the respective users.
|
||||
|
||||
- **Entity** <br>
|
||||
The `Application Score` belongs to the [Entity Domain](/manual/concepts/olares-id.md#domain-types), and is owned by the applicant of the entity. Organization admins and users can refer to [Domain Management](../contract/manage/contract.md#register-did) to manage their own nodes and sub-nodes.
|
||||
|
||||
:::info
|
||||
After the project stabilizes, ownership will be transferred to the multisig address of the DAO organization by the Terminus team.
|
||||
:::
|
||||
|
||||
## Tag
|
||||
|
||||
The [Tag](https://github.com/beclab/terminusdid-contract-system/blob/main/src/core/TagRegistry.sol) mechanism allows the [TerminusDID](https://github.com/beclab/terminusdid-contract-system/blob/main/src/core/TerminusDID.sol) contract to extend the metadata stored on nodes.
|
||||
|
||||
For example, if you are an enterprise managing an organizational domain, and you want to add the attribute employee-id to each employee under the organization, you need to extend based on Tags.
|
||||
|
||||
Tag system allows you to freely store data types such as `uint`, `int`, `address`, `boolean`, `bytes`, `string`, `structure`, `fixed length array`, `variable length array` on-chain in a specific encoding format (ABI). Before reading or writing data, you need to define the data type. The data type you define will apply to itself and all its child nodes. The information of **definer, user, and Tag name** is used to index a unique piece of data.
|
||||
|
||||
:::info Note
|
||||
|
||||
For complex structures or arrays, as well as cases where complex structures and arrays are nested within each other, if data is written in units of Tags each time, it will result in huge useless gas consumption. Therefore, we have implemented the functionality of updating a single field or operating a single array separately in the system. When performing single updates, in addition to **definer, user, and Tag name**, you also need to provide the **path** of the data, which is the variable name inside the structure.
|
||||
:::
|
||||
|
||||
### Customized Tags
|
||||
|
||||
| Field | Description |
|
||||
| ---------- | ----------------------------------------------------------------------------------------------------------------------- |
|
||||
| name | Name of this tag |
|
||||
| did | The DID that defines this tag |
|
||||
| abiType | The data type of this tag, following the encoding specifications of **abi**, also supports defining a complex structure |
|
||||
| fieldNames | When defining a complex structure, the names of internal substructures or data are flattened in a two-dimensional array |
|
||||
|
||||
|
||||
::: tip NOTE
|
||||
Owner/did as a custom tag is only effective for the node and its sub nodes.
|
||||
:::
|
||||
|
||||
### Tagger
|
||||
|
||||
Tagger is one of the necessary pieces of information inside each Tag. It represents the unique entity with permission to modify the Tag value, which can be a wallet address or a contract. Tagger may change frequently.
|
||||
|
||||
|
||||
> [!NOTE]
|
||||
> We recommend that you use contracts as Taggers.
|
||||
>
|
||||
> - Referring to the official implementations of several Taggers, you can utilize DID contracts for comprehensive operator identity authentication and also achieve more refined custom permission controls.
|
||||
> - For complex Tag structures or data content with special specifications, setting the Tagger as a contract can verify the data format on-chain or establish more comprehensive custom rules. For example, for the value of RSAPubKey in the official Tag, we perform validation of bytes data in Pkcs8 ASN.1 format on-chain to prevent setting values that cannot be parsed.
|
||||
|
||||
## Use Cases
|
||||
|
||||
Some Taggers are provided under the Root node:
|
||||
|
||||
- RSAPubKey: Users can declare RSA public keys, and third parties can send them private messages based on this public key.
|
||||
- AuthAddresses: Users can declare the wallet addresses they own.
|
||||
- DNSARecord: Users can declare the DNS A records of Edge nodes.
|
||||
|
||||
:::info About AuthAddresses
|
||||
The following systems rely on this Tag's data operation:
|
||||
|
||||
- Setting an Avatar
|
||||
|
||||
When setting an avatar in the system, you can choose any NFT image you own as an avatar. The standard for determining if you own an NFT is whether the address of the owner exists in AuthAddresses.
|
||||
|
||||
- Otmoic lp
|
||||
|
||||
Otmoic lp operates as an account with TerminusName. When signing transaction information, it verifies whether the signer's address exists in AuthAddresses.
|
||||
|
||||
Because AuthAddresses involve another wallet, simply verifying the sender of the transaction is not credible. Therefore, we have designed the following operation plan:
|
||||
|
||||
Use the declared address and DID owner to sign the following information in compliance with the EIP712 standard and submit it to the contract for verification within a limited time (30 minutes after signing).
|
||||
|
||||
```json
|
||||
{
|
||||
"address": "0x10FE2771907B0c4245695daD7e9Ed064d45860f8",
|
||||
"algorithm": 0, // 0: ECDSA
|
||||
"domain": "olivia.myterminus.com",
|
||||
"signAt": "1714287578",
|
||||
"action": 0 //0: Add 1: Remove
|
||||
}
|
||||
```
|
||||
|
||||
:::
|
||||
|
||||
|
||||
# Reputation
|
||||
|
||||
We can create highly flexible [reputation](/manual/concepts/reputation.md) protocols based on Taggers.
|
||||
|
||||
In implementing an on-chain Reputation system, the most crucial elements are:
|
||||
|
||||
- Abstracting and representing the object to be evaluated
|
||||
- Evaluating the object and storing necessary information
|
||||
- Authenticating the evaluator's identity
|
||||
|
||||
Regarding these elements, TerminusDID provides a comprehensive solution. We can use Individual and Entity types of DID to represent the object to be evaluated, use Tags to store extended metadata, and utilize TerminusDID's built-in permission management features to verify identities. Learn more in the following two cases.
|
||||
|
||||
## Otmoic Trader Reputation
|
||||
|
||||
Otmoic's reputation contract uses DID owner's EIP712 signature for identity verification, and then stores the complain did in the `complaints` field of the `otmoic.reputation` Entity.
|
||||
|
||||
:::info Deployment
|
||||
|
||||
1. Create the entity`otmoic.reputation` in the TerminusDID contract.
|
||||
2. Define a Tag named complaints.
|
||||
3. Deploy Otmoic Trader Reputation [contract](https://optimistic.etherscan.io/address/0xE924F7f68D1dcd004720e107F62c6303aF271ed3)
|
||||
4. Set the Tagger of complaints to Otmoic Trader Reputation.
|
||||
:::
|
||||
|
||||
:::info Usage
|
||||
|
||||
1. Use DID owner to sign the transaction info following EIP712
|
||||
2. Submit transaction info and signature to Otmoic Trader Reputation
|
||||
:::
|
||||
|
||||
:::info Structure
|
||||
|
||||
```mermaid
|
||||
flowchart LR
|
||||
|
||||
otmoic{{OtmoicReputation}}
|
||||
did{{TerminusDID}}
|
||||
complaints[/tag-complaints/]
|
||||
otmoicdid((otmoic.reputation))
|
||||
|
||||
otmoic-- Authentication -->did
|
||||
did-.->otmoicdid
|
||||
otmoicdid-.-complaints
|
||||
otmoic-- read/write -->complaints
|
||||
```
|
||||
:::
|
||||
|
||||
## Application Reputation
|
||||
|
||||
1. Define the Tag named `ratings` and set Tagger as the Application Reputation contract
|
||||
2. When there is a new version for an app, create **`<version>.<appname>.app.myterminus.com`** on the blockchain.
|
||||
3. Users sign the comment/ rating info, and submit to the Application Reputation contract.
|
||||
4. The Application Reputation contract saves the rating info into Ratings of `<version>.<appname>.app.myterminus.com`, and publish the comment info in the form of event
|
||||
|
||||
:::info
|
||||
|
||||
```mermaid
|
||||
flowchart TD
|
||||
|
||||
app((app.myterminus.com))
|
||||
appname((appname.app.myterminus.com))
|
||||
version1((version1.appname.app.myterminus.com))
|
||||
version2((version2.appname.app.myterminus.com))
|
||||
reputation{{TerminusAppMarketReputation}}
|
||||
ratings[/tag-ratings/]
|
||||
version1ratings[/version1-tag-ratings/]
|
||||
event[[event]]
|
||||
|
||||
app-->appname
|
||||
appname-->version1
|
||||
appname-->version2
|
||||
app-.->ratings
|
||||
ratings-.-version1ratings
|
||||
version1-.-version1ratings
|
||||
reputation-.- read/write -.->version1ratings
|
||||
reputation-.->event
|
||||
|
||||
```
|
||||
|
||||
:::
|
||||
278
docs/developer/contribute/olares-id/contract/did/design.md
Normal file
278
docs/developer/contribute/olares-id/contract/did/design.md
Normal file
@@ -0,0 +1,278 @@
|
||||
---
|
||||
outline: [2, 3]
|
||||
---
|
||||
|
||||
# DID
|
||||
|
||||
## Design of DID
|
||||
|
||||
### Data Contained in DIDs
|
||||
|
||||
#### id
|
||||
|
||||
Each DID is also a NFT (following **ERC-721** standard) and `id` is its unique identifier calculated by `keccak256(name)`.
|
||||
|
||||
#### did
|
||||
Derived from mnemonic phrases, used for authentication in systems relying on DIDs.
|
||||
|
||||
#### owner
|
||||
|
||||
Also derived from mnemonic phrases (following **BIP-44** standard) and used for authentication (mostly on-chain contracts).
|
||||
|
||||
#### note
|
||||
|
||||
DIDs have the following kinds for now:
|
||||
|
||||
- Individual
|
||||
- Organization
|
||||
- Entity
|
||||
|
||||
:::info Naming rules of TName
|
||||
A valid label of TName, i.e. each part separated by `.`:
|
||||
|
||||
- is a well-formed non-empty UTF-8 sequence; and
|
||||
- contains only Unicode code points in category L, M, N, P, S; and
|
||||
- does not contain Unicode code points in the following ranges:
|
||||
- Full Stop (U+002E)
|
||||
- Mongolian Free Variation Selectors (U+180B..U+180D)
|
||||
- Variation Selectors (U+FE00..U+FE0F)
|
||||
- Replacement Characters (U+FFFC..U+FFFD)
|
||||
- Variation Selectors Supplement (U+E0100..U+E01EF).
|
||||
- is case-sensitive, e.g. `MAX.com` and `max.com` are different TNames.
|
||||
- supports multiple characters including Chinese, e.g. `博物馆.中国`
|
||||
Ref: https://www.compart.com/en/unicode/category
|
||||
:::
|
||||
|
||||
|
||||
### Tag System
|
||||
|
||||
In addition to basic data, we hope to maintain some states or information in DIDs. That's why we implemented the tag system.
|
||||
|
||||
#### how to use
|
||||
|
||||
1. Define a tag
|
||||
2. Write to the tag
|
||||
|
||||
> [!NOTE]
|
||||
> The definition and structure of tags are complicated. Refer to the technical details of the contract if you are interested.
|
||||
> Here we briefly introduce the information in a tag definition.
|
||||
>
|
||||
> - name: the name of this tag
|
||||
> - did: the DID that defines this tag
|
||||
> - abiType: the data type of this tag, which follows the Solidity ABI specification and supports complicated structures
|
||||
> - fieldNames: the field names of structs inside this tag, flatten as a 2D string array using pre-order traversal
|
||||
|
||||
#### the scope of tags
|
||||
|
||||
Every tag is only applicable to the DID under which it was defined and its subdomains.
|
||||
For example, if the tag `employeeId` was defined in DID `a-certain-company.com`. Its subdomain `james.a-certain-company.com` can set `employeeId` value to `"001"` for itself. If the DIDs who have neither defined the tag nor is a subdomain of the definer, e.g. `another-company.com` and `emma.another-company.com`, cannot set the tag value.
|
||||
|
||||
```mermaid
|
||||
graph TB
|
||||
|
||||
a-certain((a-certain-company.com))
|
||||
another-company((another-company.com))
|
||||
emma((emma.another-company.com))
|
||||
james((james.a-certain-company.com))
|
||||
olivia((olivia.a-certain-company.com))
|
||||
employee-id[/employee-id/]
|
||||
|
||||
a-certain-->james
|
||||
a-certain-->olivia
|
||||
another-company-->emma
|
||||
a-certain-.-employee-id
|
||||
employee-id-.->james
|
||||
employee-id-.->olivia
|
||||
```
|
||||
|
||||
#### taggers
|
||||
|
||||
The tagger is part of necessary information in each tag. Unlike the fixed definition, taggers can be changed.
|
||||
A tagger represents the only person or program that has the authority to modify the tag value. It can be a wallet address or smart contract.
|
||||
|
||||
> [!NOTE]
|
||||
> We recommend you to use smart contracts for taggers.
|
||||
>
|
||||
> - You can utilize the Terminus DID contract for complete operator authentications, while achieving more fine-grained custom access control. Please refer to some official tagger implementations.
|
||||
> - For complicated tag structures or data with special formats, using contract taggers supports verifying data format on chain and customizing the rules. For example, in the official tagger we will verify the bytes data in PKCS8 ASN.1 format on chain to prevent accidentally setting unparsable values for the `RSAPubKey` tag.
|
||||
|
||||
### Who to Create DIDs
|
||||
|
||||
Since not everyone has enough gas for on-chain operations and is willing to use the owner address of existing DIDs, we offer the choice of sending tx by official forwarders on your behalf. Of couse you can also operate on your own if willing.
|
||||
|
||||
### Priviledges of DIDs
|
||||
|
||||
A DID has management priviledge over itself and all its subdomains. For 3rd-level domains which is registered directly, e.g. `a.b.c` without the registration of `b.c`, the owner of `b.c` will be set to `0x0...00d1d` and it is managed by the official.
|
||||
|
||||
### Introduction to processes and concepts
|
||||
|
||||
The extended information of TNames is managed by the tag system of the Terminus DID contract. Every tag has not only a name but also a tag type. For now, supported types include `int`, `uint`, `bool`, `string`, `address`, `bytes`, `bytesN`, `array`, `arrayN` and `tuple`. Tuples supports additional field names.
|
||||
Since tags are bound to TNames, the steps for setting a tag are:
|
||||
|
||||
- Define a tag in a TName with the tag name, tag type and field names in tuples. Setting the field names is not trivial so refer to the documentation "DIDv2.3Tag 类型注册流程介绍" for details.
|
||||
|
||||
Code example
|
||||
|
||||
```Solidity
|
||||
function defineTag(
|
||||
string calldata domain,
|
||||
string calldata name,
|
||||
bytes calldata abiType,
|
||||
string[][] calldata fieldNames
|
||||
) public
|
||||
```
|
||||
|
||||
- Set the tagger which is responsible for setting this tag. The tagger can be EOA or a contract address. Complicated validation logic can be implemented in contract taggers.
|
||||
|
||||
Code example
|
||||
|
||||
```Solidity
|
||||
function setTagger(string calldata domain, string calldata name, address tagger) public
|
||||
```
|
||||
|
||||
- Next you can perform CRUD of this tag on the definer and its subdomains.
|
||||
|
||||
```Solidity
|
||||
function addTag(string calldata from, string calldata to, string calldata name, bytes calldata value) public
|
||||
function removeTag(string calldata from, string calldata to, string calldata name) public
|
||||
function getTagElem(string calldata from, string calldata to, string calldata name, uint256[] calldata elemPath)
|
||||
public
|
||||
view
|
||||
returns (bytes memory)
|
||||
function updateTagElem(
|
||||
string calldata from,
|
||||
string calldata to,
|
||||
string calldata name,
|
||||
uint256[] calldata elemPath,
|
||||
bytes calldata value
|
||||
) public
|
||||
function getTagElemLength(
|
||||
string calldata from,
|
||||
string calldata to,
|
||||
string calldata name,
|
||||
uint256[] calldata elemPath
|
||||
) public view returns (uint256)
|
||||
function pushTagElem(
|
||||
string calldata from,
|
||||
string calldata to,
|
||||
string calldata name,
|
||||
uint256[] calldata elemPath,
|
||||
bytes calldata value
|
||||
) public
|
||||
function popTagElem(string calldata from, string calldata to, string calldata name, uint256[] calldata elemPath) public
|
||||
```
|
||||
|
||||
Among these
|
||||
|
||||
- `from` is the TName that defines this tag
|
||||
- `to` is the TName to set this tag
|
||||
- `name` is the tag name
|
||||
- `value` is the bytes value after `abi.encode`
|
||||
- `elemPath` is provided for `array` and `tuple` to access a single element. For other types just set it to an empty array. Its value is treated like indices of multi-dimensional arrays (think `tuple`s as arrays too). For example, the following type `Student` has 4-level nested tuples, and we can set `elemPath` to `[1,2,1,0,0]` to read or update `Student s -> Class class -> Teacher[1] teachers -> People info -> string name`. Note that we only have 4-level nested tuples but `elemPath` has length 5 because `teachers` is an array and adds another nesting level.
|
||||
|
||||
```Solidity
|
||||
struct Student {
|
||||
People info;
|
||||
Class class;
|
||||
}
|
||||
|
||||
struct Class {
|
||||
uint8 grade;
|
||||
uint8 classNum;
|
||||
Teacher[] teachers;
|
||||
}
|
||||
|
||||
struct People {
|
||||
string name;
|
||||
uint8 age;
|
||||
string gender;
|
||||
}
|
||||
|
||||
struct Teacher {
|
||||
People info;
|
||||
string subject;
|
||||
}
|
||||
Student s;
|
||||
```
|
||||
|
||||
- The Terminus DID contract provides a set of special tags, known as the official tags. It is defined in the empty TName `""` and its tagger is specified as the `RootTagger`. All TNames can set official tags and we'll introduce the detailed access control policy later.
|
||||
|
||||
### Access Control of Tags
|
||||
|
||||
1. Defining tags in a TName, i.e. setting the tag name and type
|
||||
|
||||
- Official tags: the `operator` has permission
|
||||
- Other tags: the owner of this TName has permission
|
||||
Defining tags can fail in the following situations:
|
||||
- A tag name can only be defined once in one TName, no duplicates
|
||||
- Tag names and field names of tuples must start with [a-z] and only contain [a-zA-Z0-9]
|
||||
- The bytes representation of a tag type cannot exceed length 31
|
||||
- The tag type must follow the type constraints in the `ABI` library
|
||||
- The value of `fieldNames` must match tuple types in the definition
|
||||
- A tuple cannot have duplicate field names
|
||||
|
||||
2. Setting the tagger:
|
||||
|
||||
- Official tags: the `operator` has permission
|
||||
- Other tags: the owner of this TName has permission
|
||||
|
||||
3. Setting the tag:
|
||||
|
||||
Taggers are responsible for access control of setting tags. Next we introduce the cases of official tags.
|
||||
|
||||
## Registration Rules and Access Control
|
||||
|
||||
From the contract's perspective, for now only the operator can register top-level TName. Normal registration is done by calling the `register` interface with arguments including the owner of the TName and some metadata. The metadata is immutable after registration. Sub-TNames can be registered by the operator or the owner of one of its parent TNames.
|
||||
That said, registration can only be performed by the following roles:
|
||||
|
||||
- The `operator` of the contract
|
||||
- The owner of a parent TName can register a sub-TName
|
||||
Registration can fail in the following cases:
|
||||
- when TName is not top-level: the parent TName is not registered yet or the parent's metadata specifies it cannot have sub-TNames
|
||||
- the TName contains an invalid label
|
||||
- the TName is already registered
|
||||
- the owner of the TName is specified as zero address
|
||||
|
||||
**Code example**:
|
||||
|
||||
```Solidity
|
||||
struct Metadata {
|
||||
string domain;
|
||||
string did;
|
||||
string notes;
|
||||
bool allowSubdomain;
|
||||
}
|
||||
|
||||
function register(address tokenOwner, Metadata calldata metadata) public returns (uint256 tokenId)
|
||||
```
|
||||
|
||||
After registration, the contract will mint a ERC-721 NFT with a returned token ID (`tokenId`). It is the Keccak-256 hash of the TName string.
|
||||
|
||||
**Code example**:
|
||||
|
||||
```Solidity
|
||||
function tokenId(string memory domain) internal pure returns (uint256) {
|
||||
return uint256(keccak256(bytes(domain)));
|
||||
}
|
||||
```
|
||||
|
||||
Since the NFT is ERC721-compatible, it supports standard ERC-721 operations like `transferFrom` and `approve`. So the ownership can be transferred by these addresses:
|
||||
|
||||
- the owner of the TName
|
||||
- the delegator of the owner
|
||||
- addresses approved by the owner
|
||||
|
||||
The Terminus DID contract adds two addresses that have transfer privilege:
|
||||
|
||||
- `operator` of the contract
|
||||
- the owner of the parent TName
|
||||
|
||||
## Roles of the Contract
|
||||
|
||||
The Terminus DID contract has an owner for upgrading itself. It also has a superuser, i.e. the `operator`, to facilitate configuration. Every TName has its owner.
|
||||
|
||||
The privileges of the contract owner include:
|
||||
|
||||
- setting the operator address
|
||||
- transferring ownership of the contract
|
||||
- upgrading the contract
|
||||
11
docs/developer/contribute/olares-id/contract/did/faq.md
Normal file
11
docs/developer/contribute/olares-id/contract/did/faq.md
Normal file
@@ -0,0 +1,11 @@
|
||||
# FAQ
|
||||
|
||||
## Transaction Fee
|
||||
|
||||
When you apply for an Olares ID, we can afford the transaction fee for calling the contract. The rough process is:
|
||||
|
||||
- You provide us the data and signature signed by your private key
|
||||
- We send the transaction to the smart contract
|
||||
- The blockchain records your data after signature verification
|
||||
|
||||
If you need to manage data under your domain in the future, you should call the contract via MetaMask. Alternatively, you can log in to Olares Space using LarePass and pay the the transaction fee by yourself.
|
||||
@@ -0,0 +1,18 @@
|
||||
# Official Taggers
|
||||
|
||||
## RootTagger
|
||||
|
||||
So far we have defined the following tags and use `RootTagger` as their taggers:
|
||||
|
||||
- rsaPubKey: the RSA public key of a TName
|
||||
type: `bytes`; access: the operator, the owner of the TName, and the owner of a parent TName
|
||||
- dnsARecord: the IP address of a TName
|
||||
type: `bytes4`; access: the operator, the owner of the TName, and the owner of a parent TName
|
||||
- latestDID: the latest DID of a TName (this is added because the metadata is immutable)
|
||||
type: `string`; access: the operator, the owner of the TName, and the owner of a parent TName
|
||||
- authAddresses: the addresses controlled by the owner of a TName
|
||||
type: `tuple(uint8,address)[]`; access: anyone with EIP-712 signatures of the owner of the TName and the added address
|
||||
|
||||
## AppStoreReputation
|
||||
|
||||
There is another special tagger `AppStoreReputation` for the tag `ratings` with type `tuple(string,uint8)[]` defined in the TName `app.myterminus.com`. It provides on-chain storage for ratings of apps in Terminus OS. Each app has a corresponding sub-TName `<appVersion>.<appId>.app.myterminus.com` where anyone who has a TName can submit ratings for these apps.
|
||||
@@ -0,0 +1,21 @@
|
||||
# Release History
|
||||
|
||||
## V2.0.0
|
||||
|
||||
Implement core architecture of DID module in Terminus DID
|
||||
|
||||
## V2.1.0
|
||||
|
||||
Add tag system without definition
|
||||
|
||||
## V2.2.0
|
||||
|
||||
Upgrade tag system to include type definition
|
||||
|
||||
## V2.3.0
|
||||
|
||||
Optimize contract structure and reduce core contract size
|
||||
|
||||
## V2.3.1
|
||||
|
||||
Bug-fix: Revert instead of going on with zero address when EIP-712 signature recover fails
|
||||
104
docs/developer/contribute/olares-id/contract/manage/contract.md
Normal file
104
docs/developer/contribute/olares-id/contract/manage/contract.md
Normal file
@@ -0,0 +1,104 @@
|
||||
---
|
||||
outline: [2, 3]
|
||||
---
|
||||
|
||||
# Call the contract directly
|
||||
|
||||
## DID
|
||||
|
||||
### Get metadata
|
||||
|
||||
There are two interfaces for fetching the metadata of a DID - `getMetadata(tokenId)` and `getMetadata(name)`.
|
||||
|
||||
#### Return value
|
||||
|
||||
```json
|
||||
[
|
||||
"james.myterminus.com", // name
|
||||
"did:key:z6MkpLwxcTwhj4MRm4eKhvBadK45qHr5QEYHUXNyhCfkXJ9U#z6MkpLwxcTwhj4MRm4eKhvBadK45qHr5QEYHUXNyhCfkXJ9U", // DID derived from mnemonic phrases
|
||||
"OrganizationalUser", // DID type
|
||||
true // allowed to create subdomains?
|
||||
]
|
||||
```
|
||||
|
||||
### Get the owner of a domain
|
||||
|
||||
Call `ownerOf(tokenId)` to get the on-chain controller address of a DID.
|
||||
|
||||
### Get token by index of creation
|
||||
|
||||
Call `tokenByIndex(index)` to get the token with a specified index. It returns a **token ID**.
|
||||
|
||||
### Get token by owner and index
|
||||
|
||||
Although we disallow owning multiple DIDs by a single wallet from the business' perspective, the contract allows this considering possible ownership transferring and NFT trading in the future. In this case, `tokenOfOwnerByIndex(owner, index)` can be called to get the token owned by a specified address with a specified index. It returns a **token ID**.
|
||||
|
||||
### Register DID
|
||||
|
||||
The owner of a domain can call `register(owner, MetaData(domain, did, note, allowSubdomain))` to register its subdomains.
|
||||
|
||||
> [!NOTE]
|
||||
> The first parameter **owner** is the specified owner of the new DID and the second parameter is a struct of metadata containing.
|
||||
>
|
||||
> - domain: the complete domain name of the new DID, which is also a Olares ID
|
||||
> - did: the DID derived from the owner's wallet
|
||||
> - note: notes about the new DID, used by off-chain systems for categorization
|
||||
> - allowSubdomain: whether to allow the new DID to register subdomains
|
||||
>
|
||||
> The metadata cannot be changed after registration. If the ownership is transferred in the future, the new DID record will be written to the `latestDid` tag.
|
||||
|
||||
## Tag
|
||||
|
||||
### Get the number of tags defined by a name
|
||||
|
||||
`getDefinedTagCount(name)` returns how many tags are defined by a specified TName.
|
||||
|
||||
### Get tag name
|
||||
|
||||
Used with the above interface, `getDefinedTagNameByIndex(name, index)` returns a single tag name and `getDefinedTagNames(name)` returns all tag names defined by a specified TName.
|
||||
|
||||
### Structured tag
|
||||
|
||||
If a tag type is a complicated structure instead of primitive value, call `getTagType(name, tagName)` to query the structure definition and then call `getFieldNamesEventBlock(fieldNamesHash)` with previously returned **fieldNamesHash** to get the block number at which this tag is defined. Finally, use the `ethers` library to get field names in the definition.
|
||||
|
||||
> [!NOTE]
|
||||
> The interface for querying tag type returns an encoded bytes of the ABI type, which should be parsed according to the code table. Querying field names can be complicated and error-prone, so we recommend to use functions in the SDK to fetch data about tags instead of calling the contract manually.
|
||||
|
||||
Call `getTagElem(definedDidName, valueDidName, tagName, elemPath)` to get the value of a tag after getting the tag type.
|
||||
|
||||
> [!NOTE]
|
||||
>
|
||||
> - definedDidName: the TName defining this tag
|
||||
> - valueDidName: the TName whose tag value is desired
|
||||
> - elemPath: path selector to read an inner element for tuples or arrays (`[]` for reading the full tag)
|
||||
>
|
||||
> This interface returns ABI-encoded data which should be parsed according to the tag type.
|
||||
> It is also recommended to use SDK instead of calling the contract manually.
|
||||
|
||||
### Define a tag
|
||||
|
||||
Call `defineTag(didName, tagName, abiType, fieldNames)` with the owner of `didName` to define a tag.
|
||||
|
||||
> [!NOTE]
|
||||
>
|
||||
> - abiType: data type of this tag following our **ABI** code format, which supports complicated structures
|
||||
> - fieldNames: the field names of structs inside this tag, flatten as a 2D string array using pre-order traversal
|
||||
|
||||
### CRUD
|
||||
|
||||
> [!NOTE]
|
||||
> We recommend to interact with the tagger contract instead of using the following interfaces to perform tag operations.
|
||||
|
||||
- Create - Call `addTag(defineDidName, valueDidName, tagName, value)` to add a tag.
|
||||
|
||||
- Update - Call `updateTagElem(defineDidName, valueDidName, tagName, elemPath, value)` to update a piece of data in a tag.
|
||||
|
||||
- Delete - Call `removeTag(defineDidName, valueDidName, tagName)` to delete a tag. This deletes a tag set on a DID instead of deleting the tag definition.
|
||||
|
||||
- Array operations - If the tag type contains an array, call `popTagElem(defineDidName, valueDidName, tagName, elePaths)` and `pushTagElem(defineDidName, valueDidName, tagName, elePaths, value)` to perform array-specific operations.
|
||||
|
||||
> [!NOTE]
|
||||
>
|
||||
> - defineDidName: the TName defining this tag
|
||||
> - valueDidName: the TName on which the tag value is set
|
||||
> - value: ABI-encoded tag value
|
||||
@@ -0,0 +1,23 @@
|
||||
---
|
||||
outline: [2, 3]
|
||||
---
|
||||
|
||||
# Environment
|
||||
|
||||
## Sepolia Optimistic
|
||||
|
||||
- TerminusDID: 0x4c8c98e652d6a01494971a8faF5d3b68338f9ED4
|
||||
- RootTagger: 0xaA5bE49799b6A71Eda74d22D01F7A808aFf41b3f
|
||||
- LibABI: 0xdc9e8faDe38eE9E2Eb43761f1553CD2360ecAEac
|
||||
|
||||
## Optimistic
|
||||
|
||||
- TerminusDID: 0x5da4fa8e567d86e52ef8da860de1be8f54cae97d
|
||||
- RootTagger: 0xe2eaba0979277a90511f8873ae1e8ca26b54e740
|
||||
- LibABI: 0x9ae3f16bd99294af1784beb1a0a5c84bf2636365
|
||||
|
||||
> [!NOTE]
|
||||
> RootTagger is the tagger for the following official tags: - DNSARecord - RSAPubKey - LatestDid - AuthAddress
|
||||
|
||||
> [!NOTE]
|
||||
> LibABI is an independent library contract, providing functions like ABI type encoding, data conversion etc.
|
||||
299
docs/developer/contribute/olares-id/contract/manage/sdk.md
Normal file
299
docs/developer/contribute/olares-id/contract/manage/sdk.md
Normal file
@@ -0,0 +1,299 @@
|
||||
---
|
||||
outline: [2, 3]
|
||||
---
|
||||
|
||||
# Management with SDK
|
||||
|
||||
## DID
|
||||
|
||||
### Get all DIDs
|
||||
|
||||
Sometimes we need complete data for statistical or other reasons. The following `fetchAll` method utilizes the contract interfaces to get complete data. Although it gets the result directly from on-chain interfaces instead of traversing Ethereum events, this can be time-consuming as the amount of data is large.
|
||||
|
||||
```Typescript
|
||||
import DID from 'did-contract-developer-components'
|
||||
|
||||
const RPC = "you-rpc-url"
|
||||
const CONTRACT_DID = "0x5da4fa8e567d86e52ef8da860de1be8f54cae97d"
|
||||
const CONTRACT_ROOT_RESOLVER = "0xe2eaba0979277a90511f8873ae1e8ca26b54e740"
|
||||
const CONTRACT_ABI_TYPE = "0x9ae3f16bd99294af1784beb1a0a5c84bf2636365"
|
||||
|
||||
const fetch = async () => {
|
||||
const did = DID.createConsole(RPC, CONTRACT_DID, CONTRACT_ROOT_RESOLVER, CONTRACT_ABI_TYPE)
|
||||
|
||||
const dids = await did.fetchAll()
|
||||
|
||||
console.log('dids:', dids)
|
||||
|
||||
console.log('format dids:', await did.formatDatas(dids))
|
||||
}
|
||||
|
||||
fetch()
|
||||
```
|
||||
|
||||
> [!NOTE]
|
||||
> If running in development environment and logging is on, the fetching progress is shown during execution.
|
||||
|
||||
#### Fast fetch
|
||||
|
||||
For your convenience, the SDK provides two functions `formatDatas` and `loadDatas`. The data returned by `formatDatas` can be stored and it can be loaded by `loadDatas` next time to reduce syncing duration. A simpler way is to access the `/all` endpoint in the official **did-support** service, which can also be loaded by `loadDatas`.
|
||||
|
||||
### Query specific DID
|
||||
|
||||
After reading the above contract interfaces, you should notice that the contract does not provide a single interface for fetching complete data related to a DID. So we simplified the design of interfaces in the SDK, where `fetchDomain` returns complete data for a DID.
|
||||
|
||||
```Typescript
|
||||
import DID from 'did-contract-developer-components'
|
||||
|
||||
const RPC = "you-rpc-url"
|
||||
const CONTRACT_DID = "0x5da4fa8e567d86e52ef8da860de1be8f54cae97d"
|
||||
const CONTRACT_ROOT_RESOLVER = "0xe2eaba0979277a90511f8873ae1e8ca26b54e740"
|
||||
const CONTRACT_ABI_TYPE = "0x9ae3f16bd99294af1784beb1a0a5c84bf2636365"
|
||||
|
||||
const fetch = async () => {
|
||||
const did = DID.createConsole(RPC, CONTRACT_DID, CONTRACT_ROOT_RESOLVER, CONTRACT_ABI_TYPE)
|
||||
|
||||
const domain = await did.fetchDomain('james.myterminus.com')
|
||||
|
||||
console.log('did:', domain)
|
||||
}
|
||||
|
||||
fetch()
|
||||
```
|
||||
|
||||
#### Fast query
|
||||
|
||||
After you execute `loadDatas` in the above SDK examples, `fetchDomain` will first try to match local data and only fetch data on-chain if there is no data for this DID on local machine.
|
||||
|
||||
#### Update DID
|
||||
|
||||
If you are worried that fast query does not return the latest data, use `updateDomain` or `updateDomainById` to update local data.
|
||||
|
||||
#### Fuzzy matching
|
||||
|
||||
Like fast query, you can use the fuzzy matching function in SDK after loading data locally. The following two functions only match the local data:
|
||||
|
||||
```Typescript
|
||||
import DID from 'did-contract-developer-components'
|
||||
//... code
|
||||
|
||||
// Query DID by owner and return all subdomains
|
||||
const domainsByOwner = DID.Domain.findSubtreesByOwner(owner, did.treesCache)
|
||||
|
||||
//Query DID by did and return all subdomains
|
||||
const domainsByDid = DID.Domain.findSubtreesByDid(did, did.treesCache)
|
||||
|
||||
```
|
||||
|
||||
## Tag
|
||||
|
||||
### Get all tags of a DID
|
||||
|
||||
Unlike calling the contract directly, this function returns data with parsed tag structure and struct field names.
|
||||
|
||||
```Typescript
|
||||
import DID from 'did-contract-developer-components'
|
||||
|
||||
const RPC = "you-rpc-url"
|
||||
const CONTRACT_DID = "0x5da4fa8e567d86e52ef8da860de1be8f54cae97d"
|
||||
const CONTRACT_ROOT_RESOLVER = "0xe2eaba0979277a90511f8873ae1e8ca26b54e740"
|
||||
const CONTRACT_ABI_TYPE = "0x9ae3f16bd99294af1784beb1a0a5c84bf2636365"
|
||||
|
||||
const fetch = async () => {
|
||||
const did = DID.createConsole(RPC, CONTRACT_DID, CONTRACT_ROOT_RESOLVER, CONTRACT_ABI_TYPE)
|
||||
|
||||
const domain = await did.fetchDomain('james.myterminus.com')
|
||||
|
||||
if (domain == undefined) {
|
||||
throw new Error("not found");
|
||||
}
|
||||
|
||||
const tags = await DID.Domain.fetchAllTagType(domain, did.getContractDID())
|
||||
|
||||
console.log('tags:', tags)
|
||||
}
|
||||
|
||||
fetch()
|
||||
```
|
||||
|
||||
### Get all tag values of a DID
|
||||
|
||||
Like the above method, this function returns parsed data with JSON tag values.
|
||||
|
||||
```Typescript
|
||||
import DID from 'did-contract-developer-components'
|
||||
|
||||
const RPC = "you-rpc-url"
|
||||
const CONTRACT_DID = "0x5da4fa8e567d86e52ef8da860de1be8f54cae97d"
|
||||
const CONTRACT_ROOT_RESOLVER = "0xe2eaba0979277a90511f8873ae1e8ca26b54e740"
|
||||
const CONTRACT_ABI_TYPE = "0x9ae3f16bd99294af1784beb1a0a5c84bf2636365"
|
||||
|
||||
const fetch = async () => {
|
||||
const did = DID.createConsole(RPC, CONTRACT_DID, CONTRACT_ROOT_RESOLVER, CONTRACT_ABI_TYPE)
|
||||
|
||||
const domain = await did.fetchDomain('james.myterminus.com')
|
||||
|
||||
if (domain == undefined) {
|
||||
throw new Error("not found");
|
||||
}
|
||||
|
||||
await DID.Domain.fetchAllTagType(domain, did.getContractDID())
|
||||
|
||||
const tags = await DID.Domain.fetchAllTagValue(domain, did.getContractDID())
|
||||
|
||||
console.dir(tags, {depth: null});
|
||||
}
|
||||
|
||||
fetch()
|
||||
```
|
||||
|
||||
### Define tag
|
||||
|
||||
Using SDK to define a tag, you can construct the inner structure of the tag type with an object-oriented approach without worrying about the encoding. The following examples include most common data types.
|
||||
|
||||
```Typescript
|
||||
import DID from 'did-contract-developer-components'
|
||||
|
||||
const RPC = "you-rpc-url"
|
||||
const CONTRACT_DID = "0x5da4fa8e567d86e52ef8da860de1be8f54cae97d"
|
||||
const CONTRACT_ROOT_RESOLVER = "0xe2eaba0979277a90511f8873ae1e8ca26b54e740"
|
||||
const CONTRACT_ABI_TYPE = "0x9ae3f16bd99294af1784beb1a0a5c84bf2636365"
|
||||
|
||||
const defineTag = async () => {
|
||||
|
||||
// tag name: simpleTag
|
||||
const tagName = 'simpleTagBox'
|
||||
|
||||
// tuple
|
||||
const testTuple = new DID.Tag.TagValueTypeTuple(undefined, undefined, true);
|
||||
|
||||
// uint
|
||||
const testUint = new DID.Tag.TagValueTypeUint(undefined, undefined, true);
|
||||
testUint.setSize(8)
|
||||
|
||||
// address
|
||||
const testAddress = new DID.Tag.TagValueTypeAddress(undefined, undefined, true);
|
||||
|
||||
// array<address>
|
||||
const testArrayAddress = new DID.Tag.TagValueTypeArray(undefined, undefined, true);
|
||||
testArrayAddress.setBuliderType(testAddress)
|
||||
|
||||
// bool
|
||||
const testBool= new DID.Tag.TagValueTypeBool(undefined, undefined, true)
|
||||
|
||||
// bytes
|
||||
const testBytes = new DID.Tag.TagValueTypeBytes(undefined, undefined, true)
|
||||
|
||||
// int
|
||||
const testInt = new DID.Tag.TagValueTypeInt(undefined, undefined, true)
|
||||
testInt.setSize(256)
|
||||
|
||||
// flarray<int>
|
||||
const testFlarrayInt = new DID.Tag.TagValueTypeFlarray(undefined, undefined, true)
|
||||
testFlarrayInt.setBuliderType(testInt)
|
||||
testFlarrayInt.setSize(3)
|
||||
|
||||
// flbytes
|
||||
const testFlbytes = new DID.Tag.TagValueTypeFlbytes(undefined, undefined, true)
|
||||
testFlbytes.setSize(5)
|
||||
|
||||
// string
|
||||
const testString = new DID.Tag.TagValueTypeString(undefined, undefined, true)
|
||||
|
||||
testTuple.setField('testUint', testUint)
|
||||
testTuple.setField('testArrayAddress', testArrayAddress)
|
||||
testTuple.setField('testBool', testBool)
|
||||
testTuple.setField('testBytes', testBytes)
|
||||
testTuple.setField('testFlarrayInt', testFlarrayInt)
|
||||
testTuple.setField('testFlbytes', testFlbytes)
|
||||
testTuple.setField('testString', testString)
|
||||
|
||||
const did = DID.createConsole(RPC, CONTRACT_DID, CONTRACT_ROOT_RESOLVER, CONTRACT_ABI_TYPE)
|
||||
|
||||
const domain = await did.fetchDomain('james.myterminus.com')
|
||||
|
||||
await DID.Domain.defineTag(domain, tagName, testTuple, did.getContractDIDByPrivateKey('you-private-key'), did)
|
||||
}
|
||||
|
||||
defineTag()
|
||||
```
|
||||
|
||||
### Set tagger
|
||||
|
||||
```Typescript
|
||||
import DID from 'did-contract-developer-components'
|
||||
|
||||
const RPC = "you-rpc-url"
|
||||
const CONTRACT_DID = "0x5da4fa8e567d86e52ef8da860de1be8f54cae97d"
|
||||
const CONTRACT_ROOT_RESOLVER = "0xe2eaba0979277a90511f8873ae1e8ca26b54e740"
|
||||
const CONTRACT_ABI_TYPE = "0x9ae3f16bd99294af1784beb1a0a5c84bf2636365"
|
||||
|
||||
const setTagger = async () => {
|
||||
|
||||
const did = DID.createConsole(RPC, CONTRACT_DID, CONTRACT_ROOT_RESOLVER, CONTRACT_ABI_TYPE)
|
||||
|
||||
const domain = await did.fetchDomain('james.myterminus.com')
|
||||
|
||||
if (domain == undefined) {
|
||||
throw new Error("not found");
|
||||
}
|
||||
|
||||
const [tag] = domain.tags.filter(tag => tag.name == 'simpleTagBox')
|
||||
|
||||
DID.Domain.setTagger(tag, 'you-tagger-address', did.getContractDIDByPrivateKey('you-private-key'))
|
||||
}
|
||||
|
||||
setTagger()
|
||||
```
|
||||
|
||||
### Set tag value
|
||||
|
||||
Like defining a tag above, when using SDK to set tag value, you only need to pass in suitable JSON data without worrying about the encoding. The tag types in the following examples are the same as the tag definition section above.
|
||||
|
||||
```Typescript
|
||||
import DID from 'did-contract-developer-components'
|
||||
|
||||
const RPC = "you-rpc-url"
|
||||
const CONTRACT_DID = "0x5da4fa8e567d86e52ef8da860de1be8f54cae97d"
|
||||
const CONTRACT_ROOT_RESOLVER = "0xe2eaba0979277a90511f8873ae1e8ca26b54e740"
|
||||
const CONTRACT_ABI_TYPE = "0x9ae3f16bd99294af1784beb1a0a5c84bf2636365"
|
||||
|
||||
const setTagValue = async () => {
|
||||
const did = DID.createConsole(RPC, CONTRACT_DID, CONTRACT_ROOT_RESOLVER, CONTRACT_ABI_TYPE)
|
||||
|
||||
const domain = await did.fetchDomain('james.myterminus.com')
|
||||
|
||||
if (domain == undefined) {
|
||||
throw new Error("not found");
|
||||
}
|
||||
|
||||
console.log(domain)
|
||||
const [tag] = domain.tags.filter(tag => tag.name == 'simpleTagBox')
|
||||
const tagType = await DID.Domain.fetchTagStructure(tag, did.getContractDID())
|
||||
console.dir(tagType, {depth: null})
|
||||
|
||||
const ba1 = ethers.hexlify(Uint8Array.from([1, 2, 3]))
|
||||
const ba2 = ethers.hexlify(Uint8Array.from([10, 18, 19]))
|
||||
|
||||
const newData = {
|
||||
testbox: {
|
||||
testUint: 1,
|
||||
testArrayAddress: ['0xF18B2Ea28c722CA87f951F5bF5327b66a7dd72A3', '0xecBA1d33b889f66ad426535f970d1E033ba5c79C'],
|
||||
testBool: true,
|
||||
testBytes: '0x0102030405' ,
|
||||
testFlarrayInt: [2, 3, 4],
|
||||
testFlbytes: '0x0a0b0c0d0e',
|
||||
testString: 'ok'
|
||||
}
|
||||
}
|
||||
console.log('newData', newData)
|
||||
|
||||
const call = await DID.Tag.doEncode(tagType, newData)
|
||||
console.log('call', call)
|
||||
|
||||
//set
|
||||
const resp = await DID.Domain.setValue(tag, call, did.getContractDIDByPrivateKey('you-private-key'))
|
||||
}
|
||||
|
||||
setTagValue()
|
||||
```
|
||||
26
docs/developer/contribute/olares-id/index.md
Normal file
26
docs/developer/contribute/olares-id/index.md
Normal file
@@ -0,0 +1,26 @@
|
||||
---
|
||||
# https://vitepress.dev/reference/default-theme-home-page
|
||||
layout: home
|
||||
|
||||
hero:
|
||||
name: "Snowinning Protocol"
|
||||
text: ""
|
||||
tagline: Building a Self-Sovereign Internet
|
||||
actions:
|
||||
- theme: brand
|
||||
text: What is Snowinning
|
||||
link: /protocol/overview.md
|
||||
- theme: alt
|
||||
text: Vist GitHub
|
||||
link: https://github.com/beclab/terminus
|
||||
|
||||
features:
|
||||
- title: Snowinning Protocol
|
||||
details: A decentralized identity and credit system that facilitates secure, trustless exchanges of information and value.
|
||||
- title: Smart Contract
|
||||
details: Snowinning Protocol's smart contract consists of DID Registry and the extended reputation systems based on DID.
|
||||
|
||||
- title: Verifiable Credential (VC)
|
||||
details: Fully ratified W3C standard that work together with DIDs to enable trustless, secure interactions.
|
||||
---
|
||||
|
||||
@@ -0,0 +1,186 @@
|
||||
# Issuer
|
||||
|
||||

|
||||
|
||||
The following is the issuer process:
|
||||
|
||||
1. Holder gets the Manifest from Issuer.
|
||||
2. Holder signs it and submits the Application.
|
||||
3. Issuer reviews the Application automatically or manually.
|
||||
4. Holder receives the review results from the Issuer and either gets the VC if approved or a reason if rejected.
|
||||
|
||||
## Manifest
|
||||
|
||||
This file will be returned to Holder.
|
||||
`outputDescriptors` is given for wallets to display VCs.
|
||||
`presentationDefinition` is in fact the later `manifest_presentation` file, used to confirm the format of Application submitted by users.
|
||||
|
||||
```json
|
||||
{
|
||||
"name": "Facebook Verifiable Credential Manifest",
|
||||
"description": "Facebook Verifiable Credential Manifest",
|
||||
"issuerDid": "",
|
||||
"issuerName": "",
|
||||
"outputDescriptors": [
|
||||
{
|
||||
"id": "",
|
||||
"schema": "",
|
||||
"name": "Facebook Verifiable Credential Manifest",
|
||||
"description": "Facebook Verifiable Credential Manifest",
|
||||
"display": {
|
||||
"title": {
|
||||
"path": ["$.credentialSubject.name", "$.vc.credentialSubject.name"],
|
||||
"schema": { "type": "string" }
|
||||
},
|
||||
"subtitle": {
|
||||
"path": ["$.credentialSubject.title", "$.vc.credentialSubject.title"],
|
||||
"schema": { "type": "string" }
|
||||
},
|
||||
"description": {
|
||||
"path": [
|
||||
"$.credentialSubject.description",
|
||||
"$.vc.credentialSubject.description"
|
||||
],
|
||||
"schema": { "type": "string" }
|
||||
},
|
||||
"properties": [
|
||||
{
|
||||
"path": ["$.credentialSubject.id", "$.vc.credentialSubject.id"],
|
||||
"schema": { "type": "string" },
|
||||
"label": "ID"
|
||||
},
|
||||
{
|
||||
"path": [
|
||||
"$.credentialSubject.email",
|
||||
"$.vc.credentialSubject.email"
|
||||
],
|
||||
"schema": { "type": "string" },
|
||||
"label": "Email"
|
||||
}
|
||||
]
|
||||
},
|
||||
"styles": {
|
||||
"background": {
|
||||
"color": "#FFFFFF"
|
||||
},
|
||||
"text": {
|
||||
"color": "#000000"
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"format": {
|
||||
"jwt_vc": {
|
||||
"alg": ["EdDSA"]
|
||||
}
|
||||
},
|
||||
"presentationDefinition": {}
|
||||
}
|
||||
```
|
||||
|
||||
## Manifest Presentation
|
||||
|
||||
Issuer uses this file to validate the format of the Application submitted by the Holder.
|
||||
|
||||
```json
|
||||
{
|
||||
"name": "Facebook Manifest Presentation Definition",
|
||||
"purpose": "Provide your token required to Facebook",
|
||||
"inputDescriptors": [
|
||||
{
|
||||
"id": "token",
|
||||
"name": "Access Token",
|
||||
"purpose": "Provide your token required to Facebook",
|
||||
"format": {
|
||||
"jwt_vc": {
|
||||
"alg": ["EdDSA"]
|
||||
}
|
||||
},
|
||||
"constraints": {
|
||||
"fields": [
|
||||
{
|
||||
"path": ["$.credentialSubject.token"]
|
||||
}
|
||||
],
|
||||
"subject_is_issuer": "preferred"
|
||||
}
|
||||
}
|
||||
],
|
||||
"author": ""
|
||||
}
|
||||
```
|
||||
|
||||
## Application Verifiable Credential
|
||||
|
||||
Although users only need `manifest_presentation` to construct VC data in client, servers need a schema to verify whether `manifest_presentation` meets the format requirements.
|
||||
This file will be returned to Holder so that Holder knows the format of data required to submit for verification.
|
||||
In the scenarios of Facebook, Twitter and Gmail, users login in client and get the access token, then submit it to the Issuer server, which can get the basic information of the user with the access token from e.g. the Facebook server etc. So users only need to submit the token which is simple.
|
||||
But in the scenario of KYC, users need to submit full name, ID photo or even verification video etc., and the fields in this file can become much more complicated.
|
||||
|
||||
```json
|
||||
{
|
||||
"author": "",
|
||||
"name": "Facebook Verifiable Credential Request Schema",
|
||||
"schema": {
|
||||
"$id": "facebook-schema-1.0",
|
||||
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
||||
"description": "Facebook Verifiable Credential Schema",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"token": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": ["token"],
|
||||
"additionalProperties": true
|
||||
},
|
||||
"sign": false
|
||||
}
|
||||
```
|
||||
|
||||
## Verifiable Credential
|
||||
|
||||
The VC format returned to Holder by Issuer
|
||||
|
||||
```json
|
||||
{
|
||||
"author": "",
|
||||
"name": "Facebook Verifiable Credential Schema",
|
||||
"schema": {
|
||||
"$id": "facebook-schema-1.0",
|
||||
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
||||
"description": "Facebook Verifiable Credential Schema",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"name": {
|
||||
"type": "string"
|
||||
},
|
||||
"title": {
|
||||
"type": "string"
|
||||
},
|
||||
"description": {
|
||||
"type": "string"
|
||||
},
|
||||
|
||||
"facebook_name": {
|
||||
"type": "string"
|
||||
},
|
||||
"profile_image": {
|
||||
"type": "string"
|
||||
},
|
||||
"email": {
|
||||
"type": "string"
|
||||
},
|
||||
"facebook_id": {
|
||||
"type": "string"
|
||||
},
|
||||
"picture_is_silhouette": {
|
||||
"type": "boolean"
|
||||
}
|
||||
},
|
||||
"required": ["name", "title", "description", "facebook_name"],
|
||||
"additionalProperties": true
|
||||
},
|
||||
"sign": false
|
||||
}
|
||||
```
|
||||
@@ -0,0 +1,46 @@
|
||||
# Use case with Olares
|
||||
|
||||
While DIDs solve the issue of identity in a decentralized network, they are typically difficult for humans to remember or use in daily situations. Olares ID provides a familiar, easy-to-remember format similar to email addresses, while still leveraging the power and security of DIDs. Each Olares ID is bound to a DID.
|
||||
|
||||
## Potential fairness issues
|
||||
|
||||
The **first-come, first-served** system in Olares ID registration may present some fairness issues, such as:
|
||||
|
||||
1. **Fraud:** For instance, the Olares ID `elonmusk@myterminus.com` might be registered by someone who isn't actually Elon Mask.
|
||||
2. **Speculation:** Pre-registration of popular names could lead to speculation, potentially boosting early network activity, but at the cost of fairness.
|
||||
|
||||
## VC process for Olares ID
|
||||
|
||||
To address the potential faireness concerns, we adopted principles from **Self-Sovereign Identity (SSI)** services proposed by the Web5 team, along with the [VC process](/manual/concepts/vc.md#verification-process) of Olares ID. This led us to design an **Issuer and Verifier** process to assist users in applying for a **Olares ID**.
|
||||
|
||||

|
||||
|
||||
### Gmail issuer service
|
||||
|
||||
We utilize Google's OAuth process to facilitate the issuance of **Verifiable Credentials (VCs)**. The simplified process is as follows:
|
||||
|
||||
1. Alice logs into her Gmail account via OAuth in LarePass, the wallet client.
|
||||
2. Google returns the OAuth credentials to LarePass.
|
||||
3. LarePass submits the OAuth credentials to the Issuer.
|
||||
4. The Issuer confirms the validity of the credentials with Google's servers and retrieves basic information (e.g., email name).
|
||||
5. The Issuer issues a VC to Alice that matches the local part of her Gmail address.
|
||||
|
||||
Alice can now store the issued VC in LarePass.
|
||||
|
||||
:::tip NOTE
|
||||
- Throughout the process, Alice only reveals basic account data within the scope of the credential authorization to LarePass and the Issuer service, with password and privacy protection ensured by Google's OAuth protocol.
|
||||
- All the code for setting up a Gmail Issuer Service or other Web2 service Issuer Services are open sourced on GitHub.
|
||||
:::
|
||||
|
||||
### Olares ID verifier service
|
||||
|
||||
Here's how the **Verifier Service** works on the Olares end:
|
||||
|
||||
1. Alice packages her DID, Olares ID, and Gmail VC into a **Verifiable Presentation (VP)** and submits the VP with its signature to the Verifier Service.
|
||||
2. The Verifier Service checks:
|
||||
- The signature's validity.
|
||||
- The validity of the VC in the VP.
|
||||
- Whether the Olares ID can be registered on the blockchain (conflicts may arise if multiple channels, such as Gmail and Twitter, are used for VC information).
|
||||
3. After all checks pass, the Verifier Service submits Alice's information to the blockchain and covers the Gas fees.
|
||||
|
||||
At this point, Alice successfully obtains her **Olares ID**. For example, if you apply with the Gmail address "hello@gmail.com", you'll receive the Olares ID "hello@myterminus.com" once all checks are completed.
|
||||
@@ -0,0 +1,55 @@
|
||||
# VC Service
|
||||
|
||||
The purpose of this documentation is to help you understand how to configure various schemas and create Issuers and Verifiers for your own scenarios using:
|
||||
- [verifiable-credential-gate](https://github.com/Above-Os/verifiable-credential-gate) and [did-gate](https://github.com/Above-Os/did-gate) by Terminus.
|
||||
- [SSI Service](https://github.com/TBD54566975/ssi-service) by the tbd team.
|
||||
|
||||
::: tip
|
||||
If you want to engage in lower-level development, read the [protocol standard](#reference) together with the source code in [SSI SDK](https://github.com/TBD54566975/ssi-sdk).
|
||||
:::
|
||||
|
||||
## Introduction
|
||||
|
||||
We have learned about [VC](/manual/concepts/vc.md) and the basic process for applying VCs.
|
||||
|
||||
Before we get into the implementation details, we can familiarize ourselves with the terms that we will encounter in the real communication process of Wallet, Verifier and Issuer.
|
||||
| Term | Definition |
|
||||
| ----------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| Holder | Holders are entities that have one or more verifiable credentials in their possession. Holders are also the entities that submit proofs to Verifiers to satisfy the requirements described in a Presentation Definition. |
|
||||
| Issuer | A role an entity can perform by asserting claims about one or more subjects, creating a verifiable credential from these claims, and transmitting the verifiable credential to a holder. |
|
||||
| Verifier | Verifiers are entities that define what proofs they require from a Holder (via a Presentation Definition) in order to proceed with an interaction. |
|
||||
| Verifiable Credential | Is a tamper-evident credential that has authorship that can be cryptographically verified. Verifiable credentials can be used to build Verifiable Presentations, which can also be cryptographically verified. The claims in a credential can be about different subjects. PEX accepts Verifiable credential in 3 forms: 1. JSON_LD which is known in our system as IVerifiableCredential, 2. JWT-Wrapped VC which is known in our system as JwtWrappedVerifiableCredential or string which is a valid Verifiable credential jwt |
|
||||
| Verifiable Presentation | s a tamper-evident presentation encoded in such a way that authorship of the data can be trusted after a process of cryptographic verification. |
|
||||
| Manifest | Credential Manifests are used to describe which credentials are available for issuance. |
|
||||
| Application | The format provided by Holder to Issuer, including |
|
||||
| Presentation Definition | Presentation Definitions are objects that articulate what proofs a Verifier requires. |
|
||||
| Presentation | Data derived from one or more verifiable credentials, issued by one or more issuers |
|
||||
| Submission | TBC |
|
||||
| Definition | TBC |
|
||||
| Schema | All different Manifest, Application, Credential, Presentation, Definition need to define Schema with JSON. The service will verify the correctness of submitted data and then go into business process. |
|
||||
|
||||
## Reference
|
||||
|
||||
The following reference materials come from the [SSI SDK](https://github.com/TBD54566975/ssi-sdk) project.
|
||||
|
||||
### Specifications
|
||||
|
||||
Here are a set of references to specifications that this library currently supports. It is a dynamic set that will change as the library evolves.
|
||||
|
||||
- [Decentralized Identifiers (DIDs) v1.0](https://www.w3.org/TR/did-core/) W3C Proposed Recommendation 03 August 2021
|
||||
- [Verifiable Credentials Data Model v1.1](https://www.w3.org/TR/vc-data-model/) W3C Recommendation 09 November 2021
|
||||
- Supports [Linked Data Proof](https://www.w3.org/TR/vc-data-model/#data-integrity-proofs) formats.
|
||||
- Supports [VC-JWT and VP-JWT](https://www.w3.org/TR/vc-data-model/#json-web-token) formats.
|
||||
- [Verifiable Credentials JSON Schema Specification](https://w3c-ccg.github.io/vc-json-schemas/v2/index.html) Draft Community Group Report, 21 September 2021
|
||||
- [Presentation Exchange 2.0.0](https://identity.foundation/presentation-exchange/) Working Group Draft, March 2022
|
||||
- [Wallet Rendering Strawman](https://identity.foundation/wallet-rendering/), June 2022
|
||||
- [Credential Manifest](https://identity.foundation/credential-manifest/) Strawman, June 2022
|
||||
- [Status List 2021](https://w3c-ccg.github.io/vc-status-list-2021/) Draft Community Group Report 04 April 2022
|
||||
|
||||
### Signing Methods
|
||||
|
||||
> - [Data Integrity 1.0](https://w3c.github.io/vc-data-integrity/) Draft Community Group Report
|
||||
> - [Linked Data Cryptographic Suite Registry](https://w3c-ccg.github.io/ld-cryptosuite-registry/) Draft Community Group Report 29 December 2020
|
||||
> - [JSON Web Signature 2020](https://w3c-ccg.github.io/lds-jws2020/) Draft Community Group Report 09 February 2022
|
||||
> - [VC Proof Formats Test Suite, VC Data Model with JSON Web Signatures](https://identity.foundation/JWS-Test-Suite/) Unofficial Draft 09 March 2022 This implementation's compliance with the JWS Test Suite can be found here.
|
||||
> - Supports both JWT and Linked Data proof formats with [JOSE compliance](https://jose.readthedocs.io/en/latest/).
|
||||
@@ -0,0 +1,164 @@
|
||||
# Verifer Service
|
||||
|
||||
Refer to [Presentation Exchange](https://identity.foundation/presentation-exchange/)
|
||||
 for the process.
|
||||
|
||||
## Presentation Definition
|
||||
|
||||
1. The Verifier returns the file to the Holder.
|
||||
2. The Holder submits a packaged file that meets the format requirements to the Verifier, after filling in the contents according to the specifications.
|
||||
|
||||
```json
|
||||
{
|
||||
"name": "Facebook Basic Info Presentation Definition",
|
||||
"purpose": "Provide your facebook basic info",
|
||||
"inputDescriptors": [
|
||||
{
|
||||
"id": "name",
|
||||
"name": "Name",
|
||||
"purpose": "Provide vc name",
|
||||
"format": {
|
||||
"jwt_vc": {
|
||||
"alg": ["EdDSA"]
|
||||
}
|
||||
},
|
||||
"constraints": {
|
||||
"fields": [
|
||||
{
|
||||
"path": ["$.credentialSubject.name"]
|
||||
}
|
||||
],
|
||||
"subject_is_issuer": "preferred"
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "title",
|
||||
"name": "Title",
|
||||
"purpose": "Provide vc title",
|
||||
"format": {
|
||||
"jwt_vc": {
|
||||
"alg": ["EdDSA"]
|
||||
}
|
||||
},
|
||||
"constraints": {
|
||||
"fields": [
|
||||
{
|
||||
"path": ["$.credentialSubject.title"]
|
||||
}
|
||||
],
|
||||
"subject_is_issuer": "preferred"
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "description",
|
||||
"name": "description",
|
||||
"purpose": "Provide vc description",
|
||||
"format": {
|
||||
"jwt_vc": {
|
||||
"alg": ["EdDSA"]
|
||||
}
|
||||
},
|
||||
"constraints": {
|
||||
"fields": [
|
||||
{
|
||||
"path": ["$.credentialSubject.description"]
|
||||
}
|
||||
],
|
||||
"subject_is_issuer": "preferred"
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
"id": "facebook_name",
|
||||
"name": "Provide your facebook name",
|
||||
"purpose": "Provide your facebook name",
|
||||
"format": {
|
||||
"jwt_vc": {
|
||||
"alg": ["EdDSA"]
|
||||
}
|
||||
},
|
||||
"constraints": {
|
||||
"fields": [
|
||||
{
|
||||
"path": ["$.credentialSubject.facebook_name"]
|
||||
}
|
||||
],
|
||||
"subject_is_issuer": "preferred"
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "profile_image",
|
||||
"name": "Provide your facebook profile image",
|
||||
"purpose": "Provide your facebook profile image",
|
||||
"format": {
|
||||
"jwt_vc": {
|
||||
"alg": ["EdDSA"]
|
||||
}
|
||||
},
|
||||
"constraints": {
|
||||
"fields": [
|
||||
{
|
||||
"path": ["$.credentialSubject.profile_image"]
|
||||
}
|
||||
],
|
||||
"subject_is_issuer": "preferred"
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "email",
|
||||
"name": "Provide your facebook email email info",
|
||||
"purpose": "Provide your facebook email info",
|
||||
"format": {
|
||||
"jwt_vc": {
|
||||
"alg": ["EdDSA"]
|
||||
}
|
||||
},
|
||||
"constraints": {
|
||||
"fields": [
|
||||
{
|
||||
"path": ["$.credentialSubject.email"]
|
||||
}
|
||||
],
|
||||
"subject_is_issuer": "preferred"
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "facebook_id",
|
||||
"name": "Provide your facebook id",
|
||||
"purpose": "Provide your facebook id",
|
||||
"format": {
|
||||
"jwt_vc": {
|
||||
"alg": ["EdDSA"]
|
||||
}
|
||||
},
|
||||
"constraints": {
|
||||
"fields": [
|
||||
{
|
||||
"path": ["$.credentialSubject.facebook_id"]
|
||||
}
|
||||
],
|
||||
"subject_is_issuer": "preferred"
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "picture_is_silhouette",
|
||||
"name": "Provide your facebook Picture is Silhouette",
|
||||
"purpose": "Provide your facebook picture_is_silhouette",
|
||||
"format": {
|
||||
"jwt_vc": {
|
||||
"alg": ["EdDSA"]
|
||||
}
|
||||
},
|
||||
"constraints": {
|
||||
"fields": [
|
||||
{
|
||||
"path": ["$.credentialSubject.picture_is_silhouette"]
|
||||
}
|
||||
],
|
||||
"subject_is_issuer": "preferred"
|
||||
}
|
||||
}
|
||||
],
|
||||
"author": ""
|
||||
}
|
||||
```
|
||||
92
docs/developer/contribute/olares.md
Normal file
92
docs/developer/contribute/olares.md
Normal file
@@ -0,0 +1,92 @@
|
||||
# Olares
|
||||
|
||||
## Directory structure
|
||||
|
||||
```
|
||||
olares
|
||||
|-- apps # olares built-in apps
|
||||
| |-- agent
|
||||
| |-- analytic
|
||||
| |-- market
|
||||
| |-- market-server
|
||||
| |-- argo
|
||||
| |-- desktop
|
||||
| |-- devbox
|
||||
| |-- vault
|
||||
| |-- files
|
||||
| |-- knowledge
|
||||
| |-- nitro
|
||||
| |-- notifications
|
||||
| |-- profile
|
||||
| |-- rss
|
||||
| |-- search
|
||||
| |-- settings
|
||||
| |-- system-apps
|
||||
| |-- wise
|
||||
| |-- wizard
|
||||
|-- build # olares installer
|
||||
| |-- installer
|
||||
| |-- manifest
|
||||
|-- frameworks # system runtime frameworks
|
||||
| |-- app-service
|
||||
| |-- backup-server
|
||||
| |-- bfl
|
||||
| |-- GPU
|
||||
| |-- l4-bfl-proxy
|
||||
| |-- osnode-init
|
||||
| |-- system-server
|
||||
| |-- tapr
|
||||
|-- libs # toolkit libs
|
||||
| |-- fs-lib
|
||||
|-- scripts # scripts for build or package the olares installer
|
||||
|-- third-party # third party libs or apps integrated in olares
|
||||
| |-- authelia
|
||||
| |-- headscale
|
||||
| |-- infisical
|
||||
| |-- juicefs
|
||||
| |-- ks-console
|
||||
| |-- ks-installer
|
||||
| |-- kube-state-metrics
|
||||
| |-- notification-mananger
|
||||
| |-- predixy
|
||||
| |-- redis-cluster-operator
|
||||
| |-- seafile-server
|
||||
| |-- seahub
|
||||
| |-- tailscale
|
||||
```
|
||||
|
||||
## How to install
|
||||
|
||||
```
|
||||
curl -fsSL https://olares.sh | bash -
|
||||
```
|
||||
|
||||
## How to build
|
||||
|
||||
```
|
||||
git clone https://github.com/beclab/olares
|
||||
|
||||
cd olares
|
||||
|
||||
bash scripts/build.sh
|
||||
|
||||
```
|
||||
|
||||
Run the above scripts, you will get the debug version installer package `install-wizard-debug.tar.gz`
|
||||
|
||||
## How to install debug version
|
||||
|
||||
```
|
||||
mkdir -p /path/to/unpack && cd /path/to/unpack
|
||||
|
||||
tar zxvf /path/to/olares/install-wizard-debug.tar.gz
|
||||
|
||||
make install VERSION=0.0.0-DEBUG
|
||||
|
||||
```
|
||||
|
||||
## How to uninstall
|
||||
|
||||
```bash
|
||||
olares-cli uninstall --all
|
||||
```
|
||||
7
docs/developer/contribute/overview.md
Normal file
7
docs/developer/contribute/overview.md
Normal file
@@ -0,0 +1,7 @@
|
||||
# Contributing To Olares
|
||||
|
||||
## Olares
|
||||
|
||||
## TermiPass
|
||||
|
||||
## Develop System App
|
||||
295
docs/developer/contribute/system-app/deployment.md
Normal file
295
docs/developer/contribute/system-app/deployment.md
Normal file
@@ -0,0 +1,295 @@
|
||||
---
|
||||
outline: [2, 3]
|
||||
---
|
||||
|
||||
# deployment.yaml
|
||||
|
||||
The system application need to be installed under the `user-space` namespace. Therefore, certain modifications are required:
|
||||
|
||||
1. Modify the `deployment.yaml` file in the Olares Application Chart.
|
||||
2. Change the original namespace of `deployment` and `service` to `user-space-{\\{ .Values.bfl.username }}`
|
||||
|
||||
```Yaml
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: desktop-dev
|
||||
namespace: user-space-{{ .Values.bfl.username }}
|
||||
```
|
||||
|
||||
3. Add `annotations` and `labels` according to the configuration in the `deployment.yaml` file of the app in **Olares**.
|
||||
|
||||
```Yaml
|
||||
metadata:
|
||||
name: desktop-dev
|
||||
namespace: user-space-{{ .Values.bfl.username }}
|
||||
labels:
|
||||
app: desktop-dev
|
||||
applications.app.bytetrade.io/name: desktop-dev
|
||||
applications.app.bytetrade.io/owner: {{ .Values.bfl.username }}
|
||||
applications.app.bytetrade.io/author: bytetrade.io
|
||||
annotations:
|
||||
applications.app.bytetrade.io/icon: https://docs-dev.olares.com/icon.png
|
||||
applications.app.bytetrade.io/title: Desktop-dev
|
||||
applications.app.bytetrade.io/version: '0.0.1'
|
||||
|
||||
# Configuration of entrances here should be consistent with the configuration in OlaresManifest.yaml.
|
||||
applications.app.bytetrade.io/entrances: '[{"name":"desktop-frontend-dev", "host":"desktop-svc-dev", "port":80,"title":"Desktop-dev"}]'
|
||||
```
|
||||
|
||||
4. Modify service
|
||||
|
||||
```Yaml
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: desktop-svc-dev
|
||||
namespace: user-space-{{ .Values.bfl.username }}
|
||||
spec:
|
||||
selector:
|
||||
app: desktop-dev
|
||||
ports:
|
||||
- protocol: TCP
|
||||
port: 80
|
||||
targetPort: 8080 # Please note, the port of the Node.js dev container is 8080. please switch to this port.
|
||||
```
|
||||
|
||||
5. Modify the section of entrances in `OlaresManifest.yaml`
|
||||
|
||||
```Yaml
|
||||
entrances:
|
||||
- name: desktop-frontend-dev # Same with annotation in deployment
|
||||
host: desktop-svc-dev # Same with the name in service
|
||||
port: 80
|
||||
icon: https://file.bttcdn.com/appstore/default/defaulticon.webp
|
||||
title: Desktop-dev
|
||||
authLevel: private
|
||||
openMethod: default
|
||||
```
|
||||
|
||||
6. Add service to provide `app-service` installation check
|
||||
|
||||
```Yaml
|
||||
# provide `app-service` installation check
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: desktop-svc-dev # Same with the name in original service
|
||||
namespace: {{ .Release.Namespace }}
|
||||
spec:
|
||||
type: ExternalName
|
||||
externalName: desktop-svc-dev.user-space-{{ .Values.bfl.username }}.svc.cluster.local
|
||||
ports:
|
||||
- protocol: TCP
|
||||
name: desktop
|
||||
port: 80
|
||||
targetPort: 80
|
||||
```
|
||||
|
||||
7. If you need to add a `local cache` or require access to the `user directory` in `JuiceFS`, you can add
|
||||
|
||||
```Yaml
|
||||
volumes:
|
||||
- name: appdata
|
||||
hostPath:
|
||||
type: DirectoryOrCreate
|
||||
path: {{ .Values.userspace.appData }}/desktop-dev
|
||||
|
||||
- name: userdata
|
||||
hostPath:
|
||||
type: DirectoryOrCreate
|
||||
path: {{ .Values.userspace.userData }}/desktop-dev
|
||||
|
||||
- name: appcache
|
||||
hostPath:
|
||||
type: DirectoryOrCreate
|
||||
path: {{ .Values.userspace.appCache }}/desktop-dev
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
:::details Example of a complete `deployment.yaml` file
|
||||
|
||||
```YAML
|
||||
---
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: desktop-dev
|
||||
namespace: user-space-{{ .Values.bfl.username }}
|
||||
labels:
|
||||
app: desktop-dev
|
||||
applications.app.bytetrade.io/name: desktop-dev
|
||||
applications.app.bytetrade.io/owner: {{ .Values.bfl.username }}
|
||||
applications.app.bytetrade.io/author: bytetrade.io
|
||||
annotations:
|
||||
applications.app.bytetrade.io/icon: https://docs-dev.olares.com/icon.png
|
||||
applications.app.bytetrade.io/title: Desktop-dev
|
||||
applications.app.bytetrade.io/version: '0.0.1'
|
||||
applications.app.bytetrade.io/entrances: '[{"name":"desktop-frontend-dev", "host":"desktop-svc-dev", "port":80,"title":"Desktop-dev"}]'
|
||||
spec:
|
||||
replicas: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
app: desktop-dev
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: desktop-dev
|
||||
spec:
|
||||
volumes:
|
||||
- name: olares-sidecar-config
|
||||
configMap:
|
||||
name: sidecar-configs
|
||||
items:
|
||||
- key: envoy.yaml
|
||||
path: envoy.yaml
|
||||
- name: appdata
|
||||
hostPath:
|
||||
type: DirectoryOrCreate
|
||||
path: {{ .Values.userspace.appData }}/desktop-dev
|
||||
|
||||
- name: userdata
|
||||
hostPath:
|
||||
type: DirectoryOrCreate
|
||||
path: {{ .Values.userspace.userData }}/desktop-dev
|
||||
|
||||
- name: appcache
|
||||
hostPath:
|
||||
type: DirectoryOrCreate
|
||||
path: {{ .Values.userspace.appCache }}/desktop-dev
|
||||
|
||||
initContainers:
|
||||
- name: olares-sidecar-init
|
||||
image: openservicemesh/init:v1.2.3
|
||||
imagePullPolicy: IfNotPresent
|
||||
securityContext:
|
||||
privileged: true
|
||||
capabilities:
|
||||
add:
|
||||
- NET_ADMIN
|
||||
runAsNonRoot: false
|
||||
runAsUser: 0
|
||||
command:
|
||||
- /bin/sh
|
||||
- -c
|
||||
- |
|
||||
iptables-restore --noflush <<EOF
|
||||
# sidecar interception rules
|
||||
*nat
|
||||
:PROXY_IN_REDIRECT - [0:0]
|
||||
:PROXY_INBOUND - [0:0]
|
||||
-A PROXY_IN_REDIRECT -p tcp -j REDIRECT --to-port 15003
|
||||
-A PROXY_INBOUND -p tcp --dport 15000 -j RETURN
|
||||
-A PROXY_INBOUND -p tcp -j PROXY_IN_REDIRECT
|
||||
-A PREROUTING -p tcp -j PROXY_INBOUND
|
||||
COMMIT
|
||||
EOF
|
||||
|
||||
env:
|
||||
- name: POD_IP
|
||||
valueFrom:
|
||||
fieldRef:
|
||||
apiVersion: v1
|
||||
fieldPath: status.podIP
|
||||
containers:
|
||||
- name: desktop
|
||||
image: "aboveos/node-ts-dev"
|
||||
imagePullPolicy: IfNotPresent
|
||||
ports:
|
||||
- name: port
|
||||
containerPort: 8080
|
||||
protocol: TCP
|
||||
resources:
|
||||
requests:
|
||||
cpu: "50m"
|
||||
memory: 100Mi
|
||||
limits:
|
||||
cpu: "0.5"
|
||||
memory: 2Gi
|
||||
volumeMounts:
|
||||
- name: appdata
|
||||
mountPath: /opt/code
|
||||
- name: appcache
|
||||
mountPath: /root/.config
|
||||
- name: olares-envoy-sidecar
|
||||
image: envoyproxy/envoy-distroless:v1.25.2
|
||||
imagePullPolicy: IfNotPresent
|
||||
securityContext:
|
||||
allowPrivilegeEscalation: false
|
||||
runAsUser: 1000
|
||||
ports:
|
||||
- name: proxy-admin
|
||||
containerPort: 15000
|
||||
- name: proxy-inbound
|
||||
containerPort: 15003
|
||||
volumeMounts:
|
||||
- name: olares-sidecar-config
|
||||
readOnly: true
|
||||
mountPath: /etc/envoy/envoy.yaml
|
||||
subPath: envoy.yaml
|
||||
command:
|
||||
- /usr/local/bin/envoy
|
||||
- --log-level
|
||||
- debug
|
||||
- -c
|
||||
- /etc/envoy/envoy.yaml
|
||||
env:
|
||||
- name: POD_UID
|
||||
valueFrom:
|
||||
fieldRef:
|
||||
fieldPath: metadata.uid
|
||||
- name: POD_NAME
|
||||
valueFrom:
|
||||
fieldRef:
|
||||
fieldPath: metadata.name
|
||||
- name: POD_NAMESPACE
|
||||
valueFrom:
|
||||
fieldRef:
|
||||
fieldPath: metadata.namespace
|
||||
- name: POD_IP
|
||||
valueFrom:
|
||||
fieldRef:
|
||||
fieldPath: status.podIP
|
||||
resources:
|
||||
requests:
|
||||
cpu: "50m"
|
||||
memory: 100Mi
|
||||
limits:
|
||||
cpu: "0.5"
|
||||
memory: 500Mi
|
||||
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: desktop-svc-dev
|
||||
namespace: user-space-{{ .Values.bfl.username }}
|
||||
spec:
|
||||
selector:
|
||||
app: desktop-dev
|
||||
ports:
|
||||
- protocol: TCP
|
||||
port: 80
|
||||
targetPort: 8080
|
||||
|
||||
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: desktop-svc-dev
|
||||
namespace: {{ .Release.Namespace }}
|
||||
spec:
|
||||
type: ExternalName
|
||||
externalName: desktop-svc-dev.user-space-{{ .Values.bfl.username }}.svc.cluster.local
|
||||
ports:
|
||||
- protocol: TCP
|
||||
name: desktop
|
||||
port: 80
|
||||
targetPort: 80
|
||||
```
|
||||
|
||||
:::
|
||||
239
docs/developer/contribute/system-app/install.md
Normal file
239
docs/developer/contribute/system-app/install.md
Normal file
@@ -0,0 +1,239 @@
|
||||
# Install System Application
|
||||
|
||||
## Install
|
||||
|
||||
Install the system app from **DevBox**. Due to the installation mechanism, the desktop may not receive proper notifications. Consequently, you might need to manually refresh the page to see the icon.
|
||||
|
||||

|
||||
|
||||
Once the application is successfully installed and in the **'Running'** state, you can access the default welcome page of VSCode. Simply click the **'Open IDE'** button on the **'Containers'** page.
|
||||
|
||||

|
||||
|
||||
::: tip
|
||||
There is no need to bind in this case.
|
||||
:::
|
||||
|
||||
## Clone Code
|
||||
|
||||
- Once you've entered the IDE, begin by installing the gh tool.
|
||||
|
||||
```shell
|
||||
apt install gh
|
||||
```
|
||||
|
||||
- Log in to GitHub
|
||||
|
||||
```shell
|
||||
gh auth login
|
||||
```
|
||||
|
||||
- Clone the code after logging in.
|
||||
|
||||
```shell
|
||||
cd /opt/code && gh repo clone beclab/desktop
|
||||
```
|
||||
:::tip
|
||||
It's recommended to clone the code into the `/opt/code` directory. This is because the `code server` is run by the `root`, while `nginx` is run by a `non-root user`. In this example, the `/opt/code` directory has been mounted to the `application data` directory of the node. So that, the code will remain saved even if the pod is restarted.
|
||||
:::
|
||||
|
||||
## Run the Application
|
||||
|
||||
Run your application in the terminal of the IDE. For example:
|
||||
|
||||
```sh
|
||||
npm run dev
|
||||
```
|
||||
|
||||
## Nginx
|
||||
|
||||
- Open the folder `/opt/code/desktop-v1` in **VS Code**
|
||||
|
||||
- To run debugging, first modify the `nginx` configuration in the container.
|
||||
|
||||
- Use **VS Code** to open the configuration file located at `/etc/nginx/conf.d/default.conf`.
|
||||
|
||||
- Modify the proxies for front-end and back-end testing.
|
||||
|
||||
```nginx
|
||||
location / {
|
||||
proxy_pass http://127.0.0.1:9000;
|
||||
proxy_set_header Host $http_host;
|
||||
proxy_set_header X-real-ip $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Upgrade $http_upgrade;
|
||||
proxy_set_header Connection $http_connection;
|
||||
proxy_set_header Accept-Encoding gzip;
|
||||
}
|
||||
|
||||
location /api {
|
||||
proxy_pass http://127.0.0.1:3010;
|
||||
proxy_set_header Host $http_host;
|
||||
proxy_set_header X-real-ip $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Upgrade $http_upgrade;
|
||||
proxy_set_header Connection $http_connection;
|
||||
proxy_set_header Accept-Encoding gzip;
|
||||
}
|
||||
```
|
||||
|
||||
You can also configure the proxy for other services in project, as an example.
|
||||
|
||||
```nginx
|
||||
location /api/logout {
|
||||
add_header 'Access-Control-Allow-Headers' 'x-api-nonce,x-api-ts,x-api-ver,x-api-source';
|
||||
proxy_pass http://authelia-svc;
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-real-ip $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
|
||||
add_header X-Frame-Options SAMEORIGIN;
|
||||
}
|
||||
```
|
||||
The configuration is exactly the same as when running in Olares, and no further modifications are required.
|
||||
|
||||
- Reload Nginx after modification.
|
||||
|
||||
```shell
|
||||
nginx -s reload
|
||||
```
|
||||
|
||||
- If you want to keep the `default.conf` of `nginx`, you can save it in either `/root/.config` or the code repository. Then, each time you restart the pod, go to VS Code Terminal and create a new soft link.
|
||||
|
||||
```shell
|
||||
cd /etc/nginx/conf.d
|
||||
rm default.conf
|
||||
ln -s /root/.config/default.conf
|
||||
|
||||
nginx -s reload
|
||||
```
|
||||
:::details Example of a complete `nginx.conf` file (Desktop as an example)
|
||||
|
||||
```nginx
|
||||
server {
|
||||
listen 8080 default_server;
|
||||
root /app;
|
||||
|
||||
location / {
|
||||
proxy_pass http://127.0.0.1:9000;
|
||||
proxy_set_header Host $http_host;
|
||||
proxy_set_header X-real-ip $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Upgrade $http_upgrade;
|
||||
proxy_set_header Connection $http_connection;
|
||||
proxy_set_header Accept-Encoding gzip;
|
||||
}
|
||||
|
||||
location /api {
|
||||
proxy_pass http://127.0.0.1:3010;
|
||||
proxy_set_header Host $http_host;
|
||||
proxy_set_header X-real-ip $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Upgrade $http_upgrade;
|
||||
proxy_set_header Connection $http_connection;
|
||||
proxy_set_header Accept-Encoding gzip;
|
||||
}
|
||||
|
||||
location /server {
|
||||
proxy_pass http://127.0.0.1:3010;
|
||||
# rewrite ^/server(.*)$ $1 break;
|
||||
|
||||
# Add original-request-related headers
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-real-ip $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
|
||||
}
|
||||
|
||||
location /notification {
|
||||
proxy_pass http://127.0.0.1:3010;
|
||||
# rewrite ^/server(.*)$ $1 break;
|
||||
|
||||
# Add original-request-related headers
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-real-ip $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
|
||||
}
|
||||
|
||||
location /video {
|
||||
proxy_pass http://127.0.0.1:3010;
|
||||
# rewrite ^/server(.*)$ $1 break;
|
||||
|
||||
# Add original-request-related headers
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-real-ip $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
|
||||
}
|
||||
|
||||
location /api/logout {
|
||||
add_header 'Access-Control-Allow-Headers' 'x-api-nonce,x-api-ts,x-api-ver,x-api-source';
|
||||
proxy_pass http://authelia-svc;
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-real-ip $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
|
||||
add_header X-Frame-Options SAMEORIGIN;
|
||||
}
|
||||
|
||||
location /api/device {
|
||||
add_header Access-Control-Allow-Headers "access-control-allow-headers,access-control-allow-methods,access-control-allow-origin,content-type,x-auth,x-unauth-error,x-authorization";
|
||||
add_header Access-Control-Allow-Methods "PUT, GET, DELETE, POST, OPTIONS";
|
||||
add_header Access-Control-Allow-Origin $http_origin;
|
||||
add_header Access-Control-Allow-Credentials true;
|
||||
|
||||
proxy_pass http://settings-service;
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-real-ip $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
|
||||
add_header X-Frame-Options SAMEORIGIN;
|
||||
}
|
||||
|
||||
location /api/refresh {
|
||||
add_header Access-Control-Allow-Headers "access-control-allow-headers,access-control-allow-methods,access-control-allow-origin,content-type,x-auth,x-unauth-error,x-authorization";
|
||||
add_header Access-Control-Allow-Methods "PUT, GET, DELETE, POST, OPTIONS";
|
||||
add_header Access-Control-Allow-Origin $http_origin;
|
||||
add_header Access-Control-Allow-Credentials true;
|
||||
|
||||
proxy_pass http://authelia-backend-svc:9091;
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-real-ip $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
|
||||
add_header X-Frame-Options SAMEORIGIN;
|
||||
}
|
||||
|
||||
location /proxy/3000/ {
|
||||
proxy_pass http://127.0.0.1:3000;
|
||||
proxy_set_header Host $http_host;
|
||||
proxy_set_header X-real-ip $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Upgrade $http_upgrade;
|
||||
proxy_set_header Connection $http_connection;
|
||||
proxy_set_header Accept-Encoding gzip;
|
||||
add_header Access-Control-Allow-Headers "Accept, Content-Type, Accept-Encoding";
|
||||
add_header Access-Control-Allow-Methods "GET, OPTIONS";
|
||||
add_header Access-Control-Allow-Origin "*";
|
||||
}
|
||||
}
|
||||
```
|
||||
:::
|
||||
|
||||
After the nginx proxy is activated, you can initiate the front-end and back-end services in the VS Code Terminal.
|
||||
|
||||
::: warning
|
||||
The service cannot be started on ports 80, 8080, and 3000.
|
||||
:::
|
||||
|
||||
## Preview
|
||||
|
||||
After install the application, you can preview it by clicking on the app icon on the Olares.
|
||||
|
||||

|
||||
100
docs/developer/contribute/system-app/olares-manifest.md
Normal file
100
docs/developer/contribute/system-app/olares-manifest.md
Normal file
@@ -0,0 +1,100 @@
|
||||
# OlaresManifest.yaml
|
||||
|
||||
## Permission
|
||||
|
||||
If you need to access the interface of `provider`, you can add following content in the `permissions` section of the `OlaresManifest.yaml` file.
|
||||
```Yaml
|
||||
permission:
|
||||
sysData:
|
||||
- dataType: app
|
||||
group: service.bfl
|
||||
version: v1
|
||||
ops:
|
||||
- InstallDevApp
|
||||
```
|
||||
|
||||
## Reference variable in env
|
||||
|
||||
You can reference the variable in the `env` section of the `deployment.yaml` file.
|
||||
|
||||
```Yaml
|
||||
env:
|
||||
- name: OS_APP_KEY
|
||||
value: {{ .Values.os.appKey }} # Please note, you need to replace it with .Values.os.desktop.appKey when submit to the install wizard.
|
||||
- name: OS_APP_SECRET
|
||||
value: {{ .Values.os.appSecret }} # Please note, you need to replace it with .Values.os.desktop.appSecret when submit to the install wizard.
|
||||
- name: OS_SYSTEM_SERVER
|
||||
value: system-server.user-system-{{ .Values.bfl.username }}
|
||||
```
|
||||
|
||||
---
|
||||
:::details Example of a complete `OlaresManifest.yaml` file
|
||||
```Yaml
|
||||
olaresManifest.version: 1
|
||||
olaresManifest.type: app
|
||||
metadata:
|
||||
name: desktop
|
||||
icon: https://file.bttcdn.com/appstore/default/defaulticon.webp
|
||||
description: app desktop
|
||||
appid: desktop
|
||||
title: desktop
|
||||
version: 0.0.2
|
||||
categories:
|
||||
- dev
|
||||
entrances:
|
||||
- name: desktop-frontend-dev
|
||||
host: desktop-svc-dev
|
||||
port: 80
|
||||
icon: https://file.bttcdn.com/appstore/default/defaulticon.webp
|
||||
title: Desktop-dev
|
||||
authLevel: private
|
||||
openMethod: default
|
||||
spec:
|
||||
versionName: 0.0.1
|
||||
requiredMemory: 2Gi
|
||||
requiredDisk: 50Mi
|
||||
supportArch:
|
||||
- amd64
|
||||
requiredCpu: 50m
|
||||
limitedMemory: 3Gi
|
||||
limitedCpu: 1000m
|
||||
permission:
|
||||
appData: true
|
||||
appCache: true
|
||||
userData: []
|
||||
sysData:
|
||||
- group: service.bfl
|
||||
dataType: app
|
||||
version: v1
|
||||
ops:
|
||||
- UserApps
|
||||
- group: service.appstore
|
||||
dataType: app
|
||||
version: v1
|
||||
ops:
|
||||
- UninstallDevApp
|
||||
- group: service.bfl
|
||||
dataType: datastore
|
||||
version: v1
|
||||
ops:
|
||||
- GetKey
|
||||
- GetKeyPrefix
|
||||
- SetKey
|
||||
- DeleteKey
|
||||
- group: service.files
|
||||
dataType: files
|
||||
version: v1
|
||||
ops:
|
||||
- Query
|
||||
options:
|
||||
resetCookie:
|
||||
enabled: false
|
||||
dependencies:
|
||||
- name: olares
|
||||
version: '>=0.1.0'
|
||||
type: system
|
||||
appScope:
|
||||
clusterScoped: false
|
||||
appRef: []
|
||||
```
|
||||
:::
|
||||
127
docs/developer/contribute/system-app/other.md
Normal file
127
docs/developer/contribute/system-app/other.md
Normal file
@@ -0,0 +1,127 @@
|
||||
# Other
|
||||
|
||||
## Change Provider Registry
|
||||
|
||||
If you need to connect the `provider` of the original system application to your development environment, you can manually change the address of the `ProviderRegistry`. In the **'CRDs'** page of the control hub, locate `sys.bytetrade.io` and then find the `ProviderRegistry`.
|
||||
|
||||

|
||||
|
||||
In the list, navigate to the app you wish to replace (in this case, **desktop-notification**). Click on the **'...'** button on the right and select **'Edit YAML'**. Modify the `endpoint` in the **YAML** file and direct it towards the service address of your **developing app**. Click **'OK'** to save and apply the changes.
|
||||
|
||||

|
||||
|
||||
|
||||
## Vite configuration
|
||||
|
||||
If your frontend project uses **Vite**, you need to add an **HMR** configuration. In development mode, **Vite** initiates a **WebSocket** to receive code reload notifications from the server. The default **WebSocket** port matches the server's startup port. However, if the development app uses an **Nginx proxy** it will operate on the default port 443. Therefore, some modifications are required.
|
||||
|
||||
If you are using **Quasar** + **Vite**, add the following in the `quasar.config.js`:
|
||||
|
||||
```js
|
||||
extendViteConf(viteConf) {
|
||||
viteConf.server.hmr = {clientPort: 443};
|
||||
},
|
||||
```
|
||||
If it is a standalone **Vite** project, modify `vite.config.js` as:
|
||||
```js
|
||||
export default defineConfig({
|
||||
server: {
|
||||
hmr: {
|
||||
clientPort: 443,
|
||||
},
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
## Use System Database
|
||||
|
||||
You can add **system databases** by adding `MiddlewareRequest` in the `deployment.yaml`.
|
||||
Using the **Postgres** in Dify as an example:
|
||||
```Yaml
|
||||
apiVersion: apr.bytetrade.io/v1alpha1
|
||||
kind: MiddlewareRequest
|
||||
metadata:
|
||||
name: dify-pg
|
||||
namespace: os-system
|
||||
spec:
|
||||
app: dify
|
||||
appNamespace: os-system
|
||||
middleware: postgres
|
||||
postgreSQL:
|
||||
user: dify_os_system
|
||||
password:
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
key: pg_password
|
||||
name: dify-secrets
|
||||
databases:
|
||||
- name: dify
|
||||
```
|
||||
|
||||
You need to set a `secret` of password for adding a `MiddlewareRequest`,
|
||||
|
||||
```Yaml
|
||||
apiVersion: v1
|
||||
kind: Secret
|
||||
metadata:
|
||||
name: dify-secrets
|
||||
namespace: {{ .Release.Namespace }}
|
||||
type: Opaque
|
||||
data:
|
||||
pg_password: {{ $pg_password }} # Password can be randomly generated, then Base64 encoded
|
||||
```
|
||||
|
||||
Configure the following in the pod where you want to use the database.
|
||||
|
||||
```Yaml
|
||||
env:
|
||||
- name: DB_USERNAME
|
||||
value: dify_user_space_{{ .Values.bfl.name }} # Please note, you need to add a namespace suffix when use the username configured in the MiddlewareRequest above. For username in Postgres, you also need to replace - with _
|
||||
- name: DB_PASSWORD
|
||||
value: {{ $pg_password | b64dec }} # The decoded password configured above
|
||||
- name: DB_HOST
|
||||
value: citus-master-svc.user-system-{{ .Values.bfl.username }} # HOST address,
|
||||
# For Redis: redis-cluster-proxy.user-system-{{ .Values.bfl.username }}
|
||||
# For Mongo: mongo-cluster-mongos.user-system-{{ .Values.bfl.username }}
|
||||
- name: DB_PORT
|
||||
value: '5432'
|
||||
# For Redis: 6379
|
||||
# For Mongo: 27017
|
||||
- name: DB_DATABASE
|
||||
value: os_system_dify # Please note, you need to add a namespace suffix when use the database name configured in the MiddlewareRequest above. For username in Postgres, you also need to replace - with _
|
||||
```
|
||||
|
||||
You can also concatenate the `dsn` link:
|
||||
|
||||
```Yaml
|
||||
postgres://dify_{{ .Values.bfl.username }}:{{ $pg_password_data }}@citus-master-svc.user-system-{{ .Values.bfl.username }}/user_space_{{ .Values.bfl.username }}_dify?sslmode=disable
|
||||
|
||||
mongodb://dify-{{ .Values.bfl.username }}:{{ $mongo_password_data }}@mongo-cluster-mongos.user-system-{{ .Values.bfl.username }}:27017/{{ .Release.Namespace }}_dify
|
||||
|
||||
redis://:{{ $redis_password | b64dec }}@redis-cluster-proxy.user-system-{{ .Values.bfl.username }}:6379/0 # Please note, Since the system uses Redis Cluster, the database name must set to '0'.
|
||||
```
|
||||
|
||||
To register a provider, you need to add a `ProviderRegistry` in the `deployment.yaml` file.
|
||||
|
||||
```Yaml
|
||||
apiVersion: sys.bytetrade.io/v1alpha1
|
||||
kind: ProviderRegistry
|
||||
metadata:
|
||||
name: desktop-provider-dev # The name cannot be duplicated with the existing one.
|
||||
namespace: user-system-{{ .Values.bfl.username }}
|
||||
spec:
|
||||
|
||||
dataType: config-dev # The dataTypes cannot be duplicated with an existing one. If you want to replace an existing dataType, you need to delete it first.
|
||||
deployment: desktop-dev
|
||||
description: Set Desktop Config
|
||||
endpoint: desktop-svc-dev.{{ .Release.Namespace }} # The address of the provider, pointing to your developing app
|
||||
group: service.desktop
|
||||
kind: provider
|
||||
namespace: {{ .Release.Namespace }}
|
||||
opApis:
|
||||
- name: Update
|
||||
uri: /server/updateDesktopConfig
|
||||
version: v1
|
||||
status:
|
||||
state: active
|
||||
```
|
||||
19
docs/developer/contribute/system-app/overview.md
Normal file
19
docs/developer/contribute/system-app/overview.md
Normal file
@@ -0,0 +1,19 @@
|
||||
|
||||
# Develop System Application for Olares
|
||||
|
||||
::: tip Prerequisites Knowledge
|
||||
- Debugging third-party applications with **DevBox**
|
||||
- Developing applications with **DevBox**
|
||||
- Understanding the architecture and mechanisms of **Olares**
|
||||
:::
|
||||
|
||||
After a year and a half of work, the Olares team now uses **DevBox** for developing system applications.
|
||||
|
||||
We will show you how to debug issues in the frontend code of **Desktop** using **DevBox**.
|
||||
1. Create an application in DevBox
|
||||
2. Configure [deployment.yaml](./deployment)
|
||||
3. Configure [OlaresManifest.yaml](./olares-manifest)
|
||||
4. Install the application
|
||||
5. Configure [nginx.conf](./install)
|
||||
|
||||
There are also some [other](./other) aspects to consider in development.
|
||||
80
docs/developer/develop/advanced/account.md
Normal file
80
docs/developer/develop/advanced/account.md
Normal file
@@ -0,0 +1,80 @@
|
||||
# Account
|
||||
|
||||
If an app in Olares wants to use the system user as the app's user, it can obtain the user information by defining a `SysEventRegistry` in application chart to receive system user event callbacks.
|
||||
|
||||
- Define `user create` callback
|
||||
|
||||
```yaml
|
||||
apiVersion: apr.bytetrade.io/v1alpha1
|
||||
kind: SysEventRegistry
|
||||
metadata:
|
||||
name: user-create-cb
|
||||
namespace: "{{ .Release.Namespace }}"
|
||||
spec:
|
||||
type: subscriber
|
||||
event: user.create
|
||||
callback: http://app-svc.{{ .Release.Namespace }}:8080/callback/create
|
||||
```
|
||||
Response data
|
||||
```http
|
||||
POST /callback/create HTTP/1.1
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"name": "user1",
|
||||
"role": "workspace-manager",
|
||||
"email": "user1@xxx.com"
|
||||
}
|
||||
```
|
||||
|
||||
- Define `user delete` callback
|
||||
|
||||
```yaml
|
||||
apiVersion: apr.bytetrade.io/v1alpha1
|
||||
kind: SysEventRegistry
|
||||
metadata:
|
||||
name: user-delete-cb
|
||||
namespace: "{{ .Release.Namespace }}"
|
||||
spec:
|
||||
type: subscriber
|
||||
event: user.delete
|
||||
callback: http://app-svc.{{ .Release.Namespace }}:8080/callback/delete
|
||||
```
|
||||
Response data
|
||||
```http
|
||||
POST /callback/delete HTTP/1.1
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"name": "user1",
|
||||
"email": "user1@xxx.com"
|
||||
}
|
||||
```
|
||||
|
||||
- Define `user active` callback
|
||||
|
||||
```yaml
|
||||
apiVersion: apr.bytetrade.io/v1alpha1
|
||||
kind: SysEventRegistry
|
||||
metadata:
|
||||
name: user-active-cb
|
||||
namespace: "{{ .Release.Namespace }}"
|
||||
spec:
|
||||
type: subscriber
|
||||
event: user.active
|
||||
callback: http://app-svc.{{ .Release.Namespace }}:8080/callback/activate
|
||||
```
|
||||
Response data
|
||||
```http
|
||||
POST /callback/activate HTTP/1.1
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"name": "user1",
|
||||
"email": "user1@xxx.com"
|
||||
}
|
||||
```
|
||||
|
||||
:::tip
|
||||
To receive system callback notifications, the app must define a service and register it. For instance, the `app-svc` mentioned above.
|
||||
:::
|
||||
547
docs/developer/develop/advanced/ai.md
Normal file
547
docs/developer/develop/advanced/ai.md
Normal file
@@ -0,0 +1,547 @@
|
||||
---
|
||||
outline: [2, 3]
|
||||
---
|
||||
|
||||
# AI
|
||||
|
||||
## API Prefix
|
||||
|
||||
`agent.{username}.olares.com/api/controllers/console/api`
|
||||
|
||||
## Basic Application Management API
|
||||
### Get App List
|
||||
- **Request**
|
||||
- **URL**: `/apps`
|
||||
- **Method**: `GET`
|
||||
- **URL Parameters**: `/apps?page=1&limit=30&name=Ashia`
|
||||
:::tip
|
||||
Most of the APIs listed in this document require the `app_id`, which can be obtained from the response of this API.
|
||||
:::
|
||||
|
||||
### Create App
|
||||
- **Request**
|
||||
- **URL**: `/apps`
|
||||
- **Method**: `POST`
|
||||
- **Body Example**:
|
||||
```json
|
||||
{
|
||||
"name": "TEST",
|
||||
"icon": "🤖",
|
||||
"icon_background": "#FFEAD5",
|
||||
"mode": "agent-chat",
|
||||
"description": "JUST A TEST"
|
||||
}
|
||||
```
|
||||
|
||||
### Get App Details
|
||||
- **Request**
|
||||
- **URL**: `/apps/{uuid:app_id}`
|
||||
- **Method**: `GET`
|
||||
- **Body Example**: `null`
|
||||
|
||||
### Delete App
|
||||
- **Request**
|
||||
- **URL**: `/apps/{uuid:app_id}`
|
||||
- **Method**: `DELETE`
|
||||
- **Body Example**: `null`
|
||||
|
||||
### Copy App
|
||||
- **Request**
|
||||
- **URL**: `/apps/{uuid:app_id}/copy`
|
||||
- **Method**: `POST`
|
||||
- **Body Example**:
|
||||
```json
|
||||
{
|
||||
"name": "Ashia-2",
|
||||
"icon": "🤖",
|
||||
"icon_background": "#FFEAD5",
|
||||
"mode": "agent-chat"
|
||||
}
|
||||
```
|
||||
|
||||
### Rename App
|
||||
- **Request**
|
||||
- **URL**: `/apps/{uuid:app_id}/name`
|
||||
- **Method**: `POST`
|
||||
- **Body Example**:
|
||||
```json
|
||||
{
|
||||
"name": "Ashia—34"
|
||||
}
|
||||
```
|
||||
|
||||
### Change App Icon
|
||||
- **Request**
|
||||
- **URL**: `/apps/{uuid:app_id}/icon`
|
||||
- **Method**: `POST`
|
||||
- **Body Example**:
|
||||
```json
|
||||
{
|
||||
"icon": "heavy_check_mark"
|
||||
}
|
||||
```
|
||||
|
||||
### App Web Access Control
|
||||
> Whether the app can be accessed from the site.
|
||||
- **Request**
|
||||
- **URL**: `/apps/{uuid:app_id}/site-enable`
|
||||
- **Method**: `POST`
|
||||
- **Body Example**:
|
||||
```json
|
||||
{
|
||||
"enable_site": true
|
||||
}
|
||||
```
|
||||
|
||||
### App API Access Control
|
||||
> Whether the app can be accessed via API.
|
||||
- **Request**
|
||||
- **URL**: `/apps/{uuid:app_id}/api-enable`
|
||||
- **Method**: `POST`
|
||||
- **Body Example**:
|
||||
```json
|
||||
{
|
||||
"enable_api": true
|
||||
}
|
||||
```
|
||||
|
||||
## Application Function API
|
||||
### Text Generation
|
||||
> Execution interface for text generation APP
|
||||
- **Request**
|
||||
- **URL**: `/apps/{uuid:app_id}/completion-messages`
|
||||
- **Method**: `POST`
|
||||
- **Body Example**:
|
||||
:::details
|
||||
```json
|
||||
{
|
||||
"inputs": {
|
||||
"query": "Hello~"
|
||||
},
|
||||
"model_config": {
|
||||
"pre_prompt": "{{query}}",
|
||||
"prompt_type": "simple",
|
||||
"chat_prompt_config": {},
|
||||
"completion_prompt_config": {},
|
||||
"user_input_form": [
|
||||
{
|
||||
"paragraph": {
|
||||
"label": "Query",
|
||||
"variable": "query",
|
||||
"required": true,
|
||||
"default": ""
|
||||
}
|
||||
}
|
||||
],
|
||||
"dataset_query_variable": "",
|
||||
"opening_statement": null,
|
||||
"suggested_questions_after_answer": {
|
||||
"enabled": false
|
||||
},
|
||||
"speech_to_text": {
|
||||
"enabled": false
|
||||
},
|
||||
"retriever_resource": {
|
||||
"enabled": false
|
||||
},
|
||||
"sensitive_word_avoidance": {
|
||||
"enabled": false,
|
||||
"type": "",
|
||||
"configs": []
|
||||
},
|
||||
"more_like_this": {
|
||||
"enabled": false
|
||||
},
|
||||
"model": {
|
||||
"provider": "openai_api_compatible",
|
||||
"name": "nitro",
|
||||
"mode": "chat",
|
||||
"completion_params": {
|
||||
"temperature": 0.7,
|
||||
"top_p": 1,
|
||||
"frequency_penalty": 0,
|
||||
"presence_penalty": 0,
|
||||
"max_tokens": 512
|
||||
}
|
||||
},
|
||||
"text_to_speech": {
|
||||
"enabled": false,
|
||||
"voice": "",
|
||||
"language": ""
|
||||
},
|
||||
"agent_mode": {
|
||||
"enabled": false,
|
||||
"tools": []
|
||||
},
|
||||
"dataset_configs": {
|
||||
"retrieval_model": "single",
|
||||
"datasets": {
|
||||
"datasets": []
|
||||
}
|
||||
},
|
||||
"file_upload": {
|
||||
"image": {
|
||||
"enabled": false,
|
||||
"number_limits": 3,
|
||||
"detail": "high",
|
||||
"transfer_methods": [
|
||||
"remote_url",
|
||||
"local_file"
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"response_mode": "streaming"
|
||||
}
|
||||
```
|
||||
:::
|
||||
|
||||
### Stop Text Generation
|
||||
> Interruption interface for text generation APP
|
||||
- **Request**
|
||||
- **URL**: `/apps/{uuid:app_id}/completion-messages/{string:task_id}/stop`
|
||||
- **Method**: `POST`
|
||||
- **Body Example**: `null`
|
||||
:::tip
|
||||
The `task_id` required in this API can be obtained from the response (streaming) of the [Text Generation](#text-generation) API.
|
||||
:::
|
||||
|
||||
### Chat
|
||||
> Execution interface for chat APP
|
||||
- **Request**
|
||||
- **URL**: `/apps/{uuid:app_id}/chat-messages`
|
||||
- **Method**: `POST`
|
||||
- **Body Example**:
|
||||
:::details
|
||||
```json
|
||||
{
|
||||
"response_mode": "streaming",
|
||||
"conversation_id": "",
|
||||
"query": "Hello~",
|
||||
"inputs": {},
|
||||
"model_config": {
|
||||
"pre_prompt": "",
|
||||
"prompt_type": "simple",
|
||||
"chat_prompt_config": {},
|
||||
"completion_prompt_config": {},
|
||||
"user_input_form": [],
|
||||
"dataset_query_variable": "",
|
||||
"opening_statement": "",
|
||||
"more_like_this": {
|
||||
"enabled": false
|
||||
},
|
||||
"suggested_questions": [],
|
||||
"suggested_questions_after_answer": {
|
||||
"enabled": false
|
||||
},
|
||||
"text_to_speech": {
|
||||
"enabled": false,
|
||||
"voice": "",
|
||||
"language": ""
|
||||
},
|
||||
"speech_to_text": {
|
||||
"enabled": false
|
||||
},
|
||||
"retriever_resource": {
|
||||
"enabled": false
|
||||
},
|
||||
"sensitive_word_avoidance": {
|
||||
"enabled": false
|
||||
},
|
||||
"agent_mode": {
|
||||
"max_iteration": 5,
|
||||
"enabled": true,
|
||||
"tools": [],
|
||||
"strategy": "react"
|
||||
},
|
||||
"dataset_configs": {
|
||||
"retrieval_model": "single",
|
||||
"datasets": {
|
||||
"datasets": []
|
||||
}
|
||||
},
|
||||
"file_upload": {
|
||||
"image": {
|
||||
"enabled": false,
|
||||
"number_limits": 2,
|
||||
"detail": "low",
|
||||
"transfer_methods": [
|
||||
"local_file"
|
||||
]
|
||||
}
|
||||
},
|
||||
"annotation_reply": {
|
||||
"enabled": false
|
||||
},
|
||||
"supportAnnotation": true,
|
||||
"appId": "2c937aae-f4f2-4cf9-b6e2-f2f2756858c0",
|
||||
"supportCitationHitInfo": true,
|
||||
"model": {
|
||||
"provider": "openai_api_compatible",
|
||||
"name": "nitro",
|
||||
"mode": "chat",
|
||||
"completion_params": {
|
||||
"temperature": 2,
|
||||
"top_p": 1,
|
||||
"frequency_penalty": 0,
|
||||
"presence_penalty": 0,
|
||||
"max_tokens": 512,
|
||||
"stop": []
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
:::
|
||||
|
||||
|
||||
### Stop Chat
|
||||
> Interruption interface for chat APP
|
||||
- **Request**
|
||||
- **URL**: `/apps/{uuid:app_id}/chat-messages/{string:task_id}/stop`
|
||||
- **Method**: `POST`
|
||||
- **Body Example**: `null`
|
||||
:::tip
|
||||
The `task_id` required in this API can be obtained from the response (streaming) of the [Chat](#chat) API.
|
||||
:::
|
||||
|
||||
### Get Conversations List (Text Generation)
|
||||
- **Request**
|
||||
- **URL**: `/apps/{uuid:app_id}/completion-conversations`
|
||||
- **Method**: `GET`
|
||||
- **URL Parameters**: `/apps/{uuid:app_id}/completion-conversations?page=1&limit=30`
|
||||
:::tip
|
||||
the Conversations (Text Generation) APIs listed below require the `conversation_id`, which can be obtained from the response of this API.
|
||||
:::
|
||||
|
||||
### Get Conversations Details (Text Generation)
|
||||
- **Request**
|
||||
- **URL**: `/apps/{uuid:app_id}/completion-conversations/{uuid:conversation_id}`
|
||||
- **Method**: `GET`
|
||||
- **Body Example**: `null`
|
||||
:::tip
|
||||
The Conversations (Text Generation) APIs listed below require the `message_id`, which can be obtained from the response of this API.
|
||||
:::
|
||||
|
||||
### Delete Conversations Details (Text Generation)
|
||||
- **Request**
|
||||
- **URL**: `/apps/{uuid:app_id}/completion-conversations/{uuid:conversation_id}`
|
||||
- **Method**: `DELETE`
|
||||
- **Body Example**: `null`
|
||||
|
||||
### Get Conversations List (Chat)
|
||||
- **Request**
|
||||
- **URL**: `/apps/{uuid:app_id}/chat-conversations`
|
||||
- **Method**: `GET`
|
||||
- **URL Parameters**: `/apps/{uuid:app_id}/chat-conversations?page=1&limit=30`
|
||||
:::tip
|
||||
the Conversations (Chat) APIs listed below require the `conversation_id`, which can be obtained from the response of this API.
|
||||
:::
|
||||
|
||||
### Get Conversations Details (Chat)
|
||||
- **Request**
|
||||
- **URL**: `/apps/{uuid:app_id}/chat-conversations/{uuid:conversation_id}`
|
||||
- **Method**: `GET`
|
||||
- **Body Example**: `null`
|
||||
:::tip
|
||||
The Conversations (Chat) APIs listed below require the `message_id`, which can be obtained from the response of this API.
|
||||
:::
|
||||
|
||||
### Delete Conversations Details (Chat)
|
||||
- **Request**
|
||||
- **URL**: `/apps/{uuid:app_id}/chat-conversations/{uuid:conversation_id}`
|
||||
- **Method**: `DELETE`
|
||||
- **Body Example**: `null`
|
||||
|
||||
### Get Suggested Questions (Chat)
|
||||
> In a chat APP, get the suggested questions that can be asked after the AI gives a response
|
||||
- **Request**
|
||||
- **URL**: `/apps/{uuid:app_id}/chat-messages/{uuid:message_id}/suggested-questions`
|
||||
- **Method**: `GET`
|
||||
- **Body Example**: `null`
|
||||
|
||||
### Get Message List (Chat)
|
||||
- **Request**
|
||||
- **URL**: `/apps/{uuid:app_id}/chat-messages`
|
||||
- **Method**: `GET`
|
||||
- **URL Parameters**: `/apps/{uuid:app_id}/chat-messages?conversation_id={conversation_id}`
|
||||
|
||||
### Message Feedback
|
||||
> Give like or dislike feedback to the message from the APP
|
||||
- **Request**
|
||||
- **URL**: `/apps/{uuid:app_id}/feedbacks`
|
||||
- **Method**: `POST`
|
||||
- **Body Example**:
|
||||
```json
|
||||
{
|
||||
"rating": "like" // "like" | "dislike" | null
|
||||
}
|
||||
```
|
||||
|
||||
### Message Annotation
|
||||
> Give annotation to the message from the APP (Text Generation)
|
||||
- **Request**
|
||||
- **URL**: `/apps/{uuid:app_id}/annotations`
|
||||
- **Method**: `POST`
|
||||
- **Body Example**:
|
||||
```json
|
||||
{
|
||||
"message_id": "2b79fdad-e513-45ef-9532-8de5086cb81c",
|
||||
"question": "query:How are you?",
|
||||
"answer": "some answer messages"
|
||||
}
|
||||
```
|
||||
|
||||
### Count Annotation
|
||||
> Get the current number of annotations of the APP's message
|
||||
- **Request**
|
||||
- **URL**: `/apps/{uuid:app_id}/annotations/count`
|
||||
- **Method**: `GET`
|
||||
- **Body Example**: `null`
|
||||
|
||||
|
||||
### Get Message Details (Chat)
|
||||
- **Request**
|
||||
- **URL**: `/apps/{uuid:app_id}/messages/{uuid:message_id}`
|
||||
- **Method**: `GET`
|
||||
- **Body Example**: `null`
|
||||
|
||||
## Advanced Application Management API
|
||||
|
||||
### Model Config
|
||||
- **Request**
|
||||
- **URL**: `/apps/{uuid:app_id}/model-config`
|
||||
- **Method**: `POST`
|
||||
- **Body Example**:
|
||||
:::details
|
||||
```json
|
||||
{
|
||||
"pre_prompt": "",
|
||||
"prompt_type": "simple",
|
||||
"chat_prompt_config": {},
|
||||
"completion_prompt_config": {},
|
||||
"user_input_form": [],
|
||||
"dataset_query_variable": "",
|
||||
"opening_statement": "",
|
||||
"suggested_questions": [],
|
||||
"more_like_this": {
|
||||
"enabled": false
|
||||
},
|
||||
"suggested_questions_after_answer": {
|
||||
"enabled": false
|
||||
},
|
||||
"speech_to_text": {
|
||||
"enabled": false
|
||||
},
|
||||
"text_to_speech": {
|
||||
"enabled": false,
|
||||
"language": "",
|
||||
"voice": ""
|
||||
},
|
||||
"retriever_resource": {
|
||||
"enabled": false
|
||||
},
|
||||
"sensitive_word_avoidance": {
|
||||
"enabled": false
|
||||
},
|
||||
"agent_mode": {
|
||||
"max_iteration": 5,
|
||||
"enabled": true,
|
||||
"strategy": "react",
|
||||
"tools": []
|
||||
},
|
||||
"model": {
|
||||
"provider": "openai_api_compatible",
|
||||
"name": "nitro",
|
||||
"mode": "chat",
|
||||
"completion_params": {
|
||||
"frequency_penalty": 0,
|
||||
"max_tokens": 512,
|
||||
"presence_penalty": 0,
|
||||
"stop": [],
|
||||
"temperature": 2,
|
||||
"top_p": 1
|
||||
}
|
||||
},
|
||||
"dataset_configs": {
|
||||
"retrieval_model": "single",
|
||||
"datasets": {
|
||||
"datasets": []
|
||||
}
|
||||
},
|
||||
"file_upload": {
|
||||
"image": {
|
||||
"enabled": false,
|
||||
"number_limits": 2,
|
||||
"detail": "low",
|
||||
"transfer_methods": [
|
||||
"local_file"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
:::
|
||||
|
||||
### Change APP Basic Info
|
||||
- **Request**
|
||||
- **URL**: `/apps/{uuid:app_id}/site`
|
||||
- **Method**: `POST`
|
||||
- **Body Example**:
|
||||
```json
|
||||
{
|
||||
"title": "Ashias-23",
|
||||
"icon": "grin",
|
||||
"icon_background": "#000000",
|
||||
"description": "How do you do~"
|
||||
}
|
||||
```
|
||||
### Access Token Reset
|
||||
> Regenerate the public access URL for the APP
|
||||
- **Request**
|
||||
- **URL**: `/apps/{uuid:app_id}/site/access-token-reset`
|
||||
- **Method**: `POST`
|
||||
- **Body Example**: `null`
|
||||
|
||||
## Application Statistics API
|
||||
### All Conversations
|
||||
- **Request**
|
||||
- **URL**: `/apps/{uuid:app_id}/statistics/daily-conversations`
|
||||
- **Method**: `GET`
|
||||
- **URL Parameters**: `/apps/{uuid:app_id}/statistics/daily-conversations?start=2024-04-19%2016%3A28&end=2024-04-26%2016%3A28`
|
||||
|
||||
### Active Users
|
||||
- **Request**
|
||||
- **URL**: `/apps/{uuid:app_id}/statistics/daily-end-users`
|
||||
- **Method**: `GET`
|
||||
- **URL Parameters**: `/apps/{uuid:app_id}/statistics/daily-end-users?start=2024-04-19%2016%3A28&end=2024-04-26%2016%3A28`
|
||||
|
||||
### Token Costs
|
||||
- **Request**
|
||||
- **URL**: `/apps/{uuid:app_id}/statistics/token-costs`
|
||||
- **Method**: `GET`
|
||||
- **URL Parameters**: `/apps/{uuid:app_id}/statistics/token-costs?start=2024-04-19%2016%3A28&end=2024-04-26%2016%3A28`
|
||||
|
||||
### Average Session Interactions
|
||||
- **Request**
|
||||
- **URL**: `/apps/{uuid:app_id}/statistics/average-session-interactions`
|
||||
- **Method**: `GET`
|
||||
- **URL Parameters**: `/apps/{uuid:app_id}/statistics/average-session-interactions?start=2024-04-19%2016%3A28&end=2024-04-26%2016%3A28`
|
||||
|
||||
### User Satisfaction
|
||||
- **Request**
|
||||
- **URL**: `/apps/{uuid:app_id}/statistics/user-satisfaction-rate`
|
||||
- **Method**: `GET`
|
||||
- **URL Parameters**: `/apps/{uuid:app_id}/statistics/user-satisfaction-rate?start=2024-04-19%2016%3A28&end=2024-04-26%2016%3A28`
|
||||
|
||||
### Average Response Time
|
||||
- **Request**
|
||||
- **URL**: `/apps/{uuid:app_id}/statistics/average-response-time`
|
||||
- **Method**: `GET`
|
||||
- **URL Parameters**: `/apps/{uuid:app_id}/statistics/average-response-time?start=2024-04-19%2016%3A28&end=2024-04-26%2016%3A28`
|
||||
|
||||
### Token Output Speed
|
||||
- **Request**
|
||||
- **URL**: `/apps/{uuid:app_id}/statistics/tokens-per-second`
|
||||
- **Method**: `GET`
|
||||
- **URL Parameters**: `/apps/{uuid:app_id}/statistics/tokens-per-second?start=2024-04-19%2016%3A28&end=2024-04-26%2016%3A28`
|
||||
33
docs/developer/develop/advanced/cli/olares-change-ip.md
Normal file
33
docs/developer/develop/advanced/cli/olares-change-ip.md
Normal file
@@ -0,0 +1,33 @@
|
||||
# `olares change-ip`
|
||||
:::warning When manually updating IP address is required
|
||||
When Olares is deployed _inside_ a virtualized environment, such as macOS (via Minikube) or Windows (via WSL), a change in the host system's IP address (e.g., due to switching Wi-Fi networks) may cause Olares to become inaccessible. This happens because the NAT gateway and DNS configuration no longer match the new IP. In such cases, you need to manually update the IP address to ensure that Olares can route traffic correctly.
|
||||
:::
|
||||
|
||||
## Synopsis
|
||||
Change the local IP address for all Olares components.
|
||||
|
||||
```bash
|
||||
olares-cli olares change-ip [option]
|
||||
```
|
||||
|
||||
## Options
|
||||
|
||||
| Name | Shorthand | Usage |
|
||||
|------------------|-----------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||
| `--base-dir` | `-b` | Sets the base directory for Olares.<br> Defaults to `$HOME/.olares`. |
|
||||
| `--distribution` | `-d` | Sets the WSL distribution name. Only applicable on Windows. <br> Defaults to `Ubuntu`. |
|
||||
| `--help` | `-h` | Displays help information. |
|
||||
| `--profile` | `-p` | Sets the Minikube profile name. Only applicable on macOS. <br> Defaults to `olares-0`. |
|
||||
| `--version` | `-v` | Specifies the Olares version. <br>Version values follow the format `x.y.z` (e.g., `1.10.0`) or include a build date (e.g., `1.10.0-20241109`).<br> Refer to the [GitHub Releases page](https://github.com/beclab/Olares/releases) for available versions. |
|
||||
|
||||
## Examples
|
||||
- For macOS:
|
||||
```bash
|
||||
# Specify the Minikube profile name and change the IP.
|
||||
olares-cli olares change-ip --profile olares-0
|
||||
```
|
||||
- For Windows WSL:
|
||||
```bash
|
||||
# Specify the Linux distribution in WSL and change the IP.
|
||||
olares-cli olares change-ip --distribution Ubuntu
|
||||
```
|
||||
50
docs/developer/develop/advanced/cli/olares-cli.md
Normal file
50
docs/developer/develop/advanced/cli/olares-cli.md
Normal file
@@ -0,0 +1,50 @@
|
||||
---
|
||||
outline: [2, 3]
|
||||
---
|
||||
# Olares CLI
|
||||
|
||||
Olares provides Olares CLI, a command-line tool for developers and system administrators to customize or troubleshoot the Olares installation process.
|
||||
|
||||
The recommended [one-liner installation command](../../../../manual/get-started/install-olares.md) retrieves a shell script from https://olares.sh/ that downloads and installs Olares CLI. Once installed, the CLI orchestrates the remainder of the setup.
|
||||
|
||||
In general, Olares CLI manages installation through three main phases:
|
||||
1. **Download**: Olares CLI fetches the necessary components.
|
||||
2. **Prepare**: Olares CLI prepares the environment for installation.
|
||||
3. **Install**: Olares CLI installs the core services of Olares.
|
||||
|
||||
This page explains the Olares CLI syntax and describes the command operations.
|
||||
|
||||
:::info Root privileges required
|
||||
Most `olares-cli` commands require root privileges. Use the root user or prepend commands with `sudo`.
|
||||
:::
|
||||
|
||||
## Syntax
|
||||
The Olares CLI uses the following syntax:
|
||||
|
||||
> `olares-cli command [subcommand] [option]`
|
||||
|
||||
where
|
||||
- `command`: Specifies the main operation you want to perform. For example, `olares download`.
|
||||
- `subcommand`: Further specifies the task of `command`. For example, `wizard` or `component`.
|
||||
- `option`: Optional arguments that modify the behavior of the `command`. Options include flags and options with arguments.
|
||||
|
||||
Olares CLI allows you to temporarily override certain Olares default settings. Each option applies only to the command in which it is used.
|
||||
|
||||
For example, if you use the `--base-dir` option with `olares-cli olares download wizard`, it will only affect the wizard downloading process and will not change the base directory for other commands, such as during the "install" phase.
|
||||
|
||||
To get detailed help for any command, run `olares-cli help`.
|
||||
|
||||
## Available CLI commands
|
||||
|
||||
| Operation | Syntax | Description |
|
||||
|--------------------|----------------------------------------------------|------------------------------------------------------------------------------------------------------------------------------|
|
||||
| `olares info` | `olares-cli olares info [option]` | Displays general information about the downloaded Olares OS. |
|
||||
| `olares download` | `olares-cli olares download [subcommand] [option]` | Downloads specific resources. |
|
||||
| `olares prepare` | `olares-cli olares prepare [option]` | Prepares the environment for the installation process, including setting up essential services and configurations of Olares. |
|
||||
| `olares install` | `olares-cli olares install [option]` | Deploys system-level and user-level components of Olares. |
|
||||
| `olares change-ip` | `olares-cli olares change-ip [option]` | Changes the IP address of the Olares OS. |
|
||||
| `olares release` | `olares-cli olares release [option]` | Packages Olares installation resources for distribution or deployment. |
|
||||
| `olares uninstall` | `olares-cli olares uninstall [option]` | Uninstalls Olares completely, or roll back the installation to a specific phase. |
|
||||
|
||||
|
||||
|
||||
46
docs/developer/develop/advanced/cli/olares-download.md
Normal file
46
docs/developer/develop/advanced/cli/olares-download.md
Normal file
@@ -0,0 +1,46 @@
|
||||
# `olares download`
|
||||
|
||||
## Synopsis
|
||||
The `olares download` command downloads the necessary packages and components required to install Olares on your local machine. It supports downloading components, checking the status of installation packages, and fetching the manifest file.
|
||||
|
||||
```bash
|
||||
olares-cli olares download [subcommand] [option]
|
||||
```
|
||||
|
||||
## Subcommands
|
||||
|
||||
| Name | Shorthand | Usage | Example |
|
||||
|-------------|-----------|-------------------------------------------------------|----------------------------------------|
|
||||
| `check` | | Checks the status of the Olares installation package. | `olares-cli olares download check` |
|
||||
| `component` | `c` | Downloads Olares components. | `olares-cli olares download component` |
|
||||
| `wizard` | `w` | Downloads the manifest file. | `olares-cli olares download wizard` |
|
||||
|
||||
## Options
|
||||
|
||||
| Name | Shorthand | Usage |
|
||||
|----------------------|-----------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||
| `--base-dir` | `-b` | Sets the base directory for Olares.<br> Defaults to `$HOME/.olares`. |
|
||||
| `--download-cdn-url` | | Sets the CDN accelerated download URL in the format `https://example.cdn.com`. <br>If not provided, the default URL will be used. |
|
||||
| `--help` | `-h` | Displays help information. |
|
||||
| `--kube` | | Specifies the Kubernetes type. <br>Supported types are `k3s` (default) and `k8s`. |
|
||||
| `--version` | `-v` | Specifies the Olares version. <br>Version values follow the format `x.y.z` (e.g., `1.10.0`) or include a build date (e.g., `1.10.0-20241109`).<br> Refer to the [GitHub Releases page](https://github.com/beclab/Olares/releases) for available versions. |
|
||||
|
||||
## Examples
|
||||
```bash
|
||||
# Specifies the base directory where all downloaded components will be stored.
|
||||
olares-cli olares download component -b /custom/path
|
||||
|
||||
# Specifies a CDN-accelerated URL for downloading Olares components.
|
||||
olares-cli olares download component --download-cdn-url https://my.cdn.com
|
||||
|
||||
# Specifies the Kubernetes type for the installation.
|
||||
olares-cli olares download component --kube k8s
|
||||
|
||||
# Sets the path to the package manifest file.
|
||||
olares-cli olares download component --manifest /custom/path/manifest.json
|
||||
|
||||
# Specifies the version of Olares packages and components to download.
|
||||
olares-cli olares download component -v 1.11.0
|
||||
```
|
||||
|
||||
|
||||
14
docs/developer/develop/advanced/cli/olares-info.md
Normal file
14
docs/developer/develop/advanced/cli/olares-info.md
Normal file
@@ -0,0 +1,14 @@
|
||||
# `olares info`
|
||||
|
||||
## Synopsis
|
||||
The `olares info` command displays general information about the installed Olares version.
|
||||
|
||||
```bash
|
||||
olares-cli olares info
|
||||
```
|
||||
|
||||
## Flags
|
||||
|
||||
| Name | Shorthand | Usage |
|
||||
|----------|-----------|---------------------------|
|
||||
| `--help` | `-h` | Display help information. |
|
||||
19
docs/developer/develop/advanced/cli/olares-install.md
Normal file
19
docs/developer/develop/advanced/cli/olares-install.md
Normal file
@@ -0,0 +1,19 @@
|
||||
# `olares install`
|
||||
|
||||
## Synopsis
|
||||
The `olares install` command installs Olares on your system. It supports various options to customize the installation process, such as specifying directories, Kubernetes types, or Minikube profiles.
|
||||
|
||||
```bash
|
||||
olares-cli olares install [option]
|
||||
```
|
||||
|
||||
## Options
|
||||
|
||||
| Name | Shorthand | Usage |
|
||||
|--------------|-----------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||
| `--base-dir` | `-b` | Sets the base directory for Olares.<br> Defaults to `$HOME/.olares`. |
|
||||
| `--help` | `-h` | Displays help information. |
|
||||
| `--kube` | | Specifies the Kubernetes type. <br>Supported types are `k3s` (default) and `k8s`. |
|
||||
| `--profile` | `-p` | Sets the Minikube profile name. Only applicable on macOS. <br> Defaults to `olares-0`. |
|
||||
| `--version` | `-v` | Specifies the Olares version. <br>Version values follow the format `x.y.z` (e.g., `1.10.0`) or include a build date (e.g., `1.10.0-20241109`).<br> Refer to the [GitHub Releases page](https://github.com/beclab/Olares/releases) for available versions. |
|
||||
|
||||
25
docs/developer/develop/advanced/cli/olares-prepare.md
Normal file
25
docs/developer/develop/advanced/cli/olares-prepare.md
Normal file
@@ -0,0 +1,25 @@
|
||||
# `olares prepare`
|
||||
|
||||
## Synopsis
|
||||
The `olares prepare` command sets up the environment required for Olares to function. This includes installing dependencies, importing container images, and starting the Olares daemon (`olaresd`).
|
||||
```bash
|
||||
olares-cli olares prepare [option]
|
||||
```
|
||||
|
||||
## Options
|
||||
|
||||
| Name | Shorthand | Usage |
|
||||
|----------------------|-----------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||
| `--base-dir` | `-b` | Sets the base directory for Olares.<br> Defaults to `$HOME/.olares`. |
|
||||
| `--help` | `-h` | Displays help information. |
|
||||
| `--kube` | | Specifies the Kubernetes type. <br>Supported types are `k3s` (default) and `k8s`. |
|
||||
| `--profile` | `-p` | Sets the Minikube profile name. Only applicable on macOS. <br> Defaults to `olares-0`. |
|
||||
| `--registry-mirrors` | `-r` | Specifies Docker container registry mirrors. <br> Multiple mirrors should be separated by commas. |
|
||||
| `--with-juicefs` | | Configures JuiceFS as the root filesystem (rootfs) for Olares workloads instead of the local disk. |
|
||||
| `--version` | `-v` | Specifies the Olares version. <br>Version values follow the format `x.y.z` (e.g., `1.10.0`) or include a build date (e.g., `1.10.0-20241109`).<br> Refer to the [GitHub Releases page](https://github.com/beclab/Olares/releases) for available versions. |
|
||||
|
||||
## Example
|
||||
```bash
|
||||
# Uses JuiceFS as the root filesystem
|
||||
olares-cli olares prepare --with-juicefs=true
|
||||
```
|
||||
20
docs/developer/develop/advanced/cli/olares-release.md
Normal file
20
docs/developer/develop/advanced/cli/olares-release.md
Normal file
@@ -0,0 +1,20 @@
|
||||
# `olares release`
|
||||
|
||||
## Synopsis
|
||||
Build a release version based on a local Olares repository. This command should be run in the root directory of the Olares repository.
|
||||
|
||||
```bash
|
||||
olares-cli olares release [option]
|
||||
```
|
||||
|
||||
## Options
|
||||
|
||||
| Name | Shorthand | Usage |
|
||||
|----------------------------|-----------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||
| `--base-dir` | `-b` | Sets the base directory for Olares.<br> Defaults to `$HOME/.olares`. |
|
||||
| `--download-cdn-url` | | Sets the CDN URL used for downloading checksums of dependencies and images. <br> Defaults to `https://dc3p1870nn3cj.cloudfront.net`. |
|
||||
| `--extract` | `-e` | Extracts the release to the `--base-dir` after the build. Set to `false` if only the release file itself is needed. <br> Defaults to `true`. |
|
||||
| `--help` | `-h` | Displays help information. |
|
||||
| `---ignore-missing-images` | | Ignores missing images when downloading checksums from the CDN. <br> Disable this only if no new images are added, as the build may fail if the image is not uploaded to the CDN yet. <br> Defaults to `true`. |
|
||||
| `--version` | `-v` | Specifies the Olares version. <br>Version values follow the format `x.y.z` (e.g., `1.10.0`) or include a build date (e.g., `1.10.0-20241109`).<br> Refer to the [GitHub Releases page](https://github.com/beclab/Olares/releases) for available versions. |
|
||||
|
||||
19
docs/developer/develop/advanced/cli/olares-uninstall.md
Normal file
19
docs/developer/develop/advanced/cli/olares-uninstall.md
Normal file
@@ -0,0 +1,19 @@
|
||||
# `olares uninstall`
|
||||
|
||||
## Synopsis
|
||||
Uninstall Olares from your machine.
|
||||
|
||||
```bash
|
||||
olares-cli olares uninstall [option]
|
||||
```
|
||||
|
||||
## Options
|
||||
|
||||
| Name | Shorthand | Usage |
|
||||
|--------------|-----------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||
| `--all` | | Uninstalls Olares completely, including dependencies installed during the "prepare" phase. |
|
||||
| `--base-dir` | `-b` | Sets the base directory for Olares.<br> Defaults to `$HOME/.olares`. |
|
||||
| `--help` | `-h` | Displays help information. |
|
||||
| `--phase` | | Uninstalls Olares from a specific phase and revert to the previous one. <br> For example, `--phase install` removes tasks performed during the "install" phase, reverting the system to the "prepare" stage. <br>Defaults to `install`. |
|
||||
| `--quiet` | | Enables quiet mode (suppress output). <br> Defaults to `false`. |
|
||||
| `--version` | `-v` | Specifies the Olares version to uninstall. <br>Use `olares-cli olares info` to check the downloaded version first. |
|
||||
26
docs/developer/develop/advanced/cookie.md
Normal file
26
docs/developer/develop/advanced/cookie.md
Normal file
@@ -0,0 +1,26 @@
|
||||
# Cookie
|
||||
|
||||
**Single Sign-On (SSO)** mode is utilized for authorization and authentication across the **Olares**, including all installed apps. **SSO** authentication is non-intrusive, using cookies as the authentication credential.
|
||||
|
||||
The system will set two cookies after login
|
||||
|
||||
- **authelia_session**
|
||||
|
||||
The content of the cookie is the session id of SSO. The scope is the user's Olares domain, `<username>.olares.com`
|
||||
|
||||
- **auth_token**
|
||||
|
||||
The user authenticated authorization token. The scope is the user's Olares domain, `<username>.olares.com`
|
||||
|
||||
To prevent cookie conflicts, **no application** (whether it's a built-in system app or a third-party app) can set cookies to the user's domain. Cookies can only be set to the domain of the app.
|
||||
|
||||
Every application in **Olares** operates under two domains: <`app id>.<username>.olares.com` and `<app id>.local.<username>.olares.com`. As a result, Olares incorporates a cookie-setting `rewrite` mechanism within the Olares Application Runtime. This ensures that the application automatically assigns cookies for both domains in the Set-`Cookie` field of the **HTTP response**.
|
||||
|
||||
To use this feature, you just need to define it in the application chart's [OlaresManifest.yaml](../package/manifest.md#resetcookie)
|
||||
|
||||
```yaml
|
||||
options:
|
||||
resetCookie:
|
||||
enabled: true
|
||||
|
||||
```
|
||||
65
docs/developer/develop/advanced/database.md
Normal file
65
docs/developer/develop/advanced/database.md
Normal file
@@ -0,0 +1,65 @@
|
||||
# Database
|
||||
|
||||
The Olares system provides three most popular data storage cluster for all APPs, covering `RDS`, `NoSQL`, and `Cache` data storage use cases.
|
||||
|
||||
## RDS
|
||||
|
||||
The system has deployed **PostgreSQL** and provides two types of databases.
|
||||
|
||||
- **Standalone PostgreSQL**, providing the most commonly used `RDS` database layer functions.
|
||||
- **Distributed PostgreSQL** extension, powered by **Citus**. Provides the ability to horizontally scale the database.
|
||||
|
||||
When setting up a **PostgreSQL** database, you can specify the type of database to be used in [OlaresManifest.yaml](../package/manifest.md#middleware).
|
||||
|
||||
```yaml
|
||||
middleware:
|
||||
postgres:
|
||||
username: postgres
|
||||
databases:
|
||||
- name: db
|
||||
distributed: true # Whether the database is distributed in the cluster.
|
||||
```
|
||||
|
||||
If you use **Citus**, **Olares** will automatically shard the database tables and perform rebalancing during the horizontal scaling of **PostgreSQL** replicas.
|
||||
|
||||
## NoSQL
|
||||
|
||||
The NoSQL cluster is not deployed by default in Olares, but it can be easily installed from the Market. To set up a NoSQL cluster, the administrator needs to install the [**MongoDB**](https://market.olares.com/middleware/mongodb) middleware. Once installed, the [Percona Operator for MongoDB](https://github.com/percona/percona-server-mongodb-operator) automatically manages the **MongoDB** cluster. Users can then horizontally scale **MongoDB** cluster replicas, as well as perform backup and restore operations on databases.
|
||||
|
||||
You can specify detailed configuration for MongoDB in [OlaresManifest.yaml](../package/manifest.md#middleware) as follows:
|
||||
|
||||
```yaml
|
||||
middleware:
|
||||
mongodb:
|
||||
username: mongodb
|
||||
databases:
|
||||
- name: db0
|
||||
- name: db1
|
||||
options:
|
||||
dependencies:
|
||||
- name: olares
|
||||
type: system
|
||||
version: ">=1.6.0-0"
|
||||
- name: mongodb
|
||||
version: ">=6.0.0-0"
|
||||
type: middleware
|
||||
```
|
||||
|
||||
## Cache
|
||||
|
||||
In terms of the Cache cluster, Olares uses Redis Cluster. The cluster is managed by a customized [Redis Cluster Operator](https://github.com/beclab/redis-cluster-operator) to achieve cloud nativeness. It enables us to scale replicas horizontally in a convenient and effective manner.
|
||||
|
||||
To ensure **data isolation** between users and apps in the **Redis cluster**, the **Olares** system has added a **Redis cluster proxy**. It isolates data based on the `namespace`. This operation is transparent, meaning app developers typically do not need to be aware of it.
|
||||
|
||||
Additionally, this proxy simplifies the process of connecting to clusters. It eliminates the need to switch from a **standalone Redis Client** to a **Redis Cluster client** in the app, thus simplifying app code modifications.
|
||||
|
||||
```
|
||||
middleware:
|
||||
redis:
|
||||
password: password
|
||||
namespace: db0
|
||||
```
|
||||
|
||||
:::info NOTE
|
||||
Since Olares uses the Redis Cluster version, developers need to understand the usage restrictions of Redis Cluster in detail when using it.
|
||||
:::
|
||||
175
docs/developer/develop/advanced/file-upload.md
Normal file
175
docs/developer/develop/advanced/file-upload.md
Normal file
@@ -0,0 +1,175 @@
|
||||
---
|
||||
outline: [2, 3]
|
||||
---
|
||||
|
||||
# File Upload
|
||||
|
||||
There are many situations where you might need to upload local files to your edge when using **Olares**. The `Olares Application Runtime` provides a common file-upload component to simplify this process in app development. Moreover, this file-upload component features **resumable upload**.
|
||||
|
||||
## How to install
|
||||
|
||||
To use this feature, simply add the following configuration to the [OlaresManifest.yaml](../package/manifest.md#upload) file in the application chart.
|
||||
```yaml
|
||||
upload:
|
||||
fileType:
|
||||
- pdf
|
||||
dest: /appdata
|
||||
limitedSize: 3729747942
|
||||
```
|
||||
|
||||
## Frontend API
|
||||
|
||||
:::info NOTE
|
||||
The limit for a single upload is 10MB. If the file is larger than 10MB, you must upload using the resumable upload API.
|
||||
:::
|
||||
|
||||
|
||||
### Upload
|
||||
|
||||
This interface is used to upload files to the server and get the file id and status.
|
||||
:::details Example
|
||||
**Request**
|
||||
```sh
|
||||
curl --location 'http://host:40030/upload/' \
|
||||
--form 'storage_path="./testupload/"' \
|
||||
--form 'file_relative_path="1.csv"' \
|
||||
--form 'file_type="csv"' \
|
||||
--form 'file_size="1937"'
|
||||
```
|
||||
**Response**
|
||||
```json
|
||||
{
|
||||
"code": 0,
|
||||
"message": "success",
|
||||
"data": {
|
||||
"id": "b0b76f02bdb8ee3269602c983c4a2aeb",
|
||||
"offset": 0,
|
||||
"file_relative_path": "1.csv",
|
||||
"file_type": "csv",
|
||||
"file_size": 1937,
|
||||
"storage_path": "./testupload/"
|
||||
}
|
||||
}
|
||||
```
|
||||
:::
|
||||
|
||||
- **Request**
|
||||
|
||||
- **URL**: `/upload/`
|
||||
|
||||
- **Method**: `POST`
|
||||
|
||||
- **Body**:
|
||||
``` json
|
||||
"mode": "formdata", //The request body type must set to multipart/form-data
|
||||
"body parameters": {
|
||||
"storage_path": string, //required, the storage path for the file on the server. Ensure that this folder exists.
|
||||
"file_relative_path": string, //required, the location of file relative to the storage_path, it must include the filename. If it is a floder, end with '/'
|
||||
"file_type": string, //required, File type
|
||||
"file_size": integer, //required, File size
|
||||
}
|
||||
```
|
||||
- **Success Response**
|
||||
|
||||
The response body contains the following content, formatted in JSON.
|
||||
- **Status Code** : `200 OK`
|
||||
```json
|
||||
"code": integer, // Response code, 0 means success, non-zero means failure.
|
||||
"message": string, // Response message, return "success" upon success, and the corresponding error message upon failure.
|
||||
"data":{ //Response data. Upon success, it includes the following fields (these contents is absent when uploading a folder):
|
||||
"id": string, // Unique identifier of the file
|
||||
"offset": integer, //The offset of the file uploaded
|
||||
"file_relative_path": string,
|
||||
"file_type": string,
|
||||
"file_size": integer,
|
||||
"storage_path": string
|
||||
}
|
||||
```
|
||||
|
||||
- **Error Response**
|
||||
- **Status Code** : `400 Bad Request`
|
||||
> The request is invalid due to illegal or missing parameters.
|
||||
- **Status Code** : `500 Internal Server Error`
|
||||
> An internal server error has occurred, which prevented the request from being fulfilled. This could be due to reasons such as failure to create a folder or save file information.
|
||||
|
||||
### Resumable Upload
|
||||
|
||||
This interface is used to continue uploading the remaining part of the file.
|
||||
:::details Example
|
||||
**Request**
|
||||
```sh
|
||||
curl --location --request PATCH 'http://host:40030/upload/b0b76f02bdb8ee3269602c983c4a2aeb' \
|
||||
--form 'file=@"/Users/yangtao/Downloads/1.csv"' \
|
||||
--form 'upload_offset="0"'
|
||||
```
|
||||
**Response**
|
||||
```json
|
||||
{
|
||||
"code": 0,
|
||||
"message": "File uploaded successfully",
|
||||
"data": {
|
||||
"id": "b0b76f02bdb8ee3269602c983c4a2aeb",
|
||||
"offset": 1937,
|
||||
"file_name": "1.csv",
|
||||
"file_type": "csv",
|
||||
"file_size": 1937,
|
||||
"storage_path": "./testupload"
|
||||
}
|
||||
}
|
||||
{
|
||||
"code": 0,
|
||||
"message": "Continue uploading",
|
||||
"data": {
|
||||
"id": "e3133b0f838124ff3ebcc9cb14774f26",
|
||||
"offset": 1048576,
|
||||
"file_name": "1.pdf",
|
||||
"file_type": ".pdf",
|
||||
"file_size": 10296258,
|
||||
"storage_path": "./testupload"
|
||||
}
|
||||
}
|
||||
```
|
||||
:::
|
||||
|
||||
- **Request**
|
||||
|
||||
- **URL**: `http://host:40030/upload/{uid}`
|
||||
|
||||
- **Method**: `PATCH`
|
||||
|
||||
- **Body**:
|
||||
``` json
|
||||
"mode": "formdata", //The request body type must set to multipart/form-data
|
||||
"body parameters": {
|
||||
"file": string, //required. The file to be uploaded. Please upload the file in multipart/form-data format.
|
||||
"upload_offset": integer, //required. The offset refers to the size of the file that has already been uploaded.
|
||||
}
|
||||
"url parameters": {
|
||||
"uid": string, //required. This is the unique identifier of the file. You can obtain it from the response data of the Upload API.
|
||||
}
|
||||
```
|
||||
- **Success Response**
|
||||
|
||||
The response body contains the following content, formatted in JSON.
|
||||
- **Status Code** : `200 OK`
|
||||
```json
|
||||
"code": integer, // Response code, 0 means success, non-zero means failure.
|
||||
"message": string, // Response message, return "File uploaded successfully" upon success, and the corresponding error message upon failure.
|
||||
"data":{ //Response data. Upon success, it includes the following fields
|
||||
"id": string, // Unique identifier of the file
|
||||
"offset": integer, //The offset of the file uploaded
|
||||
"file_relative_path": string,
|
||||
"file_type": string,
|
||||
"file_size": integer,
|
||||
"storage_path": string
|
||||
}
|
||||
```
|
||||
|
||||
- **Error Response**
|
||||
- **Status Code** : `400 Bad Request`
|
||||
> The request is invalid due to illegal or missing parameters.
|
||||
```json
|
||||
{ "code": 1, "message": "Invalid upload ID" }
|
||||
```
|
||||
- **Status Code** : `500 Internal Server Error`
|
||||
> An internal server error has occurred, which prevented the request from being fulfilled. This could be due to reasons such as failure to create a folder, save file information, or move file.
|
||||
9
docs/developer/develop/advanced/frontend.md
Normal file
9
docs/developer/develop/advanced/frontend.md
Normal file
@@ -0,0 +1,9 @@
|
||||
# Frontend
|
||||
|
||||
## 视觉规范
|
||||
|
||||
https://w8wvyn24o5.feishu.cn/wiki/Im1nwwPCRiIcGCkBy8qc1vNknVd
|
||||
|
||||
## core 库
|
||||
|
||||
## UI 库
|
||||
BIN
docs/developer/develop/advanced/image-6.png
Normal file
BIN
docs/developer/develop/advanced/image-6.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 69 KiB |
BIN
docs/developer/develop/advanced/images/restore.jpg
Normal file
BIN
docs/developer/develop/advanced/images/restore.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 240 KiB |
14
docs/developer/develop/advanced/index.md
Normal file
14
docs/developer/develop/advanced/index.md
Normal file
@@ -0,0 +1,14 @@
|
||||
# Advanced
|
||||
|
||||
1. [Olares CLI](cli/olares-cli.md)
|
||||
2. [Olares Info](./terminus-info)
|
||||
3. [Service Provider](./provider.md)
|
||||
4. [AI](./ai.md)
|
||||
5. [Cookie](./cookie.md)
|
||||
6. [Database](./database.md)
|
||||
7. [Account](./account.md)
|
||||
8. [Market](./market.md)
|
||||
9. [Websocket](./websocket.md)
|
||||
10. [Files Upload](./file-upload.md)
|
||||
11. [Secret](./secret.md)
|
||||
12. [Kubesphere](./kubesphere.md)
|
||||
14
docs/developer/develop/advanced/kubesphere.md
Normal file
14
docs/developer/develop/advanced/kubesphere.md
Normal file
@@ -0,0 +1,14 @@
|
||||
# Kubesphere
|
||||
|
||||
Olares has integrated many advanced features of Kubesphere like the multi-user system and cluster data monitoring. To install the official console tool from **Kubesphere**, download and install it from the **Olares** code repository.
|
||||
|
||||
```sh
|
||||
curl -LO https://github.com/Above-Os/terminus-os/raw/main/third-party/ks-console/ks-console-v3.3.0.tgz
|
||||
|
||||
# The username is your Olares ID
|
||||
sudo helm install console ./ks-console-v3.3.0.tgz \
|
||||
-n user-space-<username> \
|
||||
--set username=<username>
|
||||
```
|
||||
|
||||
After you install it, refresh your desktop. You'll then see the Console icon in Olares. Open Console and log in with your Olares ID and password.
|
||||
79
docs/developer/develop/advanced/market.md
Normal file
79
docs/developer/develop/advanced/market.md
Normal file
@@ -0,0 +1,79 @@
|
||||
# Market
|
||||
|
||||
To install or uninstall apps in developing applications (for example, third-party Market extensions), developers can use the `install` and `uninstall` API provided by the **Market**.
|
||||
|
||||
For how to define and call provider, please refer to [Service Provider](./provider.md)
|
||||
|
||||
**Provider from Market**
|
||||
|
||||
| Group | version | dataType | ops |
|
||||
| ---------------- | ------- | -------- | ----------------------------- |
|
||||
| service.appstore | v1 | app | `InstallDevApp`<br>`UninstallDevApp` |
|
||||
|
||||
## Install
|
||||
- **Request**
|
||||
- **URL**: <br>`http://$OS_SYSTEM_SERVER/system-server/v1alpha1/app/service.appstore/v1/InstallDevApp`
|
||||
|
||||
- **Method**: `POST`
|
||||
|
||||
- **Header**
|
||||
```http
|
||||
X-Authorization: token # auth_token in cookie
|
||||
X-Access-Token: access_token # access token get from authorization Provider
|
||||
```
|
||||
|
||||
- **Body** (Golang struct as an example)
|
||||
```go
|
||||
type InstallOptions struct {
|
||||
App string `json:"appName"` //required
|
||||
RepoUrl string `json:"repoUrl"` //required
|
||||
CfgUrl string `json:"cfgUrl"` //optional
|
||||
Version string `json:"version"` //required when upgrading
|
||||
Source string `json:"source"` //required
|
||||
}
|
||||
```
|
||||
|
||||
- **Success Responses**
|
||||
```go
|
||||
type InstallationResponse struct {
|
||||
Code int `json:"code"`
|
||||
Msg string `json:"message,omitempty"`
|
||||
Data InstallationResponseData `json:"data"`
|
||||
}
|
||||
|
||||
type InstallationResponseData struct {
|
||||
UID string `json:"uid"`
|
||||
}
|
||||
```
|
||||
|
||||
## Uninstall
|
||||
- **Request**
|
||||
- **URL**: <br>`http://$OS_SYSTEM_SERVER/system-server/v1alpha1/app/service.appstore/v1/UninstallDevApp`
|
||||
|
||||
- **Method**: `POST`
|
||||
|
||||
- **Header**
|
||||
```http
|
||||
X-Authorization: token # auth_token in cookie
|
||||
X-Access-Token: access_token # access token get from authorization Provider
|
||||
```
|
||||
|
||||
- **Body** (Golang struct as an example)
|
||||
```go
|
||||
type UninstallData struct {
|
||||
Name string `json:"name"` //required
|
||||
}
|
||||
```
|
||||
|
||||
- **Success Responses**
|
||||
```go
|
||||
type InstallationResponse struct {
|
||||
Code int `json:"code"`
|
||||
Msg string `json:"message,omitempty"`
|
||||
Data InstallationResponseData `json:"data"`
|
||||
}
|
||||
|
||||
type InstallationResponseData struct {
|
||||
UID string `json:"uid"`
|
||||
}
|
||||
```
|
||||
4
docs/developer/develop/advanced/notification.md
Normal file
4
docs/developer/develop/advanced/notification.md
Normal file
@@ -0,0 +1,4 @@
|
||||
# Notification
|
||||
|
||||
https://w8wvyn24o5.feishu.cn/wiki/SDLsw7KTAiohe5kmYM4cyNeCnCd
|
||||
https://w8wvyn24o5.feishu.cn/wiki/E8RzwY3NAiRT8UkwYxQc9Hndnbf
|
||||
117
docs/developer/develop/advanced/provider.md
Normal file
117
docs/developer/develop/advanced/provider.md
Normal file
@@ -0,0 +1,117 @@
|
||||
# Service Provider
|
||||
|
||||
App developers can define the `ProviderRegistry` in the application chart or request permission to call other providers.
|
||||
|
||||
## Define Provider
|
||||
|
||||
```yaml
|
||||
apiVersion: sys.bytetrade.io/v1alpha1
|
||||
kind: ProviderRegistry
|
||||
metadata:
|
||||
# Provider name. A namespace is required to prevent duplication.
|
||||
name: provider-{{ .Release.Namespace }}
|
||||
|
||||
# provider registry needs to be installed under user-system
|
||||
namespace: user-system-{{ .Values.bfl.username}}
|
||||
spec:
|
||||
version: v2 #The latest version is v2, but the system remains compatible with v1.
|
||||
|
||||
# dataType of provider, it is recommended to add app name to prevent duplication.
|
||||
dataType: legacy_{{ .Release.Name }}
|
||||
deployment: {{ .Release.Name }}
|
||||
description: {{ .Release.Name }} legacy api v2
|
||||
|
||||
# accessible service from the provider. Usually it is <appServiceName>.<appNameSpace>:<servicePort>
|
||||
endpoint: {{ .Release.Name }}-svc.{{ .Release.Namespace }}:1234
|
||||
|
||||
# group of the provider; it is recommended to add the app name to prevent duplication.
|
||||
group: api.{{ .Release.Name }}
|
||||
kind: provider
|
||||
namespace: "{{ .Release.Namespace }}"
|
||||
opApis:
|
||||
# name of the provided API
|
||||
- name: AppApi
|
||||
# URL of the API
|
||||
uri: /api
|
||||
status:
|
||||
state: active
|
||||
```
|
||||
|
||||
## Request Permission to Call Provider
|
||||
|
||||
You can configure it in the [OlaresManifest.yaml](../package/manifest.md#sysdata) as follows:
|
||||
|
||||
```Yaml
|
||||
sysData:
|
||||
- appName: providerapp # The appname of the api provider. Required for ProviderRegistry v2.
|
||||
port: 8888 # The port of the provider service
|
||||
|
||||
# The default domain of provider is <appName>-svc.<appName>-<username>:<port>, if the service name and app namespace is not in default format, you can specify it in following field
|
||||
svc: app-svc # Name of the service. Optional for ProviderRegistry v2.
|
||||
namespace: ns # Namespace of the app. Optional for ProviderRegistry v2.
|
||||
|
||||
version: v2 # version of the ProviderRegistry
|
||||
dataType: legacy_{{ .Release.Name }} # dataType defined in ProviderRegistry
|
||||
group: api.{{ .Release.Name }} # group defined in ProviderRegistry
|
||||
ops:
|
||||
- AppApi # name of opApis defined in ProviderRegistry
|
||||
```
|
||||
|
||||
Once configured, you can add the `access key` and `access secret` to the templates in the application chart. They will be injected during installation for authorized usage.
|
||||
|
||||
```yaml
|
||||
env:
|
||||
- name: OS_SYSTEM_SERVER
|
||||
value: system-server.user-system-{{ .Values.bfl.username }}
|
||||
- name: OS_APP_SECRET
|
||||
|
||||
# The appname is defined in the application chart
|
||||
value: "{{ .Values.os.<appnane>.appSecret }}"
|
||||
- name: OS_APP_KEY
|
||||
value: "{{ .Values.os.<appname>.appKey }}"
|
||||
```
|
||||
|
||||
You can use these three environment variables in the code to call the **Provider**. Take `curl` as an example:
|
||||
|
||||
1. Get the `access token`, which has a valid duration of 5 minutes. Token encryption algorithm: bcrypt(`app key` `timestamp` `app secret`), default cost 10.
|
||||
|
||||
```sh
|
||||
now=$(date +%s)
|
||||
token=$(htpasswd -nbBC 10 USER "${OS_APP_KEY}${now}${OS_APP_SECRET}"|awk -F":" '{print $2}')
|
||||
|
||||
curl -X POST http://${OS_SYSTEM_SERVER}/permission/v1alpha1/access -H "content-type: application/json" \
|
||||
-d "{ \
|
||||
\"app_key\": \"${OS_APP_KEY}\", \
|
||||
\"timestamp\": ${now}, \
|
||||
\"token\": \"${token}\", \
|
||||
\"perm\": { \
|
||||
\"group\": \"service.bfl\", \
|
||||
\"dataType\": \"app\", \
|
||||
\"version\": \"v1\", \
|
||||
\"ops\": [ \
|
||||
\"InstallDevApp\" \
|
||||
] \
|
||||
} \
|
||||
}'
|
||||
```
|
||||
|
||||
2. You will receive a response like:
|
||||
```json
|
||||
{
|
||||
"code": 0,
|
||||
"message": "success",
|
||||
"data": {
|
||||
"access_token": "JDJ5JDEwJE5Wbk9vbFpoLjJlSGxhUUpRY1IwRmVZVjFBWmUxUi5LOXNuQWJmVjRnN29xNWVVaFhPWmV5"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
3. You can then use the token to call the provider's API
|
||||
|
||||
```sh
|
||||
# API URL format http://${OS_SYSTEM_SERVER}/system-server/v1alpha1/<dataType>/<group>/<version>/<op>
|
||||
curl http://${OS_SYSTEM_SERVER}/system-server/v1alpha1/app/service.bfl/v1/InstallDevApp \
|
||||
-H "content-type: application/json" \
|
||||
-H "X-Access-Token: ${access_token}" \
|
||||
-d '{"data":"post to provider"}'
|
||||
```
|
||||
1
docs/developer/develop/advanced/rss.md
Normal file
1
docs/developer/develop/advanced/rss.md
Normal file
@@ -0,0 +1 @@
|
||||
# RSS
|
||||
132
docs/developer/develop/advanced/secret.md
Normal file
132
docs/developer/develop/advanced/secret.md
Normal file
@@ -0,0 +1,132 @@
|
||||
---
|
||||
outline: [2, 3]
|
||||
---
|
||||
|
||||
# Secret
|
||||
|
||||
In an app, it's often necessary to save some important user information, such as `passwords` and `Access Tokens` for external systems. Olares provides a unified Vault, based on Infisical, to securely store various keys.
|
||||
|
||||
To retrieve this information, the app only needs a simple application for API access permission. This can be done by adding a `sysData` permission to the [OlaresManifest.yaml](../package/manifest.md#sysdata) in the application chart.
|
||||
|
||||
```yaml
|
||||
permission:
|
||||
sysData:
|
||||
- dataType: secret
|
||||
group: secret.infisical
|
||||
version: v1
|
||||
ops:
|
||||
- RetrieveSecret?workspace=your-app # Each app should define its own workspace
|
||||
- CreateSecret?workspace=your-app
|
||||
- DeleteSecret?workspace=your-app
|
||||
- UpdateSecret?workspace=your-app
|
||||
- ListSecret?workspace=your-app
|
||||
```
|
||||
|
||||
## Call API
|
||||
|
||||
You can call the API in the same way you would request other providers. Use the full name of ops (including the workspace parameter) as the URI.
|
||||
|
||||
Please include this **header** in all requests.
|
||||
```http
|
||||
X-Authorization: token # auth_token in cookie
|
||||
```
|
||||
|
||||
### RetrieveSecret
|
||||
- **Request Body**
|
||||
```json
|
||||
{
|
||||
"name": "string", // secret name
|
||||
"env": "string" // environment of secret, test | dev | staging | prod (default)
|
||||
}
|
||||
```
|
||||
- **Success Response**
|
||||
```json
|
||||
{
|
||||
"code": http.StatusOK, // 200 is ok
|
||||
"message": "",
|
||||
"data":{
|
||||
"name": "string", // secret name
|
||||
"value": "string", // secret value
|
||||
"env": "string" // environment of secret, test | dev | staging | prod
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### CreateSecret
|
||||
- **Request Body**
|
||||
```json
|
||||
{
|
||||
"name": "string", // secret name
|
||||
"value": "string", // secret value
|
||||
"env": "string" // environment of secret, test | dev | staging | prod (default)
|
||||
}
|
||||
```
|
||||
|
||||
- **Success Response**
|
||||
```json
|
||||
{
|
||||
"code": http.StatusOK, // 200 is ok
|
||||
"message": "",
|
||||
"data":""
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
### DeleteSecret
|
||||
- **Request Body**
|
||||
```json
|
||||
{
|
||||
"name": "string", // secret name
|
||||
"env": "string" // environment of secret, test | dev | staging | prod (default)
|
||||
}
|
||||
```
|
||||
|
||||
- **Success Response**
|
||||
```json
|
||||
{
|
||||
"code": http.StatusOK, // 200 is ok
|
||||
"message": "",
|
||||
"data":""
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
### UpdateSecret
|
||||
- **Request Body**
|
||||
```json
|
||||
{
|
||||
"name": "string", // secret name
|
||||
"value": "string", // secret value
|
||||
"env": "string" // environment of secret, test | dev | staging | prod (default)
|
||||
}
|
||||
```
|
||||
|
||||
- **Success Response**
|
||||
```json
|
||||
{
|
||||
"code": http.StatusOK, // 200 is ok
|
||||
"message": "",
|
||||
"data":""
|
||||
}
|
||||
```
|
||||
|
||||
### ListSecret
|
||||
- **Request Body**
|
||||
```json
|
||||
{
|
||||
"env": "string" // environment of secret, test | dev | staging | prod (default)
|
||||
}
|
||||
```
|
||||
|
||||
- **Success Response**
|
||||
```json
|
||||
{
|
||||
"code": http.StatusOK, // 200 is ok
|
||||
"message": "",
|
||||
"data":{
|
||||
"name": "string", // secret name
|
||||
"value": "string", // secret value
|
||||
"env": "string" // environment of secret, test | dev | staging | prod
|
||||
}
|
||||
}
|
||||
```
|
||||
37
docs/developer/develop/advanced/terminus-info.md
Normal file
37
docs/developer/develop/advanced/terminus-info.md
Normal file
@@ -0,0 +1,37 @@
|
||||
# terminus-info
|
||||
|
||||
terminus-info is an API without authentication. It displays publicly available system information. You can think of it as a house number sign.
|
||||
|
||||
## API Call
|
||||
|
||||
```
|
||||
https://<username>.olares.com/api/terminus-info
|
||||
```
|
||||
|
||||
## Data Structure
|
||||
|
||||
```json
|
||||
interface TerminusInfo {
|
||||
terminusName: string;
|
||||
wizardStatus: string;
|
||||
selfhosted: boolean;
|
||||
tailScaleEnable: boolean;
|
||||
osVersion: string;
|
||||
avatar: string;
|
||||
loginBackground: string;
|
||||
terminusId: string;
|
||||
}
|
||||
```
|
||||
|
||||
## API Field Definitions
|
||||
|
||||
| Field | Description |
|
||||
|-----------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||
| terminusName | The user's Olares ID follows a format like `username@domain.com`. |
|
||||
| wizardStatus | Activation status of Olares, possible statuses includes: `wait_activate_vault`, `vault_activating`, `vault_activate_failed`, `wait_activate_system`, `system_activating`, `system_activate_failed`, `wait_activate_network`, `network_activating`, `network_activate_failed`, `wait_reset_password`, `completed`. When the status displays `completed`, it indicates that the system has been successfully activated. We advise against third-party programs executing excessive business-related logic before the system is fully activated. |
|
||||
| selfhosted | Whether the Olares is running on Olares Space |
|
||||
| tailScaleEnable | Whether the TailScale is activated. If so, all private entrances can only be accessed through the VPN. <br> Note: This field does not affect whether LarePass uses local access when connecting to Olares. |
|
||||
| osVersion | Olares version |
|
||||
| avatar | User's Avatar |
|
||||
| loginBackground | Background image of the login interface |
|
||||
| olaresId | Every time the user activates Olares, a new unique ID is generated. |
|
||||
171
docs/developer/develop/advanced/websocket.md
Normal file
171
docs/developer/develop/advanced/websocket.md
Normal file
@@ -0,0 +1,171 @@
|
||||
---
|
||||
outline: [2, 3]
|
||||
---
|
||||
|
||||
# Websocket
|
||||
|
||||
**WebSocket** is one of the most widely used technologies in modern front-end development. To simplify its use in **Olares** app development, **Olares Application Runtime (TAPR)** provides a common **WebSocket** component.
|
||||
|
||||
## Client
|
||||
|
||||
The Client is developed using `JavaScript/TypeScript` use the **ws** library.
|
||||
The application server provides the WebSocket through a URL formatted as `wss://<appid>.<username>.olares.com/ws`.
|
||||
|
||||
### Send Message
|
||||
|
||||
An example of WebSocket messages sent from clients is outlined below (other formats are also supported):
|
||||
```json
|
||||
{
|
||||
"event": "...",
|
||||
"data": {...}
|
||||
}
|
||||
```
|
||||
|
||||
### Ping
|
||||
|
||||
The client should send a 'ping' message every 30 seconds to keep the WebSocket connection alive. If the WebSocket service doesn't receive a 'ping' within the time limit, it will close the connection. The data format for the 'ping' message should adhere to the following structure:
|
||||
```json
|
||||
{
|
||||
"event": "ping",
|
||||
"data": {}
|
||||
}
|
||||
```
|
||||
|
||||
## App
|
||||
|
||||
The **WebSocket Service** offers multiple features:
|
||||
- It allows the server to communicate with clients either by broadcasting messages or responding to WebSocket messages sent by clients.
|
||||
- It can be used to close a WebSocket connection for a specific user or connection ID.
|
||||
- It provides the current connection list.
|
||||
|
||||
Both the **App** and **WebSocket** are deployed in the same container, allowing direct access to the **WebSocket service** via `localhost`. The service uses port `40010`.
|
||||
|
||||
### Broadcast Message
|
||||
```json
|
||||
// URL:<http://localhost:40010/tapr/ws/conn/send>
|
||||
// Request method: POST
|
||||
// body
|
||||
{
|
||||
"payload": {}, // Message.
|
||||
"conn_id": "<connId>", // Connection ID; used to respond to the client's single Ws request. Do not fill in connId when broadcasting to users
|
||||
"users": ["<userName-1>", "<userName-2>"], // Specify users. If this field is filled in, it is a broadcast. Do not fill in connId in broadcast situation
|
||||
}
|
||||
|
||||
// Response example
|
||||
{
|
||||
"code": 0,
|
||||
"message": "success",
|
||||
}
|
||||
```
|
||||
|
||||
### Close WebSocket Connection of Client
|
||||
```json
|
||||
// URL:<http://localhost:40010/tapr/ws/conn/close>
|
||||
// Request method: POST
|
||||
// body
|
||||
{
|
||||
"conns": ["<connId>", ...], // Close specified connections
|
||||
"users": ["<userName>", ...], // Close all connections for specified users
|
||||
}
|
||||
|
||||
// Response example
|
||||
{
|
||||
"code": 0,
|
||||
"message": "success",
|
||||
}
|
||||
```
|
||||
|
||||
### Get Current Online Connection List
|
||||
|
||||
```json
|
||||
// URL:<http://localhost:40010/tapr/ws/conn/list>
|
||||
// Request method: GET
|
||||
// Response example
|
||||
{
|
||||
"code": 0,
|
||||
"message": "success",
|
||||
"data": [
|
||||
{
|
||||
"name": "<userName>",
|
||||
"conns": [
|
||||
{
|
||||
"id": "<connId>", // Connection ID
|
||||
"userAgent": ""
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
### Forwards Client Messages to App via WebSocket
|
||||
|
||||
There are three types of client messages that will be forward to App:
|
||||
- Establishing a client connection
|
||||
- Regular messages sent by the client
|
||||
- Client disconnected, which happens when the browser closes or network issues occur.
|
||||
|
||||
**Client connection**
|
||||
|
||||
```json
|
||||
// URL:<http://localhost:3010/websocket/message>
|
||||
// Method: POST
|
||||
// body
|
||||
|
||||
{
|
||||
"data": {},
|
||||
"action": "open", // action
|
||||
"user_name": "<userName>",
|
||||
"conn_id": "1" // WebSocket Connection ID
|
||||
}
|
||||
|
||||
// When the app receives the "open" message, it will execute the associated processes.
|
||||
```
|
||||
|
||||
**Regular messages**
|
||||
|
||||
```json
|
||||
// URL:<http://localhost:3010/websocket/message>
|
||||
// Method: POST
|
||||
// header, the original Cookie of the client will be passed to the backend application
|
||||
Cookie: .... // New feature in version v1.0.3
|
||||
|
||||
// body
|
||||
{
|
||||
"data": { ... }, // The original data sent by the client to WSGateway, the internal structure is {"event":"", "data": {...}}
|
||||
"action": "message", // action
|
||||
"user_name": "<userName>",
|
||||
"conn_id": "1", // WebSocket Connection ID
|
||||
}
|
||||
|
||||
// After processing, the app returns the data to the client through the "Broadcast Message" API.
|
||||
```
|
||||
|
||||
**Client Disconnected**
|
||||
> The WebSocket service callback the App when it receives a close message
|
||||
```json
|
||||
// URL:<http://localhost:3010/websocket/message>
|
||||
// Method: POST
|
||||
// body
|
||||
|
||||
{
|
||||
"data": {},
|
||||
"action": "close", // action
|
||||
"user_name": "<userName>",
|
||||
"conn_id": "1" // WebSocket Connection ID
|
||||
}
|
||||
|
||||
// When the app receives the "close" message, it will execute the associated processes.
|
||||
```
|
||||
|
||||
## Deploy WebSocket Service in App
|
||||
|
||||
To use this feature, simply add the `websocket configuration` to the [OlaresManifest.yaml](../package/manifest.md#websocket) file in the application chart.
|
||||
```yaml
|
||||
options:
|
||||
websocket:
|
||||
url: /ws/message
|
||||
port: 8888
|
||||
```
|
||||
|
||||
**WebSocket** is a component that facilitates message forwarding between the client and the App. Consequently, the App must provide an **API** for **WebSocket** to manage `ws` messages from the client. For instance, in the example above, the APP should provide an API named `/ws/message` on port `8888`.
|
||||
15
docs/developer/develop/index.md
Normal file
15
docs/developer/develop/index.md
Normal file
@@ -0,0 +1,15 @@
|
||||
# Develop Olares application
|
||||
|
||||
Developing applications on Olares is not much different from regular website development. Once you learn a few basic Olares concepts, you can start creating applications on his platform.
|
||||
|
||||
- [Core Concepts of Olares](../../manual/concepts/index.md)
|
||||
- [Understanding the Format of Olares Application Chart](./package/chart.md)
|
||||
- [The structure of the Olares Application Chart](./package/chart.md)
|
||||
- [Configuration guide and field descriptions of `OlaresManifest.yaml`](./package/manifest.md)
|
||||
- [Extensions field to Helm in Olares](./package/extension.md)
|
||||
|
||||
- [Exploring Our Tutorials](./tutorial/)
|
||||
- [Learn about Devbox, an Olares Development Tool](./tutorial/studio)
|
||||
- [Creating your first application](./tutorial/note/)
|
||||
- [Exploring Advanced Concepts](./advanced/)
|
||||
- [Submitting Applications to the Olares Market](./submit/)
|
||||
48
docs/developer/develop/package/chart.md
Normal file
48
docs/developer/develop/package/chart.md
Normal file
@@ -0,0 +1,48 @@
|
||||
# Olares Application Chart Structure
|
||||
|
||||
The Olares Application Chart is built upon the structure of **Helm Chart**, with extensions to accommodate specific **Olares** information. A standard application chart contains the following files:
|
||||
```
|
||||
|-- Chart.yaml # chart metadata
|
||||
|-- OlaresManifest.yaml # Olares Application configuration
|
||||
|-- templates/ # chart deployment template files
|
||||
| |-- deployment.yaml # APP deployment script
|
||||
|-- crds/ # OPTIONAL: Custom Resource Definitions
|
||||
|-- values.yaml # OPTIONAL: The default deployment parameters for this chart
|
||||
|-- values.schema.json # OPTIONAL: A JSON Schema for imposing a structure on the values.yaml file
|
||||
|-- README.md # OPTIONAL: A human-readable README file
|
||||
```
|
||||
:::info NOTE
|
||||
To make the templates directory easier to understand, you can split the deployment into several files.
|
||||
:::
|
||||
|
||||
- A typical application chart for `App` and `Middleware`:
|
||||
```
|
||||
AppName
|
||||
|-- Chart.yaml # Required: YAML file containing chart metadata
|
||||
|-- OlaresManifest.yaml # Required: containing App configuration
|
||||
|-- values.yaml # Required: default configuration values of the chart
|
||||
|-- templates # Required: template directory, when combined with values, it can generate valid Kubernetes manifest files
|
||||
| |-- NOTES.txt # Optional: plain text file containing brief usage instructions
|
||||
| |-- deployment.yaml # Defines the deployment for App installation
|
||||
| |-- service.yaml # Defines the Service that provides the Entrance for the App
|
||||
| |-- provider.yaml # Optional: if you need to expose the Provider API
|
||||
|-- LICENSE # Optional: plain text file containing the chart license
|
||||
|-- README.md # Optional: readable README file
|
||||
```
|
||||
|
||||
- A typical application chart for `Recommend`:
|
||||
|
||||
```
|
||||
RecommendName
|
||||
|-- Chart.yaml # Required: YAML file containing chart metadata
|
||||
|-- OlaresManifest.yaml # Required: containing Recommend configuration
|
||||
|-- values.yaml # Required: default configuration values of the chart
|
||||
|-- templates # Required: template directory, when combined with values, it can generate valid Kubernetes manifest files
|
||||
| |-- NOTES.txt # Optional: plain text file containing brief usage instructions
|
||||
| |-- train.yaml # Defines the train process in recommend workflows
|
||||
| |-- prerank.yaml # Defines the prerank process in recommend workflows
|
||||
| |-- rank.yaml # Defines the rank process in recommend workflows
|
||||
| |-- embedding.yaml # Defines the embedding process in recommend workflows
|
||||
|-- LICENSE # Optional: plain text file containing the chart license
|
||||
|-- README.md # Optional: readable README file
|
||||
```
|
||||
73
docs/developer/develop/package/extension.md
Normal file
73
docs/developer/develop/package/extension.md
Normal file
@@ -0,0 +1,73 @@
|
||||
# Extensions field to Helm in Olares
|
||||
|
||||
During installation, Olares injects extended field into the APP, using the configuration from [OlaresManifest.yaml](manifest.md).
|
||||
|
||||
The information from these extended fields can be directly referenced in the template without being defined in values.yaml. If there are definitions in values.yaml with the same name, the system value will overwrite them.
|
||||
|
||||
|
||||
- User Information
|
||||
|
||||
| Value | Type | Description |
|
||||
| -------------------- | ------ | --------------------- |
|
||||
| .Values.bfl.username | String | Username of the currently installing APP |
|
||||
| .Values.user.zone | String | Domain of the current user |
|
||||
|
||||
- Domain Information
|
||||
|
||||
| Value | Type | Description |
|
||||
| -------------- | ------------------ | ---------------------------------------------------- |
|
||||
| .Values.domain | Map<String,String> | Define the Entry for the App, using the entrance name as the key and the URL as the value. |
|
||||
|
||||
- Storage Information
|
||||
| Value | Type | Description
|
||||
| -------------- | ------------------ | ---------------------------------------------------- |
|
||||
| .Values.userspace.appData | String | Cluster storage address available to the APP |
|
||||
| .Values.userspace.appCache | String | Local node cache address available to the APP |
|
||||
| .Values.userspace.userData | String | storage directory of User's data |
|
||||
|
||||
- Cluster Information
|
||||
| Value | Type | Description
|
||||
| -------------- | ------------------ | ---------------------------------------------------- |
|
||||
| .Values.cluster.arch | String | Cluster CPU architecture |
|
||||
|
||||
Multi-platform (AMD64 and ARM) cluster is not supported for now.
|
||||
|
||||
- Application Dependencies
|
||||
| Value | Type | Description
|
||||
| -------------- | ------------------ | ---------------------------------------------------- |
|
||||
| .Values.deps | Map<String, Value> | Current address and port of the applications the APP depends on |
|
||||
| .Values.svcs | Map<String, Value> | Other services and ports of the applications the APP depends on |
|
||||
|
||||
When an application sets dependencies on another application, this will be passed through the `deps` parameter. For instance, if an application, sets a dependency on another application called **'A-Server'**, and **'A-Server'** sets the entry name as **'aserver'** with the entry host configured as **'aserver-svc'**, the value will be like:
|
||||
```
|
||||
{
|
||||
"aserver_host": "aserver-svc.<A-Server namespce>",
|
||||
"aserver_port": 80
|
||||
}
|
||||
```
|
||||
At the same time, `svcs` will pass in all services of A-Server.
|
||||
```
|
||||
{
|
||||
"aserver-svc_host": "aserver-svc.<A-Server namespce>",
|
||||
"aserver-svc_port": [80] # If there are multiple ports in the service, they will be passed in together.
|
||||
}
|
||||
```
|
||||
|
||||
- Database Information
|
||||
|
||||
| Value | Type | Description |
|
||||
| -------------------------- | ------------------ | ---------------------------------------------------------------------------------------------------------- |
|
||||
| .Values.postgres.host | String | PostgreSQL database host address |
|
||||
| .Values.postgres.port | Number | PostgreSQL database port |
|
||||
| .Values.postgres.username | String | PostgreSQL database username |
|
||||
| .Values.postgres.password | String | PostgreSQL database password |
|
||||
| .Values.postgres.databases | Map<String,String> | PostgreSQL database name. Use the configured database name as the key. For instance, if it's configured as 'app_db', the variable would be `.Values.postgres.databases.app_db`. |
|
||||
| .Values.mongo.host | String | MongoDB database host address |
|
||||
| .Values.mongo.port | Number | MongoDB database port |
|
||||
| .Values.mongo.username | String | MongoDB database username |
|
||||
| .Values.mongo.password | String | MongoDB database username |
|
||||
| .Values.mongo.databases | Map<String,String> | MongoDB database name. Use the configured database name as the key. For instance, if it's configured as 'app_db', the variable would be `.Values.mongo.databases.app_db ` |
|
||||
| .Values.redis.host | String | Redis database host address |
|
||||
| .Values.redis.port | Number | Redis database port |
|
||||
| .Values.redis.password | String | Redis database username |
|
||||
| .Values.redis.namespaces | Map<String,String> | Redis namespace. Use the configured namespace as the key. For instance, if it's configured as 'app_ns', the variable would be `.Values.redis.namespaces.app_ns`|
|
||||
806
docs/developer/develop/package/manifest.md
Normal file
806
docs/developer/develop/package/manifest.md
Normal file
@@ -0,0 +1,806 @@
|
||||
---
|
||||
outline: [2, 3]
|
||||
---
|
||||
|
||||
# OlaresManifest Specification
|
||||
|
||||
Every **Olares Application Chart** should include a `OlaresManifest.yaml` file in the root directory. `OlaresManifest.yaml` provides all the essential information about an Olares App. Both the **Olares Market protocol** and the Olares depend on this information to distribute and install applications.
|
||||
|
||||
:::info NOTE
|
||||
Latest Olares Manifest version: `0.9.0`
|
||||
- Added a `conflict` field in `options` to declare incompatible applications
|
||||
- Removed `analytics` field in `options`
|
||||
- Modified the format of the `tailscale` section
|
||||
- Added a `allowedOutboundPorts` field to allow non-http protocol external access through the specified port
|
||||
- Modified the format of the `ports` section
|
||||
|
||||
:::
|
||||
:::details Changelog
|
||||
`0.8.3`
|
||||
- Add a `mandatory` field in the `dependencies` section for dependent applications required for the installation
|
||||
- Add `tailscaleAcls` section to permit applications to open specified ports via Tailscale
|
||||
|
||||
`0.8.2`
|
||||
- Add a `runAsUser` option to force the app to run under non root user
|
||||
|
||||
`0.8.1`
|
||||
- Add a `ports` section to specify exposed ports for UDP or TCP
|
||||
|
||||
`0.7.1`
|
||||
- Add new `authLevel` value `internal`
|
||||
- Change `spec`>`language` to `spec`>`locale` and support i18n
|
||||
:::
|
||||
|
||||
Here's an example of what a `OlaresManifest.yaml` file might look like:
|
||||
|
||||
::: details OlaresManifest.yaml Example
|
||||
|
||||
```Yaml
|
||||
olaresManifest.version: '0.8.0'
|
||||
olaresManifest.type: app
|
||||
metadata:
|
||||
name: helloworld
|
||||
title: Hello World
|
||||
description: app helloworld
|
||||
icon: https://file.bttcdn.com/appstore/default/defaulticon.webp
|
||||
version: 0.0.1
|
||||
categories:
|
||||
- Utilities
|
||||
entrances:
|
||||
- name: helloworld
|
||||
port: 8080
|
||||
title: Hello World
|
||||
host: helloworld
|
||||
icon: https://file.bttcdn.com/appstore/default/defaulticon.webp
|
||||
authLevel: private
|
||||
permission:
|
||||
appCache: true
|
||||
appData: true
|
||||
userData:
|
||||
- Home/Documents/
|
||||
- Home/Pictures/
|
||||
- Home/Downloads/BTDownloads/
|
||||
spec:
|
||||
versionName: '0.0.1'
|
||||
featuredImage: https://link.to/featured_image.webp
|
||||
promoteImage:
|
||||
- https://link.to/promote_image1.webp
|
||||
- https://link.to/promote_image2.webp
|
||||
fullDescription: |
|
||||
A full description of your app.
|
||||
upgradeDescription: |
|
||||
Describe what is new in this upgraded version.
|
||||
developer: Developer's Name
|
||||
website: https://link.to.your.website
|
||||
sourceCode: https://link.to.sourceCode
|
||||
submitter: Submitter's Name
|
||||
language:
|
||||
- en
|
||||
doc: https://link.to.documents
|
||||
supportArch:
|
||||
- amd64
|
||||
limitedCpu: 1000m
|
||||
limitedMemory: 1000Mi
|
||||
requiredCpu: 50m
|
||||
requiredDisk: 50Mi
|
||||
requiredMemory: 12Mi
|
||||
|
||||
options:
|
||||
dependencies:
|
||||
- name: olares
|
||||
type: system
|
||||
version: '>=0.1.0'
|
||||
```
|
||||
:::
|
||||
|
||||
## olaresManifest.type
|
||||
|
||||
- Type: `string`
|
||||
- Accepted Value: `app`, `recommend`, `middleware`
|
||||
|
||||
Olares currently supports 3 types of applications, each requiring different fields. This document uses `app` as an example to explain each field. For information on other types, please refer to the corresponding configuration guide.
|
||||
- [Recommend Configuration Guide](recommend.md)
|
||||
|
||||
:::info Example
|
||||
```Yaml
|
||||
olaresManifest.type: app
|
||||
```
|
||||
:::
|
||||
|
||||
## olaresManifest.version
|
||||
|
||||
- Type: `string`
|
||||
|
||||
As Olares evolves, the configuration specification of `OlaresManifest.yaml` may change. You can identify whether these changes will affect your application by checking the `olaresManifest.version`. The `olaresManifest.version` consists of three integers separated by periods.
|
||||
|
||||
- An increase in the **first digit** indicates the introduction of incompatible configuration items. Applications that haven't updated their `OlaresManifest.yaml` will be unable to distribute or install.
|
||||
- An increase in the **second digit** signifies changes in the mandatory fields for distribution and installation. However, the Olares remains compatible with the application distribution and installation of previous configuration versions. We recommend developers to promptly update and upgrade the application's `OlaresManifest.yaml` file.
|
||||
- A change in the **third digit** does not affect the application's distribution and installation.
|
||||
|
||||
Developers can use 1-3 digit version numbers to indicate the application's configuration version. Here are some examples of valid versions:
|
||||
```Yaml
|
||||
OlaresManifest.yaml.version: 1
|
||||
OlaresManifest.yaml.version: 1.1.0
|
||||
OlaresManifest.yaml.version: '2.2'
|
||||
OlaresManifest.yaml.version: "3.0.122"
|
||||
```
|
||||
|
||||
## Metadata
|
||||
|
||||
Basic information about the app shown in the system and Olares Market.
|
||||
|
||||
:::info Example
|
||||
```Yaml
|
||||
metadata:
|
||||
name: nextcloud
|
||||
title: Nextcloud
|
||||
description: The productivity platform that keeps you in control
|
||||
icon: https://file.bttcdn.com/appstore/nextcloud/icon.png
|
||||
version: 0.0.2
|
||||
categories:
|
||||
- Utilities
|
||||
- Productivity
|
||||
```
|
||||
:::
|
||||
|
||||
### name
|
||||
|
||||
- Type: `string`
|
||||
- Accepted Value: `[a-z][a-z0-9]?`
|
||||
|
||||
App’s namespace in Olares, lowercase alphanumeric characters only. It can be up to 30 characters, and needs to be consistent with `FolderName` and `name` field in `Chart.yaml`.
|
||||
|
||||
### title
|
||||
|
||||
- Type: `string`
|
||||
|
||||
The title of your app title shown in the Olares Market. Must be within `30` characters.
|
||||
|
||||
### description
|
||||
|
||||
- Type: `string`
|
||||
|
||||
A short description appears below app title in the Olares Market.
|
||||
|
||||
### icon
|
||||
|
||||
- Type: `url`
|
||||
|
||||
Your app icon that appears in the Olares Market.
|
||||
|
||||
The app's icon must be a `PNG` or `WEBP` format file, up to `512 KB`, with a size of `256x256 px`.
|
||||
|
||||
### version
|
||||
|
||||
- Type: `string`
|
||||
|
||||
The **Chart Version** of the application. It should be incremented each time the content in the **Chart** changes. It should follow the [Semantic Versioning 2.0.0](https://semver.org/) and needs to be consistent with the `version` field in `Chart.yaml`.
|
||||
|
||||
### categories
|
||||
|
||||
- Type: `list<string>`
|
||||
- Accepted Value: `Blockchain`, `Utilities`, `Social Network`, `Entertainment`, `Productivity`
|
||||
|
||||
Used to display your app on different category page in Olares Market.
|
||||
|
||||
## Entrances
|
||||
|
||||
The number of entrances through which to access the app. You must specify at least 1 access method, with a maximum of 10 allowed.
|
||||
|
||||
:::info Example
|
||||
```Yaml
|
||||
entrances:
|
||||
- name: a
|
||||
host: firefox
|
||||
port: 3000
|
||||
title: Firefox
|
||||
authLevel: public
|
||||
invisible: false
|
||||
- name: b
|
||||
host: firefox
|
||||
port: 3001
|
||||
title: admin
|
||||
```
|
||||
:::
|
||||
|
||||
### name
|
||||
|
||||
- Type: `string`
|
||||
- Accepted Value: `[a-z]([-a-z0-9]*[a-z0-9])?`
|
||||
|
||||
Name of the Entrance. It can be up to `63` characters, and needs to be unique in an app.
|
||||
|
||||
### port
|
||||
|
||||
- Type: `int`
|
||||
- Accepted Value: `0-65535`
|
||||
|
||||
### host
|
||||
|
||||
- Type: `string`
|
||||
- Accepted Value: `[a-z]([-a-z0-9]*[a-z0-9])?`
|
||||
|
||||
Ingress name of current entrance, lowercase alphanumeric characters and `-` only. It can be up to `63` characters.
|
||||
|
||||
### title
|
||||
|
||||
- Type: `string`
|
||||
|
||||
Title that appears in the Olares desktop after installed. It can be up to `30` characters.
|
||||
|
||||
### icon
|
||||
|
||||
- Type: `url`
|
||||
- Optional
|
||||
|
||||
Icon that appears in the Olares desktop after installed. The app's icon must be a `PNG` or `WEBP` format file, up to `512 KB`, with a size of `256x256 px`.
|
||||
|
||||
### authLevel
|
||||
|
||||
- Type: `string`
|
||||
- Accepted Value: `public`, `private`, `internal`
|
||||
- Default: `private`
|
||||
- Optional
|
||||
|
||||
Specify the authentication level of the entrance.
|
||||
- **Public**: Accessible by anyone on the Internet without restrictions.
|
||||
- **Private**: Requires authorization for access from both internal and external networks.
|
||||
- **Internal**: Requires authorization for access from external networks. No authentication is required when accessing from within the internal network (via LAN/VPN).
|
||||
|
||||
### invisible
|
||||
|
||||
- Type: `boolean`
|
||||
- Default: `false`
|
||||
- Optional
|
||||
|
||||
When `invisible` is `true`, the entrance will not be displayed on the Olares desktop.
|
||||
|
||||
### openMethod
|
||||
|
||||
- Type: `string`
|
||||
- Accepted Value: `default`, `iframe`, `window`
|
||||
- Default: `default`
|
||||
- Optional
|
||||
|
||||
Explicitly defines how to open this entrance in Desktop.
|
||||
|
||||
The `iframe` creates a new window within the desktop window through an iframe. The `window` opens a new tab in the browser. The `default` follows the system setting, which is `iframe` by default.
|
||||
|
||||
### windowPushState
|
||||
- Type: `boolean`
|
||||
- Default: `false`
|
||||
- Optional
|
||||
|
||||
When embedding the application in an iframe on the desktop, the application's URL may change dynamically. Due to browser's same-origin policy, the desktop (parent window) cannot directly detect these changes in the iframe URL. Consequently, if you reopen the application tab, it will display the initial URL instead of the updated one.
|
||||
|
||||
To ensure a seamless user experience, you can enable this option by setting it to true. This action prompts the gateway to automatically inject the following code into the iframe. This code sends an event to the parent window (desktop) whenever the iframe's URL changes. As a result, the desktop can track URL changes and open the correct page.
|
||||
|
||||
::: details Code
|
||||
```Javascript
|
||||
<script>
|
||||
(function () {
|
||||
if (window.top == window) {
|
||||
return;
|
||||
}
|
||||
const originalPushState = history.pushState;
|
||||
const pushStateEvent = new Event("pushstate");
|
||||
history.pushState = function (...args) {
|
||||
originalPushState.apply(this, args);
|
||||
window.dispatchEvent(pushStateEvent);
|
||||
};
|
||||
window.addEventListener("pushstate", () => {
|
||||
window.parent.postMessage(
|
||||
{type: "locationHref", message: location.href},
|
||||
"*"
|
||||
);
|
||||
});
|
||||
})();
|
||||
</script>
|
||||
```
|
||||
:::
|
||||
|
||||
## Ports
|
||||
|
||||
Specify exposed ports
|
||||
|
||||
:::info Example
|
||||
```Yaml
|
||||
ports:
|
||||
- name: rdp-tcp # Name of the entrance that provides service
|
||||
host: windows-svc # Ingress name of the entrance that provides service
|
||||
port: 3389 # Port of the entrance that provides service
|
||||
exposePort: 46879 # The port to be exposed can only be assigned to one application at a time within the cluster.
|
||||
addToTailscaleAcl: true # Automatically added to Tailscle's ACL
|
||||
```
|
||||
:::
|
||||
|
||||
Olares will expose the ports you specify for an application, which are accessible via the application domain name in the local network, for example: `84864c1f.your_olares_id.olares.com:46879`. For each port you expose, Olares configures both TCP and UDP with the same port number.
|
||||
|
||||
When the `addToTailscaleAcl` field is set to `true`, the port will be automatically added to the Tailscale's ACL, and there is no need to configure in the tailscale section.
|
||||
|
||||
:::info NOTE
|
||||
The exposed ports can only be accessed on the local network or through a VPN.
|
||||
:::
|
||||
|
||||
## Permission
|
||||
|
||||
:::info Example
|
||||
```Yaml
|
||||
permission:
|
||||
appCache: true
|
||||
appData: true
|
||||
userData:
|
||||
- /Home/
|
||||
sysData:
|
||||
- dataType: legacy_prowlarr
|
||||
appName: prowlarr
|
||||
port: 9696
|
||||
group: api.prowlarr
|
||||
version: v2
|
||||
ops:
|
||||
- All
|
||||
```
|
||||
:::
|
||||
|
||||
### appCache
|
||||
|
||||
- Type: `boolean`
|
||||
- Optional
|
||||
|
||||
Whether the app requires read and write permission to the `Cache` folder. If `.Values.userspace.appCache` is used in the deployment YAML, then `appCache` must be set to `true`.
|
||||
|
||||
### appData
|
||||
|
||||
- Type: `boolean`
|
||||
- Optional
|
||||
|
||||
Whether the app requires read and write permission to the `Data` folder. If `.Values.userspace.appData` is used in the deployment YAML, then `appData` must be set to `true`.
|
||||
|
||||
### userData
|
||||
|
||||
- Type: `list<string>`
|
||||
- Optional
|
||||
|
||||
Whether the app requires read and write permission to user's `Home` folder. List all directories that the application needs to access under the user's `Home`. All `userData` directory configured in the deployment YAML, must be included here.
|
||||
|
||||
### sysData
|
||||
|
||||
- Type: `list<map>`
|
||||
- Optional
|
||||
|
||||
Declare the list of APIs that this app needs to access.
|
||||
|
||||
:::info Example
|
||||
```Yaml
|
||||
sysData:
|
||||
- group: service.bfl
|
||||
dataType: app
|
||||
version: v1
|
||||
ops:
|
||||
- InstallDevApp
|
||||
- dataType: legacy_prowlarr
|
||||
appName: prowlarr
|
||||
port: 9696
|
||||
group: api.prowlarr
|
||||
version: v2
|
||||
ops:
|
||||
- All
|
||||
```
|
||||
:::
|
||||
|
||||
All system API [providers](../advanced/provider.md) are list below:
|
||||
| Group | version | dataType | ops |
|
||||
| ----------- | ----------- | ----------- | ----------- |
|
||||
| service.appstore | v1 | app | InstallDevApp, UninstallDevApp
|
||||
| message-dispatcher.system-server | v1 | event | Create, List
|
||||
| service.desktop | v1 | ai_message | AIMessage
|
||||
| service.did | v1 | did | ResolveByDID, ResolveByName, Verify
|
||||
| api.intent | v1 | legacy_api | POST
|
||||
| service.intent | v1 | intent | RegisterIntentFilter, UnregisterIntentFilter, SendIntent, QueryIntent, ListDefaultChoice, CreateDefaultChoice, RemoveDefaultChoice, ReplaceDefaultChoice
|
||||
| service.message | v1 | message | GetContactLogs, GetMessages, Message
|
||||
| service.notification | v1 | message | Create
|
||||
| service.notification | v1 | token | Create
|
||||
| service.search | v1 | search | Input, Delete, InputRSS, DeleteRSS, QueryRSS, QuestionAI
|
||||
| secret.infisical | v1 | secret | CreateSecret, RetrieveSecret
|
||||
| secret.vault | v1 | key | List, Info, Sign
|
||||
|
||||
## Tailscale
|
||||
- Type: `map`
|
||||
- Optional
|
||||
|
||||
Allow applications to add Access Control Lists (ACL) in Tailscale to open specified ports.
|
||||
|
||||
:::info Example
|
||||
```Yaml
|
||||
tailscale:
|
||||
acls:
|
||||
- proto: tcp
|
||||
dst:
|
||||
- "*:46879"
|
||||
- proto: "" # Optional. If not specified, all supported protocols will be allowed.
|
||||
dst:
|
||||
- "*:4557"
|
||||
```
|
||||
:::
|
||||
|
||||
## Spec
|
||||
Additional information about the application, primarily used for display in the Olares Market.
|
||||
|
||||
:::info Example
|
||||
```Yaml
|
||||
spec:
|
||||
namespace: os-system
|
||||
# optional. Install the app to a specified namespace, e.g. os-system, user-space, user-system
|
||||
|
||||
versionName: '10.8.11'
|
||||
# The version of the application that this chart contains. It is recommended to enclose the version number in quotes. This value corresponds to the appVersion field in the `Chart.yaml` file. Note that it is not related to the `version` field.
|
||||
|
||||
featuredImage: https://file.bttcdn.com/appstore/jellyfin/promote_image_1.jpg
|
||||
# The featured image is displayed when the app is featured in the Market.
|
||||
|
||||
promoteImage:
|
||||
- https://file.bttcdn.com/appstore/jellyfin/promote_image_1.jpg
|
||||
- https://file.bttcdn.com/appstore/jellyfin/promote_image_2.jpg
|
||||
- https://file.bttcdn.com/appstore/jellyfin/promote_image_3.jpg
|
||||
fullDescription: |
|
||||
Jellyfin is the volunteer-built media solution that puts you in control of your media. Stream to any device from your own server, with no strings attached. Your media, your server, your way.
|
||||
upgradeDescription: |
|
||||
upgrade descriptions
|
||||
developer: Jellyfin
|
||||
website: https://jellyfin.org/
|
||||
doc: https://jellyfin.org/docs/
|
||||
sourceCode: https://github.com/jellyfin/jellyfin
|
||||
submitter: Olares
|
||||
locale:
|
||||
- en-US
|
||||
- zh-CN
|
||||
# List languages and regions supported by this app
|
||||
|
||||
requiredMemory: 256Mi
|
||||
requiredDisk: 128Mi
|
||||
requiredCpu: 0.5
|
||||
# Specifies the minimum resources required to install and run the application. Once the app is installed, the system will reserve these resources to ensure optimal performance.
|
||||
|
||||
limitedDisk: 256Mi
|
||||
limitedCpu: 1
|
||||
limitedMemory: 512Mi
|
||||
# Specifies the maximum resource limits for the application. If the app exceeds these limits, it will be temporarily suspended to prevent system overload and ensure stability.
|
||||
|
||||
legal:
|
||||
- text: Community Standards
|
||||
url: https://jellyfin.org/docs/general/community-standards/
|
||||
- text: Security policy
|
||||
url: https://github.com/jellyfin/jellyfin/security/policy
|
||||
license:
|
||||
- text: GPL-2.0
|
||||
url: https://github.com/jellyfin/jellyfin/blob/master/LICENSE
|
||||
supportClient:
|
||||
- android: https://play.google.com/store/apps/details?id=org.jellyfin.mobile
|
||||
- ios: https://apps.apple.com/us/app/jellyfin-mobile/id1480192618
|
||||
```
|
||||
:::
|
||||
|
||||
### i18n
|
||||
|
||||
To add multi-language support for your app in Olares Market:
|
||||
|
||||
1. Create an `i18n` folder in the Olares Application Chart root directory.
|
||||
2. In the `i18n` folder, create separate subdirectories for each supported locale.
|
||||
3. In each locale subdirectory, place a localized version of the `OlaresManifest.yaml` file.
|
||||
|
||||
Olares Market will automatically display the content of the corresponding "OlaresManifest.yaml" file based on users' locale settings.
|
||||
:::info Example
|
||||
```
|
||||
.
|
||||
├── Chart.yaml
|
||||
├── README.md
|
||||
├── OlaresManifest.yaml
|
||||
├── i18n
|
||||
│ ├── en-US
|
||||
│ │ └── OlaresManifest.yaml
|
||||
│ └── zh-CN
|
||||
│ └── OlaresManifest.yaml
|
||||
├── owners
|
||||
├── templates
|
||||
│ └── deployment.yaml
|
||||
└── values.yaml
|
||||
```
|
||||
:::
|
||||
Currently, you can add i18n content for the following fields:
|
||||
```Yaml
|
||||
metadata:
|
||||
description:
|
||||
title:
|
||||
spec:
|
||||
fullDescription:
|
||||
upgradeDescription:
|
||||
```
|
||||
|
||||
### supportArch
|
||||
- Type: `list<string>`
|
||||
- Accepted Value: `amd64`, `arm64`
|
||||
- Optional
|
||||
|
||||
Specifies the CPU architecture supported by the application. Currently only `amd64` and `arm64` are available.
|
||||
|
||||
:::info Example
|
||||
```yaml
|
||||
spec:
|
||||
supportArch:
|
||||
- amd64
|
||||
- arm64
|
||||
```
|
||||
:::
|
||||
|
||||
:::info NOTE
|
||||
Olares does not support mixed-architecture clusters for now.
|
||||
:::
|
||||
|
||||
### onlyAdmin
|
||||
- Type: `boolean`
|
||||
- Default: `false`
|
||||
- Optional
|
||||
|
||||
When set to `true`, only the admin can install this app.
|
||||
|
||||
### runAsUser
|
||||
- Type: `boolean`
|
||||
- Optional
|
||||
|
||||
When set to `true`, Olares forces the application to run under user ID `1000` (as a non-root user).
|
||||
|
||||
## Middleware
|
||||
- Type: `map`
|
||||
- Optional
|
||||
|
||||
The Olares provides highly available middleware services. Developers do not need to install middleware repeatedly. Just simply add required middleware here, You can then directly use the corresponding middleware information in the application's deployment YAML file.
|
||||
|
||||
Use the `scripts` field to specify scripts that should be executed after the database is created. Additionally, use the `extension` field to add the corresponding extension in the database.
|
||||
|
||||
:::info Example
|
||||
```Yaml
|
||||
middleware:
|
||||
postgres:
|
||||
username: immich
|
||||
databases:
|
||||
- name: immich
|
||||
extensions:
|
||||
- vectors
|
||||
- earthdistance
|
||||
scripts:
|
||||
- BEGIN;
|
||||
- ALTER DATABASE $databasename SET search_path TO "$user", public, vectors;
|
||||
- ALTER SCHEMA vectors OWNER TO $dbusername;
|
||||
- COMMIT;
|
||||
# The OS provides two variables, $databasename and $dbusername, which will be replaced by Olares Application Runtime when the command is executed.
|
||||
redis:
|
||||
password: password
|
||||
namespace: db0
|
||||
mongodb:
|
||||
username: chromium
|
||||
databases:
|
||||
- name: chromium
|
||||
script:
|
||||
- 'db.getSiblingDB("$databasename").myCollection.insertOne({ x: 111 });'
|
||||
# Please make sure each line is a complete query.
|
||||
```
|
||||
:::
|
||||
|
||||
Use the middleware information in deployment YAML
|
||||
|
||||
```yaml
|
||||
- name: DB_POSTGRESDB_DATABASE # The database name you configured in OlaresManifest, specified in middleware.postgres.databases[i].name
|
||||
value: {{ .Values.postgres.databases.<dbname> }}
|
||||
- name: DB_POSTGRESDB_HOST
|
||||
value: {{ .Values.postgres.host }}
|
||||
- name: DB_POSTGRESDB_PORT
|
||||
value: "{{ .Values.postgres.port }}"
|
||||
- name: DB_POSTGRESDB_USER
|
||||
value: {{ .Values.postgres.username }}
|
||||
- name: DB_POSTGRESDB_PASSWORD
|
||||
value: {{ .Values.postgres.password }}
|
||||
|
||||
|
||||
# For mongodb, the corresponding value is as follows
|
||||
host --> {{ .Values.mongodb.host }}
|
||||
port --> "{{ .Values.mongodb.port }}" # The port and password in the yaml file need to be enclosed in double quotes.
|
||||
username --> {{ .Values.mongodb.username }}
|
||||
password --> "{{ .Values.mongodb.password }}" # The port and password in the yaml file need to be enclosed in double quotes.
|
||||
databases --> "{{ .Values.mongodb.databases }}" # The value type of database is a map. You can get the database using {{ .Values.mongodb.databases.<dbname> }}. The <dbname> is the name you configured in OlaresManifest, specified in middleware.mongodb.databases[i].name
|
||||
|
||||
|
||||
# For Redis, the corresponding value is as follows
|
||||
host --> {{ .Values.redis.host }}
|
||||
port --> "{{ .Values.redis.port }}"
|
||||
password --> "{{ .Values.redis.password }}"
|
||||
|
||||
```
|
||||
|
||||
## Options
|
||||
|
||||
Configure system-related options here.
|
||||
|
||||
### policies
|
||||
- Type: `map`
|
||||
- Optional
|
||||
|
||||
Define detailed access control for subdomains of the app.
|
||||
|
||||
:::info Example
|
||||
```yaml
|
||||
options:
|
||||
policies:
|
||||
- uriRegex: /$
|
||||
level: two_factor
|
||||
oneTime: false
|
||||
validDuration: 3600s
|
||||
entranceName: gitlab
|
||||
```
|
||||
:::
|
||||
|
||||
### clusterScoped
|
||||
- Type: `map`
|
||||
- Optional
|
||||
|
||||
Whether this app is installed for all users in an Olares cluster.
|
||||
|
||||
:::info Example For Server
|
||||
```yaml
|
||||
metadata:
|
||||
name: gitlab
|
||||
options:
|
||||
appScope:
|
||||
clusterScoped: true
|
||||
appRef:
|
||||
- gitlabclienta #app name of clients
|
||||
- gitlabclientb
|
||||
```
|
||||
:::
|
||||
|
||||
:::info Example For Client
|
||||
```yaml
|
||||
metadata:
|
||||
name: gitlabclienta
|
||||
options:
|
||||
dependencies:
|
||||
- name: olares
|
||||
version: ">=0.3.6-0"
|
||||
type: system
|
||||
- name: gitlab #app name of server
|
||||
version: ">=0.0.1"
|
||||
type: application
|
||||
mandatory: true
|
||||
```
|
||||
:::
|
||||
|
||||
|
||||
### dependencies
|
||||
- Type: `list<map>`
|
||||
|
||||
Specify the dependencies and requirements for your application. It includes other applications that your app depends on, as well as any specific operating system (OS) version requirements.
|
||||
|
||||
If this application requires other dependent applications for proper installation, you should set the `mandatory` field to `true`.
|
||||
|
||||
:::info Example
|
||||
```yaml
|
||||
options:
|
||||
dependencies:
|
||||
- name: olares
|
||||
version: ">=1.0.0-0"
|
||||
type: system
|
||||
- name: mongodb
|
||||
version: ">=6.0.0-0"
|
||||
type: middleware
|
||||
mandatory: true # Set this field to true if the dependency needs to be installed first.
|
||||
```
|
||||
:::
|
||||
|
||||
### websocket
|
||||
- Type: `map`
|
||||
- Optional
|
||||
|
||||
Enable websocket for the app. Refer to [websocket](../advanced/websocket.md) for more information.
|
||||
|
||||
:::info Example
|
||||
```yaml
|
||||
options:
|
||||
websocket:
|
||||
url: /ws/message
|
||||
port: 8888
|
||||
```
|
||||
:::
|
||||
|
||||
### resetCookie
|
||||
- Type: `map`
|
||||
- Optional
|
||||
|
||||
If the app requires cookies, please enable this feature. Refer to [cookie](../advanced/cookie.md) for more information.
|
||||
|
||||
:::info Example
|
||||
```yaml
|
||||
options:
|
||||
resetCookie:
|
||||
enabled: true
|
||||
```
|
||||
:::
|
||||
|
||||
### upload
|
||||
- Type: `map`
|
||||
- Optional
|
||||
|
||||
The Olares Application Runtime includes a built-in file upload component designed to simplify the file upload process in your application. Refer to [upload](../advanced/file-upload.md) for more information.
|
||||
|
||||
:::info Example
|
||||
```yaml
|
||||
upload:
|
||||
# The types of files that are allowed to be uploaded, * stands for any type, The type of the uploaded file must be in the list.
|
||||
fileType:
|
||||
- pdf
|
||||
# The path of 'dest' must be a mountPath
|
||||
dest: /appdata
|
||||
# The maximum size of file, in bytes
|
||||
limitedSize: 3729747942
|
||||
```
|
||||
:::
|
||||
|
||||
### mobileSupported
|
||||
- Type: `boolean`
|
||||
- Default: `false`
|
||||
- Optional
|
||||
|
||||
Determine whether the application is compatible with mobile web browsers and can be displayed on the mobile version of Olares Desktop. Enable this option if the app is optimized for mobile web browsers. This will make the app visible and accessible on the mobile version of Olares Desktop.
|
||||
|
||||
:::info Example
|
||||
```yaml
|
||||
mobileSupported: true
|
||||
```
|
||||
:::
|
||||
|
||||
### oidc
|
||||
- Type: `map`
|
||||
- Optional
|
||||
|
||||
The Olares includes a built-in OpenID Connect authentication component to simplify identity verification of users. Enable this option to use OpenID in your app.
|
||||
```yaml
|
||||
# OpenID related variables in yaml
|
||||
{{ .Values.oidc.client.id }}
|
||||
{{ .Values.oidc.client.secret }}
|
||||
{{ .Values.oidc.issuer }}
|
||||
```
|
||||
|
||||
:::info Example
|
||||
```yaml
|
||||
oidc:
|
||||
enabled: true
|
||||
redirectUri: /path/to/uri
|
||||
entranceName: navidrome
|
||||
```
|
||||
:::
|
||||
|
||||
### apiTimeout
|
||||
- Type: `int`
|
||||
- Optional
|
||||
|
||||
Specifies the timeout limit for API providers in seconds. The default value is `15`. Use `0` to allow an unlimited API connection.
|
||||
|
||||
:::info Example
|
||||
```yaml
|
||||
apiTimeout: 0
|
||||
```
|
||||
:::
|
||||
|
||||
|
||||
|
||||
### allowedOutboundPorts
|
||||
- Type: `map`
|
||||
- Optional
|
||||
|
||||
The specified ports will be opened to allow external access via non-HTTP protocols, such as SMTP.
|
||||
|
||||
:::info Example
|
||||
```yaml
|
||||
allowedOutboundPorts:
|
||||
- 465
|
||||
- 587
|
||||
```
|
||||
:::
|
||||
320
docs/developer/develop/package/recommend.md
Normal file
320
docs/developer/develop/package/recommend.md
Normal file
@@ -0,0 +1,320 @@
|
||||
# Configuration Guideline for Recommend
|
||||
|
||||
When creating an application chart for `recommend`, you'll primarily need to configure the four files located in the `templates/` folder: `embedding.yaml`, `prerank.yaml`, `rank.yaml`, `train.yaml`.
|
||||
|
||||
|
||||
## embedding.yaml
|
||||
|
||||
::: details embedding.yaml Example
|
||||
|
||||
```Yaml
|
||||
apiVersion: argoproj.io/v1alpha1
|
||||
kind: CronWorkflow
|
||||
metadata:
|
||||
name: user-embedding-r4sport
|
||||
namespace: {{ .Release.Namespace }}
|
||||
spec:
|
||||
schedule: '0 */1 * * *'
|
||||
startingDeadlineSeconds: 0
|
||||
concurrencyPolicy: Replace
|
||||
successfulJobsHistoryLimit: 1
|
||||
failedJobsHistoryLimit: 1
|
||||
suspend: false
|
||||
ttlStrategy:
|
||||
secondsAfterSuccess: 3600
|
||||
secondsAfterCompletion: 3600
|
||||
secondsAfterFailure: 3600
|
||||
workflowSpec:
|
||||
entrypoint: userEmbeddingFlow
|
||||
volumes:
|
||||
- name: huggingface
|
||||
hostPath:
|
||||
type: DirectoryOrCreate
|
||||
path: >-
|
||||
{{ .Values.userspace.appData }}/rss/model/huggingface
|
||||
templates:
|
||||
- name: userEmbeddingFlow
|
||||
steps:
|
||||
- - name: user-embedding
|
||||
template: user-embedding-template
|
||||
- name: user-embedding-template
|
||||
container:
|
||||
image: 'beclab/r4userembedding'
|
||||
imagePullPolicy: Always
|
||||
env:
|
||||
- name: KNOWLEDGE_BASE_API_URL
|
||||
value: {{ .Values.apiUrl }}
|
||||
- name: TERMINUS_RECOMMEND_SOURCE_NAME
|
||||
value: r4sport
|
||||
volumeMounts:
|
||||
- mountPath: /root/.cache/huggingface
|
||||
name: huggingface
|
||||
```
|
||||
|
||||
:::
|
||||
|
||||
### Field Description
|
||||
|
|
||||
| Field | Description |
|
||||
| -------------------------- | ------------------------------------------------------------------------------------------ |
|
||||
| apiVersion | The API version in use. |
|
||||
| kind | Defines a CronWorkflow object. |
|
||||
| metadata.name | The name of the CronWorkflow. |
|
||||
| metadata.namespace | The namespace that the CronWorkflow belongs to. |
|
||||
| spec.schedule | Cron expression, defines the scheduling time of the CronWorkflow. |
|
||||
| spec.startingDeadlineSeconds | The start deadline of the CronWorkflow, represents the maximum delay time from the scheduled time. |
|
||||
| spec.concurrencyPolicy | Concurrency policy, specifies how to handle the currently running job when the next schedule time of the CronWorkflow arrives. |
|
||||
| spec.successfulJobsHistoryLimit | The limit of the successful job history record. |
|
||||
| spec.failedJobsHistoryLimit | The limit of the failed job history record. |
|
||||
| spec.suspend | Indicates whether to suspend the operation of the CronWorkflow. |
|
||||
| spec.ttlStrategy.secondsAfterSuccess | The time to live after the successful job is completed, in seconds. |
|
||||
| spec.ttlStrategy.secondsAfterCompletion | The time to live after the job is completed, in seconds. |
|
||||
| spec.ttlStrategy.secondsAfterFailure | The time to live after the failed job is completed, in seconds. |
|
||||
| spec.workflowSpec.entrypoint | The entry point of the Workflow. |
|
||||
| spec.workflowSpec.volumes[0].name | The definition of the volume, the name is huggingface. |
|
||||
| spec.workflowSpec.volumes[0].hostPath.type | The host machine path type, specified as a directory or create a directory. |
|
||||
| spec.workflowSpec.volumes[0].hostPath.path | The path of the host machine. |
|
||||
| spec.workflowSpec.templates[0].name | The name of the Workflow template. |
|
||||
| spec.workflowSpec.templates[0].steps[0][0].name | The definition of the step, its name. |
|
||||
| spec.workflowSpec.templates[0].steps[0][0].template | The name of the referenced template. |
|
||||
| spec.workflowSpec.templates[1].name | The name of the template. |
|
||||
| spec.workflowSpec.templates[1].container.image | The image name of the container. |
|
||||
| spec.workflowSpec.templates[1].container.imagePullPolicy | The image pull policy. |
|
||||
| spec.workflowSpec.templates[1].container.env[0].name | The definition of the environment variable, its name. |
|
||||
| spec.workflowSpec.templates[1].container.env[0].value | The value of the environment variable. |
|
||||
| spec.workflowSpec.templates[1].container.env[1].name | The definition of the environment variable, its name. |
|
||||
| spec.workflowSpec.templates[1].container.env[1].value | The value of the environment variable. |
|
||||
| spec.workflowSpec.templates[1].container.volumeMounts[0].mountPath | The definition of the mount path. |
|
||||
| spec.workflowSpec.templates[1].container.volumeMounts[0].name | The name of the mounted volume. |
|
||||
|
||||
## prerank.yaml
|
||||
|
||||
::: details prerank.yaml Example
|
||||
|
||||
```Yaml
|
||||
apiVersion: argoproj.io/v1alpha1
|
||||
kind: CronWorkflow
|
||||
metadata:
|
||||
name: prerank-r4sport
|
||||
namespace: {{ .Release.Namespace }}
|
||||
spec:
|
||||
schedule: '*/5 * * * *'
|
||||
startingDeadlineSeconds: 0
|
||||
concurrencyPolicy: Replace
|
||||
successfulJobsHistoryLimit: 1
|
||||
failedJobsHistoryLimit: 1
|
||||
suspend: false
|
||||
ttlStrategy:
|
||||
secondsAfterSuccess: 3600
|
||||
secondsAfterCompletion: 3600
|
||||
secondsAfterFailure: 3600
|
||||
workflowSpec:
|
||||
entrypoint: algorithm
|
||||
volumes:
|
||||
- name: nfs
|
||||
hostPath:
|
||||
type: DirectoryOrCreate
|
||||
path: >-
|
||||
{{ .Values.userspace.appData }}/rss/data
|
||||
- name: juicefs
|
||||
hostPath:
|
||||
type: DirectoryOrCreate
|
||||
path: >-
|
||||
{{ .Values.userspace.appData }}/rss/data
|
||||
templates:
|
||||
- name: algorithm
|
||||
steps:
|
||||
- - name: recall
|
||||
template: recall-template
|
||||
- - name: prerank
|
||||
template: prerank-template
|
||||
- name: recall-template
|
||||
container:
|
||||
image: 'beclab/r4recall:v0.0.5'
|
||||
imagePullPolicy: Always
|
||||
env:
|
||||
- name: KNOWLEDGE_BASE_API_URL
|
||||
value: {{ .Values.apiUrl }}
|
||||
- name: NFS_ROOT_DIRECTORY
|
||||
value: /nfs
|
||||
- name: JUICEFS_ROOT_DIRECTORY
|
||||
value: /juicefs
|
||||
- name: ALGORITHM_FILE_CONFIG_PATH
|
||||
value: /usr/config/
|
||||
- name: TERMINUS_RECOMMEND_SOURCE_NAME
|
||||
value: r4sport
|
||||
- name: SUPPORT_LANGUAGE
|
||||
value: en
|
||||
- name: SUPPORT_TIMELINESS
|
||||
value: '0'
|
||||
- name: SYNC_PROVIDER
|
||||
value: bytetrade
|
||||
- name: SYNC_FEED_NAME
|
||||
value: sport
|
||||
- name: SYNC_MODEL_NAME
|
||||
value: bert_v2
|
||||
volumeMounts:
|
||||
- mountPath: /nfs
|
||||
name: nfs
|
||||
- mountPath: /juicefs
|
||||
name: juicefs
|
||||
- name: prerank-template
|
||||
container:
|
||||
image: 'beclab/r4prerank:v0.0.5'
|
||||
imagePullPolicy: Always
|
||||
env:
|
||||
- name: KNOWLEDGE_BASE_API_URL
|
||||
value: {{ .Values.apiUrl }}
|
||||
- name: NFS_ROOT_DIRECTORY
|
||||
value: /nfs
|
||||
- name: JUICEFS_ROOT_DIRECTORY
|
||||
value: /juicefs
|
||||
- name: ALGORITHM_FILE_CONFIG_PATH
|
||||
value: /usr/config/
|
||||
- name: TERMINUS_RECOMMEND_SOURCE_NAME
|
||||
value: r4sport
|
||||
- name: SUPPORT_LANGUAGE
|
||||
value: en
|
||||
- name: SUPPORT_TIMELINESS
|
||||
value: '0'
|
||||
volumeMounts:
|
||||
- mountPath: /nfs
|
||||
name: nfs
|
||||
- mountPath: /juicefs
|
||||
name: juicefs
|
||||
|
||||
```
|
||||
|
||||
:::
|
||||
|
||||
|
||||
## rank.yaml
|
||||
|
||||
::: details rank.yaml Example
|
||||
|
||||
```Yaml
|
||||
apiVersion: argoproj.io/v1alpha1
|
||||
kind: CronWorkflow
|
||||
metadata:
|
||||
name: rank-r4sport
|
||||
namespace: {{ .Release.Namespace }}
|
||||
spec:
|
||||
schedule: '*/5 * * * *'
|
||||
startingDeadlineSeconds: 0
|
||||
concurrencyPolicy: Forbid
|
||||
successfulJobsHistoryLimit: 1
|
||||
failedJobsHistoryLimit: 1
|
||||
suspend: false
|
||||
ttlStrategy:
|
||||
secondsAfterSuccess: 3600
|
||||
secondsAfterCompletion: 3600
|
||||
secondsAfterFailure: 3600
|
||||
workflowSpec:
|
||||
entrypoint: rankFlow
|
||||
volumes:
|
||||
- name: model
|
||||
hostPath:
|
||||
type: DirectoryOrCreate
|
||||
path: >-
|
||||
{{ .Values.userspace.appData }}/rss/model
|
||||
templates:
|
||||
- name: rankFlow
|
||||
steps:
|
||||
- - name: extractor
|
||||
template: extractor-template
|
||||
- - name: rank
|
||||
template: rank-template
|
||||
- name: extractor-template
|
||||
container:
|
||||
image: 'beclab/r4extractor:v0.0.5'
|
||||
imagePullPolicy: Always
|
||||
env:
|
||||
- name: KNOWLEDGE_BASE_API_URL
|
||||
value: {{ .Values.apiUrl }}
|
||||
- name: TERMINUS_RECOMMEND_SOURCE_NAME
|
||||
value: r4sport
|
||||
volumeMounts:
|
||||
- mountPath: /opt/rank_model
|
||||
name: model
|
||||
- name: rank-template
|
||||
container:
|
||||
image: 'beclab/r4rank'
|
||||
imagePullPolicy: Always
|
||||
env:
|
||||
- name: KNOWLEDGE_BASE_API_URL
|
||||
value: {{ .Values.apiUrl }}
|
||||
- name: TERMINUS_RECOMMEND_SOURCE_NAME
|
||||
value: r4sport
|
||||
volumeMounts:
|
||||
- mountPath: /opt/rank_model
|
||||
name: model
|
||||
|
||||
|
||||
```
|
||||
|
||||
:::
|
||||
|
||||
|
||||
## train.yaml
|
||||
|
||||
::: details train.yaml Example
|
||||
|
||||
```Yaml
|
||||
apiVersion: argoproj.io/v1alpha1
|
||||
kind: CronWorkflow
|
||||
metadata:
|
||||
name: rank-r4sport
|
||||
namespace: {{ .Release.Namespace }}
|
||||
spec:
|
||||
schedule: '*/5 * * * *'
|
||||
startingDeadlineSeconds: 0
|
||||
concurrencyPolicy: Forbid
|
||||
successfulJobsHistoryLimit: 1
|
||||
failedJobsHistoryLimit: 1
|
||||
suspend: false
|
||||
ttlStrategy:
|
||||
secondsAfterSuccess: 3600
|
||||
secondsAfterCompletion: 3600
|
||||
secondsAfterFailure: 3600
|
||||
workflowSpec:
|
||||
entrypoint: rankFlow
|
||||
volumes:
|
||||
- name: model
|
||||
hostPath:
|
||||
type: DirectoryOrCreate
|
||||
path: >-
|
||||
{{ .Values.userspace.appData }}/rss/model
|
||||
templates:
|
||||
- name: rankFlow
|
||||
steps:
|
||||
- - name: extractor
|
||||
template: extractor-template
|
||||
- - name: rank
|
||||
template: rank-template
|
||||
- name: extractor-template
|
||||
container:
|
||||
image: 'beclab/r4extractor:v0.0.5'
|
||||
imagePullPolicy: Always
|
||||
env:
|
||||
- name: KNOWLEDGE_BASE_API_URL
|
||||
value: {{ .Values.apiUrl }}
|
||||
- name: TERMINUS_RECOMMEND_SOURCE_NAME
|
||||
value: r4sport
|
||||
volumeMounts:
|
||||
- mountPath: /opt/rank_model
|
||||
name: model
|
||||
- name: rank-template
|
||||
container:
|
||||
image: 'beclab/r4rank'
|
||||
imagePullPolicy: Always
|
||||
env:
|
||||
- name: KNOWLEDGE_BASE_API_URL
|
||||
value: {{ .Values.apiUrl }}
|
||||
- name: TERMINUS_RECOMMEND_SOURCE_NAME
|
||||
value: r4sport
|
||||
volumeMounts:
|
||||
- mountPath: /opt/rank_model
|
||||
name: model
|
||||
|
||||
```
|
||||
:::
|
||||
123
docs/developer/develop/submit/index.md
Normal file
123
docs/developer/develop/submit/index.md
Normal file
@@ -0,0 +1,123 @@
|
||||
---
|
||||
outline: [2, 3]
|
||||
---
|
||||
|
||||
# Submit Application
|
||||
|
||||
## Submitting Your Application
|
||||
|
||||
**Brief Overview**
|
||||
|
||||
1. Test your application on Olares, create the Olares Application Chart according to [guideline](../package/chart.md).
|
||||
2. Fork the official [application repository of Olares Market](https://github.com/beclab/apps). Add your application's chart. Create a **PR** to `beclab/apps:main`.
|
||||
3. Wait for **GitBot** to check your PR. If needed, modify PR until it passes.
|
||||
4. Once the PR is merged, your application is ready to launch.
|
||||
|
||||
|
||||
### 1. Develop and test your application
|
||||
|
||||
Before submitting an application, please ensure that it has been thoroughly tested on your Olares.
|
||||
- Use DevBox's dev-container to test and debug your application in a real online environment. [Learn more about DevBox](../tutorial/studio).
|
||||
- Use the [custom installation](/manual/olares/market.md#install-custom-applications) in the Market app for user testing.
|
||||
|
||||
### 2. Submit an application
|
||||
The submission of the application needs to be completed through a **Pull Request**. Here's how:
|
||||
- Fork the official [application repository of Olares Market](https://github.com/beclab/apps) and add your application's chart in your forked repository.
|
||||
- Create a `Draft PR` pointing to `beclab/apps:main`.
|
||||
- Please edit your PR title and text according to the template.
|
||||
- **PR Title** must in this format: [PR Type][FolderName][version]Title Content
|
||||
- `PR Type` includes:
|
||||
- NEW: Submit a new application
|
||||
- UPDATE: Update an already successfully merged application
|
||||
- REMOVE: Remove an already successfully merged application
|
||||
- SUSPEND: Suspend an already successfully merged application from distribution through the application store
|
||||
- `FolderName` is your Olares Application Chart name. It must adhere to the naming requirements in [chart specification](../package/chart.md).
|
||||
- `version` refers to your application chart's `Chart Version`, which needs to be consistent with the `version` field in `Chart.yaml` and metadata section of `OlaresManifest.yaml`
|
||||
- To prevent your PR from being incorrectly parsed or closed, please adhere to the following rules:
|
||||
- Your PR title must contain only one `PR Type`, `FolderName`, and `version`.
|
||||
- Your `PR Type` must be one of the predefined types.
|
||||
- A PR should only add or modify content under the `FolderName` declared in the PR title.
|
||||
- Only one Open PR or Draft PR can exist at a time with the same `FolderName`.
|
||||
- You must be one of the owners of the folder you wish to modify. Owners are listed in the `owners` file within the chart. If you're submitting a new application, your GitHub username should be included in the `owners` file.
|
||||
|
||||
- During the Draft PR phase, you can continuously adjust your PR content and add new commits. Once everything is ready, click on the **'Ready for review'** button to submit the PR and call on **GitBot** to check.
|
||||
|
||||
:::info NOTE
|
||||
The title and content of the PR are crucial for **GitBot**. Please adhere to the template specifications when filling them out. **GitBot** may automatically close any invalid PRs.
|
||||
:::
|
||||
|
||||
### 3. Track your PR status
|
||||
- When your PR is labeled with `PR type`, it indicates that your PR title is valid. Please **do not modify the `PR Type` afterwards.** If it doesn't reflect your intentions, simply close it and create a new one.
|
||||
|
||||
- You can track the progress of your PR through the status tags:
|
||||
- `waiting to submit`: your PR has an issue and requires further modification before merging.
|
||||
- `closed`: your PR is invalid or contains uncorrectable errors.
|
||||
- `waiting to merge`: Everything is progressing smoothly. Your PR has passed the check and is now awaiting auto-merge by the **GitBot**.
|
||||
- `merged`: your PR has been automatically merged into the `beclab/apps:main`.
|
||||
|
||||
- If **GitBot** automatically closes your PR, please **do not reopen** it. This implies that the PR has irreparable issues, and **GitBot** had to terminate the check process. You can submit a new PR after making necessary modifications.
|
||||
|
||||
- During the `waiting to submit` state, you can continue to submit commits to modify your application chart. **GitBot** will recheck the application chart files and update the PR status upon receiving a new commit.
|
||||
|
||||
- Once your PR passes all checks, it will be automatically merged into the `beclab/apps:main`. The application will be listed on **Olares Market** after a while.
|
||||
|
||||
- If you encounter any issues during the submission process, feel free to reach out to the Olares team or seek assistance from the community.
|
||||
|
||||
## Managing Your Application
|
||||
|
||||
You can continue managing and maintaining your application by creating a Pull Request to `beclab/apps:main`. You can upgrade your application, modify its availability, or completely remove it from the **Olares Market**.
|
||||
|
||||
The process of managing applications is similar to submission.You create a specific type of Pull Request, and GitBot takes care of the rest. Olares uses **special control files** in the root directory of application chart to manage the application's status. These **special control files** are empty files with specific suffix, such as `.suspend` and `.remove`
|
||||
|
||||
:::info NOTE
|
||||
No ".suspend" or ".remove" files should be included in the initial submission.
|
||||
:::
|
||||
|
||||
### Update
|
||||
When you need to update a published application, you need to create an `UPDATE` PR.
|
||||
|
||||
**Please note:**
|
||||
- Whenever you make changes to your application chart, such as upgrade the program, update metadata, or change owner list, be sure to upgrade your chart version.
|
||||
- The chart version in the updated application chart must be ***greater than*** the current version in the repository.
|
||||
- No `.suspend` or `.remove` files included in the root directory of updated application chart.
|
||||
- The **Olares Market** does not offer version rollback. If there are any issues with your application, you need to submit a new version to fix it.
|
||||
- To avoid potential conflicts, we recommend syncing your fork and rebase the commits of PR to the latest main branch.
|
||||
|
||||
### Suspend
|
||||
If for any reason you want to temporarily disable your application's download and installation from the **Olares Market**, submit a `SUSPEND` PR.
|
||||
|
||||
**Please note:**
|
||||
- The chart version in the submitted application chart must ***match*** the current version in the repository.
|
||||
- The root directory you submit should contain the `.suspend` file and should not contain the `.remove` file.
|
||||
- Once the suspend PR passes check and merges, the application store will stop listing your application.
|
||||
- Users who have already downloaded and installed the application can continue to use it after suspension.
|
||||
|
||||
### Remove
|
||||
If for any reason you want to remove your application from the **Olares Market**, submit a `REMOVE` PR.
|
||||
|
||||
**Please note:**
|
||||
- Completely empty the files in the current application directory and add a `.remove` file to the root directory.
|
||||
- Once the remove PR passes check and merges, the application store will remove your application.
|
||||
- You will not be able to reuse the same directory or application chart name in the future.
|
||||
- Users who have already downloaded and installed the application can continue to use it after removal.
|
||||
|
||||
## Promoting Your Application
|
||||
|
||||
Utilizing well-organized application descriptions, screenshots, and promotional images to highlight the features and functions of your application can help attract new users in the Market. Screenshots and previews can intuitively demonstrate the user experience, helping your application stand out.
|
||||
|
||||
To add promotional images on the application detail page, include links to these assets in the `promoteImage` fields within the `spec` section of the `OlaresManifest.yaml` file.
|
||||
|
||||
:::info **Assets Specifications for the Olares Market**
|
||||
|
||||
- The application's **icon** must be in PNG or WEBP format, up to 512 KB, with a size of 256x256 px.
|
||||
|
||||
- It is highly recommended to upload at least 2 **screenshots** for promotion. **Screenshots** must be in JPEG, PNG, or WEBP format, up to 8MB each, with a size of 1440x900 px. You can upload up to 8 **screenshots**.
|
||||
|
||||
- If you wish to have your application featured in the store, a **featured image** is required. Add a link to this image in the `featuredImage` field within the `spec` section of the `OlaresManifest.yaml` file. The image must be in JPEG, PNG, or WEBP format, up to 8MB, with a size of 1440x900 px
|
||||
:::
|
||||
|
||||
## Inviting Others to Collaborate
|
||||
|
||||
There are two ways to invite others to develop Olares applications together:
|
||||
1. Add others developer's GitHub usernames to the `owners` file. Each developer listed in `owners` can then fork the repository and submit their changes independently.
|
||||
2. Add others as collaborators to your forked repository. In this case, you create the Pull Request as a representative, and all others can jointly commit to the branch that is planned to merge.
|
||||
15
docs/developer/develop/tutorial/index.md
Normal file
15
docs/developer/develop/tutorial/index.md
Normal file
@@ -0,0 +1,15 @@
|
||||
# Tutorial
|
||||
|
||||
Welcome to the Olares developer guides. These detailed tutorials offer a step-by-step guide on building an Olares Application from scratch.
|
||||
|
||||
To get started, you can learn some basic concepts of Olares, such as:
|
||||
- [Olares architectural components](../../../manual/concepts/architecture.md)
|
||||
- [Olares Application Chart](../../develop/package/chart.md)
|
||||
- [Olares Extension on Helm](../package/extension.md)
|
||||
|
||||
These fundamentals will help you grasp our development process more effectively.
|
||||
|
||||
You can also [learn about DevBox](studio.md), a built-in app that Olares provides for developers to build Olares applications.
|
||||
|
||||
If you're brand new to Olares development and want to jump straight into coding, start with the [**Create your first Olares app**](./note/index.md). This tutorial will step you through the process of building a small note application.
|
||||
|
||||
71
docs/developer/develop/tutorial/note/backend.md
Normal file
71
docs/developer/develop/tutorial/note/backend.md
Normal file
@@ -0,0 +1,71 @@
|
||||
# Develop Backend Program
|
||||
|
||||
## Clone Code
|
||||
|
||||
Open the IDE of backend Dev Container, open Terminal, clone your code to the `/Code` directory
|
||||
|
||||
```sh
|
||||
gh auth login
|
||||
|
||||
cd /Code
|
||||
git clone https://github.com/beclab/terminus-app-demo.git
|
||||
```
|
||||
|
||||
You can then open the backend code in the IDE for development.
|
||||
|
||||

|
||||
|
||||
## Connect Database
|
||||
|
||||
In the Dev Container, you can access database details through environment variables. You can do this by adding the database parameters into the container using environment variables when you deploy it.
|
||||
|
||||
Take `gorm` as an example:
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"strconv"
|
||||
|
||||
"gorm.io/driver/postgres"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
|
||||
func init() {
|
||||
var err error
|
||||
|
||||
db_host = os.Getenv("DB_HOST")
|
||||
db_port, err = strconv.Atoi(os.Getenv("DB_PORT"))
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
db_username = os.Getenv("DB_USER")
|
||||
db_password = os.Getenv("DB_PWD")
|
||||
db_name = os.Getenv("DB_NAME")
|
||||
}
|
||||
|
||||
|
||||
func main(){
|
||||
dsn := fmt.Sprintf("host=%s user=%s password=%s dbname=%s port=%d sslmode=disable TimeZone=Asia/Shanghai",
|
||||
db_host, db_username, db_password, db_name, db_port)
|
||||
db, err := gorm.Open(postgres.Open(dsn), &gorm.Config{})
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
}
|
||||
```
|
||||
|
||||
## Debug
|
||||
|
||||
After completing the development, you can run and debug your code in the IDE.
|
||||
|
||||

|
||||
|
||||
You can also run your code in the Terminal, for example:
|
||||
|
||||
```sh
|
||||
go run main.go
|
||||
```
|
||||
|
||||
Now, you can debug your interface with your front-end program.
|
||||
201
docs/developer/develop/tutorial/note/create.md
Normal file
201
docs/developer/develop/tutorial/note/create.md
Normal file
@@ -0,0 +1,201 @@
|
||||
---
|
||||
outline: [2, 3]
|
||||
---
|
||||
|
||||
# How to Start Developing an Application
|
||||
|
||||
## Install and Launch DevBox
|
||||
|
||||
1. Install [DevBox](https://market.olares.com/app/devbox) from the Olares Market.
|
||||
2. Find the DevBox icon in the launcher panel on the Olares Desktop.
|
||||
3. Click on the icon to launch the application.
|
||||
|
||||

|
||||
|
||||
## Create Your App
|
||||
|
||||
Click the **Create a new application** to create a blank Olares application from a template.
|
||||
|
||||
- In the **App Name** field, enter your application name.
|
||||
- Set the **APP type** to **app**.
|
||||
- Change the **Main Entrance Port** for your APP entrance.
|
||||
- In the **Image** field, input the image name and tag from your image repository where your app image will be stored.
|
||||
|
||||

|
||||
|
||||
## Setup App Config
|
||||
|
||||
After creating the application, you can see the Olares Application Chart files generated by DevBox under the **Files** Tab. You can add, delete, or rename various configuration files as needed.
|
||||
|
||||

|
||||
|
||||
### Chart.yaml
|
||||
|
||||
The `Chart.yaml` file is a required file in the Helm Chart specification. It contains the application's `Name` and `Chart Version`. You can [learn more here](https://helm.sh/docs/topics/charts/). For now, we're not going to change the default `Chart.yaml` yet.
|
||||
|
||||
### OlaresManifest.yaml
|
||||
|
||||
In the `OlaresManifest.yaml `file, you can change many configurations. This includes but is not limited to:
|
||||
|
||||
- Changing the app's title, icon, and other details
|
||||
- Adding system `middleware`
|
||||
- Getting `permissions` for system directory access
|
||||
- Changing the `required and limited resource` of the app
|
||||
|
||||
#### Adding a [cluster database middleware](../../package/manifest.md#middleware)
|
||||
|
||||

|
||||
|
||||
In this example, we will configure a PostgreSQL database. Add the following content to the configuration file:
|
||||
|
||||
```Yaml
|
||||
middleware:
|
||||
postgres:
|
||||
username: postgres
|
||||
databases:
|
||||
- name: db
|
||||
distributed: false
|
||||
```
|
||||
|
||||
You can specify your database `username` and `password` in the configuration. Alternatively, you can leave these fields empty and use the system-generated random password instead. You need to set the database `name` required by your APP. In addition, you can also choose to apply for a `distributed database`. If so, the system will create a [citus](https://github.com/citusdata/citus) database for you.
|
||||
|
||||
After completing the configuration, you can reference the corresponding database configuration in your `deployment.yaml`. For example, reference in the environment variables of the container.
|
||||
|
||||
```yaml
|
||||
- env:
|
||||
- name: DB_PORT
|
||||
value: "{{ .Values.postgres.port }}"
|
||||
- name: DB_NAME
|
||||
value: "{{ .Values.postgres.databases.demo }}"
|
||||
- name: DB_USER
|
||||
value: "{{ .Values.postgres.username }}"
|
||||
- name: DB_HOST
|
||||
value: "{{ .Values.postgres.host }}"
|
||||
- name: DB_PWD
|
||||
value: "{{ .Values.postgres.password }}"
|
||||
```
|
||||
|
||||
- `.Values.postgres.username`: the `username` of PostgreSQL in configuration.
|
||||
- `.Values.postgres.databases.demo`: the `database name` in configuration.
|
||||
- `.Values.postgres.password`: the `password` in configuration.
|
||||
- `.Values.postgres.host`: the database service address specified by the system for the APP.
|
||||
- `.Values.postgres.port`: the database service port specified by the system for the APP.
|
||||
|
||||
::: warning
|
||||
These parameters should not be hardcoded, they must reference the variables passed in by the system, and the system will randomize the database information in the configuration.
|
||||
:::
|
||||
|
||||
#### Adding [Access Permissions to the File System](../../package/manifest.md#permission)
|
||||
|
||||
To read and save files in the Olares system, we need to configure Access Permissions for certain file directories. These directories can be specified in the `Permissions` section of the `OlaresManifest.yaml` file:
|
||||
|
||||
- `appData`: This applies for independent cloud storage space for the app.
|
||||
- `appCache`: This applies for local disk data cache space, usually on an SSD disk, for the app.
|
||||
- `userData`: This applies for access permission to the user's data directory. List the directories you need to access here.
|
||||
|
||||
After completing the above configuration, you can reference these configurations in your deployment
|
||||
|
||||
```yaml
|
||||
volumes:
|
||||
- hostPath:
|
||||
path: "{{ .Values.userspace.appCache }}/demo"
|
||||
type: DirectoryOrCreate
|
||||
name: appcache
|
||||
- hostPath:
|
||||
path: "{{ .Values.userspace.appData }}/demo"
|
||||
type: DirectoryOrCreate
|
||||
name: appdata
|
||||
```
|
||||
|
||||
- `.Values.userspace.appCache` is the `appCache` directory
|
||||
- `.Values.userspace.appData` is the `appData` directory
|
||||
- `.Values.userspace.userData` is the `userData` directory
|
||||
|
||||
### deployment.yaml
|
||||
|
||||
The `deployment.yaml` in the `templates` folder details the deployment configuration of your application.
|
||||
|
||||
If your app includes several containers, such as front-end and back-end, you can add multiple containers in the `deployment.yaml` file in the `templates`. DevBox will recognize these different containers and bind each of them separately to different development containers. For example:
|
||||
|
||||
```yaml
|
||||
containers:
|
||||
# front-end container
|
||||
- env:
|
||||
- name: PGID
|
||||
value: "1000"
|
||||
- name: PUID
|
||||
value: "1000"
|
||||
- name: TZ
|
||||
value: Etc/UTC
|
||||
image: bytetrade/demo-app:0.0.1
|
||||
name: demo
|
||||
ports:
|
||||
- containerPort: 8080
|
||||
resources:
|
||||
limits:
|
||||
cpu: "1"
|
||||
memory: 2000Mi
|
||||
requests:
|
||||
cpu: 50m
|
||||
memory: 1000Mi
|
||||
volumeMounts:
|
||||
- mountPath: /appcache
|
||||
name: appcache
|
||||
|
||||
# Server container
|
||||
- env:
|
||||
- name: DB_PORT
|
||||
value: "{{ .Values.postgres.port }}"
|
||||
- name: DB_NAME
|
||||
value: "{{ .Values.postgres.databases.demo }}"
|
||||
- name: DB_USER
|
||||
value: "{{ .Values.postgres.username }}"
|
||||
- name: DB_HOST
|
||||
value: "{{ .Values.postgres.host }}"
|
||||
- name: DB_PWD
|
||||
value: "{{ .Values.postgres.password }}"
|
||||
- name: PGID
|
||||
value: "1000"
|
||||
- name: PUID
|
||||
value: "1000"
|
||||
- name: TZ
|
||||
value: Etc/UTC
|
||||
image: bytetrade/demo-server:0.0.1
|
||||
name: server
|
||||
ports:
|
||||
- containerPort: 9000
|
||||
resources:
|
||||
limits:
|
||||
cpu: "1"
|
||||
memory: 1000Mi
|
||||
requests:
|
||||
cpu: 50m
|
||||
memory: 500Mi
|
||||
volumeMounts:
|
||||
- mountPath: /appcache
|
||||
name: appcache
|
||||
- mountPath: /appdata
|
||||
name: appdata
|
||||
```
|
||||
|
||||
## Bind Container
|
||||
|
||||
After configuring the above details, navigate to the **Containers** page to bind the development container(**Dev Container**) for this app. Once done, you can start coding.
|
||||
|
||||

|
||||
|
||||
You can set a specified development environment for the bound **Dev Container**. Currently, DevBox supports `NodeJS`, `Golang`, and `Python` **Dev Container**. Let's bind a `NodeJS` **Dev Container** to the demo frontend container and a `Golang` **Dev Container** to the server container.
|
||||
|
||||
We create a new **Dev Container** here. If you have previously created an unbound **Dev Container**, you can also choose an existing container for binding here.
|
||||
|
||||

|
||||
|
||||
## Install App
|
||||
|
||||
After binding the **Dev Container**, click **Install** in the upper right corner to install the development app into the system. Once the installation status shifts from `Processing` to `Running`, it indicates that the app is installed and ready for coding.
|
||||
|
||||

|
||||
|
||||
Then, navigate back to the **Containers** page. You'll notice that the **Open IDE button** is now enabled. Press this button to access the **Dev Container** and begin coding in the actual environment.
|
||||
|
||||

|
||||
74
docs/developer/develop/tutorial/note/frontend.md
Normal file
74
docs/developer/develop/tutorial/note/frontend.md
Normal file
@@ -0,0 +1,74 @@
|
||||
# Develop Frontend Program
|
||||
|
||||
## Preview App
|
||||
After installing the app, you can preview the frontend of your application using the **Preview** button in **DevBox**.
|
||||
|
||||

|
||||
|
||||
## Open IDE
|
||||
|
||||
When you open the frontend **Dev Contain IDE, you'll see the welcome page. From this point, the steps are like those for [backend development](backend.md). You can clone your frontend code using the Terminal.
|
||||
|
||||
::: tip
|
||||
In this example, the frontend and backend use the same code directory. So, after you've cloned the code for the backend, you don't need to do it again.
|
||||
:::
|
||||
|
||||
After cloning the code, if you are working on a Node project, you might need to make some configuration changes.
|
||||
|
||||
- **Vite Configuration Changes**
|
||||
|
||||
If your frontend project uses **Vite**, you need to add an **HMR** configuration. In development mode, **Vite** initiates a **WebSocket** to receive code reload notifications from the server. The default **WebSocket** port matches the server's startup port. However, if the development app uses an **Nginx proxy** it will operate on the default port 443. Therefore, some modifications are required.
|
||||
|
||||
Modify the `vite.config.js` file as follows:
|
||||
```js
|
||||
export default defineConfig({
|
||||
server: {
|
||||
hmr: {
|
||||
clientPort: 443,
|
||||
},
|
||||
},
|
||||
});
|
||||
```
|
||||
- **Nginx Configuration Changes**
|
||||
|
||||
After setting up your project's development environment, you need to modify the Nginx configuration. Open `/etc/nginx/conf.d/dev/dev.conf` and make the necessary changes:
|
||||
```nginx
|
||||
location / {
|
||||
proxy_pass http://127.0.0.1:9000;
|
||||
proxy_set_header Host $http_host;
|
||||
proxy_set_header X-real-ip $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Upgrade $http_upgrade;
|
||||
proxy_set_header Connection $http_connection;
|
||||
proxy_set_header Accept-Encoding gzip;
|
||||
}
|
||||
```
|
||||
|
||||
Then, reload Nginx:
|
||||
```sh
|
||||
nginx -s reload
|
||||
```
|
||||
## Run Dev Mode
|
||||
After completing the **Nginx** configuration, you can start your frontend program in dev mode and preview your APP in Olares.
|
||||
|
||||
```sh
|
||||
npm run dev
|
||||
```
|
||||
|
||||

|
||||
|
||||
If you need to set up a backend api proxy for the frontend, you can modify the proxy configuration in **Nginx**.
|
||||
|
||||
```nginx
|
||||
location /api/ {
|
||||
proxy_pass http://127.0.0.1:9001;
|
||||
proxy_set_header Host $http_host;
|
||||
proxy_set_header X-real-ip $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Upgrade $http_upgrade;
|
||||
proxy_set_header Connection $http_connection;
|
||||
proxy_set_header Accept-Encoding gzip;
|
||||
}
|
||||
```
|
||||
16
docs/developer/develop/tutorial/note/index.md
Normal file
16
docs/developer/develop/tutorial/note/index.md
Normal file
@@ -0,0 +1,16 @@
|
||||
# Create Your First Olares App
|
||||
|
||||
You can learn how to develop an Olares app using DevBox through this tutorial.
|
||||
|
||||
The tutorial shows how to make a simple [Note](https://github.com/beclab/olares-app-demo) tool. It demonstrates how to start from scratch and develop a complete Olares App.
|
||||
|
||||
The tutorial includes three parts:
|
||||
|
||||
1. [Create an App](./create.md)<br>
|
||||
This section provides a step-by-step guide on how to create an Olares App and set up the initial development environment.
|
||||
|
||||
2. [Backend Development](./backend.md)<br>
|
||||
In this section, you'll learn how to use DevBox's IDE to develop the backend programs in `Golang` and provide API interfaces for the frontend.
|
||||
|
||||
3. [Frontend Development](./frontend.md)<br>
|
||||
In this section, you'll learn how to use DevBox's IDE to develop frontend pages, using `NodeJS` as an example.
|
||||
13
docs/developer/develop/tutorial/studio.md
Normal file
13
docs/developer/develop/tutorial/studio.md
Normal file
@@ -0,0 +1,13 @@
|
||||
# Learn about DevBox
|
||||
|
||||
At Olares, we provide a development tool called DevBox. It helps developers create applications for **Olares**.
|
||||
|
||||
- Why is DevBox necessary for developers?
|
||||
|
||||
Olares has many cloud-based features that are difficult to simulate in a standalone development environment. Furthermore, the unique sandbox system of **Olares** requires a real system environment for end-to-end testing. To simplify app simulation for developers and minimize system integration efforts during development, we provide the **DevBox**. **DevBox** is a quick, automatic toolset for creating app sandboxes.
|
||||
|
||||
- What features does DevBox have?
|
||||
|
||||
- In DevBox, you can build an app and generate a corresponding Olares Application Configuration* This deployment files can be modified, allowing you to port an existing app and deploy it to the Olares. During the modification process, you can continually attempt installation and resolve any issues that arise. Once the app passes your tests, you can download your Application Chart and submit it to the [Olares Market Repository](https://github.com/beclab/apps).
|
||||
|
||||
- In addition to porting existing apps, you can also create a native Olares application in DevBox. DevBox provides an online development container where coders can work in a real environment, utilize other system interfaces, database clusters, and more.
|
||||
38
docs/developer/install/activate-olares.md
Normal file
38
docs/developer/install/activate-olares.md
Normal file
@@ -0,0 +1,38 @@
|
||||
---
|
||||
search: false
|
||||
---
|
||||
## Activate Olares
|
||||
|
||||
Use the Wizard URL and initial one-time password to activate. This process connects the Olares device with your Olares ID using LarePass.
|
||||
|
||||
1. Enter the Wizard URL in your browser. You will be directed to the welcome page. Press any key to continue.
|
||||
|
||||

|
||||
2. Enter the one-time password and click **Continue**.
|
||||
|
||||

|
||||
3. Select the system language.
|
||||
|
||||

|
||||
4. Activate Olares using LarePass app.
|
||||
|
||||
a. Open LarePass app, and tap **Scan QR code** to scan the QR code on the Wizard page and complete the activation.
|
||||
:::warning Same network required
|
||||
To avoid activation failures, ensure that both your phone and the Olares device are connected to the same network.
|
||||
:::
|
||||
|
||||

|
||||
|
||||
b. Reset the login password for Olares by following the on-screen instructions on LarePass.
|
||||
|
||||
::: tip Reactivate Olares with the same Olares ID
|
||||
|
||||
If you have reinstalled Olares, the original instance becomes unavailable. To reactivate Olares with the same Olares ID:
|
||||
|
||||
1. Open LarePass on your phone, and you can see a red prompt: "No active Olares found".
|
||||
2. Tap **Learn more**, then **Reactivate** to enter the QR scan page.
|
||||
3. Tap **Scan QR code** to scan the QR code on the wizard page and activate Olares.
|
||||
:::
|
||||
|
||||
|
||||
After successful setup, the LarePass app will automatically go to the home screen, and the Wizard will redirect you to the login page.
|
||||
21
docs/developer/install/additional-installations.md
Normal file
21
docs/developer/install/additional-installations.md
Normal file
@@ -0,0 +1,21 @@
|
||||
---
|
||||
description: Installation guide for running Olares in containerized or virtual environments on macOS, Windows, PVE, Raspberry Pi, and more. Intended for development and testing only, not for production use.
|
||||
---
|
||||
|
||||
# Additional installation options
|
||||
|
||||
Additional installation options in this section are intended for **development or testing on special containerized or virtual environments** including Linux, macOS, Windows, PVE, or Raspberry Pi.
|
||||
|
||||
:::tip Recommendation for production environment
|
||||
Olares is optimized for Linux systems (Ubuntu or Debian). We recommend [installing Olares on Linux using script](../../manual/get-started/install-olares.md) to get the best performance and reliability for production use.
|
||||
:::
|
||||
|
||||
To run Olares, you must [create an Olares ID](../../manual/get-started/create-olares-id.md), and ensure that both the operating system and hardware meet the minimum requirements.
|
||||
|
||||
Choose your preferred option to get started:
|
||||
- [Install on Linx using Docker](linux-via-docker-compose.md)
|
||||
- [Install on macOS](/developer/install/mac)
|
||||
- [Install on Windows (WSL 2)](/developer/install/windows)
|
||||
- [Install on PVE](/developer/install/pve)
|
||||
- [Install on LXC](/developer/install/lxc)
|
||||
- [Install on Raspberry Pi](/developer/install/raspberry-pi)
|
||||
84
docs/developer/install/cli/backups-backup.md
Normal file
84
docs/developer/install/cli/backups-backup.md
Normal file
@@ -0,0 +1,84 @@
|
||||
---
|
||||
outline: [2, 3]
|
||||
---
|
||||
# `backup`
|
||||
:::warning
|
||||
The `olares-cli backups download` command must be run first to install Restic. Otherwise, this command will return an error.
|
||||
:::
|
||||
## Synopsis
|
||||
The `backup` subcommand allows you to back up data to the specified storage backend. It ensures your data is securely stored and can be restored whenever needed.
|
||||
|
||||
```bash
|
||||
olares-cli backups backup <backend> --path <path> --repo-name <name> [options]
|
||||
```
|
||||
|
||||
## Common options
|
||||
These options apply to all backends:
|
||||
|
||||
| Option | Shorthand | Usage | Required | Default |
|
||||
|---------------|-----------|----------------------------------------------|-------------------------|---------|
|
||||
| `--help` | `-h` | Displays help information. | No | N/A |
|
||||
| `--path` | | Specifies the directory to back up. | No | N/A |
|
||||
| `--repo-name` | | Specifies the name of the backup repository. | No | N/A |
|
||||
|
||||
## Backend-specific options
|
||||
### Options for `cos`
|
||||
|
||||
| Option | Shorthand | Usage | Required | Default |
|
||||
|-----------------------|-----------|--------------------------------------------------------------------------------------------------|-------------------------|------------|
|
||||
| `--access-key` | | Specifies the Access Key for Tencent COS. | No | N/A |
|
||||
| `--endpoint` | | Specifies the Tencent COS endpoint, e.g., `https://cos.{region}.myqcloud.com/{bucket}/{prefix}`. | No | N/A |
|
||||
| `--limit-upload-rate` | | Limits the upload speed to a maximum rate in KiB/s. | No | unlimited |
|
||||
| `--secret-access-key` | | Specifies the Secret Access Key for Tencent COS. | No | N/A | |
|
||||
|
||||
### Options for `fs`
|
||||
|
||||
| Option | Shorthand | Usage | Required | Default |
|
||||
|------------|-----------|----------------------------------------------------------------|-------------------------|---------|
|
||||
| `--endpoint` | | Specifies the local directory where the backup will be stored. | No | N/A |
|
||||
|
||||
### Options for `s3`
|
||||
|
||||
| Option | Shorthand | Usage | Required | Default |
|
||||
|-----------------------|-----------|---------------------------------------------------------------------------------------------|-------------------------|------------|
|
||||
| `--access-key` | | Specifies the Access Key for Amazon S3. | No | N/A |
|
||||
| `--endpoint` | | Specifies the Amazon S3 endpoint, e.g., `https://{bucket}.{region}.amazonaws.com/{prefix}`. | No | N/A |
|
||||
| `--limit-upload-rate` | | Limits the upload speed to a maximum rate in KiB/s. | No | unlimited |
|
||||
| `--secret-access-key` | | Specifies the Secret Access Key for Amazon S3. | No | N/A | |
|
||||
|
||||
### Options for `space`
|
||||
|
||||
| Option | Shorthand | Usage | Required | Default |
|
||||
|-------------------------------|-----------|------------------------------------------------------------------------------------------------------------------------------------------|-------------------------|------------|
|
||||
| `--access-token` <sup>1</sup> | | Specifies the access token for Olares Space. | No | N/A |
|
||||
| `--cloud-api-mirror` | | Specifies the cloud API mirror. | No | N/A |
|
||||
| `--cloud-name` | | Specifies the cloud name of the Olares Space instance. <br/> The cloud name can be retrieved using the [`region`](./backups-region.md) subcommand. | No | N/A |
|
||||
| `--cluster-id` <sup>2</sup> | | Specifies the cluster ID where the backup will be stored. | No | N/A |
|
||||
| `--limit-upload-rate` | | Limits the upload speed to a maximum rate in KiB/s. | No | unlimited |
|
||||
| `--olares-did` <sup>1</sup> | | Specifies the Olares DID. | No | N/A |
|
||||
| `--region-id` | | Specifies the region ID of the Olares Space instance. <br/> The region ID can be retrieved using the [`region`](./backups-region.md) subcommand. | No | N/A |
|
||||
|
||||
1. To retrieve the access token and Olares DID, inspect the payload of the network requests made by the Olares Space web interface after logging in. The `token` field corresponds to the access token, and the `userid` field corresponds to the Olares DID.
|
||||
|
||||
2. To retrieve the cluster ID, use the following command:
|
||||
```bash
|
||||
kubectl get terminus -o jsonpath='{.items[*].metadata.labels.bytetrade\.io/cluster-id}'
|
||||
```
|
||||
|
||||
## Example
|
||||
```bash
|
||||
# Backup to Tencent COS
|
||||
olares-cli backups backup cos --path /data --repo-name my_repo \
|
||||
--access-key YOUR_KEY \
|
||||
--secret-access-key YOUR_SECRET \
|
||||
--endpoint https://cos.region.myqcloud.com/bucket/prefix
|
||||
|
||||
# Backup to Olares Space
|
||||
olares-cli backups backup space --path /data --repo-name my_repo \
|
||||
--access-token YOUR_ACCESS_TOKEN \
|
||||
--cloud-api-mirror https://api-mirror.example.com \
|
||||
--cloud-name my_cloud \
|
||||
--region-id region_1 \
|
||||
--cluster-id cluster_12345 \
|
||||
--olares-did did:xyz123
|
||||
```
|
||||
19
docs/developer/install/cli/backups-download.md
Normal file
19
docs/developer/install/cli/backups-download.md
Normal file
@@ -0,0 +1,19 @@
|
||||
# `download`
|
||||
|
||||
## Synopsis
|
||||
The `download` subcommand downloads the Restic dependency tool. Restic is required for performing backup and restore operations, as well as managing snapshots.
|
||||
|
||||
```bash
|
||||
olares-cli backups download [options]
|
||||
```
|
||||
## Options
|
||||
|
||||
| Option | Shorthand | Usage | Required | Default |
|
||||
|--------------------|-----------|--------------------------------------------------------|-------------------------|--------------------|
|
||||
| `--download-cdn-url`| | Specifies the CDN URL for downloading the Restic tool. | No | System default URL |
|
||||
| `--help` | `-h` | Displays help information. | No | N/A |
|
||||
## Example
|
||||
```bash d
|
||||
# Download Restic using a custom CDN URL
|
||||
olares-cli backups download --download-cdn-url https://custom-cdn.example.com/restic
|
||||
```
|
||||
27
docs/developer/install/cli/backups-region.md
Normal file
27
docs/developer/install/cli/backups-region.md
Normal file
@@ -0,0 +1,27 @@
|
||||
# `region`
|
||||
|
||||
## Synopsis
|
||||
The `region` subcommand is used to retrieve the cloud name and region ID. It is specifically used when the storage backend is Olares Space.
|
||||
```bash
|
||||
olares-cli backups region space [options]
|
||||
```
|
||||
|
||||
## Options
|
||||
|
||||
| Option | Shorthand | Usage | Required | Default |
|
||||
|-------------------------------|-----------|----------------------------------------------|-------------------------|---------|
|
||||
| `--access-token` <sup>1</sup> | | Specifies the access token for Olares Space. | No | N/A |
|
||||
| `--cloud-api-mirror` | | Specifies the cloud API mirror. | No | N/A |
|
||||
| `--help` | `-h` | Displays help information. | No | N/A |
|
||||
| `--olares-did` <sup>1</sup> | | Specifies the Olares DID. | No | N/A |
|
||||
|
||||
1. To retrieve the access token and Olares DID, inspect the payload of the network requests made by the Olares Space web interface after logging in. The `token` field corresponds to the access token, and the `userid` field corresponds to the Olares DID.
|
||||
|
||||
## Example
|
||||
```bash
|
||||
# Query cloud name and region ID
|
||||
olares-cli backups region space \
|
||||
--access-token YOUR_ACCESS_TOKEN \
|
||||
--cloud-api-mirror https://api-mirror.example.com \
|
||||
--olares-did did:xyz123
|
||||
```
|
||||
84
docs/developer/install/cli/backups-restore.md
Normal file
84
docs/developer/install/cli/backups-restore.md
Normal file
@@ -0,0 +1,84 @@
|
||||
---
|
||||
outline: [2, 3]
|
||||
---
|
||||
# `restore`
|
||||
:::warning
|
||||
The `olares-cli backups download` command must be run first to install Restic. Otherwise, this command will return an error.
|
||||
:::
|
||||
## Synopsis
|
||||
The `restore` subcommand allows you to restore data from a specified backup repository and snapshot to a target directory.
|
||||
|
||||
```bash
|
||||
olares-cli backups restore <backend> --path <path> --repo-name <name> --snapshot-id <id> [options]
|
||||
```
|
||||
|
||||
## Common options
|
||||
These options apply to all backends:
|
||||
|
||||
| Option | Shorthand | Usage | Required | Default |
|
||||
|---------------|-----------|--------------------------------------------------------------|-------------------------|---------|
|
||||
| `--help` | `-h` | Displays help information. | No | N/A |
|
||||
| `--path` | | Specifies the directory to which data will be restored. | No | N/A |
|
||||
| `--repo-name` | | Specifies the name of the backup repository to restore from. | No | N/A |
|
||||
| `--snapshot-id`| | Specifies the snapshot ID to restore. | No | N/A | |
|
||||
|
||||
|
||||
## Backend-specific options
|
||||
|
||||
### Options for `cos`
|
||||
|
||||
| Option | Shorthand | Usage | Required | Default |
|
||||
|-------------------------|-----------|--------------------------------------------------------------------------------------------------|-------------------------|------------|
|
||||
| `--access-key` | | Specifies the Access Key for Tencent COS. | No | N/A |
|
||||
| `--endpoint` | | Specifies the Tencent COS endpoint, e.g., `https://cos.{region}.myqcloud.com/{bucket}/{prefix}`. | No | N/A |
|
||||
| `--limit-download-rate` | | Limits the download speed to a maximum rate in KiB/s. | No | unlimited |
|
||||
| `--secret-access-key` | | Specifies the Secret Access Key for Tencent COS. | No | N/A |
|
||||
|
||||
### Options for `fs`
|
||||
|
||||
| Option | Shorthand | Usage | Required | Default |
|
||||
|-------------|-----------|-----------------------------------------------------------|-------------------------|---------|
|
||||
| `--endpoint` | | Specifies the local directory where the backup is stored. | No | N/A |
|
||||
| `--olares-id` | | Specifies the Olares ID. | No | N/A |
|
||||
|
||||
### Options for `s3`
|
||||
|
||||
| Option | Shorthand | Usage | Required | Default |
|
||||
|-------------------------|-----------|---------------------------------------------------------------------------------------------|-------------------------|------------|
|
||||
| `--access-key` | | Specifies the Access Key for Amazon S3. | No | N/A |
|
||||
| `--endpoint` | | Specifies the Amazon S3 endpoint, e.g., `https://{bucket}.{region}.amazonaws.com/{prefix}`. | No | N/A |
|
||||
| `--limit-download-rate` | | Limits the download speed to a maximum rate in KiB/s. | No | unlimited |
|
||||
| `--secret-access-key` | | Specifies the Secret Access Key for Amazon S3. | No | N/A |
|
||||
|
||||
### Options for `space`
|
||||
|
||||
| Option | Shorthand | Usage | Required | Default |
|
||||
|-------------------------------|-----------|------------------------------------------------------------------------------------------------------------------------------------------|-------------------------|------------|
|
||||
| `--access-token` <sup>1</sup> | | Specifies the access token for Olares Space. | No | N/A |
|
||||
| `--cloud-api-mirror` | | Specifies the cloud API mirror. | No | N/A |
|
||||
| `--cloud-name` | | Specifies the cloud name of the Olares Space instance. <br/> The cloud name can be retrieved using the [`region`](./backups-region.md) subcommand. | No | N/A |
|
||||
| `--cluster-id` <sup>2</sup> | | Specifies the cluster ID where the backup will be stored. | No | N/A |
|
||||
| `--limit-download-rate` | | Limits the download speed to a maximum rate in KiB/s. | No | unlimited |
|
||||
| `--olares-did` <sup>1</sup> | | Specifies the Olares DID. | No | N/A |
|
||||
| `--region-id` | | Specifies the region ID of the Olares Space instance. <br/> The region ID can be retrieved using the [`region`](./backups-region.md) subcommand. | No | N/A |
|
||||
|
||||
1. To retrieve the access token and Olares DID, inspect the payload of the network requests made by the Olares Space web interface after logging in. The `token` field corresponds to the access token, and the `userid` field corresponds to the Olares DID.
|
||||
|
||||
2. To retrieve the cluster ID, use the following command:
|
||||
```bash
|
||||
kubectl get terminus -o jsonpath='{.items[*].metadata.labels.bytetrade\.io/cluster-id}'
|
||||
```
|
||||
|
||||
## Example
|
||||
```bash
|
||||
# Restore the data from Tencent COS
|
||||
olares-cli backups restore cos --path /data_restore --repo-name my_repo \
|
||||
--snapshot-id snapshot_12345 \
|
||||
--access-key YOUR_KEY \
|
||||
--secret-access-key YOUR_SECRET \
|
||||
--endpoint https://cos.region.myqcloud.com/bucket/prefix
|
||||
|
||||
# Restore the data from local filesystem
|
||||
olares-cli backups restore fs --path /data_restore --repo-name my_repo \
|
||||
--snapshot-id snapshot_12345 --endpoint /backup_repo
|
||||
```
|
||||
74
docs/developer/install/cli/backups-snapshots.md
Normal file
74
docs/developer/install/cli/backups-snapshots.md
Normal file
@@ -0,0 +1,74 @@
|
||||
---
|
||||
outline: [2, 3]
|
||||
---
|
||||
# `snapshots`
|
||||
:::warning
|
||||
The `olares-cli backups download` subcommand must be run first to install Restic. Otherwise, this command will return an error.
|
||||
:::
|
||||
## Synopsis
|
||||
The `snapshots` subcommand lists all available snapshots for a specific backup repository. It supports multiple storage backends and provides the necessary options to authenticate and query snapshots.
|
||||
|
||||
```bash
|
||||
olares-cli backups snapshots <backend> --repo-name <name> [options]
|
||||
```
|
||||
## Common options
|
||||
These options apply to all backends:
|
||||
|
||||
| Option | Shorthand | Usage | Required | Default |
|
||||
|---------------|-----------|-------------------------------------------------------|-------------------------|---------|
|
||||
| `--help` | `-h` | Displays help information. | No | N/A |
|
||||
| `--repo-name` | | Specifies the name of the backup repository to query. | No | N/A |
|
||||
|
||||
## Backend-specific options
|
||||
|
||||
### Options for `cos`
|
||||
|
||||
| Option | Shorthand | Usage | Required | Default |
|
||||
|---------------------|-----------|--------------------------------------------------------------------------------------------------|-------------------------|---------|
|
||||
| `--access-key` | | Specifies the Access Key for Tencent COS. | No | N/A |
|
||||
| `--endpoint` | | Specifies the Tencent COS endpoint, e.g., `https://cos.{region}.myqcloud.com/{bucket}/{prefix}`. | No | N/A |
|
||||
| `--secret-access-key` | | Specifies the Secret Access Key for Tencent COS. | No | N/A |
|
||||
|
||||
### Options for `fs`
|
||||
|
||||
| Option | Shorthand | Usage | Required | Default |
|
||||
|------------|-----------|----------------------------------------------------------------|-------------------------|---------|
|
||||
| `--endpoint` | | Specifies the local directory where the backup will be stored. | No | N/A |
|
||||
|
||||
### Options for `s3`
|
||||
|
||||
| Option | Shorthand | Usage | Required | Default |
|
||||
|---------------------|-----------|---------------------------------------------------------------------------------------------|-------------------------|---------|
|
||||
| `--access-key` | | Specifies the Access Key for Amazon S3. | No | N/A |
|
||||
| `--endpoint` | | Specifies the Amazon S3 endpoint, e.g., `https://{bucket}.{region}.amazonaws.com/{prefix}`. | No | N/A |
|
||||
| `--secret-access-key` | | Specifies the Secret Access Key for Amazon S3. | No | N/A |
|
||||
|
||||
### Options for `space`
|
||||
|
||||
| Option | Shorthand | Usage | Required | Default |
|
||||
|-------------------------------|-----------|------------------------------------------------------------------------------------------------------------------------------------------|-------------------------|---------|
|
||||
| `--access-token` <sup>1</sup> | | Specifies the access token for Olares Space. | No | N/A |
|
||||
| `--cloud-api-mirror` | | Specifies the cloud API mirror. | No | N/A |
|
||||
| `--cloud-name` | | Specifies the cloud name of the Olares Space instance. <br/> The cloud name can be retrieved using the [`region`](./backups-region.md) subcommand. | No | N/A |
|
||||
| `--cluster-id` <sup>2</sup> | | Specifies the cluster ID where the backup will be stored. | No | N/A |
|
||||
| `--olares-did` <sup>1</sup> | | Specifies the Olares DID. | No | N/A |
|
||||
| `--region-id` | | Specifies the region ID of the Olares Space instance. <br/> The region ID can be retrieved using the [`region`](./backups-region.md) subcommand. | No | N/A |
|
||||
|
||||
1. To retrieve the access token and Olares DID, inspect the payload of the network requests made by the Olares Space web interface after logging in. The `token` field corresponds to the access token, and the `userid` field corresponds to the Olares DID.
|
||||
|
||||
2. To retrieve the cluster ID, use the following command:
|
||||
```bash
|
||||
kubectl get terminus -o jsonpath='{.items[*].metadata.labels.bytetrade\.io/cluster-id}'
|
||||
```
|
||||
|
||||
## Example
|
||||
```bash
|
||||
# List snapshots for Tencent COS
|
||||
olares-cli backups snapshots cos --repo-name my_repo \
|
||||
--access-key YOUR_KEY \
|
||||
--secret-access-key YOUR_SECRET \
|
||||
--endpoint https://cos.region.myqcloud.com/bucket/prefix
|
||||
|
||||
# List snapshots for local filesystem
|
||||
olares-cli backups snapshots fs --repo-name my_repo --endpoint /backup_repo
|
||||
```
|
||||
23
docs/developer/install/cli/backups.md
Normal file
23
docs/developer/install/cli/backups.md
Normal file
@@ -0,0 +1,23 @@
|
||||
# `backups`
|
||||
The `backups` command provides a set of tools to manage data backups, restores, and snapshots. It supports multiple storage backends, including Tencent COS, Amazon S3, the local filesystem, and Olares Space.
|
||||
|
||||
## Subcommands
|
||||
|
||||
| Subcommand | Description |
|
||||
|-------------|----------------------------------------------------------------------------------------------------------|
|
||||
| `download` | Downloads the Restic dependency tool. |
|
||||
| `region` | Retrieves the cloud name and region ID. Specifically used only when the storage backend is Olares Space. |
|
||||
| `backup` | Backups data to a specified storage backend. |
|
||||
| `restore` | Restores data from a specified storage backend. |
|
||||
| `snapshots` | Manages and views backup snapshots. |
|
||||
|
||||
## Available backends
|
||||
|
||||
The `<backend>` parameter specifies the storage backend for the `backup` and `restore` commands. Olares CLI supports the following backends:
|
||||
|
||||
| Backend | Description |
|
||||
|---------|---------------------------------------------------------------------------------------|
|
||||
| `cos` | Tencent Cloud Object Storage (COS). Requires an access key, secret key, and endpoint. |
|
||||
| `s3` | Amazon Simple Storage Service (S3). Requires an access key, secret key, and endpoint. |
|
||||
| `fs` | Local filesystem. No credentials required. |
|
||||
| `space` | Olares Space. Requires an access token. |
|
||||
34
docs/developer/install/cli/change-ip.md
Normal file
34
docs/developer/install/cli/change-ip.md
Normal file
@@ -0,0 +1,34 @@
|
||||
# `change-ip`
|
||||
:::warning When manually updating IP address is required
|
||||
When Olares is deployed _inside_ a virtualized environment, such as macOS (via Minikube) or Windows (via WSL), a change in the host system's IP address (e.g., due to switching Wi-Fi networks) may cause Olares to become inaccessible. This happens because the NAT gateway and DNS configuration no longer match the new IP. In such cases, you need to manually update the IP address to ensure that Olares can route traffic correctly.
|
||||
:::
|
||||
|
||||
## Synopsis
|
||||
Change the local IP address for all Olares components.
|
||||
|
||||
```bash
|
||||
olares-cli change-ip [option]
|
||||
```
|
||||
|
||||
## Options
|
||||
|
||||
| Option | Shorthand | Usage | Required | Default |
|
||||
|---------------------|-----------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|-------------------------|--------------------------------|
|
||||
| `--base-dir` | `-b` | Sets the base directory for Olares. | No | `$HOME/.olares` |
|
||||
| `--distribution` | `-d` | Sets the WSL distribution name. Only applicable on Windows. | No | `Ubuntu` |
|
||||
| `--help` | `-h` | Displays help information. | No | N/A |
|
||||
| `--new-master-host` | | Specifies the new IP address of the master node on the worker node.<br> Only applicable for a multi-node Olares cluster. | No | N/A |
|
||||
| `--profile` | `-p` | Sets the Minikube profile name. Only applicable on macOS. | No | `olares-0` |
|
||||
| `--version` | `-v` | Specifies the Olares version. <br>Version values follow the format `x.y.z` (e.g., `1.10.0`) or include a build date (e.g., `1.10.0-20241109`).<br> Refer to the [GitHub Releases page](https://github.com/beclab/Olares/releases) for available versions. | No | Current version |
|
||||
|
||||
## Examples
|
||||
- For macOS:
|
||||
```bash
|
||||
# Specify the Minikube profile name and change the IP.
|
||||
olares-cli change-ip --profile olares-0
|
||||
```
|
||||
- For Windows WSL:
|
||||
```bash
|
||||
# Specify the Linux distribution in WSL and change the IP.
|
||||
olares-cli change-ip --distribution Ubuntu
|
||||
```
|
||||
46
docs/developer/install/cli/download.md
Normal file
46
docs/developer/install/cli/download.md
Normal file
@@ -0,0 +1,46 @@
|
||||
# `download`
|
||||
|
||||
## Synopsis
|
||||
The `download` command downloads the necessary packages and components required to install Olares on your local machine. It supports downloading components, checking the status of installation packages, and fetching the manifest file.
|
||||
|
||||
```bash
|
||||
olares-cli download <subcommand> [option]
|
||||
```
|
||||
|
||||
## Subcommands
|
||||
|
||||
| Name | Shorthand | Usage | Example |
|
||||
|-------------|-----------|-------------------------------------------------------|----------------------------------------|
|
||||
| `check` | | Checks the status of the Olares installation package. | `olares-cli download check` |
|
||||
| `component` | `c` | Downloads Olares components. | `olares-cli download component` |
|
||||
| `wizard` | `w` | Downloads the manifest file. | `olares-cli download wizard` |
|
||||
|
||||
## Options
|
||||
|
||||
| Option | Shorthand | Usage | Required | Default |
|
||||
|--------------------|-----------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|-------------------------|--------------------------------|
|
||||
| `--base-dir` | `-b` | Sets the base directory for Olares. | No | `$HOME/.olares` |
|
||||
| `--download-cdn-url`| | Sets the CDN accelerated download URL in the format `https://example.cdn.com`. | No | System default URL |
|
||||
| `--help` | `-h` | Displays help information. | No | N/A |
|
||||
| `--kube` | | Specifies the Kubernetes type. <br>Supported types are `k3s` and `k8s`. | No | `k3s` |
|
||||
| `--version` | `-v` | Specifies the Olares version. <br>Version values follow the format `x.y.z` (e.g., `1.10.0`) or include a build date (e.g., `1.10.0-20241109`). Defaults to the current version.<br> Refer to the [GitHub Releases page](https://github.com/beclab/Olares/releases) for available versions. | No | Current version |
|
||||
|
||||
## Examples
|
||||
```bash
|
||||
# Specifies the base directory where all downloaded components will be stored.
|
||||
olares-cli download component -b /custom/path
|
||||
|
||||
# Specifies a CDN-accelerated URL for downloading Olares components.
|
||||
olares-cli download component --download-cdn-url https://my.cdn.com
|
||||
|
||||
# Specifies the Kubernetes type for the installation.
|
||||
olares-cli download component --kube k8s
|
||||
|
||||
# Sets the path to the package manifest file.
|
||||
olares-cli download component --manifest /custom/path/manifest.json
|
||||
|
||||
# Specifies the version of Olares packages and components to download.
|
||||
olares-cli download component -v 1.11.0
|
||||
```
|
||||
|
||||
|
||||
54
docs/developer/install/cli/gpu.md
Normal file
54
docs/developer/install/cli/gpu.md
Normal file
@@ -0,0 +1,54 @@
|
||||
# `gpu`
|
||||
|
||||
## Synopsis
|
||||
|
||||
The `gpu` command manages GPU-related operations, including installing, enabling, disabling, and uninstalling GPU drivers and related components, as well as checking the GPU status.
|
||||
|
||||
```bash
|
||||
olares-cli gpu <subcommand> [options]
|
||||
```
|
||||
|
||||
:::info
|
||||
- By default, the Olares installation script detects your GPU hardware and CUDA drivers, then configures and enables the GPU components and services automatically.
|
||||
- Currently, only NVIDIA GPUs are supported.
|
||||
:::
|
||||
|
||||
## Subcommands
|
||||
|
||||
| Subcommand | Description |
|
||||
|-------------|--------------------------------------------------------------------------------------------------------------------------------------------|
|
||||
| `install` | Installs GPU drivers and dependencies. |
|
||||
| `enable` | Enables GPU functionality to support GPU-based applications. |
|
||||
| `disable` | Disables GPU functionality, stopping support for GPU-based applications. |
|
||||
| `uninstall` | Uninstalls GPU drivers and related components. |
|
||||
| `status` | Displays the installed GPU driver version, CUDA version, and the status of GPU-related services. |
|
||||
|
||||
|
||||
## Options
|
||||
|
||||
| Option | Shorthand | Usage | Required | Default |
|
||||
|------------|-----------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|-------------------------|--------------------------------|
|
||||
| `--base-dir`| `-b` | Specifies the base installation directory for the GPU components. | No | `$HOME/.olares` |
|
||||
| `--version`| `-v` | Specifies the Olares version for GPU drivers and components. <br>Version values follow the format `x.y.z` (e.g., `1.10.0`) or include a build date (e.g., `1.10.0-20241109`).<br> Refer to the [GitHub Releases page](https://github.com/beclab/Olares/releases) for available versions. | No | Current version |
|
||||
| `--help` | `-h` | Displays help information. | No | N/A |
|
||||
|
||||
## Example
|
||||
|
||||
```bash
|
||||
# Install GPU drivers and dependencies to a specific directory
|
||||
olares-cli gpu install --base-dir /home/olares/.olares --version 1.11.1-rc.4
|
||||
|
||||
# Enable GPU functionality
|
||||
olares-cli gpu enable
|
||||
|
||||
# View the status of GPU drivers and services
|
||||
olares-cli gpu status
|
||||
|
||||
# Disable GPU functionality
|
||||
olares-cli gpu disable
|
||||
|
||||
# Uninstall GPU drivers and components
|
||||
olares-cli gpu uninstall
|
||||
```
|
||||
|
||||
|
||||
14
docs/developer/install/cli/info.md
Normal file
14
docs/developer/install/cli/info.md
Normal file
@@ -0,0 +1,14 @@
|
||||
# `info`
|
||||
|
||||
## Synopsis
|
||||
The `info` command displays general information about the installed Olares version.
|
||||
|
||||
```bash
|
||||
olares-cli info
|
||||
```
|
||||
|
||||
## Flag
|
||||
|
||||
| Name | Shorthand | Usage |
|
||||
|----------|-----------|---------------------------|
|
||||
| `--help` | `-h` | Display help information. |
|
||||
18
docs/developer/install/cli/install.md
Normal file
18
docs/developer/install/cli/install.md
Normal file
@@ -0,0 +1,18 @@
|
||||
# `install`
|
||||
|
||||
## Synopsis
|
||||
The `install` command installs Olares on your system. It supports various options to customize the installation process, such as specifying directories, Kubernetes types, or Minikube profiles.
|
||||
|
||||
```bash
|
||||
olares-cli install [option]
|
||||
```
|
||||
|
||||
## Options
|
||||
|
||||
| Option | Shorthand | Usage | Required | Default |
|
||||
|------------|-----------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|-------------------------|------------------------------------------|
|
||||
| `--base-dir`| `-b` | Sets the base directory for Olares. | No | `$HOME/.olares` |
|
||||
| `--help` | `-h` | Displays help information. | No | N/A |
|
||||
| `--kube` | | Specifies the Kubernetes type. <br>Supported types are `k3s` and `k8s`. | No | `k3s` |
|
||||
| `--profile`| `-p` | Sets the Minikube profile name. Only applicable on macOS. | No | `olares-0` |
|
||||
| `--version`| `-v` | Specifies the Olares version. <br>Version values follow the format `x.y.z` (e.g., `1.10.0`) or include a build date (e.g., `1.10.0-20241109`).<br> Refer to the [GitHub Releases page](https://github.com/beclab/Olares/releases) for available versions. | No | Version installed in the `prepare` phase |
|
||||
41
docs/developer/install/cli/logs.md
Normal file
41
docs/developer/install/cli/logs.md
Normal file
@@ -0,0 +1,41 @@
|
||||
# `logs`
|
||||
|
||||
## Synopsis
|
||||
The `logs` command retrieves logs from Olares components and services found on the local machine. It searches for each component listed below, collects logs if the component is found, and skips it if not:
|
||||
|
||||
* K3s/Kubelet logs
|
||||
* Containerd logs
|
||||
* JuiceFS logs
|
||||
* Redis logs
|
||||
* MinIO logs
|
||||
* etcd logs
|
||||
* olaresd logs
|
||||
* Kubernetes pod info and logs
|
||||
* Kubernetes node info
|
||||
|
||||
```bash
|
||||
olares-cli logs [option]
|
||||
```
|
||||
|
||||
## Options
|
||||
|
||||
| Option | Shorthand | Usage | Required | Default |
|
||||
|------------------------|-----------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|-------------------------|--------------------------------|
|
||||
| `--components` | | Collects logs from specific components (comma-separated).<br/>Supported values: `k3s`, `containerd`, `olaresd`, `kubelet`, `juicefs`, `redis`, `minio`, `etcd`, `NetworkManager`. | No | All detectable components |
|
||||
| `--help` | `-h` | Displays help information. | No | N/A |
|
||||
| `--ignore-kube-errors` | | Ignores errors from `kubectl` commands (e.g., when Kubernetes API is unreachable) and continues collecting logs. | No | `false` |
|
||||
| `--max-lines` | | Limits the maximum number of lines for each component's logs to prevent large log files. | No | `3000` |
|
||||
| `--output-dir` | | Saves logs to the specified directory. Creates the directory if it does not exist. | No | `./olares-logs` |
|
||||
| `--since` | | Fetches logs newer than a specified relative duration (e.g., `5s`, `2m`, `3h`). | No | `7d` |
|
||||
|
||||
## Example
|
||||
```bash
|
||||
# Collect all logs with default settings
|
||||
olares-cli logs
|
||||
|
||||
# Collect logs for specific components
|
||||
olares-cli logs --components k3s,redis,minio
|
||||
|
||||
# Collect logs for the last 3 hours only
|
||||
olares-cli logs --since 3h
|
||||
```
|
||||
51
docs/developer/install/cli/node.md
Normal file
51
docs/developer/install/cli/node.md
Normal file
@@ -0,0 +1,51 @@
|
||||
# `node`
|
||||
|
||||
## Synopsis
|
||||
|
||||
The `node` command manages node-related operations.
|
||||
|
||||
```bash
|
||||
olares-cli node <subcommand> [options]
|
||||
```
|
||||
|
||||
## Subcommands
|
||||
|
||||
| Subcommand | Description |
|
||||
|--------------|-------------------------------------------------------------------------------------------------------------------------------|
|
||||
| `masterinfo` | Retrieves system information about a target master node and checks whether the current node can join the cluster as a worker. |
|
||||
| `add` | Adds the current node to an existing Olares cluster. The node's environment must already meet all prerequisites for Olares. |
|
||||
|
||||
## Options
|
||||
|
||||
| Option | Shorthand | Usage | Required | Default |
|
||||
|---------------------------------|-----------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|-------------------------|--------------------------------|
|
||||
| `--base-dir` | `-b` | Sets the base directory for Olares. | No | `$HOME/.olares` |
|
||||
| `--master-host` | | Defines the IP address of the master node. | Yes | N/A |
|
||||
| `--master-node-name` | | Specifies the Kubernetes node name of the master node. | No | N/A |
|
||||
| `--master-ssh-user` | | Sets the remote Linux user name for SSH login to the master node. | No | `root` |
|
||||
| `--master-ssh-password` | | Provides the password for the Linux user. | Yes if a non-root `master-ssh-user` is specified. | N/A |
|
||||
| `--master-ssh-private-key-path` | | Specifies the path to the private SSH key for authenticating as the Linux user. | No | `/root/.ssh/id_rsa` |
|
||||
| `--master-ssh-port` | | Sets the SSH service's listening port on the master node. | No | `22` |
|
||||
| `--version` | `-v` | Specifies the Olares version. <br>Version values follow the format `x.y.z` (e.g., `1.10.0`) or include a build date (e.g., `1.10.0-20241109`).<br> Refer to the [GitHub Releases page](https://github.com/beclab/Olares/releases) for available versions. | No | Current version |
|
||||
| `--help` | `-h` | Displays help information. | No | N/A | |
|
||||
|
||||
## Example
|
||||
|
||||
```bash
|
||||
# Retrieve system information from a master node at IP 192.168.1.15
|
||||
olares-cli node masterinfo --master-host 192.168.1.15
|
||||
|
||||
# If a specific SSH key is required for authentication
|
||||
olares-cli node masterinfo --master-host 192.168.1.15 --master-ssh-private-key-path /home/olares/.ssh/id_rsa
|
||||
|
||||
# For non-root SSH users, specify the username and password
|
||||
olares-cli node masterinfo --master-host 192.168.1.15 --master-ssh-user olares --master-ssh-password password123
|
||||
|
||||
# Add the current node to a cluster with the master node at IP 192.168.1.15
|
||||
olares-cli node add --master-host 192.168.1.15
|
||||
|
||||
# Specify a custom base directory for the installation
|
||||
olares-cli node add --base-dir /custom/path --master-host 192.168.1.15
|
||||
```
|
||||
|
||||
|
||||
63
docs/developer/install/cli/olares-cli.md
Normal file
63
docs/developer/install/cli/olares-cli.md
Normal file
@@ -0,0 +1,63 @@
|
||||
---
|
||||
outline: [2, 3]
|
||||
---
|
||||
# Olares CLI
|
||||
|
||||
:::warning Note
|
||||
Use this version of Olares CLI if your Olares version is 1.12.X.
|
||||
:::
|
||||
|
||||
The Olares CLI is a versatile command-line tool designed to help developers and system administrators manage and troubleshoot Olares systems. It offers a wide range of features, from installation and configuration to resource management and diagnostics.
|
||||
|
||||
With the Olares CLI, you can streamline tasks such as verifying system compatibility, downloading resources, managing nodes, collecting logs, and more. This guide provides an overview of the CLI's syntax and details the commands available for different operations.
|
||||
|
||||
:::info Root privileges required
|
||||
Most `olares-cli` commands require root privileges. Use the root user or prepend commands with `sudo`.
|
||||
:::
|
||||
|
||||
:::info Using Olares CLI with WSL
|
||||
If you installed Olares using the WSL (Windows Subsystem for Linux) method, you need to use `olares-cli` inside the WSL environment.
|
||||
|
||||
To enter the WSL environment, run the following command in PowerShell:
|
||||
|
||||
```powershell
|
||||
wsl -d Ubuntu
|
||||
```
|
||||
:::
|
||||
|
||||
## Syntax
|
||||
The Olares CLI uses the following syntax:
|
||||
|
||||
> `olares-cli command [subcommand] [option]`
|
||||
|
||||
where
|
||||
- `command`: Specifies the main operation you want to perform. For example, `olares-cli install`.
|
||||
- `subcommand`: Further specifies the task for commands that support additional operations. For example, `wizard` or `component`.
|
||||
- `option`: Optional arguments that modify the behavior of the `command`. Options include flags and options with arguments.
|
||||
|
||||
Olares CLI allows you to temporarily override certain Olares default settings. Each option applies only to the command in which it is used.
|
||||
|
||||
For example, if you use the `--base-dir` option with `olares-cli download wizard`, it will only affect the wizard downloading process and will not change the base directory for other commands, such as during the "install" phase.
|
||||
|
||||
To get detailed help for any command, run `olares-cli help`.
|
||||
|
||||
## Available CLI commands
|
||||
|
||||
| Operation | Syntax | Description |
|
||||
|--------------------|----------------------------------------------------|------------------------------------------------------------------------------------------------------------------------------|
|
||||
| `gpu` | `olares-cli gpu <subcommand> [option]` | Manages GPU-related operations. |
|
||||
| `info` | `olares-cli info <subcommand> [option]` | Displays general information about the operating system of the current device. |
|
||||
| `node` | `olares-cli node <subcommand> [option]` | Manages node-related operations. |
|
||||
| `backups` | `olares-cli backups <subcommand> [option]` | Manages backup-related operations. |
|
||||
| `change-ip` | `olares-cli change-ip [option]` | Changes the IP address of the Olares OS. |
|
||||
| `download` | `olares-cli download <subcommand> [option]` | Downloads specific resources. |
|
||||
| `info` | `olares-cli info [option]` | Displays general information about the downloaded Olares OS. |
|
||||
| `install` | `olares-cli install [option]` | Deploys system-level and user-level components of Olares. |
|
||||
| `logs` | `olares-cli logs [option]` | Collects logs from Olares system components for debugging and troubleshooting. |
|
||||
| `precheck` | `olares-cli precheck [option]` | Verifies whether the system environment meets all requirements for Olares installation. |
|
||||
| `prepare` | `olares-cli prepare [option]` | Prepares the environment for the installation process, including setting up essential services and configurations of Olares. |
|
||||
| `release` | `olares-cli release [option]` | Packages Olares installation resources for distribution or deployment. |
|
||||
| `start` | `olares-cli start [option]` | Starts Olares services and components. |
|
||||
| `stop` | `olares-cli stop [option]` | Stops Olares services and components. |
|
||||
| `uninstall` | `olares-cli uninstall [option]` | Uninstalls Olares completely, or roll back the installation to a specific phase. |
|
||||
|
||||
21
docs/developer/install/cli/osinfo.md
Normal file
21
docs/developer/install/cli/osinfo.md
Normal file
@@ -0,0 +1,21 @@
|
||||
# `osinfo`
|
||||
|
||||
## Synopsis
|
||||
|
||||
The `osinfo` command provides detailed information about the operating system of the current device. Specifically, it retrieves and displays metadata such as `OS_TYPE`, `OS_PLATFORM`, `OS_ARCH`, `OS_VERSION`, `OS_KERNEL`, and `OS_INFO`.
|
||||
|
||||
```bash
|
||||
olares-cli osinfo <subcommand> [options]
|
||||
```
|
||||
|
||||
## Subcommand
|
||||
|
||||
| Subcommand | Description |
|
||||
|------------|----------------------------------------------------------------------|
|
||||
| `show` | Prints information about the operating system of the current device. |
|
||||
|
||||
## Flag
|
||||
|
||||
| Name | Short | Description |
|
||||
|--------------|-------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||
| `--help` | `-h` | Displays help information. |
|
||||
16
docs/developer/install/cli/precheck.md
Normal file
16
docs/developer/install/cli/precheck.md
Normal file
@@ -0,0 +1,16 @@
|
||||
# `precheck`
|
||||
|
||||
## Synopsis
|
||||
The `precheck` command verifies whether the system environment satisfies all prerequisites required for Olares installation.
|
||||
|
||||
```bash
|
||||
olares-cli precheck [option]
|
||||
```
|
||||
|
||||
## Options
|
||||
|
||||
| Option | Shorthand | Usage | Required | Default |
|
||||
|------------|-----------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|-------------------------|-----------------------------------|
|
||||
| `--base-dir`| `-b` | Sets the base directory for Olares. | No | `$HOME/.olares` |
|
||||
| `--help` | `-h` | Displays help information. | No | N/A |
|
||||
| `--version`| `-v` | Specifies the Olares version. <br>Version values follow the format `x.y.z` (e.g., `1.10.0`) or include a build date (e.g., `1.10.0-20241109`).<br> Refer to the [GitHub Releases page](https://github.com/beclab/Olares/releases) for available versions. | No | Current version |
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user