fhir-persistence 0.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.
- package/CHANGELOG.md +77 -0
- package/LICENSE +21 -0
- package/README.md +225 -0
- package/dist/cjs/index.cjs +8869 -0
- package/dist/cjs/index.cjs.map +7 -0
- package/dist/cjs/index.d.ts +3114 -0
- package/dist/cjs/package.json +5 -0
- package/dist/esm/index.d.ts +3114 -0
- package/dist/esm/index.mjs +8745 -0
- package/dist/esm/index.mjs.map +7 -0
- package/dist/esm/package.json +5 -0
- package/dist/index.d.ts +3114 -0
- package/dist/lib/cache/resource-cache.d.ts +137 -0
- package/dist/lib/cache/resource-cache.d.ts.map +1 -0
- package/dist/lib/cli/reindex.d.ts +55 -0
- package/dist/lib/cli/reindex.d.ts.map +1 -0
- package/dist/lib/db/adapter.d.ts +79 -0
- package/dist/lib/db/adapter.d.ts.map +1 -0
- package/dist/lib/db/better-sqlite3-adapter.d.ts +65 -0
- package/dist/lib/db/better-sqlite3-adapter.d.ts.map +1 -0
- package/dist/lib/db/dialect.d.ts +87 -0
- package/dist/lib/db/dialect.d.ts.map +1 -0
- package/dist/lib/db/index.d.ts +18 -0
- package/dist/lib/db/index.d.ts.map +1 -0
- package/dist/lib/db/postgres-adapter.d.ts +84 -0
- package/dist/lib/db/postgres-adapter.d.ts.map +1 -0
- package/dist/lib/db/postgres-dialect.d.ts +36 -0
- package/dist/lib/db/postgres-dialect.d.ts.map +1 -0
- package/dist/lib/db/sqlite-adapter.d.ts +41 -0
- package/dist/lib/db/sqlite-adapter.d.ts.map +1 -0
- package/dist/lib/db/sqlite-dialect.d.ts +34 -0
- package/dist/lib/db/sqlite-dialect.d.ts.map +1 -0
- package/dist/lib/index.d.ts +65 -0
- package/dist/lib/index.d.ts.map +1 -0
- package/dist/lib/migration/ig-persistence-manager.d.ts +56 -0
- package/dist/lib/migration/ig-persistence-manager.d.ts.map +1 -0
- package/dist/lib/migration/migration-generator.d.ts +38 -0
- package/dist/lib/migration/migration-generator.d.ts.map +1 -0
- package/dist/lib/migration/reindex-scheduler.d.ts +82 -0
- package/dist/lib/migration/reindex-scheduler.d.ts.map +1 -0
- package/dist/lib/migration/schema-diff.d.ts +44 -0
- package/dist/lib/migration/schema-diff.d.ts.map +1 -0
- package/dist/lib/migrations/index.d.ts +8 -0
- package/dist/lib/migrations/index.d.ts.map +1 -0
- package/dist/lib/migrations/migration-runner.d.ts +102 -0
- package/dist/lib/migrations/migration-runner.d.ts.map +1 -0
- package/dist/lib/observability/search-logger.d.ts +74 -0
- package/dist/lib/observability/search-logger.d.ts.map +1 -0
- package/dist/lib/platform/platform-ig-definitions.d.ts +51 -0
- package/dist/lib/platform/platform-ig-definitions.d.ts.map +1 -0
- package/dist/lib/platform/platform-ig-loader.d.ts +30 -0
- package/dist/lib/platform/platform-ig-loader.d.ts.map +1 -0
- package/dist/lib/providers/definition-provider.d.ts +124 -0
- package/dist/lib/providers/definition-provider.d.ts.map +1 -0
- package/dist/lib/providers/fhir-definition-provider.d.ts +58 -0
- package/dist/lib/providers/fhir-definition-provider.d.ts.map +1 -0
- package/dist/lib/providers/fhir-runtime-provider.d.ts +75 -0
- package/dist/lib/providers/fhir-runtime-provider.d.ts.map +1 -0
- package/dist/lib/providers/in-memory-definition-provider.d.ts +72 -0
- package/dist/lib/providers/in-memory-definition-provider.d.ts.map +1 -0
- package/dist/lib/providers/index.d.ts +13 -0
- package/dist/lib/providers/index.d.ts.map +1 -0
- package/dist/lib/providers/property-path-runtime-provider.d.ts +34 -0
- package/dist/lib/providers/property-path-runtime-provider.d.ts.map +1 -0
- package/dist/lib/providers/runtime-provider.d.ts +84 -0
- package/dist/lib/providers/runtime-provider.d.ts.map +1 -0
- package/dist/lib/registry/element-cardinality.d.ts +15 -0
- package/dist/lib/registry/element-cardinality.d.ts.map +1 -0
- package/dist/lib/registry/index.d.ts +10 -0
- package/dist/lib/registry/index.d.ts.map +1 -0
- package/dist/lib/registry/package-registry-repo.d.ts +106 -0
- package/dist/lib/registry/package-registry-repo.d.ts.map +1 -0
- package/dist/lib/registry/search-parameter-registry.d.ts +175 -0
- package/dist/lib/registry/search-parameter-registry.d.ts.map +1 -0
- package/dist/lib/registry/structure-definition-registry.d.ts +93 -0
- package/dist/lib/registry/structure-definition-registry.d.ts.map +1 -0
- package/dist/lib/repo/errors.d.ts +61 -0
- package/dist/lib/repo/errors.d.ts.map +1 -0
- package/dist/lib/repo/history-bundle.d.ts +78 -0
- package/dist/lib/repo/history-bundle.d.ts.map +1 -0
- package/dist/lib/repo/index.d.ts +17 -0
- package/dist/lib/repo/index.d.ts.map +1 -0
- package/dist/lib/repo/indexing-pipeline.d.ts +108 -0
- package/dist/lib/repo/indexing-pipeline.d.ts.map +1 -0
- package/dist/lib/repo/lookup-table-writer.d.ts +46 -0
- package/dist/lib/repo/lookup-table-writer.d.ts.map +1 -0
- package/dist/lib/repo/reference-indexer.d.ts +56 -0
- package/dist/lib/repo/reference-indexer.d.ts.map +1 -0
- package/dist/lib/repo/row-builder.d.ts +78 -0
- package/dist/lib/repo/row-builder.d.ts.map +1 -0
- package/dist/lib/repo/row-indexer.d.ts +111 -0
- package/dist/lib/repo/row-indexer.d.ts.map +1 -0
- package/dist/lib/repo/sql-builder.d.ts +166 -0
- package/dist/lib/repo/sql-builder.d.ts.map +1 -0
- package/dist/lib/repo/types.d.ts +321 -0
- package/dist/lib/repo/types.d.ts.map +1 -0
- package/dist/lib/schema/ddl-generator.d.ts +81 -0
- package/dist/lib/schema/ddl-generator.d.ts.map +1 -0
- package/dist/lib/schema/index.d.ts +8 -0
- package/dist/lib/schema/index.d.ts.map +1 -0
- package/dist/lib/schema/table-schema-builder.d.ts +66 -0
- package/dist/lib/schema/table-schema-builder.d.ts.map +1 -0
- package/dist/lib/schema/table-schema.d.ts +236 -0
- package/dist/lib/schema/table-schema.d.ts.map +1 -0
- package/dist/lib/search/index.d.ts +22 -0
- package/dist/lib/search/index.d.ts.map +1 -0
- package/dist/lib/search/pagination.d.ts +53 -0
- package/dist/lib/search/pagination.d.ts.map +1 -0
- package/dist/lib/search/param-parser.d.ts +85 -0
- package/dist/lib/search/param-parser.d.ts.map +1 -0
- package/dist/lib/search/search-bundle.d.ts +61 -0
- package/dist/lib/search/search-bundle.d.ts.map +1 -0
- package/dist/lib/search/search-executor.d.ts +58 -0
- package/dist/lib/search/search-executor.d.ts.map +1 -0
- package/dist/lib/search/search-planner.d.ts +57 -0
- package/dist/lib/search/search-planner.d.ts.map +1 -0
- package/dist/lib/search/search-sql-builder.d.ts +86 -0
- package/dist/lib/search/search-sql-builder.d.ts.map +1 -0
- package/dist/lib/search/types.d.ts +219 -0
- package/dist/lib/search/types.d.ts.map +1 -0
- package/dist/lib/search/where-builder.d.ts +64 -0
- package/dist/lib/search/where-builder.d.ts.map +1 -0
- package/dist/lib/startup/fhir-system.d.ts +82 -0
- package/dist/lib/startup/fhir-system.d.ts.map +1 -0
- package/dist/lib/store/conditional-service.d.ts +76 -0
- package/dist/lib/store/conditional-service.d.ts.map +1 -0
- package/dist/lib/store/fhir-persistence.d.ts +81 -0
- package/dist/lib/store/fhir-persistence.d.ts.map +1 -0
- package/dist/lib/store/fhir-store.d.ts +44 -0
- package/dist/lib/store/fhir-store.d.ts.map +1 -0
- package/dist/lib/terminology/terminology-code-repo.d.ts +61 -0
- package/dist/lib/terminology/terminology-code-repo.d.ts.map +1 -0
- package/dist/lib/terminology/valueset-repo.d.ts +76 -0
- package/dist/lib/terminology/valueset-repo.d.ts.map +1 -0
- package/dist/lib/transaction/bundle-processor.d.ts +84 -0
- package/dist/lib/transaction/bundle-processor.d.ts.map +1 -0
- package/dist/lib/transaction/urn-resolver.d.ts +62 -0
- package/dist/lib/transaction/urn-resolver.d.ts.map +1 -0
- package/dist/tsdoc-metadata.json +11 -0
- package/package.json +87 -0
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SearchParameter Registry
|
|
3
|
+
*
|
|
4
|
+
* Indexes FHIR SearchParameter definitions and determines the physical
|
|
5
|
+
* storage strategy for each parameter. Drives search column generation
|
|
6
|
+
* in `TableSchemaBuilder`.
|
|
7
|
+
*
|
|
8
|
+
* ## Strategy Mapping (from WF-MIG-003)
|
|
9
|
+
*
|
|
10
|
+
* | SearchParam.type | Strategy | Column Type |
|
|
11
|
+
* |------------------|----------------|--------------------------------------|
|
|
12
|
+
* | date | column | TIMESTAMPTZ (or DATE) |
|
|
13
|
+
* | string | column | TEXT |
|
|
14
|
+
* | reference | column | TEXT |
|
|
15
|
+
* | number | column | DOUBLE PRECISION |
|
|
16
|
+
* | quantity | column | DOUBLE PRECISION |
|
|
17
|
+
* | uri | column | TEXT |
|
|
18
|
+
* | boolean | column | BOOLEAN (not used in practice) |
|
|
19
|
+
* | token | token-column | UUID[] + TEXT[] + TEXT (3 cols) |
|
|
20
|
+
* | special | skipped | — |
|
|
21
|
+
* | composite | skipped | — |
|
|
22
|
+
*
|
|
23
|
+
* Lookup-table strategy is determined by matching specific search param
|
|
24
|
+
* codes (name, address, etc.) — generates a sort column only in the
|
|
25
|
+
* main table; actual data is written by the Repository layer (Phase 9).
|
|
26
|
+
*
|
|
27
|
+
* @module fhir-persistence/registry
|
|
28
|
+
*/
|
|
29
|
+
import type { SqlColumnType } from '../schema/table-schema.js';
|
|
30
|
+
/**
|
|
31
|
+
* FHIR SearchParameter type codes.
|
|
32
|
+
*/
|
|
33
|
+
export type SearchParamType = 'number' | 'date' | 'string' | 'token' | 'reference' | 'composite' | 'quantity' | 'uri' | 'special';
|
|
34
|
+
/**
|
|
35
|
+
* Physical storage strategy for a search parameter.
|
|
36
|
+
*
|
|
37
|
+
* - `column` — single column in the main table
|
|
38
|
+
* - `token-column` — three columns (UUID[], TEXT[], TEXT) for token search
|
|
39
|
+
* - `lookup-table` — separate lookup table; only a sort column in main table
|
|
40
|
+
*/
|
|
41
|
+
export type SearchStrategy = 'column' | 'token-column' | 'lookup-table';
|
|
42
|
+
/**
|
|
43
|
+
* Column type for search parameter columns.
|
|
44
|
+
*/
|
|
45
|
+
export type SearchColumnType = SqlColumnType;
|
|
46
|
+
/**
|
|
47
|
+
* Resolved implementation details for a single search parameter
|
|
48
|
+
* on a specific resource type.
|
|
49
|
+
*/
|
|
50
|
+
export interface SearchParameterImpl {
|
|
51
|
+
/** SearchParameter.code (e.g., `'birthdate'`). */
|
|
52
|
+
code: string;
|
|
53
|
+
/** FHIR search parameter type. */
|
|
54
|
+
type: SearchParamType;
|
|
55
|
+
/** Resource types this parameter applies to. */
|
|
56
|
+
resourceTypes: string[];
|
|
57
|
+
/** FHIRPath expression for value extraction. */
|
|
58
|
+
expression: string;
|
|
59
|
+
/** Physical storage strategy. */
|
|
60
|
+
strategy: SearchStrategy;
|
|
61
|
+
/** Column name in the main table (for `column` strategy). */
|
|
62
|
+
columnName: string;
|
|
63
|
+
/** PostgreSQL column type (for `column` strategy). */
|
|
64
|
+
columnType: SearchColumnType;
|
|
65
|
+
/** Whether the column stores an array of values. */
|
|
66
|
+
array: boolean;
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Raw FHIR SearchParameter shape (subset of fields we need).
|
|
70
|
+
*/
|
|
71
|
+
export interface SearchParameterResource {
|
|
72
|
+
resourceType: 'SearchParameter';
|
|
73
|
+
code: string;
|
|
74
|
+
type: SearchParamType;
|
|
75
|
+
base: string[];
|
|
76
|
+
expression?: string;
|
|
77
|
+
url?: string;
|
|
78
|
+
name?: string;
|
|
79
|
+
target?: string[];
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Shape of a FHIR Bundle containing SearchParameter entries.
|
|
83
|
+
*/
|
|
84
|
+
export interface SearchParameterBundle {
|
|
85
|
+
resourceType: 'Bundle';
|
|
86
|
+
entry?: Array<{
|
|
87
|
+
resource?: SearchParameterResource;
|
|
88
|
+
}>;
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Indexes SearchParameter definitions by resource type.
|
|
92
|
+
*
|
|
93
|
+
* ## Usage
|
|
94
|
+
*
|
|
95
|
+
* ```typescript
|
|
96
|
+
* const registry = new SearchParameterRegistry();
|
|
97
|
+
* const bundle = JSON.parse(fs.readFileSync('search-parameters.json', 'utf8'));
|
|
98
|
+
* registry.indexBundle(bundle);
|
|
99
|
+
*
|
|
100
|
+
* const patientParams = registry.getForResource('Patient');
|
|
101
|
+
* ```
|
|
102
|
+
*/
|
|
103
|
+
export declare class SearchParameterRegistry {
|
|
104
|
+
/**
|
|
105
|
+
* Map from resource type → Map from param code → SearchParameterImpl.
|
|
106
|
+
*/
|
|
107
|
+
private readonly byResource;
|
|
108
|
+
/**
|
|
109
|
+
* Total number of indexed implementations (across all resource types).
|
|
110
|
+
*/
|
|
111
|
+
private _totalCount;
|
|
112
|
+
/**
|
|
113
|
+
* Number of skipped parameters (composite, special, ignored).
|
|
114
|
+
*/
|
|
115
|
+
private _skippedCount;
|
|
116
|
+
/**
|
|
117
|
+
* Index all SearchParameter entries from a FHIR Bundle.
|
|
118
|
+
*
|
|
119
|
+
* Skips entries that are:
|
|
120
|
+
* - Not a SearchParameter resource
|
|
121
|
+
* - Of type `composite` or `special`
|
|
122
|
+
* - In the ignored list (`_id`, `_lastUpdated`, etc.)
|
|
123
|
+
*
|
|
124
|
+
* @returns Stats about the indexing operation.
|
|
125
|
+
*/
|
|
126
|
+
indexBundle(bundle: SearchParameterBundle): {
|
|
127
|
+
indexed: number;
|
|
128
|
+
skipped: number;
|
|
129
|
+
};
|
|
130
|
+
/**
|
|
131
|
+
* Index a single SearchParameterImpl directly.
|
|
132
|
+
*
|
|
133
|
+
* Useful for adding platform-specific or custom search parameters.
|
|
134
|
+
*/
|
|
135
|
+
indexImpl(resourceType: string, impl: SearchParameterImpl): void;
|
|
136
|
+
/**
|
|
137
|
+
* Get all search parameter implementations for a resource type.
|
|
138
|
+
*
|
|
139
|
+
* @returns Array of SearchParameterImpl, sorted by code for deterministic output.
|
|
140
|
+
*/
|
|
141
|
+
getForResource(resourceType: string): SearchParameterImpl[];
|
|
142
|
+
/**
|
|
143
|
+
* Get a specific search parameter implementation for a resource type.
|
|
144
|
+
*/
|
|
145
|
+
getImpl(resourceType: string, code: string): SearchParameterImpl | undefined;
|
|
146
|
+
/**
|
|
147
|
+
* Check if a resource type has any indexed search parameters.
|
|
148
|
+
*/
|
|
149
|
+
hasResource(resourceType: string): boolean;
|
|
150
|
+
/**
|
|
151
|
+
* Get all resource types that have indexed search parameters.
|
|
152
|
+
*/
|
|
153
|
+
getResourceTypes(): string[];
|
|
154
|
+
/**
|
|
155
|
+
* Get the total number of indexed implementations.
|
|
156
|
+
*/
|
|
157
|
+
get totalCount(): number;
|
|
158
|
+
/**
|
|
159
|
+
* Get the number of skipped parameters.
|
|
160
|
+
*/
|
|
161
|
+
get skippedCount(): number;
|
|
162
|
+
/**
|
|
163
|
+
* Get the number of resource types with indexed parameters.
|
|
164
|
+
*/
|
|
165
|
+
get resourceTypeCount(): number;
|
|
166
|
+
/**
|
|
167
|
+
* Remove all indexed parameters.
|
|
168
|
+
*/
|
|
169
|
+
clear(): void;
|
|
170
|
+
/**
|
|
171
|
+
* Build a SearchParameterImpl from a raw SearchParameter resource.
|
|
172
|
+
*/
|
|
173
|
+
private buildImpl;
|
|
174
|
+
}
|
|
175
|
+
//# sourceMappingURL=search-parameter-registry.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"search-parameter-registry.d.ts","sourceRoot":"","sources":["../../../src/registry/search-parameter-registry.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAC;AAO/D;;GAEG;AACH,MAAM,MAAM,eAAe,GACvB,QAAQ,GACR,MAAM,GACN,QAAQ,GACR,OAAO,GACP,WAAW,GACX,WAAW,GACX,UAAU,GACV,KAAK,GACL,SAAS,CAAC;AAEd;;;;;;GAMG;AACH,MAAM,MAAM,cAAc,GAAG,QAAQ,GAAG,cAAc,GAAG,cAAc,CAAC;AAExE;;GAEG;AACH,MAAM,MAAM,gBAAgB,GAAG,aAAa,CAAC;AAE7C;;;GAGG;AACH,MAAM,WAAW,mBAAmB;IAClC,kDAAkD;IAClD,IAAI,EAAE,MAAM,CAAC;IAEb,kCAAkC;IAClC,IAAI,EAAE,eAAe,CAAC;IAEtB,gDAAgD;IAChD,aAAa,EAAE,MAAM,EAAE,CAAC;IAExB,gDAAgD;IAChD,UAAU,EAAE,MAAM,CAAC;IAEnB,iCAAiC;IACjC,QAAQ,EAAE,cAAc,CAAC;IAEzB,6DAA6D;IAC7D,UAAU,EAAE,MAAM,CAAC;IAEnB,sDAAsD;IACtD,UAAU,EAAE,gBAAgB,CAAC;IAE7B,oDAAoD;IACpD,KAAK,EAAE,OAAO,CAAC;CAChB;AAED;;GAEG;AACH,MAAM,WAAW,uBAAuB;IACtC,YAAY,EAAE,iBAAiB,CAAC;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,eAAe,CAAC;IACtB,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;CACnB;AAED;;GAEG;AACH,MAAM,WAAW,qBAAqB;IACpC,YAAY,EAAE,QAAQ,CAAC;IACvB,KAAK,CAAC,EAAE,KAAK,CAAC;QACZ,QAAQ,CAAC,EAAE,uBAAuB,CAAC;KACpC,CAAC,CAAC;CACJ;AAgSD;;;;;;;;;;;;GAYG;AACH,qBAAa,uBAAuB;IAClC;;OAEG;IACH,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAuD;IAElF;;OAEG;IACH,OAAO,CAAC,WAAW,CAAK;IAExB;;OAEG;IACH,OAAO,CAAC,aAAa,CAAK;IAE1B;;;;;;;;;OASG;IACH,WAAW,CAAC,MAAM,EAAE,qBAAqB,GAAG;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE;IAkEhF;;;;OAIG;IACH,SAAS,CAAC,YAAY,EAAE,MAAM,EAAE,IAAI,EAAE,mBAAmB,GAAG,IAAI;IAUhE;;;;OAIG;IACH,cAAc,CAAC,YAAY,EAAE,MAAM,GAAG,mBAAmB,EAAE;IAQ3D;;OAEG;IACH,OAAO,CAAC,YAAY,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,mBAAmB,GAAG,SAAS;IAI5E;;OAEG;IACH,WAAW,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO;IAI1C;;OAEG;IACH,gBAAgB,IAAI,MAAM,EAAE;IAI5B;;OAEG;IACH,IAAI,UAAU,IAAI,MAAM,CAEvB;IAED;;OAEG;IACH,IAAI,YAAY,IAAI,MAAM,CAEzB;IAED;;OAEG;IACH,IAAI,iBAAiB,IAAI,MAAM,CAE9B;IAED;;OAEG;IACH,KAAK,IAAI,IAAI;IAUb;;OAEG;IACH,OAAO,CAAC,SAAS;CA6BlB"}
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* StructureDefinition Registry
|
|
3
|
+
*
|
|
4
|
+
* Indexes `CanonicalProfile[]` by resource type for fast lookup.
|
|
5
|
+
* MedXAI equivalent of Medplum's `indexStructureDefinitionBundle()` →
|
|
6
|
+
* `DATA_TYPES`, but as an injectable instance (no global state).
|
|
7
|
+
*
|
|
8
|
+
* Used by `TableSchemaBuilder` to determine which resource types
|
|
9
|
+
* need tables and to access element definitions for search column
|
|
10
|
+
* generation.
|
|
11
|
+
*
|
|
12
|
+
* @module fhir-persistence/registry
|
|
13
|
+
*/
|
|
14
|
+
/**
|
|
15
|
+
* Minimal CanonicalProfile shape (replaces @medxai/fhir-core dependency).
|
|
16
|
+
*/
|
|
17
|
+
export interface CanonicalProfile {
|
|
18
|
+
url: string;
|
|
19
|
+
name: string;
|
|
20
|
+
kind: 'resource' | 'complex-type' | 'primitive-type' | 'logical';
|
|
21
|
+
type: string;
|
|
22
|
+
abstract: boolean;
|
|
23
|
+
elements: Map<string, unknown>;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Indexes CanonicalProfile instances by their `type` field for O(1) lookup.
|
|
27
|
+
*
|
|
28
|
+
* ## Usage
|
|
29
|
+
*
|
|
30
|
+
* ```typescript
|
|
31
|
+
* const registry = new StructureDefinitionRegistry();
|
|
32
|
+
* const profiles = loadBundleFromFile('profiles-resources.json').profiles;
|
|
33
|
+
* registry.indexAll(profiles);
|
|
34
|
+
*
|
|
35
|
+
* const patient = registry.get('Patient');
|
|
36
|
+
* const tableTypes = registry.getTableResourceTypes(); // ~140+ types
|
|
37
|
+
* ```
|
|
38
|
+
*/
|
|
39
|
+
export declare class StructureDefinitionRegistry {
|
|
40
|
+
private readonly profiles;
|
|
41
|
+
/**
|
|
42
|
+
* Index a single CanonicalProfile by its `type` field.
|
|
43
|
+
*
|
|
44
|
+
* If a profile with the same type already exists, it is overwritten
|
|
45
|
+
* (later definitions override earlier ones, matching BundleLoader
|
|
46
|
+
* merge semantics).
|
|
47
|
+
*/
|
|
48
|
+
index(profile: CanonicalProfile): void;
|
|
49
|
+
/**
|
|
50
|
+
* Index multiple CanonicalProfiles.
|
|
51
|
+
*
|
|
52
|
+
* Profiles are indexed in order; later entries override earlier
|
|
53
|
+
* ones with the same type.
|
|
54
|
+
*/
|
|
55
|
+
indexAll(profiles: readonly CanonicalProfile[]): void;
|
|
56
|
+
/**
|
|
57
|
+
* Get a profile by resource type name.
|
|
58
|
+
*
|
|
59
|
+
* @param resourceType - The FHIR resource type (e.g., `'Patient'`).
|
|
60
|
+
* @returns The CanonicalProfile, or `undefined` if not indexed.
|
|
61
|
+
*/
|
|
62
|
+
get(resourceType: string): CanonicalProfile | undefined;
|
|
63
|
+
/**
|
|
64
|
+
* Check if a resource type is indexed.
|
|
65
|
+
*/
|
|
66
|
+
has(resourceType: string): boolean;
|
|
67
|
+
/**
|
|
68
|
+
* Get all resource types that should have database tables.
|
|
69
|
+
*
|
|
70
|
+
* Returns types where `kind === 'resource'` AND `abstract === false`.
|
|
71
|
+
* This excludes:
|
|
72
|
+
* - Abstract types (Resource, DomainResource)
|
|
73
|
+
* - Complex types (HumanName, Address)
|
|
74
|
+
* - Primitive types (string, boolean)
|
|
75
|
+
* - Logical models
|
|
76
|
+
*
|
|
77
|
+
* Results are sorted alphabetically for deterministic output.
|
|
78
|
+
*/
|
|
79
|
+
getTableResourceTypes(): string[];
|
|
80
|
+
/**
|
|
81
|
+
* Get all indexed type names (regardless of kind or abstract).
|
|
82
|
+
*/
|
|
83
|
+
getAllTypes(): string[];
|
|
84
|
+
/**
|
|
85
|
+
* Get the number of indexed profiles.
|
|
86
|
+
*/
|
|
87
|
+
get size(): number;
|
|
88
|
+
/**
|
|
89
|
+
* Remove all indexed profiles.
|
|
90
|
+
*/
|
|
91
|
+
clear(): void;
|
|
92
|
+
}
|
|
93
|
+
//# sourceMappingURL=structure-definition-registry.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"structure-definition-registry.d.ts","sourceRoot":"","sources":["../../../src/registry/structure-definition-registry.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,UAAU,GAAG,cAAc,GAAG,gBAAgB,GAAG,SAAS,CAAC;IACjE,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,OAAO,CAAC;IAClB,QAAQ,EAAE,GAAG,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAChC;AAMD;;;;;;;;;;;;;GAaG;AACH,qBAAa,2BAA2B;IACtC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAuC;IAEhE;;;;;;OAMG;IACH,KAAK,CAAC,OAAO,EAAE,gBAAgB,GAAG,IAAI;IAItC;;;;;OAKG;IACH,QAAQ,CAAC,QAAQ,EAAE,SAAS,gBAAgB,EAAE,GAAG,IAAI;IAMrD;;;;;OAKG;IACH,GAAG,CAAC,YAAY,EAAE,MAAM,GAAG,gBAAgB,GAAG,SAAS;IAIvD;;OAEG;IACH,GAAG,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO;IAIlC;;;;;;;;;;;OAWG;IACH,qBAAqB,IAAI,MAAM,EAAE;IAOjC;;OAEG;IACH,WAAW,IAAI,MAAM,EAAE;IAIvB;;OAEG;IACH,IAAI,IAAI,IAAI,MAAM,CAEjB;IAED;;OAEG;IACH,KAAK,IAAI,IAAI;CAGd"}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Repository Error Hierarchy
|
|
3
|
+
*
|
|
4
|
+
* Maps to standard FHIR/HTTP error semantics:
|
|
5
|
+
* - 404 Not Found → ResourceNotFoundError
|
|
6
|
+
* - 410 Gone → ResourceGoneError
|
|
7
|
+
* - 412 Precondition Failed → ResourceVersionConflictError
|
|
8
|
+
*
|
|
9
|
+
* @module fhir-persistence/repo
|
|
10
|
+
*/
|
|
11
|
+
/**
|
|
12
|
+
* Base class for all repository errors.
|
|
13
|
+
*/
|
|
14
|
+
export declare class RepositoryError extends Error {
|
|
15
|
+
readonly name: string;
|
|
16
|
+
constructor(message: string);
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Resource not found (HTTP 404).
|
|
20
|
+
*/
|
|
21
|
+
export declare class ResourceNotFoundError extends RepositoryError {
|
|
22
|
+
readonly name = "ResourceNotFoundError";
|
|
23
|
+
readonly resourceType: string;
|
|
24
|
+
readonly resourceId: string;
|
|
25
|
+
constructor(resourceType: string, id: string);
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Resource has been deleted (HTTP 410 Gone).
|
|
29
|
+
*/
|
|
30
|
+
export declare class ResourceGoneError extends RepositoryError {
|
|
31
|
+
readonly name = "ResourceGoneError";
|
|
32
|
+
readonly resourceType: string;
|
|
33
|
+
readonly resourceId: string;
|
|
34
|
+
constructor(resourceType: string, id: string);
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Multiple matches found for conditional operation (HTTP 412 Precondition Failed).
|
|
38
|
+
*
|
|
39
|
+
* Thrown when a conditional update/delete matches more than one resource.
|
|
40
|
+
*/
|
|
41
|
+
export declare class PreconditionFailedError extends RepositoryError {
|
|
42
|
+
readonly name = "PreconditionFailedError";
|
|
43
|
+
readonly resourceType: string;
|
|
44
|
+
readonly matchCount: number;
|
|
45
|
+
constructor(resourceType: string, matchCount: number);
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Optimistic locking conflict (HTTP 412 Precondition Failed).
|
|
49
|
+
*
|
|
50
|
+
* Thrown when `ifMatch` (expected versionId) does not match
|
|
51
|
+
* the current versionId of the resource.
|
|
52
|
+
*/
|
|
53
|
+
export declare class ResourceVersionConflictError extends RepositoryError {
|
|
54
|
+
readonly name = "ResourceVersionConflictError";
|
|
55
|
+
readonly resourceType: string;
|
|
56
|
+
readonly resourceId: string;
|
|
57
|
+
readonly expectedVersion: string;
|
|
58
|
+
readonly actualVersion: string;
|
|
59
|
+
constructor(resourceType: string, id: string, expectedVersion: string, actualVersion: string);
|
|
60
|
+
}
|
|
61
|
+
//# sourceMappingURL=errors.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../../src/repo/errors.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAMH;;GAEG;AACH,qBAAa,eAAgB,SAAQ,KAAK;IACxC,SAAkB,IAAI,EAAE,MAAM,CAAqB;gBAEvC,OAAO,EAAE,MAAM;CAI5B;AAMD;;GAEG;AACH,qBAAa,qBAAsB,SAAQ,eAAe;IACxD,SAAkB,IAAI,2BAA2B;IACjD,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;gBAEhB,YAAY,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM;CAK7C;AAED;;GAEG;AACH,qBAAa,iBAAkB,SAAQ,eAAe;IACpD,SAAkB,IAAI,uBAAuB;IAC7C,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;gBAEhB,YAAY,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM;CAK7C;AAED;;;;GAIG;AACH,qBAAa,uBAAwB,SAAQ,eAAe;IAC1D,SAAkB,IAAI,6BAA6B;IACnD,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;gBAEhB,YAAY,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM;CAOrD;AAED;;;;;GAKG;AACH,qBAAa,4BAA6B,SAAQ,eAAe;IAC/D,SAAkB,IAAI,kCAAkC;IACxD,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,eAAe,EAAE,MAAM,CAAC;IACjC,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;gBAG7B,YAAY,EAAE,MAAM,EACpB,EAAE,EAAE,MAAM,EACV,eAAe,EAAE,MAAM,EACvB,aAAa,EAAE,MAAM;CAWxB"}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* History Bundle Builder
|
|
3
|
+
*
|
|
4
|
+
* Constructs FHIR R4 Bundle of type `history` from `HistoryEntry[]`.
|
|
5
|
+
* Pure function — no database dependency.
|
|
6
|
+
*
|
|
7
|
+
* FHIR R4 History Bundle spec:
|
|
8
|
+
* - `Bundle.type` = `"history"`
|
|
9
|
+
* - Each entry has `request` (method + URL) and `response` (status + etag)
|
|
10
|
+
* - Delete entries have `request.method = "DELETE"` and no `resource`
|
|
11
|
+
* - Entries ordered newest first
|
|
12
|
+
*
|
|
13
|
+
* @module fhir-persistence/repo
|
|
14
|
+
*/
|
|
15
|
+
import type { HistoryEntry } from './types.js';
|
|
16
|
+
/**
|
|
17
|
+
* A FHIR R4 Bundle (minimal shape for history).
|
|
18
|
+
*/
|
|
19
|
+
export interface HistoryBundle {
|
|
20
|
+
resourceType: 'Bundle';
|
|
21
|
+
id: string;
|
|
22
|
+
type: 'history';
|
|
23
|
+
total: number;
|
|
24
|
+
link?: BundleLink[];
|
|
25
|
+
entry?: HistoryBundleEntry[];
|
|
26
|
+
}
|
|
27
|
+
export interface BundleLink {
|
|
28
|
+
relation: string;
|
|
29
|
+
url: string;
|
|
30
|
+
}
|
|
31
|
+
export interface HistoryBundleEntry {
|
|
32
|
+
fullUrl?: string;
|
|
33
|
+
resource?: Record<string, unknown>;
|
|
34
|
+
request: {
|
|
35
|
+
method: string;
|
|
36
|
+
url: string;
|
|
37
|
+
};
|
|
38
|
+
response: {
|
|
39
|
+
status: string;
|
|
40
|
+
etag?: string;
|
|
41
|
+
lastModified?: string;
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Options for building a history bundle.
|
|
46
|
+
*/
|
|
47
|
+
export interface BuildHistoryBundleOptions {
|
|
48
|
+
/** Base URL for fullUrl construction (e.g., `"http://localhost:3000/fhir/R4"`). */
|
|
49
|
+
baseUrl?: string;
|
|
50
|
+
/** Total count of matching entries (may differ from entries.length if paginated). */
|
|
51
|
+
total?: number;
|
|
52
|
+
/** Self link URL. */
|
|
53
|
+
selfUrl?: string;
|
|
54
|
+
/** Next page link URL. */
|
|
55
|
+
nextUrl?: string;
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Build a FHIR R4 history Bundle from HistoryEntry[].
|
|
59
|
+
*
|
|
60
|
+
* @param entries - History entries (newest first).
|
|
61
|
+
* @param options - Optional bundle metadata.
|
|
62
|
+
* @returns A FHIR R4 Bundle of type `history`.
|
|
63
|
+
*/
|
|
64
|
+
export declare function buildHistoryBundle(entries: HistoryEntry[], options?: BuildHistoryBundleOptions): HistoryBundle;
|
|
65
|
+
/**
|
|
66
|
+
* Determine the HTTP method for a history entry.
|
|
67
|
+
*
|
|
68
|
+
* Heuristic: if the entry is the first version (oldest) for a resource,
|
|
69
|
+
* it's a POST (create). Otherwise it's a PUT (update).
|
|
70
|
+
* Delete entries are always DELETE.
|
|
71
|
+
*
|
|
72
|
+
* For simplicity, we check if this is the first entry in the history
|
|
73
|
+
* by comparing with the resource's creation time. Since we don't have
|
|
74
|
+
* that info here, we use a simple heuristic: POST for the first entry
|
|
75
|
+
* in the array (oldest), PUT for the rest.
|
|
76
|
+
*/
|
|
77
|
+
export declare function determineMethod(entries: HistoryEntry[], index: number): string;
|
|
78
|
+
//# sourceMappingURL=history-bundle.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"history-bundle.d.ts","sourceRoot":"","sources":["../../../src/repo/history-bundle.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAGH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAM/C;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,YAAY,EAAE,QAAQ,CAAC;IACvB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,SAAS,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,UAAU,EAAE,CAAC;IACpB,KAAK,CAAC,EAAE,kBAAkB,EAAE,CAAC;CAC9B;AAED,MAAM,WAAW,UAAU;IACzB,QAAQ,EAAE,MAAM,CAAC;IACjB,GAAG,EAAE,MAAM,CAAC;CACb;AAED,MAAM,WAAW,kBAAkB;IACjC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACnC,OAAO,EAAE;QACP,MAAM,EAAE,MAAM,CAAC;QACf,GAAG,EAAE,MAAM,CAAC;KACb,CAAC;IACF,QAAQ,EAAE;QACR,MAAM,EAAE,MAAM,CAAC;QACf,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,YAAY,CAAC,EAAE,MAAM,CAAC;KACvB,CAAC;CACH;AAMD;;GAEG;AACH,MAAM,WAAW,yBAAyB;IACxC,mFAAmF;IACnF,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,qFAAqF;IACrF,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,qBAAqB;IACrB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,0BAA0B;IAC1B,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CAChC,OAAO,EAAE,YAAY,EAAE,EACvB,OAAO,CAAC,EAAE,yBAAyB,GAClC,aAAa,CA0Bf;AAoCD;;;;;;;;;;;GAWG;AACH,wBAAgB,eAAe,CAC7B,OAAO,EAAE,YAAY,EAAE,EACvB,KAAK,EAAE,MAAM,GACZ,MAAM,CAMR"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Repository module — Public API (v2)
|
|
3
|
+
*
|
|
4
|
+
* @module fhir-persistence/repo
|
|
5
|
+
*/
|
|
6
|
+
export type { FhirResource, FhirMeta, PersistedResource, ResourceRepository, CreateResourceOptions, UpdateResourceOptions, HistoryOptions, HistoryEntry, SearchOptions, SearchResult, ResourceRow, HistoryRow, OperationContext, } from './types.js';
|
|
7
|
+
export { SCHEMA_VERSION, DELETED_SCHEMA_VERSION, PLATFORM_RESOURCE_TYPES, PROTECTED_RESOURCE_TYPES, PROJECT_ADMIN_RESOURCE_TYPES, } from './types.js';
|
|
8
|
+
export { RepositoryError, ResourceNotFoundError, ResourceGoneError, ResourceVersionConflictError, } from './errors.js';
|
|
9
|
+
export { buildResourceRow, buildResourceRowWithSearch, buildDeleteRow, buildHistoryRow, buildDeleteHistoryRow, } from './row-builder.js';
|
|
10
|
+
export type { ReferenceRow } from './reference-indexer.js';
|
|
11
|
+
export { extractReferences } from './reference-indexer.js';
|
|
12
|
+
export type { SearchColumnValues } from './row-indexer.js';
|
|
13
|
+
export { buildSearchColumns, buildMetadataColumns, hashToken, extractPropertyPath, getNestedValues, } from './row-indexer.js';
|
|
14
|
+
export { buildUpsertSQL, buildInsertSQL, buildSelectByIdSQL, buildSelectHistorySQL, buildSelectVersionSQL, buildInstanceHistorySQL, buildTypeHistorySQL, } from './sql-builder.js';
|
|
15
|
+
export type { HistoryBundle, HistoryBundleEntry, BundleLink, BuildHistoryBundleOptions, } from './history-bundle.js';
|
|
16
|
+
export { buildHistoryBundle } from './history-bundle.js';
|
|
17
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/repo/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,YAAY,EACV,YAAY,EACZ,QAAQ,EACR,iBAAiB,EACjB,kBAAkB,EAClB,qBAAqB,EACrB,qBAAqB,EACrB,cAAc,EACd,YAAY,EACZ,aAAa,EACb,YAAY,EACZ,WAAW,EACX,UAAU,EACV,gBAAgB,GACjB,MAAM,YAAY,CAAC;AACpB,OAAO,EACL,cAAc,EACd,sBAAsB,EACtB,uBAAuB,EACvB,wBAAwB,EACxB,4BAA4B,GAC7B,MAAM,YAAY,CAAC;AAGpB,OAAO,EACL,eAAe,EACf,qBAAqB,EACrB,iBAAiB,EACjB,4BAA4B,GAC7B,MAAM,aAAa,CAAC;AAGrB,OAAO,EACL,gBAAgB,EAChB,0BAA0B,EAC1B,cAAc,EACd,eAAe,EACf,qBAAqB,GACtB,MAAM,kBAAkB,CAAC;AAG1B,YAAY,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AAC3D,OAAO,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAG3D,YAAY,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AAC3D,OAAO,EACL,kBAAkB,EAClB,oBAAoB,EACpB,SAAS,EACT,mBAAmB,EACnB,eAAe,GAChB,MAAM,kBAAkB,CAAC;AAE1B,OAAO,EACL,cAAc,EACd,cAAc,EACd,kBAAkB,EAClB,qBAAqB,EACrB,qBAAqB,EACrB,uBAAuB,EACvB,mBAAmB,GACpB,MAAM,kBAAkB,CAAC;AAG1B,YAAY,EACV,aAAa,EACb,kBAAkB,EAClB,UAAU,EACV,yBAAyB,GAC1B,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC"}
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Indexing Pipeline — v2
|
|
3
|
+
*
|
|
4
|
+
* Unified orchestrator that combines three indexing concerns into
|
|
5
|
+
* a single `indexResource()` call:
|
|
6
|
+
*
|
|
7
|
+
* 1. **Search columns** — Extract values from resource JSON via
|
|
8
|
+
* `buildSearchColumns()` and merge into the main table row.
|
|
9
|
+
* 2. **References** — Extract outgoing references via
|
|
10
|
+
* `extractReferencesV2()` and write to `{RT}_References` table.
|
|
11
|
+
* 3. **Lookup tables** — Extract HumanName/Address/ContactPoint/Identifier
|
|
12
|
+
* rows via `buildLookupTableRows()` and write to global lookup tables.
|
|
13
|
+
*
|
|
14
|
+
* Design decisions:
|
|
15
|
+
* - Accepts SearchParameterImpl[] (resolved by caller from registry)
|
|
16
|
+
* - All writes use StorageAdapter v2 (? placeholders)
|
|
17
|
+
* - Replace strategy for references and lookup rows (delete + insert)
|
|
18
|
+
* - Search columns are returned (not written) — caller merges into main row
|
|
19
|
+
* - Pipeline is stateless; dependencies injected via constructor
|
|
20
|
+
*
|
|
21
|
+
* @module fhir-persistence/repo
|
|
22
|
+
*/
|
|
23
|
+
import type { StorageAdapter } from '../db/adapter.js';
|
|
24
|
+
import type { SearchParameterImpl } from '../registry/search-parameter-registry.js';
|
|
25
|
+
import type { FhirResource } from './types.js';
|
|
26
|
+
import type { SearchColumnValues, LookupTableRow } from './row-indexer.js';
|
|
27
|
+
import type { ReferenceRowV2 } from './reference-indexer.js';
|
|
28
|
+
import { LookupTableWriter } from './lookup-table-writer.js';
|
|
29
|
+
import type { RuntimeProvider } from '../providers/runtime-provider.js';
|
|
30
|
+
/**
|
|
31
|
+
* Result of indexing a single resource.
|
|
32
|
+
*/
|
|
33
|
+
export interface IndexResult {
|
|
34
|
+
/** Search column values to merge into the main table row. */
|
|
35
|
+
searchColumns: SearchColumnValues;
|
|
36
|
+
/** Reference rows written to {RT}_References table. */
|
|
37
|
+
referenceCount: number;
|
|
38
|
+
/** Lookup table rows written to global lookup tables. */
|
|
39
|
+
lookupRowCount: number;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Options for the indexing pipeline.
|
|
43
|
+
*/
|
|
44
|
+
export interface IndexingPipelineOptions {
|
|
45
|
+
/** Enable lookup table writes (default: true). */
|
|
46
|
+
enableLookupTables?: boolean;
|
|
47
|
+
/** Enable reference indexing (default: true). */
|
|
48
|
+
enableReferences?: boolean;
|
|
49
|
+
/** Optional RuntimeProvider for FHIRPath-driven extraction (B3). */
|
|
50
|
+
runtimeProvider?: RuntimeProvider;
|
|
51
|
+
}
|
|
52
|
+
export declare class IndexingPipeline {
|
|
53
|
+
private readonly adapter;
|
|
54
|
+
private readonly lookupWriter;
|
|
55
|
+
private readonly options;
|
|
56
|
+
private readonly runtimeProvider;
|
|
57
|
+
constructor(adapter: StorageAdapter, options?: IndexingPipelineOptions);
|
|
58
|
+
/**
|
|
59
|
+
* Index a resource: extract search columns, write references, write lookup rows.
|
|
60
|
+
*
|
|
61
|
+
* @param resourceType - The FHIR resource type (e.g., "Patient").
|
|
62
|
+
* @param resource - The FHIR resource (must have `id`).
|
|
63
|
+
* @param impls - SearchParameterImpl list for this resource type.
|
|
64
|
+
* @returns IndexResult with search columns and write counts.
|
|
65
|
+
*/
|
|
66
|
+
indexResource(resourceType: string, resource: FhirResource, impls: SearchParameterImpl[]): Promise<IndexResult>;
|
|
67
|
+
/**
|
|
68
|
+
* Remove all index data for a deleted resource.
|
|
69
|
+
*
|
|
70
|
+
* @param resourceType - The FHIR resource type.
|
|
71
|
+
* @param resourceId - The resource ID.
|
|
72
|
+
*/
|
|
73
|
+
deleteIndex(resourceType: string, resourceId: string): Promise<void>;
|
|
74
|
+
/**
|
|
75
|
+
* Extract search column values without writing references or lookup rows.
|
|
76
|
+
* Useful for re-indexing or testing.
|
|
77
|
+
*/
|
|
78
|
+
extractSearchColumns(resource: FhirResource, impls: SearchParameterImpl[]): SearchColumnValues;
|
|
79
|
+
/**
|
|
80
|
+
* Extract reference rows without writing them.
|
|
81
|
+
* Useful for re-indexing or testing.
|
|
82
|
+
*/
|
|
83
|
+
extractReferences(resource: FhirResource, impls: SearchParameterImpl[]): ReferenceRowV2[];
|
|
84
|
+
/**
|
|
85
|
+
* Extract lookup table rows without writing them.
|
|
86
|
+
* Useful for re-indexing or testing.
|
|
87
|
+
*/
|
|
88
|
+
extractLookupRows(resource: FhirResource, impls: SearchParameterImpl[]): LookupTableRow[];
|
|
89
|
+
/**
|
|
90
|
+
* Get the underlying LookupTableWriter for direct access.
|
|
91
|
+
*/
|
|
92
|
+
getLookupWriter(): LookupTableWriter;
|
|
93
|
+
private writeReferences;
|
|
94
|
+
private writeLookupRows;
|
|
95
|
+
/**
|
|
96
|
+
* Convert SearchParameterImpl[] to SearchParameterDef[] for RuntimeProvider.
|
|
97
|
+
*/
|
|
98
|
+
private implsToDefs;
|
|
99
|
+
/**
|
|
100
|
+
* Extract search column values via RuntimeProvider.
|
|
101
|
+
*/
|
|
102
|
+
private extractViaRuntime;
|
|
103
|
+
/**
|
|
104
|
+
* Extract references via RuntimeProvider → ReferenceRowV2[].
|
|
105
|
+
*/
|
|
106
|
+
private extractRefsViaRuntime;
|
|
107
|
+
}
|
|
108
|
+
//# sourceMappingURL=indexing-pipeline.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"indexing-pipeline.d.ts","sourceRoot":"","sources":["../../../src/repo/indexing-pipeline.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AACvD,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,0CAA0C,CAAC;AACpF,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAC/C,OAAO,KAAK,EAAE,kBAAkB,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAE3E,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAG7D,OAAO,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAC7D,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,kCAAkC,CAAC;AAOxE;;GAEG;AACH,MAAM,WAAW,WAAW;IAC1B,6DAA6D;IAC7D,aAAa,EAAE,kBAAkB,CAAC;IAClC,uDAAuD;IACvD,cAAc,EAAE,MAAM,CAAC;IACvB,yDAAyD;IACzD,cAAc,EAAE,MAAM,CAAC;CACxB;AAED;;GAEG;AACH,MAAM,WAAW,uBAAuB;IACtC,kDAAkD;IAClD,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAC7B,iDAAiD;IACjD,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,oEAAoE;IACpE,eAAe,CAAC,EAAE,eAAe,CAAC;CACnC;AAMD,qBAAa,gBAAgB;IAMzB,OAAO,CAAC,QAAQ,CAAC,OAAO;IAL1B,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAoB;IACjD,OAAO,CAAC,QAAQ,CAAC,OAAO,CAA6D;IACrF,OAAO,CAAC,QAAQ,CAAC,eAAe,CAA8B;gBAG3C,OAAO,EAAE,cAAc,EACxC,OAAO,CAAC,EAAE,uBAAuB;IAcnC;;;;;;;OAOG;IACG,aAAa,CACjB,YAAY,EAAE,MAAM,EACpB,QAAQ,EAAE,YAAY,EACtB,KAAK,EAAE,mBAAmB,EAAE,GAC3B,OAAO,CAAC,WAAW,CAAC;IA8BvB;;;;;OAKG;IACG,WAAW,CAAC,YAAY,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAiB1E;;;OAGG;IACH,oBAAoB,CAClB,QAAQ,EAAE,YAAY,EACtB,KAAK,EAAE,mBAAmB,EAAE,GAC3B,kBAAkB;IAMrB;;;OAGG;IACH,iBAAiB,CACf,QAAQ,EAAE,YAAY,EACtB,KAAK,EAAE,mBAAmB,EAAE,GAC3B,cAAc,EAAE;IAMnB;;;OAGG;IACH,iBAAiB,CACf,QAAQ,EAAE,YAAY,EACtB,KAAK,EAAE,mBAAmB,EAAE,GAC3B,cAAc,EAAE;IASnB;;OAEG;IACH,eAAe,IAAI,iBAAiB;YAQtB,eAAe;YAiCf,eAAe;IAc7B;;OAEG;IACH,OAAO,CAAC,WAAW;IAUnB;;OAEG;IACH,OAAO,CAAC,iBAAiB;IAyCzB;;OAEG;IACH,OAAO,CAAC,qBAAqB;CAqB9B"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Lookup Table Writer — v2
|
|
3
|
+
*
|
|
4
|
+
* Manages the 4 global lookup tables (HumanName, Address, ContactPoint, Identifier)
|
|
5
|
+
* using StorageAdapter v2. Handles DDL creation, row insertion (replace strategy),
|
|
6
|
+
* and deletion.
|
|
7
|
+
*
|
|
8
|
+
* Design decisions:
|
|
9
|
+
* - Uses StorageAdapter interface (not DatabaseClient directly)
|
|
10
|
+
* - All writes use `?` placeholders (SQLite-compatible, rewritten for PG)
|
|
11
|
+
* - Replace strategy: DELETE existing rows for resourceId, then INSERT new ones
|
|
12
|
+
* - Each lookup table has a `resourceId` column + type-specific columns
|
|
13
|
+
* - Batch insert per table type for efficiency
|
|
14
|
+
*
|
|
15
|
+
* @module fhir-persistence/repo
|
|
16
|
+
*/
|
|
17
|
+
import type { StorageAdapter } from '../db/adapter.js';
|
|
18
|
+
import type { LookupTableRow } from './row-indexer.js';
|
|
19
|
+
export declare class LookupTableWriter {
|
|
20
|
+
private readonly adapter;
|
|
21
|
+
private initialized;
|
|
22
|
+
constructor(adapter: StorageAdapter);
|
|
23
|
+
/**
|
|
24
|
+
* Create all 4 lookup tables + indexes if they don't exist.
|
|
25
|
+
*/
|
|
26
|
+
ensureTables(): Promise<void>;
|
|
27
|
+
/**
|
|
28
|
+
* Write lookup table rows for a resource (replace strategy).
|
|
29
|
+
*
|
|
30
|
+
* 1. Deletes all existing rows for the resourceId across all 4 tables
|
|
31
|
+
* 2. Inserts new rows grouped by table type
|
|
32
|
+
*
|
|
33
|
+
* @param resourceId - The resource ID to index.
|
|
34
|
+
* @param rows - LookupTableRow[] from `buildLookupTableRows()`.
|
|
35
|
+
*/
|
|
36
|
+
writeRows(resourceId: string, rows: LookupTableRow[]): Promise<void>;
|
|
37
|
+
/**
|
|
38
|
+
* Delete all lookup table rows for a given resourceId.
|
|
39
|
+
*/
|
|
40
|
+
deleteRows(resourceId: string): Promise<void>;
|
|
41
|
+
/**
|
|
42
|
+
* Get all lookup rows for a given resourceId and table type.
|
|
43
|
+
*/
|
|
44
|
+
getRows<T = Record<string, unknown>>(table: string, resourceId: string): Promise<T[]>;
|
|
45
|
+
}
|
|
46
|
+
//# sourceMappingURL=lookup-table-writer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"lookup-table-writer.d.ts","sourceRoot":"","sources":["../../../src/repo/lookup-table-writer.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AACvD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAsEvD,qBAAa,iBAAiB;IAGhB,OAAO,CAAC,QAAQ,CAAC,OAAO;IAFpC,OAAO,CAAC,WAAW,CAAS;gBAEC,OAAO,EAAE,cAAc;IAMpD;;OAEG;IACG,YAAY,IAAI,OAAO,CAAC,IAAI,CAAC;IAgBnC;;;;;;;;OAQG;IACG,SAAS,CAAC,UAAU,EAAE,MAAM,EAAE,IAAI,EAAE,cAAc,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAmC1E;;OAEG;IACG,UAAU,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAenD;;OAEG;IACG,OAAO,CAAC,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACvC,KAAK,EAAE,MAAM,EACb,UAAU,EAAE,MAAM,GACjB,OAAO,CAAC,CAAC,EAAE,CAAC;CAOhB"}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Reference Indexer
|
|
3
|
+
*
|
|
4
|
+
* Extracts outgoing reference relationships from FHIR resource JSON
|
|
5
|
+
* and produces rows for the `{ResourceType}_References` table.
|
|
6
|
+
*
|
|
7
|
+
* Used by `FhirRepository` on create/update to populate the references
|
|
8
|
+
* table, which is required for `_revinclude` support.
|
|
9
|
+
*
|
|
10
|
+
* @module fhir-persistence/repo
|
|
11
|
+
*/
|
|
12
|
+
import type { SearchParameterImpl } from '../registry/search-parameter-registry.js';
|
|
13
|
+
import type { FhirResource } from './types.js';
|
|
14
|
+
/**
|
|
15
|
+
* A single row for the `{ResourceType}_References` table.
|
|
16
|
+
*/
|
|
17
|
+
export interface ReferenceRow {
|
|
18
|
+
/** The source resource ID. */
|
|
19
|
+
resourceId: string;
|
|
20
|
+
/** The target resource ID (extracted from the reference string). */
|
|
21
|
+
targetId: string;
|
|
22
|
+
/** The search parameter code (e.g., "subject", "patient"). */
|
|
23
|
+
code: string;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* v2: A row for the `{ResourceType}_References` table.
|
|
27
|
+
* Adds targetType and referenceRaw for more precise reference queries.
|
|
28
|
+
*/
|
|
29
|
+
export interface ReferenceRowV2 {
|
|
30
|
+
/** The source resource ID. */
|
|
31
|
+
resourceId: string;
|
|
32
|
+
/** The target resource type (e.g., "Patient"). */
|
|
33
|
+
targetType: string;
|
|
34
|
+
/** The target resource ID. */
|
|
35
|
+
targetId: string;
|
|
36
|
+
/** The search parameter code (e.g., "subject"). */
|
|
37
|
+
code: string;
|
|
38
|
+
/** The original reference string, or null. */
|
|
39
|
+
referenceRaw: string | null;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Extract all outgoing reference rows from a FHIR resource.
|
|
43
|
+
*
|
|
44
|
+
* Iterates over all reference-type search parameters and extracts
|
|
45
|
+
* target resource IDs from the resource JSON.
|
|
46
|
+
*
|
|
47
|
+
* @param resource - The FHIR resource (must have `id`).
|
|
48
|
+
* @param impls - SearchParameterImpl list for this resource type.
|
|
49
|
+
* @returns Array of ReferenceRow ready for SQL insertion.
|
|
50
|
+
*/
|
|
51
|
+
export declare function extractReferences(resource: FhirResource, impls: SearchParameterImpl[]): ReferenceRow[];
|
|
52
|
+
/**
|
|
53
|
+
* v2: Extract all outgoing reference rows with targetType + referenceRaw.
|
|
54
|
+
*/
|
|
55
|
+
export declare function extractReferencesV2(resource: FhirResource, impls: SearchParameterImpl[]): ReferenceRowV2[];
|
|
56
|
+
//# sourceMappingURL=reference-indexer.d.ts.map
|