npm package: @flight-framework/core
Description: Core primitives for Flight Framework - routing, rendering, caching
Author: Flight Contributors
Latest version: 0.6.7
Deprecated: DEPRECATED: Movido a @flightdev/core

# @flight-framework/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

```bash
npm install @flight-framework/core
```

## Quick Start

### Configuration

```typescript
// flight.config.ts
import { defineConfig } from '@flight-framework/core';

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

### Create a Server

```typescript
import { createServer } from '@flight-framework/core';

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

await server.start();
```

### File-Based Routing

```typescript
import { createFileRouter, scanRoutes } from '@flight-framework/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

```typescript
import { createRouter } from '@flight-framework/core/router';

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

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

### Cache

```typescript
import { createCache, memory, cached, dedupe } from '@flight-framework/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

```typescript
import { registerAction, executeAction, cookies } from '@flight-framework/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

```typescript
import { 
  createStreamingSSR, 
  streamWithPriority 
} from '@flight-framework/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

```typescript
import { 
  defineIsland, 
  hydrateIslands,
  createReactIslandAdapter 
} from '@flight-framework/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

```typescript
import { 
  createMiddlewareChain, 
  cors, 
  logger, 
  securityHeaders 
} from '@flight-framework/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:

```typescript
import { createMiddlewareChain, errorHandler } from '@flight-framework/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:

```typescript
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:

```typescript
import type { Middleware, MiddlewareContext } from '@flight-framework/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:

```typescript
import { cors } from '@flight-framework/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

```typescript
import { logger } from '@flight-framework/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

```typescript
import { 
  FlightError, 
  createError, 
  isFlightError,
  createNotFound,
  createForbidden,
} from '@flight-framework/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

```typescript
import { ErrorProvider, useError, useFlightError } from '@flight-framework/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)

```typescript
import { renderMetadataToHead, type Metadata } from '@flight-framework/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)

```typescript
import { defineConfig } from '@flight-framework/core';

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

### Revalidation

```typescript
import { 
  revalidatePath, 
  revalidateTag,
  createRevalidateHandler 
} from '@flight-framework/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

```typescript
import { 
  isServer, 
  isBrowser, 
  isProduction,
  isDevelopment 
} from '@flight-framework/core/utils';

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

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

## Module Exports

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

## TypeScript

Full TypeScript support with exported types for all APIs:

```typescript
import type {
  FlightConfig,
  Route,
  RouteMatch,
  Cache,
  CacheAdapter,
  Middleware,
  FlightError,
  Metadata,
  StreamingHints,
} from '@flight-framework/core';
```

## Build Plugins

### Critical CSS Extraction

Extract and inline critical CSS for improved LCP:

```bash
npm install critters
```

```typescript
// vite.config.ts
import { criticalCSS } from '@flight-framework/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

```typescript
import {
    extractInlineStyles,
    mergeCSS,
    generatePreloadLink,
    generateNoscriptFallback,
} from '@flight-framework/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