From 902b483f71b71d8bdad546b003e3b823eec22e92 Mon Sep 17 00:00:00 2001 From: Guy Ben Aharon Date: Wed, 11 Mar 2026 14:11:38 +0200 Subject: [PATCH] fix: node sdk --- .github/workflows/ci.yml | 2 +- .github/workflows/publish.yml | 30 ++++++ .github/workflows/release.yml | 40 +++----- .mise.toml | 2 + README.md | 175 +++++++++++++--------------------- package-lock.json | 4 +- package.json | 2 +- src/client.ts | 44 +++++---- src/container/ca.ts | 40 ++++++++ src/container/container.ts | 36 ------- src/container/index.ts | 62 +++++------- src/container/types.ts | 9 +- src/index.ts | 22 ++--- src/types.ts | 11 ++- 14 files changed, 222 insertions(+), 257 deletions(-) create mode 100644 .github/workflows/publish.yml create mode 100644 .mise.toml create mode 100644 src/container/ca.ts delete mode 100644 src/container/container.ts diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d8fd473..eef9be7 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -11,7 +11,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - node-version: [20, 22] + node-version: [20, 22, 24] steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml new file mode 100644 index 0000000..4ebb4ec --- /dev/null +++ b/.github/workflows/publish.yml @@ -0,0 +1,30 @@ +name: Publish + +on: + push: + tags: + - "v*" + +jobs: + publish: + runs-on: ubuntu-latest + permissions: + contents: read + id-token: write + steps: + - uses: actions/checkout@v4 + + - uses: actions/setup-node@v4 + with: + node-version: 24 + cache: "npm" + registry-url: https://registry.npmjs.org + + - run: npm ci + - run: npm run typecheck + - run: npm run build + + - name: Publish to NPM + run: npm publish --provenance --access public + env: + NODE_AUTH_TOKEN: ${{ secrets.ONECLI_NPM_TOKEN }} diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 9882fd6..4d190be 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -1,35 +1,21 @@ -name: Release Node.js SDK -run-name: Release Node.js SDK +name: Release on: push: - tags: - - "v*.*.*" + branches: + - main + +permissions: + contents: write + pull-requests: write jobs: - publish: - name: Publish NPM + release: runs-on: ubuntu-latest - permissions: - contents: read - id-token: write steps: - - uses: actions/checkout@v4 - - - uses: actions/setup-node@v4 + - name: release-please + id: release + uses: googleapis/release-please-action@v4 with: - node-version: 22 - cache: "npm" - registry-url: https://registry.npmjs.org - - - run: npm ci - - - name: Set NPM version from tag - run: npm version ${GITHUB_REF_NAME#v} --allow-same-version --no-git-tag-version - - - run: npm run build - - - name: Publish to NPM - run: npm publish --provenance --access public - env: - NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} + release-type: node + token: ${{ secrets.ONECLI_OSS_RELEASE }} diff --git a/.mise.toml b/.mise.toml new file mode 100644 index 0000000..6ea5a7e --- /dev/null +++ b/.mise.toml @@ -0,0 +1,2 @@ +[tools] +node = "24" diff --git a/README.md b/README.md index 2d8aa14..c0dcad5 100644 --- a/README.md +++ b/README.md @@ -1,47 +1,35 @@

- @onecli/sdk + @onecli-sdk/node

- Official Node.js SDK for OneCLI. Connect AI agents to external services via plugins. + Official Node.js SDK for OneCLI. Route AI agent traffic through the OneCLI proxy — agents never see real credentials.

Documentation  |  Website  |  - GitHub + GitHub

- - npm version + + npm version - + MIT License - - Node.js version + + Node.js version

--- -## What is OneCLI? - -**OneCLI** (`oc`) is a thin, agent-first CLI that connects AI agents to external services via plugins. The SDK provides a programmatic interface for Node.js applications to interact with OneCLI, allowing containerized agents to access external APIs without exposing credentials. - ## Installation ```bash -npm install @onecli/sdk -``` - -```bash -pnpm add @onecli/sdk -``` - -```bash -yarn add @onecli/sdk +npm install @onecli-sdk/node ``` ## Requirements @@ -52,57 +40,55 @@ yarn add @onecli/sdk ## Quick Start -### Standalone function +### Standalone function (simplest) -The simplest way to use the SDK. A single function that configures Docker containers to use OneCLI: +A single function that fetches config from OneCLI and injects Docker flags: ```typescript -import { applyOneCLIConfig } from "@onecli/sdk"; +import { applyOneCLIConfig } from "@onecli-sdk/node"; const args = ["run", "-i", "--rm", "--name", "my-agent"]; // Fetches container config and pushes -e / -v flags onto args -const active = await applyOneCLIConfig(args, "http://localhost:18080"); +const active = await applyOneCLIConfig(args, process.env.ONECLI_KEY); -// args now contains OneCLI env vars and volume mounts +// args now contains proxy env vars and CA certificate mounts console.log(active); // true if OneCLI was reachable ``` ### Class-based client -For more control, use the `OneCLI` client class: +For more control: ```typescript -import { OneCLI } from "@onecli/sdk"; +import { OneCLI } from "@onecli-sdk/node"; const oc = new OneCLI({ - onecliUrl: "http://localhost:18080", + apiKey: "oc_...", // required: from OneCLI dashboard + url: "http://localhost:3000", // optional: defaults to https://app.onecli.sh }); // Get raw container configuration -const config = await oc.client().getContainerConfig(); -console.log(config.env); // { HTTPS_PROXY: "...", NODE_EXTRA_CA_CERTS: "...", ... } -console.log(config.mounts); // [{ hostPath: "...", containerPath: "...", readonly: true }] +const config = await oc.getContainerConfig(); +console.log(config.env); // { HTTPS_PROXY: "...", HTTP_PROXY: "...", ... } +console.log(config.caCertificate); // PEM content // Or apply directly to Docker run args const args = ["run", "-i", "--rm", "my-image"]; -const active = await oc.client().applyContainerConfig(args); +const active = await oc.applyContainerConfig(args); ``` ### Environment variable -Instead of passing `onecliUrl` explicitly, set the `ONECLI_URL` environment variable: +Instead of passing `url` explicitly, set the `ONECLI_URL` environment variable: ```bash -export ONECLI_URL=http://localhost:18080 +export ONECLI_URL=http://localhost:3000 ``` ```typescript -import { OneCLI } from "@onecli/sdk"; - -// Automatically reads from ONECLI_URL -const oc = new OneCLI(); -const active = await oc.client().applyContainerConfig(args); +const oc = new OneCLI({ apiKey: "oc_..." }); +// Automatically reads from ONECLI_URL, falls back to https://app.onecli.sh ``` ## API Reference @@ -112,69 +98,60 @@ const active = await oc.client().applyContainerConfig(args); Main SDK client. ```typescript -new OneCLI(options?: OneCLIOptions) +new OneCLI(options: OneCLIOptions) ``` -| Option | Type | Default | Description | -| ----------- | -------- | -------------------------- | ------------------------------- | -| `onecliUrl` | `string` | `process.env.ONECLI_URL` | Base URL of the OneCLI instance | -| `timeout` | `number` | `5000` | Request timeout in milliseconds | - -#### `oc.client()` - -Returns the `Client` for container configuration. Throws `OneCLIError` if no OneCLI URL is configured. - ---- +| Option | Type | Required | Default | Description | +| --------- | -------- | -------- | ----------------------------------- | ------------------------------- | +| `apiKey` | `string` | Yes | — | User API key (`oc_...`) | +| `url` | `string` | No | `ONECLI_URL` or `https://app.onecli.sh` | Base URL of the OneCLI instance | +| `timeout` | `number` | No | `5000` | Request timeout in milliseconds | -### `Client` - -Manages communication with the OneCLI `/container-config` endpoint. - -#### `client.getContainerConfig()` +#### `oc.getContainerConfig()` Fetch the raw container configuration from OneCLI. ```typescript -const config = await oc.client().getContainerConfig(); -// Returns: { env: Record, mounts: ContainerMount[] } +const config = await oc.getContainerConfig(); +// Returns: { env, caCertificate, caCertificateContainerPath } ``` -**Throws** `OneCLIRequestError` if OneCLI returns a non-200 response. +**Throws** `OneCLIRequestError` on non-200 response. -#### `client.applyContainerConfig(args, options?)` +#### `oc.applyContainerConfig(args, options?)` -Fetch the container config and push Docker flags onto the `args` array. Returns `true` if config was applied, `false` if OneCLI was unreachable. +Fetch config and push Docker flags onto the `args` array. Returns `true` on success, `false` on failure (graceful degradation). ```typescript -const active = await oc.client().applyContainerConfig(args, { +const active = await oc.applyContainerConfig(args, { combineCaBundle: true, // Merge system + OneCLI CAs (default: true) addHostMapping: true, // Add --add-host on Linux (default: true) }); ``` -| Option | Type | Default | Description | -| ---------------- | --------- | ------- | ----------------------------------------------------- | -| `combineCaBundle`| `boolean` | `true` | Build combined CA bundle for system-wide trust | -| `addHostMapping` | `boolean` | `true` | Add `host.docker.internal` mapping on Linux | +| Option | Type | Default | Description | +| ---------------- | --------- | ------- | ---------------------------------------------- | +| `combineCaBundle`| `boolean` | `true` | Build combined CA bundle for system-wide trust | +| `addHostMapping` | `boolean` | `true` | Add `host.docker.internal` mapping on Linux | **What it does:** -1. Fetches `/container-config` from OneCLI -2. Pushes `-e KEY=VALUE` for each environment variable -3. Pushes `-v host:container[:ro]` for each mount -4. Builds a combined CA bundle (system CAs + OneCLI CA) so all tools trust OneCLI +1. Fetches `/api/container-config` with `Authorization: Bearer {apiKey}` +2. Pushes `-e KEY=VALUE` for each server-controlled environment variable +3. Writes CA certificate to a temp file and mounts it into the container +4. Builds a combined CA bundle (system CAs + OneCLI CA) so curl, Python, Go, etc. also trust OneCLI 5. Adds `--add-host host.docker.internal:host-gateway` on Linux --- -### `applyOneCLIConfig(args, onecliUrl?)` +### `applyOneCLIConfig(args, apiKey, url?)` -Standalone convenience function. Equivalent to creating a `Client` and calling `applyContainerConfig`. +Standalone convenience function. Creates an `OneCLI` client internally. ```typescript -import { applyOneCLIConfig } from "@onecli/sdk"; +import { applyOneCLIConfig } from "@onecli-sdk/node"; -const active = await applyOneCLIConfig(args, "http://localhost:18080"); -// Pass undefined/null to skip (returns false immediately) +const active = await applyOneCLIConfig(args, process.env.ONECLI_KEY); +// Pass undefined/null apiKey to skip (returns false immediately) ``` --- @@ -183,34 +160,25 @@ const active = await applyOneCLIConfig(args, "http://localhost:18080"); #### `OneCLIError` -General SDK error. +General SDK error (e.g. missing `apiKey`). ```typescript -import { OneCLIError } from "@onecli/sdk"; - -try { - oc.client(); // throws if no OneCLI URL configured -} catch (error) { - if (error instanceof OneCLIError) { - console.error(error.message); - } -} +import { OneCLIError } from "@onecli-sdk/node"; ``` #### `OneCLIRequestError` -HTTP request error with context. +HTTP request error with `url` and `statusCode` properties. ```typescript -import { OneCLIRequestError } from "@onecli/sdk"; +import { OneCLIRequestError } from "@onecli-sdk/node"; try { - await oc.client().getContainerConfig(); + await oc.getContainerConfig(); } catch (error) { if (error instanceof OneCLIRequestError) { console.error(error.url); // Request URL console.error(error.statusCode); // HTTP status code - console.error(error.message); // [URL=...] [StatusCode=...] ... } } ``` @@ -219,44 +187,31 @@ try { ### Types -All types are exported for use in your own code: - ```typescript import type { OneCLIOptions, ContainerConfig, - ContainerMount, ApplyContainerConfigOptions, -} from "@onecli/sdk"; +} from "@onecli-sdk/node"; ``` ## How It Works -OneCLI runs on the host machine and acts as a MITM proxy for containerized agents. When a container makes HTTPS requests to intercepted domains (e.g. `api.anthropic.com`), OneCLI: +OneCLI acts as a MITM proxy for containerized agents. When a container makes HTTPS requests to intercepted domains (e.g. `api.anthropic.com`), OneCLI: 1. Terminates TLS using a local CA certificate -2. Inspects the request and injects real credentials (replacing placeholder tokens) +2. Inspects the request and injects real credentials 3. Forwards the request to the upstream service -4. Returns the response to the container - -This means **containers never see real API keys**. They only have placeholder tokens that OneCLI swaps out transparently. -The SDK configures containers with the right environment variables (`HTTPS_PROXY`, `NODE_EXTRA_CA_CERTS`) and volume mounts (OneCLI CA certificate) so this works automatically. +**Containers never see real API keys.** The SDK configures containers with the right environment variables (`HTTPS_PROXY`, `HTTP_PROXY`, `NODE_EXTRA_CA_CERTS`) and CA certificate mounts so this works automatically. ## Development ```bash -# Install dependencies -npm install - -# Build -npm run build - -# Type-check without emitting -npm run typecheck - -# Watch mode -npm run dev +npm install # Install dependencies +npm run build # Build CJS + ESM +npm run typecheck # Type-check without emitting +npm run dev # Watch mode ``` ## License diff --git a/package-lock.json b/package-lock.json index f9aab34..2f3592a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,11 +1,11 @@ { - "name": "@onecli/sdk", + "name": "@onecli-sh/sdk", "version": "0.1.0", "lockfileVersion": 3, "requires": true, "packages": { "": { - "name": "@onecli/sdk", + "name": "@onecli-sh/sdk", "version": "0.1.0", "license": "MIT", "devDependencies": { diff --git a/package.json b/package.json index f3b90bc..16a1d1f 100644 --- a/package.json +++ b/package.json @@ -1,5 +1,5 @@ { - "name": "@onecli-sh/sdk", + "name": "@onecli-sdk/node", "version": "0.1.0", "description": "Official Node.js SDK for OneCLI. Connect AI agents to external services via the OneCLI proxy.", "main": "./lib/index.js", diff --git a/src/client.ts b/src/client.ts index f84ddd1..1978043 100644 --- a/src/client.ts +++ b/src/client.ts @@ -1,34 +1,40 @@ import { OneCLIError } from "./errors.js"; -import { Client } from "./container/index.js"; +import { ContainerClient } from "./container/index.js"; import type { OneCLIOptions } from "./types.js"; +import type { ApplyContainerConfigOptions, ContainerConfig } from "./container/types.js"; +const DEFAULT_URL = "https://app.onecli.sh"; const DEFAULT_TIMEOUT = 5000; export class OneCLI { - private onecliUrl: string | undefined; - private timeout: number; + private containerClient: ContainerClient; - private _client: Client | undefined; + constructor(options: OneCLIOptions) { + if (!options.apiKey) { + throw new OneCLIError("apiKey is required."); + } - constructor(options?: OneCLIOptions) { - this.onecliUrl = options?.onecliUrl ?? process.env.ONECLI_URL; - this.timeout = options?.timeout ?? DEFAULT_TIMEOUT; + const url = options.url ?? process.env.ONECLI_URL ?? DEFAULT_URL; + const timeout = options.timeout ?? DEFAULT_TIMEOUT; - if (this.onecliUrl) { - this._client = new Client(this.onecliUrl, this.timeout); - } + this.containerClient = new ContainerClient(url, options.apiKey, timeout); } /** - * Access the OneCLI client for container configuration. - * Throws if no OneCLI URL was configured. + * Fetch the raw container configuration from OneCLI. */ - client = (): Client => { - if (!this._client) { - throw new OneCLIError( - 'No OneCLI URL configured. Pass { onecliUrl: "..." } to OneCLI() or set the ONECLI_URL environment variable.', - ); - } - return this._client; + getContainerConfig = (): Promise => { + return this.containerClient.getContainerConfig(); + }; + + /** + * Fetch config and apply `-e` / `-v` flags to a Docker `run` argument array. + * Returns `true` on success, `false` on failure (graceful degradation). + */ + applyContainerConfig = ( + args: string[], + options?: ApplyContainerConfigOptions, + ): Promise => { + return this.containerClient.applyContainerConfig(args, options); }; } diff --git a/src/container/ca.ts b/src/container/ca.ts new file mode 100644 index 0000000..0d526b9 --- /dev/null +++ b/src/container/ca.ts @@ -0,0 +1,40 @@ +import { readFileSync, writeFileSync } from "fs"; +import { tmpdir } from "os"; +import { join } from "path"; + +/** Host-side system CA bundle locations (in priority order). */ +const SYSTEM_CA_PATHS = [ + "/etc/ssl/cert.pem", // macOS + "/etc/ssl/certs/ca-certificates.crt", // Debian / Ubuntu + "/etc/pki/tls/certs/ca-bundle.crt", // RHEL / CentOS / Fedora +]; + +/** + * Write the proxy CA certificate PEM to a temp file on the host. + * Returns the path to the written file. + */ +export function writeCaCertificate(caCertificate: string): string { + const outPath = join(tmpdir(), "onecli-proxy-ca.pem"); + writeFileSync(outPath, caCertificate); + return outPath; +} + +/** + * Build a combined CA bundle (system CAs + OneCLI proxy CA) on the host. + * Returns the path to the combined file, or `null` on failure. + */ +export function buildCombinedCaBundle(caCertificate: string): string | null { + for (const sysPath of SYSTEM_CA_PATHS) { + try { + const sysCa = readFileSync(sysPath, "utf8"); + const combined = sysCa.trimEnd() + "\n" + caCertificate.trimEnd() + "\n"; + const outPath = join(tmpdir(), "onecli-combined-ca.pem"); + writeFileSync(outPath, combined); + return outPath; + } catch { + continue; + } + } + + return null; +} diff --git a/src/container/container.ts b/src/container/container.ts deleted file mode 100644 index ad2a658..0000000 --- a/src/container/container.ts +++ /dev/null @@ -1,36 +0,0 @@ -import { readFileSync, writeFileSync } from "fs"; -import { dirname, join } from "path"; - -/** Host-side system CA bundle locations (in priority order). */ -const SYSTEM_CA_PATHS = [ - "/etc/ssl/cert.pem", // macOS - "/etc/ssl/certs/ca-certificates.crt", // Debian / Ubuntu - "/etc/pki/tls/certs/ca-bundle.crt", // RHEL / CentOS / Fedora -]; - -/** - * Build a combined CA bundle (system CAs + OneCLI CA) on the host. - * Returns the path to the combined file, or `null` on failure. - */ -export function buildCombinedCaBundle(onecliCaHostPath: string): string | null { - let onecliCa: string; - try { - onecliCa = readFileSync(onecliCaHostPath, "utf8"); - } catch { - return null; - } - - for (const sysPath of SYSTEM_CA_PATHS) { - try { - const sysCa = readFileSync(sysPath, "utf8"); - const combined = sysCa.trimEnd() + "\n" + onecliCa.trimEnd() + "\n"; - const outPath = join(dirname(onecliCaHostPath), "combined-ca.crt"); - writeFileSync(outPath, combined); - return outPath; - } catch { - continue; - } - } - - return null; -} diff --git a/src/container/index.ts b/src/container/index.ts index 375b0d8..8d195da 100644 --- a/src/container/index.ts +++ b/src/container/index.ts @@ -1,29 +1,27 @@ import { OneCLIError, OneCLIRequestError, toOneCLIError } from "../errors.js"; -import { buildCombinedCaBundle } from "./container.js"; -import type { - ApplyContainerConfigOptions, - ContainerConfig, - ContainerMount, -} from "./types.js"; +import { writeCaCertificate, buildCombinedCaBundle } from "./ca.js"; +import type { ApplyContainerConfigOptions, ContainerConfig } from "./types.js"; -export class Client { - private onecliUrl: string; +export class ContainerClient { + private baseUrl: string; + private apiKey: string; private timeout: number; - constructor(onecliUrl: string, timeout: number) { - this.onecliUrl = onecliUrl.replace(/\/+$/, ""); + constructor(baseUrl: string, apiKey: string, timeout: number) { + this.baseUrl = baseUrl.replace(/\/+$/, ""); + this.apiKey = apiKey; this.timeout = timeout; } /** * Fetch the raw container configuration from OneCLI. - * Returns the env vars and mounts to inject into the container. */ getContainerConfig = async (): Promise => { - const url = `${this.onecliUrl}/container-config`; + const url = `${this.baseUrl}/api/container-config`; try { const res = await fetch(url, { + headers: { Authorization: `Bearer ${this.apiKey}` }, signal: AbortSignal.timeout(this.timeout), }); @@ -50,10 +48,8 @@ export class Client { * Fetch the container config from OneCLI and push the corresponding * `-e` and `-v` flags onto the Docker `run` argument array. * - * Returns `true` if OneCLI was reachable and config was applied. - * - * @param args The Docker `run` argument array to mutate. - * @param options Optional configuration for the apply behavior. + * Returns `true` if OneCLI was reachable and config was applied, + * `false` otherwise (graceful degradation). */ applyContainerConfig = async ( args: string[], @@ -68,40 +64,28 @@ export class Client { return false; } - // Inject environment variables + // Inject server-controlled environment variables for (const [key, value] of Object.entries(config.env)) { args.push("-e", `${key}=${value}`); } - // Inject volume mounts - for (const mount of config.mounts) { - if (mount.readonly) { - args.push("-v", `${mount.hostPath}:${mount.containerPath}:ro`); - } else { - args.push("-v", `${mount.hostPath}:${mount.containerPath}`); - } - } + // Write CA certificate to host temp file and mount into container + const hostCaPath = writeCaCertificate(config.caCertificate); + args.push( + "-v", + `${hostCaPath}:${config.caCertificateContainerPath}:ro`, + ); // Build combined CA bundle for system-wide trust (curl, Python, Go, etc.) - // NODE_EXTRA_CA_CERTS handles Node.js; SSL_CERT_FILE handles everything else. if (combineCaBundle) { - const nodeExtraCa = config.env["NODE_EXTRA_CA_CERTS"]; - if (nodeExtraCa) { - const caMount = config.mounts.find( - (m) => m.containerPath === nodeExtraCa, - ); - if (caMount) { - const combinedPath = buildCombinedCaBundle(caMount.hostPath); - if (combinedPath) { - args.push("-e", "SSL_CERT_FILE=/tmp/combined-ca.crt"); - args.push("-v", `${combinedPath}:/tmp/combined-ca.crt:ro`); - } - } + const combinedPath = buildCombinedCaBundle(config.caCertificate); + if (combinedPath) { + args.push("-e", "SSL_CERT_FILE=/tmp/onecli-combined-ca.pem"); + args.push("-v", `${combinedPath}:/tmp/onecli-combined-ca.pem:ro`); } } // On Linux, host.docker.internal needs explicit mapping. - // macOS Docker Desktop provides it automatically. if (addHostMapping && process.platform === "linux") { args.push("--add-host", "host.docker.internal:host-gateway"); } diff --git a/src/container/types.ts b/src/container/types.ts index b257a92..f5fc5b0 100644 --- a/src/container/types.ts +++ b/src/container/types.ts @@ -1,12 +1,7 @@ -export interface ContainerMount { - hostPath: string; - containerPath: string; - readonly: boolean; -} - export interface ContainerConfig { env: Record; - mounts: ContainerMount[]; + caCertificate: string; + caCertificateContainerPath: string; } export interface ApplyContainerConfigOptions { diff --git a/src/index.ts b/src/index.ts index 5f9fc62..ebffe51 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,11 +1,10 @@ export { OneCLI } from "./client.js"; -export { Client } from "./container/index.js"; +export { ContainerClient } from "./container/index.js"; export { OneCLIError, OneCLIRequestError } from "./errors.js"; export type { OneCLIOptions } from "./types.js"; export type { ContainerConfig, - ContainerMount, ApplyContainerConfigOptions, } from "./container/types.js"; @@ -13,24 +12,25 @@ export type { // Standalone convenience function // --------------------------------------------------------------------------- -import { Client } from "./container/index.js"; +import { OneCLI } from "./client.js"; /** * Standalone helper: fetch the container config from OneCLI and push the * corresponding `-e` and `-v` flags onto a Docker `run` argument array. * * Returns `true` if OneCLI was reachable and config was applied, - * `false` otherwise. + * `false` otherwise (including when `apiKey` is falsy). * - * @param args Docker `run` argument array to mutate. - * @param onecliUrl Base URL of OneCLI (e.g. "http://localhost:18080"). - * Pass `undefined` / `null` to skip (returns `false`). + * @param args Docker `run` argument array to mutate. + * @param apiKey User API key (`oc_...`). Pass `undefined` / empty to skip. + * @param url Base URL of OneCLI. Defaults to `ONECLI_URL` env or `https://app.onecli.sh`. */ export async function applyOneCLIConfig( args: string[], - onecliUrl?: string | null, + apiKey?: string | null, + url?: string, ): Promise { - if (!onecliUrl) return false; - const client = new Client(onecliUrl, 3000); - return client.applyContainerConfig(args); + if (!apiKey) return false; + const oc = new OneCLI({ apiKey, url }); + return oc.applyContainerConfig(args); } diff --git a/src/types.ts b/src/types.ts index 54bdfac..3a4eb5b 100644 --- a/src/types.ts +++ b/src/types.ts @@ -1,11 +1,14 @@ export interface OneCLIOptions { + /** + * User API key from the OneCLI dashboard (starts with `oc_`). + */ + apiKey: string; + /** * Base URL of the OneCLI instance. - * Example: "http://localhost:18080" - * - * Can also be set via the `ONECLI_URL` environment variable. + * Falls back to `ONECLI_URL` env var, then `https://app.onecli.sh`. */ - onecliUrl?: string; + url?: string; /** * Request timeout in milliseconds.