gdc-common-utils-ts 2.0.2 → 2.0.5

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.
Files changed (40) hide show
  1. package/README.md +45 -0
  2. package/dist/constants/verifiable-credentials.d.ts +6 -0
  3. package/dist/constants/verifiable-credentials.js +6 -0
  4. package/dist/examples/employee.d.ts +15 -0
  5. package/dist/examples/employee.js +15 -0
  6. package/dist/examples/ica-verify-response.d.ts +5 -0
  7. package/dist/examples/ica-verify-response.js +6 -0
  8. package/dist/examples/index.d.ts +2 -0
  9. package/dist/examples/index.js +2 -0
  10. package/dist/examples/individual-controller.d.ts +25 -0
  11. package/dist/examples/individual-controller.js +23 -0
  12. package/dist/examples/legal-organization-verification-transaction.d.ts +1 -0
  13. package/dist/examples/legal-organization-verification-transaction.js +76 -0
  14. package/dist/examples/organization-did-binding.d.ts +1 -0
  15. package/dist/examples/organization-did-binding.js +14 -0
  16. package/dist/examples/shared.d.ts +10 -0
  17. package/dist/examples/shared.js +11 -1
  18. package/dist/utils/bundle-reader.d.ts +2 -0
  19. package/dist/utils/bundle-reader.js +14 -0
  20. package/dist/utils/clinical-bundle-summary.d.ts +20 -0
  21. package/dist/utils/clinical-bundle-summary.js +34 -0
  22. package/dist/utils/didcomm-submit-policy.d.ts +20 -3
  23. package/dist/utils/didcomm-submit-policy.js +37 -6
  24. package/dist/utils/didcomm-submit.d.ts +10 -3
  25. package/dist/utils/didcomm-submit.js +12 -5
  26. package/dist/utils/family-organization-summary.d.ts +24 -0
  27. package/dist/utils/family-organization-summary.js +59 -0
  28. package/dist/utils/index.d.ts +6 -0
  29. package/dist/utils/index.js +6 -0
  30. package/dist/utils/legal-organization-onboarding-editor.d.ts +156 -0
  31. package/dist/utils/legal-organization-onboarding-editor.js +350 -0
  32. package/dist/utils/legal-organization-verification-transaction.d.ts +130 -0
  33. package/dist/utils/legal-organization-verification-transaction.js +118 -0
  34. package/dist/utils/organization-did-binding.d.ts +60 -0
  35. package/dist/utils/organization-did-binding.js +103 -0
  36. package/dist/utils/professional-smart.d.ts +21 -0
  37. package/dist/utils/professional-smart.js +37 -0
  38. package/dist/utils/related-person-list.d.ts +14 -0
  39. package/dist/utils/related-person-list.js +31 -0
  40. package/package.json +1 -1
@@ -0,0 +1,130 @@
1
+ import type { BundleJsonApi } from '../models/bundle';
2
+ import type { ClaimsRecord } from '../models/resource-document';
3
+ /**
4
+ * Canonical business entry type for the first host-side onboarding step that
5
+ * asks GW CORE to forward a legal-organization verification request to ICA.
6
+ *
7
+ * Responsibilities of this transaction:
8
+ * - carry the signed PDF evidence or PDF URL attachment
9
+ * - carry the controller business binding key
10
+ * - optionally carry the organization VC-signing public key chosen by the host
11
+ * - carry the legal organization claims that GW CORE should keep through the
12
+ * verification/onboarding pipeline
13
+ *
14
+ * Non-responsibilities:
15
+ * - it is not the same thing as host `_activate`
16
+ * - it does not model Fabric/CSR enrollment
17
+ */
18
+ export declare const LegalOrganizationVerificationTransactionEntryTypes: Readonly<{
19
+ readonly Request: "Organization-verification-transaction-request-v1.0";
20
+ readonly Response: "Organization-verification-transaction-response-v1.0";
21
+ }>;
22
+ export type LegalOrganizationVerificationTransactionEntryType = typeof LegalOrganizationVerificationTransactionEntryTypes[keyof typeof LegalOrganizationVerificationTransactionEntryTypes];
23
+ /**
24
+ * Explicit controller binding material that ICA should project into the legal
25
+ * representative VC.
26
+ */
27
+ export type LegalOrganizationVerificationTransactionController = Readonly<{
28
+ did?: string;
29
+ sameAs?: string;
30
+ publicKeyJwk?: Record<string, unknown>;
31
+ jwks?: {
32
+ keys: Array<Record<string, unknown>>;
33
+ };
34
+ }>;
35
+ /**
36
+ * Optional organization-side public key material that the hosting operator may
37
+ * already know before the final activation/publication step.
38
+ */
39
+ export type LegalOrganizationVerificationTransactionOrganization = Readonly<{
40
+ did?: string;
41
+ url?: string;
42
+ publicKeyJwk?: Record<string, unknown>;
43
+ jwks?: {
44
+ keys: Array<Record<string, unknown>>;
45
+ };
46
+ }>;
47
+ /**
48
+ * Additional legal-representative payload fields forwarded to ICA `_verify`.
49
+ *
50
+ * These values help ICA derive `sameAs` when the signed document itself does
51
+ * not expose that contact value in a directly reusable way.
52
+ */
53
+ export type LegalOrganizationVerificationRepresentativePayload = Readonly<{
54
+ email?: string;
55
+ sameAs?: string;
56
+ }>;
57
+ /**
58
+ * Optional verification routing hints for ICA.
59
+ *
60
+ * `resourceType` defaults to `contract`, which matches the current
61
+ * legal-organization terms flow in ICA.
62
+ */
63
+ export type LegalOrganizationVerificationRouting = Readonly<{
64
+ resourceType?: string;
65
+ }>;
66
+ /**
67
+ * Canonical input accepted by shared SDK/GW helpers when building the first
68
+ * host onboarding transaction that wraps an ICA `_verify` request.
69
+ */
70
+ export type LegalOrganizationVerificationTransactionInput = Readonly<{
71
+ claims: ClaimsRecord;
72
+ controller: LegalOrganizationVerificationTransactionController;
73
+ organization?: LegalOrganizationVerificationTransactionOrganization;
74
+ legalRepresentativePayload?: LegalOrganizationVerificationRepresentativePayload;
75
+ verification?: LegalOrganizationVerificationRouting;
76
+ attachments?: unknown[];
77
+ }>;
78
+ export type LegalOrganizationVerificationTransactionEntry = Readonly<{
79
+ type?: string;
80
+ meta?: {
81
+ claims?: ClaimsRecord;
82
+ [key: string]: unknown;
83
+ };
84
+ resource?: {
85
+ controller?: LegalOrganizationVerificationTransactionController;
86
+ organization?: LegalOrganizationVerificationTransactionOrganization;
87
+ legalRepresentativePayload?: LegalOrganizationVerificationRepresentativePayload;
88
+ legalRepresentative?: LegalOrganizationVerificationRepresentativePayload;
89
+ verification?: LegalOrganizationVerificationRouting;
90
+ [key: string]: unknown;
91
+ };
92
+ [key: string]: unknown;
93
+ }>;
94
+ /**
95
+ * Builds the canonical Bundle payload for host-side legal organization
96
+ * verification transactions.
97
+ *
98
+ * Contract notes:
99
+ * - business claims remain in `meta.claims`
100
+ * - controller binding material remains in `resource.controller.*`
101
+ * - organization signing material remains in `resource.organization.*`
102
+ * - PDF evidence or URL attachments stay at the DIDComm-message level
103
+ * - `Service.category` is the canonical business-sector input later used by GW
104
+ * to target the appropriate ICA verification route
105
+ */
106
+ export declare function buildLegalOrganizationVerificationTransactionBundle(input: LegalOrganizationVerificationTransactionInput): BundleJsonApi;
107
+ /**
108
+ * Returns the first bundle entry when the payload matches the canonical
109
+ * legal-organization verification transaction shape.
110
+ *
111
+ * This helper accepts either:
112
+ * - the raw bundle itself
113
+ * - or a DIDComm/API wrapper object whose `body` contains that bundle
114
+ */
115
+ export declare function getFirstLegalOrganizationVerificationTransactionEntry(value: unknown): LegalOrganizationVerificationTransactionEntry | undefined;
116
+ /**
117
+ * Returns the normalized controller binding payload from the first legal
118
+ * organization verification transaction entry when present.
119
+ */
120
+ export declare function getLegalOrganizationVerificationController(value: unknown): LegalOrganizationVerificationTransactionController | undefined;
121
+ /**
122
+ * Returns the normalized legal representative contact payload from the first
123
+ * legal-organization verification transaction entry when present.
124
+ *
125
+ * Compatibility note:
126
+ * - GW/SDK request builders use `resource.legalRepresentativePayload`
127
+ * - the ICA forwarding payload currently uses `resource.legalRepresentative`
128
+ * - this helper intentionally accepts both shapes
129
+ */
130
+ export declare function getLegalOrganizationVerificationRepresentativePayload(value: unknown): LegalOrganizationVerificationRepresentativePayload | undefined;
@@ -0,0 +1,118 @@
1
+ import { ClaimsServiceSchemaorg } from '../constants/schemaorg.js';
2
+ /**
3
+ * Canonical business entry type for the first host-side onboarding step that
4
+ * asks GW CORE to forward a legal-organization verification request to ICA.
5
+ *
6
+ * Responsibilities of this transaction:
7
+ * - carry the signed PDF evidence or PDF URL attachment
8
+ * - carry the controller business binding key
9
+ * - optionally carry the organization VC-signing public key chosen by the host
10
+ * - carry the legal organization claims that GW CORE should keep through the
11
+ * verification/onboarding pipeline
12
+ *
13
+ * Non-responsibilities:
14
+ * - it is not the same thing as host `_activate`
15
+ * - it does not model Fabric/CSR enrollment
16
+ */
17
+ export const LegalOrganizationVerificationTransactionEntryTypes = Object.freeze({
18
+ Request: 'Organization-verification-transaction-request-v1.0',
19
+ Response: 'Organization-verification-transaction-response-v1.0',
20
+ });
21
+ function normalizeText(value) {
22
+ return typeof value === 'string' ? value.trim() : '';
23
+ }
24
+ function asRecord(value) {
25
+ return value && typeof value === 'object' && !Array.isArray(value)
26
+ ? value
27
+ : undefined;
28
+ }
29
+ /**
30
+ * Builds the canonical Bundle payload for host-side legal organization
31
+ * verification transactions.
32
+ *
33
+ * Contract notes:
34
+ * - business claims remain in `meta.claims`
35
+ * - controller binding material remains in `resource.controller.*`
36
+ * - organization signing material remains in `resource.organization.*`
37
+ * - PDF evidence or URL attachments stay at the DIDComm-message level
38
+ * - `Service.category` is the canonical business-sector input later used by GW
39
+ * to target the appropriate ICA verification route
40
+ */
41
+ export function buildLegalOrganizationVerificationTransactionBundle(input) {
42
+ const businessSector = normalizeText(input.claims?.[ClaimsServiceSchemaorg.category]);
43
+ if (!businessSector) {
44
+ throw new Error(`buildLegalOrganizationVerificationTransactionBundle requires ${ClaimsServiceSchemaorg.category}.`);
45
+ }
46
+ return {
47
+ resourceType: 'Bundle',
48
+ type: 'collection',
49
+ total: 1,
50
+ data: [{
51
+ type: LegalOrganizationVerificationTransactionEntryTypes.Request,
52
+ meta: {
53
+ claims: input.claims,
54
+ },
55
+ resource: {
56
+ controller: input.controller,
57
+ ...(input.organization ? { organization: input.organization } : {}),
58
+ ...(input.legalRepresentativePayload
59
+ ? { legalRepresentativePayload: input.legalRepresentativePayload }
60
+ : {}),
61
+ verification: {
62
+ resourceType: normalizeText(input.verification?.resourceType) || 'contract',
63
+ },
64
+ },
65
+ }],
66
+ ...(Array.isArray(input.attachments) && input.attachments.length > 0
67
+ ? { attachments: input.attachments }
68
+ : {}),
69
+ };
70
+ }
71
+ /**
72
+ * Returns the first bundle entry when the payload matches the canonical
73
+ * legal-organization verification transaction shape.
74
+ *
75
+ * This helper accepts either:
76
+ * - the raw bundle itself
77
+ * - or a DIDComm/API wrapper object whose `body` contains that bundle
78
+ */
79
+ export function getFirstLegalOrganizationVerificationTransactionEntry(value) {
80
+ const root = asRecord(value);
81
+ const bundle = asRecord(root?.body) || root;
82
+ const data = Array.isArray(bundle?.data) ? bundle.data : [];
83
+ const first = data[0];
84
+ return asRecord(first);
85
+ }
86
+ /**
87
+ * Returns the normalized controller binding payload from the first legal
88
+ * organization verification transaction entry when present.
89
+ */
90
+ export function getLegalOrganizationVerificationController(value) {
91
+ const entry = getFirstLegalOrganizationVerificationTransactionEntry(value);
92
+ const controller = asRecord(entry?.resource?.controller);
93
+ return controller
94
+ ? controller
95
+ : undefined;
96
+ }
97
+ /**
98
+ * Returns the normalized legal representative contact payload from the first
99
+ * legal-organization verification transaction entry when present.
100
+ *
101
+ * Compatibility note:
102
+ * - GW/SDK request builders use `resource.legalRepresentativePayload`
103
+ * - the ICA forwarding payload currently uses `resource.legalRepresentative`
104
+ * - this helper intentionally accepts both shapes
105
+ */
106
+ export function getLegalOrganizationVerificationRepresentativePayload(value) {
107
+ const entry = getFirstLegalOrganizationVerificationTransactionEntry(value);
108
+ const candidate = asRecord(entry?.resource?.legalRepresentativePayload)
109
+ || asRecord(entry?.resource?.legalRepresentative);
110
+ if (!candidate)
111
+ return undefined;
112
+ const email = normalizeText(candidate.email);
113
+ const sameAs = normalizeText(candidate.sameAs);
114
+ return {
115
+ ...(email ? { email } : {}),
116
+ ...(sameAs ? { sameAs } : {}),
117
+ };
118
+ }
@@ -0,0 +1,60 @@
1
+ import type { BundleJsonApi } from '../models/bundle';
2
+ export declare const OrganizationDidBindingEntryTypes: Readonly<{
3
+ readonly Request: "Organization-did-binding-request-v1.0";
4
+ readonly Response: "Organization-did-binding-response-v1.0";
5
+ }>;
6
+ export type OrganizationDidBindingErrorCode = 'MISSING_ORGANIZATION_URL' | 'UNSUPPORTED_ORGANIZATION_LOCATOR';
7
+ export type OrganizationDidBindingValidationError = Readonly<{
8
+ code: OrganizationDidBindingErrorCode;
9
+ message: string;
10
+ claimPaths: string[];
11
+ }>;
12
+ export type OrganizationDidBindingControllerInput = Readonly<{
13
+ sameAs?: string;
14
+ }>;
15
+ export type OrganizationDidBindingOrganizationInput = Readonly<{
16
+ url: string | string[];
17
+ taxID?: string;
18
+ taxId?: string;
19
+ identifier?: string;
20
+ }>;
21
+ export type OrganizationDidBindingInput = Readonly<{
22
+ organization: OrganizationDidBindingOrganizationInput;
23
+ controller?: OrganizationDidBindingControllerInput;
24
+ }>;
25
+ export type ValidateOrganizationDidBindingInputResult = Readonly<{
26
+ ok: boolean;
27
+ errors: OrganizationDidBindingValidationError[];
28
+ normalizedInput: Readonly<{
29
+ organization: {
30
+ url: string[];
31
+ };
32
+ controller?: OrganizationDidBindingControllerInput;
33
+ }>;
34
+ }>;
35
+ /**
36
+ * Validates the tenant-scoped organization DID binding request.
37
+ *
38
+ * Canonical contract:
39
+ * - the organization is already identified by the tenant path in GW CORE
40
+ * - callers send one or more public aliases in `organization.url`
41
+ * - `controller.sameAs` is optional additional evidence, not a new key-binding
42
+ * bootstrap step
43
+ *
44
+ * Current version limits:
45
+ * - no `taxID` / `identifier` locator is required
46
+ * - sending those legacy locator fields is rejected so callers do not mix path
47
+ * identity with payload identity
48
+ */
49
+ export declare function validateOrganizationDidBindingInput(input: OrganizationDidBindingInput): ValidateOrganizationDidBindingInputResult;
50
+ /**
51
+ * Builds the canonical bundle payload for one tenant-scoped DID binding
52
+ * request.
53
+ *
54
+ * Result contract:
55
+ * - `resource.organization.url` carries the public alias replacement list
56
+ * - `resource.controller.sameAs` is optional corroborating identity material
57
+ * - organization identity is resolved from the tenant path, not from payload
58
+ * locators
59
+ */
60
+ export declare function buildOrganizationDidBindingBundle(input: OrganizationDidBindingInput): BundleJsonApi;
@@ -0,0 +1,103 @@
1
+ export const OrganizationDidBindingEntryTypes = Object.freeze({
2
+ Request: 'Organization-did-binding-request-v1.0',
3
+ Response: 'Organization-did-binding-response-v1.0',
4
+ });
5
+ function normalizeOptionalText(value) {
6
+ if (typeof value !== 'string')
7
+ return undefined;
8
+ const trimmed = value.trim();
9
+ return trimmed.length ? trimmed : undefined;
10
+ }
11
+ function normalizeOrganizationUrls(value) {
12
+ if (Array.isArray(value)) {
13
+ const urls = value
14
+ .map((item) => normalizeOptionalText(item))
15
+ .filter((item) => Boolean(item));
16
+ return urls.length ? urls : undefined;
17
+ }
18
+ const raw = normalizeOptionalText(value);
19
+ if (!raw)
20
+ return undefined;
21
+ const urls = raw
22
+ .split(',')
23
+ .map((item) => item.trim())
24
+ .filter(Boolean);
25
+ return urls.length ? urls : undefined;
26
+ }
27
+ /**
28
+ * Validates the tenant-scoped organization DID binding request.
29
+ *
30
+ * Canonical contract:
31
+ * - the organization is already identified by the tenant path in GW CORE
32
+ * - callers send one or more public aliases in `organization.url`
33
+ * - `controller.sameAs` is optional additional evidence, not a new key-binding
34
+ * bootstrap step
35
+ *
36
+ * Current version limits:
37
+ * - no `taxID` / `identifier` locator is required
38
+ * - sending those legacy locator fields is rejected so callers do not mix path
39
+ * identity with payload identity
40
+ */
41
+ export function validateOrganizationDidBindingInput(input) {
42
+ const errors = [];
43
+ const normalizedUrls = normalizeOrganizationUrls(input?.organization?.url);
44
+ const taxID = normalizeOptionalText(input?.organization?.taxID || input?.organization?.taxId);
45
+ const identifier = normalizeOptionalText(input?.organization?.identifier);
46
+ const controllerSameAs = normalizeOptionalText(input?.controller?.sameAs);
47
+ if (!normalizedUrls?.length) {
48
+ errors.push({
49
+ code: 'MISSING_ORGANIZATION_URL',
50
+ message: 'Organization DID binding requires at least one organization.url value.',
51
+ claimPaths: ['organization.url'],
52
+ });
53
+ }
54
+ if (taxID || identifier) {
55
+ errors.push({
56
+ code: 'UNSUPPORTED_ORGANIZATION_LOCATOR',
57
+ message: 'Organization DID binding in GW CORE uses the tenant path as locator and does not accept organization.taxID or organization.identifier in this version.',
58
+ claimPaths: ['organization.taxID', 'organization.identifier'],
59
+ });
60
+ }
61
+ return {
62
+ ok: errors.length === 0,
63
+ errors,
64
+ normalizedInput: {
65
+ organization: {
66
+ url: normalizedUrls || [],
67
+ },
68
+ ...(controllerSameAs ? { controller: { sameAs: controllerSameAs } } : {}),
69
+ },
70
+ };
71
+ }
72
+ /**
73
+ * Builds the canonical bundle payload for one tenant-scoped DID binding
74
+ * request.
75
+ *
76
+ * Result contract:
77
+ * - `resource.organization.url` carries the public alias replacement list
78
+ * - `resource.controller.sameAs` is optional corroborating identity material
79
+ * - organization identity is resolved from the tenant path, not from payload
80
+ * locators
81
+ */
82
+ export function buildOrganizationDidBindingBundle(input) {
83
+ const validation = validateOrganizationDidBindingInput(input);
84
+ if (!validation.ok) {
85
+ throw new Error(validation.errors.map((item) => item.message).join(' '));
86
+ }
87
+ return {
88
+ resourceType: 'Bundle',
89
+ type: 'collection',
90
+ total: 1,
91
+ data: [{
92
+ type: OrganizationDidBindingEntryTypes.Request,
93
+ resource: {
94
+ organization: {
95
+ url: validation.normalizedInput.organization.url,
96
+ },
97
+ ...(validation.normalizedInput.controller
98
+ ? { controller: validation.normalizedInput.controller }
99
+ : {}),
100
+ },
101
+ }],
102
+ };
103
+ }
@@ -0,0 +1,21 @@
1
+ export type ProfessionalEmployeeCredentialInput = Readonly<{
2
+ actorDid: string;
3
+ role: string;
4
+ additionalCredentialSubject?: Record<string, unknown>;
5
+ additionalCredential?: Record<string, unknown>;
6
+ }>;
7
+ export type ProfessionalSmartVpPayloadInput = Readonly<{
8
+ clientId: string;
9
+ actorDid: string;
10
+ role: string;
11
+ verifiableCredential?: string | Record<string, unknown> | ReadonlyArray<string | Record<string, unknown>>;
12
+ additionalVp?: Record<string, unknown>;
13
+ additionalPayload?: Record<string, unknown>;
14
+ }>;
15
+ export declare function buildProfessionalEmployeeCredential(input: ProfessionalEmployeeCredentialInput): Record<string, unknown>;
16
+ export declare function buildProfessionalSmartVpPayload(input: ProfessionalSmartVpPayloadInput): Record<string, unknown>;
17
+ export declare function buildUnsignedProfessionalSmartVpJwt(input: ProfessionalSmartVpPayloadInput, options?: Readonly<{
18
+ nowSeconds?: number;
19
+ ttlSeconds?: number;
20
+ nonce?: string;
21
+ }>): string;
@@ -0,0 +1,37 @@
1
+ import { ProfessionalCredentialTypes, W3cCredentialTypes, } from '../constants/verifiable-credentials.js';
2
+ import { buildUnsignedVpJwt } from './jwt.js';
3
+ export function buildProfessionalEmployeeCredential(input) {
4
+ return {
5
+ type: [
6
+ W3cCredentialTypes.VerifiableCredential,
7
+ ProfessionalCredentialTypes.EmployeeCredential,
8
+ ],
9
+ credentialSubject: {
10
+ id: String(input.actorDid || '').trim(),
11
+ hasOccupation: String(input.role || '').trim(),
12
+ ...(input.additionalCredentialSubject || {}),
13
+ },
14
+ ...(input.additionalCredential || {}),
15
+ };
16
+ }
17
+ export function buildProfessionalSmartVpPayload(input) {
18
+ const credentials = Array.isArray(input.verifiableCredential)
19
+ ? [...input.verifiableCredential]
20
+ : input.verifiableCredential
21
+ ? [input.verifiableCredential]
22
+ : [buildProfessionalEmployeeCredential({
23
+ actorDid: input.actorDid,
24
+ role: input.role,
25
+ })];
26
+ return {
27
+ ...(input.additionalPayload || {}),
28
+ vp: {
29
+ holder: String(input.clientId || '').trim(),
30
+ verifiableCredential: credentials,
31
+ ...(input.additionalVp || {}),
32
+ },
33
+ };
34
+ }
35
+ export function buildUnsignedProfessionalSmartVpJwt(input, options = {}) {
36
+ return buildUnsignedVpJwt(buildProfessionalSmartVpPayload(input), options);
37
+ }
@@ -9,6 +9,14 @@ export type RelatedPersonListRecord = Readonly<{
9
9
  resourceId?: string;
10
10
  claims: Record<string, unknown>;
11
11
  }>;
12
+ export type RelatedPersonListSelection = Readonly<{
13
+ index?: number;
14
+ identifier?: string;
15
+ name?: string;
16
+ telecom?: string;
17
+ patient?: string;
18
+ activeOnly?: boolean;
19
+ }>;
12
20
  /**
13
21
  * Reads subject-side relationship records from one current GW-style result
14
22
  * body into one neutral list shape for frontend screens.
@@ -18,3 +26,9 @@ export declare function readRelatedPersonListRecords(body: unknown): RelatedPers
18
26
  * Returns one related-person record by canonical business identifier.
19
27
  */
20
28
  export declare function findRelatedPersonListRecord(body: unknown, identifier: string): RelatedPersonListRecord | undefined;
29
+ /**
30
+ * Selects one related-person record from one neutralized list/body using the
31
+ * same high-level criteria that channel apps usually expose to users:
32
+ * list position, identifier, display name, contact value, or linked patient.
33
+ */
34
+ export declare function selectRelatedPersonListRecord(body: unknown, selection: RelatedPersonListSelection): RelatedPersonListRecord | undefined;
@@ -52,3 +52,34 @@ export function findRelatedPersonListRecord(body, identifier) {
52
52
  return readRelatedPersonListRecords(body)
53
53
  .find((record) => record.identifier === normalizedIdentifier);
54
54
  }
55
+ /**
56
+ * Selects one related-person record from one neutralized list/body using the
57
+ * same high-level criteria that channel apps usually expose to users:
58
+ * list position, identifier, display name, contact value, or linked patient.
59
+ */
60
+ export function selectRelatedPersonListRecord(body, selection) {
61
+ const records = readRelatedPersonListRecords(body);
62
+ const candidates = selection.activeOnly
63
+ ? records.filter((record) => record.active === 'true')
64
+ : records;
65
+ if (typeof selection.index === 'number' && Number.isInteger(selection.index)) {
66
+ return candidates[selection.index];
67
+ }
68
+ const identifier = normalizeText(selection.identifier);
69
+ if (identifier) {
70
+ return candidates.find((record) => record.identifier === identifier);
71
+ }
72
+ const name = normalizeText(selection.name)?.toLowerCase();
73
+ if (name) {
74
+ return candidates.find((record) => normalizeText(record.name)?.toLowerCase() === name);
75
+ }
76
+ const telecom = normalizeText(selection.telecom)?.toLowerCase();
77
+ if (telecom) {
78
+ return candidates.find((record) => normalizeText(record.telecom)?.toLowerCase() === telecom);
79
+ }
80
+ const patient = normalizeText(selection.patient);
81
+ if (patient) {
82
+ return candidates.find((record) => record.patient === patient);
83
+ }
84
+ return undefined;
85
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gdc-common-utils-ts",
3
- "version": "2.0.2",
3
+ "version": "2.0.5",
4
4
  "publishConfig": {
5
5
  "access": "public"
6
6
  },