Skip to content

React 19 - React Router Module #3716

@odinr

Description

@odinr

Implementation Plan: Static Route Schema & Framework Injection

Related User Story: #3715
Objective: This high-level goal will be achieved through the delivery of work described in the tasks below.

Deliver a new public module @equinor/fusion-framework-react-router that provides:

  • A typed route DSL with metadata
  • Static manifest generation at build time
  • Framework injection into React Router v7 loaders
  • Zero runtime cost and full TypeScript support

High-Level Tasks

Phase 1: Package Foundation & Core DSL

  1. Create New Package - Initialize @equinor/fusion-framework-react-router package structure
  2. Define Core Types & DSL API - Implement RouteNode, ParamSchema, SearchSchema types and DSL functions (route, index, layout, prefix)
  3. Implement DSL to React Router Conversion - Build toReactRouter() function that converts RouteNode[] to RouteObject[]

Phase 2: Framework Injection & Router Component

  1. Extend React Router Types - Augment React Router's LoaderFunctionArgs to include context.framework
  2. Implement Router Component - Create <Router> component that injects framework instance into all loaders via React Router's context

Phase 3: Manifest Generation & CLI Integration

  1. Create Route Manifest Generator - Implement extractRouteMetadata() function to extract route metadata from RouteNode[]
  2. Integrate with App Manifest Generation - Update AppBuildManifest and createAppManifestFromPackage() to include optional routes field
  3. Integrate with Portal Manifest Generation - Update PortalManifestBuildSchema to include optional routes field
  4. Add Route Validation - Implement validation and error reporting for route schemas

Phase 4: Type Safety & Developer Experience

  1. Implement Type-Safe Route Utilities - Create generatePath() and useParams() wrappers with route path inference
  2. Integrate with App Config - Update defineAppConfig() to accept routes parameter

Phase 5: Documentation & Examples

  1. Create Documentation - Write comprehensive README and API documentation
  2. Create Cookbook Example - Build cookbook demonstrating DSL usage with framework injection

Phase 6: Testing & Quality Assurance

  1. Unit Tests - Test DSL functions, conversion, and validation
  2. Integration Tests - Test Router component, framework injection, and manifest generation

Phase 7: Publishing

  1. Publish Package - Version, create changeset, publish to npm

Public API (Conceptual Examples)

routes.ts

import { Router, route, index, createRoutes } from '@equinor/fusion-framework-react-router';
import { defineAppConfig } from '@equinor/fusion-framework-cli/app';

export const routes = createRoutes([
  index("./home.tsx", {
    description: "Application home page",
    search: {
      view: { description: "UI view mode", enum: ["grid", "list"] }
    }
  }),

  route("contracts/:contractId", "./contracts/view.tsx", {
    description: "View a single contract",
    params: {
      contractId: { description: "Unique contract identifier" }
    },
    search: {
      tab: { description: "Active tab", enum: ["details", "history", "files"] },
      filter: { description: "Filter by status", enum: ["active", "archived"] }
    }
  })
]);

contracts/view.tsx

import { useLoaderData, useParams, LoaderFn } from '@equinor/fusion-framework-react-router';

export const loader: LoaderFn = async ({ context }) => {
  const client = context.framework.http.createClient('contracts');
  const contract = await client.fetch('/contracts/123');
  return { contract };
}

export default function ContractView() {
  const { contract } = useLoaderData<typeof loader>();
  const { contractId } = useParams();

  return <div>{contract.title} (ID: {contractId})</div>;
}

app.config.ts

// app.config.ts
export default defineAppConfig(() => ({ routes }));

App.tsx

// App.tsx
<Router routes={routes} />

Estimated Timeline

  • Phase 1 (Foundation): 2-3 days
  • Phase 2 (Framework Injection): 1-2 days
  • Phase 3 (Manifest Generation): 2-3 days
  • Phase 4 (Type Safety): 1-2 days
  • Phase 5 (Documentation): 1-2 days
  • Phase 6 (Testing): 2-3 days
  • Phase 7 (Publishing): 1 day

Total: ~10-16 days


Notes

  • Route extraction is optional - apps without routes continue to work
  • Framework injection works for both DSL and legacy RouteObject[] routes
  • Manifest generation happens at build time (no runtime cost)
  • Type safety is critical for developer experience

Sub-issues

Metadata

Metadata

Assignees

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions