@teamvelix/velix-core 5.2.9 → 5.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -288,7 +288,7 @@ interface RouteTreeNode {
288
288
  children: Record<string, RouteTreeNode>;
289
289
  routes: Route[];
290
290
  }
291
- interface RouteMatch {
291
+ interface RouteMatch$1 {
292
292
  route: Route;
293
293
  params: Record<string, string>;
294
294
  }
@@ -400,43 +400,42 @@ declare const RouteType: {
400
400
  readonly ERROR: "error";
401
401
  readonly NOT_FOUND: "not-found";
402
402
  };
403
+ type RouteMatch = Route & {
404
+ params: Record<string, string>;
405
+ };
406
+
407
+ /**
408
+ * Finds all layouts that apply to a route
409
+ */
410
+ declare function findRouteLayouts(route: Route, layoutsMap: Map<string, string>): Array<{
411
+ name: string;
412
+ filePath: string | undefined;
413
+ }>;
414
+
403
415
  /**
404
- * Builds the complete route tree from the app/ directory
416
+ * Matches URL path against routes
405
417
  */
406
- declare function buildRouteTree(appDir: string): {
418
+ declare function matchRoute(urlPath: string, routes: Route[]): RouteMatch | null;
419
+
420
+ /**
421
+ * Creates regex pattern for route matching
422
+ */
423
+ declare function createRoutePattern(routePath: string): RegExp;
424
+
425
+ /**
426
+ * Velix v5 Router
427
+ * File-based routing using the app/ directory convention
428
+ */
429
+ /**
430
+ * Builds the complete route tree from the app/ directory asynchronously
431
+ */
432
+ declare function buildRouteTree(appDir: string): Promise<{
407
433
  pages: Route[];
408
434
  api: Route[];
409
435
  layouts: Map<string, string>;
410
436
  tree: RouteTreeNode;
411
437
  appRoutes: Route[];
412
438
  rootLayout?: string;
413
- };
414
- /**
415
- * Matches URL path against routes
416
- */
417
- declare function matchRoute(urlPath: string, routes: Route[]): {
418
- params: Record<string, string>;
419
- type: RouteType$1;
420
- path: string;
421
- filePath: string;
422
- pattern: RegExp;
423
- segments: string[];
424
- layout?: string | null;
425
- loading?: string | null;
426
- error?: string | null;
427
- notFound?: string | null;
428
- template?: string | null;
429
- middleware?: string | null;
430
- isServerComponent?: boolean;
431
- isClientComponent?: boolean;
432
- isIsland?: boolean;
433
- } | null;
434
- /**
435
- * Finds all layouts that apply to a route
436
- */
437
- declare function findRouteLayouts(route: Route, layoutsMap: Map<string, string>): Array<{
438
- name: string;
439
- filePath: string | undefined;
440
439
  }>;
441
440
 
442
441
  /**
@@ -1191,107 +1190,41 @@ declare function isClientComponent(filePath: string): boolean;
1191
1190
  */
1192
1191
  declare function isIsland(filePath: string): boolean;
1193
1192
 
1194
- /**
1195
- * Velix v5 — Advanced Cache (VelixCache)
1196
- *
1197
- * Production-grade caching with:
1198
- * - LRU eviction (configurable maxSize)
1199
- * - TTL-based expiration
1200
- * - Stale-while-revalidate (SWR) window
1201
- * - Tag-based invalidation
1202
- * - Type-safe generics
1203
- */
1204
- type RevalidationType = 'path' | 'tag' | 'layout';
1205
- interface CacheOptions {
1206
- /** Time-to-live in milliseconds */
1193
+ interface ICacheAdapter {
1194
+ get<T>(key: string): Promise<T | null>;
1195
+ set<T>(key: string, value: T, options?: CacheSetOptions): Promise<void>;
1196
+ delete(key: string): Promise<void>;
1197
+ deleteByTag(tag: string): Promise<void>;
1198
+ deleteByPrefix(prefix: string): Promise<void>;
1199
+ clear(): Promise<void>;
1200
+ has(key: string): Promise<boolean>;
1201
+ }
1202
+ type CacheSetOptions = {
1207
1203
  ttl?: number;
1208
- /** Stale-while-revalidate window in milliseconds (after TTL expires) */
1209
- swr?: number;
1210
- /** Tags for group invalidation */
1211
1204
  tags?: string[];
1212
- }
1213
- interface VelixCacheConfig {
1214
- /** Maximum number of entries (default: 1000) */
1215
- maxSize?: number;
1216
- /** Default TTL in ms (default: 60_000 — 1 minute) */
1217
- defaultTtl?: number;
1218
- /** Default SWR window in ms (default: 10_000 — 10 seconds) */
1219
- defaultSwr?: number;
1220
- }
1205
+ };
1206
+
1207
+ type RevalidationType = 'path' | 'tag' | 'layout';
1221
1208
  declare class VelixCache {
1222
- private readonly maxSize;
1223
- private readonly defaultTtl;
1224
- private readonly defaultSwr;
1225
- private readonly store;
1226
- private readonly tagIndex;
1227
- private readonly head;
1228
- private readonly tail;
1229
- constructor(config?: VelixCacheConfig);
1230
- /** Current number of entries */
1231
- get size(): number;
1232
- /**
1233
- * Store a value with optional TTL, SWR, and tags.
1234
- */
1235
- set<T>(key: string, value: T, options?: CacheOptions): void;
1236
- /**
1237
- * Get a cached value. Returns `null` if not found or expired beyond SWR window.
1238
- *
1239
- * @returns `{ value, stale }` — `stale` is true when the entry is past TTL but within SWR window.
1240
- */
1241
- get<T>(key: string): {
1242
- value: T;
1243
- stale: boolean;
1244
- } | null;
1245
- /**
1246
- * Simple get that returns only the value (ignoring staleness).
1247
- * Returns `null` if not found or expired.
1248
- */
1249
- getValue<T>(key: string): T | null;
1250
- /** Check whether a key exists and is not expired */
1251
- has(key: string): boolean;
1252
- /** Remove a specific key */
1253
- delete(key: string): boolean;
1254
- /** Invalidate a specific path/key */
1255
- revalidatePath(path: string): void;
1256
- /** Invalidate all entries associated with a tag */
1257
- revalidateTag(tag: string): void;
1258
- /** Clear all entries */
1259
- invalidateAll(): void;
1260
- /** Get cache stats for debugging/monitoring */
1261
- stats(): {
1262
- size: number;
1263
- maxSize: number;
1264
- tags: number;
1265
- };
1266
- private createSentinel;
1267
- private addToHead;
1268
- private removeFromList;
1269
- private moveToHead;
1270
- private evictLRU;
1271
- private removeEntry;
1209
+ private adapter;
1210
+ private deduplicator;
1211
+ constructor(adapter?: ICacheAdapter);
1212
+ revalidatePath(path: string): Promise<void>;
1213
+ revalidateTag(tag: string): Promise<void>;
1214
+ unstable_cache<T>(fn: () => Promise<T>, keys: string[], options?: {
1215
+ tags?: string[];
1216
+ revalidate?: number;
1217
+ }): () => Promise<T>;
1272
1218
  }
1273
1219
  declare const cacheManager: VelixCache;
1274
1220
  /**
1275
1221
  * Revalidate a specific path
1276
- * @example
1277
- * ```ts
1278
- * import { revalidatePath } from 'velix/actions';
1279
- *
1280
- * await revalidatePath('/blog');
1281
- * await revalidatePath('/blog/[slug]', 'layout');
1282
- * ```
1283
1222
  */
1284
- declare function revalidatePath(path: string, _type?: RevalidationType): void;
1223
+ declare function revalidatePath(path: string, _type?: RevalidationType): Promise<void>;
1285
1224
  /**
1286
1225
  * Revalidate all paths with a specific cache tag
1287
- * @example
1288
- * ```ts
1289
- * import { revalidateTag } from 'velix/actions';
1290
- *
1291
- * await revalidateTag('blog-posts');
1292
- * ```
1293
1226
  */
1294
- declare function revalidateTag(tag: string): void;
1227
+ declare function revalidateTag(tag: string): Promise<void>;
1295
1228
  /**
1296
1229
  * Unstable cache wrapper (experimental)
1297
1230
  */
@@ -1382,6 +1315,48 @@ type LoaderResult<T> = {
1382
1315
  };
1383
1316
  declare function defineLoader<T>(fn: (ctx: LoaderContext) => Promise<T>): (ctx: LoaderContext) => Promise<LoaderResult<T>>;
1384
1317
 
1318
+ /**
1319
+ * Backplane Redis Pub/Sub pour la synchronisation HMR multi-instances.
1320
+ *
1321
+ * Problème sans backplane :
1322
+ * Pod A déclenche un HMR → notifie uniquement ses clients WebSocket.
1323
+ * Les clients connectés sur les pods B et C ne reçoivent rien.
1324
+ *
1325
+ * Solution :
1326
+ * Chaque pod publie ses events HMR sur le channel Redis 'velix:hmr'.
1327
+ * Chaque pod écoute ce channel et rebroadcast aux clients WebSocket locaux.
1328
+ *
1329
+ * @example
1330
+ * ```ts
1331
+ * import { HMRPubSubBackplane } from 'velix-core/dev/hmr-pubsub';
1332
+ * import { createHMRServer } from 'velix-core/dev/hmr-server';
1333
+ *
1334
+ * const pubsub = new HMRPubSubBackplane(process.env.REDIS_URL);
1335
+ * const hmr = createHMRServer(httpServer, projectRoot, { pubsub });
1336
+ * ```
1337
+ */
1338
+ declare class HMRPubSubBackplane {
1339
+ private pub;
1340
+ private sub;
1341
+ private handlers;
1342
+ constructor(redisUrl: string);
1343
+ /**
1344
+ * Publie un event HMR sur le channel Redis.
1345
+ * Tous les pods abonnés le recevront et le rebroadcastent à leurs clients.
1346
+ */
1347
+ publish(event: HMREvent): Promise<void>;
1348
+ /**
1349
+ * S'abonne aux events HMR reçus depuis les autres instances.
1350
+ * Retourne une fonction de désinscription.
1351
+ */
1352
+ onEvent(handler: (event: HMREvent) => void): () => void;
1353
+ /**
1354
+ * Ferme proprement les connexions pub et sub.
1355
+ * À appeler au shutdown du serveur de dev.
1356
+ */
1357
+ disconnect(): Promise<void>;
1358
+ }
1359
+
1385
1360
  type HMREvent = {
1386
1361
  type: 'file-changed';
1387
1362
  file: string;
@@ -1408,8 +1383,16 @@ type HMREvent = {
1408
1383
  type: 'full-reload';
1409
1384
  timestamp: number;
1410
1385
  };
1411
- declare function createHMRServer(httpServer: Server, projectRoot: string): {
1386
+ interface HMRServerOptions {
1387
+ /**
1388
+ * Backplane Redis Pub/Sub pour la synchronisation HMR multi-instances.
1389
+ * Optionnel — si absent, le HMR est local à cette instance uniquement.
1390
+ */
1391
+ pubsub?: HMRPubSubBackplane;
1392
+ }
1393
+ declare function createHMRServer(httpServer: Server, projectRoot: string, options?: HMRServerOptions): {
1412
1394
  broadcast: (event: HMREvent) => void;
1395
+ broadcastLocal: (event: HMREvent) => void;
1413
1396
  watcher: chokidar.FSWatcher;
1414
1397
  wss: ws.Server<typeof WebSocket, typeof http.IncomingMessage>;
1415
1398
  clients: Set<WebSocket>;
@@ -1427,4 +1410,4 @@ declare function resolveErrorBoundary(routeFilePath: string, appDir: string, typ
1427
1410
  declare function defineError(component: ErrorComponent): ErrorComponent;
1428
1411
  declare function defineNotFound(component: NotFoundComponent): NotFoundComponent;
1429
1412
 
1430
- export { type AIClient, type AIInput, type AIPluginConfig, type AIProvider, type AIProviderType, type AIResponse, type AIStreamChunk, type ActionAIConfig, type ActionContext, type ActionOptions, type ActionResult, type ActionState, type Alternates, type ApiHandler, type ApiRoute, type Author, type BuildOptions, type BuildResult, type CacheOptions, type ChatInput, type ChatMessage, type EmbedInput, type EmbedResponse, type ErrorBoundaryType, type ErrorComponent, type ErrorProps, ForbiddenError, type FormatDetection, type HMREvent, type HttpMethod, type IconDescriptor, type Icons, type InferActionInput, type InferActionOutput, type InferLoaderData, type IslandConfig, type IslandManifest, type LayoutComponent, type LayoutProps, type LoaderContext, type LoaderResult, type LoadingComponent, type LoadingProps, type Metadata, type Middleware, type MiddlewareFunction, type MiddlewareRequest, type MiddlewareResponse, type MiddlewareResult, type NextFunction, type NotFoundComponent, NotFoundError, type NotFoundProps, type OGImage, type OGVideo, OllamaProvider, OpenAIProvider, type OpenGraph, type PageComponent, type PageProps, type PluginHook, type PluginHookArgs, PluginHooks, PluginManager, type ResolvedBoundary, type RevalidationType, type Robots, type Route, type RouteContext, type RouteHandler, type RouteMatch, type RouteTree, RouteType, type ServerAction, type StaticPath, type StaticProps, type TailwindPluginOptions, type ThemeColor, type Twitter, type TwitterImage, type TypedActionResult, UnauthorizedError, VelixCache, type VelixConfig, VelixConfigSchema, VelixHttpError, type VelixPlugin, type VelixPluginDefinition, type Verification, type Viewport, buildApiManifest, buildPrompt, buildRouteTree, builtinPlugins, cacheManager, cleanDir, composeMiddleware, copyDir, createAIAction, createAIClient, createDeferred, createHMRServer, createStreamDecoder, debounce, defaultConfig, defineConfig, defineError, defineLoader, defineNotFound, definePlugin, defineRoute, ensureDir, escapeHtml, estimateTokens, filePathToRoute, findFiles, findRouteLayouts, formatBytes, formatTime, generateHash, generateJsonLd, generateMetadataTags, generateRobotsTxt, generateSitemap, getErrorBoundaryType, handleApiRequest, isClientComponent, isIsland, isServerComponent, jsonLd, loadConfig, loadMiddleware, loadPlugins, logger, matchRoute, mergeMetadata, middlewares, parseSSE, pluginManager, resolveErrorBoundary, resolvePaths, retry, revalidatePath, revalidateTag, runMiddleware, safeJsonParse, sanitizeInput, serverAction, sleep, truncateToTokens, unstable_cache, useAI, validateApiKey, validateInput };
1413
+ export { type AIClient, type AIInput, type AIPluginConfig, type AIProvider, type AIProviderType, type AIResponse, type AIStreamChunk, type ActionAIConfig, type ActionContext, type ActionOptions, type ActionResult, type ActionState, type Alternates, type ApiHandler, type ApiRoute, type Author, type BuildOptions, type BuildResult, type ChatInput, type ChatMessage, type EmbedInput, type EmbedResponse, type ErrorBoundaryType, type ErrorComponent, type ErrorProps, ForbiddenError, type FormatDetection, type HMREvent, type HMRServerOptions, type HttpMethod, type IconDescriptor, type Icons, type InferActionInput, type InferActionOutput, type InferLoaderData, type IslandConfig, type IslandManifest, type LayoutComponent, type LayoutProps, type LoaderContext, type LoaderResult, type LoadingComponent, type LoadingProps, type Metadata, type Middleware, type MiddlewareFunction, type MiddlewareRequest, type MiddlewareResponse, type MiddlewareResult, type NextFunction, type NotFoundComponent, NotFoundError, type NotFoundProps, type OGImage, type OGVideo, OllamaProvider, OpenAIProvider, type OpenGraph, type PageComponent, type PageProps, type PluginHook, type PluginHookArgs, PluginHooks, PluginManager, type ResolvedBoundary, type RevalidationType, type Robots, type Route, type RouteContext, type RouteHandler, type RouteMatch$1 as RouteMatch, type RouteTree, RouteType, type ServerAction, type StaticPath, type StaticProps, type TailwindPluginOptions, type ThemeColor, type Twitter, type TwitterImage, type TypedActionResult, UnauthorizedError, VelixCache, type VelixConfig, VelixConfigSchema, VelixHttpError, type VelixPlugin, type VelixPluginDefinition, type Verification, type Viewport, buildApiManifest, buildPrompt, buildRouteTree, builtinPlugins, cacheManager, cleanDir, composeMiddleware, copyDir, createAIAction, createAIClient, createDeferred, createHMRServer, createRoutePattern, createStreamDecoder, debounce, defaultConfig, defineConfig, defineError, defineLoader, defineNotFound, definePlugin, defineRoute, ensureDir, escapeHtml, estimateTokens, filePathToRoute, findFiles, findRouteLayouts, formatBytes, formatTime, generateHash, generateJsonLd, generateMetadataTags, generateRobotsTxt, generateSitemap, getErrorBoundaryType, handleApiRequest, isClientComponent, isIsland, isServerComponent, jsonLd, loadConfig, loadMiddleware, loadPlugins, logger, matchRoute, mergeMetadata, middlewares, parseSSE, pluginManager, resolveErrorBoundary, resolvePaths, retry, revalidatePath, revalidateTag, runMiddleware, safeJsonParse, sanitizeInput, serverAction, sleep, truncateToTokens, unstable_cache, useAI, validateApiKey, validateInput };