@trimjs/web-app
v0.4.2
Published
web app sdk for nas
Readme
@trimjs/web-app
SDK for building apps that run inside the Trim host environment.
@trimjs/web-app provides a single JavaScript API for common host capabilities, including page title updates, file operations, file authorization, app settings, and App Auth route flows. It works in supported web iframe hosts and mobile WebView hosts.
Installation
npm install @trimjs/web-appyarn add @trimjs/web-apppnpm add @trimjs/web-appQuick Start
import { TrimApp } from '@trimjs/web-app';
const app = new TrimApp();
await app.setTitle('My App');
const config = await app.getPlatformConfig();
console.log(config.theme, config.language);All host APIs wait for SDK initialization internally. You usually do not need to call ready() before using them.
Basic Usage
import { TrimApp } from '@trimjs/web-app';
const app = new TrimApp({ debug: true });
await app.setTitle('Document Viewer');
await app.openFile('/vol1/1000/demo.pdf');
await app.openFileManager('/vol1/1000');
await app.setExitPageTips({
title: 'Leave this page?',
content: 'Unsaved changes may be lost.',
});
const files = await app.pickFile({
multiple: true,
accept: ['.pdf', '.doc', '.docx'],
title: 'Select files',
});
const userFileAuth = await app.authorizeUserFile('/vol1/1000/photos');
console.log(userFileAuth?.data);Public APIs
Constructor
new TrimApp(options?: TrimAppOptions)Creates a Trim app SDK instance.
const app = new TrimApp({ debug: true });ready
ready(): Promise<void>Waits until the SDK initialization is complete. Most apps do not need to call this explicitly because SDK methods wait for initialization automatically.
setTitle
setTitle(title: string): Promise<void | null>Sets the current app page title in the host.
await app.setTitle('My App');setExitPageTips
setExitPageTips(params?: { title?: string; content?: string }): Promise<void | null>Sets or clears the confirmation message shown when the user leaves the app page.
await app.setExitPageTips({
title: 'Leave this page?',
content: 'Unsaved changes may be lost.',
});
await app.setExitPageTips();getPlatformConfig
getPlatformConfig(): Promise<PlatformConfig>Returns host platform settings such as theme, language, app version, system version, date format, and time format.
const config = await app.getPlatformConfig();
if (config.theme === 'dark') {
document.documentElement.classList.add('dark');
}openFile
openFile(path: string): Promise<void | null>Opens a file with the host system.
await app.openFile('/vol1/1000/demo.pdf');openFileManager
openFileManager(path: string): Promise<void | null>Opens the host file manager and navigates to the given path.
await app.openFileManager('/vol1/1000');openAppSetting
openAppSetting(): Promise<void | null>Opens the current app settings page in the host system.
await app.openAppSetting();openURL
openURL(url: string, target?: string, features?: string): Promise<void | null>Opens a URL using the host-supported behavior. In a web host, this follows browser window.open behavior. In a mobile WebView host, it opens the URL in the system browser.
await app.openURL('https://example.com', '_blank');close
close(): Promise<void | null>Closes the current app page.
await app.close();showFileDetails
showFileDetails(paths: string[], options?: FileDetailsOptions): Promise<void | null>Shows the host file details panel for one or more paths.
await app.showFileDetails(['/vol1/1000/photos'], { admin: true });authorizeUserFile
authorizeUserFile(path: string): Promise<AppBridgeResponse<boolean> | undefined>Requests authorization for a user file or folder path.
const result = await app.authorizeUserFile('/vol1/1000/photos');
if (result?.data) {
console.log('Authorized');
}authorizeSharedFile
authorizeSharedFile(path: string): Promise<AppBridgeResponse<boolean> | undefined>Requests authorization for a shared file or folder path.
const result = await app.authorizeSharedFile('/share/demo');pickFile
pickFile(params: FilePickerParams): Promise<string[] | undefined>Opens the host file picker.
const files = await app.pickFile({
multiple: true,
accept: ['.pdf', '.jpg', '.jpeg', '.png', '.gif', '.webp'],
sidebarGroup: ['myFiles', 'external'],
title: 'Select files',
});pickUserFile
pickUserFile(params?: FilePickerParams): Promise<AppBridgeResponse<string[]> | undefined>Opens the user file picker and authorizes the selected paths for the current app.
const result = await app.pickUserFile({
accept: ['.jpg', '.jpeg', '.png'],
sidebarGroup: ['myFiles', 'external'],
title: 'Select and authorize files',
});
console.log(result?.data);Common FilePickerParams fields:
| Field | Type | Description |
| --------------- | ---------- | --------------------------------------------------- |
| multiple | boolean | Allows selecting multiple files. |
| directory | boolean | Allows selecting folders instead of files. |
| accept | string[] | Accepted file extensions, each prefixed with .. |
| sidebarGroup | string[] | Sidebar groups to show, in display order. |
| title | string | Picker title. |
| okText | string | Confirm button text. |
| creatable | boolean | Allows creating folders when supported by the host. |
| disabledPaths | string[] | Paths that cannot be selected. |
pickSharedFile
pickSharedFile(
params?: Omit<FilePickerParams, 'directory'>,
): Promise<AppBridgeResponse<string[]> | undefined>Opens the shared file picker and authorizes the selected shared paths for the current app. The host controls the directory behavior, so callers should not pass it.
const result = await app.pickSharedFile({
title: 'Select shared folder',
sidebarGroup: ['myFiles', 'otherShare'],
});
console.log(result?.data);Host Events
$on
$on(event: string, callback: (...args: unknown[]) => void): Promise<void>Subscribes to host events when the current runtime provides an event bus. The most common use cases are reacting to theme and language changes.
await app.$on('os/theme', (theme) => {
console.log('Theme changed:', theme);
});
await app.$on('os/language', (language) => {
console.log('Language changed:', language);
});App Auth Route Flow
App Auth routes are useful when an app needs to start a file authorization or file picker flow through a route-based page and receive the result through a callback URL.
openAppAuth
openAppAuth(
method: AppAuthMethod,
params: AppAuthParams,
options?: { target?: string; features?: string },
): Promise<string>Starts an App Auth route flow. The returned string is the URL that was opened.
await app.openAppAuth('pickFile', {
appName: 'trim.demo',
directory: true,
redirectUri: '/callback',
state: 'pick-file-demo',
});Supported method names and their internal routes:
| method | route |
| --------------------- | --------------------------------- |
| pickFile | /app-auth/pick-file |
| pickUserFile | /app-auth/pick-user-file |
| pickSharedFile | /app-auth/pick-shared-file |
| authorizeUserFile | /app-auth/authorize-user-file |
| authorizeSharedFile | /app-auth/authorize-shared-file |
parseAppAuthCallback
parseAppAuthCallback(input?: string | URL | URLSearchParams): AppAuthResultParses the callback query parameters returned by an App Auth route flow.
const result = app.parseAppAuthCallback();
console.log(result.status);
console.log(result.method);
console.log(result.state);
console.log(result.path);For successful picker routes, result.path contains the selected paths.
buildAppAuthUrl
buildAppAuthUrl(method: AppAuthMethod, params: AppAuthParams): Promise<string>Builds an App Auth route URL without opening it. Most apps should use openAppAuth() directly. Use this helper only when you need to control navigation yourself.
All methods accept these common params:
| Field | Type | Required | Description |
| ------------- | -------- | -------- | --------------------------------------------------------------- |
| appName | string | Yes | App identifier used by the authorization flow. |
| redirectUri | string | No | Callback URL or path that receives the authorization result. |
| state | string | No | Caller-defined opaque value returned unchanged in the callback. |
state does not affect authorization. Use it to correlate a callback with the flow that created it. For security-sensitive flows, generate an unpredictable value, store it before navigation, and verify that the callback returns the same value.
pickFile
buildAppAuthUrl(method: 'pickFile', params: AppAuthPickFileParams): Promise<string>| Field | Type | Required | Description |
| -------------- | ---------- | -------- | ------------------------------------------------- |
| directory | boolean | No | Select folders instead of files. |
| accept | string[] | No | Accepted file extensions, each prefixed with .. |
| sidebarGroup | string[] | No | Sidebar groups to show, in display order. |
const url = await app.buildAppAuthUrl('pickFile', {
appName: 'trim.demo',
directory: false,
accept: ['.jpg', '.jpeg', '.png'],
sidebarGroup: ['myFiles', 'external'],
redirectUri: '/callback',
state: 'pick-file-demo',
});pickUserFile
buildAppAuthUrl(method: 'pickUserFile', params: AppAuthPickFileParams): Promise<string>pickUserFile supports the same picker params as pickFile, then authorizes the selected user paths for appName before redirecting.
| Field | Type | Required | Description |
| -------------- | ---------- | -------- | ------------------------------------------------- |
| directory | boolean | No | Select folders instead of files. |
| accept | string[] | No | Accepted file extensions, each prefixed with .. |
| sidebarGroup | string[] | No | Sidebar groups to show, in display order. |
const url = await app.buildAppAuthUrl('pickUserFile', {
appName: 'trim.demo',
directory: false,
accept: ['.jpg', '.jpeg', '.png'],
sidebarGroup: ['myFiles', 'external'],
redirectUri: '/callback',
state: 'pick-user-file-demo',
});pickSharedFile
buildAppAuthUrl(method: 'pickSharedFile', params: AppAuthPickSharedFileParams): Promise<string>pickSharedFile selects a shared folder. Its directory behavior is controlled by the host and cannot be configured by the caller.
| Field | Type | Required | Description |
| -------------- | ---------- | -------- | ----------------------------------------- |
| sidebarGroup | string[] | No | Sidebar groups to show, in display order. |
const url = await app.buildAppAuthUrl('pickSharedFile', {
appName: 'trim.demo',
sidebarGroup: ['myFiles', 'otherShare'],
redirectUri: '/callback',
state: 'pick-shared-file-demo',
});authorizeUserFile
buildAppAuthUrl(method: 'authorizeUserFile', params: AppAuthAuthorizeParams): Promise<string>| Field | Type | Required | Description |
| ------ | -------- | -------- | -------------------------------------- |
| path | string | Yes | User file or folder path to authorize. |
const url = await app.buildAppAuthUrl('authorizeUserFile', {
appName: 'trim.demo',
path: '/vol1/1000/photos',
redirectUri: '/callback',
state: 'authorize-user-file-demo',
});authorizeSharedFile
buildAppAuthUrl(method: 'authorizeSharedFile', params: AppAuthAuthorizeParams): Promise<string>| Field | Type | Required | Description |
| ------ | -------- | -------- | ---------------------------------------- |
| path | string | Yes | Shared file or folder path to authorize. |
const url = await app.buildAppAuthUrl('authorizeSharedFile', {
appName: 'trim.demo',
path: '/share/demo',
redirectUri: '/callback',
state: 'authorize-shared-file-demo',
});Instance Properties
isWeb
isWeb: boolean;Indicates whether the current runtime is a web host.
isStandaloneWeb
isStandaloneWeb: boolean;Indicates whether the current runtime is a standalone browser page without an iframe host.
Types
import type {
AppAuthAuthorizeParams,
AppAuthBaseParams,
AppAuthCallbackError,
AppAuthCallbackStatus,
AppAuthMethod,
AppAuthMethodParamsMap,
AppAuthParams,
AppAuthPickFileParams,
AppAuthPickSharedFileParams,
AppAuthResult,
AppBridgeResponse,
AuthorizeFileResult,
FileDetailsOptions,
FilePickerParams,
PlatformConfig,
TrimAppOptions,
} from '@trimjs/web-app';TrimAppOptions
interface TrimAppOptions {
debug?: boolean;
}PlatformConfig
interface PlatformConfig {
theme: 'dark' | 'light';
language: string;
appVersion?: string;
systemVersion: string;
format: {
date?: string;
time?: string;
};
}AppBridgeResponse
type AppBridgeResponse<T> = {
code: number;
msg: string;
data: T;
};Platform Notes
The SDK normalizes supported host APIs across web iframe hosts and mobile WebView hosts. Some APIs may require a recent host version. When an API is unavailable, the SDK throws an error or returns undefined depending on the method behavior.
For route-based App Auth flows, use openAppAuth() to start the flow and parseAppAuthCallback() on the callback page to read the result.
License
MIT
