Skip to content

fm bridge vite plugin#150

Merged
eluce2 merged 4 commits intomainfrom
codex/fm-bridge-vite-plugin
Mar 17, 2026
Merged

fm bridge vite plugin#150
eluce2 merged 4 commits intomainfrom
codex/fm-bridge-vite-plugin

Conversation

@eluce2
Copy link
Collaborator

@eluce2 eluce2 commented Mar 17, 2026

Summary by CodeRabbit

  • New Features

    • Added a local WebViewer bridge plugin that auto-discovers connected files and configures WebSocket URLs for development.
  • Tests

    • Introduced a comprehensive test suite and test configuration; added a test runner script.
  • Documentation

    • Clarified prerequisites for local WebViewer development (Path D) and common local setup steps.
  • Chores

    • Updated build inputs and package exports to expose the new plugin and related tooling.

@eluce2 eluce2 changed the base branch from main to graphite-base/150 March 17, 2026 13:06
@eluce2 eluce2 force-pushed the graphite-base/150 branch from 17b40aa to ee3c1f2 Compare March 17, 2026 13:06
@eluce2 eluce2 changed the base branch from graphite-base/150 to feat/fm-http-typegen March 17, 2026 13:06
Copy link
Collaborator Author

eluce2 commented Mar 17, 2026

This stack of pull requests is managed by Graphite. Learn more about stacking.

@coderabbitai
Copy link

coderabbitai bot commented Mar 17, 2026

📝 Walkthrough

Walkthrough

Adds a FileMaker WebViewer Vite plugin with HTTP-based connectedFiles discovery, WebSocket URL resolution, and mock-script injection; exposes the plugin via package exports, adds tests and Vitest config, updates Vite build input, and clarifies a documentation prerequisite for Path D.

Changes

Cohort / File(s) Summary
FileMaker Bridge Plugin
packages/webviewer/src/fm-bridge.ts, packages/webviewer/src/vite-plugins.ts
New Vite plugin implementing FM HTTP connectedFiles discovery, wsUrl resolution, mock script-tag construction, and HTML injection; small façade re-exports public types and plugin alias.
Build & Test Configuration
packages/webviewer/package.json, packages/webviewer/vite.config.ts, packages/webviewer/vitest.config.ts
Added export entry ./vite-plugins, added vitest devDependency and test script, included ./src/vite-plugins.ts in Vite input, and added Vitest config excluding node_modules/dist.
Plugin Test Suite
packages/webviewer/tests/vite-plugins.test.ts
New comprehensive tests for resolveWsUrl, buildMockScriptTag, discoverConnectedFileName (HTTP/payload/error paths), and fmBridge plugin behavior in serve vs build modes.
Documentation
packages/typegen/skills/getting-started/SKILL.md
Path D prerequisite changed to require the FileMaker file be reachable via the FM HTTP connectedFiles endpoint; notes common setup is opening file locally and running a bridging script that establishes the bridge.

Sequence Diagram

sequenceDiagram
    participant Dev as rgba(66,133,244,0.5) Dev Server
    participant Plugin as rgba(15,157,88,0.5) fm-bridge Plugin
    participant FmHttp as rgba(219,68,55,0.5) FM HTTP Server
    participant Html as rgba(244,180,0,0.5) HTML Transformer

    Dev->>Plugin: start in serve mode
    Plugin->>Plugin: check options.fileName
    alt fileName not provided
        Plugin->>FmHttp: GET /connectedFiles
        FmHttp-->>Plugin: connectedFiles array
        Plugin->>Plugin: validate & pick first fileName
    end
    Plugin->>Plugin: resolveWsUrl(fmHttpBaseUrl, wsUrl)
    Plugin->>Plugin: buildMockScriptTag(baseUrl,fileName,wsUrl,debug)
    Plugin->>Html: transformIndexHtml -> inject script tag
    Html-->>Dev: return HTML with fm-mock script injected
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

  • wv import paths #47: Modifies packages/webviewer/vite.config.ts build input entries; closely related to the Vite input changes in this PR.
🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'fm bridge vite plugin' clearly summarizes the main change: adding a Vite plugin for FileMaker bridge functionality, which aligns with the core changes (new fm-bridge.ts module, vite-plugins.ts facade, and related build/test infrastructure).
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch codex/fm-bridge-vite-plugin
📝 Coding Plan
  • Generate coding plan for human review comments

Comment @coderabbitai help to get the list of available commands and usage tips.

@eluce2 eluce2 requested a review from toddgeist March 17, 2026 13:59
@eluce2 eluce2 force-pushed the feat/fm-http-typegen branch from ee3c1f2 to 675c83e Compare March 17, 2026 14:50
@eluce2 eluce2 force-pushed the codex/fm-bridge-vite-plugin branch from b344ed7 to 2b33374 Compare March 17, 2026 14:50
@vercel
Copy link

vercel bot commented Mar 17, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
proofkit-docs Ready Ready Preview Mar 17, 2026 3:06pm

Request Review

Copy link

@coderabbitai coderabbitai bot left a 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

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@packages/webviewer/src/fm-bridge.ts`:
- Around line 46-53: discoverConnectedFileName currently awaits
fetch(connectedFilesUrl) without a timeout which can block transformIndexHtml;
wrap the fetch in an AbortController with a short timeout (e.g., 3–10s), pass
controller.signal to fetch(connectedFilesUrl), clear the timer on success, and
handle the abort case by throwing the existing error message (preserving the
original error as cause) so stalled requests fail fast when fm-http is
unresponsive; update the try/catch around fetch in discoverConnectedFileName
accordingly and ensure any AbortError is propagated with the same user-facing
message.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: cdb4a5ec-b3c6-4540-bc51-11e1a798ba7d

📥 Commits

Reviewing files that changed from the base of the PR and between 675c83e and 2b33374.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (7)
  • packages/typegen/skills/getting-started/SKILL.md
  • packages/webviewer/package.json
  • packages/webviewer/src/fm-bridge.ts
  • packages/webviewer/src/vite-plugins.ts
  • packages/webviewer/tests/vite-plugins.test.ts
  • packages/webviewer/vite.config.ts
  • packages/webviewer/vitest.config.ts

Copy link
Collaborator Author

eluce2 commented Mar 17, 2026

Merge activity

  • Mar 17, 3:04 PM UTC: A user started a stack merge that includes this pull request via Graphite.
  • Mar 17, 3:06 PM UTC: Graphite rebased this pull request as part of a merge.
  • Mar 17, 3:06 PM UTC: @eluce2 merged this pull request with Graphite.

@eluce2 eluce2 changed the base branch from feat/fm-http-typegen to graphite-base/150 March 17, 2026 15:04
@eluce2 eluce2 changed the base branch from graphite-base/150 to main March 17, 2026 15:04
@eluce2 eluce2 force-pushed the codex/fm-bridge-vite-plugin branch from 83e2fee to 7eafe6b Compare March 17, 2026 15:05
Copy link

@coderabbitai coderabbitai bot left a 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

🧹 Nitpick comments (1)
packages/webviewer/src/fm-bridge.ts (1)

125-143: Avoid duplicate connectedFiles lookups by caching the in-flight discovery.

configureServer and transformIndexHtml can both trigger discovery when resolvedFileName is unset. Caching one in-flight promise avoids duplicate network calls and racey retries.

Refactor sketch
 export const fmBridge = (options: FmBridgeOptions = {}): Plugin => {
   const baseUrl = trimToNull(options.fmHttpBaseUrl) ?? defaultFmHttpBaseUrl;
   const wsUrl = resolveWsUrl(options);
   const debug = options.debug === true;
   let resolvedFileName: string | null = trimToNull(options.fileName);
   let isServeMode = true;
+  let discoveryPromise: Promise<string> | null = null;
+
+  const ensureResolvedFileName = async (): Promise<string> => {
+    if (resolvedFileName) return resolvedFileName;
+    discoveryPromise ??= discoverConnectedFileName(baseUrl)
+      .then((fileName: string) => {
+        resolvedFileName = fileName;
+        return fileName;
+      })
+      .finally(() => {
+        discoveryPromise = null;
+      });
+    return discoveryPromise;
+  };

   return {
@@
     async configureServer() {
       if (!isServeMode) {
         return;
       }

       if (resolvedFileName) {
         return;
       }

-      resolvedFileName = await discoverConnectedFileName(baseUrl);
+      await ensureResolvedFileName();
     },
     async transformIndexHtml() {
       if (!isServeMode) {
         return;
       }

       if (!resolvedFileName) {
-        resolvedFileName = await discoverConnectedFileName(baseUrl);
+        await ensureResolvedFileName();
       }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/webviewer/src/fm-bridge.ts` around lines 125 - 143, Both
configureServer and transformIndexHtml can call
discoverConnectedFileName(baseUrl) concurrently when resolvedFileName is unset;
introduce a shared in-flight promise (e.g., resolvedFileNamePromise) that is
assigned before awaiting discoverConnectedFileName so both functions await the
same promise, then set resolvedFileName from its result and clear the promise on
error or success. Update configureServer and transformIndexHtml to check
resolvedFileName first, then check/assign resolvedFileNamePromise before
awaiting discoverConnectedFileName(baseUrl), and ensure error handling clears
the promise so future attempts can retry.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@packages/webviewer/src/fm-bridge.ts`:
- Around line 71-74: The call to response.json() inside fmBridge can throw a
generic parse error and lose context when /connectedFiles returns non-JSON; wrap
the JSON parsing in a try-catch around the await response.json() (referencing
connectedFilesUrl, response, and payload) and on parse failure throw a new Error
that includes fmBridge context, the connectedFilesUrl, and the original error
message (optionally include the raw response body via response.text() to aid
debugging) before continuing with the existing Array.isArray(payload) check.

---

Nitpick comments:
In `@packages/webviewer/src/fm-bridge.ts`:
- Around line 125-143: Both configureServer and transformIndexHtml can call
discoverConnectedFileName(baseUrl) concurrently when resolvedFileName is unset;
introduce a shared in-flight promise (e.g., resolvedFileNamePromise) that is
assigned before awaiting discoverConnectedFileName so both functions await the
same promise, then set resolvedFileName from its result and clear the promise on
error or success. Update configureServer and transformIndexHtml to check
resolvedFileName first, then check/assign resolvedFileNamePromise before
awaiting discoverConnectedFileName(baseUrl), and ensure error handling clears
the promise so future attempts can retry.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 28e39cc4-ddd9-41f2-8c25-b088445cd4d2

📥 Commits

Reviewing files that changed from the base of the PR and between 2b33374 and 83e2fee.

📒 Files selected for processing (2)
  • packages/webviewer/src/fm-bridge.ts
  • packages/webviewer/tests/vite-plugins.test.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • packages/webviewer/tests/vite-plugins.test.ts

Comment on lines +71 to +74
const payload = (await response.json()) as unknown;
if (!Array.isArray(payload)) {
throw new Error(`fmBridge expected an array response from ${connectedFilesUrl}.`);
}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Handle invalid JSON payloads with a descriptive error.

If /connectedFiles returns non-JSON, response.json() throws a generic parse error and loses fmBridge context.

Proposed fix
-  const payload = (await response.json()) as unknown;
+  let payload: unknown;
+  try {
+    payload = await response.json();
+  } catch (error) {
+    throw new Error(
+      `fmBridge received invalid JSON from ${connectedFilesUrl}. Ensure fm-http returned a JSON array.`,
+      { cause: error },
+    );
+  }

As per coding guidelines, "Handle errors appropriately in async code with try-catch blocks".

📝 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.

Suggested change
const payload = (await response.json()) as unknown;
if (!Array.isArray(payload)) {
throw new Error(`fmBridge expected an array response from ${connectedFilesUrl}.`);
}
let payload: unknown;
try {
payload = await response.json();
} catch (error) {
throw new Error(
`fmBridge received invalid JSON from ${connectedFilesUrl}. Ensure fm-http returned a JSON array.`,
{ cause: error },
);
}
if (!Array.isArray(payload)) {
throw new Error(`fmBridge expected an array response from ${connectedFilesUrl}.`);
}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/webviewer/src/fm-bridge.ts` around lines 71 - 74, The call to
response.json() inside fmBridge can throw a generic parse error and lose context
when /connectedFiles returns non-JSON; wrap the JSON parsing in a try-catch
around the await response.json() (referencing connectedFilesUrl, response, and
payload) and on parse failure throw a new Error that includes fmBridge context,
the connectedFilesUrl, and the original error message (optionally include the
raw response body via response.text() to aid debugging) before continuing with
the existing Array.isArray(payload) check.

@eluce2 eluce2 merged commit 0b99080 into main Mar 17, 2026
11 of 13 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant