@hasna/connectors 1.4.2 → 1.4.4
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/bin/index.js +145 -98
- package/bin/mcp.js +1 -1
- package/bin/serve.js +144 -93
- package/connectors/clickbank/README.md +2 -2
- package/connectors/split-in-batches/CLAUDE.md +1 -1
- package/connectors/split-in-batches/README.md +1 -1
- package/connectors/split-in-batches/src/api/client.test.ts +16 -17
- package/connectors/split-in-batches/src/api/client.ts +4 -3
- package/connectors/split-in-batches/src/cli/index.ts +1 -1
- package/connectors/spreadsheet-file/.env.example +1 -1
- package/connectors/spreadsheet-file/CLAUDE.md +2 -2
- package/connectors/spreadsheet-file/README.md +3 -3
- package/connectors/spreadsheet-file/src/api/client.test.ts +8 -9
- package/connectors/spreadsheet-file/src/api/client.ts +4 -3
- package/connectors/spreadsheet-file/src/cli/index.ts +1 -1
- package/connectors/sse-trigger/.env.example +1 -1
- package/connectors/sse-trigger/CLAUDE.md +2 -2
- package/connectors/sse-trigger/README.md +1 -1
- package/connectors/sse-trigger/src/api/client.test.ts +12 -8
- package/connectors/sse-trigger/src/api/client.ts +4 -3
- package/connectors/sse-trigger/src/api/index.ts +1 -1
- package/connectors/sse-trigger/src/cli/index.ts +1 -1
- package/connectors/sse-trigger/src/index.ts +1 -1
- package/connectors/stability-api-platform/AGENTS.md +1 -1
- package/connectors/stability-api-platform/CLAUDE.md +1 -1
- package/connectors/stability-api-platform/README.md +2 -2
- package/connectors/stability-api-platform/src/api/client.test.ts +17 -12
- package/connectors/stability-api-platform/src/api/client.ts +4 -3
- package/connectors/stability-api-platform/src/api/index.ts +0 -1
- package/connectors/stability-api-platform/src/cli/index.ts +1 -1
- package/connectors/stability-api-platform/src/index.ts +0 -1
- package/connectors/stop-and-error/.env.example +1 -1
- package/connectors/stop-and-error/CLAUDE.md +1 -1
- package/connectors/stop-and-error/README.md +1 -1
- package/connectors/stop-and-error/src/api/client.test.ts +12 -8
- package/connectors/stop-and-error/src/api/client.ts +4 -3
- package/connectors/stop-and-error/src/cli/index.ts +2 -2
- package/connectors/stripe-financial-connections/.env.example +1 -1
- package/connectors/stripe-financial-connections/CLAUDE.md +2 -2
- package/connectors/stripe-financial-connections/src/api/client.test.ts +34 -0
- package/connectors/stripe-financial-connections/src/api/client.ts +4 -3
- package/connectors/stripe-financial-connections/src/cli/index.ts +1 -1
- package/connectors/sucuri-api-platform/.env.example +1 -1
- package/connectors/sucuri-api-platform/CLAUDE.md +1 -1
- package/connectors/sucuri-api-platform/README.md +2 -2
- package/connectors/sucuri-api-platform/src/api/client.test.ts +9 -7
- package/connectors/sucuri-api-platform/src/api/client.ts +4 -3
- package/connectors/sucuri-api-platform/src/api/index.ts +1 -1
- package/connectors/sucuri-api-platform/src/cli/index.ts +1 -1
- package/connectors/sucuri-api-platform/src/index.ts +1 -1
- package/connectors/tettra-api-platform/CLAUDE.md +1 -1
- package/connectors/tettra-api-platform/README.md +2 -2
- package/connectors/tettra-api-platform/src/api/client.test.ts +7 -8
- package/connectors/tettra-api-platform/src/api/client.ts +4 -3
- package/connectors/tettra-api-platform/src/api/index.ts +1 -1
- package/connectors/tettra-api-platform/src/cli/index.ts +1 -1
- package/connectors/tettra-api-platform/src/index.ts +1 -1
- package/connectors/together-api-platform/.env.example +1 -1
- package/connectors/together-api-platform/CLAUDE.md +1 -1
- package/connectors/together-api-platform/README.md +1 -1
- package/connectors/together-api-platform/src/api/client.test.ts +11 -7
- package/connectors/together-api-platform/src/api/client.ts +4 -4
- package/connectors/together-api-platform/src/api/index.ts +1 -1
- package/connectors/together-api-platform/src/cli/index.ts +1 -1
- package/connectors/together-api-platform/src/index.ts +1 -1
- package/connectors/travo-real-estate/CLAUDE.md +1 -1
- package/connectors/travo-real-estate/README.md +1 -1
- package/connectors/travo-real-estate/src/api/client.test.ts +20 -16
- package/connectors/travo-real-estate/src/api/client.ts +4 -3
- package/connectors/travo-real-estate/src/utils/config.ts +2 -4
- package/connectors/tray-api-platform/CLAUDE.md +1 -1
- package/connectors/tray-api-platform/src/api/client.test.ts +17 -13
- package/connectors/tray-api-platform/src/api/client.ts +4 -3
- package/connectors/tray-api-platform/src/api/index.ts +1 -1
- package/connectors/tray-api-platform/src/cli/index.ts +1 -1
- package/connectors/tray-api-platform/src/index.ts +0 -1
- package/connectors/turso-api-platform/CLAUDE.md +1 -1
- package/connectors/turso-api-platform/README.md +2 -2
- package/connectors/turso-api-platform/src/api/client.test.ts +17 -13
- package/connectors/turso-api-platform/src/api/client.ts +4 -3
- package/connectors/turso-api-platform/src/cli/index.ts +2 -2
- package/connectors/twilio-api-platform/CLAUDE.md +1 -1
- package/connectors/twilio-api-platform/src/api/client.test.ts +11 -11
- package/connectors/twilio-api-platform/src/api/client.ts +4 -3
- package/connectors/twilio-api-platform/src/api/index.ts +1 -1
- package/connectors/twilio-api-platform/src/cli/index.ts +1 -1
- package/connectors/twilio-api-platform/src/index.ts +1 -1
- package/connectors/tyk-api-platform/.env.example +1 -1
- package/connectors/tyk-api-platform/CLAUDE.md +2 -2
- package/connectors/tyk-api-platform/README.md +1 -1
- package/connectors/tyk-api-platform/src/api/client.test.ts +14 -15
- package/connectors/tyk-api-platform/src/api/client.ts +4 -3
- package/connectors/tyk-api-platform/src/api/index.ts +1 -1
- package/connectors/tyk-api-platform/src/cli/index.ts +1 -1
- package/connectors/tyk-api-platform/src/index.ts +1 -1
- package/connectors/vector-legal/.env.example +1 -1
- package/connectors/vector-legal/AGENTS.md +1 -1
- package/connectors/vector-legal/CLAUDE.md +1 -1
- package/connectors/vector-legal/README.md +1 -1
- package/connectors/vector-legal/src/api/client.test.ts +9 -5
- package/connectors/vector-legal/src/api/client.ts +4 -3
- package/connectors/vector-legal/src/api/index.ts +1 -1
- package/connectors/vector-legal/src/cli/index.ts +2 -2
- package/connectors/vector-legal/src/index.ts +0 -1
- package/connectors/vector-legal-api/CLAUDE.md +1 -1
- package/connectors/vector-legal-api/README.md +2 -2
- package/connectors/vector-legal-api/src/api/client.test.ts +12 -7
- package/connectors/vector-legal-api/src/api/client.ts +4 -3
- package/connectors/vector-legal-api/src/api/index.ts +1 -1
- package/connectors/vector-legal-api/src/cli/index.ts +1 -1
- package/connectors/vector-legal-api/src/index.ts +1 -2
- package/connectors/velum-data-quality/.env.example +1 -1
- package/connectors/velum-data-quality/CLAUDE.md +1 -1
- package/connectors/velum-data-quality/src/api/client.test.ts +15 -16
- package/connectors/velum-data-quality/src/api/client.ts +4 -3
- package/connectors/velum-data-quality/src/api/index.ts +1 -1
- package/connectors/velum-data-quality/src/cli/index.ts +1 -1
- package/connectors/velum-data-quality/src/index.ts +0 -1
- package/connectors/vercel-api-platform/.env.example +1 -1
- package/connectors/vercel-api-platform/CLAUDE.md +2 -2
- package/connectors/vercel-api-platform/README.md +2 -2
- package/connectors/vercel-api-platform/src/api/client.test.ts +27 -6
- package/connectors/vercel-api-platform/src/api/client.ts +4 -3
- package/connectors/vercel-api-platform/src/api/index.ts +1 -1
- package/connectors/vercel-api-platform/src/cli/index.ts +2 -2
- package/connectors/vercel-api-platform/src/index.ts +0 -1
- package/connectors/veriphone/README.md +2 -2
- package/connectors/wave-accounting/CLAUDE.md +1 -1
- package/connectors/wave-accounting/src/utils/auth.ts +1 -1
- package/connectors/weaviate-api-platform/CLAUDE.md +1 -1
- package/connectors/weaviate-api-platform/src/api/client.test.ts +32 -7
- package/connectors/weaviate-api-platform/src/api/client.ts +4 -3
- package/connectors/weaviate-api-platform/src/api/index.ts +1 -1
- package/connectors/weaviate-api-platform/src/cli/index.ts +1 -1
- package/connectors/weaviate-api-platform/src/index.ts +1 -1
- package/connectors/workflow-trigger/.env.example +1 -1
- package/connectors/workflow-trigger/CLAUDE.md +1 -1
- package/connectors/workflow-trigger/README.md +1 -1
- package/connectors/workflow-trigger/src/api/client.test.ts +10 -6
- package/connectors/workflow-trigger/src/api/client.ts +4 -3
- package/connectors/workflow-trigger/src/cli/index.ts +1 -1
- package/connectors/write-binary-file/CLAUDE.md +1 -1
- package/connectors/write-binary-file/README.md +1 -1
- package/connectors/write-binary-file/src/api/client.test.ts +16 -12
- package/connectors/write-binary-file/src/api/client.ts +4 -3
- package/connectors/write-binary-file/src/api/index.ts +1 -1
- package/connectors/write-binary-file/src/index.ts +1 -1
- package/connectors/wubookratechecker/src/api/client.test.ts +34 -0
- package/connectors/wubookratechecker/src/api/client.ts +3 -1
- package/connectors/wubookratechecker/src/api/index.ts +1 -1
- package/connectors/wubookratechecker/src/types/index.ts +1 -1
- package/connectors/xai-api-platform/.env.example +1 -1
- package/connectors/xai-api-platform/CLAUDE.md +1 -1
- package/connectors/xai-api-platform/README.md +1 -1
- package/connectors/xai-api-platform/src/api/client.test.ts +33 -8
- package/connectors/xai-api-platform/src/api/client.ts +4 -3
- package/connectors/xai-api-platform/src/api/index.ts +1 -1
- package/connectors/xai-api-platform/src/index.ts +1 -1
- package/connectors/xai-api-platform/src/utils/config.ts +2 -3
- package/connectors/zapier-api-platform/CLAUDE.md +1 -1
- package/connectors/zapier-api-platform/README.md +1 -1
- package/connectors/zapier-api-platform/src/api/client.test.ts +19 -14
- package/connectors/zapier-api-platform/src/api/client.ts +4 -3
- package/connectors/zapier-api-platform/src/api/index.ts +1 -1
- package/connectors/zapier-api-platform/src/cli/index.ts +1 -1
- package/connectors/zapier-api-platform/src/index.ts +1 -1
- package/dist/index.js +1 -1
- package/package.json +1 -1
|
@@ -15,11 +15,11 @@ describe('ConnectorClient', () => {
|
|
|
15
15
|
});
|
|
16
16
|
|
|
17
17
|
test('requires apiKey', () => {
|
|
18
|
-
expect(() => new ConnectorClient({ apiKey: '' })).toThrow('API key is required');
|
|
18
|
+
expect(() => new ConnectorClient({ apiKey: '', baseUrl: 'https://configured.example.com/v1' })).toThrow('API key is required');
|
|
19
19
|
});
|
|
20
20
|
|
|
21
21
|
test('creates client with valid config', () => {
|
|
22
|
-
const client = new ConnectorClient({ apiKey: 'travo-real-estate-key' });
|
|
22
|
+
const client = new ConnectorClient({ apiKey: 'travo-real-estate-key', baseUrl: 'https://configured.example.com/v1' });
|
|
23
23
|
expect(client.getApiKeyPreview()).toBe('travo-...-key');
|
|
24
24
|
});
|
|
25
25
|
|
|
@@ -33,12 +33,12 @@ describe('ConnectorClient', () => {
|
|
|
33
33
|
});
|
|
34
34
|
|
|
35
35
|
test('builds default listings URL', () => {
|
|
36
|
-
const client = new ConnectorClient({ apiKey: 'key' });
|
|
37
|
-
expect(client.buildRequestUrl('/listings')).toBe('https://
|
|
36
|
+
const client = new ConnectorClient({ apiKey: 'key', baseUrl: 'https://configured.example.com/v1' });
|
|
37
|
+
expect(client.buildRequestUrl('/listings')).toBe('https://configured.example.com/v1/listings');
|
|
38
38
|
});
|
|
39
39
|
|
|
40
40
|
test('sends Bearer authorization header', async () => {
|
|
41
|
-
const client = new ConnectorClient({ apiKey: 'travo-real-estate-key' });
|
|
41
|
+
const client = new ConnectorClient({ apiKey: 'travo-real-estate-key', baseUrl: 'https://configured.example.com/v1' });
|
|
42
42
|
const captured: Array<{ url: string; init?: RequestInit }> = [];
|
|
43
43
|
|
|
44
44
|
globalThis.fetch = mock(async (input: string | URL | Request, init?: RequestInit) => {
|
|
@@ -50,12 +50,12 @@ describe('ConnectorClient', () => {
|
|
|
50
50
|
}) as any;
|
|
51
51
|
|
|
52
52
|
await client.get('/listings');
|
|
53
|
-
expect(captured[0]?.url).toBe('https://
|
|
53
|
+
expect(captured[0]?.url).toBe('https://configured.example.com/v1/listings');
|
|
54
54
|
expect(new Headers(captured[0]?.init?.headers).get('Authorization')).toBe('Bearer travo-real-estate-key');
|
|
55
55
|
});
|
|
56
56
|
|
|
57
57
|
test('GET listing by ID uses encoded path', async () => {
|
|
58
|
-
const client = new ConnectorClient({ apiKey: 'travo-real-estate-key' });
|
|
58
|
+
const client = new ConnectorClient({ apiKey: 'travo-real-estate-key', baseUrl: 'https://configured.example.com/v1' });
|
|
59
59
|
const captured: string[] = [];
|
|
60
60
|
|
|
61
61
|
globalThis.fetch = mock(async (input: string | URL | Request) => {
|
|
@@ -64,11 +64,11 @@ describe('ConnectorClient', () => {
|
|
|
64
64
|
}) as any;
|
|
65
65
|
|
|
66
66
|
await client.get('/listings/item-1');
|
|
67
|
-
expect(captured[0]).toBe('https://
|
|
67
|
+
expect(captured[0]).toBe('https://configured.example.com/v1/listings/item-1');
|
|
68
68
|
});
|
|
69
69
|
|
|
70
70
|
test('GET events endpoint', async () => {
|
|
71
|
-
const client = new ConnectorClient({ apiKey: 'travo-real-estate-key' });
|
|
71
|
+
const client = new ConnectorClient({ apiKey: 'travo-real-estate-key', baseUrl: 'https://configured.example.com/v1' });
|
|
72
72
|
const captured: string[] = [];
|
|
73
73
|
|
|
74
74
|
globalThis.fetch = mock(async (input: string | URL | Request) => {
|
|
@@ -77,11 +77,11 @@ describe('ConnectorClient', () => {
|
|
|
77
77
|
}) as any;
|
|
78
78
|
|
|
79
79
|
await client.get('/events', { limit: 10 });
|
|
80
|
-
expect(captured[0]).toBe('https://
|
|
80
|
+
expect(captured[0]).toBe('https://configured.example.com/v1/events?limit=10');
|
|
81
81
|
});
|
|
82
82
|
|
|
83
83
|
test('POST search endpoint', async () => {
|
|
84
|
-
const client = new ConnectorClient({ apiKey: 'travo-real-estate-key' });
|
|
84
|
+
const client = new ConnectorClient({ apiKey: 'travo-real-estate-key', baseUrl: 'https://configured.example.com/v1' });
|
|
85
85
|
const captured: Array<{ url: string; init?: RequestInit }> = [];
|
|
86
86
|
|
|
87
87
|
globalThis.fetch = mock(async (input: string | URL | Request, init?: RequestInit) => {
|
|
@@ -93,13 +93,13 @@ describe('ConnectorClient', () => {
|
|
|
93
93
|
}) as any;
|
|
94
94
|
|
|
95
95
|
await client.post('/search', { query: 'apartment' });
|
|
96
|
-
expect(captured[0]?.url).toBe('https://
|
|
96
|
+
expect(captured[0]?.url).toBe('https://configured.example.com/v1/search');
|
|
97
97
|
expect(captured[0]?.init?.method).toBe('POST');
|
|
98
98
|
expect(captured[0]?.init?.body).toBe(JSON.stringify({ query: 'apartment' }));
|
|
99
99
|
});
|
|
100
100
|
|
|
101
101
|
test('throws ConnectorApiError on HTTP error', async () => {
|
|
102
|
-
const client = new ConnectorClient({ apiKey: 'travo-real-estate-key' });
|
|
102
|
+
const client = new ConnectorClient({ apiKey: 'travo-real-estate-key', baseUrl: 'https://configured.example.com/v1' });
|
|
103
103
|
|
|
104
104
|
globalThis.fetch = mock(async () =>
|
|
105
105
|
new Response('Unauthorized', { status: 401, statusText: 'Unauthorized' })
|
|
@@ -128,7 +128,7 @@ describe('TravoRealEstate', () => {
|
|
|
128
128
|
});
|
|
129
129
|
|
|
130
130
|
test('listListings and getListing hit expected paths', async () => {
|
|
131
|
-
const connector = new TravoRealEstate({ apiKey: 'travo-real-estate-key' });
|
|
131
|
+
const connector = new TravoRealEstate({ apiKey: 'travo-real-estate-key', baseUrl: 'https://configured.example.com/v1' });
|
|
132
132
|
const captured: string[] = [];
|
|
133
133
|
|
|
134
134
|
globalThis.fetch = mock(async (input: string | URL | Request) => {
|
|
@@ -139,8 +139,8 @@ describe('TravoRealEstate', () => {
|
|
|
139
139
|
await connector.listListings();
|
|
140
140
|
await connector.getListing('item-1');
|
|
141
141
|
|
|
142
|
-
expect(captured[0]).toBe('https://
|
|
143
|
-
expect(captured[1]).toBe('https://
|
|
142
|
+
expect(captured[0]).toBe('https://configured.example.com/v1/listings');
|
|
143
|
+
expect(captured[1]).toBe('https://configured.example.com/v1/listings/item-1');
|
|
144
144
|
});
|
|
145
145
|
});
|
|
146
146
|
|
|
@@ -151,4 +151,8 @@ describe('ConnectorApiError', () => {
|
|
|
151
151
|
expect(err.responseBody).toBe('{"error":"invalid_key"}');
|
|
152
152
|
expect(err.name).toBe('ConnectorApiError');
|
|
153
153
|
});
|
|
154
|
+
|
|
155
|
+
test('refuses to send without a configured base URL (no default endpoint)', () => {
|
|
156
|
+
expect(() => new ConnectorClient({ apiKey: 'test-key' })).toThrow(/baseUrl/);
|
|
157
|
+
});
|
|
154
158
|
});
|
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
import type { ConnectorConfig, QueryParams, RawRequestOptions } from '../types';
|
|
2
2
|
import { ConnectorApiError, parseApiError } from '../types';
|
|
3
3
|
|
|
4
|
-
export const DEFAULT_BASE_URL = 'https://api.travo-real-estate.com/v1';
|
|
5
|
-
|
|
6
4
|
export interface RequestOptions {
|
|
7
5
|
method?: 'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH';
|
|
8
6
|
params?: QueryParams;
|
|
@@ -21,7 +19,10 @@ export class ConnectorClient {
|
|
|
21
19
|
throw new Error('API key is required');
|
|
22
20
|
}
|
|
23
21
|
this.apiKey = config.apiKey;
|
|
24
|
-
|
|
22
|
+
if (!config.baseUrl) {
|
|
23
|
+
throw new Error('baseUrl is required: no default endpoint is configured; set baseUrl (profile, config, or the connector BASE_URL environment variable)');
|
|
24
|
+
}
|
|
25
|
+
this.baseUrl = config.baseUrl.replace(/\/$/, '');
|
|
25
26
|
}
|
|
26
27
|
|
|
27
28
|
private buildUrl(path: string, params?: QueryParams): string {
|
|
@@ -4,7 +4,6 @@ import { join } from 'path';
|
|
|
4
4
|
|
|
5
5
|
const CONNECTOR_NAME = 'connect-travo-real-estate';
|
|
6
6
|
const DEFAULT_PROFILE = 'default';
|
|
7
|
-
const DEFAULT_BASE_URL = 'https://api.travo-real-estate.com/v1';
|
|
8
7
|
|
|
9
8
|
export interface ProfileConfig {
|
|
10
9
|
apiKey?: string;
|
|
@@ -146,8 +145,8 @@ export function setApiKey(apiKey: string): void {
|
|
|
146
145
|
saveProfile(config);
|
|
147
146
|
}
|
|
148
147
|
|
|
149
|
-
export function getBaseUrl(): string {
|
|
150
|
-
return process.env.TRAVO_REAL_ESTATE_BASE_URL || loadProfile().baseUrl
|
|
148
|
+
export function getBaseUrl(): string | undefined {
|
|
149
|
+
return process.env.TRAVO_REAL_ESTATE_BASE_URL || loadProfile().baseUrl;
|
|
151
150
|
}
|
|
152
151
|
|
|
153
152
|
export function setBaseUrl(baseUrl: string): void {
|
|
@@ -168,4 +167,3 @@ export function getActiveProfileName(): string {
|
|
|
168
167
|
return getCurrentProfile();
|
|
169
168
|
}
|
|
170
169
|
|
|
171
|
-
export { DEFAULT_BASE_URL };
|
|
@@ -4,7 +4,7 @@ Tray API Platform connector — customer runtime REST API for items, events, and
|
|
|
4
4
|
|
|
5
5
|
## API Details
|
|
6
6
|
|
|
7
|
-
- **Base URL**:
|
|
7
|
+
- **Base URL**: no default (must be configured) (tenant-specific override supported)
|
|
8
8
|
- **Auth**: API key via Bearer token (`Authorization: Bearer <api_key>`)
|
|
9
9
|
- **Not** the tray.io iPaaS or Tray Platform workspace management API
|
|
10
10
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { afterEach, describe, expect, test } from 'bun:test';
|
|
2
|
+
import { ConnectorClient } from './client';
|
|
2
3
|
import { Connector } from './index';
|
|
3
|
-
import { DEFAULT_BASE_URL } from './client';
|
|
4
4
|
|
|
5
5
|
const realFetch = globalThis.fetch;
|
|
6
6
|
|
|
@@ -62,12 +62,12 @@ describe('Tray API Platform client', () => {
|
|
|
62
62
|
test('listItems sends Bearer auth and GET /items', async () => {
|
|
63
63
|
const recorded = installFetch((entry) => {
|
|
64
64
|
expect(entry.method).toBe('GET');
|
|
65
|
-
expect(entry.url).toBe(
|
|
65
|
+
expect(entry.url).toBe(`https://configured.example.com/v1/items`);
|
|
66
66
|
expect(entry.headers.authorization).toBe('Bearer test-api-key');
|
|
67
67
|
return { items: [] };
|
|
68
68
|
});
|
|
69
69
|
|
|
70
|
-
const connector = new Connector({ apiKey: 'test-api-key' });
|
|
70
|
+
const connector = new Connector({ apiKey: 'test-api-key', baseUrl: 'https://configured.example.com/v1' });
|
|
71
71
|
const result = await connector.items.list();
|
|
72
72
|
expect(result).toEqual({ items: [] });
|
|
73
73
|
expect(recorded).toHaveLength(1);
|
|
@@ -76,12 +76,12 @@ describe('Tray API Platform client', () => {
|
|
|
76
76
|
test('getItem encodes item ID and calls GET /items/:id', async () => {
|
|
77
77
|
const recorded = installFetch((entry) => {
|
|
78
78
|
expect(entry.method).toBe('GET');
|
|
79
|
-
expect(entry.url).toBe(
|
|
79
|
+
expect(entry.url).toBe(`https://configured.example.com/v1/items/item%2F123`);
|
|
80
80
|
expect(entry.headers.authorization).toBe('Bearer test-api-key');
|
|
81
81
|
return { id: 'item/123' };
|
|
82
82
|
});
|
|
83
83
|
|
|
84
|
-
const connector = new Connector({ apiKey: 'test-api-key' });
|
|
84
|
+
const connector = new Connector({ apiKey: 'test-api-key', baseUrl: 'https://configured.example.com/v1' });
|
|
85
85
|
const result = await connector.items.get('item/123');
|
|
86
86
|
expect(result).toEqual({ id: 'item/123' });
|
|
87
87
|
expect(recorded).toHaveLength(1);
|
|
@@ -90,12 +90,12 @@ describe('Tray API Platform client', () => {
|
|
|
90
90
|
test('createItem POSTs JSON body to /items', async () => {
|
|
91
91
|
const recorded = installFetch((entry) => {
|
|
92
92
|
expect(entry.method).toBe('POST');
|
|
93
|
-
expect(entry.url).toBe(
|
|
93
|
+
expect(entry.url).toBe(`https://configured.example.com/v1/items`);
|
|
94
94
|
expect(entry.body).toBe(JSON.stringify({ name: 'widget' }));
|
|
95
95
|
return { id: 'new-item' };
|
|
96
96
|
});
|
|
97
97
|
|
|
98
|
-
const connector = new Connector({ apiKey: 'test-api-key' });
|
|
98
|
+
const connector = new Connector({ apiKey: 'test-api-key', baseUrl: 'https://configured.example.com/v1' });
|
|
99
99
|
await connector.items.create({ name: 'widget' });
|
|
100
100
|
expect(recorded).toHaveLength(1);
|
|
101
101
|
});
|
|
@@ -117,12 +117,12 @@ describe('Tray API Platform client', () => {
|
|
|
117
117
|
test('listEvents sends GET /events', async () => {
|
|
118
118
|
const recorded = installFetch((entry) => {
|
|
119
119
|
expect(entry.method).toBe('GET');
|
|
120
|
-
expect(entry.url).toBe(
|
|
120
|
+
expect(entry.url).toBe(`https://configured.example.com/v1/events`);
|
|
121
121
|
expect(entry.headers.authorization).toBe('Bearer test-api-key');
|
|
122
122
|
return { events: [] };
|
|
123
123
|
});
|
|
124
124
|
|
|
125
|
-
const connector = new Connector({ apiKey: 'test-api-key' });
|
|
125
|
+
const connector = new Connector({ apiKey: 'test-api-key', baseUrl: 'https://configured.example.com/v1' });
|
|
126
126
|
const result = await connector.events.list();
|
|
127
127
|
expect(result).toEqual({ events: [] });
|
|
128
128
|
expect(recorded).toHaveLength(1);
|
|
@@ -131,12 +131,12 @@ describe('Tray API Platform client', () => {
|
|
|
131
131
|
test('search POSTs JSON body to /search', async () => {
|
|
132
132
|
const recorded = installFetch((entry) => {
|
|
133
133
|
expect(entry.method).toBe('POST');
|
|
134
|
-
expect(entry.url).toBe(
|
|
134
|
+
expect(entry.url).toBe(`https://configured.example.com/v1/search`);
|
|
135
135
|
expect(entry.body).toBe(JSON.stringify({ query: 'widget' }));
|
|
136
136
|
return { results: [] };
|
|
137
137
|
});
|
|
138
138
|
|
|
139
|
-
const connector = new Connector({ apiKey: 'test-api-key' });
|
|
139
|
+
const connector = new Connector({ apiKey: 'test-api-key', baseUrl: 'https://configured.example.com/v1' });
|
|
140
140
|
const result = await connector.search.search({ query: 'widget' });
|
|
141
141
|
expect(result).toEqual({ results: [] });
|
|
142
142
|
expect(recorded).toHaveLength(1);
|
|
@@ -145,12 +145,12 @@ describe('Tray API Platform client', () => {
|
|
|
145
145
|
test('rawRequest supports custom path and method', async () => {
|
|
146
146
|
const recorded = installFetch((entry) => {
|
|
147
147
|
expect(entry.method).toBe('POST');
|
|
148
|
-
expect(entry.url).toBe(
|
|
148
|
+
expect(entry.url).toBe(`https://configured.example.com/v1/custom/path`);
|
|
149
149
|
expect(entry.body).toBe(JSON.stringify({ action: 'ping' }));
|
|
150
150
|
return { ok: true };
|
|
151
151
|
});
|
|
152
152
|
|
|
153
|
-
const connector = new Connector({ apiKey: 'test-api-key' });
|
|
153
|
+
const connector = new Connector({ apiKey: 'test-api-key', baseUrl: 'https://configured.example.com/v1' });
|
|
154
154
|
const result = await connector.rawRequest({
|
|
155
155
|
method: 'POST',
|
|
156
156
|
path: '/custom/path',
|
|
@@ -163,4 +163,8 @@ describe('Tray API Platform client', () => {
|
|
|
163
163
|
test('requires API key', () => {
|
|
164
164
|
expect(() => new Connector({})).toThrow('API key or token is required');
|
|
165
165
|
});
|
|
166
|
+
|
|
167
|
+
test('refuses to send without a configured base URL (no default endpoint)', () => {
|
|
168
|
+
expect(() => new ConnectorClient({ apiKey: 'test-key' })).toThrow(/baseUrl/);
|
|
169
|
+
});
|
|
166
170
|
});
|
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
import type { ConnectorConfig, ListQueryParams } from '../types';
|
|
2
2
|
import { ConnectorApiError, parseApiError } from '../types';
|
|
3
3
|
|
|
4
|
-
export const DEFAULT_BASE_URL = 'https://api.trayapiplatform.com/v1';
|
|
5
|
-
|
|
6
4
|
export interface RequestOptions {
|
|
7
5
|
method?: 'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH';
|
|
8
6
|
params?: ListQueryParams;
|
|
@@ -22,7 +20,10 @@ export class ConnectorClient {
|
|
|
22
20
|
throw new Error('API key or token is required');
|
|
23
21
|
}
|
|
24
22
|
this.apiKey = key;
|
|
25
|
-
|
|
23
|
+
if (!config.baseUrl) {
|
|
24
|
+
throw new Error('baseUrl is required: no default endpoint is configured; set baseUrl (profile, config, or the connector BASE_URL environment variable)');
|
|
25
|
+
}
|
|
26
|
+
this.baseUrl = config.baseUrl.replace(/\/+$/, '');
|
|
26
27
|
}
|
|
27
28
|
|
|
28
29
|
getBaseUrl(): string {
|
|
@@ -43,7 +43,7 @@ export class Connector {
|
|
|
43
43
|
}
|
|
44
44
|
}
|
|
45
45
|
|
|
46
|
-
export { ConnectorClient
|
|
46
|
+
export { ConnectorClient } from './client';
|
|
47
47
|
export { ItemsApi } from './items';
|
|
48
48
|
export { EventsApi } from './events';
|
|
49
49
|
export { SearchApi } from './search';
|
|
@@ -219,7 +219,7 @@ configCmd
|
|
|
219
219
|
console.log(chalk.bold(`Active Profile: ${profileName}`));
|
|
220
220
|
info(`Config directory: ${getConfigDir()}`);
|
|
221
221
|
info(`API Key: ${apiKey ? `${apiKey.substring(0, 8)}...` : chalk.gray('not set')}`);
|
|
222
|
-
info(`Base URL: ${baseUrl || chalk.gray('
|
|
222
|
+
info(`Base URL: ${baseUrl || chalk.gray('none configured')}`);
|
|
223
223
|
});
|
|
224
224
|
|
|
225
225
|
configCmd
|
|
@@ -20,7 +20,7 @@ bun test
|
|
|
20
20
|
|
|
21
21
|
Bearer token via `Authorization: Bearer <api_key>` header.
|
|
22
22
|
|
|
23
|
-
Default base URL:
|
|
23
|
+
Default base URL: none (must be configured)
|
|
24
24
|
|
|
25
25
|
Credentials stored in `~/.hasna/connectors/connect-turso-api-platform/profiles/`.
|
|
26
26
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Turso Api Platform Connector
|
|
2
2
|
|
|
3
|
-
TypeScript connector and CLI for the [Turso Api Platform](
|
|
3
|
+
TypeScript connector and CLI for the [Turso Api Platform](configured.example.com/v1) REST API.
|
|
4
4
|
|
|
5
5
|
## Features
|
|
6
6
|
|
|
@@ -19,7 +19,7 @@ bun install
|
|
|
19
19
|
|
|
20
20
|
```bash
|
|
21
21
|
connect-turso-api-platform auth set-key <api-key>
|
|
22
|
-
connect-turso-api-platform auth set-base-url
|
|
22
|
+
connect-turso-api-platform auth set-base-url configured.example.com/v1
|
|
23
23
|
connect-turso-api-platform auth status
|
|
24
24
|
```
|
|
25
25
|
|
|
@@ -1,21 +1,21 @@
|
|
|
1
1
|
import { describe, test, expect, mock, beforeEach, afterEach } from 'bun:test';
|
|
2
|
-
import { TursoApiPlatformClient
|
|
2
|
+
import { TursoApiPlatformClient } from './client';
|
|
3
3
|
import { TursoApiPlatform } from './index';
|
|
4
4
|
import { TursoApiPlatformApiError } from '../types';
|
|
5
5
|
|
|
6
6
|
describe('TursoApiPlatformClient', () => {
|
|
7
7
|
test('requires apiKey', () => {
|
|
8
|
-
expect(() => new TursoApiPlatformClient({ apiKey: '' })).toThrow('API key is required');
|
|
8
|
+
expect(() => new TursoApiPlatformClient({ apiKey: '', baseUrl: 'https://configured.example.com/v1' })).toThrow('API key is required');
|
|
9
9
|
});
|
|
10
10
|
|
|
11
11
|
test('builds canonical items URL', () => {
|
|
12
|
-
const client = new TursoApiPlatformClient({ apiKey: 'test-key' });
|
|
13
|
-
expect(client.buildUrl('/items')).toBe(
|
|
12
|
+
const client = new TursoApiPlatformClient({ apiKey: 'test-key', baseUrl: 'https://configured.example.com/v1' });
|
|
13
|
+
expect(client.buildUrl('/items')).toBe(`https://configured.example.com/v1/items`);
|
|
14
14
|
});
|
|
15
15
|
|
|
16
16
|
test('builds canonical item-by-id URL', () => {
|
|
17
|
-
const client = new TursoApiPlatformClient({ apiKey: 'test-key' });
|
|
18
|
-
expect(client.buildUrl('/items/item-123')).toBe(
|
|
17
|
+
const client = new TursoApiPlatformClient({ apiKey: 'test-key', baseUrl: 'https://configured.example.com/v1' });
|
|
18
|
+
expect(client.buildUrl('/items/item-123')).toBe(`https://configured.example.com/v1/items/item-123`);
|
|
19
19
|
});
|
|
20
20
|
|
|
21
21
|
test('respects custom base URL', () => {
|
|
@@ -27,7 +27,7 @@ describe('TursoApiPlatformClient', () => {
|
|
|
27
27
|
});
|
|
28
28
|
|
|
29
29
|
test('getApiKeyPreview masks key', () => {
|
|
30
|
-
const client = new TursoApiPlatformClient({ apiKey: 'abcdef1234567890' });
|
|
30
|
+
const client = new TursoApiPlatformClient({ apiKey: 'abcdef1234567890', baseUrl: 'https://configured.example.com/v1' });
|
|
31
31
|
expect(client.getApiKeyPreview()).toBe('abcdef...7890');
|
|
32
32
|
});
|
|
33
33
|
});
|
|
@@ -44,7 +44,7 @@ describe('TursoApiPlatformClient request', () => {
|
|
|
44
44
|
});
|
|
45
45
|
|
|
46
46
|
test('sends Bearer authorization header on list items', async () => {
|
|
47
|
-
const client = new TursoApiPlatformClient({ apiKey: 'secret-api-key' });
|
|
47
|
+
const client = new TursoApiPlatformClient({ apiKey: 'secret-api-key', baseUrl: 'https://configured.example.com/v1' });
|
|
48
48
|
let capturedUrl = '';
|
|
49
49
|
let capturedHeaders: Headers | undefined;
|
|
50
50
|
|
|
@@ -60,13 +60,13 @@ describe('TursoApiPlatformClient request', () => {
|
|
|
60
60
|
}) as unknown as typeof fetch;
|
|
61
61
|
|
|
62
62
|
const result = await client.get('/items');
|
|
63
|
-
expect(capturedUrl).toBe(
|
|
63
|
+
expect(capturedUrl).toBe(`https://configured.example.com/v1/items`);
|
|
64
64
|
expect(capturedHeaders?.get('Authorization')).toBe('Bearer secret-api-key');
|
|
65
65
|
expect(result).toEqual([{ id: '1', name: 'alpha' }]);
|
|
66
66
|
});
|
|
67
67
|
|
|
68
68
|
test('sends Bearer authorization header on get item', async () => {
|
|
69
|
-
const client = new TursoApiPlatformClient({ apiKey: 'secret-api-key' });
|
|
69
|
+
const client = new TursoApiPlatformClient({ apiKey: 'secret-api-key', baseUrl: 'https://configured.example.com/v1' });
|
|
70
70
|
let capturedUrl = '';
|
|
71
71
|
let capturedHeaders: Headers | undefined;
|
|
72
72
|
|
|
@@ -81,16 +81,16 @@ describe('TursoApiPlatformClient request', () => {
|
|
|
81
81
|
);
|
|
82
82
|
}) as unknown as typeof fetch;
|
|
83
83
|
|
|
84
|
-
const api = new TursoApiPlatform({ apiKey: 'secret-api-key' });
|
|
84
|
+
const api = new TursoApiPlatform({ apiKey: 'secret-api-key', baseUrl: 'https://configured.example.com/v1' });
|
|
85
85
|
const result = await api.getItem('item-42');
|
|
86
86
|
|
|
87
|
-
expect(capturedUrl).toBe(
|
|
87
|
+
expect(capturedUrl).toBe(`https://configured.example.com/v1/items/item-42`);
|
|
88
88
|
expect(capturedHeaders?.get('Authorization')).toBe('Bearer secret-api-key');
|
|
89
89
|
expect(result).toEqual({ id: 'item-42', name: 'beta' });
|
|
90
90
|
});
|
|
91
91
|
|
|
92
92
|
test('throws TursoApiPlatformApiError on HTTP error', async () => {
|
|
93
|
-
const client = new TursoApiPlatformClient({ apiKey: 'secret-api-key' });
|
|
93
|
+
const client = new TursoApiPlatformClient({ apiKey: 'secret-api-key', baseUrl: 'https://configured.example.com/v1' });
|
|
94
94
|
|
|
95
95
|
globalThis.fetch = mock(() =>
|
|
96
96
|
Promise.resolve(
|
|
@@ -103,4 +103,8 @@ describe('TursoApiPlatformClient request', () => {
|
|
|
103
103
|
|
|
104
104
|
await expect(client.get('/items')).rejects.toThrow(TursoApiPlatformApiError);
|
|
105
105
|
});
|
|
106
|
+
|
|
107
|
+
test('refuses to send without a configured base URL (no default endpoint)', () => {
|
|
108
|
+
expect(() => new TursoApiPlatformClient({ apiKey: 'test-key' })).toThrow(/baseUrl/);
|
|
109
|
+
});
|
|
106
110
|
});
|
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
import type { TursoApiPlatformConfig, TursoApiPlatformErrorResponse } from '../types';
|
|
2
2
|
import { TursoApiPlatformApiError } from '../types';
|
|
3
3
|
|
|
4
|
-
export const DEFAULT_BASE_URL = 'https://api.tursoapiplatform.com/v1';
|
|
5
|
-
|
|
6
4
|
export interface RequestOptions {
|
|
7
5
|
method?: 'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH';
|
|
8
6
|
params?: Record<string, string | number | boolean | undefined>;
|
|
@@ -19,7 +17,10 @@ export class TursoApiPlatformClient {
|
|
|
19
17
|
throw new Error('API key is required');
|
|
20
18
|
}
|
|
21
19
|
this.apiKey = config.apiKey;
|
|
22
|
-
|
|
20
|
+
if (!config.baseUrl) {
|
|
21
|
+
throw new Error('baseUrl is required: no default endpoint is configured; set baseUrl (profile, config, or the connector BASE_URL environment variable)');
|
|
22
|
+
}
|
|
23
|
+
this.baseUrl = config.baseUrl.replace(/\/$/, '');
|
|
23
24
|
}
|
|
24
25
|
|
|
25
26
|
buildUrl(path: string, params?: Record<string, string | number | boolean | undefined>): string {
|
|
@@ -55,7 +55,7 @@ authCmd
|
|
|
55
55
|
authCmd
|
|
56
56
|
.command('set-base-url')
|
|
57
57
|
.description('Set custom API base URL')
|
|
58
|
-
.argument('<url>', 'Base URL (e.g. https://
|
|
58
|
+
.argument('<url>', 'Base URL (e.g. https://configured.example.com/v1)')
|
|
59
59
|
.action((url: string) => {
|
|
60
60
|
setBaseUrl(url);
|
|
61
61
|
console.log(chalk.green(`Base URL saved to profile "${getCurrentProfile()}"`));
|
|
@@ -76,7 +76,7 @@ authCmd
|
|
|
76
76
|
|
|
77
77
|
console.log(chalk.bold('Configuration:'));
|
|
78
78
|
console.log(` Profile: ${chalk.cyan(getCurrentProfile())}`);
|
|
79
|
-
console.log(` Base URL: ${chalk.white(baseUrl || '
|
|
79
|
+
console.log(` Base URL: ${chalk.white(baseUrl || 'none configured')}`);
|
|
80
80
|
console.log(` API Key: ${chalk.green('Set')}`);
|
|
81
81
|
|
|
82
82
|
try {
|
|
@@ -4,7 +4,7 @@ Guidance for working with the Twilio Api Platform connector.
|
|
|
4
4
|
|
|
5
5
|
## Overview
|
|
6
6
|
|
|
7
|
-
`connect-twilio-api-platform` is a TypeScript CLI and library for the Twilio Api Platform REST API (`
|
|
7
|
+
`connect-twilio-api-platform` is a TypeScript CLI and library for the Twilio Api Platform REST API (`configured.example.com/v1`). This is distinct from `connect-twilio` (classic Twilio SMS/voice at `api.twilio.com`).
|
|
8
8
|
|
|
9
9
|
## Commands
|
|
10
10
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { afterEach, describe, expect, mock, test } from 'bun:test';
|
|
2
|
-
import { TwilioApiPlatform, TwilioApiPlatformClient
|
|
2
|
+
import { TwilioApiPlatform, TwilioApiPlatformClient } from './index';
|
|
3
3
|
import { TwilioApiPlatformApiError } from '../types';
|
|
4
4
|
|
|
5
5
|
const realFetch = globalThis.fetch;
|
|
@@ -26,29 +26,29 @@ afterEach(() => {
|
|
|
26
26
|
|
|
27
27
|
describe('TwilioApiPlatformClient', () => {
|
|
28
28
|
test('requires api key', () => {
|
|
29
|
-
expect(() => new TwilioApiPlatformClient({ apiKey: '' })).toThrow('API key is required');
|
|
29
|
+
expect(() => new TwilioApiPlatformClient({ apiKey: '', baseUrl: 'https://configured.example.com/v1' })).toThrow('API key is required');
|
|
30
30
|
});
|
|
31
31
|
|
|
32
|
-
test('
|
|
33
|
-
expect(
|
|
32
|
+
test('refuses to send without a configured base URL (no default endpoint)', () => {
|
|
33
|
+
expect(() => new TwilioApiPlatformClient({ apiKey: 'test-key' })).toThrow(/baseUrl/);
|
|
34
34
|
});
|
|
35
35
|
|
|
36
36
|
test('listItems sends Bearer auth to /items', async () => {
|
|
37
37
|
const captured = installFetch();
|
|
38
|
-
const client = new TwilioApiPlatformClient({ apiKey: 'twilio-api-platform-key' });
|
|
38
|
+
const client = new TwilioApiPlatformClient({ apiKey: 'twilio-api-platform-key', baseUrl: 'https://configured.example.com/v1' });
|
|
39
39
|
await client.get('/items');
|
|
40
40
|
|
|
41
41
|
expect(captured).toHaveLength(1);
|
|
42
|
-
expect(captured[0].url).toBe('https://
|
|
42
|
+
expect(captured[0].url).toBe('https://configured.example.com/v1/items');
|
|
43
43
|
expect(new Headers(captured[0].init?.headers).get('Authorization')).toBe('Bearer twilio-api-platform-key');
|
|
44
44
|
});
|
|
45
45
|
|
|
46
46
|
test('getItem encodes item id in path', async () => {
|
|
47
47
|
const captured = installFetch();
|
|
48
|
-
const api = new TwilioApiPlatform({ apiKey: 'twilio-api-platform-key' });
|
|
48
|
+
const api = new TwilioApiPlatform({ apiKey: 'twilio-api-platform-key', baseUrl: 'https://configured.example.com/v1' });
|
|
49
49
|
await api.getItem('item-1');
|
|
50
50
|
|
|
51
|
-
expect(captured[0].url).toBe('https://
|
|
51
|
+
expect(captured[0].url).toBe('https://configured.example.com/v1/items/item-1');
|
|
52
52
|
expect(new Headers(captured[0].init?.headers).get('Authorization')).toBe('Bearer twilio-api-platform-key');
|
|
53
53
|
});
|
|
54
54
|
|
|
@@ -65,11 +65,11 @@ describe('TwilioApiPlatformClient', () => {
|
|
|
65
65
|
|
|
66
66
|
test('search posts JSON body to /search', async () => {
|
|
67
67
|
const captured = installFetch();
|
|
68
|
-
const api = new TwilioApiPlatform({ apiKey: 'key' });
|
|
68
|
+
const api = new TwilioApiPlatform({ apiKey: 'key', baseUrl: 'https://configured.example.com/v1' });
|
|
69
69
|
await api.search({ q: 'hello' });
|
|
70
70
|
|
|
71
71
|
const request = captured[0];
|
|
72
|
-
expect(request.url).toBe('https://
|
|
72
|
+
expect(request.url).toBe('https://configured.example.com/v1/search');
|
|
73
73
|
expect(request.init?.method).toBe('POST');
|
|
74
74
|
expect(request.init?.body).toBe(JSON.stringify({ q: 'hello' }));
|
|
75
75
|
});
|
|
@@ -79,7 +79,7 @@ describe('TwilioApiPlatformClient', () => {
|
|
|
79
79
|
Response.json({ message: 'Unauthorized' }, { status: 401 }),
|
|
80
80
|
) as unknown as typeof fetch;
|
|
81
81
|
|
|
82
|
-
const client = new TwilioApiPlatformClient({ apiKey: 'bad-key' });
|
|
82
|
+
const client = new TwilioApiPlatformClient({ apiKey: 'bad-key', baseUrl: 'https://configured.example.com/v1' });
|
|
83
83
|
await expect(client.get('/items')).rejects.toThrow(TwilioApiPlatformApiError);
|
|
84
84
|
});
|
|
85
85
|
});
|
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
import type { TwilioApiPlatformConfig } from '../types';
|
|
2
2
|
import { parseApiError } from '../types';
|
|
3
3
|
|
|
4
|
-
export const DEFAULT_BASE_URL = 'https://api.twilioapiplatform.com/v1';
|
|
5
|
-
|
|
6
4
|
export interface RequestOptions {
|
|
7
5
|
method?: 'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH';
|
|
8
6
|
params?: Record<string, string | number | boolean | undefined>;
|
|
@@ -19,7 +17,10 @@ export class TwilioApiPlatformClient {
|
|
|
19
17
|
throw new Error('API key is required');
|
|
20
18
|
}
|
|
21
19
|
this.apiKey = config.apiKey;
|
|
22
|
-
|
|
20
|
+
if (!config.baseUrl) {
|
|
21
|
+
throw new Error('baseUrl is required: no default endpoint is configured; set baseUrl (profile, config, or the connector BASE_URL environment variable)');
|
|
22
|
+
}
|
|
23
|
+
this.baseUrl = config.baseUrl.replace(/\/$/, '');
|
|
23
24
|
}
|
|
24
25
|
|
|
25
26
|
private buildUrl(path: string, params?: Record<string, string | number | boolean | undefined>): string {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { TwilioApiPlatformConfig, TwilioApiPlatformResponse } from '../types';
|
|
2
2
|
import { TwilioApiPlatformClient, type RequestOptions } from './client';
|
|
3
3
|
|
|
4
|
-
export { TwilioApiPlatformClient
|
|
4
|
+
export { TwilioApiPlatformClient } from './client';
|
|
5
5
|
|
|
6
6
|
export class TwilioApiPlatform {
|
|
7
7
|
private readonly client: TwilioApiPlatformClient;
|
|
@@ -202,7 +202,7 @@ configCmd
|
|
|
202
202
|
console.log(chalk.bold(`Active Profile: ${profileName}`));
|
|
203
203
|
info(`Config directory: ${getConfigDir()}`);
|
|
204
204
|
info(`API Key: ${apiKey ? `${apiKey.substring(0, 8)}...` : chalk.gray('not set')}`);
|
|
205
|
-
info(`Base URL: ${baseUrl || '
|
|
205
|
+
info(`Base URL: ${baseUrl || 'none configured'}`);
|
|
206
206
|
});
|
|
207
207
|
|
|
208
208
|
configCmd
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
# Tyk API Platform credentials
|
|
2
2
|
TYK_API_PLATFORM_API_KEY=your-api-key-here
|
|
3
3
|
|
|
4
|
-
# Optional: override the API base URL (default
|
|
4
|
+
# Optional: override the API base URL (no default - must be configured)
|
|
5
5
|
# TYK_API_PLATFORM_BASE_URL=https://api.tykapiplatform.com/v1
|
|
@@ -53,7 +53,7 @@ connect-tyk-api-platform raw --path /search --method POST --data '{"query":"test
|
|
|
53
53
|
| Variable | Description |
|
|
54
54
|
|----------|-------------|
|
|
55
55
|
| `TYK_API_PLATFORM_API_KEY` | API key (overrides profile config) |
|
|
56
|
-
| `TYK_API_PLATFORM_BASE_URL` | API base URL (default: `
|
|
56
|
+
| `TYK_API_PLATFORM_BASE_URL` | API base URL (default: `configured.example.com/v1`) |
|
|
57
57
|
|
|
58
58
|
## Authentication
|
|
59
59
|
|
|
@@ -73,7 +73,7 @@ Profile JSON structure:
|
|
|
73
73
|
```json
|
|
74
74
|
{
|
|
75
75
|
"apiKey": "your-api-key",
|
|
76
|
-
"baseUrl": "
|
|
76
|
+
"baseUrl": "configured.example.com/v1"
|
|
77
77
|
}
|
|
78
78
|
```
|
|
79
79
|
|