# @effect-firebase/admin 中文文档

规范地址：https://npmcn.com/package/%40effect-firebase/admin/

版本：1\.0\.1
npm 元数据更新时间：2026-10-08T13:55:32.832Z
中文译文更新时间：2026-11-13T17:47:05.622Z
软件包许可：MIT

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

原始 npm 页面：https://www.npmjs.com/package/%40effect-firebase/admin
原文对照：https://npmcn.com/package/%40effect-firebase/admin/?lang=original
项目主页：https://github.com/fwal/effect-firebase#readme
源码仓库：https://github.com/fwal/effect-firebase

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

- 包体积（解压后）：173 kB，87 个文件
- 模块格式：ES Module
- TypeScript 类型：包内自带
- 运行依赖：1 个
- peer 依赖：effect ^4\.0\.0，express ^5\.2\.1，firebase-admin ^14\.3\.0，effect-firebase 1\.0\.1，firebase-functions ^7\.3\.2
- 首次发布：2025-10-10T08:38:44.615Z
- 最新版本发布：2026-10-08T13:55:32.396Z
- 近 30 天下载量：3306（2026-10-13 至 2026-11-11，npm 官方下载统计）
- 已发布版本数：40（近 12 个月 39 个）

## 中文简介

Firebase Admin SDK集成,用于效应Firebase. 规定 a `FirestoreService` 执行和云函数触发效果包.

## 安装

```sh
npm install @effect-firebase/admin
```

也可以使用：`pnpm add @effect-firebase/admin`、`yarn add @effect-firebase/admin`、`bun add @effect-firebase/admin`

## README

# @ effect- firebase/ admin (英语)

Firebase Admin SDK集成,用于效应Firebase. 规定 a `FirestoreService` 执行和云函数触发效果包.

## 安装

```bash
npm install @effect-firebase/admin effect-firebase effect
npm install firebase-admin firebase-functions express
```

## 设置

从一层创建运行时间并将其传递给函数处理器 :

```typescript
import { initializeApp } from 'firebase-admin/app';
import { Admin, FunctionsRuntime } from '@effect-firebase/admin';

const runtime = FunctionsRuntime.make(Admin.layer({ app: initializeApp() }));
```

`Admin.layer` 接受 `{ app }`, (中文(简体) ), `{ firestore }`,或者没有参数(使用/初始化默认应用). 它规定 `FirestoreService` 并接通了"云寻". `FunctionsRuntime.Default(app?)` 是一个缩写 `make(Admin.layer(...))`。 。 。 . `make` 处理运行时间 `SIGINT`编号 :`SIGTERM`。 。 。 .

存储器只是需要的效果 `FirestoreService`这样 `yield* PostRepository` 在操作员内部工作,却不提供其他东西.

## 云函数

### HTTP (英语:`onRequest`(中文(简体) )

```typescript
import { onRequestEffect } from '@effect-firebase/admin';
import { Query } from 'effect-firebase';

export const myFunction = onRequestEffect({ runtime }, (request, response) =>
  Effect.gen(function* () {
    const repo = yield* PostRepository;
    response.json({ posts: yield* repo.query(Query.limit(20)) });
  }),
);
```

### 可调用( N)`onCall`(中文(简体) )

```typescript
import { onCallEffect } from '@effect-firebase/admin';
import { Schema } from 'effect';

const Input = Schema.Struct({ title: Schema.String, content: Schema.String });
const Output = Schema.Struct({ postId: Schema.String });

export const createPost = onCallEffect(
  { runtime, inputSchema: Input, outputSchema: Output },
  (input) =>
    Effect.gen(function* () {
      const repo = yield* PostRepository;
      const postId = yield* repo.add({ ...input, status: 'draft' });
      return { postId };
    }),
);
```

何时 `inputSchema` 财务报告和审定财务报表 `outputSchema` 自动处理解码和编码.

何时 `inputSchema` 设置, 处理器收到 `(input, context)`· ; `context` 曝光情况 `auth`, (中文(简体) ), `app`, (中文(简体) ), `rawRequest`, (中文(简体) ), `instanceIdToken`, (中文(简体) ), `acceptsStreaming` 当 客户端已调用 `httpsCallable(...).stream()`,则 `response` 手动对象 `sendChunk` 打电话 无 `inputSchema`,处理器接收原始 `(request, response)`。 。 。 .

`onRequestEffect` 采取同样做法: `bodySchema` 处理器收到 `(body, request, response)`; 与 `responseSchema` 它返回编码和发送的值(状态) `successStatus`默认值 `200`) (中文(简体) ).

### 可流调( N)`onCall` + 键 `sendChunk`(中文(简体) )

`onCallStreamEffect` 需要一个处理器返回 a `Stream`。每个元素的编码为: `chunkSchema` 并发送到客户端 `response.sendChunk` 因为它是生产的。 当 溪流完成, 收集的块作为可调用的最后块返回 `data`,所以一个 调用此函数的客户端 `.stream()` 仍然得到全部结果。 溪流是 当客户端断开时中断,包括飞行中拉出.

```typescript
import { onCallStreamEffect } from '@effect-firebase/admin';
import { Schema, Stream } from 'effect';
import { LanguageModel } from 'effect/ai';

export const chat = onCallStreamEffect(
  {
    runtime,
    timeoutSeconds: 540,
    inputSchema: Schema.Struct({ prompt: Schema.String }),
    chunkSchema: Schema.Struct({ delta: Schema.String }),
  },
  (input) =>
    LanguageModel.streamText({ prompt: input.prompt }).pipe(
      Stream.filter((part) => part.type === 'text-delta'),
      Stream.map((part) => ({ delta: part.delta })),
      Stream.provide(AnthropicModel), // any Effect AI provider layer
    ),
);
```

客户端 :

```typescript
const { stream, data } = await httpsCallable(functions, 'chat').stream({
  prompt,
});
for await (const chunk of stream) append(chunk.delta);
const allChunks = await data; // ReadonlyArray<{ delta: string }>
```

流式调用需要 2 gen 云函数; set `timeoutSeconds` 足够高 历代相传.

#### 测试可调用设备

`CallableFunction.stream()` 火场的功能还是根茎,所以 `@effect-firebase/admin` 以假充名的船舶 `CallableResponse`数字 :

```typescript
import {
  runCallable,
  streamCallable,
  makeCallableRequest,
} from '@effect-firebase/admin';

const { stream, data, abort } = streamCallable(chat, { prompt: 'hi' });
for await (const chunk of stream) chunks.push(chunk); // what the client would see
expect(await data).toEqual(chunks); // final `data`
abort(); // simulate a client disconnect

await runCallable(chat, { prompt: 'hi' }); // non-streaming client, final `data` only

// full control over auth/app/rawRequest
streamCallable(
  chat,
  makeCallableRequest(
    { prompt: 'hi' },
    { auth: { uid: 'u1', token, rawToken: 'test-token' } },
  ),
);
```

### 火炉触发器

```typescript
import {
  onDocumentCreatedEffect,
  onDocumentUpdatedEffect,
  onDocumentDeletedEffect,
  onDocumentWrittenEffect,
} from '@effect-firebase/admin';

export const onPostCreated = onDocumentCreatedEffect(
  { runtime, document: 'posts/{postId}', schema: PostModel, idField: 'id' },
  (post) => Effect.log(`Created: ${post.id}`),
);
```

Firestore 触发处理器必须返回 `Effect<void, never, R>`: 自己处理或记录每个故障. `onDocumentUpdatedEffect` 通过 a `TypedChange<A>` (单位:千美元)`{ before, after }`, (中文(简体) ), `onDocumentWrittenEffect` (单位:千美元) `TypedWrittenChange<A>` (单位:千美元)`{ before: Option<A>, after: Option<A> }`) (中文(简体) ). 每个触发器也有一个 `...WithAuthContextEffect` 变体(例如:. `onDocumentCreatedWithAuthContextEffect`(其操作者收到) `(event, data)`。 。 。 .

### Pub/Sub (中文(简体) )`onMessagePublished`(中文(简体) )

```typescript
import { onMessagePublishedEffect } from '@effect-firebase/admin';

const MessageSchema = Schema.Struct({ userId: Schema.String });

export const onMessage = onMessagePublishedEffect(
  { runtime, topic: 'my-topic', messageSchema: MessageSchema },
  (message) => Effect.log(`Received for user: ${message.userId}`),
);
```

### 云层任务( O)`onTaskDispatched`(中文(简体) )

```typescript
import { onTaskDispatchedEffect } from '@effect-firebase/admin';

const TaskSchema = Schema.Struct({ email: Schema.String });

export const processEmail = onTaskDispatchedEffect(
  { runtime, retryConfig: { maxAttempts: 5 }, schema: TaskSchema },
  (task) => Effect.log(`Sending to: ${task.email}`),
);
```

### 计划`onSchedule`(中文(简体) )

```typescript
import { onScheduleEffect } from '@effect-firebase/admin';

export const cleanup = onScheduleEffect(
  { runtime, schedule: 'every 24 hours' },
  (event) => Effect.log(`Running cleanup job: ${event.jobName}`),
);
```

## 设置出错( E)`onSetupError`(中文(简体) )

每个包装器解码输入的数据,并用你的计划编码输出的数据 声明 当失败时——调用者发送的数据不匹配 `inputSchema`页:1 文档不匹配 `schema` - 包装器升起一个 `FunctionSetupError` 携带 页:1 `phase` 失败( e)`decode-input`, (中文(简体) ), `encode-output`, (中文(简体) ), `decode-body`, (中文(简体) ), `encode-response`, (中文(简体) ), `decode-document`, (中文(简体) ), `decode-message`, (中文(简体) ), `decode-task`)和 基础失败, 如 `cause` (通常为a) `SchemaError`; 平原 `Error` 当一个pub/Sub时 有效有效载荷为JSON). `FunctionSetupError` 财务报告和审定财务报表 `isFunctionSetupError` 导出.

过 `onSetupError` 以回收代替默认:

```typescript
import { onCallEffect } from '@effect-firebase/admin';
import { HttpsError } from 'firebase-functions/https';

export const createPost = onCallEffect(
  {
    runtime,
    inputSchema: Input,
    outputSchema: Output,
    onSetupError: (error, request) =>
      Effect.fail(new HttpsError('invalid-argument', error.cause.message)),
  },
  (input, context) => handle(input, context),
);
```

钩子接收包装器的本地参数, 所以一个 HTTP 处理器可以自己写 反应和触发器可以检查事件:

```typescript
export const onPostCreated = onDocumentCreatedEffect(
  {
    runtime,
    document: 'posts/{postId}',
    schema: PostModel,
    onSetupError: (error, event) =>
      Effect.logWarning(`Skipping malformed post ${event.params.postId}`),
  },
  (post) => handle(post),
);
```

默认时间 `onSetupError` 省略:

| 包装 | 无效的数据 | 编码失败 |
| --- | --- | --- |
| `onCallEffect` | `HttpsError('invalid-argument', ...)` | `HttpsError('internal')` |
| `onCallStreamEffect` | `HttpsError('invalid-argument', ...)` | `HttpsError('internal')` |
| `onRequestEffect` | `400 { error: 'Invalid request body' }` | `500` |
| 火炉 / Pub/Sub | 已登录缺陷( 无重试) | —— 说 |
| 任务 | 已登记缺陷,重推(重审) | —— 说 |

`onCallStreamEffect` 不暴露一个 `onSetupError` 选项,因此其上行是无条件的;其他包装则允许 `onSetupError` 覆盖这些默认值 .

`onCallEffect` 财务报告和审定财务报表 `onCallStreamEffect` 还宣传任何 `HttpsError` 处理器本身失败到 客户端的代码和信件完整,所以 `Effect.catchTag(...)` 链条结束于 `Effect.fail(new HttpsError(...))` 以书面形式工作.

回收只覆盖边界 。 您的处理器升起的错误从未经过 `onSetupError` 包括: `FunctionSetupError` 你养活自己 所以两个留下来 可以区分.

### 预期拒绝和缺陷记录

单位 `onCallEffect`, (中文(简体) ), `onCallStreamEffect` 财务报告和审定财务报表 `onRequestEffect`,一个可以逃出 处理器被记录为缺陷,除非它是预期的拒绝: `HttpsError`,或任何 带有 Effect 注释的错误 `ErrorReporter.ignore` (《公约》) `HttpApiError.BadRequest` 并使用朋友. `onRequestEffect` 仍然响应 `500`; 仅 日志行被跳过 。 触发包装符( Firestore、 Pub/ Sub、 任务、 时间表) 日志 逃出错误 。 任务和计划处理器在日志后重播, 所以重试 配置适用。 对于可调用和 HTTP 处理器,请注释您自己的错误以保存它们 出自缺陷日志, 但仍无法通过调用 :

```typescript
import { Data, ErrorReporter } from 'effect';

class RejectedError extends Data.TaggedError('RejectedError')<{
  readonly reason: string;
}> {
  readonly [ErrorReporter.ignore] = true;
}
```

## 云记录

`Admin.layer` 自动将默认效果日志替换为将结构化日志写入 Cloud 日志的日志 :

```typescript
Effect.gen(function* () {
  yield* Effect.log('info message');
  yield* Effect.logError('error message');
}).pipe(Effect.provide(Admin.layer({ app: initializeApp() })));
```

跟踪的平地物体成为条目 `jsonPayload`,如同 `firebase-functions`自己的记录器。 日志说明、日志长度和原因合并为同一有效载荷:

```typescript
Effect.logError('Could not add order', cause, { partnerId }).pipe(
  Effect.annotateLogs({ orderId }),
  Effect.withLogSpan('checkout'),
);
// jsonPayload: { orderId, partnerId, logSpans: { checkout: 12 }, cause: '<Cause.pretty>' }
```

-   在密钥相撞时,明确的后导对象胜过说明.
-   当原因倒塌到一个 `Error`,其堆栈被附加到 `message`,因此错误 报告分组 真实错误 而不是内部合成的堆栈 `firebase-functions`其它原因都印得漂亮.
-   有效载荷值为 JSON 安全, 并带有效果 `Formatter.formatJson` (大写,错误,循环引用, `Redacted`); 仍然无法序列化的值被替换为 `'[Unserializable]'`。 。 。 .

伐木机也可以单独使用,作为 `Logger.cloudConsole` 层.

## 解决问题

**`Failed to initialize Google Cloud Firestore client with the available credentials`** 通常由多个安装的复制件造成 `firebase-admin`或加以去除(`pnpm why firebase-admin`)或直接通过 Firestore 实例:

```typescript
import { getFirestore } from 'firebase-admin/firestore';

const db = getFirestore(initializeApp());
const runtime = FunctionsRuntime.make(Admin.layer({ firestore: db }));
```

## 许可证

麻省理工学院

## 常见问题

### @effect-firebase/admin 是什么？

Firebase Admin SDK集成,用于效应Firebase\. 规定 a FirestoreService 执行和云函数触发效果包\.

### 如何安装 @effect-firebase/admin？

在项目目录运行 npm install @effect-firebase/admin，或使用 pnpm add / yarn add / bun add。它还需要宿主项目提供 peer 依赖：effect（^4\.0\.0）、express（^5\.2\.1）、firebase-admin（^14\.3\.0）、effect-firebase（1\.0\.1）、firebase-functions（^7\.3\.2）。npm 7 及以上与 pnpm 8 及以上默认会自动安装必需的 peer 依赖，Yarn 需要手动安装。

### @effect-firebase/admin 支持 TypeScript 吗？

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

### @effect-firebase/admin 支持 ESM 还是 CommonJS？

以 ES Module 形式发布，推荐使用 import 引入。在 CommonJS 项目中，Node\.js 20\.19\+ / 22\.12\+ 可以直接 require\(\) 不含顶层 await 的 ES Module，更早的版本需要改用动态 import\(\)。

### @effect-firebase/admin 可以商用吗？

@effect-firebase/admin 使用 MIT 许可。宽松许可：允许商业使用、修改和再分发，通常只需在分发时保留原版权与许可声明。以上为概括，不构成法律意见，请以许可原文为准。

### @effect-firebase/admin 的下载量有多少？

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

### @effect-firebase/admin 还在维护吗？

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

