# @webority/mobile-core 中文文档

规范地址：https://npmcn.com/package/%40webority/mobile-core/

版本：0\.119\.0
npm 元数据更新时间：2026-11-02T21:03:15.743Z
中文译文更新时间：2026-11-02T22:00:39.035Z
软件包许可：SEE LICENSE IN LICENSE\.txt

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

原始 npm 页面：https://www.npmjs.com/package/%40webority/mobile-core
原文对照：https://npmcn.com/package/%40webority/mobile-core/?lang=original
项目主页：https://www.webority.com/

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

- 包体积（解压后）：839 kB，399 个文件
- 模块格式：ESM + CJS
- TypeScript 类型：包内自带
- 运行依赖：2 个
- peer 依赖：expo \>=57\.0\.0，react ^19\.1\.0，expo-camera \>=57\.0\.0，expo-crypto \>=57\.0\.0，expo-sqlite \>=57\.0\.0，react-redux ^9\.3\.0，expo-network \>=57\.0\.0，expo-sharing \>=57\.0\.0，expo-updates \>=57\.0\.0，react-native \>=0\.81\.0，expo-calendar \>=57\.0\.0，expo-contacts \>=57\.0\.0，expo-location \>=57\.0\.0，@reduxjs/toolkit ^2\.12\.0，expo-application \>=57\.0\.0，expo-file-system \>=57\.0\.0，expo-image-picker \>=57\.0\.0，expo-secure-store \>=57\.0\.0，expo-store-review \>=57\.0\.0，expo-task-manager \>=57\.0\.0，expo-media-library \>=57\.0\.0，expo-notifications \>=57\.0\.0，expo-screen-capture \>=57\.0\.0，expo-document-picker \>=57\.0\.0，expo-image-manipulator \>=57\.0\.0，expo-local-authentication \>=57\.0\.0
- 首次发布：2026-10-04T07:10:04.413Z
- 最新版本发布：2026-11-02T21:03:15.377Z
- 已发布版本数：101（近 12 个月 101 个）

## 中文简介

webbority React Native应用的平台层：HTTP客户端、认证/令牌存储、配置、日志、格式化器、验证器、网络状态、权限、存储、版本检查和无线更新。没有用户界面。

## 安装

```sh
npm install @webority/mobile-core
```

也可以使用：`pnpm add @webority/mobile-core`、`yarn add @webority/mobile-core`、`bun add @webority/mobile-core`

## README

# @webority / mobile-core

web React Native应用的平台层：HTTP客户端、认证和令牌存储、配置、 日志，格式化程序，验证程序，网络状态，权限，存储，图像压缩和 版本检查。 **没有用户界面** -组件生活在 [`@webority/mobile-ui`](https://www.npmjs.com/package/@webority/mobile-ui).

```bash
npm install @webority/mobile-core
```

运行时依赖关系: `axios` 和 `libphonenumber-js`。所需的对等体有 `expo`， `expo-application`， `expo-network`， `expo-secure-store` (HTTP客户端从 它), `expo-sqlite`。其他本地对等体都是可选的，只能通过自己的导入来访问 下面的路径，因此包安装和运行时不需要它们。 `react-native-keychain` 没有 不再使用;令牌存储移至 `expo-secure-store`.

完整的文档位于存储库的 `docs/` 目录中。

## 导入路径

任何需要原生包的东西都在它自己的路径后面，所以一个应用只打包它需要的东西 进口:

```ts
import { Permissions } from '@webority/mobile-core/permissions';
import { Geolocation } from '@webority/mobile-core/geolocation';
import { openDatabase } from '@webority/mobile-core/sqlite';
import { downloadFile } from '@webority/mobile-core/download';
import { shareFile } from '@webority/mobile-core/share';
import { fetchAttachment, fetchPreviewAttachment, previewKind } from '@webority/mobile-core/attachments';
import { getOrCreateInstallationId, clearTokensOnFirstLaunch } from '@webority/mobile-core/installation';
import { requestReviewAfterSuccess } from '@webority/mobile-core/review';
import { initPush, enablePush, usePush } from '@webority/mobile-core/push';
import { definePushActionTask } from '@webority/mobile-core/push/task';
import { compressImage } from '@webority/mobile-core/compressor';
import { initOtaUpdates, useOtaUpdates } from '@webority/mobile-core/updates';
import { createApiBaseQuery, createAppApi, setupApiListeners } from '@webority/mobile-core/query';
```

Metro解析是静态的，所以任何可以从主桶访问的东西都被绑定 每一个消费者。让他们远离这些是让他们的同伴真正可以选择的原因。

`/query` 为RTK查询层；它需要 `@reduxjs/toolkit` （2.12或更高版本）和 `react-redux`， 都是可选的对等体。一个 `createApi` 每个应用程序，构建与 `createAppApi` 基本查询结束 库的客户端，所以刷新，重试，脱机检查和 `extractApiError` 失败 形状停留在一个地方。从来没有一个 `fetchBaseQuery`.

```ts
// services/api/apiSlice.ts
import { publicClient, userClient } from '@webority/mobile-core';
import { createApiBaseQuery, createAppApi, buildListQuery, providesPagedList,
  type PagedDataObject } from '@webority/mobile-core/query';

export const apiSlice = createAppApi({
  reducerPath: 'api',
  baseQuery: createApiBaseQuery({ client: userClient, publicClient }),
  tagTypes: ['Project'],
  endpoints: (build) => ({
    getProjects: build.query<PagedDataObject<Project>, { page: number }>({
      query: ({ page }) => ({ url: '/api/projects', params: buildListQuery({ page, pageSize: 20 }) }),
      providesTags: providesPagedList('Project')
    })
  })
});
// store.ts: add apiSlice.reducer and apiSlice.middleware, then setupApiListeners(store.dispatch)
```

`setupApiListeners` 将应用程序映射到前台(`AppState`)到RTK查询的焦点， 并将本馆的网络状态分为线上和线下；RTK自己的默认值 `window` 从未在设备上触发的事件。有标记的呼叫 `silent: true`的端点 `extraOptions: { silent: true }`, `silent` 在 `action.meta.baseQueryMeta`，其中 吐司中间件跳过错误。

`/push` 为手机注册推送通知。它需要 `expo-notifications`，可选 同行和报告 `unavailable` 没有它或在世博会上。呼叫 `initPush` 在开始的时候 `getInstallationId`， `register`， `unregister` 和 `onOpen`； `enablePush` 请求许可，发送 本地令牌(`Fcm` 在Android上, `Apns` 在iOS上)和bundle id to `register`, 当令牌更改时重新注册； `disablePush` 调用 `unregister` 开关只推一次 它成功了（失败拒绝并留下push）。 `resetPush` 把电话按下，没有 服务器调用并丢弃本机令牌，用于没有会话剩余的签出。 `onOpen` 接收 点击通知的数据为字符串，包括启动应用的点击。 `usePush` 给出了一个 设置开关 `status` 和 `enabled`。库不记得这个开关：一个应用程序 保持来电推送 `enablePush` 每次出发。 `setBadgeCount(count)` 设置应用图标徽章。 `dismissAllNotifications()` 清除通知托盘中的每个通知；它从不抛出，并在warn处记录失败。

-   `enablePush({ prompt: false })` 从不显示权限提示：已授予的电话 静默注册，并且任何其他都以其状态(`undetermined` 当人已不在 有人问过， `denied` 当拒绝时，提示仍然可以显示， `blocked` 当只有 设置可以打开它)。在签到时打电话，然后打电话 `enablePush()` 当 人到了问问题有意义的时候。
-   每个注册设备都携带 `timeZone`，手机的IANA区域(`Asia/Kolkata`)，或为空 平台不报告任何信息，因此服务器可以在用户的本地时间发送信息。
-   每个注册设备都携带 `apnsEnvironment`： `Development` 或者 `Production` 在iOS上，请阅读 从构建的 `aps-environment` （expo-application），因此服务器将每个电话发送到 apn网关其签名接受。它在Android上为空，在iOS上无法读取时为空 模拟器);然后服务器使用它自己的设置。
-   `onReceive(handler)` 调用 `handler({ notificationId, title, body, data })` 为每一个 通知在应用打开时到达，显示或不显示，所以应用可以刷新列表或 未读计数。它返回一个删除处理程序的函数。通知到达 背景没有达到它；它的水龙头仍然是 `onOpen`.

### 离线副本

`createPersistedQueries` 将所选端点的答案保存在手机上，因此打开了一个屏幕 “无连接”显示最后一次加载数据的时间。列出的端点保存到 `Storage` 当它们装载时； `restore` 一开始就放回去。

1.  通过 `extractRehydrationInfo` 来 `createAppApi`.
2.  添加 `middleware` 在api的中间件之后。
3.  呼叫 `restore(store.dispatch)` 在创建存储之后。
4.  呼叫 `clear()` 签到，所以下一个接电话的人永远不会看到上一个人的数据。

```ts
// services/api/offlineQueries.ts
export const offlineQueries = createPersistedQueries({
  storageKey: 'offline.queries',
  endpoints: ['getProjects']
});

// services/api/apiSlice.ts: add extractRehydrationInfo: offlineQueries.extractRehydrationInfo
// store.ts: reducer: { [apiSlice.reducerPath]: apiSlice.reducer }
//           middleware: (getDefault) => getDefault().concat(apiSlice.middleware, offlineQueries.middleware)
offlineQueries.restore(store.dispatch); // once, after the store exists
// sign-out
await offlineQueries.clear();
```

还原后的答案立即显示，无需取回，所以设置 `refetchOnMountOrArgChange: true` 在每一个 保留端点：挂载的屏幕再次询问服务器并刷新已恢复的数据。

### 通知按钮

push命名一个类别；这个类别的按钮是在手机上注册的。在以下网址登记 每次开始，在两个平台上使用相同的id：

```ts
import { setCategories, notifyLocal } from '@webority/mobile-core/push';

await setCategories([
  {
    id: 'approval',
    actions: [
      { id: 'approve', title: 'Approve', opensApp: false },
      { id: 'reject', title: 'Reject', destructive: true }
    ]
  },
  {
    id: 'reply',
    actions: [
      {
        id: 'reply',
        title: 'Reply',
        opensApp: false,
        textInput: { submitTitle: 'Send', placeholder: 'Write a reply' }
      }
    ]
  }
]);
```

`opensApp` 默认为true； `destructive` 和 `authenticationRequired` （首先解锁）是iOS 只有。点击按钮到达 `{ actionId, userText, data, notificationId }`： `userText` 是 回复文本, `data` push数据作为字符串， `notificationId` 通知的标识符为 电话。一个普通的水龙头仍然是 `onOpen`； 没有处理程序的按钮点击像普通点击一样打开。

要接收每个应用状态下的按钮点击，被杀死的应用包括call `definePushActionTask` 在根组件注册之前，在入口文件的模块范围内。它需要 `expo-task-manager`，可选的对等体(`npx expo install expo-task-manager`)，所以它以自己的方式生活 自己的路:

```js
// index.js
import { definePushActionTask } from '@webority/mobile-core/push/task';
import { notifyLocal } from '@webority/mobile-core/push';

definePushActionTask(async ({ actionId, userText, data }) => {
  try {
    await settle(actionId, userText, data);
  } catch {
    await notifyLocal({ title: 'Could not approve', body: 'Open the app to try again.' });
  }
});
```

等待处理程序的promise，因此它的请求可以在后台工作结束之前完成。 `onAction(handler)` 从 `/push` 在JavaScript运行时为点击设置相同的处理程序 返回一个删除它的函数。在10秒内报告了两次回应(发射为， 侦听器和Android任务可以各自报告它运行一次。

-   **Android:** 控件上的按钮点击时，后台通知任务运行处理程序 按钮只出现在通知上，博览会通知绘图 例子 `notifyLocal`）. 这是一款应用程序，它可以从纯数据推送中获取自己的通知 每个按钮的意图都要用世博会的 `NotificationsService.createNotificationResponseIntent`， 所以tap到达这个处理程序。
-   **iOS:** 一个带有 `opensApp: false` 在后台启动应用程序；响应 到达听众 `definePushActionTask` 设置。任务未在iOS上注册。

存储和网络状态保持在主桶上，但不加载自己的包。把它们连接在 启动与 `setStorageImplementation` 和 `setNetworkStatusImplementation` 如果你想要的话。

## 构建号标头和强制更新

两个HTTP客户端都发送 `App-Build: <integer>` 在每个请求上：应用程序的整个构建号 （`VERSION_INTERNAL`， Android版本码，iOS CFBundleVersion)。API将其与最小值进行比较 答案是426的旧建筑 `client_update_required`。这个数字来自 `initWebority({ appBuild })` （`setConfig({ appBuild })`)， else来自expo-application’s `nativeBuildVersion`。如果没有整数，报头将被删除，并且服务器永远不会拒绝 没有它的请求。 `Client-Build` （`<appVersion>+<commit>`)不变。

两个HTTP客户端也发送 `Client-App: <appId>` 当配置有一个app id (`initWebority({ appId })`）。 它是应用程序的商店标识符，因此API可以区分相同客户端类型的应用程序。

版本层只来自于 `Min-App-Version` 响应头。当一个答复带着它， `useVersionCheck` 转 `isUpdateRequired` 对于它下面的构建。一个426 `client_update_required` 不移动地板，所以没有标题的426离开地板。426永远不会 重试。

应用程序通过运行移动到该合约 `webority upgrade 0.93.0`。它重新命名旧的 `X-` 头 字符串到普通名称， `ApiError.detail` 来 `diagnostic` 和 `detail.signOutReason` 来 `detail.code`，并列出每个已删除的选项(`correlationIdHeader`， `signOutReasonHeader`), 一个人要删除的常量。

## 静默请求和日志编校

两个HTTP客户端都记录了一个失败的响应 `Logger.error`。对于一个呼叫失败的应用程序 处理自己，传递 `skipErrorLog: true` 在axios配置和客户端保持沉默：

```ts
await userClient.get('/status', { skipErrorLog: true });
```

`Logger` 在任何接收器看到它们之前隐藏每个消息和参数中的秘密： `Bearer` 令牌, jwt形状的字符串，以及名为 `token`， `accessToken`， `refreshToken`， `password` 和 `authorization` （任何情况下）的对象和JSON字符串。

`configureLogger({ redactKeys })` 将应用程序键添加到内置屏蔽列表中，并且永远不会删除一个。 `Logger.getBreadcrumbs()` 返回最后50个面包屑，最老的放在第一位，已经编辑； `configureLogger({ breadcrumbLimit })` 改变盖子。 `initWebority` 这是必需的 `remoteLogger`水槽，或者 `null` 对于没有崩溃报告的构建。这也是必需的 `appId`，商店id (`APP_ID` 在appsettings。Json，没有环境后缀)，以及一个必需的 `environment`。它添加了环境的后缀(`.development`， `.staging`当结果与已安装的应用的id不同时，拒绝启动。

## 应用锁

`@webority/mobile-core/appLock` 当一个登录的人在锁定延迟（默认为5分钟）后返回时，锁定应用程序。 `useAppLock` 返回设置屏幕和锁定屏幕需要的内容：

```ts
import { useAppLock } from '@webority/mobile-core/appLock';

const { locked, enabled, biometricAvailable, availabilityKnown, setEnabled, unlock } = useAppLock({ active: isSignedIn });
```

-   `availabilityKnown` 在第一次生物识别检查结束前都是假的。在那之前 `biometricAvailable` 还不是答案，所以屏幕应该等待，然后显示锁不可用或禁用其开关。
-   `setEnabled(next)` 和 `unlock(reason)` 返回一个 `AppLockResult`： `{ ok: true }`，或者 `{ ok: false, reason }` 有了理由 `cancelled`， `lockout`， `not-enrolled`， `not-available` 或者 `failed`.
-   `policy` 覆盖延迟和两个存储键；默认值用于任何遗漏的键。

## 地铁桥

`@webority/mobile-core/metro` 构建Metro开发工具所读取的开发桥梁 `globalThis.__METRO_BRIDGE__`。应用程序在下面分配它 `__DEV__`； 建造者没有添加自己的检查。

```ts
import { createMetroBridge } from '@webority/mobile-core/metro';

if (__DEV__) {
  globalThis.__METRO_BRIDGE__ = createMetroBridge({ store, navigationRef, signIn, signOut, isSignedIn });
}
```

-   `store`Redux存储，通读 `getState` 写了一遍 `dispatch`.
-   `navigationRef`：导航容器的ref (`isReady`， `getRootState`， `canGoBack`， `goBack`， `navigate`）。
-   `signIn(request)` 解决了 `{ codeRequired }`； `signOut()` 一旦会话被清除就解析； `isSignedIn()` 返回一个布尔值。
-   `commands` （可选）：额外命名的命令。一个名字 `signIn`， `signOut` 或者 `navigate` 抛出 创建桥的时候。

这座桥暴露了 `commands` （`signIn`， `signOut`， `navigate`，以及额外费用)， `navigation` （`getState`，在导航器准备好之前，该值为空 `goBack`，返回 `{ wentBack }`)， `redux`， `auth` （`isSignedIn`), `push` （`notifyLocal` 和 `deviceToken`，设备的推送令牌)。

## 常见问题

### @webority/mobile-core 是什么？

webbority React Native应用的平台层：HTTP客户端、认证/令牌存储、配置、日志、格式化器、验证器、网络状态、权限、存储、版本检查和无线更新。没有用户界面。

### 如何安装 @webority/mobile-core？

在项目目录运行 npm install @webority/mobile-core，或使用 pnpm add / yarn add / bun add。它还需要宿主项目提供 peer 依赖：expo（\>=57\.0\.0）、react（^19\.1\.0）、expo-crypto（\>=57\.0\.0）、expo-sqlite（\>=57\.0\.0）、expo-network（\>=57\.0\.0）、react-native（\>=0\.81\.0）、expo-application（\>=57\.0\.0）、expo-secure-store（\>=57\.0\.0）。npm 7 及以上与 pnpm 8 及以上默认会自动安装必需的 peer 依赖，Yarn 需要手动安装。

### @webority/mobile-core 支持 TypeScript 吗？

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

### @webority/mobile-core 支持 ESM 还是 CommonJS？

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

### @webority/mobile-core 可以商用吗？

@webority/mobile-core 使用 SEE LICENSE IN LICENSE\.txt 许可。许可条款写在包内的独立文件中，请阅读该文件确认可否商用。以上为概括，不构成法律意见，请以许可原文为准。

### @webority/mobile-core 还在维护吗？

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

