fhir-persistence 0.9.0 → 0.10.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 CHANGED
@@ -5,6 +5,56 @@ All notable changes to this project will be documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## [0.10.0] - 2025-03-24
9
+
10
+ ### Added
11
+
12
+ #### PERS-01: PUT-as-Create (Upsert)
13
+
14
+ - **`FhirStore.updateResource`** and **`FhirPersistence.updateResource`** — new `upsert` option; when `true` and resource does not exist, creates it instead of throwing `ResourceNotFoundError`
15
+ - Return type changed to `UpdateResourceResult<T>` with `{ resource, created }` — `created: true` for upsert-created resources, `false` for normal updates
16
+ - **`FhirPersistence.createResource`** — return type changed to `CreateResourceResult<T>` with `{ resource, created }` for consistency
17
+
18
+ #### PERS-02: Conditional Create (ifNoneExist)
19
+
20
+ - **`FhirPersistence.createResource`** — new `ifNoneExist` option accepting `ParsedSearchParam[]`; searches first, returns existing resource if exactly one match, throws `PreconditionFailedError` if multiple matches, creates new resource if no matches
21
+
22
+ #### PERS-06: Type-Level History
23
+
24
+ - **`FhirStore.readTypeHistory`** and **`FhirPersistence.readTypeHistory`** — new method for `GET /<ResourceType>/_history` queries with `_since`, `_count`, and cursor pagination support
25
+
26
+ #### Exports
27
+
28
+ - **`ConditionalService`** + types (`ConditionalCreateResult`, `ConditionalUpdateResult`, `ConditionalDeleteResult`) now exported from package entry point
29
+ - **`processTransactionV2`**, **`processBatchV2`** + bundle types (`Bundle`, `BundleEntry`, `BundleResponse`, `BundleResponseEntry`) now exported
30
+ - **`buildUrnMap`**, **`deepResolveUrns`** + `UrnTarget` type now exported
31
+ - **`FhirStore`** option/result types (`StoreUpdateResourceResult`, `StoreUpdateResourceOptions`) now exported
32
+ - **`FhirPersistence`** option/result types (`PersistenceCreateResourceOptions`, `CreateResourceResult`, `PersistenceUpdateResourceOptions`, `UpdateResourceResult`) now exported
33
+
34
+ ### Fixed
35
+
36
+ #### PERS-07: String `:exact` Search Modifier on HumanName
37
+
38
+ - **`where-builder.ts`** — `name:exact` search now matches against individual `family` and `given` columns in the HumanName lookup table instead of the concatenated `name` column
39
+ - Previously `name:exact=Smith` would fail to match because the `name` column contains `"Smith John"` (concatenated); now correctly matches if `family = "Smith"` OR `given = "Smith"`
40
+ - Fix applied to both v1 (PostgreSQL `$N`) and v2 (SQLite `?`) WHERE builders
41
+
42
+ #### Bundle Processor PUT Compatibility
43
+
44
+ - **`bundle-processor.ts`** — `processBatchEntry` PUT handler updated to extract `.resource` from `UpdateResourceResult` and use `upsert: true` for PUT-as-Create semantics; response status now correctly returns `201` for created resources
45
+
46
+ ### Changed
47
+
48
+ - **`FhirStore.updateResource`** — return type changed from `T & PersistedResource` to `UpdateResourceResult<T>` (breaking change for direct callers)
49
+ - **`FhirPersistence.createResource`** — return type changed from `T & PersistedResource` to `CreateResourceResult<T>` (breaking change for direct callers)
50
+ - **`FhirPersistence.updateResource`** — return type changed from `T & PersistedResource` to `UpdateResourceResult<T>` (breaking change for direct callers)
51
+
52
+ ### Test Coverage
53
+
54
+ - **1057 passing tests**, 8 skipped, across 63 test files — no regressions
55
+ - All existing tests updated for new `UpdateResourceResult` / `CreateResourceResult` return types
56
+ - PERS-07 test assertions updated to verify per-component HumanName matching
57
+
8
58
  ## [0.9.0] - 2025-03-20
9
59
 
10
60
  ### Fixed
package/README.md CHANGED
@@ -5,7 +5,7 @@ Embedded FHIR R4 persistence layer — CRUD, search, indexing, and schema migrat
5
5
  [![npm version](https://img.shields.io/npm/v/fhir-persistence)](https://www.npmjs.com/package/fhir-persistence)
6
6
  [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](./LICENSE)
7
7
 
8
- > **v0.9.0** — Token search fix: FHIR-correct code-only / empty-system matching (`|code`, `code`)
8
+ > **v0.10.0** — PUT-as-Create (upsert), Conditional Create, Type-Level History, HumanName `:exact` fix
9
9
 
10
10
  ## Features
11
11
 
@@ -22,9 +22,12 @@ Embedded FHIR R4 persistence layer — CRUD, search, indexing, and schema migrat
22
22
  - **IG-driven schema** — StructureDefinition + SearchParameter → DDL (SQLite + PostgreSQL dialects)
23
23
  - **Migration engine** — SchemaDiff → MigrationGenerator → MigrationRunnerV2
24
24
  - **Full-text search** — SQLite FTS5 + PostgreSQL tsvector/GIN for string search parameters
25
+ - **PUT-as-Create (upsert)** — `updateResource({ upsert: true })` creates resource if not found
26
+ - **Conditional Create** — `createResource({ ifNoneExist })` with FHIR R4 conditional semantics
25
27
  - **Conditional operations** — conditionalCreate / conditionalUpdate / conditionalDelete via `ConditionalService`
28
+ - **Type-level history** — `readTypeHistory('Patient')` for `GET /Patient/_history`
26
29
  - **Reindex progress** — `onProgress` callback for CLI and UI progress reporting
27
- - **Bundle processing** — transaction and batch bundle support
30
+ - **Bundle processing** — transaction and batch bundle support with PUT-as-Create
28
31
  - **Terminology** — TerminologyCodeRepo + ValueSetRepo
29
32
  - **FhirSystem orchestrator** — end-to-end startup flow for `fhir-engine` integration
30
33
  - **Provider bridges** — `FhirDefinitionBridge` + `FhirRuntimeProvider` for `fhir-definition` / `fhir-runtime`
@@ -69,7 +72,7 @@ const persistence = new FhirPersistence({
69
72
  });
70
73
 
71
74
  // 4. CRUD with automatic indexing
72
- const patient = await persistence.createResource("Patient", {
75
+ const { resource: patient } = await persistence.createResource("Patient", {
73
76
  resourceType: "Patient",
74
77
  name: [{ family: "Smith", given: ["John"] }],
75
78
  birthDate: "1990-01-15",
@@ -132,7 +135,7 @@ const { persistence, sdRegistry, spRegistry, igResult } =
132
135
  await system.initialize(definitionBridge);
133
136
 
134
137
  // 5. Use persistence
135
- const patient = await persistence.createResource('Patient', { resourceType: 'Patient', ... });
138
+ const { resource: patient } = await persistence.createResource('Patient', { resourceType: 'Patient', ... });
136
139
  ```
137
140
 
138
141
  ## Architecture