brigent-sdk 0.1.0

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/README.md ADDED
@@ -0,0 +1,184 @@
1
+ # @brigent/sdk
2
+
3
+ TypeScript SDK for the **Brigent** Agent-Native Infrastructure Platform.
4
+
5
+ AI agents call Brigent to deploy services. Brigent orchestrates compute, databases, cache, storage, and domains — agents get back a live URL.
6
+
7
+ ## Install
8
+
9
+ ```bash
10
+ npm install @brigent/sdk
11
+ ```
12
+
13
+ ## Quick Start
14
+
15
+ ```typescript
16
+ import { BrigentClient } from "@brigent/sdk";
17
+
18
+ const client = new BrigentClient({
19
+ apiKey: "brg_your_api_key",
20
+ baseUrl: "https://brigent-production.up.railway.app",
21
+ });
22
+
23
+ // Deploy a Docker image
24
+ const deploy = await client.deploy({
25
+ type: "api",
26
+ name: "my-service",
27
+ source: { method: "docker_image", image: "nginx:alpine" },
28
+ health_check_path: "/",
29
+ budget_cap_usdc: "5.00",
30
+ });
31
+
32
+ // Wait for it to go live
33
+ const detail = await client.monitor.waitForLive(deploy.deployment_id);
34
+ console.log(`Live at: ${detail.url}`);
35
+ ```
36
+
37
+ ## API Reference
38
+
39
+ ### Deployments
40
+
41
+ ```typescript
42
+ // Deploy a new service
43
+ client.deploy(request: DeployRequest): Promise<DeployResponse>
44
+
45
+ // Get deployment status and URL
46
+ client.getDeployment(id: string): Promise<DeploymentDetail>
47
+
48
+ // List all deployments
49
+ client.listDeployments(options?): Promise<PaginatedResponse<DeploymentListItem>>
50
+
51
+ // Delete / terminate a deployment
52
+ client.deleteDeployment(id: string): Promise<void>
53
+
54
+ // Fetch container logs
55
+ client.getLogs(id: string, options?): Promise<LogEntry[]>
56
+
57
+ // Scale replicas / memory
58
+ client.scale(id: string, config: ScaleConfig): Promise<void>
59
+
60
+ // Update environment variables
61
+ client.updateEnv(id: string, envVars: Record<string, string>): Promise<void>
62
+ ```
63
+
64
+ ### Lifecycle
65
+
66
+ ```typescript
67
+ client.pause(id: string)
68
+ client.resume(id: string)
69
+ client.restart(id: string)
70
+ client.cancel(id: string)
71
+ ```
72
+
73
+ ### Monitoring
74
+
75
+ ```typescript
76
+ // Poll until deployment is live (throws on failure/timeout)
77
+ client.monitor.waitForLive(deploymentId, {
78
+ timeoutMs: 300_000, // default: 5 min
79
+ pollIntervalMs: 3_000, // default: 3s
80
+ })
81
+
82
+ // Stream real-time events via SSE
83
+ for await (const event of client.streamEvents(deploymentId)) {
84
+ console.log(event.status, event.data);
85
+ }
86
+ ```
87
+
88
+ ### Cost & Billing
89
+
90
+ ```typescript
91
+ client.getCost(id: string): Promise<CostResponse>
92
+ client.estimate(request: Partial<DeployRequest>): Promise<CostEstimate>
93
+ client.getBillingSummary(options?): Promise<BillingSummary>
94
+ client.getPricing(): Promise<PricingResponse>
95
+ client.getTier(): Promise<TierResponse>
96
+ ```
97
+
98
+ ### API Keys
99
+
100
+ ```typescript
101
+ client.createApiKey({ name, scopes, rate_limit_tier }): Promise<ApiKeyResponse>
102
+ client.listApiKeys(): Promise<ApiKeyListItem[]>
103
+ client.deleteApiKey(id: string): Promise<void>
104
+ ```
105
+
106
+ ### Webhooks
107
+
108
+ ```typescript
109
+ client.createWebhook({ url, events, secret }): Promise<WebhookResponse>
110
+ client.listWebhooks(): Promise<WebhookListItem[]>
111
+ client.updateWebhook(id, updates): Promise<WebhookListItem>
112
+ client.deleteWebhook(id: string): Promise<void>
113
+
114
+ // Verify incoming webhook signatures
115
+ import { verifyWebhookSignature } from "@brigent/sdk";
116
+ const valid = verifyWebhookSignature(payload, signature, secret);
117
+ ```
118
+
119
+ ### Templates
120
+
121
+ ```typescript
122
+ client.createTemplate(params): Promise<TemplateResponse>
123
+ client.listTemplates(): Promise<TemplateResponse[]>
124
+ client.getTemplate(id: string): Promise<TemplateResponse>
125
+ client.deleteTemplate(id: string): Promise<void>
126
+ client.deployFromTemplate(templateId, { name, ...overrides }): Promise<DeployResponse>
127
+ ```
128
+
129
+ ### Custom Domains
130
+
131
+ ```typescript
132
+ client.assignCustomDomain(deploymentId, "app.example.com"): Promise<CustomDomainResponse>
133
+ ```
134
+
135
+ ### Health
136
+
137
+ ```typescript
138
+ client.getHealth(): Promise<HealthResponse>
139
+ client.getReadiness(): Promise<ReadinessResponse>
140
+ ```
141
+
142
+ ## Error Handling
143
+
144
+ ```typescript
145
+ import { BrigentApiError } from "@brigent/sdk";
146
+
147
+ try {
148
+ await client.deploy(request);
149
+ } catch (err) {
150
+ if (err instanceof BrigentApiError) {
151
+ console.log(err.code); // "INVALID_REQUEST"
152
+ console.log(err.suggestedAction); // "Check the request body..."
153
+ console.log(err.status); // 400
154
+ console.log(err.requestId); // "abc-123"
155
+ }
156
+ }
157
+ ```
158
+
159
+ ## Configuration
160
+
161
+ ```typescript
162
+ const client = new BrigentClient({
163
+ apiKey: "brg_...", // Required
164
+ baseUrl: "https://...", // Default: https://api.brigent.dev
165
+ timeout: 30_000, // Request timeout in ms
166
+ maxRetries: 2, // Auto-retry on 429/5xx
167
+ });
168
+ ```
169
+
170
+ ## Deployment Types
171
+
172
+ | Type | Compute | Database | Cache | Storage | Domain | Health Check |
173
+ |------|---------|----------|-------|---------|--------|-------------|
174
+ | `api` | Yes | Optional | Optional | Optional | Yes | Yes |
175
+ | `fullstack` | Yes | Optional | Optional | Optional | Yes | Yes |
176
+ | `frontend` | Yes | No | No | No | Yes | Yes |
177
+ | `worker` | Yes | Optional | Optional | Optional | No | No |
178
+ | `cron` | Yes | Optional | No | No | No | No |
179
+ | `static_site` | No | No | No | Required | Yes | No |
180
+ | `database_only` | No | Required | Optional | No | No | No |
181
+
182
+ ## License
183
+
184
+ MIT
@@ -0,0 +1,81 @@
1
+ import { DeploymentMonitor } from "./monitor.js";
2
+ import type { StreamEventsOptions } from "./events.js";
3
+ import type { AnalyticsOverview, AuditLogEntry, AuditLogOptions, BillingSummary, BillingSummaryOptions, CustomDomainResponse, DeploymentEvent, DeploymentMetrics, PricingResponse, TierResponse, TemplateCreateParams, TemplateResponse, WebhookDeliveryItem, ApiKeyCreateParams, ApiKeyListItem, ApiKeyResponse, BrigentClientOptions, CostEstimate, CostResponse, DeploymentDetail, DeploymentListItem, DeployRequest, DeployResponse, HealthResponse, ReadinessResponse, LogEntry, PaginatedResponse, ScaleConfig, WebhookCreateParams, WebhookListItem, WebhookResponse, WebhookUpdateParams } from "./types.js";
4
+ export interface ListDeploymentsOptions {
5
+ status?: string;
6
+ type?: string;
7
+ page?: number;
8
+ per_page?: number;
9
+ sort?: string;
10
+ order?: "asc" | "desc";
11
+ }
12
+ export interface GetLogsOptions {
13
+ since?: string;
14
+ limit?: number;
15
+ }
16
+ export declare class BrigentClient {
17
+ private readonly http;
18
+ readonly monitor: DeploymentMonitor;
19
+ constructor(options: BrigentClientOptions);
20
+ deploy(request: DeployRequest): Promise<DeployResponse>;
21
+ getDeployment(id: string): Promise<DeploymentDetail>;
22
+ listDeployments(options?: ListDeploymentsOptions): Promise<PaginatedResponse<DeploymentListItem>>;
23
+ deleteDeployment(id: string): Promise<void>;
24
+ getLogs(id: string, options?: GetLogsOptions): Promise<LogEntry[]>;
25
+ scale(id: string, config: ScaleConfig): Promise<void>;
26
+ updateEnv(id: string, envVars: Record<string, string>): Promise<void>;
27
+ getCost(id: string): Promise<CostResponse>;
28
+ estimate(request: Partial<DeployRequest>): Promise<CostEstimate>;
29
+ createApiKey(params: ApiKeyCreateParams): Promise<ApiKeyResponse>;
30
+ listApiKeys(): Promise<ApiKeyListItem[]>;
31
+ deleteApiKey(id: string): Promise<void>;
32
+ createWebhook(params: WebhookCreateParams): Promise<WebhookResponse>;
33
+ listWebhooks(): Promise<WebhookListItem[]>;
34
+ deleteWebhook(id: string): Promise<void>;
35
+ updateWebhook(id: string, updates: WebhookUpdateParams): Promise<WebhookListItem>;
36
+ getWebhookDeliveries(webhookId: string, options?: {
37
+ page?: number;
38
+ per_page?: number;
39
+ }): Promise<PaginatedResponse<WebhookDeliveryItem>>;
40
+ replayWebhookDelivery(webhookId: string, deliveryId: string): Promise<{
41
+ delivery_id: string;
42
+ status: string;
43
+ }>;
44
+ getHealth(): Promise<HealthResponse>;
45
+ getReadiness(): Promise<ReadinessResponse>;
46
+ getAnalyticsOverview(): Promise<AnalyticsOverview>;
47
+ getDeploymentMetrics(id: string): Promise<DeploymentMetrics>;
48
+ getAuditLog(options?: AuditLogOptions): Promise<PaginatedResponse<AuditLogEntry>>;
49
+ getBillingSummary(options?: BillingSummaryOptions): Promise<BillingSummary>;
50
+ getPricing(): Promise<PricingResponse>;
51
+ getTier(): Promise<TierResponse>;
52
+ createTemplate(params: TemplateCreateParams): Promise<TemplateResponse>;
53
+ listTemplates(): Promise<TemplateResponse[]>;
54
+ getTemplate(id: string): Promise<TemplateResponse>;
55
+ deleteTemplate(id: string): Promise<void>;
56
+ deployFromTemplate(templateId: string, overrides: {
57
+ name: string;
58
+ } & Partial<DeployRequest>): Promise<DeployResponse>;
59
+ pause(id: string): Promise<{
60
+ deployment_id: string;
61
+ status: string;
62
+ }>;
63
+ resume(id: string): Promise<{
64
+ deployment_id: string;
65
+ status: string;
66
+ }>;
67
+ restart(id: string): Promise<{
68
+ deployment_id: string;
69
+ status: string;
70
+ }>;
71
+ cancel(id: string): Promise<{
72
+ deployment_id: string;
73
+ status: string;
74
+ }>;
75
+ assignCustomDomain(deploymentId: string, domain: string): Promise<CustomDomainResponse>;
76
+ /**
77
+ * Stream real-time deployment status events via SSE.
78
+ * Returns an async generator yielding DeploymentEvent objects.
79
+ */
80
+ streamEvents(deploymentId: string, options?: StreamEventsOptions): AsyncGenerator<DeploymentEvent>;
81
+ }
package/dist/client.js ADDED
@@ -0,0 +1,190 @@
1
+ import { HttpClient } from "./http.js";
2
+ import { DeploymentMonitor } from "./monitor.js";
3
+ import { streamDeploymentEvents } from "./events.js";
4
+ const DEFAULT_BASE_URL = "https://api.brigent.dev";
5
+ const DEFAULT_TIMEOUT = 30_000;
6
+ const DEFAULT_MAX_RETRIES = 2;
7
+ export class BrigentClient {
8
+ http;
9
+ monitor;
10
+ constructor(options) {
11
+ this.http = new HttpClient({
12
+ baseUrl: options.baseUrl ?? DEFAULT_BASE_URL,
13
+ apiKey: options.apiKey,
14
+ timeout: options.timeout ?? DEFAULT_TIMEOUT,
15
+ maxRetries: options.maxRetries ?? DEFAULT_MAX_RETRIES,
16
+ });
17
+ this.monitor = new DeploymentMonitor(this.http);
18
+ }
19
+ // --- Deployments ---
20
+ async deploy(request) {
21
+ return this.http.post("/v1/deploy", request);
22
+ }
23
+ async getDeployment(id) {
24
+ return this.http.get(`/v1/deployments/${id}`);
25
+ }
26
+ async listDeployments(options) {
27
+ const params = new URLSearchParams();
28
+ if (options?.status)
29
+ params.set("status", options.status);
30
+ if (options?.type)
31
+ params.set("type", options.type);
32
+ if (options?.page)
33
+ params.set("page", String(options.page));
34
+ if (options?.per_page)
35
+ params.set("per_page", String(options.per_page));
36
+ if (options?.sort)
37
+ params.set("sort", options.sort);
38
+ if (options?.order)
39
+ params.set("order", options.order);
40
+ const qs = params.toString();
41
+ return this.http.get(`/v1/deployments${qs ? `?${qs}` : ""}`);
42
+ }
43
+ async deleteDeployment(id) {
44
+ await this.http.delete(`/v1/deployments/${id}`);
45
+ }
46
+ async getLogs(id, options) {
47
+ const params = new URLSearchParams();
48
+ if (options?.since)
49
+ params.set("since", options.since);
50
+ if (options?.limit)
51
+ params.set("limit", String(options.limit));
52
+ const qs = params.toString();
53
+ const response = await this.http.get(`/v1/deployments/${id}/logs${qs ? `?${qs}` : ""}`);
54
+ return response.logs;
55
+ }
56
+ async scale(id, config) {
57
+ await this.http.post(`/v1/deployments/${id}/scale`, config);
58
+ }
59
+ async updateEnv(id, envVars) {
60
+ await this.http.patch(`/v1/deployments/${id}`, { env_vars: envVars });
61
+ }
62
+ // --- Cost ---
63
+ async getCost(id) {
64
+ return this.http.get(`/v1/deployments/${id}/cost`);
65
+ }
66
+ async estimate(request) {
67
+ return this.http.post("/v1/estimate", request);
68
+ }
69
+ // --- API Keys ---
70
+ async createApiKey(params) {
71
+ return this.http.post("/v1/account/keys", params);
72
+ }
73
+ async listApiKeys() {
74
+ const response = await this.http.get("/v1/account/keys");
75
+ return response.keys;
76
+ }
77
+ async deleteApiKey(id) {
78
+ await this.http.delete(`/v1/account/keys/${id}`);
79
+ }
80
+ // --- Webhooks ---
81
+ async createWebhook(params) {
82
+ return this.http.post("/v1/webhooks", params);
83
+ }
84
+ async listWebhooks() {
85
+ const response = await this.http.get("/v1/webhooks");
86
+ return response.webhooks;
87
+ }
88
+ async deleteWebhook(id) {
89
+ await this.http.delete(`/v1/webhooks/${id}`);
90
+ }
91
+ async updateWebhook(id, updates) {
92
+ return this.http.patch(`/v1/webhooks/${id}`, updates);
93
+ }
94
+ async getWebhookDeliveries(webhookId, options) {
95
+ const params = new URLSearchParams();
96
+ if (options?.page)
97
+ params.set("page", String(options.page));
98
+ if (options?.per_page)
99
+ params.set("per_page", String(options.per_page));
100
+ const qs = params.toString();
101
+ return this.http.get(`/v1/webhooks/${webhookId}/deliveries${qs ? `?${qs}` : ""}`);
102
+ }
103
+ async replayWebhookDelivery(webhookId, deliveryId) {
104
+ return this.http.post(`/v1/webhooks/${webhookId}/deliveries/${deliveryId}/replay`, {});
105
+ }
106
+ // --- Health ---
107
+ async getHealth() {
108
+ return this.http.get("/v1/health");
109
+ }
110
+ async getReadiness() {
111
+ return this.http.get("/v1/health/ready");
112
+ }
113
+ // --- Analytics ---
114
+ async getAnalyticsOverview() {
115
+ return this.http.get("/v1/analytics/overview");
116
+ }
117
+ async getDeploymentMetrics(id) {
118
+ return this.http.get(`/v1/analytics/deployments/${id}/metrics`);
119
+ }
120
+ async getAuditLog(options) {
121
+ const params = new URLSearchParams();
122
+ if (options?.action)
123
+ params.set("action", options.action);
124
+ if (options?.since)
125
+ params.set("since", options.since);
126
+ if (options?.page)
127
+ params.set("page", String(options.page));
128
+ if (options?.per_page)
129
+ params.set("per_page", String(options.per_page));
130
+ const qs = params.toString();
131
+ return this.http.get(`/v1/account/audit${qs ? `?${qs}` : ""}`);
132
+ }
133
+ async getBillingSummary(options) {
134
+ const params = new URLSearchParams();
135
+ if (options?.since)
136
+ params.set("since", options.since);
137
+ if (options?.until)
138
+ params.set("until", options.until);
139
+ const qs = params.toString();
140
+ return this.http.get(`/v1/account/billing/summary${qs ? `?${qs}` : ""}`);
141
+ }
142
+ // --- Pricing ---
143
+ async getPricing() {
144
+ return this.http.get("/v1/pricing");
145
+ }
146
+ async getTier() {
147
+ return this.http.get("/v1/account/tier");
148
+ }
149
+ // --- Templates ---
150
+ async createTemplate(params) {
151
+ return this.http.post("/v1/templates", params);
152
+ }
153
+ async listTemplates() {
154
+ return this.http.get("/v1/templates");
155
+ }
156
+ async getTemplate(id) {
157
+ return this.http.get(`/v1/templates/${id}`);
158
+ }
159
+ async deleteTemplate(id) {
160
+ await this.http.delete(`/v1/templates/${id}`);
161
+ }
162
+ async deployFromTemplate(templateId, overrides) {
163
+ return this.http.post("/v1/deploy", { ...overrides, template_id: templateId });
164
+ }
165
+ // --- Lifecycle ---
166
+ async pause(id) {
167
+ return this.http.post(`/v1/deployments/${id}/pause`, {});
168
+ }
169
+ async resume(id) {
170
+ return this.http.post(`/v1/deployments/${id}/resume`, {});
171
+ }
172
+ async restart(id) {
173
+ return this.http.post(`/v1/deployments/${id}/restart`, {});
174
+ }
175
+ async cancel(id) {
176
+ return this.http.post(`/v1/deployments/${id}/cancel`, {});
177
+ }
178
+ // --- Custom Domains ---
179
+ async assignCustomDomain(deploymentId, domain) {
180
+ return this.http.post(`/v1/deployments/${deploymentId}/domains`, { domain });
181
+ }
182
+ // --- SSE Events ---
183
+ /**
184
+ * Stream real-time deployment status events via SSE.
185
+ * Returns an async generator yielding DeploymentEvent objects.
186
+ */
187
+ streamEvents(deploymentId, options) {
188
+ return streamDeploymentEvents(this.http.baseUrl, this.http.apiKey, deploymentId, options);
189
+ }
190
+ }
package/dist/cost.d.ts ADDED
@@ -0,0 +1,13 @@
1
+ import type { CostEstimate, DeploymentType } from "./types.js";
2
+ export interface EstimateOptions {
3
+ type?: DeploymentType;
4
+ database?: boolean;
5
+ cache?: boolean;
6
+ storage?: boolean;
7
+ tierMultiplier?: number;
8
+ }
9
+ /**
10
+ * Client-side cost estimation that mirrors the server-side logic.
11
+ * Useful for building UIs that show cost previews before deploying.
12
+ */
13
+ export declare function estimateCost(options?: EstimateOptions): CostEstimate;
package/dist/cost.js ADDED
@@ -0,0 +1,106 @@
1
+ const PRICING = {
2
+ build: { unit: "per build", unitPrice: 0.10 },
3
+ compute: { unit: "per hour", unitPrice: 0.03 },
4
+ database: { unit: "per hour", unitPrice: 0.01 },
5
+ cache: { unit: "per hour", unitPrice: 0.005 },
6
+ storage: { unit: "per hour", unitPrice: 0.002 },
7
+ domain: { unit: "included", unitPrice: 0.00 },
8
+ };
9
+ const HOURS_PER_MONTH = 720;
10
+ /**
11
+ * Client-side cost estimation that mirrors the server-side logic.
12
+ * Useful for building UIs that show cost previews before deploying.
13
+ */
14
+ export function estimateCost(options = {}) {
15
+ const multiplier = options.tierMultiplier ?? 1.0;
16
+ const isStaticSite = options.type === "static_site";
17
+ const isDatabaseOnly = options.type === "database_only";
18
+ const breakdown = [];
19
+ // Build cost (skipped for static_site and database_only)
20
+ if (!isStaticSite && !isDatabaseOnly) {
21
+ const price = PRICING.build.unitPrice * multiplier;
22
+ breakdown.push({
23
+ resource: "build",
24
+ unit: PRICING.build.unit,
25
+ unit_price_usdc: formatPrice(price),
26
+ quantity: 1,
27
+ subtotal_usdc: formatPrice(price),
28
+ });
29
+ }
30
+ // Compute (skipped for static_site and database_only)
31
+ if (!isStaticSite && !isDatabaseOnly) {
32
+ const price = PRICING.compute.unitPrice * multiplier;
33
+ breakdown.push({
34
+ resource: "compute",
35
+ unit: PRICING.compute.unit,
36
+ unit_price_usdc: formatPrice(price),
37
+ quantity: 1,
38
+ subtotal_usdc: formatPrice(price),
39
+ });
40
+ }
41
+ // Database
42
+ if (options.database || isDatabaseOnly) {
43
+ const price = PRICING.database.unitPrice * multiplier;
44
+ breakdown.push({
45
+ resource: "database",
46
+ unit: PRICING.database.unit,
47
+ unit_price_usdc: formatPrice(price),
48
+ quantity: 1,
49
+ subtotal_usdc: formatPrice(price),
50
+ });
51
+ }
52
+ // Cache
53
+ if (options.cache) {
54
+ const price = PRICING.cache.unitPrice * multiplier;
55
+ breakdown.push({
56
+ resource: "cache",
57
+ unit: PRICING.cache.unit,
58
+ unit_price_usdc: formatPrice(price),
59
+ quantity: 1,
60
+ subtotal_usdc: formatPrice(price),
61
+ });
62
+ }
63
+ // Storage
64
+ if (options.storage || isStaticSite) {
65
+ const price = PRICING.storage.unitPrice * multiplier;
66
+ breakdown.push({
67
+ resource: "storage",
68
+ unit: PRICING.storage.unit,
69
+ unit_price_usdc: formatPrice(price),
70
+ quantity: 1,
71
+ subtotal_usdc: formatPrice(price),
72
+ });
73
+ }
74
+ // Domain (skipped for database_only)
75
+ if (!isDatabaseOnly) {
76
+ breakdown.push({
77
+ resource: "domain",
78
+ unit: PRICING.domain.unit,
79
+ unit_price_usdc: formatPrice(PRICING.domain.unitPrice * multiplier),
80
+ quantity: 1,
81
+ subtotal_usdc: formatPrice(PRICING.domain.unitPrice * multiplier),
82
+ });
83
+ }
84
+ // Calculate totals
85
+ const setupUsdc = breakdown
86
+ .filter((i) => i.resource === "build")
87
+ .reduce((sum, i) => sum + parseFloat(i.subtotal_usdc), 0);
88
+ const hourlyUsdc = breakdown
89
+ .filter((i) => i.resource !== "build" && i.resource !== "domain")
90
+ .reduce((sum, i) => sum + parseFloat(i.subtotal_usdc), 0);
91
+ return {
92
+ setup_usdc: setupUsdc.toFixed(2),
93
+ hourly_usdc: hourlyUsdc.toFixed(2),
94
+ monthly_estimate_usdc: (setupUsdc + hourlyUsdc * HOURS_PER_MONTH).toFixed(2),
95
+ breakdown,
96
+ };
97
+ }
98
+ function formatPrice(value) {
99
+ // For prices like 0.005, 0.002 — preserve significant decimals
100
+ if (value === 0)
101
+ return "0.00";
102
+ const str = value.toString();
103
+ const decimalPart = str.split(".")[1] ?? "";
104
+ const minDecimals = Math.max(2, decimalPart.length);
105
+ return value.toFixed(minDecimals);
106
+ }
@@ -0,0 +1,10 @@
1
+ import type { BrigentErrorBody } from "./types.js";
2
+ export declare class BrigentApiError extends Error {
3
+ readonly status: number;
4
+ readonly code: string;
5
+ readonly suggestedAction: string;
6
+ readonly requestId: string;
7
+ readonly retryAfterSeconds?: number;
8
+ readonly details?: Record<string, unknown>;
9
+ constructor(status: number, body: BrigentErrorBody);
10
+ }
package/dist/errors.js ADDED
@@ -0,0 +1,18 @@
1
+ export class BrigentApiError extends Error {
2
+ status;
3
+ code;
4
+ suggestedAction;
5
+ requestId;
6
+ retryAfterSeconds;
7
+ details;
8
+ constructor(status, body) {
9
+ super(body.error.message);
10
+ this.name = "BrigentApiError";
11
+ this.status = status;
12
+ this.code = body.error.code;
13
+ this.suggestedAction = body.error.suggested_action;
14
+ this.requestId = body.request_id;
15
+ this.retryAfterSeconds = body.error.retry_after_seconds;
16
+ this.details = body.error.details;
17
+ }
18
+ }
@@ -0,0 +1,29 @@
1
+ export interface DeploymentEvent {
2
+ deployment_id: string;
3
+ status: string;
4
+ previous_status?: string;
5
+ timestamp: string;
6
+ failure_reason?: string;
7
+ }
8
+ export interface StreamEventsOptions {
9
+ /** Abort signal for cancellation */
10
+ signal?: AbortSignal;
11
+ /** Maximum reconnect attempts (default: 5) */
12
+ maxReconnectAttempts?: number;
13
+ /** Base reconnect delay in ms (default: 1000, uses exponential backoff) */
14
+ reconnectDelayMs?: number;
15
+ }
16
+ /**
17
+ * Stream deployment events via SSE.
18
+ * Returns an async iterable that yields DeploymentEvent objects.
19
+ * Supports auto-reconnect with exponential backoff.
20
+ *
21
+ * Usage:
22
+ * ```typescript
23
+ * for await (const event of streamDeploymentEvents(baseUrl, apiKey, "dep_123")) {
24
+ * console.log(event.status);
25
+ * if (event.status === "live") break;
26
+ * }
27
+ * ```
28
+ */
29
+ export declare function streamDeploymentEvents(baseUrl: string, apiKey: string, deploymentId: string, options?: StreamEventsOptions): AsyncGenerator<DeploymentEvent>;