hadars 1.0.4 → 1.0.6
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 +14 -14
- package/dist/{chunk-QOTDCUE5.js → chunk-6SOA2HTO.js} +27 -17
- package/dist/{chunk-PQ5N5GOY.js → chunk-VAR5KTG3.js} +13 -2
- package/dist/cli.js +55 -23
- package/dist/cloudflare.cjs +39 -18
- package/dist/cloudflare.js +2 -2
- package/dist/lambda.cjs +39 -18
- package/dist/lambda.js +2 -2
- package/dist/slim-react/index.cjs +27 -17
- package/dist/slim-react/index.d.cts +2 -2
- package/dist/slim-react/index.d.ts +2 -2
- package/dist/slim-react/index.js +1 -1
- package/dist/ssr-render-worker.js +15 -3
- package/package.json +2 -1
package/README.md
CHANGED
|
@@ -21,30 +21,30 @@ Bring your own router (or none), keep your components as plain React, and get SS
|
|
|
21
21
|
## Benchmarks
|
|
22
22
|
|
|
23
23
|
<!-- BENCHMARK_START -->
|
|
24
|
-
> Last run: 2026-
|
|
25
|
-
> hadars is **
|
|
24
|
+
> Last run: 2026-05-12 · 120s · 100 connections · Bun runtime
|
|
25
|
+
> hadars is **8.9x faster** in requests/sec
|
|
26
26
|
|
|
27
27
|
**Throughput** (autocannon, 120s)
|
|
28
28
|
|
|
29
29
|
| Metric | hadars | Next.js |
|
|
30
30
|
|---|---:|---:|
|
|
31
|
-
| Requests/sec | **
|
|
32
|
-
| Latency median | **
|
|
33
|
-
| Latency p99 | **
|
|
34
|
-
| Throughput | **
|
|
35
|
-
| Peak RSS |
|
|
36
|
-
| Avg RSS |
|
|
37
|
-
| Build time | 0.
|
|
31
|
+
| Requests/sec | **152** | 17 |
|
|
32
|
+
| Latency median | **603 ms** | 2762 ms |
|
|
33
|
+
| Latency p99 | **1307 ms** | 4162 ms |
|
|
34
|
+
| Throughput | **43.4** MB/s | 9.4 MB/s |
|
|
35
|
+
| Peak RSS | 788.6 MB | **477.3 MB** |
|
|
36
|
+
| Avg RSS | 617.5 MB | **425.6 MB** |
|
|
37
|
+
| Build time | 0.6 s | 6.1 s |
|
|
38
38
|
|
|
39
39
|
**Page load** (Playwright · Chromium headless · median)
|
|
40
40
|
|
|
41
41
|
| Metric | hadars | Next.js |
|
|
42
42
|
|---|---:|---:|
|
|
43
|
-
| TTFB | **
|
|
44
|
-
| FCP | **
|
|
45
|
-
| DOMContentLoaded | **
|
|
46
|
-
| Load | **
|
|
47
|
-
| Peak RSS |
|
|
43
|
+
| TTFB | **18 ms** | 43 ms |
|
|
44
|
+
| FCP | **96 ms** | 144 ms |
|
|
45
|
+
| DOMContentLoaded | **39 ms** | 131 ms |
|
|
46
|
+
| Load | **121 ms** | 177 ms |
|
|
47
|
+
| Peak RSS | 457.3 MB | **288.8 MB** |
|
|
48
48
|
<!-- BENCHMARK_END -->
|
|
49
49
|
|
|
50
50
|
## Quick start
|
|
@@ -26,6 +26,13 @@ function captureUnsuspend() {
|
|
|
26
26
|
function restoreUnsuspend(u) {
|
|
27
27
|
_g[UNSUSPEND_KEY] = u;
|
|
28
28
|
}
|
|
29
|
+
var HADARS_CTX_KEY = "__hadarsContext";
|
|
30
|
+
function captureHadarsCtx() {
|
|
31
|
+
return _g[HADARS_CTX_KEY];
|
|
32
|
+
}
|
|
33
|
+
function restoreHadarsCtx(h) {
|
|
34
|
+
_g[HADARS_CTX_KEY] = h;
|
|
35
|
+
}
|
|
29
36
|
function getContextValue(context) {
|
|
30
37
|
const map = _g[MAP_KEY];
|
|
31
38
|
if (map && map.has(context)) return map.get(context);
|
|
@@ -165,8 +172,8 @@ function useState(initialState) {
|
|
|
165
172
|
return [value, () => {
|
|
166
173
|
}];
|
|
167
174
|
}
|
|
168
|
-
function useReducer(_reducer,
|
|
169
|
-
return [
|
|
175
|
+
function useReducer(_reducer, initialArg, init) {
|
|
176
|
+
return [init ? init(initialArg) : initialArg, () => {
|
|
170
177
|
}];
|
|
171
178
|
}
|
|
172
179
|
function useEffect(_effect, _deps) {
|
|
@@ -313,12 +320,13 @@ function restoreDispatcher(prev) {
|
|
|
313
320
|
|
|
314
321
|
// src/slim-react/render.ts
|
|
315
322
|
function captureRenderCtx() {
|
|
316
|
-
return { m: captureMap(), u: captureUnsuspend(), t: snapshotContext() };
|
|
323
|
+
return { m: captureMap(), u: captureUnsuspend(), t: snapshotContext(), h: captureHadarsCtx() };
|
|
317
324
|
}
|
|
318
325
|
function restoreRenderCtx(ctx) {
|
|
319
326
|
swapContextMap(ctx.m);
|
|
320
327
|
restoreUnsuspend(ctx.u);
|
|
321
328
|
restoreContext(ctx.t);
|
|
329
|
+
restoreHadarsCtx(ctx.h);
|
|
322
330
|
}
|
|
323
331
|
var VOID_ELEMENTS = /* @__PURE__ */ new Set([
|
|
324
332
|
"area",
|
|
@@ -926,11 +934,18 @@ function renderChildArrayFrom(children, startIndex, writer, isSvg) {
|
|
|
926
934
|
const r = renderNode(child, writer, isSvg);
|
|
927
935
|
if (r && typeof r.then === "function") {
|
|
928
936
|
const rctx = captureRenderCtx();
|
|
929
|
-
return r.then(
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
937
|
+
return r.then(
|
|
938
|
+
() => {
|
|
939
|
+
restoreRenderCtx(rctx);
|
|
940
|
+
popTreeContext(savedTree);
|
|
941
|
+
return renderChildArrayFrom(children, i + 1, writer, isSvg);
|
|
942
|
+
},
|
|
943
|
+
(e) => {
|
|
944
|
+
restoreRenderCtx(rctx);
|
|
945
|
+
popTreeContext(savedTree);
|
|
946
|
+
throw e;
|
|
947
|
+
}
|
|
948
|
+
);
|
|
934
949
|
}
|
|
935
950
|
popTreeContext(savedTree);
|
|
936
951
|
}
|
|
@@ -1020,20 +1035,15 @@ function renderToStream(element, options) {
|
|
|
1020
1035
|
}
|
|
1021
1036
|
});
|
|
1022
1037
|
}
|
|
1023
|
-
var NULL_WRITER = {
|
|
1024
|
-
lastWasText: false,
|
|
1025
|
-
write(_c) {
|
|
1026
|
-
},
|
|
1027
|
-
text(_s) {
|
|
1028
|
-
}
|
|
1029
|
-
};
|
|
1030
1038
|
async function renderPreflight(element, options) {
|
|
1031
1039
|
const idPrefix = options?.identifierPrefix ?? "";
|
|
1040
|
+
const writer = { lastWasText: false, write() {
|
|
1041
|
+
}, text() {
|
|
1042
|
+
} };
|
|
1032
1043
|
const prev = swapContextMap(null);
|
|
1033
1044
|
try {
|
|
1034
1045
|
resetRenderState(idPrefix);
|
|
1035
|
-
|
|
1036
|
-
const r = renderNode(element, NULL_WRITER);
|
|
1046
|
+
const r = renderNode(element, writer);
|
|
1037
1047
|
if (r && typeof r.then === "function") {
|
|
1038
1048
|
const rctx = captureRenderCtx();
|
|
1039
1049
|
await r;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
2
|
renderPreflight,
|
|
3
3
|
renderToString
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-6SOA2HTO.js";
|
|
5
5
|
import {
|
|
6
6
|
createElement
|
|
7
7
|
} from "./chunk-OZUZS2PD.js";
|
|
@@ -180,7 +180,16 @@ var getReactResponse = async (req, opts) => {
|
|
|
180
180
|
globalThis.__hadarsContext = context;
|
|
181
181
|
const element = createElement(App, props);
|
|
182
182
|
let bodyHtml = null;
|
|
183
|
-
if (opts.
|
|
183
|
+
if (opts.dataOnly) {
|
|
184
|
+
globalThis.__hadarsUnsuspend = unsuspend;
|
|
185
|
+
globalThis.__hadarsContext = context;
|
|
186
|
+
try {
|
|
187
|
+
await renderPreflight(element);
|
|
188
|
+
} finally {
|
|
189
|
+
globalThis.__hadarsUnsuspend = null;
|
|
190
|
+
globalThis.__hadarsContext = null;
|
|
191
|
+
}
|
|
192
|
+
} else if (opts.singlePass) {
|
|
184
193
|
globalThis.__hadarsUnsuspend = unsuspend;
|
|
185
194
|
globalThis.__hadarsContext = context;
|
|
186
195
|
try {
|
|
@@ -190,6 +199,8 @@ var getReactResponse = async (req, opts) => {
|
|
|
190
199
|
globalThis.__hadarsContext = null;
|
|
191
200
|
}
|
|
192
201
|
} else {
|
|
202
|
+
globalThis.__hadarsUnsuspend = unsuspend;
|
|
203
|
+
globalThis.__hadarsContext = context;
|
|
193
204
|
try {
|
|
194
205
|
await renderPreflight(element);
|
|
195
206
|
} finally {
|
package/dist/cli.js
CHANGED
|
@@ -167,6 +167,13 @@ function captureUnsuspend() {
|
|
|
167
167
|
function restoreUnsuspend(u) {
|
|
168
168
|
_g[UNSUSPEND_KEY] = u;
|
|
169
169
|
}
|
|
170
|
+
var HADARS_CTX_KEY = "__hadarsContext";
|
|
171
|
+
function captureHadarsCtx() {
|
|
172
|
+
return _g[HADARS_CTX_KEY];
|
|
173
|
+
}
|
|
174
|
+
function restoreHadarsCtx(h) {
|
|
175
|
+
_g[HADARS_CTX_KEY] = h;
|
|
176
|
+
}
|
|
170
177
|
function getContextValue(context) {
|
|
171
178
|
const map = _g[MAP_KEY];
|
|
172
179
|
if (map && map.has(context))
|
|
@@ -320,8 +327,8 @@ function useState(initialState) {
|
|
|
320
327
|
const value = typeof initialState === "function" ? initialState() : initialState;
|
|
321
328
|
return [value, () => {}];
|
|
322
329
|
}
|
|
323
|
-
function useReducer(_reducer,
|
|
324
|
-
return [
|
|
330
|
+
function useReducer(_reducer, initialArg, init) {
|
|
331
|
+
return [init ? init(initialArg) : initialArg, () => {}];
|
|
325
332
|
}
|
|
326
333
|
function useEffect(_effect, _deps) {}
|
|
327
334
|
function useLayoutEffect(_effect, _deps) {}
|
|
@@ -431,12 +438,13 @@ function restoreDispatcher(prev) {
|
|
|
431
438
|
|
|
432
439
|
// src/slim-react/render.ts
|
|
433
440
|
function captureRenderCtx() {
|
|
434
|
-
return { m: captureMap(), u: captureUnsuspend(), t: snapshotContext() };
|
|
441
|
+
return { m: captureMap(), u: captureUnsuspend(), t: snapshotContext(), h: captureHadarsCtx() };
|
|
435
442
|
}
|
|
436
443
|
function restoreRenderCtx(ctx) {
|
|
437
444
|
swapContextMap(ctx.m);
|
|
438
445
|
restoreUnsuspend(ctx.u);
|
|
439
446
|
restoreContext(ctx.t);
|
|
447
|
+
restoreHadarsCtx(ctx.h);
|
|
440
448
|
}
|
|
441
449
|
var VOID_ELEMENTS = new Set([
|
|
442
450
|
"area",
|
|
@@ -1061,6 +1069,10 @@ function renderChildArrayFrom(children, startIndex, writer, isSvg) {
|
|
|
1061
1069
|
restoreRenderCtx(rctx);
|
|
1062
1070
|
popTreeContext(savedTree);
|
|
1063
1071
|
return renderChildArrayFrom(children, i + 1, writer, isSvg);
|
|
1072
|
+
}, (e) => {
|
|
1073
|
+
restoreRenderCtx(rctx);
|
|
1074
|
+
popTreeContext(savedTree);
|
|
1075
|
+
throw e;
|
|
1064
1076
|
});
|
|
1065
1077
|
}
|
|
1066
1078
|
popTreeContext(savedTree);
|
|
@@ -1111,18 +1123,13 @@ async function renderSuspense(props, writer, isSvg = false) {
|
|
|
1111
1123
|
}
|
|
1112
1124
|
}
|
|
1113
1125
|
var _streamEncoder = new TextEncoder;
|
|
1114
|
-
var NULL_WRITER = {
|
|
1115
|
-
lastWasText: false,
|
|
1116
|
-
write(_c) {},
|
|
1117
|
-
text(_s) {}
|
|
1118
|
-
};
|
|
1119
1126
|
async function renderPreflight(element, options) {
|
|
1120
1127
|
const idPrefix = options?.identifierPrefix ?? "";
|
|
1128
|
+
const writer = { lastWasText: false, write() {}, text() {} };
|
|
1121
1129
|
const prev = swapContextMap(null);
|
|
1122
1130
|
try {
|
|
1123
1131
|
resetRenderState(idPrefix);
|
|
1124
|
-
|
|
1125
|
-
const r = renderNode(element, NULL_WRITER);
|
|
1132
|
+
const r = renderNode(element, writer);
|
|
1126
1133
|
if (r && typeof r.then === "function") {
|
|
1127
1134
|
const rctx = captureRenderCtx();
|
|
1128
1135
|
await r;
|
|
@@ -1221,7 +1228,16 @@ var getReactResponse = async (req, opts) => {
|
|
|
1221
1228
|
globalThis.__hadarsContext = context;
|
|
1222
1229
|
const element = createElement(App, props);
|
|
1223
1230
|
let bodyHtml = null;
|
|
1224
|
-
if (opts.
|
|
1231
|
+
if (opts.dataOnly) {
|
|
1232
|
+
globalThis.__hadarsUnsuspend = unsuspend;
|
|
1233
|
+
globalThis.__hadarsContext = context;
|
|
1234
|
+
try {
|
|
1235
|
+
await renderPreflight(element);
|
|
1236
|
+
} finally {
|
|
1237
|
+
globalThis.__hadarsUnsuspend = null;
|
|
1238
|
+
globalThis.__hadarsContext = null;
|
|
1239
|
+
}
|
|
1240
|
+
} else if (opts.singlePass) {
|
|
1225
1241
|
globalThis.__hadarsUnsuspend = unsuspend;
|
|
1226
1242
|
globalThis.__hadarsContext = context;
|
|
1227
1243
|
try {
|
|
@@ -1231,6 +1247,8 @@ var getReactResponse = async (req, opts) => {
|
|
|
1231
1247
|
globalThis.__hadarsContext = null;
|
|
1232
1248
|
}
|
|
1233
1249
|
} else {
|
|
1250
|
+
globalThis.__hadarsUnsuspend = unsuspend;
|
|
1251
|
+
globalThis.__hadarsContext = context;
|
|
1234
1252
|
try {
|
|
1235
1253
|
await renderPreflight(element);
|
|
1236
1254
|
} finally {
|
|
@@ -1753,6 +1771,15 @@ async function tryServeFile(filePath) {
|
|
|
1753
1771
|
return null;
|
|
1754
1772
|
}
|
|
1755
1773
|
}
|
|
1774
|
+
var _notFound = new Set;
|
|
1775
|
+
async function tryServeFileCached(filePath) {
|
|
1776
|
+
if (_notFound.has(filePath))
|
|
1777
|
+
return null;
|
|
1778
|
+
const res = await tryServeFile(filePath);
|
|
1779
|
+
if (!res)
|
|
1780
|
+
_notFound.add(filePath);
|
|
1781
|
+
return res;
|
|
1782
|
+
}
|
|
1756
1783
|
|
|
1757
1784
|
// src/build.ts
|
|
1758
1785
|
import { RspackDevServer } from "@rspack/dev-server";
|
|
@@ -1776,10 +1803,11 @@ function buildSsrResponse(head, status, getAppBody, finalize, getPrecontentHtml)
|
|
|
1776
1803
|
async start(controller) {
|
|
1777
1804
|
try {
|
|
1778
1805
|
const [precontentHtml, postContent] = precontentResult instanceof Promise ? await precontentResult : precontentResult;
|
|
1806
|
+
const finalizePromise = finalize();
|
|
1779
1807
|
controller.enqueue(encoder.encode(precontentHtml));
|
|
1780
1808
|
const bodyHtml = await getAppBody();
|
|
1781
1809
|
controller.enqueue(encoder.encode(`<div id="app">${bodyHtml}</div>`));
|
|
1782
|
-
const { clientProps } = await
|
|
1810
|
+
const { clientProps } = await finalizePromise;
|
|
1783
1811
|
const scriptContent = JSON.stringify({ hadars: { props: clientProps } }).replace(/</g, "\\u003c");
|
|
1784
1812
|
controller.enqueue(encoder.encode(`<script id="hadars" type="application/json">${scriptContent}</script>` + postContent));
|
|
1785
1813
|
controller.close();
|
|
@@ -2735,6 +2763,7 @@ var dev = async (options) => {
|
|
|
2735
2763
|
} catch (e) {}
|
|
2736
2764
|
})();
|
|
2737
2765
|
const getPrecontentHtml = makePrecontentHtmlGetter(readyPromise.then(() => fs.readFile(pathMod2.join(__dirname3, StaticPath, "out.html"), "utf-8")));
|
|
2766
|
+
const projectStaticPath = pathMod2.resolve(process.cwd(), "static");
|
|
2738
2767
|
await serve(port, async (req, ctx) => {
|
|
2739
2768
|
await readyPromise;
|
|
2740
2769
|
const request = parseRequest(req);
|
|
@@ -2755,11 +2784,10 @@ var dev = async (options) => {
|
|
|
2755
2784
|
return proxied;
|
|
2756
2785
|
const url = new URL(request.url);
|
|
2757
2786
|
const path2 = url.pathname;
|
|
2758
|
-
const staticRes = await
|
|
2787
|
+
const staticRes = await tryServeFileCached(pathMod2.join(__dirname3, StaticPath, path2));
|
|
2759
2788
|
if (staticRes)
|
|
2760
2789
|
return staticRes;
|
|
2761
|
-
const
|
|
2762
|
-
const projectRes = await tryServeFile(pathMod2.join(projectStaticPath, path2));
|
|
2790
|
+
const projectRes = await tryServeFileCached(pathMod2.join(projectStaticPath, path2));
|
|
2763
2791
|
if (projectRes)
|
|
2764
2792
|
return projectRes;
|
|
2765
2793
|
const ssrComponentPath = pathMod2.join(__dirname3, HadarsFolder, SSR_FILENAME);
|
|
@@ -2775,6 +2803,7 @@ var dev = async (options) => {
|
|
|
2775
2803
|
getFinalProps
|
|
2776
2804
|
} = cachedSsrModule;
|
|
2777
2805
|
globalThis.__hadarsGraphQL = devStaticCtx?.graphql;
|
|
2806
|
+
const isDataOnly = request.headers.get("Accept") === "application/json";
|
|
2778
2807
|
const { head, status, getAppBody, finalize } = await getReactResponse(request, {
|
|
2779
2808
|
document: {
|
|
2780
2809
|
body: Component,
|
|
@@ -2783,9 +2812,10 @@ var dev = async (options) => {
|
|
|
2783
2812
|
getFinalProps
|
|
2784
2813
|
},
|
|
2785
2814
|
staticCtx: devStaticCtx,
|
|
2786
|
-
singlePass:
|
|
2815
|
+
singlePass: !isDataOnly,
|
|
2816
|
+
dataOnly: isDataOnly
|
|
2787
2817
|
});
|
|
2788
|
-
if (
|
|
2818
|
+
if (isDataOnly) {
|
|
2789
2819
|
const { clientProps } = await finalize();
|
|
2790
2820
|
const serverData = clientProps.__serverData ?? {};
|
|
2791
2821
|
return new Response(JSON.stringify({ serverData }), {
|
|
@@ -2892,6 +2922,7 @@ var run = async (options) => {
|
|
|
2892
2922
|
console.log(`[hadars] SSR render pool: ${workers} worker threads`);
|
|
2893
2923
|
}
|
|
2894
2924
|
const getPrecontentHtml = makePrecontentHtmlGetter(fs.readFile(pathMod2.join(__dirname3, StaticPath, "out.html"), "utf-8"));
|
|
2925
|
+
const projectStaticPath = pathMod2.resolve(process.cwd(), "static");
|
|
2895
2926
|
const componentPath = pathToFileURL(pathMod2.resolve(__dirname3, HadarsFolder, SSR_FILENAME)).href;
|
|
2896
2927
|
const ssrModulePromise = import(componentPath);
|
|
2897
2928
|
const runHandler = async (req, ctx) => {
|
|
@@ -2908,16 +2939,15 @@ var run = async (options) => {
|
|
|
2908
2939
|
return proxied;
|
|
2909
2940
|
const url = new URL(request.url);
|
|
2910
2941
|
const path2 = url.pathname;
|
|
2911
|
-
const staticRes = await
|
|
2942
|
+
const staticRes = await tryServeFileCached(pathMod2.join(__dirname3, StaticPath, path2));
|
|
2912
2943
|
if (staticRes)
|
|
2913
2944
|
return staticRes;
|
|
2914
|
-
const
|
|
2915
|
-
const projectRes = await tryServeFile(pathMod2.join(projectStaticPath, path2));
|
|
2945
|
+
const projectRes = await tryServeFileCached(pathMod2.join(projectStaticPath, path2));
|
|
2916
2946
|
if (projectRes)
|
|
2917
2947
|
return projectRes;
|
|
2918
2948
|
const routeClean = path2.replace(/(^\/|\/$)/g, "");
|
|
2919
2949
|
if (routeClean) {
|
|
2920
|
-
const routeRes = await
|
|
2950
|
+
const routeRes = await tryServeFileCached(pathMod2.join(__dirname3, StaticPath, routeClean, "index.html"));
|
|
2921
2951
|
if (routeRes)
|
|
2922
2952
|
return routeRes;
|
|
2923
2953
|
}
|
|
@@ -2936,6 +2966,7 @@ var run = async (options) => {
|
|
|
2936
2966
|
status: wStatus
|
|
2937
2967
|
});
|
|
2938
2968
|
}
|
|
2969
|
+
const isDataOnly = request.headers.get("Accept") === "application/json";
|
|
2939
2970
|
const { head, status, getAppBody, finalize } = await getReactResponse(request, {
|
|
2940
2971
|
document: {
|
|
2941
2972
|
body: Component,
|
|
@@ -2943,9 +2974,10 @@ var run = async (options) => {
|
|
|
2943
2974
|
getInitProps,
|
|
2944
2975
|
getFinalProps
|
|
2945
2976
|
},
|
|
2946
|
-
singlePass:
|
|
2977
|
+
singlePass: !isDataOnly,
|
|
2978
|
+
dataOnly: isDataOnly
|
|
2947
2979
|
});
|
|
2948
|
-
if (
|
|
2980
|
+
if (isDataOnly) {
|
|
2949
2981
|
const { clientProps } = await finalize();
|
|
2950
2982
|
const serverData = clientProps.__serverData ?? {};
|
|
2951
2983
|
return new Response(JSON.stringify({ serverData }), {
|
package/dist/cloudflare.cjs
CHANGED
|
@@ -176,6 +176,13 @@ function captureUnsuspend() {
|
|
|
176
176
|
function restoreUnsuspend(u) {
|
|
177
177
|
_g[UNSUSPEND_KEY] = u;
|
|
178
178
|
}
|
|
179
|
+
var HADARS_CTX_KEY = "__hadarsContext";
|
|
180
|
+
function captureHadarsCtx() {
|
|
181
|
+
return _g[HADARS_CTX_KEY];
|
|
182
|
+
}
|
|
183
|
+
function restoreHadarsCtx(h) {
|
|
184
|
+
_g[HADARS_CTX_KEY] = h;
|
|
185
|
+
}
|
|
179
186
|
function getContextValue(context) {
|
|
180
187
|
const map = _g[MAP_KEY];
|
|
181
188
|
if (map && map.has(context)) return map.get(context);
|
|
@@ -329,8 +336,8 @@ function useState(initialState) {
|
|
|
329
336
|
return [value, () => {
|
|
330
337
|
}];
|
|
331
338
|
}
|
|
332
|
-
function useReducer(_reducer,
|
|
333
|
-
return [
|
|
339
|
+
function useReducer(_reducer, initialArg, init) {
|
|
340
|
+
return [init ? init(initialArg) : initialArg, () => {
|
|
334
341
|
}];
|
|
335
342
|
}
|
|
336
343
|
function useEffect(_effect, _deps) {
|
|
@@ -445,12 +452,13 @@ function restoreDispatcher(prev) {
|
|
|
445
452
|
|
|
446
453
|
// src/slim-react/render.ts
|
|
447
454
|
function captureRenderCtx() {
|
|
448
|
-
return { m: captureMap(), u: captureUnsuspend(), t: snapshotContext() };
|
|
455
|
+
return { m: captureMap(), u: captureUnsuspend(), t: snapshotContext(), h: captureHadarsCtx() };
|
|
449
456
|
}
|
|
450
457
|
function restoreRenderCtx(ctx) {
|
|
451
458
|
swapContextMap(ctx.m);
|
|
452
459
|
restoreUnsuspend(ctx.u);
|
|
453
460
|
restoreContext(ctx.t);
|
|
461
|
+
restoreHadarsCtx(ctx.h);
|
|
454
462
|
}
|
|
455
463
|
var VOID_ELEMENTS = /* @__PURE__ */ new Set([
|
|
456
464
|
"area",
|
|
@@ -1058,11 +1066,18 @@ function renderChildArrayFrom(children, startIndex, writer, isSvg) {
|
|
|
1058
1066
|
const r = renderNode(child, writer, isSvg);
|
|
1059
1067
|
if (r && typeof r.then === "function") {
|
|
1060
1068
|
const rctx = captureRenderCtx();
|
|
1061
|
-
return r.then(
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
|
|
1069
|
+
return r.then(
|
|
1070
|
+
() => {
|
|
1071
|
+
restoreRenderCtx(rctx);
|
|
1072
|
+
popTreeContext(savedTree);
|
|
1073
|
+
return renderChildArrayFrom(children, i + 1, writer, isSvg);
|
|
1074
|
+
},
|
|
1075
|
+
(e) => {
|
|
1076
|
+
restoreRenderCtx(rctx);
|
|
1077
|
+
popTreeContext(savedTree);
|
|
1078
|
+
throw e;
|
|
1079
|
+
}
|
|
1080
|
+
);
|
|
1066
1081
|
}
|
|
1067
1082
|
popTreeContext(savedTree);
|
|
1068
1083
|
}
|
|
@@ -1111,20 +1126,15 @@ async function renderSuspense(props, writer, isSvg = false) {
|
|
|
1111
1126
|
}
|
|
1112
1127
|
}
|
|
1113
1128
|
var _streamEncoder = new TextEncoder();
|
|
1114
|
-
var NULL_WRITER = {
|
|
1115
|
-
lastWasText: false,
|
|
1116
|
-
write(_c) {
|
|
1117
|
-
},
|
|
1118
|
-
text(_s) {
|
|
1119
|
-
}
|
|
1120
|
-
};
|
|
1121
1129
|
async function renderPreflight(element, options) {
|
|
1122
1130
|
const idPrefix = options?.identifierPrefix ?? "";
|
|
1131
|
+
const writer = { lastWasText: false, write() {
|
|
1132
|
+
}, text() {
|
|
1133
|
+
} };
|
|
1123
1134
|
const prev = swapContextMap(null);
|
|
1124
1135
|
try {
|
|
1125
1136
|
resetRenderState(idPrefix);
|
|
1126
|
-
|
|
1127
|
-
const r = renderNode(element, NULL_WRITER);
|
|
1137
|
+
const r = renderNode(element, writer);
|
|
1128
1138
|
if (r && typeof r.then === "function") {
|
|
1129
1139
|
const rctx = captureRenderCtx();
|
|
1130
1140
|
await r;
|
|
@@ -1221,7 +1231,16 @@ var getReactResponse = async (req, opts) => {
|
|
|
1221
1231
|
globalThis.__hadarsContext = context;
|
|
1222
1232
|
const element = createElement(App, props);
|
|
1223
1233
|
let bodyHtml = null;
|
|
1224
|
-
if (opts.
|
|
1234
|
+
if (opts.dataOnly) {
|
|
1235
|
+
globalThis.__hadarsUnsuspend = unsuspend;
|
|
1236
|
+
globalThis.__hadarsContext = context;
|
|
1237
|
+
try {
|
|
1238
|
+
await renderPreflight(element);
|
|
1239
|
+
} finally {
|
|
1240
|
+
globalThis.__hadarsUnsuspend = null;
|
|
1241
|
+
globalThis.__hadarsContext = null;
|
|
1242
|
+
}
|
|
1243
|
+
} else if (opts.singlePass) {
|
|
1225
1244
|
globalThis.__hadarsUnsuspend = unsuspend;
|
|
1226
1245
|
globalThis.__hadarsContext = context;
|
|
1227
1246
|
try {
|
|
@@ -1231,6 +1250,8 @@ var getReactResponse = async (req, opts) => {
|
|
|
1231
1250
|
globalThis.__hadarsContext = null;
|
|
1232
1251
|
}
|
|
1233
1252
|
} else {
|
|
1253
|
+
globalThis.__hadarsUnsuspend = unsuspend;
|
|
1254
|
+
globalThis.__hadarsContext = context;
|
|
1234
1255
|
try {
|
|
1235
1256
|
await renderPreflight(element);
|
|
1236
1257
|
} finally {
|
package/dist/cloudflare.js
CHANGED
|
@@ -6,8 +6,8 @@ import {
|
|
|
6
6
|
getReactResponse,
|
|
7
7
|
makePrecontentHtmlGetter,
|
|
8
8
|
parseRequest
|
|
9
|
-
} from "./chunk-
|
|
10
|
-
import "./chunk-
|
|
9
|
+
} from "./chunk-VAR5KTG3.js";
|
|
10
|
+
import "./chunk-6SOA2HTO.js";
|
|
11
11
|
import "./chunk-OZUZS2PD.js";
|
|
12
12
|
|
|
13
13
|
// src/cloudflare.ts
|
package/dist/lambda.cjs
CHANGED
|
@@ -216,6 +216,13 @@ function captureUnsuspend() {
|
|
|
216
216
|
function restoreUnsuspend(u) {
|
|
217
217
|
_g[UNSUSPEND_KEY] = u;
|
|
218
218
|
}
|
|
219
|
+
var HADARS_CTX_KEY = "__hadarsContext";
|
|
220
|
+
function captureHadarsCtx() {
|
|
221
|
+
return _g[HADARS_CTX_KEY];
|
|
222
|
+
}
|
|
223
|
+
function restoreHadarsCtx(h) {
|
|
224
|
+
_g[HADARS_CTX_KEY] = h;
|
|
225
|
+
}
|
|
219
226
|
function getContextValue(context) {
|
|
220
227
|
const map = _g[MAP_KEY];
|
|
221
228
|
if (map && map.has(context)) return map.get(context);
|
|
@@ -369,8 +376,8 @@ function useState(initialState) {
|
|
|
369
376
|
return [value, () => {
|
|
370
377
|
}];
|
|
371
378
|
}
|
|
372
|
-
function useReducer(_reducer,
|
|
373
|
-
return [
|
|
379
|
+
function useReducer(_reducer, initialArg, init) {
|
|
380
|
+
return [init ? init(initialArg) : initialArg, () => {
|
|
374
381
|
}];
|
|
375
382
|
}
|
|
376
383
|
function useEffect(_effect, _deps) {
|
|
@@ -485,12 +492,13 @@ function restoreDispatcher(prev) {
|
|
|
485
492
|
|
|
486
493
|
// src/slim-react/render.ts
|
|
487
494
|
function captureRenderCtx() {
|
|
488
|
-
return { m: captureMap(), u: captureUnsuspend(), t: snapshotContext() };
|
|
495
|
+
return { m: captureMap(), u: captureUnsuspend(), t: snapshotContext(), h: captureHadarsCtx() };
|
|
489
496
|
}
|
|
490
497
|
function restoreRenderCtx(ctx) {
|
|
491
498
|
swapContextMap(ctx.m);
|
|
492
499
|
restoreUnsuspend(ctx.u);
|
|
493
500
|
restoreContext(ctx.t);
|
|
501
|
+
restoreHadarsCtx(ctx.h);
|
|
494
502
|
}
|
|
495
503
|
var VOID_ELEMENTS = /* @__PURE__ */ new Set([
|
|
496
504
|
"area",
|
|
@@ -1098,11 +1106,18 @@ function renderChildArrayFrom(children, startIndex, writer, isSvg) {
|
|
|
1098
1106
|
const r = renderNode(child, writer, isSvg);
|
|
1099
1107
|
if (r && typeof r.then === "function") {
|
|
1100
1108
|
const rctx = captureRenderCtx();
|
|
1101
|
-
return r.then(
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
|
|
1109
|
+
return r.then(
|
|
1110
|
+
() => {
|
|
1111
|
+
restoreRenderCtx(rctx);
|
|
1112
|
+
popTreeContext(savedTree);
|
|
1113
|
+
return renderChildArrayFrom(children, i + 1, writer, isSvg);
|
|
1114
|
+
},
|
|
1115
|
+
(e) => {
|
|
1116
|
+
restoreRenderCtx(rctx);
|
|
1117
|
+
popTreeContext(savedTree);
|
|
1118
|
+
throw e;
|
|
1119
|
+
}
|
|
1120
|
+
);
|
|
1106
1121
|
}
|
|
1107
1122
|
popTreeContext(savedTree);
|
|
1108
1123
|
}
|
|
@@ -1151,20 +1166,15 @@ async function renderSuspense(props, writer, isSvg = false) {
|
|
|
1151
1166
|
}
|
|
1152
1167
|
}
|
|
1153
1168
|
var _streamEncoder = new TextEncoder();
|
|
1154
|
-
var NULL_WRITER = {
|
|
1155
|
-
lastWasText: false,
|
|
1156
|
-
write(_c) {
|
|
1157
|
-
},
|
|
1158
|
-
text(_s) {
|
|
1159
|
-
}
|
|
1160
|
-
};
|
|
1161
1169
|
async function renderPreflight(element, options) {
|
|
1162
1170
|
const idPrefix = options?.identifierPrefix ?? "";
|
|
1171
|
+
const writer = { lastWasText: false, write() {
|
|
1172
|
+
}, text() {
|
|
1173
|
+
} };
|
|
1163
1174
|
const prev = swapContextMap(null);
|
|
1164
1175
|
try {
|
|
1165
1176
|
resetRenderState(idPrefix);
|
|
1166
|
-
|
|
1167
|
-
const r = renderNode(element, NULL_WRITER);
|
|
1177
|
+
const r = renderNode(element, writer);
|
|
1168
1178
|
if (r && typeof r.then === "function") {
|
|
1169
1179
|
const rctx = captureRenderCtx();
|
|
1170
1180
|
await r;
|
|
@@ -1261,7 +1271,16 @@ var getReactResponse = async (req, opts) => {
|
|
|
1261
1271
|
globalThis.__hadarsContext = context;
|
|
1262
1272
|
const element = createElement(App, props);
|
|
1263
1273
|
let bodyHtml = null;
|
|
1264
|
-
if (opts.
|
|
1274
|
+
if (opts.dataOnly) {
|
|
1275
|
+
globalThis.__hadarsUnsuspend = unsuspend;
|
|
1276
|
+
globalThis.__hadarsContext = context;
|
|
1277
|
+
try {
|
|
1278
|
+
await renderPreflight(element);
|
|
1279
|
+
} finally {
|
|
1280
|
+
globalThis.__hadarsUnsuspend = null;
|
|
1281
|
+
globalThis.__hadarsContext = null;
|
|
1282
|
+
}
|
|
1283
|
+
} else if (opts.singlePass) {
|
|
1265
1284
|
globalThis.__hadarsUnsuspend = unsuspend;
|
|
1266
1285
|
globalThis.__hadarsContext = context;
|
|
1267
1286
|
try {
|
|
@@ -1271,6 +1290,8 @@ var getReactResponse = async (req, opts) => {
|
|
|
1271
1290
|
globalThis.__hadarsContext = null;
|
|
1272
1291
|
}
|
|
1273
1292
|
} else {
|
|
1293
|
+
globalThis.__hadarsUnsuspend = unsuspend;
|
|
1294
|
+
globalThis.__hadarsContext = context;
|
|
1274
1295
|
try {
|
|
1275
1296
|
await renderPreflight(element);
|
|
1276
1297
|
} finally {
|
package/dist/lambda.js
CHANGED
|
@@ -104,6 +104,13 @@ function captureUnsuspend() {
|
|
|
104
104
|
function restoreUnsuspend(u) {
|
|
105
105
|
_g[UNSUSPEND_KEY] = u;
|
|
106
106
|
}
|
|
107
|
+
var HADARS_CTX_KEY = "__hadarsContext";
|
|
108
|
+
function captureHadarsCtx() {
|
|
109
|
+
return _g[HADARS_CTX_KEY];
|
|
110
|
+
}
|
|
111
|
+
function restoreHadarsCtx(h) {
|
|
112
|
+
_g[HADARS_CTX_KEY] = h;
|
|
113
|
+
}
|
|
107
114
|
function getContextValue(context) {
|
|
108
115
|
const map = _g[MAP_KEY];
|
|
109
116
|
if (map && map.has(context)) return map.get(context);
|
|
@@ -270,8 +277,8 @@ function useState(initialState) {
|
|
|
270
277
|
return [value, () => {
|
|
271
278
|
}];
|
|
272
279
|
}
|
|
273
|
-
function useReducer(_reducer,
|
|
274
|
-
return [
|
|
280
|
+
function useReducer(_reducer, initialArg, init) {
|
|
281
|
+
return [init ? init(initialArg) : initialArg, () => {
|
|
275
282
|
}];
|
|
276
283
|
}
|
|
277
284
|
function useEffect(_effect, _deps) {
|
|
@@ -418,12 +425,13 @@ function restoreDispatcher(prev) {
|
|
|
418
425
|
|
|
419
426
|
// src/slim-react/render.ts
|
|
420
427
|
function captureRenderCtx() {
|
|
421
|
-
return { m: captureMap(), u: captureUnsuspend(), t: snapshotContext() };
|
|
428
|
+
return { m: captureMap(), u: captureUnsuspend(), t: snapshotContext(), h: captureHadarsCtx() };
|
|
422
429
|
}
|
|
423
430
|
function restoreRenderCtx(ctx) {
|
|
424
431
|
swapContextMap(ctx.m);
|
|
425
432
|
restoreUnsuspend(ctx.u);
|
|
426
433
|
restoreContext(ctx.t);
|
|
434
|
+
restoreHadarsCtx(ctx.h);
|
|
427
435
|
}
|
|
428
436
|
var VOID_ELEMENTS = /* @__PURE__ */ new Set([
|
|
429
437
|
"area",
|
|
@@ -1031,11 +1039,18 @@ function renderChildArrayFrom(children, startIndex, writer, isSvg) {
|
|
|
1031
1039
|
const r = renderNode(child, writer, isSvg);
|
|
1032
1040
|
if (r && typeof r.then === "function") {
|
|
1033
1041
|
const rctx = captureRenderCtx();
|
|
1034
|
-
return r.then(
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1042
|
+
return r.then(
|
|
1043
|
+
() => {
|
|
1044
|
+
restoreRenderCtx(rctx);
|
|
1045
|
+
popTreeContext(savedTree);
|
|
1046
|
+
return renderChildArrayFrom(children, i + 1, writer, isSvg);
|
|
1047
|
+
},
|
|
1048
|
+
(e) => {
|
|
1049
|
+
restoreRenderCtx(rctx);
|
|
1050
|
+
popTreeContext(savedTree);
|
|
1051
|
+
throw e;
|
|
1052
|
+
}
|
|
1053
|
+
);
|
|
1039
1054
|
}
|
|
1040
1055
|
popTreeContext(savedTree);
|
|
1041
1056
|
}
|
|
@@ -1125,20 +1140,15 @@ function renderToStream(element, options) {
|
|
|
1125
1140
|
}
|
|
1126
1141
|
});
|
|
1127
1142
|
}
|
|
1128
|
-
var NULL_WRITER = {
|
|
1129
|
-
lastWasText: false,
|
|
1130
|
-
write(_c) {
|
|
1131
|
-
},
|
|
1132
|
-
text(_s) {
|
|
1133
|
-
}
|
|
1134
|
-
};
|
|
1135
1143
|
async function renderPreflight(element, options) {
|
|
1136
1144
|
const idPrefix = options?.identifierPrefix ?? "";
|
|
1145
|
+
const writer = { lastWasText: false, write() {
|
|
1146
|
+
}, text() {
|
|
1147
|
+
} };
|
|
1137
1148
|
const prev = swapContextMap(null);
|
|
1138
1149
|
try {
|
|
1139
1150
|
resetRenderState(idPrefix);
|
|
1140
|
-
|
|
1141
|
-
const r = renderNode(element, NULL_WRITER);
|
|
1151
|
+
const r = renderNode(element, writer);
|
|
1142
1152
|
if (r && typeof r.then === "function") {
|
|
1143
1153
|
const rctx = captureRenderCtx();
|
|
1144
1154
|
await r;
|
|
@@ -11,7 +11,7 @@ declare function setReactVersion(major: number, version?: string): void;
|
|
|
11
11
|
* compatible libraries to work during server-side rendering.
|
|
12
12
|
*/
|
|
13
13
|
declare function useState<T>(initialState: T | (() => T)): [T, (value: T | ((prev: T) => T)) => void];
|
|
14
|
-
declare function useReducer<S, A>(_reducer: (state: S, action: A) => S,
|
|
14
|
+
declare function useReducer<S, A>(_reducer: (state: S, action: A) => S, initialArg: S, init?: (arg: S) => S): [S, (action: A) => void];
|
|
15
15
|
declare function useEffect(_effect: () => void | (() => void), _deps?: any[]): void;
|
|
16
16
|
declare function useLayoutEffect(_effect: () => void | (() => void), _deps?: any[]): void;
|
|
17
17
|
declare function useInsertionEffect(_effect: () => void | (() => void), _deps?: any[]): void;
|
|
@@ -100,7 +100,7 @@ declare function renderToStream(element: SlimNode, options?: RenderOptions): Rea
|
|
|
100
100
|
/**
|
|
101
101
|
* Pass-1 preflight render.
|
|
102
102
|
*
|
|
103
|
-
* Walks the component tree with a
|
|
103
|
+
* Walks the component tree with a discard writer (no HTML output) so
|
|
104
104
|
* that all `useServerData` promises are resolved into the `__hadarsUnsuspend`
|
|
105
105
|
* cache and all `context.head` mutations are applied.
|
|
106
106
|
*
|
|
@@ -11,7 +11,7 @@ declare function setReactVersion(major: number, version?: string): void;
|
|
|
11
11
|
* compatible libraries to work during server-side rendering.
|
|
12
12
|
*/
|
|
13
13
|
declare function useState<T>(initialState: T | (() => T)): [T, (value: T | ((prev: T) => T)) => void];
|
|
14
|
-
declare function useReducer<S, A>(_reducer: (state: S, action: A) => S,
|
|
14
|
+
declare function useReducer<S, A>(_reducer: (state: S, action: A) => S, initialArg: S, init?: (arg: S) => S): [S, (action: A) => void];
|
|
15
15
|
declare function useEffect(_effect: () => void | (() => void), _deps?: any[]): void;
|
|
16
16
|
declare function useLayoutEffect(_effect: () => void | (() => void), _deps?: any[]): void;
|
|
17
17
|
declare function useInsertionEffect(_effect: () => void | (() => void), _deps?: any[]): void;
|
|
@@ -100,7 +100,7 @@ declare function renderToStream(element: SlimNode, options?: RenderOptions): Rea
|
|
|
100
100
|
/**
|
|
101
101
|
* Pass-1 preflight render.
|
|
102
102
|
*
|
|
103
|
-
* Walks the component tree with a
|
|
103
|
+
* Walks the component tree with a discard writer (no HTML output) so
|
|
104
104
|
* that all `useServerData` promises are resolved into the `__hadarsUnsuspend`
|
|
105
105
|
* cache and all `context.head` mutations are applied.
|
|
106
106
|
*
|
package/dist/slim-react/index.js
CHANGED
|
@@ -27,6 +27,13 @@ function captureUnsuspend() {
|
|
|
27
27
|
function restoreUnsuspend(u) {
|
|
28
28
|
_g[UNSUSPEND_KEY] = u;
|
|
29
29
|
}
|
|
30
|
+
var HADARS_CTX_KEY = "__hadarsContext";
|
|
31
|
+
function captureHadarsCtx() {
|
|
32
|
+
return _g[HADARS_CTX_KEY];
|
|
33
|
+
}
|
|
34
|
+
function restoreHadarsCtx(h) {
|
|
35
|
+
_g[HADARS_CTX_KEY] = h;
|
|
36
|
+
}
|
|
30
37
|
function getContextValue(context) {
|
|
31
38
|
const map = _g[MAP_KEY];
|
|
32
39
|
if (map && map.has(context))
|
|
@@ -180,8 +187,8 @@ function useState(initialState) {
|
|
|
180
187
|
const value = typeof initialState === "function" ? initialState() : initialState;
|
|
181
188
|
return [value, () => {}];
|
|
182
189
|
}
|
|
183
|
-
function useReducer(_reducer,
|
|
184
|
-
return [
|
|
190
|
+
function useReducer(_reducer, initialArg, init) {
|
|
191
|
+
return [init ? init(initialArg) : initialArg, () => {}];
|
|
185
192
|
}
|
|
186
193
|
function useEffect(_effect, _deps) {}
|
|
187
194
|
function useLayoutEffect(_effect, _deps) {}
|
|
@@ -291,12 +298,13 @@ function restoreDispatcher(prev) {
|
|
|
291
298
|
|
|
292
299
|
// src/slim-react/render.ts
|
|
293
300
|
function captureRenderCtx() {
|
|
294
|
-
return { m: captureMap(), u: captureUnsuspend(), t: snapshotContext() };
|
|
301
|
+
return { m: captureMap(), u: captureUnsuspend(), t: snapshotContext(), h: captureHadarsCtx() };
|
|
295
302
|
}
|
|
296
303
|
function restoreRenderCtx(ctx) {
|
|
297
304
|
swapContextMap(ctx.m);
|
|
298
305
|
restoreUnsuspend(ctx.u);
|
|
299
306
|
restoreContext(ctx.t);
|
|
307
|
+
restoreHadarsCtx(ctx.h);
|
|
300
308
|
}
|
|
301
309
|
var VOID_ELEMENTS = new Set([
|
|
302
310
|
"area",
|
|
@@ -921,6 +929,10 @@ function renderChildArrayFrom(children, startIndex, writer, isSvg) {
|
|
|
921
929
|
restoreRenderCtx(rctx);
|
|
922
930
|
popTreeContext(savedTree);
|
|
923
931
|
return renderChildArrayFrom(children, i + 1, writer, isSvg);
|
|
932
|
+
}, (e) => {
|
|
933
|
+
restoreRenderCtx(rctx);
|
|
934
|
+
popTreeContext(savedTree);
|
|
935
|
+
throw e;
|
|
924
936
|
});
|
|
925
937
|
}
|
|
926
938
|
popTreeContext(savedTree);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "hadars",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.6",
|
|
4
4
|
"description": "Minimal SSR framework for React — rspack, HMR, TypeScript, Bun/Node/Deno",
|
|
5
5
|
"module": "./dist/index.js",
|
|
6
6
|
"type": "module",
|
|
@@ -85,6 +85,7 @@
|
|
|
85
85
|
"typescript": "^5.9.3"
|
|
86
86
|
},
|
|
87
87
|
"dependencies": {
|
|
88
|
+
"hadars": "^1.0.5",
|
|
88
89
|
"postcss": "^8.5.8",
|
|
89
90
|
"postcss-load-config": "^6.0.1",
|
|
90
91
|
"postcss-loader": "^8.2.1"
|