gdc-sdk-node-ts
v0.9.1
Published
Next-generation Node runtime package for the GDC SDK family
Readme
gdc-sdk-node-ts
Node runtime package for consuming the shared GDC SDK contracts against real gateway backends.
Use this package when your backend needs to:
- call GW APIs
- submit/poll async operations
- orchestrate onboarding, consent, communication, and search flows
- consume the shared relationship invitation/acceptance contracts from
gdc-sdk-core-ts
This package is for runtime execution. It is not the place where the canonical business contract is defined.
Architectural rule:
- shared contracts and actor boundaries come from
gdc-sdk-core-ts - this package executes those flows against GW
- this package should not widen an actor facade just because the runtime client happens to expose the underlying method
Start Here
If you are integrating this package for the first time, open these in order:
- gdc-sdk-core-ts/docs/101-SDK_PACKAGE_BOUNDARIES.md
Why
core,node, andfrontare separate packages, what belongs in each one, and why actor-scoped facades must stay aligned across runtimes. - docs/101-SDK_END_TO_END.md Ordered onboarding guide with end-to-end journeys, copy/paste snippets, and the recommended reading path for new backend integrators.
- docs/101-SDK_INTEGRATION.md
Real backend setup, imports,
initializeCommunicationIdentity(...),new NodeHttpClient(...), route context, facade selection, and live method usage. - docs/101-LIVE_GW_LOCAL.md Exact TTY/local/Docker commands for running the SDK against a real local GW CORE, including tenant bootstrap and employee-seat setup.
- docs/101-DISCOVERY.md Node/BFF dataspace discovery, hosting-operator resolution, provider resolution, and the correct integration boundary for fallback and cache.
- gdc-sdk-core-ts/docs/101-SDK_FLOWS.md Actor split and business-flow map across organization, individual, permissions, invitation, import, and SMART flows.
- gdc-common-utils-ts/src/examples/ Shared payload values used by the docs and tests.
- gdc-common-utils-ts/docs/101-LIFECYCLE.md
Canonical
enable/disable/deletesemantics and copy/paste placeholders.
If you need the shortest path:
- main onboarding guide: docs/101-SDK_END_TO_END.md
- GW CORE app identity:
appIdmandatory,appVersionoptional with defaultv1.0 - backend technical identity:
initializeCommunicationIdentity(...)for the technical channel/runtime identity, not the legal organization id - runtime client:
NodeHttpClient - step-by-step runtime usage: docs/101-SDK_INTEGRATION.md
- dataspace discovery and fallback/cache boundary: docs/101-DISCOVERY.md
Executable Usage Examples
Open these tests when you want to see exact method calls and exact inputs:
- tests/host-onboarding.test.mjs Organization activation and order confirmation.
- tests/individual-start.test.mjs Individual organization start flow.
- tests/individual-onboarding.test.mjs Individual order/offer confirmation flow.
- tests/device-activation.test.mjs Employee activation code and activation request flows.
- tests/resource-operations.test.mjs Related person upsert, communication ingestion, search, and access grants.
- tests/smart-token.test.mjs SMART token request flow.
- tests/live-gw-node-runtime.e2e.test.mjs End-to-end runtime wiring against a real GW environment.
- tests/101-dataspace-resolver.test.mjs
Minimal
HttpDataspaceResolver101 with one host and one published provider. - tests/101-default-first-dataspace-discovery.test.mjs
Minimal
default-firstdiscovery with one host and one publishedIndexProvider.
Live GW CORE Flow
Use tests/live-gw-node-runtime.e2e.test.mjs as the canonical runtime flow.
Before running that suite, read:
Teaching rule:
- defaults come from
gdc-common-utils-ts/examples - override with env vars only when your tenant, bearer, or route is different
- local GW default is
http://127.0.0.1:3000 - Docker-exposed GW can be overridden with
BASE_URL=http://127.0.0.1:8000
Current live flow covered by the test suite:
- bootstrap tenant / legal organization
- bootstrap doctor or controller employee
- bootstrap individual and grant consent for the doctor
default example:
INDIVIDUAL_ALTERNATE_NAME=Doraemon - ingest two IPS
Communicationbundles, each with oneMedicationStatement - read the IPS/clinical index and verify both medications are present
- request the consolidated IPS bundle through
Bundle?type=document&composition.subject=<did>&composition.type=http://loinc.org|60591-5 - verify the returned bundle document contains both medication statements
- persist audit/debug traces in
test-results/*.jsonl
Shared example source of truth:
- tenant/route/controller/professional defaults: gdc-common-utils-ts/src/examples/shared.ts
- live employee defaults: gdc-common-utils-ts/src/examples/organization-controller.ts
- live consent defaults: gdc-common-utils-ts/src/examples/individual-controller.ts
The two medication defaults used by the live test are intentionally reusable:
Ibuprofen 400 mgParacetamol 600 mg- both every
8hours - both
PRN/dosage-asneeded = true - note text keeps the
4hour gap in English
Run the full live runtime baseline:
npm run test:e2e:live-gwRun the IPS ingestion/search branch as well:
RUN_LIVE_GW_E2E_IPS_INGESTION=1 \
npm run test:e2e:live-gwImplementation note:
- the public runtime contract is still
Bundle/_search gdc-sdk-node-tssubmits that request as-is- GW CORE resolves it internally from indexed subject sections and returns the consolidated IPS bundle document
Common overrides:
BASE_URL=http://127.0.0.1:3000 \
AUTH_BEARER=... \
TENANT_ID=VATES-B00112233 \
TENANT_ROUTE_ID=acme-live \
JURISDICTION=ES \
SECTOR=health-care \
SUBJECT_DID=did:web:api.acme.org:individual:123 \
RUN_LIVE_GW_E2E_IPS_INGESTION=1 \
LIVE_GW_NODE_E2E_DEBUG=1 \
npm run test:e2e:live-gwDocker-exposed GW example:
BASE_URL=http://127.0.0.1:8000 \
RUN_LIVE_GW_E2E_IPS_INGESTION=1 \
npm run test:e2e:live-gwDocumentation consistency rule for this repo family:
- scripts, README examples, Swagger examples, and internal tests must reuse the same example data and flow order
- if a new request/response example is added, add it first to
gdc-common-utils-ts/examplesand consume it from there instead of re-hardcoding values locally
Dataspace Discovery Quick Map
Use the Node discovery layer when your backend or BFF needs to:
- start from preloaded hosting-operator semantics
- fetch the canonical host-scoped
/<hosting-operator-network-context>/.well-known/dspace-versionentrypoint - derive the participant-scoped
/dsp/catalog/dcat.jsonartifact - return normalized provider/operator matches to portal or app backends
Primary references:
- docs/101-DISCOVERY.md
- tests/101-default-first-dataspace-discovery.test.mjs
- tests/101-dataspace-resolver.test.mjs
- tests/dataspace-resolver-advanced.test.mjs
- tests/dataspace-resolver.test.mjs
Architecture note:
- the reusable discovery resolver logic lives in
gdc-sdk-core-ts gdc-sdk-node-tsre-exports it and supplies the Node runtime surface
Copy/paste starting point:
import { createDefaultFirstDataspaceDiscovery } from 'gdc-sdk-node-ts';
import { DataspaceSectors } from 'gdc-common-utils-ts';
import { HostNetworkTypes } from 'gdc-common-utils-ts/constants/network';
const discovery = createDefaultFirstDataspaceDiscovery({
version: 'v1',
networkType: HostNetworkTypes.Test,
defaults,
});
const providers = await discovery.getIndexProviders({
sector: DataspaceSectors.AnimalCare,
jurisdiction: 'ES',
});Actor Split And Runtime Scope
This package must be understandable from the same actor split used by the shared contracts:
- organization controller
- organization employee / professional member
- individual controller
- individual member / self
- related person
- professional with consented access
The Node runtime layer is where those shared flows are executed against GW.
That includes organization onboarding, employee creation, individual bootstrap,
permission grants, RelatedPerson upserts, SMART token requests, and clinical
data ingestion/search.
Flow Families
- organization activation and order/offer confirmation
- employee creation and employee activation
- individual organization start and order confirmation
- related person upsert
- professional access grant
- invitation / OTP / relationship PIN runtime wiring
- permission-request
Communication - communication ingestion and search
- SMART token retrieval
Main Flows
1. Controller invites a related person or professional
Typical backend sequence:
- build shared invitation payload with
gdc-sdk-core-ts - send it through the node runtime client or your backend adapter
- persist or return the invitation state to portal/app
What matters here:
- this package executes the runtime call
gdc-sdk-core-tsdefines the payload shape- callers should not hardcode route families in app code
2. Invitee accepts the relationship
Typical backend sequence:
- start OTP challenge
- confirm OTP
- set relationship PIN if required
- activate the relationship channel
Shared contract builders come from gdc-sdk-core-ts; this package is where a
Node backend wires them to real runtime operations.
3. Consent-aware communication and search
Use this package when your backend needs to:
- ingest
Communication - search clinical bundles
- request SMART tokens
- grant access
- create or update
RelatedPerson
What This Package Owns
- Node runtime client
- submit/poll orchestration
- actor-scoped node sessions
- backend-facing orchestration helpers
What This Package Does Not Own
- the canonical invitation/OTP/PIN contract
- UNID-specific reminder runtime semantics
- frontend session UX
Those belong to:
gdc-sdk-core-tsfor shared contracts- runtime extensions such as UNID/UHC for product-specific behavior
gdc-sdk-front-tsfor frontend-facing consumption
Minimal Examples
Use shared invitation contract from Node
import {
createRelationshipChannelInvitationInput,
RelationshipAccessActorKinds,
RelationshipEnrollmentChannels,
type RelationshipChannelInvitationInput,
} from 'gdc-sdk-core-ts';
import {
buildIndividualDidWeb,
HealthcareActorRoles,
HealthcareConsentPurposes,
} from 'gdc-common-utils-ts';
const tenantId = 'acme-id';
const jurisdiction = 'ES';
const sector = 'health-care';
const providerOrganizationDid = subjectProfile.organizationDid;
const subjectLocalId = subjectProfile.subjectId;
const subjectId = buildIndividualDidWeb({
organizationDidWeb: providerOrganizationDid,
subjectId: subjectLocalId,
});
const professionalEmail = invitedProfessional.email;
const invitationInput: RelationshipChannelInvitationInput = {
tenantId,
jurisdiction,
sector,
subjectId,
subjectKind: 'person',
actorKind: RelationshipAccessActorKinds.Professional,
actorIdentifier: professionalEmail,
actorRole: HealthcareActorRoles.Physician,
deliveryChannel: RelationshipEnrollmentChannels.Email,
deliveryTarget: professionalEmail,
purpose: HealthcareConsentPurposes.Treatment,
relationshipLabel: 'primary-physician',
phonePinOptional: false,
};
const invitation = createRelationshipChannelInvitationInput(invitationInput);The backend should obtain those variables from:
- tenant route selection
- target subject identifier
- invited actor identity
- selected enrollment channel
- intended purpose/relationship label
Request SMART token and search bundle
import { NodeHttpClient } from 'gdc-sdk-node-ts';
import {
EXAMPLE_LATEST_IPS_SEARCH_INPUT,
} from 'gdc-common-utils-ts/examples/individual-controller';
import { HealthcareBasicSections } from 'gdc-common-utils-ts/constants/healthcare';
import { buildSmartCompositionReadScope } from 'gdc-common-utils-ts/utils/smart-scope';
const client = new NodeHttpClient({ baseUrl: process.env.BASE_URL! });
const subjectDid = EXAMPLE_LATEST_IPS_SEARCH_INPUT.subject;
const token = await client.requestSmartToken({
ctx,
actorDid: 'did:web:doctor.example.org:employee:001',
subjectDid,
scopes: [
buildSmartCompositionReadScope({
subjectDid,
sections: HealthcareBasicSections.PatientSummaryDocument.claim,
}),
],
idToken: '...',
});
const result = await client.searchClinicalBundle(ctx, {
subject: subjectDid,
});Teaching rule:
- start with the composition read scope when the actor only needs subject-scoped read access
- add
SmartGatewayScopesFhirR4.ConsentCrudsonly if the backend also needs consent management operations
Shared Contract Sources
Reusable payload examples:
- gdc-common-utils-ts/src/examples/organization-controller.ts
- gdc-common-utils-ts/src/examples/individual-controller.ts
- gdc-common-utils-ts/src/examples/professional.ts
- gdc-common-utils-ts/src/examples/shared.ts
- gdc-common-utils-ts/src/examples/lifecycle.ts
- gdc-common-utils-ts/src/examples/api-flow-examples.ts
API Index
Full Public Surface
This package exports the full gdc-sdk-core-ts surface plus the Node runtime
modules below.
src/runtime-contracts.ts- types/constants:
LegacyNodeSourcePackage,NodeRuntimeMode,NodeInteropMode,TenantContext,NodeOperatorContext,NodeFetchLike,NodeRuntimeConfig,NodePackageStatus,GDC_SDK_NODE_STATUS
- types/constants:
src/identity-bootstrap.ts- function:
initializeCommunicationIdentity(...)
- function:
src/async-polling.ts- types:
AcceptedPollResponse - function:
pollUntilCompleteWithMethod(...)
- types:
src/poll-options.ts- re-export:
resolvePollOptionsFromSeconds(...)
- re-export:
src/host-onboarding.ts- types:
HostRouteContext,LegalOrganizationOrderInput - function:
confirmLegalOrganizationOrderWithDeps(...)
- types:
src/individual-start.ts- types:
IndividualOrganizationBootstrapInput,OfferPreview,IndividualOrganizationStartResult - function:
startIndividualOrganizationWithDeps(...)
- types:
src/individual-onboarding.ts- types:
RouteContext,IndividualOrganizationConfirmOrderInput - function:
confirmIndividualOrganizationOrderWithDeps(...)
- types:
src/device-activation.ts- types:
EmployeeDeviceActivationInput,EmployeeDeviceActivationRequestInput,EmployeeDeviceActivationResult - functions:
activateEmployeeDeviceWithActivationCodeWithDeps(...),activateEmployeeDeviceWithActivationRequestWithDeps(...)
- types:
src/smart-token.ts- types:
SmartTokenRequestInput,SmartTokenExchangeResult - function:
requestSmartTokenWithDeps(...)
- types:
src/resource-operations.ts- types:
OrganizationEmployeeCreationInput,IpsOrFhirImportInput,RelatedPersonUpsertInput,CommunicationIngestionInput,ClinicalDateRange,ClinicalBundleSearchInput,ConsentActorTargetInput,GrantProfessionalAccessInput,GrantProfessionalAccessResult,DigitalTwinGenerationInput - functions:
createOrganizationEmployeeWithDeps(...),importIpsOrFhirAndUpdateIndexWithDeps(...),upsertRelatedPersonAndPollWithDeps(...),ingestCommunicationAndUpdateIndexWithDeps(...),searchClinicalBundleWithDeps(...),searchLatestIpsWithDeps(...),grantProfessionalAccessWithDeps(...),generateDigitalTwinFromSubjectDataWithDeps(...)
- types:
src/session.ts- types:
NodeCapability,NodeActorSessionContext,ActorSessionContext - classes:
ActorSession,NodeActorSession
- types:
src/node-runtime-client.ts- types:
HttpRuntimeClientOptions,NodeHttpClientOptions - classes:
HttpRuntimeClient,NodeHttpClient
- types:
src/gdc-session-bridge.ts- functions:
createNodeActorSessionsFromFacades(...),createNodeActorSessionFromFacade(...),createNodeActorSessionsFromDescriptor(...),createNodeActorSessionFromDescriptor(...),createActorSessionsFromFacades(...),createActorSessionFromFacade(...),createActorSessionsFromDescriptor(...),createActorSessionFromDescriptor(...)
- functions:
src/orchestration/client-port.ts- types:
RuntimeClient,NodeRuntimeClient - functions:
requireClientMethod(...),submitAndPollWithMethods(...),canClientSubmitAndPoll(...),submitAndPollWithClient(...)
- types:
src/orchestration/host-onboarding-sdk.ts- class:
HostOnboardingSdk
- class:
src/orchestration/organization-controller-sdk.ts- class:
OrganizationControllerSdk
- class:
src/orchestration/organization-employee-sdk.ts- class:
OrganizationEmployeeSdk
- class:
src/orchestration/individual-controller-sdk.ts- class:
IndividualControllerSdk
- class:
src/orchestration/individual-member-sdk.ts- class:
IndividualMemberSdk
- class:
src/orchestration/personal-sdk.ts- class:
PersonalSdk
- class:
src/orchestration/professional-sdk.ts- class:
ProfessionalSdk
- class:
src/legacy-compat.ts- compatibility aliases for simplified helpers, runtime classes, and legacy names such as
GdcNodeActorSessionandGdcNodeHttpClient
- compatibility aliases for simplified helpers, runtime classes, and legacy names such as
Re-exported shared helpers from gdc-sdk-core-ts
- consent access helpers
- relationship invitation/acceptance builders
- communication/document builders
- draft/outbox helpers
- document facade helpers
- vital-sign helpers
Node runtime client
NodeHttpClientNodeHttpClient.ingestCommunicationAndUpdateIndex(...)NodeHttpClient.submitCommunicationAndPoll(...)NodeHttpClient.searchClinicalBundle(...)NodeHttpClient.searchLatestIps(...)NodeHttpClient.grantProfessionalAccess(...)NodeHttpClient.requestSmartToken(...)
Runtime configuration
Low-level orchestration helpers
createOrganizationEmployeeWithDeps(...)importIpsOrFhirAndUpdateIndexWithDeps(...)upsertRelatedPersonAndPollWithDeps(...)ingestCommunicationAndUpdateIndexWithDeps(...)searchClinicalBundleWithDeps(...)searchLatestIpsWithDeps(...)grantProfessionalAccessWithDeps(...)
Documentation Rule
- README explains backend-facing flows first.
- Shared contract shapes must be documented in
gdc-sdk-core-ts, not duplicated here. - Route details and GW-specific behavior belong in runtime docs and JSDoc, not in app-facing examples.
