1#[cfg(feature = "rust")]
2use bon::Builder;
3#[cfg(feature = "node")]
4use napi_derive::napi;
5#[cfg(feature = "python")]
6use pyo3::{pyclass, pymethods};
7#[cfg(feature = "python")]
8use pyo3_stub_gen::derive::{gen_stub_pyclass, gen_stub_pymethods};
9use serde::{Deserialize, Deserializer, Serialize};
10
11fn deserialize_as_json_string<'de, D>(deserializer: D) -> Result<String, D::Error>
12where
13 D: Deserializer<'de>,
14{
15 let value = serde_json::Value::deserialize(deserializer)?;
16 serde_json::to_string(&value).map_err(serde::de::Error::custom)
17}
18
19#[cfg_attr(feature = "node", napi(string_enum))]
23#[cfg_attr(not(feature = "node"), derive(Clone))]
24#[derive(Debug, Serialize, Deserialize)]
25#[serde(rename_all = "snake_case")]
26pub enum StreamRegion {
27 UsaEast,
28 EuropeCentral,
29 AsiaEast,
30}
31
32#[cfg_attr(feature = "node", napi(string_enum))]
34#[cfg_attr(not(feature = "node"), derive(Clone))]
35#[derive(Debug, Serialize, Deserialize)]
36#[serde(rename_all = "snake_case")]
37pub enum StreamDataset {
38 Block,
39 BlockWithReceipts,
40 Transactions,
41 Logs,
42 Receipts,
43 TraceBlocks,
44 DebugTraces,
45 BlockWithReceiptsDebugTrace,
46 BlockWithReceiptsTraceBlock,
47 BlobSidecars,
48 ProgramsWithLogs,
49 Ledger,
50 Events,
51 Orders,
52 Trades,
53 BookUpdates,
54 Twap,
55 WriterActions,
56}
57
58#[cfg_attr(feature = "node", napi(string_enum))]
60#[cfg_attr(not(feature = "node"), derive(Clone))]
61#[derive(Debug, Serialize, Deserialize)]
62#[serde(rename_all = "snake_case")]
63pub enum StreamDestination {
64 Webhook,
65 S3,
66 Azure,
67 Postgres,
68 Clickhouse,
69 Snowflake,
70 Mysql,
71 Mongo,
72 Kafka,
73 Redis,
74}
75
76#[cfg_attr(feature = "node", napi(string_enum))]
78#[cfg_attr(not(feature = "node"), derive(Clone))]
79#[derive(Debug, Serialize, Deserialize)]
80#[serde(rename_all = "snake_case")]
81pub enum FilterLanguage {
82 Javascript,
83 Go,
84 Wasm,
85}
86
87#[cfg_attr(feature = "node", napi(string_enum))]
89#[cfg_attr(not(feature = "node"), derive(Clone))]
90#[derive(Debug, Serialize, Deserialize)]
91#[serde(rename_all = "snake_case")]
92pub enum StreamMetadataLocation {
93 Body,
94 Header,
95 None,
96}
97
98#[cfg_attr(feature = "node", napi(string_enum))]
100#[cfg_attr(not(feature = "node"), derive(Clone))]
101#[derive(Debug, Serialize, Deserialize)]
102#[serde(rename_all = "snake_case")]
103pub enum ProductType {
104 Stream,
105 Webhook,
106}
107
108#[cfg_attr(feature = "node", napi(string_enum))]
110#[cfg_attr(not(feature = "node"), derive(Clone))]
111#[derive(Debug, Serialize, Deserialize)]
112#[serde(rename_all = "snake_case")]
113pub enum StreamStatus {
114 Active,
115 Paused,
116 Terminated,
117 Completed,
118 Blocked,
119}
120
121#[cfg_attr(feature = "python", gen_stub_pyclass)]
128#[cfg_attr(feature = "python", pyclass(get_all, set_all))]
129#[cfg_attr(feature = "node", napi(object))]
130#[derive(Debug, Clone, Serialize, Deserialize)]
131pub struct WebhookAttributes {
132 pub url: String,
134 pub max_retry: i32,
136 pub retry_interval_sec: i32,
138 pub post_timeout_sec: i32,
140 #[serde(skip_serializing_if = "Option::is_none")]
142 pub security_token: Option<String>,
143 pub compression: String,
145}
146
147#[cfg(feature = "python")]
148#[gen_stub_pymethods]
149#[pymethods]
150impl WebhookAttributes {
151 #[new]
152 #[pyo3(signature = (url, max_retry, retry_interval_sec, post_timeout_sec, compression, security_token=None))]
153 pub fn new(
154 url: String,
155 max_retry: i32,
156 retry_interval_sec: i32,
157 post_timeout_sec: i32,
158 compression: String,
159 security_token: Option<String>,
160 ) -> Self {
161 Self {
162 url,
163 max_retry,
164 retry_interval_sec,
165 post_timeout_sec,
166 security_token,
167 compression,
168 }
169 }
170}
171
172#[cfg_attr(feature = "python", gen_stub_pyclass)]
174#[cfg_attr(feature = "python", pyclass(get_all, set_all))]
175#[cfg_attr(feature = "node", napi(object))]
176#[derive(Debug, Clone, Serialize, Deserialize)]
177pub struct S3Attributes {
178 pub endpoint: String,
180 pub access_key: String,
182 pub secret_key: String,
184 pub bucket: String,
186 pub object_prefix: String,
188 pub compression: String,
190 pub file_type: String,
192 pub max_retry: i32,
194 pub retry_interval_sec: i32,
196 #[serde(skip_serializing_if = "Option::is_none")]
198 pub use_ssl: Option<bool>,
199}
200
201#[cfg(feature = "python")]
202#[gen_stub_pymethods]
203#[pymethods]
204impl S3Attributes {
205 #[new]
206 #[allow(clippy::too_many_arguments)]
207 #[pyo3(signature = (endpoint, access_key, secret_key, bucket, object_prefix, compression, file_type, max_retry, retry_interval_sec, use_ssl=None))]
208 pub fn new(
209 endpoint: String,
210 access_key: String,
211 secret_key: String,
212 bucket: String,
213 object_prefix: String,
214 compression: String,
215 file_type: String,
216 max_retry: i32,
217 retry_interval_sec: i32,
218 use_ssl: Option<bool>,
219 ) -> Self {
220 Self {
221 endpoint,
222 access_key,
223 secret_key,
224 bucket,
225 object_prefix,
226 compression,
227 file_type,
228 max_retry,
229 retry_interval_sec,
230 use_ssl,
231 }
232 }
233}
234
235#[cfg_attr(feature = "python", gen_stub_pyclass)]
237#[cfg_attr(feature = "python", pyclass(get_all, set_all))]
238#[cfg_attr(feature = "node", napi(object))]
239#[derive(Debug, Clone, Serialize, Deserialize)]
240pub struct AzureAttributes {
241 pub storage_account: String,
243 pub sas_token: String,
245 pub container: String,
247 pub compression: String,
249 pub file_type: String,
251 pub max_retry: i32,
253 pub retry_interval_sec: i32,
255 #[serde(skip_serializing_if = "Option::is_none")]
257 pub blob_prefix: Option<String>,
258}
259
260#[cfg(feature = "python")]
261#[gen_stub_pymethods]
262#[pymethods]
263impl AzureAttributes {
264 #[new]
265 #[allow(clippy::too_many_arguments)]
266 #[pyo3(signature = (storage_account, sas_token, container, compression, file_type, max_retry, retry_interval_sec, blob_prefix=None))]
267 pub fn new(
268 storage_account: String,
269 sas_token: String,
270 container: String,
271 compression: String,
272 file_type: String,
273 max_retry: i32,
274 retry_interval_sec: i32,
275 blob_prefix: Option<String>,
276 ) -> Self {
277 Self {
278 storage_account,
279 sas_token,
280 container,
281 compression,
282 file_type,
283 max_retry,
284 retry_interval_sec,
285 blob_prefix,
286 }
287 }
288}
289
290#[cfg_attr(feature = "python", gen_stub_pyclass)]
292#[cfg_attr(feature = "python", pyclass(get_all, set_all))]
293#[cfg_attr(feature = "node", napi(object))]
294#[derive(Debug, Clone, Serialize, Deserialize)]
295pub struct PostgresAttributes {
296 pub host: String,
298 pub port: i32,
300 pub database: String,
302 pub username: String,
304 pub password: String,
306 pub table_name: String,
308 pub sslmode: String,
310 pub max_retry: i32,
312 pub retry_interval_sec: i32,
314}
315
316#[cfg(feature = "python")]
317#[gen_stub_pymethods]
318#[pymethods]
319impl PostgresAttributes {
320 #[new]
321 #[allow(clippy::too_many_arguments)]
322 pub fn new(
323 host: String,
324 port: i32,
325 database: String,
326 username: String,
327 password: String,
328 table_name: String,
329 sslmode: String,
330 max_retry: i32,
331 retry_interval_sec: i32,
332 ) -> Self {
333 Self {
334 host,
335 port,
336 database,
337 username,
338 password,
339 table_name,
340 sslmode,
341 max_retry,
342 retry_interval_sec,
343 }
344 }
345}
346
347#[cfg_attr(feature = "python", gen_stub_pyclass)]
349#[cfg_attr(feature = "python", pyclass(get_all, set_all))]
350#[cfg_attr(feature = "node", napi(object))]
351#[derive(Debug, Clone, Serialize, Deserialize)]
352pub struct MysqlAttributes {
353 pub host: String,
355 pub port: i32,
357 pub database: String,
359 pub username: String,
361 pub password: String,
363 pub table_name: String,
365 pub max_retry: i32,
367 pub retry_interval_sec: i32,
369}
370
371#[cfg(feature = "python")]
372#[gen_stub_pymethods]
373#[pymethods]
374impl MysqlAttributes {
375 #[new]
376 #[allow(clippy::too_many_arguments)]
377 pub fn new(
378 host: String,
379 port: i32,
380 database: String,
381 username: String,
382 password: String,
383 table_name: String,
384 max_retry: i32,
385 retry_interval_sec: i32,
386 ) -> Self {
387 Self {
388 host,
389 port,
390 database,
391 username,
392 password,
393 table_name,
394 max_retry,
395 retry_interval_sec,
396 }
397 }
398}
399
400#[cfg_attr(feature = "python", gen_stub_pyclass)]
402#[cfg_attr(feature = "python", pyclass(get_all, set_all))]
403#[cfg_attr(feature = "node", napi(object))]
404#[derive(Debug, Clone, Serialize, Deserialize)]
405pub struct MongoAttributes {
406 pub host: String,
408 pub database: String,
410 pub username: String,
412 pub password: String,
414 pub collection_name: String,
416 pub max_retry: i32,
418 pub retry_interval_sec: i32,
420}
421
422#[cfg(feature = "python")]
423#[gen_stub_pymethods]
424#[pymethods]
425impl MongoAttributes {
426 #[new]
427 pub fn new(
428 host: String,
429 database: String,
430 username: String,
431 password: String,
432 collection_name: String,
433 max_retry: i32,
434 retry_interval_sec: i32,
435 ) -> Self {
436 Self {
437 host,
438 database,
439 username,
440 password,
441 collection_name,
442 max_retry,
443 retry_interval_sec,
444 }
445 }
446}
447
448#[cfg_attr(feature = "python", gen_stub_pyclass)]
450#[cfg_attr(feature = "python", pyclass(get_all, set_all))]
451#[cfg_attr(feature = "node", napi(object))]
452#[derive(Debug, Clone, Serialize, Deserialize)]
453pub struct ClickhouseAttributes {
454 pub hosts: String,
456 pub database: String,
458 pub username: String,
460 pub password: String,
462 pub table_name: String,
464 pub default_table_engine_opts: String,
466 pub default_granularity: i32,
468 pub default_compression: String,
470 pub default_index_type: String,
472 pub max_retry: i32,
474 pub retry_interval_sec: i32,
476 #[serde(skip_serializing_if = "Option::is_none")]
478 pub disable_datetime_precision: Option<bool>,
479 #[serde(skip_serializing_if = "Option::is_none")]
481 pub dont_support_rename_column: Option<bool>,
482 #[serde(skip_serializing_if = "Option::is_none")]
484 pub dont_support_empty_default_value: Option<bool>,
485 #[serde(skip_serializing_if = "Option::is_none")]
487 pub skip_initialize_with_version: Option<bool>,
488}
489
490#[cfg(feature = "python")]
491#[gen_stub_pymethods]
492#[pymethods]
493impl ClickhouseAttributes {
494 #[new]
495 #[pyo3(signature = (hosts, database, username, password, table_name, default_table_engine_opts, default_granularity, default_compression, default_index_type, max_retry, retry_interval_sec, disable_datetime_precision=None, dont_support_rename_column=None, dont_support_empty_default_value=None, skip_initialize_with_version=None))]
496 #[allow(clippy::too_many_arguments)]
497 pub fn new(
498 hosts: String,
499 database: String,
500 username: String,
501 password: String,
502 table_name: String,
503 default_table_engine_opts: String,
504 default_granularity: i32,
505 default_compression: String,
506 default_index_type: String,
507 max_retry: i32,
508 retry_interval_sec: i32,
509 disable_datetime_precision: Option<bool>,
510 dont_support_rename_column: Option<bool>,
511 dont_support_empty_default_value: Option<bool>,
512 skip_initialize_with_version: Option<bool>,
513 ) -> Self {
514 Self {
515 hosts,
516 database,
517 username,
518 password,
519 table_name,
520 default_table_engine_opts,
521 default_granularity,
522 default_compression,
523 default_index_type,
524 max_retry,
525 retry_interval_sec,
526 disable_datetime_precision,
527 dont_support_rename_column,
528 dont_support_empty_default_value,
529 skip_initialize_with_version,
530 }
531 }
532}
533
534#[cfg_attr(feature = "python", gen_stub_pyclass)]
536#[cfg_attr(feature = "python", pyclass(get_all, set_all))]
537#[cfg_attr(feature = "node", napi(object))]
538#[derive(Debug, Clone, Serialize, Deserialize)]
539pub struct SnowflakeAttributes {
540 pub account: String,
542 pub host: String,
544 pub port: i32,
546 pub protocol: String,
548 pub database: String,
550 pub schema: String,
552 pub warehouse: String,
554 pub username: String,
556 pub password: String,
558 pub max_retry: i32,
560 pub retry_interval_sec: i32,
562 #[serde(skip_serializing_if = "Option::is_none")]
564 pub table_name: Option<String>,
565}
566
567#[cfg(feature = "python")]
568#[gen_stub_pymethods]
569#[pymethods]
570impl SnowflakeAttributes {
571 #[new]
572 #[pyo3(signature = (account, host, port, protocol, database, schema, warehouse, username, password, max_retry, retry_interval_sec, table_name=None))]
573 #[allow(clippy::too_many_arguments)]
574 pub fn new(
575 account: String,
576 host: String,
577 port: i32,
578 protocol: String,
579 database: String,
580 schema: String,
581 warehouse: String,
582 username: String,
583 password: String,
584 max_retry: i32,
585 retry_interval_sec: i32,
586 table_name: Option<String>,
587 ) -> Self {
588 Self {
589 account,
590 host,
591 port,
592 protocol,
593 database,
594 schema,
595 warehouse,
596 username,
597 password,
598 max_retry,
599 retry_interval_sec,
600 table_name,
601 }
602 }
603}
604
605#[cfg_attr(feature = "python", gen_stub_pyclass)]
607#[cfg_attr(feature = "python", pyclass(get_all, set_all))]
608#[cfg_attr(feature = "node", napi(object))]
609#[derive(Debug, Clone, Serialize, Deserialize)]
610pub struct KafkaAttributes {
611 pub bootstrap_servers: String,
613 pub topic_name: String,
615 pub compression_type: String,
617 pub batch_size: i32,
619 pub linger_ms: i32,
621 pub max_request_size: i32,
623 pub timeout_sec: i32,
625 pub max_retry: i32,
627 pub retry_interval_sec: i32,
629 #[serde(skip_serializing_if = "Option::is_none")]
631 pub username: Option<String>,
632 #[serde(skip_serializing_if = "Option::is_none")]
634 pub password: Option<String>,
635 #[serde(skip_serializing_if = "Option::is_none")]
637 pub protocol: Option<String>,
638 #[serde(skip_serializing_if = "Option::is_none")]
640 pub mechanisms: Option<String>,
641}
642
643#[cfg(feature = "python")]
644#[gen_stub_pymethods]
645#[pymethods]
646impl KafkaAttributes {
647 #[new]
648 #[pyo3(signature = (bootstrap_servers, topic_name, compression_type, batch_size, linger_ms, max_request_size, timeout_sec, max_retry, retry_interval_sec, username=None, password=None, protocol=None, mechanisms=None))]
649 #[allow(clippy::too_many_arguments)]
650 pub fn new(
651 bootstrap_servers: String,
652 topic_name: String,
653 compression_type: String,
654 batch_size: i32,
655 linger_ms: i32,
656 max_request_size: i32,
657 timeout_sec: i32,
658 max_retry: i32,
659 retry_interval_sec: i32,
660 username: Option<String>,
661 password: Option<String>,
662 protocol: Option<String>,
663 mechanisms: Option<String>,
664 ) -> Self {
665 Self {
666 bootstrap_servers,
667 topic_name,
668 compression_type,
669 batch_size,
670 linger_ms,
671 max_request_size,
672 timeout_sec,
673 max_retry,
674 retry_interval_sec,
675 username,
676 password,
677 protocol,
678 mechanisms,
679 }
680 }
681}
682
683#[cfg_attr(feature = "python", gen_stub_pyclass)]
685#[cfg_attr(feature = "python", pyclass(get_all, set_all))]
686#[cfg_attr(feature = "node", napi(object))]
687#[derive(Debug, Clone, Serialize, Deserialize)]
688pub struct RedisAttributes {
689 pub host: String,
691 pub port: i32,
693 pub database: i32,
695 pub username: String,
697 pub password: String,
699 pub key_name: String,
701 pub max_retry: i32,
703 pub retry_interval_sec: i32,
705 #[serde(skip_serializing_if = "Option::is_none")]
707 pub tls: Option<bool>,
708}
709
710#[cfg(feature = "python")]
711#[gen_stub_pymethods]
712#[pymethods]
713impl RedisAttributes {
714 #[new]
715 #[pyo3(signature = (host, port, database, username, password, key_name, max_retry, retry_interval_sec, tls=None))]
716 #[allow(clippy::too_many_arguments)]
717 pub fn new(
718 host: String,
719 port: i32,
720 database: i32,
721 username: String,
722 password: String,
723 key_name: String,
724 max_retry: i32,
725 retry_interval_sec: i32,
726 tls: Option<bool>,
727 ) -> Self {
728 Self {
729 host,
730 port,
731 database,
732 username,
733 password,
734 key_name,
735 max_retry,
736 retry_interval_sec,
737 tls,
738 }
739 }
740}
741
742#[cfg_attr(feature = "python", gen_stub_pyclass)]
747#[cfg_attr(feature = "python", pyclass(get_all, set_all))]
748#[cfg_attr(feature = "node", napi(object))]
749#[derive(Debug, Clone, Serialize, Deserialize)]
750pub struct AddressBookConfig {
751 pub address_book_id: String,
753 #[serde(skip_serializing_if = "Option::is_none")]
755 pub objects_filter_path: Option<String>,
756 pub elements_filter_paths: Vec<String>,
758}
759
760#[cfg(feature = "python")]
761#[gen_stub_pymethods]
762#[pymethods]
763impl AddressBookConfig {
764 #[new]
765 #[pyo3(signature = (address_book_id, elements_filter_paths, objects_filter_path=None))]
766 pub fn new(
767 address_book_id: String,
768 elements_filter_paths: Vec<String>,
769 objects_filter_path: Option<String>,
770 ) -> Self {
771 Self {
772 address_book_id,
773 objects_filter_path,
774 elements_filter_paths,
775 }
776 }
777}
778
779#[derive(Debug, Clone, Serialize, Deserialize)]
789#[serde(
790 tag = "destination",
791 content = "destination_attributes",
792 rename_all = "snake_case"
793)]
794pub enum DestinationAttributes {
795 Webhook(WebhookAttributes),
797 S3(S3Attributes),
799 Azure(AzureAttributes),
801 Postgres(PostgresAttributes),
803 Mysql(MysqlAttributes),
805 Mongo(MongoAttributes),
807 Clickhouse(ClickhouseAttributes),
809 Snowflake(SnowflakeAttributes),
811 Kafka(KafkaAttributes),
813 Redis(RedisAttributes),
815}
816
817impl DestinationAttributes {
818 pub fn tag(&self) -> StreamDestination {
819 match self {
820 Self::Webhook(_) => StreamDestination::Webhook,
821 Self::S3(_) => StreamDestination::S3,
822 Self::Azure(_) => StreamDestination::Azure,
823 Self::Postgres(_) => StreamDestination::Postgres,
824 Self::Mysql(_) => StreamDestination::Mysql,
825 Self::Mongo(_) => StreamDestination::Mongo,
826 Self::Clickhouse(_) => StreamDestination::Clickhouse,
827 Self::Snowflake(_) => StreamDestination::Snowflake,
828 Self::Kafka(_) => StreamDestination::Kafka,
829 Self::Redis(_) => StreamDestination::Redis,
830 }
831 }
832}
833
834#[cfg_attr(feature = "rust", derive(Builder))]
838#[derive(Debug, Clone, Serialize, Deserialize)]
839pub struct CreateStreamParams {
840 pub name: String,
842 pub region: StreamRegion,
844 pub network: String,
846 pub dataset: StreamDataset,
848 pub start_range: i64,
850 pub end_range: i64,
852 #[serde(flatten)]
855 pub destination_attributes: DestinationAttributes,
856 pub plan: String,
858 pub threshold_fetch_buffer: i64,
860 #[serde(skip_serializing_if = "Option::is_none")]
862 pub dataset_batch_size: Option<i64>,
863 #[serde(skip_serializing_if = "Option::is_none")]
865 pub max_batch_size: Option<i64>,
866 #[serde(skip_serializing_if = "Option::is_none")]
868 pub max_buffer_range_size: Option<i64>,
869 #[serde(skip_serializing_if = "Option::is_none")]
871 pub max_buffer_processing_workers: Option<i64>,
872 #[serde(skip_serializing_if = "Option::is_none")]
874 pub keep_distance_from_tip: Option<i64>,
875 #[serde(skip_serializing_if = "Option::is_none")]
877 pub filter_function: Option<String>,
878 #[serde(skip_serializing_if = "Option::is_none")]
880 pub filter_language: Option<FilterLanguage>,
881 #[serde(skip_serializing_if = "Option::is_none")]
883 pub address_book_config: Option<AddressBookConfig>,
884 #[serde(skip_serializing_if = "Option::is_none")]
886 pub include_stream_metadata: Option<StreamMetadataLocation>,
887 #[serde(skip_serializing_if = "Option::is_none")]
889 pub product_type: Option<ProductType>,
890 #[serde(skip_serializing_if = "Option::is_none")]
892 pub status: Option<StreamStatus>,
893 #[serde(skip_serializing_if = "Option::is_none")]
895 pub notification_email: Option<String>,
896 #[serde(skip_serializing_if = "Option::is_none")]
898 pub charge_min_cap: Option<i32>,
899 #[serde(skip_serializing_if = "Option::is_none")]
901 pub fix_block_reorgs: Option<i32>,
902 #[serde(skip_serializing_if = "Option::is_none")]
904 pub elastic_batch_enabled: Option<bool>,
905 #[serde(skip_serializing_if = "Option::is_none")]
908 pub extra_destinations: Option<Vec<DestinationAttributes>>,
909}
910
911#[derive(Debug, Clone, Serialize, Deserialize)]
915pub struct Stream {
916 pub id: String,
918 pub name: String,
920 pub status: String,
922 pub created_at: String,
924 pub updated_at: String,
926 pub sequence: i64,
928 pub network: String,
930 pub dataset: String,
932 pub region: String,
934 pub start_range: i64,
936 pub end_range: i64,
938 #[serde(skip_serializing_if = "Option::is_none")]
940 pub plan: Option<String>,
941 #[serde(skip_serializing_if = "Option::is_none")]
943 pub threshold_fetch_buffer: Option<i64>,
944 #[serde(skip_serializing_if = "Option::is_none")]
946 pub dataset_batch_size: Option<i64>,
947 #[serde(skip_serializing_if = "Option::is_none")]
949 pub max_batch_size: Option<i64>,
950 #[serde(skip_serializing_if = "Option::is_none")]
952 pub max_buffer_range_size: Option<i64>,
953 #[serde(skip_serializing_if = "Option::is_none")]
955 pub max_buffer_processing_workers: Option<i64>,
956 #[serde(skip_serializing_if = "Option::is_none")]
958 pub keep_distance_from_tip: Option<i64>,
959 #[serde(skip_serializing_if = "Option::is_none")]
961 pub filter_function: Option<String>,
962 #[serde(skip_serializing_if = "Option::is_none")]
964 pub filter_language: Option<String>,
965 #[serde(skip_serializing_if = "Option::is_none")]
967 pub include_stream_metadata: Option<String>,
968 #[serde(skip_serializing_if = "Option::is_none")]
970 pub product_type: Option<String>,
971 #[serde(skip_serializing_if = "Option::is_none")]
973 pub notification_email: Option<String>,
974 #[serde(skip_serializing_if = "Option::is_none")]
976 pub fix_block_reorgs: Option<i32>,
977 #[serde(skip_serializing_if = "Option::is_none")]
979 pub current_hash: Option<String>,
980 #[serde(flatten, default, skip_serializing_if = "Option::is_none")]
983 pub destination_attributes: Option<DestinationAttributes>,
984 #[serde(skip_serializing_if = "Option::is_none")]
986 pub elastic_batch_enabled: Option<bool>,
987 #[serde(skip_serializing_if = "Option::is_none")]
989 pub qn_account_id: Option<String>,
990 #[serde(skip_serializing_if = "Option::is_none")]
992 pub charge_min_cap: Option<i32>,
993 #[serde(skip_serializing_if = "Option::is_none")]
995 pub memo: Option<String>,
996 #[serde(skip_serializing_if = "Option::is_none")]
998 pub address_book_config: Option<AddressBookConfig>,
999 #[serde(default, skip_serializing_if = "Option::is_none")]
1001 pub extra_destinations: Option<Vec<DestinationAttributes>>,
1002}
1003
1004#[cfg_attr(feature = "python", gen_stub_pyclass)]
1008#[cfg_attr(feature = "python", pyclass(get_all, set_all))]
1009#[cfg_attr(feature = "node", napi(object))]
1010#[derive(Debug, Clone, Serialize, Deserialize)]
1011pub struct PageInfo {
1012 pub limit: i64,
1014 pub offset: i64,
1016 pub total: i64,
1018}
1019
1020#[derive(Debug, Clone, Serialize, Deserialize)]
1022pub struct ListStreamsResponse {
1023 pub data: Vec<Stream>,
1025 #[serde(rename = "pageInfo")]
1027 pub page_info: PageInfo,
1028}
1029
1030#[cfg_attr(feature = "node", napi(object))]
1032#[cfg_attr(not(feature = "node"), derive(Clone))]
1033#[derive(Debug, Default, Serialize, Deserialize)]
1034pub struct ListStreamsParams {
1035 #[serde(skip_serializing_if = "Option::is_none")]
1037 pub stream_type: Option<String>,
1038 #[serde(skip_serializing_if = "Option::is_none")]
1040 pub offset: Option<i64>,
1041 #[serde(skip_serializing_if = "Option::is_none")]
1043 pub limit: Option<i64>,
1044 #[serde(skip_serializing_if = "Option::is_none")]
1046 pub order_by: Option<String>,
1047 #[serde(skip_serializing_if = "Option::is_none")]
1049 pub order_direction: Option<String>,
1050}
1051
1052#[derive(Debug, Default, Clone, Serialize, Deserialize)]
1055pub struct UpdateStreamParams {
1056 #[serde(skip_serializing_if = "Option::is_none")]
1058 pub name: Option<String>,
1059 #[serde(skip_serializing_if = "Option::is_none")]
1061 pub region: Option<StreamRegion>,
1062 #[serde(skip_serializing_if = "Option::is_none")]
1064 pub network: Option<String>,
1065 #[serde(skip_serializing_if = "Option::is_none")]
1067 pub dataset: Option<StreamDataset>,
1068 #[serde(skip_serializing_if = "Option::is_none")]
1070 pub start_range: Option<i64>,
1071 #[serde(skip_serializing_if = "Option::is_none")]
1073 pub end_range: Option<i64>,
1074 #[serde(flatten, skip_serializing_if = "Option::is_none")]
1077 pub destination_attributes: Option<DestinationAttributes>,
1078 #[serde(skip_serializing_if = "Option::is_none")]
1080 pub plan: Option<String>,
1081 #[serde(skip_serializing_if = "Option::is_none")]
1083 pub threshold_fetch_buffer: Option<i64>,
1084 #[serde(skip_serializing_if = "Option::is_none")]
1086 pub dataset_batch_size: Option<i64>,
1087 #[serde(skip_serializing_if = "Option::is_none")]
1089 pub max_batch_size: Option<i64>,
1090 #[serde(skip_serializing_if = "Option::is_none")]
1092 pub max_buffer_range_size: Option<i64>,
1093 #[serde(skip_serializing_if = "Option::is_none")]
1095 pub max_buffer_processing_workers: Option<i64>,
1096 #[serde(skip_serializing_if = "Option::is_none")]
1098 pub keep_distance_from_tip: Option<i64>,
1099 #[serde(skip_serializing_if = "Option::is_none")]
1101 pub filter_function: Option<String>,
1102 #[serde(skip_serializing_if = "Option::is_none")]
1104 pub filter_language: Option<FilterLanguage>,
1105 #[serde(skip_serializing_if = "Option::is_none")]
1107 pub address_book_config: Option<AddressBookConfig>,
1108 #[serde(skip_serializing_if = "Option::is_none")]
1110 pub include_stream_metadata: Option<StreamMetadataLocation>,
1111 #[serde(skip_serializing_if = "Option::is_none")]
1113 pub notification_email: Option<String>,
1114 #[serde(skip_serializing_if = "Option::is_none")]
1116 pub charge_min_cap: Option<i32>,
1117 #[serde(skip_serializing_if = "Option::is_none")]
1119 pub fix_block_reorgs: Option<i32>,
1120 #[serde(skip_serializing_if = "Option::is_none")]
1122 pub elastic_batch_enabled: Option<bool>,
1123 #[serde(skip_serializing_if = "Option::is_none")]
1125 pub status: Option<StreamStatus>,
1126 #[serde(skip_serializing_if = "Option::is_none")]
1128 pub memo: Option<String>,
1129 #[serde(skip_serializing_if = "Option::is_none")]
1131 pub extra_destinations: Option<Vec<DestinationAttributes>>,
1132}
1133
1134#[cfg_attr(feature = "node", napi(object))]
1136#[cfg_attr(not(feature = "node"), derive(Clone))]
1137#[derive(Debug, Serialize, Deserialize)]
1138pub struct TestFilterParams {
1139 pub network: String,
1141 pub dataset: StreamDataset,
1143 pub block: String,
1145 #[serde(skip_serializing_if = "Option::is_none")]
1147 pub filter_function: Option<String>,
1148 #[serde(skip_serializing_if = "Option::is_none")]
1150 pub filter_language: Option<FilterLanguage>,
1151 #[serde(skip_serializing_if = "Option::is_none")]
1153 pub address_book_config: Option<AddressBookConfig>,
1154}
1155
1156#[cfg_attr(feature = "python", gen_stub_pyclass)]
1158#[cfg_attr(feature = "python", pyclass(get_all, set_all))]
1159#[cfg_attr(feature = "node", napi(object))]
1160#[derive(Debug, Clone, Serialize, Deserialize)]
1161pub struct TestFilterResponse {
1162 #[serde(deserialize_with = "deserialize_as_json_string")]
1164 pub result: String,
1165 pub logs: Vec<String>,
1167}
1168
1169#[cfg_attr(feature = "python", gen_stub_pyclass)]
1171#[cfg_attr(feature = "python", pyclass(get_all, set_all))]
1172#[cfg_attr(feature = "node", napi(object))]
1173#[derive(Debug, Clone, Serialize, Deserialize)]
1174pub struct EnabledCountResponse {
1175 pub total: i64,
1177}
1178
1179#[cfg(test)]
1180#[allow(clippy::unwrap_used)]
1181mod destination_attributes_tests {
1182 use super::*;
1183
1184 #[test]
1185 fn webhook_roundtrip() {
1186 let attrs = DestinationAttributes::Webhook(WebhookAttributes {
1187 url: "https://x.example/hook".to_string(),
1188 max_retry: 3,
1189 retry_interval_sec: 5,
1190 post_timeout_sec: 10,
1191 compression: "none".to_string(),
1192 security_token: None,
1193 });
1194 let json = serde_json::to_string(&attrs).unwrap();
1195 assert!(json.contains(r#""destination":"webhook""#));
1196 assert!(json.contains(r#""url":"https://x.example/hook""#));
1197 let parsed: DestinationAttributes = serde_json::from_str(&json).unwrap();
1198 assert!(matches!(parsed, DestinationAttributes::Webhook(_)));
1199 assert!(matches!(parsed.tag(), StreamDestination::Webhook));
1200 }
1201
1202 #[test]
1203 fn s3_roundtrip() {
1204 let attrs = DestinationAttributes::S3(S3Attributes {
1205 endpoint: "s3.amazonaws.com".to_string(),
1206 access_key: "AK".to_string(),
1207 secret_key: "SK".to_string(),
1208 bucket: "b".to_string(),
1209 object_prefix: "p".to_string(),
1210 compression: "none".to_string(),
1211 file_type: "json".to_string(),
1212 max_retry: 3,
1213 retry_interval_sec: 5,
1214 use_ssl: Some(true),
1215 });
1216 let json = serde_json::to_string(&attrs).unwrap();
1217 assert!(json.contains(r#""destination":"s3""#));
1218 let parsed: DestinationAttributes = serde_json::from_str(&json).unwrap();
1219 assert!(matches!(parsed, DestinationAttributes::S3(_)));
1220 }
1221
1222 #[test]
1223 fn azure_roundtrip() {
1224 let attrs = DestinationAttributes::Azure(AzureAttributes {
1225 storage_account: "acct".to_string(),
1226 sas_token: "tok".to_string(),
1227 container: "c".to_string(),
1228 compression: "none".to_string(),
1229 file_type: "json".to_string(),
1230 max_retry: 3,
1231 retry_interval_sec: 5,
1232 blob_prefix: None,
1233 });
1234 let json = serde_json::to_string(&attrs).unwrap();
1235 assert!(json.contains(r#""destination":"azure""#));
1236 let parsed: DestinationAttributes = serde_json::from_str(&json).unwrap();
1237 assert!(matches!(parsed, DestinationAttributes::Azure(_)));
1238 }
1239
1240 #[test]
1241 fn postgres_roundtrip() {
1242 let attrs = DestinationAttributes::Postgres(PostgresAttributes {
1243 host: "h".to_string(),
1244 port: 5432,
1245 database: "db".to_string(),
1246 username: "u".to_string(),
1247 password: "p".to_string(),
1248 table_name: "t".to_string(),
1249 sslmode: "disable".to_string(),
1250 max_retry: 3,
1251 retry_interval_sec: 5,
1252 });
1253 let json = serde_json::to_string(&attrs).unwrap();
1254 assert!(json.contains(r#""destination":"postgres""#));
1255 let parsed: DestinationAttributes = serde_json::from_str(&json).unwrap();
1256 assert!(matches!(parsed, DestinationAttributes::Postgres(_)));
1257 }
1258
1259 #[test]
1260 fn mysql_roundtrip() {
1261 let attrs = DestinationAttributes::Mysql(MysqlAttributes {
1262 host: "h".to_string(),
1263 port: 3306,
1264 database: "db".to_string(),
1265 username: "u".to_string(),
1266 password: "p".to_string(),
1267 table_name: "t".to_string(),
1268 max_retry: 3,
1269 retry_interval_sec: 5,
1270 });
1271 let json = serde_json::to_string(&attrs).unwrap();
1272 assert!(json.contains(r#""destination":"mysql""#));
1273 let parsed: DestinationAttributes = serde_json::from_str(&json).unwrap();
1274 assert!(matches!(parsed, DestinationAttributes::Mysql(_)));
1275 }
1276
1277 #[test]
1278 fn mongo_roundtrip() {
1279 let attrs = DestinationAttributes::Mongo(MongoAttributes {
1280 host: "h".to_string(),
1281 database: "db".to_string(),
1282 username: "u".to_string(),
1283 password: "p".to_string(),
1284 collection_name: "c".to_string(),
1285 max_retry: 3,
1286 retry_interval_sec: 5,
1287 });
1288 let json = serde_json::to_string(&attrs).unwrap();
1289 assert!(json.contains(r#""destination":"mongo""#));
1290 let parsed: DestinationAttributes = serde_json::from_str(&json).unwrap();
1291 assert!(matches!(parsed, DestinationAttributes::Mongo(_)));
1292 }
1293
1294 #[test]
1295 fn clickhouse_roundtrip() {
1296 let attrs = DestinationAttributes::Clickhouse(ClickhouseAttributes {
1297 hosts: "h".to_string(),
1298 database: "db".to_string(),
1299 username: "u".to_string(),
1300 password: "p".to_string(),
1301 table_name: "t".to_string(),
1302 default_table_engine_opts: "()".to_string(),
1303 default_granularity: 8192,
1304 default_compression: "lz4".to_string(),
1305 default_index_type: "minmax".to_string(),
1306 max_retry: 3,
1307 retry_interval_sec: 5,
1308 disable_datetime_precision: None,
1309 dont_support_rename_column: None,
1310 dont_support_empty_default_value: None,
1311 skip_initialize_with_version: None,
1312 });
1313 let json = serde_json::to_string(&attrs).unwrap();
1314 assert!(json.contains(r#""destination":"clickhouse""#));
1315 let parsed: DestinationAttributes = serde_json::from_str(&json).unwrap();
1316 assert!(matches!(parsed, DestinationAttributes::Clickhouse(_)));
1317 }
1318
1319 #[test]
1320 fn snowflake_roundtrip() {
1321 let attrs = DestinationAttributes::Snowflake(SnowflakeAttributes {
1322 account: "acct".to_string(),
1323 host: "h".to_string(),
1324 port: 443,
1325 protocol: "https".to_string(),
1326 database: "db".to_string(),
1327 schema: "s".to_string(),
1328 warehouse: "w".to_string(),
1329 username: "u".to_string(),
1330 password: "p".to_string(),
1331 max_retry: 3,
1332 retry_interval_sec: 5,
1333 table_name: Some("t".to_string()),
1334 });
1335 let json = serde_json::to_string(&attrs).unwrap();
1336 assert!(json.contains(r#""destination":"snowflake""#));
1337 let parsed: DestinationAttributes = serde_json::from_str(&json).unwrap();
1338 assert!(matches!(parsed, DestinationAttributes::Snowflake(_)));
1339 }
1340
1341 #[test]
1342 fn kafka_roundtrip() {
1343 let attrs = DestinationAttributes::Kafka(KafkaAttributes {
1344 bootstrap_servers: "host:9092".to_string(),
1345 topic_name: "t".to_string(),
1346 compression_type: "gzip".to_string(),
1347 batch_size: 100,
1348 linger_ms: 10,
1349 max_request_size: 1024,
1350 timeout_sec: 30,
1351 max_retry: 3,
1352 retry_interval_sec: 5,
1353 username: None,
1354 password: None,
1355 protocol: None,
1356 mechanisms: None,
1357 });
1358 let json = serde_json::to_string(&attrs).unwrap();
1359 assert!(json.contains(r#""destination":"kafka""#));
1360 let parsed: DestinationAttributes = serde_json::from_str(&json).unwrap();
1361 assert!(matches!(parsed, DestinationAttributes::Kafka(_)));
1362 }
1363
1364 #[test]
1365 fn redis_roundtrip() {
1366 let attrs = DestinationAttributes::Redis(RedisAttributes {
1367 host: "h".to_string(),
1368 port: 6379,
1369 database: 0,
1370 username: "u".to_string(),
1371 password: "p".to_string(),
1372 key_name: "k".to_string(),
1373 max_retry: 3,
1374 retry_interval_sec: 5,
1375 tls: Some(false),
1376 });
1377 let json = serde_json::to_string(&attrs).unwrap();
1378 assert!(json.contains(r#""destination":"redis""#));
1379 let parsed: DestinationAttributes = serde_json::from_str(&json).unwrap();
1380 assert!(matches!(parsed, DestinationAttributes::Redis(_)));
1381 }
1382}