Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .changeset/better-auth-type-errors.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
"@proofkit/better-auth": patch
---

Fix TypeScript build errors by making adapter/migration types resilient to upstream Better Auth changes.

3 changes: 1 addition & 2 deletions packages/better-auth/src/adapter.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import {
CleanedWhere,
createAdapter,
type AdapterDebugLogs,
} from "better-auth/adapters";
import { createRawFetch, type FmOdataConfig } from "./odata";
import { prettifyError, z } from "zod/v4";
Expand All @@ -25,7 +24,7 @@ interface FileMakerAdapterConfig {
/**
* Helps you debug issues with the adapter.
*/
debugLogs?: AdapterDebugLogs;
debugLogs?: boolean | { isRunningAdapterTests?: boolean };
/**
* If the table names in the schema are plural.
*/
Expand Down
31 changes: 30 additions & 1 deletion packages/better-auth/src/cli/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,33 @@ import { AdapterOptions } from "../adapter";
import { createRawFetch } from "../odata";
import "dotenv/config";

function getFileMakerAdapterConfigFromAdapterOptions(
options: unknown,
): AdapterOptions["config"] {
if (!options || typeof options !== "object") {
throw new Error("FileMaker adapter options were missing.");
}

const opts = options as Record<string, unknown>;

// Our adapter returns: { options: { config: FileMakerAdapterConfig } }
if (opts.config && typeof opts.config === "object") {
return opts.config as AdapterOptions["config"];
}

// Some Better Auth versions wrap adapter options under `adapterConfig`.
if (opts.adapterConfig && typeof opts.adapterConfig === "object") {
const adapterConfig = opts.adapterConfig as Record<string, unknown>;
if (adapterConfig.config && typeof adapterConfig.config === "object") {
return adapterConfig.config as AdapterOptions["config"];
}
}

throw new Error(
"Could not locate FileMaker adapter configuration from Better Auth adapter options.",
);
}

async function main() {
const program = new Command();

Expand Down Expand Up @@ -63,7 +90,9 @@ async function main() {

const betterAuthSchema = getAuthTables(config);

const adapterConfig = (adapter.options as AdapterOptions).config;
const adapterConfig = getFileMakerAdapterConfigFromAdapterOptions(
adapter.options,
);
const { fetch } = createRawFetch({
...adapterConfig.odata,
auth:
Expand Down
43 changes: 36 additions & 7 deletions packages/better-auth/src/migrate.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,27 @@
import { type BetterAuthDbSchema } from "better-auth/db";
import { type Metadata } from "fm-odata-client";
import chalk from "chalk";
import z from "zod/v4";
import { createRawFetch } from "./odata";

type BetterAuthTableField = {
fieldName?: string;
type: unknown;
};

type BetterAuthTableDef = {
modelName: string;
fields: Record<string, BetterAuthTableField>;
order?: number;
};

export type BetterAuthAuthTables = Record<string, BetterAuthTableDef>;

function normalizeBetterAuthFieldType(fieldType: unknown): string {
if (typeof fieldType === "string") return fieldType;
if (Array.isArray(fieldType)) return fieldType.map(String).join("|");
return String(fieldType);
}

export async function getMetadata(
fetch: ReturnType<typeof createRawFetch>["fetch"],
databaseName: string,
Expand Down Expand Up @@ -31,7 +49,7 @@ export async function getMetadata(

export async function planMigration(
fetch: ReturnType<typeof createRawFetch>["fetch"],
betterAuthSchema: BetterAuthDbSchema,
betterAuthSchema: BetterAuthAuthTables,
databaseName: string,
): Promise<MigrationPlan> {
const metadata = await getMetadata(fetch, databaseName);
Expand Down Expand Up @@ -93,12 +111,23 @@ export async function planMigration(
const fields: FmField[] = Object.entries(baTable.fields).map(
([key, field]) => ({
name: field.fieldName ?? key,
// Better Auth's FieldType can be a string literal union or arrays.
// Normalize it to a string so our FM mapping logic remains stable.
// Examples: "number", "string[]", ["string", "number"] (plugin-defined)
// See Better Auth: FieldType = "string" | "number" | ... | Array<LiteralString>
//
// We only need coarse mapping for FileMaker field creation.
// Anything unknown falls back to "varchar".
//
type:
field.type === "boolean" || field.type.includes("number")
? "numeric"
: field.type === "date"
? "timestamp"
: "varchar",
(() => {
const t = normalizeBetterAuthFieldType(field.type);
return t === "boolean" || t.includes("number")
? "numeric"
: t === "date"
? "timestamp"
: "varchar";
})(),
}),
);

Expand Down
Loading
Loading