diff --git a/.changeset/config.json b/.changeset/config.json index c1762463..fa7a7092 100644 --- a/.changeset/config.json +++ b/.changeset/config.json @@ -7,5 +7,5 @@ "linked": [], "access": "public", "updateInternalDependencies": "patch", - "ignore": ["@proofkit/docs", "demo"] + "ignore": ["@proofkit/docs", "demo", "@proofkit/typegen-web"] } diff --git a/.changeset/olive-coins-trade.md b/.changeset/olive-coins-trade.md new file mode 100644 index 00000000..7c1408c5 --- /dev/null +++ b/.changeset/olive-coins-trade.md @@ -0,0 +1,5 @@ +--- +"@proofkit/fmodata": minor +--- + +Beta release diff --git a/.changeset/pre.json b/.changeset/pre.json index 310e7334..2f7be70c 100644 --- a/.changeset/pre.json +++ b/.changeset/pre.json @@ -12,11 +12,15 @@ "@proofkit/registry": "1.0.0", "tmp": "0.0.0", "@proofkit/typegen": "1.0.10", - "@proofkit/webviewer": "3.0.6" + "@proofkit/webviewer": "3.0.6", + "@proofkit/fmodata": "0.1.0-alpha.20", + "@proofkit/typegen-web": "0.0.0" }, "changesets": [ "brown-keys-float", + "olive-coins-trade", "quick-ends-drop", + "real-ideas-sort", "swift-swans-rush", "tough-forks-start", "ui-default-shadcn" diff --git a/apps/docs/src/app/typegen-config-schema.json/route.ts b/apps/docs/src/app/typegen-config-schema.json/route.ts index 7520a92a..a34c2ff0 100644 --- a/apps/docs/src/app/typegen-config-schema.json/route.ts +++ b/apps/docs/src/app/typegen-config-schema.json/route.ts @@ -1,6 +1,11 @@ -import { typegenConfig } from "@proofkit/typegen/config"; +import { typegenConfigForValidation } from "@proofkit/typegen/src/types.ts"; import { z } from "zod/v4"; export const GET = async () => { - return Response.json(z.toJSONSchema(typegenConfig, { reused: "ref" })); + return Response.json( + z.toJSONSchema(typegenConfigForValidation, { + reused: "ref", + target: "draft-7", + }), + ); }; diff --git a/packages/cli/package.json b/packages/cli/package.json index aea6db7d..daf6465f 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -1,6 +1,6 @@ { "name": "@proofkit/cli", - "version": "2.0.0-beta.6", + "version": "2.0.0-beta.7", "description": "Create web application with the ProofKit stack", "license": "MIT", "repository": { @@ -59,7 +59,6 @@ "@better-fetch/fetch": "1.1.17", "@clack/core": "^0.3.4", "@clack/prompts": "^0.11.0", - "@ianvs/prettier-plugin-sort-imports": "^4.4.1", "@proofkit/fmdapi": "workspace:*", "@proofkit/typegen": "workspace:*", "@types/glob": "^8.1.0", diff --git a/packages/cli/prettier.config.mjs b/packages/cli/prettier.config.mjs index 052200b9..df64a7fb 100644 --- a/packages/cli/prettier.config.mjs +++ b/packages/cli/prettier.config.mjs @@ -1,14 +1,12 @@ // import baseConfig from "../"; /** - * @type {import('prettier').Config & import('prettier-plugin-tailwindcss').PluginOptions & - * import("@ianvs/prettier-plugin-sort-imports").PluginConfig} + * @type {import('prettier').Config & import('prettier-plugin-tailwindcss').PluginOptions} */ const config = { // ...baseConfig, arrowParens: "always", plugins: [ - "@ianvs/prettier-plugin-sort-imports", "prettier-plugin-tailwindcss", ], tailwindConfig: "./template/extras/config/tailwind.config.ts", diff --git a/packages/fmodata/CHANGELOG.md b/packages/fmodata/CHANGELOG.md index 53d16662..88d9cb64 100644 --- a/packages/fmodata/CHANGELOG.md +++ b/packages/fmodata/CHANGELOG.md @@ -1,5 +1,11 @@ # @proofkit/fmodata +## 0.1.0-beta.21 + +### Minor Changes + +- Beta release + ## 0.0.0 Initial setup of the package. diff --git a/packages/fmodata/package.json b/packages/fmodata/package.json index 7b51a9f0..9308660c 100644 --- a/packages/fmodata/package.json +++ b/packages/fmodata/package.json @@ -1,6 +1,6 @@ { "name": "@proofkit/fmodata", - "version": "0.1.0-alpha.20", + "version": "0.1.0-beta.21", "description": "FileMaker OData API client", "repository": "git@github.com:proofgeist/proofkit.git", "author": "Eric <37158449+eluce2@users.noreply.github.com>", diff --git a/packages/typegen/CHANGELOG.md b/packages/typegen/CHANGELOG.md index 2c0d9a63..cfcf2cc9 100644 --- a/packages/typegen/CHANGELOG.md +++ b/packages/typegen/CHANGELOG.md @@ -1,5 +1,17 @@ # @proofkit/typegen +## 1.1.0-beta.2 + +### Minor Changes + +- 7672233: New command: `npx @proofkit/typegen@latest ui` will launch a web UI for configuring and running your typegen config. + (beta) support for @proofkit/fmodata typegen config. + +### Patch Changes + +- Updated dependencies + - @proofkit/fmodata@0.1.0-beta.21 + ## 1.0.11-beta.1 ### Patch Changes diff --git a/packages/typegen/package.json b/packages/typegen/package.json index 67631c16..4eddd6e4 100644 --- a/packages/typegen/package.json +++ b/packages/typegen/package.json @@ -1,6 +1,6 @@ { "name": "@proofkit/typegen", - "version": "1.0.11-beta.1", + "version": "1.1.0-beta.2", "description": "", "type": "module", "main": "dist/esm/index.js", diff --git a/packages/typegen/src/server/api.ts b/packages/typegen/src/server/api.ts index 9fa6ed1a..1993448f 100644 --- a/packages/typegen/src/server/api.ts +++ b/packages/typegen/src/server/api.ts @@ -115,7 +115,14 @@ async function handlePostConfig( // Write to disk as pretty JSON (replacing JSONC) const fullPath = path.resolve(context.cwd, context.configPath); - const jsonContent = JSON.stringify(validation.data, null, 2) + "\n"; + // Add $schema at the top of the config + const configData = validation.data as Record; + const { $schema: _, ...rest } = configData; + const configWithSchema = { + $schema: "https://proofkit.dev/typegen-config-schema.json", + ...rest, + }; + const jsonContent = JSON.stringify(configWithSchema, null, 2) + "\n"; await fs.ensureDir(path.dirname(fullPath)); await fs.writeFile(fullPath, jsonContent, "utf8"); diff --git a/packages/typegen/src/server/app.ts b/packages/typegen/src/server/app.ts index 15b03c8f..b4ab907a 100644 --- a/packages/typegen/src/server/app.ts +++ b/packages/typegen/src/server/app.ts @@ -3,7 +3,11 @@ import { zValidator } from "@hono/zod-validator"; import fs from "fs-extra"; import path from "path"; import { parse } from "jsonc-parser"; -import { typegenConfig, typegenConfigSingle } from "../types"; +import { + typegenConfig, + typegenConfigSingle, + typegenConfigSingleForValidation, +} from "../types"; import z from "zod/v4"; import { type clientTypes, FileMakerError } from "@proofkit/fmdapi"; import { @@ -52,6 +56,16 @@ function flattenLayouts( } export function createApiApp(context: ApiContext) { + // Request-validation schema: add default `type` for backwards compatibility. + // Important: we keep `typegenConfigSingleForValidation` as a pure discriminated union + // so JSON Schema generation (apps/docs) remains unchanged. + const typegenConfigSingleRequestForValidation = z.preprocess((data) => { + if (data && typeof data === "object" && !("type" in data)) { + return { ...(data as Record), type: "fmdapi" }; + } + return data; + }, typegenConfigSingleForValidation); + // Define all routes with proper chaining for type inference const app = new Hono() .basePath("/api") @@ -99,15 +113,30 @@ export function createApiApp(context: ApiContext) { zValidator( "json", z.object({ - config: z.array(typegenConfigSingle), + config: z.array(typegenConfigSingleRequestForValidation), }), ), async (c) => { try { const data = c.req.valid("json"); + // Transform validated data using runtime schema (applies transforms) + const transformedData = { + config: data.config.map((config) => { + // Add default type if missing (backwards compatibility) + const configWithType = + "type" in config && config.type + ? config + : Object.assign({}, config as Record, { + type: "fmdapi" as const, + }); + // Parse with runtime schema to apply transforms + return typegenConfigSingle.parse(configWithType); + }), + }; + // Validate with Zod (data is already { config: [...] }) - const validation = typegenConfig.safeParse(data); + const validation = typegenConfig.safeParse(transformedData); if (!validation.success) { const issues = validation.error.issues.map((err) => ({ @@ -138,7 +167,14 @@ export function createApiApp(context: ApiContext) { // Write to disk as pretty JSON (replacing JSONC) const fullPath = path.resolve(context.cwd, context.configPath); - const jsonContent = JSON.stringify(validation.data, null, 2) + "\n"; + // Add $schema at the top of the config + const configData = validation.data as Record; + const { $schema: _, ...rest } = configData; + const configWithSchema = { + $schema: "https://proofkit.dev/typegen-config-schema.json", + ...rest, + }; + const jsonContent = JSON.stringify(configWithSchema, null, 2) + "\n"; await fs.ensureDir(path.dirname(fullPath)); await fs.writeFile(fullPath, jsonContent, "utf8"); @@ -186,12 +222,33 @@ export function createApiApp(context: ApiContext) { zValidator( "json", z.object({ - config: z.union([z.array(typegenConfigSingle), typegenConfigSingle]), + config: z.union([ + z.array(typegenConfigSingleRequestForValidation), + typegenConfigSingleRequestForValidation, + ]), }), ), async (c, next) => { - const data = c.req.valid("json"); - const config = data.config; + const rawData = c.req.valid("json"); + // Transform validated data using runtime schema (applies transforms) + const configArray = Array.isArray(rawData.config) + ? rawData.config + : [rawData.config]; + const transformedConfig = configArray.map((config) => { + // Add default type if missing (backwards compatibility) + const configWithType = + "type" in config && config.type + ? config + : Object.assign({}, config as Record, { + type: "fmdapi" as const, + }); + // Parse with runtime schema to apply transforms + return typegenConfigSingle.parse(configWithType); + }); + const config: z.infer["config"] = + transformedConfig.length === 1 + ? transformedConfig[0]! + : transformedConfig; await generateTypedClients(config); await next(); @@ -319,14 +376,21 @@ export function createApiApp(context: ApiContext) { zValidator( "json", z.object({ - config: typegenConfigSingle, + config: typegenConfigSingleRequestForValidation, tableName: z.string(), }), ), async (c) => { - const input = c.req.valid("json"); - const config = input.config; - const { tableName } = input; + const rawInput = c.req.valid("json"); + // Transform validated data using runtime schema (applies transforms) + const configWithType = + "type" in rawInput.config && rawInput.config.type + ? rawInput.config + : Object.assign({}, rawInput.config as Record, { + type: "fmdapi" as const, + }); + const config = typegenConfigSingle.parse(configWithType); + const tableName = rawInput.tableName; if (config.type !== "fmodata") { return c.json({ error: "Invalid config type" }, 400); } @@ -415,11 +479,21 @@ export function createApiApp(context: ApiContext) { // POST /api/test-connection .post( "/test-connection", - zValidator("json", z.object({ config: typegenConfigSingle })), + zValidator( + "json", + z.object({ config: typegenConfigSingleRequestForValidation }), + ), async (c) => { try { - const data = c.req.valid("json"); - const config = data.config; + const rawData = c.req.valid("json"); + // Transform validated data using runtime schema (applies transforms) + const configWithType = + "type" in rawData.config && rawData.config.type + ? rawData.config + : Object.assign({}, rawData.config as Record, { + type: "fmdapi" as const, + }); + const config = typegenConfigSingle.parse(configWithType); // Validate config type if (config.type === "fmdapi") { diff --git a/packages/typegen/src/types.ts b/packages/typegen/src/types.ts index 8b1cc39c..6d2e2b2a 100644 --- a/packages/typegen/src/types.ts +++ b/packages/typegen/src/types.ts @@ -24,45 +24,57 @@ const layoutConfig = z.object({ }), }); -const envNames = z +// Base schema without transforms for JSON Schema generation (used in API validation) +export const envNamesBase = z .object({ - server: z - .string() - .optional() - .transform((val) => (val === "" ? undefined : val)), - db: z - .string() - .optional() - .transform((val) => (val === "" ? undefined : val)), + server: z.string().optional(), + db: z.string().optional(), auth: z .object({ - apiKey: z - .string() - .optional() - .transform((val) => (val === "" ? undefined : val)), - username: z - .string() - .optional() - .transform((val) => (val === "" ? undefined : val)), - password: z - .string() - .optional() - .transform((val) => (val === "" ? undefined : val)), + apiKey: z.string().optional(), + username: z.string().optional(), + password: z.string().optional(), }) - .optional() - .transform((val) => { - if (!val || Object.values(val).every((v) => v === undefined)) { - return undefined; - } - return val; - }), + .optional(), }) .optional() + .meta({ + description: + "If you're using other environment variables than the default, custom the NAMES of them here for the typegen to lookup their values when it runs.", + }); + +// Runtime schema with transforms (used for actual typegen processing) +const envNames = envNamesBase .transform((val) => { - if (val && Object.values(val).every((v) => v === undefined)) { + if (!val) return undefined; + + // Transform empty strings to undefined + const transformed: typeof val = { + server: val.server === "" ? undefined : val.server, + db: val.db === "" ? undefined : val.db, + auth: val.auth + ? { + apiKey: val.auth.apiKey === "" ? undefined : val.auth.apiKey, + username: val.auth.username === "" ? undefined : val.auth.username, + password: val.auth.password === "" ? undefined : val.auth.password, + } + : undefined, + }; + + // Remove auth if all values are undefined + if ( + transformed.auth && + Object.values(transformed.auth).every((v) => v === undefined) + ) { + transformed.auth = undefined; + } + + // Return undefined if all top-level values are undefined + if (Object.values(transformed).every((v) => v === undefined)) { return undefined; } - return val ?? undefined; + + return transformed; }) .meta({ description: @@ -134,63 +146,106 @@ const tableConfig = z.object({ }), }); -const typegenConfigSingleBase = z.discriminatedUnion("type", [ +// Shared field definitions to avoid duplication +const clearOldFilesField = z.boolean().default(false).optional().meta({ + description: + "If false, the path will not be cleared before the new files are written. Only the `client` and `generated` directories are cleared to allow for potential overrides to be kept.", +}); + +const validatorField = z + .union([z.enum(["zod", "zod/v4", "zod/v3"]), z.literal(false)]) + .default("zod/v4") + .optional() + .meta({ + description: + "If set to 'zod', 'zod/v4', or 'zod/v3', the validator will be generated using zod, otherwise it will generated Typescript types only and no runtime validation will be performed", + }); + +const clientSuffixField = z.string().default("Layout").optional().meta({ + description: "The suffix to be added to the schema name for each layout", +}); + +const generateClientField = z.boolean().default(true).optional().meta({ + description: + "If true, a layout-specific client will be generated for each layout provided, otherwise it will only generate the types. This option can be overridden for each layout individually.", +}); + +const webviewerScriptNameField = z.string().optional().meta({ + description: + "The name of the webviewer script to be used. If this key is set, the generated client will use the @proofkit/webviewer adapter instead of the OttoFMS or Fetch adapter, which will only work when loaded inside of a FileMaker webviewer.", +}); + +const reduceMetadataField = z.boolean().optional().meta({ + description: + "If true, reduced OData annotations will be requested from the server to reduce payload size. This will prevent comments, entity ids, and other properties from being generated.", +}); + +const alwaysOverrideFieldNamesField = z + .boolean() + .default(true) + .optional() + .meta({ + description: + "If true (default), field names will always be updated to match metadata, even when matching by entity ID. If false, existing field names are preserved when matching by entity ID.", + }); + +const tablesField = z.array(tableConfig).default([]).meta({ + description: + "Required array of tables to generate. Only the tables specified here will be downloaded and generated. Each table can have field-level overrides for excluding fields, renaming variables, and overriding field types.", +}); + +const includeAllFieldsByDefaultField = z + .boolean() + .default(true) + .optional() + .meta({ + description: + "If true, all fields will be included by default. If false, only fields that are explicitly listed in the `fields` array will be included.", + }); + +// Helper function to create config objects with different envNames schemas +const createFmdapiConfig = ( + envNamesSchema: typeof envNames | typeof envNamesBase, +) => z.object({ type: z.literal("fmdapi"), configName: z.string().optional(), - envNames, + envNames: envNamesSchema, layouts: z.array(layoutConfig).default([]), path, - clearOldFiles: z.boolean().default(false).optional().meta({ - description: - "If false, the path will not be cleared before the new files are written. Only the `client` and `generated` directories are cleared to allow for potential overrides to be kept.", - }), - validator: z - .union([z.enum(["zod", "zod/v4", "zod/v3"]), z.literal(false)]) - .default("zod/v4") - .optional() - .meta({ - description: - "If set to 'zod', 'zod/v4', or 'zod/v3', the validator will be generated using zod, otherwise it will generated Typescript types only and no runtime validation will be performed", - }), - clientSuffix: z.string().default("Layout").optional().meta({ - description: "The suffix to be added to the schema name for each layout", - }), - generateClient: z.boolean().default(true).optional().meta({ - description: - "If true, a layout-specific client will be generated for each layout provided, otherwise it will only generate the types. This option can be overridden for each layout individually.", - }), - webviewerScriptName: z.string().optional().meta({ - description: - "The name of the webviewer script to be used. If this key is set, the generated client will use the @proofkit/webviewer adapter instead of the OttoFMS or Fetch adapter, which will only work when loaded inside of a FileMaker webviewer.", - }), - }), + clearOldFiles: clearOldFilesField, + validator: validatorField, + clientSuffix: clientSuffixField, + generateClient: generateClientField, + webviewerScriptName: webviewerScriptNameField, + }); + +const createFmodataConfig = ( + envNamesSchema: typeof envNames | typeof envNamesBase, +) => z.object({ type: z.literal("fmodata"), configName: z.string().optional(), - envNames: z.optional(envNames), + envNames: z.optional(envNamesSchema), path, - reduceMetadata: z.boolean().optional().meta({ - description: - "If true, reduced OData annotations will be requested from the server to reduce payload size. This will prevent comments, entity ids, and other properties from being generated.", - }), - clearOldFiles: z.boolean().default(false).optional().meta({ - description: - "If false, the path will not be cleared before the new files are written. Only the `client` and `generated` directories are cleared to allow for potential overrides to be kept.", - }), - alwaysOverrideFieldNames: z.boolean().default(true).optional().meta({ - description: - "If true (default), field names will always be updated to match metadata, even when matching by entity ID. If false, existing field names are preserved when matching by entity ID.", - }), - tables: z.array(tableConfig).default([]).meta({ - description: - "Required array of tables to generate. Only the tables specified here will be downloaded and generated. Each table can have field-level overrides for excluding fields, renaming variables, and overriding field types.", - }), - includeAllFieldsByDefault: z.boolean().default(true).optional().meta({ - description: - "If true, all fields will be included by default. If false, only fields that are explicitly listed in the `fields` array will be included.", - }), - }), + reduceMetadata: reduceMetadataField, + clearOldFiles: clearOldFilesField, + alwaysOverrideFieldNames: alwaysOverrideFieldNamesField, + tables: tablesField, + includeAllFieldsByDefault: includeAllFieldsByDefaultField, + }); + +// Runtime schema with transforms (used for actual typegen processing) +const typegenConfigSingleBase = z.discriminatedUnion("type", [ + createFmdapiConfig(envNames), + createFmodataConfig(envNames), +]); + +// Validation schema without transforms/preprocess for API routes (JSON Schema compatible) +// This schema is used in API validation where JSON Schema generation is needed +export const typegenConfigSingleForValidation = z.discriminatedUnion("type", [ + createFmdapiConfig(envNamesBase), + createFmodataConfig(envNamesBase), ]); // Add default "type" field for backwards compatibility @@ -205,6 +260,14 @@ export const typegenConfig = z.object({ config: z.union([z.array(typegenConfigSingle), typegenConfigSingle]), }); +// Validation version for JSON Schema generation (no transforms, no preprocess) +export const typegenConfigForValidation = z.object({ + config: z.union([ + z.array(typegenConfigSingleForValidation), + typegenConfigSingleForValidation, + ]), +}); + export type TypegenConfig = z.infer; export type FmodataConfig = Extract< diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index e088c58e..d8900db9 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -149,22 +149,22 @@ importers: version: 2.1.1 fumadocs-core: specifier: 15.7.13 - version: 15.7.13(@types/react@19.2.7)(next@16.1.0(@babel/core@7.28.5)(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react-dom@19.2.3(react@19.2.3))(react@19.2.3) + version: 15.7.13(@types/react@19.2.7)(next@16.1.0(@babel/core@7.27.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react-dom@19.2.3(react@19.2.3))(react@19.2.3) fumadocs-docgen: specifier: ^2.1.0 version: 2.1.0 fumadocs-mdx: specifier: 11.6.4 - version: 11.6.4(acorn@8.14.1)(fumadocs-core@15.7.13(@types/react@19.2.7)(next@16.1.0(@babel/core@7.28.5)(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(next@16.1.0(@babel/core@7.28.5)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)) + version: 11.6.4(acorn@8.14.1)(fumadocs-core@15.7.13(@types/react@19.2.7)(next@16.1.0(@babel/core@7.27.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(next@16.1.0(@babel/core@7.27.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)) fumadocs-twoslash: specifier: ^3.1.7 - version: 3.1.7(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(fumadocs-ui@15.7.13(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(next@16.1.0(@babel/core@7.28.5)(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(tailwindcss@4.1.11))(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(typescript@5.9.3) + version: 3.1.7(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(fumadocs-ui@15.7.13(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(next@16.1.0(@babel/core@7.27.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(tailwindcss@4.1.11))(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(typescript@5.9.3) fumadocs-typescript: specifier: ^4.0.8 - version: 4.0.8(@types/react@19.2.7)(fumadocs-core@15.7.13(@types/react@19.2.7)(next@16.1.0(@babel/core@7.28.5)(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(fumadocs-ui@15.7.13(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(next@16.1.0(@babel/core@7.28.5)(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(tailwindcss@4.1.11))(typescript@5.9.3) + version: 4.0.8(@types/react@19.2.7)(fumadocs-core@15.7.13(@types/react@19.2.7)(next@16.1.0(@babel/core@7.27.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(fumadocs-ui@15.7.13(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(next@16.1.0(@babel/core@7.27.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(tailwindcss@4.1.11))(typescript@5.9.3) fumadocs-ui: specifier: 15.7.13 - version: 15.7.13(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(next@16.1.0(@babel/core@7.28.5)(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(tailwindcss@4.1.11) + version: 15.7.13(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(next@16.1.0(@babel/core@7.27.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(tailwindcss@4.1.11) hono: specifier: ^4.9.0 version: 4.9.0 @@ -176,7 +176,7 @@ importers: version: 0.511.0(react@19.2.3) next: specifier: 16.1.0 - version: 16.1.0(@babel/core@7.28.5)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) + version: 16.1.0(@babel/core@7.27.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) next-themes: specifier: ^0.4.6 version: 0.4.6(react-dom@19.2.3(react@19.2.3))(react@19.2.3) @@ -329,9 +329,6 @@ importers: '@clack/prompts': specifier: ^0.11.0 version: 0.11.0 - '@ianvs/prettier-plugin-sort-imports': - specifier: ^4.4.1 - version: 4.4.1(prettier@3.5.3) '@proofkit/fmdapi': specifier: workspace:* version: link:../fmdapi @@ -9969,6 +9966,7 @@ snapshots: '@jridgewell/gen-mapping': 0.3.8 '@jridgewell/trace-mapping': 0.3.25 jsesc: 3.1.0 + optional: true '@babel/generator@7.28.3': dependencies: @@ -10119,6 +10117,7 @@ snapshots: '@babel/parser@7.27.2': dependencies: '@babel/types': 7.27.1 + optional: true '@babel/parser@7.28.3': dependencies: @@ -10319,6 +10318,7 @@ snapshots: globals: 11.12.0 transitivePeerDependencies: - supports-color + optional: true '@babel/traverse@7.27.7': dependencies: @@ -10348,6 +10348,7 @@ snapshots: dependencies: '@babel/helper-string-parser': 7.27.1 '@babel/helper-validator-identifier': 7.27.1 + optional: true '@babel/types@7.27.7': dependencies: @@ -11189,6 +11190,7 @@ snapshots: semver: 7.7.2 transitivePeerDependencies: - supports-color + optional: true '@img/colour@1.0.0': optional: true @@ -14061,6 +14063,15 @@ snapshots: chai: 6.2.1 tinyrainbow: 3.0.3 + '@vitest/mocker@4.0.15(msw@2.10.2(@types/node@22.17.1)(typescript@5.9.3))(vite@6.3.5(@types/node@22.17.1)(jiti@1.21.7)(lightningcss@1.30.2)(tsx@4.21.0)(yaml@2.8.0))': + dependencies: + '@vitest/spy': 4.0.15 + estree-walker: 3.0.3 + magic-string: 0.30.21 + optionalDependencies: + msw: 2.10.2(@types/node@22.17.1)(typescript@5.9.3) + vite: 6.3.5(@types/node@22.17.1)(jiti@1.21.7)(lightningcss@1.30.2)(tsx@4.21.0)(yaml@2.8.0) + '@vitest/mocker@4.0.15(msw@2.10.2(@types/node@22.17.1)(typescript@5.9.3))(vite@6.3.5(@types/node@22.17.1)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.20.3)(yaml@2.8.0))': dependencies: '@vitest/spy': 4.0.15 @@ -15376,7 +15387,7 @@ snapshots: '@next/eslint-plugin-next': 16.1.0 eslint: 9.27.0(jiti@2.6.1) eslint-import-resolver-node: 0.3.9 - eslint-import-resolver-typescript: 3.10.1(eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.50.0(eslint@9.27.0(jiti@2.6.1))(typescript@5.9.3))(eslint@9.27.0(jiti@2.6.1)))(eslint@9.27.0(jiti@2.6.1)) + eslint-import-resolver-typescript: 3.10.1(eslint-plugin-import@2.32.0)(eslint@9.27.0(jiti@2.6.1)) eslint-plugin-import: 2.32.0(@typescript-eslint/parser@8.50.0(eslint@9.27.0(jiti@2.6.1))(typescript@5.9.3))(eslint-import-resolver-typescript@3.10.1)(eslint@9.27.0(jiti@2.6.1)) eslint-plugin-jsx-a11y: 6.10.2(eslint@9.27.0(jiti@2.6.1)) eslint-plugin-react: 7.37.5(eslint@9.27.0(jiti@2.6.1)) @@ -15399,7 +15410,7 @@ snapshots: transitivePeerDependencies: - supports-color - eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.50.0(eslint@9.27.0(jiti@2.6.1))(typescript@5.9.3))(eslint@9.27.0(jiti@2.6.1)))(eslint@9.27.0(jiti@2.6.1)): + eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.32.0)(eslint@9.27.0(jiti@2.6.1)): dependencies: '@nolyfill/is-core-module': 1.0.39 debug: 4.4.1(supports-color@5.5.0) @@ -15414,14 +15425,14 @@ snapshots: transitivePeerDependencies: - supports-color - eslint-module-utils@2.12.1(@typescript-eslint/parser@8.50.0(eslint@9.27.0(jiti@2.6.1))(typescript@5.9.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.50.0(eslint@9.27.0(jiti@2.6.1))(typescript@5.9.3))(eslint@9.27.0(jiti@2.6.1)))(eslint@9.27.0(jiti@2.6.1)))(eslint@9.27.0(jiti@2.6.1)): + eslint-module-utils@2.12.1(@typescript-eslint/parser@8.50.0(eslint@9.27.0(jiti@2.6.1))(typescript@5.9.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.10.1)(eslint@9.27.0(jiti@2.6.1)): dependencies: debug: 3.2.7 optionalDependencies: '@typescript-eslint/parser': 8.50.0(eslint@9.27.0(jiti@2.6.1))(typescript@5.9.3) eslint: 9.27.0(jiti@2.6.1) eslint-import-resolver-node: 0.3.9 - eslint-import-resolver-typescript: 3.10.1(eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.50.0(eslint@9.27.0(jiti@2.6.1))(typescript@5.9.3))(eslint@9.27.0(jiti@2.6.1)))(eslint@9.27.0(jiti@2.6.1)) + eslint-import-resolver-typescript: 3.10.1(eslint-plugin-import@2.32.0)(eslint@9.27.0(jiti@2.6.1)) transitivePeerDependencies: - supports-color @@ -15436,7 +15447,7 @@ snapshots: doctrine: 2.1.0 eslint: 9.27.0(jiti@2.6.1) eslint-import-resolver-node: 0.3.9 - eslint-module-utils: 2.12.1(@typescript-eslint/parser@8.50.0(eslint@9.27.0(jiti@2.6.1))(typescript@5.9.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.50.0(eslint@9.27.0(jiti@2.6.1))(typescript@5.9.3))(eslint@9.27.0(jiti@2.6.1)))(eslint@9.27.0(jiti@2.6.1)))(eslint@9.27.0(jiti@2.6.1)) + eslint-module-utils: 2.12.1(@typescript-eslint/parser@8.50.0(eslint@9.27.0(jiti@2.6.1))(typescript@5.9.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.10.1)(eslint@9.27.0(jiti@2.6.1)) hasown: 2.0.2 is-core-module: 2.16.1 is-glob: 4.0.3 @@ -15953,7 +15964,7 @@ snapshots: fsevents@2.3.3: optional: true - fumadocs-core@15.7.13(@types/react@19.2.7)(next@16.1.0(@babel/core@7.28.5)(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react-dom@19.2.3(react@19.2.3))(react@19.2.3): + fumadocs-core@15.7.13(@types/react@19.2.7)(next@16.1.0(@babel/core@7.27.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react-dom@19.2.3(react@19.2.3))(react@19.2.3): dependencies: '@formatjs/intl-localematcher': 0.6.1 '@orama/orama': 3.1.14 @@ -15974,7 +15985,7 @@ snapshots: unist-util-visit: 5.0.0 optionalDependencies: '@types/react': 19.2.7 - next: 16.1.0(@babel/core@7.28.5)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) + next: 16.1.0(@babel/core@7.27.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) react: 19.2.3 react-dom: 19.2.3(react@19.2.3) transitivePeerDependencies: @@ -15989,7 +16000,7 @@ snapshots: unist-util-visit: 5.0.0 zod: 3.25.76 - fumadocs-mdx@11.6.4(acorn@8.14.1)(fumadocs-core@15.7.13(@types/react@19.2.7)(next@16.1.0(@babel/core@7.28.5)(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(next@16.1.0(@babel/core@7.28.5)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)): + fumadocs-mdx@11.6.4(acorn@8.14.1)(fumadocs-core@15.7.13(@types/react@19.2.7)(next@16.1.0(@babel/core@7.27.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(next@16.1.0(@babel/core@7.27.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)): dependencies: '@mdx-js/mdx': 3.1.0(acorn@8.14.1) '@standard-schema/spec': 1.0.0 @@ -15998,11 +16009,11 @@ snapshots: esbuild: 0.25.4 estree-util-value-to-estree: 3.4.0 fast-glob: 3.3.3 - fumadocs-core: 15.7.13(@types/react@19.2.7)(next@16.1.0(@babel/core@7.28.5)(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react-dom@19.2.3(react@19.2.3))(react@19.2.3) + fumadocs-core: 15.7.13(@types/react@19.2.7)(next@16.1.0(@babel/core@7.27.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react-dom@19.2.3(react@19.2.3))(react@19.2.3) gray-matter: 4.0.3 js-yaml: 4.1.0 lru-cache: 11.1.0 - next: 16.1.0(@babel/core@7.28.5)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) + next: 16.1.0(@babel/core@7.27.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) picocolors: 1.1.1 unist-util-visit: 5.0.0 zod: 3.25.76 @@ -16010,11 +16021,11 @@ snapshots: - acorn - supports-color - fumadocs-twoslash@3.1.7(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(fumadocs-ui@15.7.13(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(next@16.1.0(@babel/core@7.28.5)(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(tailwindcss@4.1.11))(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(typescript@5.9.3): + fumadocs-twoslash@3.1.7(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(fumadocs-ui@15.7.13(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(next@16.1.0(@babel/core@7.27.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(tailwindcss@4.1.11))(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(typescript@5.9.3): dependencies: '@radix-ui/react-popover': 1.1.15(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) '@shikijs/twoslash': 3.13.0(typescript@5.9.3) - fumadocs-ui: 15.7.13(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(next@16.1.0(@babel/core@7.28.5)(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(tailwindcss@4.1.11) + fumadocs-ui: 15.7.13(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(next@16.1.0(@babel/core@7.27.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(tailwindcss@4.1.11) mdast-util-from-markdown: 2.0.2 mdast-util-gfm: 3.1.0 mdast-util-to-hast: 13.2.0 @@ -16030,10 +16041,10 @@ snapshots: - supports-color - typescript - fumadocs-typescript@4.0.8(@types/react@19.2.7)(fumadocs-core@15.7.13(@types/react@19.2.7)(next@16.1.0(@babel/core@7.28.5)(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(fumadocs-ui@15.7.13(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(next@16.1.0(@babel/core@7.28.5)(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(tailwindcss@4.1.11))(typescript@5.9.3): + fumadocs-typescript@4.0.8(@types/react@19.2.7)(fumadocs-core@15.7.13(@types/react@19.2.7)(next@16.1.0(@babel/core@7.27.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(fumadocs-ui@15.7.13(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(next@16.1.0(@babel/core@7.27.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(tailwindcss@4.1.11))(typescript@5.9.3): dependencies: estree-util-value-to-estree: 3.4.0 - fumadocs-core: 15.7.13(@types/react@19.2.7)(next@16.1.0(@babel/core@7.28.5)(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react-dom@19.2.3(react@19.2.3))(react@19.2.3) + fumadocs-core: 15.7.13(@types/react@19.2.7)(next@16.1.0(@babel/core@7.27.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react-dom@19.2.3(react@19.2.3))(react@19.2.3) hast-util-to-estree: 3.1.3 hast-util-to-jsx-runtime: 2.3.6 remark: 15.0.1 @@ -16044,11 +16055,11 @@ snapshots: unist-util-visit: 5.0.0 optionalDependencies: '@types/react': 19.2.7 - fumadocs-ui: 15.7.13(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(next@16.1.0(@babel/core@7.28.5)(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(tailwindcss@4.1.11) + fumadocs-ui: 15.7.13(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(next@16.1.0(@babel/core@7.27.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(tailwindcss@4.1.11) transitivePeerDependencies: - supports-color - fumadocs-ui@15.7.13(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(next@16.1.0(@babel/core@7.28.5)(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(tailwindcss@4.1.11): + fumadocs-ui@15.7.13(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(next@16.1.0(@babel/core@7.27.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(tailwindcss@4.1.11): dependencies: '@radix-ui/react-accordion': 1.2.12(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) '@radix-ui/react-collapsible': 1.1.12(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) @@ -16061,7 +16072,7 @@ snapshots: '@radix-ui/react-slot': 1.2.3(@types/react@19.2.7)(react@19.2.3) '@radix-ui/react-tabs': 1.1.13(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) class-variance-authority: 0.7.1 - fumadocs-core: 15.7.13(@types/react@19.2.7)(next@16.1.0(@babel/core@7.28.5)(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react-dom@19.2.3(react@19.2.3))(react@19.2.3) + fumadocs-core: 15.7.13(@types/react@19.2.7)(next@16.1.0(@babel/core@7.27.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react-dom@19.2.3(react@19.2.3))(react@19.2.3) lodash.merge: 4.6.2 next-themes: 0.4.6(react-dom@19.2.3(react@19.2.3))(react@19.2.3) postcss-selector-parser: 7.1.0 @@ -16072,7 +16083,7 @@ snapshots: tailwind-merge: 3.3.1 optionalDependencies: '@types/react': 19.2.7 - next: 16.1.0(@babel/core@7.28.5)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) + next: 16.1.0(@babel/core@7.27.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) tailwindcss: 4.1.11 transitivePeerDependencies: - '@mixedbread/sdk' @@ -17718,30 +17729,6 @@ snapshots: - '@babel/core' - babel-plugin-macros - next@16.1.0(@babel/core@7.28.5)(react-dom@19.2.3(react@19.2.3))(react@19.2.3): - dependencies: - '@next/env': 16.1.0 - '@swc/helpers': 0.5.15 - baseline-browser-mapping: 2.9.11 - caniuse-lite: 1.0.30001726 - postcss: 8.4.31 - react: 19.2.3 - react-dom: 19.2.3(react@19.2.3) - styled-jsx: 5.1.6(@babel/core@7.28.5)(react@19.2.3) - optionalDependencies: - '@next/swc-darwin-arm64': 16.1.0 - '@next/swc-darwin-x64': 16.1.0 - '@next/swc-linux-arm64-gnu': 16.1.0 - '@next/swc-linux-arm64-musl': 16.1.0 - '@next/swc-linux-x64-gnu': 16.1.0 - '@next/swc-linux-x64-musl': 16.1.0 - '@next/swc-win32-arm64-msvc': 16.1.0 - '@next/swc-win32-x64-msvc': 16.1.0 - sharp: 0.34.5 - transitivePeerDependencies: - - '@babel/core' - - babel-plugin-macros - node-abi@3.75.0: dependencies: semver: 7.7.3 @@ -19215,13 +19202,6 @@ snapshots: optionalDependencies: '@babel/core': 7.28.5 - styled-jsx@5.1.6(@babel/core@7.28.5)(react@19.2.3): - dependencies: - client-only: 0.0.1 - react: 19.2.3 - optionalDependencies: - '@babel/core': 7.28.5 - superjson@2.2.2: dependencies: copy-anything: 3.0.5 @@ -19955,7 +19935,7 @@ snapshots: vitest@4.0.15(@types/node@22.17.1)(happy-dom@15.11.7)(jiti@1.21.7)(lightningcss@1.30.2)(msw@2.10.2(@types/node@22.17.1)(typescript@5.9.3))(tsx@4.21.0)(yaml@2.8.0): dependencies: '@vitest/expect': 4.0.15 - '@vitest/mocker': 4.0.15(msw@2.10.2(@types/node@22.17.1)(typescript@5.9.3))(vite@6.3.5(@types/node@22.17.1)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.21.0)(yaml@2.8.0)) + '@vitest/mocker': 4.0.15(msw@2.10.2(@types/node@22.17.1)(typescript@5.9.3))(vite@6.3.5(@types/node@22.17.1)(jiti@1.21.7)(lightningcss@1.30.2)(tsx@4.21.0)(yaml@2.8.0)) '@vitest/pretty-format': 4.0.15 '@vitest/runner': 4.0.15 '@vitest/snapshot': 4.0.15 diff --git a/prettier.config.mjs b/prettier.config.mjs index 550865d3..6727cd7b 100644 --- a/prettier.config.mjs +++ b/prettier.config.mjs @@ -1,5 +1,5 @@ /** - * @type {import('prettier').Config & import("@ianvs/prettier-plugin-sort-imports").PluginConfig} + * @type {import('prettier').Config} */ const config = { arrowParens: "always",