hadars 0.1.40 → 0.2.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/README.md +85 -70
- package/cli-lib.ts +89 -12
- package/dist/chunk-HWOLYLPF.js +332 -0
- package/dist/{chunk-2ENP7IAW.js → chunk-LY5MTHFV.js} +360 -203
- package/dist/cli.js +506 -274
- package/dist/cloudflare.cjs +1394 -0
- package/dist/cloudflare.d.cts +64 -0
- package/dist/cloudflare.d.ts +64 -0
- package/dist/cloudflare.js +68 -0
- package/dist/{hadars-Bh-V5YXg.d.cts → hadars-DEBSYAQl.d.cts} +1 -36
- package/dist/{hadars-Bh-V5YXg.d.ts → hadars-DEBSYAQl.d.ts} +1 -36
- package/dist/index.cjs +129 -156
- package/dist/index.d.cts +5 -11
- package/dist/index.d.ts +5 -11
- package/dist/index.js +129 -155
- package/dist/lambda.cjs +391 -229
- package/dist/lambda.d.cts +1 -2
- package/dist/lambda.d.ts +1 -2
- package/dist/lambda.js +18 -307
- package/dist/slim-react/index.cjs +361 -203
- package/dist/slim-react/index.d.cts +24 -8
- package/dist/slim-react/index.d.ts +24 -8
- package/dist/slim-react/index.js +3 -1
- package/dist/ssr-render-worker.js +352 -221
- package/dist/utils/Head.tsx +132 -187
- package/package.json +7 -2
- package/src/build.ts +7 -6
- package/src/cloudflare.ts +139 -0
- package/src/index.tsx +0 -3
- package/src/lambda.ts +6 -2
- package/src/slim-react/context.ts +2 -1
- package/src/slim-react/index.ts +21 -18
- package/src/slim-react/render.ts +379 -240
- package/src/slim-react/renderContext.ts +105 -45
- package/src/ssr-render-worker.ts +14 -44
- package/src/types/hadars.ts +0 -1
- package/src/utils/Head.tsx +132 -187
- package/src/utils/cookies.ts +1 -1
- package/src/utils/response.tsx +68 -33
- package/src/utils/serve.ts +29 -27
- package/src/utils/ssrHandler.ts +54 -25
- package/src/utils/staticFile.ts +2 -7
package/dist/cli.js
CHANGED
|
@@ -107,7 +107,11 @@ var parseCookies = (cookieString) => {
|
|
|
107
107
|
if (index > -1) {
|
|
108
108
|
const key = pair.slice(0, index).trim();
|
|
109
109
|
const value = pair.slice(index + 1).trim();
|
|
110
|
-
|
|
110
|
+
try {
|
|
111
|
+
cookies[key] = decodeURIComponent(value);
|
|
112
|
+
} catch {
|
|
113
|
+
cookies[key] = value;
|
|
114
|
+
}
|
|
111
115
|
}
|
|
112
116
|
}
|
|
113
117
|
return cookies;
|
|
@@ -171,6 +175,13 @@ function swapContextMap(map) {
|
|
|
171
175
|
function captureMap() {
|
|
172
176
|
return _g[MAP_KEY];
|
|
173
177
|
}
|
|
178
|
+
var UNSUSPEND_KEY = "__hadarsUnsuspend";
|
|
179
|
+
function captureUnsuspend() {
|
|
180
|
+
return _g[UNSUSPEND_KEY];
|
|
181
|
+
}
|
|
182
|
+
function restoreUnsuspend(u) {
|
|
183
|
+
_g[UNSUSPEND_KEY] = u;
|
|
184
|
+
}
|
|
174
185
|
function getContextValue(context) {
|
|
175
186
|
const map = _g[MAP_KEY];
|
|
176
187
|
if (map && map.has(context)) return map.get(context);
|
|
@@ -178,10 +189,14 @@ function getContextValue(context) {
|
|
|
178
189
|
return "_defaultValue" in c ? c._defaultValue : c._currentValue;
|
|
179
190
|
}
|
|
180
191
|
function pushContextValue(context, value) {
|
|
181
|
-
|
|
192
|
+
let map = _g[MAP_KEY];
|
|
193
|
+
if (map === null) {
|
|
194
|
+
map = /* @__PURE__ */ new Map();
|
|
195
|
+
_g[MAP_KEY] = map;
|
|
196
|
+
}
|
|
182
197
|
const c = context;
|
|
183
|
-
const prev = map
|
|
184
|
-
map
|
|
198
|
+
const prev = map.has(context) ? map.get(context) : "_defaultValue" in c ? c._defaultValue : c._currentValue;
|
|
199
|
+
map.set(context, value);
|
|
185
200
|
return prev;
|
|
186
201
|
}
|
|
187
202
|
function popContextValue(context, prev) {
|
|
@@ -189,48 +204,57 @@ function popContextValue(context, prev) {
|
|
|
189
204
|
}
|
|
190
205
|
var GLOBAL_KEY = "__slimReactRenderState";
|
|
191
206
|
var EMPTY = { id: 1, overflow: "" };
|
|
207
|
+
var _stateCache = null;
|
|
192
208
|
function s() {
|
|
193
|
-
|
|
194
|
-
if (!
|
|
195
|
-
|
|
209
|
+
if (_stateCache !== null) return _stateCache;
|
|
210
|
+
if (!_g[GLOBAL_KEY]) {
|
|
211
|
+
_g[GLOBAL_KEY] = { currentTreeContext: { ...EMPTY }, localIdCounter: 0, idPrefix: "" };
|
|
196
212
|
}
|
|
197
|
-
|
|
213
|
+
_stateCache = _g[GLOBAL_KEY];
|
|
214
|
+
return _stateCache;
|
|
198
215
|
}
|
|
216
|
+
var _treeIdStack = [];
|
|
217
|
+
var _treeOvStack = [];
|
|
218
|
+
var _treeDepth = 0;
|
|
199
219
|
function resetRenderState(idPrefix = "") {
|
|
200
220
|
const st = s();
|
|
201
|
-
st.currentTreeContext =
|
|
221
|
+
st.currentTreeContext.id = EMPTY.id;
|
|
222
|
+
st.currentTreeContext.overflow = EMPTY.overflow;
|
|
202
223
|
st.localIdCounter = 0;
|
|
203
224
|
st.idPrefix = idPrefix;
|
|
225
|
+
_treeDepth = 0;
|
|
204
226
|
}
|
|
205
227
|
function pushTreeContext(totalChildren, index) {
|
|
206
228
|
const st = s();
|
|
207
|
-
const
|
|
208
|
-
const
|
|
209
|
-
|
|
229
|
+
const ctx = st.currentTreeContext;
|
|
230
|
+
const depth = _treeDepth++;
|
|
231
|
+
_treeIdStack[depth] = ctx.id;
|
|
232
|
+
_treeOvStack[depth] = ctx.overflow;
|
|
233
|
+
const baseIdWithLeadingBit = ctx.id;
|
|
234
|
+
const baseOverflow = ctx.overflow;
|
|
210
235
|
const baseLength = 31 - Math.clz32(baseIdWithLeadingBit);
|
|
211
236
|
let baseId = baseIdWithLeadingBit & ~(1 << baseLength);
|
|
212
237
|
const slot = index + 1;
|
|
213
238
|
const newBits = 32 - Math.clz32(totalChildren);
|
|
214
239
|
const length = newBits + baseLength;
|
|
215
240
|
if (30 < length) {
|
|
216
|
-
const
|
|
217
|
-
const overflowStr = (baseId & (1 <<
|
|
218
|
-
baseId >>=
|
|
219
|
-
const newBaseLength = baseLength -
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
overflow: overflowStr + baseOverflow
|
|
223
|
-
};
|
|
241
|
+
const overflowBits = baseLength - baseLength % 5;
|
|
242
|
+
const overflowStr = (baseId & (1 << overflowBits) - 1).toString(32);
|
|
243
|
+
baseId >>= overflowBits;
|
|
244
|
+
const newBaseLength = baseLength - overflowBits;
|
|
245
|
+
ctx.id = 1 << newBits + newBaseLength | slot << newBaseLength | baseId;
|
|
246
|
+
ctx.overflow = overflowStr + baseOverflow;
|
|
224
247
|
} else {
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
overflow: baseOverflow
|
|
228
|
-
};
|
|
248
|
+
ctx.id = 1 << length | slot << baseLength | baseId;
|
|
249
|
+
ctx.overflow = baseOverflow;
|
|
229
250
|
}
|
|
230
|
-
return
|
|
251
|
+
return depth;
|
|
231
252
|
}
|
|
232
|
-
function popTreeContext(
|
|
233
|
-
s().currentTreeContext
|
|
253
|
+
function popTreeContext(depth) {
|
|
254
|
+
const ctx = s().currentTreeContext;
|
|
255
|
+
ctx.id = _treeIdStack[depth];
|
|
256
|
+
ctx.overflow = _treeOvStack[depth];
|
|
257
|
+
_treeDepth = depth;
|
|
234
258
|
}
|
|
235
259
|
function pushComponentScope() {
|
|
236
260
|
const st = s();
|
|
@@ -246,12 +270,16 @@ function componentCalledUseId() {
|
|
|
246
270
|
}
|
|
247
271
|
function snapshotContext() {
|
|
248
272
|
const st = s();
|
|
249
|
-
|
|
273
|
+
const ctx = st.currentTreeContext;
|
|
274
|
+
return { tree: { id: ctx.id, overflow: ctx.overflow }, localId: st.localIdCounter, treeDepth: _treeDepth };
|
|
250
275
|
}
|
|
251
276
|
function restoreContext(snap) {
|
|
252
277
|
const st = s();
|
|
253
|
-
|
|
278
|
+
const ctx = st.currentTreeContext;
|
|
279
|
+
ctx.id = snap.tree.id;
|
|
280
|
+
ctx.overflow = snap.tree.overflow;
|
|
254
281
|
st.localIdCounter = snap.localId;
|
|
282
|
+
_treeDepth = snap.treeDepth;
|
|
255
283
|
}
|
|
256
284
|
function getTreeId() {
|
|
257
285
|
const { id, overflow } = s().currentTreeContext;
|
|
@@ -382,19 +410,80 @@ var VOID_ELEMENTS = /* @__PURE__ */ new Set([
|
|
|
382
410
|
"wbr"
|
|
383
411
|
]);
|
|
384
412
|
var HTML_ESC = { "&": "&", "<": "<", ">": ">", "'": "'" };
|
|
413
|
+
var HTML_ESC_RE = /[&<>']/;
|
|
385
414
|
function escapeHtml(str) {
|
|
415
|
+
if (!HTML_ESC_RE.test(str)) return str;
|
|
386
416
|
return str.replace(/[&<>']/g, (c) => HTML_ESC[c]);
|
|
387
417
|
}
|
|
388
418
|
var ATTR_ESC = { "&": "&", '"': """, "<": "<", ">": ">" };
|
|
419
|
+
var ATTR_ESC_RE = /[&"<>]/;
|
|
389
420
|
function escapeAttr(str) {
|
|
421
|
+
if (!ATTR_ESC_RE.test(str)) return str;
|
|
390
422
|
return str.replace(/[&"<>]/g, (c) => ATTR_ESC[c]);
|
|
391
423
|
}
|
|
424
|
+
var UNITLESS_CSS = /* @__PURE__ */ new Set([
|
|
425
|
+
"animationIterationCount",
|
|
426
|
+
"aspectRatio",
|
|
427
|
+
"borderImageOutset",
|
|
428
|
+
"borderImageSlice",
|
|
429
|
+
"borderImageWidth",
|
|
430
|
+
"boxFlex",
|
|
431
|
+
"boxFlexGroup",
|
|
432
|
+
"boxOrdinalGroup",
|
|
433
|
+
"columnCount",
|
|
434
|
+
"columns",
|
|
435
|
+
"flex",
|
|
436
|
+
"flexGrow",
|
|
437
|
+
"flexPositive",
|
|
438
|
+
"flexShrink",
|
|
439
|
+
"flexNegative",
|
|
440
|
+
"flexOrder",
|
|
441
|
+
"gridArea",
|
|
442
|
+
"gridRow",
|
|
443
|
+
"gridRowEnd",
|
|
444
|
+
"gridRowSpan",
|
|
445
|
+
"gridRowStart",
|
|
446
|
+
"gridColumn",
|
|
447
|
+
"gridColumnEnd",
|
|
448
|
+
"gridColumnSpan",
|
|
449
|
+
"gridColumnStart",
|
|
450
|
+
"fontWeight",
|
|
451
|
+
"lineClamp",
|
|
452
|
+
"lineHeight",
|
|
453
|
+
"opacity",
|
|
454
|
+
"order",
|
|
455
|
+
"orphans",
|
|
456
|
+
"scale",
|
|
457
|
+
"tabSize",
|
|
458
|
+
"widows",
|
|
459
|
+
"zIndex",
|
|
460
|
+
"zoom",
|
|
461
|
+
"fillOpacity",
|
|
462
|
+
"floodOpacity",
|
|
463
|
+
"stopOpacity",
|
|
464
|
+
"strokeDasharray",
|
|
465
|
+
"strokeDashoffset",
|
|
466
|
+
"strokeMiterlimit",
|
|
467
|
+
"strokeOpacity",
|
|
468
|
+
"strokeWidth"
|
|
469
|
+
]);
|
|
470
|
+
var _cssKeyCache = /* @__PURE__ */ new Map();
|
|
392
471
|
function styleObjectToString(style) {
|
|
393
472
|
let result = "";
|
|
394
473
|
for (const key in style) {
|
|
474
|
+
const value = style[key];
|
|
475
|
+
if (value == null || typeof value === "boolean") continue;
|
|
395
476
|
if (result) result += ";";
|
|
396
|
-
|
|
397
|
-
|
|
477
|
+
let cssKey = _cssKeyCache.get(key);
|
|
478
|
+
if (cssKey === void 0) {
|
|
479
|
+
cssKey = key.replace(/[A-Z]/g, (m) => "-" + m.toLowerCase());
|
|
480
|
+
_cssKeyCache.set(key, cssKey);
|
|
481
|
+
}
|
|
482
|
+
if (typeof value === "number" && value !== 0 && !UNITLESS_CSS.has(key)) {
|
|
483
|
+
result += cssKey + ":" + value + "px";
|
|
484
|
+
} else {
|
|
485
|
+
result += cssKey + ":" + value;
|
|
486
|
+
}
|
|
398
487
|
}
|
|
399
488
|
return result;
|
|
400
489
|
}
|
|
@@ -529,14 +618,22 @@ var SVG_ATTR_MAP = {
|
|
|
529
618
|
xChannelSelector: "xChannelSelector",
|
|
530
619
|
yChannelSelector: "yChannelSelector"
|
|
531
620
|
};
|
|
532
|
-
|
|
533
|
-
|
|
621
|
+
var TEXTAREA_SKIP_PROPS = /* @__PURE__ */ new Set(["value", "defaultValue", "children"]);
|
|
622
|
+
var SELECT_SKIP_PROPS = /* @__PURE__ */ new Set(["value", "defaultValue"]);
|
|
623
|
+
var INTERNAL_PROPS = /* @__PURE__ */ new Set([
|
|
624
|
+
"children",
|
|
625
|
+
"key",
|
|
626
|
+
"ref",
|
|
627
|
+
"dangerouslySetInnerHTML",
|
|
628
|
+
"suppressHydrationWarning",
|
|
629
|
+
"suppressContentEditableWarning"
|
|
630
|
+
]);
|
|
631
|
+
function writeAttributes(writer, props, isSvg, skip) {
|
|
534
632
|
for (const key in props) {
|
|
633
|
+
if (skip !== void 0 && skip.has(key)) continue;
|
|
535
634
|
const value = props[key];
|
|
536
|
-
if (key
|
|
537
|
-
|
|
538
|
-
if (key.startsWith("on") && key.length > 2 && key[2] === key[2].toUpperCase())
|
|
539
|
-
continue;
|
|
635
|
+
if (INTERNAL_PROPS.has(key)) continue;
|
|
636
|
+
if (key.length > 2 && key.charCodeAt(0) === 111 && key.charCodeAt(1) === 110 && key.charCodeAt(2) >= 65 && key.charCodeAt(2) <= 90) continue;
|
|
540
637
|
let attrName;
|
|
541
638
|
if (isSvg && key in SVG_ATTR_MAP) {
|
|
542
639
|
attrName = SVG_ATTR_MAP[key];
|
|
@@ -544,41 +641,46 @@ function renderAttributes(props, isSvg) {
|
|
|
544
641
|
attrName = key === "className" ? "class" : key === "htmlFor" ? "for" : key === "tabIndex" ? "tabindex" : key === "defaultValue" ? "value" : key === "defaultChecked" ? "checked" : key;
|
|
545
642
|
}
|
|
546
643
|
if (value === false || value == null) {
|
|
547
|
-
if (value === false && (attrName.startsWith("aria-") || attrName.startsWith("data-"))) {
|
|
548
|
-
|
|
644
|
+
if (value === false && (attrName.charCodeAt(0) === 97 && attrName.startsWith("aria-") || attrName.charCodeAt(0) === 100 && attrName.startsWith("data-"))) {
|
|
645
|
+
writer.write(` ${attrName}="false"`);
|
|
549
646
|
}
|
|
550
647
|
continue;
|
|
551
648
|
}
|
|
552
649
|
if (value === true) {
|
|
553
|
-
if (attrName.startsWith("aria-") || attrName.startsWith("data-")) {
|
|
554
|
-
|
|
650
|
+
if (attrName.charCodeAt(0) === 97 && attrName.startsWith("aria-") || attrName.charCodeAt(0) === 100 && attrName.startsWith("data-")) {
|
|
651
|
+
writer.write(` ${attrName}="true"`);
|
|
555
652
|
} else {
|
|
556
|
-
|
|
653
|
+
writer.write(` ${attrName}=""`);
|
|
557
654
|
}
|
|
558
655
|
continue;
|
|
559
656
|
}
|
|
560
657
|
if (key === "style" && typeof value === "object") {
|
|
561
658
|
const styleStr = styleObjectToString(value);
|
|
562
|
-
if (styleStr)
|
|
659
|
+
if (styleStr) writer.write(` style="${escapeAttr(styleStr)}"`);
|
|
563
660
|
continue;
|
|
564
661
|
}
|
|
565
|
-
|
|
662
|
+
writer.write(` ${attrName}="${escapeAttr(typeof value === "string" ? value : String(value))}"`);
|
|
566
663
|
}
|
|
567
|
-
return attrs;
|
|
568
664
|
}
|
|
569
|
-
var BufferWriter = class {
|
|
570
|
-
|
|
665
|
+
var BufferWriter = class _BufferWriter {
|
|
666
|
+
data = "";
|
|
571
667
|
lastWasText = false;
|
|
572
668
|
write(chunk) {
|
|
573
|
-
this.
|
|
669
|
+
this.data += chunk;
|
|
574
670
|
this.lastWasText = false;
|
|
575
671
|
}
|
|
576
672
|
text(s2) {
|
|
577
|
-
this.
|
|
673
|
+
this.data += s2;
|
|
578
674
|
this.lastWasText = true;
|
|
579
675
|
}
|
|
580
|
-
|
|
581
|
-
|
|
676
|
+
/** Flush accumulated output into a parent writer and reset. */
|
|
677
|
+
flushTo(target) {
|
|
678
|
+
if (!this.data) return;
|
|
679
|
+
if (target instanceof _BufferWriter) {
|
|
680
|
+
target.data += this.data;
|
|
681
|
+
} else {
|
|
682
|
+
target.write(this.data);
|
|
683
|
+
}
|
|
582
684
|
target.lastWasText = this.lastWasText;
|
|
583
685
|
}
|
|
584
686
|
};
|
|
@@ -595,15 +697,12 @@ function renderNode(node, writer, isSvg = false) {
|
|
|
595
697
|
if (Array.isArray(node)) {
|
|
596
698
|
return renderChildArray(node, writer, isSvg);
|
|
597
699
|
}
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
writer,
|
|
602
|
-
isSvg
|
|
603
|
-
);
|
|
700
|
+
const obj = node;
|
|
701
|
+
if (Symbol.iterator in obj && !("$$typeof" in obj)) {
|
|
702
|
+
return renderChildArray(Array.from(obj), writer, isSvg);
|
|
604
703
|
}
|
|
605
|
-
if (
|
|
606
|
-
const elType =
|
|
704
|
+
if ("$$typeof" in obj) {
|
|
705
|
+
const elType = obj["$$typeof"];
|
|
607
706
|
if (elType !== SLIM_ELEMENT && elType !== REACT19_ELEMENT) return;
|
|
608
707
|
const element = node;
|
|
609
708
|
const { type, props } = element;
|
|
@@ -613,15 +712,15 @@ function renderNode(node, writer, isSvg = false) {
|
|
|
613
712
|
if (type === SUSPENSE_TYPE) {
|
|
614
713
|
return renderSuspense(props, writer, isSvg);
|
|
615
714
|
}
|
|
715
|
+
if (typeof type === "string") {
|
|
716
|
+
return renderHostElement(type, props, writer, isSvg);
|
|
717
|
+
}
|
|
616
718
|
if (typeof type === "function") {
|
|
617
719
|
return renderComponent(type, props, writer, isSvg);
|
|
618
720
|
}
|
|
619
721
|
if (typeof type === "object" && type !== null) {
|
|
620
722
|
return renderComponent(type, props, writer, isSvg);
|
|
621
723
|
}
|
|
622
|
-
if (typeof type === "string") {
|
|
623
|
-
return renderHostElement(type, props, writer, isSvg);
|
|
624
|
-
}
|
|
625
724
|
}
|
|
626
725
|
}
|
|
627
726
|
function markSelectedOptionsMulti(children, selectedValues) {
|
|
@@ -647,26 +746,21 @@ function markSelectedOptionsMulti(children, selectedValues) {
|
|
|
647
746
|
return children;
|
|
648
747
|
}
|
|
649
748
|
function renderHostElement(tag, props, writer, isSvg) {
|
|
650
|
-
const
|
|
651
|
-
const childSvg = isSvg || enteringSvg;
|
|
749
|
+
const childSvg = isSvg || tag === "svg";
|
|
652
750
|
if (tag === "textarea") {
|
|
653
751
|
const textContent = props.value ?? props.defaultValue ?? props.children ?? "";
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
}
|
|
658
|
-
writer.write(`<textarea${renderAttributes(filteredProps, false)}>`);
|
|
752
|
+
writer.write("<textarea");
|
|
753
|
+
writeAttributes(writer, props, false, TEXTAREA_SKIP_PROPS);
|
|
754
|
+
writer.write(">");
|
|
659
755
|
writer.text(escapeHtml(String(textContent)));
|
|
660
756
|
writer.write("</textarea>");
|
|
661
757
|
return;
|
|
662
758
|
}
|
|
663
759
|
if (tag === "select") {
|
|
664
760
|
const selectedValue = props.value ?? props.defaultValue;
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
}
|
|
669
|
-
writer.write(`<select${renderAttributes(filteredProps, false)}>`);
|
|
761
|
+
writer.write("<select");
|
|
762
|
+
writeAttributes(writer, props, false, SELECT_SKIP_PROPS);
|
|
763
|
+
writer.write(">");
|
|
670
764
|
const selectedSet = selectedValue == null ? null : Array.isArray(selectedValue) ? new Set(selectedValue.map(String)) : /* @__PURE__ */ new Set([String(selectedValue)]);
|
|
671
765
|
const patchedChildren = selectedSet != null ? markSelectedOptionsMulti(props.children, selectedSet) : props.children;
|
|
672
766
|
const inner2 = renderChildren(patchedChildren, writer, false);
|
|
@@ -678,7 +772,8 @@ function renderHostElement(tag, props, writer, isSvg) {
|
|
|
678
772
|
writer.write("</select>");
|
|
679
773
|
return;
|
|
680
774
|
}
|
|
681
|
-
writer.write(`<${tag}
|
|
775
|
+
writer.write(`<${tag}`);
|
|
776
|
+
writeAttributes(writer, props, childSvg);
|
|
682
777
|
if (VOID_ELEMENTS.has(tag)) {
|
|
683
778
|
writer.write("/>");
|
|
684
779
|
return;
|
|
@@ -704,8 +799,25 @@ var REACT_PROVIDER = /* @__PURE__ */ Symbol.for("react.provider");
|
|
|
704
799
|
var REACT_CONTEXT = /* @__PURE__ */ Symbol.for("react.context");
|
|
705
800
|
var REACT_CONSUMER = /* @__PURE__ */ Symbol.for("react.consumer");
|
|
706
801
|
var REACT_LAZY = /* @__PURE__ */ Symbol.for("react.lazy");
|
|
707
|
-
|
|
708
|
-
|
|
802
|
+
var SUSPENSE_RETRY_LIMIT = /* @__PURE__ */ Symbol("SuspenseRetryLimit");
|
|
803
|
+
var MAX_COMPONENT_SUSPENSE_RETRIES = 25;
|
|
804
|
+
function patchPromiseStatus(p) {
|
|
805
|
+
const w = p;
|
|
806
|
+
if (w.status) return;
|
|
807
|
+
w.status = "pending";
|
|
808
|
+
w.then(
|
|
809
|
+
(v) => {
|
|
810
|
+
w.status = "fulfilled";
|
|
811
|
+
w.value = v;
|
|
812
|
+
},
|
|
813
|
+
(r) => {
|
|
814
|
+
w.status = "rejected";
|
|
815
|
+
w.reason = r;
|
|
816
|
+
}
|
|
817
|
+
);
|
|
818
|
+
}
|
|
819
|
+
function renderComponent(type, props, writer, isSvg, _suspenseRetries = 0) {
|
|
820
|
+
const typeOf = type.$$typeof;
|
|
709
821
|
if (typeOf === REACT_MEMO) {
|
|
710
822
|
return renderNode(
|
|
711
823
|
{ $$typeof: SLIM_ELEMENT, type: type.type, props, key: null },
|
|
@@ -717,7 +829,23 @@ function renderComponent(type, props, writer, isSvg) {
|
|
|
717
829
|
return renderComponent(type.render, props, writer, isSvg);
|
|
718
830
|
}
|
|
719
831
|
if (typeOf === REACT_LAZY) {
|
|
720
|
-
|
|
832
|
+
let resolved;
|
|
833
|
+
try {
|
|
834
|
+
resolved = type._init(type._payload);
|
|
835
|
+
} catch (e) {
|
|
836
|
+
if (e && typeof e.then === "function") {
|
|
837
|
+
if (_suspenseRetries + 1 >= MAX_COMPONENT_SUSPENSE_RETRIES) throw SUSPENSE_RETRY_LIMIT;
|
|
838
|
+
patchPromiseStatus(e);
|
|
839
|
+
const m = captureMap();
|
|
840
|
+
const u = captureUnsuspend();
|
|
841
|
+
return e.then(() => {
|
|
842
|
+
swapContextMap(m);
|
|
843
|
+
restoreUnsuspend(u);
|
|
844
|
+
return renderComponent(type, props, writer, isSvg, _suspenseRetries + 1);
|
|
845
|
+
});
|
|
846
|
+
}
|
|
847
|
+
throw e;
|
|
848
|
+
}
|
|
721
849
|
const LazyComp = resolved?.default ?? resolved;
|
|
722
850
|
return renderComponent(LazyComp, props, writer, isSvg);
|
|
723
851
|
}
|
|
@@ -726,12 +854,12 @@ function renderComponent(type, props, writer, isSvg) {
|
|
|
726
854
|
const value = ctx2 ? getContextValue(ctx2) : void 0;
|
|
727
855
|
const result2 = typeof props.children === "function" ? props.children(value) : null;
|
|
728
856
|
const savedScope2 = pushComponentScope();
|
|
729
|
-
const
|
|
857
|
+
const finish = () => popComponentScope(savedScope2);
|
|
730
858
|
const r2 = renderNode(result2, writer, isSvg);
|
|
731
859
|
if (r2 && typeof r2.then === "function") {
|
|
732
|
-
return r2.then(
|
|
860
|
+
return r2.then(finish);
|
|
733
861
|
}
|
|
734
|
-
|
|
862
|
+
finish();
|
|
735
863
|
return;
|
|
736
864
|
}
|
|
737
865
|
const isProvider = "_context" in type || typeOf === REACT_PROVIDER || typeOf === REACT_CONTEXT && "value" in props;
|
|
@@ -743,26 +871,29 @@ function renderComponent(type, props, writer, isSvg) {
|
|
|
743
871
|
}
|
|
744
872
|
const savedScope = pushComponentScope();
|
|
745
873
|
if (isProvider && typeof type !== "function") {
|
|
746
|
-
const
|
|
874
|
+
const finish = () => {
|
|
747
875
|
popComponentScope(savedScope);
|
|
748
876
|
popContextValue(ctx, prevCtxValue);
|
|
749
877
|
};
|
|
750
878
|
const r2 = renderChildren(props.children, writer, isSvg);
|
|
751
879
|
if (r2 && typeof r2.then === "function") {
|
|
752
880
|
const m = captureMap();
|
|
881
|
+
const u = captureUnsuspend();
|
|
753
882
|
return r2.then(
|
|
754
883
|
() => {
|
|
755
884
|
swapContextMap(m);
|
|
756
|
-
|
|
885
|
+
restoreUnsuspend(u);
|
|
886
|
+
finish();
|
|
757
887
|
},
|
|
758
888
|
(e) => {
|
|
759
889
|
swapContextMap(m);
|
|
760
|
-
|
|
890
|
+
restoreUnsuspend(u);
|
|
891
|
+
finish();
|
|
761
892
|
throw e;
|
|
762
893
|
}
|
|
763
894
|
);
|
|
764
895
|
}
|
|
765
|
-
|
|
896
|
+
finish();
|
|
766
897
|
return;
|
|
767
898
|
}
|
|
768
899
|
let result;
|
|
@@ -782,6 +913,17 @@ function renderComponent(type, props, writer, isSvg) {
|
|
|
782
913
|
restoreDispatcher(prevDispatcher);
|
|
783
914
|
popComponentScope(savedScope);
|
|
784
915
|
if (isProvider) popContextValue(ctx, prevCtxValue);
|
|
916
|
+
if (e && typeof e.then === "function") {
|
|
917
|
+
if (_suspenseRetries + 1 >= MAX_COMPONENT_SUSPENSE_RETRIES) throw SUSPENSE_RETRY_LIMIT;
|
|
918
|
+
patchPromiseStatus(e);
|
|
919
|
+
const m = captureMap();
|
|
920
|
+
const u = captureUnsuspend();
|
|
921
|
+
return e.then(() => {
|
|
922
|
+
swapContextMap(m);
|
|
923
|
+
restoreUnsuspend(u);
|
|
924
|
+
return renderComponent(type, props, writer, isSvg, _suspenseRetries + 1);
|
|
925
|
+
});
|
|
926
|
+
}
|
|
785
927
|
throw e;
|
|
786
928
|
}
|
|
787
929
|
restoreDispatcher(prevDispatcher);
|
|
@@ -789,97 +931,93 @@ function renderComponent(type, props, writer, isSvg) {
|
|
|
789
931
|
if (!(result instanceof Promise) && componentCalledUseId()) {
|
|
790
932
|
savedIdTree = pushTreeContext(1, 0);
|
|
791
933
|
}
|
|
792
|
-
const finish = () => {
|
|
793
|
-
if (savedIdTree !== void 0) popTreeContext(savedIdTree);
|
|
794
|
-
popComponentScope(savedScope);
|
|
795
|
-
if (isProvider) popContextValue(ctx, prevCtxValue);
|
|
796
|
-
};
|
|
797
934
|
if (result instanceof Promise) {
|
|
798
935
|
const m = captureMap();
|
|
936
|
+
const u = captureUnsuspend();
|
|
799
937
|
return result.then((resolved) => {
|
|
800
938
|
swapContextMap(m);
|
|
939
|
+
restoreUnsuspend(u);
|
|
801
940
|
let asyncSavedIdTree;
|
|
802
941
|
if (componentCalledUseId()) {
|
|
803
942
|
asyncSavedIdTree = pushTreeContext(1, 0);
|
|
804
943
|
}
|
|
805
|
-
const asyncFinish = () => {
|
|
806
|
-
if (asyncSavedIdTree !== void 0) popTreeContext(asyncSavedIdTree);
|
|
807
|
-
popComponentScope(savedScope);
|
|
808
|
-
if (isProvider) popContextValue(ctx, prevCtxValue);
|
|
809
|
-
};
|
|
810
944
|
const r2 = renderNode(resolved, writer, isSvg);
|
|
811
945
|
if (r2 && typeof r2.then === "function") {
|
|
812
946
|
const m2 = captureMap();
|
|
947
|
+
const u2 = captureUnsuspend();
|
|
813
948
|
return r2.then(
|
|
814
949
|
() => {
|
|
815
950
|
swapContextMap(m2);
|
|
816
|
-
|
|
951
|
+
restoreUnsuspend(u2);
|
|
952
|
+
if (asyncSavedIdTree !== void 0) popTreeContext(asyncSavedIdTree);
|
|
953
|
+
popComponentScope(savedScope);
|
|
954
|
+
if (isProvider) popContextValue(ctx, prevCtxValue);
|
|
817
955
|
},
|
|
818
956
|
(e) => {
|
|
819
957
|
swapContextMap(m2);
|
|
820
|
-
|
|
958
|
+
restoreUnsuspend(u2);
|
|
959
|
+
if (asyncSavedIdTree !== void 0) popTreeContext(asyncSavedIdTree);
|
|
960
|
+
popComponentScope(savedScope);
|
|
961
|
+
if (isProvider) popContextValue(ctx, prevCtxValue);
|
|
821
962
|
throw e;
|
|
822
963
|
}
|
|
823
964
|
);
|
|
824
965
|
}
|
|
825
|
-
|
|
966
|
+
if (asyncSavedIdTree !== void 0) popTreeContext(asyncSavedIdTree);
|
|
967
|
+
popComponentScope(savedScope);
|
|
968
|
+
if (isProvider) popContextValue(ctx, prevCtxValue);
|
|
826
969
|
}, (e) => {
|
|
827
970
|
swapContextMap(m);
|
|
828
|
-
|
|
971
|
+
restoreUnsuspend(u);
|
|
972
|
+
popComponentScope(savedScope);
|
|
973
|
+
if (isProvider) popContextValue(ctx, prevCtxValue);
|
|
829
974
|
throw e;
|
|
830
975
|
});
|
|
831
976
|
}
|
|
832
977
|
const r = renderNode(result, writer, isSvg);
|
|
833
978
|
if (r && typeof r.then === "function") {
|
|
834
979
|
const m = captureMap();
|
|
980
|
+
const u = captureUnsuspend();
|
|
835
981
|
return r.then(
|
|
836
982
|
() => {
|
|
837
983
|
swapContextMap(m);
|
|
838
|
-
|
|
984
|
+
restoreUnsuspend(u);
|
|
985
|
+
if (savedIdTree !== void 0) popTreeContext(savedIdTree);
|
|
986
|
+
popComponentScope(savedScope);
|
|
987
|
+
if (isProvider) popContextValue(ctx, prevCtxValue);
|
|
839
988
|
},
|
|
840
989
|
(e) => {
|
|
841
990
|
swapContextMap(m);
|
|
842
|
-
|
|
991
|
+
restoreUnsuspend(u);
|
|
992
|
+
if (savedIdTree !== void 0) popTreeContext(savedIdTree);
|
|
993
|
+
popComponentScope(savedScope);
|
|
994
|
+
if (isProvider) popContextValue(ctx, prevCtxValue);
|
|
843
995
|
throw e;
|
|
844
996
|
}
|
|
845
997
|
);
|
|
846
998
|
}
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
return typeof node === "string" || typeof node === "number";
|
|
999
|
+
if (savedIdTree !== void 0) popTreeContext(savedIdTree);
|
|
1000
|
+
popComponentScope(savedScope);
|
|
1001
|
+
if (isProvider) popContextValue(ctx, prevCtxValue);
|
|
851
1002
|
}
|
|
852
1003
|
function renderChildArray(children, writer, isSvg) {
|
|
853
|
-
|
|
854
|
-
for (let i = 0; i < totalChildren; i++) {
|
|
855
|
-
if (isTextLike(children[i]) && writer.lastWasText) {
|
|
856
|
-
writer.write("<!-- -->");
|
|
857
|
-
}
|
|
858
|
-
const savedTree = pushTreeContext(totalChildren, i);
|
|
859
|
-
const r = renderNode(children[i], writer, isSvg);
|
|
860
|
-
if (r && typeof r.then === "function") {
|
|
861
|
-
const m = captureMap();
|
|
862
|
-
return r.then(() => {
|
|
863
|
-
swapContextMap(m);
|
|
864
|
-
popTreeContext(savedTree);
|
|
865
|
-
return renderChildArrayFrom(children, i + 1, writer, isSvg);
|
|
866
|
-
});
|
|
867
|
-
}
|
|
868
|
-
popTreeContext(savedTree);
|
|
869
|
-
}
|
|
1004
|
+
return renderChildArrayFrom(children, 0, writer, isSvg);
|
|
870
1005
|
}
|
|
871
1006
|
function renderChildArrayFrom(children, startIndex, writer, isSvg) {
|
|
872
1007
|
const totalChildren = children.length;
|
|
873
1008
|
for (let i = startIndex; i < totalChildren; i++) {
|
|
874
|
-
|
|
1009
|
+
const child = children[i];
|
|
1010
|
+
if ((typeof child === "string" || typeof child === "number") && writer.lastWasText) {
|
|
875
1011
|
writer.write("<!-- -->");
|
|
876
1012
|
}
|
|
877
1013
|
const savedTree = pushTreeContext(totalChildren, i);
|
|
878
|
-
const r = renderNode(
|
|
1014
|
+
const r = renderNode(child, writer, isSvg);
|
|
879
1015
|
if (r && typeof r.then === "function") {
|
|
880
1016
|
const m = captureMap();
|
|
1017
|
+
const u = captureUnsuspend();
|
|
881
1018
|
return r.then(() => {
|
|
882
1019
|
swapContextMap(m);
|
|
1020
|
+
restoreUnsuspend(u);
|
|
883
1021
|
popTreeContext(savedTree);
|
|
884
1022
|
return renderChildArrayFrom(children, i + 1, writer, isSvg);
|
|
885
1023
|
});
|
|
@@ -894,87 +1032,94 @@ function renderChildren(children, writer, isSvg = false) {
|
|
|
894
1032
|
}
|
|
895
1033
|
return renderNode(children, writer, isSvg);
|
|
896
1034
|
}
|
|
897
|
-
var MAX_SUSPENSE_RETRIES = 25;
|
|
898
1035
|
async function renderSuspense(props, writer, isSvg = false) {
|
|
899
1036
|
const { children, fallback } = props;
|
|
900
|
-
let attempts = 0;
|
|
901
1037
|
const snap = snapshotContext();
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
1038
|
+
const savedMap = captureMap();
|
|
1039
|
+
const savedMapClone = savedMap ? new Map(savedMap) : null;
|
|
1040
|
+
const buffer = new BufferWriter();
|
|
1041
|
+
try {
|
|
1042
|
+
const r = renderNode(children, buffer, isSvg);
|
|
1043
|
+
if (r && typeof r.then === "function") {
|
|
1044
|
+
const m = captureMap();
|
|
1045
|
+
const u = captureUnsuspend();
|
|
1046
|
+
await r;
|
|
1047
|
+
swapContextMap(m);
|
|
1048
|
+
restoreUnsuspend(u);
|
|
1049
|
+
}
|
|
1050
|
+
writer.write("<!--$-->");
|
|
1051
|
+
buffer.flushTo(writer);
|
|
1052
|
+
writer.write("<!--/$-->");
|
|
1053
|
+
writer.flush?.();
|
|
1054
|
+
} catch (error) {
|
|
1055
|
+
if (error === SUSPENSE_RETRY_LIMIT) {
|
|
1056
|
+
restoreContext(snap);
|
|
1057
|
+
swapContextMap(savedMapClone);
|
|
1058
|
+
writer.write("<!--$?-->");
|
|
1059
|
+
if (fallback) {
|
|
1060
|
+
const r = renderNode(fallback, writer, isSvg);
|
|
1061
|
+
if (r && typeof r.then === "function") {
|
|
1062
|
+
const m = captureMap();
|
|
1063
|
+
const u = captureUnsuspend();
|
|
1064
|
+
await r;
|
|
1065
|
+
swapContextMap(m);
|
|
1066
|
+
restoreUnsuspend(u);
|
|
1067
|
+
}
|
|
911
1068
|
}
|
|
912
|
-
writer.write("<!--$-->");
|
|
913
|
-
buffer.flush(writer);
|
|
914
1069
|
writer.write("<!--/$-->");
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
if (error && typeof error.then === "function") {
|
|
918
|
-
const m = captureMap();
|
|
919
|
-
await error;
|
|
920
|
-
swapContextMap(m);
|
|
921
|
-
attempts++;
|
|
922
|
-
} else {
|
|
923
|
-
throw error;
|
|
924
|
-
}
|
|
1070
|
+
} else {
|
|
1071
|
+
throw error;
|
|
925
1072
|
}
|
|
926
1073
|
}
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
1074
|
+
}
|
|
1075
|
+
var _streamEncoder = new TextEncoder();
|
|
1076
|
+
var NULL_WRITER = {
|
|
1077
|
+
lastWasText: false,
|
|
1078
|
+
write(_c) {
|
|
1079
|
+
},
|
|
1080
|
+
text(_s) {
|
|
1081
|
+
}
|
|
1082
|
+
};
|
|
1083
|
+
async function renderPreflight(element, options) {
|
|
1084
|
+
const idPrefix = options?.identifierPrefix ?? "";
|
|
1085
|
+
const prev = swapContextMap(null);
|
|
1086
|
+
try {
|
|
1087
|
+
resetRenderState(idPrefix);
|
|
1088
|
+
NULL_WRITER.lastWasText = false;
|
|
1089
|
+
const r = renderNode(element, NULL_WRITER);
|
|
931
1090
|
if (r && typeof r.then === "function") {
|
|
932
1091
|
const m = captureMap();
|
|
933
1092
|
await r;
|
|
934
1093
|
swapContextMap(m);
|
|
935
1094
|
}
|
|
1095
|
+
} finally {
|
|
1096
|
+
swapContextMap(prev);
|
|
936
1097
|
}
|
|
937
|
-
writer.write("<!--/$-->");
|
|
938
1098
|
}
|
|
939
1099
|
async function renderToString(element, options) {
|
|
940
1100
|
const idPrefix = options?.identifierPrefix ?? "";
|
|
941
|
-
const
|
|
942
|
-
|
|
1101
|
+
const prev = swapContextMap(null);
|
|
1102
|
+
let output = "";
|
|
1103
|
+
const writer = {
|
|
1104
|
+
lastWasText: false,
|
|
1105
|
+
write(c) {
|
|
1106
|
+
output += c;
|
|
1107
|
+
this.lastWasText = false;
|
|
1108
|
+
},
|
|
1109
|
+
text(s2) {
|
|
1110
|
+
output += s2;
|
|
1111
|
+
this.lastWasText = true;
|
|
1112
|
+
}
|
|
1113
|
+
};
|
|
943
1114
|
try {
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
const
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
write(c) {
|
|
951
|
-
chunks.push(c);
|
|
952
|
-
this.lastWasText = false;
|
|
953
|
-
},
|
|
954
|
-
text(s2) {
|
|
955
|
-
chunks.push(s2);
|
|
956
|
-
this.lastWasText = true;
|
|
957
|
-
}
|
|
958
|
-
};
|
|
959
|
-
try {
|
|
960
|
-
const r = renderNode(element, writer);
|
|
961
|
-
if (r && typeof r.then === "function") {
|
|
962
|
-
const m = captureMap();
|
|
963
|
-
await r;
|
|
964
|
-
swapContextMap(m);
|
|
965
|
-
}
|
|
966
|
-
return chunks.join("");
|
|
967
|
-
} catch (error) {
|
|
968
|
-
if (error && typeof error.then === "function") {
|
|
969
|
-
const m = captureMap();
|
|
970
|
-
await error;
|
|
971
|
-
swapContextMap(m);
|
|
972
|
-
continue;
|
|
973
|
-
}
|
|
974
|
-
throw error;
|
|
975
|
-
}
|
|
1115
|
+
resetRenderState(idPrefix);
|
|
1116
|
+
const r = renderNode(element, writer);
|
|
1117
|
+
if (r && typeof r.then === "function") {
|
|
1118
|
+
const m = captureMap();
|
|
1119
|
+
await r;
|
|
1120
|
+
swapContextMap(m);
|
|
976
1121
|
}
|
|
977
|
-
|
|
1122
|
+
return output;
|
|
978
1123
|
} finally {
|
|
979
1124
|
swapContextMap(prev);
|
|
980
1125
|
}
|
|
@@ -995,8 +1140,8 @@ var ATTR = {
|
|
|
995
1140
|
fetchPriority: "fetchpriority",
|
|
996
1141
|
hrefLang: "hreflang"
|
|
997
1142
|
};
|
|
998
|
-
function renderHeadTag(tag, opts, selfClose = false) {
|
|
999
|
-
let attrs = ""
|
|
1143
|
+
function renderHeadTag(tag, id, opts, selfClose = false) {
|
|
1144
|
+
let attrs = ` id="${escAttr(id)}"`;
|
|
1000
1145
|
let inner = "";
|
|
1001
1146
|
for (const [k, v] of Object.entries(opts)) {
|
|
1002
1147
|
if (k === "key" || k === "children") continue;
|
|
@@ -1010,18 +1155,18 @@ function renderHeadTag(tag, opts, selfClose = false) {
|
|
|
1010
1155
|
}
|
|
1011
1156
|
return selfClose ? `<${tag}${attrs}>` : `<${tag}${attrs}>${inner}</${tag}>`;
|
|
1012
1157
|
}
|
|
1013
|
-
|
|
1158
|
+
function buildHeadHtml(seoData) {
|
|
1014
1159
|
let html = `<title>${escText(seoData.title ?? "")}</title>`;
|
|
1015
|
-
for (const opts of Object.
|
|
1016
|
-
html += renderHeadTag("meta", opts, true);
|
|
1017
|
-
for (const opts of Object.
|
|
1018
|
-
html += renderHeadTag("link", opts, true);
|
|
1019
|
-
for (const opts of Object.
|
|
1020
|
-
html += renderHeadTag("style", opts);
|
|
1021
|
-
for (const opts of Object.
|
|
1022
|
-
html += renderHeadTag("script", opts);
|
|
1160
|
+
for (const [id, opts] of Object.entries(seoData.meta))
|
|
1161
|
+
html += renderHeadTag("meta", id, opts, true);
|
|
1162
|
+
for (const [id, opts] of Object.entries(seoData.link))
|
|
1163
|
+
html += renderHeadTag("link", id, opts, true);
|
|
1164
|
+
for (const [id, opts] of Object.entries(seoData.style))
|
|
1165
|
+
html += renderHeadTag("style", id, opts);
|
|
1166
|
+
for (const [id, opts] of Object.entries(seoData.script))
|
|
1167
|
+
html += renderHeadTag("script", id, opts);
|
|
1023
1168
|
return html;
|
|
1024
|
-
}
|
|
1169
|
+
}
|
|
1025
1170
|
var getReactResponse = async (req, opts) => {
|
|
1026
1171
|
const App = opts.document.body;
|
|
1027
1172
|
const { getInitProps, getFinalProps } = opts.document;
|
|
@@ -1035,28 +1180,44 @@ var getReactResponse = async (req, opts) => {
|
|
|
1035
1180
|
};
|
|
1036
1181
|
const unsuspend = { cache: /* @__PURE__ */ new Map() };
|
|
1037
1182
|
globalThis.__hadarsUnsuspend = unsuspend;
|
|
1038
|
-
|
|
1183
|
+
globalThis.__hadarsContext = context;
|
|
1184
|
+
const element = createElement(App, props);
|
|
1039
1185
|
try {
|
|
1040
|
-
|
|
1186
|
+
await renderPreflight(element);
|
|
1041
1187
|
} finally {
|
|
1042
1188
|
globalThis.__hadarsUnsuspend = null;
|
|
1189
|
+
globalThis.__hadarsContext = null;
|
|
1043
1190
|
}
|
|
1044
|
-
const
|
|
1045
|
-
const
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
1191
|
+
const status = context.head.status;
|
|
1192
|
+
const getAppBody = async () => {
|
|
1193
|
+
globalThis.__hadarsUnsuspend = unsuspend;
|
|
1194
|
+
globalThis.__hadarsContext = context;
|
|
1195
|
+
try {
|
|
1196
|
+
return await renderToString(element);
|
|
1197
|
+
} finally {
|
|
1198
|
+
globalThis.__hadarsUnsuspend = null;
|
|
1199
|
+
globalThis.__hadarsContext = null;
|
|
1200
|
+
}
|
|
1053
1201
|
};
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1202
|
+
const finalize = async () => {
|
|
1203
|
+
const { context: _, ...restProps } = getFinalProps ? await getFinalProps(props) : props;
|
|
1204
|
+
const serverData = {};
|
|
1205
|
+
let hasServerData = false;
|
|
1206
|
+
for (const [key, entry] of unsuspend.cache) {
|
|
1207
|
+
if (entry.status === "fulfilled") {
|
|
1208
|
+
serverData[key] = entry.value;
|
|
1209
|
+
hasServerData = true;
|
|
1210
|
+
}
|
|
1211
|
+
}
|
|
1212
|
+
return {
|
|
1213
|
+
clientProps: {
|
|
1214
|
+
...restProps,
|
|
1215
|
+
location: req.location,
|
|
1216
|
+
...hasServerData ? { __serverData: serverData } : {}
|
|
1217
|
+
}
|
|
1218
|
+
};
|
|
1059
1219
|
};
|
|
1220
|
+
return { head: context.head, status, getAppBody, finalize };
|
|
1060
1221
|
};
|
|
1061
1222
|
|
|
1062
1223
|
// src/utils/rspack.ts
|
|
@@ -1454,27 +1615,6 @@ function nodeReadableToWebStream(readable) {
|
|
|
1454
1615
|
});
|
|
1455
1616
|
}
|
|
1456
1617
|
var noopCtx = { upgrade: () => false };
|
|
1457
|
-
var COMPRESSIBLE_RE = /\b(?:text\/|application\/(?:json|javascript|xml)|image\/svg\+xml)/;
|
|
1458
|
-
function withCompression(handler) {
|
|
1459
|
-
return async (req, ctx) => {
|
|
1460
|
-
const res = await handler(req, ctx);
|
|
1461
|
-
if (!res?.body) return res;
|
|
1462
|
-
if (!COMPRESSIBLE_RE.test(res.headers.get("Content-Type") ?? "")) return res;
|
|
1463
|
-
if (res.headers.has("Content-Encoding")) return res;
|
|
1464
|
-
const accept = req.headers.get("Accept-Encoding") ?? "";
|
|
1465
|
-
const encoding = accept.includes("br") ? "br" : accept.includes("gzip") ? "gzip" : null;
|
|
1466
|
-
if (!encoding) return res;
|
|
1467
|
-
try {
|
|
1468
|
-
const compressed = res.body.pipeThrough(new globalThis.CompressionStream(encoding));
|
|
1469
|
-
const headers = new Headers(res.headers);
|
|
1470
|
-
headers.set("Content-Encoding", encoding);
|
|
1471
|
-
headers.delete("Content-Length");
|
|
1472
|
-
return new Response(compressed, { status: res.status, statusText: res.statusText, headers });
|
|
1473
|
-
} catch {
|
|
1474
|
-
return res;
|
|
1475
|
-
}
|
|
1476
|
-
};
|
|
1477
|
-
}
|
|
1478
1618
|
function withRequestLogging(handler) {
|
|
1479
1619
|
return async (req, ctx) => {
|
|
1480
1620
|
const start = performance.now();
|
|
@@ -1486,9 +1626,27 @@ function withRequestLogging(handler) {
|
|
|
1486
1626
|
return res;
|
|
1487
1627
|
};
|
|
1488
1628
|
}
|
|
1629
|
+
var COMPRESSIBLE_RE = /^text\/|\/json|\/javascript|\/xml|\/wasm/;
|
|
1630
|
+
function withCompression(handler) {
|
|
1631
|
+
return async (req, ctx) => {
|
|
1632
|
+
const res = await handler(req, ctx);
|
|
1633
|
+
if (!res || !res.body) return res;
|
|
1634
|
+
const accept = req.headers.get("Accept-Encoding") ?? "";
|
|
1635
|
+
if (!accept.includes("gzip")) return res;
|
|
1636
|
+
if (res.headers.has("content-encoding")) return res;
|
|
1637
|
+
const ct = res.headers.get("content-type") ?? "";
|
|
1638
|
+
if (!COMPRESSIBLE_RE.test(ct)) return res;
|
|
1639
|
+
const compressed = res.body.pipeThrough(
|
|
1640
|
+
new globalThis.CompressionStream("gzip")
|
|
1641
|
+
);
|
|
1642
|
+
const headers = new Headers(res.headers);
|
|
1643
|
+
headers.set("content-encoding", "gzip");
|
|
1644
|
+
headers.delete("content-length");
|
|
1645
|
+
return new Response(compressed, { status: res.status, headers });
|
|
1646
|
+
};
|
|
1647
|
+
}
|
|
1489
1648
|
async function serve(port, fetchHandler, websocket) {
|
|
1490
|
-
fetchHandler = withCompression(fetchHandler);
|
|
1491
|
-
fetchHandler = withRequestLogging(fetchHandler);
|
|
1649
|
+
fetchHandler = withCompression(withRequestLogging(fetchHandler));
|
|
1492
1650
|
if (isBun) {
|
|
1493
1651
|
globalThis.Bun.serve({
|
|
1494
1652
|
port,
|
|
@@ -1561,7 +1719,7 @@ async function serve(port, fetchHandler, websocket) {
|
|
|
1561
1719
|
}
|
|
1562
1720
|
|
|
1563
1721
|
// src/utils/staticFile.ts
|
|
1564
|
-
import { readFile
|
|
1722
|
+
import { readFile } from "node:fs/promises";
|
|
1565
1723
|
var MIME = {
|
|
1566
1724
|
html: "text/html; charset=utf-8",
|
|
1567
1725
|
htm: "text/html; charset=utf-8",
|
|
@@ -1587,16 +1745,11 @@ var MIME = {
|
|
|
1587
1745
|
pdf: "application/pdf"
|
|
1588
1746
|
};
|
|
1589
1747
|
async function tryServeFile(filePath) {
|
|
1590
|
-
try {
|
|
1591
|
-
await stat(filePath);
|
|
1592
|
-
} catch {
|
|
1593
|
-
return null;
|
|
1594
|
-
}
|
|
1595
1748
|
try {
|
|
1596
1749
|
const data = await readFile(filePath);
|
|
1597
1750
|
const ext = filePath.split(".").pop()?.toLowerCase() ?? "";
|
|
1598
1751
|
const contentType = MIME[ext] ?? "application/octet-stream";
|
|
1599
|
-
return new Response(data
|
|
1752
|
+
return new Response(data, { headers: { "Content-Type": contentType } });
|
|
1600
1753
|
} catch {
|
|
1601
1754
|
return null;
|
|
1602
1755
|
}
|
|
@@ -1617,16 +1770,25 @@ import cluster from "node:cluster";
|
|
|
1617
1770
|
var HEAD_MARKER = '<meta name="HADARS_HEAD">';
|
|
1618
1771
|
var BODY_MARKER = '<meta name="HADARS_BODY">';
|
|
1619
1772
|
var encoder = new TextEncoder();
|
|
1620
|
-
|
|
1773
|
+
function buildSsrResponse(head, status, getAppBody, finalize, getPrecontentHtml) {
|
|
1774
|
+
const headHtml = buildHeadHtml(head);
|
|
1775
|
+
const precontentResult = getPrecontentHtml(headHtml);
|
|
1621
1776
|
const responseStream = new ReadableStream({
|
|
1622
1777
|
async start(controller) {
|
|
1623
|
-
|
|
1624
|
-
|
|
1625
|
-
|
|
1626
|
-
|
|
1627
|
-
`<div id="app">${bodyHtml}</div
|
|
1628
|
-
|
|
1629
|
-
|
|
1778
|
+
try {
|
|
1779
|
+
const [precontentHtml, postContent] = precontentResult instanceof Promise ? await precontentResult : precontentResult;
|
|
1780
|
+
controller.enqueue(encoder.encode(precontentHtml));
|
|
1781
|
+
const bodyHtml = await getAppBody();
|
|
1782
|
+
controller.enqueue(encoder.encode(`<div id="app">${bodyHtml}</div>`));
|
|
1783
|
+
const { clientProps } = await finalize();
|
|
1784
|
+
const scriptContent = JSON.stringify({ hadars: { props: clientProps } }).replace(/</g, "\\u003c");
|
|
1785
|
+
controller.enqueue(encoder.encode(
|
|
1786
|
+
`<script id="hadars" type="application/json">${scriptContent}</script>` + postContent
|
|
1787
|
+
));
|
|
1788
|
+
controller.close();
|
|
1789
|
+
} catch (err) {
|
|
1790
|
+
controller.error(err);
|
|
1791
|
+
}
|
|
1630
1792
|
}
|
|
1631
1793
|
});
|
|
1632
1794
|
return new Response(responseStream, {
|
|
@@ -1638,16 +1800,18 @@ var makePrecontentHtmlGetter = (htmlFilePromise) => {
|
|
|
1638
1800
|
let preHead = null;
|
|
1639
1801
|
let postHead = null;
|
|
1640
1802
|
let postContent = null;
|
|
1641
|
-
return
|
|
1642
|
-
if (preHead
|
|
1643
|
-
|
|
1803
|
+
return (headHtml) => {
|
|
1804
|
+
if (preHead !== null) {
|
|
1805
|
+
return [preHead + headHtml + postHead, postContent];
|
|
1806
|
+
}
|
|
1807
|
+
return htmlFilePromise.then((html) => {
|
|
1644
1808
|
const headEnd = html.indexOf(HEAD_MARKER);
|
|
1645
1809
|
const contentStart = html.indexOf(BODY_MARKER);
|
|
1646
1810
|
preHead = html.slice(0, headEnd);
|
|
1647
1811
|
postHead = html.slice(headEnd + HEAD_MARKER.length, contentStart);
|
|
1648
1812
|
postContent = html.slice(contentStart + BODY_MARKER.length);
|
|
1649
|
-
|
|
1650
|
-
|
|
1813
|
+
return [preHead + headHtml + postHead, postContent];
|
|
1814
|
+
});
|
|
1651
1815
|
};
|
|
1652
1816
|
};
|
|
1653
1817
|
async function transformStream(data, stream) {
|
|
@@ -2117,7 +2281,7 @@ var dev = async (options) => {
|
|
|
2117
2281
|
getInitProps,
|
|
2118
2282
|
getFinalProps
|
|
2119
2283
|
} = await import(importPath);
|
|
2120
|
-
const {
|
|
2284
|
+
const { head, status, getAppBody, finalize } = await getReactResponse(request, {
|
|
2121
2285
|
document: {
|
|
2122
2286
|
body: Component,
|
|
2123
2287
|
lang: "en",
|
|
@@ -2126,13 +2290,14 @@ var dev = async (options) => {
|
|
|
2126
2290
|
}
|
|
2127
2291
|
});
|
|
2128
2292
|
if (request.headers.get("Accept") === "application/json") {
|
|
2293
|
+
const { clientProps } = await finalize();
|
|
2129
2294
|
const serverData = clientProps.__serverData ?? {};
|
|
2130
2295
|
return new Response(JSON.stringify({ serverData }), {
|
|
2131
2296
|
status,
|
|
2132
2297
|
headers: { "Content-Type": "application/json; charset=utf-8" }
|
|
2133
2298
|
});
|
|
2134
2299
|
}
|
|
2135
|
-
return buildSsrResponse(
|
|
2300
|
+
return buildSsrResponse(head, status, getAppBody, finalize, getPrecontentHtml);
|
|
2136
2301
|
} catch (err) {
|
|
2137
2302
|
console.error("[hadars] SSR render error:", err);
|
|
2138
2303
|
const msg = (err?.stack ?? err?.message ?? String(err)).replace(/</g, "<");
|
|
@@ -2274,7 +2439,7 @@ var run = async (options) => {
|
|
|
2274
2439
|
status: wStatus
|
|
2275
2440
|
});
|
|
2276
2441
|
}
|
|
2277
|
-
const {
|
|
2442
|
+
const { head, status, getAppBody, finalize } = await getReactResponse(request, {
|
|
2278
2443
|
document: {
|
|
2279
2444
|
body: Component,
|
|
2280
2445
|
lang: "en",
|
|
@@ -2283,13 +2448,14 @@ var run = async (options) => {
|
|
|
2283
2448
|
}
|
|
2284
2449
|
});
|
|
2285
2450
|
if (request.headers.get("Accept") === "application/json") {
|
|
2451
|
+
const { clientProps } = await finalize();
|
|
2286
2452
|
const serverData = clientProps.__serverData ?? {};
|
|
2287
2453
|
return new Response(JSON.stringify({ serverData }), {
|
|
2288
2454
|
status,
|
|
2289
2455
|
headers: { "Content-Type": "application/json; charset=utf-8" }
|
|
2290
2456
|
});
|
|
2291
2457
|
}
|
|
2292
|
-
return buildSsrResponse(
|
|
2458
|
+
return buildSsrResponse(head, status, getAppBody, finalize, getPrecontentHtml);
|
|
2293
2459
|
} catch (err) {
|
|
2294
2460
|
console.error("[hadars] SSR render error:", err);
|
|
2295
2461
|
return new Response("Internal Server Error", { status: 500 });
|
|
@@ -2335,6 +2501,67 @@ async function loadConfig(configPath) {
|
|
|
2335
2501
|
const mod = await import(url);
|
|
2336
2502
|
return mod && (mod.default ?? mod);
|
|
2337
2503
|
}
|
|
2504
|
+
async function bundleCloudflare(config, configPath, outputFile, cwd) {
|
|
2505
|
+
console.log("Building hadars project...");
|
|
2506
|
+
await build({ ...config, mode: "production" });
|
|
2507
|
+
const ssrBundle = resolve(cwd, ".hadars", "index.ssr.js");
|
|
2508
|
+
const outHtml = resolve(cwd, ".hadars", "static", "out.html");
|
|
2509
|
+
if (!existsSync3(ssrBundle)) {
|
|
2510
|
+
console.error(`SSR bundle not found: ${ssrBundle}`);
|
|
2511
|
+
process.exit(1);
|
|
2512
|
+
}
|
|
2513
|
+
if (!existsSync3(outHtml)) {
|
|
2514
|
+
console.error(`HTML template not found: ${outHtml}`);
|
|
2515
|
+
process.exit(1);
|
|
2516
|
+
}
|
|
2517
|
+
const cloudflareModule = resolve(dirname(fileURLToPath3(import.meta.url)), "cloudflare.js");
|
|
2518
|
+
const shimPath = join(cwd, `.hadars-cloudflare-shim-${Date.now()}.ts`);
|
|
2519
|
+
const shim = [
|
|
2520
|
+
`import * as ssrModule from ${JSON.stringify(ssrBundle)};`,
|
|
2521
|
+
`import outHtml from ${JSON.stringify(outHtml)};`,
|
|
2522
|
+
`import { createCloudflareHandler } from ${JSON.stringify(cloudflareModule)};`,
|
|
2523
|
+
`import config from ${JSON.stringify(configPath)};`,
|
|
2524
|
+
`export default createCloudflareHandler(config as any, { ssrModule: ssrModule as any, outHtml });`
|
|
2525
|
+
].join("\n") + "\n";
|
|
2526
|
+
await writeFile(shimPath, shim, "utf-8");
|
|
2527
|
+
try {
|
|
2528
|
+
const { build: esbuild } = await import("esbuild");
|
|
2529
|
+
console.log(`Bundling Cloudflare Worker \u2192 ${outputFile}`);
|
|
2530
|
+
await esbuild({
|
|
2531
|
+
entryPoints: [shimPath],
|
|
2532
|
+
bundle: true,
|
|
2533
|
+
// 'browser' avoids Node.js built-in shims; CF Workers uses Web APIs.
|
|
2534
|
+
// If you use node:* APIs in your app code, add nodejs_compat to wrangler.toml.
|
|
2535
|
+
platform: "browser",
|
|
2536
|
+
format: "esm",
|
|
2537
|
+
target: ["es2022"],
|
|
2538
|
+
outfile: outputFile,
|
|
2539
|
+
sourcemap: false,
|
|
2540
|
+
loader: { ".html": "text", ".tsx": "tsx", ".ts": "ts" },
|
|
2541
|
+
// @rspack/* is build-time only — never imported at Worker runtime.
|
|
2542
|
+
external: ["@rspack/*"],
|
|
2543
|
+
// Cloudflare Workers supports the Web Crypto API natively; suppress
|
|
2544
|
+
// esbuild's attempt to polyfill node:crypto.
|
|
2545
|
+
define: { "global": "globalThis" }
|
|
2546
|
+
});
|
|
2547
|
+
console.log(`Cloudflare Worker bundle written to ${outputFile}`);
|
|
2548
|
+
console.log(`
|
|
2549
|
+
Deploy instructions:`);
|
|
2550
|
+
console.log(` 1. Ensure wrangler.toml points to the output file:`);
|
|
2551
|
+
console.log(` name = "my-app"`);
|
|
2552
|
+
console.log(` main = "${outputFile}"`);
|
|
2553
|
+
console.log(` compatibility_date = "2024-09-23"`);
|
|
2554
|
+
console.log(` compatibility_flags = ["nodejs_compat"]`);
|
|
2555
|
+
console.log(` 2. Upload .hadars/static/ assets to R2 (or another CDN):`);
|
|
2556
|
+
console.log(` wrangler r2 object put my-bucket/assets/ --file .hadars/static/ --recursive`);
|
|
2557
|
+
console.log(` 3. Add a route rule in wrangler.toml to send *.js / *.css to R2`);
|
|
2558
|
+
console.log(` and all other requests to the Worker.`);
|
|
2559
|
+
console.log(` 4. Deploy: wrangler deploy`);
|
|
2560
|
+
} finally {
|
|
2561
|
+
await unlink(shimPath).catch(() => {
|
|
2562
|
+
});
|
|
2563
|
+
}
|
|
2564
|
+
}
|
|
2338
2565
|
async function bundleLambda(config, configPath, outputFile, cwd) {
|
|
2339
2566
|
console.log("Building hadars project...");
|
|
2340
2567
|
await build({ ...config, mode: "production" });
|
|
@@ -2436,7 +2663,7 @@ export default config;
|
|
|
2436
2663
|
dist/
|
|
2437
2664
|
`,
|
|
2438
2665
|
"src/App.tsx": () => `import React from 'react';
|
|
2439
|
-
import {
|
|
2666
|
+
import { HadarsHead, type HadarsApp } from 'hadars';
|
|
2440
2667
|
|
|
2441
2668
|
const css = \`
|
|
2442
2669
|
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
|
|
@@ -2548,15 +2775,15 @@ const css = \`
|
|
|
2548
2775
|
|
|
2549
2776
|
\`;
|
|
2550
2777
|
|
|
2551
|
-
const App: HadarsApp<{}> = (
|
|
2778
|
+
const App: HadarsApp<{}> = () => {
|
|
2552
2779
|
const [count, setCount] = React.useState(0);
|
|
2553
2780
|
|
|
2554
2781
|
return (
|
|
2555
|
-
|
|
2782
|
+
<>
|
|
2556
2783
|
<HadarsHead status={200}>
|
|
2557
2784
|
<title>My App</title>
|
|
2558
|
-
<meta
|
|
2559
|
-
<style id="app-styles" dangerouslySetInnerHTML={{ __html: css }} />
|
|
2785
|
+
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
2786
|
+
<style data-id="app-styles" dangerouslySetInnerHTML={{ __html: css }} />
|
|
2560
2787
|
</HadarsHead>
|
|
2561
2788
|
|
|
2562
2789
|
<nav className="nav">
|
|
@@ -2614,7 +2841,7 @@ const App: HadarsApp<{}> = ({ context }) => {
|
|
|
2614
2841
|
</div>
|
|
2615
2842
|
</div>
|
|
2616
2843
|
|
|
2617
|
-
|
|
2844
|
+
</>
|
|
2618
2845
|
);
|
|
2619
2846
|
};
|
|
2620
2847
|
|
|
@@ -2643,7 +2870,7 @@ Done! Next steps:
|
|
|
2643
2870
|
`);
|
|
2644
2871
|
}
|
|
2645
2872
|
function usage() {
|
|
2646
|
-
console.log("Usage: hadars <new <name> | dev | build | run | export lambda [output.mjs]>");
|
|
2873
|
+
console.log("Usage: hadars <new <name> | dev | build | run | export lambda [output.mjs] | export cloudflare [output.mjs]>");
|
|
2647
2874
|
}
|
|
2648
2875
|
async function runCli(argv, cwd = process.cwd()) {
|
|
2649
2876
|
const cmd = argv[2];
|
|
@@ -2686,13 +2913,18 @@ async function runCli(argv, cwd = process.cwd()) {
|
|
|
2686
2913
|
process.exit(0);
|
|
2687
2914
|
case "export": {
|
|
2688
2915
|
const subCmd = argv[3];
|
|
2689
|
-
if (subCmd
|
|
2690
|
-
|
|
2916
|
+
if (subCmd === "lambda") {
|
|
2917
|
+
const outputFile = resolve(cwd, argv[4] ?? "lambda.mjs");
|
|
2918
|
+
await bundleLambda(cfg, configPath, outputFile, cwd);
|
|
2919
|
+
process.exit(0);
|
|
2920
|
+
} else if (subCmd === "cloudflare") {
|
|
2921
|
+
const outputFile = resolve(cwd, argv[4] ?? "cloudflare.mjs");
|
|
2922
|
+
await bundleCloudflare(cfg, configPath, outputFile, cwd);
|
|
2923
|
+
process.exit(0);
|
|
2924
|
+
} else {
|
|
2925
|
+
console.error(`Unknown export target: ${subCmd ?? "(none)"}. Supported: lambda, cloudflare`);
|
|
2691
2926
|
process.exit(1);
|
|
2692
2927
|
}
|
|
2693
|
-
const outputFile = resolve(cwd, argv[4] ?? "lambda.mjs");
|
|
2694
|
-
await bundleLambda(cfg, configPath, outputFile, cwd);
|
|
2695
|
-
process.exit(0);
|
|
2696
2928
|
}
|
|
2697
2929
|
case "run":
|
|
2698
2930
|
console.log("Running project...");
|