gdc-common-utils-ts 2.3.1 → 2.3.3
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 +22 -0
- package/dist/CryptographyService.d.ts +3 -0
- package/dist/CryptographyService.js +64 -35
- package/dist/constants/identity-identifiers.d.ts +60 -7
- package/dist/constants/identity-identifiers.js +58 -7
- package/dist/constants/schemaorg.d.ts +4 -0
- package/dist/constants/schemaorg.js +4 -0
- package/dist/constants/urn.d.ts +1 -0
- package/dist/constants/urn.js +1 -0
- package/dist/convert/convert-allergy-intolerance.js +2 -1
- package/dist/convert/convert-condition.js +2 -1
- package/dist/convert/index.d.ts +1 -0
- package/dist/convert/index.js +1 -0
- package/dist/convert/schemaorg-to-gaia-x.d.ts +115 -0
- package/dist/convert/schemaorg-to-gaia-x.js +208 -0
- package/dist/models/bundle-editor-types.d.ts +13 -3
- package/dist/models/bundle-editor-types.js +9 -1
- package/dist/models/gaia-x.d.ts +128 -0
- package/dist/models/gaia-x.js +26 -0
- package/dist/models/index.d.ts +2 -0
- package/dist/models/index.js +2 -0
- package/dist/models/jwe.d.ts +25 -0
- package/dist/models/subject-identifier-ledger.d.ts +16 -0
- package/dist/models/subject-identifier-ledger.js +1 -0
- package/dist/utils/bundle-editor-core.d.ts +9 -0
- package/dist/utils/bundle-editor-core.js +46 -0
- package/dist/utils/bundle-editor.d.ts +2 -0
- package/dist/utils/bundle-editor.js +2 -0
- package/dist/utils/bundle-entry-editor.d.ts +6 -0
- package/dist/utils/bundle-entry-editor.js +20 -0
- package/dist/utils/communication-consent-access-editor.d.ts +14 -1
- package/dist/utils/communication-consent-access-editor.js +27 -0
- package/dist/utils/consent-entry-editor.d.ts +42 -0
- package/dist/utils/consent-entry-editor.js +80 -0
- package/dist/utils/index.d.ts +1 -0
- package/dist/utils/index.js +1 -0
- package/dist/utils/individual-identifier.d.ts +14 -0
- package/dist/utils/individual-identifier.js +39 -0
- package/dist/utils/multibasehash.d.ts +19 -5
- package/dist/utils/multibasehash.js +35 -10
- package/dist/utils/multiformat-profile.d.ts +4 -2
- package/dist/utils/multiformat-profile.js +5 -3
- package/dist/utils/related-person-entry-editor.d.ts +32 -0
- package/dist/utils/related-person-entry-editor.js +97 -0
- package/dist/utils/same-as.d.ts +10 -0
- package/dist/utils/same-as.js +28 -3
- package/package.json +2 -1
|
@@ -0,0 +1,208 @@
|
|
|
1
|
+
// Copyright 2026 Antifraud Services Inc. under the Apache License, Version 2.0.
|
|
2
|
+
import { ClaimsOrganizationSchemaorg, ClaimsServiceSchemaorg } from '../constants/schemaorg.js';
|
|
3
|
+
import { GaiaXCredentialAttachmentFormat, GaiaXCredentialAttachmentRole, GaiaXCredentialMediaType, } from '../models/gaia-x.js';
|
|
4
|
+
const W3C_VC_V2_CONTEXT = 'https://www.w3.org/ns/credentials/v2';
|
|
5
|
+
function requiredClaim(claims, key, label) {
|
|
6
|
+
const value = String(claims[key] ?? '').trim();
|
|
7
|
+
if (!value)
|
|
8
|
+
throw new Error(`Missing ${label} required for Gaia-X projection.`);
|
|
9
|
+
return value;
|
|
10
|
+
}
|
|
11
|
+
function optionalClaim(claims, key) {
|
|
12
|
+
const value = String(claims[key] ?? '').trim();
|
|
13
|
+
return value || undefined;
|
|
14
|
+
}
|
|
15
|
+
function requiredInput(value, label) {
|
|
16
|
+
const normalized = value.trim();
|
|
17
|
+
if (!normalized)
|
|
18
|
+
throw new Error(`Missing ${label} required for Gaia-X projection.`);
|
|
19
|
+
return normalized;
|
|
20
|
+
}
|
|
21
|
+
function asObject(value) {
|
|
22
|
+
return value && typeof value === 'object' && !Array.isArray(value)
|
|
23
|
+
? value
|
|
24
|
+
: undefined;
|
|
25
|
+
}
|
|
26
|
+
function asString(value) {
|
|
27
|
+
return typeof value === 'string' ? value.trim() : '';
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Reads the canonical schema.org `PropertyValue` organization identifier.
|
|
31
|
+
* During migration it also accepts the historical nested
|
|
32
|
+
* `identifier.identifier` form. When the structure is absent, `taxID` becomes
|
|
33
|
+
* a VAT/TAX fallback, matching ICA's OrganizationCredential issuance rule.
|
|
34
|
+
*/
|
|
35
|
+
export function resolveSchemaOrgOrganizationRegistrationIdentifier(credentialSubject) {
|
|
36
|
+
const outerIdentifier = asObject(credentialSubject.identifier);
|
|
37
|
+
const identifier = asObject(outerIdentifier?.identifier) || outerIdentifier;
|
|
38
|
+
const taxId = asString(credentialSubject.taxID || credentialSubject.taxId);
|
|
39
|
+
const value = asString(identifier?.value) || taxId;
|
|
40
|
+
if (!value)
|
|
41
|
+
throw new Error('Missing OrganizationCredential credentialSubject.identifier.value or taxID.');
|
|
42
|
+
const explicitType = asString(identifier?.additionalType || outerIdentifier?.additionalType);
|
|
43
|
+
return {
|
|
44
|
+
additionalType: explicitType || (/^VAT[A-Z]{2}-/i.test(value) ? 'VAT' : 'TAX'),
|
|
45
|
+
value,
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Converts canonical schema.org organization claims into an unsigned Gaia-X
|
|
50
|
+
* ICAM 25.11 LegalPerson VC draft.
|
|
51
|
+
*
|
|
52
|
+
* Semantic boundary:
|
|
53
|
+
* - Gaia-X `LegalPerson` is the juridical organization/legal entity. It is not
|
|
54
|
+
* GDC's natural-person `LegalRepresentativeCredential`.
|
|
55
|
+
* - representative claims are intentionally never projected by this function.
|
|
56
|
+
* - VAT/tax remains in the source schema.org OrganizationCredential. Gaia-X's
|
|
57
|
+
* `gx:legalRegistrationNumber` is a resolvable reference to the separate
|
|
58
|
+
* registration/notary credential, not an assertion synthesized from VAT.
|
|
59
|
+
* - this function is deterministic and does not sign. The authoritative GW
|
|
60
|
+
* signs the returned draft as VC-JWT; ICA caches and verifies that exact JWT.
|
|
61
|
+
*
|
|
62
|
+
* This projection targets the credential structure and semantic model described
|
|
63
|
+
* by Gaia-X ICAM 25.11. Passing the resulting shape tests neither Gaia-X policy
|
|
64
|
+
* compliance nor GXDCH/TCK conformance.
|
|
65
|
+
*
|
|
66
|
+
* @see https://docs.gaia-x.eu/technical-committee/identity-credential-access-management/25.11/gaia-x_credentials/
|
|
67
|
+
* @see https://docs.gaia-x.eu/technical-committee/identity-credential-access-management/25.11/semantic_model/
|
|
68
|
+
*/
|
|
69
|
+
export function buildGaiaXLegalPersonCredentialDraft(input) {
|
|
70
|
+
const country = requiredClaim(input.claims, ClaimsOrganizationSchemaorg.addressCountry, 'organization ISO 3166-1 country code').toUpperCase();
|
|
71
|
+
const gaiaXAddress = { 'gx:countryCode': country };
|
|
72
|
+
const website = optionalClaim(input.claims, ClaimsOrganizationSchemaorg.url);
|
|
73
|
+
return {
|
|
74
|
+
'@context': [W3C_VC_V2_CONTEXT],
|
|
75
|
+
type: ['VerifiableCredential', 'LegalPerson'],
|
|
76
|
+
id: requiredInput(input.credentialId, 'credentialId'),
|
|
77
|
+
issuer: requiredInput(input.issuerId, 'issuerId'),
|
|
78
|
+
validFrom: requiredInput(input.validFrom, 'validFrom'),
|
|
79
|
+
credentialSubject: {
|
|
80
|
+
id: requiredInput(input.subjectId, 'subjectId'),
|
|
81
|
+
type: 'gx:LegalPerson',
|
|
82
|
+
'gx:legalName': requiredClaim(input.claims, ClaimsOrganizationSchemaorg.legalName, 'organization legal name'),
|
|
83
|
+
'gx:legalRegistrationNumber': {
|
|
84
|
+
id: requiredInput(input.legalRegistrationNumberCredentialId, 'legal registration number credential id'),
|
|
85
|
+
},
|
|
86
|
+
'gx:headquarterAddress': gaiaXAddress,
|
|
87
|
+
'gx:legalAddress': gaiaXAddress,
|
|
88
|
+
...(website ? { 'gx:website': website } : {}),
|
|
89
|
+
},
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Projects an ICA/GDC schema.org OrganizationCredential into a Gaia-X
|
|
94
|
+
* LegalPerson draft while preserving the organization `credentialSubject.id`.
|
|
95
|
+
*
|
|
96
|
+
* The source VC and Gaia-X VC are different signed statements, so their
|
|
97
|
+
* credential IDs must not silently collide. By default the Gaia-X credential
|
|
98
|
+
* receives `<source credential id>#gaia-x-legal-person`; callers may provide a
|
|
99
|
+
* separately resolvable ID. `registrationIdentifier` is returned for the
|
|
100
|
+
* notary/GXDCH registration step, while `gx:legalRegistrationNumber` remains a
|
|
101
|
+
* reference to the resulting registration credential.
|
|
102
|
+
*/
|
|
103
|
+
export function buildGaiaXLegalPersonProjectionFromOrganizationCredential(input) {
|
|
104
|
+
const sourceCredentialId = requiredInput(asString(input.organizationCredential.id), 'source credential id');
|
|
105
|
+
const subject = asObject(input.organizationCredential.credentialSubject);
|
|
106
|
+
if (!subject)
|
|
107
|
+
throw new Error('OrganizationCredential requires one object credentialSubject.');
|
|
108
|
+
const subjectId = requiredInput(asString(subject.id || subject['@id']), 'organization credentialSubject.id');
|
|
109
|
+
const registrationIdentifier = resolveSchemaOrgOrganizationRegistrationIdentifier(subject);
|
|
110
|
+
const address = asObject(subject.address);
|
|
111
|
+
const claims = {
|
|
112
|
+
[ClaimsOrganizationSchemaorg.legalName]: asString(subject.legalName || subject.name),
|
|
113
|
+
[ClaimsOrganizationSchemaorg.url]: asString(subject.url),
|
|
114
|
+
[ClaimsOrganizationSchemaorg.addressCountry]: input.addressCountryCode || asString(address?.addressCountry),
|
|
115
|
+
[ClaimsOrganizationSchemaorg.identifierType]: registrationIdentifier.additionalType,
|
|
116
|
+
[ClaimsOrganizationSchemaorg.identifierValue]: registrationIdentifier.value,
|
|
117
|
+
};
|
|
118
|
+
return {
|
|
119
|
+
sourceCredentialId,
|
|
120
|
+
registrationIdentifier,
|
|
121
|
+
credential: buildGaiaXLegalPersonCredentialDraft({
|
|
122
|
+
claims,
|
|
123
|
+
credentialId: input.credentialId || `${sourceCredentialId}#gaia-x-legal-person`,
|
|
124
|
+
subjectId,
|
|
125
|
+
issuerId: input.issuerId,
|
|
126
|
+
legalRegistrationNumberCredentialId: input.legalRegistrationNumberCredentialId,
|
|
127
|
+
validFrom: input.validFrom,
|
|
128
|
+
}),
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* Converts schema.org service claims into an unsigned Gaia-X ServiceOffering
|
|
133
|
+
* VC draft. A service offering is independent from the participant credential:
|
|
134
|
+
* it references the LegalPerson credential through `gx:providedBy` and carries
|
|
135
|
+
* its own mandatory terms reference.
|
|
136
|
+
*
|
|
137
|
+
* The GW must sign this draft as a separate VC-JWT. A DCAT DataService is useful
|
|
138
|
+
* catalog metadata but is not a substitute for this credential.
|
|
139
|
+
*/
|
|
140
|
+
export function buildGaiaXServiceOfferingCredentialDraft(input) {
|
|
141
|
+
const name = optionalClaim(input.claims, ClaimsServiceSchemaorg.name);
|
|
142
|
+
const description = optionalClaim(input.claims, ClaimsServiceSchemaorg.description);
|
|
143
|
+
const endpointUrl = optionalClaim(input.claims, ClaimsServiceSchemaorg.url);
|
|
144
|
+
const termsHash = requiredInput(input.termsAndConditionsHash, 'terms and conditions SHA-256 hash');
|
|
145
|
+
if (!/^[a-f0-9]{64}$/i.test(termsHash)) {
|
|
146
|
+
throw new Error('Gaia-X terms and conditions hash must be a 64-character SHA-256 hexadecimal digest of the published document bytes.');
|
|
147
|
+
}
|
|
148
|
+
return {
|
|
149
|
+
'@context': [W3C_VC_V2_CONTEXT],
|
|
150
|
+
type: ['VerifiableCredential', 'ServiceOffering'],
|
|
151
|
+
id: requiredInput(input.credentialId, 'credentialId'),
|
|
152
|
+
issuer: requiredInput(input.issuerId, 'issuerId'),
|
|
153
|
+
validFrom: requiredInput(input.validFrom, 'validFrom'),
|
|
154
|
+
credentialSubject: {
|
|
155
|
+
id: requiredInput(input.subjectId, 'subjectId'),
|
|
156
|
+
type: 'gx:ServiceOffering',
|
|
157
|
+
'gx:providedBy': { id: requiredInput(input.providedByCredentialId, 'providedBy credential id') },
|
|
158
|
+
'gx:serviceOfferingTermsAndConditions': [{
|
|
159
|
+
'gx:url': requiredInput(input.termsAndConditionsUrl, 'terms and conditions URL'),
|
|
160
|
+
'gx:hash': termsHash.toLowerCase(),
|
|
161
|
+
}],
|
|
162
|
+
...(name ? { 'gx:name': name } : {}),
|
|
163
|
+
...(description ? { 'gx:description': description } : {}),
|
|
164
|
+
...(endpointUrl ? { 'gx:endpoint': [{ 'gx:endpointURL': endpointUrl }] } : {}),
|
|
165
|
+
},
|
|
166
|
+
};
|
|
167
|
+
}
|
|
168
|
+
/** Builds the mandatory first Gaia-X participant attachment for ICA discovery. */
|
|
169
|
+
export function buildGaiaXParticipantAttachment(input) {
|
|
170
|
+
return buildGaiaXVcJwtAttachment({
|
|
171
|
+
...input,
|
|
172
|
+
role: GaiaXCredentialAttachmentRole.Participant,
|
|
173
|
+
});
|
|
174
|
+
}
|
|
175
|
+
/** Wraps an exact signed Gaia-X VC-JWT without decoding or re-signing it. */
|
|
176
|
+
export function buildGaiaXVcJwtAttachment(input) {
|
|
177
|
+
return {
|
|
178
|
+
id: requiredInput(input.id, 'attachment id'),
|
|
179
|
+
format: GaiaXCredentialAttachmentFormat,
|
|
180
|
+
role: input.role,
|
|
181
|
+
media_type: GaiaXCredentialMediaType.VcJwt,
|
|
182
|
+
data: { json: { jwt: requiredInput(input.jwt, 'VC-JWT') } },
|
|
183
|
+
};
|
|
184
|
+
}
|
|
185
|
+
/**
|
|
186
|
+
* Assembles one ICA member discovery entry and enforces the interoperable
|
|
187
|
+
* ordering contract: schema.org OrganizationCredential first in `vc[]`, and
|
|
188
|
+
* Gaia-X participant VC-JWT first in `attachments[]`.
|
|
189
|
+
*
|
|
190
|
+
* The caller owns signature verification and cache freshness. This helper does
|
|
191
|
+
* not derive or duplicate VAT outside `vc[]` and does not mutate signed data.
|
|
192
|
+
*/
|
|
193
|
+
export function buildIcaMemberDiscoveryData(input) {
|
|
194
|
+
if (!input.vc.length) {
|
|
195
|
+
throw new Error('ICA member discovery requires vc[0] OrganizationCredential.');
|
|
196
|
+
}
|
|
197
|
+
if (input.attachments[0]?.role !== GaiaXCredentialAttachmentRole.Participant) {
|
|
198
|
+
throw new Error('ICA member discovery requires the Gaia-X participant VC-JWT as attachments[0].');
|
|
199
|
+
}
|
|
200
|
+
return {
|
|
201
|
+
id: requiredInput(input.id, 'member id'),
|
|
202
|
+
vc: [...input.vc],
|
|
203
|
+
did: { document: input.did.document, meta: { ...input.did.meta } },
|
|
204
|
+
attachments: [...input.attachments],
|
|
205
|
+
...(input.dcat ? { dcat: input.dcat } : {}),
|
|
206
|
+
...(input.meta ? { meta: input.meta } : {}),
|
|
207
|
+
};
|
|
208
|
+
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { type BundleEntry, type BundleJsonApi, type BundleRequest } from './bundle';
|
|
2
|
-
import {
|
|
2
|
+
import { type EmployeeClaims } from '../utils/employee';
|
|
3
3
|
import type { BundleEntryEditor } from '../utils/bundle-entry-editor';
|
|
4
4
|
import type { EmployeeEntryEditor } from '../utils/employee-entry-editor';
|
|
5
5
|
import type { VitalSignEntryEditor } from '../utils/vital-sign-entry-editor';
|
|
@@ -18,11 +18,21 @@ import type { CoverageEntryEditor } from '../utils/coverage-entry-editor';
|
|
|
18
18
|
import type { ImmunizationEntryEditor } from '../utils/immunization-entry-editor';
|
|
19
19
|
import type { ProcedureEntryEditor } from '../utils/procedure-entry-editor';
|
|
20
20
|
import type { DiagnosticReportEntryEditor } from '../utils/diagnostic-report-entry-editor';
|
|
21
|
-
|
|
21
|
+
import type { ConsentEntryEditor } from '../utils/consent-entry-editor';
|
|
22
|
+
import type { RelatedPersonEntryEditor } from '../utils/related-person-entry-editor';
|
|
23
|
+
/** Runtime-neutral business operations staged by `BundleEditor`. */
|
|
24
|
+
export declare const BundleOperations: Readonly<{
|
|
25
|
+
readonly create: "create";
|
|
26
|
+
readonly search: "search";
|
|
27
|
+
readonly disable: "disable";
|
|
28
|
+
readonly purge: "purge";
|
|
29
|
+
}>;
|
|
30
|
+
export type BundleOperation = (typeof BundleOperations)[keyof typeof BundleOperations];
|
|
22
31
|
/** Resource types that the shared bundle editors currently know how to open as typed entry editors. */
|
|
23
32
|
export declare const BundleEditableResourceTypes: Readonly<{
|
|
24
33
|
readonly employee: "Employee";
|
|
25
34
|
readonly consent: "Consent";
|
|
35
|
+
readonly relatedPerson: "RelatedPerson";
|
|
26
36
|
readonly observation: "Observation";
|
|
27
37
|
readonly vitalSign: "Observation";
|
|
28
38
|
readonly allergyIntolerance: "AllergyIntolerance";
|
|
@@ -86,4 +96,4 @@ export type BundleJsonApiShape = BundleJsonApi<BundleEntry>;
|
|
|
86
96
|
* resource type they requested, instead of falling back to the generic
|
|
87
97
|
* `BundleEntryEditor` API.
|
|
88
98
|
*/
|
|
89
|
-
export type ResourceTypeEntryEditor<T extends AllowedResourceType> = T extends typeof BundleEditableResourceTypes.employee ? EmployeeEntryEditor : T extends typeof BundleEditableResourceTypes.vitalSign ? VitalSignEntryEditor : T extends typeof BundleEditableResourceTypes.observation ? ObservationEntryEditor : T extends typeof BundleEditableResourceTypes.allergyIntolerance ? AllergyIntoleranceEntryEditor : T extends typeof BundleEditableResourceTypes.condition ? ConditionEntryEditor : T extends typeof BundleEditableResourceTypes.medicationStatement ? MedicationStatementEntryEditor : T extends typeof BundleEditableResourceTypes.documentReference ? DocumentReferenceEntryEditor : T extends typeof BundleEditableResourceTypes.carePlan ? CarePlanEntryEditor : T extends typeof BundleEditableResourceTypes.flag ? FlagEntryEditor : T extends typeof BundleEditableResourceTypes.clinicalImpression ? ClinicalImpressionEntryEditor : T extends typeof BundleEditableResourceTypes.device ? DeviceEntryEditor : T extends typeof BundleEditableResourceTypes.deviceUseStatement ? DeviceUseStatementEntryEditor : T extends typeof BundleEditableResourceTypes.encounter ? EncounterEntryEditor : T extends typeof BundleEditableResourceTypes.coverage ? CoverageEntryEditor : T extends typeof BundleEditableResourceTypes.immunization ? ImmunizationEntryEditor : T extends typeof BundleEditableResourceTypes.procedure ? ProcedureEntryEditor : T extends typeof BundleEditableResourceTypes.diagnosticReport ? DiagnosticReportEntryEditor : BundleEntryEditor;
|
|
99
|
+
export type ResourceTypeEntryEditor<T extends AllowedResourceType> = T extends typeof BundleEditableResourceTypes.employee ? EmployeeEntryEditor : T extends typeof BundleEditableResourceTypes.consent ? ConsentEntryEditor : T extends typeof BundleEditableResourceTypes.relatedPerson ? RelatedPersonEntryEditor : T extends typeof BundleEditableResourceTypes.vitalSign ? VitalSignEntryEditor : T extends typeof BundleEditableResourceTypes.observation ? ObservationEntryEditor : T extends typeof BundleEditableResourceTypes.allergyIntolerance ? AllergyIntoleranceEntryEditor : T extends typeof BundleEditableResourceTypes.condition ? ConditionEntryEditor : T extends typeof BundleEditableResourceTypes.medicationStatement ? MedicationStatementEntryEditor : T extends typeof BundleEditableResourceTypes.documentReference ? DocumentReferenceEntryEditor : T extends typeof BundleEditableResourceTypes.carePlan ? CarePlanEntryEditor : T extends typeof BundleEditableResourceTypes.flag ? FlagEntryEditor : T extends typeof BundleEditableResourceTypes.clinicalImpression ? ClinicalImpressionEntryEditor : T extends typeof BundleEditableResourceTypes.device ? DeviceEntryEditor : T extends typeof BundleEditableResourceTypes.deviceUseStatement ? DeviceUseStatementEntryEditor : T extends typeof BundleEditableResourceTypes.encounter ? EncounterEntryEditor : T extends typeof BundleEditableResourceTypes.coverage ? CoverageEntryEditor : T extends typeof BundleEditableResourceTypes.immunization ? ImmunizationEntryEditor : T extends typeof BundleEditableResourceTypes.procedure ? ProcedureEntryEditor : T extends typeof BundleEditableResourceTypes.diagnosticReport ? DiagnosticReportEntryEditor : BundleEntryEditor;
|
|
@@ -5,11 +5,19 @@
|
|
|
5
5
|
* - Do not move helper implementations or class logic here.
|
|
6
6
|
*/
|
|
7
7
|
import { ResourceTypesFhirR4 } from '../constants/fhir-resource-types.js';
|
|
8
|
-
import { EmployeeResourceTypes, } from '../utils/employee.js';
|
|
8
|
+
import { EmployeeBundleOperations, EmployeeResourceTypes, } from '../utils/employee.js';
|
|
9
|
+
/** Runtime-neutral business operations staged by `BundleEditor`. */
|
|
10
|
+
export const BundleOperations = Object.freeze({
|
|
11
|
+
create: EmployeeBundleOperations.create,
|
|
12
|
+
search: EmployeeBundleOperations.search,
|
|
13
|
+
disable: EmployeeBundleOperations.disable,
|
|
14
|
+
purge: EmployeeBundleOperations.purge,
|
|
15
|
+
});
|
|
9
16
|
/** Resource types that the shared bundle editors currently know how to open as typed entry editors. */
|
|
10
17
|
export const BundleEditableResourceTypes = Object.freeze({
|
|
11
18
|
employee: EmployeeResourceTypes.employee,
|
|
12
19
|
consent: ResourceTypesFhirR4.Consent,
|
|
20
|
+
relatedPerson: ResourceTypesFhirR4.RelatedPerson,
|
|
13
21
|
observation: ResourceTypesFhirR4.Observation,
|
|
14
22
|
vitalSign: ResourceTypesFhirR4.Observation,
|
|
15
23
|
allergyIntolerance: ResourceTypesFhirR4.AllergyIntolerance,
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
import type { DidCommAttachment } from './comm';
|
|
2
|
+
import type { DidDocument } from './did';
|
|
3
|
+
export type JsonObject = Record<string, unknown>;
|
|
4
|
+
/** Versioned Gaia-X profile targeted by the schema.org semantic projection. */
|
|
5
|
+
export declare const GaiaXProfile: Readonly<{
|
|
6
|
+
readonly Icam2511: "icam-25.11";
|
|
7
|
+
}>;
|
|
8
|
+
/** Media types used to transport signed Gaia-X credentials without decoding them. */
|
|
9
|
+
export declare const GaiaXCredentialMediaType: Readonly<{
|
|
10
|
+
readonly VcJwt: "application/vc+jwt";
|
|
11
|
+
}>;
|
|
12
|
+
/** DIDComm attachment format identifier used by the existing ICA contract. */
|
|
13
|
+
export declare const GaiaXCredentialAttachmentFormat: "vc+jwt";
|
|
14
|
+
/**
|
|
15
|
+
* Semantic roles for Gaia-X VC-JWT attachments in an ICA member aggregate.
|
|
16
|
+
*
|
|
17
|
+
* `Participant` is deliberately first in a member's `attachments[]`. It is the
|
|
18
|
+
* Gaia-X legal-entity projection corresponding to the same organization
|
|
19
|
+
* represented by the first schema.org `OrganizationCredential` in `vc[]`.
|
|
20
|
+
* They are different signed credentials and MUST NOT be treated as bytewise or
|
|
21
|
+
* schema-equivalent copies.
|
|
22
|
+
*/
|
|
23
|
+
export declare const GaiaXCredentialAttachmentRole: Readonly<{
|
|
24
|
+
readonly Participant: "gaia-x-participant-vc-jwt";
|
|
25
|
+
readonly LegalRegistrationNumber: "gaia-x-legal-registration-number-vc-jwt";
|
|
26
|
+
readonly TermsAndConditions: "gaia-x-terms-and-conditions-vc-jwt";
|
|
27
|
+
readonly ServiceOffering: "gaia-x-service-offering-vc-jwt";
|
|
28
|
+
}>;
|
|
29
|
+
export type GaiaXCredentialAttachmentRoleValue = typeof GaiaXCredentialAttachmentRole[keyof typeof GaiaXCredentialAttachmentRole];
|
|
30
|
+
/** DIDComm attachment containing the compact, already-signed Gaia-X VC-JWT. */
|
|
31
|
+
export interface GaiaXVcJwtAttachment extends DidCommAttachment {
|
|
32
|
+
media_type: typeof GaiaXCredentialMediaType.VcJwt;
|
|
33
|
+
format: typeof GaiaXCredentialAttachmentFormat;
|
|
34
|
+
role: GaiaXCredentialAttachmentRoleValue;
|
|
35
|
+
data: {
|
|
36
|
+
json: {
|
|
37
|
+
jwt: string;
|
|
38
|
+
};
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
/** Cache metadata kept next to a resolved artifact, never inside that artifact. */
|
|
42
|
+
export interface IcaDiscoveryArtifactMeta {
|
|
43
|
+
sourceUrl?: string;
|
|
44
|
+
fetchedAt: string;
|
|
45
|
+
sourceUpdatedAt?: string;
|
|
46
|
+
verifiedAt?: string;
|
|
47
|
+
expiresAt?: string;
|
|
48
|
+
etag?: string;
|
|
49
|
+
contentHash?: string;
|
|
50
|
+
}
|
|
51
|
+
/** Resolved DID document plus cache provenance, following the old document/meta split. */
|
|
52
|
+
export interface IcaDiscoveredDid {
|
|
53
|
+
document: DidDocument;
|
|
54
|
+
meta: IcaDiscoveryArtifactMeta;
|
|
55
|
+
}
|
|
56
|
+
/** Resolved DCAT document plus cache provenance. */
|
|
57
|
+
export interface IcaDiscoveredDcat {
|
|
58
|
+
document: JsonObject;
|
|
59
|
+
meta: IcaDiscoveryArtifactMeta;
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* One authorized ICA member's complete discovery record.
|
|
63
|
+
*
|
|
64
|
+
* The VAT is intentionally not repeated at this level. Consumers obtain legal
|
|
65
|
+
* identifiers from the authoritative schema.org OrganizationCredential in
|
|
66
|
+
* `vc[0].credentialSubject.taxID` (or the versioned equivalent). `attachments`
|
|
67
|
+
* contains exact Gaia-X VC-JWT artifacts, while `did.document` and
|
|
68
|
+
* `dcat.document` make discovery possible without a second host request.
|
|
69
|
+
*/
|
|
70
|
+
export interface IcaMemberDiscoveryData {
|
|
71
|
+
id: string;
|
|
72
|
+
vc: JsonObject[];
|
|
73
|
+
did: IcaDiscoveredDid;
|
|
74
|
+
attachments: GaiaXVcJwtAttachment[];
|
|
75
|
+
dcat?: IcaDiscoveredDcat;
|
|
76
|
+
meta?: {
|
|
77
|
+
assembledAt: string;
|
|
78
|
+
refreshAfter?: string;
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
/** DIDComm/JSON:API-compatible body returned by ICA member autodiscovery. */
|
|
82
|
+
export interface IcaMemberDiscoveryBody {
|
|
83
|
+
data: IcaMemberDiscoveryData[];
|
|
84
|
+
meta: {
|
|
85
|
+
generatedAt: string;
|
|
86
|
+
maxAgeSeconds?: number;
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
export interface GaiaXLegalPersonCredentialSubject extends JsonObject {
|
|
90
|
+
id: string;
|
|
91
|
+
type: 'gx:LegalPerson';
|
|
92
|
+
'gx:legalName': string;
|
|
93
|
+
'gx:legalRegistrationNumber': {
|
|
94
|
+
id: string;
|
|
95
|
+
};
|
|
96
|
+
'gx:headquarterAddress': {
|
|
97
|
+
'gx:countryCode': string;
|
|
98
|
+
};
|
|
99
|
+
'gx:legalAddress': {
|
|
100
|
+
'gx:countryCode': string;
|
|
101
|
+
};
|
|
102
|
+
'gx:website'?: string;
|
|
103
|
+
}
|
|
104
|
+
export interface GaiaXServiceOfferingCredentialSubject extends JsonObject {
|
|
105
|
+
id: string;
|
|
106
|
+
type: 'gx:ServiceOffering';
|
|
107
|
+
'gx:providedBy': {
|
|
108
|
+
id: string;
|
|
109
|
+
};
|
|
110
|
+
'gx:serviceOfferingTermsAndConditions': Array<{
|
|
111
|
+
'gx:url': string;
|
|
112
|
+
'gx:hash': string;
|
|
113
|
+
}>;
|
|
114
|
+
'gx:name'?: string;
|
|
115
|
+
'gx:description'?: string;
|
|
116
|
+
'gx:endpoint'?: Array<{
|
|
117
|
+
'gx:endpointURL': string;
|
|
118
|
+
}>;
|
|
119
|
+
}
|
|
120
|
+
/** Unsigned VC Data Model 2.0 draft. Signing and VC-JWT encoding belong to the GW. */
|
|
121
|
+
export interface GaiaXCredentialDraft<TSubject extends JsonObject> extends JsonObject {
|
|
122
|
+
'@context': ['https://www.w3.org/ns/credentials/v2'];
|
|
123
|
+
type: ['VerifiableCredential', 'LegalPerson' | 'ServiceOffering'];
|
|
124
|
+
id: string;
|
|
125
|
+
issuer: string;
|
|
126
|
+
validFrom: string;
|
|
127
|
+
credentialSubject: TSubject;
|
|
128
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
// Copyright 2026 Antifraud Services Inc. under the Apache License, Version 2.0.
|
|
2
|
+
/** Versioned Gaia-X profile targeted by the schema.org semantic projection. */
|
|
3
|
+
export const GaiaXProfile = Object.freeze({
|
|
4
|
+
Icam2511: 'icam-25.11',
|
|
5
|
+
});
|
|
6
|
+
/** Media types used to transport signed Gaia-X credentials without decoding them. */
|
|
7
|
+
export const GaiaXCredentialMediaType = Object.freeze({
|
|
8
|
+
VcJwt: 'application/vc+jwt',
|
|
9
|
+
});
|
|
10
|
+
/** DIDComm attachment format identifier used by the existing ICA contract. */
|
|
11
|
+
export const GaiaXCredentialAttachmentFormat = 'vc+jwt';
|
|
12
|
+
/**
|
|
13
|
+
* Semantic roles for Gaia-X VC-JWT attachments in an ICA member aggregate.
|
|
14
|
+
*
|
|
15
|
+
* `Participant` is deliberately first in a member's `attachments[]`. It is the
|
|
16
|
+
* Gaia-X legal-entity projection corresponding to the same organization
|
|
17
|
+
* represented by the first schema.org `OrganizationCredential` in `vc[]`.
|
|
18
|
+
* They are different signed credentials and MUST NOT be treated as bytewise or
|
|
19
|
+
* schema-equivalent copies.
|
|
20
|
+
*/
|
|
21
|
+
export const GaiaXCredentialAttachmentRole = Object.freeze({
|
|
22
|
+
Participant: 'gaia-x-participant-vc-jwt',
|
|
23
|
+
LegalRegistrationNumber: 'gaia-x-legal-registration-number-vc-jwt',
|
|
24
|
+
TermsAndConditions: 'gaia-x-terms-and-conditions-vc-jwt',
|
|
25
|
+
ServiceOffering: 'gaia-x-service-offering-vc-jwt',
|
|
26
|
+
});
|
package/dist/models/index.d.ts
CHANGED
|
@@ -21,6 +21,7 @@ export * from './dataspace-protocol';
|
|
|
21
21
|
export * from './device-license';
|
|
22
22
|
export * from './did';
|
|
23
23
|
export * from './fhir-documents';
|
|
24
|
+
export * from './gaia-x';
|
|
24
25
|
export * from './interoperable-claims';
|
|
25
26
|
export * from './indexing';
|
|
26
27
|
export * from './identity-bootstrap';
|
|
@@ -46,6 +47,7 @@ export * from './permission-templates';
|
|
|
46
47
|
export * from './resource-document';
|
|
47
48
|
export * from './relationship-access';
|
|
48
49
|
export * from './response';
|
|
50
|
+
export * from './subject-identifier-ledger';
|
|
49
51
|
export * from './urlPath';
|
|
50
52
|
export * from './verifiable-credential';
|
|
51
53
|
export * from './wallet';
|
package/dist/models/index.js
CHANGED
|
@@ -21,6 +21,7 @@ export * from './dataspace-protocol.js';
|
|
|
21
21
|
export * from './device-license.js';
|
|
22
22
|
export * from './did.js';
|
|
23
23
|
export * from './fhir-documents.js';
|
|
24
|
+
export * from './gaia-x.js';
|
|
24
25
|
export * from './interoperable-claims.js';
|
|
25
26
|
export * from './indexing.js';
|
|
26
27
|
export * from './identity-bootstrap.js';
|
|
@@ -46,6 +47,7 @@ export * from './permission-templates.js';
|
|
|
46
47
|
export * from './resource-document.js';
|
|
47
48
|
export * from './relationship-access.js';
|
|
48
49
|
export * from './response.js';
|
|
50
|
+
export * from './subject-identifier-ledger.js';
|
|
49
51
|
export * from './urlPath.js';
|
|
50
52
|
export * from './verifiable-credential.js';
|
|
51
53
|
export * from './wallet.js';
|
package/dist/models/jwe.d.ts
CHANGED
|
@@ -16,6 +16,12 @@ export interface ProtectedHeadersJWE {
|
|
|
16
16
|
kid?: string;
|
|
17
17
|
skid?: string;
|
|
18
18
|
zip?: string;
|
|
19
|
+
/** Versioned private profile while the JOSE ML-KEM binding remains an IETF draft. */
|
|
20
|
+
gdc_pq_profile?: 'confidential-pqc-v1';
|
|
21
|
+
/** Domain-separated purpose for storage envelopes. */
|
|
22
|
+
gdc_key_purpose?: 'document-at-rest';
|
|
23
|
+
/** Non-reversible binding to the profile/tenant storage owner. */
|
|
24
|
+
gdc_owner_binding?: string;
|
|
19
25
|
}
|
|
20
26
|
/**
|
|
21
27
|
* Unprotected headers that are not integrity protected.
|
|
@@ -33,6 +39,25 @@ export interface RecipientDataJWE {
|
|
|
33
39
|
kid: string;
|
|
34
40
|
};
|
|
35
41
|
}
|
|
42
|
+
/**
|
|
43
|
+
* Opaque recipient payload carried by JWE `encrypted_key` for
|
|
44
|
+
* `confidential-pqc-v1`.
|
|
45
|
+
*
|
|
46
|
+
* The content is encrypted once with a random AES-256-GCM CEK. ML-KEM derives
|
|
47
|
+
* a recipient KEK, and that KEK protects the CEK with AES-256-GCM. Keeping the
|
|
48
|
+
* CEK distinct from the KEM shared secret makes a future General JWE
|
|
49
|
+
* multi-recipient profile possible without re-encrypting the document.
|
|
50
|
+
*/
|
|
51
|
+
export interface MlKemWrappedCekV1 {
|
|
52
|
+
v: 'gdc-mlkem-cek-wrap-v1';
|
|
53
|
+
kem: 'ML-KEM-768';
|
|
54
|
+
kdf: 'HKDF-SHA-256';
|
|
55
|
+
wrap: 'A256GCM';
|
|
56
|
+
kemCiphertext: string;
|
|
57
|
+
iv: string;
|
|
58
|
+
ciphertext: string;
|
|
59
|
+
tag: string;
|
|
60
|
+
}
|
|
36
61
|
/**
|
|
37
62
|
* Represents the protected (integrity-protected) header of a JWE.
|
|
38
63
|
* These parameters are combined with the AAD (Additional Authenticated Data)
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/** Public provider pointer stored for one opaque subject-identifier asset. */
|
|
2
|
+
export type SubjectIdentifierProviderPointer = Readonly<{
|
|
3
|
+
identifier: Readonly<{
|
|
4
|
+
value: string;
|
|
5
|
+
}>;
|
|
6
|
+
/** Bare DNS domain: no URL scheme, path, DID or tenant identifier. */
|
|
7
|
+
url: string;
|
|
8
|
+
}>;
|
|
9
|
+
/** Ledger payload. It deliberately contains no subject DID or raw identifier. */
|
|
10
|
+
export type SubjectIdentifierLedgerPayload = Readonly<{
|
|
11
|
+
provider: SubjectIdentifierProviderPointer;
|
|
12
|
+
}>;
|
|
13
|
+
/** One individual/animal bundle entry expanded into one write per `sameAs` alias. */
|
|
14
|
+
export type SubjectIdentifierLedgerBundleEntry = Readonly<{
|
|
15
|
+
sameAs: string | readonly string[];
|
|
16
|
+
}>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -50,6 +50,15 @@ export declare class BundleEditor {
|
|
|
50
50
|
setBundleType(type: BundleType): this;
|
|
51
51
|
/** Returns the declared target bundle shape. */
|
|
52
52
|
getBundleType(): BundleType;
|
|
53
|
+
/**
|
|
54
|
+
* Replaces staged entries with one previously materialized JSON-API-like
|
|
55
|
+
* Bundle snapshot so a later UI session can reopen, edit or append entries.
|
|
56
|
+
*
|
|
57
|
+
* This is an in-memory authoring operation only. It does not imply that the
|
|
58
|
+
* supplied Bundle came from authoritative GW readback and it performs no
|
|
59
|
+
* Communication wrapping, submission or polling.
|
|
60
|
+
*/
|
|
61
|
+
setBundle(bundle: BundleJsonApi<BundleEntry>): this;
|
|
53
62
|
setCompositionIdentifier(identifier?: string | null): this;
|
|
54
63
|
/** Returns the normalized `Composition.identifier` staged for the future document root. */
|
|
55
64
|
getCompositionIdentifier(): string | undefined;
|
|
@@ -77,6 +77,52 @@ export class BundleEditor {
|
|
|
77
77
|
getBundleType() {
|
|
78
78
|
return this.bundleType;
|
|
79
79
|
}
|
|
80
|
+
/**
|
|
81
|
+
* Replaces staged entries with one previously materialized JSON-API-like
|
|
82
|
+
* Bundle snapshot so a later UI session can reopen, edit or append entries.
|
|
83
|
+
*
|
|
84
|
+
* This is an in-memory authoring operation only. It does not imply that the
|
|
85
|
+
* supplied Bundle came from authoritative GW readback and it performs no
|
|
86
|
+
* Communication wrapping, submission or polling.
|
|
87
|
+
*/
|
|
88
|
+
setBundle(bundle) {
|
|
89
|
+
if (!bundle || bundle.resourceType !== ResourceTypesFhirR4.Bundle || !Array.isArray(bundle.data)) {
|
|
90
|
+
throw new TypeError('BundleEditor.setBundle requires a Bundle with data[].');
|
|
91
|
+
}
|
|
92
|
+
if (!Object.values(BundleTypes).includes(bundle.type)) {
|
|
93
|
+
throw new TypeError(`BundleEditor.setBundle does not support Bundle.type: ${String(bundle.type || '')}`);
|
|
94
|
+
}
|
|
95
|
+
const operation = this.requireBundleOperation();
|
|
96
|
+
const nextEntries = bundle.data.map((source, index) => {
|
|
97
|
+
const resource = source?.resource;
|
|
98
|
+
const resourceType = normalizeOptionalIdentifier(resource?.resourceType);
|
|
99
|
+
if (!resource || !resourceType) {
|
|
100
|
+
throw new TypeError(`BundleEditor.setBundle requires data[${index}].resource.resourceType.`);
|
|
101
|
+
}
|
|
102
|
+
if (bundle.type !== BundleTypes.document
|
|
103
|
+
&& this.allowedResourceType
|
|
104
|
+
&& resourceType !== this.allowedResourceType) {
|
|
105
|
+
throw new Error(`BundleEditor cannot mix resource types in ${bundle.type} mode: ${this.allowedResourceType} vs ${resourceType}`);
|
|
106
|
+
}
|
|
107
|
+
const cloned = cloneEntry(source);
|
|
108
|
+
return {
|
|
109
|
+
type: normalizeOptionalIdentifier(cloned.type) || inferGenericEntryType(resourceType, operation),
|
|
110
|
+
request: cloned.request || { method: resolveRequestMethodForOperation(operation) },
|
|
111
|
+
...(cloned.fullUrl ? { fullUrl: cloned.fullUrl } : {}),
|
|
112
|
+
resource: {
|
|
113
|
+
...cloned.resource,
|
|
114
|
+
resourceType,
|
|
115
|
+
meta: {
|
|
116
|
+
...(cloned.resource?.meta || {}),
|
|
117
|
+
claims: { ...(cloned.resource?.meta?.claims || {}) },
|
|
118
|
+
},
|
|
119
|
+
},
|
|
120
|
+
};
|
|
121
|
+
});
|
|
122
|
+
this.bundleType = bundle.type;
|
|
123
|
+
this.entries.splice(0, this.entries.length, ...nextEntries);
|
|
124
|
+
return this;
|
|
125
|
+
}
|
|
80
126
|
setCompositionIdentifier(identifier) {
|
|
81
127
|
return this.setCompositionScalarClaim(CompositionClaim.Identifier, identifier);
|
|
82
128
|
}
|
|
@@ -19,3 +19,5 @@ export * from './immunization-entry-editor';
|
|
|
19
19
|
export * from './procedure-entry-editor';
|
|
20
20
|
export * from './diagnostic-report-entry-editor';
|
|
21
21
|
export * from './employee-entry-editor';
|
|
22
|
+
export * from './consent-entry-editor';
|
|
23
|
+
export * from './related-person-entry-editor';
|
|
@@ -19,3 +19,5 @@ export * from './immunization-entry-editor.js';
|
|
|
19
19
|
export * from './procedure-entry-editor.js';
|
|
20
20
|
export * from './diagnostic-report-entry-editor.js';
|
|
21
21
|
export * from './employee-entry-editor.js';
|
|
22
|
+
export * from './consent-entry-editor.js';
|
|
23
|
+
export * from './related-person-entry-editor.js';
|
|
@@ -17,6 +17,8 @@ import type { MedicationStatementEntryEditor } from './medication-statement-entr
|
|
|
17
17
|
import type { ObservationEntryEditor } from './observation-entry-editor';
|
|
18
18
|
import type { ProcedureEntryEditor } from './procedure-entry-editor';
|
|
19
19
|
import type { VitalSignEntryEditor } from './vital-sign-entry-editor';
|
|
20
|
+
import type { ConsentEntryEditor } from './consent-entry-editor';
|
|
21
|
+
import type { RelatedPersonEntryEditor } from './related-person-entry-editor';
|
|
20
22
|
import { type EmployeeClaims } from './employee';
|
|
21
23
|
export declare class BundleEntryEditor {
|
|
22
24
|
protected readonly bundleEditor: BundleEditor;
|
|
@@ -31,6 +33,10 @@ export declare class BundleEntryEditor {
|
|
|
31
33
|
asResourceType<T extends AllowedResourceType>(resourceType: T): ResourceTypeEntryEditor<T>;
|
|
32
34
|
/** Opens the current entry as one employee-specific resource editor. */
|
|
33
35
|
asEmployee(): EmployeeEntryEditor;
|
|
36
|
+
/** Opens the current entry as one Consent permission editor. */
|
|
37
|
+
asConsent(): ConsentEntryEditor;
|
|
38
|
+
/** Opens the current entry as one RelatedPerson/contact editor. */
|
|
39
|
+
asRelatedPerson(): RelatedPersonEntryEditor;
|
|
34
40
|
/** Opens the current entry as one vital-sign-specific Observation editor. */
|
|
35
41
|
asVitalSign(): VitalSignEntryEditor;
|
|
36
42
|
/** Opens the current entry as one general Observation editor. */
|
|
@@ -27,6 +27,10 @@ export class BundleEntryEditor {
|
|
|
27
27
|
switch (normalized) {
|
|
28
28
|
case BundleEditableResourceTypes.employee:
|
|
29
29
|
return this.asEmployee();
|
|
30
|
+
case BundleEditableResourceTypes.consent:
|
|
31
|
+
return this.asConsent();
|
|
32
|
+
case BundleEditableResourceTypes.relatedPerson:
|
|
33
|
+
return this.asRelatedPerson();
|
|
30
34
|
case BundleEditableResourceTypes.vitalSign:
|
|
31
35
|
return this.asVitalSign();
|
|
32
36
|
case BundleEditableResourceTypes.observation:
|
|
@@ -71,6 +75,22 @@ export class BundleEntryEditor {
|
|
|
71
75
|
}
|
|
72
76
|
return createRegisteredBundleEntryEditor(BundleEditableResourceTypes.employee, this.bundleEditor, this.entryIndex);
|
|
73
77
|
}
|
|
78
|
+
/** Opens the current entry as one Consent permission editor. */
|
|
79
|
+
asConsent() {
|
|
80
|
+
const entry = this.getMutableEntry();
|
|
81
|
+
if (entry.resource?.resourceType !== ResourceTypesFhirR4.Consent) {
|
|
82
|
+
throw new Error(`BundleEntryEditor cannot open this entry as Consent: ${String(entry.resource?.resourceType || '')}`);
|
|
83
|
+
}
|
|
84
|
+
return createRegisteredBundleEntryEditor(BundleEditableResourceTypes.consent, this.bundleEditor, this.entryIndex);
|
|
85
|
+
}
|
|
86
|
+
/** Opens the current entry as one RelatedPerson/contact editor. */
|
|
87
|
+
asRelatedPerson() {
|
|
88
|
+
const entry = this.getMutableEntry();
|
|
89
|
+
if (entry.resource?.resourceType !== ResourceTypesFhirR4.RelatedPerson) {
|
|
90
|
+
throw new Error(`BundleEntryEditor cannot open this entry as RelatedPerson: ${String(entry.resource?.resourceType || '')}`);
|
|
91
|
+
}
|
|
92
|
+
return createRegisteredBundleEntryEditor(BundleEditableResourceTypes.relatedPerson, this.bundleEditor, this.entryIndex);
|
|
93
|
+
}
|
|
74
94
|
/** Opens the current entry as one vital-sign-specific Observation editor. */
|
|
75
95
|
asVitalSign() {
|
|
76
96
|
const entry = this.getMutableEntry();
|