@agentuity/server 0.0.42 → 0.0.44

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.
Files changed (114) hide show
  1. package/dist/api/api.d.ts +28 -12
  2. package/dist/api/api.d.ts.map +1 -1
  3. package/dist/api/api.js +208 -84
  4. package/dist/api/api.js.map +1 -1
  5. package/dist/api/index.d.ts +2 -0
  6. package/dist/api/index.d.ts.map +1 -1
  7. package/dist/api/index.js +2 -0
  8. package/dist/api/index.js.map +1 -1
  9. package/dist/api/org/list.d.ts +14 -8
  10. package/dist/api/org/list.d.ts.map +1 -1
  11. package/dist/api/org/list.js +8 -3
  12. package/dist/api/org/list.js.map +1 -1
  13. package/dist/api/project/create.d.ts +15 -7
  14. package/dist/api/project/create.d.ts.map +1 -1
  15. package/dist/api/project/create.js +8 -3
  16. package/dist/api/project/create.js.map +1 -1
  17. package/dist/api/project/delete.d.ts.map +1 -1
  18. package/dist/api/project/delete.js +1 -1
  19. package/dist/api/project/delete.js.map +1 -1
  20. package/dist/api/project/deploy.d.ts +184 -0
  21. package/dist/api/project/deploy.d.ts.map +1 -0
  22. package/dist/api/project/deploy.js +160 -0
  23. package/dist/api/project/deploy.js.map +1 -0
  24. package/dist/api/project/env-delete.d.ts +15 -0
  25. package/dist/api/project/env-delete.d.ts.map +1 -0
  26. package/dist/api/project/env-delete.js +24 -0
  27. package/dist/api/project/env-delete.js.map +1 -0
  28. package/dist/api/project/env-update.d.ts +17 -0
  29. package/dist/api/project/env-update.d.ts.map +1 -0
  30. package/dist/api/project/env-update.js +39 -0
  31. package/dist/api/project/env-update.js.map +1 -0
  32. package/dist/api/project/exists.d.ts +7 -5
  33. package/dist/api/project/exists.d.ts.map +1 -1
  34. package/dist/api/project/exists.js +1 -1
  35. package/dist/api/project/exists.js.map +1 -1
  36. package/dist/api/project/get.d.ts +7 -12
  37. package/dist/api/project/get.d.ts.map +1 -1
  38. package/dist/api/project/get.js +5 -4
  39. package/dist/api/project/get.js.map +1 -1
  40. package/dist/api/project/index.d.ts +3 -0
  41. package/dist/api/project/index.d.ts.map +1 -1
  42. package/dist/api/project/index.js +3 -0
  43. package/dist/api/project/index.js.map +1 -1
  44. package/dist/api/project/list.d.ts +20 -8
  45. package/dist/api/project/list.d.ts.map +1 -1
  46. package/dist/api/project/list.js +9 -6
  47. package/dist/api/project/list.js.map +1 -1
  48. package/dist/api/region/create.d.ts +46 -0
  49. package/dist/api/region/create.d.ts.map +1 -0
  50. package/dist/api/region/create.js +35 -0
  51. package/dist/api/region/create.js.map +1 -0
  52. package/dist/api/region/delete.d.ts +38 -0
  53. package/dist/api/region/delete.d.ts.map +1 -0
  54. package/dist/api/region/delete.js +31 -0
  55. package/dist/api/region/delete.js.map +1 -0
  56. package/dist/api/region/index.d.ts +5 -0
  57. package/dist/api/region/index.d.ts.map +1 -0
  58. package/dist/api/region/index.js +5 -0
  59. package/dist/api/region/index.js.map +1 -0
  60. package/dist/api/region/list.d.ts +27 -0
  61. package/dist/api/region/list.d.ts.map +1 -0
  62. package/dist/api/region/list.js +21 -0
  63. package/dist/api/region/list.js.map +1 -0
  64. package/dist/api/region/resources.d.ts +53 -0
  65. package/dist/api/region/resources.d.ts.map +1 -0
  66. package/dist/api/region/resources.js +35 -0
  67. package/dist/api/region/resources.js.map +1 -0
  68. package/dist/api/user/index.d.ts +2 -0
  69. package/dist/api/user/index.d.ts.map +1 -0
  70. package/dist/api/user/index.js +2 -0
  71. package/dist/api/user/index.js.map +1 -0
  72. package/dist/api/user/whoami.d.ts +35 -0
  73. package/dist/api/user/whoami.d.ts.map +1 -0
  74. package/dist/api/user/whoami.js +26 -0
  75. package/dist/api/user/whoami.js.map +1 -0
  76. package/dist/config.d.ts +1 -0
  77. package/dist/config.d.ts.map +1 -1
  78. package/dist/config.js +1 -0
  79. package/dist/config.js.map +1 -1
  80. package/dist/index.d.ts +1 -0
  81. package/dist/index.d.ts.map +1 -1
  82. package/dist/index.js +1 -0
  83. package/dist/index.js.map +1 -1
  84. package/dist/logger.d.ts +39 -0
  85. package/dist/logger.d.ts.map +1 -0
  86. package/dist/logger.js +241 -0
  87. package/dist/logger.js.map +1 -0
  88. package/dist/server.js +2 -2
  89. package/dist/server.js.map +1 -1
  90. package/package.json +4 -2
  91. package/src/api/api-example.md +16 -11
  92. package/src/api/api.ts +254 -93
  93. package/src/api/index.ts +2 -0
  94. package/src/api/org/list.ts +13 -10
  95. package/src/api/project/create.ts +14 -9
  96. package/src/api/project/delete.ts +2 -2
  97. package/src/api/project/deploy.ts +224 -0
  98. package/src/api/project/env-delete.ts +40 -0
  99. package/src/api/project/env-update.ts +59 -0
  100. package/src/api/project/exists.ts +1 -1
  101. package/src/api/project/get.ts +12 -12
  102. package/src/api/project/index.ts +3 -0
  103. package/src/api/project/list.ts +20 -15
  104. package/src/api/region/create.ts +55 -0
  105. package/src/api/region/delete.ts +49 -0
  106. package/src/api/region/index.ts +4 -0
  107. package/src/api/region/list.ts +31 -0
  108. package/src/api/region/resources.ts +51 -0
  109. package/src/api/user/index.ts +1 -0
  110. package/src/api/user/whoami.ts +31 -0
  111. package/src/config.ts +2 -0
  112. package/src/index.ts +1 -0
  113. package/src/logger.ts +291 -0
  114. package/src/server.ts +2 -2
package/src/api/api.ts CHANGED
@@ -9,6 +9,7 @@
9
9
  */
10
10
 
11
11
  import { z } from 'zod';
12
+ import type { Logger } from '@agentuity/core';
12
13
 
13
14
  export interface APIErrorResponse {
14
15
  success: boolean;
@@ -24,14 +25,19 @@ export interface APIErrorResponse {
24
25
  export interface APIClientConfig {
25
26
  skipVersionCheck?: boolean;
26
27
  userAgent?: string;
28
+ maxRetries?: number;
29
+ retryDelayMs?: number;
27
30
  }
28
31
 
29
32
  export class ValidationError extends Error {
33
+ public url: string;
30
34
  constructor(
35
+ url: string,
31
36
  message: string,
32
37
  public issues: z.ZodIssue[]
33
38
  ) {
34
39
  super(message);
40
+ this.url = url;
35
41
  this.name = 'ValidationError';
36
42
  }
37
43
  }
@@ -55,33 +61,39 @@ export class APIError extends Error {
55
61
  }
56
62
 
57
63
  export class APIClient {
58
- private baseUrl: string;
59
- private apiKey?: string;
60
- private config?: APIClientConfig;
64
+ #baseUrl: string;
65
+ #apiKey?: string;
66
+ #config?: APIClientConfig;
67
+ #logger: Logger;
61
68
 
62
- constructor(baseUrl: string, config?: APIClientConfig);
63
- constructor(baseUrl: string, apiKey: string, config?: APIClientConfig);
69
+ constructor(baseUrl: string, logger: Logger, config?: APIClientConfig);
70
+ constructor(baseUrl: string, logger: Logger, apiKey: string, config?: APIClientConfig);
64
71
  constructor(
65
72
  baseUrl: string,
73
+ logger: Logger,
66
74
  apiKeyOrConfig?: string | APIClientConfig,
67
75
  config?: APIClientConfig
68
76
  ) {
69
- this.baseUrl = baseUrl;
77
+ this.#baseUrl = baseUrl;
78
+ this.#logger = logger;
70
79
 
71
- // Detect if second parameter is apiKey (string) or config (object)
80
+ // Detect if third parameter is apiKey (string) or config (object)
72
81
  if (typeof apiKeyOrConfig === 'string') {
73
- this.apiKey = apiKeyOrConfig;
74
- this.config = config;
82
+ this.#apiKey = apiKeyOrConfig;
83
+ this.#config = config;
75
84
  } else {
76
- this.apiKey = undefined;
77
- this.config = apiKeyOrConfig;
85
+ this.#apiKey = undefined;
86
+ this.#config = apiKeyOrConfig;
87
+ }
88
+ if (!this.#apiKey && process.env.AGENTUITY_SDK_KEY) {
89
+ this.#apiKey = process.env.AGENTUITY_SDK_KEY;
78
90
  }
79
91
  }
80
92
 
81
- async request<TResponse, TBody = unknown>(
93
+ async request<TResponse = void, TBody = unknown>(
82
94
  method: string,
83
95
  endpoint: string,
84
- responseSchema: z.ZodType<TResponse>,
96
+ responseSchema?: z.ZodType<TResponse>,
85
97
  body?: TBody,
86
98
  bodySchema?: z.ZodType<TBody>
87
99
  ): Promise<TResponse> {
@@ -90,13 +102,14 @@ export class APIClient {
90
102
  const validationResult = bodySchema.safeParse(body);
91
103
  if (!validationResult.success) {
92
104
  throw new ValidationError(
105
+ endpoint,
93
106
  'Request body validation failed',
94
107
  validationResult.error.issues
95
108
  );
96
109
  }
97
110
  }
98
111
 
99
- const response = await this.makeRequest(method, endpoint, body);
112
+ const response = await this.#makeRequest(method, endpoint, body);
100
113
 
101
114
  // Handle empty responses (204 or zero-length body)
102
115
  let data: unknown;
@@ -108,7 +121,7 @@ export class APIClient {
108
121
  data = null;
109
122
  } else {
110
123
  const contentType = response.headers.get('content-type');
111
- if (contentType && contentType.includes('application/json')) {
124
+ if (contentType?.includes('application/json')) {
112
125
  data = JSON.parse(text);
113
126
  } else {
114
127
  data = text;
@@ -116,105 +129,225 @@ export class APIClient {
116
129
  }
117
130
  }
118
131
 
119
- // Validate response
120
- const validationResult = responseSchema.safeParse(data);
121
- if (!validationResult.success) {
122
- throw new ValidationError('Response validation failed', validationResult.error.issues);
132
+ if (responseSchema) {
133
+ // Validate response
134
+ const validationResult = responseSchema.safeParse(data);
135
+ if (!validationResult.success) {
136
+ throw new ValidationError(
137
+ endpoint,
138
+ 'Response validation failed',
139
+ validationResult.error.issues
140
+ );
141
+ }
142
+
143
+ return validationResult.data;
123
144
  }
124
145
 
125
- return validationResult.data;
146
+ return undefined as TResponse;
126
147
  }
127
148
 
128
- private async makeRequest(method: string, endpoint: string, body?: unknown): Promise<Response> {
129
- const url = `${this.baseUrl}${endpoint}`;
130
- const headers: Record<string, string> = {
131
- 'Content-Type': 'application/json',
132
- };
149
+ async #makeRequest(method: string, endpoint: string, body?: unknown): Promise<Response> {
150
+ const maxRetries = this.#config?.maxRetries ?? 3;
151
+ const baseDelayMs = this.#config?.retryDelayMs ?? 100;
133
152
 
134
- if (this.config?.userAgent) {
135
- headers['User-Agent'] = this.config.userAgent;
136
- }
153
+ for (let attempt = 0; attempt <= maxRetries; attempt++) {
154
+ try {
155
+ const url = `${this.#baseUrl}${endpoint}`;
156
+ const headers: Record<string, string> = {
157
+ 'Content-Type': 'application/json',
158
+ };
137
159
 
138
- if (this.apiKey) {
139
- headers['Authorization'] = `Bearer ${this.apiKey}`;
140
- }
160
+ if (this.#config?.userAgent) {
161
+ headers['User-Agent'] = this.#config.userAgent;
162
+ }
141
163
 
142
- const response = await fetch(url, {
143
- method,
144
- headers,
145
- body: body !== undefined ? JSON.stringify(body) : undefined,
146
- });
164
+ if (this.#apiKey) {
165
+ headers['Authorization'] = `Bearer ${this.#apiKey}`;
166
+ }
147
167
 
148
- if (!response.ok) {
149
- const responseBody = await response.text();
168
+ const response = await fetch(url, {
169
+ method,
170
+ headers,
171
+ body: body !== undefined ? JSON.stringify(body) : undefined,
172
+ });
173
+
174
+ // Check if we should retry on specific status codes (409, 501, 503)
175
+ const retryableStatuses = [409, 501, 503];
176
+ if (retryableStatuses.includes(response.status) && attempt < maxRetries) {
177
+ let delayMs = this.#getRetryDelay(attempt, baseDelayMs);
178
+
179
+ // For 409, check for rate limit headers
180
+ if (response.status === 409) {
181
+ const rateLimitDelay = this.#getRateLimitDelay(response);
182
+ if (rateLimitDelay !== null) {
183
+ delayMs = rateLimitDelay;
184
+ this.#logger.debug(
185
+ `Got 409 with rate limit headers, waiting ${delayMs}ms (attempt ${attempt + 1}/${maxRetries + 1})`
186
+ );
187
+ } else {
188
+ this.#logger.debug(
189
+ `Got 409, retrying with backoff ${delayMs}ms (attempt ${attempt + 1}/${maxRetries + 1})`
190
+ );
191
+ }
192
+ } else {
193
+ this.#logger.debug(
194
+ `Got ${response.status}, retrying (attempt ${attempt + 1}/${maxRetries + 1})`
195
+ );
196
+ }
150
197
 
151
- // Try to parse error response
152
- let errorData: APIErrorResponse | null = null;
153
- try {
154
- errorData = JSON.parse(responseBody) as APIErrorResponse;
155
- } catch {
156
- // Not JSON, ignore
157
- }
198
+ await this.#sleep(delayMs);
199
+ continue;
200
+ }
158
201
 
159
- if (process.env.DEBUG) {
160
- // Sanitize headers to avoid leaking API keys
161
- const sanitizedHeaders = { ...headers };
162
- for (const key in sanitizedHeaders) {
163
- if (key.toLowerCase() === 'authorization') {
164
- sanitizedHeaders[key] = 'REDACTED';
202
+ // Handle error responses
203
+ if (!response.ok) {
204
+ const responseBody = await response.text();
205
+
206
+ // Try to parse error response
207
+ let errorData: APIErrorResponse | null = null;
208
+ try {
209
+ errorData = JSON.parse(responseBody) as APIErrorResponse;
210
+ } catch {
211
+ // Not JSON, ignore
165
212
  }
166
- }
167
213
 
168
- console.error('API Error Details:');
169
- console.error(' URL:', url);
170
- console.error(' Method:', method);
171
- console.error(' Status:', response.status, response.statusText);
172
- console.error(' Headers:', JSON.stringify(sanitizedHeaders, null, 2));
173
- console.error(' Response:', responseBody);
174
- }
214
+ // Sanitize headers to avoid leaking API keys
215
+ const sanitizedHeaders = { ...headers };
216
+ for (const key in sanitizedHeaders) {
217
+ if (key.toLowerCase() === 'authorization') {
218
+ sanitizedHeaders[key] = 'REDACTED';
219
+ }
220
+ }
221
+
222
+ this.#logger.debug('API Error Details:');
223
+ this.#logger.debug(' URL:', url);
224
+ this.#logger.debug(' Method:', method);
225
+ this.#logger.debug(' Status:', response.status, response.statusText);
226
+ this.#logger.debug(' Headers:', JSON.stringify(sanitizedHeaders, null, 2));
227
+ this.#logger.debug(' Response:', responseBody);
228
+
229
+ // Check for UPGRADE_REQUIRED error
230
+ if (errorData?.code === 'UPGRADE_REQUIRED') {
231
+ // Skip version check if configured
232
+ if (this.#config?.skipVersionCheck) {
233
+ this.#logger.debug('Skipping version check (configured to skip)');
234
+ // Request is still rejected, but throw UpgradeRequiredError so callers
235
+ // can detect it and handle UI behavior (e.g., suppress banner) based on skip flag
236
+ throw new UpgradeRequiredError(
237
+ errorData.message ||
238
+ 'Version check skipped, but request failed. Try upgrading the client.'
239
+ );
240
+ }
241
+
242
+ throw new UpgradeRequiredError(
243
+ errorData.message || 'Please upgrade to the latest version'
244
+ );
245
+ }
175
246
 
176
- // Check for UPGRADE_REQUIRED error
177
- if (errorData?.code === 'UPGRADE_REQUIRED') {
178
- // Skip version check if configured
179
- if (this.config?.skipVersionCheck) {
180
- if (process.env.DEBUG) {
181
- console.error('[DEBUG] Skipping version check (configured to skip)');
247
+ // Handle Zod validation errors from the API
248
+ if (errorData?.error?.name === 'ZodError' && errorData.error.issues) {
249
+ throw new ValidationError(url, 'API validation failed', errorData.error.issues);
182
250
  }
183
- // Request is still rejected, but throw UpgradeRequiredError so callers
184
- // can detect it and handle UI behavior (e.g., suppress banner) based on skip flag
185
- throw new UpgradeRequiredError(
186
- errorData.message ||
187
- 'Version check skipped, but request failed. Try upgrading the client.'
251
+
252
+ // Throw with message from API if available
253
+ if (errorData?.message) {
254
+ throw new APIError(errorData.message, response.status, errorData.code);
255
+ }
256
+
257
+ throw new APIError(
258
+ `API error: ${response.status} ${response.statusText}`,
259
+ response.status
188
260
  );
189
261
  }
190
262
 
191
- throw new UpgradeRequiredError(
192
- errorData.message || 'Please upgrade to the latest version'
193
- );
194
- }
263
+ // Successful response; handle empty bodies (e.g., 204 No Content)
264
+ if (response.status === 204 || response.headers.get('content-length') === '0') {
265
+ return new Response(null, { status: 204 });
266
+ }
195
267
 
196
- // Handle Zod validation errors from the API
197
- if (errorData?.error?.name === 'ZodError' && errorData.error.issues) {
198
- throw new ValidationError('API validation failed', errorData.error.issues);
199
- }
268
+ return response;
269
+ } catch (error) {
270
+ // Check if it's a retryable connection error
271
+ const isRetryable = this.#isRetryableError(error);
272
+
273
+ if (isRetryable && attempt < maxRetries) {
274
+ this.#logger.debug(
275
+ `Connection error, retrying (attempt ${attempt + 1}/${maxRetries + 1}):`,
276
+ error
277
+ );
278
+ await this.#sleep(this.#getRetryDelay(attempt, baseDelayMs));
279
+ continue;
280
+ }
200
281
 
201
- // Throw with message from API if available
202
- if (errorData?.message) {
203
- throw new APIError(errorData.message, response.status, errorData.code);
282
+ throw error;
204
283
  }
284
+ }
285
+
286
+ throw new Error('Max retries exceeded');
287
+ }
205
288
 
206
- throw new APIError(
207
- `API error: ${response.status} ${response.statusText}`,
208
- response.status
289
+ #isRetryableError(error: unknown): boolean {
290
+ if (error && typeof error === 'object') {
291
+ const err = error as { code?: string; errno?: number };
292
+ // Retryable connection errors
293
+ return (
294
+ err.code === 'ECONNRESET' ||
295
+ err.code === 'ETIMEDOUT' ||
296
+ err.code === 'ECONNREFUSED' ||
297
+ err.code === 'ENOTFOUND'
209
298
  );
210
299
  }
300
+ return false;
301
+ }
211
302
 
212
- // Successful response; handle empty bodies (e.g., 204 No Content)
213
- if (response.status === 204 || response.headers.get('content-length') === '0') {
214
- return new Response(null, { status: 204 });
303
+ #getRetryDelay(attempt: number, baseDelayMs: number): number {
304
+ // Exponential backoff with jitter: delay = base * 2^attempt * (0.5 + random(0, 0.5))
305
+ const exponentialDelay = baseDelayMs * Math.pow(2, attempt);
306
+ const jitter = 0.5 + Math.random() * 0.5;
307
+ return Math.floor(exponentialDelay * jitter);
308
+ }
309
+
310
+ #sleep(ms: number): Promise<void> {
311
+ return new Promise((resolve) => setTimeout(resolve, ms));
312
+ }
313
+
314
+ #getRateLimitDelay(response: Response): number | null {
315
+ // Check for Retry-After header (standard HTTP)
316
+ const retryAfter = response.headers.get('Retry-After');
317
+ if (retryAfter) {
318
+ // Can be either seconds or HTTP date
319
+ const seconds = parseInt(retryAfter, 10);
320
+ if (!isNaN(seconds)) {
321
+ return seconds * 1000; // Convert to milliseconds
322
+ }
323
+ // Try parsing as HTTP date
324
+ const retryDate = new Date(retryAfter);
325
+ if (!isNaN(retryDate.getTime())) {
326
+ const delayMs = retryDate.getTime() - Date.now();
327
+ return Math.max(0, delayMs);
328
+ }
329
+ }
330
+
331
+ // Check for X-RateLimit-Reset (Unix timestamp in seconds)
332
+ const rateLimitReset = response.headers.get('X-RateLimit-Reset');
333
+ if (rateLimitReset) {
334
+ const resetTime = parseInt(rateLimitReset, 10);
335
+ if (!isNaN(resetTime)) {
336
+ const delayMs = resetTime * 1000 - Date.now();
337
+ return Math.max(0, delayMs);
338
+ }
339
+ }
340
+
341
+ // Check for X-RateLimit-Retry-After (seconds)
342
+ const rateLimitRetryAfter = response.headers.get('X-RateLimit-Retry-After');
343
+ if (rateLimitRetryAfter) {
344
+ const seconds = parseInt(rateLimitRetryAfter, 10);
345
+ if (!isNaN(seconds)) {
346
+ return seconds * 1000;
347
+ }
215
348
  }
216
349
 
217
- return response;
350
+ return null;
218
351
  }
219
352
  }
220
353
 
@@ -243,8 +376,36 @@ export function getAppBaseURL(overrides?: { app_url?: string }): string {
243
376
  }
244
377
 
245
378
  export const APIResponseSchema = <T extends z.ZodType>(dataSchema: T) =>
246
- z.object({
247
- success: z.boolean(),
248
- message: z.string().optional().describe('the error message if success=false'),
249
- data: dataSchema.optional(),
250
- });
379
+ z.discriminatedUnion('success', [
380
+ z.object({
381
+ success: z.literal<false>(false),
382
+ message: z.string().describe('the error message'),
383
+ }),
384
+ z.object({
385
+ success: z.literal<true>(true),
386
+ data: dataSchema,
387
+ }),
388
+ ]);
389
+
390
+ export const APIResponseSchemaOptionalData = <T extends z.ZodType>(dataSchema: T) =>
391
+ z.discriminatedUnion('success', [
392
+ z.object({
393
+ success: z.literal<false>(false),
394
+ message: z.string().describe('the error message'),
395
+ }),
396
+ z.object({
397
+ success: z.literal<true>(true),
398
+ data: dataSchema.optional(),
399
+ }),
400
+ ]);
401
+
402
+ export const APIResponseSchemaNoData = () =>
403
+ z.discriminatedUnion('success', [
404
+ z.object({
405
+ success: z.literal<false>(false),
406
+ message: z.string().describe('the error message'),
407
+ }),
408
+ z.object({
409
+ success: z.literal<true>(true),
410
+ }),
411
+ ]);
package/src/api/index.ts CHANGED
@@ -1,3 +1,5 @@
1
1
  export * from './api';
2
2
  export * from './org';
3
3
  export * from './project';
4
+ export * from './region';
5
+ export * from './user';
@@ -1,17 +1,16 @@
1
1
  import { z } from 'zod';
2
2
  import { APIResponseSchema, APIClient } from '../api';
3
3
 
4
- const ListOrganizationsResponseSchema = APIResponseSchema(
5
- z.array(
6
- z.object({
7
- id: z.string().describe('the unique id for the organization'),
8
- name: z.string().describe('the name of the organization'),
9
- })
10
- )
4
+ const ListOrganizationsResponse = z.array(
5
+ z.object({
6
+ id: z.string().describe('the unique id for the organization'),
7
+ name: z.string().describe('the name of the organization'),
8
+ })
11
9
  );
10
+ const ListOrganizationsResponseSchema = APIResponseSchema(ListOrganizationsResponse);
12
11
 
13
12
  export type ListOrganizationsResponse = z.infer<typeof ListOrganizationsResponseSchema>;
14
- export type OrganizationList = NonNullable<ListOrganizationsResponse['data']>;
13
+ export type OrganizationList = z.infer<typeof ListOrganizationsResponse>;
15
14
 
16
15
  /**
17
16
  * List all organizations
@@ -19,10 +18,14 @@ export type OrganizationList = NonNullable<ListOrganizationsResponse['data']>;
19
18
  * @param client
20
19
  * @returns
21
20
  */
22
- export async function listOrganizations(client: APIClient): Promise<ListOrganizationsResponse> {
23
- return client.request<ListOrganizationsResponse>(
21
+ export async function listOrganizations(client: APIClient): Promise<OrganizationList> {
22
+ const resp = await client.request<ListOrganizationsResponse>(
24
23
  'GET',
25
24
  '/cli/organization',
26
25
  ListOrganizationsResponseSchema
27
26
  );
27
+ if (resp.success) {
28
+ return resp.data;
29
+ }
30
+ throw new Error(resp.message);
28
31
  }
@@ -11,16 +11,17 @@ const CreateProjectRequestSchema = z.object({
11
11
  provider: z.string().max(255).min(1),
12
12
  });
13
13
 
14
- const CreateProjectResponseSchema = APIResponseSchema(
15
- z.object({
16
- id: z.string().describe('the unique id for the project'),
17
- api_key: z.string().describe('the SDK api key for the project'),
18
- projectKey: z.string().describe('the Project api key for the project'),
19
- })
20
- );
14
+ const CreateProjectResponse = z.object({
15
+ id: z.string().describe('the unique id for the project'),
16
+ api_key: z.string().describe('the SDK api key for the project'),
17
+ projectKey: z.string().describe('the Project api key for the project'),
18
+ });
19
+
20
+ const CreateProjectResponseSchema = APIResponseSchema(CreateProjectResponse);
21
21
 
22
22
  export type CreateProjectRequest = z.infer<typeof CreateProjectRequestSchema>;
23
23
  export type CreateProjectResponse = z.infer<typeof CreateProjectResponseSchema>;
24
+ export type NewProject = Omit<z.infer<typeof CreateProjectResponse>, 'projectKey'>;
24
25
 
25
26
  /**
26
27
  * Create a new Project
@@ -32,12 +33,16 @@ export type CreateProjectResponse = z.infer<typeof CreateProjectResponseSchema>;
32
33
  export async function projectCreate(
33
34
  client: APIClient,
34
35
  body: CreateProjectRequest
35
- ): Promise<Omit<CreateProjectResponse, 'projectKey'>> {
36
- return client.request<CreateProjectResponse, CreateProjectRequest>(
36
+ ): Promise<NewProject> {
37
+ const resp = await client.request<CreateProjectResponse, CreateProjectRequest>(
37
38
  'POST',
38
39
  '/cli/project',
39
40
  CreateProjectResponseSchema,
40
41
  body,
41
42
  CreateProjectRequestSchema
42
43
  );
44
+ if (resp.success) {
45
+ return resp.data;
46
+ }
47
+ throw new Error(resp.message);
43
48
  }
@@ -7,7 +7,7 @@ const ProjectDeleteResponseSchema = APIResponseSchema(z.array(z.string()));
7
7
  type ProjectDeleteRequest = z.infer<typeof ProjectDeleteRequestSchema>;
8
8
  type ProjectDeleteResponse = z.infer<typeof ProjectDeleteResponseSchema>;
9
9
 
10
- export async function projectDelete(client: APIClient, ...ids: string[]) {
10
+ export async function projectDelete(client: APIClient, ...ids: string[]): Promise<string[]> {
11
11
  const resp = await client.request<ProjectDeleteResponse, ProjectDeleteRequest>(
12
12
  'DELETE',
13
13
  '/cli/project',
@@ -16,7 +16,7 @@ export async function projectDelete(client: APIClient, ...ids: string[]) {
16
16
  ProjectDeleteRequestSchema
17
17
  );
18
18
 
19
- if (resp.data) {
19
+ if (resp.success) {
20
20
  return resp.data;
21
21
  }
22
22