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

@assethub/api-client

v0.1.16

Published

Typed client for the public AssetHub API.

Readme

@assethub/api-client

Typed client for the public AssetHub API.

Advertised operations and Workspace Skills

discoverApiOperations(client) reads authenticated v1/v2 OpenAPI documents. Use searchApiOperations(discovery.catalog, query) and describeApiOperation(operation, operation.path.startsWith('/api/v1/') ? discovery.specs.v1 : discovery.specs.v2) to inspect contracts, then callApiOperation(client, discovery, {operation, path, query, body, operationId}) to execute one advertised JSON operation. V1 operation names have a V1 prefix and use discovery.specs.v1 for description. Mutations require an explicit operation UUID; retain its exact inputs and inspect any uncertain run before retrying. The server remains authoritative for gates, permissions, and billing.

Typed client.v2 Workspace Skill methods cover list/get, updates, controls, learning, and proposal prepare/get/accept. They preserve server-owned actor checks and optimistic revisions. learnWorkspaceSkill(input, {idempotencyKey: operationUuid}) requires a stable UUID; reuse the same UUID and input to recover its original learning root. Creator approval requires a human decision.

Personal API keys

Use createAssetHubClient({apiKey, workspaceId}) with an ah_pat_ personal key. The client sends X-AssetHub-Workspace on JSON and streaming requests, including canvas and historical asset operations. The server enforces current membership, workspace scope, and read/write permissions; the key does not grant account, member, or key administration.

Discover accessible workspaces with createWorkspaceClient({accessToken: apiKey}) and .list({query, limit, cursor}) (limit 1–100). Personal responses include authentication: 'personal' and an optional nextCursor. .select(workspaceId) validates access and returns the selected workspace; it does not alter a browser session. Workspace keys and user access tokens retain their existing behavior.

Historical assets

Scoped to the API key workspace: client.v2.listMeshes({query, cursor, limit}), listGraphs({cursor, limit}), and getGraph(graphId, {source, artifactId, direction, depth}) read existing UI assets and graphs. Use getAsset(assetId) for a signed mesh download URL. Continue pagination until nextCursor is null, even after an empty graph page. Generated graphs read the current authoritative head; uploaded graphs use source: 'upload'. A graph export retains blob references, not downloaded bytes.

Recorded canvas executions

Discover availability with client.v2.getCapabilities(). Create a canvas with createCanvas({name}, {idempotencyKey: operationUuid}), then pass executionContext: {canvasId, clientOperationId, source: 'api'} to generateImage or generateMesh, with the same clientOperationId as idempotencyKey. Responses retain existing fields and add execution. Poll getRun(runId) for durable outputs; listCanvasRuns, getCanvasGraph, and the evaluation submission/ list/get methods use the same owner-scoped records. getRun accepts an AbortSignal.

Existing generation requests without context keep their previous behavior. listCanvasNodes(canvasId) discovers saved UI shape IDs and available actions. For native mesh generation or composition, pass executionContext.canvasNode: {nodeId: 'shape:...'} and omit mesh sources or composer parts/reference. The server uses that node's saved inputs and settings; optional model/params or composer mode/version overrides still apply. A retry with the same operation ID retains the original resolved inputs. Mesh receipts include execution.meshGeneration with the canonical mesh ID and progress when available. Native node actions require the api_canvas_native_nodes feature gate.

Canvas execution is available to authenticated users with access to the selected workspace; unavailable evaluators are explicitly reported by capability discovery. External evaluation reports are agent submissions, not human approval or server-verified judgments.

Native Composer refinement uses client.v2.getMeshRefinementModes() for the available mode policies and client.v2.refineMesh({...}, {idempotencyKey}) for durable execution. Supply every part's ten-number transform and an instruction; the returned execution.operation is mesh.refine, and incomplete native results use status: 'needs_review'. A refinement receipt can carry the final composition.parts, composition.transforms, composition.referenceTransform, and a refinement report.

import {createAssetHubClient} from '@assethub/api-client'

const client = createAssetHubClient({
  apiKey: process.env.ASSETHUB_API_KEY!,
})

const models = await client.v2.listModels()

const segmented = await client.v2.segment({
  source: {resourceId: '<mesh-resource-id>'},
  granularity: 'balanced',
})
const result = await client.v2.pollJob(segmented.jobId)

for await (const event of client.v2.editImage({
  source: {resourceId: '<image-resource-id>'},
  goalId: 'Clean Up',
})) {
  console.log(event)
}

Texture generation defaults to Tripo when modelId is omitted. Select Meshy Retexture with exactly one style input: style_prompt or referenceSource. Meshy texture_quality: 'extreme' produces 8K and bills its higher-quality plan; detailed is the 4K default. Discover current prices through the model catalog.

const textured = await client.v2.texture({
  source: {resourceId: '<mesh-resource-id>'},
  modelId: 'meshProcess.meshy_retexture',
  style_prompt: 'Weathered bronze with subtle patina',
  texture_quality: 'extreme',
  pbr: true,
})
const textureResult = await client.v2.pollJob(textured.jobId)

// Alternatively, use a completed image upload as the style reference.
const referenced = await client.v2.texture({
  source: {resourceId: '<mesh-resource-id>'},
  modelId: 'meshProcess.meshy_retexture',
  referenceSource: {uploadId: '<completed-image-upload-id>'},
})
const referencedResult = await client.v2.pollJob(referenced.jobId)

textureQuality remains an alias of texture_quality; if both are supplied, they must match. source and referenceSource accept uploadId, resourceId, fileRef, or url.

NDJSON workflow methods throw AssetHubWorkflowError when a failure arrives inside an HTTP 200 stream, so callers do not have to mistake stream acceptance for completed generation.

The client only talks to the public /api/v1 and /api/v2 surfaces. It must not import AssetHub server internals, database clients, or private app modules.

Production automation accepts writeToCanvas: true, config.meshCompare.models (up to six model IDs), and config.cleanup.prompt when cleanBackground is enabled. Prefer config.autoCompose: false to disable composition; the legacy config.meshCompare.autoCompose: false remains supported when the top-level switch is omitted. Neither client inserts a composition default.

Reusable project context and moodboards

v2.importCanvasAsset, getCanvasContext and putCanvasContext manage owned references and versioned context. generateImage accepts projectContext and moodboardRevisionId with a matching executionContext; saved run inputs retain the context hash and reference IDs. Native moodboard CRUD/analysis methods remain internal actor gated. languageText and languageVision use the existing public text/vision routes and accept an idempotency key for safe response recovery.

Account-authenticated team membership is available through createWorkspaceClient: listMembers(workspaceId), inviteMember(workspaceId, {email, role, resend?}), setMemberRole(workspaceId, {userId, role}), and removeMember(workspaceId, userId). These calls use a user access token, preserve workspace MFA proofs, and never retry mutations automatically. See the CLI README for permissions and email recovery.

Canvas handoff export (staged)

const handoff = await client.v2.exportCanvas(42, {mesh: 'mesh_123'})

Omit mesh to include the owned canvas's visible assets and recorded ancestors. CanvasExport supplies signed file URLs, safe generation steps, missing-evidence warnings and an explicit truncated indicator. This reads UI and API history; canvas wiring does not establish actual mesh inputs. URLs expire after one hour. The workflow_canvas_handoff_enabled gate controls the additive route.