fhir-engine 0.4.0 → 0.4.2

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,47 @@ 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.4.2] - 2026-03-15
9
+
10
+ ### Added
11
+
12
+ - **PostgreSQL support** — `database.type = 'postgres'` now creates a `PostgresAdapter` via `pg.Pool`, with full CRUD, search, schema migration, and dual-backend support. Requires `npm install pg` as a peer dependency.
13
+ - **`PostgresDatabaseConfig` pool options** — New optional fields: `max`, `idleTimeoutMillis`, `connectionTimeoutMillis` for connection pool tuning
14
+ - **Credential masking** — PostgreSQL connection URL is masked in log output (`//*****@`)
15
+
16
+ ### Changed
17
+
18
+ - **`fhir-persistence` dependency** — upgraded from `^0.1.0` to `^0.3.0` (adds `PostgresAdapter`, `PostgresDialect`, dual-backend validation)
19
+ - **`sqlite-wasm` adapter deprecated** — `SQLiteAdapter` was removed in fhir-persistence v0.3.0; `database.type = 'sqlite-wasm'` now throws a descriptive error directing users to `'sqlite'`
20
+ - **Test suite expanded** — from 96 to 97 tests:
21
+ - New: sqlite-wasm deprecation error test, postgres pg-missing error test
22
+
23
+ ### Notes
24
+
25
+ - PostgreSQL requires the `pg` npm package as a peer dependency (`npm install pg`)
26
+ - The engine lazy-imports `pg` so SQLite-only projects incur no extra dependency
27
+ - All existing SQLite functionality is unaffected
28
+
29
+ ---
30
+
31
+ ## [0.4.1] - 2026-03-15
32
+
33
+ ### Fixed
34
+
35
+ - **`resolvePackages()` — 0 resource types after cache linking** — When the system cache package was installed by third-party tools (e.g. Firely Terminal) that only place `package.json` inside the `package/` subdirectory (not at cache root), `PackageScanner` would discover the package at the wrong depth, causing `PackageLoader` to construct a double-nested `package/package` path → ENOENT → 0 StructureDefinitions loaded → 0 tables created → `no such table: Patient_References`
36
+ - **New helper `ensureCacheRootManifest()`** — Copies `package/package.json` to cache root before creating junction/symlink, ensuring consistent structure regardless of which tool populated the cache
37
+
38
+ ### Changed
39
+
40
+ - **Test suite expanded** — from 95 to 96 tests:
41
+ - New test: verify cache root `package.json` exists after resolve (Firely Terminal scenario)
42
+
43
+ ### Notes
44
+
45
+ - Resolves `FIX_ZERO_RESOURCE_TYPES.md` — Method A fix applied in `fhir-engine`; optional Method B (fhir-definition scanner hardening) deferred to P1
46
+
47
+ ---
48
+
8
49
  ## [0.4.0] - 2026-03-15
9
50
 
10
51
  ### Added
package/README.md CHANGED
@@ -13,7 +13,7 @@
13
13
  - **Package resolution** — `resolvePackages()` downloads/caches FHIR IG packages automatically
14
14
  - **Plugin system** — lifecycle hooks (`init` / `start` / `ready` / `stop`) for extensibility
15
15
  - **Config file support** — `fhir.config.ts` / `.js` / `.json` with env variable overrides
16
- - **Multi-adapter** — SQLite (native + WASM) out of the box, PostgreSQL planned
16
+ - **Multi-adapter** — SQLite (native) and PostgreSQL out of the box
17
17
  - **TypeScript-first** — full type safety, dual ESM/CJS builds
18
18
 
19
19
  ## Install
@@ -272,16 +272,35 @@ Loads config from a file. Auto-discovers `fhir.config.ts` → `.js` → `.mjs`
272
272
 
273
273
  ## Database Adapters
274
274
 
275
- | `database.type` | Adapter | Use Case |
276
- | --------------- | ---------------------- | --------------------------- |
277
- | `sqlite` | `BetterSqlite3Adapter` | Node.js / Electron / CLI |
278
- | `sqlite-wasm` | `SQLiteAdapter` | Browser / WASM |
279
- | `postgres` | — | Not yet available (planned) |
275
+ | `database.type` | Adapter | Use Case |
276
+ | --------------- | ---------------------- | ---------------------------------- |
277
+ | `sqlite` | `BetterSqlite3Adapter` | Node.js / Electron / CLI |
278
+ | `postgres` | `PostgresAdapter` | Production servers (via `pg.Pool`) |
279
+ | `sqlite-wasm` | — | Removed in v0.4.2 use `sqlite` |
280
+
281
+ ### PostgreSQL Setup
282
+
283
+ ```bash
284
+ npm install pg # required peer dependency for postgres
285
+ ```
286
+
287
+ ```ts
288
+ const engine = await createFhirEngine({
289
+ database: {
290
+ type: "postgres",
291
+ url: "postgresql://user:pass@localhost:5432/fhir_db",
292
+ max: 20, // pool size (default: 10)
293
+ idleTimeoutMillis: 30000, // idle timeout (default: 30s)
294
+ },
295
+ packages: { path: "./fhir-packages" },
296
+ });
297
+ ```
280
298
 
281
299
  ## Requirements
282
300
 
283
301
  - Node.js >= 18.0.0
284
302
  - npm >= 9.0.0
303
+ - `pg` package (only if using PostgreSQL)
285
304
 
286
305
  ## License
287
306
 
@@ -53,14 +53,28 @@ function createAdapter(config, logger) {
53
53
  });
54
54
  }
55
55
  case "sqlite-wasm": {
56
- logger.info(`Creating SQLiteAdapter (WASM, path: ${config.path})`);
57
- return new import_fhir_persistence.SQLiteAdapter(config.path);
58
- }
59
- case "postgres": {
60
56
  throw new Error(
61
- 'fhir-engine: PostgreSQL adapter is not yet available. PostgresAdapter is not exported from fhir-persistence v0.1.0. Use database.type = "sqlite" for now.'
57
+ 'fhir-engine: sqlite-wasm adapter was removed in fhir-persistence v0.3.0. Use database.type = "sqlite" (BetterSqlite3Adapter) instead.'
62
58
  );
63
59
  }
60
+ case "postgres": {
61
+ logger.info(`Creating PostgresAdapter (url: ${config.url.replace(/\/\/.*@/, "//*****@")})`);
62
+ let Pool;
63
+ try {
64
+ Pool = require("pg").Pool;
65
+ } catch {
66
+ throw new Error(
67
+ 'fhir-engine: PostgreSQL requires the "pg" package. Install it with: npm install pg'
68
+ );
69
+ }
70
+ const pool = new Pool({
71
+ connectionString: config.url,
72
+ max: config.max ?? 10,
73
+ idleTimeoutMillis: config.idleTimeoutMillis ?? 3e4,
74
+ connectionTimeoutMillis: config.connectionTimeoutMillis ?? 0
75
+ });
76
+ return new import_fhir_persistence.PostgresAdapter(pool);
77
+ }
64
78
  default: {
65
79
  const _exhaustive = config;
66
80
  throw new Error(`fhir-engine: unknown database type: ${_exhaustive.type}`);
@@ -246,6 +260,7 @@ async function resolvePackages(config, options) {
246
260
  const cachePath = cache.getPath(ig.name, version);
247
261
  if (cachePath) {
248
262
  logger?.info(`Found ${ig.name}@${version} in system cache, linking...`);
263
+ ensureCacheRootManifest(cachePath);
249
264
  createLink(cachePath, localPath);
250
265
  results.push({ name: ig.name, version, path: localPath, source: "cache" });
251
266
  continue;
@@ -266,6 +281,7 @@ async function resolvePackages(config, options) {
266
281
  errors.push({ name: ig.name, error: `Failed to locate cached package after download` });
267
282
  continue;
268
283
  }
284
+ ensureCacheRootManifest(newCachePath);
269
285
  createLink(newCachePath, localPath);
270
286
  results.push({ name: ig.name, version, path: localPath, source: "download" });
271
287
  } catch (err) {
@@ -281,6 +297,13 @@ async function resolvePackages(config, options) {
281
297
  errors
282
298
  };
283
299
  }
300
+ function ensureCacheRootManifest(cachePath) {
301
+ const rootManifest = (0, import_node_path2.join)(cachePath, "package.json");
302
+ const nestedManifest = (0, import_node_path2.join)(cachePath, "package", "package.json");
303
+ if (!(0, import_node_fs2.existsSync)(rootManifest) && (0, import_node_fs2.existsSync)(nestedManifest)) {
304
+ (0, import_node_fs2.copyFileSync)(nestedManifest, rootManifest);
305
+ }
306
+ }
284
307
  function createLink(target, linkPath) {
285
308
  if ((0, import_node_fs2.existsSync)(linkPath)) {
286
309
  try {
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/index.ts", "../../src/engine.ts", "../../src/adapter-factory.ts", "../../src/config.ts", "../../src/logger.ts", "../../src/package-resolver.ts"],
4
- "sourcesContent": ["// fhir-engine \u2014 public API\n\nexport { createFhirEngine } from './engine.js';\nexport { defineConfig, loadFhirConfig } from './config.js';\nexport { createConsoleLogger } from './logger.js';\nexport { createAdapter } from './adapter-factory.js';\nexport { resolvePackages } from './package-resolver.js';\n\nexport type {\n FhirEngine,\n FhirEngineConfig,\n FhirEnginePlugin,\n FhirEngineStatus,\n EngineContext,\n DatabaseConfig,\n SqliteDatabaseConfig,\n SqliteWasmDatabaseConfig,\n PostgresDatabaseConfig,\n PackagesConfig,\n Logger,\n ResolvePackagesOptions,\n ResolvedPackage,\n ResolvePackagesResult,\n} from './types.js';\n\n// Re-export key upstream types for convenience\nexport type { DefinitionRegistry, DefinitionProvider } from 'fhir-definition';\nexport type { FhirRuntimeInstance } from 'fhir-runtime';\nexport type { FhirPersistence, StorageAdapter } from 'fhir-persistence';\n\n// ---------------------------------------------------------------------------\n// Search utilities (from fhir-persistence)\n// ---------------------------------------------------------------------------\n\nexport { parseSearchRequest, executeSearch } from 'fhir-persistence';\nexport type { SearchRequest, SearchResult, SearchOptions } from 'fhir-persistence';\n\n// ---------------------------------------------------------------------------\n// FHIRPath evaluation (from fhir-runtime)\n// ---------------------------------------------------------------------------\n\nexport { evalFhirPath, evalFhirPathBoolean, evalFhirPathString, evalFhirPathTyped } from 'fhir-runtime';\n", "import { loadDefinitionPackages } from 'fhir-definition';\nimport { createRuntime, extractSearchValues, extractAllSearchValues, extractReferences } from 'fhir-runtime';\nimport { FhirDefinitionBridge, FhirRuntimeProvider, FhirSystem, parseSearchRequest, executeSearch } from 'fhir-persistence';\n\nimport { createAdapter } from './adapter-factory.js';\nimport { loadFhirConfig } from './config.js';\nimport { createConsoleLogger } from './logger.js';\nimport { resolvePackages } from './package-resolver.js';\nimport type { EngineContext, FhirEngine, FhirEngineConfig, FhirEnginePlugin, FhirEngineStatus } from './types.js';\n\n/**\n * Resolve the SQL dialect from the database config type.\n */\nfunction resolveDialect(type: FhirEngineConfig['database']['type']): 'sqlite' | 'postgres' {\n switch (type) {\n case 'sqlite':\n case 'sqlite-wasm':\n return 'sqlite';\n case 'postgres':\n return 'postgres';\n }\n}\n\n/**\n * Validate the engine configuration, throwing on missing required fields.\n */\nfunction validateConfig(config: FhirEngineConfig): void {\n if (!config.database) {\n throw new Error('fhir-engine: config.database is required');\n }\n if (!config.database.type) {\n throw new Error('fhir-engine: config.database.type is required (sqlite | sqlite-wasm | postgres)');\n }\n if (!config.packages) {\n throw new Error('fhir-engine: config.packages is required');\n }\n if (!config.packages.path) {\n throw new Error('fhir-engine: config.packages.path is required');\n }\n}\n\n/**\n * Run a lifecycle hook on all plugins in order.\n * Wraps errors with the plugin name for clear diagnostics.\n */\nasync function runPluginHook(\n plugins: FhirEnginePlugin[],\n hook: 'init' | 'start' | 'ready',\n ctx: EngineContext,\n): Promise<void> {\n for (const plugin of plugins) {\n const fn = plugin[hook];\n if (fn) {\n try {\n await fn.call(plugin, ctx);\n } catch (err) {\n throw new Error(\n `fhir-engine: plugin \"${plugin.name}\" failed during ${hook}: ${err instanceof Error ? err.message : String(err)}`,\n { cause: err },\n );\n }\n }\n }\n}\n\n/**\n * Create and bootstrap a fully initialized FHIR engine.\n *\n * This is the single entry point for all FHIR applications.\n * It assembles fhir-definition, fhir-runtime, and fhir-persistence\n * into a running system from a single configuration object.\n *\n * @example\n * ```ts\n * const engine = await createFhirEngine({\n * database: { type: 'sqlite', path: ':memory:' },\n * packages: { path: './fhir-packages' },\n * });\n *\n * const patient = await engine.persistence.createResource('Patient', {\n * resourceType: 'Patient',\n * name: [{ family: 'Smith', given: ['John'] }],\n * });\n *\n * await engine.stop();\n * ```\n */\nexport async function createFhirEngine(config?: FhirEngineConfig): Promise<FhirEngine> {\n // \u2500\u2500 0. Resolve config \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n if (!config) {\n config = await loadFhirConfig();\n }\n validateConfig(config);\n\n const logger = config.logger ?? createConsoleLogger();\n const plugins = config.plugins ?? [];\n logger.info('Initializing fhir-engine...');\n\n // \u2500\u2500 1a. Resolve packages (download/link if config.igs is set) \u2500\n if (config.igs && config.igs.length > 0) {\n logger.info(`Resolving ${config.igs.length} IG package(s)...`);\n const resolveResult = await resolvePackages(config, { logger });\n for (const pkg of resolveResult.packages) {\n logger.info(`Resolved ${pkg.name}@${pkg.version} (${pkg.source})`);\n }\n if (!resolveResult.success) {\n for (const err of resolveResult.errors) {\n logger.warn(`Failed to resolve package ${err.name}: ${err.error}`);\n }\n }\n }\n\n // \u2500\u2500 1b. Load FHIR definitions \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n logger.info(`Loading FHIR packages from: ${config.packages.path}`);\n const { registry, result } = loadDefinitionPackages(config.packages.path);\n logger.info(\n `Loaded ${result.packages.length} package(s): ${result.packages.map((p) => `${p.name}@${p.version}`).join(', ')}`,\n );\n\n // \u2500\u2500 2. Create fhir-runtime \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n logger.info('Creating fhir-runtime instance...');\n const runtime = await createRuntime({ definitions: registry, preloadCore: false });\n\n // \u2500\u2500 3. Build provider bridges \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n const definitionBridge = new FhirDefinitionBridge(registry);\n const runtimeProvider = new FhirRuntimeProvider({\n extractSearchValues,\n extractAllSearchValues,\n extractReferences,\n });\n\n // \u2500\u2500 4. Create storage adapter \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n const adapter = createAdapter(config.database, logger);\n\n // \u2500\u2500 5. Build EngineContext \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n const ctx: { -readonly [K in keyof EngineContext]: EngineContext[K] } = {\n config,\n definitions: registry,\n runtime,\n adapter,\n persistence: undefined,\n logger,\n };\n\n // \u2500\u2500 6. INIT phase \u2014 plugins run before persistence \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n if (plugins.length > 0) {\n logger.info(`Running init for ${plugins.length} plugin(s): ${plugins.map((p) => p.name).join(', ')}`);\n await runPluginHook(plugins, 'init', ctx);\n }\n\n // \u2500\u2500 7. Initialize FhirSystem \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n const dialect = resolveDialect(config.database.type);\n const system = new FhirSystem(adapter, {\n dialect,\n runtimeProvider,\n packageName: config.packageName ?? 'fhir-engine.default',\n packageVersion: config.packageVersion ?? '1.0.0',\n });\n\n logger.info('Initializing persistence system (schema + migration)...');\n const { persistence, sdRegistry, spRegistry, igResult, resourceTypes } =\n await system.initialize(definitionBridge);\n\n logger.info(`Persistence ready \u2014 IG action: ${igResult.action}, ${resourceTypes.length} resource type(s)`);\n\n // ctx.persistence now available\n ctx.persistence = persistence;\n\n // \u2500\u2500 8. START phase \u2014 plugins can access persistence \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n if (plugins.length > 0) {\n logger.info(`Running start for ${plugins.length} plugin(s)...`);\n await runPluginHook(plugins, 'start', ctx);\n }\n\n // \u2500\u2500 9. READY phase \u2014 system fully operational \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n if (plugins.length > 0) {\n logger.info(`Running ready for ${plugins.length} plugin(s)...`);\n await runPluginHook(plugins, 'ready', ctx);\n }\n\n // \u2500\u2500 10. Return FhirEngine \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n let stopped = false;\n const startedAt = new Date();\n const loadedPackages = result.packages.map((p) => `${p.name}@${p.version}`);\n const fhirVersions = [...new Set(\n result.packages\n .map((p) => {\n if (p.name.includes('.r4.')) return '4.0';\n if (p.name.includes('.r4b.')) return '4.3';\n if (p.name.includes('.r5.')) return '5.0';\n return undefined;\n })\n .filter(Boolean),\n )] as string[];\n\n const engine: FhirEngine = {\n definitions: registry,\n runtime,\n adapter,\n persistence,\n sdRegistry,\n spRegistry,\n igResult,\n resourceTypes,\n logger,\n context: ctx as EngineContext,\n\n async search(resourceType, queryParams, options) {\n const request = parseSearchRequest(resourceType, queryParams, spRegistry);\n return executeSearch(adapter, request, spRegistry, options);\n },\n\n status(): FhirEngineStatus {\n return {\n fhirVersions,\n loadedPackages,\n resourceTypes,\n databaseType: config.database.type,\n igAction: igResult.action,\n startedAt,\n plugins: plugins.map((p) => p.name),\n };\n },\n\n async stop() {\n if (stopped) return;\n stopped = true;\n logger.info('Stopping fhir-engine...');\n\n // Stop plugins in reverse registration order\n for (let i = plugins.length - 1; i >= 0; i--) {\n const plugin = plugins[i];\n if (plugin.stop) {\n try {\n await plugin.stop.call(plugin, ctx as EngineContext);\n } catch (err) {\n logger.error(\n `Plugin \"${plugin.name}\" failed during stop: ${err instanceof Error ? err.message : String(err)}`,\n );\n }\n }\n }\n\n await adapter.close();\n logger.info('fhir-engine stopped.');\n },\n };\n\n logger.info('fhir-engine ready.');\n return engine;\n}\n", "import { BetterSqlite3Adapter, SQLiteAdapter } from 'fhir-persistence';\nimport type { StorageAdapter } from 'fhir-persistence';\nimport type { DatabaseConfig, Logger } from './types.js';\n\n/**\n * Create a StorageAdapter from the database configuration.\n *\n * Supported adapters:\n * - `sqlite` \u2192 BetterSqlite3Adapter (native, Node.js / Electron)\n * - `sqlite-wasm` \u2192 SQLiteAdapter (sql.js WASM, browser / cross-platform)\n * - `postgres` \u2192 not yet available (PostgresAdapter not exported from fhir-persistence)\n */\nexport function createAdapter(config: DatabaseConfig, logger: Logger): StorageAdapter {\n switch (config.type) {\n case 'sqlite': {\n logger.info(`Creating BetterSqlite3Adapter (path: ${config.path})`);\n return new BetterSqlite3Adapter({\n path: config.path,\n wal: config.wal ?? true,\n busyTimeout: config.busyTimeout ?? 5000,\n });\n }\n\n case 'sqlite-wasm': {\n logger.info(`Creating SQLiteAdapter (WASM, path: ${config.path})`);\n return new SQLiteAdapter(config.path);\n }\n\n case 'postgres': {\n throw new Error(\n 'fhir-engine: PostgreSQL adapter is not yet available. ' +\n 'PostgresAdapter is not exported from fhir-persistence v0.1.0. ' +\n 'Use database.type = \"sqlite\" for now.',\n );\n }\n\n default: {\n const _exhaustive: never = config;\n throw new Error(`fhir-engine: unknown database type: ${(_exhaustive as DatabaseConfig).type}`);\n }\n }\n}\n", "import { existsSync, readFileSync } from 'node:fs';\nimport { resolve, extname } from 'node:path';\nimport { pathToFileURL } from 'node:url';\nimport type { FhirEngineConfig, DatabaseConfig } from './types.js';\n\n// ---------------------------------------------------------------------------\n// defineConfig \u2014 typed identity helper for fhir.config.ts / .js\n// ---------------------------------------------------------------------------\n\n/**\n * Type-safe config helper for `fhir.config.ts` / `fhir.config.js`.\n *\n * @example\n * ```ts\n * // fhir.config.ts\n * import { defineConfig } from 'fhir-engine';\n *\n * export default defineConfig({\n * database: { type: 'sqlite', path: './fhir.db' },\n * packages: { path: './fhir-packages' },\n * });\n * ```\n */\nexport function defineConfig(config: FhirEngineConfig): FhirEngineConfig {\n return config;\n}\n\n// ---------------------------------------------------------------------------\n// Config file discovery order\n// ---------------------------------------------------------------------------\n\nconst CONFIG_FILENAMES = [\n 'fhir.config.ts',\n 'fhir.config.js',\n 'fhir.config.mjs',\n 'fhir.config.json',\n] as const;\n\n// ---------------------------------------------------------------------------\n// loadFhirConfig \u2014 auto-discover and load config\n// ---------------------------------------------------------------------------\n\n/**\n * Load engine configuration from a file.\n *\n * If `configPath` is provided, loads that exact file.\n * Otherwise, searches the current working directory for config files\n * in this order: `fhir.config.ts` \u2192 `fhir.config.js` \u2192 `fhir.config.mjs` \u2192 `fhir.config.json`.\n *\n * Environment variable overrides are applied on top of the loaded config.\n *\n * @param configPath - Explicit path to a config file (optional).\n * @returns The resolved `FhirEngineConfig`.\n */\nexport async function loadFhirConfig(configPath?: string): Promise<FhirEngineConfig> {\n let resolvedPath: string;\n\n if (configPath) {\n resolvedPath = resolve(configPath);\n if (!existsSync(resolvedPath)) {\n throw new Error(`fhir-engine: config file not found: ${resolvedPath}`);\n }\n } else {\n const cwd = process.cwd();\n const found = CONFIG_FILENAMES\n .map((name) => resolve(cwd, name))\n .find((p) => existsSync(p));\n if (!found) {\n throw new Error(\n `fhir-engine: no config file found in ${cwd}. ` +\n `Expected one of: ${CONFIG_FILENAMES.join(', ')}`,\n );\n }\n resolvedPath = found;\n }\n\n const config = await loadConfigFile(resolvedPath);\n return applyEnvOverrides(config);\n}\n\n// ---------------------------------------------------------------------------\n// File loaders\n// ---------------------------------------------------------------------------\n\nasync function loadConfigFile(filePath: string): Promise<FhirEngineConfig> {\n const ext = extname(filePath);\n\n if (ext === '.json') {\n return loadJsonConfig(filePath);\n }\n\n if (ext === '.ts' || ext === '.js' || ext === '.mjs') {\n return loadModuleConfig(filePath);\n }\n\n throw new Error(`fhir-engine: unsupported config file extension: ${ext}`);\n}\n\nfunction loadJsonConfig(filePath: string): FhirEngineConfig {\n try {\n const raw = readFileSync(filePath, 'utf-8');\n return JSON.parse(raw) as FhirEngineConfig;\n } catch (err) {\n throw new Error(\n `fhir-engine: failed to parse config file ${filePath}: ${err instanceof Error ? err.message : String(err)}`,\n { cause: err },\n );\n }\n}\n\nasync function loadModuleConfig(filePath: string): Promise<FhirEngineConfig> {\n try {\n const fileUrl = pathToFileURL(filePath).href;\n const mod = await import(fileUrl);\n const config = mod.default ?? mod;\n\n if (!config || typeof config !== 'object') {\n throw new Error('config file must export a FhirEngineConfig object as default export');\n }\n\n return config as FhirEngineConfig;\n } catch (err) {\n if (err instanceof Error && err.message.includes('must export')) {\n throw err;\n }\n throw new Error(\n `fhir-engine: failed to load config file ${filePath}: ${err instanceof Error ? err.message : String(err)}`,\n { cause: err },\n );\n }\n}\n\n// ---------------------------------------------------------------------------\n// Environment variable overrides\n// ---------------------------------------------------------------------------\n\nconst VALID_DB_TYPES = ['sqlite', 'sqlite-wasm', 'postgres'] as const;\n\n/**\n * Apply environment variable overrides on top of a loaded config.\n *\n * | Env Variable | Overrides |\n * |---------------------|----------------------------------|\n * | FHIR_DATABASE_TYPE | config.database.type |\n * | FHIR_DATABASE_URL | config.database.path / .url |\n * | FHIR_PACKAGES_PATH | config.packages.path |\n * | FHIR_LOG_LEVEL | (stored for logger filtering) |\n */\nexport function applyEnvOverrides(config: FhirEngineConfig): FhirEngineConfig {\n const result = structuredClone(config);\n\n const dbType = process.env.FHIR_DATABASE_TYPE;\n const dbUrl = process.env.FHIR_DATABASE_URL;\n const pkgPath = process.env.FHIR_PACKAGES_PATH;\n\n if (dbType) {\n if (!VALID_DB_TYPES.includes(dbType as typeof VALID_DB_TYPES[number])) {\n throw new Error(\n `fhir-engine: FHIR_DATABASE_TYPE must be one of: ${VALID_DB_TYPES.join(', ')}. Got: \"${dbType}\"`,\n );\n }\n // Rebuild database config with overridden type\n const validType = dbType as DatabaseConfig['type'];\n if (validType === 'postgres') {\n result.database = { type: 'postgres', url: (result.database as { url?: string }).url ?? '' };\n } else if (validType === 'sqlite-wasm') {\n result.database = { type: 'sqlite-wasm', path: (result.database as { path?: string }).path ?? '' };\n } else {\n result.database = { type: 'sqlite', path: (result.database as { path?: string }).path ?? '' };\n }\n }\n\n if (dbUrl) {\n const type = result.database?.type;\n if (type === 'postgres') {\n result.database = { ...result.database, type: 'postgres', url: dbUrl };\n } else if (type === 'sqlite-wasm') {\n result.database = { ...result.database, type: 'sqlite-wasm', path: dbUrl };\n } else {\n result.database = { ...result.database, type: 'sqlite', path: dbUrl };\n }\n }\n\n if (pkgPath) {\n result.packages = { ...result.packages, path: pkgPath };\n }\n\n return result;\n}\n", "import type { Logger } from './types.js';\n\n/**\n * Default console-based logger.\n */\nexport function createConsoleLogger(): Logger {\n return {\n debug: (message: string, ...args: unknown[]) => console.debug(`[fhir-engine] ${message}`, ...args),\n info: (message: string, ...args: unknown[]) => console.info(`[fhir-engine] ${message}`, ...args),\n warn: (message: string, ...args: unknown[]) => console.warn(`[fhir-engine] ${message}`, ...args),\n error: (message: string, ...args: unknown[]) => console.error(`[fhir-engine] ${message}`, ...args),\n };\n}\n", "import { resolve, join } from 'node:path';\nimport { existsSync, mkdirSync, symlinkSync, readFileSync, lstatSync } from 'node:fs';\nimport { PackageCache, PackageRegistryClient } from 'fhir-definition';\n\nimport type { FhirEngineConfig, ResolvePackagesOptions, ResolvedPackage, ResolvePackagesResult, Logger } from './types.js';\n\n/**\n * Ensure the given directory exists (recursive mkdir).\n */\nfunction ensureDirSync(dir: string): void {\n if (!existsSync(dir)) {\n mkdirSync(dir, { recursive: true });\n }\n}\n\n/**\n * Check if a directory contains a FHIR package manifest.\n * Checks both root/package.json and package/package.json\n * (cached packages store content in a 'package' subdirectory).\n */\nfunction hasManifest(dir: string): boolean {\n return existsSync(join(dir, 'package.json')) || existsSync(join(dir, 'package', 'package.json'));\n}\n\n/**\n * Read the version from a package.json file.\n * Checks both root and package/ subdirectory.\n * Returns the version string or 'local' if not found.\n */\nfunction readLocalVersion(pkgDir: string): string {\n for (const candidate of [join(pkgDir, 'package.json'), join(pkgDir, 'package', 'package.json')]) {\n try {\n const raw = readFileSync(candidate, 'utf-8');\n const manifest = JSON.parse(raw);\n return manifest.version ?? 'local';\n } catch {\n // try next candidate\n }\n }\n return 'local';\n}\n\n/**\n * Resolve FHIR packages into a project's packages directory.\n *\n * Resolution order for each package:\n * 1. Already exists in packagesPath \u2192 use as-is (source: 'local')\n * 2. Found in system cache (~/.fhir/packages) \u2192 create symlink/junction (source: 'cache')\n * 3. Download from FHIR Package Registry \u2192 cache \u2192 create symlink (source: 'download')\n *\n * @param config Engine configuration (uses config.igs and config.packages.path)\n * @param options Override packages list, target path, download policy, or logger\n * @returns Result with resolved packages and any errors\n *\n * @example\n * ```ts\n * const result = await resolvePackages(config);\n * if (!result.success) {\n * console.warn('Some packages failed:', result.errors);\n * }\n * ```\n */\nexport async function resolvePackages(\n config: FhirEngineConfig,\n options?: ResolvePackagesOptions,\n): Promise<ResolvePackagesResult> {\n const packagesPath = resolve(options?.packagesPath ?? config.packages.path);\n const igs = options?.packages ?? config.igs ?? [];\n const allowDownload = options?.allowDownload ?? config.packageResolve?.allowDownload ?? true;\n const logger: Logger | undefined = options?.logger ?? config.logger;\n\n const cache = new PackageCache();\n const client = new PackageRegistryClient();\n const results: ResolvedPackage[] = [];\n const errors: Array<{ name: string; error: string }> = [];\n\n ensureDirSync(packagesPath);\n\n for (const ig of igs) {\n try {\n // 1. Already exists locally?\n const localPath = join(packagesPath, ig.name);\n if (hasManifest(localPath)) {\n const localVersion = readLocalVersion(localPath);\n logger?.debug(`Package ${ig.name} already exists locally at ${localPath}`);\n results.push({ name: ig.name, version: localVersion, path: localPath, source: 'local' });\n continue;\n }\n\n // 2. Resolve version\n let version = ig.version ?? 'latest';\n if (version === 'latest') {\n if (!allowDownload) {\n errors.push({\n name: ig.name,\n error: `Cannot resolve \"latest\" version for ${ig.name} without network access`,\n });\n continue;\n }\n logger?.info(`Resolving latest version for ${ig.name}...`);\n version = await client.getLatestVersion(ig.name);\n logger?.info(`Latest version for ${ig.name}: ${version}`);\n }\n\n // 3. Check system cache\n const cachePath = cache.getPath(ig.name, version);\n if (cachePath) {\n // Cache hit \u2014 create symlink\n logger?.info(`Found ${ig.name}@${version} in system cache, linking...`);\n createLink(cachePath, localPath);\n results.push({ name: ig.name, version, path: localPath, source: 'cache' });\n continue;\n }\n\n // 4. Download\n if (!allowDownload) {\n errors.push({\n name: ig.name,\n error: `Package ${ig.name}@${version} not found in cache, and downloads are disabled`,\n });\n continue;\n }\n\n logger?.info(`Downloading ${ig.name}@${version} from registry...`);\n const tarball = await client.download(ig.name, version);\n cache.put(ig.name, version, tarball);\n logger?.info(`Downloaded and cached ${ig.name}@${version}`);\n\n // Create symlink from cache to project packages dir\n const newCachePath = cache.getPath(ig.name, version);\n if (!newCachePath) {\n errors.push({ name: ig.name, error: `Failed to locate cached package after download` });\n continue;\n }\n createLink(newCachePath, localPath);\n results.push({ name: ig.name, version, path: localPath, source: 'download' });\n } catch (err) {\n errors.push({\n name: ig.name,\n error: err instanceof Error ? err.message : String(err),\n });\n }\n }\n\n return {\n success: errors.length === 0,\n packages: results,\n errors,\n };\n}\n\n/**\n * Create a directory junction (Windows) or symlink (Unix) from target to linkPath.\n * Idempotent \u2014 if link already exists, does nothing.\n */\nfunction createLink(target: string, linkPath: string): void {\n if (existsSync(linkPath)) {\n // Already exists (either real dir or symlink) \u2014 skip\n try {\n const stat = lstatSync(linkPath);\n if (stat.isSymbolicLink() || stat.isDirectory()) {\n return;\n }\n } catch {\n // If stat fails, try to create anyway\n }\n }\n // Use 'junction' on Windows (no admin needed), 'dir' on Unix\n const linkType = process.platform === 'win32' ? 'junction' : 'dir';\n symlinkSync(target, linkPath, linkType);\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["// fhir-engine \u2014 public API\n\nexport { createFhirEngine } from './engine.js';\nexport { defineConfig, loadFhirConfig } from './config.js';\nexport { createConsoleLogger } from './logger.js';\nexport { createAdapter } from './adapter-factory.js';\nexport { resolvePackages } from './package-resolver.js';\n\nexport type {\n FhirEngine,\n FhirEngineConfig,\n FhirEnginePlugin,\n FhirEngineStatus,\n EngineContext,\n DatabaseConfig,\n SqliteDatabaseConfig,\n SqliteWasmDatabaseConfig,\n PostgresDatabaseConfig,\n PackagesConfig,\n Logger,\n ResolvePackagesOptions,\n ResolvedPackage,\n ResolvePackagesResult,\n} from './types.js';\n\n// Re-export key upstream types for convenience\nexport type { DefinitionRegistry, DefinitionProvider } from 'fhir-definition';\nexport type { FhirRuntimeInstance } from 'fhir-runtime';\nexport type { FhirPersistence, StorageAdapter } from 'fhir-persistence';\n\n// ---------------------------------------------------------------------------\n// Search utilities (from fhir-persistence)\n// ---------------------------------------------------------------------------\n\nexport { parseSearchRequest, executeSearch } from 'fhir-persistence';\nexport type { SearchRequest, SearchResult, SearchOptions } from 'fhir-persistence';\n\n// ---------------------------------------------------------------------------\n// FHIRPath evaluation (from fhir-runtime)\n// ---------------------------------------------------------------------------\n\nexport { evalFhirPath, evalFhirPathBoolean, evalFhirPathString, evalFhirPathTyped } from 'fhir-runtime';\n", "import { loadDefinitionPackages } from 'fhir-definition';\nimport { createRuntime, extractSearchValues, extractAllSearchValues, extractReferences } from 'fhir-runtime';\nimport { FhirDefinitionBridge, FhirRuntimeProvider, FhirSystem, parseSearchRequest, executeSearch } from 'fhir-persistence';\n\nimport { createAdapter } from './adapter-factory.js';\nimport { loadFhirConfig } from './config.js';\nimport { createConsoleLogger } from './logger.js';\nimport { resolvePackages } from './package-resolver.js';\nimport type { EngineContext, FhirEngine, FhirEngineConfig, FhirEnginePlugin, FhirEngineStatus } from './types.js';\n\n/**\n * Resolve the SQL dialect from the database config type.\n */\nfunction resolveDialect(type: FhirEngineConfig['database']['type']): 'sqlite' | 'postgres' {\n switch (type) {\n case 'sqlite':\n case 'sqlite-wasm':\n return 'sqlite';\n case 'postgres':\n return 'postgres';\n }\n}\n\n/**\n * Validate the engine configuration, throwing on missing required fields.\n */\nfunction validateConfig(config: FhirEngineConfig): void {\n if (!config.database) {\n throw new Error('fhir-engine: config.database is required');\n }\n if (!config.database.type) {\n throw new Error('fhir-engine: config.database.type is required (sqlite | sqlite-wasm | postgres)');\n }\n if (!config.packages) {\n throw new Error('fhir-engine: config.packages is required');\n }\n if (!config.packages.path) {\n throw new Error('fhir-engine: config.packages.path is required');\n }\n}\n\n/**\n * Run a lifecycle hook on all plugins in order.\n * Wraps errors with the plugin name for clear diagnostics.\n */\nasync function runPluginHook(\n plugins: FhirEnginePlugin[],\n hook: 'init' | 'start' | 'ready',\n ctx: EngineContext,\n): Promise<void> {\n for (const plugin of plugins) {\n const fn = plugin[hook];\n if (fn) {\n try {\n await fn.call(plugin, ctx);\n } catch (err) {\n throw new Error(\n `fhir-engine: plugin \"${plugin.name}\" failed during ${hook}: ${err instanceof Error ? err.message : String(err)}`,\n { cause: err },\n );\n }\n }\n }\n}\n\n/**\n * Create and bootstrap a fully initialized FHIR engine.\n *\n * This is the single entry point for all FHIR applications.\n * It assembles fhir-definition, fhir-runtime, and fhir-persistence\n * into a running system from a single configuration object.\n *\n * @example\n * ```ts\n * const engine = await createFhirEngine({\n * database: { type: 'sqlite', path: ':memory:' },\n * packages: { path: './fhir-packages' },\n * });\n *\n * const patient = await engine.persistence.createResource('Patient', {\n * resourceType: 'Patient',\n * name: [{ family: 'Smith', given: ['John'] }],\n * });\n *\n * await engine.stop();\n * ```\n */\nexport async function createFhirEngine(config?: FhirEngineConfig): Promise<FhirEngine> {\n // \u2500\u2500 0. Resolve config \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n if (!config) {\n config = await loadFhirConfig();\n }\n validateConfig(config);\n\n const logger = config.logger ?? createConsoleLogger();\n const plugins = config.plugins ?? [];\n logger.info('Initializing fhir-engine...');\n\n // \u2500\u2500 1a. Resolve packages (download/link if config.igs is set) \u2500\n if (config.igs && config.igs.length > 0) {\n logger.info(`Resolving ${config.igs.length} IG package(s)...`);\n const resolveResult = await resolvePackages(config, { logger });\n for (const pkg of resolveResult.packages) {\n logger.info(`Resolved ${pkg.name}@${pkg.version} (${pkg.source})`);\n }\n if (!resolveResult.success) {\n for (const err of resolveResult.errors) {\n logger.warn(`Failed to resolve package ${err.name}: ${err.error}`);\n }\n }\n }\n\n // \u2500\u2500 1b. Load FHIR definitions \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n logger.info(`Loading FHIR packages from: ${config.packages.path}`);\n const { registry, result } = loadDefinitionPackages(config.packages.path);\n logger.info(\n `Loaded ${result.packages.length} package(s): ${result.packages.map((p) => `${p.name}@${p.version}`).join(', ')}`,\n );\n\n // \u2500\u2500 2. Create fhir-runtime \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n logger.info('Creating fhir-runtime instance...');\n const runtime = await createRuntime({ definitions: registry, preloadCore: false });\n\n // \u2500\u2500 3. Build provider bridges \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n const definitionBridge = new FhirDefinitionBridge(registry);\n const runtimeProvider = new FhirRuntimeProvider({\n extractSearchValues,\n extractAllSearchValues,\n extractReferences,\n });\n\n // \u2500\u2500 4. Create storage adapter \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n const adapter = createAdapter(config.database, logger);\n\n // \u2500\u2500 5. Build EngineContext \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n const ctx: { -readonly [K in keyof EngineContext]: EngineContext[K] } = {\n config,\n definitions: registry,\n runtime,\n adapter,\n persistence: undefined,\n logger,\n };\n\n // \u2500\u2500 6. INIT phase \u2014 plugins run before persistence \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n if (plugins.length > 0) {\n logger.info(`Running init for ${plugins.length} plugin(s): ${plugins.map((p) => p.name).join(', ')}`);\n await runPluginHook(plugins, 'init', ctx);\n }\n\n // \u2500\u2500 7. Initialize FhirSystem \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n const dialect = resolveDialect(config.database.type);\n const system = new FhirSystem(adapter, {\n dialect,\n runtimeProvider,\n packageName: config.packageName ?? 'fhir-engine.default',\n packageVersion: config.packageVersion ?? '1.0.0',\n });\n\n logger.info('Initializing persistence system (schema + migration)...');\n const { persistence, sdRegistry, spRegistry, igResult, resourceTypes } =\n await system.initialize(definitionBridge);\n\n logger.info(`Persistence ready \u2014 IG action: ${igResult.action}, ${resourceTypes.length} resource type(s)`);\n\n // ctx.persistence now available\n ctx.persistence = persistence;\n\n // \u2500\u2500 8. START phase \u2014 plugins can access persistence \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n if (plugins.length > 0) {\n logger.info(`Running start for ${plugins.length} plugin(s)...`);\n await runPluginHook(plugins, 'start', ctx);\n }\n\n // \u2500\u2500 9. READY phase \u2014 system fully operational \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n if (plugins.length > 0) {\n logger.info(`Running ready for ${plugins.length} plugin(s)...`);\n await runPluginHook(plugins, 'ready', ctx);\n }\n\n // \u2500\u2500 10. Return FhirEngine \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n let stopped = false;\n const startedAt = new Date();\n const loadedPackages = result.packages.map((p) => `${p.name}@${p.version}`);\n const fhirVersions = [...new Set(\n result.packages\n .map((p) => {\n if (p.name.includes('.r4.')) return '4.0';\n if (p.name.includes('.r4b.')) return '4.3';\n if (p.name.includes('.r5.')) return '5.0';\n return undefined;\n })\n .filter(Boolean),\n )] as string[];\n\n const engine: FhirEngine = {\n definitions: registry,\n runtime,\n adapter,\n persistence,\n sdRegistry,\n spRegistry,\n igResult,\n resourceTypes,\n logger,\n context: ctx as EngineContext,\n\n async search(resourceType, queryParams, options) {\n const request = parseSearchRequest(resourceType, queryParams, spRegistry);\n return executeSearch(adapter, request, spRegistry, options);\n },\n\n status(): FhirEngineStatus {\n return {\n fhirVersions,\n loadedPackages,\n resourceTypes,\n databaseType: config.database.type,\n igAction: igResult.action,\n startedAt,\n plugins: plugins.map((p) => p.name),\n };\n },\n\n async stop() {\n if (stopped) return;\n stopped = true;\n logger.info('Stopping fhir-engine...');\n\n // Stop plugins in reverse registration order\n for (let i = plugins.length - 1; i >= 0; i--) {\n const plugin = plugins[i];\n if (plugin.stop) {\n try {\n await plugin.stop.call(plugin, ctx as EngineContext);\n } catch (err) {\n logger.error(\n `Plugin \"${plugin.name}\" failed during stop: ${err instanceof Error ? err.message : String(err)}`,\n );\n }\n }\n }\n\n await adapter.close();\n logger.info('fhir-engine stopped.');\n },\n };\n\n logger.info('fhir-engine ready.');\n return engine;\n}\n", "import { BetterSqlite3Adapter, PostgresAdapter } from 'fhir-persistence';\nimport type { StorageAdapter } from 'fhir-persistence';\nimport type { DatabaseConfig, Logger } from './types.js';\n\n/**\n * Create a StorageAdapter from the database configuration.\n *\n * Supported adapters:\n * - `sqlite` \u2192 BetterSqlite3Adapter (native, Node.js / Electron)\n * - `sqlite-wasm` \u2192 removed in fhir-persistence v0.3.0; use `sqlite` instead\n * - `postgres` \u2192 PostgresAdapter (pg connection pool)\n */\nexport function createAdapter(config: DatabaseConfig, logger: Logger): StorageAdapter {\n switch (config.type) {\n case 'sqlite': {\n logger.info(`Creating BetterSqlite3Adapter (path: ${config.path})`);\n return new BetterSqlite3Adapter({\n path: config.path,\n wal: config.wal ?? true,\n busyTimeout: config.busyTimeout ?? 5000,\n });\n }\n\n case 'sqlite-wasm': {\n throw new Error(\n 'fhir-engine: sqlite-wasm adapter was removed in fhir-persistence v0.3.0. ' +\n 'Use database.type = \"sqlite\" (BetterSqlite3Adapter) instead.',\n );\n }\n\n case 'postgres': {\n logger.info(`Creating PostgresAdapter (url: ${config.url.replace(/\\/\\/.*@/, '//*****@')})`);\n // Lazy-import pg to avoid hard dependency when using SQLite only\n let Pool: any;\n try {\n Pool = require('pg').Pool;\n } catch {\n throw new Error(\n 'fhir-engine: PostgreSQL requires the \"pg\" package. Install it with: npm install pg',\n );\n }\n const pool = new Pool({\n connectionString: config.url,\n max: config.max ?? 10,\n idleTimeoutMillis: config.idleTimeoutMillis ?? 30000,\n connectionTimeoutMillis: config.connectionTimeoutMillis ?? 0,\n });\n return new PostgresAdapter(pool);\n }\n\n default: {\n const _exhaustive: never = config;\n throw new Error(`fhir-engine: unknown database type: ${(_exhaustive as DatabaseConfig).type}`);\n }\n }\n}\n", "import { existsSync, readFileSync } from 'node:fs';\nimport { resolve, extname } from 'node:path';\nimport { pathToFileURL } from 'node:url';\nimport type { FhirEngineConfig, DatabaseConfig } from './types.js';\n\n// ---------------------------------------------------------------------------\n// defineConfig \u2014 typed identity helper for fhir.config.ts / .js\n// ---------------------------------------------------------------------------\n\n/**\n * Type-safe config helper for `fhir.config.ts` / `fhir.config.js`.\n *\n * @example\n * ```ts\n * // fhir.config.ts\n * import { defineConfig } from 'fhir-engine';\n *\n * export default defineConfig({\n * database: { type: 'sqlite', path: './fhir.db' },\n * packages: { path: './fhir-packages' },\n * });\n * ```\n */\nexport function defineConfig(config: FhirEngineConfig): FhirEngineConfig {\n return config;\n}\n\n// ---------------------------------------------------------------------------\n// Config file discovery order\n// ---------------------------------------------------------------------------\n\nconst CONFIG_FILENAMES = [\n 'fhir.config.ts',\n 'fhir.config.js',\n 'fhir.config.mjs',\n 'fhir.config.json',\n] as const;\n\n// ---------------------------------------------------------------------------\n// loadFhirConfig \u2014 auto-discover and load config\n// ---------------------------------------------------------------------------\n\n/**\n * Load engine configuration from a file.\n *\n * If `configPath` is provided, loads that exact file.\n * Otherwise, searches the current working directory for config files\n * in this order: `fhir.config.ts` \u2192 `fhir.config.js` \u2192 `fhir.config.mjs` \u2192 `fhir.config.json`.\n *\n * Environment variable overrides are applied on top of the loaded config.\n *\n * @param configPath - Explicit path to a config file (optional).\n * @returns The resolved `FhirEngineConfig`.\n */\nexport async function loadFhirConfig(configPath?: string): Promise<FhirEngineConfig> {\n let resolvedPath: string;\n\n if (configPath) {\n resolvedPath = resolve(configPath);\n if (!existsSync(resolvedPath)) {\n throw new Error(`fhir-engine: config file not found: ${resolvedPath}`);\n }\n } else {\n const cwd = process.cwd();\n const found = CONFIG_FILENAMES\n .map((name) => resolve(cwd, name))\n .find((p) => existsSync(p));\n if (!found) {\n throw new Error(\n `fhir-engine: no config file found in ${cwd}. ` +\n `Expected one of: ${CONFIG_FILENAMES.join(', ')}`,\n );\n }\n resolvedPath = found;\n }\n\n const config = await loadConfigFile(resolvedPath);\n return applyEnvOverrides(config);\n}\n\n// ---------------------------------------------------------------------------\n// File loaders\n// ---------------------------------------------------------------------------\n\nasync function loadConfigFile(filePath: string): Promise<FhirEngineConfig> {\n const ext = extname(filePath);\n\n if (ext === '.json') {\n return loadJsonConfig(filePath);\n }\n\n if (ext === '.ts' || ext === '.js' || ext === '.mjs') {\n return loadModuleConfig(filePath);\n }\n\n throw new Error(`fhir-engine: unsupported config file extension: ${ext}`);\n}\n\nfunction loadJsonConfig(filePath: string): FhirEngineConfig {\n try {\n const raw = readFileSync(filePath, 'utf-8');\n return JSON.parse(raw) as FhirEngineConfig;\n } catch (err) {\n throw new Error(\n `fhir-engine: failed to parse config file ${filePath}: ${err instanceof Error ? err.message : String(err)}`,\n { cause: err },\n );\n }\n}\n\nasync function loadModuleConfig(filePath: string): Promise<FhirEngineConfig> {\n try {\n const fileUrl = pathToFileURL(filePath).href;\n const mod = await import(fileUrl);\n const config = mod.default ?? mod;\n\n if (!config || typeof config !== 'object') {\n throw new Error('config file must export a FhirEngineConfig object as default export');\n }\n\n return config as FhirEngineConfig;\n } catch (err) {\n if (err instanceof Error && err.message.includes('must export')) {\n throw err;\n }\n throw new Error(\n `fhir-engine: failed to load config file ${filePath}: ${err instanceof Error ? err.message : String(err)}`,\n { cause: err },\n );\n }\n}\n\n// ---------------------------------------------------------------------------\n// Environment variable overrides\n// ---------------------------------------------------------------------------\n\nconst VALID_DB_TYPES = ['sqlite', 'sqlite-wasm', 'postgres'] as const;\n\n/**\n * Apply environment variable overrides on top of a loaded config.\n *\n * | Env Variable | Overrides |\n * |---------------------|----------------------------------|\n * | FHIR_DATABASE_TYPE | config.database.type |\n * | FHIR_DATABASE_URL | config.database.path / .url |\n * | FHIR_PACKAGES_PATH | config.packages.path |\n * | FHIR_LOG_LEVEL | (stored for logger filtering) |\n */\nexport function applyEnvOverrides(config: FhirEngineConfig): FhirEngineConfig {\n const result = structuredClone(config);\n\n const dbType = process.env.FHIR_DATABASE_TYPE;\n const dbUrl = process.env.FHIR_DATABASE_URL;\n const pkgPath = process.env.FHIR_PACKAGES_PATH;\n\n if (dbType) {\n if (!VALID_DB_TYPES.includes(dbType as typeof VALID_DB_TYPES[number])) {\n throw new Error(\n `fhir-engine: FHIR_DATABASE_TYPE must be one of: ${VALID_DB_TYPES.join(', ')}. Got: \"${dbType}\"`,\n );\n }\n // Rebuild database config with overridden type\n const validType = dbType as DatabaseConfig['type'];\n if (validType === 'postgres') {\n result.database = { type: 'postgres', url: (result.database as { url?: string }).url ?? '' };\n } else if (validType === 'sqlite-wasm') {\n result.database = { type: 'sqlite-wasm', path: (result.database as { path?: string }).path ?? '' };\n } else {\n result.database = { type: 'sqlite', path: (result.database as { path?: string }).path ?? '' };\n }\n }\n\n if (dbUrl) {\n const type = result.database?.type;\n if (type === 'postgres') {\n result.database = { ...result.database, type: 'postgres', url: dbUrl };\n } else if (type === 'sqlite-wasm') {\n result.database = { ...result.database, type: 'sqlite-wasm', path: dbUrl };\n } else {\n result.database = { ...result.database, type: 'sqlite', path: dbUrl };\n }\n }\n\n if (pkgPath) {\n result.packages = { ...result.packages, path: pkgPath };\n }\n\n return result;\n}\n", "import type { Logger } from './types.js';\n\n/**\n * Default console-based logger.\n */\nexport function createConsoleLogger(): Logger {\n return {\n debug: (message: string, ...args: unknown[]) => console.debug(`[fhir-engine] ${message}`, ...args),\n info: (message: string, ...args: unknown[]) => console.info(`[fhir-engine] ${message}`, ...args),\n warn: (message: string, ...args: unknown[]) => console.warn(`[fhir-engine] ${message}`, ...args),\n error: (message: string, ...args: unknown[]) => console.error(`[fhir-engine] ${message}`, ...args),\n };\n}\n", "import { resolve, join } from 'node:path';\nimport { existsSync, mkdirSync, symlinkSync, readFileSync, lstatSync, copyFileSync } from 'node:fs';\nimport { PackageCache, PackageRegistryClient } from 'fhir-definition';\n\nimport type { FhirEngineConfig, ResolvePackagesOptions, ResolvedPackage, ResolvePackagesResult, Logger } from './types.js';\n\n/**\n * Ensure the given directory exists (recursive mkdir).\n */\nfunction ensureDirSync(dir: string): void {\n if (!existsSync(dir)) {\n mkdirSync(dir, { recursive: true });\n }\n}\n\n/**\n * Check if a directory contains a FHIR package manifest.\n * Checks both root/package.json and package/package.json\n * (cached packages store content in a 'package' subdirectory).\n */\nfunction hasManifest(dir: string): boolean {\n return existsSync(join(dir, 'package.json')) || existsSync(join(dir, 'package', 'package.json'));\n}\n\n/**\n * Read the version from a package.json file.\n * Checks both root and package/ subdirectory.\n * Returns the version string or 'local' if not found.\n */\nfunction readLocalVersion(pkgDir: string): string {\n for (const candidate of [join(pkgDir, 'package.json'), join(pkgDir, 'package', 'package.json')]) {\n try {\n const raw = readFileSync(candidate, 'utf-8');\n const manifest = JSON.parse(raw);\n return manifest.version ?? 'local';\n } catch {\n // try next candidate\n }\n }\n return 'local';\n}\n\n/**\n * Resolve FHIR packages into a project's packages directory.\n *\n * Resolution order for each package:\n * 1. Already exists in packagesPath \u2192 use as-is (source: 'local')\n * 2. Found in system cache (~/.fhir/packages) \u2192 create symlink/junction (source: 'cache')\n * 3. Download from FHIR Package Registry \u2192 cache \u2192 create symlink (source: 'download')\n *\n * @param config Engine configuration (uses config.igs and config.packages.path)\n * @param options Override packages list, target path, download policy, or logger\n * @returns Result with resolved packages and any errors\n *\n * @example\n * ```ts\n * const result = await resolvePackages(config);\n * if (!result.success) {\n * console.warn('Some packages failed:', result.errors);\n * }\n * ```\n */\nexport async function resolvePackages(\n config: FhirEngineConfig,\n options?: ResolvePackagesOptions,\n): Promise<ResolvePackagesResult> {\n const packagesPath = resolve(options?.packagesPath ?? config.packages.path);\n const igs = options?.packages ?? config.igs ?? [];\n const allowDownload = options?.allowDownload ?? config.packageResolve?.allowDownload ?? true;\n const logger: Logger | undefined = options?.logger ?? config.logger;\n\n const cache = new PackageCache();\n const client = new PackageRegistryClient();\n const results: ResolvedPackage[] = [];\n const errors: Array<{ name: string; error: string }> = [];\n\n ensureDirSync(packagesPath);\n\n for (const ig of igs) {\n try {\n // 1. Already exists locally?\n const localPath = join(packagesPath, ig.name);\n if (hasManifest(localPath)) {\n const localVersion = readLocalVersion(localPath);\n logger?.debug(`Package ${ig.name} already exists locally at ${localPath}`);\n results.push({ name: ig.name, version: localVersion, path: localPath, source: 'local' });\n continue;\n }\n\n // 2. Resolve version\n let version = ig.version ?? 'latest';\n if (version === 'latest') {\n if (!allowDownload) {\n errors.push({\n name: ig.name,\n error: `Cannot resolve \"latest\" version for ${ig.name} without network access`,\n });\n continue;\n }\n logger?.info(`Resolving latest version for ${ig.name}...`);\n version = await client.getLatestVersion(ig.name);\n logger?.info(`Latest version for ${ig.name}: ${version}`);\n }\n\n // 3. Check system cache\n const cachePath = cache.getPath(ig.name, version);\n if (cachePath) {\n // Cache hit \u2014 create symlink\n logger?.info(`Found ${ig.name}@${version} in system cache, linking...`);\n ensureCacheRootManifest(cachePath);\n createLink(cachePath, localPath);\n results.push({ name: ig.name, version, path: localPath, source: 'cache' });\n continue;\n }\n\n // 4. Download\n if (!allowDownload) {\n errors.push({\n name: ig.name,\n error: `Package ${ig.name}@${version} not found in cache, and downloads are disabled`,\n });\n continue;\n }\n\n logger?.info(`Downloading ${ig.name}@${version} from registry...`);\n const tarball = await client.download(ig.name, version);\n cache.put(ig.name, version, tarball);\n logger?.info(`Downloaded and cached ${ig.name}@${version}`);\n\n // Create symlink from cache to project packages dir\n const newCachePath = cache.getPath(ig.name, version);\n if (!newCachePath) {\n errors.push({ name: ig.name, error: `Failed to locate cached package after download` });\n continue;\n }\n ensureCacheRootManifest(newCachePath);\n createLink(newCachePath, localPath);\n results.push({ name: ig.name, version, path: localPath, source: 'download' });\n } catch (err) {\n errors.push({\n name: ig.name,\n error: err instanceof Error ? err.message : String(err),\n });\n }\n }\n\n return {\n success: errors.length === 0,\n packages: results,\n errors,\n };\n}\n\n/**\n * Ensure the cache root directory has a package.json manifest.\n * Some tools (e.g. Firely Terminal) only place package.json inside the\n * package/ subdirectory. Without a root manifest, PackageScanner discovers\n * the package at the wrong depth, causing PackageLoader to construct a\n * double-nested \"package/package\" path that doesn't exist (\u2192 0 resources).\n */\nfunction ensureCacheRootManifest(cachePath: string): void {\n const rootManifest = join(cachePath, 'package.json');\n const nestedManifest = join(cachePath, 'package', 'package.json');\n if (!existsSync(rootManifest) && existsSync(nestedManifest)) {\n copyFileSync(nestedManifest, rootManifest);\n }\n}\n\n/**\n * Create a directory junction (Windows) or symlink (Unix) from target to linkPath.\n * Idempotent \u2014 if link already exists, does nothing.\n */\nfunction createLink(target: string, linkPath: string): void {\n if (existsSync(linkPath)) {\n // Already exists (either real dir or symlink) \u2014 skip\n try {\n const stat = lstatSync(linkPath);\n if (stat.isSymbolicLink() || stat.isDirectory()) {\n return;\n }\n } catch {\n // If stat fails, try to create anyway\n }\n }\n // Use 'junction' on Windows (no admin needed), 'dir' on Unix\n const linkType = process.platform === 'win32' ? 'junction' : 'dir';\n symlinkSync(target, linkPath, linkType);\n}\n"],
5
+ "mappings": "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",
6
6
  "names": ["import_fhir_definition", "import_fhir_persistence", "import_node_path", "import_node_fs", "import_fhir_persistence", "import_fhir_runtime"]
7
7
  }
@@ -21,8 +21,8 @@ import type { StructureDefinitionRegistry } from 'fhir-persistence';
21
21
  *
22
22
  * Supported adapters:
23
23
  * - `sqlite` → BetterSqlite3Adapter (native, Node.js / Electron)
24
- * - `sqlite-wasm` → SQLiteAdapter (sql.js WASM, browser / cross-platform)
25
- * - `postgres` → not yet available (PostgresAdapter not exported from fhir-persistence)
24
+ * - `sqlite-wasm` → removed in fhir-persistence v0.3.0; use `sqlite` instead
25
+ * - `postgres` → PostgresAdapter (pg connection pool)
26
26
  */
27
27
  export declare function createAdapter(config: DatabaseConfig, logger: Logger): StorageAdapter;
28
28
 
@@ -226,8 +226,14 @@ export { parseSearchRequest }
226
226
 
227
227
  export declare interface PostgresDatabaseConfig {
228
228
  type: 'postgres';
229
- /** PostgreSQL connection string. */
229
+ /** PostgreSQL connection string (e.g. 'postgresql://user:pass@localhost:5432/fhir_db'). */
230
230
  url: string;
231
+ /** Maximum number of clients in the pool (default: 10). */
232
+ max?: number;
233
+ /** Idle timeout in milliseconds before a client is closed (default: 30000). */
234
+ idleTimeoutMillis?: number;
235
+ /** Connection timeout in milliseconds (default: 0 = no timeout). */
236
+ connectionTimeoutMillis?: number;
231
237
  }
232
238
 
233
239
  export declare interface ResolvedPackage {
@@ -21,8 +21,8 @@ import type { StructureDefinitionRegistry } from 'fhir-persistence';
21
21
  *
22
22
  * Supported adapters:
23
23
  * - `sqlite` → BetterSqlite3Adapter (native, Node.js / Electron)
24
- * - `sqlite-wasm` → SQLiteAdapter (sql.js WASM, browser / cross-platform)
25
- * - `postgres` → not yet available (PostgresAdapter not exported from fhir-persistence)
24
+ * - `sqlite-wasm` → removed in fhir-persistence v0.3.0; use `sqlite` instead
25
+ * - `postgres` → PostgresAdapter (pg connection pool)
26
26
  */
27
27
  export declare function createAdapter(config: DatabaseConfig, logger: Logger): StorageAdapter;
28
28
 
@@ -226,8 +226,14 @@ export { parseSearchRequest }
226
226
 
227
227
  export declare interface PostgresDatabaseConfig {
228
228
  type: 'postgres';
229
- /** PostgreSQL connection string. */
229
+ /** PostgreSQL connection string (e.g. 'postgresql://user:pass@localhost:5432/fhir_db'). */
230
230
  url: string;
231
+ /** Maximum number of clients in the pool (default: 10). */
232
+ max?: number;
233
+ /** Idle timeout in milliseconds before a client is closed (default: 30000). */
234
+ idleTimeoutMillis?: number;
235
+ /** Connection timeout in milliseconds (default: 0 = no timeout). */
236
+ connectionTimeoutMillis?: number;
231
237
  }
232
238
 
233
239
  export declare interface ResolvedPackage {
@@ -1,10 +1,17 @@
1
+ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
2
+ get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
3
+ }) : x)(function(x) {
4
+ if (typeof require !== "undefined") return require.apply(this, arguments);
5
+ throw Error('Dynamic require of "' + x + '" is not supported');
6
+ });
7
+
1
8
  // src/engine.ts
2
9
  import { loadDefinitionPackages } from "fhir-definition";
3
10
  import { createRuntime, extractSearchValues, extractAllSearchValues, extractReferences } from "fhir-runtime";
4
11
  import { FhirDefinitionBridge, FhirRuntimeProvider, FhirSystem, parseSearchRequest, executeSearch } from "fhir-persistence";
5
12
 
6
13
  // src/adapter-factory.ts
7
- import { BetterSqlite3Adapter, SQLiteAdapter } from "fhir-persistence";
14
+ import { BetterSqlite3Adapter, PostgresAdapter } from "fhir-persistence";
8
15
  function createAdapter(config, logger) {
9
16
  switch (config.type) {
10
17
  case "sqlite": {
@@ -16,14 +23,28 @@ function createAdapter(config, logger) {
16
23
  });
17
24
  }
18
25
  case "sqlite-wasm": {
19
- logger.info(`Creating SQLiteAdapter (WASM, path: ${config.path})`);
20
- return new SQLiteAdapter(config.path);
21
- }
22
- case "postgres": {
23
26
  throw new Error(
24
- 'fhir-engine: PostgreSQL adapter is not yet available. PostgresAdapter is not exported from fhir-persistence v0.1.0. Use database.type = "sqlite" for now.'
27
+ 'fhir-engine: sqlite-wasm adapter was removed in fhir-persistence v0.3.0. Use database.type = "sqlite" (BetterSqlite3Adapter) instead.'
25
28
  );
26
29
  }
30
+ case "postgres": {
31
+ logger.info(`Creating PostgresAdapter (url: ${config.url.replace(/\/\/.*@/, "//*****@")})`);
32
+ let Pool;
33
+ try {
34
+ Pool = __require("pg").Pool;
35
+ } catch {
36
+ throw new Error(
37
+ 'fhir-engine: PostgreSQL requires the "pg" package. Install it with: npm install pg'
38
+ );
39
+ }
40
+ const pool = new Pool({
41
+ connectionString: config.url,
42
+ max: config.max ?? 10,
43
+ idleTimeoutMillis: config.idleTimeoutMillis ?? 3e4,
44
+ connectionTimeoutMillis: config.connectionTimeoutMillis ?? 0
45
+ });
46
+ return new PostgresAdapter(pool);
47
+ }
27
48
  default: {
28
49
  const _exhaustive = config;
29
50
  throw new Error(`fhir-engine: unknown database type: ${_exhaustive.type}`);
@@ -153,7 +174,7 @@ function createConsoleLogger() {
153
174
 
154
175
  // src/package-resolver.ts
155
176
  import { resolve as resolve2, join } from "node:path";
156
- import { existsSync as existsSync2, mkdirSync, symlinkSync, readFileSync as readFileSync2, lstatSync } from "node:fs";
177
+ import { existsSync as existsSync2, mkdirSync, symlinkSync, readFileSync as readFileSync2, lstatSync, copyFileSync } from "node:fs";
157
178
  import { PackageCache, PackageRegistryClient } from "fhir-definition";
158
179
  function ensureDirSync(dir) {
159
180
  if (!existsSync2(dir)) {
@@ -209,6 +230,7 @@ async function resolvePackages(config, options) {
209
230
  const cachePath = cache.getPath(ig.name, version);
210
231
  if (cachePath) {
211
232
  logger?.info(`Found ${ig.name}@${version} in system cache, linking...`);
233
+ ensureCacheRootManifest(cachePath);
212
234
  createLink(cachePath, localPath);
213
235
  results.push({ name: ig.name, version, path: localPath, source: "cache" });
214
236
  continue;
@@ -229,6 +251,7 @@ async function resolvePackages(config, options) {
229
251
  errors.push({ name: ig.name, error: `Failed to locate cached package after download` });
230
252
  continue;
231
253
  }
254
+ ensureCacheRootManifest(newCachePath);
232
255
  createLink(newCachePath, localPath);
233
256
  results.push({ name: ig.name, version, path: localPath, source: "download" });
234
257
  } catch (err) {
@@ -244,6 +267,13 @@ async function resolvePackages(config, options) {
244
267
  errors
245
268
  };
246
269
  }
270
+ function ensureCacheRootManifest(cachePath) {
271
+ const rootManifest = join(cachePath, "package.json");
272
+ const nestedManifest = join(cachePath, "package", "package.json");
273
+ if (!existsSync2(rootManifest) && existsSync2(nestedManifest)) {
274
+ copyFileSync(nestedManifest, rootManifest);
275
+ }
276
+ }
247
277
  function createLink(target, linkPath) {
248
278
  if (existsSync2(linkPath)) {
249
279
  try {
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/engine.ts", "../../src/adapter-factory.ts", "../../src/config.ts", "../../src/logger.ts", "../../src/package-resolver.ts", "../../src/index.ts"],
4
- "sourcesContent": ["import { loadDefinitionPackages } from 'fhir-definition';\nimport { createRuntime, extractSearchValues, extractAllSearchValues, extractReferences } from 'fhir-runtime';\nimport { FhirDefinitionBridge, FhirRuntimeProvider, FhirSystem, parseSearchRequest, executeSearch } from 'fhir-persistence';\n\nimport { createAdapter } from './adapter-factory.js';\nimport { loadFhirConfig } from './config.js';\nimport { createConsoleLogger } from './logger.js';\nimport { resolvePackages } from './package-resolver.js';\nimport type { EngineContext, FhirEngine, FhirEngineConfig, FhirEnginePlugin, FhirEngineStatus } from './types.js';\n\n/**\n * Resolve the SQL dialect from the database config type.\n */\nfunction resolveDialect(type: FhirEngineConfig['database']['type']): 'sqlite' | 'postgres' {\n switch (type) {\n case 'sqlite':\n case 'sqlite-wasm':\n return 'sqlite';\n case 'postgres':\n return 'postgres';\n }\n}\n\n/**\n * Validate the engine configuration, throwing on missing required fields.\n */\nfunction validateConfig(config: FhirEngineConfig): void {\n if (!config.database) {\n throw new Error('fhir-engine: config.database is required');\n }\n if (!config.database.type) {\n throw new Error('fhir-engine: config.database.type is required (sqlite | sqlite-wasm | postgres)');\n }\n if (!config.packages) {\n throw new Error('fhir-engine: config.packages is required');\n }\n if (!config.packages.path) {\n throw new Error('fhir-engine: config.packages.path is required');\n }\n}\n\n/**\n * Run a lifecycle hook on all plugins in order.\n * Wraps errors with the plugin name for clear diagnostics.\n */\nasync function runPluginHook(\n plugins: FhirEnginePlugin[],\n hook: 'init' | 'start' | 'ready',\n ctx: EngineContext,\n): Promise<void> {\n for (const plugin of plugins) {\n const fn = plugin[hook];\n if (fn) {\n try {\n await fn.call(plugin, ctx);\n } catch (err) {\n throw new Error(\n `fhir-engine: plugin \"${plugin.name}\" failed during ${hook}: ${err instanceof Error ? err.message : String(err)}`,\n { cause: err },\n );\n }\n }\n }\n}\n\n/**\n * Create and bootstrap a fully initialized FHIR engine.\n *\n * This is the single entry point for all FHIR applications.\n * It assembles fhir-definition, fhir-runtime, and fhir-persistence\n * into a running system from a single configuration object.\n *\n * @example\n * ```ts\n * const engine = await createFhirEngine({\n * database: { type: 'sqlite', path: ':memory:' },\n * packages: { path: './fhir-packages' },\n * });\n *\n * const patient = await engine.persistence.createResource('Patient', {\n * resourceType: 'Patient',\n * name: [{ family: 'Smith', given: ['John'] }],\n * });\n *\n * await engine.stop();\n * ```\n */\nexport async function createFhirEngine(config?: FhirEngineConfig): Promise<FhirEngine> {\n // \u2500\u2500 0. Resolve config \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n if (!config) {\n config = await loadFhirConfig();\n }\n validateConfig(config);\n\n const logger = config.logger ?? createConsoleLogger();\n const plugins = config.plugins ?? [];\n logger.info('Initializing fhir-engine...');\n\n // \u2500\u2500 1a. Resolve packages (download/link if config.igs is set) \u2500\n if (config.igs && config.igs.length > 0) {\n logger.info(`Resolving ${config.igs.length} IG package(s)...`);\n const resolveResult = await resolvePackages(config, { logger });\n for (const pkg of resolveResult.packages) {\n logger.info(`Resolved ${pkg.name}@${pkg.version} (${pkg.source})`);\n }\n if (!resolveResult.success) {\n for (const err of resolveResult.errors) {\n logger.warn(`Failed to resolve package ${err.name}: ${err.error}`);\n }\n }\n }\n\n // \u2500\u2500 1b. Load FHIR definitions \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n logger.info(`Loading FHIR packages from: ${config.packages.path}`);\n const { registry, result } = loadDefinitionPackages(config.packages.path);\n logger.info(\n `Loaded ${result.packages.length} package(s): ${result.packages.map((p) => `${p.name}@${p.version}`).join(', ')}`,\n );\n\n // \u2500\u2500 2. Create fhir-runtime \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n logger.info('Creating fhir-runtime instance...');\n const runtime = await createRuntime({ definitions: registry, preloadCore: false });\n\n // \u2500\u2500 3. Build provider bridges \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n const definitionBridge = new FhirDefinitionBridge(registry);\n const runtimeProvider = new FhirRuntimeProvider({\n extractSearchValues,\n extractAllSearchValues,\n extractReferences,\n });\n\n // \u2500\u2500 4. Create storage adapter \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n const adapter = createAdapter(config.database, logger);\n\n // \u2500\u2500 5. Build EngineContext \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n const ctx: { -readonly [K in keyof EngineContext]: EngineContext[K] } = {\n config,\n definitions: registry,\n runtime,\n adapter,\n persistence: undefined,\n logger,\n };\n\n // \u2500\u2500 6. INIT phase \u2014 plugins run before persistence \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n if (plugins.length > 0) {\n logger.info(`Running init for ${plugins.length} plugin(s): ${plugins.map((p) => p.name).join(', ')}`);\n await runPluginHook(plugins, 'init', ctx);\n }\n\n // \u2500\u2500 7. Initialize FhirSystem \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n const dialect = resolveDialect(config.database.type);\n const system = new FhirSystem(adapter, {\n dialect,\n runtimeProvider,\n packageName: config.packageName ?? 'fhir-engine.default',\n packageVersion: config.packageVersion ?? '1.0.0',\n });\n\n logger.info('Initializing persistence system (schema + migration)...');\n const { persistence, sdRegistry, spRegistry, igResult, resourceTypes } =\n await system.initialize(definitionBridge);\n\n logger.info(`Persistence ready \u2014 IG action: ${igResult.action}, ${resourceTypes.length} resource type(s)`);\n\n // ctx.persistence now available\n ctx.persistence = persistence;\n\n // \u2500\u2500 8. START phase \u2014 plugins can access persistence \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n if (plugins.length > 0) {\n logger.info(`Running start for ${plugins.length} plugin(s)...`);\n await runPluginHook(plugins, 'start', ctx);\n }\n\n // \u2500\u2500 9. READY phase \u2014 system fully operational \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n if (plugins.length > 0) {\n logger.info(`Running ready for ${plugins.length} plugin(s)...`);\n await runPluginHook(plugins, 'ready', ctx);\n }\n\n // \u2500\u2500 10. Return FhirEngine \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n let stopped = false;\n const startedAt = new Date();\n const loadedPackages = result.packages.map((p) => `${p.name}@${p.version}`);\n const fhirVersions = [...new Set(\n result.packages\n .map((p) => {\n if (p.name.includes('.r4.')) return '4.0';\n if (p.name.includes('.r4b.')) return '4.3';\n if (p.name.includes('.r5.')) return '5.0';\n return undefined;\n })\n .filter(Boolean),\n )] as string[];\n\n const engine: FhirEngine = {\n definitions: registry,\n runtime,\n adapter,\n persistence,\n sdRegistry,\n spRegistry,\n igResult,\n resourceTypes,\n logger,\n context: ctx as EngineContext,\n\n async search(resourceType, queryParams, options) {\n const request = parseSearchRequest(resourceType, queryParams, spRegistry);\n return executeSearch(adapter, request, spRegistry, options);\n },\n\n status(): FhirEngineStatus {\n return {\n fhirVersions,\n loadedPackages,\n resourceTypes,\n databaseType: config.database.type,\n igAction: igResult.action,\n startedAt,\n plugins: plugins.map((p) => p.name),\n };\n },\n\n async stop() {\n if (stopped) return;\n stopped = true;\n logger.info('Stopping fhir-engine...');\n\n // Stop plugins in reverse registration order\n for (let i = plugins.length - 1; i >= 0; i--) {\n const plugin = plugins[i];\n if (plugin.stop) {\n try {\n await plugin.stop.call(plugin, ctx as EngineContext);\n } catch (err) {\n logger.error(\n `Plugin \"${plugin.name}\" failed during stop: ${err instanceof Error ? err.message : String(err)}`,\n );\n }\n }\n }\n\n await adapter.close();\n logger.info('fhir-engine stopped.');\n },\n };\n\n logger.info('fhir-engine ready.');\n return engine;\n}\n", "import { BetterSqlite3Adapter, SQLiteAdapter } from 'fhir-persistence';\nimport type { StorageAdapter } from 'fhir-persistence';\nimport type { DatabaseConfig, Logger } from './types.js';\n\n/**\n * Create a StorageAdapter from the database configuration.\n *\n * Supported adapters:\n * - `sqlite` \u2192 BetterSqlite3Adapter (native, Node.js / Electron)\n * - `sqlite-wasm` \u2192 SQLiteAdapter (sql.js WASM, browser / cross-platform)\n * - `postgres` \u2192 not yet available (PostgresAdapter not exported from fhir-persistence)\n */\nexport function createAdapter(config: DatabaseConfig, logger: Logger): StorageAdapter {\n switch (config.type) {\n case 'sqlite': {\n logger.info(`Creating BetterSqlite3Adapter (path: ${config.path})`);\n return new BetterSqlite3Adapter({\n path: config.path,\n wal: config.wal ?? true,\n busyTimeout: config.busyTimeout ?? 5000,\n });\n }\n\n case 'sqlite-wasm': {\n logger.info(`Creating SQLiteAdapter (WASM, path: ${config.path})`);\n return new SQLiteAdapter(config.path);\n }\n\n case 'postgres': {\n throw new Error(\n 'fhir-engine: PostgreSQL adapter is not yet available. ' +\n 'PostgresAdapter is not exported from fhir-persistence v0.1.0. ' +\n 'Use database.type = \"sqlite\" for now.',\n );\n }\n\n default: {\n const _exhaustive: never = config;\n throw new Error(`fhir-engine: unknown database type: ${(_exhaustive as DatabaseConfig).type}`);\n }\n }\n}\n", "import { existsSync, readFileSync } from 'node:fs';\nimport { resolve, extname } from 'node:path';\nimport { pathToFileURL } from 'node:url';\nimport type { FhirEngineConfig, DatabaseConfig } from './types.js';\n\n// ---------------------------------------------------------------------------\n// defineConfig \u2014 typed identity helper for fhir.config.ts / .js\n// ---------------------------------------------------------------------------\n\n/**\n * Type-safe config helper for `fhir.config.ts` / `fhir.config.js`.\n *\n * @example\n * ```ts\n * // fhir.config.ts\n * import { defineConfig } from 'fhir-engine';\n *\n * export default defineConfig({\n * database: { type: 'sqlite', path: './fhir.db' },\n * packages: { path: './fhir-packages' },\n * });\n * ```\n */\nexport function defineConfig(config: FhirEngineConfig): FhirEngineConfig {\n return config;\n}\n\n// ---------------------------------------------------------------------------\n// Config file discovery order\n// ---------------------------------------------------------------------------\n\nconst CONFIG_FILENAMES = [\n 'fhir.config.ts',\n 'fhir.config.js',\n 'fhir.config.mjs',\n 'fhir.config.json',\n] as const;\n\n// ---------------------------------------------------------------------------\n// loadFhirConfig \u2014 auto-discover and load config\n// ---------------------------------------------------------------------------\n\n/**\n * Load engine configuration from a file.\n *\n * If `configPath` is provided, loads that exact file.\n * Otherwise, searches the current working directory for config files\n * in this order: `fhir.config.ts` \u2192 `fhir.config.js` \u2192 `fhir.config.mjs` \u2192 `fhir.config.json`.\n *\n * Environment variable overrides are applied on top of the loaded config.\n *\n * @param configPath - Explicit path to a config file (optional).\n * @returns The resolved `FhirEngineConfig`.\n */\nexport async function loadFhirConfig(configPath?: string): Promise<FhirEngineConfig> {\n let resolvedPath: string;\n\n if (configPath) {\n resolvedPath = resolve(configPath);\n if (!existsSync(resolvedPath)) {\n throw new Error(`fhir-engine: config file not found: ${resolvedPath}`);\n }\n } else {\n const cwd = process.cwd();\n const found = CONFIG_FILENAMES\n .map((name) => resolve(cwd, name))\n .find((p) => existsSync(p));\n if (!found) {\n throw new Error(\n `fhir-engine: no config file found in ${cwd}. ` +\n `Expected one of: ${CONFIG_FILENAMES.join(', ')}`,\n );\n }\n resolvedPath = found;\n }\n\n const config = await loadConfigFile(resolvedPath);\n return applyEnvOverrides(config);\n}\n\n// ---------------------------------------------------------------------------\n// File loaders\n// ---------------------------------------------------------------------------\n\nasync function loadConfigFile(filePath: string): Promise<FhirEngineConfig> {\n const ext = extname(filePath);\n\n if (ext === '.json') {\n return loadJsonConfig(filePath);\n }\n\n if (ext === '.ts' || ext === '.js' || ext === '.mjs') {\n return loadModuleConfig(filePath);\n }\n\n throw new Error(`fhir-engine: unsupported config file extension: ${ext}`);\n}\n\nfunction loadJsonConfig(filePath: string): FhirEngineConfig {\n try {\n const raw = readFileSync(filePath, 'utf-8');\n return JSON.parse(raw) as FhirEngineConfig;\n } catch (err) {\n throw new Error(\n `fhir-engine: failed to parse config file ${filePath}: ${err instanceof Error ? err.message : String(err)}`,\n { cause: err },\n );\n }\n}\n\nasync function loadModuleConfig(filePath: string): Promise<FhirEngineConfig> {\n try {\n const fileUrl = pathToFileURL(filePath).href;\n const mod = await import(fileUrl);\n const config = mod.default ?? mod;\n\n if (!config || typeof config !== 'object') {\n throw new Error('config file must export a FhirEngineConfig object as default export');\n }\n\n return config as FhirEngineConfig;\n } catch (err) {\n if (err instanceof Error && err.message.includes('must export')) {\n throw err;\n }\n throw new Error(\n `fhir-engine: failed to load config file ${filePath}: ${err instanceof Error ? err.message : String(err)}`,\n { cause: err },\n );\n }\n}\n\n// ---------------------------------------------------------------------------\n// Environment variable overrides\n// ---------------------------------------------------------------------------\n\nconst VALID_DB_TYPES = ['sqlite', 'sqlite-wasm', 'postgres'] as const;\n\n/**\n * Apply environment variable overrides on top of a loaded config.\n *\n * | Env Variable | Overrides |\n * |---------------------|----------------------------------|\n * | FHIR_DATABASE_TYPE | config.database.type |\n * | FHIR_DATABASE_URL | config.database.path / .url |\n * | FHIR_PACKAGES_PATH | config.packages.path |\n * | FHIR_LOG_LEVEL | (stored for logger filtering) |\n */\nexport function applyEnvOverrides(config: FhirEngineConfig): FhirEngineConfig {\n const result = structuredClone(config);\n\n const dbType = process.env.FHIR_DATABASE_TYPE;\n const dbUrl = process.env.FHIR_DATABASE_URL;\n const pkgPath = process.env.FHIR_PACKAGES_PATH;\n\n if (dbType) {\n if (!VALID_DB_TYPES.includes(dbType as typeof VALID_DB_TYPES[number])) {\n throw new Error(\n `fhir-engine: FHIR_DATABASE_TYPE must be one of: ${VALID_DB_TYPES.join(', ')}. Got: \"${dbType}\"`,\n );\n }\n // Rebuild database config with overridden type\n const validType = dbType as DatabaseConfig['type'];\n if (validType === 'postgres') {\n result.database = { type: 'postgres', url: (result.database as { url?: string }).url ?? '' };\n } else if (validType === 'sqlite-wasm') {\n result.database = { type: 'sqlite-wasm', path: (result.database as { path?: string }).path ?? '' };\n } else {\n result.database = { type: 'sqlite', path: (result.database as { path?: string }).path ?? '' };\n }\n }\n\n if (dbUrl) {\n const type = result.database?.type;\n if (type === 'postgres') {\n result.database = { ...result.database, type: 'postgres', url: dbUrl };\n } else if (type === 'sqlite-wasm') {\n result.database = { ...result.database, type: 'sqlite-wasm', path: dbUrl };\n } else {\n result.database = { ...result.database, type: 'sqlite', path: dbUrl };\n }\n }\n\n if (pkgPath) {\n result.packages = { ...result.packages, path: pkgPath };\n }\n\n return result;\n}\n", "import type { Logger } from './types.js';\n\n/**\n * Default console-based logger.\n */\nexport function createConsoleLogger(): Logger {\n return {\n debug: (message: string, ...args: unknown[]) => console.debug(`[fhir-engine] ${message}`, ...args),\n info: (message: string, ...args: unknown[]) => console.info(`[fhir-engine] ${message}`, ...args),\n warn: (message: string, ...args: unknown[]) => console.warn(`[fhir-engine] ${message}`, ...args),\n error: (message: string, ...args: unknown[]) => console.error(`[fhir-engine] ${message}`, ...args),\n };\n}\n", "import { resolve, join } from 'node:path';\nimport { existsSync, mkdirSync, symlinkSync, readFileSync, lstatSync } from 'node:fs';\nimport { PackageCache, PackageRegistryClient } from 'fhir-definition';\n\nimport type { FhirEngineConfig, ResolvePackagesOptions, ResolvedPackage, ResolvePackagesResult, Logger } from './types.js';\n\n/**\n * Ensure the given directory exists (recursive mkdir).\n */\nfunction ensureDirSync(dir: string): void {\n if (!existsSync(dir)) {\n mkdirSync(dir, { recursive: true });\n }\n}\n\n/**\n * Check if a directory contains a FHIR package manifest.\n * Checks both root/package.json and package/package.json\n * (cached packages store content in a 'package' subdirectory).\n */\nfunction hasManifest(dir: string): boolean {\n return existsSync(join(dir, 'package.json')) || existsSync(join(dir, 'package', 'package.json'));\n}\n\n/**\n * Read the version from a package.json file.\n * Checks both root and package/ subdirectory.\n * Returns the version string or 'local' if not found.\n */\nfunction readLocalVersion(pkgDir: string): string {\n for (const candidate of [join(pkgDir, 'package.json'), join(pkgDir, 'package', 'package.json')]) {\n try {\n const raw = readFileSync(candidate, 'utf-8');\n const manifest = JSON.parse(raw);\n return manifest.version ?? 'local';\n } catch {\n // try next candidate\n }\n }\n return 'local';\n}\n\n/**\n * Resolve FHIR packages into a project's packages directory.\n *\n * Resolution order for each package:\n * 1. Already exists in packagesPath \u2192 use as-is (source: 'local')\n * 2. Found in system cache (~/.fhir/packages) \u2192 create symlink/junction (source: 'cache')\n * 3. Download from FHIR Package Registry \u2192 cache \u2192 create symlink (source: 'download')\n *\n * @param config Engine configuration (uses config.igs and config.packages.path)\n * @param options Override packages list, target path, download policy, or logger\n * @returns Result with resolved packages and any errors\n *\n * @example\n * ```ts\n * const result = await resolvePackages(config);\n * if (!result.success) {\n * console.warn('Some packages failed:', result.errors);\n * }\n * ```\n */\nexport async function resolvePackages(\n config: FhirEngineConfig,\n options?: ResolvePackagesOptions,\n): Promise<ResolvePackagesResult> {\n const packagesPath = resolve(options?.packagesPath ?? config.packages.path);\n const igs = options?.packages ?? config.igs ?? [];\n const allowDownload = options?.allowDownload ?? config.packageResolve?.allowDownload ?? true;\n const logger: Logger | undefined = options?.logger ?? config.logger;\n\n const cache = new PackageCache();\n const client = new PackageRegistryClient();\n const results: ResolvedPackage[] = [];\n const errors: Array<{ name: string; error: string }> = [];\n\n ensureDirSync(packagesPath);\n\n for (const ig of igs) {\n try {\n // 1. Already exists locally?\n const localPath = join(packagesPath, ig.name);\n if (hasManifest(localPath)) {\n const localVersion = readLocalVersion(localPath);\n logger?.debug(`Package ${ig.name} already exists locally at ${localPath}`);\n results.push({ name: ig.name, version: localVersion, path: localPath, source: 'local' });\n continue;\n }\n\n // 2. Resolve version\n let version = ig.version ?? 'latest';\n if (version === 'latest') {\n if (!allowDownload) {\n errors.push({\n name: ig.name,\n error: `Cannot resolve \"latest\" version for ${ig.name} without network access`,\n });\n continue;\n }\n logger?.info(`Resolving latest version for ${ig.name}...`);\n version = await client.getLatestVersion(ig.name);\n logger?.info(`Latest version for ${ig.name}: ${version}`);\n }\n\n // 3. Check system cache\n const cachePath = cache.getPath(ig.name, version);\n if (cachePath) {\n // Cache hit \u2014 create symlink\n logger?.info(`Found ${ig.name}@${version} in system cache, linking...`);\n createLink(cachePath, localPath);\n results.push({ name: ig.name, version, path: localPath, source: 'cache' });\n continue;\n }\n\n // 4. Download\n if (!allowDownload) {\n errors.push({\n name: ig.name,\n error: `Package ${ig.name}@${version} not found in cache, and downloads are disabled`,\n });\n continue;\n }\n\n logger?.info(`Downloading ${ig.name}@${version} from registry...`);\n const tarball = await client.download(ig.name, version);\n cache.put(ig.name, version, tarball);\n logger?.info(`Downloaded and cached ${ig.name}@${version}`);\n\n // Create symlink from cache to project packages dir\n const newCachePath = cache.getPath(ig.name, version);\n if (!newCachePath) {\n errors.push({ name: ig.name, error: `Failed to locate cached package after download` });\n continue;\n }\n createLink(newCachePath, localPath);\n results.push({ name: ig.name, version, path: localPath, source: 'download' });\n } catch (err) {\n errors.push({\n name: ig.name,\n error: err instanceof Error ? err.message : String(err),\n });\n }\n }\n\n return {\n success: errors.length === 0,\n packages: results,\n errors,\n };\n}\n\n/**\n * Create a directory junction (Windows) or symlink (Unix) from target to linkPath.\n * Idempotent \u2014 if link already exists, does nothing.\n */\nfunction createLink(target: string, linkPath: string): void {\n if (existsSync(linkPath)) {\n // Already exists (either real dir or symlink) \u2014 skip\n try {\n const stat = lstatSync(linkPath);\n if (stat.isSymbolicLink() || stat.isDirectory()) {\n return;\n }\n } catch {\n // If stat fails, try to create anyway\n }\n }\n // Use 'junction' on Windows (no admin needed), 'dir' on Unix\n const linkType = process.platform === 'win32' ? 'junction' : 'dir';\n symlinkSync(target, linkPath, linkType);\n}\n", "// fhir-engine \u2014 public API\n\nexport { createFhirEngine } from './engine.js';\nexport { defineConfig, loadFhirConfig } from './config.js';\nexport { createConsoleLogger } from './logger.js';\nexport { createAdapter } from './adapter-factory.js';\nexport { resolvePackages } from './package-resolver.js';\n\nexport type {\n FhirEngine,\n FhirEngineConfig,\n FhirEnginePlugin,\n FhirEngineStatus,\n EngineContext,\n DatabaseConfig,\n SqliteDatabaseConfig,\n SqliteWasmDatabaseConfig,\n PostgresDatabaseConfig,\n PackagesConfig,\n Logger,\n ResolvePackagesOptions,\n ResolvedPackage,\n ResolvePackagesResult,\n} from './types.js';\n\n// Re-export key upstream types for convenience\nexport type { DefinitionRegistry, DefinitionProvider } from 'fhir-definition';\nexport type { FhirRuntimeInstance } from 'fhir-runtime';\nexport type { FhirPersistence, StorageAdapter } from 'fhir-persistence';\n\n// ---------------------------------------------------------------------------\n// Search utilities (from fhir-persistence)\n// ---------------------------------------------------------------------------\n\nexport { parseSearchRequest, executeSearch } from 'fhir-persistence';\nexport type { SearchRequest, SearchResult, SearchOptions } from 'fhir-persistence';\n\n// ---------------------------------------------------------------------------\n// FHIRPath evaluation (from fhir-runtime)\n// ---------------------------------------------------------------------------\n\nexport { evalFhirPath, evalFhirPathBoolean, evalFhirPathString, evalFhirPathTyped } from 'fhir-runtime';\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import { loadDefinitionPackages } from 'fhir-definition';\nimport { createRuntime, extractSearchValues, extractAllSearchValues, extractReferences } from 'fhir-runtime';\nimport { FhirDefinitionBridge, FhirRuntimeProvider, FhirSystem, parseSearchRequest, executeSearch } from 'fhir-persistence';\n\nimport { createAdapter } from './adapter-factory.js';\nimport { loadFhirConfig } from './config.js';\nimport { createConsoleLogger } from './logger.js';\nimport { resolvePackages } from './package-resolver.js';\nimport type { EngineContext, FhirEngine, FhirEngineConfig, FhirEnginePlugin, FhirEngineStatus } from './types.js';\n\n/**\n * Resolve the SQL dialect from the database config type.\n */\nfunction resolveDialect(type: FhirEngineConfig['database']['type']): 'sqlite' | 'postgres' {\n switch (type) {\n case 'sqlite':\n case 'sqlite-wasm':\n return 'sqlite';\n case 'postgres':\n return 'postgres';\n }\n}\n\n/**\n * Validate the engine configuration, throwing on missing required fields.\n */\nfunction validateConfig(config: FhirEngineConfig): void {\n if (!config.database) {\n throw new Error('fhir-engine: config.database is required');\n }\n if (!config.database.type) {\n throw new Error('fhir-engine: config.database.type is required (sqlite | sqlite-wasm | postgres)');\n }\n if (!config.packages) {\n throw new Error('fhir-engine: config.packages is required');\n }\n if (!config.packages.path) {\n throw new Error('fhir-engine: config.packages.path is required');\n }\n}\n\n/**\n * Run a lifecycle hook on all plugins in order.\n * Wraps errors with the plugin name for clear diagnostics.\n */\nasync function runPluginHook(\n plugins: FhirEnginePlugin[],\n hook: 'init' | 'start' | 'ready',\n ctx: EngineContext,\n): Promise<void> {\n for (const plugin of plugins) {\n const fn = plugin[hook];\n if (fn) {\n try {\n await fn.call(plugin, ctx);\n } catch (err) {\n throw new Error(\n `fhir-engine: plugin \"${plugin.name}\" failed during ${hook}: ${err instanceof Error ? err.message : String(err)}`,\n { cause: err },\n );\n }\n }\n }\n}\n\n/**\n * Create and bootstrap a fully initialized FHIR engine.\n *\n * This is the single entry point for all FHIR applications.\n * It assembles fhir-definition, fhir-runtime, and fhir-persistence\n * into a running system from a single configuration object.\n *\n * @example\n * ```ts\n * const engine = await createFhirEngine({\n * database: { type: 'sqlite', path: ':memory:' },\n * packages: { path: './fhir-packages' },\n * });\n *\n * const patient = await engine.persistence.createResource('Patient', {\n * resourceType: 'Patient',\n * name: [{ family: 'Smith', given: ['John'] }],\n * });\n *\n * await engine.stop();\n * ```\n */\nexport async function createFhirEngine(config?: FhirEngineConfig): Promise<FhirEngine> {\n // \u2500\u2500 0. Resolve config \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n if (!config) {\n config = await loadFhirConfig();\n }\n validateConfig(config);\n\n const logger = config.logger ?? createConsoleLogger();\n const plugins = config.plugins ?? [];\n logger.info('Initializing fhir-engine...');\n\n // \u2500\u2500 1a. Resolve packages (download/link if config.igs is set) \u2500\n if (config.igs && config.igs.length > 0) {\n logger.info(`Resolving ${config.igs.length} IG package(s)...`);\n const resolveResult = await resolvePackages(config, { logger });\n for (const pkg of resolveResult.packages) {\n logger.info(`Resolved ${pkg.name}@${pkg.version} (${pkg.source})`);\n }\n if (!resolveResult.success) {\n for (const err of resolveResult.errors) {\n logger.warn(`Failed to resolve package ${err.name}: ${err.error}`);\n }\n }\n }\n\n // \u2500\u2500 1b. Load FHIR definitions \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n logger.info(`Loading FHIR packages from: ${config.packages.path}`);\n const { registry, result } = loadDefinitionPackages(config.packages.path);\n logger.info(\n `Loaded ${result.packages.length} package(s): ${result.packages.map((p) => `${p.name}@${p.version}`).join(', ')}`,\n );\n\n // \u2500\u2500 2. Create fhir-runtime \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n logger.info('Creating fhir-runtime instance...');\n const runtime = await createRuntime({ definitions: registry, preloadCore: false });\n\n // \u2500\u2500 3. Build provider bridges \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n const definitionBridge = new FhirDefinitionBridge(registry);\n const runtimeProvider = new FhirRuntimeProvider({\n extractSearchValues,\n extractAllSearchValues,\n extractReferences,\n });\n\n // \u2500\u2500 4. Create storage adapter \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n const adapter = createAdapter(config.database, logger);\n\n // \u2500\u2500 5. Build EngineContext \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n const ctx: { -readonly [K in keyof EngineContext]: EngineContext[K] } = {\n config,\n definitions: registry,\n runtime,\n adapter,\n persistence: undefined,\n logger,\n };\n\n // \u2500\u2500 6. INIT phase \u2014 plugins run before persistence \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n if (plugins.length > 0) {\n logger.info(`Running init for ${plugins.length} plugin(s): ${plugins.map((p) => p.name).join(', ')}`);\n await runPluginHook(plugins, 'init', ctx);\n }\n\n // \u2500\u2500 7. Initialize FhirSystem \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n const dialect = resolveDialect(config.database.type);\n const system = new FhirSystem(adapter, {\n dialect,\n runtimeProvider,\n packageName: config.packageName ?? 'fhir-engine.default',\n packageVersion: config.packageVersion ?? '1.0.0',\n });\n\n logger.info('Initializing persistence system (schema + migration)...');\n const { persistence, sdRegistry, spRegistry, igResult, resourceTypes } =\n await system.initialize(definitionBridge);\n\n logger.info(`Persistence ready \u2014 IG action: ${igResult.action}, ${resourceTypes.length} resource type(s)`);\n\n // ctx.persistence now available\n ctx.persistence = persistence;\n\n // \u2500\u2500 8. START phase \u2014 plugins can access persistence \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n if (plugins.length > 0) {\n logger.info(`Running start for ${plugins.length} plugin(s)...`);\n await runPluginHook(plugins, 'start', ctx);\n }\n\n // \u2500\u2500 9. READY phase \u2014 system fully operational \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n if (plugins.length > 0) {\n logger.info(`Running ready for ${plugins.length} plugin(s)...`);\n await runPluginHook(plugins, 'ready', ctx);\n }\n\n // \u2500\u2500 10. Return FhirEngine \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n let stopped = false;\n const startedAt = new Date();\n const loadedPackages = result.packages.map((p) => `${p.name}@${p.version}`);\n const fhirVersions = [...new Set(\n result.packages\n .map((p) => {\n if (p.name.includes('.r4.')) return '4.0';\n if (p.name.includes('.r4b.')) return '4.3';\n if (p.name.includes('.r5.')) return '5.0';\n return undefined;\n })\n .filter(Boolean),\n )] as string[];\n\n const engine: FhirEngine = {\n definitions: registry,\n runtime,\n adapter,\n persistence,\n sdRegistry,\n spRegistry,\n igResult,\n resourceTypes,\n logger,\n context: ctx as EngineContext,\n\n async search(resourceType, queryParams, options) {\n const request = parseSearchRequest(resourceType, queryParams, spRegistry);\n return executeSearch(adapter, request, spRegistry, options);\n },\n\n status(): FhirEngineStatus {\n return {\n fhirVersions,\n loadedPackages,\n resourceTypes,\n databaseType: config.database.type,\n igAction: igResult.action,\n startedAt,\n plugins: plugins.map((p) => p.name),\n };\n },\n\n async stop() {\n if (stopped) return;\n stopped = true;\n logger.info('Stopping fhir-engine...');\n\n // Stop plugins in reverse registration order\n for (let i = plugins.length - 1; i >= 0; i--) {\n const plugin = plugins[i];\n if (plugin.stop) {\n try {\n await plugin.stop.call(plugin, ctx as EngineContext);\n } catch (err) {\n logger.error(\n `Plugin \"${plugin.name}\" failed during stop: ${err instanceof Error ? err.message : String(err)}`,\n );\n }\n }\n }\n\n await adapter.close();\n logger.info('fhir-engine stopped.');\n },\n };\n\n logger.info('fhir-engine ready.');\n return engine;\n}\n", "import { BetterSqlite3Adapter, PostgresAdapter } from 'fhir-persistence';\nimport type { StorageAdapter } from 'fhir-persistence';\nimport type { DatabaseConfig, Logger } from './types.js';\n\n/**\n * Create a StorageAdapter from the database configuration.\n *\n * Supported adapters:\n * - `sqlite` \u2192 BetterSqlite3Adapter (native, Node.js / Electron)\n * - `sqlite-wasm` \u2192 removed in fhir-persistence v0.3.0; use `sqlite` instead\n * - `postgres` \u2192 PostgresAdapter (pg connection pool)\n */\nexport function createAdapter(config: DatabaseConfig, logger: Logger): StorageAdapter {\n switch (config.type) {\n case 'sqlite': {\n logger.info(`Creating BetterSqlite3Adapter (path: ${config.path})`);\n return new BetterSqlite3Adapter({\n path: config.path,\n wal: config.wal ?? true,\n busyTimeout: config.busyTimeout ?? 5000,\n });\n }\n\n case 'sqlite-wasm': {\n throw new Error(\n 'fhir-engine: sqlite-wasm adapter was removed in fhir-persistence v0.3.0. ' +\n 'Use database.type = \"sqlite\" (BetterSqlite3Adapter) instead.',\n );\n }\n\n case 'postgres': {\n logger.info(`Creating PostgresAdapter (url: ${config.url.replace(/\\/\\/.*@/, '//*****@')})`);\n // Lazy-import pg to avoid hard dependency when using SQLite only\n let Pool: any;\n try {\n Pool = require('pg').Pool;\n } catch {\n throw new Error(\n 'fhir-engine: PostgreSQL requires the \"pg\" package. Install it with: npm install pg',\n );\n }\n const pool = new Pool({\n connectionString: config.url,\n max: config.max ?? 10,\n idleTimeoutMillis: config.idleTimeoutMillis ?? 30000,\n connectionTimeoutMillis: config.connectionTimeoutMillis ?? 0,\n });\n return new PostgresAdapter(pool);\n }\n\n default: {\n const _exhaustive: never = config;\n throw new Error(`fhir-engine: unknown database type: ${(_exhaustive as DatabaseConfig).type}`);\n }\n }\n}\n", "import { existsSync, readFileSync } from 'node:fs';\nimport { resolve, extname } from 'node:path';\nimport { pathToFileURL } from 'node:url';\nimport type { FhirEngineConfig, DatabaseConfig } from './types.js';\n\n// ---------------------------------------------------------------------------\n// defineConfig \u2014 typed identity helper for fhir.config.ts / .js\n// ---------------------------------------------------------------------------\n\n/**\n * Type-safe config helper for `fhir.config.ts` / `fhir.config.js`.\n *\n * @example\n * ```ts\n * // fhir.config.ts\n * import { defineConfig } from 'fhir-engine';\n *\n * export default defineConfig({\n * database: { type: 'sqlite', path: './fhir.db' },\n * packages: { path: './fhir-packages' },\n * });\n * ```\n */\nexport function defineConfig(config: FhirEngineConfig): FhirEngineConfig {\n return config;\n}\n\n// ---------------------------------------------------------------------------\n// Config file discovery order\n// ---------------------------------------------------------------------------\n\nconst CONFIG_FILENAMES = [\n 'fhir.config.ts',\n 'fhir.config.js',\n 'fhir.config.mjs',\n 'fhir.config.json',\n] as const;\n\n// ---------------------------------------------------------------------------\n// loadFhirConfig \u2014 auto-discover and load config\n// ---------------------------------------------------------------------------\n\n/**\n * Load engine configuration from a file.\n *\n * If `configPath` is provided, loads that exact file.\n * Otherwise, searches the current working directory for config files\n * in this order: `fhir.config.ts` \u2192 `fhir.config.js` \u2192 `fhir.config.mjs` \u2192 `fhir.config.json`.\n *\n * Environment variable overrides are applied on top of the loaded config.\n *\n * @param configPath - Explicit path to a config file (optional).\n * @returns The resolved `FhirEngineConfig`.\n */\nexport async function loadFhirConfig(configPath?: string): Promise<FhirEngineConfig> {\n let resolvedPath: string;\n\n if (configPath) {\n resolvedPath = resolve(configPath);\n if (!existsSync(resolvedPath)) {\n throw new Error(`fhir-engine: config file not found: ${resolvedPath}`);\n }\n } else {\n const cwd = process.cwd();\n const found = CONFIG_FILENAMES\n .map((name) => resolve(cwd, name))\n .find((p) => existsSync(p));\n if (!found) {\n throw new Error(\n `fhir-engine: no config file found in ${cwd}. ` +\n `Expected one of: ${CONFIG_FILENAMES.join(', ')}`,\n );\n }\n resolvedPath = found;\n }\n\n const config = await loadConfigFile(resolvedPath);\n return applyEnvOverrides(config);\n}\n\n// ---------------------------------------------------------------------------\n// File loaders\n// ---------------------------------------------------------------------------\n\nasync function loadConfigFile(filePath: string): Promise<FhirEngineConfig> {\n const ext = extname(filePath);\n\n if (ext === '.json') {\n return loadJsonConfig(filePath);\n }\n\n if (ext === '.ts' || ext === '.js' || ext === '.mjs') {\n return loadModuleConfig(filePath);\n }\n\n throw new Error(`fhir-engine: unsupported config file extension: ${ext}`);\n}\n\nfunction loadJsonConfig(filePath: string): FhirEngineConfig {\n try {\n const raw = readFileSync(filePath, 'utf-8');\n return JSON.parse(raw) as FhirEngineConfig;\n } catch (err) {\n throw new Error(\n `fhir-engine: failed to parse config file ${filePath}: ${err instanceof Error ? err.message : String(err)}`,\n { cause: err },\n );\n }\n}\n\nasync function loadModuleConfig(filePath: string): Promise<FhirEngineConfig> {\n try {\n const fileUrl = pathToFileURL(filePath).href;\n const mod = await import(fileUrl);\n const config = mod.default ?? mod;\n\n if (!config || typeof config !== 'object') {\n throw new Error('config file must export a FhirEngineConfig object as default export');\n }\n\n return config as FhirEngineConfig;\n } catch (err) {\n if (err instanceof Error && err.message.includes('must export')) {\n throw err;\n }\n throw new Error(\n `fhir-engine: failed to load config file ${filePath}: ${err instanceof Error ? err.message : String(err)}`,\n { cause: err },\n );\n }\n}\n\n// ---------------------------------------------------------------------------\n// Environment variable overrides\n// ---------------------------------------------------------------------------\n\nconst VALID_DB_TYPES = ['sqlite', 'sqlite-wasm', 'postgres'] as const;\n\n/**\n * Apply environment variable overrides on top of a loaded config.\n *\n * | Env Variable | Overrides |\n * |---------------------|----------------------------------|\n * | FHIR_DATABASE_TYPE | config.database.type |\n * | FHIR_DATABASE_URL | config.database.path / .url |\n * | FHIR_PACKAGES_PATH | config.packages.path |\n * | FHIR_LOG_LEVEL | (stored for logger filtering) |\n */\nexport function applyEnvOverrides(config: FhirEngineConfig): FhirEngineConfig {\n const result = structuredClone(config);\n\n const dbType = process.env.FHIR_DATABASE_TYPE;\n const dbUrl = process.env.FHIR_DATABASE_URL;\n const pkgPath = process.env.FHIR_PACKAGES_PATH;\n\n if (dbType) {\n if (!VALID_DB_TYPES.includes(dbType as typeof VALID_DB_TYPES[number])) {\n throw new Error(\n `fhir-engine: FHIR_DATABASE_TYPE must be one of: ${VALID_DB_TYPES.join(', ')}. Got: \"${dbType}\"`,\n );\n }\n // Rebuild database config with overridden type\n const validType = dbType as DatabaseConfig['type'];\n if (validType === 'postgres') {\n result.database = { type: 'postgres', url: (result.database as { url?: string }).url ?? '' };\n } else if (validType === 'sqlite-wasm') {\n result.database = { type: 'sqlite-wasm', path: (result.database as { path?: string }).path ?? '' };\n } else {\n result.database = { type: 'sqlite', path: (result.database as { path?: string }).path ?? '' };\n }\n }\n\n if (dbUrl) {\n const type = result.database?.type;\n if (type === 'postgres') {\n result.database = { ...result.database, type: 'postgres', url: dbUrl };\n } else if (type === 'sqlite-wasm') {\n result.database = { ...result.database, type: 'sqlite-wasm', path: dbUrl };\n } else {\n result.database = { ...result.database, type: 'sqlite', path: dbUrl };\n }\n }\n\n if (pkgPath) {\n result.packages = { ...result.packages, path: pkgPath };\n }\n\n return result;\n}\n", "import type { Logger } from './types.js';\n\n/**\n * Default console-based logger.\n */\nexport function createConsoleLogger(): Logger {\n return {\n debug: (message: string, ...args: unknown[]) => console.debug(`[fhir-engine] ${message}`, ...args),\n info: (message: string, ...args: unknown[]) => console.info(`[fhir-engine] ${message}`, ...args),\n warn: (message: string, ...args: unknown[]) => console.warn(`[fhir-engine] ${message}`, ...args),\n error: (message: string, ...args: unknown[]) => console.error(`[fhir-engine] ${message}`, ...args),\n };\n}\n", "import { resolve, join } from 'node:path';\nimport { existsSync, mkdirSync, symlinkSync, readFileSync, lstatSync, copyFileSync } from 'node:fs';\nimport { PackageCache, PackageRegistryClient } from 'fhir-definition';\n\nimport type { FhirEngineConfig, ResolvePackagesOptions, ResolvedPackage, ResolvePackagesResult, Logger } from './types.js';\n\n/**\n * Ensure the given directory exists (recursive mkdir).\n */\nfunction ensureDirSync(dir: string): void {\n if (!existsSync(dir)) {\n mkdirSync(dir, { recursive: true });\n }\n}\n\n/**\n * Check if a directory contains a FHIR package manifest.\n * Checks both root/package.json and package/package.json\n * (cached packages store content in a 'package' subdirectory).\n */\nfunction hasManifest(dir: string): boolean {\n return existsSync(join(dir, 'package.json')) || existsSync(join(dir, 'package', 'package.json'));\n}\n\n/**\n * Read the version from a package.json file.\n * Checks both root and package/ subdirectory.\n * Returns the version string or 'local' if not found.\n */\nfunction readLocalVersion(pkgDir: string): string {\n for (const candidate of [join(pkgDir, 'package.json'), join(pkgDir, 'package', 'package.json')]) {\n try {\n const raw = readFileSync(candidate, 'utf-8');\n const manifest = JSON.parse(raw);\n return manifest.version ?? 'local';\n } catch {\n // try next candidate\n }\n }\n return 'local';\n}\n\n/**\n * Resolve FHIR packages into a project's packages directory.\n *\n * Resolution order for each package:\n * 1. Already exists in packagesPath \u2192 use as-is (source: 'local')\n * 2. Found in system cache (~/.fhir/packages) \u2192 create symlink/junction (source: 'cache')\n * 3. Download from FHIR Package Registry \u2192 cache \u2192 create symlink (source: 'download')\n *\n * @param config Engine configuration (uses config.igs and config.packages.path)\n * @param options Override packages list, target path, download policy, or logger\n * @returns Result with resolved packages and any errors\n *\n * @example\n * ```ts\n * const result = await resolvePackages(config);\n * if (!result.success) {\n * console.warn('Some packages failed:', result.errors);\n * }\n * ```\n */\nexport async function resolvePackages(\n config: FhirEngineConfig,\n options?: ResolvePackagesOptions,\n): Promise<ResolvePackagesResult> {\n const packagesPath = resolve(options?.packagesPath ?? config.packages.path);\n const igs = options?.packages ?? config.igs ?? [];\n const allowDownload = options?.allowDownload ?? config.packageResolve?.allowDownload ?? true;\n const logger: Logger | undefined = options?.logger ?? config.logger;\n\n const cache = new PackageCache();\n const client = new PackageRegistryClient();\n const results: ResolvedPackage[] = [];\n const errors: Array<{ name: string; error: string }> = [];\n\n ensureDirSync(packagesPath);\n\n for (const ig of igs) {\n try {\n // 1. Already exists locally?\n const localPath = join(packagesPath, ig.name);\n if (hasManifest(localPath)) {\n const localVersion = readLocalVersion(localPath);\n logger?.debug(`Package ${ig.name} already exists locally at ${localPath}`);\n results.push({ name: ig.name, version: localVersion, path: localPath, source: 'local' });\n continue;\n }\n\n // 2. Resolve version\n let version = ig.version ?? 'latest';\n if (version === 'latest') {\n if (!allowDownload) {\n errors.push({\n name: ig.name,\n error: `Cannot resolve \"latest\" version for ${ig.name} without network access`,\n });\n continue;\n }\n logger?.info(`Resolving latest version for ${ig.name}...`);\n version = await client.getLatestVersion(ig.name);\n logger?.info(`Latest version for ${ig.name}: ${version}`);\n }\n\n // 3. Check system cache\n const cachePath = cache.getPath(ig.name, version);\n if (cachePath) {\n // Cache hit \u2014 create symlink\n logger?.info(`Found ${ig.name}@${version} in system cache, linking...`);\n ensureCacheRootManifest(cachePath);\n createLink(cachePath, localPath);\n results.push({ name: ig.name, version, path: localPath, source: 'cache' });\n continue;\n }\n\n // 4. Download\n if (!allowDownload) {\n errors.push({\n name: ig.name,\n error: `Package ${ig.name}@${version} not found in cache, and downloads are disabled`,\n });\n continue;\n }\n\n logger?.info(`Downloading ${ig.name}@${version} from registry...`);\n const tarball = await client.download(ig.name, version);\n cache.put(ig.name, version, tarball);\n logger?.info(`Downloaded and cached ${ig.name}@${version}`);\n\n // Create symlink from cache to project packages dir\n const newCachePath = cache.getPath(ig.name, version);\n if (!newCachePath) {\n errors.push({ name: ig.name, error: `Failed to locate cached package after download` });\n continue;\n }\n ensureCacheRootManifest(newCachePath);\n createLink(newCachePath, localPath);\n results.push({ name: ig.name, version, path: localPath, source: 'download' });\n } catch (err) {\n errors.push({\n name: ig.name,\n error: err instanceof Error ? err.message : String(err),\n });\n }\n }\n\n return {\n success: errors.length === 0,\n packages: results,\n errors,\n };\n}\n\n/**\n * Ensure the cache root directory has a package.json manifest.\n * Some tools (e.g. Firely Terminal) only place package.json inside the\n * package/ subdirectory. Without a root manifest, PackageScanner discovers\n * the package at the wrong depth, causing PackageLoader to construct a\n * double-nested \"package/package\" path that doesn't exist (\u2192 0 resources).\n */\nfunction ensureCacheRootManifest(cachePath: string): void {\n const rootManifest = join(cachePath, 'package.json');\n const nestedManifest = join(cachePath, 'package', 'package.json');\n if (!existsSync(rootManifest) && existsSync(nestedManifest)) {\n copyFileSync(nestedManifest, rootManifest);\n }\n}\n\n/**\n * Create a directory junction (Windows) or symlink (Unix) from target to linkPath.\n * Idempotent \u2014 if link already exists, does nothing.\n */\nfunction createLink(target: string, linkPath: string): void {\n if (existsSync(linkPath)) {\n // Already exists (either real dir or symlink) \u2014 skip\n try {\n const stat = lstatSync(linkPath);\n if (stat.isSymbolicLink() || stat.isDirectory()) {\n return;\n }\n } catch {\n // If stat fails, try to create anyway\n }\n }\n // Use 'junction' on Windows (no admin needed), 'dir' on Unix\n const linkType = process.platform === 'win32' ? 'junction' : 'dir';\n symlinkSync(target, linkPath, linkType);\n}\n", "// fhir-engine \u2014 public API\n\nexport { createFhirEngine } from './engine.js';\nexport { defineConfig, loadFhirConfig } from './config.js';\nexport { createConsoleLogger } from './logger.js';\nexport { createAdapter } from './adapter-factory.js';\nexport { resolvePackages } from './package-resolver.js';\n\nexport type {\n FhirEngine,\n FhirEngineConfig,\n FhirEnginePlugin,\n FhirEngineStatus,\n EngineContext,\n DatabaseConfig,\n SqliteDatabaseConfig,\n SqliteWasmDatabaseConfig,\n PostgresDatabaseConfig,\n PackagesConfig,\n Logger,\n ResolvePackagesOptions,\n ResolvedPackage,\n ResolvePackagesResult,\n} from './types.js';\n\n// Re-export key upstream types for convenience\nexport type { DefinitionRegistry, DefinitionProvider } from 'fhir-definition';\nexport type { FhirRuntimeInstance } from 'fhir-runtime';\nexport type { FhirPersistence, StorageAdapter } from 'fhir-persistence';\n\n// ---------------------------------------------------------------------------\n// Search utilities (from fhir-persistence)\n// ---------------------------------------------------------------------------\n\nexport { parseSearchRequest, executeSearch } from 'fhir-persistence';\nexport type { SearchRequest, SearchResult, SearchOptions } from 'fhir-persistence';\n\n// ---------------------------------------------------------------------------\n// FHIRPath evaluation (from fhir-runtime)\n// ---------------------------------------------------------------------------\n\nexport { evalFhirPath, evalFhirPathBoolean, evalFhirPathString, evalFhirPathTyped } from 'fhir-runtime';\n"],
5
+ "mappings": "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",
6
6
  "names": ["resolve", "existsSync", "readFileSync", "parseSearchRequest", "executeSearch"]
7
7
  }
package/dist/index.d.ts CHANGED
@@ -21,8 +21,8 @@ import type { StructureDefinitionRegistry } from 'fhir-persistence';
21
21
  *
22
22
  * Supported adapters:
23
23
  * - `sqlite` → BetterSqlite3Adapter (native, Node.js / Electron)
24
- * - `sqlite-wasm` → SQLiteAdapter (sql.js WASM, browser / cross-platform)
25
- * - `postgres` → not yet available (PostgresAdapter not exported from fhir-persistence)
24
+ * - `sqlite-wasm` → removed in fhir-persistence v0.3.0; use `sqlite` instead
25
+ * - `postgres` → PostgresAdapter (pg connection pool)
26
26
  */
27
27
  export declare function createAdapter(config: DatabaseConfig, logger: Logger): StorageAdapter;
28
28
 
@@ -226,8 +226,14 @@ export { parseSearchRequest }
226
226
 
227
227
  export declare interface PostgresDatabaseConfig {
228
228
  type: 'postgres';
229
- /** PostgreSQL connection string. */
229
+ /** PostgreSQL connection string (e.g. 'postgresql://user:pass@localhost:5432/fhir_db'). */
230
230
  url: string;
231
+ /** Maximum number of clients in the pool (default: 10). */
232
+ max?: number;
233
+ /** Idle timeout in milliseconds before a client is closed (default: 30000). */
234
+ idleTimeoutMillis?: number;
235
+ /** Connection timeout in milliseconds (default: 0 = no timeout). */
236
+ connectionTimeoutMillis?: number;
231
237
  }
232
238
 
233
239
  export declare interface ResolvedPackage {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "fhir-engine",
3
- "version": "0.4.0",
3
+ "version": "0.4.2",
4
4
  "description": "FHIR Engine for healthcare data management",
5
5
  "homepage": "https://github.com/medxaidev/fhir-engine#readme",
6
6
  "license": "MIT",
@@ -69,7 +69,7 @@
69
69
  "dependencies": {
70
70
  "fhir-definition": "^0.5.0",
71
71
  "fhir-runtime": "^0.8.1",
72
- "fhir-persistence": "^0.1.0"
72
+ "fhir-persistence": "^0.3.0"
73
73
  },
74
74
  "devDependencies": {
75
75
  "@microsoft/api-extractor": "^7.57.7",