heliumts 0.8.5 → 0.8.7

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 (42) hide show
  1. package/dist/bin/helium.js +0 -0
  2. package/dist/client/Router.d.ts.map +1 -1
  3. package/dist/client/Router.js +35 -7
  4. package/dist/client/Router.js.map +1 -1
  5. package/dist/server/defineServerSideProps.d.ts +11 -1
  6. package/dist/server/defineServerSideProps.d.ts.map +1 -1
  7. package/dist/server/defineServerSideProps.js.map +1 -1
  8. package/dist/server/defineWorker.d.ts +6 -1
  9. package/dist/server/defineWorker.d.ts.map +1 -1
  10. package/dist/server/defineWorker.js +67 -8
  11. package/dist/server/defineWorker.js.map +1 -1
  12. package/dist/server/devServer.d.ts.map +1 -1
  13. package/dist/server/devServer.js +79 -62
  14. package/dist/server/devServer.js.map +1 -1
  15. package/dist/server/ipExtractor.d.ts +48 -0
  16. package/dist/server/ipExtractor.d.ts.map +1 -0
  17. package/dist/server/ipExtractor.js +96 -0
  18. package/dist/server/ipExtractor.js.map +1 -0
  19. package/dist/server/prodServer.d.ts.map +1 -1
  20. package/dist/server/prodServer.js +21 -6
  21. package/dist/server/prodServer.js.map +1 -1
  22. package/dist/server/requestRouting.d.ts +4 -0
  23. package/dist/server/requestRouting.d.ts.map +1 -0
  24. package/dist/server/requestRouting.js +67 -0
  25. package/dist/server/requestRouting.js.map +1 -0
  26. package/dist/server/ssr.d.ts +26 -4
  27. package/dist/server/ssr.d.ts.map +1 -1
  28. package/dist/server/ssr.js +48 -5
  29. package/dist/server/ssr.js.map +1 -1
  30. package/dist/utils/deepEqual.d.ts +1 -0
  31. package/dist/utils/deepEqual.d.ts.map +1 -0
  32. package/dist/utils/deepEqual.js +2 -0
  33. package/dist/utils/deepEqual.js.map +1 -0
  34. package/dist/utils/formatError.d.ts +2 -0
  35. package/dist/utils/formatError.d.ts.map +1 -0
  36. package/dist/utils/formatError.js +18 -0
  37. package/dist/utils/formatError.js.map +1 -0
  38. package/package.json +1 -1
  39. package/dist/server/serverPropsRouter.d.ts +0 -1
  40. package/dist/server/serverPropsRouter.d.ts.map +0 -1
  41. package/dist/server/serverPropsRouter.js +0 -2
  42. package/dist/server/serverPropsRouter.js.map +0 -1
File without changes
@@ -1 +1 @@
1
- {"version":3,"file":"Router.d.ts","sourceRoot":"","sources":["../../src/client/Router.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,OAAO,CAAC;AAC3C,OAAO,KAAuD,MAAM,OAAO,CAAC;AA2D5E,KAAK,WAAW,GAAG,YAAY,GAAG,mBAAmB,CAAC;AACtD,KAAK,aAAa,GAAG,CAAC,KAAK,EAAE;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,EAAE,EAAE,MAAM,CAAC;IAAC,cAAc,CAAC,EAAE,MAAM,IAAI,CAAA;CAAE,KAAK,IAAI,CAAC;AAiKhG,kDAAkD;AAClD,MAAM,WAAW,uBAAuB;IACpC,qDAAqD;IACrD,WAAW,CAAC,EAAE,OAAO,CAAC;CACzB;AAGD,KAAK,aAAa,GAAG;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC,CAAC;IAC1C,YAAY,EAAE,eAAe,CAAC;IAC9B,IAAI,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,uBAAuB,KAAK,IAAI,CAAC;IAChE,OAAO,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,uBAAuB,KAAK,IAAI,CAAC;IACnE,EAAE,EAAE,CAAC,KAAK,EAAE,WAAW,EAAE,QAAQ,EAAE,aAAa,KAAK,MAAM,IAAI,CAAC;IAChE,MAAM,EAAE,GAAG,GAAG,GAAG,CAAC;IAClB,YAAY,EAAE,OAAO,CAAC;IACtB,8GAA8G;IAC9G,SAAS,EAAE,OAAO,CAAC;CACtB,CAAC;AAEF,eAAO,MAAM,aAAa,qCAAkD,CAAC;AAE7E;;;;;;;;GAQG;AACH,wBAAgB,SAAS,kBAmCxB;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,QAAQ,CAAC,EAAE,EAAE,EAAE,OAAe,EAAE,EAAE;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,OAAO,CAAA;CAAE,QAyBlF;AA6CD,MAAM,MAAM,SAAS,GAAG,KAAK,CAAC,iBAAiB,CAC3C,IAAI,CAAC,KAAK,CAAC,oBAAoB,CAAC,iBAAiB,CAAC,EAAE,MAAM,CAAC,GAAG;IAC1D,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,0EAA0E;IAC1E,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,qDAAqD;IACrD,WAAW,CAAC,EAAE,OAAO,CAAC;CACzB,CACJ,CAAC;AA+BF;;;;;;;;;GASG;AACH,wBAAgB,IAAI,CAAC,KAAK,EAAE,SAAS,2CA4DpC;AAGD;;;;GAIG;AACH,MAAM,MAAM,aAAa,CAAC,UAAU,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,IAAI;IAC9F,SAAS,EAAE,aAAa,CAAC,UAAU,CAAC,CAAC;IACrC,SAAS,EAAE,UAAU,CAAC;IACtB,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;CAC9B,CAAC;AAGF,wBAAgB,SAAS,CAAC,EAAE,QAAQ,EAAE,EAAE;IAAE,QAAQ,CAAC,EAAE,aAAa,CAAC,aAAa,CAAC,CAAA;CAAE,2CA0KlF"}
1
+ {"version":3,"file":"Router.d.ts","sourceRoot":"","sources":["../../src/client/Router.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,OAAO,CAAC;AAC3C,OAAO,KAAuD,MAAM,OAAO,CAAC;AA6F5E,KAAK,WAAW,GAAG,YAAY,GAAG,mBAAmB,CAAC;AACtD,KAAK,aAAa,GAAG,CAAC,KAAK,EAAE;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,EAAE,EAAE,MAAM,CAAC;IAAC,cAAc,CAAC,EAAE,MAAM,IAAI,CAAA;CAAE,KAAK,IAAI,CAAC;AAiKhG,kDAAkD;AAClD,MAAM,WAAW,uBAAuB;IACpC,qDAAqD;IACrD,WAAW,CAAC,EAAE,OAAO,CAAC;CACzB;AAGD,KAAK,aAAa,GAAG;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC,CAAC;IAC1C,YAAY,EAAE,eAAe,CAAC;IAC9B,IAAI,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,uBAAuB,KAAK,IAAI,CAAC;IAChE,OAAO,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,uBAAuB,KAAK,IAAI,CAAC;IACnE,EAAE,EAAE,CAAC,KAAK,EAAE,WAAW,EAAE,QAAQ,EAAE,aAAa,KAAK,MAAM,IAAI,CAAC;IAChE,MAAM,EAAE,GAAG,GAAG,GAAG,CAAC;IAClB,YAAY,EAAE,OAAO,CAAC;IACtB,8GAA8G;IAC9G,SAAS,EAAE,OAAO,CAAC;CACtB,CAAC;AAEF,eAAO,MAAM,aAAa,qCAAkD,CAAC;AAE7E;;;;;;;;GAQG;AACH,wBAAgB,SAAS,kBAmCxB;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,QAAQ,CAAC,EAAE,EAAE,EAAE,OAAe,EAAE,EAAE;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,OAAO,CAAA;CAAE,QAyBlF;AA6CD,MAAM,MAAM,SAAS,GAAG,KAAK,CAAC,iBAAiB,CAC3C,IAAI,CAAC,KAAK,CAAC,oBAAoB,CAAC,iBAAiB,CAAC,EAAE,MAAM,CAAC,GAAG;IAC1D,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,0EAA0E;IAC1E,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,qDAAqD;IACrD,WAAW,CAAC,EAAE,OAAO,CAAC;CACzB,CACJ,CAAC;AA+BF;;;;;;;;;GASG;AACH,wBAAgB,IAAI,CAAC,KAAK,EAAE,SAAS,2CA4DpC;AAGD;;;;GAIG;AACH,MAAM,MAAM,aAAa,CAAC,UAAU,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,IAAI;IAC9F,SAAS,EAAE,aAAa,CAAC,UAAU,CAAC,CAAC;IACrC,SAAS,EAAE,UAAU,CAAC;IACtB,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;CAC9B,CAAC;AAGF,wBAAgB,SAAS,CAAC,EAAE,QAAQ,EAAE,EAAE;IAAE,QAAQ,CAAC,EAAE,aAAa,CAAC,aAAa,CAAC,CAAA;CAAE,2CA8LlF"}
@@ -24,16 +24,28 @@ async function fetchSSRPageProps(path) {
24
24
  },
25
25
  });
26
26
  if (!response.ok) {
27
- return null;
27
+ return { kind: "none" };
28
28
  }
29
29
  const payload = (await response.json());
30
- if (!payload.ssr || !payload.props) {
31
- return null;
30
+ if (!payload.ssr) {
31
+ return { kind: "none" };
32
32
  }
33
- return payload.props;
33
+ if (payload.redirect && typeof payload.redirect.destination === "string" && payload.redirect.destination.length > 0) {
34
+ return {
35
+ kind: "redirect",
36
+ redirect: payload.redirect,
37
+ };
38
+ }
39
+ if (!payload.props) {
40
+ return { kind: "none" };
41
+ }
42
+ return {
43
+ kind: "props",
44
+ props: payload.props,
45
+ };
34
46
  }
35
47
  catch {
36
- return null;
48
+ return { kind: "none" };
37
49
  }
38
50
  }
39
51
  class RouterEventEmitter {
@@ -431,11 +443,27 @@ export function AppRouter({ AppShell }) {
431
443
  }
432
444
  let cancelled = false;
433
445
  const load = async () => {
434
- const props = await fetchSSRPageProps(targetPath);
446
+ const ssrPayload = await fetchSSRPageProps(targetPath);
435
447
  if (cancelled) {
436
448
  return;
437
449
  }
438
- setRuntimeSSRProps(props ?? {});
450
+ if (ssrPayload.kind === "redirect") {
451
+ const destination = ssrPayload.redirect.destination;
452
+ if (isExternalUrl(destination)) {
453
+ window.location.assign(destination);
454
+ return;
455
+ }
456
+ navigate(destination, {
457
+ replace: ssrPayload.redirect.replace ?? true,
458
+ scrollToTop: true,
459
+ });
460
+ return;
461
+ }
462
+ if (ssrPayload.kind === "props") {
463
+ setRuntimeSSRProps(ssrPayload.props);
464
+ return;
465
+ }
466
+ setRuntimeSSRProps({});
439
467
  };
440
468
  void load();
441
469
  return () => {
@@ -1 +1 @@
1
- {"version":3,"file":"Router.js","sourceRoot":"","sources":["../../src/client/Router.tsx"],"names":[],"mappings":";AACA,OAAO,KAAK,EAAE,EAAE,OAAO,EAAE,oBAAoB,EAAE,aAAa,EAAE,MAAM,OAAO,CAAC;AAE5E,OAAO,EAAE,uBAAuB,EAAE,MAAM,+BAA+B,CAAC;AACxE,OAAO,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAC;AAE5C,OAAO,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAClD,OAAO,EAAE,yBAAyB,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AAOlG,SAAS,sBAAsB;IAC3B,IAAI,OAAO,MAAM,KAAK,WAAW,EAAE,CAAC;QAChC,OAAO,IAAI,CAAC;IAChB,CAAC;IAED,MAAM,YAAY,GAAG,MAEpB,CAAC;IAEF,MAAM,OAAO,GAAG,YAAY,CAAC,mBAAmB,CAAC;IACjD,IAAI,CAAC,OAAO,IAAI,OAAO,OAAO,KAAK,QAAQ,IAAI,OAAO,OAAO,CAAC,IAAI,KAAK,QAAQ,IAAI,OAAO,OAAO,CAAC,KAAK,KAAK,QAAQ,IAAI,OAAO,CAAC,KAAK,KAAK,IAAI,EAAE,CAAC;QAC7I,OAAO,IAAI,CAAC;IAChB,CAAC;IAED,OAAO,OAAO,CAAC;AACnB,CAAC;AAED,KAAK,UAAU,iBAAiB,CAAC,IAAY;IACzC,IAAI,CAAC;QACD,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,+BAA+B,kBAAkB,CAAC,IAAI,CAAC,EAAE,EAAE;YACpF,MAAM,EAAE,KAAK;YACb,OAAO,EAAE;gBACL,MAAM,EAAE,kBAAkB;aAC7B;SACJ,CAAC,CAAC;QAEH,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;YACf,OAAO,IAAI,CAAC;QAChB,CAAC;QAED,MAAM,OAAO,GAAG,CAAC,MAAM,QAAQ,CAAC,IAAI,EAAE,CAGrC,CAAC;QAEF,IAAI,CAAC,OAAO,CAAC,GAAG,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC;YACjC,OAAO,IAAI,CAAC;QAChB,CAAC;QAED,OAAO,OAAO,CAAC,KAAK,CAAC;IACzB,CAAC;IAAC,MAAM,CAAC;QACL,OAAO,IAAI,CAAC;IAChB,CAAC;AACL,CAAC;AAMD,MAAM,kBAAkB;IAAxB;QACY,cAAS,GAAyC,IAAI,GAAG,EAAE,CAAC;IAsCxE,CAAC;IApCG,EAAE,CAAC,KAAkB,EAAE,QAAuB;QAC1C,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC;YAC7B,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,KAAK,EAAE,IAAI,GAAG,EAAE,CAAC,CAAC;QACzC,CAAC;QACD,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,KAAK,CAAE,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QAEzC,8BAA8B;QAC9B,OAAO,GAAG,EAAE;YACR,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC,QAAQ,CAAC,CAAC;QAChD,CAAC,CAAC;IACN,CAAC;IAED,IAAI,CAAC,KAAkB,EAAE,IAAkC;QACvD,MAAM,cAAc,GAAG,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;QACjD,IAAI,CAAC,cAAc,IAAI,cAAc,CAAC,IAAI,KAAK,CAAC,EAAE,CAAC;YAC/C,OAAO,IAAI,CAAC;QAChB,CAAC;QAED,IAAI,SAAS,GAAG,KAAK,CAAC;QACtB,MAAM,cAAc,GAAG,GAAG,EAAE;YACxB,SAAS,GAAG,IAAI,CAAC;QACrB,CAAC,CAAC;QAEF,MAAM,SAAS,GAAG,KAAK,KAAK,mBAAmB,CAAC,CAAC,CAAC,EAAE,GAAG,IAAI,EAAE,cAAc,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;QAErF,cAAc,CAAC,OAAO,CAAC,CAAC,QAAQ,EAAE,EAAE;YAChC,QAAQ,CAAC,SAAS,CAAC,CAAC;QACxB,CAAC,CAAC,CAAC;QAEH,OAAO,CAAC,SAAS,CAAC;IACtB,CAAC;IAED,uCAAuC;IACvC,KAAK;QACD,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,CAAC;IAC3B,CAAC;CACJ;AAED,uEAAuE;AACvE,IAAI,kBAAsC,CAAC;AAE3C,IAAI,OAAO,MAAM,KAAK,WAAW,IAAI,gBAAgB,EAAE,EAAE,CAAC;IACtD,0DAA0D;IAC1D,MAAM,YAAY,GAAG,MAAwE,CAAC;IAC9F,IAAI,CAAC,YAAY,CAAC,qBAAqB,EAAE,CAAC;QACtC,YAAY,CAAC,qBAAqB,GAAG,IAAI,kBAAkB,EAAE,CAAC;IAClE,CAAC;IACD,kBAAkB,GAAG,YAAY,CAAC,qBAAqB,CAAC;AAC5D,CAAC;KAAM,CAAC;IACJ,kBAAkB,GAAG,IAAI,kBAAkB,EAAE,CAAC;AAClD,CAAC;AAQD,SAAS,WAAW;IAChB,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,GAAG,MAAM,CAAC,QAAQ,CAAC;IAC7C,OAAO;QACH,IAAI,EAAE,QAAQ;QACd,YAAY,EAAE,IAAI,eAAe,CAAC,MAAM,CAAC;QACzC,YAAY,EAAE,KAAK;KACtB,CAAC;AACN,CAAC;AAED,SAAS,UAAU,CAAC,IAAY,EAAE,MAAoB;IAClD,KAAK,MAAM,CAAC,IAAI,MAAM,EAAE,CAAC;QACrB,MAAM,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;QAC1B,IAAI,CAAC,EAAE,CAAC;YACJ,OAAO,EAAE,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC;QAC1C,CAAC;IACL,CAAC;IACD,OAAO,IAAI,CAAC;AAChB,CAAC;AAED,0CAA0C;AAC1C,yDAAyD;AACzD,IAAI,eAA4B,CAAC;AACjC,IAAI,iBAAkC,CAAC;AAEvC,IAAI,OAAO,MAAM,KAAK,WAAW,IAAI,gBAAgB,EAAE,EAAE,CAAC;IACtD,MAAM,YAAY,GAAG,MAGpB,CAAC;IACF,IAAI,CAAC,YAAY,CAAC,uBAAuB,EAAE,CAAC;QACxC,YAAY,CAAC,uBAAuB,GAAG,WAAW,EAAE,CAAC;IACzD,CAAC;IACD,IAAI,CAAC,YAAY,CAAC,yBAAyB,EAAE,CAAC;QAC1C,YAAY,CAAC,yBAAyB,GAAG,IAAI,GAAG,EAAE,CAAC;IACvD,CAAC;IACD,eAAe,GAAG,YAAY,CAAC,uBAAuB,CAAC;IACvD,iBAAiB,GAAG,YAAY,CAAC,yBAAyB,CAAC;AAC/D,CAAC;KAAM,IAAI,OAAO,MAAM,KAAK,WAAW,EAAE,CAAC;IACvC,eAAe,GAAG,WAAW,EAAE,CAAC;IAChC,iBAAiB,GAAG,IAAI,GAAG,EAAE,CAAC;AAClC,CAAC;KAAM,CAAC;IACJ,eAAe,GAAG,EAAE,IAAI,EAAE,GAAG,EAAE,YAAY,EAAE,IAAI,eAAe,EAAE,EAAE,YAAY,EAAE,KAAK,EAAE,CAAC;IAC1F,iBAAiB,GAAG,IAAI,GAAG,EAAE,CAAC;AAClC,CAAC;AAED,uEAAuE;AACvE,SAAS,qBAAqB,CAAC,IAAY;IACvC,IAAI,OAAO,MAAM,KAAK,WAAW,IAAI,gBAAgB,EAAE,EAAE,CAAC;QACtD,MAAM,YAAY,GAAG,MAAiE,CAAC;QACvF,MAAM,MAAM,GAAG,YAAY,CAAC,oBAAoB,CAAC;QACjD,IAAI,MAAM,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC9B,MAAM,KAAK,GAAG,UAAU,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;YACvC,IAAI,KAAK,EAAE,CAAC;gBACR,OAAO,KAAK,CAAC,MAAM,CAAC;YACxB,CAAC;QACL,CAAC;IACL,CAAC;IACD,OAAO,EAAE,CAAC;AACd,CAAC;AAED,SAAS,mBAAmB,CAAC,QAAoB;IAC7C,iBAAiB,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;IAChC,OAAO,GAAG,EAAE,CAAC,iBAAiB,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;AACpD,CAAC;AAED,SAAS,mBAAmB;IACxB,OAAO,eAAe,CAAC;AAC3B,CAAC;AAED,MAAM,eAAe,GAAgB,EAAE,IAAI,EAAE,GAAG,EAAE,YAAY,EAAE,IAAI,eAAe,EAAE,EAAE,YAAY,EAAE,KAAK,EAAE,CAAC;AAC7G,SAAS,iBAAiB;IACtB,OAAO,eAAe,CAAC;AAC3B,CAAC;AAED,SAAS,cAAc,CAAC,YAAY,GAAG,KAAK;IACxC,MAAM,WAAW,GAAG,EAAE,GAAG,WAAW,EAAE,EAAE,YAAY,EAAE,CAAC;IACvD,eAAe,GAAG,WAAW,CAAC;IAC9B,0CAA0C;IAC1C,IAAI,OAAO,MAAM,KAAK,WAAW,IAAI,gBAAgB,EAAE,EAAE,CAAC;QACrD,MAAoE,CAAC,uBAAuB,GAAG,WAAW,CAAC;IAChH,CAAC;IACD,iBAAiB,CAAC,OAAO,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,QAAQ,EAAE,CAAC,CAAC;AACxD,CAAC;AAED,+BAA+B;AAC/B,IAAI,OAAO,MAAM,KAAK,WAAW,EAAE,CAAC;IAChC,iCAAiC;IACjC,MAAM,YAAY,GAAG,MAAqE,CAAC;IAC3F,IAAI,CAAC,YAAY,CAAC,6BAA6B,EAAE,CAAC;QAC9C,YAAY,CAAC,6BAA6B,GAAG,IAAI,CAAC;QAElD,MAAM,CAAC,gBAAgB,CAAC,UAAU,EAAE,GAAG,EAAE,CAAC,cAAc,CAAC,KAAK,CAAC,CAAC,CAAC;QAEjE,oDAAoD;QACpD,kBAAkB,CAAC,EAAE,CAAC,YAAY,EAAE,GAAG,EAAE,CAAC,cAAc,CAAC,KAAK,CAAC,CAAC,CAAC;IACrE,CAAC;AACL,CAAC;AAsBD,MAAM,CAAC,MAAM,aAAa,GAAG,KAAK,CAAC,aAAa,CAAuB,IAAI,CAAC,CAAC;AAE7E;;;;;;;;GAQG;AACH,MAAM,UAAU,SAAS;IACrB,MAAM,GAAG,GAAG,KAAK,CAAC,UAAU,CAAC,aAAa,CAAC,CAAC;IAC5C,IAAI,CAAC,GAAG,EAAE,CAAC;QACP,sEAAsE;QACtE,gEAAgE;QAChE,0DAA0D;QAC1D,IAAI,OAAO,MAAM,KAAK,WAAW,IAAI,gBAAgB,EAAE,EAAE,CAAC;YACtD,MAAM,WAAW,GAAG,MAAM,CAAC,QAAQ,CAAC,QAAQ,CAAC;YAC7C,OAAO;gBACH,IAAI,EAAE,WAAW;gBACjB,MAAM,EAAE,qBAAqB,CAAC,WAAW,CAAC;gBAC1C,YAAY,EAAE,IAAI,eAAe,CAAC,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC;gBACzD,IAAI,EAAE,CAAC,IAAY,EAAE,OAAiC,EAAE,EAAE;oBACtD,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,EAAE,EAAE,EAAE,EAAE,IAAI,CAAC,CAAC;oBACvC,IAAI,OAAO,EAAE,WAAW,KAAK,KAAK,EAAE,CAAC;wBACjC,MAAM,CAAC,QAAQ,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,QAAQ,EAAE,QAAQ,EAAE,CAAC,CAAC;oBAC7D,CAAC;oBACD,MAAM,CAAC,aAAa,CAAC,IAAI,aAAa,CAAC,UAAU,CAAC,CAAC,CAAC;gBACxD,CAAC;gBACD,OAAO,EAAE,CAAC,IAAY,EAAE,OAAiC,EAAE,EAAE;oBACzD,MAAM,CAAC,OAAO,CAAC,YAAY,CAAC,EAAE,EAAE,EAAE,EAAE,IAAI,CAAC,CAAC;oBAC1C,IAAI,OAAO,EAAE,WAAW,KAAK,KAAK,EAAE,CAAC;wBACjC,MAAM,CAAC,QAAQ,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,QAAQ,EAAE,QAAQ,EAAE,CAAC,CAAC;oBAC7D,CAAC;oBACD,MAAM,CAAC,aAAa,CAAC,IAAI,aAAa,CAAC,UAAU,CAAC,CAAC,CAAC;gBACxD,CAAC;gBACD,EAAE,EAAE,GAAG,EAAE,CAAC,GAAG,EAAE,GAAE,CAAC;gBAClB,MAAM,EAAE,GAAY;gBACpB,YAAY,EAAE,KAAK;gBACnB,SAAS,EAAE,KAAK;aACnB,CAAC;QACN,CAAC;QACD,MAAM,IAAI,KAAK,CAAC,2CAA2C,CAAC,CAAC;IACjE,CAAC;IACD,OAAO,GAAG,CAAC;AACf,CAAC;AAED;;;;;;;;;;GAUG;AACH,MAAM,UAAU,QAAQ,CAAC,EAAE,EAAE,EAAE,OAAO,GAAG,KAAK,EAAqC;IAC/E,MAAM,aAAa,GAAG,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IAE1C,+CAA+C;IAC/C,KAAK,CAAC,eAAe,CAAC,GAAG,EAAE;QACvB,MAAM,UAAU,GAAG,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;QACpC,IAAI,CAAC,aAAa,CAAC,OAAO,IAAI,MAAM,CAAC,QAAQ,CAAC,QAAQ,KAAK,UAAU,EAAE,CAAC;YACpE,aAAa,CAAC,OAAO,GAAG,IAAI,CAAC;YAE7B,qBAAqB;YACrB,IAAI,OAAO,EAAE,CAAC;gBACV,MAAM,CAAC,OAAO,CAAC,YAAY,CAAC,IAAI,EAAE,EAAE,EAAE,EAAE,CAAC,CAAC;YAC9C,CAAC;iBAAM,CAAC;gBACJ,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,IAAI,EAAE,EAAE,EAAE,EAAE,CAAC,CAAC;YAC3C,CAAC;YAED,+CAA+C;YAC/C,kBAAkB,CAAC,IAAI,CAAC,YAAY,EAAE;gBAClC,IAAI,EAAE,MAAM,CAAC,QAAQ,CAAC,QAAQ;gBAC9B,EAAE,EAAE,UAAU;aACjB,CAAC,CAAC;QACP,CAAC;IACL,CAAC,EAAE,CAAC,EAAE,EAAE,OAAO,CAAC,CAAC,CAAC;IAElB,OAAO,IAAI,CAAC;AAChB,CAAC;AAQD,oBAAoB;AACpB,SAAS,QAAQ,CAAC,IAAY,EAAE,UAA2B,EAAE;IACzD,MAAM,EAAE,OAAO,GAAG,KAAK,EAAE,WAAW,GAAG,IAAI,EAAE,GAAG,OAAO,CAAC;IACxD,MAAM,IAAI,GAAG,MAAM,CAAC,QAAQ,CAAC,QAAQ,CAAC;IACtC,MAAM,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,6BAA6B;IAE5D,kDAAkD;IAClD,MAAM,WAAW,GAAG,kBAAkB,CAAC,IAAI,CAAC,mBAAmB,EAAE,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC,CAAC;IAC/E,IAAI,CAAC,WAAW,EAAE,CAAC;QACf,OAAO,CAAC,2BAA2B;IACvC,CAAC;IAED,iDAAiD;IACjD,eAAe,GAAG,EAAE,GAAG,eAAe,EAAE,YAAY,EAAE,IAAI,EAAE,CAAC;IAC7D,iBAAiB,CAAC,OAAO,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,QAAQ,EAAE,CAAC,CAAC;IAEpD,IAAI,OAAO,EAAE,CAAC;QACV,MAAM,CAAC,OAAO,CAAC,YAAY,CAAC,IAAI,EAAE,EAAE,EAAE,IAAI,CAAC,CAAC;IAChD,CAAC;SAAM,CAAC;QACJ,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,IAAI,EAAE,EAAE,EAAE,IAAI,CAAC,CAAC;IAC7C,CAAC;IAED,sEAAsE;IACtE,qEAAqE;IACrE,sEAAsE;IACtE,IAAI,WAAW,EAAE,CAAC;QACd,MAAM,CAAC,QAAQ,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,QAAQ,EAAE,SAAS,EAAE,CAAC,CAAC;IAC9D,CAAC;IAED,wEAAwE;IACxE,yCAAyC;IACzC,cAAc,CAAC,KAAK,CAAC,CAAC;IAEtB,kDAAkD;IAClD,kBAAkB,CAAC,IAAI,CAAC,YAAY,EAAE,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC,CAAC;AACxD,CAAC;AAaD;;GAEG;AACH,SAAS,aAAa,CAAC,IAAY;IAC/B,IAAI,OAAO,MAAM,KAAK,WAAW,EAAE,CAAC;QAChC,OAAO,KAAK,CAAC;IACjB,CAAC;IACD,IAAI,CAAC;QACD,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,IAAI,EAAE,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;QAClD,OAAO,GAAG,CAAC,MAAM,KAAK,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC;IACjD,CAAC;IAAC,MAAM,CAAC;QACL,OAAO,KAAK,CAAC;IACjB,CAAC;AACL,CAAC;AAED,2DAA2D;AAC3D,kCAAkC;AAClC,IAAI,YAA0B,CAAC;AAE/B,IAAI,OAAO,MAAM,KAAK,WAAW,IAAI,gBAAgB,EAAE,EAAE,CAAC;IACtD,MAAM,YAAY,GAAG,MAAiE,CAAC;IACvF,IAAI,CAAC,YAAY,CAAC,oBAAoB,EAAE,CAAC;QACrC,YAAY,CAAC,oBAAoB,GAAG,EAAE,CAAC;IAC3C,CAAC;IACD,YAAY,GAAG,YAAY,CAAC,oBAAoB,CAAC;AACrD,CAAC;KAAM,CAAC;IACJ,YAAY,GAAG,EAAE,CAAC;AACtB,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,UAAU,IAAI,CAAC,KAAgB;IACjC,MAAM,EACF,QAAQ,EACR,IAAI,EACJ,SAAS,EACT,QAAQ,EAAE,YAAY,GAAG,IAAI,EAC7B,WAAW,GAAG,IAAI,EAClB,OAAO,EAAE,WAAW,EACpB,MAAM,EACN,QAAQ,EACR,OAAO,EAAE,WAAW,EACpB,YAAY,EAAE,gBAAgB,EAC9B,OAAO,EAAE,WAAW,EACpB,GAAG,SAAS,EACf,GAAG,KAAK,CAAC;IAEV,MAAM,OAAO,GAAG,CAAC,CAAsC,EAAE,EAAE;QACvD,mEAAmE;QACnE,WAAW,EAAE,CAAC,CAAC,CAAC,CAAC;QAEjB,IACI,CAAC,CAAC,gBAAgB;YAClB,CAAC,CAAC,MAAM,KAAK,CAAC,IAAI,kBAAkB;YACpC,CAAC,CAAC,OAAO;YACT,CAAC,CAAC,OAAO;YACT,CAAC,CAAC,QAAQ;YACV,CAAC,CAAC,MAAM;YACR,MAAM,IAAI,0CAA0C;YACpD,QAAQ,IAAI,IAAI,IAAI,+BAA+B;YACnD,aAAa,CAAC,IAAI,CAAC,CAAC,oCAAoC;UAC1D,CAAC;YACC,OAAO;QACX,CAAC;QACD,CAAC,CAAC,cAAc,EAAE,CAAC;QACnB,QAAQ,CAAC,IAAI,EAAE,EAAE,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,CAAC,CAAC;IAC1D,CAAC,CAAC;IAEF,MAAM,YAAY,GAAG,KAAK,EAAE,CAAsC,EAAE,EAAE;QAClE,qFAAqF;QACrF,IAAI,YAAY,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,IAAI,YAAY,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAClE,MAAM,EAAE,aAAa,EAAE,GAAG,MAAM,MAAM,CAAC,eAAe,CAAC,CAAC;YACxD,aAAa,CAAC,IAAI,EAAE,YAAY,CAAC,CAAC;QACtC,CAAC;QACD,gBAAgB,EAAE,CAAC,CAAC,CAAC,CAAC;IAC1B,CAAC,CAAC;IAEF,MAAM,OAAO,GAAG,KAAK,EAAE,CAAsC,EAAE,EAAE;QAC7D,+CAA+C;QAC/C,IAAI,YAAY,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,IAAI,YAAY,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAClE,MAAM,EAAE,aAAa,EAAE,GAAG,MAAM,MAAM,CAAC,eAAe,CAAC,CAAC;YACxD,aAAa,CAAC,IAAI,EAAE,YAAY,CAAC,CAAC;QACtC,CAAC;QACD,WAAW,EAAE,CAAC,CAAC,CAAC,CAAC;IACrB,CAAC,CAAC;IAEF,OAAO,CACH,eAAO,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,QAAQ,EAAE,OAAO,EAAE,OAAO,EAAE,YAAY,EAAE,YAAY,EAAE,OAAO,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS,YACjJ,QAAQ,GACT,CACP,CAAC;AACN,CAAC;AAcD,wBAAwB;AACxB,MAAM,UAAU,SAAS,CAAC,EAAE,QAAQ,EAA+C;IAC/E,gGAAgG;IAChG,MAAM,CAAC,SAAS,EAAE,eAAe,CAAC,GAAG,aAAa,EAAE,CAAC;IAErD,gDAAgD;IAChD,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,GAAG,OAAO,CAAC,GAAG,EAAE;QACtC,IAAI,OAAO,MAAM,KAAK,WAAW,EAAE,CAAC;YAChC,OAAO,EAAE,MAAM,EAAE,EAAE,EAAE,QAAQ,EAAE,SAAS,EAAE,CAAC;QAC/C,CAAC;QACD,MAAM,MAAM,GAAG,WAAW,EAAE,CAAC;QAC7B,6CAA6C;QAC7C,+DAA+D;QAC/D,IAAI,gBAAgB,EAAE,EAAE,CAAC;YACrB,MAAM,YAAY,GAAG,MAAiE,CAAC;YACvF,YAAY,CAAC,oBAAoB,GAAG,MAAM,CAAC,MAAM,CAAC;YAClD,4CAA4C;YAC5C,YAAY,CAAC,MAAM,GAAG,CAAC,CAAC;YACxB,YAAY,CAAC,IAAI,CAAC,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC;QACxC,CAAC;aAAM,CAAC;YACJ,YAAY,GAAG,MAAM,CAAC,MAAM,CAAC;QACjC,CAAC;QACD,OAAO,MAAM,CAAC;IAClB,CAAC,EAAE,EAAE,CAAC,CAAC;IAEP,4DAA4D;IAC5D,yDAAyD;IACzD,MAAM,KAAK,GAAG,oBAAoB,CAAC,mBAAmB,EAAE,mBAAmB,EAAE,iBAAiB,CAAC,CAAC;IAChG,MAAM,CAAC,eAAe,EAAE,kBAAkB,CAAC,GAAG,KAAK,CAAC,QAAQ,CAA0B,GAAG,EAAE;QACvF,MAAM,OAAO,GAAG,sBAAsB,EAAE,CAAC;QACzC,IAAI,CAAC,OAAO,EAAE,CAAC;YACX,OAAO,EAAE,CAAC;QACd,CAAC;QAED,IAAI,OAAO,CAAC,IAAI,KAAK,MAAM,CAAC,QAAQ,CAAC,QAAQ,EAAE,CAAC;YAC5C,OAAO,OAAO,CAAC,KAAK,CAAC;QACzB,CAAC;QAED,OAAO,EAAE,CAAC;IACd,CAAC,CAAC,CAAC;IACH,MAAM,CAAC,aAAa,EAAE,gBAAgB,CAAC,GAAG,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;IAEhE,MAAM,KAAK,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC,UAAU,CAAC,KAAK,CAAC,IAAI,EAAE,MAAM,CAAC,EAAE,CAAC,KAAK,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC;IAElF,6FAA6F;IAC7F,MAAM,aAAa,GAAG,KAAK,EAAE,MAAM,IAAI,CAAC,gBAAgB,EAAE,CAAC,CAAC,CAAC,qBAAqB,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;IAErG,gFAAgF;IAChF,MAAM,mBAAmB,GAAG,gBAAgB,EAAE,CAAC,CAAC,CAAC,IAAI,eAAe,CAAC,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,YAAY,CAAC;IAElH,MAAM,WAAW,GAAkB;QAC/B,IAAI,EAAE,KAAK,CAAC,IAAI;QAChB,MAAM,EAAE,aAAa;QACrB,YAAY,EAAE,mBAAmB;QACjC,IAAI,EAAE,CAAC,IAAI,EAAE,OAAO,EAAE,EAAE;YACpB,0DAA0D;YAC1D,eAAe,CAAC,GAAG,EAAE;gBACjB,QAAQ,CAAC,IAAI,EAAE,EAAE,WAAW,EAAE,OAAO,EAAE,WAAW,EAAE,CAAC,CAAC;YAC1D,CAAC,CAAC,CAAC;QACP,CAAC;QACD,OAAO,EAAE,CAAC,IAAI,EAAE,OAAO,EAAE,EAAE;YACvB,eAAe,CAAC,GAAG,EAAE;gBACjB,QAAQ,CAAC,IAAI,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,WAAW,EAAE,OAAO,EAAE,WAAW,EAAE,CAAC,CAAC;YACzE,CAAC,CAAC,CAAC;QACP,CAAC;QACD,EAAE,EAAE,CAAC,KAAK,EAAE,QAAQ,EAAE,EAAE,CAAC,kBAAkB,CAAC,EAAE,CAAC,KAAK,EAAE,QAAQ,CAAC;QAC/D,MAAM,EAAE,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG;QACzB,YAAY,EAAE,KAAK,CAAC,YAAY;QAChC,SAAS;KACZ,CAAC;IAEF,KAAK,CAAC,SAAS,CAAC,GAAG,EAAE;QACjB,MAAM,UAAU,GAAG,GAAG,KAAK,CAAC,IAAI,GAAG,MAAM,CAAC,QAAQ,CAAC,MAAM,IAAI,EAAE,EAAE,CAAC;QAElE,gFAAgF;QAChF,IAAI,CAAC,aAAa,EAAE,CAAC;YACjB,MAAM,SAAS,GAAG,sBAAsB,EAAE,CAAC;YAC3C,IAAI,SAAS,IAAI,SAAS,CAAC,IAAI,KAAK,KAAK,CAAC,IAAI,EAAE,CAAC;gBAC7C,gBAAgB,CAAC,IAAI,CAAC,CAAC;gBACvB,OAAO;YACX,CAAC;YACD,gBAAgB,CAAC,IAAI,CAAC,CAAC;QAC3B,CAAC;QAED,IAAI,SAAS,GAAG,KAAK,CAAC;QAEtB,MAAM,IAAI,GAAG,KAAK,IAAI,EAAE;YACpB,MAAM,KAAK,GAAG,MAAM,iBAAiB,CAAC,UAAU,CAAC,CAAC;YAClD,IAAI,SAAS,EAAE,CAAC;gBACZ,OAAO;YACX,CAAC;YAED,kBAAkB,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC;QACpC,CAAC,CAAC;QAEF,KAAK,IAAI,EAAE,CAAC;QAEZ,OAAO,GAAG,EAAE;YACR,SAAS,GAAG,IAAI,CAAC;QACrB,CAAC,CAAC;IACN,CAAC,EAAE,CAAC,KAAK,CAAC,IAAI,EAAE,mBAAmB,CAAC,QAAQ,EAAE,EAAE,aAAa,CAAC,CAAC,CAAC;IAEhE,KAAK,CAAC,SAAS,CAAC,GAAG,EAAE;QACjB,MAAM,UAAU,GAAG,IAAI,eAAe,EAAE,CAAC;QACzC,MAAM,UAAU,GAAG,GAAG,KAAK,CAAC,IAAI,GAAG,MAAM,CAAC,QAAQ,CAAC,MAAM,IAAI,EAAE,EAAE,CAAC;QAElE,MAAM,YAAY,GAAG,KAAK,IAAI,EAAE;YAC5B,IAAI,CAAC;gBACD,IAAI,UAAU,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;oBAC5B,OAAO;gBACX,CAAC;gBAED,MAAM,MAAM,GAAG,MAAM,kBAAkB,CACnC,uBAAuB,EACvB,EAAE,IAAI,EAAE,UAAU,EAAE,EACpB;oBACI,SAAS,EAAE,yBAAyB,EAAE,IAAI,iBAAiB,EAAE;iBAChE,CACJ,CAAC;gBAEF,IAAI,UAAU,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;oBAC5B,OAAO;gBACX,CAAC;gBAED,kBAAkB,CAAC,MAAM,CAAC,IAAI,IAAI,IAAI,CAAC,CAAC;YAC5C,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACb,IAAK,KAA2B,EAAE,IAAI,KAAK,YAAY,EAAE,CAAC;oBACtD,OAAO;gBACX,CAAC;YACL,CAAC;QACL,CAAC,CAAC;QAEF,YAAY,EAAE,CAAC;QAEf,OAAO,GAAG,EAAE,CAAC,UAAU,CAAC,KAAK,EAAE,CAAC;IACpC,CAAC,EAAE,CAAC,KAAK,CAAC,IAAI,EAAE,mBAAmB,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC;IAEjD,IAAI,CAAC,KAAK,EAAE,CAAC;QACT,MAAM,YAAY,GAAG,QAAQ,IAAI,CAAC,GAAG,EAAE,CAAC,sCAAoB,CAAC,CAAC;QAC9D,MAAM,OAAO,GAAG,KAAC,YAAY,KAAG,CAAC;QAEjC,OAAO,KAAC,aAAa,CAAC,QAAQ,IAAC,KAAK,EAAE,WAAW,YAAG,QAAQ,CAAC,CAAC,CAAC,KAAC,QAAQ,IAAC,SAAS,EAAE,YAAY,EAAE,SAAS,EAAE,EAAE,GAAI,CAAC,CAAC,CAAC,OAAO,GAA0B,CAAC;IAC5J,CAAC;IAED,MAAM,IAAI,GAAG,KAAK,CAAC,KAAK,CAAC,SAAwG,CAAC;IAClI,MAAM,SAAS,GAAG;QACd,GAAG,eAAe;QAClB,MAAM,EAAE,KAAK,CAAC,MAAM;QACpB,YAAY,EAAE,mBAAmB;KACpC,CAAC;IAEF,uDAAuD;IACvD,MAAM,WAAW,GAAG,GAAG,EAAE;QACrB,IAAI,OAAO,GAAG,KAAC,IAAI,OAAK,SAAS,GAAI,CAAC;QACtC,+CAA+C;QAC/C,KAAK,IAAI,CAAC,GAAG,KAAK,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;YACvD,MAAM,MAAM,GAAG,KAAK,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;YACtC,OAAO,GAAG,KAAC,MAAM,cAAE,OAAO,GAAU,CAAC;QACzC,CAAC;QACD,OAAO,OAAO,CAAC;IACnB,CAAC,CAAC;IAEF,MAAM,YAAY,GAAG,QAAQ,CAAC,CAAC,CAAC,CAC5B,KAAC,QAAQ,IAAC,SAAS,EAAE,WAAW,EAAE,SAAS,EAAE,SAAS,YAClD,KAAC,WAAW,KAAG,GACR,CACd,CAAC,CAAC,CAAC,CACA,KAAC,WAAW,KAAG,CAClB,CAAC;IAEF,OAAO,KAAC,aAAa,CAAC,QAAQ,IAAC,KAAK,EAAE,WAAW,YAAG,YAAY,GAA0B,CAAC;AAC/F,CAAC;AAeD,SAAS,kBAAkB,CAAC,IAA6B;IACrD,IAAI,OAAO,QAAQ,KAAK,WAAW,EAAE,CAAC;QAClC,OAAO;IACX,CAAC;IAED,qBAAqB,EAAE,CAAC;IAExB,IAAI,CAAC,IAAI,EAAE,CAAC;QACR,OAAO;IACX,CAAC;IAED,QAAQ,CAAC,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC;IAE5B,MAAM,OAAO,GAAmE,EAAE,CAAC;IAEnF,OAAO,CAAC,IAAI,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,EAAE,QAAQ,EAAE,UAAU,EAAE,OAAO,EAAE,IAAI,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;IACpF,OAAO,CAAC,IAAI,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,EAAE,QAAQ,EAAE,SAAS,EAAE,OAAO,EAAE,IAAI,CAAC,IAAI,IAAI,SAAS,EAAE,EAAE,CAAC,CAAC;IAC/F,OAAO,CAAC,IAAI,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,cAAc,EAAE,OAAO,EAAE,IAAI,CAAC,WAAW,IAAI,qBAAqB,EAAE,EAAE,CAAC,CAAC;IACnH,OAAO,CAAC,IAAI,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,eAAe,EAAE,OAAO,EAAE,IAAI,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;IAErF,IAAI,IAAI,CAAC,WAAW,EAAE,CAAC;QACnB,OAAO,CAAC,IAAI,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,aAAa,EAAE,OAAO,EAAE,IAAI,CAAC,WAAW,EAAE,EAAE,CAAC,CAAC;QACzF,OAAO,CAAC,IAAI,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,EAAE,QAAQ,EAAE,gBAAgB,EAAE,OAAO,EAAE,IAAI,CAAC,WAAW,EAAE,EAAE,CAAC,CAAC;QAChG,OAAO,CAAC,IAAI,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,qBAAqB,EAAE,OAAO,EAAE,IAAI,CAAC,WAAW,EAAE,EAAE,CAAC,CAAC;IACrG,CAAC;IAED,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;QACb,OAAO,CAAC,IAAI,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,EAAE,QAAQ,EAAE,UAAU,EAAE,OAAO,EAAE,IAAI,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;QACpF,OAAO,CAAC,IAAI,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,eAAe,EAAE,OAAO,EAAE,IAAI,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;IACzF,CAAC;IAED,IAAI,IAAI,CAAC,YAAY,EAAE,CAAC;QACpB,OAAO,CAAC,IAAI,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,EAAE,QAAQ,EAAE,QAAQ,EAAE,OAAO,EAAE,IAAI,CAAC,YAAY,EAAE,EAAE,CAAC,CAAC;QACzF,OAAO,CAAC,IAAI,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,EAAE,GAAG,EAAE,WAAW,EAAE,IAAI,EAAE,IAAI,CAAC,YAAY,EAAE,EAAE,CAAC,CAAC;IACxF,CAAC;IAED,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;QAChB,OAAO,CAAC,IAAI,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,EAAE,QAAQ,EAAE,cAAc,EAAE,OAAO,EAAE,IAAI,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC;IAC/F,CAAC;IAED,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;QACd,OAAO,CAAC,IAAI,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,IAAI,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;IACnF,CAAC;IAED,IAAI,IAAI,CAAC,WAAW,EAAE,CAAC;QACnB,OAAO,CAAC,IAAI,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,cAAc,EAAE,OAAO,EAAE,IAAI,CAAC,WAAW,EAAE,EAAE,CAAC,CAAC;IAC9F,CAAC;IAED,IAAI,IAAI,CAAC,cAAc,EAAE,CAAC;QACtB,OAAO,CAAC,IAAI,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,iBAAiB,EAAE,OAAO,EAAE,IAAI,CAAC,cAAc,EAAE,EAAE,CAAC,CAAC;IACpG,CAAC;IAED,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;QAC1B,MAAM,IAAI,GAAG,QAAQ,CAAC,aAAa,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QAC/C,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE,CAAC;YACrD,IAAI,CAAC,YAAY,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;QAClC,CAAC;QACD,IAAI,CAAC,YAAY,CAAC,iBAAiB,EAAE,MAAM,CAAC,CAAC;QAC7C,QAAQ,CAAC,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC;IACpC,CAAC;AACL,CAAC;AAED,SAAS,qBAAqB;IAC1B,MAAM,SAAS,GAAG,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,gBAAgB,CAAC,YAAY,CAAC,CAAC,CAAC;IAE3E,KAAK,MAAM,IAAI,IAAI,SAAS,EAAE,CAAC;QAC3B,IAAI,IAAI,CAAC,YAAY,CAAC,iBAAiB,CAAC,KAAK,MAAM,EAAE,CAAC;YAClD,IAAI,CAAC,MAAM,EAAE,CAAC;YACd,SAAS;QACb,CAAC;QAED,IAAI,IAAI,CAAC,OAAO,CAAC,WAAW,EAAE,KAAK,MAAM,EAAE,CAAC;YACxC,MAAM,GAAG,GAAG,CAAC,IAAI,CAAC,YAAY,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC,WAAW,EAAE,CAAC;YAC3D,IAAI,GAAG,KAAK,WAAW,EAAE,CAAC;gBACtB,IAAI,CAAC,MAAM,EAAE,CAAC;YAClB,CAAC;YACD,SAAS;QACb,CAAC;QAED,MAAM,IAAI,GAAG,CAAC,IAAI,CAAC,YAAY,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC,WAAW,EAAE,CAAC;QAC7D,MAAM,QAAQ,GAAG,CAAC,IAAI,CAAC,YAAY,CAAC,UAAU,CAAC,IAAI,EAAE,CAAC,CAAC,WAAW,EAAE,CAAC;QAErE,IAAI,IAAI,KAAK,aAAa,IAAI,IAAI,KAAK,QAAQ,IAAI,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;YAC7E,IAAI,CAAC,MAAM,EAAE,CAAC;YACd,SAAS;QACb,CAAC;QAED,IAAI,QAAQ,CAAC,UAAU,CAAC,KAAK,CAAC,EAAE,CAAC;YAC7B,IAAI,CAAC,MAAM,EAAE,CAAC;QAClB,CAAC;IACL,CAAC;AACL,CAAC","sourcesContent":["import type { ComponentType } from \"react\";\nimport React, { useMemo, useSyncExternalStore, useTransition } from \"react\";\n\nimport { SEO_METADATA_RPC_METHOD } from \"../runtime/internalMethods.js\";\nimport { isDevEnvironment } from \"./env.js\";\nimport type { RouteEntry } from \"./routerManifest.js\";\nimport { buildRoutes } from \"./routerManifest.js\";\nimport { isAutoHttpOnMobileEnabled, isMobileRpcDevice, rpcCallWithOptions } from \"./rpcClient.js\";\n\ntype HeliumSSRBootstrap = {\n path: string;\n props: Record<string, unknown>;\n};\n\nfunction getInitialSSRBootstrap(): HeliumSSRBootstrap | null {\n if (typeof window === \"undefined\") {\n return null;\n }\n\n const globalWindow = window as typeof window & {\n __HELIUM_SSR_DATA__?: HeliumSSRBootstrap;\n };\n\n const payload = globalWindow.__HELIUM_SSR_DATA__;\n if (!payload || typeof payload !== \"object\" || typeof payload.path !== \"string\" || typeof payload.props !== \"object\" || payload.props === null) {\n return null;\n }\n\n return payload;\n}\n\nasync function fetchSSRPageProps(path: string): Promise<Record<string, unknown> | null> {\n try {\n const response = await fetch(`/__helium__/page-props?path=${encodeURIComponent(path)}`, {\n method: \"GET\",\n headers: {\n Accept: \"application/json\",\n },\n });\n\n if (!response.ok) {\n return null;\n }\n\n const payload = (await response.json()) as {\n ssr?: boolean;\n props?: Record<string, unknown> | null;\n };\n\n if (!payload.ssr || !payload.props) {\n return null;\n }\n\n return payload.props;\n } catch {\n return null;\n }\n}\n\n// Event emitter for router events\ntype RouterEvent = \"navigation\" | \"before-navigation\";\ntype EventListener = (event: { from: string; to: string; preventDefault?: () => void }) => void;\n\nclass RouterEventEmitter {\n private listeners: Map<RouterEvent, Set<EventListener>> = new Map();\n\n on(event: RouterEvent, listener: EventListener): () => void {\n if (!this.listeners.has(event)) {\n this.listeners.set(event, new Set());\n }\n this.listeners.get(event)!.add(listener);\n\n // Return unsubscribe function\n return () => {\n this.listeners.get(event)?.delete(listener);\n };\n }\n\n emit(event: RouterEvent, data: { from: string; to: string }): boolean {\n const eventListeners = this.listeners.get(event);\n if (!eventListeners || eventListeners.size === 0) {\n return true;\n }\n\n let prevented = false;\n const preventDefault = () => {\n prevented = true;\n };\n\n const eventData = event === \"before-navigation\" ? { ...data, preventDefault } : data;\n\n eventListeners.forEach((listener) => {\n listener(eventData);\n });\n\n return !prevented;\n }\n\n // Clear all listeners - useful for HMR\n clear() {\n this.listeners.clear();\n }\n}\n\n// Use a singleton that survives HMR by attaching to window in dev mode\nlet routerEventEmitter: RouterEventEmitter;\n\nif (typeof window !== \"undefined\" && isDevEnvironment()) {\n // In dev mode, reuse the same emitter instance across HMR\n const globalWindow = window as typeof window & { __heliumRouterEmitter?: RouterEventEmitter };\n if (!globalWindow.__heliumRouterEmitter) {\n globalWindow.__heliumRouterEmitter = new RouterEventEmitter();\n }\n routerEventEmitter = globalWindow.__heliumRouterEmitter;\n} else {\n routerEventEmitter = new RouterEventEmitter();\n}\n\ntype RouterState = {\n path: string;\n searchParams: URLSearchParams;\n isNavigating: boolean;\n};\n\nfunction getLocation(): RouterState {\n const { pathname, search } = window.location;\n return {\n path: pathname,\n searchParams: new URLSearchParams(search),\n isNavigating: false,\n };\n}\n\nfunction matchRoute(path: string, routes: RouteEntry[]) {\n for (const r of routes) {\n const m = r.matcher(path);\n if (m) {\n return { params: m.params, route: r };\n }\n }\n return null;\n}\n\n// Location store for useSyncExternalStore\n// Preserve across HMR by attaching to window in dev mode\nlet currentLocation: RouterState;\nlet locationListeners: Set<() => void>;\n\nif (typeof window !== \"undefined\" && isDevEnvironment()) {\n const globalWindow = window as typeof window & {\n __heliumCurrentLocation?: RouterState;\n __heliumLocationListeners?: Set<() => void>;\n };\n if (!globalWindow.__heliumCurrentLocation) {\n globalWindow.__heliumCurrentLocation = getLocation();\n }\n if (!globalWindow.__heliumLocationListeners) {\n globalWindow.__heliumLocationListeners = new Set();\n }\n currentLocation = globalWindow.__heliumCurrentLocation;\n locationListeners = globalWindow.__heliumLocationListeners;\n} else if (typeof window !== \"undefined\") {\n currentLocation = getLocation();\n locationListeners = new Set();\n} else {\n currentLocation = { path: \"/\", searchParams: new URLSearchParams(), isNavigating: false };\n locationListeners = new Set();\n}\n\n// Helper to re-extract params from path using stored routes during HMR\nfunction extractParamsFromPath(path: string): Record<string, string | string[]> {\n if (typeof window !== \"undefined\" && isDevEnvironment()) {\n const globalWindow = window as typeof window & { __heliumGlobalRoutes?: RouteEntry[] };\n const routes = globalWindow.__heliumGlobalRoutes;\n if (routes && routes.length > 0) {\n const match = matchRoute(path, routes);\n if (match) {\n return match.params;\n }\n }\n }\n return {};\n}\n\nfunction subscribeToLocation(callback: () => void) {\n locationListeners.add(callback);\n return () => locationListeners.delete(callback);\n}\n\nfunction getLocationSnapshot() {\n return currentLocation;\n}\n\nconst SERVER_SNAPSHOT: RouterState = { path: \"/\", searchParams: new URLSearchParams(), isNavigating: false };\nfunction getServerSnapshot() {\n return SERVER_SNAPSHOT;\n}\n\nfunction updateLocation(isNavigating = false) {\n const newLocation = { ...getLocation(), isNavigating };\n currentLocation = newLocation;\n // Update the global reference in dev mode\n if (typeof window !== \"undefined\" && isDevEnvironment()) {\n (window as typeof window & { __heliumCurrentLocation?: RouterState }).__heliumCurrentLocation = newLocation;\n }\n locationListeners.forEach((listener) => listener());\n}\n\n// Set up global listeners once\nif (typeof window !== \"undefined\") {\n // Only set up once, survives HMR\n const globalWindow = window as typeof window & { __heliumLocationListenerSetup?: boolean };\n if (!globalWindow.__heliumLocationListenerSetup) {\n globalWindow.__heliumLocationListenerSetup = true;\n\n window.addEventListener(\"popstate\", () => updateLocation(false));\n\n // Also listen to navigation events from the emitter\n routerEventEmitter.on(\"navigation\", () => updateLocation(false));\n }\n}\n\n/** Options for push/replace navigation methods */\nexport interface RouterNavigationOptions {\n /** Scroll to top after navigation (default: true) */\n scrollToTop?: boolean;\n}\n\n// Context for useRouter hook\ntype RouterContext = {\n path: string;\n params: Record<string, string | string[]>;\n searchParams: URLSearchParams;\n push: (href: string, options?: RouterNavigationOptions) => void;\n replace: (href: string, options?: RouterNavigationOptions) => void;\n on: (event: RouterEvent, listener: EventListener) => () => void;\n status: 200 | 404;\n isNavigating: boolean;\n /** Indicates content is stale (old content shown while new content renders) - React 18+ concurrent feature */\n isPending: boolean;\n};\n\nexport const RouterContext = React.createContext<RouterContext | null>(null);\n\n/**\n * Access router context inside a component tree managed by <AppRouter />.\n *\n * Provides current path, route params, URL search params and navigation helpers\n * (\\`push\\`, \\`replace\\`) as well as an \\`on\\` method to subscribe to navigation events.\n * The \\`isNavigating\\` property indicates when a navigation is in progress.\n * The \\`isPending\\` property indicates when content is stale (React concurrent features).\n * Throws when used outside of an <AppRouter /> provider.\n */\nexport function useRouter() {\n const ctx = React.useContext(RouterContext);\n if (!ctx) {\n // During HMR in development, context might be temporarily unavailable\n // Provide a temporary fallback to prevent white screen of death\n // Re-extract params from current path using stored routes\n if (typeof window !== \"undefined\" && isDevEnvironment()) {\n const currentPath = window.location.pathname;\n return {\n path: currentPath,\n params: extractParamsFromPath(currentPath),\n searchParams: new URLSearchParams(window.location.search),\n push: (href: string, options?: RouterNavigationOptions) => {\n window.history.pushState({}, \"\", href);\n if (options?.scrollToTop !== false) {\n window.scrollTo({ top: 0, left: 0, behavior: \"smooth\" });\n }\n window.dispatchEvent(new PopStateEvent(\"popstate\"));\n },\n replace: (href: string, options?: RouterNavigationOptions) => {\n window.history.replaceState({}, \"\", href);\n if (options?.scrollToTop !== false) {\n window.scrollTo({ top: 0, left: 0, behavior: \"smooth\" });\n }\n window.dispatchEvent(new PopStateEvent(\"popstate\"));\n },\n on: () => () => {},\n status: 200 as const,\n isNavigating: false,\n isPending: false,\n };\n }\n throw new Error(\"useRouter must be used inside <AppRouter>\");\n }\n return ctx;\n}\n\n/**\n * Redirect component for declarative navigation.\n * Use this instead of calling router.push() during render.\n *\n * @example\n * \\`\\`\\`tsx\n * export default function Docs() {\n * return <Redirect to=\"/docs/getting-started\" />;\n * }\n * \\`\\`\\`\n */\nexport function Redirect({ to, replace = false }: { to: string; replace?: boolean }) {\n const hasRedirected = React.useRef(false);\n\n // Use useLayoutEffect to redirect before paint\n React.useLayoutEffect(() => {\n const targetPath = to.split(\"?\")[0];\n if (!hasRedirected.current && window.location.pathname !== targetPath) {\n hasRedirected.current = true;\n\n // Perform navigation\n if (replace) {\n window.history.replaceState(null, \"\", to);\n } else {\n window.history.pushState(null, \"\", to);\n }\n\n // Emit navigation event to update router state\n routerEventEmitter.emit(\"navigation\", {\n from: window.location.pathname,\n to: targetPath,\n });\n }\n }, [to, replace]);\n\n return null;\n}\n\n/** Options for navigation */\ninterface NavigateOptions {\n replace?: boolean;\n scrollToTop?: boolean;\n}\n\n// Navigation helper\nfunction navigate(href: string, options: NavigateOptions = {}) {\n const { replace = false, scrollToTop = true } = options;\n const from = window.location.pathname;\n const to = href.split(\"?\")[0]; // Extract pathname from href\n\n // Emit before-navigation event (can be prevented)\n const canNavigate = routerEventEmitter.emit(\"before-navigation\", { from, to });\n if (!canNavigate) {\n return; // Navigation was prevented\n }\n\n // Set navigating state to true before navigation\n currentLocation = { ...currentLocation, isNavigating: true };\n locationListeners.forEach((listener) => listener());\n\n if (replace) {\n window.history.replaceState(null, \"\", href);\n } else {\n window.history.pushState(null, \"\", href);\n }\n\n // Scroll to top immediately after pushState, before React re-renders.\n // Using instant scroll avoids race conditions where smooth scrolling\n // gets interrupted by React DOM updates, especially on Safari mobile.\n if (scrollToTop) {\n window.scrollTo({ top: 0, left: 0, behavior: \"instant\" });\n }\n\n // Update location state synchronously so there is no stale-state window\n // between pushState and the next render.\n updateLocation(false);\n\n // Emit navigation event after state is consistent\n routerEventEmitter.emit(\"navigation\", { from, to });\n}\n\nexport type LinkProps = React.PropsWithChildren<\n Omit<React.AnchorHTMLAttributes<HTMLAnchorElement>, \"href\"> & {\n href: string;\n replace?: boolean;\n /** Disable prefetching on hover (default: false - prefetch is enabled) */\n prefetch?: boolean;\n /** Scroll to top after navigation (default: true) */\n scrollToTop?: boolean;\n }\n>;\n\n/**\n * Check if a URL is external (different origin).\n */\nfunction isExternalUrl(href: string): boolean {\n if (typeof window === \"undefined\") {\n return false;\n }\n try {\n const url = new URL(href, window.location.origin);\n return url.origin !== window.location.origin;\n } catch {\n return false;\n }\n}\n\n// Store routes globally for prefetching (set by AppRouter)\n// Preserve across HMR in dev mode\nlet globalRoutes: RouteEntry[];\n\nif (typeof window !== \"undefined\" && isDevEnvironment()) {\n const globalWindow = window as typeof window & { __heliumGlobalRoutes?: RouteEntry[] };\n if (!globalWindow.__heliumGlobalRoutes) {\n globalWindow.__heliumGlobalRoutes = [];\n }\n globalRoutes = globalWindow.__heliumGlobalRoutes;\n} else {\n globalRoutes = [];\n}\n\n/**\n * Client-side navigation link.\n *\n * Intercepts left-clicks and uses the router's navigation helpers for SPA\n * navigation. Keeps normal anchor behaviour when modifier keys are used,\n * when the link is external, or when `target` / `download` attributes\n * are present.\n *\n * Automatically prefetches page chunks on hover for faster navigation.\n */\nexport function Link(props: LinkProps) {\n const {\n children,\n href,\n className,\n prefetch: prefetchProp = true,\n scrollToTop = true,\n replace: replaceProp,\n target,\n download,\n onClick: userOnClick,\n onMouseEnter: userOnMouseEnter,\n onFocus: userOnFocus,\n ...restProps\n } = props;\n\n const onClick = (e: React.MouseEvent<HTMLAnchorElement>) => {\n // Let user's onClick run first so they can call e.preventDefault()\n userOnClick?.(e);\n\n if (\n e.defaultPrevented ||\n e.button !== 0 || // only left click\n e.metaKey ||\n e.ctrlKey ||\n e.shiftKey ||\n e.altKey ||\n target || // let browser handle target=\"_blank\" etc.\n download != null || // let browser handle downloads\n isExternalUrl(href) // let browser handle external links\n ) {\n return;\n }\n e.preventDefault();\n navigate(href, { replace: replaceProp, scrollToTop });\n };\n\n const onMouseEnter = async (e: React.MouseEvent<HTMLAnchorElement>) => {\n // Prefetch the route on hover if enabled and not external (lazy-load prefetch logic)\n if (prefetchProp && !isExternalUrl(href) && globalRoutes.length > 0) {\n const { prefetchRoute } = await import(\"./prefetch.js\");\n prefetchRoute(href, globalRoutes);\n }\n userOnMouseEnter?.(e);\n };\n\n const onFocus = async (e: React.FocusEvent<HTMLAnchorElement>) => {\n // Also prefetch on focus (keyboard navigation)\n if (prefetchProp && !isExternalUrl(href) && globalRoutes.length > 0) {\n const { prefetchRoute } = await import(\"./prefetch.js\");\n prefetchRoute(href, globalRoutes);\n }\n userOnFocus?.(e);\n };\n\n return (\n <a {...restProps} href={href} target={target} download={download} onClick={onClick} onMouseEnter={onMouseEnter} onFocus={onFocus} className={className}>\n {children}\n </a>\n );\n}\n\n// AppShell props type\n/**\n * Props passed to an optional \\`AppShell\\` wrapper component used by <AppRouter />.\n *\n * \\`Component\\` — the page component to render. \\`pageProps\\` — props provided to the page.\n */\nexport type AppShellProps<TPageProps extends Record<string, unknown> = Record<string, unknown>> = {\n Component: ComponentType<TPageProps>;\n pageProps: TPageProps;\n children?: React.ReactNode;\n};\n\n// Main router component\nexport function AppRouter({ AppShell }: { AppShell?: ComponentType<AppShellProps> }) {\n // useTransition for concurrent rendering - allows React to keep UI responsive during navigation\n const [isPending, startTransition] = useTransition();\n\n // Build routes once on mount (client-side only)\n const { routes, NotFound } = useMemo(() => {\n if (typeof window === \"undefined\") {\n return { routes: [], NotFound: undefined };\n }\n const result = buildRoutes();\n // Store routes globally for Link prefetching\n // In dev mode, also update the global reference to survive HMR\n if (isDevEnvironment()) {\n const globalWindow = window as typeof window & { __heliumGlobalRoutes?: RouteEntry[] };\n globalWindow.__heliumGlobalRoutes = result.routes;\n // Update the module-level reference as well\n globalRoutes.length = 0;\n globalRoutes.push(...result.routes);\n } else {\n globalRoutes = result.routes;\n }\n return result;\n }, []);\n\n // Use useSyncExternalStore to subscribe to location changes\n // This ensures synchronous updates when location changes\n const state = useSyncExternalStore(subscribeToLocation, getLocationSnapshot, getServerSnapshot);\n const [runtimeSSRProps, setRuntimeSSRProps] = React.useState<Record<string, unknown>>(() => {\n const payload = getInitialSSRBootstrap();\n if (!payload) {\n return {};\n }\n\n if (payload.path === window.location.pathname) {\n return payload.props;\n }\n\n return {};\n });\n const [hydrationDone, setHydrationDone] = React.useState(false);\n\n const match = useMemo(() => matchRoute(state.path, routes), [state.path, routes]);\n\n // Use matched params, or fall back to re-extracting from path using global routes during HMR\n const currentParams = match?.params ?? (isDevEnvironment() ? extractParamsFromPath(state.path) : {});\n\n // In dev mode, always read fresh searchParams from URL to handle HMR edge cases\n const currentSearchParams = isDevEnvironment() ? new URLSearchParams(window.location.search) : state.searchParams;\n\n const routerValue: RouterContext = {\n path: state.path,\n params: currentParams,\n searchParams: currentSearchParams,\n push: (href, options) => {\n // Wrap navigation in startTransition for smoother updates\n startTransition(() => {\n navigate(href, { scrollToTop: options?.scrollToTop });\n });\n },\n replace: (href, options) => {\n startTransition(() => {\n navigate(href, { replace: true, scrollToTop: options?.scrollToTop });\n });\n },\n on: (event, listener) => routerEventEmitter.on(event, listener),\n status: match ? 200 : 404,\n isNavigating: state.isNavigating,\n isPending,\n };\n\n React.useEffect(() => {\n const targetPath = `${state.path}${window.location.search || \"\"}`;\n\n // On first client render, if SSR payload already exists for this path, keep it.\n if (!hydrationDone) {\n const bootstrap = getInitialSSRBootstrap();\n if (bootstrap && bootstrap.path === state.path) {\n setHydrationDone(true);\n return;\n }\n setHydrationDone(true);\n }\n\n let cancelled = false;\n\n const load = async () => {\n const props = await fetchSSRPageProps(targetPath);\n if (cancelled) {\n return;\n }\n\n setRuntimeSSRProps(props ?? {});\n };\n\n void load();\n\n return () => {\n cancelled = true;\n };\n }, [state.path, currentSearchParams.toString(), hydrationDone]);\n\n React.useEffect(() => {\n const controller = new AbortController();\n const targetPath = `${state.path}${window.location.search || \"\"}`;\n\n const syncMetadata = async () => {\n try {\n if (controller.signal.aborted) {\n return;\n }\n\n const result = await rpcCallWithOptions<ClientSocialMeta | null, { path: string }>(\n SEO_METADATA_RPC_METHOD,\n { path: targetPath },\n {\n forceHttp: isAutoHttpOnMobileEnabled() && isMobileRpcDevice(),\n }\n );\n\n if (controller.signal.aborted) {\n return;\n }\n\n applyRouteMetadata(result.data ?? null);\n } catch (error) {\n if ((error as { name?: string })?.name === \"AbortError\") {\n return;\n }\n }\n };\n\n syncMetadata();\n\n return () => controller.abort();\n }, [state.path, currentSearchParams.toString()]);\n\n if (!match) {\n const NotFoundComp = NotFound ?? (() => <div>Not found</div>);\n const content = <NotFoundComp />;\n\n return <RouterContext.Provider value={routerValue}>{AppShell ? <AppShell Component={NotFoundComp} pageProps={{}} /> : content}</RouterContext.Provider>;\n }\n\n const Page = match.route.Component as ComponentType<{ params: Record<string, string | string[]>; searchParams: URLSearchParams }>;\n const pageProps = {\n ...runtimeSSRProps,\n params: match.params,\n searchParams: currentSearchParams,\n };\n\n // Create a wrapped component that includes all layouts\n const WrappedPage = () => {\n let content = <Page {...pageProps} />;\n // Wrap page with layouts (from outer to inner)\n for (let i = match.route.layouts.length - 1; i >= 0; i--) {\n const Layout = match.route.layouts[i];\n content = <Layout>{content}</Layout>;\n }\n return content;\n };\n\n const finalContent = AppShell ? (\n <AppShell Component={WrappedPage} pageProps={pageProps}>\n <WrappedPage />\n </AppShell>\n ) : (\n <WrappedPage />\n );\n\n return <RouterContext.Provider value={routerValue}>{finalContent}</RouterContext.Provider>;\n}\n\ntype ClientSocialMeta = {\n title: string;\n description?: string;\n image?: string;\n canonicalUrl?: string;\n siteName?: string;\n type?: string;\n robots?: string;\n twitterCard?: \"summary\" | \"summary_large_image\" | \"app\" | \"player\";\n twitterSite?: string;\n twitterCreator?: string;\n};\n\nfunction applyRouteMetadata(meta: ClientSocialMeta | null) {\n if (typeof document === \"undefined\") {\n return;\n }\n\n removeExistingSeoTags();\n\n if (!meta) {\n return;\n }\n\n document.title = meta.title;\n\n const entries: Array<{ tag: \"meta\" | \"link\"; attrs: Record<string, string> }> = [];\n\n entries.push({ tag: \"meta\", attrs: { property: \"og:title\", content: meta.title } });\n entries.push({ tag: \"meta\", attrs: { property: \"og:type\", content: meta.type ?? \"website\" } });\n entries.push({ tag: \"meta\", attrs: { name: \"twitter:card\", content: meta.twitterCard ?? \"summary_large_image\" } });\n entries.push({ tag: \"meta\", attrs: { name: \"twitter:title\", content: meta.title } });\n\n if (meta.description) {\n entries.push({ tag: \"meta\", attrs: { name: \"description\", content: meta.description } });\n entries.push({ tag: \"meta\", attrs: { property: \"og:description\", content: meta.description } });\n entries.push({ tag: \"meta\", attrs: { name: \"twitter:description\", content: meta.description } });\n }\n\n if (meta.image) {\n entries.push({ tag: \"meta\", attrs: { property: \"og:image\", content: meta.image } });\n entries.push({ tag: \"meta\", attrs: { name: \"twitter:image\", content: meta.image } });\n }\n\n if (meta.canonicalUrl) {\n entries.push({ tag: \"meta\", attrs: { property: \"og:url\", content: meta.canonicalUrl } });\n entries.push({ tag: \"link\", attrs: { rel: \"canonical\", href: meta.canonicalUrl } });\n }\n\n if (meta.siteName) {\n entries.push({ tag: \"meta\", attrs: { property: \"og:site_name\", content: meta.siteName } });\n }\n\n if (meta.robots) {\n entries.push({ tag: \"meta\", attrs: { name: \"robots\", content: meta.robots } });\n }\n\n if (meta.twitterSite) {\n entries.push({ tag: \"meta\", attrs: { name: \"twitter:site\", content: meta.twitterSite } });\n }\n\n if (meta.twitterCreator) {\n entries.push({ tag: \"meta\", attrs: { name: \"twitter:creator\", content: meta.twitterCreator } });\n }\n\n for (const entry of entries) {\n const node = document.createElement(entry.tag);\n for (const [key, value] of Object.entries(entry.attrs)) {\n node.setAttribute(key, value);\n }\n node.setAttribute(\"data-helium-seo\", \"true\");\n document.head.appendChild(node);\n }\n}\n\nfunction removeExistingSeoTags() {\n const headNodes = Array.from(document.head.querySelectorAll(\"meta, link\"));\n\n for (const node of headNodes) {\n if (node.getAttribute(\"data-helium-seo\") === \"true\") {\n node.remove();\n continue;\n }\n\n if (node.tagName.toLowerCase() === \"link\") {\n const rel = (node.getAttribute(\"rel\") || \"\").toLowerCase();\n if (rel === \"canonical\") {\n node.remove();\n }\n continue;\n }\n\n const name = (node.getAttribute(\"name\") || \"\").toLowerCase();\n const property = (node.getAttribute(\"property\") || \"\").toLowerCase();\n\n if (name === \"description\" || name === \"robots\" || name.startsWith(\"twitter:\")) {\n node.remove();\n continue;\n }\n\n if (property.startsWith(\"og:\")) {\n node.remove();\n }\n }\n}\n"]}
1
+ {"version":3,"file":"Router.js","sourceRoot":"","sources":["../../src/client/Router.tsx"],"names":[],"mappings":"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","sourcesContent":["import type { ComponentType } from \"react\";\nimport React, { useMemo, useSyncExternalStore, useTransition } from \"react\";\n\nimport { SEO_METADATA_RPC_METHOD } from \"../runtime/internalMethods.js\";\nimport { isDevEnvironment } from \"./env.js\";\nimport type { RouteEntry } from \"./routerManifest.js\";\nimport { buildRoutes } from \"./routerManifest.js\";\nimport { isAutoHttpOnMobileEnabled, isMobileRpcDevice, rpcCallWithOptions } from \"./rpcClient.js\";\n\ntype HeliumSSRBootstrap = {\n path: string;\n props: Record<string, unknown>;\n};\n\ntype SSRRedirectPayload = {\n destination: string;\n statusCode?: 301 | 302 | 303 | 307 | 308;\n replace?: boolean;\n};\n\ntype SSRPagePropsPayload =\n | {\n kind: \"props\";\n props: Record<string, unknown>;\n }\n | {\n kind: \"redirect\";\n redirect: SSRRedirectPayload;\n }\n | {\n kind: \"none\";\n };\n\nfunction getInitialSSRBootstrap(): HeliumSSRBootstrap | null {\n if (typeof window === \"undefined\") {\n return null;\n }\n\n const globalWindow = window as typeof window & {\n __HELIUM_SSR_DATA__?: HeliumSSRBootstrap;\n };\n\n const payload = globalWindow.__HELIUM_SSR_DATA__;\n if (!payload || typeof payload !== \"object\" || typeof payload.path !== \"string\" || typeof payload.props !== \"object\" || payload.props === null) {\n return null;\n }\n\n return payload;\n}\n\nasync function fetchSSRPageProps(path: string): Promise<SSRPagePropsPayload> {\n try {\n const response = await fetch(`/__helium__/page-props?path=${encodeURIComponent(path)}`, {\n method: \"GET\",\n headers: {\n Accept: \"application/json\",\n },\n });\n\n if (!response.ok) {\n return { kind: \"none\" };\n }\n\n const payload = (await response.json()) as {\n ssr?: boolean;\n props?: Record<string, unknown> | null;\n redirect?: SSRRedirectPayload;\n };\n\n if (!payload.ssr) {\n return { kind: \"none\" };\n }\n\n if (payload.redirect && typeof payload.redirect.destination === \"string\" && payload.redirect.destination.length > 0) {\n return {\n kind: \"redirect\",\n redirect: payload.redirect,\n };\n }\n\n if (!payload.props) {\n return { kind: \"none\" };\n }\n\n return {\n kind: \"props\",\n props: payload.props,\n };\n } catch {\n return { kind: \"none\" };\n }\n}\n\n// Event emitter for router events\ntype RouterEvent = \"navigation\" | \"before-navigation\";\ntype EventListener = (event: { from: string; to: string; preventDefault?: () => void }) => void;\n\nclass RouterEventEmitter {\n private listeners: Map<RouterEvent, Set<EventListener>> = new Map();\n\n on(event: RouterEvent, listener: EventListener): () => void {\n if (!this.listeners.has(event)) {\n this.listeners.set(event, new Set());\n }\n this.listeners.get(event)!.add(listener);\n\n // Return unsubscribe function\n return () => {\n this.listeners.get(event)?.delete(listener);\n };\n }\n\n emit(event: RouterEvent, data: { from: string; to: string }): boolean {\n const eventListeners = this.listeners.get(event);\n if (!eventListeners || eventListeners.size === 0) {\n return true;\n }\n\n let prevented = false;\n const preventDefault = () => {\n prevented = true;\n };\n\n const eventData = event === \"before-navigation\" ? { ...data, preventDefault } : data;\n\n eventListeners.forEach((listener) => {\n listener(eventData);\n });\n\n return !prevented;\n }\n\n // Clear all listeners - useful for HMR\n clear() {\n this.listeners.clear();\n }\n}\n\n// Use a singleton that survives HMR by attaching to window in dev mode\nlet routerEventEmitter: RouterEventEmitter;\n\nif (typeof window !== \"undefined\" && isDevEnvironment()) {\n // In dev mode, reuse the same emitter instance across HMR\n const globalWindow = window as typeof window & { __heliumRouterEmitter?: RouterEventEmitter };\n if (!globalWindow.__heliumRouterEmitter) {\n globalWindow.__heliumRouterEmitter = new RouterEventEmitter();\n }\n routerEventEmitter = globalWindow.__heliumRouterEmitter;\n} else {\n routerEventEmitter = new RouterEventEmitter();\n}\n\ntype RouterState = {\n path: string;\n searchParams: URLSearchParams;\n isNavigating: boolean;\n};\n\nfunction getLocation(): RouterState {\n const { pathname, search } = window.location;\n return {\n path: pathname,\n searchParams: new URLSearchParams(search),\n isNavigating: false,\n };\n}\n\nfunction matchRoute(path: string, routes: RouteEntry[]) {\n for (const r of routes) {\n const m = r.matcher(path);\n if (m) {\n return { params: m.params, route: r };\n }\n }\n return null;\n}\n\n// Location store for useSyncExternalStore\n// Preserve across HMR by attaching to window in dev mode\nlet currentLocation: RouterState;\nlet locationListeners: Set<() => void>;\n\nif (typeof window !== \"undefined\" && isDevEnvironment()) {\n const globalWindow = window as typeof window & {\n __heliumCurrentLocation?: RouterState;\n __heliumLocationListeners?: Set<() => void>;\n };\n if (!globalWindow.__heliumCurrentLocation) {\n globalWindow.__heliumCurrentLocation = getLocation();\n }\n if (!globalWindow.__heliumLocationListeners) {\n globalWindow.__heliumLocationListeners = new Set();\n }\n currentLocation = globalWindow.__heliumCurrentLocation;\n locationListeners = globalWindow.__heliumLocationListeners;\n} else if (typeof window !== \"undefined\") {\n currentLocation = getLocation();\n locationListeners = new Set();\n} else {\n currentLocation = { path: \"/\", searchParams: new URLSearchParams(), isNavigating: false };\n locationListeners = new Set();\n}\n\n// Helper to re-extract params from path using stored routes during HMR\nfunction extractParamsFromPath(path: string): Record<string, string | string[]> {\n if (typeof window !== \"undefined\" && isDevEnvironment()) {\n const globalWindow = window as typeof window & { __heliumGlobalRoutes?: RouteEntry[] };\n const routes = globalWindow.__heliumGlobalRoutes;\n if (routes && routes.length > 0) {\n const match = matchRoute(path, routes);\n if (match) {\n return match.params;\n }\n }\n }\n return {};\n}\n\nfunction subscribeToLocation(callback: () => void) {\n locationListeners.add(callback);\n return () => locationListeners.delete(callback);\n}\n\nfunction getLocationSnapshot() {\n return currentLocation;\n}\n\nconst SERVER_SNAPSHOT: RouterState = { path: \"/\", searchParams: new URLSearchParams(), isNavigating: false };\nfunction getServerSnapshot() {\n return SERVER_SNAPSHOT;\n}\n\nfunction updateLocation(isNavigating = false) {\n const newLocation = { ...getLocation(), isNavigating };\n currentLocation = newLocation;\n // Update the global reference in dev mode\n if (typeof window !== \"undefined\" && isDevEnvironment()) {\n (window as typeof window & { __heliumCurrentLocation?: RouterState }).__heliumCurrentLocation = newLocation;\n }\n locationListeners.forEach((listener) => listener());\n}\n\n// Set up global listeners once\nif (typeof window !== \"undefined\") {\n // Only set up once, survives HMR\n const globalWindow = window as typeof window & { __heliumLocationListenerSetup?: boolean };\n if (!globalWindow.__heliumLocationListenerSetup) {\n globalWindow.__heliumLocationListenerSetup = true;\n\n window.addEventListener(\"popstate\", () => updateLocation(false));\n\n // Also listen to navigation events from the emitter\n routerEventEmitter.on(\"navigation\", () => updateLocation(false));\n }\n}\n\n/** Options for push/replace navigation methods */\nexport interface RouterNavigationOptions {\n /** Scroll to top after navigation (default: true) */\n scrollToTop?: boolean;\n}\n\n// Context for useRouter hook\ntype RouterContext = {\n path: string;\n params: Record<string, string | string[]>;\n searchParams: URLSearchParams;\n push: (href: string, options?: RouterNavigationOptions) => void;\n replace: (href: string, options?: RouterNavigationOptions) => void;\n on: (event: RouterEvent, listener: EventListener) => () => void;\n status: 200 | 404;\n isNavigating: boolean;\n /** Indicates content is stale (old content shown while new content renders) - React 18+ concurrent feature */\n isPending: boolean;\n};\n\nexport const RouterContext = React.createContext<RouterContext | null>(null);\n\n/**\n * Access router context inside a component tree managed by <AppRouter />.\n *\n * Provides current path, route params, URL search params and navigation helpers\n * (\\`push\\`, \\`replace\\`) as well as an \\`on\\` method to subscribe to navigation events.\n * The \\`isNavigating\\` property indicates when a navigation is in progress.\n * The \\`isPending\\` property indicates when content is stale (React concurrent features).\n * Throws when used outside of an <AppRouter /> provider.\n */\nexport function useRouter() {\n const ctx = React.useContext(RouterContext);\n if (!ctx) {\n // During HMR in development, context might be temporarily unavailable\n // Provide a temporary fallback to prevent white screen of death\n // Re-extract params from current path using stored routes\n if (typeof window !== \"undefined\" && isDevEnvironment()) {\n const currentPath = window.location.pathname;\n return {\n path: currentPath,\n params: extractParamsFromPath(currentPath),\n searchParams: new URLSearchParams(window.location.search),\n push: (href: string, options?: RouterNavigationOptions) => {\n window.history.pushState({}, \"\", href);\n if (options?.scrollToTop !== false) {\n window.scrollTo({ top: 0, left: 0, behavior: \"smooth\" });\n }\n window.dispatchEvent(new PopStateEvent(\"popstate\"));\n },\n replace: (href: string, options?: RouterNavigationOptions) => {\n window.history.replaceState({}, \"\", href);\n if (options?.scrollToTop !== false) {\n window.scrollTo({ top: 0, left: 0, behavior: \"smooth\" });\n }\n window.dispatchEvent(new PopStateEvent(\"popstate\"));\n },\n on: () => () => {},\n status: 200 as const,\n isNavigating: false,\n isPending: false,\n };\n }\n throw new Error(\"useRouter must be used inside <AppRouter>\");\n }\n return ctx;\n}\n\n/**\n * Redirect component for declarative navigation.\n * Use this instead of calling router.push() during render.\n *\n * @example\n * \\`\\`\\`tsx\n * export default function Docs() {\n * return <Redirect to=\"/docs/getting-started\" />;\n * }\n * \\`\\`\\`\n */\nexport function Redirect({ to, replace = false }: { to: string; replace?: boolean }) {\n const hasRedirected = React.useRef(false);\n\n // Use useLayoutEffect to redirect before paint\n React.useLayoutEffect(() => {\n const targetPath = to.split(\"?\")[0];\n if (!hasRedirected.current && window.location.pathname !== targetPath) {\n hasRedirected.current = true;\n\n // Perform navigation\n if (replace) {\n window.history.replaceState(null, \"\", to);\n } else {\n window.history.pushState(null, \"\", to);\n }\n\n // Emit navigation event to update router state\n routerEventEmitter.emit(\"navigation\", {\n from: window.location.pathname,\n to: targetPath,\n });\n }\n }, [to, replace]);\n\n return null;\n}\n\n/** Options for navigation */\ninterface NavigateOptions {\n replace?: boolean;\n scrollToTop?: boolean;\n}\n\n// Navigation helper\nfunction navigate(href: string, options: NavigateOptions = {}) {\n const { replace = false, scrollToTop = true } = options;\n const from = window.location.pathname;\n const to = href.split(\"?\")[0]; // Extract pathname from href\n\n // Emit before-navigation event (can be prevented)\n const canNavigate = routerEventEmitter.emit(\"before-navigation\", { from, to });\n if (!canNavigate) {\n return; // Navigation was prevented\n }\n\n // Set navigating state to true before navigation\n currentLocation = { ...currentLocation, isNavigating: true };\n locationListeners.forEach((listener) => listener());\n\n if (replace) {\n window.history.replaceState(null, \"\", href);\n } else {\n window.history.pushState(null, \"\", href);\n }\n\n // Scroll to top immediately after pushState, before React re-renders.\n // Using instant scroll avoids race conditions where smooth scrolling\n // gets interrupted by React DOM updates, especially on Safari mobile.\n if (scrollToTop) {\n window.scrollTo({ top: 0, left: 0, behavior: \"instant\" });\n }\n\n // Update location state synchronously so there is no stale-state window\n // between pushState and the next render.\n updateLocation(false);\n\n // Emit navigation event after state is consistent\n routerEventEmitter.emit(\"navigation\", { from, to });\n}\n\nexport type LinkProps = React.PropsWithChildren<\n Omit<React.AnchorHTMLAttributes<HTMLAnchorElement>, \"href\"> & {\n href: string;\n replace?: boolean;\n /** Disable prefetching on hover (default: false - prefetch is enabled) */\n prefetch?: boolean;\n /** Scroll to top after navigation (default: true) */\n scrollToTop?: boolean;\n }\n>;\n\n/**\n * Check if a URL is external (different origin).\n */\nfunction isExternalUrl(href: string): boolean {\n if (typeof window === \"undefined\") {\n return false;\n }\n try {\n const url = new URL(href, window.location.origin);\n return url.origin !== window.location.origin;\n } catch {\n return false;\n }\n}\n\n// Store routes globally for prefetching (set by AppRouter)\n// Preserve across HMR in dev mode\nlet globalRoutes: RouteEntry[];\n\nif (typeof window !== \"undefined\" && isDevEnvironment()) {\n const globalWindow = window as typeof window & { __heliumGlobalRoutes?: RouteEntry[] };\n if (!globalWindow.__heliumGlobalRoutes) {\n globalWindow.__heliumGlobalRoutes = [];\n }\n globalRoutes = globalWindow.__heliumGlobalRoutes;\n} else {\n globalRoutes = [];\n}\n\n/**\n * Client-side navigation link.\n *\n * Intercepts left-clicks and uses the router's navigation helpers for SPA\n * navigation. Keeps normal anchor behaviour when modifier keys are used,\n * when the link is external, or when `target` / `download` attributes\n * are present.\n *\n * Automatically prefetches page chunks on hover for faster navigation.\n */\nexport function Link(props: LinkProps) {\n const {\n children,\n href,\n className,\n prefetch: prefetchProp = true,\n scrollToTop = true,\n replace: replaceProp,\n target,\n download,\n onClick: userOnClick,\n onMouseEnter: userOnMouseEnter,\n onFocus: userOnFocus,\n ...restProps\n } = props;\n\n const onClick = (e: React.MouseEvent<HTMLAnchorElement>) => {\n // Let user's onClick run first so they can call e.preventDefault()\n userOnClick?.(e);\n\n if (\n e.defaultPrevented ||\n e.button !== 0 || // only left click\n e.metaKey ||\n e.ctrlKey ||\n e.shiftKey ||\n e.altKey ||\n target || // let browser handle target=\"_blank\" etc.\n download != null || // let browser handle downloads\n isExternalUrl(href) // let browser handle external links\n ) {\n return;\n }\n e.preventDefault();\n navigate(href, { replace: replaceProp, scrollToTop });\n };\n\n const onMouseEnter = async (e: React.MouseEvent<HTMLAnchorElement>) => {\n // Prefetch the route on hover if enabled and not external (lazy-load prefetch logic)\n if (prefetchProp && !isExternalUrl(href) && globalRoutes.length > 0) {\n const { prefetchRoute } = await import(\"./prefetch.js\");\n prefetchRoute(href, globalRoutes);\n }\n userOnMouseEnter?.(e);\n };\n\n const onFocus = async (e: React.FocusEvent<HTMLAnchorElement>) => {\n // Also prefetch on focus (keyboard navigation)\n if (prefetchProp && !isExternalUrl(href) && globalRoutes.length > 0) {\n const { prefetchRoute } = await import(\"./prefetch.js\");\n prefetchRoute(href, globalRoutes);\n }\n userOnFocus?.(e);\n };\n\n return (\n <a {...restProps} href={href} target={target} download={download} onClick={onClick} onMouseEnter={onMouseEnter} onFocus={onFocus} className={className}>\n {children}\n </a>\n );\n}\n\n// AppShell props type\n/**\n * Props passed to an optional \\`AppShell\\` wrapper component used by <AppRouter />.\n *\n * \\`Component\\` — the page component to render. \\`pageProps\\` — props provided to the page.\n */\nexport type AppShellProps<TPageProps extends Record<string, unknown> = Record<string, unknown>> = {\n Component: ComponentType<TPageProps>;\n pageProps: TPageProps;\n children?: React.ReactNode;\n};\n\n// Main router component\nexport function AppRouter({ AppShell }: { AppShell?: ComponentType<AppShellProps> }) {\n // useTransition for concurrent rendering - allows React to keep UI responsive during navigation\n const [isPending, startTransition] = useTransition();\n\n // Build routes once on mount (client-side only)\n const { routes, NotFound } = useMemo(() => {\n if (typeof window === \"undefined\") {\n return { routes: [], NotFound: undefined };\n }\n const result = buildRoutes();\n // Store routes globally for Link prefetching\n // In dev mode, also update the global reference to survive HMR\n if (isDevEnvironment()) {\n const globalWindow = window as typeof window & { __heliumGlobalRoutes?: RouteEntry[] };\n globalWindow.__heliumGlobalRoutes = result.routes;\n // Update the module-level reference as well\n globalRoutes.length = 0;\n globalRoutes.push(...result.routes);\n } else {\n globalRoutes = result.routes;\n }\n return result;\n }, []);\n\n // Use useSyncExternalStore to subscribe to location changes\n // This ensures synchronous updates when location changes\n const state = useSyncExternalStore(subscribeToLocation, getLocationSnapshot, getServerSnapshot);\n const [runtimeSSRProps, setRuntimeSSRProps] = React.useState<Record<string, unknown>>(() => {\n const payload = getInitialSSRBootstrap();\n if (!payload) {\n return {};\n }\n\n if (payload.path === window.location.pathname) {\n return payload.props;\n }\n\n return {};\n });\n const [hydrationDone, setHydrationDone] = React.useState(false);\n\n const match = useMemo(() => matchRoute(state.path, routes), [state.path, routes]);\n\n // Use matched params, or fall back to re-extracting from path using global routes during HMR\n const currentParams = match?.params ?? (isDevEnvironment() ? extractParamsFromPath(state.path) : {});\n\n // In dev mode, always read fresh searchParams from URL to handle HMR edge cases\n const currentSearchParams = isDevEnvironment() ? new URLSearchParams(window.location.search) : state.searchParams;\n\n const routerValue: RouterContext = {\n path: state.path,\n params: currentParams,\n searchParams: currentSearchParams,\n push: (href, options) => {\n // Wrap navigation in startTransition for smoother updates\n startTransition(() => {\n navigate(href, { scrollToTop: options?.scrollToTop });\n });\n },\n replace: (href, options) => {\n startTransition(() => {\n navigate(href, { replace: true, scrollToTop: options?.scrollToTop });\n });\n },\n on: (event, listener) => routerEventEmitter.on(event, listener),\n status: match ? 200 : 404,\n isNavigating: state.isNavigating,\n isPending,\n };\n\n React.useEffect(() => {\n const targetPath = `${state.path}${window.location.search || \"\"}`;\n\n // On first client render, if SSR payload already exists for this path, keep it.\n if (!hydrationDone) {\n const bootstrap = getInitialSSRBootstrap();\n if (bootstrap && bootstrap.path === state.path) {\n setHydrationDone(true);\n return;\n }\n setHydrationDone(true);\n }\n\n let cancelled = false;\n\n const load = async () => {\n const ssrPayload = await fetchSSRPageProps(targetPath);\n if (cancelled) {\n return;\n }\n\n if (ssrPayload.kind === \"redirect\") {\n const destination = ssrPayload.redirect.destination;\n\n if (isExternalUrl(destination)) {\n window.location.assign(destination);\n return;\n }\n\n navigate(destination, {\n replace: ssrPayload.redirect.replace ?? true,\n scrollToTop: true,\n });\n return;\n }\n\n if (ssrPayload.kind === \"props\") {\n setRuntimeSSRProps(ssrPayload.props);\n return;\n }\n\n setRuntimeSSRProps({});\n };\n\n void load();\n\n return () => {\n cancelled = true;\n };\n }, [state.path, currentSearchParams.toString(), hydrationDone]);\n\n React.useEffect(() => {\n const controller = new AbortController();\n const targetPath = `${state.path}${window.location.search || \"\"}`;\n\n const syncMetadata = async () => {\n try {\n if (controller.signal.aborted) {\n return;\n }\n\n const result = await rpcCallWithOptions<ClientSocialMeta | null, { path: string }>(\n SEO_METADATA_RPC_METHOD,\n { path: targetPath },\n {\n forceHttp: isAutoHttpOnMobileEnabled() && isMobileRpcDevice(),\n }\n );\n\n if (controller.signal.aborted) {\n return;\n }\n\n applyRouteMetadata(result.data ?? null);\n } catch (error) {\n if ((error as { name?: string })?.name === \"AbortError\") {\n return;\n }\n }\n };\n\n syncMetadata();\n\n return () => controller.abort();\n }, [state.path, currentSearchParams.toString()]);\n\n if (!match) {\n const NotFoundComp = NotFound ?? (() => <div>Not found</div>);\n const content = <NotFoundComp />;\n\n return <RouterContext.Provider value={routerValue}>{AppShell ? <AppShell Component={NotFoundComp} pageProps={{}} /> : content}</RouterContext.Provider>;\n }\n\n const Page = match.route.Component as ComponentType<{ params: Record<string, string | string[]>; searchParams: URLSearchParams }>;\n const pageProps = {\n ...runtimeSSRProps,\n params: match.params,\n searchParams: currentSearchParams,\n };\n\n // Create a wrapped component that includes all layouts\n const WrappedPage = () => {\n let content = <Page {...pageProps} />;\n // Wrap page with layouts (from outer to inner)\n for (let i = match.route.layouts.length - 1; i >= 0; i--) {\n const Layout = match.route.layouts[i];\n content = <Layout>{content}</Layout>;\n }\n return content;\n };\n\n const finalContent = AppShell ? (\n <AppShell Component={WrappedPage} pageProps={pageProps}>\n <WrappedPage />\n </AppShell>\n ) : (\n <WrappedPage />\n );\n\n return <RouterContext.Provider value={routerValue}>{finalContent}</RouterContext.Provider>;\n}\n\ntype ClientSocialMeta = {\n title: string;\n description?: string;\n image?: string;\n canonicalUrl?: string;\n siteName?: string;\n type?: string;\n robots?: string;\n twitterCard?: \"summary\" | \"summary_large_image\" | \"app\" | \"player\";\n twitterSite?: string;\n twitterCreator?: string;\n};\n\nfunction applyRouteMetadata(meta: ClientSocialMeta | null) {\n if (typeof document === \"undefined\") {\n return;\n }\n\n removeExistingSeoTags();\n\n if (!meta) {\n return;\n }\n\n document.title = meta.title;\n\n const entries: Array<{ tag: \"meta\" | \"link\"; attrs: Record<string, string> }> = [];\n\n entries.push({ tag: \"meta\", attrs: { property: \"og:title\", content: meta.title } });\n entries.push({ tag: \"meta\", attrs: { property: \"og:type\", content: meta.type ?? \"website\" } });\n entries.push({ tag: \"meta\", attrs: { name: \"twitter:card\", content: meta.twitterCard ?? \"summary_large_image\" } });\n entries.push({ tag: \"meta\", attrs: { name: \"twitter:title\", content: meta.title } });\n\n if (meta.description) {\n entries.push({ tag: \"meta\", attrs: { name: \"description\", content: meta.description } });\n entries.push({ tag: \"meta\", attrs: { property: \"og:description\", content: meta.description } });\n entries.push({ tag: \"meta\", attrs: { name: \"twitter:description\", content: meta.description } });\n }\n\n if (meta.image) {\n entries.push({ tag: \"meta\", attrs: { property: \"og:image\", content: meta.image } });\n entries.push({ tag: \"meta\", attrs: { name: \"twitter:image\", content: meta.image } });\n }\n\n if (meta.canonicalUrl) {\n entries.push({ tag: \"meta\", attrs: { property: \"og:url\", content: meta.canonicalUrl } });\n entries.push({ tag: \"link\", attrs: { rel: \"canonical\", href: meta.canonicalUrl } });\n }\n\n if (meta.siteName) {\n entries.push({ tag: \"meta\", attrs: { property: \"og:site_name\", content: meta.siteName } });\n }\n\n if (meta.robots) {\n entries.push({ tag: \"meta\", attrs: { name: \"robots\", content: meta.robots } });\n }\n\n if (meta.twitterSite) {\n entries.push({ tag: \"meta\", attrs: { name: \"twitter:site\", content: meta.twitterSite } });\n }\n\n if (meta.twitterCreator) {\n entries.push({ tag: \"meta\", attrs: { name: \"twitter:creator\", content: meta.twitterCreator } });\n }\n\n for (const entry of entries) {\n const node = document.createElement(entry.tag);\n for (const [key, value] of Object.entries(entry.attrs)) {\n node.setAttribute(key, value);\n }\n node.setAttribute(\"data-helium-seo\", \"true\");\n document.head.appendChild(node);\n }\n}\n\nfunction removeExistingSeoTags() {\n const headNodes = Array.from(document.head.querySelectorAll(\"meta, link\"));\n\n for (const node of headNodes) {\n if (node.getAttribute(\"data-helium-seo\") === \"true\") {\n node.remove();\n continue;\n }\n\n if (node.tagName.toLowerCase() === \"link\") {\n const rel = (node.getAttribute(\"rel\") || \"\").toLowerCase();\n if (rel === \"canonical\") {\n node.remove();\n }\n continue;\n }\n\n const name = (node.getAttribute(\"name\") || \"\").toLowerCase();\n const property = (node.getAttribute(\"property\") || \"\").toLowerCase();\n\n if (name === \"description\" || name === \"robots\" || name.startsWith(\"twitter:\")) {\n node.remove();\n continue;\n }\n\n if (property.startsWith(\"og:\")) {\n node.remove();\n }\n }\n}\n"]}
@@ -6,7 +6,17 @@ export interface ServerSidePropsRequest {
6
6
  query: Record<string, string>;
7
7
  params: Record<string, string | string[]>;
8
8
  }
9
- export type ServerSidePropsHandler = (req: ServerSidePropsRequest, ctx: HeliumContext) => Promise<Record<string, unknown> | null | undefined> | Record<string, unknown> | null | undefined;
9
+ export interface ServerSideRedirect {
10
+ destination: string;
11
+ permanent?: boolean;
12
+ statusCode?: 301 | 302 | 303 | 307 | 308;
13
+ replace?: boolean;
14
+ }
15
+ export interface ServerSideRedirectResult {
16
+ redirect: ServerSideRedirect;
17
+ }
18
+ export type ServerSidePropsResult = Record<string, unknown> | ServerSideRedirectResult | null | undefined;
19
+ export type ServerSidePropsHandler = (req: ServerSidePropsRequest, ctx: HeliumContext) => Promise<ServerSidePropsResult> | ServerSidePropsResult;
10
20
  /**
11
21
  * Type for convention-based page server props functions:
12
22
  *
@@ -1 +1 @@
1
- {"version":3,"file":"defineServerSideProps.d.ts","sourceRoot":"","sources":["../../src/server/defineServerSideProps.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAElD,MAAM,WAAW,sBAAsB;IACnC,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,SAAS,CAAC,CAAC;IACvD,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC9B,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC,CAAC;CAC7C;AAED,MAAM,MAAM,sBAAsB,GAAG,CACjC,GAAG,EAAE,sBAAsB,EAC3B,GAAG,EAAE,aAAa,KACjB,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,GAAG,SAAS,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,GAAG,SAAS,CAAC;AAEtG;;;;;;;;;;GAUG;AACH,MAAM,MAAM,kBAAkB,GAAG,sBAAsB,CAAC"}
1
+ {"version":3,"file":"defineServerSideProps.d.ts","sourceRoot":"","sources":["../../src/server/defineServerSideProps.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAElD,MAAM,WAAW,sBAAsB;IACnC,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,SAAS,CAAC,CAAC;IACvD,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC9B,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC,CAAC;CAC7C;AAED,MAAM,WAAW,kBAAkB;IAC/B,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,UAAU,CAAC,EAAE,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC;IACzC,OAAO,CAAC,EAAE,OAAO,CAAC;CACrB;AAED,MAAM,WAAW,wBAAwB;IACrC,QAAQ,EAAE,kBAAkB,CAAC;CAChC;AAED,MAAM,MAAM,qBAAqB,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,wBAAwB,GAAG,IAAI,GAAG,SAAS,CAAC;AAE1G,MAAM,MAAM,sBAAsB,GAAG,CAAC,GAAG,EAAE,sBAAsB,EAAE,GAAG,EAAE,aAAa,KAAK,OAAO,CAAC,qBAAqB,CAAC,GAAG,qBAAqB,CAAC;AAEjJ;;;;;;;;;;GAUG;AACH,MAAM,MAAM,kBAAkB,GAAG,sBAAsB,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"defineServerSideProps.js","sourceRoot":"","sources":["../../src/server/defineServerSideProps.ts"],"names":[],"mappings":"","sourcesContent":["import type { HeliumContext } from \"./context.js\";\n\nexport interface ServerSidePropsRequest {\n method: string;\n path: string;\n headers: Record<string, string | string[] | undefined>;\n query: Record<string, string>;\n params: Record<string, string | string[]>;\n}\n\nexport type ServerSidePropsHandler = (\n req: ServerSidePropsRequest,\n ctx: HeliumContext\n) => Promise<Record<string, unknown> | null | undefined> | Record<string, unknown> | null | undefined;\n\n/**\n * Type for convention-based page server props functions:\n *\n * ```ts\n * import type { GetServerSideProps } from \"heliumts/server\";\n *\n * export const getServerSideProps: GetServerSideProps = async (req, ctx) => {\n * return { user: await getUser(req) };\n * };\n * ```\n */\nexport type GetServerSideProps = ServerSidePropsHandler;\n"]}
1
+ {"version":3,"file":"defineServerSideProps.js","sourceRoot":"","sources":["../../src/server/defineServerSideProps.ts"],"names":[],"mappings":"","sourcesContent":["import type { HeliumContext } from \"./context.js\";\n\nexport interface ServerSidePropsRequest {\n method: string;\n path: string;\n headers: Record<string, string | string[] | undefined>;\n query: Record<string, string>;\n params: Record<string, string | string[]>;\n}\n\nexport interface ServerSideRedirect {\n destination: string;\n permanent?: boolean;\n statusCode?: 301 | 302 | 303 | 307 | 308;\n replace?: boolean;\n}\n\nexport interface ServerSideRedirectResult {\n redirect: ServerSideRedirect;\n}\n\nexport type ServerSidePropsResult = Record<string, unknown> | ServerSideRedirectResult | null | undefined;\n\nexport type ServerSidePropsHandler = (req: ServerSidePropsRequest, ctx: HeliumContext) => Promise<ServerSidePropsResult> | ServerSidePropsResult;\n\n/**\n * Type for convention-based page server props functions:\n *\n * ```ts\n * import type { GetServerSideProps } from \"heliumts/server\";\n *\n * export const getServerSideProps: GetServerSideProps = async (req, ctx) => {\n * return { user: await getUser(req) };\n * };\n * ```\n */\nexport type GetServerSideProps = ServerSidePropsHandler;\n"]}
@@ -1,4 +1,9 @@
1
1
  import type { HeliumContext } from "./context.js";
2
+ export type WorkerCleanup = (() => Promise<void> | void) | void;
3
+ export interface WorkerLifecycle {
4
+ signal: AbortSignal;
5
+ onCleanup: (cleanup: WorkerCleanup) => void;
6
+ }
2
7
  export interface WorkerOptions {
3
8
  /**
4
9
  * The name of the worker, used for logging and identification.
@@ -27,7 +32,7 @@ export interface WorkerOptions {
27
32
  */
28
33
  autoStart?: boolean;
29
34
  }
30
- export type WorkerHandler = (ctx: HeliumContext) => Promise<void> | void;
35
+ export type WorkerHandler = (ctx: HeliumContext, lifecycle: WorkerLifecycle) => Promise<WorkerCleanup> | WorkerCleanup;
31
36
  export type HeliumWorkerDef = {
32
37
  __kind: "worker";
33
38
  __id: string;
@@ -1 +1 @@
1
- {"version":3,"file":"defineWorker.d.ts","sourceRoot":"","sources":["../../src/server/defineWorker.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAElD,MAAM,WAAW,aAAa;IAC1B;;;OAGG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC;IAEd;;;OAGG;IACH,WAAW,CAAC,EAAE,OAAO,CAAC;IAEtB;;;OAGG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC;IAExB;;;;OAIG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IAErB;;;OAGG;IACH,SAAS,CAAC,EAAE,OAAO,CAAC;CACvB;AAED,MAAM,MAAM,aAAa,GAAG,CAAC,GAAG,EAAE,aAAa,KAAK,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;AAEzE,MAAM,MAAM,eAAe,GAAG;IAC1B,MAAM,EAAE,QAAQ,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,aAAa,CAAC;IACvB,OAAO,EAAE,QAAQ,CAAC,aAAa,CAAC,CAAC;CACpC,CAAC;AAEF,MAAM,WAAW,cAAc;IAC3B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,SAAS,GAAG,SAAS,GAAG,SAAS,GAAG,YAAY,CAAC;IACzD,SAAS,EAAE,IAAI,GAAG,IAAI,CAAC;IACvB,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,KAAK,CAAC;IAClB,IAAI,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CAC7B;AAYD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2CG;AACH,wBAAgB,YAAY,CAAC,OAAO,EAAE,aAAa,EAAE,OAAO,GAAE,aAAkB,GAAG,eAAe,CAsBjG;AAED;;;GAGG;AACH,wBAAsB,WAAW,CAAC,MAAM,EAAE,eAAe,EAAE,aAAa,EAAE,MAAM,aAAa,GAAG,OAAO,CAAC,cAAc,CAAC,CAyFtH;AAED;;GAEG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAUhD;AAED;;GAEG;AACH,wBAAsB,cAAc,IAAI,OAAO,CAAC,IAAI,CAAC,CAQpD;AAED;;GAEG;AACH,wBAAgB,eAAe,IAAI,cAAc,EAAE,CAElD;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,cAAc,GAAG,SAAS,CAEtE"}
1
+ {"version":3,"file":"defineWorker.d.ts","sourceRoot":"","sources":["../../src/server/defineWorker.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAElD,MAAM,MAAM,aAAa,GAAG,CAAC,MAAM,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,GAAG,IAAI,CAAC;AAEhE,MAAM,WAAW,eAAe;IAC5B,MAAM,EAAE,WAAW,CAAC;IACpB,SAAS,EAAE,CAAC,OAAO,EAAE,aAAa,KAAK,IAAI,CAAC;CAC/C;AAED,MAAM,WAAW,aAAa;IAC1B;;;OAGG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC;IAEd;;;OAGG;IACH,WAAW,CAAC,EAAE,OAAO,CAAC;IAEtB;;;OAGG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC;IAExB;;;;OAIG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IAErB;;;OAGG;IACH,SAAS,CAAC,EAAE,OAAO,CAAC;CACvB;AAED,MAAM,MAAM,aAAa,GAAG,CAAC,GAAG,EAAE,aAAa,EAAE,SAAS,EAAE,eAAe,KAAK,OAAO,CAAC,aAAa,CAAC,GAAG,aAAa,CAAC;AAEvH,MAAM,MAAM,eAAe,GAAG;IAC1B,MAAM,EAAE,QAAQ,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,aAAa,CAAC;IACvB,OAAO,EAAE,QAAQ,CAAC,aAAa,CAAC,CAAC;CACpC,CAAC;AAEF,MAAM,WAAW,cAAc;IAC3B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,SAAS,GAAG,SAAS,GAAG,SAAS,GAAG,YAAY,CAAC;IACzD,SAAS,EAAE,IAAI,GAAG,IAAI,CAAC;IACvB,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,KAAK,CAAC;IAClB,IAAI,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CAC7B;AAoED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2CG;AACH,wBAAgB,YAAY,CAAC,OAAO,EAAE,aAAa,EAAE,OAAO,GAAE,aAAkB,GAAG,eAAe,CAsBjG;AAED;;;GAGG;AACH,wBAAsB,WAAW,CAAC,MAAM,EAAE,eAAe,EAAE,aAAa,EAAE,MAAM,aAAa,GAAG,OAAO,CAAC,cAAc,CAAC,CA8GtH;AAED;;GAEG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAchD;AAED;;GAEG;AACH,wBAAsB,cAAc,IAAI,OAAO,CAAC,IAAI,CAAC,CASpD;AAED;;GAEG;AACH,wBAAgB,eAAe,IAAI,cAAc,EAAE,CAElD;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,cAAc,GAAG,SAAS,CAEtE"}
@@ -1,6 +1,41 @@
1
1
  import { log } from "../utils/logger.js";
2
2
  // Map to track running worker instances
3
3
  const runningWorkers = new Map();
4
+ function isCleanupHandler(cleanup) {
5
+ return typeof cleanup === "function";
6
+ }
7
+ function registerCleanup(workerState, cleanup) {
8
+ if (!isCleanupHandler(cleanup)) {
9
+ return;
10
+ }
11
+ workerState.cleanupHandlers.push(cleanup);
12
+ }
13
+ async function runWorkerCleanup(name, workerState) {
14
+ if (workerState.cleanupPromise) {
15
+ await workerState.cleanupPromise;
16
+ return;
17
+ }
18
+ workerState.cleanupPromise = (async () => {
19
+ const cleanupHandlers = workerState.cleanupHandlers.splice(0).reverse();
20
+ for (const cleanup of cleanupHandlers) {
21
+ try {
22
+ await cleanup();
23
+ }
24
+ catch (error) {
25
+ log("error", `Worker '${name}' cleanup failed:`, error);
26
+ }
27
+ }
28
+ })();
29
+ await workerState.cleanupPromise;
30
+ }
31
+ function waitForAbort(signal) {
32
+ if (signal.aborted) {
33
+ return Promise.resolve();
34
+ }
35
+ return new Promise((resolve) => {
36
+ signal.addEventListener("abort", () => resolve(), { once: true });
37
+ });
38
+ }
4
39
  /**
5
40
  * Create a Helium background worker definition.
6
41
  *
@@ -79,6 +114,13 @@ export async function startWorker(worker, createContext) {
79
114
  }
80
115
  const abortController = new AbortController();
81
116
  let restartCount = 0;
117
+ const workerState = {
118
+ abortController,
119
+ promise: Promise.resolve(),
120
+ instance: undefined,
121
+ cleanupHandlers: [],
122
+ cleanupPromise: null,
123
+ };
82
124
  const instance = {
83
125
  id: name,
84
126
  name,
@@ -88,10 +130,12 @@ export async function startWorker(worker, createContext) {
88
130
  stop: async () => {
89
131
  abortController.abort();
90
132
  instance.status = "stopped";
133
+ await runWorkerCleanup(name, workerState);
91
134
  runningWorkers.delete(name);
92
135
  log("info", `Worker '${name}' stopped`);
93
136
  },
94
137
  };
138
+ workerState.instance = instance;
95
139
  const runWorker = async () => {
96
140
  while (!abortController.signal.aborted) {
97
141
  try {
@@ -99,9 +143,20 @@ export async function startWorker(worker, createContext) {
99
143
  instance.startedAt = new Date();
100
144
  log("info", `Starting worker '${name}'`);
101
145
  const ctx = createContext();
102
- await handler(ctx);
146
+ const lifecycle = {
147
+ signal: abortController.signal,
148
+ onCleanup: (cleanup) => {
149
+ registerCleanup(workerState, cleanup);
150
+ },
151
+ };
152
+ const cleanup = await handler(ctx, lifecycle);
153
+ registerCleanup(workerState, cleanup);
154
+ if (isCleanupHandler(cleanup) && !abortController.signal.aborted) {
155
+ await waitForAbort(abortController.signal);
156
+ }
103
157
  // If handler completes normally, exit the loop
104
158
  if (!abortController.signal.aborted) {
159
+ await runWorkerCleanup(name, workerState);
105
160
  log("info", `Worker '${name}' completed successfully`);
106
161
  instance.status = "stopped";
107
162
  runningWorkers.delete(name);
@@ -113,6 +168,8 @@ export async function startWorker(worker, createContext) {
113
168
  // Worker was intentionally stopped
114
169
  break;
115
170
  }
171
+ await runWorkerCleanup(name, workerState);
172
+ workerState.cleanupPromise = null;
116
173
  instance.lastError = error instanceof Error ? error : new Error(String(error));
117
174
  instance.status = "crashed";
118
175
  restartCount++;
@@ -137,11 +194,8 @@ export async function startWorker(worker, createContext) {
137
194
  }
138
195
  };
139
196
  const promise = runWorker();
140
- runningWorkers.set(name, {
141
- abortController,
142
- promise,
143
- instance,
144
- });
197
+ workerState.promise = promise;
198
+ runningWorkers.set(name, workerState);
145
199
  return instance;
146
200
  }
147
201
  /**
@@ -152,8 +206,12 @@ export function stopWorker(name) {
152
206
  if (worker) {
153
207
  worker.abortController.abort();
154
208
  worker.instance.status = "stopped";
155
- runningWorkers.delete(name);
156
- log("info", `Worker '${name}' stopped`);
209
+ void runWorkerCleanup(name, worker)
210
+ .catch(() => { })
211
+ .finally(() => {
212
+ runningWorkers.delete(name);
213
+ log("info", `Worker '${name}' stopped`);
214
+ });
157
215
  return true;
158
216
  }
159
217
  return false;
@@ -167,6 +225,7 @@ export async function stopAllWorkers() {
167
225
  worker.abortController.abort();
168
226
  worker.instance.status = "stopped";
169
227
  }
228
+ await Promise.all(workers.map(async (worker) => runWorkerCleanup(worker.instance.name, worker)));
170
229
  runningWorkers.clear();
171
230
  log("info", `Stopped ${workers.length} worker(s)`);
172
231
  }
@@ -1 +1 @@
1
- {"version":3,"file":"defineWorker.js","sourceRoot":"","sources":["../../src/server/defineWorker.ts"],"names":[],"mappings":"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","sourcesContent":["import { log } from \"../utils/logger.js\";\nimport type { HeliumContext } from \"./context.js\";\n\nexport interface WorkerOptions {\n /**\n * The name of the worker, used for logging and identification.\n * If not provided, the handler function name will be used.\n */\n name?: string;\n\n /**\n * Whether the worker should automatically restart if it crashes.\n * Default: true\n */\n autoRestart?: boolean;\n\n /**\n * Delay in milliseconds before restarting the worker after a crash.\n * Default: 5000 (5 seconds)\n */\n restartDelayMs?: number;\n\n /**\n * Maximum number of restart attempts before giving up.\n * Set to 0 for unlimited restarts.\n * Default: 0 (unlimited)\n */\n maxRestarts?: number;\n\n /**\n * Whether to start the worker automatically on server startup.\n * Default: true\n */\n autoStart?: boolean;\n}\n\nexport type WorkerHandler = (ctx: HeliumContext) => Promise<void> | void;\n\nexport type HeliumWorkerDef = {\n __kind: \"worker\";\n __id: string;\n name: string;\n handler: WorkerHandler;\n options: Required<WorkerOptions>;\n};\n\nexport interface WorkerInstance {\n id: string;\n name: string;\n status: \"running\" | \"stopped\" | \"crashed\" | \"restarting\";\n startedAt: Date | null;\n restartCount: number;\n lastError?: Error;\n stop: () => Promise<void>;\n}\n\n// Map to track running worker instances\nconst runningWorkers = new Map<\n string,\n {\n abortController: AbortController;\n promise: Promise<void>;\n instance: WorkerInstance;\n }\n>();\n\n/**\n * Create a Helium background worker definition.\n *\n * Workers are long-running background processes that start when the server\n * starts and continue running until the server shuts down. They are ideal for:\n * - Queue consumers (processing jobs from Redis, RabbitMQ, SQS, etc.)\n * - Background task processors\n * - Scheduled jobs and cron-like tasks\n * - Real-time data synchronization\n * - WebSocket connection managers\n * - Cache warmers and data pre-loaders\n *\n * @example\n * ```typescript\n * // Basic worker\n * export const queueConsumer = defineWorker(async (ctx) => {\n * while (true) {\n * const job = await queue.pop();\n * if (job) {\n * await processJob(job);\n * }\n * await sleep(1000);\n * }\n * }, { name: 'queueConsumer' });\n *\n * // Worker with options\n * export const dataSync = defineWorker(async (ctx) => {\n * // Sync data every 30 seconds\n * while (true) {\n * await syncData();\n * await sleep(30000);\n * }\n * }, {\n * name: 'dataSync',\n * autoRestart: true,\n * restartDelayMs: 10000,\n * maxRestarts: 5\n * });\n * ```\n *\n * @param handler - The worker function that runs in the background\n * @param options - Configuration options for the worker\n * @returns A HeliumWorkerDef that will be started by the server runtime\n */\nexport function defineWorker(handler: WorkerHandler, options: WorkerOptions = {}): HeliumWorkerDef {\n if (!handler) {\n throw new Error(\"defineWorker requires a handler\");\n }\n\n const name = options.name || handler.name || \"anonymous\";\n\n const resolvedOptions: Required<WorkerOptions> = {\n name,\n autoRestart: options.autoRestart ?? true,\n restartDelayMs: options.restartDelayMs ?? 5000,\n maxRestarts: options.maxRestarts ?? 0,\n autoStart: options.autoStart ?? true,\n };\n\n return {\n __kind: \"worker\",\n __id: name,\n name,\n handler,\n options: resolvedOptions,\n };\n}\n\n/**\n * Start a worker and manage its lifecycle.\n * @internal\n */\nexport async function startWorker(worker: HeliumWorkerDef, createContext: () => HeliumContext): Promise<WorkerInstance> {\n const { name, handler, options } = worker;\n\n // Check if worker is already running\n if (runningWorkers.has(name)) {\n const existing = runningWorkers.get(name)!;\n log(\"warn\", `Worker '${name}' is already running`);\n return existing.instance;\n }\n\n const abortController = new AbortController();\n let restartCount = 0;\n\n const instance: WorkerInstance = {\n id: name,\n name,\n status: \"running\",\n startedAt: new Date(),\n restartCount: 0,\n stop: async () => {\n abortController.abort();\n instance.status = \"stopped\";\n runningWorkers.delete(name);\n log(\"info\", `Worker '${name}' stopped`);\n },\n };\n\n const runWorker = async (): Promise<void> => {\n while (!abortController.signal.aborted) {\n try {\n instance.status = \"running\";\n instance.startedAt = new Date();\n log(\"info\", `Starting worker '${name}'`);\n\n const ctx = createContext();\n await handler(ctx);\n\n // If handler completes normally, exit the loop\n if (!abortController.signal.aborted) {\n log(\"info\", `Worker '${name}' completed successfully`);\n instance.status = \"stopped\";\n runningWorkers.delete(name);\n }\n break;\n } catch (error) {\n if (abortController.signal.aborted) {\n // Worker was intentionally stopped\n break;\n }\n\n instance.lastError = error instanceof Error ? error : new Error(String(error));\n instance.status = \"crashed\";\n restartCount++;\n instance.restartCount = restartCount;\n\n log(\"error\", `Worker '${name}' crashed:`, error);\n\n // Check if we should restart\n if (options.autoRestart) {\n if (options.maxRestarts > 0 && restartCount >= options.maxRestarts) {\n log(\"error\", `Worker '${name}' exceeded max restarts (${options.maxRestarts}), giving up`);\n runningWorkers.delete(name);\n break;\n }\n\n instance.status = \"restarting\";\n log(\n \"info\",\n `Worker '${name}' will restart in ${options.restartDelayMs}ms (attempt ${restartCount}${options.maxRestarts > 0 ? `/${options.maxRestarts}` : \"\"})`\n );\n\n await new Promise((resolve) => setTimeout(resolve, options.restartDelayMs));\n } else {\n runningWorkers.delete(name);\n break;\n }\n }\n }\n };\n\n const promise = runWorker();\n\n runningWorkers.set(name, {\n abortController,\n promise,\n instance,\n });\n\n return instance;\n}\n\n/**\n * Stop a running worker by name.\n */\nexport function stopWorker(name: string): boolean {\n const worker = runningWorkers.get(name);\n if (worker) {\n worker.abortController.abort();\n worker.instance.status = \"stopped\";\n runningWorkers.delete(name);\n log(\"info\", `Worker '${name}' stopped`);\n return true;\n }\n return false;\n}\n\n/**\n * Stop all running workers.\n */\nexport async function stopAllWorkers(): Promise<void> {\n const workers = Array.from(runningWorkers.values());\n for (const worker of workers) {\n worker.abortController.abort();\n worker.instance.status = \"stopped\";\n }\n runningWorkers.clear();\n log(\"info\", `Stopped ${workers.length} worker(s)`);\n}\n\n/**\n * Get the status of all workers.\n */\nexport function getWorkerStatus(): WorkerInstance[] {\n return Array.from(runningWorkers.values()).map((w) => w.instance);\n}\n\n/**\n * Get a specific worker's status.\n */\nexport function getWorkerById(name: string): WorkerInstance | undefined {\n return runningWorkers.get(name)?.instance;\n}\n"]}
1
+ {"version":3,"file":"defineWorker.js","sourceRoot":"","sources":["../../src/server/defineWorker.ts"],"names":[],"mappings":"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","sourcesContent":["import { log } from \"../utils/logger.js\";\nimport type { HeliumContext } from \"./context.js\";\n\nexport type WorkerCleanup = (() => Promise<void> | void) | void;\n\nexport interface WorkerLifecycle {\n signal: AbortSignal;\n onCleanup: (cleanup: WorkerCleanup) => void;\n}\n\nexport interface WorkerOptions {\n /**\n * The name of the worker, used for logging and identification.\n * If not provided, the handler function name will be used.\n */\n name?: string;\n\n /**\n * Whether the worker should automatically restart if it crashes.\n * Default: true\n */\n autoRestart?: boolean;\n\n /**\n * Delay in milliseconds before restarting the worker after a crash.\n * Default: 5000 (5 seconds)\n */\n restartDelayMs?: number;\n\n /**\n * Maximum number of restart attempts before giving up.\n * Set to 0 for unlimited restarts.\n * Default: 0 (unlimited)\n */\n maxRestarts?: number;\n\n /**\n * Whether to start the worker automatically on server startup.\n * Default: true\n */\n autoStart?: boolean;\n}\n\nexport type WorkerHandler = (ctx: HeliumContext, lifecycle: WorkerLifecycle) => Promise<WorkerCleanup> | WorkerCleanup;\n\nexport type HeliumWorkerDef = {\n __kind: \"worker\";\n __id: string;\n name: string;\n handler: WorkerHandler;\n options: Required<WorkerOptions>;\n};\n\nexport interface WorkerInstance {\n id: string;\n name: string;\n status: \"running\" | \"stopped\" | \"crashed\" | \"restarting\";\n startedAt: Date | null;\n restartCount: number;\n lastError?: Error;\n stop: () => Promise<void>;\n}\n\n// Map to track running worker instances\nconst runningWorkers = new Map<\n string,\n {\n abortController: AbortController;\n promise: Promise<void>;\n instance: WorkerInstance;\n cleanupHandlers: Array<() => Promise<void> | void>;\n cleanupPromise: Promise<void> | null;\n }\n>();\n\nfunction isCleanupHandler(cleanup: WorkerCleanup): cleanup is () => Promise<void> | void {\n return typeof cleanup === \"function\";\n}\n\nfunction registerCleanup(\n workerState: {\n cleanupHandlers: Array<() => Promise<void> | void>;\n },\n cleanup: WorkerCleanup\n) {\n if (!isCleanupHandler(cleanup)) {\n return;\n }\n\n workerState.cleanupHandlers.push(cleanup);\n}\n\nasync function runWorkerCleanup(\n name: string,\n workerState: {\n cleanupHandlers: Array<() => Promise<void> | void>;\n cleanupPromise: Promise<void> | null;\n }\n): Promise<void> {\n if (workerState.cleanupPromise) {\n await workerState.cleanupPromise;\n return;\n }\n\n workerState.cleanupPromise = (async () => {\n const cleanupHandlers = workerState.cleanupHandlers.splice(0).reverse();\n\n for (const cleanup of cleanupHandlers) {\n try {\n await cleanup();\n } catch (error) {\n log(\"error\", `Worker '${name}' cleanup failed:`, error);\n }\n }\n })();\n\n await workerState.cleanupPromise;\n}\n\nfunction waitForAbort(signal: AbortSignal): Promise<void> {\n if (signal.aborted) {\n return Promise.resolve();\n }\n\n return new Promise((resolve) => {\n signal.addEventListener(\"abort\", () => resolve(), { once: true });\n });\n}\n\n/**\n * Create a Helium background worker definition.\n *\n * Workers are long-running background processes that start when the server\n * starts and continue running until the server shuts down. They are ideal for:\n * - Queue consumers (processing jobs from Redis, RabbitMQ, SQS, etc.)\n * - Background task processors\n * - Scheduled jobs and cron-like tasks\n * - Real-time data synchronization\n * - WebSocket connection managers\n * - Cache warmers and data pre-loaders\n *\n * @example\n * ```typescript\n * // Basic worker\n * export const queueConsumer = defineWorker(async (ctx) => {\n * while (true) {\n * const job = await queue.pop();\n * if (job) {\n * await processJob(job);\n * }\n * await sleep(1000);\n * }\n * }, { name: 'queueConsumer' });\n *\n * // Worker with options\n * export const dataSync = defineWorker(async (ctx) => {\n * // Sync data every 30 seconds\n * while (true) {\n * await syncData();\n * await sleep(30000);\n * }\n * }, {\n * name: 'dataSync',\n * autoRestart: true,\n * restartDelayMs: 10000,\n * maxRestarts: 5\n * });\n * ```\n *\n * @param handler - The worker function that runs in the background\n * @param options - Configuration options for the worker\n * @returns A HeliumWorkerDef that will be started by the server runtime\n */\nexport function defineWorker(handler: WorkerHandler, options: WorkerOptions = {}): HeliumWorkerDef {\n if (!handler) {\n throw new Error(\"defineWorker requires a handler\");\n }\n\n const name = options.name || handler.name || \"anonymous\";\n\n const resolvedOptions: Required<WorkerOptions> = {\n name,\n autoRestart: options.autoRestart ?? true,\n restartDelayMs: options.restartDelayMs ?? 5000,\n maxRestarts: options.maxRestarts ?? 0,\n autoStart: options.autoStart ?? true,\n };\n\n return {\n __kind: \"worker\",\n __id: name,\n name,\n handler,\n options: resolvedOptions,\n };\n}\n\n/**\n * Start a worker and manage its lifecycle.\n * @internal\n */\nexport async function startWorker(worker: HeliumWorkerDef, createContext: () => HeliumContext): Promise<WorkerInstance> {\n const { name, handler, options } = worker;\n\n // Check if worker is already running\n if (runningWorkers.has(name)) {\n const existing = runningWorkers.get(name)!;\n log(\"warn\", `Worker '${name}' is already running`);\n return existing.instance;\n }\n\n const abortController = new AbortController();\n let restartCount = 0;\n const workerState = {\n abortController,\n promise: Promise.resolve(),\n instance: undefined as unknown as WorkerInstance,\n cleanupHandlers: [] as Array<() => Promise<void> | void>,\n cleanupPromise: null as Promise<void> | null,\n };\n\n const instance: WorkerInstance = {\n id: name,\n name,\n status: \"running\",\n startedAt: new Date(),\n restartCount: 0,\n stop: async () => {\n abortController.abort();\n instance.status = \"stopped\";\n await runWorkerCleanup(name, workerState);\n runningWorkers.delete(name);\n log(\"info\", `Worker '${name}' stopped`);\n },\n };\n workerState.instance = instance;\n\n const runWorker = async (): Promise<void> => {\n while (!abortController.signal.aborted) {\n try {\n instance.status = \"running\";\n instance.startedAt = new Date();\n log(\"info\", `Starting worker '${name}'`);\n\n const ctx = createContext();\n const lifecycle: WorkerLifecycle = {\n signal: abortController.signal,\n onCleanup: (cleanup) => {\n registerCleanup(workerState, cleanup);\n },\n };\n const cleanup = await handler(ctx, lifecycle);\n registerCleanup(workerState, cleanup);\n\n if (isCleanupHandler(cleanup) && !abortController.signal.aborted) {\n await waitForAbort(abortController.signal);\n }\n\n // If handler completes normally, exit the loop\n if (!abortController.signal.aborted) {\n await runWorkerCleanup(name, workerState);\n log(\"info\", `Worker '${name}' completed successfully`);\n instance.status = \"stopped\";\n runningWorkers.delete(name);\n }\n break;\n } catch (error) {\n if (abortController.signal.aborted) {\n // Worker was intentionally stopped\n break;\n }\n\n await runWorkerCleanup(name, workerState);\n workerState.cleanupPromise = null;\n\n instance.lastError = error instanceof Error ? error : new Error(String(error));\n instance.status = \"crashed\";\n restartCount++;\n instance.restartCount = restartCount;\n\n log(\"error\", `Worker '${name}' crashed:`, error);\n\n // Check if we should restart\n if (options.autoRestart) {\n if (options.maxRestarts > 0 && restartCount >= options.maxRestarts) {\n log(\"error\", `Worker '${name}' exceeded max restarts (${options.maxRestarts}), giving up`);\n runningWorkers.delete(name);\n break;\n }\n\n instance.status = \"restarting\";\n log(\n \"info\",\n `Worker '${name}' will restart in ${options.restartDelayMs}ms (attempt ${restartCount}${options.maxRestarts > 0 ? `/${options.maxRestarts}` : \"\"})`\n );\n\n await new Promise((resolve) => setTimeout(resolve, options.restartDelayMs));\n } else {\n runningWorkers.delete(name);\n break;\n }\n }\n }\n };\n\n const promise = runWorker();\n workerState.promise = promise;\n\n runningWorkers.set(name, workerState);\n\n return instance;\n}\n\n/**\n * Stop a running worker by name.\n */\nexport function stopWorker(name: string): boolean {\n const worker = runningWorkers.get(name);\n if (worker) {\n worker.abortController.abort();\n worker.instance.status = \"stopped\";\n void runWorkerCleanup(name, worker)\n .catch(() => {})\n .finally(() => {\n runningWorkers.delete(name);\n log(\"info\", `Worker '${name}' stopped`);\n });\n return true;\n }\n return false;\n}\n\n/**\n * Stop all running workers.\n */\nexport async function stopAllWorkers(): Promise<void> {\n const workers = Array.from(runningWorkers.values());\n for (const worker of workers) {\n worker.abortController.abort();\n worker.instance.status = \"stopped\";\n }\n await Promise.all(workers.map(async (worker) => runWorkerCleanup(worker.instance.name, worker)));\n runningWorkers.clear();\n log(\"info\", `Stopped ${workers.length} worker(s)`);\n}\n\n/**\n * Get the status of all workers.\n */\nexport function getWorkerStatus(): WorkerInstance[] {\n return Array.from(runningWorkers.values()).map((w) => w.instance);\n}\n\n/**\n * Get a specific worker's status.\n */\nexport function getWorkerById(name: string): WorkerInstance | undefined {\n return runningWorkers.get(name)?.instance;\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"devServer.d.ts","sourceRoot":"","sources":["../../src/server/devServer.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAC7B,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAC/B,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAE/B,OAAO,KAAK,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAUtD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAGhD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAEzD,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAG7C,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAE/C,OAAO,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAE3D,OAAO,EAA6D,UAAU,EAAE,MAAM,UAAU,CAAC;AAMjG,KAAK,cAAc,GAAG,CAAC,QAAQ,EAAE,WAAW,EAAE,UAAU,EAAE,UAAU,EAAE,SAAS,EAAE,iBAAiB,KAAK,IAAI,CAAC;AAC5G,KAAK,UAAU,GAAG,IAAI,CAAC,MAAM,GAAG,KAAK,CAAC,MAAM,GAAG,KAAK,CAAC,WAAW,GAAG,KAAK,CAAC,iBAAiB,CAAC;AAE3F,UAAU,WAAW;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,eAAe,CAAC;CAC3B;AAED,KAAK,cAAc,GAAG,CAAC,MAAM,OAAO,CAAC,aAAa,CAAC;IAAE,SAAS,EAAE,aAAa,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;IAAC,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAAC,QAAQ,CAAC,EAAE,SAAS,CAAA;CAAE,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC;AAY7K;;;GAGG;AACH,wBAAgB,iBAAiB,CAC7B,UAAU,EAAE,UAAU,EACtB,YAAY,EAAE,cAAc,EAC5B,MAAM,GAAE,YAAiB,EACzB,OAAO,GAAE,WAAW,EAAO,EAC3B,QAAQ,GAAE,UAAU,EAAO,EAC3B,QAAQ,GAAE,cAAqB,QA6iBlC"}
1
+ {"version":3,"file":"devServer.d.ts","sourceRoot":"","sources":["../../src/server/devServer.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAC7B,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAC/B,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAE/B,OAAO,KAAK,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAUtD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAGhD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAEzD,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAG7C,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAE/C,OAAO,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAE3D,OAAO,EAAuD,UAAU,EAAE,MAAM,UAAU,CAAC;AAM3F,KAAK,cAAc,GAAG,CAAC,QAAQ,EAAE,WAAW,EAAE,UAAU,EAAE,UAAU,EAAE,SAAS,EAAE,iBAAiB,KAAK,IAAI,CAAC;AAC5G,KAAK,UAAU,GAAG,IAAI,CAAC,MAAM,GAAG,KAAK,CAAC,MAAM,GAAG,KAAK,CAAC,WAAW,GAAG,KAAK,CAAC,iBAAiB,CAAC;AAE3F,UAAU,WAAW;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,eAAe,CAAC;CAC3B;AAED,KAAK,cAAc,GAAG,CAAC,MAAM,OAAO,CAAC,aAAa,CAAC;IAAE,SAAS,EAAE,aAAa,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;IAAC,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAAC,QAAQ,CAAC,EAAE,SAAS,CAAA;CAAE,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC;AAqD7K;;;GAGG;AACH,wBAAgB,iBAAiB,CAC7B,UAAU,EAAE,UAAU,EACtB,YAAY,EAAE,cAAc,EAC5B,MAAM,GAAE,YAAiB,EACzB,OAAO,GAAE,WAAW,EAAO,EAC3B,QAAQ,GAAE,UAAU,EAAO,EAC3B,QAAQ,GAAE,cAAqB,QA4iBlC"}