# @digo-labs/services 中文文档

规范地址：https://npmcn.com/package/%40digo-labs/services/

版本：0\.2\.19
npm 元数据更新时间：2026-11-13T13:27:41.653Z
中文译文更新时间：2026-11-14T06:50:54.734Z
软件包许可：未声明

本文由上游 README 翻译，可能存在偏差，请结合原文核对 API、命令与配置。版权与许可归原作者所有。

原始 npm 页面：https://www.npmjs.com/package/%40digo-labs/services
原文对照：https://npmcn.com/package/%40digo-labs/services/?lang=original

## 关键信息（来自 npm 元数据）

- 包体积（解压后）：495 kB，105 个文件
- 模块格式：ESM + CJS
- TypeScript 类型：包内自带
- 运行依赖：8 个
- peer 依赖：react ^19\.0\.0，react-dom ^19\.0\.0，@digo-labs/ws ^0\.2\.2，@digo-labs/common ^0\.2\.23，@digo-labs/backend ^0\.2\.15
- 首次发布：2026-05-05T22:56:24.310Z
- 最新版本发布：2026-11-13T13:27:41.419Z
- 近 30 天下载量：2191（2026-10-12 至 2026-11-10，npm 官方下载统计）
- 已发布版本数：32（近 12 个月 32 个）

## 中文简介

Digo平台的浏览器客户端:auth,设备密钥,后端API,数据库表格,文件存储,websocket通道,AI生成和AI任务.

## 安装

```sh
npm install @digo-labs/services
```

也可以使用：`pnpm add @digo-labs/services`、`yarn add @digo-labs/services`、`bun add @digo-labs/services`

## README

# @digo-labs/服务

Digo平台的浏览器客户端:auth,设备密钥,后端API,数据库表格,文件存储,websocket通道,AI生成和AI任务.

**如何是观此相.** 这个带包的向导船,因此与您所安装的版本相匹配;站点描述了最新的发布. 类型 `node_modules/@digo-labs/services/dist/*.d.ts` 如果他们不同意,是准确的,是赢的。 更深的页面 : [https://design.digo-labs.com/docs/guide/package-services (中文(简体) )](https://design.digo-labs.com/docs/guide/package-services)。 。 。 .

## 设置

不要手动关闭此软件包 . `defineApp` 从 `@digo-labs/app` 注册应用程序名称、电话 `AuthHelper.init` (与 `auth`和 `ApiHelper.init` (与 `backend: true`,然后运行您的 `services` 工厂,在工厂里建造以下的类(`...databases`, (中文(简体) ), `new Storage()`, (中文(简体) ), `new Websockets<Channels>()`, (中文(简体) ), `new Ai()`) (中文(简体) ).

## 认证 : `useAuth`, (中文(简体) ), `useGoogleSignIn`, (中文(简体) ), `AuthHelper`

```tsx
import { useAuth } from '@digo-labs/services';

const { user, session, device, instance, isReadOnly, tier, globalTier, isLoading, isOffline, isAuthenticated, signIn, signOut } = useAuth();

await signIn.social({ provider: 'google', callbackURL: window.location.href });
```

`tier` 实值 `'public' | 'user' | 'org' | 'admin'` 在选定的实例中: 注册设备的分级胜出; 否则 `org` 是一个已验证的 `@productionclub.net` 电子邮件,以及 `admin` 管理者的角色或管理者. `instance` 是所选实例的弹出和 `globalTier` 忽略实例角色:门实例管理、预算限制、文本、代理和其中的DMX. `isReadOnly` 当实例被存档时是真实的( 一个归档撤销了实例的设备密钥, 因此设备获得 `401`) (中文(简体) ). `isAuthenticated` 对用户或设备来说是真实的. `AuthHelper.auth` 是原始的更好的 Auth 客户端(包括admin 插件).

对于谷歌的登录按钮, `useGoogleSignIn({ callbackPath })` (默认) `'/'`返回时 `{ signIn, isSigningIn, error }`数字 : `signIn()` 重定向到谷歌并返回 `callbackPath` 并决心 `Result<void>` tu; `isSigningIn` 在浏览器离开或请求失败之前是真实的; `error` 保持失败.

```tsx
import { useGoogleSignIn } from '@digo-labs/services';

const { signIn, isSigningIn } = useGoogleSignIn({ callbackPath: from });

async function handleSignIn() {
  const [, error] = await signIn();

  if (error) {
    console.error(error);
    setMessage('Sign in failed. Please try again.');
  }
}

<button onClick={handleSignIn} disabled={isSigningIn}>Continue with Google</button>
```

## 设备密钥 : `Devices`, (中文(简体) ), `useDevice`, (中文(简体) ), `DeviceHelper`

一个设备密钥让一个亭子在层上行动,没有人签字. 它属于它创建于,生活于 `localStorage` 并发送到每个 API 呼叫中; 装入设备将它的浏览器切换到它的密钥实例中 .

```ts
const devices = new Devices();

await devices.enrol({ name: 'Booth 1', tier: 'org', expiresInDays: 30 }); // create and store the key here, then sign this browser out
await devices.create({ name: 'Booth 2' });  // { device, key }, key not stored
await devices.list();                       // DeviceRecord[]
await devices.revoke(id);                   // boolean
await devices.regenerate(id);               // { device, key }: old key revoked, new one revealable
devices.forget();                           // drop this device's key

await devices.create({ name: 'Booth 3', isRevealable: true }); // keep an encrypted copy
await devices.reveal(id);                   // the key again (admin, while revealable)
await devices.lock(id);                     // boolean: drop the copy for good, key keeps working
await devices.lockAll();                    // number of keys locked in this instance
```

`tier` 实值 `'user' | 'org'` (默认) `'org'`, (中文(简体) ), `expiresInDays` 最多365起(违约30起)或 `null` 为永远. `DeviceRecord.isRevealable` 说钥匙是否还有副本. `useDevice()` 返回时 `{ device, isLoading, isOffline }`页:1 `401` 丢弃存储的密钥, 而其它任何失败( 网络出错、 超时、 其它) `4xx`页:1 `5xx`(组数) `isOffline`,保留 `device` 作为记录,最后确认的后端(插入 `localStorage`自行检讨; `DeviceHelper.setKey(key)` 编号 : `clearKey()` 管理存储的密钥.

## 数据库 : `Database<T>`

每表一例. 类型实例来自 `defineDatabases` (单位:千美元)`@digo-labs/app/database`; 直接为共享表格构建一个: `new Database<StyleRecord>('styles')` (第二个参数:主键,默认值) `'id'`) (中文(简体) ).

```ts
await services.items.getAll(50, 0);                                            // T[]  (limit?, offset?), in primary-key order
await services.items.get(id);                                                   // T | null
await services.items.getBy('name', 'Hello');                                    // T[]  (column, value, limit?, offset?)
await services.items.readAll();                                                 // T[]  every row, paged by primary key
await services.items.readAllBy('name', 'Hello');                                // T[]  every matching row
await services.items.create({ name: 'Hello' });                                 // T
await services.items.update(id, { name: 'Hi' });                                // boolean
await services.items.update(id, { status: 'printing' }, { status: 'queued' }); // only if it still matches (needs read too)
await services.items.delete(id);                                                // boolean
```

读取整个表格的使用 `readAll`编号 :`readAllBy`没有循环 `offset`:它们在上一个主键读取后再行行,所以每个从起到终所存在的行都会被精确地读取一次,即使其他行被更改,添加或去除(单列主键只有;其他表格得到400个).

访问量为每张表格,在 `src/db.ts` 并同步 by `digo-db push`;没有规则的表格被拒绝。 客户端可能不会发送 `id` (给它一个数据库默认) 或表格的 `owner` 栏(后端从会话中填充).

## 实例 : `Instances`, (中文(简体) ), `useInstance`, (中文(简体) ), `InstanceHelper`

一个应用软件的孤立装置(schema,文件,已签名的频道,设备密钥,AI预算各一;开放频道只获得其名下的实例). `main` 总是存在的; 请求将实例带入 `X-Digo-Instance`: 页面主机( q)`jon.<app>.digo-labs.com` 实值 `jon`),否则浏览器的选择,否则 `main`。一个未知的存储选择被丢弃,页面重新装入 `main`,是否签名.

```ts
const instances = new Instances();

await instances.list();                                  // main, then all for a global admin or the ones you administer
await instances.current();                               // { instance, tier, isReadOnly }
instances.select('jon');                                 // store for this browser and reload
instances.getSelected();                                 // 'jon'
await instances.create({ slug: 'jon', name: 'Jon' });    // global admins only, like the calls below
await instances.rename('main', 'Las Vegas');
await instances.archive('jon');                          // read-only, device keys revoked
await instances.reopen('jon');
await instances.setAdmins('jon', ['jon@example.com']);   // replaces the list; admins of that instance only, never main
await instances.getAdmins('jon');
```

`useInstance({ userId })` 返回时 `{ instance, access, isLoading }` (单位:千美元)`access` 仅在外部获取 `main`,在网络错误上重新测试,并丢弃一个未知存储实例; `useAuth()` 已经用过了.

## 存储 : `Storage`

应用程序的 S3 桶中的文件通过预签名链接 . `new Storage()` 用途 `<app-name>-digo-labs-storage`;通过共享桶的名称(`new Storage('common-styles-digo-labs-storage')`) (中文(简体) ).

```ts
const { path, url } = await storage.uploadFile(`sketches/${id}.png`, file);  // File | Blob | ArrayBuffer, contentType?
await storage.uploadImage(path, { base64, mediaType: 'image/png' });
await storage.uploadFromUrl(path, remoteUrl, 'image/png');

storage.getUrl(path);                                   // sync link through the files route
await storage.getSignedUrl(path, { expiresIn: 300 });   // short-lived link for private prefixes
await storage.download(path);                           // Blob
await storage.list('sketches/', { limit: 100 });        // StorageObject[]
await storage.delete([path]);                           // deleted paths
storage.getPathFromUrl(url);                            // string | null
```

在表格中存储路径,而不是链接 。 前缀规则来自 `defineStorage` 内 `src/db.ts`。路径相对选定的实例: `jon` 他们住在地下 `_instances/jon/`,哪个 `getUrl`, (中文(简体) ), `getPathFromUrl` 财务报告和审定财务报表 `list` 为您添加并删除.

## 网络锁定 : `Websockets<TMap>`

A. 在websocket中枢上打入的酒吧/分站; `TMap` 将频道名称映射到有效载荷。 它在构造器中连接,并自己重新连接.

```ts
interface Channels { cursor: { x: number; y: number; }; }

const ws = new Websockets<Channels>({ auth: true });

ws.subscribe('cursor', data => move(data.x, data.y));
ws.send('cursor', { x: 1, y: 2 });       // to current subscribers
ws.setState('cursor', { x: 1, y: 2 });   // kept on the hub, replayed to new subscribers
ws.unsubscribe('cursor');
ws.onReady(() => refresh());             // also onOpen, onClose, onError, offReady, isLive, close
```

选项 : `auth`, (中文(简体) ), `url` (默认) `wss://ws.digo-labs.com`, (中文(简体) ), `app`, (中文(简体) ), `id`, (中文(简体) ), `reconnect`, (中文(简体) ), `reconnectInterval`, (中文(简体) ), `maxReconnectInterval`, (中文(简体) ), `getToken`。 。 。 .

-   **打开** (默认):频道外出作为 `<app>:<channel>` (单位:千美元)`<app>__<instance>:<channel>` 外部 `main`),除非含有: `:` 或从 `_`。命名大会;任何人都可以读取.
-   **签署于** (单位:千美元)`auth: true`: 显示后端符号(会话或设备密钥); 名称按写并对照应用程序检查 `defineChannels` 规则.

## 大赦国际: `Ai`

```ts
const ai = new Ai();

const stream = ai.text.generate({ messages: [{ role: 'user', content: 'Hi' }], systemPrompt, maxTokens: 400 });
for await (const { text } of stream) append(text);
const { text, stopReason, isBlocked } = await stream.collect();

const image = await ai.image.generate({ prompt, aspectRatio: '16:9' }, { persist: 'generations/a.jpg' });
await ai.image.edit({ prompt, image: url, strength: 0.6 });
await ai.image.upscale({ image: url, factor: 2 });
await ai.image.removeBackground({ image: url });
await ai.video.generate({ prompt, aspectRatio: '9:16', durationSeconds: 5 });
await ai.audio.speech({ text, voice: 'af_heart' });
await ai.audio.music({ prompt, durationSeconds: 30 });
await ai.audio.transcribe({ audio: url, language: 'en' });
```

中途丢出失败的文本流 `TextStreamError` 带有 `reason` (单位:千美元)`busy`, (中文(简体) ), `model_unavailable`, (中文(简体) ), `provider_down`, (中文(简体) ), `invalid_request` 或者说 `unknown`) (中文(简体) ). 文字运行于贝德罗克;媒体运行于fal. 媒体选项是 `{ persist?, signal?, onProgress? }` (单位:千美元)`transcribe` 财务报告和审定财务报表 `text.generate` 带 `{ signal }` 页:1 结果为: `{ url, contentType?, width?, height?, seed?, durationSeconds?, model? }`; 无 `persist`, (中文(简体) ), `url` 是提供者的临时链接,文件被复制到您的桶中 `url` 实值 `storage.getUrl(persist)`。原始供应商: `ai.bedrock.converseStream(body, signal?)`, (中文(简体) ), `ai.fal` (单位:千美元)`subscribe`, (中文(简体) ), `run`, (中文(简体) ), `stream`, (中文(简体) ), `queue`,(......)和 `ai.replicate` (单位:千美元) `replicate` SDK),也导出为 `Bedrock`, (中文(简体) ), `Fal`, (中文(简体) ), `Replicate`。 。 。 .

## AI 任务 : `ai.jobs`

后端运行的图像管道:输入检查,任务,输出保存到您的桶上,输出检查. 重新装入毫无损失.

```ts
const job = await services.ai.jobs.create({
  key:      `guest-${guestId}`,                       // idempotent per app instance
  inputs:   { sketch: `sketches/${guestId}.png` },
  checks:   [{ type: 'rekognition', input: 'sketch' }],
  tasks:    [{
    key:      'traditional',
    endpoint: 'fal:openai/gpt-image-2.5/flare/edit',   // AI_JOB_ENDPOINTS in @digo-labs/common
    input:    { prompt, image_urls: [{ $input: 'sketch' }] },
    output:   { path: `designs/${guestId}/traditional.png` }, // under a write: 'server' prefix
  }],
  outputChecks: [{ type: 'rekognition' }],
});

const stop = services.ai.jobs.watch(job.id, current => setTasks(current.tasks));
```

还有 `add(id, tasks)`, (中文(简体) ), `check(id, taskKey, checks)`, (中文(简体) ), `cancel(id)`, (中文(简体) ), `get(id)`,以及 `list(filters)`: 实例的工作是一页时间, 最古老的第一, 形状 `get` 返回; 过滤器 `from` 编号 : `to` (关于创作时间的ISO 8601, `to` (不包括), `statuses`, (中文(简体) ), `limit` (默认为100,最多为200),页面的 `next`,以 `cursor` 直到它变成这样 `null`。 。 。 . `onReview` 实值 `'reject'` (违约)或 `'continue'`。 。 。 . `create` 采取不 `tasks` 工作目前只检查其投入; `add` 然后工作的时候 `checking`,它的任务等待检查。 检查是 `{ type: 'rekognition', input?, reject?, review?, minConfidence?, timeoutMs? }` 或者说 `{ type: 'bedrock', prompt, input?, guardrail?, model?, provider?, timeoutMs? }`时 `provider` 实值 `'bedrock'` (违约)或 `'anthropic'` (无) `guardrail` 和(或) `timeoutMs` 3至25 s(默认情况下为25 s). `watch` 等待每个修改的后端( n)`get(id, { since, signal })` 并停止一切. `endpoint: 'fake:echo'` 建造时没有损失 一个任务 `fallbacks` (最多2个) `{ endpoint, input? }`(a) 在其提供商失败时接管 `fallbackAfter` (ms) 当电流缓慢时,也开始下一个; `servedBy` 命名保存图像的终点。 任何检查最多需要两个 `fallbacks` (或一个) `fallback`克劳德按顺序审查, 只有在前一个不能运行或时间用完的时候.

## 大赦国际的预算: `ai.budgets`

每个实例对工作的限制, 保留在后端. `null` 谓无量相.

```ts
const { budget, usage } = await services.ai.budgets.get();
await services.ai.budgets.update({ maxInFlight: null, dailyUsd: 200 }); // only the fields sent change
```

`budget` 实值 `{ maxTasksPerJob, maxInFlight, hourlyUsd, dailyUsd, isPaused }` (违约30、8、10、50, `false`(三); `usage` 实值 `{ hourlyUsd, dailyUsd, inFlight }`,估计在最后一小时和一天的开支, 以及现在供应商的要求。 两种调用都根据呼叫者自己的应用程序和实例行事;改变限制需要一个全局管理员,而一个实例管理员只能暂停和恢复(`isPaused`) (中文(简体) ). 工作请求超过答案的上限 `429`。 。 。 .

## 低级和中央领导才能

-   `ApiHelper.client` 是每个后端路由的被打入的Hono客户端; `ApiHelper.unwrap<T>(promise)` 返回 JSON 或丢出一个 `Error` 与后端的信息.
-   `new Dmx().send(channel, value)` 设置 DMX 频道(仅限管理员). `Realtime` 是空占位符; 使用 `Websockets`。 。 。 .
-   这个 `digo-db` 二进制( e)`npm run db:push` 应用程序中 : `push` 创建计划, 运行 `drizzle-kit push`,同步 `access`, (中文(简体) ), `storage` 财务报告和审定财务报表 `channels` 出口额 `src/db.ts` 并推进应用程序的每一个实例计划 `drop`, (中文(简体) ), `verify`, (中文(简体) ), `refresh`, (中文(简体) ), `schema-name`需求 `DATABASE_URL_MONOREPO` (和 `ADMIN_SECRET` 在环境, 即应用模板的 `scripts/with-monorepo-secrets.sh` 从 AWS 机密管理器中读取 :`npm run db:push` 运行 `push` 通过它; 运行其他子命令 通过它),和 `drizzle-kit` 已安装.

## 抓到他们了

-   **内建服务 `services` 工厂.** `Storage` 财务报告和审定财务报表 `Websockets` 需要应用程序名称 `defineApp` 登记和扔出没有它; `new Ai()` 构建一个 `Storage`,所以它投掷也.
-   **`useAuth` 需求 `auth` 内 `defineApp`**,或 `AuthHelper.auth` 掷出. 每页一个认证项目 .
-   **`backendURL` 没有到达荒地或复制**:他们的代理人总是使用 `https://api.digo-labs.com`。 。 。 .
-   **分级后端执行 :** 文本, fal/ 复制, 全部 `ai.jobs` 电话和 `ai.budgets.get` 需求 `org`· ; `ai.budgets.update` 和设备创建/列表/撤销需要 `admin`, (中文(简体) ), `instances.list` 登录( e)`instances.current` 实例管理是全球性的管理。 一个实例是 `admin` 仅根据该实例本身的数据、文件、频道、设备和工作;文本、fal/复制和DMX检查其全球层级。 存档实例解答写法 `423`。 。 。 . `401` 签字后, `403` 当阶梯太低的时候.
-   **共享桌名取胜 .** 后端决定 `common` 表格(例如: `styles`)在应用程序之前,所以一个同名的应用程序表是无法到达的.
-   **`getUrl` 仅在 a 下装入 `read: 'public'` 前缀** (次数) `404`; 使用情况 `getSignedUrl`。 。 。 . `getPublicUrl` 构建一个不装入的原始S3地址:桶是私有的.
-   **固定的 AI 值抛出其他 :** 图像 `aspectRatio` `1:1`, (中文(简体) ), `16:9`, (中文(简体) ), `9:16`, (中文(简体) ), `4:3`, (中文(简体) ), `3:4`; 视频 `16:9`, (中文(简体) ), `9:16`, (中文(简体) ), `1:1`(一) 持续时间中断至5或10秒; `voice` 必须是克克洛的声音(`af_heart`, (中文(简体) ), `am_adam`(中文(简体) ).
-   **网页 `send`编号 :`setState` 已断开**未排队。 重读状态 `onReady`。 。 。 .

## 常见问题

### @digo-labs/services 是什么？

Digo平台的浏览器客户端:auth,设备密钥,后端API,数据库表格,文件存储,websocket通道,AI生成和AI任务\.

### 如何安装 @digo-labs/services？

在项目目录运行 npm install @digo-labs/services，或使用 pnpm add / yarn add / bun add。它还需要宿主项目提供 peer 依赖：react（^19\.0\.0）、react-dom（^19\.0\.0）、@digo-labs/ws（^0\.2\.2）、@digo-labs/common（^0\.2\.23）、@digo-labs/backend（^0\.2\.15）。npm 7 及以上与 pnpm 8 及以上默认会自动安装必需的 peer 依赖，Yarn 需要手动安装。它还提供命令行工具 digo-db，可以用 npx digo-db 直接运行。

### @digo-labs/services 支持 TypeScript 吗？

支持。包内自带 TypeScript 类型声明（package\.json 声明了 types 入口），安装后即可获得类型提示，无需再安装 @types 包。

### @digo-labs/services 支持 ESM 还是 CommonJS？

同时提供 ES Module 与 CommonJS 入口，import 和 require\(\) 都可以使用，打包工具会自动选择合适的版本。

### @digo-labs/services 可以商用吗？

@digo-labs/services 使用 未声明 许可。package\.json 没有声明许可证。没有许可证的代码默认保留全部权利，商用前请联系作者或查看仓库中的 LICENSE 文件。以上为概括，不构成法律意见，请以许可原文为准。

### @digo-labs/services 的下载量有多少？

根据 npm 官方下载统计，@digo-labs/services 在 2026/10/12 – 2026/11/10 这 30 天内被下载 2,191 次，日均约 73 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入，适合横向比较热度，不能直接等同于使用人数。

### @digo-labs/services 还在维护吗？

最新版本 0\.2\.19 发布于 2026/11/13（今天）；至今共发布 32 个版本，其中过去 12 个月发布了 32 个；首次发布于 2026/05/06。发布频率只是参考信号：功能稳定的工具可能很少需要更新，建议结合源码仓库的 issue 和提交记录判断。

