Skip to content

fix(api): resolve issue causing the props API to fail when deployed#223

Merged
dlabaj merged 5 commits intomainfrom
fix-props-api-when-deployed
Mar 17, 2026
Merged

fix(api): resolve issue causing the props API to fail when deployed#223
dlabaj merged 5 commits intomainfrom
fix-props-api-when-deployed

Conversation

@wise-king-sullyman
Copy link
Contributor

@wise-king-sullyman wise-king-sullyman commented Mar 10, 2026

Closes #214

Assisted by Claude Code

Summary by CodeRabbit

  • New Features

    • Added a build-time endpoint that serves aggregated props and enables runtime fetching of props.
  • Refactor

    • API routes now fetch props at runtime (via the request origin) instead of reading local files and validate required parameters, returning 400 if missing.
  • Bug Fixes

    • Clearer 500-level error messages on load failures; improved 404 messaging when props for a page are absent.
  • Tests

    • Tests updated to use the remote props source, covering empty props, removal flows, and non-Error failure scenarios.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Mar 10, 2026

Walkthrough

Switches props data loading from runtime filesystem reads to HTTP fetches: adds a prerendered /props.json endpoint, a fetchProps(url) utility, updates API routes and top-level props endpoint to call fetchProps, adjusts lookup keys to PascalCase, and updates tests to mock fetchProps and its error semantics. (38 words)

Changes

Cohort / File(s) Summary
API Props Routes
src/pages/api/[version]/[section]/[page]/props.ts, src/pages/api/[version]/[section]/names.ts
Removed getConfig/path/fs reads; use fetchProps(url) to load props via HTTP; GET handlers now accept url; error messages updated to reflect fetch failures; lookup keys use pascalCase(removeSubsection(page)).
Top-level Props Endpoint
src/pages/props.ts
Replaced filesystem/config-based props loading with fetchProps(url); reads components from url.searchParams, validates input, wraps fetch in try/catch, and returns JSON or 4xx/5xx errors.
Prerendered Props Asset
src/pages/props.json.ts
New prerendered route exporting prerender = true and GET that reads props.json at build time and serves it as application/json.
Props Fetch Utility
src/utils/propsData/fetch.ts
New fetchProps(url: URL) that requests /props.json from the request origin, validates response.ok, parses JSON, and throws descriptive errors on failure.
Tests
src/__tests__/pages/api/__tests__/[version]/[section]/[page]/props.test.ts, src/__tests__/pages/api/__tests__/[version]/[section]/names.test.ts
Replaced filesystem and getConfig mocks with mockFetchProps; updated fixtures and expectations for network and non-Error rejections; removed ENOENT/path-specific assertions and file I/O mocks; added cases for empty props and PascalCase lookups.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  participant Client as Client
  participant API as Props API Route
  participant FetchUtil as fetchProps(url)
  participant Asset as /props.json (Server Asset)

  rect rgba(200,200,255,0.5)
  Client->>API: GET /api/.../props (request includes origin URL)
  end

  rect rgba(200,255,200,0.5)
  API->>FetchUtil: call fetchProps(request.url)
  FetchUtil->>Asset: HTTP GET /props.json (origin)
  Asset-->>FetchUtil: 200 + JSON / error status
  end

  rect rgba(255,200,200,0.5)
  FetchUtil-->>API: parsed props JSON (or throws)
  API-->>Client: 200 JSON (or 4xx/5xx with error details)
  end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

Suggested labels

released

Suggested reviewers

  • kmcfaul
  • dlabaj
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 50.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the main change: fixing the props API to work when deployed by removing filesystem dependencies and implementing HTTP-based fetching.
Linked Issues check ✅ Passed The PR successfully addresses all coding requirements from issue #214: removes Node.js filesystem operations, implements HTTP-based fetchProps helper, updates both props endpoints, and maintains backward compatibility.
Out of Scope Changes check ✅ Passed All changes are directly related to the stated objective of fixing props API deployment. The new fetchProps utility, updated endpoints, new props.json.ts endpoint, and test updates all support the core goal.

✏️ 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
  • Post copyable unit tests in a comment
  • Commit unit tests in branch fix-props-api-when-deployed
📝 Coding Plan
  • Generate coding plan for human review comments

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

Tip

You can disable sequence diagrams in the walkthrough.

Disable the reviews.sequence_diagrams setting to disable sequence diagrams in the walkthrough.

@cloudflare-workers-and-pages
Copy link

cloudflare-workers-and-pages bot commented Mar 10, 2026

Deploying patternfly-doc-core with  Cloudflare Pages  Cloudflare Pages

Latest commit: 18005f1
Status: ✅  Deploy successful!
Preview URL: https://e36a4e11.patternfly-doc-core.pages.dev
Branch Preview URL: https://fix-props-api-when-deployed.patternfly-doc-core.pages.dev

View logs

Copy link
Contributor

@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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/pages/props.ts (1)

5-13: ⚠️ Potential issue | 🟠 Major

Validate components and normalize fetch failures on /props.

This handler now has the same runtime dependency on /props.json as the versioned API route, but it does not catch fetchProps() failures. A missing asset or failed subrequest will bubble into Astro’s default 500 response, and requests without components still do the fetch and return 200 with an empty body.

Proposed fix
 export async function GET({ request }: { request: Request }) {
   const url = new URL(request.url)
-  const props = await fetchProps(url)
-
   const components = url.searchParams.get('components')
-  const componentsArray = components?.split(',')
-  const propsData = componentsArray?.map((component) => props[component])
-
-  return new Response(JSON.stringify(propsData))
+  if (!components) {
+    return Response.json(
+      { error: 'components query parameter is required' },
+      { status: 400 },
+    )
+  }
+
+  try {
+    const props = await fetchProps(url)
+    const propsData = components
+      .split(',')
+      .map((component) => props[component.trim()])
+
+    return Response.json(propsData)
+  } catch (error) {
+    const details = error instanceof Error ? error.message : String(error)
+    return Response.json(
+      { error: 'Failed to load props data', details },
+      { status: 500 },
+    )
+  }
 }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/pages/props.ts` around lines 5 - 13, Validate the incoming components
query and guard the fetch: in GET, read url.searchParams.get('components') and
if it's missing or empty return an early Response with a non-2xx status (e.g.
400) and a JSON error body instead of calling fetchProps; only call fetchProps
when components is present. Wrap the await fetchProps(url) call in try/catch to
normalize subrequest failures—on error return a Response with a non-200 status
(e.g. 502) and a JSON error message. After a successful fetch, split components
into componentsArray and map to propsData using props[component] but ensure
missing keys produce null (not undefined) and always return a JSON array body.
Reference: GET, fetchProps, components, componentsArray, propsData.
🧹 Nitpick comments (1)
src/utils/propsData/fetch.ts (1)

8-16: Add direct coverage for this helper.

The route suites now mock fetchProps(), so the new URL construction and response.ok handling introduced here are untested. A small unit test around this helper would make the Cloudflare fix much harder to regress.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/utils/propsData/fetch.ts` around lines 8 - 16, Add a unit test for
fetchProps that exercises the new URL construction and response.ok handling:
call fetchProps(new URL('https://example.com/some/path')) and assert the helper
requested new URL('/props.json', url.origin) (i.e.
https://example.com/props.json) by mocking global fetch and verifying the
requested URL, verify that when the mocked response.ok is true it returns the
parsed JSON, and when response.ok is false the function (fetchProps) throws an
Error with the status and statusText; use the fetchProps symbol and inspect the
propsUrl request in the mocked fetch to ensure full coverage.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/pages/props.json.ts`:
- Around line 21-30: The catch in src/pages/props.json.ts currently returns a
static 500 Response (and tries to include details: error which stringifies to
{}), so change it to fail the build instead: in the catch block of the code that
reads props data (the try/catch surrounding the props file read), rethrow the
original error (or throw a new Error with the original error.message) instead of
returning new Response, so the build/prerender process aborts and you don't ship
a broken /props.json; do not attempt to JSON.stringify the Error object for the
response.

---

Outside diff comments:
In `@src/pages/props.ts`:
- Around line 5-13: Validate the incoming components query and guard the fetch:
in GET, read url.searchParams.get('components') and if it's missing or empty
return an early Response with a non-2xx status (e.g. 400) and a JSON error body
instead of calling fetchProps; only call fetchProps when components is present.
Wrap the await fetchProps(url) call in try/catch to normalize subrequest
failures—on error return a Response with a non-200 status (e.g. 502) and a JSON
error message. After a successful fetch, split components into componentsArray
and map to propsData using props[component] but ensure missing keys produce null
(not undefined) and always return a JSON array body. Reference: GET, fetchProps,
components, componentsArray, propsData.

---

Nitpick comments:
In `@src/utils/propsData/fetch.ts`:
- Around line 8-16: Add a unit test for fetchProps that exercises the new URL
construction and response.ok handling: call fetchProps(new
URL('https://example.com/some/path')) and assert the helper requested new
URL('/props.json', url.origin) (i.e. https://example.com/props.json) by mocking
global fetch and verifying the requested URL, verify that when the mocked
response.ok is true it returns the parsed JSON, and when response.ok is false
the function (fetchProps) throws an Error with the status and statusText; use
the fetchProps symbol and inspect the propsUrl request in the mocked fetch to
ensure full coverage.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 5f668236-e95b-4746-b155-849f781e1bdc

📥 Commits

Reviewing files that changed from the base of the PR and between 5af44e5 and cea0262.

📒 Files selected for processing (7)
  • src/__tests__/pages/api/__tests__/[version]/[section]/[page]/props.test.ts
  • src/__tests__/pages/api/__tests__/[version]/[section]/names.test.ts
  • src/pages/api/[version]/[section]/[page]/props.ts
  • src/pages/api/[version]/[section]/names.ts
  • src/pages/props.json.ts
  • src/pages/props.ts
  • src/utils/propsData/fetch.ts

Copy link
Contributor

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

🧹 Nitpick comments (1)
src/pages/props.ts (1)

19-23: Non-existent component names result in null values in the response.

When a requested component name doesn't exist in props, props[component.trim()] returns undefined, which serializes to null in JSON. The consumer receives an array potentially containing null entries with no indication of which components were not found.

If this is intentional behavior, consider documenting it. Otherwise, consider filtering out undefined values or returning structured data that indicates which components were found vs. missing.

♻️ Option: Filter undefined values
     const propsData = components
       .split(',')
       .map((component) => props[component.trim()])
+      .filter((data) => data !== undefined)
 
     return createJsonResponse(propsData)
♻️ Option: Return structured response with found/missing info
-    const propsData = components
-      .split(',')
-      .map((component) => props[component.trim()])
-
-    return createJsonResponse(propsData)
+    const componentList = components.split(',').map((c) => c.trim())
+    const propsData = componentList.reduce(
+      (acc, component) => {
+        const data = props[component]
+        if (data !== undefined) {
+          acc[component] = data
+        }
+        return acc
+      },
+      {} as Record<string, any>,
+    )
+
+    return createJsonResponse(propsData)
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/pages/props.ts` around lines 19 - 23, The current mapping in propsData
uses props[component.trim()] which yields undefined for missing component names
and becomes null in the JSON; update the logic in the components.split(...) ->
propsData creation so you return a structured result per requested name (e.g., {
name, found: boolean, value?: any }) instead of raw values, by iterating over
components, trimming each into a variable, looking up props[name], and pushing
an object that sets found = true and value = props[name] when present or found =
false when missing; then pass that structured array into createJsonResponse so
consumers can see which components were found vs missing (refer to symbols:
components, props, propsData, createJsonResponse).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@src/pages/props.ts`:
- Around line 19-23: The current mapping in propsData uses
props[component.trim()] which yields undefined for missing component names and
becomes null in the JSON; update the logic in the components.split(...) ->
propsData creation so you return a structured result per requested name (e.g., {
name, found: boolean, value?: any }) instead of raw values, by iterating over
components, trimming each into a variable, looking up props[name], and pushing
an object that sets found = true and value = props[name] when present or found =
false when missing; then pass that structured array into createJsonResponse so
consumers can see which components were found vs missing (refer to symbols:
components, props, propsData, createJsonResponse).

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 365626a2-6ec5-46f0-a19e-e48750f4921b

📥 Commits

Reviewing files that changed from the base of the PR and between cea0262 and d1589af.

📒 Files selected for processing (2)
  • src/pages/props.json.ts
  • src/pages/props.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/pages/props.json.ts

Copy link
Collaborator

@kmcfaul kmcfaul left a comment

Choose a reason for hiding this comment

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

Routes work on the preview! 🎉 (though with one caveat due to a pre-existing bug in the comment below)

I also noticed that there might be an issue with missing entries in the props data (DataList is missing, but its subcomponents are there). I've looked in the full props.json that gets created locally and it's missing there too so this is probably a separate problem with how we're doing the fetching.

const props = JSON.parse(propsDataFile.toString())

const props = await fetchProps(url)
const propsData = props[sentenceCase(removeSubsection(page))]
Copy link
Collaborator

@kmcfaul kmcfaul Mar 12, 2026

Choose a reason for hiding this comment

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

sentenceCase needs to be removed here.

I'm not remembering my thought process as to why I included it initially (maybe I thought to manually format the props.json), but this is causing lookups on subcomponents or really anything with multiple words in camel/pascal case or hyphens to fail because it's inserting spaces.

This will mean that the route is case sensitive unless we add some more logic to make the data format consistent, such as formatting the props data to use lowercase without any spaces/hyphens and manipulating the url param into that format. But I think at least for now we can just remove it.

Copy link
Contributor

@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)
src/pages/api/[version]/[section]/[page]/props.ts (1)

34-34: Consider not returning raw error details in production responses.

Line 34 includes details in the JSON body. Prefer logging details server-side and returning only a stable public error shape to reduce internal info leakage.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/pages/api/`[version]/[section]/[page]/props.ts at line 34, The response
currently returns internal `details` in the JSON body (the object with { error:
'Failed to load props data', details }), which can leak internal info; instead,
log the `details` server-side (e.g., via processLogger.error or console.error
inside the handler in props.ts) and return a stable public error shape without
`details` (e.g., { error: 'Failed to load props data' } or include a safe
errorCode), updating the code paths that construct that response and any call
sites referencing `details`.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/pages/api/`[version]/[section]/[page]/props.ts:
- Line 20: The lookup uses props[removeSubsection(page)] which fails when the
route slug is kebab-case; convert the slug to PascalCase before accessing props
so keys like AboutModal/Alert match. Update the propsData assignment to call a
PascalCase normalizer around removeSubsection(page) (e.g.
props[toPascalCase(removeSubsection(page))]), and add a small helper function
toPascalCase/toPascalCaseIfNeeded if one doesn't exist; ensure the helper
handles hyphens/underscores and capitalizes each segment.

---

Nitpick comments:
In `@src/pages/api/`[version]/[section]/[page]/props.ts:
- Line 34: The response currently returns internal `details` in the JSON body
(the object with { error: 'Failed to load props data', details }), which can
leak internal info; instead, log the `details` server-side (e.g., via
processLogger.error or console.error inside the handler in props.ts) and return
a stable public error shape without `details` (e.g., { error: 'Failed to load
props data' } or include a safe errorCode), updating the code paths that
construct that response and any call sites referencing `details`.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: a7a8acee-a385-4b4d-ab67-bc29b9a4ab91

📥 Commits

Reviewing files that changed from the base of the PR and between d1589af and e346cf3.

📒 Files selected for processing (1)
  • src/pages/api/[version]/[section]/[page]/props.ts

Copy link
Contributor

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

🧹 Nitpick comments (1)
src/__tests__/pages/api/__tests__/[version]/[section]/[page]/props.test.ts (1)

12-14: Stale comment references removed utility.

The comment mentions "sentenceCase" which is no longer used in the implementation. Update the comment to reflect the current utilities being mocked.

📝 Suggested comment update
 /**
- * Mock sentenceCase and removeSubsection utilities
+ * Mock removeSubsection utility
  */
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/__tests__/pages/api/__tests__/`[version]/[section]/[page]/props.test.ts
around lines 12 - 14, Update the stale comment that references "sentenceCase" to
accurately describe the current mocks; remove "sentenceCase" from the block
comment and change it to something like "Mock removeSubsection utility" (or list
the actual utility names currently being mocked alongside removeSubsection) so
the comment matches the implementation.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@src/__tests__/pages/api/__tests__/`[version]/[section]/[page]/props.test.ts:
- Around line 12-14: Update the stale comment that references "sentenceCase" to
accurately describe the current mocks; remove "sentenceCase" from the block
comment and change it to something like "Mock removeSubsection utility" (or list
the actual utility names currently being mocked alongside removeSubsection) so
the comment matches the implementation.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 620bd6b9-5f77-4761-9a11-32ee5a5d3171

📥 Commits

Reviewing files that changed from the base of the PR and between e346cf3 and 18005f1.

📒 Files selected for processing (2)
  • src/__tests__/pages/api/__tests__/[version]/[section]/[page]/props.test.ts
  • src/pages/api/[version]/[section]/[page]/props.ts

Copy link
Contributor

@dlabaj dlabaj left a comment

Choose a reason for hiding this comment

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

lgtm

@dlabaj dlabaj merged commit 57b7b38 into main Mar 17, 2026
5 checks passed
@github-actions
Copy link

🎉 This PR is included in version 1.21.1 🎉

The release is available on:

Your semantic-release bot 📦🚀

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Props API doesn't work on deployed sites

3 participants