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.
Files changed (140) hide show
  1. package/CHANGELOG.md +77 -0
  2. package/LICENSE +21 -0
  3. package/README.md +225 -0
  4. package/dist/cjs/index.cjs +8869 -0
  5. package/dist/cjs/index.cjs.map +7 -0
  6. package/dist/cjs/index.d.ts +3114 -0
  7. package/dist/cjs/package.json +5 -0
  8. package/dist/esm/index.d.ts +3114 -0
  9. package/dist/esm/index.mjs +8745 -0
  10. package/dist/esm/index.mjs.map +7 -0
  11. package/dist/esm/package.json +5 -0
  12. package/dist/index.d.ts +3114 -0
  13. package/dist/lib/cache/resource-cache.d.ts +137 -0
  14. package/dist/lib/cache/resource-cache.d.ts.map +1 -0
  15. package/dist/lib/cli/reindex.d.ts +55 -0
  16. package/dist/lib/cli/reindex.d.ts.map +1 -0
  17. package/dist/lib/db/adapter.d.ts +79 -0
  18. package/dist/lib/db/adapter.d.ts.map +1 -0
  19. package/dist/lib/db/better-sqlite3-adapter.d.ts +65 -0
  20. package/dist/lib/db/better-sqlite3-adapter.d.ts.map +1 -0
  21. package/dist/lib/db/dialect.d.ts +87 -0
  22. package/dist/lib/db/dialect.d.ts.map +1 -0
  23. package/dist/lib/db/index.d.ts +18 -0
  24. package/dist/lib/db/index.d.ts.map +1 -0
  25. package/dist/lib/db/postgres-adapter.d.ts +84 -0
  26. package/dist/lib/db/postgres-adapter.d.ts.map +1 -0
  27. package/dist/lib/db/postgres-dialect.d.ts +36 -0
  28. package/dist/lib/db/postgres-dialect.d.ts.map +1 -0
  29. package/dist/lib/db/sqlite-adapter.d.ts +41 -0
  30. package/dist/lib/db/sqlite-adapter.d.ts.map +1 -0
  31. package/dist/lib/db/sqlite-dialect.d.ts +34 -0
  32. package/dist/lib/db/sqlite-dialect.d.ts.map +1 -0
  33. package/dist/lib/index.d.ts +65 -0
  34. package/dist/lib/index.d.ts.map +1 -0
  35. package/dist/lib/migration/ig-persistence-manager.d.ts +56 -0
  36. package/dist/lib/migration/ig-persistence-manager.d.ts.map +1 -0
  37. package/dist/lib/migration/migration-generator.d.ts +38 -0
  38. package/dist/lib/migration/migration-generator.d.ts.map +1 -0
  39. package/dist/lib/migration/reindex-scheduler.d.ts +82 -0
  40. package/dist/lib/migration/reindex-scheduler.d.ts.map +1 -0
  41. package/dist/lib/migration/schema-diff.d.ts +44 -0
  42. package/dist/lib/migration/schema-diff.d.ts.map +1 -0
  43. package/dist/lib/migrations/index.d.ts +8 -0
  44. package/dist/lib/migrations/index.d.ts.map +1 -0
  45. package/dist/lib/migrations/migration-runner.d.ts +102 -0
  46. package/dist/lib/migrations/migration-runner.d.ts.map +1 -0
  47. package/dist/lib/observability/search-logger.d.ts +74 -0
  48. package/dist/lib/observability/search-logger.d.ts.map +1 -0
  49. package/dist/lib/platform/platform-ig-definitions.d.ts +51 -0
  50. package/dist/lib/platform/platform-ig-definitions.d.ts.map +1 -0
  51. package/dist/lib/platform/platform-ig-loader.d.ts +30 -0
  52. package/dist/lib/platform/platform-ig-loader.d.ts.map +1 -0
  53. package/dist/lib/providers/definition-provider.d.ts +124 -0
  54. package/dist/lib/providers/definition-provider.d.ts.map +1 -0
  55. package/dist/lib/providers/fhir-definition-provider.d.ts +58 -0
  56. package/dist/lib/providers/fhir-definition-provider.d.ts.map +1 -0
  57. package/dist/lib/providers/fhir-runtime-provider.d.ts +75 -0
  58. package/dist/lib/providers/fhir-runtime-provider.d.ts.map +1 -0
  59. package/dist/lib/providers/in-memory-definition-provider.d.ts +72 -0
  60. package/dist/lib/providers/in-memory-definition-provider.d.ts.map +1 -0
  61. package/dist/lib/providers/index.d.ts +13 -0
  62. package/dist/lib/providers/index.d.ts.map +1 -0
  63. package/dist/lib/providers/property-path-runtime-provider.d.ts +34 -0
  64. package/dist/lib/providers/property-path-runtime-provider.d.ts.map +1 -0
  65. package/dist/lib/providers/runtime-provider.d.ts +84 -0
  66. package/dist/lib/providers/runtime-provider.d.ts.map +1 -0
  67. package/dist/lib/registry/element-cardinality.d.ts +15 -0
  68. package/dist/lib/registry/element-cardinality.d.ts.map +1 -0
  69. package/dist/lib/registry/index.d.ts +10 -0
  70. package/dist/lib/registry/index.d.ts.map +1 -0
  71. package/dist/lib/registry/package-registry-repo.d.ts +106 -0
  72. package/dist/lib/registry/package-registry-repo.d.ts.map +1 -0
  73. package/dist/lib/registry/search-parameter-registry.d.ts +175 -0
  74. package/dist/lib/registry/search-parameter-registry.d.ts.map +1 -0
  75. package/dist/lib/registry/structure-definition-registry.d.ts +93 -0
  76. package/dist/lib/registry/structure-definition-registry.d.ts.map +1 -0
  77. package/dist/lib/repo/errors.d.ts +61 -0
  78. package/dist/lib/repo/errors.d.ts.map +1 -0
  79. package/dist/lib/repo/history-bundle.d.ts +78 -0
  80. package/dist/lib/repo/history-bundle.d.ts.map +1 -0
  81. package/dist/lib/repo/index.d.ts +17 -0
  82. package/dist/lib/repo/index.d.ts.map +1 -0
  83. package/dist/lib/repo/indexing-pipeline.d.ts +108 -0
  84. package/dist/lib/repo/indexing-pipeline.d.ts.map +1 -0
  85. package/dist/lib/repo/lookup-table-writer.d.ts +46 -0
  86. package/dist/lib/repo/lookup-table-writer.d.ts.map +1 -0
  87. package/dist/lib/repo/reference-indexer.d.ts +56 -0
  88. package/dist/lib/repo/reference-indexer.d.ts.map +1 -0
  89. package/dist/lib/repo/row-builder.d.ts +78 -0
  90. package/dist/lib/repo/row-builder.d.ts.map +1 -0
  91. package/dist/lib/repo/row-indexer.d.ts +111 -0
  92. package/dist/lib/repo/row-indexer.d.ts.map +1 -0
  93. package/dist/lib/repo/sql-builder.d.ts +166 -0
  94. package/dist/lib/repo/sql-builder.d.ts.map +1 -0
  95. package/dist/lib/repo/types.d.ts +321 -0
  96. package/dist/lib/repo/types.d.ts.map +1 -0
  97. package/dist/lib/schema/ddl-generator.d.ts +81 -0
  98. package/dist/lib/schema/ddl-generator.d.ts.map +1 -0
  99. package/dist/lib/schema/index.d.ts +8 -0
  100. package/dist/lib/schema/index.d.ts.map +1 -0
  101. package/dist/lib/schema/table-schema-builder.d.ts +66 -0
  102. package/dist/lib/schema/table-schema-builder.d.ts.map +1 -0
  103. package/dist/lib/schema/table-schema.d.ts +236 -0
  104. package/dist/lib/schema/table-schema.d.ts.map +1 -0
  105. package/dist/lib/search/index.d.ts +22 -0
  106. package/dist/lib/search/index.d.ts.map +1 -0
  107. package/dist/lib/search/pagination.d.ts +53 -0
  108. package/dist/lib/search/pagination.d.ts.map +1 -0
  109. package/dist/lib/search/param-parser.d.ts +85 -0
  110. package/dist/lib/search/param-parser.d.ts.map +1 -0
  111. package/dist/lib/search/search-bundle.d.ts +61 -0
  112. package/dist/lib/search/search-bundle.d.ts.map +1 -0
  113. package/dist/lib/search/search-executor.d.ts +58 -0
  114. package/dist/lib/search/search-executor.d.ts.map +1 -0
  115. package/dist/lib/search/search-planner.d.ts +57 -0
  116. package/dist/lib/search/search-planner.d.ts.map +1 -0
  117. package/dist/lib/search/search-sql-builder.d.ts +86 -0
  118. package/dist/lib/search/search-sql-builder.d.ts.map +1 -0
  119. package/dist/lib/search/types.d.ts +219 -0
  120. package/dist/lib/search/types.d.ts.map +1 -0
  121. package/dist/lib/search/where-builder.d.ts +64 -0
  122. package/dist/lib/search/where-builder.d.ts.map +1 -0
  123. package/dist/lib/startup/fhir-system.d.ts +82 -0
  124. package/dist/lib/startup/fhir-system.d.ts.map +1 -0
  125. package/dist/lib/store/conditional-service.d.ts +76 -0
  126. package/dist/lib/store/conditional-service.d.ts.map +1 -0
  127. package/dist/lib/store/fhir-persistence.d.ts +81 -0
  128. package/dist/lib/store/fhir-persistence.d.ts.map +1 -0
  129. package/dist/lib/store/fhir-store.d.ts +44 -0
  130. package/dist/lib/store/fhir-store.d.ts.map +1 -0
  131. package/dist/lib/terminology/terminology-code-repo.d.ts +61 -0
  132. package/dist/lib/terminology/terminology-code-repo.d.ts.map +1 -0
  133. package/dist/lib/terminology/valueset-repo.d.ts +76 -0
  134. package/dist/lib/terminology/valueset-repo.d.ts.map +1 -0
  135. package/dist/lib/transaction/bundle-processor.d.ts +84 -0
  136. package/dist/lib/transaction/bundle-processor.d.ts.map +1 -0
  137. package/dist/lib/transaction/urn-resolver.d.ts +62 -0
  138. package/dist/lib/transaction/urn-resolver.d.ts.map +1 -0
  139. package/dist/tsdoc-metadata.json +11 -0
  140. package/package.json +87 -0
@@ -0,0 +1,137 @@
1
+ /**
2
+ * Resource Cache — In-Memory LRU
3
+ *
4
+ * Provides an in-memory LRU cache for `readResource` results.
5
+ * Invalidated on update and delete operations.
6
+ *
7
+ * Disabled by default. Enable via configuration.
8
+ *
9
+ * @module fhir-persistence/cache
10
+ */
11
+ import type { PersistedResource } from '../repo/types.js';
12
+ /**
13
+ * Configuration for the resource cache.
14
+ */
15
+ export interface ResourceCacheConfig {
16
+ /** Maximum number of entries. Default: 1000. */
17
+ maxSize?: number;
18
+ /** Time-to-live in milliseconds. Default: 60000 (60s). */
19
+ ttlMs?: number;
20
+ /** Whether the cache is enabled. Default: false. */
21
+ enabled?: boolean;
22
+ }
23
+ /**
24
+ * Simple LRU cache for FHIR resources.
25
+ *
26
+ * Uses a Map (insertion-ordered) for O(1) get/set/delete.
27
+ * Evicts the oldest entry when maxSize is reached.
28
+ */
29
+ export declare class ResourceCache {
30
+ private readonly cache;
31
+ private readonly maxSize;
32
+ private readonly ttlMs;
33
+ private readonly enabled;
34
+ private _hits;
35
+ private _misses;
36
+ constructor(config?: ResourceCacheConfig);
37
+ /**
38
+ * Build cache key from resourceType and id.
39
+ */
40
+ private key;
41
+ /**
42
+ * Get a resource from the cache.
43
+ * Returns undefined on miss or expiry.
44
+ */
45
+ get(resourceType: string, id: string): PersistedResource | undefined;
46
+ /**
47
+ * Put a resource into the cache.
48
+ */
49
+ set(resourceType: string, id: string, resource: PersistedResource): void;
50
+ /**
51
+ * Invalidate a cache entry (on update or delete).
52
+ */
53
+ invalidate(resourceType: string, id: string): void;
54
+ /**
55
+ * Clear all cache entries.
56
+ */
57
+ clear(): void;
58
+ /**
59
+ * Current cache size.
60
+ */
61
+ get size(): number;
62
+ /**
63
+ * Cache statistics.
64
+ */
65
+ get stats(): {
66
+ hits: number;
67
+ misses: number;
68
+ size: number;
69
+ hitRate: number;
70
+ };
71
+ get isEnabled(): boolean;
72
+ }
73
+ /**
74
+ * Eviction policy for the cache.
75
+ *
76
+ * - `lru` — Least Recently Used: evict the entry that was accessed longest ago.
77
+ * - `fifo` — First In First Out: evict the entry that was inserted first.
78
+ * - `ttl-only` — No size-based eviction; entries only expire via TTL.
79
+ */
80
+ export type EvictionPolicy = 'lru' | 'fifo' | 'ttl-only';
81
+ /**
82
+ * v2 configuration for the resource cache.
83
+ */
84
+ export interface ResourceCacheV2Config {
85
+ /** Maximum number of entries. Default: 1000. Ignored for ttl-only policy. */
86
+ maxSize?: number;
87
+ /** Time-to-live in milliseconds. Default: 60000 (60s). */
88
+ ttlMs?: number;
89
+ /** Whether the cache is enabled. Default: false. */
90
+ enabled?: boolean;
91
+ /** Eviction policy. Default: 'lru'. */
92
+ evictionPolicy?: EvictionPolicy;
93
+ }
94
+ /**
95
+ * v2 Resource Cache with configurable eviction policy.
96
+ *
97
+ * Upgrades v1 with:
98
+ * - Eviction policy: lru / fifo / ttl-only
99
+ * - stats.reset() to zero counters
100
+ * - sweep() to proactively remove expired entries
101
+ */
102
+ export declare class ResourceCacheV2 {
103
+ private readonly cache;
104
+ private readonly maxSize;
105
+ private readonly ttlMs;
106
+ private readonly enabled;
107
+ private readonly evictionPolicy;
108
+ private _hits;
109
+ private _misses;
110
+ private _evictions;
111
+ constructor(config?: ResourceCacheV2Config);
112
+ private key;
113
+ get(resourceType: string, id: string): PersistedResource | undefined;
114
+ set(resourceType: string, id: string, resource: PersistedResource): void;
115
+ invalidate(resourceType: string, id: string): void;
116
+ clear(): void;
117
+ /**
118
+ * Proactively remove all expired entries.
119
+ * @returns Number of entries swept.
120
+ */
121
+ sweep(): number;
122
+ get size(): number;
123
+ get stats(): {
124
+ hits: number;
125
+ misses: number;
126
+ size: number;
127
+ hitRate: number;
128
+ evictions: number;
129
+ };
130
+ /**
131
+ * Reset stats counters without clearing cache entries.
132
+ */
133
+ resetStats(): void;
134
+ get isEnabled(): boolean;
135
+ get policy(): EvictionPolicy;
136
+ }
137
+ //# sourceMappingURL=resource-cache.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resource-cache.d.ts","sourceRoot":"","sources":["../../../src/cache/resource-cache.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,55 @@
1
+ /**
2
+ * Reindex CLI — v2
3
+ *
4
+ * Re-populates search columns and references for existing resources
5
+ * using StorageAdapter (not DatabaseClient). Replaces v1 repo/reindex.ts
6
+ * for v2 codepaths.
7
+ *
8
+ * Usage:
9
+ * npx tsx src/cli/reindex.ts --resource Patient
10
+ * npx tsx src/cli/reindex.ts --all
11
+ *
12
+ * @module fhir-persistence/cli
13
+ */
14
+ import type { StorageAdapter } from '../db/adapter.js';
15
+ export type ReindexProgressCallbackV2 = (info: {
16
+ resourceType: string;
17
+ processed: number;
18
+ total: number;
19
+ }) => void;
20
+ export interface ReindexResultV2 {
21
+ totalProcessed: number;
22
+ totalUpdated: number;
23
+ totalErrors: number;
24
+ byType: Record<string, {
25
+ processed: number;
26
+ updated: number;
27
+ errors: number;
28
+ }>;
29
+ }
30
+ /**
31
+ * Re-index all resources of a given type using StorageAdapter.
32
+ *
33
+ * Reads all non-deleted resources in batches via keyset pagination,
34
+ * parses content JSON, and can be extended with custom row-update logic.
35
+ *
36
+ * @param adapter - StorageAdapter (SQLite or PostgreSQL).
37
+ * @param resourceType - The FHIR resource type to re-index.
38
+ * @param onProgress - Optional progress callback.
39
+ * @returns Per-type reindex result.
40
+ */
41
+ export declare function reindexResourceTypeV2(adapter: StorageAdapter, resourceType: string, onProgress?: ReindexProgressCallbackV2): Promise<{
42
+ processed: number;
43
+ updated: number;
44
+ errors: number;
45
+ }>;
46
+ /**
47
+ * Re-index all resource types using StorageAdapter.
48
+ *
49
+ * @param adapter - StorageAdapter.
50
+ * @param resourceTypes - List of resource types to re-index.
51
+ * @param onProgress - Optional progress callback.
52
+ * @returns Complete re-index result.
53
+ */
54
+ export declare function reindexAllV2(adapter: StorageAdapter, resourceTypes: string[], onProgress?: ReindexProgressCallbackV2): Promise<ReindexResultV2>;
55
+ //# sourceMappingURL=reindex.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"reindex.d.ts","sourceRoot":"","sources":["../../../src/cli/reindex.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAMvD,MAAM,MAAM,yBAAyB,GAAG,CAAC,IAAI,EAAE;IAC7C,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;CACf,KAAK,IAAI,CAAC;AAEX,MAAM,WAAW,eAAe;IAC9B,cAAc,EAAE,MAAM,CAAC;IACvB,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE;QAAE,SAAS,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CAChF;AAQD;;;;;;;;;;GAUG;AACH,wBAAsB,qBAAqB,CACzC,OAAO,EAAE,cAAc,EACvB,YAAY,EAAE,MAAM,EACpB,UAAU,CAAC,EAAE,yBAAyB,GACrC,OAAO,CAAC;IAAE,SAAS,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC,CA6CjE;AAED;;;;;;;GAOG;AACH,wBAAsB,YAAY,CAChC,OAAO,EAAE,cAAc,EACvB,aAAa,EAAE,MAAM,EAAE,EACvB,UAAU,CAAC,EAAE,yBAAyB,GACrC,OAAO,CAAC,eAAe,CAAC,CAsB1B"}
@@ -0,0 +1,79 @@
1
+ /**
2
+ * StorageAdapter — Database Abstraction Interface
3
+ *
4
+ * Provides a unified interface for database operations across
5
+ * SQLite and PostgreSQL. All business logic interacts with
6
+ * the database exclusively through this interface.
7
+ *
8
+ * v2 upgrade: Replaces direct `pg.Pool` usage in v1's `DatabaseClient`.
9
+ * The existing `DatabaseClient` is preserved for backward compatibility.
10
+ *
11
+ * @module fhir-persistence/db
12
+ */
13
+ /**
14
+ * A prepared (precompiled) SQL statement for high-frequency operations.
15
+ *
16
+ * Prepared statements avoid repeated SQL parsing overhead.
17
+ * The caller is responsible for calling `finalize()` when done.
18
+ */
19
+ export interface PreparedStatement<T = Record<string, unknown>> {
20
+ /** Execute as a read query, returning all matching rows. */
21
+ query(params?: unknown[]): T[];
22
+ /** Execute as a write operation, returning change count. */
23
+ execute(params?: unknown[]): {
24
+ changes: number;
25
+ lastInsertRowid?: number | bigint;
26
+ };
27
+ /** Release the prepared statement resources. */
28
+ finalize(): void;
29
+ }
30
+ /**
31
+ * A restricted adapter interface available inside a transaction callback.
32
+ *
33
+ * All operations within a transaction use this context to ensure
34
+ * they execute on the same database connection/transaction.
35
+ */
36
+ export interface TransactionContext {
37
+ /** Execute a write operation within the transaction. */
38
+ execute(sql: string, params?: unknown[]): {
39
+ changes: number;
40
+ };
41
+ /** Execute a read query within the transaction. */
42
+ query<T = Record<string, unknown>>(sql: string, params?: unknown[]): T[];
43
+ /** Execute a read query returning the first row or undefined. */
44
+ queryOne<T = Record<string, unknown>>(sql: string, params?: unknown[]): T | undefined;
45
+ }
46
+ /**
47
+ * Unified database access interface for SQLite and PostgreSQL.
48
+ *
49
+ * All methods are async to support both synchronous (SQLite via sql.js)
50
+ * and asynchronous (PostgreSQL via pg) database drivers.
51
+ *
52
+ * ## Transaction Semantics
53
+ * - SQLite: `BEGIN IMMEDIATE ... COMMIT / ROLLBACK`
54
+ * - PostgreSQL: `BEGIN ... COMMIT / ROLLBACK` with `SELECT FOR UPDATE`
55
+ */
56
+ export interface StorageAdapter {
57
+ /** Execute a write operation (INSERT / UPDATE / DELETE / DDL). */
58
+ execute(sql: string, params?: unknown[]): Promise<{
59
+ changes: number;
60
+ }>;
61
+ /** Execute a read query, returning all matching rows. */
62
+ query<T = Record<string, unknown>>(sql: string, params?: unknown[]): Promise<T[]>;
63
+ /** Execute a read query, returning the first row or undefined. */
64
+ queryOne<T = Record<string, unknown>>(sql: string, params?: unknown[]): Promise<T | undefined>;
65
+ /** Stream rows for large result sets (avoids full memory load). */
66
+ queryStream<T = Record<string, unknown>>(sql: string, params?: unknown[]): AsyncIterable<T>;
67
+ /** Prepare a SQL statement for repeated execution. */
68
+ prepare<T = Record<string, unknown>>(sql: string): PreparedStatement<T>;
69
+ /**
70
+ * Execute a function within a single database transaction.
71
+ *
72
+ * - On success (fn returns normally): COMMIT
73
+ * - On failure (fn throws): ROLLBACK and re-throw
74
+ */
75
+ transaction<R>(fn: (tx: TransactionContext) => R | Promise<R>): Promise<R>;
76
+ /** Close the database connection and release resources. */
77
+ close(): Promise<void>;
78
+ }
79
+ //# sourceMappingURL=adapter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"adapter.d.ts","sourceRoot":"","sources":["../../../src/db/adapter.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAMH;;;;;GAKG;AACH,MAAM,WAAW,iBAAiB,CAAC,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;IAC5D,4DAA4D;IAC5D,KAAK,CAAC,MAAM,CAAC,EAAE,OAAO,EAAE,GAAG,CAAC,EAAE,CAAC;IAE/B,4DAA4D;IAC5D,OAAO,CAAC,MAAM,CAAC,EAAE,OAAO,EAAE,GAAG;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,eAAe,CAAC,EAAE,MAAM,GAAG,MAAM,CAAA;KAAE,CAAC;IAEpF,gDAAgD;IAChD,QAAQ,IAAI,IAAI,CAAC;CAClB;AAMD;;;;;GAKG;AACH,MAAM,WAAW,kBAAkB;IACjC,wDAAwD;IACxD,OAAO,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,OAAO,EAAE,GAAG;QAAE,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC;IAE9D,mDAAmD;IACnD,KAAK,CAAC,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,OAAO,EAAE,GAAG,CAAC,EAAE,CAAC;IAEzE,iEAAiE;IACjE,QAAQ,CAAC,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,OAAO,EAAE,GAAG,CAAC,GAAG,SAAS,CAAC;CACvF;AAMD;;;;;;;;;GASG;AACH,MAAM,WAAW,cAAc;IAC7B,kEAAkE;IAClE,OAAO,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,OAAO,EAAE,GAAG,OAAO,CAAC;QAAE,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAEvE,yDAAyD;IACzD,KAAK,CAAC,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,OAAO,EAAE,GAAG,OAAO,CAAC,CAAC,EAAE,CAAC,CAAC;IAElF,kEAAkE;IAClE,QAAQ,CAAC,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,OAAO,EAAE,GAAG,OAAO,CAAC,CAAC,GAAG,SAAS,CAAC,CAAC;IAE/F,mEAAmE;IACnE,WAAW,CAAC,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACrC,GAAG,EAAE,MAAM,EACX,MAAM,CAAC,EAAE,OAAO,EAAE,GACjB,aAAa,CAAC,CAAC,CAAC,CAAC;IAEpB,sDAAsD;IACtD,OAAO,CAAC,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,GAAG,EAAE,MAAM,GAAG,iBAAiB,CAAC,CAAC,CAAC,CAAC;IAExE;;;;;OAKG;IACH,WAAW,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,kBAAkB,KAAK,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;IAE3E,2DAA2D;IAC3D,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CACxB"}
@@ -0,0 +1,65 @@
1
+ /**
2
+ * BetterSqlite3Adapter — Native SQLite Implementation of StorageAdapter
3
+ *
4
+ * Uses `better-sqlite3` for production-grade, synchronous SQLite access
5
+ * with native C++ bindings. Significantly faster than sql.js (WebAssembly)
6
+ * for most workloads, especially writes and transactions.
7
+ *
8
+ * ## Advantages over sql.js:
9
+ * - Native C++ bindings — ~3-10× faster than WebAssembly
10
+ * - True WAL mode with file-based databases
11
+ * - Real prepared statement caching
12
+ * - Synchronous API (no async overhead for each operation)
13
+ * - Lower memory overhead
14
+ *
15
+ * ## Trade-offs:
16
+ * - Requires native compilation (node-gyp, prebuild)
17
+ * - Not available in browser environments
18
+ * - Not available in some serverless environments
19
+ *
20
+ * @module fhir-persistence/db
21
+ */
22
+ import type { Database as BetterSqlite3Database } from 'better-sqlite3';
23
+ import type { StorageAdapter, PreparedStatement, TransactionContext } from './adapter.js';
24
+ export interface BetterSqlite3Options {
25
+ /** Database file path, or ':memory:' for in-memory database. */
26
+ path?: string;
27
+ /** Enable WAL journal mode (default: true). */
28
+ wal?: boolean;
29
+ /** Enable foreign key constraints (default: true). */
30
+ foreignKeys?: boolean;
31
+ /** Busy timeout in milliseconds (default: 5000). */
32
+ busyTimeout?: number;
33
+ /** Additional PRAGMA statements to execute on init. */
34
+ pragmas?: Record<string, string | number | boolean>;
35
+ }
36
+ export declare class BetterSqlite3Adapter implements StorageAdapter {
37
+ private db;
38
+ private closed;
39
+ constructor(options?: BetterSqlite3Options);
40
+ private ensureOpen;
41
+ execute(sql: string, params?: unknown[]): Promise<{
42
+ changes: number;
43
+ }>;
44
+ query<T = Record<string, unknown>>(sql: string, params?: unknown[]): Promise<T[]>;
45
+ queryOne<T = Record<string, unknown>>(sql: string, params?: unknown[]): Promise<T | undefined>;
46
+ queryStream<T = Record<string, unknown>>(sql: string, params?: unknown[]): AsyncIterable<T>;
47
+ prepare<T = Record<string, unknown>>(sql: string): PreparedStatement<T>;
48
+ transaction<R>(fn: (tx: TransactionContext) => R | Promise<R>): Promise<R>;
49
+ close(): Promise<void>;
50
+ /**
51
+ * Get the underlying better-sqlite3 Database instance.
52
+ * Use with caution — bypasses the adapter abstraction.
53
+ */
54
+ getRawDatabase(): BetterSqlite3Database;
55
+ /**
56
+ * Execute a PRAGMA and return the result.
57
+ */
58
+ pragma(statement: string): unknown;
59
+ /**
60
+ * Checkpoint WAL file to main database file.
61
+ * Useful before backup or when shutting down.
62
+ */
63
+ checkpoint(mode?: 'PASSIVE' | 'FULL' | 'RESTART' | 'TRUNCATE'): void;
64
+ }
65
+ //# sourceMappingURL=better-sqlite3-adapter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"better-sqlite3-adapter.d.ts","sourceRoot":"","sources":["../../../src/db/better-sqlite3-adapter.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAGH,OAAO,KAAK,EAAE,QAAQ,IAAI,qBAAqB,EAAE,MAAM,gBAAgB,CAAC;AACxE,OAAO,KAAK,EAAE,cAAc,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AAM1F,MAAM,WAAW,oBAAoB;IACnC,gEAAgE;IAChE,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,+CAA+C;IAC/C,GAAG,CAAC,EAAE,OAAO,CAAC;IACd,sDAAsD;IACtD,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,oDAAoD;IACpD,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,uDAAuD;IACvD,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC,CAAC;CACrD;AAED,qBAAa,oBAAqB,YAAW,cAAc;IACzD,OAAO,CAAC,EAAE,CAAwB;IAClC,OAAO,CAAC,MAAM,CAAS;gBAEX,OAAO,GAAE,oBAAyB;IA4B9C,OAAO,CAAC,UAAU;IAWZ,OAAO,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,GAAE,OAAO,EAAO,GAAG,OAAO,CAAC;QAAE,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC;IAM1E,KAAK,CAAC,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,GAAE,OAAO,EAAO,GAAG,OAAO,CAAC,CAAC,EAAE,CAAC;IAKrF,QAAQ,CAAC,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,GAAE,OAAO,EAAO,GAAG,OAAO,CAAC,CAAC,GAAG,SAAS,CAAC;IAKjG,WAAW,CAAC,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,GAAE,OAAO,EAAO,GAAG,aAAa,CAAC,CAAC,CAAC;IAQtG,OAAO,CAAC,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,GAAG,EAAE,MAAM,GAAG,iBAAiB,CAAC,CAAC,CAAC;IAsBjE,WAAW,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,kBAAkB,KAAK,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC;IA6B1E,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAW5B;;;OAGG;IACH,cAAc,IAAI,qBAAqB;IAIvC;;OAEG;IACH,MAAM,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO;IAIlC;;;OAGG;IACH,UAAU,CAAC,IAAI,GAAE,SAAS,GAAG,MAAM,GAAG,SAAS,GAAG,UAAsB,GAAG,IAAI;CAGhF"}
@@ -0,0 +1,87 @@
1
+ /**
2
+ * SqlDialect — Database-Specific SQL Generation Strategy
3
+ *
4
+ * Encapsulates syntax differences between SQLite and PostgreSQL.
5
+ * Injected into query builders (WhereBuilder, SearchSQLBuilder)
6
+ * so business logic remains dialect-agnostic.
7
+ *
8
+ * v2 upgrade: New file. v1 hardcoded PostgreSQL syntax everywhere.
9
+ *
10
+ * @module fhir-persistence/db
11
+ */
12
+ /**
13
+ * Strategy object for generating database-specific SQL fragments.
14
+ *
15
+ * Each adapter implementation provides a matching dialect instance.
16
+ */
17
+ export interface SqlDialect {
18
+ /** Dialect identifier for branching where needed. */
19
+ readonly name: 'sqlite' | 'postgres';
20
+ /**
21
+ * Positional parameter placeholder.
22
+ * - SQLite: always `?` (index ignored)
23
+ * - PostgreSQL: `$1`, `$2`, ... (1-based index)
24
+ */
25
+ placeholder(index: number): string;
26
+ /**
27
+ * Generate a TEXT[] array-contains check.
28
+ *
29
+ * Checks if any element of a TEXT[] column matches any of the given values.
30
+ * - SQLite: `EXISTS (SELECT 1 FROM json_each("col") WHERE value IN (?,?))`
31
+ * - PostgreSQL: `"col" && ARRAY[$1,$2]::text[]`
32
+ */
33
+ textArrayContains(column: string, paramCount: number, paramStartIndex: number): {
34
+ sql: string;
35
+ values: unknown[];
36
+ };
37
+ /**
38
+ * LIKE expression for string prefix / contains search.
39
+ * - SQLite: `"col" LIKE ? ESCAPE '\'`
40
+ * - PostgreSQL: `"col" LIKE $1`
41
+ */
42
+ like(column: string, paramIndex: number): string;
43
+ /**
44
+ * LIMIT / OFFSET clause.
45
+ * - SQLite: `LIMIT ? OFFSET ?`
46
+ * - PostgreSQL: `LIMIT $1 OFFSET $2`
47
+ */
48
+ limitOffset(paramStartIndex: number): {
49
+ sql: string;
50
+ };
51
+ /**
52
+ * TEXT[] array literal for INSERT/UPDATE values.
53
+ * - SQLite: JSON array string, e.g. `'["system|code","|code"]'`
54
+ * - PostgreSQL: `ARRAY['system|code','|code']::text[]`
55
+ */
56
+ arrayLiteral(values: string[]): string;
57
+ /**
58
+ * Timestamp column type.
59
+ * - SQLite: `TEXT` (ISO 8601 strings)
60
+ * - PostgreSQL: `TIMESTAMPTZ`
61
+ */
62
+ timestampType(): string;
63
+ /**
64
+ * Boolean column type.
65
+ * - SQLite: `INTEGER` (0/1)
66
+ * - PostgreSQL: `BOOLEAN`
67
+ */
68
+ booleanType(): string;
69
+ /**
70
+ * Array column type for TEXT arrays.
71
+ * - SQLite: `TEXT` (JSON serialized)
72
+ * - PostgreSQL: `TEXT[]` (native)
73
+ */
74
+ textArrayType(): string;
75
+ /**
76
+ * UPSERT suffix for ON CONFLICT handling.
77
+ * Both dialects support `ON CONFLICT ... DO UPDATE SET ...`
78
+ */
79
+ upsertSuffix(conflictColumn: string, updateColumns: string[]): string;
80
+ /**
81
+ * Auto-increment primary key type.
82
+ * - SQLite: `INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT`
83
+ * - PostgreSQL: `SERIAL PRIMARY KEY` or `INTEGER GENERATED ALWAYS AS IDENTITY`
84
+ */
85
+ autoIncrementPK(): string;
86
+ }
87
+ //# sourceMappingURL=dialect.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dialect.d.ts","sourceRoot":"","sources":["../../../src/db/dialect.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH;;;;GAIG;AACH,MAAM,WAAW,UAAU;IACzB,qDAAqD;IACrD,QAAQ,CAAC,IAAI,EAAE,QAAQ,GAAG,UAAU,CAAC;IAErC;;;;OAIG;IACH,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAAC;IAEnC;;;;;;OAMG;IACH,iBAAiB,CAAC,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,eAAe,EAAE,MAAM,GAAG;QAC9E,GAAG,EAAE,MAAM,CAAC;QACZ,MAAM,EAAE,OAAO,EAAE,CAAC;KACnB,CAAC;IAEF;;;;OAIG;IACH,IAAI,CAAC,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,MAAM,CAAC;IAEjD;;;;OAIG;IACH,WAAW,CAAC,eAAe,EAAE,MAAM,GAAG;QAAE,GAAG,EAAE,MAAM,CAAA;KAAE,CAAC;IAEtD;;;;OAIG;IACH,YAAY,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,CAAC;IAEvC;;;;OAIG;IACH,aAAa,IAAI,MAAM,CAAC;IAExB;;;;OAIG;IACH,WAAW,IAAI,MAAM,CAAC;IAEtB;;;;OAIG;IACH,aAAa,IAAI,MAAM,CAAC;IAExB;;;OAGG;IACH,YAAY,CAAC,cAAc,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,EAAE,GAAG,MAAM,CAAC;IAEtE;;;;OAIG;IACH,eAAe,IAAI,MAAM,CAAC;CAC3B"}
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Database module — Public API
3
+ *
4
+ * v1 exports: DatabaseClient (PostgreSQL-only)
5
+ * v2 exports: StorageAdapter / SqlDialect / SQLiteAdapter / SQLiteDialect
6
+ *
7
+ * @module fhir-persistence/db
8
+ */
9
+ export type { StorageAdapter, PreparedStatement, TransactionContext } from './adapter.js';
10
+ export type { SqlDialect } from './dialect.js';
11
+ export { SQLiteAdapter } from './sqlite-adapter.js';
12
+ export { SQLiteDialect } from './sqlite-dialect.js';
13
+ export { BetterSqlite3Adapter } from './better-sqlite3-adapter.js';
14
+ export type { BetterSqlite3Options } from './better-sqlite3-adapter.js';
15
+ export { PostgresAdapter, rewritePlaceholders } from './postgres-adapter.js';
16
+ export type { PgPoolLike, PgClientLike, AsyncTransactionContext } from './postgres-adapter.js';
17
+ export { PostgresDialect } from './postgres-dialect.js';
18
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/db/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAGH,YAAY,EAAE,cAAc,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AAC1F,YAAY,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAG/C,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAGpD,OAAO,EAAE,oBAAoB,EAAE,MAAM,6BAA6B,CAAC;AACnE,YAAY,EAAE,oBAAoB,EAAE,MAAM,6BAA6B,CAAC;AAGxE,OAAO,EAAE,eAAe,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AAC7E,YAAY,EAAE,UAAU,EAAE,YAAY,EAAE,uBAAuB,EAAE,MAAM,uBAAuB,CAAC;AAC/F,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC"}
@@ -0,0 +1,84 @@
1
+ /**
2
+ * PostgresAdapter — PostgreSQL Implementation of StorageAdapter
3
+ *
4
+ * Implements StorageAdapter using a pool-like interface injected at
5
+ * construction time. Does NOT import `pg` directly — accepts any
6
+ * object satisfying `PgPoolLike` (duck typing for pg.Pool).
7
+ *
8
+ * Key features:
9
+ * - Automatic `?` → `$1, $2, ...` placeholder rewriting
10
+ * - Transaction via pool client + BEGIN/COMMIT/ROLLBACK
11
+ * - queryStream via cursor-like row iteration
12
+ * - Serialization failure retry (40001) with exponential backoff
13
+ *
14
+ * @module fhir-persistence/db
15
+ */
16
+ import type { StorageAdapter, PreparedStatement, TransactionContext } from './adapter.js';
17
+ /**
18
+ * Minimal interface that pg.Pool satisfies.
19
+ * Allows PostgresAdapter to work without importing `pg`.
20
+ */
21
+ export interface PgPoolLike {
22
+ query(text: string, values?: unknown[]): Promise<{
23
+ rows: Record<string, unknown>[];
24
+ rowCount: number | null;
25
+ }>;
26
+ connect(): Promise<PgClientLike>;
27
+ end(): Promise<void>;
28
+ }
29
+ /**
30
+ * Minimal interface that pg.PoolClient satisfies.
31
+ */
32
+ export interface PgClientLike {
33
+ query(text: string, values?: unknown[]): Promise<{
34
+ rows: Record<string, unknown>[];
35
+ rowCount: number | null;
36
+ }>;
37
+ release(): void;
38
+ }
39
+ /**
40
+ * Rewrite `?` placeholders to PostgreSQL `$1, $2, ...` positional params.
41
+ *
42
+ * Handles:
43
+ * - Skips `?` inside single-quoted string literals
44
+ * - Sequential numbering starting from $1
45
+ *
46
+ * @param sql - SQL with `?` placeholders.
47
+ * @returns SQL with `$N` placeholders.
48
+ */
49
+ export declare function rewritePlaceholders(sql: string): string;
50
+ export declare class PostgresAdapter implements StorageAdapter {
51
+ private readonly pool;
52
+ private closed;
53
+ constructor(pool: PgPoolLike);
54
+ execute(sql: string, params?: unknown[]): Promise<{
55
+ changes: number;
56
+ }>;
57
+ query<T = Record<string, unknown>>(sql: string, params?: unknown[]): Promise<T[]>;
58
+ queryOne<T = Record<string, unknown>>(sql: string, params?: unknown[]): Promise<T | undefined>;
59
+ queryStream<T = Record<string, unknown>>(sql: string, params?: unknown[]): AsyncIterable<T>;
60
+ prepare<T = Record<string, unknown>>(_sql: string): PreparedStatement<T>;
61
+ transaction<R>(fn: (tx: TransactionContext) => R | Promise<R>): Promise<R>;
62
+ /**
63
+ * Async-native transaction for PostgreSQL.
64
+ *
65
+ * Unlike the StorageAdapter.transaction() which has synchronous
66
+ * TransactionContext methods (designed for SQLite), this method
67
+ * provides async transaction operations matching PG's async nature.
68
+ */
69
+ transactionAsync<R>(fn: (tx: AsyncTransactionContext) => Promise<R>): Promise<R>;
70
+ close(): Promise<void>;
71
+ private ensureNotClosed;
72
+ }
73
+ /**
74
+ * Async transaction context for PostgreSQL.
75
+ * All methods are async (unlike StorageAdapter's sync TransactionContext).
76
+ */
77
+ export interface AsyncTransactionContext {
78
+ execute(sql: string, params?: unknown[]): Promise<{
79
+ changes: number;
80
+ }>;
81
+ query<T = Record<string, unknown>>(sql: string, params?: unknown[]): Promise<T[]>;
82
+ queryOne<T = Record<string, unknown>>(sql: string, params?: unknown[]): Promise<T | undefined>;
83
+ }
84
+ //# sourceMappingURL=postgres-adapter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"postgres-adapter.d.ts","sourceRoot":"","sources":["../../../src/db/postgres-adapter.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,36 @@
1
+ /**
2
+ * PostgresDialect — PostgreSQL-Specific SQL Generation
3
+ *
4
+ * Implements SqlDialect for PostgreSQL syntax:
5
+ * - `$1, $2, ...` positional placeholders
6
+ * - Native TEXT[] arrays with `&& ARRAY[...]::text[]`
7
+ * - TIMESTAMPTZ for timestamps
8
+ * - BOOLEAN for booleans
9
+ * - GIN indexes for array contains
10
+ * - GENERATED ALWAYS AS IDENTITY for auto-increment
11
+ *
12
+ * v2 upgrade: New file. v1 hardcoded PG syntax in business logic.
13
+ * Now encapsulated in this dialect object.
14
+ *
15
+ * @module fhir-persistence/db
16
+ */
17
+ import type { SqlDialect } from './dialect.js';
18
+ export declare class PostgresDialect implements SqlDialect {
19
+ readonly name: "postgres";
20
+ placeholder(index: number): string;
21
+ textArrayContains(column: string, paramCount: number, paramStartIndex: number): {
22
+ sql: string;
23
+ values: unknown[];
24
+ };
25
+ like(column: string, paramIndex: number): string;
26
+ limitOffset(paramStartIndex: number): {
27
+ sql: string;
28
+ };
29
+ arrayLiteral(values: string[]): string;
30
+ timestampType(): string;
31
+ booleanType(): string;
32
+ textArrayType(): string;
33
+ upsertSuffix(conflictColumn: string, updateColumns: string[]): string;
34
+ autoIncrementPK(): string;
35
+ }
36
+ //# sourceMappingURL=postgres-dialect.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"postgres-dialect.d.ts","sourceRoot":"","sources":["../../../src/db/postgres-dialect.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAE/C,qBAAa,eAAgB,YAAW,UAAU;IAChD,QAAQ,CAAC,IAAI,EAAG,UAAU,CAAU;IAEpC,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM;IAIlC,iBAAiB,CAAC,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,eAAe,EAAE,MAAM,GAAG;QAC9E,GAAG,EAAE,MAAM,CAAC;QACZ,MAAM,EAAE,OAAO,EAAE,CAAC;KACnB;IAWD,IAAI,CAAC,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,MAAM;IAIhD,WAAW,CAAC,eAAe,EAAE,MAAM,GAAG;QAAE,GAAG,EAAE,MAAM,CAAA;KAAE;IAIrD,YAAY,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM;IAQtC,aAAa,IAAI,MAAM;IAIvB,WAAW,IAAI,MAAM;IAIrB,aAAa,IAAI,MAAM;IAIvB,YAAY,CAAC,cAAc,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,EAAE,GAAG,MAAM;IAKrE,eAAe,IAAI,MAAM;CAG1B"}
@@ -0,0 +1,41 @@
1
+ /**
2
+ * SQLiteAdapter — SQLite Implementation of StorageAdapter
3
+ *
4
+ * Uses `sql.js` (WebAssembly-based SQLite) for cross-platform
5
+ * compatibility without native C++ compilation requirements.
6
+ *
7
+ * v2 upgrade: New file. v1 had no SQLite support.
8
+ *
9
+ * ## WAL Mode
10
+ * sql.js runs in-memory by default. For file-based databases,
11
+ * WAL mode and foreign keys are enabled on construction.
12
+ *
13
+ * @module fhir-persistence/db
14
+ */
15
+ import type { StorageAdapter, PreparedStatement, TransactionContext } from './adapter.js';
16
+ export declare class SQLiteAdapter implements StorageAdapter {
17
+ private readonly data?;
18
+ private db;
19
+ private initPromise;
20
+ /**
21
+ * @param path - Database file path, or ':memory:' for in-memory database.
22
+ * @param data - Optional Uint8Array of an existing database file to load.
23
+ */
24
+ constructor(_path?: string, data?: Uint8Array | undefined);
25
+ private initialize;
26
+ private getDb;
27
+ execute(sql: string, params?: unknown[]): Promise<{
28
+ changes: number;
29
+ }>;
30
+ query<T = Record<string, unknown>>(sql: string, params?: unknown[]): Promise<T[]>;
31
+ queryOne<T = Record<string, unknown>>(sql: string, params?: unknown[]): Promise<T | undefined>;
32
+ queryStream<T = Record<string, unknown>>(sql: string, params?: unknown[]): AsyncIterable<T>;
33
+ prepare<T = Record<string, unknown>>(sql: string): PreparedStatement<T>;
34
+ transaction<R>(fn: (tx: TransactionContext) => R | Promise<R>): Promise<R>;
35
+ close(): Promise<void>;
36
+ /**
37
+ * Export the database as a Uint8Array (for file persistence).
38
+ */
39
+ export(): Promise<Uint8Array>;
40
+ }
41
+ //# sourceMappingURL=sqlite-adapter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sqlite-adapter.d.ts","sourceRoot":"","sources":["../../../src/db/sqlite-adapter.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAIH,OAAO,KAAK,EAAE,cAAc,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AAsB1F,qBAAa,aAAc,YAAW,cAAc;IAUhD,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC;IATxB,OAAO,CAAC,EAAE,CAA8B;IACxC,OAAO,CAAC,WAAW,CAAgB;IAEnC;;;OAGG;gBAED,KAAK,GAAE,MAAmB,EACT,IAAI,CAAC,EAAE,UAAU,YAAA;YAKtB,UAAU;YASV,KAAK;IAQb,OAAO,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,GAAE,OAAO,EAAO,GAAG,OAAO,CAAC;QAAE,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC;IAQ1E,KAAK,CAAC,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,GAAE,OAAO,EAAO,GAAG,OAAO,CAAC,CAAC,EAAE,CAAC;IAarF,QAAQ,CAAC,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,GAAE,OAAO,EAAO,GAAG,OAAO,CAAC,CAAC,GAAG,SAAS,CAAC;IAajG,WAAW,CAAC,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,GAAE,OAAO,EAAO,GAAG,aAAa,CAAC,CAAC,CAAC;IActG,OAAO,CAAC,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,GAAG,EAAE,MAAM,GAAG,iBAAiB,CAAC,CAAC,CAAC;IAmCjE,WAAW,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,kBAAkB,KAAK,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC;IA6C1E,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAQ5B;;OAEG;IACG,MAAM,IAAI,OAAO,CAAC,UAAU,CAAC;CAIpC"}