grafbase_local_backend/api/
link.rs1use super::{
2 client::create_client,
3 consts::{API_URL, PROJECT_METADATA_FILE},
4 errors::ApiError,
5 graphql::queries::viewer::{PersonalAccount, Viewer},
6 types::{AccountWithProjects, Project, ProjectMetadata},
7 utils::project_linked,
8};
9use common::environment::Environment;
10use cynic::{http::ReqwestExt, QueryBuilder};
11use std::iter;
12
13#[allow(clippy::module_name_repetitions)]
17pub async fn get_viewer_data_for_link() -> Result<Vec<AccountWithProjects>, ApiError> {
18 if project_linked().await? {
20 return Err(ApiError::ProjectAlreadyLinked);
21 }
22
23 let client = create_client().await?;
24
25 let query = Viewer::build(());
26
27 let response = client.post(API_URL).run_graphql(query).await?;
28
29 let response = response.data.expect("must exist");
30
31 let viewer_response = response.viewer.ok_or(ApiError::UnauthorizedOrDeletedUser)?;
32
33 let PersonalAccount {
34 id,
35 name,
36 slug,
37 projects,
38 } = viewer_response
39 .personal_account
40 .ok_or(ApiError::IncorrectlyScopedToken)?;
41
42 let personal_account_id = id;
43
44 let personal_account = AccountWithProjects {
45 id: personal_account_id.inner().to_owned(),
46 name,
47 slug,
48 personal: true,
49 projects: projects
50 .nodes
51 .into_iter()
52 .map(|project| Project {
53 id: project.id.into_inner(),
54 slug: project.slug,
55 })
56 .collect(),
57 };
58
59 let accounts = iter::once(personal_account)
60 .chain(viewer_response.organizations.nodes.iter().map(|organization| {
61 AccountWithProjects {
62 id: organization.id.inner().to_owned(),
63 name: organization.name.clone(),
64 slug: organization.slug.clone(),
65 personal: false,
66 projects: organization
67 .projects
68 .nodes
69 .iter()
70 .cloned()
71 .map(|project| Project {
72 id: project.id.into_inner(),
73 slug: project.slug,
74 })
75 .collect(),
76 }
77 }))
78 .collect();
79
80 Ok(accounts)
81}
82
83#[allow(clippy::module_name_repetitions)]
87pub async fn link_project(account_id: String, project_id: String) -> Result<(), ApiError> {
88 let environment = Environment::get();
89 let project_metadata_path = environment.project_dot_grafbase_path.join(PROJECT_METADATA_FILE);
90 tokio::fs::write(
91 &project_metadata_path,
92 ProjectMetadata { account_id, project_id }.to_string(),
93 )
94 .await
95 .map_err(ApiError::WriteProjectMetadataFile)
96}