@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,161 +0,0 @@
1
- /**
2
- * FlexiReact Universal Edge Runtime
3
- *
4
- * Works on:
5
- * - Node.js
6
- * - Bun
7
- * - Deno
8
- * - Cloudflare Workers
9
- * - Vercel Edge
10
- * - Any Web-standard runtime
11
- */
12
-
13
- // Detect runtime environment
14
- export type RuntimeEnvironment =
15
- | 'node'
16
- | 'bun'
17
- | 'deno'
18
- | 'cloudflare'
19
- | 'vercel-edge'
20
- | 'netlify-edge'
21
- | 'fastly'
22
- | 'unknown';
23
-
24
- export function detectRuntime(): RuntimeEnvironment {
25
- // Bun
26
- if (typeof globalThis.Bun !== 'undefined') {
27
- return 'bun';
28
- }
29
-
30
- // Deno
31
- if (typeof globalThis.Deno !== 'undefined') {
32
- return 'deno';
33
- }
34
-
35
- // Cloudflare Workers
36
- if (typeof globalThis.caches !== 'undefined' && typeof (globalThis as any).WebSocketPair !== 'undefined') {
37
- return 'cloudflare';
38
- }
39
-
40
- // Vercel Edge
41
- if (typeof process !== 'undefined' && process.env?.VERCEL_EDGE === '1') {
42
- return 'vercel-edge';
43
- }
44
-
45
- // Netlify Edge
46
- if (typeof globalThis.Netlify !== 'undefined') {
47
- return 'netlify-edge';
48
- }
49
-
50
- // Node.js
51
- if (typeof process !== 'undefined' && process.versions?.node) {
52
- return 'node';
53
- }
54
-
55
- return 'unknown';
56
- }
57
-
58
- // Runtime capabilities
59
- export interface RuntimeCapabilities {
60
- hasFileSystem: boolean;
61
- hasWebCrypto: boolean;
62
- hasWebStreams: boolean;
63
- hasFetch: boolean;
64
- hasWebSocket: boolean;
65
- hasKV: boolean;
66
- hasCache: boolean;
67
- maxExecutionTime: number; // ms, 0 = unlimited
68
- maxMemory: number; // bytes, 0 = unlimited
69
- }
70
-
71
- export function getRuntimeCapabilities(): RuntimeCapabilities {
72
- const runtime = detectRuntime();
73
-
74
- switch (runtime) {
75
- case 'cloudflare':
76
- return {
77
- hasFileSystem: false,
78
- hasWebCrypto: true,
79
- hasWebStreams: true,
80
- hasFetch: true,
81
- hasWebSocket: true,
82
- hasKV: true,
83
- hasCache: true,
84
- maxExecutionTime: 30000, // 30s for paid, 10ms for free
85
- maxMemory: 128 * 1024 * 1024 // 128MB
86
- };
87
-
88
- case 'vercel-edge':
89
- return {
90
- hasFileSystem: false,
91
- hasWebCrypto: true,
92
- hasWebStreams: true,
93
- hasFetch: true,
94
- hasWebSocket: false,
95
- hasKV: true, // Vercel KV
96
- hasCache: true,
97
- maxExecutionTime: 30000,
98
- maxMemory: 128 * 1024 * 1024
99
- };
100
-
101
- case 'deno':
102
- return {
103
- hasFileSystem: true,
104
- hasWebCrypto: true,
105
- hasWebStreams: true,
106
- hasFetch: true,
107
- hasWebSocket: true,
108
- hasKV: true, // Deno KV
109
- hasCache: true,
110
- maxExecutionTime: 0,
111
- maxMemory: 0
112
- };
113
-
114
- case 'bun':
115
- return {
116
- hasFileSystem: true,
117
- hasWebCrypto: true,
118
- hasWebStreams: true,
119
- hasFetch: true,
120
- hasWebSocket: true,
121
- hasKV: false,
122
- hasCache: false,
123
- maxExecutionTime: 0,
124
- maxMemory: 0
125
- };
126
-
127
- case 'node':
128
- default:
129
- return {
130
- hasFileSystem: true,
131
- hasWebCrypto: true,
132
- hasWebStreams: true,
133
- hasFetch: true,
134
- hasWebSocket: true,
135
- hasKV: false,
136
- hasCache: false,
137
- maxExecutionTime: 0,
138
- maxMemory: 0
139
- };
140
- }
141
- }
142
-
143
- // Runtime info
144
- export const runtime = {
145
- name: detectRuntime(),
146
- capabilities: getRuntimeCapabilities(),
147
-
148
- get isEdge(): boolean {
149
- return ['cloudflare', 'vercel-edge', 'netlify-edge', 'fastly'].includes(this.name);
150
- },
151
-
152
- get isServer(): boolean {
153
- return ['node', 'bun', 'deno'].includes(this.name);
154
- },
155
-
156
- get supportsStreaming(): boolean {
157
- return this.capabilities.hasWebStreams;
158
- }
159
- };
160
-
161
- export default runtime;
@@ -1,306 +0,0 @@
1
- /**
2
- * FlexiReact Font Optimization
3
- *
4
- * Optimized font loading with:
5
- * - Automatic font subsetting
6
- * - Preload hints generation
7
- * - Font-display: swap by default
8
- * - Self-hosted Google Fonts
9
- * - Variable font support
10
- * - CSS variable generation
11
- */
12
-
13
- import fs from 'fs';
14
- import path from 'path';
15
- import crypto from 'crypto';
16
-
17
- // Font configuration
18
- export interface FontConfig {
19
- family: string;
20
- weight?: string | number | (string | number)[];
21
- style?: 'normal' | 'italic' | 'oblique';
22
- subsets?: string[];
23
- display?: 'auto' | 'block' | 'swap' | 'fallback' | 'optional';
24
- preload?: boolean;
25
- fallback?: string[];
26
- variable?: string;
27
- adjustFontFallback?: boolean;
28
- }
29
-
30
- export interface FontResult {
31
- className: string;
32
- style: {
33
- fontFamily: string;
34
- fontWeight?: number | string;
35
- fontStyle?: string;
36
- };
37
- variable?: string;
38
- }
39
-
40
- // Google Fonts API
41
- const GOOGLE_FONTS_API = 'https://fonts.googleapis.com/css2';
42
-
43
- // Popular Google Fonts with their weights
44
- export const googleFonts = {
45
- Inter: {
46
- weights: [100, 200, 300, 400, 500, 600, 700, 800, 900],
47
- variable: true,
48
- subsets: ['latin', 'latin-ext', 'cyrillic', 'greek', 'vietnamese']
49
- },
50
- Roboto: {
51
- weights: [100, 300, 400, 500, 700, 900],
52
- variable: false,
53
- subsets: ['latin', 'latin-ext', 'cyrillic', 'greek', 'vietnamese']
54
- },
55
- 'Open Sans': {
56
- weights: [300, 400, 500, 600, 700, 800],
57
- variable: true,
58
- subsets: ['latin', 'latin-ext', 'cyrillic', 'greek', 'vietnamese']
59
- },
60
- Poppins: {
61
- weights: [100, 200, 300, 400, 500, 600, 700, 800, 900],
62
- variable: false,
63
- subsets: ['latin', 'latin-ext']
64
- },
65
- Montserrat: {
66
- weights: [100, 200, 300, 400, 500, 600, 700, 800, 900],
67
- variable: true,
68
- subsets: ['latin', 'latin-ext', 'cyrillic', 'vietnamese']
69
- },
70
- 'Fira Code': {
71
- weights: [300, 400, 500, 600, 700],
72
- variable: true,
73
- subsets: ['latin', 'latin-ext', 'cyrillic', 'greek']
74
- },
75
- 'JetBrains Mono': {
76
- weights: [100, 200, 300, 400, 500, 600, 700, 800],
77
- variable: true,
78
- subsets: ['latin', 'latin-ext', 'cyrillic', 'greek']
79
- },
80
- Geist: {
81
- weights: [100, 200, 300, 400, 500, 600, 700, 800, 900],
82
- variable: true,
83
- subsets: ['latin', 'latin-ext']
84
- },
85
- 'Geist Mono': {
86
- weights: [100, 200, 300, 400, 500, 600, 700, 800, 900],
87
- variable: true,
88
- subsets: ['latin', 'latin-ext']
89
- }
90
- };
91
-
92
- // Generate font CSS
93
- export function generateFontCSS(config: FontConfig): string {
94
- const {
95
- family,
96
- weight = 400,
97
- style = 'normal',
98
- display = 'swap',
99
- fallback = ['system-ui', 'sans-serif'],
100
- variable
101
- } = config;
102
-
103
- const weights = Array.isArray(weight) ? weight : [weight];
104
- const fallbackStr = fallback.map(f => f.includes(' ') ? `"${f}"` : f).join(', ');
105
-
106
- let css = '';
107
-
108
- // Generate @font-face for each weight
109
- for (const w of weights) {
110
- css += `
111
- @font-face {
112
- font-family: '${family}';
113
- font-style: ${style};
114
- font-weight: ${w};
115
- font-display: ${display};
116
- src: local('${family}'),
117
- url('/_flexi/font/${encodeURIComponent(family)}?weight=${w}&style=${style}') format('woff2');
118
- }
119
- `;
120
- }
121
-
122
- // Generate CSS variable if specified
123
- if (variable) {
124
- css += `
125
- :root {
126
- ${variable}: '${family}', ${fallbackStr};
127
- }
128
- `;
129
- }
130
-
131
- return css;
132
- }
133
-
134
- // Generate preload link tags
135
- export function generateFontPreloadTags(fonts: FontConfig[]): string {
136
- return fonts
137
- .filter(f => f.preload !== false)
138
- .map(f => {
139
- const weights = Array.isArray(f.weight) ? f.weight : [f.weight || 400];
140
- return weights.map(w =>
141
- `<link rel="preload" href="/_flexi/font/${encodeURIComponent(f.family)}?weight=${w}&style=${f.style || 'normal'}" as="font" type="font/woff2" crossorigin>`
142
- ).join('\n');
143
- })
144
- .join('\n');
145
- }
146
-
147
- // Create a font loader function (like next/font)
148
- export function createFont(config: FontConfig): FontResult {
149
- const {
150
- family,
151
- weight = 400,
152
- style = 'normal',
153
- fallback = ['system-ui', 'sans-serif'],
154
- variable
155
- } = config;
156
-
157
- // Generate unique class name
158
- const hash = crypto
159
- .createHash('md5')
160
- .update(`${family}-${weight}-${style}`)
161
- .digest('hex')
162
- .slice(0, 8);
163
-
164
- const className = `__font_${hash}`;
165
- const fallbackStr = fallback.map(f => f.includes(' ') ? `"${f}"` : f).join(', ');
166
-
167
- return {
168
- className,
169
- style: {
170
- fontFamily: `'${family}', ${fallbackStr}`,
171
- fontWeight: Array.isArray(weight) ? undefined : weight,
172
- fontStyle: style
173
- },
174
- variable: variable || undefined
175
- };
176
- }
177
-
178
- // Google Font loader
179
- export function googleFont(config: FontConfig): FontResult {
180
- return createFont({
181
- ...config,
182
- // Google Fonts are always preloaded
183
- preload: true
184
- });
185
- }
186
-
187
- // Local font loader
188
- export function localFont(config: FontConfig & { src: string | { path: string; weight?: string | number; style?: string }[] }): FontResult {
189
- return createFont(config);
190
- }
191
-
192
- // Handle font requests
193
- export async function handleFontRequest(
194
- req: any,
195
- res: any
196
- ): Promise<void> {
197
- const url = new URL(req.url, `http://${req.headers.host}`);
198
- const pathParts = url.pathname.split('/');
199
- const fontFamily = decodeURIComponent(pathParts[pathParts.length - 1] || '');
200
- const weight = url.searchParams.get('weight') || '400';
201
- const style = url.searchParams.get('style') || 'normal';
202
-
203
- if (!fontFamily) {
204
- res.writeHead(400, { 'Content-Type': 'text/plain' });
205
- res.end('Missing font family');
206
- return;
207
- }
208
-
209
- try {
210
- // Check local cache first
211
- const cacheDir = path.join(process.cwd(), '.flexi', 'font-cache');
212
- const cacheKey = crypto
213
- .createHash('md5')
214
- .update(`${fontFamily}-${weight}-${style}`)
215
- .digest('hex');
216
- const cachePath = path.join(cacheDir, `${cacheKey}.woff2`);
217
-
218
- if (fs.existsSync(cachePath)) {
219
- const fontData = fs.readFileSync(cachePath);
220
- res.writeHead(200, {
221
- 'Content-Type': 'font/woff2',
222
- 'Cache-Control': 'public, max-age=31536000, immutable',
223
- 'X-Flexi-Font-Cache': 'HIT'
224
- });
225
- res.end(fontData);
226
- return;
227
- }
228
-
229
- // Fetch from Google Fonts
230
- const googleUrl = `${GOOGLE_FONTS_API}?family=${encodeURIComponent(fontFamily)}:wght@${weight}&display=swap`;
231
-
232
- const cssResponse = await fetch(googleUrl, {
233
- headers: {
234
- 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36'
235
- }
236
- });
237
-
238
- if (!cssResponse.ok) {
239
- throw new Error('Failed to fetch font CSS');
240
- }
241
-
242
- const css = await cssResponse.text();
243
-
244
- // Extract woff2 URL from CSS
245
- const woff2Match = css.match(/url\((https:\/\/fonts\.gstatic\.com[^)]+\.woff2)\)/);
246
-
247
- if (!woff2Match) {
248
- throw new Error('Could not find woff2 URL');
249
- }
250
-
251
- // Fetch the actual font file
252
- const fontResponse = await fetch(woff2Match[1]);
253
-
254
- if (!fontResponse.ok) {
255
- throw new Error('Failed to fetch font file');
256
- }
257
-
258
- const fontBuffer = Buffer.from(await fontResponse.arrayBuffer());
259
-
260
- // Cache the font
261
- if (!fs.existsSync(cacheDir)) {
262
- fs.mkdirSync(cacheDir, { recursive: true });
263
- }
264
- fs.writeFileSync(cachePath, fontBuffer);
265
-
266
- // Serve the font
267
- res.writeHead(200, {
268
- 'Content-Type': 'font/woff2',
269
- 'Cache-Control': 'public, max-age=31536000, immutable',
270
- 'X-Flexi-Font-Cache': 'MISS'
271
- });
272
- res.end(fontBuffer);
273
-
274
- } catch (error: any) {
275
- console.error('Font loading error:', error);
276
- res.writeHead(500, { 'Content-Type': 'text/plain' });
277
- res.end('Font loading failed');
278
- }
279
- }
280
-
281
- // Pre-built font configurations
282
- export const fonts = {
283
- // Sans-serif
284
- inter: (config: Partial<FontConfig> = {}) => googleFont({ family: 'Inter', variable: '--font-inter', ...config }),
285
- roboto: (config: Partial<FontConfig> = {}) => googleFont({ family: 'Roboto', variable: '--font-roboto', ...config }),
286
- openSans: (config: Partial<FontConfig> = {}) => googleFont({ family: 'Open Sans', variable: '--font-open-sans', ...config }),
287
- poppins: (config: Partial<FontConfig> = {}) => googleFont({ family: 'Poppins', variable: '--font-poppins', ...config }),
288
- montserrat: (config: Partial<FontConfig> = {}) => googleFont({ family: 'Montserrat', variable: '--font-montserrat', ...config }),
289
- geist: (config: Partial<FontConfig> = {}) => googleFont({ family: 'Geist', variable: '--font-geist', ...config }),
290
-
291
- // Monospace
292
- firaCode: (config: Partial<FontConfig> = {}) => googleFont({ family: 'Fira Code', variable: '--font-fira-code', fallback: ['monospace'], ...config }),
293
- jetbrainsMono: (config: Partial<FontConfig> = {}) => googleFont({ family: 'JetBrains Mono', variable: '--font-jetbrains', fallback: ['monospace'], ...config }),
294
- geistMono: (config: Partial<FontConfig> = {}) => googleFont({ family: 'Geist Mono', variable: '--font-geist-mono', fallback: ['monospace'], ...config })
295
- };
296
-
297
- export default {
298
- createFont,
299
- googleFont,
300
- localFont,
301
- generateFontCSS,
302
- generateFontPreloadTags,
303
- handleFontRequest,
304
- fonts,
305
- googleFonts
306
- };