Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 29 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -290,6 +290,35 @@ console.log('Resolved FHIR resources:', resolved.fhirResources);

This example above demonstrates the complete lifecycle: SHL generation, content addition, manifest builder persistence in server-side database, manifest serving, and client-side resolution. In a real application, you would implement persistence for the manifest builder state and serve the manifest endpoint from your backend server.

### Directories
A `Directory` is a lightweight, serializable collection of issuer metadata used by this library: each entry contains an issuer URL, its JWK descriptors (public keys) and optional CRL entries (revoked resource ids).

It provides a local/cached source of JWKS + CRL data so verification and lookup code can resolve public keys and revocation information without hitting network endpoints repeatedly.

It can be built through the following methods:

1. Build from a JSON manifest: `Directory.fromJSON`
2. Build by fetching from issuer endpoints: `Directory.fromURLs`
3. Build by loading the VCI snapshot: `Directory.fromVCI`

#### Building a Directory from VCI Snapshot
`Directory.fromVCI` is a convenience helper that fetches the VCI Directory snapshot published by The Commons Project and returns a Directory instance built from that snapshot.

Use it when you want a quick, canonical directory of issuer metadata (JWKS + CRLs) without manually assembling or maintaining a directory JSON.

```typescript
import { Directory } from 'kill-the-clipboard'

// top-level async context or inside an async function
try {
const directory = await Directory.fromVCI()
const issuers = directory.getIssuerInfo()
console.log('Loaded issuers:', issuers.length)
} catch (err) {
console.error('Failed to load VCI Directory:', err)
}
```

### Error Handling

The library provides granular error handling with specific error codes for different failure scenarios. Check each method documentation for the specific errors that can be thrown.
Expand Down
2 changes: 1 addition & 1 deletion demo/medplum-shl/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
"@tabler/icons-react": "^3.34.1",
"argon2": "^0.44.0",
"kill-the-clipboard": "workspace:../..",
"next": "15.4.6",
"next": "15.5.7",
"react": "19.1.1",
"react-dom": "19.1.1",
"uuid": "^11.1.0"
Expand Down
2 changes: 1 addition & 1 deletion demo/shl/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@
"@tabler/icons-react": "^3.34.1",
"argon2": "^0.44.0",
"kill-the-clipboard": "workspace:../..",
"next": "15.5.3",
"next": "15.5.7",
"react": "19.1.1",
"react-dom": "19.1.1",
"uuid": "^11.1.0"
Expand Down
207 changes: 43 additions & 164 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

26 changes: 26 additions & 0 deletions src/shc/directory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,32 @@ export class Directory {
return this.issuerInfo
}

/**
* Fetch a snapshot of the VCI Directory published by The Commons Project
* and build a {@link Directory} from it.
*
* This helper fetches a well-known VCI snapshot JSON file and delegates to
* `Directory.fromJSON` to produce a `Directory` instance. If the snapshot
* cannot be retrieved (non-2xx response) the function throws an Error.
*
* @returns A {@link Directory} populated from the VCI snapshot
* @throws Error when the VCI snapshot HTTP fetch returns a non-OK status
* @example
* const directory = await Directory.fromVCI()
*/
static async fromVCI(): Promise<Directory> {
const vciSnapshotResponse = await fetch(
'https://raw.githubusercontent.com/the-commons-project/vci-directory/main/logs/vci_snapshot.json'
)
if (!vciSnapshotResponse.ok) {
throw new Error(
`Failed to fetch VCI Directory snapshot with status ${vciSnapshotResponse.status}`
)
}
const vciDirectoryJson = await vciSnapshotResponse.json()
return Directory.fromJSON(vciDirectoryJson)
}

/**
* Build a Directory from a parsed JSON object matching the published
* directory schema.
Expand Down
Loading