@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,425 +0,0 @@
1
- /**
2
- * FlexiReact Build System
3
- * Uses esbuild for fast bundling of client and server code
4
- */
5
-
6
- import * as esbuild from 'esbuild';
7
- import fs from 'fs';
8
- import path from 'path';
9
- import { fileURLToPath } from 'url';
10
- import { findFiles, ensureDir, cleanDir, generateHash, isClientComponent, isIsland } from '../utils.js';
11
- import { buildRouteTree } from '../router/index.js';
12
-
13
- const __filename = fileURLToPath(import.meta.url);
14
- const __dirname = path.dirname(__filename);
15
-
16
- /**
17
- * Build configuration
18
- */
19
- export const BuildMode = {
20
- DEVELOPMENT: 'development',
21
- PRODUCTION: 'production'
22
- };
23
-
24
- /**
25
- * Main build function
26
- */
27
- export async function build(options) {
28
- const {
29
- projectRoot,
30
- config,
31
- mode = BuildMode.PRODUCTION,
32
- analyze = false
33
- } = options;
34
-
35
- const startTime = Date.now();
36
- const outDir = config.outDir;
37
- const isDev = mode === BuildMode.DEVELOPMENT;
38
-
39
- console.log('\n⚔ FlexiReact Build\n');
40
- console.log(` Mode: ${mode}`);
41
- console.log(` Output: ${outDir}\n`);
42
-
43
- // Clean output directory
44
- cleanDir(outDir);
45
- ensureDir(path.join(outDir, 'client'));
46
- ensureDir(path.join(outDir, 'server'));
47
- ensureDir(path.join(outDir, 'static'));
48
-
49
- // Build routes
50
- const routes = buildRouteTree(config.pagesDir, config.layoutsDir);
51
-
52
- // Find all client components and islands
53
- const clientEntries = findClientEntries(config.pagesDir, config.layoutsDir);
54
-
55
- // Build client bundle
56
- console.log('šŸ“¦ Building client bundle...');
57
- const clientResult = await buildClient({
58
- entries: clientEntries,
59
- outDir: path.join(outDir, 'client'),
60
- config,
61
- isDev
62
- });
63
-
64
- // Build server bundle
65
- console.log('šŸ“¦ Building server bundle...');
66
- const serverResult = await buildServer({
67
- pagesDir: config.pagesDir,
68
- layoutsDir: config.layoutsDir,
69
- outDir: path.join(outDir, 'server'),
70
- config,
71
- isDev
72
- });
73
-
74
- // Copy public assets
75
- console.log('šŸ“ Copying public assets...');
76
- await copyPublicAssets(config.publicDir, path.join(outDir, 'static'));
77
-
78
- // Generate manifest
79
- const manifest = generateManifest({
80
- routes,
81
- clientResult,
82
- serverResult,
83
- config
84
- });
85
-
86
- fs.writeFileSync(
87
- path.join(outDir, 'manifest.json'),
88
- JSON.stringify(manifest, null, 2)
89
- );
90
-
91
- const duration = Date.now() - startTime;
92
-
93
- console.log('\n✨ Build complete!\n');
94
- console.log(` Duration: ${duration}ms`);
95
- console.log(` Client chunks: ${clientResult.outputs.length}`);
96
- console.log(` Server modules: ${serverResult.outputs.length}`);
97
- console.log('');
98
-
99
- // Generate bundle analysis if requested
100
- let analysis = null;
101
- if (analyze) {
102
- analysis = generateBundleAnalysis(clientResult, serverResult, outDir);
103
- }
104
-
105
- return {
106
- success: true,
107
- duration,
108
- manifest,
109
- clientResult,
110
- serverResult,
111
- analysis
112
- };
113
- }
114
-
115
- /**
116
- * Generates bundle analysis data
117
- */
118
- function generateBundleAnalysis(clientResult, serverResult, outDir) {
119
- const files: Record<string, { size: number; gzipSize?: number }> = {};
120
- let totalSize = 0;
121
- let totalGzipSize = 0;
122
-
123
- // Analyze client outputs
124
- for (const output of clientResult.outputs || []) {
125
- if (output.path && fs.existsSync(output.path)) {
126
- const stat = fs.statSync(output.path);
127
- const relativePath = path.relative(outDir, output.path);
128
-
129
- // Estimate gzip size (roughly 30% of original for JS)
130
- const gzipSize = Math.round(stat.size * 0.3);
131
-
132
- files[relativePath] = {
133
- size: stat.size,
134
- gzipSize
135
- };
136
-
137
- totalSize += stat.size;
138
- totalGzipSize += gzipSize;
139
- }
140
- }
141
-
142
- // Analyze server outputs
143
- for (const output of serverResult.outputs || []) {
144
- if (output.path && fs.existsSync(output.path)) {
145
- const stat = fs.statSync(output.path);
146
- const relativePath = path.relative(outDir, output.path);
147
-
148
- files[relativePath] = {
149
- size: stat.size
150
- };
151
-
152
- totalSize += stat.size;
153
- }
154
- }
155
-
156
- return {
157
- files,
158
- totalSize,
159
- totalGzipSize,
160
- clientSize: clientResult.outputs?.reduce((sum, o) => {
161
- if (o.path && fs.existsSync(o.path)) {
162
- return sum + fs.statSync(o.path).size;
163
- }
164
- return sum;
165
- }, 0) || 0,
166
- serverSize: serverResult.outputs?.reduce((sum, o) => {
167
- if (o.path && fs.existsSync(o.path)) {
168
- return sum + fs.statSync(o.path).size;
169
- }
170
- return sum;
171
- }, 0) || 0
172
- };
173
- }
174
-
175
- /**
176
- * Finds all client component entries
177
- */
178
- function findClientEntries(pagesDir, layoutsDir) {
179
- const entries = [];
180
- const dirs = [pagesDir, layoutsDir].filter(d => fs.existsSync(d));
181
-
182
- for (const dir of dirs) {
183
- const files = findFiles(dir, /\.(jsx|tsx)$/);
184
-
185
- for (const file of files) {
186
- if (isClientComponent(file) || isIsland(file)) {
187
- entries.push(file);
188
- }
189
- }
190
- }
191
-
192
- return entries;
193
- }
194
-
195
- /**
196
- * Builds client-side JavaScript
197
- */
198
- async function buildClient(options) {
199
- const { entries, outDir, config, isDev } = options;
200
-
201
- if (entries.length === 0) {
202
- return { outputs: [] };
203
- }
204
-
205
- // Create entry points map
206
- const entryPoints = {};
207
- for (const entry of entries) {
208
- const name = path.basename(entry, path.extname(entry));
209
- const hash = generateHash(entry);
210
- entryPoints[`${name}-${hash}`] = entry;
211
- }
212
-
213
- // Add runtime entry
214
- const runtimePath = path.join(__dirname, '..', 'client', 'runtime.js');
215
- if (fs.existsSync(runtimePath)) {
216
- entryPoints['runtime'] = runtimePath;
217
- }
218
-
219
- try {
220
- const result = await esbuild.build({
221
- entryPoints,
222
- bundle: true,
223
- splitting: true,
224
- format: 'esm',
225
- outdir: outDir,
226
- minify: !isDev && config.build.minify,
227
- sourcemap: config.build.sourcemap,
228
- target: config.build.target,
229
- jsx: 'automatic',
230
- jsxImportSource: 'react',
231
- metafile: true,
232
- external: [],
233
- define: {
234
- 'process.env.NODE_ENV': JSON.stringify(isDev ? 'development' : 'production')
235
- },
236
- loader: {
237
- '.js': 'jsx',
238
- '.jsx': 'jsx',
239
- '.ts': 'tsx',
240
- '.tsx': 'tsx'
241
- }
242
- });
243
-
244
- const outputs = Object.keys(result.metafile.outputs).map(file => ({
245
- file: path.basename(file),
246
- size: result.metafile.outputs[file].bytes
247
- }));
248
-
249
- return { outputs, metafile: result.metafile };
250
-
251
- } catch (error) {
252
- console.error('Client build failed:', error);
253
- throw error;
254
- }
255
- }
256
-
257
- /**
258
- * Builds server-side modules
259
- */
260
- async function buildServer(options) {
261
- const { pagesDir, layoutsDir, outDir, config, isDev } = options;
262
-
263
- const entries = [];
264
-
265
- // Find all page and layout files
266
- for (const dir of [pagesDir, layoutsDir]) {
267
- if (fs.existsSync(dir)) {
268
- entries.push(...findFiles(dir, /\.(jsx|tsx|js|ts)$/));
269
- }
270
- }
271
-
272
- if (entries.length === 0) {
273
- return { outputs: [] };
274
- }
275
-
276
- // Create entry points
277
- const entryPoints = {};
278
- for (const entry of entries) {
279
- const relativePath = path.relative(pagesDir, entry);
280
- const name = relativePath.replace(/[\/\\]/g, '_').replace(/\.(jsx|tsx|js|ts)$/, '');
281
- entryPoints[name] = entry;
282
- }
283
-
284
- try {
285
- const result = await esbuild.build({
286
- entryPoints,
287
- bundle: true,
288
- format: 'esm',
289
- platform: 'node',
290
- outdir: outDir,
291
- minify: false, // Keep server code readable
292
- sourcemap: true,
293
- target: 'node18',
294
- jsx: 'automatic',
295
- jsxImportSource: 'react',
296
- metafile: true,
297
- packages: 'external', // Don't bundle node_modules
298
- loader: {
299
- '.js': 'jsx',
300
- '.jsx': 'jsx',
301
- '.ts': 'tsx',
302
- '.tsx': 'tsx'
303
- }
304
- });
305
-
306
- const outputs = Object.keys(result.metafile.outputs).map(file => ({
307
- file: path.basename(file),
308
- size: result.metafile.outputs[file].bytes
309
- }));
310
-
311
- return { outputs, metafile: result.metafile };
312
-
313
- } catch (error) {
314
- console.error('Server build failed:', error);
315
- throw error;
316
- }
317
- }
318
-
319
- /**
320
- * Copies public assets to output directory
321
- */
322
- async function copyPublicAssets(publicDir, outDir) {
323
- if (!fs.existsSync(publicDir)) {
324
- return;
325
- }
326
-
327
- const copyRecursive = (src, dest) => {
328
- const entries = fs.readdirSync(src, { withFileTypes: true });
329
-
330
- ensureDir(dest);
331
-
332
- for (const entry of entries) {
333
- const srcPath = path.join(src, entry.name);
334
- const destPath = path.join(dest, entry.name);
335
-
336
- if (entry.isDirectory()) {
337
- copyRecursive(srcPath, destPath);
338
- } else {
339
- fs.copyFileSync(srcPath, destPath);
340
- }
341
- }
342
- };
343
-
344
- copyRecursive(publicDir, outDir);
345
- }
346
-
347
- /**
348
- * Generates build manifest
349
- */
350
- function generateManifest(options) {
351
- const { routes, clientResult, serverResult, config } = options;
352
-
353
- return {
354
- version: '2.0.0',
355
- generatedAt: new Date().toISOString(),
356
- routes: {
357
- pages: routes.pages.map(r => ({
358
- path: r.path,
359
- file: r.filePath,
360
- hasLayout: !!r.layout,
361
- hasLoading: !!r.loading,
362
- hasError: !!r.error
363
- })),
364
- api: routes.api.map(r => ({
365
- path: r.path,
366
- file: r.filePath
367
- }))
368
- },
369
- client: {
370
- chunks: clientResult.outputs || []
371
- },
372
- server: {
373
- modules: serverResult.outputs || []
374
- },
375
- config: {
376
- islands: config.islands.enabled,
377
- rsc: config.rsc.enabled
378
- }
379
- };
380
- }
381
-
382
- /**
383
- * Development build with watch mode
384
- */
385
- export async function buildDev(options) {
386
- const { projectRoot, config, onChange } = options;
387
-
388
- const outDir = config.outDir;
389
- ensureDir(outDir);
390
-
391
- // Use esbuild's watch mode
392
- const ctx = await esbuild.context({
393
- entryPoints: findFiles(config.pagesDir, /\.(jsx|tsx)$/),
394
- bundle: true,
395
- format: 'esm',
396
- outdir: path.join(outDir, 'dev'),
397
- sourcemap: true,
398
- jsx: 'automatic',
399
- jsxImportSource: 'react',
400
- loader: {
401
- '.js': 'jsx',
402
- '.jsx': 'jsx'
403
- },
404
- plugins: [{
405
- name: 'flexi-watch',
406
- setup(build) {
407
- build.onEnd(result => {
408
- if (result.errors.length === 0) {
409
- onChange?.();
410
- }
411
- });
412
- }
413
- }]
414
- });
415
-
416
- await ctx.watch();
417
-
418
- return ctx;
419
- }
420
-
421
- export default {
422
- build,
423
- buildDev,
424
- BuildMode
425
- };