hadars 0.1.35 → 0.1.37
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 +77 -0
- package/cli-lib.ts +90 -5
- package/dist/chunk-F7IIMM3J.js +1060 -0
- package/dist/chunk-UNQSQIOO.js +60 -0
- package/dist/cli.js +285 -261
- package/dist/hadars-B3b_6sj2.d.cts +188 -0
- package/dist/hadars-B3b_6sj2.d.ts +188 -0
- package/dist/index.cjs +11 -19
- package/dist/index.d.cts +105 -0
- package/dist/index.d.ts +4 -175
- package/dist/index.js +14 -42
- package/dist/{jsx-runtime-97ca74a5.d.ts → jsx-runtime-BOYrELJb.d.cts} +1 -1
- package/dist/jsx-runtime-BOYrELJb.d.ts +18 -0
- package/dist/lambda.cjs +1405 -0
- package/dist/lambda.d.cts +93 -0
- package/dist/lambda.d.ts +93 -0
- package/dist/lambda.js +499 -0
- package/dist/loader.cjs +22 -44
- package/dist/slim-react/index.cjs +29 -58
- package/dist/slim-react/index.d.cts +190 -0
- package/dist/slim-react/index.d.ts +3 -3
- package/dist/slim-react/index.js +34 -1043
- package/dist/slim-react/jsx-runtime.d.cts +1 -0
- package/dist/slim-react/jsx-runtime.d.ts +1 -1
- package/dist/ssr-render-worker.js +44 -78
- package/dist/ssr-watch.js +24 -7
- package/dist/utils/Head.tsx +2 -2
- package/package.json +11 -6
- package/src/build.ts +8 -166
- package/src/lambda.ts +287 -0
- package/src/types/hadars.ts +10 -0
- package/src/utils/Head.tsx +2 -2
- package/src/utils/rspack.ts +27 -0
- package/src/utils/ssrHandler.ts +185 -0
package/dist/cli.js
CHANGED
|
@@ -5,8 +5,9 @@ import { spawn as spawn2 } from "node:child_process";
|
|
|
5
5
|
|
|
6
6
|
// cli-lib.ts
|
|
7
7
|
import { existsSync as existsSync3 } from "node:fs";
|
|
8
|
-
import { mkdir, writeFile } from "node:fs/promises";
|
|
9
|
-
import { resolve, join } from "node:path";
|
|
8
|
+
import { mkdir, writeFile, unlink } from "node:fs/promises";
|
|
9
|
+
import { resolve, join, dirname } from "node:path";
|
|
10
|
+
import { fileURLToPath as fileURLToPath3 } from "node:url";
|
|
10
11
|
|
|
11
12
|
// src/utils/proxyHandler.tsx
|
|
12
13
|
var cloneHeaders = (headers) => {
|
|
@@ -135,10 +136,10 @@ var upgradeHandler = (options) => {
|
|
|
135
136
|
};
|
|
136
137
|
|
|
137
138
|
// src/slim-react/types.ts
|
|
138
|
-
var SLIM_ELEMENT = Symbol.for("react.element");
|
|
139
|
-
var REACT19_ELEMENT = Symbol.for("react.transitional.element");
|
|
140
|
-
var FRAGMENT_TYPE = Symbol.for("react.fragment");
|
|
141
|
-
var SUSPENSE_TYPE = Symbol.for("react.suspense");
|
|
139
|
+
var SLIM_ELEMENT = /* @__PURE__ */ Symbol.for("react.element");
|
|
140
|
+
var REACT19_ELEMENT = /* @__PURE__ */ Symbol.for("react.transitional.element");
|
|
141
|
+
var FRAGMENT_TYPE = /* @__PURE__ */ Symbol.for("react.fragment");
|
|
142
|
+
var SUSPENSE_TYPE = /* @__PURE__ */ Symbol.for("react.suspense");
|
|
142
143
|
|
|
143
144
|
// src/slim-react/jsx.ts
|
|
144
145
|
function createElement(type, props, ...children) {
|
|
@@ -161,8 +162,7 @@ function createElement(type, props, ...children) {
|
|
|
161
162
|
// src/slim-react/renderContext.ts
|
|
162
163
|
var MAP_KEY = "__slimReactContextMap";
|
|
163
164
|
var _g = globalThis;
|
|
164
|
-
if (!("__slimReactContextMap" in _g))
|
|
165
|
-
_g[MAP_KEY] = null;
|
|
165
|
+
if (!("__slimReactContextMap" in _g)) _g[MAP_KEY] = null;
|
|
166
166
|
function swapContextMap(map) {
|
|
167
167
|
const prev = _g[MAP_KEY];
|
|
168
168
|
_g[MAP_KEY] = map;
|
|
@@ -173,8 +173,7 @@ function captureMap() {
|
|
|
173
173
|
}
|
|
174
174
|
function getContextValue(context) {
|
|
175
175
|
const map = _g[MAP_KEY];
|
|
176
|
-
if (map && map.has(context))
|
|
177
|
-
return map.get(context);
|
|
176
|
+
if (map && map.has(context)) return map.get(context);
|
|
178
177
|
const c = context;
|
|
179
178
|
return "_defaultValue" in c ? c._defaultValue : c._currentValue;
|
|
180
179
|
}
|
|
@@ -256,8 +255,7 @@ function restoreContext(snap) {
|
|
|
256
255
|
}
|
|
257
256
|
function getTreeId() {
|
|
258
257
|
const { id, overflow } = s().currentTreeContext;
|
|
259
|
-
if (id === 1)
|
|
260
|
-
return overflow;
|
|
258
|
+
if (id === 1) return overflow;
|
|
261
259
|
const stripped = (id & ~(1 << 31 - Math.clz32(id))).toString(32);
|
|
262
260
|
return stripped + overflow;
|
|
263
261
|
}
|
|
@@ -266,8 +264,7 @@ function makeId() {
|
|
|
266
264
|
const treeId = getTreeId();
|
|
267
265
|
const n = st.localIdCounter++;
|
|
268
266
|
let id = "_R_" + st.idPrefix + treeId;
|
|
269
|
-
if (n > 0)
|
|
270
|
-
id += "H" + n.toString(32);
|
|
267
|
+
if (n > 0) id += "H" + n.toString(32);
|
|
271
268
|
return id + "_";
|
|
272
269
|
}
|
|
273
270
|
|
|
@@ -322,10 +319,8 @@ function use(usable) {
|
|
|
322
319
|
return getContextValue(usable);
|
|
323
320
|
}
|
|
324
321
|
const promise = usable;
|
|
325
|
-
if (promise.status === "fulfilled")
|
|
326
|
-
|
|
327
|
-
if (promise.status === "rejected")
|
|
328
|
-
throw promise.reason;
|
|
322
|
+
if (promise.status === "fulfilled") return promise.value;
|
|
323
|
+
if (promise.status === "rejected") throw promise.reason;
|
|
329
324
|
throw promise;
|
|
330
325
|
}
|
|
331
326
|
|
|
@@ -359,15 +354,13 @@ var slimDispatcher = {
|
|
|
359
354
|
useHostTransitionStatus: () => false
|
|
360
355
|
};
|
|
361
356
|
function installDispatcher() {
|
|
362
|
-
if (!_internals)
|
|
363
|
-
return null;
|
|
357
|
+
if (!_internals) return null;
|
|
364
358
|
const prev = _internals.H;
|
|
365
359
|
_internals.H = slimDispatcher;
|
|
366
360
|
return prev;
|
|
367
361
|
}
|
|
368
362
|
function restoreDispatcher(prev) {
|
|
369
|
-
if (_internals)
|
|
370
|
-
_internals.H = prev;
|
|
363
|
+
if (_internals) _internals.H = prev;
|
|
371
364
|
}
|
|
372
365
|
|
|
373
366
|
// src/slim-react/render.ts
|
|
@@ -398,8 +391,7 @@ function escapeAttr(str) {
|
|
|
398
391
|
function styleObjectToString(style) {
|
|
399
392
|
let result = "";
|
|
400
393
|
for (const key in style) {
|
|
401
|
-
if (result)
|
|
402
|
-
result += ";";
|
|
394
|
+
if (result) result += ";";
|
|
403
395
|
const cssKey = key.replace(/[A-Z]/g, (m) => "-" + m.toLowerCase());
|
|
404
396
|
result += cssKey + ":" + style[key];
|
|
405
397
|
}
|
|
@@ -566,8 +558,7 @@ function renderAttributes(props, isSvg) {
|
|
|
566
558
|
}
|
|
567
559
|
if (key === "style" && typeof value === "object") {
|
|
568
560
|
const styleStr = styleObjectToString(value);
|
|
569
|
-
if (styleStr)
|
|
570
|
-
attrs += ` style="${escapeAttr(styleStr)}"`;
|
|
561
|
+
if (styleStr) attrs += ` style="${escapeAttr(styleStr)}"`;
|
|
571
562
|
continue;
|
|
572
563
|
}
|
|
573
564
|
attrs += ` ${attrName}="${escapeAttr(String(value))}"`;
|
|
@@ -586,14 +577,12 @@ var BufferWriter = class {
|
|
|
586
577
|
this.lastWasText = true;
|
|
587
578
|
}
|
|
588
579
|
flush(target) {
|
|
589
|
-
for (const c of this.chunks)
|
|
590
|
-
target.write(c);
|
|
580
|
+
for (const c of this.chunks) target.write(c);
|
|
591
581
|
target.lastWasText = this.lastWasText;
|
|
592
582
|
}
|
|
593
583
|
};
|
|
594
584
|
function renderNode(node, writer, isSvg = false) {
|
|
595
|
-
if (node == null || typeof node === "boolean")
|
|
596
|
-
return;
|
|
585
|
+
if (node == null || typeof node === "boolean") return;
|
|
597
586
|
if (typeof node === "string") {
|
|
598
587
|
writer.text(escapeHtml(node));
|
|
599
588
|
return;
|
|
@@ -614,8 +603,7 @@ function renderNode(node, writer, isSvg = false) {
|
|
|
614
603
|
}
|
|
615
604
|
if (typeof node === "object" && node !== null && "$$typeof" in node) {
|
|
616
605
|
const elType = node["$$typeof"];
|
|
617
|
-
if (elType !== SLIM_ELEMENT && elType !== REACT19_ELEMENT)
|
|
618
|
-
return;
|
|
606
|
+
if (elType !== SLIM_ELEMENT && elType !== REACT19_ELEMENT) return;
|
|
619
607
|
const element = node;
|
|
620
608
|
const { type, props } = element;
|
|
621
609
|
if (type === FRAGMENT_TYPE) {
|
|
@@ -636,17 +624,14 @@ function renderNode(node, writer, isSvg = false) {
|
|
|
636
624
|
}
|
|
637
625
|
}
|
|
638
626
|
function markSelectedOptionsMulti(children, selectedValues) {
|
|
639
|
-
if (children == null || typeof children === "boolean")
|
|
640
|
-
|
|
641
|
-
if (typeof children === "string" || typeof children === "number")
|
|
642
|
-
return children;
|
|
627
|
+
if (children == null || typeof children === "boolean") return children;
|
|
628
|
+
if (typeof children === "string" || typeof children === "number") return children;
|
|
643
629
|
if (Array.isArray(children)) {
|
|
644
630
|
return children.map((c) => markSelectedOptionsMulti(c, selectedValues));
|
|
645
631
|
}
|
|
646
632
|
if (typeof children === "object" && "$$typeof" in children) {
|
|
647
633
|
const elType = children["$$typeof"];
|
|
648
|
-
if (elType !== SLIM_ELEMENT && elType !== REACT19_ELEMENT)
|
|
649
|
-
return children;
|
|
634
|
+
if (elType !== SLIM_ELEMENT && elType !== REACT19_ELEMENT) return children;
|
|
650
635
|
const el = children;
|
|
651
636
|
if (el.type === "option") {
|
|
652
637
|
const optValue = el.props.value !== void 0 ? el.props.value : el.props.children;
|
|
@@ -667,8 +652,7 @@ function renderHostElement(tag, props, writer, isSvg) {
|
|
|
667
652
|
const textContent = props.value ?? props.defaultValue ?? props.children ?? "";
|
|
668
653
|
const filteredProps = {};
|
|
669
654
|
for (const k of Object.keys(props)) {
|
|
670
|
-
if (k !== "value" && k !== "defaultValue" && k !== "children")
|
|
671
|
-
filteredProps[k] = props[k];
|
|
655
|
+
if (k !== "value" && k !== "defaultValue" && k !== "children") filteredProps[k] = props[k];
|
|
672
656
|
}
|
|
673
657
|
writer.write(`<textarea${renderAttributes(filteredProps, false)}>`);
|
|
674
658
|
writer.text(escapeHtml(String(textContent)));
|
|
@@ -679,8 +663,7 @@ function renderHostElement(tag, props, writer, isSvg) {
|
|
|
679
663
|
const selectedValue = props.value ?? props.defaultValue;
|
|
680
664
|
const filteredProps = {};
|
|
681
665
|
for (const k of Object.keys(props)) {
|
|
682
|
-
if (k !== "value" && k !== "defaultValue")
|
|
683
|
-
filteredProps[k] = props[k];
|
|
666
|
+
if (k !== "value" && k !== "defaultValue") filteredProps[k] = props[k];
|
|
684
667
|
}
|
|
685
668
|
writer.write(`<select${renderAttributes(filteredProps, false)}>`);
|
|
686
669
|
const selectedSet = selectedValue == null ? null : Array.isArray(selectedValue) ? new Set(selectedValue.map(String)) : /* @__PURE__ */ new Set([String(selectedValue)]);
|
|
@@ -714,12 +697,12 @@ function renderHostElement(tag, props, writer, isSvg) {
|
|
|
714
697
|
}
|
|
715
698
|
writer.write(`</${tag}>`);
|
|
716
699
|
}
|
|
717
|
-
var REACT_MEMO = Symbol.for("react.memo");
|
|
718
|
-
var REACT_FORWARD_REF = Symbol.for("react.forward_ref");
|
|
719
|
-
var REACT_PROVIDER = Symbol.for("react.provider");
|
|
720
|
-
var REACT_CONTEXT = Symbol.for("react.context");
|
|
721
|
-
var REACT_CONSUMER = Symbol.for("react.consumer");
|
|
722
|
-
var REACT_LAZY = Symbol.for("react.lazy");
|
|
700
|
+
var REACT_MEMO = /* @__PURE__ */ Symbol.for("react.memo");
|
|
701
|
+
var REACT_FORWARD_REF = /* @__PURE__ */ Symbol.for("react.forward_ref");
|
|
702
|
+
var REACT_PROVIDER = /* @__PURE__ */ Symbol.for("react.provider");
|
|
703
|
+
var REACT_CONTEXT = /* @__PURE__ */ Symbol.for("react.context");
|
|
704
|
+
var REACT_CONSUMER = /* @__PURE__ */ Symbol.for("react.consumer");
|
|
705
|
+
var REACT_LAZY = /* @__PURE__ */ Symbol.for("react.lazy");
|
|
723
706
|
function renderComponent(type, props, writer, isSvg) {
|
|
724
707
|
const typeOf = type?.$$typeof;
|
|
725
708
|
if (typeOf === REACT_MEMO) {
|
|
@@ -788,8 +771,7 @@ function renderComponent(type, props, writer, isSvg) {
|
|
|
788
771
|
const instance = new type(props);
|
|
789
772
|
if (typeof type.getDerivedStateFromProps === "function") {
|
|
790
773
|
const derived = type.getDerivedStateFromProps(props, instance.state ?? {});
|
|
791
|
-
if (derived != null)
|
|
792
|
-
instance.state = { ...instance.state ?? {}, ...derived };
|
|
774
|
+
if (derived != null) instance.state = { ...instance.state ?? {}, ...derived };
|
|
793
775
|
}
|
|
794
776
|
result = instance.render();
|
|
795
777
|
} else {
|
|
@@ -798,8 +780,7 @@ function renderComponent(type, props, writer, isSvg) {
|
|
|
798
780
|
} catch (e) {
|
|
799
781
|
restoreDispatcher(prevDispatcher);
|
|
800
782
|
popComponentScope(savedScope);
|
|
801
|
-
if (isProvider)
|
|
802
|
-
popContextValue(ctx, prevCtxValue);
|
|
783
|
+
if (isProvider) popContextValue(ctx, prevCtxValue);
|
|
803
784
|
throw e;
|
|
804
785
|
}
|
|
805
786
|
restoreDispatcher(prevDispatcher);
|
|
@@ -808,11 +789,9 @@ function renderComponent(type, props, writer, isSvg) {
|
|
|
808
789
|
savedIdTree = pushTreeContext(1, 0);
|
|
809
790
|
}
|
|
810
791
|
const finish = () => {
|
|
811
|
-
if (savedIdTree !== void 0)
|
|
812
|
-
popTreeContext(savedIdTree);
|
|
792
|
+
if (savedIdTree !== void 0) popTreeContext(savedIdTree);
|
|
813
793
|
popComponentScope(savedScope);
|
|
814
|
-
if (isProvider)
|
|
815
|
-
popContextValue(ctx, prevCtxValue);
|
|
794
|
+
if (isProvider) popContextValue(ctx, prevCtxValue);
|
|
816
795
|
};
|
|
817
796
|
if (result instanceof Promise) {
|
|
818
797
|
const m = captureMap();
|
|
@@ -823,11 +802,9 @@ function renderComponent(type, props, writer, isSvg) {
|
|
|
823
802
|
asyncSavedIdTree = pushTreeContext(1, 0);
|
|
824
803
|
}
|
|
825
804
|
const asyncFinish = () => {
|
|
826
|
-
if (asyncSavedIdTree !== void 0)
|
|
827
|
-
popTreeContext(asyncSavedIdTree);
|
|
805
|
+
if (asyncSavedIdTree !== void 0) popTreeContext(asyncSavedIdTree);
|
|
828
806
|
popComponentScope(savedScope);
|
|
829
|
-
if (isProvider)
|
|
830
|
-
popContextValue(ctx, prevCtxValue);
|
|
807
|
+
if (isProvider) popContextValue(ctx, prevCtxValue);
|
|
831
808
|
};
|
|
832
809
|
const r2 = renderNode(resolved, writer, isSvg);
|
|
833
810
|
if (r2 && typeof r2.then === "function") {
|
|
@@ -910,8 +887,7 @@ function renderChildArrayFrom(children, startIndex, writer, isSvg) {
|
|
|
910
887
|
}
|
|
911
888
|
}
|
|
912
889
|
function renderChildren(children, writer, isSvg = false) {
|
|
913
|
-
if (children == null)
|
|
914
|
-
return;
|
|
890
|
+
if (children == null) return;
|
|
915
891
|
if (Array.isArray(children)) {
|
|
916
892
|
return renderChildArray(children, writer, isSvg);
|
|
917
893
|
}
|
|
@@ -1027,14 +1003,12 @@ function processSegmentCache(html) {
|
|
|
1027
1003
|
const cacheM = /data-cache="([^"]+)"/.exec(attrs);
|
|
1028
1004
|
const keyM = /data-key="([^"]+)"/.exec(attrs);
|
|
1029
1005
|
const ttlM = /data-ttl="(\d+)"/.exec(attrs);
|
|
1030
|
-
if (!cacheM || !keyM)
|
|
1031
|
-
return match;
|
|
1006
|
+
if (!cacheM || !keyM) return match;
|
|
1032
1007
|
if (cacheM[1] === "miss") {
|
|
1033
1008
|
setSegment(keyM[1], content, ttlM ? Number(ttlM[1]) : void 0);
|
|
1034
1009
|
return content;
|
|
1035
1010
|
}
|
|
1036
|
-
if (cacheM[1] === "hit")
|
|
1037
|
-
return content;
|
|
1011
|
+
if (cacheM[1] === "hit") return content;
|
|
1038
1012
|
return match;
|
|
1039
1013
|
}
|
|
1040
1014
|
);
|
|
@@ -1060,17 +1034,14 @@ function renderHeadTag(tag, id, opts, selfClose = false) {
|
|
|
1060
1034
|
let attrs = ` id="${escAttr(id)}"`;
|
|
1061
1035
|
let inner = "";
|
|
1062
1036
|
for (const [k, v] of Object.entries(opts)) {
|
|
1063
|
-
if (k === "key" || k === "children")
|
|
1064
|
-
continue;
|
|
1037
|
+
if (k === "key" || k === "children") continue;
|
|
1065
1038
|
if (k === "dangerouslySetInnerHTML") {
|
|
1066
1039
|
inner = v.__html ?? "";
|
|
1067
1040
|
continue;
|
|
1068
1041
|
}
|
|
1069
1042
|
const attr = ATTR[k] ?? k;
|
|
1070
|
-
if (v === true)
|
|
1071
|
-
|
|
1072
|
-
else if (v !== false && v != null)
|
|
1073
|
-
attrs += ` ${attr}="${escAttr(String(v))}"`;
|
|
1043
|
+
if (v === true) attrs += ` ${attr}`;
|
|
1044
|
+
else if (v !== false && v != null) attrs += ` ${attr}="${escAttr(String(v))}"`;
|
|
1074
1045
|
}
|
|
1075
1046
|
return selfClose ? `<${tag}${attrs}>` : `<${tag}${attrs}>${inner}</${tag}>`;
|
|
1076
1047
|
}
|
|
@@ -1114,8 +1085,7 @@ var getReactResponse = async (req, opts) => {
|
|
|
1114
1085
|
const { context: _, ...restProps } = getFinalProps ? await getFinalProps(props) : props;
|
|
1115
1086
|
const serverData = {};
|
|
1116
1087
|
for (const [key, entry] of unsuspend.cache) {
|
|
1117
|
-
if (entry.status === "fulfilled")
|
|
1118
|
-
serverData[key] = entry.value;
|
|
1088
|
+
if (entry.status === "fulfilled") serverData[key] = entry.value;
|
|
1119
1089
|
}
|
|
1120
1090
|
const clientProps = {
|
|
1121
1091
|
...restProps,
|
|
@@ -1323,8 +1293,7 @@ var buildCompilerConfig = (entry, opts, includeHotPlugin) => {
|
|
|
1323
1293
|
if (!isServerBuild && opts.reactMode !== void 0) {
|
|
1324
1294
|
const rules = localConfig.module?.rules ?? [];
|
|
1325
1295
|
for (const rule of rules) {
|
|
1326
|
-
if (!rule?.use || !Array.isArray(rule.use))
|
|
1327
|
-
continue;
|
|
1296
|
+
if (!rule?.use || !Array.isArray(rule.use)) continue;
|
|
1328
1297
|
for (const entry2 of rule.use) {
|
|
1329
1298
|
if (entry2?.loader?.includes("swc-loader")) {
|
|
1330
1299
|
entry2.options = entry2.options ?? {};
|
|
@@ -1338,6 +1307,25 @@ var buildCompilerConfig = (entry, opts, includeHotPlugin) => {
|
|
|
1338
1307
|
}
|
|
1339
1308
|
}
|
|
1340
1309
|
const extraPlugins = [];
|
|
1310
|
+
if (!isServerBuild) {
|
|
1311
|
+
extraPlugins.push({
|
|
1312
|
+
apply(compiler) {
|
|
1313
|
+
compiler.hooks.compilation.tap("HadarsWorkerChunkLoading", (compilation) => {
|
|
1314
|
+
compilation.hooks.childCompiler.tap(
|
|
1315
|
+
"HadarsWorkerChunkLoading",
|
|
1316
|
+
(childCompiler) => {
|
|
1317
|
+
if (childCompiler.options?.output) {
|
|
1318
|
+
childCompiler.options.output.chunkLoading = "import-scripts";
|
|
1319
|
+
}
|
|
1320
|
+
if (childCompiler.options?.experiments) {
|
|
1321
|
+
childCompiler.options.experiments.outputModule = false;
|
|
1322
|
+
}
|
|
1323
|
+
}
|
|
1324
|
+
);
|
|
1325
|
+
});
|
|
1326
|
+
}
|
|
1327
|
+
});
|
|
1328
|
+
}
|
|
1341
1329
|
const defineValues = { ...opts.define ?? {} };
|
|
1342
1330
|
if (!isServerBuild && opts.reactMode !== void 0) {
|
|
1343
1331
|
defineValues["process.env.NODE_ENV"] = JSON.stringify(opts.reactMode);
|
|
@@ -1414,7 +1402,8 @@ var buildCompilerConfig = (entry, opts, includeHotPlugin) => {
|
|
|
1414
1402
|
},
|
|
1415
1403
|
isDev && !isServerBuild && new ReactRefreshPlugin(),
|
|
1416
1404
|
includeHotPlugin && isDev && !isServerBuild && new rspack.HotModuleReplacementPlugin(),
|
|
1417
|
-
...extraPlugins
|
|
1405
|
+
...extraPlugins,
|
|
1406
|
+
...opts.plugins ?? []
|
|
1418
1407
|
],
|
|
1419
1408
|
...localConfig,
|
|
1420
1409
|
// Merge base resolve (modules, tsConfig, extensions) with per-build resolve
|
|
@@ -1517,16 +1506,12 @@ var COMPRESSIBLE_RE = /\b(?:text\/|application\/(?:json|javascript|xml)|image\/s
|
|
|
1517
1506
|
function withCompression(handler) {
|
|
1518
1507
|
return async (req, ctx) => {
|
|
1519
1508
|
const res = await handler(req, ctx);
|
|
1520
|
-
if (!res?.body)
|
|
1521
|
-
|
|
1522
|
-
if (
|
|
1523
|
-
return res;
|
|
1524
|
-
if (res.headers.has("Content-Encoding"))
|
|
1525
|
-
return res;
|
|
1509
|
+
if (!res?.body) return res;
|
|
1510
|
+
if (!COMPRESSIBLE_RE.test(res.headers.get("Content-Type") ?? "")) return res;
|
|
1511
|
+
if (res.headers.has("Content-Encoding")) return res;
|
|
1526
1512
|
const accept = req.headers.get("Accept-Encoding") ?? "";
|
|
1527
1513
|
const encoding = accept.includes("br") ? "br" : accept.includes("gzip") ? "gzip" : null;
|
|
1528
|
-
if (!encoding)
|
|
1529
|
-
return res;
|
|
1514
|
+
if (!encoding) return res;
|
|
1530
1515
|
try {
|
|
1531
1516
|
const compressed = res.body.pipeThrough(new globalThis.CompressionStream(encoding));
|
|
1532
1517
|
const headers = new Headers(res.headers);
|
|
@@ -1604,8 +1589,7 @@ async function serve(port, fetchHandler, websocket) {
|
|
|
1604
1589
|
const reader = response.body.getReader();
|
|
1605
1590
|
while (true) {
|
|
1606
1591
|
const { done, value } = await reader.read();
|
|
1607
|
-
if (done)
|
|
1608
|
-
break;
|
|
1592
|
+
if (done) break;
|
|
1609
1593
|
await new Promise(
|
|
1610
1594
|
(resolve2, reject) => nodeRes.write(value, (err) => err ? reject(err) : resolve2())
|
|
1611
1595
|
);
|
|
@@ -1613,8 +1597,7 @@ async function serve(port, fetchHandler, websocket) {
|
|
|
1613
1597
|
}
|
|
1614
1598
|
} catch (err) {
|
|
1615
1599
|
console.error("[hadars] request error", err);
|
|
1616
|
-
if (!nodeRes.headersSent)
|
|
1617
|
-
nodeRes.writeHead(500);
|
|
1600
|
+
if (!nodeRes.headersSent) nodeRes.writeHead(500);
|
|
1618
1601
|
} finally {
|
|
1619
1602
|
nodeRes.end();
|
|
1620
1603
|
}
|
|
@@ -1677,7 +1660,122 @@ import { existsSync as existsSync2 } from "node:fs";
|
|
|
1677
1660
|
import os from "node:os";
|
|
1678
1661
|
import { spawn } from "node:child_process";
|
|
1679
1662
|
import cluster from "node:cluster";
|
|
1663
|
+
|
|
1664
|
+
// src/utils/ssrHandler.ts
|
|
1665
|
+
var HEAD_MARKER = '<meta name="HADARS_HEAD">';
|
|
1666
|
+
var BODY_MARKER = '<meta name="HADARS_BODY">';
|
|
1680
1667
|
var encoder = new TextEncoder();
|
|
1668
|
+
async function buildSsrResponse(bodyHtml, clientProps, headHtml, status, getPrecontentHtml) {
|
|
1669
|
+
const responseStream = new ReadableStream({
|
|
1670
|
+
async start(controller) {
|
|
1671
|
+
const [precontentHtml, postContent] = await getPrecontentHtml(headHtml);
|
|
1672
|
+
controller.enqueue(encoder.encode(precontentHtml));
|
|
1673
|
+
const scriptContent = JSON.stringify({ hadars: { props: clientProps } }).replace(/</g, "\\u003c");
|
|
1674
|
+
controller.enqueue(encoder.encode(
|
|
1675
|
+
`<div id="app">${bodyHtml}</div><script id="hadars" type="application/json">${scriptContent}</script>` + postContent
|
|
1676
|
+
));
|
|
1677
|
+
controller.close();
|
|
1678
|
+
}
|
|
1679
|
+
});
|
|
1680
|
+
return new Response(responseStream, {
|
|
1681
|
+
headers: { "Content-Type": "text/html; charset=utf-8" },
|
|
1682
|
+
status
|
|
1683
|
+
});
|
|
1684
|
+
}
|
|
1685
|
+
var makePrecontentHtmlGetter = (htmlFilePromise) => {
|
|
1686
|
+
let preHead = null;
|
|
1687
|
+
let postHead = null;
|
|
1688
|
+
let postContent = null;
|
|
1689
|
+
return async (headHtml) => {
|
|
1690
|
+
if (preHead === null || postHead === null || postContent === null) {
|
|
1691
|
+
const html = await htmlFilePromise;
|
|
1692
|
+
const headEnd = html.indexOf(HEAD_MARKER);
|
|
1693
|
+
const contentStart = html.indexOf(BODY_MARKER);
|
|
1694
|
+
preHead = html.slice(0, headEnd);
|
|
1695
|
+
postHead = html.slice(headEnd + HEAD_MARKER.length, contentStart);
|
|
1696
|
+
postContent = html.slice(contentStart + BODY_MARKER.length);
|
|
1697
|
+
}
|
|
1698
|
+
return [preHead + headHtml + postHead, postContent];
|
|
1699
|
+
};
|
|
1700
|
+
};
|
|
1701
|
+
async function transformStream(data, stream) {
|
|
1702
|
+
const writer = stream.writable.getWriter();
|
|
1703
|
+
writer.write(data);
|
|
1704
|
+
writer.close();
|
|
1705
|
+
const chunks = [];
|
|
1706
|
+
const reader = stream.readable.getReader();
|
|
1707
|
+
while (true) {
|
|
1708
|
+
const { done, value } = await reader.read();
|
|
1709
|
+
if (done) break;
|
|
1710
|
+
chunks.push(value);
|
|
1711
|
+
}
|
|
1712
|
+
const total = chunks.reduce((n, c) => n + c.length, 0);
|
|
1713
|
+
const out = new Uint8Array(total);
|
|
1714
|
+
let offset = 0;
|
|
1715
|
+
for (const c of chunks) {
|
|
1716
|
+
out.set(c, offset);
|
|
1717
|
+
offset += c.length;
|
|
1718
|
+
}
|
|
1719
|
+
return out;
|
|
1720
|
+
}
|
|
1721
|
+
var gzipCompress = (d) => transformStream(d, new globalThis.CompressionStream("gzip"));
|
|
1722
|
+
var gzipDecompress = (d) => transformStream(d, new globalThis.DecompressionStream("gzip"));
|
|
1723
|
+
async function buildCacheEntry(res, ttl) {
|
|
1724
|
+
const buf = await res.arrayBuffer();
|
|
1725
|
+
const body = await gzipCompress(new Uint8Array(buf));
|
|
1726
|
+
const headers = [];
|
|
1727
|
+
res.headers.forEach((v, k) => {
|
|
1728
|
+
if (k.toLowerCase() !== "content-encoding" && k.toLowerCase() !== "content-length") {
|
|
1729
|
+
headers.push([k, v]);
|
|
1730
|
+
}
|
|
1731
|
+
});
|
|
1732
|
+
headers.push(["content-encoding", "gzip"]);
|
|
1733
|
+
return { body, status: res.status, headers, expiresAt: ttl != null ? Date.now() + ttl : null };
|
|
1734
|
+
}
|
|
1735
|
+
async function serveFromEntry(entry, req) {
|
|
1736
|
+
const accept = req.headers.get("Accept-Encoding") ?? "";
|
|
1737
|
+
if (accept.includes("gzip")) {
|
|
1738
|
+
return new Response(entry.body.buffer, { status: entry.status, headers: entry.headers });
|
|
1739
|
+
}
|
|
1740
|
+
const plain = await gzipDecompress(entry.body);
|
|
1741
|
+
const headers = entry.headers.filter(([k]) => k.toLowerCase() !== "content-encoding");
|
|
1742
|
+
return new Response(plain.buffer, { status: entry.status, headers });
|
|
1743
|
+
}
|
|
1744
|
+
function createRenderCache(opts, handler) {
|
|
1745
|
+
const store = /* @__PURE__ */ new Map();
|
|
1746
|
+
const inFlight = /* @__PURE__ */ new Map();
|
|
1747
|
+
return async (req, ctx) => {
|
|
1748
|
+
const hadarsReq = parseRequest(req);
|
|
1749
|
+
const cacheOpts = await opts(hadarsReq);
|
|
1750
|
+
const key = cacheOpts?.key ?? null;
|
|
1751
|
+
if (key != null) {
|
|
1752
|
+
const entry = store.get(key);
|
|
1753
|
+
if (entry) {
|
|
1754
|
+
const expired = entry.expiresAt != null && Date.now() >= entry.expiresAt;
|
|
1755
|
+
if (!expired) return serveFromEntry(entry, req);
|
|
1756
|
+
store.delete(key);
|
|
1757
|
+
}
|
|
1758
|
+
let flight = inFlight.get(key);
|
|
1759
|
+
if (!flight) {
|
|
1760
|
+
const ttl = cacheOpts?.ttl;
|
|
1761
|
+
flight = handler(new Request(req), ctx).then(async (res) => {
|
|
1762
|
+
if (!res || res.status < 200 || res.status >= 300 || res.headers.has("set-cookie")) {
|
|
1763
|
+
return null;
|
|
1764
|
+
}
|
|
1765
|
+
const newEntry2 = await buildCacheEntry(res, ttl);
|
|
1766
|
+
store.set(key, newEntry2);
|
|
1767
|
+
return newEntry2;
|
|
1768
|
+
}).catch(() => null).finally(() => inFlight.delete(key));
|
|
1769
|
+
inFlight.set(key, flight);
|
|
1770
|
+
}
|
|
1771
|
+
const newEntry = await flight;
|
|
1772
|
+
if (newEntry) return serveFromEntry(newEntry, req);
|
|
1773
|
+
}
|
|
1774
|
+
return handler(req, ctx);
|
|
1775
|
+
};
|
|
1776
|
+
}
|
|
1777
|
+
|
|
1778
|
+
// src/build.ts
|
|
1681
1779
|
async function processHtmlTemplate(templatePath) {
|
|
1682
1780
|
const html = await fs.readFile(templatePath, "utf-8");
|
|
1683
1781
|
const styleRegex = /<style([^>]*)>([\s\S]*?)<\/style>/gi;
|
|
@@ -1686,8 +1784,7 @@ async function processHtmlTemplate(templatePath) {
|
|
|
1686
1784
|
while ((m = styleRegex.exec(html)) !== null) {
|
|
1687
1785
|
matches.push({ full: m[0], attrs: m[1] ?? "", css: m[2] ?? "" });
|
|
1688
1786
|
}
|
|
1689
|
-
if (matches.length === 0)
|
|
1690
|
-
return templatePath;
|
|
1787
|
+
if (matches.length === 0) return templatePath;
|
|
1691
1788
|
await ensureHadarsTmpDir();
|
|
1692
1789
|
const sourceHash = crypto.createHash("md5").update(html).digest("hex").slice(0, 8);
|
|
1693
1790
|
const cachedPath = pathMod2.join(HADARS_TMP_DIR, `template-${sourceHash}.html`);
|
|
@@ -1716,8 +1813,6 @@ async function processHtmlTemplate(templatePath) {
|
|
|
1716
1813
|
await fs.writeFile(cachedPath, processedHtml);
|
|
1717
1814
|
return cachedPath;
|
|
1718
1815
|
}
|
|
1719
|
-
var HEAD_MARKER = '<meta name="HADARS_HEAD">';
|
|
1720
|
-
var BODY_MARKER = '<meta name="HADARS_BODY">';
|
|
1721
1816
|
var RenderWorkerPool = class {
|
|
1722
1817
|
workers = [];
|
|
1723
1818
|
pending = /* @__PURE__ */ new Map();
|
|
@@ -1737,28 +1832,23 @@ var RenderWorkerPool = class {
|
|
|
1737
1832
|
this._ssrBundlePath = ssrBundlePath;
|
|
1738
1833
|
import("node:worker_threads").then(({ Worker }) => {
|
|
1739
1834
|
this._Worker = Worker;
|
|
1740
|
-
for (let i = 0; i < size; i++)
|
|
1741
|
-
this._spawnWorker();
|
|
1835
|
+
for (let i = 0; i < size; i++) this._spawnWorker();
|
|
1742
1836
|
}).catch((err) => {
|
|
1743
1837
|
console.error("[hadars] Failed to initialise render worker pool:", err);
|
|
1744
1838
|
});
|
|
1745
1839
|
}
|
|
1746
1840
|
_spawnWorker() {
|
|
1747
|
-
if (!this._Worker)
|
|
1748
|
-
return;
|
|
1841
|
+
if (!this._Worker) return;
|
|
1749
1842
|
const w = new this._Worker(this._workerPath, { workerData: { ssrBundlePath: this._ssrBundlePath } });
|
|
1750
1843
|
this.workerPending.set(w, /* @__PURE__ */ new Set());
|
|
1751
1844
|
w.on("message", (msg) => {
|
|
1752
1845
|
const { id, html, headHtml, status, error } = msg;
|
|
1753
1846
|
const p = this.pending.get(id);
|
|
1754
|
-
if (!p)
|
|
1755
|
-
return;
|
|
1847
|
+
if (!p) return;
|
|
1756
1848
|
this.pending.delete(id);
|
|
1757
1849
|
this.workerPending.get(w)?.delete(id);
|
|
1758
|
-
if (error)
|
|
1759
|
-
|
|
1760
|
-
else
|
|
1761
|
-
p.resolve({ html, headHtml, status });
|
|
1850
|
+
if (error) p.reject(new Error(error));
|
|
1851
|
+
else p.resolve({ html, headHtml, status });
|
|
1762
1852
|
});
|
|
1763
1853
|
w.on("error", (err) => {
|
|
1764
1854
|
console.error("[hadars] Render worker error:", err);
|
|
@@ -1774,8 +1864,7 @@ var RenderWorkerPool = class {
|
|
|
1774
1864
|
}
|
|
1775
1865
|
_handleWorkerDeath(w, err) {
|
|
1776
1866
|
const idx = this.workers.indexOf(w);
|
|
1777
|
-
if (idx !== -1)
|
|
1778
|
-
this.workers.splice(idx, 1);
|
|
1867
|
+
if (idx !== -1) this.workers.splice(idx, 1);
|
|
1779
1868
|
const ids = this.workerPending.get(w);
|
|
1780
1869
|
if (ids) {
|
|
1781
1870
|
for (const id of ids) {
|
|
@@ -1791,8 +1880,7 @@ var RenderWorkerPool = class {
|
|
|
1791
1880
|
this._spawnWorker();
|
|
1792
1881
|
}
|
|
1793
1882
|
nextWorker() {
|
|
1794
|
-
if (this.workers.length === 0)
|
|
1795
|
-
return void 0;
|
|
1883
|
+
if (this.workers.length === 0) return void 0;
|
|
1796
1884
|
const w = this.workers[this.rrIndex % this.workers.length];
|
|
1797
1885
|
this.rrIndex++;
|
|
1798
1886
|
return w;
|
|
@@ -1821,23 +1909,6 @@ var RenderWorkerPool = class {
|
|
|
1821
1909
|
await Promise.all(this.workers.map((w) => w.terminate()));
|
|
1822
1910
|
}
|
|
1823
1911
|
};
|
|
1824
|
-
async function buildSsrResponse(bodyHtml, clientProps, headHtml, status, getPrecontentHtml) {
|
|
1825
|
-
const responseStream = new ReadableStream({
|
|
1826
|
-
async start(controller) {
|
|
1827
|
-
const [precontentHtml, postContent] = await getPrecontentHtml(headHtml);
|
|
1828
|
-
controller.enqueue(encoder.encode(precontentHtml));
|
|
1829
|
-
const scriptContent = JSON.stringify({ hadars: { props: clientProps } }).replace(/</g, "\\u003c");
|
|
1830
|
-
controller.enqueue(encoder.encode(
|
|
1831
|
-
`<div id="app">${bodyHtml}</div><script id="hadars" type="application/json">${scriptContent}</script>` + postContent
|
|
1832
|
-
));
|
|
1833
|
-
controller.close();
|
|
1834
|
-
}
|
|
1835
|
-
});
|
|
1836
|
-
return new Response(responseStream, {
|
|
1837
|
-
headers: { "Content-Type": "text/html; charset=utf-8" },
|
|
1838
|
-
status
|
|
1839
|
-
});
|
|
1840
|
-
}
|
|
1841
1912
|
async function serializeRequest(req) {
|
|
1842
1913
|
const isGetOrHead = ["GET", "HEAD"].includes(req.method ?? "GET");
|
|
1843
1914
|
const body = isGetOrHead ? null : new Uint8Array(await req.clone().arrayBuffer());
|
|
@@ -1856,102 +1927,6 @@ async function serializeRequest(req) {
|
|
|
1856
1927
|
cookies: req.cookies
|
|
1857
1928
|
};
|
|
1858
1929
|
}
|
|
1859
|
-
var makePrecontentHtmlGetter = (htmlFilePromise) => {
|
|
1860
|
-
let preHead = null;
|
|
1861
|
-
let postHead = null;
|
|
1862
|
-
let postContent = null;
|
|
1863
|
-
return async (headHtml) => {
|
|
1864
|
-
if (preHead === null || postHead === null || postContent === null) {
|
|
1865
|
-
const html = await htmlFilePromise;
|
|
1866
|
-
const headEnd = html.indexOf(HEAD_MARKER);
|
|
1867
|
-
const contentStart = html.indexOf(BODY_MARKER);
|
|
1868
|
-
preHead = html.slice(0, headEnd);
|
|
1869
|
-
postHead = html.slice(headEnd + HEAD_MARKER.length, contentStart);
|
|
1870
|
-
postContent = html.slice(contentStart + BODY_MARKER.length);
|
|
1871
|
-
}
|
|
1872
|
-
return [preHead + headHtml + postHead, postContent];
|
|
1873
|
-
};
|
|
1874
|
-
};
|
|
1875
|
-
async function transformStream(data, stream) {
|
|
1876
|
-
const writer = stream.writable.getWriter();
|
|
1877
|
-
writer.write(data);
|
|
1878
|
-
writer.close();
|
|
1879
|
-
const chunks = [];
|
|
1880
|
-
const reader = stream.readable.getReader();
|
|
1881
|
-
while (true) {
|
|
1882
|
-
const { done, value } = await reader.read();
|
|
1883
|
-
if (done)
|
|
1884
|
-
break;
|
|
1885
|
-
chunks.push(value);
|
|
1886
|
-
}
|
|
1887
|
-
const total = chunks.reduce((n, c) => n + c.length, 0);
|
|
1888
|
-
const out = new Uint8Array(total);
|
|
1889
|
-
let offset = 0;
|
|
1890
|
-
for (const c of chunks) {
|
|
1891
|
-
out.set(c, offset);
|
|
1892
|
-
offset += c.length;
|
|
1893
|
-
}
|
|
1894
|
-
return out;
|
|
1895
|
-
}
|
|
1896
|
-
var gzipCompress = (d) => transformStream(d, new globalThis.CompressionStream("gzip"));
|
|
1897
|
-
var gzipDecompress = (d) => transformStream(d, new globalThis.DecompressionStream("gzip"));
|
|
1898
|
-
async function buildCacheEntry(res, ttl) {
|
|
1899
|
-
const buf = await res.arrayBuffer();
|
|
1900
|
-
const body = await gzipCompress(new Uint8Array(buf));
|
|
1901
|
-
const headers = [];
|
|
1902
|
-
res.headers.forEach((v, k) => {
|
|
1903
|
-
if (k.toLowerCase() !== "content-encoding" && k.toLowerCase() !== "content-length") {
|
|
1904
|
-
headers.push([k, v]);
|
|
1905
|
-
}
|
|
1906
|
-
});
|
|
1907
|
-
headers.push(["content-encoding", "gzip"]);
|
|
1908
|
-
return { body, status: res.status, headers, expiresAt: ttl != null ? Date.now() + ttl : null };
|
|
1909
|
-
}
|
|
1910
|
-
async function serveFromEntry(entry, req) {
|
|
1911
|
-
const accept = req.headers.get("Accept-Encoding") ?? "";
|
|
1912
|
-
if (accept.includes("gzip")) {
|
|
1913
|
-
return new Response(entry.body.buffer, { status: entry.status, headers: entry.headers });
|
|
1914
|
-
}
|
|
1915
|
-
const plain = await gzipDecompress(entry.body);
|
|
1916
|
-
const headers = entry.headers.filter(([k]) => k.toLowerCase() !== "content-encoding");
|
|
1917
|
-
return new Response(plain.buffer, { status: entry.status, headers });
|
|
1918
|
-
}
|
|
1919
|
-
function createRenderCache(opts, handler) {
|
|
1920
|
-
const store = /* @__PURE__ */ new Map();
|
|
1921
|
-
const inFlight = /* @__PURE__ */ new Map();
|
|
1922
|
-
return async (req, ctx) => {
|
|
1923
|
-
const hadarsReq = parseRequest(req);
|
|
1924
|
-
const cacheOpts = await opts(hadarsReq);
|
|
1925
|
-
const key = cacheOpts?.key ?? null;
|
|
1926
|
-
if (key != null) {
|
|
1927
|
-
const entry = store.get(key);
|
|
1928
|
-
if (entry) {
|
|
1929
|
-
const expired = entry.expiresAt != null && Date.now() >= entry.expiresAt;
|
|
1930
|
-
if (!expired) {
|
|
1931
|
-
return serveFromEntry(entry, req);
|
|
1932
|
-
}
|
|
1933
|
-
store.delete(key);
|
|
1934
|
-
}
|
|
1935
|
-
let flight = inFlight.get(key);
|
|
1936
|
-
if (!flight) {
|
|
1937
|
-
const ttl = cacheOpts?.ttl;
|
|
1938
|
-
flight = handler(new Request(req), ctx).then(async (res) => {
|
|
1939
|
-
if (!res || res.status < 200 || res.status >= 300 || res.headers.has("set-cookie")) {
|
|
1940
|
-
return null;
|
|
1941
|
-
}
|
|
1942
|
-
const newEntry2 = await buildCacheEntry(res, ttl);
|
|
1943
|
-
store.set(key, newEntry2);
|
|
1944
|
-
return newEntry2;
|
|
1945
|
-
}).catch(() => null).finally(() => inFlight.delete(key));
|
|
1946
|
-
inFlight.set(key, flight);
|
|
1947
|
-
}
|
|
1948
|
-
const newEntry = await flight;
|
|
1949
|
-
if (newEntry)
|
|
1950
|
-
return serveFromEntry(newEntry, req);
|
|
1951
|
-
}
|
|
1952
|
-
return handler(req, ctx);
|
|
1953
|
-
};
|
|
1954
|
-
}
|
|
1955
1930
|
var SSR_FILENAME = "index.ssr.js";
|
|
1956
1931
|
var __dirname2 = process.cwd();
|
|
1957
1932
|
var getSuffix = (mode) => mode === "development" ? `?v=${Date.now()}` : "";
|
|
@@ -1980,10 +1955,8 @@ var resolveWorkerCmd = (packageDir2) => {
|
|
|
1980
1955
|
const allArgs = [...process.execArgv, process.argv[1] ?? ""];
|
|
1981
1956
|
const hasTsx = allArgs.some((a) => a.includes("tsx"));
|
|
1982
1957
|
const hasTsNode = allArgs.some((a) => a.includes("ts-node"));
|
|
1983
|
-
if (hasTsx)
|
|
1984
|
-
|
|
1985
|
-
if (hasTsNode)
|
|
1986
|
-
return ["ts-node", tsPath];
|
|
1958
|
+
if (hasTsx) return ["tsx", tsPath];
|
|
1959
|
+
if (hasTsNode) return ["ts-node", tsPath];
|
|
1987
1960
|
}
|
|
1988
1961
|
if (existsSync2(jsPath)) {
|
|
1989
1962
|
return ["node", jsPath];
|
|
@@ -2030,6 +2003,7 @@ var dev = async (options) => {
|
|
|
2030
2003
|
swcPlugins: options.swcPlugins,
|
|
2031
2004
|
define: options.define,
|
|
2032
2005
|
moduleRules: options.moduleRules,
|
|
2006
|
+
plugins: options.plugins,
|
|
2033
2007
|
reactMode: options.reactMode,
|
|
2034
2008
|
htmlTemplate: resolvedHtmlTemplate
|
|
2035
2009
|
});
|
|
@@ -2073,8 +2047,7 @@ var dev = async (options) => {
|
|
|
2073
2047
|
child.stdin?.end();
|
|
2074
2048
|
const cleanupChild = () => {
|
|
2075
2049
|
try {
|
|
2076
|
-
if (!child.killed)
|
|
2077
|
-
child.kill();
|
|
2050
|
+
if (!child.killed) child.kill();
|
|
2078
2051
|
} catch {
|
|
2079
2052
|
}
|
|
2080
2053
|
};
|
|
@@ -2133,8 +2106,7 @@ var dev = async (options) => {
|
|
|
2133
2106
|
try {
|
|
2134
2107
|
while (true) {
|
|
2135
2108
|
const { done, value } = await reader.read();
|
|
2136
|
-
if (done)
|
|
2137
|
-
break;
|
|
2109
|
+
if (done) break;
|
|
2138
2110
|
const chunk = decoder.decode(value, { stream: true });
|
|
2139
2111
|
try {
|
|
2140
2112
|
process.stdout.write(chunk);
|
|
@@ -2155,8 +2127,7 @@ var dev = async (options) => {
|
|
|
2155
2127
|
const r = stderrWebStream.getReader();
|
|
2156
2128
|
while (true) {
|
|
2157
2129
|
const { done, value } = await r.read();
|
|
2158
|
-
if (done)
|
|
2159
|
-
break;
|
|
2130
|
+
if (done) break;
|
|
2160
2131
|
try {
|
|
2161
2132
|
process.stderr.write(decoder.decode(value));
|
|
2162
2133
|
} catch (e) {
|
|
@@ -2173,23 +2144,18 @@ var dev = async (options) => {
|
|
|
2173
2144
|
const request = parseRequest(req);
|
|
2174
2145
|
if (handler) {
|
|
2175
2146
|
const res = await handler(request);
|
|
2176
|
-
if (res)
|
|
2177
|
-
return res;
|
|
2147
|
+
if (res) return res;
|
|
2178
2148
|
}
|
|
2179
|
-
if (handleWS && handleWS(request, ctx))
|
|
2180
|
-
return void 0;
|
|
2149
|
+
if (handleWS && handleWS(request, ctx)) return void 0;
|
|
2181
2150
|
const proxied = await handleProxy(request);
|
|
2182
|
-
if (proxied)
|
|
2183
|
-
return proxied;
|
|
2151
|
+
if (proxied) return proxied;
|
|
2184
2152
|
const url = new URL(request.url);
|
|
2185
2153
|
const path2 = url.pathname;
|
|
2186
2154
|
const staticRes = await tryServeFile(pathMod2.join(__dirname2, StaticPath, path2));
|
|
2187
|
-
if (staticRes)
|
|
2188
|
-
return staticRes;
|
|
2155
|
+
if (staticRes) return staticRes;
|
|
2189
2156
|
const projectStaticPath = pathMod2.resolve(process.cwd(), "static");
|
|
2190
2157
|
const projectRes = await tryServeFile(pathMod2.join(projectStaticPath, path2));
|
|
2191
|
-
if (projectRes)
|
|
2192
|
-
return projectRes;
|
|
2158
|
+
if (projectRes) return projectRes;
|
|
2193
2159
|
const ssrComponentPath = pathMod2.join(__dirname2, HadarsFolder, SSR_FILENAME);
|
|
2194
2160
|
const importPath = pathToFileURL(ssrComponentPath).href + `?t=${ssrBuildId}`;
|
|
2195
2161
|
try {
|
|
@@ -2256,6 +2222,7 @@ var build = async (options) => {
|
|
|
2256
2222
|
swcPlugins: options.swcPlugins,
|
|
2257
2223
|
define: options.define,
|
|
2258
2224
|
moduleRules: options.moduleRules,
|
|
2225
|
+
plugins: options.plugins,
|
|
2259
2226
|
optimization: options.optimization,
|
|
2260
2227
|
reactMode: options.reactMode,
|
|
2261
2228
|
htmlTemplate: resolvedHtmlTemplate
|
|
@@ -2273,7 +2240,8 @@ var build = async (options) => {
|
|
|
2273
2240
|
mode: "production",
|
|
2274
2241
|
swcPlugins: options.swcPlugins,
|
|
2275
2242
|
define: options.define,
|
|
2276
|
-
moduleRules: options.moduleRules
|
|
2243
|
+
moduleRules: options.moduleRules,
|
|
2244
|
+
plugins: options.plugins
|
|
2277
2245
|
})
|
|
2278
2246
|
]);
|
|
2279
2247
|
await fs.rm(tmpFilePath);
|
|
@@ -2316,30 +2284,24 @@ var run = async (options) => {
|
|
|
2316
2284
|
const request = parseRequest(req);
|
|
2317
2285
|
if (handler) {
|
|
2318
2286
|
const res = await handler(request);
|
|
2319
|
-
if (res)
|
|
2320
|
-
return res;
|
|
2287
|
+
if (res) return res;
|
|
2321
2288
|
}
|
|
2322
|
-
if (handleWS && handleWS(request, ctx))
|
|
2323
|
-
return void 0;
|
|
2289
|
+
if (handleWS && handleWS(request, ctx)) return void 0;
|
|
2324
2290
|
const proxied = await handleProxy(request);
|
|
2325
|
-
if (proxied)
|
|
2326
|
-
return proxied;
|
|
2291
|
+
if (proxied) return proxied;
|
|
2327
2292
|
const url = new URL(request.url);
|
|
2328
2293
|
const path2 = url.pathname;
|
|
2329
2294
|
const staticRes = await tryServeFile(pathMod2.join(__dirname2, StaticPath, path2));
|
|
2330
|
-
if (staticRes)
|
|
2331
|
-
return staticRes;
|
|
2295
|
+
if (staticRes) return staticRes;
|
|
2332
2296
|
const projectStaticPath = pathMod2.resolve(process.cwd(), "static");
|
|
2333
2297
|
const projectRes = await tryServeFile(pathMod2.join(projectStaticPath, path2));
|
|
2334
|
-
if (projectRes)
|
|
2335
|
-
return projectRes;
|
|
2298
|
+
if (projectRes) return projectRes;
|
|
2336
2299
|
const routeClean = path2.replace(/(^\/|\/$)/g, "");
|
|
2337
2300
|
if (routeClean) {
|
|
2338
2301
|
const routeRes = await tryServeFile(
|
|
2339
2302
|
pathMod2.join(__dirname2, StaticPath, routeClean, "index.html")
|
|
2340
2303
|
);
|
|
2341
|
-
if (routeRes)
|
|
2342
|
-
return routeRes;
|
|
2304
|
+
if (routeRes) return routeRes;
|
|
2343
2305
|
}
|
|
2344
2306
|
const componentPath = pathToFileURL(
|
|
2345
2307
|
pathMod2.resolve(__dirname2, HadarsFolder, SSR_FILENAME)
|
|
@@ -2394,8 +2356,7 @@ var SUPPORTED = ["hadars.config.js", "hadars.config.mjs", "hadars.config.cjs", "
|
|
|
2394
2356
|
function findConfig(cwd) {
|
|
2395
2357
|
for (const name of SUPPORTED) {
|
|
2396
2358
|
const p = resolve(cwd, name);
|
|
2397
|
-
if (existsSync3(p))
|
|
2398
|
-
return p;
|
|
2359
|
+
if (existsSync3(p)) return p;
|
|
2399
2360
|
}
|
|
2400
2361
|
return null;
|
|
2401
2362
|
}
|
|
@@ -2423,6 +2384,61 @@ async function loadConfig(configPath) {
|
|
|
2423
2384
|
const mod = await import(url);
|
|
2424
2385
|
return mod && (mod.default ?? mod);
|
|
2425
2386
|
}
|
|
2387
|
+
async function bundleLambda(config, configPath, outputFile, cwd) {
|
|
2388
|
+
console.log("Building hadars project...");
|
|
2389
|
+
await build({ ...config, mode: "production" });
|
|
2390
|
+
const ssrBundle = resolve(cwd, ".hadars", "index.ssr.js");
|
|
2391
|
+
const outHtml = resolve(cwd, ".hadars", "static", "out.html");
|
|
2392
|
+
if (!existsSync3(ssrBundle)) {
|
|
2393
|
+
console.error(`SSR bundle not found: ${ssrBundle}`);
|
|
2394
|
+
process.exit(1);
|
|
2395
|
+
}
|
|
2396
|
+
if (!existsSync3(outHtml)) {
|
|
2397
|
+
console.error(`HTML template not found: ${outHtml}`);
|
|
2398
|
+
process.exit(1);
|
|
2399
|
+
}
|
|
2400
|
+
const lambdaModule = resolve(dirname(fileURLToPath3(import.meta.url)), "lambda.js");
|
|
2401
|
+
const shimPath = join(cwd, `.hadars-lambda-shim-${Date.now()}.ts`);
|
|
2402
|
+
const shim = [
|
|
2403
|
+
`import * as ssrModule from ${JSON.stringify(ssrBundle)};`,
|
|
2404
|
+
`import outHtml from ${JSON.stringify(outHtml)};`,
|
|
2405
|
+
`import { createLambdaHandler } from ${JSON.stringify(lambdaModule)};`,
|
|
2406
|
+
`import config from ${JSON.stringify(configPath)};`,
|
|
2407
|
+
`export const handler = createLambdaHandler(config as any, { ssrModule: ssrModule as any, outHtml });`
|
|
2408
|
+
].join("\n") + "\n";
|
|
2409
|
+
await writeFile(shimPath, shim, "utf-8");
|
|
2410
|
+
try {
|
|
2411
|
+
const { build: esbuild } = await import("esbuild");
|
|
2412
|
+
console.log(`Bundling Lambda handler \u2192 ${outputFile}`);
|
|
2413
|
+
await esbuild({
|
|
2414
|
+
entryPoints: [shimPath],
|
|
2415
|
+
bundle: true,
|
|
2416
|
+
platform: "node",
|
|
2417
|
+
format: "esm",
|
|
2418
|
+
target: ["node20"],
|
|
2419
|
+
outfile: outputFile,
|
|
2420
|
+
sourcemap: false,
|
|
2421
|
+
loader: { ".html": "text", ".tsx": "tsx", ".ts": "ts" },
|
|
2422
|
+
// @rspack/* contains native binaries and is build-time only —
|
|
2423
|
+
// it is never imported at Lambda runtime, so mark it external.
|
|
2424
|
+
// Everything else (React, hadars runtime, etc.) is bundled in to
|
|
2425
|
+
// produce a truly self-contained single-file deployment.
|
|
2426
|
+
external: ["@rspack/*"]
|
|
2427
|
+
});
|
|
2428
|
+
console.log(`Lambda bundle written to ${outputFile}`);
|
|
2429
|
+
console.log(`
|
|
2430
|
+
Deploy instructions:`);
|
|
2431
|
+
console.log(` 1. Create a staging directory with just this file:`);
|
|
2432
|
+
console.log(` mkdir -p lambda-deploy && cp ${outputFile} lambda-deploy/lambda.mjs`);
|
|
2433
|
+
console.log(` 2. Upload lambda-deploy/ as your Lambda function code`);
|
|
2434
|
+
console.log(` 3. Set handler to: lambda.handler (runtime: Node.js 20.x)`);
|
|
2435
|
+
console.log(` 4. Upload .hadars/static/ assets to S3 and serve via CloudFront`);
|
|
2436
|
+
console.log(` (the Lambda handler does not serve static JS/CSS \u2014 route those to S3)`);
|
|
2437
|
+
} finally {
|
|
2438
|
+
await unlink(shimPath).catch(() => {
|
|
2439
|
+
});
|
|
2440
|
+
}
|
|
2441
|
+
}
|
|
2426
2442
|
var TEMPLATES = {
|
|
2427
2443
|
"package.json": (name) => JSON.stringify({
|
|
2428
2444
|
name,
|
|
@@ -2676,7 +2692,7 @@ Done! Next steps:
|
|
|
2676
2692
|
`);
|
|
2677
2693
|
}
|
|
2678
2694
|
function usage() {
|
|
2679
|
-
console.log("Usage: hadars <new <name> | dev | build | run>");
|
|
2695
|
+
console.log("Usage: hadars <new <name> | dev | build | run | export lambda [output.mjs]>");
|
|
2680
2696
|
}
|
|
2681
2697
|
async function runCli(argv, cwd = process.cwd()) {
|
|
2682
2698
|
const cmd = argv[2];
|
|
@@ -2694,7 +2710,7 @@ async function runCli(argv, cwd = process.cwd()) {
|
|
|
2694
2710
|
}
|
|
2695
2711
|
return;
|
|
2696
2712
|
}
|
|
2697
|
-
if (!cmd || !["dev", "build", "run"].includes(cmd)) {
|
|
2713
|
+
if (!cmd || !["dev", "build", "run", "export"].includes(cmd)) {
|
|
2698
2714
|
usage();
|
|
2699
2715
|
process.exit(1);
|
|
2700
2716
|
}
|
|
@@ -2717,6 +2733,16 @@ async function runCli(argv, cwd = process.cwd()) {
|
|
|
2717
2733
|
await build2(cfg);
|
|
2718
2734
|
console.log("Build complete");
|
|
2719
2735
|
process.exit(0);
|
|
2736
|
+
case "export": {
|
|
2737
|
+
const subCmd = argv[3];
|
|
2738
|
+
if (subCmd !== "lambda") {
|
|
2739
|
+
console.error(`Unknown export target: ${subCmd ?? "(none)"}. Did you mean: hadars export lambda`);
|
|
2740
|
+
process.exit(1);
|
|
2741
|
+
}
|
|
2742
|
+
const outputFile = resolve(cwd, argv[4] ?? "lambda.mjs");
|
|
2743
|
+
await bundleLambda(cfg, configPath, outputFile, cwd);
|
|
2744
|
+
process.exit(0);
|
|
2745
|
+
}
|
|
2720
2746
|
case "run":
|
|
2721
2747
|
console.log("Running project...");
|
|
2722
2748
|
await run2(cfg);
|
|
@@ -2741,11 +2767,9 @@ if (typeof globalThis.Bun === "undefined" && typeof globalThis.Deno === "undefin
|
|
|
2741
2767
|
} catch {
|
|
2742
2768
|
}
|
|
2743
2769
|
};
|
|
2744
|
-
for (const sig of sigs)
|
|
2745
|
-
process.on(sig, fwd(sig));
|
|
2770
|
+
for (const sig of sigs) process.on(sig, fwd(sig));
|
|
2746
2771
|
child.on("error", (err) => {
|
|
2747
|
-
for (const sig of sigs)
|
|
2748
|
-
process.removeAllListeners(sig);
|
|
2772
|
+
for (const sig of sigs) process.removeAllListeners(sig);
|
|
2749
2773
|
if (err.code !== "ENOENT") {
|
|
2750
2774
|
console.error(err);
|
|
2751
2775
|
process.exit(1);
|