@game-infra/file-storage-schemas
v0.1.8
Published
File-storage-service API contract: upload/download/metadata/stats schemas + toad-contracts endpoint definitions
Readme
@game-infra/file-storage-schemas
File-storage-service API contract: valibot schemas plus toad-contracts defineApiContract definitions for the upload flow (presigned + direct + confirm), content download/delete/metadata/list/bulk-check/copy, and usage statistics. Built on top of @game-infra/api-schemas-core, which supplies the shared createSuccessResponseSchema / ApiResponseSchema wrappers.
Published to npm. Also consumable as sibling source (exports points at src/).
Install
// pnpm sibling checkout
"@game-infra/file-storage-schemas": "link:../../game-infra/packages/schemas/file-storage-schemas"
// or from npm
"@game-infra/file-storage-schemas": "^0.1.0"valibot is a peer dependency (^1.4.0); the consumer provides it. @game-infra/api-schemas-core comes along as a dependency.
Usage
Contracts carry method, path, params, and request/response schemas in one object. Build a URL with pathResolver, derive the route pattern with mapApiContractToPath:
import { contentDownloadContract, requestUploadContract } from "@game-infra/file-storage-schemas";
import { mapApiContractToPath } from "@toad-contracts/valibot";
requestUploadContract.pathResolver(); // '/content/request-upload'
contentDownloadContract.pathResolver({ storageId: "abc" }); // '/content/abc'
mapApiContractToPath(contentDownloadContract); // '/content/:storageId'List and stats endpoints take query params, modeled on the contract via requestQuerySchema. Their pathResolver returns the base path; the client appends the validated query:
import { contentListContract, statsBreakdownContract } from "@game-infra/file-storage-schemas";
contentListContract.pathResolver(); // '/content'
statsBreakdownContract.pathResolver(); // '/stats/breakdown'Register on a Hono service with @toad-contracts/hono (buildHonoRoute) and call from a frontend with @toad-contracts/frontend-http-client (sendByApiContract) — both drive off the same contract objects.
Build a full asset URL for images or audio without going through a resolver:
import { buildAssetDownloadUrl } from "@game-infra/file-storage-schemas";
buildAssetDownloadUrl("https://cdn.example.com", "abc"); // 'https://cdn.example.com/content/abc'Extension points
- Use cases:
ASSET_USE_CASES(image/music/sfx) and theuseCasefield are plain strings; games can add their own without a schema change. - Image processing:
RESIZE_MODESandIMAGE_FORMATSenumerate the supported resize/output options for image assets. - Owner model:
OwnerTypeSchema(player/developer/game) scopes stored content; re-tighten per game via your own validation.
Migrating from golem-forge
The old FileStorageApiPaths constants and FileStoragePathResolvers / FileStoragePathPatterns helpers are gone. Get a URL from the contract itself with contract.pathResolver(params) and the :param route pattern with mapApiContractToPath(contract). List/stats query params live on each contract's requestQuerySchema and are appended by the client. Prefer driving requests through @toad-contracts/frontend-http-client (sendByApiContract) and routes through @toad-contracts/hono (buildHonoRoute), which consume the contract directly so you never touch a raw path. The buildAssetDownloadUrl(baseUrl, storageId) helper is retained for prefixing an absolute CDN base onto the content download path.
Dependencies
@game-infra/api-schemas-core (shared response wrappers), @toad-contracts/core, @toad-contracts/valibot; peer valibot.
Consumers
file-storage-service (the Cloudflare Worker that serves these endpoints), and the control-center / asset-manager frontend clients that upload, list, and download assets.
