{"_id":"@0xhoneyjar/freeside-storage-client","name":"@0xhoneyjar/freeside-storage-client","dist-tags":{"latest":"0.1.0"},"versions":{"0.1.0":{"name":"@0xhoneyjar/freeside-storage-client","version":"0.1.0","description":"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.","license":"MIT","type":"module","main":"./dist/index.js","types":"./dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"}},"publishConfig":{"access":"public"},"repository":{"type":"git","url":"git+https://github.com/0xHoneyJar/freeside-storage.git","directory":"packages/storage-client"},"dependencies":{"effect":"^3.10.0","@0xhoneyjar/freeside-storage-protocol":"0.0.1"},"devDependencies":{"@types/node":"^20.12.0","typescript":"^5.4.0","vitest":"^2.1.0"},"scripts":{"build":"tsc -b","typecheck":"tsc --noEmit","clean":"rm -rf dist","test":"vitest run","test:watch":"vitest"},"_id":"@0xhoneyjar/freeside-storage-client@0.1.0","bugs":{"url":"https://github.com/0xHoneyJar/freeside-storage/issues"},"homepage":"https://github.com/0xHoneyJar/freeside-storage#readme","_integrity":"sha512-wfZxwcvfvDSuriP6zdcJkPiwdYd3skxTIJ66rzYmrPaL1WzRRXbJWE/P+hG1uo1IUeez8ajYPO7KZDR6fjAmUA==","_resolved":"/private/var/folders/7g/vv4rdz6165zg2fcg2x5wc_r00000gn/T/825a6cc316c1b3dba547787b7d80845e/0xhoneyjar-freeside-storage-client-0.1.0.tgz","_from":"file:0xhoneyjar-freeside-storage-client-0.1.0.tgz","_nodeVersion":"23.3.0","_npmVersion":"10.9.0","dist":{"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"}]},"_npmUser":{"name":"zksoju","email":"underrated@gmail.com"},"directories":{},"maintainers":[{"name":"janitooor","email":"jani@0xhoneyjar.xyz"},{"name":"zerkereth","email":"zerkereth@gmail.com"},{"name":"zksoju","email":"underrated@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/freeside-storage-client_0.1.0_1777757915371_0.8664774305683174"},"_hasShrinkwrap":false}},"time":{"created":"2026-05-02T21:38:35.290Z","0.1.0":"2026-05-02T21:38:35.504Z","modified":"2026-05-02T21:38:35.762Z"},"maintainers":[{"name":"janitooor","email":"jani@0xhoneyjar.xyz"},{"name":"zerkereth","email":"zerkereth@gmail.com"},{"name":"zksoju","email":"underrated@gmail.com"}],"description":"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.","homepage":"https://github.com/0xHoneyJar/freeside-storage#readme","repository":{"type":"git","url":"git+https://github.com/0xHoneyJar/freeside-storage.git","directory":"packages/storage-client"},"bugs":{"url":"https://github.com/0xHoneyJar/freeside-storage/issues"},"license":"MIT","readme":"# `@freeside-storage/client`\n\nType-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).\n\n## What it gives you\n\n```ts\nimport {\n  miberaImageURL,           // sync, hash → URL\n  miberaImageURLByToken,    // Effect, tokenId → URL (codex)\n  miberaMetadataURL,        // sync, tokenId → manifest URL\n  mstImageURL,              // Effect, tokenId → MST image (handles timestamp-suffix)\n  mstMetadataURL,           // sync, tokenId → honeyroad endpoint\n  grailImageURL,            // Effect, tokenId → grail image (codex authority)\n} from \"@freeside-storage/client\";\n```\n\nSync builders are pure functions. Async builders return `Effect.Effect<string, AssetError>` and integrate codex authority + remote fetch.\n\n## Why EffectTS\n\nThree things bare TypeScript doesn't give you:\n\n### 1. Schema-validated inputs\n\n```ts\nimport { TokenId, Sha40 } from \"@freeside-storage/client\";\nimport { Schema } from \"effect\";\n\nconst decoded = Schema.decodeEither(TokenId)(rawNumber);\n// → Either<ParseError, ValidatedTokenId>\n```\n\nBad inputs surface AT THE BOUNDARY with a typed error, not three layers deep in a render tree.\n\n### 2. Typed error channel\n\n`Effect<A, E, R>` — `A` is success, `E` is a typed error union, `R` is the dependency context. Errors are first-class values:\n\n```ts\ntype AssetError =\n  | NotFoundError       // collection + tokenId\n  | MalformedURLError   // raw + reason\n  | VersionDriftError   // expected + got\n  | MissingHashError    // tokenId + source\n  | NotGrailError       // tokenId\n```\n\nConsumers `Effect.catchTag(\"NotFoundError\", ...)` to handle each case.\n\n### 3. Composable layers\n\n```ts\nimport { Effect, pipe } from \"effect\";\nimport { mstImageURL } from \"@freeside-storage/client\";\n\nconst fetchWithFallback = (tokenId: number) =>\n  pipe(\n    mstImageURL(tokenId),\n    Effect.timeout(\"3 seconds\"),\n    Effect.retry({ times: 2 }),\n    Effect.catchTag(\"NotFoundError\", () =>\n      Effect.succeed(\"https://example.com/fallback.webp\"),\n    ),\n  );\n```\n\nEach `pipe` step is a composable layer. Same primitives across honeyroad, dimensions, midi.\n\n## Substrate-truth resolution\n\n`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.\n\nMibera 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.\n\nGrail 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.\n\n## Codex consumers (read-only)\n\nPer [[consuming-codex-overrides]] doctrine. The client reads the published codex artifacts; never writes.\n\n| codex source | consumer | what it provides |\n|---|---|---|\n| `mibera-image-urls.json` | `lookupMiberaURL(tokenId)` | tokenId → published image URL |\n| `grails.jsonl` | `lookupGrail(tokenId)` | grail identity (id, name, slug, category) |\n\nIn-memory cache per source URL. Call `resetMiberaURLCache()` / `resetGrailCache()` to clear (testing).\n\n## Install\n\n```sh\npnpm add @freeside-storage/client effect\n```\n\n## Test\n\n```sh\npnpm -F @freeside-storage/client test\n```\n","readmeFilename":"README.md","_rev":"1-6a7032d7d31ff18ac1af9902798832e2"}