HDSModelStreams#isContext(streamId): boolean— returnstrueiff the stream's data-model definition carriesrole: 'context'(the D3 descendant-streamId marker flag introduced in@hds/data-modelPlan 53 Phase A). Unknown streamIds returnfalse(no throw).- Use this to elide / mute / re-render context streams as metadata in settings trees, form-section renderers, and dashboards rather than as data-bearing buckets. Runtime resolution (
itemsDefs.forEventwalk-up) is unaffected. - Tests:
[CTXR-P/Q/R/S]intests/contextResolution.test.js. Validates against the locally-builtdata-model/dist/pack.jsonso the flag is sourced from real YAML.
API surface frozen: no more Collector / CollectorClient / CollectorInvite classes, no AppManagingAccount.createCollector / getCollectors / getCollectorById, no AppClientAccount.handleIncomingRequest / getCollectorClients / getContacts, and Contact is CMC-only. The CMC path (@pryv/cmc + the cmc* helpers in this lib — cmcFormSpec, cmcAppScope, cmcConstants) is the only supported flow for doctor-side forms and patient-side relationships.
CollectorRequest survives as a pure editor-state class consumed by hds-forms-js's FormBuilder UI (locked via plan 61 Path B).
- Deleted classes:
Collector,CollectorClient,CollectorInvite. - Deleted from
Contact:sources,collectorClients,invitesfields + theiraddSource/addCollectorClient/addInvitemethods. Deleted getters:primaryCollectorClient,incomingCollectorClients,isPending,hasPendingUpdate,pendingUpdateClients,pendingCollectorClient,acceptPendingInvite,refusePendingInvite,formSections,chatStreams,chatPost,collectorSources,bridgeSources. Deleted static methods:Contact.groupByContact,Contact.sourceFromAccess. TheaccessObjectsfield is kept (used byinitStreamCache+eventIsAccessible+eventIsFromContact, populated byContact.aggregateCmc). - Rewritten
Contactgetters (CMC-only):status(derived fromcmcRelationships[].acceptedAt),hasChat(fromcmcRelationships[].features.chat),appStreamIds(distinctappCodeset),allPermissions(alias forcmcAllPermissions),isActive,accessIds. - Deleted from
AppManagingAccount:createCollector,createCollectorUnitialized,getCollectors,getCollectorById,getContacts. Class is now a thinApplicationsubclass. - Deleted from
AppClientAccount:handleIncomingRequest,getCollectorClientByKey,getCollectorClients,getContacts. Class is now a thinApplicationsubclass. - Deleted from
interfaces.ts:ContactSource,ContactSourceType,ChatStreams,AccessUpdateAction,AccessUpdateRequestContent,AccessUpdateRequest.Permission,RequestSectionType,CollectorSectionInterfaceare kept. - Deleted from
appTemplatesre-exports:Collector,CollectorClient,CollectorInvite,ContactInvite,AccessUpdateRequest*. collectItemLabels(itemKey, contacts)now walkscontact.cmcRelationships[].hdsFormSpec.sectionsinstead of legacyCollectorClient.getSections().
Callers can pin to github:healthdatasafe/hds-lib-js#0fedc1d (the last pre-1.0 commit) until ported to the CMC API. bridge-redcap is frozen on this pin pending its own port — see _macro/bridge-redcap/CLAUDE.md for the port checklist.
For the doctor-side form-storage migration, see doctor-dashboard/app/formSpecAdapter.ts (CollectorRequest ↔ FormSpec translators) and doctor-dashboard/app/cmcDoctor.ts (saveFormSpec / listInviteRecordsFor / etc.) for the reference port.
- Plan-45 system-feature types + resolver (dormant). Deleted
ts/appTemplates/systemFeatureTypes.tsalong withHDSSystemAlertDef,HDSSystemAckDef,HDSSystemFeature,SystemMessageType,SystemFeatureResolutionand theresolveStreamSystemFeature/resolveStreamSystemFeatureDetailedhelpers. The account-levelapp-system-out/app-system-instream pair was superseded by the CMC per-collector channel (:_cmc:apps:<app-code>:[<path>:]collectors:<counterparty-slug>) carryingnotification/alert-cmc,notification/ack-cmc,consent/scope-request-cmc,consent/scope-update-cmc. The mode-3existingStreamRefs[]mechanism onCollectorRequeststays — generic, can reference any pre-existing stream. Data-model layer (message/system-alert+message/system-ackeventType registrations) left intact so legacy data stays valid. See_macro/_plans/64-on-the-go-app-testing-atwork/PLAN.mdPhase A.
Bumps pryv 3.0.4 → 3.1.0 (matching @pryv/monitor and @pryv/socket.io). Collapses the Plan 27 "delete-then-create" access-update workaround into a single in-place accesses.update call. Hard-requires a pryv core supporting accesses.update (Plan 66 — deployed to demo.datasafe.dev 2026-05-13 and api.datasafe.dev 2026-05-14). External self-hosted Pryv.io cores on older versions will receive raw 410 on update calls — caller's responsibility.
After Plan 66, once an access has been updated, its id serialises as composite <base>:<serial> (abc:1, abc:2, …). Never-updated accesses still serialise as bare cuids — backward-compatible read path. Equality comparisons against access.id must canonicalise via base extraction; see Contact.eventIsFromContact for the in-lib example.
bridgeAccess.getOrCreateAccess(Phase 4b) —updateIfDifferent && !permissionsMatchnow callsconnection.updateAccess(existing.id, …)instead of recreating the access. PreservesapiEndpoint+token.BridgeAccessResultexposesupdated: booleanin place ofrecreated. OnStaleAccessIdError, refetches and retries once before propagating.CollectorClient.acceptUpdate(Phase 4c) — replaces the delete+create branch with a singleaccesses.update. Theresponse/collector-v1update-acceptevent written to the doctor's inbox no longer carriesapiEndpoint. Same one-retry-budget onStaleAccessIdError.Collector.checkInbox(Phase 4d) —update-acceptevents are now read as ack-only. Opportunistically migrates legacy events carryingapiEndpointviaevents.update(drops the field). Idempotent; non-fatal on write failure.Contact.eventIsFromContact(Phase 4f) — base-aware equality viaparseAccessRef(x).base. An event with baremodifiedBy: "abc"now matches an access with compositeid: "abc:3"(and vice versa). LegacypreviousAccessIdschain check is also base-aware.CollectorInvite.checkAndGetAccessInfo(Phase 4a) — drops the manual#accessInfoshort-circuit and theforceRefreshparameter. Delegates to pryv@3.1.0'sConnection.accessInfo()cache. Theinvalid-access-token→revokeInviteside-effect is preserved.- Defensive: strip non-canonical permission fields before
accesses.update— Plan 66's server schema is strict on update (rejectsdefaultName/nameextras present inaccesses.checkAppresponses).bridgeAccess.tsstrips these before sending.
previousAccessIdschain — new code never writesclientData.hdsCollectorClient.previousAccessIds/clientData.previousAccessIds. Existing chains stay intact soContact.eventIsFromContactcontinues to attribute events authored by ancestor (pre-recreate) accesses.- Legacy
response/collector-v1events carryingapiEndpoint(Plan 27-era) are read as ack-only + opportunistically rewritten — see Phase 4d.
Connection.accessInfo()cache is per-Connectioninstance, not per-apiEndpoint. Server-side handlers that build a freshConnectionper request gain nothing.Connection.updateAccess(id, changes)translates server-side409 stale-resourceinto a typedStaleAccessIdError(exported on the top-level pryv namespace). No auto-retry — callers refetch + reapply.
eventToShortText/formatDatasource— generalized so newly added datasource-search items (treatment/coded-v1withregimen,procedure/coded-v1withprocedure) produce a clean human label instead of a raw JSON dump. The function now resolves the coded value across known shapes (drug/regimen/procedure) and falls back to the first object property carrying alabel. Appends×countwhen count > 1, the first 1–2findings[].labelentries (procedure), and a truncatednotesstring. Existing medication intake (doseValue+doseUnit+route) handling preserved; all 50 existing tests still pass.
HDSModelItemsDefs.forEvent()— when no direct(streamId, eventType)match is found acrossevent.streamIds, falls back to walking parents fromevent.streamIds[0]looking for a registered itemDef with the matching eventType. Closest ancestor wins. Lets a single itemDef registered at e.g.treatmentresolve events placed attreatment-fertility,treatment-oncology, … without per-domain item definitions. Reuses the existingstreams.getParentsIdschain helper consumed byHDSModelAuthorizations.HDSItemDef.eventTemplate({ context })— optionalcontextstreamId per Plan 46 §2.1 (D3). Validates context isitemDef.streamIdor a descendant; emits length-1streamIds: [context ?? streamId]. Throws on context outside the itemDef's subtree.HDSItemDefconstructor takes optionalmodel: HDSModel— used byeventTemplateto validate descendant streamIds viamodel.streams.getParentsIds. Backward-compatible: callers that buildHDSItemDefdirectly without the model still work; they just can't use thecontextoption.HDSModel.loadFromObject(data, overload?)— loads model from an in-memory object, skippingfetch. Useful for tests, embedded apps, or environments wherefetchcan't reach the model URL (e.g. Node'sfetchdoes not yet implementfile://).load()is reimplemented in terms ofloadFromObject.
- D3's walk-up is the third application of the same closest-ancestor algorithm in this lib: Plan 45's
resolveStream.ts(account-levelclientDatalookup) andHDSModelAuthorizations(parent-covers-child de-dup) are the existing precedents. D3 applies the algorithm at the data-model itemDef layer. - 11 new
[CTXR]tests intests/contextResolution.test.jsexercising the resolution + creation paths plus the legacy multi-streamId case.
CollectorRequestSection lacked a customFieldKeys field, so the section's reference into request.customFields[] was lost on serialize/deserialize. Added private #customFieldKeys plus public customFieldKeys getter, setCustomFieldKeys(keys) and addCustomFieldKey(key) setters, parsing in setContent() and serialization in getData(). Discovered during Phase 6 mcp-chrome smoke test — a template uploaded via loadTemplate() had its custom fields surfaced on the request but the per-section pointers dropped.
ts/appTemplates/customFieldTypes.ts—HDSCustomField,HDSCustomFieldDef,CustomFieldEventType(note/txt | note/html | count/generic | date/iso-8601 | activity/plain),EmptyDef,isEmptyDef()predicate.ts/appTemplates/systemFeatureTypes.ts—HDSSystemFeature,HDSSystemAlertDef,HDSSystemAckDef,SystemMessageType.ts/appTemplates/templateTypes.ts—AppTemplate,AppTemplateSection,CustomFieldDeclaration,ExistingStreamRef(canonical home),StreamPermission.
resolveStreamCustomField(streamTreeOrMap, streamId, eventType): HDSCustomFieldDef | nullresolveStreamCustomFieldDetailed(...): { kind: 'def' | 'optOut' | 'none', def? }resolveStreamSystemFeature(...) / resolveStreamSystemFeatureDetailed(...)— same forhdsSystemFeature[messageType].streamCustomFieldToVirtualItem(...) → VirtualItemDef | null— convenience for the form engine.customFieldDeclarationToVirtualItem(decl) → VirtualItemDef— compose-time conversion (no streamTree).buildStreamMap(streamTree)— pre-built id→stream map for repeated lookups.VirtualItemDef.eventTemplate()returns{ streamIds, type }so the result slots into hds-forms-js'sformDataToActions/prefillFromEventspipeline directly.
Inheritance: parent-chain walk, empty {} def = explicit opt-out, missing = keep walking,
root reached = none (per design spec §2.4).
loadTemplate(json) → AppTemplate— Ajv schema validation + cross-field rules (sandbox prefix, def self-identification, key/streamId suffix consistency, section refs, mode-2/mode-3 collision).loadTemplateFromUrl(url)— fetch + load.- Type guards:
isCustomFieldDeclaration,isExistingStreamRef. ts/appTemplates/schemas/appTemplate.schema.json— JSON-Schema draft-07 covering the full template shape.
- New top-level field
customFields: CustomFieldDeclaration[](Plan 45 §2.9 mode-2). addCustomField(cf)validates eventType, def.version, sandbox prefix (streamId.startsWith(def.templateId + '-')).contentgetter serializescustomFields[]when non-empty.setContentparsescustomFields[]from incoming content.
- New Mode-2 provisioning block: for each
customFields[i], creates the${templateId}-customparent (idempotent onitem-already-exists) plus the per-field child stream carryingclientData.hdsCustomField[<eventType>] = def. Appendscontributepermission to the granted access. Sandbox prefix re-checked (defence in depth).
ts/appTemplates/CUSTOM-FIELDS-AND-SYSTEM.md— canonical developer/agent reference covering both halves end-to-end (12 sections: conceptual overview,clientData.hdsCustomFieldschema with worked example,clientData.hdsSystemFeatureschema, parent-chain inheritance, validator behaviour, naming convention is soft, helper API, three stream-reference modes, bridge/export discoverability, no-promotion principle, failure modes, cross-references).AGENTS.md— cross-link to the new doc.
tests/resolveStream.test.js— 17 tests (parent-chain walk, opt-out semantics, StreamMap optimization, system-feature resolution, virtual-item conversion).tests/loader.test.js— 18 tests (Ajv shape validation, all six cross-field rules, type guards).tests/apptemplatesRequest.test.js— +8 customFields tests (parse, serialize, sandbox enforcement, eventType validation, round-trip).
Net: 43 new tests, all passing. 1 pre-existing failure unchanged.
VirtualItemDef.data.typeuses form-engine type names ('text' | 'select' | 'number' | 'date') so the result is directly consumable by<HDSFormField>.data.optionsreshaped toArray<{ value, label: { en } }>matching<Select>.
Added barrel exports: isEmptyDef, loadTemplate, loadTemplateFromUrl,
isCustomFieldDeclaration, isExistingStreamRef, buildStreamMap,
resolveStreamCustomField{Detailed}, resolveStreamSystemFeature{Detailed},
streamCustomFieldToVirtualItem, customFieldDeclarationToVirtualItem,
plus all new types.
- Added
ajv ^8.20.0for template JSON validation.
tsconfig.json—resolveJsonModule: truefor the schema import.
- New top-level field
existingStreamRefs[](Plan 45 §2.9 mode-3): request access on pre-existing streams without provisioning. Each ref carries{ streamId, permissions: ('read'|'manage'|'contribute')[], purpose? }. - New methods:
addExistingStreamRef(ref)with input validation (rejects non-string streamId, empty permissions, unknown permission levels) andexistingStreamRefsgetter. contentgetter now serializesexistingStreamRefs[]when non-empty (omitted otherwise — backwards-compatible).- New exported type:
ExistingStreamRef.
accept()now processesrequestData.existingStreamRefs[]after the existing chat-stream block:- Bootstrap-provision
app-system/app-system-out/app-system-instreams if a ref points at the system pair and the streams don't exist yet. The new streams carryclientData.hdsSystemFeaturedeclaringmessage/system-alert(onout) andmessage/system-ack(onin). Idempotent —item-already-existserrors fromstreams.createare tolerated. - Append the requested permissions to the access being granted.
- Surface system-stream wiring on
responseContent.system = { streamOut?, streamIn? }whenapp-system-*refs are present.
- Bootstrap-provision
- New properties:
hasSystem,systemSettings(returns{ streamOut?, streamIn? }). - New methods (mirroring
chatPost/chatEventInfos):systemPostAlert({ level, title, body, ackRequired?, ackId? })— posts amessage/system-alerttostreamOut. Auto-generates a UUIDackIdwhenackRequired: trueand none supplied.systemPollAcks({ ackId?, limit? })— fetchesmessage/system-ackevents fromstreamIn, optionally filtered byackId. Returns events sorted ascending by creation time.systemEventInfos(event)— identifies the source of a system event ('me'/'user'/'unknown').
exports[.].importswitched from./js/index.js(compiled JS) to./ts/index.ts(TS source). Added wildcard./js/*subpath export.defaultstill points at compiled JS for non-Vite/CJS consumers.- This brings hds-lib in line with
_claude-memory/conventions.md § Package exports: TS source for bundlersand is the prerequisite for live cross-repo dev (the previousjs/index.jsimport path created duplicate-singleton bugs when downstream libs like hds-forms-js re-importedhds-libviarequire()). See_plans/49-local-dev-dependency-graph-done/PLAN.mdfor the full rationale.
- The Plan-45 Phase 3a additions are the MVP slice of system-stream support. Full Phase 3 work (custom-fields helpers
resolveStreamCustomField+streamCustomFieldToVirtualItem, the appTemplates loader with Ajv schema, sandbox-prefix enforcement) lands in a follow-up commit. - Designed to be consumed by:
doctor-dashboardPhase 6a — operator UI callinginvite.systemPostAlert(...)andinvite.systemPollAcks(...).hds-webappPhase 7a — patient-side inbox provisioning theapp-system/*streams at boot (or relying onCollectorClient's bootstrap fallback) and rendering alerts with an Acknowledge button that postsmessage/system-ack.
- Requires
data-model≥ 1.4.0 (the newmessage/system-alert+message/system-ackevent types). - See
_plans/45-custom-fields-appTemplates-paused/spec.mdfor the locked design.
HDSItemDef.isDeprecatedgetter —truewhen the underlying itemDef hasdeprecated: truein pack.json (set indata-model≥ 1.5.0).HDSModel.itemsDefs.getAllActive()— returns every itemDef except deprecated ones. Use this for any UI that lets a user create new data points (form builder item browsers, item picker sheets, the data-model browser default listing).getAll(),forKey(),forEvent()are unchanged: they still return deprecated items so existing events remain readable / renderable.
Tests: [MDPX] block in tests/hdsModel.test.js — covers the getter on the three currently-flagged items (body-vulva-mucus-stretch, body-vulva-wetness-feeling, fertility-cycles-charted-count), the contrast with non-deprecated items, and the getAllActive vs getAll invariant.
Contract documented in data-model/AGENTS.md § "deprecated: true on items".
exports[.].importswitched from./js/index.js(compiled JS) to./ts/index.ts(TS source).- Added wildcard subpath export
./js/*(was already./ts/*) for completeness. defaultexport still points at./js/index.jsfor non-Vite/CJS consumers.
Why. Vite resolves the import condition in dev mode. With import pointing at compiled JS, live edits to ts/*.ts weren't reflected in npm-linked consumers without rebuilding hds-lib-js. Pointing import at TS source enables true live cross-repo development. This also avoids the duplicate-singleton bug surfaced by Plan 45 (a downstream lib's pre-built bundle inlining a second copy of hds-lib's HDSModel). Production builds and CJS consumers are unaffected (still hit default).
Brings hds-lib in line with _claude-memory/conventions.md § Package exports: TS source for bundlers. See _plans/49-local-dev-dependency-graph-done/PLAN.md for the full rationale.
appTemplates.collectItemLabels(itemKey, contacts)— gathers label overrides for an item across every active CollectorClient, attributing each entry to its source contact + form. Pure data layer; usable by any patient/diary surface, not just the form renderer.appTemplates.collectItemLabelsFromSections(itemKey, sources, opts?)— lower-level helper for callers that already have section objects.appTemplates.getSectionItemLabels(section, itemKey)— read labels for one item out of one section.- New types:
ItemLabels,ItemCustomization,ItemLabelSource,ItemLabelsWithSource,CollectItemLabelsOptions(mirror thesection.itemCustomizations[itemKey].labelsshape; previously duplicated as inline interfaces in hds-forms-js). - Tests:
tests/itemLabels.test.js(deduplication, requireLabels gating, options-map preservation, source attribution).
eventToShortTextnow formatstype: 'slider'events using the item def'sslider.displayblock (multiplier,precision,suffix). EQ VAS storing0.73now renders as"73 /100"everywhere events are summarised (diary card, timeline tooltips, etc.). Previously fell through to the generic number path and read"0.73".
HDSModelOverload— apps can extend the shared HDS data-model at init time with their own itemDefs, streams, eventTypes, settings, datasources, or appStreams, plus refine translations and defaultrepeatablevalues.HDSModel.load(url, overload?)— merges the overload (after policy validation) before freezing.initHDSModel({ overload })— same hook on the singleton init.extractOverloadAsDefinitions(overload)— converts an overload back into a{ filepath: content }map matching the layout underdata-model/data-model/definitions/, so apps can dump their overload to disk and open a PR upstream. Browser-safe (nofs).- Forbidden mutations (changing
parentIdof an existing stream,type/schema of an existing eventType,type/streamId/eventTypeof an existing item, etc.) throwHDSLibErrorlisting every violation.
Contact.incomingCollectorClientsgetter — filter CollectorClients by Incoming statusContact.displayStatusmapping: Deactivated → Revoked, Incoming → PendingCollector.requestAccessUpdate()— doctor-side method to request permission changes from patientCollectorClient.checkForUpdateRequests()— patient-side discovery of pending update requestsCollectorClient.acceptUpdate()/refuseUpdate()— patient-side accept/refuse with access recreateAppClientAccount.getContacts()scans active CCs for update requests in parallel- Bridge access helpers:
getOrCreateBridgeAccess(),recreateBridgeAccess(),ensureBridgeAccess()
CollectorClient.revoke()handles missing accessData gracefully (skips access deletion)AppManagingAccount.getContacts(true)callscheckInbox()on each collector to detect patient revoke/refuse responsesrequestAccessUpdatetarget key uses doctor's sharing access ID (not patient-side access info)
- Unified preferred representation API (
HDSModel-Preferred.ts)getPreferredInput(itemKey)/getPreferredDisplay(itemKey)— works for both variation and converter items- Standalone functions exported from lib
- Dynamic settings with prefix pattern:
preferred-display-{itemKey},preferred-input-{itemKey}- Stored as individual Pryv events (
settings/preferred-display,settings/preferred-input) HDSSettings.setDynamic()/getDynamic()API
- Stored as individual Pryv events (
_rawvirtual method auto-generated from dimension stops at converter engine loadresolveObservationLabel()— localized labels from method definitions for converter resultsHDSSettings._testInject()/_testClear()for test-only settings injectionformatEventDateTime()— date+time for checkbox events (skips time if midnight)- test-result/scale formatting: Positive/Negative/Indeterminate + percentage (localizable)
- 12 preferred API tests, 15 convertible shortText tests
- Convertible event content:
data→vectorsfor clarity (Plan 22) - eventToShortText convertible display:
sourceData (Method Name)format - autoConvert display:
result (target <- source %)with confidence percentage HDSSettings.get()now checks dynamic settings first- Renamed settings prefixes:
converter-auto-→preferred-display-,converter-default-→preferred-input-
- Euclidian-distance converter engine (
EuclidianDistanceEngine) for cross-method vector conversion HDSModelConverterson HDSModel with async lazy-load from{modelBaseUrl}/converters/{itemKey}/pack-latest.jsonconvertMethodToEvent(),convertEventToMethod(),convertMethodToMethod()- Converter-aware shortText formatting with
autoConvert-{itemKey}setting support modelUrlgetter on HDSModel- 32 converter engine tests
- Pryv CJS interop: declaration merging for type+value exports
- HDSProfile: graceful fallback when connection lacks profile access
- Added
getAttachmentUrltoolkit utility, fixed avatar URL in HDSProfile
- Converted library from CJS to ESM output (
"type": "module") - TS-first: import
.tsdirectly, tests run from source (Node 24) - Updated CI matrix to test Node 22.x + 24.x
- Bumped Node engine to
>=24
- HDSSettings singleton for managing user settings as individual Pryv events
- Unit-aware formatting with settings integration
formatEventDatehelper with HDSSettingsdateFormathookeventToShortTextshared event formatter replacing duplicated formatters across apps- Reminder system:
computeReminders, duration utilities,lastEventContent MonitorScope: progressive paged event loading with Monitor integrationdatasets://protocol resolution for datasource endpoints- HDSModelDatasources support
- Renamed setting event types to kebab-case for Pryv API compatibility
- Fixed datasets URL to
demo-datasets.datasafe.dev - Fixed lint errors and
formatEventDatetest bug
- Chat feature support:
hasChatFeature, chat logic components - Stream tools:
getChildrenStreamIds,streamTools - Custom setting unit support
- Updated Pryv dependencies
- Event type definitions to model
- Migrated source to TypeScript
- Reorganized source file structure
- Removed trailing
.jsin imports/require - Set proper types in
package.json
- Various type fixes and null handling for
clientData
- Handling of new variations model
- Added
getAllfor itemDefs
- Avoided infinite loops and error handling on reset
CollectorRequestclass with sections, fencing, and permission building- Collector ordering API,
itemCustomizations, and repeatable getter
- Corrected linting issues
- Fixed two test failures
getHDSModel()singleton accessor- Lazily loaded type definitions
- Type declaration files
- Updated Pryv library
- Improved type exports
- Fixed
itemDefs.eventTemplatehandling - Fixed
getCustomSettingsand cache validity
setCustomSettingssupportitems.eventTemplateaccessor
- Refactored model singleton logic
- Comprehensive documentation (README)
- Localized labels and descriptions for items
- Browser test suite
- Self-revoke capability for invites
- Revoke and refuse actions for invites
- New model singleton pattern
- Refactored test suite for better coverage
- Pryv bundled into HDSLib
- Localization and title for requests
getInviteByKeyandgetCollectorByIdaccessors
- Active state of
CollectorClient
- Application Client Account support
- Sharing capabilities
- Manager account creation
- Collectors and App Templates implementation
- Factorized apps module
- Implemented
apiOne()where possible - Consolidated Collector into a single file
- Refactored model streams into separate files
authorizationForItemKeysmethod- Authorization building methods
- Basic stream manipulations
HDSItemDefclass with maps
- Renamed
.typesto.eventTypes
- Initial release
- HDS data model loading and parsing
- Item definitions with keys
- Web-packed browser library
- Source maps for debugging