pulse-framework 0.1.43__py3-none-any.whl → 0.1.46__py3-none-any.whl
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.
- pulse/__init__.py +1 -1
- pulse/app.py +1 -1
- pulse/queries/client.py +7 -7
- pulse/queries/effect.py +16 -0
- pulse/queries/infinite_query.py +138 -29
- pulse/queries/mutation.py +1 -15
- pulse/queries/protocol.py +136 -0
- pulse/queries/query.py +610 -174
- pulse/queries/store.py +11 -14
- pulse/reactive.py +19 -1
- pulse/render_session.py +41 -25
- pulse/renderer.py +0 -43
- pulse/types/event_handler.py +3 -2
- pulse/user_session.py +7 -3
- pulse/vdom.py +100 -7
- {pulse_framework-0.1.43.dist-info → pulse_framework-0.1.46.dist-info}/METADATA +1 -1
- {pulse_framework-0.1.43.dist-info → pulse_framework-0.1.46.dist-info}/RECORD +19 -18
- {pulse_framework-0.1.43.dist-info → pulse_framework-0.1.46.dist-info}/WHEEL +0 -0
- {pulse_framework-0.1.43.dist-info → pulse_framework-0.1.46.dist-info}/entry_points.txt +0 -0
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
import datetime as dt
|
|
2
|
+
from collections.abc import Callable
|
|
3
|
+
from typing import Protocol, TypeVar, runtime_checkable
|
|
4
|
+
|
|
5
|
+
from pulse.queries.common import ActionResult, QueryStatus
|
|
6
|
+
|
|
7
|
+
T = TypeVar("T")
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
@runtime_checkable
|
|
11
|
+
class QueryResult(Protocol[T]):
|
|
12
|
+
"""
|
|
13
|
+
Unified query result interface for both keyed and unkeyed queries.
|
|
14
|
+
|
|
15
|
+
This protocol defines the public API that all query results expose,
|
|
16
|
+
regardless of whether they use keyed (cached/shared) or unkeyed
|
|
17
|
+
(dependency-tracked) execution strategies.
|
|
18
|
+
|
|
19
|
+
Keyed queries use a session-wide cache and explicit key functions to
|
|
20
|
+
determine when to refetch. Unkeyed queries automatically track reactive
|
|
21
|
+
dependencies and refetch when those dependencies change.
|
|
22
|
+
"""
|
|
23
|
+
|
|
24
|
+
# Status properties
|
|
25
|
+
@property
|
|
26
|
+
def status(self) -> QueryStatus:
|
|
27
|
+
"""Current query status: 'loading', 'success', or 'error'."""
|
|
28
|
+
...
|
|
29
|
+
|
|
30
|
+
@property
|
|
31
|
+
def is_loading(self) -> bool:
|
|
32
|
+
"""True if the query has not yet completed its initial fetch."""
|
|
33
|
+
...
|
|
34
|
+
|
|
35
|
+
@property
|
|
36
|
+
def is_success(self) -> bool:
|
|
37
|
+
"""True if the query completed successfully."""
|
|
38
|
+
...
|
|
39
|
+
|
|
40
|
+
@property
|
|
41
|
+
def is_error(self) -> bool:
|
|
42
|
+
"""True if the query completed with an error."""
|
|
43
|
+
...
|
|
44
|
+
|
|
45
|
+
@property
|
|
46
|
+
def is_fetching(self) -> bool:
|
|
47
|
+
"""True if a fetch is currently in progress (including refetches)."""
|
|
48
|
+
...
|
|
49
|
+
|
|
50
|
+
@property
|
|
51
|
+
def is_scheduled(self) -> bool:
|
|
52
|
+
"""True if a fetch is scheduled or currently running."""
|
|
53
|
+
...
|
|
54
|
+
|
|
55
|
+
# Data properties
|
|
56
|
+
@property
|
|
57
|
+
def data(self) -> T | None:
|
|
58
|
+
"""The query result data, or None if not yet available."""
|
|
59
|
+
...
|
|
60
|
+
|
|
61
|
+
@property
|
|
62
|
+
def error(self) -> Exception | None:
|
|
63
|
+
"""The error from the last fetch, or None if no error."""
|
|
64
|
+
...
|
|
65
|
+
|
|
66
|
+
# Query operations
|
|
67
|
+
def is_stale(self) -> bool:
|
|
68
|
+
"""Check if the query data is stale based on stale_time."""
|
|
69
|
+
...
|
|
70
|
+
|
|
71
|
+
async def refetch(self, cancel_refetch: bool = True) -> ActionResult[T]:
|
|
72
|
+
"""
|
|
73
|
+
Refetch the query data.
|
|
74
|
+
|
|
75
|
+
Args:
|
|
76
|
+
cancel_refetch: If True (default), cancels any in-flight request
|
|
77
|
+
before starting a new one. If False, deduplicates requests.
|
|
78
|
+
|
|
79
|
+
Returns:
|
|
80
|
+
ActionResult containing either the data or an error.
|
|
81
|
+
"""
|
|
82
|
+
...
|
|
83
|
+
|
|
84
|
+
async def wait(self) -> ActionResult[T]:
|
|
85
|
+
"""
|
|
86
|
+
Wait for the current fetch to complete.
|
|
87
|
+
|
|
88
|
+
Returns:
|
|
89
|
+
ActionResult containing either the data or an error.
|
|
90
|
+
"""
|
|
91
|
+
...
|
|
92
|
+
|
|
93
|
+
def invalidate(self) -> None:
|
|
94
|
+
"""Mark the query as stale and trigger a refetch if observed."""
|
|
95
|
+
...
|
|
96
|
+
|
|
97
|
+
# Data manipulation
|
|
98
|
+
def set_data(self, data: T | Callable[[T | None], T]) -> None:
|
|
99
|
+
"""
|
|
100
|
+
Optimistically set data without changing loading/error state.
|
|
101
|
+
|
|
102
|
+
Args:
|
|
103
|
+
data: The new data value, or a function that receives the current
|
|
104
|
+
data and returns the new data.
|
|
105
|
+
"""
|
|
106
|
+
...
|
|
107
|
+
|
|
108
|
+
def set_initial_data(
|
|
109
|
+
self,
|
|
110
|
+
data: T | Callable[[], T],
|
|
111
|
+
*,
|
|
112
|
+
updated_at: float | dt.datetime | None = None,
|
|
113
|
+
) -> None:
|
|
114
|
+
"""
|
|
115
|
+
Set data as if it were provided as initial_data.
|
|
116
|
+
|
|
117
|
+
Only takes effect if the query is still in 'loading' state.
|
|
118
|
+
|
|
119
|
+
Args:
|
|
120
|
+
data: The initial data value, or a function that returns it.
|
|
121
|
+
updated_at: Optional timestamp to seed staleness calculations.
|
|
122
|
+
"""
|
|
123
|
+
...
|
|
124
|
+
|
|
125
|
+
def set_error(self, error: Exception) -> None:
|
|
126
|
+
"""Set error state on the query."""
|
|
127
|
+
...
|
|
128
|
+
|
|
129
|
+
# Enable/disable
|
|
130
|
+
def enable(self) -> None:
|
|
131
|
+
"""Enable the query, allowing it to fetch."""
|
|
132
|
+
...
|
|
133
|
+
|
|
134
|
+
def disable(self) -> None:
|
|
135
|
+
"""Disable the query, preventing it from fetching."""
|
|
136
|
+
...
|