# ProofKit URL: https://proofkit.dev/docs A collection of TypeScript libraries for building great apps ## What is ProofKit? The ProofKit CLI aims to make web development easier for beginners and more efficient for experienced devs. It’s opinionated structure allows for more than just a starter template or bootstrapping tool, but code-mod scripts that can modify a project after the initial setup. ProofKit is not a JavaScript framework. It’s also not the only way to build a web app. It’s simply our experience of building web apps encapsulated into a CLI tool to help you structure your project and add to it over time. Each template is just a starting point, and you are free to modify any part of it as you see fit. Learn how to use the @proofkit/cli to build a new project in minutes. ## Core Libraries The ProofKit CLI will automatically install these other packages for you (depending on what you choose to build), but they are published seperately if you want to use them in your own projects, without the opinionated structure of the CLI. ### @proofkit/fmdapi A library for interacting with the FileMaker Data API. [Learn more](/docs/fmdapi) ### @proofkit/typegen A library for generating TypeScript types and validation schemas from FileMaker layouts. [Learn more](/docs/typegen) ### @proofkit/webviewer A library for interacting with the FileMaker WebViewer. [Learn more](/docs/webviewer) ### @proofkit/fmodata A strongly-typed FileMaker OData API client with full TypeScript inference and runtime validation. [Learn more](/docs/fmodata) (beta) ### @proofkit/better-auth Self-hosted auth for your web apps, backed by your FileMaker database. [Learn more](/docs/better-auth) --- # Getting Started URL: https://proofkit.dev/docs/better-auth @proofkit/better-auth import { Cards, Card } from "fumadocs-ui/components/card"; import { SquareArrowOutUpRight } from "lucide-react"; # What is Better-Auth? From the [Better-Auth](https://better-auth.com) website: > The most comprehensive authentication framework for TypeScript. Better-Auth has a robust plugin ecosystem that gives you the ability to pick and choose which authentication methods you want to use, all within a system that let's you securely host your own authentication. The @proofkit/better-auth package allows you to use FileMaker as the backend database for the better-auth library, including automated schema migrations to easily add any neccesary tables and fields to your FileMaker file. How to quickly get started with Better-Auth and FileMaker. Better-Auth Docs{" "} } href="https://better-auth.com/docs" > Learn more about the Better-Auth framework and how to use it in your app. --- # Installation & Usage URL: https://proofkit.dev/docs/better-auth/installation import { Callout } from "fumadocs-ui/components/callout"; import { CliCommand } from "@/components/CliCommand"; import { PackageInstall } from "@/components/PackageInstall"; This package is currently in beta. Please report any issues you find to the [GitHub repository](https://github.com/proofgeist/proofkit/issues), or reach out to us in the [Community](https://community.ottomatic.cloud/c/proofkit/13) # Prerequisites - Ensure OData is enabled on your FileMaker server. - Ensure your credentials have the `fmodata` privilege enabled. - If you are using OttoFMS 4.11+ and you want to use a Data API key instead of plain credentials, ensure OData is enabled for that key. # Step 1a: Automated Setup with the ProofKit CLI This automated setup expects you to have Next.js and shadcn/ui set up in your project. It will also setup various auth pages for you, but these may not work if you have a prefix configured for tailwindcss. You can use this opinionated setup to get you started, or if you need more control you should refer to the manual setup. Run the following command to add the necessary packages and config files to your project. You will not need to follow the better-auth installation guide. # Step 1b: Manual Setup Follow the [Better-Auth installation guide](https://better-auth.com/docs/installation) to get started in your app, but come back here for special instructions for anything related to your Database Setup or schema migrations. ### Database Setup Ensure you have the @proofkit/better-auth and @proofkit/fmodata packages installed in your app. Configure your database connection in your `auth.ts` file. Be sure to set these value secrets in your environment variables. The credentials you use here need `fmodata` permissions enabled, and read/write access to the better-auth tables. ```ts title="auth.ts" import { betterAuth } from "better-auth"; import { FMServerConnection } from "@proofkit/fmodata"; import { FileMakerAdapter } from "@proofkit/better-auth"; const connection = new FMServerConnection({ serverUrl: process.env.FM_SERVER_URL!, auth: { // option 1: username/password credentials username: process.env.FM_USERNAME!, password: process.env.FM_PASSWORD!, // option 2: Data API key (OttoFMS 4.11+, OData enabled for the key) // apiKey: process.env.OTTO_API_KEY!, }, }); const db = connection.database(process.env.FM_DATABASE!); export const auth = betterAuth({ database: FileMakerAdapter({ database: db }), // ...rest of your config }); ``` # Step 2: Create/Update Database Tables Run the following command to create the necessary tables and fields in your FileMaker file. It will show you a confirmation before any changes are applied, so you can review them. [Full Access] credentials are required for the schema changes to be applied automatically, but you may want to use a more restricted account for the rest of better-auth usage. If your credentials that you entered earlier in the `auth.ts` file do not have the [Full Access] permissions, you can override them in the CLI. These changes affect database schema only. No layouts or relationships are created or modified during this process. The tables/fields that are created will be dependent on how your `auth.ts` file is setup. If you want to use any of your existing tables, just set [custom table names](https://www.better-auth.com/docs/concepts/database#custom-table-names) in the `auth.ts` file before running the migration command. You may see fields added to your tables that you don't plan on using, but it's best to keep them in your database anyway to avoid potential errors. If you make any schema-related changes to the better-auth config, such as adding plugins, you will need to run the migration command again to apply the changes to your FileMaker file. --- # Troubleshooting URL: https://proofkit.dev/docs/better-auth/troubleshooting import { CliCommand } from "@/components/CliCommand"; ## Error when generating schema ```bash ERROR [Better Auth]: filemaker is not supported. If it is a custom adapter, please request the maintainer to implement createSchema ``` This means you used the better-auth CLI directly instead of the @proofkit/better-auth version. Run this instead: --- # Introduction URL: https://proofkit.dev/docs/cli Build a web-app quicker than ever before. import { InitCommand } from "@/components/InitCommand"; import { Card } from "fumadocs-ui/components/card"; ## What is ProofKit? ProofKit is a collection of TypeScript tools and libraries for building modern web applications, with a focus on seamless integration with Claris FileMaker. The ProofKit CLI aims to make web development easier for beginners and more efficient for experienced devs. Its opinionated structure allows for more than just a starter template or bootstrapping tool, but code-mod scripts that can modify a project after the initial setup. Think of it as our experience building web apps encapsulated into a CLI tool to help you structure your project and add to it over time. Each template is just a starting point, and you are free to modify any part of it as you see fit. ## Core Libraries The ProofKit CLI will automatically install these other packages for you (depending on what you choose to build), but they are published separately if you want to use them in your own projects, without the opinionated structure provided by the CLI. A library for interacting with the FileMaker Data API. A library for generating TypeScript types and validation schemas from FileMaker layouts. A library for interacting with the FileMaker WebViewer. Self-hosted auth for your web apps, backed by your FileMaker database. ## Quick Start ## Videos - Claris Engage 2025 Presentation [Watch here](https://www.youtube.com/watch?v=V3boRDZYNgw) - FileMaker Training Videos (Livestream recording) - [Day 1 (Building a web app with ProofKit)](https://youtu.be/mqq8gtn07fk?si=CU9FsZeZKbxk6iwx) - [Day 2 (Building a webviewer app)](https://youtu.be/irInOmpKCrE?si=BD1qOYGsE05LAKdY) - Community Live with Claris (June 26, 2025) [Watch here](https://www.youtube.com/watch?v=uxB9Mp4Ipm4) --- # What's new in v2? URL: https://proofkit.dev/docs/cli/v2 In this major release, the ProofKit CLI has been reimagined as a more powerful tool for building web apps. # The Highlights ### A new starting point When you start a new app using the ProofKit CLI, the new template is based on shadcn and tailwindcss instead of Mantine. This new simple template still includes the best practices from the Proof+Geist team, but now with even more flexibility. ### A new way to add [anything] The `proofkit add` command leverages the shadcn CLI to install any component or utility into your app, or you can use the shadcn CLI directly to install any component from any compatible library. Even better, these templates are now published right here on the docs site, so we can more easily release updates and new components that you can use right away. ### A new level of compatibility You can now use the ProofKit CLI in an existing Next.js app, even if it wasn’t bootstrapped with the CLI, as long as it's already using shadcn. This unlocks the ability for more advanced developers to leverage the power of ProofKit, while still trying out the latest and greatest in the JavaScript ecosystem. # Why the change? Adding new templates to the ProofKit CLI was always a challenge, and arguably the most lacking of the whole system. The templates are meant to be just a starting place, so they needed to be generic to fit any project, yet useful enough to warrant inclusion in the binary everyone downloads to run the CLI. That wasn’t scalable. But shadcn has taken the JavaScript world by storm over the past few years, especially with the rise of AI and especially tools like v0. We needed to unlock the ability to easily add anything to your JavaScript projects, whether it was a template from Proof, shadcn, v0 (AI-generated), or from any of the other emerging UI libraries built on the shadcn CLI. But this required a new starting point. While mantine and tailwind can be used together in the same project, they get in each other’s way. At Proof+Geist, we’ve been building new projects without ProofKit for a few months now, so it was time to bring those learnings back to the framework so we could all move more quickly. New projects will start with a new foundation based on tailwindcss. It’s easier for AI to understand, and more compatible with any UI component built for shadcn to install for you. But the shadcn CLI isn’t just about UI components. It can install any utility or set of components into your app. Take the new `@proofkit/better-auth` package that was recently released. It’s the best way to quickly and easily add self-hosted authentication to your web app, without having to compromise on login options or pay for an external auth service. But setting it up was not easy...until now! Check out our @proofkit/better-auth [guide](/docs/better-auth/installation) for more details. # Upgrade from v1 Unfortunately, there is not an easy path for you to upgrade projects that were created with v1 to be fully compatible with v2. But if you are able to setup tailwindcss and shadcn in your existing project, you can still use the ProofKit CLI to add new components and utilities to your app. Basic steps: 1. Configure [tailwindcss](https://tailwindcss.com/) in your project. - If possible, you should replace any use of the Mantine UI library with tailwind-based components. You could also configure tailwind with a prefix so as not to conflict with the Mantine classes, but not all of the new components are compatible. 2. Install [shadcn](https://ui.shadcn.com/). 3. Add/change the "ui" key in your `proofkit.json` file and set to "shadcn". ```json title="proofkit.json" { "ui": "shadcn" } ``` 4. Install/update the ProofKit CLI, or use the npx commands to run the CLI without needing to install it in your project Please report any issues you find to the [GitHub repository](https://github.com/proofgeist/proofkit/issues), or reach out to us in the [Community](https://community.ottomatic.cloud/c/proofkit/13) --- # Adapters URL: https://proofkit.dev/docs/fmdapi/adapters Adapters are a new level of abstraction that allows you to reuse the same client API with any number of proxies, including via a FileMaker Webviewer using the [`@proofkit/webviewer`](/docs/webviewer) package and the Execute Data API script step. The adapter is responsible for handling the specifics of the connection to the FileMaker Data API, while the shared client exposes helper functions, schema validators, and other utilities to the developer. Choose the adapter that is right for your project, or view below for how to build your own custom adatper. ## OttoFMS (recommended) To connect via the [OttoFMS](https://docs.ottofms.com/) [Data API Proxy](https://docs.ottofms.com/ottofms-features/api-proxy#data-api-proxy), use the `OttoAdapter` with a Data API key: ```ts import { DataApi, OttoAdapter } from "@proofkit/fmdapi"; ``` The OttoAdapter is compatible with API keys for both the Otto v3 and OttoFMS Data API Proxy. OttoFMS is available under a free license and is our recommended method for interacting with the Data API. #### Options | Option | Type | Description | | ------------- | -------- | ---------------------------------------------------------------------------------------- | | `auth.apiKey` | `string` | The Data API key from either Otto v3 (starts with `KEY_`) or OttoFMS (starts with `dk_`) | | `auth.port` | `string` | _(optional)_ Only used for Otto v3. Defaults to 3030 | | `db` | `string` | FileMaker database name | | `server` | `string` | FileMaker server URL (must start with include `https://`) | ## FetchAdapter To connect directly to the FileMaker Data API, use the `FetchAdapter` with a username and password: ```ts import { DataApi, FetchAdapter } from "@proofkit/fmdapi"; ``` #### Options | Option | Type | Description | | ------------ | ------------ | ------------------------------------------------------------------------------------------------------------------ | | `auth` | `object` | Authentication object. Must contain `username` and `password` | | `db` | `string` | FileMaker database name | | `server` | `string` | FileMaker server URL (must include `https://`) | | `tokenStore` | `TokenStore` | _(optional)_ If provided, will use the custom set of functions to store and retrieve the short-lived access token. | ## WebViewerAdapter For rich webviewer experiences, use the `WebViewerAdapter` with the [`@proofkit/webviewer`](/docs/webviewer) package: ```package-install @proofkit/webviewer ``` Then import the adapter like so: ```ts import { DataApi } from "@proofkit/fmdapi"; import { WebViewerAdapter } from "@proofkit/webviewer"; ``` ## Custom Adapters > **This is an advanced topic.** If you are just an application developer trying to connect to a FileMaker database, all you need to know is how you want to connect to the FileMaker server, then import the appropriate adapter. Type hint for the selected adapter will guide you through the rest. If you want to write you own adapter for your own proxy, or to override the root-level `request` method, you can write a custom adapter. All adapters must implement the `Adapter` interface. If you want to build a proxy similar to the `OttoAdapter`, you can extend the `BaseFetchAdapter` class and will likely only need to implement the `getToken` and `request` methods. View the source for the FetchAdapter for an example of this. --- # Usage Examples URL: https://proofkit.dev/docs/fmdapi/examples import { Callout } from "fumadocs-ui/components/callout"; import { Card, Cards } from "fumadocs-ui/components/card"; ## Prerequisites Before you can use any of these methods, you need to set up a FileMaker Data API client. If you haven't done this yet, check out our [Quick Start Guide](/docs/fmdapi/quick-start) to create your client in a separate file. For these examples, we'll assume you've already setup a client in another file and are importing it for use. ```ts // This is just an example - follow the Quick Start guide for your actual setup import { CustomersLayout } from "./schema/client"; ``` --- ## Retrieving Data from FileMaker ### Finding Records You can use the `find` method to perform FileMaker-style find requests on a layout. This method is limited to 100 records by default, but you can use the `findAll` helper method to automatically paginate the results and return all records that match the query. ```ts twoslash title="searchCustomers.ts" import { CustomersLayout } from "./CustomersLayout"; // ---cut--- // Simple search - find customers in a specific city (max 100 records) export async function findCustomersByCity(city: string) { const response = await CustomersLayout.find({ query: { city: city } }); console.log(`Found ${response.data.length} customers in ${city}`); return response.data; } // Get ALL matching records at once (handles pagination automatically) export async function getAllActiveCustomers() { const records = await CustomersLayout.findAll({ query: { status: "==Active" } // all standard FileMaker operators are supported }); return records; // All active customers, no pagination needed } ``` Use an array of find requests to get the OR behavior, equivalent to having multiple find requests in FileMaker. ```ts twoslash title="multipleFindRequests.ts" import { CustomersLayout } from "./CustomersLayout"; // ---cut--- export async function getCustomersByCityOrStatus(city: string, status: string) { const records = await CustomersLayout.findAll({ query: [{ city }, { status }] }); return records; } ``` There are also helper methods for common find scenarios. Any of these methods will return just a single record instead of an array. - `findOne` will throw an error unless there is exactly one record found - `findFirst` will return the first record found, but still throw if no records are found - `maybeFindFirst` will return the first record found or null ### Getting All Records If you don't need to specify any find requests, you can use the `list` or `listAll` methods. `list` will limit to 100 records per request by default, while `listAll` will automatically handle pagination via the API and return all records for the entire table. Use with caution if the table is large! ```ts twoslash title="getAllCustomers.ts" import { CustomersLayout } from "./CustomersLayout"; // ---cut--- // Get a page of customers (recommended for large datasets) export async function listCustomers() { const response = await CustomersLayout.list({ sort: [{ fieldName: "firstName", sortOrder: "ascend" }] }); return { customers: response.data, totalRecords: response.dataInfo.foundCount, hasMore: response.data.length === 100 // Default page size }; } // Get ALL customers at once (use with caution on large datasets) export async function listAllCustomers() { const records = await CustomersLayout.listAll(); console.log(`Retrieved all ${records.length} customers`); return records.map(customer => ({ id: customer.recordId, firstName: customer.fieldData.firstName, lastName: customer.fieldData.lastName, email: customer.fieldData.email, city: customer.fieldData.city })); } ``` --- ## Creating Records Use `create` to add new records to your FileMaker database. ```ts twoslash title="createCustomer.ts" import { CustomersLayout } from "./CustomersLayout"; // ---cut--- export async function createNewCustomer(customerData: { firstName: string; lastName: string; email: string; phone?: string; city?: string; }) { const response = await CustomersLayout.create({ fieldData: { firstName: customerData.firstName, lastName: customerData.lastName, email: customerData.email, phone: customerData.phone || "", city: customerData.city || "", status: "Active", created_date: new Date().toISOString() } }); console.log(`Created customer with ID: ${response.recordId}`); return response.recordId; } ``` --- ## Update / Delete Records Updating or deleting records requires the internal record id from FileMaker, not the primary key for your table. This value is returned in the `recordId` field of any create, list, or find response. This record id *can* change during imports or data migrations, so you should never store it, but instead alwyas look it up via a find request when it's needed. ```ts twoslash title="updateCustomer.ts" import { CustomersLayout } from "./CustomersLayout"; // ---cut--- export async function updateCustomerInfo(myPrimaryKey: string, updates: { firstName?: string; lastName?: string; phone?: string; city?: string; }) { const { data: { recordId } } = await CustomersLayout.findOne({ query: { myPrimaryKey: myPrimaryKey } }); // Only update fields that were provided const fieldData: any = {}; if (updates.firstName) fieldData.firstName = updates.firstName; if (updates.lastName) fieldData.lastName = updates.lastName; if (updates.phone) fieldData.phone = updates.phone; if (updates.city) fieldData.city = updates.city; const response = await CustomersLayout.update({ fieldData, recordId }); return response.modId; } ``` ```ts twoslash title="deleteCustomer.ts" import { CustomersLayout } from "./CustomersLayout"; // ---cut--- export async function deleteCustomer(myPrimaryKey: string) { // Optional: Get customer info first for logging const { data: { recordId } } = await CustomersLayout.findOne({ query: { myPrimaryKey: myPrimaryKey } }); await CustomersLayout.delete({recordId}); } ``` --- ## Working with Scripts FileMaker scripts can be executed during any other method or run directly. ### Running Scripts Directly Use `executeScript` to run a script directly. ```ts twoslash title="executeScripts.ts" import { CustomersLayout } from "./CustomersLayout"; // ---cut--- export async function sendEmailFromFileMaker() { const response = await CustomersLayout.executeScript({ script: "Send Email", scriptParam: JSON.stringify({ to: "customer@example.com", subject: "Welcome to our service", body: "Thank you for signing up!" }) }); console.log("Script result:", response.scriptResult); return response.scriptResult; } ``` ### Run a script with another method You can run scripts before or after any data operation. The script will be run in the context of the layout specified in your client and will be on the record or found set as the operation. This is especially useful when creating records, as you can run a script after the record is created, knowing the script will be focused on this newly created record; thus giving you access to the calculated values such as a UUID primary key defined in your field definitions. ```ts twoslash title="scriptsWithOperations.ts" import { CustomersLayout } from "./CustomersLayout"; // ---cut--- // Run a script after creating a record export async function createCustomerWithWelcomeEmail(customerData: any) { const response = await CustomersLayout.create({ fieldData: customerData, script: "Send Welcome Email", // script name // script param must always be a string "script.param": JSON.stringify({ email: customerData.email, name: `${customerData.firstName} ${customerData.lastName}` }) }); return { recordId: response.recordId, scriptResult: response.scriptResult }; } ``` For more details about the script execution order, see [this page](https://help.claris.com/en/data-api-guide/content/run-script-with-another-request.html) of the FileMaker Data API guide. --- See also Complete list of all available methods Set up your FileMaker Data API client --- # Overview URL: https://proofkit.dev/docs/fmdapi @proofkit/fmdapi This package is designed to make working with the FileMaker Data API much easier. Here's just a few key features: - Handles token refresh for you automatically - [OttoFMS](https://ottofms.com/) Data API proxy support - TypeScript support for easy auto-completion of your field names - [Automated type generation](/docs/typegen) based on layout metadata - Protection against field name changes with [Standard Schema](https://standardschema.dev/) runtime validation - Supports both node and edge runtimes with a customizable token store - Customizable adapters allow usage even within the [FileMaker WebViewer](/docs/webviewer) ## Edge Runtime Support This package is compatible with edge runtimes, but there are some additional considerations to avoid overwhelming your FileMaker server with too many connections. If you are developing for the edge, be sure to implement one of the following strategies: - ✅ Use a custom token store (see above) with a persistent storage method such as Upstash - ✅ Use a proxy such as the [Otto Data API Proxy](https://www.ottofms.com/docs/otto/working-with-otto/proxy-api-keys/data-api) which handles management of the access tokens itself. - Providing an API key to the client instead of username/password will automatically use the Otto proxy --- # Quick Start - Manual URL: https://proofkit.dev/docs/fmdapi/manual-setup import { Tabs, Tab } from "fumadocs-ui/components/tabs"; import { Callout } from "fumadocs-ui/components/callout"; > Note: For the best experience, use the [@proofkit/typegen](/docs/typegen) tool to generate layout-specific clients and get autocomplete hints in your IDE with your actual field names. This minimal example just demonstrates the basic setup Add the following envnironment variables to your project's `.env` file: ```sh FM_DATABASE=filename.fmp12 FM_SERVER=https://filemaker.example.com # if you want to use the OttoFMS Data API Proxy OTTO_API_KEY=dk_123456...789 # otherwise FM_USERNAME=admin FM_PASSWORD=password ``` Initialize the client with credentials, depending on your adapter ```ts // to use the OttoFMS Data API Proxy import { DataApi, OttoAdapter } from "@proofkit/fmdapi"; const client = DataApi({ adapter: new OttoAdapter({ auth: { apiKey: process.env.OTTO_API_KEY }, db: process.env.FM_DATABASE, server: process.env.FM_SERVER, }), layout: "API_Contacts", }); ``` ```ts // to use the raw Data API import { DataApi, FetchAdapter } from "@proofkit/fmdapi"; const client = DataApi({ adapter: new FetchAdapter({ auth: { username: process.env.FM_USERNAME, password: process.env.FM_PASSWORD, }, db: process.env.FM_DATABASE, server: process.env.FM_SERVER, }), layout: "API_Contacts", }); ``` Then, use the client to query your FileMaker database. [View all available methods here](https://github.com/proofgeist/fmdapi/wiki/methods). Basic Example: ```typescript const result = await client.list({ layout: "Contacts" }); ``` ## TypeScript Support If you define a schema in your client, the types will be inferred automatically. [Learn more](/docs/fmdapi/validation) The basic client will return the generic FileMaker response object by default. You can also create a type for your expected response and get a fully typed response that includes your own fields. ```typescript type TContact = { name: string; email: string; phone: string; }; // if you have portals type TOrders = { "Orders::orderId": string; "Orders::orderDate": string; "Orders::orderTotal": number; }; type TPortals = { orders: TOrders; // key is based on the portal object name }; const client = DataApi({ layout: "API_Contacts", // ... your adapter, other config }); ``` 💡 TIP: For a more ergonomic TypeScript experience, use the [@proofkit/typegen tool](/docs/typegen) to generate these types based on your FileMaker layout metadata. --- # Methods URL: https://proofkit.dev/docs/fmdapi/methods The following methods are available for all adapters. - `list` return all records from a given layout - `find` perform a FileMaker find - `get` return a single record by recordID - `create` return a new record - `update` modify a single record by recordID - `delete` delete a single record by recordID # Helper Functions This package also includes some helper methods to make working with Data API responses a little easier: - `findOne` return the first record from a find instead of an array. This method will error unless exactly 1 record is found. - `findFirst` return the first record from a find instead of an array, but will not error if multiple records are found. - `findAll` return all found records from a find, automatically handling pagination. Use caution with large datasets! - `listAll` return all records from a given layout, automatically handling pagination. Use caution with large datasets! # Adapter-Specific Functions The first-party `FetchAdapter` and `OttoAdatper` both share the following additional methods from the `BaseFetchAdapter`: - `executeScript` execute a FileMaker script directly - `layoutMetadata` return metadata for a given layout - `layouts` return a list of all layouts in the database (top-level layout key ignored) - `scripts` return a list of all scripts in the database (top-level script key ignored) - `globals` set global fields for the current session (top-level globals key ignored) If you have your own proxy, you can write your own Custom Adapter that extends the BaseFetchAdapter to also implement these methods. ## Fetch Adapter - `disconnect` forcibly logout of your FileMaker session ## Otto Adapter No additional methods --- # Quick Start - Typegen URL: https://proofkit.dev/docs/fmdapi/quick-start import { Tabs, Tab } from "fumadocs-ui/components/tabs"; import { Steps, Step } from "fumadocs-ui/components/steps"; The typegen tool is the best way to interact with this library, as it will automatically generate layout-specific clients and get autocomplete hints in your IDE with your actual field names from your solution ### Install the required packages ```package-install @proofkit/fmdapi zod ``` Zod is used by the typegen tool by default, but it can be excluded if you set `validator` to `false` in the typegen config. ### Create a typegen config file in your project ```sh npx @proofkit/typegen ``` Add the layouts you want to generate clients for to the `layouts` array in the config file. ```jsonc title='proofkit-typegen.config.jsonc' { "$schema": "https://proofkit.dev/typegen-config-schema.json", "config": { "clientSuffix": "Layout", "layouts": [ // add your layouts and name schemas here { "layoutName": "my_layout", "schemaName": "MySchema" } // repeat as needed for each layout... // { layoutName: "my_other_layout", schemaName: "MyOtherSchema" }, ], // change this value to generate the files in a different directory "path": "schema", "clearOldFiles": true }, } ``` ### Setup Environment Variables Add the following envnironment variables to your project's `.env` file: ```bash title=".env" FM_SERVER=https://filemaker.example.com # must start with https:// FM_DATABASE=filename.fmp12 # must end with .fmp12 # if you want to use the OttoFMS Data API Proxy (recommended) OTTO_API_KEY=dk_123456...789 # otherwise FM_USERNAME=admin FM_PASSWORD=password ``` ### Generate the layout-specific clients Run this command any time you make changes to your config file, any of the referenced FileMaker layouts, or any field names/types that are on the layouts. ```sh npx @proofkit/typegen ``` Tip: Add a script to your `package.json` to make it easier to run in the future. ```jsonc title="package.json" { "scripts": { // ... "typegen": "npx @proofkit/typegen" } } ``` ## Usage You can now import the layout-specifc client for use in your project. ```ts title="getCustomer.ts" import { CustomersLayout } from "./schema/client"; export async function getCustomer(id: string) { // findOne will throw an error unless exactly 1 record is returned const { data } = await CustomersLayout.findOne({ query: { id: `==${id}` } }); return data.fieldData; } ``` For all available methods, see [this page](/docs/fmdapi/methods). ## Customization If you run into any limitations from the generated code, there are many ways to customize it to your needs. How to configure the typegen tool for your use case. Customize the shape of the data returned from your database. --- # Token Store URL: https://proofkit.dev/docs/fmdapi/token-store This page applies only to the FetchAdapter when your connecting via username/password to your FileMaker server. The Otto Data API Proxy manages the token for you. If you are using username/password authentication, the fmdapi client will manage your access token for you. By default, the token is kept in memory only, but you can provide other getter and setter methods to store the token in a database or other location. Included in this package are helper functions for file storage if you have access to the filesystem, or Upstash if running in a serverless environment. ```ts import { DataApi, FetchAdapter } from "@proofkit/fmdapi"; // using file storage, if you have persistent access to the filesystem on your server import { fileTokenStore } from "@proofkit/fmdapi/tokenStore/file"; const client = DataApi({ adapter: new FetchAdapter({ // ... tokenStore: fileTokenStore(), }), }); // or with Upstash, requires `@upstash/redis` as peer dependency import { upstashTokenStore } from "@proofkit/fmdapi/tokenStore/upstash"; const client = DataApi({ adapter: new FetchAdapter({ // ... tokenStore: upstashTokenStore({ token: process.env.UPSTASH_TOKEN, url: process.env.UPSTASH_URL, }), }), }); ``` --- # Validation & Transformation URL: https://proofkit.dev/docs/fmdapi/validation Protect your app from field name changes by validating the shape of the data returned from the FileMaker Data API. import { File, Folder, Files } from "fumadocs-ui/components/files"; import { IconFileTypeTs } from "@tabler/icons-react"; ## Why validate? One of the best features of the FileMaker platform is how you can easily add, remove, and rename fields in your database. However, when you make integrations that are beyond the scope of your database, you can run into serious issues if the field names change out from under you. This library supports validation using [Standard Schema](https://standardschema.dev/) out of the box, and will throw an error _early_ to prevent unexpected behavior in your app. We suggest using the [Zod](https://zod.dev) library by default, but any other validation library that supports Standard Schema will also work. ## How does it work? When creating your layout client, add a `schema` property and define a Standard-Schema compliant schema definition for your `fieldData` and `portalData`. Your schema must be an object, and should represent a single record or portal row. Most validation libraries also support some kind of transformation, and you can use these to adjust how your FileMaker data is returned to your app. Try this interactive example that uses the [Zod](https://zod.dev/) library to validate and transform the data: