@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
package/core/router.ts DELETED
@@ -1,141 +0,0 @@
1
- import fs from 'fs';
2
- import path from 'path';
3
-
4
- /**
5
- * Scans the pages directory and builds a route map
6
- * @param {string} pagesDir - Path to the pages directory
7
- * @returns {Object} Route map with paths and file locations
8
- */
9
- export function buildRoutes(pagesDir) {
10
- const routes = {
11
- pages: [],
12
- api: []
13
- };
14
-
15
- if (!fs.existsSync(pagesDir)) {
16
- return routes;
17
- }
18
-
19
- scanDirectory(pagesDir, pagesDir, routes);
20
- return routes;
21
- }
22
-
23
- /**
24
- * Recursively scans a directory for route files
25
- */
26
- function scanDirectory(baseDir, currentDir, routes) {
27
- const entries = fs.readdirSync(currentDir, { withFileTypes: true });
28
-
29
- for (const entry of entries) {
30
- const fullPath = path.join(currentDir, entry.name);
31
- const relativePath = path.relative(baseDir, fullPath);
32
-
33
- if (entry.isDirectory()) {
34
- scanDirectory(baseDir, fullPath, routes);
35
- } else if (entry.isFile()) {
36
- const ext = path.extname(entry.name);
37
-
38
- if (ext === '.jsx' || ext === '.js') {
39
- const routePath = filePathToRoute(relativePath);
40
- const isApi = relativePath.startsWith('api' + path.sep) || relativePath.startsWith('api/');
41
-
42
- if (isApi && ext === '.js') {
43
- routes.api.push({
44
- path: routePath,
45
- filePath: fullPath,
46
- pattern: createRoutePattern(routePath)
47
- });
48
- } else if (!isApi && ext === '.jsx') {
49
- routes.pages.push({
50
- path: routePath,
51
- filePath: fullPath,
52
- pattern: createRoutePattern(routePath)
53
- });
54
- }
55
- }
56
- }
57
- }
58
- }
59
-
60
- /**
61
- * Converts a file path to a route path
62
- * pages/index.jsx -> /
63
- * pages/about.jsx -> /about
64
- * pages/blog/[id].jsx -> /blog/:id
65
- * pages/api/hello.js -> /api/hello
66
- */
67
- function filePathToRoute(filePath) {
68
- // Normalize path separators
69
- let route = filePath.replace(/\\/g, '/');
70
-
71
- // Remove extension
72
- route = route.replace(/\.(jsx|js)$/, '');
73
-
74
- // Convert [param] to :param
75
- route = route.replace(/\[([^\]]+)\]/g, ':$1');
76
-
77
- // Handle index files
78
- if (route.endsWith('/index')) {
79
- route = route.slice(0, -6) || '/';
80
- } else if (route === 'index') {
81
- route = '/';
82
- }
83
-
84
- // Ensure leading slash
85
- if (!route.startsWith('/')) {
86
- route = '/' + route;
87
- }
88
-
89
- return route;
90
- }
91
-
92
- /**
93
- * Creates a regex pattern for route matching
94
- */
95
- function createRoutePattern(routePath) {
96
- const pattern = routePath
97
- .replace(/:[^/]+/g, '([^/]+)')
98
- .replace(/\//g, '\\/');
99
-
100
- return new RegExp(`^${pattern}$`);
101
- }
102
-
103
- /**
104
- * Matches a URL path against the route map
105
- * @param {string} urlPath - The URL path to match
106
- * @param {Array} routes - Array of route objects
107
- * @returns {Object|null} Matched route with params or null
108
- */
109
- export function matchRoute(urlPath, routes) {
110
- // Normalize the URL path
111
- const normalizedPath = urlPath === '' ? '/' : urlPath;
112
-
113
- for (const route of routes) {
114
- const match = normalizedPath.match(route.pattern);
115
-
116
- if (match) {
117
- // Extract params from the match
118
- const params = {};
119
- const paramNames = (route.path.match(/:[^/]+/g) || []).map(p => p.slice(1));
120
-
121
- paramNames.forEach((name, index) => {
122
- params[name] = match[index + 1];
123
- });
124
-
125
- return {
126
- ...route,
127
- params
128
- };
129
- }
130
- }
131
-
132
- return null;
133
- }
134
-
135
- /**
136
- * Invalidates the module cache for hot reload
137
- */
138
- export function invalidateCache(filePath) {
139
- // For ESM, we use query string cache busting
140
- return `${filePath}?t=${Date.now()}`;
141
- }
package/core/rsc/index.ts DELETED
@@ -1,199 +0,0 @@
1
- /**
2
- * FlexiReact React Server Components (RSC) System
3
- *
4
- * RSC allows components to run exclusively on the server, reducing client bundle size
5
- * and enabling direct database/filesystem access in components.
6
- *
7
- * Usage:
8
- * - Add 'use server' at the top of a component file to make it a Server Component
9
- * - Add 'use client' at the top to make it a Client Component (hydrated on client)
10
- * - Server Components can import Client Components, but not vice versa
11
- */
12
-
13
- import React from 'react';
14
- import { renderToString } from 'react-dom/server';
15
- import { isServerComponent, isClientComponent } from '../utils.js';
16
-
17
- /**
18
- * RSC Payload format for streaming
19
- */
20
- export const RSC_CONTENT_TYPE = 'text/x-component';
21
-
22
- /**
23
- * Processes a component tree for RSC
24
- * Server components are rendered to HTML, client components are serialized
25
- */
26
- export async function processServerComponent(Component, props, context) {
27
- const componentInfo = {
28
- isServer: true,
29
- rendered: null,
30
- clientComponents: [],
31
- serverData: {}
32
- };
33
-
34
- try {
35
- // If component has async data fetching
36
- if (Component.getServerData) {
37
- componentInfo.serverData = await Component.getServerData(context);
38
- props = { ...props, ...componentInfo.serverData };
39
- }
40
-
41
- // Render the server component
42
- const element = React.createElement(Component, props);
43
- componentInfo.rendered = renderToString(element);
44
-
45
- } catch (error) {
46
- console.error('RSC Error:', error);
47
- throw error;
48
- }
49
-
50
- return componentInfo;
51
- }
52
-
53
- /**
54
- * Creates a client component reference for RSC payload
55
- */
56
- export function createClientReference(componentPath, props) {
57
- return {
58
- $$typeof: Symbol.for('react.client.reference'),
59
- $$id: componentPath,
60
- $$props: props
61
- };
62
- }
63
-
64
- /**
65
- * Serializes RSC payload for streaming
66
- */
67
- export function serializeRSCPayload(componentTree) {
68
- const payload = {
69
- type: 'rsc',
70
- tree: serializeNode(componentTree),
71
- timestamp: Date.now()
72
- };
73
-
74
- return JSON.stringify(payload);
75
- }
76
-
77
- /**
78
- * Serializes a React node for RSC
79
- */
80
- function serializeNode(node) {
81
- if (node === null || node === undefined) {
82
- return null;
83
- }
84
-
85
- if (typeof node === 'string' || typeof node === 'number' || typeof node === 'boolean') {
86
- return node;
87
- }
88
-
89
- if (Array.isArray(node)) {
90
- return node.map(serializeNode);
91
- }
92
-
93
- if (React.isValidElement(node)) {
94
- const { type, props } = node;
95
-
96
- // Handle client component references
97
- const typeAny = type as any;
98
- if (typeAny.$$typeof === Symbol.for('react.client.reference')) {
99
- return {
100
- $$type: 'client',
101
- $$id: typeAny.$$id,
102
- props: serializeProps(props)
103
- };
104
- }
105
-
106
- // Handle regular elements
107
- const typeName = typeof type === 'string' ? type : (typeAny.displayName || typeAny.name || 'Unknown');
108
-
109
- return {
110
- $$type: 'element',
111
- type: typeName,
112
- props: serializeProps(props)
113
- };
114
- }
115
-
116
- return String(node);
117
- }
118
-
119
- /**
120
- * Serializes props, handling special cases
121
- */
122
- function serializeProps(props: Record<string, any>) {
123
- const serialized: Record<string, any> = {};
124
-
125
- for (const [key, value] of Object.entries(props)) {
126
- if (key === 'children') {
127
- serialized.children = serializeNode(value);
128
- } else if (typeof value === 'function') {
129
- // Functions can't be serialized - mark as client action
130
- serialized[key] = { $$type: 'action', name: value.name };
131
- } else if (value instanceof Date) {
132
- serialized[key] = { $$type: 'date', value: value.toISOString() };
133
- } else if (typeof value === 'object' && value !== null) {
134
- serialized[key] = JSON.parse(JSON.stringify(value));
135
- } else {
136
- serialized[key] = value;
137
- }
138
- }
139
-
140
- return serialized;
141
- }
142
-
143
- /**
144
- * Server Actions support
145
- * Allows calling server functions from client components
146
- */
147
- export function createServerAction(fn, actionId) {
148
- // Mark function as server action
149
- fn.$$typeof = Symbol.for('react.server.action');
150
- fn.$$id = actionId;
151
-
152
- return fn;
153
- }
154
-
155
- /**
156
- * Handles server action invocation
157
- */
158
- export async function handleServerAction(actionId, args, context) {
159
- // Actions are registered during build
160
- const action = globalThis.__FLEXI_ACTIONS__?.[actionId];
161
-
162
- if (!action) {
163
- throw new Error(`Server action not found: ${actionId}`);
164
- }
165
-
166
- return await action(...args, context);
167
- }
168
-
169
- /**
170
- * RSC Boundary component
171
- * Marks the boundary between server and client rendering
172
- */
173
- export function ServerBoundary({ children, fallback }) {
174
- return children;
175
- }
176
-
177
- /**
178
- * Client Boundary component
179
- * Marks components that should be hydrated on the client
180
- */
181
- export function ClientBoundary({ children, fallback }) {
182
- // On server, render children normally
183
- // On client, this will be hydrated
184
- return React.createElement('div', {
185
- 'data-flexi-client': 'true',
186
- children
187
- });
188
- }
189
-
190
- export default {
191
- processServerComponent,
192
- createClientReference,
193
- serializeRSCPayload,
194
- createServerAction,
195
- handleServerAction,
196
- ServerBoundary,
197
- ClientBoundary,
198
- RSC_CONTENT_TYPE
199
- };