-
Notifications
You must be signed in to change notification settings - Fork 1
custom registry base #59
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
This stack of pull requests is managed by Graphite. Learn more about stacking. |
1d48167 to
ff0a446
Compare
ff0a446 to
78aa458
Compare
78aa458 to
50bfe91
Compare
c9b9731 to
e23e93b
Compare
67fd7ad to
865e618
Compare
e23e93b to
4ebe2e2
Compare
4ebe2e2 to
e767132
Compare
|
Caution Review failedThe pull request is closed. WalkthroughIntroduces a static component registry in apps/docs with Zod-typed metadata, utilities, Hono-based API routes, build-time validation, a sample “mode-toggle” template, and Vitest tests. Adds FileMaker Data API docs and client example. Updates Next.js config/redirects, source transformer, tsconfig, and testing config. Performs dependency bumps and adds a WebViewer executeScript placeholder. Changes
Sequence Diagram(s)sequenceDiagram
participant Client
participant NextRoute as Next.js Route (/r/[...])
participant Hono as Hono App
participant Utils as Registry Utils
participant FS as Filesystem
Client->>NextRoute: GET /r/index.json
NextRoute->>Hono: handle request
Hono->>Utils: getRegistryIndex()
Utils->>FS: scan templates/_meta.ts
FS-->>Utils: templates info
Utils-->>Hono: index JSON
Hono-->>Client: 200 index
Client->>NextRoute: GET /r/mode-toggle.json
NextRoute->>Hono: handle request
Hono->>Utils: getStaticComponent("mode-toggle")
Utils->>FS: load _meta.ts, read files
FS-->>Utils: file contents
Utils-->>Hono: component payload
Hono-->>Client: 200 component
sequenceDiagram
participant Build as Next Build
participant Validator as validateRegistry()
participant FS as Filesystem
Build->>Validator: run validation
Validator->>FS: find templates/_meta.ts
Validator->>FS: check declared files exist
Validator-->>Build: success or throw on error
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes Possibly related PRs
Tip 🔌 Remote MCP (Model Context Protocol) integration is now available!Pro plan users can now connect to remote MCP servers from the Integrations page. Connect with popular remote MCPs such as Notion and Linear to add more context to your reviews and chats. 📜 Recent review detailsConfiguration used: .coderabbit.yaml 💡 Knowledge Base configuration:
You can enable these sources in your CodeRabbit configuration. ⛔ Files ignored due to path filters (1)
📒 Files selected for processing (9)
✨ Finishing Touches
🧪 Generate unit tests
🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
SupportNeed help? Create a ticket on our support page for assistance with any issues or questions. CodeRabbit Commands (Invoked using PR/Issue comments)Type Other keywords and placeholders
Status, Documentation and Community
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 27
🧹 Nitpick comments (23)
.vscode/settings.json (1)
7-7: Optional: prompt contributors to use the workspace TypeScriptThis improves DX by nudging VS Code to switch to the workspace TS version when opening the repo.
Apply this diff:
- "typescript.tsdk": "node_modules/typescript/lib" + "typescript.tsdk": "node_modules/typescript/lib", + "typescript.enablePromptUseWorkspaceTsdk": truepackage.json (1)
19-19: Node type defs bumped to v22.x — align engines or verify runtime compatibilityUsing @types/node 22 with a repo-level engine of "node": ">=18" can lead to type/runtime drift if contributors use Node 18. Consider aligning engines to Node 20/22 (as several packages in the monorepo already do) or pinning @types/node to match the minimum supported runtime.
If you decide to align the root engines with the stricter packages:
{ "engines": { "node": "^20.0.0 || ^22.0.0" } }apps/docs/src/registry/templates/mode-toggle/mode-toggle.tsx (1)
14-39: Avoid hydration/FOUC issues by deferring render until mountednext-themes recommends guarding initial render to prevent a flash/mismatch when the theme class is applied on hydration. Gate with a mounted flag.
Apply this diff:
export function ModeToggle() { - const { setTheme } = useTheme(); + const { setTheme } = useTheme(); + const [mounted, setMounted] = React.useState(false); + React.useEffect(() => setMounted(true), []); + + if (!mounted) return null;apps/docs/content/docs/fmdapi/CustomersLayout.ts (1)
6-9: Avoid embedding credentials; prefer env-configured placeholdersEven for docs, showing a best-practice pattern helps prevent accidental key leaks. Consider reading the API key from environment and default to a clear placeholder string.
Apply this diff:
adapter: new OttoAdapter({ - auth: { apiKey: "dk_not_a_real_key" }, + auth: { apiKey: process.env.FMDAPI_API_KEY ?? "REPLACE_WITH_YOUR_API_KEY" }, db: "Customers.fmp12", server: "https://filemaker.example.com", }),apps/docs/source.config.ts (1)
55-63: Optional: add a small debug hint when file is not foundIf customersLayoutSource remains empty, consider a debug log (guarded by NODE_ENV) to help authors understand missing injections during local authoring.
Example:
if (!customersLayoutSource && process.env.NODE_ENV !== "production") { console.debug("[twoslash] CustomersLayout.ts not found in any candidate path"); }apps/docs/content/docs/fmdapi/examples.mdx (3)
115-117: Tighten wordingMinor clarity/conciseness tweak.
Apply this diff:
-Use `create` to add new records to your FileMaker database. +Use `create` to add records to your FileMaker database.
150-151: Fix typo: “alwyas” → “always”Small typo in guidance text.
Apply this diff:
-This record id *can* change during imports or data migrations, so you should never store it, but instead alwyas look it up via a find request when it's needed. +This record id *can* change during imports or data migrations, so you should never store it, but instead always look it up via a find request when it's needed.
217-218: Minor style improvementSmoother phrasing for the explanatory sentence.
Apply this diff:
-... on this newly created record; thus giving you access to the calculated values ... +... on this newly created record, which provides access to calculated values ....cursor/plans/static-registry.md (2)
17-31: Add a language to the fenced code blockmarkdownlint prefers a language spec for fences to improve readability.
Apply this diff:
-``` +```text src/ └── registry/ ├── lib/ │ ├── types.ts // NEW: Centralized type definitions │ ├── validator.ts // Build-time validation script │ └── utils.ts // File system and data transformation logic └── templates/ ├── button/ │ ├── _meta.ts │ └── button.tsx └── icon/ ├── _meta.ts └── index.ts--- `93-101`: **Update example route path/basePath to reflect the implementation** The plan shows /api/registry while the implementation uses apps/docs/src/app/r/[[...name]]. Update the example to avoid confusion. Apply this diff: ```diff -// src/app/api/registry/[...slug]/route.ts +// apps/docs/src/app/r/[[...name]]/route.ts @@ -const app = new Hono().basePath("/api/registry"); +const app = new Hono().basePath("/r");apps/docs/src/registry/lib/types.ts (2)
63-71: Comment claims single-or-array support, but the type enforces array-only.Either update the type to accept both forms or fix the comment to reflect array-only. Given downstream code likely expects arrays, simplest is to fix the comment.
Option A — fix the comment (safer, non-breaking):
-// Adapt shadcn RegistryItem: require `content` in files and allow both single and array forms +// Adapt shadcn RegistryItem: require `content` in files; normalize to an array formOption B — accept both single and array forms (requires downstream handling):
-export type RegistryItem = Omit<ShadcnRegistryItem, "files"> & { - files: ShadcnFilesUnion; -}; +export type RegistryItem = Omit<ShadcnRegistryItem, "files"> & { + files: ShadcnFilesUnion | ShadcnFilesUnion[number]; +};If you choose Option B, ensure utils and validators handle the union properly.
7-25: Avoid duplicating registry type enums; consider deriving from shadcn’s schema.To prevent drift with upstream updates, consider referencing or refining
registryItemTypeSchemafrom "shadcn/registry" instead of re-declaring the enum locally—unless you intentionally diverge.For example:
-const registryTypeSchema = z - .enum([ - "registry:lib", - "registry:block", - "registry:component", - "registry:ui", - "registry:hook", - "registry:page", - "registry:file", - "registry:theme", - "registry:style", - "registry:item", - "registry:example", - "registry:internal", - ]) +const registryTypeSchema = registryItemTypeSchema .describe( "The type property is used to specify the type of your registry item. This is used to determine the type and target path of the item when resolved for a project.", );Only do this if the sets are semantically equivalent in your use case.
apps/docs/server.ts (1)
4-6: Harden port parsing and default to 3000 on NaN.parseInt can yield NaN for invalid env inputs. Provide a robust fallback.
Apply this diff:
-const port = parseInt(process.env.PORT || "3000"); +const envPort = process.env.PORT; +const parsed = envPort ? Number.parseInt(envPort, 10) : NaN; +const port = Number.isFinite(parsed) ? parsed : 3000;apps/docs/next.config.ts (2)
3-7: Running validateRegistry() at import-time may slow dev or re-execute unnecessarily.Consider gating validation by environment to avoid redundant work during local dev hot reloads, while keeping CI/build enforcement.
Apply this diff:
-import { validateRegistry } from "@/registry/lib/validator"; +import { validateRegistry } from "@/registry/lib/validator"; const withMDX = createMDX(); -validateRegistry(); +if ( + process.env.CI === "true" || + process.env.NODE_ENV === "production" || + process.env.VALIDATE_REGISTRY === "true" +) { + validateRegistry(); +}
12-20: Redirect looks correct; consider adding a trailing-slash canonicalization rule if needed.If your app relies on consistent trailing-slash behavior, you might add a complementary rule (only if your router requires it). Otherwise, this is good as-is.
apps/docs/src/app/r/[[...name]]/registry.ts (2)
7-17: Consider more specific error handling and logging for production.The error handling could be improved for better debugging and monitoring:
- The error is not logged when the index fetch fails
- Generic 500 error doesn't help identify the root cause
Apply this diff to improve error handling:
app.get("/", async (c) => { try { const index = await getRegistryIndex(); return c.json(index); } catch (error) { + console.error("Failed to fetch registry index:", error); return c.json( - { error: "Failed to fetch registry index." }, + { error: "Failed to fetch registry index" }, { status: 500 }, ); } });
29-30: Inconsistent error message formatting.The error message includes a period here but not in the index endpoint (line 13).
Apply this diff for consistency:
- return c.json({ error: "Component not found." }, { status: 404 }); + return c.json({ error: "Component not found" }, { status: 404 });apps/docs/tests/utils.manifest.test.ts (1)
30-63: Type checking tests should useexpectTypeOffor better assertions.The current type checking approach with unused variables and
@ts-expect-errorcomments works but could be improved. Consider usingexpectTypeOffrom vitest for more explicit type assertions.import { expectTypeOf } from 'vitest' it("validates RegistryItem types", () => { // Test valid type expectTypeOf<RegistryItem>().toMatchTypeOf<{ name: string; type: "registry:component"; files: Array<{ type: string; path: string; content: string; target: string; }>; }>(); // Test that required fields are enforced expectTypeOf<RegistryItem>().not.toMatchTypeOf<{ name: string; type: "registry:component"; // missing files }>(); });apps/docs/src/registry/lib/validator.ts (2)
7-22: Potential performance issue with nestedreaddirSynccalls.The function performs synchronous file system operations in nested loops, which could be slow for large directory structures. Consider using async operations or caching results.
Consider refactoring to use async operations:
async function getTemplateDirs(root: string, prefix = ""): Promise<string[]> { const entries = await fs.promises.readdir(root, { withFileTypes: true }); const result: string[] = []; await Promise.all(entries.map(async (entry) => { if (!entry.isDirectory()) return; const dirPath = path.join(root, entry.name); const rel = prefix ? `${prefix}/${entry.name}` : entry.name; const files = await fs.promises.readdir(dirPath); if (files.includes("_meta.ts")) { result.push(rel); } // Recurse for nested templates const nested = await getTemplateDirs(dirPath, rel); result.push(...nested); })); return result; }
86-95: Error re-throwing logic could be simplified.The error handling logic checks if the error message includes "Template" to decide whether to re-throw, which is fragile.
Consider using a custom error class:
class TemplateValidationError extends Error { constructor(template: string, message: string) { super(`Template ${template}: ${message}`); this.name = 'TemplateValidationError'; } } // Then in the validation code: if (!meta) { throw new TemplateValidationError(rel, "_meta.ts must export a 'meta' object"); } // And in the catch block: } catch (loadError) { if (loadError instanceof TemplateValidationError) { throw loadError; } throw new TemplateValidationError(rel, `Failed to load _meta.ts - ${loadError}`); }apps/docs/src/registry/lib/utils.ts (3)
79-84: Avoid repeated full directory scans; introduce a simple module-level cache.getStaticComponent rescans the templates tree for existence checks. This is expensive and runs per request. Introduce a module-level cache keyed by templatesPath and invalidate in dev if necessary.
I can draft a small caching layer (with dev-mode invalidation via fs.mtime) if you want it included in this PR.
46-58: Optionally validate meta shape early.Given this powers a public API, validating that meta conforms to TemplateMetadata (e.g., registryType present and consistent with meta.type) can prevent hard-to-debug failures later.
If you want, I can add a lightweight runtime check using zod (if already available in types.ts) to ensure required fields exist before proceeding.
60-72: Memoize index in-process to avoid repeated jiti loads and FS scans.Both jiti transpilation and disk scans are expensive. A simple in-memory cache (invalidated in dev) will reduce latency and CPU.
Example approach (outside these lines):
- Keep a module-level Map<string, { index: RegistryIndexItem[]; mtimeMs: number }>.
- In dev (NODE_ENV !== "production"), recompute if any _meta.ts mtime has changed; in prod, reuse cached.
📜 Review details
Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (1)
pnpm-lock.yamlis excluded by!**/pnpm-lock.yaml
📒 Files selected for processing (32)
.cursor/plans/static-registry.md(1 hunks).vscode/settings.json(1 hunks)apps/demo/package.json(1 hunks)apps/docs/content/docs/fmdapi/CustomersLayout.ts(1 hunks)apps/docs/content/docs/fmdapi/examples.mdx(1 hunks)apps/docs/content/docs/fmdapi/meta.json(1 hunks)apps/docs/next.config.ts(1 hunks)apps/docs/package.json(1 hunks)apps/docs/public/test.tsx(1 hunks)apps/docs/server.ts(1 hunks)apps/docs/source.config.ts(2 hunks)apps/docs/src/app/r/[[...name]]/registry.ts(1 hunks)apps/docs/src/app/r/[[...name]]/route.ts(1 hunks)apps/docs/src/registry/lib/types.ts(1 hunks)apps/docs/src/registry/lib/utils.ts(1 hunks)apps/docs/src/registry/lib/validator.ts(1 hunks)apps/docs/src/registry/templates/mode-toggle/_meta.ts(1 hunks)apps/docs/src/registry/templates/mode-toggle/mode-toggle.tsx(1 hunks)apps/docs/test-validation.mjs(1 hunks)apps/docs/tests/registry-api.test.ts(1 hunks)apps/docs/tests/utils.manifest.test.ts(1 hunks)apps/docs/tsconfig.json(2 hunks)apps/docs/vitest.config.ts(1 hunks)package.json(1 hunks)packages/better-auth/package.json(1 hunks)packages/cli/package.json(2 hunks)packages/fmdapi/package.json(1 hunks)packages/fmdapi/tests/client-methods.test.ts(1 hunks)packages/fmodata/package.json(1 hunks)packages/typegen/package.json(2 hunks)packages/webviewer/package.json(1 hunks)pnpm-workspace.yaml(0 hunks)
💤 Files with no reviewable changes (1)
- pnpm-workspace.yaml
🧰 Additional context used
🧬 Code Graph Analysis (6)
apps/docs/src/registry/templates/mode-toggle/_meta.ts (1)
apps/docs/src/registry/lib/types.ts (1)
TemplateMetadata(61-61)
apps/docs/src/registry/lib/validator.ts (2)
apps/docs/src/registry/templates/mode-toggle/_meta.ts (1)
meta(3-20)apps/docs/src/registry/lib/types.ts (1)
templateMetadataSchema(43-58)
apps/docs/tests/utils.manifest.test.ts (2)
apps/docs/src/registry/lib/utils.ts (2)
getRegistryIndex(60-72)getStaticComponent(74-121)apps/docs/src/registry/lib/types.ts (1)
RegistryItem(69-71)
apps/docs/src/registry/lib/utils.ts (2)
apps/docs/src/registry/lib/types.ts (3)
TemplateMetadata(61-61)RegistryItem(69-71)ShadcnFilesUnion(65-67)apps/docs/src/registry/templates/mode-toggle/_meta.ts (1)
meta(3-20)
apps/docs/content/docs/fmdapi/CustomersLayout.ts (1)
packages/fmdapi/src/client.ts (1)
DataApi(550-550)
apps/docs/next.config.ts (1)
apps/docs/src/registry/lib/validator.ts (1)
validateRegistry(24-105)
🪛 LanguageTool
apps/docs/content/docs/fmdapi/examples.mdx
[style] ~115-~115: ‘new records’ might be wordy. Consider a shorter alternative.
Context: ...# Creating Records Use create to add new records to your FileMaker database. ```ts twos...
(EN_WORDINESS_PREMIUM_NEW_RECORDS)
[grammar] ~150-~150: Ensure spelling is correct
Context: ... you should never store it, but instead alwyas look it up via a find request when it's...
(QB_NEW_EN_ORTHOGRAPHY_ERROR_IDS_1)
[style] ~217-~217: Try using a synonym here to strengthen your writing.
Context: ...used on this newly created record; thus giving you access to the calculated values such as...
(GIVE_PROVIDE)
🪛 markdownlint-cli2 (0.17.2)
.cursor/plans/static-registry.md
17-17: Fenced code blocks should have a language specified
(MD040, fenced-code-language)
🔇 Additional comments (15)
packages/fmdapi/tests/client-methods.test.ts (1)
300-306: No functional change; safe whitespace tweakThe added blank line has no impact on test behavior. OK to keep.
.vscode/settings.json (1)
6-7: Use workspace TypeScript SDK — LGTMPointing VS Code to the workspace TS SDK ensures consistent tooling across contributors. Good addition.
apps/docs/tsconfig.json (2)
18-23: Alias for "@/registry/" placed before "@/" — good to avoid path ambiguityOrder here prevents "@/registry/..." from being swallowed by the more general "@/*". Looks correct.
31-31: No static imports fromsrc/registry/templates—runtime FS access only
All references to the excluded directory are dynamicpath.join(process.cwd(), "src/registry/templates")usages in your runtime code, not TS/TSX imports:• apps/docs/src/registry/lib/validator.ts:25
• apps/docs/src/registry/lib/utils.ts:7Excluding
"src/registry/templates/**/*"in tsconfig.json is safe.apps/docs/content/docs/fmdapi/meta.json (1)
12-12: Examples page verified
Theexamples.mdxfile exists atapps/docs/content/docs/fmdapi/examples.mdxand matches the"examples"slug—no further changes needed.package.json (1)
24-24: Baseline consistency confirmed across tsconfig filesAll of the project’s tsconfig.json files extend the same root tsconfig.json, and the auxiliary tsconfig.scripts.json files consistently extend tsconfig.base.json. No discrepancies in “extends” settings were found:
- Every package’s tsconfig.json →
"extends": "../../tsconfig.json"- tsconfig.scripts.json →
"extends": "../../tsconfig.base.json"No further changes needed.
packages/cli/package.json (1)
68-68: Version bumps look good and align with workspace toolchainThe dotenv/jiti/semver bumps and dev tool upgrades (Next/React/TS/@types) are consistent with the repo-wide updates and should be low risk for the CLI.
Also applies to: 74-74, 81-81, 101-101, 103-104, 109-109, 114-115, 117-117, 120-120
apps/docs/content/docs/fmdapi/CustomersLayout.ts (1)
24-24: Type export is clean and helpfulDeriving TCustomer from the schema is a nice DX touch.
apps/docs/package.json (2)
9-11: Good addition: Vitest scriptAdding "test": "vitest run" is aligned with the new tests in this PR.
29-36: Next.js 15.x is compatible with React 19.1.1npm’s peerDependencies show that next@^15.4.6 accepts react ^18.2.0 || ^19.0.0 and react-dom ^18.2.0 || ^19.0.0, and [email protected] requires react ^19.1.1. Your pinned versions of [email protected] and [email protected] satisfy all constraints—no compatibility issues detected.
apps/docs/content/docs/fmdapi/examples.mdx (1)
223-233: Unify script parameter shape across examplesElsewhere you use scriptParam; here it’s "script.param". For consistency and readability, prefer scriptParam if the client supports it.
Apply this diff if supported by the client:
// script param must always be a string - "script.param": JSON.stringify({ + scriptParam: JSON.stringify({ email: customerData.email, name: `${customerData.firstName} ${customerData.lastName}` })If DataApi strictly requires "script.param" for compound operations, consider adding a short note explaining why this example differs from executeScript.
apps/docs/server.ts (1)
2-2: Path to the registry app may fail under ESM builds; prefer alias or explicit extension.Depending on TS module target and runtime (CJS vs ESM), importing a TS file via a relative path without extension can break after compilation. Consider using a tsconfig alias or ensure extension resolution is handled.
Suggested change (if "@/..." alias resolves to src):
-import app from "./src/app/r/[[...name]]/registry"; +import app from "@/app/r/[[...name]]/registry";If you build with ESM and no bundler, you may also need to add a file extension in the emitted JS or configure TypeScript to preserve/append extensions. Please confirm your tsconfig and build pipeline handle this correctly.
apps/docs/src/registry/templates/mode-toggle/_meta.ts (1)
3-20: LGTM: metadata aligns with the schema and intent.
- Required fields present; categories/type/registryType consistent.
- Dependencies reflect component usage. No destinationPath needed for registry:component.
apps/docs/src/app/r/[[...name]]/registry.ts (1)
20-21: No directory traversal vulnerability detected – internal validation in getStaticComponent handles itThe
getStaticComponentfunction (apps/docs/src/registry/lib/utils.ts) already:
- Strips leading/trailing slashes from the incoming
namePath- Checks the normalized name against the list returned by
getTemplateDirs- Throws if the value (including any embedded slashes or
..) isn’t an exact matchThis effectively prevents directory-traversal or invalid paths. No additional critical fixes are required. If you’d like extra defense-in-depth, you can add a lightweight boundary check (e.g., disallowing
.or/in the param) before callinggetStaticComponent, but it’s not strictly necessary.apps/docs/src/app/r/[[...name]]/route.ts (1)
1-13: LGTM! Clean Vercel integration.The route handler correctly integrates the Hono app with Vercel's routing system, properly exporting all HTTP methods.
| "next": "^15.4.6", | ||
| "react": "^19.1.1", | ||
| "react-dom": "^19.1.1", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
💡 Verification agent
🧩 Analysis chain
Verify version compatibility between Next, React, and eslint-config-next.
You're on next 15.4.6 and react 19.1.1, while eslint-config-next is 15.3.3. This can cause lint rule mismatches.
Run this to list versions across workspaces and spot misalignments:
If mismatched, consider aligning eslint-config-next to the same minor as Next in each package.
Also applies to: 36-36
🏁 Script executed:
#!/bin/bash
set -euo pipefail
# List next/react/eslint-config-next versions in all package.json files
fd package.json | xargs -I{} sh -c 'echo "== {} =="; jq -r ".dependencies.next, .devDependencies[\"eslint-config-next\"], .dependencies.react" {} | sed "/null/d"'Length of output: 691
Align ESLint Config Version with Next Across Workspaces
We ran the version‐listing script and found misalignments:
- apps/demo/package.json
• next ^15.4.6
• eslint-config-next ^15.3.3 ← mismatched minor version
• react ^19.1.1 - apps/docs/package.json
• next ^15.4.6
• react ^19.1.1
• no eslint-config-next declared - packages/cli/template/nextjs/package.json (for reference)
• next ^15.2.3
• eslint-config-next 15.2.3 ← aligned here
• react 19.0.0
Action items:
- In apps/demo/package.json, bump eslint-config-next to ^15.4.6.
- In apps/docs/package.json, add eslint-config-next ^15.4.6 to devDependencies (or confirm it’s intentionally omitted).
- Review any other Next.js workspaces or templates and align eslint-config-next with the matching Next.js minor version.
🤖 Prompt for AI Agents
In apps/demo/package.json around lines 22-24 the eslint-config-next minor
version is mismatched with Next (next ^15.4.6 vs eslint-config-next ^15.3.3) —
update eslint-config-next to ^15.4.6 in devDependencies; in
apps/docs/package.json add eslint-config-next ^15.4.6 to devDependencies (unless
intentionally omitted) and run install to sync lockfile; finally scan other
Next.js workspaces/templates and align each eslint-config-next minor version to
match the corresponding next ^15.x.y used there, updating package.json entries
and reinstalling where needed.
| fieldData: z.object({ | ||
| firstName: z.string(), | ||
| lastName: z.string(), | ||
| email: z.string(), | ||
| phone: z.string(), | ||
| city: z.string(), | ||
| status: z.enum(["Active", "Inactive"]), | ||
| created_date: z.string().datetime(), | ||
| }), | ||
| }, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Strengthen schema validation and align with examples
- Email should be validated as an email.
- The docs later set an updated_date on updates; add it here (optional) to keep examples type-safe and consistent.
Apply this diff:
schema: {
fieldData: z.object({
firstName: z.string(),
lastName: z.string(),
- email: z.string(),
+ email: z.string().email(),
phone: z.string(),
city: z.string(),
status: z.enum(["Active", "Inactive"]),
created_date: z.string().datetime(),
+ updated_date: z.string().datetime().optional(),
}),
},📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| fieldData: z.object({ | |
| firstName: z.string(), | |
| lastName: z.string(), | |
| email: z.string(), | |
| phone: z.string(), | |
| city: z.string(), | |
| status: z.enum(["Active", "Inactive"]), | |
| created_date: z.string().datetime(), | |
| }), | |
| }, | |
| schema: { | |
| fieldData: z.object({ | |
| firstName: z.string(), | |
| lastName: z.string(), | |
| email: z.string().email(), | |
| phone: z.string(), | |
| city: z.string(), | |
| status: z.enum(["Active", "Inactive"]), | |
| created_date: z.string().datetime(), | |
| updated_date: z.string().datetime().optional(), | |
| }), | |
| }, |
🤖 Prompt for AI Agents
In apps/docs/content/docs/fmdapi/CustomersLayout.ts around lines 12 to 21,
strengthen the fieldData zod schema by changing email to use z.string().email()
for proper email validation and add an optional updated_date field as
z.string().datetime().optional() so examples that set updated_date are type-safe
and consistent with updates; keep created_date as-is.
| "typescript": "^5.9.2", | ||
| "vitest": "^3.2.3" | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
💡 Verification agent
🧩 Analysis chain
TypeScript 5.9.2 bump looks good; ensure workspace consistency
Dev-only change; LGTM. Please confirm all packages use the same TS version to avoid mixed tsc behavior in a monorepo.
Use this to audit TypeScript versions across the repo:
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "Per-package TypeScript versions:"
fd -H -t f -a package.json | while read -r f; do
ver=$(jq -r '(.devDependencies.typescript // .dependencies.typescript // empty)' "$f")
if [[ -n "${ver}" ]]; then
printf "%s\t%s\n" "$f" "$ver"
fi
done | sort
echo -e "\nUnique versions:"
fd -H -t f -a package.json | while read -r f; do
jq -r '(.devDependencies.typescript // .dependencies.typescript // empty)' "$f"
done | grep -v '^$' | sort | uniq -cLength of output: 5290
Inconsistent TypeScript versions detected—please bump templates from ^5 to ^5.9.2
Two package.json files in the CLI templates still reference "typescript": "^5", which can resolve to older 5.x releases. To ensure uniform tsc behavior across the monorepo, update them to the pinned version:
• packages/cli/template/nextjs/package.json
• packages/cli/template/vite-wv/package.json
Example change in each file:
- "devDependencies": {
- "typescript": "^5"
+ "devDependencies": {
+ "typescript": "^5.9.2"
}After updating, run npm install (or your preferred installer) in each template and verify CI passes.
Committable suggestion skipped: line range outside the PR's diff.
🤖 Prompt for AI Agents
In packages/better-auth/package.json around lines 69 to 71, the review calls out
inconsistent TypeScript versions in CLI template package.json files; update the
TypeScript dependency in packages/cli/template/nextjs/package.json and
packages/cli/template/vite-wv/package.json from "typescript": "^5" to
"typescript": "^5.9.2", save the files, run npm install (or your installer) in
each template to update lockfiles, and verify the repo/CI builds pass.
| "chalk": "5.4.1", | ||
| "commander": "^14.0.0", | ||
| "dotenv": "^16.4.7", | ||
| "dotenv": "^16.5.0", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
💡 Verification agent
🧩 Analysis chain
Dependency bumps acknowledged; verify @types/node major vs engines
- dotenv -> ^16.5.0: OK.
- knip/typescript: OK.
- @types/node -> ^22.17.1: If your runtime target is Node >=18 (as engines specify), using Node 22 type definitions can expose types/APIs not available on Node 18. It’s often better to align @types/node major with the minimum supported runtime (e.g., ^18.x) unless you intentionally target newer APIs.
Run this to review engines and Node types across all packages:
If you need to align with Node 18 types, update devDependencies:
- "@types/node": "^22.17.1",
+ "@types/node": "^18.19.68",Also applies to: 65-65, 71-71, 75-75
🏁 Script executed:
#!/bin/bash
set -euo pipefail
printf "package.json\tengines.node\t@types/node\n"
fd -H -t f -a package.json | while read -r f; do
eng=$(jq -r '.engines.node // empty' "$f")
types=$(jq -r '(.devDependencies["\@types/node"] // .dependencies["\@types/node"] // empty)' "$f")
if [[ -n "$eng$types" ]]; then
printf "%s\t%s\t%s\n" "$f" "${eng:-N/A}" "${types:-N/A}"
fi
done | column -t -s$'\t'Length of output: 921
Let’s retry with a simpler script that avoids escaping issues and column:
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "Scanning for package.json files with engines.node or @types/node"
find . -type f -name package.json | while read -r f; do
eng=$(jq -r '.engines.node // empty' "$f")
types=$(jq -r '.dependencies["@types/node"] // .devDependencies["@types/node"] // empty' "$f")
if [[ -n "$eng" || -n "$types" ]]; then
printf "%-70s engines: %-10s @types/node: %s\n" "$f" "${eng:-N/A}" "${types:-N/A}"
fi
doneLength of output: 53292
Align @types/node with Node ≥18 in fmdapi
The engines field in packages/fmdapi/package.json is set to “>=18.0.0”, but the @types/node devDependency was bumped to ^22.17.1. That mismatch can introduce type definitions for Node 22 APIs which won’t exist at runtime on Node 18. To ensure type safety, align @types/node with your minimum supported Node version (e.g. the latest 18.x):
• packages/fmdapi/package.json (lines 57, 65, 71, 75):
- "@types/node": "^22.17.1",
+ "@types/node": "^18.19.0",Committable suggestion skipped: line range outside the PR's diff.
🤖 Prompt for AI Agents
In packages/fmdapi/package.json (around lines 57, 65, 71, 75) the @types/node
devDependency currently targets Node 22, which mismatches the engines field
(>=18.0.0); change the @types/node version to a Node 18.x range (e.g. ^18.x, use
the latest 18.x release), update the lockfile by running your package manager
install (npm/yarn/pnpm), and re-run TypeScript compile/tests to ensure types
align with runtime Node 18.
| { | ||
| "name": "fmodata", | ||
| "version": "0.0.0", | ||
| "private": true | ||
| } No newline at end of file |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
💡 Verification agent
🧩 Analysis chain
Placeholder package: consider aligning module type and naming
If this package will evolve, consider:
- Setting "type": "module" to match ESM across the workspace (if that’s the convention).
- Using a scoped name (e.g., "@proofkit/fmodata") before publish, to avoid name conflicts.
These are optional and can be deferred if this is just a local/private workspace package.
To see how other packages in the workspace set their module type, run:
Proposed minimal change:
{
"name": "fmodata",
"version": "0.0.0",
- "private": true
+ "private": true,
+ "type": "module"
}🏁 Script executed:
#!/bin/bash
# Inspect "type" across packages to keep consistency
fd -a package.json packages | xargs -I {} sh -c 'echo {}; jq -r ".name + \" type=\" + (.type // \"undefined\")" {}'Length of output: 847
Align packages/fmodata/package.json with workspace conventions
Most packages in packages/ declare "type": "module" and use the @proofkit/… scope. To keep consistency:
• File to update:
- packages/fmodata/package.json
• Proposed changes:
{
"name": "fmodata",
"version": "0.0.0",
- "private": true
+ "private": true,
+ "type": "module"
}• And, before publishing, consider renaming:
- "name": "fmodata"
+ "name": "@proofkit/fmodata"This will align ESM usage and avoid registry-name conflicts.
🤖 Prompt for AI Agents
In packages/fmodata/package.json around lines 1 to 5, the package is missing the
workspace conventions: add "type": "module" to enable ESM semantics and change
the package name to use the @proofkit scope (e.g. "@proofkit/fmodata") to align
with other packages and avoid registry-name conflicts; update any internal
references if present and keep "private": true for now or remove/adjust before
publishing as appropriate.
| "chalk": "5.4.1", | ||
| "commander": "^14.0.0", | ||
| "dotenv": "^16.4.7", | ||
| "dotenv": "^16.5.0", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
💡 Verification agent
🧩 Analysis chain
dotenv and TypeScript bumps look fine; check repo-wide alignment
Both are safe minor bumps. Please ensure versions are consistent across packages to prevent duplicate installs or toolchain mismatches.
Audit dotenv and TypeScript versions:
Also applies to: 73-75
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "dotenv versions:"
fd -H -t f -a package.json | while read -r f; do
ver=$(jq -r '(.dependencies.dotenv // .devDependencies.dotenv // empty)' "$f")
if [[ -n "${ver}" ]]; then printf "%s\t%s\n" "$f" "$ver"; fi
done | sort
echo -e "\nUnique dotenv versions:"
fd -H -t f -a package.json | while read -r f; do
jq -r '(.dependencies.dotenv // .devDependencies.dotenv // empty)' "$f"
done | grep -v '^$' | sort | uniq -c
echo -e "\nTypeScript versions:"
fd -H -t f -a package.json | while read -r f; do
ver=$(jq -r '(.devDependencies.typescript // .dependencies.typescript // empty)' "$f")
if [[ -n "${ver}" ]]; then printf "%s\t%s\n" "$f" "$ver"; fi
done | sort
echo -e "\nUnique TypeScript versions:"
fd -H -t f -a package.json | while read -r f; do
jq -r '(.devDependencies.typescript // .dependencies.typescript // empty)' "$f"
done | grep -v '^$' | sort | uniq -cLength of output: 9853
Align dotenv and TypeScript versions across all packages
Our audit shows most packages use dotenv ^16.5.0 and TypeScript ^5.9.2, but the CLI templates lag behind:
• packages/cli/template/vite-wv/package.json
– dotenv: ^16.4.7 → ^16.5.0
– typescript: ^5 → ^5.9.2
• packages/cli/template/nextjs/package.json
– typescript: ^5 → ^5.9.2
Please update these to match the rest of the monorepo and prevent duplicate installs or mismatched toolchains.
Suggested diffs:
--- a/packages/cli/template/vite-wv/package.json
+++ b/packages/cli/template/vite-wv/package.json
@@ dependencies
- "dotenv": "^16.4.7",
+ "dotenv": "^16.5.0",
@@ devDependencies
- "typescript": "^5"
+ "typescript": "^5.9.2"--- a/packages/cli/template/nextjs/package.json
+++ b/packages/cli/template/nextjs/package.json
@@ devDependencies
- "typescript": "^5"
+ "typescript": "^5.9.2"📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| "dotenv": "^16.5.0", | |
| --- a/packages/cli/template/vite-wv/package.json | |
| +++ b/packages/cli/template/vite-wv/package.json | |
| @@ dependencies | |
| - "dotenv": "^16.4.7", | |
| + "dotenv": "^16.5.0", | |
| @@ devDependencies | |
| - "typescript": "^5" | |
| + "typescript": "^5.9.2" |
| "dotenv": "^16.5.0", | |
| --- a/packages/cli/template/nextjs/package.json | |
| +++ b/packages/cli/template/nextjs/package.json | |
| @@ devDependencies | |
| - "typescript": "^5" | |
| + "typescript": "^5.9.2" |
🤖 Prompt for AI Agents
packages/typegen/package.json lines 58-58: ensure consistency across the
monorepo by updating the CLI template package.json files to match this package's
dependency versions—edit packages/cli/template/vite-wv/package.json to set
"dotenv": "^16.5.0" and "typescript": "^5.9.2" (replacing "^16.4.7" and "^5"),
and edit packages/cli/template/nextjs/package.json to set "typescript": "^5.9.2"
(replacing "^5"); run a quick yarn/npm install or dedupe to verify no duplicate
installs.
| "@tanstack/vite-config": "^0.2.0", | ||
| "@types/filemaker-webviewer": "^1.0.0", | ||
| "@types/node": "^22.15.32", | ||
| "@types/node": "^22.17.1", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
💡 Verification agent
🧩 Analysis chain
Dev toolchain bumped — verify local Node version supports Vite 6 and Node types 22
No issues spotted. Ensure contributors use Node >=18 (Vite 6) and ideally Node 20/22 to match @types/node 22 across the repo.
Run this to spot any package-level Node engine constraints and confirm consistency:
Also applies to: 43-43, 45-45
🏁 Script executed:
#!/bin/bash
fd -a package.json | xargs -I {} sh -c '
echo "---- {}"
jq -r ".name? // \"(no name)\""
jq -r ".engines.node? // \"(no engines.node)\""
'Length of output: 798
To capture each package’s engines.node field correctly, let’s rerun with the file path passed into jq:
🏁 Script executed:
#!/bin/bash
# Check each package.json for its "name" and "engines.node" setting
fd -a package.json | xargs -I {} sh -c '
echo "---- {}"
jq -r ".name? // \"(no name)\" // empty" {}
jq -r ".engines.node? // \"(no engines.node)\" // empty" {}
'Length of output: 1184
Inconsistent Node engine constraints across packages
Our scan of all package.json files shows varying (or missing) engines.node settings:
- root
package.json:>=18 - @proofkit/cli:
^20.0.0 || ^22.0.0 - create-proofkit:
>=20.12.0 - @proofkit/fmdapi:
>=18.0.0 - All other packages (including
@proofkit/webviewer) lack anengines.nodefield
To ensure everyone runs a Node version compatible with Vite 6 and @types/node@22, please:
- Either add a uniform
engines.nodefield (>=18or bump to>=20) to all package.json files - Or standardize on a higher minimum (e.g.
>=20) across the repo, then update root and downstream packages accordingly
This will guarantee contributors use Node ≥18 (required for Vite 6) and ideally Node 20/22 to match our type definitions.
🤖 Prompt for AI Agents
packages/webviewer/package.json around line 41: this package.json lacks an
engines.node field which creates inconsistency with other packages and may allow
Node versions incompatible with Vite 6 and @types/node@22; add an "engines": {
"node": ">=18" } (or choose ">=20" if you want to standardize on Node 20) entry
to this file, and then propagate the same engines.node constraint to all other
package.json files (including root and downstream packages) and update any
CI/node version settings so the repo enforces the chosen minimum Node version.
…rs in examples.mdx
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 1
♻️ Duplicate comments (1)
apps/docs/content/docs/fmdapi/examples.mdx (1)
16-16: Align import path with other examples and Twoslash extraFilesMake the intro snippet consistent with later examples and the configured extraFiles keys to ensure resolution works.
- import { CustomersLayout } from "./schema/client"; + import { CustomersLayout } from "./CustomersLayout";
🧹 Nitpick comments (6)
apps/docs/content/docs/fmdapi/examples.mdx (6)
36-36: Use property shorthand for brevity and consistencyShorthand matches the style used elsewhere.
- query: { city: city } + query: { city }
12-12: Grammar: “set up” (verb) instead of “setup”-For these examples, we'll assume you've already setup a client in another file and are importing it for use. +For these examples, we'll assume you've already set up a client in another file and are importing it for use.
115-116: Tighten phrasing“new records” is redundant here.
-Use `create` to add new records to your FileMaker database. +Use `create` to add records to your FileMaker database.
150-151: Fix typo and improve sentence flow-This record id *can* change during imports or data migrations, so you should never store it, but instead alwyas look it up via a find request when it's needed. +This record id *can* change during imports or data migrations, so you should never store it; instead, always look it up via a find request when it's needed.
214-215: Strengthen wordingReplace “thus giving you” with a crisper alternative.
-...knowing the script will be focused on this newly created record; thus giving you access to the calculated values such as a UUID primary key defined in your field definitions. +...knowing the script will be focused on this newly created record; thereby providing access to calculated values such as a UUID primary key defined in your field definitions.
217-221: Prefer a typed payload over any in script exampleImport the TCustomer type from CustomersLayout and type the payload as a partial of its fieldData.
-import { CustomersLayout } from "./CustomersLayout"; +import { CustomersLayout, TCustomer } from "./CustomersLayout"; // ---cut--- -// Run a script after creating a record -export async function createCustomerWithWelcomeEmail(customerData: any) { +// Run a script after creating a record +export async function createCustomerWithWelcomeEmail( + customerData: Partial<TCustomer["fieldData"]>, +) {
📜 Review details
Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (2)
apps/docs/content/docs/fmdapi/examples.mdx(1 hunks)apps/docs/source.config.ts(2 hunks)
🧰 Additional context used
🪛 LanguageTool
apps/docs/content/docs/fmdapi/examples.mdx
[style] ~115-~115: ‘new records’ might be wordy. Consider a shorter alternative.
Context: ...# Creating Records Use create to add new records to your FileMaker database. ```ts twos...
(EN_WORDINESS_PREMIUM_NEW_RECORDS)
[grammar] ~150-~150: Ensure spelling is correct
Context: ... you should never store it, but instead alwyas look it up via a find request when it's...
(QB_NEW_EN_ORTHOGRAPHY_ERROR_IDS_1)
[style] ~214-~214: Try using a synonym here to strengthen your writing.
Context: ...used on this newly created record; thus giving you access to the calculated values such as...
(GIVE_PROVIDE)
🔇 Additional comments (3)
apps/docs/content/docs/fmdapi/examples.mdx (2)
58-61: LGTM: OR query now correctly uses function parametersThis resolves the earlier hard-coded values concern and reflects the intended inputs.
161-172: Please verifyfindOnereturn signature andupdated_datesupportThe example in
apps/docs/content/docs/fmdapi/examples.mdxcurrently assumes:
findOnereturns an object wrapped indata, and- the schema/type includes an
updated_datefield.Before applying the refactor, ensure:
•
CustomersLayout.findOne({…})really returns{ recordId }(not{ data: { recordId } }).
• Your actualCustomersLayoutschema/type definitions include anupdated_dateproperty.Suggested diff (lines 161–172):
- const { data: { recordId } } = await CustomersLayout.findOne({ query: { myPrimaryKey } }); + const { recordId } = await CustomersLayout.findOne({ query: { 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; + // Always stamp the modification time + fieldData.updated_date = new Date().toISOString(); const response = await CustomersLayout.update({ fieldData, recordId }); return response.modId;apps/docs/source.config.ts (1)
44-52: LGTM: robust candidate reading and no unused variablesYou now continue to the next candidate on read errors and only break on successful read; the unused selectedPath is removed. This addresses earlier feedback cleanly.
| 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}); | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fix findOne destructuring in delete example
findOne returns the record directly; destructure recordId from the top level and use object shorthand in the query.
- const { data: { recordId } } = await CustomersLayout.findOne({ query: { myPrimaryKey: myPrimaryKey } });
+ const { recordId } = await CustomersLayout.findOne({ query: { myPrimaryKey } });📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| 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}); | |
| } | |
| export async function deleteCustomer(myPrimaryKey: string) { | |
| // Optional: Get customer info first for logging | |
| const { recordId } = await CustomersLayout.findOne({ query: { myPrimaryKey } }); | |
| await CustomersLayout.delete({ recordId }); | |
| } |
🤖 Prompt for AI Agents
In apps/docs/content/docs/fmdapi/examples.mdx around lines 178–183, fix the
deleteCustomer example so it destructures recordId from the top-level result of
findOne (since findOne returns the record directly) and use object shorthand for
the query parameter; specifically call await CustomersLayout.findOne({ query: {
myPrimaryKey } }), extract const { recordId } = <result>, then pass recordId
using object shorthand to CustomersLayout.delete({ recordId }).
…CustomersLayout schema definition

Summary by CodeRabbit