orb_billing/client/plans.rs
1// Copyright Materialize, Inc. All rights reserved.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License in the LICENSE file at the
6// root of this repository, or online at
7//
8// http://www.apache.org/licenses/LICENSE-2.0
9//
10// Unless required by applicable law or agreed to in writing, software
11// distributed under the License is distributed on an "AS IS" BASIS,
12// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13// See the License for the specific language governing permissions and
14// limitations under the License.
15
16use std::collections::BTreeMap;
17
18use futures_core::Stream;
19use reqwest::Method;
20use serde::{Deserialize, Serialize};
21use time::OffsetDateTime;
22
23use crate::client::Client;
24use crate::config::ListParams;
25use crate::error::Error;
26use crate::util::StrIteratorExt;
27
28const PLANS_PATH: [&str; 1] = ["plans"];
29
30/// A plan ID.
31#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize)]
32pub enum PlanId<'a> {
33 /// An Orb plan ID.
34 #[serde(rename = "plan_id")]
35 Orb(&'a str),
36 /// An external plan ID.
37 #[serde(rename = "external_plan_id")]
38 External(&'a str),
39}
40
41impl<'a> Default for PlanId<'a> {
42 fn default() -> PlanId<'a> {
43 PlanId::Orb("")
44 }
45}
46
47/// An Orb plan.
48#[derive(Debug, Clone, PartialEq, Eq, Hash, Deserialize, Serialize)]
49pub struct Plan {
50 /// The Orb-assigned unique identifier for the plan.
51 pub id: String,
52 /// An optional user-defined ID for this plan resource, used throughout
53 /// the system as an alias for this plan.
54 #[serde(rename = "external_plan_id")]
55 pub external_id: Option<String>,
56 /// A human-readable name for the plan.
57 pub name: Option<String>,
58 /// A human-readable description of the plan.
59 pub description: String,
60 /// The time at which the plan was created.
61 #[serde(with = "time::serde::rfc3339")]
62 pub created_at: OffsetDateTime,
63 /// The parent plan id if the given plan was created by overriding one or more of the parent's
64 /// prices.
65 pub base_plan_id: Option<String>,
66 /// Arbitrary metadata that is attached to the plan. Cannot be nested, must have string values.
67 #[serde(default)]
68 pub metadata: BTreeMap<String, String>,
69 // TODO: many missing fields.
70}
71
72impl Client {
73 /// Lists all plans.
74 ///
75 /// The underlying API call is paginated. The returned stream will fetch
76 /// additional pages as it is consumed.
77 pub fn list_plans(&self, params: &ListParams) -> impl Stream<Item = Result<Plan, Error>> + '_ {
78 let req = self.build_request(Method::GET, PLANS_PATH);
79 self.stream_paginated_request(params, req)
80 }
81
82 /// Gets a plan by ID.
83 pub async fn get_plan(&self, id: &str) -> Result<Plan, Error> {
84 let req = self.build_request(Method::GET, PLANS_PATH.chain_one(id));
85 let res = self.send_request(req).await?;
86 Ok(res)
87 }
88
89 /// Gets a plan by external ID.
90 pub async fn get_plan_by_external_id(&self, external_id: &str) -> Result<Plan, Error> {
91 let req = self.build_request(
92 Method::GET,
93 PLANS_PATH
94 .chain_one("external_plan_id")
95 .chain_one(external_id),
96 );
97 let res = self.send_request(req).await?;
98 Ok(res)
99 }
100}