@bgub/fig 0.0.1 → 0.1.0-alpha.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/CHANGELOG.md +501 -0
- package/README.md +50 -19
- package/dist/element-BZ7r9ncY.d.ts +342 -0
- package/dist/element-DmbzNH0T.js +299 -0
- package/dist/element-DmbzNH0T.js.map +1 -0
- package/dist/hooks-QDRabULx.d.ts +158 -0
- package/dist/index.d.ts +3 -5
- package/dist/index.js +4 -4
- package/dist/internal.d.ts +212 -6
- package/dist/internal.js +14 -43
- package/dist/internal.js.map +1 -1
- package/dist/jsx-runtime.d.ts +1 -1
- package/dist/jsx-runtime.js +3 -3
- package/dist/jsx-runtime.js.map +1 -1
- package/dist/payload-format-KTNaSI4h.js +366 -0
- package/dist/payload-format-KTNaSI4h.js.map +1 -0
- package/dist/payload.d.ts +92 -0
- package/dist/payload.js +429 -0
- package/dist/payload.js.map +1 -0
- package/dist/{transition-DEqcImne.js → resource-kXeIR52S.js} +121 -71
- package/dist/resource-kXeIR52S.js.map +1 -0
- package/dist/{data-store-CRnNAT9-.js → transition-CC4kjjrU.js} +165 -54
- package/dist/transition-CC4kjjrU.js.map +1 -0
- package/package.json +5 -6
- package/dist/data-CHJh_xU9.d.ts +0 -79
- package/dist/data-h46EcMnE.js +0 -37
- package/dist/data-h46EcMnE.js.map +0 -1
- package/dist/data-store-CRnNAT9-.js.map +0 -1
- package/dist/data-store-EQOLQsW4.d.ts +0 -32
- package/dist/element-Bh_k9c3N.js +0 -179
- package/dist/element-Bh_k9c3N.js.map +0 -1
- package/dist/element-CCOOi4Ka.d.ts +0 -209
- package/dist/server.browser.d.ts +0 -9
- package/dist/server.browser.js +0 -8
- package/dist/server.browser.js.map +0 -1
- package/dist/server.d.ts +0 -9
- package/dist/server.js +0 -9
- package/dist/server.js.map +0 -1
- package/dist/transition-Cl6mAPcx.d.ts +0 -96
- package/dist/transition-DEqcImne.js.map +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"payload-format-KTNaSI4h.js","names":[],"sources":["../src/payload-format.ts"],"sourcesContent":["import type { FigDataHydrationEntry } from \"./data.ts\";\nimport type { Key } from \"./element.ts\";\nimport type {\n FontResource,\n MetaResource,\n ModulePreloadResource,\n PreconnectResource,\n PreloadResource,\n ScriptResource,\n StylesheetResource,\n TitleResource,\n} from \"./resource.ts\";\n\n// Asset resources represented as descriptor data. Optional fields stay optional\n// on the wire; omitted `undefined` values are part of the payload contract, not\n// a serializer implementation detail. Delivery assets prepare eagerly at row\n// arrival; document metadata stays attached to its owning decoded row until\n// that row commits.\nexport type SerializedAssetResource =\n | {\n crossorigin?: StylesheetResource[\"crossorigin\"];\n href: string;\n kind: \"stylesheet\";\n media?: string;\n precedence?: string;\n }\n | {\n as: string;\n crossorigin?: PreloadResource[\"crossorigin\"];\n fetchpriority?: PreloadResource[\"fetchpriority\"];\n href: string;\n kind: \"preload\";\n type?: string;\n }\n | {\n crossorigin?: ModulePreloadResource[\"crossorigin\"];\n fetchpriority?: ModulePreloadResource[\"fetchpriority\"];\n href: string;\n kind: \"modulepreload\";\n }\n | {\n async?: boolean;\n crossorigin?: ScriptResource[\"crossorigin\"];\n defer?: boolean;\n kind: \"script\";\n module?: boolean;\n src: string;\n }\n | {\n crossorigin?: FontResource[\"crossorigin\"];\n fetchpriority?: FontResource[\"fetchpriority\"];\n href: string;\n kind: \"font\";\n type: string;\n }\n | {\n crossorigin?: PreconnectResource[\"crossorigin\"];\n href: string;\n kind: \"preconnect\";\n }\n | {\n kind: \"title\";\n value: TitleResource[\"value\"];\n }\n | {\n charset?: MetaResource[\"charset\"];\n content?: MetaResource[\"content\"];\n \"http-equiv\"?: MetaResource[\"http-equiv\"];\n key?: string;\n kind: \"meta\";\n name?: MetaResource[\"name\"];\n property?: MetaResource[\"property\"];\n };\n\n/** The `error` row value under the server's `onError` contract. */\nexport interface PayloadErrorValue {\n digest?: string;\n message?: string;\n}\n\n/**\n * Semantic payload row before the internal codec turns it into bytes.\n */\nexport type PayloadRow =\n | { for?: number; tag: \"assets\"; value: SerializedAssetResource[] }\n | {\n id: number;\n tag: \"client\";\n value: {\n id: string;\n assets?: SerializedAssetResource[];\n exportName?: string;\n ssr?: true;\n };\n }\n | { tag: \"data\"; value: PayloadDataHydrationEntry[] }\n | { id: number; tag: \"error\"; value: PayloadErrorValue }\n | { id: number; tag: \"model\"; value: PayloadModel };\n\n/**\n * Transport-safe model value used inside internal payload rows. This is an\n * implementation format, not an application data format.\n */\nexport type PayloadModel =\n | null\n | boolean\n | number\n | string\n | PayloadModel[]\n | { [key: string]: PayloadModel }\n | PayloadElementModel\n | PayloadSpecialModel;\n\nexport type PayloadElementModel = {\n $fig: \"element\";\n id?: number;\n key: Key | null;\n props: PayloadModel;\n type: string | PayloadSpecialModel;\n};\n\nexport type PayloadSpecialModel =\n | { $fig: \"array\"; id: number; value: PayloadModel[] }\n | { $fig: \"bigint\"; value: string }\n | { $fig: \"client\"; id: number }\n | { $fig: \"date\"; value: string }\n | { $fig: \"fragment\" }\n | { $fig: \"lazy\"; id: number }\n | { $fig: \"map\"; entries: Array<[PayloadModel, PayloadModel]>; id: number }\n | { $fig: \"number\"; value: \"Infinity\" | \"-Infinity\" | \"-0\" | \"NaN\" }\n | { $fig: \"object\"; id?: number; value: Record<string, PayloadModel> }\n | { $fig: \"promise\"; id: number }\n | { $fig: \"ref\"; id: number }\n | { $fig: \"set\"; id: number; values: PayloadModel[] }\n | { $fig: \"symbol\"; key: string }\n | { $fig: \"suspense\" }\n | { $fig: \"undefined\" }\n | { $fig: \"view-transition\" };\n\nexport type PayloadValueSpecialModel = Extract<\n PayloadSpecialModel,\n {\n $fig:\n | \"array\"\n | \"bigint\"\n | \"date\"\n | \"map\"\n | \"number\"\n | \"object\"\n | \"ref\"\n | \"set\"\n | \"symbol\"\n | \"undefined\";\n }\n>;\n\nexport type PayloadDataHydrationEntry = Omit<FigDataHydrationEntry, \"value\"> & {\n value: PayloadModel;\n};\n\nexport interface PayloadCodec {\n /**\n * Opaque implementation id, e.g. \"json\" or \"binary\". Fig checks this id at\n * transport boundaries; the encoded byte layout is not a public contract.\n */\n readonly id: string;\n readonly contentType: string;\n /**\n * Creates a streaming row decoder. The decoder calls `onRow` for each\n * complete semantic row. If `onRow` throws, the decoder must propagate that\n * error; when it can already see more complete sibling rows in the same\n * input chunk, it should process those siblings before rethrowing so\n * notifications already implied by earlier rows are not lost.\n */\n createDecoder(onRow: (row: PayloadRow) => void): PayloadRowDecoder;\n encodeRow(row: PayloadRow): Uint8Array;\n}\n\nexport interface PayloadRowDecoder {\n decode(chunk: Uint8Array): void;\n flush(): void;\n}\n\nconst textEncoder = new TextEncoder();\n\n/**\n * Readable development-oriented codec: one JSON payload row per newline.\n */\nexport const jsonPayloadCodec: PayloadCodec = {\n id: \"json\",\n contentType: \"text/x-fig-payload; codec=json; charset=utf-8\",\n createDecoder(onRow) {\n return createJsonPayloadDecoder(onRow);\n },\n encodeRow(row) {\n return textEncoder.encode(`${JSON.stringify(row)}\\n`);\n },\n};\n\nfunction createJsonPayloadDecoder(\n onRow: (row: PayloadRow) => void,\n): PayloadRowDecoder {\n const decoder = new TextDecoder();\n let buffer = \"\";\n let searchStart = 0;\n\n function processBufferedLines(): void {\n let lineStart = 0;\n let firstError: unknown;\n\n for (;;) {\n const newlineIndex = buffer.indexOf(\"\\n\", searchStart);\n if (newlineIndex === -1) {\n searchStart = buffer.length;\n break;\n }\n try {\n processPayloadLine(buffer.slice(lineStart, newlineIndex), onRow);\n } catch (error) {\n firstError ??= error;\n }\n lineStart = newlineIndex + 1;\n searchStart = lineStart;\n }\n\n if (firstError !== undefined) {\n buffer = \"\";\n searchStart = 0;\n throw firstError;\n }\n if (lineStart > 0) {\n buffer = buffer.slice(lineStart);\n searchStart -= lineStart;\n }\n }\n\n return {\n decode(chunk) {\n buffer += decoder.decode(chunk, { stream: true });\n processBufferedLines();\n },\n flush() {\n buffer += decoder.decode();\n if (buffer.length > 0) {\n const line = buffer;\n buffer = \"\";\n searchStart = 0;\n processPayloadLine(line, onRow);\n }\n },\n };\n}\n\nfunction processPayloadLine(\n line: string,\n onRow: (row: PayloadRow) => void,\n): void {\n if (line.length > 0) onRow(JSON.parse(line) as PayloadRow);\n}\n\n/**\n * Extract the codec id from a payload content-type header, or null when the\n * header carries no codec parameter.\n */\nexport function payloadCodecIdFromContentType(\n contentTypeHeader: string,\n): string | null {\n const parts = contentTypeHeader.split(\";\").slice(1);\n for (const part of parts) {\n const [name, rawValue] = part.split(\"=\");\n if (name?.trim().toLowerCase() !== \"codec\") continue;\n const value = rawValue?.trim();\n if (value === undefined || value.length === 0) return null;\n return value.replace(/^\"|\"$/g, \"\");\n }\n return null;\n}\n\n/**\n * Throw when a response content-type declares a codec other than the one this\n * client decodes with. A missing header or codec parameter passes: transports\n * that strip content types stay usable, and mismatches still fail fast when\n * declared.\n */\nexport function assertPayloadCodecMatches(\n codec: PayloadCodec,\n contentTypeHeader: string | null,\n): void {\n if (contentTypeHeader === null) return;\n const received = payloadCodecIdFromContentType(contentTypeHeader);\n if (received === null || received === codec.id) return;\n throw new Error(\n `Payload codec mismatch: producer used \"${received}\" but this client expects \"${codec.id}\".`,\n );\n}\n\n/** Decode an `error` row value into a digest-carrying Error. */\nexport function errorFromPayloadValue(value: PayloadErrorValue): Error & {\n digest?: string;\n} {\n const error = new Error(value.message ?? \"The server render failed.\");\n return value.digest === undefined\n ? error\n : Object.assign(error, { digest: value.digest });\n}\n\nexport interface PayloadGraphEncodeContext {\n // Ids are dense and monotonic: id = position in `defined` + 1, so rollback\n // is popping the stack. A reverse id→object map would be redundant state.\n defined: object[];\n ids: WeakMap<object, number>;\n}\n\ninterface PayloadGraphDecodeContext {\n decodeChild: (model: PayloadModel) => unknown;\n refs: PayloadDecodeRefs;\n}\n\nfunction createPayloadGraphDecodeContext(): PayloadGraphDecodeContext {\n const refs = new Map<number, unknown>();\n const context: PayloadGraphDecodeContext = {\n decodeChild: (model) => decodeModelValue(model, context),\n refs: {\n define(id, create, fill) {\n const value = create();\n refs.set(id, value);\n fill(value);\n return value;\n },\n read(id) {\n if (!refs.has(id)) {\n throw new Error(`Payload referenced unknown object id ${id}.`);\n }\n return refs.get(id);\n },\n },\n };\n return context;\n}\n\nexport function createPayloadGraphEncodeContext(): PayloadGraphEncodeContext {\n return { defined: [], ids: new WeakMap() };\n}\n\nexport function isPlainPayloadValue(value: unknown): boolean {\n return (\n value === null ||\n value === undefined ||\n typeof value === \"string\" ||\n typeof value === \"number\" ||\n typeof value === \"boolean\" ||\n typeof value === \"bigint\" ||\n typeof value === \"symbol\"\n );\n}\n\n/**\n * Encode ordinary data values into PayloadModel. Server component references\n * such as Fig elements, promises, and client references are handled by the\n * payload renderer before ordinary values reach this helper.\n */\nexport function encodePayloadValue(value: unknown): PayloadModel {\n return encodePayloadValueWithGraph(value, createPayloadGraphEncodeContext());\n}\n\nexport function encodePayloadValueWithGraph(\n value: unknown,\n graph: PayloadGraphEncodeContext,\n): PayloadModel {\n if (value === null) return null;\n if (value === undefined) return { $fig: \"undefined\" };\n\n if (typeof value === \"string\" || typeof value === \"boolean\") return value;\n if (typeof value === \"number\") return encodePayloadNumber(value);\n if (typeof value === \"bigint\") {\n return { $fig: \"bigint\", value: value.toString() };\n }\n if (typeof value === \"symbol\") {\n const key = Symbol.keyFor(value);\n if (key === undefined) {\n throw new Error(\"Only global Symbol.for symbols can be serialized.\");\n }\n return { $fig: \"symbol\", key };\n }\n if (typeof value === \"function\") {\n throw new Error(\"Functions cannot be serialized into the payload.\");\n }\n\n if (Array.isArray(value)) {\n return serializePayloadArray(\n value,\n graph,\n () => value,\n (item) => encodePayloadValueWithGraph(item, graph),\n );\n }\n if (value instanceof Date) {\n const json = value.toJSON();\n if (json === null) {\n throw new Error(\"Invalid Date values cannot be serialized.\");\n }\n return { $fig: \"date\", value: json };\n }\n if (value instanceof Map) {\n return serializePayloadMap(value, graph, ([key, item]) => [\n encodePayloadValueWithGraph(key, graph),\n encodePayloadValueWithGraph(item, graph),\n ]);\n }\n if (value instanceof Set) {\n return serializePayloadSet(value, graph, (item) =>\n encodePayloadValueWithGraph(item, graph),\n );\n }\n\n if (typeof value === \"object\" && value !== null) {\n return serializePayloadPlainObject(value, graph, (child) =>\n encodePayloadValueWithGraph(child, graph),\n );\n }\n\n throw new Error(`Cannot serialize ${typeof value} into the payload.`);\n}\n\nexport function serializePayloadMap(\n value: Map<unknown, unknown>,\n graph: PayloadGraphEncodeContext,\n encodeEntry: (entry: [unknown, unknown]) => [PayloadModel, PayloadModel],\n): PayloadModel {\n const existing = payloadGraphReference(graph, value);\n if (existing !== null) return existing;\n const id = definePayloadGraphObject(graph, value);\n const entries: Array<[PayloadModel, PayloadModel]> = [];\n for (const entry of value) entries.push(encodeEntry(entry));\n return { $fig: \"map\", id, entries };\n}\n\nexport function serializePayloadSet(\n value: Set<unknown>,\n graph: PayloadGraphEncodeContext,\n encodeItem: (value: unknown) => PayloadModel,\n): PayloadModel {\n const existing = payloadGraphReference(graph, value);\n if (existing !== null) return existing;\n const id = definePayloadGraphObject(graph, value);\n const values: PayloadModel[] = [];\n for (const item of value) values.push(encodeItem(item));\n return { $fig: \"set\", id, values };\n}\n\nfunction payloadGraphReference(\n graph: PayloadGraphEncodeContext,\n value: object,\n): PayloadSpecialModel | null {\n const id = graph.ids.get(value);\n return id === undefined ? null : { $fig: \"ref\", id };\n}\n\nfunction definePayloadGraphObject(\n graph: PayloadGraphEncodeContext,\n value: object,\n): number {\n graph.defined.push(value);\n const id = graph.defined.length;\n graph.ids.set(value, id);\n return id;\n}\n\nexport function checkpointPayloadGraph(\n graph: PayloadGraphEncodeContext,\n): number {\n return graph.defined.length;\n}\n\nexport function rollbackPayloadGraph(\n graph: PayloadGraphEncodeContext,\n checkpoint: number,\n): void {\n while (graph.defined.length > checkpoint) {\n graph.ids.delete(graph.defined.pop() as object);\n }\n}\n\nexport function definePayloadGraphElement(\n graph: PayloadGraphEncodeContext,\n value: object,\n): number | PayloadSpecialModel {\n const existing = payloadGraphReference(graph, value);\n if (existing !== null) return existing;\n return definePayloadGraphObject(graph, value);\n}\n\nexport function serializePayloadArray<T>(\n value: object,\n graph: PayloadGraphEncodeContext,\n entries: () => readonly T[],\n encodeChild: (value: T) => PayloadModel,\n): PayloadModel {\n const existing = payloadGraphReference(graph, value);\n if (existing !== null) return existing;\n const id = definePayloadGraphObject(graph, value);\n return { $fig: \"array\", id, value: entries().map(encodeChild) };\n}\n\nexport function serializePayloadPlainObject(\n value: object,\n graph: PayloadGraphEncodeContext,\n encodeChild: (value: unknown) => PayloadModel,\n): PayloadModel {\n const existing = payloadGraphReference(graph, value);\n if (existing !== null) return existing;\n const id = definePayloadGraphObject(graph, value);\n return {\n $fig: \"object\",\n id,\n value: encodePayloadRecord(plainPayloadObject(value), encodeChild),\n };\n}\n\nfunction plainPayloadObject(value: object): Record<string, unknown> {\n const prototype = Object.getPrototypeOf(value);\n if (prototype !== Object.prototype && prototype !== null) {\n throw new Error(\n `Cannot serialize ${prototype?.constructor?.name ?? \"object\"} into the payload.`,\n );\n }\n return value as Record<string, unknown>;\n}\n\nfunction encodePayloadRecord(\n record: Record<string, unknown>,\n encodeChild: (value: unknown) => PayloadModel,\n): Record<string, PayloadModel> {\n const encoded: Record<string, PayloadModel> = {};\n for (const [name, child] of Object.entries(record)) {\n encoded[name] = encodeChild(child);\n }\n return encoded;\n}\n\nfunction encodePayloadNumber(value: number): number | PayloadSpecialModel {\n if (Number.isNaN(value)) return { $fig: \"number\", value: \"NaN\" };\n if (value === Infinity) return { $fig: \"number\", value: \"Infinity\" };\n if (value === -Infinity) return { $fig: \"number\", value: \"-Infinity\" };\n if (Object.is(value, -0)) return { $fig: \"number\", value: \"-0\" };\n return value;\n}\n\n/** Decode values produced by encodePayloadValue. */\nexport function decodePayloadValue(model: PayloadModel): unknown {\n return decodeModelValue(model, createPayloadGraphDecodeContext());\n}\n\nfunction decodeModelValue(\n model: PayloadModel,\n graph: PayloadGraphDecodeContext,\n): unknown {\n if (model === null) return null;\n if (Array.isArray(model))\n return model.map((item) => decodeModelValue(item, graph));\n if (typeof model !== \"object\") return model;\n\n if (isPayloadValueSpecialModel(model)) {\n return decodePayloadValueTag(model, graph.refs, graph.decodeChild);\n }\n\n return decodePayloadRecord(model, graph.decodeChild);\n}\n\nexport function isPayloadValueSpecialModel(\n model: object,\n): model is PayloadValueSpecialModel {\n if (!(\"$fig\" in model)) return false;\n const tag = model.$fig;\n return (\n tag === \"bigint\" ||\n tag === \"array\" ||\n tag === \"date\" ||\n tag === \"map\" ||\n tag === \"number\" ||\n tag === \"object\" ||\n tag === \"ref\" ||\n tag === \"set\" ||\n tag === \"symbol\" ||\n tag === \"undefined\"\n );\n}\n\n// The ref-store seam shared by the two decode entry points: the value codec\n// registers into a per-call refs map, while the stream decoder registers into\n// its request-wide chunk-adjacent store (with rollback on failed fills).\nexport interface PayloadDecodeRefs {\n define<T>(id: number, create: () => T, fill: (value: T) => void): T;\n read(id: number): unknown;\n}\n\nexport function decodePayloadValueTag(\n model: PayloadValueSpecialModel,\n refs: PayloadDecodeRefs,\n decodeChild: (model: PayloadModel) => unknown,\n): unknown {\n switch (model.$fig) {\n case \"array\":\n return refs.define<unknown[]>(\n model.id,\n () => [],\n (value) => {\n for (const item of model.value) value.push(decodeChild(item));\n },\n );\n case \"bigint\":\n return BigInt(model.value);\n case \"date\":\n return new Date(model.value);\n case \"map\":\n return refs.define(\n model.id,\n () => new Map<unknown, unknown>(),\n (value) => {\n for (const [key, item] of model.entries) {\n value.set(decodeChild(key), decodeChild(item));\n }\n },\n );\n case \"number\":\n return decodePayloadNumber(model.value);\n case \"object\": {\n if (model.id === undefined) {\n return decodePayloadRecord(model.value, decodeChild);\n }\n return refs.define(\n model.id,\n () => ({}),\n (value) => {\n for (const [name, child] of Object.entries(model.value)) {\n definePayloadProperty(value, name, decodeChild(child));\n }\n },\n );\n }\n case \"ref\":\n return refs.read(model.id);\n case \"set\":\n return refs.define(\n model.id,\n () => new Set<unknown>(),\n (value) => {\n for (const item of model.values) value.add(decodeChild(item));\n },\n );\n case \"symbol\":\n return Symbol.for(model.key);\n case \"undefined\":\n return undefined;\n }\n}\n\nexport function decodePayloadRecord(\n value: Record<string, PayloadModel>,\n decodeChild: (model: PayloadModel) => unknown,\n): Record<string, unknown> {\n const decoded: Record<string, unknown> = {};\n for (const [name, child] of Object.entries(value)) {\n definePayloadProperty(decoded, name, decodeChild(child));\n }\n return decoded;\n}\n\n// \"__proto__\" must go through defineProperty so a hostile payload key defines\n// an own property instead of mutating the prototype chain via the setter\n// path; every other key gets the identical own data property from plain\n// assignment at a fraction of the cost (this is the decode inner loop).\nexport function definePayloadProperty(\n target: Record<string, unknown>,\n name: string,\n value: unknown,\n): void {\n if (name === \"__proto__\") {\n Object.defineProperty(target, name, {\n configurable: true,\n enumerable: true,\n value,\n writable: true,\n });\n return;\n }\n target[name] = value;\n}\n\nexport function decodePayloadNumber(\n value: \"Infinity\" | \"-Infinity\" | \"-0\" | \"NaN\",\n): number {\n switch (value) {\n case \"Infinity\":\n return Infinity;\n case \"-Infinity\":\n return -Infinity;\n case \"-0\":\n return -0;\n case \"NaN\":\n return NaN;\n }\n}\n\nexport function encodePayloadDataEntries(\n entries: readonly FigDataHydrationEntry[],\n): PayloadDataHydrationEntry[] {\n const graph = createPayloadGraphEncodeContext();\n return entries.map((entry) => ({\n ...entry,\n value: encodePayloadValueWithGraph(entry.value, graph),\n }));\n}\n\nexport function decodePayloadDataEntries(\n entries: readonly PayloadDataHydrationEntry[],\n): FigDataHydrationEntry[] {\n const graph = createPayloadGraphDecodeContext();\n return entries.map((entry) => ({\n ...entry,\n value: decodeModelValue(entry.value, graph),\n }));\n}\n\nexport function isPayloadSpecialModel(\n model: object,\n): model is PayloadElementModel | PayloadSpecialModel {\n if (!(\"$fig\" in model)) return false;\n\n switch (model.$fig) {\n case \"array\":\n case \"bigint\":\n case \"client\":\n case \"date\":\n case \"element\":\n case \"fragment\":\n case \"lazy\":\n case \"map\":\n case \"number\":\n case \"object\":\n case \"promise\":\n case \"ref\":\n case \"set\":\n case \"suspense\":\n case \"symbol\":\n case \"undefined\":\n case \"view-transition\":\n return true;\n default:\n return false;\n }\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import { Wt as FigDataHydrationEntry, a as AwaitedFigNode, ct as FigAssetResource, l as ElementType } from "./element-BZ7r9ncY.js";
|
|
2
|
+
//#region src/payload.d.ts
|
|
3
|
+
interface PayloadClientReference {
|
|
4
|
+
assets?: readonly FigAssetResource[];
|
|
5
|
+
exportName?: string;
|
|
6
|
+
id: string;
|
|
7
|
+
ssr?: boolean;
|
|
8
|
+
}
|
|
9
|
+
type ResolveClientReference = (reference: PayloadClientReference) => ElementType<any> | PromiseLike<ElementType<any>> | undefined;
|
|
10
|
+
/**
|
|
11
|
+
* A caller-owned stateful resolver: a `ResolveClientReference` that also
|
|
12
|
+
* owns component identity. Decodes given one (as `resolveClientReference`)
|
|
13
|
+
* resolve every client reference to a single resolver-owned wrapper per
|
|
14
|
+
* reference id, so re-decoding a payload updates islands in place instead
|
|
15
|
+
* of remounting them. The caller owns the lifetime: drop entries when their
|
|
16
|
+
* modules change (HMR) or the manifest swaps.
|
|
17
|
+
*/
|
|
18
|
+
interface PayloadClientReferenceResolver {
|
|
19
|
+
(reference: PayloadClientReference): ElementType<any> | PromiseLike<ElementType<any>> | undefined;
|
|
20
|
+
clear(): void;
|
|
21
|
+
delete(id: string): boolean;
|
|
22
|
+
}
|
|
23
|
+
declare function createPayloadClientReferenceResolver(resolve: ResolveClientReference): PayloadClientReferenceResolver;
|
|
24
|
+
type PayloadDecodeCompletion = {
|
|
25
|
+
status: "aborted";
|
|
26
|
+
} | {
|
|
27
|
+
status: "complete";
|
|
28
|
+
} | {
|
|
29
|
+
status: "failed";
|
|
30
|
+
error: unknown;
|
|
31
|
+
};
|
|
32
|
+
interface PayloadDecodeOptions {
|
|
33
|
+
/**
|
|
34
|
+
* Receives decoded `data` rows for hydration into a data store. The
|
|
35
|
+
* capability itself is expected to be generation-guarded and to ignore
|
|
36
|
+
* entries after its caller loses authority.
|
|
37
|
+
*/
|
|
38
|
+
hydrate?: (entries: readonly FigDataHydrationEntry[]) => void;
|
|
39
|
+
/**
|
|
40
|
+
* Observes every outlined hole rejection — an `error` row or a stream
|
|
41
|
+
* failure stranding referenced rows, before or after the root fulfills.
|
|
42
|
+
* Abort cancellation is excluded. Called once per rejected hole; the
|
|
43
|
+
* observer is never awaited and cannot break decoding.
|
|
44
|
+
*/
|
|
45
|
+
onHoleError?: (error: unknown) => unknown;
|
|
46
|
+
/**
|
|
47
|
+
* Observes the end of ingestion: called exactly once when the stream
|
|
48
|
+
* settles as complete, failed, or aborted. Post-root failures reject the
|
|
49
|
+
* holes they strand, but a failure with no pending slot is otherwise
|
|
50
|
+
* invisible — this is the hook for reporting it. The callback is never
|
|
51
|
+
* awaited, and its exceptions and rejections are swallowed, so an
|
|
52
|
+
* observer cannot block or break decode teardown.
|
|
53
|
+
*/
|
|
54
|
+
onStreamDone?: (result: PayloadDecodeCompletion) => unknown;
|
|
55
|
+
/**
|
|
56
|
+
* Called with delivery asset resources as soon as their rows arrive
|
|
57
|
+
* (e.g. fig-dom's insertAssetResources). A returned promise gates the
|
|
58
|
+
* reveal of only the content that declared a dependency on those assets;
|
|
59
|
+
* gate settlement — fulfilled or rejected — releases the reveal, so a
|
|
60
|
+
* failed asset never blocks content.
|
|
61
|
+
*/
|
|
62
|
+
prepareAssets?: (assets: readonly FigAssetResource[]) => void | PromiseLike<void>;
|
|
63
|
+
/**
|
|
64
|
+
* Retains delivery asset dependencies as `assets(...)` declarations on
|
|
65
|
+
* their decoded owners. Document metadata is always retained because its
|
|
66
|
+
* owner may mutate the document only when it commits. Server document
|
|
67
|
+
* renderers enable this option to retain delivery assets too.
|
|
68
|
+
*/
|
|
69
|
+
retainAssets?: boolean;
|
|
70
|
+
/**
|
|
71
|
+
* Resolves client-reference rows to components. A plain function keeps
|
|
72
|
+
* identity per decode: gated and asynchronously resolved references decode
|
|
73
|
+
* to per-decode wrappers and remount on re-decode. A stateful resolver
|
|
74
|
+
* (created by `createPayloadClientReferenceResolver`) keeps every
|
|
75
|
+
* resolvable reference's identity stable across the decodes sharing it.
|
|
76
|
+
*/
|
|
77
|
+
resolveClientReference?: ResolveClientReference;
|
|
78
|
+
signal?: AbortSignal;
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Decode a payload row stream. The returned promise resolves with the
|
|
82
|
+
* decoded root FigNode as soon as the root row decodes (and rejects only
|
|
83
|
+
* when the stream fails before producing a root value, or with the root
|
|
84
|
+
* row's own error); decoding continues in the background, filling outlined
|
|
85
|
+
* holes as their rows arrive. Post-root failures reject the holes they
|
|
86
|
+
* strand and report through `onStreamDone`. Aborting `options.signal`
|
|
87
|
+
* ignores remaining rows and rejects unresolved holes with an internal
|
|
88
|
+
* cancellation reason.
|
|
89
|
+
*/
|
|
90
|
+
declare function decodePayloadStream(stream: ReadableStream<Uint8Array>, options?: PayloadDecodeOptions): Promise<AwaitedFigNode>;
|
|
91
|
+
//#endregion
|
|
92
|
+
export { PayloadClientReference, PayloadClientReferenceResolver, PayloadDecodeCompletion, PayloadDecodeOptions, ResolveClientReference, createPayloadClientReferenceResolver, decodePayloadStream };
|
package/dist/payload.js
ADDED
|
@@ -0,0 +1,429 @@
|
|
|
1
|
+
import { I as readPromise, f as Fragment, g as createElement, m as ViewTransition, p as Suspense, s as FigElementSymbol } from "./element-DmbzNH0T.js";
|
|
2
|
+
import { b as trackThenable, l as isFigAssetResource, o as assets, t as assetResourceDestination, v as isThenable } from "./resource-kXeIR52S.js";
|
|
3
|
+
import { a as decodePayloadRecord, f as errorFromPayloadValue, h as jsonPayloadCodec, i as decodePayloadDataEntries, p as isPayloadSpecialModel, s as decodePayloadValueTag } from "./payload-format-KTNaSI4h.js";
|
|
4
|
+
//#region src/payload.ts
|
|
5
|
+
const resolverEntries = /* @__PURE__ */ new WeakMap();
|
|
6
|
+
function createPayloadClientReferenceResolver(resolve) {
|
|
7
|
+
const entries = /* @__PURE__ */ new Map();
|
|
8
|
+
const resolver = Object.assign((reference) => resolve(reference), {
|
|
9
|
+
clear: () => entries.clear(),
|
|
10
|
+
delete: (id) => entries.delete(id)
|
|
11
|
+
});
|
|
12
|
+
resolverEntries.set(resolver, entries);
|
|
13
|
+
return resolver;
|
|
14
|
+
}
|
|
15
|
+
const elementGates = /* @__PURE__ */ new WeakMap();
|
|
16
|
+
const elementAssets = /* @__PURE__ */ new WeakMap();
|
|
17
|
+
var PayloadDecodeAbortedError = class extends Error {
|
|
18
|
+
constructor(reason) {
|
|
19
|
+
super("Payload decode aborted.", reason === void 0 ? void 0 : { cause: reason });
|
|
20
|
+
this.name = "PayloadDecodeAbortedError";
|
|
21
|
+
}
|
|
22
|
+
};
|
|
23
|
+
/**
|
|
24
|
+
* Decode a payload row stream. The returned promise resolves with the
|
|
25
|
+
* decoded root FigNode as soon as the root row decodes (and rejects only
|
|
26
|
+
* when the stream fails before producing a root value, or with the root
|
|
27
|
+
* row's own error); decoding continues in the background, filling outlined
|
|
28
|
+
* holes as their rows arrive. Post-root failures reject the holes they
|
|
29
|
+
* strand and report through `onStreamDone`. Aborting `options.signal`
|
|
30
|
+
* ignores remaining rows and rejects unresolved holes with an internal
|
|
31
|
+
* cancellation reason.
|
|
32
|
+
*/
|
|
33
|
+
function decodePayloadStream(stream, options = {}) {
|
|
34
|
+
return new PayloadStreamDecode(stream, options).value;
|
|
35
|
+
}
|
|
36
|
+
const noop = () => void 0;
|
|
37
|
+
function deferred() {
|
|
38
|
+
let resolve = noop;
|
|
39
|
+
let reject = noop;
|
|
40
|
+
return {
|
|
41
|
+
promise: new Promise((innerResolve, innerReject) => {
|
|
42
|
+
resolve = innerResolve;
|
|
43
|
+
reject = innerReject;
|
|
44
|
+
}),
|
|
45
|
+
reject,
|
|
46
|
+
resolve
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
function decodeAssetResources(serialized) {
|
|
50
|
+
if (serialized === void 0) return null;
|
|
51
|
+
const assets = serialized.filter(isFigAssetResource);
|
|
52
|
+
return assets.length === 0 ? null : assets;
|
|
53
|
+
}
|
|
54
|
+
var PayloadStreamDecode = class {
|
|
55
|
+
options;
|
|
56
|
+
value;
|
|
57
|
+
chunks = /* @__PURE__ */ new Map();
|
|
58
|
+
objectRefs = /* @__PURE__ */ new Map();
|
|
59
|
+
rowGates = /* @__PURE__ */ new Map();
|
|
60
|
+
rowAssets = /* @__PURE__ */ new Map();
|
|
61
|
+
clientRowGates = /* @__PURE__ */ new Map();
|
|
62
|
+
clientRowAssets = /* @__PURE__ */ new Map();
|
|
63
|
+
rowDecoder;
|
|
64
|
+
reader = null;
|
|
65
|
+
done = false;
|
|
66
|
+
gateRelease = deferred();
|
|
67
|
+
removeAbortListener = noop;
|
|
68
|
+
decodeChild = (model) => this.decodeModel(model);
|
|
69
|
+
valueRefs = {
|
|
70
|
+
define: (id, create, fill) => this.defineObjectRef(id, create, fill),
|
|
71
|
+
read: (id) => {
|
|
72
|
+
if (!this.objectRefs.has(id)) throw new Error(`Payload referenced unknown object id ${id}.`);
|
|
73
|
+
return this.objectRefs.get(id);
|
|
74
|
+
}
|
|
75
|
+
};
|
|
76
|
+
constructor(stream, options) {
|
|
77
|
+
this.options = options;
|
|
78
|
+
this.rowDecoder = jsonPayloadCodec.createDecoder((row) => this.handleRow(row));
|
|
79
|
+
this.value = this.chunkPromise(this.getChunk(0));
|
|
80
|
+
this.ingest(stream);
|
|
81
|
+
const signal = options.signal;
|
|
82
|
+
if (signal !== void 0) if (signal.aborted) this.abort(signal.reason);
|
|
83
|
+
else {
|
|
84
|
+
const onAbort = () => this.abort(signal.reason);
|
|
85
|
+
signal.addEventListener("abort", onAbort, { once: true });
|
|
86
|
+
this.removeAbortListener = () => signal.removeEventListener("abort", onAbort);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
abort(reason) {
|
|
90
|
+
if (this.done) return;
|
|
91
|
+
const error = new PayloadDecodeAbortedError(reason);
|
|
92
|
+
this.gateRelease.resolve(void 0);
|
|
93
|
+
this.reader?.cancel(error).catch(noop);
|
|
94
|
+
this.rejectUnresolved(error);
|
|
95
|
+
this.settle({ status: "aborted" });
|
|
96
|
+
}
|
|
97
|
+
async ingest(stream) {
|
|
98
|
+
const reader = stream.getReader();
|
|
99
|
+
this.reader = reader;
|
|
100
|
+
try {
|
|
101
|
+
for (;;) {
|
|
102
|
+
const { done, value } = await reader.read();
|
|
103
|
+
if (this.done) return;
|
|
104
|
+
if (done) break;
|
|
105
|
+
this.rowDecoder.decode(value);
|
|
106
|
+
}
|
|
107
|
+
this.rowDecoder.flush();
|
|
108
|
+
this.finishIngestion();
|
|
109
|
+
} catch (error) {
|
|
110
|
+
if (this.done) return;
|
|
111
|
+
reader.cancel(error).catch(noop);
|
|
112
|
+
this.failIngestion(error);
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
finishIngestion() {
|
|
116
|
+
let truncated = false;
|
|
117
|
+
for (const chunk of this.chunks.values()) if (!chunk.arrived) {
|
|
118
|
+
truncated = true;
|
|
119
|
+
break;
|
|
120
|
+
}
|
|
121
|
+
if (truncated) {
|
|
122
|
+
this.failIngestion(/* @__PURE__ */ new Error("Payload stream ended before all referenced rows arrived."));
|
|
123
|
+
return;
|
|
124
|
+
}
|
|
125
|
+
this.settle({ status: "complete" });
|
|
126
|
+
}
|
|
127
|
+
failIngestion(error) {
|
|
128
|
+
if (this.done) return;
|
|
129
|
+
this.rejectUnresolved(error);
|
|
130
|
+
this.settle({
|
|
131
|
+
status: "failed",
|
|
132
|
+
error
|
|
133
|
+
});
|
|
134
|
+
}
|
|
135
|
+
rejectUnresolved(error) {
|
|
136
|
+
for (const chunk of this.chunks.values()) {
|
|
137
|
+
if (chunk.arrived) continue;
|
|
138
|
+
chunk.arrived = true;
|
|
139
|
+
this.rejectChunk(chunk, error);
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
settle(result) {
|
|
143
|
+
if (this.done) return;
|
|
144
|
+
this.done = true;
|
|
145
|
+
this.removeAbortListener();
|
|
146
|
+
try {
|
|
147
|
+
const observed = this.options.onStreamDone?.(result);
|
|
148
|
+
if (isThenable(observed)) Promise.resolve(observed).then(noop, noop);
|
|
149
|
+
} catch {}
|
|
150
|
+
}
|
|
151
|
+
handleRow(row) {
|
|
152
|
+
if (this.done) return;
|
|
153
|
+
switch (row.tag) {
|
|
154
|
+
case "model": {
|
|
155
|
+
const chunk = this.getChunk(row.id);
|
|
156
|
+
let decoded = this.decodeModel(row.value);
|
|
157
|
+
const retainedAssets = this.rowAssets.get(row.id);
|
|
158
|
+
if (retainedAssets !== void 0) {
|
|
159
|
+
this.rowAssets.delete(row.id);
|
|
160
|
+
decoded = assets(retainedAssets, decoded);
|
|
161
|
+
}
|
|
162
|
+
chunk.arrived = true;
|
|
163
|
+
const gates = this.rowGates.get(row.id);
|
|
164
|
+
if (gates === void 0) {
|
|
165
|
+
this.fulfillChunk(chunk, decoded);
|
|
166
|
+
return;
|
|
167
|
+
}
|
|
168
|
+
this.rowGates.delete(row.id);
|
|
169
|
+
Promise.race([Promise.all(gates), this.gateRelease.promise]).then(() => this.fulfillChunk(chunk, decoded));
|
|
170
|
+
return;
|
|
171
|
+
}
|
|
172
|
+
case "client": {
|
|
173
|
+
const chunk = this.getChunk(row.id);
|
|
174
|
+
const reference = { id: row.value.id };
|
|
175
|
+
if (row.value.exportName !== void 0) reference.exportName = row.value.exportName;
|
|
176
|
+
if (row.value.ssr === true) reference.ssr = true;
|
|
177
|
+
const assets = decodeAssetResources(row.value.assets);
|
|
178
|
+
if (assets !== null) reference.assets = assets;
|
|
179
|
+
const retainedAssets = this.retainedAssets(assets);
|
|
180
|
+
if (retainedAssets !== null) this.clientRowAssets.set(row.id, retainedAssets);
|
|
181
|
+
const gate = this.prepareAssets(assets);
|
|
182
|
+
if (gate !== null) {
|
|
183
|
+
trackThenable(gate);
|
|
184
|
+
this.clientRowGates.set(row.id, gate);
|
|
185
|
+
gate.then(() => {
|
|
186
|
+
this.clientRowGates.delete(row.id);
|
|
187
|
+
});
|
|
188
|
+
}
|
|
189
|
+
const component = this.clientReferenceComponent(reference, gate, retainedAssets !== null);
|
|
190
|
+
chunk.arrived = true;
|
|
191
|
+
this.fulfillChunk(chunk, component);
|
|
192
|
+
return;
|
|
193
|
+
}
|
|
194
|
+
case "error": {
|
|
195
|
+
const chunk = this.getChunk(row.id);
|
|
196
|
+
chunk.arrived = true;
|
|
197
|
+
this.rowGates.delete(row.id);
|
|
198
|
+
this.rowAssets.delete(row.id);
|
|
199
|
+
this.rejectChunk(chunk, errorFromPayloadValue(row.value));
|
|
200
|
+
return;
|
|
201
|
+
}
|
|
202
|
+
case "data": {
|
|
203
|
+
const hydrate = this.options.hydrate;
|
|
204
|
+
if (hydrate === void 0) return;
|
|
205
|
+
hydrate(decodePayloadDataEntries(row.value));
|
|
206
|
+
return;
|
|
207
|
+
}
|
|
208
|
+
case "assets": {
|
|
209
|
+
const decodedAssets = decodeAssetResources(row.value);
|
|
210
|
+
const retainedAssets = this.retainedAssets(decodedAssets);
|
|
211
|
+
if (retainedAssets !== null && row.for !== void 0) {
|
|
212
|
+
const retained = this.rowAssets.get(row.for);
|
|
213
|
+
this.rowAssets.set(row.for, retained === void 0 ? retainedAssets : [...retained, ...retainedAssets]);
|
|
214
|
+
}
|
|
215
|
+
const gate = this.prepareAssets(decodedAssets);
|
|
216
|
+
if (gate === null || row.for === void 0) return;
|
|
217
|
+
const gates = this.rowGates.get(row.for);
|
|
218
|
+
if (gates === void 0) this.rowGates.set(row.for, [gate]);
|
|
219
|
+
else gates.push(gate);
|
|
220
|
+
return;
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
prepareAssets(assets) {
|
|
225
|
+
const prepare = this.options.prepareAssets;
|
|
226
|
+
if (prepare === void 0 || assets === null) return null;
|
|
227
|
+
const delivery = assets.filter((resource) => assetResourceDestination(resource) === "stream");
|
|
228
|
+
if (delivery.length === 0) return null;
|
|
229
|
+
let result;
|
|
230
|
+
try {
|
|
231
|
+
result = prepare(delivery);
|
|
232
|
+
} catch {
|
|
233
|
+
return null;
|
|
234
|
+
}
|
|
235
|
+
if (!isThenable(result)) return null;
|
|
236
|
+
const gate = Promise.resolve(result).then(noop, noop);
|
|
237
|
+
trackThenable(gate);
|
|
238
|
+
return gate;
|
|
239
|
+
}
|
|
240
|
+
retainedAssets(assets) {
|
|
241
|
+
if (assets === null) return null;
|
|
242
|
+
const retained = this.options.retainAssets === true ? assets : assets.filter((resource) => assetResourceDestination(resource) === "head");
|
|
243
|
+
return retained.length === 0 ? null : retained;
|
|
244
|
+
}
|
|
245
|
+
clientReferenceComponent(reference, gate, retainsAssets) {
|
|
246
|
+
const resolve = this.options.resolveClientReference;
|
|
247
|
+
const entries = resolve === void 0 ? void 0 : resolverEntries.get(resolve);
|
|
248
|
+
const existing = entries?.get(reference.id);
|
|
249
|
+
if (existing !== void 0) return existing;
|
|
250
|
+
let resolved;
|
|
251
|
+
try {
|
|
252
|
+
resolved = resolve?.(reference);
|
|
253
|
+
} catch (error) {
|
|
254
|
+
resolved = Promise.reject(error);
|
|
255
|
+
}
|
|
256
|
+
if (resolved === void 0) return function PayloadUnresolvedClientComponent() {
|
|
257
|
+
throw new Error(`Cannot render client reference "${reference.id}" because decodePayloadStream was not configured with a matching resolveClientReference.`);
|
|
258
|
+
};
|
|
259
|
+
if (entries === void 0 && gate === null && !isThenable(resolved) && !retainsAssets) return resolved;
|
|
260
|
+
const component = clientReferenceWrapper(resolved, reference.id);
|
|
261
|
+
entries?.set(reference.id, component);
|
|
262
|
+
return component;
|
|
263
|
+
}
|
|
264
|
+
getChunk(id) {
|
|
265
|
+
const existing = this.chunks.get(id);
|
|
266
|
+
if (existing !== void 0) return existing;
|
|
267
|
+
const chunk = {
|
|
268
|
+
arrived: false,
|
|
269
|
+
deferred: null,
|
|
270
|
+
id,
|
|
271
|
+
promise: null,
|
|
272
|
+
result: { status: "pending" }
|
|
273
|
+
};
|
|
274
|
+
this.chunks.set(id, chunk);
|
|
275
|
+
return chunk;
|
|
276
|
+
}
|
|
277
|
+
chunkPromise(chunk) {
|
|
278
|
+
if (chunk.promise !== null) return chunk.promise;
|
|
279
|
+
if (chunk.result.status === "fulfilled") chunk.promise = Promise.resolve(chunk.result.value);
|
|
280
|
+
else if (chunk.result.status === "rejected") {
|
|
281
|
+
chunk.promise = Promise.reject(chunk.result.error);
|
|
282
|
+
chunk.promise.catch(noop);
|
|
283
|
+
} else {
|
|
284
|
+
chunk.deferred = deferred();
|
|
285
|
+
chunk.promise = chunk.deferred.promise;
|
|
286
|
+
}
|
|
287
|
+
trackThenable(chunk.promise);
|
|
288
|
+
return chunk.promise;
|
|
289
|
+
}
|
|
290
|
+
fulfillChunk(chunk, value) {
|
|
291
|
+
if (chunk.result.status !== "pending") return;
|
|
292
|
+
chunk.result = {
|
|
293
|
+
status: "fulfilled",
|
|
294
|
+
value
|
|
295
|
+
};
|
|
296
|
+
chunk.deferred?.resolve(value);
|
|
297
|
+
}
|
|
298
|
+
rejectChunk(chunk, error) {
|
|
299
|
+
if (chunk.result.status !== "pending") return;
|
|
300
|
+
chunk.result = {
|
|
301
|
+
error,
|
|
302
|
+
status: "rejected"
|
|
303
|
+
};
|
|
304
|
+
if (chunk.deferred !== null) {
|
|
305
|
+
chunk.deferred.reject(error);
|
|
306
|
+
chunk.promise?.catch(noop);
|
|
307
|
+
}
|
|
308
|
+
if (chunk.id !== 0 && !(error instanceof PayloadDecodeAbortedError)) this.observeHoleError(error);
|
|
309
|
+
}
|
|
310
|
+
observeHoleError(error) {
|
|
311
|
+
try {
|
|
312
|
+
const observed = this.options.onHoleError?.(error);
|
|
313
|
+
if (isThenable(observed)) Promise.resolve(observed).then(noop, noop);
|
|
314
|
+
} catch {}
|
|
315
|
+
}
|
|
316
|
+
readChunkForRender(id) {
|
|
317
|
+
const chunk = this.getChunk(id);
|
|
318
|
+
if (chunk.result.status === "rejected") throw chunk.result.error;
|
|
319
|
+
if (chunk.result.status === "pending") return readPromise(this.chunkPromise(chunk));
|
|
320
|
+
return chunk.result.value;
|
|
321
|
+
}
|
|
322
|
+
decodeModel(model) {
|
|
323
|
+
if (model === null) return null;
|
|
324
|
+
if (Array.isArray(model)) return model.map(this.decodeChild);
|
|
325
|
+
if (typeof model !== "object") return model;
|
|
326
|
+
if (isPayloadSpecialModel(model)) return this.decodeSpecialModel(model);
|
|
327
|
+
return decodePayloadRecord(model, this.decodeChild);
|
|
328
|
+
}
|
|
329
|
+
decodeSpecialModel(model) {
|
|
330
|
+
switch (model.$fig) {
|
|
331
|
+
case "element": {
|
|
332
|
+
if (model.id !== void 0) return this.defineObjectRef(model.id, () => ({
|
|
333
|
+
$$typeof: FigElementSymbol,
|
|
334
|
+
key: model.key,
|
|
335
|
+
props: {},
|
|
336
|
+
type: Fragment
|
|
337
|
+
}), (element) => {
|
|
338
|
+
element.type = this.decodeElementType(model.type);
|
|
339
|
+
const props = this.decodeModel(model.props);
|
|
340
|
+
element.props = props;
|
|
341
|
+
this.attachElementDelivery(model.type, props);
|
|
342
|
+
});
|
|
343
|
+
const type = this.decodeElementType(model.type);
|
|
344
|
+
const props = this.decodeModel(model.props);
|
|
345
|
+
if (model.key !== null) props.key = model.key;
|
|
346
|
+
const element = createElement(type, props);
|
|
347
|
+
this.attachElementDelivery(model.type, element.props);
|
|
348
|
+
return element;
|
|
349
|
+
}
|
|
350
|
+
case "client": {
|
|
351
|
+
const chunk = this.chunks.get(model.id);
|
|
352
|
+
if (chunk === void 0 || chunk.result.status !== "fulfilled") throw new Error(`Payload model referenced client row ${model.id} before it arrived.`);
|
|
353
|
+
return chunk.result.value;
|
|
354
|
+
}
|
|
355
|
+
case "fragment": return Fragment;
|
|
356
|
+
case "lazy":
|
|
357
|
+
this.getChunk(model.id);
|
|
358
|
+
return createElement(PayloadStreamHole, {
|
|
359
|
+
decode: this,
|
|
360
|
+
id: model.id
|
|
361
|
+
});
|
|
362
|
+
case "promise": return this.chunkPromise(this.getChunk(model.id));
|
|
363
|
+
case "suspense": return Suspense;
|
|
364
|
+
case "view-transition": return ViewTransition;
|
|
365
|
+
default: return decodePayloadValueTag(model, this.valueRefs, this.decodeChild);
|
|
366
|
+
}
|
|
367
|
+
}
|
|
368
|
+
decodeElementType(type) {
|
|
369
|
+
if (typeof type === "string") return type;
|
|
370
|
+
return this.decodeSpecialModel(type);
|
|
371
|
+
}
|
|
372
|
+
attachElementDelivery(typeModel, props) {
|
|
373
|
+
if (typeof typeModel === "string" || typeModel.$fig !== "client") return;
|
|
374
|
+
const gate = this.clientRowGates.get(typeModel.id);
|
|
375
|
+
if (gate !== void 0) elementGates.set(props, gate);
|
|
376
|
+
const assets = this.clientRowAssets.get(typeModel.id);
|
|
377
|
+
if (assets !== void 0) elementAssets.set(props, assets);
|
|
378
|
+
}
|
|
379
|
+
defineObjectRef(id, create, fill) {
|
|
380
|
+
if (this.objectRefs.has(id)) return this.objectRefs.get(id);
|
|
381
|
+
const value = create();
|
|
382
|
+
this.objectRefs.set(id, value);
|
|
383
|
+
try {
|
|
384
|
+
fill(value);
|
|
385
|
+
return value;
|
|
386
|
+
} catch (error) {
|
|
387
|
+
this.objectRefs.delete(id);
|
|
388
|
+
throw error;
|
|
389
|
+
}
|
|
390
|
+
}
|
|
391
|
+
};
|
|
392
|
+
function PayloadStreamHole(props) {
|
|
393
|
+
return props.decode.readChunkForRender(props.id);
|
|
394
|
+
}
|
|
395
|
+
function clientReferenceWrapper(resolved, referenceId) {
|
|
396
|
+
let render;
|
|
397
|
+
if (!isThenable(resolved)) render = (props) => createElement(resolved, props);
|
|
398
|
+
else {
|
|
399
|
+
const pending = Promise.resolve(resolved);
|
|
400
|
+
trackThenable(pending);
|
|
401
|
+
let type = null;
|
|
402
|
+
render = (props) => {
|
|
403
|
+
if (type === null) type = clientReferenceType(readPromise(pending), referenceId);
|
|
404
|
+
return createElement(type, props);
|
|
405
|
+
};
|
|
406
|
+
}
|
|
407
|
+
function PayloadClientContent(content) {
|
|
408
|
+
if (content.gate !== void 0) readPromise(content.gate);
|
|
409
|
+
return render(content.props);
|
|
410
|
+
}
|
|
411
|
+
return function PayloadClientComponent(props) {
|
|
412
|
+
return attachElementAssets(props, createElement(PayloadClientContent, {
|
|
413
|
+
gate: elementGates.get(props),
|
|
414
|
+
props
|
|
415
|
+
}));
|
|
416
|
+
};
|
|
417
|
+
}
|
|
418
|
+
function attachElementAssets(props, node) {
|
|
419
|
+
const resources = elementAssets.get(props);
|
|
420
|
+
return resources === void 0 ? node : assets(resources, node);
|
|
421
|
+
}
|
|
422
|
+
function clientReferenceType(value, id) {
|
|
423
|
+
if (typeof value === "function") return value;
|
|
424
|
+
throw new Error(`Client reference "${id}" did not resolve to a component.`);
|
|
425
|
+
}
|
|
426
|
+
//#endregion
|
|
427
|
+
export { createPayloadClientReferenceResolver, decodePayloadStream };
|
|
428
|
+
|
|
429
|
+
//# sourceMappingURL=payload.js.map
|