@ datafn/ core (帮助)
DataFn生态系统的核心类型、计划验证、DFQL正常化和共享公用事业。 其它 DataFn 软件包取决于 @datafn/core。 。 。 .
安装
npm install @datafn/core
特征
- 类型定义 – 用于计划、资源、字段、关系、事件、信号和插件的完整类型脚本
- Cont-Safe 字段构建器 ——可重复使用的字面定义,保留字面名称,缺省,和enum成员
- Schema 验证 - DataFn计划运行时间验证和正常化
- DFQL 类型 查询、变异和交易类型定义
- DFQL 正常化 ——稳定缓存密钥决定正常化
- 信封图案 - 结构化
ok | error具有帮助函数的结果类型 - KV 公用事业 ——已建成的密钥-值资源助手(
ensureBuiltinKv, (中文(简体) ),kvId(中文(简体) ) - 错误代码 ——假设用于一致处理错误的错误代码
- 结构资源选择器 ——解析请求信封并收集协议级资源选择器用于路由和授权
Schema 定义
一个DataFn schema描述了您的全部数据模型:资源(表),它们的字段,以及它们之间的关系.
使用 defineSchema 完全计划,和 field 当字段需要时
复用过. 既保存字面名称,又保存输入客户端的元数据:
import { defineSchema, field } from "@datafn/core";
const id = field.string("id", {
required: true,
unique: true,
});
const sharedFields = [
field.boolean("isStarred", { default: false }),
field.string("status", {
required: true,
enum: ["NOT_STARTED", "IN_PROGRESS", "COMPLETED"],
}),
];
export const schema = defineSchema({
resources: [
{
name: "tasks",
version: 1,
fields: [id, ...sharedFields],
indices: { base: ["id", "status"] },
},
],
});
实地建设者总是返回平地计数对象并发射
required: false 财务报告和审定财务报表 nullable: false 当这些选项被省略时.
要求控制是否必须存在财产。 独立失效
控制其值是否为 null。 。 。 .
直接传递到内行对象文字 defineSchema 接受同样的
记录推论。 避免将计划或可重复使用的字段收藏注为
DatafnSchema 或者说 DatafnFieldSchema[] 打电话前 defineSchema; 这些
说明扩展字段和资源名称。 使用 satisfies 当你
只需进行可分配性检查,或使用构建器进行可重复使用的字段.
构建器选项针对每个字段类型。 默认成员
匹配该类型, 选项不能覆盖 name 或者说 type. 约束
元数据例如 enum、界限、规律、独特性、加密、波动性,
和只读的旗帜被保存给适配器和生成的图案. 核心
突变验证目前执行字段类型和无效性,而不是每个字段
限制元数据值 .
Datafn 计划
type DatafnSchema = {
resources: DatafnResourceSchema[];
relations?: DatafnRelationSchema[];
};
Datafn 资源计划
每个资源映射到数据库中的表格或收藏.
type DatafnResourceSchema = {
/** Unique resource name (e.g. "todos", "users") */
name: string;
/** Schema version — increment when making breaking changes */
version: number;
/** Optional prefix for generated IDs (e.g. "todo" → "todo:uuid") */
idPrefix?: string;
/**
* When true, the resource is never stored locally.
* Queries always go to the remote server.
*/
isRemoteOnly?: boolean;
/** Field definitions */
fields: DatafnFieldSchema[];
/**
* Index hints for optimisation.
* Can be a simple string[] (treated as base indices) or a structured object.
*/
indices?:
| { base?: string[]; search?: string[]; vector?: string[] }
| string[];
/** Optional permissions policy for server-side authorization */
permissions?: DatafnPermissionsPolicy;
};
Datafn 外地方案
每个字段都有名称,类型,以及丰富的一组可选验证约束.
type DatafnFieldSchema = {
name: string;
type:
| "string"
| "number"
| "boolean"
| "object"
| "array"
| "date"
| "file"
| "json";
required: boolean;
/** Allow explicit null values */
nullable?: boolean;
/** Prevent mutation after initial insert */
readonly?: boolean;
/** Default value applied on insert when the field is omitted */
default?: unknown;
/** Restrict to a fixed set of allowed values */
enum?: unknown[];
/** Minimum numeric value or minimum array length */
min?: number;
/** Maximum numeric value or maximum array length */
max?: number;
/** Minimum string length */
minLength?: number;
/** Maximum string length */
maxLength?: number;
/** Regex pattern the string value must match */
pattern?: string;
/**
* Uniqueness constraint.
* - `true` — globally unique
* - `string` — unique within a composite group
*/
unique?: boolean | string;
/** Encrypt the field value at rest */
encrypt?: boolean;
/** Volatile fields are excluded from sync and persistence */
volatile?: boolean;
};
支持的字段类型 :
| 类型 | 说明 |
|---|---|
string | 文本值 |
number | 数值(整数或浮数) |
boolean | true 编号 : false |
object | 任意 JSON 对象( 存储为 JSONB / JSON) |
array | 任意 JSON 阵列( 存储为 JSONB / JSON) |
date | 日期/时间值(按时间戳计算) |
file | 文件引用 |
json | JSON 相容值 |
数据关系计划
关系描述了资源如何相互联系.
type DatafnRelationSchema = {
/** Source resource name(s) */
from: string | string[];
/** Target resource name(s) */
to: string | string[];
/** Relation cardinality */
type: "one-many" | "many-one" | "many-many" | "htree";
/** Forward relation name (e.g. "tags") */
relation?: string;
/** Inverse relation name (e.g. "todos") */
inverse?: string;
/** Cache relation data for faster reads */
cache?: boolean;
/** Extra metadata fields on the join row (many-many only) */
metadata?: Array<{
name: string;
type: "string" | "number" | "boolean" | "date" | "object";
}>;
/** Foreign key field name (many-one / one-many) */
fkField?: string;
/** Materialized path field (htree) */
pathField?: string;
};
关系类型 :
| 类型 | 说明 | 存储 |
|---|---|---|
one-many | 父母生了很多孩子 父亲生了很多孩子 | 关于儿童的FK |
many-one | 孩子属于父母 | 关于儿童的FK |
many-many | 双方都有很多 | 合并表格 |
htree | 等级树 | 已实现路径 |
Datafn 许可证政策
type DatafnPermissionsPolicy = {
read?: { fields: string[] };
write?: { fields: string[] };
ownerField?: string;
};
活动
事件代表变异和同步操作的生命周期通知.
数据fnEvent
interface DatafnEvent {
type:
| "mutation_applied" // A mutation was successfully applied
| "mutation_rejected" // A mutation was rejected (validation, conflict, etc.)
| "sync_applied" // A sync operation completed successfully
| "sync_failed"; // A sync operation failed
resource?: string; // Affected resource name
ids?: string[]; // Affected record IDs
mutationId?: string; // Mutation identifier
clientId?: string; // Originating client identifier
timestampMs: number; // Event timestamp in milliseconds
context?: unknown; // Arbitrary context data
action?: string; // Mutation action (insert, merge, delete, etc.)
fields?: string[]; // Changed fields
}
数据fnEventFilter 软件
过滤签名时收到的事件 .
type DatafnEventFilter = Partial<{
type: DatafnEvent["type"] | Array<DatafnEvent["type"]>;
resource: string | string[];
ids: string | string[];
mutationId: string | string[];
action: string | string[];
fields: string | string[];
contextKeys: string[];
context: Record<string, unknown>;
}>;
信号
信号是反应性数据容器,代表活性查询结果. 他们是DataFn和你的UI框架之间的桥梁.
Datafn 信号<T>
interface DatafnSignal<T> {
/** Get the current value synchronously */
get(): T;
/** Subscribe to value changes. Returns an unsubscribe function. */
subscribe(handler: (value: T) => void): () => void;
/** True while the initial fetch is in progress */
readonly loading: boolean;
/** Non-null if the last fetch/refresh failed */
readonly error: DatafnError | null;
/** True while a background refresh is in progress (after initial load) */
readonly refreshing: boolean;
}
插件
插件在客户端和服务器上拦截并扩展查询,突变,同步操作.
数据宽度
interface DatafnPlugin {
name: string;
runsOn: Array<"client" | "server">;
/** Intercept queries before execution. Return modified query or throw to reject. */
beforeQuery?: (
ctx: DatafnHookContext,
q: unknown,
) => Promise<unknown> | unknown;
/** Process query results. Return modified result. */
afterQuery?: (
ctx: DatafnHookContext,
q: unknown,
result: unknown,
) => Promise<unknown> | unknown;
/** Intercept mutations before execution. Return modified mutation or throw to reject. */
beforeMutation?: (
ctx: DatafnHookContext,
m: unknown | unknown[],
) => Promise<unknown> | unknown;
/** React to mutation results. */
afterMutation?: (
ctx: DatafnHookContext,
m: unknown | unknown[],
result: unknown,
) => Promise<void> | void;
/** Intercept sync operations before execution. Return modified payload or throw to reject. */
beforeSync?: (
ctx: DatafnHookContext,
phase: "seed" | "clone" | "pull" | "push" | "cloneUp" | "reconcile",
payload: unknown,
) => Promise<unknown> | unknown;
/** React to sync results. */
afterSync?: (
ctx: DatafnHookContext,
phase: "seed" | "clone" | "pull" | "push" | "cloneUp" | "reconcile",
payload: unknown,
result: unknown,
) => Promise<void> | void;
}
DatafnHook 语句
type DatafnHookContext = {
env: "client" | "server";
schema: DatafnSchema;
context?: unknown;
};
DFQL 类型
DFQL (DataFn Query Language) 定义了查询,突变,和交易的结构.
Dfql 查询
type DfqlQuery = {
resource: string;
version: number;
select?: string[]; // Fields to include
omit?: string[]; // Fields to exclude
filters?: Record<string, unknown>; // Where clause
search?: Record<string, unknown>; // Full-text search
sort?: DfqlSort; // Ordering (e.g. ["-createdAt", "name"])
limit?: number; // Max results
offset?: number; // Skip N results
cursor?: DfqlCursor; // Cursor-based pagination
count?: boolean; // Return count only
groupBy?: string[]; // Group by fields
aggregations?: Record<string, unknown>; // Aggregate functions
having?: Record<string, unknown>; // Having clause for groups
};
Dfql 查询断层
缩写 resource 财务报告和审定财务报表 version - 与表API一起使用,其中隐含了这些内容.
type DfqlQueryFragment = Omit<DfqlQuery, "resource" | "version">;
Dfql 调试
type DfqlMutation = {
resource: string;
version: number;
operation: string; // "insert" | "merge" | "replace" | "delete" | "relate" | "unrelate" | "modifyRelation"
id?: string | string[]; // Target record ID(s)
record?: Record<string, unknown>;
records?: Array<Record<string, unknown>>;
clientId?: string; // For idempotency
mutationId?: string; // For idempotency
timestamp?: number | string;
context?: unknown;
relations?: Record<string, unknown>;
if?: Record<string, unknown>; // Optimistic concurrency guards
cascade?: unknown;
};
Dfql 调试 断裂
缩写 resource 财务报告和审定财务报表 version 用于表格 API.
type DfqlMutationFragment = Omit<DfqlMutation, "resource" | "version">;
Dfql 交易
type DfqlTransact = {
transactionId?: string;
atomic?: boolean;
steps: Array<{ query?: DfqlQuery; mutation?: DfqlMutation }>;
};
结构资源选择器
网关和授权插件不得重复检查 JSON 对命名字段的请求 resource 或者说 resources应用记录和过滤器可以合法使用这些名称.
import { extractStructuralResourceSelectors } from "@datafn/core";
const extracted = extractStructuralResourceSelectors("query", payload);
if (extracted.ok) {
extracted.result.selectors; // protocol-level resources only
extracted.result.protocolVersion; // "1"
}
parseDatafnRequest 加号 collectStructuralResourceSelectors 是可堆肥的形式。 不支持 protocolVersion 数值返回 DATAFN_UNSUPPORTED_PROTOCOL_VERSION。 。 。 .
光标排序( C)
type DfqlSort = string[];
// e.g. ["name", "-createdAt"] → name ASC, createdAt DESC (prefix "-" = descending)
type DfqlCursor = {
after?: Record<string, unknown>;
before?: Record<string, unknown>;
};
职能
验证计划
验证并规范 DataFn 计划。 返回一个信封.
import { validateSchema, unwrapEnvelope } from "@datafn/core";
const schema = unwrapEnvelope(
validateSchema({
resources: [
{
name: "user",
version: 1,
fields: [
{ name: "email", type: "string", required: true, unique: true },
{ name: "name", type: "string", required: true },
],
},
],
}),
);
应用规范化 :
- 转换
indices: string[]→{ base: string[], search: [], vector: [] } - 默认
relations改为[]如果省略 - 验证独特的资源名称、字段名称和所需的属性
常规 Dfql
递归常态化确定比较的值:排序对象键,去除 undefined 值、保存原始物、数组和 null。 。 。 .
import { normalizeDfql } from "@datafn/core";
normalizeDfql({ b: 2, a: 1, c: undefined });
// → { a: 1, b: 2 }
dfql 键
为 DFQL 值返回一个稳定的 JSON 字符串。 用作信号的缓存密钥 .
import { dfqlKey } from "@datafn/core";
const key = dfqlKey({ resource: "user", filters: { id: "user:1" } });
// Deterministic JSON string suitable for Map/Set keys
打开信封
解开 DatafnEnvelope: 返回 result 在成功时,抛出 DatafnError 失败.
import { unwrapEnvelope } from "@datafn/core";
const result = unwrapEnvelope(someEnvelope);
// Throws DatafnError if envelope.ok === false
确定/ 错误
帮助创建信封.
import { ok, err } from "@datafn/core";
const success = ok({ data: [1, 2, 3] });
// { ok: true, result: { data: [1, 2, 3] } }
const failure = err("NOT_FOUND", "User not found", { path: "users" });
// { ok: false, error: { code: "NOT_FOUND", message: "User not found", details: { path: "users" } } }
KV 公用事业
内置的 KV( 键值) 资源提供了一个与您输入的资源同步的无计划存储 .
保证BuiltinKv
确保计划包括内置 kv 资源。 如果它已经存在,则验证它的形状;否则会附加它.
import { ensureBuiltinKv } from "@datafn/core";
const schemaWithKv = ensureBuiltinKv(mySchema);
// Now includes { name: "kv", version: 1, fields: [{ name: "value", type: "object" }] }
千维
将普通密钥字符串转换为 Canonic KV 记录 ID .
import { kvId } from "@datafn/core";
kvId("theme"); // → "kv:theme"
kvId("user:prefs"); // → "kv:user:prefs"
KV 资源( NAME)
已建 KV 商店的 Canon 资源名称 : "kv"。 。 。 .
处理错误
数据fn 错误
具有结构形状的平面对象(不是类).
type DatafnError = {
code: DatafnErrorCode;
message: string;
details?: unknown;
};
数据fn 错误代码
type DatafnErrorCode =
| "SCHEMA_INVALID"
| "DFQL_INVALID"
| "DFQL_UNKNOWN_RESOURCE"
| "DFQL_UNKNOWN_FIELD"
| "DFQL_UNKNOWN_RELATION"
| "DFQL_UNSUPPORTED"
| "LIMIT_EXCEEDED"
| "FORBIDDEN"
| "NOT_FOUND"
| "CONFLICT"
| "INTERNAL";
数据fn 信封<T>
type DatafnEnvelope<T> =
| { ok: true; result: T }
| { ok: false; error: DatafnError };
完整 Schema 示例
import { defineSchema, field } from "@datafn/core";
const schema = defineSchema({
resources: [
{
name: "project",
version: 1,
idPrefix: "proj",
fields: [
field.string("id", { required: true, unique: true }),
field.string("name", { required: true, maxLength: 200 }),
field.string("description"),
field.string("ownerId", { required: true }),
field.date("createdAt", { required: true }),
],
indices: { base: ["ownerId", "createdAt"] },
},
{
name: "task",
version: 1,
idPrefix: "task",
fields: [
field.string("id", { required: true, unique: true }),
field.string("title", { required: true, minLength: 1 }),
field.boolean("completed", { required: true, default: false }),
field.number("priority", { min: 1, max: 5 }),
field.date("dueDate"),
field.string("projectId", { required: true }),
],
indices: { base: ["projectId", "completed"] },
},
{
name: "tag",
version: 1,
idPrefix: "tag",
fields: [
field.string("id", { required: true, unique: true }),
field.string("name", { required: true, unique: true }),
field.string("color"),
],
},
],
relations: [
{
from: "task",
to: "project",
type: "many-one",
relation: "project",
fkField: "projectId",
},
{
from: "task",
to: "tag",
type: "many-many",
relation: "tags",
inverse: "tasks",
},
{
from: "project",
to: "task",
type: "one-many",
relation: "tasks",
inverse: "project",
},
],
});
许可证
麻省理工学院
对于拉动请求,通过可信赖的应用程序计划元数据作为第三个参数:
extractStructuralResourceSelectors("pull", payload, { schema }) (或
parseDatafnRequest("pull", payload, { schema })) (中文(简体) ). 解析器翻译为已知
将光标密钥结合到他们的端点资源中。 没有计划
元数据, 光标名称仍为选择器; 未知 join_ 名字从不沉默
被忽略 。 处理关系同步的网关必须提供与该系统相同的计划
服务器并授权每个返回的终点。 服务器在飞行前提供
验证的 schema 自动; 自定义授权回调器也应将其信任的 schema 传递给帮助者.