gdc-sdk-node-ts 2.1.4 → 2.2.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +11 -5
- package/dist/backend-profile-workspace.d.ts +48 -0
- package/dist/backend-profile-workspace.js +91 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/individual-controller-backend-runtime.d.ts +6 -1
- package/dist/individual-controller-backend-runtime.js +7 -0
- package/dist/node-runtime-client.d.ts +13 -1
- package/dist/node-runtime-client.js +25 -1
- package/dist/orchestration/client-port.d.ts +3 -1
- package/dist/orchestration/individual-controller-sdk.d.ts +37 -1
- package/dist/orchestration/individual-controller-sdk.js +44 -0
- package/dist/orchestration/individual-member-sdk.d.ts +25 -0
- package/dist/orchestration/individual-member-sdk.js +29 -0
- package/dist/orchestration/personal-sdk.d.ts +3 -1
- package/dist/orchestration/personal-sdk.js +4 -0
- package/dist/orchestration/professional-sdk.d.ts +11 -1
- package/dist/orchestration/professional-sdk.js +14 -0
- package/dist/professional-backend-runtime.d.ts +6 -1
- package/dist/professional-backend-runtime.js +7 -0
- package/dist/profile-workspace.d.ts +12 -0
- package/dist/profile-workspace.js +15 -0
- package/dist/resource-operations.d.ts +74 -0
- package/dist/resource-operations.js +185 -1
- package/dist/runtime-client-paths.d.ts +2 -0
- package/dist/runtime-client-paths.js +2 -0
- package/dist/runtime-route-context.js +18 -1
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -7,7 +7,10 @@ execution adapters, or orchestration tests.
|
|
|
7
7
|
Short rule:
|
|
8
8
|
|
|
9
9
|
- `101` tests must read like executable tutorials
|
|
10
|
-
-
|
|
10
|
+
- `gdc-common-utils-ts` owns the canonical step-by-step editors/readers,
|
|
11
|
+
shared fixtures, and reusable payload examples
|
|
12
|
+
- `gdc-sdk-node-ts` starts after that shared authoring step and at
|
|
13
|
+
`ProfileRuntime -> loadProfile(...) -> workspace/session -> actor facade`
|
|
11
14
|
in node runtime tests
|
|
12
15
|
|
|
13
16
|
Node runtime package for consuming the shared GDC SDK contracts against real
|
|
@@ -69,7 +72,8 @@ If you are integrating this package for the first time, open these in order:
|
|
|
69
72
|
2. [docs/101-SDK_INTEGRATION.md](./docs/101-SDK_INTEGRATION.md)
|
|
70
73
|
Real backend setup plus the public runtime entrypoints:
|
|
71
74
|
`HostOnboardingSdk`, `OrganizationControllerSdk`,
|
|
72
|
-
`IndividualControllerSdk`, `ProfessionalSdk`,
|
|
75
|
+
`IndividualControllerSdk`, `ProfessionalSdk`, route-context usage, and the
|
|
76
|
+
canonical `ProfileRuntime -> loadProfile(...) -> workspace/session -> actor facade -> submit/poll` shape.
|
|
73
77
|
3. [tests/101-live-full-cycle-bff-runtime.e2e.test.mjs](./tests/101-live-full-cycle-bff-runtime.e2e.test.mjs)
|
|
74
78
|
Canonical live backend/BFF walkthrough on a fresh local GW lifecycle:
|
|
75
79
|
host/tenant activation, employee provisioning, individual bootstrap,
|
|
@@ -194,7 +198,8 @@ Current live `101` flow covered by the test suite:
|
|
|
194
198
|
2. provision one professional employee through the organization controller
|
|
195
199
|
3. load the individual-controller profile and bootstrap one hosted individual
|
|
196
200
|
4. confirm the returned order and verify the invoice bundle projection
|
|
197
|
-
5. ingest one IPS/clinical `Communication`
|
|
201
|
+
5. ingest one IPS/clinical `Communication` whose attached payload is the
|
|
202
|
+
canonical document `Bundle` with `Composition` first entry
|
|
198
203
|
6. grant professional consent for one patient-summary section
|
|
199
204
|
7. load the professional profile and request one SMART token
|
|
200
205
|
8. read the allowed IPS bundle as the professional actor
|
|
@@ -293,8 +298,9 @@ npm run test:e2e:live-gw
|
|
|
293
298
|
|
|
294
299
|
Implementation note:
|
|
295
300
|
|
|
296
|
-
- the
|
|
297
|
-
|
|
301
|
+
- the beginner search story stays on FHIR parameters such as
|
|
302
|
+
`Composition.section`
|
|
303
|
+
- `gdc-sdk-node-ts` submits the search request through the runtime facade
|
|
298
304
|
- GW CORE resolves it internally from indexed subject sections and returns the
|
|
299
305
|
consolidated IPS bundle document
|
|
300
306
|
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import type { ProfileLoadRequest, SubjectIndexCompositionRequest, SubjectIndexConnectionRequest, TrustedDeviceRegistrationRequest } from 'gdc-sdk-core-ts';
|
|
2
|
+
import type { BackendLoadedActorProfile, BackendProfileRuntimeClient, BackendSubjectIndexCompositionResult, BackendSubjectIndexConnectionResult, BackendTrustedDeviceRegistrationResult } from './backend-profile-runtime.js';
|
|
3
|
+
import { type OrganizationControllerProfileWorkspace, type ProfessionalProfileWorkspace } from './profile-workspace.js';
|
|
4
|
+
import { HostOnboardingSdk } from './orchestration/host-onboarding-sdk.js';
|
|
5
|
+
import { IndividualControllerSdk } from './orchestration/individual-controller-sdk.js';
|
|
6
|
+
import { IndividualMemberSdk } from './orchestration/individual-member-sdk.js';
|
|
7
|
+
import { OrganizationControllerSdk } from './orchestration/organization-controller-sdk.js';
|
|
8
|
+
import { OrganizationEmployeeSdk } from './orchestration/organization-employee-sdk.js';
|
|
9
|
+
import { ProfessionalSdk } from './orchestration/professional-sdk.js';
|
|
10
|
+
/**
|
|
11
|
+
* Backend loaded-profile workspace that keeps the canonical
|
|
12
|
+
* `loadProfile -> workspace/session -> actor facade` story explicit.
|
|
13
|
+
*/
|
|
14
|
+
export declare class LoadedProfileWorkspace {
|
|
15
|
+
private readonly profileRuntime;
|
|
16
|
+
readonly profile: BackendLoadedActorProfile;
|
|
17
|
+
constructor(profileRuntime: BackendProfileRuntimeClient, profile: BackendLoadedActorProfile);
|
|
18
|
+
close(): Promise<void>;
|
|
19
|
+
registerTrustedDevice(input: TrustedDeviceRegistrationRequest): Promise<BackendTrustedDeviceRegistrationResult>;
|
|
20
|
+
connectToSubjectIndex(input: SubjectIndexConnectionRequest): Promise<BackendSubjectIndexConnectionResult>;
|
|
21
|
+
getSubjectIndexComposition(input: SubjectIndexCompositionRequest): Promise<BackendSubjectIndexCompositionResult>;
|
|
22
|
+
asHostOnboarding(): HostOnboardingSdk;
|
|
23
|
+
asOrganizationController(): OrganizationControllerSdk;
|
|
24
|
+
asOrganizationEmployee(): OrganizationEmployeeSdk;
|
|
25
|
+
asIndividualController(): IndividualControllerSdk;
|
|
26
|
+
asIndividualMember(): IndividualMemberSdk;
|
|
27
|
+
asProfessional(): ProfessionalSdk;
|
|
28
|
+
createOrganizationControllerWorkspace(): OrganizationControllerProfileWorkspace;
|
|
29
|
+
createProfessionalWorkspace(): ProfessionalProfileWorkspace;
|
|
30
|
+
}
|
|
31
|
+
export declare class ProfileRuntime {
|
|
32
|
+
private readonly profileRuntime;
|
|
33
|
+
constructor(profileRuntime: BackendProfileRuntimeClient);
|
|
34
|
+
loadProfile(input: ProfileLoadRequest): Promise<LoadedProfileWorkspace>;
|
|
35
|
+
}
|
|
36
|
+
export declare function createLoadedProfileWorkspace(profileRuntime: BackendProfileRuntimeClient, profile: BackendLoadedActorProfile): LoadedProfileWorkspace;
|
|
37
|
+
/**
|
|
38
|
+
* @deprecated Prefer `LoadedProfileWorkspace`.
|
|
39
|
+
*/
|
|
40
|
+
export { LoadedProfileWorkspace as BackendProfileWorkspace };
|
|
41
|
+
/**
|
|
42
|
+
* @deprecated Prefer `ProfileRuntime`.
|
|
43
|
+
*/
|
|
44
|
+
export { ProfileRuntime as BackendProfileWorkspaceRuntime };
|
|
45
|
+
/**
|
|
46
|
+
* @deprecated Prefer `createLoadedProfileWorkspace`.
|
|
47
|
+
*/
|
|
48
|
+
export { createLoadedProfileWorkspace as createBackendProfileWorkspace };
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
// Copyright 2026 Antifraud Services Inc. under the Apache License, Version 2.0.
|
|
2
|
+
import { ActorKinds } from 'gdc-common-utils-ts/constants/actor-session';
|
|
3
|
+
import { closeBackendProfile, connectBackendToSubjectIndex, getBackendSubjectIndexComposition, registerBackendTrustedDevice, } from './backend-profile-runtime.js';
|
|
4
|
+
import { createOrganizationControllerProfileWorkspace, createProfessionalProfileWorkspace, } from './profile-workspace.js';
|
|
5
|
+
function requireActorSession(profile, actorKind) {
|
|
6
|
+
const session = profile.actorSessions.find((candidate) => candidate.actorKind === actorKind);
|
|
7
|
+
if (!session) {
|
|
8
|
+
throw new Error(`Loaded backend profile does not expose actor kind '${actorKind}'.`);
|
|
9
|
+
}
|
|
10
|
+
return session;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Backend loaded-profile workspace that keeps the canonical
|
|
14
|
+
* `loadProfile -> workspace/session -> actor facade` story explicit.
|
|
15
|
+
*/
|
|
16
|
+
export class LoadedProfileWorkspace {
|
|
17
|
+
constructor(profileRuntime, profile) {
|
|
18
|
+
this.profileRuntime = profileRuntime;
|
|
19
|
+
this.profile = profile;
|
|
20
|
+
}
|
|
21
|
+
close() {
|
|
22
|
+
return closeBackendProfile(this.profileRuntime, String(this.profile.descriptor.profileDid || this.profile.descriptor.profileId));
|
|
23
|
+
}
|
|
24
|
+
registerTrustedDevice(input) {
|
|
25
|
+
return registerBackendTrustedDevice(this.profileRuntime, input);
|
|
26
|
+
}
|
|
27
|
+
connectToSubjectIndex(input) {
|
|
28
|
+
return connectBackendToSubjectIndex(this.profileRuntime, input);
|
|
29
|
+
}
|
|
30
|
+
getSubjectIndexComposition(input) {
|
|
31
|
+
return getBackendSubjectIndexComposition(this.profileRuntime, input);
|
|
32
|
+
}
|
|
33
|
+
asHostOnboarding() {
|
|
34
|
+
return requireActorSession(this.profile, ActorKinds.HostOnboarding).asHostOnboarding();
|
|
35
|
+
}
|
|
36
|
+
asOrganizationController() {
|
|
37
|
+
return requireActorSession(this.profile, ActorKinds.OrganizationController).asOrganizationController();
|
|
38
|
+
}
|
|
39
|
+
asOrganizationEmployee() {
|
|
40
|
+
return requireActorSession(this.profile, ActorKinds.OrganizationEmployee).asOrganizationEmployee();
|
|
41
|
+
}
|
|
42
|
+
asIndividualController() {
|
|
43
|
+
return requireActorSession(this.profile, ActorKinds.IndividualController).asIndividualController();
|
|
44
|
+
}
|
|
45
|
+
asIndividualMember() {
|
|
46
|
+
return requireActorSession(this.profile, ActorKinds.IndividualMember).asIndividualMember();
|
|
47
|
+
}
|
|
48
|
+
asProfessional() {
|
|
49
|
+
return requireActorSession(this.profile, ActorKinds.Professional).asProfessional();
|
|
50
|
+
}
|
|
51
|
+
createOrganizationControllerWorkspace() {
|
|
52
|
+
const session = requireActorSession(this.profile, ActorKinds.OrganizationController);
|
|
53
|
+
return createOrganizationControllerProfileWorkspace({
|
|
54
|
+
profile: this.profile,
|
|
55
|
+
session,
|
|
56
|
+
sdk: this.asOrganizationController(),
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
createProfessionalWorkspace() {
|
|
60
|
+
const session = requireActorSession(this.profile, ActorKinds.Professional);
|
|
61
|
+
return createProfessionalProfileWorkspace({
|
|
62
|
+
profile: this.profile,
|
|
63
|
+
session,
|
|
64
|
+
sdk: this.asProfessional(),
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
export class ProfileRuntime {
|
|
69
|
+
constructor(profileRuntime) {
|
|
70
|
+
this.profileRuntime = profileRuntime;
|
|
71
|
+
}
|
|
72
|
+
async loadProfile(input) {
|
|
73
|
+
const profile = await this.profileRuntime.loadProfile(input);
|
|
74
|
+
return new LoadedProfileWorkspace(this.profileRuntime, profile);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
export function createLoadedProfileWorkspace(profileRuntime, profile) {
|
|
78
|
+
return new LoadedProfileWorkspace(profileRuntime, profile);
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* @deprecated Prefer `LoadedProfileWorkspace`.
|
|
82
|
+
*/
|
|
83
|
+
export { LoadedProfileWorkspace as BackendProfileWorkspace };
|
|
84
|
+
/**
|
|
85
|
+
* @deprecated Prefer `ProfileRuntime`.
|
|
86
|
+
*/
|
|
87
|
+
export { ProfileRuntime as BackendProfileWorkspaceRuntime };
|
|
88
|
+
/**
|
|
89
|
+
* @deprecated Prefer `createLoadedProfileWorkspace`.
|
|
90
|
+
*/
|
|
91
|
+
export { createLoadedProfileWorkspace as createBackendProfileWorkspace };
|
package/dist/index.d.ts
CHANGED
|
@@ -3,6 +3,7 @@ export * from './runtime-contracts.js';
|
|
|
3
3
|
export * from './identity-bootstrap.js';
|
|
4
4
|
export * from './async-polling.js';
|
|
5
5
|
export * from './backend-profile-runtime.js';
|
|
6
|
+
export * from './backend-profile-workspace.js';
|
|
6
7
|
export * from './individual-controller-backend-runtime.js';
|
|
7
8
|
export * from './organization-controller-backend-runtime.js';
|
|
8
9
|
export * from './professional-backend-runtime.js';
|
package/dist/index.js
CHANGED
|
@@ -4,6 +4,7 @@ export * from './runtime-contracts.js';
|
|
|
4
4
|
export * from './identity-bootstrap.js';
|
|
5
5
|
export * from './async-polling.js';
|
|
6
6
|
export * from './backend-profile-runtime.js';
|
|
7
|
+
export * from './backend-profile-workspace.js';
|
|
7
8
|
export * from './individual-controller-backend-runtime.js';
|
|
8
9
|
export * from './organization-controller-backend-runtime.js';
|
|
9
10
|
export * from './professional-backend-runtime.js';
|
|
@@ -4,7 +4,7 @@ import type { IndividualOrganizationConfirmOrderInput, RouteContext } from './in
|
|
|
4
4
|
import type { IndividualOrganizationBootstrapInput, IndividualOrganizationStartResult } from './individual-start.js';
|
|
5
5
|
import type { EnsureFamilyOrganizationRegistrationInput, EnsureFamilyOrganizationRegistrationResult } from './family-organization-registration.js';
|
|
6
6
|
import type { FamilyOrganizationSearchInput } from './family-organization-search.js';
|
|
7
|
-
import type { ClinicalBundleSearchInput } from './resource-operations.js';
|
|
7
|
+
import type { BlockchainArtifactRegistrationInput, ClinicalBundleSearchInput } from './resource-operations.js';
|
|
8
8
|
import { type BackendIndividualControllerProfile, type BackendProfileRuntimeClient } from './backend-profile-runtime.js';
|
|
9
9
|
import type { ProfileLoadRequest } from 'gdc-sdk-core-ts';
|
|
10
10
|
/**
|
|
@@ -56,4 +56,9 @@ export declare class IndividualControllerBackendRuntime {
|
|
|
56
56
|
* individual-controller facade.
|
|
57
57
|
*/
|
|
58
58
|
getLatestIps(profile: BackendIndividualControllerProfile, ctx: RouteContext, input: Omit<ClinicalBundleSearchInput, 'includedTypes'>): Promise<SubmitAndPollResult>;
|
|
59
|
+
/**
|
|
60
|
+
* Registers one FHIR resource or raw artifact on blockchain before it is
|
|
61
|
+
* attached to a subject communication.
|
|
62
|
+
*/
|
|
63
|
+
registerBlockchainArtifactAndUpdateIndex(profile: BackendIndividualControllerProfile, ctx: RouteContext, input: BlockchainArtifactRegistrationInput): Promise<SubmitAndPollResult>;
|
|
59
64
|
}
|
|
@@ -64,4 +64,11 @@ export class IndividualControllerBackendRuntime {
|
|
|
64
64
|
getLatestIps(profile, ctx, input) {
|
|
65
65
|
return profile.sdk.getLatestIps(ctx, input);
|
|
66
66
|
}
|
|
67
|
+
/**
|
|
68
|
+
* Registers one FHIR resource or raw artifact on blockchain before it is
|
|
69
|
+
* attached to a subject communication.
|
|
70
|
+
*/
|
|
71
|
+
registerBlockchainArtifactAndUpdateIndex(profile, ctx, input) {
|
|
72
|
+
return profile.sdk.registerBlockchainArtifactAndUpdateIndex(ctx, input);
|
|
73
|
+
}
|
|
67
74
|
}
|
|
@@ -10,7 +10,7 @@ import { type FamilyOrganizationSearchInput } from './family-organization-search
|
|
|
10
10
|
import { type SmartTokenRequestInput } from './smart-token.js';
|
|
11
11
|
import { type OrganizationLicenseOrderConfirmInput } from './organization-license-order.js';
|
|
12
12
|
import { type IndividualOrganizationBootstrapInput, type IndividualOrganizationStartResult } from './individual-start.js';
|
|
13
|
-
import { type CommunicationIngestionInput, type CommunicationParticipantRuntimeSearchInput, type ClinicalBundleSearchInput, type GrantProfessionalAccessInput, type GrantProfessionalAccessResult, type IndividualMemberLifecycleInput, type LicenseListRuntimeSearchInput, type LicenseOfferRuntimeSearchInput, type LicenseOrderRuntimeSearchInput, type OrganizationEmployeeCreationInput, type OrganizationEmployeeLifecycleInput, type OrganizationEmployeeSearchInput, type RevokeProfessionalAccessInput, type RevokeProfessionalAccessResult, type RelatedPersonUpsertInput } from './resource-operations.js';
|
|
13
|
+
import { type CommunicationIngestionInput, type BlockchainArtifactRegistrationInput, type VitalSignBatchCommunicationFromSearchResponseInput, type CommunicationParticipantRuntimeSearchInput, type ClinicalBundleSearchInput, type GrantProfessionalAccessInput, type GrantProfessionalAccessResult, type IndividualMemberLifecycleInput, type LicenseListRuntimeSearchInput, type LicenseOfferRuntimeSearchInput, type LicenseOrderRuntimeSearchInput, type OrganizationEmployeeCreationInput, type OrganizationEmployeeLifecycleInput, type OrganizationEmployeeSearchInput, type RevokeProfessionalAccessInput, type RevokeProfessionalAccessResult, type RelatedPersonUpsertInput } from './resource-operations.js';
|
|
14
14
|
import type { LegalOrganizationOrderInput } from './host-onboarding.js';
|
|
15
15
|
import type { SmartTokenExchangeResult } from './smart-token.js';
|
|
16
16
|
import type { NodeRuntimeClient, PollOptions, PollResult, SubmitAndPollResult, SubmitPayload, SubmitResponse } from './orchestration/client-port.js';
|
|
@@ -376,6 +376,16 @@ export declare class HttpRuntimeClient implements NodeRuntimeClient {
|
|
|
376
376
|
* @param input Communication payload plus route/format options.
|
|
377
377
|
*/
|
|
378
378
|
ingestCommunicationAndUpdateIndex(ctx: RouteContext, input: CommunicationIngestionInput): Promise<SubmitAndPollResult>;
|
|
379
|
+
/**
|
|
380
|
+
* Registers one FHIR resource or raw artifact on blockchain and waits until
|
|
381
|
+
* GW has indexed the resulting DocumentReference projection.
|
|
382
|
+
*/
|
|
383
|
+
registerBlockchainArtifactAndUpdateIndex(ctx: RouteContext, input: BlockchainArtifactRegistrationInput): Promise<SubmitAndPollResult>;
|
|
384
|
+
/**
|
|
385
|
+
* Builds and submits a Communication carrying the selected vital-sign day
|
|
386
|
+
* batch artifacts from a paginated search response.
|
|
387
|
+
*/
|
|
388
|
+
submitVitalSignBatchCommunicationFromSearchResponse(ctx: RouteContext, input: VitalSignBatchCommunicationFromSearchResponseInput): Promise<SubmitAndPollResult>;
|
|
379
389
|
/**
|
|
380
390
|
* Searches communication channel records by subject and participant
|
|
381
391
|
* identifiers through `Communication/_search`.
|
|
@@ -483,6 +493,8 @@ export declare class HttpRuntimeClient implements NodeRuntimeClient {
|
|
|
483
493
|
individualCommunicationPollPath(ctx: RouteContext, format: 'org.hl7.fhir.api' | 'org.hl7.fhir.r4'): string;
|
|
484
494
|
individualCommunicationSearchPath(ctx: RouteContext): string;
|
|
485
495
|
individualCommunicationSearchPollPath(ctx: RouteContext): string;
|
|
496
|
+
individualDocumentReferenceBatchPath(ctx: RouteContext): string;
|
|
497
|
+
individualDocumentReferencePollPath(ctx: RouteContext): string;
|
|
486
498
|
individualBundleSearchPath(ctx: RouteContext): string;
|
|
487
499
|
individualBundleSearchPollPath(ctx: RouteContext): string;
|
|
488
500
|
identityTokenExchangePath(ctx: RouteContext): string;
|
|
@@ -11,7 +11,7 @@ import { requestSmartTokenWithDeps } from './smart-token.js';
|
|
|
11
11
|
import { extractOfferIdFromResponseBody, extractOfferPreviewFromResponseBody, } from './order-offer-summary.js';
|
|
12
12
|
import { confirmOrganizationLicenseOrderWithDeps } from './organization-license-order.js';
|
|
13
13
|
import { startIndividualOrganizationWithDeps } from './individual-start.js';
|
|
14
|
-
import { createOrganizationEmployeeWithDeps, disableIndividualMemberWithDeps, disableIndividualOrganizationWithDeps, disableOrganizationEmployeeWithDeps, listIndividualLicenseOffersWithDeps, listIndividualLicenseOrdersWithDeps, listIndividualLicensesWithDeps, listOrganizationLicenseOffersWithDeps, listOrganizationLicenseOrdersWithDeps, listOrganizationLicensesWithDeps, grantProfessionalAccessWithDeps, ingestCommunicationAndUpdateIndexWithDeps, revokeProfessionalAccessWithDeps, searchCommunicationParticipantsWithDeps, purgeIndividualMemberWithDeps, purgeIndividualOrganizationWithDeps, purgeOrganizationEmployeeWithDeps, searchIndividualLicensesWithDeps, searchIndividualLicenseOffersWithDeps, searchIndividualLicenseOrdersWithDeps, searchOrganizationLicensesWithDeps, searchOrganizationLicenseOffersWithDeps, searchOrganizationLicenseOrdersWithDeps, searchOrganizationEmployeesWithDeps, searchClinicalBundleWithDeps, searchLatestIpsWithDeps, upsertRelatedPersonAndPollWithDeps, } from './resource-operations.js';
|
|
14
|
+
import { createOrganizationEmployeeWithDeps, disableIndividualMemberWithDeps, disableIndividualOrganizationWithDeps, disableOrganizationEmployeeWithDeps, listIndividualLicenseOffersWithDeps, listIndividualLicenseOrdersWithDeps, listIndividualLicensesWithDeps, listOrganizationLicenseOffersWithDeps, listOrganizationLicenseOrdersWithDeps, listOrganizationLicensesWithDeps, grantProfessionalAccessWithDeps, ingestCommunicationAndUpdateIndexWithDeps, buildVitalSignBatchCommunicationFromSearchResponse, registerBlockchainArtifactAndUpdateIndexWithDeps, revokeProfessionalAccessWithDeps, searchCommunicationParticipantsWithDeps, purgeIndividualMemberWithDeps, purgeIndividualOrganizationWithDeps, purgeOrganizationEmployeeWithDeps, searchIndividualLicensesWithDeps, searchIndividualLicenseOffersWithDeps, searchIndividualLicenseOrdersWithDeps, searchOrganizationLicensesWithDeps, searchOrganizationLicenseOffersWithDeps, searchOrganizationLicenseOrdersWithDeps, searchOrganizationEmployeesWithDeps, searchClinicalBundleWithDeps, searchLatestIpsWithDeps, upsertRelatedPersonAndPollWithDeps, } from './resource-operations.js';
|
|
15
15
|
import { submitAndPollWithMethods } from './orchestration/client-port.js';
|
|
16
16
|
import { buildRuntimeHeaders, fetchWithTimeout, parseResponseBody, pollBatchResponseWithRuntimeConfig, postJsonWithRuntimeConfig, } from './runtime-transport.js';
|
|
17
17
|
import { activateOrganizationInGatewayFromIcaProofWithDeps, submitLegalOrganizationIssueWithDeps, submitLegalOrganizationVerificationTransactionWithDeps, submitOrganizationDidBindingWithDeps, } from './runtime-host-submission.js';
|
|
@@ -680,6 +680,28 @@ export class HttpRuntimeClient {
|
|
|
680
680
|
submitAndPoll: this.submitAndPoll.bind(this),
|
|
681
681
|
});
|
|
682
682
|
}
|
|
683
|
+
/**
|
|
684
|
+
* Registers one FHIR resource or raw artifact on blockchain and waits until
|
|
685
|
+
* GW has indexed the resulting DocumentReference projection.
|
|
686
|
+
*/
|
|
687
|
+
async registerBlockchainArtifactAndUpdateIndex(ctx, input) {
|
|
688
|
+
return registerBlockchainArtifactAndUpdateIndexWithDeps(ctx, input, {
|
|
689
|
+
individualDocumentReferenceBatchPath: this.paths.individualDocumentReferenceBatchPath.bind(this.paths),
|
|
690
|
+
individualDocumentReferencePollPath: this.paths.individualDocumentReferencePollPath.bind(this.paths),
|
|
691
|
+
submitAndPoll: this.submitAndPoll.bind(this),
|
|
692
|
+
});
|
|
693
|
+
}
|
|
694
|
+
/**
|
|
695
|
+
* Builds and submits a Communication carrying the selected vital-sign day
|
|
696
|
+
* batch artifacts from a paginated search response.
|
|
697
|
+
*/
|
|
698
|
+
async submitVitalSignBatchCommunicationFromSearchResponse(ctx, input) {
|
|
699
|
+
return ingestCommunicationAndUpdateIndexWithDeps(ctx, buildVitalSignBatchCommunicationFromSearchResponse(input), {
|
|
700
|
+
individualCommunicationBatchPath: this.paths.individualCommunicationBatchPath.bind(this.paths),
|
|
701
|
+
individualCommunicationPollPath: this.paths.individualCommunicationPollPath.bind(this.paths),
|
|
702
|
+
submitAndPoll: this.submitAndPoll.bind(this),
|
|
703
|
+
});
|
|
704
|
+
}
|
|
683
705
|
/**
|
|
684
706
|
* Searches communication channel records by subject and participant
|
|
685
707
|
* identifiers through `Communication/_search`.
|
|
@@ -824,6 +846,8 @@ export class HttpRuntimeClient {
|
|
|
824
846
|
individualCommunicationPollPath(ctx, format) { return this.paths.individualCommunicationPollPath(ctx, format); }
|
|
825
847
|
individualCommunicationSearchPath(ctx) { return this.paths.individualCommunicationSearchPath(ctx); }
|
|
826
848
|
individualCommunicationSearchPollPath(ctx) { return this.paths.individualCommunicationSearchPollPath(ctx); }
|
|
849
|
+
individualDocumentReferenceBatchPath(ctx) { return this.paths.individualDocumentReferenceBatchPath(ctx); }
|
|
850
|
+
individualDocumentReferencePollPath(ctx) { return this.paths.individualDocumentReferencePollPath(ctx); }
|
|
827
851
|
individualBundleSearchPath(ctx) { return this.paths.individualBundleSearchPath(ctx); }
|
|
828
852
|
individualBundleSearchPollPath(ctx) { return this.paths.individualBundleSearchPollPath(ctx); }
|
|
829
853
|
identityTokenExchangePath(ctx) { return this.paths.identityTokenExchangePath(ctx); }
|
|
@@ -13,7 +13,7 @@ import type { FamilyOrganizationSearchInput } from '../family-organization-searc
|
|
|
13
13
|
import type { EnsureFamilyOrganizationRegistrationInput, EnsureFamilyOrganizationRegistrationResult } from '../family-organization-registration.js';
|
|
14
14
|
import type { OrganizationLicenseOrderConfirmInput } from '../organization-license-order.js';
|
|
15
15
|
import type { SmartTokenExchangeResult, SmartTokenRequestInput } from '../smart-token.js';
|
|
16
|
-
import type { CommunicationIngestionInput, CommunicationParticipantRuntimeSearchInput, ClinicalBundleSearchInput, DigitalTwinGenerationInput, GrantProfessionalAccessInput, GrantProfessionalAccessResult, IndividualMemberLifecycleInput, IpsOrFhirImportInput, OrganizationEmployeeCreationInput, OrganizationEmployeeLifecycleInput, OrganizationEmployeeSearchInput, RevokeProfessionalAccessInput, RevokeProfessionalAccessResult, RelatedPersonUpsertInput } from '../resource-operations.js';
|
|
16
|
+
import type { CommunicationIngestionInput, BlockchainArtifactRegistrationInput, CommunicationParticipantRuntimeSearchInput, ClinicalBundleSearchInput, VitalSignBatchCommunicationFromSearchResponseInput, DigitalTwinGenerationInput, GrantProfessionalAccessInput, GrantProfessionalAccessResult, IndividualMemberLifecycleInput, IpsOrFhirImportInput, OrganizationEmployeeCreationInput, OrganizationEmployeeLifecycleInput, OrganizationEmployeeSearchInput, RevokeProfessionalAccessInput, RevokeProfessionalAccessResult, RelatedPersonUpsertInput } from '../resource-operations.js';
|
|
17
17
|
/**
|
|
18
18
|
* Shared node-runtime activation input.
|
|
19
19
|
*
|
|
@@ -58,6 +58,7 @@ export type RuntimeClient = {
|
|
|
58
58
|
submitOrganizationDidBinding?: (ctx: RouteContext, input: NodeOrganizationDidBindingInput, pollOptions?: PollOptions) => Promise<SubmitAndPollResult>;
|
|
59
59
|
activateOrganizationInGatewayFromIcaProof?: (hostCtx: HostRouteContext, input: NodeOrganizationActivationInput, pollOptions?: PollOptions) => Promise<SubmitAndPollResult>;
|
|
60
60
|
confirmLegalOrganizationOrder?: (hostCtx: HostRouteContext, input: LegalOrganizationOrderInput, pollOptions?: PollOptions) => Promise<SubmitAndPollResult>;
|
|
61
|
+
submitVitalSignBatchCommunicationFromSearchResponse?: (ctx: RouteContext, input: VitalSignBatchCommunicationFromSearchResponseInput) => Promise<SubmitAndPollResult>;
|
|
61
62
|
disableHost?: (hostCtx: HostRouteContext, input: HostedTenantLifecycleInput, pollOptions?: PollOptions) => Promise<SubmitAndPollResult>;
|
|
62
63
|
purgeHost?: (hostCtx: HostRouteContext, input: HostedTenantLifecycleInput, pollOptions?: PollOptions) => Promise<SubmitAndPollResult>;
|
|
63
64
|
disableTenant?: (hostCtx: HostRouteContext, input: HostedTenantLifecycleInput, pollOptions?: PollOptions) => Promise<SubmitAndPollResult>;
|
|
@@ -88,6 +89,7 @@ export type RuntimeClient = {
|
|
|
88
89
|
disableIndividualOrganization?: (ctx: RouteContext, input: IndividualOrganizationLifecycleInput, pollOptions?: PollOptions) => Promise<SubmitAndPollResult>;
|
|
89
90
|
purgeIndividualOrganization?: (ctx: RouteContext, input: IndividualOrganizationLifecycleInput, pollOptions?: PollOptions) => Promise<SubmitAndPollResult>;
|
|
90
91
|
ingestCommunicationAndUpdateIndex?: (ctx: RouteContext, input: CommunicationIngestionInput) => Promise<SubmitAndPollResult>;
|
|
92
|
+
registerBlockchainArtifactAndUpdateIndex?: (ctx: RouteContext, input: BlockchainArtifactRegistrationInput) => Promise<SubmitAndPollResult>;
|
|
91
93
|
searchCommunicationParticipants?: (ctx: RouteContext, input: CommunicationParticipantRuntimeSearchInput) => Promise<SubmitAndPollResult>;
|
|
92
94
|
grantProfessionalAccess?: (ctx: RouteContext, input: GrantProfessionalAccessInput) => Promise<GrantProfessionalAccessResult>;
|
|
93
95
|
revokeProfessionalAccess?: (ctx: RouteContext, input: RevokeProfessionalAccessInput) => Promise<RevokeProfessionalAccessResult>;
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { type IndividualControllerCredentialInput, type IndividualControllerVpPayloadInput, type IndividualSubjectCredentialInput } from 'gdc-common-utils-ts';
|
|
1
2
|
import { type NodeRuntimeClient, type PollOptions, type SubmitAndPollResult, type SubmitPayload } from './client-port.js';
|
|
2
3
|
import type { FamilyOrganizationSummary } from 'gdc-common-utils-ts/utils/family-organization-summary';
|
|
3
4
|
import type { EnsureFamilyOrganizationRegistrationInput, EnsureFamilyOrganizationRegistrationResult } from '../family-organization-registration.js';
|
|
@@ -6,7 +7,7 @@ import type { IndividualOrganizationConfirmOrderInput, RouteContext } from '../i
|
|
|
6
7
|
import type { IndividualOrganizationBootstrapInput, IndividualOrganizationStartResult } from '../individual-start.js';
|
|
7
8
|
import type { NodeCapability } from '../session.js';
|
|
8
9
|
import type { IndividualOrganizationLifecycleInput } from 'gdc-sdk-core-ts';
|
|
9
|
-
import type { ClinicalBundleSearchInput, CommunicationIngestionInput, CommunicationParticipantRuntimeSearchInput, DigitalTwinGenerationInput, GrantProfessionalAccessInput, GrantProfessionalAccessResult, IndividualMemberLifecycleInput, IpsOrFhirImportInput, LicenseListRuntimeSearchInput, LicenseOfferRuntimeSearchInput, LicenseOrderRuntimeSearchInput, RevokeProfessionalAccessInput, RevokeProfessionalAccessResult, RelatedPersonUpsertInput } from '../resource-operations.js';
|
|
10
|
+
import type { BlockchainArtifactRegistrationInput, ClinicalBundleSearchInput, CommunicationIngestionInput, CommunicationParticipantRuntimeSearchInput, DigitalTwinGenerationInput, GrantProfessionalAccessInput, GrantProfessionalAccessResult, IndividualMemberLifecycleInput, IpsOrFhirImportInput, LicenseListRuntimeSearchInput, LicenseOfferRuntimeSearchInput, LicenseOrderRuntimeSearchInput, RevokeProfessionalAccessInput, RevokeProfessionalAccessResult, RelatedPersonUpsertInput } from '../resource-operations.js';
|
|
10
11
|
import type { SmartTokenExchangeResult, SmartTokenRequestInput } from '../smart-token.js';
|
|
11
12
|
/**
|
|
12
13
|
* Individual-controller oriented facade over a `NodeRuntimeClient`.
|
|
@@ -85,6 +86,11 @@ export declare class IndividualControllerSdk {
|
|
|
85
86
|
* Ingests a FHIR `Communication` and waits for indexing.
|
|
86
87
|
*/
|
|
87
88
|
ingestCommunicationAndUpdateIndex(ctx: RouteContext, input: CommunicationIngestionInput): Promise<SubmitAndPollResult>;
|
|
89
|
+
/**
|
|
90
|
+
* Registers one FHIR resource or raw artifact on blockchain before it is
|
|
91
|
+
* attached to a subject communication.
|
|
92
|
+
*/
|
|
93
|
+
registerBlockchainArtifactAndUpdateIndex(ctx: RouteContext, input: BlockchainArtifactRegistrationInput): Promise<SubmitAndPollResult>;
|
|
88
94
|
/**
|
|
89
95
|
* Searches indexed communication channel records by subject and participant
|
|
90
96
|
* identifiers.
|
|
@@ -133,6 +139,36 @@ export declare class IndividualControllerSdk {
|
|
|
133
139
|
* Requests a SMART/OpenID token for subsequent data access flows.
|
|
134
140
|
*/
|
|
135
141
|
requestSmartToken(input: SmartTokenRequestInput): Promise<SmartTokenExchangeResult>;
|
|
142
|
+
/**
|
|
143
|
+
* Returns the normalized public continuity aliases that would be embedded in
|
|
144
|
+
* the individual-controller identity VC for SMART/OpenID4VP flows.
|
|
145
|
+
*/
|
|
146
|
+
getIdentitySameAs(input: IndividualControllerCredentialInput): string[];
|
|
147
|
+
/**
|
|
148
|
+
* Builds the canonical individual-controller identity VC used by shared
|
|
149
|
+
* SMART VP helpers.
|
|
150
|
+
*/
|
|
151
|
+
getIdentityVC(input: IndividualControllerCredentialInput): Record<string, unknown>;
|
|
152
|
+
/**
|
|
153
|
+
* Builds one canonical subject VC for the dependent subject managed by the
|
|
154
|
+
* current controller, for example a child, pet, or another represented
|
|
155
|
+
* individual.
|
|
156
|
+
*/
|
|
157
|
+
getSubjectVC(input: IndividualSubjectCredentialInput): Record<string, unknown>;
|
|
158
|
+
/**
|
|
159
|
+
* Builds the canonical individual-controller identity VP payload used by
|
|
160
|
+
* shared SMART/OpenID4VP helpers.
|
|
161
|
+
*/
|
|
162
|
+
buildIdentityVpPayload(input: IndividualControllerVpPayloadInput): Record<string, unknown>;
|
|
163
|
+
/**
|
|
164
|
+
* Builds one unsigned compact VP JWT for the canonical
|
|
165
|
+
* individual-controller identity payload.
|
|
166
|
+
*/
|
|
167
|
+
buildUnsignedIdentityVpJwt(input: IndividualControllerVpPayloadInput, options?: Readonly<{
|
|
168
|
+
nowSeconds?: number;
|
|
169
|
+
ttlSeconds?: number;
|
|
170
|
+
nonce?: string;
|
|
171
|
+
}>): string;
|
|
136
172
|
/**
|
|
137
173
|
* Low-level escape hatch for direct submit/poll flows.
|
|
138
174
|
*/
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
// Copyright 2026 Antifraud Services Inc. under the Apache License, Version 2.0.
|
|
2
2
|
import { ActorCapabilities, ActorKinds } from 'gdc-common-utils-ts/constants/actor-session';
|
|
3
|
+
import { buildIndividualControllerIdentityVpPayload, buildUnsignedIndividualControllerIdentityVpJwt, getIndividualControllerIdentitySameAs, getIndividualControllerIdentityVC, getIndividualSubjectVC, } from 'gdc-common-utils-ts';
|
|
3
4
|
import { requireClientMethod, submitAndPollWithClient, } from './client-port.js';
|
|
4
5
|
import { assertFacadeCapability } from './capability-guard.js';
|
|
5
6
|
/**
|
|
@@ -123,6 +124,13 @@ export class IndividualControllerSdk {
|
|
|
123
124
|
assertFacadeCapability(this.capabilities, ActorCapabilities.IndividualIngestCommunication, ActorKinds.IndividualController, 'ingestCommunicationAndUpdateIndex');
|
|
124
125
|
return requireClientMethod(this.client, 'ingestCommunicationAndUpdateIndex')(ctx, input);
|
|
125
126
|
}
|
|
127
|
+
/**
|
|
128
|
+
* Registers one FHIR resource or raw artifact on blockchain before it is
|
|
129
|
+
* attached to a subject communication.
|
|
130
|
+
*/
|
|
131
|
+
registerBlockchainArtifactAndUpdateIndex(ctx, input) {
|
|
132
|
+
return requireClientMethod(this.client, 'registerBlockchainArtifactAndUpdateIndex')(ctx, input);
|
|
133
|
+
}
|
|
126
134
|
/**
|
|
127
135
|
* Searches indexed communication channel records by subject and participant
|
|
128
136
|
* identifiers.
|
|
@@ -194,6 +202,42 @@ export class IndividualControllerSdk {
|
|
|
194
202
|
requestSmartToken(input) {
|
|
195
203
|
return requireClientMethod(this.client, 'requestSmartToken')(input);
|
|
196
204
|
}
|
|
205
|
+
/**
|
|
206
|
+
* Returns the normalized public continuity aliases that would be embedded in
|
|
207
|
+
* the individual-controller identity VC for SMART/OpenID4VP flows.
|
|
208
|
+
*/
|
|
209
|
+
getIdentitySameAs(input) {
|
|
210
|
+
return getIndividualControllerIdentitySameAs(input);
|
|
211
|
+
}
|
|
212
|
+
/**
|
|
213
|
+
* Builds the canonical individual-controller identity VC used by shared
|
|
214
|
+
* SMART VP helpers.
|
|
215
|
+
*/
|
|
216
|
+
getIdentityVC(input) {
|
|
217
|
+
return getIndividualControllerIdentityVC(input);
|
|
218
|
+
}
|
|
219
|
+
/**
|
|
220
|
+
* Builds one canonical subject VC for the dependent subject managed by the
|
|
221
|
+
* current controller, for example a child, pet, or another represented
|
|
222
|
+
* individual.
|
|
223
|
+
*/
|
|
224
|
+
getSubjectVC(input) {
|
|
225
|
+
return getIndividualSubjectVC(input);
|
|
226
|
+
}
|
|
227
|
+
/**
|
|
228
|
+
* Builds the canonical individual-controller identity VP payload used by
|
|
229
|
+
* shared SMART/OpenID4VP helpers.
|
|
230
|
+
*/
|
|
231
|
+
buildIdentityVpPayload(input) {
|
|
232
|
+
return buildIndividualControllerIdentityVpPayload(input);
|
|
233
|
+
}
|
|
234
|
+
/**
|
|
235
|
+
* Builds one unsigned compact VP JWT for the canonical
|
|
236
|
+
* individual-controller identity payload.
|
|
237
|
+
*/
|
|
238
|
+
buildUnsignedIdentityVpJwt(input, options = {}) {
|
|
239
|
+
return buildUnsignedIndividualControllerIdentityVpJwt(input, options);
|
|
240
|
+
}
|
|
197
241
|
/**
|
|
198
242
|
* Low-level escape hatch for direct submit/poll flows.
|
|
199
243
|
*/
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { type IndividualMemberCredentialInput, type IndividualMemberVpPayloadInput } from 'gdc-common-utils-ts';
|
|
1
2
|
import { type NodeRuntimeClient } from './client-port.js';
|
|
2
3
|
import type { SmartTokenExchangeResult, SmartTokenRequestInput } from '../smart-token.js';
|
|
3
4
|
import type { RouteContext } from '../individual-onboarding.js';
|
|
@@ -14,4 +15,28 @@ export declare class IndividualMemberSdk {
|
|
|
14
15
|
* caregiver, guardian, or family member.
|
|
15
16
|
*/
|
|
16
17
|
requestSmartToken(input: SmartTokenRequestInput): Promise<SmartTokenExchangeResult>;
|
|
18
|
+
/**
|
|
19
|
+
* Returns the normalized public continuity aliases that would be embedded in
|
|
20
|
+
* the individual-member identity VC for SMART/OpenID4VP flows.
|
|
21
|
+
*/
|
|
22
|
+
getIdentitySameAs(input: IndividualMemberCredentialInput): string[];
|
|
23
|
+
/**
|
|
24
|
+
* Builds the canonical individual-member identity VC used by shared SMART VP
|
|
25
|
+
* helpers.
|
|
26
|
+
*/
|
|
27
|
+
getIdentityVC(input: IndividualMemberCredentialInput): Record<string, unknown>;
|
|
28
|
+
/**
|
|
29
|
+
* Builds the canonical individual-member identity VP payload used by shared
|
|
30
|
+
* SMART/OpenID4VP helpers.
|
|
31
|
+
*/
|
|
32
|
+
buildIdentityVpPayload(input: IndividualMemberVpPayloadInput): Record<string, unknown>;
|
|
33
|
+
/**
|
|
34
|
+
* Builds one unsigned compact VP JWT for the canonical individual-member
|
|
35
|
+
* identity payload.
|
|
36
|
+
*/
|
|
37
|
+
buildUnsignedIdentityVpJwt(input: IndividualMemberVpPayloadInput, options?: Readonly<{
|
|
38
|
+
nowSeconds?: number;
|
|
39
|
+
ttlSeconds?: number;
|
|
40
|
+
nonce?: string;
|
|
41
|
+
}>): string;
|
|
17
42
|
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
// Copyright 2026 Antifraud Services Inc. under the Apache License, Version 2.0.
|
|
2
|
+
import { buildIndividualMemberIdentityVpPayload, buildUnsignedIndividualMemberIdentityVpJwt, getIndividualMemberIdentitySameAs, getIndividualMemberIdentityVC, } from 'gdc-common-utils-ts';
|
|
2
3
|
import { requireClientMethod } from './client-port.js';
|
|
3
4
|
export class IndividualMemberSdk {
|
|
4
5
|
constructor(client) {
|
|
@@ -17,4 +18,32 @@ export class IndividualMemberSdk {
|
|
|
17
18
|
requestSmartToken(input) {
|
|
18
19
|
return requireClientMethod(this.client, 'requestSmartToken')(input);
|
|
19
20
|
}
|
|
21
|
+
/**
|
|
22
|
+
* Returns the normalized public continuity aliases that would be embedded in
|
|
23
|
+
* the individual-member identity VC for SMART/OpenID4VP flows.
|
|
24
|
+
*/
|
|
25
|
+
getIdentitySameAs(input) {
|
|
26
|
+
return getIndividualMemberIdentitySameAs(input);
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Builds the canonical individual-member identity VC used by shared SMART VP
|
|
30
|
+
* helpers.
|
|
31
|
+
*/
|
|
32
|
+
getIdentityVC(input) {
|
|
33
|
+
return getIndividualMemberIdentityVC(input);
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Builds the canonical individual-member identity VP payload used by shared
|
|
37
|
+
* SMART/OpenID4VP helpers.
|
|
38
|
+
*/
|
|
39
|
+
buildIdentityVpPayload(input) {
|
|
40
|
+
return buildIndividualMemberIdentityVpPayload(input);
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Builds one unsigned compact VP JWT for the canonical individual-member
|
|
44
|
+
* identity payload.
|
|
45
|
+
*/
|
|
46
|
+
buildUnsignedIdentityVpJwt(input, options = {}) {
|
|
47
|
+
return buildUnsignedIndividualMemberIdentityVpJwt(input, options);
|
|
48
|
+
}
|
|
20
49
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { type NodeRuntimeClient, type PollOptions, type SubmitAndPollResult, type SubmitPayload } from './client-port.js';
|
|
2
2
|
import type { IndividualOrganizationBootstrapInput, IndividualOrganizationStartResult } from '../individual-start.js';
|
|
3
3
|
import type { RouteContext } from '../individual-onboarding.js';
|
|
4
|
-
import type { ClinicalBundleSearchInput, CommunicationIngestionInput, CommunicationParticipantRuntimeSearchInput, DigitalTwinGenerationInput, GrantProfessionalAccessInput, GrantProfessionalAccessResult, IpsOrFhirImportInput, LicenseListRuntimeSearchInput, LicenseOfferRuntimeSearchInput, LicenseOrderRuntimeSearchInput } from '../resource-operations.js';
|
|
4
|
+
import type { BlockchainArtifactRegistrationInput, ClinicalBundleSearchInput, CommunicationIngestionInput, CommunicationParticipantRuntimeSearchInput, DigitalTwinGenerationInput, GrantProfessionalAccessInput, GrantProfessionalAccessResult, IpsOrFhirImportInput, LicenseListRuntimeSearchInput, LicenseOfferRuntimeSearchInput, LicenseOrderRuntimeSearchInput } from '../resource-operations.js';
|
|
5
5
|
import type { SmartTokenExchangeResult, SmartTokenRequestInput } from '../smart-token.js';
|
|
6
6
|
export declare class PersonalSdk {
|
|
7
7
|
private readonly client;
|
|
@@ -14,6 +14,8 @@ export declare class PersonalSdk {
|
|
|
14
14
|
importIpsOrFhirAndUpdateIndex(ctx: RouteContext, input: IpsOrFhirImportInput): Promise<SubmitAndPollResult>;
|
|
15
15
|
/** Ingests canonical Communication and waits for projection completion. */
|
|
16
16
|
ingestCommunicationAndUpdateIndex(ctx: RouteContext, input: CommunicationIngestionInput): Promise<SubmitAndPollResult>;
|
|
17
|
+
/** Registers one FHIR resource or raw artifact on blockchain before communication. */
|
|
18
|
+
registerBlockchainArtifactAndUpdateIndex(ctx: RouteContext, input: BlockchainArtifactRegistrationInput): Promise<SubmitAndPollResult>;
|
|
17
19
|
/** Searches indexed communication channel records by subject and participant identifiers. */
|
|
18
20
|
searchCommunicationParticipants(ctx: RouteContext, input: CommunicationParticipantRuntimeSearchInput): Promise<SubmitAndPollResult>;
|
|
19
21
|
/** Triggers digital twin generation from subject data. */
|
|
@@ -20,6 +20,10 @@ export class PersonalSdk {
|
|
|
20
20
|
ingestCommunicationAndUpdateIndex(ctx, input) {
|
|
21
21
|
return requireClientMethod(this.client, 'ingestCommunicationAndUpdateIndex')(ctx, input);
|
|
22
22
|
}
|
|
23
|
+
/** Registers one FHIR resource or raw artifact on blockchain before communication. */
|
|
24
|
+
registerBlockchainArtifactAndUpdateIndex(ctx, input) {
|
|
25
|
+
return requireClientMethod(this.client, 'registerBlockchainArtifactAndUpdateIndex')(ctx, input);
|
|
26
|
+
}
|
|
23
27
|
/** Searches indexed communication channel records by subject and participant identifiers. */
|
|
24
28
|
searchCommunicationParticipants(ctx, input) {
|
|
25
29
|
return requireClientMethod(this.client, 'searchCommunicationParticipants')(ctx, input);
|
|
@@ -2,7 +2,7 @@ import { type ProfessionalEmployeeCredentialInput, type ProfessionalSmartVpPaylo
|
|
|
2
2
|
import { type NodeRuntimeClient, type PollOptions, type SubmitAndPollResult, type SubmitPayload } from './client-port.js';
|
|
3
3
|
import type { RouteContext } from '../individual-onboarding.js';
|
|
4
4
|
import type { SmartTokenExchangeResult, SmartTokenRequestInput } from '../smart-token.js';
|
|
5
|
-
import type { CommunicationIngestionInput, CommunicationParticipantRuntimeSearchInput, ClinicalBundleSearchInput, GrantProfessionalAccessInput, GrantProfessionalAccessResult } from '../resource-operations.js';
|
|
5
|
+
import type { BlockchainArtifactRegistrationInput, CommunicationIngestionInput, CommunicationParticipantRuntimeSearchInput, ClinicalBundleSearchInput, GrantProfessionalAccessInput, GrantProfessionalAccessResult, VitalSignBatchCommunicationFromSearchResponseInput } from '../resource-operations.js';
|
|
6
6
|
/**
|
|
7
7
|
* Professional-oriented facade for runtime actions that belong to the
|
|
8
8
|
* professional actor itself after tenant and employee provisioning have already
|
|
@@ -68,6 +68,16 @@ export declare class ProfessionalSdk {
|
|
|
68
68
|
* Ingests a FHIR `Communication` and waits for indexing.
|
|
69
69
|
*/
|
|
70
70
|
ingestCommunicationAndUpdateIndex(ctx: RouteContext, input: CommunicationIngestionInput): Promise<SubmitAndPollResult>;
|
|
71
|
+
/**
|
|
72
|
+
* Registers one FHIR resource or raw document artifact on blockchain before
|
|
73
|
+
* the artifact is attached to a Communication.
|
|
74
|
+
*/
|
|
75
|
+
registerBlockchainArtifactAndUpdateIndex(ctx: RouteContext, input: BlockchainArtifactRegistrationInput): Promise<SubmitAndPollResult>;
|
|
76
|
+
/**
|
|
77
|
+
* Converts a paginated vital-sign search response into one Communication
|
|
78
|
+
* carrying the selected day-batch artifacts and submits it.
|
|
79
|
+
*/
|
|
80
|
+
submitVitalSignBatchCommunicationFromSearchResponse(ctx: RouteContext, input: VitalSignBatchCommunicationFromSearchResponseInput): Promise<SubmitAndPollResult>;
|
|
71
81
|
/**
|
|
72
82
|
* Searches indexed communication channel records by subject and participant
|
|
73
83
|
* identifiers.
|
|
@@ -80,6 +80,20 @@ export class ProfessionalSdk {
|
|
|
80
80
|
ingestCommunicationAndUpdateIndex(ctx, input) {
|
|
81
81
|
return requireClientMethod(this.client, 'ingestCommunicationAndUpdateIndex')(ctx, input);
|
|
82
82
|
}
|
|
83
|
+
/**
|
|
84
|
+
* Registers one FHIR resource or raw document artifact on blockchain before
|
|
85
|
+
* the artifact is attached to a Communication.
|
|
86
|
+
*/
|
|
87
|
+
registerBlockchainArtifactAndUpdateIndex(ctx, input) {
|
|
88
|
+
return requireClientMethod(this.client, 'registerBlockchainArtifactAndUpdateIndex')(ctx, input);
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Converts a paginated vital-sign search response into one Communication
|
|
92
|
+
* carrying the selected day-batch artifacts and submits it.
|
|
93
|
+
*/
|
|
94
|
+
submitVitalSignBatchCommunicationFromSearchResponse(ctx, input) {
|
|
95
|
+
return requireClientMethod(this.client, 'submitVitalSignBatchCommunicationFromSearchResponse')(ctx, input);
|
|
96
|
+
}
|
|
83
97
|
/**
|
|
84
98
|
* Searches indexed communication channel records by subject and participant
|
|
85
99
|
* identifiers.
|
|
@@ -2,7 +2,7 @@ import type { SubmitAndPollResult } from 'gdc-sdk-core-ts';
|
|
|
2
2
|
import type { ProfileLoadRequest } from 'gdc-sdk-core-ts';
|
|
3
3
|
import type { RouteContext } from './individual-onboarding.js';
|
|
4
4
|
import type { SmartTokenExchangeResult, SmartTokenRequestInput } from './smart-token.js';
|
|
5
|
-
import type { ClinicalBundleSearchInput } from './resource-operations.js';
|
|
5
|
+
import type { BlockchainArtifactRegistrationInput, ClinicalBundleSearchInput } from './resource-operations.js';
|
|
6
6
|
import { type BackendProfessionalProfile, type BackendProfileRuntimeClient } from './backend-profile-runtime.js';
|
|
7
7
|
/**
|
|
8
8
|
* Backend use-case facade for the current professional happy path.
|
|
@@ -33,4 +33,9 @@ export declare class ProfessionalBackendRuntime {
|
|
|
33
33
|
* Reads the latest IPS-oriented bundle through the professional facade.
|
|
34
34
|
*/
|
|
35
35
|
getLatestIps(profile: BackendProfessionalProfile, ctx: RouteContext, input: Omit<ClinicalBundleSearchInput, 'includedTypes'>): Promise<SubmitAndPollResult>;
|
|
36
|
+
/**
|
|
37
|
+
* Registers one FHIR resource or raw artifact on blockchain before it is
|
|
38
|
+
* attached to a communication.
|
|
39
|
+
*/
|
|
40
|
+
registerBlockchainArtifactAndUpdateIndex(profile: BackendProfessionalProfile, ctx: RouteContext, input: BlockchainArtifactRegistrationInput): Promise<SubmitAndPollResult>;
|
|
36
41
|
}
|
|
@@ -38,4 +38,11 @@ export class ProfessionalBackendRuntime {
|
|
|
38
38
|
getLatestIps(profile, ctx, input) {
|
|
39
39
|
return profile.sdk.getLatestIps(ctx, input);
|
|
40
40
|
}
|
|
41
|
+
/**
|
|
42
|
+
* Registers one FHIR resource or raw artifact on blockchain before it is
|
|
43
|
+
* attached to a communication.
|
|
44
|
+
*/
|
|
45
|
+
registerBlockchainArtifactAndUpdateIndex(profile, ctx, input) {
|
|
46
|
+
return profile.sdk.registerBlockchainArtifactAndUpdateIndex(ctx, input);
|
|
47
|
+
}
|
|
41
48
|
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { CommunicationAttachedBundleSession, IndividualBundleVault, buildVitalSignObservationClaims, createSummaryOperationRequestParameters, createSummaryOperationRequestParametersResource, summarizeClinicalBundle, toClinicalResourceExpandedViews, type BuildVitalSignObservationClaimsInput } from 'gdc-common-utils-ts';
|
|
2
|
+
import type { BundleEntry, BundleJsonApi } from 'gdc-common-utils-ts/models/bundle';
|
|
2
3
|
import type { BackendOrganizationControllerProfile, BackendProfessionalProfile } from './backend-profile-runtime.js';
|
|
3
4
|
export type IpsRequestDraft = Readonly<{
|
|
4
5
|
subjectId: string;
|
|
@@ -29,6 +30,17 @@ declare class ProfessionalSubjectIpsWorkspace {
|
|
|
29
30
|
processResponseBundleIps(body: unknown): ProcessedClinicalBundleResponse;
|
|
30
31
|
rememberResponseBundleIps(body: unknown): Promise<IndividualBundleVault>;
|
|
31
32
|
addVitalSign(input: BuildVitalSignObservationClaimsInput): Promise<IndividualBundleVault>;
|
|
33
|
+
buildVitalSignBatchCommunicationFromSearchResponse(searchResponse: unknown, selectedResourceIds?: readonly string[]): import("./resource-operations.js").CommunicationIngestionInput;
|
|
34
|
+
buildBlockchainArtifactBundleFromSearchResponse(searchResponse: unknown, selectedResourceIds?: readonly string[]): Readonly<{
|
|
35
|
+
availableResourceIds: readonly string[];
|
|
36
|
+
anchoredResourceIds: readonly string[];
|
|
37
|
+
unanchoredResourceIds: readonly string[];
|
|
38
|
+
selectedResourceIds: readonly string[];
|
|
39
|
+
missingResourceIds: readonly string[];
|
|
40
|
+
returnedCount: number;
|
|
41
|
+
totalCount: number;
|
|
42
|
+
bundle: BundleJsonApi<BundleEntry>;
|
|
43
|
+
}>;
|
|
32
44
|
get cache(): IndividualBundleVault;
|
|
33
45
|
}
|
|
34
46
|
declare class ProfessionalSubjectWorkspace {
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
// Copyright 2026 Antifraud Services Inc. under the Apache License, Version 2.0.
|
|
2
2
|
import { CommunicationAttachedBundleSession, IndividualBundleVault, VaultMemRepository, buildVitalSignObservationClaims, createConsentAccessEditor, createInvoiceBundleEditor, createSummaryOperationRequestParameters, createSummaryOperationRequestParametersResource, createSummaryOperationRequestReferencePath, readEmployeeSearchResults, summarizeClinicalBundle, summarizeLicenseListRecords, toClinicalResourceExpandedViews, } from 'gdc-common-utils-ts';
|
|
3
|
+
import { buildBlockchainArtifactBundleFromSearchResponse, buildVitalSignBatchCommunicationFromSearchResponse } from './resource-operations.js';
|
|
3
4
|
function normalizeSectionList(sectionList) {
|
|
4
5
|
return Array.from(new Set((sectionList || []).map((item) => String(item || '').trim()).filter(Boolean)));
|
|
5
6
|
}
|
|
@@ -69,6 +70,20 @@ class ProfessionalSubjectIpsWorkspace {
|
|
|
69
70
|
await this.bundleVault.upsertVitalSign(input);
|
|
70
71
|
return this.bundleVault;
|
|
71
72
|
}
|
|
73
|
+
buildVitalSignBatchCommunicationFromSearchResponse(searchResponse, selectedResourceIds) {
|
|
74
|
+
return buildVitalSignBatchCommunicationFromSearchResponse({
|
|
75
|
+
subject: this.subjectId,
|
|
76
|
+
searchResponse,
|
|
77
|
+
selectedResourceIds,
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
buildBlockchainArtifactBundleFromSearchResponse(searchResponse, selectedResourceIds) {
|
|
81
|
+
return buildBlockchainArtifactBundleFromSearchResponse({
|
|
82
|
+
subject: this.subjectId,
|
|
83
|
+
searchResponse,
|
|
84
|
+
selectedResourceIds,
|
|
85
|
+
});
|
|
86
|
+
}
|
|
72
87
|
get cache() {
|
|
73
88
|
return this.bundleVault;
|
|
74
89
|
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { LicenseOfferSearchState, LicenseOrderSearchState } from 'gdc-common-utils-ts/utils/license-commercial-search';
|
|
2
2
|
import type { LicenseListSearchState } from 'gdc-common-utils-ts/utils/license-list-search';
|
|
3
3
|
import type { BundleSearchQuery, CommunicationInput, DateRange, EmployeeSearchValue, IndividualOrganizationLifecycleInput } from 'gdc-sdk-core-ts';
|
|
4
|
+
import type { BundleEntry, BundleJsonApi } from 'gdc-common-utils-ts/models/bundle';
|
|
4
5
|
import type { SubmitAndPollResult } from './orchestration/client-port.js';
|
|
5
6
|
import type { RouteContext } from './individual-onboarding.js';
|
|
6
7
|
export type OrganizationEmployeeCreationInput = {
|
|
@@ -160,6 +161,53 @@ export type CommunicationIngestionInput = {
|
|
|
160
161
|
intervalMs?: number;
|
|
161
162
|
};
|
|
162
163
|
};
|
|
164
|
+
export type BlockchainArtifactRegistrationInput = {
|
|
165
|
+
subject: string;
|
|
166
|
+
resource?: Record<string, unknown>;
|
|
167
|
+
contentDataBase64?: string;
|
|
168
|
+
contentType?: string;
|
|
169
|
+
identifier?: string;
|
|
170
|
+
title?: string;
|
|
171
|
+
description?: string;
|
|
172
|
+
date?: string;
|
|
173
|
+
location?: string;
|
|
174
|
+
language?: string;
|
|
175
|
+
requestThid?: string;
|
|
176
|
+
pollOptions?: {
|
|
177
|
+
timeoutMs?: number;
|
|
178
|
+
intervalMs?: number;
|
|
179
|
+
};
|
|
180
|
+
};
|
|
181
|
+
export type BlockchainArtifactSearchSelectionInput = Readonly<{
|
|
182
|
+
subject: string;
|
|
183
|
+
searchResponse: unknown;
|
|
184
|
+
selectedResourceIds?: readonly string[];
|
|
185
|
+
}>;
|
|
186
|
+
export type BlockchainArtifactSearchSelectionResult = Readonly<{
|
|
187
|
+
availableResourceIds: readonly string[];
|
|
188
|
+
anchoredResourceIds: readonly string[];
|
|
189
|
+
unanchoredResourceIds: readonly string[];
|
|
190
|
+
selectedResourceIds: readonly string[];
|
|
191
|
+
missingResourceIds: readonly string[];
|
|
192
|
+
returnedCount: number;
|
|
193
|
+
totalCount: number;
|
|
194
|
+
bundle: BundleJsonApi<BundleEntry>;
|
|
195
|
+
}>;
|
|
196
|
+
export type VitalSignBatchCommunicationFromSearchResponseInput = Readonly<{
|
|
197
|
+
subject: string;
|
|
198
|
+
searchResponse: unknown;
|
|
199
|
+
selectedResourceIds?: readonly string[];
|
|
200
|
+
sender?: string;
|
|
201
|
+
recipient?: string | string[];
|
|
202
|
+
sent?: string;
|
|
203
|
+
status?: string;
|
|
204
|
+
noteText?: string;
|
|
205
|
+
requestThid?: string;
|
|
206
|
+
pollOptions?: {
|
|
207
|
+
timeoutMs?: number;
|
|
208
|
+
intervalMs?: number;
|
|
209
|
+
};
|
|
210
|
+
}>;
|
|
163
211
|
/**
|
|
164
212
|
* Runtime participant query for `Communication/_search`.
|
|
165
213
|
*
|
|
@@ -532,11 +580,37 @@ export declare function searchClinicalBundleWithDeps(routeCtx: RouteContext, inp
|
|
|
532
580
|
intervalMs?: number;
|
|
533
581
|
}) => Promise<SubmitAndPollResult>;
|
|
534
582
|
}): Promise<SubmitAndPollResult>;
|
|
583
|
+
/**
|
|
584
|
+
* Builds one Communication-ready ingestion payload from a paginated search
|
|
585
|
+
* response that already selected the day batches to be anchored.
|
|
586
|
+
*
|
|
587
|
+
* The search response is normalized into a `Bundle.type=batch` attachment,
|
|
588
|
+
* and the resulting `Communication` is ready for `ingestCommunication...`.
|
|
589
|
+
*/
|
|
590
|
+
export declare function buildVitalSignBatchCommunicationFromSearchResponse(input: VitalSignBatchCommunicationFromSearchResponseInput): CommunicationIngestionInput;
|
|
591
|
+
/**
|
|
592
|
+
* Builds one blockchain-ready batch bundle from a paginated search response.
|
|
593
|
+
*
|
|
594
|
+
* The helper keeps the original search result as the source of truth and only
|
|
595
|
+
* projects the selected `resource.id` values into a `Bundle.type=batch`
|
|
596
|
+
* payload for subsequent communication/registration.
|
|
597
|
+
*/
|
|
598
|
+
export declare function buildBlockchainArtifactBundleFromSearchResponse(input: BlockchainArtifactSearchSelectionInput): BlockchainArtifactSearchSelectionResult;
|
|
535
599
|
export declare function searchLatestIpsWithDeps(routeCtx: RouteContext, input: Omit<ClinicalBundleSearchInput, 'includedTypes' | 'section'> & {
|
|
536
600
|
section?: string | string[];
|
|
537
601
|
}, deps: {
|
|
538
602
|
searchClinicalBundle: (routeCtx: RouteContext, input: ClinicalBundleSearchInput) => Promise<SubmitAndPollResult>;
|
|
539
603
|
}): Promise<SubmitAndPollResult>;
|
|
604
|
+
export declare function registerBlockchainArtifactAndUpdateIndexWithDeps(routeCtx: RouteContext, input: BlockchainArtifactRegistrationInput, deps: {
|
|
605
|
+
individualDocumentReferenceBatchPath: (ctx: RouteContext) => string;
|
|
606
|
+
individualDocumentReferencePollPath: (ctx: RouteContext) => string;
|
|
607
|
+
submitAndPoll: (submitPath: string, pollPath: string, payload: {
|
|
608
|
+
thid?: string;
|
|
609
|
+
} & Record<string, unknown>, pollOptions?: {
|
|
610
|
+
timeoutMs?: number;
|
|
611
|
+
intervalMs?: number;
|
|
612
|
+
}) => Promise<SubmitAndPollResult>;
|
|
613
|
+
}): Promise<SubmitAndPollResult>;
|
|
540
614
|
export declare function grantProfessionalAccessWithDeps(routeCtx: RouteContext, input: GrantProfessionalAccessInput, deps: {
|
|
541
615
|
buildConsentClaimsWithCid: (input: GrantProfessionalAccessInput, options?: {
|
|
542
616
|
consentIdentifierFactory: () => string;
|
|
@@ -2,7 +2,8 @@
|
|
|
2
2
|
import { HealthcareBasicSections, ResourceTypesFhirR4 } from 'gdc-common-utils-ts/constants';
|
|
3
3
|
import { Format } from 'gdc-common-utils-ts/constants/Schemas';
|
|
4
4
|
import { RelatedPersonClaim } from 'gdc-common-utils-ts/models/interoperable-claims/related-person-claims';
|
|
5
|
-
import { buildCommunicationParticipantSearchBundle, createInteroperableResourceOperationEditor, IndividualOrganizationLifecycleEditor, LicenseOfferSearchEditor, LicenseOrderSearchEditor, InteroperableLifecycleStatuses, LicenseListSearchEditor, } from 'gdc-common-utils-ts';
|
|
5
|
+
import { buildCommunicationParticipantSearchBundle, buildBlockchainArtifactDocumentReference, BundleQuery, createInteroperableResourceOperationEditor, IndividualOrganizationLifecycleEditor, LicenseOfferSearchEditor, LicenseOrderSearchEditor, InteroperableLifecycleStatuses, LicenseListSearchEditor, } from 'gdc-common-utils-ts';
|
|
6
|
+
import { addFhirResourceToCommunication, createCommunicationResource, } from 'gdc-sdk-core-ts';
|
|
6
7
|
import { GwCoreLifecycleRequestMethod, GwCoreLifecycleRequestType, GwCoreLifecycleTodo, } from './constants/lifecycle.js';
|
|
7
8
|
import { buildEmployeeBatchEntry, buildEmployeeSearchBundle, ConsentClaims, } from 'gdc-sdk-core-ts';
|
|
8
9
|
export async function createOrganizationEmployeeWithDeps(routeCtx, input, options, deps) {
|
|
@@ -323,6 +324,117 @@ export async function searchClinicalBundleWithDeps(routeCtx, input, deps) {
|
|
|
323
324
|
};
|
|
324
325
|
return deps.submitAndPoll(deps.bundleSearchPath(routeCtx), deps.bundleSearchPollPath(routeCtx), payload, input.pollOptions);
|
|
325
326
|
}
|
|
327
|
+
/**
|
|
328
|
+
* Builds one Communication-ready ingestion payload from a paginated search
|
|
329
|
+
* response that already selected the day batches to be anchored.
|
|
330
|
+
*
|
|
331
|
+
* The search response is normalized into a `Bundle.type=batch` attachment,
|
|
332
|
+
* and the resulting `Communication` is ready for `ingestCommunication...`.
|
|
333
|
+
*/
|
|
334
|
+
export function buildVitalSignBatchCommunicationFromSearchResponse(input) {
|
|
335
|
+
const selection = buildBlockchainArtifactBundleFromSearchResponse({
|
|
336
|
+
subject: input.subject,
|
|
337
|
+
searchResponse: input.searchResponse,
|
|
338
|
+
selectedResourceIds: input.selectedResourceIds,
|
|
339
|
+
});
|
|
340
|
+
const communication = addFhirResourceToCommunication(createCommunicationResource({
|
|
341
|
+
subject: input.subject,
|
|
342
|
+
sender: input.sender,
|
|
343
|
+
recipient: input.recipient,
|
|
344
|
+
sent: input.sent,
|
|
345
|
+
status: input.status || 'completed',
|
|
346
|
+
noteText: input.noteText || `Selected ${selection.selectedResourceIds.length} vital-sign batch item(s) for blockchain anchoring.`,
|
|
347
|
+
claims: {
|
|
348
|
+
'Communication.vital-sign-batch-selection.subject': input.subject,
|
|
349
|
+
'Communication.vital-sign-batch-selection.selected-count': selection.selectedResourceIds.length,
|
|
350
|
+
'Communication.vital-sign-batch-selection.unanchored-count': selection.unanchoredResourceIds.length,
|
|
351
|
+
'Communication.vital-sign-batch-selection.selected-ids': selection.selectedResourceIds.join(','),
|
|
352
|
+
'Communication.vital-sign-batch-selection.missing-ids': selection.missingResourceIds.join(','),
|
|
353
|
+
},
|
|
354
|
+
}), selection.bundle, {
|
|
355
|
+
attachmentContentType: 'application/fhir+json',
|
|
356
|
+
attachmentTitle: 'vital-sign-batch-selection.json',
|
|
357
|
+
});
|
|
358
|
+
return {
|
|
359
|
+
communicationPayload: communication,
|
|
360
|
+
pathFormatSegment: 'org.hl7.fhir.r4',
|
|
361
|
+
pollOptions: input.pollOptions,
|
|
362
|
+
autoConvertClaimsToFhirR4: false,
|
|
363
|
+
};
|
|
364
|
+
}
|
|
365
|
+
/**
|
|
366
|
+
* Builds one blockchain-ready batch bundle from a paginated search response.
|
|
367
|
+
*
|
|
368
|
+
* The helper keeps the original search result as the source of truth and only
|
|
369
|
+
* projects the selected `resource.id` values into a `Bundle.type=batch`
|
|
370
|
+
* payload for subsequent communication/registration.
|
|
371
|
+
*/
|
|
372
|
+
export function buildBlockchainArtifactBundleFromSearchResponse(input) {
|
|
373
|
+
const bundle = normalizeBundleLike(input.searchResponse);
|
|
374
|
+
const query = new BundleQuery(bundle);
|
|
375
|
+
const availableResourceIds = query.getResourceIds();
|
|
376
|
+
const availableEntries = query.getResourceEntriesByIds(availableResourceIds);
|
|
377
|
+
const anchoredResourceIds = availableEntries
|
|
378
|
+
.filter((entry) => hasAuditTxId(entry))
|
|
379
|
+
.map((entry, index) => resolveBundleEntryStableId(entry, index));
|
|
380
|
+
const unanchoredResourceIds = availableResourceIds.filter((resourceId) => !anchoredResourceIds.includes(resourceId));
|
|
381
|
+
const requestedResourceIds = normalizeIdList(input.selectedResourceIds);
|
|
382
|
+
const selectedResourceIds = requestedResourceIds.length > 0
|
|
383
|
+
? requestedResourceIds.filter((resourceId) => availableResourceIds.includes(resourceId))
|
|
384
|
+
: unanchoredResourceIds;
|
|
385
|
+
const missingResourceIds = requestedResourceIds.filter((resourceId) => !availableResourceIds.includes(resourceId));
|
|
386
|
+
if (requestedResourceIds.length > 0 && selectedResourceIds.length === 0) {
|
|
387
|
+
throw new Error('buildBlockchainArtifactBundleFromSearchResponse could not match any selected resource ids.');
|
|
388
|
+
}
|
|
389
|
+
const selectedEntries = query.getResourceEntriesByIds(selectedResourceIds);
|
|
390
|
+
const artifactEntries = selectedEntries.map((entry, index) => {
|
|
391
|
+
const resource = entry.resource && typeof entry.resource === 'object' ? entry.resource : undefined;
|
|
392
|
+
if (!resource) {
|
|
393
|
+
throw new Error(`buildBlockchainArtifactBundleFromSearchResponse requires resource data for selected entry at index ${index}.`);
|
|
394
|
+
}
|
|
395
|
+
const logicalIdentifier = asTrimmedString(resource.id || entry.id || entry.fullUrl || selectedResourceIds[index]);
|
|
396
|
+
const artifact = buildBlockchainArtifactDocumentReference({
|
|
397
|
+
subject: input.subject,
|
|
398
|
+
resource,
|
|
399
|
+
identifier: logicalIdentifier || undefined,
|
|
400
|
+
title: `${asTrimmedString(resource.resourceType) || 'resource'}.json`,
|
|
401
|
+
});
|
|
402
|
+
return {
|
|
403
|
+
type: 'DocumentReference',
|
|
404
|
+
meta: { claims: artifact.documentReference.meta?.claims || {} },
|
|
405
|
+
resource: artifact.documentReference,
|
|
406
|
+
request: {
|
|
407
|
+
method: 'POST',
|
|
408
|
+
url: 'individual/org.hl7.fhir.r4/DocumentReference/_batch',
|
|
409
|
+
},
|
|
410
|
+
};
|
|
411
|
+
});
|
|
412
|
+
return {
|
|
413
|
+
availableResourceIds,
|
|
414
|
+
anchoredResourceIds,
|
|
415
|
+
unanchoredResourceIds,
|
|
416
|
+
selectedResourceIds,
|
|
417
|
+
missingResourceIds,
|
|
418
|
+
returnedCount: query.getResourceIds().length,
|
|
419
|
+
totalCount: typeof bundle.total === 'number'
|
|
420
|
+
? Number(bundle.total)
|
|
421
|
+
: query.getResourceIds().length,
|
|
422
|
+
bundle: {
|
|
423
|
+
resourceType: 'Bundle',
|
|
424
|
+
type: 'batch',
|
|
425
|
+
meta: {
|
|
426
|
+
claims: {
|
|
427
|
+
'BlockchainArtifactSelection.subject': input.subject,
|
|
428
|
+
'BlockchainArtifactSelection.availableCount': availableResourceIds.length,
|
|
429
|
+
'BlockchainArtifactSelection.selectedCount': selectedResourceIds.length,
|
|
430
|
+
'BlockchainArtifactSelection.missingCount': missingResourceIds.length,
|
|
431
|
+
'BlockchainArtifactSelection.selectedResourceIds': selectedResourceIds.join(','),
|
|
432
|
+
},
|
|
433
|
+
},
|
|
434
|
+
data: artifactEntries,
|
|
435
|
+
},
|
|
436
|
+
};
|
|
437
|
+
}
|
|
326
438
|
export async function searchLatestIpsWithDeps(routeCtx, input, deps) {
|
|
327
439
|
return deps.searchClinicalBundle(routeCtx, {
|
|
328
440
|
...input,
|
|
@@ -330,6 +442,78 @@ export async function searchLatestIpsWithDeps(routeCtx, input, deps) {
|
|
|
330
442
|
includedTypes: ['Composition', 'DocumentReference'],
|
|
331
443
|
});
|
|
332
444
|
}
|
|
445
|
+
export async function registerBlockchainArtifactAndUpdateIndexWithDeps(routeCtx, input, deps) {
|
|
446
|
+
const artifact = buildBlockchainArtifactDocumentReference({
|
|
447
|
+
subject: input.subject,
|
|
448
|
+
resource: input.resource,
|
|
449
|
+
contentDataBase64: input.contentDataBase64,
|
|
450
|
+
contentType: input.contentType,
|
|
451
|
+
identifier: input.identifier,
|
|
452
|
+
title: input.title,
|
|
453
|
+
description: input.description,
|
|
454
|
+
date: input.date,
|
|
455
|
+
location: input.location,
|
|
456
|
+
language: input.language,
|
|
457
|
+
});
|
|
458
|
+
const payload = {
|
|
459
|
+
thid: input.requestThid || `blockchain-artifact-${createRuntimeUuid()}`,
|
|
460
|
+
body: {
|
|
461
|
+
resourceType: 'Bundle',
|
|
462
|
+
type: 'batch',
|
|
463
|
+
data: [{
|
|
464
|
+
type: 'DocumentReference',
|
|
465
|
+
meta: { claims: artifact.documentReference.meta?.claims || {} },
|
|
466
|
+
resource: artifact.documentReference,
|
|
467
|
+
request: {
|
|
468
|
+
method: 'POST',
|
|
469
|
+
url: 'individual/org.hl7.fhir.r4/DocumentReference/_batch',
|
|
470
|
+
},
|
|
471
|
+
}],
|
|
472
|
+
},
|
|
473
|
+
};
|
|
474
|
+
return deps.submitAndPoll(deps.individualDocumentReferenceBatchPath(routeCtx), deps.individualDocumentReferencePollPath(routeCtx), payload, input.pollOptions);
|
|
475
|
+
}
|
|
476
|
+
function normalizeBundleLike(value) {
|
|
477
|
+
const root = value && typeof value === 'object' ? value : {};
|
|
478
|
+
const body = root.body && typeof root.body === 'object' ? root.body : root;
|
|
479
|
+
const resourceType = asTrimmedString(body.resourceType) || 'Bundle';
|
|
480
|
+
const type = asTrimmedString(body.type) || 'batch';
|
|
481
|
+
const data = Array.isArray(body.data)
|
|
482
|
+
? body.data
|
|
483
|
+
: (Array.isArray(body.entry) ? body.entry : []);
|
|
484
|
+
return {
|
|
485
|
+
...(typeof body.id === 'string' ? { id: asTrimmedString(body.id) || undefined } : {}),
|
|
486
|
+
resourceType: resourceType,
|
|
487
|
+
type,
|
|
488
|
+
total: typeof body.total === 'number' ? body.total : undefined,
|
|
489
|
+
meta: body.meta && typeof body.meta === 'object' ? body.meta : undefined,
|
|
490
|
+
data: data,
|
|
491
|
+
};
|
|
492
|
+
}
|
|
493
|
+
function normalizeIdList(value) {
|
|
494
|
+
return [...(value || [])]
|
|
495
|
+
.map((item) => asTrimmedString(item))
|
|
496
|
+
.filter(Boolean);
|
|
497
|
+
}
|
|
498
|
+
function asTrimmedString(value) {
|
|
499
|
+
if (value === undefined || value === null) {
|
|
500
|
+
return '';
|
|
501
|
+
}
|
|
502
|
+
return String(value).trim();
|
|
503
|
+
}
|
|
504
|
+
function resolveBundleEntryStableId(entry, index) {
|
|
505
|
+
const resource = entry.resource && typeof entry.resource === 'object' ? entry.resource : {};
|
|
506
|
+
return asTrimmedString(resource.id || entry.id || entry.fullUrl || `entry-${index}`);
|
|
507
|
+
}
|
|
508
|
+
function hasAuditTxId(entry) {
|
|
509
|
+
const entryAudit = entry && typeof entry === 'object' ? entry.audit : undefined;
|
|
510
|
+
const entryMeta = entry && typeof entry === 'object' ? entry.meta : undefined;
|
|
511
|
+
const resource = entry.resource && typeof entry.resource === 'object' ? entry.resource : {};
|
|
512
|
+
const resourceMeta = resource.meta && typeof resource.meta === 'object' ? resource.meta : {};
|
|
513
|
+
const audit = [entryAudit, entryMeta && typeof entryMeta === 'object' ? entryMeta.audit : undefined, resourceMeta.audit]
|
|
514
|
+
.find((candidate) => candidate && typeof candidate === 'object');
|
|
515
|
+
return Boolean(asTrimmedString(audit?.txId));
|
|
516
|
+
}
|
|
333
517
|
export async function grantProfessionalAccessWithDeps(routeCtx, input, deps) {
|
|
334
518
|
const built = deps.buildConsentClaimsWithCid({
|
|
335
519
|
subjectDid: input.subjectDid,
|
|
@@ -68,6 +68,8 @@ export declare class RuntimeClientPaths {
|
|
|
68
68
|
individualCommunicationPollPath(ctx: RouteContext, format: 'org.hl7.fhir.api' | 'org.hl7.fhir.r4'): string;
|
|
69
69
|
individualCommunicationSearchPath(ctx: RouteContext): string;
|
|
70
70
|
individualCommunicationSearchPollPath(ctx: RouteContext): string;
|
|
71
|
+
individualDocumentReferenceBatchPath(ctx: RouteContext): string;
|
|
72
|
+
individualDocumentReferencePollPath(ctx: RouteContext): string;
|
|
71
73
|
individualBundleSearchPath(ctx: RouteContext): string;
|
|
72
74
|
individualBundleSearchPollPath(ctx: RouteContext): string;
|
|
73
75
|
identityTokenExchangePath(ctx: RouteContext): string;
|
|
@@ -82,6 +82,8 @@ export class RuntimeClientPaths {
|
|
|
82
82
|
individualCommunicationPollPath(ctx, format) { return this.v1Path(ctx, 'individual', format, 'Communication', '_batch-response'); }
|
|
83
83
|
individualCommunicationSearchPath(ctx) { return this.v1Path(ctx, 'individual', 'org.hl7.fhir.r4', 'Communication', '_search'); }
|
|
84
84
|
individualCommunicationSearchPollPath(ctx) { return this.v1Path(ctx, 'individual', 'org.hl7.fhir.r4', 'Communication', '_search-response'); }
|
|
85
|
+
individualDocumentReferenceBatchPath(ctx) { return this.v1Path(ctx, 'individual', 'org.hl7.fhir.r4', 'DocumentReference', '_batch'); }
|
|
86
|
+
individualDocumentReferencePollPath(ctx) { return this.v1Path(ctx, 'individual', 'org.hl7.fhir.r4', 'DocumentReference', '_batch-response'); }
|
|
85
87
|
individualBundleSearchPath(ctx) { return this.v1Path(ctx, 'individual', 'org.hl7.fhir.r4', 'Bundle', '_search'); }
|
|
86
88
|
individualBundleSearchPollPath(ctx) { return this.v1Path(ctx, 'individual', 'org.hl7.fhir.r4', 'Bundle', '_search-response'); }
|
|
87
89
|
identityTokenExchangePath(ctx) { return buildIdentityTokenExchangePath(ctx); }
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
// Copyright 2026 Antifraud Services Inc. under the Apache License, Version 2.0.
|
|
2
|
+
import { extractTenantIdFromHostedDidWeb } from 'gdc-common-utils-ts';
|
|
3
|
+
let warnedServiceProviderDidRouteTenant = false;
|
|
2
4
|
export function requireRouteContext(ctx, defaultCtx) {
|
|
3
5
|
const resolved = ctx || defaultCtx;
|
|
4
6
|
const tenantId = String(resolved?.tenantId || '').trim();
|
|
@@ -10,7 +12,22 @@ export function requireRouteContext(ctx, defaultCtx) {
|
|
|
10
12
|
return { tenantId, jurisdiction, sector };
|
|
11
13
|
}
|
|
12
14
|
export function routeCtxFromInput(input, defaultCtx) {
|
|
13
|
-
const
|
|
15
|
+
const explicitTenantId = String(input.tenantId || '').trim();
|
|
16
|
+
const serviceProviderDid = String(input.serviceProviderDid || '').trim();
|
|
17
|
+
let tenantId = explicitTenantId;
|
|
18
|
+
if (!tenantId && serviceProviderDid) {
|
|
19
|
+
const extractedTenantId = extractTenantIdFromHostedDidWeb(serviceProviderDid);
|
|
20
|
+
if (extractedTenantId) {
|
|
21
|
+
if (!warnedServiceProviderDidRouteTenant) {
|
|
22
|
+
warnedServiceProviderDidRouteTenant = true;
|
|
23
|
+
console.warn(`[gdc-sdk-node-ts] serviceProviderDid is a compatibility alias for route tenant ids. Pass tenantId instead. Extracted tenantId='${extractedTenantId}' from hosted did:web '${serviceProviderDid}'.`);
|
|
24
|
+
}
|
|
25
|
+
tenantId = extractedTenantId;
|
|
26
|
+
}
|
|
27
|
+
else {
|
|
28
|
+
tenantId = serviceProviderDid;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
14
31
|
return requireRouteContext(tenantId && input.jurisdiction && input.sector
|
|
15
32
|
? { tenantId, jurisdiction: input.jurisdiction, sector: input.sector }
|
|
16
33
|
: undefined, defaultCtx);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "gdc-sdk-node-ts",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.2.2",
|
|
4
4
|
"description": "Next-generation Node runtime package for the GDC SDK family",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"author": "Antifraud Services Inc.",
|
|
@@ -35,8 +35,8 @@
|
|
|
35
35
|
"test:e2e:live-gw:clean": "bash ./scripts/run-live-gw-clean.sh"
|
|
36
36
|
},
|
|
37
37
|
"dependencies": {
|
|
38
|
-
"gdc-common-utils-ts": "^2.
|
|
39
|
-
"gdc-sdk-core-ts": "~2.1
|
|
38
|
+
"gdc-common-utils-ts": "^2.2.2",
|
|
39
|
+
"gdc-sdk-core-ts": "~2.2.1"
|
|
40
40
|
},
|
|
41
41
|
"devDependencies": {
|
|
42
42
|
"@types/node": "^20.14.10",
|