@taujs/react 0.1.3 → 0.1.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -44,7 +44,7 @@ type HydrateAppOptions<T> = {
44
44
  declare function hydrateApp<T>({ appComponent, rootElementId, enableDebug, logger, dataKey, onHydrationError, onStart, onSuccess, }: HydrateAppOptions<T>): void;
45
45
 
46
46
  type RenderCallbacks<T> = {
47
- onHead?: (head: string) => boolean | void;
47
+ onHead?: (head: string) => void;
48
48
  onShellReady?: () => void;
49
49
  onAllReady?: (data: T) => void;
50
50
  onFinish?: (data: T) => void;
@@ -53,34 +53,36 @@ type RenderCallbacks<T> = {
53
53
  type StreamOptions = {
54
54
  /** Timeout in ms for shell to be ready (default: 10000) */
55
55
  shellTimeoutMs?: number;
56
- /** Whether to use cork/uncork for batched writes (default: true) */
57
- useCork?: boolean;
58
56
  };
59
- type HeadContext<T extends Record<string, unknown> = Record<string, unknown>> = {
57
+ type HeadContext<T extends Record<string, unknown> = Record<string, unknown>, R = unknown> = {
60
58
  data: T;
61
59
  meta: Record<string, unknown>;
60
+ routeContext?: R;
62
61
  };
63
62
  type SSRResult = {
64
63
  headContent: string;
65
64
  appHtml: string;
66
65
  aborted: boolean;
67
66
  };
68
- type StreamCallOptions = StreamOptions & {
67
+ type StreamCallOptions<R> = StreamOptions & {
69
68
  logger?: LoggerLike;
69
+ routeContext?: R;
70
70
  };
71
- declare function createRenderer<T extends Record<string, unknown>>({ appComponent, headContent, streamOptions, logger, enableDebug, }: {
71
+ declare function createRenderer<T extends Record<string, unknown> = Record<string, unknown>, R = unknown>({ appComponent, headContent, streamOptions, logger, enableDebug, }: {
72
72
  appComponent: (props: {
73
73
  location: string;
74
+ routeContext?: R;
74
75
  }) => React.ReactElement;
75
- headContent: (ctx: HeadContext<T>) => string;
76
+ headContent: (ctx: HeadContext<T, R>) => string;
76
77
  enableDebug?: boolean;
77
78
  logger?: LoggerLike;
78
79
  streamOptions?: StreamOptions;
79
80
  }): {
80
81
  renderSSR: (initialData: T, location: string, meta?: Record<string, unknown>, signal?: AbortSignal, opts?: {
81
82
  logger?: LoggerLike;
83
+ routeContext?: R;
82
84
  }) => Promise<SSRResult>;
83
- renderStream: (writable: Writable, callbacks: RenderCallbacks<T> | undefined, initialData: T | Promise<T> | (() => Promise<T>), location: string, bootstrapModules?: string, meta?: Record<string, unknown>, cspNonce?: string, signal?: AbortSignal, opts?: StreamCallOptions) => {
85
+ renderStream: (writable: Writable, callbacks: RenderCallbacks<T> | undefined, initialData: T | Promise<T> | (() => Promise<T>), location: string, bootstrapModules?: string, meta?: Record<string, unknown>, cspNonce?: string, signal?: AbortSignal, opts?: StreamCallOptions<R>) => {
84
86
  abort: () => void;
85
87
  done: Promise<void>;
86
88
  };
package/dist/index.js CHANGED
@@ -364,7 +364,7 @@ function createRenderer({
364
364
  logger,
365
365
  enableDebug = false
366
366
  }) {
367
- const { shellTimeoutMs = 1e4, useCork = true } = streamOptions;
367
+ const { shellTimeoutMs = 1e4 } = streamOptions;
368
368
  const renderSSR = async (initialData, location, meta = {}, signal, opts) => {
369
369
  const { log, warn } = createUILogger(opts?.logger ?? logger, {
370
370
  debugCategory: "ssr",
@@ -378,11 +378,12 @@ function createRenderer({
378
378
  let aborted = false;
379
379
  const onAbort = () => aborted = true;
380
380
  signal?.addEventListener("abort", onAbort, { once: true });
381
+ const routeContext = opts?.routeContext;
381
382
  try {
382
383
  log("Starting SSR:", location);
383
- const dynamicHead = headContent({ data: initialData, meta });
384
+ const dynamicHead = headContent({ data: initialData, meta, routeContext });
384
385
  const store = createSSRStore(initialData);
385
- const html = renderToString(/* @__PURE__ */ jsx3(SSRStoreProvider, { store, children: appComponent({ location }) }));
386
+ const html = renderToString(/* @__PURE__ */ jsx3(SSRStoreProvider, { store, children: appComponent({ location, routeContext }) }));
386
387
  if (aborted) {
387
388
  warn("SSR completed after client abort", { location });
388
389
  return { headContent: "", appHtml: "", aborted: true };
@@ -409,8 +410,8 @@ function createRenderer({
409
410
  context: { scope: "react-streaming" },
410
411
  enableDebug
411
412
  });
413
+ const routeContext = opts?.routeContext;
412
414
  const effectiveShellTimeout = opts?.shellTimeoutMs ?? shellTimeoutMs;
413
- const effectiveUseCork = opts?.useCork ?? useCork;
414
415
  const controller = createStreamController(writable, { log, warn, error });
415
416
  if (signal) {
416
417
  const handleAbortSignal = () => controller.benignAbort(`AbortSignal triggered; aborting stream for location: ${location}`);
@@ -445,9 +446,10 @@ function createRenderer({
445
446
  });
446
447
  controller.setStopShellTimer(stopShellTimer);
447
448
  log("Starting stream:", location);
449
+ let piped = false;
448
450
  try {
449
451
  const store = createSSRStore(initialData);
450
- const appElement = /* @__PURE__ */ jsx3(SSRStoreProvider, { store, children: appComponent({ location }) });
452
+ const appElement = /* @__PURE__ */ jsx3(SSRStoreProvider, { store, children: appComponent({ location, routeContext }) });
451
453
  const stream = renderToPipeableStream(appElement, {
452
454
  nonce: cspNonce,
453
455
  bootstrapModules: bootstrapModules ? [bootstrapModules] : void 0,
@@ -468,39 +470,16 @@ function createRenderer({
468
470
  });
469
471
  }
470
472
  }
471
- const head = headContent({ data: headData ?? {}, meta });
472
- const canCork = effectiveUseCork && typeof writable.cork === "function" && typeof writable.uncork === "function";
473
- if (canCork)
474
- try {
475
- writable.cork();
476
- } catch {
477
- }
478
- let wroteOk = true;
479
- try {
480
- const res = typeof writable.write === "function" ? writable.write(head) : true;
481
- wroteOk = res !== false;
482
- } finally {
483
- if (canCork) {
484
- try {
485
- writable.uncork();
486
- } catch {
487
- }
488
- }
489
- }
490
- let forceWait = false;
473
+ const head = headContent({ data: headData ?? {}, meta, routeContext });
491
474
  try {
492
- forceWait = cb.onHead(head) === false;
475
+ cb.onHead(head);
493
476
  } catch (cbErr) {
494
477
  warn("onHead callback threw:", cbErr);
495
478
  }
496
- const startPipe = () => stream.pipe(writable);
497
- if (forceWait || !wroteOk) {
498
- if (typeof writable.once === "function") {
499
- writable.once("drain", startPipe);
500
- } else {
501
- startPipe();
502
- }
503
- } else startPipe();
479
+ if (!piped) {
480
+ piped = true;
481
+ stream.pipe(writable);
482
+ }
504
483
  try {
505
484
  cb.onShellReady();
506
485
  } catch (cbErr) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@taujs/react",
3
- "version": "0.1.3",
3
+ "version": "0.1.5",
4
4
  "description": "taujs | τjs",
5
5
  "author": "Aoede <taujs@aoede.uk.net> (https://www.aoede.uk.net)",
6
6
  "license": "MIT",