JSPM

@flightdev/core

0.6.8
  • ESM via JSPM
  • ES Module Entrypoint
  • Export Map
  • Keywords
  • License
  • Repository URL
  • TypeScript Types
  • README
  • Created
  • Published
  • Downloads 3
  • Score
    100M100P100Q30775F
  • License MIT

Core primitives for Flight Framework - routing, rendering, caching

Package Exports

  • @flightdev/core
  • @flightdev/core/actions
  • @flightdev/core/actions/middleware
  • @flightdev/core/actions/queue
  • @flightdev/core/actions/streaming
  • @flightdev/core/adapters
  • @flightdev/core/cache
  • @flightdev/core/client
  • @flightdev/core/config
  • @flightdev/core/errors
  • @flightdev/core/file-router
  • @flightdev/core/file-router/streaming-hints
  • @flightdev/core/handlers
  • @flightdev/core/islands
  • @flightdev/core/middleware
  • @flightdev/core/plugins
  • @flightdev/core/plugins/critical-css
  • @flightdev/core/react
  • @flightdev/core/render
  • @flightdev/core/router
  • @flightdev/core/rsc
  • @flightdev/core/rsc/adapters
  • @flightdev/core/rsc/adapters/preact
  • @flightdev/core/rsc/adapters/react
  • @flightdev/core/rsc/adapters/solid
  • @flightdev/core/rsc/adapters/vue
  • @flightdev/core/rsc/boundaries
  • @flightdev/core/rsc/context
  • @flightdev/core/rsc/payload
  • @flightdev/core/rsc/plugins
  • @flightdev/core/rsc/plugins/esbuild
  • @flightdev/core/rsc/plugins/rollup
  • @flightdev/core/rsc/renderer
  • @flightdev/core/rsc/stream
  • @flightdev/core/rsc/vite-plugin
  • @flightdev/core/server
  • @flightdev/core/streaming
  • @flightdev/core/streaming/adapters
  • @flightdev/core/streaming/conditional
  • @flightdev/core/streaming/observability
  • @flightdev/core/streaming/priority
  • @flightdev/core/utils

Readme

@flightdev/core

Core primitives for Flight Framework, including configuration, routing, caching, streaming SSR, and server actions.

Features

  • Multi-render mode: SSR, SSG, ISR, and streaming
  • Framework support: React, Vue, Svelte, Solid, HTMX
  • File-based routing with automatic route discovery
  • Type-safe server actions with form support
  • Streaming SSR with priority control
  • Islands architecture for partial hydration
  • Pluggable cache adapters with deduplication
  • Structured error handling with type guards

Installation

npm install @flightdev/core

Quick Start

Configuration

// flight.config.ts
import { defineConfig } from '@flightdev/core';

export default defineConfig({
  server: {
    port: 3000,
  },
  render: {
    defaultMode: 'ssr',
    streaming: true,
  },
});

Create a Server

import { createServer } from '@flightdev/core';

const server = createServer({
  port: 3000,
  routes: [
    { path: '/', handler: homeHandler },
    { path: '/api/*', handler: apiHandler },
  ],
});

await server.start();

File-Based Routing

import { createFileRouter, scanRoutes } from '@flightdev/core';

const routes = await scanRoutes('./src/routes');
const router = createFileRouter({ routes });

// Routes are discovered automatically:
// src/routes/index.page.tsx -> /
// src/routes/about.page.tsx -> /about
// src/routes/blog/[slug].page.tsx -> /blog/:slug

Modules

Router

import { createRouter } from '@flightdev/core/router';

const router = createRouter();
router.add('GET', '/users/:id', userHandler);

const match = router.match('GET', '/users/123');
// { params: { id: '123' }, handler: userHandler }

Cache

import { createCache, memory, cached, dedupe } from '@flightdev/core/cache';

// Create a cache with memory adapter
const cache = createCache({
  adapter: memory(),
  ttl: 60000,
});

// Cache function results
const getUser = cached(
  async (id: string) => fetchUser(id),
  { ttl: 5000, key: (id) => `user:${id}` }
);

// Deduplicate concurrent requests
const getData = dedupe(fetchData);

Server Actions

import { registerAction, executeAction, cookies } from '@flightdev/core/actions';

// Register a server action
registerAction('createUser', async (formData: FormData) => {
  const name = formData.get('name');
  const user = await db.users.create({ name });
  
  cookies().set('user_id', user.id);
  
  return { success: true, user };
});

// Execute from client
const result = await executeAction('createUser', formData);

Streaming SSR

import { 
  createStreamingSSR, 
  streamWithPriority 
} from '@flightdev/core/streaming';

// Basic streaming
const stream = await createStreamingSSR({
  component: App,
  props: { data },
});

// Priority-based streaming (out-of-order)
const result = await streamWithPriority({
  boundaries: [
    { id: 'header', priority: 100, render: Header },
    { id: 'sidebar', priority: 50, render: Sidebar },
    { id: 'content', priority: 75, render: Content },
  ],
});

Islands Architecture

import { 
  defineIsland, 
  hydrateIslands,
  createReactIslandAdapter 
} from '@flightdev/core/islands';

// Define an island component
const Counter = defineIsland({
  name: 'counter',
  component: CounterComponent,
  hydrate: 'visible', // 'load' | 'visible' | 'idle' | 'interaction'
});

// Client-side hydration
hydrateIslands({
  adapter: createReactIslandAdapter(),
});

Middleware

Flight provides a composable middleware system for request/response handling.

Middleware Chain

import { 
  createMiddlewareChain, 
  cors, 
  logger, 
  securityHeaders 
} from '@flightdev/core/middleware';

const chain = createMiddlewareChain();

chain
  .use(logger())
  .use(cors({ origin: ['https://app.example.com'] }))
  .use(securityHeaders())
  .use(async (ctx, next) => {
    const start = Date.now();
    await next();
    console.log(`Request took ${Date.now() - start}ms`);
  });

Error Handling

Centralized error handling with the errorHandler factory:

import { createMiddlewareChain, errorHandler } from '@flightdev/core/middleware';

const chain = createMiddlewareChain();

// Place error handler first in the chain
chain.use(errorHandler({
  expose: process.env.NODE_ENV === 'development',
  emit: (error, ctx) => {
    logger.error(`[${ctx.method}] ${ctx.url.pathname}:`, error);
    errorTracker.capture(error);
  },
}));

chain.use(authMiddleware);
chain.use(routeHandler);

The error handler catches all downstream errors, sets appropriate status codes, and supports custom error handlers:

chain.use(errorHandler({
  onError: async ({ error, status, ctx, timestamp }) => {
    ctx.status = status;
    ctx.responseBody = JSON.stringify({
      error: error.message,
      timestamp,
      requestId: ctx.locals.requestId,
    });
  },
}));

Typed Context

Middleware context supports generics for type-safe data sharing:

import type { Middleware, MiddlewareContext } from '@flightdev/core/middleware';

interface AppLocals {
  user: { id: string; role: string };
  requestId: string;
  db: DatabaseClient;
}

const authMiddleware: Middleware<AppLocals> = async (ctx, next) => {
  const token = ctx.headers.get('Authorization');
  const user = await verifyToken(token);
  
  ctx.locals.user = user;
  ctx.locals.requestId = crypto.randomUUID();
  
  await next();
};

// Type-safe access in subsequent middleware
const roleGuard: Middleware<AppLocals> = async (ctx, next) => {
  if (ctx.locals.user.role !== 'admin') {
    ctx.status = 403;
    ctx.responseBody = 'Forbidden';
    return;
  }
  await next();
};

CORS

CORS middleware with dynamic origin validation and CDN compatibility:

import { cors } from '@flightdev/core/middleware';

// Static origins
chain.use(cors({
  origin: ['https://app.example.com', 'https://admin.example.com'],
  methods: ['GET', 'POST', 'PUT', 'DELETE'],
  credentials: true,
}));

// Async validation (database lookup)
chain.use(cors({
  origin: async (requestOrigin) => {
    return await db.allowedOrigins.exists(requestOrigin);
  },
  exposeHeaders: ['X-Request-Id', 'X-RateLimit-Remaining'],
}));

Dynamic origins automatically set Vary: Origin for CDN/cache compatibility.

Built-in Middleware

Middleware Purpose
cors(options?) Cross-origin resource sharing
logger(options?) Request logging with configurable levels
securityHeaders(options?) Security headers (CSP, X-Frame-Options, etc.)
errorHandler(options?) Centralized error handling
compress() Mark responses for compression

Logger Configuration

import { logger } from '@flightdev/core/middleware';

chain.use(logger({
  level: 'info',           // 'debug' | 'info' | 'warn' | 'error' | 'silent'
  format: 'json',          // 'pretty' | 'json' | 'combined' | 'common' | 'short'
  skip: (ctx) => ctx.url.pathname === '/health',
  writer: (entry, formatted) => externalLogger.log(entry),
}));

The logger captures errors from downstream middleware before re-throwing, ensuring all requests are logged including failures.

Error Handling

import { 
  FlightError, 
  createError, 
  isFlightError,
  createNotFound,
  createForbidden,
} from '@flightdev/core/errors';

// Create typed errors
throw createNotFound('Page not found');
throw createForbidden('Access denied');

// Create custom errors
throw createError({
  statusCode: 422,
  message: 'Validation failed',
  data: { field: 'email', error: 'Invalid format' },
});

// Type guards
if (isFlightError(error)) {
  console.log(error.statusCode, error.digest);
}

React Integration

import { ErrorProvider, useError, useFlightError } from '@flightdev/core/react';

// Wrap your app
<ErrorProvider onError={console.error}>
  <App />
</ErrorProvider>

// Use in components
function MyComponent() {
  const { error, clearError } = useFlightError();
  
  if (error) {
    return <ErrorDisplay error={error} onRetry={clearError} />;
  }
  
  return <Content />;
}

Metadata (SEO)

import { renderMetadataToHead, type Metadata } from '@flightdev/core';

const metadata: Metadata = {
  title: 'My Page',
  description: 'Page description',
  openGraph: {
    title: 'OG Title',
    image: '/og-image.png',
  },
};

const headHtml = renderMetadataToHead(metadata);

Route Rules (ISR/SSG)

import { defineConfig } from '@flightdev/core';

export default defineConfig({
  routeRules: {
    '/': { prerender: true },
    '/blog/**': { isr: 3600 },
    '/api/**': { ssr: true },
    '/static/**': { static: true },
  },
});

Revalidation

import { 
  revalidatePath, 
  revalidateTag,
  createRevalidateHandler 
} from '@flightdev/core';

// On-demand revalidation
await revalidatePath('/blog/my-post');
await revalidateTag('blog-posts');

// Create revalidation API handler
const handler = createRevalidateHandler({
  secret: process.env.REVALIDATE_SECRET,
});

Environment Utilities

import { 
  isServer, 
  isBrowser, 
  isProduction,
  isDevelopment 
} from '@flightdev/core/utils';

if (isServer()) {
  // Server-only code
}

if (isDevelopment()) {
  console.log('Debug info');
}

Module Exports

Export Description
@flightdev/core Main entry with all primitives
@flightdev/core/router Routing utilities
@flightdev/core/cache Caching system
@flightdev/core/server HTTP server
@flightdev/core/render Rendering modes
@flightdev/core/middleware Middleware chain
@flightdev/core/actions Server actions
@flightdev/core/streaming Streaming SSR
@flightdev/core/islands Islands architecture
@flightdev/core/errors Error handling
@flightdev/core/react React integration
@flightdev/core/rsc React Server Components
@flightdev/core/config Configuration
@flightdev/core/utils Environment utilities

TypeScript

Full TypeScript support with exported types for all APIs:

import type {
  FlightConfig,
  Route,
  RouteMatch,
  Cache,
  CacheAdapter,
  Middleware,
  FlightError,
  Metadata,
  StreamingHints,
} from '@flightdev/core';

Build Plugins

Critical CSS Extraction

Extract and inline critical CSS for improved LCP:

npm install critters
// vite.config.ts
import { criticalCSS } from '@flightdev/core/plugins';

export default defineConfig({
    plugins: [
        criticalCSS({
            // Strategy for loading non-critical CSS
            preload: 'swap', // 'body' | 'media' | 'swap' | 'swap-high' | 'js' | 'js-lazy'
            
            // Remove inlined CSS from source
            pruneSource: false,
            
            // Routes to process
            include: ['**/*.html'],
            exclude: ['/api/**'],
        }),
    ],
});

Preload Strategies

Strategy Description
swap Use rel="preload" and swap on load
swap-high Like swap with fetchpriority="high"
media Use media="print" and swap
js Load via JavaScript
js-lazy Load via JavaScript when idle
body Move stylesheets to end of body

CSS Utilities

import {
    extractInlineStyles,
    mergeCSS,
    generatePreloadLink,
    generateNoscriptFallback,
} from '@flightdev/core/plugins/critical-css';

// Extract styles from HTML
const { html, styles } = extractInlineStyles(htmlString);

// Generate preload link
const preload = generatePreloadLink('/styles.css', 'swap');

// Generate noscript fallback
const fallback = generateNoscriptFallback('/styles.css');

License

MIT