protoc-gen-ts-temporal 0.0.1

protoc plugin that emits a typed TypeScript Temporal client from temporal.v1.* annotated protos
Documentation
//! Intermediate representation for parsed Temporal services.
//!
//! Mirrors cludden's annotation schema (`temporal.v1.*`). Each `*Model` carries
//! the proto-level data the renderer needs; renderer concerns (TS identifiers,
//! import paths) are intentionally not represented here.

/// One Temporal-bearing proto service after parsing.
#[derive(Debug, Clone)]
pub struct ServiceModel {
    /// Fully-qualified proto package, e.g. "invoice.v1".
    pub package: String,
    /// Service name from the proto, e.g. "InvoiceBatch".
    pub service: String,
    /// Source proto file path, e.g. "invoice/v1/invoice.proto".
    pub source_file: String,
    /// `ServiceOptions.task_queue` default applied to workflows whose own
    /// `WorkflowOptions.task_queue` is empty. Empty string when unset.
    pub default_task_queue: String,
    pub workflows: Vec<WorkflowModel>,
    pub signals: Vec<SignalModel>,
    pub queries: Vec<QueryModel>,
    pub updates: Vec<UpdateModel>,
    /// Validate-only in v1: read for collision detection, no codegen.
    pub activities: Vec<ActivityModel>,
}

impl ServiceModel {
    /// Workflow-level task_queue, falling back to the service default.
    pub fn resolved_task_queue<'a>(&'a self, wf: &'a WorkflowModel) -> &'a str {
        if !wf.task_queue.is_empty() {
            &wf.task_queue
        } else {
            &self.default_task_queue
        }
    }
}

#[derive(Debug, Clone)]
pub struct WorkflowModel {
    pub rpc_method: String,
    pub input_type: ProtoType,
    pub output_type: ProtoType,
    /// `WorkflowOptions.task_queue` override (empty string if absent).
    pub task_queue: String,
    /// `WorkflowOptions.name` override (fully-qualified registered workflow name).
    pub registered_name: Option<String>,
    /// `WorkflowOptions.aliases`.
    pub aliases: Vec<String>,
    /// Signal refs attached to this workflow.
    pub attached_signals: Vec<SignalRef>,
    /// Query refs attached to this workflow.
    pub attached_queries: Vec<QueryRef>,
    /// Update refs attached to this workflow.
    pub attached_updates: Vec<UpdateRef>,
}

#[derive(Debug, Clone)]
pub struct SignalRef {
    /// Rpc method name (the `ref` field).
    pub method: String,
    /// `WorkflowOptions.Signal.start` — emit signal-with-start convenience.
    pub signal_with_start: bool,
}

#[derive(Debug, Clone)]
pub struct QueryRef {
    pub method: String,
}

#[derive(Debug, Clone)]
pub struct UpdateRef {
    pub method: String,
    /// `WorkflowOptions.Update.start` — emit update-with-start convenience.
    pub update_with_start: bool,
    /// `WorkflowOptions.Update.validate` — emit validator hook (optional bool).
    pub update_with_validation: Option<bool>,
}

#[derive(Debug, Clone)]
pub struct SignalModel {
    pub rpc_method: String,
    pub input_type: ProtoType,
    /// Must be google.protobuf.Empty per spec — validated.
    pub output_type: ProtoType,
    /// `SignalOptions.name` override, else `rpc_method`.
    pub registered_name: String,
}

#[derive(Debug, Clone)]
pub struct QueryModel {
    pub rpc_method: String,
    pub input_type: ProtoType,
    pub output_type: ProtoType,
    /// `QueryOptions.name` override, else `rpc_method`.
    pub registered_name: String,
}

#[derive(Debug, Clone)]
pub struct UpdateModel {
    pub rpc_method: String,
    pub input_type: ProtoType,
    pub output_type: ProtoType,
    /// `UpdateOptions.name` override, else `rpc_method`.
    pub registered_name: String,
}

#[derive(Debug, Clone)]
pub struct ActivityModel {
    pub rpc_method: String,
    /// `ActivityOptions.name` override, else `rpc_method`.
    pub registered_name: String,
}

/// A proto type reference, resolved to its fully-qualified name.
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct ProtoType {
    /// Fully-qualified proto type name, e.g. "invoice.v1.RunRequest".
    pub full_name: String,
    /// `true` when the type is `google.protobuf.Empty` (special-cased downstream).
    pub is_empty: bool,
}

impl ProtoType {
    pub fn from_full_name(name: &str) -> Self {
        let full = name.strip_prefix('.').unwrap_or(name).to_string();
        let is_empty = full == "google.protobuf.Empty";
        Self {
            full_name: full,
            is_empty,
        }
    }
}