### Install Required Packages Source: https://proofkit.dev/docs/fmdapi/quick-start Install the core library and Zod validator. ```bash npm install @proofkit/fmdapi@beta zod ``` -------------------------------- ### Install and Import WebViewerAdapter Source: https://proofkit.dev/docs/fmdapi/adapters Install the @proofkit/webviewer package and import DataApi and WebViewerAdapter for rich webviewer experiences. This allows integration within FileMaker Webviewers. ```bash npm install @proofkit/webviewer ``` ```javascript import { DataApi } from "@proofkit/fmdapi"; import { WebViewerAdapter } from "@proofkit/webviewer"; ``` -------------------------------- ### Configure Typegen Source: https://proofkit.dev/docs/fmdapi/quick-start Example configuration file for defining layouts and output paths. ```json { "$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 }, } ``` -------------------------------- ### Importing the FileMaker Client Source: https://proofkit.dev/docs/fmdapi/examples Example of importing a pre-configured layout client for use in application modules. ```typescript // This is just an example - follow the Quick Start guide for your actual setup import { CustomersLayout } from "./schema/client"; ``` -------------------------------- ### Install TanStack Intent Source: https://proofkit.dev/docs/fmdapi/quick-start Command to map built-in skills for AI coding agents. ```bash npx @tanstack/intent@latest install ``` -------------------------------- ### Use Generated Client Source: https://proofkit.dev/docs/fmdapi/quick-start Example of importing and using a generated layout client to fetch data. ```typescript 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; } ``` -------------------------------- ### Create Customer Record with Welcome Email Script Source: https://proofkit.dev/docs/fmdapi/examples Creates a customer record and then executes a 'Send Welcome Email' script. The script runs in the context of the newly created record. Requires the `CustomersLayout` object. ```typescript // 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 }; } ``` -------------------------------- ### Initialize FMDAPI Client with FetchAdapter Source: https://proofkit.dev/docs/fmdapi/manual-setup Initialize the client using the FetchAdapter for the raw Data API. Ensure FM_USERNAME, FM_PASSWORD, FM_DATABASE, and FM_SERVER are set in your environment. ```typescript // 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", }); ``` -------------------------------- ### Run the upgrade codemod Source: https://proofkit.dev/docs/fmdapi/version-5 Execute this command in the project root to automate the migration to v5 packages. ```bash npx @proofgeist/fmdapi@latest upgrade ``` -------------------------------- ### Initialize Typegen Config Source: https://proofkit.dev/docs/fmdapi/quick-start Generate the initial configuration file for the typegen tool. ```bash npx @proofkit/typegen@beta ``` -------------------------------- ### Configure File-Based Token Store Source: https://proofkit.dev/docs/fmdapi/token-store Use this snippet to configure the FetchAdapter with file-based token storage. Ensure your server has filesystem access. Requires importing `fileTokenStore`. ```typescript 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(), }), }); ``` -------------------------------- ### Initialize FMDAPI Client with OttoAdapter Source: https://proofkit.dev/docs/fmdapi/manual-setup Initialize the client using the OttoAdapter for the OttoFMS Data API Proxy. Ensure OTTO_API_KEY, FM_DATABASE, and FM_SERVER are set in your environment. ```typescript // 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", }); ``` -------------------------------- ### Configure Upstash Token Store Source: https://proofkit.dev/docs/fmdapi/token-store Configure the FetchAdapter with Upstash for token storage, suitable for serverless environments. Requires `@upstash/redis` as a peer dependency and environment variables for Upstash credentials. Requires importing `upstashTokenStore`. ```typescript // 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, }), }), }); ``` -------------------------------- ### Import FetchAdapter for Direct Connection Source: https://proofkit.dev/docs/fmdapi/adapters Import the DataApi and FetchAdapter to connect directly to the FileMaker Data API using a username and password. This is suitable for direct server access. ```javascript import { DataApi, FetchAdapter } from "@proofkit/fmdapi"; ``` -------------------------------- ### Adapter-Specific Functions Source: https://proofkit.dev/docs/fmdapi/methods Additional methods available for FetchAdapter and OttoAdapter for managing scripts, layouts, and globals. ```APIDOC ## Adapter-Specific Functions ### Methods - **executeScript**: Executes a FileMaker script directly. - **layoutMetadata**: Returns metadata for a given layout. - **layouts**: Returns a list of all layouts in the database. - **scripts**: Returns a list of all scripts in the database. - **globals**: Sets global fields for the current session. - **disconnect (FetchAdapter only)**: Forcibly logs out of the FileMaker session. ``` -------------------------------- ### Import OttoAdapter for OttoFMS Source: https://proofkit.dev/docs/fmdapi/adapters Import the DataApi and OttoAdapter when connecting via the OttoFMS Data API Proxy. This adapter is recommended for its free license and compatibility with Otto v3 and OttoFMS. ```javascript import { DataApi, OttoAdapter } from "@proofkit/fmdapi"; ``` -------------------------------- ### Finding Records in FileMaker Source: https://proofkit.dev/docs/fmdapi/examples Demonstrates searching for records using specific criteria and handling pagination with findAll. ```typescript // 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 } ``` -------------------------------- ### Environment Variables for FMDAPI Source: https://proofkit.dev/docs/fmdapi/manual-setup Configure these environment variables in your project's .env file for database connection and authentication. ```env 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 ``` -------------------------------- ### Define Environment Variables Source: https://proofkit.dev/docs/fmdapi/quick-start Required environment variables for connecting to the FileMaker server. ```text 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 ``` -------------------------------- ### Add Typegen Script Source: https://proofkit.dev/docs/fmdapi/quick-start Add a shortcut script to package.json for running the typegen tool. ```json { "scripts": { // ... "typegen": "npx @proofkit/typegen@beta" } } ``` -------------------------------- ### Helper Functions Source: https://proofkit.dev/docs/fmdapi/methods Utility methods to simplify handling Data API responses, including pagination and single-record retrieval. ```APIDOC ## Helper Functions ### Methods - **findOne**: Returns the first record from a find; errors if not exactly 1 record is found. - **findFirst**: Returns the first record from a find; does not error if multiple records are found. - **findAll**: Returns all found records from a find, automatically handling pagination. - **listAll**: Returns all records from a given layout, automatically handling pagination. ``` -------------------------------- ### Update package.json typegen script Source: https://proofkit.dev/docs/fmdapi/version-5 Update the typegen script to use the new @proofkit/typegen package. ```json "typegen": "npx @proofkit/typegen" ``` -------------------------------- ### Query FileMaker Database Source: https://proofkit.dev/docs/fmdapi/manual-setup Use the initialized client to perform a basic list query on your FileMaker database. The layout parameter specifies the target layout. ```typescript const result = await client.list({ layout: "Contacts" }); ``` -------------------------------- ### Listing Records from FileMaker Source: https://proofkit.dev/docs/fmdapi/examples Retrieves records from a layout, either paginated or in full, with optional sorting. ```typescript // 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 })); } ``` -------------------------------- ### Standard CRUD Methods Source: https://proofkit.dev/docs/fmdapi/methods Core methods available for all adapters to perform CRUD operations on FileMaker records. ```APIDOC ## Standard CRUD Methods ### Methods - **list**: Returns all records from a given layout. - **find**: Performs a FileMaker find operation. - **get**: Returns a single record by recordID. - **create**: Creates a new record. - **update**: Modifies a single record by recordID. - **delete**: Deletes a single record by recordID. ``` -------------------------------- ### Execute FileMaker Script Directly Source: https://proofkit.dev/docs/fmdapi/examples Runs a FileMaker script directly and returns its result. The script parameter must be a JSON string. Requires the `CustomersLayout` object. ```typescript 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; } ``` -------------------------------- ### Performing OR Queries Source: https://proofkit.dev/docs/fmdapi/examples Uses an array of query objects to perform multiple find requests in a single operation. ```typescript export async function getCustomersByCityOrStatus(city: string, status: string) { const records = await CustomersLayout.findAll({ query: [{ city }, { status }] }); return records; } ``` -------------------------------- ### Creating New Records Source: https://proofkit.dev/docs/fmdapi/examples Adds a new record to the FileMaker database using the create method. ```typescript 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 Customer Information Source: https://proofkit.dev/docs/fmdapi/examples Updates customer details using the internal record ID. Only provided fields are updated. Requires the `CustomersLayout` object. ```typescript 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; } ``` -------------------------------- ### Define custom schema transformations Source: https://proofkit.dev/docs/fmdapi/version-5 Use Zod to define custom transformations for fields, such as coercing types or parsing dates. ```typescript import { z } from "zod/v4"; import { ZCustomers as ZCustomers_generated } from "./generated/Customers"; import dayjs from "dayjs"; import customParseFormat from "dayjs/plugin/customParseFormat"; dayjs.extend(customParseFormat); export const ZCustomers = ZCustomers_generated.omit({ active: true }).extend({ active: z.coerce.boolean(), createdAt: z .string() .transform((v) => dayjs(v, ["MM/DD/YYYY"])) .toDate(), }); ``` -------------------------------- ### Define TypeScript Response Types Source: https://proofkit.dev/docs/fmdapi/manual-setup Define custom TypeScript types for expected response data, including fields and portal data, to enable type inference for fully typed responses. ```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 }); ``` -------------------------------- ### Delete Customer Record Source: https://proofkit.dev/docs/fmdapi/examples Deletes a customer record using its internal record ID. It's recommended to find the record first to log its details if needed. Requires the `CustomersLayout` object. ```typescript 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}); } ``` -------------------------------- ### Access validated data Source: https://proofkit.dev/docs/fmdapi/version-5 Access the validated and transformed data returned from the client list method. ```typescript import { CustomersLayout } from "./schema/client"; const { data } = await CustomersLayout.list(); data[0].fieldData.active; // --> boolean ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.