{"_id":"@denna-labs/spec-client","_rev":"2-b6335475bde584c04222417b8c9254be","name":"@denna-labs/spec-client","dist-tags":{"latest":"1.1.0"},"versions":{"1.0.1":{"name":"@denna-labs/spec-client","version":"1.0.1","keywords":["denna-spec","json-schema","validation","cli"],"license":"MIT","_id":"@denna-labs/spec-client@1.0.1","maintainers":[{"name":"denna-labs-npm-org","email":"tech@denna.io"},{"name":"grace_tau","email":"grace@amatsu.io"}],"homepage":"https://github.com/daocraft/denna-spec-client#readme","bugs":{"url":"https://github.com/daocraft/denna-spec-client/issues"},"bin":{"denna":"dist/cli/index.js"},"dist":{"shasum":"c85eecf562e5b8ff9494ce9b89d7f5785c5a608b","tarball":"https://registry.npmjs.org/@denna-labs/spec-client/-/spec-client-1.0.1.tgz","fileCount":10,"integrity":"sha512-PnyHPJVheYXUCbpqJL9noj8he5lCpTaligfS3s7/W0D7W+OhOPuuBLz7qVl/Bkht0FQN52D2hRfS5i7ElYvq2w==","signatures":[{"sig":"MEUCIAMt4gluXRggJY+G+CF3kb2p8clBbCpWhmxGXWAYLiVXAiEAhTiONykZDg2yAodDBjq1QvsG0eqJGve9l/mTtJZhq/8=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":234270},"main":"./dist/index.cjs","type":"module","types":"./dist/index.d.ts","module":"./dist/index.js","engines":{"node":">=18.0.0"},"exports":{".":{"import":{"types":"./dist/index.d.ts","default":"./dist/index.js"},"require":{"types":"./dist/index.d.cts","default":"./dist/index.cjs"}}},"gitHead":"98a4716283cfc769eee403db80e18e49cd050e21","scripts":{"lint":"tsc --noEmit","test":"vitest run","build":"tsup","prepare":"npm run build","release":"semantic-release","prebuild":"rm -rf dist","test:watch":"vitest","prepublishOnly":"npm run build"},"_npmUser":{"name":"grace_tau","email":"grace@amatsu.io"},"repository":{"url":"git+https://github.com/daocraft/denna-spec-client.git","type":"git"},"_npmVersion":"10.9.7","description":"TypeScript library + CLI for loading and validating Denna Spec data files.","directories":{},"_nodeVersion":"20.20.1","dependencies":{"ajv":"^8.17.0","tsup":"^8.0.0","commander":"^13.0.0","typescript":"^5.7.0","ajv-formats":"^3.0.0","json-schema-to-typescript":"^15.0.0","@apidevtools/json-schema-ref-parser":"^11.0.0"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"vitest":"^3.0.0","@types/node":"^25.5.0","semantic-release":"^24.0.0","@semantic-release/git":"^10.0.0","@semantic-release/npm":"^12.0.0","@semantic-release/github":"^11.0.0","@semantic-release/changelog":"^6.0.0","@semantic-release/commit-analyzer":"^13.0.0","@semantic-release/release-notes-generator":"^14.0.0","conventional-changelog-conventionalcommits":"^8.0.0"},"_npmOperationalInternal":{"tmp":"tmp/spec-client_1.0.1_1774612286368_0.3668089683863609","host":"s3://npm-registry-packages-npm-production"}},"1.1.0":{"name":"@denna-labs/spec-client","version":"1.1.0","description":"TypeScript library + CLI for loading and validating Denna Spec data files.","repository":{"type":"git","url":"git+https://github.com/daocraft/denna-spec-client.git"},"publishConfig":{"access":"public"},"homepage":"https://github.com/daocraft/denna-spec-client#readme","bugs":{"url":"https://github.com/daocraft/denna-spec-client/issues"},"keywords":["denna-spec","json-schema","validation","cli"],"type":"module","main":"./dist/index.cjs","module":"./dist/index.js","types":"./dist/index.d.ts","bin":{"denna":"dist/cli/index.js"},"exports":{".":{"import":{"types":"./dist/index.d.ts","default":"./dist/index.js"},"require":{"types":"./dist/index.d.cts","default":"./dist/index.cjs"}}},"scripts":{"prebuild":"rm -rf dist","build":"tsup","test":"vitest run","test:watch":"vitest","lint":"tsc --noEmit","prepare":"npm run build","prepublishOnly":"npm run build","release":"semantic-release"},"dependencies":{"@apidevtools/json-schema-ref-parser":"^11.0.0","ajv":"^8.17.0","ajv-formats":"^3.0.0","commander":"^13.0.0","json-schema-to-typescript":"^15.0.0","tsup":"^8.0.0","typescript":"^5.7.0"},"devDependencies":{"@semantic-release/changelog":"^6.0.0","@semantic-release/commit-analyzer":"^13.0.0","@semantic-release/git":"^10.0.0","@semantic-release/github":"^11.0.0","@semantic-release/npm":"^12.0.0","@semantic-release/release-notes-generator":"^14.0.0","@types/node":"^25.5.0","conventional-changelog-conventionalcommits":"^8.0.0","semantic-release":"^24.0.0","vitest":"^3.0.0"},"engines":{"node":">=18.0.0"},"license":"MIT","_id":"@denna-labs/spec-client@1.1.0","gitHead":"0f39c91105b18953f0d69e9e91d8a7ce5393d6d3","_nodeVersion":"20.20.1","_npmVersion":"10.9.7","dist":{"integrity":"sha512-SCM3NJmQLED0gqi5ZLFSXhRMphN1mFKlCKs/ykeUs8YdfZ6acWy3uZjPLsRzSTya9A6iF5UtdsY36m0u48eogg==","shasum":"33a90998602f5935acc8f7a464eb05c7ac52b31a","tarball":"https://registry.npmjs.org/@denna-labs/spec-client/-/spec-client-1.1.0.tgz","fileCount":10,"unpackedSize":257008,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEYCIQDI52W8a65VK3dSr9MPEI8ujvxUM5WwWEbtPk09+7VLmQIhAJC1IHuR89sn62IdbZ+1+asqk+Yd+GgWxr/rzb1LHHjj"}]},"_npmUser":{"name":"grace_tau","email":"grace@amatsu.io"},"directories":{},"maintainers":[{"name":"denna-labs-npm-org","email":"tech@denna.io"},{"name":"grace_tau","email":"grace@amatsu.io"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/spec-client_1.1.0_1775024868952_0.18467298896765483"},"_hasShrinkwrap":false}},"time":{"created":"2026-03-27T11:51:26.238Z","modified":"2026-04-01T06:27:49.244Z","1.0.1":"2026-03-27T11:51:26.549Z","1.1.0":"2026-04-01T06:27:49.099Z"},"bugs":{"url":"https://github.com/daocraft/denna-spec-client/issues"},"license":"MIT","homepage":"https://github.com/daocraft/denna-spec-client#readme","keywords":["denna-spec","json-schema","validation","cli"],"repository":{"type":"git","url":"git+https://github.com/daocraft/denna-spec-client.git"},"description":"TypeScript library + CLI for loading and validating Denna Spec data files.","maintainers":[{"name":"denna-labs-npm-org","email":"tech@denna.io"},{"name":"grace_tau","email":"grace@amatsu.io"}],"readme":"# @denna-spec/client\n\nTypeScript library + CLI for loading, validating, and generating types from [Denna Spec](https://spec.denna.io) data files.\n\nDenna Spec is a convention for structuring protocol parameters as JSON files validated by JSON Schema 2020-12. This client handles the full lifecycle: schema-driven codegen at build time, and validated + typed data loading at runtime.\n\n## Install\n\n```bash\nnpm install @denna-spec/client\n```\n\n## Quick start\n\n### Load a data file\n\n```ts\nimport { DennaSpec } from '@denna-spec/client';\n\nconst denna = new DennaSpec();\nconst data = await denna.load('shared/stablecoin-addresses.denna-spec.json');\n\nconsole.log(data.metadata.kind); // \"io.denna.defi.address-registry\"\nconsole.log(data.addresses);\n```\n\n`load()` does the following in order:\n\n1. Resolves the source (file path, URL, or alias from config)\n2. Fetches and parses the JSON\n3. Reads the `$schema` field and fetches the schema\n4. Pre-loads any `$ref`-referenced schemas from disk to avoid network requests\n5. Validates with Ajv (JSON Schema 2020-12, strict mode)\n6. Dereferences `$ref` chains and hydrates missing optional fields with zero values\n7. Returns the typed result\n\n### Generate TypeScript types from schemas\n\n```ts\nimport { generateTypes } from '@denna-spec/client';\n\nconst output = await generateTypes({\n  schemas: ['https://spec.denna.io/v1/defi/rates.schema.json'],\n  output: './generated/denna-types.ts',\n});\n```\n\nThis produces TypeScript interfaces from JSON Schema files, plus a `SchemaTypeMap` interface that maps schema `$id` URLs to their root types.\n\n## CLI\n\nThe package ships a `denna` CLI with three commands.\n\n### `denna sync`\n\nRegenerate TypeScript types from the schemas listed in `denna.config.json`.\n\n```bash\ndenna sync\ndenna sync --config path/to/denna.config.json\n```\n\n### `denna load <source>`\n\nLoad, validate, and print a data file as JSON.\n\n```bash\ndenna load shared/stablecoin-addresses.denna-spec.json\ndenna load sky:spark/protocol-config --compact\n```\n\n### `denna validate <sources...>`\n\nValidate one or more data files. Supports glob patterns. Exits non-zero on failure.\n\n```bash\ndenna validate shared/*.denna-spec.json\ndenna validate sky:spark/* sky:obex/*\n```\n\n## Configuration\n\nCreate a `denna.config.json` in your project root (the CLI auto-discovers it by walking up from `cwd`):\n\n```json\n{\n  \"schemas\": [\n    \"https://spec.denna.io/v1/defi/rates.schema.json\",\n    \"./local/schemas/custom.schema.json\"\n  ],\n  \"output\": \"./generated/denna-types.ts\",\n  \"sources\": {\n    \"sky\": {\n      \"type\": \"filesystem\",\n      \"path\": \"../sky-parameters\"\n    },\n    \"remote\": {\n      \"type\": \"github\",\n      \"repo\": \"org/repo\",\n      \"ref\": \"main\"\n    }\n  }\n}\n```\n\n| Field | Description |\n|-------|-------------|\n| `schemas` | Schema URLs or file paths for codegen (`denna sync`) |\n| `output` | Output path for generated TypeScript types |\n| `sources` | Named aliases for data sources (filesystem paths or GitHub repos) |\n\n### Source aliases\n\nAliases let you reference data files without full paths:\n\n- `sky:spark/protocol-config` resolves to `<source.path>/spark/protocol-config.denna-spec.json` for filesystem sources, or the equivalent raw GitHub URL for GitHub sources.\n- Glob patterns work with aliases: `sky:spark/*`\n\n## API\n\n### `DennaSpec`\n\n```ts\nimport { DennaSpec } from '@denna-spec/client';\n\n// Auto-discover denna.config.json\nconst denna = new DennaSpec();\n\n// Explicit config path\nconst denna = new DennaSpec({ config: './denna.config.json' });\n\n// No config (resolve paths directly)\nconst denna = new DennaSpec({ config: false });\n\nconst data = await denna.load<MyType>('source');\n```\n\n### `generateTypes(options)`\n\n```ts\nimport { generateTypes } from '@denna-spec/client';\n\nconst ts = await generateTypes({\n  schemas: ['./schema.json'],\n  output: './types.ts', // optional — also writes to file\n});\n```\n\n### `loadConfig(path)` / `discoverConfig(startDir)`\n\n```ts\nimport { loadConfig, discoverConfig } from '@denna-spec/client';\n\nconst configPath = await discoverConfig(process.cwd());\nconst config = configPath ? await loadConfig(configPath) : null;\n```\n\n### Errors\n\nAll errors extend `DennaError`:\n\n| Class | When |\n|-------|------|\n| `DennaLoadError` | File not found, network error, HTTP error |\n| `DennaParseError` | Invalid JSON or invalid config structure |\n| `DennaValidationError` | Schema validation failure (includes `.errors` array with paths and messages) |\n| `DennaSchemaError` | Schema fetch/compile failure |\n\nAll errors preserve the original `cause` for debugging.\n\n## How data files work\n\nA `.denna-spec.json` file looks like:\n\n```json\n{\n  \"$schema\": \"https://spec.denna.io/v1/defi/rates.schema.json\",\n  \"metadata\": { \"kind\": \"io.denna.defi.rates\" },\n  \"rates\": {\n    \"ssrSpread\": { \"value\": 30, \"unit\": \"bps\" }\n  }\n}\n```\n\nThe `$schema` field points to the JSON Schema that validates the file. Schemas use JSON Schema 2020-12 and may reference shared type definitions via `$ref`.\n\n## License\n\nMIT\n","readmeFilename":"README.md"}