zlayer_types/client.rs
1//! Client-facing wire types shared between the `ZLayer` daemon and SDK
2//! clients (CLI, `zlayer-docker`, `zlayer-py`, future language SDKs).
3//!
4//! These were originally defined in `zlayer-client`; they are pure serde
5//! DTOs with no transport or async state, so they live here so that
6//! crates which want the wire shapes don't have to pull in the full HTTP
7//! client.
8
9use std::collections::HashMap;
10
11use chrono::{DateTime, Utc};
12use serde::{Deserialize, Serialize};
13
14// ---------------------------------------------------------------------------
15// Session
16// ---------------------------------------------------------------------------
17
18/// Persisted CLI session record (lives at `~/.zlayer/session.json`,
19/// mode 0600 on Unix).
20///
21/// Stores the JWT returned by `POST /auth/token` (or `/auth/login`) so
22/// subsequent CLI invocations don't need to re-authenticate. The daemon
23/// client attaches `Authorization: Bearer <token>` from this record when
24/// present.
25#[derive(Debug, Clone, Serialize, Deserialize)]
26pub struct Session {
27 /// JWT access token.
28 pub token: String,
29 /// Email of the authenticated user (for `whoami` display).
30 pub email: String,
31 /// Token expiry. Used to warn the user before the token actually expires.
32 pub expires_at: DateTime<Utc>,
33}
34
35impl Session {
36 /// Whether the token is past its expiry.
37 #[must_use]
38 pub fn is_expired(&self) -> bool {
39 Utc::now() >= self.expires_at
40 }
41}
42
43// ---------------------------------------------------------------------------
44// Build DTOs (client-side mirrors of zlayer-api build request/response shapes)
45// ---------------------------------------------------------------------------
46
47/// Specification sent to the daemon's `POST /api/v1/build/json` endpoint to
48/// start an image build against a server-side context path.
49///
50/// Mirrors `zlayer_api::handlers::build::BuildRequestWithContext` on the
51/// wire; the server-side type is `Deserialize`-only so we carry a
52/// `Serialize` mirror here.
53#[derive(Debug, Clone, Default, Serialize)]
54pub struct BuildSpec {
55 /// Path to the build context on the daemon host. Must already exist.
56 pub context_path: String,
57 /// Runtime template name (e.g. `"node20"`) to use instead of a Dockerfile.
58 #[serde(skip_serializing_if = "Option::is_none")]
59 pub runtime: Option<String>,
60 /// Build arguments (Dockerfile `ARG` values).
61 #[serde(skip_serializing_if = "HashMap::is_empty")]
62 pub build_args: HashMap<String, String>,
63 /// Target stage for multi-stage Dockerfiles.
64 #[serde(skip_serializing_if = "Option::is_none")]
65 pub target: Option<String>,
66 /// Tags to apply to the resulting image.
67 #[serde(skip_serializing_if = "Vec::is_empty")]
68 pub tags: Vec<String>,
69 /// Disable the buildah layer cache.
70 #[serde(skip_serializing_if = "std::ops::Not::not")]
71 pub no_cache: bool,
72 /// Push the resulting image to its registry after the build succeeds.
73 #[serde(skip_serializing_if = "std::ops::Not::not")]
74 pub push: bool,
75}
76
77/// Handle returned by the daemon `start_build` endpoint. Mirrors the wire
78/// shape of `zlayer_api::handlers::build::TriggerBuildResponse` (which is
79/// `Serialize`-only, so we carry a `Deserialize` mirror here).
80///
81/// The `build_id` can be fed to `GET /api/v1/build/{id}`,
82/// `GET /api/v1/build/{id}/stream`, and `GET /api/v1/build/{id}/logs`.
83#[derive(Debug, Clone, Deserialize)]
84pub struct BuildHandle {
85 /// Unique build ID for tracking.
86 pub build_id: String,
87 /// Human-readable message from the daemon.
88 pub message: String,
89}