-
Notifications
You must be signed in to change notification settings - Fork 10
codegen
This package also includes a helper function that will automatically generate types for each of your layouts. Use this tool regularly during development to easily keep your types updated with any schema changes in FileMaker. 🤯
The generated file also produces a layout-specific client instance that will automatically type all of the methods for that layout and validates the response using the zod
library. This validation happens at runtime so you can protect against dangerous field changes even when you haven't ran the code generator recently, or in your production deployment!
- Add a schema configuation file to the root of your project
pnpm codegen --init
# or
pnpx @proofgeist/fmdapi --init
- Edit the configuration file (
fmschema.config.mjs
) to include your FileMaker layouts (see more configuration options below). - Run the
codegen
command to generate your types!
pnpm codegen
# or
pnpx @proofgeist/fmdapi
Assuming you have a layout called customer_api
containing name
phone
and email
fields for a customer, the generated code will look something like this:
// schema/Customer.ts
import { z } from "zod";
export const ZCustomer = z.object({
name: z.string(),
phone: z.string(),
email: z.string(),
});
export type TCustomer = z.infer<typeof ZCustomer>;
// schema/client/Customer.ts
import { DataApi, OttoAdapter } from "@proofgeist/fmdapi";
export const client = DataApi<any, TCustomer>({
adapter: new OttoAdapter({
auth: { apiKey: process.env.OTTO_API_KEY },
db: process.env.FM_DATABASE,
server: process.env.FM_SERVER,
})
layout: "customer_api",
zodValidation: { fieldData: ZCustomer },
});
You can use the exported types to type your own client, or simply use the generated client to get typed and validated results, like so:
import { CustomerClient } from "schema/client";
...
const result = await CustomerClient.list(); // result will be fully typed and validated!
Option | Type | Default | Description |
---|---|---|---|
envNames | object |
undefined | This object has the same structure as the client config parameters and is used to overrride the environment variable names used for the generated client. |
schemas | Schema[] |
(required) | An array of Schema objects to generate types for (see below) |
path | string |
"./schema" |
Path to folder where generated files should be saved. |
generateClient | boolean |
true |
Will generate a layout-specific typed client for you. Set to false if you only want to generate the types. |
useZod | boolean |
true |
When enabled, will generate Zod schema in addition to TypeScript types and add validation to the generated client for each layout |
clientSuffix | string |
"Client" |
(v4.1+) Suffix to add to the end of the generated client name. e.g. CustomerClient
|
Option | Type | Default | Description |
---|---|---|---|
layout | string |
(required) | The FileMaker source layout name |
schemaName | string |
(required) | The label for your schema (will also be the name of the generated file) |
valueLists |
strict allowEmpty ignore
|
ignore |
If strict , will add enum types based on the value list defined for the field. If allowEmpty , will append "" to the value list and values that are not in the list will also be converted to "" . Otherwise, fields are typed as strings. |
strictNumbers | boolean |
false |
(v2.2.11+) If true, the zod schema will apply a transformer to force all number fields to be either number or null . WARNING: If you are not using Zod or the auto-generated layout specific client, enabling this option may result in false types! |
generateClient | boolean |
none | If present, override the generateClient option for this schema only. |
Option | Default | Description |
---|---|---|
--init | false | Run with this flag to add the config file to your project |
--config | - | path to a non-default config file |
--env-path | .env.local | path to your .env file |
--skip-env-check | - | Ignore loading environment variables from a file. |
Editing the generated files is not reccommended as it would undermine the main benefit of being able to re-run the script at a later date when the schema changes—all your edits would be overritten. If you need to extend the types, it's better to do extend them into a new type/zod schema in another file. Or, if you have suggesstions for the underlying engine, Pull Requests are welcome!
FileMaker may return numbers as strings in certain cases (such as very large numbers in scientific notation or blank fields). This ensures you properly account for this in your frontend code. If you wish to force all numbers to be typed as number | null
, you can enable the strictNumbers
flag per schema in your definition.
WARNING: the strictNumbers
setting is disabled by default because it may result in false types if you are not using Zod or the auto-generated layout specific client. It works by applying a transformer to the zod schema to force all number fields to be either number
or null
.
Values lists are exported as their own types within the schema file, but they are not enforced within the schema by default because the actual data in the field may not be fully validated.
If you want the type to be enforced to a value from the value list, you can enable the strictValueLists
flag per schema in your definition. This feature is only reccommended when you're also using the Zod library, as your returned data will fail the validation if the value is not in the value list.
For now, these are all typed as strings. You probably want to transform these values anyway, so we keep it simple at the automated level.
Yes, great idea! This could be a great way to catch errors that would arise from any changes to the FileMaker schema.
In short: Zod is a TypeScript-first schema declaration and validation library. When you use it, you get runtime validation of your data instead of just compile-time validation.
FileMaker is great for being able to change schema very quickly and easily. Yes, you probably have naming conventions in place that help protect against these changes in your web apps, but no system is perfect. Zod lets you start with the assumption that any data coming from an external API might be in a format that you don't expect and then valdiates it so that you can catch errors early. This allows the typed object that it returns to you to be much more trusted throughout your app.
But wait, does this mean that I might get a fatal error in my production app if the FileMaker schema changes? Yes, yes it does. This is actually what you'd want to happen. Without validating the data returned from an API, it's possible to get other unexpcted side-effects in your app that don't present as errors, which may lead to bugs that are hard to track down or inconsistencies in your data.