@flanksource/clicky-ui 0.3.41 → 0.3.42
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/ai.cjs +4 -0
- package/dist/ai.cjs.map +1 -1
- package/dist/ai.js +4 -0
- package/dist/ai.js.map +1 -1
- package/dist/comments/CommentCard.cjs +3 -1
- package/dist/comments/CommentCard.cjs.map +1 -1
- package/dist/comments/CommentCard.d.ts.map +1 -1
- package/dist/comments/CommentCard.js +4 -2
- package/dist/comments/CommentCard.js.map +1 -1
- package/dist/comments/CommentCardParts.cjs +16 -0
- package/dist/comments/CommentCardParts.cjs.map +1 -1
- package/dist/comments/CommentCardParts.d.ts +4 -1
- package/dist/comments/CommentCardParts.d.ts.map +1 -1
- package/dist/comments/CommentCardParts.js +16 -0
- package/dist/comments/CommentCardParts.js.map +1 -1
- package/dist/comments/comment-types.cjs.map +1 -1
- package/dist/comments/comment-types.d.ts +4 -0
- package/dist/comments/comment-types.d.ts.map +1 -1
- package/dist/comments/comment-types.js.map +1 -1
- package/dist/components/Combobox.cjs +54 -8
- package/dist/components/Combobox.cjs.map +1 -1
- package/dist/components/Combobox.d.ts.map +1 -1
- package/dist/components/Combobox.js +56 -10
- package/dist/components/Combobox.js.map +1 -1
- package/dist/components/ComboboxMenu.cjs +139 -113
- package/dist/components/ComboboxMenu.cjs.map +1 -1
- package/dist/components/ComboboxMenu.d.ts +3 -1
- package/dist/components/ComboboxMenu.d.ts.map +1 -1
- package/dist/components/ComboboxMenu.js +139 -113
- package/dist/components/ComboboxMenu.js.map +1 -1
- package/dist/components/ComboboxMenuTrigger.cjs +87 -0
- package/dist/components/ComboboxMenuTrigger.cjs.map +1 -0
- package/dist/components/ComboboxMenuTrigger.d.ts +23 -0
- package/dist/components/ComboboxMenuTrigger.d.ts.map +1 -0
- package/dist/components/ComboboxMenuTrigger.js +87 -0
- package/dist/components/ComboboxMenuTrigger.js.map +1 -0
- package/dist/components/JsonSchemaForm.cjs +30 -7
- package/dist/components/JsonSchemaForm.cjs.map +1 -1
- package/dist/components/JsonSchemaForm.d.ts.map +1 -1
- package/dist/components/JsonSchemaForm.js +30 -7
- package/dist/components/JsonSchemaForm.js.map +1 -1
- package/dist/components/SegmentedControl.cjs +20 -3
- package/dist/components/SegmentedControl.cjs.map +1 -1
- package/dist/components/SegmentedControl.d.ts +11 -0
- package/dist/components/SegmentedControl.d.ts.map +1 -1
- package/dist/components/SegmentedControl.js +21 -4
- package/dist/components/SegmentedControl.js.map +1 -1
- package/dist/components/combobox-types.d.ts +8 -0
- package/dist/components/combobox-types.d.ts.map +1 -1
- package/dist/components/json-schema-form-debug-badge.cjs +108 -0
- package/dist/components/json-schema-form-debug-badge.cjs.map +1 -0
- package/dist/components/json-schema-form-debug-badge.d.ts +10 -0
- package/dist/components/json-schema-form-debug-badge.d.ts.map +1 -0
- package/dist/components/json-schema-form-debug-badge.js +108 -0
- package/dist/components/json-schema-form-debug-badge.js.map +1 -0
- package/dist/components/json-schema-form-debug-glyph-map.cjs +129 -0
- package/dist/components/json-schema-form-debug-glyph-map.cjs.map +1 -0
- package/dist/components/json-schema-form-debug-glyph-map.d.ts +20 -0
- package/dist/components/json-schema-form-debug-glyph-map.d.ts.map +1 -0
- package/dist/components/json-schema-form-debug-glyph-map.js +129 -0
- package/dist/components/json-schema-form-debug-glyph-map.js.map +1 -0
- package/dist/components/json-schema-form-debug-glyph.cjs +13 -0
- package/dist/components/json-schema-form-debug-glyph.cjs.map +1 -0
- package/dist/components/json-schema-form-debug-glyph.d.ts +6 -0
- package/dist/components/json-schema-form-debug-glyph.d.ts.map +1 -0
- package/dist/components/json-schema-form-debug-glyph.js +13 -0
- package/dist/components/json-schema-form-debug-glyph.js.map +1 -0
- package/dist/components/json-schema-form-debug-groups.cjs +56 -0
- package/dist/components/json-schema-form-debug-groups.cjs.map +1 -0
- package/dist/components/json-schema-form-debug-groups.d.ts +8 -0
- package/dist/components/json-schema-form-debug-groups.d.ts.map +1 -0
- package/dist/components/json-schema-form-debug-groups.js +56 -0
- package/dist/components/json-schema-form-debug-groups.js.map +1 -0
- package/dist/components/json-schema-form-debug-keywords.cjs +159 -0
- package/dist/components/json-schema-form-debug-keywords.cjs.map +1 -0
- package/dist/components/json-schema-form-debug-keywords.d.ts +6 -0
- package/dist/components/json-schema-form-debug-keywords.d.ts.map +1 -0
- package/dist/components/json-schema-form-debug-keywords.js +159 -0
- package/dist/components/json-schema-form-debug-keywords.js.map +1 -0
- package/dist/components/json-schema-form-debug-listeners.cjs +102 -0
- package/dist/components/json-schema-form-debug-listeners.cjs.map +1 -0
- package/dist/components/json-schema-form-debug-listeners.d.ts +6 -0
- package/dist/components/json-schema-form-debug-listeners.d.ts.map +1 -0
- package/dist/components/json-schema-form-debug-listeners.js +102 -0
- package/dist/components/json-schema-form-debug-listeners.js.map +1 -0
- package/dist/components/json-schema-form-debug.cjs +31 -0
- package/dist/components/json-schema-form-debug.cjs.map +1 -0
- package/dist/components/json-schema-form-debug.d.ts +11 -0
- package/dist/components/json-schema-form-debug.d.ts.map +1 -0
- package/dist/components/json-schema-form-debug.js +31 -0
- package/dist/components/json-schema-form-debug.js.map +1 -0
- package/dist/components/json-schema-form-enum-choice.cjs +114 -0
- package/dist/components/json-schema-form-enum-choice.cjs.map +1 -0
- package/dist/components/json-schema-form-enum-choice.d.ts +14 -0
- package/dist/components/json-schema-form-enum-choice.d.ts.map +1 -0
- package/dist/components/json-schema-form-enum-choice.js +114 -0
- package/dist/components/json-schema-form-enum-choice.js.map +1 -0
- package/dist/components/json-schema-form-fields.cjs +3 -93
- package/dist/components/json-schema-form-fields.cjs.map +1 -1
- package/dist/components/json-schema-form-fields.d.ts.map +1 -1
- package/dist/components/json-schema-form-fields.js +1 -91
- package/dist/components/json-schema-form-fields.js.map +1 -1
- package/dist/components/json-schema-form-listeners.cjs +7 -1
- package/dist/components/json-schema-form-listeners.cjs.map +1 -1
- package/dist/components/json-schema-form-listeners.d.ts.map +1 -1
- package/dist/components/json-schema-form-listeners.js +7 -1
- package/dist/components/json-schema-form-listeners.js.map +1 -1
- package/dist/components/json-schema-form-preferences.cjs +1 -0
- package/dist/components/json-schema-form-preferences.cjs.map +1 -1
- package/dist/components/json-schema-form-preferences.d.ts +1 -0
- package/dist/components/json-schema-form-preferences.d.ts.map +1 -1
- package/dist/components/json-schema-form-preferences.js +1 -0
- package/dist/components/json-schema-form-preferences.js.map +1 -1
- package/dist/components/json-schema-form-render.cjs +21 -5
- package/dist/components/json-schema-form-render.cjs.map +1 -1
- package/dist/components/json-schema-form-render.d.ts.map +1 -1
- package/dist/components/json-schema-form-render.js +21 -5
- package/dist/components/json-schema-form-render.js.map +1 -1
- package/dist/components/json-schema-form-runtime-types.d.ts +1 -0
- package/dist/components/json-schema-form-runtime-types.d.ts.map +1 -1
- package/dist/components/json-schema-form-tone.cjs +12 -0
- package/dist/components/json-schema-form-tone.cjs.map +1 -1
- package/dist/components/json-schema-form-tone.js +12 -0
- package/dist/components/json-schema-form-tone.js.map +1 -1
- package/dist/components/json-schema-form-types.d.ts +1 -0
- package/dist/components/json-schema-form-types.d.ts.map +1 -1
- package/dist/data/GraphDiagram.cjs +125 -138
- package/dist/data/GraphDiagram.cjs.map +1 -1
- package/dist/data/GraphDiagram.d.ts +30 -23
- package/dist/data/GraphDiagram.d.ts.map +1 -1
- package/dist/data/GraphDiagram.js +128 -141
- package/dist/data/GraphDiagram.js.map +1 -1
- package/dist/data/GraphDiagramEdges.cjs +208 -0
- package/dist/data/GraphDiagramEdges.cjs.map +1 -0
- package/dist/data/GraphDiagramEdges.d.ts +40 -0
- package/dist/data/GraphDiagramEdges.d.ts.map +1 -0
- package/dist/data/GraphDiagramEdges.js +208 -0
- package/dist/data/GraphDiagramEdges.js.map +1 -0
- package/dist/data/GraphDiagramNodes.cjs +142 -0
- package/dist/data/GraphDiagramNodes.cjs.map +1 -0
- package/dist/data/GraphDiagramNodes.d.ts +22 -0
- package/dist/data/GraphDiagramNodes.d.ts.map +1 -0
- package/dist/data/GraphDiagramNodes.js +142 -0
- package/dist/data/GraphDiagramNodes.js.map +1 -0
- package/dist/data/ai/PromptRunEditor/RuntimeRows.cjs +8 -3
- package/dist/data/ai/PromptRunEditor/RuntimeRows.cjs.map +1 -1
- package/dist/data/ai/PromptRunEditor/RuntimeRows.d.ts.map +1 -1
- package/dist/data/ai/PromptRunEditor/RuntimeRows.js +8 -3
- package/dist/data/ai/PromptRunEditor/RuntimeRows.js.map +1 -1
- package/dist/data/ai/PromptRunEditor/index.cjs +37 -43
- package/dist/data/ai/PromptRunEditor/index.cjs.map +1 -1
- package/dist/data/ai/PromptRunEditor/index.d.ts +3 -1
- package/dist/data/ai/PromptRunEditor/index.d.ts.map +1 -1
- package/dist/data/ai/PromptRunEditor/index.js +38 -44
- package/dist/data/ai/PromptRunEditor/index.js.map +1 -1
- package/dist/data/ai/PromptRunEditor/runtimeActions.cjs +16 -5
- package/dist/data/ai/PromptRunEditor/runtimeActions.cjs.map +1 -1
- package/dist/data/ai/PromptRunEditor/runtimeActions.d.ts +4 -1
- package/dist/data/ai/PromptRunEditor/runtimeActions.d.ts.map +1 -1
- package/dist/data/ai/PromptRunEditor/runtimeActions.js +17 -6
- package/dist/data/ai/PromptRunEditor/runtimeActions.js.map +1 -1
- package/dist/data/ai/SessionInspector.approvals-model.cjs +12 -0
- package/dist/data/ai/SessionInspector.approvals-model.cjs.map +1 -1
- package/dist/data/ai/SessionInspector.approvals-model.d.ts +11 -2
- package/dist/data/ai/SessionInspector.approvals-model.d.ts.map +1 -1
- package/dist/data/ai/SessionInspector.approvals-model.js +12 -0
- package/dist/data/ai/SessionInspector.approvals-model.js.map +1 -1
- package/dist/data/ai/SessionInspector.approvals.cjs +25 -1
- package/dist/data/ai/SessionInspector.approvals.cjs.map +1 -1
- package/dist/data/ai/SessionInspector.approvals.d.ts.map +1 -1
- package/dist/data/ai/SessionInspector.approvals.js +26 -2
- package/dist/data/ai/SessionInspector.approvals.js.map +1 -1
- package/dist/data/ai/SessionInspector.summary.cjs +9 -3
- package/dist/data/ai/SessionInspector.summary.cjs.map +1 -1
- package/dist/data/ai/SessionInspector.summary.d.ts.map +1 -1
- package/dist/data/ai/SessionInspector.summary.js +9 -3
- package/dist/data/ai/SessionInspector.summary.js.map +1 -1
- package/dist/data/ai/SessionInspector.transcript.cjs +4 -0
- package/dist/data/ai/SessionInspector.transcript.cjs.map +1 -1
- package/dist/data/ai/SessionInspector.transcript.d.ts.map +1 -1
- package/dist/data/ai/SessionInspector.transcript.js +4 -0
- package/dist/data/ai/SessionInspector.transcript.js.map +1 -1
- package/dist/data/ai/SessionViewer.approval-body.cjs +146 -0
- package/dist/data/ai/SessionViewer.approval-body.cjs.map +1 -0
- package/dist/data/ai/SessionViewer.approval-body.d.ts +11 -0
- package/dist/data/ai/SessionViewer.approval-body.d.ts.map +1 -0
- package/dist/data/ai/SessionViewer.approval-body.js +146 -0
- package/dist/data/ai/SessionViewer.approval-body.js.map +1 -0
- package/dist/data/ai/SessionViewer.approval-forms.cjs +150 -0
- package/dist/data/ai/SessionViewer.approval-forms.cjs.map +1 -0
- package/dist/data/ai/SessionViewer.approval-forms.d.ts +23 -0
- package/dist/data/ai/SessionViewer.approval-forms.d.ts.map +1 -0
- package/dist/data/ai/SessionViewer.approval-forms.js +150 -0
- package/dist/data/ai/SessionViewer.approval-forms.js.map +1 -0
- package/dist/data/ai/SessionViewer.cjs +57 -20
- package/dist/data/ai/SessionViewer.cjs.map +1 -1
- package/dist/data/ai/SessionViewer.d.ts +13 -3
- package/dist/data/ai/SessionViewer.d.ts.map +1 -1
- package/dist/data/ai/SessionViewer.decision-controls.cjs +313 -0
- package/dist/data/ai/SessionViewer.decision-controls.cjs.map +1 -0
- package/dist/data/ai/SessionViewer.decision-controls.d.ts +43 -0
- package/dist/data/ai/SessionViewer.decision-controls.d.ts.map +1 -0
- package/dist/data/ai/SessionViewer.decision-controls.js +313 -0
- package/dist/data/ai/SessionViewer.decision-controls.js.map +1 -0
- package/dist/data/ai/SessionViewer.decision.cjs +21 -0
- package/dist/data/ai/SessionViewer.decision.cjs.map +1 -0
- package/dist/data/ai/SessionViewer.decision.d.ts +12 -0
- package/dist/data/ai/SessionViewer.decision.d.ts.map +1 -0
- package/dist/data/ai/SessionViewer.decision.js +21 -0
- package/dist/data/ai/SessionViewer.decision.js.map +1 -0
- package/dist/data/ai/SessionViewer.input.cjs +14 -0
- package/dist/data/ai/SessionViewer.input.cjs.map +1 -1
- package/dist/data/ai/SessionViewer.input.d.ts +5 -0
- package/dist/data/ai/SessionViewer.input.d.ts.map +1 -1
- package/dist/data/ai/SessionViewer.input.js +14 -0
- package/dist/data/ai/SessionViewer.input.js.map +1 -1
- package/dist/data/ai/SessionViewer.js +58 -21
- package/dist/data/ai/SessionViewer.js.map +1 -1
- package/dist/data/ai/SessionViewer.model.cjs.map +1 -1
- package/dist/data/ai/SessionViewer.model.d.ts +4 -0
- package/dist/data/ai/SessionViewer.model.d.ts.map +1 -1
- package/dist/data/ai/SessionViewer.model.js.map +1 -1
- package/dist/data/ai/SessionViewer.rows.cjs +6 -3
- package/dist/data/ai/SessionViewer.rows.cjs.map +1 -1
- package/dist/data/ai/SessionViewer.rows.d.ts +2 -1
- package/dist/data/ai/SessionViewer.rows.d.ts.map +1 -1
- package/dist/data/ai/SessionViewer.rows.js +6 -3
- package/dist/data/ai/SessionViewer.rows.js.map +1 -1
- package/dist/data/ai/SessionViewer.tool-row.cjs +29 -237
- package/dist/data/ai/SessionViewer.tool-row.cjs.map +1 -1
- package/dist/data/ai/SessionViewer.tool-row.d.ts.map +1 -1
- package/dist/data/ai/SessionViewer.tool-row.js +27 -235
- package/dist/data/ai/SessionViewer.tool-row.js.map +1 -1
- package/dist/data/ai/SessionViewer.unified.d.ts +4 -0
- package/dist/data/ai/SessionViewer.unified.d.ts.map +1 -1
- package/dist/data/ai/SessionViewerMenu.cjs +8 -2
- package/dist/data/ai/SessionViewerMenu.cjs.map +1 -1
- package/dist/data/ai/SessionViewerMenu.d.ts +4 -1
- package/dist/data/ai/SessionViewerMenu.d.ts.map +1 -1
- package/dist/data/ai/SessionViewerMenu.js +8 -2
- package/dist/data/ai/SessionViewerMenu.js.map +1 -1
- package/dist/data/ai/SpecRuntimeEditor/CommitSection.cjs +28 -17
- package/dist/data/ai/SpecRuntimeEditor/CommitSection.cjs.map +1 -1
- package/dist/data/ai/SpecRuntimeEditor/CommitSection.d.ts +10 -2
- package/dist/data/ai/SpecRuntimeEditor/CommitSection.d.ts.map +1 -1
- package/dist/data/ai/SpecRuntimeEditor/CommitSection.js +29 -18
- package/dist/data/ai/SpecRuntimeEditor/CommitSection.js.map +1 -1
- package/dist/data/ai/SpecRuntimeEditor/index.cjs +9 -1
- package/dist/data/ai/SpecRuntimeEditor/index.cjs.map +1 -1
- package/dist/data/ai/SpecRuntimeEditor/index.d.ts +9 -2
- package/dist/data/ai/SpecRuntimeEditor/index.d.ts.map +1 -1
- package/dist/data/ai/SpecRuntimeEditor/index.js +9 -1
- package/dist/data/ai/SpecRuntimeEditor/index.js.map +1 -1
- package/dist/data/ai/SpecRuntimeEditor/permission-mode-visuals.cjs +1 -1
- package/dist/data/ai/SpecRuntimeEditor/permission-mode-visuals.js +1 -1
- package/dist/data/ai/SpecRuntimeEditor/summaries.cjs.map +1 -1
- package/dist/data/ai/SpecRuntimeEditor/summaries.d.ts +8 -2
- package/dist/data/ai/SpecRuntimeEditor/summaries.d.ts.map +1 -1
- package/dist/data/ai/SpecRuntimeEditor/summaries.js.map +1 -1
- package/dist/data/ai/SpecRuntimeEditor/update.cjs +14 -6
- package/dist/data/ai/SpecRuntimeEditor/update.cjs.map +1 -1
- package/dist/data/ai/SpecRuntimeEditor/update.d.ts +1 -0
- package/dist/data/ai/SpecRuntimeEditor/update.d.ts.map +1 -1
- package/dist/data/ai/SpecRuntimeEditor/update.js +14 -6
- package/dist/data/ai/SpecRuntimeEditor/update.js.map +1 -1
- package/dist/data/ai/approval-request.cjs +75 -0
- package/dist/data/ai/approval-request.cjs.map +1 -0
- package/dist/data/ai/approval-request.d.ts +155 -0
- package/dist/data/ai/approval-request.d.ts.map +1 -0
- package/dist/data/ai/approval-request.js +75 -0
- package/dist/data/ai/approval-request.js.map +1 -0
- package/dist/data/ai/index.d.ts +3 -0
- package/dist/data/ai/index.d.ts.map +1 -1
- package/dist/data/ai/runtime-preset-menu/SavePresetDialog.cjs +125 -0
- package/dist/data/ai/runtime-preset-menu/SavePresetDialog.cjs.map +1 -0
- package/dist/data/ai/runtime-preset-menu/SavePresetDialog.d.ts +11 -0
- package/dist/data/ai/runtime-preset-menu/SavePresetDialog.d.ts.map +1 -0
- package/dist/data/ai/runtime-preset-menu/SavePresetDialog.js +125 -0
- package/dist/data/ai/runtime-preset-menu/SavePresetDialog.js.map +1 -0
- package/dist/data/ai/runtime-preset-menu/index.d.ts +3 -0
- package/dist/data/ai/runtime-preset-menu/index.d.ts.map +1 -0
- package/dist/data/ai/runtime-preset-menu/model.cjs +73 -0
- package/dist/data/ai/runtime-preset-menu/model.cjs.map +1 -0
- package/dist/data/ai/runtime-preset-menu/model.d.ts +13 -0
- package/dist/data/ai/runtime-preset-menu/model.d.ts.map +1 -0
- package/dist/data/ai/runtime-preset-menu/model.js +73 -0
- package/dist/data/ai/runtime-preset-menu/model.js.map +1 -0
- package/dist/data/ai/runtime-preset-menu/use-runtime-preset-menu.cjs +149 -0
- package/dist/data/ai/runtime-preset-menu/use-runtime-preset-menu.cjs.map +1 -0
- package/dist/data/ai/runtime-preset-menu/use-runtime-preset-menu.d.ts +15 -0
- package/dist/data/ai/runtime-preset-menu/use-runtime-preset-menu.d.ts.map +1 -0
- package/dist/data/ai/runtime-preset-menu/use-runtime-preset-menu.js +149 -0
- package/dist/data/ai/runtime-preset-menu/use-runtime-preset-menu.js.map +1 -0
- package/dist/data/ai/runtime-spec-fields.cjs +166 -0
- package/dist/data/ai/runtime-spec-fields.cjs.map +1 -0
- package/dist/data/ai/runtime-spec-fields.d.ts +13 -0
- package/dist/data/ai/runtime-spec-fields.d.ts.map +1 -0
- package/dist/data/ai/runtime-spec-fields.js +166 -0
- package/dist/data/ai/runtime-spec-fields.js.map +1 -0
- package/dist/data/ai/session-categories.cjs +4 -0
- package/dist/data/ai/session-categories.cjs.map +1 -1
- package/dist/data/ai/session-categories.d.ts +1 -0
- package/dist/data/ai/session-categories.d.ts.map +1 -1
- package/dist/data/ai/session-categories.js +4 -0
- package/dist/data/ai/session-categories.js.map +1 -1
- package/dist/data/ai/use-session-scroll.cjs +49 -21
- package/dist/data/ai/use-session-scroll.cjs.map +1 -1
- package/dist/data/ai/use-session-scroll.d.ts +2 -0
- package/dist/data/ai/use-session-scroll.d.ts.map +1 -1
- package/dist/data/ai/use-session-scroll.js +49 -21
- package/dist/data/ai/use-session-scroll.js.map +1 -1
- package/dist/data/chat/Chat.runtime.cjs +1 -1
- package/dist/data/chat/Chat.runtime.cjs.map +1 -1
- package/dist/data/chat/Chat.runtime.d.ts.map +1 -1
- package/dist/data/chat/Chat.runtime.js +1 -1
- package/dist/data/chat/Chat.runtime.js.map +1 -1
- package/dist/data/graph-columns-layout.cjs +216 -0
- package/dist/data/graph-columns-layout.cjs.map +1 -0
- package/dist/data/graph-columns-layout.d.ts +56 -0
- package/dist/data/graph-columns-layout.d.ts.map +1 -0
- package/dist/data/graph-columns-layout.js +216 -0
- package/dist/data/graph-columns-layout.js.map +1 -0
- package/dist/data/graph-diagram-model.cjs +73 -0
- package/dist/data/graph-diagram-model.cjs.map +1 -0
- package/dist/data/graph-diagram-model.d.ts +90 -0
- package/dist/data/graph-diagram-model.d.ts.map +1 -0
- package/dist/data/graph-diagram-model.js +73 -0
- package/dist/data/graph-diagram-model.js.map +1 -0
- package/dist/data/graph-edge-routing.cjs +235 -0
- package/dist/data/graph-edge-routing.cjs.map +1 -0
- package/dist/data/graph-edge-routing.d.ts +73 -0
- package/dist/data/graph-edge-routing.d.ts.map +1 -0
- package/dist/data/graph-edge-routing.js +235 -0
- package/dist/data/graph-edge-routing.js.map +1 -0
- package/dist/data/graph-layout.cjs +0 -82
- package/dist/data/graph-layout.cjs.map +1 -1
- package/dist/data/graph-layout.d.ts +1 -28
- package/dist/data/graph-layout.d.ts.map +1 -1
- package/dist/data/graph-layout.js +1 -83
- package/dist/data/graph-layout.js.map +1 -1
- package/dist/data/har/HarPanel.cjs +129 -33
- package/dist/data/har/HarPanel.cjs.map +1 -1
- package/dist/data/har/HarPanel.d.ts +13 -1
- package/dist/data/har/HarPanel.d.ts.map +1 -1
- package/dist/data/har/HarPanel.js +130 -34
- package/dist/data/har/HarPanel.js.map +1 -1
- package/dist/data/har/fixtures.d.ts +12 -0
- package/dist/data/har/fixtures.d.ts.map +1 -1
- package/dist/data/har/types.d.ts +12 -0
- package/dist/data/har/types.d.ts.map +1 -1
- package/dist/data/runtime/RuntimeBar.cjs +67 -84
- package/dist/data/runtime/RuntimeBar.cjs.map +1 -1
- package/dist/data/runtime/RuntimeBar.d.ts +4 -5
- package/dist/data/runtime/RuntimeBar.d.ts.map +1 -1
- package/dist/data/runtime/RuntimeBar.fields.cjs +170 -0
- package/dist/data/runtime/RuntimeBar.fields.cjs.map +1 -0
- package/dist/data/runtime/RuntimeBar.fields.d.ts +16 -0
- package/dist/data/runtime/RuntimeBar.fields.d.ts.map +1 -0
- package/dist/data/runtime/RuntimeBar.fields.js +170 -0
- package/dist/data/runtime/RuntimeBar.fields.js.map +1 -0
- package/dist/data/runtime/RuntimeBar.js +70 -87
- package/dist/data/runtime/RuntimeBar.js.map +1 -1
- package/dist/data/runtime/RuntimeBar.selection.cjs +56 -0
- package/dist/data/runtime/RuntimeBar.selection.cjs.map +1 -0
- package/dist/data/runtime/RuntimeBar.selection.d.ts +20 -0
- package/dist/data/runtime/RuntimeBar.selection.d.ts.map +1 -0
- package/dist/data/runtime/RuntimeBar.selection.js +56 -0
- package/dist/data/runtime/RuntimeBar.selection.js.map +1 -0
- package/dist/data/runtime/RuntimeBarActions.cjs +10 -6
- package/dist/data/runtime/RuntimeBarActions.cjs.map +1 -1
- package/dist/data/runtime/RuntimeBarActions.d.ts +8 -1
- package/dist/data/runtime/RuntimeBarActions.d.ts.map +1 -1
- package/dist/data/runtime/RuntimeBarActions.js +10 -6
- package/dist/data/runtime/RuntimeBarActions.js.map +1 -1
- package/dist/data/runtime/RuntimeBarIdentity.cjs +166 -0
- package/dist/data/runtime/RuntimeBarIdentity.cjs.map +1 -0
- package/dist/data/runtime/RuntimeBarIdentity.d.ts +25 -0
- package/dist/data/runtime/RuntimeBarIdentity.d.ts.map +1 -0
- package/dist/data/runtime/RuntimeBarIdentity.js +166 -0
- package/dist/data/runtime/RuntimeBarIdentity.js.map +1 -0
- package/dist/data/runtime/RuntimeBarLayout.cjs +95 -0
- package/dist/data/runtime/RuntimeBarLayout.cjs.map +1 -0
- package/dist/data/runtime/RuntimeBarLayout.d.ts +9 -0
- package/dist/data/runtime/RuntimeBarLayout.d.ts.map +1 -0
- package/dist/data/runtime/RuntimeBarLayout.js +95 -0
- package/dist/data/runtime/RuntimeBarLayout.js.map +1 -0
- package/dist/data/runtime/RuntimeBarSegment.cjs +25 -14
- package/dist/data/runtime/RuntimeBarSegment.cjs.map +1 -1
- package/dist/data/runtime/RuntimeBarSegment.d.ts +4 -0
- package/dist/data/runtime/RuntimeBarSegment.d.ts.map +1 -1
- package/dist/data/runtime/RuntimeBarSegment.js +25 -14
- package/dist/data/runtime/RuntimeBarSegment.js.map +1 -1
- package/dist/data/runtime/RuntimeLimitInput.cjs +41 -0
- package/dist/data/runtime/RuntimeLimitInput.cjs.map +1 -0
- package/dist/data/runtime/RuntimeLimitInput.d.ts +9 -0
- package/dist/data/runtime/RuntimeLimitInput.d.ts.map +1 -0
- package/dist/data/runtime/RuntimeLimitInput.js +41 -0
- package/dist/data/runtime/RuntimeLimitInput.js.map +1 -0
- package/dist/data/runtime/use-runtime-bar-overflow.cjs +70 -0
- package/dist/data/runtime/use-runtime-bar-overflow.cjs.map +1 -0
- package/dist/data/runtime/use-runtime-bar-overflow.d.ts +13 -0
- package/dist/data/runtime/use-runtime-bar-overflow.d.ts.map +1 -0
- package/dist/data/runtime/use-runtime-bar-overflow.js +70 -0
- package/dist/data/runtime/use-runtime-bar-overflow.js.map +1 -0
- package/dist/data/use-edge-focus.cjs +20 -0
- package/dist/data/use-edge-focus.cjs.map +1 -0
- package/dist/data/use-edge-focus.d.ts +23 -0
- package/dist/data/use-edge-focus.d.ts.map +1 -0
- package/dist/data/use-edge-focus.js +20 -0
- package/dist/data/use-edge-focus.js.map +1 -0
- package/dist/data/use-pan-zoom.cjs +159 -0
- package/dist/data/use-pan-zoom.cjs.map +1 -0
- package/dist/data/use-pan-zoom.d.ts +79 -0
- package/dist/data/use-pan-zoom.d.ts.map +1 -0
- package/dist/data/use-pan-zoom.js +159 -0
- package/dist/data/use-pan-zoom.js.map +1 -0
- package/dist/data/version-info.cjs +3 -3
- package/dist/data/version-info.js +3 -3
- package/dist/data.cjs +5 -1
- package/dist/data.cjs.map +1 -1
- package/dist/data.d.ts +4 -3
- package/dist/data.d.ts.map +1 -1
- package/dist/data.js +6 -2
- package/dist/data.js.map +1 -1
- package/dist/index.cjs +5 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +6 -2
- package/dist/index.js.map +1 -1
- package/dist/overlay/DropdownMenu.cjs +1 -0
- package/dist/overlay/DropdownMenu.cjs.map +1 -1
- package/dist/overlay/DropdownMenu.d.ts +4 -0
- package/dist/overlay/DropdownMenu.d.ts.map +1 -1
- package/dist/overlay/DropdownMenu.js +1 -0
- package/dist/overlay/DropdownMenu.js.map +1 -1
- package/dist/overlay/DropdownMenuSubmenu.cjs +31 -15
- package/dist/overlay/DropdownMenuSubmenu.cjs.map +1 -1
- package/dist/overlay/DropdownMenuSubmenu.d.ts.map +1 -1
- package/dist/overlay/DropdownMenuSubmenu.js +31 -15
- package/dist/overlay/DropdownMenuSubmenu.js.map +1 -1
- package/dist/rpc/OperationCatalog.cjs +3 -1
- package/dist/rpc/OperationCatalog.cjs.map +1 -1
- package/dist/rpc/OperationCatalog.d.ts +3 -1
- package/dist/rpc/OperationCatalog.d.ts.map +1 -1
- package/dist/rpc/OperationCatalog.js +3 -1
- package/dist/rpc/OperationCatalog.js.map +1 -1
- package/dist/rpc/useOperationPages.cjs +6 -1
- package/dist/rpc/useOperationPages.cjs.map +1 -1
- package/dist/rpc/useOperationPages.d.ts +3 -1
- package/dist/rpc/useOperationPages.d.ts.map +1 -1
- package/dist/rpc/useOperationPages.js +6 -1
- package/dist/rpc/useOperationPages.js.map +1 -1
- package/dist/styles.css +1 -1
- package/package.json +1 -1
- package/schemas/json-schema-form.schema.json +5 -0
- package/dist/data/runtime/RuntimeBarCombo.cjs +0 -423
- package/dist/data/runtime/RuntimeBarCombo.cjs.map +0 -1
- package/dist/data/runtime/RuntimeBarCombo.d.ts +0 -33
- package/dist/data/runtime/RuntimeBarCombo.d.ts.map +0 -1
- package/dist/data/runtime/RuntimeBarCombo.js +0 -423
- package/dist/data/runtime/RuntimeBarCombo.js.map +0 -1
- package/dist/data/runtime/RuntimeBarLimits.cjs +0 -262
- package/dist/data/runtime/RuntimeBarLimits.cjs.map +0 -1
- package/dist/data/runtime/RuntimeBarLimits.d.ts +0 -17
- package/dist/data/runtime/RuntimeBarLimits.d.ts.map +0 -1
- package/dist/data/runtime/RuntimeBarLimits.js +0 -262
- package/dist/data/runtime/RuntimeBarLimits.js.map +0 -1
- package/dist/data/runtime/RuntimeBarSegments.cjs +0 -346
- package/dist/data/runtime/RuntimeBarSegments.cjs.map +0 -1
- package/dist/data/runtime/RuntimeBarSegments.d.ts +0 -37
- package/dist/data/runtime/RuntimeBarSegments.d.ts.map +0 -1
- package/dist/data/runtime/RuntimeBarSegments.js +0 -346
- package/dist/data/runtime/RuntimeBarSegments.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"OperationCatalog.js","sources":["../../src/rpc/OperationCatalog.tsx"],"sourcesContent":["import {\n useCallback,\n useEffect,\n useMemo,\n useRef,\n useState,\n type ReactNode,\n} from \"react\";\nimport { keepPreviousData, useQuery } from \"@tanstack/react-query\";\nimport { useOperationPages } from \"./useOperationPages\";\nimport { filterOperationsByDomain } from \"./classify\";\nimport {\n filterOperationsBySurface,\n findSurfaceCollectionActions,\n findSurfaceDetailOperation,\n findSurfaceListOperation,\n getOperationClickyMeta,\n} from \"./clickyMetadata\";\nimport type {\n ClickyCommandRuntime,\n ClickyDownloadOptions,\n ClickyRemoteFormat,\n ClickyRow,\n ClickyRowDetailRenderer,\n ClickyCellRenderers,\n ClickyRowCardRenderer,\n ClickyRowDetailTitle,\n} from \"../data/Clicky\";\nimport type { ModalSize } from \"../overlay/Modal\";\nimport type { CellFilterChange } from \"../data/cells/CellFilterActions\";\nimport { EndpointList, type RenderLink } from \"./EndpointList\";\nimport { OperationCatalogActions } from \"./OperationCatalogActions\";\nimport { OperationsApiClientError } from \"./apiClient\";\nimport { renderOperationError } from \"./operationErrorDiagnostics\";\nimport {\n OperationResultView,\n type OperationResultFilterConfig,\n type ResultRenderer,\n} from \"./OperationResultView\";\nimport { type FormActionsRenderer } from \"./SchemaActionForm\";\nimport {\n applyFilterExtensions,\n type FilterExtension,\n} from \"../components/filter-bar-utils\";\nimport type {\n PreExtension,\n PostExtension,\n} from \"../components/json-schema-form-types\";\nimport {\n type DomainDefinition,\n type ExecutionResponse,\n type OperationLookupResponse,\n type ResolvedOperation,\n} from \"./types\";\nimport { useOperations, type OperationsApiClient } from \"./useOperations\";\nimport {\n dataTablePaginationFromForm,\n packLookupParameterValues,\n parametersToFormConfig,\n type ParameterFormOptions,\n} from \"./formMetadata\";\nimport { cursorParameterName, useCursorStaleRecovery } from \"./cursorStale\";\nimport { useOperationFilterSearch } from \"./operationFilterSearch\";\nimport {\n parseMultiFilterValue,\n serializeMultiFilterValue,\n} from \"../data/data-table-filter-values\";\nimport { Loading } from \"../components/loading\";\nimport { getClickyRowId } from \"./rowNavigation\";\nimport { useOperationCatalogFilterState } from \"./operationCatalogFilterState\";\nimport {\n followRowOrder,\n mergeFollowRowsIntoResponse,\n partitionFollowRows,\n} from \"./operationCatalogFollow\";\nimport { OperationCatalogFollowStatus } from \"./OperationCatalogFollowStatus\";\nimport { useOperationCatalogFollow, type OperationCatalogFollowOption } from \"./useOperationCatalogFollow\";\nimport type { LogTailError } from \"../hooks/use-log-tail\";\nimport {\n markUnavailableRows,\n operationLookupQuery,\n pickerTableRowSelection,\n type OperationCatalogRowSelection,\n} from \"./operationCatalogRowSelection\";\n\nexport type OperationCatalogProps = {\n definition: DomainDefinition;\n entities: string[];\n client: OperationsApiClient;\n renderLink: RenderLink;\n // Override to return all operations (e.g. for an \"API explorer\" domain\n // that shouldn't be filtered by entity tags).\n allOperations?: boolean;\n surfaceKey?: string;\n // Domain-specific filter decorators (e.g. stamp an entity icon by filter\n // name). Composed in array order; mirrors JsonSchemaForm's `pre`.\n filterPre?: FilterExtension[];\n getCommandHref?: (operationId: string, op: ResolvedOperation) => string;\n renderError?: (err: unknown, title: string) => ReactNode;\n commandRuntime?: ClickyCommandRuntime;\n // Custom JsonSchemaForm field extensions forwarded to the create/edit form.\n formPre?: PreExtension[];\n formPost?: PostExtension[];\n // Optional extra footer actions for the create/edit form (e.g. a connection\n // \"Test\" button).\n formActions?: FormActionsRenderer;\n actionLabels?: Record<string, string>;\n // Optional host override for the result surface, keyed off the current surface.\n // Receives the default OperationResultView so non-overridden surfaces render\n // unchanged.\n resultRenderer?: ResultRenderer;\n /**\n * Portal target for the collection action bar (Create, bulk actions). When\n * set, the bar renders into this element — typically an app shell's\n * `bodyActions` slot — instead of inline under the catalog header.\n *\n * A portal rather than a render-prop because the bar owns its own dialog\n * state and closes over the catalog's live filters and list query; moving the\n * element would sever both. Falls back to inline rendering when null, so\n * existing consumers are unaffected.\n */\n actionsContainer?: Element | null;\n getRowDetailHref?: (id: string) => string | undefined;\n actionInitialValues?: Record<string, Record<string, string>>;\n /** Plural noun used by the cross-page selection notice. */\n selectionNoun?: string;\n /**\n * Parameter values pinned by the host — sent on every list request, every\n * filter lookup (both `client.lookupFilters` and per-filter type-ahead), and\n * every export/download URL. Never rendered as an editable filter chip or\n * form field, and never round-tripped through the URL: the host, not the\n * reader, owns them (e.g. the `stream` a trace-results panel is scoped to).\n */\n lockedValues?: Record<string, string>;\n /**\n * Editable seed values for filters the URL has no value for yet — e.g. a\n * database filter that should start at the host's current environment but\n * stay changeable. Applied per-key only when the URL is silent on that key\n * (a URL value always wins), still rendered as an ordinary editable filter\n * field, and never sent as a locked value or written back to the URL as\n * anything other than the resulting filter edit. Unlike `lockedValues`,\n * these seed the FilterBar's own state, not an overlay on top of it.\n */\n initialValues?: Record<string, string>;\n /**\n * Controls whether list filters/pagination/sort read and write the URL.\n * Omit for today's behaviour: unprefixed query params. `false` neither\n * reads nor writes the URL — for a catalog embedded where the host owns the\n * whole URL. `{ prefix }` reads and writes only `<prefix>.<name>` keys, so\n * the catalog can live inside a host route with its own `?step=`/`?tab=`\n * params without colliding.\n */\n urlState?: false | { prefix: string };\n /** Omit to infer cursor walking automatically; set when a host requires a specific paging presentation. */\n paginationMode?: \"paged\" | \"infinite\";\n /** Column names retained in raw rows for detail rendering but omitted from the table. */\n hiddenColumns?: string[];\n /**\n * Host row-detail configuration for the result table. `render` receives raw\n * row values keyed by column name, including columns hidden from `columns`\n * — see `ClickyRowDetailRenderer`. Never disturbs server paging, filters,\n * sort or export.\n */\n rowDetail?: {\n render: ClickyRowDetailRenderer;\n /** How the detail is surfaced when a row is clicked. Defaults to \"row\". */\n style?: \"row\" | \"dialog\";\n /** Dialog size when `style` is \"dialog\". Defaults to DataTable's \"lg\". */\n dialogSize?: ModalSize;\n /** Dialog title when `style` is \"dialog\", given the same raw row values as `render`. */\n title?: ClickyRowDetailTitle;\n };\n /** Override selected result table cells using raw server values. */\n cellRenderers?: ClickyCellRenderers;\n /** Render each list result as a card from its raw row values. */\n rowCard?: ClickyRowCardRenderer;\n /**\n * Follows the surface's list results live over the commons-db sessions SSE\n * API instead of polling: rows the server has appended since the last\n * fetch appear in the table without a refetch. Requires the list\n * operation to advertise a session-start operation (`POST\n * <listPath>/sessions`) in the loaded OpenAPI document — when it does not,\n * the catalog fails loudly with an explicit error naming the surface\n * rather than silently rendering as if `follow` had never been set.\n *\n * The session opens with the same locked values and active filters the\n * list request itself sends, and restarts whenever either changes.\n * Pass `{ maxRows }` to size the in-memory live buffer (default 5,000 —\n * see `useLogTail`); older rows are evicted and counted as `dropped`.\n */\n follow?: OperationCatalogFollowOption;\n /**\n * Turns the catalog into a picker: every row gets a checkbox, a row click\n * toggles it instead of opening the detail page, and the surface's action\n * bar (create and bulk actions) is not rendered — the host owns the\n * selection and what happens to it. Requires a list operation.\n */\n rowSelection?: OperationCatalogRowSelection;\n};\n\nconst defaultCommandHref = (operationId: string) => `/commands/${operationId}`;\nconst EMPTY_LOCKED_VALUES: Record<string, string> = {};\nconst EMPTY_INITIAL_VALUES: Record<string, string> = {};\n\nexport function OperationCatalog({\n definition,\n entities,\n client,\n renderLink,\n allOperations = false,\n surfaceKey,\n filterPre,\n getCommandHref = defaultCommandHref,\n renderError = renderOperationError,\n commandRuntime,\n formPre,\n formPost,\n formActions,\n actionLabels,\n resultRenderer,\n actionsContainer,\n getRowDetailHref,\n actionInitialValues,\n selectionNoun,\n lockedValues = EMPTY_LOCKED_VALUES,\n initialValues = EMPTY_INITIAL_VALUES,\n urlState,\n paginationMode,\n hiddenColumns,\n rowDetail,\n cellRenderers,\n rowCard,\n follow,\n rowSelection,\n}: OperationCatalogProps) {\n const renderRowDetail = rowDetail?.render;\n const rowDetailStyle = rowDetail?.style;\n const rowDetailDialogSize = rowDetail?.dialogSize;\n const rowDetailTitle = rowDetail?.title;\n const { operations, spec, isLoading } = useOperations(client);\n const filterShapes = spec?.components?.[\"x-clicky-filters\"];\n\n const surfaceOps = useMemo(\n () => filterOperationsBySurface(operations, surfaceKey),\n [operations, surfaceKey]\n );\n const useSurfaceMetadata = surfaceOps.length > 0;\n\n const domainOps = useMemo(() => {\n if (useSurfaceMetadata) return surfaceOps;\n return allOperations\n ? operations\n : filterOperationsByDomain(operations, entities);\n }, [allOperations, entities, operations, surfaceOps, useSurfaceMetadata]);\n\n const listEndpoint = useMemo(() => {\n if (!useSurfaceMetadata) return undefined;\n return findSurfaceListOperation(domainOps, surfaceKey);\n }, [domainOps, surfaceKey, useSurfaceMetadata]);\n const detailOperation = useMemo(\n () =>\n useSurfaceMetadata\n ? findSurfaceDetailOperation(domainOps, surfaceKey)\n : undefined,\n [domainOps, surfaceKey, useSurfaceMetadata]\n );\n const listParameters = listEndpoint?.operation.parameters ?? [];\n const { filters, setFilters, effectiveFilters } =\n useOperationCatalogFilterState({\n listParameters,\n lockedValues,\n urlState,\n initialValues,\n });\n const [selectedRowIds, setSelectedRowIds] = useState<string[]>([]);\n const [selectedRows, setSelectedRows] = useState<ClickyRow[]>([]);\n const [selectedScopeId, setSelectedScopeId] = useState<string>();\n const membershipFilterParameterNames = useMemo(\n () =>\n listParameters\n .filter(\n (parameter) =>\n ![\"limit\", \"offset\", \"cursor\", \"sort\", \"order\"].includes(\n parameter[\"x-clicky\"]?.role ?? \"\"\n )\n )\n .map((parameter) => parameter.name),\n [listParameters]\n );\n const membershipFilterKey = useMemo(\n () =>\n JSON.stringify(\n membershipFilterParameterNames.map((name) => [\n name,\n filters[name] ?? \"\",\n ])\n ),\n [filters, membershipFilterParameterNames]\n );\n const previousMembershipFilterKey = useRef(membershipFilterKey);\n useEffect(() => {\n if (previousMembershipFilterKey.current !== membershipFilterKey) {\n setSelectedRowIds([]);\n setSelectedRows([]);\n setSelectedScopeId(undefined);\n previousMembershipFilterKey.current = membershipFilterKey;\n }\n }, [membershipFilterKey]);\n const lookupParameters = useMemo(\n () => packLookupParameterValues(effectiveFilters, listParameters),\n [effectiveFilters, listParameters]\n );\n const download = useMemo<ClickyDownloadOptions | undefined>(() => {\n const meta = listEndpoint?.operation[\"x-clicky\"]?.export;\n if (!meta) return undefined;\n return {\n label: definition.title,\n ...(meta.formats\n ? { formats: meta.formats as ClickyRemoteFormat[] }\n : {}),\n ...(meta.scopes ? { scopes: meta.scopes } : {}),\n ...(meta.allRowsMode ? { allRowsMode: meta.allRowsMode } : {}),\n ...(meta.formatMaxRows\n ? {\n formatMaxRows: meta.formatMaxRows as Partial<\n Record<ClickyRemoteFormat, number>\n >,\n }\n : {}),\n };\n }, [definition.title, listEndpoint]);\n\n const list = useOperationPages({\n client,\n endpoint: listEndpoint,\n parameters: listParameters,\n filters: effectiveFilters,\n ...(paginationMode ? { paginationMode } : {}),\n });\n\n const { followEnabled, sessionOperation, followMissing, tail } =\n useOperationCatalogFollow({\n follow,\n operations,\n listEndpoint,\n listParameters,\n effectiveFilters,\n showTable: !!listEndpoint,\n });\n const reconcileFollow = typeof follow === \"object\" && follow?.mode === \"reconcile\";\n const refetchList = useRef(list.refetch);\n refetchList.current = list.refetch;\n const onReconcile = useRef(reconcileFollow ? follow.onReconcile : undefined);\n onReconcile.current = reconcileFollow ? follow.onReconcile : undefined;\n useEffect(() => {\n if (!reconcileFollow || tail.lastSequence === null) return;\n const sequence = tail.lastSequence;\n const timer = setTimeout(() => {\n refetchList.current();\n onReconcile.current?.(sequence);\n }, 250);\n return () => clearTimeout(timer);\n }, [reconcileFollow, tail.lastSequence]);\n\n useCursorStaleRecovery({\n error: list.error,\n parameters: listParameters,\n values: filters,\n setValues: setFilters,\n });\n\n const lookupQuery = useQuery<OperationLookupResponse>({\n ...operationLookupQuery(client, listEndpoint, lookupParameters),\n enabled: !!listEndpoint && !!client.lookupFilters,\n placeholderData: keepPreviousData,\n staleTime: 30_000,\n retry: 0,\n });\n\n const actionOps = useMemo(\n () =>\n useSurfaceMetadata\n ? findSurfaceCollectionActions(domainOps, surfaceKey)\n : [],\n [domainOps, surfaceKey, useSurfaceMetadata]\n );\n const selectionActionOps = useMemo(\n () =>\n actionOps.filter(\n (operation) => getOperationClickyMeta(operation)?.supportsFilterMode\n ),\n [actionOps]\n );\n const collectionActionOps = useMemo(\n () =>\n actionOps.filter(\n (operation) => !getOperationClickyMeta(operation)?.supportsFilterMode\n ),\n [actionOps]\n );\n\n const lookupSearch = useOperationFilterSearch(\n client,\n listEndpoint,\n effectiveFilters,\n listParameters\n );\n\n const filterBarConfig = useMemo(() => {\n const options: ParameterFormOptions = {\n includeLocations: [\"query\"],\n lookupSearch,\n components: filterShapes,\n lockedValues,\n hideLocked: true,\n };\n if (lookupQuery.data != null) {\n options.lookup = lookupQuery.data;\n }\n return parametersToFormConfig(listParameters, filters, setFilters, options);\n }, [\n filters,\n filterShapes,\n listParameters,\n lockedValues,\n lookupQuery.data,\n lookupSearch,\n ]);\n const dataTablePagination = useMemo(\n () =>\n dataTablePaginationFromForm(filterBarConfig.pagination, list.response),\n [filterBarConfig.pagination, list.response]\n );\n const followOrder = followRowOrder(filterBarConfig.sort?.value?.dir);\n const decoratedTimeRange = useMemo(\n () =>\n filterBarConfig.timeRange\n ? applyFilterExtensions(\n {\n key: \"timeRange\",\n kind: \"date-range\",\n label:\n filterBarConfig.timeRange.timeEnabled === false\n ? \"Date range\"\n : \"Time range\",\n ...filterBarConfig.timeRange,\n },\n filterPre\n )\n : undefined,\n [filterBarConfig.timeRange, filterPre]\n );\n const decoratedFilters = useMemo(() => {\n const next = filterBarConfig.filters.map((filter) =>\n applyFilterExtensions(filter, filterPre)\n );\n if (decoratedTimeRange?.placement === \"overflow\") {\n next.push(decoratedTimeRange);\n }\n return next;\n }, [decoratedTimeRange, filterBarConfig.filters, filterPre]);\n const cellFilters = useMemo(\n () =>\n Object.fromEntries(\n listParameters\n .filter((parameter) => parameter[\"x-clicky\"]?.role === \"filter\")\n .map((parameter) => [\n parameter.name,\n parseMultiFilterValue(filters[parameter.name] ?? \"\"),\n ])\n ),\n [filters, listParameters]\n );\n const onCellFilterChange = useCallback(\n ({ key, value, mode }: CellFilterChange) => {\n if (\n !listParameters.some(\n (parameter) =>\n parameter.name === key && parameter[\"x-clicky\"]?.role === \"filter\"\n )\n ) {\n throw new Error(\n `Clicky table column references unknown filter parameter ${key}`\n );\n }\n\n setFilters((current) => {\n const selected = parseMultiFilterValue(current[key] ?? \"\");\n if (mode === undefined) {\n delete selected[value];\n } else {\n selected[value] = mode;\n }\n\n const next = { ...current };\n const serialized = serializeMultiFilterValue(selected);\n if (serialized) {\n next[key] = serialized;\n } else {\n delete next[key];\n }\n\n const offset = listParameters.find(\n (parameter) => parameter[\"x-clicky\"]?.role === \"offset\"\n );\n if (offset) next[offset.name] = \"0\";\n const cursor = cursorParameterName(listParameters);\n if (cursor) next[cursor] = \"\";\n return next;\n });\n },\n [listParameters]\n );\n const resultFilterConfig = useMemo<OperationResultFilterConfig>(\n () => ({\n filters: decoratedFilters,\n cellFilters,\n onCellFilterChange,\n ...(filterBarConfig.search ? { search: filterBarConfig.search } : {}),\n ...(filterBarConfig.timeRange &&\n decoratedTimeRange?.placement !== \"overflow\"\n ? { timeRange: filterBarConfig.timeRange }\n : {}),\n }),\n [\n cellFilters,\n decoratedFilters,\n filterBarConfig.search,\n filterBarConfig.timeRange,\n decoratedTimeRange?.placement,\n onCellFilterChange,\n ]\n );\n\n const pickerSelection = useMemo(\n () =>\n rowSelection\n ? pickerTableRowSelection(rowSelection, effectiveFilters)\n : undefined,\n [effectiveFilters, rowSelection]\n );\n\n const showTable = !!listEndpoint;\n if (rowSelection && !isLoading && !showTable) {\n throw new Error(\n `OperationCatalog rowSelection needs a list operation, but surface \"${surfaceKey ?? definition.title}\" has none`\n );\n }\n let listError: unknown;\n if (!list.isFetching) {\n if (list.isError) {\n listError = list.error;\n } else if (list.response?.success === false) {\n listError = new OperationsApiClientError(\n list.response.error ||\n list.response.message ||\n list.response.stderr ||\n `Command failed with exit code ${list.response.exit_code}`,\n {\n method: listEndpoint?.method,\n url: list.response.requestUrl,\n responseBody: list.response.stdout,\n responseData: list.response.parsed,\n responseHeaders: list.response.responseHeaders,\n }\n );\n }\n }\n const tableError =\n listError !== undefined\n ? renderError(listError, `Failed to load ${listEndpoint?.path ?? \"\"}`)\n : undefined;\n const tableResponse = list.response?.success === false ? null : list.response;\n // The presented ClickyRow rides next to each raw follow row (see\n // LogTailEvent.clickyRow); a row-shaped event without one is a stream\n // contract violation for a tabular follow surface, never guessed at as\n // plain text, so it is surfaced as an error rather than merged.\n const followPartition = partitionFollowRows(tail.rows, tail.clickyRows);\n const followStreamError: LogTailError | null =\n tail.error ??\n (!reconcileFollow && followPartition.missingClickyRow\n ? {\n scope: \"stream\",\n message:\n \"a follow event arrived without its presented row (clickyRow) — the profile stopped sending it\",\n }\n : null);\n const followMerge =\n followEnabled && sessionOperation && !reconcileFollow\n ? mergeFollowRowsIntoResponse(\n tableResponse,\n followPartition.rows,\n followOrder\n )\n : undefined;\n const unavailableRows = rowSelection?.unavailableRows;\n const markRows = (response: ExecutionResponse | null) =>\n response && unavailableRows\n ? markUnavailableRows(response, unavailableRows)\n : response;\n const mergedTableResponse = markRows(\n followMerge ? followMerge.response : tableResponse\n );\n // The last fetch's total undercounts once live rows have been folded in\n // that it never saw — reported as a lower bound (\"gte\"), never restated as\n // an exact count nobody promised.\n const resultsPagination =\n followMerge && followMerge.addedCount > 0 && dataTablePagination\n ? {\n ...dataTablePagination,\n total: (dataTablePagination.total ?? 0) + followMerge.addedCount,\n totalRelation: \"gte\" as const,\n }\n : dataTablePagination;\n const walkProps = list.infinite\n ? {\n pages: unavailableRows\n ? list.pages.map((page) => markUnavailableRows(page, unavailableRows))\n : list.pages,\n infinite: list.infinite,\n }\n : {};\n if (isLoading || (showTable && list.isPending && list.response == null)) {\n return (\n <Loading variant=\"centered\" label={`Loading ${definition.title}…`} />\n );\n }\n\n return (\n <div\n className=\"flex h-full min-h-0 flex-1 flex-col gap-2\"\n data-slot=\"operation-catalog\"\n >\n {/* No title/description here by design: page headers and breadcrumbs are\n the host's to define (e.g. an app shell's bodyHeader), so the catalog\n never invents chrome the consumer would have to fight or duplicate. */}\n {!rowSelection && <OperationCatalogActions\n actions={collectionActionOps}\n selectionActions={selectionActionOps}\n filters={filters}\n filterParameterNames={listParameters.map((parameter) => parameter.name)}\n membershipFilterParameterNames={membershipFilterParameterNames}\n selectedRowIds={selectedRowIds}\n selectedRows={selectedRows}\n {...(selectedScopeId && dataTablePagination?.total != null\n ? {\n selectedScope: {\n id: selectedScopeId,\n total: dataTablePagination.total,\n },\n }\n : {})}\n clearSelection={() => {\n setSelectedRowIds([]);\n setSelectedRows([]);\n setSelectedScopeId(undefined);\n }}\n onExecuted={() => list.refetch()}\n {...(actionsContainer ? { actionsContainer } : {})}\n {...(actionInitialValues\n ? { initialValuesByAction: actionInitialValues }\n : {})}\n {...(commandRuntime ? { commandRuntime } : {})}\n {...(formPre ? { formPre } : {})}\n {...(formPost ? { formPost } : {})}\n {...(formActions ? { formActions } : {})}\n {...(actionLabels ? { actionLabels } : {})}\n client={client}\n />}\n\n {showTable ? (\n <div className=\"flex min-h-0 flex-1 flex-col\" data-slot=\"operation-catalog-results\">\n {followMissing ? (\n renderError(\n new Error(\n `Surface \"${surfaceKey ?? definition.title}\" set follow, but ${listEndpoint?.path} advertises no session to follow (expected POST ${listEndpoint?.path}/sessions)`\n ),\n \"Live follow is not available\"\n )\n ) : (\n <>\n {followEnabled && sessionOperation && (\n <OperationCatalogFollowStatus\n status={tail.status}\n error={followStreamError}\n droppedRows={reconcileFollow ? 0 : tail.droppedRows}\n addedCount={followMerge?.addedCount ?? 0}\n className=\"mb-2\"\n />\n )}\n {(() => {\n const defaultView = (\n <OperationResultView\n response={mergedTableResponse}\n loading={list.isFetching}\n loadingMessage={`Loading ${definition.title} results…`}\n emptyMessage=\"No records returned\"\n ariaLabel={`${definition.title} results`}\n className=\"mt-0 h-full min-h-0 flex-1\"\n detailOperation={pickerSelection ? undefined : detailOperation}\n {...(hiddenColumns ? { hiddenColumns } : {})}\n {...(getRowDetailHref && !pickerSelection\n ? { getRowDetailHref }\n : {})}\n {...(pickerSelection\n ? { rowSelection: pickerSelection }\n : selectionActionOps.length > 0\n ? {\n rowSelection: {\n selectedRowIds,\n onSelectionChange: (\n ids: string[],\n rows: ClickyRow[]\n ) => {\n setSelectedRowIds(ids);\n setSelectedRows(rows);\n setSelectedScopeId(undefined);\n },\n ...(dataTablePagination?.total != null &&\n dataTablePagination.totalRelation === \"eq\"\n ? {\n selectAllPages: {\n ...(selectedScopeId\n ? { selectedScopeId }\n : {}),\n noun:\n selectionNoun ??\n definition.title.toLocaleLowerCase(),\n scopes: [\n {\n id: \"all-matching\",\n total: dataTablePagination.total,\n onSelectAll: () =>\n setSelectedScopeId(\"all-matching\"),\n },\n ],\n },\n }\n : {}),\n getRowId: (row: ClickyRow) => {\n const id = getClickyRowId(row);\n if (!id) {\n throw new Error(\n \"Clicky bulk action row is missing an _id or id cell\"\n );\n }\n return id;\n },\n isRowSelectable: (row: ClickyRow) =>\n getClickyRowId(row) != null,\n },\n }\n : {})}\n filterConfig={resultFilterConfig}\n {...(tableError ? { error: tableError } : {})}\n {...(commandRuntime ? { commandRuntime } : {})}\n {...(resultsPagination\n ? { pagination: resultsPagination }\n : {})}\n {...(filterBarConfig.sort\n ? { sort: filterBarConfig.sort }\n : {})}\n {...(download ? { download } : {})}\n {...(renderRowDetail ? { renderRowDetail } : {})}\n {...(cellRenderers ? { cellRenderers } : {})}\n {...(rowCard ? { renderRowCard: rowCard } : {})}\n {...(rowDetailStyle ? { detailStyle: rowDetailStyle } : {})}\n {...(rowDetailDialogSize\n ? { detailDialogSize: rowDetailDialogSize }\n : {})}\n {...(rowDetailTitle\n ? { detailDialogTitle: rowDetailTitle }\n : {})}\n {...walkProps}\n />\n );\n return resultRenderer\n ? resultRenderer({\n response: list.response,\n loading: list.isFetching,\n defaultView,\n filterConfig: resultFilterConfig,\n // A renderer that replaces the table owns the whole surface,\n // pager and download menu included. Without these it can only\n // drop them, which is how a replaced view silently loses the\n // ability to reach page two — or, under a walk, page one's\n // rows the moment page two arrives.\n ...(dataTablePagination\n ? { pagination: dataTablePagination }\n : {}),\n ...(filterBarConfig.sort\n ? { sort: filterBarConfig.sort }\n : {}),\n ...(download ? { download } : {}),\n ...(surfaceKey ? { surfaceKey } : {}),\n ...(renderRowDetail ? { renderRowDetail } : {}),\n ...(rowCard ? { renderRowCard: rowCard } : {}),\n ...(rowDetailStyle ? { detailStyle: rowDetailStyle } : {}),\n ...(rowDetailDialogSize\n ? { detailDialogSize: rowDetailDialogSize }\n : {}),\n ...(rowDetailTitle\n ? { detailDialogTitle: rowDetailTitle }\n : {}),\n ...walkProps,\n })\n : defaultView;\n })()}\n </>\n )}\n </div>\n ) : (\n <EndpointList\n operations={domainOps}\n definition={definition}\n renderLink={renderLink}\n getCommandHref={getCommandHref}\n />\n )}\n </div>\n );\n}\n"],"names":["_a"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"OperationCatalog.js","sources":["../../src/rpc/OperationCatalog.tsx"],"sourcesContent":["import {\n useCallback,\n useEffect,\n useMemo,\n useRef,\n useState,\n type ReactNode,\n} from \"react\";\nimport { keepPreviousData, useQuery } from \"@tanstack/react-query\";\nimport { useOperationPages } from \"./useOperationPages\";\nimport { filterOperationsByDomain } from \"./classify\";\nimport {\n filterOperationsBySurface,\n findSurfaceCollectionActions,\n findSurfaceDetailOperation,\n findSurfaceListOperation,\n getOperationClickyMeta,\n} from \"./clickyMetadata\";\nimport type {\n ClickyCommandRuntime,\n ClickyDownloadOptions,\n ClickyRemoteFormat,\n ClickyRow,\n ClickyRowDetailRenderer,\n ClickyCellRenderers,\n ClickyRowCardRenderer,\n ClickyRowDetailTitle,\n} from \"../data/Clicky\";\nimport type { ModalSize } from \"../overlay/Modal\";\nimport type { CellFilterChange } from \"../data/cells/CellFilterActions\";\nimport { EndpointList, type RenderLink } from \"./EndpointList\";\nimport { OperationCatalogActions } from \"./OperationCatalogActions\";\nimport { OperationsApiClientError } from \"./apiClient\";\nimport { renderOperationError } from \"./operationErrorDiagnostics\";\nimport {\n OperationResultView,\n type OperationResultFilterConfig,\n type ResultRenderer,\n} from \"./OperationResultView\";\nimport { type FormActionsRenderer } from \"./SchemaActionForm\";\nimport {\n applyFilterExtensions,\n type FilterExtension,\n} from \"../components/filter-bar-utils\";\nimport type {\n PreExtension,\n PostExtension,\n} from \"../components/json-schema-form-types\";\nimport {\n type DomainDefinition,\n type ExecutionResponse,\n type OperationLookupResponse,\n type ResolvedOperation,\n} from \"./types\";\nimport { useOperations, type OperationsApiClient } from \"./useOperations\";\nimport {\n dataTablePaginationFromForm,\n packLookupParameterValues,\n parametersToFormConfig,\n type ParameterFormOptions,\n} from \"./formMetadata\";\nimport { cursorParameterName, useCursorStaleRecovery } from \"./cursorStale\";\nimport { useOperationFilterSearch } from \"./operationFilterSearch\";\nimport {\n parseMultiFilterValue,\n serializeMultiFilterValue,\n} from \"../data/data-table-filter-values\";\nimport { Loading } from \"../components/loading\";\nimport { getClickyRowId } from \"./rowNavigation\";\nimport { useOperationCatalogFilterState } from \"./operationCatalogFilterState\";\nimport {\n followRowOrder,\n mergeFollowRowsIntoResponse,\n partitionFollowRows,\n} from \"./operationCatalogFollow\";\nimport { OperationCatalogFollowStatus } from \"./OperationCatalogFollowStatus\";\nimport { useOperationCatalogFollow, type OperationCatalogFollowOption } from \"./useOperationCatalogFollow\";\nimport type { LogTailError } from \"../hooks/use-log-tail\";\nimport {\n markUnavailableRows,\n operationLookupQuery,\n pickerTableRowSelection,\n type OperationCatalogRowSelection,\n} from \"./operationCatalogRowSelection\";\n\nexport type OperationCatalogProps = {\n definition: DomainDefinition;\n entities: string[];\n client: OperationsApiClient;\n renderLink: RenderLink;\n // Override to return all operations (e.g. for an \"API explorer\" domain\n // that shouldn't be filtered by entity tags).\n allOperations?: boolean;\n surfaceKey?: string;\n // Domain-specific filter decorators (e.g. stamp an entity icon by filter\n // name). Composed in array order; mirrors JsonSchemaForm's `pre`.\n filterPre?: FilterExtension[];\n getCommandHref?: (operationId: string, op: ResolvedOperation) => string;\n renderError?: (err: unknown, title: string) => ReactNode;\n commandRuntime?: ClickyCommandRuntime;\n // Custom JsonSchemaForm field extensions forwarded to the create/edit form.\n formPre?: PreExtension[];\n formPost?: PostExtension[];\n // Optional extra footer actions for the create/edit form (e.g. a connection\n // \"Test\" button).\n formActions?: FormActionsRenderer;\n actionLabels?: Record<string, string>;\n // Optional host override for the result surface, keyed off the current surface.\n // Receives the default OperationResultView so non-overridden surfaces render\n // unchanged.\n resultRenderer?: ResultRenderer;\n /**\n * Portal target for the collection action bar (Create, bulk actions). When\n * set, the bar renders into this element — typically an app shell's\n * `bodyActions` slot — instead of inline under the catalog header.\n *\n * A portal rather than a render-prop because the bar owns its own dialog\n * state and closes over the catalog's live filters and list query; moving the\n * element would sever both. Falls back to inline rendering when null, so\n * existing consumers are unaffected.\n */\n actionsContainer?: Element | null;\n getRowDetailHref?: (id: string) => string | undefined;\n actionInitialValues?: Record<string, Record<string, string>>;\n /** Plural noun used by the cross-page selection notice. */\n selectionNoun?: string;\n /**\n * Parameter values pinned by the host — sent on every list request, every\n * filter lookup (both `client.lookupFilters` and per-filter type-ahead), and\n * every export/download URL. Never rendered as an editable filter chip or\n * form field, and never round-tripped through the URL: the host, not the\n * reader, owns them (e.g. the `stream` a trace-results panel is scoped to).\n */\n lockedValues?: Record<string, string>;\n /**\n * Editable seed values for filters the URL has no value for yet — e.g. a\n * database filter that should start at the host's current environment but\n * stay changeable. Applied per-key only when the URL is silent on that key\n * (a URL value always wins), still rendered as an ordinary editable filter\n * field, and never sent as a locked value or written back to the URL as\n * anything other than the resulting filter edit. Unlike `lockedValues`,\n * these seed the FilterBar's own state, not an overlay on top of it.\n */\n initialValues?: Record<string, string>;\n /**\n * Controls whether list filters/pagination/sort read and write the URL.\n * Omit for today's behaviour: unprefixed query params. `false` neither\n * reads nor writes the URL — for a catalog embedded where the host owns the\n * whole URL. `{ prefix }` reads and writes only `<prefix>.<name>` keys, so\n * the catalog can live inside a host route with its own `?step=`/`?tab=`\n * params without colliding.\n */\n urlState?: false | { prefix: string };\n /** Omit to infer cursor walking automatically; set when a host requires a specific paging presentation. */\n paginationMode?: \"paged\" | \"infinite\";\n /** Poll the current server page while it can change, in milliseconds. */\n refreshIntervalMs?: number;\n /** Column names retained in raw rows for detail rendering but omitted from the table. */\n hiddenColumns?: string[];\n /**\n * Host row-detail configuration for the result table. `render` receives raw\n * row values keyed by column name, including columns hidden from `columns`\n * — see `ClickyRowDetailRenderer`. Never disturbs server paging, filters,\n * sort or export.\n */\n rowDetail?: {\n render: ClickyRowDetailRenderer;\n /** How the detail is surfaced when a row is clicked. Defaults to \"row\". */\n style?: \"row\" | \"dialog\";\n /** Dialog size when `style` is \"dialog\". Defaults to DataTable's \"lg\". */\n dialogSize?: ModalSize;\n /** Dialog title when `style` is \"dialog\", given the same raw row values as `render`. */\n title?: ClickyRowDetailTitle;\n };\n /** Override selected result table cells using raw server values. */\n cellRenderers?: ClickyCellRenderers;\n /** Render each list result as a card from its raw row values. */\n rowCard?: ClickyRowCardRenderer;\n /**\n * Follows the surface's list results live over the commons-db sessions SSE\n * API instead of polling: rows the server has appended since the last\n * fetch appear in the table without a refetch. Requires the list\n * operation to advertise a session-start operation (`POST\n * <listPath>/sessions`) in the loaded OpenAPI document — when it does not,\n * the catalog fails loudly with an explicit error naming the surface\n * rather than silently rendering as if `follow` had never been set.\n *\n * The session opens with the same locked values and active filters the\n * list request itself sends, and restarts whenever either changes.\n * Pass `{ maxRows }` to size the in-memory live buffer (default 5,000 —\n * see `useLogTail`); older rows are evicted and counted as `dropped`.\n */\n follow?: OperationCatalogFollowOption;\n /**\n * Turns the catalog into a picker: every row gets a checkbox, a row click\n * toggles it instead of opening the detail page, and the surface's action\n * bar (create and bulk actions) is not rendered — the host owns the\n * selection and what happens to it. Requires a list operation.\n */\n rowSelection?: OperationCatalogRowSelection;\n};\n\nconst defaultCommandHref = (operationId: string) => `/commands/${operationId}`;\nconst EMPTY_LOCKED_VALUES: Record<string, string> = {};\nconst EMPTY_INITIAL_VALUES: Record<string, string> = {};\n\nexport function OperationCatalog({\n definition,\n entities,\n client,\n renderLink,\n allOperations = false,\n surfaceKey,\n filterPre,\n getCommandHref = defaultCommandHref,\n renderError = renderOperationError,\n commandRuntime,\n formPre,\n formPost,\n formActions,\n actionLabels,\n resultRenderer,\n actionsContainer,\n getRowDetailHref,\n actionInitialValues,\n selectionNoun,\n lockedValues = EMPTY_LOCKED_VALUES,\n initialValues = EMPTY_INITIAL_VALUES,\n urlState,\n paginationMode,\n refreshIntervalMs,\n hiddenColumns,\n rowDetail,\n cellRenderers,\n rowCard,\n follow,\n rowSelection,\n}: OperationCatalogProps) {\n const renderRowDetail = rowDetail?.render;\n const rowDetailStyle = rowDetail?.style;\n const rowDetailDialogSize = rowDetail?.dialogSize;\n const rowDetailTitle = rowDetail?.title;\n const { operations, spec, isLoading } = useOperations(client);\n const filterShapes = spec?.components?.[\"x-clicky-filters\"];\n\n const surfaceOps = useMemo(\n () => filterOperationsBySurface(operations, surfaceKey),\n [operations, surfaceKey]\n );\n const useSurfaceMetadata = surfaceOps.length > 0;\n\n const domainOps = useMemo(() => {\n if (useSurfaceMetadata) return surfaceOps;\n return allOperations\n ? operations\n : filterOperationsByDomain(operations, entities);\n }, [allOperations, entities, operations, surfaceOps, useSurfaceMetadata]);\n\n const listEndpoint = useMemo(() => {\n if (!useSurfaceMetadata) return undefined;\n return findSurfaceListOperation(domainOps, surfaceKey);\n }, [domainOps, surfaceKey, useSurfaceMetadata]);\n const detailOperation = useMemo(\n () =>\n useSurfaceMetadata\n ? findSurfaceDetailOperation(domainOps, surfaceKey)\n : undefined,\n [domainOps, surfaceKey, useSurfaceMetadata]\n );\n const listParameters = listEndpoint?.operation.parameters ?? [];\n const { filters, setFilters, effectiveFilters } =\n useOperationCatalogFilterState({\n listParameters,\n lockedValues,\n urlState,\n initialValues,\n });\n const [selectedRowIds, setSelectedRowIds] = useState<string[]>([]);\n const [selectedRows, setSelectedRows] = useState<ClickyRow[]>([]);\n const [selectedScopeId, setSelectedScopeId] = useState<string>();\n const membershipFilterParameterNames = useMemo(\n () =>\n listParameters\n .filter(\n (parameter) =>\n ![\"limit\", \"offset\", \"cursor\", \"sort\", \"order\"].includes(\n parameter[\"x-clicky\"]?.role ?? \"\"\n )\n )\n .map((parameter) => parameter.name),\n [listParameters]\n );\n const membershipFilterKey = useMemo(\n () =>\n JSON.stringify(\n membershipFilterParameterNames.map((name) => [\n name,\n filters[name] ?? \"\",\n ])\n ),\n [filters, membershipFilterParameterNames]\n );\n const previousMembershipFilterKey = useRef(membershipFilterKey);\n useEffect(() => {\n if (previousMembershipFilterKey.current !== membershipFilterKey) {\n setSelectedRowIds([]);\n setSelectedRows([]);\n setSelectedScopeId(undefined);\n previousMembershipFilterKey.current = membershipFilterKey;\n }\n }, [membershipFilterKey]);\n const lookupParameters = useMemo(\n () => packLookupParameterValues(effectiveFilters, listParameters),\n [effectiveFilters, listParameters]\n );\n const download = useMemo<ClickyDownloadOptions | undefined>(() => {\n const meta = listEndpoint?.operation[\"x-clicky\"]?.export;\n if (!meta) return undefined;\n return {\n label: definition.title,\n ...(meta.formats\n ? { formats: meta.formats as ClickyRemoteFormat[] }\n : {}),\n ...(meta.scopes ? { scopes: meta.scopes } : {}),\n ...(meta.allRowsMode ? { allRowsMode: meta.allRowsMode } : {}),\n ...(meta.formatMaxRows\n ? {\n formatMaxRows: meta.formatMaxRows as Partial<\n Record<ClickyRemoteFormat, number>\n >,\n }\n : {}),\n };\n }, [definition.title, listEndpoint]);\n\n const list = useOperationPages({\n client,\n endpoint: listEndpoint,\n parameters: listParameters,\n filters: effectiveFilters,\n ...(paginationMode ? { paginationMode } : {}),\n ...(refreshIntervalMs !== undefined ? { refreshIntervalMs } : {}),\n });\n\n const { followEnabled, sessionOperation, followMissing, tail } =\n useOperationCatalogFollow({\n follow,\n operations,\n listEndpoint,\n listParameters,\n effectiveFilters,\n showTable: !!listEndpoint,\n });\n const reconcileFollow = typeof follow === \"object\" && follow?.mode === \"reconcile\";\n const refetchList = useRef(list.refetch);\n refetchList.current = list.refetch;\n const onReconcile = useRef(reconcileFollow ? follow.onReconcile : undefined);\n onReconcile.current = reconcileFollow ? follow.onReconcile : undefined;\n useEffect(() => {\n if (!reconcileFollow || tail.lastSequence === null) return;\n const sequence = tail.lastSequence;\n const timer = setTimeout(() => {\n refetchList.current();\n onReconcile.current?.(sequence);\n }, 250);\n return () => clearTimeout(timer);\n }, [reconcileFollow, tail.lastSequence]);\n\n useCursorStaleRecovery({\n error: list.error,\n parameters: listParameters,\n values: filters,\n setValues: setFilters,\n });\n\n const lookupQuery = useQuery<OperationLookupResponse>({\n ...operationLookupQuery(client, listEndpoint, lookupParameters),\n enabled: !!listEndpoint && !!client.lookupFilters,\n placeholderData: keepPreviousData,\n staleTime: 30_000,\n retry: 0,\n });\n\n const actionOps = useMemo(\n () =>\n useSurfaceMetadata\n ? findSurfaceCollectionActions(domainOps, surfaceKey)\n : [],\n [domainOps, surfaceKey, useSurfaceMetadata]\n );\n const selectionActionOps = useMemo(\n () =>\n actionOps.filter(\n (operation) => getOperationClickyMeta(operation)?.supportsFilterMode\n ),\n [actionOps]\n );\n const collectionActionOps = useMemo(\n () =>\n actionOps.filter(\n (operation) => !getOperationClickyMeta(operation)?.supportsFilterMode\n ),\n [actionOps]\n );\n\n const lookupSearch = useOperationFilterSearch(\n client,\n listEndpoint,\n effectiveFilters,\n listParameters\n );\n\n const filterBarConfig = useMemo(() => {\n const options: ParameterFormOptions = {\n includeLocations: [\"query\"],\n lookupSearch,\n components: filterShapes,\n lockedValues,\n hideLocked: true,\n };\n if (lookupQuery.data != null) {\n options.lookup = lookupQuery.data;\n }\n return parametersToFormConfig(listParameters, filters, setFilters, options);\n }, [\n filters,\n filterShapes,\n listParameters,\n lockedValues,\n lookupQuery.data,\n lookupSearch,\n ]);\n const dataTablePagination = useMemo(\n () =>\n dataTablePaginationFromForm(filterBarConfig.pagination, list.response),\n [filterBarConfig.pagination, list.response]\n );\n const followOrder = followRowOrder(filterBarConfig.sort?.value?.dir);\n const decoratedTimeRange = useMemo(\n () =>\n filterBarConfig.timeRange\n ? applyFilterExtensions(\n {\n key: \"timeRange\",\n kind: \"date-range\",\n label:\n filterBarConfig.timeRange.timeEnabled === false\n ? \"Date range\"\n : \"Time range\",\n ...filterBarConfig.timeRange,\n },\n filterPre\n )\n : undefined,\n [filterBarConfig.timeRange, filterPre]\n );\n const decoratedFilters = useMemo(() => {\n const next = filterBarConfig.filters.map((filter) =>\n applyFilterExtensions(filter, filterPre)\n );\n if (decoratedTimeRange?.placement === \"overflow\") {\n next.push(decoratedTimeRange);\n }\n return next;\n }, [decoratedTimeRange, filterBarConfig.filters, filterPre]);\n const cellFilters = useMemo(\n () =>\n Object.fromEntries(\n listParameters\n .filter((parameter) => parameter[\"x-clicky\"]?.role === \"filter\")\n .map((parameter) => [\n parameter.name,\n parseMultiFilterValue(filters[parameter.name] ?? \"\"),\n ])\n ),\n [filters, listParameters]\n );\n const onCellFilterChange = useCallback(\n ({ key, value, mode }: CellFilterChange) => {\n if (\n !listParameters.some(\n (parameter) =>\n parameter.name === key && parameter[\"x-clicky\"]?.role === \"filter\"\n )\n ) {\n throw new Error(\n `Clicky table column references unknown filter parameter ${key}`\n );\n }\n\n setFilters((current) => {\n const selected = parseMultiFilterValue(current[key] ?? \"\");\n if (mode === undefined) {\n delete selected[value];\n } else {\n selected[value] = mode;\n }\n\n const next = { ...current };\n const serialized = serializeMultiFilterValue(selected);\n if (serialized) {\n next[key] = serialized;\n } else {\n delete next[key];\n }\n\n const offset = listParameters.find(\n (parameter) => parameter[\"x-clicky\"]?.role === \"offset\"\n );\n if (offset) next[offset.name] = \"0\";\n const cursor = cursorParameterName(listParameters);\n if (cursor) next[cursor] = \"\";\n return next;\n });\n },\n [listParameters]\n );\n const resultFilterConfig = useMemo<OperationResultFilterConfig>(\n () => ({\n filters: decoratedFilters,\n cellFilters,\n onCellFilterChange,\n ...(filterBarConfig.search ? { search: filterBarConfig.search } : {}),\n ...(filterBarConfig.timeRange &&\n decoratedTimeRange?.placement !== \"overflow\"\n ? { timeRange: filterBarConfig.timeRange }\n : {}),\n }),\n [\n cellFilters,\n decoratedFilters,\n filterBarConfig.search,\n filterBarConfig.timeRange,\n decoratedTimeRange?.placement,\n onCellFilterChange,\n ]\n );\n\n const pickerSelection = useMemo(\n () =>\n rowSelection\n ? pickerTableRowSelection(rowSelection, effectiveFilters)\n : undefined,\n [effectiveFilters, rowSelection]\n );\n\n const showTable = !!listEndpoint;\n if (rowSelection && !isLoading && !showTable) {\n throw new Error(\n `OperationCatalog rowSelection needs a list operation, but surface \"${surfaceKey ?? definition.title}\" has none`\n );\n }\n let listError: unknown;\n if (!list.isFetching) {\n if (list.isError) {\n listError = list.error;\n } else if (list.response?.success === false) {\n listError = new OperationsApiClientError(\n list.response.error ||\n list.response.message ||\n list.response.stderr ||\n `Command failed with exit code ${list.response.exit_code}`,\n {\n method: listEndpoint?.method,\n url: list.response.requestUrl,\n responseBody: list.response.stdout,\n responseData: list.response.parsed,\n responseHeaders: list.response.responseHeaders,\n }\n );\n }\n }\n const tableError =\n listError !== undefined\n ? renderError(listError, `Failed to load ${listEndpoint?.path ?? \"\"}`)\n : undefined;\n const tableResponse = list.response?.success === false ? null : list.response;\n // The presented ClickyRow rides next to each raw follow row (see\n // LogTailEvent.clickyRow); a row-shaped event without one is a stream\n // contract violation for a tabular follow surface, never guessed at as\n // plain text, so it is surfaced as an error rather than merged.\n const followPartition = partitionFollowRows(tail.rows, tail.clickyRows);\n const followStreamError: LogTailError | null =\n tail.error ??\n (!reconcileFollow && followPartition.missingClickyRow\n ? {\n scope: \"stream\",\n message:\n \"a follow event arrived without its presented row (clickyRow) — the profile stopped sending it\",\n }\n : null);\n const followMerge =\n followEnabled && sessionOperation && !reconcileFollow\n ? mergeFollowRowsIntoResponse(\n tableResponse,\n followPartition.rows,\n followOrder\n )\n : undefined;\n const unavailableRows = rowSelection?.unavailableRows;\n const markRows = (response: ExecutionResponse | null) =>\n response && unavailableRows\n ? markUnavailableRows(response, unavailableRows)\n : response;\n const mergedTableResponse = markRows(\n followMerge ? followMerge.response : tableResponse\n );\n // The last fetch's total undercounts once live rows have been folded in\n // that it never saw — reported as a lower bound (\"gte\"), never restated as\n // an exact count nobody promised.\n const resultsPagination =\n followMerge && followMerge.addedCount > 0 && dataTablePagination\n ? {\n ...dataTablePagination,\n total: (dataTablePagination.total ?? 0) + followMerge.addedCount,\n totalRelation: \"gte\" as const,\n }\n : dataTablePagination;\n const walkProps = list.infinite\n ? {\n pages: unavailableRows\n ? list.pages.map((page) => markUnavailableRows(page, unavailableRows))\n : list.pages,\n infinite: list.infinite,\n }\n : {};\n if (isLoading || (showTable && list.isPending && list.response == null)) {\n return (\n <Loading variant=\"centered\" label={`Loading ${definition.title}…`} />\n );\n }\n\n return (\n <div\n className=\"flex h-full min-h-0 flex-1 flex-col gap-2\"\n data-slot=\"operation-catalog\"\n >\n {/* No title/description here by design: page headers and breadcrumbs are\n the host's to define (e.g. an app shell's bodyHeader), so the catalog\n never invents chrome the consumer would have to fight or duplicate. */}\n {!rowSelection && <OperationCatalogActions\n actions={collectionActionOps}\n selectionActions={selectionActionOps}\n filters={filters}\n filterParameterNames={listParameters.map((parameter) => parameter.name)}\n membershipFilterParameterNames={membershipFilterParameterNames}\n selectedRowIds={selectedRowIds}\n selectedRows={selectedRows}\n {...(selectedScopeId && dataTablePagination?.total != null\n ? {\n selectedScope: {\n id: selectedScopeId,\n total: dataTablePagination.total,\n },\n }\n : {})}\n clearSelection={() => {\n setSelectedRowIds([]);\n setSelectedRows([]);\n setSelectedScopeId(undefined);\n }}\n onExecuted={() => list.refetch()}\n {...(actionsContainer ? { actionsContainer } : {})}\n {...(actionInitialValues\n ? { initialValuesByAction: actionInitialValues }\n : {})}\n {...(commandRuntime ? { commandRuntime } : {})}\n {...(formPre ? { formPre } : {})}\n {...(formPost ? { formPost } : {})}\n {...(formActions ? { formActions } : {})}\n {...(actionLabels ? { actionLabels } : {})}\n client={client}\n />}\n\n {showTable ? (\n <div className=\"flex min-h-0 flex-1 flex-col\" data-slot=\"operation-catalog-results\">\n {followMissing ? (\n renderError(\n new Error(\n `Surface \"${surfaceKey ?? definition.title}\" set follow, but ${listEndpoint?.path} advertises no session to follow (expected POST ${listEndpoint?.path}/sessions)`\n ),\n \"Live follow is not available\"\n )\n ) : (\n <>\n {followEnabled && sessionOperation && (\n <OperationCatalogFollowStatus\n status={tail.status}\n error={followStreamError}\n droppedRows={reconcileFollow ? 0 : tail.droppedRows}\n addedCount={followMerge?.addedCount ?? 0}\n className=\"mb-2\"\n />\n )}\n {(() => {\n const defaultView = (\n <OperationResultView\n response={mergedTableResponse}\n loading={list.isFetching}\n loadingMessage={`Loading ${definition.title} results…`}\n emptyMessage=\"No records returned\"\n ariaLabel={`${definition.title} results`}\n className=\"mt-0 h-full min-h-0 flex-1\"\n detailOperation={pickerSelection ? undefined : detailOperation}\n {...(hiddenColumns ? { hiddenColumns } : {})}\n {...(getRowDetailHref && !pickerSelection\n ? { getRowDetailHref }\n : {})}\n {...(pickerSelection\n ? { rowSelection: pickerSelection }\n : selectionActionOps.length > 0\n ? {\n rowSelection: {\n selectedRowIds,\n onSelectionChange: (\n ids: string[],\n rows: ClickyRow[]\n ) => {\n setSelectedRowIds(ids);\n setSelectedRows(rows);\n setSelectedScopeId(undefined);\n },\n ...(dataTablePagination?.total != null &&\n dataTablePagination.totalRelation === \"eq\"\n ? {\n selectAllPages: {\n ...(selectedScopeId\n ? { selectedScopeId }\n : {}),\n noun:\n selectionNoun ??\n definition.title.toLocaleLowerCase(),\n scopes: [\n {\n id: \"all-matching\",\n total: dataTablePagination.total,\n onSelectAll: () =>\n setSelectedScopeId(\"all-matching\"),\n },\n ],\n },\n }\n : {}),\n getRowId: (row: ClickyRow) => {\n const id = getClickyRowId(row);\n if (!id) {\n throw new Error(\n \"Clicky bulk action row is missing an _id or id cell\"\n );\n }\n return id;\n },\n isRowSelectable: (row: ClickyRow) =>\n getClickyRowId(row) != null,\n },\n }\n : {})}\n filterConfig={resultFilterConfig}\n {...(tableError ? { error: tableError } : {})}\n {...(commandRuntime ? { commandRuntime } : {})}\n {...(resultsPagination\n ? { pagination: resultsPagination }\n : {})}\n {...(filterBarConfig.sort\n ? { sort: filterBarConfig.sort }\n : {})}\n {...(download ? { download } : {})}\n {...(renderRowDetail ? { renderRowDetail } : {})}\n {...(cellRenderers ? { cellRenderers } : {})}\n {...(rowCard ? { renderRowCard: rowCard } : {})}\n {...(rowDetailStyle ? { detailStyle: rowDetailStyle } : {})}\n {...(rowDetailDialogSize\n ? { detailDialogSize: rowDetailDialogSize }\n : {})}\n {...(rowDetailTitle\n ? { detailDialogTitle: rowDetailTitle }\n : {})}\n {...walkProps}\n />\n );\n return resultRenderer\n ? resultRenderer({\n response: list.response,\n loading: list.isFetching,\n defaultView,\n filterConfig: resultFilterConfig,\n // A renderer that replaces the table owns the whole surface,\n // pager and download menu included. Without these it can only\n // drop them, which is how a replaced view silently loses the\n // ability to reach page two — or, under a walk, page one's\n // rows the moment page two arrives.\n ...(dataTablePagination\n ? { pagination: dataTablePagination }\n : {}),\n ...(filterBarConfig.sort\n ? { sort: filterBarConfig.sort }\n : {}),\n ...(download ? { download } : {}),\n ...(surfaceKey ? { surfaceKey } : {}),\n ...(renderRowDetail ? { renderRowDetail } : {}),\n ...(rowCard ? { renderRowCard: rowCard } : {}),\n ...(rowDetailStyle ? { detailStyle: rowDetailStyle } : {}),\n ...(rowDetailDialogSize\n ? { detailDialogSize: rowDetailDialogSize }\n : {}),\n ...(rowDetailTitle\n ? { detailDialogTitle: rowDetailTitle }\n : {}),\n ...walkProps,\n })\n : defaultView;\n })()}\n </>\n )}\n </div>\n ) : (\n <EndpointList\n operations={domainOps}\n definition={definition}\n renderLink={renderLink}\n getCommandHref={getCommandHref}\n />\n )}\n </div>\n );\n}\n"],"names":["_a"],"mappings":"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"}
|
|
@@ -11,7 +11,8 @@ function useOperationPages({
|
|
|
11
11
|
endpoint,
|
|
12
12
|
parameters,
|
|
13
13
|
filters,
|
|
14
|
-
paginationMode
|
|
14
|
+
paginationMode,
|
|
15
|
+
refreshIntervalMs
|
|
15
16
|
}) {
|
|
16
17
|
var _a;
|
|
17
18
|
const queryClient = reactQuery.useQueryClient();
|
|
@@ -24,6 +25,9 @@ function useOperationPages({
|
|
|
24
25
|
);
|
|
25
26
|
}
|
|
26
27
|
const walkMode = paginationMode === "infinite" || paginationMode === void 0 && !!cursorParam;
|
|
28
|
+
if (refreshIntervalMs !== void 0 && (!Number.isFinite(refreshIntervalMs) || refreshIntervalMs <= 0 || walkMode)) {
|
|
29
|
+
throw new Error("Operation page refresh requires a positive interval and paged mode");
|
|
30
|
+
}
|
|
27
31
|
const walkFilters = react.useMemo(() => {
|
|
28
32
|
if (!cursorParam) return filters;
|
|
29
33
|
const rest = { ...filters };
|
|
@@ -45,6 +49,7 @@ function useOperationPages({
|
|
|
45
49
|
enabled: !!endpoint && !walkMode,
|
|
46
50
|
placeholderData: reactQuery.keepPreviousData,
|
|
47
51
|
staleTime: 3e4,
|
|
52
|
+
...refreshIntervalMs !== void 0 ? { refetchInterval: refreshIntervalMs } : {},
|
|
48
53
|
retry: 0
|
|
49
54
|
});
|
|
50
55
|
const walkKey = react.useMemo(
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useOperationPages.cjs","sources":["../../src/rpc/useOperationPages.ts"],"sourcesContent":["import { useCallback, useEffect, useMemo } from \"react\";\nimport {\n keepPreviousData,\n useInfiniteQuery,\n useQuery,\n useQueryClient,\n type InfiniteData,\n type QueryKey,\n} from \"@tanstack/react-query\";\n\nimport type { DataTableInfinite } from \"../data/DataTable\";\nimport { cursorParameterName, isCursorStale } from \"./cursorStale\";\nimport { packParameterValues, type ParameterValues } from \"./formMetadata\";\nimport type {\n ExecutionResponse,\n OpenAPIParameter,\n ResolvedOperation,\n} from \"./types\";\nimport type { OperationsApiClient } from \"./useOperations\";\n\nconst LIST_KEY = \"operation-list\";\nconst CLICKY_HEADERS = { Accept: \"application/json+clicky\" };\n\nexport type OperationPagesOptions = {\n client: OperationsApiClient;\n /** The list operation, or undefined for a surface that has none. */\n endpoint: ResolvedOperation | undefined;\n /** Every parameter the operation declares — the source of the cursor role. */\n parameters: OpenAPIParameter[];\n /** Current filter/pagination state, as the catalog holds and URL-mirrors it. */\n filters: ParameterValues;\n /** Omit to infer a cursor walk from the operation; hosts may force either presentation. */\n paginationMode?: \"paged\" | \"infinite\";\n};\n\nexport type OperationPages = {\n /** Every page fetched so far, oldest first. One entry outside a walk. */\n pages: ExecutionResponse[];\n /** The newest page — what every renderer means by \"the response\". */\n response: ExecutionResponse | null;\n /** True while the whole result is being replaced, not while it is growing. */\n isFetching: boolean;\n isPending: boolean;\n isError: boolean;\n error: unknown;\n /** Re-runs the list. A walk restarts rather than replaying its cursors. */\n refetch: () => void;\n /** Load-more handle; absent unless the operation can walk by cursor. */\n infinite?: DataTableInfinite;\n};\n\n/**\n * useOperationPages runs a surface's list operation, walking it forward when it\n * declares a cursor and fetching a single page when it does not. A host can\n * explicitly keep a cursor-capable operation paged when readers need offset\n * controls; omission retains automatic selection.\n *\n * Automatic mode follows the operation: a cursor role is the server saying\n * \"you may resume this query\", and everything else keeps the single-page query\n * it has always had. An explicit host override changes only the presentation;\n * the operation still owns the available cursor and offset capabilities.\n *\n * In walk mode the cursor is deliberately absent from the query key. The key is\n * the identity of the query being walked, and the cursor is a position inside\n * it; keying on it made every page a different query, which is precisely why\n * advancing replaced the rows instead of extending them. Every other filter\n * stays in the key, so any filter, parameter or time-range change starts a new\n * walk on its own, with no reset logic layered on top.\n */\nexport function useOperationPages({\n client,\n endpoint,\n parameters,\n filters,\n paginationMode,\n}: OperationPagesOptions): OperationPages {\n const queryClient = useQueryClient();\n const cursorParam = cursorParameterName(parameters);\n const path = endpoint?.path;\n const method = endpoint?.method;\n if (endpoint && paginationMode === \"infinite\" && !cursorParam) {\n throw new Error(\n `Operation ${method?.toUpperCase()} ${path} cannot use infinite pagination without a cursor parameter`,\n );\n }\n const walkMode = paginationMode === \"infinite\" || (paginationMode === undefined && !!cursorParam);\n\n // The walk's own view of the filters: everything that identifies the query,\n // with the position taken out. A cursor left over in the URL from a shared\n // link names a position in a walk this session never made, so it is dropped\n // rather than replayed.\n const walkFilters = useMemo(() => {\n if (!cursorParam) return filters;\n const rest = { ...filters };\n delete rest[cursorParam];\n return rest;\n }, [cursorParam, filters]);\n\n const execute = useCallback(\n (values: ParameterValues) =>\n client.executeCommand(\n path!,\n method!,\n packParameterValues(values, parameters),\n CLICKY_HEADERS,\n ),\n [client, method, parameters, path],\n );\n\n // Both queries are declared on every render — hooks are not conditional — and\n // exactly one is enabled. Their keys differ in shape as well as content, so a\n // surface that switches modes can never read a page array as a page.\n const single = useQuery<ExecutionResponse>({\n queryKey: [LIST_KEY, method, path, filters],\n queryFn: () => execute(filters),\n enabled: !!endpoint && !walkMode,\n placeholderData: keepPreviousData,\n staleTime: 30_000,\n retry: 0,\n });\n\n // Prefixed with the same LIST_KEY as the single-page query: host apps\n // invalidate [\"operation-list\"] after a mutation, and a walk that fell\n // outside that prefix would keep serving rows the mutation changed.\n const walkKey = useMemo(\n () => [LIST_KEY, \"walk\", method, path, walkFilters],\n [method, path, walkFilters],\n );\n\n const walk = useInfiniteQuery<\n ExecutionResponse,\n Error,\n InfiniteData<ExecutionResponse, string | undefined>,\n QueryKey,\n string | undefined\n >({\n queryKey: walkKey,\n queryFn: ({ pageParam }) =>\n execute(pageParam ? { ...walkFilters, [cursorParam!]: pageParam } : walkFilters),\n initialPageParam: undefined,\n // The server's two answers, both required: it has more, and here is where\n // to resume. A page claiming more without minting a token cannot be walked,\n // and guessing one is how a client forges a position it was never given.\n getNextPageParam: (lastPage) =>\n lastPage.pagination?.hasMore ? lastPage.pagination.nextCursor : undefined,\n enabled: !!endpoint && walkMode,\n placeholderData: keepPreviousData,\n staleTime: 30_000,\n retry: 0,\n });\n\n const walkPages = walk.data?.pages;\n\n // A cursor the server refuses is recoverable by construction: the query is\n // fine and only the position is gone, so the walk starts again instead of\n // stranding the reader on an error panel they cannot page out of. Resetting\n // is what does it — refetching would replay the very cursors that were\n // refused, page by page.\n //\n // Guarded on a page having already been fetched, because only then can a\n // cursor have been sent. A first page refused this way is a server that\n // answers `cursor_stale` to a request carrying no cursor, and restarting on\n // that spins: refuse, restart, refuse.\n const staleWalk = isCursorStale(walk.error) && (walkPages?.length ?? 0) > 0;\n\n useEffect(() => {\n if (!staleWalk) return;\n void queryClient.resetQueries({ queryKey: walkKey });\n }, [queryClient, staleWalk, walkKey]);\n\n const fetchNextPage = walk.fetchNextPage;\n const infinite = useMemo<DataTableInfinite | undefined>(() => {\n if (!walkMode || !cursorParam) return undefined;\n return {\n hasMore: walk.hasNextPage,\n loading: walk.isFetchingNextPage,\n onLoadMore: () => void fetchNextPage(),\n };\n }, [cursorParam, fetchNextPage, walk.hasNextPage, walk.isFetchingNextPage, walkMode]);\n\n const resetWalk = useCallback(() => {\n void queryClient.resetQueries({ queryKey: walkKey });\n }, [queryClient, walkKey]);\n const refetchSingle = single.refetch;\n\n if (!walkMode) {\n return {\n pages: single.data ? [single.data] : [],\n response: single.data ?? null,\n isFetching: single.isFetching,\n isPending: single.isPending,\n isError: single.isError,\n error: single.error,\n refetch: () => void refetchSingle(),\n };\n }\n\n const pages = walkPages ?? [];\n return {\n pages,\n response: pages[pages.length - 1] ?? null,\n // Fetching the next page grows the run; it does not replace it. Reporting\n // it as a load of the whole surface is what drops a spinner over rows the\n // reader is still reading.\n isFetching: walk.isFetching && !walk.isFetchingNextPage,\n isPending: walk.isPending,\n isError: walk.isError && !staleWalk,\n error: staleWalk ? undefined : walk.error,\n // A mutation just changed the rows this walk was cut from, so its cursors\n // no longer name positions in it. Starting over is the only honest refetch.\n refetch: resetWalk,\n ...(infinite ? { infinite } : {}),\n };\n}\n"],"names":["useQueryClient","cursorParameterName","useMemo","useCallback","packParameterValues","useQuery","keepPreviousData","useInfiniteQuery","_a","isCursorStale","useEffect"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"useOperationPages.cjs","sources":["../../src/rpc/useOperationPages.ts"],"sourcesContent":["import { useCallback, useEffect, useMemo } from \"react\";\nimport {\n keepPreviousData,\n useInfiniteQuery,\n useQuery,\n useQueryClient,\n type InfiniteData,\n type QueryKey,\n} from \"@tanstack/react-query\";\n\nimport type { DataTableInfinite } from \"../data/DataTable\";\nimport { cursorParameterName, isCursorStale } from \"./cursorStale\";\nimport { packParameterValues, type ParameterValues } from \"./formMetadata\";\nimport type {\n ExecutionResponse,\n OpenAPIParameter,\n ResolvedOperation,\n} from \"./types\";\nimport type { OperationsApiClient } from \"./useOperations\";\n\nconst LIST_KEY = \"operation-list\";\nconst CLICKY_HEADERS = { Accept: \"application/json+clicky\" };\n\nexport type OperationPagesOptions = {\n client: OperationsApiClient;\n /** The list operation, or undefined for a surface that has none. */\n endpoint: ResolvedOperation | undefined;\n /** Every parameter the operation declares — the source of the cursor role. */\n parameters: OpenAPIParameter[];\n /** Current filter/pagination state, as the catalog holds and URL-mirrors it. */\n filters: ParameterValues;\n /** Omit to infer a cursor walk from the operation; hosts may force either presentation. */\n paginationMode?: \"paged\" | \"infinite\";\n /** Poll the current server page while it can change, in milliseconds. */\n refreshIntervalMs?: number;\n};\n\nexport type OperationPages = {\n /** Every page fetched so far, oldest first. One entry outside a walk. */\n pages: ExecutionResponse[];\n /** The newest page — what every renderer means by \"the response\". */\n response: ExecutionResponse | null;\n /** True while the whole result is being replaced, not while it is growing. */\n isFetching: boolean;\n isPending: boolean;\n isError: boolean;\n error: unknown;\n /** Re-runs the list. A walk restarts rather than replaying its cursors. */\n refetch: () => void;\n /** Load-more handle; absent unless the operation can walk by cursor. */\n infinite?: DataTableInfinite;\n};\n\n/**\n * useOperationPages runs a surface's list operation, walking it forward when it\n * declares a cursor and fetching a single page when it does not. A host can\n * explicitly keep a cursor-capable operation paged when readers need offset\n * controls; omission retains automatic selection.\n *\n * Automatic mode follows the operation: a cursor role is the server saying\n * \"you may resume this query\", and everything else keeps the single-page query\n * it has always had. An explicit host override changes only the presentation;\n * the operation still owns the available cursor and offset capabilities.\n *\n * In walk mode the cursor is deliberately absent from the query key. The key is\n * the identity of the query being walked, and the cursor is a position inside\n * it; keying on it made every page a different query, which is precisely why\n * advancing replaced the rows instead of extending them. Every other filter\n * stays in the key, so any filter, parameter or time-range change starts a new\n * walk on its own, with no reset logic layered on top.\n */\nexport function useOperationPages({\n client,\n endpoint,\n parameters,\n filters,\n paginationMode,\n refreshIntervalMs,\n}: OperationPagesOptions): OperationPages {\n const queryClient = useQueryClient();\n const cursorParam = cursorParameterName(parameters);\n const path = endpoint?.path;\n const method = endpoint?.method;\n if (endpoint && paginationMode === \"infinite\" && !cursorParam) {\n throw new Error(\n `Operation ${method?.toUpperCase()} ${path} cannot use infinite pagination without a cursor parameter`,\n );\n }\n const walkMode = paginationMode === \"infinite\" || (paginationMode === undefined && !!cursorParam);\n if (refreshIntervalMs !== undefined && (!Number.isFinite(refreshIntervalMs) || refreshIntervalMs <= 0 || walkMode)) {\n throw new Error(\"Operation page refresh requires a positive interval and paged mode\");\n }\n\n // The walk's own view of the filters: everything that identifies the query,\n // with the position taken out. A cursor left over in the URL from a shared\n // link names a position in a walk this session never made, so it is dropped\n // rather than replayed.\n const walkFilters = useMemo(() => {\n if (!cursorParam) return filters;\n const rest = { ...filters };\n delete rest[cursorParam];\n return rest;\n }, [cursorParam, filters]);\n\n const execute = useCallback(\n (values: ParameterValues) =>\n client.executeCommand(\n path!,\n method!,\n packParameterValues(values, parameters),\n CLICKY_HEADERS,\n ),\n [client, method, parameters, path],\n );\n\n // Both queries are declared on every render — hooks are not conditional — and\n // exactly one is enabled. Their keys differ in shape as well as content, so a\n // surface that switches modes can never read a page array as a page.\n const single = useQuery<ExecutionResponse>({\n queryKey: [LIST_KEY, method, path, filters],\n queryFn: () => execute(filters),\n enabled: !!endpoint && !walkMode,\n placeholderData: keepPreviousData,\n staleTime: 30_000,\n ...(refreshIntervalMs !== undefined ? { refetchInterval: refreshIntervalMs } : {}),\n retry: 0,\n });\n\n // Prefixed with the same LIST_KEY as the single-page query: host apps\n // invalidate [\"operation-list\"] after a mutation, and a walk that fell\n // outside that prefix would keep serving rows the mutation changed.\n const walkKey = useMemo(\n () => [LIST_KEY, \"walk\", method, path, walkFilters],\n [method, path, walkFilters],\n );\n\n const walk = useInfiniteQuery<\n ExecutionResponse,\n Error,\n InfiniteData<ExecutionResponse, string | undefined>,\n QueryKey,\n string | undefined\n >({\n queryKey: walkKey,\n queryFn: ({ pageParam }) =>\n execute(pageParam ? { ...walkFilters, [cursorParam!]: pageParam } : walkFilters),\n initialPageParam: undefined,\n // The server's two answers, both required: it has more, and here is where\n // to resume. A page claiming more without minting a token cannot be walked,\n // and guessing one is how a client forges a position it was never given.\n getNextPageParam: (lastPage) =>\n lastPage.pagination?.hasMore ? lastPage.pagination.nextCursor : undefined,\n enabled: !!endpoint && walkMode,\n placeholderData: keepPreviousData,\n staleTime: 30_000,\n retry: 0,\n });\n\n const walkPages = walk.data?.pages;\n\n // A cursor the server refuses is recoverable by construction: the query is\n // fine and only the position is gone, so the walk starts again instead of\n // stranding the reader on an error panel they cannot page out of. Resetting\n // is what does it — refetching would replay the very cursors that were\n // refused, page by page.\n //\n // Guarded on a page having already been fetched, because only then can a\n // cursor have been sent. A first page refused this way is a server that\n // answers `cursor_stale` to a request carrying no cursor, and restarting on\n // that spins: refuse, restart, refuse.\n const staleWalk = isCursorStale(walk.error) && (walkPages?.length ?? 0) > 0;\n\n useEffect(() => {\n if (!staleWalk) return;\n void queryClient.resetQueries({ queryKey: walkKey });\n }, [queryClient, staleWalk, walkKey]);\n\n const fetchNextPage = walk.fetchNextPage;\n const infinite = useMemo<DataTableInfinite | undefined>(() => {\n if (!walkMode || !cursorParam) return undefined;\n return {\n hasMore: walk.hasNextPage,\n loading: walk.isFetchingNextPage,\n onLoadMore: () => void fetchNextPage(),\n };\n }, [cursorParam, fetchNextPage, walk.hasNextPage, walk.isFetchingNextPage, walkMode]);\n\n const resetWalk = useCallback(() => {\n void queryClient.resetQueries({ queryKey: walkKey });\n }, [queryClient, walkKey]);\n const refetchSingle = single.refetch;\n\n if (!walkMode) {\n return {\n pages: single.data ? [single.data] : [],\n response: single.data ?? null,\n isFetching: single.isFetching,\n isPending: single.isPending,\n isError: single.isError,\n error: single.error,\n refetch: () => void refetchSingle(),\n };\n }\n\n const pages = walkPages ?? [];\n return {\n pages,\n response: pages[pages.length - 1] ?? null,\n // Fetching the next page grows the run; it does not replace it. Reporting\n // it as a load of the whole surface is what drops a spinner over rows the\n // reader is still reading.\n isFetching: walk.isFetching && !walk.isFetchingNextPage,\n isPending: walk.isPending,\n isError: walk.isError && !staleWalk,\n error: staleWalk ? undefined : walk.error,\n // A mutation just changed the rows this walk was cut from, so its cursors\n // no longer name positions in it. Starting over is the only honest refetch.\n refetch: resetWalk,\n ...(infinite ? { infinite } : {}),\n };\n}\n"],"names":["useQueryClient","cursorParameterName","useMemo","useCallback","packParameterValues","useQuery","keepPreviousData","useInfiniteQuery","_a","isCursorStale","useEffect"],"mappings":"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"}
|
|
@@ -12,6 +12,8 @@ export type OperationPagesOptions = {
|
|
|
12
12
|
filters: ParameterValues;
|
|
13
13
|
/** Omit to infer a cursor walk from the operation; hosts may force either presentation. */
|
|
14
14
|
paginationMode?: "paged" | "infinite";
|
|
15
|
+
/** Poll the current server page while it can change, in milliseconds. */
|
|
16
|
+
refreshIntervalMs?: number;
|
|
15
17
|
};
|
|
16
18
|
export type OperationPages = {
|
|
17
19
|
/** Every page fetched so far, oldest first. One entry outside a walk. */
|
|
@@ -46,5 +48,5 @@ export type OperationPages = {
|
|
|
46
48
|
* stays in the key, so any filter, parameter or time-range change starts a new
|
|
47
49
|
* walk on its own, with no reset logic layered on top.
|
|
48
50
|
*/
|
|
49
|
-
export declare function useOperationPages({ client, endpoint, parameters, filters, paginationMode, }: OperationPagesOptions): OperationPages;
|
|
51
|
+
export declare function useOperationPages({ client, endpoint, parameters, filters, paginationMode, refreshIntervalMs, }: OperationPagesOptions): OperationPages;
|
|
50
52
|
//# sourceMappingURL=useOperationPages.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useOperationPages.d.ts","sourceRoot":"","sources":["../../src/rpc/useOperationPages.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AAE3D,OAAO,EAAuB,KAAK,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAC3E,OAAO,KAAK,EACV,iBAAiB,EACjB,gBAAgB,EAChB,iBAAiB,EAClB,MAAM,SAAS,CAAC;AACjB,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,iBAAiB,CAAC;AAK3D,MAAM,MAAM,qBAAqB,GAAG;IAClC,MAAM,EAAE,mBAAmB,CAAC;IAC5B,oEAAoE;IACpE,QAAQ,EAAE,iBAAiB,GAAG,SAAS,CAAC;IACxC,8EAA8E;IAC9E,UAAU,EAAE,gBAAgB,EAAE,CAAC;IAC/B,gFAAgF;IAChF,OAAO,EAAE,eAAe,CAAC;IACzB,2FAA2F;IAC3F,cAAc,CAAC,EAAE,OAAO,GAAG,UAAU,CAAC;
|
|
1
|
+
{"version":3,"file":"useOperationPages.d.ts","sourceRoot":"","sources":["../../src/rpc/useOperationPages.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AAE3D,OAAO,EAAuB,KAAK,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAC3E,OAAO,KAAK,EACV,iBAAiB,EACjB,gBAAgB,EAChB,iBAAiB,EAClB,MAAM,SAAS,CAAC;AACjB,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,iBAAiB,CAAC;AAK3D,MAAM,MAAM,qBAAqB,GAAG;IAClC,MAAM,EAAE,mBAAmB,CAAC;IAC5B,oEAAoE;IACpE,QAAQ,EAAE,iBAAiB,GAAG,SAAS,CAAC;IACxC,8EAA8E;IAC9E,UAAU,EAAE,gBAAgB,EAAE,CAAC;IAC/B,gFAAgF;IAChF,OAAO,EAAE,eAAe,CAAC;IACzB,2FAA2F;IAC3F,cAAc,CAAC,EAAE,OAAO,GAAG,UAAU,CAAC;IACtC,yEAAyE;IACzE,iBAAiB,CAAC,EAAE,MAAM,CAAC;CAC5B,CAAC;AAEF,MAAM,MAAM,cAAc,GAAG;IAC3B,yEAAyE;IACzE,KAAK,EAAE,iBAAiB,EAAE,CAAC;IAC3B,qEAAqE;IACrE,QAAQ,EAAE,iBAAiB,GAAG,IAAI,CAAC;IACnC,8EAA8E;IAC9E,UAAU,EAAE,OAAO,CAAC;IACpB,SAAS,EAAE,OAAO,CAAC;IACnB,OAAO,EAAE,OAAO,CAAC;IACjB,KAAK,EAAE,OAAO,CAAC;IACf,2EAA2E;IAC3E,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,wEAAwE;IACxE,QAAQ,CAAC,EAAE,iBAAiB,CAAC;CAC9B,CAAC;AAEF;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,iBAAiB,CAAC,EAChC,MAAM,EACN,QAAQ,EACR,UAAU,EACV,OAAO,EACP,cAAc,EACd,iBAAiB,GAClB,EAAE,qBAAqB,GAAG,cAAc,CA8IxC"}
|
|
@@ -9,7 +9,8 @@ function useOperationPages({
|
|
|
9
9
|
endpoint,
|
|
10
10
|
parameters,
|
|
11
11
|
filters,
|
|
12
|
-
paginationMode
|
|
12
|
+
paginationMode,
|
|
13
|
+
refreshIntervalMs
|
|
13
14
|
}) {
|
|
14
15
|
var _a;
|
|
15
16
|
const queryClient = useQueryClient();
|
|
@@ -22,6 +23,9 @@ function useOperationPages({
|
|
|
22
23
|
);
|
|
23
24
|
}
|
|
24
25
|
const walkMode = paginationMode === "infinite" || paginationMode === void 0 && !!cursorParam;
|
|
26
|
+
if (refreshIntervalMs !== void 0 && (!Number.isFinite(refreshIntervalMs) || refreshIntervalMs <= 0 || walkMode)) {
|
|
27
|
+
throw new Error("Operation page refresh requires a positive interval and paged mode");
|
|
28
|
+
}
|
|
25
29
|
const walkFilters = useMemo(() => {
|
|
26
30
|
if (!cursorParam) return filters;
|
|
27
31
|
const rest = { ...filters };
|
|
@@ -43,6 +47,7 @@ function useOperationPages({
|
|
|
43
47
|
enabled: !!endpoint && !walkMode,
|
|
44
48
|
placeholderData: keepPreviousData,
|
|
45
49
|
staleTime: 3e4,
|
|
50
|
+
...refreshIntervalMs !== void 0 ? { refetchInterval: refreshIntervalMs } : {},
|
|
46
51
|
retry: 0
|
|
47
52
|
});
|
|
48
53
|
const walkKey = useMemo(
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useOperationPages.js","sources":["../../src/rpc/useOperationPages.ts"],"sourcesContent":["import { useCallback, useEffect, useMemo } from \"react\";\nimport {\n keepPreviousData,\n useInfiniteQuery,\n useQuery,\n useQueryClient,\n type InfiniteData,\n type QueryKey,\n} from \"@tanstack/react-query\";\n\nimport type { DataTableInfinite } from \"../data/DataTable\";\nimport { cursorParameterName, isCursorStale } from \"./cursorStale\";\nimport { packParameterValues, type ParameterValues } from \"./formMetadata\";\nimport type {\n ExecutionResponse,\n OpenAPIParameter,\n ResolvedOperation,\n} from \"./types\";\nimport type { OperationsApiClient } from \"./useOperations\";\n\nconst LIST_KEY = \"operation-list\";\nconst CLICKY_HEADERS = { Accept: \"application/json+clicky\" };\n\nexport type OperationPagesOptions = {\n client: OperationsApiClient;\n /** The list operation, or undefined for a surface that has none. */\n endpoint: ResolvedOperation | undefined;\n /** Every parameter the operation declares — the source of the cursor role. */\n parameters: OpenAPIParameter[];\n /** Current filter/pagination state, as the catalog holds and URL-mirrors it. */\n filters: ParameterValues;\n /** Omit to infer a cursor walk from the operation; hosts may force either presentation. */\n paginationMode?: \"paged\" | \"infinite\";\n};\n\nexport type OperationPages = {\n /** Every page fetched so far, oldest first. One entry outside a walk. */\n pages: ExecutionResponse[];\n /** The newest page — what every renderer means by \"the response\". */\n response: ExecutionResponse | null;\n /** True while the whole result is being replaced, not while it is growing. */\n isFetching: boolean;\n isPending: boolean;\n isError: boolean;\n error: unknown;\n /** Re-runs the list. A walk restarts rather than replaying its cursors. */\n refetch: () => void;\n /** Load-more handle; absent unless the operation can walk by cursor. */\n infinite?: DataTableInfinite;\n};\n\n/**\n * useOperationPages runs a surface's list operation, walking it forward when it\n * declares a cursor and fetching a single page when it does not. A host can\n * explicitly keep a cursor-capable operation paged when readers need offset\n * controls; omission retains automatic selection.\n *\n * Automatic mode follows the operation: a cursor role is the server saying\n * \"you may resume this query\", and everything else keeps the single-page query\n * it has always had. An explicit host override changes only the presentation;\n * the operation still owns the available cursor and offset capabilities.\n *\n * In walk mode the cursor is deliberately absent from the query key. The key is\n * the identity of the query being walked, and the cursor is a position inside\n * it; keying on it made every page a different query, which is precisely why\n * advancing replaced the rows instead of extending them. Every other filter\n * stays in the key, so any filter, parameter or time-range change starts a new\n * walk on its own, with no reset logic layered on top.\n */\nexport function useOperationPages({\n client,\n endpoint,\n parameters,\n filters,\n paginationMode,\n}: OperationPagesOptions): OperationPages {\n const queryClient = useQueryClient();\n const cursorParam = cursorParameterName(parameters);\n const path = endpoint?.path;\n const method = endpoint?.method;\n if (endpoint && paginationMode === \"infinite\" && !cursorParam) {\n throw new Error(\n `Operation ${method?.toUpperCase()} ${path} cannot use infinite pagination without a cursor parameter`,\n );\n }\n const walkMode = paginationMode === \"infinite\" || (paginationMode === undefined && !!cursorParam);\n\n // The walk's own view of the filters: everything that identifies the query,\n // with the position taken out. A cursor left over in the URL from a shared\n // link names a position in a walk this session never made, so it is dropped\n // rather than replayed.\n const walkFilters = useMemo(() => {\n if (!cursorParam) return filters;\n const rest = { ...filters };\n delete rest[cursorParam];\n return rest;\n }, [cursorParam, filters]);\n\n const execute = useCallback(\n (values: ParameterValues) =>\n client.executeCommand(\n path!,\n method!,\n packParameterValues(values, parameters),\n CLICKY_HEADERS,\n ),\n [client, method, parameters, path],\n );\n\n // Both queries are declared on every render — hooks are not conditional — and\n // exactly one is enabled. Their keys differ in shape as well as content, so a\n // surface that switches modes can never read a page array as a page.\n const single = useQuery<ExecutionResponse>({\n queryKey: [LIST_KEY, method, path, filters],\n queryFn: () => execute(filters),\n enabled: !!endpoint && !walkMode,\n placeholderData: keepPreviousData,\n staleTime: 30_000,\n retry: 0,\n });\n\n // Prefixed with the same LIST_KEY as the single-page query: host apps\n // invalidate [\"operation-list\"] after a mutation, and a walk that fell\n // outside that prefix would keep serving rows the mutation changed.\n const walkKey = useMemo(\n () => [LIST_KEY, \"walk\", method, path, walkFilters],\n [method, path, walkFilters],\n );\n\n const walk = useInfiniteQuery<\n ExecutionResponse,\n Error,\n InfiniteData<ExecutionResponse, string | undefined>,\n QueryKey,\n string | undefined\n >({\n queryKey: walkKey,\n queryFn: ({ pageParam }) =>\n execute(pageParam ? { ...walkFilters, [cursorParam!]: pageParam } : walkFilters),\n initialPageParam: undefined,\n // The server's two answers, both required: it has more, and here is where\n // to resume. A page claiming more without minting a token cannot be walked,\n // and guessing one is how a client forges a position it was never given.\n getNextPageParam: (lastPage) =>\n lastPage.pagination?.hasMore ? lastPage.pagination.nextCursor : undefined,\n enabled: !!endpoint && walkMode,\n placeholderData: keepPreviousData,\n staleTime: 30_000,\n retry: 0,\n });\n\n const walkPages = walk.data?.pages;\n\n // A cursor the server refuses is recoverable by construction: the query is\n // fine and only the position is gone, so the walk starts again instead of\n // stranding the reader on an error panel they cannot page out of. Resetting\n // is what does it — refetching would replay the very cursors that were\n // refused, page by page.\n //\n // Guarded on a page having already been fetched, because only then can a\n // cursor have been sent. A first page refused this way is a server that\n // answers `cursor_stale` to a request carrying no cursor, and restarting on\n // that spins: refuse, restart, refuse.\n const staleWalk = isCursorStale(walk.error) && (walkPages?.length ?? 0) > 0;\n\n useEffect(() => {\n if (!staleWalk) return;\n void queryClient.resetQueries({ queryKey: walkKey });\n }, [queryClient, staleWalk, walkKey]);\n\n const fetchNextPage = walk.fetchNextPage;\n const infinite = useMemo<DataTableInfinite | undefined>(() => {\n if (!walkMode || !cursorParam) return undefined;\n return {\n hasMore: walk.hasNextPage,\n loading: walk.isFetchingNextPage,\n onLoadMore: () => void fetchNextPage(),\n };\n }, [cursorParam, fetchNextPage, walk.hasNextPage, walk.isFetchingNextPage, walkMode]);\n\n const resetWalk = useCallback(() => {\n void queryClient.resetQueries({ queryKey: walkKey });\n }, [queryClient, walkKey]);\n const refetchSingle = single.refetch;\n\n if (!walkMode) {\n return {\n pages: single.data ? [single.data] : [],\n response: single.data ?? null,\n isFetching: single.isFetching,\n isPending: single.isPending,\n isError: single.isError,\n error: single.error,\n refetch: () => void refetchSingle(),\n };\n }\n\n const pages = walkPages ?? [];\n return {\n pages,\n response: pages[pages.length - 1] ?? null,\n // Fetching the next page grows the run; it does not replace it. Reporting\n // it as a load of the whole surface is what drops a spinner over rows the\n // reader is still reading.\n isFetching: walk.isFetching && !walk.isFetchingNextPage,\n isPending: walk.isPending,\n isError: walk.isError && !staleWalk,\n error: staleWalk ? undefined : walk.error,\n // A mutation just changed the rows this walk was cut from, so its cursors\n // no longer name positions in it. Starting over is the only honest refetch.\n refetch: resetWalk,\n ...(infinite ? { infinite } : {}),\n };\n}\n"],"names":["_a"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"useOperationPages.js","sources":["../../src/rpc/useOperationPages.ts"],"sourcesContent":["import { useCallback, useEffect, useMemo } from \"react\";\nimport {\n keepPreviousData,\n useInfiniteQuery,\n useQuery,\n useQueryClient,\n type InfiniteData,\n type QueryKey,\n} from \"@tanstack/react-query\";\n\nimport type { DataTableInfinite } from \"../data/DataTable\";\nimport { cursorParameterName, isCursorStale } from \"./cursorStale\";\nimport { packParameterValues, type ParameterValues } from \"./formMetadata\";\nimport type {\n ExecutionResponse,\n OpenAPIParameter,\n ResolvedOperation,\n} from \"./types\";\nimport type { OperationsApiClient } from \"./useOperations\";\n\nconst LIST_KEY = \"operation-list\";\nconst CLICKY_HEADERS = { Accept: \"application/json+clicky\" };\n\nexport type OperationPagesOptions = {\n client: OperationsApiClient;\n /** The list operation, or undefined for a surface that has none. */\n endpoint: ResolvedOperation | undefined;\n /** Every parameter the operation declares — the source of the cursor role. */\n parameters: OpenAPIParameter[];\n /** Current filter/pagination state, as the catalog holds and URL-mirrors it. */\n filters: ParameterValues;\n /** Omit to infer a cursor walk from the operation; hosts may force either presentation. */\n paginationMode?: \"paged\" | \"infinite\";\n /** Poll the current server page while it can change, in milliseconds. */\n refreshIntervalMs?: number;\n};\n\nexport type OperationPages = {\n /** Every page fetched so far, oldest first. One entry outside a walk. */\n pages: ExecutionResponse[];\n /** The newest page — what every renderer means by \"the response\". */\n response: ExecutionResponse | null;\n /** True while the whole result is being replaced, not while it is growing. */\n isFetching: boolean;\n isPending: boolean;\n isError: boolean;\n error: unknown;\n /** Re-runs the list. A walk restarts rather than replaying its cursors. */\n refetch: () => void;\n /** Load-more handle; absent unless the operation can walk by cursor. */\n infinite?: DataTableInfinite;\n};\n\n/**\n * useOperationPages runs a surface's list operation, walking it forward when it\n * declares a cursor and fetching a single page when it does not. A host can\n * explicitly keep a cursor-capable operation paged when readers need offset\n * controls; omission retains automatic selection.\n *\n * Automatic mode follows the operation: a cursor role is the server saying\n * \"you may resume this query\", and everything else keeps the single-page query\n * it has always had. An explicit host override changes only the presentation;\n * the operation still owns the available cursor and offset capabilities.\n *\n * In walk mode the cursor is deliberately absent from the query key. The key is\n * the identity of the query being walked, and the cursor is a position inside\n * it; keying on it made every page a different query, which is precisely why\n * advancing replaced the rows instead of extending them. Every other filter\n * stays in the key, so any filter, parameter or time-range change starts a new\n * walk on its own, with no reset logic layered on top.\n */\nexport function useOperationPages({\n client,\n endpoint,\n parameters,\n filters,\n paginationMode,\n refreshIntervalMs,\n}: OperationPagesOptions): OperationPages {\n const queryClient = useQueryClient();\n const cursorParam = cursorParameterName(parameters);\n const path = endpoint?.path;\n const method = endpoint?.method;\n if (endpoint && paginationMode === \"infinite\" && !cursorParam) {\n throw new Error(\n `Operation ${method?.toUpperCase()} ${path} cannot use infinite pagination without a cursor parameter`,\n );\n }\n const walkMode = paginationMode === \"infinite\" || (paginationMode === undefined && !!cursorParam);\n if (refreshIntervalMs !== undefined && (!Number.isFinite(refreshIntervalMs) || refreshIntervalMs <= 0 || walkMode)) {\n throw new Error(\"Operation page refresh requires a positive interval and paged mode\");\n }\n\n // The walk's own view of the filters: everything that identifies the query,\n // with the position taken out. A cursor left over in the URL from a shared\n // link names a position in a walk this session never made, so it is dropped\n // rather than replayed.\n const walkFilters = useMemo(() => {\n if (!cursorParam) return filters;\n const rest = { ...filters };\n delete rest[cursorParam];\n return rest;\n }, [cursorParam, filters]);\n\n const execute = useCallback(\n (values: ParameterValues) =>\n client.executeCommand(\n path!,\n method!,\n packParameterValues(values, parameters),\n CLICKY_HEADERS,\n ),\n [client, method, parameters, path],\n );\n\n // Both queries are declared on every render — hooks are not conditional — and\n // exactly one is enabled. Their keys differ in shape as well as content, so a\n // surface that switches modes can never read a page array as a page.\n const single = useQuery<ExecutionResponse>({\n queryKey: [LIST_KEY, method, path, filters],\n queryFn: () => execute(filters),\n enabled: !!endpoint && !walkMode,\n placeholderData: keepPreviousData,\n staleTime: 30_000,\n ...(refreshIntervalMs !== undefined ? { refetchInterval: refreshIntervalMs } : {}),\n retry: 0,\n });\n\n // Prefixed with the same LIST_KEY as the single-page query: host apps\n // invalidate [\"operation-list\"] after a mutation, and a walk that fell\n // outside that prefix would keep serving rows the mutation changed.\n const walkKey = useMemo(\n () => [LIST_KEY, \"walk\", method, path, walkFilters],\n [method, path, walkFilters],\n );\n\n const walk = useInfiniteQuery<\n ExecutionResponse,\n Error,\n InfiniteData<ExecutionResponse, string | undefined>,\n QueryKey,\n string | undefined\n >({\n queryKey: walkKey,\n queryFn: ({ pageParam }) =>\n execute(pageParam ? { ...walkFilters, [cursorParam!]: pageParam } : walkFilters),\n initialPageParam: undefined,\n // The server's two answers, both required: it has more, and here is where\n // to resume. A page claiming more without minting a token cannot be walked,\n // and guessing one is how a client forges a position it was never given.\n getNextPageParam: (lastPage) =>\n lastPage.pagination?.hasMore ? lastPage.pagination.nextCursor : undefined,\n enabled: !!endpoint && walkMode,\n placeholderData: keepPreviousData,\n staleTime: 30_000,\n retry: 0,\n });\n\n const walkPages = walk.data?.pages;\n\n // A cursor the server refuses is recoverable by construction: the query is\n // fine and only the position is gone, so the walk starts again instead of\n // stranding the reader on an error panel they cannot page out of. Resetting\n // is what does it — refetching would replay the very cursors that were\n // refused, page by page.\n //\n // Guarded on a page having already been fetched, because only then can a\n // cursor have been sent. A first page refused this way is a server that\n // answers `cursor_stale` to a request carrying no cursor, and restarting on\n // that spins: refuse, restart, refuse.\n const staleWalk = isCursorStale(walk.error) && (walkPages?.length ?? 0) > 0;\n\n useEffect(() => {\n if (!staleWalk) return;\n void queryClient.resetQueries({ queryKey: walkKey });\n }, [queryClient, staleWalk, walkKey]);\n\n const fetchNextPage = walk.fetchNextPage;\n const infinite = useMemo<DataTableInfinite | undefined>(() => {\n if (!walkMode || !cursorParam) return undefined;\n return {\n hasMore: walk.hasNextPage,\n loading: walk.isFetchingNextPage,\n onLoadMore: () => void fetchNextPage(),\n };\n }, [cursorParam, fetchNextPage, walk.hasNextPage, walk.isFetchingNextPage, walkMode]);\n\n const resetWalk = useCallback(() => {\n void queryClient.resetQueries({ queryKey: walkKey });\n }, [queryClient, walkKey]);\n const refetchSingle = single.refetch;\n\n if (!walkMode) {\n return {\n pages: single.data ? [single.data] : [],\n response: single.data ?? null,\n isFetching: single.isFetching,\n isPending: single.isPending,\n isError: single.isError,\n error: single.error,\n refetch: () => void refetchSingle(),\n };\n }\n\n const pages = walkPages ?? [];\n return {\n pages,\n response: pages[pages.length - 1] ?? null,\n // Fetching the next page grows the run; it does not replace it. Reporting\n // it as a load of the whole surface is what drops a spinner over rows the\n // reader is still reading.\n isFetching: walk.isFetching && !walk.isFetchingNextPage,\n isPending: walk.isPending,\n isError: walk.isError && !staleWalk,\n error: staleWalk ? undefined : walk.error,\n // A mutation just changed the rows this walk was cut from, so its cursors\n // no longer name positions in it. Starting over is the only honest refetch.\n refetch: resetWalk,\n ...(infinite ? { infinite } : {}),\n };\n}\n"],"names":["_a"],"mappings":"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"}
|