@amigo-ai/sdk 1.0.0-alpha.1

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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Amigo
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,94 @@
1
+ # Amigo TypeScript SDK
2
+
3
+ [![Tests](https://github.com/amigo-ai/amigo-typescript-sdk/actions/workflows/test.yml/badge.svg)](https://github.com/amigo-ai/amigo-typescript-sdk/actions/workflows/test.yml)
4
+ [![codecov](https://codecov.io/gh/amigo-ai/amigo-typescript-sdk/graph/badge.svg?token=PQU5JBU941)](https://codecov.io/gh/amigo-ai/amigo-typescript-sdk)
5
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
6
+
7
+ The official TypeScript SDK for the Amigo API, providing a simple and intuitive interface to interact with Amigo's AI services.
8
+
9
+ ## Installation
10
+
11
+ Install the SDK using npm:
12
+
13
+ ```bash
14
+ npm install @amigo/amigo-typescript-sdk
15
+ ```
16
+
17
+ ## Quick Start
18
+
19
+ ```typescript
20
+ import { AmigoClient } from '@amigo/amigo-typescript-sdk'
21
+
22
+ // Initialize the client
23
+ const client = new AmigoClient({
24
+ apiKey: 'your-api-key',
25
+ apiKeyId: 'your-api-key-id',
26
+ userId: 'user-id',
27
+ orgId: 'your-organization-id',
28
+ })
29
+
30
+ // Get organization details
31
+ async function example() {
32
+ try {
33
+ const organization = await client.organizations.getOrganization('your-org-id')
34
+ console.log('Organization:', organization)
35
+ } catch (error) {
36
+ console.error('Error:', error)
37
+ }
38
+ }
39
+
40
+ example()
41
+ ```
42
+
43
+ ## Configuration
44
+
45
+ The SDK requires the following configuration parameters:
46
+
47
+ | Parameter | Type | Required | Description |
48
+ | ---------- | ------ | -------- | -------------------------------------------------------------- |
49
+ | `apiKey` | string | ✅ | API key from Amigo dashboard |
50
+ | `apiKeyId` | string | ✅ | API key ID from Amigo dashboard |
51
+ | `userId` | string | ✅ | User ID on whose behalf the request is made |
52
+ | `orgId` | string | ✅ | Your organization ID |
53
+ | `baseUrl` | string | ❌ | Base URL of the Amigo API (defaults to `https://api.amigo.ai`) |
54
+
55
+ ### Getting Your API Credentials
56
+
57
+ 1. **API Key & API Key ID**: Generate these from your Amigo admin dashboard or programmatically using the API
58
+ 2. **Organization ID**: Found in your Amigo dashboard URL or organization settings
59
+ 3. **User ID**: The ID of the user you want to impersonate for API calls
60
+
61
+ For detailed instructions on generating API keys, see the [Authentication Guide](https://docs.amigo.ai/developer-guide).
62
+
63
+ ## Error Handling
64
+
65
+ The SDK provides typed error handling:
66
+
67
+ ```typescript
68
+ import { AmigoClient, errors } from '@amigo/amigo-typescript-sdk'
69
+
70
+ try {
71
+ const result = await client.organizations.getOrganization('org-id')
72
+ } catch (error) {
73
+ if (error instanceof errors.AuthenticationError) {
74
+ console.error('Authentication failed:', error.message)
75
+ } else if (error instanceof errors.NetworkError) {
76
+ console.error('Network error:', error.message)
77
+ } else {
78
+ console.error('Unexpected error:', error)
79
+ }
80
+ }
81
+ ```
82
+
83
+ ## Documentation
84
+
85
+ - **Developer Guide**: [https://docs.amigo.ai/developer-guide](https://docs.amigo.ai/developer-guide)
86
+ - **API Reference**: [https://docs.amigo.ai/api-reference](https://docs.amigo.ai/api-reference)
87
+
88
+ ## License
89
+
90
+ This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
91
+
92
+ ## Support
93
+
94
+ For questions, issues, or feature requests, please visit our [GitHub repository](https://github.com/amigo-ai/amigo-typescript-sdk) or contact support through the Amigo dashboard.
package/dist/index.js ADDED
@@ -0,0 +1,353 @@
1
+ var __defProp = Object.defineProperty;
2
+ var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
3
+ var __export = (target, all) => {
4
+ for (var name in all)
5
+ __defProp(target, name, { get: all[name], enumerable: true });
6
+ };
7
+ var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
8
+
9
+ // src/core/errors.ts
10
+ var errors_exports = {};
11
+ __export(errors_exports, {
12
+ AmigoError: () => AmigoError,
13
+ AuthenticationError: () => AuthenticationError,
14
+ BadRequestError: () => BadRequestError,
15
+ ConfigurationError: () => ConfigurationError,
16
+ ConflictError: () => ConflictError,
17
+ NetworkError: () => NetworkError,
18
+ NotFoundError: () => NotFoundError,
19
+ ParseError: () => ParseError,
20
+ PermissionError: () => PermissionError,
21
+ RateLimitError: () => RateLimitError,
22
+ ServerError: () => ServerError,
23
+ ServiceUnavailableError: () => ServiceUnavailableError,
24
+ ValidationError: () => ValidationError,
25
+ createApiError: () => createApiError,
26
+ createErrorMiddleware: () => createErrorMiddleware,
27
+ isAmigoError: () => isAmigoError
28
+ });
29
+
30
+ // src/core/utils.ts
31
+ async function extractData(responsePromise) {
32
+ const result = await responsePromise;
33
+ return result.data;
34
+ }
35
+ async function parseResponseBody(response) {
36
+ try {
37
+ const text = await response.text();
38
+ if (!text) return void 0;
39
+ try {
40
+ return JSON.parse(text);
41
+ } catch {
42
+ return text;
43
+ }
44
+ } catch {
45
+ return void 0;
46
+ }
47
+ }
48
+ function isNetworkError(error) {
49
+ if (!(error instanceof Error)) return false;
50
+ return error instanceof TypeError || error.message.includes("fetch") || error.message.includes("Failed to fetch") || error.message.includes("Network request failed") || error.message.includes("ECONNREFUSED") || error.message.includes("ETIMEDOUT") || error.message.includes("ENOTFOUND") || error.message.includes("network");
51
+ }
52
+
53
+ // src/core/errors.ts
54
+ var AmigoError = class extends Error {
55
+ constructor(message, options) {
56
+ super(message);
57
+ /**
58
+ * Unique error code for programmatic error handling
59
+ */
60
+ __publicField(this, "errorCode");
61
+ /**
62
+ * HTTP status code if applicable
63
+ */
64
+ __publicField(this, "statusCode");
65
+ /**
66
+ * Additional context data
67
+ */
68
+ __publicField(this, "context");
69
+ this.name = this.constructor.name;
70
+ Object.setPrototypeOf(this, new.target.prototype);
71
+ if (Error.captureStackTrace) {
72
+ Error.captureStackTrace(this, this.constructor);
73
+ }
74
+ Object.assign(this, options);
75
+ }
76
+ /**
77
+ * Returns a JSON-serializable representation of the error
78
+ */
79
+ toJSON() {
80
+ return {
81
+ name: this.name,
82
+ message: this.message,
83
+ code: this.errorCode,
84
+ statusCode: this.statusCode,
85
+ context: this.context,
86
+ stack: this.stack
87
+ };
88
+ }
89
+ };
90
+ var BadRequestError = class extends AmigoError {
91
+ };
92
+ var AuthenticationError = class extends AmigoError {
93
+ };
94
+ var PermissionError = class extends AmigoError {
95
+ };
96
+ var NotFoundError = class extends AmigoError {
97
+ };
98
+ var ConflictError = class extends AmigoError {
99
+ };
100
+ var RateLimitError = class extends AmigoError {
101
+ };
102
+ var ServerError = class extends AmigoError {
103
+ };
104
+ var ServiceUnavailableError = class extends ServerError {
105
+ };
106
+ var ConfigurationError = class extends AmigoError {
107
+ constructor(message, field) {
108
+ super(message);
109
+ this.field = field;
110
+ this.context = { field };
111
+ }
112
+ };
113
+ var ValidationError = class extends BadRequestError {
114
+ constructor(msg, fieldErrors) {
115
+ super(msg);
116
+ this.fieldErrors = fieldErrors;
117
+ }
118
+ };
119
+ var NetworkError = class extends AmigoError {
120
+ constructor(message, originalError, request) {
121
+ super(message, { cause: originalError });
122
+ this.originalError = originalError;
123
+ this.request = request;
124
+ this.context = { request };
125
+ }
126
+ };
127
+ var ParseError = class extends AmigoError {
128
+ constructor(message, parseType, originalError) {
129
+ super(message, { cause: originalError });
130
+ this.parseType = parseType;
131
+ this.originalError = originalError;
132
+ this.context = { parseType };
133
+ }
134
+ };
135
+ function isAmigoError(error) {
136
+ return error instanceof AmigoError;
137
+ }
138
+ function createApiError(response, body) {
139
+ const map = {
140
+ 400: BadRequestError,
141
+ 401: AuthenticationError,
142
+ 403: PermissionError,
143
+ 404: NotFoundError,
144
+ 409: ConflictError,
145
+ 422: ValidationError,
146
+ 429: RateLimitError,
147
+ 500: ServerError,
148
+ 503: ServiceUnavailableError
149
+ };
150
+ const ErrorClass = map[response.status] ?? AmigoError;
151
+ const message = body && typeof body === "object" && "message" in body ? String(body.message) : response.statusText;
152
+ const options = {
153
+ status: response.status,
154
+ code: body && typeof body === "object" && "code" in body ? body.code : void 0,
155
+ response: body
156
+ };
157
+ const error = new ErrorClass(message, options);
158
+ return error;
159
+ }
160
+ function createErrorMiddleware() {
161
+ return {
162
+ onResponse: async ({ response }) => {
163
+ if (!response.ok) {
164
+ const body = await parseResponseBody(response);
165
+ throw createApiError(response, body);
166
+ }
167
+ },
168
+ onError: async ({ error, request }) => {
169
+ if (isNetworkError(error)) {
170
+ throw new NetworkError(
171
+ `Network error: ${error instanceof Error ? error.message : String(error)}`,
172
+ error instanceof Error ? error : new Error(String(error)),
173
+ {
174
+ url: request?.url,
175
+ method: request?.method
176
+ }
177
+ );
178
+ }
179
+ throw error;
180
+ }
181
+ };
182
+ }
183
+
184
+ // src/core/openapi-client.ts
185
+ import createClient from "openapi-fetch";
186
+
187
+ // src/core/auth.ts
188
+ async function getBearerToken(config) {
189
+ const url = `${config.baseUrl}/v1/${config.orgId}/user/signin_with_api_key`;
190
+ try {
191
+ const response = await fetch(url, {
192
+ method: "POST",
193
+ headers: {
194
+ "x-api-key": config.apiKey,
195
+ "x-api-key-id": config.apiKeyId,
196
+ "x-user-id": config.userId
197
+ }
198
+ });
199
+ if (!response.ok) {
200
+ const body = await parseResponseBody(response);
201
+ const apiError = createApiError(response, body);
202
+ if (response.status === 401) {
203
+ throw new AuthenticationError(`Authentication failed: ${apiError.message}`, {
204
+ ...apiError,
205
+ context: { ...apiError.context, endpoint: "signin_with_api_key" }
206
+ });
207
+ }
208
+ throw apiError;
209
+ }
210
+ return await response.json();
211
+ } catch (err) {
212
+ if (err instanceof AmigoError) {
213
+ throw err;
214
+ }
215
+ if (isNetworkError(err)) {
216
+ throw new NetworkError("Failed to connect to authentication endpoint", err, {
217
+ url,
218
+ method: "POST"
219
+ });
220
+ }
221
+ throw new ParseError(
222
+ "Failed to parse authentication response",
223
+ "json",
224
+ err instanceof Error ? err : new Error(String(err))
225
+ );
226
+ }
227
+ }
228
+ function createAuthMiddleware(config) {
229
+ let token = null;
230
+ let refreshPromise = null;
231
+ const shouldRefreshToken = (tokenData) => {
232
+ if (!tokenData.expires_at) return false;
233
+ const expiryTime = new Date(tokenData.expires_at).getTime();
234
+ const currentTime = Date.now();
235
+ const timeUntilExpiry = expiryTime - currentTime;
236
+ const refreshThreshold = 5 * 60 * 1e3;
237
+ return timeUntilExpiry <= refreshThreshold;
238
+ };
239
+ const ensureValidToken = async () => {
240
+ if (!token || shouldRefreshToken(token)) {
241
+ if (!refreshPromise) {
242
+ refreshPromise = getBearerToken(config);
243
+ try {
244
+ token = await refreshPromise;
245
+ } finally {
246
+ refreshPromise = null;
247
+ }
248
+ } else {
249
+ token = await refreshPromise;
250
+ }
251
+ }
252
+ return token;
253
+ };
254
+ return {
255
+ onRequest: async ({ request }) => {
256
+ try {
257
+ const validToken = await ensureValidToken();
258
+ if (validToken?.id_token) {
259
+ request.headers.set("Authorization", `Bearer ${validToken.id_token}`);
260
+ }
261
+ } catch (error) {
262
+ token = null;
263
+ throw error;
264
+ }
265
+ return request;
266
+ },
267
+ onResponse: async ({ response }) => {
268
+ if (response.status === 401) {
269
+ token = null;
270
+ }
271
+ },
272
+ onError: async ({ error }) => {
273
+ token = null;
274
+ throw error;
275
+ }
276
+ };
277
+ }
278
+
279
+ // src/core/openapi-client.ts
280
+ function createAmigoFetch(config, mockFetch) {
281
+ const client = createClient({
282
+ baseUrl: config.baseUrl,
283
+ ...mockFetch && { fetch: mockFetch }
284
+ });
285
+ client.use(createErrorMiddleware());
286
+ client.use(createAuthMiddleware(config));
287
+ return client;
288
+ }
289
+
290
+ // src/resources/organization.ts
291
+ var OrganizationResource = class {
292
+ constructor(c) {
293
+ this.c = c;
294
+ }
295
+ async getOrganization(orgId) {
296
+ return extractData(
297
+ this.c.GET("/v1/{organization}/organization/", {
298
+ params: { path: { organization: orgId } }
299
+ })
300
+ );
301
+ }
302
+ };
303
+
304
+ // src/resources/services.ts
305
+ var ServiceResource = class {
306
+ constructor(c) {
307
+ this.c = c;
308
+ }
309
+ async getServices(orgId) {
310
+ return extractData(
311
+ this.c.GET("/v1/{organization}/service/", {
312
+ params: { path: { organization: orgId } }
313
+ })
314
+ );
315
+ }
316
+ };
317
+
318
+ // src/index.ts
319
+ var defaultBaseUrl = "https://api.amigo.ai";
320
+ var AmigoClient = class {
321
+ constructor(config) {
322
+ __publicField(this, "organizations");
323
+ __publicField(this, "services");
324
+ __publicField(this, "config");
325
+ this.config = validateConfig(config);
326
+ const api = createAmigoFetch(this.config);
327
+ this.organizations = new OrganizationResource(api);
328
+ this.services = new ServiceResource(api);
329
+ }
330
+ };
331
+ function validateConfig(config) {
332
+ if (!config.apiKey) {
333
+ throw new ConfigurationError("API key is required", "apiKey");
334
+ }
335
+ if (!config.apiKeyId) {
336
+ throw new ConfigurationError("API key ID is required", "apiKeyId");
337
+ }
338
+ if (!config.userId) {
339
+ throw new ConfigurationError("User ID is required", "userId");
340
+ }
341
+ if (!config.orgId) {
342
+ throw new ConfigurationError("Organization ID is required", "orgId");
343
+ }
344
+ if (!config.baseUrl) {
345
+ config.baseUrl = defaultBaseUrl;
346
+ }
347
+ return config;
348
+ }
349
+ export {
350
+ AmigoClient,
351
+ errors_exports as errors
352
+ };
353
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../src/core/errors.ts", "../src/core/utils.ts", "../src/core/openapi-client.ts", "../src/core/auth.ts", "../src/resources/organization.ts", "../src/resources/services.ts", "../src/index.ts"],
4
+ "sourcesContent": ["import type { Middleware } from 'openapi-fetch'\nimport { isNetworkError, parseResponseBody } from './utils'\n\n/**\n * Base error class for all Amigo SDK errors.\n * Provides common functionality and error identification.\n */\nexport class AmigoError extends Error {\n /**\n * Unique error code for programmatic error handling\n */\n readonly errorCode?: string\n\n /**\n * HTTP status code if applicable\n */\n readonly statusCode?: number\n\n /**\n * Additional context data\n */\n context?: Record<string, unknown>\n\n constructor(message: string, options?: Record<string, unknown>) {\n super(message)\n this.name = this.constructor.name\n\n // Ensure proper prototype chain for instanceof checks\n Object.setPrototypeOf(this, new.target.prototype)\n\n // Capture stack trace\n if (Error.captureStackTrace) {\n Error.captureStackTrace(this, this.constructor)\n }\n\n // copies status, code, etc.\n Object.assign(this, options)\n }\n\n /**\n * Returns a JSON-serializable representation of the error\n */\n toJSON(): Record<string, unknown> {\n return {\n name: this.name,\n message: this.message,\n code: this.errorCode,\n statusCode: this.statusCode,\n context: this.context,\n stack: this.stack,\n }\n }\n}\n\n/* 4xx client errors */\nexport class BadRequestError extends AmigoError {}\nexport class AuthenticationError extends AmigoError {}\nexport class PermissionError extends AmigoError {}\nexport class NotFoundError extends AmigoError {}\nexport class ConflictError extends AmigoError {}\nexport class RateLimitError extends AmigoError {}\n\n/* 5xx server errors */\nexport class ServerError extends AmigoError {}\nexport class ServiceUnavailableError extends ServerError {}\n\n/* Internal SDK errors */\nexport class ConfigurationError extends AmigoError {\n constructor(\n message: string,\n public field?: string\n ) {\n super(message)\n this.context = { field }\n }\n}\n\n/* Validation errors */\nexport class ValidationError extends BadRequestError {\n constructor(\n msg: string,\n public fieldErrors?: Record<string, string>\n ) {\n super(msg)\n }\n}\n\n/* Network-related errors */\nexport class NetworkError extends AmigoError {\n constructor(\n message: string,\n public readonly originalError?: Error,\n public readonly request?: {\n url?: string\n method?: string\n }\n ) {\n super(message, { cause: originalError })\n this.context = { request }\n }\n}\n\n/* Parsing errors */\nexport class ParseError extends AmigoError {\n constructor(\n message: string,\n public readonly parseType: 'json' | 'response' | 'other',\n public readonly originalError?: Error\n ) {\n super(message, { cause: originalError })\n this.context = { parseType }\n }\n}\n\n/* Type guard functions */\nexport function isAmigoError(error: unknown): error is AmigoError {\n return error instanceof AmigoError\n}\n\n/* Error factory to create appropriate error instances from API responses */\nexport function createApiError(response: Response, body?: unknown): AmigoError {\n const map: Record<number, typeof AmigoError> = {\n 400: BadRequestError,\n 401: AuthenticationError,\n 403: PermissionError,\n 404: NotFoundError,\n 409: ConflictError,\n 422: ValidationError,\n 429: RateLimitError,\n 500: ServerError,\n 503: ServiceUnavailableError,\n }\n\n const ErrorClass = map[response.status] ?? AmigoError\n const message =\n body && typeof body === 'object' && 'message' in body\n ? String((body as Record<string, unknown>).message)\n : response.statusText\n\n const options = {\n status: response.status,\n code:\n body && typeof body === 'object' && 'code' in body\n ? (body as Record<string, unknown>).code\n : undefined,\n response: body,\n }\n\n const error = new ErrorClass(message, options)\n\n return error\n}\n\nexport function createErrorMiddleware(): Middleware {\n return {\n onResponse: async ({ response }) => {\n if (!response.ok) {\n const body = await parseResponseBody(response)\n throw createApiError(response, body)\n }\n },\n onError: async ({ error, request }) => {\n // Handle network-related errors consistently\n if (isNetworkError(error)) {\n throw new NetworkError(\n `Network error: ${error instanceof Error ? error.message : String(error)}`,\n error instanceof Error ? error : new Error(String(error)),\n {\n url: request?.url,\n method: request?.method,\n }\n )\n }\n throw error\n },\n }\n}\n", "// Note: ParseError import removed as it's unused in current implementation\n\n// Type helper to extract the data type from openapi-fetch responses\nexport type ExtractDataType<T> = T extends { data?: infer D } ? D : never\n\n// Helper function to extract data from openapi-fetch responses\n// Since our middleware throws on errors, successful responses will have data\nexport async function extractData<T>(responsePromise: Promise<T>): Promise<ExtractDataType<T>> {\n const result = await responsePromise\n // openapi-fetch guarantees data exists on successful responses\n return (result as { data: ExtractDataType<T> }).data\n}\n\n// Utility function to safely parse response bodies without throwing errors\nexport async function parseResponseBody(response: Response): Promise<unknown> {\n try {\n const text = await response.text()\n if (!text) return undefined\n try {\n return JSON.parse(text)\n } catch {\n return text // Return as string if not valid JSON\n }\n } catch {\n return undefined // Return undefined if any error occurs\n }\n}\n\n// Helper to detect network-related errors\nexport function isNetworkError(error: unknown): boolean {\n if (!(error instanceof Error)) return false\n\n return (\n error instanceof TypeError ||\n error.message.includes('fetch') ||\n error.message.includes('Failed to fetch') ||\n error.message.includes('Network request failed') ||\n error.message.includes('ECONNREFUSED') ||\n error.message.includes('ETIMEDOUT') ||\n error.message.includes('ENOTFOUND') ||\n error.message.includes('network')\n )\n}\n", "import createClient, { type Client } from 'openapi-fetch'\nimport { createErrorMiddleware } from './errors'\nimport { createAuthMiddleware } from './auth'\nimport type { paths } from '../generated/api-types'\nimport type { AmigoSdkConfig } from '..'\n\nexport type AmigoFetch = Client<paths>\n\nexport function createAmigoFetch(\n config: AmigoSdkConfig,\n mockFetch?: (input: Request) => Promise<Response>\n): AmigoFetch {\n const client = createClient<paths>({\n baseUrl: config.baseUrl,\n ...(mockFetch && { fetch: mockFetch }),\n })\n\n // Apply error handling middleware first (to catch all errors)\n client.use(createErrorMiddleware())\n\n // Apply auth middleware after error handling (so auth errors are properly handled)\n client.use(createAuthMiddleware(config))\n\n return client\n}\n", "import type { Middleware } from 'openapi-fetch'\nimport type { components } from '../generated/api-types'\nimport type { AmigoSdkConfig } from '..'\nimport { AmigoError, AuthenticationError, NetworkError, ParseError, createApiError } from './errors'\nimport { isNetworkError, parseResponseBody } from './utils'\n\ntype SignInWithApiKeyResponse =\n components['schemas']['src__app__endpoints__user__sign_in_with_api_key__Response']\n\n/** Helper function to trade API key for a bearer token */\nexport async function getBearerToken(config: AmigoSdkConfig): Promise<SignInWithApiKeyResponse> {\n const url = `${config.baseUrl}/v1/${config.orgId}/user/signin_with_api_key`\n\n try {\n const response = await fetch(url, {\n method: 'POST',\n headers: {\n 'x-api-key': config.apiKey,\n 'x-api-key-id': config.apiKeyId,\n 'x-user-id': config.userId,\n },\n })\n\n if (!response.ok) {\n const body = await parseResponseBody(response)\n const apiError = createApiError(response, body)\n\n // Enhance authentication errors with additional context\n if (response.status === 401) {\n throw new AuthenticationError(`Authentication failed: ${apiError.message}`, {\n ...apiError,\n context: { ...apiError.context, endpoint: 'signin_with_api_key' },\n })\n }\n throw apiError\n }\n\n return (await response.json()) as SignInWithApiKeyResponse\n } catch (err) {\n // Re-throw our custom errors as-is\n if (err instanceof AmigoError) {\n throw err\n }\n\n // Handle network errors\n if (isNetworkError(err)) {\n throw new NetworkError('Failed to connect to authentication endpoint', err as Error, {\n url,\n method: 'POST',\n })\n }\n\n // Handle JSON parsing errors\n throw new ParseError(\n 'Failed to parse authentication response',\n 'json',\n err instanceof Error ? err : new Error(String(err))\n )\n }\n}\n\nexport function createAuthMiddleware(config: AmigoSdkConfig): Middleware {\n let token: SignInWithApiKeyResponse | null = null\n let refreshPromise: Promise<SignInWithApiKeyResponse> | null = null\n\n const shouldRefreshToken = (tokenData: SignInWithApiKeyResponse): boolean => {\n if (!tokenData.expires_at) return false\n\n const expiryTime = new Date(tokenData.expires_at).getTime()\n const currentTime = Date.now()\n const timeUntilExpiry = expiryTime - currentTime\n const refreshThreshold = 5 * 60 * 1000 // 5 minutes in milliseconds\n\n return timeUntilExpiry <= refreshThreshold\n }\n\n const ensureValidToken = async (): Promise<SignInWithApiKeyResponse> => {\n if (!token || shouldRefreshToken(token)) {\n if (!refreshPromise) {\n refreshPromise = getBearerToken(config)\n try {\n token = await refreshPromise\n } finally {\n refreshPromise = null\n }\n } else {\n token = await refreshPromise\n }\n }\n return token\n }\n\n return {\n onRequest: async ({ request }) => {\n try {\n const validToken = await ensureValidToken()\n if (validToken?.id_token) {\n request.headers.set('Authorization', `Bearer ${validToken.id_token}`)\n }\n } catch (error) {\n // Clear token and re-throw - getBearerToken already provides proper error types\n token = null\n throw error\n }\n return request\n },\n\n onResponse: async ({ response }) => {\n // Handle 401 responses by clearing token to force refresh on next request\n if (response.status === 401) {\n token = null\n }\n },\n\n onError: async ({ error }) => {\n // Clear token on any error to force refresh\n token = null\n throw error\n },\n }\n}\n", "import type { AmigoFetch } from '../core/openapi-client'\nimport { extractData } from '../core/utils'\n\nexport class OrganizationResource {\n constructor(private c: AmigoFetch) {}\n\n async getOrganization(orgId: string) {\n return extractData(\n this.c.GET('/v1/{organization}/organization/', {\n params: { path: { organization: orgId } },\n })\n )\n }\n}\n", "import type { AmigoFetch } from '../core/openapi-client'\nimport { extractData } from '../core/utils'\n\nexport class ServiceResource {\n constructor(private c: AmigoFetch) {}\n\n async getServices(orgId: string) {\n return extractData(\n this.c.GET('/v1/{organization}/service/', {\n params: { path: { organization: orgId } },\n })\n )\n }\n}\n", "import { ConfigurationError } from './core/errors'\nimport { createAmigoFetch } from './core/openapi-client'\nimport { OrganizationResource } from './resources/organization'\nimport { ServiceResource } from './resources/services'\n\nexport interface AmigoSdkConfig {\n /** API key from Amigo dashboard */\n apiKey: string\n /** API-key ID from Amigo dashboard */\n apiKeyId: string\n /** User ID on whose behalf the request is made */\n userId: string\n /** The Organization ID */\n orgId: string\n /** Base URL of the Amigo API */\n baseUrl?: string\n}\n\nconst defaultBaseUrl = 'https://api.amigo.ai'\n\nexport class AmigoClient {\n readonly organizations: OrganizationResource\n readonly services: ServiceResource\n readonly config: AmigoSdkConfig\n\n constructor(config: AmigoSdkConfig) {\n this.config = validateConfig(config)\n\n const api = createAmigoFetch(this.config)\n this.organizations = new OrganizationResource(api)\n this.services = new ServiceResource(api)\n }\n}\n\nfunction validateConfig(config: AmigoSdkConfig) {\n if (!config.apiKey) {\n throw new ConfigurationError('API key is required', 'apiKey')\n }\n if (!config.apiKeyId) {\n throw new ConfigurationError('API key ID is required', 'apiKeyId')\n }\n if (!config.userId) {\n throw new ConfigurationError('User ID is required', 'userId')\n }\n if (!config.orgId) {\n throw new ConfigurationError('Organization ID is required', 'orgId')\n }\n if (!config.baseUrl) {\n config.baseUrl = defaultBaseUrl\n }\n return config\n}\n\n// Export all errors as a namespace to avoid polluting the main import space\nexport * as errors from './core/errors'\n"],
5
+ "mappings": "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",
6
+ "names": []
7
+ }
@@ -0,0 +1,8 @@
1
+ import type { Middleware } from 'openapi-fetch';
2
+ import type { components } from '../generated/api-types';
3
+ import type { AmigoSdkConfig } from '..';
4
+ type SignInWithApiKeyResponse = components['schemas']['src__app__endpoints__user__sign_in_with_api_key__Response'];
5
+ /** Helper function to trade API key for a bearer token */
6
+ export declare function getBearerToken(config: AmigoSdkConfig): Promise<SignInWithApiKeyResponse>;
7
+ export declare function createAuthMiddleware(config: AmigoSdkConfig): Middleware;
8
+ export {};
@@ -0,0 +1,67 @@
1
+ import type { Middleware } from 'openapi-fetch';
2
+ /**
3
+ * Base error class for all Amigo SDK errors.
4
+ * Provides common functionality and error identification.
5
+ */
6
+ export declare class AmigoError extends Error {
7
+ /**
8
+ * Unique error code for programmatic error handling
9
+ */
10
+ readonly errorCode?: string;
11
+ /**
12
+ * HTTP status code if applicable
13
+ */
14
+ readonly statusCode?: number;
15
+ /**
16
+ * Additional context data
17
+ */
18
+ context?: Record<string, unknown>;
19
+ constructor(message: string, options?: Record<string, unknown>);
20
+ /**
21
+ * Returns a JSON-serializable representation of the error
22
+ */
23
+ toJSON(): Record<string, unknown>;
24
+ }
25
+ export declare class BadRequestError extends AmigoError {
26
+ }
27
+ export declare class AuthenticationError extends AmigoError {
28
+ }
29
+ export declare class PermissionError extends AmigoError {
30
+ }
31
+ export declare class NotFoundError extends AmigoError {
32
+ }
33
+ export declare class ConflictError extends AmigoError {
34
+ }
35
+ export declare class RateLimitError extends AmigoError {
36
+ }
37
+ export declare class ServerError extends AmigoError {
38
+ }
39
+ export declare class ServiceUnavailableError extends ServerError {
40
+ }
41
+ export declare class ConfigurationError extends AmigoError {
42
+ field?: string | undefined;
43
+ constructor(message: string, field?: string | undefined);
44
+ }
45
+ export declare class ValidationError extends BadRequestError {
46
+ fieldErrors?: Record<string, string> | undefined;
47
+ constructor(msg: string, fieldErrors?: Record<string, string> | undefined);
48
+ }
49
+ export declare class NetworkError extends AmigoError {
50
+ readonly originalError?: Error | undefined;
51
+ readonly request?: {
52
+ url?: string;
53
+ method?: string;
54
+ } | undefined;
55
+ constructor(message: string, originalError?: Error | undefined, request?: {
56
+ url?: string;
57
+ method?: string;
58
+ } | undefined);
59
+ }
60
+ export declare class ParseError extends AmigoError {
61
+ readonly parseType: 'json' | 'response' | 'other';
62
+ readonly originalError?: Error | undefined;
63
+ constructor(message: string, parseType: 'json' | 'response' | 'other', originalError?: Error | undefined);
64
+ }
65
+ export declare function isAmigoError(error: unknown): error is AmigoError;
66
+ export declare function createApiError(response: Response, body?: unknown): AmigoError;
67
+ export declare function createErrorMiddleware(): Middleware;
@@ -0,0 +1,5 @@
1
+ import { type Client } from 'openapi-fetch';
2
+ import type { paths } from '../generated/api-types';
3
+ import type { AmigoSdkConfig } from '..';
4
+ export type AmigoFetch = Client<paths>;
5
+ export declare function createAmigoFetch(config: AmigoSdkConfig, mockFetch?: (input: Request) => Promise<Response>): AmigoFetch;
@@ -0,0 +1,6 @@
1
+ export type ExtractDataType<T> = T extends {
2
+ data?: infer D;
3
+ } ? D : never;
4
+ export declare function extractData<T>(responsePromise: Promise<T>): Promise<ExtractDataType<T>>;
5
+ export declare function parseResponseBody(response: Response): Promise<unknown>;
6
+ export declare function isNetworkError(error: unknown): boolean;