@flexireact/core 1.0.1 → 2.0.0

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 (37) hide show
  1. package/README.md +117 -116
  2. package/bin/flexireact.js +23 -0
  3. package/cli/index.ts +9 -21
  4. package/core/cli/{logger.js → logger.ts} +8 -2
  5. package/core/client/{hydration.js → hydration.ts} +10 -0
  6. package/core/client/{islands.js → islands.ts} +6 -1
  7. package/core/client/{navigation.js → navigation.ts} +10 -2
  8. package/core/client/{runtime.js → runtime.ts} +16 -0
  9. package/core/{index.js → index.ts} +2 -1
  10. package/core/islands/{index.js → index.ts} +16 -4
  11. package/core/{logger.js → logger.ts} +1 -1
  12. package/core/middleware/{index.js → index.ts} +32 -9
  13. package/core/plugins/{index.js → index.ts} +9 -6
  14. package/core/render/index.ts +1069 -0
  15. package/core/{render.js → render.ts} +7 -5
  16. package/core/router/index.ts +543 -0
  17. package/core/rsc/{index.js → index.ts} +6 -5
  18. package/core/server/{index.js → index.ts} +25 -6
  19. package/core/{server.js → server.ts} +8 -2
  20. package/core/ssg/{index.js → index.ts} +30 -5
  21. package/core/start-dev.ts +6 -0
  22. package/core/start-prod.ts +6 -0
  23. package/core/tsconfig.json +28 -0
  24. package/core/types.ts +239 -0
  25. package/package.json +19 -14
  26. package/cli/index.js +0 -992
  27. package/core/render/index.js +0 -765
  28. package/core/router/index.js +0 -296
  29. /package/core/{api.js → api.ts} +0 -0
  30. /package/core/build/{index.js → index.ts} +0 -0
  31. /package/core/client/{index.js → index.ts} +0 -0
  32. /package/core/{config.js → config.ts} +0 -0
  33. /package/core/{context.js → context.ts} +0 -0
  34. /package/core/{dev.js → dev.ts} +0 -0
  35. /package/core/{loader.js → loader.ts} +0 -0
  36. /package/core/{router.js → router.ts} +0 -0
  37. /package/core/{utils.js → utils.ts} +0 -0
@@ -1,296 +0,0 @@
1
- /**
2
- * FlexiReact Router v2
3
- * Advanced file-based routing with nested routes, loading, and error boundaries
4
- */
5
-
6
- import fs from 'fs';
7
- import path from 'path';
8
- import { isServerComponent, isClientComponent, isIsland } from '../utils.js';
9
-
10
- /**
11
- * Route types
12
- */
13
- export const RouteType = {
14
- PAGE: 'page',
15
- API: 'api',
16
- LAYOUT: 'layout',
17
- LOADING: 'loading',
18
- ERROR: 'error',
19
- NOT_FOUND: 'not-found'
20
- };
21
-
22
- /**
23
- * Builds the complete route tree from pages directory
24
- */
25
- export function buildRouteTree(pagesDir, layoutsDir) {
26
- const routes = {
27
- pages: [],
28
- api: [],
29
- layouts: new Map(),
30
- tree: {}
31
- };
32
-
33
- if (!fs.existsSync(pagesDir)) {
34
- return routes;
35
- }
36
-
37
- // Scan pages directory
38
- scanDirectory(pagesDir, pagesDir, routes);
39
-
40
- // Scan layouts directory
41
- if (fs.existsSync(layoutsDir)) {
42
- scanLayouts(layoutsDir, routes.layouts);
43
- }
44
-
45
- // Build route tree for nested routes
46
- routes.tree = buildTree(routes.pages);
47
-
48
- return routes;
49
- }
50
-
51
- /**
52
- * Scans directory recursively for route files
53
- */
54
- function scanDirectory(baseDir, currentDir, routes, parentSegments = []) {
55
- const entries = fs.readdirSync(currentDir, { withFileTypes: true });
56
-
57
- // First, find special files in current directory
58
- const specialFiles = {
59
- layout: null,
60
- loading: null,
61
- error: null,
62
- notFound: null
63
- };
64
-
65
- for (const entry of entries) {
66
- if (entry.isFile()) {
67
- const name = entry.name.replace(/\.(jsx|js|tsx|ts)$/, '');
68
- const fullPath = path.join(currentDir, entry.name);
69
-
70
- if (name === 'layout') specialFiles.layout = fullPath;
71
- if (name === 'loading') specialFiles.loading = fullPath;
72
- if (name === 'error') specialFiles.error = fullPath;
73
- if (name === 'not-found' || name === '404') specialFiles.notFound = fullPath;
74
- }
75
- }
76
-
77
- for (const entry of entries) {
78
- const fullPath = path.join(currentDir, entry.name);
79
- const relativePath = path.relative(baseDir, fullPath);
80
-
81
- if (entry.isDirectory()) {
82
- // Handle route groups (parentheses)
83
- const isGroup = entry.name.startsWith('(') && entry.name.endsWith(')');
84
- const newSegments = isGroup ? parentSegments : [...parentSegments, entry.name];
85
-
86
- scanDirectory(baseDir, fullPath, routes, newSegments);
87
- } else if (entry.isFile()) {
88
- const ext = path.extname(entry.name);
89
- const baseName = path.basename(entry.name, ext);
90
-
91
- // Skip special files (already processed)
92
- if (['layout', 'loading', 'error', 'not-found', '404'].includes(baseName)) {
93
- continue;
94
- }
95
-
96
- if (['.jsx', '.js', '.tsx', '.ts'].includes(ext)) {
97
- const isApi = relativePath.startsWith('api' + path.sep) || relativePath.startsWith('api/');
98
-
99
- if (isApi && ['.js', '.ts'].includes(ext)) {
100
- routes.api.push(createRoute(fullPath, baseDir, specialFiles, RouteType.API));
101
- } else if (!isApi && ['.jsx', '.tsx'].includes(ext)) {
102
- routes.pages.push(createRoute(fullPath, baseDir, specialFiles, RouteType.PAGE));
103
- }
104
- }
105
- }
106
- }
107
- }
108
-
109
- /**
110
- * Creates a route object from file path
111
- */
112
- function createRoute(filePath, baseDir, specialFiles, type) {
113
- const relativePath = path.relative(baseDir, filePath);
114
- const routePath = filePathToRoute(relativePath);
115
-
116
- return {
117
- type,
118
- path: routePath,
119
- filePath,
120
- pattern: createRoutePattern(routePath),
121
- segments: routePath.split('/').filter(Boolean),
122
- layout: specialFiles.layout,
123
- loading: specialFiles.loading,
124
- error: specialFiles.error,
125
- notFound: specialFiles.notFound,
126
- isServerComponent: isServerComponent(filePath),
127
- isClientComponent: isClientComponent(filePath),
128
- isIsland: isIsland(filePath)
129
- };
130
- }
131
-
132
- /**
133
- * Scans layouts directory
134
- */
135
- function scanLayouts(layoutsDir, layoutsMap) {
136
- const entries = fs.readdirSync(layoutsDir, { withFileTypes: true });
137
-
138
- for (const entry of entries) {
139
- if (entry.isFile() && /\.(jsx|tsx)$/.test(entry.name)) {
140
- const name = entry.name.replace(/\.(jsx|tsx)$/, '');
141
- layoutsMap.set(name, path.join(layoutsDir, entry.name));
142
- }
143
- }
144
- }
145
-
146
- /**
147
- * Converts file path to route path
148
- */
149
- function filePathToRoute(filePath) {
150
- let route = filePath.replace(/\\/g, '/');
151
-
152
- // Remove extension
153
- route = route.replace(/\.(jsx|js|tsx|ts)$/, '');
154
-
155
- // Convert [param] to :param
156
- route = route.replace(/\[\.\.\.([^\]]+)\]/g, '*$1'); // Catch-all [...slug]
157
- route = route.replace(/\[([^\]]+)\]/g, ':$1');
158
-
159
- // Handle index files
160
- if (route.endsWith('/index')) {
161
- route = route.slice(0, -6) || '/';
162
- } else if (route === 'index') {
163
- route = '/';
164
- }
165
-
166
- // Handle route groups - remove (groupName) from path
167
- route = route.replace(/\/?\([^)]+\)\/?/g, '/');
168
-
169
- // Ensure leading slash and clean up
170
- if (!route.startsWith('/')) {
171
- route = '/' + route;
172
- }
173
- route = route.replace(/\/+/g, '/');
174
-
175
- return route;
176
- }
177
-
178
- /**
179
- * Creates regex pattern for route matching
180
- */
181
- function createRoutePattern(routePath) {
182
- let pattern = routePath
183
- .replace(/\*[^/]*/g, '(.*)') // Catch-all
184
- .replace(/:[^/]+/g, '([^/]+)') // Dynamic segments
185
- .replace(/\//g, '\\/');
186
-
187
- return new RegExp(`^${pattern}$`);
188
- }
189
-
190
- /**
191
- * Builds a tree structure for nested routes
192
- */
193
- function buildTree(routes) {
194
- const tree = { children: {}, routes: [] };
195
-
196
- for (const route of routes) {
197
- let current = tree;
198
-
199
- for (const segment of route.segments) {
200
- if (!current.children[segment]) {
201
- current.children[segment] = { children: {}, routes: [] };
202
- }
203
- current = current.children[segment];
204
- }
205
-
206
- current.routes.push(route);
207
- }
208
-
209
- return tree;
210
- }
211
-
212
- /**
213
- * Matches URL path against routes
214
- */
215
- export function matchRoute(urlPath, routes) {
216
- const normalizedPath = urlPath === '' ? '/' : urlPath.split('?')[0];
217
-
218
- for (const route of routes) {
219
- const match = normalizedPath.match(route.pattern);
220
-
221
- if (match) {
222
- const params = extractParams(route.path, match);
223
- return { ...route, params };
224
- }
225
- }
226
-
227
- return null;
228
- }
229
-
230
- /**
231
- * Extracts parameters from route match
232
- */
233
- function extractParams(routePath, match) {
234
- const params = {};
235
- const paramNames = [];
236
-
237
- // Extract param names from route path
238
- const paramRegex = /:([^/]+)|\*([^/]*)/g;
239
- let paramMatch;
240
-
241
- while ((paramMatch = paramRegex.exec(routePath)) !== null) {
242
- paramNames.push(paramMatch[1] || paramMatch[2] || 'splat');
243
- }
244
-
245
- paramNames.forEach((name, index) => {
246
- params[name] = match[index + 1];
247
- });
248
-
249
- return params;
250
- }
251
-
252
- /**
253
- * Finds all layouts that apply to a route
254
- */
255
- export function findRouteLayouts(route, layoutsMap) {
256
- const layouts = [];
257
-
258
- // Check for segment-based layouts
259
- let currentPath = '';
260
- for (const segment of route.segments) {
261
- currentPath += '/' + segment;
262
- const layoutName = segment;
263
-
264
- if (layoutsMap.has(layoutName)) {
265
- layouts.push({
266
- name: layoutName,
267
- filePath: layoutsMap.get(layoutName)
268
- });
269
- }
270
- }
271
-
272
- // Check for route-specific layout
273
- if (route.layout) {
274
- layouts.push({
275
- name: 'route',
276
- filePath: route.layout
277
- });
278
- }
279
-
280
- // Check for root layout
281
- if (layoutsMap.has('root')) {
282
- layouts.unshift({
283
- name: 'root',
284
- filePath: layoutsMap.get('root')
285
- });
286
- }
287
-
288
- return layouts;
289
- }
290
-
291
- export default {
292
- buildRouteTree,
293
- matchRoute,
294
- findRouteLayouts,
295
- RouteType
296
- };
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes