npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@ivcap/client

v0.1.0

Published

TypeScript/JavaScript client SDK for IVCAP – a platform for offering and ordering analytics services

Downloads

30

Readme

@ivcap/client

TypeScript / JavaScript client SDK for IVCAP – a platform for offering, discovering and ordering analytics services.

npm version license


Table of Contents


Features

  • 🔐 Auth – bearer-token injection, env-variable fallback (IVCAP_JWT)
  • 📦 Typed resourcesartifacts, services, jobs, aspects, queues, projects, secrets
  • ♾️ Async iteration – lazy cursor-based pagination with for await...of
  • 🔄 Fire-and-forget jobsjobs.createAndWait() submits and polls until done
  • 🚦 Rich errors – typed error classes (NotFoundError, UnauthorizedError, …)
  • 🌐 Universal – works in Node ≥ 18, modern browsers, edge runtimes (Axios-based)
  • 📝 ESM + CJS – ships both module formats plus TypeScript declarations

Installation

npm install @ivcap/client
# or
yarn add @ivcap/client
# or
pnpm add @ivcap/client

Quick Start

import { IvcapClient } from "@ivcap/client";

const client = new IvcapClient({
  baseUrl: "https://develop.ivcap.net",
  token: process.env.IVCAP_JWT,
});

// ── Browse services ──────────────────────────────────────────────────────────
for await (const svc of client.services.list()) {
  console.log(svc.id, svc.name);
}

// ── Inspect a service's parameter schema ─────────────────────────────────────
const detail = await client.services.get("urn:ivcap:service:my-analysis-service");
detail.parameters.forEach(p => console.log(" ", p.name, p.type));

// ── Upload an input artifact ─────────────────────────────────────────────────
const artifact = await client.artifacts.upload(
  JSON.stringify({ temperature: [21.3, 22.1, 19.8] }),
  { name: "sensor-data.json", contentType: "application/json" }
);
console.log("Uploaded:", artifact.id);

// ── Submit a job and wait for results ────────────────────────────────────────
const job = await client.jobs.createAndWait(
  "urn:ivcap:service:my-analysis-service",
  {
    parameters: [
      { name: "input", value: artifact.id },
      { name: "threshold", value: "0.05" },
    ],
    name: "My analysis run",
  },
  {
    pollInterval: 5_000,  // check every 5 s
    timeout: 300_000,     // give up after 5 min
    onUpdate: (j) => console.log("status:", j.status),
  }
);

if (job.status === "succeeded") {
  for (const product of job.products.items) {
    console.log("Product:", product.id, product.mimeType);
    const text = await client.artifacts.downloadText(product.id);
    console.log(text);
  }
}

Key Concepts

| Entity | URN pattern | Description | |--------|-------------|-------------| | Service | urn:ivcap:service:<uuid> | A registered analytic capability with defined parameters | | Job | urn:ivcap:job:<uuid> | A single execution of a service | | Artifact | urn:ivcap:artifact:<uuid> | Any binary or structured data blob stored on the platform | | Aspect | urn:ivcap:aspect:<uuid> | Typed, time-stamped metadata attached to any entity |

Note on terminology: Some parts of the IVCAP platform and the ivcap CLI still use the term order for jobs. These mean the same thing. The canonical term is now job.


Configuration

| Option | Type | Default | Description | |-----------|----------|---------|-------------| | baseUrl | string | IVCAP_URL env var | Base URL of the IVCAP deployment | | token | string | IVCAP_JWT env var | Bearer authentication token | | timeout | number | 30000 | Request timeout in milliseconds | | headers | Record<string,string> | – | Extra HTTP headers sent with every request |

export IVCAP_URL=https://develop.ivcap.net
export IVCAP_JWT=eyJhbGciOiJ...
const client = new IvcapClient(); // picks up env vars automatically

Resources

client.artifacts

| Method | Description | |--------|-------------| | list(opts?) | Async iterator over all artifacts (lazy pagination) | | listPage(opts?) | Fetch a single page | | get(id) | Fetch full artifact metadata | | upload(data, opts?) | Upload string / Buffer / Blob / ReadableStream | | download(id) | Download as ArrayBuffer | | downloadText(id) | Download as UTF-8 string | | downloadJson<T>(id) | Download and JSON-parse |

client.services

| Method | Description | |--------|-------------| | list(opts?) | Async iterator over all available services | | listPage(opts?) | Fetch a single page | | get(id) | Fetch service details including parameter schema |

client.jobs

Jobs are always scoped to a service. All methods take a serviceId as their first argument. API paths follow /1/services/{serviceId}/jobs/....

| Method | Description | |--------|-------------| | list(serviceId, opts?) | Async iterator over all jobs for a service | | listPage(serviceId, opts?) | Fetch a single page | | get(serviceId, jobId) | Fetch job status, parameters, and products | | create(serviceId, req) | Submit a new job | | createAndWait(serviceId, req, opts?) | Submit and poll until terminal state | | waitUntilDone(serviceId, jobId, opts?) | Poll an existing job until done | | getOutput(serviceId, jobId) | Retrieve the structured result payload | | JobResource.buildParameters(obj) | Convert {key: val}JobParameter[] |

Job status values: pendingscheduledexecutingsucceeded / failed / error

client.aspects

Aspects are typed, time-stamped metadata records attached to any entity URN. They are the foundation of IVCAP's provenance model.

| Method | Description | |--------|-------------| | list(opts?) | Async iterator filtered by entity, schema, time, etc. | | listPage(opts?) | Fetch a single page | | get(id) | Fetch aspect detail | | create(input) | Assert a new aspect on an entity | | update(id, content) | Retract + re-assert with new content | | retract(id) | Logically delete an aspect |

client.queues

| Method | Description | |--------|-------------| | list(opts?) | Async iterator over all queues | | get(id) | Fetch queue details | | create(req) | Create a queue | | delete(id) | Delete a queue | | enqueue(id, msg) | Publish a message | | dequeue(id) | Consume the next message (null if empty) |

client.projects

| Method | Description | |--------|-------------| | list(opts?) | Async iterator over all projects | | get(id) | Fetch project details | | create(req) | Create a project |

client.secrets

| Method | Description | |--------|-------------| | list() | List secret names + expiry (values not returned) | | get(name) | Retrieve a secret value | | set(req) | Create or update a secret | | delete(name) | Delete a secret |


Pagination

All list() methods return a PageIterator that lazily fetches pages as you consume items:

// Iterate item-by-item (lazy – only fetches pages as needed)
for await (const artifact of client.artifacts.list({ limit: 50 })) {
  process(artifact);
}

// Collect everything at once
import { collectAll } from "@ivcap/client";
const all = await collectAll(client.services.list());

// Or use the helper on the iterator itself
const all = await client.artifacts.list().toArray();

// First page only
const firstPage = await client.artifacts.list().firstPage();

// Callback style
await client.jobs.list(serviceId).forEach(async (job) => {
  console.log(job.id, job.status);
});

Typical Workflow

1. List available services     client.services.list()
2. Inspect a service           client.services.get(serviceId)
3. Upload input data           client.artifacts.upload(data, opts)
4. Submit a job                client.jobs.create(serviceId, req)
5. Poll for completion         client.jobs.waitUntilDone(serviceId, jobId)
   (or combine 4+5)            client.jobs.createAndWait(serviceId, req)
6. Download result artifacts   client.artifacts.download(productId)

Error Handling

import {
  IvcapClient,
  NotFoundError,
  UnauthorizedError,
  TimeoutError,
} from "@ivcap/client";

try {
  const job = await client.jobs.get(serviceId, "urn:ivcap:job:unknown");
} catch (err) {
  if (err instanceof NotFoundError) {
    console.error("Job not found:", err.resourceId);
  } else if (err instanceof UnauthorizedError) {
    console.error("Check your IVCAP_JWT token");
  } else if (err instanceof TimeoutError) {
    console.error("Job polling timed out");
  } else {
    throw err;
  }
}

Available error classes:

| Class | HTTP status | |-------|-------------| | BadRequestError | 400 | | UnauthorizedError | 401 | | ForbiddenError | 403 | | NotFoundError | 404 | | ConflictError | 409 | | InvalidParameterError | 422 | | NotImplementedError | 501 | | ServiceUnavailableError | 503 | | AmbiguousResultError | (multiple matches) | | TimeoutError | (polling timeout) | | IvcapError | (base class) |


Advanced Usage

Using JobResource.buildParameters

import { JobResource } from "@ivcap/client";

const job = await client.jobs.create(serviceId, {
  name: "fire-risk-analysis",
  parameters: JobResource.buildParameters({
    region:     "Tasmania-North",
    threshold:  "0.05",
    "input-data": artifactId,
  }),
});

Provenance queries via Aspects

// What jobs produced a given artifact?
for await (const aspect of client.aspects.list({
  entity: artifactId,
  schema: "urn:ivcap:schema:artifact-usedBy-order.1",
})) {
  console.log(aspect.content);
}

// Historical query: what was known at a point in time?
const historical = await client.aspects.list({
  entity: artifactId,
  atTime: "2025-06-01T12:00:00Z",
}).toArray();

Token rotation

const client = new IvcapClient({ baseUrl: "..." });

setInterval(async () => {
  const newToken = await myTokenProvider.refresh();
  client.setToken(newToken);
}, 60_000);

Low-level HTTP access

const axiosInstance = client.getHttpClient().getAxios();
const raw = await axiosInstance.get("/1/some/custom/endpoint");

Browser / Vite / Next.js

The package ships both ESM (dist/index.mjs) and CJS (dist/index.js) builds with TypeScript declarations. Axios handles the HTTP layer and works transparently in browser environments — no polyfills needed for modern browsers.


Contributing

Contributions are very welcome! The preferred way to contribute is to open a Pull Request on GitHub. If you've found a bug, have a feature idea, or spotted something wrong in the documentation but don't have time for a fix, please raise an issue instead — just include enough detail (steps to reproduce, expected vs. actual behaviour, SDK version, runtime) so we can act on it.

See CONTRIBUTING for the full guide (setup, code style, docs workflow).


Development

npm install           # install dependencies
npm run typecheck     # type-check without emitting
npm run build         # CJS + ESM + .d.ts → dist/
npm test              # run tests (Vitest)
npm run test:watch    # watch mode
npm run test:coverage # coverage report

License

MIT © Commonwealth Scientific and Industrial Research Organisation (CSIRO) and contributors