@absolutejs/absolute 0.19.0-beta.350 → 0.19.0-beta.352

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.
@@ -1,9 +1,10 @@
1
- import { type AppendStreamingSlotsOptions, type StreamingSlot } from '../utils/streamingSlots';
1
+ import { type AppendStreamingSlotsOptions, type StreamingSlotPolicy, type StreamingSlot } from '../utils/streamingSlots';
2
2
  type ResponseLike = Response | Promise<Response>;
3
3
  export type StreamingSlotEnhancerOptions = Omit<AppendStreamingSlotsOptions, 'injectRuntime'> & {
4
4
  streamingSlots?: StreamingSlot[];
5
+ policy?: StreamingSlotPolicy;
5
6
  };
6
- export declare const enhanceHtmlResponseWithStreamingSlots: (response: Response, { nonce, onError, streamingSlots }?: StreamingSlotEnhancerOptions) => Response;
7
+ export declare const enhanceHtmlResponseWithStreamingSlots: (response: Response, { nonce, onError, streamingSlots, policy }?: StreamingSlotEnhancerOptions) => Response;
7
8
  export declare const withStreamingSlots: (responseLike: ResponseLike, options?: StreamingSlotEnhancerOptions) => Promise<Response>;
8
9
  export declare const withRegisteredStreamingSlots: (renderResponse: () => ResponseLike, options?: StreamingSlotEnhancerOptions) => Promise<Response>;
9
10
  export {};
@@ -5,4 +5,5 @@ export * from './defineEnv';
5
5
  export * from './getEnv';
6
6
  export * from './networking';
7
7
  export * from './registerClientScript';
8
+ export * from './streamingSlotMetricSink';
8
9
  export * from './streamingSlots';
@@ -0,0 +1,18 @@
1
+ import type { StreamingSlotMetric, StreamingSlotMetricHandler, StreamingSlotMetricType } from './streamingSlots';
2
+ export type StreamingSlotMetricMetadataValue = string | number | boolean | null;
3
+ export type StreamingSlotMetricMetadata = Record<string, StreamingSlotMetricMetadataValue>;
4
+ export type StreamingSlotMetricSinkEvent = StreamingSlotMetric & {
5
+ at: number;
6
+ route?: string;
7
+ metadata?: StreamingSlotMetricMetadata;
8
+ };
9
+ export type StreamingSlotMetricSinkOptions = {
10
+ onReport?: (metric: StreamingSlotMetricSinkEvent) => void | Promise<void>;
11
+ onError?: (error: unknown, metric: StreamingSlotMetricSinkEvent) => void;
12
+ route?: string;
13
+ metadata?: StreamingSlotMetricMetadata;
14
+ includeTypes?: StreamingSlotMetricType[];
15
+ excludeTypes?: StreamingSlotMetricType[];
16
+ sampleRate?: number;
17
+ };
18
+ export declare const createStreamingSlotMetricSink: ({ excludeTypes, includeTypes, metadata, onReport, onError, route, sampleRate }?: StreamingSlotMetricSinkOptions) => StreamingSlotMetricHandler;
@@ -1,4 +1,33 @@
1
1
  type SlotResolver = () => Promise<string> | string;
2
+ type SlotErrorHandler = (error: unknown, slot: StreamingSlot) => void;
3
+ export type StreamingSlotMetricType = 'prepared' | 'dropped' | 'resolved' | 'patched' | 'timeout' | 'size_exceeded' | 'error';
4
+ export type StreamingSlotMetric = {
5
+ type: StreamingSlotMetricType;
6
+ slotId: string;
7
+ durationMs?: number;
8
+ bytes?: number;
9
+ reason?: string;
10
+ error?: unknown;
11
+ };
12
+ export type StreamingSlotMetricHandler = (metric: StreamingSlotMetric) => void;
13
+ export type StreamingSlotPolicy = {
14
+ timeoutMs?: number;
15
+ fallbackHtml?: string;
16
+ errorHtml?: string;
17
+ maxSlotsPerResponse?: number;
18
+ maxSlotHtmlSizeBytes?: number;
19
+ onError?: SlotErrorHandler;
20
+ onSlotMetric?: StreamingSlotMetricHandler;
21
+ };
22
+ type StreamingSlotPolicyValue = {
23
+ timeoutMs: number;
24
+ fallbackHtml: string;
25
+ errorHtml?: string;
26
+ maxSlotsPerResponse: number;
27
+ maxSlotHtmlSizeBytes: number;
28
+ onError?: SlotErrorHandler;
29
+ onSlotMetric?: StreamingSlotMetricHandler;
30
+ };
2
31
  export type StreamingSlot = {
3
32
  errorHtml?: string;
4
33
  fallbackHtml?: string;
@@ -12,12 +41,16 @@ type DeferredStreamingSlot = Omit<StreamingSlot, 'id'> & {
12
41
  export type AppendStreamingSlotsOptions = {
13
42
  injectRuntime?: boolean;
14
43
  nonce?: string;
44
+ policy?: StreamingSlotPolicy;
45
+ onSlotMetric?: StreamingSlotMetricHandler;
15
46
  onError?: (error: unknown, slot: StreamingSlot) => void;
16
47
  };
17
48
  export type StreamOutOfOrderSlotsOptions = {
18
49
  footerHtml?: string;
19
50
  headerHtml?: string;
20
51
  nonce?: string;
52
+ policy?: StreamingSlotPolicy;
53
+ onSlotMetric?: StreamingSlotMetricHandler;
21
54
  onError?: (error: unknown, slot: StreamingSlot) => void;
22
55
  slots: DeferredStreamingSlot[];
23
56
  };
@@ -27,7 +60,10 @@ export declare const renderStreamingSlotsRuntimeTag: (nonce?: string) => string;
27
60
  export declare const renderStreamingSlotPlaceholder: (id: string, fallbackHtml?: string) => string;
28
61
  export declare const renderStreamingSlotPatchTag: (id: string, html: string, nonce?: string) => string;
29
62
  export declare const injectHtmlIntoHead: (html: string, injection: string) => string;
30
- export declare const streamOutOfOrderSlots: ({ footerHtml, headerHtml, nonce, onError, slots }: StreamOutOfOrderSlotsOptions) => ReadableStream<Uint8Array<ArrayBufferLike>>;
63
+ export declare const getStreamingSlotPolicy: () => StreamingSlotPolicyValue;
64
+ export declare const setStreamingSlotPolicy: (policy?: StreamingSlotPolicy) => void;
65
+ export declare const withStreamingSlotPolicy: <T>(policy: StreamingSlotPolicy, callback: () => Promise<T> | T) => Promise<T>;
66
+ export declare const streamOutOfOrderSlots: ({ footerHtml, headerHtml, nonce, policy, onSlotMetric, onError, slots }: StreamOutOfOrderSlotsOptions) => ReadableStream<Uint8Array<ArrayBufferLike>>;
31
67
  export declare const injectStreamingRuntimeIntoStream: (stream: ReadableStream<string | Uint8Array>, nonce?: string) => ReadableStream<Uint8Array<ArrayBufferLike>>;
32
- export declare const appendStreamingSlotPatchesToStream: (stream: ReadableStream<string | Uint8Array>, slots?: StreamingSlot[], { injectRuntime, nonce, onError }?: AppendStreamingSlotsOptions) => ReadableStream<Uint8Array<ArrayBufferLike>>;
68
+ export declare const appendStreamingSlotPatchesToStream: (stream: ReadableStream<string | Uint8Array>, slots?: DeferredStreamingSlot[], { injectRuntime, nonce, onError, onSlotMetric, policy }?: AppendStreamingSlotsOptions) => ReadableStream<string | Uint8Array<ArrayBufferLike>>;
33
69
  export {};
@@ -2,3 +2,5 @@ export declare const handleVuePageRequest: <Component extends import("vue").Comp
2
2
  export { Island } from './Island';
3
3
  export { createTypedIsland } from './createIsland';
4
4
  export { useIslandStore } from './useIslandStore';
5
+ export { default as Image } from './components/Image.vue';
6
+ export { StreamSlot, SuspenseSlot } from './components';
@@ -30881,6 +30881,9 @@ var CLOSING_PAGE_TAG_REGEX = /<\/body>\s*<\/html>\s*$/i;
30881
30881
  var STREAMING_RUNTIME_GLOBAL = "__ABS_SLOT_ENQUEUE__";
30882
30882
  var STREAMING_PENDING_GLOBAL = "__ABS_SLOT_PENDING__";
30883
30883
  var STREAM_TAIL_LOOKBEHIND = 128;
30884
+ var STREAMING_SLOT_TIMEOUT_MS = 5000;
30885
+ var STREAMING_SLOT_MAX_PER_RESPONSE = 128;
30886
+ var STREAMING_SLOT_MAX_HTML_BYTES = 64000;
30884
30887
  var createSlotPlaceholderId = (id) => `${SLOT_PLACEHOLDER_PREFIX}${id}`;
30885
30888
  var createSlotPatchStatement = (id, html) => `(window.${STREAMING_RUNTIME_GLOBAL}||function(i,h){window.${STREAMING_PENDING_GLOBAL}=window.${STREAMING_PENDING_GLOBAL}||{};window.${STREAMING_PENDING_GLOBAL}[i]=h;})(${JSON.stringify(id)},${JSON.stringify(html)});`;
30886
30889
  var createNonceAttr = (nonce) => nonce ? ` nonce="${nonce}"` : "";
@@ -30897,32 +30900,197 @@ var injectHtmlIntoHead = (html, injection) => {
30897
30900
  return `${html}${injection}`;
30898
30901
  };
30899
30902
  var toUint8 = (value, encoder) => encoder.encode(value);
30900
- var toStreamingSlot = (slot) => ({
30901
- ...slot,
30902
- id: slot.id ?? createStreamingSlotId()
30903
+ var currentStreamingSlotPolicy = {
30904
+ timeoutMs: STREAMING_SLOT_TIMEOUT_MS,
30905
+ fallbackHtml: "",
30906
+ errorHtml: undefined,
30907
+ maxSlotsPerResponse: STREAMING_SLOT_MAX_PER_RESPONSE,
30908
+ maxSlotHtmlSizeBytes: STREAMING_SLOT_MAX_HTML_BYTES
30909
+ };
30910
+ var clonePolicy = (policy) => ({
30911
+ ...policy
30912
+ });
30913
+ var normalizeSlotBytes = (value, fallback) => {
30914
+ if (typeof value === "number" && Number.isFinite(value) && value >= 0) {
30915
+ return Math.floor(value);
30916
+ }
30917
+ return fallback;
30918
+ };
30919
+ var normalizeSlotText = (value, fallback) => typeof value === "string" ? value : fallback;
30920
+ var normalizeSlotError = (value, fallback) => typeof value === "string" ? value : fallback;
30921
+ var hasPolicyValue = (policy, key) => Object.prototype.hasOwnProperty.call(policy, key);
30922
+ var applyStreamingSlotPolicyOverrides = (base, overridePolicy = {}) => ({
30923
+ timeoutMs: hasPolicyValue(overridePolicy, "timeoutMs") ? normalizeSlotBytes(overridePolicy.timeoutMs, base.timeoutMs) : base.timeoutMs,
30924
+ fallbackHtml: hasPolicyValue(overridePolicy, "fallbackHtml") ? normalizeSlotText(overridePolicy.fallbackHtml, "") : base.fallbackHtml,
30925
+ errorHtml: hasPolicyValue(overridePolicy, "errorHtml") ? normalizeSlotError(overridePolicy.errorHtml) : base.errorHtml,
30926
+ maxSlotsPerResponse: hasPolicyValue(overridePolicy, "maxSlotsPerResponse") ? normalizeSlotBytes(overridePolicy.maxSlotsPerResponse, base.maxSlotsPerResponse) : base.maxSlotsPerResponse,
30927
+ maxSlotHtmlSizeBytes: hasPolicyValue(overridePolicy, "maxSlotHtmlSizeBytes") ? normalizeSlotBytes(overridePolicy.maxSlotHtmlSizeBytes, base.maxSlotHtmlSizeBytes) : base.maxSlotHtmlSizeBytes,
30928
+ onError: hasPolicyValue(overridePolicy, "onError") ? overridePolicy.onError : base.onError,
30929
+ onSlotMetric: hasPolicyValue(overridePolicy, "onSlotMetric") ? overridePolicy.onSlotMetric : base.onSlotMetric
30930
+ });
30931
+ var createCombinedSlotErrorHandler = (policyOnError, enhancerOnError) => {
30932
+ if (!policyOnError && !enhancerOnError)
30933
+ return;
30934
+ return (error, slot) => {
30935
+ policyOnError?.(error, slot);
30936
+ enhancerOnError?.(error, slot);
30937
+ };
30938
+ };
30939
+ var createCombinedSlotMetricHandler = (policyOnSlotMetric, callOnSlotMetric) => {
30940
+ if (!policyOnSlotMetric && !callOnSlotMetric)
30941
+ return;
30942
+ return (metric) => {
30943
+ policyOnSlotMetric?.(metric);
30944
+ callOnSlotMetric?.(metric);
30945
+ };
30946
+ };
30947
+ var resolveStreamingSlotPolicy = (overridePolicy = {}) => {
30948
+ const base = getStreamingSlotPolicy();
30949
+ return applyStreamingSlotPolicyOverrides(base, overridePolicy);
30950
+ };
30951
+ var getStreamingSlotPolicy = () => clonePolicy(currentStreamingSlotPolicy);
30952
+ var setStreamingSlotPolicy = (policy = {}) => {
30953
+ const base = getStreamingSlotPolicy();
30954
+ currentStreamingSlotPolicy = applyStreamingSlotPolicyOverrides(base, policy);
30955
+ };
30956
+ var withStreamingSlotPolicy = async (policy, callback) => {
30957
+ const previous = getStreamingSlotPolicy();
30958
+ setStreamingSlotPolicy(policy);
30959
+ try {
30960
+ return await callback();
30961
+ } finally {
30962
+ currentStreamingSlotPolicy = previous;
30963
+ }
30964
+ };
30965
+ var emitSlotMetric = (metric, onSlotMetric) => {
30966
+ onSlotMetric?.(metric);
30967
+ };
30968
+ var createTimeoutError = (slot, timeoutMs) => {
30969
+ const error = new Error(`Streaming slot "${slot.id}" timed out after ${timeoutMs}ms`);
30970
+ error.__absTimeout = true;
30971
+ return error;
30972
+ };
30973
+ var toStreamingSlot = (slot, policy) => ({
30974
+ errorHtml: slot.errorHtml === undefined ? policy.errorHtml : slot.errorHtml,
30975
+ fallbackHtml: normalizeSlotText(slot.fallbackHtml, policy.fallbackHtml),
30976
+ id: slot.id ?? createStreamingSlotId(),
30977
+ timeoutMs: normalizeSlotBytes(slot.timeoutMs, policy.timeoutMs),
30978
+ resolve: slot.resolve
30903
30979
  });
30904
- var resolveSlot = async (slot, onError) => {
30980
+ var prepareSlots = ({
30981
+ policy,
30982
+ slots,
30983
+ onError,
30984
+ onSlotMetric
30985
+ }) => {
30986
+ const preparedSlots = slots.map((slot) => toStreamingSlot(slot, policy));
30987
+ const maxSlotsPerResponse = policy.maxSlotsPerResponse;
30988
+ if (maxSlotsPerResponse === 0) {
30989
+ const error = new Error("Streaming slot limit is set to 0");
30990
+ for (const slot of preparedSlots) {
30991
+ onError?.(error, slot);
30992
+ emitSlotMetric({
30993
+ type: "dropped",
30994
+ slotId: slot.id,
30995
+ reason: "maxSlotsPerResponse is 0"
30996
+ }, onSlotMetric);
30997
+ }
30998
+ return [];
30999
+ }
31000
+ if (preparedSlots.length <= maxSlotsPerResponse) {
31001
+ preparedSlots.forEach((slot) => emitSlotMetric({
31002
+ type: "prepared",
31003
+ slotId: slot.id
31004
+ }, onSlotMetric));
31005
+ return preparedSlots;
31006
+ }
31007
+ const keptSlots = preparedSlots.slice(0, maxSlotsPerResponse);
31008
+ const droppedSlots = preparedSlots.slice(maxSlotsPerResponse);
31009
+ droppedSlots.forEach((slot) => {
31010
+ onError?.(new Error(`Streaming slot "${slot.id}" dropped because ${maxSlotsPerResponse} slots is the configured maximum`), slot);
31011
+ emitSlotMetric({
31012
+ type: "dropped",
31013
+ slotId: slot.id,
31014
+ reason: `maxSlotsPerResponse is ${maxSlotsPerResponse}`
31015
+ }, onSlotMetric);
31016
+ });
31017
+ keptSlots.forEach((slot) => emitSlotMetric({
31018
+ type: "prepared",
31019
+ slotId: slot.id
31020
+ }, onSlotMetric));
31021
+ return keptSlots;
31022
+ };
31023
+ var htmlByteLength = (value, encoder) => encoder.encode(value).length;
31024
+ var resolveSlot = async (slot, onError, policy, onSlotMetric) => {
31025
+ const safePolicy = policy ?? getStreamingSlotPolicy();
31026
+ const encoder = new TextEncoder;
31027
+ const start = Date.now();
30905
31028
  try {
30906
- const resolved = slot.resolve();
30907
- const html = typeof slot.timeoutMs === "number" && slot.timeoutMs > 0 ? await Promise.race([
30908
- Promise.resolve(resolved),
30909
- new Promise((_, reject) => setTimeout(() => reject(new Error(`Streaming slot "${slot.id}" timed out after ${slot.timeoutMs}ms`)), slot.timeoutMs))
30910
- ]) : await resolved;
31029
+ const maybeAsyncValue = Promise.resolve(slot.resolve());
31030
+ const resolved = typeof slot.timeoutMs === "number" && slot.timeoutMs > 0 ? await Promise.race([
31031
+ maybeAsyncValue,
31032
+ new Promise((_, reject) => setTimeout(() => {
31033
+ reject(createTimeoutError(slot, slot.timeoutMs ?? 0));
31034
+ }, slot.timeoutMs))
31035
+ ]) : await maybeAsyncValue;
31036
+ const html = typeof resolved === "string" ? resolved : `${resolved}`;
31037
+ if (safePolicy.maxSlotHtmlSizeBytes > 0 && htmlByteLength(html, encoder) > safePolicy.maxSlotHtmlSizeBytes) {
31038
+ const bytes2 = htmlByteLength(html, encoder);
31039
+ const error = new Error(`Streaming slot "${slot.id}" exceeded max payload size of ${safePolicy.maxSlotHtmlSizeBytes} bytes`);
31040
+ const durationMs2 = Date.now() - start;
31041
+ onError?.(error, slot);
31042
+ emitSlotMetric({
31043
+ type: "size_exceeded",
31044
+ slotId: slot.id,
31045
+ durationMs: durationMs2,
31046
+ bytes: bytes2,
31047
+ error
31048
+ }, onSlotMetric);
31049
+ const fallbackHtml = typeof slot.errorHtml === "string" ? slot.errorHtml : null;
31050
+ return {
31051
+ html: fallbackHtml,
31052
+ id: slot.id,
31053
+ durationMs: durationMs2,
31054
+ bytes: fallbackHtml === null ? 0 : htmlByteLength(fallbackHtml, encoder)
31055
+ };
31056
+ }
31057
+ const durationMs = Date.now() - start;
31058
+ const bytes = htmlByteLength(html, encoder);
31059
+ emitSlotMetric({
31060
+ type: "resolved",
31061
+ slotId: slot.id,
31062
+ durationMs,
31063
+ bytes
31064
+ }, onSlotMetric);
30911
31065
  return {
30912
31066
  html,
30913
- id: slot.id
31067
+ id: slot.id,
31068
+ durationMs,
31069
+ bytes
30914
31070
  };
30915
31071
  } catch (error) {
31072
+ const durationMs = Date.now() - start;
30916
31073
  onError?.(error, slot);
31074
+ emitSlotMetric({
31075
+ type: error?.__absTimeout === true ? "timeout" : "error",
31076
+ slotId: slot.id,
31077
+ durationMs,
31078
+ error
31079
+ }, onSlotMetric);
30917
31080
  if (typeof slot.errorHtml === "string") {
31081
+ const html = slot.errorHtml;
30918
31082
  return {
30919
- html: slot.errorHtml,
30920
- id: slot.id
31083
+ html,
31084
+ id: slot.id,
31085
+ durationMs,
31086
+ bytes: htmlByteLength(html, encoder)
30921
31087
  };
30922
31088
  }
30923
31089
  return {
30924
31090
  html: null,
30925
- id: slot.id
31091
+ id: slot.id,
31092
+ durationMs,
31093
+ bytes: 0
30926
31094
  };
30927
31095
  }
30928
31096
  };
@@ -30938,23 +31106,37 @@ var streamOutOfOrderSlots = ({
30938
31106
  footerHtml = "",
30939
31107
  headerHtml = "",
30940
31108
  nonce,
31109
+ policy,
31110
+ onSlotMetric,
30941
31111
  onError,
30942
31112
  slots
30943
31113
  }) => {
31114
+ const resolvedPolicy = resolveStreamingSlotPolicy(policy);
31115
+ const combinedOnError = createCombinedSlotErrorHandler(resolvedPolicy.onError, onError);
31116
+ const combinedOnSlotMetric = createCombinedSlotMetricHandler(resolvedPolicy.onSlotMetric, onSlotMetric);
31117
+ const effectivePolicy = {
31118
+ ...resolvedPolicy,
31119
+ onSlotMetric: combinedOnSlotMetric
31120
+ };
31121
+ const preparedSlots = prepareSlots({
31122
+ policy: effectivePolicy,
31123
+ slots,
31124
+ onError: combinedOnError,
31125
+ onSlotMetric: combinedOnSlotMetric
31126
+ });
30944
31127
  const encoder = new TextEncoder;
30945
31128
  return new ReadableStream({
30946
31129
  async start(controller) {
30947
31130
  try {
30948
31131
  let header = headerHtml;
30949
- if (!header.includes(STREAMING_RUNTIME_GLOBAL)) {
31132
+ if (preparedSlots.length > 0 && !header.includes(STREAMING_RUNTIME_GLOBAL)) {
30950
31133
  header = injectHtmlIntoHead(header, renderStreamingSlotsRuntimeTag(nonce));
30951
31134
  }
30952
31135
  controller.enqueue(toUint8(header, encoder));
30953
- const pending = slots.map((slot) => {
30954
- const resolvedSlot = toStreamingSlot(slot);
30955
- const fallback = renderStreamingSlotPlaceholder(resolvedSlot.id, resolvedSlot.fallbackHtml ?? "");
31136
+ const pending = preparedSlots.map((slot) => {
31137
+ const fallback = renderStreamingSlotPlaceholder(slot.id, slot.fallbackHtml ?? "");
30956
31138
  controller.enqueue(toUint8(fallback, encoder));
30957
- return resolveSlot(resolvedSlot, onError);
31139
+ return resolveSlot(slot, combinedOnError, effectivePolicy, combinedOnSlotMetric);
30958
31140
  });
30959
31141
  while (pending.length > 0) {
30960
31142
  const { original, result } = await nextResolvedSlot(pending);
@@ -30963,6 +31145,12 @@ var streamOutOfOrderSlots = ({
30963
31145
  pending.splice(index, 1);
30964
31146
  if (result.html === null)
30965
31147
  continue;
31148
+ emitSlotMetric({
31149
+ type: "patched",
31150
+ slotId: result.id,
31151
+ durationMs: result.durationMs,
31152
+ bytes: result.bytes
31153
+ }, combinedOnSlotMetric);
30966
31154
  controller.enqueue(toUint8(renderStreamingSlotPatchTag(result.id, result.html, nonce), encoder));
30967
31155
  }
30968
31156
  if (footerHtml.length > 0) {
@@ -31026,12 +31214,33 @@ var injectStreamingRuntimeIntoStream = (stream, nonce) => {
31026
31214
  }
31027
31215
  });
31028
31216
  };
31029
- var appendStreamingSlotPatchesToStream = (stream, slots = [], { injectRuntime = true, nonce, onError } = {}) => {
31217
+ var appendStreamingSlotPatchesToStream = (stream, slots = [], {
31218
+ injectRuntime = true,
31219
+ nonce,
31220
+ onError,
31221
+ onSlotMetric,
31222
+ policy
31223
+ } = {}) => {
31224
+ const resolvedPolicy = resolveStreamingSlotPolicy(policy);
31225
+ const combinedOnError = createCombinedSlotErrorHandler(resolvedPolicy.onError, onError);
31226
+ const combinedOnSlotMetric = createCombinedSlotMetricHandler(resolvedPolicy.onSlotMetric, onSlotMetric);
31227
+ const effectivePolicy = {
31228
+ ...resolvedPolicy,
31229
+ onSlotMetric: combinedOnSlotMetric
31230
+ };
31231
+ const preparedSlots = prepareSlots({
31232
+ policy: effectivePolicy,
31233
+ slots,
31234
+ onError: combinedOnError,
31235
+ onSlotMetric: combinedOnSlotMetric
31236
+ });
31237
+ if (preparedSlots.length === 0)
31238
+ return stream;
31030
31239
  const source = injectRuntime ? injectStreamingRuntimeIntoStream(stream, nonce) : stream;
31031
31240
  const encoder = new TextEncoder;
31032
31241
  const decoder = new TextDecoder;
31033
31242
  const reader = source.getReader();
31034
- const pending = slots.map((slot) => resolveSlot(slot, onError));
31243
+ const pending = preparedSlots.map((slot) => resolveSlot(slot, combinedOnError, effectivePolicy, combinedOnSlotMetric));
31035
31244
  return new ReadableStream({
31036
31245
  async start(controller) {
31037
31246
  let baseDone = false;
@@ -31088,6 +31297,12 @@ var appendStreamingSlotPatchesToStream = (stream, slots = [], { injectRuntime =
31088
31297
  pending.splice(index, 1);
31089
31298
  if (winner.result.html === null)
31090
31299
  continue;
31300
+ emitSlotMetric({
31301
+ type: "patched",
31302
+ slotId: winner.result.id,
31303
+ durationMs: winner.result.durationMs,
31304
+ bytes: winner.result.bytes
31305
+ }, combinedOnSlotMetric);
31091
31306
  controller.enqueue(encoder.encode(renderStreamingSlotPatchTag(winner.result.id, winner.result.html, nonce)));
31092
31307
  }
31093
31308
  if (footer.length > 0)
@@ -31146,13 +31361,14 @@ var cloneHeaders = (response) => {
31146
31361
  const headers = new Headers(response.headers);
31147
31362
  return headers;
31148
31363
  };
31149
- var enhanceHtmlResponseWithStreamingSlots = (response, { nonce, onError, streamingSlots = [] } = {}) => {
31364
+ var enhanceHtmlResponseWithStreamingSlots = (response, { nonce, onError, streamingSlots = [], policy } = {}) => {
31150
31365
  if (!response.body || streamingSlots.length === 0) {
31151
31366
  return response;
31152
31367
  }
31153
31368
  const body = appendStreamingSlotPatchesToStream(response.body, streamingSlots, {
31154
31369
  nonce,
31155
- onError
31370
+ onError,
31371
+ policy
31156
31372
  });
31157
31373
  return new Response(body, {
31158
31374
  headers: cloneHeaders(response),
@@ -31335,5 +31551,5 @@ export {
31335
31551
  AwaitSlot_default as AwaitSlot
31336
31552
  };
31337
31553
 
31338
- //# debugId=1BB7CFD3565A43C264756E2164756E21
31554
+ //# debugId=CF6826373193F13564756E2164756E21
31339
31555
  //# sourceMappingURL=index.js.map