gdc-sdk-node-ts 2.4.35 → 2.4.36

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.
@@ -10,6 +10,9 @@ export declare function assertDigitalTwinSubjectId(value: unknown): asserts valu
10
10
  /** Search parameters added by the digital-twin Composition profile. */
11
11
  export declare const DigitalTwinSearchParameter: Readonly<{
12
12
  Section: "section";
13
+ DateFrom: "date-from";
14
+ DateTo: "date-to";
15
+ Text: "text";
13
16
  MetaTag: "Composition.meta-tag";
14
17
  }>;
15
18
  export type DigitalTwinSearchInput = {
@@ -18,6 +21,15 @@ export type DigitalTwinSearchInput = {
18
21
  thid?: string;
19
22
  format?: DigitalTwinFhirFormat;
20
23
  resourceType?: string;
24
+ /** One or more IPS section tokens. Basic search uses OR across sections. */
25
+ sections?: readonly string[];
26
+ /** Inclusive clinical-event lower bound as ISO date or dateTime. */
27
+ dateFrom?: string;
28
+ /** Inclusive upper bound. When omitted, GW resolves its current time. */
29
+ dateTo?: string;
30
+ /** Case- and accent-insensitive text matched against GW's private derived index. */
31
+ text?: string;
32
+ /** Advanced/compatibility filters. Do not combine with basic-search fields. */
21
33
  filters?: Readonly<Record<string, string | readonly string[] | undefined>>;
22
34
  pollOptions?: PollOptions;
23
35
  };
@@ -16,6 +16,9 @@ export function assertDigitalTwinSubjectId(value) {
16
16
  /** Search parameters added by the digital-twin Composition profile. */
17
17
  export const DigitalTwinSearchParameter = Object.freeze({
18
18
  Section: 'section',
19
+ DateFrom: 'date-from',
20
+ DateTo: 'date-to',
21
+ Text: 'text',
19
22
  MetaTag: 'Composition.meta-tag',
20
23
  });
21
24
  /**
@@ -132,10 +135,42 @@ export async function searchDigitalTwinsWithDeps(ctx, input, deps) {
132
135
  const resourceType = String(input.resourceType || 'Composition').trim();
133
136
  if (!resourceType)
134
137
  throw new Error('Digital twin resourceType is required.');
135
- const parameters = Object.entries(input.filters || {}).flatMap(([name, value]) => {
138
+ const usesBasicSearch = Boolean(input.sections || input.dateFrom || input.dateTo || input.text);
139
+ if (usesBasicSearch && Object.keys(input.filters || {}).length > 0) {
140
+ throw new Error('Digital twin basic search cannot be combined with advanced filters.');
141
+ }
142
+ const sections = (input.sections || []).map((value) => String(value || '').trim()).filter(Boolean);
143
+ const dateFrom = String(input.dateFrom || '').trim();
144
+ const dateTo = String(input.dateTo || '').trim();
145
+ const searchText = String(input.text || '').trim();
146
+ if (usesBasicSearch) {
147
+ if (sections.length === 0)
148
+ throw new Error('Digital twin basic search requires at least one section.');
149
+ if (!dateFrom)
150
+ throw new Error('Digital twin basic search requires dateFrom.');
151
+ if (!searchText)
152
+ throw new Error('Digital twin basic search requires text.');
153
+ const fromMs = Date.parse(dateFrom);
154
+ const toMs = dateTo ? Date.parse(dateTo) : undefined;
155
+ if (Number.isNaN(fromMs))
156
+ throw new Error('Digital twin basic search dateFrom must be an ISO date or dateTime.');
157
+ if (dateTo && Number.isNaN(toMs))
158
+ throw new Error('Digital twin basic search dateTo must be an ISO date or dateTime.');
159
+ if (toMs !== undefined && toMs < fromMs)
160
+ throw new Error('Digital twin basic search dateTo must be on or after dateFrom.');
161
+ }
162
+ const advancedParameters = Object.entries(input.filters || {}).flatMap(([name, value]) => {
136
163
  const values = Array.isArray(value) ? value : value === undefined ? [] : [value];
137
164
  return values.map((item) => ({ name, valueString: String(item) }));
138
165
  });
166
+ const parameters = usesBasicSearch
167
+ ? [
168
+ ...sections.map((section) => ({ name: DigitalTwinSearchParameter.Section, valueString: section })),
169
+ { name: DigitalTwinSearchParameter.DateFrom, valueDate: dateFrom },
170
+ ...(dateTo ? [{ name: DigitalTwinSearchParameter.DateTo, valueDate: dateTo }] : []),
171
+ { name: DigitalTwinSearchParameter.Text, valueString: searchText },
172
+ ]
173
+ : advancedParameters;
139
174
  const thid = String(input.thid || randomUUID());
140
175
  const body = format === 'org.hl7.fhir.api'
141
176
  ? {
@@ -145,7 +180,7 @@ export async function searchDigitalTwinsWithDeps(ctx, input, deps) {
145
180
  meta: {
146
181
  claims: Object.fromEntries([
147
182
  ['@context', format],
148
- ...parameters.map((parameter) => [parameter.name, parameter.valueString]),
183
+ ...parameters.map((parameter) => [parameter.name, parameter.valueString || parameter.valueDate || '']),
149
184
  ]),
150
185
  },
151
186
  }],
@@ -1,6 +1,6 @@
1
1
  import type { SubmitAndPollResult } from 'gdc-sdk-core-ts';
2
2
  import type { FamilyOrganizationSummary } from 'gdc-common-utils-ts/utils/family-organization-summary';
3
- import type { IndividualOrganizationConfirmOrderInput, RouteContext } from './individual-onboarding.js';
3
+ import type { IndividualOrganizationConfirmOrderInput, IndividualOrganizationOrderResult, RouteContext } from './individual-onboarding.js';
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';
@@ -45,7 +45,7 @@ export declare class IndividualControllerBackendRuntime {
45
45
  /**
46
46
  * Confirms the order returned by the individual bootstrap flow.
47
47
  */
48
- confirmIndividualOrganizationOrder(profile: BackendIndividualControllerProfile, input: IndividualOrganizationConfirmOrderInput): Promise<SubmitAndPollResult>;
48
+ confirmIndividualOrganizationOrder(profile: BackendIndividualControllerProfile, input: IndividualOrganizationConfirmOrderInput): Promise<IndividualOrganizationOrderResult>;
49
49
  /**
50
50
  * Reads the authoritative subject document through the canonical
51
51
  * `Communication -> Subject/$summary -> FHIR Parameters` lifecycle.
@@ -21,6 +21,13 @@ export type IndividualOrganizationConfirmOrderInput = {
21
21
  timeoutSeconds?: number;
22
22
  intervalSeconds?: number;
23
23
  };
24
+ /**
25
+ * Terminal individual Order result with the opaque code required by the
26
+ * subsequent managed-wallet activation and DCR flow.
27
+ */
28
+ export type IndividualOrganizationOrderResult = SubmitAndPollResult & Readonly<{
29
+ activationCode: string;
30
+ }>;
24
31
  type ConfirmIndividualOrganizationOrderDeps = {
25
32
  input: IndividualOrganizationConfirmOrderInput;
26
33
  routeCtx: RouteContext;
@@ -32,5 +39,11 @@ type ConfirmIndividualOrganizationOrderDeps = {
32
39
  thid?: string;
33
40
  } & Record<string, unknown>, options?: PollOptions) => Promise<SubmitAndPollResult>;
34
41
  };
35
- export declare function confirmIndividualOrganizationOrderWithDeps(deps: ConfirmIndividualOrganizationOrderDeps): Promise<SubmitAndPollResult>;
42
+ export declare function confirmIndividualOrganizationOrderWithDeps(deps: ConfirmIndividualOrganizationOrderDeps): Promise<IndividualOrganizationOrderResult>;
43
+ /**
44
+ * Reads the opaque controller activation code from a completed individual
45
+ * Order. Integrators should consume `result.activationCode` instead of calling
46
+ * this reader directly; it remains public for response-adapter compatibility.
47
+ */
48
+ export declare function readIndividualOrganizationActivationCode(responseBody: unknown): string | undefined;
36
49
  export {};
@@ -1,4 +1,5 @@
1
1
  // Copyright 2026 Antifraud Services Inc. under the Apache License, Version 2.0.
2
+ import { extractPrimaryClaims } from 'gdc-common-utils-ts';
2
3
  import { resolvePollOptionsFromSeconds } from './poll-options.js';
3
4
  export async function confirmIndividualOrganizationOrderWithDeps(deps) {
4
5
  /**
@@ -35,7 +36,21 @@ export async function confirmIndividualOrganizationOrderWithDeps(deps) {
35
36
  timeoutMs: deps.defaultTimeoutMs,
36
37
  intervalMs: deps.defaultIntervalMs,
37
38
  });
38
- return deps.submitAndPoll(deps.individualFamilyOrderBatchPath(deps.routeCtx), deps.individualFamilyOrderPollPath(deps.routeCtx), payload, pollOptions);
39
+ const order = await deps.submitAndPoll(deps.individualFamilyOrderBatchPath(deps.routeCtx), deps.individualFamilyOrderPollPath(deps.routeCtx), payload, pollOptions);
40
+ const activationCode = readIndividualOrganizationActivationCode(order.poll.body);
41
+ if (!activationCode) {
42
+ throw new Error('confirmIndividualOrganizationOrder failed: missing controller activation code in GW Order response.');
43
+ }
44
+ return { ...order, activationCode };
45
+ }
46
+ /**
47
+ * Reads the opaque controller activation code from a completed individual
48
+ * Order. Integrators should consume `result.activationCode` instead of calling
49
+ * this reader directly; it remains public for response-adapter compatibility.
50
+ */
51
+ export function readIndividualOrganizationActivationCode(responseBody) {
52
+ const claims = extractPrimaryClaims(responseBody);
53
+ return String(claims['org.schema.IndividualProduct.serialNumber'] || '').trim() || undefined;
39
54
  }
40
55
  function createRuntimeUuid() {
41
56
  const fromCrypto = globalThis.crypto?.randomUUID?.();
@@ -5,7 +5,7 @@ import { type ResolvedAppInfo, type CommunicationClinicalFormatRenderers, type S
5
5
  import { type HostRouteContext, type HostedTenantLifecycleInput } from './host-onboarding.js';
6
6
  import type { HostedTenantDescendantKind } from './host-onboarding.js';
7
7
  import type { NodeLegalOrganizationVerificationTransactionInput, NodeOrganizationDidBindingInput, NodeOrganizationActivationInput } from './orchestration/client-port.js';
8
- import { type IndividualOrganizationConfirmOrderInput, type RouteContext } from './individual-onboarding.js';
8
+ import { type IndividualOrganizationConfirmOrderInput, type IndividualOrganizationOrderResult, type RouteContext } from './individual-onboarding.js';
9
9
  import { type EnsureFamilyOrganizationRegistrationInput } from './family-organization-registration.js';
10
10
  import { type FamilyOrganizationSearchInput } from './family-organization-search.js';
11
11
  import { type SmartTokenRequestInput } from './smart-token.js';
@@ -376,7 +376,7 @@ export declare class HttpRuntimeClient implements NodeRuntimeClient {
376
376
  /**
377
377
  * Confirms the order returned by `startIndividualOrganization(...)`.
378
378
  */
379
- confirmIndividualOrganizationOrder(input: IndividualOrganizationConfirmOrderInput): Promise<SubmitAndPollResult>;
379
+ confirmIndividualOrganizationOrder(input: IndividualOrganizationConfirmOrderInput): Promise<IndividualOrganizationOrderResult>;
380
380
  /**
381
381
  * Disables a hosted individual/family organization without releasing licenses.
382
382
  *
@@ -9,7 +9,7 @@ import type { EmployeeDeviceActivationResult, EmployeeDeviceActivationRequestInp
9
9
  import type { OrganizationEmployeeProvisioningInput, OrganizationEmployeeProvisioningResult } from '../organization-employee-lifecycle.js';
10
10
  import type { OrganizationEmployeeLifecycleRecord } from 'gdc-common-utils-ts/models/organization-employee-lifecycle';
11
11
  import type { HostRouteContext, HostedTenantLifecycleInput, LegalOrganizationOrderInput } from '../host-onboarding.js';
12
- import type { IndividualOrganizationConfirmOrderInput, RouteContext } from '../individual-onboarding.js';
12
+ import type { IndividualOrganizationConfirmOrderInput, IndividualOrganizationOrderResult, RouteContext } from '../individual-onboarding.js';
13
13
  import type { IndividualOrganizationBootstrapInput, IndividualOrganizationStartResult } from '../individual-start.js';
14
14
  import type { FamilyOrganizationSearchInput } from '../family-organization-search.js';
15
15
  import type { FhirR5SubscriptionTopic } from 'gdc-common-utils-ts/models/fhir-r5-subscription';
@@ -106,7 +106,7 @@ export type RuntimeClient = {
106
106
  startIndividualOrganization?: (input: IndividualOrganizationBootstrapInput) => Promise<IndividualOrganizationStartResult>;
107
107
  searchFamilyOrganization?: (ctx: RouteContext, input: FamilyOrganizationSearchInput) => Promise<FamilyOrganizationSummary | null>;
108
108
  ensureFamilyOrganizationRegistration?: (ctx: RouteContext, input: EnsureFamilyOrganizationRegistrationInput) => Promise<EnsureFamilyOrganizationRegistrationResult>;
109
- confirmIndividualOrganizationOrder?: (input: IndividualOrganizationConfirmOrderInput) => Promise<SubmitAndPollResult>;
109
+ confirmIndividualOrganizationOrder?: (input: IndividualOrganizationConfirmOrderInput) => Promise<IndividualOrganizationOrderResult>;
110
110
  disableIndividual?: (ctx: RouteContext, input: IndividualOrganizationLifecycleInput, pollOptions?: PollOptions) => Promise<SubmitAndPollResult>;
111
111
  purgeIndividual?: (ctx: RouteContext, input: IndividualOrganizationLifecycleInput, pollOptions?: PollOptions) => Promise<SubmitAndPollResult>;
112
112
  disableIndividualMember?: (ctx: RouteContext, input: IndividualMemberLifecycleInput, pollOptions?: PollOptions) => Promise<SubmitAndPollResult>;
@@ -10,7 +10,14 @@ export declare class DigitalTwinSdk {
10
10
  constructor(client: NodeRuntimeClient, actorDid?: string);
11
11
  /** Requests the SMART token used by subsequent digital-twin operations. */
12
12
  requestSmartToken(input: SmartTokenRequestInput): Promise<SmartTokenExchangeResult>;
13
- /** Searches pseudonymous records and exposes matched Compositions directly. */
13
+ /**
14
+ * Searches pseudonymous records and exposes matched Compositions directly.
15
+ *
16
+ * MVP basic search supplies `sections`, `dateFrom`, optional `dateTo`, and
17
+ * `text`. GW resolves an omitted `dateTo` to its current time, applies OR
18
+ * across sections and requires text/date to match the same clinical record.
19
+ * Organization/tenant scope comes from the authenticated SMART token.
20
+ */
14
21
  search(ctx: RouteContext, input: DigitalTwinSearchInput): Promise<DigitalTwinSearchResult>;
15
22
  /**
16
23
  * Saves a tagged researcher-owned working selection for one matching twin.
@@ -28,7 +28,14 @@ export class DigitalTwinSdk {
28
28
  this.researcherDid = actorDid;
29
29
  return result;
30
30
  }
31
- /** Searches pseudonymous records and exposes matched Compositions directly. */
31
+ /**
32
+ * Searches pseudonymous records and exposes matched Compositions directly.
33
+ *
34
+ * MVP basic search supplies `sections`, `dateFrom`, optional `dateTo`, and
35
+ * `text`. GW resolves an omitted `dateTo` to its current time, applies OR
36
+ * across sections and requires text/date to match the same clinical record.
37
+ * Organization/tenant scope comes from the authenticated SMART token.
38
+ */
32
39
  async search(ctx, input) {
33
40
  const filters = { ...(input.filters || {}) };
34
41
  const isPrivateSelectionSearch = Object.keys(filters).some((name) => {
@@ -3,7 +3,7 @@ import { type NodeRuntimeClient, type PollOptions, type SubmitAndPollResult, typ
3
3
  import type { FamilyOrganizationSummary } from 'gdc-common-utils-ts/utils/family-organization-summary';
4
4
  import type { EnsureFamilyOrganizationRegistrationInput, EnsureFamilyOrganizationRegistrationResult } from '../family-organization-registration.js';
5
5
  import type { FamilyOrganizationSearchInput } from '../family-organization-search.js';
6
- import type { IndividualOrganizationConfirmOrderInput, RouteContext } from '../individual-onboarding.js';
6
+ import type { IndividualOrganizationConfirmOrderInput, IndividualOrganizationOrderResult, RouteContext } from '../individual-onboarding.js';
7
7
  import type { IndividualOrganizationBootstrapInput, IndividualOrganizationStartResult } from '../individual-start.js';
8
8
  import type { NodeCapability } from '../session.js';
9
9
  import type { IndividualOrganizationLifecycleInput } from 'gdc-sdk-core-ts';
@@ -39,7 +39,7 @@ export declare class IndividualControllerSdk {
39
39
  /**
40
40
  * Confirms the order returned by `startIndividualOrganization(...)`.
41
41
  */
42
- confirmIndividualOrganizationOrder(input: IndividualOrganizationConfirmOrderInput): Promise<SubmitAndPollResult>;
42
+ confirmIndividualOrganizationOrder(input: IndividualOrganizationConfirmOrderInput): Promise<IndividualOrganizationOrderResult>;
43
43
  /**
44
44
  * Disables the hosted individual/family organization without freeing licenses.
45
45
  */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gdc-sdk-node-ts",
3
- "version": "2.4.35",
3
+ "version": "2.4.36",
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.",
@@ -38,7 +38,7 @@
38
38
  "test:e2e:live-gw:clean": "bash ./scripts/run-live-gw-clean.sh"
39
39
  },
40
40
  "dependencies": {
41
- "gdc-common-utils-ts": "2.5.15",
41
+ "gdc-common-utils-ts": "2.5.20",
42
42
  "gdc-sdk-core-ts": "~2.3.18"
43
43
  },
44
44
  "devDependencies": {
@@ -1,16 +0,0 @@
1
- import type { VerifiableCredentialV2 } from 'gdc-common-utils-ts/models/verifiable-credential';
2
- import type { IWallet, WalletExecutionContext, WalletKeySelection } from 'gdc-sdk-core-ts';
3
- /** Input required to add one human-authorizer proof to the out-of-band VC. */
4
- export type SignOrganizationRegistrationAuthorizationInput = Readonly<{
5
- credential: VerifiableCredentialV2;
6
- wallet: IWallet;
7
- context: WalletExecutionContext;
8
- key: WalletKeySelection;
9
- verificationMethod: string;
10
- createdAt?: string;
11
- }>;
12
- /**
13
- * Adds one detached JWS proof made by the already-unlocked professional
14
- * profile. The browser never receives the private key or clear wallet seed.
15
- */
16
- export declare function signOrganizationRegistrationAuthorizationCredential(input: SignOrganizationRegistrationAuthorizationInput): Promise<VerifiableCredentialV2>;
@@ -1,34 +0,0 @@
1
- import { canonicalizeOrganizationRegistrationAuthorizationCredential, } from 'gdc-common-utils-ts/utils/organization-registration-authorization';
2
- /**
3
- * Adds one detached JWS proof made by the already-unlocked professional
4
- * profile. The browser never receives the private key or clear wallet seed.
5
- */
6
- export async function signOrganizationRegistrationAuthorizationCredential(input) {
7
- if (!input.wallet.signDetachedJws) {
8
- throw new Error('Wallet does not support detached organization authorization proofs.');
9
- }
10
- const verificationMethod = String(input.verificationMethod || '').trim();
11
- if (!verificationMethod)
12
- throw new Error('Organization authorization proof requires verificationMethod.');
13
- const payload = canonicalizeOrganizationRegistrationAuthorizationCredential(input.credential);
14
- const jws = await input.wallet.signDetachedJws(input.context, {
15
- payload,
16
- header: { typ: 'application/vc+ld+json' },
17
- key: input.key,
18
- });
19
- const existingProofs = Array.isArray(input.credential.proof)
20
- ? input.credential.proof
21
- : input.credential.proof
22
- ? [input.credential.proof]
23
- : [];
24
- return {
25
- ...input.credential,
26
- proof: [...existingProofs, {
27
- type: 'JsonWebSignature2020',
28
- created: input.createdAt || new Date().toISOString(),
29
- proofPurpose: 'contractAgreement',
30
- verificationMethod,
31
- jws,
32
- }],
33
- };
34
- }