@cavsnode/cavs-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.
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/errors.ts","../src/auth.ts","../src/telemetry.ts","../src/http.ts","../src/uri.ts","../src/resources/artifacts.ts","../src/transfer.ts","../src/resources/snapshots.ts","../src/resources/releases.ts","../src/resources/runs.ts","../src/resources/lineage.ts","../src/resources/usage.ts","../src/resources/serviceAccounts.ts","../src/client.ts"],"sourcesContent":["/**\n * Typed error hierarchy for the CAVS SDK.\n *\n * The server returns errors using the envelope described in CONTRACT.md §8:\n *\n * { \"error\": { \"code\": \"quota_exceeded\", \"message\": \"human readable\" } }\n *\n * {@link toCAVSError} maps an HTTP status + envelope to the correct subclass.\n * All errors extend {@link CAVSError}. Tokens and presigned URLs are NEVER\n * included in error messages (CONTRACT.md §2).\n */\n\nexport interface CAVSErrorOptions {\n /** Machine-readable error code from the server envelope. */\n code?: string;\n /** HTTP status code, when the error originated from a response. */\n status?: number;\n /** Server-supplied request id (from `X-Request-Id`/`X-CAVS-Request-Id`), if any. */\n requestId?: string;\n /** Underlying cause (e.g. a network error). */\n cause?: unknown;\n /** Retry-After hint in milliseconds, when the server supplied one. */\n retryAfterMs?: number;\n}\n\n/** Base class for every error thrown by the SDK. */\nexport class CAVSError extends Error {\n readonly code?: string;\n readonly status?: number;\n readonly requestId?: string;\n readonly retryAfterMs?: number;\n\n constructor(message: string, options: CAVSErrorOptions = {}) {\n super(message, options.cause !== undefined ? { cause: options.cause } : undefined);\n this.name = new.target.name;\n this.code = options.code;\n this.status = options.status;\n this.requestId = options.requestId;\n this.retryAfterMs = options.retryAfterMs;\n // Restore prototype chain when compiled down to ES5-ish targets.\n Object.setPrototypeOf(this, new.target.prototype);\n }\n}\n\n/** 401 — the token is missing, malformed or rejected. */\nexport class AuthenticationError extends CAVSError {}\n/** 403 — the token is valid but not permitted to perform the action. */\nexport class AuthorizationError extends CAVSError {}\n/** 404 — the requested resource does not exist. */\nexport class NotFoundError extends CAVSError {}\n/** 409 — the request conflicts with the current state of the resource. */\nexport class ConflictError extends CAVSError {}\n/** 429 — rate limited. Honour {@link CAVSError.retryAfterMs}. */\nexport class RateLimitError extends CAVSError {}\n/** 413 / 402 — a storage/billing quota has been exceeded. */\nexport class QuotaExceededError extends CAVSError {}\n/** A downloaded object's sha256 did not match its oid. */\nexport class ChecksumError extends CAVSError {}\n/** The upload data-plane transfer failed. */\nexport class UploadError extends CAVSError {}\n/** The download data-plane transfer failed. */\nexport class DownloadError extends CAVSError {}\n/** 5xx / network / timeout — a transient failure that is retried. */\nexport class TemporaryServiceError extends CAVSError {}\n\ninterface ErrorEnvelope {\n error?: { code?: string; message?: string };\n}\n\n/**\n * Map an HTTP status code and (optional) parsed error envelope to the correct\n * {@link CAVSError} subclass.\n */\nexport function toCAVSError(\n status: number,\n body: unknown,\n extra: { requestId?: string; retryAfterMs?: number } = {},\n): CAVSError {\n const envelope = (body ?? {}) as ErrorEnvelope;\n const code = envelope.error?.code;\n const message = envelope.error?.message ?? `CAVS request failed with status ${status}`;\n const opts: CAVSErrorOptions = {\n code,\n status,\n requestId: extra.requestId,\n retryAfterMs: extra.retryAfterMs,\n };\n\n switch (status) {\n case 401:\n return new AuthenticationError(message, opts);\n case 403:\n return new AuthorizationError(message, opts);\n case 404:\n return new NotFoundError(message, opts);\n case 409:\n return new ConflictError(message, opts);\n case 402:\n case 413:\n return new QuotaExceededError(message, opts);\n case 429:\n return new RateLimitError(message, opts);\n case 426:\n // Version unsupported → base CAVSError carrying the deprecation message.\n return new CAVSError(message, opts);\n default:\n if (status >= 500) {\n return new TemporaryServiceError(message, opts);\n }\n // quota_exceeded can also arrive with a non-standard status.\n if (code === \"quota_exceeded\") {\n return new QuotaExceededError(message, opts);\n }\n return new CAVSError(message, opts);\n }\n}\n","/**\n * Token resolution and redaction (CONTRACT.md §2).\n *\n * Resolution order: explicit argument → `$CAVS_TOKEN` → (no config file in this\n * SDK). Tokens are opaque; only the prefix (`cavs_sk_`, `cavs_pat_`, …) is\n * meaningful. The token is NEVER printed in full — {@link redactToken} produces a\n * safe form such as `cavs_sk_…abcd`.\n */\n\nimport { AuthenticationError } from \"./errors.js\";\n\nconst KNOWN_PREFIX = /^(cavs_[a-z]+_)/;\n\n/**\n * Resolve the auth token from an explicit value or the environment.\n *\n * @throws {AuthenticationError} when no token can be found.\n */\nexport function resolveToken(\n explicit?: string,\n env: NodeJS.ProcessEnv = process.env,\n): string {\n const token = explicit ?? env.CAVS_TOKEN;\n if (!token || token.trim() === \"\") {\n throw new AuthenticationError(\n \"No CAVS token provided. Pass { token } or set the CAVS_TOKEN environment variable.\",\n );\n }\n return token.trim();\n}\n\n/**\n * Redact a token to a form safe for logs and error messages, e.g.\n * `cavs_sk_…abcd`. Returns `…` for empty input. The full token is never\n * exposed. Any short/unknown token is redacted to its last four characters.\n */\nexport function redactToken(token: string | undefined | null): string {\n if (!token) {\n return \"…\";\n }\n const last4 = token.length >= 4 ? token.slice(-4) : token;\n const prefixMatch = KNOWN_PREFIX.exec(token);\n if (prefixMatch) {\n return `${prefixMatch[1]}…${last4}`;\n }\n return `…${last4}`;\n}\n","/**\n * Telemetry headers sent on every request (CONTRACT.md §7).\n *\n * User-Agent: cavs-node/<version>\n * X-CAVS-Client: javascript-sdk\n * X-CAVS-Integration: <javascript-sdk by default; integrations override>\n * X-CAVS-Integration-Version: <version>\n * X-CAVS-Run-ID: <optional correlation id>\n */\n\n/** The SDK version, embedded in the User-Agent and integration-version headers. */\nexport const VERSION = \"0.1.0\";\n\n/** Client identifier reported to the server. */\nexport const CLIENT_ID = \"javascript-sdk\";\n\nexport interface TelemetryOptions {\n /** Integration id; defaults to {@link CLIENT_ID}. Integrations built on top override it. */\n integration?: string;\n /** Version of the integration; defaults to the SDK {@link VERSION}. */\n integrationVersion?: string;\n /** Optional run / correlation id, surfaced as `X-CAVS-Run-ID`. */\n runId?: string;\n}\n\n/** Build the telemetry headers for a request. */\nexport function telemetryHeaders(opts: TelemetryOptions = {}): Record<string, string> {\n const headers: Record<string, string> = {\n \"User-Agent\": `cavs-node/${VERSION}`,\n \"X-CAVS-Client\": CLIENT_ID,\n \"X-CAVS-Integration\": opts.integration ?? CLIENT_ID,\n \"X-CAVS-Integration-Version\": opts.integrationVersion ?? VERSION,\n };\n if (opts.runId) {\n headers[\"X-CAVS-Run-ID\"] = opts.runId;\n }\n return headers;\n}\n","/**\n * HTTP transport built on the global `fetch` (CONTRACT.md §7, §8).\n *\n * Responsibilities:\n * - Attach auth + telemetry headers and an optional Idempotency-Key.\n * - Retry <= `maxRetries` times on 429 / 5xx / network errors with exponential\n * backoff + jitter, honouring `Retry-After` (capped ~30s).\n * - Enforce a request timeout via AbortController and propagate external\n * cancellation.\n * - Bound redirects (<= 5).\n * - Map the server error envelope to a typed {@link CAVSError}.\n * - Never log tokens or presigned URLs.\n */\n\nimport { CAVSError, TemporaryServiceError, toCAVSError } from \"./errors.js\";\nimport { telemetryHeaders, type TelemetryOptions } from \"./telemetry.js\";\n\n/** Injectable fetch implementation (defaults to the global `fetch`). */\nexport type FetchLike = typeof fetch;\n\n/** The request-body type accepted by `fetch` (derived to avoid needing the DOM lib). */\nexport type BodyInit = NonNullable<RequestInit[\"body\"]>;\n\n/** A no-arg factory that produces a fresh request body — required so streamed\n * bodies can be rewound and resent on retry. */\nexport type BodyFactory = () => BodyInit;\n\nexport interface HttpClientOptions {\n baseUrl: string;\n token: string;\n fetch?: FetchLike;\n telemetry?: TelemetryOptions;\n /** Max retries on 429/5xx/network (default 4). Total attempts = maxRetries + 1. */\n maxRetries?: number;\n /** Max redirects to follow (default 5). */\n maxRedirects?: number;\n /** Per-attempt timeout in ms (default 30000). */\n timeoutMs?: number;\n /** Base backoff in ms (default 200). Set to 0 in tests to disable delays. */\n retryBaseMs?: number;\n /** Cap on any single backoff/Retry-After wait in ms (default 30000). */\n maxBackoffMs?: number;\n /** Called (never throws) when the server sends `X-CAVS-Deprecation`. */\n onDeprecation?: (message: string) => void;\n /** Injectable sleep (for tests). */\n sleepImpl?: (ms: number) => Promise<void>;\n}\n\nexport interface RequestOptions {\n method?: string;\n path: string;\n query?: Record<string, string | number | boolean | undefined>;\n body?: unknown;\n headers?: Record<string, string>;\n idempotencyKey?: string;\n signal?: AbortSignal;\n}\n\nconst RETRYABLE_STATUS = (status: number) => status === 429 || status >= 500;\n\nexport class HttpClient {\n private readonly baseUrl: string;\n private readonly token: string;\n private readonly fetchImpl: FetchLike;\n private readonly telemetry: TelemetryOptions;\n readonly maxRetries: number;\n readonly maxRedirects: number;\n readonly timeoutMs: number;\n private readonly retryBaseMs: number;\n private readonly maxBackoffMs: number;\n private readonly onDeprecation: (message: string) => void;\n private readonly sleepImpl: (ms: number) => Promise<void>;\n\n constructor(opts: HttpClientOptions) {\n this.baseUrl = opts.baseUrl.replace(/\\/+$/, \"\");\n this.token = opts.token;\n this.fetchImpl = opts.fetch ?? fetch;\n this.telemetry = opts.telemetry ?? {};\n this.maxRetries = opts.maxRetries ?? 4;\n this.maxRedirects = opts.maxRedirects ?? 5;\n this.timeoutMs = opts.timeoutMs ?? 30_000;\n this.retryBaseMs = opts.retryBaseMs ?? 200;\n this.maxBackoffMs = opts.maxBackoffMs ?? 30_000;\n this.onDeprecation =\n opts.onDeprecation ??\n ((message: string) => {\n console.warn(`[cavs] deprecation: ${message}`);\n });\n this.sleepImpl =\n opts.sleepImpl ?? ((ms) => new Promise((resolve) => setTimeout(resolve, ms)));\n }\n\n /** Build the standard header set for a control-plane request. */\n private baseHeaders(extra?: Record<string, string>): Record<string, string> {\n return {\n Authorization: `Bearer ${this.token}`,\n Accept: \"application/json\",\n ...telemetryHeaders(this.telemetry),\n ...extra,\n };\n }\n\n private buildUrl(path: string, query?: RequestOptions[\"query\"]): string {\n const suffix = path.startsWith(\"/\") ? path : `/${path}`;\n const full = new URL(this.baseUrl + suffix);\n if (query) {\n for (const [key, value] of Object.entries(query)) {\n if (value !== undefined) {\n full.searchParams.set(key, String(value));\n }\n }\n }\n return full.toString();\n }\n\n /** Perform a JSON control-plane request with retries and typed errors. */\n async requestJson<T = unknown>(opts: RequestOptions): Promise<T> {\n const method = opts.method ?? \"GET\";\n const url = this.buildUrl(opts.path, opts.query);\n const headers = this.baseHeaders(opts.headers);\n let body: BodyInit | undefined;\n if (opts.body !== undefined) {\n body = JSON.stringify(opts.body);\n headers[\"Content-Type\"] = \"application/json\";\n }\n if (opts.idempotencyKey) {\n headers[\"Idempotency-Key\"] = opts.idempotencyKey;\n }\n\n const res = await this.executeWithRetry(url, { method, headers, body }, opts.signal);\n return this.parseJson<T>(res);\n }\n\n /**\n * Send a request whose body is a (possibly streamed) factory, retrying with a\n * fresh body each attempt. Used for presigned PUT uploads. Returns the raw\n * Response. Presigned URLs must never be logged.\n */\n async sendStream(\n url: string,\n opts: {\n method: string;\n bodyFactory: BodyFactory;\n headers?: Record<string, string>;\n signal?: AbortSignal;\n /** Extra fetch init (e.g. `duplex: \"half\"`). */\n init?: RequestInit;\n },\n ): Promise<Response> {\n return this.executeWithRetry(\n url,\n {\n method: opts.method,\n headers: opts.headers ?? {},\n bodyFactory: opts.bodyFactory,\n extraInit: opts.init,\n },\n opts.signal,\n /* isDataPlane */ true,\n );\n }\n\n /** Open a streaming GET (presigned download). Returns the raw Response. */\n async openStream(url: string, opts: { signal?: AbortSignal } = {}): Promise<Response> {\n return this.executeWithRetry(\n url,\n { method: \"GET\", headers: {} },\n opts.signal,\n /* isDataPlane */ true,\n );\n }\n\n private async executeWithRetry(\n url: string,\n req: {\n method: string;\n headers: Record<string, string>;\n body?: BodyInit;\n bodyFactory?: BodyFactory;\n extraInit?: RequestInit;\n },\n externalSignal?: AbortSignal,\n isDataPlane = false,\n ): Promise<Response> {\n let lastError: unknown;\n for (let attempt = 0; ; attempt++) {\n const { signal, cleanup, timedOut } = this.armSignal(externalSignal);\n try {\n const body = req.bodyFactory ? req.bodyFactory() : req.body;\n const init: RequestInit = {\n method: req.method,\n headers: req.headers,\n signal,\n ...req.extraInit,\n };\n if (body !== undefined) {\n init.body = body;\n }\n const res = await this.fetchWithRedirects(url, init);\n\n if (!isDataPlane) {\n const dep = res.headers.get(\"x-cavs-deprecation\");\n if (dep) {\n this.safeDeprecation(dep);\n }\n }\n\n if (res.ok) {\n return res;\n }\n\n if (RETRYABLE_STATUS(res.status) && attempt < this.maxRetries) {\n const wait = this.retryAfterMs(res) ?? this.backoff(attempt);\n cleanup();\n await this.sleepImpl(wait);\n continue;\n }\n\n throw await this.toError(res);\n } catch (err) {\n // A genuine user cancellation must propagate untouched.\n if (externalSignal?.aborted) {\n cleanup();\n throw externalSignal.reason instanceof Error\n ? externalSignal.reason\n : new CAVSError(\"Request cancelled\", { cause: externalSignal.reason });\n }\n // A typed CAVSError from a non-retryable status: rethrow.\n if (err instanceof CAVSError) {\n cleanup();\n throw err;\n }\n // Otherwise: network error or timeout — retryable.\n lastError = err;\n if (attempt < this.maxRetries) {\n cleanup();\n await this.sleepImpl(this.backoff(attempt));\n continue;\n }\n cleanup();\n const reason = timedOut() ? \"request timed out\" : \"network error\";\n throw new TemporaryServiceError(`CAVS ${reason} after ${attempt + 1} attempt(s)`, {\n cause: err,\n });\n } finally {\n cleanup();\n }\n }\n // Unreachable, but keeps the type checker happy.\n throw new TemporaryServiceError(\"CAVS request failed\", { cause: lastError });\n }\n\n /** Follow redirects manually, bounded by {@link maxRedirects}. */\n private async fetchWithRedirects(url: string, init: RequestInit): Promise<Response> {\n let current = url;\n for (let i = 0; i <= this.maxRedirects; i++) {\n const res = await this.fetchImpl(current, { ...init, redirect: \"manual\" });\n const location = res.headers.get(\"location\");\n if (res.status >= 300 && res.status < 400 && location) {\n if (i === this.maxRedirects) {\n throw new TemporaryServiceError(\n `Too many redirects (>${this.maxRedirects})`,\n { status: res.status },\n );\n }\n current = new URL(location, current).toString();\n continue;\n }\n return res;\n }\n // Unreachable.\n throw new TemporaryServiceError(\"Redirect handling failed\");\n }\n\n private armSignal(external?: AbortSignal): {\n signal: AbortSignal;\n cleanup: () => void;\n timedOut: () => boolean;\n } {\n const controller = new AbortController();\n let didTimeout = false;\n const timer = setTimeout(() => {\n didTimeout = true;\n controller.abort(new Error(\"timeout\"));\n }, this.timeoutMs);\n const onExternal = () => controller.abort(external?.reason);\n if (external) {\n if (external.aborted) {\n controller.abort(external.reason);\n } else {\n external.addEventListener(\"abort\", onExternal);\n }\n }\n let done = false;\n const cleanup = () => {\n if (done) return;\n done = true;\n clearTimeout(timer);\n external?.removeEventListener(\"abort\", onExternal);\n };\n return { signal: controller.signal, cleanup, timedOut: () => didTimeout };\n }\n\n private backoff(attempt: number): number {\n const base = this.retryBaseMs * Math.pow(2, attempt);\n const jitter = Math.random() * this.retryBaseMs;\n return Math.min(base + jitter, this.maxBackoffMs);\n }\n\n private retryAfterMs(res: Response): number | undefined {\n const header = res.headers.get(\"retry-after\");\n if (!header) return undefined;\n const asInt = Number(header);\n let ms: number;\n if (!Number.isNaN(asInt)) {\n ms = asInt * 1000;\n } else {\n const date = Date.parse(header);\n if (Number.isNaN(date)) return undefined;\n ms = date - Date.now();\n }\n if (ms < 0) ms = 0;\n return Math.min(ms, this.maxBackoffMs);\n }\n\n private safeDeprecation(message: string): void {\n try {\n this.onDeprecation(message);\n } catch {\n // Deprecation surfacing must never break a request.\n }\n }\n\n private async toError(res: Response): Promise<CAVSError> {\n const requestId =\n res.headers.get(\"x-request-id\") ?? res.headers.get(\"x-cavs-request-id\") ?? undefined;\n const retryAfterMs = this.retryAfterMs(res);\n let body: unknown;\n try {\n const text = await res.text();\n body = text ? JSON.parse(text) : undefined;\n } catch {\n body = undefined;\n }\n return toCAVSError(res.status, body, { requestId, retryAfterMs });\n }\n\n private async parseJson<T>(res: Response): Promise<T> {\n if (res.status === 204) {\n return undefined as T;\n }\n const text = await res.text();\n if (!text) {\n return undefined as T;\n }\n try {\n return JSON.parse(text) as T;\n } catch (err) {\n throw new CAVSError(\"Failed to parse CAVS response as JSON\", { cause: err });\n }\n }\n}\n","/**\n * `cavs://` URI parsing and formatting (CONTRACT.md §9).\n *\n * cavs://{org}/{project}/{kind}/{name}:{version} logical (mutable)\n * cavs://{org}/{project}/{kind}/{name}@sha256:{oid} immutable\n *\n * Behaviour is pinned by spec/contract/uri-vectors.json — every valid vector\n * must parse to its `parsed` object and reformat to its `canonical` string, and\n * every invalid vector must throw.\n */\n\nimport { CAVSError } from \"./errors.js\";\n\nconst SCHEME = \"cavs://\";\nconst OID_RE = /^[0-9a-f]{64}$/;\nconst SHA_MARKER = \"@sha256:\";\n\n/** A parsed `cavs://` URI. Exactly one of {@link version} / {@link oid} is set. */\nexport interface ParsedURI {\n org: string;\n project: string;\n kind: string;\n name: string;\n /** Logical version tag, or `null` for immutable references. */\n version: string | null;\n /** 64-char lowercase hex sha256, or `null` for logical references. */\n oid: string | null;\n /** `true` when the reference is pinned to an oid. */\n immutable: boolean;\n}\n\n/** Raised when a string is not a valid `cavs://` URI. */\nexport class InvalidURIError extends CAVSError {}\n\n/**\n * Parse a `cavs://` URI into its components.\n *\n * @throws {InvalidURIError} when the URI is malformed.\n */\nexport function parse(uri: string): ParsedURI {\n if (typeof uri !== \"string\" || !uri.startsWith(SCHEME)) {\n throw new InvalidURIError(`Invalid cavs:// URI: wrong scheme (${redact(uri)})`);\n }\n\n const rest = uri.slice(SCHEME.length);\n const segments = rest.split(\"/\");\n if (segments.length !== 4) {\n throw new InvalidURIError(\n `Invalid cavs:// URI: expected org/project/kind/name, got ${segments.length} segment(s)`,\n );\n }\n\n const [org, project, kind, last] = segments;\n if (!org || !project || !kind || !last) {\n throw new InvalidURIError(\"Invalid cavs:// URI: empty path segment\");\n }\n\n const shaIdx = last.indexOf(SHA_MARKER);\n if (shaIdx !== -1) {\n const name = last.slice(0, shaIdx);\n const oid = last.slice(shaIdx + SHA_MARKER.length);\n if (!name) {\n throw new InvalidURIError(\"Invalid cavs:// URI: empty name\");\n }\n if (name.includes(\":\")) {\n throw new InvalidURIError(\"Invalid cavs:// URI: cannot specify both version and oid\");\n }\n if (!OID_RE.test(oid)) {\n throw new InvalidURIError(\"Invalid cavs:// URI: oid must be 64 lowercase hex chars\");\n }\n return { org, project, kind, name, version: null, oid, immutable: true };\n }\n\n const colonIdx = last.indexOf(\":\");\n if (colonIdx === -1) {\n throw new InvalidURIError(\"Invalid cavs:// URI: missing version or @sha256:oid\");\n }\n const name = last.slice(0, colonIdx);\n const version = last.slice(colonIdx + 1);\n if (!name) {\n throw new InvalidURIError(\"Invalid cavs:// URI: empty name\");\n }\n if (!version) {\n throw new InvalidURIError(\"Invalid cavs:// URI: empty version\");\n }\n return { org, project, kind, name, version, oid: null, immutable: false };\n}\n\n/** Format a {@link ParsedURI} (or the equivalent fields) back to a canonical string. */\nexport function format(parsed: {\n org: string;\n project: string;\n kind: string;\n name: string;\n version?: string | null;\n oid?: string | null;\n}): string {\n const { org, project, kind, name, version, oid } = parsed;\n if (!org || !project || !kind || !name) {\n throw new InvalidURIError(\"Cannot format cavs:// URI: missing required field\");\n }\n if (oid) {\n if (version) {\n throw new InvalidURIError(\"Cannot format cavs:// URI: both version and oid provided\");\n }\n if (!OID_RE.test(oid)) {\n throw new InvalidURIError(\"Cannot format cavs:// URI: oid must be 64 lowercase hex chars\");\n }\n return `${SCHEME}${org}/${project}/${kind}/${name}${SHA_MARKER}${oid}`;\n }\n if (!version) {\n throw new InvalidURIError(\"Cannot format cavs:// URI: either version or oid is required\");\n }\n return `${SCHEME}${org}/${project}/${kind}/${name}:${version}`;\n}\n\nfunction redact(uri: string): string {\n if (typeof uri !== \"string\") {\n return String(uri);\n }\n return uri.length > 40 ? `${uri.slice(0, 40)}…` : uri;\n}\n","/**\n * Artifacts resource — the upload/download data plane plus artifact discovery\n * (CONTRACT.md §4, §5).\n *\n * `project` is an alias for `repository`: the caller passes `project` (a repo\n * slug or id) and it is used directly as `{repo}` in the repository-scoped\n * endpoints. `org` is only needed for org-scoped listing.\n */\n\nimport { randomUUID } from \"node:crypto\";\n\nimport type { ClientContext } from \"../client.js\";\nimport { CAVSError, UploadError } from \"../errors.js\";\nimport type { BodyInit } from \"../http.js\";\nimport {\n countingReadStream,\n downloadToFile,\n prepareUpload,\n type LocalFile,\n} from \"../transfer.js\";\nimport type {\n Artifact,\n ArtifactVersion,\n DownloadResult,\n DownloadedFile,\n ProgressCallback,\n UploadResult,\n UploadedFile,\n} from \"../types.js\";\nimport * as uri from \"../uri.js\";\n\nexport interface UploadOptions {\n /** Local file or directory to upload. */\n path: string;\n /** Project (repository slug or id) to upload into. */\n project: string;\n /** Artifact name. */\n name: string;\n /** Artifact kind (e.g. `model`, `dataset`, `game-build`). */\n kind: string;\n /** Logical version tag. */\n version: string;\n /** Arbitrary metadata attached to the version. */\n metadata?: Record<string, unknown>;\n /** Organization slug (only recorded; defaults to the client's org). */\n org?: string;\n /** Stable idempotency key; a deterministic one is derived when omitted. */\n idempotencyKey?: string;\n /** Progress callback (hashing + upload phases). */\n onProgress?: ProgressCallback;\n /** Cancellation signal. */\n signal?: AbortSignal;\n}\n\nexport interface DownloadOptions {\n /** Destination directory. */\n dest: string;\n /** Organization slug override (defaults to the reference's org). */\n org?: string;\n /** Progress callback (download phase). */\n onProgress?: ProgressCallback;\n /** Cancellation signal. */\n signal?: AbortSignal;\n}\n\ninterface CreateSessionResponse {\n session_id?: string;\n id?: string;\n}\n\ninterface ObjectAuthEntry {\n oid: string;\n upload_url?: string;\n exists?: boolean;\n error?: string;\n}\n\ninterface FinalizeResponse {\n artifact_id: string;\n artifact_reference?: string;\n reference?: string;\n version: string;\n sha256: string;\n logical_bytes?: number;\n physical_bytes?: number;\n deduplicated_bytes?: number;\n deduplication_ratio?: number;\n}\n\ninterface DownloadAuthEntry {\n oid: string;\n download_url?: string;\n error?: string;\n}\n\ninterface ResolveResponse {\n repository?: string;\n repository_id?: string;\n repo?: string;\n artifact_id?: string;\n reference?: string;\n version?: string;\n files?: Array<{ path: string; oid: string; size?: number }>;\n}\n\nexport class ArtifactsResource {\n constructor(private readonly ctx: ClientContext) {}\n\n /** `GET /api/v1/artifacts/{id}`. */\n async get(artifactId: string, signal?: AbortSignal): Promise<Artifact> {\n return this.ctx.http.requestJson<Artifact>({\n path: `/api/v1/artifacts/${encodeURIComponent(artifactId)}`,\n signal,\n });\n }\n\n /** `GET /api/v1/artifacts/{id}/versions`. */\n async versions(artifactId: string, signal?: AbortSignal): Promise<ArtifactVersion[]> {\n return this.ctx.http.requestJson<ArtifactVersion[]>({\n path: `/api/v1/artifacts/${encodeURIComponent(artifactId)}/versions`,\n signal,\n });\n }\n\n /** `GET /api/v1/organizations/{org}/artifacts`. */\n async list(\n opts: { org?: string; limit?: number; type?: string; q?: string; signal?: AbortSignal } = {},\n ): Promise<Artifact[]> {\n const org = opts.org ?? this.ctx.defaultOrg;\n if (!org) {\n throw new CAVSError(\"No organization specified for artifacts.list (pass { org } or set CAVS_ORG).\");\n }\n return this.ctx.http.requestJson<Artifact[]>({\n path: `/api/v1/organizations/${encodeURIComponent(org)}/artifacts`,\n query: { limit: opts.limit, type: opts.type, q: opts.q },\n signal: opts.signal,\n });\n }\n\n /**\n * Upload a file or directory as a new artifact version, following the\n * choreography in CONTRACT.md §5. Streams every object; skips objects that\n * already exist (dedup); resumable because step 3 re-reports `exists`.\n */\n async upload(opts: UploadOptions): Promise<UploadResult> {\n const repo = opts.project;\n // 1. Hash all files (streamed). Fails fast on bad paths before any request.\n const files = await prepareUpload(opts.path, {\n signal: opts.signal,\n onProgress: opts.onProgress,\n });\n if (files.length === 0) {\n throw new UploadError(`Nothing to upload: ${opts.path} contains no files`);\n }\n\n const idempotencyKey =\n opts.idempotencyKey ?? `upload:${repo}:${opts.kind}:${opts.name}:${opts.version}`;\n const repoPath = `/api/v1/repositories/${encodeURIComponent(repo)}`;\n\n // 2. Open the upload session.\n const session = await this.ctx.http.requestJson<CreateSessionResponse>({\n method: \"POST\",\n path: `${repoPath}/uploads`,\n idempotencyKey,\n body: { expected_objects: files.length },\n signal: opts.signal,\n });\n const sessionId = session.session_id ?? session.id;\n if (!sessionId) {\n throw new UploadError(\"Upload session response did not include a session id\");\n }\n const sessionPath = `${repoPath}/uploads/${encodeURIComponent(sessionId)}`;\n\n // 3. Authorize objects (dedup: exists === true means skip the PUT).\n const uniqueObjects = dedupeObjects(files);\n const authResults = await this.ctx.http.requestJson<ObjectAuthEntry[]>({\n method: \"POST\",\n path: `${sessionPath}/objects`,\n body: { objects: uniqueObjects.map((f) => ({ oid: f.oid, size: f.size })) },\n signal: opts.signal,\n });\n const authByOid = new Map(authResults.map((r) => [r.oid, r]));\n\n // 4 + 5. Upload each object needing it, then complete.\n const uploaded: UploadedFile[] = [];\n const doneOids = new Set<string>();\n for (const file of files) {\n const entry = authByOid.get(file.oid);\n if (!entry) {\n throw new UploadError(`Server did not return an authorization for oid ${file.oid}`);\n }\n if (entry.error) {\n throw new UploadError(`Upload rejected for ${file.relPath}: ${entry.error}`);\n }\n\n const deduplicated = entry.exists === true;\n if (!deduplicated && !doneOids.has(file.oid)) {\n if (!entry.upload_url) {\n throw new UploadError(`Missing upload URL for ${file.relPath}`);\n }\n await this.putObject(entry.upload_url, file, opts);\n await this.ctx.http.requestJson({\n method: \"POST\",\n path: `${sessionPath}/objects/${encodeURIComponent(file.oid)}/complete`,\n body: { size: file.size },\n signal: opts.signal,\n });\n }\n doneOids.add(file.oid);\n uploaded.push({\n path: file.relPath,\n oid: file.oid,\n size: file.size,\n deduplicated,\n });\n }\n\n // 6. Finalize → artifact version + dedup stats.\n const finalize = await this.ctx.http.requestJson<FinalizeResponse>({\n method: \"POST\",\n path: `${sessionPath}/finalize`,\n idempotencyKey: `${idempotencyKey}:finalize`,\n body: {\n name: opts.name,\n kind: opts.kind,\n version: opts.version,\n metadata: opts.metadata ?? {},\n files: files.map((f) => ({ path: f.relPath, oid: f.oid, size: f.size })),\n },\n signal: opts.signal,\n });\n\n const logical = finalize.logical_bytes ?? files.reduce((n, f) => n + f.size, 0);\n return {\n artifactId: finalize.artifact_id,\n reference:\n finalize.artifact_reference ??\n finalize.reference ??\n uri.format({\n org: opts.org ?? this.ctx.defaultOrg ?? \"org\",\n project: opts.project,\n kind: opts.kind,\n name: opts.name,\n version: opts.version,\n }),\n version: finalize.version,\n sha256: finalize.sha256,\n logicalBytes: logical,\n physicalBytes: finalize.physical_bytes ?? logical,\n deduplicatedBytes: finalize.deduplicated_bytes ?? 0,\n deduplicationRatio: finalize.deduplication_ratio ?? 0,\n files: uploaded,\n };\n }\n\n private async putObject(\n uploadUrl: string,\n file: LocalFile,\n opts: UploadOptions,\n ): Promise<void> {\n const res = await this.ctx.http.sendStream(uploadUrl, {\n method: \"PUT\",\n headers: { \"Content-Length\": String(file.size) },\n bodyFactory: () =>\n countingReadStream(file.absPath, (bytes) => {\n this.reportUpload(file, bytes, opts);\n }) as unknown as BodyInit,\n init: { duplex: \"half\" } as RequestInit,\n signal: opts.signal,\n });\n if (!res.ok) {\n throw new UploadError(\n `Presigned upload failed for ${file.relPath} (status ${res.status})`,\n { status: res.status },\n );\n }\n }\n\n private reportUpload(file: LocalFile, bytes: number, opts: UploadOptions): void {\n if (!opts.onProgress) return;\n const state = (this.uploadProgress ??= new Map());\n const loaded = (state.get(file.oid) ?? 0) + bytes;\n state.set(file.oid, loaded);\n opts.onProgress({ phase: \"upload\", path: file.relPath, loaded, total: file.size });\n }\n private uploadProgress?: Map<string, number>;\n\n /**\n * Download an artifact by its `cavs://` reference into `opts.dest`, verifying\n * each object's sha256 and writing atomically (CONTRACT.md §5).\n */\n async download(reference: string, opts: DownloadOptions): Promise<DownloadResult> {\n // Validates the reference (throws InvalidURIError on malformed input).\n uri.parse(reference);\n\n const resolved = await this.ctx.http.requestJson<ResolveResponse>({\n path: \"/api/v1/resolve\",\n query: { uri: reference },\n signal: opts.signal,\n });\n\n const repo = resolved.repository ?? resolved.repository_id ?? resolved.repo;\n if (!repo) {\n throw new CAVSError(\"Resolve response did not include a repository for the reference\");\n }\n const files = resolved.files ?? [];\n if (files.length === 0) {\n throw new CAVSError(`No files found for reference ${reference}`);\n }\n\n const oids = [...new Set(files.map((f) => f.oid))];\n const auth = await this.ctx.http.requestJson<DownloadAuthEntry[]>({\n method: \"POST\",\n path: `/api/v1/repositories/${encodeURIComponent(repo)}/downloads/authorize`,\n body: { oids },\n signal: opts.signal,\n });\n const urlByOid = new Map(auth.map((a) => [a.oid, a]));\n\n const results: DownloadedFile[] = [];\n for (const file of files) {\n const entry = urlByOid.get(file.oid);\n if (!entry || entry.error || !entry.download_url) {\n throw new CAVSError(\n `Download authorization failed for ${file.path}${entry?.error ? `: ${entry.error}` : \"\"}`,\n );\n }\n const res = await this.ctx.http.openStream(entry.download_url, { signal: opts.signal });\n const written = await downloadToFile(res.body, {\n destDir: opts.dest,\n relPath: file.path,\n oid: file.oid,\n size: file.size,\n onProgress: opts.onProgress,\n signal: opts.signal,\n });\n results.push(written);\n }\n\n return { dest: opts.dest, files: results };\n }\n}\n\nfunction dedupeObjects(files: LocalFile[]): LocalFile[] {\n const seen = new Set<string>();\n const out: LocalFile[] = [];\n for (const f of files) {\n if (!seen.has(f.oid)) {\n seen.add(f.oid);\n out.push(f);\n }\n }\n return out;\n}\n\n// Ensure randomUUID stays importable for callers deriving keys elsewhere.\nexport const _uuid = randomUUID;\n","/**\n * Streaming data-plane primitives (CONTRACT.md §5, §6, §P6).\n *\n * Everything here streams: files are hashed and transferred chunk-by-chunk and\n * are NEVER read whole into memory. Downloads are verified (sha256 === oid) and\n * atomically renamed; temp files are removed on failure; path traversal is\n * guarded.\n */\n\nimport { createHash } from \"node:crypto\";\nimport { createReadStream, createWriteStream } from \"node:fs\";\nimport * as fs from \"node:fs/promises\";\nimport * as path from \"node:path\";\nimport { Readable, Transform } from \"node:stream\";\nimport { pipeline } from \"node:stream/promises\";\n\nimport { ChecksumError, DownloadError, UploadError } from \"./errors.js\";\nimport type { ProgressCallback } from \"./types.js\";\n\n/** A local file discovered for upload. */\nexport interface LocalFile {\n /** Absolute path on disk. */\n absPath: string;\n /** Path relative to the upload root, using forward slashes. */\n relPath: string;\n oid: string;\n size: number;\n}\n\nexport interface HashOptions {\n signal?: AbortSignal;\n onProgress?: (loaded: number) => void;\n /** Chunk size for the read stream; the resulting oid is independent of this. */\n highWaterMark?: number;\n}\n\n/**\n * Compute the streaming sha256 (\"oid\") and byte size of a file. The whole file\n * is never buffered in memory.\n */\nexport async function sha256File(\n filePath: string,\n opts: HashOptions = {},\n): Promise<{ oid: string; size: number }> {\n throwIfAborted(opts.signal);\n const hash = createHash(\"sha256\");\n let size = 0;\n const stream = createReadStream(filePath, { highWaterMark: opts.highWaterMark });\n\n await new Promise<void>((resolve, reject) => {\n const onAbort = () => stream.destroy(abortError(opts.signal));\n if (opts.signal) {\n opts.signal.addEventListener(\"abort\", onAbort, { once: true });\n }\n stream.on(\"data\", (chunk: string | Buffer) => {\n hash.update(chunk);\n size += chunk.length;\n opts.onProgress?.(size);\n });\n stream.on(\"error\", (err) => {\n opts.signal?.removeEventListener(\"abort\", onAbort);\n reject(err);\n });\n stream.on(\"end\", () => {\n opts.signal?.removeEventListener(\"abort\", onAbort);\n resolve();\n });\n });\n\n return { oid: hash.digest(\"hex\"), size };\n}\n\n/**\n * Recursively enumerate the files under `root` (or the single file). Returns\n * entries with relative paths using forward slashes. Symlinks are not followed.\n */\nexport async function collectFiles(root: string): Promise<Array<{ absPath: string; relPath: string }>> {\n const stat = await fs.stat(root);\n if (stat.isFile()) {\n return [{ absPath: path.resolve(root), relPath: path.basename(root) }];\n }\n if (!stat.isDirectory()) {\n throw new UploadError(`Not a regular file or directory: ${root}`);\n }\n const out: Array<{ absPath: string; relPath: string }> = [];\n const base = path.resolve(root);\n async function walk(dir: string): Promise<void> {\n const entries = await fs.readdir(dir, { withFileTypes: true });\n for (const entry of entries) {\n const abs = path.join(dir, entry.name);\n if (entry.isDirectory()) {\n await walk(abs);\n } else if (entry.isFile()) {\n const rel = path.relative(base, abs).split(path.sep).join(\"/\");\n out.push({ absPath: abs, relPath: rel });\n }\n }\n }\n await walk(base);\n out.sort((a, b) => (a.relPath < b.relPath ? -1 : a.relPath > b.relPath ? 1 : 0));\n return out;\n}\n\n/**\n * Prepare local files for upload: enumerate, then compute streamed oid + size\n * for each (CONTRACT.md §5.1 — fail fast before opening a session).\n */\nexport async function prepareUpload(\n root: string,\n opts: { signal?: AbortSignal; onProgress?: ProgressCallback } = {},\n): Promise<LocalFile[]> {\n const found = await collectFiles(root);\n const files: LocalFile[] = [];\n for (const f of found) {\n const { oid, size } = await sha256File(f.absPath, {\n signal: opts.signal,\n onProgress: (loaded) =>\n opts.onProgress?.({ phase: \"hash\", path: f.relPath, loaded, total: 0 }),\n });\n files.push({ ...f, oid, size });\n }\n return files;\n}\n\n/** A counting Node Readable that reports bytes read (for upload progress). */\nexport function countingReadStream(\n filePath: string,\n onChunk: (bytes: number) => void,\n): Readable {\n const stream = createReadStream(filePath);\n stream.on(\"data\", (chunk: string | Buffer) => onChunk(chunk.length));\n return stream;\n}\n\n/**\n * Stream an HTTP response body to a deterministic temp file inside `destDir`\n * while hashing, verify sha256 === oid, then atomically rename to `relPath`.\n * On any failure the temp file is removed. Guards against path traversal.\n */\nexport async function downloadToFile(\n body: ReadableStream<Uint8Array> | null,\n args: {\n destDir: string;\n relPath: string;\n oid: string;\n size?: number;\n onProgress?: ProgressCallback;\n signal?: AbortSignal;\n },\n): Promise<{ path: string; oid: string; size: number }> {\n const target = safeJoin(args.destDir, args.relPath);\n await fs.mkdir(path.dirname(target), { recursive: true });\n\n // Deterministic temp path (same directory → rename stays atomic on one fs).\n const tmp = path.join(path.dirname(target), `.cavs-download-${args.oid}.part`);\n\n if (!body) {\n throw new DownloadError(`Empty response body while downloading ${args.relPath}`);\n }\n\n const hash = createHash(\"sha256\");\n let size = 0;\n const nodeReadable = Readable.fromWeb(body as any);\n // Hash + count as bytes pass through, without buffering the whole file.\n const hashing = new Transform({\n transform(chunk: Buffer, _enc, cb) {\n hash.update(chunk);\n size += chunk.length;\n args.onProgress?.({\n phase: \"download\",\n path: args.relPath,\n loaded: size,\n total: args.size ?? 0,\n });\n cb(null, chunk);\n },\n });\n\n try {\n await pipeline(nodeReadable, hashing, createWriteStream(tmp), { signal: args.signal });\n } catch (err) {\n await safeUnlink(tmp);\n throw err instanceof ChecksumError\n ? err\n : new DownloadError(`Failed to download ${args.relPath}`, { cause: err });\n }\n\n const digest = hash.digest(\"hex\");\n if (digest !== args.oid) {\n await safeUnlink(tmp);\n throw new ChecksumError(\n `Checksum mismatch for ${args.relPath}: expected ${args.oid}, got ${digest}`,\n );\n }\n\n await fs.rename(tmp, target);\n return { path: args.relPath, oid: args.oid, size };\n}\n\n/**\n * Join `destDir` and a relative member path, refusing anything that would\n * escape `destDir` (path-traversal guard, CONTRACT.md §2).\n */\nexport function safeJoin(destDir: string, relPath: string): string {\n if (path.isAbsolute(relPath)) {\n throw new DownloadError(`Refusing absolute path in artifact: ${relPath}`);\n }\n const base = path.resolve(destDir);\n const target = path.resolve(base, relPath);\n const withSep = base.endsWith(path.sep) ? base : base + path.sep;\n if (target !== base && !target.startsWith(withSep)) {\n throw new DownloadError(`Path traversal detected in artifact member: ${relPath}`);\n }\n return target;\n}\n\nfunction throwIfAborted(signal?: AbortSignal): void {\n if (signal?.aborted) {\n throw abortError(signal);\n }\n}\n\nfunction abortError(signal?: AbortSignal): Error {\n const reason = signal?.reason;\n return reason instanceof Error ? reason : new Error(\"Operation aborted\");\n}\n\nasync function safeUnlink(p: string): Promise<void> {\n try {\n await fs.unlink(p);\n } catch {\n // Best-effort cleanup.\n }\n}\n","/** Snapshots resource (CONTRACT.md §4). `project` is a repository slug/id. */\n\nimport type { ClientContext } from \"../client.js\";\nimport type { Snapshot } from \"../types.js\";\n\nexport interface CreateSnapshotOptions {\n message?: string;\n metadata?: Record<string, unknown>;\n idempotencyKey?: string;\n signal?: AbortSignal;\n}\n\nexport class SnapshotsResource {\n constructor(private readonly ctx: ClientContext) {}\n\n /** `GET /api/v1/repositories/{repo}/snapshots`. */\n async list(project: string, signal?: AbortSignal): Promise<Snapshot[]> {\n return this.ctx.http.requestJson<Snapshot[]>({\n path: `/api/v1/repositories/${encodeURIComponent(project)}/snapshots`,\n signal,\n });\n }\n\n /** `POST /api/v1/repositories/{repo}/snapshots`. */\n async create(project: string, opts: CreateSnapshotOptions = {}): Promise<Snapshot> {\n return this.ctx.http.requestJson<Snapshot>({\n method: \"POST\",\n path: `/api/v1/repositories/${encodeURIComponent(project)}/snapshots`,\n idempotencyKey: opts.idempotencyKey,\n body: { message: opts.message, metadata: opts.metadata ?? {} },\n signal: opts.signal,\n });\n }\n}\n","/** Releases resource (CONTRACT.md §4). `project` is a repository slug/id. */\n\nimport type { ClientContext } from \"../client.js\";\nimport type { Release } from \"../types.js\";\n\nexport class ReleasesResource {\n constructor(private readonly ctx: ClientContext) {}\n\n /** `GET /api/v1/repositories/{repo}/releases`. */\n async list(project: string, signal?: AbortSignal): Promise<Release[]> {\n return this.ctx.http.requestJson<Release[]>({\n path: `/api/v1/repositories/${encodeURIComponent(project)}/releases`,\n signal,\n });\n }\n\n /** `GET /api/v1/repositories/{repo}/releases/{tag}`. */\n async get(project: string, tag: string, signal?: AbortSignal): Promise<Release> {\n return this.ctx.http.requestJson<Release>({\n path: `/api/v1/repositories/${encodeURIComponent(project)}/releases/${encodeURIComponent(tag)}`,\n signal,\n });\n }\n}\n","/** Runs resource (CONTRACT.md §4 — runs & lineage). `project` is a repo slug/id. */\n\nimport type { ClientContext } from \"../client.js\";\nimport type { Run } from \"../types.js\";\n\nexport interface CreateRunOptions {\n name: string;\n system: string;\n externalId?: string;\n gitCommit?: string;\n pipeline?: string;\n environment?: string;\n status?: string;\n metadata?: Record<string, unknown>;\n idempotencyKey?: string;\n signal?: AbortSignal;\n}\n\nexport interface UpdateRunOptions {\n status?: string;\n endedAt?: string;\n metadata?: Record<string, unknown>;\n idempotencyKey?: string;\n signal?: AbortSignal;\n}\n\n/** An artifact association to record on a run (creates lineage edges). */\nexport interface RunArtifact {\n oid?: string;\n reference?: string;\n role: \"input\" | \"output\";\n [key: string]: unknown;\n}\n\nexport class RunsResource {\n constructor(private readonly ctx: ClientContext) {}\n\n private base(project: string): string {\n return `/api/v1/repositories/${encodeURIComponent(project)}/runs`;\n }\n\n /** `POST /api/v1/repositories/{repo}/runs`. */\n async create(project: string, opts: CreateRunOptions): Promise<Run> {\n return this.ctx.http.requestJson<Run>({\n method: \"POST\",\n path: this.base(project),\n idempotencyKey: opts.idempotencyKey,\n body: {\n name: opts.name,\n system: opts.system,\n external_id: opts.externalId,\n git_commit: opts.gitCommit,\n pipeline: opts.pipeline,\n environment: opts.environment,\n status: opts.status,\n metadata: opts.metadata ?? {},\n },\n signal: opts.signal,\n });\n }\n\n /** `GET /api/v1/repositories/{repo}/runs`. */\n async list(project: string, signal?: AbortSignal): Promise<Run[]> {\n return this.ctx.http.requestJson<Run[]>({ path: this.base(project), signal });\n }\n\n /** `GET /api/v1/repositories/{repo}/runs/{run}`. */\n async get(project: string, runId: string, signal?: AbortSignal): Promise<Run> {\n return this.ctx.http.requestJson<Run>({\n path: `${this.base(project)}/${encodeURIComponent(runId)}`,\n signal,\n });\n }\n\n /** `PATCH /api/v1/repositories/{repo}/runs/{run}`. */\n async update(project: string, runId: string, opts: UpdateRunOptions): Promise<Run> {\n return this.ctx.http.requestJson<Run>({\n method: \"PATCH\",\n path: `${this.base(project)}/${encodeURIComponent(runId)}`,\n idempotencyKey: opts.idempotencyKey,\n body: { status: opts.status, ended_at: opts.endedAt, metadata: opts.metadata },\n signal: opts.signal,\n });\n }\n\n /** `POST /api/v1/repositories/{repo}/runs/{run}/artifacts` — record lineage. */\n async addArtifacts(\n project: string,\n runId: string,\n artifacts: RunArtifact[],\n opts: { idempotencyKey?: string; signal?: AbortSignal } = {},\n ): Promise<unknown> {\n return this.ctx.http.requestJson({\n method: \"POST\",\n path: `${this.base(project)}/${encodeURIComponent(runId)}/artifacts`,\n idempotencyKey: opts.idempotencyKey,\n body: { artifacts },\n signal: opts.signal,\n });\n }\n}\n","/** Lineage graph resource (CONTRACT.md §4). `project` is a repository slug/id. */\n\nimport type { ClientContext } from \"../client.js\";\nimport type { LineageEdge, LineageGraph } from \"../types.js\";\n\nexport interface AddEdgeOptions {\n fromType: string;\n fromKey: string;\n toType: string;\n toKey: string;\n relation: string;\n metadata?: Record<string, unknown>;\n idempotencyKey?: string;\n signal?: AbortSignal;\n}\n\nexport class LineageResource {\n constructor(private readonly ctx: ClientContext) {}\n\n /** `GET /api/v1/repositories/{repo}/graph`. */\n async graph(project: string, signal?: AbortSignal): Promise<LineageGraph> {\n return this.ctx.http.requestJson<LineageGraph>({\n path: `/api/v1/repositories/${encodeURIComponent(project)}/graph`,\n signal,\n });\n }\n\n /** `POST /api/v1/repositories/{repo}/graph/edges`. */\n async addEdge(project: string, opts: AddEdgeOptions): Promise<LineageEdge> {\n return this.ctx.http.requestJson<LineageEdge>({\n method: \"POST\",\n path: `/api/v1/repositories/${encodeURIComponent(project)}/graph/edges`,\n idempotencyKey: opts.idempotencyKey,\n body: {\n from_type: opts.fromType,\n from_key: opts.fromKey,\n to_type: opts.toType,\n to_key: opts.toKey,\n relation: opts.relation,\n metadata: opts.metadata ?? {},\n },\n signal: opts.signal,\n });\n }\n}\n","/** Usage / dedup-stats resource (CONTRACT.md §4). */\n\nimport type { ClientContext } from \"../client.js\";\nimport { CAVSError } from \"../errors.js\";\nimport type { Usage } from \"../types.js\";\n\nexport class UsageResource {\n constructor(private readonly ctx: ClientContext) {}\n\n /** `GET /api/v1/organizations/{org}/usage`. */\n async get(opts: { org?: string; signal?: AbortSignal } = {}): Promise<Usage> {\n const org = opts.org ?? this.ctx.defaultOrg;\n if (!org) {\n throw new CAVSError(\"No organization specified for usage.get (pass { org } or set CAVS_ORG).\");\n }\n return this.ctx.http.requestJson<Usage>({\n path: `/api/v1/organizations/${encodeURIComponent(org)}/usage`,\n signal: opts.signal,\n });\n }\n}\n","/** Service accounts resource (org admin, CONTRACT.md §4). */\n\nimport type { ClientContext } from \"../client.js\";\nimport { CAVSError } from \"../errors.js\";\nimport type { ServiceAccount, ServiceAccountKey } from \"../types.js\";\n\nexport interface CreateServiceAccountOptions {\n name: string;\n description?: string;\n scopes?: string[];\n repositoryIds?: string[];\n environment?: string;\n org?: string;\n signal?: AbortSignal;\n}\n\nexport class ServiceAccountsResource {\n constructor(private readonly ctx: ClientContext) {}\n\n private org(explicit?: string): string {\n const org = explicit ?? this.ctx.defaultOrg;\n if (!org) {\n throw new CAVSError(\"No organization specified (pass { org } or set CAVS_ORG).\");\n }\n return org;\n }\n\n private base(org?: string): string {\n return `/api/v1/organizations/${encodeURIComponent(this.org(org))}/service-accounts`;\n }\n\n /** `GET …/service-accounts`. */\n async list(opts: { org?: string; signal?: AbortSignal } = {}): Promise<ServiceAccount[]> {\n return this.ctx.http.requestJson<ServiceAccount[]>({ path: this.base(opts.org), signal: opts.signal });\n }\n\n /** `POST …/service-accounts`. */\n async create(opts: CreateServiceAccountOptions): Promise<ServiceAccount> {\n return this.ctx.http.requestJson<ServiceAccount>({\n method: \"POST\",\n path: this.base(opts.org),\n body: {\n name: opts.name,\n description: opts.description,\n scopes: opts.scopes,\n repository_ids: opts.repositoryIds,\n environment: opts.environment,\n },\n signal: opts.signal,\n });\n }\n\n /** `PATCH …/service-accounts/{id}` — enable/disable, edit scopes/repos. */\n async update(\n id: string,\n patch: { disabled?: boolean; scopes?: string[]; repositoryIds?: string[] },\n opts: { org?: string; signal?: AbortSignal } = {},\n ): Promise<ServiceAccount> {\n return this.ctx.http.requestJson<ServiceAccount>({\n method: \"PATCH\",\n path: `${this.base(opts.org)}/${encodeURIComponent(id)}`,\n body: {\n disabled: patch.disabled,\n scopes: patch.scopes,\n repository_ids: patch.repositoryIds,\n },\n signal: opts.signal,\n });\n }\n\n /** `DELETE …/service-accounts/{id}`. */\n async delete(id: string, opts: { org?: string; signal?: AbortSignal } = {}): Promise<void> {\n await this.ctx.http.requestJson({\n method: \"DELETE\",\n path: `${this.base(opts.org)}/${encodeURIComponent(id)}`,\n signal: opts.signal,\n });\n }\n\n /** `POST …/service-accounts/{id}/keys` — the secret is returned once. */\n async createKey(id: string, opts: { org?: string; signal?: AbortSignal } = {}): Promise<ServiceAccountKey> {\n return this.ctx.http.requestJson<ServiceAccountKey>({\n method: \"POST\",\n path: `${this.base(opts.org)}/${encodeURIComponent(id)}/keys`,\n signal: opts.signal,\n });\n }\n\n /** `POST …/service-accounts/{id}/keys/{key}/rotate`. */\n async rotateKey(\n id: string,\n keyId: string,\n opts: { org?: string; signal?: AbortSignal } = {},\n ): Promise<ServiceAccountKey> {\n return this.ctx.http.requestJson<ServiceAccountKey>({\n method: \"POST\",\n path: `${this.base(opts.org)}/${encodeURIComponent(id)}/keys/${encodeURIComponent(keyId)}/rotate`,\n signal: opts.signal,\n });\n }\n\n /** `DELETE …/service-accounts/{id}/keys/{key}`. */\n async deleteKey(\n id: string,\n keyId: string,\n opts: { org?: string; signal?: AbortSignal } = {},\n ): Promise<void> {\n await this.ctx.http.requestJson({\n method: \"DELETE\",\n path: `${this.base(opts.org)}/${encodeURIComponent(id)}/keys/${encodeURIComponent(keyId)}`,\n signal: opts.signal,\n });\n }\n}\n","/**\n * The {@link CAVS} client — the entry point of the SDK.\n *\n * ```ts\n * import { CAVS } from \"@cavsnode/cavs-sdk\";\n * const client = CAVS.fromEnv();\n * const art = await client.artifacts.upload({ path: \"./model\", project: \"vision-models\",\n * name: \"resnet50\", kind: \"model\", version: \"1.4.0\" });\n * await client.artifacts.download(art.reference, { dest: \"./out\" });\n * ```\n */\n\nimport { resolveToken } from \"./auth.js\";\nimport { CAVSError } from \"./errors.js\";\nimport { HttpClient, type FetchLike } from \"./http.js\";\nimport type { Me } from \"./types.js\";\nimport * as uri from \"./uri.js\";\n\nimport { ArtifactsResource } from \"./resources/artifacts.js\";\nimport { SnapshotsResource } from \"./resources/snapshots.js\";\nimport { ReleasesResource } from \"./resources/releases.js\";\nimport { RunsResource } from \"./resources/runs.js\";\nimport { LineageResource } from \"./resources/lineage.js\";\nimport { UsageResource } from \"./resources/usage.js\";\nimport { ServiceAccountsResource } from \"./resources/serviceAccounts.js\";\n\n/** The default control-plane base URL. */\nexport const DEFAULT_API = \"https://api.cavs.dev\";\n\nexport interface CAVSOptions {\n /** Auth token. Falls back to `$CAVS_TOKEN`. */\n token?: string;\n /** Base URL of the CAVS Hub. Falls back to `$CAVS_API` then {@link DEFAULT_API}. */\n api?: string;\n /**\n * Default organization slug for org-scoped calls. Falls back to `$CAVS_ORG`.\n * Repository/upload/download calls do not require it (they key on the repo).\n */\n org?: string;\n /** Injectable `fetch` — makes the client trivial to mock in tests. */\n fetch?: FetchLike;\n /** Override the `X-CAVS-Integration` header (default `javascript-sdk`). */\n integration?: string;\n /** Override the `X-CAVS-Integration-Version` header. */\n integrationVersion?: string;\n /** Optional `X-CAVS-Run-ID` correlation id. */\n runId?: string;\n /** Per-attempt request timeout in ms (default 30000). */\n timeoutMs?: number;\n /** Max retries on 429/5xx/network (default 4). */\n maxRetries?: number;\n /** Called when the server sends `X-CAVS-Deprecation`. */\n onDeprecation?: (message: string) => void;\n /** Internal/testing knobs forwarded to the transport. */\n retryBaseMs?: number;\n sleepImpl?: (ms: number) => Promise<void>;\n}\n\n/** Context handed to each resource module. */\nexport interface ClientContext {\n http: HttpClient;\n defaultOrg?: string;\n}\n\nexport class CAVS {\n readonly http: HttpClient;\n private readonly defaultOrg?: string;\n\n readonly artifacts: ArtifactsResource;\n readonly snapshots: SnapshotsResource;\n readonly releases: ReleasesResource;\n readonly runs: RunsResource;\n readonly lineage: LineageResource;\n readonly usage: UsageResource;\n readonly serviceAccounts: ServiceAccountsResource;\n\n constructor(options: CAVSOptions = {}) {\n const token = resolveToken(options.token);\n const api = (options.api ?? process.env.CAVS_API ?? DEFAULT_API).replace(/\\/+$/, \"\");\n this.defaultOrg = options.org ?? process.env.CAVS_ORG;\n\n this.http = new HttpClient({\n baseUrl: api,\n token,\n fetch: options.fetch,\n telemetry: {\n integration: options.integration,\n integrationVersion: options.integrationVersion,\n runId: options.runId,\n },\n timeoutMs: options.timeoutMs,\n maxRetries: options.maxRetries,\n onDeprecation: options.onDeprecation,\n retryBaseMs: options.retryBaseMs,\n sleepImpl: options.sleepImpl,\n });\n\n const ctx: ClientContext = { http: this.http, defaultOrg: this.defaultOrg };\n this.artifacts = new ArtifactsResource(ctx);\n this.snapshots = new SnapshotsResource(ctx);\n this.releases = new ReleasesResource(ctx);\n this.runs = new RunsResource(ctx);\n this.lineage = new LineageResource(ctx);\n this.usage = new UsageResource(ctx);\n this.serviceAccounts = new ServiceAccountsResource(ctx);\n }\n\n /** Construct a client from the environment (`CAVS_TOKEN`, `CAVS_API`, `CAVS_ORG`). */\n static fromEnv(options: CAVSOptions = {}): CAVS {\n return new CAVS(options);\n }\n\n /** Resolve the org to use for org-scoped calls. */\n resolveOrg(explicit?: string): string {\n const org = explicit ?? this.defaultOrg;\n if (!org) {\n throw new CAVSError(\n \"No organization specified. Pass { org } to the call or the constructor, or set CAVS_ORG.\",\n );\n }\n return org;\n }\n\n /** `GET /api/v1/users/me` — the authenticated identity. */\n async me(signal?: AbortSignal): Promise<Me> {\n return this.http.requestJson<Me>({ path: \"/api/v1/users/me\", signal });\n }\n\n /** `GET /api/v1/search?q=` — cross-org search. */\n async search(q: string, signal?: AbortSignal): Promise<unknown> {\n return this.http.requestJson({ path: \"/api/v1/search\", query: { q }, signal });\n }\n\n /** `GET /api/v1/resolve?uri=` — resolve a `cavs://` reference to concrete objects. */\n async resolve(reference: string, signal?: AbortSignal): Promise<unknown> {\n // Validate the reference locally before hitting the server.\n uri.parse(reference);\n return this.http.requestJson({ path: \"/api/v1/resolve\", query: { uri: reference }, signal });\n }\n\n /** `GET /api/v1/organizations/{org}/repositories`. */\n async listRepositories(org?: string, signal?: AbortSignal): Promise<unknown> {\n const slug = this.resolveOrg(org);\n return this.http.requestJson({\n path: `/api/v1/organizations/${encodeURIComponent(slug)}/repositories`,\n signal,\n });\n }\n}\n"],"mappings":"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","names":["resolve","path","name","resolve","stat"]}
package/package.json ADDED
@@ -0,0 +1,64 @@
1
+ {
2
+ "name": "@cavsnode/cavs-sdk",
3
+ "version": "0.1.0",
4
+ "description": "Official TypeScript/JavaScript SDK for CAVS Hub — the deduplicating, content-addressed artifact store for AI, CI/CD and game pipelines.",
5
+ "type": "module",
6
+ "license": "Apache-2.0",
7
+ "author": "CAVS",
8
+ "publishConfig": {
9
+ "access": "public"
10
+ },
11
+ "homepage": "https://github.com/orelvis15/cavs-sdks/tree/main/typescript",
12
+ "repository": {
13
+ "type": "git",
14
+ "url": "git+https://github.com/orelvis15/cavs-sdks.git",
15
+ "directory": "typescript"
16
+ },
17
+ "engines": {
18
+ "node": ">=18"
19
+ },
20
+ "main": "./dist/index.cjs",
21
+ "module": "./dist/index.js",
22
+ "types": "./dist/index.d.ts",
23
+ "exports": {
24
+ ".": {
25
+ "import": {
26
+ "types": "./dist/index.d.ts",
27
+ "default": "./dist/index.js"
28
+ },
29
+ "require": {
30
+ "types": "./dist/index.d.cts",
31
+ "default": "./dist/index.cjs"
32
+ }
33
+ }
34
+ },
35
+ "files": [
36
+ "dist"
37
+ ],
38
+ "sideEffects": false,
39
+ "keywords": [
40
+ "cavs",
41
+ "artifacts",
42
+ "content-addressed",
43
+ "deduplication",
44
+ "mlops",
45
+ "sdk"
46
+ ],
47
+ "scripts": {
48
+ "build": "tsup",
49
+ "typecheck": "tsc --noEmit",
50
+ "lint": "eslint src test",
51
+ "test": "vitest run --coverage",
52
+ "test:watch": "vitest"
53
+ },
54
+ "devDependencies": {
55
+ "@eslint/js": "^9.17.0",
56
+ "@types/node": "^20.14.0",
57
+ "@vitest/coverage-v8": "^2.1.8",
58
+ "eslint": "^9.17.0",
59
+ "tsup": "^8.3.5",
60
+ "typescript": "^5.7.2",
61
+ "typescript-eslint": "^8.18.0",
62
+ "vitest": "^2.1.8"
63
+ }
64
+ }