1use serde::{Deserialize, Serialize};
8use std::collections::HashMap;
9
10#[derive(Debug, Clone, Serialize, Deserialize)]
16pub struct SdkConfig {
17 pub version: String,
19 pub base_url: String,
21 pub languages: Vec<SdkLanguage>,
23 pub api_version: String,
25}
26
27#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Hash)]
29#[serde(rename_all = "lowercase")]
30pub enum SdkLanguage {
31 Python,
32 NodeJs,
33 Go,
34 Rust,
35 Java,
36 CSharp,
37 Ruby,
38 Php,
39}
40
41impl std::fmt::Display for SdkLanguage {
42 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
43 match self {
44 SdkLanguage::Python => write!(f, "python"),
45 SdkLanguage::NodeJs => write!(f, "nodejs"),
46 SdkLanguage::Go => write!(f, "go"),
47 SdkLanguage::Rust => write!(f, "rust"),
48 SdkLanguage::Java => write!(f, "java"),
49 SdkLanguage::CSharp => write!(f, "csharp"),
50 SdkLanguage::Ruby => write!(f, "ruby"),
51 SdkLanguage::Php => write!(f, "php"),
52 }
53 }
54}
55
56pub const PYTHON_SDK_TEMPLATE: &str = r#"# Chasm Python SDK
62# Auto-generated - Do not edit directly
63# Version: {{version}}
64
65"""
66Chasm Python SDK
67
68A Python client library for the Chasm API.
69
70Usage:
71 from chasm import ChasmClient
72
73 client = ChasmClient(api_key="your-api-key")
74 sessions = client.sessions.list()
75"""
76
77import os
78import json
79import requests
80from typing import Optional, List, Dict, Any, Union
81from dataclasses import dataclass, field
82from datetime import datetime
83from urllib.parse import urljoin
84
85__version__ = "{{version}}"
86__api_version__ = "{{api_version}}"
87
88
89@dataclass
90class ChasmConfig:
91 """Configuration for Chasm client."""
92 base_url: str = "{{base_url}}"
93 api_key: Optional[str] = None
94 timeout: int = 30
95 retry_count: int = 3
96 retry_delay: float = 1.0
97
98
99@dataclass
100class Session:
101 """Represents a chat session."""
102 id: str
103 title: str
104 provider: str
105 workspace_id: Optional[str] = None
106 message_count: int = 0
107 token_count: int = 0
108 created_at: Optional[datetime] = None
109 updated_at: Optional[datetime] = None
110 tags: List[str] = field(default_factory=list)
111 archived: bool = False
112
113
114@dataclass
115class Message:
116 """Represents a chat message."""
117 id: str
118 session_id: str
119 role: str
120 content: str
121 model: Optional[str] = None
122 token_count: int = 0
123 created_at: Optional[datetime] = None
124
125
126@dataclass
127class Workspace:
128 """Represents a workspace."""
129 id: str
130 name: str
131 path: str
132 provider: str
133 session_count: int = 0
134 created_at: Optional[datetime] = None
135
136
137class ChasmError(Exception):
138 """Base exception for Chasm errors."""
139 def __init__(self, message: str, status_code: Optional[int] = None, response: Optional[dict] = None):
140 super().__init__(message)
141 self.status_code = status_code
142 self.response = response
143
144
145class AuthenticationError(ChasmError):
146 """Authentication failed."""
147 pass
148
149
150class RateLimitError(ChasmError):
151 """Rate limit exceeded."""
152 pass
153
154
155class NotFoundError(ChasmError):
156 """Resource not found."""
157 pass
158
159
160class ApiClient:
161 """Low-level API client."""
162
163 def __init__(self, config: ChasmConfig):
164 self.config = config
165 self.session = requests.Session()
166 if config.api_key:
167 self.session.headers["Authorization"] = f"Bearer {config.api_key}"
168 self.session.headers["Content-Type"] = "application/json"
169 self.session.headers["User-Agent"] = f"chasm-python/{__version__}"
170
171 def request(self, method: str, path: str, **kwargs) -> dict:
172 """Make an API request."""
173 url = urljoin(self.config.base_url, path)
174 kwargs.setdefault("timeout", self.config.timeout)
175
176 response = self.session.request(method, url, **kwargs)
177
178 if response.status_code == 401:
179 raise AuthenticationError("Invalid API key", 401)
180 elif response.status_code == 404:
181 raise NotFoundError("Resource not found", 404)
182 elif response.status_code == 429:
183 raise RateLimitError("Rate limit exceeded", 429)
184 elif response.status_code >= 400:
185 raise ChasmError(f"API error: {response.text}", response.status_code)
186
187 if response.content:
188 return response.json()
189 return {}
190
191 def get(self, path: str, params: Optional[dict] = None) -> dict:
192 return self.request("GET", path, params=params)
193
194 def post(self, path: str, data: Optional[dict] = None) -> dict:
195 return self.request("POST", path, json=data)
196
197 def put(self, path: str, data: Optional[dict] = None) -> dict:
198 return self.request("PUT", path, json=data)
199
200 def delete(self, path: str) -> dict:
201 return self.request("DELETE", path)
202
203
204class SessionsResource:
205 """Sessions API resource."""
206
207 def __init__(self, client: ApiClient):
208 self._client = client
209
210 def list(
211 self,
212 workspace_id: Optional[str] = None,
213 provider: Optional[str] = None,
214 archived: Optional[bool] = None,
215 limit: int = 20,
216 offset: int = 0,
217 ) -> List[Session]:
218 """List sessions."""
219 params = {"limit": limit, "offset": offset}
220 if workspace_id:
221 params["workspace_id"] = workspace_id
222 if provider:
223 params["provider"] = provider
224 if archived is not None:
225 params["archived"] = str(archived).lower()
226
227 response = self._client.get("/api/sessions", params)
228 return [self._parse_session(s) for s in response.get("sessions", [])]
229
230 def get(self, session_id: str) -> Session:
231 """Get a session by ID."""
232 response = self._client.get(f"/api/sessions/{session_id}")
233 return self._parse_session(response)
234
235 def create(self, title: str, provider: str, workspace_id: Optional[str] = None) -> Session:
236 """Create a new session."""
237 data = {"title": title, "provider": provider}
238 if workspace_id:
239 data["workspace_id"] = workspace_id
240 response = self._client.post("/api/sessions", data)
241 return self._parse_session(response)
242
243 def update(self, session_id: str, **kwargs) -> Session:
244 """Update a session."""
245 response = self._client.put(f"/api/sessions/{session_id}", kwargs)
246 return self._parse_session(response)
247
248 def delete(self, session_id: str) -> bool:
249 """Delete a session."""
250 self._client.delete(f"/api/sessions/{session_id}")
251 return True
252
253 def archive(self, session_id: str) -> Session:
254 """Archive a session."""
255 return self.update(session_id, archived=True)
256
257 def search(self, query: str, limit: int = 20) -> List[Session]:
258 """Search sessions."""
259 response = self._client.get("/api/sessions/search", {"q": query, "limit": limit})
260 return [self._parse_session(s) for s in response.get("sessions", [])]
261
262 def _parse_session(self, data: dict) -> Session:
263 return Session(
264 id=data["id"],
265 title=data.get("title", "Untitled"),
266 provider=data.get("provider", "unknown"),
267 workspace_id=data.get("workspace_id"),
268 message_count=data.get("message_count", 0),
269 token_count=data.get("token_count", 0),
270 tags=data.get("tags", []),
271 archived=data.get("archived", False),
272 )
273
274
275class WorkspacesResource:
276 """Workspaces API resource."""
277
278 def __init__(self, client: ApiClient):
279 self._client = client
280
281 def list(self, limit: int = 20, offset: int = 0) -> List[Workspace]:
282 """List workspaces."""
283 response = self._client.get("/api/workspaces", {"limit": limit, "offset": offset})
284 return [self._parse_workspace(w) for w in response.get("workspaces", [])]
285
286 def get(self, workspace_id: str) -> Workspace:
287 """Get a workspace by ID."""
288 response = self._client.get(f"/api/workspaces/{workspace_id}")
289 return self._parse_workspace(response)
290
291 def _parse_workspace(self, data: dict) -> Workspace:
292 return Workspace(
293 id=data["id"],
294 name=data.get("name", ""),
295 path=data.get("path", ""),
296 provider=data.get("provider", ""),
297 session_count=data.get("session_count", 0),
298 )
299
300
301class HarvestResource:
302 """Harvest API resource."""
303
304 def __init__(self, client: ApiClient):
305 self._client = client
306
307 def run(self, providers: Optional[List[str]] = None) -> dict:
308 """Run harvest."""
309 data = {}
310 if providers:
311 data["providers"] = providers
312 return self._client.post("/api/harvest", data)
313
314 def status(self) -> dict:
315 """Get harvest status."""
316 return self._client.get("/api/harvest/status")
317
318
319class ChasmClient:
320 """Main Chasm client."""
321
322 def __init__(
323 self,
324 api_key: Optional[str] = None,
325 base_url: Optional[str] = None,
326 **kwargs
327 ):
328 api_key = api_key or os.environ.get("CHASM_API_KEY")
329 config = ChasmConfig(
330 api_key=api_key,
331 base_url=base_url or "{{base_url}}",
332 **kwargs
333 )
334 self._api = ApiClient(config)
335
336 # Resources
337 self.sessions = SessionsResource(self._api)
338 self.workspaces = WorkspacesResource(self._api)
339 self.harvest = HarvestResource(self._api)
340
341 def health(self) -> dict:
342 """Check API health."""
343 return self._api.get("/health")
344
345 def stats(self) -> dict:
346 """Get statistics."""
347 return self._api.get("/api/stats")
348
349
350# Convenience function
351def create_client(**kwargs) -> ChasmClient:
352 """Create a Chasm client with environment configuration."""
353 return ChasmClient(**kwargs)
354"#;
355
356pub const NODEJS_SDK_TEMPLATE: &str = r#"/**
358 * Chasm Node.js SDK
359 * Auto-generated - Do not edit directly
360 * Version: {{version}}
361 */
362
363const https = require('https');
364const http = require('http');
365const { URL } = require('url');
366
367const VERSION = '{{version}}';
368const API_VERSION = '{{api_version}}';
369
370/**
371 * Chasm client configuration
372 */
373class ChasmConfig {
374 constructor(options = {}) {
375 this.baseUrl = options.baseUrl || process.env.CHASM_BASE_URL || '{{base_url}}';
376 this.apiKey = options.apiKey || process.env.CHASM_API_KEY;
377 this.timeout = options.timeout || 30000;
378 this.retryCount = options.retryCount || 3;
379 }
380}
381
382/**
383 * Custom error classes
384 */
385class ChasmError extends Error {
386 constructor(message, statusCode, response) {
387 super(message);
388 this.name = 'ChasmError';
389 this.statusCode = statusCode;
390 this.response = response;
391 }
392}
393
394class AuthenticationError extends ChasmError {
395 constructor(message) {
396 super(message, 401);
397 this.name = 'AuthenticationError';
398 }
399}
400
401class NotFoundError extends ChasmError {
402 constructor(message) {
403 super(message, 404);
404 this.name = 'NotFoundError';
405 }
406}
407
408class RateLimitError extends ChasmError {
409 constructor(message) {
410 super(message, 429);
411 this.name = 'RateLimitError';
412 }
413}
414
415/**
416 * Low-level API client
417 */
418class ApiClient {
419 constructor(config) {
420 this.config = config;
421 }
422
423 async request(method, path, options = {}) {
424 const url = new URL(path, this.config.baseUrl);
425 const isHttps = url.protocol === 'https:';
426 const client = isHttps ? https : http;
427
428 if (options.params) {
429 Object.entries(options.params).forEach(([key, value]) => {
430 if (value !== undefined) {
431 url.searchParams.append(key, String(value));
432 }
433 });
434 }
435
436 const requestOptions = {
437 method,
438 hostname: url.hostname,
439 port: url.port || (isHttps ? 443 : 80),
440 path: url.pathname + url.search,
441 headers: {
442 'Content-Type': 'application/json',
443 'User-Agent': `chasm-nodejs/${VERSION}`,
444 ...(this.config.apiKey && { Authorization: `Bearer ${this.config.apiKey}` }),
445 },
446 timeout: this.config.timeout,
447 };
448
449 return new Promise((resolve, reject) => {
450 const req = client.request(requestOptions, (res) => {
451 let data = '';
452 res.on('data', (chunk) => (data += chunk));
453 res.on('end', () => {
454 if (res.statusCode === 401) {
455 reject(new AuthenticationError('Invalid API key'));
456 } else if (res.statusCode === 404) {
457 reject(new NotFoundError('Resource not found'));
458 } else if (res.statusCode === 429) {
459 reject(new RateLimitError('Rate limit exceeded'));
460 } else if (res.statusCode >= 400) {
461 reject(new ChasmError(`API error: ${data}`, res.statusCode));
462 } else {
463 resolve(data ? JSON.parse(data) : {});
464 }
465 });
466 });
467
468 req.on('error', reject);
469 req.on('timeout', () => {
470 req.destroy();
471 reject(new ChasmError('Request timeout'));
472 });
473
474 if (options.body) {
475 req.write(JSON.stringify(options.body));
476 }
477 req.end();
478 });
479 }
480
481 get(path, params) {
482 return this.request('GET', path, { params });
483 }
484
485 post(path, body) {
486 return this.request('POST', path, { body });
487 }
488
489 put(path, body) {
490 return this.request('PUT', path, { body });
491 }
492
493 delete(path) {
494 return this.request('DELETE', path);
495 }
496}
497
498/**
499 * Sessions resource
500 */
501class SessionsResource {
502 constructor(client) {
503 this._client = client;
504 }
505
506 async list(options = {}) {
507 const params = {
508 limit: options.limit || 20,
509 offset: options.offset || 0,
510 workspace_id: options.workspaceId,
511 provider: options.provider,
512 archived: options.archived,
513 };
514 const response = await this._client.get('/api/sessions', params);
515 return response.sessions || [];
516 }
517
518 async get(sessionId) {
519 return this._client.get(`/api/sessions/${sessionId}`);
520 }
521
522 async create(data) {
523 return this._client.post('/api/sessions', data);
524 }
525
526 async update(sessionId, data) {
527 return this._client.put(`/api/sessions/${sessionId}`, data);
528 }
529
530 async delete(sessionId) {
531 await this._client.delete(`/api/sessions/${sessionId}`);
532 return true;
533 }
534
535 async search(query, limit = 20) {
536 const response = await this._client.get('/api/sessions/search', { q: query, limit });
537 return response.sessions || [];
538 }
539}
540
541/**
542 * Workspaces resource
543 */
544class WorkspacesResource {
545 constructor(client) {
546 this._client = client;
547 }
548
549 async list(options = {}) {
550 const params = {
551 limit: options.limit || 20,
552 offset: options.offset || 0,
553 };
554 const response = await this._client.get('/api/workspaces', params);
555 return response.workspaces || [];
556 }
557
558 async get(workspaceId) {
559 return this._client.get(`/api/workspaces/${workspaceId}`);
560 }
561}
562
563/**
564 * Harvest resource
565 */
566class HarvestResource {
567 constructor(client) {
568 this._client = client;
569 }
570
571 async run(providers) {
572 const data = providers ? { providers } : {};
573 return this._client.post('/api/harvest', data);
574 }
575
576 async status() {
577 return this._client.get('/api/harvest/status');
578 }
579}
580
581/**
582 * Main Chasm client
583 */
584class ChasmClient {
585 constructor(options = {}) {
586 const config = new ChasmConfig(options);
587 this._api = new ApiClient(config);
588
589 this.sessions = new SessionsResource(this._api);
590 this.workspaces = new WorkspacesResource(this._api);
591 this.harvest = new HarvestResource(this._api);
592 }
593
594 async health() {
595 return this._api.get('/health');
596 }
597
598 async stats() {
599 return this._api.get('/api/stats');
600 }
601}
602
603module.exports = {
604 ChasmClient,
605 ChasmConfig,
606 ChasmError,
607 AuthenticationError,
608 NotFoundError,
609 RateLimitError,
610 VERSION,
611 API_VERSION,
612};
613"#;
614
615pub const GO_SDK_TEMPLATE: &str = r#"// Chasm Go SDK
617// Auto-generated - Do not edit directly
618// Version: {{version}}
619
620package chasm
621
622import (
623 "bytes"
624 "encoding/json"
625 "fmt"
626 "io"
627 "net/http"
628 "net/url"
629 "os"
630 "time"
631)
632
633const (
634 Version = "{{version}}"
635 APIVersion = "{{api_version}}"
636)
637
638// Config holds client configuration
639type Config struct {
640 BaseURL string
641 APIKey string
642 Timeout time.Duration
643 RetryCount int
644}
645
646// DefaultConfig returns default configuration
647func DefaultConfig() *Config {
648 baseURL := os.Getenv("CHASM_BASE_URL")
649 if baseURL == "" {
650 baseURL = "{{base_url}}"
651 }
652 return &Config{
653 BaseURL: baseURL,
654 APIKey: os.Getenv("CHASM_API_KEY"),
655 Timeout: 30 * time.Second,
656 RetryCount: 3,
657 }
658}
659
660// Session represents a chat session
661type Session struct {
662 ID string `json:"id"`
663 Title string `json:"title"`
664 Provider string `json:"provider"`
665 WorkspaceID *string `json:"workspace_id,omitempty"`
666 MessageCount int `json:"message_count"`
667 TokenCount int `json:"token_count"`
668 Tags []string `json:"tags"`
669 Archived bool `json:"archived"`
670 CreatedAt time.Time `json:"created_at,omitempty"`
671 UpdatedAt time.Time `json:"updated_at,omitempty"`
672}
673
674// Workspace represents a workspace
675type Workspace struct {
676 ID string `json:"id"`
677 Name string `json:"name"`
678 Path string `json:"path"`
679 Provider string `json:"provider"`
680 SessionCount int `json:"session_count"`
681 CreatedAt time.Time `json:"created_at,omitempty"`
682}
683
684// Error types
685type ChasmError struct {
686 Message string
687 StatusCode int
688}
689
690func (e *ChasmError) Error() string {
691 return fmt.Sprintf("chasm: %s (status %d)", e.Message, e.StatusCode)
692}
693
694// Client is the main Chasm client
695type Client struct {
696 config *Config
697 httpClient *http.Client
698 Sessions *SessionsService
699 Workspaces *WorkspacesService
700 Harvest *HarvestService
701}
702
703// NewClient creates a new Chasm client
704func NewClient(config *Config) *Client {
705 if config == nil {
706 config = DefaultConfig()
707 }
708
709 c := &Client{
710 config: config,
711 httpClient: &http.Client{
712 Timeout: config.Timeout,
713 },
714 }
715
716 c.Sessions = &SessionsService{client: c}
717 c.Workspaces = &WorkspacesService{client: c}
718 c.Harvest = &HarvestService{client: c}
719
720 return c
721}
722
723func (c *Client) request(method, path string, body interface{}, result interface{}) error {
724 u, err := url.Parse(c.config.BaseURL + path)
725 if err != nil {
726 return err
727 }
728
729 var bodyReader io.Reader
730 if body != nil {
731 b, err := json.Marshal(body)
732 if err != nil {
733 return err
734 }
735 bodyReader = bytes.NewReader(b)
736 }
737
738 req, err := http.NewRequest(method, u.String(), bodyReader)
739 if err != nil {
740 return err
741 }
742
743 req.Header.Set("Content-Type", "application/json")
744 req.Header.Set("User-Agent", fmt.Sprintf("chasm-go/%s", Version))
745 if c.config.APIKey != "" {
746 req.Header.Set("Authorization", "Bearer "+c.config.APIKey)
747 }
748
749 resp, err := c.httpClient.Do(req)
750 if err != nil {
751 return err
752 }
753 defer resp.Body.Close()
754
755 if resp.StatusCode >= 400 {
756 return &ChasmError{
757 Message: fmt.Sprintf("API error: %s", resp.Status),
758 StatusCode: resp.StatusCode,
759 }
760 }
761
762 if result != nil {
763 return json.NewDecoder(resp.Body).Decode(result)
764 }
765 return nil
766}
767
768// Health checks API health
769func (c *Client) Health() (map[string]interface{}, error) {
770 var result map[string]interface{}
771 err := c.request("GET", "/health", nil, &result)
772 return result, err
773}
774
775// Stats gets statistics
776func (c *Client) Stats() (map[string]interface{}, error) {
777 var result map[string]interface{}
778 err := c.request("GET", "/api/stats", nil, &result)
779 return result, err
780}
781
782// SessionsService handles session operations
783type SessionsService struct {
784 client *Client
785}
786
787// ListOptions for listing resources
788type ListOptions struct {
789 Limit int
790 Offset int
791 WorkspaceID string
792 Provider string
793 Archived *bool
794}
795
796func (s *SessionsService) List(opts *ListOptions) ([]Session, error) {
797 path := "/api/sessions"
798 if opts != nil {
799 params := url.Values{}
800 if opts.Limit > 0 {
801 params.Set("limit", fmt.Sprintf("%d", opts.Limit))
802 }
803 if opts.Offset > 0 {
804 params.Set("offset", fmt.Sprintf("%d", opts.Offset))
805 }
806 if opts.WorkspaceID != "" {
807 params.Set("workspace_id", opts.WorkspaceID)
808 }
809 if opts.Provider != "" {
810 params.Set("provider", opts.Provider)
811 }
812 if opts.Archived != nil {
813 params.Set("archived", fmt.Sprintf("%t", *opts.Archived))
814 }
815 if len(params) > 0 {
816 path += "?" + params.Encode()
817 }
818 }
819
820 var result struct {
821 Sessions []Session `json:"sessions"`
822 }
823 err := s.client.request("GET", path, nil, &result)
824 return result.Sessions, err
825}
826
827func (s *SessionsService) Get(id string) (*Session, error) {
828 var session Session
829 err := s.client.request("GET", "/api/sessions/"+id, nil, &session)
830 return &session, err
831}
832
833func (s *SessionsService) Create(title, provider string, workspaceID *string) (*Session, error) {
834 body := map[string]interface{}{
835 "title": title,
836 "provider": provider,
837 }
838 if workspaceID != nil {
839 body["workspace_id"] = *workspaceID
840 }
841 var session Session
842 err := s.client.request("POST", "/api/sessions", body, &session)
843 return &session, err
844}
845
846func (s *SessionsService) Delete(id string) error {
847 return s.client.request("DELETE", "/api/sessions/"+id, nil, nil)
848}
849
850func (s *SessionsService) Search(query string, limit int) ([]Session, error) {
851 path := fmt.Sprintf("/api/sessions/search?q=%s&limit=%d", url.QueryEscape(query), limit)
852 var result struct {
853 Sessions []Session `json:"sessions"`
854 }
855 err := s.client.request("GET", path, nil, &result)
856 return result.Sessions, err
857}
858
859// WorkspacesService handles workspace operations
860type WorkspacesService struct {
861 client *Client
862}
863
864func (w *WorkspacesService) List(opts *ListOptions) ([]Workspace, error) {
865 path := "/api/workspaces"
866 if opts != nil && (opts.Limit > 0 || opts.Offset > 0) {
867 params := url.Values{}
868 if opts.Limit > 0 {
869 params.Set("limit", fmt.Sprintf("%d", opts.Limit))
870 }
871 if opts.Offset > 0 {
872 params.Set("offset", fmt.Sprintf("%d", opts.Offset))
873 }
874 path += "?" + params.Encode()
875 }
876
877 var result struct {
878 Workspaces []Workspace `json:"workspaces"`
879 }
880 err := w.client.request("GET", path, nil, &result)
881 return result.Workspaces, err
882}
883
884func (w *WorkspacesService) Get(id string) (*Workspace, error) {
885 var workspace Workspace
886 err := w.client.request("GET", "/api/workspaces/"+id, nil, &workspace)
887 return &workspace, err
888}
889
890// HarvestService handles harvest operations
891type HarvestService struct {
892 client *Client
893}
894
895func (h *HarvestService) Run(providers []string) (map[string]interface{}, error) {
896 body := map[string]interface{}{}
897 if len(providers) > 0 {
898 body["providers"] = providers
899 }
900 var result map[string]interface{}
901 err := h.client.request("POST", "/api/harvest", body, &result)
902 return result, err
903}
904
905func (h *HarvestService) Status() (map[string]interface{}, error) {
906 var result map[string]interface{}
907 err := h.client.request("GET", "/api/harvest/status", nil, &result)
908 return result, err
909}
910"#;
911
912pub struct SdkGenerator {
918 config: SdkConfig,
919}
920
921impl SdkGenerator {
922 pub fn new(config: SdkConfig) -> Self {
924 Self { config }
925 }
926
927 pub fn generate(&self, language: SdkLanguage) -> String {
929 let template = match language {
930 SdkLanguage::Python => PYTHON_SDK_TEMPLATE,
931 SdkLanguage::NodeJs => NODEJS_SDK_TEMPLATE,
932 SdkLanguage::Go => GO_SDK_TEMPLATE,
933 _ => return format!("// SDK for {} not yet implemented", language),
934 };
935
936 template
937 .replace("{{version}}", &self.config.version)
938 .replace("{{api_version}}", &self.config.api_version)
939 .replace("{{base_url}}", &self.config.base_url)
940 }
941
942 pub fn generate_all(&self) -> HashMap<SdkLanguage, String> {
944 self.config
945 .languages
946 .iter()
947 .map(|lang| (lang.clone(), self.generate(lang.clone())))
948 .collect()
949 }
950
951 pub fn get_filename(&self, language: &SdkLanguage) -> String {
953 match language {
954 SdkLanguage::Python => "chasm.py".to_string(),
955 SdkLanguage::NodeJs => "chasm.js".to_string(),
956 SdkLanguage::Go => "chasm.go".to_string(),
957 SdkLanguage::Rust => "chasm.rs".to_string(),
958 SdkLanguage::Java => "Chasm.java".to_string(),
959 SdkLanguage::CSharp => "Chasm.cs".to_string(),
960 SdkLanguage::Ruby => "chasm.rb".to_string(),
961 SdkLanguage::Php => "Chasm.php".to_string(),
962 }
963 }
964}
965
966impl Default for SdkConfig {
967 fn default() -> Self {
968 Self {
969 version: "1.0.0".to_string(),
970 base_url: "http://localhost:8787".to_string(),
971 languages: vec![SdkLanguage::Python, SdkLanguage::NodeJs, SdkLanguage::Go],
972 api_version: "v1".to_string(),
973 }
974 }
975}
976
977#[cfg(test)]
978mod tests {
979 use super::*;
980
981 #[test]
982 fn test_sdk_generation() {
983 let config = SdkConfig::default();
984 let generator = SdkGenerator::new(config);
985
986 let python_sdk = generator.generate(SdkLanguage::Python);
987 assert!(python_sdk.contains("class ChasmClient"));
988 assert!(python_sdk.contains("1.0.0"));
989
990 let nodejs_sdk = generator.generate(SdkLanguage::NodeJs);
991 assert!(nodejs_sdk.contains("class ChasmClient"));
992
993 let go_sdk = generator.generate(SdkLanguage::Go);
994 assert!(go_sdk.contains("type Client struct"));
995 }
996}