fhir-data-utils-ts 0.6.1 → 0.6.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/CHANGELOG.md CHANGED
@@ -2,6 +2,21 @@
2
2
 
3
3
  ## Unreleased
4
4
 
5
+ - Publish repository-safe Appointment/Communication and Encounter-transfer
6
+ fixtures from the explicit `fhir-data-utils-ts/data` entry point. Their
7
+ `*.data.ts` implementations are excluded from executable coverage while the
8
+ historical source modules remain compatibility reexports.
9
+ - Remove notification-channel policy from the general root and `builders`
10
+ surfaces. The historical reminder subpath and non-standard `Task.channel`
11
+ claim remain deprecated compatibility only while product packages migrate;
12
+ SOS/Vet/UHC own channel choices and dispatch behavior.
13
+
14
+ ## 0.6.2 - 2026-09-30
15
+
16
+ - Add strict FHIR `instant` to Unix epoch-second derivation while preserving
17
+ the boundary between clinical time, `Encounter.id`, provider business
18
+ identifiers and human display codes.
19
+
5
20
  ## 0.6.1 - 2026-09-30
6
21
 
7
22
  - Add canonical flat claims, a claims-first builder and native R5 projection
package/README.md CHANGED
@@ -92,6 +92,12 @@ metadata and protected endpoint references only. DICOM instances and pixel
92
92
  payloads remain outside this neutral package and are never embedded as flat
93
93
  claims.
94
94
 
95
+ FHIR instants, resource ids and provider business identifiers remain separate.
96
+ Use `fhirInstantToEpochSeconds(...)` only when a downstream convention needs a
97
+ derived whole-second value; retain the original timezone-bearing instant and
98
+ an independent `Encounter.id`. See
99
+ [`docs/ENCOUNTER_IDENTIFIERS_AND_TIME.md`](docs/ENCOUNTER_IDENTIFIERS_AND_TIME.md).
100
+
95
101
  No consumer should copy claim paths or rebuild these structures with literals.
96
102
  Use `fhir-data-utils-ts/claims`, `/converters`, `/fhir-bundle`,
97
103
  `/fhir-search-parameters`, `/clinical-terminology`, `/group-r5` or
@@ -1,63 +1,2 @@
1
- import type { FhirBundle, FhirResource } from './fhir-types.js';
2
- /** Repository-safe reusable evidence for appointment Bundle and calendar tests. */
3
- export declare const FHIR_APPOINTMENT_COMMUNICATION_TEST_DATA: Readonly<{
4
- release: "r5";
5
- start: "2026-10-05T16:00:00.000Z";
6
- end: "2026-10-05T16:30:00.000Z";
7
- communicationId: "communication-one";
8
- subjectReference: "Patient/animal-one";
9
- senderReference: "Organization/clinic-one";
10
- recipientReference: "RelatedPerson/controller-one";
11
- appointmentReference: "Appointment/appointment-one";
12
- calendarData: string;
13
- appointment: Readonly<{
14
- [key: string]: unknown;
15
- resourceType: string;
16
- id?: string;
17
- language?: string;
18
- meta?: Readonly<Record<string, unknown>>;
19
- contained?: readonly FhirResource[];
20
- }>;
21
- calendarDocument: Readonly<{
22
- [key: string]: unknown;
23
- resourceType: string;
24
- id?: string;
25
- language?: string;
26
- meta?: Readonly<Record<string, unknown>>;
27
- contained?: readonly FhirResource[];
28
- }>;
29
- communication: Readonly<{
30
- [key: string]: unknown;
31
- resourceType: string;
32
- id?: string;
33
- language?: string;
34
- meta?: Readonly<Record<string, unknown>>;
35
- contained?: readonly FhirResource[];
36
- }>;
37
- outerBatch: FhirBundle;
38
- outerBatchWithInvalidDocument: FhirBundle;
39
- outerBatchWithInvalidInnerBatch: FhirBundle;
40
- outerBatchWithBareAppointment: Readonly<{
41
- resourceType: "Bundle";
42
- type: "batch";
43
- entry: {
44
- resource: {
45
- payload: {
46
- contentAttachment: {
47
- contentType: string;
48
- data: string;
49
- };
50
- }[];
51
- resourceType: string;
52
- id?: string;
53
- language?: string;
54
- meta?: Readonly<Record<string, unknown>>;
55
- contained?: readonly FhirResource[];
56
- };
57
- request: {
58
- method: string;
59
- url: string;
60
- };
61
- }[];
62
- }>;
63
- }>;
1
+ /** @deprecated Import reusable fixtures from `fhir-data-utils-ts/data`. */
2
+ export * from './data/appointment-communication.data.js';
@@ -1,77 +1,2 @@
1
- const APPOINTMENT_ID = 'appointment-one';
2
- const COMMUNICATION_ID = 'communication-one';
3
- const CALENDAR_DOCUMENT_ID = 'appointment-calendar-one';
4
- const SUBJECT_REFERENCE = 'Patient/animal-one';
5
- const SENDER_REFERENCE = 'Organization/clinic-one';
6
- const RECIPIENT_REFERENCE = 'RelatedPerson/controller-one';
7
- const APPOINTMENT_REFERENCE = `Appointment/${APPOINTMENT_ID}`;
8
- const CALENDAR_DOCUMENT_REFERENCE = `DocumentReference/${CALENDAR_DOCUMENT_ID}`;
9
- const APPOINTMENT_START = '2026-10-05T16:00:00.000Z';
10
- const APPOINTMENT_END = '2026-10-05T16:30:00.000Z';
11
- const CALENDAR_DATA = encodeBase64Utf8('BEGIN:VCALENDAR\r\nVERSION:2.0\r\nBEGIN:VEVENT\r\nDTSTART:20261005T160000Z\r\nDTEND:20261005T163000Z\r\nEND:VEVENT\r\nEND:VCALENDAR\r\n');
12
- const APPOINTMENT = Object.freeze({
13
- resourceType: 'Appointment', id: APPOINTMENT_ID, identifier: [{ value: APPOINTMENT_ID }], status: 'booked',
14
- start: APPOINTMENT_START, end: APPOINTMENT_END,
15
- participant: [{ actor: { reference: SUBJECT_REFERENCE }, status: 'accepted' }, { actor: { reference: 'PractitionerRole/veterinarian-one' }, status: 'accepted' }, { actor: { reference: 'Location/consultation-one' }, status: 'accepted' }],
16
- slot: [{ reference: 'Slot/consultation-one' }], supportingInformation: [{ reference: CALENDAR_DOCUMENT_REFERENCE }],
17
- });
18
- const CALENDAR_DOCUMENT = Object.freeze({
19
- resourceType: 'DocumentReference', id: CALENDAR_DOCUMENT_ID, identifier: [{ value: CALENDAR_DOCUMENT_ID }], status: 'current',
20
- subject: { reference: SUBJECT_REFERENCE }, context: { related: [{ reference: APPOINTMENT_REFERENCE }] },
21
- content: [{ attachment: { contentType: 'text/calendar', data: CALENDAR_DATA, title: 'appointment.ics' } }],
22
- });
23
- const INNER_BUNDLE = Object.freeze({ resourceType: 'Bundle', type: 'collection', entry: [{ resource: APPOINTMENT }, { resource: CALENDAR_DOCUMENT }] });
24
- const COMMUNICATION = Object.freeze({
25
- resourceType: 'Communication', id: COMMUNICATION_ID, identifier: [{ value: COMMUNICATION_ID }], status: 'completed',
26
- subject: { reference: SUBJECT_REFERENCE }, recipient: [{ reference: RECIPIENT_REFERENCE }], sender: { reference: SENDER_REFERENCE },
27
- payload: [{ contentAttachment: { contentType: 'application/fhir+json', data: encodeBase64Utf8(JSON.stringify(INNER_BUNDLE)), title: 'appointment-bundle.json' } }],
28
- });
29
- function communicationWithInnerBundle(innerBundle) {
30
- return Object.freeze({
31
- ...COMMUNICATION,
32
- payload: [{ contentAttachment: { contentType: 'application/fhir+json', data: encodeBase64Utf8(JSON.stringify(innerBundle)) } }],
33
- });
34
- }
35
- function outerBatchWithCommunication(communication) {
36
- return Object.freeze({
37
- resourceType: 'Bundle',
38
- type: 'batch',
39
- entry: [{ resource: communication, request: { method: 'POST', url: 'Communication' } }],
40
- });
41
- }
42
- /** Repository-safe reusable evidence for appointment Bundle and calendar tests. */
43
- export const FHIR_APPOINTMENT_COMMUNICATION_TEST_DATA = Object.freeze({
44
- release: 'r5',
45
- start: APPOINTMENT_START,
46
- end: APPOINTMENT_END,
47
- communicationId: COMMUNICATION_ID,
48
- subjectReference: SUBJECT_REFERENCE,
49
- senderReference: SENDER_REFERENCE,
50
- recipientReference: RECIPIENT_REFERENCE,
51
- appointmentReference: APPOINTMENT_REFERENCE,
52
- calendarData: CALENDAR_DATA,
53
- appointment: APPOINTMENT,
54
- calendarDocument: CALENDAR_DOCUMENT,
55
- communication: COMMUNICATION,
56
- outerBatch: outerBatchWithCommunication(COMMUNICATION),
57
- outerBatchWithInvalidDocument: outerBatchWithCommunication(communicationWithInnerBundle(Object.freeze({
58
- resourceType: 'Bundle',
59
- type: 'document',
60
- entry: [{ resource: APPOINTMENT }],
61
- }))),
62
- outerBatchWithInvalidInnerBatch: outerBatchWithCommunication(communicationWithInnerBundle(Object.freeze({
63
- resourceType: 'Bundle',
64
- type: 'batch',
65
- entry: [{ resource: APPOINTMENT }],
66
- }))),
67
- outerBatchWithBareAppointment: Object.freeze({
68
- resourceType: 'Bundle', type: 'batch', entry: [{ resource: { ...COMMUNICATION, payload: [{ contentAttachment: { contentType: 'application/fhir+json', data: encodeBase64Utf8(JSON.stringify(APPOINTMENT)) } }] }, request: { method: 'POST', url: 'Communication' } }],
69
- }),
70
- });
71
- function encodeBase64Utf8(value) {
72
- const bytes = new TextEncoder().encode(value);
73
- let binary = '';
74
- for (const byte of bytes)
75
- binary += String.fromCharCode(byte);
76
- return globalThis.btoa(binary);
77
- }
1
+ /** @deprecated Import reusable fixtures from `fhir-data-utils-ts/data`. */
2
+ export * from './data/appointment-communication.data.js';
@@ -5,6 +5,10 @@ export declare const ImmunizationReminderTaskValues: Readonly<{
5
5
  readonly Code: "immunization-reminder";
6
6
  readonly TriggerType: "scheduled";
7
7
  }>;
8
+ /**
9
+ * @deprecated Compatibility only. Notification-channel policy belongs to the
10
+ * consuming SOS/Vet/UHC data package, not to the general FHIR data package.
11
+ */
8
12
  export declare const ImmunizationReminderChannels: readonly ["push", "email", "sms", "whatsapp", "telephone"];
9
13
  export type ImmunizationReminderChannel = (typeof ImmunizationReminderChannels)[number];
10
14
  export type ImmunizationReminderPlanInput = Readonly<{
@@ -8,6 +8,10 @@ export const ImmunizationReminderTaskValues = Object.freeze({
8
8
  Code: 'immunization-reminder',
9
9
  TriggerType: 'scheduled',
10
10
  });
11
+ /**
12
+ * @deprecated Compatibility only. Notification-channel policy belongs to the
13
+ * consuming SOS/Vet/UHC data package, not to the general FHIR data package.
14
+ */
11
15
  export const ImmunizationReminderChannels = Object.freeze([
12
16
  'push',
13
17
  'email',
@@ -3,4 +3,3 @@ export * from './department-service-graph.js';
3
3
  export * from './service-schedule-graph.js';
4
4
  export * from './device-compliance-graph.js';
5
5
  export * from './immunization-graph.js';
6
- export * from './immunization-reminders.js';
@@ -3,4 +3,3 @@ export * from './department-service-graph.js';
3
3
  export * from './service-schedule-graph.js';
4
4
  export * from './device-compliance-graph.js';
5
5
  export * from './immunization-graph.js';
6
- export * from './immunization-reminders.js';
@@ -21,6 +21,7 @@ export declare enum TaskClaimsFhirApi {
21
21
  BasedOn = "Task.based-on",
22
22
  BasedOnDisplay = "Task.based-on-display",
23
23
  Language = "Task.language",
24
+ /** @deprecated Non-standard compatibility claim. Model delivery policy outside FHIR. */
24
25
  Channel = "Task.channel",
25
26
  AuthoredOn = "Task.authored-on",
26
27
  LastModified = "Task.last-modified",
@@ -24,6 +24,7 @@ export var TaskClaimsFhirApi;
24
24
  TaskClaimsFhirApi["BasedOn"] = "Task.based-on";
25
25
  TaskClaimsFhirApi["BasedOnDisplay"] = "Task.based-on-display";
26
26
  TaskClaimsFhirApi["Language"] = "Task.language";
27
+ /** @deprecated Non-standard compatibility claim. Model delivery policy outside FHIR. */
27
28
  TaskClaimsFhirApi["Channel"] = "Task.channel";
28
29
  TaskClaimsFhirApi["AuthoredOn"] = "Task.authored-on";
29
30
  TaskClaimsFhirApi["LastModified"] = "Task.last-modified";
@@ -0,0 +1,63 @@
1
+ import type { FhirBundle, FhirResource } from '../fhir-types.js';
2
+ /** Repository-safe reusable evidence for appointment Bundle and calendar tests. */
3
+ export declare const FHIR_APPOINTMENT_COMMUNICATION_TEST_DATA: Readonly<{
4
+ release: "r5";
5
+ start: "2026-10-05T16:00:00.000Z";
6
+ end: "2026-10-05T16:30:00.000Z";
7
+ communicationId: "communication-one";
8
+ subjectReference: "Patient/animal-one";
9
+ senderReference: "Organization/clinic-one";
10
+ recipientReference: "RelatedPerson/controller-one";
11
+ appointmentReference: "Appointment/appointment-one";
12
+ calendarData: string;
13
+ appointment: Readonly<{
14
+ [key: string]: unknown;
15
+ resourceType: string;
16
+ id?: string;
17
+ language?: string;
18
+ meta?: Readonly<Record<string, unknown>>;
19
+ contained?: readonly FhirResource[];
20
+ }>;
21
+ calendarDocument: Readonly<{
22
+ [key: string]: unknown;
23
+ resourceType: string;
24
+ id?: string;
25
+ language?: string;
26
+ meta?: Readonly<Record<string, unknown>>;
27
+ contained?: readonly FhirResource[];
28
+ }>;
29
+ communication: Readonly<{
30
+ [key: string]: unknown;
31
+ resourceType: string;
32
+ id?: string;
33
+ language?: string;
34
+ meta?: Readonly<Record<string, unknown>>;
35
+ contained?: readonly FhirResource[];
36
+ }>;
37
+ outerBatch: FhirBundle;
38
+ outerBatchWithInvalidDocument: FhirBundle;
39
+ outerBatchWithInvalidInnerBatch: FhirBundle;
40
+ outerBatchWithBareAppointment: Readonly<{
41
+ resourceType: "Bundle";
42
+ type: "batch";
43
+ entry: {
44
+ resource: {
45
+ payload: {
46
+ contentAttachment: {
47
+ contentType: string;
48
+ data: string;
49
+ };
50
+ }[];
51
+ resourceType: string;
52
+ id?: string;
53
+ language?: string;
54
+ meta?: Readonly<Record<string, unknown>>;
55
+ contained?: readonly FhirResource[];
56
+ };
57
+ request: {
58
+ method: string;
59
+ url: string;
60
+ };
61
+ }[];
62
+ }>;
63
+ }>;
@@ -0,0 +1,77 @@
1
+ const APPOINTMENT_ID = 'appointment-one';
2
+ const COMMUNICATION_ID = 'communication-one';
3
+ const CALENDAR_DOCUMENT_ID = 'appointment-calendar-one';
4
+ const SUBJECT_REFERENCE = 'Patient/animal-one';
5
+ const SENDER_REFERENCE = 'Organization/clinic-one';
6
+ const RECIPIENT_REFERENCE = 'RelatedPerson/controller-one';
7
+ const APPOINTMENT_REFERENCE = `Appointment/${APPOINTMENT_ID}`;
8
+ const CALENDAR_DOCUMENT_REFERENCE = `DocumentReference/${CALENDAR_DOCUMENT_ID}`;
9
+ const APPOINTMENT_START = '2026-10-05T16:00:00.000Z';
10
+ const APPOINTMENT_END = '2026-10-05T16:30:00.000Z';
11
+ const CALENDAR_DATA = encodeBase64Utf8('BEGIN:VCALENDAR\r\nVERSION:2.0\r\nBEGIN:VEVENT\r\nDTSTART:20261005T160000Z\r\nDTEND:20261005T163000Z\r\nEND:VEVENT\r\nEND:VCALENDAR\r\n');
12
+ const APPOINTMENT = Object.freeze({
13
+ resourceType: 'Appointment', id: APPOINTMENT_ID, identifier: [{ value: APPOINTMENT_ID }], status: 'booked',
14
+ start: APPOINTMENT_START, end: APPOINTMENT_END,
15
+ participant: [{ actor: { reference: SUBJECT_REFERENCE }, status: 'accepted' }, { actor: { reference: 'PractitionerRole/veterinarian-one' }, status: 'accepted' }, { actor: { reference: 'Location/consultation-one' }, status: 'accepted' }],
16
+ slot: [{ reference: 'Slot/consultation-one' }], supportingInformation: [{ reference: CALENDAR_DOCUMENT_REFERENCE }],
17
+ });
18
+ const CALENDAR_DOCUMENT = Object.freeze({
19
+ resourceType: 'DocumentReference', id: CALENDAR_DOCUMENT_ID, identifier: [{ value: CALENDAR_DOCUMENT_ID }], status: 'current',
20
+ subject: { reference: SUBJECT_REFERENCE }, context: { related: [{ reference: APPOINTMENT_REFERENCE }] },
21
+ content: [{ attachment: { contentType: 'text/calendar', data: CALENDAR_DATA, title: 'appointment.ics' } }],
22
+ });
23
+ const INNER_BUNDLE = Object.freeze({ resourceType: 'Bundle', type: 'collection', entry: [{ resource: APPOINTMENT }, { resource: CALENDAR_DOCUMENT }] });
24
+ const COMMUNICATION = Object.freeze({
25
+ resourceType: 'Communication', id: COMMUNICATION_ID, identifier: [{ value: COMMUNICATION_ID }], status: 'completed',
26
+ subject: { reference: SUBJECT_REFERENCE }, recipient: [{ reference: RECIPIENT_REFERENCE }], sender: { reference: SENDER_REFERENCE },
27
+ payload: [{ contentAttachment: { contentType: 'application/fhir+json', data: encodeBase64Utf8(JSON.stringify(INNER_BUNDLE)), title: 'appointment-bundle.json' } }],
28
+ });
29
+ function communicationWithInnerBundle(innerBundle) {
30
+ return Object.freeze({
31
+ ...COMMUNICATION,
32
+ payload: [{ contentAttachment: { contentType: 'application/fhir+json', data: encodeBase64Utf8(JSON.stringify(innerBundle)) } }],
33
+ });
34
+ }
35
+ function outerBatchWithCommunication(communication) {
36
+ return Object.freeze({
37
+ resourceType: 'Bundle',
38
+ type: 'batch',
39
+ entry: [{ resource: communication, request: { method: 'POST', url: 'Communication' } }],
40
+ });
41
+ }
42
+ /** Repository-safe reusable evidence for appointment Bundle and calendar tests. */
43
+ export const FHIR_APPOINTMENT_COMMUNICATION_TEST_DATA = Object.freeze({
44
+ release: 'r5',
45
+ start: APPOINTMENT_START,
46
+ end: APPOINTMENT_END,
47
+ communicationId: COMMUNICATION_ID,
48
+ subjectReference: SUBJECT_REFERENCE,
49
+ senderReference: SENDER_REFERENCE,
50
+ recipientReference: RECIPIENT_REFERENCE,
51
+ appointmentReference: APPOINTMENT_REFERENCE,
52
+ calendarData: CALENDAR_DATA,
53
+ appointment: APPOINTMENT,
54
+ calendarDocument: CALENDAR_DOCUMENT,
55
+ communication: COMMUNICATION,
56
+ outerBatch: outerBatchWithCommunication(COMMUNICATION),
57
+ outerBatchWithInvalidDocument: outerBatchWithCommunication(communicationWithInnerBundle(Object.freeze({
58
+ resourceType: 'Bundle',
59
+ type: 'document',
60
+ entry: [{ resource: APPOINTMENT }],
61
+ }))),
62
+ outerBatchWithInvalidInnerBatch: outerBatchWithCommunication(communicationWithInnerBundle(Object.freeze({
63
+ resourceType: 'Bundle',
64
+ type: 'batch',
65
+ entry: [{ resource: APPOINTMENT }],
66
+ }))),
67
+ outerBatchWithBareAppointment: Object.freeze({
68
+ resourceType: 'Bundle', type: 'batch', entry: [{ resource: { ...COMMUNICATION, payload: [{ contentAttachment: { contentType: 'application/fhir+json', data: encodeBase64Utf8(JSON.stringify(APPOINTMENT)) } }] }, request: { method: 'POST', url: 'Communication' } }],
69
+ }),
70
+ });
71
+ function encodeBase64Utf8(value) {
72
+ const bytes = new TextEncoder().encode(value);
73
+ let binary = '';
74
+ for (const byte of bytes)
75
+ binary += String.fromCharCode(byte);
76
+ return globalThis.btoa(binary);
77
+ }
@@ -0,0 +1,41 @@
1
+ import { EncounterStatusR5 } from '../claims/encounter-claims.js';
2
+ /** Product-neutral identifiers and references for cross-package Encounter transfer contract tests. */
3
+ export declare const FHIR_ENCOUNTER_TRANSFER_TEST_DATA: Readonly<{
4
+ communicationIdentifier: "urn:uuid:00000000-0000-4000-8000-000000000401";
5
+ subjectReference: "Patient/00000000-0000-4000-8000-000000000402";
6
+ senderReference: "Organization/00000000-0000-4000-8000-000000000403";
7
+ indexRecipientReference: "Organization/00000000-0000-4000-8000-000000000404";
8
+ occurredAt: "2026-09-30T10:10:00Z";
9
+ invalidOccurredAtWithoutTimezone: "2026-09-30T10:10:00";
10
+ class: Readonly<{
11
+ system: "http://terminology.hl7.org/CodeSystem/v3-ActCode";
12
+ code: "EMER";
13
+ }>;
14
+ source: Readonly<{
15
+ id: "00000000-0000-4000-8000-000000000405";
16
+ reference: "Encounter/00000000-0000-4000-8000-000000000405";
17
+ identifier: "urn:uuid:00000000-0000-4000-8000-000000000405";
18
+ serviceReference: "HealthcareService/00000000-0000-4000-8000-000000000406";
19
+ locationReference: "Location/00000000-0000-4000-8000-000000000407";
20
+ statusWhenReturning: EncounterStatusR5.OnHold;
21
+ statusWhenNotReturning: EncounterStatusR5.Completed;
22
+ }>;
23
+ destination: Readonly<{
24
+ id: "00000000-0000-4000-8000-000000000408";
25
+ reference: "Encounter/00000000-0000-4000-8000-000000000408";
26
+ identifier: "urn:uuid:00000000-0000-4000-8000-000000000408";
27
+ serviceReference: "HealthcareService/00000000-0000-4000-8000-000000000409";
28
+ locationReference: "Location/00000000-0000-4000-8000-000000000410";
29
+ statusOnArrival: EncounterStatusR5.InProgress;
30
+ }>;
31
+ sourceHistory: Readonly<{
32
+ id: "00000000-0000-4000-8000-000000000411";
33
+ identifier: "urn:uuid:00000000-0000-4000-8000-000000000411";
34
+ encounterReference: "Encounter/00000000-0000-4000-8000-000000000405";
35
+ }>;
36
+ destinationHistory: Readonly<{
37
+ id: "00000000-0000-4000-8000-000000000412";
38
+ identifier: "urn:uuid:00000000-0000-4000-8000-000000000412";
39
+ encounterReference: "Encounter/00000000-0000-4000-8000-000000000408";
40
+ }>;
41
+ }>;
@@ -0,0 +1,38 @@
1
+ import { EncounterStatusR5 } from '../claims/encounter-claims.js';
2
+ /** Product-neutral identifiers and references for cross-package Encounter transfer contract tests. */
3
+ export const FHIR_ENCOUNTER_TRANSFER_TEST_DATA = Object.freeze({
4
+ communicationIdentifier: 'urn:uuid:00000000-0000-4000-8000-000000000401',
5
+ subjectReference: 'Patient/00000000-0000-4000-8000-000000000402',
6
+ senderReference: 'Organization/00000000-0000-4000-8000-000000000403',
7
+ indexRecipientReference: 'Organization/00000000-0000-4000-8000-000000000404',
8
+ occurredAt: '2026-09-30T10:10:00Z',
9
+ invalidOccurredAtWithoutTimezone: '2026-09-30T10:10:00',
10
+ class: Object.freeze({ system: 'http://terminology.hl7.org/CodeSystem/v3-ActCode', code: 'EMER' }),
11
+ source: Object.freeze({
12
+ id: '00000000-0000-4000-8000-000000000405',
13
+ reference: 'Encounter/00000000-0000-4000-8000-000000000405',
14
+ identifier: 'urn:uuid:00000000-0000-4000-8000-000000000405',
15
+ serviceReference: 'HealthcareService/00000000-0000-4000-8000-000000000406',
16
+ locationReference: 'Location/00000000-0000-4000-8000-000000000407',
17
+ statusWhenReturning: EncounterStatusR5.OnHold,
18
+ statusWhenNotReturning: EncounterStatusR5.Completed,
19
+ }),
20
+ destination: Object.freeze({
21
+ id: '00000000-0000-4000-8000-000000000408',
22
+ reference: 'Encounter/00000000-0000-4000-8000-000000000408',
23
+ identifier: 'urn:uuid:00000000-0000-4000-8000-000000000408',
24
+ serviceReference: 'HealthcareService/00000000-0000-4000-8000-000000000409',
25
+ locationReference: 'Location/00000000-0000-4000-8000-000000000410',
26
+ statusOnArrival: EncounterStatusR5.InProgress,
27
+ }),
28
+ sourceHistory: Object.freeze({
29
+ id: '00000000-0000-4000-8000-000000000411',
30
+ identifier: 'urn:uuid:00000000-0000-4000-8000-000000000411',
31
+ encounterReference: 'Encounter/00000000-0000-4000-8000-000000000405',
32
+ }),
33
+ destinationHistory: Object.freeze({
34
+ id: '00000000-0000-4000-8000-000000000412',
35
+ identifier: 'urn:uuid:00000000-0000-4000-8000-000000000412',
36
+ encounterReference: 'Encounter/00000000-0000-4000-8000-000000000408',
37
+ }),
38
+ });
@@ -0,0 +1,3 @@
1
+ /** Reusable, repository-safe examples for tests, docs and portal demos. */
2
+ export * from './appointment-communication.data.js';
3
+ export * from './encounter-transfer.data.js';
@@ -0,0 +1,3 @@
1
+ /** Reusable, repository-safe examples for tests, docs and portal demos. */
2
+ export * from './appointment-communication.data.js';
3
+ export * from './encounter-transfer.data.js';
@@ -1,40 +1,2 @@
1
- import { EncounterStatusR5 } from './claims/encounter-claims.js';
2
- /** Product-neutral identifiers and references for cross-package Encounter transfer contract tests. */
3
- export declare const FHIR_ENCOUNTER_TRANSFER_TEST_DATA: Readonly<{
4
- communicationIdentifier: "urn:uuid:00000000-0000-4000-8000-000000000401";
5
- subjectReference: "Patient/00000000-0000-4000-8000-000000000402";
6
- senderReference: "Organization/00000000-0000-4000-8000-000000000403";
7
- indexRecipientReference: "Organization/00000000-0000-4000-8000-000000000404";
8
- occurredAt: "2026-09-30T10:10:00Z";
9
- class: Readonly<{
10
- system: "http://terminology.hl7.org/CodeSystem/v3-ActCode";
11
- code: "EMER";
12
- }>;
13
- source: Readonly<{
14
- id: "00000000-0000-4000-8000-000000000405";
15
- reference: "Encounter/00000000-0000-4000-8000-000000000405";
16
- identifier: "urn:uuid:00000000-0000-4000-8000-000000000405";
17
- serviceReference: "HealthcareService/00000000-0000-4000-8000-000000000406";
18
- locationReference: "Location/00000000-0000-4000-8000-000000000407";
19
- statusWhenReturning: EncounterStatusR5.OnHold;
20
- statusWhenNotReturning: EncounterStatusR5.Completed;
21
- }>;
22
- destination: Readonly<{
23
- id: "00000000-0000-4000-8000-000000000408";
24
- reference: "Encounter/00000000-0000-4000-8000-000000000408";
25
- identifier: "urn:uuid:00000000-0000-4000-8000-000000000408";
26
- serviceReference: "HealthcareService/00000000-0000-4000-8000-000000000409";
27
- locationReference: "Location/00000000-0000-4000-8000-000000000410";
28
- statusOnArrival: EncounterStatusR5.InProgress;
29
- }>;
30
- sourceHistory: Readonly<{
31
- id: "00000000-0000-4000-8000-000000000411";
32
- identifier: "urn:uuid:00000000-0000-4000-8000-000000000411";
33
- encounterReference: "Encounter/00000000-0000-4000-8000-000000000405";
34
- }>;
35
- destinationHistory: Readonly<{
36
- id: "00000000-0000-4000-8000-000000000412";
37
- identifier: "urn:uuid:00000000-0000-4000-8000-000000000412";
38
- encounterReference: "Encounter/00000000-0000-4000-8000-000000000408";
39
- }>;
40
- }>;
1
+ /** @deprecated Import reusable fixtures from `fhir-data-utils-ts/data`. */
2
+ export * from './data/encounter-transfer.data.js';
@@ -1,37 +1,2 @@
1
- import { EncounterStatusR5 } from './claims/encounter-claims.js';
2
- /** Product-neutral identifiers and references for cross-package Encounter transfer contract tests. */
3
- export const FHIR_ENCOUNTER_TRANSFER_TEST_DATA = Object.freeze({
4
- communicationIdentifier: 'urn:uuid:00000000-0000-4000-8000-000000000401',
5
- subjectReference: 'Patient/00000000-0000-4000-8000-000000000402',
6
- senderReference: 'Organization/00000000-0000-4000-8000-000000000403',
7
- indexRecipientReference: 'Organization/00000000-0000-4000-8000-000000000404',
8
- occurredAt: '2026-09-30T10:10:00Z',
9
- class: Object.freeze({ system: 'http://terminology.hl7.org/CodeSystem/v3-ActCode', code: 'EMER' }),
10
- source: Object.freeze({
11
- id: '00000000-0000-4000-8000-000000000405',
12
- reference: 'Encounter/00000000-0000-4000-8000-000000000405',
13
- identifier: 'urn:uuid:00000000-0000-4000-8000-000000000405',
14
- serviceReference: 'HealthcareService/00000000-0000-4000-8000-000000000406',
15
- locationReference: 'Location/00000000-0000-4000-8000-000000000407',
16
- statusWhenReturning: EncounterStatusR5.OnHold,
17
- statusWhenNotReturning: EncounterStatusR5.Completed,
18
- }),
19
- destination: Object.freeze({
20
- id: '00000000-0000-4000-8000-000000000408',
21
- reference: 'Encounter/00000000-0000-4000-8000-000000000408',
22
- identifier: 'urn:uuid:00000000-0000-4000-8000-000000000408',
23
- serviceReference: 'HealthcareService/00000000-0000-4000-8000-000000000409',
24
- locationReference: 'Location/00000000-0000-4000-8000-000000000410',
25
- statusOnArrival: EncounterStatusR5.InProgress,
26
- }),
27
- sourceHistory: Object.freeze({
28
- id: '00000000-0000-4000-8000-000000000411',
29
- identifier: 'urn:uuid:00000000-0000-4000-8000-000000000411',
30
- encounterReference: 'Encounter/00000000-0000-4000-8000-000000000405',
31
- }),
32
- destinationHistory: Object.freeze({
33
- id: '00000000-0000-4000-8000-000000000412',
34
- identifier: 'urn:uuid:00000000-0000-4000-8000-000000000412',
35
- encounterReference: 'Encounter/00000000-0000-4000-8000-000000000408',
36
- }),
37
- });
1
+ /** @deprecated Import reusable fixtures from `fhir-data-utils-ts/data`. */
2
+ export * from './data/encounter-transfer.data.js';
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Derives whole Unix epoch seconds from a valid FHIR `instant`.
3
+ *
4
+ * A FHIR instant remains the authoritative ISO 8601 value with a timezone.
5
+ * Epoch seconds are a derived numeric representation and must never replace
6
+ * `Encounter.id`, `Encounter.identifier`, or the original clinical time.
7
+ */
8
+ export declare function fhirInstantToEpochSeconds(instant: string): number;
@@ -0,0 +1,16 @@
1
+ const FHIR_INSTANT_PATTERN = /^\d{4}-(?:0[1-9]|1[0-2])-(?:0[1-9]|[12]\d|3[01])T(?:[01]\d|2[0-3]):[0-5]\d:[0-5]\d(?:\.\d+)?(?:Z|[+-](?:[01]\d|2[0-3]):[0-5]\d)$/;
2
+ /**
3
+ * Derives whole Unix epoch seconds from a valid FHIR `instant`.
4
+ *
5
+ * A FHIR instant remains the authoritative ISO 8601 value with a timezone.
6
+ * Epoch seconds are a derived numeric representation and must never replace
7
+ * `Encounter.id`, `Encounter.identifier`, or the original clinical time.
8
+ */
9
+ export function fhirInstantToEpochSeconds(instant) {
10
+ if (!FHIR_INSTANT_PATTERN.test(instant))
11
+ throw new TypeError('fhir_instant_invalid');
12
+ const epochMilliseconds = Date.parse(instant);
13
+ if (!Number.isFinite(epochMilliseconds))
14
+ throw new TypeError('fhir_instant_invalid');
15
+ return Math.floor(epochMilliseconds / 1000);
16
+ }
package/dist/index.d.ts CHANGED
@@ -16,7 +16,6 @@ export * from './constants/index.js';
16
16
  export * from './clinical-terminology.js';
17
17
  export * from './care-emergency-alert.js';
18
18
  export * from './immunization-flat-claims.js';
19
- export * from './immunization-reminder-plan.js';
20
19
  export * from './builders/index.js';
21
20
  export * from './group-r5.js';
22
21
  export * from './research-study-r5.js';
@@ -25,5 +24,5 @@ export * from './related-person.js';
25
24
  export * from './imaging-types.js';
26
25
  export * from './subscription-r5.js';
27
26
  export * from './healthcare-service-specialty-map.js';
28
- export * from './appointment-communication-test-data.js';
29
- export * from './encounter-transfer-test-data.js';
27
+ export * from './data/index.js';
28
+ export * from './fhir-instant.js';
package/dist/index.js CHANGED
@@ -16,7 +16,6 @@ export * from './constants/index.js';
16
16
  export * from './clinical-terminology.js';
17
17
  export * from './care-emergency-alert.js';
18
18
  export * from './immunization-flat-claims.js';
19
- export * from './immunization-reminder-plan.js';
20
19
  export * from './builders/index.js';
21
20
  export * from './group-r5.js';
22
21
  export * from './research-study-r5.js';
@@ -25,5 +24,5 @@ export * from './related-person.js';
25
24
  export * from './imaging-types.js';
26
25
  export * from './subscription-r5.js';
27
26
  export * from './healthcare-service-specialty-map.js';
28
- export * from './appointment-communication-test-data.js';
29
- export * from './encounter-transfer-test-data.js';
27
+ export * from './data/index.js';
28
+ export * from './fhir-instant.js';
@@ -0,0 +1,19 @@
1
+ # Encounter identifiers and time
2
+
3
+ FHIR time and encounter identity are separate concepts.
4
+
5
+ - A FHIR `instant` is an ISO 8601 date and time with at least second precision
6
+ and an explicit timezone. It is not a Unix timestamp.
7
+ - Unix epoch seconds may be derived for sorting, interoperability or a
8
+ provider-owned business identifier, but they never replace the original
9
+ instant.
10
+ - `Encounter.id` is the FHIR resource identifier.
11
+ - `Encounter.identifier` contains the business identifiers assigned by the
12
+ care provider. Their namespace and uniqueness belong to the assigning
13
+ organization.
14
+ - A display code is not sufficient authorization or subject resolution. An
15
+ authoritative lookup must also verify the assigner and exact subject.
16
+
17
+ Reusable test data lives in `FHIR_ENCOUNTER_TRANSFER_TEST_DATA`. Tests and
18
+ downstream documentation import its named fields instead of duplicating raw
19
+ identifiers, timestamps or references.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "fhir-data-utils-ts",
3
- "version": "0.6.1",
3
+ "version": "0.6.3",
4
4
  "description": "FHIR-version-neutral flat-claim and SearchParameter data utilities",
5
5
  "license": "Apache-2.0",
6
6
  "type": "module",
@@ -122,6 +122,10 @@
122
122
  "./constants": {
123
123
  "types": "./dist/constants/index.d.ts",
124
124
  "default": "./dist/constants/index.js"
125
+ },
126
+ "./data": {
127
+ "types": "./dist/data/index.d.ts",
128
+ "default": "./dist/data/index.js"
125
129
  }
126
130
  },
127
131
  "files": [
@@ -136,7 +140,7 @@
136
140
  "build": "npm run clean && tsc -p tsconfig.json",
137
141
  "typecheck": "tsc -p tsconfig.json --noEmit",
138
142
  "test": "npm run build && node --test tests/*.test.mjs",
139
- "test:coverage": "node --test --experimental-test-coverage --test-coverage-include='dist/converters/*.js' --test-coverage-include='dist/builders/*.js' --test-coverage-include='dist/fhir-*.js' --test-coverage-lines=95 --test-coverage-functions=80 --test-coverage-branches=40 tests/*.test.mjs",
143
+ "test:coverage": "node --test --experimental-test-coverage --test-coverage-include='dist/converters/*.js' --test-coverage-include='dist/builders/*.js' --test-coverage-include='dist/fhir-*.js' --test-coverage-exclude='dist/**/*.data.js' --test-coverage-lines=95 --test-coverage-functions=80 --test-coverage-branches=40 tests/*.test.mjs",
140
144
  "check": "npm run typecheck && npm test && npm run test:coverage",
141
145
  "prepack": "npm run check"
142
146
  },