Resources
Define data resources with names, versions, and field configurations.
DatafnResourceSchema
A resource represents a collection of records (analogous to a database table). Each resource has a name, version, fields, optional indices, and optional permissions.
type DatafnResourceSchema = {
name: string;
version: number;
idPrefix?: string;
isRemoteOnly?: boolean;
fields: DatafnFieldSchema[];
indices?:
| { base?: string[]; search?: string[]; vector?: string[] }
| string[];
permissions?: DatafnPermissionsPolicy;
};| Property | Type | Description |
|---|---|---|
name | string | Unique resource name. Used in queries, mutations, and API paths. |
version | number | Integer schema version. Increment when making breaking changes. |
idPrefix | string | Optional prefix for generated IDs. An idPrefix of "tsk" produces IDs like tsk_abc123. |
isRemoteOnly | boolean | When true, the resource is not synced to the client offline store. Queries always go to the server. |
fields | DatafnFieldSchema[] | Array of field definitions. Max 200 fields per resource. See Fields. |
indices | object or string[] | Index configuration for query optimization. |
permissions | DatafnPermissionsPolicy | Field-level read/write access control. |
Defining a Resource
import { defineSchema } from "@datafn/core";
const schema = defineSchema({
resources: [
{
name: "articles",
version: 1,
idPrefix: "art",
fields: [
{ name: "title", type: "string", required: true, maxLength: 500 },
{ name: "body", type: "string", required: true },
{ name: "publishedAt", type: "date", required: false },
{ name: "viewCount", type: "number", required: false, default: 0 },
{ name: "tags", type: "array", required: false },
{ name: "metadata", type: "json", required: false },
],
indices: {
base: ["title", "publishedAt"],
search: ["body"],
},
},
],
});Indices
Indices control how the database optimizes queries for the resource. There are three categories:
| Category | Purpose |
|---|---|
base | Standard B-tree indices for equality and range filters. |
search | Full-text search indices. |
vector | Vector similarity indices for embedding-based queries. |
You can use the shorthand array syntax to define base indices only:
// Shorthand -- all entries become base indices
indices: ["title", "publishedAt"]
// Equivalent expanded form
indices: {
base: ["title", "publishedAt"],
search: [],
vector: [],
}All referenced field names must match declared fields on the resource. A type error (with defineSchema) or a validation error (with validateSchema) is raised for unknown field references.
Permissions
The permissions property defines field-level access control on the server.
type DatafnPermissionsPolicy = {
read?: { fields: string[] };
write?: { fields: string[] };
ownerField?: string;
};| Property | Type | Description |
|---|---|---|
read.fields | string[] | Fields that can be selected and used in filters. |
write.fields | string[] | Fields that can be set via mutations. |
ownerField | string | Optional field name for owner-scoped authorization checks. |
{
name: "users",
version: 1,
fields: [
{ name: "email", type: "string", required: true, unique: true },
{ name: "displayName", type: "string", required: true },
{ name: "role", type: "string", required: true, enum: ["admin", "member"] },
{ name: "internalNotes", type: "string", required: false },
],
permissions: {
read: { fields: ["email", "displayName", "role"] },
write: { fields: ["displayName"] },
ownerField: "email",
},
}In this example, internalNotes is excluded from both read and write, making it inaccessible through the DataFn API. The ownerField enables owner-scoped authorization so users can only modify their own records.
Remote-Only Resources
Setting isRemoteOnly: true tells the client not to sync this resource to the local offline store. All queries for this resource go directly to the server.
{
name: "auditLogs",
version: 1,
isRemoteOnly: true,
fields: [
{ name: "action", type: "string", required: true },
{ name: "actor", type: "string", required: true },
{ name: "timestamp", type: "date", required: true },
{ name: "payload", type: "json", required: false },
],
indices: { base: ["action", "actor", "timestamp"] },
}This is useful for large or append-only datasets that do not benefit from client-side caching.