Add dynamic sitemap and plugin map endpoints#28
Conversation
|
Warning @023dominus-coder this pull request is linked to an issue that is already assigned to another user. Please link it to an open issue assigned to you or to an unassigned open issue. |
📝 WalkthroughWalkthroughThis PR introduces a standalone sitemap generator for apps and plugins. It adds type contracts for sitemap metadata (apps, plugins, entries), builder functions to generate sorted sitemap entries and JSON payloads from defaults, an XML renderer with escape handling, and helper converters for app/plugin-to-entry transformation. The worker router is extended with three deterministic endpoints— 🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Warning There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure. 🔧 ESLint
ESLint skipped: no ESLint configuration detected in root package.json. To enable, add 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. Comment |
There was a problem hiding this comment.
Actionable comments posted: 2
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 897890bd-0c5d-4af4-84c4-1827371ebec2
📒 Files selected for processing (3)
src/sitemap.tssrc/worker.tstests/sitemap.test.ts
| if (url.pathname === '/sitemap.xml') { | ||
| return withRouterRevision(new Response(renderSitemapXml(), { | ||
| headers: { | ||
| 'Content-Type': 'application/xml; charset=utf-8', | ||
| 'Cache-Control': 'public, max-age=300', | ||
| }, | ||
| })) | ||
| } | ||
|
|
||
| if (url.pathname === '/sitemap.json') { | ||
| return withRouterRevision(json(buildJsonSitemap())) | ||
| } | ||
|
|
||
| if (url.pathname === '/plugins.json') { | ||
| return withRouterRevision(json(buildJsonPluginMap())) | ||
| } |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Look for existing host/apex gating patterns and any app-level sitemap handling in the router.
rg -nP "url\.hostname|inHost\s*===|=== '?ubq\.fi" --type=ts
rg -nP "sitemap|plugins\.json" --type=ts -g '!tests/**'Repository: ubiquity/ubq.fi-router
Length of output: 665
🏁 Script executed:
#!/bin/bash
set -euo pipefail
# Show the relevant section of src/worker.ts around sitemap endpoints and any surrounding host gating.
sed -n '60,120p' src/worker.ts
# Find where 'pathname' routing branches are defined and whether hostname/inHost gating is applied for them.
rg -n "pathname === '/(sitemap\.xml|sitemap\.json|plugins\.json)'" src/worker.ts
rg -n "inHost\s*=" src/worker.ts
rg -n "workIncoming:|=== 'work\.ubq\.fi'" src/worker.ts
# Inspect the router helper to see whether it already scopes by hostname.
rg -n "function withRouterRevision|withRouterRevision" -S src
ls -la src | headRepository: ubiquity/ubq.fi-router
Length of output: 3792
🏁 Script executed:
#!/bin/bash
set -euo pipefail
rg -n "/sitemap\.xml|sitemap\.json|plugins\.json" -S src
rg -n "buildJsonSitemap|renderSitemapXml|buildJsonPluginMap" -S src/sitemap.ts src/worker.ts
rg -n "hostname|inHost|apex|ubq\.fi" -S src/sitemap.ts src/worker.tsRepository: ubiquity/ubq.fi-router
Length of output: 2243
Scope sitemap/plugin JSON routes by hostname (avoid shadowing proxied apps)
In src/worker.ts, /sitemap.xml, /sitemap.json, and /plugins.json are matched on url.pathname only, and run before any url.hostname/plugin routing logic—so these endpoints are served for all incoming hosts. If a proxied app serves its own sitemap at these paths, this router will shadow it; gate these routes to intended apex/allowed hostnames (e.g., ubq.fi / www.ubq.fi).
| test('serves sitemap and plugin map endpoints before proxy routing', async () => { | ||
| const xml = await worker.fetch(new Request('https://ubq.fi/sitemap.xml'), {} as Env) | ||
| const json = await worker.fetch(new Request('https://ubq.fi/sitemap.json'), {} as Env) | ||
| const plugins = await worker.fetch(new Request('https://ubq.fi/plugins.json'), {} as Env) | ||
|
|
||
| expect(xml.headers.get('content-type')).toContain('application/xml') | ||
| expect(await xml.text()).toContain('<urlset') | ||
| expect((await json.json()).total).toBeGreaterThan(0) | ||
| expect((await plugins.json()).totalPlugins).toBeGreaterThan(0) | ||
| }) |
There was a problem hiding this comment.
Fix the failing tsc build: .json() resolves to unknown.
CI is red at Lines 45-46 (TS2571). Response.json() returns unknown, so property access fails type-checking. Cast the parsed payloads.
🐛 Proposed fix
- expect((await json.json()).total).toBeGreaterThan(0)
- expect((await plugins.json()).totalPlugins).toBeGreaterThan(0)
+ expect(((await json.json()) as { total: number }).total).toBeGreaterThan(0)
+ expect(((await plugins.json()) as { totalPlugins: number }).totalPlugins).toBeGreaterThan(0)📝 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.
| test('serves sitemap and plugin map endpoints before proxy routing', async () => { | |
| const xml = await worker.fetch(new Request('https://ubq.fi/sitemap.xml'), {} as Env) | |
| const json = await worker.fetch(new Request('https://ubq.fi/sitemap.json'), {} as Env) | |
| const plugins = await worker.fetch(new Request('https://ubq.fi/plugins.json'), {} as Env) | |
| expect(xml.headers.get('content-type')).toContain('application/xml') | |
| expect(await xml.text()).toContain('<urlset') | |
| expect((await json.json()).total).toBeGreaterThan(0) | |
| expect((await plugins.json()).totalPlugins).toBeGreaterThan(0) | |
| }) | |
| test('serves sitemap and plugin map endpoints before proxy routing', async () => { | |
| const xml = await worker.fetch(new Request('https://ubq.fi/sitemap.xml'), {} as Env) | |
| const json = await worker.fetch(new Request('https://ubq.fi/sitemap.json'), {} as Env) | |
| const plugins = await worker.fetch(new Request('https://ubq.fi/plugins.json'), {} as Env) | |
| expect(xml.headers.get('content-type')).toContain('application/xml') | |
| expect(await xml.text()).toContain('<urlset') | |
| expect(((await json.json()) as { total: number }).total).toBeGreaterThan(0) | |
| expect(((await plugins.json()) as { totalPlugins: number }).totalPlugins).toBeGreaterThan(0) | |
| }) |
🧰 Tools
🪛 GitHub Actions: CI / 2_test.txt
[error] 45-45: TypeScript (tsc) error TS2571: Object is of type 'unknown'.
[error] 46-46: TypeScript (tsc) error TS2571: Object is of type 'unknown'.
🪛 GitHub Actions: CI / test
[error] 45-45: TypeScript (tsc): TS2571 Object is of type 'unknown'.
[error] 46-46: TypeScript (tsc): TS2571 Object is of type 'unknown'.
Closes #2
Summary
Adds deterministic sitemap and plugin map generation for UBQ.FI apps and plugins.
What changed
src/sitemap.tswith JSON sitemap, plugin map, and XML rendering helpers./sitemap.xml,/sitemap.json, and/plugins.json.Notes
The implementation is local-config driven and keeps the router's no-KV/no-discovery approach.
Validation
Could not run
bun testlocally becausebun,npm, andtscare not available on PATH in this environment.