@drawcall/market
Typed client, dependency resolver, and CLI for the Drawcall Market — an asset marketplace for 3D models, textures, animations, audio, environments, flipbooks, and templates.
This package is the single source of truth for the Market API surface: the oRPC contract, Zod schemas, and TypeScript types. It ships both a programmatic API and the market CLI.
Install
npm install @drawcall/market
Usage
createMarketClient is the one API. It returns a fully-typed oRPC client where every procedure — search, exact, downloadZip, downloadPreviewImage, uploadZip, generate, installMetadata — is type-checked end-to-end against the contract.
import { createMarketClient } from '@drawcall/market'
const client = createMarketClient()
const asset = await client.asset.exact({ name: 'my-model', includeUnapproved: false })
const zip = await client.asset.downloadZip({ name: 'my-model', version: asset.latestVersion })
Reads (search, exact, downloadZip, downloadPreviewImage, installMetadata) are public. uploadZip and generate require an authToken.
Searching
client.asset.search takes a query plus paging/sorting and returns a paginated list:
const page = await client.asset.search({
query: 'robot',
type: 'model',
page: 1,
limit: 12,
includeUnapproved: false,
sort: 'relevance',
})
Output format
search resolves to a PaginatedList<AssetSearchResult>:
{
items: AssetSearchResult[]
total: number
page: number
limit: number
totalPages: number
}
Each AssetSearchResult is:
{
id: string
name: string
type: string
description: string | null
ownerId: string
createdAt: Date
updatedAt: Date
latestVersion: string
approved: boolean
npmDependencies: string
assetDependencies: string
skillDependencies: string
previewUrl: string | null
}
The three *Dependencies fields are JSON strings (parse with JSON.parse); everything else is ready to use.
Previews
previewUrl is the image URL for a result, or null for types without a preview (only model, humanoid-model, texture, environment, and flipbook have one). It is a plain WebP URL served directly from object storage, so drop it straight into an <img src> and the browser fetches, caches, and lazy-loads it:
import { createMarketClient } from '@drawcall/market'
const client = createMarketClient()
const { items } = await client.asset.search({
query: 'robot',
type: 'model',
page: 1,
limit: 12,
includeUnapproved: false,
sort: 'relevance',
})
for (const item of items) {
if (!item.previewUrl) continue
}
Preview keys are random and unguessable, so the URLs are safe to serve even for unapproved assets. The runnable examples/market-ui Vite app renders results immediately and lets the browser load previews from these URLs.
resolve — dependency resolution
Resolve a set of assets (and their transitive asset/npm/skill dependencies) to a concrete, installable plan. The CLI and any server-side caller share this resolver:
import { createMarketClient, resolve } from '@drawcall/market'
const client = createMarketClient()
const plan = await resolve(client.asset, [{ name: 'my-model', range: '^1.0.0' }])
plan.assets
plan.npmDependencies
plan.skillDependencies
The Node-only filesystem install (download + write + package.json merge + skills add) is available from the @drawcall/market/install entry point and is used by the CLI.
CLI
npx @drawcall/market install my-model
npx @drawcall/market list
npx @drawcall/market search robot --type model
npx @drawcall/market preview my-model
npx @drawcall/market upload my-model ./my-model.zip "A robot" --type model
npx @drawcall/market login
Reads (install, list, search, preview) work without auth; upload and generate require market login. After an install, the CLI prints each asset's type-specific post-install note beneath that asset.
list is an offline local inventory command. It reads .drawcall/market-lock.json from the nearest package root and prints exact installed asset names, versions, types, and installed file paths.
Run npx @drawcall/market skill to print the agent workflow guidance, or npx @drawcall/market --help for the full command list.