@stubborn-sh/broker-client 0.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs ADDED
@@ -0,0 +1,427 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/index.ts
21
+ var index_exports = {};
22
+ __export(index_exports, {
23
+ BrokerApiError: () => BrokerApiError,
24
+ BrokerAuthError: () => BrokerAuthError,
25
+ BrokerClient: () => BrokerClient,
26
+ BrokerConflictError: () => BrokerConflictError,
27
+ BrokerConnectionError: () => BrokerConnectionError,
28
+ BrokerForbiddenError: () => BrokerForbiddenError,
29
+ BrokerNotFoundError: () => BrokerNotFoundError,
30
+ BrokerValidationError: () => BrokerValidationError,
31
+ buildAuthHeader: () => buildAuthHeader,
32
+ fetchAllPages: () => fetchAllPages,
33
+ pageIterator: () => pageIterator,
34
+ resolveConfig: () => resolveConfig
35
+ });
36
+ module.exports = __toCommonJS(index_exports);
37
+
38
+ // src/config.ts
39
+ var DEFAULT_PAGE_SIZE = 20;
40
+ var DEFAULT_TIMEOUT_MS = 3e4;
41
+ function resolveConfig(config) {
42
+ const baseUrl = config.baseUrl.replace(/\/+$/, "");
43
+ if (!/^https?:\/\//i.test(baseUrl)) {
44
+ throw new Error(`Invalid baseUrl scheme: "${baseUrl}". Must start with http:// or https://`);
45
+ }
46
+ return {
47
+ ...config,
48
+ baseUrl,
49
+ defaultPageSize: config.defaultPageSize !== void 0 && config.defaultPageSize > 0 ? config.defaultPageSize : DEFAULT_PAGE_SIZE,
50
+ timeoutMs: config.timeoutMs !== void 0 && config.timeoutMs > 0 ? config.timeoutMs : DEFAULT_TIMEOUT_MS
51
+ };
52
+ }
53
+ function buildAuthHeader(config) {
54
+ if (config.token !== void 0 && config.token !== "") {
55
+ return `Bearer ${config.token}`;
56
+ }
57
+ if (config.username !== void 0 && config.username !== "") {
58
+ const encoded = Buffer.from(`${config.username}:${config.password ?? ""}`).toString("base64");
59
+ return `Basic ${encoded}`;
60
+ }
61
+ return void 0;
62
+ }
63
+
64
+ // src/errors.ts
65
+ var BrokerApiError = class extends Error {
66
+ status;
67
+ errorResponse;
68
+ constructor(status, message, errorResponse = null) {
69
+ super(message);
70
+ this.name = "BrokerApiError";
71
+ this.status = status;
72
+ this.errorResponse = errorResponse;
73
+ }
74
+ };
75
+ var BrokerAuthError = class extends BrokerApiError {
76
+ constructor(message = "Authentication failed", errorResponse = null) {
77
+ super(401, message, errorResponse);
78
+ this.name = "BrokerAuthError";
79
+ }
80
+ };
81
+ var BrokerForbiddenError = class extends BrokerApiError {
82
+ constructor(message = "Insufficient permissions", errorResponse = null) {
83
+ super(403, message, errorResponse);
84
+ this.name = "BrokerForbiddenError";
85
+ }
86
+ };
87
+ var BrokerNotFoundError = class extends BrokerApiError {
88
+ constructor(message = "Resource not found", errorResponse = null) {
89
+ super(404, message, errorResponse);
90
+ this.name = "BrokerNotFoundError";
91
+ }
92
+ };
93
+ var BrokerConflictError = class extends BrokerApiError {
94
+ constructor(message = "Resource already exists", errorResponse = null) {
95
+ super(409, message, errorResponse);
96
+ this.name = "BrokerConflictError";
97
+ }
98
+ };
99
+ var BrokerValidationError = class extends BrokerApiError {
100
+ constructor(message = "Validation failed", errorResponse = null) {
101
+ super(400, message, errorResponse);
102
+ this.name = "BrokerValidationError";
103
+ }
104
+ };
105
+ var BrokerConnectionError = class extends Error {
106
+ cause;
107
+ constructor(message, cause) {
108
+ super(message);
109
+ this.name = "BrokerConnectionError";
110
+ this.cause = cause;
111
+ }
112
+ };
113
+
114
+ // src/client.ts
115
+ var API_PREFIX = "/api/v1";
116
+ var BrokerClient = class {
117
+ baseUrl;
118
+ config;
119
+ fetchFn;
120
+ defaultPageSize;
121
+ timeoutMs;
122
+ constructor(config) {
123
+ const resolved = resolveConfig(config);
124
+ this.baseUrl = resolved.baseUrl;
125
+ this.config = resolved;
126
+ this.fetchFn = config.fetch ?? globalThis.fetch.bind(globalThis);
127
+ this.defaultPageSize = resolved.defaultPageSize;
128
+ this.timeoutMs = resolved.timeoutMs;
129
+ }
130
+ // ── Applications ──────────────────────────────────────────────────────
131
+ async listApplications(params) {
132
+ const query = this.buildListQuery(params);
133
+ return this.get(`/applications?${query}`);
134
+ }
135
+ async getApplication(name) {
136
+ return this.get(`/applications/${enc(name)}`);
137
+ }
138
+ async registerApplication(request) {
139
+ return this.post("/applications", request);
140
+ }
141
+ async updateApplication(name, request) {
142
+ return this.put(`/applications/${enc(name)}`, request);
143
+ }
144
+ async deleteApplication(name) {
145
+ await this.delete(`/applications/${enc(name)}`);
146
+ }
147
+ async listVersions(applicationName) {
148
+ return this.get(`/applications/${enc(applicationName)}/versions`);
149
+ }
150
+ // ── Contracts ─────────────────────────────────────────────────────────
151
+ async listContracts(applicationName, version, params) {
152
+ const query = this.buildPageQuery(params);
153
+ return this.get(
154
+ `/applications/${enc(applicationName)}/versions/${enc(version)}/contracts?${query}`
155
+ );
156
+ }
157
+ async getContract(applicationName, version, contractName) {
158
+ return this.get(
159
+ `/applications/${enc(applicationName)}/versions/${enc(version)}/contracts/${enc(contractName)}`
160
+ );
161
+ }
162
+ async publishContract(applicationName, version, request) {
163
+ return this.post(
164
+ `/applications/${enc(applicationName)}/versions/${enc(version)}/contracts`,
165
+ request
166
+ );
167
+ }
168
+ async deleteContract(applicationName, version, contractName) {
169
+ await this.delete(
170
+ `/applications/${enc(applicationName)}/versions/${enc(version)}/contracts/${enc(contractName)}`
171
+ );
172
+ }
173
+ // ── Verifications ─────────────────────────────────────────────────────
174
+ async listVerifications(params) {
175
+ const query = this.buildListQuery(params);
176
+ return this.get(`/verifications?${query}`);
177
+ }
178
+ async recordVerification(request) {
179
+ return this.post("/verifications", request);
180
+ }
181
+ // ── Environments ──────────────────────────────────────────────────────
182
+ async listEnvironments() {
183
+ return this.get("/environments");
184
+ }
185
+ async getEnvironment(name) {
186
+ return this.get(`/environments/${enc(name)}`);
187
+ }
188
+ async createEnvironment(request) {
189
+ return this.post("/environments", request);
190
+ }
191
+ async updateEnvironment(name, request) {
192
+ return this.put(`/environments/${enc(name)}`, request);
193
+ }
194
+ async deleteEnvironment(name) {
195
+ await this.delete(`/environments/${enc(name)}`);
196
+ }
197
+ // ── Deployments ───────────────────────────────────────────────────────
198
+ async listDeployments(environment, params) {
199
+ const query = this.buildPageQuery(params);
200
+ return this.get(
201
+ `/environments/${enc(environment)}/deployments?${query}`
202
+ );
203
+ }
204
+ async getDeployment(environment, applicationName) {
205
+ return this.get(
206
+ `/environments/${enc(environment)}/deployments/${enc(applicationName)}`
207
+ );
208
+ }
209
+ async recordDeployment(environment, request) {
210
+ return this.post(`/environments/${enc(environment)}/deployments`, request);
211
+ }
212
+ // ── Safety ────────────────────────────────────────────────────────────
213
+ async canIDeploy(application, version, environment) {
214
+ const params = new URLSearchParams({
215
+ application,
216
+ version,
217
+ environment
218
+ });
219
+ return this.get(`/can-i-deploy?${params.toString()}`);
220
+ }
221
+ // ── Graph ─────────────────────────────────────────────────────────────
222
+ async getDependencyGraph(environment) {
223
+ const params = new URLSearchParams();
224
+ if (environment !== void 0 && environment !== "") {
225
+ params.set("environment", environment);
226
+ }
227
+ const qs = params.toString();
228
+ return this.get(`/graph${qs !== "" ? `?${qs}` : ""}`);
229
+ }
230
+ async getApplicationDependencies(applicationName) {
231
+ return this.get(`/graph/applications/${enc(applicationName)}`);
232
+ }
233
+ // ── Webhooks ──────────────────────────────────────────────────────────
234
+ async listWebhooks(params) {
235
+ const query = this.buildListQuery(params);
236
+ return this.get(`/webhooks?${query}`);
237
+ }
238
+ async getWebhook(id) {
239
+ return this.get(`/webhooks/${enc(id)}`);
240
+ }
241
+ async createWebhook(request) {
242
+ return this.post("/webhooks", request);
243
+ }
244
+ async updateWebhook(id, request) {
245
+ return this.put(`/webhooks/${enc(id)}`, request);
246
+ }
247
+ async deleteWebhook(id) {
248
+ await this.delete(`/webhooks/${enc(id)}`);
249
+ }
250
+ async listWebhookExecutions(id, params) {
251
+ const query = this.buildPageQuery(params);
252
+ return this.get(`/webhooks/${enc(id)}/executions?${query}`);
253
+ }
254
+ // ── Matrix ────────────────────────────────────────────────────────────
255
+ async queryMatrix(provider, consumer) {
256
+ const params = new URLSearchParams();
257
+ if (provider !== void 0 && provider !== "") {
258
+ params.set("provider", provider);
259
+ }
260
+ if (consumer !== void 0 && consumer !== "") {
261
+ params.set("consumer", consumer);
262
+ }
263
+ const qs = params.toString();
264
+ return this.get(`/matrix${qs !== "" ? `?${qs}` : ""}`);
265
+ }
266
+ // ── Selectors ─────────────────────────────────────────────────────────
267
+ async resolveSelectors(selectors) {
268
+ return this.post("/selectors/resolve", { selectors });
269
+ }
270
+ // ── Tags ──────────────────────────────────────────────────────────────
271
+ async listTags(applicationName, version) {
272
+ return this.get(
273
+ `/applications/${enc(applicationName)}/versions/${enc(version)}/tags`
274
+ );
275
+ }
276
+ async addTag(applicationName, version, tag) {
277
+ return this.put(
278
+ `/applications/${enc(applicationName)}/versions/${enc(version)}/tags/${enc(tag)}`
279
+ );
280
+ }
281
+ async removeTag(applicationName, version, tag) {
282
+ await this.delete(
283
+ `/applications/${enc(applicationName)}/versions/${enc(version)}/tags/${enc(tag)}`
284
+ );
285
+ }
286
+ async getLatestVersionByTag(applicationName, tag) {
287
+ return this.get(
288
+ `/applications/${enc(applicationName)}/versions/latest?tag=${enc(tag)}`
289
+ );
290
+ }
291
+ // ── Maintenance ───────────────────────────────────────────────────────
292
+ async runCleanup(request) {
293
+ return this.post("/maintenance/cleanup", request);
294
+ }
295
+ // ── HTTP helpers ──────────────────────────────────────────────────────
296
+ async get(path) {
297
+ return this.request("GET", path);
298
+ }
299
+ async post(path, body) {
300
+ return this.request("POST", path, body);
301
+ }
302
+ async put(path, body) {
303
+ return this.request("PUT", path, body);
304
+ }
305
+ async delete(path) {
306
+ await this.requestRaw("DELETE", path);
307
+ }
308
+ async request(method, path, body) {
309
+ const response = await this.requestRaw(method, path, body);
310
+ return await response.json();
311
+ }
312
+ async requestRaw(method, path, body) {
313
+ const url = `${this.baseUrl}${API_PREFIX}${path}`;
314
+ const headers = {};
315
+ const auth = buildAuthHeader(this.config);
316
+ if (auth !== void 0) {
317
+ headers["Authorization"] = auth;
318
+ }
319
+ if (body !== void 0) {
320
+ headers["Content-Type"] = "application/json";
321
+ }
322
+ let response;
323
+ const init = { method, headers, signal: AbortSignal.timeout(this.timeoutMs) };
324
+ if (body !== void 0) {
325
+ init.body = JSON.stringify(body);
326
+ }
327
+ try {
328
+ response = await this.fetchFn(url, init);
329
+ } catch (err) {
330
+ throw new BrokerConnectionError(
331
+ `Failed to connect to broker at ${this.baseUrl}: ${err instanceof Error ? err.message : String(err)}`,
332
+ err
333
+ );
334
+ }
335
+ if (response.ok) {
336
+ return response;
337
+ }
338
+ let errorResponse = null;
339
+ try {
340
+ errorResponse = await response.json();
341
+ } catch {
342
+ }
343
+ const message = errorResponse?.message ?? `${method} ${path} failed with status ${String(response.status)}`;
344
+ switch (response.status) {
345
+ case 400:
346
+ throw new BrokerValidationError(message, errorResponse);
347
+ case 401:
348
+ throw new BrokerAuthError(message, errorResponse);
349
+ case 403:
350
+ throw new BrokerForbiddenError(message, errorResponse);
351
+ case 404:
352
+ throw new BrokerNotFoundError(message, errorResponse);
353
+ case 409:
354
+ throw new BrokerConflictError(message, errorResponse);
355
+ default:
356
+ throw new BrokerApiError(response.status, message, errorResponse);
357
+ }
358
+ }
359
+ buildPageQuery(params) {
360
+ const urlParams = new URLSearchParams();
361
+ urlParams.set("page", String(params?.page ?? 0));
362
+ urlParams.set("size", String(params?.size ?? this.defaultPageSize));
363
+ if (params?.sort !== void 0 && params.sort !== "") {
364
+ urlParams.set("sort", params.sort);
365
+ }
366
+ return urlParams.toString();
367
+ }
368
+ buildListQuery(params) {
369
+ const urlParams = new URLSearchParams();
370
+ urlParams.set("page", String(params?.page ?? 0));
371
+ urlParams.set("size", String(params?.size ?? this.defaultPageSize));
372
+ if (params?.sort !== void 0 && params.sort !== "") {
373
+ urlParams.set("sort", params.sort);
374
+ }
375
+ if (params?.search !== void 0 && params.search !== "") {
376
+ urlParams.set("search", params.search);
377
+ }
378
+ return urlParams.toString();
379
+ }
380
+ };
381
+ function enc(value) {
382
+ return encodeURIComponent(value);
383
+ }
384
+
385
+ // src/pagination.ts
386
+ var MAX_PAGES = 1e3;
387
+ async function* pageIterator(fetcher, params = {}) {
388
+ let currentPage = params.page ?? 0;
389
+ const size = params.size ?? 20;
390
+ let hasMore = true;
391
+ let pagesRead = 0;
392
+ while (hasMore) {
393
+ if (pagesRead >= MAX_PAGES) {
394
+ throw new Error(`Exceeded maximum page limit (${String(MAX_PAGES)})`);
395
+ }
396
+ const page = await fetcher({ ...params, page: currentPage, size });
397
+ for (const item of page.content) {
398
+ yield item;
399
+ }
400
+ currentPage++;
401
+ pagesRead++;
402
+ hasMore = currentPage < page.totalPages;
403
+ }
404
+ }
405
+ async function fetchAllPages(fetcher, params = {}) {
406
+ const items = [];
407
+ for await (const item of pageIterator(fetcher, params)) {
408
+ items.push(item);
409
+ }
410
+ return items;
411
+ }
412
+ // Annotate the CommonJS export names for ESM import in node:
413
+ 0 && (module.exports = {
414
+ BrokerApiError,
415
+ BrokerAuthError,
416
+ BrokerClient,
417
+ BrokerConflictError,
418
+ BrokerConnectionError,
419
+ BrokerForbiddenError,
420
+ BrokerNotFoundError,
421
+ BrokerValidationError,
422
+ buildAuthHeader,
423
+ fetchAllPages,
424
+ pageIterator,
425
+ resolveConfig
426
+ });
427
+ //# sourceMappingURL=index.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/index.ts","../src/config.ts","../src/errors.ts","../src/client.ts","../src/pagination.ts"],"sourcesContent":["export { BrokerClient } from \"./client.js\";\r\nexport type { BrokerClientConfig } from \"./config.js\";\r\nexport { resolveConfig, buildAuthHeader } from \"./config.js\";\r\nexport { pageIterator, fetchAllPages } from \"./pagination.js\";\r\nexport {\r\n BrokerApiError,\r\n BrokerAuthError,\r\n BrokerForbiddenError,\r\n BrokerNotFoundError,\r\n BrokerConflictError,\r\n BrokerValidationError,\r\n BrokerConnectionError,\r\n} from \"./errors.js\";\r\nexport type {\r\n ApplicationResponse,\r\n RegisterApplicationRequest,\r\n UpdateApplicationRequest,\r\n ContractResponse,\r\n PublishContractRequest,\r\n VerificationResponse,\r\n VerificationStatus,\r\n RecordVerificationRequest,\r\n EnvironmentResponse,\r\n CreateEnvironmentRequest,\r\n UpdateEnvironmentRequest,\r\n DeploymentResponse,\r\n RecordDeploymentRequest,\r\n CanIDeployResponse,\r\n ConsumerResult,\r\n DependencyNode,\r\n DependencyEdge,\r\n DependencyGraphResponse,\r\n ApplicationDependenciesResponse,\r\n EventType,\r\n WebhookResponse,\r\n CreateWebhookRequest,\r\n UpdateWebhookRequest,\r\n WebhookExecutionResponse,\r\n MatrixEntry,\r\n ConsumerVersionSelector,\r\n ResolvedContract,\r\n TagResponse,\r\n CleanupRequest,\r\n CleanupResult,\r\n Page,\r\n PageParams,\r\n ListParams,\r\n ErrorResponse,\r\n} from \"./types.js\";\r\n","/** Configuration for the BrokerClient. */\r\nexport interface BrokerClientConfig {\r\n /** Base URL of the broker API (e.g., \"http://localhost:8080\"). */\r\n readonly baseUrl: string;\r\n\r\n /** Username for basic auth (optional). */\r\n readonly username?: string;\r\n\r\n /** Password for basic auth (optional). */\r\n readonly password?: string;\r\n\r\n /** Bearer token for JWT auth (optional, takes precedence over basic auth). */\r\n readonly token?: string;\r\n\r\n /** Custom fetch implementation (defaults to global fetch). */\r\n readonly fetch?: typeof globalThis.fetch;\r\n\r\n /** Default page size for paginated requests. */\r\n readonly defaultPageSize?: number;\r\n\r\n /** Request timeout in milliseconds (default: 30000). */\r\n readonly timeoutMs?: number;\r\n}\r\n\r\nconst DEFAULT_PAGE_SIZE = 20;\r\nconst DEFAULT_TIMEOUT_MS = 30_000;\r\n\r\n/** Resolve a BrokerClientConfig with defaults applied. */\r\nexport function resolveConfig(\r\n config: BrokerClientConfig,\r\n): Required<Pick<BrokerClientConfig, \"baseUrl\" | \"defaultPageSize\" | \"timeoutMs\">> &\r\n BrokerClientConfig {\r\n const baseUrl = config.baseUrl.replace(/\\/+$/, \"\");\r\n if (!/^https?:\\/\\//i.test(baseUrl)) {\r\n throw new Error(`Invalid baseUrl scheme: \"${baseUrl}\". Must start with http:// or https://`);\r\n }\r\n return {\r\n ...config,\r\n baseUrl,\r\n defaultPageSize:\r\n config.defaultPageSize !== undefined && config.defaultPageSize > 0\r\n ? config.defaultPageSize\r\n : DEFAULT_PAGE_SIZE,\r\n timeoutMs:\r\n config.timeoutMs !== undefined && config.timeoutMs > 0\r\n ? config.timeoutMs\r\n : DEFAULT_TIMEOUT_MS,\r\n };\r\n}\r\n\r\n/** Build the Authorization header value from config. */\r\nexport function buildAuthHeader(config: BrokerClientConfig): string | undefined {\r\n if (config.token !== undefined && config.token !== \"\") {\r\n return `Bearer ${config.token}`;\r\n }\r\n if (config.username !== undefined && config.username !== \"\") {\r\n const encoded = Buffer.from(`${config.username}:${config.password ?? \"\"}`).toString(\"base64\");\r\n return `Basic ${encoded}`;\r\n }\r\n return undefined;\r\n}\r\n","import type { ErrorResponse } from \"./types.js\";\r\n\r\n/** Base error for all broker API errors. */\r\nexport class BrokerApiError extends Error {\r\n readonly status: number;\r\n readonly errorResponse: ErrorResponse | null;\r\n\r\n constructor(status: number, message: string, errorResponse: ErrorResponse | null = null) {\r\n super(message);\r\n this.name = \"BrokerApiError\";\r\n this.status = status;\r\n this.errorResponse = errorResponse;\r\n }\r\n}\r\n\r\n/** 401 Unauthorized — invalid or missing credentials. */\r\nexport class BrokerAuthError extends BrokerApiError {\r\n constructor(\r\n message: string = \"Authentication failed\",\r\n errorResponse: ErrorResponse | null = null,\r\n ) {\r\n super(401, message, errorResponse);\r\n this.name = \"BrokerAuthError\";\r\n }\r\n}\r\n\r\n/** 403 Forbidden — insufficient permissions. */\r\nexport class BrokerForbiddenError extends BrokerApiError {\r\n constructor(\r\n message: string = \"Insufficient permissions\",\r\n errorResponse: ErrorResponse | null = null,\r\n ) {\r\n super(403, message, errorResponse);\r\n this.name = \"BrokerForbiddenError\";\r\n }\r\n}\r\n\r\n/** 404 Not Found — requested resource does not exist. */\r\nexport class BrokerNotFoundError extends BrokerApiError {\r\n constructor(message: string = \"Resource not found\", errorResponse: ErrorResponse | null = null) {\r\n super(404, message, errorResponse);\r\n this.name = \"BrokerNotFoundError\";\r\n }\r\n}\r\n\r\n/** 409 Conflict — resource already exists. */\r\nexport class BrokerConflictError extends BrokerApiError {\r\n constructor(\r\n message: string = \"Resource already exists\",\r\n errorResponse: ErrorResponse | null = null,\r\n ) {\r\n super(409, message, errorResponse);\r\n this.name = \"BrokerConflictError\";\r\n }\r\n}\r\n\r\n/** 400 Bad Request — validation error. */\r\nexport class BrokerValidationError extends BrokerApiError {\r\n constructor(message: string = \"Validation failed\", errorResponse: ErrorResponse | null = null) {\r\n super(400, message, errorResponse);\r\n this.name = \"BrokerValidationError\";\r\n }\r\n}\r\n\r\n/** Network or connection error. */\r\nexport class BrokerConnectionError extends Error {\r\n readonly cause: unknown;\r\n\r\n constructor(message: string, cause: unknown) {\r\n super(message);\r\n this.name = \"BrokerConnectionError\";\r\n this.cause = cause;\r\n }\r\n}\r\n","import type {\r\n ApplicationResponse,\r\n RegisterApplicationRequest,\r\n UpdateApplicationRequest,\r\n ContractResponse,\r\n PublishContractRequest,\r\n VerificationResponse,\r\n RecordVerificationRequest,\r\n EnvironmentResponse,\r\n CreateEnvironmentRequest,\r\n UpdateEnvironmentRequest,\r\n DeploymentResponse,\r\n RecordDeploymentRequest,\r\n CanIDeployResponse,\r\n DependencyGraphResponse,\r\n ApplicationDependenciesResponse,\r\n WebhookResponse,\r\n CreateWebhookRequest,\r\n UpdateWebhookRequest,\r\n WebhookExecutionResponse,\r\n MatrixEntry,\r\n ConsumerVersionSelector,\r\n ResolvedContract,\r\n TagResponse,\r\n CleanupRequest,\r\n CleanupResult,\r\n Page,\r\n PageParams,\r\n ListParams,\r\n ErrorResponse,\r\n} from \"./types.js\";\r\nimport type { BrokerClientConfig } from \"./config.js\";\r\nimport { resolveConfig, buildAuthHeader } from \"./config.js\";\r\nimport {\r\n BrokerApiError,\r\n BrokerAuthError,\r\n BrokerForbiddenError,\r\n BrokerNotFoundError,\r\n BrokerConflictError,\r\n BrokerValidationError,\r\n BrokerConnectionError,\r\n} from \"./errors.js\";\r\n\r\nconst API_PREFIX = \"/api/v1\";\r\n\r\nexport class BrokerClient {\r\n private readonly baseUrl: string;\r\n private readonly config: BrokerClientConfig;\r\n private readonly fetchFn: typeof globalThis.fetch;\r\n private readonly defaultPageSize: number;\r\n private readonly timeoutMs: number;\r\n\r\n constructor(config: BrokerClientConfig) {\r\n const resolved = resolveConfig(config);\r\n this.baseUrl = resolved.baseUrl;\r\n this.config = resolved;\r\n this.fetchFn = config.fetch ?? globalThis.fetch.bind(globalThis);\r\n this.defaultPageSize = resolved.defaultPageSize;\r\n this.timeoutMs = resolved.timeoutMs;\r\n }\r\n\r\n // ── Applications ──────────────────────────────────────────────────────\r\n\r\n async listApplications(params?: ListParams): Promise<Page<ApplicationResponse>> {\r\n const query = this.buildListQuery(params);\r\n return this.get<Page<ApplicationResponse>>(`/applications?${query}`);\r\n }\r\n\r\n async getApplication(name: string): Promise<ApplicationResponse> {\r\n return this.get<ApplicationResponse>(`/applications/${enc(name)}`);\r\n }\r\n\r\n async registerApplication(request: RegisterApplicationRequest): Promise<ApplicationResponse> {\r\n return this.post<ApplicationResponse>(\"/applications\", request);\r\n }\r\n\r\n async updateApplication(\r\n name: string,\r\n request: UpdateApplicationRequest,\r\n ): Promise<ApplicationResponse> {\r\n return this.put<ApplicationResponse>(`/applications/${enc(name)}`, request);\r\n }\r\n\r\n async deleteApplication(name: string): Promise<void> {\r\n await this.delete(`/applications/${enc(name)}`);\r\n }\r\n\r\n async listVersions(applicationName: string): Promise<readonly string[]> {\r\n return this.get<string[]>(`/applications/${enc(applicationName)}/versions`);\r\n }\r\n\r\n // ── Contracts ─────────────────────────────────────────────────────────\r\n\r\n async listContracts(\r\n applicationName: string,\r\n version: string,\r\n params?: PageParams,\r\n ): Promise<Page<ContractResponse>> {\r\n const query = this.buildPageQuery(params);\r\n return this.get<Page<ContractResponse>>(\r\n `/applications/${enc(applicationName)}/versions/${enc(version)}/contracts?${query}`,\r\n );\r\n }\r\n\r\n async getContract(\r\n applicationName: string,\r\n version: string,\r\n contractName: string,\r\n ): Promise<ContractResponse> {\r\n return this.get<ContractResponse>(\r\n `/applications/${enc(applicationName)}/versions/${enc(version)}/contracts/${enc(contractName)}`,\r\n );\r\n }\r\n\r\n async publishContract(\r\n applicationName: string,\r\n version: string,\r\n request: PublishContractRequest,\r\n ): Promise<ContractResponse> {\r\n return this.post<ContractResponse>(\r\n `/applications/${enc(applicationName)}/versions/${enc(version)}/contracts`,\r\n request,\r\n );\r\n }\r\n\r\n async deleteContract(\r\n applicationName: string,\r\n version: string,\r\n contractName: string,\r\n ): Promise<void> {\r\n await this.delete(\r\n `/applications/${enc(applicationName)}/versions/${enc(version)}/contracts/${enc(contractName)}`,\r\n );\r\n }\r\n\r\n // ── Verifications ─────────────────────────────────────────────────────\r\n\r\n async listVerifications(params?: ListParams): Promise<Page<VerificationResponse>> {\r\n const query = this.buildListQuery(params);\r\n return this.get<Page<VerificationResponse>>(`/verifications?${query}`);\r\n }\r\n\r\n async recordVerification(request: RecordVerificationRequest): Promise<VerificationResponse> {\r\n return this.post<VerificationResponse>(\"/verifications\", request);\r\n }\r\n\r\n // ── Environments ──────────────────────────────────────────────────────\r\n\r\n async listEnvironments(): Promise<readonly EnvironmentResponse[]> {\r\n return this.get<EnvironmentResponse[]>(\"/environments\");\r\n }\r\n\r\n async getEnvironment(name: string): Promise<EnvironmentResponse> {\r\n return this.get<EnvironmentResponse>(`/environments/${enc(name)}`);\r\n }\r\n\r\n async createEnvironment(request: CreateEnvironmentRequest): Promise<EnvironmentResponse> {\r\n return this.post<EnvironmentResponse>(\"/environments\", request);\r\n }\r\n\r\n async updateEnvironment(\r\n name: string,\r\n request: UpdateEnvironmentRequest,\r\n ): Promise<EnvironmentResponse> {\r\n return this.put<EnvironmentResponse>(`/environments/${enc(name)}`, request);\r\n }\r\n\r\n async deleteEnvironment(name: string): Promise<void> {\r\n await this.delete(`/environments/${enc(name)}`);\r\n }\r\n\r\n // ── Deployments ───────────────────────────────────────────────────────\r\n\r\n async listDeployments(\r\n environment: string,\r\n params?: PageParams,\r\n ): Promise<Page<DeploymentResponse>> {\r\n const query = this.buildPageQuery(params);\r\n return this.get<Page<DeploymentResponse>>(\r\n `/environments/${enc(environment)}/deployments?${query}`,\r\n );\r\n }\r\n\r\n async getDeployment(environment: string, applicationName: string): Promise<DeploymentResponse> {\r\n return this.get<DeploymentResponse>(\r\n `/environments/${enc(environment)}/deployments/${enc(applicationName)}`,\r\n );\r\n }\r\n\r\n async recordDeployment(\r\n environment: string,\r\n request: RecordDeploymentRequest,\r\n ): Promise<DeploymentResponse> {\r\n return this.post<DeploymentResponse>(`/environments/${enc(environment)}/deployments`, request);\r\n }\r\n\r\n // ── Safety ────────────────────────────────────────────────────────────\r\n\r\n async canIDeploy(\r\n application: string,\r\n version: string,\r\n environment: string,\r\n ): Promise<CanIDeployResponse> {\r\n const params = new URLSearchParams({\r\n application,\r\n version,\r\n environment,\r\n });\r\n return this.get<CanIDeployResponse>(`/can-i-deploy?${params.toString()}`);\r\n }\r\n\r\n // ── Graph ─────────────────────────────────────────────────────────────\r\n\r\n async getDependencyGraph(environment?: string): Promise<DependencyGraphResponse> {\r\n const params = new URLSearchParams();\r\n if (environment !== undefined && environment !== \"\") {\r\n params.set(\"environment\", environment);\r\n }\r\n const qs = params.toString();\r\n return this.get<DependencyGraphResponse>(`/graph${qs !== \"\" ? `?${qs}` : \"\"}`);\r\n }\r\n\r\n async getApplicationDependencies(\r\n applicationName: string,\r\n ): Promise<ApplicationDependenciesResponse> {\r\n return this.get<ApplicationDependenciesResponse>(`/graph/applications/${enc(applicationName)}`);\r\n }\r\n\r\n // ── Webhooks ──────────────────────────────────────────────────────────\r\n\r\n async listWebhooks(params?: ListParams): Promise<Page<WebhookResponse>> {\r\n const query = this.buildListQuery(params);\r\n return this.get<Page<WebhookResponse>>(`/webhooks?${query}`);\r\n }\r\n\r\n async getWebhook(id: string): Promise<WebhookResponse> {\r\n return this.get<WebhookResponse>(`/webhooks/${enc(id)}`);\r\n }\r\n\r\n async createWebhook(request: CreateWebhookRequest): Promise<WebhookResponse> {\r\n return this.post<WebhookResponse>(\"/webhooks\", request);\r\n }\r\n\r\n async updateWebhook(id: string, request: UpdateWebhookRequest): Promise<WebhookResponse> {\r\n return this.put<WebhookResponse>(`/webhooks/${enc(id)}`, request);\r\n }\r\n\r\n async deleteWebhook(id: string): Promise<void> {\r\n await this.delete(`/webhooks/${enc(id)}`);\r\n }\r\n\r\n async listWebhookExecutions(\r\n id: string,\r\n params?: PageParams,\r\n ): Promise<Page<WebhookExecutionResponse>> {\r\n const query = this.buildPageQuery(params);\r\n return this.get<Page<WebhookExecutionResponse>>(`/webhooks/${enc(id)}/executions?${query}`);\r\n }\r\n\r\n // ── Matrix ────────────────────────────────────────────────────────────\r\n\r\n async queryMatrix(provider?: string, consumer?: string): Promise<readonly MatrixEntry[]> {\r\n const params = new URLSearchParams();\r\n if (provider !== undefined && provider !== \"\") {\r\n params.set(\"provider\", provider);\r\n }\r\n if (consumer !== undefined && consumer !== \"\") {\r\n params.set(\"consumer\", consumer);\r\n }\r\n const qs = params.toString();\r\n return this.get<MatrixEntry[]>(`/matrix${qs !== \"\" ? `?${qs}` : \"\"}`);\r\n }\r\n\r\n // ── Selectors ─────────────────────────────────────────────────────────\r\n\r\n async resolveSelectors(\r\n selectors: readonly ConsumerVersionSelector[],\r\n ): Promise<readonly ResolvedContract[]> {\r\n return this.post<ResolvedContract[]>(\"/selectors/resolve\", { selectors });\r\n }\r\n\r\n // ── Tags ──────────────────────────────────────────────────────────────\r\n\r\n async listTags(applicationName: string, version: string): Promise<readonly TagResponse[]> {\r\n return this.get<TagResponse[]>(\r\n `/applications/${enc(applicationName)}/versions/${enc(version)}/tags`,\r\n );\r\n }\r\n\r\n async addTag(applicationName: string, version: string, tag: string): Promise<TagResponse> {\r\n return this.put<TagResponse>(\r\n `/applications/${enc(applicationName)}/versions/${enc(version)}/tags/${enc(tag)}`,\r\n );\r\n }\r\n\r\n async removeTag(applicationName: string, version: string, tag: string): Promise<void> {\r\n await this.delete(\r\n `/applications/${enc(applicationName)}/versions/${enc(version)}/tags/${enc(tag)}`,\r\n );\r\n }\r\n\r\n async getLatestVersionByTag(applicationName: string, tag: string): Promise<{ version: string }> {\r\n return this.get<{ version: string }>(\r\n `/applications/${enc(applicationName)}/versions/latest?tag=${enc(tag)}`,\r\n );\r\n }\r\n\r\n // ── Maintenance ───────────────────────────────────────────────────────\r\n\r\n async runCleanup(request: CleanupRequest): Promise<CleanupResult> {\r\n return this.post<CleanupResult>(\"/maintenance/cleanup\", request);\r\n }\r\n\r\n // ── HTTP helpers ──────────────────────────────────────────────────────\r\n\r\n private async get<T>(path: string): Promise<T> {\r\n return this.request<T>(\"GET\", path);\r\n }\r\n\r\n private async post<T>(path: string, body?: unknown): Promise<T> {\r\n return this.request<T>(\"POST\", path, body);\r\n }\r\n\r\n private async put<T>(path: string, body?: unknown): Promise<T> {\r\n return this.request<T>(\"PUT\", path, body);\r\n }\r\n\r\n private async delete(path: string): Promise<void> {\r\n await this.requestRaw(\"DELETE\", path);\r\n }\r\n\r\n private async request<T>(method: string, path: string, body?: unknown): Promise<T> {\r\n const response = await this.requestRaw(method, path, body);\r\n return (await response.json()) as T;\r\n }\r\n\r\n private async requestRaw(method: string, path: string, body?: unknown): Promise<Response> {\r\n const url = `${this.baseUrl}${API_PREFIX}${path}`;\r\n const headers: Record<string, string> = {};\r\n\r\n const auth = buildAuthHeader(this.config);\r\n if (auth !== undefined) {\r\n headers[\"Authorization\"] = auth;\r\n }\r\n\r\n if (body !== undefined) {\r\n headers[\"Content-Type\"] = \"application/json\";\r\n }\r\n\r\n let response: Response;\r\n const init: RequestInit = { method, headers, signal: AbortSignal.timeout(this.timeoutMs) };\r\n if (body !== undefined) {\r\n init.body = JSON.stringify(body);\r\n }\r\n try {\r\n response = await this.fetchFn(url, init);\r\n } catch (err: unknown) {\r\n throw new BrokerConnectionError(\r\n `Failed to connect to broker at ${this.baseUrl}: ${err instanceof Error ? err.message : String(err)}`,\r\n err,\r\n );\r\n }\r\n\r\n if (response.ok) {\r\n return response;\r\n }\r\n\r\n let errorResponse: ErrorResponse | null = null;\r\n try {\r\n errorResponse = (await response.json()) as ErrorResponse;\r\n } catch {\r\n // response body is not JSON — leave errorResponse as null\r\n }\r\n\r\n const message =\r\n errorResponse?.message ?? `${method} ${path} failed with status ${String(response.status)}`;\r\n\r\n switch (response.status) {\r\n case 400:\r\n throw new BrokerValidationError(message, errorResponse);\r\n case 401:\r\n throw new BrokerAuthError(message, errorResponse);\r\n case 403:\r\n throw new BrokerForbiddenError(message, errorResponse);\r\n case 404:\r\n throw new BrokerNotFoundError(message, errorResponse);\r\n case 409:\r\n throw new BrokerConflictError(message, errorResponse);\r\n default:\r\n throw new BrokerApiError(response.status, message, errorResponse);\r\n }\r\n }\r\n\r\n private buildPageQuery(params?: PageParams): string {\r\n const urlParams = new URLSearchParams();\r\n urlParams.set(\"page\", String(params?.page ?? 0));\r\n urlParams.set(\"size\", String(params?.size ?? this.defaultPageSize));\r\n if (params?.sort !== undefined && params.sort !== \"\") {\r\n urlParams.set(\"sort\", params.sort);\r\n }\r\n return urlParams.toString();\r\n }\r\n\r\n private buildListQuery(params?: ListParams): string {\r\n const urlParams = new URLSearchParams();\r\n urlParams.set(\"page\", String(params?.page ?? 0));\r\n urlParams.set(\"size\", String(params?.size ?? this.defaultPageSize));\r\n if (params?.sort !== undefined && params.sort !== \"\") {\r\n urlParams.set(\"sort\", params.sort);\r\n }\r\n if (params?.search !== undefined && params.search !== \"\") {\r\n urlParams.set(\"search\", params.search);\r\n }\r\n return urlParams.toString();\r\n }\r\n}\r\n\r\nfunction enc(value: string): string {\r\n return encodeURIComponent(value);\r\n}\r\n","import type { Page, PageParams } from \"./types.js\";\r\n\r\n/** Maximum number of pages to fetch to prevent infinite loops. */\r\nconst MAX_PAGES = 1000;\r\n\r\n/** Async iterator that fetches all pages from a paginated endpoint. */\r\nexport async function* pageIterator<T>(\r\n fetcher: (params: PageParams) => Promise<Page<T>>,\r\n params: PageParams = {},\r\n): AsyncGenerator<T, void, undefined> {\r\n let currentPage = params.page ?? 0;\r\n const size = params.size ?? 20;\r\n let hasMore = true;\r\n let pagesRead = 0;\r\n\r\n while (hasMore) {\r\n if (pagesRead >= MAX_PAGES) {\r\n throw new Error(`Exceeded maximum page limit (${String(MAX_PAGES)})`);\r\n }\r\n const page = await fetcher({ ...params, page: currentPage, size });\r\n for (const item of page.content) {\r\n yield item;\r\n }\r\n currentPage++;\r\n pagesRead++;\r\n hasMore = currentPage < page.totalPages;\r\n }\r\n}\r\n\r\n/** Collect all items from all pages into a single array. */\r\nexport async function fetchAllPages<T>(\r\n fetcher: (params: PageParams) => Promise<Page<T>>,\r\n params: PageParams = {},\r\n): Promise<readonly T[]> {\r\n const items: T[] = [];\r\n for await (const item of pageIterator(fetcher, params)) {\r\n items.push(item);\r\n }\r\n return items;\r\n}\r\n"],"mappings":"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","names":[]}
package/dist/index.js ADDED
@@ -0,0 +1,389 @@
1
+ // src/config.ts
2
+ var DEFAULT_PAGE_SIZE = 20;
3
+ var DEFAULT_TIMEOUT_MS = 3e4;
4
+ function resolveConfig(config) {
5
+ const baseUrl = config.baseUrl.replace(/\/+$/, "");
6
+ if (!/^https?:\/\//i.test(baseUrl)) {
7
+ throw new Error(`Invalid baseUrl scheme: "${baseUrl}". Must start with http:// or https://`);
8
+ }
9
+ return {
10
+ ...config,
11
+ baseUrl,
12
+ defaultPageSize: config.defaultPageSize !== void 0 && config.defaultPageSize > 0 ? config.defaultPageSize : DEFAULT_PAGE_SIZE,
13
+ timeoutMs: config.timeoutMs !== void 0 && config.timeoutMs > 0 ? config.timeoutMs : DEFAULT_TIMEOUT_MS
14
+ };
15
+ }
16
+ function buildAuthHeader(config) {
17
+ if (config.token !== void 0 && config.token !== "") {
18
+ return `Bearer ${config.token}`;
19
+ }
20
+ if (config.username !== void 0 && config.username !== "") {
21
+ const encoded = Buffer.from(`${config.username}:${config.password ?? ""}`).toString("base64");
22
+ return `Basic ${encoded}`;
23
+ }
24
+ return void 0;
25
+ }
26
+
27
+ // src/errors.ts
28
+ var BrokerApiError = class extends Error {
29
+ status;
30
+ errorResponse;
31
+ constructor(status, message, errorResponse = null) {
32
+ super(message);
33
+ this.name = "BrokerApiError";
34
+ this.status = status;
35
+ this.errorResponse = errorResponse;
36
+ }
37
+ };
38
+ var BrokerAuthError = class extends BrokerApiError {
39
+ constructor(message = "Authentication failed", errorResponse = null) {
40
+ super(401, message, errorResponse);
41
+ this.name = "BrokerAuthError";
42
+ }
43
+ };
44
+ var BrokerForbiddenError = class extends BrokerApiError {
45
+ constructor(message = "Insufficient permissions", errorResponse = null) {
46
+ super(403, message, errorResponse);
47
+ this.name = "BrokerForbiddenError";
48
+ }
49
+ };
50
+ var BrokerNotFoundError = class extends BrokerApiError {
51
+ constructor(message = "Resource not found", errorResponse = null) {
52
+ super(404, message, errorResponse);
53
+ this.name = "BrokerNotFoundError";
54
+ }
55
+ };
56
+ var BrokerConflictError = class extends BrokerApiError {
57
+ constructor(message = "Resource already exists", errorResponse = null) {
58
+ super(409, message, errorResponse);
59
+ this.name = "BrokerConflictError";
60
+ }
61
+ };
62
+ var BrokerValidationError = class extends BrokerApiError {
63
+ constructor(message = "Validation failed", errorResponse = null) {
64
+ super(400, message, errorResponse);
65
+ this.name = "BrokerValidationError";
66
+ }
67
+ };
68
+ var BrokerConnectionError = class extends Error {
69
+ cause;
70
+ constructor(message, cause) {
71
+ super(message);
72
+ this.name = "BrokerConnectionError";
73
+ this.cause = cause;
74
+ }
75
+ };
76
+
77
+ // src/client.ts
78
+ var API_PREFIX = "/api/v1";
79
+ var BrokerClient = class {
80
+ baseUrl;
81
+ config;
82
+ fetchFn;
83
+ defaultPageSize;
84
+ timeoutMs;
85
+ constructor(config) {
86
+ const resolved = resolveConfig(config);
87
+ this.baseUrl = resolved.baseUrl;
88
+ this.config = resolved;
89
+ this.fetchFn = config.fetch ?? globalThis.fetch.bind(globalThis);
90
+ this.defaultPageSize = resolved.defaultPageSize;
91
+ this.timeoutMs = resolved.timeoutMs;
92
+ }
93
+ // ── Applications ──────────────────────────────────────────────────────
94
+ async listApplications(params) {
95
+ const query = this.buildListQuery(params);
96
+ return this.get(`/applications?${query}`);
97
+ }
98
+ async getApplication(name) {
99
+ return this.get(`/applications/${enc(name)}`);
100
+ }
101
+ async registerApplication(request) {
102
+ return this.post("/applications", request);
103
+ }
104
+ async updateApplication(name, request) {
105
+ return this.put(`/applications/${enc(name)}`, request);
106
+ }
107
+ async deleteApplication(name) {
108
+ await this.delete(`/applications/${enc(name)}`);
109
+ }
110
+ async listVersions(applicationName) {
111
+ return this.get(`/applications/${enc(applicationName)}/versions`);
112
+ }
113
+ // ── Contracts ─────────────────────────────────────────────────────────
114
+ async listContracts(applicationName, version, params) {
115
+ const query = this.buildPageQuery(params);
116
+ return this.get(
117
+ `/applications/${enc(applicationName)}/versions/${enc(version)}/contracts?${query}`
118
+ );
119
+ }
120
+ async getContract(applicationName, version, contractName) {
121
+ return this.get(
122
+ `/applications/${enc(applicationName)}/versions/${enc(version)}/contracts/${enc(contractName)}`
123
+ );
124
+ }
125
+ async publishContract(applicationName, version, request) {
126
+ return this.post(
127
+ `/applications/${enc(applicationName)}/versions/${enc(version)}/contracts`,
128
+ request
129
+ );
130
+ }
131
+ async deleteContract(applicationName, version, contractName) {
132
+ await this.delete(
133
+ `/applications/${enc(applicationName)}/versions/${enc(version)}/contracts/${enc(contractName)}`
134
+ );
135
+ }
136
+ // ── Verifications ─────────────────────────────────────────────────────
137
+ async listVerifications(params) {
138
+ const query = this.buildListQuery(params);
139
+ return this.get(`/verifications?${query}`);
140
+ }
141
+ async recordVerification(request) {
142
+ return this.post("/verifications", request);
143
+ }
144
+ // ── Environments ──────────────────────────────────────────────────────
145
+ async listEnvironments() {
146
+ return this.get("/environments");
147
+ }
148
+ async getEnvironment(name) {
149
+ return this.get(`/environments/${enc(name)}`);
150
+ }
151
+ async createEnvironment(request) {
152
+ return this.post("/environments", request);
153
+ }
154
+ async updateEnvironment(name, request) {
155
+ return this.put(`/environments/${enc(name)}`, request);
156
+ }
157
+ async deleteEnvironment(name) {
158
+ await this.delete(`/environments/${enc(name)}`);
159
+ }
160
+ // ── Deployments ───────────────────────────────────────────────────────
161
+ async listDeployments(environment, params) {
162
+ const query = this.buildPageQuery(params);
163
+ return this.get(
164
+ `/environments/${enc(environment)}/deployments?${query}`
165
+ );
166
+ }
167
+ async getDeployment(environment, applicationName) {
168
+ return this.get(
169
+ `/environments/${enc(environment)}/deployments/${enc(applicationName)}`
170
+ );
171
+ }
172
+ async recordDeployment(environment, request) {
173
+ return this.post(`/environments/${enc(environment)}/deployments`, request);
174
+ }
175
+ // ── Safety ────────────────────────────────────────────────────────────
176
+ async canIDeploy(application, version, environment) {
177
+ const params = new URLSearchParams({
178
+ application,
179
+ version,
180
+ environment
181
+ });
182
+ return this.get(`/can-i-deploy?${params.toString()}`);
183
+ }
184
+ // ── Graph ─────────────────────────────────────────────────────────────
185
+ async getDependencyGraph(environment) {
186
+ const params = new URLSearchParams();
187
+ if (environment !== void 0 && environment !== "") {
188
+ params.set("environment", environment);
189
+ }
190
+ const qs = params.toString();
191
+ return this.get(`/graph${qs !== "" ? `?${qs}` : ""}`);
192
+ }
193
+ async getApplicationDependencies(applicationName) {
194
+ return this.get(`/graph/applications/${enc(applicationName)}`);
195
+ }
196
+ // ── Webhooks ──────────────────────────────────────────────────────────
197
+ async listWebhooks(params) {
198
+ const query = this.buildListQuery(params);
199
+ return this.get(`/webhooks?${query}`);
200
+ }
201
+ async getWebhook(id) {
202
+ return this.get(`/webhooks/${enc(id)}`);
203
+ }
204
+ async createWebhook(request) {
205
+ return this.post("/webhooks", request);
206
+ }
207
+ async updateWebhook(id, request) {
208
+ return this.put(`/webhooks/${enc(id)}`, request);
209
+ }
210
+ async deleteWebhook(id) {
211
+ await this.delete(`/webhooks/${enc(id)}`);
212
+ }
213
+ async listWebhookExecutions(id, params) {
214
+ const query = this.buildPageQuery(params);
215
+ return this.get(`/webhooks/${enc(id)}/executions?${query}`);
216
+ }
217
+ // ── Matrix ────────────────────────────────────────────────────────────
218
+ async queryMatrix(provider, consumer) {
219
+ const params = new URLSearchParams();
220
+ if (provider !== void 0 && provider !== "") {
221
+ params.set("provider", provider);
222
+ }
223
+ if (consumer !== void 0 && consumer !== "") {
224
+ params.set("consumer", consumer);
225
+ }
226
+ const qs = params.toString();
227
+ return this.get(`/matrix${qs !== "" ? `?${qs}` : ""}`);
228
+ }
229
+ // ── Selectors ─────────────────────────────────────────────────────────
230
+ async resolveSelectors(selectors) {
231
+ return this.post("/selectors/resolve", { selectors });
232
+ }
233
+ // ── Tags ──────────────────────────────────────────────────────────────
234
+ async listTags(applicationName, version) {
235
+ return this.get(
236
+ `/applications/${enc(applicationName)}/versions/${enc(version)}/tags`
237
+ );
238
+ }
239
+ async addTag(applicationName, version, tag) {
240
+ return this.put(
241
+ `/applications/${enc(applicationName)}/versions/${enc(version)}/tags/${enc(tag)}`
242
+ );
243
+ }
244
+ async removeTag(applicationName, version, tag) {
245
+ await this.delete(
246
+ `/applications/${enc(applicationName)}/versions/${enc(version)}/tags/${enc(tag)}`
247
+ );
248
+ }
249
+ async getLatestVersionByTag(applicationName, tag) {
250
+ return this.get(
251
+ `/applications/${enc(applicationName)}/versions/latest?tag=${enc(tag)}`
252
+ );
253
+ }
254
+ // ── Maintenance ───────────────────────────────────────────────────────
255
+ async runCleanup(request) {
256
+ return this.post("/maintenance/cleanup", request);
257
+ }
258
+ // ── HTTP helpers ──────────────────────────────────────────────────────
259
+ async get(path) {
260
+ return this.request("GET", path);
261
+ }
262
+ async post(path, body) {
263
+ return this.request("POST", path, body);
264
+ }
265
+ async put(path, body) {
266
+ return this.request("PUT", path, body);
267
+ }
268
+ async delete(path) {
269
+ await this.requestRaw("DELETE", path);
270
+ }
271
+ async request(method, path, body) {
272
+ const response = await this.requestRaw(method, path, body);
273
+ return await response.json();
274
+ }
275
+ async requestRaw(method, path, body) {
276
+ const url = `${this.baseUrl}${API_PREFIX}${path}`;
277
+ const headers = {};
278
+ const auth = buildAuthHeader(this.config);
279
+ if (auth !== void 0) {
280
+ headers["Authorization"] = auth;
281
+ }
282
+ if (body !== void 0) {
283
+ headers["Content-Type"] = "application/json";
284
+ }
285
+ let response;
286
+ const init = { method, headers, signal: AbortSignal.timeout(this.timeoutMs) };
287
+ if (body !== void 0) {
288
+ init.body = JSON.stringify(body);
289
+ }
290
+ try {
291
+ response = await this.fetchFn(url, init);
292
+ } catch (err) {
293
+ throw new BrokerConnectionError(
294
+ `Failed to connect to broker at ${this.baseUrl}: ${err instanceof Error ? err.message : String(err)}`,
295
+ err
296
+ );
297
+ }
298
+ if (response.ok) {
299
+ return response;
300
+ }
301
+ let errorResponse = null;
302
+ try {
303
+ errorResponse = await response.json();
304
+ } catch {
305
+ }
306
+ const message = errorResponse?.message ?? `${method} ${path} failed with status ${String(response.status)}`;
307
+ switch (response.status) {
308
+ case 400:
309
+ throw new BrokerValidationError(message, errorResponse);
310
+ case 401:
311
+ throw new BrokerAuthError(message, errorResponse);
312
+ case 403:
313
+ throw new BrokerForbiddenError(message, errorResponse);
314
+ case 404:
315
+ throw new BrokerNotFoundError(message, errorResponse);
316
+ case 409:
317
+ throw new BrokerConflictError(message, errorResponse);
318
+ default:
319
+ throw new BrokerApiError(response.status, message, errorResponse);
320
+ }
321
+ }
322
+ buildPageQuery(params) {
323
+ const urlParams = new URLSearchParams();
324
+ urlParams.set("page", String(params?.page ?? 0));
325
+ urlParams.set("size", String(params?.size ?? this.defaultPageSize));
326
+ if (params?.sort !== void 0 && params.sort !== "") {
327
+ urlParams.set("sort", params.sort);
328
+ }
329
+ return urlParams.toString();
330
+ }
331
+ buildListQuery(params) {
332
+ const urlParams = new URLSearchParams();
333
+ urlParams.set("page", String(params?.page ?? 0));
334
+ urlParams.set("size", String(params?.size ?? this.defaultPageSize));
335
+ if (params?.sort !== void 0 && params.sort !== "") {
336
+ urlParams.set("sort", params.sort);
337
+ }
338
+ if (params?.search !== void 0 && params.search !== "") {
339
+ urlParams.set("search", params.search);
340
+ }
341
+ return urlParams.toString();
342
+ }
343
+ };
344
+ function enc(value) {
345
+ return encodeURIComponent(value);
346
+ }
347
+
348
+ // src/pagination.ts
349
+ var MAX_PAGES = 1e3;
350
+ async function* pageIterator(fetcher, params = {}) {
351
+ let currentPage = params.page ?? 0;
352
+ const size = params.size ?? 20;
353
+ let hasMore = true;
354
+ let pagesRead = 0;
355
+ while (hasMore) {
356
+ if (pagesRead >= MAX_PAGES) {
357
+ throw new Error(`Exceeded maximum page limit (${String(MAX_PAGES)})`);
358
+ }
359
+ const page = await fetcher({ ...params, page: currentPage, size });
360
+ for (const item of page.content) {
361
+ yield item;
362
+ }
363
+ currentPage++;
364
+ pagesRead++;
365
+ hasMore = currentPage < page.totalPages;
366
+ }
367
+ }
368
+ async function fetchAllPages(fetcher, params = {}) {
369
+ const items = [];
370
+ for await (const item of pageIterator(fetcher, params)) {
371
+ items.push(item);
372
+ }
373
+ return items;
374
+ }
375
+ export {
376
+ BrokerApiError,
377
+ BrokerAuthError,
378
+ BrokerClient,
379
+ BrokerConflictError,
380
+ BrokerConnectionError,
381
+ BrokerForbiddenError,
382
+ BrokerNotFoundError,
383
+ BrokerValidationError,
384
+ buildAuthHeader,
385
+ fetchAllPages,
386
+ pageIterator,
387
+ resolveConfig
388
+ };
389
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/config.ts","../src/errors.ts","../src/client.ts","../src/pagination.ts"],"sourcesContent":["/** Configuration for the BrokerClient. */\r\nexport interface BrokerClientConfig {\r\n /** Base URL of the broker API (e.g., \"http://localhost:8080\"). */\r\n readonly baseUrl: string;\r\n\r\n /** Username for basic auth (optional). */\r\n readonly username?: string;\r\n\r\n /** Password for basic auth (optional). */\r\n readonly password?: string;\r\n\r\n /** Bearer token for JWT auth (optional, takes precedence over basic auth). */\r\n readonly token?: string;\r\n\r\n /** Custom fetch implementation (defaults to global fetch). */\r\n readonly fetch?: typeof globalThis.fetch;\r\n\r\n /** Default page size for paginated requests. */\r\n readonly defaultPageSize?: number;\r\n\r\n /** Request timeout in milliseconds (default: 30000). */\r\n readonly timeoutMs?: number;\r\n}\r\n\r\nconst DEFAULT_PAGE_SIZE = 20;\r\nconst DEFAULT_TIMEOUT_MS = 30_000;\r\n\r\n/** Resolve a BrokerClientConfig with defaults applied. */\r\nexport function resolveConfig(\r\n config: BrokerClientConfig,\r\n): Required<Pick<BrokerClientConfig, \"baseUrl\" | \"defaultPageSize\" | \"timeoutMs\">> &\r\n BrokerClientConfig {\r\n const baseUrl = config.baseUrl.replace(/\\/+$/, \"\");\r\n if (!/^https?:\\/\\//i.test(baseUrl)) {\r\n throw new Error(`Invalid baseUrl scheme: \"${baseUrl}\". Must start with http:// or https://`);\r\n }\r\n return {\r\n ...config,\r\n baseUrl,\r\n defaultPageSize:\r\n config.defaultPageSize !== undefined && config.defaultPageSize > 0\r\n ? config.defaultPageSize\r\n : DEFAULT_PAGE_SIZE,\r\n timeoutMs:\r\n config.timeoutMs !== undefined && config.timeoutMs > 0\r\n ? config.timeoutMs\r\n : DEFAULT_TIMEOUT_MS,\r\n };\r\n}\r\n\r\n/** Build the Authorization header value from config. */\r\nexport function buildAuthHeader(config: BrokerClientConfig): string | undefined {\r\n if (config.token !== undefined && config.token !== \"\") {\r\n return `Bearer ${config.token}`;\r\n }\r\n if (config.username !== undefined && config.username !== \"\") {\r\n const encoded = Buffer.from(`${config.username}:${config.password ?? \"\"}`).toString(\"base64\");\r\n return `Basic ${encoded}`;\r\n }\r\n return undefined;\r\n}\r\n","import type { ErrorResponse } from \"./types.js\";\r\n\r\n/** Base error for all broker API errors. */\r\nexport class BrokerApiError extends Error {\r\n readonly status: number;\r\n readonly errorResponse: ErrorResponse | null;\r\n\r\n constructor(status: number, message: string, errorResponse: ErrorResponse | null = null) {\r\n super(message);\r\n this.name = \"BrokerApiError\";\r\n this.status = status;\r\n this.errorResponse = errorResponse;\r\n }\r\n}\r\n\r\n/** 401 Unauthorized — invalid or missing credentials. */\r\nexport class BrokerAuthError extends BrokerApiError {\r\n constructor(\r\n message: string = \"Authentication failed\",\r\n errorResponse: ErrorResponse | null = null,\r\n ) {\r\n super(401, message, errorResponse);\r\n this.name = \"BrokerAuthError\";\r\n }\r\n}\r\n\r\n/** 403 Forbidden — insufficient permissions. */\r\nexport class BrokerForbiddenError extends BrokerApiError {\r\n constructor(\r\n message: string = \"Insufficient permissions\",\r\n errorResponse: ErrorResponse | null = null,\r\n ) {\r\n super(403, message, errorResponse);\r\n this.name = \"BrokerForbiddenError\";\r\n }\r\n}\r\n\r\n/** 404 Not Found — requested resource does not exist. */\r\nexport class BrokerNotFoundError extends BrokerApiError {\r\n constructor(message: string = \"Resource not found\", errorResponse: ErrorResponse | null = null) {\r\n super(404, message, errorResponse);\r\n this.name = \"BrokerNotFoundError\";\r\n }\r\n}\r\n\r\n/** 409 Conflict — resource already exists. */\r\nexport class BrokerConflictError extends BrokerApiError {\r\n constructor(\r\n message: string = \"Resource already exists\",\r\n errorResponse: ErrorResponse | null = null,\r\n ) {\r\n super(409, message, errorResponse);\r\n this.name = \"BrokerConflictError\";\r\n }\r\n}\r\n\r\n/** 400 Bad Request — validation error. */\r\nexport class BrokerValidationError extends BrokerApiError {\r\n constructor(message: string = \"Validation failed\", errorResponse: ErrorResponse | null = null) {\r\n super(400, message, errorResponse);\r\n this.name = \"BrokerValidationError\";\r\n }\r\n}\r\n\r\n/** Network or connection error. */\r\nexport class BrokerConnectionError extends Error {\r\n readonly cause: unknown;\r\n\r\n constructor(message: string, cause: unknown) {\r\n super(message);\r\n this.name = \"BrokerConnectionError\";\r\n this.cause = cause;\r\n }\r\n}\r\n","import type {\r\n ApplicationResponse,\r\n RegisterApplicationRequest,\r\n UpdateApplicationRequest,\r\n ContractResponse,\r\n PublishContractRequest,\r\n VerificationResponse,\r\n RecordVerificationRequest,\r\n EnvironmentResponse,\r\n CreateEnvironmentRequest,\r\n UpdateEnvironmentRequest,\r\n DeploymentResponse,\r\n RecordDeploymentRequest,\r\n CanIDeployResponse,\r\n DependencyGraphResponse,\r\n ApplicationDependenciesResponse,\r\n WebhookResponse,\r\n CreateWebhookRequest,\r\n UpdateWebhookRequest,\r\n WebhookExecutionResponse,\r\n MatrixEntry,\r\n ConsumerVersionSelector,\r\n ResolvedContract,\r\n TagResponse,\r\n CleanupRequest,\r\n CleanupResult,\r\n Page,\r\n PageParams,\r\n ListParams,\r\n ErrorResponse,\r\n} from \"./types.js\";\r\nimport type { BrokerClientConfig } from \"./config.js\";\r\nimport { resolveConfig, buildAuthHeader } from \"./config.js\";\r\nimport {\r\n BrokerApiError,\r\n BrokerAuthError,\r\n BrokerForbiddenError,\r\n BrokerNotFoundError,\r\n BrokerConflictError,\r\n BrokerValidationError,\r\n BrokerConnectionError,\r\n} from \"./errors.js\";\r\n\r\nconst API_PREFIX = \"/api/v1\";\r\n\r\nexport class BrokerClient {\r\n private readonly baseUrl: string;\r\n private readonly config: BrokerClientConfig;\r\n private readonly fetchFn: typeof globalThis.fetch;\r\n private readonly defaultPageSize: number;\r\n private readonly timeoutMs: number;\r\n\r\n constructor(config: BrokerClientConfig) {\r\n const resolved = resolveConfig(config);\r\n this.baseUrl = resolved.baseUrl;\r\n this.config = resolved;\r\n this.fetchFn = config.fetch ?? globalThis.fetch.bind(globalThis);\r\n this.defaultPageSize = resolved.defaultPageSize;\r\n this.timeoutMs = resolved.timeoutMs;\r\n }\r\n\r\n // ── Applications ──────────────────────────────────────────────────────\r\n\r\n async listApplications(params?: ListParams): Promise<Page<ApplicationResponse>> {\r\n const query = this.buildListQuery(params);\r\n return this.get<Page<ApplicationResponse>>(`/applications?${query}`);\r\n }\r\n\r\n async getApplication(name: string): Promise<ApplicationResponse> {\r\n return this.get<ApplicationResponse>(`/applications/${enc(name)}`);\r\n }\r\n\r\n async registerApplication(request: RegisterApplicationRequest): Promise<ApplicationResponse> {\r\n return this.post<ApplicationResponse>(\"/applications\", request);\r\n }\r\n\r\n async updateApplication(\r\n name: string,\r\n request: UpdateApplicationRequest,\r\n ): Promise<ApplicationResponse> {\r\n return this.put<ApplicationResponse>(`/applications/${enc(name)}`, request);\r\n }\r\n\r\n async deleteApplication(name: string): Promise<void> {\r\n await this.delete(`/applications/${enc(name)}`);\r\n }\r\n\r\n async listVersions(applicationName: string): Promise<readonly string[]> {\r\n return this.get<string[]>(`/applications/${enc(applicationName)}/versions`);\r\n }\r\n\r\n // ── Contracts ─────────────────────────────────────────────────────────\r\n\r\n async listContracts(\r\n applicationName: string,\r\n version: string,\r\n params?: PageParams,\r\n ): Promise<Page<ContractResponse>> {\r\n const query = this.buildPageQuery(params);\r\n return this.get<Page<ContractResponse>>(\r\n `/applications/${enc(applicationName)}/versions/${enc(version)}/contracts?${query}`,\r\n );\r\n }\r\n\r\n async getContract(\r\n applicationName: string,\r\n version: string,\r\n contractName: string,\r\n ): Promise<ContractResponse> {\r\n return this.get<ContractResponse>(\r\n `/applications/${enc(applicationName)}/versions/${enc(version)}/contracts/${enc(contractName)}`,\r\n );\r\n }\r\n\r\n async publishContract(\r\n applicationName: string,\r\n version: string,\r\n request: PublishContractRequest,\r\n ): Promise<ContractResponse> {\r\n return this.post<ContractResponse>(\r\n `/applications/${enc(applicationName)}/versions/${enc(version)}/contracts`,\r\n request,\r\n );\r\n }\r\n\r\n async deleteContract(\r\n applicationName: string,\r\n version: string,\r\n contractName: string,\r\n ): Promise<void> {\r\n await this.delete(\r\n `/applications/${enc(applicationName)}/versions/${enc(version)}/contracts/${enc(contractName)}`,\r\n );\r\n }\r\n\r\n // ── Verifications ─────────────────────────────────────────────────────\r\n\r\n async listVerifications(params?: ListParams): Promise<Page<VerificationResponse>> {\r\n const query = this.buildListQuery(params);\r\n return this.get<Page<VerificationResponse>>(`/verifications?${query}`);\r\n }\r\n\r\n async recordVerification(request: RecordVerificationRequest): Promise<VerificationResponse> {\r\n return this.post<VerificationResponse>(\"/verifications\", request);\r\n }\r\n\r\n // ── Environments ──────────────────────────────────────────────────────\r\n\r\n async listEnvironments(): Promise<readonly EnvironmentResponse[]> {\r\n return this.get<EnvironmentResponse[]>(\"/environments\");\r\n }\r\n\r\n async getEnvironment(name: string): Promise<EnvironmentResponse> {\r\n return this.get<EnvironmentResponse>(`/environments/${enc(name)}`);\r\n }\r\n\r\n async createEnvironment(request: CreateEnvironmentRequest): Promise<EnvironmentResponse> {\r\n return this.post<EnvironmentResponse>(\"/environments\", request);\r\n }\r\n\r\n async updateEnvironment(\r\n name: string,\r\n request: UpdateEnvironmentRequest,\r\n ): Promise<EnvironmentResponse> {\r\n return this.put<EnvironmentResponse>(`/environments/${enc(name)}`, request);\r\n }\r\n\r\n async deleteEnvironment(name: string): Promise<void> {\r\n await this.delete(`/environments/${enc(name)}`);\r\n }\r\n\r\n // ── Deployments ───────────────────────────────────────────────────────\r\n\r\n async listDeployments(\r\n environment: string,\r\n params?: PageParams,\r\n ): Promise<Page<DeploymentResponse>> {\r\n const query = this.buildPageQuery(params);\r\n return this.get<Page<DeploymentResponse>>(\r\n `/environments/${enc(environment)}/deployments?${query}`,\r\n );\r\n }\r\n\r\n async getDeployment(environment: string, applicationName: string): Promise<DeploymentResponse> {\r\n return this.get<DeploymentResponse>(\r\n `/environments/${enc(environment)}/deployments/${enc(applicationName)}`,\r\n );\r\n }\r\n\r\n async recordDeployment(\r\n environment: string,\r\n request: RecordDeploymentRequest,\r\n ): Promise<DeploymentResponse> {\r\n return this.post<DeploymentResponse>(`/environments/${enc(environment)}/deployments`, request);\r\n }\r\n\r\n // ── Safety ────────────────────────────────────────────────────────────\r\n\r\n async canIDeploy(\r\n application: string,\r\n version: string,\r\n environment: string,\r\n ): Promise<CanIDeployResponse> {\r\n const params = new URLSearchParams({\r\n application,\r\n version,\r\n environment,\r\n });\r\n return this.get<CanIDeployResponse>(`/can-i-deploy?${params.toString()}`);\r\n }\r\n\r\n // ── Graph ─────────────────────────────────────────────────────────────\r\n\r\n async getDependencyGraph(environment?: string): Promise<DependencyGraphResponse> {\r\n const params = new URLSearchParams();\r\n if (environment !== undefined && environment !== \"\") {\r\n params.set(\"environment\", environment);\r\n }\r\n const qs = params.toString();\r\n return this.get<DependencyGraphResponse>(`/graph${qs !== \"\" ? `?${qs}` : \"\"}`);\r\n }\r\n\r\n async getApplicationDependencies(\r\n applicationName: string,\r\n ): Promise<ApplicationDependenciesResponse> {\r\n return this.get<ApplicationDependenciesResponse>(`/graph/applications/${enc(applicationName)}`);\r\n }\r\n\r\n // ── Webhooks ──────────────────────────────────────────────────────────\r\n\r\n async listWebhooks(params?: ListParams): Promise<Page<WebhookResponse>> {\r\n const query = this.buildListQuery(params);\r\n return this.get<Page<WebhookResponse>>(`/webhooks?${query}`);\r\n }\r\n\r\n async getWebhook(id: string): Promise<WebhookResponse> {\r\n return this.get<WebhookResponse>(`/webhooks/${enc(id)}`);\r\n }\r\n\r\n async createWebhook(request: CreateWebhookRequest): Promise<WebhookResponse> {\r\n return this.post<WebhookResponse>(\"/webhooks\", request);\r\n }\r\n\r\n async updateWebhook(id: string, request: UpdateWebhookRequest): Promise<WebhookResponse> {\r\n return this.put<WebhookResponse>(`/webhooks/${enc(id)}`, request);\r\n }\r\n\r\n async deleteWebhook(id: string): Promise<void> {\r\n await this.delete(`/webhooks/${enc(id)}`);\r\n }\r\n\r\n async listWebhookExecutions(\r\n id: string,\r\n params?: PageParams,\r\n ): Promise<Page<WebhookExecutionResponse>> {\r\n const query = this.buildPageQuery(params);\r\n return this.get<Page<WebhookExecutionResponse>>(`/webhooks/${enc(id)}/executions?${query}`);\r\n }\r\n\r\n // ── Matrix ────────────────────────────────────────────────────────────\r\n\r\n async queryMatrix(provider?: string, consumer?: string): Promise<readonly MatrixEntry[]> {\r\n const params = new URLSearchParams();\r\n if (provider !== undefined && provider !== \"\") {\r\n params.set(\"provider\", provider);\r\n }\r\n if (consumer !== undefined && consumer !== \"\") {\r\n params.set(\"consumer\", consumer);\r\n }\r\n const qs = params.toString();\r\n return this.get<MatrixEntry[]>(`/matrix${qs !== \"\" ? `?${qs}` : \"\"}`);\r\n }\r\n\r\n // ── Selectors ─────────────────────────────────────────────────────────\r\n\r\n async resolveSelectors(\r\n selectors: readonly ConsumerVersionSelector[],\r\n ): Promise<readonly ResolvedContract[]> {\r\n return this.post<ResolvedContract[]>(\"/selectors/resolve\", { selectors });\r\n }\r\n\r\n // ── Tags ──────────────────────────────────────────────────────────────\r\n\r\n async listTags(applicationName: string, version: string): Promise<readonly TagResponse[]> {\r\n return this.get<TagResponse[]>(\r\n `/applications/${enc(applicationName)}/versions/${enc(version)}/tags`,\r\n );\r\n }\r\n\r\n async addTag(applicationName: string, version: string, tag: string): Promise<TagResponse> {\r\n return this.put<TagResponse>(\r\n `/applications/${enc(applicationName)}/versions/${enc(version)}/tags/${enc(tag)}`,\r\n );\r\n }\r\n\r\n async removeTag(applicationName: string, version: string, tag: string): Promise<void> {\r\n await this.delete(\r\n `/applications/${enc(applicationName)}/versions/${enc(version)}/tags/${enc(tag)}`,\r\n );\r\n }\r\n\r\n async getLatestVersionByTag(applicationName: string, tag: string): Promise<{ version: string }> {\r\n return this.get<{ version: string }>(\r\n `/applications/${enc(applicationName)}/versions/latest?tag=${enc(tag)}`,\r\n );\r\n }\r\n\r\n // ── Maintenance ───────────────────────────────────────────────────────\r\n\r\n async runCleanup(request: CleanupRequest): Promise<CleanupResult> {\r\n return this.post<CleanupResult>(\"/maintenance/cleanup\", request);\r\n }\r\n\r\n // ── HTTP helpers ──────────────────────────────────────────────────────\r\n\r\n private async get<T>(path: string): Promise<T> {\r\n return this.request<T>(\"GET\", path);\r\n }\r\n\r\n private async post<T>(path: string, body?: unknown): Promise<T> {\r\n return this.request<T>(\"POST\", path, body);\r\n }\r\n\r\n private async put<T>(path: string, body?: unknown): Promise<T> {\r\n return this.request<T>(\"PUT\", path, body);\r\n }\r\n\r\n private async delete(path: string): Promise<void> {\r\n await this.requestRaw(\"DELETE\", path);\r\n }\r\n\r\n private async request<T>(method: string, path: string, body?: unknown): Promise<T> {\r\n const response = await this.requestRaw(method, path, body);\r\n return (await response.json()) as T;\r\n }\r\n\r\n private async requestRaw(method: string, path: string, body?: unknown): Promise<Response> {\r\n const url = `${this.baseUrl}${API_PREFIX}${path}`;\r\n const headers: Record<string, string> = {};\r\n\r\n const auth = buildAuthHeader(this.config);\r\n if (auth !== undefined) {\r\n headers[\"Authorization\"] = auth;\r\n }\r\n\r\n if (body !== undefined) {\r\n headers[\"Content-Type\"] = \"application/json\";\r\n }\r\n\r\n let response: Response;\r\n const init: RequestInit = { method, headers, signal: AbortSignal.timeout(this.timeoutMs) };\r\n if (body !== undefined) {\r\n init.body = JSON.stringify(body);\r\n }\r\n try {\r\n response = await this.fetchFn(url, init);\r\n } catch (err: unknown) {\r\n throw new BrokerConnectionError(\r\n `Failed to connect to broker at ${this.baseUrl}: ${err instanceof Error ? err.message : String(err)}`,\r\n err,\r\n );\r\n }\r\n\r\n if (response.ok) {\r\n return response;\r\n }\r\n\r\n let errorResponse: ErrorResponse | null = null;\r\n try {\r\n errorResponse = (await response.json()) as ErrorResponse;\r\n } catch {\r\n // response body is not JSON — leave errorResponse as null\r\n }\r\n\r\n const message =\r\n errorResponse?.message ?? `${method} ${path} failed with status ${String(response.status)}`;\r\n\r\n switch (response.status) {\r\n case 400:\r\n throw new BrokerValidationError(message, errorResponse);\r\n case 401:\r\n throw new BrokerAuthError(message, errorResponse);\r\n case 403:\r\n throw new BrokerForbiddenError(message, errorResponse);\r\n case 404:\r\n throw new BrokerNotFoundError(message, errorResponse);\r\n case 409:\r\n throw new BrokerConflictError(message, errorResponse);\r\n default:\r\n throw new BrokerApiError(response.status, message, errorResponse);\r\n }\r\n }\r\n\r\n private buildPageQuery(params?: PageParams): string {\r\n const urlParams = new URLSearchParams();\r\n urlParams.set(\"page\", String(params?.page ?? 0));\r\n urlParams.set(\"size\", String(params?.size ?? this.defaultPageSize));\r\n if (params?.sort !== undefined && params.sort !== \"\") {\r\n urlParams.set(\"sort\", params.sort);\r\n }\r\n return urlParams.toString();\r\n }\r\n\r\n private buildListQuery(params?: ListParams): string {\r\n const urlParams = new URLSearchParams();\r\n urlParams.set(\"page\", String(params?.page ?? 0));\r\n urlParams.set(\"size\", String(params?.size ?? this.defaultPageSize));\r\n if (params?.sort !== undefined && params.sort !== \"\") {\r\n urlParams.set(\"sort\", params.sort);\r\n }\r\n if (params?.search !== undefined && params.search !== \"\") {\r\n urlParams.set(\"search\", params.search);\r\n }\r\n return urlParams.toString();\r\n }\r\n}\r\n\r\nfunction enc(value: string): string {\r\n return encodeURIComponent(value);\r\n}\r\n","import type { Page, PageParams } from \"./types.js\";\r\n\r\n/** Maximum number of pages to fetch to prevent infinite loops. */\r\nconst MAX_PAGES = 1000;\r\n\r\n/** Async iterator that fetches all pages from a paginated endpoint. */\r\nexport async function* pageIterator<T>(\r\n fetcher: (params: PageParams) => Promise<Page<T>>,\r\n params: PageParams = {},\r\n): AsyncGenerator<T, void, undefined> {\r\n let currentPage = params.page ?? 0;\r\n const size = params.size ?? 20;\r\n let hasMore = true;\r\n let pagesRead = 0;\r\n\r\n while (hasMore) {\r\n if (pagesRead >= MAX_PAGES) {\r\n throw new Error(`Exceeded maximum page limit (${String(MAX_PAGES)})`);\r\n }\r\n const page = await fetcher({ ...params, page: currentPage, size });\r\n for (const item of page.content) {\r\n yield item;\r\n }\r\n currentPage++;\r\n pagesRead++;\r\n hasMore = currentPage < page.totalPages;\r\n }\r\n}\r\n\r\n/** Collect all items from all pages into a single array. */\r\nexport async function fetchAllPages<T>(\r\n fetcher: (params: PageParams) => Promise<Page<T>>,\r\n params: PageParams = {},\r\n): Promise<readonly T[]> {\r\n const items: T[] = [];\r\n for await (const item of pageIterator(fetcher, params)) {\r\n items.push(item);\r\n }\r\n return items;\r\n}\r\n"],"mappings":"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","names":[]}
package/package.json ADDED
@@ -0,0 +1,27 @@
1
+ {
2
+ "name": "@stubborn-sh/broker-client",
3
+ "version": "0.0.3",
4
+ "type": "module",
5
+ "main": "./dist/index.js",
6
+ "types": "./dist/index.d.ts",
7
+ "exports": {
8
+ ".": {
9
+ "types": "./dist/index.d.ts",
10
+ "import": "./dist/index.js",
11
+ "require": "./dist/index.cjs"
12
+ }
13
+ },
14
+ "files": [
15
+ "dist"
16
+ ],
17
+ "scripts": {
18
+ "build": "tsup",
19
+ "typecheck": "tsc --noEmit"
20
+ },
21
+ "publishConfig": {
22
+ "access": "public"
23
+ },
24
+ "devDependencies": {
25
+ "tsup": "^8.4.0"
26
+ }
27
+ }