gdc-common-utils-ts 2.0.18 → 2.1.0

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 (57) hide show
  1. package/README.md +0 -1
  2. package/dist/examples/bundle-didcomm-payload.d.ts +11 -0
  3. package/dist/examples/bundle-didcomm-payload.js +13 -0
  4. package/dist/examples/communication-attached-bundle-session.js +2 -1
  5. package/dist/examples/communication-didcomm-payload.d.ts +35 -0
  6. package/dist/examples/communication-didcomm-payload.js +38 -0
  7. package/dist/examples/index.d.ts +4 -0
  8. package/dist/examples/index.js +4 -0
  9. package/dist/examples/profile-manager-mem.d.ts +45 -0
  10. package/dist/examples/profile-manager-mem.js +29 -0
  11. package/dist/examples/shared.d.ts +1 -0
  12. package/dist/examples/shared.js +1 -0
  13. package/dist/examples/wallet-mem.d.ts +38 -0
  14. package/dist/examples/wallet-mem.js +40 -0
  15. package/dist/index.d.ts +1 -0
  16. package/dist/index.js +1 -0
  17. package/dist/interfaces/IProfileOutboxRepository.d.ts +36 -0
  18. package/dist/interfaces/IProfileOutboxRepository.js +2 -0
  19. package/dist/interfaces/IWallet.d.ts +74 -0
  20. package/dist/interfaces/IWallet.js +2 -0
  21. package/dist/interfaces/IWalletQueue.d.ts +30 -0
  22. package/dist/interfaces/IWalletQueue.js +2 -0
  23. package/dist/interfaces/index.d.ts +8 -0
  24. package/dist/interfaces/index.js +8 -0
  25. package/dist/models/communication-attached-bundle-session.d.ts +193 -0
  26. package/dist/models/communication-attached-bundle-session.js +34 -0
  27. package/dist/models/index.d.ts +3 -0
  28. package/dist/models/index.js +3 -0
  29. package/dist/models/interoperable-claims/diagnostic-report-claims.d.ts +1 -2
  30. package/dist/models/interoperable-claims/diagnostic-report-claims.js +1 -2
  31. package/dist/models/profile-manager.d.ts +85 -0
  32. package/dist/models/profile-manager.js +2 -0
  33. package/dist/models/wallet.d.ts +59 -0
  34. package/dist/models/wallet.js +22 -0
  35. package/dist/utils/backend-message-manager-mem.d.ts +67 -0
  36. package/dist/utils/backend-message-manager-mem.js +227 -0
  37. package/dist/utils/bundle-didcomm-payload.d.ts +29 -0
  38. package/dist/utils/bundle-didcomm-payload.js +48 -0
  39. package/dist/utils/communication-attached-bundle-session-helpers.d.ts +54 -0
  40. package/dist/utils/communication-attached-bundle-session-helpers.js +517 -0
  41. package/dist/utils/communication-attached-bundle-session.d.ts +59 -302
  42. package/dist/utils/communication-attached-bundle-session.js +114 -839
  43. package/dist/utils/communication-consent-access-editor.d.ts +85 -0
  44. package/dist/utils/communication-consent-access-editor.js +244 -0
  45. package/dist/utils/communication-didcomm-payload.d.ts +33 -0
  46. package/dist/utils/communication-didcomm-payload.js +75 -0
  47. package/dist/utils/index.d.ts +8 -0
  48. package/dist/utils/index.js +8 -0
  49. package/dist/utils/profile-manager-mem.d.ts +69 -0
  50. package/dist/utils/profile-manager-mem.js +79 -0
  51. package/dist/utils/profile-outbox-memory-repository.d.ts +34 -0
  52. package/dist/utils/profile-outbox-memory-repository.js +57 -0
  53. package/dist/utils/wallet-mem.d.ts +93 -0
  54. package/dist/utils/wallet-mem.js +277 -0
  55. package/dist/utils/wallet-memory-queue.d.ts +32 -0
  56. package/dist/utils/wallet-memory-queue.js +82 -0
  57. package/package.json +1 -1
@@ -0,0 +1,85 @@
1
+ import { type HealthcareActorRoleDescriptor, type HealthcareSectionDescriptor } from '../constants/healthcare';
2
+ import type { DataspaceSector } from '../constants/sectors';
3
+ import type { CommunicationAttachedBundleSessionOptions, ConsentEditorClassifiedActors, ConsentEditorClassifiedPurpose, ConsentEditorClassifiedRoles, ConsentEditorClassifiedTarget, ConsentViewModel } from '../models/communication-attached-bundle-session';
4
+ import type { ConsentDuplicateRuleConflict } from './consent-duplicate-rules';
5
+ import { CommunicationAttachedBundleSession } from './communication-attached-bundle-session';
6
+ /**
7
+ * High-level consent-access editor alias for onboarding and app-facing code.
8
+ *
9
+ * This keeps the business intent explicit for developers who are editing
10
+ * Consent access rules inside a Communication-carried bundle and should not
11
+ * need to start from the lower-level generic session name.
12
+ */
13
+ export declare class ConsentAccessEditor extends CommunicationAttachedBundleSession {
14
+ /** Returns duplicate atomic consent-rule conflicts across the current bundle. */
15
+ getConsentRuleDuplicateConflicts(): ConsentDuplicateRuleConflict[];
16
+ /** Returns duplicate atomic consent-rule conflicts affecting the active Consent entry. */
17
+ getActiveConsentRuleDuplicateConflicts(): ConsentDuplicateRuleConflict[];
18
+ /** Returns one frontend-facing editable view model for the active Consent entry. */
19
+ getConsentViewModel(): ConsentViewModel;
20
+ /** Applies one frontend-facing editable view model back into the active Consent entry. */
21
+ applyConsentViewModel(viewModel: ConsentViewModel): this;
22
+ /** Returns the canonical permit/deny decision from the active Consent entry. */
23
+ getDecision(): string;
24
+ /** @deprecated Use `getDecision()`. */
25
+ getPermit(): string;
26
+ /** Returns target classification derived from the current consent claim contract. */
27
+ getTargetsClassified(): ConsentEditorClassifiedTarget[];
28
+ getCoreSectionOptions(): readonly ConsentEditorClassifiedTarget[];
29
+ getCoreSectionCatalog(): Readonly<Record<string, HealthcareSectionDescriptor>>;
30
+ getKindOfDocumentOptions(): readonly ConsentEditorClassifiedTarget[];
31
+ getKindOfDocumentCatalog(): Readonly<Record<string, HealthcareSectionDescriptor>>;
32
+ getTypeOfServiceOptions(): readonly ConsentEditorClassifiedTarget[];
33
+ getTypeOfServiceCatalog(): Readonly<Record<string, HealthcareSectionDescriptor>>;
34
+ getSubjectMatterDomainOptions(): readonly ConsentEditorClassifiedTarget[];
35
+ getSubjectMatterDomainCatalog(): Readonly<Record<string, HealthcareSectionDescriptor>>;
36
+ getResourceTypeOptions(): readonly ConsentEditorClassifiedTarget[];
37
+ getResourceTypeCatalog(): readonly string[];
38
+ getAvailableProfessionalRolesBySector(sector: DataspaceSector): Readonly<Record<string, HealthcareActorRoleDescriptor>>;
39
+ getAvailableRelationshipRoles(): Readonly<Record<string, HealthcareActorRoleDescriptor>>;
40
+ getSelectedCoreSections(): string[];
41
+ getSelectedKindOfDocuments(): string[];
42
+ getSelectedTypeOfServices(): string[];
43
+ getSelectedSubjectMatterDomains(): string[];
44
+ getSelectedResourceTypes(): string[];
45
+ setSelectedCoreSections(codes: readonly string[]): this;
46
+ setSelectedKindOfDocuments(codes: readonly string[]): this;
47
+ setSelectedTypeOfServices(codes: readonly string[]): this;
48
+ setSelectedSubjectMatterDomains(codes: readonly string[]): this;
49
+ setSelectedResourceTypes(codes: readonly string[]): this;
50
+ addCoreSections(codes: readonly string[]): this;
51
+ removeCoreSections(codes: readonly string[]): this;
52
+ addKindOfDocuments(codes: readonly string[]): this;
53
+ removeKindOfDocuments(codes: readonly string[]): this;
54
+ addTypeOfServices(codes: readonly string[]): this;
55
+ removeTypeOfServices(codes: readonly string[]): this;
56
+ addSubjectMatterDomains(codes: readonly string[]): this;
57
+ removeSubjectMatterDomains(codes: readonly string[]): this;
58
+ addResourceTypes(codes: readonly string[]): this;
59
+ removeResourceTypes(codes: readonly string[]): this;
60
+ getPurposesClassified(): ConsentEditorClassifiedPurpose[];
61
+ getSelectedPurposes(): string[];
62
+ setSelectedPurposes(codes: readonly string[]): this;
63
+ addPurposes(codes: readonly string[]): this;
64
+ removePurposes(codes: readonly string[]): this;
65
+ getRolesClassified(): ConsentEditorClassifiedRoles;
66
+ getSelectedRoles(): string[];
67
+ setSelectedRoles(codes: readonly string[]): this;
68
+ addRoles(codes: readonly string[]): this;
69
+ removeRoles(codes: readonly string[]): this;
70
+ getActorsClassified(): ConsentEditorClassifiedActors;
71
+ private getSelectedSectionCodesByFamily;
72
+ private setSelectedSectionCodesByFamily;
73
+ private addSectionCodesByFamily;
74
+ private removeSectionCodesByFamily;
75
+ private setActiveEntryClaimList;
76
+ private addActiveEntryClaimList;
77
+ private removeActiveEntryClaimList;
78
+ }
79
+ /**
80
+ * High-level factory for consent-access editing.
81
+ *
82
+ * Prefer this name in onboarding docs when the developer intent is:
83
+ * "edit a Consent access bundle carried by a Communication".
84
+ */
85
+ export declare function createConsentAccessEditor(options?: CommunicationAttachedBundleSessionOptions): ConsentAccessEditor;
@@ -0,0 +1,244 @@
1
+ // Copyright 2026 Conectate Soluciones y Aplicaciones SL under the Apache License, Version 2.0.
2
+ import { ResourceTypesFhirR4 } from '../constants/fhir-resource-types.js';
3
+ import { getHealthcareProfessionalRolesBySector, getHealthcareRolesByFamily, getHealthcareSectionsByFamily, getHealthcareSectionFamilyByCode, HealthcareRoleFamilies, HealthcareCanonicalSectionFamilies, } from '../constants/healthcare.js';
4
+ import { ClaimConsent } from '../models/consent-rule.js';
5
+ import { ConsentEditorScopeCodes, ConsentEditorTargetKinds, } from '../models/communication-attached-bundle-session.js';
6
+ import { detectDuplicateConsentRuleConflicts } from './consent-duplicate-rules.js';
7
+ import { CommunicationAttachedBundleSession } from './communication-attached-bundle-session.js';
8
+ import { asTrimmedString, buildClassifiedConsentTarget, buildConsentViewModel, buildSectionCatalogOptions, classifyConsentActors, classifyConsentPurposes, classifyConsentRoles, classifyConsentTargetsFromClaims, CSV_SEPARATOR, flattenClassifiedActors, flattenClassifiedRoles, flattenClassifiedTargets, normalizeCsvValues, splitCsv, } from './communication-attached-bundle-session-helpers.js';
9
+ /**
10
+ * High-level consent-access editor alias for onboarding and app-facing code.
11
+ *
12
+ * This keeps the business intent explicit for developers who are editing
13
+ * Consent access rules inside a Communication-carried bundle and should not
14
+ * need to start from the lower-level generic session name.
15
+ */
16
+ export class ConsentAccessEditor extends CommunicationAttachedBundleSession {
17
+ /** Returns duplicate atomic consent-rule conflicts across the current bundle. */
18
+ getConsentRuleDuplicateConflicts() {
19
+ return detectDuplicateConsentRuleConflicts(this.getBundleInMemory().data);
20
+ }
21
+ /** Returns duplicate atomic consent-rule conflicts affecting the active Consent entry. */
22
+ getActiveConsentRuleDuplicateConflicts() {
23
+ const activeEntryIndex = this.getActiveEntryIndex();
24
+ if (activeEntryIndex === null) {
25
+ return [];
26
+ }
27
+ return this.getConsentRuleDuplicateConflicts()
28
+ .filter((conflict) => conflict.affectedEntries.some((entry) => entry.entryIndex === activeEntryIndex));
29
+ }
30
+ /** Returns one frontend-facing editable view model for the active Consent entry. */
31
+ getConsentViewModel() {
32
+ return buildConsentViewModel(this.getActiveEntry(), this.getDecision(), this.getActorsClassified(), this.getRolesClassified(), this.getPurposesClassified(), this.getTargetsClassified());
33
+ }
34
+ /** Applies one frontend-facing editable view model back into the active Consent entry. */
35
+ applyConsentViewModel(viewModel) {
36
+ this.setActiveEntryClaim(ClaimConsent.identifier, viewModel.identifier);
37
+ this.setActiveEntryClaim(ClaimConsent.subject, viewModel.subject);
38
+ this.setActiveEntryClaim(ClaimConsent.decision, viewModel.decision);
39
+ this.setActiveEntryClaimList(ClaimConsent.actorIdentifier, flattenClassifiedActors(viewModel.classifiedActors));
40
+ this.setSelectedRoles(flattenClassifiedRoles(viewModel.classifiedRoles));
41
+ this.setSelectedPurposes(viewModel.classifiedPurposes.map((purpose) => purpose.code));
42
+ const flattenedTargets = flattenClassifiedTargets(viewModel.classifiedTargets);
43
+ this.setSelectedCoreSections(flattenedTargets.coreSections);
44
+ this.setSelectedKindOfDocuments(flattenedTargets.kindOfDocuments);
45
+ this.setSelectedTypeOfServices(flattenedTargets.typeOfServices);
46
+ this.setSelectedSubjectMatterDomains(flattenedTargets.subjectMatterDomains);
47
+ this.setSelectedResourceTypes(flattenedTargets.resourceTypes);
48
+ return this;
49
+ }
50
+ /** Returns the canonical permit/deny decision from the active Consent entry. */
51
+ getDecision() {
52
+ return asTrimmedString(this.getActiveEntryClaim(ClaimConsent.decision));
53
+ }
54
+ /** @deprecated Use `getDecision()`. */
55
+ getPermit() {
56
+ return this.getDecision();
57
+ }
58
+ /** Returns target classification derived from the current consent claim contract. */
59
+ getTargetsClassified() {
60
+ return classifyConsentTargetsFromClaims({
61
+ ...(this.getActiveEntry()?.resource?.meta?.claims || {}),
62
+ });
63
+ }
64
+ getCoreSectionOptions() {
65
+ return buildSectionCatalogOptions(HealthcareCanonicalSectionFamilies.CoreSection);
66
+ }
67
+ getCoreSectionCatalog() {
68
+ return getHealthcareSectionsByFamily(HealthcareCanonicalSectionFamilies.CoreSection);
69
+ }
70
+ getKindOfDocumentOptions() {
71
+ return buildSectionCatalogOptions(HealthcareCanonicalSectionFamilies.KindOfDocument);
72
+ }
73
+ getKindOfDocumentCatalog() {
74
+ return getHealthcareSectionsByFamily(HealthcareCanonicalSectionFamilies.KindOfDocument);
75
+ }
76
+ getTypeOfServiceOptions() {
77
+ return buildSectionCatalogOptions(HealthcareCanonicalSectionFamilies.TypeOfService);
78
+ }
79
+ getTypeOfServiceCatalog() {
80
+ return getHealthcareSectionsByFamily(HealthcareCanonicalSectionFamilies.TypeOfService);
81
+ }
82
+ getSubjectMatterDomainOptions() {
83
+ return buildSectionCatalogOptions(HealthcareCanonicalSectionFamilies.SubjectMatterDomain);
84
+ }
85
+ getSubjectMatterDomainCatalog() {
86
+ return getHealthcareSectionsByFamily(HealthcareCanonicalSectionFamilies.SubjectMatterDomain);
87
+ }
88
+ getResourceTypeOptions() {
89
+ return this.getSelectedResourceTypes().map((code) => buildClassifiedConsentTarget(ConsentEditorTargetKinds.ResourceType, code, [ConsentEditorScopeCodes.Read]));
90
+ }
91
+ getResourceTypeCatalog() {
92
+ return Object.values(ResourceTypesFhirR4).filter((resourceType) => resourceType !== ResourceTypesFhirR4.Bundle);
93
+ }
94
+ getAvailableProfessionalRolesBySector(sector) {
95
+ return getHealthcareProfessionalRolesBySector(sector);
96
+ }
97
+ getAvailableRelationshipRoles() {
98
+ return getHealthcareRolesByFamily(HealthcareRoleFamilies.PersonalRelationshipHl7);
99
+ }
100
+ getSelectedCoreSections() {
101
+ return this.getSelectedSectionCodesByFamily(ClaimConsent.action, HealthcareCanonicalSectionFamilies.CoreSection);
102
+ }
103
+ getSelectedKindOfDocuments() {
104
+ return splitCsv(this.getActiveEntryClaim(ClaimConsent.category));
105
+ }
106
+ getSelectedTypeOfServices() {
107
+ return this.getSelectedSectionCodesByFamily(ClaimConsent.action, HealthcareCanonicalSectionFamilies.TypeOfService);
108
+ }
109
+ getSelectedSubjectMatterDomains() {
110
+ return this.getSelectedSectionCodesByFamily(ClaimConsent.action, HealthcareCanonicalSectionFamilies.SubjectMatterDomain);
111
+ }
112
+ getSelectedResourceTypes() {
113
+ return splitCsv(this.getActiveEntryClaim(ClaimConsent.resourceType));
114
+ }
115
+ setSelectedCoreSections(codes) {
116
+ return this.setSelectedSectionCodesByFamily(ClaimConsent.action, HealthcareCanonicalSectionFamilies.CoreSection, codes);
117
+ }
118
+ setSelectedKindOfDocuments(codes) {
119
+ return this.setActiveEntryClaimList(ClaimConsent.category, codes);
120
+ }
121
+ setSelectedTypeOfServices(codes) {
122
+ return this.setSelectedSectionCodesByFamily(ClaimConsent.action, HealthcareCanonicalSectionFamilies.TypeOfService, codes);
123
+ }
124
+ setSelectedSubjectMatterDomains(codes) {
125
+ return this.setSelectedSectionCodesByFamily(ClaimConsent.action, HealthcareCanonicalSectionFamilies.SubjectMatterDomain, codes);
126
+ }
127
+ setSelectedResourceTypes(codes) {
128
+ return this.setActiveEntryClaimList(ClaimConsent.resourceType, codes);
129
+ }
130
+ addCoreSections(codes) {
131
+ return this.addSectionCodesByFamily(ClaimConsent.action, HealthcareCanonicalSectionFamilies.CoreSection, codes);
132
+ }
133
+ removeCoreSections(codes) {
134
+ return this.removeSectionCodesByFamily(ClaimConsent.action, HealthcareCanonicalSectionFamilies.CoreSection, codes);
135
+ }
136
+ addKindOfDocuments(codes) {
137
+ return this.addActiveEntryClaimList(ClaimConsent.category, codes);
138
+ }
139
+ removeKindOfDocuments(codes) {
140
+ return this.removeActiveEntryClaimList(ClaimConsent.category, codes);
141
+ }
142
+ addTypeOfServices(codes) {
143
+ return this.addSectionCodesByFamily(ClaimConsent.action, HealthcareCanonicalSectionFamilies.TypeOfService, codes);
144
+ }
145
+ removeTypeOfServices(codes) {
146
+ return this.removeSectionCodesByFamily(ClaimConsent.action, HealthcareCanonicalSectionFamilies.TypeOfService, codes);
147
+ }
148
+ addSubjectMatterDomains(codes) {
149
+ return this.addSectionCodesByFamily(ClaimConsent.action, HealthcareCanonicalSectionFamilies.SubjectMatterDomain, codes);
150
+ }
151
+ removeSubjectMatterDomains(codes) {
152
+ return this.removeSectionCodesByFamily(ClaimConsent.action, HealthcareCanonicalSectionFamilies.SubjectMatterDomain, codes);
153
+ }
154
+ addResourceTypes(codes) {
155
+ return this.addActiveEntryClaimList(ClaimConsent.resourceType, codes);
156
+ }
157
+ removeResourceTypes(codes) {
158
+ return this.removeActiveEntryClaimList(ClaimConsent.resourceType, codes);
159
+ }
160
+ getPurposesClassified() {
161
+ return classifyConsentPurposes(this.getSelectedPurposes());
162
+ }
163
+ getSelectedPurposes() {
164
+ return splitCsv(this.getActiveEntryClaim(ClaimConsent.purpose));
165
+ }
166
+ setSelectedPurposes(codes) {
167
+ return this.setActiveEntryClaimList(ClaimConsent.purpose, codes);
168
+ }
169
+ addPurposes(codes) {
170
+ return this.addActiveEntryClaimList(ClaimConsent.purpose, codes);
171
+ }
172
+ removePurposes(codes) {
173
+ return this.removeActiveEntryClaimList(ClaimConsent.purpose, codes);
174
+ }
175
+ getRolesClassified() {
176
+ return classifyConsentRoles(this.getSelectedRoles());
177
+ }
178
+ getSelectedRoles() {
179
+ return splitCsv(this.getActiveEntryClaim(ClaimConsent.actorRole));
180
+ }
181
+ setSelectedRoles(codes) {
182
+ return this.setActiveEntryClaimList(ClaimConsent.actorRole, codes);
183
+ }
184
+ addRoles(codes) {
185
+ return this.addActiveEntryClaimList(ClaimConsent.actorRole, codes);
186
+ }
187
+ removeRoles(codes) {
188
+ return this.removeActiveEntryClaimList(ClaimConsent.actorRole, codes);
189
+ }
190
+ getActorsClassified() {
191
+ const claims = {
192
+ ...(this.getActiveEntry()?.resource?.meta?.claims || {}),
193
+ };
194
+ return classifyConsentActors(splitCsv(claims[ClaimConsent.actorIdentifier]), splitCsv(claims[ClaimConsent.actorRole])[0] || '');
195
+ }
196
+ getSelectedSectionCodesByFamily(claimKey, family) {
197
+ return splitCsv(this.getActiveEntryClaim(claimKey))
198
+ .filter((code) => getHealthcareSectionFamilyByCode(code) === family);
199
+ }
200
+ setSelectedSectionCodesByFamily(claimKey, family, codes) {
201
+ const preserved = splitCsv(this.getActiveEntryClaim(claimKey))
202
+ .filter((code) => getHealthcareSectionFamilyByCode(code) !== family);
203
+ return this.setActiveEntryClaimList(claimKey, [...preserved, ...codes]);
204
+ }
205
+ addSectionCodesByFamily(claimKey, family, codes) {
206
+ const next = [...this.getSelectedSectionCodesByFamily(claimKey, family), ...codes];
207
+ return this.setSelectedSectionCodesByFamily(claimKey, family, next);
208
+ }
209
+ removeSectionCodesByFamily(claimKey, family, codes) {
210
+ const codesToRemove = new Set(normalizeCsvValues(codes));
211
+ const next = this.getSelectedSectionCodesByFamily(claimKey, family)
212
+ .filter((code) => !codesToRemove.has(code));
213
+ return this.setSelectedSectionCodesByFamily(claimKey, family, next);
214
+ }
215
+ setActiveEntryClaimList(key, values) {
216
+ const normalized = normalizeCsvValues(values);
217
+ if (normalized.length === 0) {
218
+ return this.removeActiveEntryClaim(key);
219
+ }
220
+ return this.setActiveEntryClaim(key, normalized.join(CSV_SEPARATOR));
221
+ }
222
+ addActiveEntryClaimList(key, values) {
223
+ const next = normalizeCsvValues([
224
+ ...splitCsv(this.getActiveEntryClaim(key)),
225
+ ...values,
226
+ ]);
227
+ return this.setActiveEntryClaimList(key, next);
228
+ }
229
+ removeActiveEntryClaimList(key, values) {
230
+ const valuesToRemove = new Set(normalizeCsvValues(values));
231
+ const next = splitCsv(this.getActiveEntryClaim(key))
232
+ .filter((value) => !valuesToRemove.has(value));
233
+ return this.setActiveEntryClaimList(key, next);
234
+ }
235
+ }
236
+ /**
237
+ * High-level factory for consent-access editing.
238
+ *
239
+ * Prefer this name in onboarding docs when the developer intent is:
240
+ * "edit a Consent access bundle carried by a Communication".
241
+ */
242
+ export function createConsentAccessEditor(options = {}) {
243
+ return new ConsentAccessEditor(options);
244
+ }
@@ -0,0 +1,33 @@
1
+ import type { IDecodedDidcommPayload } from '../models/confidential-message';
2
+ export declare const CommunicationDidcommEntryTypes: Readonly<{
3
+ readonly AttachedBundle: "Communication-attached-bundle-v1.0";
4
+ }>;
5
+ /**
6
+ * Input contract for wrapping canonical Communication claims as one low-level
7
+ * DIDComm-style batch payload.
8
+ */
9
+ export type BuildDidcommPayloadFromCommunicationClaimsInput = Readonly<{
10
+ communicationClaims: Record<string, unknown>;
11
+ iss: string;
12
+ aud: string;
13
+ jti: string;
14
+ thid: string;
15
+ entryType?: string;
16
+ }>;
17
+ /**
18
+ * Builds the low-level DIDComm-style batch payload that carries one FHIR-like
19
+ * `Communication` resource authored from canonical communication claims.
20
+ *
21
+ * This helper intentionally stays below actor-specific SDK facades so frontend,
22
+ * BFF, and GW-like tests can reuse the same wrapping contract.
23
+ */
24
+ export declare function buildDidcommPayloadFromCommunicationClaims(input: BuildDidcommPayloadFromCommunicationClaimsInput): IDecodedDidcommPayload;
25
+ /**
26
+ * Reads canonical communication claims from the first `body.data[]` entry of
27
+ * one DIDComm-style payload.
28
+ */
29
+ export declare function getFirstCommunicationClaimsFromDidcommPayload(payload: IDecodedDidcommPayload): Record<string, unknown>;
30
+ /**
31
+ * Decodes the attached bundle carried in `Communication.content-attachment-data`.
32
+ */
33
+ export declare function decodeAttachedBundleFromCommunicationClaims(communicationClaims: Record<string, unknown>): Record<string, unknown>;
@@ -0,0 +1,75 @@
1
+ // Copyright 2026 Conectate Soluciones y Aplicaciones SL under the Apache License, Version 2.0.
2
+ import { CommunicationClaim } from '../models/interoperable-claims/communication-claims.js';
3
+ import { transformCommunicationClaimsToResourceFhirR4 } from './communication-fhir-r4.js';
4
+ export const CommunicationDidcommEntryTypes = Object.freeze({
5
+ AttachedBundle: 'Communication-attached-bundle-v1.0',
6
+ });
7
+ function clone(value) {
8
+ return JSON.parse(JSON.stringify(value));
9
+ }
10
+ /**
11
+ * Builds the low-level DIDComm-style batch payload that carries one FHIR-like
12
+ * `Communication` resource authored from canonical communication claims.
13
+ *
14
+ * This helper intentionally stays below actor-specific SDK facades so frontend,
15
+ * BFF, and GW-like tests can reuse the same wrapping contract.
16
+ */
17
+ export function buildDidcommPayloadFromCommunicationClaims(input) {
18
+ const claims = clone(input.communicationClaims);
19
+ const transformed = transformCommunicationClaimsToResourceFhirR4([claims], {
20
+ mode: 'strict',
21
+ });
22
+ const communicationResource = transformed.resources[0] || {};
23
+ return {
24
+ iss: String(input.iss || '').trim(),
25
+ aud: String(input.aud || '').trim(),
26
+ jti: String(input.jti || '').trim(),
27
+ thid: String(input.thid || '').trim(),
28
+ type: CommunicationDidcommEntryTypes.AttachedBundle,
29
+ body: {
30
+ data: [
31
+ {
32
+ id: String(claims[CommunicationClaim.Identifier] || input.jti || '').trim(),
33
+ type: String(input.entryType || CommunicationDidcommEntryTypes.AttachedBundle).trim(),
34
+ meta: {
35
+ claims,
36
+ },
37
+ resource: communicationResource,
38
+ },
39
+ ],
40
+ },
41
+ };
42
+ }
43
+ /**
44
+ * Reads canonical communication claims from the first `body.data[]` entry of
45
+ * one DIDComm-style payload.
46
+ */
47
+ export function getFirstCommunicationClaimsFromDidcommPayload(payload) {
48
+ const first = Array.isArray(payload?.body?.data) ? payload.body.data[0] : undefined;
49
+ const metaClaims = first?.meta && typeof first.meta === 'object'
50
+ ? first.meta['claims']
51
+ : undefined;
52
+ if (metaClaims && typeof metaClaims === 'object') {
53
+ return clone(metaClaims);
54
+ }
55
+ const resource = first?.resource && typeof first.resource === 'object'
56
+ ? first.resource
57
+ : {};
58
+ const meta = resource.meta && typeof resource.meta === 'object'
59
+ ? resource.meta
60
+ : {};
61
+ const claims = meta.claims && typeof meta.claims === 'object'
62
+ ? meta.claims
63
+ : {};
64
+ return clone(claims);
65
+ }
66
+ /**
67
+ * Decodes the attached bundle carried in `Communication.content-attachment-data`.
68
+ */
69
+ export function decodeAttachedBundleFromCommunicationClaims(communicationClaims) {
70
+ const encoded = String(communicationClaims[CommunicationClaim.ContentAttachmentData] || '').trim();
71
+ if (!encoded) {
72
+ throw new Error(`decodeAttachedBundleFromCommunicationClaims requires ${CommunicationClaim.ContentAttachmentData}.`);
73
+ }
74
+ return JSON.parse(Buffer.from(encoded, 'base64').toString('utf8'));
75
+ }
@@ -42,6 +42,9 @@ export * from './communication-participant-search';
42
42
  export * from './communication-participant-search-test-data';
43
43
  export * from './communication-retention-policy';
44
44
  export * from './communication-attached-bundle-session';
45
+ export * from './communication-consent-access-editor';
46
+ export * from './bundle-didcomm-payload';
47
+ export * from './communication-didcomm-payload';
45
48
  export * from './confidential-storage-persistence';
46
49
  export * from './confidential-storage-test-data';
47
50
  export * from './permission-templates';
@@ -91,3 +94,8 @@ export * from './service-act-reasons';
91
94
  export * from './same-as';
92
95
  export * from './activation-request';
93
96
  export * from './vp-token';
97
+ export * from './wallet-mem';
98
+ export * from './wallet-memory-queue';
99
+ export * from './profile-outbox-memory-repository';
100
+ export * from './backend-message-manager-mem';
101
+ export * from './profile-manager-mem';
@@ -42,6 +42,9 @@ export * from './communication-participant-search.js';
42
42
  export * from './communication-participant-search-test-data.js';
43
43
  export * from './communication-retention-policy.js';
44
44
  export * from './communication-attached-bundle-session.js';
45
+ export * from './communication-consent-access-editor.js';
46
+ export * from './bundle-didcomm-payload.js';
47
+ export * from './communication-didcomm-payload.js';
45
48
  export * from './confidential-storage-persistence.js';
46
49
  export * from './confidential-storage-test-data.js';
47
50
  export * from './permission-templates.js';
@@ -91,3 +94,8 @@ export * from './service-act-reasons.js';
91
94
  export * from './same-as.js';
92
95
  export * from './activation-request.js';
93
96
  export * from './vp-token.js';
97
+ export * from './wallet-mem.js';
98
+ export * from './wallet-memory-queue.js';
99
+ export * from './profile-outbox-memory-repository.js';
100
+ export * from './backend-message-manager-mem.js';
101
+ export * from './profile-manager-mem.js';
@@ -0,0 +1,69 @@
1
+ import type { IWallet } from '../interfaces/IWallet';
2
+ import type { IProfileOutboxRepository } from '../interfaces/IProfileOutboxRepository';
3
+ import type { BackendMessageResponseRecord, BackendMessageTransport, ProfileOutboxMessageRecord, ProfileManagerMemProfile, QueueProfileMessageInput } from '../models/profile-manager';
4
+ import type { WalletQueuedMessage } from '../models/wallet';
5
+ import { BackendMessageManagerMem } from './backend-message-manager-mem';
6
+ export type ProfileManagerMemOptions = Readonly<{
7
+ profile: ProfileManagerMemProfile;
8
+ wallet: IWallet;
9
+ transport: BackendMessageTransport;
10
+ outboxRepository?: IProfileOutboxRepository;
11
+ }>;
12
+ /**
13
+ * Minimal memory-backed profile manager for low-level tests.
14
+ *
15
+ * Responsibility:
16
+ * - own one logical profile
17
+ * - ensure the profile keys exist in the wallet
18
+ * - delegate queue/submit/response operations to `BackendMessageManagerMem`
19
+ *
20
+ * Non-goal:
21
+ * - actor-specific orchestration belongs to higher SDK layers
22
+ */
23
+ export declare class ProfileManagerMem {
24
+ readonly profile: ProfileManagerMemProfile;
25
+ readonly wallet: IWallet;
26
+ readonly messageManager: BackendMessageManagerMem;
27
+ readonly outboxRepository: IProfileOutboxRepository;
28
+ constructor(options: ProfileManagerMemOptions);
29
+ /**
30
+ * Provisions the local profile keys before any queue or transport operation.
31
+ */
32
+ initialize(): Promise<void>;
33
+ /**
34
+ * Queues one outbound profile payload.
35
+ */
36
+ queueMessage(input: QueueProfileMessageInput): Promise<WalletQueuedMessage>;
37
+ /**
38
+ * Returns the current queued messages in processing order.
39
+ */
40
+ listQueuedMessages(): Promise<WalletQueuedMessage[]>;
41
+ /**
42
+ * Submits the next pending message and optionally stores the decoded response.
43
+ */
44
+ submitNextPendingMessage(recipientEncryptionJwk: Record<string, unknown>): Promise<{
45
+ message: WalletQueuedMessage;
46
+ response?: BackendMessageResponseRecord;
47
+ pending?: boolean;
48
+ }>;
49
+ /**
50
+ * Reads the latest decoded response for one thread id.
51
+ */
52
+ getResponseByThreadId(thid: string): BackendMessageResponseRecord | undefined;
53
+ /**
54
+ * Reads one decoded response by thread id from memory or repository storage.
55
+ */
56
+ readResponseByThreadId(thid: string): Promise<BackendMessageResponseRecord | undefined>;
57
+ /**
58
+ * Lists historical outbox records already submitted through this profile manager.
59
+ */
60
+ listOutboxHistory(): Promise<ProfileOutboxMessageRecord[]>;
61
+ /**
62
+ * Polls one asynchronous outbox record by id.
63
+ */
64
+ pollSubmittedMessage(messageId: string): Promise<{
65
+ pending: boolean;
66
+ response?: BackendMessageResponseRecord;
67
+ record: ProfileOutboxMessageRecord;
68
+ }>;
69
+ }
@@ -0,0 +1,79 @@
1
+ // Copyright 2026 Conectate Soluciones y Aplicaciones SL under the Apache License, Version 2.0.
2
+ import { BackendMessageManagerMem } from './backend-message-manager-mem.js';
3
+ import { MemoryProfileOutboxRepository } from './profile-outbox-memory-repository.js';
4
+ /**
5
+ * Minimal memory-backed profile manager for low-level tests.
6
+ *
7
+ * Responsibility:
8
+ * - own one logical profile
9
+ * - ensure the profile keys exist in the wallet
10
+ * - delegate queue/submit/response operations to `BackendMessageManagerMem`
11
+ *
12
+ * Non-goal:
13
+ * - actor-specific orchestration belongs to higher SDK layers
14
+ */
15
+ export class ProfileManagerMem {
16
+ profile;
17
+ wallet;
18
+ messageManager;
19
+ outboxRepository;
20
+ constructor(options) {
21
+ this.profile = options.profile;
22
+ this.wallet = options.wallet;
23
+ this.outboxRepository = options.outboxRepository ?? new MemoryProfileOutboxRepository();
24
+ this.messageManager = new BackendMessageManagerMem({
25
+ wallet: options.wallet,
26
+ entityId: options.profile.profileId,
27
+ transport: options.transport,
28
+ outboxRepository: this.outboxRepository,
29
+ });
30
+ }
31
+ /**
32
+ * Provisions the local profile keys before any queue or transport operation.
33
+ */
34
+ async initialize() {
35
+ await this.wallet.provisionKeys(this.profile.profileId);
36
+ }
37
+ /**
38
+ * Queues one outbound profile payload.
39
+ */
40
+ async queueMessage(input) {
41
+ return this.messageManager.queueMessage(input);
42
+ }
43
+ /**
44
+ * Returns the current queued messages in processing order.
45
+ */
46
+ async listQueuedMessages() {
47
+ return this.messageManager.listQueuedMessages();
48
+ }
49
+ /**
50
+ * Submits the next pending message and optionally stores the decoded response.
51
+ */
52
+ async submitNextPendingMessage(recipientEncryptionJwk) {
53
+ return this.messageManager.submitNextPendingMessage(recipientEncryptionJwk);
54
+ }
55
+ /**
56
+ * Reads the latest decoded response for one thread id.
57
+ */
58
+ getResponseByThreadId(thid) {
59
+ return this.messageManager.getResponseByThreadId(thid);
60
+ }
61
+ /**
62
+ * Reads one decoded response by thread id from memory or repository storage.
63
+ */
64
+ async readResponseByThreadId(thid) {
65
+ return this.messageManager.readResponseByThreadId(thid);
66
+ }
67
+ /**
68
+ * Lists historical outbox records already submitted through this profile manager.
69
+ */
70
+ async listOutboxHistory() {
71
+ return this.messageManager.listOutboxHistory();
72
+ }
73
+ /**
74
+ * Polls one asynchronous outbox record by id.
75
+ */
76
+ async pollSubmittedMessage(messageId) {
77
+ return this.messageManager.pollSubmittedMessage(messageId);
78
+ }
79
+ }
@@ -0,0 +1,34 @@
1
+ import type { IProfileOutboxRepository } from '../interfaces/IProfileOutboxRepository';
2
+ import type { BackendMessageResponseRecord, ProfileOutboxMessageRecord } from '../models/profile-manager';
3
+ /**
4
+ * In-memory profile outbox repository used by low-level tests and as the
5
+ * default history/response store for `ProfileManagerMem`.
6
+ */
7
+ export declare class MemoryProfileOutboxRepository implements IProfileOutboxRepository {
8
+ private readonly messages;
9
+ private readonly responses;
10
+ /**
11
+ * Stores one immutable message history record.
12
+ */
13
+ putMessage(record: ProfileOutboxMessageRecord): Promise<ProfileOutboxMessageRecord>;
14
+ /**
15
+ * Reads one message history record.
16
+ */
17
+ getMessage(messageId: string): Promise<ProfileOutboxMessageRecord | undefined>;
18
+ /**
19
+ * Lists all message history records in insertion order.
20
+ */
21
+ listMessages(): Promise<ProfileOutboxMessageRecord[]>;
22
+ /**
23
+ * Stores one decoded response record grouped by thread id.
24
+ */
25
+ putResponse(record: BackendMessageResponseRecord): Promise<BackendMessageResponseRecord>;
26
+ /**
27
+ * Returns the latest decoded response for the provided thread id.
28
+ */
29
+ getLatestResponseByThreadId(thid: string): Promise<BackendMessageResponseRecord | undefined>;
30
+ /**
31
+ * Lists all decoded responses across all threads.
32
+ */
33
+ listResponses(): Promise<BackendMessageResponseRecord[]>;
34
+ }