@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,416 +0,0 @@
1
- /**
2
- * FlexiReact Middleware System
3
- *
4
- * Middlewares run before every request and can:
5
- * - Modify the request/response
6
- * - Redirect or rewrite URLs
7
- * - Add headers
8
- * - Authenticate users
9
- * - Log requests
10
- *
11
- * Usage:
12
- * Create a middleware.js file in your project root:
13
- *
14
- * export default function middleware(request) {
15
- * // Return a response to short-circuit
16
- * // Return NextResponse.next() to continue
17
- * // Return NextResponse.redirect() to redirect
18
- * }
19
- *
20
- * export const config = {
21
- * matcher: ['/protected/:path*']
22
- * };
23
- */
24
-
25
- import fs from 'fs';
26
- import path from 'path';
27
- import { pathToFileURL } from 'url';
28
-
29
- /**
30
- * Middleware response helpers
31
- */
32
- interface MiddlewareResponseOptions {
33
- type?: string;
34
- status?: number;
35
- headers?: Record<string, string>;
36
- body?: any;
37
- url?: string | null;
38
- }
39
-
40
- export class MiddlewareResponse {
41
- type: string;
42
- status: number;
43
- headers: Map<string, string>;
44
- body: any;
45
- url: string | null;
46
-
47
- constructor(options: MiddlewareResponseOptions = {}) {
48
- this.type = options.type || 'next';
49
- this.status = options.status || 200;
50
- this.headers = new Map(Object.entries(options.headers || {}));
51
- this.body = options.body || null;
52
- this.url = options.url || null;
53
- }
54
-
55
- /**
56
- * Continue to the next middleware/handler
57
- */
58
- static next(options = {}) {
59
- return new MiddlewareResponse({ ...options, type: 'next' });
60
- }
61
-
62
- /**
63
- * Redirect to a different URL
64
- */
65
- static redirect(url, status = 302) {
66
- return new MiddlewareResponse({
67
- type: 'redirect',
68
- url,
69
- status
70
- });
71
- }
72
-
73
- /**
74
- * Rewrite the request to a different URL (internal)
75
- */
76
- static rewrite(url) {
77
- return new MiddlewareResponse({
78
- type: 'rewrite',
79
- url
80
- });
81
- }
82
-
83
- /**
84
- * Return a JSON response
85
- */
86
- static json(data: any, options: { status?: number; headers?: Record<string, string> } = {}) {
87
- return new MiddlewareResponse({
88
- type: 'response',
89
- status: options.status || 200,
90
- headers: { 'Content-Type': 'application/json', ...options.headers },
91
- body: JSON.stringify(data)
92
- });
93
- }
94
-
95
- /**
96
- * Return an HTML response
97
- */
98
- static html(content: string, options: { status?: number; headers?: Record<string, string> } = {}) {
99
- return new MiddlewareResponse({
100
- type: 'response',
101
- status: options.status || 200,
102
- headers: { 'Content-Type': 'text/html', ...options.headers },
103
- body: content
104
- });
105
- }
106
- }
107
-
108
- /**
109
- * Middleware request wrapper
110
- */
111
- export class MiddlewareRequest {
112
- raw: any;
113
- method: string;
114
- url: string;
115
- headers: Map<string, string>;
116
- pathname: string;
117
- searchParams: URLSearchParams;
118
- query: Record<string, string>;
119
- cookies: Map<string, string>;
120
-
121
- constructor(req: any) {
122
- this.raw = req;
123
- this.method = req.method;
124
- this.url = req.url;
125
- this.headers = new Map(Object.entries(req.headers || {}));
126
-
127
- // Parse URL
128
- const parsedUrl = new URL(req.url, `http://${req.headers.host || 'localhost'}`);
129
- this.pathname = parsedUrl.pathname;
130
- this.searchParams = parsedUrl.searchParams;
131
- this.query = Object.fromEntries(parsedUrl.searchParams) as Record<string, string>;
132
-
133
- // Parse cookies
134
- this.cookies = this._parseCookies(req.headers.cookie || '');
135
- }
136
-
137
- _parseCookies(cookieHeader) {
138
- const cookies = new Map();
139
- if (!cookieHeader) return cookies;
140
-
141
- cookieHeader.split(';').forEach(cookie => {
142
- const [name, ...rest] = cookie.split('=');
143
- if (name) {
144
- cookies.set(name.trim(), rest.join('=').trim());
145
- }
146
- });
147
-
148
- return cookies;
149
- }
150
-
151
- /**
152
- * Get a header value
153
- */
154
- header(name) {
155
- return this.headers.get(name.toLowerCase());
156
- }
157
-
158
- /**
159
- * Get a cookie value
160
- */
161
- cookie(name) {
162
- return this.cookies.get(name);
163
- }
164
-
165
- /**
166
- * Check if request matches a path pattern
167
- */
168
- matches(pattern) {
169
- return matchPath(this.pathname, pattern);
170
- }
171
- }
172
-
173
- /**
174
- * Loads middleware from project
175
- */
176
- export async function loadMiddleware(projectRoot) {
177
- const middlewarePath = path.join(projectRoot, 'middleware.js');
178
-
179
- if (!fs.existsSync(middlewarePath)) {
180
- return null;
181
- }
182
-
183
- try {
184
- const url = pathToFileURL(middlewarePath).href;
185
- const module = await import(`${url}?t=${Date.now()}`);
186
-
187
- return {
188
- handler: module.default,
189
- config: module.config || {}
190
- };
191
- } catch (error) {
192
- console.error('Failed to load middleware:', error);
193
- return null;
194
- }
195
- }
196
-
197
- /**
198
- * Runs middleware chain
199
- */
200
- export async function runMiddleware(req, res, middleware) {
201
- if (!middleware) {
202
- return { continue: true };
203
- }
204
-
205
- const { handler, config } = middleware;
206
- const request = new MiddlewareRequest(req);
207
-
208
- // Check if request matches middleware patterns
209
- if (config.matcher) {
210
- const patterns = Array.isArray(config.matcher) ? config.matcher : [config.matcher];
211
- const matches = patterns.some(pattern => matchPath(request.pathname, pattern));
212
-
213
- if (!matches) {
214
- return { continue: true };
215
- }
216
- }
217
-
218
- try {
219
- const response = await handler(request);
220
-
221
- if (!response || response.type === 'next') {
222
- // Apply any headers from middleware
223
- if (response?.headers) {
224
- for (const [key, value] of response.headers) {
225
- res.setHeader(key, value);
226
- }
227
- }
228
- return { continue: true };
229
- }
230
-
231
- if (response.type === 'redirect') {
232
- res.writeHead(response.status, { Location: response.url });
233
- res.end();
234
- return { continue: false };
235
- }
236
-
237
- if (response.type === 'rewrite') {
238
- // Modify the request URL internally
239
- req.url = response.url;
240
- return { continue: true, rewritten: true };
241
- }
242
-
243
- if (response.type === 'response') {
244
- // Apply headers
245
- for (const [key, value] of response.headers) {
246
- res.setHeader(key, value);
247
- }
248
- res.writeHead(response.status);
249
- res.end(response.body);
250
- return { continue: false };
251
- }
252
-
253
- return { continue: true };
254
-
255
- } catch (error) {
256
- console.error('Middleware error:', error);
257
- return { continue: true, error };
258
- }
259
- }
260
-
261
- /**
262
- * Matches a path against a pattern
263
- */
264
- function matchPath(pathname, pattern) {
265
- // Convert pattern to regex
266
- let regex = pattern
267
- .replace(/\*/g, '.*')
268
- .replace(/:path\*/g, '.*')
269
- .replace(/:(\w+)/g, '[^/]+');
270
-
271
- regex = `^${regex}$`;
272
-
273
- return new RegExp(regex).test(pathname);
274
- }
275
-
276
- /**
277
- * Compose multiple middleware functions
278
- */
279
- export function composeMiddleware(...middlewares) {
280
- return async (request) => {
281
- for (const middleware of middlewares) {
282
- const response = await middleware(request);
283
-
284
- if (response && response.type !== 'next') {
285
- return response;
286
- }
287
- }
288
-
289
- return MiddlewareResponse.next();
290
- };
291
- }
292
-
293
- /**
294
- * Built-in middleware helpers
295
- */
296
- export const middlewares = {
297
- /**
298
- * CORS middleware
299
- */
300
- cors(options: { origin?: string; methods?: string; headers?: string; credentials?: boolean } = {}) {
301
- const {
302
- origin = '*',
303
- methods = 'GET,HEAD,PUT,PATCH,POST,DELETE',
304
- headers = 'Content-Type,Authorization',
305
- credentials = false
306
- } = options;
307
-
308
- return (request) => {
309
- const response = MiddlewareResponse.next({
310
- headers: {
311
- 'Access-Control-Allow-Origin': origin,
312
- 'Access-Control-Allow-Methods': methods,
313
- 'Access-Control-Allow-Headers': headers,
314
- ...(credentials && { 'Access-Control-Allow-Credentials': 'true' })
315
- }
316
- });
317
-
318
- // Handle preflight
319
- if (request.method === 'OPTIONS') {
320
- return MiddlewareResponse.json({}, { status: 204, headers: Object.fromEntries(response.headers) });
321
- }
322
-
323
- return response;
324
- };
325
- },
326
-
327
- /**
328
- * Basic auth middleware
329
- */
330
- basicAuth(options) {
331
- const { username, password, realm = 'Protected' } = options;
332
- const expected = Buffer.from(`${username}:${password}`).toString('base64');
333
-
334
- return (request) => {
335
- const auth = request.header('authorization');
336
-
337
- if (!auth || !auth.startsWith('Basic ')) {
338
- return MiddlewareResponse.html('Unauthorized', {
339
- status: 401,
340
- headers: { 'WWW-Authenticate': `Basic realm="${realm}"` }
341
- });
342
- }
343
-
344
- const provided = auth.slice(6);
345
- if (provided !== expected) {
346
- return MiddlewareResponse.html('Unauthorized', { status: 401 });
347
- }
348
-
349
- return MiddlewareResponse.next();
350
- };
351
- },
352
-
353
- /**
354
- * Rate limiting middleware
355
- */
356
- rateLimit(options: { windowMs?: number; max?: number } = {}) {
357
- const { windowMs = 60000, max = 100 } = options;
358
- const requests = new Map();
359
-
360
- return (request) => {
361
- const ip = request.header('x-forwarded-for') || 'unknown';
362
- const now = Date.now();
363
-
364
- // Clean old entries
365
- for (const [key, data] of requests) {
366
- if (now - data.start > windowMs) {
367
- requests.delete(key);
368
- }
369
- }
370
-
371
- // Check rate limit
372
- const data = requests.get(ip) || { count: 0, start: now };
373
- data.count++;
374
- requests.set(ip, data);
375
-
376
- if (data.count > max) {
377
- return MiddlewareResponse.json(
378
- { error: 'Too many requests' },
379
- { status: 429 }
380
- );
381
- }
382
-
383
- return MiddlewareResponse.next({
384
- headers: {
385
- 'X-RateLimit-Limit': String(max),
386
- 'X-RateLimit-Remaining': String(max - data.count)
387
- }
388
- });
389
- };
390
- },
391
-
392
- /**
393
- * Logging middleware
394
- */
395
- logger(options: { format?: string } = {}) {
396
- const { format = 'combined' } = options;
397
-
398
- return (request) => {
399
- const start = Date.now();
400
- const { method, pathname } = request;
401
-
402
- console.log(`→ ${method} ${pathname}`);
403
-
404
- return MiddlewareResponse.next();
405
- };
406
- }
407
- };
408
-
409
- export default {
410
- MiddlewareRequest,
411
- MiddlewareResponse,
412
- loadMiddleware,
413
- runMiddleware,
414
- composeMiddleware,
415
- middlewares
416
- };