sos-sdk-core-ts 0.3.1 → 0.5.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.
- package/CHANGELOG.md +42 -2
- package/README.md +27 -5
- package/dist/bundle-changes-response.d.ts +32 -0
- package/dist/bundle-changes-response.js +154 -0
- package/dist/care-emergency-alert-orchestration.js +12 -23
- package/dist/communication-bundle.d.ts +125 -0
- package/dist/communication-bundle.js +312 -0
- package/dist/emergency-authorization.d.ts +1 -11
- package/dist/emergency-authorization.js +0 -2
- package/dist/encounter-transfer-communication.d.ts +40 -0
- package/dist/encounter-transfer-communication.js +120 -0
- package/dist/equipment-compliance-orchestration.d.ts +39 -0
- package/dist/equipment-compliance-orchestration.js +18 -0
- package/dist/fhir-scheduling.d.ts +40 -0
- package/dist/fhir-scheduling.js +127 -0
- package/dist/index.d.ts +7 -4
- package/dist/index.js +6 -3
- package/docs/CARE_EMERGENCY_AND_ALERT_ORCHESTRATION.md +7 -6
- package/docs/COMMUNICATION_BUNDLE_EDITOR_READER.md +85 -0
- package/docs/ENCOUNTER_TRANSFER_PROJECTION.md +38 -0
- package/docs/EQUIPMENT_COMPLIANCE.md +43 -0
- package/docs/FHIR_SCHEDULING_INTEROPERABILITY.md +28 -0
- package/package.json +24 -11
- package/dist/emergency-group.d.ts +0 -2
- package/dist/emergency-group.js +0 -2
- package/dist/place-card-association.d.ts +0 -2
- package/dist/place-card-association.js +0 -2
package/CHANGELOG.md
CHANGED
|
@@ -2,9 +2,49 @@
|
|
|
2
2
|
|
|
3
3
|
## Unreleased
|
|
4
4
|
|
|
5
|
+
- Add the claims-first Encounter transfer projection helper. It keeps a
|
|
6
|
+
returning source `on-hold`, completes a definitive source departure, starts
|
|
7
|
+
the destination `in-progress`, records both `EncounterHistory` milestones,
|
|
8
|
+
and sends the already-committed result to the subject index in one completed
|
|
9
|
+
Communication batch.
|
|
10
|
+
- Document that movement does not imply `discharged`, that department sender,
|
|
11
|
+
HealthcareService and authenticated audit actor remain distinct, and that
|
|
12
|
+
emergency-contact files stay DocumentReference resources inside the Bundle.
|
|
13
|
+
|
|
14
|
+
- Add the neutral `bundle-changes-response` contract and publish its scheduling
|
|
15
|
+
ownership guide. UHC consumers no longer expose a provisional copy.
|
|
16
|
+
|
|
17
|
+
- Move the standard Appointment-in-Communication authoring flow and the
|
|
18
|
+
capability-driven FHIR scheduling client into the shared SOS/Vet/UHC layer.
|
|
19
|
+
Product packages no longer need human or veterinary wrappers for standard
|
|
20
|
+
FHIR resources.
|
|
21
|
+
- Remove temporary SOSChain-prefixed emergency authorization aliases and data
|
|
22
|
+
reexport subpaths. Emergency Group and card-to-Place records now come from
|
|
23
|
+
their single owner, `sos-data-utils-ts@0.6.0`.
|
|
24
|
+
- Consume the complete shared Task status vocabulary directly instead of
|
|
25
|
+
maintaining a local compatibility overlay.
|
|
26
|
+
|
|
27
|
+
## 0.4.0 - 2026-09-29
|
|
28
|
+
|
|
29
|
+
- Add the shared high-level Communication Bundle editor and reader for SOS,
|
|
30
|
+
Vet and UHC. Author an outer batch Bundle of Communications, validate each
|
|
31
|
+
attached inner document/batch/collection Bundle with
|
|
32
|
+
`fhir-data-utils-ts@0.6.0`, and keep PDF, image, audio and calendar files as
|
|
33
|
+
inner DocumentReference resources.
|
|
34
|
+
- Pin `sos-data-utils-ts@0.5.1` and extend the existing
|
|
35
|
+
`gdc-common-utils-ts@2.9.21` Bundle editor, reader and attached-Bundle session
|
|
36
|
+
rather than introducing a parallel high-level implementation.
|
|
37
|
+
|
|
38
|
+
- Add runtime-neutral, department-aware equipment calibration and operating-authorization orchestration; blood-bank labeling remains explicitly deferred.
|
|
39
|
+
|
|
40
|
+
- Link the coordinated SOS/Vet/UHC clinical accessor adoption boundary so
|
|
41
|
+
shared orchestration is added only with an actual multichannel workflow.
|
|
42
|
+
|
|
5
43
|
- Require the initial emergency triage Task owner to be a professional Group,
|
|
6
|
-
while keeping the accepting PractitionerRole as Task owner and
|
|
7
|
-
|
|
44
|
+
while keeping the accepting PractitionerRole as Task owner and authenticated
|
|
45
|
+
transport actor after acknowledgement.
|
|
46
|
+
- Define the department Organization as the FHIR Communication sender and keep
|
|
47
|
+
the professional Group solely as the stable reply queue.
|
|
8
48
|
- Clarify that Group reply routing never replaces the legal Organization
|
|
9
49
|
document author, professional attester or authenticated transport actor.
|
|
10
50
|
|
package/README.md
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
# Shared SOS SDK Core
|
|
2
|
+
|
|
3
|
+
Shared SOS/Vet/UHC orchestration includes [equipment calibration and operating authorization](docs/EQUIPMENT_COMPLIANCE.md) without embedding product roles or persistence plumbing.
|
|
2
4
|
## Blocking local-first SDK release
|
|
3
5
|
|
|
4
6
|
The canonical contract is [`SDK_LAYERING.md`](https://github.com/Fundacion-UNID/sos-data-utils-ts/blob/main/docs/SDK_LAYERING.md).
|
|
@@ -38,6 +40,28 @@ jobs; those adapters do not belong here.
|
|
|
38
40
|
Git, workspace, vendored and `file:` dependencies are forbidden in committed
|
|
39
41
|
or deployed dependency state.
|
|
40
42
|
|
|
43
|
+
The cross-product Bundle/Communication editor and reader are owned here as
|
|
44
|
+
high-level extensions of the existing `gdc-common-utils-ts` `BundleEditor`,
|
|
45
|
+
`BundleReader` and `CommunicationAttachedBundleSession`. They preserve those
|
|
46
|
+
APIs instead of duplicating their attachment or claims-first lifecycle, while
|
|
47
|
+
`fhir-data-utils-ts` supplies neutral import, projection and validation tools.
|
|
48
|
+
Follow the
|
|
49
|
+
[SOS/Vet/UHC clinical accessor adoption matrix](https://github.com/Fundacion-UNID/sos-data-utils-ts/blob/main/docs/CLINICAL_TYPED_ACCESSOR_ADOPTION.md)
|
|
50
|
+
before changing dependencies: unaffected portals and assistants are not forced
|
|
51
|
+
to upgrade merely because a lower package published a newer editor.
|
|
52
|
+
|
|
53
|
+
All cross-participant exchanges use the established claims-first outer batch
|
|
54
|
+
Bundle containing one or more Communication resources. Each Communication
|
|
55
|
+
contains exactly one inner document, batch or collection Bundle in its
|
|
56
|
+
`application/fhir+json` attachment claims. Binary files such as PDF, image,
|
|
57
|
+
audio or `text/calendar` are DocumentReference entries inside the inner Bundle.
|
|
58
|
+
Native FHIR R4/R5 is materialized only at an explicit adapter boundary. See
|
|
59
|
+
[Communication Bundle editor and reader](docs/COMMUNICATION_BUNDLE_EDITOR_READER.md).
|
|
60
|
+
The shared scheduling and response-correlation boundary is documented in
|
|
61
|
+
[FHIR scheduling interoperability](docs/FHIR_SCHEDULING_INTEROPERABILITY.md).
|
|
62
|
+
Source-to-destination care movement and subject-index projection are documented
|
|
63
|
+
in [Encounter transfer projection](docs/ENCOUNTER_TRANSFER_PROJECTION.md).
|
|
64
|
+
|
|
41
65
|
The emergency-group contract stores subject references only on an enumerated
|
|
42
66
|
FHIR Group. A group assistance request references that Group from one standard,
|
|
43
67
|
compact-coded ServiceRequest; it never copies members or persists split coding
|
|
@@ -52,11 +76,9 @@ The `incident-reporter` relationship represents a short-lived grant issued by
|
|
|
52
76
|
a trusted scan resolver to an already verified person at the scene; it does
|
|
53
77
|
not imply guardianship, control or professional status.
|
|
54
78
|
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
`buildSoschainPlaceCardAssociationClaims` records a UHC/VetChain card link to
|
|
59
|
-
a canonical SOSChain Place or vehicle without merging either identity.
|
|
79
|
+
Emergency evidence, Group records and card-to-Place associations are imported
|
|
80
|
+
directly from `sos-data-utils-ts`; this orchestration package does not retain
|
|
81
|
+
temporary reexport subpaths or product-prefixed authorization aliases.
|
|
60
82
|
|
|
61
83
|
## Care, emergency and alert orchestration
|
|
62
84
|
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import type { BundleEntry, BundleJsonApi } from 'gdc-common-utils-ts/models/bundle';
|
|
2
|
+
export declare const BundleChangeResponseStates: Readonly<{
|
|
3
|
+
readonly Successful: "successful";
|
|
4
|
+
readonly Failed: "failed";
|
|
5
|
+
readonly Pending: "pending";
|
|
6
|
+
}>;
|
|
7
|
+
export type BundleChangeResponseState = typeof BundleChangeResponseStates[keyof typeof BundleChangeResponseStates];
|
|
8
|
+
export type BundleChangeResponseItem = Readonly<{
|
|
9
|
+
identifier: string;
|
|
10
|
+
changeEntryIndex: number;
|
|
11
|
+
responseEntryIndex?: number;
|
|
12
|
+
state: BundleChangeResponseState;
|
|
13
|
+
responseStatus?: string;
|
|
14
|
+
diagnostics: readonly string[];
|
|
15
|
+
}>;
|
|
16
|
+
export type BundleChangesResponseAnalysis = Readonly<{
|
|
17
|
+
entries: readonly BundleChangeResponseItem[];
|
|
18
|
+
successfulIdentifiers: readonly string[];
|
|
19
|
+
failedIdentifiers: readonly string[];
|
|
20
|
+
pendingIdentifiers: readonly string[];
|
|
21
|
+
diagnostics: readonly string[];
|
|
22
|
+
}>;
|
|
23
|
+
/** Reads every stable identifier carried by one Bundle entry in preference order. */
|
|
24
|
+
export declare function readBundleEntryCorrelationIdentifiers(entry: BundleEntry): readonly string[];
|
|
25
|
+
/**
|
|
26
|
+
* Correlates the submitted changes Bundle with the GW Bundle response.
|
|
27
|
+
*
|
|
28
|
+
* Correlation uses stable identifiers only, never array position. A missing,
|
|
29
|
+
* malformed or ambiguous response remains pending until the caller performs
|
|
30
|
+
* the resource-specific authoritative search.
|
|
31
|
+
*/
|
|
32
|
+
export declare function analyzeBundleChangesResponse(changesBundle: BundleJsonApi<BundleEntry>, responseBundle: BundleJsonApi<BundleEntry>): BundleChangesResponseAnalysis;
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
// Copyright 2026 Connecting Solution & Applications Ltd under the Apache License, Version 2.0.
|
|
2
|
+
export const BundleChangeResponseStates = Object.freeze({
|
|
3
|
+
Successful: 'successful',
|
|
4
|
+
Failed: 'failed',
|
|
5
|
+
Pending: 'pending',
|
|
6
|
+
});
|
|
7
|
+
function asRecord(value) {
|
|
8
|
+
return value !== null && typeof value === 'object'
|
|
9
|
+
? value
|
|
10
|
+
: {};
|
|
11
|
+
}
|
|
12
|
+
function asNonEmptyString(value) {
|
|
13
|
+
return typeof value === 'string' && value.trim().length > 0
|
|
14
|
+
? value.trim()
|
|
15
|
+
: undefined;
|
|
16
|
+
}
|
|
17
|
+
function appendIdentifier(target, value) {
|
|
18
|
+
const identifier = asNonEmptyString(value);
|
|
19
|
+
if (identifier && !target.includes(identifier))
|
|
20
|
+
target.push(identifier);
|
|
21
|
+
}
|
|
22
|
+
function appendClaimIdentifiers(target, claims) {
|
|
23
|
+
for (const [name, value] of Object.entries(claims)) {
|
|
24
|
+
if (name === 'identifier' || name.endsWith('.identifier') || name.endsWith('.identifier.value')) {
|
|
25
|
+
appendIdentifier(target, value);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
/** Reads every stable identifier carried by one Bundle entry in preference order. */
|
|
30
|
+
export function readBundleEntryCorrelationIdentifiers(entry) {
|
|
31
|
+
const identifiers = [];
|
|
32
|
+
const resource = asRecord(entry.resource);
|
|
33
|
+
const resourceMeta = asRecord(resource.meta);
|
|
34
|
+
const entryMeta = asRecord(entry.meta);
|
|
35
|
+
appendIdentifier(identifiers, entry.fullUrl);
|
|
36
|
+
appendIdentifier(identifiers, resource.id);
|
|
37
|
+
appendIdentifier(identifiers, entry.id);
|
|
38
|
+
appendClaimIdentifiers(identifiers, asRecord(resourceMeta.claims));
|
|
39
|
+
appendClaimIdentifiers(identifiers, asRecord(entryMeta.claims));
|
|
40
|
+
return identifiers;
|
|
41
|
+
}
|
|
42
|
+
function readBundleEntryResponseOutcome(entry) {
|
|
43
|
+
const response = asRecord(entry.response);
|
|
44
|
+
const outcome = asRecord(response.outcome);
|
|
45
|
+
const issues = Array.isArray(outcome.issue) ? outcome.issue.map(asRecord) : [];
|
|
46
|
+
const severities = [];
|
|
47
|
+
const diagnostics = [];
|
|
48
|
+
for (const issue of issues) {
|
|
49
|
+
const severity = asNonEmptyString(issue.severity)?.toLowerCase();
|
|
50
|
+
if (severity)
|
|
51
|
+
severities.push(severity);
|
|
52
|
+
const diagnostic = asNonEmptyString(issue.diagnostics)
|
|
53
|
+
?? asNonEmptyString(asRecord(issue.details).text);
|
|
54
|
+
if (diagnostic)
|
|
55
|
+
diagnostics.push(diagnostic);
|
|
56
|
+
}
|
|
57
|
+
const status = asNonEmptyString(response.status);
|
|
58
|
+
return { ...(status ? { status } : {}), severities, diagnostics };
|
|
59
|
+
}
|
|
60
|
+
function isSuccessfulStatus(status) {
|
|
61
|
+
return !!status && /^2\d\d(?:\s|$)/.test(status);
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Correlates the submitted changes Bundle with the GW Bundle response.
|
|
65
|
+
*
|
|
66
|
+
* Correlation uses stable identifiers only, never array position. A missing,
|
|
67
|
+
* malformed or ambiguous response remains pending until the caller performs
|
|
68
|
+
* the resource-specific authoritative search.
|
|
69
|
+
*/
|
|
70
|
+
export function analyzeBundleChangesResponse(changesBundle, responseBundle) {
|
|
71
|
+
const responseEntries = responseBundle.data.map((entry, index) => ({
|
|
72
|
+
entry,
|
|
73
|
+
index,
|
|
74
|
+
identifiers: readBundleEntryCorrelationIdentifiers(entry),
|
|
75
|
+
}));
|
|
76
|
+
const seenChangeIdentifiers = new Set();
|
|
77
|
+
const claimedResponseIndexes = new Set();
|
|
78
|
+
const diagnostics = [];
|
|
79
|
+
const entries = [];
|
|
80
|
+
const changes = changesBundle.data.map((changeEntry, changeEntryIndex) => {
|
|
81
|
+
const identifiers = readBundleEntryCorrelationIdentifiers(changeEntry);
|
|
82
|
+
const identifier = identifiers[0];
|
|
83
|
+
if (!identifier) {
|
|
84
|
+
throw new Error(`Changes Bundle entry ${changeEntryIndex} requires a stable fullUrl, resource.id, entry.id or identifier claim.`);
|
|
85
|
+
}
|
|
86
|
+
if (seenChangeIdentifiers.has(identifier)) {
|
|
87
|
+
throw new Error(`Changes Bundle contains duplicate primary identifier '${identifier}'.`);
|
|
88
|
+
}
|
|
89
|
+
seenChangeIdentifiers.add(identifier);
|
|
90
|
+
return {
|
|
91
|
+
index: changeEntryIndex,
|
|
92
|
+
identifier,
|
|
93
|
+
matchingResponses: responseEntries.filter((candidate) => candidate.identifiers.some((candidateIdentifier) => identifiers.includes(candidateIdentifier))),
|
|
94
|
+
};
|
|
95
|
+
});
|
|
96
|
+
const responseMatchCounts = new Map();
|
|
97
|
+
changes.forEach(({ matchingResponses }) => matchingResponses.forEach(({ index }) => {
|
|
98
|
+
responseMatchCounts.set(index, (responseMatchCounts.get(index) ?? 0) + 1);
|
|
99
|
+
}));
|
|
100
|
+
changes.forEach(({ identifier, index: changeEntryIndex, matchingResponses }) => {
|
|
101
|
+
if (matchingResponses.length !== 1) {
|
|
102
|
+
const message = matchingResponses.length === 0
|
|
103
|
+
? `No response entry carries a stable identifier for change '${identifier}'.`
|
|
104
|
+
: `More than one response entry matches change '${identifier}'.`;
|
|
105
|
+
diagnostics.push(message);
|
|
106
|
+
entries.push({ identifier, changeEntryIndex, state: BundleChangeResponseStates.Pending, diagnostics: [message] });
|
|
107
|
+
return;
|
|
108
|
+
}
|
|
109
|
+
const match = matchingResponses[0];
|
|
110
|
+
if ((responseMatchCounts.get(match.index) ?? 0) > 1) {
|
|
111
|
+
const message = `Response entry ${match.index} ambiguously matches more than one submitted change.`;
|
|
112
|
+
diagnostics.push(message);
|
|
113
|
+
entries.push({
|
|
114
|
+
identifier,
|
|
115
|
+
changeEntryIndex,
|
|
116
|
+
responseEntryIndex: match.index,
|
|
117
|
+
state: BundleChangeResponseStates.Pending,
|
|
118
|
+
diagnostics: [message],
|
|
119
|
+
});
|
|
120
|
+
return;
|
|
121
|
+
}
|
|
122
|
+
claimedResponseIndexes.add(match.index);
|
|
123
|
+
const outcome = readBundleEntryResponseOutcome(match.entry);
|
|
124
|
+
const hasError = outcome.severities.some((severity) => severity === 'fatal' || severity === 'error');
|
|
125
|
+
const state = !outcome.status
|
|
126
|
+
? BundleChangeResponseStates.Pending
|
|
127
|
+
: isSuccessfulStatus(outcome.status) && !hasError
|
|
128
|
+
? BundleChangeResponseStates.Successful
|
|
129
|
+
: BundleChangeResponseStates.Failed;
|
|
130
|
+
const itemDiagnostics = [...outcome.diagnostics];
|
|
131
|
+
if (!outcome.status)
|
|
132
|
+
itemDiagnostics.push(`Response entry ${match.index} has no status.`);
|
|
133
|
+
entries.push({
|
|
134
|
+
identifier,
|
|
135
|
+
changeEntryIndex,
|
|
136
|
+
responseEntryIndex: match.index,
|
|
137
|
+
state,
|
|
138
|
+
...(outcome.status ? { responseStatus: outcome.status } : {}),
|
|
139
|
+
diagnostics: itemDiagnostics,
|
|
140
|
+
});
|
|
141
|
+
});
|
|
142
|
+
responseEntries.forEach(({ index }) => {
|
|
143
|
+
if (!claimedResponseIndexes.has(index)) {
|
|
144
|
+
diagnostics.push(`Response entry ${index} does not correlate with one submitted change.`);
|
|
145
|
+
}
|
|
146
|
+
});
|
|
147
|
+
return {
|
|
148
|
+
entries,
|
|
149
|
+
successfulIdentifiers: entries.filter(({ state }) => state === BundleChangeResponseStates.Successful).map(({ identifier }) => identifier),
|
|
150
|
+
failedIdentifiers: entries.filter(({ state }) => state === BundleChangeResponseStates.Failed).map(({ identifier }) => identifier),
|
|
151
|
+
pendingIdentifiers: entries.filter(({ state }) => state === BundleChangeResponseStates.Pending).map(({ identifier }) => identifier),
|
|
152
|
+
diagnostics,
|
|
153
|
+
};
|
|
154
|
+
}
|
|
@@ -89,17 +89,6 @@ export function orchestrateEmergencyRequest(input) {
|
|
|
89
89
|
});
|
|
90
90
|
return Object.freeze({ intake, serviceRequestEntry, triageTaskEntry });
|
|
91
91
|
}
|
|
92
|
-
// Compatibility overlay for the published data package used by clean installs.
|
|
93
|
-
// The next grouped release exposes the same standard values directly there.
|
|
94
|
-
const EmergencyTaskStatus = Object.freeze({
|
|
95
|
-
...TaskStatus,
|
|
96
|
-
Received: 'received',
|
|
97
|
-
Accepted: 'accepted',
|
|
98
|
-
Rejected: 'rejected',
|
|
99
|
-
Ready: 'ready',
|
|
100
|
-
OnHold: 'on-hold',
|
|
101
|
-
EnteredInError: 'entered-in-error',
|
|
102
|
-
});
|
|
103
92
|
/**
|
|
104
93
|
* Reads only the standard, claims-first coordinates required by a responder
|
|
105
94
|
* console. It does not resolve contact endpoints or grant callback authority.
|
|
@@ -110,7 +99,7 @@ export function readEmergencyTriageTask(taskEntry) {
|
|
|
110
99
|
}
|
|
111
100
|
const claims = taskEntry.claims;
|
|
112
101
|
const status = scalarClaim(claims[TaskClaim.Status], 'emergency_triage_status_required');
|
|
113
|
-
if (!Object.values(
|
|
102
|
+
if (!Object.values(TaskStatus).includes(status)) {
|
|
114
103
|
throw new TypeError('emergency_triage_status_invalid');
|
|
115
104
|
}
|
|
116
105
|
return Object.freeze({
|
|
@@ -161,7 +150,7 @@ export function prepareEmergencyResponderCallback(input) {
|
|
|
161
150
|
const responderReference = reference(input.responderReference, 'PractitionerRole', 'emergency_callback_responder_invalid');
|
|
162
151
|
if (task.ownerReference !== responderReference)
|
|
163
152
|
throw new TypeError('emergency_callback_task_owner_required');
|
|
164
|
-
if (task.status !==
|
|
153
|
+
if (task.status !== TaskStatus.Accepted && task.status !== TaskStatus.InProgress) {
|
|
165
154
|
throw new TypeError('emergency_callback_active_task_required');
|
|
166
155
|
}
|
|
167
156
|
if (!task.communicationThreadId)
|
|
@@ -180,20 +169,20 @@ export function prepareEmergencyResponderCallback(input) {
|
|
|
180
169
|
}
|
|
181
170
|
function emergencyTriageTransition(currentStatus, action) {
|
|
182
171
|
const transitions = {
|
|
183
|
-
acknowledge: { [
|
|
184
|
-
start: { [
|
|
172
|
+
acknowledge: { [TaskStatus.Requested]: TaskStatus.Accepted, [TaskStatus.Received]: TaskStatus.Accepted },
|
|
173
|
+
start: { [TaskStatus.Accepted]: TaskStatus.InProgress, [TaskStatus.Ready]: TaskStatus.InProgress },
|
|
185
174
|
escalate: {
|
|
186
|
-
[
|
|
187
|
-
[
|
|
188
|
-
[
|
|
189
|
-
[
|
|
175
|
+
[TaskStatus.Requested]: TaskStatus.Requested,
|
|
176
|
+
[TaskStatus.Received]: TaskStatus.Requested,
|
|
177
|
+
[TaskStatus.Accepted]: TaskStatus.Requested,
|
|
178
|
+
[TaskStatus.InProgress]: TaskStatus.Requested,
|
|
190
179
|
},
|
|
191
180
|
reject: {
|
|
192
|
-
[
|
|
193
|
-
[
|
|
194
|
-
[
|
|
181
|
+
[TaskStatus.Requested]: TaskStatus.Rejected,
|
|
182
|
+
[TaskStatus.Received]: TaskStatus.Rejected,
|
|
183
|
+
[TaskStatus.Accepted]: TaskStatus.Rejected,
|
|
195
184
|
},
|
|
196
|
-
complete: { [
|
|
185
|
+
complete: { [TaskStatus.InProgress]: TaskStatus.Completed },
|
|
197
186
|
};
|
|
198
187
|
const nextStatus = transitions[action]?.[currentStatus];
|
|
199
188
|
if (!nextStatus)
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
import { BundleEditor } from 'gdc-common-utils-ts/utils/bundle-editor';
|
|
2
|
+
import { BundleReader } from 'gdc-common-utils-ts/utils/bundle-reader';
|
|
3
|
+
import { CommunicationAttachedBundleSession } from 'gdc-common-utils-ts/utils/communication-attached-bundle-session';
|
|
4
|
+
import { type FhirResource } from 'fhir-data-utils-ts';
|
|
5
|
+
export type CommunicationInnerBundleType = 'document' | 'batch' | 'collection';
|
|
6
|
+
export type AttachmentDocumentInput = Readonly<{
|
|
7
|
+
identifier: string;
|
|
8
|
+
subjectReference: string;
|
|
9
|
+
contentType: string;
|
|
10
|
+
dataBase64?: string;
|
|
11
|
+
url?: string;
|
|
12
|
+
title?: string;
|
|
13
|
+
description?: string;
|
|
14
|
+
date?: string;
|
|
15
|
+
authorReferences?: readonly string[];
|
|
16
|
+
eventReferences?: readonly string[];
|
|
17
|
+
}>;
|
|
18
|
+
export type AppointmentCommunicationBundleInput = Readonly<{
|
|
19
|
+
communicationIdentifier: string;
|
|
20
|
+
status: string;
|
|
21
|
+
category?: string | readonly string[];
|
|
22
|
+
topic?: string;
|
|
23
|
+
text?: string;
|
|
24
|
+
subjectReference: string;
|
|
25
|
+
senderReference: string;
|
|
26
|
+
recipientReferences: readonly string[];
|
|
27
|
+
sent?: string;
|
|
28
|
+
appointment: FhirResource & Readonly<{
|
|
29
|
+
resourceType: 'Appointment';
|
|
30
|
+
id: string;
|
|
31
|
+
}>;
|
|
32
|
+
calendarDocument?: Readonly<{
|
|
33
|
+
identifier: string;
|
|
34
|
+
contentType: 'text/calendar';
|
|
35
|
+
dataBase64?: string;
|
|
36
|
+
url?: string;
|
|
37
|
+
title?: string;
|
|
38
|
+
}>;
|
|
39
|
+
}>;
|
|
40
|
+
/**
|
|
41
|
+
* SOS/Vet/UHC extension of the existing GDC BundleEditor.
|
|
42
|
+
*
|
|
43
|
+
* The inherited editor owns the canonical outer claims-first batch. Each
|
|
44
|
+
* staged message is a CommunicationAttachedBundleSession, so the existing
|
|
45
|
+
* attachment synchronization and Bundle lifecycle remain the source of truth.
|
|
46
|
+
* FHIR data utilities are used only at import/materialization boundaries.
|
|
47
|
+
*/
|
|
48
|
+
export declare class CommunicationBundleEditor extends BundleEditor {
|
|
49
|
+
#private;
|
|
50
|
+
constructor();
|
|
51
|
+
newCommunication(): CommunicationMessageEditor;
|
|
52
|
+
/** Builds the inherited claims-first outer batch after validating every attached Bundle. */
|
|
53
|
+
build(): ReturnType<BundleEditor['build']>;
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Authors the standard FHIR Appointment delivery flow for every sector.
|
|
57
|
+
*
|
|
58
|
+
* Product SDKs use this class directly. They must not introduce human or
|
|
59
|
+
* veterinary Appointment wrappers unless they add a genuinely sector-owned
|
|
60
|
+
* rule that is absent from the FHIR and shared data contracts.
|
|
61
|
+
*/
|
|
62
|
+
export declare class AppointmentCommunicationBundleEditor extends CommunicationBundleEditor {
|
|
63
|
+
addAppointmentCommunication(input: AppointmentCommunicationBundleInput): this;
|
|
64
|
+
}
|
|
65
|
+
/** Authors one standard Appointment delivery without a product-specific wrapper. */
|
|
66
|
+
export declare function prepareAppointmentCommunicationBundle(input: AppointmentCommunicationBundleInput): Record<string, unknown>;
|
|
67
|
+
/** High-level message editor extending the established attached-Bundle session. */
|
|
68
|
+
export declare class CommunicationMessageEditor extends CommunicationAttachedBundleSession {
|
|
69
|
+
#private;
|
|
70
|
+
constructor(parent: CommunicationBundleEditor);
|
|
71
|
+
setIdentifier(value: string): this;
|
|
72
|
+
getIdentifier(): string | undefined;
|
|
73
|
+
setStatus(value: string): this;
|
|
74
|
+
getStatus(): string | undefined;
|
|
75
|
+
setSubject(value: string): this;
|
|
76
|
+
getSubject(): string | undefined;
|
|
77
|
+
setSender(value: string): this;
|
|
78
|
+
getSender(): string | undefined;
|
|
79
|
+
setRecipients(values: readonly string[]): this;
|
|
80
|
+
getRecipients(): readonly string[];
|
|
81
|
+
setSent(value: string): this;
|
|
82
|
+
getSent(): string | undefined;
|
|
83
|
+
setAttachmentTitle(value: string): this;
|
|
84
|
+
getAttachmentTitle(): string | undefined;
|
|
85
|
+
setInnerBundleType(value: CommunicationInnerBundleType): this;
|
|
86
|
+
getInnerBundleType(): CommunicationInnerBundleType;
|
|
87
|
+
/** Adds one canonical claims-first resource to the existing attached-Bundle session. */
|
|
88
|
+
addResource(resource: FhirResource, request?: Readonly<{
|
|
89
|
+
method: 'POST' | 'PUT' | 'PATCH' | 'DELETE' | 'GET';
|
|
90
|
+
url: string;
|
|
91
|
+
ifMatch?: string;
|
|
92
|
+
}>): this;
|
|
93
|
+
/** Adds a PDF, image, audio or calendar file as an inner DocumentReference. */
|
|
94
|
+
addAttachmentDocument(input: AttachmentDocumentInput): this;
|
|
95
|
+
doneCommunication(): CommunicationBundleEditor;
|
|
96
|
+
/** @internal */
|
|
97
|
+
validateForBuild(): void;
|
|
98
|
+
/** @internal */
|
|
99
|
+
getCompleteCommunicationClaims(): Record<string, unknown>;
|
|
100
|
+
}
|
|
101
|
+
/** Read-only extension of the established BundleReader for an outer Communication batch. */
|
|
102
|
+
export declare class CommunicationBundleReader extends BundleReader {
|
|
103
|
+
#private;
|
|
104
|
+
constructor(outerBatch: Record<string, unknown>);
|
|
105
|
+
getCommunicationCount(): number;
|
|
106
|
+
openCommunication(index: number): CommunicationMessageReader;
|
|
107
|
+
}
|
|
108
|
+
/** High-level getters over one claims-first Communication and its attached Bundle. */
|
|
109
|
+
export declare class CommunicationMessageReader extends BundleReader {
|
|
110
|
+
#private;
|
|
111
|
+
constructor(entry: Record<string, unknown>);
|
|
112
|
+
getCommunication(): FhirResource;
|
|
113
|
+
getInnerBundle(): Record<string, unknown>;
|
|
114
|
+
getIdentifier(): string;
|
|
115
|
+
getStatus(): string | undefined;
|
|
116
|
+
getSubject(): string | undefined;
|
|
117
|
+
getSender(): string | undefined;
|
|
118
|
+
getRecipients(): readonly string[];
|
|
119
|
+
getSent(): string | undefined;
|
|
120
|
+
getAttachmentTitle(): string | undefined;
|
|
121
|
+
getInnerBundleType(): string | undefined;
|
|
122
|
+
getResourcesByType<TResource extends FhirResource = FhirResource>(resourceType: string): readonly TResource[];
|
|
123
|
+
getAppointments(): readonly FhirResource[];
|
|
124
|
+
getDocumentReferences(): readonly FhirResource[];
|
|
125
|
+
}
|