@drawcall/market
v0.1.66
Published
Typed client, dependency resolver, and CLI for the [Drawcall Market](https://market.drawcall.ai) — an asset marketplace for 3D models, textures, animations, audio, environments, flipbooks, and templates.
Readme
@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/marketUsage
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()
// createMarketClient({ baseUrl, fetch, authToken }) to override the API host,
// supply a custom fetch, or authenticate reads/writes.
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', // optional AssetType; omit to search every type
page: 1,
limit: 12,
includeUnapproved: false,
sort: 'relevance', // 'relevance' | 'newest' | 'alphabetical'
})Output format
search resolves to a PaginatedList<AssetSearchResult>:
{
items: AssetSearchResult[]
total: number // total matches across all pages
page: number
limit: number
totalPages: number
}Each AssetSearchResult is:
{
id: string
name: string // globally unique, install by this name
type: string // AssetType, e.g. 'model'
description: string | null
ownerId: string
createdAt: Date
updatedAt: Date
latestVersion: string // semver of the latest published version
approved: boolean
npmDependencies: string // JSON-encoded Record<string, string>
assetDependencies: string // JSON-encoded Record<string, string>
skillDependencies: string // JSON-encoded Record<string, string>
previewUrl: string | null // image URL for an <img>, or 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
// <img src={item.previewUrl} loading="lazy">
}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 // resolved name@version per asset (with its type)
plan.npmDependencies // merged npm ranges
plan.skillDependencies // merged skill sourcesThe 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 # resolve + install by name
npx @drawcall/market list # list locally installed assets
npx @drawcall/market search robot --type model
npx @drawcall/market preview my-model # save the preview image
npx @drawcall/market pack ./my-model.zip --out ./my-model.packed.zip
npx @drawcall/market upload my-model ./my-model.zip "A robot" --type model
npx @drawcall/market login # device-authorization sign-inReads (install, list, search, preview) work without auth; pack is offline; upload and generate require market login. After an install, the CLI prints each asset's type-specific post-install note beneath that asset.
pack creates the same asset zip that upload sends. It runs offline, infers template packing from a root package.json, and accepts --type only when you need to override that inference. upload calls the shared pack step internally, then publishes.
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.
