Catalog npm
Back to packageRELEASE DETAILS

0.1.0

npm

@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.

Published2 May 2026
Direct dependencies5
Transitive dependenciesNot calculated

README

Current package documentation

@freeside-storage/client

Type-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).

What it gives you

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.

Why EffectTS

Three things bare TypeScript doesn't give you:

1. Schema-validated inputs

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.

2. Typed error channel

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.

3. Composable layers

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.

Substrate-truth resolution

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.

Codex consumers (read-only)

Per [[consuming-codex-overrides]] doctrine. The client reads the published codex artifacts; never writes.

codex sourceconsumerwhat it provides
mibera-image-urls.jsonlookupMiberaURL(tokenId)tokenId → published image URL
grails.jsonllookupGrail(tokenId)grail identity (id, name, slug, category)

In-memory cache per source URL. Call resetMiberaURLCache() / resetGrailCache() to clear (testing).

Install

pnpm add @freeside-storage/client effect

Test

pnpm -F @freeside-storage/client test

Downloads & popularity

Awaiting observations

No metric observations yet

Download counts and popularity will appear here as the collector receives them.

Declared dependencies 5

Native requirements
5 direct targetsNot calculated transitive count
Package / targetRequirementRelationship
effect
Environment
{
  "local_name": "effect",
  "alias": false,
  "peer_metadata": null
}
^3.10.0runtime
@0xhoneyjar/freeside-storage-protocol
Environment
{
  "local_name": "@0xhoneyjar/freeside-storage-protocol",
  "alias": false,
  "peer_metadata": null
}
0.0.1runtime
@types/node
Environment
{
  "local_name": "@types/node",
  "alias": false,
  "peer_metadata": null
}
^20.12.0development
typescript
Environment
{
  "local_name": "typescript",
  "alias": false,
  "peer_metadata": null
}
^5.4.0development
vitest
Environment
{
  "local_name": "vitest",
  "alias": false,
  "peer_metadata": null
}
^2.1.0development

Distribution files

1 collected
Distribution 1

Source distribution

Source file
Checksums from source
{
  "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"
    }
  ]
}

Repository

PENDING
0xhoneyjar/freeside-storage

Shared repository data · GitHub

License detected in repository
Not collected

Metadata history

Meaningful changes
Current collected state Current

Observed since 21 Oct, 08:56 UTC

No superseded metadata states collected. Unchanged observations do not create new revisions.

Record identity

package_version:d6f2fa8b2fb60fea56230654aa20c2c204d7c41b1fe802c4fed24ecb4314498e

Other collected versions

View all collected versions →