Skip to content

feat: export MeshCore packet monitor log as JSONL (#3391)#3394

Merged
Yeraze merged 1 commit into
mainfrom
feat/3391-meshcore-packet-export
Jun 9, 2026
Merged

feat: export MeshCore packet monitor log as JSONL (#3391)#3394
Yeraze merged 1 commit into
mainfrom
feat/3391-meshcore-packet-export

Conversation

@Yeraze

@Yeraze Yeraze commented Jun 9, 2026

Copy link
Copy Markdown
Owner

Summary

Closes #3391 — adds a JSON(L) export to the MeshCore Packet Monitor, mirroring the existing Meshtastic packet-monitor export.

Changes

  • src/server/routes/meshcoreRoutes.ts — new GET /api/sources/:id/meshcore/packets/export route. Streams the source's OTA packet log as JSONL (one JSON object per line, newest first), honoring the same payload_type / route_type / since filters as the list endpoint. Uses the same optionalAuth + packetmonitor:read permission, and returns a timestamped attachment filename (meshcore-packet-monitor-<ts>.jsonl, or …-filtered-<ts>.jsonl when filters are active).
  • src/components/MeshCore/MeshCorePacketMonitorView.tsx — a Download button in the monitor toolbar (next to Refresh/Clear) with a handleExport blob-download handler that carries the currently-active payload/route filters. Reuses the existing common.export i18n key.
  • src/server/routes/meshcoreRoutes.test.ts — mocks meshcorePacketLogService and adds coverage for: JSONL body + attachment headers, filter pass-through + -filtered- filename, and the per-source 404 guard.

Behavior

Matches the Meshtastic export exactly — same JSONL format, same streaming approach, same filter-aware filename — so the two packet monitors behave identically.

Testing

  • npx tsc --noEmit — clean
  • vitest run src/server/routes/meshcoreRoutes.test.ts — 140/140 pass (incl. 3 new export tests)

🤖 Generated with Claude Code

Add a JSON(L) export to the MeshCore Packet Monitor, mirroring the
Meshtastic packet-monitor export.

- meshcoreRoutes.ts: new GET /api/sources/:id/meshcore/packets/export route
  streaming the OTA packet log as one JSON object per line (newest first),
  honoring the same payload_type / route_type / since filters as the list
  endpoint. Same optionalAuth + packetmonitor:read permission, timestamped
  attachment filename (…-filtered-… when filters are active).
- MeshCorePacketMonitorView.tsx: Download toolbar button + handleExport blob
  download, carrying the active payload/route filters.
- meshcoreRoutes.test.ts: mock meshcorePacketLogService; cover JSONL output +
  headers, filter pass-through/filename, and the per-source 404 guard.

Closes #3391

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@github-actions

github-actions Bot commented Jun 9, 2026

Copy link
Copy Markdown

Claude finished @Yeraze's task —— View job


PR Review: MeshCore Packet Export

Review Tasks

  • Read repository guidelines (CLAUDE.md)
  • Review route implementation (meshcoreRoutes.ts)
  • Review UI component changes (MeshCorePacketMonitorView.tsx)
  • Review test coverage (meshcoreRoutes.test.ts)
  • Analyze code quality and best practices
  • Check for security concerns
  • Evaluate performance considerations
  • Provide comprehensive feedback

Overall Assessment ✅

This is a well-implemented feature that successfully mirrors the existing Meshtastic packet export functionality for MeshCore. The implementation follows repository conventions and maintains consistency with the existing codebase.

Code Quality & Best Practices ✅

Strengths:

  • Consistent with existing patterns: The implementation exactly mirrors the Meshtastic packetRoutes.ts export pattern
  • Proper TypeScript usage: Type safety maintained throughout
  • Repository compliance: Follows CLAUDE.md guidelines (per-source scoping, async patterns, permission checks)
  • Code reuse: Leverages existing meshcorePacketLogService infrastructure
  • Error handling: Comprehensive try-catch blocks with proper error responses

Minor observations:

  • Logic duplication between Meshtastic and MeshCore exports is expected and appropriate for feature parity
  • Timestamp formatting logic (replace(/[:.]/g, '-').substring(0, 19)) is consistent across both implementations

Security Analysis ✅

Authentication & Authorization:

  • optionalAuth() middleware correctly applied
  • requirePermission('packetmonitor', 'read') with proper source scoping
  • ✅ Source ID extraction and validation (req.params.id!)
  • ✅ Input sanitization via parseInt() with Number.isFinite() checks

Input Validation:

// Line 3015-3019: Proper parameter validation
const payloadType = req.query.payload_type !== undefined ? parseInt(req.query.payload_type as string, 10) : undefined;
const routeType = req.query.route_type !== undefined ? parseInt(req.query.route_type as string, 10) : undefined;
let since = req.query.since !== undefined ? parseInt(req.query.since as string, 10) : undefined;
if (since !== undefined && since < 1e12) since = since * 1000; // Seconds to milliseconds conversion
  • ✅ No SQL injection risk (uses Drizzle ORM)
  • ✅ No XSS risk (server-side endpoint, JSON response)

Performance Considerations ✅

Efficient Implementation:

  • ✅ Uses existing service layer (meshcorePacketLogService.getMaxCount())
  • ✅ Respects retention limits (maxCount from configuration)
  • ✅ Streaming response pattern (res.write() + res.end())
  • ✅ No unnecessary buffering in memory

Potential concerns:

  • Large exports could impact server memory, but this mirrors existing Meshtastic behavior
  • No explicit rate limiting, but packet monitor permission requirement provides access control

Test Coverage ✅

Comprehensive test suite (meshcoreRoutes.test.ts:1771-1816):

  • Happy path: JSONL format, attachment headers, correct service calls
  • Filter handling: Parameter pass-through and -filtered- filename logic
  • Error cases: 404 for non-existent sources
  • Mocking: Proper async service mocking with mockResolvedValue

The tests cover all critical functionality and edge cases.

UI Implementation ✅

Frontend changes (MeshCorePacketMonitorView.tsx:174-202):

  • Consistent UX: Download button placement matches existing controls
  • Filter integration: Honors active payloadFilter and routeFilter states
  • Filename handling: Extracts server-provided timestamped filename from Content-Disposition
  • Error handling: Proper error state management
  • Blob download: Standard browser download pattern with cleanup

Specific Technical Comments

  1. Route Implementation (meshcoreRoutes.ts:3001-3052):

    • Excellent parameter validation and type safety
    • Proper source isolation via sourceId scoping
    • Consistent error handling and logging patterns
  2. Time Handling (line 3018-3019):

    // Accept seconds or milliseconds (mirror the list endpoint).
    if (since !== undefined && since < 1e12) since = since * 1000;

    Smart backward compatibility for timestamp formats.

  3. Filename Generation (lines 3032-3037):

    const hasActiveFilters = req.query.payload_type !== undefined ||
                             req.query.route_type !== undefined ||
                             req.query.since !== undefined;
    const filterInfo = hasActiveFilters ? '-filtered' : '';

    Clear filter detection logic with descriptive naming.

Minor Suggestions

  1. Consider adding JSDoc to the export route for consistency with other documented endpoints in the file
  2. Query parameter documentation could be enhanced in the route comment block

Conclusion

This PR successfully implements JSONL export for MeshCore packets with:

  • Security: Proper authentication, authorization, and input validation
  • Performance: Efficient streaming implementation
  • Quality: Follows existing patterns and repository conventions
  • Testing: Comprehensive coverage of functionality and edge cases
  • UX: Seamless integration with existing packet monitor interface

Recommendation: APPROVE 🎉

The implementation is production-ready and maintains the high quality standards of the codebase.

@Yeraze Yeraze merged commit f845431 into main Jun 9, 2026
19 checks passed
@Yeraze Yeraze deleted the feat/3391-meshcore-packet-export branch June 9, 2026 20:32
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.

[FEAT] Export from Meshcore Packet Monitor

1 participant