fhir-engine 0.2.0 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -5,6 +5,26 @@ 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.3.0] - 2026-03-15
9
+
10
+ ### Added
11
+
12
+ - **`engine.search(resourceType, queryParams, options?)`** — High-level FHIR search method on the engine instance; parses query parameters and executes search in one call, returning `SearchResult` with matched resources, includes, and optional total
13
+ - **Re-exported search utilities** — `parseSearchRequest`, `executeSearch` functions and `SearchRequest`, `SearchResult`, `SearchOptions` types from `fhir-persistence`
14
+ - **Re-exported FHIRPath functions** — `evalFhirPath`, `evalFhirPathBoolean`, `evalFhirPathString`, `evalFhirPathTyped` from `fhir-runtime`
15
+
16
+ ### Changed
17
+
18
+ - **Test suite expanded** — from 73 to 84 tests:
19
+ - engine.search(): 6 tests
20
+ - Re-exported API verification: 5 tests (evalFhirPath, evalFhirPathBoolean, evalFhirPathString, parseSearchRequest, executeSearch)
21
+
22
+ ### Notes
23
+
24
+ - Resolves `FHIR_ENGINE_API_GAP_REQUEST.md` — fhir-cli can now import search and FHIRPath APIs from `fhir-engine` without violating the Layer 1 import restriction
25
+
26
+ ---
27
+
8
28
  ## [0.2.0] - 2026-03-15
9
29
 
10
30
  ### Added
package/README.md CHANGED
@@ -146,19 +146,20 @@ Creates and bootstraps a fully initialized FHIR engine.
146
146
 
147
147
  ### `FhirEngine`
148
148
 
149
- | Property | Type | Description |
150
- | --------------- | ----------------------------- | ---------------------------------------------- |
151
- | `definitions` | `DefinitionRegistry` | FHIR definitions from fhir-definition |
152
- | `runtime` | `FhirRuntimeInstance` | FHIRPath, validation from fhir-runtime |
153
- | `persistence` | `FhirPersistence` | CRUD + search + indexing from fhir-persistence |
154
- | `adapter` | `StorageAdapter` | Underlying database adapter |
155
- | `sdRegistry` | `StructureDefinitionRegistry` | Loaded StructureDefinitions |
156
- | `spRegistry` | `SearchParameterRegistry` | Loaded SearchParameters |
157
- | `resourceTypes` | `string[]` | Resource types with database tables |
158
- | `context` | `EngineContext` | Shared context (same object plugins receive) |
159
- | `logger` | `Logger` | Logger instance |
160
- | `status()` | `() => FhirEngineStatus` | Engine health and status information |
161
- | `stop()` | `() => Promise<void>` | Gracefully shut down the engine |
149
+ | Property | Type | Description |
150
+ | --------------- | ------------------------------------------------ | ---------------------------------------------- |
151
+ | `definitions` | `DefinitionRegistry` | FHIR definitions from fhir-definition |
152
+ | `runtime` | `FhirRuntimeInstance` | FHIRPath, validation from fhir-runtime |
153
+ | `persistence` | `FhirPersistence` | CRUD + search + indexing from fhir-persistence |
154
+ | `adapter` | `StorageAdapter` | Underlying database adapter |
155
+ | `sdRegistry` | `StructureDefinitionRegistry` | Loaded StructureDefinitions |
156
+ | `spRegistry` | `SearchParameterRegistry` | Loaded SearchParameters |
157
+ | `resourceTypes` | `string[]` | Resource types with database tables |
158
+ | `context` | `EngineContext` | Shared context (same object plugins receive) |
159
+ | `logger` | `Logger` | Logger instance |
160
+ | `search()` | `(type, params, opts?) => Promise<SearchResult>` | High-level FHIR search |
161
+ | `status()` | `() => FhirEngineStatus` | Engine health and status information |
162
+ | `stop()` | `() => Promise<void>` | Gracefully shut down the engine |
162
163
 
163
164
  ### `FhirEngineConfig`
164
165
 
@@ -189,6 +190,46 @@ interface FhirEngineStatus {
189
190
  }
190
191
  ```
191
192
 
193
+ ### `engine.search(resourceType, queryParams, options?)`
194
+
195
+ High-level FHIR search — parses URL query parameters and executes search in one call:
196
+
197
+ ```ts
198
+ const result = await engine.search("Patient", { name: "Smith", _count: "10" });
199
+ console.log(result.resources); // PersistedResource[]
200
+ console.log(result.total); // number (if options.total = 'accurate')
201
+ ```
202
+
203
+ ### Search Utilities (re-exported from fhir-persistence)
204
+
205
+ For lower-level search control:
206
+
207
+ ```ts
208
+ import { parseSearchRequest, executeSearch } from "fhir-engine";
209
+ import type { SearchRequest, SearchResult, SearchOptions } from "fhir-engine";
210
+
211
+ const request = parseSearchRequest(
212
+ "Patient",
213
+ { name: "Smith" },
214
+ engine.spRegistry,
215
+ );
216
+ const result = await executeSearch(engine.adapter, request, engine.spRegistry);
217
+ ```
218
+
219
+ ### FHIRPath Evaluation (re-exported from fhir-runtime)
220
+
221
+ ```ts
222
+ import {
223
+ evalFhirPath,
224
+ evalFhirPathBoolean,
225
+ evalFhirPathString,
226
+ } from "fhir-engine";
227
+
228
+ const values = evalFhirPath("Patient.name.family", patient); // unknown[]
229
+ const active = evalFhirPathBoolean("Patient.active", patient); // boolean
230
+ const family = evalFhirPathString("Patient.name.family", patient); // string | undefined
231
+ ```
232
+
192
233
  ### `defineConfig(config)`
193
234
 
194
235
  Type-safe identity helper for config files. Returns the config unchanged.
@@ -24,7 +24,13 @@ __export(index_exports, {
24
24
  createConsoleLogger: () => createConsoleLogger,
25
25
  createFhirEngine: () => createFhirEngine,
26
26
  defineConfig: () => defineConfig,
27
- loadFhirConfig: () => loadFhirConfig
27
+ evalFhirPath: () => import_fhir_runtime2.evalFhirPath,
28
+ evalFhirPathBoolean: () => import_fhir_runtime2.evalFhirPathBoolean,
29
+ evalFhirPathString: () => import_fhir_runtime2.evalFhirPathString,
30
+ evalFhirPathTyped: () => import_fhir_runtime2.evalFhirPathTyped,
31
+ executeSearch: () => import_fhir_persistence3.executeSearch,
32
+ loadFhirConfig: () => loadFhirConfig,
33
+ parseSearchRequest: () => import_fhir_persistence3.parseSearchRequest
28
34
  });
29
35
  module.exports = __toCommonJS(index_exports);
30
36
 
@@ -295,6 +301,10 @@ async function createFhirEngine(config) {
295
301
  resourceTypes,
296
302
  logger,
297
303
  context: ctx,
304
+ async search(resourceType, queryParams, options) {
305
+ const request = (0, import_fhir_persistence2.parseSearchRequest)(resourceType, queryParams, spRegistry);
306
+ return (0, import_fhir_persistence2.executeSearch)(adapter, request, spRegistry, options);
307
+ },
298
308
  status() {
299
309
  return {
300
310
  fhirVersions,
@@ -329,12 +339,22 @@ async function createFhirEngine(config) {
329
339
  logger.info("fhir-engine ready.");
330
340
  return engine;
331
341
  }
342
+
343
+ // src/index.ts
344
+ var import_fhir_persistence3 = require("fhir-persistence");
345
+ var import_fhir_runtime2 = require("fhir-runtime");
332
346
  // Annotate the CommonJS export names for ESM import in node:
333
347
  0 && (module.exports = {
334
348
  createAdapter,
335
349
  createConsoleLogger,
336
350
  createFhirEngine,
337
351
  defineConfig,
338
- loadFhirConfig
352
+ evalFhirPath,
353
+ evalFhirPathBoolean,
354
+ evalFhirPathString,
355
+ evalFhirPathTyped,
356
+ executeSearch,
357
+ loadFhirConfig,
358
+ parseSearchRequest
339
359
  });
340
360
  //# sourceMappingURL=index.cjs.map
@@ -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"],
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';\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} 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", "import { loadDefinitionPackages } from 'fhir-definition';\nimport { createRuntime, extractSearchValues, extractAllSearchValues, extractReferences } from 'fhir-runtime';\nimport { FhirDefinitionBridge, FhirRuntimeProvider, FhirSystem } from 'fhir-persistence';\n\nimport { createAdapter } from './adapter-factory.js';\nimport { loadFhirConfig } from './config.js';\nimport { createConsoleLogger } from './logger.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 1. 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 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"],
5
- "mappings": "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",
6
- "names": ["import_fhir_persistence"]
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';\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} 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 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 1. 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"],
5
+ "mappings": "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",
6
+ "names": ["import_fhir_persistence", "import_fhir_persistence", "import_fhir_runtime"]
7
7
  }
@@ -1,9 +1,18 @@
1
1
  import { DefinitionProvider } from 'fhir-definition';
2
2
  import { DefinitionRegistry } from 'fhir-definition';
3
+ import { evalFhirPath } from 'fhir-runtime';
4
+ import { evalFhirPathBoolean } from 'fhir-runtime';
5
+ import { evalFhirPathString } from 'fhir-runtime';
6
+ import { evalFhirPathTyped } from 'fhir-runtime';
7
+ import { executeSearch } from 'fhir-persistence';
3
8
  import { FhirPersistence } from 'fhir-persistence';
4
9
  import { FhirRuntimeInstance } from 'fhir-runtime';
5
10
  import type { FhirSystemReady } from 'fhir-persistence';
11
+ import { parseSearchRequest } from 'fhir-persistence';
12
+ import { SearchOptions } from 'fhir-persistence';
6
13
  import type { SearchParameterRegistry } from 'fhir-persistence';
14
+ import { SearchRequest } from 'fhir-persistence';
15
+ import { SearchResult } from 'fhir-persistence';
7
16
  import { StorageAdapter } from 'fhir-persistence';
8
17
  import type { StructureDefinitionRegistry } from 'fhir-persistence';
9
18
 
@@ -83,6 +92,16 @@ export declare interface EngineContext {
83
92
  readonly logger: Logger;
84
93
  }
85
94
 
95
+ export { evalFhirPath }
96
+
97
+ export { evalFhirPathBoolean }
98
+
99
+ export { evalFhirPathString }
100
+
101
+ export { evalFhirPathTyped }
102
+
103
+ export { executeSearch }
104
+
86
105
  export declare interface FhirEngine {
87
106
  /** The loaded DefinitionRegistry from fhir-definition. */
88
107
  readonly definitions: DefinitionRegistry;
@@ -104,6 +123,15 @@ export declare interface FhirEngine {
104
123
  readonly logger: Logger;
105
124
  /** Shared context (same object plugins receive). */
106
125
  readonly context: EngineContext;
126
+ /**
127
+ * High-level FHIR search — parses query params, executes search, returns results.
128
+ *
129
+ * @param resourceType - The FHIR resource type (e.g. 'Patient').
130
+ * @param queryParams - URL query parameters (e.g. `{ name: 'Smith', _count: '10' }`).
131
+ * @param options - Optional search options (e.g. `{ total: 'accurate' }`).
132
+ * @returns Search result with matched resources, includes, and optional total.
133
+ */
134
+ search(resourceType: string, queryParams: Record<string, string | string[] | undefined>, options?: SearchOptions): Promise<SearchResult>;
107
135
  /** Return engine health/status information. */
108
136
  status(): FhirEngineStatus;
109
137
  /** Gracefully shut down the engine (closes adapter). */
@@ -185,12 +213,20 @@ export declare interface PackagesConfig {
185
213
  path: string;
186
214
  }
187
215
 
216
+ export { parseSearchRequest }
217
+
188
218
  export declare interface PostgresDatabaseConfig {
189
219
  type: 'postgres';
190
220
  /** PostgreSQL connection string. */
191
221
  url: string;
192
222
  }
193
223
 
224
+ export { SearchOptions }
225
+
226
+ export { SearchRequest }
227
+
228
+ export { SearchResult }
229
+
194
230
  export declare interface SqliteDatabaseConfig {
195
231
  type: 'sqlite';
196
232
  /** File path or ':memory:' for in-memory database. */
@@ -1,9 +1,18 @@
1
1
  import { DefinitionProvider } from 'fhir-definition';
2
2
  import { DefinitionRegistry } from 'fhir-definition';
3
+ import { evalFhirPath } from 'fhir-runtime';
4
+ import { evalFhirPathBoolean } from 'fhir-runtime';
5
+ import { evalFhirPathString } from 'fhir-runtime';
6
+ import { evalFhirPathTyped } from 'fhir-runtime';
7
+ import { executeSearch } from 'fhir-persistence';
3
8
  import { FhirPersistence } from 'fhir-persistence';
4
9
  import { FhirRuntimeInstance } from 'fhir-runtime';
5
10
  import type { FhirSystemReady } from 'fhir-persistence';
11
+ import { parseSearchRequest } from 'fhir-persistence';
12
+ import { SearchOptions } from 'fhir-persistence';
6
13
  import type { SearchParameterRegistry } from 'fhir-persistence';
14
+ import { SearchRequest } from 'fhir-persistence';
15
+ import { SearchResult } from 'fhir-persistence';
7
16
  import { StorageAdapter } from 'fhir-persistence';
8
17
  import type { StructureDefinitionRegistry } from 'fhir-persistence';
9
18
 
@@ -83,6 +92,16 @@ export declare interface EngineContext {
83
92
  readonly logger: Logger;
84
93
  }
85
94
 
95
+ export { evalFhirPath }
96
+
97
+ export { evalFhirPathBoolean }
98
+
99
+ export { evalFhirPathString }
100
+
101
+ export { evalFhirPathTyped }
102
+
103
+ export { executeSearch }
104
+
86
105
  export declare interface FhirEngine {
87
106
  /** The loaded DefinitionRegistry from fhir-definition. */
88
107
  readonly definitions: DefinitionRegistry;
@@ -104,6 +123,15 @@ export declare interface FhirEngine {
104
123
  readonly logger: Logger;
105
124
  /** Shared context (same object plugins receive). */
106
125
  readonly context: EngineContext;
126
+ /**
127
+ * High-level FHIR search — parses query params, executes search, returns results.
128
+ *
129
+ * @param resourceType - The FHIR resource type (e.g. 'Patient').
130
+ * @param queryParams - URL query parameters (e.g. `{ name: 'Smith', _count: '10' }`).
131
+ * @param options - Optional search options (e.g. `{ total: 'accurate' }`).
132
+ * @returns Search result with matched resources, includes, and optional total.
133
+ */
134
+ search(resourceType: string, queryParams: Record<string, string | string[] | undefined>, options?: SearchOptions): Promise<SearchResult>;
107
135
  /** Return engine health/status information. */
108
136
  status(): FhirEngineStatus;
109
137
  /** Gracefully shut down the engine (closes adapter). */
@@ -185,12 +213,20 @@ export declare interface PackagesConfig {
185
213
  path: string;
186
214
  }
187
215
 
216
+ export { parseSearchRequest }
217
+
188
218
  export declare interface PostgresDatabaseConfig {
189
219
  type: 'postgres';
190
220
  /** PostgreSQL connection string. */
191
221
  url: string;
192
222
  }
193
223
 
224
+ export { SearchOptions }
225
+
226
+ export { SearchRequest }
227
+
228
+ export { SearchResult }
229
+
194
230
  export declare interface SqliteDatabaseConfig {
195
231
  type: 'sqlite';
196
232
  /** File path or ':memory:' for in-memory database. */
@@ -1,7 +1,7 @@
1
1
  // src/engine.ts
2
2
  import { loadDefinitionPackages } from "fhir-definition";
3
3
  import { createRuntime, extractSearchValues, extractAllSearchValues, extractReferences } from "fhir-runtime";
4
- import { FhirDefinitionBridge, FhirRuntimeProvider, FhirSystem } from "fhir-persistence";
4
+ import { FhirDefinitionBridge, FhirRuntimeProvider, FhirSystem, parseSearchRequest, executeSearch } from "fhir-persistence";
5
5
 
6
6
  // src/adapter-factory.ts
7
7
  import { BetterSqlite3Adapter, SQLiteAdapter } from "fhir-persistence";
@@ -265,6 +265,10 @@ async function createFhirEngine(config) {
265
265
  resourceTypes,
266
266
  logger,
267
267
  context: ctx,
268
+ async search(resourceType, queryParams, options) {
269
+ const request = parseSearchRequest(resourceType, queryParams, spRegistry);
270
+ return executeSearch(adapter, request, spRegistry, options);
271
+ },
268
272
  status() {
269
273
  return {
270
274
  fhirVersions,
@@ -299,11 +303,21 @@ async function createFhirEngine(config) {
299
303
  logger.info("fhir-engine ready.");
300
304
  return engine;
301
305
  }
306
+
307
+ // src/index.ts
308
+ import { parseSearchRequest as parseSearchRequest2, executeSearch as executeSearch2 } from "fhir-persistence";
309
+ import { evalFhirPath, evalFhirPathBoolean, evalFhirPathString, evalFhirPathTyped } from "fhir-runtime";
302
310
  export {
303
311
  createAdapter,
304
312
  createConsoleLogger,
305
313
  createFhirEngine,
306
314
  defineConfig,
307
- loadFhirConfig
315
+ evalFhirPath,
316
+ evalFhirPathBoolean,
317
+ evalFhirPathString,
318
+ evalFhirPathTyped,
319
+ executeSearch2 as executeSearch,
320
+ loadFhirConfig,
321
+ parseSearchRequest2 as parseSearchRequest
308
322
  };
309
323
  //# sourceMappingURL=index.mjs.map
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
- "sources": ["../../src/engine.ts", "../../src/adapter-factory.ts", "../../src/config.ts", "../../src/logger.ts"],
4
- "sourcesContent": ["import { loadDefinitionPackages } from 'fhir-definition';\nimport { createRuntime, extractSearchValues, extractAllSearchValues, extractReferences } from 'fhir-runtime';\nimport { FhirDefinitionBridge, FhirRuntimeProvider, FhirSystem } from 'fhir-persistence';\n\nimport { createAdapter } from './adapter-factory.js';\nimport { loadFhirConfig } from './config.js';\nimport { createConsoleLogger } from './logger.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 1. 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 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"],
5
- "mappings": "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",
6
- "names": []
3
+ "sources": ["../../src/engine.ts", "../../src/adapter-factory.ts", "../../src/config.ts", "../../src/logger.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 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 1. 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", "// 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';\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} 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
+ "names": ["parseSearchRequest", "executeSearch"]
7
7
  }
package/dist/index.d.ts CHANGED
@@ -1,9 +1,18 @@
1
1
  import { DefinitionProvider } from 'fhir-definition';
2
2
  import { DefinitionRegistry } from 'fhir-definition';
3
+ import { evalFhirPath } from 'fhir-runtime';
4
+ import { evalFhirPathBoolean } from 'fhir-runtime';
5
+ import { evalFhirPathString } from 'fhir-runtime';
6
+ import { evalFhirPathTyped } from 'fhir-runtime';
7
+ import { executeSearch } from 'fhir-persistence';
3
8
  import { FhirPersistence } from 'fhir-persistence';
4
9
  import { FhirRuntimeInstance } from 'fhir-runtime';
5
10
  import type { FhirSystemReady } from 'fhir-persistence';
11
+ import { parseSearchRequest } from 'fhir-persistence';
12
+ import { SearchOptions } from 'fhir-persistence';
6
13
  import type { SearchParameterRegistry } from 'fhir-persistence';
14
+ import { SearchRequest } from 'fhir-persistence';
15
+ import { SearchResult } from 'fhir-persistence';
7
16
  import { StorageAdapter } from 'fhir-persistence';
8
17
  import type { StructureDefinitionRegistry } from 'fhir-persistence';
9
18
 
@@ -83,6 +92,16 @@ export declare interface EngineContext {
83
92
  readonly logger: Logger;
84
93
  }
85
94
 
95
+ export { evalFhirPath }
96
+
97
+ export { evalFhirPathBoolean }
98
+
99
+ export { evalFhirPathString }
100
+
101
+ export { evalFhirPathTyped }
102
+
103
+ export { executeSearch }
104
+
86
105
  export declare interface FhirEngine {
87
106
  /** The loaded DefinitionRegistry from fhir-definition. */
88
107
  readonly definitions: DefinitionRegistry;
@@ -104,6 +123,15 @@ export declare interface FhirEngine {
104
123
  readonly logger: Logger;
105
124
  /** Shared context (same object plugins receive). */
106
125
  readonly context: EngineContext;
126
+ /**
127
+ * High-level FHIR search — parses query params, executes search, returns results.
128
+ *
129
+ * @param resourceType - The FHIR resource type (e.g. 'Patient').
130
+ * @param queryParams - URL query parameters (e.g. `{ name: 'Smith', _count: '10' }`).
131
+ * @param options - Optional search options (e.g. `{ total: 'accurate' }`).
132
+ * @returns Search result with matched resources, includes, and optional total.
133
+ */
134
+ search(resourceType: string, queryParams: Record<string, string | string[] | undefined>, options?: SearchOptions): Promise<SearchResult>;
107
135
  /** Return engine health/status information. */
108
136
  status(): FhirEngineStatus;
109
137
  /** Gracefully shut down the engine (closes adapter). */
@@ -185,12 +213,20 @@ export declare interface PackagesConfig {
185
213
  path: string;
186
214
  }
187
215
 
216
+ export { parseSearchRequest }
217
+
188
218
  export declare interface PostgresDatabaseConfig {
189
219
  type: 'postgres';
190
220
  /** PostgreSQL connection string. */
191
221
  url: string;
192
222
  }
193
223
 
224
+ export { SearchOptions }
225
+
226
+ export { SearchRequest }
227
+
228
+ export { SearchResult }
229
+
194
230
  export declare interface SqliteDatabaseConfig {
195
231
  type: 'sqlite';
196
232
  /** File path or ':memory:' for in-memory database. */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "fhir-engine",
3
- "version": "0.2.0",
3
+ "version": "0.3.0",
4
4
  "description": "FHIR Engine for healthcare data management",
5
5
  "homepage": "https://github.com/medxaidev/fhir-engine#readme",
6
6
  "license": "MIT",