@lytjs/ssr 6.0.0 → 6.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +482 -6
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +241 -1
- package/dist/index.d.ts +241 -1
- package/dist/index.mjs +470 -7
- package/dist/index.mjs.map +1 -1
- package/package.json +4 -4
package/dist/index.mjs
CHANGED
|
@@ -183,6 +183,38 @@ var VirtualList = defineComponent({
|
|
|
183
183
|
}
|
|
184
184
|
});
|
|
185
185
|
var DEFAULT_CHUNK_SIZE = 4096;
|
|
186
|
+
var DEFAULT_TIMEOUT = 3e4;
|
|
187
|
+
var DEFAULT_FALLBACK_HTML = '<div id="lyt-fallback">\u670D\u52A1\u6B63\u5728\u52A0\u8F7D\u4E2D...</div>';
|
|
188
|
+
var StreamTimeoutError = class extends Error {
|
|
189
|
+
constructor(message = "Stream rendering timeout") {
|
|
190
|
+
super(message);
|
|
191
|
+
this.name = "StreamTimeoutError";
|
|
192
|
+
}
|
|
193
|
+
};
|
|
194
|
+
var FlowController = class {
|
|
195
|
+
constructor(maxBytesPerSecond) {
|
|
196
|
+
this.bytesSentInSecond = 0;
|
|
197
|
+
this.lastSecondTimestamp = Date.now();
|
|
198
|
+
this.maxBytesPerSecond = maxBytesPerSecond;
|
|
199
|
+
}
|
|
200
|
+
/**
|
|
201
|
+
* 尝试发送字节,如超出速率则等待
|
|
202
|
+
*/
|
|
203
|
+
async waitForRateLimit(byteCount) {
|
|
204
|
+
const now = Date.now();
|
|
205
|
+
if (now - this.lastSecondTimestamp >= 1e3) {
|
|
206
|
+
this.bytesSentInSecond = 0;
|
|
207
|
+
this.lastSecondTimestamp = now;
|
|
208
|
+
}
|
|
209
|
+
if (this.bytesSentInSecond + byteCount > this.maxBytesPerSecond) {
|
|
210
|
+
const waitTime = 1e3 - (now - this.lastSecondTimestamp);
|
|
211
|
+
await new Promise((resolve) => setTimeout(resolve, waitTime));
|
|
212
|
+
this.bytesSentInSecond = 0;
|
|
213
|
+
this.lastSecondTimestamp = Date.now();
|
|
214
|
+
}
|
|
215
|
+
this.bytesSentInSecond += byteCount;
|
|
216
|
+
}
|
|
217
|
+
};
|
|
186
218
|
var SUSPENSE_TYPE = "Suspense";
|
|
187
219
|
function isSuspenseVNode(vnode) {
|
|
188
220
|
return isObject(vnode) && (typeof vnode.type === "object" && vnode.type !== null && "__suspense" in vnode.type || isString(vnode.type) && vnode.type === SUSPENSE_TYPE);
|
|
@@ -254,11 +286,32 @@ function renderToStream(vnode, options) {
|
|
|
254
286
|
const {
|
|
255
287
|
chunkSize = DEFAULT_CHUNK_SIZE,
|
|
256
288
|
onShellReady,
|
|
257
|
-
onError
|
|
289
|
+
onError,
|
|
290
|
+
timeout = DEFAULT_TIMEOUT,
|
|
291
|
+
fallbackHtml = DEFAULT_FALLBACK_HTML,
|
|
292
|
+
maxBytesPerSecond,
|
|
293
|
+
errorRecovery = true
|
|
258
294
|
} = options || {};
|
|
259
295
|
const encoder = new TextEncoder();
|
|
296
|
+
let flowController = maxBytesPerSecond ? new FlowController(maxBytesPerSecond) : null;
|
|
297
|
+
let timeoutId = null;
|
|
260
298
|
return new ReadableStream({
|
|
261
299
|
start(controller) {
|
|
300
|
+
timeoutId = setTimeout(() => {
|
|
301
|
+
try {
|
|
302
|
+
if (errorRecovery) {
|
|
303
|
+
console.warn("Stream rendering timed out, using fallback HTML");
|
|
304
|
+
controller.enqueue(encoder.encode(fallbackHtml));
|
|
305
|
+
controller.close();
|
|
306
|
+
onError?.(new StreamTimeoutError("Stream rendering timed out"));
|
|
307
|
+
} else {
|
|
308
|
+
controller.error(new StreamTimeoutError("Stream rendering timed out"));
|
|
309
|
+
}
|
|
310
|
+
} catch (err) {
|
|
311
|
+
const error = err instanceof Error ? err : new Error(String(err));
|
|
312
|
+
onError?.(error);
|
|
313
|
+
}
|
|
314
|
+
}, timeout);
|
|
262
315
|
try {
|
|
263
316
|
const suspenseBoundaryIndex = [];
|
|
264
317
|
const chunks = collectChunks(vnode, suspenseBoundaryIndex);
|
|
@@ -269,29 +322,64 @@ function renderToStream(vnode, options) {
|
|
|
269
322
|
const shellHtml = shellChunks.join("");
|
|
270
323
|
const byteChunks = splitIntoByteChunks(shellHtml, chunkSize);
|
|
271
324
|
for (const chunk of byteChunks) {
|
|
272
|
-
controller
|
|
325
|
+
sendChunk(controller, encoder, chunk);
|
|
273
326
|
}
|
|
274
327
|
onShellReady?.();
|
|
275
328
|
const remainingChunks = chunks.slice(shellBoundary);
|
|
276
329
|
const remainingHtml = remainingChunks.join("");
|
|
277
330
|
const remainingByteChunks = splitIntoByteChunks(remainingHtml, chunkSize);
|
|
278
331
|
for (const chunk of remainingByteChunks) {
|
|
279
|
-
controller
|
|
332
|
+
sendChunk(controller, encoder, chunk);
|
|
280
333
|
}
|
|
281
334
|
} else {
|
|
282
335
|
const byteChunks = splitIntoByteChunks(fullHtml, chunkSize);
|
|
283
336
|
for (const chunk of byteChunks) {
|
|
284
|
-
controller
|
|
337
|
+
sendChunk(controller, encoder, chunk);
|
|
285
338
|
}
|
|
286
339
|
}
|
|
340
|
+
if (timeoutId) {
|
|
341
|
+
clearTimeout(timeoutId);
|
|
342
|
+
timeoutId = null;
|
|
343
|
+
}
|
|
287
344
|
controller.close();
|
|
288
345
|
} catch (err) {
|
|
346
|
+
if (timeoutId) {
|
|
347
|
+
clearTimeout(timeoutId);
|
|
348
|
+
timeoutId = null;
|
|
349
|
+
}
|
|
289
350
|
const error = err instanceof Error ? err : new Error(String(err));
|
|
290
351
|
onError?.(error);
|
|
291
|
-
|
|
352
|
+
if (errorRecovery) {
|
|
353
|
+
try {
|
|
354
|
+
console.warn("Error occurred during stream rendering, using fallback HTML");
|
|
355
|
+
controller.enqueue(encoder.encode(fallbackHtml));
|
|
356
|
+
controller.close();
|
|
357
|
+
} catch (e) {
|
|
358
|
+
controller.error(error);
|
|
359
|
+
}
|
|
360
|
+
} else {
|
|
361
|
+
controller.error(error);
|
|
362
|
+
}
|
|
363
|
+
}
|
|
364
|
+
},
|
|
365
|
+
cancel(reason) {
|
|
366
|
+
if (timeoutId) {
|
|
367
|
+
clearTimeout(timeoutId);
|
|
292
368
|
}
|
|
369
|
+
console.log("Stream cancelled:", reason);
|
|
293
370
|
}
|
|
294
371
|
});
|
|
372
|
+
function sendChunk(controller, encoder2, chunk) {
|
|
373
|
+
const encoded = encoder2.encode(chunk);
|
|
374
|
+
if (flowController) {
|
|
375
|
+
(async () => {
|
|
376
|
+
await flowController.waitForRateLimit(encoded.length);
|
|
377
|
+
controller.enqueue(encoded);
|
|
378
|
+
})();
|
|
379
|
+
} else {
|
|
380
|
+
controller.enqueue(encoded);
|
|
381
|
+
}
|
|
382
|
+
}
|
|
295
383
|
}
|
|
296
384
|
function renderToStreamAsync(vnode, options) {
|
|
297
385
|
const {
|
|
@@ -433,7 +521,12 @@ var DEFAULT_SSG_OPTIONS = {
|
|
|
433
521
|
siteName: "LytJS Site",
|
|
434
522
|
hashMode: false,
|
|
435
523
|
globalScripts: [],
|
|
436
|
-
globalStyles: []
|
|
524
|
+
globalStyles: [],
|
|
525
|
+
isr: {
|
|
526
|
+
revalidate: 60,
|
|
527
|
+
enabled: false,
|
|
528
|
+
fallback: false
|
|
529
|
+
}
|
|
437
530
|
};
|
|
438
531
|
function normalizePath(path) {
|
|
439
532
|
let normalized = path.startsWith("/") ? path : `/${path}`;
|
|
@@ -552,6 +645,376 @@ function validatePages(pages) {
|
|
|
552
645
|
}
|
|
553
646
|
return errors;
|
|
554
647
|
}
|
|
648
|
+
var ISRCacheManager = class {
|
|
649
|
+
constructor() {
|
|
650
|
+
this.cache = /* @__PURE__ */ new Map();
|
|
651
|
+
this.revalidateTasks = /* @__PURE__ */ new Map();
|
|
652
|
+
}
|
|
653
|
+
/**
|
|
654
|
+
* 获取缓存的页面
|
|
655
|
+
*/
|
|
656
|
+
get(path) {
|
|
657
|
+
return this.cache.get(path);
|
|
658
|
+
}
|
|
659
|
+
/**
|
|
660
|
+
* 设置缓存
|
|
661
|
+
*/
|
|
662
|
+
set(path, html) {
|
|
663
|
+
this.cache.set(path, {
|
|
664
|
+
html,
|
|
665
|
+
timestamp: Date.now(),
|
|
666
|
+
isRevalidating: false
|
|
667
|
+
});
|
|
668
|
+
}
|
|
669
|
+
/**
|
|
670
|
+
* 检查是否需要重新验证
|
|
671
|
+
*/
|
|
672
|
+
needsRevalidation(path, revalidateSeconds) {
|
|
673
|
+
const entry = this.cache.get(path);
|
|
674
|
+
if (!entry) return true;
|
|
675
|
+
const age = (Date.now() - entry.timestamp) / 1e3;
|
|
676
|
+
return age > revalidateSeconds && !entry.isRevalidating;
|
|
677
|
+
}
|
|
678
|
+
/**
|
|
679
|
+
* 标记为正在重新生成
|
|
680
|
+
*/
|
|
681
|
+
markRevalidating(path) {
|
|
682
|
+
const entry = this.cache.get(path);
|
|
683
|
+
if (entry) {
|
|
684
|
+
entry.isRevalidating = true;
|
|
685
|
+
}
|
|
686
|
+
}
|
|
687
|
+
/**
|
|
688
|
+
* 完成重新生成
|
|
689
|
+
*/
|
|
690
|
+
finishRevalidation(path, html) {
|
|
691
|
+
this.set(path, html);
|
|
692
|
+
this.revalidateTasks.delete(path);
|
|
693
|
+
}
|
|
694
|
+
/**
|
|
695
|
+
* 获取正在进行的重新生成任务
|
|
696
|
+
*/
|
|
697
|
+
getRevalidateTask(path) {
|
|
698
|
+
return this.revalidateTasks.get(path);
|
|
699
|
+
}
|
|
700
|
+
/**
|
|
701
|
+
* 设置重新生成任务
|
|
702
|
+
*/
|
|
703
|
+
setRevalidateTask(path, task) {
|
|
704
|
+
this.revalidateTasks.set(path, task);
|
|
705
|
+
}
|
|
706
|
+
/**
|
|
707
|
+
* 清除过期的缓存
|
|
708
|
+
*/
|
|
709
|
+
clearExpired(maxAgeSeconds) {
|
|
710
|
+
const now = Date.now();
|
|
711
|
+
let cleared = 0;
|
|
712
|
+
for (const [path, entry] of this.cache) {
|
|
713
|
+
const age = (now - entry.timestamp) / 1e3;
|
|
714
|
+
if (age > maxAgeSeconds) {
|
|
715
|
+
this.cache.delete(path);
|
|
716
|
+
cleared++;
|
|
717
|
+
}
|
|
718
|
+
}
|
|
719
|
+
return cleared;
|
|
720
|
+
}
|
|
721
|
+
/**
|
|
722
|
+
* 获取缓存统计信息
|
|
723
|
+
*/
|
|
724
|
+
getStats() {
|
|
725
|
+
return {
|
|
726
|
+
total: this.cache.size,
|
|
727
|
+
paths: Array.from(this.cache.keys())
|
|
728
|
+
};
|
|
729
|
+
}
|
|
730
|
+
};
|
|
731
|
+
var isrCache = new ISRCacheManager();
|
|
732
|
+
function createISRMiddleware(options) {
|
|
733
|
+
const { staticPages, revalidate = 60, enabled = true, regenerate } = options;
|
|
734
|
+
for (const [path, html] of staticPages) {
|
|
735
|
+
isrCache.set(path, html);
|
|
736
|
+
}
|
|
737
|
+
return async (req, res, next) => {
|
|
738
|
+
if (!enabled) {
|
|
739
|
+
return next();
|
|
740
|
+
}
|
|
741
|
+
let path = req.path;
|
|
742
|
+
if (path.endsWith("/")) {
|
|
743
|
+
path = path + "index.html";
|
|
744
|
+
} else if (!path.endsWith(".html")) {
|
|
745
|
+
path = path + "/index.html";
|
|
746
|
+
}
|
|
747
|
+
const cached = isrCache.get(path);
|
|
748
|
+
if (cached) {
|
|
749
|
+
res.setHeader("Cache-Control", `s-maxage=${revalidate}, stale-while-revalidate`);
|
|
750
|
+
res.setHeader("X-ISR-Cache", "HIT");
|
|
751
|
+
res.setHeader("X-ISR-Timestamp", cached.timestamp.toString());
|
|
752
|
+
res.send(cached.html);
|
|
753
|
+
if (isrCache.needsRevalidation(path, revalidate) && regenerate) {
|
|
754
|
+
isrCache.markRevalidating(path);
|
|
755
|
+
try {
|
|
756
|
+
const newHtml = await regenerate(path);
|
|
757
|
+
isrCache.finishRevalidation(path, newHtml);
|
|
758
|
+
} catch (error) {
|
|
759
|
+
console.error("[ISR] Revalidation failed for", path, error);
|
|
760
|
+
const entry = isrCache.get(path);
|
|
761
|
+
if (entry) {
|
|
762
|
+
entry.isRevalidating = false;
|
|
763
|
+
}
|
|
764
|
+
}
|
|
765
|
+
}
|
|
766
|
+
} else {
|
|
767
|
+
if (regenerate) {
|
|
768
|
+
try {
|
|
769
|
+
const html = await regenerate(path);
|
|
770
|
+
isrCache.set(path, html);
|
|
771
|
+
res.setHeader("X-ISR-Cache", "MISS");
|
|
772
|
+
res.send(html);
|
|
773
|
+
} catch (error) {
|
|
774
|
+
next(error);
|
|
775
|
+
}
|
|
776
|
+
} else {
|
|
777
|
+
next();
|
|
778
|
+
}
|
|
779
|
+
}
|
|
780
|
+
};
|
|
781
|
+
}
|
|
782
|
+
async function revalidateOnDemand(path, regenerate) {
|
|
783
|
+
const existingTask = isrCache.getRevalidateTask(path);
|
|
784
|
+
if (existingTask) {
|
|
785
|
+
return existingTask;
|
|
786
|
+
}
|
|
787
|
+
const task = (async () => {
|
|
788
|
+
isrCache.markRevalidating(path);
|
|
789
|
+
try {
|
|
790
|
+
const html = await regenerate();
|
|
791
|
+
isrCache.finishRevalidation(path, html);
|
|
792
|
+
return html;
|
|
793
|
+
} catch (error) {
|
|
794
|
+
const entry = isrCache.get(path);
|
|
795
|
+
if (entry) {
|
|
796
|
+
entry.isRevalidating = false;
|
|
797
|
+
}
|
|
798
|
+
throw error;
|
|
799
|
+
}
|
|
800
|
+
})();
|
|
801
|
+
isrCache.setRevalidateTask(path, task);
|
|
802
|
+
return task;
|
|
803
|
+
}
|
|
804
|
+
function getISRCacheStats() {
|
|
805
|
+
return isrCache.getStats();
|
|
806
|
+
}
|
|
807
|
+
function clearISRCache(path, maxAge) {
|
|
808
|
+
if (path) {
|
|
809
|
+
const cache = isrCache.cache;
|
|
810
|
+
cache.delete(path);
|
|
811
|
+
} else if (maxAge) {
|
|
812
|
+
isrCache.clearExpired(maxAge);
|
|
813
|
+
}
|
|
814
|
+
}
|
|
815
|
+
var ServerComponentStateManager = class {
|
|
816
|
+
constructor() {
|
|
817
|
+
/** 注册的组件 */
|
|
818
|
+
this.registrations = /* @__PURE__ */ new Map();
|
|
819
|
+
/** 正在执行的预取请求 */
|
|
820
|
+
this.pendingPrefetches = /* @__PURE__ */ new Map();
|
|
821
|
+
/** 组件初始化状态 */
|
|
822
|
+
this.initializationStates = /* @__PURE__ */ new Map();
|
|
823
|
+
}
|
|
824
|
+
/**
|
|
825
|
+
* 注册服务端组件
|
|
826
|
+
*/
|
|
827
|
+
register(name, registration) {
|
|
828
|
+
this.registrations.set(name, registration);
|
|
829
|
+
}
|
|
830
|
+
/**
|
|
831
|
+
* 取消注册服务端组件
|
|
832
|
+
*/
|
|
833
|
+
unregister(name) {
|
|
834
|
+
this.registrations.delete(name);
|
|
835
|
+
}
|
|
836
|
+
/**
|
|
837
|
+
* 获取已注册的组件
|
|
838
|
+
*/
|
|
839
|
+
getRegistration(name) {
|
|
840
|
+
return this.registrations.get(name);
|
|
841
|
+
}
|
|
842
|
+
/**
|
|
843
|
+
* 初始化服务端组件
|
|
844
|
+
*/
|
|
845
|
+
async initializeComponent(name, context) {
|
|
846
|
+
const registration = this.registrations.get(name);
|
|
847
|
+
if (!registration) {
|
|
848
|
+
throw new Error(`Server component ${name} not registered`);
|
|
849
|
+
}
|
|
850
|
+
if (this.initializationStates.get(name)) {
|
|
851
|
+
return;
|
|
852
|
+
}
|
|
853
|
+
if (registration.onServerInit) {
|
|
854
|
+
await Promise.resolve(registration.onServerInit(context));
|
|
855
|
+
}
|
|
856
|
+
this.initializationStates.set(name, true);
|
|
857
|
+
}
|
|
858
|
+
/**
|
|
859
|
+
* 清理服务端组件
|
|
860
|
+
*/
|
|
861
|
+
async cleanupComponent(name, context) {
|
|
862
|
+
const registration = this.registrations.get(name);
|
|
863
|
+
if (!registration) {
|
|
864
|
+
return;
|
|
865
|
+
}
|
|
866
|
+
if (registration.onServerCleanup) {
|
|
867
|
+
await Promise.resolve(registration.onServerCleanup(context));
|
|
868
|
+
}
|
|
869
|
+
this.initializationStates.delete(name);
|
|
870
|
+
}
|
|
871
|
+
/**
|
|
872
|
+
* 预取组件数据(带缓存)
|
|
873
|
+
*/
|
|
874
|
+
async prefetchComponentData(name, context, cacheKey) {
|
|
875
|
+
const registration = this.registrations.get(name);
|
|
876
|
+
if (!registration || !registration.prefetch) {
|
|
877
|
+
return { data: {} };
|
|
878
|
+
}
|
|
879
|
+
const key = cacheKey || `${name}-${JSON.stringify(context)}`;
|
|
880
|
+
const existing = this.pendingPrefetches.get(key);
|
|
881
|
+
if (existing) {
|
|
882
|
+
return existing;
|
|
883
|
+
}
|
|
884
|
+
const promise = registration.prefetch(context).finally(() => {
|
|
885
|
+
this.pendingPrefetches.delete(key);
|
|
886
|
+
});
|
|
887
|
+
this.pendingPrefetches.set(key, promise);
|
|
888
|
+
return promise;
|
|
889
|
+
}
|
|
890
|
+
/**
|
|
891
|
+
* 清除所有缓存
|
|
892
|
+
*/
|
|
893
|
+
clearAll() {
|
|
894
|
+
this.registrations.clear();
|
|
895
|
+
this.pendingPrefetches.clear();
|
|
896
|
+
this.initializationStates.clear();
|
|
897
|
+
}
|
|
898
|
+
};
|
|
899
|
+
var stateManager = new ServerComponentStateManager();
|
|
900
|
+
function registerServerComponent(name, registration) {
|
|
901
|
+
stateManager.register(name, registration);
|
|
902
|
+
}
|
|
903
|
+
function unregisterServerComponent(name) {
|
|
904
|
+
stateManager.unregister(name);
|
|
905
|
+
}
|
|
906
|
+
function collectPrefetchComponents(vnode) {
|
|
907
|
+
const components = [];
|
|
908
|
+
collectComponentsRecursive(vnode, components);
|
|
909
|
+
return components;
|
|
910
|
+
}
|
|
911
|
+
function collectComponentsRecursive(vnode, result) {
|
|
912
|
+
if (!isObject(vnode)) {
|
|
913
|
+
return;
|
|
914
|
+
}
|
|
915
|
+
const node = vnode;
|
|
916
|
+
if (isArray(vnode)) {
|
|
917
|
+
for (const child of vnode) {
|
|
918
|
+
collectComponentsRecursive(child, result);
|
|
919
|
+
}
|
|
920
|
+
return;
|
|
921
|
+
}
|
|
922
|
+
if (isFunction(node.type)) {
|
|
923
|
+
const compName = node.type.name;
|
|
924
|
+
if (compName && stateManager.getRegistration(compName)) {
|
|
925
|
+
if (!result.includes(compName)) {
|
|
926
|
+
result.push(compName);
|
|
927
|
+
}
|
|
928
|
+
}
|
|
929
|
+
}
|
|
930
|
+
const children = node.children;
|
|
931
|
+
if (isArray(children)) {
|
|
932
|
+
for (const child of children) {
|
|
933
|
+
collectComponentsRecursive(child, result);
|
|
934
|
+
}
|
|
935
|
+
} else if (isObject(children)) {
|
|
936
|
+
collectComponentsRecursive(children, result);
|
|
937
|
+
}
|
|
938
|
+
}
|
|
939
|
+
async function prefetchAllComponents(components, context) {
|
|
940
|
+
const results = {};
|
|
941
|
+
const promises = [];
|
|
942
|
+
for (const name of components) {
|
|
943
|
+
const promise = stateManager.prefetchComponentData(name, context).then((result) => {
|
|
944
|
+
results[name] = result;
|
|
945
|
+
}).catch((err) => {
|
|
946
|
+
console.warn(`Prefetch failed for component ${name}`, err);
|
|
947
|
+
results[name] = { data: {} };
|
|
948
|
+
});
|
|
949
|
+
promises.push(promise);
|
|
950
|
+
}
|
|
951
|
+
await Promise.all(promises);
|
|
952
|
+
return results;
|
|
953
|
+
}
|
|
954
|
+
function safeSerializeState(state) {
|
|
955
|
+
const seen = /* @__PURE__ */ new WeakSet();
|
|
956
|
+
return JSON.stringify(state, (_key, value) => {
|
|
957
|
+
if (typeof value === "object" && value !== null) {
|
|
958
|
+
if (seen.has(value)) {
|
|
959
|
+
return "[Circular]";
|
|
960
|
+
}
|
|
961
|
+
seen.add(value);
|
|
962
|
+
}
|
|
963
|
+
if (value instanceof Date) {
|
|
964
|
+
return { __type: "Date", value: value.toISOString() };
|
|
965
|
+
}
|
|
966
|
+
if (value instanceof RegExp) {
|
|
967
|
+
return { __type: "RegExp", source: value.source, flags: value.flags };
|
|
968
|
+
}
|
|
969
|
+
if (value instanceof Set) {
|
|
970
|
+
return { __type: "Set", values: Array.from(value) };
|
|
971
|
+
}
|
|
972
|
+
if (value instanceof Map) {
|
|
973
|
+
return { __type: "Map", entries: Array.from(value.entries()) };
|
|
974
|
+
}
|
|
975
|
+
return value;
|
|
976
|
+
});
|
|
977
|
+
}
|
|
978
|
+
function safeDeserializeState(serialized) {
|
|
979
|
+
return JSON.parse(serialized, (_key, value) => {
|
|
980
|
+
if (typeof value === "object" && value !== null && "__type" in value) {
|
|
981
|
+
const typedValue = value;
|
|
982
|
+
switch (typedValue.__type) {
|
|
983
|
+
case "Date":
|
|
984
|
+
return new Date(typedValue.value);
|
|
985
|
+
case "RegExp":
|
|
986
|
+
return new RegExp(typedValue.source, typedValue.flags);
|
|
987
|
+
case "Set":
|
|
988
|
+
return new Set(typedValue.values);
|
|
989
|
+
case "Map":
|
|
990
|
+
return new Map(typedValue.entries);
|
|
991
|
+
}
|
|
992
|
+
}
|
|
993
|
+
return value;
|
|
994
|
+
});
|
|
995
|
+
}
|
|
996
|
+
function buildDehydratedState(prefetchResults) {
|
|
997
|
+
const state = {};
|
|
998
|
+
for (const [name, result] of Object.entries(prefetchResults)) {
|
|
999
|
+
state[name] = {
|
|
1000
|
+
componentName: name,
|
|
1001
|
+
props: {},
|
|
1002
|
+
data: result.data
|
|
1003
|
+
};
|
|
1004
|
+
}
|
|
1005
|
+
return state;
|
|
1006
|
+
}
|
|
1007
|
+
function ServerComponent(options) {
|
|
1008
|
+
return function(target) {
|
|
1009
|
+
registerServerComponent(options.name, {
|
|
1010
|
+
name: options.name,
|
|
1011
|
+
render: target.render || (() => ({ type: "div" })),
|
|
1012
|
+
prefetch: options.prefetch,
|
|
1013
|
+
onServerInit: options.onInit,
|
|
1014
|
+
onServerCleanup: options.onCleanup
|
|
1015
|
+
});
|
|
1016
|
+
};
|
|
1017
|
+
}
|
|
555
1018
|
var HYDRATE_ATTR = "data-hydrate";
|
|
556
1019
|
var HYDRATE_STRATEGY_ATTR = "data-hydrate-strategy";
|
|
557
1020
|
var DEHYDRATED_STATE_ID = "__LYT_DEHYDRATED_STATE__";
|
|
@@ -717,6 +1180,6 @@ function createDehydratedState(vnode, initialState) {
|
|
|
717
1180
|
return `<script id="${DEHYDRATED_STATE_ID}" type="application/json">${safeJson}</script>`;
|
|
718
1181
|
}
|
|
719
1182
|
|
|
720
|
-
export { VirtualList, createDehydratedState, createHydrationMarkers, render_default as default, generateRouteManifest, generateStaticPages, getHydrationStrategy, renderToHtml, renderToStream, renderToStreamAsync, renderToStreamEnhanced, renderToString, resetComponentIdCounter, serializeHydrationState, validatePages, writeStaticFiles };
|
|
1183
|
+
export { ServerComponent, VirtualList, buildDehydratedState, clearISRCache, collectPrefetchComponents, createDehydratedState, createHydrationMarkers, createISRMiddleware, render_default as default, generateRouteManifest, generateStaticPages, getHydrationStrategy, getISRCacheStats, prefetchAllComponents, registerServerComponent, renderToHtml, renderToStream, renderToStreamAsync, renderToStreamEnhanced, renderToString, resetComponentIdCounter, revalidateOnDemand, safeDeserializeState, safeSerializeState, serializeHydrationState, stateManager, unregisterServerComponent, validatePages, writeStaticFiles };
|
|
721
1184
|
//# sourceMappingURL=index.mjs.map
|
|
722
1185
|
//# sourceMappingURL=index.mjs.map
|