@_linked/server-utils

中文文档
1.17.0发布于 2026/10/28MITTypeScriptES Module构建来源已验证近 30 天下载 4429

为应用提供一套具有林克-服务器后端的公用事业.

中文使用文档
文档目录8 节
  1. 服务器
  2. 调用失败
  3. 认证钩
  4. 客户端可以调用哪些提供者的方法
  5. 无用户工作 : runAsSystem
  6. 链接电子邮件
  7. 设置默认提供者
  8. 共享状态和错误品牌

林克-服务器-实用

为应用提供一套具有林克-服务器后端的公用事业.

服务器

import { Server } from 'lincd-server-utils/lib/utils/Server';

从前端呼叫服务器 .

调用失败

默认情况下,一个无法使用非-2xx响应的呼叫会记录一个警告并解决 undefined。 。 。 .

拒绝,通过一个 CallConfig 与 rejectOnError: true 作为方法 :

import { Server, ServerCallError } from '@_linked/server-utils/utils/Server';

try {
  const result = await Server.call(this, { method: 'selectQuery', rejectOnError: true }, query);
} catch (err) {
  if (ServerCallError.is(err)) {
    err.status; // e.g. 500 (provider threw) or 501 (no provider for the call)
    err.message; // the server's {error} message, or the status text
  }
}

随着选择进入,一个成功的呼叫仍然解决 任何提供者返回,包括 null 或者说 undefined。 。 。 .

在后门上, Server.call 直接调用本地服务器并遵循相同的规则 :

  • 无供养. 一个没有提供者处理的电话解决了 undefined 默认。 与 rejectOnError 它以501的地位拒绝.
  • 供养所掷. 一个总是拒绝的提供者方法。 与 rejectOnError 拒绝是 ServerCallError 状态 500,原始错误保留为 cause。 。 。 .

认证钩

认证软件包通过注册让服务器呼叫周围的会话存在 AuthHandler. 服务器使用器对符号一无所知: 处理器更改默认信头(Server.addDefaultHeaders 编号 : Server.removeDefaultHeaders)),而每个请求头都是在钩子运行后所建.

import { Server } from '@_linked/server-utils/utils/Server';

Server.setAuthHandler({
  // before every request: e.g. refresh a token that has already expired
  async beforeRequest(url, init) {
    if (tokenExpired()) await refresh(); // refresh() calls Server.addDefaultHeaders(...)
  },
  // after a 401: resolve true to send the request again, once, with the current default headers
  async onUnauthorized(url, response) {
    return refresh();
  },
});
  • 打电话来. HTTP的每个电话: Server.call, (中文(简体) ), Server.customPost 财务报告和审定财务报表 Server.callCustomShapeMethod。直接针对后端本地服务器的电话不使用。 有一个处理器;设置另一个替换它 null 将取去.
  • init 是一个预览. 要更改发送的内容, 请更改默认标题 .
  • 401号. 403表示来电者是已知的且不允许的;刷新无济于事,所以不会传递给 onUnauthorized。 。 。 .
  • 每个电话最多一次重试. 重试的回复是给打电话的人的: onUnauthorized 再来一次 如果在请求飞行时默认头部发生变化(同时刷新了另一通电话),则401在一次重审时无需询问.
  • 货币. 重试状态属于每个呼叫. 做同时刷新 分享一次往返是处理者的工作.
  • 扔钩子 被登录,并作为“无变化” /“不重试”.
  • 反应行动没有经过反复研究. 一个回答的提供者 200 反应行动(例如: @_linked/auth是因为 ENFORCE_SIGNIN)已经运行了,并且可能在决定来电者不签名之前写过一些东西,所以再次发送请求并不安全. 反应行动将持续到 Server.registerActionHandler。 。 。 .

callCustomShapeMethod 发送默认信头, 但 Content-Type (身体经常是) FormData,它需要浏览器来设定边界。 信头传递给它胜利。 它的躯体又被重试送去,所以使用一个能成为躯体的躯体(一串, FormData页:1 Blob),不是溪流.

客户端可以调用哪些提供者的方法

提供者方法可以达到 /call/... 只有在它被宣布的时候。 类型脚本 private 财务报告和审定财务报表 protected 在运行时间不存在,所以宣言是决定的。 有三个宣言,全部在 @_linked/server-utils/utils/callable (没有服务器导入, 可以安全加载客户端):

  • @callable('public' | 'signed-in') 使用实例方法,或 declareCallable(Cls, {method: level}) (原始内容存档于2018-09-21) (英语). In plain JS. 'user' 是一个已贬值的别名,其名称是: 'signed-in',对待完全像它.
  • @internal() 使用实例方法,或 declareInternal(Cls, ['method'])。它也用于您从另一个软件包导入的类.
  • 终不宣说.

当客户称这个方法时 每个人会做什么:

声明超过 HTTP
@callable('public')任何人都可以打电话, 签名与否.
@callable('signed-in')没有会话, 服务器会回答 401 在方法体运行之前。 机体从调用上下文读取用户,从不读取其论据.
未申报取决于 server.rpcExposure 内 @_linked/server: 内 warn 模式(默认)它运行一次并记录一次 enforce 模式 501,似乎该方法不存在.
@internal()从未以任何方式通过 HTTP 发送( )501),即使它也被宣布为可调用. 后端代码仍然使用 Server.call。 。 。 .

为登录用户采取行动的方法必须宣布 @callable('signed-in') 并读取用户 requireSessionUser()。 。 。 . 'public' 允许任何人进入,而参数中的用户id是客户端发送的任意信息.

import { BackendProvider } from '@_linked/server-utils/utils/BackendProvider';
import { callable, internal } from '@_linked/server-utils/utils/callable';
import { requireSessionUser } from '@_linked/server-utils/utils/CallContext';

export default class NotesBackendProvider extends BackendProvider {
  @callable('public')
  getPublicNotes() {
    return loadPublicNotes();
  }

  @callable('signed-in')
  getMyNotes() {
    const user = requireSessionUser(); // the session's user account, not an argument
    return loadNotesOf(user);
  }

  @internal()
  purgeNotes(olderThan: Date) {
    // only reachable from backend code
  }
}

requireSessionUser() 丢出一个 401 ServerCallError 在HTTP呼叫中,没有一个会话,所以它也是对一种方法的检查,有人忘记了它.

一些规则值得了解:

  • 只能宣告实例方法;静态方法或错误的页码名称丢出一个 TypeError。 。 。 .
  • 一个子类,在不重新宣布的情况下,将宣布的最严格级别保留在它的阶级链上('signed-in' 结束 'public') (中文(简体) ). @internal() 被覆盖所继承,并且胜过可调用的声明(带有警告).
  • 后端到后端的呼叫( N)Server.call )跳过这些检查,包括内部方法.

无用户工作 : runAsSystem

每个HTTP呼叫都运行在带有其请求的呼叫上下文中,因此一个呼叫的用户遵循它所期待的或计划的一切. 未为该用户完成的工作,如从请求内开始的工作、计时器或队列消费者,必须包入 runAsSystem,或以该请求的用户身份运行 :

import { runAsSystem } from '@_linked/server-utils/utils/CallContext';

runAsSystem(() => startNightlyReindex(), 'nightly reindex');

在系统内 requireSessionUser() 抛出平原 Error (没有用户可以接受);在那里,一个用户的行为得到该用户的明确通过. getCallContext() 返回时 {kind: 'http', request, response} 或者说 {kind: 'system', reason}。 。 。 .

链接电子邮件

从后端的任何地方发送邮件 .

确保先安装电子邮件客户端, 如 lincd-zeptomail。 。 。 . 通过添加 lincd-zeptomail 到您的项目( in package.json), 它会自动用作默认的电子邮件客户端 .

在此之后, 您可以从后端的任何地方发送邮件 .

LinkedEmail.sendEmail({
  ...
});

设置默认提供者

如果您想要执行电子邮件客户端, 您可以使用 LinkedEmail.setDefaultProvider 设置默认的电子邮件客户端. 您可以在您的后端提供者的构造器中做到这一点 。 以下是一个例子:

import { LinkedEmail } from 'lincd-server-utils/lib/utils/LinkedEmail';
// import your email client from this package
import { MyMailClient } from './utils/MyMailClient';
import { BackendProvider } from 'lincd-server-utils/lib/utils/BackendProvider';
export class MyBackendProvider extends BackendProvider {
  constructor(s) {
    super(s);
    LinkedEmail.setDefaultProvider(new MyMailClient());
  }
}

共享状态和错误品牌

此软件包的一个模块可以在一次运行中两次得到评价(Vite's SSR srunder and Node under linked start,或两个浏览器捆绑。 呼叫者设置的州 -- Server.setLocalServer, (中文(简体) ), addDefaultHeaders, (中文(简体) ), setAuthHandler, (中文(简体) ), registerActionHandler, (中文(简体) ), LinkedEmail.setDefaultProvider, (中文(简体) ), 实时更新日志,请求数据——保存在 globalThis 与 sharedState 从 @_linked/core,所以每个副本都能看到它. ServerCallError 标记为: isLinkedError(err, ServerCallError) 从 @_linked/core (或 ServerCallError.is(err)(没有) instanceof。新的代码遵循相同的规则;参见 共享状态和错误品牌。 。 。 .

版本与发布记录

@_linked/server-utils 共发布 41 个版本,首次发布于 2026/04/23;过去 12 个月发布了 41 个版本。最新版本附带 npm provenance 构建来源证明,可追溯到公开的 CI 构建记录。

版本发布日期距今
1.17.0latest2026/10/2810 天前
1.16.22026/10/2513 天前
1.16.12026/10/2414 天前
1.16.02026/10/2415 天前
1.15.02026/10/2216 天前
1.14.12026/10/1919 天前

关于 @_linked/server-utils 的常见问题

@_linked/server-utils 是什么?

为应用提供一套具有林克-服务器后端的公用事业.

如何安装 @_linked/server-utils?

在项目目录运行 npm install @_linked/server-utils,或使用 pnpm add / yarn add / bun add。它还需要宿主项目提供 peer 依赖:react(^18.2.0 || ^19.0.0)。npm 7 及以上与 pnpm 8 及以上默认会自动安装必需的 peer 依赖,Yarn 需要手动安装。

@_linked/server-utils 支持 TypeScript 吗?

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

@_linked/server-utils 支持 ESM 还是 CommonJS?

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

@_linked/server-utils 可以商用吗?

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

@_linked/server-utils 的下载量有多少?

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

@_linked/server-utils 还在维护吗?

最新版本 1.17.0 发布于 2026/10/28(10 天前);至今共发布 41 个版本,其中过去 12 个月发布了 41 个;首次发布于 2026/04/23。发布频率只是参考信号:功能稳定的工具可能很少需要更新,建议结合源码仓库的 issue 和提交记录判断。