@castari/sdk 0.1.4 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/client.js CHANGED
@@ -1,242 +1,102 @@
1
- export * from './types';
2
- const DEFAULT_LOCAL_URL = 'http://localhost:3000';
3
- const DEFAULT_PLATFORM_URL = 'https://castari-api-12511-04c55b73-g4p2s9om.onporter.run';
1
+ import { HttpClient } from './http.js';
2
+ import { AgentsAPI } from './agents.js';
3
+ import { UsageAPI } from './usage.js';
4
+ import { AuthAPI } from './auth.js';
5
+ import { getAuth } from './config.js';
6
+ import { AuthenticationError } from './errors.js';
7
+ /**
8
+ * Main client for interacting with the Castari API
9
+ *
10
+ * @example
11
+ * ```typescript
12
+ * import { CastariClient } from '@castari/sdk';
13
+ *
14
+ * // Uses credentials from ~/.castari or CASTARI_API_KEY env var
15
+ * const client = new CastariClient();
16
+ *
17
+ * // Or provide credentials explicitly
18
+ * const client = new CastariClient({ apiKey: 'cap_xxxxx' });
19
+ *
20
+ * // List agents
21
+ * const agents = await client.agents.list();
22
+ *
23
+ * // Deploy an agent
24
+ * await client.agents.deploy('my-agent');
25
+ *
26
+ * // Invoke an agent
27
+ * const result = await client.agents.invoke('my-agent', { prompt: 'Hello!' });
28
+ * ```
29
+ */
4
30
  export class CastariClient {
5
- ws;
6
31
  options;
7
- messageHandlers = [];
8
- sandboxId;
9
- resolvedClientId;
10
- resolvedPlatformApiKey;
32
+ httpClient;
33
+ initialized = false;
34
+ initPromise = null;
35
+ /** API for managing agents */
36
+ agents;
37
+ /** API for accessing usage statistics */
38
+ usage;
39
+ /** API for authentication operations */
40
+ auth;
41
+ /**
42
+ * Create a new Castari client
43
+ * @param options - Client configuration options
44
+ */
11
45
  constructor(options = {}) {
12
- this.options = {
13
- ...options,
14
- };
15
- }
16
- async start() {
17
- const anthropicApiKey = this.options.anthropicApiKey || process.env.ANTHROPIC_API_KEY;
18
- if (!anthropicApiKey) {
19
- throw new Error('ANTHROPIC_API_KEY is required');
20
- }
21
- this.resolvedClientId =
22
- this.options.clientId || process.env.CASTARI_CLIENT_ID || undefined;
23
- this.resolvedPlatformApiKey =
24
- this.options.platformApiKey || process.env.CASTARI_API_KEY || undefined;
25
- const connection = this.options.connectionUrl
26
- ? await this.setupLocalConnection()
27
- : await this.setupPlatformConnection();
28
- if (this.options.debug) {
29
- console.log(`📡 Configuring server at ${connection.configUrl}...`);
30
- }
31
- const configPayload = {
32
- anthropicApiKey,
33
- agents: this.options.agents,
34
- allowedTools: this.options.allowedTools,
35
- systemPrompt: this.options.systemPrompt,
36
- model: this.options.model,
37
- resume: this.options.resume,
38
- };
39
- if (this.options.debug) {
40
- console.log(`📋 Config payload:`, JSON.stringify(configPayload, null, 2));
41
- }
42
- const configHeaders = {
43
- 'Content-Type': 'application/json',
44
- ...connection.authHeaders,
45
- };
46
- let configResponse = null;
47
- const maxConfigAttempts = 5;
48
- for (let attempt = 1; attempt <= maxConfigAttempts; attempt++) {
49
- configResponse = await fetch(connection.configUrl, {
50
- method: 'POST',
51
- headers: configHeaders,
52
- body: JSON.stringify(configPayload),
53
- }).catch(err => {
54
- if (this.options.debug) {
55
- console.warn(`⚠️ Config request failed on attempt ${attempt}:`, err);
56
- }
57
- return null;
58
- });
59
- if (configResponse && configResponse.ok)
60
- break;
61
- if (this.options.debug) {
62
- console.warn(`⚠️ Config attempt ${attempt} failed (status ${configResponse?.status ?? 'n/a'}).`);
63
- }
64
- if (attempt < maxConfigAttempts) {
65
- await new Promise(resolve => setTimeout(resolve, 3000));
66
- }
67
- }
68
- if (!configResponse || !configResponse.ok) {
69
- const errorText = configResponse ? await configResponse.text() : 'no response';
70
- if (connection.cleanup)
71
- await connection.cleanup();
72
- throw new Error(`Failed to configure server (status ${configResponse?.status ?? 'n/a'}): ${errorText}`);
73
- }
74
- const { connectionToken } = (await configResponse.json());
75
- if (!connectionToken) {
76
- if (connection.cleanup)
77
- await connection.cleanup();
78
- throw new Error('Server did not return a connectionToken');
79
- }
80
- const wsUrlParams = new URLSearchParams();
81
- wsUrlParams.set('token', connectionToken);
82
- // Add any auth params from platform (for sandbox proxy auth)
83
- if (connection.authParams) {
84
- for (const [key, value] of Object.entries(connection.authParams)) {
85
- wsUrlParams.set(key, value);
86
- }
87
- }
88
- const wsUrlJoiner = connection.wsUrl.includes('?') ? '&' : '?';
89
- const wsUrl = `${connection.wsUrl}${wsUrlJoiner}${wsUrlParams.toString()}`;
90
- if (this.options.debug) {
91
- console.log(`🔌 Connecting to WebSocket at ${wsUrl}...`);
92
- }
93
- return new Promise((resolve, reject) => {
94
- this.ws = new WebSocket(wsUrl);
95
- this.ws.onopen = () => {
96
- if (this.options.debug)
97
- console.log('✅ Connected to Castari Server');
98
- resolve();
99
- };
100
- this.ws.onmessage = event => {
101
- try {
102
- const message = JSON.parse(event.data.toString());
103
- this.handleMessage(message);
104
- }
105
- catch (error) {
106
- console.error('Failed to parse message:', error);
107
- }
108
- };
109
- this.ws.onerror = error => {
110
- console.error('WebSocket error:', error);
111
- reject(error);
112
- };
113
- this.ws.onclose = () => {
114
- if (this.options.debug)
115
- console.log('👋 Disconnected');
116
- };
46
+ this.options = options;
47
+ // Create HTTP client with provided or default base URL
48
+ this.httpClient = new HttpClient({
49
+ baseUrl: options.baseUrl || 'https://web-13239-04c55b73-wp4aqyqk.onporter.run',
117
50
  });
51
+ // Set auth if provided directly
52
+ if (options.apiKey) {
53
+ this.httpClient.setAuth('api_key', options.apiKey);
54
+ this.initialized = true;
55
+ }
56
+ else if (options.token) {
57
+ this.httpClient.setAuth('token', options.token);
58
+ this.initialized = true;
59
+ }
60
+ // Initialize API classes
61
+ this.agents = new AgentsAPI(this.httpClient);
62
+ this.usage = new UsageAPI(this.httpClient);
63
+ this.auth = new AuthAPI(this.httpClient);
118
64
  }
119
- async setupLocalConnection() {
120
- const baseUrl = (this.options.connectionUrl || DEFAULT_LOCAL_URL).replace(/\/$/, '');
121
- return {
122
- configUrl: `${baseUrl.replace('ws://', 'http://').replace('wss://', 'https://')}/config`,
123
- wsUrl: `${baseUrl.replace('http://', 'ws://').replace('https://', 'wss://')}/ws`,
124
- };
65
+ /**
66
+ * Initialize the client by loading credentials from config
67
+ * This is called automatically before the first API request
68
+ */
69
+ async initialize() {
70
+ if (this.initialized)
71
+ return;
72
+ // If already initializing, wait for it
73
+ if (this.initPromise) {
74
+ await this.initPromise;
75
+ return;
76
+ }
77
+ this.initPromise = this.doInitialize();
78
+ await this.initPromise;
125
79
  }
126
- async setupPlatformConnection() {
127
- if (!this.resolvedClientId) {
128
- throw new Error('CASTARI_CLIENT_ID is required when connecting via the Castari Platform');
129
- }
130
- const platformUrl = (this.options.platformUrl || process.env.CASTARI_PLATFORM_URL || DEFAULT_PLATFORM_URL).replace(/\/$/, '');
131
- if (this.options.debug) {
132
- console.log(`🚀 Requesting sandbox from ${platformUrl}...`);
133
- }
134
- const response = await fetch(`${platformUrl}/sandbox/start`, {
135
- method: 'POST',
136
- headers: {
137
- 'Content-Type': 'application/json',
138
- ...(this.resolvedPlatformApiKey
139
- ? { Authorization: `Bearer ${this.resolvedPlatformApiKey}` }
140
- : {}),
141
- },
142
- body: JSON.stringify({
143
- snapshot: this.options.snapshot,
144
- labels: this.options.labels,
145
- volume: this.options.volume,
146
- clientId: this.resolvedClientId
147
- })
148
- });
149
- if (!response.ok) {
150
- const errorText = await response.text();
151
- throw new Error(`Failed to start sandbox: ${errorText}`);
152
- }
153
- const { id, url, proxyUrl, authHeaders, authParams } = await response.json();
154
- this.sandboxId = id;
155
- // Default to proxy mode (true) unless explicitly disabled
156
- const useProxy = this.options.useProxy ?? (process.env.CASTARI_USE_PROXY !== 'false');
157
- if (this.options.debug) {
158
- console.log(`✅ Sandbox started: ${id} at ${url}`);
159
- if (useProxy && proxyUrl) {
160
- console.log(`🔀 Using proxy mode via ${proxyUrl}`);
80
+ async doInitialize() {
81
+ // Load auth from config if not provided
82
+ if (!this.options.apiKey && !this.options.token) {
83
+ const auth = await getAuth();
84
+ if (auth) {
85
+ this.httpClient.setAuth(auth.type, auth.value);
161
86
  }
162
87
  }
163
- // If proxy mode is enabled and we have a proxy URL, use it
164
- if (useProxy && proxyUrl) {
165
- // Proxy mode: connect through platform API
166
- const proxyConfigUrl = `${platformUrl}/proxy/${id}/config`;
167
- const proxyWsUrl = proxyUrl;
168
- return {
169
- configUrl: proxyConfigUrl,
170
- wsUrl: proxyWsUrl,
171
- // No auth headers/params needed - proxy handles sandbox auth
172
- cleanup: async () => {
173
- await this.stop({ delete: true });
174
- }
175
- };
176
- }
177
- // Direct mode: connect to sandbox directly
178
- const baseUrl = url.replace(/\/$/, '');
179
- const configUrl = `${baseUrl.replace('ws://', 'http://').replace('wss://', 'https://')}/config`;
180
- const wsUrlBase = `${baseUrl.replace('https://', 'wss://').replace('http://', 'ws://')}/ws`;
181
- return {
182
- configUrl,
183
- wsUrl: wsUrlBase,
184
- authHeaders,
185
- authParams,
186
- cleanup: async () => {
187
- await this.stop({ delete: true });
188
- }
189
- };
190
- }
191
- handleMessage(message) {
192
- if (this.options.debug) {
193
- console.log('📨 Received message:', JSON.stringify(message, null, 2));
194
- }
195
- this.messageHandlers.forEach(handler => handler(message));
88
+ this.initialized = true;
196
89
  }
197
- onMessage(handler) {
198
- this.messageHandlers.push(handler);
199
- return () => {
200
- this.messageHandlers = this.messageHandlers.filter(h => h !== handler);
201
- };
202
- }
203
- send(message) {
204
- if (!this.ws || this.ws.readyState !== WebSocket.OPEN) {
205
- throw new Error('WebSocket is not connected');
206
- }
207
- this.ws.send(JSON.stringify(message));
208
- }
209
- async stop(options = { delete: true }) {
210
- if (this.ws) {
211
- this.ws.close();
212
- }
213
- if (this.sandboxId) {
214
- const platformUrl = (this.options.platformUrl || process.env.CASTARI_PLATFORM_URL || DEFAULT_PLATFORM_URL).replace(/\/$/, '');
215
- try {
216
- const clientId = this.resolvedClientId || this.options.clientId || process.env.CASTARI_CLIENT_ID;
217
- const apiKey = this.resolvedPlatformApiKey || this.options.platformApiKey || process.env.CASTARI_API_KEY;
218
- const response = await fetch(`${platformUrl}/sandbox/stop`, {
219
- method: 'POST',
220
- headers: {
221
- 'Content-Type': 'application/json',
222
- ...(apiKey ? { Authorization: `Bearer ${apiKey}` } : {}),
223
- },
224
- body: JSON.stringify({
225
- sandboxId: this.sandboxId,
226
- delete: options.delete,
227
- clientId
228
- })
229
- });
230
- if (!response.ok) {
231
- console.error(`Failed to stop sandbox: ${await response.text()}`);
232
- }
233
- else if (this.options.debug) {
234
- console.log(`🛑 Sandbox ${options.delete ? 'deleted' : 'stopped'}`);
235
- }
236
- }
237
- catch (err) {
238
- console.error('Failed to call stop endpoint:', err);
239
- }
90
+ /**
91
+ * Ensure the client is initialized before making requests
92
+ * @throws AuthenticationError if no credentials are available
93
+ */
94
+ async ensureAuthenticated() {
95
+ await this.initialize();
96
+ const auth = await getAuth();
97
+ if (!auth && !this.options.apiKey && !this.options.token) {
98
+ throw new AuthenticationError();
240
99
  }
241
100
  }
242
101
  }
102
+ //# sourceMappingURL=client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,47 @@
1
+ /**
2
+ * Credentials stored in ~/.castari/credentials.yaml
3
+ */
4
+ export interface Credentials {
5
+ token?: string;
6
+ api_key?: string;
7
+ }
8
+ /**
9
+ * Config stored in ~/.castari/config.yaml
10
+ */
11
+ export interface Config {
12
+ api_url?: string;
13
+ }
14
+ /**
15
+ * Load credentials from ~/.castari/credentials.yaml
16
+ */
17
+ export declare function loadCredentials(): Promise<Credentials>;
18
+ /**
19
+ * Save credentials to ~/.castari/credentials.yaml
20
+ * File is created with mode 0600 for security
21
+ */
22
+ export declare function saveCredentials(credentials: Credentials): Promise<void>;
23
+ /**
24
+ * Clear all stored credentials
25
+ */
26
+ export declare function clearCredentials(): Promise<void>;
27
+ /**
28
+ * Load config from ~/.castari/config.yaml
29
+ */
30
+ export declare function loadConfig(): Promise<Config>;
31
+ /**
32
+ * Save config to ~/.castari/config.yaml
33
+ */
34
+ export declare function saveConfig(config: Config): Promise<void>;
35
+ /**
36
+ * Get the API URL from config, env var, or default
37
+ */
38
+ export declare function getApiUrl(): Promise<string>;
39
+ /**
40
+ * Get the auth token or API key from env vars or config
41
+ * Priority: CASTARI_API_KEY env var > credentials file
42
+ */
43
+ export declare function getAuth(): Promise<{
44
+ type: 'api_key' | 'token';
45
+ value: string;
46
+ } | null>;
47
+ //# sourceMappingURL=config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAeA;;GAEG;AACH,MAAM,WAAW,WAAW;IAC1B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED;;GAEG;AACH,MAAM,WAAW,MAAM;IACrB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAWD;;GAEG;AACH,wBAAsB,eAAe,IAAI,OAAO,CAAC,WAAW,CAAC,CAO5D;AAED;;;GAGG;AACH,wBAAsB,eAAe,CAAC,WAAW,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CAI7E;AAED;;GAEG;AACH,wBAAsB,gBAAgB,IAAI,OAAO,CAAC,IAAI,CAAC,CAMtD;AAED;;GAEG;AACH,wBAAsB,UAAU,IAAI,OAAO,CAAC,MAAM,CAAC,CAOlD;AAED;;GAEG;AACH,wBAAsB,UAAU,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAI9D;AAED;;GAEG;AACH,wBAAsB,SAAS,IAAI,OAAO,CAAC,MAAM,CAAC,CAcjD;AAED;;;GAGG;AACH,wBAAsB,OAAO,IAAI,OAAO,CAAC;IAAE,IAAI,EAAE,SAAS,GAAG,OAAO,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAAC,CAiB5F"}
package/dist/config.js ADDED
@@ -0,0 +1,108 @@
1
+ import { homedir } from 'node:os';
2
+ import { join } from 'node:path';
3
+ import { mkdir, readFile, writeFile, rm } from 'node:fs/promises';
4
+ import { existsSync } from 'node:fs';
5
+ import { parse as parseYaml, stringify as stringifyYaml } from 'yaml';
6
+ /** Directory for Castari config files */
7
+ const CONFIG_DIR = join(homedir(), '.castari');
8
+ /** Path to credentials file */
9
+ const CREDENTIALS_FILE = join(CONFIG_DIR, 'credentials.yaml');
10
+ /** Path to config file */
11
+ const CONFIG_FILE = join(CONFIG_DIR, 'config.yaml');
12
+ /**
13
+ * Ensure the config directory exists
14
+ */
15
+ async function ensureConfigDir() {
16
+ if (!existsSync(CONFIG_DIR)) {
17
+ await mkdir(CONFIG_DIR, { recursive: true, mode: 0o700 });
18
+ }
19
+ }
20
+ /**
21
+ * Load credentials from ~/.castari/credentials.yaml
22
+ */
23
+ export async function loadCredentials() {
24
+ try {
25
+ const content = await readFile(CREDENTIALS_FILE, 'utf-8');
26
+ return parseYaml(content) || {};
27
+ }
28
+ catch {
29
+ return {};
30
+ }
31
+ }
32
+ /**
33
+ * Save credentials to ~/.castari/credentials.yaml
34
+ * File is created with mode 0600 for security
35
+ */
36
+ export async function saveCredentials(credentials) {
37
+ await ensureConfigDir();
38
+ const content = stringifyYaml(credentials);
39
+ await writeFile(CREDENTIALS_FILE, content, { mode: 0o600 });
40
+ }
41
+ /**
42
+ * Clear all stored credentials
43
+ */
44
+ export async function clearCredentials() {
45
+ try {
46
+ await rm(CREDENTIALS_FILE);
47
+ }
48
+ catch {
49
+ // File doesn't exist, that's fine
50
+ }
51
+ }
52
+ /**
53
+ * Load config from ~/.castari/config.yaml
54
+ */
55
+ export async function loadConfig() {
56
+ try {
57
+ const content = await readFile(CONFIG_FILE, 'utf-8');
58
+ return parseYaml(content) || {};
59
+ }
60
+ catch {
61
+ return {};
62
+ }
63
+ }
64
+ /**
65
+ * Save config to ~/.castari/config.yaml
66
+ */
67
+ export async function saveConfig(config) {
68
+ await ensureConfigDir();
69
+ const content = stringifyYaml(config);
70
+ await writeFile(CONFIG_FILE, content, { mode: 0o644 });
71
+ }
72
+ /**
73
+ * Get the API URL from config, env var, or default
74
+ */
75
+ export async function getApiUrl() {
76
+ // Check env var first
77
+ if (process.env.CASTARI_API_URL) {
78
+ return process.env.CASTARI_API_URL;
79
+ }
80
+ // Check config file
81
+ const config = await loadConfig();
82
+ if (config.api_url) {
83
+ return config.api_url;
84
+ }
85
+ // Default
86
+ return 'https://web-13239-04c55b73-wp4aqyqk.onporter.run';
87
+ }
88
+ /**
89
+ * Get the auth token or API key from env vars or config
90
+ * Priority: CASTARI_API_KEY env var > credentials file
91
+ */
92
+ export async function getAuth() {
93
+ // Check env var first (for CI/CD)
94
+ const apiKey = process.env.CASTARI_API_KEY;
95
+ if (apiKey) {
96
+ return { type: 'api_key', value: apiKey };
97
+ }
98
+ // Check credentials file
99
+ const credentials = await loadCredentials();
100
+ if (credentials.api_key) {
101
+ return { type: 'api_key', value: credentials.api_key };
102
+ }
103
+ if (credentials.token) {
104
+ return { type: 'token', value: credentials.token };
105
+ }
106
+ return null;
107
+ }
108
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,52 @@
1
+ /**
2
+ * Base error class for all Castari SDK errors
3
+ */
4
+ export declare class CastariError extends Error {
5
+ /** Error code from the API */
6
+ code?: string;
7
+ /** HTTP status code */
8
+ statusCode?: number;
9
+ constructor(message: string, options?: {
10
+ code?: string;
11
+ statusCode?: number;
12
+ });
13
+ }
14
+ /**
15
+ * Error thrown when authentication fails or is missing
16
+ */
17
+ export declare class AuthenticationError extends CastariError {
18
+ constructor(message?: string);
19
+ }
20
+ /**
21
+ * Error thrown when a resource is not found
22
+ */
23
+ export declare class NotFoundError extends CastariError {
24
+ constructor(message?: string);
25
+ }
26
+ /**
27
+ * Error thrown when request validation fails
28
+ */
29
+ export declare class ValidationError extends CastariError {
30
+ constructor(message?: string);
31
+ }
32
+ /**
33
+ * Error thrown when rate limit is exceeded
34
+ */
35
+ export declare class RateLimitError extends CastariError {
36
+ /** Seconds to wait before retrying */
37
+ retryAfter?: number;
38
+ constructor(message?: string, retryAfter?: number);
39
+ }
40
+ /**
41
+ * Error thrown when the API returns a bad request
42
+ */
43
+ export declare class BadRequestError extends CastariError {
44
+ constructor(message?: string);
45
+ }
46
+ /**
47
+ * Error thrown for server-side errors
48
+ */
49
+ export declare class ServerError extends CastariError {
50
+ constructor(message?: string);
51
+ }
52
+ //# sourceMappingURL=errors.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,qBAAa,YAAa,SAAQ,KAAK;IACrC,8BAA8B;IAC9B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,uBAAuB;IACvB,UAAU,CAAC,EAAE,MAAM,CAAC;gBAER,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE;QAAE,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,UAAU,CAAC,EAAE,MAAM,CAAA;KAAE;CAM9E;AAED;;GAEG;AACH,qBAAa,mBAAoB,SAAQ,YAAY;gBACvC,OAAO,SAA+D;CAInF;AAED;;GAEG;AACH,qBAAa,aAAc,SAAQ,YAAY;gBACjC,OAAO,SAAwB;CAI5C;AAED;;GAEG;AACH,qBAAa,eAAgB,SAAQ,YAAY;gBACnC,OAAO,SAAsB;CAI1C;AAED;;GAEG;AACH,qBAAa,cAAe,SAAQ,YAAY;IAC9C,sCAAsC;IACtC,UAAU,CAAC,EAAE,MAAM,CAAC;gBAER,OAAO,SAAyB,EAAE,UAAU,CAAC,EAAE,MAAM;CAKlE;AAED;;GAEG;AACH,qBAAa,eAAgB,SAAQ,YAAY;gBACnC,OAAO,SAAiB;CAIrC;AAED;;GAEG;AACH,qBAAa,WAAY,SAAQ,YAAY;gBAC/B,OAAO,SAA0C;CAI9D"}
package/dist/errors.js ADDED
@@ -0,0 +1,73 @@
1
+ /**
2
+ * Base error class for all Castari SDK errors
3
+ */
4
+ export class CastariError extends Error {
5
+ /** Error code from the API */
6
+ code;
7
+ /** HTTP status code */
8
+ statusCode;
9
+ constructor(message, options) {
10
+ super(message);
11
+ this.name = 'CastariError';
12
+ this.code = options?.code;
13
+ this.statusCode = options?.statusCode;
14
+ }
15
+ }
16
+ /**
17
+ * Error thrown when authentication fails or is missing
18
+ */
19
+ export class AuthenticationError extends CastariError {
20
+ constructor(message = 'Authentication failed. Run \'cast login\' to authenticate.') {
21
+ super(message, { statusCode: 401 });
22
+ this.name = 'AuthenticationError';
23
+ }
24
+ }
25
+ /**
26
+ * Error thrown when a resource is not found
27
+ */
28
+ export class NotFoundError extends CastariError {
29
+ constructor(message = 'Resource not found.') {
30
+ super(message, { statusCode: 404 });
31
+ this.name = 'NotFoundError';
32
+ }
33
+ }
34
+ /**
35
+ * Error thrown when request validation fails
36
+ */
37
+ export class ValidationError extends CastariError {
38
+ constructor(message = 'Validation error.') {
39
+ super(message, { statusCode: 422 });
40
+ this.name = 'ValidationError';
41
+ }
42
+ }
43
+ /**
44
+ * Error thrown when rate limit is exceeded
45
+ */
46
+ export class RateLimitError extends CastariError {
47
+ /** Seconds to wait before retrying */
48
+ retryAfter;
49
+ constructor(message = 'Rate limit exceeded.', retryAfter) {
50
+ super(message, { statusCode: 429 });
51
+ this.name = 'RateLimitError';
52
+ this.retryAfter = retryAfter;
53
+ }
54
+ }
55
+ /**
56
+ * Error thrown when the API returns a bad request
57
+ */
58
+ export class BadRequestError extends CastariError {
59
+ constructor(message = 'Bad request.') {
60
+ super(message, { statusCode: 400 });
61
+ this.name = 'BadRequestError';
62
+ }
63
+ }
64
+ /**
65
+ * Error thrown for server-side errors
66
+ */
67
+ export class ServerError extends CastariError {
68
+ constructor(message = 'Server error. Please try again later.') {
69
+ super(message, { statusCode: 500 });
70
+ this.name = 'ServerError';
71
+ }
72
+ }
73
+ //# sourceMappingURL=errors.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.js","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,MAAM,OAAO,YAAa,SAAQ,KAAK;IACrC,8BAA8B;IAC9B,IAAI,CAAU;IACd,uBAAuB;IACvB,UAAU,CAAU;IAEpB,YAAY,OAAe,EAAE,OAAgD;QAC3E,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,cAAc,CAAC;QAC3B,IAAI,CAAC,IAAI,GAAG,OAAO,EAAE,IAAI,CAAC;QAC1B,IAAI,CAAC,UAAU,GAAG,OAAO,EAAE,UAAU,CAAC;IACxC,CAAC;CACF;AAED;;GAEG;AACH,MAAM,OAAO,mBAAoB,SAAQ,YAAY;IACnD,YAAY,OAAO,GAAG,4DAA4D;QAChF,KAAK,CAAC,OAAO,EAAE,EAAE,UAAU,EAAE,GAAG,EAAE,CAAC,CAAC;QACpC,IAAI,CAAC,IAAI,GAAG,qBAAqB,CAAC;IACpC,CAAC;CACF;AAED;;GAEG;AACH,MAAM,OAAO,aAAc,SAAQ,YAAY;IAC7C,YAAY,OAAO,GAAG,qBAAqB;QACzC,KAAK,CAAC,OAAO,EAAE,EAAE,UAAU,EAAE,GAAG,EAAE,CAAC,CAAC;QACpC,IAAI,CAAC,IAAI,GAAG,eAAe,CAAC;IAC9B,CAAC;CACF;AAED;;GAEG;AACH,MAAM,OAAO,eAAgB,SAAQ,YAAY;IAC/C,YAAY,OAAO,GAAG,mBAAmB;QACvC,KAAK,CAAC,OAAO,EAAE,EAAE,UAAU,EAAE,GAAG,EAAE,CAAC,CAAC;QACpC,IAAI,CAAC,IAAI,GAAG,iBAAiB,CAAC;IAChC,CAAC;CACF;AAED;;GAEG;AACH,MAAM,OAAO,cAAe,SAAQ,YAAY;IAC9C,sCAAsC;IACtC,UAAU,CAAU;IAEpB,YAAY,OAAO,GAAG,sBAAsB,EAAE,UAAmB;QAC/D,KAAK,CAAC,OAAO,EAAE,EAAE,UAAU,EAAE,GAAG,EAAE,CAAC,CAAC;QACpC,IAAI,CAAC,IAAI,GAAG,gBAAgB,CAAC;QAC7B,IAAI,CAAC,UAAU,GAAG,UAAU,CAAC;IAC/B,CAAC;CACF;AAED;;GAEG;AACH,MAAM,OAAO,eAAgB,SAAQ,YAAY;IAC/C,YAAY,OAAO,GAAG,cAAc;QAClC,KAAK,CAAC,OAAO,EAAE,EAAE,UAAU,EAAE,GAAG,EAAE,CAAC,CAAC;QACpC,IAAI,CAAC,IAAI,GAAG,iBAAiB,CAAC;IAChC,CAAC;CACF;AAED;;GAEG;AACH,MAAM,OAAO,WAAY,SAAQ,YAAY;IAC3C,YAAY,OAAO,GAAG,uCAAuC;QAC3D,KAAK,CAAC,OAAO,EAAE,EAAE,UAAU,EAAE,GAAG,EAAE,CAAC,CAAC;QACpC,IAAI,CAAC,IAAI,GAAG,aAAa,CAAC;IAC5B,CAAC;CACF"}
package/dist/http.d.ts ADDED
@@ -0,0 +1,32 @@
1
+ export type HttpMethod = 'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH';
2
+ export interface HttpClientOptions {
3
+ baseUrl: string;
4
+ authType?: 'api_key' | 'token';
5
+ authValue?: string;
6
+ }
7
+ /**
8
+ * HTTP client for making API requests
9
+ */
10
+ export declare class HttpClient {
11
+ private baseUrl;
12
+ private authType?;
13
+ private authValue?;
14
+ constructor(options: HttpClientOptions);
15
+ /**
16
+ * Set authentication credentials
17
+ */
18
+ setAuth(type: 'api_key' | 'token', value: string): void;
19
+ /**
20
+ * Make an HTTP request to the API
21
+ */
22
+ request<T>(method: HttpMethod, path: string, options?: {
23
+ body?: unknown;
24
+ query?: Record<string, string | number | undefined>;
25
+ timeout?: number;
26
+ }): Promise<T>;
27
+ /**
28
+ * Handle HTTP error responses
29
+ */
30
+ private handleError;
31
+ }
32
+ //# sourceMappingURL=http.d.ts.map