pulse-framework 0.1.62__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 +1493 -0
- pulse/_examples.py +29 -0
- pulse/app.py +1086 -0
- pulse/channel.py +607 -0
- pulse/cli/__init__.py +0 -0
- pulse/cli/cmd.py +575 -0
- pulse/cli/dependencies.py +181 -0
- pulse/cli/folder_lock.py +134 -0
- pulse/cli/helpers.py +271 -0
- pulse/cli/logging.py +102 -0
- pulse/cli/models.py +35 -0
- pulse/cli/packages.py +262 -0
- pulse/cli/processes.py +292 -0
- pulse/cli/secrets.py +39 -0
- pulse/cli/uvicorn_log_config.py +87 -0
- pulse/code_analysis.py +38 -0
- pulse/codegen/__init__.py +0 -0
- pulse/codegen/codegen.py +359 -0
- pulse/codegen/templates/__init__.py +0 -0
- pulse/codegen/templates/layout.py +106 -0
- pulse/codegen/templates/route.py +345 -0
- pulse/codegen/templates/routes_ts.py +42 -0
- pulse/codegen/utils.py +20 -0
- pulse/component.py +237 -0
- pulse/components/__init__.py +0 -0
- pulse/components/for_.py +83 -0
- pulse/components/if_.py +86 -0
- pulse/components/react_router.py +94 -0
- pulse/context.py +108 -0
- pulse/cookies.py +322 -0
- pulse/decorators.py +344 -0
- pulse/dom/__init__.py +0 -0
- pulse/dom/elements.py +1024 -0
- pulse/dom/events.py +445 -0
- pulse/dom/props.py +1250 -0
- pulse/dom/svg.py +0 -0
- pulse/dom/tags.py +328 -0
- pulse/dom/tags.pyi +480 -0
- pulse/env.py +178 -0
- pulse/form.py +538 -0
- pulse/helpers.py +541 -0
- pulse/hooks/__init__.py +0 -0
- pulse/hooks/core.py +452 -0
- pulse/hooks/effects.py +88 -0
- pulse/hooks/init.py +668 -0
- pulse/hooks/runtime.py +464 -0
- pulse/hooks/setup.py +254 -0
- pulse/hooks/stable.py +138 -0
- pulse/hooks/state.py +192 -0
- pulse/js/__init__.py +125 -0
- pulse/js/__init__.pyi +115 -0
- pulse/js/_types.py +299 -0
- pulse/js/array.py +339 -0
- pulse/js/console.py +50 -0
- pulse/js/date.py +119 -0
- pulse/js/document.py +145 -0
- pulse/js/error.py +140 -0
- pulse/js/json.py +66 -0
- pulse/js/map.py +97 -0
- pulse/js/math.py +69 -0
- pulse/js/navigator.py +79 -0
- pulse/js/number.py +57 -0
- pulse/js/obj.py +81 -0
- pulse/js/object.py +172 -0
- pulse/js/promise.py +172 -0
- pulse/js/pulse.py +115 -0
- pulse/js/react.py +495 -0
- pulse/js/regexp.py +57 -0
- pulse/js/set.py +124 -0
- pulse/js/string.py +38 -0
- pulse/js/weakmap.py +53 -0
- pulse/js/weakset.py +48 -0
- pulse/js/window.py +205 -0
- pulse/messages.py +202 -0
- pulse/middleware.py +471 -0
- pulse/plugin.py +96 -0
- pulse/proxy.py +242 -0
- pulse/py.typed +0 -0
- pulse/queries/__init__.py +0 -0
- pulse/queries/client.py +609 -0
- pulse/queries/common.py +101 -0
- pulse/queries/effect.py +55 -0
- pulse/queries/infinite_query.py +1418 -0
- pulse/queries/mutation.py +295 -0
- pulse/queries/protocol.py +136 -0
- pulse/queries/query.py +1314 -0
- pulse/queries/store.py +120 -0
- pulse/react_component.py +88 -0
- pulse/reactive.py +1208 -0
- pulse/reactive_extensions.py +1172 -0
- pulse/render_session.py +768 -0
- pulse/renderer.py +584 -0
- pulse/request.py +205 -0
- pulse/routing.py +598 -0
- pulse/serializer.py +279 -0
- pulse/state.py +556 -0
- pulse/test_helpers.py +15 -0
- pulse/transpiler/__init__.py +111 -0
- pulse/transpiler/assets.py +81 -0
- pulse/transpiler/builtins.py +1029 -0
- pulse/transpiler/dynamic_import.py +130 -0
- pulse/transpiler/emit_context.py +49 -0
- pulse/transpiler/errors.py +96 -0
- pulse/transpiler/function.py +611 -0
- pulse/transpiler/id.py +18 -0
- pulse/transpiler/imports.py +341 -0
- pulse/transpiler/js_module.py +336 -0
- pulse/transpiler/modules/__init__.py +33 -0
- pulse/transpiler/modules/asyncio.py +57 -0
- pulse/transpiler/modules/json.py +24 -0
- pulse/transpiler/modules/math.py +265 -0
- pulse/transpiler/modules/pulse/__init__.py +5 -0
- pulse/transpiler/modules/pulse/tags.py +250 -0
- pulse/transpiler/modules/typing.py +63 -0
- pulse/transpiler/nodes.py +1987 -0
- pulse/transpiler/py_module.py +135 -0
- pulse/transpiler/transpiler.py +1100 -0
- pulse/transpiler/vdom.py +256 -0
- pulse/types/__init__.py +0 -0
- pulse/types/event_handler.py +50 -0
- pulse/user_session.py +386 -0
- pulse/version.py +69 -0
- pulse_framework-0.1.62.dist-info/METADATA +198 -0
- pulse_framework-0.1.62.dist-info/RECORD +126 -0
- pulse_framework-0.1.62.dist-info/WHEEL +4 -0
- pulse_framework-0.1.62.dist-info/entry_points.txt +3 -0
pulse/js/date.py
ADDED
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
"""
|
|
2
|
+
JavaScript Date builtin module.
|
|
3
|
+
|
|
4
|
+
Usage:
|
|
5
|
+
|
|
6
|
+
```python
|
|
7
|
+
from pulse.js import Date
|
|
8
|
+
Date() # -> new Date()
|
|
9
|
+
Date.now() # -> Date.now()
|
|
10
|
+
Date.parse("2023-01-01") # -> Date.parse("2023-01-01")
|
|
11
|
+
|
|
12
|
+
# Or import from module directly:
|
|
13
|
+
from pulse.js.date import Date
|
|
14
|
+
```
|
|
15
|
+
"""
|
|
16
|
+
|
|
17
|
+
from typing import Any as _Any
|
|
18
|
+
|
|
19
|
+
from pulse.transpiler.js_module import JsModule
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
class Date:
|
|
23
|
+
"""Class for JavaScript Date instances."""
|
|
24
|
+
|
|
25
|
+
def __init__(self, value: int | str | None = None, /): ...
|
|
26
|
+
|
|
27
|
+
@staticmethod
|
|
28
|
+
def now() -> float: ...
|
|
29
|
+
|
|
30
|
+
@staticmethod
|
|
31
|
+
def parse(dateString: str) -> float: ...
|
|
32
|
+
|
|
33
|
+
@staticmethod
|
|
34
|
+
def UTC(
|
|
35
|
+
year: int,
|
|
36
|
+
month: int,
|
|
37
|
+
date: int | None = None,
|
|
38
|
+
hours: int | None = None,
|
|
39
|
+
minutes: int | None = None,
|
|
40
|
+
seconds: int | None = None,
|
|
41
|
+
ms: int | None = None,
|
|
42
|
+
/,
|
|
43
|
+
) -> float: ...
|
|
44
|
+
|
|
45
|
+
def getDate(self) -> int: ...
|
|
46
|
+
def getDay(self) -> int: ...
|
|
47
|
+
def getFullYear(self) -> int: ...
|
|
48
|
+
def getHours(self) -> int: ...
|
|
49
|
+
def getMilliseconds(self) -> int: ...
|
|
50
|
+
def getMinutes(self) -> int: ...
|
|
51
|
+
def getMonth(self) -> int: ...
|
|
52
|
+
def getSeconds(self) -> int: ...
|
|
53
|
+
def getTime(self) -> float: ...
|
|
54
|
+
def getTimezoneOffset(self) -> int: ...
|
|
55
|
+
def getUTCDate(self) -> int: ...
|
|
56
|
+
def getUTCDay(self) -> int: ...
|
|
57
|
+
def getUTCFullYear(self) -> int: ...
|
|
58
|
+
def getUTCHours(self) -> int: ...
|
|
59
|
+
def getUTCMilliseconds(self) -> int: ...
|
|
60
|
+
def getUTCMinutes(self) -> int: ...
|
|
61
|
+
def getUTCMonth(self) -> int: ...
|
|
62
|
+
def getUTCSeconds(self) -> int: ...
|
|
63
|
+
def setDate(self, date: int) -> float: ...
|
|
64
|
+
def setFullYear(
|
|
65
|
+
self, year: int, month: int | None = None, date: int | None = None, /
|
|
66
|
+
) -> float: ...
|
|
67
|
+
def setHours(
|
|
68
|
+
self,
|
|
69
|
+
hours: int,
|
|
70
|
+
min: int | None = None,
|
|
71
|
+
sec: int | None = None,
|
|
72
|
+
ms: int | None = None,
|
|
73
|
+
/,
|
|
74
|
+
) -> float: ...
|
|
75
|
+
def setMilliseconds(self, ms: int) -> float: ...
|
|
76
|
+
def setMinutes(
|
|
77
|
+
self, min: int, sec: int | None = None, ms: int | None = None, /
|
|
78
|
+
) -> float: ...
|
|
79
|
+
def setMonth(self, month: int, date: int | None = None, /) -> float: ...
|
|
80
|
+
def setSeconds(self, sec: int, ms: int | None = None, /) -> float: ...
|
|
81
|
+
def setTime(self, time: float) -> float: ...
|
|
82
|
+
def setUTCDate(self, date: int) -> float: ...
|
|
83
|
+
def setUTCFullYear(
|
|
84
|
+
self, year: int, month: int | None = None, date: int | None = None
|
|
85
|
+
) -> float: ...
|
|
86
|
+
def setUTCHours(
|
|
87
|
+
self,
|
|
88
|
+
hours: int,
|
|
89
|
+
min: int | None = None,
|
|
90
|
+
sec: int | None = None,
|
|
91
|
+
ms: int | None = None,
|
|
92
|
+
/,
|
|
93
|
+
) -> float: ...
|
|
94
|
+
def setUTCMilliseconds(self, ms: int) -> float: ...
|
|
95
|
+
def setUTCMinutes(
|
|
96
|
+
self, min: int, sec: int | None = None, ms: int | None = None, /
|
|
97
|
+
) -> float: ...
|
|
98
|
+
def setUTCMonth(self, month: int, date: int | None = None, /) -> float: ...
|
|
99
|
+
def setUTCSeconds(self, sec: int, ms: int | None = None, /) -> float: ...
|
|
100
|
+
def toDateString(self) -> str: ...
|
|
101
|
+
def toISOString(self) -> str: ...
|
|
102
|
+
def toJSON(self, key: _Any | None = None, /) -> str: ...
|
|
103
|
+
def toLocaleDateString(
|
|
104
|
+
self, locales: str | None = None, options: _Any | None = None, /
|
|
105
|
+
) -> str: ...
|
|
106
|
+
def toLocaleString(
|
|
107
|
+
self, locales: str | None = None, options: _Any | None = None, /
|
|
108
|
+
) -> str: ...
|
|
109
|
+
def toLocaleTimeString(
|
|
110
|
+
self, locales: str | None = None, options: _Any | None = None, /
|
|
111
|
+
) -> str: ...
|
|
112
|
+
def toString(self) -> str: ...
|
|
113
|
+
def toTimeString(self) -> str: ...
|
|
114
|
+
def toUTCString(self) -> str: ...
|
|
115
|
+
def valueOf(self) -> float: ...
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
# Self-register this module as a JS builtin (global identifier)
|
|
119
|
+
JsModule.register(name=None)
|
pulse/js/document.py
ADDED
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
"""Browser document global object.
|
|
2
|
+
|
|
3
|
+
Usage:
|
|
4
|
+
|
|
5
|
+
```python
|
|
6
|
+
from pulse.js import document
|
|
7
|
+
document.querySelector("#app") # -> document.querySelector("#app")
|
|
8
|
+
```
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
from collections.abc import Callable as _Callable
|
|
12
|
+
from typing import Any as _Any
|
|
13
|
+
|
|
14
|
+
from pulse.js._types import Element as _Element
|
|
15
|
+
from pulse.js._types import HTMLCollection as _HTMLCollection
|
|
16
|
+
from pulse.js._types import HTMLElement as _HTMLElement
|
|
17
|
+
from pulse.js._types import NodeList as _NodeList
|
|
18
|
+
from pulse.transpiler.js_module import JsModule
|
|
19
|
+
|
|
20
|
+
# Read-only properties
|
|
21
|
+
body: _HTMLElement
|
|
22
|
+
head: _HTMLElement
|
|
23
|
+
documentElement: _HTMLElement
|
|
24
|
+
activeElement: _Element | None
|
|
25
|
+
title: str
|
|
26
|
+
readyState: str # "loading" | "interactive" | "complete"
|
|
27
|
+
cookie: str
|
|
28
|
+
referrer: str
|
|
29
|
+
URL: str
|
|
30
|
+
domain: str
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
# Query methods
|
|
34
|
+
def querySelector(selectors: str) -> _Element | None:
|
|
35
|
+
"""Return the first element matching the selector, or None."""
|
|
36
|
+
...
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
def querySelectorAll(selectors: str) -> _NodeList[_Element]:
|
|
40
|
+
"""Return all elements matching the selector."""
|
|
41
|
+
...
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
def getElementById(elementId: str) -> _Element | None:
|
|
45
|
+
"""Return the element with the given ID, or None."""
|
|
46
|
+
...
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
def getElementsByClassName(classNames: str) -> _HTMLCollection[_Element]:
|
|
50
|
+
"""Return all elements with the given class name(s)."""
|
|
51
|
+
...
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
def getElementsByTagName(qualifiedName: str) -> _HTMLCollection[_Element]:
|
|
55
|
+
"""Return all elements with the given tag name."""
|
|
56
|
+
...
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
def getElementsByName(elementName: str) -> _NodeList[_Element]:
|
|
60
|
+
"""Return all elements with the given name attribute."""
|
|
61
|
+
...
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
# Element creation
|
|
65
|
+
def createElement(
|
|
66
|
+
tagName: str, options: dict[str, str] | None = None, /
|
|
67
|
+
) -> _HTMLElement:
|
|
68
|
+
"""Create a new element with the given tag name."""
|
|
69
|
+
...
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
def createTextNode(data: str) -> _Any:
|
|
73
|
+
"""Create a new text node."""
|
|
74
|
+
...
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
def createDocumentFragment() -> _Any:
|
|
78
|
+
"""Create a new document fragment."""
|
|
79
|
+
...
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
def createComment(data: str) -> _Any:
|
|
83
|
+
"""Create a new comment node."""
|
|
84
|
+
...
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
# Event methods
|
|
88
|
+
def addEventListener(
|
|
89
|
+
type: str,
|
|
90
|
+
listener: _Callable[..., None],
|
|
91
|
+
options: bool | dict[str, bool] | None = None,
|
|
92
|
+
/,
|
|
93
|
+
) -> None:
|
|
94
|
+
"""Add an event listener to the document."""
|
|
95
|
+
...
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
def removeEventListener(
|
|
99
|
+
type: str,
|
|
100
|
+
listener: _Callable[..., None],
|
|
101
|
+
options: bool | dict[str, bool] | None = None,
|
|
102
|
+
/,
|
|
103
|
+
) -> None:
|
|
104
|
+
"""Remove an event listener from the document."""
|
|
105
|
+
...
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
def dispatchEvent(event: _Any) -> bool:
|
|
109
|
+
"""Dispatch an event to the document."""
|
|
110
|
+
...
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
# Focus methods
|
|
114
|
+
def hasFocus() -> bool:
|
|
115
|
+
"""Return True if the document has focus."""
|
|
116
|
+
...
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
# Selection
|
|
120
|
+
def getSelection() -> _Any:
|
|
121
|
+
"""Return the current selection."""
|
|
122
|
+
...
|
|
123
|
+
|
|
124
|
+
|
|
125
|
+
# Node tree methods
|
|
126
|
+
def importNode(node: _Element, deep: bool = False, /) -> _Element:
|
|
127
|
+
"""Import a node from another document."""
|
|
128
|
+
...
|
|
129
|
+
|
|
130
|
+
|
|
131
|
+
def adoptNode(node: _Element) -> _Element:
|
|
132
|
+
"""Adopt a node from another document."""
|
|
133
|
+
...
|
|
134
|
+
|
|
135
|
+
|
|
136
|
+
# Full-screen API
|
|
137
|
+
def exitFullscreen() -> _Any:
|
|
138
|
+
"""Exit full-screen mode. Returns a Promise."""
|
|
139
|
+
...
|
|
140
|
+
|
|
141
|
+
|
|
142
|
+
fullscreenElement: _Element | None
|
|
143
|
+
|
|
144
|
+
|
|
145
|
+
JsModule.register(name="document")
|
pulse/js/error.py
ADDED
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
"""
|
|
2
|
+
JavaScript Error builtin module.
|
|
3
|
+
|
|
4
|
+
Usage:
|
|
5
|
+
|
|
6
|
+
```python
|
|
7
|
+
from pulse.js import Error
|
|
8
|
+
Error("message") # -> new Error("message")
|
|
9
|
+
|
|
10
|
+
from pulse.js.error import TypeError, RangeError, ReferenceError
|
|
11
|
+
TypeError("message") # -> new TypeError("message")
|
|
12
|
+
```
|
|
13
|
+
"""
|
|
14
|
+
|
|
15
|
+
from pulse.transpiler.js_module import JsModule
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
class Error:
|
|
19
|
+
"""Class for JavaScript Error instances."""
|
|
20
|
+
|
|
21
|
+
def __init__(self, message: str | None = None, /): ...
|
|
22
|
+
|
|
23
|
+
@property
|
|
24
|
+
def message(self) -> str: ...
|
|
25
|
+
|
|
26
|
+
@property
|
|
27
|
+
def name(self) -> str: ...
|
|
28
|
+
|
|
29
|
+
@property
|
|
30
|
+
def stack(self) -> str | None: ...
|
|
31
|
+
|
|
32
|
+
def toString(self) -> str: ...
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
# Error Subclasses - these are separate globals in JS, not members of Error
|
|
36
|
+
# TODO: These need a different architecture (separate modules or standalone identifiers)
|
|
37
|
+
class EvalError:
|
|
38
|
+
"""Class for JavaScript EvalError instances."""
|
|
39
|
+
|
|
40
|
+
def __init__(self, message: str | None = None, /): ...
|
|
41
|
+
|
|
42
|
+
@property
|
|
43
|
+
def message(self) -> str: ...
|
|
44
|
+
|
|
45
|
+
@property
|
|
46
|
+
def name(self) -> str: ...
|
|
47
|
+
|
|
48
|
+
@property
|
|
49
|
+
def stack(self) -> str | None: ...
|
|
50
|
+
|
|
51
|
+
def toString(self) -> str: ...
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
class RangeError:
|
|
55
|
+
"""Class for JavaScript RangeError instances."""
|
|
56
|
+
|
|
57
|
+
def __init__(self, message: str | None = None, /): ...
|
|
58
|
+
|
|
59
|
+
@property
|
|
60
|
+
def message(self) -> str: ...
|
|
61
|
+
|
|
62
|
+
@property
|
|
63
|
+
def name(self) -> str: ...
|
|
64
|
+
|
|
65
|
+
@property
|
|
66
|
+
def stack(self) -> str | None: ...
|
|
67
|
+
|
|
68
|
+
def toString(self) -> str: ...
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
class ReferenceError:
|
|
72
|
+
"""Class for JavaScript ReferenceError instances."""
|
|
73
|
+
|
|
74
|
+
def __init__(self, message: str | None = None, /): ...
|
|
75
|
+
|
|
76
|
+
@property
|
|
77
|
+
def message(self) -> str: ...
|
|
78
|
+
|
|
79
|
+
@property
|
|
80
|
+
def name(self) -> str: ...
|
|
81
|
+
|
|
82
|
+
@property
|
|
83
|
+
def stack(self) -> str | None: ...
|
|
84
|
+
|
|
85
|
+
def toString(self) -> str: ...
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
class SyntaxError:
|
|
89
|
+
"""Class for JavaScript SyntaxError instances."""
|
|
90
|
+
|
|
91
|
+
def __init__(self, message: str | None = None, /): ...
|
|
92
|
+
|
|
93
|
+
@property
|
|
94
|
+
def message(self) -> str: ...
|
|
95
|
+
|
|
96
|
+
@property
|
|
97
|
+
def name(self) -> str: ...
|
|
98
|
+
|
|
99
|
+
@property
|
|
100
|
+
def stack(self) -> str | None: ...
|
|
101
|
+
|
|
102
|
+
def toString(self) -> str: ...
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
class TypeError:
|
|
106
|
+
"""Class for JavaScript TypeError instances."""
|
|
107
|
+
|
|
108
|
+
def __init__(self, message: str | None = None, /): ...
|
|
109
|
+
|
|
110
|
+
@property
|
|
111
|
+
def message(self) -> str: ...
|
|
112
|
+
|
|
113
|
+
@property
|
|
114
|
+
def name(self) -> str: ...
|
|
115
|
+
|
|
116
|
+
@property
|
|
117
|
+
def stack(self) -> str | None: ...
|
|
118
|
+
|
|
119
|
+
def toString(self) -> str: ...
|
|
120
|
+
|
|
121
|
+
|
|
122
|
+
class URIError:
|
|
123
|
+
"""Class for JavaScript URIError instances."""
|
|
124
|
+
|
|
125
|
+
def __init__(self, message: str | None = None, /): ...
|
|
126
|
+
|
|
127
|
+
@property
|
|
128
|
+
def message(self) -> str: ...
|
|
129
|
+
|
|
130
|
+
@property
|
|
131
|
+
def name(self) -> str: ...
|
|
132
|
+
|
|
133
|
+
@property
|
|
134
|
+
def stack(self) -> str | None: ...
|
|
135
|
+
|
|
136
|
+
def toString(self) -> str: ...
|
|
137
|
+
|
|
138
|
+
|
|
139
|
+
# Self-register this module as a JS builtin (global identifiers)
|
|
140
|
+
JsModule.register(name=None)
|
pulse/js/json.py
ADDED
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
"""
|
|
2
|
+
JavaScript JSON builtin module.
|
|
3
|
+
|
|
4
|
+
Usage:
|
|
5
|
+
|
|
6
|
+
```python
|
|
7
|
+
import pulse.js.json as JSON
|
|
8
|
+
JSON.stringify({"a": 1}) # -> JSON.stringify({"a": 1})
|
|
9
|
+
JSON.parse('{"a": 1}') # -> JSON.parse('{"a": 1}')
|
|
10
|
+
|
|
11
|
+
from pulse.js.json import stringify, parse
|
|
12
|
+
stringify({"a": 1}) # -> JSON.stringify({"a": 1})
|
|
13
|
+
parse('{"a": 1}') # -> JSON.parse('{"a": 1}')
|
|
14
|
+
```
|
|
15
|
+
"""
|
|
16
|
+
|
|
17
|
+
from collections.abc import Callable as _Callable
|
|
18
|
+
from collections.abc import Sequence as _Sequence
|
|
19
|
+
from typing import TypeVar as _TypeVar
|
|
20
|
+
|
|
21
|
+
from pulse.transpiler.js_module import JsModule
|
|
22
|
+
|
|
23
|
+
# JSON types
|
|
24
|
+
JSONValue = None | bool | int | float | str | list["JSONValue"] | dict[str, "JSONValue"]
|
|
25
|
+
JSONReplacer = _Sequence[str | int] | _Callable[[str, JSONValue], JSONValue]
|
|
26
|
+
JSONReviver = _Callable[[str, JSONValue], JSONValue]
|
|
27
|
+
|
|
28
|
+
T = _TypeVar("T")
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
def parse(text: str, reviver: JSONReviver | None = None, /) -> JSONValue:
|
|
32
|
+
"""Parse a JSON string into a JavaScript value.
|
|
33
|
+
|
|
34
|
+
Args:
|
|
35
|
+
text: The JSON string to parse.
|
|
36
|
+
reviver: Optional function (key: str, value: Any) -> Any that transforms the parsed value.
|
|
37
|
+
Called for each key-value pair. Return the value to use, or undefined to omit.
|
|
38
|
+
|
|
39
|
+
Returns:
|
|
40
|
+
The parsed JavaScript value (null, bool, number, string, array, or object).
|
|
41
|
+
"""
|
|
42
|
+
...
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
def stringify(
|
|
46
|
+
value: JSONValue,
|
|
47
|
+
replacer: JSONReplacer | None = None,
|
|
48
|
+
space: int | str | None = None,
|
|
49
|
+
/,
|
|
50
|
+
) -> str:
|
|
51
|
+
"""Convert a JavaScript value to a JSON string.
|
|
52
|
+
|
|
53
|
+
Args:
|
|
54
|
+
value: The value to convert to JSON.
|
|
55
|
+
replacer: Optional array of property names/indices, or function (key: str, value: Any) -> Any
|
|
56
|
+
that controls which properties are included. Return undefined to omit.
|
|
57
|
+
space: Optional indentation. Number for spaces per level, or string (up to 10 chars).
|
|
58
|
+
|
|
59
|
+
Returns:
|
|
60
|
+
The JSON string representation of the value.
|
|
61
|
+
"""
|
|
62
|
+
...
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
# Self-register this module as a JS builtin
|
|
66
|
+
JsModule.register(name="JSON")
|
pulse/js/map.py
ADDED
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
"""
|
|
2
|
+
JavaScript Map builtin module.
|
|
3
|
+
|
|
4
|
+
Usage:
|
|
5
|
+
|
|
6
|
+
```python
|
|
7
|
+
from pulse.js import Map
|
|
8
|
+
Map() # -> new Map()
|
|
9
|
+
Map([["a", 1]]) # -> new Map([["a", 1]])
|
|
10
|
+
|
|
11
|
+
# Or import from module directly:
|
|
12
|
+
from pulse.js.map import Map
|
|
13
|
+
```
|
|
14
|
+
"""
|
|
15
|
+
|
|
16
|
+
from collections.abc import Callable as _Callable
|
|
17
|
+
from collections.abc import Iterable as _Iterable
|
|
18
|
+
from collections.abc import Iterator as _Iterator
|
|
19
|
+
from typing import Any as _Any
|
|
20
|
+
from typing import Generic as _Generic
|
|
21
|
+
from typing import TypeVar as _TypeVar
|
|
22
|
+
|
|
23
|
+
from pulse.transpiler.js_module import JsModule
|
|
24
|
+
|
|
25
|
+
K = _TypeVar("K")
|
|
26
|
+
V = _TypeVar("V")
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
class Map(_Generic[K, V]):
|
|
30
|
+
"""JavaScript Map - a collection of keyed data items.
|
|
31
|
+
|
|
32
|
+
Map[K, V] preserves insertion order and allows keys of any type.
|
|
33
|
+
"""
|
|
34
|
+
|
|
35
|
+
def __init__(self, iterable: _Iterable[tuple[K, V]] | None = None, /) -> None: ...
|
|
36
|
+
|
|
37
|
+
@property
|
|
38
|
+
def size(self) -> int:
|
|
39
|
+
"""The number of key/value pairs in the Map."""
|
|
40
|
+
...
|
|
41
|
+
|
|
42
|
+
def clear(self) -> None:
|
|
43
|
+
"""Remove all key/value pairs."""
|
|
44
|
+
...
|
|
45
|
+
|
|
46
|
+
def delete(self, key: K) -> bool:
|
|
47
|
+
"""Remove a key and its value. Returns True if the key existed."""
|
|
48
|
+
...
|
|
49
|
+
|
|
50
|
+
def get(self, key: K) -> V | None:
|
|
51
|
+
"""Return the value for a key, or None if not present."""
|
|
52
|
+
...
|
|
53
|
+
|
|
54
|
+
def has(self, key: K) -> bool:
|
|
55
|
+
"""Return True if the key exists in the Map."""
|
|
56
|
+
...
|
|
57
|
+
|
|
58
|
+
def set(self, key: K, value: V) -> "Map[K, V]":
|
|
59
|
+
"""Set a key/value pair. Returns the Map for chaining."""
|
|
60
|
+
...
|
|
61
|
+
|
|
62
|
+
def forEach(
|
|
63
|
+
self,
|
|
64
|
+
callback: _Callable[[V, K, "Map[K, V]"], None],
|
|
65
|
+
thisArg: _Any | None = None,
|
|
66
|
+
/,
|
|
67
|
+
) -> None:
|
|
68
|
+
"""Execute a function for each key/value pair."""
|
|
69
|
+
...
|
|
70
|
+
|
|
71
|
+
def keys(self) -> _Iterable[K]:
|
|
72
|
+
"""Return an iterator of keys."""
|
|
73
|
+
...
|
|
74
|
+
|
|
75
|
+
def values(self) -> _Iterable[V]:
|
|
76
|
+
"""Return an iterator of values."""
|
|
77
|
+
...
|
|
78
|
+
|
|
79
|
+
def entries(self) -> _Iterable[tuple[K, V]]:
|
|
80
|
+
"""Return an iterator of [key, value] pairs."""
|
|
81
|
+
...
|
|
82
|
+
|
|
83
|
+
def __iter__(self) -> _Iterator[tuple[K, V]]:
|
|
84
|
+
"""Iterate over [key, value] pairs."""
|
|
85
|
+
...
|
|
86
|
+
|
|
87
|
+
def __len__(self) -> int:
|
|
88
|
+
"""Return the number of key/value pairs (same as size)."""
|
|
89
|
+
...
|
|
90
|
+
|
|
91
|
+
def __contains__(self, key: K) -> bool:
|
|
92
|
+
"""Check if key exists in the Map (same as has)."""
|
|
93
|
+
...
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
# Self-register this module as a JS builtin (global identifiers)
|
|
97
|
+
JsModule.register(name=None)
|
pulse/js/math.py
ADDED
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
"""
|
|
2
|
+
JavaScript Math builtin module.
|
|
3
|
+
|
|
4
|
+
Usage:
|
|
5
|
+
|
|
6
|
+
```python
|
|
7
|
+
import pulse.js.math as Math
|
|
8
|
+
Math.PI # -> Math.PI
|
|
9
|
+
Math.floor(3.7) # -> Math.floor(3.7)
|
|
10
|
+
|
|
11
|
+
from pulse.js.math import PI, floor
|
|
12
|
+
PI # -> Math.PI
|
|
13
|
+
floor(3.7) # -> Math.floor(3.7)
|
|
14
|
+
```
|
|
15
|
+
"""
|
|
16
|
+
|
|
17
|
+
from pulse.transpiler.js_module import JsModule
|
|
18
|
+
|
|
19
|
+
# Constants (type stubs for IDE support)
|
|
20
|
+
PI: float
|
|
21
|
+
E: float
|
|
22
|
+
LN2: float
|
|
23
|
+
LN10: float
|
|
24
|
+
LOG2E: float
|
|
25
|
+
LOG10E: float
|
|
26
|
+
SQRT1_2: float
|
|
27
|
+
SQRT2: float
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
# Methods (type stubs for IDE support)
|
|
31
|
+
def abs(x: float) -> float: ...
|
|
32
|
+
def acos(x: float) -> float: ...
|
|
33
|
+
def acosh(x: float) -> float: ...
|
|
34
|
+
def asin(x: float) -> float: ...
|
|
35
|
+
def asinh(x: float) -> float: ...
|
|
36
|
+
def atan(x: float) -> float: ...
|
|
37
|
+
def atan2(y: float, x: float) -> float: ...
|
|
38
|
+
def atanh(x: float) -> float: ...
|
|
39
|
+
def cbrt(x: float) -> float: ...
|
|
40
|
+
def ceil(x: float) -> int: ...
|
|
41
|
+
def clz32(x: int) -> int: ...
|
|
42
|
+
def cos(x: float) -> float: ...
|
|
43
|
+
def cosh(x: float) -> float: ...
|
|
44
|
+
def exp(x: float) -> float: ...
|
|
45
|
+
def expm1(x: float) -> float: ...
|
|
46
|
+
def floor(x: float) -> int: ...
|
|
47
|
+
def fround(x: float) -> float: ...
|
|
48
|
+
def hypot(*values: float) -> float: ...
|
|
49
|
+
def imul(x: int, y: int) -> int: ...
|
|
50
|
+
def log(x: float) -> float: ...
|
|
51
|
+
def log10(x: float) -> float: ...
|
|
52
|
+
def log1p(x: float) -> float: ...
|
|
53
|
+
def log2(x: float) -> float: ...
|
|
54
|
+
def max(*values: float) -> float: ...
|
|
55
|
+
def min(*values: float) -> float: ...
|
|
56
|
+
def pow(x: float, y: float) -> float: ...
|
|
57
|
+
def random() -> float: ...
|
|
58
|
+
def round(x: float) -> int: ...
|
|
59
|
+
def sign(x: float) -> int: ...
|
|
60
|
+
def sin(x: float) -> float: ...
|
|
61
|
+
def sinh(x: float) -> float: ...
|
|
62
|
+
def sqrt(x: float) -> float: ...
|
|
63
|
+
def tan(x: float) -> float: ...
|
|
64
|
+
def tanh(x: float) -> float: ...
|
|
65
|
+
def trunc(x: float) -> int: ...
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
# Self-register this module as a JS builtin
|
|
69
|
+
JsModule.register(name="Math")
|
pulse/js/navigator.py
ADDED
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
"""Browser navigator global object.
|
|
2
|
+
|
|
3
|
+
Usage:
|
|
4
|
+
|
|
5
|
+
```python
|
|
6
|
+
from pulse.js import navigator, console
|
|
7
|
+
console.log(navigator.userAgent)
|
|
8
|
+
```
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
from typing import Any as _Any
|
|
12
|
+
|
|
13
|
+
from pulse.js._types import Clipboard as _Clipboard
|
|
14
|
+
from pulse.transpiler.js_module import JsModule
|
|
15
|
+
|
|
16
|
+
# User agent and browser info
|
|
17
|
+
userAgent: str
|
|
18
|
+
language: str
|
|
19
|
+
languages: list[str]
|
|
20
|
+
platform: str
|
|
21
|
+
vendor: str
|
|
22
|
+
appName: str
|
|
23
|
+
appVersion: str
|
|
24
|
+
|
|
25
|
+
# Online status
|
|
26
|
+
onLine: bool
|
|
27
|
+
|
|
28
|
+
# Hardware info
|
|
29
|
+
hardwareConcurrency: int
|
|
30
|
+
maxTouchPoints: int
|
|
31
|
+
deviceMemory: float | None # May not be available in all browsers
|
|
32
|
+
|
|
33
|
+
# Cookies
|
|
34
|
+
cookieEnabled: bool
|
|
35
|
+
|
|
36
|
+
# PDF viewer
|
|
37
|
+
pdfViewerEnabled: bool
|
|
38
|
+
|
|
39
|
+
# Clipboard API
|
|
40
|
+
clipboard: _Clipboard
|
|
41
|
+
|
|
42
|
+
# Media devices (typed as _Any for simplicity)
|
|
43
|
+
mediaDevices: _Any
|
|
44
|
+
|
|
45
|
+
# Permissions (typed as _Any for simplicity)
|
|
46
|
+
permissions: _Any
|
|
47
|
+
|
|
48
|
+
# Service worker (typed as _Any for simplicity)
|
|
49
|
+
serviceWorker: _Any
|
|
50
|
+
|
|
51
|
+
# Geolocation (typed as _Any for simplicity)
|
|
52
|
+
geolocation: _Any
|
|
53
|
+
|
|
54
|
+
# Storage
|
|
55
|
+
storage: _Any
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
# Methods
|
|
59
|
+
def vibrate(pattern: int | list[int]) -> bool:
|
|
60
|
+
"""Vibrate the device. Returns True if vibration is supported."""
|
|
61
|
+
...
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
def share(data: dict[str, str]) -> _Any:
|
|
65
|
+
"""Share data via the Web Share API. Returns a Promise."""
|
|
66
|
+
...
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
def sendBeacon(url: str, data: str | bytes | _Any | None = None, /) -> bool:
|
|
70
|
+
"""Send data to a URL asynchronously. Returns True if successful."""
|
|
71
|
+
...
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
def canShare(data: dict[str, str] | None = None, /) -> bool:
|
|
75
|
+
"""Check if data can be shared via the Web Share API."""
|
|
76
|
+
...
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
JsModule.register(name="navigator")
|