@arrirpc/codegen-rust 0.54.0 → 0.57.0

Sign up to get free protection for your applications and to get access to all the features.
package/README.md CHANGED
@@ -37,31 +37,101 @@ cargo add arri_client
37
37
 
38
38
  ## Using the generated code
39
39
 
40
- ### Initialize the client
40
+ All of the generated procedures in this client will be async functions, so you will need an async runtime like [tokio](https://tokio.rs/)
41
+
42
+ ### Initializing the client
41
43
 
42
44
  ```rust
43
45
  let config = ArriClientConfig {
44
46
  http_client: reqwest::Client::new(),
45
47
  base_url: "https://example.com".to_string(),
46
- // this function will run before every request
47
- headers: || {
48
- let mut header_map = Hashmap::<&'static str, &'static str>::new();
49
- header_map.insert("some-header", "some-header-value");
50
- header_map
51
- }
48
+ headers: Hashmap::new(),
52
49
  }
53
- let client = MyClient::create(&config);
50
+ let client = MyClient::create(config);
54
51
 
52
+ // start calling procedures
55
53
  client.my_procedure().await;
56
54
  ```
57
55
 
58
56
  The root client will be a struct containing all of the services and procedures. If you only need a particular service you can initialize just that service.
59
57
 
60
58
  ```rust
61
- let users_service = MyClientUsersService(&config);
59
+ let users_service = MyClientUsersService(config);
62
60
  users_service.some_procedure().await;
63
61
  ```
64
62
 
63
+ ### Updating Headers
64
+
65
+ For instances that you need to update the http headers (like in the case of an expired auth token), you can call the `update_headers()` function. When called, changes will propagate to all nested subservices.
66
+
67
+ ```rust
68
+ client.update_headers(new_headers);
69
+ ```
70
+
71
+ Be aware that if `update_headers()` is called from a subservice it will not propagate up to the parent service(s).
72
+
73
+ ```rust
74
+ client.subservice.update_headers(new_headers);
75
+
76
+ // this will still use the original headers
77
+ client.do_something();
78
+ ```
79
+
80
+ `update_headers()` be also be called across threads.
81
+
82
+ ```rust
83
+ let mut headers: HashMap<&'static str, String> = HashMap::new();
84
+ let config = ArriClientConfig {
85
+ http_client: reqwest::Client::new(),
86
+ base_url: "https://example.com".to_string(),
87
+ headers: headers.clone(),
88
+ }
89
+ let client = Arc::new(MyClient::create(config));
90
+ tokio::spawn(async move {
91
+ loop {
92
+ client.do_something().await;
93
+ }
94
+ });
95
+ tokio::spawn(async move {
96
+ loop {
97
+ client.do_another_thing().await;
98
+ }
99
+ });
100
+
101
+ // wait two seconds then change the headers
102
+ tokio::time::sleep(Duration::from_millis(2000)).await;
103
+ headers.insert("hello", "world".to_string());
104
+ client.update_headers(headers.clone());
105
+ // now both threads will start using the updated headers on their next loop
106
+ ```
107
+
108
+ ### Calling SSE Procedures
109
+
110
+ ```rust
111
+ let mut msg_count = 0;
112
+ let mut open_count = 0;
113
+ client
114
+ .users
115
+ .watch_user(
116
+ &mut |event, controller| match event {
117
+ SseEvent::Message(msg) => {
118
+ msg_count += 1;
119
+ printl("NEW_MESSAGE: {:?}", msg);
120
+ }
121
+ SSeEvent::Error(err) => {
122
+ // call abort to close the event stream
123
+ controller.abort()
124
+ }
125
+ SseEvent::Open => {
126
+ open_count += 1;
127
+ }
128
+ SseEvent::Close => {}
129
+ },
130
+ None, // max_retry_count (u64)
131
+ None, // max_retry_interval (u64)
132
+ ).await;
133
+ ```
134
+
65
135
  ### Using the generated types
66
136
 
67
137
  All the generated types will have the following methods implemented
package/dist/index.cjs CHANGED
@@ -1544,15 +1544,7 @@ function rustRpcFromSchema(schema, context) {
1544
1544
  }
1545
1545
  }
1546
1546
  function rustHttpRpcFromSchema(schema, context) {
1547
- if (schema.isEventStream) {
1548
- console.warn(
1549
- `[rust-codegen] SSE is not supported at this time. Skipping ${context.instancePath}.`
1550
- );
1551
- return "";
1552
- }
1553
1547
  const functionName = getFunctionName(context.instancePath);
1554
- const params = schema.params ? validRustName(schema.params) : void 0;
1555
- const response = schema.response ? validRustName(schema.response) : void 0;
1556
1548
  let leading = "";
1557
1549
  if (schema.description) {
1558
1550
  leading += formatDescriptionComment(schema.description);
@@ -1561,16 +1553,44 @@ function rustHttpRpcFromSchema(schema, context) {
1561
1553
  if (schema.isDeprecated) {
1562
1554
  leading += "#[deprecated]\n";
1563
1555
  }
1564
- return `${leading}pub async fn ${functionName} (
1565
- self: &Self,
1556
+ const params = schema.params ? validRustName(schema.params) : void 0;
1557
+ const response = schema.response ? validRustName(schema.response) : void 0;
1558
+ if (schema.isEventStream) {
1559
+ return `${leading}pub async fn ${functionName}<OnEvent>(
1560
+ &self,
1561
+ ${params ? `params: ${context.typeNamePrefix}${params},` : ""}
1562
+ on_event: &mut OnEvent,
1563
+ max_retry_count: Option<u64>,
1564
+ max_retry_interval: Option<u64>,
1565
+ ) where
1566
+ OnEvent: FnMut(SseEvent<${response ? `${context.typeNamePrefix}${response}` : "EmptyArriModel"}>, &mut SseController) + std::marker::Send + std::marker::Sync,
1567
+ {
1568
+ parsed_arri_sse_request(
1569
+ ArriParsedSseRequestOptions {
1570
+ client: &self._config.http_client,
1571
+ url: format!("{}${schema.path}", &self._config.base_url),
1572
+ method: reqwest::Method::${schema.method.toUpperCase()},
1573
+ headers: self._config.headers.clone(),
1574
+ client_version: "${context.clientVersion}".to_string(),
1575
+ max_retry_count,
1576
+ max_retry_interval,
1577
+ },
1578
+ ${params ? `Some(params)` : "None::<EmptyArriModel>"},
1579
+ on_event,
1580
+ )
1581
+ .await;
1582
+ }`;
1583
+ }
1584
+ return `${leading}pub async fn ${functionName}(
1585
+ &self,
1566
1586
  ${params ? `params: ${context.typeNamePrefix}${params},` : ""}
1567
1587
  ) -> Result<${context.typeNamePrefix}${response ?? "()"}, ArriServerError> {
1568
1588
  parsed_arri_request(
1569
1589
  ArriParsedRequestOptions {
1570
- http_client: &self.config.http_client,
1571
- url: format!("{}${schema.path}", &self.config.base_url),
1590
+ http_client: &self._config.http_client,
1591
+ url: format!("{}${schema.path}", &self._config.base_url),
1572
1592
  method: reqwest::Method::${schema.method.toUpperCase()},
1573
- headers: self.config.headers,
1593
+ headers: self._config.headers.clone(),
1574
1594
  client_version: "${context.clientVersion}".to_string(),
1575
1595
  },
1576
1596
  ${params ? `Some(params)` : "None::<EmptyArriModel>"},
@@ -1637,23 +1657,30 @@ function rustServiceFromSchema(schema, context) {
1637
1657
  `[rust-codegen] Invalid schema at /procedures/${context.instancePath}.`
1638
1658
  );
1639
1659
  }
1660
+ const paramSuffix = subServices.length > 0 ? ".clone()" : "";
1640
1661
  return {
1641
1662
  name: serviceName,
1642
- content: `pub struct ${serviceName}<'a> {
1643
- config: &'a ArriClientConfig,
1644
- ${subServices.map((service) => ` pub ${service.key}: ${service.name}<'a>,`).join("\n")}
1663
+ content: `#[derive(Clone)]
1664
+ pub struct ${serviceName} {
1665
+ _config: InternalArriClientConfig,
1666
+ ${subServices.map((service) => ` pub ${service.key}: ${service.name},`).join("\n")}
1645
1667
  }
1646
1668
 
1647
- impl<'a> ArriClientService<'a> for ${serviceName}<'a> {
1648
- fn create(config: &'a ArriClientConfig) -> Self {
1669
+ impl ArriClientService for ${serviceName} {
1670
+ fn create(config: ArriClientConfig) -> Self {
1649
1671
  Self {
1650
- config: &config,
1651
- ${subServices.map((service) => ` ${service.key}: ${service.name}::create(config),`).join("\n")}
1672
+ _config: InternalArriClientConfig::from(config${paramSuffix}),
1673
+ ${subServices.map((service, index) => ` ${service.key}: ${service.name}::create(config${index === subServices.length - 1 ? "" : ".clone()"}),`).join("\n")}
1652
1674
  }
1653
1675
  }
1676
+ fn update_headers(&self, headers: HashMap<&'static str, String>) {
1677
+ let mut unwrapped_headers = self._config.headers.write().unwrap();
1678
+ *unwrapped_headers = headers.clone();
1679
+ ${subServices.map((service, index) => ` self.${service.key}.update_headers(headers${index === subServices.length - 1 ? "" : ".clone()"});`).join("\n")}
1680
+ }
1654
1681
  }
1655
1682
 
1656
- impl ${serviceName}<'_> {
1683
+ impl ${serviceName} {
1657
1684
  ${rpcParts.join("\n")}
1658
1685
  }
1659
1686
 
@@ -1892,35 +1919,51 @@ use arri_client::{
1892
1919
  utils::{serialize_date_time, serialize_string},
1893
1920
  ArriEnum, ArriModel,
1894
1921
  };
1895
- use std::collections::BTreeMap;
1922
+ use std::collections::{BTreeMap, HashMap};
1896
1923
  ${modelParts.join("\n\n")}`;
1897
1924
  }
1898
1925
  const clientName = validRustName(context.clientName);
1899
- return `#![allow(dead_code, unused_imports, unused_variables, unconditional_recursion, deprecated)]
1926
+ const paramSuffix = subServices.length > 0 ? ".clone()" : "";
1927
+ return `#![allow(
1928
+ dead_code,
1929
+ unused_imports,
1930
+ unused_variables,
1931
+ unconditional_recursion,
1932
+ deprecated
1933
+ )]
1900
1934
  use arri_client::{
1901
1935
  chrono::{DateTime, FixedOffset},
1902
- parsed_arri_request, reqwest, serde_json,
1936
+ parsed_arri_request,
1937
+ reqwest::{self, Request},
1938
+ serde_json::{self, Map},
1939
+ sse::{parsed_arri_sse_request, ArriParsedSseRequestOptions, SseController, SseEvent},
1903
1940
  utils::{serialize_date_time, serialize_string},
1904
1941
  ArriClientConfig, ArriClientService, ArriEnum, ArriModel, ArriParsedRequestOptions,
1905
- ArriServerError, EmptyArriModel,
1942
+ ArriServerError, EmptyArriModel, InternalArriClientConfig,
1906
1943
  };
1907
- use std::collections::BTreeMap;
1944
+ use std::collections::{BTreeMap, HashMap};
1908
1945
 
1909
- pub struct ${clientName}<'a> {
1910
- config: &'a ArriClientConfig,
1911
- ${subServices.map((service) => ` pub ${service.key}: ${service.name}<'a>,`).join("\n")}
1946
+ #[derive(Clone)]
1947
+ pub struct ${clientName} {
1948
+ _config: InternalArriClientConfig,
1949
+ ${subServices.map((service) => ` pub ${service.key}: ${service.name},`).join("\n")}
1912
1950
  }
1913
1951
 
1914
- impl<'a> ArriClientService<'a> for ${clientName}<'a> {
1915
- fn create(config: &'a ArriClientConfig) -> Self {
1952
+ impl ArriClientService for ${clientName} {
1953
+ fn create(config: ArriClientConfig) -> Self {
1916
1954
  Self {
1917
- config: &config,
1918
- ${subServices.map((service) => ` ${service.key}: ${service.name}::create(config),`).join("\n")}
1955
+ _config: InternalArriClientConfig::from(config${paramSuffix}),
1956
+ ${subServices.map((service, index) => ` ${service.key}: ${service.name}::create(config${index === subServices.length - 1 ? "" : ".clone()"}),`).join("\n")}
1919
1957
  }
1920
1958
  }
1959
+ fn update_headers(&self, headers: HashMap<&'static str, String>) {
1960
+ let mut unwrapped_headers = self._config.headers.write().unwrap();
1961
+ *unwrapped_headers = headers.clone();
1962
+ ${subServices.map((service, index) => ` self.${service.key}.update_headers(headers${index === subServices.length - 1 ? "" : ".clone()"});`).join("\n")}
1963
+ }
1921
1964
  }
1922
1965
 
1923
- impl ${clientName}<'_> {
1966
+ impl ${clientName} {
1924
1967
  ${rpcParts.join("\n")}
1925
1968
  }
1926
1969
 
package/dist/index.mjs CHANGED
@@ -1536,15 +1536,7 @@ function rustRpcFromSchema(schema, context) {
1536
1536
  }
1537
1537
  }
1538
1538
  function rustHttpRpcFromSchema(schema, context) {
1539
- if (schema.isEventStream) {
1540
- console.warn(
1541
- `[rust-codegen] SSE is not supported at this time. Skipping ${context.instancePath}.`
1542
- );
1543
- return "";
1544
- }
1545
1539
  const functionName = getFunctionName(context.instancePath);
1546
- const params = schema.params ? validRustName(schema.params) : void 0;
1547
- const response = schema.response ? validRustName(schema.response) : void 0;
1548
1540
  let leading = "";
1549
1541
  if (schema.description) {
1550
1542
  leading += formatDescriptionComment(schema.description);
@@ -1553,16 +1545,44 @@ function rustHttpRpcFromSchema(schema, context) {
1553
1545
  if (schema.isDeprecated) {
1554
1546
  leading += "#[deprecated]\n";
1555
1547
  }
1556
- return `${leading}pub async fn ${functionName} (
1557
- self: &Self,
1548
+ const params = schema.params ? validRustName(schema.params) : void 0;
1549
+ const response = schema.response ? validRustName(schema.response) : void 0;
1550
+ if (schema.isEventStream) {
1551
+ return `${leading}pub async fn ${functionName}<OnEvent>(
1552
+ &self,
1553
+ ${params ? `params: ${context.typeNamePrefix}${params},` : ""}
1554
+ on_event: &mut OnEvent,
1555
+ max_retry_count: Option<u64>,
1556
+ max_retry_interval: Option<u64>,
1557
+ ) where
1558
+ OnEvent: FnMut(SseEvent<${response ? `${context.typeNamePrefix}${response}` : "EmptyArriModel"}>, &mut SseController) + std::marker::Send + std::marker::Sync,
1559
+ {
1560
+ parsed_arri_sse_request(
1561
+ ArriParsedSseRequestOptions {
1562
+ client: &self._config.http_client,
1563
+ url: format!("{}${schema.path}", &self._config.base_url),
1564
+ method: reqwest::Method::${schema.method.toUpperCase()},
1565
+ headers: self._config.headers.clone(),
1566
+ client_version: "${context.clientVersion}".to_string(),
1567
+ max_retry_count,
1568
+ max_retry_interval,
1569
+ },
1570
+ ${params ? `Some(params)` : "None::<EmptyArriModel>"},
1571
+ on_event,
1572
+ )
1573
+ .await;
1574
+ }`;
1575
+ }
1576
+ return `${leading}pub async fn ${functionName}(
1577
+ &self,
1558
1578
  ${params ? `params: ${context.typeNamePrefix}${params},` : ""}
1559
1579
  ) -> Result<${context.typeNamePrefix}${response ?? "()"}, ArriServerError> {
1560
1580
  parsed_arri_request(
1561
1581
  ArriParsedRequestOptions {
1562
- http_client: &self.config.http_client,
1563
- url: format!("{}${schema.path}", &self.config.base_url),
1582
+ http_client: &self._config.http_client,
1583
+ url: format!("{}${schema.path}", &self._config.base_url),
1564
1584
  method: reqwest::Method::${schema.method.toUpperCase()},
1565
- headers: self.config.headers,
1585
+ headers: self._config.headers.clone(),
1566
1586
  client_version: "${context.clientVersion}".to_string(),
1567
1587
  },
1568
1588
  ${params ? `Some(params)` : "None::<EmptyArriModel>"},
@@ -1629,23 +1649,30 @@ function rustServiceFromSchema(schema, context) {
1629
1649
  `[rust-codegen] Invalid schema at /procedures/${context.instancePath}.`
1630
1650
  );
1631
1651
  }
1652
+ const paramSuffix = subServices.length > 0 ? ".clone()" : "";
1632
1653
  return {
1633
1654
  name: serviceName,
1634
- content: `pub struct ${serviceName}<'a> {
1635
- config: &'a ArriClientConfig,
1636
- ${subServices.map((service) => ` pub ${service.key}: ${service.name}<'a>,`).join("\n")}
1655
+ content: `#[derive(Clone)]
1656
+ pub struct ${serviceName} {
1657
+ _config: InternalArriClientConfig,
1658
+ ${subServices.map((service) => ` pub ${service.key}: ${service.name},`).join("\n")}
1637
1659
  }
1638
1660
 
1639
- impl<'a> ArriClientService<'a> for ${serviceName}<'a> {
1640
- fn create(config: &'a ArriClientConfig) -> Self {
1661
+ impl ArriClientService for ${serviceName} {
1662
+ fn create(config: ArriClientConfig) -> Self {
1641
1663
  Self {
1642
- config: &config,
1643
- ${subServices.map((service) => ` ${service.key}: ${service.name}::create(config),`).join("\n")}
1664
+ _config: InternalArriClientConfig::from(config${paramSuffix}),
1665
+ ${subServices.map((service, index) => ` ${service.key}: ${service.name}::create(config${index === subServices.length - 1 ? "" : ".clone()"}),`).join("\n")}
1644
1666
  }
1645
1667
  }
1668
+ fn update_headers(&self, headers: HashMap<&'static str, String>) {
1669
+ let mut unwrapped_headers = self._config.headers.write().unwrap();
1670
+ *unwrapped_headers = headers.clone();
1671
+ ${subServices.map((service, index) => ` self.${service.key}.update_headers(headers${index === subServices.length - 1 ? "" : ".clone()"});`).join("\n")}
1672
+ }
1646
1673
  }
1647
1674
 
1648
- impl ${serviceName}<'_> {
1675
+ impl ${serviceName} {
1649
1676
  ${rpcParts.join("\n")}
1650
1677
  }
1651
1678
 
@@ -1884,35 +1911,51 @@ use arri_client::{
1884
1911
  utils::{serialize_date_time, serialize_string},
1885
1912
  ArriEnum, ArriModel,
1886
1913
  };
1887
- use std::collections::BTreeMap;
1914
+ use std::collections::{BTreeMap, HashMap};
1888
1915
  ${modelParts.join("\n\n")}`;
1889
1916
  }
1890
1917
  const clientName = validRustName(context.clientName);
1891
- return `#![allow(dead_code, unused_imports, unused_variables, unconditional_recursion, deprecated)]
1918
+ const paramSuffix = subServices.length > 0 ? ".clone()" : "";
1919
+ return `#![allow(
1920
+ dead_code,
1921
+ unused_imports,
1922
+ unused_variables,
1923
+ unconditional_recursion,
1924
+ deprecated
1925
+ )]
1892
1926
  use arri_client::{
1893
1927
  chrono::{DateTime, FixedOffset},
1894
- parsed_arri_request, reqwest, serde_json,
1928
+ parsed_arri_request,
1929
+ reqwest::{self, Request},
1930
+ serde_json::{self, Map},
1931
+ sse::{parsed_arri_sse_request, ArriParsedSseRequestOptions, SseController, SseEvent},
1895
1932
  utils::{serialize_date_time, serialize_string},
1896
1933
  ArriClientConfig, ArriClientService, ArriEnum, ArriModel, ArriParsedRequestOptions,
1897
- ArriServerError, EmptyArriModel,
1934
+ ArriServerError, EmptyArriModel, InternalArriClientConfig,
1898
1935
  };
1899
- use std::collections::BTreeMap;
1936
+ use std::collections::{BTreeMap, HashMap};
1900
1937
 
1901
- pub struct ${clientName}<'a> {
1902
- config: &'a ArriClientConfig,
1903
- ${subServices.map((service) => ` pub ${service.key}: ${service.name}<'a>,`).join("\n")}
1938
+ #[derive(Clone)]
1939
+ pub struct ${clientName} {
1940
+ _config: InternalArriClientConfig,
1941
+ ${subServices.map((service) => ` pub ${service.key}: ${service.name},`).join("\n")}
1904
1942
  }
1905
1943
 
1906
- impl<'a> ArriClientService<'a> for ${clientName}<'a> {
1907
- fn create(config: &'a ArriClientConfig) -> Self {
1944
+ impl ArriClientService for ${clientName} {
1945
+ fn create(config: ArriClientConfig) -> Self {
1908
1946
  Self {
1909
- config: &config,
1910
- ${subServices.map((service) => ` ${service.key}: ${service.name}::create(config),`).join("\n")}
1947
+ _config: InternalArriClientConfig::from(config${paramSuffix}),
1948
+ ${subServices.map((service, index) => ` ${service.key}: ${service.name}::create(config${index === subServices.length - 1 ? "" : ".clone()"}),`).join("\n")}
1911
1949
  }
1912
1950
  }
1951
+ fn update_headers(&self, headers: HashMap<&'static str, String>) {
1952
+ let mut unwrapped_headers = self._config.headers.write().unwrap();
1953
+ *unwrapped_headers = headers.clone();
1954
+ ${subServices.map((service, index) => ` self.${service.key}.update_headers(headers${index === subServices.length - 1 ? "" : ".clone()"});`).join("\n")}
1955
+ }
1913
1956
  }
1914
1957
 
1915
- impl ${clientName}<'_> {
1958
+ impl ${clientName} {
1916
1959
  ${rpcParts.join("\n")}
1917
1960
  }
1918
1961
 
package/package.json CHANGED
@@ -22,10 +22,10 @@
22
22
  ],
23
23
  "dependencies": {
24
24
  "pathe": "^1.1.2",
25
- "@arrirpc/codegen-utils": "0.54.0"
25
+ "@arrirpc/codegen-utils": "0.57.0"
26
26
  },
27
27
  "devDependencies": {
28
- "@arrirpc/schema": "0.54.0"
28
+ "@arrirpc/schema": "0.57.0"
29
29
  },
30
- "version": "0.54.0"
30
+ "version": "0.57.0"
31
31
  }