@aigne/afs-synology 1.11.0-beta.12
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE.md +26 -0
- package/dist/_virtual/_@oxc-project_runtime@0.108.0/helpers/decorate.cjs +11 -0
- package/dist/_virtual/_@oxc-project_runtime@0.108.0/helpers/decorate.mjs +10 -0
- package/dist/client.cjs +252 -0
- package/dist/client.d.cts +96 -0
- package/dist/client.d.cts.map +1 -0
- package/dist/client.d.mts +96 -0
- package/dist/client.d.mts.map +1 -0
- package/dist/client.mjs +253 -0
- package/dist/client.mjs.map +1 -0
- package/dist/errors.cjs +37 -0
- package/dist/errors.d.cts +10 -0
- package/dist/errors.d.cts.map +1 -0
- package/dist/errors.d.mts +10 -0
- package/dist/errors.d.mts.map +1 -0
- package/dist/errors.mjs +37 -0
- package/dist/errors.mjs.map +1 -0
- package/dist/formatters.cjs +139 -0
- package/dist/formatters.mjs +128 -0
- package/dist/formatters.mjs.map +1 -0
- package/dist/index.cjs +15 -0
- package/dist/index.d.cts +5 -0
- package/dist/index.d.mts +5 -0
- package/dist/index.mjs +6 -0
- package/dist/synology-afs.cjs +1686 -0
- package/dist/synology-afs.d.cts +232 -0
- package/dist/synology-afs.d.cts.map +1 -0
- package/dist/synology-afs.d.mts +232 -0
- package/dist/synology-afs.d.mts.map +1 -0
- package/dist/synology-afs.mjs +1687 -0
- package/dist/synology-afs.mjs.map +1 -0
- package/dist/types.cjs +44 -0
- package/dist/types.d.cts +174 -0
- package/dist/types.d.cts.map +1 -0
- package/dist/types.d.mts +174 -0
- package/dist/types.d.mts.map +1 -0
- package/dist/types.mjs +42 -0
- package/dist/types.mjs.map +1 -0
- package/package.json +57 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"synology-afs.mjs","names":[],"sources":["../src/synology-afs.ts"],"sourcesContent":["/**\n * AFSSynology - Synology NAS AFS Provider\n *\n * Maps Synology DSM management capabilities to AFS filesystem interface.\n * File read/write goes through afs-fs (NFS/SMB); this provider focuses on:\n * - System health monitoring\n * - Storage status (disks, pools, volumes)\n * - Docker container management (including start/stop/restart)\n * - Backup monitoring and task triggering\n * - Package management (start/stop)\n */\n\nimport {\n Actions,\n type AFSAccessMode,\n AFSBaseProvider,\n type AFSEntry,\n AFSError,\n type AFSExecResult,\n type AFSExplainResult,\n type AFSListResult,\n type AFSModuleLoadParams,\n AFSNotFoundError,\n type AFSSearchOptions,\n type AFSSearchResult,\n type AFSStatResult,\n type CapabilitiesManifest,\n Explain,\n List,\n type ListHandlerResult,\n Meta,\n type ProviderManifest,\n type ProviderTreeSchema,\n Read,\n type RouteContext,\n Search,\n type SecurityProfile,\n Stat,\n} from \"@aigne/afs\";\nimport { joinURL } from \"ufo\";\nimport { z } from \"zod\";\nimport { SynologyClient } from \"./client.js\";\nimport {\n formatBackupTaskInfo,\n formatBytes,\n formatContainerInfo,\n formatDiskInfo,\n formatHardwareInfo,\n formatImageInfo,\n formatPackageInfo,\n formatPoolInfo,\n formatShareInfo,\n formatSystemStatus,\n formatSystemUtilization,\n formatVolumeInfo,\n} from \"./formatters.js\";\nimport {\n type AFSSynologyConfig,\n AFSSynologyConfigSchema,\n KINDS,\n type SynoBackupTaskInfo,\n type SynoContainerInfo,\n type SynoDiskInfo,\n type SynoImageInfo,\n type SynoPackageInfo,\n type SynoShareInfo,\n type SynoStoragePoolInfo,\n type SynoSystemInfo,\n type SynoSystemUtilization,\n type SynoVolumeInfo,\n} from \"./types.js\";\n\n/**\n * Synology NAS AFS Provider\n *\n * Readwrite mode: supports exec operations (container start/stop/restart,\n * backup trigger, package start/stop). Write and delete are never supported.\n */\nexport class AFSSynology extends AFSBaseProvider {\n static securityProfiles(): Record<string, SecurityProfile> {\n return {\n admin: { actionPolicy: \"full\", sensitivity: \"full\" },\n user: {\n actionPolicy: \"standard\",\n sensitiveFields: [\"serial_number\"],\n sensitivity: \"redacted\",\n },\n kid: {\n actionPolicy: \"safe\",\n accessMode: \"readonly\",\n blockedActions: [\"stop\", \"restart\"],\n sensitiveFields: [\"serial_number\"],\n sensitivity: \"redacted\",\n },\n guest: {\n actionPolicy: \"safe\",\n accessMode: \"readonly\",\n sensitiveFields: [\"serial_number\"],\n sensitivity: \"redacted\",\n },\n };\n }\n\n override readonly name: string;\n override readonly description?: string;\n override readonly accessMode: AFSAccessMode = \"readwrite\";\n\n private client: SynologyClient;\n\n // Cached data from Synology APIs\n private systemInfo: SynoSystemInfo | null = null;\n private utilization: SynoSystemUtilization | null = null;\n private disks: SynoDiskInfo[] | null = null;\n private pools: SynoStoragePoolInfo[] | null = null;\n private volumes: SynoVolumeInfo[] | null = null;\n private containers: SynoContainerInfo[] | null = null;\n private images: SynoImageInfo[] | null = null;\n private shares: SynoShareInfo[] | null = null;\n private packages: SynoPackageInfo[] | null = null;\n private backupTasks: SynoBackupTaskInfo[] | null = null;\n\n constructor(config: AFSSynologyConfig & { uri?: string }) {\n super();\n\n // Strip unknown keys\n const { uri: _uri, ...cleanConfig } = config as AFSSynologyConfig & { uri?: string };\n\n // Validate\n const validated = AFSSynologyConfigSchema.parse(cleanConfig);\n\n // Validate URL format\n if (!validated.url.startsWith(\"http://\") && !validated.url.startsWith(\"https://\")) {\n throw new AFSError(\"URL must start with http:// or https://\", \"AFS_INVALID_PARAMETER\");\n }\n\n this.name = validated.name || \"synology\";\n this.description = validated.description || `Synology NAS at ${validated.url}`;\n\n this.client = new SynologyClient({\n url: validated.url,\n account: validated.account,\n password: validated.password,\n otpCode: validated.otpCode,\n deviceId: validated.deviceId,\n verifySsl: validated.verifySsl,\n });\n }\n\n // ========== Static Methods ==========\n\n static schema() {\n return AFSSynologyConfigSchema;\n }\n\n static manifest(): ProviderManifest {\n return {\n name: \"synology\",\n description:\n \"Synology NAS management — system health, storage status, Docker containers, backup monitoring.\\n- Monitor CPU, RAM, disk health, temperature\\n- View Docker containers, images, networks\\n- Start/stop/restart Docker containers\\n- Check Hyper Backup task status and trigger backups\\n- Start/stop DSM packages\\n- Path structure: `/system/`, `/storage/`, `/docker/`, `/shares/`, `/packages/`, `/backup/`\",\n uriTemplate: \"synology://{host}\",\n category: \"storage\",\n schema: z.object({\n host: z.string().optional(),\n }),\n tags: [\"synology\", \"nas\", \"docker\", \"storage\", \"backup\"],\n capabilityTags: [\n \"read-write\",\n \"crud\",\n \"search\",\n \"auth:token\",\n \"remote\",\n \"http\",\n \"on-premise\",\n ],\n security: {\n riskLevel: \"external\",\n resourceAccess: [\"internet\", \"local-network\"],\n requires: [\"docker\"],\n dataSensitivity: [\"system-config\", \"media\"],\n notes: [\"Manages NAS system — can start/stop Docker containers and DSM packages\"],\n },\n capabilities: {\n network: { egress: true },\n secrets: [\"synology/password\"],\n },\n };\n }\n\n static treeSchema(): ProviderTreeSchema {\n return {\n operations: [\"list\", \"read\", \"search\", \"exec\", \"stat\", \"explain\"],\n tree: {\n \"/\": { kind: \"nas:root\" },\n \"/system\": { kind: \"nas:system-group\", operations: [\"list\"] },\n \"/system/status\": { kind: \"nas:system-info\", operations: [\"read\"] },\n \"/system/utilization\": { kind: \"nas:system-info\", operations: [\"read\"] },\n \"/system/hardware\": { kind: \"nas:system-info\", operations: [\"read\"] },\n \"/storage\": { kind: \"nas:storage-group\", operations: [\"list\"] },\n \"/storage/disks\": { kind: \"afs:directory\", operations: [\"list\"] },\n \"/storage/disks/{diskId}\": { kind: \"nas:disk\", operations: [\"read\"] },\n \"/storage/pools\": { kind: \"afs:directory\", operations: [\"list\"] },\n \"/storage/pools/{poolId}\": { kind: \"nas:storage-pool\", operations: [\"read\"] },\n \"/storage/volumes\": { kind: \"afs:directory\", operations: [\"list\"] },\n \"/storage/volumes/{volumeId}\": { kind: \"nas:volume\", operations: [\"read\"] },\n \"/docker\": { kind: \"nas:docker-group\", operations: [\"list\"] },\n \"/docker/containers\": { kind: \"afs:directory\", operations: [\"list\"] },\n \"/docker/containers/{name}\": {\n kind: \"nas:container\",\n operations: [\"read\", \"exec\"],\n actions: [\"start\", \"stop\", \"restart\"],\n destructive: [\"stop\"],\n },\n \"/docker/images\": { kind: \"afs:directory\", operations: [\"list\"] },\n \"/docker/images/{name}\": { kind: \"nas:docker-image\", operations: [\"read\"] },\n \"/docker/networks\": { kind: \"afs:directory\", operations: [\"list\"] },\n \"/docker/projects\": { kind: \"afs:directory\", operations: [\"list\"] },\n \"/shares\": { kind: \"afs:directory\", operations: [\"list\"] },\n \"/shares/{name}\": { kind: \"nas:shared-folder\", operations: [\"read\"] },\n \"/packages\": { kind: \"afs:directory\", operations: [\"list\"] },\n \"/packages/{name}\": {\n kind: \"nas:package\",\n operations: [\"read\", \"exec\"],\n actions: [\"start\", \"stop\"],\n },\n \"/backup\": { kind: \"afs:directory\", operations: [\"list\"] },\n \"/backup/tasks\": { kind: \"afs:directory\", operations: [\"list\"] },\n \"/backup/tasks/{taskId}\": {\n kind: \"nas:backup-task\",\n operations: [\"read\", \"exec\"],\n actions: [\"run\"],\n },\n },\n auth: { type: \"custom\", env: [\"SYNOLOGY_URL\", \"SYNOLOGY_ACCOUNT\", \"SYNOLOGY_PASSWORD\"] },\n bestFor: [\"NAS monitoring\", \"Docker management\", \"backup monitoring\"],\n notFor: [\"file read/write\", \"database queries\"],\n };\n }\n\n static async load({ config }: AFSModuleLoadParams = {}): Promise<AFSSynology> {\n const validated = AFSSynologyConfigSchema.parse(config ?? {});\n return new AFSSynology(validated);\n }\n\n // ========== Data Fetching Helpers ==========\n\n private async getSystemInfo(): Promise<SynoSystemInfo> {\n if (!this.systemInfo) {\n this.systemInfo = await this.client.request<SynoSystemInfo>({\n api: \"SYNO.Core.System\",\n method: \"info\",\n version: 1,\n });\n }\n return this.systemInfo;\n }\n\n private async getUtilization(): Promise<SynoSystemUtilization> {\n if (!this.utilization) {\n this.utilization = await this.client.request<SynoSystemUtilization>({\n api: \"SYNO.Core.System.Utilization\",\n method: \"get\",\n version: 1,\n });\n }\n return this.utilization;\n }\n\n private async getDisks(): Promise<SynoDiskInfo[]> {\n if (!this.disks) {\n const data = await this.client.request<{ disks: SynoDiskInfo[] }>({\n api: \"SYNO.Storage.CGI.Storage\",\n method: \"load_info\",\n version: 1,\n });\n this.disks = data.disks || [];\n }\n return this.disks;\n }\n\n private async getPools(): Promise<SynoStoragePoolInfo[]> {\n if (!this.pools) {\n const data = await this.client.request<{ storagePools: SynoStoragePoolInfo[] }>({\n api: \"SYNO.Storage.CGI.Storage\",\n method: \"load_info\",\n version: 1,\n });\n this.pools = data.storagePools || [];\n }\n return this.pools;\n }\n\n private async getVolumes(): Promise<SynoVolumeInfo[]> {\n if (!this.volumes) {\n const data = await this.client.request<{ volumes: SynoVolumeInfo[] }>({\n api: \"SYNO.Storage.CGI.Storage\",\n method: \"load_info\",\n version: 1,\n });\n this.volumes = data.volumes || [];\n }\n return this.volumes;\n }\n\n private async getContainers(): Promise<SynoContainerInfo[]> {\n if (!this.containers) {\n const data = await this.client.request<{ containers: SynoContainerInfo[] }>({\n api: \"SYNO.Docker.Container\",\n method: \"list\",\n version: 1,\n extra: { limit: -1, offset: 0, type: \"all\" },\n });\n this.containers = data.containers || [];\n }\n return this.containers;\n }\n\n private async getImages(): Promise<SynoImageInfo[]> {\n if (!this.images) {\n const data = await this.client.request<{ images: SynoImageInfo[] }>({\n api: \"SYNO.Docker.Image\",\n method: \"list\",\n version: 1,\n extra: { limit: -1, offset: 0 },\n });\n this.images = data.images || [];\n }\n return this.images;\n }\n\n private async getShares(): Promise<SynoShareInfo[]> {\n if (!this.shares) {\n const data = await this.client.request<{ shares: SynoShareInfo[] }>({\n api: \"SYNO.Core.Share\",\n method: \"list\",\n version: 1,\n });\n this.shares = data.shares || [];\n }\n return this.shares;\n }\n\n private async getPackages(): Promise<SynoPackageInfo[]> {\n if (!this.packages) {\n const data = await this.client.request<{ packages: SynoPackageInfo[] }>({\n api: \"SYNO.Core.Package\",\n method: \"list\",\n version: 1,\n });\n this.packages = data.packages || [];\n }\n return this.packages;\n }\n\n private async getBackupTasks(): Promise<SynoBackupTaskInfo[]> {\n if (!this.backupTasks) {\n const data = await this.client.request<{ tasks: SynoBackupTaskInfo[] }>({\n api: \"SYNO.Backup.Task\",\n method: \"list\",\n version: 1,\n });\n this.backupTasks = data.tasks || [];\n }\n return this.backupTasks;\n }\n\n /** Sanitize image name for use as path segment (replace / with -) */\n private sanitizeImageName(repository: string, _tag: string): string {\n return `${repository.replace(/\\//g, \"-\")}`;\n }\n\n /** Invalidate container cache after exec operations */\n private invalidateContainerCache(): void {\n this.containers = null;\n this.client.invalidateCache();\n }\n\n /** Invalidate package cache after exec operations */\n private invalidatePackageCache(): void {\n this.packages = null;\n }\n\n /** Invalidate backup task cache after exec operations */\n private invalidateBackupTaskCache(): void {\n this.backupTasks = null;\n }\n\n // ========== Capabilities ==========\n\n @Read(\"/.meta/.capabilities\")\n async readCapabilities(_ctx: RouteContext): Promise<AFSEntry> {\n const manifest: CapabilitiesManifest = {\n schemaVersion: 1,\n provider: this.name,\n description: this.description || \"Synology NAS management provider\",\n tools: [],\n actions: [],\n operations: this.getOperationsDeclaration(),\n };\n\n return {\n id: \"/.meta/.capabilities\",\n path: \"/.meta/.capabilities\",\n content: manifest,\n meta: { kind: \"afs:capabilities\" },\n };\n }\n\n // ========== Meta Handlers ==========\n\n @Meta(\"/\")\n async metaRoot(_ctx: RouteContext): Promise<AFSEntry> {\n const info = await this.getSystemInfo();\n return {\n id: \"\",\n path: \"/.meta\",\n meta: {\n kind: KINDS.NAS,\n model: info.model,\n version: info.version,\n serial: info.serial,\n childrenCount: 6,\n description: `Synology ${info.model} running DSM ${info.version}`,\n },\n };\n }\n\n @Meta(\"/system\")\n async metaSystem(_ctx: RouteContext): Promise<AFSEntry> {\n return {\n id: \"system\",\n path: \"/system/.meta\",\n meta: {\n kind: KINDS.SYSTEM_GROUP,\n childrenCount: 3,\n description: \"System health and resource monitoring\",\n },\n };\n }\n\n @Meta(\"/system/:item\")\n async metaSystemItem(ctx: RouteContext<{ item: string }>): Promise<AFSEntry> {\n const { item } = ctx.params;\n const descriptions: Record<string, string> = {\n status: \"System health status summary\",\n utilization: \"CPU, RAM, disk I/O, network statistics\",\n hardware: \"Temperature, fan speed, power status\",\n };\n if (!descriptions[item]) {\n throw new AFSNotFoundError(joinURL(\"/system\", item));\n }\n return {\n id: item,\n path: joinURL(\"/system\", item, \".meta\"),\n meta: {\n kind: KINDS.SYSTEM_INFO,\n childrenCount: 0,\n description: descriptions[item],\n },\n };\n }\n\n @Meta(\"/storage\")\n async metaStorage(_ctx: RouteContext): Promise<AFSEntry> {\n return {\n id: \"storage\",\n path: \"/storage/.meta\",\n meta: {\n kind: KINDS.STORAGE_GROUP,\n childrenCount: 3,\n description: \"Physical disks, storage pools, and volumes\",\n },\n };\n }\n\n @Meta(\"/storage/disks\")\n async metaDisks(_ctx: RouteContext): Promise<AFSEntry> {\n const disks = await this.getDisks();\n return {\n id: \"disks\",\n path: \"/storage/disks/.meta\",\n meta: {\n childrenCount: disks.length,\n description: \"Physical disk drives\",\n },\n };\n }\n\n @Meta(\"/storage/disks/:diskId\")\n async metaDisk(ctx: RouteContext<{ diskId: string }>): Promise<AFSEntry> {\n const disks = await this.getDisks();\n const disk = disks.find((d) => d.id === ctx.params.diskId);\n if (!disk) {\n throw new AFSNotFoundError(joinURL(\"/storage/disks\", ctx.params.diskId));\n }\n return {\n id: disk.id,\n path: joinURL(\"/storage/disks\", disk.id, \".meta\"),\n meta: {\n kind: KINDS.DISK,\n id: disk.id,\n childrenCount: 0,\n description: `${disk.model} - ${formatBytes(disk.size_total)} - ${disk.smart_status || disk.status}`,\n },\n };\n }\n\n @Meta(\"/storage/pools\")\n async metaPools(_ctx: RouteContext): Promise<AFSEntry> {\n const pools = await this.getPools();\n return {\n id: \"pools\",\n path: \"/storage/pools/.meta\",\n meta: {\n childrenCount: pools.length,\n description: \"RAID storage pools\",\n },\n };\n }\n\n @Meta(\"/storage/pools/:poolId\")\n async metaPool(ctx: RouteContext<{ poolId: string }>): Promise<AFSEntry> {\n const pools = await this.getPools();\n const pool = pools.find((p) => p.id === ctx.params.poolId);\n if (!pool) {\n throw new AFSNotFoundError(joinURL(\"/storage/pools\", ctx.params.poolId));\n }\n return {\n id: pool.id,\n path: joinURL(\"/storage/pools\", pool.id, \".meta\"),\n meta: {\n kind: KINDS.STORAGE_POOL,\n id: pool.id,\n childrenCount: 0,\n description: `${pool.raidType || \"unknown\"} pool - ${pool.status}`,\n },\n };\n }\n\n @Meta(\"/storage/volumes\")\n async metaVolumes(_ctx: RouteContext): Promise<AFSEntry> {\n const volumes = await this.getVolumes();\n return {\n id: \"volumes\",\n path: \"/storage/volumes/.meta\",\n meta: {\n childrenCount: volumes.length,\n description: \"Logical volumes\",\n },\n };\n }\n\n @Meta(\"/storage/volumes/:volumeId\")\n async metaVolume(ctx: RouteContext<{ volumeId: string }>): Promise<AFSEntry> {\n const volumes = await this.getVolumes();\n const volume = volumes.find((v) => v.id === ctx.params.volumeId);\n if (!volume) {\n throw new AFSNotFoundError(joinURL(\"/storage/volumes\", ctx.params.volumeId));\n }\n const usedPercent = Math.round((volume.size.used / volume.size.total) * 100);\n return {\n id: volume.id,\n path: joinURL(\"/storage/volumes\", volume.id, \".meta\"),\n meta: {\n kind: KINDS.VOLUME,\n id: volume.id,\n childrenCount: 0,\n description: `${volume.fs_type} - ${usedPercent}% used`,\n },\n };\n }\n\n @Meta(\"/docker\")\n async metaDocker(_ctx: RouteContext): Promise<AFSEntry> {\n return {\n id: \"docker\",\n path: \"/docker/.meta\",\n meta: {\n kind: KINDS.DOCKER_GROUP,\n childrenCount: 4,\n description: \"Docker containers, images, networks, and projects\",\n },\n };\n }\n\n @Meta(\"/docker/containers\")\n async metaContainers(_ctx: RouteContext): Promise<AFSEntry> {\n return {\n id: \"containers\",\n path: \"/docker/containers/.meta\",\n meta: {\n childrenCount: -1,\n description: \"Running and stopped containers\",\n },\n };\n }\n\n @Meta(\"/docker/containers/:containerName\")\n async metaContainer(ctx: RouteContext<{ containerName: string }>): Promise<AFSEntry> {\n const containers = await this.getContainers();\n const container = containers.find((c) => c.name === ctx.params.containerName);\n if (!container) {\n throw new AFSNotFoundError(joinURL(\"/docker/containers\", ctx.params.containerName));\n }\n return {\n id: container.name,\n path: joinURL(\"/docker/containers\", container.name, \".meta\"),\n meta: {\n kind: KINDS.CONTAINER,\n id: container.name,\n childrenCount: 0,\n description: `${container.image} - ${container.status}`,\n },\n };\n }\n\n @Meta(\"/docker/images\")\n async metaImages(_ctx: RouteContext): Promise<AFSEntry> {\n return {\n id: \"images\",\n path: \"/docker/images/.meta\",\n meta: {\n childrenCount: -1,\n description: \"Local Docker images\",\n },\n };\n }\n\n @Meta(\"/docker/images/:imageName\")\n async metaImage(ctx: RouteContext<{ imageName: string }>): Promise<AFSEntry> {\n const images = await this.getImages();\n const image = images.find(\n (i) => this.sanitizeImageName(i.repository, i.tag) === ctx.params.imageName,\n );\n if (!image) {\n throw new AFSNotFoundError(joinURL(\"/docker/images\", ctx.params.imageName));\n }\n return {\n id: `${image.repository}:${image.tag}`,\n path: joinURL(\"/docker/images\", ctx.params.imageName, \".meta\"),\n meta: {\n kind: KINDS.DOCKER_IMAGE,\n id: `${image.repository}:${image.tag}`,\n childrenCount: 0,\n },\n };\n }\n\n @Meta(\"/docker/networks\")\n async metaNetworks(_ctx: RouteContext): Promise<AFSEntry> {\n return {\n id: \"networks\",\n path: \"/docker/networks/.meta\",\n meta: {\n childrenCount: 0,\n description: \"Docker networks\",\n },\n };\n }\n\n @Meta(\"/docker/projects\")\n async metaProjects(_ctx: RouteContext): Promise<AFSEntry> {\n return {\n id: \"projects\",\n path: \"/docker/projects/.meta\",\n meta: {\n childrenCount: 0,\n description: \"Docker Compose projects (DSM 7.2+)\",\n },\n };\n }\n\n @Meta(\"/shares\")\n async metaShares(_ctx: RouteContext): Promise<AFSEntry> {\n const shares = await this.getShares();\n return {\n id: \"shares\",\n path: \"/shares/.meta\",\n meta: {\n childrenCount: shares.length,\n description: \"Shared folders\",\n },\n };\n }\n\n @Meta(\"/shares/:shareName\")\n async metaShare(ctx: RouteContext<{ shareName: string }>): Promise<AFSEntry> {\n const shares = await this.getShares();\n const share = shares.find((s) => s.name === ctx.params.shareName);\n if (!share) {\n throw new AFSNotFoundError(joinURL(\"/shares\", ctx.params.shareName));\n }\n return {\n id: share.name,\n path: joinURL(\"/shares\", share.name, \".meta\"),\n meta: {\n kind: KINDS.SHARED_FOLDER,\n id: share.name,\n childrenCount: 0,\n description: share.path,\n },\n };\n }\n\n @Meta(\"/packages\")\n async metaPackages(_ctx: RouteContext): Promise<AFSEntry> {\n const packages = await this.getPackages();\n return {\n id: \"packages\",\n path: \"/packages/.meta\",\n meta: {\n childrenCount: packages.length,\n description: \"Installed DSM packages\",\n },\n };\n }\n\n @Meta(\"/packages/:packageName\")\n async metaPackage(ctx: RouteContext<{ packageName: string }>): Promise<AFSEntry> {\n const packages = await this.getPackages();\n const pkg = packages.find((p) => p.id === ctx.params.packageName);\n if (!pkg) {\n throw new AFSNotFoundError(joinURL(\"/packages\", ctx.params.packageName));\n }\n const updateStr = pkg.has_update ? \" (update available)\" : \"\";\n return {\n id: pkg.id,\n path: joinURL(\"/packages\", pkg.id, \".meta\"),\n meta: {\n kind: KINDS.PACKAGE,\n id: pkg.id,\n childrenCount: 0,\n description: `${pkg.name} v${pkg.version} - ${pkg.status}${updateStr}`,\n },\n };\n }\n\n @Meta(\"/backup\")\n async metaBackup(_ctx: RouteContext): Promise<AFSEntry> {\n return {\n id: \"backup\",\n path: \"/backup/.meta\",\n meta: {\n childrenCount: 1,\n description: \"Backup management\",\n },\n };\n }\n\n @Meta(\"/backup/tasks\")\n async metaBackupTasks(_ctx: RouteContext): Promise<AFSEntry> {\n const tasks = await this.getBackupTasks();\n return {\n id: \"tasks\",\n path: \"/backup/tasks/.meta\",\n meta: {\n childrenCount: tasks.length,\n description: \"Hyper Backup tasks\",\n },\n };\n }\n\n @Meta(\"/backup/tasks/:taskName\")\n async metaBackupTask(ctx: RouteContext<{ taskName: string }>): Promise<AFSEntry> {\n const tasks = await this.getBackupTasks();\n const task = tasks.find((t) => t.name === ctx.params.taskName);\n if (!task) {\n throw new AFSNotFoundError(joinURL(\"/backup/tasks\", ctx.params.taskName));\n }\n const lastRunDate = task.last_run ? task.last_run.split(\"T\")[0] : \"never\";\n return {\n id: task.name,\n path: joinURL(\"/backup/tasks\", task.name, \".meta\"),\n meta: {\n kind: KINDS.BACKUP_TASK,\n id: task.name,\n childrenCount: 0,\n description: `${task.status} - last run ${lastRunDate}`,\n },\n };\n }\n\n // ========== List Handlers ==========\n\n @List(\"/\")\n async listRoot(_ctx: RouteContext): Promise<ListHandlerResult> {\n const children: AFSEntry[] = [\n this.buildEntry(\"/system\", {\n meta: {\n kind: KINDS.SYSTEM_GROUP,\n childrenCount: 3,\n description: \"System health and resource monitoring\",\n },\n }),\n this.buildEntry(\"/storage\", {\n meta: {\n kind: KINDS.STORAGE_GROUP,\n childrenCount: 3,\n description: \"Physical disks, storage pools, and volumes\",\n },\n }),\n this.buildEntry(\"/docker\", {\n meta: {\n kind: KINDS.DOCKER_GROUP,\n childrenCount: 4,\n description: \"Docker containers, images, networks, and projects\",\n },\n }),\n this.buildEntry(\"/shares\", {\n meta: {\n kind: \"nas:shared-folder-group\",\n childrenCount: -1, // Will be resolved dynamically\n description: \"Shared folders\",\n },\n }),\n this.buildEntry(\"/packages\", {\n meta: {\n kind: \"nas:package-group\",\n childrenCount: -1,\n description: \"Installed DSM packages\",\n },\n }),\n this.buildEntry(\"/backup\", {\n meta: {\n kind: \"nas:backup-group\",\n childrenCount: 1,\n description: \"Backup management\",\n },\n }),\n ];\n\n return { data: children };\n }\n\n @List(\"/system\")\n async listSystem(_ctx: RouteContext): Promise<AFSListResult> {\n return {\n data: [\n this.buildEntry(\"/system/status\", {\n meta: {\n kind: KINDS.SYSTEM_INFO,\n childrenCount: 0,\n description: \"System health status summary\",\n },\n }),\n this.buildEntry(\"/system/utilization\", {\n meta: {\n kind: KINDS.SYSTEM_INFO,\n childrenCount: 0,\n description: \"CPU, RAM, disk I/O, network statistics\",\n },\n }),\n this.buildEntry(\"/system/hardware\", {\n meta: {\n kind: KINDS.SYSTEM_INFO,\n childrenCount: 0,\n description: \"Temperature, fan speed, power status\",\n },\n }),\n ],\n };\n }\n\n @List(\"/storage\")\n async listStorage(_ctx: RouteContext): Promise<AFSListResult> {\n const [disks, pools, volumes] = await Promise.all([\n this.getDisks(),\n this.getPools(),\n this.getVolumes(),\n ]);\n return {\n data: [\n this.buildEntry(\"/storage/disks\", {\n meta: { childrenCount: disks.length, description: \"Physical disk drives\" },\n }),\n this.buildEntry(\"/storage/pools\", {\n meta: { childrenCount: pools.length, description: \"RAID storage pools\" },\n }),\n this.buildEntry(\"/storage/volumes\", {\n meta: { childrenCount: volumes.length, description: \"Logical volumes\" },\n }),\n ],\n };\n }\n\n @List(\"/storage/disks\")\n async listDisks(_ctx: RouteContext): Promise<AFSListResult> {\n const disks = await this.getDisks();\n return {\n data: disks.map((d) =>\n this.buildEntry(joinURL(\"/storage/disks\", d.id), {\n meta: {\n kind: KINDS.DISK,\n id: d.id,\n childrenCount: 0,\n description: `${d.model} - ${formatBytes(d.size_total)} - ${d.smart_status || d.status}`,\n },\n }),\n ),\n };\n }\n\n @List(\"/storage/pools\")\n async listPools(_ctx: RouteContext): Promise<AFSListResult> {\n const pools = await this.getPools();\n return {\n data: pools.map((p) =>\n this.buildEntry(joinURL(\"/storage/pools\", p.id), {\n meta: {\n kind: KINDS.STORAGE_POOL,\n id: p.id,\n childrenCount: 0,\n description: `${p.raidType || \"unknown\"} pool - ${p.status}`,\n },\n }),\n ),\n };\n }\n\n @List(\"/storage/volumes\")\n async listVolumes(_ctx: RouteContext): Promise<AFSListResult> {\n const volumes = await this.getVolumes();\n return {\n data: volumes.map((v) => {\n const usedPercent = Math.round((v.size.used / v.size.total) * 100);\n return this.buildEntry(joinURL(\"/storage/volumes\", v.id), {\n meta: {\n kind: KINDS.VOLUME,\n id: v.id,\n childrenCount: 0,\n description: `${v.fs_type} - ${usedPercent}% used`,\n },\n });\n }),\n };\n }\n\n @List(\"/docker\")\n async listDocker(_ctx: RouteContext): Promise<AFSListResult> {\n return {\n data: [\n this.buildEntry(\"/docker/containers\", {\n meta: { childrenCount: -1, description: \"Running and stopped containers\" },\n }),\n this.buildEntry(\"/docker/images\", {\n meta: { childrenCount: -1, description: \"Local Docker images\" },\n }),\n this.buildEntry(\"/docker/networks\", {\n meta: { childrenCount: 0, description: \"Docker networks\" },\n }),\n this.buildEntry(\"/docker/projects\", {\n meta: { childrenCount: 0, description: \"Docker Compose projects (DSM 7.2+)\" },\n }),\n ],\n };\n }\n\n @List(\"/docker/containers\")\n async listContainers(_ctx: RouteContext): Promise<AFSListResult> {\n const containers = await this.getContainers();\n return {\n data: containers.map((c) =>\n this.buildEntry(joinURL(\"/docker/containers\", c.name), {\n meta: {\n kind: KINDS.CONTAINER,\n id: c.name,\n childrenCount: 0,\n description: `${c.image} - ${c.status}`,\n },\n }),\n ),\n };\n }\n\n @List(\"/docker/images\")\n async listImages(_ctx: RouteContext): Promise<AFSListResult> {\n const images = await this.getImages();\n return {\n data: images.map((i) => {\n const safeName = this.sanitizeImageName(i.repository, i.tag);\n return this.buildEntry(joinURL(\"/docker/images\", safeName), {\n meta: {\n kind: KINDS.DOCKER_IMAGE,\n id: `${i.repository}:${i.tag}`,\n childrenCount: 0,\n },\n });\n }),\n };\n }\n\n @List(\"/docker/networks\")\n async listNetworks(_ctx: RouteContext): Promise<AFSListResult> {\n return { data: [] };\n }\n\n @List(\"/docker/projects\")\n async listProjects(_ctx: RouteContext): Promise<AFSListResult> {\n return { data: [] };\n }\n\n @List(\"/shares\")\n async listShares(_ctx: RouteContext): Promise<AFSListResult> {\n const shares = await this.getShares();\n return {\n data: shares.map((s) =>\n this.buildEntry(joinURL(\"/shares\", s.name), {\n meta: {\n kind: KINDS.SHARED_FOLDER,\n id: s.name,\n childrenCount: 0,\n description: s.path,\n },\n }),\n ),\n };\n }\n\n @List(\"/packages\")\n async listPackages(_ctx: RouteContext): Promise<AFSListResult> {\n const packages = await this.getPackages();\n return {\n data: packages.map((p) => {\n const updateStr = p.has_update ? \" (update available)\" : \"\";\n return this.buildEntry(joinURL(\"/packages\", p.id), {\n meta: {\n kind: KINDS.PACKAGE,\n id: p.id,\n childrenCount: 0,\n description: `${p.name} v${p.version} - ${p.status}${updateStr}`,\n },\n });\n }),\n };\n }\n\n @List(\"/backup\")\n async listBackup(_ctx: RouteContext): Promise<AFSListResult> {\n const tasks = await this.getBackupTasks();\n return {\n data: [\n this.buildEntry(\"/backup/tasks\", {\n meta: { childrenCount: tasks.length, description: \"Hyper Backup tasks\" },\n }),\n ],\n };\n }\n\n @List(\"/backup/tasks\")\n async listBackupTasks(_ctx: RouteContext): Promise<AFSListResult> {\n const tasks = await this.getBackupTasks();\n return {\n data: tasks.map((t) => {\n const lastRunDate = t.last_run ? t.last_run.split(\"T\")[0] : \"never\";\n return this.buildEntry(joinURL(\"/backup/tasks\", t.name), {\n meta: {\n kind: KINDS.BACKUP_TASK,\n id: t.name,\n childrenCount: 0,\n description: `${t.status} - last run ${lastRunDate}`,\n },\n });\n }),\n };\n }\n\n // ========== Leaf Node List Handlers (return empty data for file nodes) ==========\n\n @List(\"/system/:item\")\n async listSystemLeaf(_ctx: RouteContext<{ item: string }>): Promise<AFSListResult> {\n const validItems = [\"status\", \"utilization\", \"hardware\"];\n if (!validItems.includes(_ctx.params.item)) {\n throw new AFSNotFoundError(joinURL(\"/system\", _ctx.params.item));\n }\n return { data: [] };\n }\n\n @List(\"/storage/disks/:diskId\")\n async listDiskLeaf(ctx: RouteContext<{ diskId: string }>): Promise<AFSListResult> {\n const disks = await this.getDisks();\n if (!disks.find((d) => d.id === ctx.params.diskId)) {\n throw new AFSNotFoundError(joinURL(\"/storage/disks\", ctx.params.diskId));\n }\n return { data: [] };\n }\n\n @List(\"/storage/pools/:poolId\")\n async listPoolLeaf(ctx: RouteContext<{ poolId: string }>): Promise<AFSListResult> {\n const pools = await this.getPools();\n if (!pools.find((p) => p.id === ctx.params.poolId)) {\n throw new AFSNotFoundError(joinURL(\"/storage/pools\", ctx.params.poolId));\n }\n return { data: [] };\n }\n\n @List(\"/storage/volumes/:volumeId\")\n async listVolumeLeaf(ctx: RouteContext<{ volumeId: string }>): Promise<AFSListResult> {\n const volumes = await this.getVolumes();\n if (!volumes.find((v) => v.id === ctx.params.volumeId)) {\n throw new AFSNotFoundError(joinURL(\"/storage/volumes\", ctx.params.volumeId));\n }\n return { data: [] };\n }\n\n @List(\"/docker/containers/:containerName\")\n async listContainerLeaf(ctx: RouteContext<{ containerName: string }>): Promise<AFSListResult> {\n const containers = await this.getContainers();\n if (!containers.find((c) => c.name === ctx.params.containerName)) {\n throw new AFSNotFoundError(joinURL(\"/docker/containers\", ctx.params.containerName));\n }\n return { data: [] };\n }\n\n @List(\"/docker/images/:imageName\")\n async listImageLeaf(ctx: RouteContext<{ imageName: string }>): Promise<AFSListResult> {\n const images = await this.getImages();\n if (!images.find((i) => this.sanitizeImageName(i.repository, i.tag) === ctx.params.imageName)) {\n throw new AFSNotFoundError(joinURL(\"/docker/images\", ctx.params.imageName));\n }\n return { data: [] };\n }\n\n @List(\"/shares/:shareName\")\n async listShareLeaf(ctx: RouteContext<{ shareName: string }>): Promise<AFSListResult> {\n const shares = await this.getShares();\n if (!shares.find((s) => s.name === ctx.params.shareName)) {\n throw new AFSNotFoundError(joinURL(\"/shares\", ctx.params.shareName));\n }\n return { data: [] };\n }\n\n @List(\"/packages/:packageName\")\n async listPackageLeaf(ctx: RouteContext<{ packageName: string }>): Promise<AFSListResult> {\n const packages = await this.getPackages();\n if (!packages.find((p) => p.id === ctx.params.packageName)) {\n throw new AFSNotFoundError(joinURL(\"/packages\", ctx.params.packageName));\n }\n return { data: [] };\n }\n\n @List(\"/backup/tasks/:taskName\")\n async listBackupTaskLeaf(ctx: RouteContext<{ taskName: string }>): Promise<AFSListResult> {\n const tasks = await this.getBackupTasks();\n if (!tasks.find((t) => t.name === ctx.params.taskName)) {\n throw new AFSNotFoundError(joinURL(\"/backup/tasks\", ctx.params.taskName));\n }\n return { data: [] };\n }\n\n // ========== Read Handlers ==========\n\n @Read(\"/\")\n async readRoot(_ctx: RouteContext): Promise<AFSEntry> {\n const info = await this.getSystemInfo();\n return this.buildEntry(\"/\", {\n content: `model: \"${info.model}\"\\nversion: \"${info.version}\"\\nserial: \"${info.serial}\"\\nuptime_seconds: ${info.uptime}`,\n meta: {\n kind: KINDS.NAS,\n model: info.model,\n version: info.version,\n serial: info.serial,\n childrenCount: 6,\n description: `Synology ${info.model} running DSM ${info.version}`,\n },\n });\n }\n\n @Read(\"/system\")\n async readSystem(_ctx: RouteContext): Promise<AFSEntry> {\n return this.buildEntry(\"/system\", {\n meta: {\n kind: KINDS.SYSTEM_GROUP,\n childrenCount: 3,\n description: \"System health and resource monitoring\",\n },\n });\n }\n\n @Read(\"/system/status\")\n async readSystemStatus(_ctx: RouteContext): Promise<AFSEntry> {\n const info = await this.getSystemInfo();\n return this.buildEntry(\"/system/status\", {\n content: formatSystemStatus(info),\n meta: {\n kind: KINDS.SYSTEM_INFO,\n childrenCount: 0,\n description: \"System health status summary\",\n },\n });\n }\n\n @Read(\"/system/utilization\")\n async readSystemUtilization(_ctx: RouteContext): Promise<AFSEntry> {\n const util = await this.getUtilization();\n return this.buildEntry(\"/system/utilization\", {\n content: formatSystemUtilization(util),\n meta: {\n kind: KINDS.SYSTEM_INFO,\n childrenCount: 0,\n description: \"CPU, RAM, disk I/O, network statistics\",\n },\n });\n }\n\n @Read(\"/system/hardware\")\n async readSystemHardware(_ctx: RouteContext): Promise<AFSEntry> {\n const info = await this.getSystemInfo();\n return this.buildEntry(\"/system/hardware\", {\n content: formatHardwareInfo(info),\n meta: {\n kind: KINDS.SYSTEM_INFO,\n childrenCount: 0,\n description: \"Temperature, fan speed, power status\",\n },\n });\n }\n\n @Read(\"/storage\")\n async readStorage(_ctx: RouteContext): Promise<AFSEntry> {\n return this.buildEntry(\"/storage\", {\n meta: {\n kind: KINDS.STORAGE_GROUP,\n childrenCount: 3,\n description: \"Physical disks, storage pools, and volumes\",\n },\n });\n }\n\n @Read(\"/storage/disks\")\n async readStorageDisks(_ctx: RouteContext): Promise<AFSEntry> {\n const disks = await this.getDisks();\n return this.buildEntry(\"/storage/disks\", {\n meta: { childrenCount: disks.length, description: \"Physical disk drives\" },\n });\n }\n\n @Read(\"/storage/disks/:diskId\")\n async readDisk(ctx: RouteContext<{ diskId: string }>): Promise<AFSEntry> {\n const disks = await this.getDisks();\n const disk = disks.find((d) => d.id === ctx.params.diskId);\n if (!disk) {\n throw new AFSNotFoundError(joinURL(\"/storage/disks\", ctx.params.diskId));\n }\n return this.buildEntry(joinURL(\"/storage/disks\", disk.id), {\n content: formatDiskInfo(disk),\n meta: {\n kind: KINDS.DISK,\n id: disk.id,\n childrenCount: 0,\n description: `${disk.model} - ${formatBytes(disk.size_total)} - ${disk.smart_status || disk.status}`,\n },\n });\n }\n\n @Read(\"/storage/pools\")\n async readStoragePools(_ctx: RouteContext): Promise<AFSEntry> {\n const pools = await this.getPools();\n return this.buildEntry(\"/storage/pools\", {\n meta: { childrenCount: pools.length, description: \"RAID storage pools\" },\n });\n }\n\n @Read(\"/storage/pools/:poolId\")\n async readPool(ctx: RouteContext<{ poolId: string }>): Promise<AFSEntry> {\n const pools = await this.getPools();\n const pool = pools.find((p) => p.id === ctx.params.poolId);\n if (!pool) {\n throw new AFSNotFoundError(joinURL(\"/storage/pools\", ctx.params.poolId));\n }\n return this.buildEntry(joinURL(\"/storage/pools\", pool.id), {\n content: formatPoolInfo(pool),\n meta: {\n kind: KINDS.STORAGE_POOL,\n id: pool.id,\n childrenCount: 0,\n description: `${pool.raidType || \"unknown\"} pool - ${pool.status}`,\n },\n });\n }\n\n @Read(\"/storage/volumes\")\n async readStorageVolumes(_ctx: RouteContext): Promise<AFSEntry> {\n const volumes = await this.getVolumes();\n return this.buildEntry(\"/storage/volumes\", {\n meta: { childrenCount: volumes.length, description: \"Logical volumes\" },\n });\n }\n\n @Read(\"/storage/volumes/:volumeId\")\n async readVolume(ctx: RouteContext<{ volumeId: string }>): Promise<AFSEntry> {\n const volumes = await this.getVolumes();\n const volume = volumes.find((v) => v.id === ctx.params.volumeId);\n if (!volume) {\n throw new AFSNotFoundError(joinURL(\"/storage/volumes\", ctx.params.volumeId));\n }\n const usedPercent = Math.round((volume.size.used / volume.size.total) * 100);\n return this.buildEntry(joinURL(\"/storage/volumes\", volume.id), {\n content: formatVolumeInfo(volume),\n meta: {\n kind: KINDS.VOLUME,\n id: volume.id,\n childrenCount: 0,\n description: `${volume.fs_type} - ${usedPercent}% used`,\n },\n });\n }\n\n @Read(\"/docker\")\n async readDocker(_ctx: RouteContext): Promise<AFSEntry> {\n return this.buildEntry(\"/docker\", {\n meta: {\n kind: KINDS.DOCKER_GROUP,\n childrenCount: 4,\n description: \"Docker containers, images, networks, and projects\",\n },\n });\n }\n\n @Read(\"/docker/containers\")\n async readDockerContainers(_ctx: RouteContext): Promise<AFSEntry> {\n return this.buildEntry(\"/docker/containers\", {\n meta: { childrenCount: -1, description: \"Running and stopped containers\" },\n });\n }\n\n @Read(\"/docker/containers/:containerName\")\n async readContainer(ctx: RouteContext<{ containerName: string }>): Promise<AFSEntry> {\n const containers = await this.getContainers();\n const container = containers.find((c) => c.name === ctx.params.containerName);\n if (!container) {\n throw new AFSNotFoundError(joinURL(\"/docker/containers\", ctx.params.containerName));\n }\n return this.buildEntry(joinURL(\"/docker/containers\", container.name), {\n content: formatContainerInfo(container),\n meta: {\n kind: KINDS.CONTAINER,\n id: container.name,\n childrenCount: 0,\n description: `${container.image} - ${container.status}`,\n },\n });\n }\n\n @Read(\"/docker/images\")\n async readDockerImages(_ctx: RouteContext): Promise<AFSEntry> {\n return this.buildEntry(\"/docker/images\", {\n meta: { childrenCount: -1, description: \"Local Docker images\" },\n });\n }\n\n @Read(\"/docker/images/:imageName\")\n async readImage(ctx: RouteContext<{ imageName: string }>): Promise<AFSEntry> {\n const images = await this.getImages();\n const image = images.find(\n (i) => this.sanitizeImageName(i.repository, i.tag) === ctx.params.imageName,\n );\n if (!image) {\n throw new AFSNotFoundError(joinURL(\"/docker/images\", ctx.params.imageName));\n }\n const safeName = this.sanitizeImageName(image.repository, image.tag);\n return this.buildEntry(joinURL(\"/docker/images\", safeName), {\n content: formatImageInfo(image),\n meta: {\n kind: KINDS.DOCKER_IMAGE,\n id: `${image.repository}:${image.tag}`,\n childrenCount: 0,\n },\n });\n }\n\n @Read(\"/docker/networks\")\n async readDockerNetworks(_ctx: RouteContext): Promise<AFSEntry> {\n return this.buildEntry(\"/docker/networks\", {\n meta: { childrenCount: 0, description: \"Docker networks\" },\n });\n }\n\n @Read(\"/docker/projects\")\n async readDockerProjects(_ctx: RouteContext): Promise<AFSEntry> {\n return this.buildEntry(\"/docker/projects\", {\n meta: { childrenCount: 0, description: \"Docker Compose projects (DSM 7.2+)\" },\n });\n }\n\n @Read(\"/shares\")\n async readSharesDir(_ctx: RouteContext): Promise<AFSEntry> {\n const shares = await this.getShares();\n return this.buildEntry(\"/shares\", {\n meta: { childrenCount: shares.length, description: \"Shared folders\" },\n });\n }\n\n @Read(\"/shares/:shareName\")\n async readShare(ctx: RouteContext<{ shareName: string }>): Promise<AFSEntry> {\n const shares = await this.getShares();\n const share = shares.find((s) => s.name === ctx.params.shareName);\n if (!share) {\n throw new AFSNotFoundError(joinURL(\"/shares\", ctx.params.shareName));\n }\n return this.buildEntry(joinURL(\"/shares\", share.name), {\n content: formatShareInfo(share),\n meta: {\n kind: KINDS.SHARED_FOLDER,\n id: share.name,\n childrenCount: 0,\n description: share.path,\n },\n });\n }\n\n @Read(\"/packages\")\n async readPackagesDir(_ctx: RouteContext): Promise<AFSEntry> {\n const packages = await this.getPackages();\n return this.buildEntry(\"/packages\", {\n meta: { childrenCount: packages.length, description: \"Installed DSM packages\" },\n });\n }\n\n @Read(\"/packages/:packageName\")\n async readPackage(ctx: RouteContext<{ packageName: string }>): Promise<AFSEntry> {\n const packages = await this.getPackages();\n const pkg = packages.find((p) => p.id === ctx.params.packageName);\n if (!pkg) {\n throw new AFSNotFoundError(joinURL(\"/packages\", ctx.params.packageName));\n }\n const updateStr = pkg.has_update ? \" (update available)\" : \"\";\n return this.buildEntry(joinURL(\"/packages\", pkg.id), {\n content: formatPackageInfo(pkg),\n meta: {\n kind: KINDS.PACKAGE,\n id: pkg.id,\n childrenCount: 0,\n description: `${pkg.name} v${pkg.version} - ${pkg.status}${updateStr}`,\n },\n });\n }\n\n @Read(\"/backup\")\n async readBackupDir(_ctx: RouteContext): Promise<AFSEntry> {\n return this.buildEntry(\"/backup\", {\n meta: { childrenCount: 1, description: \"Backup management\" },\n });\n }\n\n @Read(\"/backup/tasks\")\n async readBackupTasksDir(_ctx: RouteContext): Promise<AFSEntry> {\n const tasks = await this.getBackupTasks();\n return this.buildEntry(\"/backup/tasks\", {\n meta: { childrenCount: tasks.length, description: \"Hyper Backup tasks\" },\n });\n }\n\n @Read(\"/backup/tasks/:taskName\")\n async readBackupTask(ctx: RouteContext<{ taskName: string }>): Promise<AFSEntry> {\n const tasks = await this.getBackupTasks();\n const task = tasks.find((t) => t.name === ctx.params.taskName);\n if (!task) {\n throw new AFSNotFoundError(joinURL(\"/backup/tasks\", ctx.params.taskName));\n }\n const lastRunDate = task.last_run ? task.last_run.split(\"T\")[0] : \"never\";\n return this.buildEntry(joinURL(\"/backup/tasks\", task.name), {\n content: formatBackupTaskInfo(task),\n meta: {\n kind: KINDS.BACKUP_TASK,\n id: task.name,\n childrenCount: 0,\n description: `${task.status} - last run ${lastRunDate}`,\n },\n });\n }\n\n // ========== Stat Handlers ==========\n\n @Stat(\"/\")\n @Stat(\"/system\")\n @Stat(\"/system/:item\")\n @Stat(\"/storage\")\n @Stat(\"/storage/disks\")\n @Stat(\"/storage/disks/:diskId\")\n @Stat(\"/storage/pools\")\n @Stat(\"/storage/pools/:poolId\")\n @Stat(\"/storage/volumes\")\n @Stat(\"/storage/volumes/:volumeId\")\n @Stat(\"/docker\")\n @Stat(\"/docker/containers\")\n @Stat(\"/docker/containers/:containerName\")\n @Stat(\"/docker/images\")\n @Stat(\"/docker/images/:imageName\")\n @Stat(\"/docker/networks\")\n @Stat(\"/docker/projects\")\n @Stat(\"/shares\")\n @Stat(\"/shares/:shareName\")\n @Stat(\"/packages\")\n @Stat(\"/packages/:packageName\")\n @Stat(\"/backup\")\n @Stat(\"/backup/tasks\")\n @Stat(\"/backup/tasks/:taskName\")\n async statHandler(ctx: RouteContext): Promise<AFSStatResult> {\n // Use read to get the entry, then extract stat info\n const readResult = await this.read(ctx.path);\n const entry = readResult.data;\n if (!entry) {\n throw new AFSNotFoundError(ctx.path);\n }\n return {\n data: {\n id: entry.id,\n path: entry.path,\n meta: entry.meta as Record<string, unknown>,\n },\n };\n }\n\n // ========== Explain Handlers ==========\n\n @Explain(\"/\")\n async explainRoot(_ctx: RouteContext): Promise<AFSExplainResult> {\n const info = await this.getSystemInfo();\n const content = `# Synology NAS: ${info.model}\n\n- **Model**: ${info.model}\n- **DSM Version**: ${info.version}\n- **Serial**: ${info.serial}\n- **Uptime**: ${Math.floor(info.uptime / 3600)}h ${Math.floor((info.uptime % 3600) / 60)}m\n\n## Navigation\n\n- \\`/system/\\` - System health and resource monitoring\n- \\`/storage/\\` - Physical disks, storage pools, and volumes\n- \\`/docker/\\` - Docker containers, images, networks\n- \\`/shares/\\` - Shared folders\n- \\`/packages/\\` - Installed DSM packages\n- \\`/backup/\\` - Hyper Backup task management\n`;\n return { format: \"markdown\", content };\n }\n\n @Explain(\"/system\")\n async explainSystem(_ctx: RouteContext): Promise<AFSExplainResult> {\n const content = `# System Monitoring\n\nSystem health and resource monitoring for the Synology NAS.\n\n## Sub-items\n\n- \\`/system/status\\` - Overall system health (temperature, uptime)\n- \\`/system/utilization\\` - Real-time CPU, RAM, disk I/O, network stats\n- \\`/system/hardware\\` - Hardware sensors (temperature, fan speed, power)\n\nData sourced from SYNO.Core.System and SYNO.Core.System.Utilization APIs.\n`;\n return { format: \"markdown\", content };\n }\n\n @Explain(\"/storage\")\n async explainStorage(_ctx: RouteContext): Promise<AFSExplainResult> {\n const content = `# Storage Overview\n\nHierarchical view of physical storage:\n\n\\`\\`\\`\nPhysical Disks --> Storage Pools (RAID) --> Volumes (filesystem)\n\\`\\`\\`\n\n## Sub-items\n\n- \\`/storage/disks/\\` - Physical disk drives with SMART status\n- \\`/storage/pools/\\` - RAID storage pools\n- \\`/storage/volumes/\\` - Logical volumes with usage info\n\nData sourced from SYNO.Storage.CGI.Storage API.\n`;\n return { format: \"markdown\", content };\n }\n\n @Explain(\"/docker\")\n async explainDocker(_ctx: RouteContext): Promise<AFSExplainResult> {\n const containers = await this.getContainers();\n const running = containers.filter((c) => c.status === \"running\").length;\n const stopped = containers.length - running;\n const content = `# Docker Environment\n\nContainer management for the Synology NAS.\n\n- **Running containers**: ${running}\n- **Stopped containers**: ${stopped}\n\n## Sub-items\n\n- \\`/docker/containers/\\` - Container list and details\n- \\`/docker/images/\\` - Local Docker images\n- \\`/docker/networks/\\` - Docker networks\n- \\`/docker/projects/\\` - Docker Compose projects (DSM 7.2+)\n\n## Actions\n\nContainers support the following actions via exec:\n- \\`start\\` - Start a stopped container\n- \\`stop\\` - Stop a running container\n- \\`restart\\` - Restart a container\n`;\n return { format: \"markdown\", content };\n }\n\n @Explain(\"/system/:item\")\n @Explain(\"/storage/disks\")\n @Explain(\"/storage/disks/:diskId\")\n @Explain(\"/storage/pools\")\n @Explain(\"/storage/pools/:poolId\")\n @Explain(\"/storage/volumes\")\n @Explain(\"/storage/volumes/:volumeId\")\n @Explain(\"/docker/containers\")\n @Explain(\"/docker/containers/:containerName\")\n @Explain(\"/docker/images\")\n @Explain(\"/docker/images/:imageName\")\n @Explain(\"/docker/networks\")\n @Explain(\"/docker/projects\")\n @Explain(\"/shares\")\n @Explain(\"/shares/:shareName\")\n @Explain(\"/packages\")\n @Explain(\"/packages/:packageName\")\n @Explain(\"/backup\")\n @Explain(\"/backup/tasks\")\n @Explain(\"/backup/tasks/:taskName\")\n async explainGeneric(ctx: RouteContext): Promise<AFSExplainResult> {\n // Use read to get data, then format as explanation\n const readResult = await this.read(ctx.path);\n const entry = readResult.data;\n if (!entry) {\n throw new AFSNotFoundError(ctx.path);\n }\n const name = ctx.path.split(\"/\").filter(Boolean).pop() || ctx.path;\n const desc = (entry.meta?.description as string) || \"No description available\";\n const kind = (entry.meta?.kind as string) || \"unknown\";\n let content = `# ${name}\\n\\n- **Path**: \\`${ctx.path}\\`\\n- **Kind**: ${kind}\\n- **Description**: ${desc}\\n`;\n if (entry.content && typeof entry.content === \"string\") {\n content += `\\n## Data\\n\\n\\`\\`\\`yaml\\n${entry.content}\\n\\`\\`\\`\\n`;\n }\n return { format: \"markdown\", content };\n }\n\n // ========== Search Handler ==========\n\n @Search(\"/\")\n @Search(\"/:path*\")\n async searchHandler(\n ctx: RouteContext<{ path?: string }>,\n query: string,\n options?: AFSSearchOptions,\n ): Promise<AFSSearchResult> {\n const searchPath = ctx.params.path ? `/${ctx.params.path}` : \"/\";\n const limit = options?.limit ?? 100;\n const searchQuery = query.toLowerCase();\n\n // Collect all entries under searchPath via list\n const entries: AFSEntry[] = [];\n\n const collectEntries = async (listPath: string): Promise<void> => {\n try {\n const result = await this.list(listPath, { maxDepth: 10 });\n for (const entry of result.data) {\n entries.push(entry);\n }\n } catch {\n // Ignore errors during search\n }\n };\n\n await collectEntries(searchPath);\n\n // Filter by query (case-insensitive match on name, id, description, kind)\n const matched = entries.filter((entry) => {\n if (!searchQuery) return true;\n const name = entry.path.split(\"/\").filter(Boolean).pop() || \"\";\n const id = String(entry.meta?.id || entry.id || \"\");\n const description = String(entry.meta?.description || \"\");\n const kind = String(entry.meta?.kind || \"\");\n const searchFields = [name, id, description, kind].join(\" \").toLowerCase();\n return searchFields.includes(searchQuery);\n });\n\n return {\n data: matched.slice(0, limit),\n };\n }\n\n // ========== Docker Container Actions (Phase 2) ==========\n\n @Actions(\"/docker/containers/:containerName\")\n async listContainerActions(ctx: RouteContext<{ containerName: string }>): Promise<AFSListResult> {\n const containers = await this.getContainers();\n const container = containers.find((c) => c.name === ctx.params.containerName);\n if (!container) {\n throw new AFSNotFoundError(joinURL(\"/docker/containers\", ctx.params.containerName));\n }\n\n const actions = [\n {\n id: \"start\",\n path: joinURL(ctx.path, \"start\"),\n summary: \"Start the container\",\n meta: {\n kind: \"afs:executable\",\n kinds: [\"afs:executable\", \"afs:node\"],\n severity: \"boundary\",\n inputSchema: { type: \"object\", properties: {} },\n },\n },\n {\n id: \"stop\",\n path: joinURL(ctx.path, \"stop\"),\n summary: \"Stop the container\",\n meta: {\n kind: \"afs:executable\",\n kinds: [\"afs:executable\", \"afs:node\"],\n severity: \"boundary\",\n inputSchema: { type: \"object\", properties: {} },\n },\n },\n {\n id: \"restart\",\n path: joinURL(ctx.path, \"restart\"),\n summary: \"Restart the container\",\n meta: {\n kind: \"afs:executable\",\n kinds: [\"afs:executable\", \"afs:node\"],\n severity: \"boundary\",\n inputSchema: { type: \"object\", properties: {} },\n },\n },\n ];\n\n return { data: actions };\n }\n\n @Actions.Exec(\"/docker/containers/:containerName\", \"start\")\n async startContainerAction(\n ctx: RouteContext<{ containerName: string }>,\n _args: Record<string, unknown>,\n ): Promise<AFSExecResult> {\n const containers = await this.getContainers();\n const container = containers.find((c) => c.name === ctx.params.containerName);\n if (!container) {\n throw new AFSNotFoundError(joinURL(\"/docker/containers\", ctx.params.containerName));\n }\n\n try {\n await this.client.request({\n api: \"SYNO.Docker.Container\",\n method: \"start\",\n version: 1,\n extra: { name: ctx.params.containerName },\n });\n } catch (error) {\n if (error instanceof AFSError) {\n return {\n success: false,\n error: { code: \"CONTAINER_ERROR\", message: error.message },\n };\n }\n throw error;\n }\n\n this.invalidateContainerCache();\n return {\n success: true,\n data: { container: ctx.params.containerName, action: \"start\", status: \"running\" },\n };\n }\n\n @Actions.Exec(\"/docker/containers/:containerName\", \"stop\")\n async stopContainerAction(\n ctx: RouteContext<{ containerName: string }>,\n _args: Record<string, unknown>,\n ): Promise<AFSExecResult> {\n const containers = await this.getContainers();\n const container = containers.find((c) => c.name === ctx.params.containerName);\n if (!container) {\n throw new AFSNotFoundError(joinURL(\"/docker/containers\", ctx.params.containerName));\n }\n\n try {\n await this.client.request({\n api: \"SYNO.Docker.Container\",\n method: \"stop\",\n version: 1,\n extra: { name: ctx.params.containerName },\n });\n } catch (error) {\n if (error instanceof AFSError) {\n return {\n success: false,\n error: { code: \"CONTAINER_ERROR\", message: error.message },\n };\n }\n throw error;\n }\n\n this.invalidateContainerCache();\n return {\n success: true,\n data: { container: ctx.params.containerName, action: \"stop\", status: \"stopped\" },\n };\n }\n\n @Actions.Exec(\"/docker/containers/:containerName\", \"restart\")\n async restartContainerAction(\n ctx: RouteContext<{ containerName: string }>,\n _args: Record<string, unknown>,\n ): Promise<AFSExecResult> {\n const containers = await this.getContainers();\n const container = containers.find((c) => c.name === ctx.params.containerName);\n if (!container) {\n throw new AFSNotFoundError(joinURL(\"/docker/containers\", ctx.params.containerName));\n }\n\n try {\n await this.client.request({\n api: \"SYNO.Docker.Container\",\n method: \"restart\",\n version: 1,\n extra: { name: ctx.params.containerName },\n });\n } catch (error) {\n if (error instanceof AFSError) {\n return {\n success: false,\n error: { code: \"CONTAINER_ERROR\", message: error.message },\n };\n }\n throw error;\n }\n\n this.invalidateContainerCache();\n return {\n success: true,\n data: { container: ctx.params.containerName, action: \"restart\", status: \"running\" },\n };\n }\n\n // ========== Backup Task Actions (Phase 3) ==========\n\n @Actions(\"/backup/tasks/:taskName\")\n async listBackupTaskActions(ctx: RouteContext<{ taskName: string }>): Promise<AFSListResult> {\n const tasks = await this.getBackupTasks();\n const task = tasks.find((t) => t.name === ctx.params.taskName);\n if (!task) {\n throw new AFSNotFoundError(joinURL(\"/backup/tasks\", ctx.params.taskName));\n }\n\n return {\n data: [\n {\n id: \"run\",\n path: joinURL(ctx.path, \"run\"),\n summary: \"Trigger backup execution\",\n meta: {\n kind: \"afs:executable\",\n kinds: [\"afs:executable\", \"afs:node\"],\n severity: \"boundary\",\n inputSchema: { type: \"object\", properties: {} },\n },\n },\n ],\n };\n }\n\n @Actions.Exec(\"/backup/tasks/:taskName\", \"run\")\n async runBackupTaskAction(\n ctx: RouteContext<{ taskName: string }>,\n _args: Record<string, unknown>,\n ): Promise<AFSExecResult> {\n const tasks = await this.getBackupTasks();\n const task = tasks.find((t) => t.name === ctx.params.taskName);\n if (!task) {\n throw new AFSNotFoundError(joinURL(\"/backup/tasks\", ctx.params.taskName));\n }\n\n try {\n await this.client.request({\n api: \"SYNO.Backup.Task\",\n method: \"run\",\n version: 1,\n extra: { name: ctx.params.taskName },\n });\n } catch (error) {\n if (error instanceof AFSError) {\n return {\n success: false,\n error: { code: \"BACKUP_ERROR\", message: error.message },\n };\n }\n throw error;\n }\n\n this.invalidateBackupTaskCache();\n return {\n success: true,\n data: { task: ctx.params.taskName, action: \"run\", status: \"running\" },\n };\n }\n\n // ========== Package Actions (Phase 3) ==========\n\n @Actions(\"/packages/:packageName\")\n async listPackageActions(ctx: RouteContext<{ packageName: string }>): Promise<AFSListResult> {\n const packages = await this.getPackages();\n const pkg = packages.find((p) => p.id === ctx.params.packageName);\n if (!pkg) {\n throw new AFSNotFoundError(joinURL(\"/packages\", ctx.params.packageName));\n }\n\n return {\n data: [\n {\n id: \"start\",\n path: joinURL(ctx.path, \"start\"),\n summary: \"Start the package\",\n meta: {\n kind: \"afs:executable\",\n kinds: [\"afs:executable\", \"afs:node\"],\n severity: \"boundary\",\n inputSchema: { type: \"object\", properties: {} },\n },\n },\n {\n id: \"stop\",\n path: joinURL(ctx.path, \"stop\"),\n summary: \"Stop the package\",\n meta: {\n kind: \"afs:executable\",\n kinds: [\"afs:executable\", \"afs:node\"],\n severity: \"boundary\",\n inputSchema: { type: \"object\", properties: {} },\n },\n },\n ],\n };\n }\n\n @Actions.Exec(\"/packages/:packageName\", \"start\")\n async startPackageAction(\n ctx: RouteContext<{ packageName: string }>,\n _args: Record<string, unknown>,\n ): Promise<AFSExecResult> {\n const packages = await this.getPackages();\n const pkg = packages.find((p) => p.id === ctx.params.packageName);\n if (!pkg) {\n throw new AFSNotFoundError(joinURL(\"/packages\", ctx.params.packageName));\n }\n\n try {\n await this.client.request({\n api: \"SYNO.Core.Package\",\n method: \"start\",\n version: 1,\n extra: { id: ctx.params.packageName },\n });\n } catch (error) {\n if (error instanceof AFSError) {\n return {\n success: false,\n error: { code: \"PACKAGE_ERROR\", message: error.message },\n };\n }\n throw error;\n }\n\n this.invalidatePackageCache();\n return {\n success: true,\n data: { package: ctx.params.packageName, action: \"start\", status: \"running\" },\n };\n }\n\n @Actions.Exec(\"/packages/:packageName\", \"stop\")\n async stopPackageAction(\n ctx: RouteContext<{ packageName: string }>,\n _args: Record<string, unknown>,\n ): Promise<AFSExecResult> {\n const packages = await this.getPackages();\n const pkg = packages.find((p) => p.id === ctx.params.packageName);\n if (!pkg) {\n throw new AFSNotFoundError(joinURL(\"/packages\", ctx.params.packageName));\n }\n\n try {\n await this.client.request({\n api: \"SYNO.Core.Package\",\n method: \"stop\",\n version: 1,\n extra: { id: ctx.params.packageName },\n });\n } catch (error) {\n if (error instanceof AFSError) {\n return {\n success: false,\n error: { code: \"PACKAGE_ERROR\", message: error.message },\n };\n }\n throw error;\n }\n\n this.invalidatePackageCache();\n return {\n success: true,\n data: { package: ctx.params.packageName, action: \"stop\", status: \"stopped\" },\n };\n }\n\n // ========== Lifecycle ==========\n\n async destroy(): Promise<void> {\n await this.client.destroy();\n }\n}\n"],"mappings":"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"}
|
package/dist/types.cjs
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
let zod = require("zod");
|
|
2
|
+
|
|
3
|
+
//#region src/types.ts
|
|
4
|
+
/**
|
|
5
|
+
* Synology AFS Provider - Types and Configuration Schema
|
|
6
|
+
*/
|
|
7
|
+
/** Provider kind constant */
|
|
8
|
+
const PROVIDER_KIND = "synology";
|
|
9
|
+
/** Synology API base path */
|
|
10
|
+
const API_BASE_PATH = "/webapi/entry.cgi";
|
|
11
|
+
/** meta.kind taxonomy for different node types */
|
|
12
|
+
const KINDS = {
|
|
13
|
+
NAS: "nas:root",
|
|
14
|
+
SYSTEM_GROUP: "nas:system-group",
|
|
15
|
+
SYSTEM_INFO: "nas:system-info",
|
|
16
|
+
STORAGE_GROUP: "nas:storage-group",
|
|
17
|
+
DISK: "nas:disk",
|
|
18
|
+
STORAGE_POOL: "nas:storage-pool",
|
|
19
|
+
VOLUME: "nas:volume",
|
|
20
|
+
DOCKER_GROUP: "nas:docker-group",
|
|
21
|
+
CONTAINER: "nas:container",
|
|
22
|
+
DOCKER_IMAGE: "nas:docker-image",
|
|
23
|
+
SHARED_FOLDER: "nas:shared-folder",
|
|
24
|
+
PACKAGE: "nas:package",
|
|
25
|
+
BACKUP_TASK: "nas:backup-task"
|
|
26
|
+
};
|
|
27
|
+
/** Configuration schema for AFSSynology */
|
|
28
|
+
const AFSSynologyConfigSchema = zod.z.object({
|
|
29
|
+
url: zod.z.string().describe("Synology DSM URL (e.g., https://192.168.1.50:5001)"),
|
|
30
|
+
account: zod.z.string().describe("DSM admin username"),
|
|
31
|
+
password: zod.z.string().describe("DSM password"),
|
|
32
|
+
otpCode: zod.z.string().optional().describe("2FA OTP code (first login only)"),
|
|
33
|
+
deviceId: zod.z.string().optional().describe("Persisted 2FA device_id"),
|
|
34
|
+
deviceIdPath: zod.z.string().optional().describe("File path to persist device_id"),
|
|
35
|
+
verifySsl: zod.z.boolean().default(false).describe("Verify HTTPS certificate (false for self-signed)"),
|
|
36
|
+
name: zod.z.string().optional().describe("Provider name override"),
|
|
37
|
+
description: zod.z.string().optional().describe("Provider description override")
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
//#endregion
|
|
41
|
+
exports.AFSSynologyConfigSchema = AFSSynologyConfigSchema;
|
|
42
|
+
exports.API_BASE_PATH = API_BASE_PATH;
|
|
43
|
+
exports.KINDS = KINDS;
|
|
44
|
+
exports.PROVIDER_KIND = PROVIDER_KIND;
|
package/dist/types.d.cts
ADDED
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
|
|
3
|
+
//#region src/types.d.ts
|
|
4
|
+
/** Provider kind constant */
|
|
5
|
+
declare const PROVIDER_KIND: "synology";
|
|
6
|
+
/** Synology API base path */
|
|
7
|
+
declare const API_BASE_PATH = "/webapi/entry.cgi";
|
|
8
|
+
/** meta.kind taxonomy for different node types */
|
|
9
|
+
declare const KINDS: {
|
|
10
|
+
readonly NAS: "nas:root";
|
|
11
|
+
readonly SYSTEM_GROUP: "nas:system-group";
|
|
12
|
+
readonly SYSTEM_INFO: "nas:system-info";
|
|
13
|
+
readonly STORAGE_GROUP: "nas:storage-group";
|
|
14
|
+
readonly DISK: "nas:disk";
|
|
15
|
+
readonly STORAGE_POOL: "nas:storage-pool";
|
|
16
|
+
readonly VOLUME: "nas:volume";
|
|
17
|
+
readonly DOCKER_GROUP: "nas:docker-group";
|
|
18
|
+
readonly CONTAINER: "nas:container";
|
|
19
|
+
readonly DOCKER_IMAGE: "nas:docker-image";
|
|
20
|
+
readonly SHARED_FOLDER: "nas:shared-folder";
|
|
21
|
+
readonly PACKAGE: "nas:package";
|
|
22
|
+
readonly BACKUP_TASK: "nas:backup-task";
|
|
23
|
+
};
|
|
24
|
+
/** Configuration schema for AFSSynology */
|
|
25
|
+
declare const AFSSynologyConfigSchema: z.ZodObject<{
|
|
26
|
+
url: z.ZodString;
|
|
27
|
+
account: z.ZodString;
|
|
28
|
+
password: z.ZodString;
|
|
29
|
+
otpCode: z.ZodOptional<z.ZodString>;
|
|
30
|
+
deviceId: z.ZodOptional<z.ZodString>;
|
|
31
|
+
deviceIdPath: z.ZodOptional<z.ZodString>;
|
|
32
|
+
verifySsl: z.ZodDefault<z.ZodBoolean>;
|
|
33
|
+
name: z.ZodOptional<z.ZodString>;
|
|
34
|
+
description: z.ZodOptional<z.ZodString>;
|
|
35
|
+
}, z.core.$strip>;
|
|
36
|
+
type AFSSynologyConfig = z.infer<typeof AFSSynologyConfigSchema>;
|
|
37
|
+
/** Synology API response wrapper */
|
|
38
|
+
interface SynoApiResponse<T = unknown> {
|
|
39
|
+
success: boolean;
|
|
40
|
+
data?: T;
|
|
41
|
+
error?: {
|
|
42
|
+
code: number;
|
|
43
|
+
errors?: unknown;
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
/** Synology API Info entry */
|
|
47
|
+
interface SynoApiInfoEntry {
|
|
48
|
+
path: string;
|
|
49
|
+
minVersion: number;
|
|
50
|
+
maxVersion: number;
|
|
51
|
+
requestFormat?: string;
|
|
52
|
+
}
|
|
53
|
+
/** Synology system info response data */
|
|
54
|
+
interface SynoSystemInfo {
|
|
55
|
+
model: string;
|
|
56
|
+
ram: number;
|
|
57
|
+
serial: string;
|
|
58
|
+
temperature: number;
|
|
59
|
+
uptime: number;
|
|
60
|
+
version: string;
|
|
61
|
+
version_string?: string;
|
|
62
|
+
}
|
|
63
|
+
/** Synology system utilization response data */
|
|
64
|
+
interface SynoSystemUtilization {
|
|
65
|
+
cpu: {
|
|
66
|
+
current_load: number;
|
|
67
|
+
other_load?: number;
|
|
68
|
+
system_load?: number;
|
|
69
|
+
user_load?: number;
|
|
70
|
+
};
|
|
71
|
+
memory: {
|
|
72
|
+
total_real: number;
|
|
73
|
+
avail_real: number;
|
|
74
|
+
total_swap?: number;
|
|
75
|
+
avail_swap?: number;
|
|
76
|
+
real_usage?: number;
|
|
77
|
+
buffer?: number;
|
|
78
|
+
cached?: number;
|
|
79
|
+
};
|
|
80
|
+
network?: Array<{
|
|
81
|
+
device: string;
|
|
82
|
+
rx: number;
|
|
83
|
+
tx: number;
|
|
84
|
+
}>;
|
|
85
|
+
disk?: Array<{
|
|
86
|
+
device: string;
|
|
87
|
+
read_access?: number;
|
|
88
|
+
write_access?: number;
|
|
89
|
+
}>;
|
|
90
|
+
}
|
|
91
|
+
/** Synology storage info */
|
|
92
|
+
interface SynoStorageInfo {
|
|
93
|
+
disks: SynoDiskInfo[];
|
|
94
|
+
volumes: SynoVolumeInfo[];
|
|
95
|
+
storagePools: SynoStoragePoolInfo[];
|
|
96
|
+
}
|
|
97
|
+
interface SynoDiskInfo {
|
|
98
|
+
id: string;
|
|
99
|
+
device?: string;
|
|
100
|
+
model: string;
|
|
101
|
+
vendor?: string;
|
|
102
|
+
size_total: number;
|
|
103
|
+
temp: number;
|
|
104
|
+
status: string;
|
|
105
|
+
smart_status?: string;
|
|
106
|
+
exceeded_bad_sector_thresh?: boolean;
|
|
107
|
+
below_remaining_life_thresh?: boolean;
|
|
108
|
+
firmware?: string;
|
|
109
|
+
diskType?: string;
|
|
110
|
+
}
|
|
111
|
+
interface SynoVolumeInfo {
|
|
112
|
+
id: string;
|
|
113
|
+
size: {
|
|
114
|
+
total: number;
|
|
115
|
+
used: number;
|
|
116
|
+
};
|
|
117
|
+
fs_type: string;
|
|
118
|
+
status: string;
|
|
119
|
+
deploy_path?: string;
|
|
120
|
+
}
|
|
121
|
+
interface SynoStoragePoolInfo {
|
|
122
|
+
id: string;
|
|
123
|
+
raidType?: string;
|
|
124
|
+
status: string;
|
|
125
|
+
disks?: string[];
|
|
126
|
+
}
|
|
127
|
+
/** Docker container info */
|
|
128
|
+
interface SynoContainerInfo {
|
|
129
|
+
name: string;
|
|
130
|
+
id?: string;
|
|
131
|
+
image: string;
|
|
132
|
+
status: string;
|
|
133
|
+
state?: string;
|
|
134
|
+
uptime?: string;
|
|
135
|
+
ports?: string[];
|
|
136
|
+
cpu_percent?: number;
|
|
137
|
+
memory_usage_mb?: number;
|
|
138
|
+
memory_limit_mb?: number;
|
|
139
|
+
}
|
|
140
|
+
/** Docker image info */
|
|
141
|
+
interface SynoImageInfo {
|
|
142
|
+
repository: string;
|
|
143
|
+
tag: string;
|
|
144
|
+
size: number;
|
|
145
|
+
created?: string;
|
|
146
|
+
}
|
|
147
|
+
/** Shared folder info */
|
|
148
|
+
interface SynoShareInfo {
|
|
149
|
+
name: string;
|
|
150
|
+
path: string;
|
|
151
|
+
quota?: number;
|
|
152
|
+
encrypted?: boolean;
|
|
153
|
+
desc?: string;
|
|
154
|
+
}
|
|
155
|
+
/** Package info */
|
|
156
|
+
interface SynoPackageInfo {
|
|
157
|
+
id: string;
|
|
158
|
+
name: string;
|
|
159
|
+
version: string;
|
|
160
|
+
status: string;
|
|
161
|
+
has_update?: boolean;
|
|
162
|
+
desc?: string;
|
|
163
|
+
}
|
|
164
|
+
/** Backup task info */
|
|
165
|
+
interface SynoBackupTaskInfo {
|
|
166
|
+
name: string;
|
|
167
|
+
status: string;
|
|
168
|
+
last_run?: string;
|
|
169
|
+
next_run?: string;
|
|
170
|
+
size?: number;
|
|
171
|
+
}
|
|
172
|
+
//#endregion
|
|
173
|
+
export { AFSSynologyConfig, AFSSynologyConfigSchema, API_BASE_PATH, KINDS, PROVIDER_KIND, SynoApiInfoEntry, SynoApiResponse, SynoBackupTaskInfo, SynoContainerInfo, SynoDiskInfo, SynoImageInfo, SynoPackageInfo, SynoShareInfo, SynoStorageInfo, SynoStoragePoolInfo, SynoSystemInfo, SynoSystemUtilization, SynoVolumeInfo };
|
|
174
|
+
//# sourceMappingURL=types.d.cts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.cts","names":[],"sources":["../src/types.ts"],"mappings":";;;;cAOa,aAAA;;cAGA,aAAA;AAAb;AAAA,cAGa,KAAA;EAAA;;;;;;;;;;;;;;;cAiBA,uBAAA,EAAuB,CAAA,CAAA,SAAA;;;;;;;;;;;KAexB,iBAAA,GAAoB,CAAA,CAAE,KAAA,QAAa,uBAAA;;UAG9B,eAAA;EACf,OAAA;EACA,IAAA,GAAO,CAAA;EACP,KAAA;IACE,IAAA;IACA,MAAA;EAAA;AAAA;;UAKa,gBAAA;EACf,IAAA;EACA,UAAA;EACA,UAAA;EACA,aAAA;AAAA;;UAIe,cAAA;EACf,KAAA;EACA,GAAA;EACA,MAAA;EACA,WAAA;EACA,MAAA;EACA,OAAA;EACA,cAAA;AAAA;;UAIe,qBAAA;EACf,GAAA;IAAO,YAAA;IAAsB,UAAA;IAAqB,WAAA;IAAsB,SAAA;EAAA;EACxE,MAAA;IACE,UAAA;IACA,UAAA;IACA,UAAA;IACA,UAAA;IACA,UAAA;IACA,MAAA;IACA,MAAA;EAAA;EAEF,OAAA,GAAU,KAAA;IAAQ,MAAA;IAAgB,EAAA;IAAY,EAAA;EAAA;EAC9C,IAAA,GAAO,KAAA;IAAQ,MAAA;IAAgB,WAAA;IAAsB,YAAA;EAAA;AAAA;;UAItC,eAAA;EACf,KAAA,EAAO,YAAA;EACP,OAAA,EAAS,cAAA;EACT,YAAA,EAAc,mBAAA;AAAA;AAAA,UAGC,YAAA;EACf,EAAA;EACA,MAAA;EACA,KAAA;EACA,MAAA;EACA,UAAA;EACA,IAAA;EACA,MAAA;EACA,YAAA;EACA,0BAAA;EACA,2BAAA;EACA,QAAA;EACA,QAAA;AAAA;AAAA,UAGe,cAAA;EACf,EAAA;EACA,IAAA;IAAQ,KAAA;IAAe,IAAA;EAAA;EACvB,OAAA;EACA,MAAA;EACA,WAAA;AAAA;AAAA,UAGe,mBAAA;EACf,EAAA;EACA,QAAA;EACA,MAAA;EACA,KAAA;AAAA;;UAIe,iBAAA;EACf,IAAA;EACA,EAAA;EACA,KAAA;EACA,MAAA;EACA,KAAA;EACA,MAAA;EACA,KAAA;EACA,WAAA;EACA,eAAA;EACA,eAAA;AAAA;;UAIe,aAAA;EACf,UAAA;EACA,GAAA;EACA,IAAA;EACA,OAAA;AAAA;;UAIe,aAAA;EACf,IAAA;EACA,IAAA;EACA,KAAA;EACA,SAAA;EACA,IAAA;AAAA;;UAIe,eAAA;EACf,EAAA;EACA,IAAA;EACA,OAAA;EACA,MAAA;EACA,UAAA;EACA,IAAA;AAAA;;UAIe,kBAAA;EACf,IAAA;EACA,MAAA;EACA,QAAA;EACA,QAAA;EACA,IAAA;AAAA"}
|
package/dist/types.d.mts
ADDED
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
|
|
3
|
+
//#region src/types.d.ts
|
|
4
|
+
/** Provider kind constant */
|
|
5
|
+
declare const PROVIDER_KIND: "synology";
|
|
6
|
+
/** Synology API base path */
|
|
7
|
+
declare const API_BASE_PATH = "/webapi/entry.cgi";
|
|
8
|
+
/** meta.kind taxonomy for different node types */
|
|
9
|
+
declare const KINDS: {
|
|
10
|
+
readonly NAS: "nas:root";
|
|
11
|
+
readonly SYSTEM_GROUP: "nas:system-group";
|
|
12
|
+
readonly SYSTEM_INFO: "nas:system-info";
|
|
13
|
+
readonly STORAGE_GROUP: "nas:storage-group";
|
|
14
|
+
readonly DISK: "nas:disk";
|
|
15
|
+
readonly STORAGE_POOL: "nas:storage-pool";
|
|
16
|
+
readonly VOLUME: "nas:volume";
|
|
17
|
+
readonly DOCKER_GROUP: "nas:docker-group";
|
|
18
|
+
readonly CONTAINER: "nas:container";
|
|
19
|
+
readonly DOCKER_IMAGE: "nas:docker-image";
|
|
20
|
+
readonly SHARED_FOLDER: "nas:shared-folder";
|
|
21
|
+
readonly PACKAGE: "nas:package";
|
|
22
|
+
readonly BACKUP_TASK: "nas:backup-task";
|
|
23
|
+
};
|
|
24
|
+
/** Configuration schema for AFSSynology */
|
|
25
|
+
declare const AFSSynologyConfigSchema: z.ZodObject<{
|
|
26
|
+
url: z.ZodString;
|
|
27
|
+
account: z.ZodString;
|
|
28
|
+
password: z.ZodString;
|
|
29
|
+
otpCode: z.ZodOptional<z.ZodString>;
|
|
30
|
+
deviceId: z.ZodOptional<z.ZodString>;
|
|
31
|
+
deviceIdPath: z.ZodOptional<z.ZodString>;
|
|
32
|
+
verifySsl: z.ZodDefault<z.ZodBoolean>;
|
|
33
|
+
name: z.ZodOptional<z.ZodString>;
|
|
34
|
+
description: z.ZodOptional<z.ZodString>;
|
|
35
|
+
}, z.core.$strip>;
|
|
36
|
+
type AFSSynologyConfig = z.infer<typeof AFSSynologyConfigSchema>;
|
|
37
|
+
/** Synology API response wrapper */
|
|
38
|
+
interface SynoApiResponse<T = unknown> {
|
|
39
|
+
success: boolean;
|
|
40
|
+
data?: T;
|
|
41
|
+
error?: {
|
|
42
|
+
code: number;
|
|
43
|
+
errors?: unknown;
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
/** Synology API Info entry */
|
|
47
|
+
interface SynoApiInfoEntry {
|
|
48
|
+
path: string;
|
|
49
|
+
minVersion: number;
|
|
50
|
+
maxVersion: number;
|
|
51
|
+
requestFormat?: string;
|
|
52
|
+
}
|
|
53
|
+
/** Synology system info response data */
|
|
54
|
+
interface SynoSystemInfo {
|
|
55
|
+
model: string;
|
|
56
|
+
ram: number;
|
|
57
|
+
serial: string;
|
|
58
|
+
temperature: number;
|
|
59
|
+
uptime: number;
|
|
60
|
+
version: string;
|
|
61
|
+
version_string?: string;
|
|
62
|
+
}
|
|
63
|
+
/** Synology system utilization response data */
|
|
64
|
+
interface SynoSystemUtilization {
|
|
65
|
+
cpu: {
|
|
66
|
+
current_load: number;
|
|
67
|
+
other_load?: number;
|
|
68
|
+
system_load?: number;
|
|
69
|
+
user_load?: number;
|
|
70
|
+
};
|
|
71
|
+
memory: {
|
|
72
|
+
total_real: number;
|
|
73
|
+
avail_real: number;
|
|
74
|
+
total_swap?: number;
|
|
75
|
+
avail_swap?: number;
|
|
76
|
+
real_usage?: number;
|
|
77
|
+
buffer?: number;
|
|
78
|
+
cached?: number;
|
|
79
|
+
};
|
|
80
|
+
network?: Array<{
|
|
81
|
+
device: string;
|
|
82
|
+
rx: number;
|
|
83
|
+
tx: number;
|
|
84
|
+
}>;
|
|
85
|
+
disk?: Array<{
|
|
86
|
+
device: string;
|
|
87
|
+
read_access?: number;
|
|
88
|
+
write_access?: number;
|
|
89
|
+
}>;
|
|
90
|
+
}
|
|
91
|
+
/** Synology storage info */
|
|
92
|
+
interface SynoStorageInfo {
|
|
93
|
+
disks: SynoDiskInfo[];
|
|
94
|
+
volumes: SynoVolumeInfo[];
|
|
95
|
+
storagePools: SynoStoragePoolInfo[];
|
|
96
|
+
}
|
|
97
|
+
interface SynoDiskInfo {
|
|
98
|
+
id: string;
|
|
99
|
+
device?: string;
|
|
100
|
+
model: string;
|
|
101
|
+
vendor?: string;
|
|
102
|
+
size_total: number;
|
|
103
|
+
temp: number;
|
|
104
|
+
status: string;
|
|
105
|
+
smart_status?: string;
|
|
106
|
+
exceeded_bad_sector_thresh?: boolean;
|
|
107
|
+
below_remaining_life_thresh?: boolean;
|
|
108
|
+
firmware?: string;
|
|
109
|
+
diskType?: string;
|
|
110
|
+
}
|
|
111
|
+
interface SynoVolumeInfo {
|
|
112
|
+
id: string;
|
|
113
|
+
size: {
|
|
114
|
+
total: number;
|
|
115
|
+
used: number;
|
|
116
|
+
};
|
|
117
|
+
fs_type: string;
|
|
118
|
+
status: string;
|
|
119
|
+
deploy_path?: string;
|
|
120
|
+
}
|
|
121
|
+
interface SynoStoragePoolInfo {
|
|
122
|
+
id: string;
|
|
123
|
+
raidType?: string;
|
|
124
|
+
status: string;
|
|
125
|
+
disks?: string[];
|
|
126
|
+
}
|
|
127
|
+
/** Docker container info */
|
|
128
|
+
interface SynoContainerInfo {
|
|
129
|
+
name: string;
|
|
130
|
+
id?: string;
|
|
131
|
+
image: string;
|
|
132
|
+
status: string;
|
|
133
|
+
state?: string;
|
|
134
|
+
uptime?: string;
|
|
135
|
+
ports?: string[];
|
|
136
|
+
cpu_percent?: number;
|
|
137
|
+
memory_usage_mb?: number;
|
|
138
|
+
memory_limit_mb?: number;
|
|
139
|
+
}
|
|
140
|
+
/** Docker image info */
|
|
141
|
+
interface SynoImageInfo {
|
|
142
|
+
repository: string;
|
|
143
|
+
tag: string;
|
|
144
|
+
size: number;
|
|
145
|
+
created?: string;
|
|
146
|
+
}
|
|
147
|
+
/** Shared folder info */
|
|
148
|
+
interface SynoShareInfo {
|
|
149
|
+
name: string;
|
|
150
|
+
path: string;
|
|
151
|
+
quota?: number;
|
|
152
|
+
encrypted?: boolean;
|
|
153
|
+
desc?: string;
|
|
154
|
+
}
|
|
155
|
+
/** Package info */
|
|
156
|
+
interface SynoPackageInfo {
|
|
157
|
+
id: string;
|
|
158
|
+
name: string;
|
|
159
|
+
version: string;
|
|
160
|
+
status: string;
|
|
161
|
+
has_update?: boolean;
|
|
162
|
+
desc?: string;
|
|
163
|
+
}
|
|
164
|
+
/** Backup task info */
|
|
165
|
+
interface SynoBackupTaskInfo {
|
|
166
|
+
name: string;
|
|
167
|
+
status: string;
|
|
168
|
+
last_run?: string;
|
|
169
|
+
next_run?: string;
|
|
170
|
+
size?: number;
|
|
171
|
+
}
|
|
172
|
+
//#endregion
|
|
173
|
+
export { AFSSynologyConfig, AFSSynologyConfigSchema, API_BASE_PATH, KINDS, PROVIDER_KIND, SynoApiInfoEntry, SynoApiResponse, SynoBackupTaskInfo, SynoContainerInfo, SynoDiskInfo, SynoImageInfo, SynoPackageInfo, SynoShareInfo, SynoStorageInfo, SynoStoragePoolInfo, SynoSystemInfo, SynoSystemUtilization, SynoVolumeInfo };
|
|
174
|
+
//# sourceMappingURL=types.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.mts","names":[],"sources":["../src/types.ts"],"mappings":";;;;cAOa,aAAA;;cAGA,aAAA;AAAb;AAAA,cAGa,KAAA;EAAA;;;;;;;;;;;;;;;cAiBA,uBAAA,EAAuB,CAAA,CAAA,SAAA;;;;;;;;;;;KAexB,iBAAA,GAAoB,CAAA,CAAE,KAAA,QAAa,uBAAA;;UAG9B,eAAA;EACf,OAAA;EACA,IAAA,GAAO,CAAA;EACP,KAAA;IACE,IAAA;IACA,MAAA;EAAA;AAAA;;UAKa,gBAAA;EACf,IAAA;EACA,UAAA;EACA,UAAA;EACA,aAAA;AAAA;;UAIe,cAAA;EACf,KAAA;EACA,GAAA;EACA,MAAA;EACA,WAAA;EACA,MAAA;EACA,OAAA;EACA,cAAA;AAAA;;UAIe,qBAAA;EACf,GAAA;IAAO,YAAA;IAAsB,UAAA;IAAqB,WAAA;IAAsB,SAAA;EAAA;EACxE,MAAA;IACE,UAAA;IACA,UAAA;IACA,UAAA;IACA,UAAA;IACA,UAAA;IACA,MAAA;IACA,MAAA;EAAA;EAEF,OAAA,GAAU,KAAA;IAAQ,MAAA;IAAgB,EAAA;IAAY,EAAA;EAAA;EAC9C,IAAA,GAAO,KAAA;IAAQ,MAAA;IAAgB,WAAA;IAAsB,YAAA;EAAA;AAAA;;UAItC,eAAA;EACf,KAAA,EAAO,YAAA;EACP,OAAA,EAAS,cAAA;EACT,YAAA,EAAc,mBAAA;AAAA;AAAA,UAGC,YAAA;EACf,EAAA;EACA,MAAA;EACA,KAAA;EACA,MAAA;EACA,UAAA;EACA,IAAA;EACA,MAAA;EACA,YAAA;EACA,0BAAA;EACA,2BAAA;EACA,QAAA;EACA,QAAA;AAAA;AAAA,UAGe,cAAA;EACf,EAAA;EACA,IAAA;IAAQ,KAAA;IAAe,IAAA;EAAA;EACvB,OAAA;EACA,MAAA;EACA,WAAA;AAAA;AAAA,UAGe,mBAAA;EACf,EAAA;EACA,QAAA;EACA,MAAA;EACA,KAAA;AAAA;;UAIe,iBAAA;EACf,IAAA;EACA,EAAA;EACA,KAAA;EACA,MAAA;EACA,KAAA;EACA,MAAA;EACA,KAAA;EACA,WAAA;EACA,eAAA;EACA,eAAA;AAAA;;UAIe,aAAA;EACf,UAAA;EACA,GAAA;EACA,IAAA;EACA,OAAA;AAAA;;UAIe,aAAA;EACf,IAAA;EACA,IAAA;EACA,KAAA;EACA,SAAA;EACA,IAAA;AAAA;;UAIe,eAAA;EACf,EAAA;EACA,IAAA;EACA,OAAA;EACA,MAAA;EACA,UAAA;EACA,IAAA;AAAA;;UAIe,kBAAA;EACf,IAAA;EACA,MAAA;EACA,QAAA;EACA,QAAA;EACA,IAAA;AAAA"}
|