Skip to content

Building apps (hds-lib)

If you ask the agent to build a web page or a Node script that talks to HDS — rather than “agent processes my folder and writes events” — the agent should always reach for hds-lib. It wraps Pryv and adds everything HDS-aware: the data-model singleton, item lookup, HDSService, app-template scaffolding, localisation, converters. hds-lib already bundles Pryv and re-exports it as HDSLib.pryv, so there is never a reason to load the raw pryv SDK as a separate dependency.

hds-lib ships as a git-URL npm package. Use any bundler you like — Vite is the fastest from-scratch path:

Terminal window
npm create vite@latest my-hds-app -- --template vanilla
cd my-hds-app
npm install
npm install git+https://github.com/healthdatasafe/hds-lib-js.git

Then import * as HDSLib from 'hds-lib' in your code.

Full reference: healthdatasafe.github.io/hds-lib-js. The API surface behind HDSLib.pryv (api batching, streamed events, attachments, HF events, auth customization) is covered by Pryv’s agent reference and the pryv/lib-js README — documentation only: Pryv’s docs describe standalone use, so ignore their npm install pryv — never install pryv as a second dependency.

While building, request a wide scope — manage on * streams — against a demo account, so your app and your agent can create and reshape the streams they need. Before the app meets a real account, shrink the requested permissions to the minimal set the finished flow uses. See Connect & permissions.

itemDef-first: derive streams + event shapes from the model — never hardcode

Section titled “itemDef-first: derive streams + event shapes from the model — never hardcode”

No item for your data? Don’t hardcode strings or dump to note/txt. Register your own itemDef — initHDSModel({ overload: { items: { … } } }) merges a brand-new item (plus its streams/eventTypes) into the model, and from then on it behaves like any core item (itemsDefs.forKey, eventTemplate, getNecessaryListForItems). A working custom itemDef is the same shape as a core data-model definition, so propose it upstream to grow the catalogue rather than keeping it private. (Overrides of an existing item are limited to display fields; structural fields are immutable. An app token cannot create a top-level root — request a new root in the initial OAuth scope with a defaultName, or parent your custom item under an existing root.)

pryv.Browser.setupAuth already writes a cookie (pryv-libjs-<appId>) and tries to auto-restore from it — so the “tokens in memory only” advice you’ll see elsewhere describes the MCP server, not a browser app, and the cookie auto-restore is inconsistent in practice. Pick a persistence model deliberately: cookie (the lib default), localStorage (survives reload, app-managed), or in-memory (re-OAuth each reload). The apiEndpoint is a bearer credential reachable by XSS wherever you store it — never log it or send it to a third party. Validate a restored token before trusting it: call getAccessInfo (a revoked/expired token returns 403 invalid-access-token), and on failure clear it and fall back to sign-in. A patient app should also re-provision its streams on restore (StreamsAutoCreate.ensureExistsForItems), since the model may have grown since last visit.

A few exports an agent building on hds-lib will reach for often:

  • toolkit.StreamsAutoCreate.attachToConnection(conn).ensureExistsForItems(itemKeys) — provisions every stream a set of items needs (parents first, idempotent) in one call. Use this instead of any hand-written stream tree.
  • getHDSModel().streams.getNecessaryListForItems(itemKeys, { knowExistingStreamsIds }) — the lower-level primitive: the raw streams.create payloads, if you need them (e.g. to derive a read filter).
  • getHDSModel().itemsDefs.forKey(key).eventTemplate(){ streamIds, type } for an item’s write; picks the first variation automatically.
  • eventToShortText(event) — shared formatter for displaying events as "60 Kg" / "Aspirin · 100mg" / etc.
  • MonitorScope — progressive event loading + WebSocket subscribe; use for live timelines and dashboards.
  • computeReminders(item, source) — “what’s due now” computation.
  • HDSSettings, getPreferredInput, getPreferredDisplay — per-user unit / locale / date-format awareness.
  • appTemplates.* — the legal/consent shape every HDS app uses (AppManagingAccount, AppClientAccount, Collector, CollectorClient).

The full flat enumeration with one-line descriptions lives in hds-lib-js/AGENTS.md.

For richer apps, hds-lib is the foundation — these build on top of it (all expect a bundler, no CDN script tags; all install via git+https://…, none are on the npm registry):

| Library | What it gives you | Agent docs | |----------------------------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------|-------------------------------------------------------------------------------------------------------------| | hds-forms-js | <HDSFormField> — React form input that auto-renders from an HDS item definition. | AGENTS.md | | hds-feminine-cycle-ui | FEMM / Billings / Creighton / Mira chart cells + cervix-position glyphs for cycle-tracking events. | AGENTS.md | | lib-bridge-js | Express skeleton for HDS bridges — backend services that sync a third-party platform’s data into HDS. | AGENTS.md |