@cohesivesystems/presentation-react 0.1.0-alpha.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +55 -0
- package/dist/collection-chrome-slot-renderer-registry.d.ts +12 -0
- package/dist/collection-chrome-slot-renderer-registry.d.ts.map +1 -0
- package/dist/collection-chrome-slot-renderer-registry.js +12 -0
- package/dist/collection-chrome-slot-renderer-registry.js.map +1 -0
- package/dist/collection-selection-state-context.d.ts +6 -0
- package/dist/collection-selection-state-context.d.ts.map +1 -0
- package/dist/collection-selection-state-context.js +25 -0
- package/dist/collection-selection-state-context.js.map +1 -0
- package/dist/collection-selection-state.d.ts +3 -0
- package/dist/collection-selection-state.d.ts.map +1 -0
- package/dist/collection-selection-state.js +52 -0
- package/dist/collection-selection-state.js.map +1 -0
- package/dist/document-workspace-runtime.d.ts +262 -0
- package/dist/document-workspace-runtime.d.ts.map +1 -0
- package/dist/document-workspace-runtime.js +699 -0
- package/dist/document-workspace-runtime.js.map +1 -0
- package/dist/index.d.ts +51 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +51 -0
- package/dist/index.js.map +1 -0
- package/dist/input-form-endpoint-runtime.d.ts +140 -0
- package/dist/input-form-endpoint-runtime.d.ts.map +1 -0
- package/dist/input-form-endpoint-runtime.js +280 -0
- package/dist/input-form-endpoint-runtime.js.map +1 -0
- package/dist/local-flow-state-data-source-projection.d.ts +21 -0
- package/dist/local-flow-state-data-source-projection.d.ts.map +1 -0
- package/dist/local-flow-state-data-source-projection.js +65 -0
- package/dist/local-flow-state-data-source-projection.js.map +1 -0
- package/dist/navigation-runtime-context.d.ts +22 -0
- package/dist/navigation-runtime-context.d.ts.map +1 -0
- package/dist/navigation-runtime-context.js +23 -0
- package/dist/navigation-runtime-context.js.map +1 -0
- package/dist/navigation-shell-frame-renderer-registry.d.ts +20 -0
- package/dist/navigation-shell-frame-renderer-registry.d.ts.map +1 -0
- package/dist/navigation-shell-frame-renderer-registry.js +9 -0
- package/dist/navigation-shell-frame-renderer-registry.js.map +1 -0
- package/dist/navigation-shell-region-component-registry.d.ts +50 -0
- package/dist/navigation-shell-region-component-registry.d.ts.map +1 -0
- package/dist/navigation-shell-region-component-registry.js +44 -0
- package/dist/navigation-shell-region-component-registry.js.map +1 -0
- package/dist/navigation-shell-slot-renderer-registry.d.ts +22 -0
- package/dist/navigation-shell-slot-renderer-registry.d.ts.map +1 -0
- package/dist/navigation-shell-slot-renderer-registry.js +9 -0
- package/dist/navigation-shell-slot-renderer-registry.js.map +1 -0
- package/dist/page-host-projection.d.ts +127 -0
- package/dist/page-host-projection.d.ts.map +1 -0
- package/dist/page-host-projection.js +59 -0
- package/dist/page-host-projection.js.map +1 -0
- package/dist/page-host-renderer-registry.d.ts +72 -0
- package/dist/page-host-renderer-registry.d.ts.map +1 -0
- package/dist/page-host-renderer-registry.js +63 -0
- package/dist/page-host-renderer-registry.js.map +1 -0
- package/dist/presentation-action-group-runtime-options.d.ts +36 -0
- package/dist/presentation-action-group-runtime-options.d.ts.map +1 -0
- package/dist/presentation-action-group-runtime-options.js +50 -0
- package/dist/presentation-action-group-runtime-options.js.map +1 -0
- package/dist/presentation-action-runtime.d.ts +52 -0
- package/dist/presentation-action-runtime.d.ts.map +1 -0
- package/dist/presentation-action-runtime.js +78 -0
- package/dist/presentation-action-runtime.js.map +1 -0
- package/dist/presentation-data-source-binding-runtime.d.ts +3 -0
- package/dist/presentation-data-source-binding-runtime.d.ts.map +1 -0
- package/dist/presentation-data-source-binding-runtime.js +65 -0
- package/dist/presentation-data-source-binding-runtime.js.map +1 -0
- package/dist/presentation-data-source-binding.d.ts +12 -0
- package/dist/presentation-data-source-binding.d.ts.map +1 -0
- package/dist/presentation-data-source-binding.js +13 -0
- package/dist/presentation-data-source-binding.js.map +1 -0
- package/dist/presentation-flow-runtime.d.ts +139 -0
- package/dist/presentation-flow-runtime.d.ts.map +1 -0
- package/dist/presentation-flow-runtime.js +514 -0
- package/dist/presentation-flow-runtime.js.map +1 -0
- package/dist/presentation-module-context.d.ts +4 -0
- package/dist/presentation-module-context.d.ts.map +1 -0
- package/dist/presentation-module-context.js +6 -0
- package/dist/presentation-module-context.js.map +1 -0
- package/dist/presentation-module-provider.d.ts +7 -0
- package/dist/presentation-module-provider.d.ts.map +1 -0
- package/dist/presentation-module-provider.js +7 -0
- package/dist/presentation-module-provider.js.map +1 -0
- package/dist/presentation-projection-diagnostics-context.d.ts +8 -0
- package/dist/presentation-projection-diagnostics-context.d.ts.map +1 -0
- package/dist/presentation-projection-diagnostics-context.js +3 -0
- package/dist/presentation-projection-diagnostics-context.js.map +1 -0
- package/dist/presentation-projection-diagnostics-hooks.d.ts +4 -0
- package/dist/presentation-projection-diagnostics-hooks.d.ts.map +1 -0
- package/dist/presentation-projection-diagnostics-hooks.js +17 -0
- package/dist/presentation-projection-diagnostics-hooks.js.map +1 -0
- package/dist/presentation-projection-diagnostics-runtime.d.ts +12 -0
- package/dist/presentation-projection-diagnostics-runtime.d.ts.map +1 -0
- package/dist/presentation-projection-diagnostics-runtime.js +54 -0
- package/dist/presentation-projection-diagnostics-runtime.js.map +1 -0
- package/dist/presentation-projection-trace.d.ts +27 -0
- package/dist/presentation-projection-trace.d.ts.map +1 -0
- package/dist/presentation-projection-trace.js +54 -0
- package/dist/presentation-projection-trace.js.map +1 -0
- package/dist/presentation-query-form-runtime.d.ts +30 -0
- package/dist/presentation-query-form-runtime.d.ts.map +1 -0
- package/dist/presentation-query-form-runtime.js +75 -0
- package/dist/presentation-query-form-runtime.js.map +1 -0
- package/dist/presentation-query-form-state-adapter-registry.d.ts +4 -0
- package/dist/presentation-query-form-state-adapter-registry.d.ts.map +1 -0
- package/dist/presentation-query-form-state-adapter-registry.js +13 -0
- package/dist/presentation-query-form-state-adapter-registry.js.map +1 -0
- package/dist/presentation-query-form-state-context.d.ts +20 -0
- package/dist/presentation-query-form-state-context.d.ts.map +1 -0
- package/dist/presentation-query-form-state-context.js +20 -0
- package/dist/presentation-query-form-state-context.js.map +1 -0
- package/dist/presentation-query-form-state.d.ts +29 -0
- package/dist/presentation-query-form-state.d.ts.map +1 -0
- package/dist/presentation-query-form-state.js +99 -0
- package/dist/presentation-query-form-state.js.map +1 -0
- package/dist/presentation-renderer-registry.d.ts +109 -0
- package/dist/presentation-renderer-registry.d.ts.map +1 -0
- package/dist/presentation-renderer-registry.js +25 -0
- package/dist/presentation-renderer-registry.js.map +1 -0
- package/dist/presentation-standards-context.d.ts +4 -0
- package/dist/presentation-standards-context.d.ts.map +1 -0
- package/dist/presentation-standards-context.js +12 -0
- package/dist/presentation-standards-context.js.map +1 -0
- package/dist/presentation-standards-provider.d.ts +14 -0
- package/dist/presentation-standards-provider.d.ts.map +1 -0
- package/dist/presentation-standards-provider.js +16 -0
- package/dist/presentation-standards-provider.js.map +1 -0
- package/dist/projected-document-action-runtime-bindings.d.ts +20 -0
- package/dist/projected-document-action-runtime-bindings.d.ts.map +1 -0
- package/dist/projected-document-action-runtime-bindings.js +88 -0
- package/dist/projected-document-action-runtime-bindings.js.map +1 -0
- package/dist/projected-document-action-runtime.d.ts +76 -0
- package/dist/projected-document-action-runtime.d.ts.map +1 -0
- package/dist/projected-document-action-runtime.js +224 -0
- package/dist/projected-document-action-runtime.js.map +1 -0
- package/dist/projected-document-process-preview-action-runtime-bindings.d.ts +26 -0
- package/dist/projected-document-process-preview-action-runtime-bindings.d.ts.map +1 -0
- package/dist/projected-document-process-preview-action-runtime-bindings.js +106 -0
- package/dist/projected-document-process-preview-action-runtime-bindings.js.map +1 -0
- package/dist/projected-document-process-preview-action-runtime.d.ts +321 -0
- package/dist/projected-document-process-preview-action-runtime.d.ts.map +1 -0
- package/dist/projected-document-process-preview-action-runtime.js +729 -0
- package/dist/projected-document-process-preview-action-runtime.js.map +1 -0
- package/dist/projected-document-process-preview-capability-runtime.d.ts +47 -0
- package/dist/projected-document-process-preview-capability-runtime.d.ts.map +1 -0
- package/dist/projected-document-process-preview-capability-runtime.js +49 -0
- package/dist/projected-document-process-preview-capability-runtime.js.map +1 -0
- package/dist/projected-document-workspace-action-runtime.d.ts +87 -0
- package/dist/projected-document-workspace-action-runtime.d.ts.map +1 -0
- package/dist/projected-document-workspace-action-runtime.js +150 -0
- package/dist/projected-document-workspace-action-runtime.js.map +1 -0
- package/dist/projected-document-workspace-projection-renderer-diagnostics.d.ts +18 -0
- package/dist/projected-document-workspace-projection-renderer-diagnostics.d.ts.map +1 -0
- package/dist/projected-document-workspace-projection-renderer-diagnostics.js +207 -0
- package/dist/projected-document-workspace-projection-renderer-diagnostics.js.map +1 -0
- package/dist/projected-document-workspace-runtime-binding-diagnostics.d.ts +19 -0
- package/dist/projected-document-workspace-runtime-binding-diagnostics.d.ts.map +1 -0
- package/dist/projected-document-workspace-runtime-binding-diagnostics.js +124 -0
- package/dist/projected-document-workspace-runtime-binding-diagnostics.js.map +1 -0
- package/dist/projected-navigation-provider.d.ts +16 -0
- package/dist/projected-navigation-provider.d.ts.map +1 -0
- package/dist/projected-navigation-provider.js +51 -0
- package/dist/projected-navigation-provider.js.map +1 -0
- package/dist/projected-presentation-flow-host.d.ts +16 -0
- package/dist/projected-presentation-flow-host.d.ts.map +1 -0
- package/dist/projected-presentation-flow-host.js +14 -0
- package/dist/projected-presentation-flow-host.js.map +1 -0
- package/dist/projected-query-form-state-adapter.d.ts +12 -0
- package/dist/projected-query-form-state-adapter.d.ts.map +1 -0
- package/dist/projected-query-form-state-adapter.js +361 -0
- package/dist/projected-query-form-state-adapter.js.map +1 -0
- package/dist/react-router-binding.d.ts +133 -0
- package/dist/react-router-binding.d.ts.map +1 -0
- package/dist/react-router-binding.js +76 -0
- package/dist/react-router-binding.js.map +1 -0
- package/dist/react-router-path.d.ts +4 -0
- package/dist/react-router-path.d.ts.map +1 -0
- package/dist/react-router-path.js +11 -0
- package/dist/react-router-path.js.map +1 -0
- package/dist/scope-selection-context.d.ts +28 -0
- package/dist/scope-selection-context.d.ts.map +1 -0
- package/dist/scope-selection-context.js +13 -0
- package/dist/scope-selection-context.js.map +1 -0
- package/dist/scope-selection-provider.d.ts +33 -0
- package/dist/scope-selection-provider.d.ts.map +1 -0
- package/dist/scope-selection-provider.js +162 -0
- package/dist/scope-selection-provider.js.map +1 -0
- package/dist/scope-selection-request.d.ts +6 -0
- package/dist/scope-selection-request.d.ts.map +1 -0
- package/dist/scope-selection-request.js +12 -0
- package/dist/scope-selection-request.js.map +1 -0
- package/dist/standard-navigation-shell-frame-renderers.d.ts +15 -0
- package/dist/standard-navigation-shell-frame-renderers.d.ts.map +1 -0
- package/dist/standard-navigation-shell-frame-renderers.js +22 -0
- package/dist/standard-navigation-shell-frame-renderers.js.map +1 -0
- package/dist/standard-navigation-shell-slot-renderers.d.ts +59 -0
- package/dist/standard-navigation-shell-slot-renderers.d.ts.map +1 -0
- package/dist/standard-navigation-shell-slot-renderers.js +67 -0
- package/dist/standard-navigation-shell-slot-renderers.js.map +1 -0
- package/dist/view-chrome-slot-renderer-registry.d.ts +12 -0
- package/dist/view-chrome-slot-renderer-registry.d.ts.map +1 -0
- package/dist/view-chrome-slot-renderer-registry.js +12 -0
- package/dist/view-chrome-slot-renderer-registry.js.map +1 -0
- package/package.json +60 -0
- package/src/collection-chrome-slot-renderer-registry.ts +66 -0
- package/src/collection-selection-state-context.ts +51 -0
- package/src/collection-selection-state.tsx +101 -0
- package/src/document-workspace-runtime.tsx +1505 -0
- package/src/index.ts +50 -0
- package/src/input-form-endpoint-runtime.ts +632 -0
- package/src/local-flow-state-data-source-projection.ts +133 -0
- package/src/navigation-runtime-context.ts +40 -0
- package/src/navigation-shell-frame-renderer-registry.ts +54 -0
- package/src/navigation-shell-region-component-registry.tsx +127 -0
- package/src/navigation-shell-slot-renderer-registry.ts +88 -0
- package/src/page-host-projection.ts +356 -0
- package/src/page-host-renderer-registry.tsx +353 -0
- package/src/presentation-action-group-runtime-options.ts +121 -0
- package/src/presentation-action-runtime.ts +190 -0
- package/src/presentation-data-source-binding-runtime.ts +109 -0
- package/src/presentation-data-source-binding.tsx +24 -0
- package/src/presentation-flow-runtime.tsx +835 -0
- package/src/presentation-module-context.ts +10 -0
- package/src/presentation-module-provider.tsx +19 -0
- package/src/presentation-projection-diagnostics-context.ts +17 -0
- package/src/presentation-projection-diagnostics-hooks.ts +29 -0
- package/src/presentation-projection-diagnostics-runtime.tsx +95 -0
- package/src/presentation-projection-trace.ts +117 -0
- package/src/presentation-query-form-runtime.ts +148 -0
- package/src/presentation-query-form-state-adapter-registry.ts +25 -0
- package/src/presentation-query-form-state-context.ts +56 -0
- package/src/presentation-query-form-state.tsx +250 -0
- package/src/presentation-renderer-registry.ts +214 -0
- package/src/presentation-standards-context.ts +21 -0
- package/src/presentation-standards-provider.tsx +44 -0
- package/src/projected-document-action-runtime-bindings.ts +132 -0
- package/src/projected-document-action-runtime.ts +414 -0
- package/src/projected-document-process-preview-action-runtime-bindings.ts +231 -0
- package/src/projected-document-process-preview-action-runtime.ts +1725 -0
- package/src/projected-document-process-preview-capability-runtime.ts +216 -0
- package/src/projected-document-workspace-action-runtime.ts +402 -0
- package/src/projected-document-workspace-projection-renderer-diagnostics.ts +342 -0
- package/src/projected-document-workspace-runtime-binding-diagnostics.ts +208 -0
- package/src/projected-navigation-provider.tsx +104 -0
- package/src/projected-presentation-flow-host.tsx +46 -0
- package/src/projected-query-form-state-adapter.ts +578 -0
- package/src/react-router-binding.tsx +417 -0
- package/src/react-router-path.ts +16 -0
- package/src/scope-selection-context.ts +58 -0
- package/src/scope-selection-provider.tsx +324 -0
- package/src/scope-selection-request.ts +21 -0
- package/src/standard-navigation-shell-frame-renderers.tsx +106 -0
- package/src/standard-navigation-shell-slot-renderers.tsx +289 -0
- package/src/view-chrome-slot-renderer-registry.ts +66 -0
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
import type { ReactNode } from 'react'
|
|
2
|
+
|
|
3
|
+
import type {
|
|
4
|
+
ActionDefinition,
|
|
5
|
+
ActionPlacementDefinition,
|
|
6
|
+
PresentationDataSourceResolver,
|
|
7
|
+
PresentationModuleDefinition,
|
|
8
|
+
ViewDefinition,
|
|
9
|
+
} from '@cohesivesystems/presentation-core'
|
|
10
|
+
import type {
|
|
11
|
+
PresentationActionRuntimeRegistry,
|
|
12
|
+
} from '@cohesivesystems/presentation-core'
|
|
13
|
+
|
|
14
|
+
export interface PresentationActionRenderState {
|
|
15
|
+
readonly disabledReason?: ReactNode
|
|
16
|
+
readonly isDisabled?: boolean
|
|
17
|
+
readonly isHidden?: boolean
|
|
18
|
+
readonly isPending?: boolean
|
|
19
|
+
readonly label?: ReactNode
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export interface PresentationActionGroupRenderContext<TContext> {
|
|
23
|
+
readonly context: TContext
|
|
24
|
+
readonly dataSourceResolver: PresentationDataSourceResolver
|
|
25
|
+
readonly module: Pick<PresentationModuleDefinition, 'Actions' | 'Targets'>
|
|
26
|
+
readonly view: ViewDefinition
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export interface PresentationActionRenderContext<TContext>
|
|
30
|
+
extends PresentationActionGroupRenderContext<TContext> {
|
|
31
|
+
readonly action: ActionDefinition | null
|
|
32
|
+
readonly invalidatedDataSourceIds: readonly string[]
|
|
33
|
+
readonly isFetching: boolean
|
|
34
|
+
readonly placement: ActionPlacementDefinition
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export interface PresentationActionGroupOptions<TContext> {
|
|
38
|
+
readonly canExecuteAction?: (context: PresentationActionRenderContext<TContext>) => boolean
|
|
39
|
+
readonly executeAction?: (context: PresentationActionRenderContext<TContext>) => Promise<void> | void
|
|
40
|
+
readonly renderActionLabel?: (context: PresentationActionRenderContext<TContext>) => ReactNode
|
|
41
|
+
readonly resolveActionState?: (
|
|
42
|
+
context: PresentationActionRenderContext<TContext>,
|
|
43
|
+
) => PresentationActionRenderState | null | undefined
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export interface PresentationActionGroupRuntimeOptions<TContext>
|
|
47
|
+
extends PresentationActionGroupOptions<TContext> {
|
|
48
|
+
readonly runtimes?: PresentationActionRuntimeRegistry<
|
|
49
|
+
PresentationActionRenderContext<TContext>,
|
|
50
|
+
ReactNode
|
|
51
|
+
>
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Creates standard action-group options from a semantic action runtime registry.
|
|
56
|
+
*/
|
|
57
|
+
export function createPresentationActionGroupRuntimeOptions<TContext>({
|
|
58
|
+
canExecuteAction,
|
|
59
|
+
executeAction,
|
|
60
|
+
renderActionLabel,
|
|
61
|
+
resolveActionState,
|
|
62
|
+
runtimes,
|
|
63
|
+
...options
|
|
64
|
+
}: PresentationActionGroupRuntimeOptions<TContext> = {}): PresentationActionGroupOptions<TContext> {
|
|
65
|
+
const resolvedExecuteAction =
|
|
66
|
+
runtimes || executeAction
|
|
67
|
+
? (context: PresentationActionRenderContext<TContext>) => {
|
|
68
|
+
const runtime = resolveRuntime(runtimes, context)
|
|
69
|
+
if (
|
|
70
|
+
runtime?.execute &&
|
|
71
|
+
!runtime.isDisabled &&
|
|
72
|
+
!runtime.isHidden &&
|
|
73
|
+
(runtime.canExecute?.(context) ?? true)
|
|
74
|
+
) {
|
|
75
|
+
return runtime.execute(context)
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
return executeAction?.(context)
|
|
79
|
+
}
|
|
80
|
+
: undefined
|
|
81
|
+
|
|
82
|
+
return {
|
|
83
|
+
...options,
|
|
84
|
+
canExecuteAction: (context) => {
|
|
85
|
+
const runtime = resolveRuntime(runtimes, context)
|
|
86
|
+
if (runtime?.isDisabled || runtime?.isHidden) {
|
|
87
|
+
return false
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
if (runtime?.canExecute && !runtime.canExecute(context)) {
|
|
91
|
+
return false
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
return canExecuteAction?.(context) ?? true
|
|
95
|
+
},
|
|
96
|
+
executeAction: resolvedExecuteAction,
|
|
97
|
+
renderActionLabel,
|
|
98
|
+
resolveActionState: (context) => {
|
|
99
|
+
const runtime = resolveRuntime(runtimes, context)
|
|
100
|
+
const baseState = resolveActionState?.(context)
|
|
101
|
+
return {
|
|
102
|
+
...baseState,
|
|
103
|
+
disabledReason: runtime?.disabledReason ?? baseState?.disabledReason,
|
|
104
|
+
isDisabled: Boolean(baseState?.isDisabled || runtime?.isDisabled),
|
|
105
|
+
isHidden: Boolean(baseState?.isHidden || runtime?.isHidden),
|
|
106
|
+
isPending: Boolean(baseState?.isPending || runtime?.isPending),
|
|
107
|
+
label:
|
|
108
|
+
runtime?.isPending && runtime.pendingLabel
|
|
109
|
+
? runtime.pendingLabel
|
|
110
|
+
: (runtime?.label ?? baseState?.label),
|
|
111
|
+
}
|
|
112
|
+
},
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
function resolveRuntime<TContext>(
|
|
117
|
+
runtimes: PresentationActionGroupRuntimeOptions<TContext>['runtimes'] | undefined,
|
|
118
|
+
context: PresentationActionRenderContext<TContext>,
|
|
119
|
+
) {
|
|
120
|
+
return runtimes?.[context.placement.ActionId] ?? null
|
|
121
|
+
}
|
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
import { useMutation, useQueryClient, type QueryClient } from '@tanstack/react-query'
|
|
2
|
+
import { useMemo } from 'react'
|
|
3
|
+
|
|
4
|
+
import type {
|
|
5
|
+
PresentationActionEndpointExecutionRequest,
|
|
6
|
+
} from '@cohesivesystems/presentation-core'
|
|
7
|
+
import {
|
|
8
|
+
findPresentationAction,
|
|
9
|
+
type ActionDefinition,
|
|
10
|
+
type PresentationBindingDefinition,
|
|
11
|
+
type PresentationModuleDefinition,
|
|
12
|
+
resolvePresentationActionEndpointBinding,
|
|
13
|
+
} from '@cohesivesystems/presentation-core'
|
|
14
|
+
|
|
15
|
+
export type { PresentationActionEndpointExecutionRequest } from '@cohesivesystems/presentation-core'
|
|
16
|
+
|
|
17
|
+
export type PresentationActionEndpointExecutor = <TResult = unknown>(
|
|
18
|
+
endpointId: string,
|
|
19
|
+
request: PresentationActionEndpointExecutionRequest,
|
|
20
|
+
) => Promise<TResult>
|
|
21
|
+
|
|
22
|
+
export interface PresentationActionRequestPreparationContext<TInput> {
|
|
23
|
+
readonly action: ActionDefinition | null
|
|
24
|
+
readonly actionId: string
|
|
25
|
+
readonly binding: PresentationBindingDefinition | null
|
|
26
|
+
readonly endpointId: string
|
|
27
|
+
readonly input: TInput
|
|
28
|
+
readonly module: PresentationModuleDefinition | null
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export interface PresentationActionSuccessContext<TInput, TResult> {
|
|
32
|
+
readonly action: ActionDefinition | null
|
|
33
|
+
readonly actionId: string
|
|
34
|
+
readonly endpointId: string
|
|
35
|
+
readonly input: TInput
|
|
36
|
+
readonly queryClient: QueryClient
|
|
37
|
+
readonly result: TResult
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export interface UsePresentationActionExecutorOptions<TInput, TResult> {
|
|
41
|
+
readonly actionId: string
|
|
42
|
+
readonly componentSet?: string | null
|
|
43
|
+
readonly dataSourceId?: string | null
|
|
44
|
+
readonly dataSourceQueryKey?: (dataSourceId: string) => readonly unknown[]
|
|
45
|
+
readonly executeEndpoint: PresentationActionEndpointExecutor
|
|
46
|
+
readonly invalidateDataSourceIds?:
|
|
47
|
+
| readonly string[]
|
|
48
|
+
| ((context: PresentationActionSuccessContext<TInput, TResult>) => readonly string[])
|
|
49
|
+
readonly module: PresentationModuleDefinition | null
|
|
50
|
+
readonly prepareRequest: (
|
|
51
|
+
context: PresentationActionRequestPreparationContext<TInput>,
|
|
52
|
+
) => PresentationActionEndpointExecutionRequest
|
|
53
|
+
readonly processResult?: (context: PresentationActionSuccessContext<TInput, TResult>) => void
|
|
54
|
+
readonly setResultQueryData?: (context: PresentationActionSuccessContext<TInput, TResult>) => void
|
|
55
|
+
readonly onSuccess?: (context: PresentationActionSuccessContext<TInput, TResult>) => void
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
export interface PresentationActionExecutor<TInput, TResult> {
|
|
59
|
+
readonly action: ActionDefinition | null
|
|
60
|
+
readonly endpointId: string | null
|
|
61
|
+
readonly error: unknown
|
|
62
|
+
readonly execute: (input: TInput) => void
|
|
63
|
+
readonly executeAsync: (input: TInput) => Promise<TResult>
|
|
64
|
+
readonly isPending: boolean
|
|
65
|
+
readonly isSuccess: boolean
|
|
66
|
+
readonly reset: () => void
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Runtime projection for endpoint-backed presentation actions. It resolves the
|
|
71
|
+
* endpoint from the action definition/target bindings, prepares an endpoint
|
|
72
|
+
* request from the caller's semantic input, executes it through the app's API
|
|
73
|
+
* adapter, and applies result/query invalidation policy.
|
|
74
|
+
*/
|
|
75
|
+
export function usePresentationActionExecutor<TInput = void, TResult = unknown>({
|
|
76
|
+
actionId,
|
|
77
|
+
componentSet = 'cohesive.presentation.react',
|
|
78
|
+
dataSourceId,
|
|
79
|
+
dataSourceQueryKey,
|
|
80
|
+
executeEndpoint,
|
|
81
|
+
invalidateDataSourceIds,
|
|
82
|
+
module,
|
|
83
|
+
onSuccess,
|
|
84
|
+
prepareRequest,
|
|
85
|
+
processResult,
|
|
86
|
+
setResultQueryData,
|
|
87
|
+
}: UsePresentationActionExecutorOptions<TInput, TResult>): PresentationActionExecutor<TInput, TResult> {
|
|
88
|
+
const queryClient = useQueryClient()
|
|
89
|
+
const action = useMemo(
|
|
90
|
+
() => findPresentationAction<ActionDefinition>(module, actionId),
|
|
91
|
+
[actionId, module],
|
|
92
|
+
)
|
|
93
|
+
const binding = useMemo(
|
|
94
|
+
() =>
|
|
95
|
+
resolvePresentationActionEndpointBinding({
|
|
96
|
+
actionId,
|
|
97
|
+
componentSet,
|
|
98
|
+
dataSourceId,
|
|
99
|
+
module,
|
|
100
|
+
}),
|
|
101
|
+
[actionId, componentSet, dataSourceId, module],
|
|
102
|
+
)
|
|
103
|
+
const endpointId = binding?.EndpointId ?? null
|
|
104
|
+
const mutation = useMutation<TResult, unknown, TInput>({
|
|
105
|
+
mutationFn: async (input) => {
|
|
106
|
+
if (!endpointId) {
|
|
107
|
+
throw new Error(`No endpoint binding is registered for action '${actionId}'.`)
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
return await executeEndpoint<TResult>(
|
|
111
|
+
endpointId,
|
|
112
|
+
prepareRequest({
|
|
113
|
+
action,
|
|
114
|
+
actionId,
|
|
115
|
+
binding,
|
|
116
|
+
endpointId,
|
|
117
|
+
input,
|
|
118
|
+
module,
|
|
119
|
+
}),
|
|
120
|
+
)
|
|
121
|
+
},
|
|
122
|
+
onSuccess: async (result, input) => {
|
|
123
|
+
if (!endpointId) {
|
|
124
|
+
return
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
const context = {
|
|
128
|
+
action,
|
|
129
|
+
actionId,
|
|
130
|
+
endpointId,
|
|
131
|
+
input,
|
|
132
|
+
queryClient,
|
|
133
|
+
result,
|
|
134
|
+
} satisfies PresentationActionSuccessContext<TInput, TResult>
|
|
135
|
+
|
|
136
|
+
setResultQueryData?.(context)
|
|
137
|
+
processResult?.(context)
|
|
138
|
+
await invalidatePresentationActionDataSources({
|
|
139
|
+
action,
|
|
140
|
+
context,
|
|
141
|
+
dataSourceQueryKey,
|
|
142
|
+
invalidateDataSourceIds,
|
|
143
|
+
queryClient,
|
|
144
|
+
})
|
|
145
|
+
onSuccess?.(context)
|
|
146
|
+
},
|
|
147
|
+
})
|
|
148
|
+
|
|
149
|
+
return {
|
|
150
|
+
action,
|
|
151
|
+
endpointId,
|
|
152
|
+
error: mutation.error,
|
|
153
|
+
execute: mutation.mutate,
|
|
154
|
+
executeAsync: mutation.mutateAsync,
|
|
155
|
+
isPending: mutation.isPending,
|
|
156
|
+
isSuccess: mutation.isSuccess,
|
|
157
|
+
reset: mutation.reset,
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
async function invalidatePresentationActionDataSources<TInput, TResult>({
|
|
162
|
+
action,
|
|
163
|
+
context,
|
|
164
|
+
dataSourceQueryKey,
|
|
165
|
+
invalidateDataSourceIds,
|
|
166
|
+
queryClient,
|
|
167
|
+
}: {
|
|
168
|
+
readonly action: ActionDefinition | null
|
|
169
|
+
readonly context: PresentationActionSuccessContext<TInput, TResult>
|
|
170
|
+
readonly dataSourceQueryKey?: (dataSourceId: string) => readonly unknown[]
|
|
171
|
+
readonly invalidateDataSourceIds?:
|
|
172
|
+
| readonly string[]
|
|
173
|
+
| ((context: PresentationActionSuccessContext<TInput, TResult>) => readonly string[])
|
|
174
|
+
readonly queryClient: QueryClient
|
|
175
|
+
}) {
|
|
176
|
+
if (!dataSourceQueryKey) {
|
|
177
|
+
return
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
const dataSourceIds =
|
|
181
|
+
typeof invalidateDataSourceIds === 'function'
|
|
182
|
+
? invalidateDataSourceIds(context)
|
|
183
|
+
: (invalidateDataSourceIds ?? action?.Result?.InvalidateDataSourceIds ?? [])
|
|
184
|
+
|
|
185
|
+
await Promise.all(
|
|
186
|
+
Array.from(new Set(dataSourceIds)).map((dataSourceId) =>
|
|
187
|
+
queryClient.invalidateQueries({ queryKey: dataSourceQueryKey(dataSourceId) }),
|
|
188
|
+
),
|
|
189
|
+
)
|
|
190
|
+
}
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
import { useQueries } from '@tanstack/react-query'
|
|
2
|
+
import { useMemo } from 'react'
|
|
3
|
+
|
|
4
|
+
import {
|
|
5
|
+
findPresentationDataSource,
|
|
6
|
+
isTanStackQueryBinding,
|
|
7
|
+
resolveDataSourceAuthorization,
|
|
8
|
+
type DataSourceDefinition,
|
|
9
|
+
type PresentationDataSourceBinding,
|
|
10
|
+
type PresentationDataSourceState,
|
|
11
|
+
type PresentationDataSourceStateMap,
|
|
12
|
+
type PresentationLocalValueDataSourceBinding,
|
|
13
|
+
type PresentationTanStackQueryDataSourceBinding,
|
|
14
|
+
} from '@cohesivesystems/presentation-core'
|
|
15
|
+
import { usePresentationModule } from './presentation-module-context'
|
|
16
|
+
|
|
17
|
+
interface PresentationAsyncDataSourceResult {
|
|
18
|
+
readonly data: unknown
|
|
19
|
+
readonly error: unknown
|
|
20
|
+
readonly isFetching: boolean
|
|
21
|
+
readonly isPending: boolean
|
|
22
|
+
readonly refetch: () => Promise<unknown>
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export function usePresentationDataSources(
|
|
26
|
+
bindings: readonly PresentationDataSourceBinding[],
|
|
27
|
+
) {
|
|
28
|
+
const module = usePresentationModule()
|
|
29
|
+
const queryBindings = useMemo(
|
|
30
|
+
() => bindings.filter(isTanStackQueryBinding),
|
|
31
|
+
[bindings],
|
|
32
|
+
)
|
|
33
|
+
const queryResults = useQueries({
|
|
34
|
+
queries: queryBindings.map((binding) => {
|
|
35
|
+
const authorization = resolveDataSourceAuthorization(binding)
|
|
36
|
+
return {
|
|
37
|
+
enabled: (binding.enabled ?? true) && !authorization.isBlocked,
|
|
38
|
+
queryFn: binding.queryFn,
|
|
39
|
+
queryKey: binding.queryKey,
|
|
40
|
+
refetchInterval: binding.refetchInterval,
|
|
41
|
+
retry: binding.retry,
|
|
42
|
+
staleTime: binding.staleTime,
|
|
43
|
+
}
|
|
44
|
+
}),
|
|
45
|
+
})
|
|
46
|
+
const dataSources = useMemo<PresentationDataSourceStateMap>(() => {
|
|
47
|
+
const definitionsById = new Map(
|
|
48
|
+
module?.DataSources.map((definition) => [definition.Id, definition] as const) ?? [],
|
|
49
|
+
)
|
|
50
|
+
const asyncResultsByDataSourceId = new Map(
|
|
51
|
+
queryBindings.map((binding, index) => [binding.dataSourceId, queryResults[index]] as const),
|
|
52
|
+
)
|
|
53
|
+
return Object.fromEntries(
|
|
54
|
+
bindings.map((binding) => {
|
|
55
|
+
const definition =
|
|
56
|
+
definitionsById.get(binding.dataSourceId) ??
|
|
57
|
+
findPresentationDataSource(module, binding.dataSourceId)
|
|
58
|
+
const state = isTanStackQueryBinding(binding)
|
|
59
|
+
? createAsyncDataSourceState(
|
|
60
|
+
binding,
|
|
61
|
+
asyncResultsByDataSourceId.get(binding.dataSourceId) as PresentationAsyncDataSourceResult,
|
|
62
|
+
definition,
|
|
63
|
+
)
|
|
64
|
+
: createLocalValueDataSourceState(binding, definition)
|
|
65
|
+
return [binding.dataSourceId, state]
|
|
66
|
+
}),
|
|
67
|
+
)
|
|
68
|
+
}, [bindings, module, queryBindings, queryResults])
|
|
69
|
+
return dataSources
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
function createAsyncDataSourceState(
|
|
73
|
+
binding: PresentationTanStackQueryDataSourceBinding,
|
|
74
|
+
result: PresentationAsyncDataSourceResult,
|
|
75
|
+
definition: DataSourceDefinition | null,
|
|
76
|
+
): PresentationDataSourceState {
|
|
77
|
+
const authorization = resolveDataSourceAuthorization(binding)
|
|
78
|
+
return {
|
|
79
|
+
blockedLabel: authorization.blockedLabel,
|
|
80
|
+
data: result.data === undefined ? binding.fallbackData : result.data,
|
|
81
|
+
definition,
|
|
82
|
+
emptyMessage: binding.emptyMessage,
|
|
83
|
+
error: result.error,
|
|
84
|
+
isBlocked: authorization.isBlocked,
|
|
85
|
+
isFetching: result.isFetching,
|
|
86
|
+
isPending: result.isPending,
|
|
87
|
+
pendingLabel: binding.pendingLabel,
|
|
88
|
+
refetch: result.refetch,
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
function createLocalValueDataSourceState(
|
|
93
|
+
binding: PresentationLocalValueDataSourceBinding,
|
|
94
|
+
definition: DataSourceDefinition | null,
|
|
95
|
+
): PresentationDataSourceState {
|
|
96
|
+
const authorization = resolveDataSourceAuthorization(binding)
|
|
97
|
+
return {
|
|
98
|
+
blockedLabel: authorization.blockedLabel,
|
|
99
|
+
data: binding.data,
|
|
100
|
+
definition,
|
|
101
|
+
emptyMessage: binding.emptyMessage,
|
|
102
|
+
error: binding.error,
|
|
103
|
+
isBlocked: authorization.isBlocked,
|
|
104
|
+
isFetching: binding.isFetching,
|
|
105
|
+
isPending: binding.isPending,
|
|
106
|
+
pendingLabel: binding.pendingLabel,
|
|
107
|
+
refetch: binding.refetch,
|
|
108
|
+
}
|
|
109
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { type ReactNode } from 'react'
|
|
2
|
+
|
|
3
|
+
import {
|
|
4
|
+
type PresentationDataSourceBinding,
|
|
5
|
+
type PresentationDataSourceStateMap,
|
|
6
|
+
} from '@cohesivesystems/presentation-core'
|
|
7
|
+
import { usePresentationDataSources } from './presentation-data-source-binding-runtime'
|
|
8
|
+
|
|
9
|
+
export interface PresentationDataSourceBinderProps {
|
|
10
|
+
readonly bindings: readonly PresentationDataSourceBinding[]
|
|
11
|
+
readonly children: (dataSources: PresentationDataSourceStateMap) => ReactNode
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Binds declared presentation data sources to runtime state for projected React
|
|
16
|
+
* components.
|
|
17
|
+
*/
|
|
18
|
+
export function PresentationDataSourceBinder({
|
|
19
|
+
bindings,
|
|
20
|
+
children,
|
|
21
|
+
}: PresentationDataSourceBinderProps) {
|
|
22
|
+
const dataSources = usePresentationDataSources(bindings)
|
|
23
|
+
return <>{children(dataSources)}</>
|
|
24
|
+
}
|