diff --git a/.release-please-manifest.json b/.release-please-manifest.json index acc5a4e..c70be76 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "0.1.0-alpha.31" + ".": "0.1.0-alpha.32" } diff --git a/.stats.yml b/.stats.yml index 1523999..6024b95 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ -configured_endpoints: 15 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/the-san-francisco-compute-company/sfc-nodes-679b42a61deffd275fd9e01d6e2c0024540cd0059f4cc01bb52cc2876aaff3af.yml -openapi_spec_hash: 8c3eea1499910eb3683d774fe1a21f79 +configured_endpoints: 2 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/the-san-francisco-compute-company/sfc-nodes-58790875b9aca7481caf8eadc7c5235d56b2134a0733e4a76ac32c5fe97ac9fa.yml +openapi_spec_hash: 345ddd17750fb97c4ab7c9156b89e541 config_hash: 8457a42ab599fb499cdacdb3ff40cfe9 diff --git a/CHANGELOG.md b/CHANGELOG.md index 851331a..67eb47f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,26 @@ # Changelog +## 0.1.0-alpha.32 (2026-07-01) + +Full Changelog: [v0.1.0-alpha.31...v0.1.0-alpha.32](https://github.com/sfcompute/nodes-typescript/compare/v0.1.0-alpha.31...v0.1.0-alpha.32) + +### Features + +* **api:** api update ([5e5179e](https://github.com/sfcompute/nodes-typescript/commit/5e5179e1706895ba15ab49a5cd6ab6e3bf7aff2d)) +* **api:** api update ([9af0bc4](https://github.com/sfcompute/nodes-typescript/commit/9af0bc4c3845a3666b132927c36b564f276ef5d4)) +* **api:** api update ([41d0397](https://github.com/sfcompute/nodes-typescript/commit/41d039709d0b6a83adaf223ff3ec8f08619b3bd8)) +* **api:** api update ([35f91a2](https://github.com/sfcompute/nodes-typescript/commit/35f91a27ce035bbf213c19243ce481312855641d)) + + +### Bug Fixes + +* **client:** send content-type header for requests with an omitted optional body ([7246bb9](https://github.com/sfcompute/nodes-typescript/commit/7246bb916cb644bca7fd48e6bd9ba1f66f64ad53)) + + +### Chores + +* **internal:** codegen related update ([f6cf9d5](https://github.com/sfcompute/nodes-typescript/commit/f6cf9d5c39d45df96bee9673184fb5f955c69dd3)) + ## 0.1.0-alpha.31 (2026-05-19) Full Changelog: [v0.1.0-alpha.30...v0.1.0-alpha.31](https://github.com/sfcompute/nodes-typescript/compare/v0.1.0-alpha.30...v0.1.0-alpha.31) diff --git a/README.md b/README.md index c78c179..608cad5 100644 --- a/README.md +++ b/README.md @@ -26,9 +26,9 @@ const client = new SFCNodes({ bearerToken: process.env['SFC_NODES_BEARER_TOKEN'], // This is the default and can be omitted }); -const listResponseNode = await client.nodes.list(); +const images = await client.vms.images.list({ workspace: 'wksp_k3R-nX9vLm7Qp2Yw5Jd8F' }); -console.log(listResponseNode.data); +console.log(images.data); ``` ### Request & Response types @@ -43,7 +43,8 @@ const client = new SFCNodes({ bearerToken: process.env['SFC_NODES_BEARER_TOKEN'], // This is the default and can be omitted }); -const listResponseNode: SFCNodes.ListResponseNode = await client.nodes.list(); +const params: SFCNodes.VMs.ImageListParams = { workspace: 'wksp_k3R-nX9vLm7Qp2Yw5Jd8F' }; +const images: SFCNodes.VMs.ImageListResponse = await client.vms.images.list(params); ``` Documentation for each method, request param, and response field are available in docstrings and will appear on hover in most modern editors. @@ -56,15 +57,17 @@ a subclass of `APIError` will be thrown: ```ts -const listResponseNode = await client.nodes.list().catch(async (err) => { - if (err instanceof SFCNodes.APIError) { - console.log(err.status); // 400 - console.log(err.name); // BadRequestError - console.log(err.headers); // {server: 'nginx', ...} - } else { - throw err; - } -}); +const images = await client.vms.images + .list({ workspace: 'wksp_k3R-nX9vLm7Qp2Yw5Jd8F' }) + .catch(async (err) => { + if (err instanceof SFCNodes.APIError) { + console.log(err.status); // 400 + console.log(err.name); // BadRequestError + console.log(err.headers); // {server: 'nginx', ...} + } else { + throw err; + } + }); ``` Error codes are as follows: @@ -96,7 +99,7 @@ const client = new SFCNodes({ }); // Or, configure per-request: -await client.nodes.list({ +await client.vms.images.list({ workspace: 'wksp_k3R-nX9vLm7Qp2Yw5Jd8F' }, { maxRetries: 5, }); ``` @@ -113,7 +116,7 @@ const client = new SFCNodes({ }); // Override per-request: -await client.nodes.list({ +await client.vms.images.list({ workspace: 'wksp_k3R-nX9vLm7Qp2Yw5Jd8F' }, { timeout: 5 * 1000, }); ``` @@ -136,13 +139,17 @@ Unlike `.asResponse()` this method consumes the body, returning once it is parse ```ts const client = new SFCNodes(); -const response = await client.nodes.list().asResponse(); +const response = await client.vms.images + .list({ workspace: 'wksp_k3R-nX9vLm7Qp2Yw5Jd8F' }) + .asResponse(); console.log(response.headers.get('X-My-Header')); console.log(response.statusText); // access the underlying Response object -const { data: listResponseNode, response: raw } = await client.nodes.list().withResponse(); +const { data: images, response: raw } = await client.vms.images + .list({ workspace: 'wksp_k3R-nX9vLm7Qp2Yw5Jd8F' }) + .withResponse(); console.log(raw.headers.get('X-My-Header')); -console.log(listResponseNode.data); +console.log(images.data); ``` ### Logging @@ -222,7 +229,7 @@ parameter. This library doesn't validate at runtime that the request matches the send will be sent as-is. ```ts -client.nodes.list({ +client.vms.images.list({ // ... // @ts-expect-error baz is not yet public baz: 'undocumented option', diff --git a/api.md b/api.md index 5fb1a7e..6f56b10 100644 --- a/api.md +++ b/api.md @@ -1,28 +1,7 @@ # VMs -Types: - -- VMLogsResponse -- VMSSHResponse - -Methods: - -- client.vms.logs({ ...params }) -> VMLogsResponse -- client.vms.ssh({ ...params }) -> VMSSHResponse - ## Script -Types: - -- UserData -- ScriptCreateResponse -- ScriptRetrieveResponse - -Methods: - -- client.vms.script.create({ ...params }) -> ScriptCreateResponse -- client.vms.script.retrieve() -> ScriptRetrieveResponse - ## Images Types: @@ -37,37 +16,4 @@ Methods: # Nodes -Types: - -- AcceleratorType -- CreateNodesRequest -- ErrorContent -- ErrorDetail -- ErrorType -- ExtendNodeRequest -- ListResponseNode -- Node -- NodeType -- Status - -Methods: - -- client.nodes.create({ ...params }) -> ListResponseNode -- client.nodes.list({ ...params }) -> ListResponseNode -- client.nodes.delete(id) -> void -- client.nodes.extend(id, { ...params }) -> Node -- client.nodes.get(id) -> Node -- client.nodes.redeploy(id, { ...params }) -> Node -- client.nodes.release(id) -> Node - # Zones - -Types: - -- ZoneListResponse -- ZoneGetResponse - -Methods: - -- client.zones.list() -> ZoneListResponse -- client.zones.get(id) -> ZoneGetResponse diff --git a/package.json b/package.json index cf2dafa..122ec13 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@sfcompute/nodes-sdk-alpha", - "version": "0.1.0-alpha.31", + "version": "0.1.0-alpha.32", "description": "The official TypeScript library for the SFC Nodes API", "author": "SFC Nodes ", "types": "dist/index.d.ts", diff --git a/src/client.ts b/src/client.ts index bf4babd..a067d9e 100644 --- a/src/client.ts +++ b/src/client.ts @@ -17,25 +17,9 @@ import * as Errors from './core/error'; import * as Uploads from './core/uploads'; import * as API from './resources/index'; import { APIPromise } from './core/api-promise'; -import { - AcceleratorType, - CreateNodesRequest, - ErrorContent, - ErrorDetail, - ErrorType, - ExtendNodeRequest, - ListResponseNode, - Node, - NodeCreateParams, - NodeExtendParams, - NodeListParams, - NodeRedeployParams, - NodeType, - Nodes, - Status, -} from './resources/nodes'; -import { ZoneGetResponse, ZoneListResponse, Zones } from './resources/zones'; -import { VMLogsParams, VMLogsResponse, VMSSHParams, VMSSHResponse, VMs } from './resources/vms/vms'; +import { Nodes } from './resources/nodes'; +import { Zones } from './resources/zones'; +import { VMs } from './resources/vms/vms'; import { type Fetch } from './internal/builtin-types'; import { HeadersLike, NullableHeaders, buildHeaders } from './internal/headers'; import { FinalRequestOptions, RequestOptions } from './internal/request-options'; @@ -687,11 +671,19 @@ export class SFCNodes { return () => controller.abort(); } - private buildBody({ options: { body, headers: rawHeaders } }: { options: FinalRequestOptions }): { + private buildBody({ options }: { options: FinalRequestOptions }): { bodyHeaders: HeadersLike; body: BodyInit | undefined; } { + const { body, headers: rawHeaders } = options; if (!body) { + // A resource method always passes a `body` key when its operation defines a + // request body, even if the caller omitted an optional body param. Keep the + // content-type for those, and only elide it for operations with no body at + // all (e.g. GET/DELETE). + if (body == null && 'body' in options) { + return this.#encoder({ body, headers: buildHeaders([rawHeaders]) }); + } return { bodyHeaders: undefined, body: undefined }; } const headers = buildHeaders([rawHeaders]); @@ -751,19 +743,8 @@ export class SFCNodes { static toFile = Uploads.toFile; - /** - * Manage your Virtual Machines. - */ vms: API.VMs = new API.VMs(this); - /** - * Manage compute nodes. Create, list, extend, and release nodes for your workloads. - */ nodes: API.Nodes = new API.Nodes(this); - /** - * Zones represent physically colocated datacenters. - * Use these endpoints to discover available zones and their capacity, - * hardware specifications, and regional information. - */ zones: API.Zones = new API.Zones(this); } @@ -774,35 +755,9 @@ SFCNodes.Zones = Zones; export declare namespace SFCNodes { export type RequestOptions = Opts.RequestOptions; - export { - VMs as VMs, - type VMLogsResponse as VMLogsResponse, - type VMSSHResponse as VMSSHResponse, - type VMLogsParams as VMLogsParams, - type VMSSHParams as VMSSHParams, - }; - - export { - Nodes as Nodes, - type AcceleratorType as AcceleratorType, - type CreateNodesRequest as CreateNodesRequest, - type ErrorContent as ErrorContent, - type ErrorDetail as ErrorDetail, - type ErrorType as ErrorType, - type ExtendNodeRequest as ExtendNodeRequest, - type ListResponseNode as ListResponseNode, - type Node as Node, - type NodeType as NodeType, - type Status as Status, - type NodeCreateParams as NodeCreateParams, - type NodeListParams as NodeListParams, - type NodeExtendParams as NodeExtendParams, - type NodeRedeployParams as NodeRedeployParams, - }; - - export { - Zones as Zones, - type ZoneListResponse as ZoneListResponse, - type ZoneGetResponse as ZoneGetResponse, - }; + export { VMs as VMs }; + + export { Nodes as Nodes }; + + export { Zones as Zones }; } diff --git a/src/resources/index.ts b/src/resources/index.ts index 30616f8..856526d 100644 --- a/src/resources/index.ts +++ b/src/resources/index.ts @@ -1,21 +1,5 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -export { - Nodes, - type AcceleratorType, - type CreateNodesRequest, - type ErrorContent, - type ErrorDetail, - type ErrorType, - type ExtendNodeRequest, - type ListResponseNode, - type Node, - type NodeType, - type Status, - type NodeCreateParams, - type NodeListParams, - type NodeExtendParams, - type NodeRedeployParams, -} from './nodes'; -export { VMs, type VMLogsResponse, type VMSSHResponse, type VMLogsParams, type VMSSHParams } from './vms/vms'; -export { Zones, type ZoneListResponse, type ZoneGetResponse } from './zones'; +export { Nodes } from './nodes'; +export { VMs } from './vms/vms'; +export { Zones } from './zones'; diff --git a/src/resources/nodes.ts b/src/resources/nodes.ts index 993bb52..a86bc8f 100644 --- a/src/resources/nodes.ts +++ b/src/resources/nodes.ts @@ -1,604 +1,5 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. import { APIResource } from '../core/resource'; -import * as NodesAPI from './nodes'; -import { APIPromise } from '../core/api-promise'; -import { buildHeaders } from '../internal/headers'; -import { RequestOptions } from '../internal/request-options'; -import { path } from '../internal/utils/path'; -/** - * Manage compute nodes. Create, list, extend, and release nodes for your workloads. - */ -export class Nodes extends APIResource { - /** - * Create VM nodes - * - * @example - * ```ts - * const listResponseNode = await client.nodes.create({ - * desired_count: 1, - * max_price_per_node_hour: 1600, - * }); - * ``` - */ - create(body: NodeCreateParams, options?: RequestOptions): APIPromise { - return this._client.post('/v1/nodes', { body, ...options }); - } - - /** - * List all nodes for the authenticated account - * - * @example - * ```ts - * const listResponseNode = await client.nodes.list(); - * ``` - */ - list( - query: NodeListParams | null | undefined = {}, - options?: RequestOptions, - ): APIPromise { - return this._client.get('/v1/nodes', { query, ...options }); - } - - /** - * Delete a node by id. The node cannot be deleted if it has active or pending VMs. - * - * @example - * ```ts - * await client.nodes.delete('id'); - * ``` - */ - delete(id: string, options?: RequestOptions): APIPromise { - return this._client.delete(path`/v1/nodes/${id}`, { - ...options, - headers: buildHeaders([{ Accept: '*/*' }, options?.headers]), - }); - } - - /** - * Purchase additional time to extend the end time of a reserved VM node - * - * @example - * ```ts - * const node = await client.nodes.extend('id', { - * duration_seconds: 7200, - * max_price_per_node_hour: 1000, - * }); - * ``` - */ - extend(id: string, body: NodeExtendParams, options?: RequestOptions): APIPromise { - return this._client.patch(path`/v1/nodes/${id}/extend`, { body, ...options }); - } - - /** - * Retrieve details of a specific node by its ID or name - * - * @example - * ```ts - * const node = await client.nodes.get('id'); - * ``` - */ - get(id: string, options?: RequestOptions): APIPromise { - return this._client.get(path`/v1/nodes/${id}`, options); - } - - /** - * Redeploy a node by replacing its current VM with a new one. Optionally update - * the VM image and cloud init user data. - * - * @example - * ```ts - * const node = await client.nodes.redeploy('id'); - * ``` - */ - redeploy(id: string, body: NodeRedeployParams, options?: RequestOptions): APIPromise { - return this._client.put(path`/v1/nodes/${id}/redeploy`, { body, ...options }); - } - - /** - * Release an auto reserved VM node from its procurement, reducing the - * procurement's desired quantity by 1 - * - * @example - * ```ts - * const node = await client.nodes.release('id'); - * ``` - */ - release(id: string, options?: RequestOptions): APIPromise { - return this._client.patch(path`/v1/nodes/${id}/release`, options); - } -} - -export type AcceleratorType = 'H100' | 'H200'; - -export interface CreateNodesRequest { - desired_count: number; - - /** - * Max price per hour for a node in cents - */ - max_price_per_node_hour: number; - - /** - * **Experimental — subject to change or removal without notice.** Enables - * InfiniBand. Requires hardware in the chosen zone that supports InfiniBand. - */ - _preview_enable_infiniband?: boolean; - - /** - * Allow auto reserved nodes to be created in any zone that meets the requirements - */ - any_zone?: boolean; - - /** - * User script to be executed during the VM's boot process Data should be base64 - * encoded - */ - cloud_init_user_data?: string; - - /** - * End time as Unix timestamp in seconds If provided, end time must be aligned to - * the hour If not provided, the node will be created as an autoreserved node - */ - end_at?: number | null; - - /** - * (Optional) If set, enables forwarding to the VM on port 443. - */ - forward_443?: boolean; - - /** - * Custom image ID to use for the VM instances - */ - image_id?: string; - - /** - * Custom node names Names cannot begin with 'vm*' or 'n*' as this is reserved for - * system-generated IDs Names cannot be numeric strings Names cannot exceed 256 - * characters - */ - names?: Array; - - node_type?: NodeType | null; - - /** - * Start time as Unix timestamp in seconds Optional for reserved nodes. If not - * provided, defaults to now - */ - start_at?: number; - - /** - * Zone to create the nodes in. Required for auto reserved nodes if any_zone is - * false. - */ - zone?: string; -} - -export interface ErrorContent { - message: string; - - type: ErrorType; - - details?: Array; -} - -export interface ErrorDetail { - /** - * Specific error code for this detail - */ - code: string; - - /** - * Human-readable error message - */ - message: string; - - /** - * The field that caused the error (for validation errors) - */ - field?: string | null; -} - -export type ErrorType = - | 'api_error' - | 'invalid_request_error' - | 'authentication_error' - | 'idempotency_error' - | 'conflict' - | 'not_found' - | 'request_timed_out' - | 'forbidden' - | 'not_implemented' - | 'upgrade_required' - | 'payment_required' - | 'service_unavailable' - | 'unprocessable_entity' - | 'gone'; - -export interface ExtendNodeRequest { - /** - * Duration in seconds to extend the node Must be at least 1 hour (3600 seconds) - * and a multiple of 1 hour. - */ - duration_seconds: number; - - /** - * Max price per hour for the extension in cents - */ - max_price_per_node_hour: number; -} - -export interface ListResponseNode { - data: Array; - - object: string; -} - -export namespace ListResponseNode { - export interface Data { - id: string; - - gpu_type: NodesAPI.AcceleratorType; - - name: string; - - node_type: NodesAPI.NodeType; - - object: string; - - owner: string; - - /** - * Node Status - */ - status: NodesAPI.Status; - - /** - * Creation time as Unix timestamp in seconds - */ - created_at?: number | null; - - current_vm?: Data.CurrentVM | null; - - /** - * Deletion time as Unix timestamp in seconds - */ - deleted_at?: number | null; - - /** - * End time as Unix timestamp in seconds - */ - end_at?: number | null; - - /** - * Max price per hour you're willing to pay for a node in cents - */ - max_price_per_node_hour?: number | null; - - procurement_id?: string | null; - - /** - * Start time as Unix timestamp in seconds - */ - start_at?: number | null; - - /** - * Last updated time as Unix timestamp in seconds - */ - updated_at?: number | null; - - vms?: Data.VMs | null; - - zone?: string | null; - } - - export namespace Data { - export interface CurrentVM { - id: string; - - created_at: number; - - end_at: number | null; - - object: string; - - start_at: number | null; - - status: 'Pending' | 'Running' | 'Destroyed' | 'NodeFailure' | 'Unspecified'; - - updated_at: number; - - zone: string; - - image_id?: string | null; - } - - export interface VMs { - data: Array; - - object: string; - } - - export namespace VMs { - export interface Data { - id: string; - - created_at: number; - - end_at: number | null; - - object: string; - - start_at: number | null; - - status: 'Pending' | 'Running' | 'Destroyed' | 'NodeFailure' | 'Unspecified'; - - updated_at: number; - - zone: string; - - image_id?: string | null; - } - } - } -} - -export interface Node { - id: string; - - gpu_type: AcceleratorType; - - name: string; - - node_type: NodeType; - - object: string; - - owner: string; - - /** - * Node Status - */ - status: Status; - - /** - * Creation time as Unix timestamp in seconds - */ - created_at?: number | null; - - current_vm?: Node.CurrentVM | null; - - /** - * Deletion time as Unix timestamp in seconds - */ - deleted_at?: number | null; - - /** - * End time as Unix timestamp in seconds - */ - end_at?: number | null; - - /** - * Max price per hour you're willing to pay for a node in cents - */ - max_price_per_node_hour?: number | null; - - procurement_id?: string | null; - - /** - * Start time as Unix timestamp in seconds - */ - start_at?: number | null; - - /** - * Last updated time as Unix timestamp in seconds - */ - updated_at?: number | null; - - vms?: Node.VMs | null; - - zone?: string | null; -} - -export namespace Node { - export interface CurrentVM { - id: string; - - created_at: number; - - end_at: number | null; - - object: string; - - start_at: number | null; - - status: 'Pending' | 'Running' | 'Destroyed' | 'NodeFailure' | 'Unspecified'; - - updated_at: number; - - zone: string; - - image_id?: string | null; - } - - export interface VMs { - data: Array; - - object: string; - } - - export namespace VMs { - export interface Data { - id: string; - - created_at: number; - - end_at: number | null; - - object: string; - - start_at: number | null; - - status: 'Pending' | 'Running' | 'Destroyed' | 'NodeFailure' | 'Unspecified'; - - updated_at: number; - - zone: string; - - image_id?: string | null; - } - } -} - -export type NodeType = 'autoreserved' | 'reserved'; - -/** - * Node Status - */ -export type Status = - | 'pending' - | 'awaitingcapacity' - | 'running' - | 'released' - | 'terminated' - | 'deleted' - | 'failed' - | 'unknown'; - -export interface NodeCreateParams { - desired_count: number; - - /** - * Max price per hour for a node in cents - */ - max_price_per_node_hour: number; - - /** - * **Experimental — subject to change or removal without notice.** Enables - * InfiniBand. Requires hardware in the chosen zone that supports InfiniBand. - */ - _preview_enable_infiniband?: boolean; - - /** - * Allow auto reserved nodes to be created in any zone that meets the requirements - */ - any_zone?: boolean; - - /** - * User script to be executed during the VM's boot process Data should be base64 - * encoded - */ - cloud_init_user_data?: string; - - /** - * End time as Unix timestamp in seconds If provided, end time must be aligned to - * the hour If not provided, the node will be created as an autoreserved node - */ - end_at?: number | null; - - /** - * (Optional) If set, enables forwarding to the VM on port 443. - */ - forward_443?: boolean; - - /** - * Custom image ID to use for the VM instances - */ - image_id?: string; - - /** - * Custom node names Names cannot begin with 'vm*' or 'n*' as this is reserved for - * system-generated IDs Names cannot be numeric strings Names cannot exceed 256 - * characters - */ - names?: Array; - - node_type?: NodeType | null; - - /** - * Start time as Unix timestamp in seconds Optional for reserved nodes. If not - * provided, defaults to now - */ - start_at?: number; - - /** - * Zone to create the nodes in. Required for auto reserved nodes if any_zone is - * false. - */ - zone?: string; -} - -export interface NodeListParams { - /** - * Filter nodes by node_id Use ?id=n_b1dc52505c6db142&id=n_b1dc52505c6db133 to - * specify multiple IDs. Cannot combine with name or node_type - */ - id?: Array; - - /** - * Filter nodes by their names Use ?name=val1&name=val2 to specify multiple names. - * Cannot combine with id or node_type - */ - name?: Array; - - /** - * Filter nodes by their type Cannot combine with id or name - */ - type?: NodeType; -} - -export interface NodeExtendParams { - /** - * Duration in seconds to extend the node Must be at least 1 hour (3600 seconds) - * and a multiple of 1 hour. - */ - duration_seconds: number; - - /** - * Max price per hour for the extension in cents - */ - max_price_per_node_hour: number; -} - -export interface NodeRedeployParams { - /** - * Update the cloud init user data for VMs running on this node Data should be - * base64 encoded - */ - cloud_init_user_data?: string; - - /** - * Redeploy node with this VM image ID - */ - image_id?: string; - - /** - * If false, then the new VM will inherit any configuration (like image_id, - * cloud_init_user_data) that is left empty in this request from the current VM. - * - * If true, then any configuration left empty will be set as empty in the new VM. - * E.g if cloud_init_user_data is left unset and override_empty is true, then the - * new VM will not have any cloud init user data. override_empty defaults to false. - */ - override_empty?: boolean; -} - -export declare namespace Nodes { - export { - type AcceleratorType as AcceleratorType, - type CreateNodesRequest as CreateNodesRequest, - type ErrorContent as ErrorContent, - type ErrorDetail as ErrorDetail, - type ErrorType as ErrorType, - type ExtendNodeRequest as ExtendNodeRequest, - type ListResponseNode as ListResponseNode, - type Node as Node, - type NodeType as NodeType, - type Status as Status, - type NodeCreateParams as NodeCreateParams, - type NodeListParams as NodeListParams, - type NodeExtendParams as NodeExtendParams, - type NodeRedeployParams as NodeRedeployParams, - }; -} +export class Nodes extends APIResource {} diff --git a/src/resources/vms/images.ts b/src/resources/vms/images.ts index b2637dc..4bb2ba4 100644 --- a/src/resources/vms/images.ts +++ b/src/resources/vms/images.ts @@ -16,11 +16,7 @@ export class Images extends APIResource { * the workspace to list sfc-provided public images instead. */ list(query: ImageListParams, options?: RequestOptions): APIPromise { - return this._client.get('/preview/v2/images', { - query, - defaultBaseURL: 'https://api.sfcompute.com', - ...options, - }); + return this._client.get('/preview/v2/images', { query, ...options }); } /** @@ -29,10 +25,7 @@ export class Images extends APIResource { * Retrieve an image by ID. Returns both user-owned and public images. */ get(id: string, options?: RequestOptions): APIPromise { - return this._client.get(path`/preview/v2/images/${id}`, { - defaultBaseURL: 'https://api.sfcompute.com', - ...options, - }); + return this._client.get(path`/preview/v2/images/${id}`, options); } } @@ -48,6 +41,10 @@ export interface ImageListResponse { export namespace ImageListResponse { export interface Data { + /** + * Accepts the canonical prefix below; additional legacy prefixes are aliased for + * read compatibility. Writes always emit the canonical form. + */ id: string; /** @@ -55,6 +52,11 @@ export namespace ImageListResponse { */ created_at: number; + /** + * Whether this is an sfc-provided public image. + */ + is_public: boolean; + name: string; object: 'image'; @@ -71,6 +73,11 @@ export namespace ImageListResponse { workspace: string; + /** + * The workspace that owns this image. + */ + workspace_id: string; + provider?: string | null; sha256?: string | null; @@ -78,6 +85,10 @@ export namespace ImageListResponse { } export interface ImageGetResponse { + /** + * Accepts the canonical prefix below; additional legacy prefixes are aliased for + * read compatibility. Writes always emit the canonical form. + */ id: string; /** @@ -85,6 +96,11 @@ export interface ImageGetResponse { */ created_at: number; + /** + * Whether this is an sfc-provided public image. + */ + is_public: boolean; + name: string; object: 'image'; @@ -101,6 +117,11 @@ export interface ImageGetResponse { workspace: string; + /** + * The workspace that owns this image. + */ + workspace_id: string; + provider?: string | null; sha256?: string | null; diff --git a/src/resources/vms/index.ts b/src/resources/vms/index.ts index 5678612..cfa8d96 100644 --- a/src/resources/vms/index.ts +++ b/src/resources/vms/index.ts @@ -1,11 +1,5 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. export { Images, type ImageListResponse, type ImageGetResponse, type ImageListParams } from './images'; -export { - Script, - type UserData, - type ScriptCreateResponse, - type ScriptRetrieveResponse, - type ScriptCreateParams, -} from './script'; -export { VMs, type VMLogsResponse, type VMSSHResponse, type VMLogsParams, type VMSSHParams } from './vms'; +export { Script } from './script'; +export { VMs } from './vms'; diff --git a/src/resources/vms/script.ts b/src/resources/vms/script.ts index e70af7b..acfa60c 100644 --- a/src/resources/vms/script.ts +++ b/src/resources/vms/script.ts @@ -1,57 +1,5 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. import { APIResource } from '../../core/resource'; -import { APIPromise } from '../../core/api-promise'; -import { RequestOptions } from '../../internal/request-options'; -/** - * Manage your Virtual Machines. - */ -export class Script extends APIResource { - create(body: ScriptCreateParams, options?: RequestOptions): APIPromise { - return this._client.post('/v0/vms/script', { body, ...options }); - } - - retrieve(options?: RequestOptions): APIPromise { - return this._client.get('/v0/vms/script', options); - } -} - -/** - * if the script is valid utf8 then the response may be in either string, or byte - * form and the client must handle both - */ -export type UserData = string | Array; - -export interface ScriptCreateResponse { - /** - * if the script is valid utf8 then the response may be in either string, or byte - * form and the client must handle both - */ - script: UserData; -} - -export interface ScriptRetrieveResponse { - /** - * if the script is valid utf8 then the response may be in either string, or byte - * form and the client must handle both - */ - script: UserData; -} - -export interface ScriptCreateParams { - /** - * if the script is valid utf8 then the response may be in either string, or byte - * form and the client must handle both - */ - script: UserData; -} - -export declare namespace Script { - export { - type UserData as UserData, - type ScriptCreateResponse as ScriptCreateResponse, - type ScriptRetrieveResponse as ScriptRetrieveResponse, - type ScriptCreateParams as ScriptCreateParams, - }; -} +export class Script extends APIResource {} diff --git a/src/resources/vms/vms.ts b/src/resources/vms/vms.ts index 5e8e580..c48a9ae 100644 --- a/src/resources/vms/vms.ts +++ b/src/resources/vms/vms.ts @@ -4,113 +4,18 @@ import { APIResource } from '../../core/resource'; import * as ImagesAPI from './images'; import { ImageGetResponse, ImageListParams, ImageListResponse, Images } from './images'; import * as ScriptAPI from './script'; -import { Script, ScriptCreateParams, ScriptCreateResponse, ScriptRetrieveResponse, UserData } from './script'; -import { APIPromise } from '../../core/api-promise'; -import { RequestOptions } from '../../internal/request-options'; +import { Script } from './script'; -/** - * Manage your Virtual Machines. - */ export class VMs extends APIResource { script: ScriptAPI.Script = new ScriptAPI.Script(this._client); images: ImagesAPI.Images = new ImagesAPI.Images(this._client); - - logs(query: VMLogsParams, options?: RequestOptions): APIPromise { - return this._client.get('/v0/vms/logs2', { query, ...options }); - } - - ssh(query: VMSSHParams, options?: RequestOptions): APIPromise { - return this._client.get('/v0/vms/ssh', { query, ...options }); - } -} - -export interface VMLogsResponse { - data: Array; -} - -export namespace VMLogsResponse { - export interface Data { - data: Array; - - instance_id: string; - - monotonic_timestamp_nano_sec: number; - - monotonic_timestamp_sec: number; - - /** - * In RFC 3339 format - */ - realtime_timestamp: string; - - seqnum: number; - } -} - -export interface VMSSHResponse { - ssh_hostname: string; - - ssh_port: number; - - /** - * Unix timestamp. - */ - last_attempted_key_update?: number | null; - - /** - * Unix timestamp. - */ - last_successful_key_update?: number | null; - - ssh_host_keys?: Array | null; -} - -export namespace VMSSHResponse { - export interface SSHHostKey { - base64_encoded_key: string; - - key_type: string; - } -} - -export interface VMLogsParams { - instance_id: string; - - order_by: 'seqnum_asc' | 'seqnum_desc'; - - before_realtime_timestamp?: string; - - before_seqnum?: number; - - limit?: number; - - since_realtime_timestamp?: string; - - since_seqnum?: number; -} - -export interface VMSSHParams { - vm_id: string; } VMs.Script = Script; VMs.Images = Images; export declare namespace VMs { - export { - type VMLogsResponse as VMLogsResponse, - type VMSSHResponse as VMSSHResponse, - type VMLogsParams as VMLogsParams, - type VMSSHParams as VMSSHParams, - }; - - export { - Script as Script, - type UserData as UserData, - type ScriptCreateResponse as ScriptCreateResponse, - type ScriptRetrieveResponse as ScriptRetrieveResponse, - type ScriptCreateParams as ScriptCreateParams, - }; + export { Script as Script }; export { Images as Images, diff --git a/src/resources/zones.ts b/src/resources/zones.ts index c083de3..4283ec5 100644 --- a/src/resources/zones.ts +++ b/src/resources/zones.ts @@ -1,128 +1,5 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. import { APIResource } from '../core/resource'; -import * as NodesAPI from './nodes'; -import { APIPromise } from '../core/api-promise'; -import { RequestOptions } from '../internal/request-options'; -import { path } from '../internal/utils/path'; -/** - * Zones represent physically colocated datacenters. - * Use these endpoints to discover available zones and their capacity, - * hardware specifications, and regional information. - */ -export class Zones extends APIResource { - /** - * List all available zones - */ - list(options?: RequestOptions): APIPromise { - return this._client.get('/v0/zones', options); - } - - /** - * Get detailed information about a specific zone - */ - get(id: string, options?: RequestOptions): APIPromise { - return this._client.get(path`/v0/zones/${id}`, options); - } -} - -export interface ZoneListResponse { - data: Array; - - object: string; -} - -export namespace ZoneListResponse { - export interface Data { - /** - * The available capacity on this cluster, in the shape of consecutive - * "availability rectangles". - */ - available_capacity: Array; - - delivery_type: 'K8s' | 'VM'; - - hardware_type: NodesAPI.AcceleratorType; - - interconnect_type: 'Infiniband' | 'None'; - - name: string; - - object: string; - - region: 'NorthAmerica' | 'AsiaPacific' | 'EuropeMiddleEastAfrica'; - - /** - * User-facing zone name (e.g., "Hayes Valley", "Land's End") - */ - display_name?: string | null; - } - - export namespace Data { - export interface AvailableCapacity { - /** - * Unix timestamp. - */ - end_timestamp: number; - - /** - * The number of nodes available during this time period - */ - quantity: number; - - /** - * Unix timestamp. - */ - start_timestamp: number; - } - } -} - -export interface ZoneGetResponse { - /** - * The available capacity on this cluster, in the shape of consecutive - * "availability rectangles". - */ - available_capacity: Array; - - delivery_type: 'K8s' | 'VM'; - - hardware_type: NodesAPI.AcceleratorType; - - interconnect_type: 'Infiniband' | 'None'; - - name: string; - - object: string; - - region: 'NorthAmerica' | 'AsiaPacific' | 'EuropeMiddleEastAfrica'; - - /** - * User-facing zone name (e.g., "Hayes Valley", "Land's End") - */ - display_name?: string | null; -} - -export namespace ZoneGetResponse { - export interface AvailableCapacity { - /** - * Unix timestamp. - */ - end_timestamp: number; - - /** - * The number of nodes available during this time period - */ - quantity: number; - - /** - * Unix timestamp. - */ - start_timestamp: number; - } -} - -export declare namespace Zones { - export { type ZoneListResponse as ZoneListResponse, type ZoneGetResponse as ZoneGetResponse }; -} +export class Zones extends APIResource {} diff --git a/src/version.ts b/src/version.ts index 3ca7b12..537925f 100644 --- a/src/version.ts +++ b/src/version.ts @@ -1 +1 @@ -export const VERSION = '0.1.0-alpha.31'; // x-release-please-version +export const VERSION = '0.1.0-alpha.32'; // x-release-please-version diff --git a/tests/api-resources/nodes.test.ts b/tests/api-resources/nodes.test.ts deleted file mode 100644 index 76a6992..0000000 --- a/tests/api-resources/nodes.test.ts +++ /dev/null @@ -1,138 +0,0 @@ -// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -import SFCNodes from '@sfcompute/nodes-sdk-alpha'; - -const client = new SFCNodes({ - bearerToken: 'My Bearer Token', - baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', -}); - -describe('resource nodes', () => { - // Mock server tests are disabled - test.skip('create: only required params', async () => { - const responsePromise = client.nodes.create({ desired_count: 1, max_price_per_node_hour: 1600 }); - const rawResponse = await responsePromise.asResponse(); - expect(rawResponse).toBeInstanceOf(Response); - const response = await responsePromise; - expect(response).not.toBeInstanceOf(Response); - const dataAndResponse = await responsePromise.withResponse(); - expect(dataAndResponse.data).toBe(response); - expect(dataAndResponse.response).toBe(rawResponse); - }); - - // Mock server tests are disabled - test.skip('create: required and optional params', async () => { - const response = await client.nodes.create({ - desired_count: 1, - max_price_per_node_hour: 1600, - _preview_enable_infiniband: false, - any_zone: false, - cloud_init_user_data: 'aGVsbG8gd29ybGQ=', - end_at: 0, - forward_443: false, - image_id: 'image_1234567890abcdef', - names: ['cuda-crunch'], - node_type: 'autoreserved', - start_at: 1640995200, - zone: 'hayesvalley', - }); - }); - - // Mock server tests are disabled - test.skip('list', async () => { - const responsePromise = client.nodes.list(); - const rawResponse = await responsePromise.asResponse(); - expect(rawResponse).toBeInstanceOf(Response); - const response = await responsePromise; - expect(response).not.toBeInstanceOf(Response); - const dataAndResponse = await responsePromise.withResponse(); - expect(dataAndResponse.data).toBe(response); - expect(dataAndResponse.response).toBe(rawResponse); - }); - - // Mock server tests are disabled - test.skip('list: request options and params are passed correctly', async () => { - // ensure the request options are being passed correctly by passing an invalid HTTP method in order to cause an error - await expect( - client.nodes.list( - { - id: ['string'], - name: ['string'], - type: 'autoreserved', - }, - { path: '/_stainless_unknown_path' }, - ), - ).rejects.toThrow(SFCNodes.NotFoundError); - }); - - // Mock server tests are disabled - test.skip('delete', async () => { - const responsePromise = client.nodes.delete('id'); - const rawResponse = await responsePromise.asResponse(); - expect(rawResponse).toBeInstanceOf(Response); - const response = await responsePromise; - expect(response).not.toBeInstanceOf(Response); - const dataAndResponse = await responsePromise.withResponse(); - expect(dataAndResponse.data).toBe(response); - expect(dataAndResponse.response).toBe(rawResponse); - }); - - // Mock server tests are disabled - test.skip('extend: only required params', async () => { - const responsePromise = client.nodes.extend('id', { - duration_seconds: 7200, - max_price_per_node_hour: 1000, - }); - const rawResponse = await responsePromise.asResponse(); - expect(rawResponse).toBeInstanceOf(Response); - const response = await responsePromise; - expect(response).not.toBeInstanceOf(Response); - const dataAndResponse = await responsePromise.withResponse(); - expect(dataAndResponse.data).toBe(response); - expect(dataAndResponse.response).toBe(rawResponse); - }); - - // Mock server tests are disabled - test.skip('extend: required and optional params', async () => { - const response = await client.nodes.extend('id', { - duration_seconds: 7200, - max_price_per_node_hour: 1000, - }); - }); - - // Mock server tests are disabled - test.skip('get', async () => { - const responsePromise = client.nodes.get('id'); - const rawResponse = await responsePromise.asResponse(); - expect(rawResponse).toBeInstanceOf(Response); - const response = await responsePromise; - expect(response).not.toBeInstanceOf(Response); - const dataAndResponse = await responsePromise.withResponse(); - expect(dataAndResponse.data).toBe(response); - expect(dataAndResponse.response).toBe(rawResponse); - }); - - // Mock server tests are disabled - test.skip('redeploy', async () => { - const responsePromise = client.nodes.redeploy('id', {}); - const rawResponse = await responsePromise.asResponse(); - expect(rawResponse).toBeInstanceOf(Response); - const response = await responsePromise; - expect(response).not.toBeInstanceOf(Response); - const dataAndResponse = await responsePromise.withResponse(); - expect(dataAndResponse.data).toBe(response); - expect(dataAndResponse.response).toBe(rawResponse); - }); - - // Mock server tests are disabled - test.skip('release', async () => { - const responsePromise = client.nodes.release('id'); - const rawResponse = await responsePromise.asResponse(); - expect(rawResponse).toBeInstanceOf(Response); - const response = await responsePromise; - expect(response).not.toBeInstanceOf(Response); - const dataAndResponse = await responsePromise.withResponse(); - expect(dataAndResponse.data).toBe(response); - expect(dataAndResponse.response).toBe(rawResponse); - }); -}); diff --git a/tests/api-resources/vms/script.test.ts b/tests/api-resources/vms/script.test.ts deleted file mode 100644 index cbf87a4..0000000 --- a/tests/api-resources/vms/script.test.ts +++ /dev/null @@ -1,39 +0,0 @@ -// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -import SFCNodes from '@sfcompute/nodes-sdk-alpha'; - -const client = new SFCNodes({ - bearerToken: 'My Bearer Token', - baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', -}); - -describe('resource script', () => { - // Mock server tests are disabled - test.skip('create: only required params', async () => { - const responsePromise = client.vms.script.create({ script: 'string' }); - const rawResponse = await responsePromise.asResponse(); - expect(rawResponse).toBeInstanceOf(Response); - const response = await responsePromise; - expect(response).not.toBeInstanceOf(Response); - const dataAndResponse = await responsePromise.withResponse(); - expect(dataAndResponse.data).toBe(response); - expect(dataAndResponse.response).toBe(rawResponse); - }); - - // Mock server tests are disabled - test.skip('create: required and optional params', async () => { - const response = await client.vms.script.create({ script: 'string' }); - }); - - // Mock server tests are disabled - test.skip('retrieve', async () => { - const responsePromise = client.vms.script.retrieve(); - const rawResponse = await responsePromise.asResponse(); - expect(rawResponse).toBeInstanceOf(Response); - const response = await responsePromise; - expect(response).not.toBeInstanceOf(Response); - const dataAndResponse = await responsePromise.withResponse(); - expect(dataAndResponse.data).toBe(response); - expect(dataAndResponse.response).toBe(rawResponse); - }); -}); diff --git a/tests/api-resources/vms/vms.test.ts b/tests/api-resources/vms/vms.test.ts deleted file mode 100644 index 9f4b608..0000000 --- a/tests/api-resources/vms/vms.test.ts +++ /dev/null @@ -1,52 +0,0 @@ -// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -import SFCNodes from '@sfcompute/nodes-sdk-alpha'; - -const client = new SFCNodes({ - bearerToken: 'My Bearer Token', - baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', -}); - -describe('resource vms', () => { - // Mock server tests are disabled - test.skip('logs: only required params', async () => { - const responsePromise = client.vms.logs({ instance_id: 'instance_id', order_by: 'seqnum_asc' }); - const rawResponse = await responsePromise.asResponse(); - expect(rawResponse).toBeInstanceOf(Response); - const response = await responsePromise; - expect(response).not.toBeInstanceOf(Response); - const dataAndResponse = await responsePromise.withResponse(); - expect(dataAndResponse.data).toBe(response); - expect(dataAndResponse.response).toBe(rawResponse); - }); - - // Mock server tests are disabled - test.skip('logs: required and optional params', async () => { - const response = await client.vms.logs({ - instance_id: 'instance_id', - order_by: 'seqnum_asc', - before_realtime_timestamp: 'before_realtime_timestamp', - before_seqnum: 0, - limit: 1, - since_realtime_timestamp: 'since_realtime_timestamp', - since_seqnum: 0, - }); - }); - - // Mock server tests are disabled - test.skip('ssh: only required params', async () => { - const responsePromise = client.vms.ssh({ vm_id: 'vm_id' }); - const rawResponse = await responsePromise.asResponse(); - expect(rawResponse).toBeInstanceOf(Response); - const response = await responsePromise; - expect(response).not.toBeInstanceOf(Response); - const dataAndResponse = await responsePromise.withResponse(); - expect(dataAndResponse.data).toBe(response); - expect(dataAndResponse.response).toBe(rawResponse); - }); - - // Mock server tests are disabled - test.skip('ssh: required and optional params', async () => { - const response = await client.vms.ssh({ vm_id: 'vm_id' }); - }); -}); diff --git a/tests/api-resources/zones.test.ts b/tests/api-resources/zones.test.ts deleted file mode 100644 index 63b26a7..0000000 --- a/tests/api-resources/zones.test.ts +++ /dev/null @@ -1,34 +0,0 @@ -// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -import SFCNodes from '@sfcompute/nodes-sdk-alpha'; - -const client = new SFCNodes({ - bearerToken: 'My Bearer Token', - baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', -}); - -describe('resource zones', () => { - // Mock server tests are disabled - test.skip('list', async () => { - const responsePromise = client.zones.list(); - const rawResponse = await responsePromise.asResponse(); - expect(rawResponse).toBeInstanceOf(Response); - const response = await responsePromise; - expect(response).not.toBeInstanceOf(Response); - const dataAndResponse = await responsePromise.withResponse(); - expect(dataAndResponse.data).toBe(response); - expect(dataAndResponse.response).toBe(rawResponse); - }); - - // Mock server tests are disabled - test.skip('get', async () => { - const responsePromise = client.zones.get('id'); - const rawResponse = await responsePromise.asResponse(); - expect(rawResponse).toBeInstanceOf(Response); - const response = await responsePromise; - expect(response).not.toBeInstanceOf(Response); - const dataAndResponse = await responsePromise.withResponse(); - expect(dataAndResponse.data).toBe(response); - expect(dataAndResponse.response).toBe(rawResponse); - }); -}); diff --git a/yarn.lock b/yarn.lock index 00842e3..06fc108 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1215,9 +1215,9 @@ baseline-browser-mapping@^2.9.0: integrity sha512-B0xUquLkiGLgHhpPBqvl7GWegWBUNuujQ6kXd/r1U38ElPT6Ok8KZ8e+FpUGEc2ZoRQUzq/aUnaKFc/svWUGSg== brace-expansion@^2.0.2: - version "2.1.0" - resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-2.1.0.tgz#4f41a41190216ee36067ec381526fe9539c4f0ae" - integrity sha512-TN1kCZAgdgweJhWWpgKYrQaMNHcDULHkWwQIspdtjV4Y5aurRdZpjAqn6yX3FPqTA9ngHCc4hJxMAMgGfve85w== + version "2.1.1" + resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-2.1.1.tgz#c68b1c4111c76aae3a6fba55d496cee10c39dad8" + integrity sha512-WR1cURNjuvBLMZBMbqM0UoE+WAfdUcEV1ccD8PVBVOI+Z3ND4+SZbN8RsfT2bMuG1qwz5RFvPukSZm5fF2D5eA== dependencies: balanced-match "^1.0.0"