proofkit-fmodata

Type-safe ORM for FileMaker's OData API with TypeScript code generation.

Safety Notice

This listing is imported from skills.sh public index metadata. Review upstream SKILL.md and repository scripts before running.

Copy this and send it to your AI assistant to learn

Install skill "proofkit-fmodata" with this command: npx skills add proofgeist/proofkit/proofgeist-proofkit-proofkit-fmodata

ProofKit FMOData

Type-safe ORM for FileMaker's OData API with TypeScript code generation.

Up-to-Date Documentation

For the latest docs, fetch from proofkit.dev:

Quick Setup

1. Install packages

pnpm add @proofkit/fmodata@beta @proofkit/typegen

2. Create config (proofkit-typegen.config.jsonc)

npx @proofkit/typegen init

3. Set env vars

FM_SERVER=https://your-server.com FM_DATABASE=YourDatabase.fmp12 OTTO_API_KEY=your-api-key # or FM_USERNAME/FM_PASSWORD

4. Generate types

npx @proofkit/typegen generate

5. Or use interactive UI

npx @proofkit/typegen ui

Define Tables

import { fmTableOccurrence, textField, numberField, timestampField } from "@proofkit/fmodata"; import { z } from "zod";

export const Users = fmTableOccurrence("Users", { id: textField().primaryKey().entityId("FMFID:100001"), name: textField().notNull(), email: textField().notNull(), active: numberField() .readValidator(z.coerce.boolean()) .writeValidator(z.boolean().transform(v => v ? 1 : 0)), createdAt: timestampField().readOnly(), }, { entityId: "FMTID:1000001", navigationPaths: ["Contacts", "Orders"], });

Query Patterns

import { FMServerConnection, eq, and, gt, asc, contains } from "@proofkit/fmodata";

const connection = new FMServerConnection({ serverUrl: process.env.FM_SERVER, auth: { apiKey: process.env.OTTO_API_KEY } }); const db = connection.database("MyDatabase.fmp12");

// List with filters const result = await db.from(Users).list() .where(and(eq(Users.active, true), gt(Users.age, 18))) .orderBy(asc(Users.name)) .top(10) .execute();

// Get single record const user = await db.from(Users).get("user-123").execute();

// Select specific fields const result = await db.from(Users).list() .select({ userId: Users.id, userName: Users.name }) .execute();

// String filters .where(contains(Users.email, "@example.com")) .where(startsWith(Users.name, "John"))

CRUD Operations

// Insert const result = await db.from(Users) .insert({ name: "John", email: "john@example.com" }) .execute();

// Update const result = await db.from(Users) .update({ name: "Jane" }) .byId("user-123") .execute();

// Delete const result = await db.from(Users) .delete() .byId("user-123") .execute();

// Batch operations (atomic) const result = await db.batch([ db.from(Users).list().top(10), db.from(Users).insert({ name: "Alice", email: "alice@example.com" }), ]).execute();

Relationships

// Expand related records const result = await db.from(Users).list() .expand(Contacts, (b) => b.select({ name: Contacts.name }) .where(eq(Contacts.active, true)) ) .execute();

// Navigate from a record const result = await db.from(Contacts).get("contact-123") .navigate(Users) .select({ username: Users.username }) .execute();

Error Handling

import { isHTTPError, ValidationError, TimeoutError } from "@proofkit/fmodata";

const result = await db.from(Users).list().execute();

if (result.error) { if (isHTTPError(result.error)) { if (result.error.isNotFound()) console.log("Not found"); if (result.error.is5xx()) console.log("Server error"); } else if (result.error instanceof ValidationError) { console.log("Validation failed:", result.error.issues); } else if (result.error instanceof TimeoutError) { console.log("Request timed out"); } }

Troubleshooting

Connection Issues

"Unauthorized" or 401 errors

  • Verify OTTO_API_KEY or FM_USERNAME /FM_PASSWORD env vars

  • Ensure FM account has fmodata privilege enabled

  • Check OData service is enabled on FM Server

"Not Found" or 404 errors

  • Verify database name includes .fmp12 extension

  • Check table/layout name matches exactly (case-sensitive)

  • Ensure OData is enabled for the table occurrence

Type Generation Issues

typegen can't connect

  • Run npx @proofkit/typegen ui to debug interactively

  • Check connection health indicator in UI

  • Verify env vars are loaded (check --env-path flag)

Generated types don't match FM schema

  • Re-run npx @proofkit/typegen generate after FM schema changes

  • Use --reset-overrides to recreate override files

  • Check field type mappings in config

Query Issues

"Field not found" errors

  • Ensure field is defined in fmTableOccurrence

  • Check entityId matches FM field ID (use typegen to auto-generate)

  • Verify field is on the OData-exposed table occurrence

Validation errors on read/write

  • Check readValidator /writeValidator schemas match FM data types

  • FM stores booleans as 0/1 numbers - use coercion validators

  • Empty strings may need .catch("") or .nullable()

Performance Issues

Slow queries

  • Add .top(n) to limit results

  • Use .select() to fetch only needed fields

  • Avoid expanding large related record sets

References

  • fmodata-api.md - Complete API reference: field builders, operators, query methods

  • typegen-config.md - Configuration options and examples

Source Transparency

This detail page is rendered from real SKILL.md content. Trust labels are metadata-based hints, not a safety guarantee.

Related Skills

Related by shared tags or category signals.

Coding

openclaw-version-monitor

监控 OpenClaw GitHub 版本更新,获取最新版本发布说明,翻译成中文, 并推送到 Telegram 和 Feishu。用于:(1) 定时检查版本更新 (2) 推送版本更新通知 (3) 生成中文版发布说明

Archived SourceRecently Updated
Coding

ask-claude

Delegate a task to Claude Code CLI and immediately report the result back in chat. Supports persistent sessions with full context memory. Safe execution: no data exfiltration, no external calls, file operations confined to workspace. Use when the user asks to run Claude, delegate a coding task, continue a previous Claude session, or any task benefiting from Claude Code's tools (file editing, code analysis, bash, etc.).

Archived SourceRecently Updated
Coding

ai-dating

This skill enables dating and matchmaking workflows. Use it when a user asks to make friends, find a partner, run matchmaking, or provide dating preferences/profile updates. The skill should execute `dating-cli` commands to complete profile setup, task creation/update, match checking, contact reveal, and review.

Archived SourceRecently Updated