@datafn/server

中文文档
0.2.1发布于 2026/11/11MITTypeScriptESM + CJS构建来源已验证近 30 天下载 3201

DataFn 服务器运行时间 - DFQL 查询、变异和同步的 HTTP 端点

中文使用文档
文档目录28 节
  1. 安装
  2. 特征
  3. 初步地区安置
  4. 快速启动
  5. 配置
  6. 数据fnServer 配置
  7. 绘图
  8. 终点
  9. 获取/datafn/状态
  10. POST / 数据fn/克瑞
  11. POST /数据fn/搜索
  12. POST/数据fn/计算
  13. POST/数据fn/交易
  14. POST / 数据fn/ clone
  15. POST/数据fn/推
  16. POST/数据fn/推
  17. POST /数据fn/调节
  18. POST /数据fn/种子
  19. 多用途/多用途隔离
  20. 序列存储
  21. 创建序列Store( 配置)
  22. REST 终点( 可选)
  23. 网络安全套
  24. 插件
  25. 服务器实例
  26. 出口
  27. 许可证
  28. 修复继承的不活动

@ datafn/ 服务器

DataFn的HTTP服务器运行时间. 提供DFQL查询执行,以一能和乐观的相通性进行突变,原子交易,完全双向同步(clone/pull/push/reconcile/seed),每个用户/租户隔离,REST端点生成,WebSocket实时更新,插件钩,可配置限制.

安装

npm install @datafn/server @datafn/core @superfunctions/db @superfunctions/http @superfunctions/http-hono hono @hono/node-server

特征

特性说明
查询执行DFQL 有过滤、排序、页码、关系、聚合等查询
变异CRUD 具有一能性(clientId + 键 mutationId 减值)和乐观货币(if 警卫)
关系操作relate, (中文(简体) ), unrelate, (中文(简体) ), modifyRelation 用于多种关系类型和其他关系类型
交易有查询+变异步骤的原子多步操作
同步: 克隆初始水合的全部数据下载
同步: 拉基于光标的递增更改同步
同步: 推从客户端更改日志上传下线突变
同步: 调和探测并解决地上/远地漂流
同步:种子种子数据输入数据库
授权行动授权钩
多用户隔离用于跟踪变化的用户/租户命名空间隔离
多区域网关原租户的安置、执行前的牢房围栏、经签名的内部转发、有限度地重新试验和控制下的行动
REST 终点在DFQL(GET/POST/PATCH/DELETE)上可选 REST包装器
网络安全套实时光标进行实时更新
插件连接查询、突变和同步到服务器侧
序列存储可插件服务器Seq后端:数据库, Redis, KV, 或连锁商店
有效载荷限制可配置的最大查询限制、交易步骤和有效载荷大小
KV 资源内置的密钥值资源自动包含在计划内

多区域网关模式是可选入的,并保持所有权与 权限指令投影。 见 multi-region-gateway.mdx 用于配置、错误、 WebSocket、一致性、迁移和操作 合同.

初步地区安置

DataFn 在不嵌入产品数据的情况下提供可重复使用的区域选择 居住或能力政策:

import {
  readDatafnCloudflarePlacementLocation,
  selectDatafnPlacementRegion,
} from "@datafn/server/placement";

const decision = selectDatafnPlacementRegion({
  candidates: regions,
  location: readDatafnCloudflarePlacementLocation(request),
  constraints: [
    (region) => allowedRegionIds.includes(region.regionId),
    (region) => healthyRegionIds.has(region.regionId),
  ],
});

符合条件的明确偏好先取胜, 信任的坐标或大陆 元数据按距离排列其余区域,可选 stableKey 能够确定后退。 返回的决定记录是 已使用。 申请仍负责界定合格区域,收集 明确组织选择,并解剖性地声称由此产生的命名空间 通过放置目录.


快速启动

import { createDatafnServer } from "@datafn/server";
import { drizzleAdapter } from "@superfunctions/db/adapters";
import { toHono } from "@superfunctions/http-hono";
import { Hono } from "hono";
import { serve } from "@hono/node-server";

const server = await createDatafnServer({
  schema: {
    resources: [
      {
        name: "tasks",
        version: 1,
        fields: [
          { name: "id", type: "string", required: true, unique: true },
          { name: "title", type: "string", required: true },
          { name: "completed", type: "boolean", required: true, default: false },
        ],
      },
    ],
  },
  database: drizzleAdapter({ db: myDrizzleInstance, dialect: "postgres" }),
  authorize: async (ctx, action, payload) => {
    return true; // Allow all (replace with real logic)
  },
});

const app = new Hono();
app.route("/", toHono(server.router));
serve({ fetch: app.fetch, port: 3000 });

配置

数据fnServer 配置

interface DatafnServerConfig<TContext = any> {
  /** DataFn schema — validated and normalized at startup */
  schema: DatafnSchema;

  /** Database adapter (e.g. drizzleAdapter, memoryAdapter) */
  database?: Adapter;

  /** Server-side plugins */
  plugins?: DatafnPlugin[];

  /**
   * Authorization callback. Called on every request after JSON parsing.
   * Return true to allow, false to reject with 403 FORBIDDEN.
   */
  authorize?: (
    ctx: TContext,
    action:
      | "status" | "query" | "mutation" | "transact"
      | "seed" | "clone" | "pull" | "push" | "reconcile",
    payload: unknown,
  ) => Promise<boolean> | boolean;

  /** Static request context or a request-scoped context factory. */
  context?: TContext | ((request: Request) => Promise<TContext> | TContext);

  /** Configurable limits */
  limits?: {
    /** Maximum number of records per query (default: 100) */
    maxLimit?: number;
    /** Maximum transaction steps */
    maxTransactSteps?: number;
    /** Maximum request body size in bytes */
    maxPayloadBytes?: number;
  };

  /** Custom server time provider (for testing) */
  getServerTime?: () => number;

  /**
   * Enable REST endpoint generation.
   * When true, generates REST wrappers alongside DFQL endpoints.
   */
  rest?: boolean;

  /**
   * Auth context provider for per-user/tenant isolation.
   * Extracts user/tenant context from request to create isolated namespaces.
   */
  authContextProvider?: {
    getContext: (ctx: TContext) => AuthContext | Promise<AuthContext>;
  };

  /** Trusted namespace and optional actor derivation from request context. */
  namespaceProvider?: {
    getNamespace: (ctx: TContext) => string | Promise<string>;
    getActorId?: (ctx: TContext) => string | undefined | Promise<string | undefined>;
  };

  /**
   * Redis adapter for atomic operations (serverSeq, rate limiting, caching).
   * Used when dbMapping.serverseq = "redis".
   */
  redis?: RedisAdapter;

  /**
   * KV store adapter for simple key-value operations.
   * Must support incr() for serverSeq. Used when dbMapping.serverseq = "kv".
   */
  kvStore?: KVStoreAdapter;

  /**
   * Database mapping — choose which backend for each concern.
   * Default: main database for everything.
   */
  dbMapping?: DbMapping;
}

绘图

将不同的服务器关切运行到不同的后端 :

type DbMapping = {
  /** Backend for serverSeq counter: "db" | "redis" | "kv" */
  serverseq?: "db" | "redis" | "kv";
  /** Backend for rate limiting */
  ratelimiting?: "db" | "redis" | "kv";
  /** Backend for caching */
  cache?: "db" | "redis" | "kv";
};

终点

获取/datafn/状态

服务器健康检查,计划散列,能力和限制.

{
  "ok": true,
  "result": {
    "schemaHash": "a1b2c3...",
    "capabilities": [
      "dfql.query", "dfql.mutation", "dfql.transact",
      "sync.seed", "sync.clone", "sync.pull", "sync.push", "sync.reconcile"
    ],
    "limits": { "maxLimit": 100 },
    "serverTimeMs": 1707000000000
  }
}

POST / 数据fn/克瑞

执行 DFQL 查询,包括全过滤、排序、页码和关系扩展.

请:

{
  "resource": "tasks",
  "version": 1,
  "select": ["id", "title", "completed"],
  "filters": { "completed": false },
  "sort": ["title:asc"],
  "limit": 20
}

回应:

{
  "ok": true,
  "result": {
    "data": [
      { "id": "task:1", "title": "Buy milk", "completed": false }
    ],
    "nextCursor": null
  }
}

过滤操作符 :

运算符示例说明
eq (隐含){ "status": "active" }等数
eq (解释性){ "status": { "eq": "active" } }等数
ne{ "status": { "ne": "archived" } }不等于一个
gt 编号 : gte{ "age": { "gt": 18 } }大于 / 或相等
lt 编号 : lte{ "age": { "lt": 65 } }小于/或等值
like{ "name": { "like": "%john%" } }对大小写敏感的模式匹配
ilike{ "name": { "ilike": "%john%" } }大小写模式匹配
is_null{ "deletedAt": { "is_null": true } }无效
is_not_null{ "email": { "is_not_null": true } }不为空
in{ "status": { "in": ["active", "pending"] } }设定
nin{ "status": { "nin": ["archived"] } }未设定
contains{ "tags": { "contains": "urgent" } }阵列/ JSON 包含

逻辑组 :

{
  "$or": [
    { "status": "active" },
    { "priority": { "gte": 4 } }
  ]
}

POST /数据fn/搜索

通过配置的服务器执行跨资源搜索 searchProvider。 。 。 .

请:

{
  "query": "test",
  "resources": ["tasks", "projects"],
  "limit": 20,
  "prefix": true,
  "fuzzy": 0.2,
  "fieldBoosts": { "title": 2, "name": 1 }
}

回应:

{
  "ok": true,
  "result": {
    "results": [
      { "resource": "tasks", "id": "task:1", "score": 12.34, "data": {} }
    ]
  }
}

与客户端路径的搜索选项均等 :

  • prefix 启用前缀匹配 .
  • fuzzy 允许模糊匹配 .
  • fieldBoosts 应用字段级加权.

这些选项在路由/平流边界被验证后被传送到提供者执行.

汇总查询 :

{
  "resource": "tasks",
  "version": 1,
  "groupBy": ["status"],
  "aggregations": {
    "count": { "fn": "count" },
    "avgPriority": { "fn": "avg", "field": "priority" }
  },
  "having": { "count": { "gt": 5 } }
}

POST/数据fn/计算

以一能和乐观的货币来执行突变.

插入:

{
  "resource": "tasks",
  "version": 1,
  "operation": "insert",
  "clientId": "client:device-1",
  "mutationId": "m-001",
  "record": { "title": "New task", "completed": false }
}

合并( 部分更新) :

{
  "resource": "tasks",
  "version": 1,
  "operation": "merge",
  "clientId": "client:device-1",
  "mutationId": "m-002",
  "id": "task:abc",
  "record": { "completed": true }
}

删除:

{
  "resource": "tasks",
  "version": 1,
  "operation": "delete",
  "clientId": "client:device-1",
  "mutationId": "m-003",
  "id": "task:abc"
}

乐观货币( 如果是警卫):

{
  "resource": "tasks",
  "version": 1,
  "operation": "merge",
  "id": "task:abc",
  "record": { "status": "completed" },
  "if": { "status": "in_progress" }
}

变异被拒绝 CONFLICT 如果看守条件没有得到满足.

关系业务:

{
  "resource": "tasks",
  "version": 1,
  "operation": "relate",
  "id": "task:1",
  "relation": "tags",
  "targetId": "tag:urgent"
}
运行说明
relate在记录之间建立关系
unrelate删除关系
modifyRelation更新关系元数据

回应:

{
  "ok": true,
  "result": {
    "ok": true,
    "mutationId": "m-001",
    "affectedIds": ["task:new-uuid"],
    "errors": [],
    "deduped": false
  }
}
  • deduped: true 表示已应用了突变(偶发性).

POST/数据fn/交易

原子多步骤交易混合了询问和突变.

原子执行需要数据库交易. 适配器报告时 capabilities.transactions.supported === false (例如SQLite或Cloudflare D1上的Drizzle适配器),一个带有任何变异步骤的原子变换器返回 HTTP 400 与 DFQL_UNSUPPORTED (单位:千美元)details.path: "atomic")在任何东西被写入之前. 发送 "atomic": false 一次实施步骤一.

请:

{
  "transactionId": "tx-batch",
  "atomic": true,
  "steps": [
    {
      "query": {
        "resource": "tasks",
        "version": 1,
        "select": ["id"],
        "filters": { "completed": false }
      }
    },
    {
      "mutation": {
        "resource": "tasks",
        "version": 1,
        "operation": "merge",
        "id": "task:1",
        "record": { "completed": true }
      }
    }
  ]
}

回应:

{
  "ok": true,
  "result": {
    "ok": true,
    "results": [
      { "kind": "query", "ok": true, "result": { "data": [...] } },
      { "kind": "mutation", "ok": true, "result": { ... } }
    ]
  }
}

POST / 数据fn/ clone

初始水分完全数据下载. 支持帕吉纳克.

请:

{
  "version": 1,
  "tables": ["tasks", "categories"]
}

回应:

{
  "ok": true,
  "result": {
    "ok": true,
    "data": {
      "tasks": [{ "id": "task:1", "title": "..." }],
      "categories": [{ "id": "cat:1", "name": "..." }]
    },
    "cursors": {
      "tasks": "42",
      "categories": "15"
    }
  }
}

POST/数据fn/推

递增同步——仅返回自上个光标后的变化 .

请:

{
  "version": 1,
  "cursors": {
    "tasks": "42",
    "categories": "15"
  }
}

回应:

{
  "ok": true,
  "result": {
    "ok": true,
    "records": {
      "tasks": [{ "id": "task:3", "title": "New since last pull", "__deleted": false }]
    },
    "cursors": {
      "tasks": "44",
      "categories": "15"
    }
  }
}

POST/数据fn/推

从客户端更改日志上传下线突变.

请:

{
  "version": 1,
  "mutations": [
    {
      "resource": "tasks",
      "version": 1,
      "operation": "insert",
      "clientId": "client:device-1",
      "mutationId": "m-offline-1",
      "record": { "title": "Created offline" }
    }
  ]
}

POST /数据fn/调节

探测并解决本地和偏远地区之间的漂移.

请:

{
  "version": 1,
  "counts": {
    "tasks": 42,
    "categories": 8
  }
}

POST /数据fn/种子

种子数据输入数据库.

请:

{
  "data": {
    "tasks": [
      { "id": "task:seed-1", "title": "Seeded Task", "completed": false }
    ]
  }
}

多用途/多用途隔离

按用户或租户单独跟踪变化情况。 每个命名空间都有自己的 serverSeq 计数器,确保用户只看到自己的修改.

const server = await createDatafnServer({
  schema,
  database: adapter,
  authContextProvider: {
    getContext: (ctx) => ({
      userId: ctx.session?.userId,
      tenantId: ctx.session?.tenantId,
    }),
  },
});

命名空间格式 :

  • 无认证 : datafn (默认)
  • 单租户: user:${userId}
  • 多租户: tenant:${tenantId}:user:${userId}

行为:

  1. 每一个要求, authContextProvider.getContext(ctx) 名为
  2. 命名空间来源于 userId 和可选 tenantId
  3. 所有更改跟踪( 服务器Seq, 更改记录) 都使用此命名空间
  4. Pull/ clone 只返回用户命名空间的更改
  5. 若为 getContext() 失败, 回到默认状态 datafn 命名空间

序列存储

服务器使用 SequenceStore 用于生成单调增序数。 选择适合您的基础设施的后端 :

// Default: use main database
const server = await createDatafnServer({
  schema,
  database: adapter,
});

// Redis for high-throughput atomic INCR
const server = await createDatafnServer({
  schema,
  database: adapter,
  redis: myRedisAdapter,
  dbMapping: { serverseq: "redis" },
});

// KV store (e.g. Cloudflare KV, DynamoDB)
const server = await createDatafnServer({
  schema,
  database: adapter,
  kvStore: myKVAdapter,
  dbMapping: { serverseq: "kv" },
});

可用的执行:

存储后端最好还是
DatabaseSequenceStore主数据库简单部署
RedisSequenceStore重写高吞吐量,原子内核
KVSequenceStoreKV 存储无服务器环境
ChainedSequenceStore链条初级+数据库链(例如Redis → DB)

创建序列Store( 配置)

创建适当商店的工厂 dbMapping数字 :

import { createSequenceStore } from "@datafn/server";

const store = createSequenceStore({
  db: myAdapter,
  redis: myRedisAdapter,
  dbMapping: { serverseq: "redis" },
});

REST 终点( 可选)

启用 DFQL 端点旁的 REST 包装器 :

const server = await createDatafnServer({
  schema,
  database: adapter,
  rest: true, // Enable REST endpoints
});

生成路线 :

方法路径地图到
获取/datafn/resources/:resource查询包装
邮政/datafn/resources/:resource插入包装
帕齐/datafn/resources/:resource/:id合并包装
迪莱特/datafn/resources/:resource/:id删除包装

网络安全套

服务器显示一个用于实时光标广播的 WebSocket 处理器:

const server = await createDatafnServer({ schema, database: adapter });

// Wire WebSocket connections to server handler
wss.on("connection", (ws) => {
  const client = { id: ws.id, send: (msg) => ws.send(msg) };
  server.websocketHandler.addClient(client);
  ws.on("message", (data) => server.websocketHandler.handleMessage(client, data));
  ws.on("close", () => server.websocketHandler.removeClient(client));
});

插件

服务器端插件拦截查询、突变和同步 :

const auditPlugin: DatafnPlugin = {
  name: "server-audit",
  runsOn: ["server"],

  afterMutation(ctx, mutation, result) {
    console.log("Server mutation:", mutation);
  },

  beforeSync(ctx, phase, payload) {
    console.log(`Sync ${phase} started`);
    return payload; // Return modified payload or original
  },
};

const server = await createDatafnServer({
  schema,
  database: adapter,
  plugins: [auditPlugin],
});

服务器实例

createDatafnServer 返回 a DatafnServer数字 :

interface DatafnServer<TContext = any> {
  /** HTTP router — wire to your framework (Hono, Express, etc.) */
  router: Router<TContext>;

  /** WebSocket handler for real-time updates */
  websocketHandler: {
    addClient(client: WebSocketClient): void;
    removeClient(client: WebSocketClient): void;
    handleMessage(client: WebSocketClient, data: string): void;
  };
}

使用 @superfunctions/http-hono 或者说 @superfunctions/http-express 以挂载路由器 :

// Hono
import { toHono } from "@superfunctions/http-hono";
app.route("/", toHono(server.router));

// Express
import { toExpress } from "@superfunctions/http-express";
app.use("/", toExpress(server.router));

出口

// Server factory and types
export { createDatafnServer }
export type { DatafnServerConfig, DatafnServer }
export type { StatusResult }

// Sequence store
export type { SequenceStore, DbMapping }
export {
  createSequenceStore,
  RedisSequenceStore,
  KVSequenceStore,
  DatabaseSequenceStore,
  ChainedSequenceStore,
}

许可证

麻省理工学院

修复继承的不活动

recomputeAncestorInactive 在一个命名空间中扫描已限定的批次; 以 nextCursor。 。 。 . recomputeAncestorInactiveAll 重复扫描直到验证 扫描找不到更改或跳过比较和设置的写入 。 检查 converged· ; updated: 0 单靠自己不能证明完成. skipped 计数同时写入 冲突。 干运行数不匹配而不写入 .

修复从祖先存档/崩溃状态和关系链接中获取值, 从不存储 isAncestorInactive 旗帜。 周期、缺失/畸形父母, 越轨限制的违反会造成明显的错误. batchSize, (中文(简体) ), maxSweeps 财务报告和审定财务报表 maxGraphNodes 必须是正安全整数; maxGraphNodes 默认为 每行修补一万个节点。 失败的批次可以安全重放; 之前完成的写作是一能的.

以祖先/链接突变进行修复 比较和设定保护 每个字段来自同时传播的文字;它不提供 所有祖先记录的原子快照 同时恢复和核实 活动在依赖修复的价值进行消费者迁移之前就已解决.

版本与发布记录

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

版本发布日期距今
0.2.1latest2026/11/11今天
0.1.4-maint.0maint2026/11/038 天前
0.2.02026/09/201 个月前
0.1.32026/09/161 个月前
0.1.12026/08/312 个月前
0.1.02026/08/292 个月前

关于 @datafn/server 的常见问题

@datafn/server 是什么?

DataFn 服务器运行时间 - DFQL 查询、变异和同步的 HTTP 端点

如何安装 @datafn/server?

在项目目录运行 npm install @datafn/server,或使用 pnpm add / yarn add / bun add。

@datafn/server 支持 TypeScript 吗?

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

@datafn/server 支持 ESM 还是 CommonJS?

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

@datafn/server 需要什么版本的 Node.js?

package.json 的 engines 字段要求 Node.js >=18.18.0。版本不符时 npm 默认只给出警告,开启 engine-strict 后会拒绝安装。

@datafn/server 可以商用吗?

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

@datafn/server 的下载量有多少?

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

@datafn/server 还在维护吗?

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