vet-data-utils-ts 0.5.29 → 0.5.30

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,5 +1,18 @@
1
1
  # vet-data-utils-ts
2
2
 
3
+ ## Lost-animal access and behavior
4
+
5
+ `normalizeIso3166Jurisdiction(...)` and
6
+ `buildLostAnimalEmergencyJurisdictionActors(...)` create exact country or
7
+ subdivision Consent actors such as `urn:iso:3166-2:CA-BC`. The
8
+ `LostAnimalEmergencyAccess` profile limits standing access to licensed
9
+ veterinarians, emergency treatment and a minimal veterinary summary. GW still
10
+ verifies the credential, active licence, route jurisdiction and exact animal.
11
+
12
+ `buildAnimalBehaviorObservation(...)` records controller-reported temperament
13
+ and fear context as a claims-first social-history Observation. It deliberately
14
+ uses narrative text rather than inventing a veterinary diagnosis code.
15
+
3
16
  The product-local `place-service-directory` export models persistent public
4
17
  sites as claims-only Schema.org `Place` resources and their offerings as
5
18
  claims-only `Service` or `Product` resources. A care organization publishes
@@ -0,0 +1,18 @@
1
+ export type AnimalBehaviorObservationInput = Readonly<{
2
+ id: string;
3
+ subject: string;
4
+ observedAt: string;
5
+ language: string;
6
+ summary: string;
7
+ note?: string;
8
+ localLabel?: string;
9
+ }>;
10
+ export type AnimalBehaviorObservation = Readonly<{
11
+ resourceType: 'Observation';
12
+ id: string;
13
+ meta: Readonly<{
14
+ claims: Readonly<Record<string, string>>;
15
+ }>;
16
+ }>;
17
+ /** Builds one claims-first, controller-reported behavior Observation without inventing a diagnosis code. */
18
+ export declare function buildAnimalBehaviorObservation(input: AnimalBehaviorObservationInput): AnimalBehaviorObservation;
@@ -0,0 +1,44 @@
1
+ import { ObservationCategoryCodes } from 'gdc-common-utils-ts/constants/observation-category';
2
+ import { ObservationClaim } from 'gdc-common-utils-ts/models/interoperable-claims/observation-claims';
3
+ import { isVetChainAnimalCardDid } from './animal-card.js';
4
+ const ENGLISH_DISPLAY = 'Animal temperament and fear response';
5
+ function boundedText(value, name, max) {
6
+ const normalized = String(value || '').trim();
7
+ if (!normalized || normalized.length > max)
8
+ throw new TypeError(`animal_behavior_${name}_invalid`);
9
+ return normalized;
10
+ }
11
+ /** Builds one claims-first, controller-reported behavior Observation without inventing a diagnosis code. */
12
+ export function buildAnimalBehaviorObservation(input) {
13
+ const id = String(input.id || '').trim();
14
+ if (!/^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$/.test(id))
15
+ throw new TypeError('animal_behavior_id_invalid');
16
+ const subject = String(input.subject || '').trim();
17
+ if (!isVetChainAnimalCardDid(subject))
18
+ throw new TypeError('animal_behavior_animal_card_did_required');
19
+ const observedAt = String(input.observedAt || '').trim();
20
+ if (!observedAt || Number.isNaN(Date.parse(observedAt)))
21
+ throw new TypeError('animal_behavior_observedAt_invalid');
22
+ const language = String(input.language || '').trim();
23
+ if (!/^[a-z]{2,3}(?:-[A-Za-z0-9]{2,8})*$/.test(language))
24
+ throw new TypeError('animal_behavior_language_invalid');
25
+ const summary = boundedText(input.summary, 'summary', 1000);
26
+ const note = input.note === undefined ? undefined : boundedText(input.note, 'note', 1000);
27
+ const localLabel = input.localLabel === undefined ? ENGLISH_DISPLAY : boundedText(input.localLabel, 'local_label', 120);
28
+ const claims = {
29
+ '@context': 'org.hl7.fhir.api',
30
+ [ObservationClaim.Identifier]: id,
31
+ [ObservationClaim.Subject]: subject,
32
+ [ObservationClaim.Status]: 'final',
33
+ [ObservationClaim.Category]: ObservationCategoryCodes.SocialHistory.claim,
34
+ [ObservationClaim.CodeText]: localLabel,
35
+ [ObservationClaim.CodeDisplay]: ENGLISH_DISPLAY,
36
+ [ObservationClaim.ValueString]: summary,
37
+ [ObservationClaim.Date]: observedAt,
38
+ [ObservationClaim.EffectiveDateTime]: observedAt,
39
+ [ObservationClaim.Language]: language,
40
+ };
41
+ if (note)
42
+ claims[ObservationClaim.Note] = note;
43
+ return Object.freeze({ resourceType: 'Observation', id, meta: Object.freeze({ claims: Object.freeze(claims) }) });
44
+ }
package/dist/index.d.ts CHANGED
@@ -1,4 +1,5 @@
1
1
  export * from './animal-card.js';
2
+ export * from './animal-behavior.js';
2
3
  export * from './assistant.js';
3
4
  export * from './communication.js';
4
5
  export * from './clinical-terminology.js';
@@ -13,6 +14,7 @@ export * from './international-health-card.js';
13
14
  export * from './index-projection-tags.js';
14
15
  export * from './insurance-consent.js';
15
16
  export * from './iso-jurisdictions.js';
17
+ export * from './lost-animal-access.js';
16
18
  export * from './organization-application.js';
17
19
  export * from './payment.js';
18
20
  export * from './place-service-directory.js';
package/dist/index.js CHANGED
@@ -1,4 +1,5 @@
1
1
  export * from './animal-card.js';
2
+ export * from './animal-behavior.js';
2
3
  export * from './assistant.js';
3
4
  export * from './communication.js';
4
5
  export * from './clinical-terminology.js';
@@ -13,6 +14,7 @@ export * from './international-health-card.js';
13
14
  export * from './index-projection-tags.js';
14
15
  export * from './insurance-consent.js';
15
16
  export * from './iso-jurisdictions.js';
17
+ export * from './lost-animal-access.js';
16
18
  export * from './organization-application.js';
17
19
  export * from './payment.js';
18
20
  export * from './place-service-directory.js';
@@ -0,0 +1,23 @@
1
+ export type Iso3166Jurisdiction = Readonly<{
2
+ code: string;
3
+ countryCode: string;
4
+ kind: 'country' | 'subdivision';
5
+ actorIdentifier: string;
6
+ }>;
7
+ /** Normalizes an ISO 3166 country or subdivision into its canonical Consent actor. */
8
+ export declare function normalizeIso3166Jurisdiction(input: unknown): Iso3166Jurisdiction;
9
+ /** Builds a deterministic, duplicate-free actor list for controller-authored regional Consent rules. */
10
+ export declare function buildLostAnimalEmergencyJurisdictionActors(input: readonly unknown[]): readonly string[];
11
+ /**
12
+ * Least-privilege standing access profile for a lost animal.
13
+ *
14
+ * A matching rule is not proof that the requester is a veterinarian: GW must
15
+ * independently verify the professional credential, active licence, route
16
+ * jurisdiction and exact animal subject before issuing a short-lived token.
17
+ */
18
+ export declare const LostAnimalEmergencyAccess: Readonly<{
19
+ actorRole: "ISCO-08|2250";
20
+ purpose: "ETREAT";
21
+ resourceTypes: readonly ["Composition"];
22
+ sections: readonly `LOINC|${string}`[];
23
+ }>;
@@ -0,0 +1,45 @@
1
+ import { HealthcareActorRoles, HealthcareConsentPurposes } from 'gdc-common-utils-ts/constants/healthcare';
2
+ import { isIso3166CountryCode, isIso3166SubdivisionForCountry } from './iso-jurisdictions.js';
3
+ import { VeterinarySummarySections } from './veterinary-sections.js';
4
+ const countryActor = /^urn:iso:3166:([a-z]{2})$/i;
5
+ const subdivisionActor = /^urn:iso:3166-2:([a-z]{2}-[a-z0-9]{1,3})$/i;
6
+ /** Normalizes an ISO 3166 country or subdivision into its canonical Consent actor. */
7
+ export function normalizeIso3166Jurisdiction(input) {
8
+ const raw = String(input || '').trim();
9
+ const unwrapped = countryActor.exec(raw)?.[1] || subdivisionActor.exec(raw)?.[1] || raw;
10
+ const code = unwrapped.toUpperCase();
11
+ const countryCode = code.slice(0, 2);
12
+ if (code.length === 2 && isIso3166CountryCode(code)) {
13
+ return Object.freeze({ code, countryCode, kind: 'country', actorIdentifier: `urn:iso:3166:${code}` });
14
+ }
15
+ if (isIso3166CountryCode(countryCode) && isIso3166SubdivisionForCountry(code, countryCode)) {
16
+ return Object.freeze({ code, countryCode, kind: 'subdivision', actorIdentifier: `urn:iso:3166-2:${code}` });
17
+ }
18
+ throw new TypeError('lost_animal_access_iso_3166_jurisdiction_invalid');
19
+ }
20
+ /** Builds a deterministic, duplicate-free actor list for controller-authored regional Consent rules. */
21
+ export function buildLostAnimalEmergencyJurisdictionActors(input) {
22
+ if (!Array.isArray(input) || input.length === 0)
23
+ throw new TypeError('lost_animal_access_jurisdiction_required');
24
+ return Object.freeze([...new Set(input.map(value => normalizeIso3166Jurisdiction(value).actorIdentifier))]);
25
+ }
26
+ /**
27
+ * Least-privilege standing access profile for a lost animal.
28
+ *
29
+ * A matching rule is not proof that the requester is a veterinarian: GW must
30
+ * independently verify the professional credential, active licence, route
31
+ * jurisdiction and exact animal subject before issuing a short-lived token.
32
+ */
33
+ export const LostAnimalEmergencyAccess = Object.freeze({
34
+ actorRole: HealthcareActorRoles.Veterinarian,
35
+ purpose: HealthcareConsentPurposes.EmergencyTreatment,
36
+ resourceTypes: Object.freeze(['Composition']),
37
+ sections: Object.freeze([
38
+ VeterinarySummarySections.Alerts.value,
39
+ VeterinarySummarySections.Allergies.value,
40
+ VeterinarySummarySections.Medications.value,
41
+ VeterinarySummarySections.Immunizations.value,
42
+ VeterinarySummarySections.Problems.value,
43
+ VeterinarySummarySections.EnvironmentAndLifestyle.value,
44
+ ]),
45
+ });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vet-data-utils-ts",
3
- "version": "0.5.29",
3
+ "version": "0.5.30",
4
4
  "description": "Browser-safe governed VetChain data contracts",
5
5
  "license": "Apache-2.0",
6
6
  "author": "Connecting Solution & Applications Ltd",
@@ -16,6 +16,10 @@
16
16
  "types": "./dist/animal-card.d.ts",
17
17
  "default": "./dist/animal-card.js"
18
18
  },
19
+ "./animal-behavior": {
20
+ "types": "./dist/animal-behavior.d.ts",
21
+ "default": "./dist/animal-behavior.js"
22
+ },
19
23
  "./communication": {
20
24
  "types": "./dist/communication.d.ts",
21
25
  "default": "./dist/communication.js"
@@ -68,6 +72,10 @@
68
72
  "types": "./dist/iso-jurisdictions.d.ts",
69
73
  "default": "./dist/iso-jurisdictions.js"
70
74
  },
75
+ "./lost-animal-access": {
76
+ "types": "./dist/lost-animal-access.d.ts",
77
+ "default": "./dist/lost-animal-access.js"
78
+ },
71
79
  "./organization-application": {
72
80
  "types": "./dist/organization-application.d.ts",
73
81
  "default": "./dist/organization-application.js"