@taujs/react 0.1.1 → 0.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -11,3 +11,7 @@
11
11
  React Renderer: CSR, SSR, Streaming SSR
12
12
 
13
13
  https://taujs.dev/
14
+
15
+ A lightweight, production-ready React SSR library with streaming capabilities, built for modern TypeScript applications. Designed as part of the taujs (τjs) ecosystem but fully standalone and runtime-agnostic.
16
+
17
+ https://taujs.dev/renderers/react/
package/dist/index.d.ts CHANGED
@@ -22,10 +22,10 @@ type UILogger = {
22
22
  error: (...args: unknown[]) => void;
23
23
  };
24
24
  type ServerLogs = {
25
- info: (message: string, meta?: unknown) => void;
26
- warn: (message: string, meta?: unknown) => void;
27
- error: (message: string, meta?: unknown) => void;
28
- debug?: (category: string, message: string, meta?: unknown) => void;
25
+ info: (meta?: unknown, message?: string) => void;
26
+ warn: (meta?: unknown, message?: string) => void;
27
+ error: (meta?: unknown, message?: string) => void;
28
+ debug?: (category: string, meta?: unknown, message?: string) => void;
29
29
  child?: (ctx: Record<string, unknown>) => ServerLogs;
30
30
  isDebugEnabled?: (category: string) => boolean;
31
31
  };
@@ -56,6 +56,10 @@ type StreamOptions = {
56
56
  /** Whether to use cork/uncork for batched writes (default: true) */
57
57
  useCork?: boolean;
58
58
  };
59
+ type HeadContext<T extends Record<string, unknown> = Record<string, unknown>> = {
60
+ data: T;
61
+ meta: Record<string, unknown>;
62
+ };
59
63
  type SSRResult = {
60
64
  headContent: string;
61
65
  appHtml: string;
@@ -68,10 +72,7 @@ declare function createRenderer<T extends Record<string, unknown>>({ appComponen
68
72
  appComponent: (props: {
69
73
  location: string;
70
74
  }) => React.ReactElement;
71
- headContent: (ctx: {
72
- data: T;
73
- meta: Record<string, unknown>;
74
- }) => string;
75
+ headContent: (ctx: HeadContext<T>) => string;
75
76
  enableDebug?: boolean;
76
77
  logger?: LoggerLike;
77
78
  streamOptions?: StreamOptions;
@@ -85,4 +86,70 @@ declare function createRenderer<T extends Record<string, unknown>>({ appComponen
85
86
  };
86
87
  };
87
88
 
88
- export { type HydrateAppOptions, type RenderCallbacks, type SSRStore, SSRStoreProvider, type ServerLogs, type StreamOptions, createRenderer, createSSRStore, hydrateApp, useSSRStore };
89
+ /**
90
+ * τjs Client Data Bridge
91
+ *
92
+ * Provides framework-agnostic primitives for accessing route data:
93
+ * - SSR hydration (window.__INITIAL_DATA__)
94
+ * - Client-side fetch (/__taujs/data endpoint)
95
+ *
96
+ * This is a transport layer only. For data orchestration (caching, refetch, etc.),
97
+ * use TanStack Query or similar.
98
+ */
99
+ type RouteData = Record<string, unknown>;
100
+ /**
101
+ * Error thrown when fetchRouteData receives a non-2xx response.
102
+ * Contains structured error information from the server.
103
+ */
104
+ declare class RouteDataError extends Error {
105
+ readonly status: number;
106
+ readonly statusText: string;
107
+ readonly code?: string;
108
+ readonly body?: unknown;
109
+ constructor(message: string, opts: {
110
+ status: number;
111
+ statusText: string;
112
+ code?: string;
113
+ body?: unknown;
114
+ });
115
+ }
116
+ /**
117
+ * Read SSR boot data from window.__INITIAL_DATA__ exactly once.
118
+ * Subsequent calls return null (forces client-side fetch).
119
+ *
120
+ * Returns null on server (typeof window === 'undefined').
121
+ */
122
+ declare function readInitialDataOnce<T extends RouteData = RouteData>(): T | null;
123
+ /**
124
+ * Fetch route data from the τjs data endpoint.
125
+ *
126
+ * Calls: GET /__taujs/data?url=<pathname>
127
+ * Returns: { data: T }
128
+ *
129
+ * Throws RouteDataError on non-2xx responses with structured error info.
130
+ *
131
+ * @example
132
+ * const data = await fetchRouteData('/app/dashboard');
133
+ *
134
+ * @example
135
+ * try {
136
+ * const data = await fetchRouteData('/app/dashboard');
137
+ * } catch (err) {
138
+ * if (err instanceof RouteDataError && err.status === 404) {
139
+ * // Handle not found
140
+ * }
141
+ * }
142
+ */
143
+ declare function fetchRouteData<T extends RouteData = RouteData>(pathname: string, init?: RequestInit): Promise<T>;
144
+ /**
145
+ * Get the current browser path (pathname + search).
146
+ * Does not include hash.
147
+ *
148
+ * Returns null on server (typeof window === 'undefined').
149
+ *
150
+ * @example
151
+ * const path = getCurrentPath(); // "/app/dashboard?tab=overview"
152
+ */
153
+ declare function getCurrentPath(): string | null;
154
+
155
+ export { type HeadContext, type HydrateAppOptions, type RenderCallbacks, type RouteData, RouteDataError, type SSRStore, SSRStoreProvider, type ServerLogs, type StreamOptions, createRenderer, createSSRStore, fetchRouteData, getCurrentPath, hydrateApp, readInitialDataOnce, useSSRStore };
package/dist/index.js CHANGED
@@ -90,10 +90,16 @@ var splitMsgAndMeta = (args) => {
90
90
  };
91
91
  function createUILogger(logger, opts = {}) {
92
92
  const { debugCategory = "ssr", context, preferDebug = false, enableDebug = false } = opts;
93
- if (!enableDebug) return { log: () => {
94
- }, warn: () => {
95
- }, error: () => {
96
- } };
93
+ if (!enableDebug) {
94
+ return {
95
+ log: () => {
96
+ },
97
+ warn: () => {
98
+ },
99
+ error: () => {
100
+ }
101
+ };
102
+ }
97
103
  const looksServer = !!logger && ("info" in logger || "debug" in logger || "child" in logger || "isDebugEnabled" in logger);
98
104
  if (looksServer) {
99
105
  let s = logger;
@@ -103,11 +109,11 @@ function createUILogger(logger, opts = {}) {
103
109
  } catch {
104
110
  }
105
111
  }
106
- const info = s.info ? s.info.bind(s) : (m, meta) => meta ? console.log(m, meta) : console.log(m);
107
- const warn = s.warn ? s.warn.bind(s) : (m, meta) => meta ? console.warn(m, meta) : console.warn(m);
108
- const error = s.error ? s.error.bind(s) : (m, meta) => meta ? console.error(m, meta) : console.error(m);
109
- const debug = s.debug ? s.debug.bind(s) : void 0;
110
- const isDebugEnabled = s.isDebugEnabled ? s.isDebugEnabled.bind(s) : void 0;
112
+ const info = s.info ? (msg, meta) => s.info(meta, msg) : (msg, meta) => meta ? console.log(msg, meta) : console.log(msg);
113
+ const warn = s.warn ? (msg, meta) => s.warn(meta, msg) : (msg, meta) => meta ? console.warn(msg, meta) : console.warn(msg);
114
+ const error = s.error ? (msg, meta) => s.error(meta, msg) : (msg, meta) => meta ? console.error(msg, meta) : console.error(msg);
115
+ const debug = s.debug ? (category, msg, meta) => s.debug(category, meta, msg) : void 0;
116
+ const isDebugEnabled = s.isDebugEnabled ? (category) => s.isDebugEnabled(category) : void 0;
111
117
  return {
112
118
  log: (...args) => {
113
119
  const { msg, meta } = splitMsgAndMeta(args);
@@ -559,10 +565,73 @@ function createRenderer({
559
565
  };
560
566
  return { renderSSR, renderStream };
561
567
  }
568
+
569
+ // src/RouteData.ts
570
+ var RouteDataError = class _RouteDataError extends Error {
571
+ status;
572
+ statusText;
573
+ code;
574
+ body;
575
+ constructor(message, opts) {
576
+ super(message);
577
+ this.name = "RouteDataError";
578
+ this.status = opts.status;
579
+ this.statusText = opts.statusText;
580
+ this.code = opts.code;
581
+ this.body = opts.body;
582
+ Object.setPrototypeOf(this, _RouteDataError.prototype);
583
+ }
584
+ };
585
+ var INITIAL_DATA_KEY = "__INITIAL_DATA__";
586
+ function readInitialDataOnce() {
587
+ if (typeof window === "undefined") return null;
588
+ const w = window;
589
+ const data = w[INITIAL_DATA_KEY];
590
+ if (!data) return null;
591
+ delete w[INITIAL_DATA_KEY];
592
+ return data;
593
+ }
594
+ async function fetchRouteData(pathname, init) {
595
+ if (!pathname) {
596
+ throw new Error("fetchRouteData: pathname is required");
597
+ }
598
+ const url = `/__taujs/data?url=${encodeURIComponent(pathname)}`;
599
+ const res = await fetch(url, {
600
+ credentials: "include",
601
+ ...init
602
+ });
603
+ if (!res.ok) {
604
+ let body2;
605
+ try {
606
+ body2 = await res.json();
607
+ } catch {
608
+ const text = await res.text().catch(() => "");
609
+ body2 = { error: text };
610
+ }
611
+ const json = body2;
612
+ throw new RouteDataError(json.error ?? `Request failed: ${res.status}`, {
613
+ status: res.status,
614
+ statusText: json.statusText ?? res.statusText,
615
+ code: json.code,
616
+ body: body2
617
+ });
618
+ }
619
+ const body = await res.json();
620
+ return body.data ?? {};
621
+ }
622
+ function getCurrentPath() {
623
+ if (typeof window === "undefined") return null;
624
+ const { pathname, search } = window.location;
625
+ return `${pathname}${search}`;
626
+ }
562
627
  export {
628
+ RouteDataError,
563
629
  SSRStoreProvider,
564
630
  createRenderer,
565
631
  createSSRStore,
632
+ fetchRouteData,
633
+ getCurrentPath,
566
634
  hydrateApp,
635
+ readInitialDataOnce,
567
636
  useSSRStore
568
637
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@taujs/react",
3
- "version": "0.1.1",
3
+ "version": "0.1.2",
4
4
  "description": "taujs | τjs",
5
5
  "author": "Aoede <taujs@aoede.uk.net> (https://www.aoede.uk.net)",
6
6
  "license": "MIT",