@flight-framework/bundler-flightpack 0.1.3 → 0.1.5

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.
package/dist/index.js CHANGED
@@ -42,7 +42,7 @@ function flightpack(options = {}) {
42
42
  port,
43
43
  publicDir: resolvePath(config.root, "public"),
44
44
  outDir: resolvePath(config.root, config.build.outDir),
45
- hmr: options.hmr ?? true,
45
+ hmr: typeof options.hmr === "boolean" ? options.hmr : options.hmr !== void 0 ? true : true,
46
46
  root: config.root
47
47
  });
48
48
  logDevServerStarted(result.url, "FlightPack");
@@ -110,28 +110,265 @@ function flightpack(options = {}) {
110
110
  async build(config) {
111
111
  const native = await loadNativeBinding();
112
112
  const timer = createTimer();
113
+ const { existsSync } = await import("fs");
114
+ const { mkdir, copyFile, writeFile, readFile } = await import("fs/promises");
115
+ const { join, basename, relative } = await import("path");
116
+ const resolvedOptions = {
117
+ minify: typeof options.minify === "boolean" ? options.minify : config.build.minify !== false && config.build.minify !== void 0,
118
+ sourcemap: typeof options.sourcemap === "boolean" ? options.sourcemap : config.build.sourcemap !== false && config.build.sourcemap !== void 0,
119
+ treeshake: typeof options.treeshake === "boolean" ? options.treeshake : typeof options.treeshake === "object" ? options.treeshake.enabled : true,
120
+ splitting: typeof options.splitting === "boolean" ? options.splitting : typeof options.splitting === "object" ? options.splitting.enabled : true,
121
+ cache: typeof options.cache === "boolean" ? options.cache : typeof options.cache === "object" ? options.cache.enabled : true,
122
+ cacheDir: options.cacheDir ?? (typeof options.cache === "object" ? options.cache.directory : void 0) ?? ".flightpack_cache",
123
+ rsc: options.rsc ?? true,
124
+ target: options.target ?? "es2022",
125
+ external: options.external ?? [],
126
+ noExternal: options.noExternal ?? []
127
+ };
128
+ const baseOutDir = resolvePath(config.root, config.build.outDir);
129
+ const cacheDir = resolvePath(config.root, resolvedOptions.cacheDir);
130
+ const allFiles = [];
131
+ let totalSize = 0;
132
+ let cacheHits = 0;
133
+ let cacheMisses = 0;
113
134
  try {
114
- const minifyOption = typeof options.minify === "boolean" ? options.minify : typeof config.build.minify === "boolean" ? config.build.minify : true;
115
- const flightpackOptions = {
116
- entry: await getEntryPoints(config),
117
- outDir: resolvePath(config.root, config.build.outDir),
135
+ await cleanDirectory(baseOutDir);
136
+ console.log("\n\u250C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510");
137
+ console.log("\u2502 \u26A1 FlightPack Production Build \u2502");
138
+ console.log("\u251C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524");
139
+ console.log(`\u2502 Tree Shaking: ${resolvedOptions.treeshake ? "\u2713 InnerGraph (statement-level)" : "\u2717 disabled"} `);
140
+ console.log(`\u2502 Code Splitting: ${resolvedOptions.splitting ? "\u2713 ChunkSplitter" : "\u2717 disabled"} `);
141
+ console.log(`\u2502 Caching: ${resolvedOptions.cache ? "\u2713 TurboCache + ArtifactStore" : "\u2717 disabled"} `);
142
+ console.log(`\u2502 Target: ${resolvedOptions.target} `);
143
+ console.log("\u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518\n");
144
+ console.log("\u26A1 Phase 1/6: Building client bundle...");
145
+ const clientEntries = await getEntryPoints(config, "client");
146
+ const clientOutDir = join(baseOutDir, "client", "assets");
147
+ await mkdir(clientOutDir, { recursive: true });
148
+ const browserConditions = native.getPlatformConditions("browser");
149
+ const clientOptions = {
150
+ entry: clientEntries,
151
+ outDir: clientOutDir,
118
152
  root: config.root,
119
- minify: minifyOption,
120
- sourcemap: typeof options.sourcemap === "boolean" ? options.sourcemap : typeof config.build.sourcemap === "boolean" ? config.build.sourcemap : true,
121
- rsc: options.rsc ?? true
153
+ minify: resolvedOptions.minify,
154
+ sourcemap: resolvedOptions.sourcemap,
155
+ rsc: resolvedOptions.rsc,
156
+ // Full capabilities
157
+ treeshake: resolvedOptions.treeshake,
158
+ splitting: resolvedOptions.splitting,
159
+ cache: resolvedOptions.cache,
160
+ cacheDir,
161
+ platform: "browser",
162
+ external: [],
163
+ // Browser bundles include everything
164
+ target: resolvedOptions.target
122
165
  };
123
- const result = await native.build(flightpackOptions);
124
- const files = result.chunks.map((chunk) => ({
125
- path: chunk.fileName,
126
- size: chunk.size,
127
- type: chunk.chunkType,
128
- isDynamicEntry: false
129
- }));
166
+ const clientResult = await native.build(clientOptions);
167
+ for (const chunk of clientResult.chunks) {
168
+ allFiles.push({
169
+ path: `client/assets/${chunk.fileName}`,
170
+ size: chunk.size,
171
+ type: chunk.chunkType,
172
+ isDynamicEntry: false
173
+ });
174
+ totalSize += chunk.size;
175
+ }
176
+ console.log(` \u2713 Client: ${clientResult.chunks.length} chunks (${formatBytes(clientResult.totalSize)})`);
177
+ const isSSR = config.rendering?.default !== "csr";
178
+ if (isSSR) {
179
+ console.log("\u26A1 Phase 2/6: Building server bundle (SSR)...");
180
+ const serverEntries = await getEntryPoints(config, "server");
181
+ const serverOutDir = join(baseOutDir, "server");
182
+ await mkdir(serverOutDir, { recursive: true });
183
+ const nodeBuiltins = native.getNodeBuiltins();
184
+ const serverExternals = [
185
+ ...nodeBuiltins,
186
+ ...resolvedOptions.external
187
+ ].filter((ext) => !resolvedOptions.noExternal.includes(ext));
188
+ const serverOptions = {
189
+ entry: serverEntries,
190
+ outDir: serverOutDir,
191
+ root: config.root,
192
+ minify: false,
193
+ // Server bundles: keep readable for debugging
194
+ sourcemap: resolvedOptions.sourcemap,
195
+ rsc: resolvedOptions.rsc,
196
+ treeshake: resolvedOptions.treeshake,
197
+ splitting: false,
198
+ // Single SSR bundle recommended
199
+ cache: resolvedOptions.cache,
200
+ cacheDir,
201
+ platform: "node",
202
+ external: serverExternals,
203
+ target: "es2022"
204
+ // Node 18+ supports ES2022
205
+ };
206
+ const serverResult = await native.build(serverOptions);
207
+ for (const chunk of serverResult.chunks) {
208
+ allFiles.push({
209
+ path: `server/${chunk.fileName}`,
210
+ size: chunk.size,
211
+ type: chunk.chunkType,
212
+ isDynamicEntry: false
213
+ });
214
+ totalSize += chunk.size;
215
+ }
216
+ console.log(` \u2713 Server: ${serverResult.chunks.length} chunks (${formatBytes(serverResult.totalSize)})`);
217
+ } else {
218
+ console.log("\u26A1 Phase 2/6: Skipped (CSR mode)");
219
+ }
220
+ const hasEdgeConfig = options.environments?.edge;
221
+ if (hasEdgeConfig) {
222
+ console.log("\u26A1 Phase 3/6: Building edge bundle...");
223
+ const edgeOutDir = join(baseOutDir, "edge");
224
+ await mkdir(edgeOutDir, { recursive: true });
225
+ const edgeIncompatible = native.getEdgeIncompatibleModules();
226
+ const edgeOptions = {
227
+ entry: hasEdgeConfig.entry ?? await getEntryPoints(config, "server"),
228
+ outDir: edgeOutDir,
229
+ root: config.root,
230
+ minify: true,
231
+ sourcemap: resolvedOptions.sourcemap,
232
+ rsc: resolvedOptions.rsc,
233
+ treeshake: true,
234
+ // Always tree shake edge bundles
235
+ splitting: false,
236
+ cache: resolvedOptions.cache,
237
+ cacheDir,
238
+ platform: "edge",
239
+ external: edgeIncompatible,
240
+ target: "es2022"
241
+ };
242
+ const edgeResult = await native.build(edgeOptions);
243
+ for (const chunk of edgeResult.chunks) {
244
+ allFiles.push({
245
+ path: `edge/${chunk.fileName}`,
246
+ size: chunk.size,
247
+ type: chunk.chunkType,
248
+ isDynamicEntry: false
249
+ });
250
+ totalSize += chunk.size;
251
+ }
252
+ console.log(` \u2713 Edge: ${edgeResult.chunks.length} chunks (${formatBytes(edgeResult.totalSize)})`);
253
+ } else {
254
+ console.log("\u26A1 Phase 3/6: Skipped (no edge config)");
255
+ }
256
+ console.log("\u26A1 Phase 4/6: Processing CSS...");
257
+ const cssFiles = await findCssFiles(config.root);
258
+ let cssProcessed = 0;
259
+ if (cssFiles.length > 0) {
260
+ const cssOutDir = join(baseOutDir, "client", "assets");
261
+ await mkdir(cssOutDir, { recursive: true });
262
+ const cssOptions = typeof options.css === "object" ? options.css : {};
263
+ const cssTargets = "targets" in cssOptions ? cssOptions.targets : void 0;
264
+ for (const cssFile of cssFiles) {
265
+ try {
266
+ const cssContent = await readFile(cssFile, "utf-8");
267
+ const isCssModule = cssFile.includes(".module.");
268
+ let processedCss;
269
+ let classMap = [];
270
+ if (isCssModule) {
271
+ const result = native.transformCssModule(cssContent, cssFile);
272
+ processedCss = result.code;
273
+ classMap = result.classMap;
274
+ } else {
275
+ const result = native.transformCss(cssContent, cssFile, {
276
+ minify: resolvedOptions.minify,
277
+ cssModules: false,
278
+ sourcemap: resolvedOptions.sourcemap,
279
+ browserTargets: cssTargets
280
+ });
281
+ processedCss = result.code;
282
+ }
283
+ const outFileName = basename(cssFile);
284
+ const outPath = join(cssOutDir, outFileName);
285
+ await writeFile(outPath, processedCss);
286
+ if (resolvedOptions.sourcemap) {
287
+ }
288
+ allFiles.push({
289
+ path: `client/assets/${outFileName}`,
290
+ size: processedCss.length,
291
+ type: "asset",
292
+ isDynamicEntry: false
293
+ });
294
+ totalSize += processedCss.length;
295
+ cssProcessed++;
296
+ } catch (e) {
297
+ console.warn(` \u26A0 Warning: CSS processing failed for ${basename(cssFile)}`);
298
+ }
299
+ }
300
+ }
301
+ console.log(` \u2713 CSS: ${cssProcessed} files processed`);
302
+ console.log("\u26A1 Phase 5/6: Copying static assets...");
303
+ let assetsCount = 0;
304
+ const htmlSource = join(config.root, "index.html");
305
+ const htmlDest = join(baseOutDir, "client", "index.html");
306
+ if (existsSync(htmlSource)) {
307
+ await mkdir(join(baseOutDir, "client"), { recursive: true });
308
+ let htmlContent = await readFile(htmlSource, "utf-8");
309
+ const clientEntry = clientResult.chunks.find((c) => c.chunkType === "entry");
310
+ if (clientEntry) {
311
+ htmlContent = htmlContent.replace(
312
+ "</body>",
313
+ ` <script type="module" src="/assets/${clientEntry.fileName}"></script>
314
+ </body>`
315
+ );
316
+ }
317
+ await writeFile(htmlDest, htmlContent);
318
+ allFiles.push({
319
+ path: "client/index.html",
320
+ size: htmlContent.length,
321
+ type: "asset",
322
+ isDynamicEntry: false
323
+ });
324
+ assetsCount++;
325
+ }
326
+ const publicDir = join(config.root, "public");
327
+ if (existsSync(publicDir)) {
328
+ const copied = await copyDirectoryRecursive(publicDir, join(baseOutDir, "client"));
329
+ assetsCount += copied;
330
+ }
331
+ console.log(` \u2713 Assets: ${assetsCount} files copied`);
332
+ if (resolvedOptions.rsc && isSSR) {
333
+ console.log("\u26A1 Phase 6/6: Generating RSC manifests...");
334
+ const clientManifest = {
335
+ ssrModuleMapping: {},
336
+ edgeSSRModuleMapping: {},
337
+ clientModules: {},
338
+ entryCSSFiles: {}
339
+ };
340
+ const serverManifest = {
341
+ node: {},
342
+ edge: {}
343
+ };
344
+ await writeFile(
345
+ join(baseOutDir, "client", "react-client-manifest.json"),
346
+ JSON.stringify(clientManifest, null, 2)
347
+ );
348
+ await writeFile(
349
+ join(baseOutDir, "server", "react-server-manifest.json"),
350
+ JSON.stringify(serverManifest, null, 2)
351
+ );
352
+ console.log(" \u2713 RSC manifests generated");
353
+ } else {
354
+ console.log("\u26A1 Phase 6/6: Skipped (RSC disabled or CSR mode)");
355
+ }
356
+ const duration = timer.stop();
357
+ console.log("\n\u250C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510");
358
+ console.log("\u2502 Build Summary \u2502");
359
+ console.log("\u251C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524");
360
+ console.log(`\u2502 Duration: ${duration}ms `);
361
+ console.log(`\u2502 Total Size: ${formatBytes(totalSize)} `);
362
+ console.log(`\u2502 Files: ${allFiles.length} `);
363
+ if (resolvedOptions.cache) {
364
+ console.log(`\u2502 Cache: ${cacheDir} `);
365
+ }
366
+ console.log("\u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518\n");
130
367
  const buildResult = {
131
- outDir: result.outputDir,
132
- duration: timer.stop(),
133
- files,
134
- totalSize: result.totalSize,
368
+ outDir: baseOutDir,
369
+ duration,
370
+ files: allFiles,
371
+ totalSize,
135
372
  errors: [],
136
373
  warnings: [],
137
374
  success: true
@@ -140,7 +377,7 @@ function flightpack(options = {}) {
140
377
  return buildResult;
141
378
  } catch (error) {
142
379
  const buildResult = {
143
- outDir: resolvePath(config.root, config.build.outDir),
380
+ outDir: baseOutDir,
144
381
  duration: timer.stop(),
145
382
  files: [],
146
383
  totalSize: 0,
@@ -268,40 +505,104 @@ function flightpack(options = {}) {
268
505
  }
269
506
  return adapter;
270
507
  }
271
- async function getEntryPoints(config) {
508
+ async function getEntryPoints(config, type = "client") {
272
509
  const entries = [];
273
510
  const { existsSync } = await import("fs");
274
511
  const { join } = await import("path");
275
- const possibleEntries = [
276
- // Standard Flight entries
277
- "src/entry-client.tsx",
278
- "src/entry-client.ts",
279
- // Vite-style entries
280
- "src/main.tsx",
281
- "src/main.ts",
282
- // App-style entries
283
- "src/App.tsx",
284
- "src/App.ts",
285
- "src/app.tsx",
286
- "src/app.ts",
287
- // Index-style entries
288
- "src/index.tsx",
289
- "src/index.ts"
290
- ];
291
- for (const entry of possibleEntries) {
292
- const fullPath = join(config.root, entry);
293
- if (existsSync(fullPath)) {
294
- entries.push(entry);
295
- break;
512
+ if (type === "server") {
513
+ const serverEntries = [
514
+ "src/entry-server.tsx",
515
+ "src/entry-server.ts",
516
+ "src/server.tsx",
517
+ "src/server.ts"
518
+ ];
519
+ for (const entry of serverEntries) {
520
+ const fullPath = join(config.root, entry);
521
+ if (existsSync(fullPath)) {
522
+ entries.push(entry);
523
+ break;
524
+ }
525
+ }
526
+ if (entries.length === 0) {
527
+ entries.push("src/entry-server.tsx");
528
+ }
529
+ } else {
530
+ const clientEntries = [
531
+ "src/entry-client.tsx",
532
+ "src/entry-client.ts",
533
+ "src/main.tsx",
534
+ "src/main.ts",
535
+ "src/App.tsx",
536
+ "src/App.ts",
537
+ "src/app.tsx",
538
+ "src/app.ts",
539
+ "src/index.tsx",
540
+ "src/index.ts"
541
+ ];
542
+ for (const entry of clientEntries) {
543
+ const fullPath = join(config.root, entry);
544
+ if (existsSync(fullPath)) {
545
+ entries.push(entry);
546
+ break;
547
+ }
548
+ }
549
+ if (entries.length === 0) {
550
+ entries.push("src/index.tsx");
296
551
  }
297
- }
298
- if (entries.length === 0) {
299
- entries.push("src/index.tsx");
300
552
  }
301
553
  return entries;
302
554
  }
555
+ async function findCssFiles(root) {
556
+ const { readdir, stat } = await import("fs/promises");
557
+ const { join } = await import("path");
558
+ const cssFiles = [];
559
+ async function walkDir(dir) {
560
+ try {
561
+ const items = await readdir(dir);
562
+ for (const item of items) {
563
+ if (item === "node_modules" || item.startsWith(".")) continue;
564
+ const itemPath = join(dir, item);
565
+ const itemStat = await stat(itemPath);
566
+ if (itemStat.isDirectory()) {
567
+ await walkDir(itemPath);
568
+ } else if (item.endsWith(".css")) {
569
+ cssFiles.push(itemPath);
570
+ }
571
+ }
572
+ } catch {
573
+ }
574
+ }
575
+ await walkDir(join(root, "src"));
576
+ return cssFiles;
577
+ }
578
+ async function copyDirectoryRecursive(src, dest) {
579
+ const { mkdir, readdir, copyFile, stat } = await import("fs/promises");
580
+ const { join } = await import("path");
581
+ await mkdir(dest, { recursive: true });
582
+ let count = 0;
583
+ const items = await readdir(src);
584
+ for (const item of items) {
585
+ const srcPath = join(src, item);
586
+ const destPath = join(dest, item);
587
+ const itemStat = await stat(srcPath);
588
+ if (itemStat.isDirectory()) {
589
+ count += await copyDirectoryRecursive(srcPath, destPath);
590
+ } else {
591
+ await copyFile(srcPath, destPath);
592
+ count++;
593
+ }
594
+ }
595
+ return count;
596
+ }
597
+ function formatBytes(bytes) {
598
+ if (bytes === 0) return "0 B";
599
+ const k = 1024;
600
+ const sizes = ["B", "KB", "MB", "GB"];
601
+ const i = Math.floor(Math.log(bytes) / Math.log(k));
602
+ return `${parseFloat((bytes / Math.pow(k, i)).toFixed(2))} ${sizes[i]}`;
603
+ }
303
604
  var index_default = flightpack;
304
- var VERSION = "0.0.1";
605
+ var VERSION = "0.1.4";
305
606
  export {
306
607
  VERSION,
307
608
  flightpack as createFlightPackAdapter,