refactor: name the workspace catalog list response
This commit is contained in:
@@ -2,7 +2,10 @@ use crate::{BackendApiClient, BackendApiClientError};
|
|||||||
use reqwest::Method;
|
use reqwest::Method;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use workspace_api::{WorkspaceCreateResponse, WorkspaceRepositoryRecord, WorkspaceSummary};
|
use workspace_api::{
|
||||||
|
WorkspaceCatalogListResponse, WorkspaceCreateResponse, WorkspaceRepositoryRecord,
|
||||||
|
WorkspaceSummary,
|
||||||
|
};
|
||||||
|
|
||||||
const DEFAULT_WORKSPACE_LIMIT: usize = 200;
|
const DEFAULT_WORKSPACE_LIMIT: usize = 200;
|
||||||
|
|
||||||
@@ -88,7 +91,7 @@ async fn list_backend_workspaces_with_client(
|
|||||||
.send()
|
.send()
|
||||||
.await?;
|
.await?;
|
||||||
client.check_status(response.status())?;
|
client.check_status(response.status())?;
|
||||||
Ok(response.json::<Vec<BackendWorkspace>>().await?)
|
Ok(response.json::<WorkspaceCatalogListResponse>().await?.0)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn create_backend_workspace(
|
pub async fn create_backend_workspace(
|
||||||
|
|||||||
@@ -105,6 +105,14 @@ pub struct WorkspaceSummary {
|
|||||||
pub updated_at: String,
|
pub updated_at: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Public response returned by `GET /api/workspaces`.
|
||||||
|
///
|
||||||
|
/// The transparent newtype keeps the established top-level JSON array while making the
|
||||||
|
/// complete list response a named cross-crate and generated-TypeScript authority.
|
||||||
|
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
|
||||||
|
#[cfg_attr(feature = "typescript", derive(ts_rs::TS))]
|
||||||
|
pub struct WorkspaceCatalogListResponse(pub Vec<WorkspaceSummary>);
|
||||||
|
|
||||||
/// Public Repository record embedded in Workspace creation responses.
|
/// Public Repository record embedded in Workspace creation responses.
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
|
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
|
||||||
#[cfg_attr(feature = "typescript", derive(ts_rs::TS))]
|
#[cfg_attr(feature = "typescript", derive(ts_rs::TS))]
|
||||||
@@ -754,6 +762,7 @@ pub fn catalog_typescript() -> String {
|
|||||||
let config = ts_rs::Config::default();
|
let config = ts_rs::Config::default();
|
||||||
let declarations = [
|
let declarations = [
|
||||||
WorkspaceSummary::decl(&config),
|
WorkspaceSummary::decl(&config),
|
||||||
|
WorkspaceCatalogListResponse::decl(&config),
|
||||||
WorkspaceRepositoryRecord::decl(&config),
|
WorkspaceRepositoryRecord::decl(&config),
|
||||||
WorkspaceCreateResponse::decl(&config),
|
WorkspaceCreateResponse::decl(&config),
|
||||||
WorkspaceAuthConfig::decl(&config),
|
WorkspaceAuthConfig::decl(&config),
|
||||||
@@ -814,6 +823,17 @@ mod tests {
|
|||||||
let parsed: WorkspaceResponse = serde_json::from_value(workspace.clone()).unwrap();
|
let parsed: WorkspaceResponse = serde_json::from_value(workspace.clone()).unwrap();
|
||||||
assert_eq!(serde_json::to_value(parsed).unwrap(), workspace);
|
assert_eq!(serde_json::to_value(parsed).unwrap(), workspace);
|
||||||
|
|
||||||
|
let catalog = serde_json::json!([{
|
||||||
|
"workspace_id": "workspace-test",
|
||||||
|
"owner_account_id": "user-test",
|
||||||
|
"display_name": "Test",
|
||||||
|
"state": "active",
|
||||||
|
"created_at": "2026-01-01T00:00:00Z",
|
||||||
|
"updated_at": "2026-01-01T00:00:00Z"
|
||||||
|
}]);
|
||||||
|
let parsed: WorkspaceCatalogListResponse = serde_json::from_value(catalog.clone()).unwrap();
|
||||||
|
assert_eq!(serde_json::to_value(parsed).unwrap(), catalog);
|
||||||
|
|
||||||
let repositories = serde_json::json!({
|
let repositories = serde_json::json!({
|
||||||
"workspace_id": "workspace-test",
|
"workspace_id": "workspace-test",
|
||||||
"items": [{
|
"items": [{
|
||||||
@@ -860,6 +880,9 @@ mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
fn generated_catalog_typescript_keeps_public_wrappers_and_nullability() {
|
fn generated_catalog_typescript_keeps_public_wrappers_and_nullability() {
|
||||||
let output = catalog_typescript();
|
let output = catalog_typescript();
|
||||||
|
assert!(
|
||||||
|
output.contains("export type WorkspaceCatalogListResponse = Array<WorkspaceSummary>")
|
||||||
|
);
|
||||||
assert!(output.contains("export type WorkspaceResponse ="));
|
assert!(output.contains("export type WorkspaceResponse ="));
|
||||||
assert!(output.contains("permissions: WorkspacePermissionSummary"));
|
assert!(output.contains("permissions: WorkspacePermissionSummary"));
|
||||||
assert!(output.contains("export type RepositoryListResponse ="));
|
assert!(output.contains("export type RepositoryListResponse ="));
|
||||||
|
|||||||
@@ -67,10 +67,10 @@ use workspace_api::{
|
|||||||
RepositoryDetailResponse, RepositoryListResponse, RepositoryLogResponse,
|
RepositoryDetailResponse, RepositoryListResponse, RepositoryLogResponse,
|
||||||
RepositorySshCredential, RepositorySshHostTrust, RotateRepositorySshCredentialRequest,
|
RepositorySshCredential, RepositorySshHostTrust, RotateRepositorySshCredentialRequest,
|
||||||
RuntimeConnectionTestResponse, RuntimeManagementSummary, TICKET_ORCHESTRATION_PLANS_QUERY_PATH,
|
RuntimeConnectionTestResponse, RuntimeManagementSummary, TICKET_ORCHESTRATION_PLANS_QUERY_PATH,
|
||||||
TICKET_RELATIONS_QUERY_PATH, WorkspaceCreateResponse, WorkspaceExtensionPointState,
|
TICKET_RELATIONS_QUERY_PATH, WorkspaceCatalogListResponse, WorkspaceCreateResponse,
|
||||||
WorkspaceExtensionPoints, WorkspacePermissionSummary, WorkspaceRepositoryRecord,
|
WorkspaceExtensionPointState, WorkspaceExtensionPoints, WorkspacePermissionSummary,
|
||||||
WorkspaceResponse, WorkspaceRuntimeResource, WorkspaceSummary, WorkspaceWorkerDiscoveryItem,
|
WorkspaceRepositoryRecord, WorkspaceResponse, WorkspaceRuntimeResource, WorkspaceSummary,
|
||||||
WorkspaceWorkerDiscoveryPage, WorkspaceWorkerSubject,
|
WorkspaceWorkerDiscoveryItem, WorkspaceWorkerDiscoveryPage, WorkspaceWorkerSubject,
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::auth::{
|
use crate::auth::{
|
||||||
@@ -980,7 +980,9 @@ async fn list_server_workspaces(
|
|||||||
let owner = match resolve_server_actor(&api, &headers).await {
|
let owner = match resolve_server_actor(&api, &headers).await {
|
||||||
Ok(Some(actor)) => Some(actor.account_id),
|
Ok(Some(actor)) => Some(actor.account_id),
|
||||||
Ok(None) => match api.catalog.is_empty() {
|
Ok(None) => match api.catalog.is_empty() {
|
||||||
Ok(true) => return Json(Vec::<WorkspaceSummary>::new()).into_response(),
|
Ok(true) => {
|
||||||
|
return Json(WorkspaceCatalogListResponse(Vec::new())).into_response();
|
||||||
|
}
|
||||||
Ok(false) => return StatusCode::UNAUTHORIZED.into_response(),
|
Ok(false) => return StatusCode::UNAUTHORIZED.into_response(),
|
||||||
Err(error) => return server_error_response(error),
|
Err(error) => return server_error_response(error),
|
||||||
},
|
},
|
||||||
@@ -990,12 +992,9 @@ async fn list_server_workspaces(
|
|||||||
.catalog
|
.catalog
|
||||||
.list(owner.as_deref(), query.limit.unwrap_or(100))
|
.list(owner.as_deref(), query.limit.unwrap_or(100))
|
||||||
{
|
{
|
||||||
Ok(workspaces) => Json(
|
Ok(workspaces) => Json(WorkspaceCatalogListResponse(
|
||||||
workspaces
|
workspaces.into_iter().map(workspace_summary).collect(),
|
||||||
.into_iter()
|
))
|
||||||
.map(workspace_summary)
|
|
||||||
.collect::<Vec<_>>(),
|
|
||||||
)
|
|
||||||
.into_response(),
|
.into_response(),
|
||||||
Err(error) => server_error_response(error),
|
Err(error) => server_error_response(error),
|
||||||
}
|
}
|
||||||
@@ -17784,10 +17783,10 @@ mod tests {
|
|||||||
let catalog_body = to_bytes(authenticated_catalog.into_body(), usize::MAX)
|
let catalog_body = to_bytes(authenticated_catalog.into_body(), usize::MAX)
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let typed_catalog: Vec<workspace_api::WorkspaceSummary> =
|
let typed_catalog: workspace_api::WorkspaceCatalogListResponse =
|
||||||
serde_json::from_slice(&catalog_body).unwrap();
|
serde_json::from_slice(&catalog_body).unwrap();
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
typed_catalog[0].workspace_id,
|
typed_catalog.0[0].workspace_id,
|
||||||
workspace.workspace.workspace_id
|
workspace.workspace.workspace_id
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@@ -10,6 +10,8 @@ export type WorkspaceSummary = {
|
|||||||
updated_at: string;
|
updated_at: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export type WorkspaceCatalogListResponse = Array<WorkspaceSummary>;
|
||||||
|
|
||||||
export type WorkspaceRepositoryRecord = {
|
export type WorkspaceRepositoryRecord = {
|
||||||
workspace_id: string;
|
workspace_id: string;
|
||||||
repository_id: string;
|
repository_id: string;
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ import type {
|
|||||||
RepositorySourceKind,
|
RepositorySourceKind,
|
||||||
RepositorySummary,
|
RepositorySummary,
|
||||||
WorkspaceAuthConfig,
|
WorkspaceAuthConfig,
|
||||||
|
WorkspaceCatalogListResponse,
|
||||||
WorkspaceCreateResponse,
|
WorkspaceCreateResponse,
|
||||||
WorkspaceExtensionPoints,
|
WorkspaceExtensionPoints,
|
||||||
WorkspaceExtensionPointState,
|
WorkspaceExtensionPointState,
|
||||||
@@ -28,6 +29,7 @@ export type {
|
|||||||
RepositoryListResponse,
|
RepositoryListResponse,
|
||||||
RepositoryLogResponse,
|
RepositoryLogResponse,
|
||||||
RepositorySummary,
|
RepositorySummary,
|
||||||
|
WorkspaceCatalogListResponse,
|
||||||
WorkspaceCreateResponse,
|
WorkspaceCreateResponse,
|
||||||
WorkspacePermissionSummary,
|
WorkspacePermissionSummary,
|
||||||
WorkspaceResponse,
|
WorkspaceResponse,
|
||||||
@@ -412,7 +414,7 @@ function commitSummary(value: unknown, path: string): GitCommitSummary {
|
|||||||
|
|
||||||
export function parseWorkspaceCatalogResponse(
|
export function parseWorkspaceCatalogResponse(
|
||||||
value: unknown,
|
value: unknown,
|
||||||
): WorkspaceSummary[] {
|
): WorkspaceCatalogListResponse {
|
||||||
return array(value, "workspaces").map((item, index) =>
|
return array(value, "workspaces").map((item, index) =>
|
||||||
workspaceSummary(item, `workspaces[${index}]`)
|
workspaceSummary(item, `workspaces[${index}]`)
|
||||||
);
|
);
|
||||||
|
|||||||
Reference in New Issue
Block a user