Skip to main content

open_lark/
lib.rs

1//! OpenLark 官方入口 crate。
2//!
3//! 普通用户应优先使用 `openlark`,通过业务 feature 开启所需能力:
4//!
5//! ```toml
6//! [dependencies]
7//! openlark = { version = "0.16.0", default-features = false, features = ["auth", "docs-drive", "docs-bitable", "webhook-signature"] }
8//! ```
9//!
10//! - 统一客户端入口:[`Client`]
11//! - 高级业务模块入口:[`auth`]、[`communication`]、[`docs`]、[`workflow`] 等
12//! - 统一预导出:[`prelude`]
13//!
14//! 若只想要单一业务域的最小依赖,再直接使用 `openlark-{domain}` 子 crate。
15//!
16//! Canonical public API 入口规则见 `docs/PUBLIC_REEXPORT_POLICY.md`。
17//!
18//! 推荐顺序:
19//!
20//! - 运行时入口:[`Client`] / [`ClientBuilder`]
21//! - 导入入口:[`prelude`]
22//! - 业务命名空间:`open_lark::auth`、`open_lark::communication`、`open_lark::docs`
23//! - 最小依赖场景:直接依赖对应 `openlark-{domain}` crate
24//!
25//! 顶层 `AuthClient`、`DocsClient`、`HrClient` 等类型 re-export 会继续保留,
26//! 但它们的定位是 compatibility alias,而不是普通用户的主入口。
27//!
28//! 根 crate `prelude` 有意不暴露客户端实现层细节:
29//!
30//! ```rust,compile_fail
31//! use open_lark::prelude::*;
32//!
33//! let _registry: ServiceRegistry;
34//! ```
35
36// 允许测试模块中的未使用导入(测试桩代码常见模式)
37#![allow(unused_imports)]
38
39// 原始 crate-name passthrough re-export 仅用于兼容历史路径,
40// 不再作为根 crate 的推荐公开入口出现在文档中。
41#[deprecated(
42    since = "0.15.0",
43    note = "Use open_lark::{Client, ClientBuilder, prelude} or depend on openlark-client directly; open_lark::openlark_client is a legacy compatibility entrypoint."
44)]
45#[doc(hidden)]
46pub use openlark_client;
47pub use openlark_client::{Client, ClientBuilder, Config, Error, Result};
48#[deprecated(
49    since = "0.15.0",
50    note = "Use the root common types (CoreConfig, CoreError, RequestOption, SDKResult) or depend on openlark-core directly; open_lark::openlark_core is a legacy compatibility entrypoint."
51)]
52#[doc(hidden)]
53pub use openlark_core;
54#[deprecated(
55    since = "0.15.0",
56    note = "Use the root common types (CoreConfig, CoreError, RequestOption, SDKResult) or depend on openlark-core directly; open_lark::core is a legacy compatibility entrypoint."
57)]
58#[doc(hidden)]
59pub use openlark_core as core;
60pub use openlark_core::SDKResult;
61pub use openlark_core::config::Config as CoreConfig;
62pub use openlark_core::error::{CoreError, ErrorCode, ErrorSeverity, ErrorTrait, ErrorType};
63pub use openlark_core::req_option::RequestOption;
64
65#[cfg(feature = "websocket")]
66/// WebSocket 客户端相关类型导出。
67pub mod ws_client {
68    pub use openlark_client::ws_client::*;
69}
70
71#[cfg(feature = "auth")]
72#[deprecated(
73    since = "0.15.0",
74    note = "Use open_lark::auth or Client.auth for runtime access, or depend on the auth crate directly; open_lark::openlark_auth is a legacy compatibility entrypoint."
75)]
76#[doc(hidden)]
77pub use openlark_auth;
78
79#[cfg(feature = "auth")]
80pub use openlark_auth as auth;
81
82#[cfg(feature = "communication")]
83#[deprecated(
84    since = "0.15.0",
85    note = "Use open_lark::communication or Client.communication for runtime access, or depend on the communication crate directly; open_lark::openlark_communication is a legacy compatibility entrypoint."
86)]
87#[doc(hidden)]
88pub use openlark_communication;
89
90#[cfg(feature = "communication")]
91pub use openlark_communication as communication;
92
93#[cfg(any(
94    feature = "docs",
95    feature = "docs-ccm",
96    feature = "docs-base",
97    feature = "docs-bitable",
98    feature = "docs-drive",
99    feature = "docs-explorer",
100    feature = "docs-sheets",
101    feature = "docs-sheets-v2",
102    feature = "docs-sheets-v3",
103    feature = "docs-full"
104))]
105#[deprecated(
106    since = "0.15.0",
107    note = "Use open_lark::docs or Client.docs for runtime access, or depend on the docs crate directly; open_lark::openlark_docs is a legacy compatibility entrypoint."
108)]
109#[doc(hidden)]
110pub use openlark_docs;
111
112#[cfg(any(
113    feature = "docs",
114    feature = "docs-ccm",
115    feature = "docs-base",
116    feature = "docs-bitable",
117    feature = "docs-drive",
118    feature = "docs-explorer",
119    feature = "docs-sheets",
120    feature = "docs-sheets-v2",
121    feature = "docs-sheets-v3",
122    feature = "docs-full"
123))]
124pub use openlark_docs as docs;
125
126#[cfg(feature = "hr")]
127pub use openlark_hr as hr;
128
129#[cfg(feature = "ai")]
130pub use openlark_ai as ai;
131
132#[cfg(feature = "helpdesk")]
133pub use openlark_helpdesk as helpdesk;
134
135#[cfg(feature = "mail")]
136pub use openlark_mail as mail;
137
138#[cfg(feature = "meeting")]
139pub use openlark_meeting as meeting;
140
141#[cfg(feature = "application")]
142pub use openlark_application as application;
143
144#[cfg(feature = "security")]
145pub use openlark_security as security;
146
147#[cfg(feature = "workflow")]
148pub use openlark_workflow as workflow;
149
150#[cfg(feature = "platform")]
151pub use openlark_platform as platform;
152
153#[cfg(feature = "analytics")]
154pub use openlark_analytics as analytics;
155
156#[cfg(feature = "user")]
157pub use openlark_user as user;
158
159#[cfg(feature = "webhook")]
160#[deprecated(
161    since = "0.15.0",
162    note = "Use open_lark::webhook or depend on openlark-webhook directly; open_lark::openlark_webhook is a legacy compatibility entrypoint."
163)]
164#[doc(hidden)]
165pub use openlark_webhook;
166
167#[cfg(feature = "webhook")]
168pub use openlark_webhook as webhook;
169
170#[cfg(feature = "cardkit")]
171pub use openlark_cardkit as cardkit;
172
173// 顶层 meta client 类型 re-export 保留为兼容层;
174// 普通 `openlark` 用户优先通过 `Client` 字段访问业务能力。
175#[cfg(feature = "auth")]
176#[deprecated(
177    since = "0.15.0",
178    note = "Use Client.auth for runtime access, or use openlark-client / business-crate paths for explicit types; root-level *Client aliases are legacy compatibility entrypoints."
179)]
180#[doc(hidden)]
181pub use openlark_client::AuthClient;
182
183#[cfg(any(
184    feature = "docs",
185    feature = "docs-ccm",
186    feature = "docs-base",
187    feature = "docs-bitable",
188    feature = "docs-drive",
189    feature = "docs-explorer",
190    feature = "docs-sheets",
191    feature = "docs-sheets-v2",
192    feature = "docs-sheets-v3",
193    feature = "docs-full"
194))]
195#[deprecated(
196    since = "0.15.0",
197    note = "Use Client.docs for runtime access, or use openlark-client / business-crate paths for explicit types; root-level *Client aliases are legacy compatibility entrypoints."
198)]
199#[doc(hidden)]
200pub use openlark_client::DocsClient;
201
202#[cfg(feature = "communication")]
203#[deprecated(
204    since = "0.15.0",
205    note = "Use Client.communication for runtime access, or use openlark-client / business-crate paths for explicit types; root-level *Client aliases are legacy compatibility entrypoints."
206)]
207#[doc(hidden)]
208pub use openlark_client::CommunicationClient;
209
210#[cfg(feature = "hr")]
211#[deprecated(
212    since = "0.15.0",
213    note = "Use Client.hr for runtime access, or use openlark-client / business-crate paths for explicit types; root-level *Client aliases are legacy compatibility entrypoints."
214)]
215#[doc(hidden)]
216pub use openlark_client::HrClient;
217
218#[cfg(feature = "meeting")]
219#[deprecated(
220    since = "0.15.0",
221    note = "Use Client.meeting for runtime access, or use openlark-client / business-crate paths for explicit types; root-level *Client aliases are legacy compatibility entrypoints."
222)]
223#[doc(hidden)]
224pub use openlark_client::MeetingClient;
225
226#[cfg(feature = "cardkit")]
227#[deprecated(
228    since = "0.15.0",
229    note = "Use Client.cardkit for runtime access, or use openlark-client / business-crate paths for explicit types; root-level *Client aliases are legacy compatibility entrypoints."
230)]
231#[doc(hidden)]
232pub use openlark_client::CardkitClient;
233
234#[cfg(feature = "ai")]
235#[deprecated(
236    since = "0.15.0",
237    note = "Use Client.ai for runtime access, or use openlark-client / business-crate paths for explicit types; root-level *Client aliases are legacy compatibility entrypoints."
238)]
239#[doc(hidden)]
240pub use openlark_client::AiClient;
241
242#[cfg(feature = "workflow")]
243#[deprecated(
244    since = "0.15.0",
245    note = "Use Client.workflow for runtime access, or use openlark-client / business-crate paths for explicit types; root-level *Client aliases are legacy compatibility entrypoints."
246)]
247#[doc(hidden)]
248pub use openlark_client::WorkflowClient;
249
250#[cfg(feature = "platform")]
251#[deprecated(
252    since = "0.15.0",
253    note = "Use Client.platform for runtime access, or use openlark-client / business-crate paths for explicit types; root-level *Client aliases are legacy compatibility entrypoints."
254)]
255#[doc(hidden)]
256pub use openlark_client::PlatformClient;
257
258#[cfg(feature = "application")]
259#[deprecated(
260    since = "0.15.0",
261    note = "Use Client.application for runtime access, or use openlark-client / business-crate paths for explicit types; root-level *Client aliases are legacy compatibility entrypoints."
262)]
263#[doc(hidden)]
264pub use openlark_client::ApplicationClient;
265
266#[cfg(feature = "helpdesk")]
267#[deprecated(
268    since = "0.15.0",
269    note = "Use Client.helpdesk for runtime access, or use openlark-client / business-crate paths for explicit types; root-level *Client aliases are legacy compatibility entrypoints."
270)]
271#[doc(hidden)]
272pub use openlark_client::HelpdeskClient;
273
274#[cfg(feature = "mail")]
275#[deprecated(
276    since = "0.15.0",
277    note = "Use Client.mail for runtime access, or use openlark-client / business-crate paths for explicit types; root-level *Client aliases are legacy compatibility entrypoints."
278)]
279#[doc(hidden)]
280pub use openlark_client::MailClient;
281
282#[cfg(feature = "analytics")]
283#[deprecated(
284    since = "0.15.0",
285    note = "Use Client.analytics for runtime access, or use openlark-client / business-crate paths for explicit types; root-level *Client aliases are legacy compatibility entrypoints."
286)]
287#[doc(hidden)]
288pub use openlark_client::AnalyticsClient;
289
290#[cfg(feature = "user")]
291#[deprecated(
292    since = "0.15.0",
293    note = "Use Client.user for runtime access, or use openlark-client / business-crate paths for explicit types; root-level *Client aliases are legacy compatibility entrypoints."
294)]
295#[doc(hidden)]
296pub use openlark_client::UserClient;
297
298#[cfg(feature = "security")]
299#[deprecated(
300    since = "0.15.0",
301    note = "Use Client.security for runtime access, or use openlark-client / business-crate paths for explicit types; root-level *Client aliases are legacy compatibility entrypoints."
302)]
303#[doc(hidden)]
304pub use openlark_client::SecurityClient;
305
306/// 面向 `openlark` 用户的统一预导出。
307///
308/// 该模块只导出“创建客户端 + 顶层业务入口”所需的稳定公共类型。
309/// registry / feature loader / traits 等高级客户端层能力保留在 `openlark-client`。
310#[allow(deprecated)]
311pub mod prelude {
312    #[cfg(feature = "ai")]
313    #[doc(hidden)]
314    pub use crate::AiClient;
315    #[cfg(feature = "analytics")]
316    #[doc(hidden)]
317    pub use crate::AnalyticsClient;
318    #[cfg(feature = "application")]
319    #[doc(hidden)]
320    pub use crate::ApplicationClient;
321    #[cfg(feature = "auth")]
322    #[doc(hidden)]
323    pub use crate::AuthClient;
324    #[cfg(feature = "communication")]
325    #[doc(hidden)]
326    pub use crate::CommunicationClient;
327    #[cfg(any(
328        feature = "docs",
329        feature = "docs-ccm",
330        feature = "docs-base",
331        feature = "docs-bitable",
332        feature = "docs-drive",
333        feature = "docs-explorer",
334        feature = "docs-sheets",
335        feature = "docs-sheets-v2",
336        feature = "docs-sheets-v3",
337        feature = "docs-full"
338    ))]
339    #[doc(hidden)]
340    pub use crate::DocsClient;
341    #[cfg(feature = "helpdesk")]
342    #[doc(hidden)]
343    pub use crate::HelpdeskClient;
344    #[cfg(feature = "hr")]
345    #[doc(hidden)]
346    pub use crate::HrClient;
347    #[cfg(feature = "mail")]
348    #[doc(hidden)]
349    pub use crate::MailClient;
350    #[cfg(feature = "meeting")]
351    #[doc(hidden)]
352    pub use crate::MeetingClient;
353    #[cfg(feature = "platform")]
354    #[doc(hidden)]
355    pub use crate::PlatformClient;
356    pub use crate::SDKResult;
357    #[cfg(feature = "security")]
358    #[doc(hidden)]
359    pub use crate::SecurityClient;
360    #[cfg(feature = "user")]
361    #[doc(hidden)]
362    pub use crate::UserClient;
363    #[cfg(feature = "workflow")]
364    #[doc(hidden)]
365    pub use crate::WorkflowClient;
366    pub use crate::{Client, ClientBuilder, Config, CoreConfig, Error, Result};
367    pub use crate::{CoreError, ErrorCode, ErrorSeverity, ErrorTrait, ErrorType, RequestOption};
368    pub use openlark_core::prelude::*;
369}
370
371#[cfg(test)]
372mod tests {
373    use super::*;
374
375    fn build_test_client() -> Result<Client> {
376        Client::builder()
377            .app_id("test_app")
378            .app_secret("test_secret")
379            .build()
380    }
381
382    #[test]
383    fn root_prelude_exposes_canonical_core_entrypoints() {
384        use crate::prelude::*;
385
386        let _builder: ClientBuilder = Client::builder();
387        let _config: Config = Config::builder()
388            .app_id("test_app")
389            .app_secret("test_secret")
390            .build()
391            .expect("test config should build");
392        let _request_option: Option<RequestOption> = None;
393    }
394
395    #[test]
396    fn root_minimal_builder_works_without_service_features() {
397        let client = build_test_client().expect("client should build with minimal features");
398        assert_eq!(client.config().app_id, "test_app");
399    }
400
401    #[cfg(feature = "auth")]
402    #[test]
403    #[allow(deprecated)]
404    fn root_client_exposes_auth_entrypoint() {
405        let client = build_test_client().expect("client should build with auth feature");
406
407        let _auth = &client.auth;
408        let alias = std::any::type_name::<crate::AuthClient>();
409        let compat = std::any::type_name::<openlark_client::AuthClient>();
410
411        assert_eq!(alias, compat);
412    }
413
414    #[cfg(feature = "communication")]
415    #[test]
416    fn root_client_exposes_communication_namespace() {
417        let client = build_test_client().expect("client should build with communication feature");
418
419        let _communication = &client.communication;
420        let _endpoint = crate::communication::endpoints::IM_V1_MESSAGES;
421    }
422
423    #[cfg(any(
424        feature = "docs",
425        feature = "docs-ccm",
426        feature = "docs-base",
427        feature = "docs-bitable",
428        feature = "docs-drive",
429        feature = "docs-explorer",
430        feature = "docs-sheets",
431        feature = "docs-sheets-v2",
432        feature = "docs-sheets-v3",
433        feature = "docs-full"
434    ))]
435    #[test]
436    #[allow(deprecated)]
437    fn root_client_exposes_docs_namespace() {
438        let client = build_test_client().expect("client should build with docs feature");
439
440        let _docs = &client.docs;
441        let alias = std::any::type_name::<crate::DocsClient>();
442        let compat = std::any::type_name::<openlark_client::DocsClient>();
443
444        assert_eq!(alias, compat);
445    }
446
447    #[cfg(feature = "hr")]
448    #[test]
449    #[allow(deprecated)]
450    fn root_client_exposes_hr_entrypoint() {
451        let client = build_test_client().expect("client should build with hr feature");
452
453        let _hr = &client.hr;
454        let alias = std::any::type_name::<crate::HrClient>();
455        let compat = std::any::type_name::<openlark_client::HrClient>();
456
457        assert_eq!(alias, compat);
458    }
459
460    #[cfg(feature = "security")]
461    #[test]
462    #[allow(deprecated)]
463    fn root_client_exposes_security_entrypoint() {
464        let client = build_test_client().expect("client should build with security feature");
465
466        let _security = &client.security;
467        let alias = std::any::type_name::<crate::SecurityClient>();
468        let compat = std::any::type_name::<openlark_client::SecurityClient>();
469
470        assert_eq!(alias, compat);
471    }
472
473    #[cfg(feature = "docs-bitable")]
474    #[test]
475    fn root_docs_bitable_feature_exposes_query_helper() {
476        let query = crate::docs::BitableRecordQuery::new("app_token", "table_id")
477            .where_equals("状态", "进行中");
478
479        assert_eq!(query.app_token, "app_token");
480        assert_eq!(query.table_id, "table_id");
481    }
482
483    #[cfg(feature = "docs-drive")]
484    #[test]
485    fn root_docs_drive_feature_exposes_drive_helpers() {
486        let upload = crate::docs::DriveUploadFile::new("demo.txt", vec![1, 2, 3]);
487        let range = crate::docs::DriveDownloadRange::from_start(0).with_end(9);
488
489        assert_eq!(upload.file_name, "demo.txt");
490        assert_eq!(upload.size(), 3);
491        assert_eq!(range.to_header_value(), "bytes=0-9");
492    }
493
494    #[cfg(feature = "essential")]
495    #[test]
496    fn root_essential_feature_combines_docs_and_communication_paths() {
497        let client = build_test_client().expect("client should build with essential feature");
498
499        let _communication = &client.communication;
500        let _docs = &client.docs;
501        let recipient = crate::communication::MessageRecipient::open_id("ou_xxx");
502        let query = crate::docs::BitableRecordQuery::new("app_token", "table_id");
503
504        assert_eq!(recipient.receive_id, "ou_xxx");
505        assert_eq!(query.table_id, "table_id");
506    }
507
508    #[cfg(feature = "enterprise")]
509    #[test]
510    fn root_enterprise_feature_combines_quality_critical_domains() {
511        let client = build_test_client().expect("client should build with enterprise feature");
512
513        let _security = &client.security;
514        let _hr = &client.hr;
515        let _workflow = &client.workflow;
516        let action = crate::workflow::ApprovalTaskAction::new(
517            "approval_code",
518            "instance_code",
519            "ou_xxx",
520            "task_123",
521        )
522        .comment("同意");
523
524        assert_eq!(action.task_id, "task_123");
525        assert_eq!(action.comment.as_deref(), Some("同意"));
526    }
527
528    #[cfg(feature = "webhook-full")]
529    #[test]
530    fn root_webhook_full_feature_exposes_signature_and_robot_client() {
531        let client = crate::webhook::WebhookClient::new();
532        let signature = crate::webhook::common::signature::sign(1_700_000_000, "secret");
533
534        let _ = client;
535        assert!(!signature.is_empty());
536    }
537}