convex-rust 0.0.0-stage → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (90) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +137 -2
  3. package/dist/cli/bin.d.ts +2 -0
  4. package/dist/cli/bin.js +200 -0
  5. package/dist/cli/build.d.ts +146 -0
  6. package/dist/cli/build.js +902 -0
  7. package/dist/cli/demangle.d.ts +7 -0
  8. package/dist/cli/demangle.js +328 -0
  9. package/dist/cli/diagnostics.d.ts +34 -0
  10. package/dist/cli/diagnostics.js +296 -0
  11. package/dist/cli/generate.d.ts +29 -0
  12. package/dist/cli/generate.js +82 -0
  13. package/dist/cli/manifest.d.ts +24 -0
  14. package/dist/cli/manifest.js +75 -0
  15. package/dist/cli/rustApi.d.ts +78 -0
  16. package/dist/cli/rustApi.js +609 -0
  17. package/dist/cli/scaffold.d.ts +22 -0
  18. package/dist/cli/scaffold.js +114 -0
  19. package/dist/cli/shim.d.ts +30 -0
  20. package/dist/cli/shim.js +140 -0
  21. package/dist/cli/size.d.ts +17 -0
  22. package/dist/cli/size.js +73 -0
  23. package/dist/cli/split.d.ts +20 -0
  24. package/dist/cli/split.js +140 -0
  25. package/dist/cli/symbols.d.ts +30 -0
  26. package/dist/cli/symbols.js +133 -0
  27. package/dist/cli/toolchain.d.ts +53 -0
  28. package/dist/cli/toolchain.js +167 -0
  29. package/dist/cli/validators.d.ts +6 -0
  30. package/dist/cli/validators.js +66 -0
  31. package/dist/cli/wasisdk.d.ts +82 -0
  32. package/dist/cli/wasisdk.js +220 -0
  33. package/dist/cli/wasmHints.d.ts +29 -0
  34. package/dist/cli/wasmHints.js +172 -0
  35. package/dist/runtime/base64.d.ts +4 -0
  36. package/dist/runtime/base64.js +77 -0
  37. package/dist/runtime/crypto.d.ts +7 -0
  38. package/dist/runtime/crypto.js +421 -0
  39. package/dist/runtime/fastjson.d.ts +3 -0
  40. package/dist/runtime/fastjson.js +170 -0
  41. package/dist/runtime/host.d.ts +73 -0
  42. package/dist/runtime/host.js +1230 -0
  43. package/dist/runtime/http.d.ts +40 -0
  44. package/dist/runtime/http.js +157 -0
  45. package/dist/runtime/index.d.ts +2 -0
  46. package/dist/runtime/index.js +1 -0
  47. package/dist/runtime/intl.d.ts +5 -0
  48. package/dist/runtime/intl.js +69 -0
  49. package/dist/runtime/tmpfs.d.ts +129 -0
  50. package/dist/runtime/tmpfs.js +624 -0
  51. package/dist/runtime/wasi.d.ts +33 -0
  52. package/dist/runtime/wasi.js +216 -0
  53. package/package.json +57 -4
  54. package/rust/convex_fn/Cargo.toml +32 -0
  55. package/rust/convex_fn/LICENSE +201 -0
  56. package/rust/convex_fn/build.rs +3 -0
  57. package/rust/convex_fn/src/args.rs +416 -0
  58. package/rust/convex_fn/src/crypto.rs +237 -0
  59. package/rust/convex_fn/src/ctx.rs +1044 -0
  60. package/rust/convex_fn/src/dns.rs +356 -0
  61. package/rust/convex_fn/src/error.rs +179 -0
  62. package/rust/convex_fn/src/executor.rs +577 -0
  63. package/rust/convex_fn/src/fanout.rs +106 -0
  64. package/rust/convex_fn/src/fs.rs +19 -0
  65. package/rust/convex_fn/src/function_ref.rs +219 -0
  66. package/rust/convex_fn/src/http.rs +441 -0
  67. package/rust/convex_fn/src/intl.rs +75 -0
  68. package/rust/convex_fn/src/lib.rs +242 -0
  69. package/rust/convex_fn/src/logging.rs +222 -0
  70. package/rust/convex_fn/src/native.rs +360 -0
  71. package/rust/convex_fn/src/net.rs +122 -0
  72. package/rust/convex_fn/src/sys.rs +178 -0
  73. package/rust/convex_fn/src/values.rs +121 -0
  74. package/rust/convex_fn/src/wire.rs +579 -0
  75. package/rust/convex_fn_macros/Cargo.toml +13 -0
  76. package/rust/convex_fn_macros/LICENSE +201 -0
  77. package/rust/convex_fn_macros/src/derive.rs +632 -0
  78. package/rust/convex_fn_macros/src/lib.rs +338 -0
  79. package/rust/convex_reqwest/Cargo.toml +69 -0
  80. package/rust/convex_reqwest/LICENSE +201 -0
  81. package/rust/convex_reqwest/src/blocking.rs +287 -0
  82. package/rust/convex_reqwest/src/body.rs +152 -0
  83. package/rust/convex_reqwest/src/client.rs +359 -0
  84. package/rust/convex_reqwest/src/config_types.rs +150 -0
  85. package/rust/convex_reqwest/src/error.rs +241 -0
  86. package/rust/convex_reqwest/src/into_url.rs +57 -0
  87. package/rust/convex_reqwest/src/lib.rs +42 -0
  88. package/rust/convex_reqwest/src/multipart.rs +140 -0
  89. package/rust/convex_reqwest/src/request.rs +358 -0
  90. package/rust/convex_reqwest/src/response.rs +310 -0
@@ -0,0 +1,287 @@
1
+ //! A blocking `Client` API, built on `convex_fn::block_on`.
2
+ //!
3
+ //! Works from plain synchronous code and from inside a running action:
4
+ //! `convex_fn::block_on` detects the nested case and drives the host task
5
+ //! directly (submit + blocking `task_poll`) instead of starting a second tokio
6
+ //! runtime. Because the guest is single-threaded, tasks spawned on the tokio
7
+ //! `LocalSet` (and tokio timers) do not progress while a blocking call is in
8
+ //! flight; do not block on something that needs them.
9
+
10
+ use std::{io, time::Duration};
11
+
12
+ use bytes::Bytes;
13
+ use http::{
14
+ header::{HeaderMap, HeaderName, HeaderValue},
15
+ Method, StatusCode, Version,
16
+ };
17
+ use serde::{de::DeserializeOwned, Serialize};
18
+ use url::Url;
19
+
20
+ use crate::{body::Body, error::Result, into_url::IntoUrl, multipart, redirect, Proxy, Request};
21
+
22
+ fn wait<F: std::future::Future>(f: F) -> F::Output {
23
+ convex_fn::block_on(f)
24
+ }
25
+
26
+ /// Shortcut method to quickly make a blocking `GET` request.
27
+ pub fn get<T: IntoUrl>(url: T) -> Result<Response> {
28
+ Client::new().get(url).send()
29
+ }
30
+
31
+ /// A blocking `Client` to make Requests with.
32
+ #[derive(Clone, Debug)]
33
+ pub struct Client {
34
+ inner: crate::Client,
35
+ }
36
+
37
+ impl Default for Client {
38
+ fn default() -> Self {
39
+ Self::new()
40
+ }
41
+ }
42
+
43
+ impl Client {
44
+ pub fn new() -> Client {
45
+ ClientBuilder::new().build().expect("default client")
46
+ }
47
+ pub fn builder() -> ClientBuilder {
48
+ ClientBuilder::new()
49
+ }
50
+ pub fn get<U: IntoUrl>(&self, url: U) -> RequestBuilder {
51
+ self.request(Method::GET, url)
52
+ }
53
+ pub fn post<U: IntoUrl>(&self, url: U) -> RequestBuilder {
54
+ self.request(Method::POST, url)
55
+ }
56
+ pub fn put<U: IntoUrl>(&self, url: U) -> RequestBuilder {
57
+ self.request(Method::PUT, url)
58
+ }
59
+ pub fn patch<U: IntoUrl>(&self, url: U) -> RequestBuilder {
60
+ self.request(Method::PATCH, url)
61
+ }
62
+ pub fn delete<U: IntoUrl>(&self, url: U) -> RequestBuilder {
63
+ self.request(Method::DELETE, url)
64
+ }
65
+ pub fn head<U: IntoUrl>(&self, url: U) -> RequestBuilder {
66
+ self.request(Method::HEAD, url)
67
+ }
68
+ pub fn request<U: IntoUrl>(&self, method: Method, url: U) -> RequestBuilder {
69
+ RequestBuilder {
70
+ inner: self.inner.request(method, url),
71
+ }
72
+ }
73
+ pub fn execute(&self, request: Request) -> Result<Response> {
74
+ wait(self.inner.execute(request)).map(Response::new)
75
+ }
76
+ }
77
+
78
+ /// A `ClientBuilder` can be used to create a blocking `Client`.
79
+ #[derive(Debug)]
80
+ pub struct ClientBuilder {
81
+ inner: crate::ClientBuilder,
82
+ timeout: Option<Duration>,
83
+ }
84
+
85
+ impl Default for ClientBuilder {
86
+ fn default() -> Self {
87
+ Self::new()
88
+ }
89
+ }
90
+
91
+ macro_rules! passthrough {
92
+ ($($name:ident($($arg:ident: $ty:ty),*);)*) => {
93
+ $(
94
+ pub fn $name(mut self $(, $arg: $ty)*) -> ClientBuilder {
95
+ self.inner = self.inner.$name($($arg),*);
96
+ self
97
+ }
98
+ )*
99
+ };
100
+ }
101
+
102
+ impl ClientBuilder {
103
+ pub fn new() -> ClientBuilder {
104
+ ClientBuilder {
105
+ inner: crate::ClientBuilder::new(),
106
+ // reqwest::blocking defaults to a 30 s timeout.
107
+ timeout: Some(Duration::from_secs(30)),
108
+ }
109
+ }
110
+
111
+ pub fn build(self) -> Result<Client> {
112
+ let b = match self.timeout {
113
+ Some(t) => self.inner.timeout(t),
114
+ None => self.inner,
115
+ };
116
+ Ok(Client { inner: b.build()? })
117
+ }
118
+
119
+ /// Enables a request timeout (`None` disables it).
120
+ pub fn timeout<T: Into<Option<Duration>>>(mut self, timeout: T) -> ClientBuilder {
121
+ self.timeout = timeout.into();
122
+ self
123
+ }
124
+
125
+ pub fn user_agent<V>(mut self, value: V) -> ClientBuilder
126
+ where
127
+ HeaderValue: TryFrom<V>,
128
+ <HeaderValue as TryFrom<V>>::Error: Into<http::Error>,
129
+ {
130
+ self.inner = self.inner.user_agent(value);
131
+ self
132
+ }
133
+
134
+ passthrough! {
135
+ default_headers(headers: HeaderMap);
136
+ https_only(enabled: bool);
137
+ redirect(policy: redirect::Policy);
138
+ proxy(proxy: Proxy);
139
+ no_proxy();
140
+ connect_timeout(timeout: Duration);
141
+ pool_max_idle_per_host(max: usize);
142
+ gzip(enable: bool);
143
+ brotli(enable: bool);
144
+ deflate(enable: bool);
145
+ danger_accept_invalid_certs(accept: bool);
146
+ use_native_tls();
147
+ use_rustls_tls();
148
+ http1_only();
149
+ tcp_nodelay(enabled: bool);
150
+ }
151
+ }
152
+
153
+ /// A builder to construct the properties of a blocking `Request`.
154
+ #[derive(Debug)]
155
+ #[must_use = "RequestBuilder does nothing until you 'send' it"]
156
+ pub struct RequestBuilder {
157
+ inner: crate::RequestBuilder,
158
+ }
159
+
160
+ impl RequestBuilder {
161
+ pub fn header<K, V>(mut self, key: K, value: V) -> RequestBuilder
162
+ where
163
+ HeaderName: TryFrom<K>,
164
+ <HeaderName as TryFrom<K>>::Error: Into<http::Error>,
165
+ HeaderValue: TryFrom<V>,
166
+ <HeaderValue as TryFrom<V>>::Error: Into<http::Error>,
167
+ {
168
+ self.inner = self.inner.header(key, value);
169
+ self
170
+ }
171
+ pub fn headers(mut self, headers: HeaderMap) -> RequestBuilder {
172
+ self.inner = self.inner.headers(headers);
173
+ self
174
+ }
175
+ pub fn basic_auth<U, P>(mut self, username: U, password: Option<P>) -> RequestBuilder
176
+ where
177
+ U: std::fmt::Display,
178
+ P: std::fmt::Display,
179
+ {
180
+ self.inner = self.inner.basic_auth(username, password);
181
+ self
182
+ }
183
+ pub fn bearer_auth<T: std::fmt::Display>(mut self, token: T) -> RequestBuilder {
184
+ self.inner = self.inner.bearer_auth(token);
185
+ self
186
+ }
187
+ pub fn body<T: Into<Body>>(mut self, body: T) -> RequestBuilder {
188
+ self.inner = self.inner.body(body);
189
+ self
190
+ }
191
+ pub fn timeout(mut self, timeout: Duration) -> RequestBuilder {
192
+ self.inner = self.inner.timeout(timeout);
193
+ self
194
+ }
195
+ pub fn multipart(mut self, form: multipart::Form) -> RequestBuilder {
196
+ self.inner = self.inner.multipart(form);
197
+ self
198
+ }
199
+ pub fn query<T: Serialize + ?Sized>(mut self, query: &T) -> RequestBuilder {
200
+ self.inner = self.inner.query(query);
201
+ self
202
+ }
203
+ pub fn form<T: Serialize + ?Sized>(mut self, form: &T) -> RequestBuilder {
204
+ self.inner = self.inner.form(form);
205
+ self
206
+ }
207
+ pub fn json<T: Serialize + ?Sized>(mut self, json: &T) -> RequestBuilder {
208
+ self.inner = self.inner.json(json);
209
+ self
210
+ }
211
+ pub fn build(self) -> Result<Request> {
212
+ self.inner.build()
213
+ }
214
+ pub fn send(self) -> Result<Response> {
215
+ wait(self.inner.send()).map(Response::new)
216
+ }
217
+ pub fn try_clone(&self) -> Option<RequestBuilder> {
218
+ self.inner.try_clone().map(|inner| RequestBuilder { inner })
219
+ }
220
+ }
221
+
222
+ /// A blocking `Response`.
223
+ #[derive(Debug)]
224
+ pub struct Response {
225
+ inner: crate::Response,
226
+ pending: Bytes,
227
+ }
228
+
229
+ impl Response {
230
+ fn new(inner: crate::Response) -> Response {
231
+ Response {
232
+ inner,
233
+ pending: Bytes::new(),
234
+ }
235
+ }
236
+ pub fn status(&self) -> StatusCode {
237
+ self.inner.status()
238
+ }
239
+ pub fn version(&self) -> Version {
240
+ self.inner.version()
241
+ }
242
+ pub fn headers(&self) -> &HeaderMap {
243
+ self.inner.headers()
244
+ }
245
+ pub fn url(&self) -> &Url {
246
+ self.inner.url()
247
+ }
248
+ pub fn content_length(&self) -> Option<u64> {
249
+ self.inner.content_length()
250
+ }
251
+ pub fn text(self) -> Result<String> {
252
+ wait(self.inner.text())
253
+ }
254
+ pub fn json<T: DeserializeOwned>(self) -> Result<T> {
255
+ wait(self.inner.json())
256
+ }
257
+ pub fn bytes(self) -> Result<Bytes> {
258
+ wait(self.inner.bytes())
259
+ }
260
+ pub fn error_for_status(self) -> Result<Self> {
261
+ let pending = self.pending;
262
+ self.inner
263
+ .error_for_status()
264
+ .map(|inner| Response { inner, pending })
265
+ }
266
+ pub fn error_for_status_ref(&self) -> Result<&Self> {
267
+ self.inner.error_for_status_ref().map(|_| self)
268
+ }
269
+ /// Copies the body into `w`; returns the number of bytes copied.
270
+ pub fn copy_to<W: io::Write + ?Sized>(&mut self, w: &mut W) -> Result<u64> {
271
+ io::copy(self, w).map_err(crate::error::Error::body)
272
+ }
273
+ }
274
+
275
+ impl io::Read for Response {
276
+ fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
277
+ if self.pending.is_empty() {
278
+ match wait(self.inner.chunk())? {
279
+ Some(c) => self.pending = c,
280
+ None => return Ok(0),
281
+ }
282
+ }
283
+ let n = buf.len().min(self.pending.len());
284
+ buf[..n].copy_from_slice(&self.pending.split_to(n));
285
+ Ok(n)
286
+ }
287
+ }
@@ -0,0 +1,152 @@
1
+ use std::{fmt, pin::Pin, sync::Mutex, task::Poll};
2
+
3
+ use bytes::Bytes;
4
+ use futures_core::Stream;
5
+ use futures_util::TryStream;
6
+
7
+ use crate::error::{BoxError, Error};
8
+
9
+ /// An asynchronous request body.
10
+ pub struct Body {
11
+ inner: Inner,
12
+ }
13
+
14
+ type BoxStream = Pin<Box<dyn Stream<Item = Result<Bytes, BoxError>> + Send>>;
15
+
16
+ enum Inner {
17
+ Bytes(Bytes),
18
+ Stream(Mutex<BoxStream>),
19
+ }
20
+
21
+ impl Body {
22
+ /// Returns a reference to the internal data of the `Body`, or `None` for a
23
+ /// streaming body.
24
+ pub fn as_bytes(&self) -> Option<&[u8]> {
25
+ match &self.inner {
26
+ Inner::Bytes(b) => Some(b),
27
+ Inner::Stream(_) => None,
28
+ }
29
+ }
30
+
31
+ /// Wraps a futures `Stream` in a box inside `Body`.
32
+ pub fn wrap_stream<S>(stream: S) -> Body
33
+ where
34
+ S: TryStream + Send + 'static,
35
+ S::Error: Into<BoxError>,
36
+ Bytes: From<S::Ok>,
37
+ {
38
+ let mut stream = Box::pin(stream);
39
+ let s = futures_util::stream::poll_fn(move |cx| {
40
+ stream
41
+ .as_mut()
42
+ .try_poll_next(cx)
43
+ .map(|o| o.map(|r| r.map(Bytes::from).map_err(Into::into)))
44
+ });
45
+ Body {
46
+ inner: Inner::Stream(Mutex::new(Box::pin(s))),
47
+ }
48
+ }
49
+
50
+ /// Splits into the bytes of an in-memory body or the stream of a streaming one.
51
+ pub(crate) fn into_source(self) -> Result<Bytes, StreamSource> {
52
+ match self.inner {
53
+ Inner::Bytes(b) => Ok(b),
54
+ Inner::Stream(s) => Err(StreamSource(
55
+ s.into_inner().unwrap_or_else(|e| e.into_inner()),
56
+ )),
57
+ }
58
+ }
59
+
60
+ pub(crate) fn try_clone(&self) -> Option<Body> {
61
+ match &self.inner {
62
+ Inner::Bytes(b) => Some(Body::from(b.clone())),
63
+ Inner::Stream(_) => None,
64
+ }
65
+ }
66
+ }
67
+
68
+ /// A streaming request body as a `convex_fn` chunk source (a streamed upload).
69
+ pub(crate) struct StreamSource(BoxStream);
70
+
71
+ impl convex_fn::ChunkSource for StreamSource {
72
+ async fn next_chunk(&mut self) -> convex_fn::Result<Option<Vec<u8>>> {
73
+ let next = std::future::poll_fn(|cx| self.0.as_mut().poll_next(cx)).await;
74
+ match next {
75
+ Some(Ok(c)) => Ok(Some(c.to_vec())),
76
+ Some(Err(e)) => Err(convex_fn::Error::msg(e.to_string())),
77
+ None => Ok(None),
78
+ }
79
+ }
80
+ }
81
+
82
+ impl fmt::Debug for Body {
83
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
84
+ let mut d = f.debug_struct("Body");
85
+ match &self.inner {
86
+ Inner::Bytes(b) => d.field("bytes", &b.len()),
87
+ Inner::Stream(_) => d.field("stream", &"..."),
88
+ };
89
+ d.finish()
90
+ }
91
+ }
92
+
93
+ impl Default for Body {
94
+ fn default() -> Body {
95
+ Body::from(Bytes::new())
96
+ }
97
+ }
98
+
99
+ impl From<Bytes> for Body {
100
+ fn from(b: Bytes) -> Body {
101
+ Body {
102
+ inner: Inner::Bytes(b),
103
+ }
104
+ }
105
+ }
106
+ impl From<Vec<u8>> for Body {
107
+ fn from(v: Vec<u8>) -> Body {
108
+ Bytes::from(v).into()
109
+ }
110
+ }
111
+ impl From<&'static [u8]> for Body {
112
+ fn from(v: &'static [u8]) -> Body {
113
+ Bytes::from_static(v).into()
114
+ }
115
+ }
116
+ impl From<String> for Body {
117
+ fn from(v: String) -> Body {
118
+ Bytes::from(v).into()
119
+ }
120
+ }
121
+ impl From<&'static str> for Body {
122
+ fn from(v: &'static str) -> Body {
123
+ Bytes::from_static(v.as_bytes()).into()
124
+ }
125
+ }
126
+
127
+ impl http_body::Body for Body {
128
+ type Data = Bytes;
129
+ type Error = Error;
130
+
131
+ fn poll_frame(
132
+ self: Pin<&mut Self>,
133
+ cx: &mut std::task::Context<'_>,
134
+ ) -> Poll<Option<Result<http_body::Frame<Bytes>, Error>>> {
135
+ let this = self.get_mut();
136
+ match &mut this.inner {
137
+ Inner::Bytes(b) => {
138
+ if b.is_empty() {
139
+ Poll::Ready(None)
140
+ } else {
141
+ Poll::Ready(Some(Ok(http_body::Frame::data(std::mem::take(b)))))
142
+ }
143
+ }
144
+ Inner::Stream(s) => {
145
+ let s = s.get_mut().unwrap_or_else(|e| e.into_inner());
146
+ s.as_mut()
147
+ .poll_next(cx)
148
+ .map(|o| o.map(|r| r.map(http_body::Frame::data).map_err(Error::body)))
149
+ }
150
+ }
151
+ }
152
+ }