vite-plugin-smart-prefetch 0.4.0 → 0.4.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.
package/dist/index.cjs CHANGED
@@ -574,7 +574,7 @@ ${"\u2550".repeat(60)}`);
574
574
  }
575
575
  };
576
576
 
577
- // src/plugin/model/guessjs-ml-trainer.ts
577
+ // src/plugin/model/prefetch-ml-trainer.ts
578
578
  var MarkovChainTrainer = class {
579
579
  constructor(config, debug = false) {
580
580
  this.config = config;
@@ -754,57 +754,6 @@ var MarkovChainTrainer = class {
754
754
  topDestination
755
755
  };
756
756
  }
757
- /**
758
- * Train segment-specific Markov models from navigation data with segment field
759
- * Creates separate models for each user segment/role
760
- */
761
- trainSegmentedModels(navigationDataWithSegments, environment) {
762
- if (this.debug) {
763
- console.log(`
764
- \u{1F916} Training Segment-Specific Markov Models...`);
765
- }
766
- const dataBySegment = /* @__PURE__ */ new Map();
767
- navigationDataWithSegments.forEach((data) => {
768
- const segment = data.segment || "default";
769
- if (!dataBySegment.has(segment)) {
770
- dataBySegment.set(segment, []);
771
- }
772
- dataBySegment.get(segment).push({
773
- from: data.from,
774
- to: data.to,
775
- count: data.count
776
- });
777
- });
778
- if (this.debug) {
779
- console.log(`
780
- \u{1F4CA} Detected segments:`);
781
- dataBySegment.forEach((data, segment) => {
782
- console.log(` \u2022 ${segment}: ${data.length} transitions`);
783
- });
784
- }
785
- const segmentModels = /* @__PURE__ */ new Map();
786
- dataBySegment.forEach((navigationData, segment) => {
787
- if (this.debug) {
788
- console.log(`
789
- \u{1F504} Training model for segment: "${segment}"`);
790
- }
791
- const model = this.trainMLModel(navigationData, environment);
792
- model.dataSource.provider = `markov-chain[${segment}]`;
793
- segmentModels.set(segment, model);
794
- if (this.debug) {
795
- const totalTargets = Object.values(model.routes).reduce(
796
- (sum, route) => sum + (route.prefetch?.length || 0),
797
- 0
798
- );
799
- console.log(` \u2705 Model for "${segment}" trained with ${totalTargets} prefetch targets`);
800
- }
801
- });
802
- if (this.debug) {
803
- console.log(`
804
- \u2705 All ${segmentModels.size} segment models trained successfully`);
805
- }
806
- return segmentModels;
807
- }
808
757
  /**
809
758
  * Get date range string
810
759
  */
@@ -837,7 +786,6 @@ var ConfigGenerator = class {
837
786
  }
838
787
  /**
839
788
  * Generate final prefetch configuration with chunk mappings
840
- * Includes common prefetch rules and segment-specific rules if available
841
789
  */
842
790
  generate(model) {
843
791
  if (this.debug) {
@@ -846,9 +794,6 @@ var ConfigGenerator = class {
846
794
  console.log(` Manifest entries: ${Object.keys(this.manifest).length}`);
847
795
  console.log(` Model routes: ${Object.keys(model.routes).length}`);
848
796
  console.log(` Manual rules: ${Object.keys(this.manualRules).length}`);
849
- if (Object.values(model.routes).some((r) => r.segments)) {
850
- console.log(` \u2139\uFE0F Segment-based rules detected`);
851
- }
852
797
  }
853
798
  const mergedModel = this.mergeManualRules(model);
854
799
  const routePatterns = this.extractRoutePatterns(Object.keys(mergedModel.routes));
@@ -869,10 +814,8 @@ var ConfigGenerator = class {
869
814
  };
870
815
  let mappedRoutes = 0;
871
816
  let unmappedRoutes = 0;
872
- let totalSegmentRules = 0;
873
817
  Object.entries(mergedModel.routes).forEach(([sourceRoute, prediction]) => {
874
818
  const prefetchTargets = [];
875
- const segmentConfigs = {};
876
819
  const sourceChunk = this.routeToChunk(sourceRoute);
877
820
  if (sourceChunk && !config.chunks[sourceRoute]) {
878
821
  config.chunks[sourceRoute] = sourceChunk;
@@ -911,46 +854,12 @@ var ConfigGenerator = class {
911
854
  unmappedRoutes++;
912
855
  }
913
856
  });
914
- if (prediction.segments) {
915
- Object.entries(prediction.segments).forEach(([segment, segmentTargets]) => {
916
- const segmentPrefetchTargets = [];
917
- segmentTargets.forEach((target) => {
918
- const chunkFile = this.routeToChunk(target.route);
919
- if (chunkFile) {
920
- const manifestEntry = this.getManifestEntryByFile(chunkFile);
921
- const importChunkIds = manifestEntry?.imports || [];
922
- const imports = importChunkIds.map((chunkId) => {
923
- const entry = this.manifest[chunkId];
924
- return entry?.file;
925
- }).filter((file) => !!file);
926
- segmentPrefetchTargets.push({
927
- ...target,
928
- chunk: chunkFile,
929
- chunk_prod: chunkFile,
930
- // NEW: Include production chunk path
931
- imports
932
- });
933
- config.chunks[target.route] = chunkFile;
934
- totalSegmentRules++;
935
- }
936
- });
937
- if (segmentPrefetchTargets.length > 0) {
938
- segmentConfigs[segment] = segmentPrefetchTargets;
939
- }
940
- });
941
- if (this.debug && Object.keys(segmentConfigs).length > 0) {
942
- console.log(` \u{1F465} Segment configs for ${sourceRoute}: ${Object.keys(segmentConfigs).join(", ")}`);
943
- }
944
- }
945
857
  const patterns = routePatterns[sourceRoute] || [sourceRoute];
946
- if (prefetchTargets.length > 0 || Object.keys(segmentConfigs).length > 0) {
858
+ if (prefetchTargets.length > 0) {
947
859
  config.routes[sourceRoute] = {
948
860
  patterns,
949
- // NEW: Include patterns for dynamic route matching
861
+ // Include patterns for dynamic route matching
950
862
  prefetch: prefetchTargets,
951
- ...Object.keys(segmentConfigs).length > 0 && {
952
- segments: segmentConfigs
953
- },
954
863
  metadata: prediction.metadata
955
864
  };
956
865
  }
@@ -959,21 +868,8 @@ var ConfigGenerator = class {
959
868
  console.log(`\u2705 Configuration generated`);
960
869
  console.log(` Routes with prefetch: ${Object.keys(config.routes).length}`);
961
870
  console.log(` Mapped chunks: ${mappedRoutes}`);
962
- console.log(` Segment-specific rules: ${totalSegmentRules}`);
963
871
  console.log(` Unmapped routes: ${unmappedRoutes}`);
964
872
  }
965
- const allSegments = /* @__PURE__ */ new Set();
966
- Object.values(config.routes).forEach((route) => {
967
- if (route.segments) {
968
- Object.keys(route.segments).forEach((seg) => allSegments.add(seg));
969
- }
970
- });
971
- if (allSegments.size > 0) {
972
- config.segmentInfo = {
973
- available: Array.from(allSegments),
974
- description: "Load segment-specific config based on user role/segment"
975
- };
976
- }
977
873
  return config;
978
874
  }
979
875
  /**
@@ -1167,32 +1063,6 @@ var ConfigGenerator = class {
1167
1063
  }
1168
1064
  return null;
1169
1065
  }
1170
- /**
1171
- * Generate segment-specific prefetch configurations
1172
- * Creates one config per user segment/role
1173
- */
1174
- generateSegmentConfigs(segmentModels) {
1175
- const segmentConfigs = /* @__PURE__ */ new Map();
1176
- segmentModels.forEach((model, segment) => {
1177
- if (this.debug) {
1178
- console.log(`
1179
- \u{1F4E6} Generating config for segment: "${segment}"`);
1180
- }
1181
- const config = this.generate(model);
1182
- config.segment = segment;
1183
- segmentConfigs.set(segment, config);
1184
- if (this.debug) {
1185
- console.log(` \u2705 Config generated for "${segment}"`);
1186
- console.log(` Routes: ${Object.keys(config.routes).length}`);
1187
- console.log(` Chunks: ${Object.keys(config.chunks).length}`);
1188
- }
1189
- });
1190
- if (this.debug) {
1191
- console.log(`
1192
- \u2705 Generated ${segmentConfigs.size} segment-specific configurations`);
1193
- }
1194
- return segmentConfigs;
1195
- }
1196
1066
  };
1197
1067
 
1198
1068
  // src/plugin/cache-manager.ts
@@ -1368,7 +1238,6 @@ function smartPrefetch(options = {}) {
1368
1238
  let config;
1369
1239
  let cacheManager;
1370
1240
  let prefetchModel = null;
1371
- let segmentModels = null;
1372
1241
  return {
1373
1242
  name: "@farmart/vite-plugin-smart-prefetch",
1374
1243
  enforce: "post",
@@ -1449,9 +1318,6 @@ function smartPrefetch(options = {}) {
1449
1318
  res.setHeader("Access-Control-Allow-Origin", "*");
1450
1319
  res.setHeader("Cache-Control", "no-cache, no-store, must-revalidate");
1451
1320
  res.end(JSON.stringify(finalConfig, null, 2));
1452
- if (debug) {
1453
- console.log("\u{1F4E4} Serving fresh prefetch-config.json from development server");
1454
- }
1455
1321
  return;
1456
1322
  } catch (error) {
1457
1323
  if (debug) {
@@ -1489,37 +1355,30 @@ function smartPrefetch(options = {}) {
1489
1355
  debug,
1490
1356
  analytics.credentials.keyFilePath
1491
1357
  );
1492
- console.log("\n\u{1F3AF} Using real navigation data from BigQuery GA4 export...");
1358
+ if (debug) {
1359
+ console.log("\n\u{1F3AF} Using real navigation data from BigQuery GA4 export...");
1360
+ }
1493
1361
  const navigationData = await bqConnector.fetchNavigationSequences(analytics.dataRange);
1494
1362
  if (navigationData.length === 0) {
1495
1363
  console.warn("\u26A0\uFE0F No navigation data found, using manual rules only");
1496
1364
  prefetchModel = createManualModel(manualRules, environment);
1497
1365
  return;
1498
1366
  }
1499
- console.log(`
1367
+ if (debug) {
1368
+ console.log(`
1500
1369
  \u{1F916} Training model using Markov Chain ML...`);
1370
+ }
1501
1371
  const mlTrainer = new MarkovChainTrainer(analytics.model, debug);
1502
1372
  const prefetchModelResult = mlTrainer.trainMLModel(navigationData, environment);
1503
1373
  prefetchModel = prefetchModelResult;
1504
1374
  await cacheManager.set(environment, prefetchModel);
1505
- try {
1506
- const navigationWithSegments = await bqConnector.fetchNavigationWithSegments(analytics.dataRange);
1507
- if (navigationWithSegments.length > 0) {
1508
- console.log(`
1509
- \u{1F465} Training segment-specific models...`);
1510
- segmentModels = mlTrainer.trainSegmentedModels(navigationWithSegments, environment);
1511
- if (debug && segmentModels.size > 0) {
1512
- console.log(` \u2705 Trained ${segmentModels.size} segment-specific models`);
1513
- }
1514
- }
1515
- } catch (error) {
1516
- if (debug) {
1517
- console.warn(`\u26A0\uFE0F Could not train segment models:`, error instanceof Error ? error.message : "Unknown error");
1518
- }
1519
- }
1520
1375
  } catch (error) {
1521
- console.error("\u274C Failed to fetch analytics data:", error);
1522
- console.log("\u26A0\uFE0F Falling back to manual rules only");
1376
+ if (debug) {
1377
+ console.error("\u274C Failed to fetch analytics data:", error);
1378
+ }
1379
+ if (debug) {
1380
+ console.log("\u26A0\uFE0F Falling back to manual rules only");
1381
+ }
1523
1382
  prefetchModel = createManualModel(manualRules, environment);
1524
1383
  if (debug) {
1525
1384
  console.error("Error details:", error);
@@ -1528,7 +1387,9 @@ function smartPrefetch(options = {}) {
1528
1387
  },
1529
1388
  async writeBundle(outputOptions) {
1530
1389
  if (!prefetchModel) {
1531
- console.warn("\u26A0\uFE0F No prefetch model available, skipping config generation");
1390
+ if (debug) {
1391
+ console.warn("\u26A0\uFE0F No prefetch model available, skipping config generation");
1392
+ }
1532
1393
  return;
1533
1394
  }
1534
1395
  const fs2 = await import("fs");
@@ -1536,7 +1397,9 @@ function smartPrefetch(options = {}) {
1536
1397
  const outDir = outputOptions.dir || "dist";
1537
1398
  const manifestPath = path2.join(outDir, ".vite", "manifest.json");
1538
1399
  if (!fs2.existsSync(manifestPath)) {
1539
- console.warn("\u26A0\uFE0F Vite manifest not found at:", manifestPath);
1400
+ if (debug) {
1401
+ console.warn("\u26A0\uFE0F Vite manifest not found at:", manifestPath);
1402
+ }
1540
1403
  return;
1541
1404
  }
1542
1405
  const manifestContent = fs2.readFileSync(manifestPath, "utf-8");
@@ -1548,10 +1411,10 @@ function smartPrefetch(options = {}) {
1548
1411
  const generator = new ConfigGenerator(manifest, manualRules, debug);
1549
1412
  const finalConfig = generator.generate(prefetchModel);
1550
1413
  const validation = generator.validateChunks(finalConfig);
1551
- if (!validation.valid) {
1414
+ if (!validation.valid && debug) {
1552
1415
  console.warn("\u26A0\uFE0F Some chunks could not be mapped:");
1553
1416
  validation.missing.forEach((m) => console.warn(` ${m}`));
1554
- } else {
1417
+ } else if (debug) {
1555
1418
  console.log(`\u2705 All ${Object.keys(finalConfig.chunks).length} chunks successfully mapped with real build hashes`);
1556
1419
  }
1557
1420
  const configPath = path2.join(outDir, "prefetch-config.json");
@@ -1564,37 +1427,6 @@ function smartPrefetch(options = {}) {
1564
1427
  console.log(`\u{1F4CA} Total routes configured: ${Object.keys(finalConfig.routes).length}`);
1565
1428
  console.log(`\u{1F4E6} Total chunks: ${Object.keys(finalConfig.chunks).length}`);
1566
1429
  }
1567
- if (segmentModels && segmentModels.size > 0) {
1568
- console.log(`
1569
- \u{1F4C1} Generating segment-specific prefetch configurations...`);
1570
- const segmentGenerator = new ConfigGenerator(manifest, manualRules, debug);
1571
- const segmentConfigs = segmentGenerator.generateSegmentConfigs(segmentModels);
1572
- const segmentDir = path2.join(outDir, "prefetch-configs");
1573
- if (!fs2.existsSync(segmentDir)) {
1574
- fs2.mkdirSync(segmentDir, { recursive: true });
1575
- }
1576
- segmentConfigs.forEach((segConfig, segment) => {
1577
- const segmentPath = path2.join(segmentDir, `${segment}.json`);
1578
- fs2.writeFileSync(segmentPath, JSON.stringify(segConfig, null, 2));
1579
- if (debug) {
1580
- console.log(` \u2705 Emitted ${segment}.json (${Object.keys(segConfig.routes).length} routes)`);
1581
- }
1582
- });
1583
- const segmentIndex = {
1584
- generatedAt: (/* @__PURE__ */ new Date()).toISOString(),
1585
- environment: analytics?.environment || (config.command === "serve" ? "development" : "production"),
1586
- segments: Array.from(segmentConfigs.keys()),
1587
- description: "Segment-specific prefetch configurations. Use based on user role/segment."
1588
- };
1589
- const segmentIndexPath = path2.join(segmentDir, "index.json");
1590
- fs2.writeFileSync(segmentIndexPath, JSON.stringify(segmentIndex, null, 2));
1591
- if (debug) {
1592
- console.log(`
1593
- \u2705 Emitted ${segmentConfigs.size} segment-specific configurations`);
1594
- console.log(` Location: ${segmentDir}`);
1595
- console.log(` Segments: ${Array.from(segmentConfigs.keys()).join(", ")}`);
1596
- }
1597
- }
1598
1430
  if (analytics?.dashboard) {
1599
1431
  const dashboardHtml = generateDashboard(finalConfig);
1600
1432
  const dashboardPath = path2.join(outDir, "prefetch-report.html");