@spotpatch/runtime 1.11.0 → 1.12.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/{chunk-QY5T4DPA.js → chunk-2WA6XVA4.js} +13 -6
- package/dist/chunk-2WA6XVA4.js.map +1 -0
- package/dist/chunk-RZDOL5BT.js +1 -0
- package/dist/chunk-RZDOL5BT.js.map +1 -0
- package/dist/data-flow-panel.cjs +162 -0
- package/dist/data-flow-panel.cjs.map +1 -1
- package/dist/data-flow-panel.d.cts +4 -2
- package/dist/data-flow-panel.d.ts +4 -2
- package/dist/data-flow-panel.js +26 -0
- package/dist/data-flow-panel.js.map +1 -1
- package/dist/{data-flow-runtime-B3itbieT.d.cts → data-flow-runtime-DMmV0d3E.d.cts} +7 -3
- package/dist/{data-flow-runtime-B3itbieT.d.ts → data-flow-runtime-DMmV0d3E.d.ts} +7 -3
- package/dist/data-flow.cjs +12 -5
- package/dist/data-flow.cjs.map +1 -1
- package/dist/data-flow.d.cts +1 -1
- package/dist/data-flow.d.ts +1 -1
- package/dist/data-flow.js +2 -1
- package/dist/index.cjs +12 -5
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +4 -4
- package/package.json +3 -3
- package/dist/chunk-QY5T4DPA.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/ui/data-flow-panel.ts"],"sourcesContent":["import type { DataDependency, SpotPatchLocale } from \"@spotpatch/shared\";\n\nimport { createButton, createMarkedElement } from \"./dom.js\";\nimport type {\n DataFlowPanel,\n DataFlowPanelSnapshot,\n DataFlowViewState,\n} from \"./data-flow-panel-contract.js\";\n\ninterface Labels {\n readonly bindings: string;\n readonly changes: string;\n readonly componentEmpty: string;\n readonly componentTab: string;\n readonly componentTitle: string;\n readonly consumed: string;\n readonly declared: string;\n readonly diagnostics: string;\n readonly disabled: string;\n readonly error: string;\n readonly evidence: string;\n readonly loading: string;\n readonly logicalObserved: string;\n readonly noParameters: string;\n readonly observed: string;\n readonly pageEmpty: string;\n readonly pageTab: string;\n readonly pageTitle: string;\n readonly parameters: string;\n readonly refresh: string;\n readonly unknown: string;\n}\n\nconst LABELS = Object.freeze({\n \"zh-CN\": Object.freeze({\n bindings: \"数据去向\",\n changes: \"修改说明\",\n componentEmpty: \"当前组件没有找到可证明的接口。未找到不等于没有请求。\",\n componentTab: \"数据链路\",\n componentTitle: \"组件数据链路\",\n consumed: \"读取字段\",\n declared: \"代码声明,尚未在本次页面会话中观测\",\n diagnostics: \"诊断\",\n disabled: \"数据链路能力未启用,请在插件配置中设置 dataFlow: {}。\",\n error: \"数据链路报告加载失败\",\n evidence: \"证据\",\n loading: \"正在分析源码并合并运行时证据…\",\n logicalObserved: \"本次会话已进入 tRPC 调用链\",\n noParameters: \"未提取到可证明的参数键\",\n observed: \"本次会话已实际请求\",\n pageEmpty: \"当前已选页面范围内没有静态接口或运行时网络记录。\",\n pageTab: \"页面接口\",\n pageTitle: \"页面接口\",\n parameters: \"请求参数\",\n refresh: \"刷新证据\",\n unknown: \"未知\",\n }),\n \"en-US\": Object.freeze({\n bindings: \"Data destinations\",\n changes: \"Changes\",\n componentEmpty:\n \"No proven interface was found for this component. This does not prove that no request exists.\",\n componentTab: \"Data flow\",\n componentTitle: \"Component data flow\",\n consumed: \"Consumed fields\",\n declared: \"Declared in code, not observed in this page session\",\n diagnostics: \"Diagnostics\",\n disabled: \"Data flow is disabled. Set dataFlow: {} in the plugin options.\",\n error: \"Failed to load the data-flow report\",\n evidence: \"Evidence\",\n loading: \"Analyzing source and merging runtime evidence…\",\n logicalObserved: \"Dispatched through the tRPC link in this session\",\n noParameters: \"No proven parameter keys were extracted\",\n observed: \"Actually requested in this session\",\n pageEmpty:\n \"No static interface or runtime traffic is available for the selected page scope.\",\n pageTab: \"Page APIs\",\n pageTitle: \"Page interfaces\",\n parameters: \"Request parameters\",\n refresh: \"Refresh evidence\",\n unknown: \"Unknown\",\n }),\n}) satisfies Readonly<Record<SpotPatchLocale, Labels>>;\n\nfunction badge(document: Document, text: string, tone: string): HTMLElement {\n const element = createMarkedElement(document, \"span\");\n element.className = \"spotpatch-data-flow-badge\";\n element.dataset.tone = tone;\n element.textContent = text;\n return element;\n}\n\nfunction detailRow(document: Document, label: string, value: string): HTMLElement {\n const row = createMarkedElement(document, \"div\");\n row.className = \"spotpatch-data-flow-detail\";\n const key = createMarkedElement(document, \"span\");\n key.textContent = label;\n const content = createMarkedElement(document, \"code\");\n content.textContent = value;\n row.append(key, content);\n return row;\n}\n\nfunction renderDependency(\n document: Document,\n dependency: DataDependency,\n labels: Labels,\n): HTMLElement {\n const card = createMarkedElement(document, \"article\");\n card.className = \"spotpatch-data-flow-card\";\n const header = createMarkedElement(document, \"div\");\n header.className = \"spotpatch-data-flow-card-head\";\n const endpoint = createMarkedElement(document, \"div\");\n endpoint.className = \"spotpatch-data-flow-endpoint\";\n const method = createMarkedElement(document, \"strong\");\n method.textContent = dependency.method ?? labels.unknown;\n const path = createMarkedElement(document, \"code\");\n path.textContent =\n dependency.url === undefined\n ? (dependency.operation ?? labels.unknown)\n : `${dependency.url.origin ?? \"\"}${dependency.url.pathname}`;\n endpoint.append(method, path);\n const states = createMarkedElement(document, \"div\");\n states.className = \"spotpatch-data-flow-badges\";\n states.append(\n badge(\n document,\n dependency.execution === \"observed\"\n ? dependency.kind === \"rpc\"\n ? labels.logicalObserved\n : labels.observed\n : labels.declared,\n dependency.execution === \"observed\" ? \"success\" : \"neutral\",\n ),\n badge(\n document,\n dependency.proof,\n dependency.proof === \"proven\" ? \"proof\" : \"warning\",\n ),\n badge(document, dependency.association, \"neutral\"),\n );\n header.append(endpoint, states);\n\n const parameters =\n dependency.parameters.length === 0\n ? labels.noParameters\n : dependency.parameters\n .map(\n (parameter) =>\n `${parameter.position}.${parameter.path}${parameter.type === undefined ? \"\" : `: ${parameter.type}`}${parameter.sensitive ? \" [sensitive]\" : \"\"}${parameter.condition === undefined ? \"\" : ` [when ${parameter.condition}]`}`,\n )\n .join(\"\\n\");\n const consumed =\n dependency.response.consumedFields.length === 0\n ? labels.unknown\n : dependency.response.consumedFields.join(\", \");\n const bindings =\n dependency.suppliedBindings.length === 0\n ? labels.unknown\n : dependency.suppliedBindings.join(\", \");\n const body = createMarkedElement(document, \"div\");\n body.className = \"spotpatch-data-flow-card-body\";\n const observationIds = new Set(dependency.observationIds);\n const staticEvidenceCount = dependency.evidenceIds.filter(\n (id) => !observationIds.has(id),\n ).length;\n body.append(\n detailRow(document, labels.parameters, parameters),\n detailRow(document, labels.consumed, consumed),\n detailRow(document, labels.bindings, bindings),\n detailRow(\n document,\n labels.evidence,\n `${String(staticEvidenceCount)} static · ${String(dependency.observationIds.length)} runtime`,\n ),\n );\n card.append(header, body);\n return card;\n}\n\nfunction createReportRoot(\n document: Document,\n titleText: string,\n): Readonly<{ root: HTMLElement; status: HTMLElement; list: HTMLElement }> {\n const root = createMarkedElement(document, \"section\");\n root.className = \"spotpatch-data-flow-panel\";\n const title = createMarkedElement(document, \"h3\");\n title.textContent = titleText;\n const status = createMarkedElement(document, \"p\");\n status.className = \"spotpatch-data-flow-status\";\n const list = createMarkedElement(document, \"div\");\n list.className = \"spotpatch-data-flow-list\";\n root.append(title, status, list);\n return Object.freeze({ root, status, list });\n}\n\nexport function createDataFlowPanel(\n document: Document,\n enabled: boolean,\n locale: () => SpotPatchLocale,\n changesRoot: HTMLElement,\n diagnosticsRoot: HTMLElement,\n onViewChange: () => void,\n): DataFlowPanel {\n let labels = LABELS[locale()];\n const component = createReportRoot(document, labels.componentTitle);\n const page = createReportRoot(document, labels.pageTitle);\n const refreshButton = createButton(document, labels.refresh);\n const styles = document.createElement(\"style\");\n styles.textContent = DATA_FLOW_PANEL_STYLES;\n refreshButton.classList.add(\"spotpatch-data-flow-refresh\");\n component.root.prepend(refreshButton);\n const root = createMarkedElement(document, \"div\");\n const tabs = createMarkedElement(document, \"nav\");\n tabs.className = \"spotpatch-view-tabs\";\n tabs.setAttribute(\"aria-label\", \"SpotPatch views\");\n tabs.setAttribute(\"role\", \"tablist\");\n const views = new Map([\n [\"changes\", changesRoot],\n [\"component-data\", component.root],\n [\"page-data\", page.root],\n [\"diagnostics\", diagnosticsRoot],\n ]);\n const tabButtons = new Map<string, HTMLButtonElement>();\n let activeView = \"changes\";\n for (const id of views.keys()) {\n const button = createButton(document, \"\");\n button.dataset.viewId = id;\n button.id = `spotpatch-view-${id}-tab`;\n button.setAttribute(\"role\", \"tab\");\n button.setAttribute(\"aria-selected\", String(id === activeView));\n const view = views.get(id);\n view?.setAttribute(\"aria-labelledby\", button.id);\n view?.setAttribute(\"role\", \"tabpanel\");\n if (!enabled && (id === \"component-data\" || id === \"page-data\")) {\n button.hidden = true;\n }\n tabButtons.set(id, button);\n tabs.append(button);\n }\n root.append(tabs, ...views.values());\n\n function selectView(viewId: string): void {\n if (!views.has(viewId)) return;\n activeView = viewId;\n for (const [id, view] of views) {\n view.hidden = id !== viewId;\n const button = tabButtons.get(id);\n button?.setAttribute(\"aria-selected\", String(id === viewId));\n if (button !== undefined) button.tabIndex = id === viewId ? 0 : -1;\n }\n onViewChange();\n }\n\n function handleTabClick(event: Event): void {\n if (!(event.target instanceof HTMLButtonElement)) return;\n const viewId = event.target.dataset.viewId;\n if (viewId !== undefined) selectView(viewId);\n }\n\n tabs.addEventListener(\"click\", handleTabClick);\n selectView(activeView);\n\n function renderSnapshot(\n target: ReturnType<typeof createReportRoot>,\n snapshot: DataFlowPanelSnapshot,\n empty: string,\n ): void {\n target.list.replaceChildren();\n target.status.dataset.state = snapshot.status;\n if (!enabled || snapshot.status === \"disabled\") {\n target.status.textContent = labels.disabled;\n return;\n }\n if (snapshot.status === \"loading\") {\n target.status.textContent = labels.loading;\n return;\n }\n if (snapshot.status === \"error\") {\n target.status.textContent = snapshot.message ?? labels.error;\n return;\n }\n const report = snapshot.report;\n const diagnosticCodes =\n report === undefined\n ? \"\"\n : [...new Set(report.diagnostics.map(({ code }) => code))].join(\", \");\n const diagnosticSuffix =\n diagnosticCodes.length === 0\n ? \"\"\n : ` · ${labels.diagnostics}: ${diagnosticCodes}`;\n if (report === undefined || report.dependencies.length === 0) {\n target.status.textContent = `${empty}${diagnosticSuffix}`;\n return;\n }\n target.status.textContent = `${String(report.dependencies.length)} · ${report.completeness.complete ? \"complete\" : \"partial\"}${diagnosticSuffix}`;\n target.list.append(\n ...report.dependencies.map((dependency) =>\n renderDependency(document, dependency, labels),\n ),\n );\n }\n\n return Object.freeze({\n root,\n refreshButton,\n styles,\n dispose(): void {\n tabs.removeEventListener(\"click\", handleTabClick);\n },\n render(state: DataFlowViewState): void {\n labels = LABELS[locale()];\n const tabLabels = [\n labels.changes,\n labels.componentTab,\n labels.pageTab,\n labels.diagnostics,\n ];\n [...tabButtons.values()].forEach((button, index) => {\n button.textContent = tabLabels[index] ?? \"\";\n });\n refreshButton.textContent = `${labels.refresh} · ${String(state.observationCount)}`;\n refreshButton.disabled = !enabled || state.component.status === \"loading\";\n renderSnapshot(component, state.component, labels.componentEmpty);\n renderSnapshot(page, state.page, labels.pageEmpty);\n },\n resetView(): void {\n selectView(\"changes\");\n },\n });\n}\n\nconst DATA_FLOW_PANEL_STYLES = `\n .spotpatch-view-tabs { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 4px; margin-bottom: 12px; padding: 3px; border: 1px solid rgb(255 255 255 / 7%); border-radius: 9px; background: rgb(3 7 18 / 42%); }\n .spotpatch-view-tabs button { min-width: 0; border: 0; border-radius: 7px; padding: 7px 5px; color: var(--spotpatch-text-muted); background: transparent; cursor: pointer; font-size: 10.5px; }\n .spotpatch-view-tabs button[aria-selected=\"true\"] { color: #f8fafc; background: rgb(139 124 247 / 18%); }\n .spotpatch-data-flow-panel { position: relative; }\n .spotpatch-data-flow-panel > h3 { margin: 0 0 3px; color: #f3f4f6; font-size: 13px; }\n .spotpatch-data-flow-refresh { position: absolute; top: -4px; right: 0; border: 1px solid rgb(139 124 247 / 30%); border-radius: 7px; padding: 4px 8px; color: #c4baff; background: rgb(139 124 247 / 8%); cursor: pointer; font-size: 10.5px; }\n .spotpatch-data-flow-refresh:disabled { cursor: not-allowed; opacity: .45; }\n .spotpatch-data-flow-status { margin: 0 0 10px; color: var(--spotpatch-text-muted); font-size: 10.5px; line-height: 1.5; }\n .spotpatch-data-flow-list { display: grid; gap: 8px; }\n .spotpatch-data-flow-card { overflow: hidden; border: 1px solid rgb(255 255 255 / 8%); border-radius: 9px; background: rgb(255 255 255 / 2.5%); }\n .spotpatch-data-flow-card-head { display: grid; gap: 7px; padding: 10px; border-bottom: 1px solid rgb(255 255 255 / 7%); }\n .spotpatch-data-flow-endpoint { display: flex; min-width: 0; align-items: center; gap: 8px; }\n .spotpatch-data-flow-endpoint strong { color: #79d9e7; font: 700 10px/1 ui-monospace, SFMono-Regular, Menlo, monospace; }\n .spotpatch-data-flow-endpoint code { min-width: 0; overflow: hidden; color: #f8fafc; font: 11px/1.4 ui-monospace, SFMono-Regular, Menlo, monospace; text-overflow: ellipsis; white-space: nowrap; }\n .spotpatch-data-flow-badges { display: flex; flex-wrap: wrap; gap: 4px; }\n .spotpatch-data-flow-badge { border-radius: 999px; padding: 2px 6px; color: #9ca3af; background: rgb(255 255 255 / 5%); font-size: 9px; }\n .spotpatch-data-flow-badge[data-tone=\"success\"] { color: #6ee7b7; background: rgb(16 185 129 / 10%); }\n .spotpatch-data-flow-badge[data-tone=\"proof\"] { color: #c4b5fd; background: rgb(139 92 246 / 11%); }\n .spotpatch-data-flow-badge[data-tone=\"warning\"] { color: #fcd34d; background: rgb(245 158 11 / 10%); }\n .spotpatch-data-flow-card-body { display: grid; gap: 7px; padding: 10px; }\n .spotpatch-data-flow-detail { display: grid; grid-template-columns: 82px minmax(0, 1fr); gap: 8px; align-items: start; }\n .spotpatch-data-flow-detail > span { color: var(--spotpatch-text-muted); font-size: 10px; }\n .spotpatch-data-flow-detail > code { overflow-wrap: anywhere; color: #cbd5e1; font: 10px/1.5 ui-monospace, SFMono-Regular, Menlo, monospace; white-space: pre-wrap; }\n`;\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/ui/data-flow-panel.ts","../src/data-flow-panel-entry.ts"],"sourcesContent":["import type { DataDependency, SpotPatchLocale } from \"@spotpatch/shared\";\n\nimport { createButton, createMarkedElement } from \"./dom.js\";\nimport type {\n DataFlowPanel,\n DataFlowPanelSnapshot,\n DataFlowViewState,\n} from \"./data-flow-panel-contract.js\";\n\ninterface Labels {\n readonly bindings: string;\n readonly changes: string;\n readonly componentEmpty: string;\n readonly componentTab: string;\n readonly componentTitle: string;\n readonly consumed: string;\n readonly declared: string;\n readonly diagnostics: string;\n readonly disabled: string;\n readonly error: string;\n readonly evidence: string;\n readonly loading: string;\n readonly logicalObserved: string;\n readonly noParameters: string;\n readonly observed: string;\n readonly pageEmpty: string;\n readonly pageTab: string;\n readonly pageTitle: string;\n readonly parameters: string;\n readonly refresh: string;\n readonly unknown: string;\n}\n\nconst LABELS = Object.freeze({\n \"zh-CN\": Object.freeze({\n bindings: \"数据去向\",\n changes: \"修改说明\",\n componentEmpty: \"当前组件没有找到可证明的接口。未找到不等于没有请求。\",\n componentTab: \"数据链路\",\n componentTitle: \"组件数据链路\",\n consumed: \"读取字段\",\n declared: \"代码声明,尚未在本次页面会话中观测\",\n diagnostics: \"诊断\",\n disabled: \"数据链路能力未启用,请在插件配置中设置 dataFlow: {}。\",\n error: \"数据链路报告加载失败\",\n evidence: \"证据\",\n loading: \"正在分析源码并合并运行时证据…\",\n logicalObserved: \"本次会话已进入 tRPC 调用链\",\n noParameters: \"未提取到可证明的参数键\",\n observed: \"本次会话已实际请求\",\n pageEmpty: \"当前已选页面范围内没有静态接口或运行时网络记录。\",\n pageTab: \"页面接口\",\n pageTitle: \"页面接口\",\n parameters: \"请求参数\",\n refresh: \"刷新证据\",\n unknown: \"未知\",\n }),\n \"en-US\": Object.freeze({\n bindings: \"Data destinations\",\n changes: \"Changes\",\n componentEmpty:\n \"No proven interface was found for this component. This does not prove that no request exists.\",\n componentTab: \"Data flow\",\n componentTitle: \"Component data flow\",\n consumed: \"Consumed fields\",\n declared: \"Declared in code, not observed in this page session\",\n diagnostics: \"Diagnostics\",\n disabled: \"Data flow is disabled. Set dataFlow: {} in the plugin options.\",\n error: \"Failed to load the data-flow report\",\n evidence: \"Evidence\",\n loading: \"Analyzing source and merging runtime evidence…\",\n logicalObserved: \"Dispatched through the tRPC link in this session\",\n noParameters: \"No proven parameter keys were extracted\",\n observed: \"Actually requested in this session\",\n pageEmpty:\n \"No static interface or runtime traffic is available for the selected page scope.\",\n pageTab: \"Page APIs\",\n pageTitle: \"Page interfaces\",\n parameters: \"Request parameters\",\n refresh: \"Refresh evidence\",\n unknown: \"Unknown\",\n }),\n}) satisfies Readonly<Record<SpotPatchLocale, Labels>>;\n\nfunction badge(document: Document, text: string, tone: string): HTMLElement {\n const element = createMarkedElement(document, \"span\");\n element.className = \"spotpatch-data-flow-badge\";\n element.dataset.tone = tone;\n element.textContent = text;\n return element;\n}\n\nfunction detailRow(document: Document, label: string, value: string): HTMLElement {\n const row = createMarkedElement(document, \"div\");\n row.className = \"spotpatch-data-flow-detail\";\n const key = createMarkedElement(document, \"span\");\n key.textContent = label;\n const content = createMarkedElement(document, \"code\");\n content.textContent = value;\n row.append(key, content);\n return row;\n}\n\nfunction renderDependency(\n document: Document,\n dependency: DataDependency,\n labels: Labels,\n): HTMLElement {\n const card = createMarkedElement(document, \"article\");\n card.className = \"spotpatch-data-flow-card\";\n const header = createMarkedElement(document, \"div\");\n header.className = \"spotpatch-data-flow-card-head\";\n const endpoint = createMarkedElement(document, \"div\");\n endpoint.className = \"spotpatch-data-flow-endpoint\";\n const method = createMarkedElement(document, \"strong\");\n method.textContent = dependency.method ?? labels.unknown;\n const path = createMarkedElement(document, \"code\");\n path.textContent =\n dependency.url === undefined\n ? (dependency.operation ?? labels.unknown)\n : `${dependency.url.origin ?? \"\"}${dependency.url.pathname}`;\n endpoint.append(method, path);\n const states = createMarkedElement(document, \"div\");\n states.className = \"spotpatch-data-flow-badges\";\n states.append(\n badge(\n document,\n dependency.execution === \"observed\"\n ? dependency.kind === \"rpc\"\n ? labels.logicalObserved\n : labels.observed\n : labels.declared,\n dependency.execution === \"observed\" ? \"success\" : \"neutral\",\n ),\n badge(\n document,\n dependency.proof,\n dependency.proof === \"proven\" ? \"proof\" : \"warning\",\n ),\n badge(document, dependency.association, \"neutral\"),\n );\n header.append(endpoint, states);\n\n const parameters =\n dependency.parameters.length === 0\n ? labels.noParameters\n : dependency.parameters\n .map(\n (parameter) =>\n `${parameter.position}.${parameter.path}${parameter.type === undefined ? \"\" : `: ${parameter.type}`}${parameter.sensitive ? \" [sensitive]\" : \"\"}${parameter.condition === undefined ? \"\" : ` [when ${parameter.condition}]`}`,\n )\n .join(\"\\n\");\n const consumed =\n dependency.response.consumedFields.length === 0\n ? labels.unknown\n : dependency.response.consumedFields.join(\", \");\n const bindings =\n dependency.suppliedBindings.length === 0\n ? labels.unknown\n : dependency.suppliedBindings.join(\", \");\n const body = createMarkedElement(document, \"div\");\n body.className = \"spotpatch-data-flow-card-body\";\n const observationIds = new Set(dependency.observationIds);\n const staticEvidenceCount = dependency.evidenceIds.filter(\n (id) => !observationIds.has(id),\n ).length;\n body.append(\n detailRow(document, labels.parameters, parameters),\n detailRow(document, labels.consumed, consumed),\n detailRow(document, labels.bindings, bindings),\n detailRow(\n document,\n labels.evidence,\n `${String(staticEvidenceCount)} static · ${String(dependency.observationIds.length)} runtime`,\n ),\n );\n card.append(header, body);\n return card;\n}\n\nfunction createReportRoot(\n document: Document,\n titleText: string,\n): Readonly<{ root: HTMLElement; status: HTMLElement; list: HTMLElement }> {\n const root = createMarkedElement(document, \"section\");\n root.className = \"spotpatch-data-flow-panel\";\n const title = createMarkedElement(document, \"h3\");\n title.textContent = titleText;\n const status = createMarkedElement(document, \"p\");\n status.className = \"spotpatch-data-flow-status\";\n const list = createMarkedElement(document, \"div\");\n list.className = \"spotpatch-data-flow-list\";\n root.append(title, status, list);\n return Object.freeze({ root, status, list });\n}\n\nexport function createDataFlowPanel(\n document: Document,\n enabled: boolean,\n locale: () => SpotPatchLocale,\n changesRoot: HTMLElement,\n diagnosticsRoot: HTMLElement,\n onViewChange: () => void,\n): DataFlowPanel {\n let labels = LABELS[locale()];\n const component = createReportRoot(document, labels.componentTitle);\n const page = createReportRoot(document, labels.pageTitle);\n const refreshButton = createButton(document, labels.refresh);\n const styles = document.createElement(\"style\");\n styles.textContent = DATA_FLOW_PANEL_STYLES;\n refreshButton.classList.add(\"spotpatch-data-flow-refresh\");\n component.root.prepend(refreshButton);\n const root = createMarkedElement(document, \"div\");\n const tabs = createMarkedElement(document, \"nav\");\n tabs.className = \"spotpatch-view-tabs\";\n tabs.setAttribute(\"aria-label\", \"SpotPatch views\");\n tabs.setAttribute(\"role\", \"tablist\");\n const views = new Map([\n [\"changes\", changesRoot],\n [\"component-data\", component.root],\n [\"page-data\", page.root],\n [\"diagnostics\", diagnosticsRoot],\n ]);\n const tabButtons = new Map<string, HTMLButtonElement>();\n let activeView = \"changes\";\n for (const id of views.keys()) {\n const button = createButton(document, \"\");\n button.dataset.viewId = id;\n button.id = `spotpatch-view-${id}-tab`;\n button.setAttribute(\"role\", \"tab\");\n button.setAttribute(\"aria-selected\", String(id === activeView));\n const view = views.get(id);\n view?.setAttribute(\"aria-labelledby\", button.id);\n view?.setAttribute(\"role\", \"tabpanel\");\n if (!enabled && (id === \"component-data\" || id === \"page-data\")) {\n button.hidden = true;\n }\n tabButtons.set(id, button);\n tabs.append(button);\n }\n root.append(tabs, ...views.values());\n\n function selectView(viewId: string): void {\n if (!views.has(viewId)) return;\n activeView = viewId;\n for (const [id, view] of views) {\n view.hidden = id !== viewId;\n const button = tabButtons.get(id);\n button?.setAttribute(\"aria-selected\", String(id === viewId));\n if (button !== undefined) button.tabIndex = id === viewId ? 0 : -1;\n }\n onViewChange();\n }\n\n function handleTabClick(event: Event): void {\n if (!(event.target instanceof HTMLButtonElement)) return;\n const viewId = event.target.dataset.viewId;\n if (viewId !== undefined) selectView(viewId);\n }\n\n tabs.addEventListener(\"click\", handleTabClick);\n selectView(activeView);\n\n function renderSnapshot(\n target: ReturnType<typeof createReportRoot>,\n snapshot: DataFlowPanelSnapshot,\n empty: string,\n ): void {\n target.list.replaceChildren();\n target.status.dataset.state = snapshot.status;\n if (!enabled || snapshot.status === \"disabled\") {\n target.status.textContent = labels.disabled;\n return;\n }\n if (snapshot.status === \"loading\") {\n target.status.textContent = labels.loading;\n return;\n }\n if (snapshot.status === \"error\") {\n target.status.textContent = snapshot.message ?? labels.error;\n return;\n }\n const report = snapshot.report;\n const diagnosticCodes =\n report === undefined\n ? \"\"\n : [...new Set(report.diagnostics.map(({ code }) => code))].join(\", \");\n const diagnosticSuffix =\n diagnosticCodes.length === 0\n ? \"\"\n : ` · ${labels.diagnostics}: ${diagnosticCodes}`;\n if (report === undefined || report.dependencies.length === 0) {\n target.status.textContent = `${empty}${diagnosticSuffix}`;\n return;\n }\n target.status.textContent = `${String(report.dependencies.length)} · ${report.completeness.complete ? \"complete\" : \"partial\"}${diagnosticSuffix}`;\n target.list.append(\n ...report.dependencies.map((dependency) =>\n renderDependency(document, dependency, labels),\n ),\n );\n }\n\n return Object.freeze({\n root,\n refreshButton,\n styles,\n dispose(): void {\n tabs.removeEventListener(\"click\", handleTabClick);\n },\n render(state: DataFlowViewState): void {\n labels = LABELS[locale()];\n const tabLabels = [\n labels.changes,\n labels.componentTab,\n labels.pageTab,\n labels.diagnostics,\n ];\n [...tabButtons.values()].forEach((button, index) => {\n button.textContent = tabLabels[index] ?? \"\";\n });\n refreshButton.textContent = `${labels.refresh} · ${String(state.observationCount)}`;\n refreshButton.disabled = !enabled || state.component.status === \"loading\";\n renderSnapshot(component, state.component, labels.componentEmpty);\n renderSnapshot(page, state.page, labels.pageEmpty);\n },\n resetView(): void {\n selectView(\"changes\");\n },\n });\n}\n\nconst DATA_FLOW_PANEL_STYLES = `\n .spotpatch-view-tabs { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 4px; margin-bottom: 12px; padding: 3px; border: 1px solid rgb(255 255 255 / 7%); border-radius: 9px; background: rgb(3 7 18 / 42%); }\n .spotpatch-view-tabs button { min-width: 0; border: 0; border-radius: 7px; padding: 7px 5px; color: var(--spotpatch-text-muted); background: transparent; cursor: pointer; font-size: 10.5px; }\n .spotpatch-view-tabs button[aria-selected=\"true\"] { color: #f8fafc; background: rgb(139 124 247 / 18%); }\n .spotpatch-data-flow-panel { position: relative; }\n .spotpatch-data-flow-panel > h3 { margin: 0 0 3px; color: #f3f4f6; font-size: 13px; }\n .spotpatch-data-flow-refresh { position: absolute; top: -4px; right: 0; border: 1px solid rgb(139 124 247 / 30%); border-radius: 7px; padding: 4px 8px; color: #c4baff; background: rgb(139 124 247 / 8%); cursor: pointer; font-size: 10.5px; }\n .spotpatch-data-flow-refresh:disabled { cursor: not-allowed; opacity: .45; }\n .spotpatch-data-flow-status { margin: 0 0 10px; color: var(--spotpatch-text-muted); font-size: 10.5px; line-height: 1.5; }\n .spotpatch-data-flow-list { display: grid; gap: 8px; }\n .spotpatch-data-flow-card { overflow: hidden; border: 1px solid rgb(255 255 255 / 8%); border-radius: 9px; background: rgb(255 255 255 / 2.5%); }\n .spotpatch-data-flow-card-head { display: grid; gap: 7px; padding: 10px; border-bottom: 1px solid rgb(255 255 255 / 7%); }\n .spotpatch-data-flow-endpoint { display: flex; min-width: 0; align-items: center; gap: 8px; }\n .spotpatch-data-flow-endpoint strong { color: #79d9e7; font: 700 10px/1 ui-monospace, SFMono-Regular, Menlo, monospace; }\n .spotpatch-data-flow-endpoint code { min-width: 0; overflow: hidden; color: #f8fafc; font: 11px/1.4 ui-monospace, SFMono-Regular, Menlo, monospace; text-overflow: ellipsis; white-space: nowrap; }\n .spotpatch-data-flow-badges { display: flex; flex-wrap: wrap; gap: 4px; }\n .spotpatch-data-flow-badge { border-radius: 999px; padding: 2px 6px; color: #9ca3af; background: rgb(255 255 255 / 5%); font-size: 9px; }\n .spotpatch-data-flow-badge[data-tone=\"success\"] { color: #6ee7b7; background: rgb(16 185 129 / 10%); }\n .spotpatch-data-flow-badge[data-tone=\"proof\"] { color: #c4b5fd; background: rgb(139 92 246 / 11%); }\n .spotpatch-data-flow-badge[data-tone=\"warning\"] { color: #fcd34d; background: rgb(245 158 11 / 10%); }\n .spotpatch-data-flow-card-body { display: grid; gap: 7px; padding: 10px; }\n .spotpatch-data-flow-detail { display: grid; grid-template-columns: 82px minmax(0, 1fr); gap: 8px; align-items: start; }\n .spotpatch-data-flow-detail > span { color: var(--spotpatch-text-muted); font-size: 10px; }\n .spotpatch-data-flow-detail > code { overflow-wrap: anywhere; color: #cbd5e1; font: 10px/1.5 ui-monospace, SFMono-Regular, Menlo, monospace; white-space: pre-wrap; }\n`;\n","export { createDataFlowPanel } from \"./ui/data-flow-panel.js\";\nexport {\n getDataFlowExtension,\n registerDataFlowExtension,\n type DataFlowExtension,\n type DataFlowPanel,\n type DataFlowPanelFactory,\n type DataFlowPanelSnapshot,\n type DataFlowPanelStatus,\n type DataFlowViewState,\n} from \"./ui/data-flow-panel-contract.js\";\n\nimport {\n getDataFlowRuntime,\n mergeComponentDataFlowReport,\n mergePageDataFlowReport,\n} from \"./data-flow-entry.js\";\nimport { createDataFlowPanel } from \"./ui/data-flow-panel.js\";\nimport { registerDataFlowExtension } from \"./ui/data-flow-panel-contract.js\";\n\nexport function installDataFlowPanelExtension(): void {\n registerDataFlowExtension(\n Object.freeze({\n createPanel: createDataFlowPanel,\n getComponentRegistration(component: object) {\n return getDataFlowRuntime()?.getComponentRegistration(component);\n },\n observations(routeKey: string) {\n const runtime = getDataFlowRuntime();\n runtime?.updateRoute(routeKey);\n return runtime?.observations() ?? Object.freeze([]);\n },\n mergeComponentReport: mergeComponentDataFlowReport,\n mergePageReport: mergePageDataFlowReport,\n }),\n );\n}\n"],"mappings":";;;;;;;;;;;;;;;;AAiCA,IAAM,SAAS,OAAO,OAAO;AAAA,EAC3B,SAAS,OAAO,OAAO;AAAA,IACrB,UAAU;AAAA,IACV,SAAS;AAAA,IACT,gBAAgB;AAAA,IAChB,cAAc;AAAA,IACd,gBAAgB;AAAA,IAChB,UAAU;AAAA,IACV,UAAU;AAAA,IACV,aAAa;AAAA,IACb,UAAU;AAAA,IACV,OAAO;AAAA,IACP,UAAU;AAAA,IACV,SAAS;AAAA,IACT,iBAAiB;AAAA,IACjB,cAAc;AAAA,IACd,UAAU;AAAA,IACV,WAAW;AAAA,IACX,SAAS;AAAA,IACT,WAAW;AAAA,IACX,YAAY;AAAA,IACZ,SAAS;AAAA,IACT,SAAS;AAAA,EACX,CAAC;AAAA,EACD,SAAS,OAAO,OAAO;AAAA,IACrB,UAAU;AAAA,IACV,SAAS;AAAA,IACT,gBACE;AAAA,IACF,cAAc;AAAA,IACd,gBAAgB;AAAA,IAChB,UAAU;AAAA,IACV,UAAU;AAAA,IACV,aAAa;AAAA,IACb,UAAU;AAAA,IACV,OAAO;AAAA,IACP,UAAU;AAAA,IACV,SAAS;AAAA,IACT,iBAAiB;AAAA,IACjB,cAAc;AAAA,IACd,UAAU;AAAA,IACV,WACE;AAAA,IACF,SAAS;AAAA,IACT,WAAW;AAAA,IACX,YAAY;AAAA,IACZ,SAAS;AAAA,IACT,SAAS;AAAA,EACX,CAAC;AACH,CAAC;AAED,SAAS,MAAM,UAAoB,MAAc,MAA2B;AAC1E,QAAM,UAAU,oBAAoB,UAAU,MAAM;AACpD,UAAQ,YAAY;AACpB,UAAQ,QAAQ,OAAO;AACvB,UAAQ,cAAc;AACtB,SAAO;AACT;AAEA,SAAS,UAAU,UAAoB,OAAe,OAA4B;AAChF,QAAM,MAAM,oBAAoB,UAAU,KAAK;AAC/C,MAAI,YAAY;AAChB,QAAM,MAAM,oBAAoB,UAAU,MAAM;AAChD,MAAI,cAAc;AAClB,QAAM,UAAU,oBAAoB,UAAU,MAAM;AACpD,UAAQ,cAAc;AACtB,MAAI,OAAO,KAAK,OAAO;AACvB,SAAO;AACT;AAEA,SAAS,iBACP,UACA,YACA,QACa;AACb,QAAM,OAAO,oBAAoB,UAAU,SAAS;AACpD,OAAK,YAAY;AACjB,QAAM,SAAS,oBAAoB,UAAU,KAAK;AAClD,SAAO,YAAY;AACnB,QAAM,WAAW,oBAAoB,UAAU,KAAK;AACpD,WAAS,YAAY;AACrB,QAAM,SAAS,oBAAoB,UAAU,QAAQ;AACrD,SAAO,cAAc,WAAW,UAAU,OAAO;AACjD,QAAM,OAAO,oBAAoB,UAAU,MAAM;AACjD,OAAK,cACH,WAAW,QAAQ,SACd,WAAW,aAAa,OAAO,UAChC,GAAG,WAAW,IAAI,UAAU,EAAE,GAAG,WAAW,IAAI,QAAQ;AAC9D,WAAS,OAAO,QAAQ,IAAI;AAC5B,QAAM,SAAS,oBAAoB,UAAU,KAAK;AAClD,SAAO,YAAY;AACnB,SAAO;AAAA,IACL;AAAA,MACE;AAAA,MACA,WAAW,cAAc,aACrB,WAAW,SAAS,QAClB,OAAO,kBACP,OAAO,WACT,OAAO;AAAA,MACX,WAAW,cAAc,aAAa,YAAY;AAAA,IACpD;AAAA,IACA;AAAA,MACE;AAAA,MACA,WAAW;AAAA,MACX,WAAW,UAAU,WAAW,UAAU;AAAA,IAC5C;AAAA,IACA,MAAM,UAAU,WAAW,aAAa,SAAS;AAAA,EACnD;AACA,SAAO,OAAO,UAAU,MAAM;AAE9B,QAAM,aACJ,WAAW,WAAW,WAAW,IAC7B,OAAO,eACP,WAAW,WACR;AAAA,IACC,CAAC,cACC,GAAG,UAAU,QAAQ,IAAI,UAAU,IAAI,GAAG,UAAU,SAAS,SAAY,KAAK,KAAK,UAAU,IAAI,EAAE,GAAG,UAAU,YAAY,iBAAiB,EAAE,GAAG,UAAU,cAAc,SAAY,KAAK,UAAU,UAAU,SAAS,GAAG;AAAA,EAC/N,EACC,KAAK,IAAI;AAClB,QAAM,WACJ,WAAW,SAAS,eAAe,WAAW,IAC1C,OAAO,UACP,WAAW,SAAS,eAAe,KAAK,IAAI;AAClD,QAAM,WACJ,WAAW,iBAAiB,WAAW,IACnC,OAAO,UACP,WAAW,iBAAiB,KAAK,IAAI;AAC3C,QAAM,OAAO,oBAAoB,UAAU,KAAK;AAChD,OAAK,YAAY;AACjB,QAAM,iBAAiB,IAAI,IAAI,WAAW,cAAc;AACxD,QAAM,sBAAsB,WAAW,YAAY;AAAA,IACjD,CAAC,OAAO,CAAC,eAAe,IAAI,EAAE;AAAA,EAChC,EAAE;AACF,OAAK;AAAA,IACH,UAAU,UAAU,OAAO,YAAY,UAAU;AAAA,IACjD,UAAU,UAAU,OAAO,UAAU,QAAQ;AAAA,IAC7C,UAAU,UAAU,OAAO,UAAU,QAAQ;AAAA,IAC7C;AAAA,MACE;AAAA,MACA,OAAO;AAAA,MACP,GAAG,OAAO,mBAAmB,CAAC,gBAAa,OAAO,WAAW,eAAe,MAAM,CAAC;AAAA,IACrF;AAAA,EACF;AACA,OAAK,OAAO,QAAQ,IAAI;AACxB,SAAO;AACT;AAEA,SAAS,iBACP,UACA,WACyE;AACzE,QAAM,OAAO,oBAAoB,UAAU,SAAS;AACpD,OAAK,YAAY;AACjB,QAAM,QAAQ,oBAAoB,UAAU,IAAI;AAChD,QAAM,cAAc;AACpB,QAAM,SAAS,oBAAoB,UAAU,GAAG;AAChD,SAAO,YAAY;AACnB,QAAM,OAAO,oBAAoB,UAAU,KAAK;AAChD,OAAK,YAAY;AACjB,OAAK,OAAO,OAAO,QAAQ,IAAI;AAC/B,SAAO,OAAO,OAAO,EAAE,MAAM,QAAQ,KAAK,CAAC;AAC7C;AAEO,SAAS,oBACd,UACA,SACA,QACA,aACA,iBACA,cACe;AACf,MAAI,SAAS,OAAO,OAAO,CAAC;AAC5B,QAAM,YAAY,iBAAiB,UAAU,OAAO,cAAc;AAClE,QAAM,OAAO,iBAAiB,UAAU,OAAO,SAAS;AACxD,QAAM,gBAAgB,aAAa,UAAU,OAAO,OAAO;AAC3D,QAAM,SAAS,SAAS,cAAc,OAAO;AAC7C,SAAO,cAAc;AACrB,gBAAc,UAAU,IAAI,6BAA6B;AACzD,YAAU,KAAK,QAAQ,aAAa;AACpC,QAAM,OAAO,oBAAoB,UAAU,KAAK;AAChD,QAAM,OAAO,oBAAoB,UAAU,KAAK;AAChD,OAAK,YAAY;AACjB,OAAK,aAAa,cAAc,iBAAiB;AACjD,OAAK,aAAa,QAAQ,SAAS;AACnC,QAAM,QAAQ,oBAAI,IAAI;AAAA,IACpB,CAAC,WAAW,WAAW;AAAA,IACvB,CAAC,kBAAkB,UAAU,IAAI;AAAA,IACjC,CAAC,aAAa,KAAK,IAAI;AAAA,IACvB,CAAC,eAAe,eAAe;AAAA,EACjC,CAAC;AACD,QAAM,aAAa,oBAAI,IAA+B;AACtD,MAAI,aAAa;AACjB,aAAW,MAAM,MAAM,KAAK,GAAG;AAC7B,UAAM,SAAS,aAAa,UAAU,EAAE;AACxC,WAAO,QAAQ,SAAS;AACxB,WAAO,KAAK,kBAAkB,EAAE;AAChC,WAAO,aAAa,QAAQ,KAAK;AACjC,WAAO,aAAa,iBAAiB,OAAO,OAAO,UAAU,CAAC;AAC9D,UAAM,OAAO,MAAM,IAAI,EAAE;AACzB,UAAM,aAAa,mBAAmB,OAAO,EAAE;AAC/C,UAAM,aAAa,QAAQ,UAAU;AACrC,QAAI,CAAC,YAAY,OAAO,oBAAoB,OAAO,cAAc;AAC/D,aAAO,SAAS;AAAA,IAClB;AACA,eAAW,IAAI,IAAI,MAAM;AACzB,SAAK,OAAO,MAAM;AAAA,EACpB;AACA,OAAK,OAAO,MAAM,GAAG,MAAM,OAAO,CAAC;AAEnC,WAAS,WAAW,QAAsB;AACxC,QAAI,CAAC,MAAM,IAAI,MAAM,EAAG;AACxB,iBAAa;AACb,eAAW,CAAC,IAAI,IAAI,KAAK,OAAO;AAC9B,WAAK,SAAS,OAAO;AACrB,YAAM,SAAS,WAAW,IAAI,EAAE;AAChC,cAAQ,aAAa,iBAAiB,OAAO,OAAO,MAAM,CAAC;AAC3D,UAAI,WAAW,OAAW,QAAO,WAAW,OAAO,SAAS,IAAI;AAAA,IAClE;AACA,iBAAa;AAAA,EACf;AAEA,WAAS,eAAe,OAAoB;AAC1C,QAAI,EAAE,MAAM,kBAAkB,mBAAoB;AAClD,UAAM,SAAS,MAAM,OAAO,QAAQ;AACpC,QAAI,WAAW,OAAW,YAAW,MAAM;AAAA,EAC7C;AAEA,OAAK,iBAAiB,SAAS,cAAc;AAC7C,aAAW,UAAU;AAErB,WAAS,eACP,QACA,UACA,OACM;AACN,WAAO,KAAK,gBAAgB;AAC5B,WAAO,OAAO,QAAQ,QAAQ,SAAS;AACvC,QAAI,CAAC,WAAW,SAAS,WAAW,YAAY;AAC9C,aAAO,OAAO,cAAc,OAAO;AACnC;AAAA,IACF;AACA,QAAI,SAAS,WAAW,WAAW;AACjC,aAAO,OAAO,cAAc,OAAO;AACnC;AAAA,IACF;AACA,QAAI,SAAS,WAAW,SAAS;AAC/B,aAAO,OAAO,cAAc,SAAS,WAAW,OAAO;AACvD;AAAA,IACF;AACA,UAAM,SAAS,SAAS;AACxB,UAAM,kBACJ,WAAW,SACP,KACA,CAAC,GAAG,IAAI,IAAI,OAAO,YAAY,IAAI,CAAC,EAAE,KAAK,MAAM,IAAI,CAAC,CAAC,EAAE,KAAK,IAAI;AACxE,UAAM,mBACJ,gBAAgB,WAAW,IACvB,KACA,SAAM,OAAO,WAAW,KAAK,eAAe;AAClD,QAAI,WAAW,UAAa,OAAO,aAAa,WAAW,GAAG;AAC5D,aAAO,OAAO,cAAc,GAAG,KAAK,GAAG,gBAAgB;AACvD;AAAA,IACF;AACA,WAAO,OAAO,cAAc,GAAG,OAAO,OAAO,aAAa,MAAM,CAAC,SAAM,OAAO,aAAa,WAAW,aAAa,SAAS,GAAG,gBAAgB;AAC/I,WAAO,KAAK;AAAA,MACV,GAAG,OAAO,aAAa;AAAA,QAAI,CAAC,eAC1B,iBAAiB,UAAU,YAAY,MAAM;AAAA,MAC/C;AAAA,IACF;AAAA,EACF;AAEA,SAAO,OAAO,OAAO;AAAA,IACnB;AAAA,IACA;AAAA,IACA;AAAA,IACA,UAAgB;AACd,WAAK,oBAAoB,SAAS,cAAc;AAAA,IAClD;AAAA,IACA,OAAO,OAAgC;AACrC,eAAS,OAAO,OAAO,CAAC;AACxB,YAAM,YAAY;AAAA,QAChB,OAAO;AAAA,QACP,OAAO;AAAA,QACP,OAAO;AAAA,QACP,OAAO;AAAA,MACT;AACA,OAAC,GAAG,WAAW,OAAO,CAAC,EAAE,QAAQ,CAAC,QAAQ,UAAU;AAClD,eAAO,cAAc,UAAU,KAAK,KAAK;AAAA,MAC3C,CAAC;AACD,oBAAc,cAAc,GAAG,OAAO,OAAO,SAAM,OAAO,MAAM,gBAAgB,CAAC;AACjF,oBAAc,WAAW,CAAC,WAAW,MAAM,UAAU,WAAW;AAChE,qBAAe,WAAW,MAAM,WAAW,OAAO,cAAc;AAChE,qBAAe,MAAM,MAAM,MAAM,OAAO,SAAS;AAAA,IACnD;AAAA,IACA,YAAkB;AAChB,iBAAW,SAAS;AAAA,IACtB;AAAA,EACF,CAAC;AACH;AAEA,IAAM,yBAAyB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACxTxB,SAAS,gCAAsC;AACpD;AAAA,IACE,OAAO,OAAO;AAAA,MACZ,aAAa;AAAA,MACb,yBAAyB,WAAmB;AAC1C,eAAO,mBAAmB,GAAG,yBAAyB,SAAS;AAAA,MACjE;AAAA,MACA,aAAa,UAAkB;AAC7B,cAAM,UAAU,mBAAmB;AACnC,iBAAS,YAAY,QAAQ;AAC7B,eAAO,SAAS,aAAa,KAAK,OAAO,OAAO,CAAC,CAAC;AAAA,MACpD;AAAA,MACA,sBAAsB;AAAA,MACtB,iBAAiB;AAAA,IACnB,CAAC;AAAA,EACH;AACF;","names":[]}
|
|
@@ -40,6 +40,10 @@ interface DataFlowRuntime {
|
|
|
40
40
|
readonly withInvocation: <Result>(token: DataFlowInvocationToken | undefined, callback: () => Result) => Result;
|
|
41
41
|
readonly withRequestFrame: <Result>(token: DataFlowInvocationToken | undefined, metadata: DataFlowRequestMetadata, callback: () => Result) => Result;
|
|
42
42
|
}
|
|
43
|
+
interface DataFlowObservationPolicy {
|
|
44
|
+
readonly shouldObserveFetch?: (input: RequestInfo | URL, init: RequestInit | undefined, baseUrl: string) => boolean;
|
|
45
|
+
readonly shouldObserveXhr?: (url: string, baseUrl: string) => boolean;
|
|
46
|
+
}
|
|
43
47
|
interface DataFlowTrpcOperation {
|
|
44
48
|
readonly path: unknown;
|
|
45
49
|
readonly type: unknown;
|
|
@@ -60,8 +64,8 @@ interface MutableDataFlowGlobal extends DataFlowGlobal {
|
|
|
60
64
|
}
|
|
61
65
|
type DataFlowRuntimeStore = Partial<Record<symbol, DataFlowRuntime>>;
|
|
62
66
|
type GlobalWithDataFlow = MutableDataFlowGlobal & DataFlowRuntimeStore;
|
|
63
|
-
declare function createDataFlowRuntime(config: RuntimeDataFlowConfig, target?: MutableDataFlowGlobal): DataFlowRuntime;
|
|
64
|
-
declare function installDataFlowPrelude(config: RuntimeDataFlowConfig, target?: GlobalWithDataFlow): DataFlowRuntime | undefined;
|
|
67
|
+
declare function createDataFlowRuntime(config: RuntimeDataFlowConfig, target?: MutableDataFlowGlobal, policy?: DataFlowObservationPolicy): DataFlowRuntime;
|
|
68
|
+
declare function installDataFlowPrelude(config: RuntimeDataFlowConfig, target?: GlobalWithDataFlow, policy?: DataFlowObservationPolicy): DataFlowRuntime | undefined;
|
|
65
69
|
declare function getDataFlowRuntime(target?: GlobalWithDataFlow): DataFlowRuntime | undefined;
|
|
66
70
|
|
|
67
|
-
export { type DataFlowComponentRegistration as D, type DataFlowInvocationToken as a, type DataFlowRequestFrame as b, type DataFlowRequestMetadata as c, type DataFlowRuntime as d, type DataFlowTriggerMetadata as e, createDataFlowRuntime as f, getDataFlowRuntime as g, type
|
|
71
|
+
export { type DataFlowComponentRegistration as D, type DataFlowInvocationToken as a, type DataFlowRequestFrame as b, type DataFlowRequestMetadata as c, type DataFlowRuntime as d, type DataFlowTriggerMetadata as e, createDataFlowRuntime as f, getDataFlowRuntime as g, type DataFlowObservationPolicy as h, installDataFlowPrelude as i, type DataFlowTrpcLink as j, type DataFlowTrpcLinkOptions as k, type DataFlowTrpcOperation as l };
|
|
@@ -40,6 +40,10 @@ interface DataFlowRuntime {
|
|
|
40
40
|
readonly withInvocation: <Result>(token: DataFlowInvocationToken | undefined, callback: () => Result) => Result;
|
|
41
41
|
readonly withRequestFrame: <Result>(token: DataFlowInvocationToken | undefined, metadata: DataFlowRequestMetadata, callback: () => Result) => Result;
|
|
42
42
|
}
|
|
43
|
+
interface DataFlowObservationPolicy {
|
|
44
|
+
readonly shouldObserveFetch?: (input: RequestInfo | URL, init: RequestInit | undefined, baseUrl: string) => boolean;
|
|
45
|
+
readonly shouldObserveXhr?: (url: string, baseUrl: string) => boolean;
|
|
46
|
+
}
|
|
43
47
|
interface DataFlowTrpcOperation {
|
|
44
48
|
readonly path: unknown;
|
|
45
49
|
readonly type: unknown;
|
|
@@ -60,8 +64,8 @@ interface MutableDataFlowGlobal extends DataFlowGlobal {
|
|
|
60
64
|
}
|
|
61
65
|
type DataFlowRuntimeStore = Partial<Record<symbol, DataFlowRuntime>>;
|
|
62
66
|
type GlobalWithDataFlow = MutableDataFlowGlobal & DataFlowRuntimeStore;
|
|
63
|
-
declare function createDataFlowRuntime(config: RuntimeDataFlowConfig, target?: MutableDataFlowGlobal): DataFlowRuntime;
|
|
64
|
-
declare function installDataFlowPrelude(config: RuntimeDataFlowConfig, target?: GlobalWithDataFlow): DataFlowRuntime | undefined;
|
|
67
|
+
declare function createDataFlowRuntime(config: RuntimeDataFlowConfig, target?: MutableDataFlowGlobal, policy?: DataFlowObservationPolicy): DataFlowRuntime;
|
|
68
|
+
declare function installDataFlowPrelude(config: RuntimeDataFlowConfig, target?: GlobalWithDataFlow, policy?: DataFlowObservationPolicy): DataFlowRuntime | undefined;
|
|
65
69
|
declare function getDataFlowRuntime(target?: GlobalWithDataFlow): DataFlowRuntime | undefined;
|
|
66
70
|
|
|
67
|
-
export { type DataFlowComponentRegistration as D, type DataFlowInvocationToken as a, type DataFlowRequestFrame as b, type DataFlowRequestMetadata as c, type DataFlowRuntime as d, type DataFlowTriggerMetadata as e, createDataFlowRuntime as f, getDataFlowRuntime as g, type
|
|
71
|
+
export { type DataFlowComponentRegistration as D, type DataFlowInvocationToken as a, type DataFlowRequestFrame as b, type DataFlowRequestMetadata as c, type DataFlowRuntime as d, type DataFlowTriggerMetadata as e, createDataFlowRuntime as f, getDataFlowRuntime as g, type DataFlowObservationPolicy as h, installDataFlowPrelude as i, type DataFlowTrpcLink as j, type DataFlowTrpcLinkOptions as k, type DataFlowTrpcOperation as l };
|
package/dist/data-flow.cjs
CHANGED
|
@@ -161,7 +161,7 @@ function recordWithoutAffectingHost(record) {
|
|
|
161
161
|
} catch {
|
|
162
162
|
}
|
|
163
163
|
}
|
|
164
|
-
function createDataFlowRuntime(config, target = globalThis) {
|
|
164
|
+
function createDataFlowRuntime(config, target = globalThis, policy = {}) {
|
|
165
165
|
const componentRegistry = /* @__PURE__ */ new WeakMap();
|
|
166
166
|
const xhrMetadata = /* @__PURE__ */ new WeakMap();
|
|
167
167
|
const store = createRingStore(config.limits, target);
|
|
@@ -193,7 +193,11 @@ function createDataFlowRuntime(config, target = globalThis) {
|
|
|
193
193
|
if (isSpotPatchInternalUrl(
|
|
194
194
|
rawUrl,
|
|
195
195
|
target.location?.href ?? "http://spotpatch.invalid/"
|
|
196
|
-
)
|
|
196
|
+
) || policy.shouldObserveFetch?.(
|
|
197
|
+
input,
|
|
198
|
+
init,
|
|
199
|
+
target.location?.href ?? "http://spotpatch.invalid/"
|
|
200
|
+
) === false) {
|
|
197
201
|
return;
|
|
198
202
|
}
|
|
199
203
|
store.add(
|
|
@@ -249,7 +253,10 @@ function createDataFlowRuntime(config, target = globalThis) {
|
|
|
249
253
|
if (metadata === void 0 || isSpotPatchInternalUrl(
|
|
250
254
|
metadata.url,
|
|
251
255
|
target.location?.href ?? "http://spotpatch.invalid/"
|
|
252
|
-
)
|
|
256
|
+
) || policy.shouldObserveXhr?.(
|
|
257
|
+
metadata.url,
|
|
258
|
+
target.location?.href ?? "http://spotpatch.invalid/"
|
|
259
|
+
) === false) {
|
|
253
260
|
return;
|
|
254
261
|
}
|
|
255
262
|
const frame = currentRequestFrame;
|
|
@@ -423,9 +430,9 @@ function createDataFlowRuntime(config, target = globalThis) {
|
|
|
423
430
|
});
|
|
424
431
|
return runtime;
|
|
425
432
|
}
|
|
426
|
-
function installDataFlowPrelude(config, target = globalThis) {
|
|
433
|
+
function installDataFlowPrelude(config, target = globalThis, policy = {}) {
|
|
427
434
|
if (!config.enabled) return void 0;
|
|
428
|
-
const runtime = target[RUNTIME_KEY] ?? createDataFlowRuntime(config, target);
|
|
435
|
+
const runtime = target[RUNTIME_KEY] ?? createDataFlowRuntime(config, target, policy);
|
|
429
436
|
target[RUNTIME_KEY] = runtime;
|
|
430
437
|
return runtime;
|
|
431
438
|
}
|
package/dist/data-flow.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/data-flow-entry.ts","../src/data-flow/data-flow-runtime.ts","../src/data-flow/report-merger.ts"],"sourcesContent":["export {\n createDataFlowRuntime,\n getDataFlowRuntime,\n installDataFlowPrelude,\n type DataFlowComponentRegistration,\n type DataFlowInvocationToken,\n type DataFlowRequestFrame,\n type DataFlowRequestMetadata,\n type DataFlowRuntime,\n type DataFlowTriggerMetadata,\n type DataFlowTrpcLink,\n type DataFlowTrpcLinkOptions,\n type DataFlowTrpcOperation,\n} from \"./data-flow/data-flow-runtime.js\";\nexport {\n mergeComponentDataFlowReport,\n mergePageDataFlowReport,\n} from \"./data-flow/report-merger.js\";\n","import {\n DATA_FLOW_SCHEMA_VERSION,\n DATA_FLOW_URL_QUERY_KEY_LIMIT,\n SPOTPATCH_API_BASE,\n type NetworkObservation,\n type RuntimeDataFlowConfig,\n type RuntimeDataFlowLimits,\n type SanitizedObservedUrl,\n} from \"@spotpatch/shared/data-flow-runtime\";\n\nexport interface DataFlowComponentRegistration {\n readonly componentSourceId: string;\n readonly sourceVersion: string;\n}\n\nexport interface DataFlowInvocationToken {\n readonly invocationId: string;\n readonly componentSourceId: string;\n readonly triggerCallsiteId: string;\n readonly sourceVersion: string;\n}\n\nexport interface DataFlowRequestFrame {\n readonly requestCallsiteId: string;\n readonly sourceVersion: string;\n readonly invocationToken?: DataFlowInvocationToken;\n}\n\nexport interface DataFlowTriggerMetadata {\n readonly componentSourceId: string;\n readonly triggerCallsiteId: string;\n readonly sourceVersion: string;\n}\n\nexport interface DataFlowRequestMetadata {\n readonly requestCallsiteId: string;\n readonly sourceVersion: string;\n}\n\nexport interface DataFlowRuntime {\n readonly beginInvocation: (\n metadata: DataFlowTriggerMetadata,\n ) => DataFlowInvocationToken;\n readonly bindInvocation: <Arguments extends readonly unknown[], Result>(\n token: DataFlowInvocationToken | undefined,\n callback: (...args: Arguments) => Result,\n ) => (...args: Arguments) => Result;\n readonly bindTrigger: <Callback>(\n metadata: DataFlowTriggerMetadata,\n callback: Callback,\n ) => Callback;\n readonly captureInvocation: () => DataFlowInvocationToken | undefined;\n readonly clear: () => void;\n readonly createTrpcLink: () => DataFlowTrpcLink;\n readonly dispose: () => void;\n readonly getComponentRegistration: (\n component: object,\n ) => DataFlowComponentRegistration | undefined;\n readonly getCurrentRequestFrame: () => DataFlowRequestFrame | undefined;\n readonly observations: () => readonly NetworkObservation[];\n readonly updateRoute: (routeKey: string) => void;\n readonly registerComponent: (\n component: object,\n componentSourceId: string,\n sourceVersion: string,\n ) => void;\n readonly withInvocation: <Result>(\n token: DataFlowInvocationToken | undefined,\n callback: () => Result,\n ) => Result;\n readonly withRequestFrame: <Result>(\n token: DataFlowInvocationToken | undefined,\n metadata: DataFlowRequestMetadata,\n callback: () => Result,\n ) => Result;\n}\n\nexport interface DataFlowTrpcOperation {\n readonly path: unknown;\n readonly type: unknown;\n}\n\nexport interface DataFlowTrpcLinkOptions<\n Operation extends DataFlowTrpcOperation,\n Result,\n> {\n readonly next: (operation: Operation) => Result;\n readonly op: Operation;\n}\n\nexport type DataFlowTrpcLink = (\n runtime: unknown,\n) => <Operation extends DataFlowTrpcOperation, Result>(\n options: DataFlowTrpcLinkOptions<Operation, Result>,\n) => Result;\n\ninterface DataFlowGlobal {\n readonly fetch?: typeof globalThis.fetch;\n readonly location?: Location;\n readonly performance?: Performance;\n readonly XMLHttpRequest?: typeof globalThis.XMLHttpRequest;\n}\n\ninterface MutableDataFlowGlobal extends DataFlowGlobal {\n fetch?: typeof globalThis.fetch;\n}\n\ninterface XhrMetadata {\n readonly method: string;\n readonly url: string;\n}\n\ninterface RingEntry {\n readonly bytes: number;\n readonly observation: NetworkObservation;\n readonly recordedAt: number;\n}\n\nconst RUNTIME_KEY: unique symbol = Symbol.for(\n \"spotpatch.data-flow.runtime.v1\",\n) as never;\nconst REACT_MEMO_TYPE = Symbol.for(\"react.memo\");\nconst REACT_FORWARD_REF_TYPE = Symbol.for(\"react.forward_ref\");\n\ntype DataFlowRuntimeStore = Partial<Record<symbol, DataFlowRuntime>>;\ntype GlobalWithDataFlow = MutableDataFlowGlobal & DataFlowRuntimeStore;\n\nfunction positiveNow(target: DataFlowGlobal): number {\n return target.performance?.now() ?? Date.now();\n}\n\nfunction createOpaqueSequence(prefix: string): () => string {\n let sequence = 0;\n const randomPrefix = (() => {\n try {\n const bytes = new Uint8Array(8);\n globalThis.crypto.getRandomValues(bytes);\n return Array.from(bytes, (value) => value.toString(36).padStart(2, \"0\")).join(\"\");\n } catch {\n return \"local\";\n }\n })();\n\n return () => {\n sequence += 1;\n return `${prefix}_${randomPrefix}_${sequence.toString(36)}`;\n };\n}\n\nfunction freezeUrl(value: string, baseUrl: string): SanitizedObservedUrl {\n try {\n const url = new URL(value, baseUrl);\n return Object.freeze({\n origin: url.origin,\n pathname: url.pathname,\n queryKeys: Object.freeze(\n [...new Set(url.searchParams.keys())]\n .sort()\n .slice(0, DATA_FLOW_URL_QUERY_KEY_LIMIT),\n ),\n });\n } catch {\n return Object.freeze({\n pathname: value.split(/[?#]/u, 1)[0] ?? \"{invalid}\",\n queryKeys: Object.freeze([]),\n });\n }\n}\n\nfunction readFetchUrl(input: RequestInfo | URL): string {\n if (typeof input === \"string\") return input;\n if (input instanceof URL) return input.toString();\n return input.url;\n}\n\nfunction readFetchMethod(input: RequestInfo | URL, init?: RequestInit): string {\n if (init?.method !== undefined) return init.method.toUpperCase();\n return typeof Request !== \"undefined\" && input instanceof Request\n ? input.method.toUpperCase()\n : \"GET\";\n}\n\nfunction isSpotPatchInternalUrl(value: string, baseUrl: string): boolean {\n try {\n const pathname = new URL(value, baseUrl).pathname;\n return (\n pathname === SPOTPATCH_API_BASE || pathname.startsWith(`${SPOTPATCH_API_BASE}/`)\n );\n } catch {\n return false;\n }\n}\n\nfunction approximateBytes(value: unknown): number {\n return new TextEncoder().encode(JSON.stringify(value)).byteLength;\n}\n\nfunction createRingStore(\n limits: RuntimeDataFlowLimits,\n target: DataFlowGlobal,\n): Readonly<{\n add: (observation: NetworkObservation) => void;\n clear: () => void;\n values: () => readonly NetworkObservation[];\n}> {\n const entries: RingEntry[] = [];\n let totalBytes = 0;\n\n function removeExpired(now: number): void {\n while (\n entries[0] !== undefined &&\n now - entries[0].recordedAt > limits.observationTtlMs\n ) {\n const removed = entries.shift();\n if (removed !== undefined) totalBytes -= removed.bytes;\n }\n }\n\n return Object.freeze({\n add(observation): void {\n const now = positiveNow(target);\n removeExpired(now);\n const bytes = approximateBytes(observation);\n if (bytes > limits.observationMaxBytes) return;\n entries.push(Object.freeze({ bytes, observation, recordedAt: now }));\n totalBytes += bytes;\n\n while (\n entries.length > limits.observationMaxEntries ||\n totalBytes > limits.observationMaxBytes\n ) {\n const removed = entries.shift();\n if (removed !== undefined) totalBytes -= removed.bytes;\n }\n },\n clear(): void {\n entries.length = 0;\n totalBytes = 0;\n },\n values(): readonly NetworkObservation[] {\n removeExpired(positiveNow(target));\n return Object.freeze(entries.map(({ observation }) => observation));\n },\n });\n}\n\nfunction ownPropertyDescriptor(\n target: object,\n key: PropertyKey,\n): PropertyDescriptor | undefined {\n try {\n return Object.getOwnPropertyDescriptor(target, key);\n } catch {\n return undefined;\n }\n}\n\nfunction nestedReactWrapperComponent(candidate: object): object | undefined {\n const marker: unknown = ownPropertyDescriptor(candidate, \"$$typeof\")?.value;\n const key =\n marker === REACT_MEMO_TYPE\n ? \"type\"\n : marker === REACT_FORWARD_REF_TYPE\n ? \"render\"\n : undefined;\n if (key === undefined) return undefined;\n const nested: unknown = ownPropertyDescriptor(candidate, key)?.value;\n return (typeof nested === \"object\" && nested !== null) || typeof nested === \"function\"\n ? nested\n : undefined;\n}\n\nfunction installWritableDataProperty(\n target: object,\n key: PropertyKey,\n replacement: object,\n original: PropertyDescriptor | undefined = ownPropertyDescriptor(target, key),\n): (() => void) | undefined {\n if (original === undefined || !(\"value\" in original) || !original.writable) {\n return undefined;\n }\n\n try {\n Object.defineProperty(target, key, { ...original, value: replacement });\n } catch {\n return undefined;\n }\n\n return (): void => {\n try {\n if (ownPropertyDescriptor(target, key)?.value === replacement) {\n Object.defineProperty(target, key, original);\n }\n } catch {\n // A host or later wrapper can make the property non-configurable.\n }\n };\n}\n\nfunction recordWithoutAffectingHost(record: () => void): void {\n try {\n record();\n } catch {\n // Observation is optional; the host transport result is authoritative.\n }\n}\n\nexport function createDataFlowRuntime(\n config: RuntimeDataFlowConfig,\n target: MutableDataFlowGlobal = globalThis,\n): DataFlowRuntime {\n const componentRegistry = new WeakMap<object, DataFlowComponentRegistration>();\n const xhrMetadata = new WeakMap<object, XhrMetadata>();\n const store = createRingStore(config.limits, target);\n const nextInvocationId = createOpaqueSequence(\"invocation\");\n const nextObservationId = createOpaqueSequence(\"observation\");\n const pageEpoch = createOpaqueSequence(\"page\")();\n const nextRouteEpoch = createOpaqueSequence(\"route\");\n let routeEpoch = nextRouteEpoch();\n let routeKey: string | undefined;\n let currentInvocation: DataFlowInvocationToken | undefined;\n let currentRequestFrame: DataFlowRequestFrame | undefined;\n let disposed = false;\n\n const originalFetch = (() => {\n try {\n return target.fetch;\n } catch {\n return undefined;\n }\n })();\n function spotPatchFetch(\n this: typeof globalThis,\n input: RequestInfo | URL,\n init?: RequestInit,\n ): Promise<Response> {\n if (originalFetch === undefined) {\n throw new TypeError(\"Fetch is unavailable.\");\n }\n const result = Reflect.apply(originalFetch, this, [input, init]);\n recordWithoutAffectingHost(() => {\n const frame = currentRequestFrame;\n const token = frame?.invocationToken;\n const rawUrl = readFetchUrl(input);\n if (\n isSpotPatchInternalUrl(\n rawUrl,\n target.location?.href ?? \"http://spotpatch.invalid/\",\n )\n ) {\n return;\n }\n store.add(\n Object.freeze({\n schemaVersion: DATA_FLOW_SCHEMA_VERSION,\n id: nextObservationId(),\n pageEpoch,\n routeEpoch,\n ...(frame === undefined\n ? {}\n : {\n requestCallsiteId: frame.requestCallsiteId,\n sourceVersion: frame.sourceVersion,\n }),\n ...(token === undefined\n ? {}\n : {\n invocationId: token.invocationId,\n componentSourceId: token.componentSourceId,\n triggerCallsiteId: token.triggerCallsiteId,\n }),\n transport: \"fetch\",\n method: readFetchMethod(input, init),\n url: freezeUrl(rawUrl, target.location?.href ?? \"http://spotpatch.invalid/\"),\n outcome: \"dispatched\",\n freshness: \"current\",\n diagnosticIds: Object.freeze([]),\n }),\n );\n });\n return result;\n }\n\n const restoreFetch =\n originalFetch === undefined\n ? undefined\n : installWritableDataProperty(target, \"fetch\", spotPatchFetch);\n\n const xhrPrototype = (() => {\n try {\n return target.XMLHttpRequest?.prototype;\n } catch {\n return undefined;\n }\n })();\n const originalOpenDescriptor =\n xhrPrototype === undefined\n ? undefined\n : ownPropertyDescriptor(xhrPrototype, \"open\");\n const originalSendDescriptor =\n xhrPrototype === undefined\n ? undefined\n : ownPropertyDescriptor(xhrPrototype, \"send\");\n\n function spotPatchOpen(\n this: XMLHttpRequest,\n method: string,\n url: string | URL,\n ...rest: readonly unknown[]\n ): void {\n const original: unknown = originalOpenDescriptor?.value;\n if (typeof original === \"function\") {\n Reflect.apply(original, this, [method, url, ...rest]);\n }\n recordWithoutAffectingHost(() => {\n xhrMetadata.set(this, Object.freeze({ method, url: String(url) }));\n });\n }\n\n function spotPatchSend(\n this: XMLHttpRequest,\n body?: Document | XMLHttpRequestBodyInit | null,\n ): void {\n const original: unknown = originalSendDescriptor?.value;\n if (typeof original === \"function\") Reflect.apply(original, this, [body]);\n recordWithoutAffectingHost(() => {\n const metadata = xhrMetadata.get(this);\n if (\n metadata === undefined ||\n isSpotPatchInternalUrl(\n metadata.url,\n target.location?.href ?? \"http://spotpatch.invalid/\",\n )\n ) {\n return;\n }\n const frame = currentRequestFrame;\n const token = frame?.invocationToken;\n store.add(\n Object.freeze({\n schemaVersion: DATA_FLOW_SCHEMA_VERSION,\n id: nextObservationId(),\n pageEpoch,\n routeEpoch,\n ...(frame === undefined\n ? {}\n : {\n requestCallsiteId: frame.requestCallsiteId,\n sourceVersion: frame.sourceVersion,\n }),\n ...(token === undefined\n ? {}\n : {\n invocationId: token.invocationId,\n componentSourceId: token.componentSourceId,\n triggerCallsiteId: token.triggerCallsiteId,\n }),\n transport: \"xhr\",\n method: metadata.method.toUpperCase(),\n url: freezeUrl(\n metadata.url,\n target.location?.href ?? \"http://spotpatch.invalid/\",\n ),\n outcome: \"dispatched\",\n freshness: \"current\",\n diagnosticIds: Object.freeze([]),\n }),\n );\n });\n }\n\n const restoreXhrOpen =\n xhrPrototype === undefined || typeof originalOpenDescriptor?.value !== \"function\"\n ? undefined\n : installWritableDataProperty(\n xhrPrototype,\n \"open\",\n spotPatchOpen,\n originalOpenDescriptor,\n );\n const restoreXhrSend =\n xhrPrototype === undefined || typeof originalSendDescriptor?.value !== \"function\"\n ? undefined\n : installWritableDataProperty(\n xhrPrototype,\n \"send\",\n spotPatchSend,\n originalSendDescriptor,\n );\n\n const runtime: DataFlowRuntime = Object.freeze({\n beginInvocation(metadata: DataFlowTriggerMetadata): DataFlowInvocationToken {\n return Object.freeze({\n invocationId: nextInvocationId(),\n componentSourceId: metadata.componentSourceId,\n triggerCallsiteId: metadata.triggerCallsiteId,\n sourceVersion: metadata.sourceVersion,\n });\n },\n bindInvocation<Arguments extends readonly unknown[], Result>(\n token: DataFlowInvocationToken | undefined,\n callback: (...args: Arguments) => Result,\n ): (...args: Arguments) => Result {\n return function boundInvocation(this: unknown, ...args: Arguments): Result {\n return runtime.withInvocation(token, () => Reflect.apply(callback, this, args));\n };\n },\n bindTrigger<Callback>(\n metadata: DataFlowTriggerMetadata,\n callback: Callback,\n ): Callback {\n if (typeof callback !== \"function\") return callback;\n const callable = callback as (...args: readonly unknown[]) => unknown;\n return function boundTrigger(this: unknown, ...args: readonly unknown[]) {\n const token = runtime.beginInvocation(metadata);\n return runtime.withInvocation(token, () => Reflect.apply(callable, this, args));\n } as Callback;\n },\n captureInvocation: () => currentInvocation,\n clear: store.clear,\n createTrpcLink(): DataFlowTrpcLink {\n return () =>\n <Operation extends DataFlowTrpcOperation, Result>(\n options: DataFlowTrpcLinkOptions<Operation, Result>,\n ): Result => {\n recordWithoutAffectingHost(() => {\n const operation = options.op.path;\n const operationType = options.op.type;\n if (\n typeof operation !== \"string\" ||\n operation.length === 0 ||\n operation.length > 512 ||\n (operationType !== \"query\" &&\n operationType !== \"mutation\" &&\n operationType !== \"subscription\")\n ) {\n return;\n }\n const frame = currentRequestFrame;\n const token = frame?.invocationToken;\n store.add(\n Object.freeze({\n schemaVersion: DATA_FLOW_SCHEMA_VERSION,\n id: nextObservationId(),\n pageEpoch,\n routeEpoch,\n ...(frame === undefined\n ? {}\n : {\n requestCallsiteId: frame.requestCallsiteId,\n sourceVersion: frame.sourceVersion,\n }),\n ...(token === undefined\n ? {}\n : {\n invocationId: token.invocationId,\n componentSourceId: token.componentSourceId,\n triggerCallsiteId: token.triggerCallsiteId,\n }),\n transport: \"trpc\",\n method: operationType.toUpperCase(),\n operation,\n url: Object.freeze({\n pathname: operation,\n queryKeys: Object.freeze([]),\n }),\n outcome: \"dispatched\",\n freshness: \"current\",\n diagnosticIds: Object.freeze([]),\n }),\n );\n });\n return options.next(options.op);\n };\n },\n dispose(): void {\n if (disposed) return;\n disposed = true;\n store.clear();\n restoreFetch?.();\n restoreXhrOpen?.();\n restoreXhrSend?.();\n },\n getComponentRegistration: (component: object) => componentRegistry.get(component),\n getCurrentRequestFrame: () => currentRequestFrame,\n observations: () =>\n Object.freeze(\n store\n .values()\n .map((observation) =>\n observation.routeEpoch === routeEpoch\n ? observation\n : Object.freeze({ ...observation, freshness: \"stale-route\" as const }),\n ),\n ),\n registerComponent(\n component: object,\n componentSourceId: string,\n registeredSourceVersion: string,\n ): void {\n const registration = Object.freeze({\n componentSourceId,\n sourceVersion: registeredSourceVersion,\n });\n const pending = [component];\n const registered = new Set<object>();\n while (pending.length > 0) {\n const candidate = pending.pop();\n if (candidate === undefined || registered.has(candidate)) continue;\n registered.add(candidate);\n componentRegistry.set(candidate, registration);\n\n const nested = nestedReactWrapperComponent(candidate);\n if (nested !== undefined) pending.push(nested);\n }\n },\n updateRoute(nextRouteKey: string): void {\n if (routeKey === undefined) {\n routeKey = nextRouteKey;\n } else if (routeKey !== nextRouteKey) {\n routeKey = nextRouteKey;\n routeEpoch = nextRouteEpoch();\n }\n },\n withInvocation<Result>(\n token: DataFlowInvocationToken | undefined,\n callback: () => Result,\n ): Result {\n const parent = currentInvocation;\n currentInvocation = token;\n try {\n return callback();\n } finally {\n currentInvocation = parent;\n }\n },\n withRequestFrame<Result>(\n token: DataFlowInvocationToken | undefined,\n metadata: DataFlowRequestMetadata,\n callback: () => Result,\n ): Result {\n const parent = currentRequestFrame;\n currentRequestFrame = Object.freeze({\n requestCallsiteId: metadata.requestCallsiteId,\n sourceVersion: metadata.sourceVersion,\n ...(token === undefined ? {} : { invocationToken: token }),\n });\n try {\n return callback();\n } finally {\n currentRequestFrame = parent;\n }\n },\n });\n\n return runtime;\n}\n\nexport function installDataFlowPrelude(\n config: RuntimeDataFlowConfig,\n target: GlobalWithDataFlow = globalThis,\n): DataFlowRuntime | undefined {\n if (!config.enabled) return undefined;\n const runtime = target[RUNTIME_KEY] ?? createDataFlowRuntime(config, target);\n target[RUNTIME_KEY] = runtime;\n return runtime;\n}\n\nexport function getDataFlowRuntime(\n target: GlobalWithDataFlow = globalThis,\n): DataFlowRuntime | undefined {\n return target[RUNTIME_KEY];\n}\n","import {\n isSensitiveName,\n limitDataFlowReportCollections,\n type ComponentDataFlowReport,\n type DataDependency,\n type EvidenceRef,\n type NetworkObservation,\n type PageDataFlowReport,\n} from \"@spotpatch/shared\";\n\nfunction observationMatchesDependency(\n observation: NetworkObservation,\n dependency: DataDependency,\n): boolean {\n const origin = dependency.origin;\n const transportMatches =\n dependency.kind === \"rpc\"\n ? observation.transport === \"trpc\" &&\n dependency.operation !== undefined &&\n observation.operation === dependency.operation\n : dependency.kind === \"http\"\n ? observation.transport === \"fetch\" || observation.transport === \"xhr\"\n : false;\n if (\n !transportMatches ||\n observation.freshness !== \"current\" ||\n origin === undefined ||\n observation.requestCallsiteId !== origin.requestCallsiteId ||\n observation.sourceVersion !== origin.sourceVersion ||\n (dependency.method !== undefined &&\n observation.method.toUpperCase() !== dependency.method.toUpperCase()) ||\n (dependency.url !== undefined &&\n observation.url.pathname !== dependency.url.pathname) ||\n (dependency.url?.origin !== undefined &&\n observation.url.origin !== dependency.url.origin) ||\n (origin.componentSourceId !== undefined &&\n observation.componentSourceId !== undefined &&\n observation.componentSourceId !== origin.componentSourceId) ||\n (origin.triggerCallsiteId !== undefined &&\n observation.triggerCallsiteId !== undefined &&\n observation.triggerCallsiteId !== origin.triggerCallsiteId)\n ) {\n return false;\n }\n\n return (\n dependency.association !== \"transitive\" ||\n (observation.componentSourceId === origin.componentSourceId &&\n observation.triggerCallsiteId === origin.triggerCallsiteId)\n );\n}\n\nfunction runtimeEvidence(observation: NetworkObservation): EvidenceRef {\n return Object.freeze({\n id: observation.id,\n kind: \"runtime-observation\",\n summaryKey: \"dataFlow.evidence.runtimeDispatch\",\n });\n}\n\nfunction mergeDependencies(\n dependencies: readonly DataDependency[],\n observations: readonly NetworkObservation[],\n): Readonly<{\n dependencies: readonly DataDependency[];\n matchedObservationIds: ReadonlySet<string>;\n}> {\n const matchedObservationIds = new Set<string>();\n const merged = dependencies.map((dependency) => {\n const matches = observations.filter((observation) =>\n observationMatchesDependency(observation, dependency),\n );\n for (const observation of matches) matchedObservationIds.add(observation.id);\n if (matches.length === 0) return dependency;\n const observedOrigins = [\n ...new Set(\n matches.flatMap(({ url }) => (url.origin === undefined ? [] : [url.origin])),\n ),\n ];\n const observedOrigin =\n observedOrigins.length === 1 ? observedOrigins[0] : undefined;\n return Object.freeze({\n ...dependency,\n ...(dependency.url === undefined ||\n dependency.url.origin !== undefined ||\n observedOrigin === undefined\n ? {}\n : {\n url: Object.freeze({\n ...dependency.url,\n origin: observedOrigin,\n }),\n }),\n execution: \"observed\" as const,\n observationIds: Object.freeze([\n ...new Set([...dependency.observationIds, ...matches.map(({ id }) => id)]),\n ]),\n evidenceIds: Object.freeze([\n ...new Set([...dependency.evidenceIds, ...matches.map(({ id }) => id)]),\n ]),\n });\n });\n return Object.freeze({\n dependencies: Object.freeze(merged),\n matchedObservationIds,\n });\n}\n\nfunction appendRuntimeEvidence(\n evidence: readonly EvidenceRef[],\n observations: readonly NetworkObservation[],\n matchedIds: ReadonlySet<string>,\n): readonly EvidenceRef[] {\n const existing = new Set(evidence.map(({ id }) => id));\n return Object.freeze([\n ...evidence,\n ...observations.flatMap((observation) =>\n matchedIds.has(observation.id) && !existing.has(observation.id)\n ? [runtimeEvidence(observation)]\n : [],\n ),\n ]);\n}\n\nexport function mergeComponentDataFlowReport(\n report: ComponentDataFlowReport,\n observations: readonly NetworkObservation[],\n): ComponentDataFlowReport {\n const componentObservations = observations.filter(\n (observation) =>\n observation.componentSourceId === undefined ||\n observation.componentSourceId === report.component.componentSourceId,\n );\n const merged = mergeDependencies(report.dependencies, componentObservations);\n return limitDataFlowReportCollections(\n Object.freeze({\n ...report,\n dependencies: merged.dependencies,\n evidence: appendRuntimeEvidence(\n report.evidence,\n componentObservations,\n merged.matchedObservationIds,\n ),\n }),\n { mode: \"observation\" },\n );\n}\n\nfunction unassignedDependency(observation: NetworkObservation): DataDependency {\n const isRpc = observation.transport === \"trpc\";\n return Object.freeze({\n id: observation.id,\n kind: isRpc ? \"rpc\" : \"http\",\n direction:\n observation.method === \"GET\" ||\n observation.method === \"HEAD\" ||\n observation.method === \"QUERY\" ||\n observation.method === \"SUBSCRIPTION\"\n ? \"read\"\n : \"write\",\n execution: \"observed\",\n proof: \"unavailable\",\n association: \"unassigned\",\n method: observation.method,\n ...(isRpc\n ? observation.operation === undefined\n ? {}\n : { operation: observation.operation }\n : { url: observation.url }),\n parameters: Object.freeze(\n (isRpc ? [] : observation.url.queryKeys).map((path) =>\n Object.freeze({\n path,\n position: \"query\" as const,\n sensitive: isSensitiveName(path),\n valueState: \"not-collected\" as const,\n evidenceIds: Object.freeze([observation.id]),\n }),\n ),\n ),\n response: Object.freeze({\n consumedFields: Object.freeze([]),\n }),\n suppliedBindings: Object.freeze([]),\n locationIds: Object.freeze([]),\n evidenceIds: Object.freeze([observation.id]),\n observationIds: Object.freeze([observation.id]),\n });\n}\n\nexport function mergePageDataFlowReport(\n report: PageDataFlowReport,\n observations: readonly NetworkObservation[],\n): PageDataFlowReport {\n const currentObservations = observations.filter(\n ({ freshness }) => freshness === \"current\",\n );\n const merged = mergeDependencies(report.dependencies, currentObservations);\n const unassigned = currentObservations\n .filter(({ id }) => !merged.matchedObservationIds.has(id))\n .map(unassignedDependency);\n const allObservationIds = new Set(currentObservations.map(({ id }) => id));\n return limitDataFlowReportCollections(\n Object.freeze({\n ...report,\n dependencies: Object.freeze([...merged.dependencies, ...unassigned]),\n evidence: appendRuntimeEvidence(\n report.evidence,\n currentObservations,\n allObservationIds,\n ),\n }),\n { mode: \"observation\" },\n );\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/data-flow-entry.ts","../src/data-flow/data-flow-runtime.ts","../src/data-flow/report-merger.ts"],"sourcesContent":["export {\n createDataFlowRuntime,\n getDataFlowRuntime,\n installDataFlowPrelude,\n type DataFlowComponentRegistration,\n type DataFlowInvocationToken,\n type DataFlowObservationPolicy,\n type DataFlowRequestFrame,\n type DataFlowRequestMetadata,\n type DataFlowRuntime,\n type DataFlowTriggerMetadata,\n type DataFlowTrpcLink,\n type DataFlowTrpcLinkOptions,\n type DataFlowTrpcOperation,\n} from \"./data-flow/data-flow-runtime.js\";\nexport {\n mergeComponentDataFlowReport,\n mergePageDataFlowReport,\n} from \"./data-flow/report-merger.js\";\n","import {\n DATA_FLOW_SCHEMA_VERSION,\n DATA_FLOW_URL_QUERY_KEY_LIMIT,\n SPOTPATCH_API_BASE,\n type NetworkObservation,\n type RuntimeDataFlowConfig,\n type RuntimeDataFlowLimits,\n type SanitizedObservedUrl,\n} from \"@spotpatch/shared/data-flow-runtime\";\n\nexport interface DataFlowComponentRegistration {\n readonly componentSourceId: string;\n readonly sourceVersion: string;\n}\n\nexport interface DataFlowInvocationToken {\n readonly invocationId: string;\n readonly componentSourceId: string;\n readonly triggerCallsiteId: string;\n readonly sourceVersion: string;\n}\n\nexport interface DataFlowRequestFrame {\n readonly requestCallsiteId: string;\n readonly sourceVersion: string;\n readonly invocationToken?: DataFlowInvocationToken;\n}\n\nexport interface DataFlowTriggerMetadata {\n readonly componentSourceId: string;\n readonly triggerCallsiteId: string;\n readonly sourceVersion: string;\n}\n\nexport interface DataFlowRequestMetadata {\n readonly requestCallsiteId: string;\n readonly sourceVersion: string;\n}\n\nexport interface DataFlowRuntime {\n readonly beginInvocation: (\n metadata: DataFlowTriggerMetadata,\n ) => DataFlowInvocationToken;\n readonly bindInvocation: <Arguments extends readonly unknown[], Result>(\n token: DataFlowInvocationToken | undefined,\n callback: (...args: Arguments) => Result,\n ) => (...args: Arguments) => Result;\n readonly bindTrigger: <Callback>(\n metadata: DataFlowTriggerMetadata,\n callback: Callback,\n ) => Callback;\n readonly captureInvocation: () => DataFlowInvocationToken | undefined;\n readonly clear: () => void;\n readonly createTrpcLink: () => DataFlowTrpcLink;\n readonly dispose: () => void;\n readonly getComponentRegistration: (\n component: object,\n ) => DataFlowComponentRegistration | undefined;\n readonly getCurrentRequestFrame: () => DataFlowRequestFrame | undefined;\n readonly observations: () => readonly NetworkObservation[];\n readonly updateRoute: (routeKey: string) => void;\n readonly registerComponent: (\n component: object,\n componentSourceId: string,\n sourceVersion: string,\n ) => void;\n readonly withInvocation: <Result>(\n token: DataFlowInvocationToken | undefined,\n callback: () => Result,\n ) => Result;\n readonly withRequestFrame: <Result>(\n token: DataFlowInvocationToken | undefined,\n metadata: DataFlowRequestMetadata,\n callback: () => Result,\n ) => Result;\n}\n\nexport interface DataFlowObservationPolicy {\n readonly shouldObserveFetch?: (\n input: RequestInfo | URL,\n init: RequestInit | undefined,\n baseUrl: string,\n ) => boolean;\n readonly shouldObserveXhr?: (url: string, baseUrl: string) => boolean;\n}\n\nexport interface DataFlowTrpcOperation {\n readonly path: unknown;\n readonly type: unknown;\n}\n\nexport interface DataFlowTrpcLinkOptions<\n Operation extends DataFlowTrpcOperation,\n Result,\n> {\n readonly next: (operation: Operation) => Result;\n readonly op: Operation;\n}\n\nexport type DataFlowTrpcLink = (\n runtime: unknown,\n) => <Operation extends DataFlowTrpcOperation, Result>(\n options: DataFlowTrpcLinkOptions<Operation, Result>,\n) => Result;\n\ninterface DataFlowGlobal {\n readonly fetch?: typeof globalThis.fetch;\n readonly location?: Location;\n readonly performance?: Performance;\n readonly XMLHttpRequest?: typeof globalThis.XMLHttpRequest;\n}\n\ninterface MutableDataFlowGlobal extends DataFlowGlobal {\n fetch?: typeof globalThis.fetch;\n}\n\ninterface XhrMetadata {\n readonly method: string;\n readonly url: string;\n}\n\ninterface RingEntry {\n readonly bytes: number;\n readonly observation: NetworkObservation;\n readonly recordedAt: number;\n}\n\nconst RUNTIME_KEY: unique symbol = Symbol.for(\n \"spotpatch.data-flow.runtime.v1\",\n) as never;\nconst REACT_MEMO_TYPE = Symbol.for(\"react.memo\");\nconst REACT_FORWARD_REF_TYPE = Symbol.for(\"react.forward_ref\");\n\ntype DataFlowRuntimeStore = Partial<Record<symbol, DataFlowRuntime>>;\ntype GlobalWithDataFlow = MutableDataFlowGlobal & DataFlowRuntimeStore;\n\nfunction positiveNow(target: DataFlowGlobal): number {\n return target.performance?.now() ?? Date.now();\n}\n\nfunction createOpaqueSequence(prefix: string): () => string {\n let sequence = 0;\n const randomPrefix = (() => {\n try {\n const bytes = new Uint8Array(8);\n globalThis.crypto.getRandomValues(bytes);\n return Array.from(bytes, (value) => value.toString(36).padStart(2, \"0\")).join(\"\");\n } catch {\n return \"local\";\n }\n })();\n\n return () => {\n sequence += 1;\n return `${prefix}_${randomPrefix}_${sequence.toString(36)}`;\n };\n}\n\nfunction freezeUrl(value: string, baseUrl: string): SanitizedObservedUrl {\n try {\n const url = new URL(value, baseUrl);\n return Object.freeze({\n origin: url.origin,\n pathname: url.pathname,\n queryKeys: Object.freeze(\n [...new Set(url.searchParams.keys())]\n .sort()\n .slice(0, DATA_FLOW_URL_QUERY_KEY_LIMIT),\n ),\n });\n } catch {\n return Object.freeze({\n pathname: value.split(/[?#]/u, 1)[0] ?? \"{invalid}\",\n queryKeys: Object.freeze([]),\n });\n }\n}\n\nfunction readFetchUrl(input: RequestInfo | URL): string {\n if (typeof input === \"string\") return input;\n if (input instanceof URL) return input.toString();\n return input.url;\n}\n\nfunction readFetchMethod(input: RequestInfo | URL, init?: RequestInit): string {\n if (init?.method !== undefined) return init.method.toUpperCase();\n return typeof Request !== \"undefined\" && input instanceof Request\n ? input.method.toUpperCase()\n : \"GET\";\n}\n\nfunction isSpotPatchInternalUrl(value: string, baseUrl: string): boolean {\n try {\n const pathname = new URL(value, baseUrl).pathname;\n return (\n pathname === SPOTPATCH_API_BASE || pathname.startsWith(`${SPOTPATCH_API_BASE}/`)\n );\n } catch {\n return false;\n }\n}\n\nfunction approximateBytes(value: unknown): number {\n return new TextEncoder().encode(JSON.stringify(value)).byteLength;\n}\n\nfunction createRingStore(\n limits: RuntimeDataFlowLimits,\n target: DataFlowGlobal,\n): Readonly<{\n add: (observation: NetworkObservation) => void;\n clear: () => void;\n values: () => readonly NetworkObservation[];\n}> {\n const entries: RingEntry[] = [];\n let totalBytes = 0;\n\n function removeExpired(now: number): void {\n while (\n entries[0] !== undefined &&\n now - entries[0].recordedAt > limits.observationTtlMs\n ) {\n const removed = entries.shift();\n if (removed !== undefined) totalBytes -= removed.bytes;\n }\n }\n\n return Object.freeze({\n add(observation): void {\n const now = positiveNow(target);\n removeExpired(now);\n const bytes = approximateBytes(observation);\n if (bytes > limits.observationMaxBytes) return;\n entries.push(Object.freeze({ bytes, observation, recordedAt: now }));\n totalBytes += bytes;\n\n while (\n entries.length > limits.observationMaxEntries ||\n totalBytes > limits.observationMaxBytes\n ) {\n const removed = entries.shift();\n if (removed !== undefined) totalBytes -= removed.bytes;\n }\n },\n clear(): void {\n entries.length = 0;\n totalBytes = 0;\n },\n values(): readonly NetworkObservation[] {\n removeExpired(positiveNow(target));\n return Object.freeze(entries.map(({ observation }) => observation));\n },\n });\n}\n\nfunction ownPropertyDescriptor(\n target: object,\n key: PropertyKey,\n): PropertyDescriptor | undefined {\n try {\n return Object.getOwnPropertyDescriptor(target, key);\n } catch {\n return undefined;\n }\n}\n\nfunction nestedReactWrapperComponent(candidate: object): object | undefined {\n const marker: unknown = ownPropertyDescriptor(candidate, \"$$typeof\")?.value;\n const key =\n marker === REACT_MEMO_TYPE\n ? \"type\"\n : marker === REACT_FORWARD_REF_TYPE\n ? \"render\"\n : undefined;\n if (key === undefined) return undefined;\n const nested: unknown = ownPropertyDescriptor(candidate, key)?.value;\n return (typeof nested === \"object\" && nested !== null) || typeof nested === \"function\"\n ? nested\n : undefined;\n}\n\nfunction installWritableDataProperty(\n target: object,\n key: PropertyKey,\n replacement: object,\n original: PropertyDescriptor | undefined = ownPropertyDescriptor(target, key),\n): (() => void) | undefined {\n if (original === undefined || !(\"value\" in original) || !original.writable) {\n return undefined;\n }\n\n try {\n Object.defineProperty(target, key, { ...original, value: replacement });\n } catch {\n return undefined;\n }\n\n return (): void => {\n try {\n if (ownPropertyDescriptor(target, key)?.value === replacement) {\n Object.defineProperty(target, key, original);\n }\n } catch {\n // A host or later wrapper can make the property non-configurable.\n }\n };\n}\n\nfunction recordWithoutAffectingHost(record: () => void): void {\n try {\n record();\n } catch {\n // Observation is optional; the host transport result is authoritative.\n }\n}\n\nexport function createDataFlowRuntime(\n config: RuntimeDataFlowConfig,\n target: MutableDataFlowGlobal = globalThis,\n policy: DataFlowObservationPolicy = {},\n): DataFlowRuntime {\n const componentRegistry = new WeakMap<object, DataFlowComponentRegistration>();\n const xhrMetadata = new WeakMap<object, XhrMetadata>();\n const store = createRingStore(config.limits, target);\n const nextInvocationId = createOpaqueSequence(\"invocation\");\n const nextObservationId = createOpaqueSequence(\"observation\");\n const pageEpoch = createOpaqueSequence(\"page\")();\n const nextRouteEpoch = createOpaqueSequence(\"route\");\n let routeEpoch = nextRouteEpoch();\n let routeKey: string | undefined;\n let currentInvocation: DataFlowInvocationToken | undefined;\n let currentRequestFrame: DataFlowRequestFrame | undefined;\n let disposed = false;\n\n const originalFetch = (() => {\n try {\n return target.fetch;\n } catch {\n return undefined;\n }\n })();\n function spotPatchFetch(\n this: typeof globalThis,\n input: RequestInfo | URL,\n init?: RequestInit,\n ): Promise<Response> {\n if (originalFetch === undefined) {\n throw new TypeError(\"Fetch is unavailable.\");\n }\n const result = Reflect.apply(originalFetch, this, [input, init]);\n recordWithoutAffectingHost(() => {\n const frame = currentRequestFrame;\n const token = frame?.invocationToken;\n const rawUrl = readFetchUrl(input);\n if (\n isSpotPatchInternalUrl(\n rawUrl,\n target.location?.href ?? \"http://spotpatch.invalid/\",\n ) ||\n policy.shouldObserveFetch?.(\n input,\n init,\n target.location?.href ?? \"http://spotpatch.invalid/\",\n ) === false\n ) {\n return;\n }\n store.add(\n Object.freeze({\n schemaVersion: DATA_FLOW_SCHEMA_VERSION,\n id: nextObservationId(),\n pageEpoch,\n routeEpoch,\n ...(frame === undefined\n ? {}\n : {\n requestCallsiteId: frame.requestCallsiteId,\n sourceVersion: frame.sourceVersion,\n }),\n ...(token === undefined\n ? {}\n : {\n invocationId: token.invocationId,\n componentSourceId: token.componentSourceId,\n triggerCallsiteId: token.triggerCallsiteId,\n }),\n transport: \"fetch\",\n method: readFetchMethod(input, init),\n url: freezeUrl(rawUrl, target.location?.href ?? \"http://spotpatch.invalid/\"),\n outcome: \"dispatched\",\n freshness: \"current\",\n diagnosticIds: Object.freeze([]),\n }),\n );\n });\n return result;\n }\n\n const restoreFetch =\n originalFetch === undefined\n ? undefined\n : installWritableDataProperty(target, \"fetch\", spotPatchFetch);\n\n const xhrPrototype = (() => {\n try {\n return target.XMLHttpRequest?.prototype;\n } catch {\n return undefined;\n }\n })();\n const originalOpenDescriptor =\n xhrPrototype === undefined\n ? undefined\n : ownPropertyDescriptor(xhrPrototype, \"open\");\n const originalSendDescriptor =\n xhrPrototype === undefined\n ? undefined\n : ownPropertyDescriptor(xhrPrototype, \"send\");\n\n function spotPatchOpen(\n this: XMLHttpRequest,\n method: string,\n url: string | URL,\n ...rest: readonly unknown[]\n ): void {\n const original: unknown = originalOpenDescriptor?.value;\n if (typeof original === \"function\") {\n Reflect.apply(original, this, [method, url, ...rest]);\n }\n recordWithoutAffectingHost(() => {\n xhrMetadata.set(this, Object.freeze({ method, url: String(url) }));\n });\n }\n\n function spotPatchSend(\n this: XMLHttpRequest,\n body?: Document | XMLHttpRequestBodyInit | null,\n ): void {\n const original: unknown = originalSendDescriptor?.value;\n if (typeof original === \"function\") Reflect.apply(original, this, [body]);\n recordWithoutAffectingHost(() => {\n const metadata = xhrMetadata.get(this);\n if (\n metadata === undefined ||\n isSpotPatchInternalUrl(\n metadata.url,\n target.location?.href ?? \"http://spotpatch.invalid/\",\n ) ||\n policy.shouldObserveXhr?.(\n metadata.url,\n target.location?.href ?? \"http://spotpatch.invalid/\",\n ) === false\n ) {\n return;\n }\n const frame = currentRequestFrame;\n const token = frame?.invocationToken;\n store.add(\n Object.freeze({\n schemaVersion: DATA_FLOW_SCHEMA_VERSION,\n id: nextObservationId(),\n pageEpoch,\n routeEpoch,\n ...(frame === undefined\n ? {}\n : {\n requestCallsiteId: frame.requestCallsiteId,\n sourceVersion: frame.sourceVersion,\n }),\n ...(token === undefined\n ? {}\n : {\n invocationId: token.invocationId,\n componentSourceId: token.componentSourceId,\n triggerCallsiteId: token.triggerCallsiteId,\n }),\n transport: \"xhr\",\n method: metadata.method.toUpperCase(),\n url: freezeUrl(\n metadata.url,\n target.location?.href ?? \"http://spotpatch.invalid/\",\n ),\n outcome: \"dispatched\",\n freshness: \"current\",\n diagnosticIds: Object.freeze([]),\n }),\n );\n });\n }\n\n const restoreXhrOpen =\n xhrPrototype === undefined || typeof originalOpenDescriptor?.value !== \"function\"\n ? undefined\n : installWritableDataProperty(\n xhrPrototype,\n \"open\",\n spotPatchOpen,\n originalOpenDescriptor,\n );\n const restoreXhrSend =\n xhrPrototype === undefined || typeof originalSendDescriptor?.value !== \"function\"\n ? undefined\n : installWritableDataProperty(\n xhrPrototype,\n \"send\",\n spotPatchSend,\n originalSendDescriptor,\n );\n\n const runtime: DataFlowRuntime = Object.freeze({\n beginInvocation(metadata: DataFlowTriggerMetadata): DataFlowInvocationToken {\n return Object.freeze({\n invocationId: nextInvocationId(),\n componentSourceId: metadata.componentSourceId,\n triggerCallsiteId: metadata.triggerCallsiteId,\n sourceVersion: metadata.sourceVersion,\n });\n },\n bindInvocation<Arguments extends readonly unknown[], Result>(\n token: DataFlowInvocationToken | undefined,\n callback: (...args: Arguments) => Result,\n ): (...args: Arguments) => Result {\n return function boundInvocation(this: unknown, ...args: Arguments): Result {\n return runtime.withInvocation(token, () => Reflect.apply(callback, this, args));\n };\n },\n bindTrigger<Callback>(\n metadata: DataFlowTriggerMetadata,\n callback: Callback,\n ): Callback {\n if (typeof callback !== \"function\") return callback;\n const callable = callback as (...args: readonly unknown[]) => unknown;\n return function boundTrigger(this: unknown, ...args: readonly unknown[]) {\n const token = runtime.beginInvocation(metadata);\n return runtime.withInvocation(token, () => Reflect.apply(callable, this, args));\n } as Callback;\n },\n captureInvocation: () => currentInvocation,\n clear: store.clear,\n createTrpcLink(): DataFlowTrpcLink {\n return () =>\n <Operation extends DataFlowTrpcOperation, Result>(\n options: DataFlowTrpcLinkOptions<Operation, Result>,\n ): Result => {\n recordWithoutAffectingHost(() => {\n const operation = options.op.path;\n const operationType = options.op.type;\n if (\n typeof operation !== \"string\" ||\n operation.length === 0 ||\n operation.length > 512 ||\n (operationType !== \"query\" &&\n operationType !== \"mutation\" &&\n operationType !== \"subscription\")\n ) {\n return;\n }\n const frame = currentRequestFrame;\n const token = frame?.invocationToken;\n store.add(\n Object.freeze({\n schemaVersion: DATA_FLOW_SCHEMA_VERSION,\n id: nextObservationId(),\n pageEpoch,\n routeEpoch,\n ...(frame === undefined\n ? {}\n : {\n requestCallsiteId: frame.requestCallsiteId,\n sourceVersion: frame.sourceVersion,\n }),\n ...(token === undefined\n ? {}\n : {\n invocationId: token.invocationId,\n componentSourceId: token.componentSourceId,\n triggerCallsiteId: token.triggerCallsiteId,\n }),\n transport: \"trpc\",\n method: operationType.toUpperCase(),\n operation,\n url: Object.freeze({\n pathname: operation,\n queryKeys: Object.freeze([]),\n }),\n outcome: \"dispatched\",\n freshness: \"current\",\n diagnosticIds: Object.freeze([]),\n }),\n );\n });\n return options.next(options.op);\n };\n },\n dispose(): void {\n if (disposed) return;\n disposed = true;\n store.clear();\n restoreFetch?.();\n restoreXhrOpen?.();\n restoreXhrSend?.();\n },\n getComponentRegistration: (component: object) => componentRegistry.get(component),\n getCurrentRequestFrame: () => currentRequestFrame,\n observations: () =>\n Object.freeze(\n store\n .values()\n .map((observation) =>\n observation.routeEpoch === routeEpoch\n ? observation\n : Object.freeze({ ...observation, freshness: \"stale-route\" as const }),\n ),\n ),\n registerComponent(\n component: object,\n componentSourceId: string,\n registeredSourceVersion: string,\n ): void {\n const registration = Object.freeze({\n componentSourceId,\n sourceVersion: registeredSourceVersion,\n });\n const pending = [component];\n const registered = new Set<object>();\n while (pending.length > 0) {\n const candidate = pending.pop();\n if (candidate === undefined || registered.has(candidate)) continue;\n registered.add(candidate);\n componentRegistry.set(candidate, registration);\n\n const nested = nestedReactWrapperComponent(candidate);\n if (nested !== undefined) pending.push(nested);\n }\n },\n updateRoute(nextRouteKey: string): void {\n if (routeKey === undefined) {\n routeKey = nextRouteKey;\n } else if (routeKey !== nextRouteKey) {\n routeKey = nextRouteKey;\n routeEpoch = nextRouteEpoch();\n }\n },\n withInvocation<Result>(\n token: DataFlowInvocationToken | undefined,\n callback: () => Result,\n ): Result {\n const parent = currentInvocation;\n currentInvocation = token;\n try {\n return callback();\n } finally {\n currentInvocation = parent;\n }\n },\n withRequestFrame<Result>(\n token: DataFlowInvocationToken | undefined,\n metadata: DataFlowRequestMetadata,\n callback: () => Result,\n ): Result {\n const parent = currentRequestFrame;\n currentRequestFrame = Object.freeze({\n requestCallsiteId: metadata.requestCallsiteId,\n sourceVersion: metadata.sourceVersion,\n ...(token === undefined ? {} : { invocationToken: token }),\n });\n try {\n return callback();\n } finally {\n currentRequestFrame = parent;\n }\n },\n });\n\n return runtime;\n}\n\nexport function installDataFlowPrelude(\n config: RuntimeDataFlowConfig,\n target: GlobalWithDataFlow = globalThis,\n policy: DataFlowObservationPolicy = {},\n): DataFlowRuntime | undefined {\n if (!config.enabled) return undefined;\n const runtime = target[RUNTIME_KEY] ?? createDataFlowRuntime(config, target, policy);\n target[RUNTIME_KEY] = runtime;\n return runtime;\n}\n\nexport function getDataFlowRuntime(\n target: GlobalWithDataFlow = globalThis,\n): DataFlowRuntime | undefined {\n return target[RUNTIME_KEY];\n}\n","import {\n isSensitiveName,\n limitDataFlowReportCollections,\n type ComponentDataFlowReport,\n type DataDependency,\n type EvidenceRef,\n type NetworkObservation,\n type PageDataFlowReport,\n} from \"@spotpatch/shared\";\n\nfunction observationMatchesDependency(\n observation: NetworkObservation,\n dependency: DataDependency,\n): boolean {\n const origin = dependency.origin;\n const transportMatches =\n dependency.kind === \"rpc\"\n ? observation.transport === \"trpc\" &&\n dependency.operation !== undefined &&\n observation.operation === dependency.operation\n : dependency.kind === \"http\"\n ? observation.transport === \"fetch\" || observation.transport === \"xhr\"\n : false;\n if (\n !transportMatches ||\n observation.freshness !== \"current\" ||\n origin === undefined ||\n observation.requestCallsiteId !== origin.requestCallsiteId ||\n observation.sourceVersion !== origin.sourceVersion ||\n (dependency.method !== undefined &&\n observation.method.toUpperCase() !== dependency.method.toUpperCase()) ||\n (dependency.url !== undefined &&\n observation.url.pathname !== dependency.url.pathname) ||\n (dependency.url?.origin !== undefined &&\n observation.url.origin !== dependency.url.origin) ||\n (origin.componentSourceId !== undefined &&\n observation.componentSourceId !== undefined &&\n observation.componentSourceId !== origin.componentSourceId) ||\n (origin.triggerCallsiteId !== undefined &&\n observation.triggerCallsiteId !== undefined &&\n observation.triggerCallsiteId !== origin.triggerCallsiteId)\n ) {\n return false;\n }\n\n return (\n dependency.association !== \"transitive\" ||\n (observation.componentSourceId === origin.componentSourceId &&\n observation.triggerCallsiteId === origin.triggerCallsiteId)\n );\n}\n\nfunction runtimeEvidence(observation: NetworkObservation): EvidenceRef {\n return Object.freeze({\n id: observation.id,\n kind: \"runtime-observation\",\n summaryKey: \"dataFlow.evidence.runtimeDispatch\",\n });\n}\n\nfunction mergeDependencies(\n dependencies: readonly DataDependency[],\n observations: readonly NetworkObservation[],\n): Readonly<{\n dependencies: readonly DataDependency[];\n matchedObservationIds: ReadonlySet<string>;\n}> {\n const matchedObservationIds = new Set<string>();\n const merged = dependencies.map((dependency) => {\n const matches = observations.filter((observation) =>\n observationMatchesDependency(observation, dependency),\n );\n for (const observation of matches) matchedObservationIds.add(observation.id);\n if (matches.length === 0) return dependency;\n const observedOrigins = [\n ...new Set(\n matches.flatMap(({ url }) => (url.origin === undefined ? [] : [url.origin])),\n ),\n ];\n const observedOrigin =\n observedOrigins.length === 1 ? observedOrigins[0] : undefined;\n return Object.freeze({\n ...dependency,\n ...(dependency.url === undefined ||\n dependency.url.origin !== undefined ||\n observedOrigin === undefined\n ? {}\n : {\n url: Object.freeze({\n ...dependency.url,\n origin: observedOrigin,\n }),\n }),\n execution: \"observed\" as const,\n observationIds: Object.freeze([\n ...new Set([...dependency.observationIds, ...matches.map(({ id }) => id)]),\n ]),\n evidenceIds: Object.freeze([\n ...new Set([...dependency.evidenceIds, ...matches.map(({ id }) => id)]),\n ]),\n });\n });\n return Object.freeze({\n dependencies: Object.freeze(merged),\n matchedObservationIds,\n });\n}\n\nfunction appendRuntimeEvidence(\n evidence: readonly EvidenceRef[],\n observations: readonly NetworkObservation[],\n matchedIds: ReadonlySet<string>,\n): readonly EvidenceRef[] {\n const existing = new Set(evidence.map(({ id }) => id));\n return Object.freeze([\n ...evidence,\n ...observations.flatMap((observation) =>\n matchedIds.has(observation.id) && !existing.has(observation.id)\n ? [runtimeEvidence(observation)]\n : [],\n ),\n ]);\n}\n\nexport function mergeComponentDataFlowReport(\n report: ComponentDataFlowReport,\n observations: readonly NetworkObservation[],\n): ComponentDataFlowReport {\n const componentObservations = observations.filter(\n (observation) =>\n observation.componentSourceId === undefined ||\n observation.componentSourceId === report.component.componentSourceId,\n );\n const merged = mergeDependencies(report.dependencies, componentObservations);\n return limitDataFlowReportCollections(\n Object.freeze({\n ...report,\n dependencies: merged.dependencies,\n evidence: appendRuntimeEvidence(\n report.evidence,\n componentObservations,\n merged.matchedObservationIds,\n ),\n }),\n { mode: \"observation\" },\n );\n}\n\nfunction unassignedDependency(observation: NetworkObservation): DataDependency {\n const isRpc = observation.transport === \"trpc\";\n return Object.freeze({\n id: observation.id,\n kind: isRpc ? \"rpc\" : \"http\",\n direction:\n observation.method === \"GET\" ||\n observation.method === \"HEAD\" ||\n observation.method === \"QUERY\" ||\n observation.method === \"SUBSCRIPTION\"\n ? \"read\"\n : \"write\",\n execution: \"observed\",\n proof: \"unavailable\",\n association: \"unassigned\",\n method: observation.method,\n ...(isRpc\n ? observation.operation === undefined\n ? {}\n : { operation: observation.operation }\n : { url: observation.url }),\n parameters: Object.freeze(\n (isRpc ? [] : observation.url.queryKeys).map((path) =>\n Object.freeze({\n path,\n position: \"query\" as const,\n sensitive: isSensitiveName(path),\n valueState: \"not-collected\" as const,\n evidenceIds: Object.freeze([observation.id]),\n }),\n ),\n ),\n response: Object.freeze({\n consumedFields: Object.freeze([]),\n }),\n suppliedBindings: Object.freeze([]),\n locationIds: Object.freeze([]),\n evidenceIds: Object.freeze([observation.id]),\n observationIds: Object.freeze([observation.id]),\n });\n}\n\nexport function mergePageDataFlowReport(\n report: PageDataFlowReport,\n observations: readonly NetworkObservation[],\n): PageDataFlowReport {\n const currentObservations = observations.filter(\n ({ freshness }) => freshness === \"current\",\n );\n const merged = mergeDependencies(report.dependencies, currentObservations);\n const unassigned = currentObservations\n .filter(({ id }) => !merged.matchedObservationIds.has(id))\n .map(unassignedDependency);\n const allObservationIds = new Set(currentObservations.map(({ id }) => id));\n return limitDataFlowReportCollections(\n Object.freeze({\n ...report,\n dependencies: Object.freeze([...merged.dependencies, ...unassigned]),\n evidence: appendRuntimeEvidence(\n report.evidence,\n currentObservations,\n allObservationIds,\n ),\n }),\n { mode: \"observation\" },\n );\n}\n"],"mappings":"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","names":[]}
|
package/dist/data-flow.d.cts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { D as DataFlowComponentRegistration, a as DataFlowInvocationToken, b as DataFlowRequestFrame, c as DataFlowRequestMetadata, d as DataFlowRuntime, e as DataFlowTriggerMetadata,
|
|
1
|
+
export { D as DataFlowComponentRegistration, a as DataFlowInvocationToken, h as DataFlowObservationPolicy, b as DataFlowRequestFrame, c as DataFlowRequestMetadata, d as DataFlowRuntime, e as DataFlowTriggerMetadata, j as DataFlowTrpcLink, k as DataFlowTrpcLinkOptions, l as DataFlowTrpcOperation, f as createDataFlowRuntime, g as getDataFlowRuntime, i as installDataFlowPrelude } from './data-flow-runtime-DMmV0d3E.cjs';
|
|
2
2
|
import { ComponentDataFlowReport, NetworkObservation, PageDataFlowReport } from '@spotpatch/shared';
|
|
3
3
|
import '@spotpatch/shared/data-flow-runtime';
|
|
4
4
|
|
package/dist/data-flow.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { D as DataFlowComponentRegistration, a as DataFlowInvocationToken, b as DataFlowRequestFrame, c as DataFlowRequestMetadata, d as DataFlowRuntime, e as DataFlowTriggerMetadata,
|
|
1
|
+
export { D as DataFlowComponentRegistration, a as DataFlowInvocationToken, h as DataFlowObservationPolicy, b as DataFlowRequestFrame, c as DataFlowRequestMetadata, d as DataFlowRuntime, e as DataFlowTriggerMetadata, j as DataFlowTrpcLink, k as DataFlowTrpcLinkOptions, l as DataFlowTrpcOperation, f as createDataFlowRuntime, g as getDataFlowRuntime, i as installDataFlowPrelude } from './data-flow-runtime-DMmV0d3E.js';
|
|
2
2
|
import { ComponentDataFlowReport, NetworkObservation, PageDataFlowReport } from '@spotpatch/shared';
|
|
3
3
|
import '@spotpatch/shared/data-flow-runtime';
|
|
4
4
|
|
package/dist/data-flow.js
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
|
+
import "./chunk-RZDOL5BT.js";
|
|
1
2
|
import {
|
|
2
3
|
createDataFlowRuntime,
|
|
3
4
|
getDataFlowRuntime,
|
|
4
5
|
installDataFlowPrelude,
|
|
5
6
|
mergeComponentDataFlowReport,
|
|
6
7
|
mergePageDataFlowReport
|
|
7
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-2WA6XVA4.js";
|
|
8
9
|
export {
|
|
9
10
|
createDataFlowRuntime,
|
|
10
11
|
getDataFlowRuntime,
|
package/dist/index.cjs
CHANGED
|
@@ -6264,7 +6264,7 @@ function recordWithoutAffectingHost(record2) {
|
|
|
6264
6264
|
} catch {
|
|
6265
6265
|
}
|
|
6266
6266
|
}
|
|
6267
|
-
function createDataFlowRuntime(config, target2 = globalThis) {
|
|
6267
|
+
function createDataFlowRuntime(config, target2 = globalThis, policy = {}) {
|
|
6268
6268
|
const componentRegistry = /* @__PURE__ */ new WeakMap();
|
|
6269
6269
|
const xhrMetadata = /* @__PURE__ */ new WeakMap();
|
|
6270
6270
|
const store = createRingStore(config.limits, target2);
|
|
@@ -6296,7 +6296,11 @@ function createDataFlowRuntime(config, target2 = globalThis) {
|
|
|
6296
6296
|
if (isSpotPatchInternalUrl(
|
|
6297
6297
|
rawUrl,
|
|
6298
6298
|
target2.location?.href ?? "http://spotpatch.invalid/"
|
|
6299
|
-
)
|
|
6299
|
+
) || policy.shouldObserveFetch?.(
|
|
6300
|
+
input,
|
|
6301
|
+
init,
|
|
6302
|
+
target2.location?.href ?? "http://spotpatch.invalid/"
|
|
6303
|
+
) === false) {
|
|
6300
6304
|
return;
|
|
6301
6305
|
}
|
|
6302
6306
|
store.add(
|
|
@@ -6352,7 +6356,10 @@ function createDataFlowRuntime(config, target2 = globalThis) {
|
|
|
6352
6356
|
if (metadata === void 0 || isSpotPatchInternalUrl(
|
|
6353
6357
|
metadata.url,
|
|
6354
6358
|
target2.location?.href ?? "http://spotpatch.invalid/"
|
|
6355
|
-
)
|
|
6359
|
+
) || policy.shouldObserveXhr?.(
|
|
6360
|
+
metadata.url,
|
|
6361
|
+
target2.location?.href ?? "http://spotpatch.invalid/"
|
|
6362
|
+
) === false) {
|
|
6356
6363
|
return;
|
|
6357
6364
|
}
|
|
6358
6365
|
const frame = currentRequestFrame;
|
|
@@ -6526,9 +6533,9 @@ function createDataFlowRuntime(config, target2 = globalThis) {
|
|
|
6526
6533
|
});
|
|
6527
6534
|
return runtime;
|
|
6528
6535
|
}
|
|
6529
|
-
function installDataFlowPrelude(config, target2 = globalThis) {
|
|
6536
|
+
function installDataFlowPrelude(config, target2 = globalThis, policy = {}) {
|
|
6530
6537
|
if (!config.enabled) return void 0;
|
|
6531
|
-
const runtime = target2[RUNTIME_KEY] ?? createDataFlowRuntime(config, target2);
|
|
6538
|
+
const runtime = target2[RUNTIME_KEY] ?? createDataFlowRuntime(config, target2, policy);
|
|
6532
6539
|
target2[RUNTIME_KEY] = runtime;
|
|
6533
6540
|
return runtime;
|
|
6534
6541
|
}
|