Skip to content
17 changes: 12 additions & 5 deletions apps/docs/content/docs/fmdapi/quick-start.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ title: Quick Start - Typegen

import { Tabs, Tab } from "fumadocs-ui/components/tabs";
import { Steps, Step } from "fumadocs-ui/components/steps";
import { AgentCommand } from "@/components/AgentCommand";

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

Expand All @@ -12,19 +13,25 @@ The typegen tool is the best way to interact with this library, as it will autom
### Install the required packages

```package-install
@proofkit/fmdapi zod
@proofkit/fmdapi@beta zod
```

<Callout type="info">
Zod is used by the typegen tool by default, but it can be excluded if you set `validator` to `false` in the typegen config.
</Callout>

#### AI Agent Integration

If you use an AI coding agent, run this command to map ProofKit's built-in skills to your project. See the [TanStack Intent docs](https://tanstack.com/intent/latest/docs/getting-started/quick-start-consumers) for more details.

<AgentCommand />

</Step>

<Step>
### Create a typegen config file in your project
```sh
npx @proofkit/typegen
npx @proofkit/typegen@beta
```


Expand Down Expand Up @@ -73,7 +80,7 @@ The typegen tool is the best way to interact with this library, as it will autom
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
npx @proofkit/typegen@beta
```

<Callout type="info" >
Expand All @@ -83,7 +90,7 @@ The typegen tool is the best way to interact with this library, as it will autom
{
"scripts": {
// ...
"typegen": "npx @proofkit/typegen"
"typegen": "npx @proofkit/typegen@beta"
}
}
```
Expand Down Expand Up @@ -122,4 +129,4 @@ If you run into any limitations from the generated code, there are many ways to
<Cards>
<Card title="Typegen Config" href="/docs/typegen/customization">How to configure the typegen tool for your use case.</Card>
<Card title="Transformations" href="/docs/fmdapi/validation">Customize the shape of the data returned from your database.</Card>
</Cards>
</Cards>
11 changes: 3 additions & 8 deletions apps/docs/content/docs/fmodata/cli.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -5,24 +5,19 @@ description: Run fmodata operations from the command line — queries, scripts,

import { Callout } from "fumadocs-ui/components/callout";
import { Tab, Tabs } from "fumadocs-ui/components/tabs";
import { PackageInstall } from "@/components/PackageInstall";

The `@proofkit/fmodata` package ships a built-in CLI binary called **`fmodata`**. It exposes every library operation — querying records, running scripts, managing webhooks, inspecting metadata, and modifying schema — as a non-interactive command suitable for scripting, CI pipelines, and quick one-off database operations.

## Installation

The binary is included automatically when you install the package:

```bash
pnpm add @proofkit/fmodata
# or
npm install @proofkit/fmodata
```
<PackageInstall packages="@proofkit/fmodata" />

If you want it available globally:

```bash
pnpm add -g @proofkit/fmodata
```
<PackageInstall packages="@proofkit/fmodata" global />

## Connection Configuration

Expand Down
7 changes: 0 additions & 7 deletions apps/docs/content/docs/fmodata/index.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ description: "@proofkit/fmodata"

import { Callout } from "fumadocs-ui/components/callout";
import { Card, Cards } from "fumadocs-ui/components/card";
import { CliCommand } from "@/components/CliCommand";

<Callout type="warning">
This library is in beta status. We don't expect the method names or arguments to change further, but please submit feedback or report issues on the [community forum](https://community.ottomatic.cloud/c/proofkit/13) or on [GitHub](https://github.com/proofgeist/proofkit/issues).
Expand Down Expand Up @@ -33,12 +32,6 @@ To use this library you need:
- (if using OttoFMS) a Data API key setup for your FileMaker account with OData enabled


## AI Agent Integration

If you use an AI coding agent, install ProofKit skills for better code generation after installing the package:

<CliCommand command="@tanstack/intent@latest install" exec />

## When to Use OData vs Data API

Claris has given signals that OData is the future of data access for FileMaker. It's much faster and more powerful than the Data API since it does not require the server to spin up a server-side client or maintain a session for each request. However, it's a new paradigm for thinking about how we can interact with the FileMaker server and may take some adjustment. You should not worry about continuing to use the Data API if needed, but we suggest trying OData for new projects.
Expand Down
3 changes: 1 addition & 2 deletions apps/docs/content/docs/fmodata/meta.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,8 @@
"entity-ids",
"extra-properties",
"custom-fetch-handlers",
"---CLI---",
"cli",
"---Reference---",
"cli",
"errors",
"methods"
],
Expand Down
5 changes: 3 additions & 2 deletions apps/docs/content/docs/fmodata/quick-start.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import {
import { Callout } from "fumadocs-ui/components/callout";
import { Card } from "fumadocs-ui/components/card";
import { CliCommand } from "@/components/CliCommand";
import { AgentCommand } from "@/components/AgentCommand";
import { PackageInstall } from "@/components/PackageInstall";
import { Badge } from "@/components/ui/badge";

Expand All @@ -25,9 +26,9 @@ Here's a minimal example to get you started with `@proofkit/fmodata`:

#### AI Agent Integration

If you use an AI coding agent, install ProofKit skills for better code generation:
If you use an AI coding agent, run this command to map ProofKit's built-in skills to your project. See the [TanStack Intent docs](https://tanstack.com/intent/latest/docs/getting-started/quick-start-consumers) for more details.

<CliCommand command="@tanstack/intent@latest install" exec />
<AgentCommand />

</Step>

Expand Down
3 changes: 3 additions & 0 deletions apps/docs/src/app/docs/(docs)/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@ export default function Layout({ children }: { children: ReactNode }) {
<DocsLayout
tree={source.pageTree}
{...baseOptions}
containerProps={{
className: "[--fd-layout-width:100%]",
}}
sidebar={{
footer: (
<div className="mt-2 flex items-center justify-center text-muted-foreground text-xs">
Expand Down
3 changes: 3 additions & 0 deletions apps/docs/src/app/docs/templates/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,9 @@ export default async function Layout({ children }: { children: ReactNode }) {
<DocsLayout
tree={newTree}
{...baseOptions}
containerProps={{
className: "[--fd-layout-width:100%]",
}}
sidebar={{
tabs,
footer: (
Expand Down
50 changes: 50 additions & 0 deletions apps/docs/src/components/AgentCommand.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
"use client";

import { CheckIcon, CopyIcon } from "lucide-react";
import { useCallback, useState } from "react";

interface AgentCommandProps {
command?: string;
label?: string;
}

export function AgentCommand({
command = "npx @tanstack/intent@latest install",
label = "Tell your agent to run",
}: AgentCommandProps) {
const [copied, setCopied] = useState(false);

const copy = useCallback(() => {
navigator.clipboard.writeText(command);
setCopied(true);
setTimeout(() => setCopied(false), 2000);
}, [command]);

return (
<div className="group relative my-4 font-mono text-sm">
<div className="overflow-hidden rounded-lg border border-[#e87a2a] bg-[#1a1a2e]">
<div className="flex items-center justify-between border-b border-[#e87a2a]/40 px-4 py-2">
<span className="text-xs text-[#e87a2a]">{label}</span>
<button
type="button"
onClick={copy}
className="rounded-md p-1 text-[#7a7a9e] transition-colors hover:text-[#e0e0e0]"
aria-label="Copy command"
>
{copied ? (
<CheckIcon className="size-4 text-green-400" />
) : (
<CopyIcon className="size-4" />
)}
</button>
</div>
<div className="px-4 py-3">
<span className="text-[#e87a2a]">❯ </span>
<span className="text-[#e0e0e0]">{command}</span>
</div>
</div>
</div>
);
}

export default AgentCommand;
10 changes: 9 additions & 1 deletion apps/docs/src/components/CliCommand.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,15 @@ export function CliCommand({
execPackage?: string;
packageName?: string;
}) {
const pkg = execPackage ?? `${packageName}@${cliVersion}`;
const hasVersionSpecifier = (pkg: string) => {
if (pkg.startsWith("@")) {
const slash = pkg.indexOf("/");
return slash !== -1 && pkg.indexOf("@", slash + 1) !== -1;
}
return pkg.includes("@");
};
const shouldAppendVersion = packageName.startsWith("@proofkit/") && !hasVersionSpecifier(packageName);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Runtime error: packageName is optional but accessed without null check. When packageName is undefined, calling .startsWith() will throw TypeError: Cannot read property 'startsWith' of undefined.

Fix by adding a null check:

const shouldAppendVersion = packageName?.startsWith("@proofkit/") && !hasVersionSpecifier(packageName);

Or use a guard clause:

const shouldAppendVersion = packageName && packageName.startsWith("@proofkit/") && !hasVersionSpecifier(packageName);
Suggested change
const shouldAppendVersion = packageName.startsWith("@proofkit/") && !hasVersionSpecifier(packageName);
const shouldAppendVersion = packageName?.startsWith("@proofkit/") && !hasVersionSpecifier(packageName);

Spotted by Graphite

Fix in Graphite


Is this helpful? React 👍 or 👎 to let us know.

const pkg = execPackage ?? (shouldAppendVersion ? `${packageName}@${cliVersion}` : packageName);
return (
<Tabs groupId="package-manager" id="package-manager" items={MANAGERS.map((m) => m.label)} persist>
{MANAGERS.map((manager) => (
Expand Down
12 changes: 6 additions & 6 deletions apps/docs/src/components/PackageInstall.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@ import { Tab, Tabs } from "fumadocs-ui/components/tabs";
import { cliVersion } from "@/lib/constants";

const MANAGERS = [
{ key: "npm", label: "npm", prefix: "npm install" },
{ key: "pnpm", label: "pnpm", prefix: "pnpm add" },
{ key: "yarn", label: "yarn", prefix: "yarn add" },
{ key: "bun", label: "bun", prefix: "bun add" },
{ key: "npm", label: "npm", prefix: "npm install", globalPrefix: "npm install -g" },
{ key: "pnpm", label: "pnpm", prefix: "pnpm add", globalPrefix: "pnpm add -g" },
{ key: "yarn", label: "yarn", prefix: "yarn add", globalPrefix: "yarn global add" },
{ key: "bun", label: "bun", prefix: "bun add", globalPrefix: "bun add -g" },
];

const WHITESPACE_RE = /\s+/;
Expand All @@ -16,7 +16,7 @@ const WHITESPACE_RE = /\s+/;
* Renders a tabbed package install command.
* Automatically appends @{cliVersion} to @proofkit/* packages unless version is already specified.
*/
export function PackageInstall({ packages }: { packages: string }) {
export function PackageInstall({ packages, global: isGlobal }: { packages: string; global?: boolean }) {
const pkgs = packages
.trim()
.split(WHITESPACE_RE)
Expand All @@ -33,7 +33,7 @@ export function PackageInstall({ packages }: { packages: string }) {
<Tabs groupId="package-manager" id="package-manager" items={MANAGERS.map((m) => m.label)} persist>
{MANAGERS.map((manager) => (
<Tab key={manager.key} value={manager.label}>
<DynamicCodeBlock code={`${manager.prefix} ${pkgs}`} lang="bash" />
<DynamicCodeBlock code={`${isGlobal ? manager.globalPrefix : manager.prefix} ${pkgs}`} lang="bash" />
</Tab>
))}
</Tabs>
Expand Down
Loading