@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.
Files changed (168) hide show
  1. package/bin/index.js +145 -98
  2. package/bin/mcp.js +1 -1
  3. package/bin/serve.js +144 -93
  4. package/connectors/clickbank/README.md +2 -2
  5. package/connectors/split-in-batches/CLAUDE.md +1 -1
  6. package/connectors/split-in-batches/README.md +1 -1
  7. package/connectors/split-in-batches/src/api/client.test.ts +16 -17
  8. package/connectors/split-in-batches/src/api/client.ts +4 -3
  9. package/connectors/split-in-batches/src/cli/index.ts +1 -1
  10. package/connectors/spreadsheet-file/.env.example +1 -1
  11. package/connectors/spreadsheet-file/CLAUDE.md +2 -2
  12. package/connectors/spreadsheet-file/README.md +3 -3
  13. package/connectors/spreadsheet-file/src/api/client.test.ts +8 -9
  14. package/connectors/spreadsheet-file/src/api/client.ts +4 -3
  15. package/connectors/spreadsheet-file/src/cli/index.ts +1 -1
  16. package/connectors/sse-trigger/.env.example +1 -1
  17. package/connectors/sse-trigger/CLAUDE.md +2 -2
  18. package/connectors/sse-trigger/README.md +1 -1
  19. package/connectors/sse-trigger/src/api/client.test.ts +12 -8
  20. package/connectors/sse-trigger/src/api/client.ts +4 -3
  21. package/connectors/sse-trigger/src/api/index.ts +1 -1
  22. package/connectors/sse-trigger/src/cli/index.ts +1 -1
  23. package/connectors/sse-trigger/src/index.ts +1 -1
  24. package/connectors/stability-api-platform/AGENTS.md +1 -1
  25. package/connectors/stability-api-platform/CLAUDE.md +1 -1
  26. package/connectors/stability-api-platform/README.md +2 -2
  27. package/connectors/stability-api-platform/src/api/client.test.ts +17 -12
  28. package/connectors/stability-api-platform/src/api/client.ts +4 -3
  29. package/connectors/stability-api-platform/src/api/index.ts +0 -1
  30. package/connectors/stability-api-platform/src/cli/index.ts +1 -1
  31. package/connectors/stability-api-platform/src/index.ts +0 -1
  32. package/connectors/stop-and-error/.env.example +1 -1
  33. package/connectors/stop-and-error/CLAUDE.md +1 -1
  34. package/connectors/stop-and-error/README.md +1 -1
  35. package/connectors/stop-and-error/src/api/client.test.ts +12 -8
  36. package/connectors/stop-and-error/src/api/client.ts +4 -3
  37. package/connectors/stop-and-error/src/cli/index.ts +2 -2
  38. package/connectors/stripe-financial-connections/.env.example +1 -1
  39. package/connectors/stripe-financial-connections/CLAUDE.md +2 -2
  40. package/connectors/stripe-financial-connections/src/api/client.test.ts +34 -0
  41. package/connectors/stripe-financial-connections/src/api/client.ts +4 -3
  42. package/connectors/stripe-financial-connections/src/cli/index.ts +1 -1
  43. package/connectors/sucuri-api-platform/.env.example +1 -1
  44. package/connectors/sucuri-api-platform/CLAUDE.md +1 -1
  45. package/connectors/sucuri-api-platform/README.md +2 -2
  46. package/connectors/sucuri-api-platform/src/api/client.test.ts +9 -7
  47. package/connectors/sucuri-api-platform/src/api/client.ts +4 -3
  48. package/connectors/sucuri-api-platform/src/api/index.ts +1 -1
  49. package/connectors/sucuri-api-platform/src/cli/index.ts +1 -1
  50. package/connectors/sucuri-api-platform/src/index.ts +1 -1
  51. package/connectors/tettra-api-platform/CLAUDE.md +1 -1
  52. package/connectors/tettra-api-platform/README.md +2 -2
  53. package/connectors/tettra-api-platform/src/api/client.test.ts +7 -8
  54. package/connectors/tettra-api-platform/src/api/client.ts +4 -3
  55. package/connectors/tettra-api-platform/src/api/index.ts +1 -1
  56. package/connectors/tettra-api-platform/src/cli/index.ts +1 -1
  57. package/connectors/tettra-api-platform/src/index.ts +1 -1
  58. package/connectors/together-api-platform/.env.example +1 -1
  59. package/connectors/together-api-platform/CLAUDE.md +1 -1
  60. package/connectors/together-api-platform/README.md +1 -1
  61. package/connectors/together-api-platform/src/api/client.test.ts +11 -7
  62. package/connectors/together-api-platform/src/api/client.ts +4 -4
  63. package/connectors/together-api-platform/src/api/index.ts +1 -1
  64. package/connectors/together-api-platform/src/cli/index.ts +1 -1
  65. package/connectors/together-api-platform/src/index.ts +1 -1
  66. package/connectors/travo-real-estate/CLAUDE.md +1 -1
  67. package/connectors/travo-real-estate/README.md +1 -1
  68. package/connectors/travo-real-estate/src/api/client.test.ts +20 -16
  69. package/connectors/travo-real-estate/src/api/client.ts +4 -3
  70. package/connectors/travo-real-estate/src/utils/config.ts +2 -4
  71. package/connectors/tray-api-platform/CLAUDE.md +1 -1
  72. package/connectors/tray-api-platform/src/api/client.test.ts +17 -13
  73. package/connectors/tray-api-platform/src/api/client.ts +4 -3
  74. package/connectors/tray-api-platform/src/api/index.ts +1 -1
  75. package/connectors/tray-api-platform/src/cli/index.ts +1 -1
  76. package/connectors/tray-api-platform/src/index.ts +0 -1
  77. package/connectors/turso-api-platform/CLAUDE.md +1 -1
  78. package/connectors/turso-api-platform/README.md +2 -2
  79. package/connectors/turso-api-platform/src/api/client.test.ts +17 -13
  80. package/connectors/turso-api-platform/src/api/client.ts +4 -3
  81. package/connectors/turso-api-platform/src/cli/index.ts +2 -2
  82. package/connectors/twilio-api-platform/CLAUDE.md +1 -1
  83. package/connectors/twilio-api-platform/src/api/client.test.ts +11 -11
  84. package/connectors/twilio-api-platform/src/api/client.ts +4 -3
  85. package/connectors/twilio-api-platform/src/api/index.ts +1 -1
  86. package/connectors/twilio-api-platform/src/cli/index.ts +1 -1
  87. package/connectors/twilio-api-platform/src/index.ts +1 -1
  88. package/connectors/tyk-api-platform/.env.example +1 -1
  89. package/connectors/tyk-api-platform/CLAUDE.md +2 -2
  90. package/connectors/tyk-api-platform/README.md +1 -1
  91. package/connectors/tyk-api-platform/src/api/client.test.ts +14 -15
  92. package/connectors/tyk-api-platform/src/api/client.ts +4 -3
  93. package/connectors/tyk-api-platform/src/api/index.ts +1 -1
  94. package/connectors/tyk-api-platform/src/cli/index.ts +1 -1
  95. package/connectors/tyk-api-platform/src/index.ts +1 -1
  96. package/connectors/vector-legal/.env.example +1 -1
  97. package/connectors/vector-legal/AGENTS.md +1 -1
  98. package/connectors/vector-legal/CLAUDE.md +1 -1
  99. package/connectors/vector-legal/README.md +1 -1
  100. package/connectors/vector-legal/src/api/client.test.ts +9 -5
  101. package/connectors/vector-legal/src/api/client.ts +4 -3
  102. package/connectors/vector-legal/src/api/index.ts +1 -1
  103. package/connectors/vector-legal/src/cli/index.ts +2 -2
  104. package/connectors/vector-legal/src/index.ts +0 -1
  105. package/connectors/vector-legal-api/CLAUDE.md +1 -1
  106. package/connectors/vector-legal-api/README.md +2 -2
  107. package/connectors/vector-legal-api/src/api/client.test.ts +12 -7
  108. package/connectors/vector-legal-api/src/api/client.ts +4 -3
  109. package/connectors/vector-legal-api/src/api/index.ts +1 -1
  110. package/connectors/vector-legal-api/src/cli/index.ts +1 -1
  111. package/connectors/vector-legal-api/src/index.ts +1 -2
  112. package/connectors/velum-data-quality/.env.example +1 -1
  113. package/connectors/velum-data-quality/CLAUDE.md +1 -1
  114. package/connectors/velum-data-quality/src/api/client.test.ts +15 -16
  115. package/connectors/velum-data-quality/src/api/client.ts +4 -3
  116. package/connectors/velum-data-quality/src/api/index.ts +1 -1
  117. package/connectors/velum-data-quality/src/cli/index.ts +1 -1
  118. package/connectors/velum-data-quality/src/index.ts +0 -1
  119. package/connectors/vercel-api-platform/.env.example +1 -1
  120. package/connectors/vercel-api-platform/CLAUDE.md +2 -2
  121. package/connectors/vercel-api-platform/README.md +2 -2
  122. package/connectors/vercel-api-platform/src/api/client.test.ts +27 -6
  123. package/connectors/vercel-api-platform/src/api/client.ts +4 -3
  124. package/connectors/vercel-api-platform/src/api/index.ts +1 -1
  125. package/connectors/vercel-api-platform/src/cli/index.ts +2 -2
  126. package/connectors/vercel-api-platform/src/index.ts +0 -1
  127. package/connectors/veriphone/README.md +2 -2
  128. package/connectors/wave-accounting/CLAUDE.md +1 -1
  129. package/connectors/wave-accounting/src/utils/auth.ts +1 -1
  130. package/connectors/weaviate-api-platform/CLAUDE.md +1 -1
  131. package/connectors/weaviate-api-platform/src/api/client.test.ts +32 -7
  132. package/connectors/weaviate-api-platform/src/api/client.ts +4 -3
  133. package/connectors/weaviate-api-platform/src/api/index.ts +1 -1
  134. package/connectors/weaviate-api-platform/src/cli/index.ts +1 -1
  135. package/connectors/weaviate-api-platform/src/index.ts +1 -1
  136. package/connectors/workflow-trigger/.env.example +1 -1
  137. package/connectors/workflow-trigger/CLAUDE.md +1 -1
  138. package/connectors/workflow-trigger/README.md +1 -1
  139. package/connectors/workflow-trigger/src/api/client.test.ts +10 -6
  140. package/connectors/workflow-trigger/src/api/client.ts +4 -3
  141. package/connectors/workflow-trigger/src/cli/index.ts +1 -1
  142. package/connectors/write-binary-file/CLAUDE.md +1 -1
  143. package/connectors/write-binary-file/README.md +1 -1
  144. package/connectors/write-binary-file/src/api/client.test.ts +16 -12
  145. package/connectors/write-binary-file/src/api/client.ts +4 -3
  146. package/connectors/write-binary-file/src/api/index.ts +1 -1
  147. package/connectors/write-binary-file/src/index.ts +1 -1
  148. package/connectors/wubookratechecker/src/api/client.test.ts +34 -0
  149. package/connectors/wubookratechecker/src/api/client.ts +3 -1
  150. package/connectors/wubookratechecker/src/api/index.ts +1 -1
  151. package/connectors/wubookratechecker/src/types/index.ts +1 -1
  152. package/connectors/xai-api-platform/.env.example +1 -1
  153. package/connectors/xai-api-platform/CLAUDE.md +1 -1
  154. package/connectors/xai-api-platform/README.md +1 -1
  155. package/connectors/xai-api-platform/src/api/client.test.ts +33 -8
  156. package/connectors/xai-api-platform/src/api/client.ts +4 -3
  157. package/connectors/xai-api-platform/src/api/index.ts +1 -1
  158. package/connectors/xai-api-platform/src/index.ts +1 -1
  159. package/connectors/xai-api-platform/src/utils/config.ts +2 -3
  160. package/connectors/zapier-api-platform/CLAUDE.md +1 -1
  161. package/connectors/zapier-api-platform/README.md +1 -1
  162. package/connectors/zapier-api-platform/src/api/client.test.ts +19 -14
  163. package/connectors/zapier-api-platform/src/api/client.ts +4 -3
  164. package/connectors/zapier-api-platform/src/api/index.ts +1 -1
  165. package/connectors/zapier-api-platform/src/cli/index.ts +1 -1
  166. package/connectors/zapier-api-platform/src/index.ts +1 -1
  167. package/dist/index.js +1 -1
  168. 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://api.travo-real-estate.com/v1/listings');
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://api.travo-real-estate.com/v1/listings');
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://api.travo-real-estate.com/v1/listings/item-1');
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://api.travo-real-estate.com/v1/events?limit=10');
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://api.travo-real-estate.com/v1/search');
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://api.travo-real-estate.com/v1/listings');
143
- expect(captured[1]).toBe('https://api.travo-real-estate.com/v1/listings/item-1');
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
- this.baseUrl = (config.baseUrl || DEFAULT_BASE_URL).replace(/\/$/, '');
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 || DEFAULT_BASE_URL;
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**: `https://api.trayapiplatform.com/v1` (tenant-specific override supported)
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(`${DEFAULT_BASE_URL}/items`);
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(`${DEFAULT_BASE_URL}/items/item%2F123`);
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(`${DEFAULT_BASE_URL}/items`);
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(`${DEFAULT_BASE_URL}/events`);
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(`${DEFAULT_BASE_URL}/search`);
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(`${DEFAULT_BASE_URL}/custom/path`);
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
- this.baseUrl = (config.baseUrl || DEFAULT_BASE_URL).replace(/\/+$/, '');
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, DEFAULT_BASE_URL } from './client';
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('https://api.trayapiplatform.com/v1 (default)')}`);
222
+ info(`Base URL: ${baseUrl || chalk.gray('none configured')}`);
223
223
  });
224
224
 
225
225
  configCmd
@@ -2,7 +2,6 @@ export { Connector } from './api';
2
2
  export * from './types';
3
3
  export {
4
4
  ConnectorClient,
5
- DEFAULT_BASE_URL,
6
5
  ItemsApi,
7
6
  EventsApi,
8
7
  SearchApi,
@@ -20,7 +20,7 @@ bun test
20
20
 
21
21
  Bearer token via `Authorization: Bearer <api_key>` header.
22
22
 
23
- Default base URL: `https://api.tursoapiplatform.com/v1`
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](https://api.tursoapiplatform.com) REST API.
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 https://api.tursoapiplatform.com/v1
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, DEFAULT_BASE_URL } from './client';
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(`${DEFAULT_BASE_URL}/items`);
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(`${DEFAULT_BASE_URL}/items/item-123`);
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(`${DEFAULT_BASE_URL}/items`);
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(`${DEFAULT_BASE_URL}/items/item-42`);
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
- this.baseUrl = (config.baseUrl || DEFAULT_BASE_URL).replace(/\/$/, '');
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://api.tursoapiplatform.com/v1)')
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 || 'https://api.tursoapiplatform.com/v1 (default)')}`);
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 (`https://api.twilioapiplatform.com/v1`). This is distinct from `connect-twilio` (classic Twilio SMS/voice at `api.twilio.com`).
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, DEFAULT_BASE_URL } from './index';
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('uses default base URL', () => {
33
- expect(DEFAULT_BASE_URL).toBe('https://api.twilioapiplatform.com/v1');
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://api.twilioapiplatform.com/v1/items');
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://api.twilioapiplatform.com/v1/items/item-1');
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://api.twilioapiplatform.com/v1/search');
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
- this.baseUrl = (config.baseUrl || DEFAULT_BASE_URL).replace(/\/$/, '');
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, DEFAULT_BASE_URL } from './client';
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 || 'https://api.twilioapiplatform.com/v1 (default)'}`);
205
+ info(`Base URL: ${baseUrl || 'none configured'}`);
206
206
  });
207
207
 
208
208
  configCmd
@@ -1,4 +1,4 @@
1
- export { TwilioApiPlatform, TwilioApiPlatformClient, DEFAULT_BASE_URL } from './api';
1
+ export { TwilioApiPlatform, TwilioApiPlatformClient } from './api';
2
2
  export * from './types';
3
3
 
4
4
  export {
@@ -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: https://api.tykapiplatform.com/v1)
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: `https://api.tykapiplatform.com/v1`) |
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": "https://api.tykapiplatform.com/v1"
76
+ "baseUrl": "configured.example.com/v1"
77
77
  }
78
78
  ```
79
79