@flexireact/core 3.0.1 → 3.0.3

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.
Files changed (55) hide show
  1. package/dist/cli/index.js +1514 -0
  2. package/dist/cli/index.js.map +1 -0
  3. package/dist/core/client/index.js +373 -0
  4. package/dist/core/client/index.js.map +1 -0
  5. package/dist/core/index.js +6415 -0
  6. package/dist/core/index.js.map +1 -0
  7. package/dist/core/server/index.js +3094 -0
  8. package/dist/core/server/index.js.map +1 -0
  9. package/package.json +80 -80
  10. package/bin/flexireact.js +0 -23
  11. package/cli/generators.ts +0 -616
  12. package/cli/index.ts +0 -1182
  13. package/core/actions/index.ts +0 -364
  14. package/core/api.ts +0 -143
  15. package/core/build/index.ts +0 -425
  16. package/core/cli/logger.ts +0 -353
  17. package/core/client/Link.tsx +0 -345
  18. package/core/client/hydration.ts +0 -147
  19. package/core/client/index.ts +0 -12
  20. package/core/client/islands.ts +0 -143
  21. package/core/client/navigation.ts +0 -212
  22. package/core/client/runtime.ts +0 -52
  23. package/core/config.ts +0 -116
  24. package/core/context.ts +0 -83
  25. package/core/dev.ts +0 -47
  26. package/core/devtools/index.ts +0 -644
  27. package/core/edge/cache.ts +0 -344
  28. package/core/edge/fetch-polyfill.ts +0 -247
  29. package/core/edge/handler.ts +0 -248
  30. package/core/edge/index.ts +0 -81
  31. package/core/edge/ppr.ts +0 -264
  32. package/core/edge/runtime.ts +0 -161
  33. package/core/font/index.ts +0 -306
  34. package/core/helpers.ts +0 -494
  35. package/core/image/index.ts +0 -413
  36. package/core/index.ts +0 -218
  37. package/core/islands/index.ts +0 -293
  38. package/core/loader.ts +0 -111
  39. package/core/logger.ts +0 -242
  40. package/core/metadata/index.ts +0 -622
  41. package/core/middleware/index.ts +0 -416
  42. package/core/plugins/index.ts +0 -373
  43. package/core/render/index.ts +0 -1243
  44. package/core/render.ts +0 -136
  45. package/core/router/index.ts +0 -551
  46. package/core/router.ts +0 -141
  47. package/core/rsc/index.ts +0 -199
  48. package/core/server/index.ts +0 -779
  49. package/core/server.ts +0 -203
  50. package/core/ssg/index.ts +0 -346
  51. package/core/start-dev.ts +0 -6
  52. package/core/start-prod.ts +0 -6
  53. package/core/tsconfig.json +0 -30
  54. package/core/types.ts +0 -239
  55. package/core/utils.ts +0 -176
@@ -1,413 +0,0 @@
1
- /**
2
- * FlexiReact Image Optimization
3
- *
4
- * Optimized image component with:
5
- * - Automatic WebP/AVIF conversion
6
- * - Responsive srcset generation
7
- * - Lazy loading with blur placeholder
8
- * - Priority loading for LCP images
9
- * - Automatic width/height to prevent CLS
10
- */
11
-
12
- import React from 'react';
13
- import path from 'path';
14
- import fs from 'fs';
15
- import crypto from 'crypto';
16
-
17
- // Image optimization config
18
- export interface ImageConfig {
19
- domains: string[];
20
- deviceSizes: number[];
21
- imageSizes: number[];
22
- formats: ('webp' | 'avif' | 'png' | 'jpeg')[];
23
- minimumCacheTTL: number;
24
- dangerouslyAllowSVG: boolean;
25
- quality: number;
26
- cacheDir: string;
27
- }
28
-
29
- export const defaultImageConfig: ImageConfig = {
30
- domains: [],
31
- deviceSizes: [640, 750, 828, 1080, 1200, 1920, 2048, 3840],
32
- imageSizes: [16, 32, 48, 64, 96, 128, 256, 384],
33
- formats: ['webp', 'avif'],
34
- minimumCacheTTL: 60 * 60 * 24 * 30, // 30 days
35
- dangerouslyAllowSVG: false,
36
- quality: 75,
37
- cacheDir: '.flexi/image-cache'
38
- };
39
-
40
- // Image props
41
- export interface ImageProps {
42
- src: string;
43
- alt: string;
44
- width?: number;
45
- height?: number;
46
- fill?: boolean;
47
- sizes?: string;
48
- quality?: number;
49
- priority?: boolean;
50
- placeholder?: 'blur' | 'empty' | 'data:image/...';
51
- blurDataURL?: string;
52
- loading?: 'lazy' | 'eager';
53
- className?: string;
54
- style?: React.CSSProperties;
55
- onLoad?: () => void;
56
- onError?: () => void;
57
- unoptimized?: boolean;
58
- }
59
-
60
- // Generate blur placeholder
61
- export async function generateBlurPlaceholder(imagePath: string): Promise<string> {
62
- try {
63
- // For now, return a simple SVG blur placeholder
64
- // In production, we'd use sharp to generate a tiny blurred version
65
- return `data:image/svg+xml;base64,${Buffer.from(
66
- `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 8 5">
67
- <filter id="b" color-interpolation-filters="sRGB">
68
- <feGaussianBlur stdDeviation="1"/>
69
- </filter>
70
- <rect width="100%" height="100%" fill="#1a1a1a"/>
71
- <rect width="100%" height="100%" filter="url(#b)" opacity="0.5" fill="#333"/>
72
- </svg>`
73
- ).toString('base64')}`;
74
- } catch {
75
- return '';
76
- }
77
- }
78
-
79
- // Get image dimensions
80
- export async function getImageDimensions(src: string): Promise<{ width: number; height: number } | null> {
81
- try {
82
- // For local files
83
- if (!src.startsWith('http')) {
84
- const imagePath = path.join(process.cwd(), 'public', src);
85
- if (fs.existsSync(imagePath)) {
86
- // Read first bytes to detect dimensions
87
- const buffer = fs.readFileSync(imagePath);
88
- return detectDimensions(buffer);
89
- }
90
- }
91
- return null;
92
- } catch {
93
- return null;
94
- }
95
- }
96
-
97
- // Detect image dimensions from buffer
98
- function detectDimensions(buffer: Buffer): { width: number; height: number } | null {
99
- // PNG
100
- if (buffer[0] === 0x89 && buffer[1] === 0x50) {
101
- return {
102
- width: buffer.readUInt32BE(16),
103
- height: buffer.readUInt32BE(20)
104
- };
105
- }
106
-
107
- // JPEG
108
- if (buffer[0] === 0xff && buffer[1] === 0xd8) {
109
- let offset = 2;
110
- while (offset < buffer.length) {
111
- if (buffer[offset] !== 0xff) break;
112
- const marker = buffer[offset + 1];
113
- if (marker === 0xc0 || marker === 0xc2) {
114
- return {
115
- height: buffer.readUInt16BE(offset + 5),
116
- width: buffer.readUInt16BE(offset + 7)
117
- };
118
- }
119
- offset += 2 + buffer.readUInt16BE(offset + 2);
120
- }
121
- }
122
-
123
- // GIF
124
- if (buffer[0] === 0x47 && buffer[1] === 0x49 && buffer[2] === 0x46) {
125
- return {
126
- width: buffer.readUInt16LE(6),
127
- height: buffer.readUInt16LE(8)
128
- };
129
- }
130
-
131
- // WebP
132
- if (buffer[0] === 0x52 && buffer[1] === 0x49 && buffer[8] === 0x57 && buffer[9] === 0x45) {
133
- // VP8
134
- if (buffer[12] === 0x56 && buffer[13] === 0x50 && buffer[14] === 0x38) {
135
- if (buffer[15] === 0x20) { // VP8
136
- return {
137
- width: buffer.readUInt16LE(26) & 0x3fff,
138
- height: buffer.readUInt16LE(28) & 0x3fff
139
- };
140
- }
141
- if (buffer[15] === 0x4c) { // VP8L
142
- const bits = buffer.readUInt32LE(21);
143
- return {
144
- width: (bits & 0x3fff) + 1,
145
- height: ((bits >> 14) & 0x3fff) + 1
146
- };
147
- }
148
- }
149
- }
150
-
151
- return null;
152
- }
153
-
154
- // Generate srcset for responsive images
155
- export function generateSrcSet(
156
- src: string,
157
- widths: number[],
158
- quality: number = 75
159
- ): string {
160
- return widths
161
- .map(w => `/_flexi/image?url=${encodeURIComponent(src)}&w=${w}&q=${quality} ${w}w`)
162
- .join(', ');
163
- }
164
-
165
- // Generate sizes attribute
166
- export function generateSizes(sizes?: string): string {
167
- if (sizes) return sizes;
168
- return '100vw';
169
- }
170
-
171
- // Image optimization endpoint handler
172
- export async function handleImageOptimization(
173
- req: any,
174
- res: any,
175
- config: Partial<ImageConfig> = {}
176
- ): Promise<void> {
177
- const fullConfig = { ...defaultImageConfig, ...config };
178
- const url = new URL(req.url, `http://${req.headers.host}`);
179
-
180
- const imageUrl = url.searchParams.get('url');
181
- const width = parseInt(url.searchParams.get('w') || '0', 10);
182
- const quality = parseInt(url.searchParams.get('q') || String(fullConfig.quality), 10);
183
- const format = url.searchParams.get('f') as 'webp' | 'avif' | 'png' | 'jpeg' | null;
184
-
185
- if (!imageUrl) {
186
- res.writeHead(400, { 'Content-Type': 'text/plain' });
187
- res.end('Missing url parameter');
188
- return;
189
- }
190
-
191
- try {
192
- let imageBuffer: Buffer;
193
- let contentType: string;
194
-
195
- // Fetch image
196
- if (imageUrl.startsWith('http')) {
197
- // Remote image
198
- const response = await fetch(imageUrl);
199
- if (!response.ok) throw new Error('Failed to fetch image');
200
- imageBuffer = Buffer.from(await response.arrayBuffer());
201
- contentType = response.headers.get('content-type') || 'image/jpeg';
202
- } else {
203
- // Local image
204
- const imagePath = path.join(process.cwd(), 'public', imageUrl);
205
- if (!fs.existsSync(imagePath)) {
206
- res.writeHead(404, { 'Content-Type': 'text/plain' });
207
- res.end('Image not found');
208
- return;
209
- }
210
- imageBuffer = fs.readFileSync(imagePath);
211
- contentType = getContentType(imagePath);
212
- }
213
-
214
- // Generate cache key
215
- const cacheKey = crypto
216
- .createHash('md5')
217
- .update(`${imageUrl}-${width}-${quality}-${format}`)
218
- .digest('hex');
219
-
220
- const cacheDir = path.join(process.cwd(), fullConfig.cacheDir);
221
- const cachePath = path.join(cacheDir, `${cacheKey}.${format || 'webp'}`);
222
-
223
- // Check cache
224
- if (fs.existsSync(cachePath)) {
225
- const cachedImage = fs.readFileSync(cachePath);
226
- res.writeHead(200, {
227
- 'Content-Type': `image/${format || 'webp'}`,
228
- 'Cache-Control': `public, max-age=${fullConfig.minimumCacheTTL}`,
229
- 'X-Flexi-Image-Cache': 'HIT'
230
- });
231
- res.end(cachedImage);
232
- return;
233
- }
234
-
235
- // For now, serve original image
236
- // In production, we'd use sharp for resizing/conversion
237
- // TODO: Integrate sharp for actual optimization
238
-
239
- res.writeHead(200, {
240
- 'Content-Type': contentType,
241
- 'Cache-Control': `public, max-age=${fullConfig.minimumCacheTTL}`,
242
- 'X-Flexi-Image-Cache': 'MISS'
243
- });
244
- res.end(imageBuffer);
245
-
246
- } catch (error: any) {
247
- console.error('Image optimization error:', error);
248
- res.writeHead(500, { 'Content-Type': 'text/plain' });
249
- res.end('Image optimization failed');
250
- }
251
- }
252
-
253
- // Get content type from file extension
254
- function getContentType(filePath: string): string {
255
- const ext = path.extname(filePath).toLowerCase();
256
- const types: Record<string, string> = {
257
- '.jpg': 'image/jpeg',
258
- '.jpeg': 'image/jpeg',
259
- '.png': 'image/png',
260
- '.gif': 'image/gif',
261
- '.webp': 'image/webp',
262
- '.avif': 'image/avif',
263
- '.svg': 'image/svg+xml',
264
- '.ico': 'image/x-icon'
265
- };
266
- return types[ext] || 'application/octet-stream';
267
- }
268
-
269
- // Image component (server-side rendered)
270
- export function createImageComponent(config: Partial<ImageConfig> = {}) {
271
- const fullConfig = { ...defaultImageConfig, ...config };
272
-
273
- return function Image(props: ImageProps): React.ReactElement {
274
- const {
275
- src,
276
- alt,
277
- width,
278
- height,
279
- fill = false,
280
- sizes,
281
- quality = fullConfig.quality,
282
- priority = false,
283
- placeholder = 'empty',
284
- blurDataURL,
285
- loading,
286
- className = '',
287
- style = {},
288
- unoptimized = false,
289
- ...rest
290
- } = props;
291
-
292
- // Determine loading strategy
293
- const loadingAttr = priority ? 'eager' : (loading || 'lazy');
294
-
295
- // Generate optimized src
296
- const optimizedSrc = unoptimized
297
- ? src
298
- : `/_flexi/image?url=${encodeURIComponent(src)}&w=${width || 1920}&q=${quality}`;
299
-
300
- // Generate srcset for responsive images
301
- const allSizes = [...fullConfig.imageSizes, ...fullConfig.deviceSizes].sort((a, b) => a - b);
302
- const relevantSizes = width
303
- ? allSizes.filter(s => s <= width * 2)
304
- : allSizes;
305
-
306
- const srcSet = unoptimized
307
- ? undefined
308
- : generateSrcSet(src, relevantSizes, quality);
309
-
310
- // Build styles
311
- const imgStyle: React.CSSProperties = {
312
- ...style,
313
- ...(fill ? {
314
- position: 'absolute',
315
- top: 0,
316
- left: 0,
317
- width: '100%',
318
- height: '100%',
319
- objectFit: 'cover'
320
- } : {})
321
- };
322
-
323
- // Placeholder styles
324
- const wrapperStyle: React.CSSProperties = fill ? {
325
- position: 'relative',
326
- width: '100%',
327
- height: '100%'
328
- } : {};
329
-
330
- const placeholderStyle: React.CSSProperties = placeholder === 'blur' ? {
331
- backgroundImage: `url(${blurDataURL || generateBlurPlaceholderSync()})`,
332
- backgroundSize: 'cover',
333
- backgroundPosition: 'center',
334
- filter: 'blur(20px)',
335
- transform: 'scale(1.1)'
336
- } : {};
337
-
338
- // Create image element
339
- const imgElement = React.createElement('img', {
340
- src: optimizedSrc,
341
- alt,
342
- width: fill ? undefined : width,
343
- height: fill ? undefined : height,
344
- loading: loadingAttr,
345
- decoding: 'async',
346
- srcSet,
347
- sizes: generateSizes(sizes),
348
- className: `flexi-image ${className}`.trim(),
349
- style: imgStyle,
350
- fetchPriority: priority ? 'high' : undefined,
351
- ...rest
352
- });
353
-
354
- // Wrap with placeholder if needed
355
- if (fill || placeholder === 'blur') {
356
- return React.createElement('div', {
357
- className: 'flexi-image-wrapper',
358
- style: { ...wrapperStyle, ...placeholderStyle }
359
- }, imgElement);
360
- }
361
-
362
- return imgElement;
363
- };
364
- }
365
-
366
- // Sync blur placeholder (for SSR)
367
- function generateBlurPlaceholderSync(): string {
368
- return `data:image/svg+xml;base64,${Buffer.from(
369
- `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 8 5">
370
- <filter id="b" color-interpolation-filters="sRGB">
371
- <feGaussianBlur stdDeviation="1"/>
372
- </filter>
373
- <rect width="100%" height="100%" fill="#1a1a1a"/>
374
- </svg>`
375
- ).toString('base64')}`;
376
- }
377
-
378
- // Default Image component
379
- export const Image = createImageComponent();
380
-
381
- // Loader types for different image providers
382
- export interface ImageLoader {
383
- (props: { src: string; width: number; quality?: number }): string;
384
- }
385
-
386
- // Built-in loaders
387
- export const imageLoaders = {
388
- default: ({ src, width, quality = 75 }: { src: string; width: number; quality?: number }) =>
389
- `/_flexi/image?url=${encodeURIComponent(src)}&w=${width}&q=${quality}`,
390
-
391
- cloudinary: ({ src, width, quality = 75 }: { src: string; width: number; quality?: number }) =>
392
- `https://res.cloudinary.com/demo/image/fetch/w_${width},q_${quality}/${src}`,
393
-
394
- imgix: ({ src, width, quality = 75 }: { src: string; width: number; quality?: number }) =>
395
- `${src}?w=${width}&q=${quality}&auto=format`,
396
-
397
- vercel: ({ src, width, quality = 75 }: { src: string; width: number; quality?: number }) =>
398
- `/_vercel/image?url=${encodeURIComponent(src)}&w=${width}&q=${quality}`,
399
-
400
- cloudflare: ({ src, width, quality = 75 }: { src: string; width: number; quality?: number }) =>
401
- `/cdn-cgi/image/width=${width},quality=${quality}/${src}`
402
- };
403
-
404
- export default {
405
- Image,
406
- createImageComponent,
407
- handleImageOptimization,
408
- generateBlurPlaceholder,
409
- getImageDimensions,
410
- generateSrcSet,
411
- imageLoaders,
412
- defaultImageConfig
413
- };
package/core/index.ts DELETED
@@ -1,218 +0,0 @@
1
- /**
2
- * FlexiReact v2 - Main Entry Point
3
- * A modern React framework with RSC, SSG, Islands, and more
4
- */
5
-
6
- // Types
7
- export type { FlexiConfig, Route, RouteType as RouteTypeEnum, PageProps, LayoutProps } from './types.js';
8
-
9
- // Core exports
10
- export { loadConfig, defaultConfig, resolvePaths } from './config.js';
11
- export { createRequestContext, useRequest, useParams, useQuery, usePathname } from './context.js';
12
- export * from './utils.js';
13
-
14
- // Router
15
- export { buildRouteTree, matchRoute, findRouteLayouts, RouteType } from './router/index.js';
16
-
17
- // Render
18
- export { renderPage, renderPageStream, streamToResponse, renderError, renderLoading } from './render/index.js';
19
-
20
- // Server
21
- import { createServer } from './server/index.js';
22
- export { createServer };
23
-
24
- // Build
25
- export { build, buildDev, BuildMode } from './build/index.js';
26
-
27
- // SSG
28
- export { generateStaticSite, SSGResult, ISRManager } from './ssg/index.js';
29
-
30
- // RSC
31
- export {
32
- processServerComponent,
33
- createClientReference,
34
- serializeRSCPayload,
35
- createServerAction,
36
- handleServerAction,
37
- ServerBoundary,
38
- ClientBoundary,
39
- RSC_CONTENT_TYPE
40
- } from './rsc/index.js';
41
-
42
- // Islands
43
- export {
44
- Island,
45
- createIsland,
46
- createLazyIsland,
47
- getRegisteredIslands,
48
- generateHydrationScript,
49
- generateAdvancedHydrationScript,
50
- LoadStrategy
51
- } from './islands/index.js';
52
-
53
- // Middleware
54
- export {
55
- MiddlewareRequest,
56
- MiddlewareResponse,
57
- loadMiddleware,
58
- runMiddleware,
59
- composeMiddleware,
60
- middlewares
61
- } from './middleware/index.js';
62
-
63
- // Plugins
64
- export {
65
- PluginManager,
66
- PluginHooks,
67
- pluginManager,
68
- loadPlugins,
69
- definePlugin,
70
- builtinPlugins
71
- } from './plugins/index.js';
72
-
73
- // Edge Runtime
74
- export {
75
- // Runtime
76
- detectRuntime,
77
- getRuntimeCapabilities,
78
- edgeRuntimeInfo,
79
- // Fetch
80
- FlexiRequest,
81
- FlexiResponse,
82
- FlexiHeaders,
83
- // Handler
84
- createEdgeApp,
85
- // Cache
86
- smartCache,
87
- initCache,
88
- cacheFunction,
89
- unstable_cache,
90
- revalidateTag,
91
- revalidatePath,
92
- reactCache,
93
- // PPR
94
- dynamic,
95
- staticComponent,
96
- PPRBoundary,
97
- PPRShell,
98
- prerenderWithPPR,
99
- streamPPR,
100
- pprFetch,
101
- PPRLoading,
102
- experimental_ppr,
103
- // Default exports
104
- createApp
105
- } from './edge/index.js';
106
- export type {
107
- RuntimeEnvironment,
108
- RuntimeCapabilities,
109
- EdgeContext,
110
- EdgeHandler,
111
- EdgeMiddleware,
112
- EdgeAppConfig,
113
- CacheEntry,
114
- CacheOptions,
115
- PPRConfig,
116
- PPRRenderResult,
117
- PPRPageConfig,
118
- GenerateStaticParams
119
- } from './edge/index.js';
120
-
121
- // Font Optimization
122
- export {
123
- createFont,
124
- googleFont,
125
- localFont,
126
- generateFontCSS,
127
- generateFontPreloadTags,
128
- handleFontRequest,
129
- fonts,
130
- googleFonts
131
- } from './font/index.js';
132
- export type { FontConfig, FontResult } from './font/index.js';
133
-
134
- // Metadata API
135
- export {
136
- generateMetadataTags,
137
- mergeMetadata,
138
- generateJsonLd,
139
- jsonLd
140
- } from './metadata/index.js';
141
- export type {
142
- Metadata,
143
- OpenGraph,
144
- Twitter,
145
- Icons,
146
- Robots,
147
- Viewport,
148
- Author
149
- } from './metadata/index.js';
150
-
151
- // Image Optimization
152
- export {
153
- Image,
154
- createImageComponent,
155
- handleImageOptimization,
156
- generateBlurPlaceholder,
157
- getImageDimensions,
158
- generateSrcSet,
159
- imageLoaders,
160
- defaultImageConfig
161
- } from './image/index.js';
162
- export type { ImageProps, ImageConfig, ImageLoader } from './image/index.js';
163
-
164
- // Server Actions
165
- export {
166
- serverAction,
167
- registerAction,
168
- getAction,
169
- executeAction,
170
- callServerAction,
171
- formAction,
172
- createFormState,
173
- bindArgs,
174
- useActionContext
175
- } from './actions/index.js';
176
- export type { ActionContext, ActionResult, ServerActionFunction } from './actions/index.js';
177
-
178
- // Server Helpers
179
- export {
180
- // Response helpers
181
- redirect,
182
- notFound,
183
- json,
184
- html,
185
- text,
186
- // Error classes
187
- RedirectError,
188
- NotFoundError,
189
- // Cookies API
190
- cookies,
191
- // Headers API
192
- headers,
193
- // Request helpers
194
- parseJson,
195
- parseFormData,
196
- parseSearchParams,
197
- getMethod,
198
- getPathname,
199
- isMethod
200
- } from './helpers.js';
201
- export type { CookieOptions } from './helpers.js';
202
-
203
- // DevTools
204
- export {
205
- devtools,
206
- DevToolsOverlay,
207
- initPerformanceMonitoring,
208
- initNetworkInterceptor
209
- } from './devtools/index.js';
210
-
211
- // Version
212
- export const VERSION = '3.0.0';
213
-
214
- // Default export
215
- export default {
216
- VERSION,
217
- createServer
218
- };