@flexireact/core 3.0.0 → 3.0.2

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 (56) hide show
  1. package/README.md +204 -52
  2. package/dist/cli/index.js +1514 -0
  3. package/dist/cli/index.js.map +1 -0
  4. package/dist/core/client/index.js +373 -0
  5. package/dist/core/client/index.js.map +1 -0
  6. package/dist/core/index.js +6415 -0
  7. package/dist/core/index.js.map +1 -0
  8. package/dist/core/server/index.js +3094 -0
  9. package/dist/core/server/index.js.map +1 -0
  10. package/package.json +80 -80
  11. package/bin/flexireact.js +0 -23
  12. package/cli/generators.ts +0 -616
  13. package/cli/index.ts +0 -1182
  14. package/core/actions/index.ts +0 -364
  15. package/core/api.ts +0 -143
  16. package/core/build/index.ts +0 -425
  17. package/core/cli/logger.ts +0 -353
  18. package/core/client/Link.tsx +0 -345
  19. package/core/client/hydration.ts +0 -147
  20. package/core/client/index.ts +0 -12
  21. package/core/client/islands.ts +0 -143
  22. package/core/client/navigation.ts +0 -212
  23. package/core/client/runtime.ts +0 -52
  24. package/core/config.ts +0 -116
  25. package/core/context.ts +0 -83
  26. package/core/dev.ts +0 -47
  27. package/core/devtools/index.ts +0 -644
  28. package/core/edge/cache.ts +0 -344
  29. package/core/edge/fetch-polyfill.ts +0 -247
  30. package/core/edge/handler.ts +0 -248
  31. package/core/edge/index.ts +0 -81
  32. package/core/edge/ppr.ts +0 -264
  33. package/core/edge/runtime.ts +0 -161
  34. package/core/font/index.ts +0 -306
  35. package/core/helpers.ts +0 -494
  36. package/core/image/index.ts +0 -413
  37. package/core/index.ts +0 -218
  38. package/core/islands/index.ts +0 -293
  39. package/core/loader.ts +0 -111
  40. package/core/logger.ts +0 -242
  41. package/core/metadata/index.ts +0 -622
  42. package/core/middleware/index.ts +0 -416
  43. package/core/plugins/index.ts +0 -373
  44. package/core/render/index.ts +0 -1243
  45. package/core/render.ts +0 -136
  46. package/core/router/index.ts +0 -551
  47. package/core/router.ts +0 -141
  48. package/core/rsc/index.ts +0 -199
  49. package/core/server/index.ts +0 -779
  50. package/core/server.ts +0 -203
  51. package/core/ssg/index.ts +0 -346
  52. package/core/start-dev.ts +0 -6
  53. package/core/start-prod.ts +0 -6
  54. package/core/tsconfig.json +0 -30
  55. package/core/types.ts +0 -239
  56. 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
- };