hadars 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js ADDED
@@ -0,0 +1,263 @@
1
+ // src/utils/Head.tsx
2
+ import React from "react";
3
+ import { jsx } from "react/jsx-runtime";
4
+ var AppContext = React.createContext({
5
+ setTitle: () => {
6
+ console.warn("AppContext: setTitle called outside of provider");
7
+ },
8
+ addMeta: () => {
9
+ console.warn("AppContext: addMeta called outside of provider");
10
+ },
11
+ addLink: () => {
12
+ console.warn("AppContext: addLink called outside of provider");
13
+ },
14
+ addStyle: () => {
15
+ console.warn("AppContext: addStyle called outside of provider");
16
+ },
17
+ addScript: () => {
18
+ console.warn("AppContext: addScript called outside of provider");
19
+ },
20
+ setStatus: () => {
21
+ }
22
+ });
23
+ var AppProviderSSR = React.memo(({ children, context }) => {
24
+ const { head } = context;
25
+ const setTitle = React.useCallback((title) => {
26
+ head.title = title;
27
+ }, [head]);
28
+ const addMeta = React.useCallback((id, props) => {
29
+ head.meta[id] = props;
30
+ }, [head]);
31
+ const addLink = React.useCallback((id, props) => {
32
+ head.link[id] = props;
33
+ }, [head]);
34
+ const addStyle = React.useCallback((id, props) => {
35
+ head.style[id] = props;
36
+ }, [head]);
37
+ const addScript = React.useCallback((id, props) => {
38
+ head.script[id] = props;
39
+ }, [head]);
40
+ const setStatus = React.useCallback((status) => {
41
+ head.status = status;
42
+ }, [head]);
43
+ const contextValue = React.useMemo(() => ({
44
+ setTitle,
45
+ addMeta,
46
+ addLink,
47
+ addStyle,
48
+ addScript,
49
+ setStatus
50
+ }), [setTitle, addMeta, addLink, addStyle, addScript, setStatus]);
51
+ return /* @__PURE__ */ jsx(AppContext.Provider, { value: contextValue, children });
52
+ });
53
+ var AppProviderCSR = React.memo(({ children }) => {
54
+ const setTitle = React.useCallback((title) => {
55
+ document.title = title;
56
+ }, []);
57
+ const addMeta = React.useCallback((id, props) => {
58
+ let meta = document.querySelector(`#${id}`);
59
+ if (!meta) {
60
+ meta = document.createElement("meta");
61
+ meta.setAttribute("id", id);
62
+ document.head.appendChild(meta);
63
+ }
64
+ Object.keys(props).forEach((key) => {
65
+ const value = props[key];
66
+ if (value) {
67
+ meta.setAttribute(key, value);
68
+ }
69
+ });
70
+ }, []);
71
+ const addLink = React.useCallback((id, props) => {
72
+ let link = document.querySelector(`#${id}`);
73
+ if (!link) {
74
+ link = document.createElement("link");
75
+ link.setAttribute("id", id);
76
+ document.head.appendChild(link);
77
+ }
78
+ Object.keys(props).forEach((key) => {
79
+ const value = props[key];
80
+ if (value) {
81
+ link.setAttribute(key, value);
82
+ }
83
+ });
84
+ }, []);
85
+ const addStyle = React.useCallback((id, props) => {
86
+ let style = document.getElementById(id);
87
+ if (!style) {
88
+ style = document.createElement("style");
89
+ style.setAttribute("id", id);
90
+ document.head.appendChild(style);
91
+ }
92
+ Object.keys(props).forEach((key) => {
93
+ if (key === "dangerouslySetInnerHTML" && props[key] && props[key].__html) {
94
+ style.innerHTML = props[key].__html;
95
+ return;
96
+ }
97
+ const value = props[key];
98
+ if (value) {
99
+ style[key] = value;
100
+ }
101
+ });
102
+ }, []);
103
+ const addScript = React.useCallback((id, props) => {
104
+ let script = document.getElementById(id);
105
+ if (!script) {
106
+ script = document.createElement("script");
107
+ script.setAttribute("id", id);
108
+ document.body.appendChild(script);
109
+ }
110
+ Object.keys(props).forEach((key) => {
111
+ if (key === "dangerouslySetInnerHTML" && props[key] && props[key].__html) {
112
+ script.innerHTML = props[key].__html;
113
+ return;
114
+ }
115
+ const value = props[key];
116
+ if (value) {
117
+ script[key] = value;
118
+ }
119
+ });
120
+ }, []);
121
+ const contextValue = React.useMemo(() => ({
122
+ setTitle,
123
+ addMeta,
124
+ addLink,
125
+ addStyle,
126
+ addScript,
127
+ setStatus: () => {
128
+ }
129
+ }), [setTitle, addMeta, addLink, addStyle, addScript]);
130
+ return /* @__PURE__ */ jsx(AppContext.Provider, { value: contextValue, children });
131
+ });
132
+ var useApp = () => React.useContext(AppContext);
133
+ var clientServerDataCache = /* @__PURE__ */ new Map();
134
+ function useServerData(key, fn) {
135
+ const cacheKey = Array.isArray(key) ? key.join("\0") : key;
136
+ if (typeof window !== "undefined") {
137
+ if (clientServerDataCache.has(cacheKey)) {
138
+ return clientServerDataCache.get(cacheKey);
139
+ }
140
+ return fn();
141
+ }
142
+ const unsuspend = globalThis.__hadarsUnsuspend;
143
+ if (!unsuspend)
144
+ return void 0;
145
+ const existing = unsuspend.cache.get(cacheKey);
146
+ if (existing?.status === "suspense-resolved") {
147
+ try {
148
+ return fn();
149
+ } catch {
150
+ return void 0;
151
+ }
152
+ }
153
+ if (!existing) {
154
+ let result;
155
+ try {
156
+ result = fn();
157
+ } catch (thrown) {
158
+ if (thrown !== null && typeof thrown === "object" && typeof thrown.then === "function") {
159
+ const suspensePromise = Promise.resolve(thrown).then(
160
+ () => {
161
+ unsuspend.cache.set(cacheKey, { status: "suspense-resolved" });
162
+ },
163
+ () => {
164
+ unsuspend.cache.set(cacheKey, { status: "suspense-resolved" });
165
+ }
166
+ );
167
+ unsuspend.cache.set(cacheKey, { status: "pending", promise: suspensePromise });
168
+ unsuspend.hasPending = true;
169
+ return void 0;
170
+ }
171
+ throw thrown;
172
+ }
173
+ const isThenable = result !== null && typeof result === "object" && typeof result.then === "function";
174
+ if (!isThenable) {
175
+ const value = result;
176
+ unsuspend.cache.set(cacheKey, { status: "fulfilled", value });
177
+ return value;
178
+ }
179
+ const promise = result.then(
180
+ (value) => {
181
+ unsuspend.cache.set(cacheKey, { status: "fulfilled", value });
182
+ },
183
+ (reason) => {
184
+ unsuspend.cache.set(cacheKey, { status: "rejected", reason });
185
+ }
186
+ );
187
+ unsuspend.cache.set(cacheKey, { status: "pending", promise });
188
+ unsuspend.hasPending = true;
189
+ return void 0;
190
+ }
191
+ if (existing.status === "pending") {
192
+ unsuspend.hasPending = true;
193
+ return void 0;
194
+ }
195
+ if (existing.status === "rejected")
196
+ throw existing.reason;
197
+ return existing.value;
198
+ }
199
+ var genRandomId = () => {
200
+ return "head-" + Math.random().toString(36).substr(2, 9);
201
+ };
202
+ var Head = React.memo(({ children, status }) => {
203
+ const {
204
+ setStatus,
205
+ setTitle,
206
+ addMeta,
207
+ addLink,
208
+ addStyle,
209
+ addScript
210
+ } = useApp();
211
+ if (status) {
212
+ setStatus(status);
213
+ }
214
+ React.Children.forEach(children, (child) => {
215
+ if (!React.isValidElement(child))
216
+ return;
217
+ const childType = child.type;
218
+ const childProps = child.props;
219
+ const id = childProps["id"] || genRandomId();
220
+ switch (childType) {
221
+ case "title": {
222
+ setTitle(childProps["children"]);
223
+ return;
224
+ }
225
+ case "meta": {
226
+ addMeta(id.toString(), childProps);
227
+ return;
228
+ }
229
+ case "link": {
230
+ addLink(id.toString(), childProps);
231
+ return;
232
+ }
233
+ case "script": {
234
+ addScript(id.toString(), childProps);
235
+ return;
236
+ }
237
+ case "style": {
238
+ addStyle(id.toString(), childProps);
239
+ return;
240
+ }
241
+ default: {
242
+ console.warn(`HadarsHead: Unsupported child type: ${childType}`);
243
+ return;
244
+ }
245
+ }
246
+ });
247
+ return null;
248
+ });
249
+
250
+ // src/index.tsx
251
+ var HadarsContext = typeof window === "undefined" ? AppProviderSSR : AppProviderCSR;
252
+ function loadModule(path) {
253
+ return import(
254
+ /* webpackIgnore: true */
255
+ path
256
+ );
257
+ }
258
+ export {
259
+ HadarsContext,
260
+ Head as HadarsHead,
261
+ loadModule,
262
+ useServerData
263
+ };
@@ -0,0 +1,34 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+ var loader_exports = {};
20
+ __export(loader_exports, {
21
+ default: () => loader
22
+ });
23
+ module.exports = __toCommonJS(loader_exports);
24
+ const LOAD_MODULE_RE = /\bloadModule\s*(?:<.*?>\s*)?\(\s*(['"`])((?:\\.|(?!\1)[^\\])*)\1\s*\)/gs;
25
+ function loader(source) {
26
+ const isServer = this.target === "node" || this.target === "async-node";
27
+ return source.replace(LOAD_MODULE_RE, (_match, quote, modulePath) => {
28
+ if (isServer) {
29
+ return `Promise.resolve(require(${quote}${modulePath}${quote}))`;
30
+ } else {
31
+ return `import(${quote}${modulePath}${quote})`;
32
+ }
33
+ });
34
+ }
@@ -0,0 +1,92 @@
1
+ // src/ssr-render-worker.ts
2
+ import { workerData, parentPort } from "node:worker_threads";
3
+ import { createRequire } from "node:module";
4
+ import pathMod from "node:path";
5
+ import { pathToFileURL } from "node:url";
6
+ var { ssrBundlePath } = workerData;
7
+ var _React = null;
8
+ var _renderToStaticMarkup = null;
9
+ var _renderToString = null;
10
+ var _renderToReadableStream = null;
11
+ var _Component = null;
12
+ async function init() {
13
+ if (_React && _renderToStaticMarkup && _renderToString && _renderToReadableStream && _Component)
14
+ return;
15
+ const req = createRequire(pathMod.resolve(process.cwd(), "__ninety_fake__.js"));
16
+ if (!_React) {
17
+ const reactPath = pathToFileURL(req.resolve("react")).href;
18
+ const reactMod = await import(reactPath);
19
+ _React = reactMod.default ?? reactMod;
20
+ }
21
+ if (!_renderToString || !_renderToStaticMarkup) {
22
+ const serverPath = pathToFileURL(req.resolve("react-dom/server")).href;
23
+ const serverMod = await import(serverPath);
24
+ _renderToString = serverMod.renderToString;
25
+ _renderToStaticMarkup = serverMod.renderToStaticMarkup;
26
+ }
27
+ if (!_renderToReadableStream) {
28
+ const browserPath = pathToFileURL(req.resolve("react-dom/server.browser")).href;
29
+ const browserMod = await import(browserPath);
30
+ _renderToReadableStream = browserMod.renderToReadableStream;
31
+ }
32
+ if (!_Component) {
33
+ const ssrMod = await import(pathToFileURL(ssrBundlePath).href);
34
+ _Component = ssrMod.default;
35
+ }
36
+ }
37
+ function buildReactPage(R, appProps, clientProps) {
38
+ return R.createElement(
39
+ R.Fragment,
40
+ null,
41
+ R.createElement(
42
+ "div",
43
+ { id: "app" },
44
+ R.createElement(_Component, appProps)
45
+ ),
46
+ R.createElement("script", {
47
+ id: "hadars",
48
+ type: "application/json",
49
+ dangerouslySetInnerHTML: {
50
+ __html: JSON.stringify({ hadars: { props: clientProps } })
51
+ }
52
+ })
53
+ );
54
+ }
55
+ parentPort.on("message", async (msg) => {
56
+ const { id, type } = msg;
57
+ try {
58
+ await init();
59
+ const R = _React;
60
+ const unsuspend = msg.appProps?.context?._unsuspend ?? null;
61
+ if (type === "renderStream") {
62
+ const { appProps: appProps2, clientProps: clientProps2 } = msg;
63
+ const ReactPage2 = buildReactPage(R, appProps2, clientProps2);
64
+ globalThis.__hadarsUnsuspend = unsuspend;
65
+ const stream = await _renderToReadableStream(ReactPage2);
66
+ globalThis.__hadarsUnsuspend = null;
67
+ const reader = stream.getReader();
68
+ while (true) {
69
+ const { done, value } = await reader.read();
70
+ if (done)
71
+ break;
72
+ parentPort.postMessage({ id, type: "chunk", chunk: value }, [value.buffer]);
73
+ }
74
+ parentPort.postMessage({ id, type: "done" });
75
+ return;
76
+ }
77
+ const { appProps, clientProps } = msg;
78
+ const ReactPage = buildReactPage(R, appProps, clientProps);
79
+ globalThis.__hadarsUnsuspend = unsuspend;
80
+ const html = _renderToString(ReactPage);
81
+ globalThis.__hadarsUnsuspend = null;
82
+ parentPort.postMessage({ id, html });
83
+ } catch (err) {
84
+ globalThis.__hadarsUnsuspend = null;
85
+ const errMsg = err?.message ?? String(err);
86
+ if (type === "renderStream") {
87
+ parentPort.postMessage({ id, type: "error", error: errMsg });
88
+ } else {
89
+ parentPort.postMessage({ id, error: errMsg });
90
+ }
91
+ }
92
+ });