UNPKG

@fly/sprites

Version:

JavaScript/TypeScript SDK for Sprites - remote command execution

191 lines 6.46 kB
/** * Sprites client implementation */ import { Sprite } from './sprite.js'; /** * Main client for interacting with the Sprites API */ export class SpritesClient { baseURL; token; timeout; constructor(token, options = {}) { this.token = token; this.baseURL = (options.baseURL || 'https://api.sprites.dev').replace(/\/+$/, ''); this.timeout = options.timeout || 30000; } /** * Get a handle to a sprite (doesn't create it on the server) */ sprite(name) { return new Sprite(name, this); } /** * Create a new sprite */ async createSprite(name, config) { const request = { name, config }; const response = await this.fetch(`${this.baseURL}/v1/sprites`, { method: 'POST', headers: { 'Authorization': `Bearer ${this.token}`, 'Content-Type': 'application/json', }, body: JSON.stringify(request), signal: AbortSignal.timeout(120000), // 2 minute timeout for creation }); if (!response.ok) { const body = await response.text(); throw new Error(`Failed to create sprite (status ${response.status}): ${body}`); } const result = await response.json(); return new Sprite(result.name, this); } /** * Get information about a sprite */ async getSprite(name) { const response = await this.fetch(`${this.baseURL}/v1/sprites/${name}`, { method: 'GET', headers: { 'Authorization': `Bearer ${this.token}`, }, signal: AbortSignal.timeout(this.timeout), }); if (response.status === 404) { throw new Error(`Sprite not found: ${name}`); } if (!response.ok) { const body = await response.text(); throw new Error(`Failed to get sprite (status ${response.status}): ${body}`); } const info = await response.json(); const sprite = new Sprite(info.name, this); Object.assign(sprite, info); return sprite; } /** * List sprites with optional filtering and pagination */ async listSprites(options = {}) { const params = new URLSearchParams(); if (options.maxResults) params.set('max_results', options.maxResults.toString()); if (options.continuationToken) params.set('continuation_token', options.continuationToken); if (options.prefix) params.set('prefix', options.prefix); const url = `${this.baseURL}/v1/sprites?${params}`; const response = await this.fetch(url, { method: 'GET', headers: { 'Authorization': `Bearer ${this.token}`, }, signal: AbortSignal.timeout(this.timeout), }); if (!response.ok) { const body = await response.text(); throw new Error(`Failed to list sprites (status ${response.status}): ${body}`); } return await response.json(); } /** * List all sprites, handling pagination automatically */ async listAllSprites(prefix) { const allSprites = []; let continuationToken; do { const result = await this.listSprites({ prefix, maxResults: 100, continuationToken, }); for (const info of result.sprites) { const sprite = new Sprite(info.name, this); Object.assign(sprite, info); allSprites.push(sprite); } continuationToken = result.hasMore ? result.nextContinuationToken : undefined; } while (continuationToken); return allSprites; } /** * Delete a sprite */ async deleteSprite(name) { const response = await this.fetch(`${this.baseURL}/v1/sprites/${name}`, { method: 'DELETE', headers: { 'Authorization': `Bearer ${this.token}`, }, signal: AbortSignal.timeout(this.timeout), }); if (!response.ok && response.status !== 204) { const body = await response.text(); throw new Error(`Failed to delete sprite (status ${response.status}): ${body}`); } } /** * Upgrade a sprite to the latest version */ async upgradeSprite(name) { const response = await this.fetch(`${this.baseURL}/v1/sprites/${name}/upgrade`, { method: 'POST', headers: { 'Authorization': `Bearer ${this.token}`, }, signal: AbortSignal.timeout(60000), }); if (!response.ok && response.status !== 204) { const body = await response.text(); throw new Error(`Failed to upgrade sprite (status ${response.status}): ${body}`); } } /** * Create a sprite access token using a Fly.io macaroon token */ static async createToken(flyMacaroon, orgSlug, inviteCode) { const apiURL = 'https://api.sprites.dev'; const url = `${apiURL}/v1/organizations/${orgSlug}/tokens`; const body = { description: 'Sprite SDK Token', }; if (inviteCode) { body.invite_code = inviteCode; } const response = await fetch(url, { method: 'POST', headers: { 'Authorization': `FlyV1 ${flyMacaroon}`, 'Content-Type': 'application/json', }, body: JSON.stringify(body), signal: AbortSignal.timeout(30000), }); if (!response.ok) { const text = await response.text(); throw new Error(`API returned status ${response.status}: ${text}`); } const result = await response.json(); if (!result.token) { throw new Error('No token returned in response'); } return result.token; } /** * Wrapper around fetch for consistent error handling */ async fetch(url, init) { try { return await fetch(url, init); } catch (error) { if (error instanceof Error) { throw new Error(`Network error: ${error.message}`); } throw error; } } } //# sourceMappingURL=client.js.map