Observed since 21 Oct, 08:56 UTC
No superseded metadata states collected. Unchanged observations do not create new revisions.
@0xhoneyjar/freeside-storage-client
Type-safe URL builders + codex consumers for the freeside-storage URL contract. EffectTS Schema validates inputs/outputs; URL_CONTRACT_V1 is the source of truth.
@freeside-storage/clientType-safe URL builders + codex consumers for the freeside-storage URL contract. EffectTS Schema validates inputs; typed errors make failure modes first-class; codex-authority cascade for per-token overrides (read-only).
import {
miberaImageURL, // sync, hash → URL
miberaImageURLByToken, // Effect, tokenId → URL (codex)
miberaMetadataURL, // sync, tokenId → manifest URL
mstImageURL, // Effect, tokenId → MST image (handles timestamp-suffix)
mstMetadataURL, // sync, tokenId → honeyroad endpoint
grailImageURL, // Effect, tokenId → grail image (codex authority)
} from "@freeside-storage/client";
Sync builders are pure functions. Async builders return Effect.Effect<string, AssetError> and integrate codex authority + remote fetch.
Three things bare TypeScript doesn't give you:
import { TokenId, Sha40 } from "@freeside-storage/client";
import { Schema } from "effect";
const decoded = Schema.decodeEither(TokenId)(rawNumber);
// → Either<ParseError, ValidatedTokenId>
Bad inputs surface AT THE BOUNDARY with a typed error, not three layers deep in a render tree.
Effect<A, E, R> — A is success, E is a typed error union, R is the dependency context. Errors are first-class values:
type AssetError =
| NotFoundError // collection + tokenId
| MalformedURLError // raw + reason
| VersionDriftError // expected + got
| MissingHashError // tokenId + source
| NotGrailError // tokenId
Consumers Effect.catchTag("NotFoundError", ...) to handle each case.
import { Effect, pipe } from "effect";
import { mstImageURL } from "@freeside-storage/client";
const fetchWithFallback = (tokenId: number) =>
pipe(
mstImageURL(tokenId),
Effect.timeout("3 seconds"),
Effect.retry({ times: 2 }),
Effect.catchTag("NotFoundError", () =>
Effect.succeed("https://example.com/fallback.webp"),
),
);
Each pipe step is a composable layer. Same primitives across honeyroad, dimensions, midi.
URL_CONTRACT_V1 (from @freeside-storage/protocol) is the source of truth. Builders return URLs where bytes live TODAY — both canonical routes and legacyRoutes are consumed.
Mibera image URLs resolve via the reveal_phase{N}/images/{hash}.png legacyRoute shape (where bytes live), since URL_CONTRACT_V1 marks the canonical Mibera/final/{tokenId}.png as gated by the optional mibera-2 polish cycle.
Grail URLs are NOT constructed from slug + extension — extensions are heterogeneous (.png / .PNG), some slugs contain spaces. The codex mibera-image-urls.json publishes the full URL per tokenId; the client reads.
Per [[consuming-codex-overrides]] doctrine. The client reads the published codex artifacts; never writes.
| codex source | consumer | what it provides |
|---|---|---|
mibera-image-urls.json | lookupMiberaURL(tokenId) | tokenId → published image URL |
grails.jsonl | lookupGrail(tokenId) | grail identity (id, name, slug, category) |
In-memory cache per source URL. Call resetMiberaURLCache() / resetGrailCache() to clear (testing).
pnpm add @freeside-storage/client effect
pnpm -F @freeside-storage/client test
Download counts and popularity will appear here as the collector receives them.
| Package / target | Requirement | Relationship |
|---|---|---|
effectEnvironment{
"local_name": "effect",
"alias": false,
"peer_metadata": null
} | ^3.10.0 | runtime |
@0xhoneyjar/freeside-storage-protocolEnvironment{
"local_name": "@0xhoneyjar/freeside-storage-protocol",
"alias": false,
"peer_metadata": null
} | 0.0.1 | runtime |
@types/nodeEnvironment{
"local_name": "@types/node",
"alias": false,
"peer_metadata": null
} | ^20.12.0 | development |
typescriptEnvironment{
"local_name": "typescript",
"alias": false,
"peer_metadata": null
} | ^5.4.0 | development |
vitestEnvironment{
"local_name": "vitest",
"alias": false,
"peer_metadata": null
} | ^2.1.0 | development |
Source distribution
{
"integrity": "sha512-wfZxwcvfvDSuriP6zdcJkPiwdYd3skxTIJ66rzYmrPaL1WzRRXbJWE/P+hG1uo1IUeez8ajYPO7KZDR6fjAmUA==",
"shasum": "ca5936dc18a4914a51d2dad99635b7d4bc27ba84",
"tarball": "https://registry.npmjs.org/@0xhoneyjar/freeside-storage-client/-/freeside-storage-client-0.1.0.tgz",
"fileCount": 33,
"unpackedSize": 51910,
"signatures": [
{
"keyid": "SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U",
"sig": "MEYCIQDZLdkcmPQ7E7KW8lkyyHABp4PxiZh2IP0FqQeFzpTS1AIhAPH7Fi3ABEfkffEy/4phleb/PZFTxNIv8CuuXJqm+aN6"
}
]
}Shared repository data · GitHub
Observed since 21 Oct, 08:56 UTC
No superseded metadata states collected. Unchanged observations do not create new revisions.
package_version:d6f2fa8b2fb60fea56230654aa20c2c204d7c41b1fe802c4fed24ecb4314498e