ug-file
v0.3.1
Published
Unofficial SDK for UGOS Pro file management APIs.
Downloads
734
Maintainers
Readme
ug-file
Unofficial TypeScript SDK for UGOS Pro / UGREEN NAS file management APIs.
ug-file provides a small ESM client for authenticating with UGOS, resolving UGREENlink aliases, listing directories, reading and uploading files, and performing common file operations such as copy, move, rename, trash, and delete.
Features
- Authenticate against UGOS Pro with RSA-encrypted credentials.
- Reuse exported sessions without storing passwords in the client.
- Connect by direct UGOS URL or by UGREENlink ID.
- List root folders and directory contents with file/directory helpers.
- Read, download, and upload files.
- Create folders and manage files with copy, move, rename, trash, and permanent delete operations.
- Use native
fetch, or inject a customfetchimplementation. - Fully typed TypeScript API.
Requirements
- A runtime with
fetch,FormData, andBlobsupport. Node.js 18+ works out of the box. - Network access to your UGOS Pro / UGREEN NAS instance.
Installation
npm install ug-fileOr with other package managers:
yarn add ug-file
pnpm add ug-fileDevelopment
This library is developed with Bun ([email protected]). Use Bun for local development workflows.
bun install
bun run typecheck
bun run buildQuick Start
import { UgosClient } from "ug-file";
const client = new UgosClient({
url: "https://your-nas.example.com"
});
let login = await client.login({ username: "admin", password: "your-password", keepalive: true });
if (login.requiresCode) {
login = await login.verifyCode("123456", true);
}
if (!login.success) {
throw new Error(login.message ?? `Login failed: ${login.code}`);
}
const entries = await client.list("/Documents");
for (const entry of entries) {
console.log(entry.name, entry.isDirectory() ? "directory" : "file");
}Connecting
Direct URL
Use url when you already know the UGOS base URL.
const client = new UgosClient({
url: "https://your-nas.example.com"
});UGREENlink ID
Use uglinkid to resolve a UGREENlink alias automatically through the public UGREENlink API.
const client = new UgosClient({
uglinkid: "your-alias"
});You can also resolve an alias directly:
const url = await UgosClient.resolveUgreenLinkUrl("your-alias");Custom Fetch
Pass fetch when your runtime does not provide globalThis.fetch, or when you need custom transport behavior.
const client = new UgosClient({
url: "https://your-nas.example.com",
trustInfo: {
client_type: "sdk",
system: "node",
dev_name: "backup-worker"
},
fetch: customFetch
});Usage
Call login() before using authenticated file APIs. Credentials are passed to login() and are not stored in the client.
const result = await client.login({ username: "admin", password: "your-password", keepalive: true });
if (result.success) {
console.log(result.session.uid);
}When UGOS requires OTP, login() returns an interactive challenge result. Pass keepalive: true to create a session that can be exported and reused later (see Session export). Pass true to verifyCode() to trust this device, or false to avoid adding a trusted device.
let result = await client.login({ username: "admin", password: "your-password", keepalive: true });
if (result.requiresCode) {
result = await result.verifyCode("123456", true);
}
if (!result.success) {
throw new Error(result.message ?? `Login failed: ${result.code}`);
}Use checkLogin() to verify whether the current in-memory token is still valid:
if (!(await client.checkLogin())) {
const result = await client.login({ username: "admin", password: "your-password", keepalive: true });
if (!result.success) {
throw new Error(result.message ?? `Login failed: ${result.code}`);
}
}Session export
Only sessions created with keepalive: true can be exported. If you logged in without keepalive (or with keepalive: false), exportSession() returns undefined.
const exportedSession = client.exportSession();
if (exportedSession) {
await anotherClient.login(exportedSession);
}List Files
const entries = await client.list("/Documents", { page: 1, limit: 100 });
for (const entry of entries) {
if (entry.isFile()) {
console.log(entry.path, entry.size);
}
}Root Folders
const { personal, shared } = await client.root();
console.log("Personal roots", personal.map((entry) => entry.name));
console.log("Shared roots", shared.map((entry) => entry.name));File Metadata and Existence
if (await client.exists("/Documents/report.pdf")) {
const stat = await client.stat("/Documents/report.pdf");
console.log(stat.name, stat.size, new Date(stat.mtime));
}Read and Download Files
const text = await client.readFile("/Documents/notes.txt", "utf8");
const bytes = await client.readFile("/Documents/archive.bin");
const response = await client.download("/Documents/report.pdf");
const arrayBuffer = await response.arrayBuffer();Upload Files
await client.upload("/Documents/hello.txt", "Hello from ug-file");
const bytes = new TextEncoder().encode("binary content");
await client.upload("/Documents/data.bin", bytes);Upload content can be a string, Blob, ArrayBuffer, ArrayBufferView, or ReadableStream<Uint8Array>.
Manage Files and Folders
await client.mkdir("/Documents/Projects", true);
await client.copy("/Documents/file.txt", "/Backup/", "skip");
await client.move(["/Downloads/a.txt", "/Downloads/b.txt"], "/Documents/", "overwrite");
await client.rename("/Documents/old-name.txt", "new-name.txt");
await client.trash("/Documents/old-file.txt");
await client.delete("/Documents/remove-forever.txt");Conflict actions for copy and move are:
"skip"or0: skip conflicting items."overwrite"or1: replace conflicting items."keep-both"or3: keep both files by allowing UGOS to rename the copied or moved entry.
API Overview
Main exports:
UgosClientUgosApiErrorUgosHttpError- Type exports including
UgosClientConfig,UgosLoginCredentials,UgosLoginResult,UgosLoginCodeOptions,UgosDirent,UgosFileEntry,UgosRoot,SessionContainer,LoginResponse, andConflictAction.
UgosClient methods:
UgosClient.resolveUgreenLinkUrl(ugreenLinkId, fetchImpl?)client.login(username, password)client.login({ username, password, keepalive? })client.login(credentialsOrSession)loginResult.verifyCode(code, trustOrOptions?)client.checkLogin()client.currentSessionclient.exportSession()— returns session only when logged in withkeepalive: trueclient.list(path?, options?)client.exists(path)client.root()client.stat(path)client.mkdir(path, recursive?)client.copy(src, dst, action?)client.move(src, dst, action?)client.rename(path, newName)client.download(path)client.readFile(path, encoding?)client.upload(path, content)client.trash(path)client.delete(path)
Error Handling
import { UgosApiError, UgosHttpError } from "ug-file";
try {
const result = await client.login({ username: "admin", password: "your-password", keepalive: true });
if (!result.success) {
throw new Error(result.message ?? `Login failed: ${result.code}`);
}
await client.list("/Documents");
} catch (error) {
if (error instanceof UgosApiError) {
console.error("UGOS API error", error.code, error.body);
} else if (error instanceof UgosHttpError) {
console.error("HTTP error", error.status, error.body);
} else {
throw error;
}
}Development
bun install
bun run typecheck
bun run buildAvailable scripts:
bun run build: generate declaration files and bundle the package intodist.bun run build:types: emit TypeScript declaration files only.bun run build:bundle: bundlesrc/index.tsintodist.bun run typecheck: run TypeScript without emitting files.
Notes
- This is an unofficial SDK and is not affiliated with UGREEN or UGOS.
- File operations run against your NAS account and may modify or permanently delete remote files.
delete()permanently removes files. Usetrash()when you want UGOS recycle-bin recovery behavior.
