fhir-persistence 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (140) hide show
  1. package/CHANGELOG.md +77 -0
  2. package/LICENSE +21 -0
  3. package/README.md +225 -0
  4. package/dist/cjs/index.cjs +8869 -0
  5. package/dist/cjs/index.cjs.map +7 -0
  6. package/dist/cjs/index.d.ts +3114 -0
  7. package/dist/cjs/package.json +5 -0
  8. package/dist/esm/index.d.ts +3114 -0
  9. package/dist/esm/index.mjs +8745 -0
  10. package/dist/esm/index.mjs.map +7 -0
  11. package/dist/esm/package.json +5 -0
  12. package/dist/index.d.ts +3114 -0
  13. package/dist/lib/cache/resource-cache.d.ts +137 -0
  14. package/dist/lib/cache/resource-cache.d.ts.map +1 -0
  15. package/dist/lib/cli/reindex.d.ts +55 -0
  16. package/dist/lib/cli/reindex.d.ts.map +1 -0
  17. package/dist/lib/db/adapter.d.ts +79 -0
  18. package/dist/lib/db/adapter.d.ts.map +1 -0
  19. package/dist/lib/db/better-sqlite3-adapter.d.ts +65 -0
  20. package/dist/lib/db/better-sqlite3-adapter.d.ts.map +1 -0
  21. package/dist/lib/db/dialect.d.ts +87 -0
  22. package/dist/lib/db/dialect.d.ts.map +1 -0
  23. package/dist/lib/db/index.d.ts +18 -0
  24. package/dist/lib/db/index.d.ts.map +1 -0
  25. package/dist/lib/db/postgres-adapter.d.ts +84 -0
  26. package/dist/lib/db/postgres-adapter.d.ts.map +1 -0
  27. package/dist/lib/db/postgres-dialect.d.ts +36 -0
  28. package/dist/lib/db/postgres-dialect.d.ts.map +1 -0
  29. package/dist/lib/db/sqlite-adapter.d.ts +41 -0
  30. package/dist/lib/db/sqlite-adapter.d.ts.map +1 -0
  31. package/dist/lib/db/sqlite-dialect.d.ts +34 -0
  32. package/dist/lib/db/sqlite-dialect.d.ts.map +1 -0
  33. package/dist/lib/index.d.ts +65 -0
  34. package/dist/lib/index.d.ts.map +1 -0
  35. package/dist/lib/migration/ig-persistence-manager.d.ts +56 -0
  36. package/dist/lib/migration/ig-persistence-manager.d.ts.map +1 -0
  37. package/dist/lib/migration/migration-generator.d.ts +38 -0
  38. package/dist/lib/migration/migration-generator.d.ts.map +1 -0
  39. package/dist/lib/migration/reindex-scheduler.d.ts +82 -0
  40. package/dist/lib/migration/reindex-scheduler.d.ts.map +1 -0
  41. package/dist/lib/migration/schema-diff.d.ts +44 -0
  42. package/dist/lib/migration/schema-diff.d.ts.map +1 -0
  43. package/dist/lib/migrations/index.d.ts +8 -0
  44. package/dist/lib/migrations/index.d.ts.map +1 -0
  45. package/dist/lib/migrations/migration-runner.d.ts +102 -0
  46. package/dist/lib/migrations/migration-runner.d.ts.map +1 -0
  47. package/dist/lib/observability/search-logger.d.ts +74 -0
  48. package/dist/lib/observability/search-logger.d.ts.map +1 -0
  49. package/dist/lib/platform/platform-ig-definitions.d.ts +51 -0
  50. package/dist/lib/platform/platform-ig-definitions.d.ts.map +1 -0
  51. package/dist/lib/platform/platform-ig-loader.d.ts +30 -0
  52. package/dist/lib/platform/platform-ig-loader.d.ts.map +1 -0
  53. package/dist/lib/providers/definition-provider.d.ts +124 -0
  54. package/dist/lib/providers/definition-provider.d.ts.map +1 -0
  55. package/dist/lib/providers/fhir-definition-provider.d.ts +58 -0
  56. package/dist/lib/providers/fhir-definition-provider.d.ts.map +1 -0
  57. package/dist/lib/providers/fhir-runtime-provider.d.ts +75 -0
  58. package/dist/lib/providers/fhir-runtime-provider.d.ts.map +1 -0
  59. package/dist/lib/providers/in-memory-definition-provider.d.ts +72 -0
  60. package/dist/lib/providers/in-memory-definition-provider.d.ts.map +1 -0
  61. package/dist/lib/providers/index.d.ts +13 -0
  62. package/dist/lib/providers/index.d.ts.map +1 -0
  63. package/dist/lib/providers/property-path-runtime-provider.d.ts +34 -0
  64. package/dist/lib/providers/property-path-runtime-provider.d.ts.map +1 -0
  65. package/dist/lib/providers/runtime-provider.d.ts +84 -0
  66. package/dist/lib/providers/runtime-provider.d.ts.map +1 -0
  67. package/dist/lib/registry/element-cardinality.d.ts +15 -0
  68. package/dist/lib/registry/element-cardinality.d.ts.map +1 -0
  69. package/dist/lib/registry/index.d.ts +10 -0
  70. package/dist/lib/registry/index.d.ts.map +1 -0
  71. package/dist/lib/registry/package-registry-repo.d.ts +106 -0
  72. package/dist/lib/registry/package-registry-repo.d.ts.map +1 -0
  73. package/dist/lib/registry/search-parameter-registry.d.ts +175 -0
  74. package/dist/lib/registry/search-parameter-registry.d.ts.map +1 -0
  75. package/dist/lib/registry/structure-definition-registry.d.ts +93 -0
  76. package/dist/lib/registry/structure-definition-registry.d.ts.map +1 -0
  77. package/dist/lib/repo/errors.d.ts +61 -0
  78. package/dist/lib/repo/errors.d.ts.map +1 -0
  79. package/dist/lib/repo/history-bundle.d.ts +78 -0
  80. package/dist/lib/repo/history-bundle.d.ts.map +1 -0
  81. package/dist/lib/repo/index.d.ts +17 -0
  82. package/dist/lib/repo/index.d.ts.map +1 -0
  83. package/dist/lib/repo/indexing-pipeline.d.ts +108 -0
  84. package/dist/lib/repo/indexing-pipeline.d.ts.map +1 -0
  85. package/dist/lib/repo/lookup-table-writer.d.ts +46 -0
  86. package/dist/lib/repo/lookup-table-writer.d.ts.map +1 -0
  87. package/dist/lib/repo/reference-indexer.d.ts +56 -0
  88. package/dist/lib/repo/reference-indexer.d.ts.map +1 -0
  89. package/dist/lib/repo/row-builder.d.ts +78 -0
  90. package/dist/lib/repo/row-builder.d.ts.map +1 -0
  91. package/dist/lib/repo/row-indexer.d.ts +111 -0
  92. package/dist/lib/repo/row-indexer.d.ts.map +1 -0
  93. package/dist/lib/repo/sql-builder.d.ts +166 -0
  94. package/dist/lib/repo/sql-builder.d.ts.map +1 -0
  95. package/dist/lib/repo/types.d.ts +321 -0
  96. package/dist/lib/repo/types.d.ts.map +1 -0
  97. package/dist/lib/schema/ddl-generator.d.ts +81 -0
  98. package/dist/lib/schema/ddl-generator.d.ts.map +1 -0
  99. package/dist/lib/schema/index.d.ts +8 -0
  100. package/dist/lib/schema/index.d.ts.map +1 -0
  101. package/dist/lib/schema/table-schema-builder.d.ts +66 -0
  102. package/dist/lib/schema/table-schema-builder.d.ts.map +1 -0
  103. package/dist/lib/schema/table-schema.d.ts +236 -0
  104. package/dist/lib/schema/table-schema.d.ts.map +1 -0
  105. package/dist/lib/search/index.d.ts +22 -0
  106. package/dist/lib/search/index.d.ts.map +1 -0
  107. package/dist/lib/search/pagination.d.ts +53 -0
  108. package/dist/lib/search/pagination.d.ts.map +1 -0
  109. package/dist/lib/search/param-parser.d.ts +85 -0
  110. package/dist/lib/search/param-parser.d.ts.map +1 -0
  111. package/dist/lib/search/search-bundle.d.ts +61 -0
  112. package/dist/lib/search/search-bundle.d.ts.map +1 -0
  113. package/dist/lib/search/search-executor.d.ts +58 -0
  114. package/dist/lib/search/search-executor.d.ts.map +1 -0
  115. package/dist/lib/search/search-planner.d.ts +57 -0
  116. package/dist/lib/search/search-planner.d.ts.map +1 -0
  117. package/dist/lib/search/search-sql-builder.d.ts +86 -0
  118. package/dist/lib/search/search-sql-builder.d.ts.map +1 -0
  119. package/dist/lib/search/types.d.ts +219 -0
  120. package/dist/lib/search/types.d.ts.map +1 -0
  121. package/dist/lib/search/where-builder.d.ts +64 -0
  122. package/dist/lib/search/where-builder.d.ts.map +1 -0
  123. package/dist/lib/startup/fhir-system.d.ts +82 -0
  124. package/dist/lib/startup/fhir-system.d.ts.map +1 -0
  125. package/dist/lib/store/conditional-service.d.ts +76 -0
  126. package/dist/lib/store/conditional-service.d.ts.map +1 -0
  127. package/dist/lib/store/fhir-persistence.d.ts +81 -0
  128. package/dist/lib/store/fhir-persistence.d.ts.map +1 -0
  129. package/dist/lib/store/fhir-store.d.ts +44 -0
  130. package/dist/lib/store/fhir-store.d.ts.map +1 -0
  131. package/dist/lib/terminology/terminology-code-repo.d.ts +61 -0
  132. package/dist/lib/terminology/terminology-code-repo.d.ts.map +1 -0
  133. package/dist/lib/terminology/valueset-repo.d.ts +76 -0
  134. package/dist/lib/terminology/valueset-repo.d.ts.map +1 -0
  135. package/dist/lib/transaction/bundle-processor.d.ts +84 -0
  136. package/dist/lib/transaction/bundle-processor.d.ts.map +1 -0
  137. package/dist/lib/transaction/urn-resolver.d.ts +62 -0
  138. package/dist/lib/transaction/urn-resolver.d.ts.map +1 -0
  139. package/dist/tsdoc-metadata.json +11 -0
  140. package/package.json +87 -0
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/index.ts", "../../src/registry/structure-definition-registry.ts", "../../src/registry/element-cardinality.ts", "../../src/registry/search-parameter-registry.ts", "../../src/schema/table-schema-builder.ts", "../../src/schema/ddl-generator.ts", "../../src/repo/types.ts", "../../src/repo/errors.ts", "../../src/repo/row-indexer.ts", "../../src/repo/row-builder.ts", "../../src/repo/reference-indexer.ts", "../../src/repo/sql-builder.ts", "../../src/repo/history-bundle.ts", "../../src/search/types.ts", "../../src/search/param-parser.ts", "../../src/search/where-builder.ts", "../../src/search/search-sql-builder.ts", "../../src/search/search-bundle.ts", "../../src/search/pagination.ts", "../../src/search/search-executor.ts", "../../src/search/search-planner.ts", "../../src/db/sqlite-adapter.ts", "../../src/db/better-sqlite3-adapter.ts", "../../src/store/fhir-store.ts", "../../src/store/fhir-persistence.ts", "../../src/repo/lookup-table-writer.ts", "../../src/repo/indexing-pipeline.ts", "../../src/migration/schema-diff.ts", "../../src/migration/migration-generator.ts", "../../src/registry/package-registry-repo.ts", "../../src/migrations/migration-runner.ts", "../../src/migration/reindex-scheduler.ts", "../../src/migration/ig-persistence-manager.ts", "../../src/terminology/terminology-code-repo.ts", "../../src/terminology/valueset-repo.ts", "../../src/platform/platform-ig-definitions.ts", "../../src/platform/platform-ig-loader.ts", "../../src/cache/resource-cache.ts", "../../src/observability/search-logger.ts", "../../src/cli/reindex.ts", "../../src/startup/fhir-system.ts", "../../src/providers/fhir-definition-provider.ts", "../../src/providers/fhir-runtime-provider.ts"],
4
+ "sourcesContent": ["/**\r\n * `fhir-persistence` \u2014 Embedded FHIR R4 Persistence Layer\r\n *\r\n * Provides CRUD, search, indexing, schema migration, and terminology\r\n * for FHIR R4 resources over SQLite (sql.js / better-sqlite3) and PostgreSQL.\r\n *\r\n * @packageDocumentation\r\n */\r\n\r\n// \u2500\u2500\u2500 Schema Types \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\r\nexport type {\r\n SqlColumnType,\r\n ColumnSchema,\r\n IndexSchema,\r\n ConstraintSchema,\r\n MainTableSchema,\r\n HistoryTableSchema,\r\n ReferencesTableSchema,\r\n ResourceTableSet,\r\n SchemaDefinition,\r\n} from './schema/index.js';\r\n\r\n// \u2500\u2500\u2500 Registry \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\r\nexport { StructureDefinitionRegistry } from './registry/index.js';\r\nexport type { CanonicalProfile } from './registry/index.js';\r\nexport { SearchParameterRegistry } from './registry/index.js';\r\nexport type {\r\n SearchParamType,\r\n SearchStrategy,\r\n SearchColumnType,\r\n SearchParameterImpl,\r\n SearchParameterResource,\r\n SearchParameterBundle,\r\n} from './registry/index.js';\r\n\r\n// \u2500\u2500\u2500 Schema Builder \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\r\nexport {\r\n buildResourceTableSet,\r\n buildAllResourceTableSets,\r\n buildSchemaDefinition,\r\n} from './schema/table-schema-builder.js';\r\n\r\n// \u2500\u2500\u2500 DDL Generator \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\r\nexport {\r\n generateCreateMainTable,\r\n generateCreateHistoryTable,\r\n generateCreateReferencesTable,\r\n generateCreateIndex,\r\n generateResourceDDL,\r\n generateSchemaDDL,\r\n generateSchemaDDLString,\r\n} from './schema/ddl-generator.js';\r\n\r\n// \u2500\u2500\u2500 Repository \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\r\nexport type {\r\n FhirResource,\r\n FhirMeta,\r\n PersistedResource,\r\n ResourceRepository,\r\n CreateResourceOptions,\r\n UpdateResourceOptions,\r\n HistoryOptions,\r\n HistoryEntry,\r\n SearchOptions,\r\n SearchResult,\r\n HistoryBundle,\r\n HistoryBundleEntry,\r\n BuildHistoryBundleOptions,\r\n OperationContext,\r\n} from './repo/index.js';\r\nexport {\r\n SCHEMA_VERSION,\r\n DELETED_SCHEMA_VERSION,\r\n PLATFORM_RESOURCE_TYPES,\r\n PROTECTED_RESOURCE_TYPES,\r\n PROJECT_ADMIN_RESOURCE_TYPES,\r\n} from './repo/index.js';\r\nexport {\r\n RepositoryError,\r\n ResourceNotFoundError,\r\n ResourceGoneError,\r\n ResourceVersionConflictError,\r\n} from './repo/index.js';\r\nexport { buildHistoryBundle } from './repo/index.js';\r\nexport type { SearchColumnValues } from './repo/index.js';\r\nexport {\r\n buildSearchColumns,\r\n buildResourceRowWithSearch,\r\n hashToken,\r\n extractPropertyPath,\r\n getNestedValues,\r\n} from './repo/index.js';\r\n\r\n// \u2500\u2500\u2500 Search \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\r\nexport type {\r\n SearchPrefix,\r\n SearchModifier,\r\n ParsedSearchParam,\r\n SortRule,\r\n SearchRequest,\r\n WhereFragment,\r\n SearchSQL,\r\n CountSQL,\r\n SearchBundle,\r\n SearchBundleEntry,\r\n BuildSearchBundleOptions,\r\n PaginationContext,\r\n} from './search/index.js';\r\nexport {\r\n SEARCH_PREFIXES,\r\n PREFIX_TYPES,\r\n DEFAULT_SEARCH_COUNT,\r\n MAX_SEARCH_COUNT,\r\n parseSearchRequest,\r\n parseParamKey,\r\n splitSearchValues,\r\n extractPrefix,\r\n parseSortParam,\r\n prefixToOperator,\r\n buildSearchBundle,\r\n buildSelfLink,\r\n buildNextLink,\r\n hasNextPage,\r\n buildPaginationContext,\r\n executeSearchV2 as executeSearch,\r\n mapRowsToResourcesV2 as mapRowsToResources,\r\n} from './search/index.js';\r\n\r\n// \u2500\u2500\u2500 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\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\r\nexport type { StorageAdapter, TransactionContext } from './db/adapter.js';\r\nexport { SQLiteAdapter } from './db/sqlite-adapter.js';\r\nexport { BetterSqlite3Adapter } from './db/better-sqlite3-adapter.js';\r\nexport type { BetterSqlite3Options } from './db/better-sqlite3-adapter.js';\r\n\r\n// \u2500\u2500\u2500 FhirStore (basic CRUD) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\r\nexport { FhirStore } from './store/fhir-store.js';\r\n\r\n// \u2500\u2500\u2500 FhirPersistence (end-to-end facade with indexing) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\r\nexport { FhirPersistence } from './store/fhir-persistence.js';\r\nexport type { FhirPersistenceOptions } from './store/fhir-persistence.js';\r\n\r\n// \u2500\u2500\u2500 Indexing Pipeline \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\r\nexport { IndexingPipeline } from './repo/indexing-pipeline.js';\r\nexport type { IndexResult, IndexingPipelineOptions } from './repo/indexing-pipeline.js';\r\n\r\n// \u2500\u2500\u2500 Lookup Table Writer \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\r\nexport { LookupTableWriter } from './repo/lookup-table-writer.js';\r\n\r\n// \u2500\u2500\u2500 Reference Indexer \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\r\nexport type { ReferenceRowV2 } from './repo/reference-indexer.js';\r\nexport { extractReferencesV2 } from './repo/reference-indexer.js';\r\n\r\n// \u2500\u2500\u2500 Lookup Table Rows \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\r\nexport type { LookupTableRow } from './repo/row-indexer.js';\r\nexport { buildLookupTableRows } from './repo/row-indexer.js';\r\n\r\n// \u2500\u2500\u2500 SQL Builders \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\r\nexport {\r\n buildInsertMainSQLv2,\r\n buildUpdateMainSQLv2,\r\n buildInsertHistorySQLv2,\r\n buildSelectByIdSQLv2,\r\n buildSelectVersionSQLv2,\r\n buildDeleteReferencesSQLv2,\r\n buildInsertReferencesSQLv2,\r\n buildInstanceHistorySQLv2,\r\n buildTypeHistorySQLv2,\r\n} from './repo/sql-builder.js';\r\n\r\n// \u2500\u2500\u2500 Migration Engine \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\r\nexport type { SchemaDelta, DeltaKind } from './migration/schema-diff.js';\r\nexport { compareSchemas } from './migration/schema-diff.js';\r\nexport type { GeneratedMigration } from './migration/migration-generator.js';\r\nexport { generateMigration } from './migration/migration-generator.js';\r\nexport { PackageRegistryRepo } from './registry/package-registry-repo.js';\r\nexport { IGPersistenceManager } from './migration/ig-persistence-manager.js';\r\nexport { ReindexScheduler } from './migration/reindex-scheduler.js';\r\nexport { MigrationRunnerV2 } from './migrations/index.js';\r\nexport type { MigrationV2, MigrationResultV2 } from './migrations/index.js';\r\n\r\n// \u2500\u2500\u2500 Terminology \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\r\nexport { TerminologyCodeRepo } from './terminology/terminology-code-repo.js';\r\nexport { ValueSetRepo } from './terminology/valueset-repo.js';\r\n\r\n// \u2500\u2500\u2500 Platform IG \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\r\nexport { PLATFORM_SEARCH_PARAMETERS, PLATFORM_PACKAGE_NAME, PLATFORM_PACKAGE_VERSION } from './platform/platform-ig-definitions.js';\r\nexport { buildPlatformTableSets, initializePlatformIG } from './platform/platform-ig-loader.js';\r\n\r\n// \u2500\u2500\u2500 Search Enhancement \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\r\nexport { buildWhereFragmentV2, buildWhereClauseV2 } from './search/where-builder.js';\r\nexport { buildSearchSQLv2, buildCountSQLv2, buildTwoPhaseSearchSQLv2 } from './search/search-sql-builder.js';\r\nexport type { TwoPhaseSearchSQL } from './search/search-sql-builder.js';\r\nexport type { SearchPlan, SearchPlannerOptions } from './search/search-planner.js';\r\nexport { planSearch } from './search/search-planner.js';\r\n\r\n// \u2500\u2500\u2500 Production Hardening \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\r\nexport { ResourceCacheV2 } from './cache/resource-cache.js';\r\nexport { SearchLogger } from './observability/search-logger.js';\r\nexport { reindexResourceTypeV2, reindexAllV2 } from './cli/reindex.js';\r\n\r\n// \u2500\u2500\u2500 FhirSystem (startup orchestrator for fhir-engine) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\r\nexport { FhirSystem } from './startup/fhir-system.js';\r\nexport type { FhirSystemOptions, FhirSystemReady } from './startup/fhir-system.js';\r\n\r\n// \u2500\u2500\u2500 Provider bridges (for fhir-engine integration) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\r\nexport { FhirDefinitionBridge } from './providers/fhir-definition-provider.js';\r\nexport { FhirRuntimeProvider, createFhirRuntimeProvider } from './providers/fhir-runtime-provider.js';\r\nexport type { FhirRuntimeProviderOptions } from './providers/fhir-runtime-provider.js';", "/**\n * StructureDefinition Registry\n *\n * Indexes `CanonicalProfile[]` by resource type for fast lookup.\n * MedXAI equivalent of Medplum's `indexStructureDefinitionBundle()` \u2192\n * `DATA_TYPES`, but as an injectable instance (no global state).\n *\n * Used by `TableSchemaBuilder` to determine which resource types\n * need tables and to access element definitions for search column\n * generation.\n *\n * @module fhir-persistence/registry\n */\n\n/**\n * Minimal CanonicalProfile shape (replaces @medxai/fhir-core dependency).\n */\nexport interface CanonicalProfile {\n url: string;\n name: string;\n kind: 'resource' | 'complex-type' | 'primitive-type' | 'logical';\n type: string;\n abstract: boolean;\n elements: Map<string, unknown>;\n}\n\n// =============================================================================\n// Section 1: StructureDefinitionRegistry\n// =============================================================================\n\n/**\n * Indexes CanonicalProfile instances by their `type` field for O(1) lookup.\n *\n * ## Usage\n *\n * ```typescript\n * const registry = new StructureDefinitionRegistry();\n * const profiles = loadBundleFromFile('profiles-resources.json').profiles;\n * registry.indexAll(profiles);\n *\n * const patient = registry.get('Patient');\n * const tableTypes = registry.getTableResourceTypes(); // ~140+ types\n * ```\n */\nexport class StructureDefinitionRegistry {\n private readonly profiles = new Map<string, CanonicalProfile>();\n\n /**\n * Index a single CanonicalProfile by its `type` field.\n *\n * If a profile with the same type already exists, it is overwritten\n * (later definitions override earlier ones, matching BundleLoader\n * merge semantics).\n */\n index(profile: CanonicalProfile): void {\n this.profiles.set(profile.type, profile);\n }\n\n /**\n * Index multiple CanonicalProfiles.\n *\n * Profiles are indexed in order; later entries override earlier\n * ones with the same type.\n */\n indexAll(profiles: readonly CanonicalProfile[]): void {\n for (const profile of profiles) {\n this.index(profile);\n }\n }\n\n /**\n * Get a profile by resource type name.\n *\n * @param resourceType - The FHIR resource type (e.g., `'Patient'`).\n * @returns The CanonicalProfile, or `undefined` if not indexed.\n */\n get(resourceType: string): CanonicalProfile | undefined {\n return this.profiles.get(resourceType);\n }\n\n /**\n * Check if a resource type is indexed.\n */\n has(resourceType: string): boolean {\n return this.profiles.has(resourceType);\n }\n\n /**\n * Get all resource types that should have database tables.\n *\n * Returns types where `kind === 'resource'` AND `abstract === false`.\n * This excludes:\n * - Abstract types (Resource, DomainResource)\n * - Complex types (HumanName, Address)\n * - Primitive types (string, boolean)\n * - Logical models\n *\n * Results are sorted alphabetically for deterministic output.\n */\n getTableResourceTypes(): string[] {\n return Array.from(this.profiles.values())\n .filter((p) => p.kind === 'resource' && p.abstract === false)\n .map((p) => p.type)\n .sort();\n }\n\n /**\n * Get all indexed type names (regardless of kind or abstract).\n */\n getAllTypes(): string[] {\n return Array.from(this.profiles.keys()).sort();\n }\n\n /**\n * Get the number of indexed profiles.\n */\n get size(): number {\n return this.profiles.size;\n }\n\n /**\n * Remove all indexed profiles.\n */\n clear(): void {\n this.profiles.clear();\n }\n}\n", "/**\n * FHIR R4 element cardinality map \u2014 auto-generated.\n *\n * Contains element paths where max != \"1\" (i.e., the element is an array).\n * If a path is NOT in this set, it is assumed to be scalar (max = \"1\").\n *\n * Generated from 256 StructureDefinitions, 3119 array paths.\n * DO NOT EDIT MANUALLY \u2014 regenerate with: npx tsx scripts/generate-cardinality-map.ts\n */\n\n/**\n * Set of FHIR element paths that have max cardinality != \"1\".\n * Format: \"ResourceType.property\" or \"ResourceType.backbone.property\"\n */\nexport const ARRAY_ELEMENT_PATHS: ReadonlySet<string> = new Set([\n 'Account',\n 'Account.contained',\n 'Account.coverage',\n 'Account.coverage.extension',\n 'Account.coverage.modifierExtension',\n 'Account.extension',\n 'Account.guarantor',\n 'Account.guarantor.extension',\n 'Account.guarantor.modifierExtension',\n 'Account.identifier',\n 'Account.modifierExtension',\n 'Account.subject',\n 'ActivityDefinition',\n 'ActivityDefinition.author',\n 'ActivityDefinition.bodySite',\n 'ActivityDefinition.contact',\n 'ActivityDefinition.contained',\n 'ActivityDefinition.dosage',\n 'ActivityDefinition.dynamicValue',\n 'ActivityDefinition.dynamicValue.extension',\n 'ActivityDefinition.dynamicValue.modifierExtension',\n 'ActivityDefinition.editor',\n 'ActivityDefinition.endorser',\n 'ActivityDefinition.extension',\n 'ActivityDefinition.identifier',\n 'ActivityDefinition.jurisdiction',\n 'ActivityDefinition.library',\n 'ActivityDefinition.modifierExtension',\n 'ActivityDefinition.observationRequirement',\n 'ActivityDefinition.observationResultRequirement',\n 'ActivityDefinition.participant',\n 'ActivityDefinition.participant.extension',\n 'ActivityDefinition.participant.modifierExtension',\n 'ActivityDefinition.relatedArtifact',\n 'ActivityDefinition.reviewer',\n 'ActivityDefinition.specimenRequirement',\n 'ActivityDefinition.topic',\n 'ActivityDefinition.useContext',\n 'Address',\n 'Address.extension',\n 'Address.line',\n 'AdverseEvent',\n 'AdverseEvent.category',\n 'AdverseEvent.contained',\n 'AdverseEvent.contributor',\n 'AdverseEvent.extension',\n 'AdverseEvent.modifierExtension',\n 'AdverseEvent.referenceDocument',\n 'AdverseEvent.resultingCondition',\n 'AdverseEvent.study',\n 'AdverseEvent.subjectMedicalHistory',\n 'AdverseEvent.suspectEntity',\n 'AdverseEvent.suspectEntity.causality',\n 'AdverseEvent.suspectEntity.causality.extension',\n 'AdverseEvent.suspectEntity.causality.modifierExtension',\n 'AdverseEvent.suspectEntity.extension',\n 'AdverseEvent.suspectEntity.modifierExtension',\n 'Age',\n 'Age.extension',\n 'AllergyIntolerance',\n 'AllergyIntolerance.category',\n 'AllergyIntolerance.contained',\n 'AllergyIntolerance.extension',\n 'AllergyIntolerance.identifier',\n 'AllergyIntolerance.modifierExtension',\n 'AllergyIntolerance.note',\n 'AllergyIntolerance.reaction',\n 'AllergyIntolerance.reaction.extension',\n 'AllergyIntolerance.reaction.manifestation',\n 'AllergyIntolerance.reaction.modifierExtension',\n 'AllergyIntolerance.reaction.note',\n 'Annotation',\n 'Annotation.extension',\n 'Appointment',\n 'Appointment.basedOn',\n 'Appointment.contained',\n 'Appointment.extension',\n 'Appointment.identifier',\n 'Appointment.modifierExtension',\n 'Appointment.participant',\n 'Appointment.participant.extension',\n 'Appointment.participant.modifierExtension',\n 'Appointment.participant.type',\n 'Appointment.reasonCode',\n 'Appointment.reasonReference',\n 'Appointment.requestedPeriod',\n 'Appointment.serviceCategory',\n 'Appointment.serviceType',\n 'Appointment.slot',\n 'Appointment.specialty',\n 'Appointment.supportingInformation',\n 'AppointmentResponse',\n 'AppointmentResponse.contained',\n 'AppointmentResponse.extension',\n 'AppointmentResponse.identifier',\n 'AppointmentResponse.modifierExtension',\n 'AppointmentResponse.participantType',\n 'Attachment',\n 'Attachment.extension',\n 'AuditEvent',\n 'AuditEvent.agent',\n 'AuditEvent.agent.extension',\n 'AuditEvent.agent.modifierExtension',\n 'AuditEvent.agent.network.extension',\n 'AuditEvent.agent.network.modifierExtension',\n 'AuditEvent.agent.policy',\n 'AuditEvent.agent.purposeOfUse',\n 'AuditEvent.agent.role',\n 'AuditEvent.contained',\n 'AuditEvent.entity',\n 'AuditEvent.entity.detail',\n 'AuditEvent.entity.detail.extension',\n 'AuditEvent.entity.detail.modifierExtension',\n 'AuditEvent.entity.extension',\n 'AuditEvent.entity.modifierExtension',\n 'AuditEvent.entity.securityLabel',\n 'AuditEvent.extension',\n 'AuditEvent.modifierExtension',\n 'AuditEvent.purposeOfEvent',\n 'AuditEvent.source.extension',\n 'AuditEvent.source.modifierExtension',\n 'AuditEvent.source.type',\n 'AuditEvent.subtype',\n 'BackboneElement',\n 'BackboneElement.extension',\n 'BackboneElement.modifierExtension',\n 'Basic',\n 'Basic.contained',\n 'Basic.extension',\n 'Basic.identifier',\n 'Basic.modifierExtension',\n 'Binary',\n 'BiologicallyDerivedProduct',\n 'BiologicallyDerivedProduct.collection.extension',\n 'BiologicallyDerivedProduct.collection.modifierExtension',\n 'BiologicallyDerivedProduct.contained',\n 'BiologicallyDerivedProduct.extension',\n 'BiologicallyDerivedProduct.identifier',\n 'BiologicallyDerivedProduct.manipulation.extension',\n 'BiologicallyDerivedProduct.manipulation.modifierExtension',\n 'BiologicallyDerivedProduct.modifierExtension',\n 'BiologicallyDerivedProduct.parent',\n 'BiologicallyDerivedProduct.processing',\n 'BiologicallyDerivedProduct.processing.extension',\n 'BiologicallyDerivedProduct.processing.modifierExtension',\n 'BiologicallyDerivedProduct.request',\n 'BiologicallyDerivedProduct.storage',\n 'BiologicallyDerivedProduct.storage.extension',\n 'BiologicallyDerivedProduct.storage.modifierExtension',\n 'BodyStructure',\n 'BodyStructure.contained',\n 'BodyStructure.extension',\n 'BodyStructure.identifier',\n 'BodyStructure.image',\n 'BodyStructure.locationQualifier',\n 'BodyStructure.modifierExtension',\n 'Bundle',\n 'Bundle.entry',\n 'Bundle.entry.extension',\n 'Bundle.entry.link',\n 'Bundle.entry.modifierExtension',\n 'Bundle.entry.request.extension',\n 'Bundle.entry.request.modifierExtension',\n 'Bundle.entry.response.extension',\n 'Bundle.entry.response.modifierExtension',\n 'Bundle.entry.search.extension',\n 'Bundle.entry.search.modifierExtension',\n 'Bundle.link',\n 'Bundle.link.extension',\n 'Bundle.link.modifierExtension',\n 'CapabilityStatement',\n 'CapabilityStatement.contact',\n 'CapabilityStatement.contained',\n 'CapabilityStatement.document',\n 'CapabilityStatement.document.extension',\n 'CapabilityStatement.document.modifierExtension',\n 'CapabilityStatement.extension',\n 'CapabilityStatement.format',\n 'CapabilityStatement.implementation.extension',\n 'CapabilityStatement.implementation.modifierExtension',\n 'CapabilityStatement.implementationGuide',\n 'CapabilityStatement.imports',\n 'CapabilityStatement.instantiates',\n 'CapabilityStatement.jurisdiction',\n 'CapabilityStatement.messaging',\n 'CapabilityStatement.messaging.endpoint',\n 'CapabilityStatement.messaging.endpoint.extension',\n 'CapabilityStatement.messaging.endpoint.modifierExtension',\n 'CapabilityStatement.messaging.extension',\n 'CapabilityStatement.messaging.modifierExtension',\n 'CapabilityStatement.messaging.supportedMessage',\n 'CapabilityStatement.messaging.supportedMessage.extension',\n 'CapabilityStatement.messaging.supportedMessage.modifierExtension',\n 'CapabilityStatement.modifierExtension',\n 'CapabilityStatement.patchFormat',\n 'CapabilityStatement.rest',\n 'CapabilityStatement.rest.compartment',\n 'CapabilityStatement.rest.extension',\n 'CapabilityStatement.rest.interaction',\n 'CapabilityStatement.rest.interaction.extension',\n 'CapabilityStatement.rest.interaction.modifierExtension',\n 'CapabilityStatement.rest.modifierExtension',\n 'CapabilityStatement.rest.operation',\n 'CapabilityStatement.rest.resource',\n 'CapabilityStatement.rest.resource.extension',\n 'CapabilityStatement.rest.resource.interaction',\n 'CapabilityStatement.rest.resource.interaction.extension',\n 'CapabilityStatement.rest.resource.interaction.modifierExtension',\n 'CapabilityStatement.rest.resource.modifierExtension',\n 'CapabilityStatement.rest.resource.operation',\n 'CapabilityStatement.rest.resource.operation.extension',\n 'CapabilityStatement.rest.resource.operation.modifierExtension',\n 'CapabilityStatement.rest.resource.referencePolicy',\n 'CapabilityStatement.rest.resource.searchInclude',\n 'CapabilityStatement.rest.resource.searchParam',\n 'CapabilityStatement.rest.resource.searchParam.extension',\n 'CapabilityStatement.rest.resource.searchParam.modifierExtension',\n 'CapabilityStatement.rest.resource.searchRevInclude',\n 'CapabilityStatement.rest.resource.supportedProfile',\n 'CapabilityStatement.rest.searchParam',\n 'CapabilityStatement.rest.security.extension',\n 'CapabilityStatement.rest.security.modifierExtension',\n 'CapabilityStatement.rest.security.service',\n 'CapabilityStatement.software.extension',\n 'CapabilityStatement.software.modifierExtension',\n 'CapabilityStatement.useContext',\n 'CarePlan',\n 'CarePlan.activity',\n 'CarePlan.activity.detail.extension',\n 'CarePlan.activity.detail.goal',\n 'CarePlan.activity.detail.instantiatesCanonical',\n 'CarePlan.activity.detail.instantiatesUri',\n 'CarePlan.activity.detail.modifierExtension',\n 'CarePlan.activity.detail.performer',\n 'CarePlan.activity.detail.reasonCode',\n 'CarePlan.activity.detail.reasonReference',\n 'CarePlan.activity.extension',\n 'CarePlan.activity.modifierExtension',\n 'CarePlan.activity.outcomeCodeableConcept',\n 'CarePlan.activity.outcomeReference',\n 'CarePlan.activity.progress',\n 'CarePlan.addresses',\n 'CarePlan.basedOn',\n 'CarePlan.careTeam',\n 'CarePlan.category',\n 'CarePlan.contained',\n 'CarePlan.contributor',\n 'CarePlan.extension',\n 'CarePlan.goal',\n 'CarePlan.identifier',\n 'CarePlan.instantiatesCanonical',\n 'CarePlan.instantiatesUri',\n 'CarePlan.modifierExtension',\n 'CarePlan.note',\n 'CarePlan.partOf',\n 'CarePlan.replaces',\n 'CarePlan.supportingInfo',\n 'CareTeam',\n 'CareTeam.category',\n 'CareTeam.contained',\n 'CareTeam.extension',\n 'CareTeam.identifier',\n 'CareTeam.managingOrganization',\n 'CareTeam.modifierExtension',\n 'CareTeam.note',\n 'CareTeam.participant',\n 'CareTeam.participant.extension',\n 'CareTeam.participant.modifierExtension',\n 'CareTeam.participant.role',\n 'CareTeam.reasonCode',\n 'CareTeam.reasonReference',\n 'CareTeam.telecom',\n 'CatalogEntry',\n 'CatalogEntry.additionalCharacteristic',\n 'CatalogEntry.additionalClassification',\n 'CatalogEntry.additionalIdentifier',\n 'CatalogEntry.classification',\n 'CatalogEntry.contained',\n 'CatalogEntry.extension',\n 'CatalogEntry.identifier',\n 'CatalogEntry.modifierExtension',\n 'CatalogEntry.relatedEntry',\n 'CatalogEntry.relatedEntry.extension',\n 'CatalogEntry.relatedEntry.modifierExtension',\n 'ChargeItem',\n 'ChargeItem.account',\n 'ChargeItem.bodysite',\n 'ChargeItem.contained',\n 'ChargeItem.definitionCanonical',\n 'ChargeItem.definitionUri',\n 'ChargeItem.extension',\n 'ChargeItem.identifier',\n 'ChargeItem.modifierExtension',\n 'ChargeItem.note',\n 'ChargeItem.partOf',\n 'ChargeItem.performer',\n 'ChargeItem.performer.extension',\n 'ChargeItem.performer.modifierExtension',\n 'ChargeItem.reason',\n 'ChargeItem.service',\n 'ChargeItem.supportingInformation',\n 'ChargeItemDefinition',\n 'ChargeItemDefinition.applicability',\n 'ChargeItemDefinition.applicability.extension',\n 'ChargeItemDefinition.applicability.modifierExtension',\n 'ChargeItemDefinition.contact',\n 'ChargeItemDefinition.contained',\n 'ChargeItemDefinition.derivedFromUri',\n 'ChargeItemDefinition.extension',\n 'ChargeItemDefinition.identifier',\n 'ChargeItemDefinition.instance',\n 'ChargeItemDefinition.jurisdiction',\n 'ChargeItemDefinition.modifierExtension',\n 'ChargeItemDefinition.partOf',\n 'ChargeItemDefinition.propertyGroup',\n 'ChargeItemDefinition.propertyGroup.applicability',\n 'ChargeItemDefinition.propertyGroup.extension',\n 'ChargeItemDefinition.propertyGroup.modifierExtension',\n 'ChargeItemDefinition.propertyGroup.priceComponent',\n 'ChargeItemDefinition.propertyGroup.priceComponent.extension',\n 'ChargeItemDefinition.propertyGroup.priceComponent.modifierExtension',\n 'ChargeItemDefinition.replaces',\n 'ChargeItemDefinition.useContext',\n 'Claim',\n 'Claim.accident.extension',\n 'Claim.accident.modifierExtension',\n 'Claim.careTeam',\n 'Claim.careTeam.extension',\n 'Claim.careTeam.modifierExtension',\n 'Claim.contained',\n 'Claim.diagnosis',\n 'Claim.diagnosis.extension',\n 'Claim.diagnosis.modifierExtension',\n 'Claim.diagnosis.type',\n 'Claim.extension',\n 'Claim.identifier',\n 'Claim.insurance',\n 'Claim.insurance.extension',\n 'Claim.insurance.modifierExtension',\n 'Claim.insurance.preAuthRef',\n 'Claim.item',\n 'Claim.item.careTeamSequence',\n 'Claim.item.detail',\n 'Claim.item.detail.extension',\n 'Claim.item.detail.modifier',\n 'Claim.item.detail.modifierExtension',\n 'Claim.item.detail.programCode',\n 'Claim.item.detail.subDetail',\n 'Claim.item.detail.subDetail.extension',\n 'Claim.item.detail.subDetail.modifier',\n 'Claim.item.detail.subDetail.modifierExtension',\n 'Claim.item.detail.subDetail.programCode',\n 'Claim.item.detail.subDetail.udi',\n 'Claim.item.detail.udi',\n 'Claim.item.diagnosisSequence',\n 'Claim.item.encounter',\n 'Claim.item.extension',\n 'Claim.item.informationSequence',\n 'Claim.item.modifier',\n 'Claim.item.modifierExtension',\n 'Claim.item.procedureSequence',\n 'Claim.item.programCode',\n 'Claim.item.subSite',\n 'Claim.item.udi',\n 'Claim.modifierExtension',\n 'Claim.payee.extension',\n 'Claim.payee.modifierExtension',\n 'Claim.procedure',\n 'Claim.procedure.extension',\n 'Claim.procedure.modifierExtension',\n 'Claim.procedure.type',\n 'Claim.procedure.udi',\n 'Claim.related',\n 'Claim.related.extension',\n 'Claim.related.modifierExtension',\n 'Claim.supportingInfo',\n 'Claim.supportingInfo.extension',\n 'Claim.supportingInfo.modifierExtension',\n 'ClaimResponse',\n 'ClaimResponse.addItem',\n 'ClaimResponse.addItem.adjudication',\n 'ClaimResponse.addItem.detail',\n 'ClaimResponse.addItem.detail.adjudication',\n 'ClaimResponse.addItem.detail.extension',\n 'ClaimResponse.addItem.detail.modifier',\n 'ClaimResponse.addItem.detail.modifierExtension',\n 'ClaimResponse.addItem.detail.noteNumber',\n 'ClaimResponse.addItem.detail.subDetail',\n 'ClaimResponse.addItem.detail.subDetail.adjudication',\n 'ClaimResponse.addItem.detail.subDetail.extension',\n 'ClaimResponse.addItem.detail.subDetail.modifier',\n 'ClaimResponse.addItem.detail.subDetail.modifierExtension',\n 'ClaimResponse.addItem.detail.subDetail.noteNumber',\n 'ClaimResponse.addItem.detailSequence',\n 'ClaimResponse.addItem.extension',\n 'ClaimResponse.addItem.itemSequence',\n 'ClaimResponse.addItem.modifier',\n 'ClaimResponse.addItem.modifierExtension',\n 'ClaimResponse.addItem.noteNumber',\n 'ClaimResponse.addItem.programCode',\n 'ClaimResponse.addItem.provider',\n 'ClaimResponse.addItem.subSite',\n 'ClaimResponse.addItem.subdetailSequence',\n 'ClaimResponse.adjudication',\n 'ClaimResponse.communicationRequest',\n 'ClaimResponse.contained',\n 'ClaimResponse.error',\n 'ClaimResponse.error.extension',\n 'ClaimResponse.error.modifierExtension',\n 'ClaimResponse.extension',\n 'ClaimResponse.identifier',\n 'ClaimResponse.insurance',\n 'ClaimResponse.insurance.extension',\n 'ClaimResponse.insurance.modifierExtension',\n 'ClaimResponse.item',\n 'ClaimResponse.item.adjudication',\n 'ClaimResponse.item.adjudication.extension',\n 'ClaimResponse.item.adjudication.modifierExtension',\n 'ClaimResponse.item.detail',\n 'ClaimResponse.item.detail.adjudication',\n 'ClaimResponse.item.detail.extension',\n 'ClaimResponse.item.detail.modifierExtension',\n 'ClaimResponse.item.detail.noteNumber',\n 'ClaimResponse.item.detail.subDetail',\n 'ClaimResponse.item.detail.subDetail.adjudication',\n 'ClaimResponse.item.detail.subDetail.extension',\n 'ClaimResponse.item.detail.subDetail.modifierExtension',\n 'ClaimResponse.item.detail.subDetail.noteNumber',\n 'ClaimResponse.item.extension',\n 'ClaimResponse.item.modifierExtension',\n 'ClaimResponse.item.noteNumber',\n 'ClaimResponse.modifierExtension',\n 'ClaimResponse.payment.extension',\n 'ClaimResponse.payment.modifierExtension',\n 'ClaimResponse.processNote',\n 'ClaimResponse.processNote.extension',\n 'ClaimResponse.processNote.modifierExtension',\n 'ClaimResponse.total',\n 'ClaimResponse.total.extension',\n 'ClaimResponse.total.modifierExtension',\n 'ClinicalImpression',\n 'ClinicalImpression.contained',\n 'ClinicalImpression.extension',\n 'ClinicalImpression.finding',\n 'ClinicalImpression.finding.extension',\n 'ClinicalImpression.finding.modifierExtension',\n 'ClinicalImpression.identifier',\n 'ClinicalImpression.investigation',\n 'ClinicalImpression.investigation.extension',\n 'ClinicalImpression.investigation.item',\n 'ClinicalImpression.investigation.modifierExtension',\n 'ClinicalImpression.modifierExtension',\n 'ClinicalImpression.note',\n 'ClinicalImpression.problem',\n 'ClinicalImpression.prognosisCodeableConcept',\n 'ClinicalImpression.prognosisReference',\n 'ClinicalImpression.protocol',\n 'ClinicalImpression.supportingInfo',\n 'CodeSystem',\n 'CodeSystem.concept',\n 'CodeSystem.concept.concept',\n 'CodeSystem.concept.designation',\n 'CodeSystem.concept.designation.extension',\n 'CodeSystem.concept.designation.modifierExtension',\n 'CodeSystem.concept.extension',\n 'CodeSystem.concept.modifierExtension',\n 'CodeSystem.concept.property',\n 'CodeSystem.concept.property.extension',\n 'CodeSystem.concept.property.modifierExtension',\n 'CodeSystem.contact',\n 'CodeSystem.contained',\n 'CodeSystem.extension',\n 'CodeSystem.filter',\n 'CodeSystem.filter.extension',\n 'CodeSystem.filter.modifierExtension',\n 'CodeSystem.filter.operator',\n 'CodeSystem.identifier',\n 'CodeSystem.jurisdiction',\n 'CodeSystem.modifierExtension',\n 'CodeSystem.property',\n 'CodeSystem.property.extension',\n 'CodeSystem.property.modifierExtension',\n 'CodeSystem.useContext',\n 'CodeableConcept',\n 'CodeableConcept.coding',\n 'CodeableConcept.extension',\n 'Coding',\n 'Coding.extension',\n 'Communication',\n 'Communication.about',\n 'Communication.basedOn',\n 'Communication.category',\n 'Communication.contained',\n 'Communication.extension',\n 'Communication.identifier',\n 'Communication.inResponseTo',\n 'Communication.instantiatesCanonical',\n 'Communication.instantiatesUri',\n 'Communication.medium',\n 'Communication.modifierExtension',\n 'Communication.note',\n 'Communication.partOf',\n 'Communication.payload',\n 'Communication.payload.extension',\n 'Communication.payload.modifierExtension',\n 'Communication.reasonCode',\n 'Communication.reasonReference',\n 'Communication.recipient',\n 'CommunicationRequest',\n 'CommunicationRequest.about',\n 'CommunicationRequest.basedOn',\n 'CommunicationRequest.category',\n 'CommunicationRequest.contained',\n 'CommunicationRequest.extension',\n 'CommunicationRequest.identifier',\n 'CommunicationRequest.medium',\n 'CommunicationRequest.modifierExtension',\n 'CommunicationRequest.note',\n 'CommunicationRequest.payload',\n 'CommunicationRequest.payload.extension',\n 'CommunicationRequest.payload.modifierExtension',\n 'CommunicationRequest.reasonCode',\n 'CommunicationRequest.reasonReference',\n 'CommunicationRequest.recipient',\n 'CommunicationRequest.replaces',\n 'CompartmentDefinition',\n 'CompartmentDefinition.contact',\n 'CompartmentDefinition.contained',\n 'CompartmentDefinition.extension',\n 'CompartmentDefinition.modifierExtension',\n 'CompartmentDefinition.resource',\n 'CompartmentDefinition.resource.extension',\n 'CompartmentDefinition.resource.modifierExtension',\n 'CompartmentDefinition.resource.param',\n 'CompartmentDefinition.useContext',\n 'Composition',\n 'Composition.attester',\n 'Composition.attester.extension',\n 'Composition.attester.modifierExtension',\n 'Composition.author',\n 'Composition.category',\n 'Composition.contained',\n 'Composition.event',\n 'Composition.event.code',\n 'Composition.event.detail',\n 'Composition.event.extension',\n 'Composition.event.modifierExtension',\n 'Composition.extension',\n 'Composition.modifierExtension',\n 'Composition.relatesTo',\n 'Composition.relatesTo.extension',\n 'Composition.relatesTo.modifierExtension',\n 'Composition.section',\n 'Composition.section.author',\n 'Composition.section.entry',\n 'Composition.section.extension',\n 'Composition.section.modifierExtension',\n 'Composition.section.section',\n 'ConceptMap',\n 'ConceptMap.contact',\n 'ConceptMap.contained',\n 'ConceptMap.extension',\n 'ConceptMap.group',\n 'ConceptMap.group.element',\n 'ConceptMap.group.element.extension',\n 'ConceptMap.group.element.modifierExtension',\n 'ConceptMap.group.element.target',\n 'ConceptMap.group.element.target.dependsOn',\n 'ConceptMap.group.element.target.dependsOn.extension',\n 'ConceptMap.group.element.target.dependsOn.modifierExtension',\n 'ConceptMap.group.element.target.extension',\n 'ConceptMap.group.element.target.modifierExtension',\n 'ConceptMap.group.element.target.product',\n 'ConceptMap.group.extension',\n 'ConceptMap.group.modifierExtension',\n 'ConceptMap.group.unmapped.extension',\n 'ConceptMap.group.unmapped.modifierExtension',\n 'ConceptMap.jurisdiction',\n 'ConceptMap.modifierExtension',\n 'ConceptMap.useContext',\n 'Condition',\n 'Condition.bodySite',\n 'Condition.category',\n 'Condition.contained',\n 'Condition.evidence',\n 'Condition.evidence.code',\n 'Condition.evidence.detail',\n 'Condition.evidence.extension',\n 'Condition.evidence.modifierExtension',\n 'Condition.extension',\n 'Condition.identifier',\n 'Condition.modifierExtension',\n 'Condition.note',\n 'Condition.stage',\n 'Condition.stage.assessment',\n 'Condition.stage.extension',\n 'Condition.stage.modifierExtension',\n 'Consent',\n 'Consent.category',\n 'Consent.contained',\n 'Consent.extension',\n 'Consent.identifier',\n 'Consent.modifierExtension',\n 'Consent.organization',\n 'Consent.performer',\n 'Consent.policy',\n 'Consent.policy.extension',\n 'Consent.policy.modifierExtension',\n 'Consent.provision.action',\n 'Consent.provision.actor',\n 'Consent.provision.actor.extension',\n 'Consent.provision.actor.modifierExtension',\n 'Consent.provision.class',\n 'Consent.provision.code',\n 'Consent.provision.data',\n 'Consent.provision.data.extension',\n 'Consent.provision.data.modifierExtension',\n 'Consent.provision.extension',\n 'Consent.provision.modifierExtension',\n 'Consent.provision.provision',\n 'Consent.provision.purpose',\n 'Consent.provision.securityLabel',\n 'Consent.verification',\n 'Consent.verification.extension',\n 'Consent.verification.modifierExtension',\n 'ContactDetail',\n 'ContactDetail.extension',\n 'ContactDetail.telecom',\n 'ContactPoint',\n 'ContactPoint.extension',\n 'Contract',\n 'Contract.alias',\n 'Contract.authority',\n 'Contract.contained',\n 'Contract.contentDefinition.extension',\n 'Contract.contentDefinition.modifierExtension',\n 'Contract.domain',\n 'Contract.extension',\n 'Contract.friendly',\n 'Contract.friendly.extension',\n 'Contract.friendly.modifierExtension',\n 'Contract.identifier',\n 'Contract.legal',\n 'Contract.legal.extension',\n 'Contract.legal.modifierExtension',\n 'Contract.modifierExtension',\n 'Contract.relevantHistory',\n 'Contract.rule',\n 'Contract.rule.extension',\n 'Contract.rule.modifierExtension',\n 'Contract.signer',\n 'Contract.signer.extension',\n 'Contract.signer.modifierExtension',\n 'Contract.signer.signature',\n 'Contract.site',\n 'Contract.subType',\n 'Contract.subject',\n 'Contract.supportingInfo',\n 'Contract.term',\n 'Contract.term.action',\n 'Contract.term.action.contextLinkId',\n 'Contract.term.action.extension',\n 'Contract.term.action.linkId',\n 'Contract.term.action.modifierExtension',\n 'Contract.term.action.note',\n 'Contract.term.action.performerLinkId',\n 'Contract.term.action.performerType',\n 'Contract.term.action.reason',\n 'Contract.term.action.reasonCode',\n 'Contract.term.action.reasonLinkId',\n 'Contract.term.action.reasonReference',\n 'Contract.term.action.requester',\n 'Contract.term.action.requesterLinkId',\n 'Contract.term.action.securityLabelNumber',\n 'Contract.term.action.subject',\n 'Contract.term.action.subject.extension',\n 'Contract.term.action.subject.modifierExtension',\n 'Contract.term.action.subject.reference',\n 'Contract.term.asset',\n 'Contract.term.asset.answer',\n 'Contract.term.asset.context',\n 'Contract.term.asset.context.code',\n 'Contract.term.asset.context.extension',\n 'Contract.term.asset.context.modifierExtension',\n 'Contract.term.asset.extension',\n 'Contract.term.asset.linkId',\n 'Contract.term.asset.modifierExtension',\n 'Contract.term.asset.period',\n 'Contract.term.asset.periodType',\n 'Contract.term.asset.securityLabelNumber',\n 'Contract.term.asset.subtype',\n 'Contract.term.asset.type',\n 'Contract.term.asset.typeReference',\n 'Contract.term.asset.usePeriod',\n 'Contract.term.asset.valuedItem',\n 'Contract.term.asset.valuedItem.extension',\n 'Contract.term.asset.valuedItem.linkId',\n 'Contract.term.asset.valuedItem.modifierExtension',\n 'Contract.term.asset.valuedItem.securityLabelNumber',\n 'Contract.term.extension',\n 'Contract.term.group',\n 'Contract.term.modifierExtension',\n 'Contract.term.offer.answer',\n 'Contract.term.offer.answer.extension',\n 'Contract.term.offer.answer.modifierExtension',\n 'Contract.term.offer.decisionMode',\n 'Contract.term.offer.extension',\n 'Contract.term.offer.identifier',\n 'Contract.term.offer.linkId',\n 'Contract.term.offer.modifierExtension',\n 'Contract.term.offer.party',\n 'Contract.term.offer.party.extension',\n 'Contract.term.offer.party.modifierExtension',\n 'Contract.term.offer.party.reference',\n 'Contract.term.offer.securityLabelNumber',\n 'Contract.term.securityLabel',\n 'Contract.term.securityLabel.category',\n 'Contract.term.securityLabel.control',\n 'Contract.term.securityLabel.extension',\n 'Contract.term.securityLabel.modifierExtension',\n 'Contract.term.securityLabel.number',\n 'Contributor',\n 'Contributor.contact',\n 'Contributor.extension',\n 'Count',\n 'Count.extension',\n 'Coverage',\n 'Coverage.class',\n 'Coverage.class.extension',\n 'Coverage.class.modifierExtension',\n 'Coverage.contained',\n 'Coverage.contract',\n 'Coverage.costToBeneficiary',\n 'Coverage.costToBeneficiary.exception',\n 'Coverage.costToBeneficiary.exception.extension',\n 'Coverage.costToBeneficiary.exception.modifierExtension',\n 'Coverage.costToBeneficiary.extension',\n 'Coverage.costToBeneficiary.modifierExtension',\n 'Coverage.extension',\n 'Coverage.identifier',\n 'Coverage.modifierExtension',\n 'Coverage.payor',\n 'CoverageEligibilityRequest',\n 'CoverageEligibilityRequest.contained',\n 'CoverageEligibilityRequest.extension',\n 'CoverageEligibilityRequest.identifier',\n 'CoverageEligibilityRequest.insurance',\n 'CoverageEligibilityRequest.insurance.extension',\n 'CoverageEligibilityRequest.insurance.modifierExtension',\n 'CoverageEligibilityRequest.item',\n 'CoverageEligibilityRequest.item.detail',\n 'CoverageEligibilityRequest.item.diagnosis',\n 'CoverageEligibilityRequest.item.diagnosis.extension',\n 'CoverageEligibilityRequest.item.diagnosis.modifierExtension',\n 'CoverageEligibilityRequest.item.extension',\n 'CoverageEligibilityRequest.item.modifier',\n 'CoverageEligibilityRequest.item.modifierExtension',\n 'CoverageEligibilityRequest.item.supportingInfoSequence',\n 'CoverageEligibilityRequest.modifierExtension',\n 'CoverageEligibilityRequest.purpose',\n 'CoverageEligibilityRequest.supportingInfo',\n 'CoverageEligibilityRequest.supportingInfo.extension',\n 'CoverageEligibilityRequest.supportingInfo.modifierExtension',\n 'CoverageEligibilityResponse',\n 'CoverageEligibilityResponse.contained',\n 'CoverageEligibilityResponse.error',\n 'CoverageEligibilityResponse.error.extension',\n 'CoverageEligibilityResponse.error.modifierExtension',\n 'CoverageEligibilityResponse.extension',\n 'CoverageEligibilityResponse.identifier',\n 'CoverageEligibilityResponse.insurance',\n 'CoverageEligibilityResponse.insurance.extension',\n 'CoverageEligibilityResponse.insurance.item',\n 'CoverageEligibilityResponse.insurance.item.authorizationSupporting',\n 'CoverageEligibilityResponse.insurance.item.benefit',\n 'CoverageEligibilityResponse.insurance.item.benefit.extension',\n 'CoverageEligibilityResponse.insurance.item.benefit.modifierExtension',\n 'CoverageEligibilityResponse.insurance.item.extension',\n 'CoverageEligibilityResponse.insurance.item.modifier',\n 'CoverageEligibilityResponse.insurance.item.modifierExtension',\n 'CoverageEligibilityResponse.insurance.modifierExtension',\n 'CoverageEligibilityResponse.modifierExtension',\n 'CoverageEligibilityResponse.purpose',\n 'DataRequirement',\n 'DataRequirement.codeFilter',\n 'DataRequirement.codeFilter.code',\n 'DataRequirement.codeFilter.extension',\n 'DataRequirement.dateFilter',\n 'DataRequirement.dateFilter.extension',\n 'DataRequirement.extension',\n 'DataRequirement.mustSupport',\n 'DataRequirement.profile',\n 'DataRequirement.sort',\n 'DataRequirement.sort.extension',\n 'DetectedIssue',\n 'DetectedIssue.contained',\n 'DetectedIssue.evidence',\n 'DetectedIssue.evidence.code',\n 'DetectedIssue.evidence.detail',\n 'DetectedIssue.evidence.extension',\n 'DetectedIssue.evidence.modifierExtension',\n 'DetectedIssue.extension',\n 'DetectedIssue.identifier',\n 'DetectedIssue.implicated',\n 'DetectedIssue.mitigation',\n 'DetectedIssue.mitigation.extension',\n 'DetectedIssue.mitigation.modifierExtension',\n 'DetectedIssue.modifierExtension',\n 'Device',\n 'Device.contact',\n 'Device.contained',\n 'Device.deviceName',\n 'Device.deviceName.extension',\n 'Device.deviceName.modifierExtension',\n 'Device.extension',\n 'Device.identifier',\n 'Device.modifierExtension',\n 'Device.note',\n 'Device.property',\n 'Device.property.extension',\n 'Device.property.modifierExtension',\n 'Device.property.valueCode',\n 'Device.property.valueQuantity',\n 'Device.safety',\n 'Device.specialization',\n 'Device.specialization.extension',\n 'Device.specialization.modifierExtension',\n 'Device.statusReason',\n 'Device.udiCarrier',\n 'Device.udiCarrier.extension',\n 'Device.udiCarrier.modifierExtension',\n 'Device.version',\n 'Device.version.extension',\n 'Device.version.modifierExtension',\n 'DeviceDefinition',\n 'DeviceDefinition.capability',\n 'DeviceDefinition.capability.description',\n 'DeviceDefinition.capability.extension',\n 'DeviceDefinition.capability.modifierExtension',\n 'DeviceDefinition.contact',\n 'DeviceDefinition.contained',\n 'DeviceDefinition.deviceName',\n 'DeviceDefinition.deviceName.extension',\n 'DeviceDefinition.deviceName.modifierExtension',\n 'DeviceDefinition.extension',\n 'DeviceDefinition.identifier',\n 'DeviceDefinition.languageCode',\n 'DeviceDefinition.material',\n 'DeviceDefinition.material.extension',\n 'DeviceDefinition.material.modifierExtension',\n 'DeviceDefinition.modifierExtension',\n 'DeviceDefinition.note',\n 'DeviceDefinition.property',\n 'DeviceDefinition.property.extension',\n 'DeviceDefinition.property.modifierExtension',\n 'DeviceDefinition.property.valueCode',\n 'DeviceDefinition.property.valueQuantity',\n 'DeviceDefinition.safety',\n 'DeviceDefinition.shelfLifeStorage',\n 'DeviceDefinition.specialization',\n 'DeviceDefinition.specialization.extension',\n 'DeviceDefinition.specialization.modifierExtension',\n 'DeviceDefinition.udiDeviceIdentifier',\n 'DeviceDefinition.udiDeviceIdentifier.extension',\n 'DeviceDefinition.udiDeviceIdentifier.modifierExtension',\n 'DeviceDefinition.version',\n 'DeviceMetric',\n 'DeviceMetric.calibration',\n 'DeviceMetric.calibration.extension',\n 'DeviceMetric.calibration.modifierExtension',\n 'DeviceMetric.contained',\n 'DeviceMetric.extension',\n 'DeviceMetric.identifier',\n 'DeviceMetric.modifierExtension',\n 'DeviceRequest',\n 'DeviceRequest.basedOn',\n 'DeviceRequest.contained',\n 'DeviceRequest.extension',\n 'DeviceRequest.identifier',\n 'DeviceRequest.instantiatesCanonical',\n 'DeviceRequest.instantiatesUri',\n 'DeviceRequest.insurance',\n 'DeviceRequest.modifierExtension',\n 'DeviceRequest.note',\n 'DeviceRequest.parameter',\n 'DeviceRequest.parameter.extension',\n 'DeviceRequest.parameter.modifierExtension',\n 'DeviceRequest.priorRequest',\n 'DeviceRequest.reasonCode',\n 'DeviceRequest.reasonReference',\n 'DeviceRequest.relevantHistory',\n 'DeviceRequest.supportingInfo',\n 'DeviceUseStatement',\n 'DeviceUseStatement.basedOn',\n 'DeviceUseStatement.contained',\n 'DeviceUseStatement.derivedFrom',\n 'DeviceUseStatement.extension',\n 'DeviceUseStatement.identifier',\n 'DeviceUseStatement.modifierExtension',\n 'DeviceUseStatement.note',\n 'DeviceUseStatement.reasonCode',\n 'DeviceUseStatement.reasonReference',\n 'DiagnosticReport',\n 'DiagnosticReport.basedOn',\n 'DiagnosticReport.category',\n 'DiagnosticReport.conclusionCode',\n 'DiagnosticReport.contained',\n 'DiagnosticReport.extension',\n 'DiagnosticReport.identifier',\n 'DiagnosticReport.imagingStudy',\n 'DiagnosticReport.media',\n 'DiagnosticReport.media.extension',\n 'DiagnosticReport.media.modifierExtension',\n 'DiagnosticReport.modifierExtension',\n 'DiagnosticReport.performer',\n 'DiagnosticReport.presentedForm',\n 'DiagnosticReport.result',\n 'DiagnosticReport.resultsInterpreter',\n 'DiagnosticReport.specimen',\n 'Distance',\n 'Distance.extension',\n 'DocumentManifest',\n 'DocumentManifest.author',\n 'DocumentManifest.contained',\n 'DocumentManifest.content',\n 'DocumentManifest.extension',\n 'DocumentManifest.identifier',\n 'DocumentManifest.modifierExtension',\n 'DocumentManifest.recipient',\n 'DocumentManifest.related',\n 'DocumentManifest.related.extension',\n 'DocumentManifest.related.modifierExtension',\n 'DocumentReference',\n 'DocumentReference.author',\n 'DocumentReference.category',\n 'DocumentReference.contained',\n 'DocumentReference.content',\n 'DocumentReference.content.extension',\n 'DocumentReference.content.modifierExtension',\n 'DocumentReference.context.encounter',\n 'DocumentReference.context.event',\n 'DocumentReference.context.extension',\n 'DocumentReference.context.modifierExtension',\n 'DocumentReference.context.related',\n 'DocumentReference.extension',\n 'DocumentReference.identifier',\n 'DocumentReference.modifierExtension',\n 'DocumentReference.relatesTo',\n 'DocumentReference.relatesTo.extension',\n 'DocumentReference.relatesTo.modifierExtension',\n 'DocumentReference.securityLabel',\n 'DomainResource',\n 'DomainResource.contained',\n 'DomainResource.extension',\n 'DomainResource.modifierExtension',\n 'Dosage',\n 'Dosage.additionalInstruction',\n 'Dosage.doseAndRate',\n 'Dosage.doseAndRate.extension',\n 'Dosage.extension',\n 'Dosage.modifierExtension',\n 'Duration',\n 'Duration.extension',\n 'EffectEvidenceSynthesis',\n 'EffectEvidenceSynthesis.author',\n 'EffectEvidenceSynthesis.certainty',\n 'EffectEvidenceSynthesis.certainty.certaintySubcomponent',\n 'EffectEvidenceSynthesis.certainty.certaintySubcomponent.extension',\n 'EffectEvidenceSynthesis.certainty.certaintySubcomponent.modifierExtension',\n 'EffectEvidenceSynthesis.certainty.certaintySubcomponent.note',\n 'EffectEvidenceSynthesis.certainty.certaintySubcomponent.rating',\n 'EffectEvidenceSynthesis.certainty.extension',\n 'EffectEvidenceSynthesis.certainty.modifierExtension',\n 'EffectEvidenceSynthesis.certainty.note',\n 'EffectEvidenceSynthesis.certainty.rating',\n 'EffectEvidenceSynthesis.contact',\n 'EffectEvidenceSynthesis.contained',\n 'EffectEvidenceSynthesis.editor',\n 'EffectEvidenceSynthesis.effectEstimate',\n 'EffectEvidenceSynthesis.effectEstimate.extension',\n 'EffectEvidenceSynthesis.effectEstimate.modifierExtension',\n 'EffectEvidenceSynthesis.effectEstimate.precisionEstimate',\n 'EffectEvidenceSynthesis.effectEstimate.precisionEstimate.extension',\n 'EffectEvidenceSynthesis.effectEstimate.precisionEstimate.modifierExtension',\n 'EffectEvidenceSynthesis.endorser',\n 'EffectEvidenceSynthesis.extension',\n 'EffectEvidenceSynthesis.identifier',\n 'EffectEvidenceSynthesis.jurisdiction',\n 'EffectEvidenceSynthesis.modifierExtension',\n 'EffectEvidenceSynthesis.note',\n 'EffectEvidenceSynthesis.relatedArtifact',\n 'EffectEvidenceSynthesis.resultsByExposure',\n 'EffectEvidenceSynthesis.resultsByExposure.extension',\n 'EffectEvidenceSynthesis.resultsByExposure.modifierExtension',\n 'EffectEvidenceSynthesis.reviewer',\n 'EffectEvidenceSynthesis.sampleSize.extension',\n 'EffectEvidenceSynthesis.sampleSize.modifierExtension',\n 'EffectEvidenceSynthesis.topic',\n 'EffectEvidenceSynthesis.useContext',\n 'Element',\n 'Element.extension',\n 'ElementDefinition',\n 'ElementDefinition.alias',\n 'ElementDefinition.base.extension',\n 'ElementDefinition.binding.extension',\n 'ElementDefinition.code',\n 'ElementDefinition.condition',\n 'ElementDefinition.constraint',\n 'ElementDefinition.constraint.extension',\n 'ElementDefinition.example',\n 'ElementDefinition.example.extension',\n 'ElementDefinition.extension',\n 'ElementDefinition.mapping',\n 'ElementDefinition.mapping.extension',\n 'ElementDefinition.modifierExtension',\n 'ElementDefinition.representation',\n 'ElementDefinition.slicing.discriminator',\n 'ElementDefinition.slicing.discriminator.extension',\n 'ElementDefinition.slicing.extension',\n 'ElementDefinition.type',\n 'ElementDefinition.type.aggregation',\n 'ElementDefinition.type.extension',\n 'ElementDefinition.type.profile',\n 'ElementDefinition.type.targetProfile',\n 'Encounter',\n 'Encounter.account',\n 'Encounter.appointment',\n 'Encounter.basedOn',\n 'Encounter.classHistory',\n 'Encounter.classHistory.extension',\n 'Encounter.classHistory.modifierExtension',\n 'Encounter.contained',\n 'Encounter.diagnosis',\n 'Encounter.diagnosis.extension',\n 'Encounter.diagnosis.modifierExtension',\n 'Encounter.episodeOfCare',\n 'Encounter.extension',\n 'Encounter.hospitalization.dietPreference',\n 'Encounter.hospitalization.extension',\n 'Encounter.hospitalization.modifierExtension',\n 'Encounter.hospitalization.specialArrangement',\n 'Encounter.hospitalization.specialCourtesy',\n 'Encounter.identifier',\n 'Encounter.location',\n 'Encounter.location.extension',\n 'Encounter.location.modifierExtension',\n 'Encounter.modifierExtension',\n 'Encounter.participant',\n 'Encounter.participant.extension',\n 'Encounter.participant.modifierExtension',\n 'Encounter.participant.type',\n 'Encounter.reasonCode',\n 'Encounter.reasonReference',\n 'Encounter.statusHistory',\n 'Encounter.statusHistory.extension',\n 'Encounter.statusHistory.modifierExtension',\n 'Encounter.type',\n 'Endpoint',\n 'Endpoint.contact',\n 'Endpoint.contained',\n 'Endpoint.extension',\n 'Endpoint.header',\n 'Endpoint.identifier',\n 'Endpoint.modifierExtension',\n 'Endpoint.payloadMimeType',\n 'Endpoint.payloadType',\n 'EnrollmentRequest',\n 'EnrollmentRequest.contained',\n 'EnrollmentRequest.extension',\n 'EnrollmentRequest.identifier',\n 'EnrollmentRequest.modifierExtension',\n 'EnrollmentResponse',\n 'EnrollmentResponse.contained',\n 'EnrollmentResponse.extension',\n 'EnrollmentResponse.identifier',\n 'EnrollmentResponse.modifierExtension',\n 'EpisodeOfCare',\n 'EpisodeOfCare.account',\n 'EpisodeOfCare.contained',\n 'EpisodeOfCare.diagnosis',\n 'EpisodeOfCare.diagnosis.extension',\n 'EpisodeOfCare.diagnosis.modifierExtension',\n 'EpisodeOfCare.extension',\n 'EpisodeOfCare.identifier',\n 'EpisodeOfCare.modifierExtension',\n 'EpisodeOfCare.referralRequest',\n 'EpisodeOfCare.statusHistory',\n 'EpisodeOfCare.statusHistory.extension',\n 'EpisodeOfCare.statusHistory.modifierExtension',\n 'EpisodeOfCare.team',\n 'EpisodeOfCare.type',\n 'EventDefinition',\n 'EventDefinition.author',\n 'EventDefinition.contact',\n 'EventDefinition.contained',\n 'EventDefinition.editor',\n 'EventDefinition.endorser',\n 'EventDefinition.extension',\n 'EventDefinition.identifier',\n 'EventDefinition.jurisdiction',\n 'EventDefinition.modifierExtension',\n 'EventDefinition.relatedArtifact',\n 'EventDefinition.reviewer',\n 'EventDefinition.topic',\n 'EventDefinition.trigger',\n 'EventDefinition.useContext',\n 'Evidence',\n 'Evidence.author',\n 'Evidence.contact',\n 'Evidence.contained',\n 'Evidence.editor',\n 'Evidence.endorser',\n 'Evidence.exposureVariant',\n 'Evidence.extension',\n 'Evidence.identifier',\n 'Evidence.jurisdiction',\n 'Evidence.modifierExtension',\n 'Evidence.note',\n 'Evidence.outcome',\n 'Evidence.relatedArtifact',\n 'Evidence.reviewer',\n 'Evidence.topic',\n 'Evidence.useContext',\n 'EvidenceVariable',\n 'EvidenceVariable.author',\n 'EvidenceVariable.characteristic',\n 'EvidenceVariable.characteristic.extension',\n 'EvidenceVariable.characteristic.modifierExtension',\n 'EvidenceVariable.characteristic.usageContext',\n 'EvidenceVariable.contact',\n 'EvidenceVariable.contained',\n 'EvidenceVariable.editor',\n 'EvidenceVariable.endorser',\n 'EvidenceVariable.extension',\n 'EvidenceVariable.identifier',\n 'EvidenceVariable.jurisdiction',\n 'EvidenceVariable.modifierExtension',\n 'EvidenceVariable.note',\n 'EvidenceVariable.relatedArtifact',\n 'EvidenceVariable.reviewer',\n 'EvidenceVariable.topic',\n 'EvidenceVariable.useContext',\n 'ExampleScenario',\n 'ExampleScenario.actor',\n 'ExampleScenario.actor.extension',\n 'ExampleScenario.actor.modifierExtension',\n 'ExampleScenario.contact',\n 'ExampleScenario.contained',\n 'ExampleScenario.extension',\n 'ExampleScenario.identifier',\n 'ExampleScenario.instance',\n 'ExampleScenario.instance.containedInstance',\n 'ExampleScenario.instance.containedInstance.extension',\n 'ExampleScenario.instance.containedInstance.modifierExtension',\n 'ExampleScenario.instance.extension',\n 'ExampleScenario.instance.modifierExtension',\n 'ExampleScenario.instance.version',\n 'ExampleScenario.instance.version.extension',\n 'ExampleScenario.instance.version.modifierExtension',\n 'ExampleScenario.jurisdiction',\n 'ExampleScenario.modifierExtension',\n 'ExampleScenario.process',\n 'ExampleScenario.process.extension',\n 'ExampleScenario.process.modifierExtension',\n 'ExampleScenario.process.step',\n 'ExampleScenario.process.step.alternative',\n 'ExampleScenario.process.step.alternative.extension',\n 'ExampleScenario.process.step.alternative.modifierExtension',\n 'ExampleScenario.process.step.alternative.step',\n 'ExampleScenario.process.step.extension',\n 'ExampleScenario.process.step.modifierExtension',\n 'ExampleScenario.process.step.operation.extension',\n 'ExampleScenario.process.step.operation.modifierExtension',\n 'ExampleScenario.process.step.process',\n 'ExampleScenario.useContext',\n 'ExampleScenario.workflow',\n 'ExplanationOfBenefit',\n 'ExplanationOfBenefit.accident.extension',\n 'ExplanationOfBenefit.accident.modifierExtension',\n 'ExplanationOfBenefit.addItem',\n 'ExplanationOfBenefit.addItem.adjudication',\n 'ExplanationOfBenefit.addItem.detail',\n 'ExplanationOfBenefit.addItem.detail.adjudication',\n 'ExplanationOfBenefit.addItem.detail.extension',\n 'ExplanationOfBenefit.addItem.detail.modifier',\n 'ExplanationOfBenefit.addItem.detail.modifierExtension',\n 'ExplanationOfBenefit.addItem.detail.noteNumber',\n 'ExplanationOfBenefit.addItem.detail.subDetail',\n 'ExplanationOfBenefit.addItem.detail.subDetail.adjudication',\n 'ExplanationOfBenefit.addItem.detail.subDetail.extension',\n 'ExplanationOfBenefit.addItem.detail.subDetail.modifier',\n 'ExplanationOfBenefit.addItem.detail.subDetail.modifierExtension',\n 'ExplanationOfBenefit.addItem.detail.subDetail.noteNumber',\n 'ExplanationOfBenefit.addItem.detailSequence',\n 'ExplanationOfBenefit.addItem.extension',\n 'ExplanationOfBenefit.addItem.itemSequence',\n 'ExplanationOfBenefit.addItem.modifier',\n 'ExplanationOfBenefit.addItem.modifierExtension',\n 'ExplanationOfBenefit.addItem.noteNumber',\n 'ExplanationOfBenefit.addItem.programCode',\n 'ExplanationOfBenefit.addItem.provider',\n 'ExplanationOfBenefit.addItem.subDetailSequence',\n 'ExplanationOfBenefit.addItem.subSite',\n 'ExplanationOfBenefit.adjudication',\n 'ExplanationOfBenefit.benefitBalance',\n 'ExplanationOfBenefit.benefitBalance.extension',\n 'ExplanationOfBenefit.benefitBalance.financial',\n 'ExplanationOfBenefit.benefitBalance.financial.extension',\n 'ExplanationOfBenefit.benefitBalance.financial.modifierExtension',\n 'ExplanationOfBenefit.benefitBalance.modifierExtension',\n 'ExplanationOfBenefit.careTeam',\n 'ExplanationOfBenefit.careTeam.extension',\n 'ExplanationOfBenefit.careTeam.modifierExtension',\n 'ExplanationOfBenefit.contained',\n 'ExplanationOfBenefit.diagnosis',\n 'ExplanationOfBenefit.diagnosis.extension',\n 'ExplanationOfBenefit.diagnosis.modifierExtension',\n 'ExplanationOfBenefit.diagnosis.type',\n 'ExplanationOfBenefit.extension',\n 'ExplanationOfBenefit.identifier',\n 'ExplanationOfBenefit.insurance',\n 'ExplanationOfBenefit.insurance.extension',\n 'ExplanationOfBenefit.insurance.modifierExtension',\n 'ExplanationOfBenefit.insurance.preAuthRef',\n 'ExplanationOfBenefit.item',\n 'ExplanationOfBenefit.item.adjudication',\n 'ExplanationOfBenefit.item.adjudication.extension',\n 'ExplanationOfBenefit.item.adjudication.modifierExtension',\n 'ExplanationOfBenefit.item.careTeamSequence',\n 'ExplanationOfBenefit.item.detail',\n 'ExplanationOfBenefit.item.detail.adjudication',\n 'ExplanationOfBenefit.item.detail.extension',\n 'ExplanationOfBenefit.item.detail.modifier',\n 'ExplanationOfBenefit.item.detail.modifierExtension',\n 'ExplanationOfBenefit.item.detail.noteNumber',\n 'ExplanationOfBenefit.item.detail.programCode',\n 'ExplanationOfBenefit.item.detail.subDetail',\n 'ExplanationOfBenefit.item.detail.subDetail.adjudication',\n 'ExplanationOfBenefit.item.detail.subDetail.extension',\n 'ExplanationOfBenefit.item.detail.subDetail.modifier',\n 'ExplanationOfBenefit.item.detail.subDetail.modifierExtension',\n 'ExplanationOfBenefit.item.detail.subDetail.noteNumber',\n 'ExplanationOfBenefit.item.detail.subDetail.programCode',\n 'ExplanationOfBenefit.item.detail.subDetail.udi',\n 'ExplanationOfBenefit.item.detail.udi',\n 'ExplanationOfBenefit.item.diagnosisSequence',\n 'ExplanationOfBenefit.item.encounter',\n 'ExplanationOfBenefit.item.extension',\n 'ExplanationOfBenefit.item.informationSequence',\n 'ExplanationOfBenefit.item.modifier',\n 'ExplanationOfBenefit.item.modifierExtension',\n 'ExplanationOfBenefit.item.noteNumber',\n 'ExplanationOfBenefit.item.procedureSequence',\n 'ExplanationOfBenefit.item.programCode',\n 'ExplanationOfBenefit.item.subSite',\n 'ExplanationOfBenefit.item.udi',\n 'ExplanationOfBenefit.modifierExtension',\n 'ExplanationOfBenefit.payee.extension',\n 'ExplanationOfBenefit.payee.modifierExtension',\n 'ExplanationOfBenefit.payment.extension',\n 'ExplanationOfBenefit.payment.modifierExtension',\n 'ExplanationOfBenefit.preAuthRef',\n 'ExplanationOfBenefit.preAuthRefPeriod',\n 'ExplanationOfBenefit.procedure',\n 'ExplanationOfBenefit.procedure.extension',\n 'ExplanationOfBenefit.procedure.modifierExtension',\n 'ExplanationOfBenefit.procedure.type',\n 'ExplanationOfBenefit.procedure.udi',\n 'ExplanationOfBenefit.processNote',\n 'ExplanationOfBenefit.processNote.extension',\n 'ExplanationOfBenefit.processNote.modifierExtension',\n 'ExplanationOfBenefit.related',\n 'ExplanationOfBenefit.related.extension',\n 'ExplanationOfBenefit.related.modifierExtension',\n 'ExplanationOfBenefit.supportingInfo',\n 'ExplanationOfBenefit.supportingInfo.extension',\n 'ExplanationOfBenefit.supportingInfo.modifierExtension',\n 'ExplanationOfBenefit.total',\n 'ExplanationOfBenefit.total.extension',\n 'ExplanationOfBenefit.total.modifierExtension',\n 'Expression',\n 'Expression.extension',\n 'Extension',\n 'Extension.extension',\n 'FamilyMemberHistory',\n 'FamilyMemberHistory.condition',\n 'FamilyMemberHistory.condition.extension',\n 'FamilyMemberHistory.condition.modifierExtension',\n 'FamilyMemberHistory.condition.note',\n 'FamilyMemberHistory.contained',\n 'FamilyMemberHistory.extension',\n 'FamilyMemberHistory.identifier',\n 'FamilyMemberHistory.instantiatesCanonical',\n 'FamilyMemberHistory.instantiatesUri',\n 'FamilyMemberHistory.modifierExtension',\n 'FamilyMemberHistory.note',\n 'FamilyMemberHistory.reasonCode',\n 'FamilyMemberHistory.reasonReference',\n 'Flag',\n 'Flag.category',\n 'Flag.contained',\n 'Flag.extension',\n 'Flag.identifier',\n 'Flag.modifierExtension',\n 'Goal',\n 'Goal.addresses',\n 'Goal.category',\n 'Goal.contained',\n 'Goal.extension',\n 'Goal.identifier',\n 'Goal.modifierExtension',\n 'Goal.note',\n 'Goal.outcomeCode',\n 'Goal.outcomeReference',\n 'Goal.target',\n 'Goal.target.extension',\n 'Goal.target.modifierExtension',\n 'GraphDefinition',\n 'GraphDefinition.contact',\n 'GraphDefinition.contained',\n 'GraphDefinition.extension',\n 'GraphDefinition.jurisdiction',\n 'GraphDefinition.link',\n 'GraphDefinition.link.extension',\n 'GraphDefinition.link.modifierExtension',\n 'GraphDefinition.link.target',\n 'GraphDefinition.link.target.compartment',\n 'GraphDefinition.link.target.compartment.extension',\n 'GraphDefinition.link.target.compartment.modifierExtension',\n 'GraphDefinition.link.target.extension',\n 'GraphDefinition.link.target.link',\n 'GraphDefinition.link.target.modifierExtension',\n 'GraphDefinition.modifierExtension',\n 'GraphDefinition.useContext',\n 'Group',\n 'Group.characteristic',\n 'Group.characteristic.extension',\n 'Group.characteristic.modifierExtension',\n 'Group.contained',\n 'Group.extension',\n 'Group.identifier',\n 'Group.member',\n 'Group.member.extension',\n 'Group.member.modifierExtension',\n 'Group.modifierExtension',\n 'GuidanceResponse',\n 'GuidanceResponse.contained',\n 'GuidanceResponse.dataRequirement',\n 'GuidanceResponse.evaluationMessage',\n 'GuidanceResponse.extension',\n 'GuidanceResponse.identifier',\n 'GuidanceResponse.modifierExtension',\n 'GuidanceResponse.note',\n 'GuidanceResponse.reasonCode',\n 'GuidanceResponse.reasonReference',\n 'HealthcareService',\n 'HealthcareService.availableTime',\n 'HealthcareService.availableTime.daysOfWeek',\n 'HealthcareService.availableTime.extension',\n 'HealthcareService.availableTime.modifierExtension',\n 'HealthcareService.category',\n 'HealthcareService.characteristic',\n 'HealthcareService.communication',\n 'HealthcareService.contained',\n 'HealthcareService.coverageArea',\n 'HealthcareService.eligibility',\n 'HealthcareService.eligibility.extension',\n 'HealthcareService.eligibility.modifierExtension',\n 'HealthcareService.endpoint',\n 'HealthcareService.extension',\n 'HealthcareService.identifier',\n 'HealthcareService.location',\n 'HealthcareService.modifierExtension',\n 'HealthcareService.notAvailable',\n 'HealthcareService.notAvailable.extension',\n 'HealthcareService.notAvailable.modifierExtension',\n 'HealthcareService.program',\n 'HealthcareService.referralMethod',\n 'HealthcareService.serviceProvisionCode',\n 'HealthcareService.specialty',\n 'HealthcareService.telecom',\n 'HealthcareService.type',\n 'HumanName',\n 'HumanName.extension',\n 'HumanName.given',\n 'HumanName.prefix',\n 'HumanName.suffix',\n 'Identifier',\n 'Identifier.extension',\n 'ImagingStudy',\n 'ImagingStudy.basedOn',\n 'ImagingStudy.contained',\n 'ImagingStudy.endpoint',\n 'ImagingStudy.extension',\n 'ImagingStudy.identifier',\n 'ImagingStudy.interpreter',\n 'ImagingStudy.modality',\n 'ImagingStudy.modifierExtension',\n 'ImagingStudy.note',\n 'ImagingStudy.procedureCode',\n 'ImagingStudy.reasonCode',\n 'ImagingStudy.reasonReference',\n 'ImagingStudy.series',\n 'ImagingStudy.series.endpoint',\n 'ImagingStudy.series.extension',\n 'ImagingStudy.series.instance',\n 'ImagingStudy.series.instance.extension',\n 'ImagingStudy.series.instance.modifierExtension',\n 'ImagingStudy.series.modifierExtension',\n 'ImagingStudy.series.performer',\n 'ImagingStudy.series.performer.extension',\n 'ImagingStudy.series.performer.modifierExtension',\n 'ImagingStudy.series.specimen',\n 'Immunization',\n 'Immunization.contained',\n 'Immunization.education',\n 'Immunization.education.extension',\n 'Immunization.education.modifierExtension',\n 'Immunization.extension',\n 'Immunization.identifier',\n 'Immunization.modifierExtension',\n 'Immunization.note',\n 'Immunization.performer',\n 'Immunization.performer.extension',\n 'Immunization.performer.modifierExtension',\n 'Immunization.programEligibility',\n 'Immunization.protocolApplied',\n 'Immunization.protocolApplied.extension',\n 'Immunization.protocolApplied.modifierExtension',\n 'Immunization.protocolApplied.targetDisease',\n 'Immunization.reaction',\n 'Immunization.reaction.extension',\n 'Immunization.reaction.modifierExtension',\n 'Immunization.reasonCode',\n 'Immunization.reasonReference',\n 'Immunization.subpotentReason',\n 'ImmunizationEvaluation',\n 'ImmunizationEvaluation.contained',\n 'ImmunizationEvaluation.doseStatusReason',\n 'ImmunizationEvaluation.extension',\n 'ImmunizationEvaluation.identifier',\n 'ImmunizationEvaluation.modifierExtension',\n 'ImmunizationRecommendation',\n 'ImmunizationRecommendation.contained',\n 'ImmunizationRecommendation.extension',\n 'ImmunizationRecommendation.identifier',\n 'ImmunizationRecommendation.modifierExtension',\n 'ImmunizationRecommendation.recommendation',\n 'ImmunizationRecommendation.recommendation.contraindicatedVaccineCode',\n 'ImmunizationRecommendation.recommendation.dateCriterion',\n 'ImmunizationRecommendation.recommendation.dateCriterion.extension',\n 'ImmunizationRecommendation.recommendation.dateCriterion.modifierExtension',\n 'ImmunizationRecommendation.recommendation.extension',\n 'ImmunizationRecommendation.recommendation.forecastReason',\n 'ImmunizationRecommendation.recommendation.modifierExtension',\n 'ImmunizationRecommendation.recommendation.supportingImmunization',\n 'ImmunizationRecommendation.recommendation.supportingPatientInformation',\n 'ImmunizationRecommendation.recommendation.vaccineCode',\n 'ImplementationGuide',\n 'ImplementationGuide.contact',\n 'ImplementationGuide.contained',\n 'ImplementationGuide.definition.extension',\n 'ImplementationGuide.definition.grouping',\n 'ImplementationGuide.definition.grouping.extension',\n 'ImplementationGuide.definition.grouping.modifierExtension',\n 'ImplementationGuide.definition.modifierExtension',\n 'ImplementationGuide.definition.page.extension',\n 'ImplementationGuide.definition.page.modifierExtension',\n 'ImplementationGuide.definition.page.page',\n 'ImplementationGuide.definition.parameter',\n 'ImplementationGuide.definition.parameter.extension',\n 'ImplementationGuide.definition.parameter.modifierExtension',\n 'ImplementationGuide.definition.resource',\n 'ImplementationGuide.definition.resource.extension',\n 'ImplementationGuide.definition.resource.fhirVersion',\n 'ImplementationGuide.definition.resource.modifierExtension',\n 'ImplementationGuide.definition.template',\n 'ImplementationGuide.definition.template.extension',\n 'ImplementationGuide.definition.template.modifierExtension',\n 'ImplementationGuide.dependsOn',\n 'ImplementationGuide.dependsOn.extension',\n 'ImplementationGuide.dependsOn.modifierExtension',\n 'ImplementationGuide.extension',\n 'ImplementationGuide.fhirVersion',\n 'ImplementationGuide.global',\n 'ImplementationGuide.global.extension',\n 'ImplementationGuide.global.modifierExtension',\n 'ImplementationGuide.jurisdiction',\n 'ImplementationGuide.manifest.extension',\n 'ImplementationGuide.manifest.image',\n 'ImplementationGuide.manifest.modifierExtension',\n 'ImplementationGuide.manifest.other',\n 'ImplementationGuide.manifest.page',\n 'ImplementationGuide.manifest.page.anchor',\n 'ImplementationGuide.manifest.page.extension',\n 'ImplementationGuide.manifest.page.modifierExtension',\n 'ImplementationGuide.manifest.resource',\n 'ImplementationGuide.manifest.resource.extension',\n 'ImplementationGuide.manifest.resource.modifierExtension',\n 'ImplementationGuide.modifierExtension',\n 'ImplementationGuide.useContext',\n 'InsurancePlan',\n 'InsurancePlan.alias',\n 'InsurancePlan.contact',\n 'InsurancePlan.contact.extension',\n 'InsurancePlan.contact.modifierExtension',\n 'InsurancePlan.contact.telecom',\n 'InsurancePlan.contained',\n 'InsurancePlan.coverage',\n 'InsurancePlan.coverage.benefit',\n 'InsurancePlan.coverage.benefit.extension',\n 'InsurancePlan.coverage.benefit.limit',\n 'InsurancePlan.coverage.benefit.limit.extension',\n 'InsurancePlan.coverage.benefit.limit.modifierExtension',\n 'InsurancePlan.coverage.benefit.modifierExtension',\n 'InsurancePlan.coverage.extension',\n 'InsurancePlan.coverage.modifierExtension',\n 'InsurancePlan.coverage.network',\n 'InsurancePlan.coverageArea',\n 'InsurancePlan.endpoint',\n 'InsurancePlan.extension',\n 'InsurancePlan.identifier',\n 'InsurancePlan.modifierExtension',\n 'InsurancePlan.network',\n 'InsurancePlan.plan',\n 'InsurancePlan.plan.coverageArea',\n 'InsurancePlan.plan.extension',\n 'InsurancePlan.plan.generalCost',\n 'InsurancePlan.plan.generalCost.extension',\n 'InsurancePlan.plan.generalCost.modifierExtension',\n 'InsurancePlan.plan.identifier',\n 'InsurancePlan.plan.modifierExtension',\n 'InsurancePlan.plan.network',\n 'InsurancePlan.plan.specificCost',\n 'InsurancePlan.plan.specificCost.benefit',\n 'InsurancePlan.plan.specificCost.benefit.cost',\n 'InsurancePlan.plan.specificCost.benefit.cost.extension',\n 'InsurancePlan.plan.specificCost.benefit.cost.modifierExtension',\n 'InsurancePlan.plan.specificCost.benefit.cost.qualifiers',\n 'InsurancePlan.plan.specificCost.benefit.extension',\n 'InsurancePlan.plan.specificCost.benefit.modifierExtension',\n 'InsurancePlan.plan.specificCost.extension',\n 'InsurancePlan.plan.specificCost.modifierExtension',\n 'InsurancePlan.type',\n 'Invoice',\n 'Invoice.contained',\n 'Invoice.extension',\n 'Invoice.identifier',\n 'Invoice.lineItem',\n 'Invoice.lineItem.extension',\n 'Invoice.lineItem.modifierExtension',\n 'Invoice.lineItem.priceComponent',\n 'Invoice.lineItem.priceComponent.extension',\n 'Invoice.lineItem.priceComponent.modifierExtension',\n 'Invoice.modifierExtension',\n 'Invoice.note',\n 'Invoice.participant',\n 'Invoice.participant.extension',\n 'Invoice.participant.modifierExtension',\n 'Invoice.totalPriceComponent',\n 'Library',\n 'Library.author',\n 'Library.contact',\n 'Library.contained',\n 'Library.content',\n 'Library.dataRequirement',\n 'Library.editor',\n 'Library.endorser',\n 'Library.extension',\n 'Library.identifier',\n 'Library.jurisdiction',\n 'Library.modifierExtension',\n 'Library.parameter',\n 'Library.relatedArtifact',\n 'Library.reviewer',\n 'Library.topic',\n 'Library.useContext',\n 'Linkage',\n 'Linkage.contained',\n 'Linkage.extension',\n 'Linkage.item',\n 'Linkage.item.extension',\n 'Linkage.item.modifierExtension',\n 'Linkage.modifierExtension',\n 'List',\n 'List.contained',\n 'List.entry',\n 'List.entry.extension',\n 'List.entry.modifierExtension',\n 'List.extension',\n 'List.identifier',\n 'List.modifierExtension',\n 'List.note',\n 'Location',\n 'Location.alias',\n 'Location.contained',\n 'Location.endpoint',\n 'Location.extension',\n 'Location.hoursOfOperation',\n 'Location.hoursOfOperation.daysOfWeek',\n 'Location.hoursOfOperation.extension',\n 'Location.hoursOfOperation.modifierExtension',\n 'Location.identifier',\n 'Location.modifierExtension',\n 'Location.position.extension',\n 'Location.position.modifierExtension',\n 'Location.telecom',\n 'Location.type',\n 'MarketingStatus',\n 'MarketingStatus.extension',\n 'MarketingStatus.modifierExtension',\n 'Measure',\n 'Measure.author',\n 'Measure.contact',\n 'Measure.contained',\n 'Measure.definition',\n 'Measure.editor',\n 'Measure.endorser',\n 'Measure.extension',\n 'Measure.group',\n 'Measure.group.extension',\n 'Measure.group.modifierExtension',\n 'Measure.group.population',\n 'Measure.group.population.extension',\n 'Measure.group.population.modifierExtension',\n 'Measure.group.stratifier',\n 'Measure.group.stratifier.component',\n 'Measure.group.stratifier.component.extension',\n 'Measure.group.stratifier.component.modifierExtension',\n 'Measure.group.stratifier.extension',\n 'Measure.group.stratifier.modifierExtension',\n 'Measure.identifier',\n 'Measure.jurisdiction',\n 'Measure.library',\n 'Measure.modifierExtension',\n 'Measure.relatedArtifact',\n 'Measure.reviewer',\n 'Measure.supplementalData',\n 'Measure.supplementalData.extension',\n 'Measure.supplementalData.modifierExtension',\n 'Measure.supplementalData.usage',\n 'Measure.topic',\n 'Measure.type',\n 'Measure.useContext',\n 'MeasureReport',\n 'MeasureReport.contained',\n 'MeasureReport.evaluatedResource',\n 'MeasureReport.extension',\n 'MeasureReport.group',\n 'MeasureReport.group.extension',\n 'MeasureReport.group.modifierExtension',\n 'MeasureReport.group.population',\n 'MeasureReport.group.population.extension',\n 'MeasureReport.group.population.modifierExtension',\n 'MeasureReport.group.stratifier',\n 'MeasureReport.group.stratifier.code',\n 'MeasureReport.group.stratifier.extension',\n 'MeasureReport.group.stratifier.modifierExtension',\n 'MeasureReport.group.stratifier.stratum',\n 'MeasureReport.group.stratifier.stratum.component',\n 'MeasureReport.group.stratifier.stratum.component.extension',\n 'MeasureReport.group.stratifier.stratum.component.modifierExtension',\n 'MeasureReport.group.stratifier.stratum.extension',\n 'MeasureReport.group.stratifier.stratum.modifierExtension',\n 'MeasureReport.group.stratifier.stratum.population',\n 'MeasureReport.group.stratifier.stratum.population.extension',\n 'MeasureReport.group.stratifier.stratum.population.modifierExtension',\n 'MeasureReport.identifier',\n 'MeasureReport.modifierExtension',\n 'Media',\n 'Media.basedOn',\n 'Media.contained',\n 'Media.extension',\n 'Media.identifier',\n 'Media.modifierExtension',\n 'Media.note',\n 'Media.partOf',\n 'Media.reasonCode',\n 'Medication',\n 'Medication.batch.extension',\n 'Medication.batch.modifierExtension',\n 'Medication.contained',\n 'Medication.extension',\n 'Medication.identifier',\n 'Medication.ingredient',\n 'Medication.ingredient.extension',\n 'Medication.ingredient.modifierExtension',\n 'Medication.modifierExtension',\n 'MedicationAdministration',\n 'MedicationAdministration.contained',\n 'MedicationAdministration.device',\n 'MedicationAdministration.dosage.extension',\n 'MedicationAdministration.dosage.modifierExtension',\n 'MedicationAdministration.eventHistory',\n 'MedicationAdministration.extension',\n 'MedicationAdministration.identifier',\n 'MedicationAdministration.instantiates',\n 'MedicationAdministration.modifierExtension',\n 'MedicationAdministration.note',\n 'MedicationAdministration.partOf',\n 'MedicationAdministration.performer',\n 'MedicationAdministration.performer.extension',\n 'MedicationAdministration.performer.modifierExtension',\n 'MedicationAdministration.reasonCode',\n 'MedicationAdministration.reasonReference',\n 'MedicationAdministration.statusReason',\n 'MedicationAdministration.supportingInformation',\n 'MedicationDispense',\n 'MedicationDispense.authorizingPrescription',\n 'MedicationDispense.contained',\n 'MedicationDispense.detectedIssue',\n 'MedicationDispense.dosageInstruction',\n 'MedicationDispense.eventHistory',\n 'MedicationDispense.extension',\n 'MedicationDispense.identifier',\n 'MedicationDispense.modifierExtension',\n 'MedicationDispense.note',\n 'MedicationDispense.partOf',\n 'MedicationDispense.performer',\n 'MedicationDispense.performer.extension',\n 'MedicationDispense.performer.modifierExtension',\n 'MedicationDispense.receiver',\n 'MedicationDispense.substitution.extension',\n 'MedicationDispense.substitution.modifierExtension',\n 'MedicationDispense.substitution.reason',\n 'MedicationDispense.substitution.responsibleParty',\n 'MedicationDispense.supportingInformation',\n 'MedicationKnowledge',\n 'MedicationKnowledge.administrationGuidelines',\n 'MedicationKnowledge.administrationGuidelines.dosage',\n 'MedicationKnowledge.administrationGuidelines.dosage.dosage',\n 'MedicationKnowledge.administrationGuidelines.dosage.extension',\n 'MedicationKnowledge.administrationGuidelines.dosage.modifierExtension',\n 'MedicationKnowledge.administrationGuidelines.extension',\n 'MedicationKnowledge.administrationGuidelines.modifierExtension',\n 'MedicationKnowledge.administrationGuidelines.patientCharacteristics',\n 'MedicationKnowledge.administrationGuidelines.patientCharacteristics.extension',\n 'MedicationKnowledge.administrationGuidelines.patientCharacteristics.modifierExtension',\n 'MedicationKnowledge.administrationGuidelines.patientCharacteristics.value',\n 'MedicationKnowledge.associatedMedication',\n 'MedicationKnowledge.contained',\n 'MedicationKnowledge.contraindication',\n 'MedicationKnowledge.cost',\n 'MedicationKnowledge.cost.extension',\n 'MedicationKnowledge.cost.modifierExtension',\n 'MedicationKnowledge.drugCharacteristic',\n 'MedicationKnowledge.drugCharacteristic.extension',\n 'MedicationKnowledge.drugCharacteristic.modifierExtension',\n 'MedicationKnowledge.extension',\n 'MedicationKnowledge.ingredient',\n 'MedicationKnowledge.ingredient.extension',\n 'MedicationKnowledge.ingredient.modifierExtension',\n 'MedicationKnowledge.intendedRoute',\n 'MedicationKnowledge.kinetics',\n 'MedicationKnowledge.kinetics.areaUnderCurve',\n 'MedicationKnowledge.kinetics.extension',\n 'MedicationKnowledge.kinetics.lethalDose50',\n 'MedicationKnowledge.kinetics.modifierExtension',\n 'MedicationKnowledge.medicineClassification',\n 'MedicationKnowledge.medicineClassification.classification',\n 'MedicationKnowledge.medicineClassification.extension',\n 'MedicationKnowledge.medicineClassification.modifierExtension',\n 'MedicationKnowledge.modifierExtension',\n 'MedicationKnowledge.monitoringProgram',\n 'MedicationKnowledge.monitoringProgram.extension',\n 'MedicationKnowledge.monitoringProgram.modifierExtension',\n 'MedicationKnowledge.monograph',\n 'MedicationKnowledge.monograph.extension',\n 'MedicationKnowledge.monograph.modifierExtension',\n 'MedicationKnowledge.packaging.extension',\n 'MedicationKnowledge.packaging.modifierExtension',\n 'MedicationKnowledge.productType',\n 'MedicationKnowledge.regulatory',\n 'MedicationKnowledge.regulatory.extension',\n 'MedicationKnowledge.regulatory.maxDispense.extension',\n 'MedicationKnowledge.regulatory.maxDispense.modifierExtension',\n 'MedicationKnowledge.regulatory.modifierExtension',\n 'MedicationKnowledge.regulatory.schedule',\n 'MedicationKnowledge.regulatory.schedule.extension',\n 'MedicationKnowledge.regulatory.schedule.modifierExtension',\n 'MedicationKnowledge.regulatory.substitution',\n 'MedicationKnowledge.regulatory.substitution.extension',\n 'MedicationKnowledge.regulatory.substitution.modifierExtension',\n 'MedicationKnowledge.relatedMedicationKnowledge',\n 'MedicationKnowledge.relatedMedicationKnowledge.extension',\n 'MedicationKnowledge.relatedMedicationKnowledge.modifierExtension',\n 'MedicationKnowledge.relatedMedicationKnowledge.reference',\n 'MedicationKnowledge.synonym',\n 'MedicationRequest',\n 'MedicationRequest.basedOn',\n 'MedicationRequest.category',\n 'MedicationRequest.contained',\n 'MedicationRequest.detectedIssue',\n 'MedicationRequest.dispenseRequest.extension',\n 'MedicationRequest.dispenseRequest.initialFill.extension',\n 'MedicationRequest.dispenseRequest.initialFill.modifierExtension',\n 'MedicationRequest.dispenseRequest.modifierExtension',\n 'MedicationRequest.dosageInstruction',\n 'MedicationRequest.eventHistory',\n 'MedicationRequest.extension',\n 'MedicationRequest.identifier',\n 'MedicationRequest.instantiatesCanonical',\n 'MedicationRequest.instantiatesUri',\n 'MedicationRequest.insurance',\n 'MedicationRequest.modifierExtension',\n 'MedicationRequest.note',\n 'MedicationRequest.reasonCode',\n 'MedicationRequest.reasonReference',\n 'MedicationRequest.substitution.extension',\n 'MedicationRequest.substitution.modifierExtension',\n 'MedicationRequest.supportingInformation',\n 'MedicationStatement',\n 'MedicationStatement.basedOn',\n 'MedicationStatement.contained',\n 'MedicationStatement.derivedFrom',\n 'MedicationStatement.dosage',\n 'MedicationStatement.extension',\n 'MedicationStatement.identifier',\n 'MedicationStatement.modifierExtension',\n 'MedicationStatement.note',\n 'MedicationStatement.partOf',\n 'MedicationStatement.reasonCode',\n 'MedicationStatement.reasonReference',\n 'MedicationStatement.statusReason',\n 'MedicinalProduct',\n 'MedicinalProduct.attachedDocument',\n 'MedicinalProduct.clinicalTrial',\n 'MedicinalProduct.contact',\n 'MedicinalProduct.contained',\n 'MedicinalProduct.crossReference',\n 'MedicinalProduct.extension',\n 'MedicinalProduct.identifier',\n 'MedicinalProduct.manufacturingBusinessOperation',\n 'MedicinalProduct.manufacturingBusinessOperation.extension',\n 'MedicinalProduct.manufacturingBusinessOperation.manufacturer',\n 'MedicinalProduct.manufacturingBusinessOperation.modifierExtension',\n 'MedicinalProduct.marketingStatus',\n 'MedicinalProduct.masterFile',\n 'MedicinalProduct.modifierExtension',\n 'MedicinalProduct.name',\n 'MedicinalProduct.name.countryLanguage',\n 'MedicinalProduct.name.countryLanguage.extension',\n 'MedicinalProduct.name.countryLanguage.modifierExtension',\n 'MedicinalProduct.name.extension',\n 'MedicinalProduct.name.modifierExtension',\n 'MedicinalProduct.name.namePart',\n 'MedicinalProduct.name.namePart.extension',\n 'MedicinalProduct.name.namePart.modifierExtension',\n 'MedicinalProduct.packagedMedicinalProduct',\n 'MedicinalProduct.pharmaceuticalProduct',\n 'MedicinalProduct.productClassification',\n 'MedicinalProduct.specialDesignation',\n 'MedicinalProduct.specialDesignation.extension',\n 'MedicinalProduct.specialDesignation.identifier',\n 'MedicinalProduct.specialDesignation.modifierExtension',\n 'MedicinalProduct.specialMeasures',\n 'MedicinalProductAuthorization',\n 'MedicinalProductAuthorization.contained',\n 'MedicinalProductAuthorization.country',\n 'MedicinalProductAuthorization.extension',\n 'MedicinalProductAuthorization.identifier',\n 'MedicinalProductAuthorization.jurisdiction',\n 'MedicinalProductAuthorization.jurisdictionalAuthorization',\n 'MedicinalProductAuthorization.jurisdictionalAuthorization.extension',\n 'MedicinalProductAuthorization.jurisdictionalAuthorization.identifier',\n 'MedicinalProductAuthorization.jurisdictionalAuthorization.jurisdiction',\n 'MedicinalProductAuthorization.jurisdictionalAuthorization.modifierExtension',\n 'MedicinalProductAuthorization.modifierExtension',\n 'MedicinalProductAuthorization.procedure.application',\n 'MedicinalProductAuthorization.procedure.extension',\n 'MedicinalProductAuthorization.procedure.modifierExtension',\n 'MedicinalProductContraindication',\n 'MedicinalProductContraindication.comorbidity',\n 'MedicinalProductContraindication.contained',\n 'MedicinalProductContraindication.extension',\n 'MedicinalProductContraindication.modifierExtension',\n 'MedicinalProductContraindication.otherTherapy',\n 'MedicinalProductContraindication.otherTherapy.extension',\n 'MedicinalProductContraindication.otherTherapy.modifierExtension',\n 'MedicinalProductContraindication.population',\n 'MedicinalProductContraindication.subject',\n 'MedicinalProductContraindication.therapeuticIndication',\n 'MedicinalProductIndication',\n 'MedicinalProductIndication.comorbidity',\n 'MedicinalProductIndication.contained',\n 'MedicinalProductIndication.extension',\n 'MedicinalProductIndication.modifierExtension',\n 'MedicinalProductIndication.otherTherapy',\n 'MedicinalProductIndication.otherTherapy.extension',\n 'MedicinalProductIndication.otherTherapy.modifierExtension',\n 'MedicinalProductIndication.population',\n 'MedicinalProductIndication.subject',\n 'MedicinalProductIndication.undesirableEffect',\n 'MedicinalProductIngredient',\n 'MedicinalProductIngredient.contained',\n 'MedicinalProductIngredient.extension',\n 'MedicinalProductIngredient.manufacturer',\n 'MedicinalProductIngredient.modifierExtension',\n 'MedicinalProductIngredient.specifiedSubstance',\n 'MedicinalProductIngredient.specifiedSubstance.extension',\n 'MedicinalProductIngredient.specifiedSubstance.modifierExtension',\n 'MedicinalProductIngredient.specifiedSubstance.strength',\n 'MedicinalProductIngredient.specifiedSubstance.strength.country',\n 'MedicinalProductIngredient.specifiedSubstance.strength.extension',\n 'MedicinalProductIngredient.specifiedSubstance.strength.modifierExtension',\n 'MedicinalProductIngredient.specifiedSubstance.strength.referenceStrength',\n 'MedicinalProductIngredient.specifiedSubstance.strength.referenceStrength.country',\n 'MedicinalProductIngredient.specifiedSubstance.strength.referenceStrength.extension',\n 'MedicinalProductIngredient.specifiedSubstance.strength.referenceStrength.modifierExtension',\n 'MedicinalProductIngredient.substance.extension',\n 'MedicinalProductIngredient.substance.modifierExtension',\n 'MedicinalProductIngredient.substance.strength',\n 'MedicinalProductInteraction',\n 'MedicinalProductInteraction.contained',\n 'MedicinalProductInteraction.extension',\n 'MedicinalProductInteraction.interactant',\n 'MedicinalProductInteraction.interactant.extension',\n 'MedicinalProductInteraction.interactant.modifierExtension',\n 'MedicinalProductInteraction.modifierExtension',\n 'MedicinalProductInteraction.subject',\n 'MedicinalProductManufactured',\n 'MedicinalProductManufactured.contained',\n 'MedicinalProductManufactured.extension',\n 'MedicinalProductManufactured.ingredient',\n 'MedicinalProductManufactured.manufacturer',\n 'MedicinalProductManufactured.modifierExtension',\n 'MedicinalProductManufactured.otherCharacteristics',\n 'MedicinalProductPackaged',\n 'MedicinalProductPackaged.batchIdentifier',\n 'MedicinalProductPackaged.batchIdentifier.extension',\n 'MedicinalProductPackaged.batchIdentifier.modifierExtension',\n 'MedicinalProductPackaged.contained',\n 'MedicinalProductPackaged.extension',\n 'MedicinalProductPackaged.identifier',\n 'MedicinalProductPackaged.manufacturer',\n 'MedicinalProductPackaged.marketingStatus',\n 'MedicinalProductPackaged.modifierExtension',\n 'MedicinalProductPackaged.packageItem',\n 'MedicinalProductPackaged.packageItem.alternateMaterial',\n 'MedicinalProductPackaged.packageItem.device',\n 'MedicinalProductPackaged.packageItem.extension',\n 'MedicinalProductPackaged.packageItem.identifier',\n 'MedicinalProductPackaged.packageItem.manufacturedItem',\n 'MedicinalProductPackaged.packageItem.manufacturer',\n 'MedicinalProductPackaged.packageItem.material',\n 'MedicinalProductPackaged.packageItem.modifierExtension',\n 'MedicinalProductPackaged.packageItem.otherCharacteristics',\n 'MedicinalProductPackaged.packageItem.packageItem',\n 'MedicinalProductPackaged.packageItem.shelfLifeStorage',\n 'MedicinalProductPackaged.subject',\n 'MedicinalProductPharmaceutical',\n 'MedicinalProductPharmaceutical.characteristics',\n 'MedicinalProductPharmaceutical.characteristics.extension',\n 'MedicinalProductPharmaceutical.characteristics.modifierExtension',\n 'MedicinalProductPharmaceutical.contained',\n 'MedicinalProductPharmaceutical.device',\n 'MedicinalProductPharmaceutical.extension',\n 'MedicinalProductPharmaceutical.identifier',\n 'MedicinalProductPharmaceutical.ingredient',\n 'MedicinalProductPharmaceutical.modifierExtension',\n 'MedicinalProductPharmaceutical.routeOfAdministration',\n 'MedicinalProductPharmaceutical.routeOfAdministration.extension',\n 'MedicinalProductPharmaceutical.routeOfAdministration.modifierExtension',\n 'MedicinalProductPharmaceutical.routeOfAdministration.targetSpecies',\n 'MedicinalProductPharmaceutical.routeOfAdministration.targetSpecies.extension',\n 'MedicinalProductPharmaceutical.routeOfAdministration.targetSpecies.modifierExtension',\n 'MedicinalProductPharmaceutical.routeOfAdministration.targetSpecies.withdrawalPeriod',\n 'MedicinalProductPharmaceutical.routeOfAdministration.targetSpecies.withdrawalPeriod.extension',\n 'MedicinalProductPharmaceutical.routeOfAdministration.targetSpecies.withdrawalPeriod.modifierExtension',\n 'MedicinalProductUndesirableEffect',\n 'MedicinalProductUndesirableEffect.contained',\n 'MedicinalProductUndesirableEffect.extension',\n 'MedicinalProductUndesirableEffect.modifierExtension',\n 'MedicinalProductUndesirableEffect.population',\n 'MedicinalProductUndesirableEffect.subject',\n 'MessageDefinition',\n 'MessageDefinition.allowedResponse',\n 'MessageDefinition.allowedResponse.extension',\n 'MessageDefinition.allowedResponse.modifierExtension',\n 'MessageDefinition.contact',\n 'MessageDefinition.contained',\n 'MessageDefinition.extension',\n 'MessageDefinition.focus',\n 'MessageDefinition.focus.extension',\n 'MessageDefinition.focus.modifierExtension',\n 'MessageDefinition.graph',\n 'MessageDefinition.identifier',\n 'MessageDefinition.jurisdiction',\n 'MessageDefinition.modifierExtension',\n 'MessageDefinition.parent',\n 'MessageDefinition.replaces',\n 'MessageDefinition.useContext',\n 'MessageHeader',\n 'MessageHeader.contained',\n 'MessageHeader.destination',\n 'MessageHeader.destination.extension',\n 'MessageHeader.destination.modifierExtension',\n 'MessageHeader.extension',\n 'MessageHeader.focus',\n 'MessageHeader.modifierExtension',\n 'MessageHeader.response.extension',\n 'MessageHeader.response.modifierExtension',\n 'MessageHeader.source.extension',\n 'MessageHeader.source.modifierExtension',\n 'Meta',\n 'Meta.extension',\n 'Meta.profile',\n 'Meta.security',\n 'Meta.tag',\n 'MolecularSequence',\n 'MolecularSequence.contained',\n 'MolecularSequence.extension',\n 'MolecularSequence.identifier',\n 'MolecularSequence.modifierExtension',\n 'MolecularSequence.pointer',\n 'MolecularSequence.quality',\n 'MolecularSequence.quality.extension',\n 'MolecularSequence.quality.modifierExtension',\n 'MolecularSequence.quality.roc.extension',\n 'MolecularSequence.quality.roc.fMeasure',\n 'MolecularSequence.quality.roc.modifierExtension',\n 'MolecularSequence.quality.roc.numFN',\n 'MolecularSequence.quality.roc.numFP',\n 'MolecularSequence.quality.roc.numTP',\n 'MolecularSequence.quality.roc.precision',\n 'MolecularSequence.quality.roc.score',\n 'MolecularSequence.quality.roc.sensitivity',\n 'MolecularSequence.referenceSeq.extension',\n 'MolecularSequence.referenceSeq.modifierExtension',\n 'MolecularSequence.repository',\n 'MolecularSequence.repository.extension',\n 'MolecularSequence.repository.modifierExtension',\n 'MolecularSequence.structureVariant',\n 'MolecularSequence.structureVariant.extension',\n 'MolecularSequence.structureVariant.inner.extension',\n 'MolecularSequence.structureVariant.inner.modifierExtension',\n 'MolecularSequence.structureVariant.modifierExtension',\n 'MolecularSequence.structureVariant.outer.extension',\n 'MolecularSequence.structureVariant.outer.modifierExtension',\n 'MolecularSequence.variant',\n 'MolecularSequence.variant.extension',\n 'MolecularSequence.variant.modifierExtension',\n 'Money',\n 'Money.extension',\n 'NamingSystem',\n 'NamingSystem.contact',\n 'NamingSystem.contained',\n 'NamingSystem.extension',\n 'NamingSystem.jurisdiction',\n 'NamingSystem.modifierExtension',\n 'NamingSystem.uniqueId',\n 'NamingSystem.uniqueId.extension',\n 'NamingSystem.uniqueId.modifierExtension',\n 'NamingSystem.useContext',\n 'Narrative',\n 'Narrative.extension',\n 'NutritionOrder',\n 'NutritionOrder.allergyIntolerance',\n 'NutritionOrder.contained',\n 'NutritionOrder.enteralFormula.administration',\n 'NutritionOrder.enteralFormula.administration.extension',\n 'NutritionOrder.enteralFormula.administration.modifierExtension',\n 'NutritionOrder.enteralFormula.extension',\n 'NutritionOrder.enteralFormula.modifierExtension',\n 'NutritionOrder.excludeFoodModifier',\n 'NutritionOrder.extension',\n 'NutritionOrder.foodPreferenceModifier',\n 'NutritionOrder.identifier',\n 'NutritionOrder.instantiates',\n 'NutritionOrder.instantiatesCanonical',\n 'NutritionOrder.instantiatesUri',\n 'NutritionOrder.modifierExtension',\n 'NutritionOrder.note',\n 'NutritionOrder.oralDiet.extension',\n 'NutritionOrder.oralDiet.fluidConsistencyType',\n 'NutritionOrder.oralDiet.modifierExtension',\n 'NutritionOrder.oralDiet.nutrient',\n 'NutritionOrder.oralDiet.nutrient.extension',\n 'NutritionOrder.oralDiet.nutrient.modifierExtension',\n 'NutritionOrder.oralDiet.schedule',\n 'NutritionOrder.oralDiet.texture',\n 'NutritionOrder.oralDiet.texture.extension',\n 'NutritionOrder.oralDiet.texture.modifierExtension',\n 'NutritionOrder.oralDiet.type',\n 'NutritionOrder.supplement',\n 'NutritionOrder.supplement.extension',\n 'NutritionOrder.supplement.modifierExtension',\n 'NutritionOrder.supplement.schedule',\n 'Observation',\n 'Observation.basedOn',\n 'Observation.category',\n 'Observation.category.coding',\n 'Observation.category.coding.extension',\n 'Observation.category.extension',\n 'Observation.code.coding',\n 'Observation.code.coding.extension',\n 'Observation.code.extension',\n 'Observation.component',\n 'Observation.component.code.coding',\n 'Observation.component.code.coding.extension',\n 'Observation.component.code.extension',\n 'Observation.component.extension',\n 'Observation.component.interpretation',\n 'Observation.component.modifierExtension',\n 'Observation.component.referenceRange',\n 'Observation.component.value[x].extension',\n 'Observation.contained',\n 'Observation.derivedFrom',\n 'Observation.extension',\n 'Observation.focus',\n 'Observation.hasMember',\n 'Observation.identifier',\n 'Observation.interpretation',\n 'Observation.modifierExtension',\n 'Observation.note',\n 'Observation.partOf',\n 'Observation.performer',\n 'Observation.referenceRange',\n 'Observation.referenceRange.appliesTo',\n 'Observation.referenceRange.extension',\n 'Observation.referenceRange.modifierExtension',\n 'Observation.value[x].extension',\n 'ObservationDefinition',\n 'ObservationDefinition.category',\n 'ObservationDefinition.contained',\n 'ObservationDefinition.extension',\n 'ObservationDefinition.identifier',\n 'ObservationDefinition.modifierExtension',\n 'ObservationDefinition.permittedDataType',\n 'ObservationDefinition.qualifiedInterval',\n 'ObservationDefinition.qualifiedInterval.appliesTo',\n 'ObservationDefinition.qualifiedInterval.extension',\n 'ObservationDefinition.qualifiedInterval.modifierExtension',\n 'ObservationDefinition.quantitativeDetails.extension',\n 'ObservationDefinition.quantitativeDetails.modifierExtension',\n 'OperationDefinition',\n 'OperationDefinition.contact',\n 'OperationDefinition.contained',\n 'OperationDefinition.extension',\n 'OperationDefinition.jurisdiction',\n 'OperationDefinition.modifierExtension',\n 'OperationDefinition.overload',\n 'OperationDefinition.overload.extension',\n 'OperationDefinition.overload.modifierExtension',\n 'OperationDefinition.overload.parameterName',\n 'OperationDefinition.parameter',\n 'OperationDefinition.parameter.binding.extension',\n 'OperationDefinition.parameter.binding.modifierExtension',\n 'OperationDefinition.parameter.extension',\n 'OperationDefinition.parameter.modifierExtension',\n 'OperationDefinition.parameter.part',\n 'OperationDefinition.parameter.referencedFrom',\n 'OperationDefinition.parameter.referencedFrom.extension',\n 'OperationDefinition.parameter.referencedFrom.modifierExtension',\n 'OperationDefinition.parameter.targetProfile',\n 'OperationDefinition.resource',\n 'OperationDefinition.useContext',\n 'OperationOutcome',\n 'OperationOutcome.contained',\n 'OperationOutcome.extension',\n 'OperationOutcome.issue',\n 'OperationOutcome.issue.expression',\n 'OperationOutcome.issue.extension',\n 'OperationOutcome.issue.location',\n 'OperationOutcome.issue.modifierExtension',\n 'OperationOutcome.modifierExtension',\n 'Organization',\n 'Organization.address',\n 'Organization.alias',\n 'Organization.contact',\n 'Organization.contact.extension',\n 'Organization.contact.modifierExtension',\n 'Organization.contact.telecom',\n 'Organization.contained',\n 'Organization.endpoint',\n 'Organization.extension',\n 'Organization.identifier',\n 'Organization.modifierExtension',\n 'Organization.telecom',\n 'Organization.type',\n 'OrganizationAffiliation',\n 'OrganizationAffiliation.code',\n 'OrganizationAffiliation.contained',\n 'OrganizationAffiliation.endpoint',\n 'OrganizationAffiliation.extension',\n 'OrganizationAffiliation.healthcareService',\n 'OrganizationAffiliation.identifier',\n 'OrganizationAffiliation.location',\n 'OrganizationAffiliation.modifierExtension',\n 'OrganizationAffiliation.network',\n 'OrganizationAffiliation.specialty',\n 'OrganizationAffiliation.telecom',\n 'ParameterDefinition',\n 'ParameterDefinition.extension',\n 'Parameters',\n 'Parameters.parameter',\n 'Parameters.parameter.extension',\n 'Parameters.parameter.modifierExtension',\n 'Parameters.parameter.part',\n 'Patient',\n 'Patient.address',\n 'Patient.communication',\n 'Patient.communication.extension',\n 'Patient.communication.modifierExtension',\n 'Patient.contact',\n 'Patient.contact.extension',\n 'Patient.contact.modifierExtension',\n 'Patient.contact.relationship',\n 'Patient.contact.telecom',\n 'Patient.contained',\n 'Patient.extension',\n 'Patient.generalPractitioner',\n 'Patient.identifier',\n 'Patient.link',\n 'Patient.link.extension',\n 'Patient.link.modifierExtension',\n 'Patient.modifierExtension',\n 'Patient.name',\n 'Patient.photo',\n 'Patient.telecom',\n 'PaymentNotice',\n 'PaymentNotice.contained',\n 'PaymentNotice.extension',\n 'PaymentNotice.identifier',\n 'PaymentNotice.modifierExtension',\n 'PaymentReconciliation',\n 'PaymentReconciliation.contained',\n 'PaymentReconciliation.detail',\n 'PaymentReconciliation.detail.extension',\n 'PaymentReconciliation.detail.modifierExtension',\n 'PaymentReconciliation.extension',\n 'PaymentReconciliation.identifier',\n 'PaymentReconciliation.modifierExtension',\n 'PaymentReconciliation.processNote',\n 'PaymentReconciliation.processNote.extension',\n 'PaymentReconciliation.processNote.modifierExtension',\n 'Period',\n 'Period.extension',\n 'Person',\n 'Person.address',\n 'Person.contained',\n 'Person.extension',\n 'Person.identifier',\n 'Person.link',\n 'Person.link.extension',\n 'Person.link.modifierExtension',\n 'Person.modifierExtension',\n 'Person.name',\n 'Person.telecom',\n 'PlanDefinition',\n 'PlanDefinition.action',\n 'PlanDefinition.action.action',\n 'PlanDefinition.action.code',\n 'PlanDefinition.action.condition',\n 'PlanDefinition.action.condition.extension',\n 'PlanDefinition.action.condition.modifierExtension',\n 'PlanDefinition.action.documentation',\n 'PlanDefinition.action.dynamicValue',\n 'PlanDefinition.action.dynamicValue.extension',\n 'PlanDefinition.action.dynamicValue.modifierExtension',\n 'PlanDefinition.action.extension',\n 'PlanDefinition.action.goalId',\n 'PlanDefinition.action.input',\n 'PlanDefinition.action.modifierExtension',\n 'PlanDefinition.action.output',\n 'PlanDefinition.action.participant',\n 'PlanDefinition.action.participant.extension',\n 'PlanDefinition.action.participant.modifierExtension',\n 'PlanDefinition.action.reason',\n 'PlanDefinition.action.relatedAction',\n 'PlanDefinition.action.relatedAction.extension',\n 'PlanDefinition.action.relatedAction.modifierExtension',\n 'PlanDefinition.action.trigger',\n 'PlanDefinition.author',\n 'PlanDefinition.contact',\n 'PlanDefinition.contained',\n 'PlanDefinition.editor',\n 'PlanDefinition.endorser',\n 'PlanDefinition.extension',\n 'PlanDefinition.goal',\n 'PlanDefinition.goal.addresses',\n 'PlanDefinition.goal.documentation',\n 'PlanDefinition.goal.extension',\n 'PlanDefinition.goal.modifierExtension',\n 'PlanDefinition.goal.target',\n 'PlanDefinition.goal.target.extension',\n 'PlanDefinition.goal.target.modifierExtension',\n 'PlanDefinition.identifier',\n 'PlanDefinition.jurisdiction',\n 'PlanDefinition.library',\n 'PlanDefinition.modifierExtension',\n 'PlanDefinition.relatedArtifact',\n 'PlanDefinition.reviewer',\n 'PlanDefinition.topic',\n 'PlanDefinition.useContext',\n 'Population',\n 'Population.extension',\n 'Population.modifierExtension',\n 'Practitioner',\n 'Practitioner.address',\n 'Practitioner.communication',\n 'Practitioner.contained',\n 'Practitioner.extension',\n 'Practitioner.identifier',\n 'Practitioner.modifierExtension',\n 'Practitioner.name',\n 'Practitioner.photo',\n 'Practitioner.qualification',\n 'Practitioner.qualification.extension',\n 'Practitioner.qualification.identifier',\n 'Practitioner.qualification.modifierExtension',\n 'Practitioner.telecom',\n 'PractitionerRole',\n 'PractitionerRole.availableTime',\n 'PractitionerRole.availableTime.daysOfWeek',\n 'PractitionerRole.availableTime.extension',\n 'PractitionerRole.availableTime.modifierExtension',\n 'PractitionerRole.code',\n 'PractitionerRole.contained',\n 'PractitionerRole.endpoint',\n 'PractitionerRole.extension',\n 'PractitionerRole.healthcareService',\n 'PractitionerRole.identifier',\n 'PractitionerRole.location',\n 'PractitionerRole.modifierExtension',\n 'PractitionerRole.notAvailable',\n 'PractitionerRole.notAvailable.extension',\n 'PractitionerRole.notAvailable.modifierExtension',\n 'PractitionerRole.specialty',\n 'PractitionerRole.telecom',\n 'Procedure',\n 'Procedure.basedOn',\n 'Procedure.bodySite',\n 'Procedure.complication',\n 'Procedure.complicationDetail',\n 'Procedure.contained',\n 'Procedure.extension',\n 'Procedure.focalDevice',\n 'Procedure.focalDevice.extension',\n 'Procedure.focalDevice.modifierExtension',\n 'Procedure.followUp',\n 'Procedure.identifier',\n 'Procedure.instantiatesCanonical',\n 'Procedure.instantiatesUri',\n 'Procedure.modifierExtension',\n 'Procedure.note',\n 'Procedure.partOf',\n 'Procedure.performer',\n 'Procedure.performer.extension',\n 'Procedure.performer.modifierExtension',\n 'Procedure.reasonCode',\n 'Procedure.reasonReference',\n 'Procedure.report',\n 'Procedure.usedCode',\n 'Procedure.usedReference',\n 'ProdCharacteristic',\n 'ProdCharacteristic.color',\n 'ProdCharacteristic.extension',\n 'ProdCharacteristic.image',\n 'ProdCharacteristic.imprint',\n 'ProdCharacteristic.modifierExtension',\n 'ProductShelfLife',\n 'ProductShelfLife.extension',\n 'ProductShelfLife.modifierExtension',\n 'ProductShelfLife.specialPrecautionsForStorage',\n 'Provenance',\n 'Provenance.agent',\n 'Provenance.agent.extension',\n 'Provenance.agent.modifierExtension',\n 'Provenance.agent.role',\n 'Provenance.contained',\n 'Provenance.entity',\n 'Provenance.entity.agent',\n 'Provenance.entity.extension',\n 'Provenance.entity.modifierExtension',\n 'Provenance.extension',\n 'Provenance.modifierExtension',\n 'Provenance.policy',\n 'Provenance.reason',\n 'Provenance.signature',\n 'Provenance.target',\n 'Quantity',\n 'Quantity.extension',\n 'Questionnaire',\n 'Questionnaire.code',\n 'Questionnaire.contact',\n 'Questionnaire.contained',\n 'Questionnaire.derivedFrom',\n 'Questionnaire.extension',\n 'Questionnaire.identifier',\n 'Questionnaire.item',\n 'Questionnaire.item.answerOption',\n 'Questionnaire.item.answerOption.extension',\n 'Questionnaire.item.answerOption.modifierExtension',\n 'Questionnaire.item.code',\n 'Questionnaire.item.enableWhen',\n 'Questionnaire.item.enableWhen.extension',\n 'Questionnaire.item.enableWhen.modifierExtension',\n 'Questionnaire.item.extension',\n 'Questionnaire.item.initial',\n 'Questionnaire.item.initial.extension',\n 'Questionnaire.item.initial.modifierExtension',\n 'Questionnaire.item.item',\n 'Questionnaire.item.modifierExtension',\n 'Questionnaire.jurisdiction',\n 'Questionnaire.modifierExtension',\n 'Questionnaire.subjectType',\n 'Questionnaire.useContext',\n 'QuestionnaireResponse',\n 'QuestionnaireResponse.basedOn',\n 'QuestionnaireResponse.contained',\n 'QuestionnaireResponse.extension',\n 'QuestionnaireResponse.item',\n 'QuestionnaireResponse.item.answer',\n 'QuestionnaireResponse.item.answer.extension',\n 'QuestionnaireResponse.item.answer.item',\n 'QuestionnaireResponse.item.answer.modifierExtension',\n 'QuestionnaireResponse.item.extension',\n 'QuestionnaireResponse.item.item',\n 'QuestionnaireResponse.item.modifierExtension',\n 'QuestionnaireResponse.modifierExtension',\n 'QuestionnaireResponse.partOf',\n 'Range',\n 'Range.extension',\n 'Ratio',\n 'Ratio.extension',\n 'Reference',\n 'Reference.extension',\n 'RelatedArtifact',\n 'RelatedArtifact.extension',\n 'RelatedPerson',\n 'RelatedPerson.address',\n 'RelatedPerson.communication',\n 'RelatedPerson.communication.extension',\n 'RelatedPerson.communication.modifierExtension',\n 'RelatedPerson.contained',\n 'RelatedPerson.extension',\n 'RelatedPerson.identifier',\n 'RelatedPerson.modifierExtension',\n 'RelatedPerson.name',\n 'RelatedPerson.photo',\n 'RelatedPerson.relationship',\n 'RelatedPerson.telecom',\n 'RequestGroup',\n 'RequestGroup.action',\n 'RequestGroup.action.action',\n 'RequestGroup.action.code',\n 'RequestGroup.action.condition',\n 'RequestGroup.action.condition.extension',\n 'RequestGroup.action.condition.modifierExtension',\n 'RequestGroup.action.documentation',\n 'RequestGroup.action.extension',\n 'RequestGroup.action.modifierExtension',\n 'RequestGroup.action.participant',\n 'RequestGroup.action.relatedAction',\n 'RequestGroup.action.relatedAction.extension',\n 'RequestGroup.action.relatedAction.modifierExtension',\n 'RequestGroup.basedOn',\n 'RequestGroup.contained',\n 'RequestGroup.extension',\n 'RequestGroup.identifier',\n 'RequestGroup.instantiatesCanonical',\n 'RequestGroup.instantiatesUri',\n 'RequestGroup.modifierExtension',\n 'RequestGroup.note',\n 'RequestGroup.reasonCode',\n 'RequestGroup.reasonReference',\n 'RequestGroup.replaces',\n 'ResearchDefinition',\n 'ResearchDefinition.author',\n 'ResearchDefinition.comment',\n 'ResearchDefinition.contact',\n 'ResearchDefinition.contained',\n 'ResearchDefinition.editor',\n 'ResearchDefinition.endorser',\n 'ResearchDefinition.extension',\n 'ResearchDefinition.identifier',\n 'ResearchDefinition.jurisdiction',\n 'ResearchDefinition.library',\n 'ResearchDefinition.modifierExtension',\n 'ResearchDefinition.relatedArtifact',\n 'ResearchDefinition.reviewer',\n 'ResearchDefinition.topic',\n 'ResearchDefinition.useContext',\n 'ResearchElementDefinition',\n 'ResearchElementDefinition.author',\n 'ResearchElementDefinition.characteristic',\n 'ResearchElementDefinition.characteristic.extension',\n 'ResearchElementDefinition.characteristic.modifierExtension',\n 'ResearchElementDefinition.characteristic.usageContext',\n 'ResearchElementDefinition.comment',\n 'ResearchElementDefinition.contact',\n 'ResearchElementDefinition.contained',\n 'ResearchElementDefinition.editor',\n 'ResearchElementDefinition.endorser',\n 'ResearchElementDefinition.extension',\n 'ResearchElementDefinition.identifier',\n 'ResearchElementDefinition.jurisdiction',\n 'ResearchElementDefinition.library',\n 'ResearchElementDefinition.modifierExtension',\n 'ResearchElementDefinition.relatedArtifact',\n 'ResearchElementDefinition.reviewer',\n 'ResearchElementDefinition.topic',\n 'ResearchElementDefinition.useContext',\n 'ResearchStudy',\n 'ResearchStudy.arm',\n 'ResearchStudy.arm.extension',\n 'ResearchStudy.arm.modifierExtension',\n 'ResearchStudy.category',\n 'ResearchStudy.condition',\n 'ResearchStudy.contact',\n 'ResearchStudy.contained',\n 'ResearchStudy.enrollment',\n 'ResearchStudy.extension',\n 'ResearchStudy.focus',\n 'ResearchStudy.identifier',\n 'ResearchStudy.keyword',\n 'ResearchStudy.location',\n 'ResearchStudy.modifierExtension',\n 'ResearchStudy.note',\n 'ResearchStudy.objective',\n 'ResearchStudy.objective.extension',\n 'ResearchStudy.objective.modifierExtension',\n 'ResearchStudy.partOf',\n 'ResearchStudy.protocol',\n 'ResearchStudy.relatedArtifact',\n 'ResearchStudy.site',\n 'ResearchSubject',\n 'ResearchSubject.contained',\n 'ResearchSubject.extension',\n 'ResearchSubject.identifier',\n 'ResearchSubject.modifierExtension',\n 'Resource',\n 'RiskAssessment',\n 'RiskAssessment.basis',\n 'RiskAssessment.contained',\n 'RiskAssessment.extension',\n 'RiskAssessment.identifier',\n 'RiskAssessment.modifierExtension',\n 'RiskAssessment.note',\n 'RiskAssessment.prediction',\n 'RiskAssessment.prediction.extension',\n 'RiskAssessment.prediction.modifierExtension',\n 'RiskAssessment.reasonCode',\n 'RiskAssessment.reasonReference',\n 'RiskEvidenceSynthesis',\n 'RiskEvidenceSynthesis.author',\n 'RiskEvidenceSynthesis.certainty',\n 'RiskEvidenceSynthesis.certainty.certaintySubcomponent',\n 'RiskEvidenceSynthesis.certainty.certaintySubcomponent.extension',\n 'RiskEvidenceSynthesis.certainty.certaintySubcomponent.modifierExtension',\n 'RiskEvidenceSynthesis.certainty.certaintySubcomponent.note',\n 'RiskEvidenceSynthesis.certainty.certaintySubcomponent.rating',\n 'RiskEvidenceSynthesis.certainty.extension',\n 'RiskEvidenceSynthesis.certainty.modifierExtension',\n 'RiskEvidenceSynthesis.certainty.note',\n 'RiskEvidenceSynthesis.certainty.rating',\n 'RiskEvidenceSynthesis.contact',\n 'RiskEvidenceSynthesis.contained',\n 'RiskEvidenceSynthesis.editor',\n 'RiskEvidenceSynthesis.endorser',\n 'RiskEvidenceSynthesis.extension',\n 'RiskEvidenceSynthesis.identifier',\n 'RiskEvidenceSynthesis.jurisdiction',\n 'RiskEvidenceSynthesis.modifierExtension',\n 'RiskEvidenceSynthesis.note',\n 'RiskEvidenceSynthesis.relatedArtifact',\n 'RiskEvidenceSynthesis.reviewer',\n 'RiskEvidenceSynthesis.riskEstimate.extension',\n 'RiskEvidenceSynthesis.riskEstimate.modifierExtension',\n 'RiskEvidenceSynthesis.riskEstimate.precisionEstimate',\n 'RiskEvidenceSynthesis.riskEstimate.precisionEstimate.extension',\n 'RiskEvidenceSynthesis.riskEstimate.precisionEstimate.modifierExtension',\n 'RiskEvidenceSynthesis.sampleSize.extension',\n 'RiskEvidenceSynthesis.sampleSize.modifierExtension',\n 'RiskEvidenceSynthesis.topic',\n 'RiskEvidenceSynthesis.useContext',\n 'SampledData',\n 'SampledData.extension',\n 'Schedule',\n 'Schedule.actor',\n 'Schedule.contained',\n 'Schedule.extension',\n 'Schedule.identifier',\n 'Schedule.modifierExtension',\n 'Schedule.serviceCategory',\n 'Schedule.serviceType',\n 'Schedule.specialty',\n 'SearchParameter',\n 'SearchParameter.base',\n 'SearchParameter.chain',\n 'SearchParameter.comparator',\n 'SearchParameter.component',\n 'SearchParameter.component.extension',\n 'SearchParameter.component.modifierExtension',\n 'SearchParameter.contact',\n 'SearchParameter.contained',\n 'SearchParameter.extension',\n 'SearchParameter.jurisdiction',\n 'SearchParameter.modifier',\n 'SearchParameter.modifierExtension',\n 'SearchParameter.target',\n 'SearchParameter.useContext',\n 'ServiceRequest',\n 'ServiceRequest.basedOn',\n 'ServiceRequest.bodySite',\n 'ServiceRequest.category',\n 'ServiceRequest.contained',\n 'ServiceRequest.extension',\n 'ServiceRequest.identifier',\n 'ServiceRequest.instantiatesCanonical',\n 'ServiceRequest.instantiatesUri',\n 'ServiceRequest.insurance',\n 'ServiceRequest.locationCode',\n 'ServiceRequest.locationReference',\n 'ServiceRequest.modifierExtension',\n 'ServiceRequest.note',\n 'ServiceRequest.orderDetail',\n 'ServiceRequest.performer',\n 'ServiceRequest.reasonCode',\n 'ServiceRequest.reasonReference',\n 'ServiceRequest.relevantHistory',\n 'ServiceRequest.replaces',\n 'ServiceRequest.specimen',\n 'ServiceRequest.supportingInfo',\n 'Signature',\n 'Signature.extension',\n 'Signature.type',\n 'Slot',\n 'Slot.contained',\n 'Slot.extension',\n 'Slot.identifier',\n 'Slot.modifierExtension',\n 'Slot.serviceCategory',\n 'Slot.serviceType',\n 'Slot.specialty',\n 'Specimen',\n 'Specimen.collection.extension',\n 'Specimen.collection.modifierExtension',\n 'Specimen.condition',\n 'Specimen.contained',\n 'Specimen.container',\n 'Specimen.container.extension',\n 'Specimen.container.identifier',\n 'Specimen.container.modifierExtension',\n 'Specimen.extension',\n 'Specimen.identifier',\n 'Specimen.modifierExtension',\n 'Specimen.note',\n 'Specimen.parent',\n 'Specimen.processing',\n 'Specimen.processing.additive',\n 'Specimen.processing.extension',\n 'Specimen.processing.modifierExtension',\n 'Specimen.request',\n 'SpecimenDefinition',\n 'SpecimenDefinition.collection',\n 'SpecimenDefinition.contained',\n 'SpecimenDefinition.extension',\n 'SpecimenDefinition.modifierExtension',\n 'SpecimenDefinition.patientPreparation',\n 'SpecimenDefinition.typeTested',\n 'SpecimenDefinition.typeTested.container.additive',\n 'SpecimenDefinition.typeTested.container.additive.extension',\n 'SpecimenDefinition.typeTested.container.additive.modifierExtension',\n 'SpecimenDefinition.typeTested.container.extension',\n 'SpecimenDefinition.typeTested.container.modifierExtension',\n 'SpecimenDefinition.typeTested.extension',\n 'SpecimenDefinition.typeTested.handling',\n 'SpecimenDefinition.typeTested.handling.extension',\n 'SpecimenDefinition.typeTested.handling.modifierExtension',\n 'SpecimenDefinition.typeTested.modifierExtension',\n 'SpecimenDefinition.typeTested.rejectionCriterion',\n 'StructureDefinition',\n 'StructureDefinition.contact',\n 'StructureDefinition.contained',\n 'StructureDefinition.context',\n 'StructureDefinition.context.extension',\n 'StructureDefinition.context.modifierExtension',\n 'StructureDefinition.contextInvariant',\n 'StructureDefinition.differential.element',\n 'StructureDefinition.differential.extension',\n 'StructureDefinition.differential.modifierExtension',\n 'StructureDefinition.extension',\n 'StructureDefinition.identifier',\n 'StructureDefinition.jurisdiction',\n 'StructureDefinition.keyword',\n 'StructureDefinition.mapping',\n 'StructureDefinition.mapping.extension',\n 'StructureDefinition.mapping.modifierExtension',\n 'StructureDefinition.modifierExtension',\n 'StructureDefinition.snapshot.element',\n 'StructureDefinition.snapshot.extension',\n 'StructureDefinition.snapshot.modifierExtension',\n 'StructureDefinition.useContext',\n 'StructureMap',\n 'StructureMap.contact',\n 'StructureMap.contained',\n 'StructureMap.extension',\n 'StructureMap.group',\n 'StructureMap.group.extension',\n 'StructureMap.group.input',\n 'StructureMap.group.input.extension',\n 'StructureMap.group.input.modifierExtension',\n 'StructureMap.group.modifierExtension',\n 'StructureMap.group.rule',\n 'StructureMap.group.rule.dependent',\n 'StructureMap.group.rule.dependent.extension',\n 'StructureMap.group.rule.dependent.modifierExtension',\n 'StructureMap.group.rule.dependent.variable',\n 'StructureMap.group.rule.extension',\n 'StructureMap.group.rule.modifierExtension',\n 'StructureMap.group.rule.rule',\n 'StructureMap.group.rule.source',\n 'StructureMap.group.rule.source.extension',\n 'StructureMap.group.rule.source.modifierExtension',\n 'StructureMap.group.rule.target',\n 'StructureMap.group.rule.target.extension',\n 'StructureMap.group.rule.target.listMode',\n 'StructureMap.group.rule.target.modifierExtension',\n 'StructureMap.group.rule.target.parameter',\n 'StructureMap.group.rule.target.parameter.extension',\n 'StructureMap.group.rule.target.parameter.modifierExtension',\n 'StructureMap.identifier',\n 'StructureMap.import',\n 'StructureMap.jurisdiction',\n 'StructureMap.modifierExtension',\n 'StructureMap.structure',\n 'StructureMap.structure.extension',\n 'StructureMap.structure.modifierExtension',\n 'StructureMap.useContext',\n 'Subscription',\n 'Subscription.channel.extension',\n 'Subscription.channel.header',\n 'Subscription.channel.modifierExtension',\n 'Subscription.contact',\n 'Subscription.contained',\n 'Subscription.extension',\n 'Subscription.modifierExtension',\n 'Substance',\n 'Substance.category',\n 'Substance.contained',\n 'Substance.extension',\n 'Substance.identifier',\n 'Substance.ingredient',\n 'Substance.ingredient.extension',\n 'Substance.ingredient.modifierExtension',\n 'Substance.instance',\n 'Substance.instance.extension',\n 'Substance.instance.modifierExtension',\n 'Substance.modifierExtension',\n 'SubstanceAmount',\n 'SubstanceAmount.extension',\n 'SubstanceAmount.modifierExtension',\n 'SubstanceAmount.referenceRange.extension',\n 'SubstanceNucleicAcid',\n 'SubstanceNucleicAcid.contained',\n 'SubstanceNucleicAcid.extension',\n 'SubstanceNucleicAcid.modifierExtension',\n 'SubstanceNucleicAcid.subunit',\n 'SubstanceNucleicAcid.subunit.extension',\n 'SubstanceNucleicAcid.subunit.linkage',\n 'SubstanceNucleicAcid.subunit.linkage.extension',\n 'SubstanceNucleicAcid.subunit.linkage.modifierExtension',\n 'SubstanceNucleicAcid.subunit.modifierExtension',\n 'SubstanceNucleicAcid.subunit.sugar',\n 'SubstanceNucleicAcid.subunit.sugar.extension',\n 'SubstanceNucleicAcid.subunit.sugar.modifierExtension',\n 'SubstancePolymer',\n 'SubstancePolymer.contained',\n 'SubstancePolymer.copolymerConnectivity',\n 'SubstancePolymer.extension',\n 'SubstancePolymer.modification',\n 'SubstancePolymer.modifierExtension',\n 'SubstancePolymer.monomerSet',\n 'SubstancePolymer.monomerSet.extension',\n 'SubstancePolymer.monomerSet.modifierExtension',\n 'SubstancePolymer.monomerSet.startingMaterial',\n 'SubstancePolymer.monomerSet.startingMaterial.extension',\n 'SubstancePolymer.monomerSet.startingMaterial.modifierExtension',\n 'SubstancePolymer.repeat',\n 'SubstancePolymer.repeat.extension',\n 'SubstancePolymer.repeat.modifierExtension',\n 'SubstancePolymer.repeat.repeatUnit',\n 'SubstancePolymer.repeat.repeatUnit.degreeOfPolymerisation',\n 'SubstancePolymer.repeat.repeatUnit.degreeOfPolymerisation.extension',\n 'SubstancePolymer.repeat.repeatUnit.degreeOfPolymerisation.modifierExtension',\n 'SubstancePolymer.repeat.repeatUnit.extension',\n 'SubstancePolymer.repeat.repeatUnit.modifierExtension',\n 'SubstancePolymer.repeat.repeatUnit.structuralRepresentation',\n 'SubstancePolymer.repeat.repeatUnit.structuralRepresentation.extension',\n 'SubstancePolymer.repeat.repeatUnit.structuralRepresentation.modifierExtension',\n 'SubstanceProtein',\n 'SubstanceProtein.contained',\n 'SubstanceProtein.disulfideLinkage',\n 'SubstanceProtein.extension',\n 'SubstanceProtein.modifierExtension',\n 'SubstanceProtein.subunit',\n 'SubstanceProtein.subunit.extension',\n 'SubstanceProtein.subunit.modifierExtension',\n 'SubstanceReferenceInformation',\n 'SubstanceReferenceInformation.classification',\n 'SubstanceReferenceInformation.classification.extension',\n 'SubstanceReferenceInformation.classification.modifierExtension',\n 'SubstanceReferenceInformation.classification.source',\n 'SubstanceReferenceInformation.classification.subtype',\n 'SubstanceReferenceInformation.contained',\n 'SubstanceReferenceInformation.extension',\n 'SubstanceReferenceInformation.gene',\n 'SubstanceReferenceInformation.gene.extension',\n 'SubstanceReferenceInformation.gene.modifierExtension',\n 'SubstanceReferenceInformation.gene.source',\n 'SubstanceReferenceInformation.geneElement',\n 'SubstanceReferenceInformation.geneElement.extension',\n 'SubstanceReferenceInformation.geneElement.modifierExtension',\n 'SubstanceReferenceInformation.geneElement.source',\n 'SubstanceReferenceInformation.modifierExtension',\n 'SubstanceReferenceInformation.target',\n 'SubstanceReferenceInformation.target.extension',\n 'SubstanceReferenceInformation.target.modifierExtension',\n 'SubstanceReferenceInformation.target.source',\n 'SubstanceSourceMaterial',\n 'SubstanceSourceMaterial.contained',\n 'SubstanceSourceMaterial.countryOfOrigin',\n 'SubstanceSourceMaterial.extension',\n 'SubstanceSourceMaterial.fractionDescription',\n 'SubstanceSourceMaterial.fractionDescription.extension',\n 'SubstanceSourceMaterial.fractionDescription.modifierExtension',\n 'SubstanceSourceMaterial.geographicalLocation',\n 'SubstanceSourceMaterial.modifierExtension',\n 'SubstanceSourceMaterial.organism.author',\n 'SubstanceSourceMaterial.organism.author.extension',\n 'SubstanceSourceMaterial.organism.author.modifierExtension',\n 'SubstanceSourceMaterial.organism.extension',\n 'SubstanceSourceMaterial.organism.hybrid.extension',\n 'SubstanceSourceMaterial.organism.hybrid.modifierExtension',\n 'SubstanceSourceMaterial.organism.modifierExtension',\n 'SubstanceSourceMaterial.organism.organismGeneral.extension',\n 'SubstanceSourceMaterial.organism.organismGeneral.modifierExtension',\n 'SubstanceSourceMaterial.parentSubstanceId',\n 'SubstanceSourceMaterial.parentSubstanceName',\n 'SubstanceSourceMaterial.partDescription',\n 'SubstanceSourceMaterial.partDescription.extension',\n 'SubstanceSourceMaterial.partDescription.modifierExtension',\n 'SubstanceSpecification',\n 'SubstanceSpecification.code',\n 'SubstanceSpecification.code.extension',\n 'SubstanceSpecification.code.modifierExtension',\n 'SubstanceSpecification.code.source',\n 'SubstanceSpecification.contained',\n 'SubstanceSpecification.extension',\n 'SubstanceSpecification.modifierExtension',\n 'SubstanceSpecification.moiety',\n 'SubstanceSpecification.moiety.extension',\n 'SubstanceSpecification.moiety.modifierExtension',\n 'SubstanceSpecification.molecularWeight',\n 'SubstanceSpecification.name',\n 'SubstanceSpecification.name.domain',\n 'SubstanceSpecification.name.extension',\n 'SubstanceSpecification.name.jurisdiction',\n 'SubstanceSpecification.name.language',\n 'SubstanceSpecification.name.modifierExtension',\n 'SubstanceSpecification.name.official',\n 'SubstanceSpecification.name.official.extension',\n 'SubstanceSpecification.name.official.modifierExtension',\n 'SubstanceSpecification.name.source',\n 'SubstanceSpecification.name.synonym',\n 'SubstanceSpecification.name.translation',\n 'SubstanceSpecification.property',\n 'SubstanceSpecification.property.extension',\n 'SubstanceSpecification.property.modifierExtension',\n 'SubstanceSpecification.relationship',\n 'SubstanceSpecification.relationship.extension',\n 'SubstanceSpecification.relationship.modifierExtension',\n 'SubstanceSpecification.relationship.source',\n 'SubstanceSpecification.source',\n 'SubstanceSpecification.structure.extension',\n 'SubstanceSpecification.structure.isotope',\n 'SubstanceSpecification.structure.isotope.extension',\n 'SubstanceSpecification.structure.isotope.modifierExtension',\n 'SubstanceSpecification.structure.isotope.molecularWeight.extension',\n 'SubstanceSpecification.structure.isotope.molecularWeight.modifierExtension',\n 'SubstanceSpecification.structure.modifierExtension',\n 'SubstanceSpecification.structure.representation',\n 'SubstanceSpecification.structure.representation.extension',\n 'SubstanceSpecification.structure.representation.modifierExtension',\n 'SubstanceSpecification.structure.source',\n 'SupplyDelivery',\n 'SupplyDelivery.basedOn',\n 'SupplyDelivery.contained',\n 'SupplyDelivery.extension',\n 'SupplyDelivery.identifier',\n 'SupplyDelivery.modifierExtension',\n 'SupplyDelivery.partOf',\n 'SupplyDelivery.receiver',\n 'SupplyDelivery.suppliedItem.extension',\n 'SupplyDelivery.suppliedItem.modifierExtension',\n 'SupplyRequest',\n 'SupplyRequest.contained',\n 'SupplyRequest.extension',\n 'SupplyRequest.identifier',\n 'SupplyRequest.modifierExtension',\n 'SupplyRequest.parameter',\n 'SupplyRequest.parameter.extension',\n 'SupplyRequest.parameter.modifierExtension',\n 'SupplyRequest.reasonCode',\n 'SupplyRequest.reasonReference',\n 'SupplyRequest.supplier',\n 'Task',\n 'Task.basedOn',\n 'Task.contained',\n 'Task.extension',\n 'Task.identifier',\n 'Task.input',\n 'Task.input.extension',\n 'Task.input.modifierExtension',\n 'Task.insurance',\n 'Task.modifierExtension',\n 'Task.note',\n 'Task.output',\n 'Task.output.extension',\n 'Task.output.modifierExtension',\n 'Task.partOf',\n 'Task.performerType',\n 'Task.relevantHistory',\n 'Task.restriction.extension',\n 'Task.restriction.modifierExtension',\n 'Task.restriction.recipient',\n 'TerminologyCapabilities',\n 'TerminologyCapabilities.closure.extension',\n 'TerminologyCapabilities.closure.modifierExtension',\n 'TerminologyCapabilities.codeSystem',\n 'TerminologyCapabilities.codeSystem.extension',\n 'TerminologyCapabilities.codeSystem.modifierExtension',\n 'TerminologyCapabilities.codeSystem.version',\n 'TerminologyCapabilities.codeSystem.version.extension',\n 'TerminologyCapabilities.codeSystem.version.filter',\n 'TerminologyCapabilities.codeSystem.version.filter.extension',\n 'TerminologyCapabilities.codeSystem.version.filter.modifierExtension',\n 'TerminologyCapabilities.codeSystem.version.filter.op',\n 'TerminologyCapabilities.codeSystem.version.language',\n 'TerminologyCapabilities.codeSystem.version.modifierExtension',\n 'TerminologyCapabilities.codeSystem.version.property',\n 'TerminologyCapabilities.contact',\n 'TerminologyCapabilities.contained',\n 'TerminologyCapabilities.expansion.extension',\n 'TerminologyCapabilities.expansion.modifierExtension',\n 'TerminologyCapabilities.expansion.parameter',\n 'TerminologyCapabilities.expansion.parameter.extension',\n 'TerminologyCapabilities.expansion.parameter.modifierExtension',\n 'TerminologyCapabilities.extension',\n 'TerminologyCapabilities.implementation.extension',\n 'TerminologyCapabilities.implementation.modifierExtension',\n 'TerminologyCapabilities.jurisdiction',\n 'TerminologyCapabilities.modifierExtension',\n 'TerminologyCapabilities.software.extension',\n 'TerminologyCapabilities.software.modifierExtension',\n 'TerminologyCapabilities.translation.extension',\n 'TerminologyCapabilities.translation.modifierExtension',\n 'TerminologyCapabilities.useContext',\n 'TerminologyCapabilities.validateCode.extension',\n 'TerminologyCapabilities.validateCode.modifierExtension',\n 'TestReport',\n 'TestReport.contained',\n 'TestReport.extension',\n 'TestReport.modifierExtension',\n 'TestReport.participant',\n 'TestReport.participant.extension',\n 'TestReport.participant.modifierExtension',\n 'TestReport.setup.action',\n 'TestReport.setup.action.assert.extension',\n 'TestReport.setup.action.assert.modifierExtension',\n 'TestReport.setup.action.extension',\n 'TestReport.setup.action.modifierExtension',\n 'TestReport.setup.action.operation.extension',\n 'TestReport.setup.action.operation.modifierExtension',\n 'TestReport.setup.extension',\n 'TestReport.setup.modifierExtension',\n 'TestReport.teardown.action',\n 'TestReport.teardown.action.extension',\n 'TestReport.teardown.action.modifierExtension',\n 'TestReport.teardown.extension',\n 'TestReport.teardown.modifierExtension',\n 'TestReport.test',\n 'TestReport.test.action',\n 'TestReport.test.action.extension',\n 'TestReport.test.action.modifierExtension',\n 'TestReport.test.extension',\n 'TestReport.test.modifierExtension',\n 'TestScript',\n 'TestScript.contact',\n 'TestScript.contained',\n 'TestScript.destination',\n 'TestScript.destination.extension',\n 'TestScript.destination.modifierExtension',\n 'TestScript.extension',\n 'TestScript.fixture',\n 'TestScript.fixture.extension',\n 'TestScript.fixture.modifierExtension',\n 'TestScript.jurisdiction',\n 'TestScript.metadata.capability',\n 'TestScript.metadata.capability.extension',\n 'TestScript.metadata.capability.link',\n 'TestScript.metadata.capability.modifierExtension',\n 'TestScript.metadata.capability.origin',\n 'TestScript.metadata.extension',\n 'TestScript.metadata.link',\n 'TestScript.metadata.link.extension',\n 'TestScript.metadata.link.modifierExtension',\n 'TestScript.metadata.modifierExtension',\n 'TestScript.modifierExtension',\n 'TestScript.origin',\n 'TestScript.origin.extension',\n 'TestScript.origin.modifierExtension',\n 'TestScript.profile',\n 'TestScript.setup.action',\n 'TestScript.setup.action.assert.extension',\n 'TestScript.setup.action.assert.modifierExtension',\n 'TestScript.setup.action.extension',\n 'TestScript.setup.action.modifierExtension',\n 'TestScript.setup.action.operation.extension',\n 'TestScript.setup.action.operation.modifierExtension',\n 'TestScript.setup.action.operation.requestHeader',\n 'TestScript.setup.action.operation.requestHeader.extension',\n 'TestScript.setup.action.operation.requestHeader.modifierExtension',\n 'TestScript.setup.extension',\n 'TestScript.setup.modifierExtension',\n 'TestScript.teardown.action',\n 'TestScript.teardown.action.extension',\n 'TestScript.teardown.action.modifierExtension',\n 'TestScript.teardown.extension',\n 'TestScript.teardown.modifierExtension',\n 'TestScript.test',\n 'TestScript.test.action',\n 'TestScript.test.action.extension',\n 'TestScript.test.action.modifierExtension',\n 'TestScript.test.extension',\n 'TestScript.test.modifierExtension',\n 'TestScript.useContext',\n 'TestScript.variable',\n 'TestScript.variable.extension',\n 'TestScript.variable.modifierExtension',\n 'Timing',\n 'Timing.event',\n 'Timing.extension',\n 'Timing.modifierExtension',\n 'Timing.repeat.dayOfWeek',\n 'Timing.repeat.extension',\n 'Timing.repeat.timeOfDay',\n 'Timing.repeat.when',\n 'TriggerDefinition',\n 'TriggerDefinition.data',\n 'TriggerDefinition.extension',\n 'UsageContext',\n 'UsageContext.extension',\n 'ValueSet',\n 'ValueSet.compose.exclude',\n 'ValueSet.compose.extension',\n 'ValueSet.compose.include',\n 'ValueSet.compose.include.concept',\n 'ValueSet.compose.include.concept.designation',\n 'ValueSet.compose.include.concept.designation.extension',\n 'ValueSet.compose.include.concept.designation.modifierExtension',\n 'ValueSet.compose.include.concept.extension',\n 'ValueSet.compose.include.concept.modifierExtension',\n 'ValueSet.compose.include.extension',\n 'ValueSet.compose.include.filter',\n 'ValueSet.compose.include.filter.extension',\n 'ValueSet.compose.include.filter.modifierExtension',\n 'ValueSet.compose.include.modifierExtension',\n 'ValueSet.compose.include.valueSet',\n 'ValueSet.compose.modifierExtension',\n 'ValueSet.contact',\n 'ValueSet.contained',\n 'ValueSet.expansion.contains',\n 'ValueSet.expansion.contains.contains',\n 'ValueSet.expansion.contains.designation',\n 'ValueSet.expansion.contains.extension',\n 'ValueSet.expansion.contains.modifierExtension',\n 'ValueSet.expansion.extension',\n 'ValueSet.expansion.modifierExtension',\n 'ValueSet.expansion.parameter',\n 'ValueSet.expansion.parameter.extension',\n 'ValueSet.expansion.parameter.modifierExtension',\n 'ValueSet.extension',\n 'ValueSet.identifier',\n 'ValueSet.jurisdiction',\n 'ValueSet.modifierExtension',\n 'ValueSet.useContext',\n 'VerificationResult',\n 'VerificationResult.attestation.extension',\n 'VerificationResult.attestation.modifierExtension',\n 'VerificationResult.contained',\n 'VerificationResult.extension',\n 'VerificationResult.modifierExtension',\n 'VerificationResult.primarySource',\n 'VerificationResult.primarySource.communicationMethod',\n 'VerificationResult.primarySource.extension',\n 'VerificationResult.primarySource.modifierExtension',\n 'VerificationResult.primarySource.pushTypeAvailable',\n 'VerificationResult.primarySource.type',\n 'VerificationResult.target',\n 'VerificationResult.targetLocation',\n 'VerificationResult.validationProcess',\n 'VerificationResult.validator',\n 'VerificationResult.validator.extension',\n 'VerificationResult.validator.modifierExtension',\n 'VisionPrescription',\n 'VisionPrescription.contained',\n 'VisionPrescription.extension',\n 'VisionPrescription.identifier',\n 'VisionPrescription.lensSpecification',\n 'VisionPrescription.lensSpecification.extension',\n 'VisionPrescription.lensSpecification.modifierExtension',\n 'VisionPrescription.lensSpecification.note',\n 'VisionPrescription.lensSpecification.prism',\n 'VisionPrescription.lensSpecification.prism.extension',\n 'VisionPrescription.lensSpecification.prism.modifierExtension',\n 'VisionPrescription.modifierExtension',\n]);\n", "/**\n * SearchParameter Registry\n *\n * Indexes FHIR SearchParameter definitions and determines the physical\n * storage strategy for each parameter. Drives search column generation\n * in `TableSchemaBuilder`.\n *\n * ## Strategy Mapping (from WF-MIG-003)\n *\n * | SearchParam.type | Strategy | Column Type |\n * |------------------|----------------|--------------------------------------|\n * | date | column | TIMESTAMPTZ (or DATE) |\n * | string | column | TEXT |\n * | reference | column | TEXT |\n * | number | column | DOUBLE PRECISION |\n * | quantity | column | DOUBLE PRECISION |\n * | uri | column | TEXT |\n * | boolean | column | BOOLEAN (not used in practice) |\n * | token | token-column | UUID[] + TEXT[] + TEXT (3 cols) |\n * | special | skipped | \u2014 |\n * | composite | skipped | \u2014 |\n *\n * Lookup-table strategy is determined by matching specific search param\n * codes (name, address, etc.) \u2014 generates a sort column only in the\n * main table; actual data is written by the Repository layer (Phase 9).\n *\n * @module fhir-persistence/registry\n */\n\nimport type { SqlColumnType } from '../schema/table-schema.js';\nimport { ARRAY_ELEMENT_PATHS } from './element-cardinality.js';\n\n// =============================================================================\n// Section 1: Types\n// =============================================================================\n\n/**\n * FHIR SearchParameter type codes.\n */\nexport type SearchParamType =\n | 'number'\n | 'date'\n | 'string'\n | 'token'\n | 'reference'\n | 'composite'\n | 'quantity'\n | 'uri'\n | 'special';\n\n/**\n * Physical storage strategy for a search parameter.\n *\n * - `column` \u2014 single column in the main table\n * - `token-column` \u2014 three columns (UUID[], TEXT[], TEXT) for token search\n * - `lookup-table` \u2014 separate lookup table; only a sort column in main table\n */\nexport type SearchStrategy = 'column' | 'token-column' | 'lookup-table';\n\n/**\n * Column type for search parameter columns.\n */\nexport type SearchColumnType = SqlColumnType;\n\n/**\n * Resolved implementation details for a single search parameter\n * on a specific resource type.\n */\nexport interface SearchParameterImpl {\n /** SearchParameter.code (e.g., `'birthdate'`). */\n code: string;\n\n /** FHIR search parameter type. */\n type: SearchParamType;\n\n /** Resource types this parameter applies to. */\n resourceTypes: string[];\n\n /** FHIRPath expression for value extraction. */\n expression: string;\n\n /** Physical storage strategy. */\n strategy: SearchStrategy;\n\n /** Column name in the main table (for `column` strategy). */\n columnName: string;\n\n /** PostgreSQL column type (for `column` strategy). */\n columnType: SearchColumnType;\n\n /** Whether the column stores an array of values. */\n array: boolean;\n}\n\n/**\n * Raw FHIR SearchParameter shape (subset of fields we need).\n */\nexport interface SearchParameterResource {\n resourceType: 'SearchParameter';\n code: string;\n type: SearchParamType;\n base: string[];\n expression?: string;\n url?: string;\n name?: string;\n target?: string[];\n}\n\n/**\n * Shape of a FHIR Bundle containing SearchParameter entries.\n */\nexport interface SearchParameterBundle {\n resourceType: 'Bundle';\n entry?: Array<{\n resource?: SearchParameterResource;\n }>;\n}\n\n// =============================================================================\n// Section 2: Constants\n// =============================================================================\n\n/**\n * SearchParameter codes that are already handled by fixed columns\n * and should NOT generate additional search columns.\n */\nconst IGNORED_SEARCH_PARAMS = new Set([\n '_id',\n '_lastUpdated',\n '_profile',\n '_compartment',\n '_source',\n '_version',\n]);\n\n/**\n * Search parameters that should override the default strategy.\n *\n * `version` is type=token in FHIR R4, but Medplum stores it as a plain\n * TEXT column (not token-column) because canonical versions are simple\n * strings like \"1.0.0\". Also avoids name collision with the internal\n * `__version INTEGER` fixed column.\n */\nconst STRATEGY_OVERRIDES = new Map<string, { strategy: SearchStrategy; type: SearchParamType }>([\n ['version', { strategy: 'column', type: 'string' }],\n]);\n\n/**\n * SearchParameter types that are skipped entirely.\n */\nconst SKIPPED_TYPES = new Set<SearchParamType>(['composite', 'special']);\n\n/**\n * Search parameter codes that use the lookup-table strategy.\n *\n * These parameters target complex FHIR types (HumanName, Address, etc.)\n * that require multi-column storage in separate lookup tables.\n * Only a sort column is generated in the main table.\n *\n * NOTE: Matching is done by code AND expression pattern to avoid false\n * positives (e.g. Account.name is a plain string, not HumanName).\n */\nconst LOOKUP_TABLE_PARAMS = new Set([\n // HumanName-related\n 'name',\n 'given',\n 'family',\n 'phonetic',\n // Address-related\n 'address',\n 'address-city',\n 'address-country',\n 'address-postalcode',\n 'address-state',\n 'address-use',\n // Contact-related\n 'email',\n 'phone',\n 'telecom',\n]);\n\n/**\n * FHIRPath expression suffixes that indicate a complex lookup-table type.\n *\n * A search parameter uses lookup-table strategy only when its code is in\n * LOOKUP_TABLE_PARAMS AND its expression ends with one of these suffixes\n * (i.e. it actually targets a HumanName, Address, or ContactPoint element).\n */\nconst LOOKUP_TABLE_EXPRESSION_SUFFIXES = [\n '.name',\n '.given',\n '.family',\n '.address',\n '.telecom',\n];\n\n// =============================================================================\n// Section 3: Strategy Resolution\n// =============================================================================\n\n/**\n * Determine the search strategy for a given search parameter.\n *\n * Lookup-table strategy requires BOTH:\n * 1. The param code is in LOOKUP_TABLE_PARAMS\n * 2. The expression targets a known complex type path (HumanName, Address, ContactPoint)\n *\n * This prevents plain-string fields named 'name' (e.g. Account.name) from\n * incorrectly using the lookup-table strategy.\n */\nfunction resolveStrategy(code: string, type: SearchParamType, expression: string): SearchStrategy {\n if (LOOKUP_TABLE_PARAMS.has(code)) {\n // Only use lookup-table if the expression actually targets a complex type\n const exprLower = expression.toLowerCase();\n const targetsComplexType = LOOKUP_TABLE_EXPRESSION_SUFFIXES.some(\n (suffix) => exprLower.includes(suffix),\n );\n if (targetsComplexType) {\n return 'lookup-table';\n }\n }\n if (type === 'token') {\n return 'token-column';\n }\n return 'column';\n}\n\n/**\n * Convert a hyphenated search parameter code to a camelCase column name.\n *\n * Examples:\n * - `'birth-date'` \u2192 `'birthDate'`\n * - `'address-city'` \u2192 `'addressCity'`\n * - `'active'` \u2192 `'active'`\n */\nfunction codeToColumnName(code: string): string {\n return code.replace(/-([a-z])/g, (_, c: string) => c.toUpperCase());\n}\n\n/**\n * Determine the PostgreSQL column type for a search parameter.\n *\n * @param type - FHIR search parameter type\n * @param array - Whether the column stores multiple values\n * @returns The PostgreSQL column type\n */\nfunction resolveColumnType(type: SearchParamType, array: boolean): SearchColumnType {\n switch (type) {\n case 'date':\n return array ? 'TIMESTAMPTZ[]' : 'TIMESTAMPTZ';\n case 'number':\n case 'quantity':\n return array ? 'DOUBLE PRECISION[]' : 'DOUBLE PRECISION';\n case 'string':\n case 'uri':\n case 'reference':\n return array ? 'TEXT[]' : 'TEXT';\n case 'token':\n // Token columns use TEXT for the hash column in v2 DDL;\n // the actual column type is set by the token-column strategy\n return 'TEXT';\n default:\n return 'TEXT';\n }\n}\n\n/**\n * Extract the expression fragment relevant to a specific resource type.\n *\n * Given \"AllergyIntolerance.patient | CarePlan.subject.where(resolve() is Patient)\",\n * for resourceType \"AllergyIntolerance\" returns \"AllergyIntolerance.patient\".\n */\nfunction getExpressionsForResourceType(resourceType: string, expression: string): string[] {\n const results: string[] = [];\n const parts = expression.split('|').map(s => s.trim());\n for (const part of parts) {\n if (part.startsWith(resourceType + '.') || part.startsWith('(' + resourceType + '.')) {\n // Only strip matching outer parentheses (not unbalanced ones)\n let result = part;\n if (result.startsWith('(') && result.endsWith(')')) {\n result = result.slice(1, -1);\n }\n results.push(result);\n }\n }\n // Single expression without union\n if (results.length === 0 && !expression.includes('|') && expression.startsWith(resourceType + '.')) {\n results.push(expression);\n }\n return results;\n}\n\n/**\n * Strip a balanced function call from an expression string.\n *\n * Handles nested parentheses correctly, e.g.:\n * - `.where(resolve() is Patient)` \u2192 removed entirely\n * - `.ofType(CodeableConcept)` \u2192 removed entirely\n *\n * @param input - The expression string\n * @param funcName - The function prefix to strip (e.g. '.where', '.as')\n * @returns The expression with all occurrences of funcName(...) removed\n */\nfunction stripBalancedCall(input: string, funcName: string): string {\n let result = input;\n let idx: number;\n while ((idx = result.indexOf(funcName + '(')) !== -1) {\n // Find the matching closing paren\n let depth = 0;\n let end = idx + funcName.length; // points to '('\n for (let i = end; i < result.length; i++) {\n if (result[i] === '(') depth++;\n else if (result[i] === ')') {\n depth--;\n if (depth === 0) {\n end = i + 1;\n break;\n }\n }\n }\n result = result.slice(0, idx) + result.slice(end);\n }\n return result;\n}\n\n/**\n * Determine whether a search parameter produces an array column.\n *\n * Uses FHIR R4 element cardinality (from StructureDefinitions) to determine\n * whether any element along the FHIRPath expression path has max != '1'.\n *\n * This matches Medplum's `crawlSearchParameterDetails` logic which sets\n * `builder.array = true` when `elementDefinition.isArray` is true.\n *\n * Rules:\n * - token-column / lookup-table: always array (UUID[] hash column / sort only)\n * - Walk each segment of the expression path for the specific resource type\n * - If ANY segment has max != '1' in FHIR R4 \u2192 array\n * - [0] indexer makes result NOT array\n * - .where() / .as() / .resolve() / .ofType() are stripped\n */\nfunction resolveIsArray(\n type: SearchParamType,\n strategy: SearchStrategy,\n expression: string,\n _targets: string[],\n resourceType?: string,\n): boolean {\n if (strategy === 'token-column') {\n return true; // Token columns are always arrays\n }\n\n // If no resource type provided, fall back to old heuristic\n if (!resourceType) {\n return false;\n }\n\n // Get ALL expression fragments for this specific resource type\n // (e.g., combo-value-quantity has both Observation.value and Observation.component.value)\n const rtExprs = getExpressionsForResourceType(resourceType, expression);\n if (rtExprs.length === 0) {\n return false;\n }\n\n // If ANY expression fragment traverses an array path, the column is array\n for (const rtExpr of rtExprs) {\n // Strip FHIRPath functions with potentially nested parentheses:\n // .where(resolve() is Patient), .as(Type), .resolve(), .ofType(Type)\n let cleaned = stripBalancedCall(rtExpr, '.where');\n cleaned = stripBalancedCall(cleaned, '.as');\n cleaned = stripBalancedCall(cleaned, '.ofType');\n cleaned = cleaned.replace(/\\.resolve\\(\\)/g, '');\n // Strip FHIRPath infix 'as Type' syntax: (Observation.value as Quantity)\n cleaned = cleaned.replace(/\\s+as\\s+\\w+/g, '');\n\n // Check for [0] indexer \u2014 makes result NOT array\n const hasIndexer = cleaned.includes('[0]');\n cleaned = cleaned.replace(/\\[0\\]/g, '');\n\n // Walk each segment of the path\n const segments = cleaned.split('.');\n if (segments.length < 2) continue;\n\n let currentPath = segments[0]; // ResourceType\n for (let i = 1; i < segments.length; i++) {\n const seg = segments[i];\n if (!seg) continue;\n currentPath += '.' + seg;\n\n if (ARRAY_ELEMENT_PATHS.has(currentPath)) {\n // If the expression had [0] indexer, this fragment is not array\n if (hasIndexer) break;\n return true;\n }\n }\n }\n\n return false;\n}\n\n// =============================================================================\n// Section 4: SearchParameterRegistry\n// =============================================================================\n\n/**\n * Indexes SearchParameter definitions by resource type.\n *\n * ## Usage\n *\n * ```typescript\n * const registry = new SearchParameterRegistry();\n * const bundle = JSON.parse(fs.readFileSync('search-parameters.json', 'utf8'));\n * registry.indexBundle(bundle);\n *\n * const patientParams = registry.getForResource('Patient');\n * ```\n */\nexport class SearchParameterRegistry {\n /**\n * Map from resource type \u2192 Map from param code \u2192 SearchParameterImpl.\n */\n private readonly byResource = new Map<string, Map<string, SearchParameterImpl>>();\n\n /**\n * Total number of indexed implementations (across all resource types).\n */\n private _totalCount = 0;\n\n /**\n * Number of skipped parameters (composite, special, ignored).\n */\n private _skippedCount = 0;\n\n /**\n * Index all SearchParameter entries from a FHIR Bundle.\n *\n * Skips entries that are:\n * - Not a SearchParameter resource\n * - Of type `composite` or `special`\n * - In the ignored list (`_id`, `_lastUpdated`, etc.)\n *\n * @returns Stats about the indexing operation.\n */\n indexBundle(bundle: SearchParameterBundle): { indexed: number; skipped: number } {\n let indexed = 0;\n let skipped = 0;\n\n if (!bundle.entry) {\n return { indexed: 0, skipped: 0 };\n }\n\n for (const entry of bundle.entry) {\n const resource = entry.resource;\n if (!resource || resource.resourceType !== 'SearchParameter') {\n skipped++;\n continue;\n }\n\n if (SKIPPED_TYPES.has(resource.type)) {\n skipped++;\n continue;\n }\n\n if (IGNORED_SEARCH_PARAMS.has(resource.code)) {\n skipped++;\n continue;\n }\n\n if (!resource.base || resource.base.length === 0) {\n skipped++;\n continue;\n }\n\n // Build a per-resource-type impl (array determination depends on resource type)\n let builtAny = false;\n for (const base of resource.base) {\n // Skip abstract base types \u2014 they don't have tables\n if (base === 'Resource' || base === 'DomainResource') {\n continue;\n }\n\n const impl = this.buildImpl(resource, base);\n if (!impl) {\n continue;\n }\n\n let resourceMap = this.byResource.get(base);\n if (!resourceMap) {\n resourceMap = new Map();\n this.byResource.set(base, resourceMap);\n }\n resourceMap.set(impl.code, impl);\n builtAny = true;\n }\n\n if (!builtAny) {\n skipped++;\n continue;\n }\n\n indexed++;\n }\n\n this._totalCount += indexed;\n this._skippedCount += skipped;\n\n return { indexed, skipped };\n }\n\n /**\n * Index a single SearchParameterImpl directly.\n *\n * Useful for adding platform-specific or custom search parameters.\n */\n indexImpl(resourceType: string, impl: SearchParameterImpl): void {\n let resourceMap = this.byResource.get(resourceType);\n if (!resourceMap) {\n resourceMap = new Map();\n this.byResource.set(resourceType, resourceMap);\n }\n resourceMap.set(impl.code, impl);\n this._totalCount++;\n }\n\n /**\n * Get all search parameter implementations for a resource type.\n *\n * @returns Array of SearchParameterImpl, sorted by code for deterministic output.\n */\n getForResource(resourceType: string): SearchParameterImpl[] {\n const resourceMap = this.byResource.get(resourceType);\n if (!resourceMap) {\n return [];\n }\n return Array.from(resourceMap.values()).sort((a, b) => a.code.localeCompare(b.code));\n }\n\n /**\n * Get a specific search parameter implementation for a resource type.\n */\n getImpl(resourceType: string, code: string): SearchParameterImpl | undefined {\n return this.byResource.get(resourceType)?.get(code);\n }\n\n /**\n * Check if a resource type has any indexed search parameters.\n */\n hasResource(resourceType: string): boolean {\n return this.byResource.has(resourceType);\n }\n\n /**\n * Get all resource types that have indexed search parameters.\n */\n getResourceTypes(): string[] {\n return Array.from(this.byResource.keys()).sort();\n }\n\n /**\n * Get the total number of indexed implementations.\n */\n get totalCount(): number {\n return this._totalCount;\n }\n\n /**\n * Get the number of skipped parameters.\n */\n get skippedCount(): number {\n return this._skippedCount;\n }\n\n /**\n * Get the number of resource types with indexed parameters.\n */\n get resourceTypeCount(): number {\n return this.byResource.size;\n }\n\n /**\n * Remove all indexed parameters.\n */\n clear(): void {\n this.byResource.clear();\n this._totalCount = 0;\n this._skippedCount = 0;\n }\n\n // ---------------------------------------------------------------------------\n // Private\n // ---------------------------------------------------------------------------\n\n /**\n * Build a SearchParameterImpl from a raw SearchParameter resource.\n */\n private buildImpl(resource: SearchParameterResource, resourceType: string): SearchParameterImpl | null {\n const { code, type, base, expression } = resource;\n\n if (!code || !type || !base) {\n return null;\n }\n\n const expr = expression ?? '';\n const targets = resource.target ?? [];\n\n // Check for strategy override (e.g., 'version' \u2192 column/string)\n const override = STRATEGY_OVERRIDES.get(code);\n const effectiveType = override?.type ?? type;\n const strategy = override?.strategy ?? resolveStrategy(code, effectiveType, expr);\n const columnName = codeToColumnName(code);\n const array = resolveIsArray(effectiveType, strategy, expr, targets, resourceType);\n const columnType = resolveColumnType(effectiveType, array);\n\n return {\n code,\n type: effectiveType,\n resourceTypes: [...base],\n expression: expression ?? '',\n strategy,\n columnName,\n columnType,\n array,\n };\n }\n}\n", "/**\n * Table Schema Builder\n *\n * Core of Phase 8. Pure functions that derive `ResourceTableSet`\n * (3 tables per resource) from `StructureDefinitionRegistry` and\n * `SearchParameterRegistry`.\n *\n * ## Design\n *\n * Each FHIR resource type gets:\n * - **Main table** \u2014 fixed columns + search columns\n * - **History table** \u2014 fixed structure (no search columns)\n * - **References table** \u2014 fixed structure with composite PK\n *\n * Search columns are generated from `SearchParameterImpl`:\n * - `column` strategy \u2192 one column per param\n * - `token-column` strategy \u2192 three columns per param (__X, __XText, __XSort)\n * - `lookup-table` strategy \u2192 sort column only (__XSort)\n *\n * All functions are pure \u2014 no global state, no database dependency.\n *\n * @module fhir-persistence/schema\n */\n\nimport type {\n ColumnSchema,\n IndexSchema,\n ConstraintSchema,\n MainTableSchema,\n HistoryTableSchema,\n ReferencesTableSchema,\n GlobalLookupTableSchema,\n LookupTableType,\n ResourceTableSet,\n SchemaDefinition,\n} from './table-schema.js';\nimport type { StructureDefinitionRegistry } from '../registry/structure-definition-registry.js';\nimport type { SearchParameterRegistry } from '../registry/search-parameter-registry.js';\nimport type { SearchParameterImpl } from '../registry/search-parameter-registry.js';\n\n// =============================================================================\n// Section 1: Fixed Column Definitions\n// =============================================================================\n\n/**\n * Fixed columns present on every main resource table.\n *\n * v2 changes:\n * - Removed `projectId` (no multi-tenancy)\n * - Removed `__version` (schema version, not resource version)\n * - Added `versionId` (UUID for ETag / optimistic locking)\n * - Changed `deleted` from BOOLEAN to INTEGER (SQLite compat)\n * - Changed `lastUpdated` from TIMESTAMPTZ to TEXT (dialect-neutral; DDL maps to TIMESTAMPTZ for PG)\n * - Token columns: UUID[] \u2192 TEXT[], removed Text middle column (2-col: __X + __XSort)\n * - compartments: UUID[] \u2192 TEXT (JSON array)\n */\nfunction buildFixedMainColumns(): ColumnSchema[] {\n return [\n { name: 'id', type: 'TEXT', notNull: true, primaryKey: true, strategy: 'skip' },\n { name: 'versionId', type: 'TEXT', notNull: true, primaryKey: false, strategy: 'skip' },\n { name: 'content', type: 'TEXT', notNull: true, primaryKey: false, strategy: 'skip' },\n { name: 'lastUpdated', type: 'TEXT', notNull: true, primaryKey: false, strategy: 'skip' },\n { name: 'deleted', type: 'INTEGER', notNull: true, primaryKey: false, defaultValue: '0', strategy: 'skip' },\n { name: '_source', type: 'TEXT', notNull: false, primaryKey: false, strategy: 'skip' },\n { name: '_profile', type: 'TEXT', notNull: false, primaryKey: false, strategy: 'skip' }, // JSON array\n // Metadata token columns \u2014 _tag (meta.tag) \u2014 2-col: TEXT[] + Sort TEXT\n { name: '___tag', type: 'TEXT', notNull: false, primaryKey: false, strategy: 'token-column', searchParamCode: '_tag' },\n { name: '___tagSort', type: 'TEXT', notNull: false, primaryKey: false, strategy: 'token-column' },\n // Metadata token columns \u2014 _security (meta.security) \u2014 2-col: TEXT[] + Sort TEXT\n { name: '___security', type: 'TEXT', notNull: false, primaryKey: false, strategy: 'token-column', searchParamCode: '_security' },\n { name: '___securitySort', type: 'TEXT', notNull: false, primaryKey: false, strategy: 'token-column' },\n ];\n}\n\n/**\n * The `compartments` column \u2014 present on all resources except Binary.\n */\nfunction buildCompartmentsColumn(): ColumnSchema {\n return { name: 'compartments', type: 'TEXT', notNull: false, primaryKey: false, strategy: 'skip' };\n}\n\n/**\n * Fixed columns for the history table.\n */\nfunction buildHistoryColumns(): ColumnSchema[] {\n return [\n { name: 'versionSeq', type: 'INTEGER', notNull: true, primaryKey: true }, // AUTOINCREMENT in DDL\n { name: 'id', type: 'TEXT', notNull: true, primaryKey: false },\n { name: 'versionId', type: 'TEXT', notNull: true, primaryKey: false },\n { name: 'content', type: 'TEXT', notNull: true, primaryKey: false },\n { name: 'lastUpdated', type: 'TEXT', notNull: true, primaryKey: false },\n { name: 'deleted', type: 'INTEGER', notNull: true, primaryKey: false, defaultValue: '0' },\n ];\n}\n\n/**\n * Fixed columns for the references table.\n */\nfunction buildReferencesColumns(): ColumnSchema[] {\n return [\n { name: 'resourceId', type: 'TEXT', notNull: true, primaryKey: false },\n { name: 'targetType', type: 'TEXT', notNull: true, primaryKey: false },\n { name: 'targetId', type: 'TEXT', notNull: true, primaryKey: false },\n { name: 'code', type: 'TEXT', notNull: true, primaryKey: false },\n { name: 'referenceRaw', type: 'TEXT', notNull: false, primaryKey: false },\n ];\n}\n\n// =============================================================================\n// Section 2: Fixed Index Definitions\n// =============================================================================\n\n/**\n * Fixed indexes for the main table.\n */\nfunction buildFixedMainIndexes(resourceType: string): IndexSchema[] {\n return [\n {\n name: `${resourceType}_lastUpdated_idx`,\n columns: ['lastUpdated'],\n indexType: 'btree',\n unique: false,\n },\n {\n name: `${resourceType}__source_idx`,\n columns: ['_source'],\n indexType: 'btree',\n unique: false,\n },\n ];\n}\n\n/**\n * Compartments index \u2014 present on all resources except Binary.\n */\nfunction buildCompartmentsIndex(resourceType: string): IndexSchema {\n return {\n name: `${resourceType}_compartments_idx`,\n columns: ['compartments'],\n indexType: 'gin',\n unique: false,\n };\n}\n\n/**\n * Fixed indexes for the history table.\n */\nfunction buildHistoryIndexes(resourceType: string): IndexSchema[] {\n return [\n {\n name: `${resourceType}_History_id_seq_idx`,\n columns: ['id', 'versionSeq'],\n indexType: 'btree',\n unique: false,\n },\n ];\n}\n\n/**\n * Fixed indexes for the references table.\n */\nfunction buildReferencesIndexes(resourceType: string): IndexSchema[] {\n return [\n {\n name: `${resourceType}_References_target_idx`,\n columns: ['targetType', 'targetId', 'code'],\n indexType: 'btree',\n unique: false,\n },\n {\n name: `${resourceType}_References_resourceId_idx`,\n columns: ['resourceId'],\n indexType: 'btree',\n unique: false,\n },\n ];\n}\n\n// =============================================================================\n// Section 3: Search Column Generation\n// =============================================================================\n\n/**\n * Generate search columns for a resource type based on its SearchParameterImpls.\n */\nfunction buildSearchColumns(impls: SearchParameterImpl[]): ColumnSchema[] {\n const columns: ColumnSchema[] = [];\n\n for (const impl of impls) {\n switch (impl.strategy) {\n case 'column':\n columns.push({\n name: impl.columnName,\n type: impl.columnType,\n notNull: false,\n primaryKey: false,\n searchParamCode: impl.code,\n });\n break;\n\n case 'token-column':\n // v2: Two columns per token param (not three):\n // __code TEXT (JSON array of \"system|code\" strings in SQLite, TEXT[] in PG)\n // __codeSort TEXT \u2014 display text for :text modifier\n columns.push(\n {\n name: `__${impl.columnName}`,\n type: 'TEXT',\n notNull: false,\n primaryKey: false,\n searchParamCode: impl.code,\n strategy: 'token-column',\n },\n {\n name: `__${impl.columnName}Sort`,\n type: 'TEXT',\n notNull: false,\n primaryKey: false,\n searchParamCode: impl.code,\n strategy: 'token-column',\n },\n );\n break;\n\n case 'lookup-table':\n // Only a sort column in the main table\n columns.push({\n name: `__${impl.columnName}Sort`,\n type: 'TEXT',\n notNull: false,\n primaryKey: false,\n searchParamCode: impl.code,\n });\n break;\n }\n }\n\n return columns;\n}\n\n/**\n * Generate search indexes for a resource type based on its SearchParameterImpls.\n */\nfunction buildSearchIndexes(resourceType: string, impls: SearchParameterImpl[]): IndexSchema[] {\n const indexes: IndexSchema[] = [];\n\n for (const impl of impls) {\n switch (impl.strategy) {\n case 'column': {\n const isArray = impl.array;\n indexes.push({\n name: `${resourceType}_${impl.columnName}_idx`,\n columns: [impl.columnName],\n indexType: isArray ? 'gin' : 'btree',\n unique: false,\n });\n break;\n }\n\n case 'token-column':\n // v2: btree index on token column (GIN only for PG TEXT[])\n indexes.push({\n name: `${resourceType}___${impl.columnName}_idx`,\n columns: [`__${impl.columnName}`],\n indexType: 'btree',\n unique: false,\n });\n break;\n\n case 'lookup-table':\n // Sort column gets a btree index\n indexes.push({\n name: `${resourceType}___${impl.columnName}Sort_idx`,\n columns: [`__${impl.columnName}Sort`],\n indexType: 'btree',\n unique: false,\n });\n break;\n }\n }\n\n return indexes;\n}\n\n// =============================================================================\n// Section 3b: Global Lookup Table Generation (Medplum-style)\n// =============================================================================\n\n/**\n * Build the 4 global shared lookup tables matching Medplum's production design.\n *\n * These tables are shared across ALL resource types and store decomposed\n * complex FHIR types for precise search via JOINs:\n * - `HumanName` \u2014 name/given/family from Patient.name, Practitioner.name, etc.\n * - `Address` \u2014 address/city/country/postalCode/state/use\n * - `ContactPoint` \u2014 system/value/use from telecom fields\n * - `Identifier` \u2014 system/value from identifier fields\n *\n * Each table has Medplum-style indexes: btree + trigram (gin_trgm_ops)\n * for efficient prefix, exact, and substring search.\n */\nexport function buildGlobalLookupTables(): GlobalLookupTableSchema[] {\n return [\n buildHumanNameTable(),\n buildAddressTable(),\n buildContactPointTable(),\n buildIdentifierTable(),\n ];\n}\n\nfunction buildHumanNameTable(): GlobalLookupTableSchema {\n const tableName: LookupTableType = 'HumanName';\n return {\n tableName,\n columns: [\n { name: 'resourceId', type: 'TEXT', notNull: true, primaryKey: false },\n { name: 'resourceType', type: 'TEXT', notNull: true, primaryKey: false },\n { name: 'name', type: 'TEXT', notNull: false, primaryKey: false },\n { name: 'given', type: 'TEXT', notNull: false, primaryKey: false },\n { name: 'family', type: 'TEXT', notNull: false, primaryKey: false },\n ],\n indexes: [\n { name: `${tableName}_resourceId_idx`, columns: ['resourceId'], indexType: 'btree', unique: false },\n { name: `${tableName}_name_idx`, columns: ['name'], indexType: 'btree', unique: false },\n { name: `${tableName}_given_idx`, columns: ['given'], indexType: 'btree', unique: false },\n { name: `${tableName}_family_idx`, columns: ['family'], indexType: 'btree', unique: false },\n { name: `${tableName}_nameTrgm_idx`, columns: ['name'], indexType: 'gin', unique: false, opClass: 'gin_trgm_ops' },\n { name: `${tableName}_givenTrgm_idx`, columns: ['given'], indexType: 'gin', unique: false, opClass: 'gin_trgm_ops' },\n { name: `${tableName}_familyTrgm_idx`, columns: ['family'], indexType: 'gin', unique: false, opClass: 'gin_trgm_ops' },\n { name: `${tableName}_name_idx_tsv`, columns: ['name'], indexType: 'gin', unique: false, expression: `to_tsvector('simple'::regconfig, name)` },\n { name: `${tableName}_given_idx_tsv`, columns: ['given'], indexType: 'gin', unique: false, expression: `to_tsvector('simple'::regconfig, given)` },\n { name: `${tableName}_family_idx_tsv`, columns: ['family'], indexType: 'gin', unique: false, expression: `to_tsvector('simple'::regconfig, family)` },\n ],\n };\n}\n\nfunction buildAddressTable(): GlobalLookupTableSchema {\n const tableName: LookupTableType = 'Address';\n return {\n tableName,\n columns: [\n { name: 'resourceId', type: 'TEXT', notNull: true, primaryKey: false },\n { name: 'resourceType', type: 'TEXT', notNull: true, primaryKey: false },\n { name: 'address', type: 'TEXT', notNull: false, primaryKey: false },\n { name: 'city', type: 'TEXT', notNull: false, primaryKey: false },\n { name: 'country', type: 'TEXT', notNull: false, primaryKey: false },\n { name: 'postalCode', type: 'TEXT', notNull: false, primaryKey: false },\n { name: 'state', type: 'TEXT', notNull: false, primaryKey: false },\n { name: 'use', type: 'TEXT', notNull: false, primaryKey: false },\n ],\n indexes: [\n { name: `${tableName}_resourceId_idx`, columns: ['resourceId'], indexType: 'btree', unique: false },\n { name: `${tableName}_address_idx`, columns: ['address'], indexType: 'btree', unique: false },\n { name: `${tableName}_address_idx_tsv`, columns: ['address'], indexType: 'gin', unique: false, expression: `to_tsvector('simple'::regconfig, address)` },\n { name: `${tableName}_city_idx`, columns: ['city'], indexType: 'btree', unique: false },\n { name: `${tableName}_city_idx_tsv`, columns: ['city'], indexType: 'gin', unique: false, expression: `to_tsvector('simple'::regconfig, city)` },\n { name: `${tableName}_country_idx`, columns: ['country'], indexType: 'btree', unique: false },\n { name: `${tableName}_country_idx_tsv`, columns: ['country'], indexType: 'gin', unique: false, expression: `to_tsvector('simple'::regconfig, country)` },\n { name: `${tableName}_postalCode_idx`, columns: ['postalCode'], indexType: 'btree', unique: false },\n { name: `${tableName}_postalCode_idx_tsv`, columns: ['postalCode'], indexType: 'gin', unique: false, expression: `to_tsvector('simple'::regconfig, \"postalCode\")` },\n { name: `${tableName}_state_idx`, columns: ['state'], indexType: 'btree', unique: false },\n { name: `${tableName}_state_idx_tsv`, columns: ['state'], indexType: 'gin', unique: false, expression: `to_tsvector('simple'::regconfig, state)` },\n { name: `${tableName}_use_idx`, columns: ['use'], indexType: 'btree', unique: false },\n { name: `${tableName}_use_idx_tsv`, columns: ['use'], indexType: 'gin', unique: false, expression: `to_tsvector('simple'::regconfig, use)` },\n ],\n };\n}\n\nfunction buildContactPointTable(): GlobalLookupTableSchema {\n const tableName: LookupTableType = 'ContactPoint';\n return {\n tableName,\n columns: [\n { name: 'resourceId', type: 'TEXT', notNull: true, primaryKey: false },\n { name: 'resourceType', type: 'TEXT', notNull: true, primaryKey: false },\n { name: 'system', type: 'TEXT', notNull: false, primaryKey: false },\n { name: 'value', type: 'TEXT', notNull: false, primaryKey: false },\n { name: 'use', type: 'TEXT', notNull: false, primaryKey: false },\n ],\n indexes: [\n { name: `${tableName}_resourceId_idx`, columns: ['resourceId'], indexType: 'btree', unique: false },\n { name: `${tableName}_system_idx`, columns: ['system'], indexType: 'btree', unique: false },\n { name: `${tableName}_value_idx`, columns: ['value'], indexType: 'btree', unique: false },\n ],\n };\n}\n\nfunction buildIdentifierTable(): GlobalLookupTableSchema {\n const tableName: LookupTableType = 'Identifier';\n return {\n tableName,\n columns: [\n { name: 'resourceId', type: 'TEXT', notNull: true, primaryKey: false },\n { name: 'resourceType', type: 'TEXT', notNull: true, primaryKey: false },\n { name: 'system', type: 'TEXT', notNull: false, primaryKey: false },\n { name: 'value', type: 'TEXT', notNull: false, primaryKey: false },\n ],\n indexes: [\n { name: `${tableName}_resourceId_idx`, columns: ['resourceId'], indexType: 'btree', unique: false },\n { name: `${tableName}_value_idx`, columns: ['value'], indexType: 'btree', unique: false },\n ],\n };\n}\n\n// =============================================================================\n// Section 3c: Shared Token Columns\n// =============================================================================\n\n/**\n * v2: Shared token columns removed.\n * In v2, each token column stores \"system|code\" strings directly.\n * No need for a unified shared token column.\n *\n * @deprecated Kept as empty function for backward compatibility.\n */\nfunction buildSharedTokenColumns(): ColumnSchema[] {\n return [];\n}\n\n/**\n * @deprecated Shared token indexes removed in v2.\n */\nfunction buildSharedTokenIndexes(_resourceType: string): IndexSchema[] {\n return [];\n}\n\n// =============================================================================\n// Section 3d: Trigram Indexes\n// =============================================================================\n\n/**\n * v2: Trigram indexes simplified.\n * In v2, token columns store \"system|code\" strings directly in TEXT/TEXT[].\n * Trigram indexes are only needed for PG TEXT[] columns.\n * For SQLite, these are skipped (no GIN support).\n */\nfunction buildTrigramIndexes(_resourceType: string, _impls: SearchParameterImpl[]): IndexSchema[] {\n // v2: Trigram indexes are PG-only and will be added by PostgresDialect\n // in the DDL generation phase, not in the schema builder.\n return [];\n}\n\n// =============================================================================\n// Section 4: Public API\n// =============================================================================\n\n/**\n * Build the complete 3-table schema for a single resource type.\n *\n * @param resourceType - The FHIR resource type (e.g., `'Patient'`).\n * @param sdRegistry - StructureDefinitionRegistry (used to verify the type exists).\n * @param spRegistry - SearchParameterRegistry (provides search column definitions).\n * @returns The complete `ResourceTableSet` for the resource type.\n * @throws Error if the resource type is not found or is abstract.\n */\nexport function buildResourceTableSet(\n resourceType: string,\n sdRegistry: StructureDefinitionRegistry,\n spRegistry: SearchParameterRegistry,\n): ResourceTableSet {\n const profile = sdRegistry.get(resourceType);\n if (!profile) {\n throw new Error(`Resource type \"${resourceType}\" not found in StructureDefinitionRegistry`);\n }\n if (profile.abstract) {\n throw new Error(`Cannot build table for abstract resource type \"${resourceType}\"`);\n }\n if (profile.kind !== 'resource') {\n throw new Error(`Cannot build table for non-resource type \"${resourceType}\" (kind: ${profile.kind})`);\n }\n\n const isBinary = resourceType === 'Binary';\n const searchImpls = spRegistry.getForResource(resourceType);\n\n // --- Main table ---\n const mainColumns = buildFixedMainColumns();\n if (!isBinary) {\n mainColumns.push(buildCompartmentsColumn());\n }\n mainColumns.push(...buildSearchColumns(searchImpls));\n mainColumns.push(...buildSharedTokenColumns());\n\n const mainIndexes = buildFixedMainIndexes(resourceType);\n if (!isBinary) {\n mainIndexes.push(buildCompartmentsIndex(resourceType));\n }\n mainIndexes.push(...buildSearchIndexes(resourceType, searchImpls));\n mainIndexes.push(...buildSharedTokenIndexes(resourceType));\n mainIndexes.push(...buildTrigramIndexes(resourceType, searchImpls));\n\n const mainConstraints: ConstraintSchema[] = [\n {\n name: `${resourceType}_pk`,\n type: 'primary_key',\n columns: ['id'],\n },\n ];\n\n const main: MainTableSchema = {\n tableName: resourceType,\n resourceType,\n columns: mainColumns,\n indexes: mainIndexes,\n constraints: mainConstraints,\n };\n\n // --- History table ---\n const history: HistoryTableSchema = {\n tableName: `${resourceType}_History`,\n resourceType,\n columns: buildHistoryColumns(),\n indexes: buildHistoryIndexes(resourceType),\n };\n\n // --- References table ---\n const references: ReferencesTableSchema = {\n tableName: `${resourceType}_References`,\n resourceType,\n columns: buildReferencesColumns(),\n indexes: buildReferencesIndexes(resourceType),\n compositePrimaryKey: ['resourceId', 'targetType', 'targetId', 'code'],\n };\n\n // v2: Preserve SP metadata for SchemaDiff\n const searchParamsMeta = searchImpls.map(impl => ({\n code: impl.code,\n type: impl.type,\n expression: impl.expression,\n }));\n\n return {\n resourceType,\n main,\n history,\n references,\n searchParams: searchParamsMeta,\n };\n}\n\n/**\n * Build table schemas for ALL non-abstract resource types.\n *\n * @returns Array of `ResourceTableSet`, one per concrete resource type, sorted alphabetically.\n */\nexport function buildAllResourceTableSets(\n sdRegistry: StructureDefinitionRegistry,\n spRegistry: SearchParameterRegistry,\n): ResourceTableSet[] {\n const resourceTypes = sdRegistry.getTableResourceTypes();\n return resourceTypes.map((rt) => buildResourceTableSet(rt, sdRegistry, spRegistry));\n}\n\n/**\n * Build a complete `SchemaDefinition` for all resource types.\n *\n * @param sdRegistry - StructureDefinitionRegistry with indexed profiles.\n * @param spRegistry - SearchParameterRegistry with indexed search params.\n * @param version - Schema version string (default: `'fhir-r4-v4.0.1'`).\n * @returns The complete `SchemaDefinition`.\n */\nexport function buildSchemaDefinition(\n sdRegistry: StructureDefinitionRegistry,\n spRegistry: SearchParameterRegistry,\n version: string = 'fhir-r4-v4.0.1',\n): SchemaDefinition {\n return {\n version,\n generatedAt: new Date().toISOString(),\n tableSets: buildAllResourceTableSets(sdRegistry, spRegistry),\n globalLookupTables: buildGlobalLookupTables(),\n };\n}\n", "/**\n * DDL Generator\n *\n * Converts `ResourceTableSet` / `SchemaDefinition` to SQL DDL strings.\n * All functions are pure \u2014 no database dependency.\n *\n * v2 upgrade: Now supports both SQLite and PostgreSQL dialects.\n * The `dialect` parameter controls type mapping and syntax differences.\n *\n * ## Output Format\n *\n * - All identifiers are double-quoted for safety\n * - Uses `CREATE TABLE IF NOT EXISTS` / `CREATE INDEX IF NOT EXISTS`\n * - Generates all CREATE TABLEs first, then all CREATE INDEXes\n * - Idempotent \u2014 safe to run multiple times\n *\n * @module fhir-persistence/schema\n */\n\nimport type {\n ColumnSchema,\n IndexSchema,\n ConstraintSchema,\n MainTableSchema,\n HistoryTableSchema,\n ReferencesTableSchema,\n LookupTableSchema,\n GlobalLookupTableSchema,\n ResourceTableSet,\n SchemaDefinition,\n SqlColumnType,\n} from './table-schema.js';\n\n// =============================================================================\n// Section 0: Dialect Type\n// =============================================================================\n\nexport type DDLDialect = 'sqlite' | 'postgres';\n\n/**\n * Map a logical SqlColumnType to the dialect-specific type string.\n *\n * SQLite mappings:\n * - BOOLEAN \u2192 INTEGER\n * - TIMESTAMPTZ \u2192 TEXT\n * - TEXT[] \u2192 TEXT (JSON array)\n * - DOUBLE PRECISION \u2192 REAL\n * - DATE \u2192 TEXT\n * - NUMERIC \u2192 REAL\n * - BIGINT \u2192 INTEGER\n *\n * PostgreSQL: types pass through unchanged.\n */\nfunction mapColumnType(type: SqlColumnType, dialect: DDLDialect): string {\n if (dialect === 'postgres') return type;\n\n // SQLite type mapping\n switch (type) {\n case 'BOOLEAN': return 'INTEGER';\n case 'TIMESTAMPTZ': return 'TEXT';\n case 'TIMESTAMPTZ[]': return 'TEXT';\n case 'TEXT[]': return 'TEXT';\n case 'DOUBLE PRECISION': return 'REAL';\n case 'DOUBLE PRECISION[]': return 'TEXT';\n case 'DATE': return 'TEXT';\n case 'DATE[]': return 'TEXT';\n case 'NUMERIC': return 'REAL';\n case 'BIGINT': return 'INTEGER';\n default: return type;\n }\n}\n\n// =============================================================================\n// Section 1: Column DDL\n// =============================================================================\n\n/**\n * Generate the DDL fragment for a single column definition.\n *\n * Example: `\"id\" TEXT NOT NULL`\n */\nfunction columnDDL(col: ColumnSchema, dialect: DDLDialect = 'postgres'): string {\n const mappedType = mapColumnType(col.type, dialect);\n const parts: string[] = [`\"${col.name}\"`, mappedType];\n\n if (col.notNull) {\n parts.push('NOT NULL');\n }\n\n if (col.defaultValue !== undefined) {\n parts.push(`DEFAULT ${col.defaultValue}`);\n }\n\n return ' ' + parts.join(' ');\n}\n\n// =============================================================================\n// Section 2: Constraint DDL\n// =============================================================================\n\n/**\n * Generate the DDL fragment for a table constraint.\n *\n * Example: `CONSTRAINT \"Patient_pk\" PRIMARY KEY (\"id\")`\n */\nfunction constraintDDL(constraint: ConstraintSchema): string {\n switch (constraint.type) {\n case 'primary_key':\n return ` CONSTRAINT \"${constraint.name}\" PRIMARY KEY (${constraint.columns!.map((c) => `\"${c}\"`).join(', ')})`;\n\n case 'unique':\n return ` CONSTRAINT \"${constraint.name}\" UNIQUE (${constraint.columns!.map((c) => `\"${c}\"`).join(', ')})`;\n\n case 'check':\n return ` CONSTRAINT \"${constraint.name}\" CHECK (${constraint.expression})`;\n }\n}\n\n// =============================================================================\n// Section 3: CREATE TABLE\n// =============================================================================\n\n/**\n * Generate a `CREATE TABLE IF NOT EXISTS` statement for a main table.\n */\nexport function generateCreateMainTable(table: MainTableSchema, dialect: DDLDialect = 'postgres'): string {\n const lines: string[] = [];\n\n lines.push(`CREATE TABLE IF NOT EXISTS \"${table.tableName}\" (`);\n\n const entries: string[] = [];\n for (const col of table.columns) {\n entries.push(columnDDL(col, dialect));\n }\n for (const constraint of table.constraints) {\n entries.push(constraintDDL(constraint));\n }\n\n lines.push(entries.join(',\\n'));\n lines.push(');');\n\n return lines.join('\\n');\n}\n\n/**\n * Generate a `CREATE TABLE IF NOT EXISTS` statement for a history table.\n *\n * v2: Handles versionSeq AUTOINCREMENT for SQLite and GENERATED ALWAYS for PG.\n */\nexport function generateCreateHistoryTable(table: HistoryTableSchema, dialect: DDLDialect = 'postgres'): string {\n const lines: string[] = [];\n\n lines.push(`CREATE TABLE IF NOT EXISTS \"${table.tableName}\" (`);\n\n const entries: string[] = [];\n for (const col of table.columns) {\n if (col.name === 'versionSeq' && col.primaryKey) {\n // Special handling for auto-increment PK\n if (dialect === 'sqlite') {\n entries.push(' \"versionSeq\" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT');\n } else {\n entries.push(' \"versionSeq\" INTEGER GENERATED ALWAYS AS IDENTITY PRIMARY KEY');\n }\n continue;\n }\n entries.push(columnDDL(col, dialect));\n }\n\n // Add UNIQUE constraint on (id, versionId)\n entries.push(` UNIQUE (\"id\", \"versionId\")`);\n\n lines.push(entries.join(',\\n'));\n lines.push(');');\n\n return lines.join('\\n');\n}\n\n/**\n * Generate a `CREATE TABLE IF NOT EXISTS` statement for a references table.\n */\nexport function generateCreateReferencesTable(table: ReferencesTableSchema, dialect: DDLDialect = 'postgres'): string {\n const lines: string[] = [];\n\n lines.push(`CREATE TABLE IF NOT EXISTS \"${table.tableName}\" (`);\n\n const entries: string[] = [];\n for (const col of table.columns) {\n entries.push(columnDDL(col, dialect));\n }\n\n // v2: References tables no longer use composite PK (rows are not unique per (resourceId, target, code))\n // Keeping the constraint generation for backward compatibility if set\n if (table.compositePrimaryKey && table.compositePrimaryKey.length > 0) {\n // Skip composite PK for v2 \u2014 references can have duplicates\n // const pkCols = table.compositePrimaryKey.map((c) => `\"${c}\"`).join(', ');\n // entries.push(` CONSTRAINT \"${table.tableName}_pk\" PRIMARY KEY (${pkCols})`);\n }\n\n lines.push(entries.join(',\\n'));\n lines.push(');');\n\n return lines.join('\\n');\n}\n\n// =============================================================================\n// Section 4: CREATE INDEX\n// =============================================================================\n\n/**\n * Generate a `CREATE INDEX IF NOT EXISTS` statement.\n *\n * Supports:\n * - `opClass` \u2014 operator class appended to each column key (e.g., `gin_trgm_ops`)\n * - `expression` \u2014 functional expression to index instead of plain columns\n * (e.g., `to_tsvector('simple'::regconfig, family)`)\n */\nexport function generateCreateIndex(index: IndexSchema, tableName: string, dialect: DDLDialect = 'postgres'): string | null {\n // SQLite: skip GIN indexes (not supported)\n if (dialect === 'sqlite' && (index.indexType === 'gin' || index.indexType === 'gist')) {\n return null;\n }\n // SQLite: skip expression indexes and opClass indexes (PG-only features)\n if (dialect === 'sqlite' && (index.expression || index.opClass)) {\n return null;\n }\n\n const unique = index.unique ? 'UNIQUE ' : '';\n\n let indexExpr: string;\n if (index.expression) {\n indexExpr = index.expression;\n } else if (index.opClass) {\n indexExpr = index.columns.map((c) => `\"${c}\" ${index.opClass}`).join(', ');\n } else {\n indexExpr = index.columns.map((c) => `\"${c}\"`).join(', ');\n }\n\n let sql: string;\n if (dialect === 'sqlite') {\n // SQLite doesn't support USING clause\n sql = `CREATE ${unique}INDEX IF NOT EXISTS \"${index.name}\" ON \"${tableName}\" (${indexExpr})`;\n } else {\n sql = `CREATE ${unique}INDEX IF NOT EXISTS \"${index.name}\"\\n ON \"${tableName}\" USING ${index.indexType} (${indexExpr})`;\n }\n\n if (index.include && index.include.length > 0 && dialect === 'postgres') {\n const includeCols = index.include.map((c) => `\"${c}\"`).join(', ');\n sql += `\\n INCLUDE (${includeCols})`;\n }\n\n if (index.where) {\n if (dialect === 'sqlite') {\n // SQLite supports WHERE in partial indexes\n sql += ` WHERE ${index.where}`;\n } else {\n sql += `\\n WHERE ${index.where}`;\n }\n }\n\n sql += ';';\n return sql;\n}\n\n// =============================================================================\n// Section 5: Resource DDL (3 tables + all indexes)\n// =============================================================================\n\n/**\n * Generate all DDL statements for a single resource type (3 tables + indexes).\n *\n * Returns an array of SQL statements in order:\n * 1. CREATE TABLE for main table\n * 2. CREATE TABLE for history table\n * 3. CREATE TABLE for references table\n * 4. All CREATE INDEX statements\n */\nexport function generateResourceDDL(tableSet: ResourceTableSet, dialect: DDLDialect = 'postgres'): string[] {\n const statements: string[] = [];\n\n // Tables\n statements.push(generateCreateMainTable(tableSet.main, dialect));\n statements.push(generateCreateHistoryTable(tableSet.history, dialect));\n statements.push(generateCreateReferencesTable(tableSet.references, dialect));\n\n // Indexes \u2014 main table\n for (const idx of tableSet.main.indexes) {\n const sql = generateCreateIndex(idx, tableSet.main.tableName, dialect);\n if (sql) statements.push(sql);\n }\n\n // Indexes \u2014 history table\n for (const idx of tableSet.history.indexes) {\n const sql = generateCreateIndex(idx, tableSet.history.tableName, dialect);\n if (sql) statements.push(sql);\n }\n\n // Indexes \u2014 references table\n for (const idx of tableSet.references.indexes) {\n const sql = generateCreateIndex(idx, tableSet.references.tableName, dialect);\n if (sql) statements.push(sql);\n }\n\n return statements;\n}\n\n/**\n * Generate a `CREATE TABLE IF NOT EXISTS` statement for a lookup sub-table.\n */\nexport function generateCreateLookupTable(table: LookupTableSchema, dialect: DDLDialect = 'postgres'): string {\n const lines: string[] = [];\n\n lines.push(`CREATE TABLE IF NOT EXISTS \"${table.tableName}\" (`);\n\n const entries: string[] = [];\n for (const col of table.columns) {\n entries.push(columnDDL(col, dialect));\n }\n\n if (table.compositePrimaryKey.length > 0) {\n const pkCols = table.compositePrimaryKey.map((c) => `\"${c}\"`).join(', ');\n entries.push(` CONSTRAINT \"${table.tableName}_pk\" PRIMARY KEY (${pkCols})`);\n }\n\n lines.push(entries.join(',\\n'));\n lines.push(');');\n\n return lines.join('\\n');\n}\n\n// =============================================================================\n// Section 6: Full Schema DDL\n// =============================================================================\n\n/**\n * Generate a `CREATE TABLE IF NOT EXISTS` statement for a global lookup table.\n */\nexport function generateCreateGlobalLookupTable(table: GlobalLookupTableSchema, dialect: DDLDialect = 'postgres'): string {\n const lines: string[] = [];\n\n lines.push(`CREATE TABLE IF NOT EXISTS \"${table.tableName}\" (`);\n\n const entries: string[] = [];\n for (const col of table.columns) {\n entries.push(columnDDL(col, dialect));\n }\n\n lines.push(entries.join(',\\n'));\n lines.push(');');\n\n return lines.join('\\n');\n}\n\n/**\n * Generate all DDL statements for a complete schema definition.\n *\n * Order:\n * 1. Global lookup tables (HumanName, Address, ContactPoint, Identifier)\n * 2. Resource tables (main, history, references)\n * 3. All indexes (global lookup + resource tables)\n *\n * @param schema - The complete schema definition.\n * @returns Array of SQL DDL statements.\n */\nexport function generateSchemaDDL(schema: SchemaDefinition, dialect: DDLDialect = 'postgres'): string[] {\n const tableStatements: string[] = [];\n const indexStatements: string[] = [];\n\n // PG-only extensions\n if (dialect === 'postgres') {\n tableStatements.push('CREATE EXTENSION IF NOT EXISTS pg_trgm;');\n tableStatements.push('CREATE EXTENSION IF NOT EXISTS btree_gin;');\n tableStatements.push(\n `CREATE OR REPLACE FUNCTION token_array_to_text(arr text[]) RETURNS text LANGUAGE sql IMMUTABLE AS $$ SELECT array_to_string(arr, ' ') $$;`,\n );\n }\n\n // Global lookup tables first\n if (schema.globalLookupTables) {\n for (const lookup of schema.globalLookupTables) {\n tableStatements.push(generateCreateGlobalLookupTable(lookup, dialect));\n }\n for (const lookup of schema.globalLookupTables) {\n for (const idx of lookup.indexes) {\n const sql = generateCreateIndex(idx, lookup.tableName, dialect);\n if (sql) indexStatements.push(sql);\n }\n }\n }\n\n // Resource tables\n for (const tableSet of schema.tableSets) {\n tableStatements.push(generateCreateMainTable(tableSet.main, dialect));\n tableStatements.push(generateCreateHistoryTable(tableSet.history, dialect));\n tableStatements.push(generateCreateReferencesTable(tableSet.references, dialect));\n\n for (const idx of tableSet.main.indexes) {\n const sql = generateCreateIndex(idx, tableSet.main.tableName, dialect);\n if (sql) indexStatements.push(sql);\n }\n for (const idx of tableSet.history.indexes) {\n const sql = generateCreateIndex(idx, tableSet.history.tableName, dialect);\n if (sql) indexStatements.push(sql);\n }\n for (const idx of tableSet.references.indexes) {\n const sql = generateCreateIndex(idx, tableSet.references.tableName, dialect);\n if (sql) indexStatements.push(sql);\n }\n }\n\n return [...tableStatements, ...indexStatements];\n}\n\n/**\n * Generate the complete DDL as a single string, with statements\n * separated by double newlines.\n *\n * Includes a header comment with version and generation timestamp.\n */\nexport function generateSchemaDDLString(schema: SchemaDefinition, dialect: DDLDialect = 'postgres'): string {\n const header = [\n `-- MedXAI FHIR Schema DDL`,\n `-- Version: ${schema.version}`,\n `-- Dialect: ${dialect}`,\n `-- Generated: ${schema.generatedAt}`,\n `-- Resource types: ${schema.tableSets.length}`,\n `--`,\n `-- This file is auto-generated. Do not edit manually.`,\n '',\n ].join('\\n');\n\n const statements = generateSchemaDDL(schema, dialect);\n return header + statements.join('\\n\\n') + '\\n';\n}\n", "/**\n * Repository Types & Interfaces\n *\n * Defines the contract for FHIR resource persistence operations.\n * All implementations must support transactional CRUD with versioning.\n *\n * Design decisions (from WF-E2E-001 Medplum analysis):\n * - `id` and `versionId` are UUIDs, generated app-side\n * - Every write produces a new history entry (new version snapshot)\n * - Soft delete: `deleted=true`, `content=''`, `__version=-1`\n * - Optimistic locking via `ifMatch` (versionId comparison)\n *\n * @module fhir-persistence/repo\n */\n\n// =============================================================================\n// Section 0: Operation Context (ADR-006)\n// =============================================================================\n\n/**\n * Operation context \u2014 flows through all CRUD/Search operations.\n *\n * S1 (Phase B): Only `project` is used \u2014 multi-tenant isolation.\n * S5 (Phase C): Will extend to use `author`, `accessPolicy`, `superAdmin`.\n */\nexport interface OperationContext {\n /** Current project ID for multi-tenant scoping. */\n project?: string;\n\n /** The actor performing the operation (User/Bot/ClientApplication reference). */\n author?: string;\n\n /** The AccessPolicy ID bound to this operation. */\n accessPolicy?: string;\n\n /** Whether this is a super-admin operation (bypasses project scoping). */\n superAdmin?: boolean;\n}\n\n// =============================================================================\n// Section 0b: Platform Resource Type Guards (ADR-006)\n// =============================================================================\n\n/**\n * Platform resource types that require special handling.\n *\n * These are MedXAI-defined resources (not part of FHIR R4 base spec).\n * They participate in multi-tenant isolation via `projectId`.\n */\nexport const PLATFORM_RESOURCE_TYPES: ReadonlySet<string> = new Set([\n 'Project',\n 'User',\n 'ProjectMembership',\n 'Login',\n 'ClientApplication',\n 'AccessPolicy',\n 'JsonWebKey',\n]);\n\n/**\n * Protected resource types that can only be managed by super-admins or\n * the system itself. Normal project-scoped operations cannot create/update/delete these.\n *\n * Phase B: informational only \u2014 enforcement deferred to Phase C (Auth).\n */\nexport const PROTECTED_RESOURCE_TYPES: ReadonlySet<string> = new Set([\n 'Project',\n 'JsonWebKey',\n]);\n\n/**\n * Resource types that can be managed by project admins (not just super-admins).\n *\n * Phase B: informational only \u2014 enforcement deferred to Phase C (Auth).\n */\nexport const PROJECT_ADMIN_RESOURCE_TYPES: ReadonlySet<string> = new Set([\n 'ProjectMembership',\n 'ClientApplication',\n 'AccessPolicy',\n 'User',\n 'Login',\n]);\n\n// =============================================================================\n// Section 1: FHIR Resource Shape\n// =============================================================================\n\n/**\n * Minimal FHIR resource shape for persistence operations.\n *\n * This is intentionally loose \u2014 the repository does not validate\n * resource structure (that's the validator's job). It only requires\n * `resourceType` and optionally `id` / `meta`.\n */\nexport interface FhirResource {\n resourceType: string;\n id?: string;\n meta?: FhirMeta;\n [key: string]: unknown;\n}\n\n/**\n * FHIR Meta element (subset used by the repository).\n */\nexport interface FhirMeta {\n versionId?: string;\n lastUpdated?: string;\n source?: string;\n profile?: string[];\n [key: string]: unknown;\n}\n\n/**\n * A FHIR resource that has been persisted (id and meta are guaranteed).\n */\nexport interface PersistedResource extends FhirResource {\n id: string;\n meta: FhirMeta & {\n versionId: string;\n lastUpdated: string;\n };\n}\n\n// =============================================================================\n// Section 2: Repository Options\n// =============================================================================\n\n/**\n * Options for `createResource()`.\n */\nexport interface CreateResourceOptions {\n /**\n * Pre-assigned UUID for the resource.\n * Used in batch/transaction operations where the ID is determined\n * before the create call.\n */\n assignedId?: string;\n}\n\n/**\n * Options for `updateResource()`.\n */\nexport interface UpdateResourceOptions {\n /**\n * Expected versionId for optimistic locking.\n * If provided and does not match the current versionId,\n * the update is rejected with `ResourceVersionConflictError`.\n *\n * Corresponds to the HTTP `If-Match` header.\n */\n ifMatch?: string;\n}\n\n/**\n * Options for history queries.\n */\nexport interface HistoryOptions {\n /**\n * Only include versions updated after this instant.\n * Corresponds to the `_since` parameter.\n */\n since?: string;\n\n /**\n * Maximum number of entries to return.\n * Corresponds to the `_count` parameter.\n */\n count?: number;\n\n /**\n * Cursor for pagination \u2014 the `lastUpdated` value of the last\n * entry from the previous page. Only entries with `lastUpdated`\n * strictly before this value are returned.\n */\n cursor?: string;\n}\n\n/**\n * A single entry in a history result, including delete markers.\n */\nexport interface HistoryEntry {\n /** The resource (null for delete entries). */\n resource: PersistedResource | null;\n /** The versionId for this entry. */\n versionId: string;\n /** The timestamp of this version. */\n lastUpdated: string;\n /** Whether this entry represents a deletion. */\n deleted: boolean;\n /** The resource type (needed for delete entries where resource is null). */\n resourceType: string;\n /** The resource id. */\n id: string;\n}\n\n// =============================================================================\n// Section 3: Search Options\n// =============================================================================\n\n/**\n * Options for search execution.\n */\nexport interface SearchOptions {\n /** Whether to include total count. */\n total?: 'none' | 'estimate' | 'accurate';\n}\n\n/**\n * Result of a search execution.\n */\nexport interface SearchResult {\n /** Matched resources. */\n resources: PersistedResource[];\n /** Included resources from _include/_revinclude (search.mode = 'include'). */\n included?: PersistedResource[];\n /** Total count (only when `total=accurate`). */\n total?: number;\n}\n\n// =============================================================================\n// Section 4: Repository Interface\n// =============================================================================\n\n/**\n * FHIR Resource Repository \u2014 persistence contract.\n *\n * All write operations are transactional (ACID).\n * All write operations produce a history entry.\n */\nexport interface ResourceRepository {\n /**\n * Create a new FHIR resource.\n *\n * - Generates `id` (UUID) if not provided via `options.assignedId`\n * - Generates `meta.versionId` (UUID)\n * - Sets `meta.lastUpdated` to current time\n * - Writes to main table + history table in a transaction\n * - If `context.project` is set, injects projectId into the row\n *\n * @returns The persisted resource with populated `id` and `meta`.\n */\n createResource<T extends FhirResource>(\n resource: T,\n options?: CreateResourceOptions,\n context?: OperationContext,\n ): Promise<T & PersistedResource>;\n\n /**\n * Read a resource by type and ID.\n *\n * When `context.project` is set, verifies the resource belongs to that project.\n *\n * @throws ResourceNotFoundError if the resource does not exist.\n * @throws ResourceGoneError if the resource has been deleted.\n */\n readResource(resourceType: string, id: string, context?: OperationContext): Promise<PersistedResource>;\n\n /**\n * Update an existing resource.\n *\n * - The resource must have `id` set.\n * - Generates new `meta.versionId` (UUID)\n * - Sets `meta.lastUpdated` to current time\n * - Writes to main table (UPSERT) + history table in a transaction\n * - If `options.ifMatch` is set, performs optimistic locking check\n * - If `context.project` is set, injects projectId into the row\n *\n * @throws ResourceNotFoundError if the resource does not exist.\n * @throws ResourceGoneError if the resource has been deleted.\n * @throws ResourceVersionConflictError if `ifMatch` does not match.\n */\n updateResource<T extends FhirResource>(\n resource: T,\n options?: UpdateResourceOptions,\n context?: OperationContext,\n ): Promise<T & PersistedResource>;\n\n /**\n * Soft-delete a resource.\n *\n * - Sets `deleted=true`, `content=''`, `__version=-1`\n * - Writes a delete history entry\n *\n * @throws ResourceNotFoundError if the resource does not exist.\n * @throws ResourceGoneError if already deleted.\n */\n deleteResource(resourceType: string, id: string, context?: OperationContext): Promise<void>;\n\n /**\n * Read the version history of a resource (newest first).\n */\n readHistory(\n resourceType: string,\n id: string,\n options?: HistoryOptions,\n ): Promise<HistoryEntry[]>;\n\n /**\n * Read type-level history (all changes to a resource type, newest first).\n */\n readTypeHistory(\n resourceType: string,\n options?: HistoryOptions,\n ): Promise<HistoryEntry[]>;\n\n /**\n * Read a specific version of a resource.\n *\n * @throws ResourceNotFoundError if the version does not exist.\n */\n readVersion(\n resourceType: string,\n id: string,\n versionId: string,\n ): Promise<PersistedResource>;\n\n /**\n * Search for resources matching the given search request.\n *\n * - Executes parameterized SQL built from the search request\n * - Optionally returns total count when `options.total === 'accurate'`\n * - If `context.project` is set, adds projectId filter to the query\n *\n * @param request - Parsed FHIR search request.\n * @param options - Search options (e.g., total mode).\n * @param context - Operation context for project scoping.\n * @returns Search result with matched resources and optional total.\n */\n searchResources(\n request: import('../search/types.js').SearchRequest,\n options?: SearchOptions,\n context?: OperationContext,\n ): Promise<SearchResult>;\n}\n\n// =============================================================================\n// Section 4: Internal Row Types\n// =============================================================================\n\n/**\n * v1 ResourceRow \u2014 preserved for backward compatibility with FhirRepository (PG).\n * @deprecated Use ResourceRowV2 for new code.\n */\nexport interface ResourceRow {\n [key: string]: unknown;\n id: string;\n content: string;\n lastUpdated: string;\n deleted: boolean;\n projectId: string;\n __version: number;\n _source?: string;\n _profile?: string[];\n compartments?: string[];\n}\n\n/**\n * v2 ResourceRow \u2014 dialect-neutral, no projectId/__version.\n *\n * Changes from v1:\n * - Removed `projectId` (no multi-tenancy)\n * - Removed `__version` (schema version tracking)\n * - Added `versionId` (UUID for ETag / optimistic locking)\n * - `deleted` is number (0/1) for SQLite compat\n * - `_profile` is JSON string, not string[]\n * - `compartments` is JSON string, not string[]\n */\nexport interface ResourceRowV2 {\n [key: string]: unknown;\n id: string;\n versionId: string;\n content: string;\n lastUpdated: string;\n deleted: number;\n _source?: string | null;\n _profile?: string | null;\n compartments?: string | null;\n}\n\n/**\n * v1 HistoryRow \u2014 preserved for backward compatibility.\n * @deprecated Use HistoryRowV2 for new code.\n */\nexport interface HistoryRow {\n [key: string]: unknown;\n id: string;\n versionId: string;\n lastUpdated: string;\n content: string;\n}\n\n/**\n * v2 HistoryRow \u2014 includes deleted flag.\n *\n * Changes from v1:\n * - Added `deleted` (0/1) for soft-delete tracking\n * - `content` preserved even on delete (ADR-08)\n */\nexport interface HistoryRowV2 {\n [key: string]: unknown;\n id: string;\n versionId: string;\n lastUpdated: string;\n content: string;\n deleted: number;\n}\n\n/**\n * Schema version constant.\n *\n * Tracks the schema migration version (not the resource version).\n * Incremented when the schema structure changes.\n * Set to -1 for deleted resources.\n */\nexport const SCHEMA_VERSION = 1;\n\n/**\n * Schema version for deleted resources.\n */\nexport const DELETED_SCHEMA_VERSION = -1;\n", "/**\n * Repository Error Hierarchy\n *\n * Maps to standard FHIR/HTTP error semantics:\n * - 404 Not Found \u2192 ResourceNotFoundError\n * - 410 Gone \u2192 ResourceGoneError\n * - 412 Precondition Failed \u2192 ResourceVersionConflictError\n *\n * @module fhir-persistence/repo\n */\n\n// =============================================================================\n// Section 1: Base Error\n// =============================================================================\n\n/**\n * Base class for all repository errors.\n */\nexport class RepositoryError extends Error {\n override readonly name: string = 'RepositoryError';\n\n constructor(message: string) {\n super(message);\n Object.setPrototypeOf(this, new.target.prototype);\n }\n}\n\n// =============================================================================\n// Section 2: Specific Errors\n// =============================================================================\n\n/**\n * Resource not found (HTTP 404).\n */\nexport class ResourceNotFoundError extends RepositoryError {\n override readonly name = 'ResourceNotFoundError';\n readonly resourceType: string;\n readonly resourceId: string;\n\n constructor(resourceType: string, id: string) {\n super(`${resourceType}/${id} not found`);\n this.resourceType = resourceType;\n this.resourceId = id;\n }\n}\n\n/**\n * Resource has been deleted (HTTP 410 Gone).\n */\nexport class ResourceGoneError extends RepositoryError {\n override readonly name = 'ResourceGoneError';\n readonly resourceType: string;\n readonly resourceId: string;\n\n constructor(resourceType: string, id: string) {\n super(`${resourceType}/${id} has been deleted`);\n this.resourceType = resourceType;\n this.resourceId = id;\n }\n}\n\n/**\n * Multiple matches found for conditional operation (HTTP 412 Precondition Failed).\n *\n * Thrown when a conditional update/delete matches more than one resource.\n */\nexport class PreconditionFailedError extends RepositoryError {\n override readonly name = 'PreconditionFailedError';\n readonly resourceType: string;\n readonly matchCount: number;\n\n constructor(resourceType: string, matchCount: number) {\n super(\n `Conditional operation on ${resourceType} matched ${matchCount} resources (expected 0 or 1)`,\n );\n this.resourceType = resourceType;\n this.matchCount = matchCount;\n }\n}\n\n/**\n * Optimistic locking conflict (HTTP 412 Precondition Failed).\n *\n * Thrown when `ifMatch` (expected versionId) does not match\n * the current versionId of the resource.\n */\nexport class ResourceVersionConflictError extends RepositoryError {\n override readonly name = 'ResourceVersionConflictError';\n readonly resourceType: string;\n readonly resourceId: string;\n readonly expectedVersion: string;\n readonly actualVersion: string;\n\n constructor(\n resourceType: string,\n id: string,\n expectedVersion: string,\n actualVersion: string,\n ) {\n super(\n `Version conflict for ${resourceType}/${id}: ` +\n `expected ${expectedVersion}, actual ${actualVersion}`,\n );\n this.resourceType = resourceType;\n this.resourceId = id;\n this.expectedVersion = expectedVersion;\n this.actualVersion = actualVersion;\n }\n}\n", "/**\n * Row Indexer\n *\n * Extracts search parameter values from FHIR resource JSON and produces\n * column name \u2192 value pairs for the main table's search columns.\n *\n * Phase 14: Uses simplified property path extraction (not full FHIRPath).\n * Full FHIRPath evaluation can be added in a future phase.\n *\n * @module fhir-persistence/repo\n */\n\nimport { createHash } from \"node:crypto\";\nimport type { SearchParameterImpl } from \"../registry/search-parameter-registry.js\";\nimport type { LookupTableType } from \"../schema/table-schema.js\";\nimport type { FhirResource } from \"./types.js\";\n\n// =============================================================================\n// Section 1: Types\n// =============================================================================\n\n/**\n * Search column values to merge into the main table row.\n */\nexport interface SearchColumnValues {\n [columnName: string]: unknown;\n}\n\n// =============================================================================\n// Section 2: Token Hashing\n// =============================================================================\n\n/**\n * Generate a deterministic UUID-like hash for a token value.\n *\n * Produces a v4-format UUID string from the SHA-256 hash of `system|code`.\n * This matches Medplum's approach of using a deterministic hash for token\n * search columns (UUID[] type).\n */\nexport function hashToken(system: string, code: string): string {\n const input = `${system}|${code}`;\n const hash = createHash(\"sha256\").update(input).digest(\"hex\");\n // Format as UUID: 8-4-4-4-12\n return [\n hash.slice(0, 8),\n hash.slice(8, 12),\n hash.slice(12, 16),\n hash.slice(16, 20),\n hash.slice(20, 32),\n ].join(\"-\");\n}\n\n// =============================================================================\n// Section 3: Expression Path Parsing\n// =============================================================================\n\n/**\n * Extract the property path for a given resource type from a FHIRPath expression.\n *\n * Handles:\n * - Simple: `\"Patient.birthDate\"` \u2192 `[\"birthDate\"]`\n * - Union: `\"Patient.name | Practitioner.name\"` \u2192 `[\"name\"]` (for Patient)\n * - .where(): `\"Account.subject.where(resolve() is Patient)\"` \u2192 `[\"subject\"]`\n * - Nested: `\"Observation.value.as(Quantity)\"` \u2192 `[\"valueQuantity\"]` (special)\n * - Deep: `\"Patient.contact.name\"` \u2192 `[\"contact\", \"name\"]`\n *\n * @returns Array of path segments, or null if no matching path found.\n */\nexport function extractPropertyPath(\n expression: string,\n resourceType: string,\n): string[] | null {\n if (!expression) return null;\n\n // Split by union operator and find the path for this resource type\n const parts = expression.split(\"|\").map((p) => p.trim());\n let matchedPath: string | null = null;\n\n for (const part of parts) {\n if (part.startsWith(`${resourceType}.`)) {\n matchedPath = part;\n break;\n }\n }\n\n if (!matchedPath) return null;\n\n // Strip resource type prefix\n let path = matchedPath.slice(resourceType.length + 1);\n\n // Strip .where(...) clauses (handles nested parens like .where(resolve() is Patient))\n // Use greedy match to consume all content including nested parens\n path = path.replace(/\\.where\\(.*\\)/g, \"\");\n\n // Strip .as(...) type casts\n path = path.replace(/\\.as\\([^)]*\\)/g, \"\");\n\n // Strip .resolve() calls\n path = path.replace(/\\.resolve\\(\\)/g, \"\");\n\n // Strip trailing dots\n path = path.replace(/\\.+$/, \"\");\n\n if (!path) return null;\n\n return path.split(\".\");\n}\n\n// =============================================================================\n// Section 4: Value Extraction\n// =============================================================================\n\n/**\n * Navigate a resource object using a property path and return the value(s).\n *\n * Handles arrays at any level \u2014 if a path segment hits an array,\n * the remaining path is applied to each element.\n *\n * @returns Array of extracted values (may be empty).\n */\nexport function getNestedValues(\n obj: unknown,\n pathSegments: string[],\n): unknown[] {\n if (obj === null || obj === undefined) return [];\n\n if (Array.isArray(obj)) {\n // Flatten: apply remaining path to each array element\n const results: unknown[] = [];\n for (const item of obj) {\n results.push(...getNestedValues(item, pathSegments));\n }\n return results;\n }\n\n if (pathSegments.length === 0) return [obj];\n\n const [head, ...rest] = pathSegments;\n\n if (typeof obj === \"object\") {\n const record = obj as Record<string, unknown>;\n const value = record[head];\n if (value === undefined || value === null) return [];\n return getNestedValues(value, rest);\n }\n\n return [];\n}\n\n/**\n * Extract a reference string from a FHIR Reference object.\n *\n * Input: `{ reference: \"Patient/123\", display: \"John\" }`\n * Output: `\"Patient/123\"`\n */\nfunction extractReferenceValue(value: unknown): string | null {\n if (typeof value === \"string\") return value;\n if (typeof value === \"object\" && value !== null) {\n const ref = (value as Record<string, unknown>).reference;\n if (typeof ref === \"string\") return ref;\n }\n return null;\n}\n\n/**\n * Extract token values (system|code pairs) from a FHIR value.\n *\n * Handles:\n * - Coding: `{ system, code, display }`\n * - CodeableConcept: `{ coding: [{ system, code }], text }`\n * - code (string): plain string value\n * - boolean: `\"true\"` or `\"false\"`\n * - Identifier: `{ system, value }`\n */\nfunction extractTokenValues(\n value: unknown,\n): Array<{ system: string; code: string; display: string }> {\n if (value === null || value === undefined) return [];\n\n // Boolean\n if (typeof value === \"boolean\") {\n return [{ system: \"\", code: String(value), display: String(value) }];\n }\n\n // Plain string (code)\n if (typeof value === \"string\") {\n return [{ system: \"\", code: value, display: value }];\n }\n\n if (typeof value !== \"object\") return [];\n\n const obj = value as Record<string, unknown>;\n\n // CodeableConcept: has `coding` array\n if (Array.isArray(obj.coding)) {\n const results: Array<{ system: string; code: string; display: string }> =\n [];\n for (const coding of obj.coding) {\n if (typeof coding === \"object\" && coding !== null) {\n const c = coding as Record<string, unknown>;\n const system = typeof c.system === \"string\" ? c.system : \"\";\n const code = typeof c.code === \"string\" ? c.code : \"\";\n const display = typeof c.display === \"string\" ? c.display : \"\";\n if (code) {\n results.push({ system, code, display });\n }\n }\n }\n // Also include text if present\n if (typeof obj.text === \"string\" && results.length === 0) {\n results.push({ system: \"\", code: obj.text, display: obj.text });\n }\n return results;\n }\n\n // Coding: has `code` field (but not `coding` array)\n if (typeof obj.code === \"string\") {\n const system = typeof obj.system === \"string\" ? obj.system : \"\";\n const display = typeof obj.display === \"string\" ? obj.display : \"\";\n return [{ system, code: obj.code, display }];\n }\n\n // Identifier: has `value` field\n if (typeof obj.value === \"string\") {\n const system = typeof obj.system === \"string\" ? obj.system : \"\";\n return [{ system, code: obj.value, display: obj.value }];\n }\n\n return [];\n}\n\n/**\n * Extract a sort-friendly string from a HumanName or Address value.\n *\n * HumanName: family + \" \" + given.join(\" \")\n * Address: line.join(\" \") + \" \" + city + \" \" + state + \" \" + postalCode\n * String: as-is\n */\nfunction extractSortString(value: unknown): string | null {\n if (typeof value === \"string\") return value;\n if (typeof value !== \"object\" || value === null) return null;\n\n const obj = value as Record<string, unknown>;\n\n // HumanName\n if (typeof obj.family === \"string\" || Array.isArray(obj.given)) {\n const parts: string[] = [];\n if (typeof obj.family === \"string\") parts.push(obj.family);\n if (Array.isArray(obj.given)) {\n for (const g of obj.given) {\n if (typeof g === \"string\") parts.push(g);\n }\n }\n return parts.join(\" \") || null;\n }\n\n // Address\n if (Array.isArray(obj.line) || typeof obj.city === \"string\") {\n const parts: string[] = [];\n if (Array.isArray(obj.line)) {\n for (const l of obj.line) {\n if (typeof l === \"string\") parts.push(l);\n }\n }\n if (typeof obj.city === \"string\") parts.push(obj.city);\n if (typeof obj.state === \"string\") parts.push(obj.state);\n if (typeof obj.postalCode === \"string\") parts.push(obj.postalCode);\n if (typeof obj.country === \"string\") parts.push(obj.country);\n return parts.join(\" \") || null;\n }\n\n // ContactPoint (telecom)\n if (typeof obj.value === \"string\") {\n return obj.value;\n }\n\n return null;\n}\n\n// =============================================================================\n// Section 5: Main Entry Point\n// =============================================================================\n\n/**\n * Build search column values for a FHIR resource.\n *\n * Given a resource and its applicable SearchParameterImpl list,\n * extracts values from the resource JSON and returns a map of\n * column name \u2192 value pairs ready for SQL insertion.\n *\n * @param resource - The FHIR resource to index.\n * @param impls - SearchParameterImpl list for this resource type.\n * @returns Column name \u2192 value map for search columns.\n */\nexport function buildSearchColumns(\n resource: FhirResource,\n impls: SearchParameterImpl[],\n): SearchColumnValues {\n const columns: SearchColumnValues = {};\n const resourceType = resource.resourceType;\n\n for (const impl of impls) {\n const path = extractPropertyPath(impl.expression, resourceType);\n if (!path) continue;\n\n switch (impl.strategy) {\n case \"column\":\n populateColumnStrategy(resource, impl, path, columns);\n break;\n case \"token-column\":\n populateTokenColumnStrategy(resource, impl, path, columns);\n break;\n case \"lookup-table\":\n populateLookupTableStrategy(resource, impl, path, columns);\n break;\n }\n }\n\n return columns;\n}\n\n// =============================================================================\n// Section 6: Strategy Handlers\n// =============================================================================\n\n/**\n * Populate a direct column value (string, date, reference, number, uri).\n */\nfunction populateColumnStrategy(\n resource: FhirResource,\n impl: SearchParameterImpl,\n path: string[],\n columns: SearchColumnValues,\n): void {\n const values = getNestedValues(resource, path);\n if (values.length === 0) return;\n\n if (impl.type === \"reference\") {\n const refs = values\n .map(extractReferenceValue)\n .filter((r): r is string => r !== null);\n if (refs.length === 0) return;\n\n if (impl.array) {\n columns[impl.columnName] = refs;\n } else {\n columns[impl.columnName] = refs[0];\n }\n return;\n }\n\n // For date, number, string, uri \u2014 take the first primitive value\n const primitives = values.filter(\n (v) =>\n typeof v === \"string\" || typeof v === \"number\" || typeof v === \"boolean\",\n );\n if (primitives.length === 0) return;\n\n if (impl.array) {\n columns[impl.columnName] = primitives;\n } else {\n columns[impl.columnName] = primitives[0];\n }\n}\n\n/**\n * Populate token-column values (2 columns: __X TEXT[], __XSort TEXT).\n *\n * v2 DDL produces only 2 columns per token-column SearchParameter:\n * - `__<name>` \u2014 TEXT[] of \"system|code\" strings (not UUID hashes)\n * - `__<name>Sort` \u2014 display text for :text modifier search\n */\nfunction populateTokenColumnStrategy(\n resource: FhirResource,\n impl: SearchParameterImpl,\n path: string[],\n columns: SearchColumnValues,\n): void {\n const values = getNestedValues(resource, path);\n if (values.length === 0) return;\n\n const allTokens: Array<{ system: string; code: string; display: string }> =\n [];\n for (const val of values) {\n allTokens.push(...extractTokenValues(val));\n }\n\n if (allTokens.length === 0) return;\n\n // Token column: __<name> TEXT[] \u2014 \"system|code\" strings (v2 DDL: TEXT[], not UUID[])\n const tokenStrings: string[] = [];\n for (const t of allTokens) {\n // With system: \"system|code\"\n if (t.system) {\n tokenStrings.push(`${t.system}|${t.code}`);\n }\n // Without system (or as fallback): \"|code\"\n tokenStrings.push(`|${t.code}`);\n }\n columns[`__${impl.columnName}`] = tokenStrings;\n\n // Sort column: __<name>Sort TEXT \u2014 display text for :text modifier search\n const sortValue = allTokens[0].display\n || (allTokens[0].system ? `${allTokens[0].system}|${allTokens[0].code}` : allTokens[0].code)\n || null;\n columns[`__${impl.columnName}Sort`] = sortValue;\n}\n\n/**\n * Populate lookup-table sort column only (__<name>Sort TEXT).\n *\n * The actual lookup table data is written separately (future phase).\n */\nfunction populateLookupTableStrategy(\n resource: FhirResource,\n impl: SearchParameterImpl,\n path: string[],\n columns: SearchColumnValues,\n): void {\n const values = getNestedValues(resource, path);\n if (values.length === 0) return;\n\n // Extract sort string from first value\n const sortStr = extractSortString(values[0]);\n if (sortStr) {\n columns[`__${impl.columnName}Sort`] = sortStr;\n }\n}\n\n// =============================================================================\n// Section 6b: Shared Token Aggregation\n// =============================================================================\n\n/**\n * Build shared token columns by aggregating token values from\n * `identifier`, `_tag`, and `_security` into unified arrays.\n *\n * Called after buildSearchColumns() and buildMetadataColumns()\n * to merge their token values.\n */\nexport function buildSharedTokenColumns(\n searchCols: SearchColumnValues,\n metadataCols: SearchColumnValues,\n): SearchColumnValues {\n const allTexts: string[] = [];\n\n // Collect from identifier token columns (search columns)\n // v2: __identifier stores TEXT[] of \"system|code\" strings directly\n if (Array.isArray(searchCols[\"__identifier\"])) {\n allTexts.push(...(searchCols[\"__identifier\"] as string[]));\n }\n\n // Collect from _tag (metadata columns \u2014 triple underscore)\n if (Array.isArray(metadataCols[\"___tag\"])) {\n allTexts.push(...(metadataCols[\"___tag\"] as string[]));\n }\n\n // Collect from _security (metadata columns \u2014 triple underscore)\n if (Array.isArray(metadataCols[\"___security\"])) {\n allTexts.push(...(metadataCols[\"___security\"] as string[]));\n }\n\n const result: SearchColumnValues = {};\n if (allTexts.length > 0) {\n result[\"__sharedTokens\"] = allTexts;\n }\n return result;\n}\n\n// =============================================================================\n// Section 7: Metadata Column Population\n// =============================================================================\n\n/**\n * Build metadata search column values from a FHIR resource's `meta` element.\n *\n * Extracts `meta.tag` and `meta.security` into the fixed metadata columns:\n * - `___tag` TEXT[] of \"system|code\" strings, `___tagSort` TEXT (triple underscore \u2014 matches Medplum)\n * - `___security` TEXT[] of \"system|code\" strings, `___securitySort` TEXT\n *\n * v2 DDL: 2 columns per metadata token (not 3). No UUID hash, no Text column.\n *\n * @param resource - The FHIR resource to extract metadata from.\n * @returns Column name \u2192 value map for metadata search columns.\n */\nexport function buildMetadataColumns(\n resource: FhirResource,\n): SearchColumnValues {\n const columns: SearchColumnValues = {};\n const meta = (resource as Record<string, unknown>).meta as\n | Record<string, unknown>\n | undefined;\n if (!meta) return columns;\n\n // _tag \u2014 meta.tag (array of Coding)\n if (Array.isArray(meta.tag)) {\n const tokens: Array<{ system: string; code: string; display: string }> = [];\n for (const tag of meta.tag) {\n tokens.push(...extractTokenValues(tag));\n }\n if (tokens.length > 0) {\n const tagStrings: string[] = [];\n for (const t of tokens) {\n if (t.system) tagStrings.push(`${t.system}|${t.code}`);\n tagStrings.push(`|${t.code}`);\n }\n columns[\"___tag\"] = tagStrings;\n columns[\"___tagSort\"] = tokens[0].display\n || (tokens[0].system ? `${tokens[0].system}|${tokens[0].code}` : tokens[0].code)\n || null;\n }\n }\n\n // _security \u2014 meta.security (array of Coding)\n if (Array.isArray(meta.security)) {\n const tokens: Array<{ system: string; code: string; display: string }> = [];\n for (const sec of meta.security) {\n tokens.push(...extractTokenValues(sec));\n }\n if (tokens.length > 0) {\n const secStrings: string[] = [];\n for (const t of tokens) {\n if (t.system) secStrings.push(`${t.system}|${t.code}`);\n secStrings.push(`|${t.code}`);\n }\n columns[\"___security\"] = secStrings;\n columns[\"___securitySort\"] = tokens[0].display\n || (tokens[0].system ? `${tokens[0].system}|${tokens[0].code}` : tokens[0].code)\n || null;\n }\n }\n\n return columns;\n}\n\n// =============================================================================\n// Section 8: Global Lookup Table Row Extraction\n// =============================================================================\n\n/**\n * A row to be inserted into one of the 4 global lookup tables.\n */\nexport interface LookupTableRow {\n /** Which global table: HumanName, Address, ContactPoint, or Identifier. */\n table: LookupTableType;\n\n /** Column name \u2192 value map for the lookup table row. */\n values: Record<string, unknown>;\n}\n\n/**\n * Extract rows for global lookup tables from a FHIR resource.\n *\n * Scans the resource for HumanName, Address, ContactPoint, and Identifier\n * values and decomposes them into individual rows matching Medplum's schema:\n *\n * - `HumanName` \u2192 { resourceId, name, given, family }\n * - `Address` \u2192 { resourceId, address, city, country, postalCode, state, use }\n * - `ContactPoint` \u2192 { resourceId, system, value, use }\n * - `Identifier` \u2192 { resourceId, system, value }\n *\n * @param resource - The FHIR resource (must have `id`).\n * @param impls - SearchParameterImpl list for this resource type.\n * @returns Array of LookupTableRow to insert into global tables.\n */\nexport function buildLookupTableRows(\n resource: FhirResource & { id: string },\n impls: SearchParameterImpl[],\n): LookupTableRow[] {\n const rows: LookupTableRow[] = [];\n const resourceId = resource.id;\n const resourceType = resource.resourceType;\n\n for (const impl of impls) {\n if (impl.strategy !== \"lookup-table\") continue;\n\n const path = extractPropertyPath(impl.expression, resourceType);\n if (!path) continue;\n\n const values = getNestedValues(resource, path);\n if (values.length === 0) continue;\n\n for (const val of values) {\n if (val === null || val === undefined) continue;\n const lookupRows = extractLookupRows(resourceId, impl.code, val);\n rows.push(...lookupRows);\n }\n }\n\n return rows;\n}\n\n/**\n * Extract lookup table rows from a single value based on the search param code.\n */\nfunction extractLookupRows(\n resourceId: string,\n code: string,\n value: unknown,\n): LookupTableRow[] {\n if (typeof value !== \"object\" || value === null) {\n return [];\n }\n\n const obj = value as Record<string, unknown>;\n\n // HumanName detection: has family or given\n if (code === \"name\" || code === \"given\" || code === \"family\" || code === \"phonetic\") {\n if (typeof obj.family === \"string\" || Array.isArray(obj.given)) {\n return extractHumanNameRows(resourceId, obj);\n }\n }\n\n // Address detection\n if (\n code === \"address\" ||\n code === \"address-city\" ||\n code === \"address-country\" ||\n code === \"address-postalcode\" ||\n code === \"address-state\" ||\n code === \"address-use\"\n ) {\n if (\n Array.isArray(obj.line) ||\n typeof obj.city === \"string\" ||\n typeof obj.state === \"string\" ||\n typeof obj.postalCode === \"string\" ||\n typeof obj.country === \"string\"\n ) {\n return extractAddressRows(resourceId, obj);\n }\n }\n\n // ContactPoint detection (telecom)\n if (code === \"telecom\" || code === \"email\" || code === \"phone\") {\n if (typeof obj.value === \"string\") {\n return extractContactPointRows(resourceId, obj);\n }\n }\n\n return [];\n}\n\n/**\n * Extract HumanName rows. Each HumanName produces one row with:\n * - name: concatenation of all name parts\n * - given: given names joined\n * - family: family name\n */\nfunction extractHumanNameRows(\n resourceId: string,\n obj: Record<string, unknown>,\n): LookupTableRow[] {\n const family = typeof obj.family === \"string\" ? obj.family : null;\n const givenArr = Array.isArray(obj.given)\n ? (obj.given as unknown[]).filter((g): g is string => typeof g === \"string\")\n : [];\n const given = givenArr.length > 0 ? givenArr.join(\" \") : null;\n\n // Build the composite \"name\" string (Medplum concatenates all parts)\n const nameParts: string[] = [];\n if (family) nameParts.push(family);\n if (givenArr.length > 0) nameParts.push(...givenArr);\n if (typeof obj.text === \"string\") nameParts.push(obj.text);\n if (Array.isArray(obj.prefix)) {\n for (const p of obj.prefix) {\n if (typeof p === \"string\") nameParts.push(p);\n }\n }\n if (Array.isArray(obj.suffix)) {\n for (const s of obj.suffix) {\n if (typeof s === \"string\") nameParts.push(s);\n }\n }\n const name = nameParts.length > 0 ? nameParts.join(\" \") : null;\n\n return [\n {\n table: \"HumanName\",\n values: { resourceId, name, given, family },\n },\n ];\n}\n\n/**\n * Extract Address rows. Each Address produces one row with decomposed fields.\n */\nfunction extractAddressRows(\n resourceId: string,\n obj: Record<string, unknown>,\n): LookupTableRow[] {\n const lines = Array.isArray(obj.line)\n ? (obj.line as unknown[]).filter((l): l is string => typeof l === \"string\")\n : [];\n const city = typeof obj.city === \"string\" ? obj.city : null;\n const country = typeof obj.country === \"string\" ? obj.country : null;\n const postalCode = typeof obj.postalCode === \"string\" ? obj.postalCode : null;\n const state = typeof obj.state === \"string\" ? obj.state : null;\n const use = typeof obj.use === \"string\" ? obj.use : null;\n\n const addressParts: string[] = [...lines];\n if (city) addressParts.push(city);\n if (state) addressParts.push(state);\n if (postalCode) addressParts.push(postalCode);\n if (country) addressParts.push(country);\n const address = addressParts.length > 0 ? addressParts.join(\" \") : null;\n\n return [\n {\n table: \"Address\",\n values: { resourceId, address, city, country, postalCode, state, use },\n },\n ];\n}\n\n/**\n * Extract ContactPoint rows. Each ContactPoint produces one row.\n */\nfunction extractContactPointRows(\n resourceId: string,\n obj: Record<string, unknown>,\n): LookupTableRow[] {\n const system = typeof obj.system === \"string\" ? obj.system : null;\n const value = typeof obj.value === \"string\" ? obj.value : null;\n const use = typeof obj.use === \"string\" ? obj.use : null;\n\n return [\n {\n table: \"ContactPoint\",\n values: { resourceId, system, value, use },\n },\n ];\n}\n", "/**\n * Row Builder\n *\n * Converts a FHIR resource into a database row for the main table\n * and history table. Handles fixed columns and (future) search columns.\n *\n * Phase 9 MVP: populates fixed columns + content JSON only.\n * Search column population will be added incrementally.\n *\n * @module fhir-persistence/repo\n */\n\nimport type { PersistedResource, ResourceRow, HistoryRow, OperationContext } from \"./types.js\";\nimport { SCHEMA_VERSION, DELETED_SCHEMA_VERSION } from \"./types.js\";\nimport type { SearchParameterImpl } from \"../registry/search-parameter-registry.js\";\nimport {\n buildSearchColumns,\n buildMetadataColumns,\n buildSharedTokenColumns,\n extractPropertyPath,\n getNestedValues,\n} from \"./row-indexer.js\";\n\n// =============================================================================\n// Section 1: Main Table Row\n// =============================================================================\n\n/**\n * Build a main table row from a persisted FHIR resource.\n *\n * Populates:\n * - Fixed columns: `id`, `content`, `lastUpdated`, `deleted`, `__version`\n * - Meta columns: `_source`, `_profile`\n * - (Future) Search columns via SearchParameterRegistry + FHIRPath\n *\n * @param resource - The persisted resource (must have `id` and `meta`).\n * @returns A `ResourceRow` ready for SQL insertion.\n */\nexport function buildResourceRow(resource: PersistedResource, context?: OperationContext): ResourceRow {\n const row: ResourceRow = {\n id: resource.id,\n content: JSON.stringify(resource),\n lastUpdated: resource.meta.lastUpdated,\n deleted: false,\n projectId: resolveProjectId(resource, context),\n __version: SCHEMA_VERSION,\n compartments:\n resource.resourceType === \"Binary\"\n ? undefined\n : buildCompartments(resource),\n };\n\n // Optional meta columns\n if (resource.meta.source) {\n row._source = resource.meta.source;\n }\n\n if (resource.meta.profile && resource.meta.profile.length > 0) {\n row._profile = resource.meta.profile;\n }\n\n return row;\n}\n\n/**\n * Build a main table row with search column values populated.\n *\n * Extends `buildResourceRow()` by extracting search parameter values\n * from the resource JSON and merging them into the row.\n *\n * @param resource - The persisted resource.\n * @param searchImpls - SearchParameterImpl list for this resource type.\n * @returns A `ResourceRow` with both fixed and search columns.\n */\nexport function buildResourceRowWithSearch(\n resource: PersistedResource,\n searchImpls: SearchParameterImpl[],\n context?: OperationContext,\n): ResourceRow {\n const fixedRow = buildResourceRow(resource, context);\n const searchCols = buildSearchColumns(resource, searchImpls);\n const metadataCols = buildMetadataColumns(resource);\n const sharedTokenCols = buildSharedTokenColumns(searchCols, metadataCols);\n\n // Override compartments with full extraction (using search impls)\n const compartments =\n resource.resourceType === \"Binary\"\n ? undefined\n : buildCompartments(resource, searchImpls);\n\n return {\n ...fixedRow,\n ...searchCols,\n ...metadataCols,\n ...sharedTokenCols,\n compartments,\n };\n}\n\n// =============================================================================\n// Section 1b: Compartment Extraction\n// =============================================================================\n\n/**\n * Build compartments array for a resource.\n *\n * Phase 18: Full compartment extraction.\n * - Patient resources: compartment = [own ID]\n * - Other resources: scan all reference-type search params for Patient references,\n * extract the Patient IDs as compartment members.\n *\n * @param resource - The persisted resource.\n * @param searchImpls - Optional SearchParameterImpl list for reference extraction.\n * @returns Array of compartment UUIDs (Patient IDs).\n */\nexport function buildCompartments(\n resource: PersistedResource,\n searchImpls?: SearchParameterImpl[],\n): string[] {\n // Patient resources belong to their own compartment\n if (resource.resourceType === \"Patient\") {\n return [resource.id];\n }\n\n if (!searchImpls || searchImpls.length === 0) {\n return [];\n }\n\n // Scan all reference-type search params for Patient references\n const patientIds = new Set<string>();\n const resourceType = resource.resourceType;\n\n for (const impl of searchImpls) {\n if (impl.type !== \"reference\") continue;\n\n const path = extractPropertyPath(impl.expression, resourceType);\n if (!path) continue;\n\n const values = getNestedValues(resource, path);\n for (const val of values) {\n const patientId = extractPatientReferenceId(val);\n if (patientId) {\n patientIds.add(patientId);\n }\n }\n }\n\n // Filter to valid UUIDs only (compartments column is UUID[])\n return [...patientIds].filter(isValidUuid);\n}\n\nconst UUID_REGEX =\n /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;\n\nfunction isValidUuid(value: string): boolean {\n return UUID_REGEX.test(value);\n}\n\n/**\n * Resolve the projectId for a resource row.\n *\n * Priority:\n * 1. context.project (from OperationContext \u2014 multi-tenant scoping)\n * 2. resource.meta.project (legacy/direct injection)\n * 3. Nil UUID fallback (no project context)\n */\nfunction resolveProjectId(resource: PersistedResource, context?: OperationContext): string {\n if (context?.project) {\n return context.project;\n }\n return (\n ((resource.meta as Record<string, unknown>)[\"project\"] as string) ??\n \"00000000-0000-0000-0000-000000000000\"\n );\n}\n\nfunction extractPatientReferenceId(value: unknown): string | null {\n let refString: string | null = null;\n\n if (typeof value === \"string\") {\n refString = value;\n } else if (typeof value === \"object\" && value !== null) {\n const ref = (value as Record<string, unknown>).reference;\n if (typeof ref === \"string\") {\n refString = ref;\n }\n }\n\n if (!refString) return null;\n\n // Skip contained and URN references\n if (refString.startsWith(\"#\") || refString.startsWith(\"urn:\")) return null;\n\n // Check if this is a Patient reference\n // Handle both \"Patient/id\" and \"http://example.com/fhir/Patient/id\"\n const segments = refString.split(\"/\");\n if (segments.length < 2) return null;\n\n const id = segments[segments.length - 1];\n const type = segments[segments.length - 2];\n\n if (type === \"Patient\" && id) {\n return id;\n }\n\n return null;\n}\n\n// =============================================================================\n// Section 2: Delete Row\n// =============================================================================\n\n/**\n * Build a main table row for a soft-deleted resource.\n *\n * Sets `deleted=true`, `content=''`, `__version=-1`.\n * All search columns will be null (not populated).\n *\n * @param resourceType - The resource type.\n * @param id - The resource ID.\n * @param lastUpdated - The deletion timestamp.\n * @returns A `ResourceRow` representing the deleted state.\n */\nexport function buildDeleteRow(\n resourceType: string,\n id: string,\n lastUpdated: string,\n context?: OperationContext,\n): ResourceRow {\n return {\n id,\n content: \"\",\n lastUpdated,\n deleted: true,\n projectId: context?.project ?? \"00000000-0000-0000-0000-000000000000\",\n __version: DELETED_SCHEMA_VERSION,\n compartments: resourceType === \"Binary\" ? undefined : [],\n };\n}\n\n// =============================================================================\n// Section 3: History Table Row\n// =============================================================================\n\n/**\n * Build a history table row from a persisted FHIR resource.\n *\n * @param resource - The persisted resource.\n * @returns A `HistoryRow` for the history table.\n */\nexport function buildHistoryRow(resource: PersistedResource): HistoryRow {\n return {\n id: resource.id,\n versionId: resource.meta.versionId,\n lastUpdated: resource.meta.lastUpdated,\n content: JSON.stringify(resource),\n };\n}\n\n/**\n * Build a history table row for a delete event.\n *\n * @param id - The resource ID.\n * @param versionId - The versionId for this delete event.\n * @param lastUpdated - The deletion timestamp.\n * @returns A `HistoryRow` with empty content.\n */\nexport function buildDeleteHistoryRow(\n id: string,\n versionId: string,\n lastUpdated: string,\n): HistoryRow {\n return {\n id,\n versionId,\n lastUpdated,\n content: \"\",\n };\n}\n", "/**\n * Reference Indexer\n *\n * Extracts outgoing reference relationships from FHIR resource JSON\n * and produces rows for the `{ResourceType}_References` table.\n *\n * Used by `FhirRepository` on create/update to populate the references\n * table, which is required for `_revinclude` support.\n *\n * @module fhir-persistence/repo\n */\n\nimport type { SearchParameterImpl } from '../registry/search-parameter-registry.js';\nimport type { FhirResource } from './types.js';\nimport { extractPropertyPath, getNestedValues } from './row-indexer.js';\n\n// =============================================================================\n// Section 1: Types\n// =============================================================================\n\n/**\n * A single row for the `{ResourceType}_References` table.\n */\nexport interface ReferenceRow {\n /** The source resource ID. */\n resourceId: string;\n /** The target resource ID (extracted from the reference string). */\n targetId: string;\n /** The search parameter code (e.g., \"subject\", \"patient\"). */\n code: string;\n}\n\n/**\n * v2: A row for the `{ResourceType}_References` table.\n * Adds targetType and referenceRaw for more precise reference queries.\n */\nexport interface ReferenceRowV2 {\n /** The source resource ID. */\n resourceId: string;\n /** The target resource type (e.g., \"Patient\"). */\n targetType: string;\n /** The target resource ID. */\n targetId: string;\n /** The search parameter code (e.g., \"subject\"). */\n code: string;\n /** The original reference string, or null. */\n referenceRaw: string | null;\n}\n\n// =============================================================================\n// Section 2: Reference Extraction\n// =============================================================================\n\n/**\n * Extract all outgoing reference rows from a FHIR resource.\n *\n * Iterates over all reference-type search parameters and extracts\n * target resource IDs from the resource JSON.\n *\n * @param resource - The FHIR resource (must have `id`).\n * @param impls - SearchParameterImpl list for this resource type.\n * @returns Array of ReferenceRow ready for SQL insertion.\n */\nexport function extractReferences(\n resource: FhirResource,\n impls: SearchParameterImpl[],\n): ReferenceRow[] {\n const resourceId = resource.id;\n if (!resourceId) return [];\n\n const rows: ReferenceRow[] = [];\n const resourceType = resource.resourceType;\n\n for (const impl of impls) {\n if (impl.type !== 'reference') continue;\n\n const path = extractPropertyPath(impl.expression, resourceType);\n if (!path) continue;\n\n const values = getNestedValues(resource, path);\n for (const val of values) {\n const targetId = extractTargetId(val);\n if (targetId) {\n rows.push({ resourceId, targetId, code: impl.code });\n }\n }\n }\n\n return rows;\n}\n\n// =============================================================================\n// Section 3: Target ID Extraction\n// =============================================================================\n\n/**\n * Extract a target resource ID from a FHIR Reference value.\n *\n * Handles:\n * - Reference object: `{ reference: \"Patient/123\" }` \u2192 `\"123\"`\n * - Reference object with absolute URL: `{ reference: \"http://example.com/Patient/123\" }` \u2192 `\"123\"`\n * - String value: `\"Patient/123\"` \u2192 `\"123\"`\n * - Display-only: `{ display: \"Dr. Smith\" }` \u2192 null (skipped)\n */\nfunction extractTargetId(value: unknown): string | null {\n let refString: string | null = null;\n\n if (typeof value === 'string') {\n refString = value;\n } else if (typeof value === 'object' && value !== null) {\n const ref = (value as Record<string, unknown>).reference;\n if (typeof ref === 'string') {\n refString = ref;\n }\n }\n\n if (!refString) return null;\n\n return parseReferenceId(refString);\n}\n\n/**\n * Parse a FHIR reference string to extract the target resource ID.\n *\n * - `\"Patient/123\"` \u2192 `\"123\"`\n * - `\"http://example.com/fhir/Patient/123\"` \u2192 `\"123\"`\n * - `\"urn:uuid:abc-def\"` \u2192 null (URN references not indexed)\n * - `\"#contained\"` \u2192 null (contained references not indexed)\n */\nfunction parseReferenceId(ref: string): string | null {\n // Skip contained references\n if (ref.startsWith('#')) return null;\n\n // Skip URN references\n if (ref.startsWith('urn:')) return null;\n\n // Handle relative or absolute references: take the last segment after \"/\"\n const slashIdx = ref.lastIndexOf('/');\n if (slashIdx === -1) return null;\n\n const id = ref.slice(slashIdx + 1);\n if (!id) return null;\n\n return id;\n}\n\n// =============================================================================\n// Section 4: v2 Reference Extraction (targetType + referenceRaw)\n// =============================================================================\n\n/**\n * v2: Extract a reference string from a value (Reference object or string).\n */\nfunction extractRefString(value: unknown): string | null {\n if (typeof value === 'string') return value;\n if (typeof value === 'object' && value !== null) {\n const ref = (value as Record<string, unknown>).reference;\n if (typeof ref === 'string') return ref;\n }\n return null;\n}\n\n/**\n * v2: Parse a FHIR reference to extract both targetType and targetId.\n *\n * - `\"Patient/123\"` \u2192 `{ targetType: \"Patient\", targetId: \"123\" }`\n * - `\"http://example.com/fhir/Patient/123\"` \u2192 `{ targetType: \"Patient\", targetId: \"123\" }`\n * - `\"urn:uuid:abc\"` \u2192 null\n * - `\"#contained\"` \u2192 null\n */\nfunction parseReferenceV2(ref: string): { targetType: string; targetId: string } | null {\n if (ref.startsWith('#')) return null;\n if (ref.startsWith('urn:')) return null;\n\n const segments = ref.split('/');\n if (segments.length < 2) return null;\n\n const targetId = segments[segments.length - 1];\n const targetType = segments[segments.length - 2];\n\n if (!targetId || !targetType) return null;\n // targetType should start with uppercase (resource type convention)\n if (targetType[0] !== targetType[0].toUpperCase()) return null;\n\n return { targetType, targetId };\n}\n\n/**\n * v2: Extract all outgoing reference rows with targetType + referenceRaw.\n */\nexport function extractReferencesV2(\n resource: FhirResource,\n impls: SearchParameterImpl[],\n): ReferenceRowV2[] {\n const resourceId = resource.id;\n if (!resourceId) return [];\n\n const rows: ReferenceRowV2[] = [];\n const resourceType = resource.resourceType;\n\n for (const impl of impls) {\n if (impl.type !== 'reference') continue;\n\n const path = extractPropertyPath(impl.expression, resourceType);\n if (!path) continue;\n\n const values = getNestedValues(resource, path);\n for (const val of values) {\n const refString = extractRefString(val);\n if (!refString) continue;\n\n const parsed = parseReferenceV2(refString);\n if (!parsed) continue;\n\n rows.push({\n resourceId,\n targetType: parsed.targetType,\n targetId: parsed.targetId,\n code: impl.code,\n referenceRaw: refString,\n });\n }\n }\n\n return rows;\n}\n", "/**\n * SQL Builder\n *\n * Generates parameterized SQL statements for FHIR resource persistence.\n * All queries use `$1, $2, ...` placeholders \u2014 no string interpolation\n * of user data (SQL injection safe).\n *\n * Table and column names are double-quoted for safety but are NOT\n * parameterized (they come from the schema, not user input).\n *\n * @module fhir-persistence/repo\n */\n\n// =============================================================================\n// Section 1: Upsert (Main Table)\n// =============================================================================\n\n/**\n * Build an UPSERT statement for the main resource table.\n *\n * Generates:\n * ```sql\n * INSERT INTO \"Patient\" (\"id\", \"content\", ...)\n * VALUES ($1, $2, ...)\n * ON CONFLICT (\"id\") DO UPDATE SET\n * \"content\" = EXCLUDED.\"content\", ...\n * ```\n *\n * @param tableName - The table name (e.g., `'Patient'`).\n * @param columns - Column name \u2192 value map. Order is preserved.\n * @returns `{ sql, values }` ready for `client.query()`.\n */\nexport function buildUpsertSQL(\n tableName: string,\n columns: Record<string, unknown>,\n): { sql: string; values: unknown[] } {\n const keys = Object.keys(columns);\n const values = Object.values(columns);\n\n const colList = keys.map((k) => `\"${k}\"`).join(', ');\n const paramList = keys.map((_, i) => `$${i + 1}`).join(', ');\n\n // ON CONFLICT \u2014 update all columns except \"id\"\n const updateCols = keys\n .filter((k) => k !== 'id')\n .map((k) => `\"${k}\" = EXCLUDED.\"${k}\"`)\n .join(', ');\n\n const sql =\n `INSERT INTO \"${tableName}\" (${colList})\\n` +\n `VALUES (${paramList})\\n` +\n `ON CONFLICT (\"id\") DO UPDATE SET\\n` +\n ` ${updateCols}`;\n\n return { sql, values };\n}\n\n// =============================================================================\n// Section 2: Insert (History Table)\n// =============================================================================\n\n/**\n * Build a plain INSERT statement (no conflict handling).\n *\n * Used for history table writes where each row is unique\n * (keyed by `versionId`).\n *\n * @param tableName - The table name (e.g., `'Patient_History'`).\n * @param columns - Column name \u2192 value map.\n * @returns `{ sql, values }` ready for `client.query()`.\n */\nexport function buildInsertSQL(\n tableName: string,\n columns: Record<string, unknown>,\n): { sql: string; values: unknown[] } {\n const keys = Object.keys(columns);\n const values = Object.values(columns);\n\n const colList = keys.map((k) => `\"${k}\"`).join(', ');\n const paramList = keys.map((_, i) => `$${i + 1}`).join(', ');\n\n const sql = `INSERT INTO \"${tableName}\" (${colList})\\nVALUES (${paramList})`;\n\n return { sql, values };\n}\n\n// =============================================================================\n// Section 3: Select\n// =============================================================================\n\n/**\n * Build a SELECT statement to read a resource by ID.\n *\n * Returns `content` and `deleted` columns.\n *\n * @param tableName - The table name (e.g., `'Patient'`).\n * @returns `{ sql }` \u2014 use with `values: [id]`.\n */\nexport function buildSelectByIdSQL(tableName: string): string {\n return `SELECT \"content\", \"deleted\", \"projectId\" FROM \"${tableName}\" WHERE \"id\" = $1`;\n}\n\n/**\n * Build a SELECT statement to read history entries for a resource.\n *\n * Returns all history rows ordered by `lastUpdated` descending (newest first).\n *\n * @param tableName - The history table name (e.g., `'Patient_History'`).\n * @returns `{ sql }` \u2014 use with `values: [id]`.\n */\nexport function buildSelectHistorySQL(tableName: string): string {\n return (\n `SELECT \"content\" FROM \"${tableName}\"\\n` +\n `WHERE \"id\" = $1\\n` +\n `ORDER BY \"lastUpdated\" DESC`\n );\n}\n\n// =============================================================================\n// Section 4: History with Options\n// =============================================================================\n\n/**\n * Options for building history SQL with filtering and pagination.\n */\nexport interface HistorySQLOptions {\n since?: string;\n count?: number;\n cursor?: string;\n}\n\n/**\n * Build a SELECT for instance history with optional _since, _count, cursor.\n *\n * Returns `id`, `versionId`, `lastUpdated`, `content` columns.\n *\n * @param tableName - The history table name.\n * @returns `{ sql, values }`.\n */\nexport function buildInstanceHistorySQL(\n tableName: string,\n resourceId: string,\n options?: HistorySQLOptions,\n): { sql: string; values: unknown[] } {\n const conditions: string[] = ['\"id\" = $1'];\n const values: unknown[] = [resourceId];\n let paramIdx = 2;\n\n if (options?.since) {\n conditions.push(`\"lastUpdated\" >= $${paramIdx}`);\n values.push(options.since);\n paramIdx++;\n }\n\n if (options?.cursor) {\n conditions.push(`\"lastUpdated\" < $${paramIdx}`);\n values.push(options.cursor);\n paramIdx++;\n }\n\n let sql =\n `SELECT \"id\", \"versionId\", \"lastUpdated\", \"content\" FROM \"${tableName}\"\\n` +\n `WHERE ${conditions.join(' AND ')}\\n` +\n `ORDER BY \"lastUpdated\" DESC`;\n\n if (options?.count !== undefined && options.count > 0) {\n sql += `\\nLIMIT $${paramIdx}`;\n values.push(options.count);\n }\n\n return { sql, values };\n}\n\n/**\n * Build a SELECT for type-level history (all resources of a type).\n *\n * @param tableName - The history table name.\n * @returns `{ sql, values }`.\n */\nexport function buildTypeHistorySQL(\n tableName: string,\n options?: HistorySQLOptions,\n): { sql: string; values: unknown[] } {\n const conditions: string[] = [];\n const values: unknown[] = [];\n let paramIdx = 1;\n\n if (options?.since) {\n conditions.push(`\"lastUpdated\" >= $${paramIdx}`);\n values.push(options.since);\n paramIdx++;\n }\n\n if (options?.cursor) {\n conditions.push(`\"lastUpdated\" < $${paramIdx}`);\n values.push(options.cursor);\n paramIdx++;\n }\n\n const whereClause = conditions.length > 0 ? `\\nWHERE ${conditions.join(' AND ')}` : '';\n\n let sql =\n `SELECT \"id\", \"versionId\", \"lastUpdated\", \"content\" FROM \"${tableName}\"` +\n whereClause +\n `\\nORDER BY \"lastUpdated\" DESC`;\n\n if (options?.count !== undefined && options.count > 0) {\n sql += `\\nLIMIT $${paramIdx}`;\n values.push(options.count);\n }\n\n return { sql, values };\n}\n\n/**\n * Build a SELECT statement to read a specific version from the history table.\n *\n * @param tableName - The history table name (e.g., `'Patient_History'`).\n * @returns `{ sql }` \u2014 use with `values: [id, versionId]`.\n */\nexport function buildSelectVersionSQL(tableName: string): string {\n return (\n `SELECT \"content\" FROM \"${tableName}\"\\n` +\n `WHERE \"id\" = $1 AND \"versionId\" = $2`\n );\n}\n\n// =============================================================================\n// Section 5: v2 SQL Builders (SQLite ? placeholders, no projectId)\n// =============================================================================\n\n/**\n * v2: Build an INSERT statement for the main resource table.\n * Uses `?` placeholders (SQLite-compatible).\n */\nexport function buildInsertMainSQLv2(\n tableName: string,\n columns: Record<string, unknown>,\n): { sql: string; values: unknown[] } {\n const keys = Object.keys(columns);\n const values = Object.values(columns);\n const colList = keys.map((k) => `\"${k}\"`).join(', ');\n const paramList = keys.map(() => '?').join(', ');\n const sql = `INSERT INTO \"${tableName}\" (${colList}) VALUES (${paramList})`;\n return { sql, values };\n}\n\n/**\n * v2: Build an UPDATE statement for the main resource table.\n * Uses `?` placeholders. Updates all columns except `id`.\n */\nexport function buildUpdateMainSQLv2(\n tableName: string,\n columns: Record<string, unknown>,\n): { sql: string; values: unknown[] } {\n const keys = Object.keys(columns);\n const updateKeys = keys.filter((k) => k !== 'id');\n const setClauses = updateKeys.map((k) => `\"${k}\" = ?`).join(', ');\n const values = [...updateKeys.map((k) => columns[k]), columns['id']];\n const sql = `UPDATE \"${tableName}\" SET ${setClauses} WHERE \"id\" = ?`;\n return { sql, values };\n}\n\n/**\n * v2: Build an INSERT statement for the history table.\n * Uses `?` placeholders. Does NOT include versionSeq (AUTOINCREMENT).\n */\nexport function buildInsertHistorySQLv2(\n tableName: string,\n columns: Record<string, unknown>,\n): { sql: string; values: unknown[] } {\n const keys = Object.keys(columns);\n const values = Object.values(columns);\n const colList = keys.map((k) => `\"${k}\"`).join(', ');\n const paramList = keys.map(() => '?').join(', ');\n const sql = `INSERT INTO \"${tableName}\" (${colList}) VALUES (${paramList})`;\n return { sql, values };\n}\n\n/**\n * v2: SELECT by ID \u2014 no projectId, returns versionId + deleted.\n */\nexport function buildSelectByIdSQLv2(tableName: string): string {\n return `SELECT \"id\", \"versionId\", \"content\", \"deleted\", \"lastUpdated\" FROM \"${tableName}\" WHERE \"id\" = ?`;\n}\n\n/**\n * v2: SELECT a specific version from the history table.\n */\nexport function buildSelectVersionSQLv2(tableName: string): string {\n return `SELECT \"content\", \"deleted\" FROM \"${tableName}\" WHERE \"id\" = ? AND \"versionId\" = ?`;\n}\n\n/**\n * v2: DELETE all reference rows for a resource (before re-inserting on update).\n */\nexport function buildDeleteReferencesSQLv2(tableName: string): string {\n return `DELETE FROM \"${tableName}\" WHERE \"resourceId\" = ?`;\n}\n\n/**\n * v2: Build a multi-row INSERT for the references table.\n * Each row has 5 columns: resourceId, targetType, targetId, code, referenceRaw.\n */\nexport function buildInsertReferencesSQLv2(\n tableName: string,\n rowCount: number,\n): string {\n const rowPlaceholder = '(?, ?, ?, ?, ?)';\n const allRows = Array.from({ length: rowCount }, () => rowPlaceholder).join(', ');\n return `INSERT INTO \"${tableName}\" (\"resourceId\", \"targetType\", \"targetId\", \"code\", \"referenceRaw\") VALUES ${allRows}`;\n}\n\n/**\n * v2: Instance history SELECT with optional _since, _count, cursor.\n * Uses `?` placeholders and ORDER BY versionSeq DESC.\n */\nexport function buildInstanceHistorySQLv2(\n tableName: string,\n resourceId: string,\n options?: { since?: string; count?: number; cursor?: string },\n): { sql: string; values: unknown[] } {\n const conditions: string[] = ['\"id\" = ?'];\n const values: unknown[] = [resourceId];\n\n if (options?.since) {\n conditions.push('\"lastUpdated\" >= ?');\n values.push(options.since);\n }\n if (options?.cursor) {\n conditions.push('\"lastUpdated\" < ?');\n values.push(options.cursor);\n }\n\n let sql =\n `SELECT \"id\", \"versionId\", \"lastUpdated\", \"content\", \"deleted\" FROM \"${tableName}\"\\n` +\n `WHERE ${conditions.join(' AND ')}\\n` +\n `ORDER BY \"versionSeq\" DESC`;\n\n if (options?.count !== undefined && options.count > 0) {\n sql += '\\nLIMIT ?';\n values.push(options.count);\n }\n\n return { sql, values };\n}\n\n/**\n * v2: Type-level history SELECT.\n * Uses `?` placeholders and ORDER BY versionSeq DESC.\n */\nexport function buildTypeHistorySQLv2(\n tableName: string,\n options?: { since?: string; count?: number; cursor?: string },\n): { sql: string; values: unknown[] } {\n const conditions: string[] = [];\n const values: unknown[] = [];\n\n if (options?.since) {\n conditions.push('\"lastUpdated\" >= ?');\n values.push(options.since);\n }\n if (options?.cursor) {\n conditions.push('\"lastUpdated\" < ?');\n values.push(options.cursor);\n }\n\n const whereClause = conditions.length > 0 ? `\\nWHERE ${conditions.join(' AND ')}` : '';\n\n let sql =\n `SELECT \"id\", \"versionId\", \"lastUpdated\", \"content\", \"deleted\" FROM \"${tableName}\"` +\n whereClause +\n '\\nORDER BY \"versionSeq\" DESC';\n\n if (options?.count !== undefined && options.count > 0) {\n sql += '\\nLIMIT ?';\n values.push(options.count);\n }\n\n return { sql, values };\n}\n", "/**\n * History Bundle Builder\n *\n * Constructs FHIR R4 Bundle of type `history` from `HistoryEntry[]`.\n * Pure function \u2014 no database dependency.\n *\n * FHIR R4 History Bundle spec:\n * - `Bundle.type` = `\"history\"`\n * - Each entry has `request` (method + URL) and `response` (status + etag)\n * - Delete entries have `request.method = \"DELETE\"` and no `resource`\n * - Entries ordered newest first\n *\n * @module fhir-persistence/repo\n */\n\nimport { randomUUID } from 'node:crypto';\nimport type { HistoryEntry } from './types.js';\n\n// =============================================================================\n// Section 1: Types\n// =============================================================================\n\n/**\n * A FHIR R4 Bundle (minimal shape for history).\n */\nexport interface HistoryBundle {\n resourceType: 'Bundle';\n id: string;\n type: 'history';\n total: number;\n link?: BundleLink[];\n entry?: HistoryBundleEntry[];\n}\n\nexport interface BundleLink {\n relation: string;\n url: string;\n}\n\nexport interface HistoryBundleEntry {\n fullUrl?: string;\n resource?: Record<string, unknown>;\n request: {\n method: string;\n url: string;\n };\n response: {\n status: string;\n etag?: string;\n lastModified?: string;\n };\n}\n\n// =============================================================================\n// Section 2: Bundle Construction\n// =============================================================================\n\n/**\n * Options for building a history bundle.\n */\nexport interface BuildHistoryBundleOptions {\n /** Base URL for fullUrl construction (e.g., `\"http://localhost:3000/fhir/R4\"`). */\n baseUrl?: string;\n /** Total count of matching entries (may differ from entries.length if paginated). */\n total?: number;\n /** Self link URL. */\n selfUrl?: string;\n /** Next page link URL. */\n nextUrl?: string;\n}\n\n/**\n * Build a FHIR R4 history Bundle from HistoryEntry[].\n *\n * @param entries - History entries (newest first).\n * @param options - Optional bundle metadata.\n * @returns A FHIR R4 Bundle of type `history`.\n */\nexport function buildHistoryBundle(\n entries: HistoryEntry[],\n options?: BuildHistoryBundleOptions,\n): HistoryBundle {\n const bundle: HistoryBundle = {\n resourceType: 'Bundle',\n id: randomUUID(),\n type: 'history',\n total: options?.total ?? entries.length,\n };\n\n // Links\n const links: BundleLink[] = [];\n if (options?.selfUrl) {\n links.push({ relation: 'self', url: options.selfUrl });\n }\n if (options?.nextUrl) {\n links.push({ relation: 'next', url: options.nextUrl });\n }\n if (links.length > 0) {\n bundle.link = links;\n }\n\n // Entries\n if (entries.length > 0) {\n bundle.entry = entries.map((entry) => toBundleEntry(entry, options?.baseUrl));\n }\n\n return bundle;\n}\n\n// =============================================================================\n// Section 3: Entry Construction\n// =============================================================================\n\nfunction toBundleEntry(\n entry: HistoryEntry,\n baseUrl?: string,\n): HistoryBundleEntry {\n const { resourceType, id, versionId, lastUpdated, deleted, resource } = entry;\n const resourceUrl = `${resourceType}/${id}`;\n\n const bundleEntry: HistoryBundleEntry = {\n request: {\n method: deleted ? 'DELETE' : (resource?.meta?.versionId === versionId ? 'PUT' : 'POST'),\n url: resourceUrl,\n },\n response: {\n status: deleted ? '204' : '200',\n etag: `W/\"${versionId}\"`,\n lastModified: lastUpdated,\n },\n };\n\n if (baseUrl) {\n bundleEntry.fullUrl = `${baseUrl}/${resourceUrl}`;\n }\n\n if (!deleted && resource) {\n bundleEntry.resource = resource as unknown as Record<string, unknown>;\n }\n\n return bundleEntry;\n}\n\n/**\n * Determine the HTTP method for a history entry.\n *\n * Heuristic: if the entry is the first version (oldest) for a resource,\n * it's a POST (create). Otherwise it's a PUT (update).\n * Delete entries are always DELETE.\n *\n * For simplicity, we check if this is the first entry in the history\n * by comparing with the resource's creation time. Since we don't have\n * that info here, we use a simple heuristic: POST for the first entry\n * in the array (oldest), PUT for the rest.\n */\nexport function determineMethod(\n entries: HistoryEntry[],\n index: number,\n): string {\n const entry = entries[index];\n if (entry.deleted) return 'DELETE';\n // Last entry in the array (oldest, since newest-first) = POST (create)\n if (index === entries.length - 1) return 'POST';\n return 'PUT';\n}\n", "/**\n * Search Types\n *\n * Defines the data structures for FHIR search request parsing\n * and SQL WHERE clause generation.\n *\n * ## FHIR Search Semantics\n *\n * - Multiple values for the same parameter \u2192 OR (comma-separated)\n * - Multiple different parameters \u2192 AND (separate query params)\n * - Prefixes (eq, ne, lt, gt, le, ge) \u2192 comparison operators\n * - Modifiers (:exact, :contains, :missing, :not) \u2192 behavior modifiers\n *\n * Reference: https://hl7.org/fhir/R4/search.html\n *\n * @module fhir-persistence/search\n */\n\n// =============================================================================\n// Section 1: Search Prefix\n// =============================================================================\n\n/**\n * FHIR search prefix for number, date, and quantity parameters.\n *\n * See: https://hl7.org/fhir/R4/search.html#prefix\n */\nexport type SearchPrefix = 'eq' | 'ne' | 'lt' | 'gt' | 'le' | 'ge' | 'sa' | 'eb' | 'ap';\n\n/**\n * All valid search prefixes.\n */\nexport const SEARCH_PREFIXES: ReadonlySet<string> = new Set<SearchPrefix>([\n 'eq', 'ne', 'lt', 'gt', 'le', 'ge', 'sa', 'eb', 'ap',\n]);\n\n/**\n * FHIR search parameter types that support prefixes.\n */\nexport const PREFIX_TYPES: ReadonlySet<string> = new Set(['number', 'date', 'quantity']);\n\n// =============================================================================\n// Section 2: Search Modifier\n// =============================================================================\n\n/**\n * FHIR search modifier.\n *\n * See: https://hl7.org/fhir/R4/search.html#modifiers\n */\nexport type SearchModifier =\n | 'exact'\n | 'contains'\n | 'missing'\n | 'not'\n | 'text'\n | 'above'\n | 'below'\n | 'in'\n | 'not-in'\n | 'of-type';\n\n// =============================================================================\n// Section 3: Parsed Search Parameter\n// =============================================================================\n\n/**\n * A single parsed search parameter from a FHIR search URL.\n *\n * Examples:\n * - `?gender=male` \u2192 `{ code: \"gender\", values: [\"male\"] }`\n * - `?gender=male,female` \u2192 `{ code: \"gender\", values: [\"male\", \"female\"] }`\n * - `?birthdate=ge1990-01-01`\u2192 `{ code: \"birthdate\", prefix: \"ge\", values: [\"1990-01-01\"] }`\n * - `?name:exact=Smith` \u2192 `{ code: \"name\", modifier: \"exact\", values: [\"Smith\"] }`\n */\nexport interface ParsedSearchParam {\n /** The search parameter code (e.g., `\"gender\"`, `\"birthdate\"`). */\n code: string;\n\n /** Optional modifier (e.g., `\"exact\"`, `\"contains\"`, `\"missing\"`). */\n modifier?: SearchModifier;\n\n /** Optional prefix for number/date/quantity (e.g., `\"ge\"`, `\"lt\"`). */\n prefix?: SearchPrefix;\n\n /**\n * The search values (OR semantics within a single parameter).\n * Comma-separated values in the URL are split into this array.\n */\n values: string[];\n\n /**\n * Chained search info (single-level).\n *\n * Present when the param uses chained syntax:\n * `subject:Patient.name=Smith` \u2192\n * code = \"subject\", chain = { targetType: \"Patient\", targetParam: \"name\" }\n */\n chain?: ChainedSearchTarget;\n}\n\n/**\n * Target information for a chained search parameter.\n *\n * Example: `subject:Patient.name=Smith`\n * - `targetType` = `\"Patient\"`\n * - `targetParam` = `\"name\"`\n */\nexport interface ChainedSearchTarget {\n /** The target resource type (e.g., `\"Patient\"`). */\n targetType: string;\n /** The search parameter on the target resource (e.g., `\"name\"`). */\n targetParam: string;\n}\n\n// =============================================================================\n// Section 4: Sort Rule\n// =============================================================================\n\n/**\n * A single sort rule from the `_sort` parameter.\n *\n * Examples:\n * - `_sort=birthdate` \u2192 `{ code: \"birthdate\", descending: false }`\n * - `_sort=-birthdate` \u2192 `{ code: \"birthdate\", descending: true }`\n */\nexport interface SortRule {\n /** The search parameter code to sort by. */\n code: string;\n\n /** Whether to sort in descending order. */\n descending: boolean;\n}\n\n// =============================================================================\n// Section 5: Include Target\n// =============================================================================\n\n/**\n * A parsed `_include` or `_revinclude` target.\n *\n * Syntax: `{sourceType}:{searchParam}` or `{sourceType}:{searchParam}:{targetType}`\n *\n * Examples:\n * - `_include=MedicationRequest:patient` \u2192 `{ resourceType: \"MedicationRequest\", searchParam: \"patient\" }`\n * - `_include=Observation:subject:Patient` \u2192 `{ resourceType: \"Observation\", searchParam: \"subject\", targetType: \"Patient\" }`\n */\nexport interface IncludeTarget {\n /** Source resource type (e.g., \"MedicationRequest\"). */\n resourceType: string;\n /** Search parameter code (e.g., \"patient\", \"subject\"). */\n searchParam: string;\n /** Optional target type filter (e.g., \"Patient\"). */\n targetType?: string;\n /**\n * If true, this is an `_include:iterate` \u2014 recursively include\n * resources referenced by included resources (max depth 3, with cycle detection).\n */\n iterate?: boolean;\n /**\n * If true, this is a wildcard `_include=*` \u2014 include ALL referenced resources.\n */\n wildcard?: boolean;\n}\n\n// =============================================================================\n// Section 6: Search Request\n// =============================================================================\n\n/**\n * A fully parsed FHIR search request.\n *\n * Produced by `parseSearchRequest()` from a URL query string.\n * Consumed by `buildSearchSQL()` to generate a SQL query.\n */\nexport interface SearchRequest {\n /** The FHIR resource type to search. */\n resourceType: string;\n\n /** Parsed search parameters (AND semantics between parameters). */\n params: ParsedSearchParam[];\n\n /**\n * Maximum number of results to return.\n * Corresponds to `_count`. Default: 20.\n */\n count?: number;\n\n /**\n * Offset for pagination.\n * Corresponds to `_offset`.\n */\n offset?: number;\n\n /**\n * Sort rules.\n * Corresponds to `_sort`.\n */\n sort?: SortRule[];\n\n /**\n * Total count mode.\n * Corresponds to `_total`.\n */\n total?: 'none' | 'estimate' | 'accurate';\n\n /**\n * Resources to include (forward references).\n * Corresponds to `_include`.\n */\n include?: IncludeTarget[];\n\n /**\n * Resources to reverse-include (reverse references).\n * Corresponds to `_revinclude`.\n */\n revinclude?: IncludeTarget[];\n\n /**\n * Compartment filter for compartment search.\n * Set when the URL is `/:compartmentType/:compartmentId/:resourceType`.\n *\n * Example: `GET /Patient/123/Observation` \u2192\n * `{ resourceType: \"Patient\", id: \"123\" }`\n */\n compartment?: {\n resourceType: string;\n id: string;\n };\n\n /**\n * Project ID for multi-tenant scoping.\n * When set, search results are restricted to resources with matching `projectId`.\n *\n * Injected by the server layer from OperationContext.project.\n */\n project?: string;\n}\n\n/**\n * Default page size for search results.\n */\nexport const DEFAULT_SEARCH_COUNT = 20;\n\n/**\n * Maximum allowed page size.\n */\nexport const MAX_SEARCH_COUNT = 1000;\n\n// =============================================================================\n// Section 6: SQL Fragment Types\n// =============================================================================\n\n/**\n * A SQL WHERE clause fragment with parameterized values.\n *\n * Used by `buildWhereFragment()` to produce composable SQL pieces.\n */\nexport interface WhereFragment {\n /** The SQL expression (e.g., `'\"gender\" = $1'`). */\n sql: string;\n\n /** The parameter values (e.g., `['male']`). */\n values: unknown[];\n}\n\n/**\n * A complete search SQL query with parameterized values.\n *\n * Produced by `buildSearchSQL()`.\n */\nexport interface SearchSQL {\n /** The full SQL query string. */\n sql: string;\n\n /** The parameter values for the query. */\n values: unknown[];\n}\n\n/**\n * Result of a count query.\n */\nexport interface CountSQL {\n /** The SQL COUNT query string. */\n sql: string;\n\n /** The parameter values for the query. */\n values: unknown[];\n}\n", "/**\n * Search Parameter Parser\n *\n * Parses FHIR search URL query strings into structured `ParsedSearchParam[]`.\n * Handles prefixes, modifiers, comma-separated OR values, and special\n * parameters (_count, _sort, _offset, _total).\n *\n * Reference: https://hl7.org/fhir/R4/search.html\n *\n * @module fhir-persistence/search\n */\n\nimport type { SearchParameterRegistry } from '../registry/search-parameter-registry.js';\nimport type {\n ChainedSearchTarget,\n IncludeTarget,\n ParsedSearchParam,\n SearchModifier,\n SearchPrefix,\n SearchRequest,\n SortRule,\n} from './types.js';\nimport {\n SEARCH_PREFIXES,\n PREFIX_TYPES,\n MAX_SEARCH_COUNT,\n} from './types.js';\n\n// =============================================================================\n// Section 1: Special Parameter Names\n// =============================================================================\n\n/**\n * FHIR search result parameters that are NOT search filters.\n * These control pagination, sorting, and result format.\n */\nconst RESULT_PARAMS = new Set([\n '_count',\n '_offset',\n '_sort',\n '_total',\n '_include',\n '_revinclude',\n '_summary',\n '_elements',\n '_contained',\n '_containedType',\n]);\n\n/**\n * Special search parameters handled by fixed columns.\n * These bypass the SearchParameterRegistry lookup.\n */\nconst SPECIAL_PARAMS = new Set([\n '_id',\n '_lastUpdated',\n '_profile',\n '_source',\n '_tag',\n '_security',\n]);\n\n// =============================================================================\n// Section 2: Main Parser\n// =============================================================================\n\n/**\n * Parse a FHIR search URL query string into a `SearchRequest`.\n *\n * @param resourceType - The FHIR resource type being searched.\n * @param queryParams - The URL query parameters as a key-value record.\n * For repeated keys, values should be joined with `&` or passed as arrays.\n * @param registry - Optional SearchParameterRegistry for parameter validation.\n * If provided, unknown parameter codes will be rejected.\n * @returns A fully parsed SearchRequest.\n * @throws Error if a parameter code is unknown and registry is provided.\n */\nexport function parseSearchRequest(\n resourceType: string,\n queryParams: Record<string, string | string[] | undefined>,\n registry?: SearchParameterRegistry,\n): SearchRequest {\n const request: SearchRequest = {\n resourceType,\n params: [],\n };\n\n for (const [rawKey, rawValue] of Object.entries(queryParams)) {\n if (rawValue === undefined || rawValue === '') {\n continue;\n }\n\n // Normalize array values to individual entries\n const values = Array.isArray(rawValue) ? rawValue : [rawValue];\n\n for (const value of values) {\n if (value === '') continue;\n processQueryParam(request, rawKey, value, registry);\n }\n }\n\n return request;\n}\n\n// =============================================================================\n// Section 3: Query Parameter Processing\n// =============================================================================\n\n/**\n * Process a single query parameter key-value pair.\n */\nfunction processQueryParam(\n request: SearchRequest,\n key: string,\n value: string,\n registry?: SearchParameterRegistry,\n): void {\n // Handle result parameters\n if (key === '_count') {\n const count = parseInt(value, 10);\n if (!isNaN(count) && count >= 0) {\n request.count = Math.min(count, MAX_SEARCH_COUNT);\n }\n return;\n }\n\n if (key === '_offset') {\n const offset = parseInt(value, 10);\n if (!isNaN(offset) && offset >= 0) {\n request.offset = offset;\n }\n return;\n }\n\n if (key === '_sort') {\n request.sort = parseSortParam(value);\n return;\n }\n\n if (key === '_total') {\n if (value === 'none' || value === 'estimate' || value === 'accurate') {\n request.total = value;\n }\n return;\n }\n\n if (key === '_include' || key === '_include:iterate') {\n const target = parseIncludeValue(value);\n if (target) {\n if (key === '_include:iterate') target.iterate = true;\n if (!request.include) request.include = [];\n request.include.push(target);\n }\n return;\n }\n\n if (key === '_revinclude' || key === '_revinclude:iterate') {\n const target = parseIncludeValue(value);\n if (target) {\n if (key === '_revinclude:iterate') target.iterate = true;\n if (!request.revinclude) request.revinclude = [];\n request.revinclude.push(target);\n }\n return;\n }\n\n // Skip other result parameters\n if (RESULT_PARAMS.has(key)) {\n return;\n }\n\n // Parse the parameter code, optional modifier, and optional chain\n const { code, modifier, chain } = parseParamKey(key);\n\n // Validate against registry if provided (skip special params and chained params)\n if (registry && !SPECIAL_PARAMS.has(code) && !chain) {\n const impl = registry.getImpl(request.resourceType, code);\n if (!impl) {\n throw new Error(`Unknown search parameter: ${code} for ${request.resourceType}`);\n }\n }\n\n // Determine the FHIR search parameter type for prefix detection\n // For chained params, detect prefix based on the TARGET param type\n let paramType: string | undefined;\n if (chain && registry) {\n const targetImpl = registry.getImpl(chain.targetType, chain.targetParam);\n paramType = targetImpl?.type;\n } else if (registry && !SPECIAL_PARAMS.has(code)) {\n const impl = registry.getImpl(request.resourceType, code);\n paramType = impl?.type;\n } else if (code === '_lastUpdated') {\n paramType = 'date';\n }\n\n // Parse values (comma-separated \u2192 OR)\n const parsedValues = splitSearchValues(value);\n\n // Extract prefix if applicable\n const { prefix, cleanValues } = extractPrefix(parsedValues, paramType);\n\n const param: ParsedSearchParam = {\n code,\n values: cleanValues,\n };\n\n if (modifier) {\n param.modifier = modifier;\n }\n\n if (prefix) {\n param.prefix = prefix;\n }\n\n if (chain) {\n param.chain = chain;\n }\n\n request.params.push(param);\n}\n\n// =============================================================================\n// Section 4: Key Parsing\n// =============================================================================\n\n/**\n * Parse a query parameter key into code, optional modifier, and optional chain.\n *\n * Examples:\n * - `\"gender\"` \u2192 `{ code: \"gender\" }`\n * - `\"name:exact\"` \u2192 `{ code: \"name\", modifier: \"exact\" }`\n * - `\"code:not\"` \u2192 `{ code: \"code\", modifier: \"not\" }`\n * - `\"subject:Patient.name\"` \u2192 `{ code: \"subject\", chain: { targetType: \"Patient\", targetParam: \"name\" } }`\n */\nexport function parseParamKey(key: string): { code: string; modifier?: SearchModifier; chain?: ChainedSearchTarget } {\n const colonIdx = key.indexOf(':');\n if (colonIdx === -1) {\n return { code: key };\n }\n\n const code = key.substring(0, colonIdx);\n const rest = key.substring(colonIdx + 1);\n\n // Chained search: rest contains a dot \u2192 \"Patient.name\"\n const dotIdx = rest.indexOf('.');\n if (dotIdx !== -1) {\n const targetType = rest.substring(0, dotIdx);\n const targetParam = rest.substring(dotIdx + 1);\n if (targetType && targetParam) {\n return {\n code,\n chain: { targetType, targetParam },\n };\n }\n }\n\n const modifier = rest as SearchModifier;\n return { code, modifier };\n}\n\n// =============================================================================\n// Section 5: Value Parsing\n// =============================================================================\n\n/**\n * Split a search value string on commas (OR semantics).\n *\n * Escaped commas (`\\,`) are preserved as literal commas.\n *\n * Examples:\n * - `\"male\"` \u2192 `[\"male\"]`\n * - `\"male,female\"` \u2192 `[\"male\", \"female\"]`\n * - `\"a\\\\,b\"` \u2192 `[\"a,b\"]`\n */\nexport function splitSearchValues(value: string): string[] {\n const results: string[] = [];\n let current = '';\n\n for (let i = 0; i < value.length; i++) {\n if (value[i] === '\\\\' && i + 1 < value.length && value[i + 1] === ',') {\n current += ',';\n i++; // skip the comma\n } else if (value[i] === ',') {\n results.push(current);\n current = '';\n } else {\n current += value[i];\n }\n }\n\n results.push(current);\n return results.filter((v) => v !== '');\n}\n\n/**\n * Extract a search prefix from values if the parameter type supports it.\n *\n * Prefixes are two-letter codes at the start of the first value:\n * - `\"ge1990-01-01\"` \u2192 prefix `\"ge\"`, value `\"1990-01-01\"`\n * - `\"male\"` \u2192 no prefix, value `\"male\"`\n *\n * Only number, date, and quantity types support prefixes.\n */\nexport function extractPrefix(\n values: string[],\n paramType?: string,\n): { prefix?: SearchPrefix; cleanValues: string[] } {\n if (!paramType || !PREFIX_TYPES.has(paramType)) {\n return { cleanValues: values };\n }\n\n // Check each value for a prefix\n const cleanValues: string[] = [];\n let detectedPrefix: SearchPrefix | undefined;\n\n for (const value of values) {\n const candidate = value.substring(0, 2);\n if (SEARCH_PREFIXES.has(candidate) && value.length > 2) {\n if (!detectedPrefix) {\n detectedPrefix = candidate as SearchPrefix;\n }\n cleanValues.push(value.substring(2));\n } else {\n cleanValues.push(value);\n }\n }\n\n return { prefix: detectedPrefix, cleanValues };\n}\n\n// =============================================================================\n// Section 6: Include Parsing\n// =============================================================================\n\n/**\n * Parse a `_include` or `_revinclude` value into an `IncludeTarget`.\n *\n * Syntax: `{sourceType}:{searchParam}` or `{sourceType}:{searchParam}:{targetType}`\n *\n * Examples:\n * - `\"MedicationRequest:patient\"` \u2192 `{ resourceType: \"MedicationRequest\", searchParam: \"patient\" }`\n * - `\"Observation:subject:Patient\"` \u2192 `{ resourceType: \"Observation\", searchParam: \"subject\", targetType: \"Patient\" }`\n *\n * @returns Parsed IncludeTarget, or null if the format is invalid.\n */\nexport function parseIncludeValue(value: string): IncludeTarget | null {\n // Wildcard: _include=*\n if (value === '*') {\n return { resourceType: '*', searchParam: '*', wildcard: true };\n }\n\n const parts = value.split(':');\n if (parts.length < 2 || !parts[0] || !parts[1]) {\n return null;\n }\n\n const target: IncludeTarget = {\n resourceType: parts[0],\n searchParam: parts[1],\n };\n\n if (parts.length >= 3 && parts[2]) {\n target.targetType = parts[2];\n }\n\n return target;\n}\n\n// =============================================================================\n// Section 7: Sort Parsing\n// =============================================================================\n\n/**\n * Parse the `_sort` parameter value into `SortRule[]`.\n *\n * Examples:\n * - `\"birthdate\"` \u2192 `[{ code: \"birthdate\", descending: false }]`\n * - `\"-birthdate\"` \u2192 `[{ code: \"birthdate\", descending: true }]`\n * - `\"family,-birthdate\"` \u2192 two rules\n */\nexport function parseSortParam(value: string): SortRule[] {\n return value\n .split(',')\n .filter((v) => v.trim() !== '')\n .map((v) => {\n const trimmed = v.trim();\n if (trimmed.startsWith('-')) {\n return { code: trimmed.substring(1), descending: true };\n }\n return { code: trimmed, descending: false };\n });\n}\n", "/**\n * WHERE Clause Builder\n *\n * Generates parameterized SQL WHERE clause fragments from parsed\n * FHIR search parameters. Each fragment is composable \u2014 multiple\n * fragments are joined with AND/OR as needed.\n *\n * ## Design Principles\n *\n * 1. **Parameterized only** \u2014 all user values use `$N` placeholders (SQL injection safe)\n * 2. **Column names from registry** \u2014 never from user input\n * 3. **Composable fragments** \u2014 each function returns `{ sql, values }`\n * 4. **Strategy-aware** \u2014 handles column, token-column, and lookup-table differently\n *\n * Reference: https://hl7.org/fhir/R4/search.html\n *\n * @module fhir-persistence/search\n */\n\nimport type { SearchParameterImpl } from '../registry/search-parameter-registry.js';\nimport type { SearchParameterRegistry } from '../registry/search-parameter-registry.js';\nimport type { ParsedSearchParam, WhereFragment, SearchPrefix, ChainedSearchTarget } from './types.js';\n\n// =============================================================================\n// Section 1: Prefix \u2192 SQL Operator Mapping\n// =============================================================================\n\n/**\n * Map a FHIR search prefix to a SQL comparison operator.\n */\nexport function prefixToOperator(prefix?: SearchPrefix): string {\n switch (prefix) {\n case 'eq':\n case undefined:\n return '=';\n case 'ne':\n return '<>';\n case 'lt':\n return '<';\n case 'gt':\n return '>';\n case 'le':\n return '<=';\n case 'ge':\n return '>=';\n case 'sa':\n return '>'; // starts after\n case 'eb':\n return '<'; // ends before\n case 'ap':\n return 'ap'; // approximately \u2014 handled by type-specific builders\n default:\n return '=';\n }\n}\n\n// =============================================================================\n// Section 2: Core WHERE Fragment Builder\n// =============================================================================\n\n/**\n * Build a WHERE clause fragment for a single parsed search parameter.\n *\n * Dispatches to type-specific builders based on the SearchParameterImpl type\n * and the parameter's modifier.\n *\n * @param impl - The search parameter implementation from the registry.\n * @param param - The parsed search parameter from the URL.\n * @param startIndex - The starting `$N` parameter index (1-based).\n * @returns A WhereFragment with SQL and values, or null if the parameter\n * cannot be converted (e.g., lookup-table strategy).\n */\nexport function buildWhereFragment(\n impl: SearchParameterImpl,\n param: ParsedSearchParam,\n startIndex: number,\n): WhereFragment | null {\n // Handle :missing modifier (any type)\n if (param.modifier === 'missing') {\n return buildMissingFragment(impl, param, startIndex);\n }\n\n // Lookup-table strategy \u2014 search the __<name>Sort column\n if (impl.strategy === 'lookup-table') {\n return buildLookupTableFragment(impl, param, startIndex);\n }\n\n // Dispatch by strategy\n if (impl.strategy === 'token-column') {\n return buildTokenColumnFragment(impl, param, startIndex);\n }\n\n // Column strategy \u2014 dispatch by FHIR type\n switch (impl.type) {\n case 'string':\n return buildStringFragment(impl, param, startIndex);\n case 'date':\n return buildDateFragment(impl, param, startIndex);\n case 'number':\n case 'quantity':\n return buildNumberFragment(impl, param, startIndex);\n case 'reference':\n return buildReferenceFragment(impl, param, startIndex);\n case 'uri':\n return buildUriFragment(impl, param, startIndex);\n case 'token':\n return buildTokenColumnFragment(impl, param, startIndex);\n default:\n return buildDefaultFragment(impl, param, startIndex);\n }\n}\n\n// =============================================================================\n// Section 2b: Chained Search Fragment\n// =============================================================================\n\n/**\n * Build a WHERE fragment for a chained search parameter.\n *\n * Chained search: `subject:Patient.name=Smith`\n * - Source param: `subject` (reference on source resource type)\n * - Target type: `Patient`\n * - Target param: `name` (search param on target type)\n * - Value: `Smith`\n *\n * Generated SQL:\n * ```sql\n * EXISTS (\n * SELECT 1 FROM \"Observation_References\" __ref\n * JOIN \"Patient\" __target ON __ref.\"targetId\" = __target.\"id\"\n * WHERE __ref.\"resourceId\" = \"Observation\".\"id\"\n * AND __ref.\"code\" = 'subject'\n * AND __target.\"deleted\" = false\n * AND <target param condition>\n * )\n * ```\n */\nfunction buildChainedFragment(\n param: ParsedSearchParam,\n chain: ChainedSearchTarget,\n registry: SearchParameterRegistry,\n sourceResourceType: string,\n startIndex: number,\n): WhereFragment | null {\n // Resolve the target param implementation on the TARGET resource type\n const targetImpl = resolveImpl(\n { code: chain.targetParam, values: param.values, modifier: param.modifier, prefix: param.prefix },\n registry,\n chain.targetType,\n );\n if (!targetImpl) return null;\n\n // Build the inner WHERE condition for the target table\n // We use a temporary param that represents the target search\n const innerParam: ParsedSearchParam = {\n code: chain.targetParam,\n values: param.values,\n modifier: param.modifier,\n prefix: param.prefix,\n };\n\n const innerFragment = buildWhereFragment(targetImpl, innerParam, startIndex);\n if (!innerFragment) return null;\n\n // Rewrite the inner SQL to prefix column names with __target.\n // The inner fragment produces SQL like: \"name\" = $1\n // We need: __target.\"name\" = $1\n const innerSql = rewriteColumnRefsForAlias(innerFragment.sql, '__target');\n\n const refTable = `${sourceResourceType}_References`;\n const sql = [\n `EXISTS (`,\n ` SELECT 1 FROM \"${refTable}\" __ref`,\n ` JOIN \"${chain.targetType}\" __target ON __ref.\"targetId\" = __target.\"id\"`,\n ` WHERE __ref.\"resourceId\" = \"${sourceResourceType}\".\"id\"`,\n ` AND __ref.\"code\" = '${param.code}'`,\n ` AND __target.\"deleted\" = false`,\n ` AND ${innerSql}`,\n `)`,\n ].join('\\n');\n\n return { sql, values: innerFragment.values };\n}\n\n/**\n * Rewrite quoted column references in SQL to use a table alias prefix.\n *\n * Transforms `\"columnName\"` \u2192 `__alias.\"columnName\"`\n * but avoids rewriting `$N` parameters or already-aliased references.\n *\n * This is needed because buildWhereFragment generates column references\n * without table qualification, but inside an EXISTS subquery we need\n * to qualify them with the target table alias.\n */\nfunction rewriteColumnRefsForAlias(sql: string, alias: string): string {\n // Match quoted identifiers that are NOT preceded by a dot or another quote\n // Pattern: a standalone \"identifier\" at the start or after whitespace/operators\n return sql.replace(/(?<![.\"a-zA-Z])\"([^\"]+)\"/g, `${alias}.\"$1\"`);\n}\n\n// =============================================================================\n// Section 3: :missing Modifier\n// =============================================================================\n\n/**\n * Build a WHERE fragment for the `:missing` modifier.\n *\n * - `?active:missing=true` \u2192 `\"active\" IS NULL`\n * - `?active:missing=false` \u2192 `\"active\" IS NOT NULL`\n */\nfunction buildMissingFragment(\n impl: SearchParameterImpl,\n param: ParsedSearchParam,\n _startIndex: number,\n): WhereFragment {\n const isMissing = param.values[0] === 'true';\n const columnName = quoteColumn(impl.columnName);\n const sql = isMissing ? `${columnName} IS NULL` : `${columnName} IS NOT NULL`;\n return { sql, values: [] };\n}\n\n// =============================================================================\n// Section 3b: Lookup-Table Strategy (global table JOIN search)\n// =============================================================================\n\n/**\n * Map search param codes to their global lookup table and column.\n *\n * Matches Medplum's production design:\n * - HumanName: name/given/family columns\n * - Address: address/city/country/postalCode/state/use columns\n * - ContactPoint: system/value columns\n */\nconst LOOKUP_TABLE_MAP: Record<string, { table: string; column: string }> = {\n // HumanName\n name: { table: 'HumanName', column: 'name' },\n given: { table: 'HumanName', column: 'given' },\n family: { table: 'HumanName', column: 'family' },\n phonetic: { table: 'HumanName', column: 'name' },\n // Address\n address: { table: 'Address', column: 'address' },\n 'address-city': { table: 'Address', column: 'city' },\n 'address-country': { table: 'Address', column: 'country' },\n 'address-postalcode': { table: 'Address', column: 'postalCode' },\n 'address-state': { table: 'Address', column: 'state' },\n 'address-use': { table: 'Address', column: 'use' },\n // ContactPoint\n telecom: { table: 'ContactPoint', column: 'value' },\n email: { table: 'ContactPoint', column: 'value' },\n phone: { table: 'ContactPoint', column: 'value' },\n};\n\n/**\n * Build a WHERE fragment for lookup-table strategy parameters.\n *\n * Generates an EXISTS subquery against the appropriate global lookup table:\n * ```sql\n * EXISTS (SELECT 1 FROM \"HumanName\" __lookup\n * WHERE __lookup.\"resourceId\" = \"id\" AND LOWER(__lookup.\"family\") LIKE $1)\n * ```\n *\n * Falls back to `__<name>Sort` column search if no mapping exists.\n *\n * Supports string modifiers:\n * - No modifier \u2192 case-insensitive prefix match (ILIKE 'value%')\n * - `:exact` \u2192 exact match (`= $N`)\n * - `:contains` \u2192 contains match (ILIKE '%value%')\n */\nfunction buildLookupTableFragment(\n impl: SearchParameterImpl,\n param: ParsedSearchParam,\n startIndex: number,\n): WhereFragment {\n const mapping = LOOKUP_TABLE_MAP[impl.code];\n\n // Fallback to sort-column search if no global table mapping\n if (!mapping) {\n const sortColumn = quoteColumn(`__${impl.columnName}Sort`);\n if (param.modifier === 'exact') {\n return buildOrFragment(sortColumn, '=', param.values, startIndex);\n }\n if (param.modifier === 'contains') {\n return buildLikeFragment(sortColumn, param.values, startIndex, '%', '%');\n }\n return buildLikeFragment(sortColumn, param.values, startIndex, '', '%');\n }\n\n // Build EXISTS subquery against global lookup table\n const { table, column } = mapping;\n const colRef = `__lookup.\"${column}\"`;\n\n if (param.modifier === 'exact') {\n // Exact: direct equality\n if (param.values.length === 1) {\n const sql = `EXISTS (SELECT 1 FROM \"${table}\" __lookup WHERE __lookup.\"resourceId\" = \"id\" AND ${colRef} = $${startIndex})`;\n return { sql, values: [param.values[0]] };\n }\n const conditions = param.values.map((_, i) => `${colRef} = $${startIndex + i}`);\n const sql = `EXISTS (SELECT 1 FROM \"${table}\" __lookup WHERE __lookup.\"resourceId\" = \"id\" AND (${conditions.join(' OR ')}))`;\n return { sql, values: [...param.values] };\n }\n\n if (param.modifier === 'contains') {\n // Contains: ILIKE '%value%'\n if (param.values.length === 1) {\n const sql = `EXISTS (SELECT 1 FROM \"${table}\" __lookup WHERE __lookup.\"resourceId\" = \"id\" AND LOWER(${colRef}) LIKE $${startIndex})`;\n return { sql, values: [`%${param.values[0].toLowerCase()}%`] };\n }\n const conditions = param.values.map((_, i) => `LOWER(${colRef}) LIKE $${startIndex + i}`);\n const sql = `EXISTS (SELECT 1 FROM \"${table}\" __lookup WHERE __lookup.\"resourceId\" = \"id\" AND (${conditions.join(' OR ')}))`;\n return { sql, values: param.values.map(v => `%${v.toLowerCase()}%`) };\n }\n\n // Default: prefix match (ILIKE 'value%')\n if (param.values.length === 1) {\n const sql = `EXISTS (SELECT 1 FROM \"${table}\" __lookup WHERE __lookup.\"resourceId\" = \"id\" AND LOWER(${colRef}) LIKE $${startIndex})`;\n return { sql, values: [`${param.values[0].toLowerCase()}%`] };\n }\n const conditions = param.values.map((_, i) => `LOWER(${colRef}) LIKE $${startIndex + i}`);\n const sql = `EXISTS (SELECT 1 FROM \"${table}\" __lookup WHERE __lookup.\"resourceId\" = \"id\" AND (${conditions.join(' OR ')}))`;\n return { sql, values: param.values.map(v => `${v.toLowerCase()}%`) };\n}\n\n// =============================================================================\n// Section 4: String Type\n// =============================================================================\n\n/**\n * Build a WHERE fragment for string search parameters.\n *\n * Default behavior: case-insensitive prefix match (ILIKE 'value%').\n * - `:exact` modifier \u2192 exact match (`= $N`)\n * - `:contains` modifier \u2192 contains match (`ILIKE '%value%'`)\n * - No modifier \u2192 prefix match (`ILIKE 'value%'`)\n */\nfunction buildStringFragment(\n impl: SearchParameterImpl,\n param: ParsedSearchParam,\n startIndex: number,\n): WhereFragment {\n const columnName = quoteColumn(impl.columnName);\n\n if (param.modifier === 'exact') {\n return buildOrFragment(columnName, '=', param.values, startIndex);\n }\n\n if (param.modifier === 'contains') {\n return buildLikeFragment(columnName, param.values, startIndex, '%', '%');\n }\n\n // Default: prefix match\n return buildLikeFragment(columnName, param.values, startIndex, '', '%');\n}\n\n/**\n * Build an ILIKE fragment with optional prefix/suffix wildcards.\n */\nfunction buildLikeFragment(\n columnName: string,\n values: string[],\n startIndex: number,\n prefix: string,\n suffix: string,\n): WhereFragment {\n if (values.length === 1) {\n const sql = `LOWER(${columnName}) LIKE $${startIndex}`;\n const escapedValue = escapeLikeString(values[0]).toLowerCase();\n return { sql, values: [`${prefix}${escapedValue}${suffix}`] };\n }\n\n // Multiple values \u2192 OR\n const conditions: string[] = [];\n const allValues: unknown[] = [];\n let idx = startIndex;\n\n for (const value of values) {\n conditions.push(`LOWER(${columnName}) LIKE $${idx}`);\n const escapedValue = escapeLikeString(value).toLowerCase();\n allValues.push(`${prefix}${escapedValue}${suffix}`);\n idx++;\n }\n\n const sql = `(${conditions.join(' OR ')})`;\n return { sql, values: allValues };\n}\n\n// =============================================================================\n// Section 5: Date Type\n// =============================================================================\n\n/**\n * Build a WHERE fragment for date search parameters.\n *\n * Supports prefixes: eq, ne, lt, gt, le, ge, ap.\n * For `ap`, uses a \u00B11 day range around the target date.\n */\nfunction buildDateFragment(\n impl: SearchParameterImpl,\n param: ParsedSearchParam,\n startIndex: number,\n): WhereFragment {\n const columnName = quoteColumn(impl.columnName);\n\n // ap (approximately) \u2192 BETWEEN (date - 1 day) AND (date + 1 day)\n if (param.prefix === 'ap') {\n return buildApproximateDateFragment(columnName, param.values, startIndex);\n }\n\n const operator = prefixToOperator(param.prefix);\n return buildOrFragment(columnName, operator, param.values, startIndex);\n}\n\n/**\n * Build a BETWEEN fragment for approximate date matching.\n * Uses \u00B11 day range for each value.\n */\nfunction buildApproximateDateFragment(\n columnName: string,\n values: string[],\n startIndex: number,\n): WhereFragment {\n if (values.length === 1) {\n const sql = `${columnName} BETWEEN $${startIndex} AND $${startIndex + 1}`;\n const d = new Date(values[0]);\n const lo = new Date(d.getTime() - 86_400_000).toISOString();\n const hi = new Date(d.getTime() + 86_400_000).toISOString();\n return { sql, values: [lo, hi] };\n }\n\n const conditions: string[] = [];\n const allValues: unknown[] = [];\n let idx = startIndex;\n for (const value of values) {\n conditions.push(`${columnName} BETWEEN $${idx} AND $${idx + 1}`);\n const d = new Date(value);\n allValues.push(new Date(d.getTime() - 86_400_000).toISOString());\n allValues.push(new Date(d.getTime() + 86_400_000).toISOString());\n idx += 2;\n }\n return { sql: `(${conditions.join(' OR ')})`, values: allValues };\n}\n\n// =============================================================================\n// Section 6: Number / Quantity Type\n// =============================================================================\n\n/**\n * Build a WHERE fragment for number and quantity search parameters.\n *\n * Supports prefixes: eq, ne, lt, gt, le, ge, ap.\n * For `ap`, uses a \u00B110% range around the target value.\n */\nfunction buildNumberFragment(\n impl: SearchParameterImpl,\n param: ParsedSearchParam,\n startIndex: number,\n): WhereFragment {\n const columnName = quoteColumn(impl.columnName);\n\n // ap (approximately) \u2192 BETWEEN (value * 0.9) AND (value * 1.1)\n if (param.prefix === 'ap') {\n return buildApproximateNumberFragment(columnName, param.values, startIndex);\n }\n\n const operator = prefixToOperator(param.prefix);\n\n // Convert values to numbers\n const numericValues = param.values.map((v) => {\n const n = parseFloat(v);\n return isNaN(n) ? v : n;\n });\n\n return buildOrFragmentRaw(columnName, operator, numericValues, startIndex);\n}\n\n/**\n * Build a BETWEEN fragment for approximate number matching.\n * Uses \u00B110% range for each value (FHIR spec).\n */\nfunction buildApproximateNumberFragment(\n columnName: string,\n values: string[],\n startIndex: number,\n): WhereFragment {\n if (values.length === 1) {\n const n = parseFloat(values[0]);\n const lo = n * 0.9;\n const hi = n * 1.1;\n const sql = `${columnName} BETWEEN $${startIndex} AND $${startIndex + 1}`;\n return { sql, values: [lo, hi] };\n }\n\n const conditions: string[] = [];\n const allValues: unknown[] = [];\n let idx = startIndex;\n for (const value of values) {\n const n = parseFloat(value);\n conditions.push(`${columnName} BETWEEN $${idx} AND $${idx + 1}`);\n allValues.push(n * 0.9);\n allValues.push(n * 1.1);\n idx += 2;\n }\n return { sql: `(${conditions.join(' OR ')})`, values: allValues };\n}\n\n// =============================================================================\n// Section 7: Reference Type\n// =============================================================================\n\n/**\n * Build a WHERE fragment for reference search parameters.\n *\n * Reference values can be:\n * - Full reference: `\"Patient/123\"`\n * - Just the ID: `\"123\"` (for subject/patient columns, auto-prefixed)\n */\nfunction buildReferenceFragment(\n impl: SearchParameterImpl,\n param: ParsedSearchParam,\n startIndex: number,\n): WhereFragment {\n const columnName = quoteColumn(impl.columnName);\n\n // For array reference columns (TEXT[]), use array overlap operator\n if (impl.array) {\n if (param.values.length === 1) {\n const sql = `${columnName} && ARRAY[$${startIndex}]::text[]`;\n return { sql, values: [param.values[0]] };\n }\n const placeholders = param.values.map((_, i) => `$${startIndex + i}`);\n const sql = `${columnName} && ARRAY[${placeholders.join(', ')}]::text[]`;\n return { sql, values: [...param.values] };\n }\n\n // Scalar reference column \u2014 simple equality\n return buildOrFragment(columnName, '=', param.values, startIndex);\n}\n\n// =============================================================================\n// Section 8: URI Type\n// =============================================================================\n\n/**\n * Build a WHERE fragment for URI search parameters.\n *\n * Exact match by default.\n */\nfunction buildUriFragment(\n impl: SearchParameterImpl,\n param: ParsedSearchParam,\n startIndex: number,\n): WhereFragment {\n const columnName = quoteColumn(impl.columnName);\n\n // For array URI columns (e.g., _profile TEXT[]), use array overlap\n if (impl.array) {\n const placeholders = param.values.map((_, i) => `$${startIndex + i}`);\n const sql = `${columnName} && ARRAY[${placeholders.join(', ')}]::text[]`;\n return { sql, values: [...param.values] };\n }\n\n return buildOrFragment(columnName, '=', param.values, startIndex);\n}\n\n// =============================================================================\n// Section 9: Token Type (column strategy)\n// =============================================================================\n\n/**\n * Build a WHERE fragment for token search parameters.\n *\n * Token values can be:\n * - `\"code\"` \u2192 match code only\n * - `\"system|code\"` \u2192 match system and code\n * - `\"system|\"` \u2192 match system only\n * - `\"|code\"` \u2192 match code with no system\n *\n * For token-column strategy, we use ARRAY overlap operators.\n * For column strategy (simple tokens like gender), we use equality.\n */\nfunction buildTokenColumnFragment(\n impl: SearchParameterImpl,\n param: ParsedSearchParam,\n startIndex: number,\n): WhereFragment {\n // For token-column strategy, the actual DB columns are:\n // __<name> UUID[] (hash column)\n // __<name>Text TEXT[] (system|code text column)\n // __<name>Sort TEXT (first display/text value for sorting)\n const textColumnName = quoteColumn(`__${impl.columnName}Text`);\n const sortColumnName = quoteColumn(`__${impl.columnName}Sort`);\n\n // :text modifier \u2014 search display text via sort column with ILIKE prefix match\n if (param.modifier === 'text') {\n if (param.values.length === 1) {\n const sql = `LOWER(${sortColumnName}) LIKE $${startIndex}`;\n return { sql, values: [param.values[0].toLowerCase() + '%'] };\n }\n const conditions: string[] = [];\n const allValues: unknown[] = [];\n for (let i = 0; i < param.values.length; i++) {\n conditions.push(`LOWER(${sortColumnName}) LIKE $${startIndex + i}`);\n allValues.push(param.values[i].toLowerCase() + '%');\n }\n return { sql: `(${conditions.join(' OR ')})`, values: allValues };\n }\n\n // Check for system| pattern (system with any code) \u2014 needs LIKE-based search\n const needsLike = param.values.some((v) => v.endsWith('|'));\n if (needsLike) {\n const conditions: string[] = [];\n const allValues: unknown[] = [];\n let idx = startIndex;\n for (const value of param.values) {\n if (value.endsWith('|')) {\n // system| \u2192 match any entry starting with \"system|\"\n conditions.push(\n `EXISTS (SELECT 1 FROM unnest(${textColumnName}) __t WHERE __t LIKE $${idx})`,\n );\n allValues.push(value + '%');\n } else {\n // Normal value \u2014 array overlap\n conditions.push(`${textColumnName} && ARRAY[$${idx}]::text[]`);\n allValues.push(value.startsWith('|') ? value.slice(1) : value);\n }\n idx++;\n }\n const sql = param.modifier === 'not'\n ? `NOT (${conditions.join(' OR ')})`\n : conditions.length === 1\n ? conditions[0]\n : `(${conditions.join(' OR ')})`;\n return { sql, values: allValues };\n }\n\n // For |code pattern, strip the leading pipe and search for plain code\n const resolvedValues = param.values.map((v) => (v.startsWith('|') ? v.slice(1) : v));\n\n if (param.modifier === 'not') {\n // NOT: none of the values should be in the array\n if (resolvedValues.length === 1) {\n const sql = `NOT (${textColumnName} && ARRAY[$${startIndex}]::text[])`;\n return { sql, values: [resolvedValues[0]] };\n }\n const placeholders = resolvedValues.map((_, i) => `$${startIndex + i}`);\n const sql = `NOT (${textColumnName} && ARRAY[${placeholders.join(', ')}]::text[])`;\n return { sql, values: [...resolvedValues] };\n }\n\n // Default: array overlap \u2014 any of the values match\n if (resolvedValues.length === 1) {\n const sql = `${textColumnName} && ARRAY[$${startIndex}]::text[]`;\n return { sql, values: [resolvedValues[0]] };\n }\n\n const placeholders = resolvedValues.map((_, i) => `$${startIndex + i}`);\n const sql = `${textColumnName} && ARRAY[${placeholders.join(', ')}]::text[]`;\n return { sql, values: [...resolvedValues] };\n}\n\n// =============================================================================\n// Section 10: Default / Fallback\n// =============================================================================\n\n/**\n * Build a WHERE fragment for unknown or unsupported parameter types.\n * Falls back to simple equality.\n */\nfunction buildDefaultFragment(\n impl: SearchParameterImpl,\n param: ParsedSearchParam,\n startIndex: number,\n): WhereFragment {\n const columnName = quoteColumn(impl.columnName);\n const operator = prefixToOperator(param.prefix);\n return buildOrFragment(columnName, operator, param.values, startIndex);\n}\n\n// =============================================================================\n// Section 11: Shared Helpers\n// =============================================================================\n\n/**\n * Build an OR fragment for multiple values with the same operator.\n *\n * Single value: `\"col\" = $1`\n * Multiple values: `(\"col\" = $1 OR \"col\" = $2)`\n */\nfunction buildOrFragment(\n columnName: string,\n operator: string,\n values: string[],\n startIndex: number,\n): WhereFragment {\n return buildOrFragmentRaw(columnName, operator, values, startIndex);\n}\n\n/**\n * Build an OR fragment with raw (non-string) values.\n */\nfunction buildOrFragmentRaw(\n columnName: string,\n operator: string,\n values: unknown[],\n startIndex: number,\n): WhereFragment {\n if (values.length === 1) {\n const sql = `${columnName} ${operator} $${startIndex}`;\n return { sql, values: [values[0]] };\n }\n\n const conditions: string[] = [];\n const allValues: unknown[] = [];\n let idx = startIndex;\n\n for (const value of values) {\n conditions.push(`${columnName} ${operator} $${idx}`);\n allValues.push(value);\n idx++;\n }\n\n const sql = `(${conditions.join(' OR ')})`;\n return { sql, values: allValues };\n}\n\n/**\n * Double-quote a column name for safe SQL usage.\n */\nfunction quoteColumn(name: string): string {\n return `\"${name}\"`;\n}\n\n/**\n * Escape special characters in a LIKE pattern.\n *\n * Escapes `%`, `_`, and `\\` with a backslash.\n */\nfunction escapeLikeString(value: string): string {\n return value.replace(/[%_\\\\]/g, '\\\\$&');\n}\n\n// =============================================================================\n// Section 12: Composite WHERE Builder\n// =============================================================================\n\n/**\n * Build a complete WHERE clause from multiple parsed search parameters.\n *\n * Multiple parameters are joined with AND.\n * Returns null if no valid fragments are produced.\n *\n * @param params - The parsed search parameters.\n * @param registry - The SearchParameterRegistry for looking up implementations.\n * @param resourceType - The FHIR resource type.\n * @returns A WhereFragment with the combined WHERE clause, or null.\n */\nexport function buildWhereClause(\n params: ParsedSearchParam[],\n registry: SearchParameterRegistry,\n resourceType: string,\n): WhereFragment | null {\n const fragments: WhereFragment[] = [];\n let paramIndex = 1;\n\n for (const param of params) {\n // Handle chained search parameters\n if (param.chain) {\n const fragment = buildChainedFragment(param, param.chain, registry, resourceType, paramIndex);\n if (fragment) {\n fragments.push(fragment);\n paramIndex += fragment.values.length;\n }\n continue;\n }\n\n // Handle special parameters\n const impl = resolveImpl(param, registry, resourceType);\n if (!impl) {\n continue;\n }\n\n const fragment = buildWhereFragment(impl, param, paramIndex);\n if (fragment) {\n fragments.push(fragment);\n paramIndex += fragment.values.length;\n }\n }\n\n if (fragments.length === 0) {\n return null;\n }\n\n const sql = fragments.map((f) => f.sql).join(' AND ');\n const values = fragments.flatMap((f) => f.values);\n return { sql, values };\n}\n\n/**\n * Resolve a SearchParameterImpl for a parsed parameter.\n *\n * Handles special parameters (_id, _lastUpdated) with synthetic impls.\n */\nfunction resolveImpl(\n param: ParsedSearchParam,\n registry: SearchParameterRegistry,\n resourceType: string,\n): SearchParameterImpl | null {\n // Special parameters with fixed columns\n switch (param.code) {\n case '_id':\n return {\n code: '_id',\n type: 'uri',\n resourceTypes: [resourceType],\n expression: 'id',\n strategy: 'column',\n columnName: 'id',\n columnType: 'TEXT',\n array: false,\n };\n case '_lastUpdated':\n return {\n code: '_lastUpdated',\n type: 'date',\n resourceTypes: [resourceType],\n expression: 'meta.lastUpdated',\n strategy: 'column',\n columnName: 'lastUpdated',\n columnType: 'TIMESTAMPTZ',\n array: false,\n };\n case '_tag':\n return {\n code: '_tag',\n type: 'token',\n resourceTypes: [resourceType],\n expression: 'meta.tag',\n strategy: 'token-column',\n columnName: '_tag',\n columnType: 'TEXT[]',\n array: true,\n };\n case '_security':\n return {\n code: '_security',\n type: 'token',\n resourceTypes: [resourceType],\n expression: 'meta.security',\n strategy: 'token-column',\n columnName: '_security',\n columnType: 'TEXT[]',\n array: true,\n };\n case '_profile':\n return {\n code: '_profile',\n type: 'uri',\n resourceTypes: [resourceType],\n expression: 'meta.profile',\n strategy: 'column',\n columnName: '_profile',\n columnType: 'TEXT[]',\n array: true,\n };\n case '_source':\n return {\n code: '_source',\n type: 'uri',\n resourceTypes: [resourceType],\n expression: 'meta.source',\n strategy: 'column',\n columnName: '_source',\n columnType: 'TEXT',\n array: false,\n };\n default:\n return registry.getImpl(resourceType, param.code) ?? null;\n }\n}\n\n// =============================================================================\n// Section 13: v2 WHERE Builder (SQLite ? placeholders)\n// =============================================================================\n\n/**\n * v2: Build a WHERE clause fragment using ? placeholders (SQLite).\n *\n * Dispatches to type-specific v2 builders. Key differences from v1:\n * - Uses `?` instead of `$N`\n * - Token search uses `json_each()` instead of `ARRAY[]::text[]`\n * - Array columns use `json_each()` instead of PG array operators\n */\nexport function buildWhereFragmentV2(\n impl: SearchParameterImpl,\n param: ParsedSearchParam,\n): WhereFragment | null {\n if (param.modifier === 'missing') {\n return buildMissingFragmentV2(impl, param);\n }\n\n if (impl.strategy === 'lookup-table') {\n return buildLookupTableFragmentV2(impl, param);\n }\n\n if (impl.strategy === 'token-column') {\n return buildTokenColumnFragmentV2(impl, param);\n }\n\n switch (impl.type) {\n case 'string':\n return buildStringFragmentV2(impl, param);\n case 'date':\n return buildDateFragmentV2(impl, param);\n case 'number':\n case 'quantity':\n return buildNumberFragmentV2(impl, param);\n case 'reference':\n return buildReferenceFragmentV2(impl, param);\n case 'uri':\n return buildUriFragmentV2(impl, param);\n case 'token':\n return buildTokenColumnFragmentV2(impl, param);\n default:\n return buildDefaultFragmentV2(impl, param);\n }\n}\n\n// -- v2 :missing --\nfunction buildMissingFragmentV2(\n impl: SearchParameterImpl,\n param: ParsedSearchParam,\n): WhereFragment {\n const isMissing = param.values[0] === 'true';\n const col = quoteColumn(impl.columnName);\n return { sql: isMissing ? `${col} IS NULL` : `${col} IS NOT NULL`, values: [] };\n}\n\n// -- v2 lookup-table --\nfunction buildLookupTableFragmentV2(\n impl: SearchParameterImpl,\n param: ParsedSearchParam,\n): WhereFragment {\n const mapping = LOOKUP_TABLE_MAP[impl.code];\n if (!mapping) {\n const sortCol = quoteColumn(`__${impl.columnName}Sort`);\n if (param.modifier === 'exact') return buildOrFragmentV2(sortCol, '=', param.values);\n if (param.modifier === 'contains') return buildLikeFragmentV2(sortCol, param.values, '%', '%');\n return buildLikeFragmentV2(sortCol, param.values, '', '%');\n }\n const { table, column } = mapping;\n const colRef = `__lookup.\"${column}\"`;\n if (param.modifier === 'exact') {\n if (param.values.length === 1) {\n return { sql: `EXISTS (SELECT 1 FROM \"${table}\" __lookup WHERE __lookup.\"resourceId\" = \"id\" AND ${colRef} = ?)`, values: [param.values[0]] };\n }\n const conds = param.values.map(() => `${colRef} = ?`);\n return { sql: `EXISTS (SELECT 1 FROM \"${table}\" __lookup WHERE __lookup.\"resourceId\" = \"id\" AND (${conds.join(' OR ')}))`, values: [...param.values] };\n }\n if (param.modifier === 'contains') {\n if (param.values.length === 1) {\n return { sql: `EXISTS (SELECT 1 FROM \"${table}\" __lookup WHERE __lookup.\"resourceId\" = \"id\" AND LOWER(${colRef}) LIKE ?)`, values: [`%${param.values[0].toLowerCase()}%`] };\n }\n const conds = param.values.map(() => `LOWER(${colRef}) LIKE ?`);\n return { sql: `EXISTS (SELECT 1 FROM \"${table}\" __lookup WHERE __lookup.\"resourceId\" = \"id\" AND (${conds.join(' OR ')}))`, values: param.values.map(v => `%${v.toLowerCase()}%`) };\n }\n // default prefix match\n if (param.values.length === 1) {\n return { sql: `EXISTS (SELECT 1 FROM \"${table}\" __lookup WHERE __lookup.\"resourceId\" = \"id\" AND LOWER(${colRef}) LIKE ?)`, values: [`${param.values[0].toLowerCase()}%`] };\n }\n const conds = param.values.map(() => `LOWER(${colRef}) LIKE ?`);\n return { sql: `EXISTS (SELECT 1 FROM \"${table}\" __lookup WHERE __lookup.\"resourceId\" = \"id\" AND (${conds.join(' OR ')}))`, values: param.values.map(v => `${v.toLowerCase()}%`) };\n}\n\n// -- v2 string --\nfunction buildStringFragmentV2(\n impl: SearchParameterImpl,\n param: ParsedSearchParam,\n): WhereFragment {\n const col = quoteColumn(impl.columnName);\n if (param.modifier === 'exact') return buildOrFragmentV2(col, '=', param.values);\n if (param.modifier === 'contains') return buildLikeFragmentV2(col, param.values, '%', '%');\n return buildLikeFragmentV2(col, param.values, '', '%');\n}\n\n// -- v2 date --\nfunction buildDateFragmentV2(\n impl: SearchParameterImpl,\n param: ParsedSearchParam,\n): WhereFragment {\n const col = quoteColumn(impl.columnName);\n if (param.prefix === 'ap') {\n if (param.values.length === 1) {\n const d = new Date(param.values[0]);\n const lo = new Date(d.getTime() - 86_400_000).toISOString();\n const hi = new Date(d.getTime() + 86_400_000).toISOString();\n return { sql: `${col} BETWEEN ? AND ?`, values: [lo, hi] };\n }\n const conds: string[] = [];\n const vals: unknown[] = [];\n for (const v of param.values) {\n conds.push(`${col} BETWEEN ? AND ?`);\n const d = new Date(v);\n vals.push(new Date(d.getTime() - 86_400_000).toISOString());\n vals.push(new Date(d.getTime() + 86_400_000).toISOString());\n }\n return { sql: `(${conds.join(' OR ')})`, values: vals };\n }\n const op = prefixToOperator(param.prefix);\n return buildOrFragmentV2(col, op, param.values);\n}\n\n// -- v2 number/quantity --\nfunction buildNumberFragmentV2(\n impl: SearchParameterImpl,\n param: ParsedSearchParam,\n): WhereFragment {\n const col = quoteColumn(impl.columnName);\n if (param.prefix === 'ap') {\n if (param.values.length === 1) {\n const n = parseFloat(param.values[0]);\n return { sql: `${col} BETWEEN ? AND ?`, values: [n * 0.9, n * 1.1] };\n }\n const conds: string[] = [];\n const vals: unknown[] = [];\n for (const v of param.values) {\n const n = parseFloat(v);\n conds.push(`${col} BETWEEN ? AND ?`);\n vals.push(n * 0.9, n * 1.1);\n }\n return { sql: `(${conds.join(' OR ')})`, values: vals };\n }\n const op = prefixToOperator(param.prefix);\n const numVals = param.values.map(v => { const n = parseFloat(v); return isNaN(n) ? v : n; });\n return buildOrFragmentV2Raw(col, op, numVals);\n}\n\n// -- v2 reference --\nfunction buildReferenceFragmentV2(\n impl: SearchParameterImpl,\n param: ParsedSearchParam,\n): WhereFragment {\n const col = quoteColumn(impl.columnName);\n // For array reference columns in SQLite, use json_each\n if (impl.array) {\n if (param.values.length === 1) {\n return { sql: `EXISTS (SELECT 1 FROM json_each(${col}) WHERE json_each.value = ?)`, values: [param.values[0]] };\n }\n const placeholders = param.values.map(() => '?').join(', ');\n return { sql: `EXISTS (SELECT 1 FROM json_each(${col}) WHERE json_each.value IN (${placeholders}))`, values: [...param.values] };\n }\n return buildOrFragmentV2(col, '=', param.values);\n}\n\n// -- v2 uri --\nfunction buildUriFragmentV2(\n impl: SearchParameterImpl,\n param: ParsedSearchParam,\n): WhereFragment {\n const col = quoteColumn(impl.columnName);\n if (impl.array) {\n if (param.values.length === 1) {\n return { sql: `EXISTS (SELECT 1 FROM json_each(${col}) WHERE json_each.value = ?)`, values: [param.values[0]] };\n }\n const placeholders = param.values.map(() => '?').join(', ');\n return { sql: `EXISTS (SELECT 1 FROM json_each(${col}) WHERE json_each.value IN (${placeholders}))`, values: [...param.values] };\n }\n return buildOrFragmentV2(col, '=', param.values);\n}\n\n// -- v2 token (json_each for SQLite) --\nfunction buildTokenColumnFragmentV2(\n impl: SearchParameterImpl,\n param: ParsedSearchParam,\n): WhereFragment {\n // v2 token columns: __<name>Text is a JSON array string (TEXT), __<name>Sort is TEXT\n const textCol = quoteColumn(`__${impl.columnName}Text`);\n const sortCol = quoteColumn(`__${impl.columnName}Sort`);\n\n // :text modifier \u2014 search display text via sort column\n if (param.modifier === 'text') {\n return buildLikeFragmentV2(sortCol, param.values, '', '%');\n }\n\n // system| pattern\n const needsLike = param.values.some(v => v.endsWith('|'));\n if (needsLike) {\n const conds: string[] = [];\n const vals: unknown[] = [];\n for (const value of param.values) {\n if (value.endsWith('|')) {\n conds.push(`EXISTS (SELECT 1 FROM json_each(${textCol}) WHERE json_each.value LIKE ?)`);\n vals.push(value + '%');\n } else {\n conds.push(`EXISTS (SELECT 1 FROM json_each(${textCol}) WHERE json_each.value = ?)`);\n vals.push(value.startsWith('|') ? value.slice(1) : value);\n }\n }\n const inner = conds.length === 1 ? conds[0] : `(${conds.join(' OR ')})`;\n const sql = param.modifier === 'not' ? `NOT (${inner})` : inner;\n return { sql, values: vals };\n }\n\n const resolvedValues = param.values.map(v => v.startsWith('|') ? v.slice(1) : v);\n\n if (param.modifier === 'not') {\n if (resolvedValues.length === 1) {\n return { sql: `NOT EXISTS (SELECT 1 FROM json_each(${textCol}) WHERE json_each.value = ?)`, values: [resolvedValues[0]] };\n }\n const placeholders = resolvedValues.map(() => '?').join(', ');\n return { sql: `NOT EXISTS (SELECT 1 FROM json_each(${textCol}) WHERE json_each.value IN (${placeholders}))`, values: [...resolvedValues] };\n }\n\n // Default: any value matches\n if (resolvedValues.length === 1) {\n return { sql: `EXISTS (SELECT 1 FROM json_each(${textCol}) WHERE json_each.value = ?)`, values: [resolvedValues[0]] };\n }\n const placeholders = resolvedValues.map(() => '?').join(', ');\n return { sql: `EXISTS (SELECT 1 FROM json_each(${textCol}) WHERE json_each.value IN (${placeholders}))`, values: [...resolvedValues] };\n}\n\n// -- v2 default --\nfunction buildDefaultFragmentV2(\n impl: SearchParameterImpl,\n param: ParsedSearchParam,\n): WhereFragment {\n const col = quoteColumn(impl.columnName);\n const op = prefixToOperator(param.prefix);\n return buildOrFragmentV2(col, op, param.values);\n}\n\n// -- v2 shared helpers --\nfunction buildOrFragmentV2(col: string, op: string, values: string[]): WhereFragment {\n return buildOrFragmentV2Raw(col, op, values);\n}\n\nfunction buildOrFragmentV2Raw(col: string, op: string, values: unknown[]): WhereFragment {\n if (values.length === 1) {\n return { sql: `${col} ${op} ?`, values: [values[0]] };\n }\n const conds = values.map(() => `${col} ${op} ?`);\n return { sql: `(${conds.join(' OR ')})`, values: [...values] };\n}\n\nfunction buildLikeFragmentV2(col: string, values: string[], prefix: string, suffix: string): WhereFragment {\n if (values.length === 1) {\n const escaped = escapeLikeString(values[0]).toLowerCase();\n return { sql: `LOWER(${col}) LIKE ?`, values: [`${prefix}${escaped}${suffix}`] };\n }\n const conds: string[] = [];\n const vals: unknown[] = [];\n for (const v of values) {\n conds.push(`LOWER(${col}) LIKE ?`);\n vals.push(`${prefix}${escapeLikeString(v).toLowerCase()}${suffix}`);\n }\n return { sql: `(${conds.join(' OR ')})`, values: vals };\n}\n\n/**\n * v2: Build a WHERE fragment for chained search using ? placeholders.\n *\n * Chained search: `subject:Patient.name=Smith`\n * Generated SQL (SQLite):\n * ```sql\n * EXISTS (\n * SELECT 1 FROM \"Observation_References\" __ref\n * JOIN \"Patient\" __target ON __ref.\"targetId\" = __target.\"id\"\n * WHERE __ref.\"resourceId\" = \"Observation\".\"id\"\n * AND __ref.\"code\" = ?\n * AND __target.\"deleted\" = 0\n * AND <target param condition>\n * )\n * ```\n */\nfunction buildChainedFragmentV2(\n param: ParsedSearchParam,\n chain: ChainedSearchTarget,\n registry: SearchParameterRegistry,\n sourceResourceType: string,\n): WhereFragment | null {\n // Resolve the target param implementation on the TARGET resource type\n const targetImpl = resolveImplV2(\n { code: chain.targetParam, values: param.values, modifier: param.modifier, prefix: param.prefix },\n registry,\n chain.targetType,\n );\n if (!targetImpl) return null;\n\n // Build the inner WHERE condition for the target table\n const innerParam: ParsedSearchParam = {\n code: chain.targetParam,\n values: param.values,\n modifier: param.modifier,\n prefix: param.prefix,\n };\n\n const innerFragment = buildWhereFragmentV2(targetImpl, innerParam);\n if (!innerFragment) return null;\n\n // Rewrite the inner SQL to prefix column names with __target.\n const innerSql = rewriteColumnRefsForAlias(innerFragment.sql, '__target');\n\n const refTable = `${sourceResourceType}_References`;\n const sql = [\n `EXISTS (`,\n ` SELECT 1 FROM \"${refTable}\" __ref`,\n ` JOIN \"${chain.targetType}\" __target ON __ref.\"targetId\" = __target.\"id\"`,\n ` WHERE __ref.\"resourceId\" = \"${sourceResourceType}\".\"id\"`,\n ` AND __ref.\"code\" = ?`,\n ` AND __ref.\"targetType\" = ?`,\n ` AND __target.\"deleted\" = 0`,\n ` AND ${innerSql}`,\n `)`,\n ].join('\\n');\n\n return { sql, values: [param.code, chain.targetType, ...innerFragment.values] };\n}\n\n/**\n * v2: Build a complete WHERE clause from parsed search params using ? placeholders.\n */\nexport function buildWhereClauseV2(\n params: ParsedSearchParam[],\n registry: SearchParameterRegistry,\n resourceType: string,\n): WhereFragment | null {\n const fragments: WhereFragment[] = [];\n\n for (const param of params) {\n // Handle chained search parameters (subject:Patient.name=Smith)\n if (param.chain) {\n const fragment = buildChainedFragmentV2(param, param.chain, registry, resourceType);\n if (fragment) {\n fragments.push(fragment);\n }\n continue;\n }\n\n const impl = resolveImplV2(param, registry, resourceType);\n if (!impl) continue;\n\n const fragment = buildWhereFragmentV2(impl, param);\n if (fragment) {\n fragments.push(fragment);\n }\n }\n\n if (fragments.length === 0) return null;\n\n const sql = fragments.map(f => f.sql).join(' AND ');\n const values = fragments.flatMap(f => f.values);\n return { sql, values };\n}\n\n/**\n * v2: Resolve a SearchParameterImpl for special + registry params.\n */\nfunction resolveImplV2(\n param: ParsedSearchParam,\n registry: SearchParameterRegistry,\n resourceType: string,\n): SearchParameterImpl | null {\n switch (param.code) {\n case '_id':\n return { code: '_id', type: 'uri', resourceTypes: [resourceType], expression: 'id', strategy: 'column', columnName: 'id', columnType: 'TEXT', array: false };\n case '_lastUpdated':\n return { code: '_lastUpdated', type: 'date', resourceTypes: [resourceType], expression: 'meta.lastUpdated', strategy: 'column', columnName: 'lastUpdated', columnType: 'TEXT', array: false };\n case '_tag':\n return { code: '_tag', type: 'token', resourceTypes: [resourceType], expression: 'meta.tag', strategy: 'token-column', columnName: '_tag', columnType: 'TEXT', array: true };\n case '_security':\n return { code: '_security', type: 'token', resourceTypes: [resourceType], expression: 'meta.security', strategy: 'token-column', columnName: '_security', columnType: 'TEXT', array: true };\n case '_profile':\n return { code: '_profile', type: 'uri', resourceTypes: [resourceType], expression: 'meta.profile', strategy: 'column', columnName: '_profile', columnType: 'TEXT', array: true };\n case '_source':\n return { code: '_source', type: 'uri', resourceTypes: [resourceType], expression: 'meta.source', strategy: 'column', columnName: '_source', columnType: 'TEXT', array: false };\n default:\n return registry.getImpl(resourceType, param.code) ?? null;\n }\n}\n", "/**\n * Search SQL Builder\n *\n * Composes a full SELECT statement from a parsed SearchRequest,\n * combining WHERE clauses, ORDER BY, and LIMIT/OFFSET.\n *\n * ## Generated SQL Shape\n *\n * ```sql\n * SELECT \"id\", \"content\", \"lastUpdated\", \"deleted\"\n * FROM \"Patient\"\n * WHERE \"deleted\" = false\n * AND \"gender\" = $1\n * AND \"birthdate\" >= $2\n * ORDER BY \"lastUpdated\" DESC\n * LIMIT $3\n * OFFSET $4\n * ```\n *\n * @module fhir-persistence/search\n */\n\nimport type { SearchParameterRegistry } from '../registry/search-parameter-registry.js';\nimport type { SearchRequest, SearchSQL, CountSQL, SortRule } from './types.js';\nimport { DEFAULT_SEARCH_COUNT } from './types.js';\nimport { buildWhereClause } from './where-builder.js';\n\n// =============================================================================\n// Section 1: Select Columns\n// =============================================================================\n\n/**\n * Default columns returned by search queries.\n */\nconst SEARCH_COLUMNS = ['\"id\"', '\"content\"', '\"lastUpdated\"', '\"deleted\"'].join(', ');\n\n// =============================================================================\n// Section 2: Main Builder\n// =============================================================================\n\n/**\n * Build a complete search SQL query from a parsed SearchRequest.\n *\n * @param request - The parsed search request.\n * @param registry - The SearchParameterRegistry for resolving parameter implementations.\n * @returns A SearchSQL with the full query and parameter values.\n */\nexport function buildSearchSQL(\n request: SearchRequest,\n registry: SearchParameterRegistry,\n): SearchSQL {\n const tableName = quoteTable(request.resourceType);\n const parts: string[] = [];\n const allValues: unknown[] = [];\n let paramIndex = 1;\n\n // SELECT\n parts.push(`SELECT ${SEARCH_COLUMNS}`);\n parts.push(`FROM ${tableName}`);\n\n // WHERE\n const whereConditions: string[] = [];\n\n // Always filter out deleted resources\n whereConditions.push('\"deleted\" = false');\n\n // Add project filter for multi-tenant scoping\n if (request.project) {\n whereConditions.push(`\"projectId\" = $${paramIndex}`);\n allValues.push(request.project);\n paramIndex++;\n }\n\n // Add compartment filter if present\n if (request.compartment) {\n whereConditions.push(`\"compartments\" @> ARRAY[$${paramIndex}]::uuid[]`);\n allValues.push(request.compartment.id);\n paramIndex++;\n }\n\n // Add search parameter conditions\n if (request.params.length > 0) {\n const whereFragment = buildWhereClause(request.params, registry, request.resourceType);\n if (whereFragment) {\n // Reindex parameters to account for the offset\n const reindexedSql = reindexParams(whereFragment.sql, whereFragment.values.length, paramIndex);\n whereConditions.push(reindexedSql);\n allValues.push(...whereFragment.values);\n paramIndex += whereFragment.values.length;\n }\n }\n\n parts.push(`WHERE ${whereConditions.join(' AND ')}`);\n\n // ORDER BY\n const orderBy = buildOrderBy(request.sort, registry, request.resourceType);\n parts.push(`ORDER BY ${orderBy}`);\n\n // LIMIT\n const count = request.count ?? DEFAULT_SEARCH_COUNT;\n parts.push(`LIMIT $${paramIndex}`);\n allValues.push(count);\n paramIndex++;\n\n // OFFSET\n if (request.offset !== undefined && request.offset > 0) {\n parts.push(`OFFSET $${paramIndex}`);\n allValues.push(request.offset);\n paramIndex++;\n }\n\n return {\n sql: parts.join('\\n'),\n values: allValues,\n };\n}\n\n// =============================================================================\n// Section 3: Count Builder\n// =============================================================================\n\n/**\n * Build a COUNT query for a search request (for _total=accurate).\n *\n * @param request - The parsed search request.\n * @param registry - The SearchParameterRegistry.\n * @returns A CountSQL with the count query and parameter values.\n */\nexport function buildCountSQL(\n request: SearchRequest,\n registry: SearchParameterRegistry,\n): CountSQL {\n const tableName = quoteTable(request.resourceType);\n const parts: string[] = [];\n const allValues: unknown[] = [];\n let paramIndex = 1;\n\n parts.push(`SELECT COUNT(*) AS \"count\"`);\n parts.push(`FROM ${tableName}`);\n\n const whereConditions: string[] = [];\n whereConditions.push('\"deleted\" = false');\n\n // Add project filter for multi-tenant scoping\n if (request.project) {\n whereConditions.push(`\"projectId\" = $${paramIndex}`);\n allValues.push(request.project);\n paramIndex++;\n }\n\n // Add compartment filter if present\n if (request.compartment) {\n whereConditions.push(`\"compartments\" @> ARRAY[$${paramIndex}]::uuid[]`);\n allValues.push(request.compartment.id);\n paramIndex++;\n }\n\n if (request.params.length > 0) {\n const whereFragment = buildWhereClause(request.params, registry, request.resourceType);\n if (whereFragment) {\n const reindexedSql = reindexParams(whereFragment.sql, whereFragment.values.length, paramIndex);\n whereConditions.push(reindexedSql);\n allValues.push(...whereFragment.values);\n paramIndex += whereFragment.values.length;\n }\n }\n\n parts.push(`WHERE ${whereConditions.join(' AND ')}`);\n\n return {\n sql: parts.join('\\n'),\n values: allValues,\n };\n}\n\n// =============================================================================\n// Section 4: ORDER BY Builder\n// =============================================================================\n\n/**\n * Build an ORDER BY clause from sort rules.\n *\n * Default: `ORDER BY \"lastUpdated\" DESC`.\n */\nfunction buildOrderBy(\n sort: SortRule[] | undefined,\n registry: SearchParameterRegistry,\n resourceType: string,\n): string {\n if (!sort || sort.length === 0) {\n return '\"lastUpdated\" DESC';\n }\n\n const clauses: string[] = [];\n\n for (const rule of sort) {\n const columnName = resolveOrderByColumn(rule.code, registry, resourceType);\n if (columnName) {\n const direction = rule.descending ? 'DESC' : 'ASC';\n clauses.push(`\"${columnName}\" ${direction}`);\n }\n }\n\n if (clauses.length === 0) {\n return '\"lastUpdated\" DESC';\n }\n\n return clauses.join(', ');\n}\n\n/**\n * Resolve a sort parameter code to a column name.\n */\nfunction resolveOrderByColumn(\n code: string,\n registry: SearchParameterRegistry,\n resourceType: string,\n): string | null {\n // Special parameters\n switch (code) {\n case '_id':\n return 'id';\n case '_lastUpdated':\n return 'lastUpdated';\n }\n\n // Look up in registry\n const impl = registry.getImpl(resourceType, code);\n if (!impl) {\n return null;\n }\n\n // Column strategy: use the column name directly\n if (impl.strategy === 'column') {\n return impl.columnName;\n }\n\n // Token-column and lookup-table strategies: use the __XSort column\n if (impl.strategy === 'token-column' || impl.strategy === 'lookup-table') {\n return `__${impl.columnName}Sort`;\n }\n\n return null;\n}\n\n// =============================================================================\n// Section 5: Helpers\n// =============================================================================\n\n/**\n * Double-quote a table name for safe SQL usage.\n */\nfunction quoteTable(name: string): string {\n return `\"${name}\"`;\n}\n\n/**\n * Re-index parameter placeholders from $1-based to $startIndex-based.\n *\n * The WHERE builder always starts at $1. When composing into a larger\n * query, we need to shift the indices.\n */\nfunction reindexParams(sql: string, paramCount: number, startIndex: number): string {\n if (startIndex === 1) {\n return sql; // No reindexing needed\n }\n\n // Replace $N with $(N + offset), working from highest to lowest to avoid double-replacement\n let result = sql;\n const offset = startIndex - 1;\n\n for (let i = paramCount; i >= 1; i--) {\n result = result.replace(new RegExp(`\\\\$${i}(?!\\\\d)`, 'g'), `$${i + offset}`);\n }\n\n return result;\n}\n\n// =============================================================================\n// Section 6: v2 Search SQL Builder (SQLite ? placeholders, no projectId)\n// =============================================================================\n\nimport { buildWhereClauseV2 } from './where-builder.js';\n\n/**\n * v2: Default columns returned by search queries.\n * Includes versionId (for ETag), no projectId.\n */\nconst SEARCH_COLUMNS_V2 = ['\"id\"', '\"versionId\"', '\"content\"', '\"lastUpdated\"', '\"deleted\"'].join(', ');\n\n/**\n * v2: Build a complete search SQL query using ? placeholders.\n * No projectId filter. deleted = 0 (INTEGER).\n */\nexport function buildSearchSQLv2(\n request: SearchRequest,\n registry: SearchParameterRegistry,\n): SearchSQL {\n const tableName = quoteTable(request.resourceType);\n const parts: string[] = [];\n const allValues: unknown[] = [];\n\n parts.push(`SELECT ${SEARCH_COLUMNS_V2}`);\n parts.push(`FROM ${tableName}`);\n\n const whereConditions: string[] = [];\n whereConditions.push('\"deleted\" = 0');\n\n // Compartment filter (v2: json_each)\n if (request.compartment) {\n whereConditions.push('EXISTS (SELECT 1 FROM json_each(\"compartments\") WHERE json_each.value = ?)');\n allValues.push(request.compartment.id);\n }\n\n // Search parameter conditions\n if (request.params.length > 0) {\n const whereFragment = buildWhereClauseV2(request.params, registry, request.resourceType);\n if (whereFragment) {\n whereConditions.push(whereFragment.sql);\n allValues.push(...whereFragment.values);\n }\n }\n\n parts.push(`WHERE ${whereConditions.join(' AND ')}`);\n\n // ORDER BY\n const orderBy = buildOrderByV2(request.sort, registry, request.resourceType);\n parts.push(`ORDER BY ${orderBy}`);\n\n // LIMIT\n const count = request.count ?? DEFAULT_SEARCH_COUNT;\n parts.push('LIMIT ?');\n allValues.push(count);\n\n // OFFSET\n if (request.offset !== undefined && request.offset > 0) {\n parts.push('OFFSET ?');\n allValues.push(request.offset);\n }\n\n return { sql: parts.join('\\n'), values: allValues };\n}\n\n/**\n * v2: Build a COUNT query using ? placeholders.\n */\nexport function buildCountSQLv2(\n request: SearchRequest,\n registry: SearchParameterRegistry,\n): CountSQL {\n const tableName = quoteTable(request.resourceType);\n const parts: string[] = [];\n const allValues: unknown[] = [];\n\n parts.push('SELECT COUNT(*) AS \"count\"');\n parts.push(`FROM ${tableName}`);\n\n const whereConditions: string[] = [];\n whereConditions.push('\"deleted\" = 0');\n\n if (request.compartment) {\n whereConditions.push('EXISTS (SELECT 1 FROM json_each(\"compartments\") WHERE json_each.value = ?)');\n allValues.push(request.compartment.id);\n }\n\n if (request.params.length > 0) {\n const whereFragment = buildWhereClauseV2(request.params, registry, request.resourceType);\n if (whereFragment) {\n whereConditions.push(whereFragment.sql);\n allValues.push(...whereFragment.values);\n }\n }\n\n parts.push(`WHERE ${whereConditions.join(' AND ')}`);\n return { sql: parts.join('\\n'), values: allValues };\n}\n\n/**\n * v2: Build ORDER BY clause.\n */\nfunction buildOrderByV2(\n sort: SortRule[] | undefined,\n registry: SearchParameterRegistry,\n resourceType: string,\n): string {\n if (!sort || sort.length === 0) {\n return '\"lastUpdated\" DESC';\n }\n const clauses: string[] = [];\n for (const rule of sort) {\n const col = resolveOrderByColumn(rule.code, registry, resourceType);\n if (col) {\n clauses.push(`\"${col}\" ${rule.descending ? 'DESC' : 'ASC'}`);\n }\n }\n return clauses.length > 0 ? clauses.join(', ') : '\"lastUpdated\" DESC';\n}\n\n// =============================================================================\n// Section 7: v2 Two-Phase SQL Builder\n// =============================================================================\n\n/**\n * Result of a two-phase search SQL build.\n */\nexport interface TwoPhaseSearchSQL {\n /** Phase 1: SELECT id with full WHERE + ORDER BY + LIMIT/OFFSET. */\n phase1: SearchSQL;\n /** Phase 2: SELECT content WHERE id IN (?,...). Values are id strings from Phase 1 results. */\n phase2Template: string;\n}\n\n/**\n * v2: Build two-phase search SQL for improved performance on large tables.\n *\n * ## Strategy\n *\n * **Phase 1** \u2014 Lightweight id-only query with all filters, sorting, and pagination.\n * Only reads the indexed columns, avoiding expensive content deserialization.\n *\n * ```sql\n * SELECT \"id\" FROM \"Patient\"\n * WHERE \"deleted\" = 0 AND \"birthdate\" >= ?\n * ORDER BY \"lastUpdated\" DESC\n * LIMIT ?\n * ```\n *\n * **Phase 2** \u2014 Fetch full content for matched ids (executed by caller).\n *\n * ```sql\n * SELECT \"id\", \"versionId\", \"content\", \"lastUpdated\", \"deleted\"\n * FROM \"Patient\"\n * WHERE \"id\" IN (?, ?, ?)\n * ```\n *\n * @param request - The parsed search request.\n * @param registry - The SearchParameterRegistry.\n * @returns TwoPhaseSearchSQL with phase1 query and phase2 template.\n */\nexport function buildTwoPhaseSearchSQLv2(\n request: SearchRequest,\n registry: SearchParameterRegistry,\n): TwoPhaseSearchSQL {\n const tableName = quoteTable(request.resourceType);\n\n // --- Phase 1: id-only query ---\n const p1Parts: string[] = [];\n const p1Values: unknown[] = [];\n\n p1Parts.push(`SELECT \"id\"`);\n p1Parts.push(`FROM ${tableName}`);\n\n const whereConditions: string[] = [];\n whereConditions.push('\"deleted\" = 0');\n\n if (request.compartment) {\n whereConditions.push('EXISTS (SELECT 1 FROM json_each(\"compartments\") WHERE json_each.value = ?)');\n p1Values.push(request.compartment.id);\n }\n\n if (request.params.length > 0) {\n const whereFragment = buildWhereClauseV2(request.params, registry, request.resourceType);\n if (whereFragment) {\n whereConditions.push(whereFragment.sql);\n p1Values.push(...whereFragment.values);\n }\n }\n\n p1Parts.push(`WHERE ${whereConditions.join(' AND ')}`);\n\n const orderBy = buildOrderByV2(request.sort, registry, request.resourceType);\n p1Parts.push(`ORDER BY ${orderBy}`);\n\n const count = request.count ?? DEFAULT_SEARCH_COUNT;\n p1Parts.push('LIMIT ?');\n p1Values.push(count);\n\n if (request.offset !== undefined && request.offset > 0) {\n p1Parts.push('OFFSET ?');\n p1Values.push(request.offset);\n }\n\n const phase1: SearchSQL = {\n sql: p1Parts.join('\\n'),\n values: p1Values,\n };\n\n // --- Phase 2 template: fetch content by ids ---\n const phase2Template = [\n `SELECT ${SEARCH_COLUMNS_V2}`,\n `FROM ${tableName}`,\n `WHERE \"id\" IN (%PLACEHOLDERS%)`,\n ].join('\\n');\n\n return { phase1, phase2Template };\n}\n", "/**\n * SearchSet Bundle Builder\n *\n * Constructs FHIR R4 Bundle of type `searchset` from search results.\n * Pure function \u2014 no database dependency.\n *\n * FHIR R4 Search Bundle spec:\n * - `Bundle.type` = `\"searchset\"`\n * - Each entry has `search.mode` = `\"match\"`\n * - `Bundle.total` is optional (only when `_total=accurate`)\n * - `Bundle.link` includes `self` and optionally `next`\n *\n * @module fhir-persistence/search\n */\n\nimport { randomUUID } from 'node:crypto';\nimport type { PersistedResource } from '../repo/types.js';\nimport type { BundleLink } from '../repo/history-bundle.js';\n\n// =============================================================================\n// Section 1: Types\n// =============================================================================\n\n/**\n * A FHIR R4 Bundle of type `searchset`.\n */\nexport interface SearchBundle {\n resourceType: 'Bundle';\n id: string;\n type: 'searchset';\n total?: number;\n link?: BundleLink[];\n entry?: SearchBundleEntry[];\n}\n\n/**\n * A single entry in a searchset Bundle.\n */\nexport interface SearchBundleEntry {\n fullUrl?: string;\n resource: Record<string, unknown>;\n search: {\n mode: 'match' | 'include' | 'outcome';\n };\n}\n\n/**\n * Options for building a searchset Bundle.\n */\nexport interface BuildSearchBundleOptions {\n /** Base URL for fullUrl construction (e.g., `\"http://localhost:3000/fhir/R4\"`). */\n baseUrl?: string;\n /** Total count of matching resources (only included when `_total=accurate`). */\n total?: number;\n /** Self link URL. */\n selfUrl?: string;\n /** Next page link URL. */\n nextUrl?: string;\n /** Included resources from _include/_revinclude. */\n included?: PersistedResource[];\n}\n\n// =============================================================================\n// Section 2: Bundle Construction\n// =============================================================================\n\n/**\n * Build a FHIR R4 searchset Bundle from PersistedResource[].\n *\n * @param resources - Matched resources.\n * @param options - Optional bundle metadata.\n * @returns A FHIR R4 Bundle of type `searchset`.\n */\nexport function buildSearchBundle(\n resources: PersistedResource[],\n options?: BuildSearchBundleOptions,\n): SearchBundle {\n const bundle: SearchBundle = {\n resourceType: 'Bundle',\n id: randomUUID(),\n type: 'searchset',\n };\n\n // Total (only when explicitly provided)\n if (options?.total !== undefined) {\n bundle.total = options.total;\n }\n\n // Links\n const links: BundleLink[] = [];\n if (options?.selfUrl) {\n links.push({ relation: 'self', url: options.selfUrl });\n }\n if (options?.nextUrl) {\n links.push({ relation: 'next', url: options.nextUrl });\n }\n if (links.length > 0) {\n bundle.link = links;\n }\n\n // Entries\n const entries: SearchBundleEntry[] = [];\n\n // Primary match entries\n for (const resource of resources) {\n entries.push(toSearchEntry(resource, 'match', options?.baseUrl));\n }\n\n // Included entries (_include / _revinclude)\n if (options?.included && options.included.length > 0) {\n for (const resource of options.included) {\n entries.push(toSearchEntry(resource, 'include', options?.baseUrl));\n }\n }\n\n if (entries.length > 0) {\n bundle.entry = entries;\n }\n\n return bundle;\n}\n\n// =============================================================================\n// Section 3: Entry Construction\n// =============================================================================\n\n/**\n * Convert a PersistedResource to a SearchBundleEntry.\n */\nfunction toSearchEntry(\n resource: PersistedResource,\n mode: 'match' | 'include' | 'outcome',\n baseUrl?: string,\n): SearchBundleEntry {\n const entry: SearchBundleEntry = {\n resource: resource as unknown as Record<string, unknown>,\n search: {\n mode,\n },\n };\n\n if (baseUrl) {\n entry.fullUrl = `${baseUrl}/${resource.resourceType}/${resource.id}`;\n }\n\n return entry;\n}\n", "/**\n * Pagination Helpers\n *\n * Build pagination URLs for FHIR search Bundle links.\n * Pure functions \u2014 no database dependency.\n *\n * FHIR R4 Pagination spec:\n * - `Bundle.link` with `relation: \"self\"` \u2014 current page URL\n * - `Bundle.link` with `relation: \"next\"` \u2014 next page URL (if more results)\n * - Offset-based pagination using `_offset` and `_count`\n *\n * @module fhir-persistence/search\n */\n\nimport { DEFAULT_SEARCH_COUNT } from './types.js';\n\n// =============================================================================\n// Section 1: Types\n// =============================================================================\n\n/**\n * Context for building pagination links.\n */\nexport interface PaginationContext {\n /** Base URL of the FHIR server (e.g., `\"http://localhost:3000/fhir/R4\"`). */\n baseUrl: string;\n /** The FHIR resource type being searched. */\n resourceType: string;\n /** Original query parameters (excluding `_offset`). */\n queryParams: Record<string, string | string[]>;\n /** Page size (`_count`). */\n count: number;\n /** Current offset (`_offset`). */\n offset: number;\n /** Number of results returned on the current page. */\n resultCount: number;\n}\n\n// =============================================================================\n// Section 2: Link Builders\n// =============================================================================\n\n/**\n * Build the `self` link URL for the current search page.\n */\nexport function buildSelfLink(ctx: PaginationContext): string {\n const params = new URLSearchParams();\n\n // Add all original query params\n for (const [key, value] of Object.entries(ctx.queryParams)) {\n if (key === '_offset') continue; // We'll add offset explicitly\n if (Array.isArray(value)) {\n for (const v of value) {\n params.append(key, v);\n }\n } else {\n params.append(key, value);\n }\n }\n\n // Add offset if non-zero\n if (ctx.offset > 0) {\n params.set('_offset', String(ctx.offset));\n }\n\n const qs = params.toString();\n return qs\n ? `${ctx.baseUrl}/${ctx.resourceType}?${qs}`\n : `${ctx.baseUrl}/${ctx.resourceType}`;\n}\n\n/**\n * Build the `next` link URL, or `undefined` if there is no next page.\n *\n * A next page exists when the current page returned exactly `count` results,\n * indicating there may be more.\n */\nexport function buildNextLink(ctx: PaginationContext): string | undefined {\n if (!hasNextPage(ctx)) {\n return undefined;\n }\n\n const nextOffset = ctx.offset + ctx.count;\n const params = new URLSearchParams();\n\n for (const [key, value] of Object.entries(ctx.queryParams)) {\n if (key === '_offset') continue;\n if (Array.isArray(value)) {\n for (const v of value) {\n params.append(key, v);\n }\n } else {\n params.append(key, value);\n }\n }\n\n params.set('_offset', String(nextOffset));\n\n return `${ctx.baseUrl}/${ctx.resourceType}?${params.toString()}`;\n}\n\n/**\n * Determine whether there is a next page of results.\n *\n * Returns `true` when the current page is full (resultCount === count),\n * indicating there may be more results.\n */\nexport function hasNextPage(ctx: PaginationContext): boolean {\n if (ctx.count <= 0) return false;\n return ctx.resultCount >= ctx.count;\n}\n\n/**\n * Build a pagination context from search request parameters.\n */\nexport function buildPaginationContext(\n baseUrl: string,\n resourceType: string,\n queryParams: Record<string, string | string[]>,\n count: number | undefined,\n offset: number | undefined,\n resultCount: number,\n): PaginationContext {\n return {\n baseUrl,\n resourceType,\n queryParams,\n count: count ?? DEFAULT_SEARCH_COUNT,\n offset: offset ?? 0,\n resultCount,\n };\n}\n", "/**\n * Search Executor (v2)\n *\n * Executes FHIR search queries using StorageAdapter and returns results.\n * Supports _include, _revinclude, and _include:iterate.\n *\n * @module fhir-persistence/search\n */\n\nimport type { PersistedResource } from '../repo/types.js';\nimport type { SearchParameterRegistry } from '../registry/search-parameter-registry.js';\nimport type { SearchRequest, IncludeTarget } from './types.js';\nimport type { StorageAdapter } from '../db/adapter.js';\nimport { buildSearchSQLv2, buildCountSQLv2 } from './search-sql-builder.js';\n\n// =============================================================================\n// Section 1: Types\n// =============================================================================\n\n/**\n * Options for search execution.\n */\nexport interface SearchOptions {\n /** Whether to include total count. */\n total?: 'none' | 'estimate' | 'accurate';\n}\n\n/**\n * Result of a search execution.\n */\nexport interface SearchResult {\n /** Matched resources. */\n resources: PersistedResource[];\n /** Included resources from _include/_revinclude (search.mode = 'include'). */\n included?: PersistedResource[];\n /** Total count (only when `total=accurate`). */\n total?: number;\n}\n\n/**\n * v2: Raw row shape returned by search SQL.\n * Uses deleted: number (0/1) instead of boolean.\n */\ninterface SearchRowV2 {\n id: string;\n versionId: string;\n content: string;\n deleted: number;\n lastUpdated: string;\n [key: string]: unknown;\n}\n\n/**\n * v2: Execute a FHIR search query using StorageAdapter.\n *\n * Key differences from v1:\n * - Uses `StorageAdapter` instead of `DatabaseClient`\n * - Uses `?` placeholders (SQLite)\n * - `deleted` is number (0/1), not boolean\n * - No `_include` / `_revinclude` in this MVP (can be added)\n */\nexport async function executeSearchV2(\n adapter: StorageAdapter,\n request: SearchRequest,\n registry: SearchParameterRegistry,\n options?: SearchOptions,\n): Promise<SearchResult> {\n // 1. Build and execute search SQL\n const searchSQL = buildSearchSQLv2(request, registry);\n const rows = await adapter.query<SearchRowV2>(searchSQL.sql, searchSQL.values);\n\n // 2. Map rows to PersistedResource[]\n const resources = mapRowsToResourcesV2(rows);\n\n // 3. Optionally get total count\n let total: number | undefined;\n if (options?.total === 'accurate') {\n const countSQL = buildCountSQLv2(request, registry);\n const countRow = await adapter.queryOne<{ count: number }>(countSQL.sql, countSQL.values);\n total = countRow?.count ?? 0;\n }\n\n // 4. Execute _include and _revinclude (v2 using StorageAdapter)\n const allIncluded: PersistedResource[] = [];\n\n if (request.include && request.include.length > 0) {\n const included = await executeIncludeV2(adapter, resources, request.include, registry);\n allIncluded.push(...included);\n }\n\n if (request.revinclude && request.revinclude.length > 0) {\n const revincluded = await executeRevincludeV2(adapter, resources, request.revinclude);\n allIncluded.push(...revincluded);\n }\n\n const result: SearchResult = { resources, total };\n if (allIncluded.length > 0) {\n result.included = allIncluded;\n }\n\n return result;\n}\n\n/**\n * v2: Map rows with deleted:number to PersistedResource[].\n */\nexport function mapRowsToResourcesV2(rows: SearchRowV2[]): PersistedResource[] {\n const resources: PersistedResource[] = [];\n for (const row of rows) {\n if (row.deleted === 1) continue;\n if (!row.content) continue;\n try {\n resources.push(JSON.parse(row.content) as PersistedResource);\n } catch {\n // Skip invalid JSON\n }\n }\n return resources;\n}\n\n// =============================================================================\n// Section 5: v2 Include / Revinclude (StorageAdapter)\n// =============================================================================\n\n/** Maximum recursion depth for _include:iterate (ADR limit). */\nconst MAX_INCLUDE_ITERATE_DEPTH = 3;\n\n/** Maximum total included resources (safety cap). */\nconst MAX_INCLUDE_RESOURCES = 1000;\n\n/**\n * v2: Execute _include using StorageAdapter with ? placeholders.\n * Supports _include:iterate for recursive include resolution.\n */\nasync function executeIncludeV2(\n adapter: StorageAdapter,\n primaryResults: PersistedResource[],\n includes: IncludeTarget[],\n registry: SearchParameterRegistry,\n): Promise<PersistedResource[]> {\n if (primaryResults.length === 0 || includes.length === 0) return [];\n\n const seen = new Set(primaryResults.map(r => `${r.resourceType}/${r.id}`));\n const allIncluded: PersistedResource[] = [];\n\n // Separate iterate vs non-iterate includes\n const nonIterateIncludes = includes.filter(i => !i.iterate);\n const iterateIncludes = includes.filter(i => i.iterate);\n\n // Phase 1: Non-iterate includes (single pass)\n const firstPassResults = await resolveIncludesOnce(\n adapter, primaryResults, nonIterateIncludes, registry, seen, allIncluded,\n );\n\n // Phase 2: Iterate includes (recursive, up to MAX_INCLUDE_ITERATE_DEPTH)\n if (iterateIncludes.length > 0) {\n // Start with primary + first-pass results as the source pool\n let currentSources: PersistedResource[] = [...primaryResults, ...firstPassResults];\n\n for (let depth = 0; depth < MAX_INCLUDE_ITERATE_DEPTH; depth++) {\n if (allIncluded.length >= MAX_INCLUDE_RESOURCES) break;\n\n const newlyIncluded = await resolveIncludesOnce(\n adapter, currentSources, iterateIncludes, registry, seen, allIncluded,\n );\n\n if (newlyIncluded.length === 0) break; // No new resources found \u2014 stop\n currentSources = newlyIncluded; // Next iteration uses newly included as sources\n }\n }\n\n return allIncluded;\n}\n\n/**\n * Single pass of include resolution. Returns newly included resources.\n */\nasync function resolveIncludesOnce(\n adapter: StorageAdapter,\n sourceResources: PersistedResource[],\n includes: IncludeTarget[],\n registry: SearchParameterRegistry,\n seen: Set<string>,\n allIncluded: PersistedResource[],\n): Promise<PersistedResource[]> {\n const newlyIncluded: PersistedResource[] = [];\n\n for (const include of includes) {\n if (allIncluded.length >= MAX_INCLUDE_RESOURCES) break;\n\n if (include.wildcard) {\n for (const resource of sourceResources) {\n if (allIncluded.length >= MAX_INCLUDE_RESOURCES) break;\n const refs = extractAllRefsFromResource(resource);\n for (const ref of refs) {\n if (allIncluded.length >= MAX_INCLUDE_RESOURCES) break;\n const key = `${ref.resourceType}/${ref.id}`;\n if (seen.has(key)) continue;\n try {\n const row = await adapter.queryOne<{ content: string; deleted: number }>(\n `SELECT \"content\", \"deleted\" FROM \"${ref.resourceType}\" WHERE \"id\" = ? AND \"deleted\" = 0`,\n [ref.id],\n );\n if (row) {\n const res = JSON.parse(row.content) as PersistedResource;\n seen.add(key);\n allIncluded.push(res);\n newlyIncluded.push(res);\n }\n } catch {\n // Table may not exist\n }\n }\n }\n continue;\n }\n\n const impl = registry.getImpl(include.resourceType, include.searchParam);\n if (!impl || impl.type !== 'reference') continue;\n\n const matchingResources = sourceResources.filter(r => r.resourceType === include.resourceType);\n for (const resource of matchingResources) {\n if (allIncluded.length >= MAX_INCLUDE_RESOURCES) break;\n const refs = extractRefsFromField(resource, impl.columnName);\n for (const ref of refs) {\n if (allIncluded.length >= MAX_INCLUDE_RESOURCES) break;\n if (include.targetType && ref.resourceType !== include.targetType) continue;\n const key = `${ref.resourceType}/${ref.id}`;\n if (seen.has(key)) continue;\n try {\n const row = await adapter.queryOne<{ content: string; deleted: number }>(\n `SELECT \"content\", \"deleted\" FROM \"${ref.resourceType}\" WHERE \"id\" = ? AND \"deleted\" = 0`,\n [ref.id],\n );\n if (row) {\n const res = JSON.parse(row.content) as PersistedResource;\n seen.add(key);\n allIncluded.push(res);\n newlyIncluded.push(res);\n }\n } catch {\n // Table may not exist\n }\n }\n }\n }\n\n return newlyIncluded;\n}\n\n/**\n * v2: Execute _revinclude using StorageAdapter with ? placeholders.\n * Uses the References table with targetType column for precise queries.\n */\nasync function executeRevincludeV2(\n adapter: StorageAdapter,\n primaryResults: PersistedResource[],\n revincludes: IncludeTarget[],\n): Promise<PersistedResource[]> {\n if (primaryResults.length === 0 || revincludes.length === 0) return [];\n\n const primaryKeySet = new Set(primaryResults.map(r => `${r.resourceType}/${r.id}`));\n const allIncluded: PersistedResource[] = [];\n const seen = new Set(primaryKeySet);\n\n for (const rev of revincludes) {\n const sourceType = rev.resourceType;\n const refTable = `${sourceType}_References`;\n\n for (const primary of primaryResults) {\n // Use targetType for precise matching (v2 References table has targetType)\n const sql = `SELECT \"resourceId\" FROM \"${refTable}\" WHERE \"targetId\" = ? AND \"code\" = ? AND \"targetType\" = ?`;\n try {\n const rows = await adapter.query<{ resourceId: string }>(sql, [primary.id, rev.searchParam, primary.resourceType]);\n for (const row of rows) {\n const key = `${sourceType}/${row.resourceId}`;\n if (seen.has(key)) continue;\n const resourceRow = await adapter.queryOne<{ content: string; deleted: number }>(\n `SELECT \"content\", \"deleted\" FROM \"${sourceType}\" WHERE \"id\" = ? AND \"deleted\" = 0`,\n [row.resourceId],\n );\n if (resourceRow) {\n const res = JSON.parse(resourceRow.content) as PersistedResource;\n seen.add(key);\n allIncluded.push(res);\n }\n }\n } catch {\n // Table may not exist\n }\n }\n }\n\n return allIncluded;\n}\n\n// -- v2 reference extraction helpers --\n\nfunction extractAllRefsFromResource(resource: PersistedResource): Array<{ resourceType: string; id: string }> {\n const results: Array<{ resourceType: string; id: string }> = [];\n const stack: unknown[] = [resource];\n while (stack.length > 0) {\n const current = stack.pop();\n if (current === null || current === undefined || typeof current !== 'object') continue;\n if (Array.isArray(current)) { for (const item of current) stack.push(item); continue; }\n const record = current as Record<string, unknown>;\n if (typeof record.reference === 'string') {\n const parsed = parseRefV2(record.reference);\n if (parsed) results.push(parsed);\n }\n for (const value of Object.values(record)) {\n if (typeof value === 'object' && value !== null) stack.push(value);\n }\n }\n return results;\n}\n\nfunction extractRefsFromField(resource: PersistedResource, fieldName: string): Array<{ resourceType: string; id: string }> {\n const record = resource as unknown as Record<string, unknown>;\n const value = record[fieldName];\n if (!value) return [];\n const results: Array<{ resourceType: string; id: string }> = [];\n if (Array.isArray(value)) {\n for (const v of value) {\n const ref = extractRefStringV2(v);\n if (ref) { const parsed = parseRefV2(ref); if (parsed) results.push(parsed); }\n }\n } else {\n const ref = extractRefStringV2(value);\n if (ref) { const parsed = parseRefV2(ref); if (parsed) results.push(parsed); }\n }\n return results;\n}\n\nfunction extractRefStringV2(value: unknown): string | null {\n if (typeof value === 'string') return value;\n if (typeof value === 'object' && value !== null) {\n const ref = (value as Record<string, unknown>).reference;\n if (typeof ref === 'string') return ref;\n }\n return null;\n}\n\nfunction parseRefV2(ref: string): { resourceType: string; id: string } | null {\n if (ref.startsWith('#') || ref.startsWith('urn:')) return null;\n const segments = ref.split('/');\n if (segments.length < 2) return null;\n const id = segments[segments.length - 1];\n const resourceType = segments[segments.length - 2];\n if (!id || !resourceType) return null;\n return { resourceType, id };\n}\n", "/**\n * Search Planner\n *\n * Analyzes and optimizes a parsed SearchRequest before SQL generation.\n * Responsibilities:\n *\n * 1. **Filter reordering** \u2014 moves high-selectivity params first\n * (_id > token > reference > date > string > lookup-table)\n * 2. **Chain depth validation** \u2014 rejects chains deeper than maxChainDepth\n * 3. **Index strategy hints** \u2014 annotates whether two-phase SQL is beneficial\n *\n * ## Design Principles\n *\n * - Pure function \u2014 no side effects or database access\n * - Non-destructive \u2014 returns a new SearchRequest, original is unchanged\n * - Graceful degradation \u2014 unknown params are left in place\n *\n * @module fhir-persistence/search\n */\n\nimport type { SearchParameterRegistry } from '../registry/search-parameter-registry.js';\nimport type { SearchParameterImpl } from '../registry/search-parameter-registry.js';\nimport type { ParsedSearchParam, SearchRequest } from './types.js';\n\n// =============================================================================\n// Section 1: Types\n// =============================================================================\n\n/**\n * Search plan produced by the planner.\n */\nexport interface SearchPlan {\n /** The optimized search request (params reordered). */\n request: SearchRequest;\n /** Whether two-phase SQL is recommended for this query. */\n useTwoPhase: boolean;\n /** Whether any chained search params are present. */\n hasChainedSearch: boolean;\n /** Estimated selectivity: 'high' (few results), 'medium', 'low' (many results). */\n estimatedSelectivity: 'high' | 'medium' | 'low';\n /** Warnings produced during planning (e.g., deep chain rejected). */\n warnings: string[];\n}\n\n/**\n * Options for the search planner.\n */\nexport interface SearchPlannerOptions {\n /** Maximum allowed chain depth (default: 1, i.e., single-level chain). */\n maxChainDepth?: number;\n /** Row count threshold above which two-phase SQL is recommended. Default: 10000. */\n twoPhaseThreshold?: number;\n /** Estimated table row count (from stats or hint). Default: 0 (unknown). */\n estimatedRowCount?: number;\n}\n\n// =============================================================================\n// Section 2: Selectivity Priority\n// =============================================================================\n\n/**\n * Priority map for filter reordering.\n * Lower number = higher selectivity = evaluated first.\n */\nfunction getSelectivityPriority(\n param: ParsedSearchParam,\n registry: SearchParameterRegistry,\n resourceType: string,\n): number {\n // _id is the most selective (unique PK)\n if (param.code === '_id') return 0;\n\n // Chained search \u2014 always evaluated last (expensive EXISTS subquery)\n if (param.chain) return 90;\n\n // Resolve impl for strategy-based ordering\n const impl = registry.getImpl(resourceType, param.code);\n if (!impl) return 50; // Unknown \u2192 middle priority\n\n return getStrategyPriority(impl);\n}\n\n/**\n * Map search strategy + type to selectivity priority.\n */\nfunction getStrategyPriority(impl: SearchParameterImpl): number {\n // token-column: high selectivity (system|code matching)\n if (impl.strategy === 'token-column') return 10;\n\n // reference: high selectivity (specific target)\n if (impl.type === 'reference') return 15;\n\n // date: medium-high selectivity (range queries)\n if (impl.type === 'date') return 20;\n\n // number/quantity: medium selectivity\n if (impl.type === 'number' || impl.type === 'quantity') return 25;\n\n // uri: medium selectivity\n if (impl.type === 'uri') return 30;\n\n // string (column strategy): medium-low (prefix match)\n if (impl.strategy === 'column' && impl.type === 'string') return 40;\n\n // lookup-table: low selectivity (expensive JOIN)\n if (impl.strategy === 'lookup-table') return 70;\n\n return 50; // default\n}\n\n// =============================================================================\n// Section 3: Chain Depth Validation\n// =============================================================================\n\n/**\n * Validate chain depth. Currently only single-level chains are supported.\n * Returns warnings for rejected chains.\n */\nfunction validateChainDepth(\n params: ParsedSearchParam[],\n maxDepth: number,\n): { valid: ParsedSearchParam[]; warnings: string[] } {\n const valid: ParsedSearchParam[] = [];\n const warnings: string[] = [];\n\n for (const param of params) {\n if (param.chain) {\n // Currently only depth-1 chains are supported (subject:Patient.name)\n // Future: nested chains like subject:Patient.generalPractitioner:Practitioner.name\n const depth = 1; // Single-level chain = depth 1\n if (depth > maxDepth) {\n warnings.push(\n `Chain search \"${param.code}:${param.chain.targetType}.${param.chain.targetParam}\" rejected: ` +\n `depth ${depth} exceeds max ${maxDepth}`,\n );\n continue;\n }\n }\n valid.push(param);\n }\n\n return { valid, warnings };\n}\n\n// =============================================================================\n// Section 4: Two-Phase SQL Recommendation\n// =============================================================================\n\n/**\n * Determine if two-phase SQL is beneficial.\n *\n * Two-phase SQL:\n * - Phase 1: SELECT id FROM ... WHERE ... ORDER BY ... LIMIT N\n * - Phase 2: SELECT content FROM ... WHERE id IN (...)\n *\n * Beneficial when:\n * - Table has many rows (> threshold)\n * - Query has complex WHERE conditions (lookup-table JOINs, chains)\n * - Content column is large (avoids reading content for non-matching rows)\n */\nfunction shouldUseTwoPhase(\n params: ParsedSearchParam[],\n registry: SearchParameterRegistry,\n resourceType: string,\n estimatedRowCount: number,\n threshold: number,\n): boolean {\n // Always use two-phase for large tables\n if (estimatedRowCount > threshold) return true;\n\n // Use two-phase if there are chain searches (expensive)\n if (params.some(p => p.chain)) return true;\n\n // Use two-phase if there are lookup-table searches (expensive JOIN)\n for (const param of params) {\n if (param.chain) continue;\n const impl = registry.getImpl(resourceType, param.code);\n if (impl?.strategy === 'lookup-table') return true;\n }\n\n return false;\n}\n\n// =============================================================================\n// Section 5: Estimated Selectivity\n// =============================================================================\n\n/**\n * Estimate overall query selectivity based on parameter types.\n */\nfunction estimateSelectivity(\n params: ParsedSearchParam[],\n registry: SearchParameterRegistry,\n resourceType: string,\n): 'high' | 'medium' | 'low' {\n if (params.length === 0) return 'low';\n\n // _id search is always high selectivity\n if (params.some(p => p.code === '_id')) return 'high';\n\n // Multiple token/reference params \u2192 high\n let highSelectivityCount = 0;\n for (const param of params) {\n if (param.chain) continue;\n const impl = registry.getImpl(resourceType, param.code);\n if (impl && (impl.strategy === 'token-column' || impl.type === 'reference')) {\n highSelectivityCount++;\n }\n }\n if (highSelectivityCount >= 2) return 'high';\n if (highSelectivityCount >= 1 && params.length >= 2) return 'high';\n\n // Single filter or string-only \u2192 low-medium\n if (params.length >= 2) return 'medium';\n return 'low';\n}\n\n// =============================================================================\n// Section 6: Main Planner Function\n// =============================================================================\n\n/**\n * Plan and optimize a search request.\n *\n * @param request - The parsed search request.\n * @param registry - The SearchParameterRegistry for resolving implementations.\n * @param options - Optional planner configuration.\n * @returns A SearchPlan with the optimized request and metadata.\n */\nexport function planSearch(\n request: SearchRequest,\n registry: SearchParameterRegistry,\n options?: SearchPlannerOptions,\n): SearchPlan {\n const maxChainDepth = options?.maxChainDepth ?? 1;\n const twoPhaseThreshold = options?.twoPhaseThreshold ?? 10_000;\n const estimatedRowCount = options?.estimatedRowCount ?? 0;\n\n // Step 1: Validate chain depth\n const { valid, warnings } = validateChainDepth(request.params, maxChainDepth);\n\n // Step 2: Reorder filters by selectivity\n const sorted = [...valid].sort((a, b) => {\n const pa = getSelectivityPriority(a, registry, request.resourceType);\n const pb = getSelectivityPriority(b, registry, request.resourceType);\n return pa - pb;\n });\n\n // Step 3: Determine two-phase recommendation\n const useTwoPhase = shouldUseTwoPhase(\n sorted, registry, request.resourceType, estimatedRowCount, twoPhaseThreshold,\n );\n\n // Step 4: Estimate selectivity\n const estimatedSelectivity = estimateSelectivity(sorted, registry, request.resourceType);\n\n // Step 5: Build optimized request\n const optimizedRequest: SearchRequest = {\n ...request,\n params: sorted,\n };\n\n return {\n request: optimizedRequest,\n useTwoPhase,\n hasChainedSearch: sorted.some(p => p.chain),\n estimatedSelectivity,\n warnings,\n };\n}\n", "/**\n * SQLiteAdapter \u2014 SQLite Implementation of StorageAdapter\n *\n * Uses `sql.js` (WebAssembly-based SQLite) for cross-platform\n * compatibility without native C++ compilation requirements.\n *\n * v2 upgrade: New file. v1 had no SQLite support.\n *\n * ## WAL Mode\n * sql.js runs in-memory by default. For file-based databases,\n * WAL mode and foreign keys are enabled on construction.\n *\n * @module fhir-persistence/db\n */\n\nimport initSqlJs from 'sql.js';\nimport type { Database as SqlJsDatabase, SqlJsStatic } from 'sql.js';\nimport type { StorageAdapter, PreparedStatement, TransactionContext } from './adapter.js';\n\n// =============================================================================\n// Section 1: Initialization Helper\n// =============================================================================\n\nlet sqlJsInitPromise: Promise<SqlJsStatic> | null = null;\n\n/**\n * Initialize sql.js (loads WebAssembly). Cached after first call.\n */\nasync function getSqlJs(): Promise<SqlJsStatic> {\n if (!sqlJsInitPromise) {\n sqlJsInitPromise = initSqlJs();\n }\n return sqlJsInitPromise;\n}\n\n// =============================================================================\n// Section 2: SQLiteAdapter\n// =============================================================================\n\nexport class SQLiteAdapter implements StorageAdapter {\n private db: SqlJsDatabase | null = null;\n private initPromise: Promise<void>;\n\n /**\n * @param path - Database file path, or ':memory:' for in-memory database.\n * @param data - Optional Uint8Array of an existing database file to load.\n */\n constructor(\n _path: string = ':memory:',\n private readonly data?: Uint8Array,\n ) {\n this.initPromise = this.initialize();\n }\n\n private async initialize(): Promise<void> {\n const SQL = await getSqlJs();\n this.db = new SQL.Database(this.data);\n // Enable WAL mode for better concurrent read performance\n this.db.run('PRAGMA journal_mode = WAL');\n // Enable foreign key constraints\n this.db.run('PRAGMA foreign_keys = ON');\n }\n\n private async getDb(): Promise<SqlJsDatabase> {\n await this.initPromise;\n if (!this.db) {\n throw new Error('SQLiteAdapter: database is closed');\n }\n return this.db;\n }\n\n async execute(sql: string, params: unknown[] = []): Promise<{ changes: number }> {\n const db = await this.getDb();\n db.run(sql, params as (string | number | null | Uint8Array)[]);\n const result = db.exec('SELECT changes() as c');\n const changes = result.length > 0 ? (result[0].values[0][0] as number) : 0;\n return { changes };\n }\n\n async query<T = Record<string, unknown>>(sql: string, params: unknown[] = []): Promise<T[]> {\n const db = await this.getDb();\n const stmt = db.prepare(sql);\n stmt.bind(params as (string | number | null | Uint8Array)[]);\n\n const rows: T[] = [];\n while (stmt.step()) {\n rows.push(stmt.getAsObject() as T);\n }\n stmt.free();\n return rows;\n }\n\n async queryOne<T = Record<string, unknown>>(sql: string, params: unknown[] = []): Promise<T | undefined> {\n const db = await this.getDb();\n const stmt = db.prepare(sql);\n stmt.bind(params as (string | number | null | Uint8Array)[]);\n\n let result: T | undefined;\n if (stmt.step()) {\n result = stmt.getAsObject() as T;\n }\n stmt.free();\n return result;\n }\n\n async *queryStream<T = Record<string, unknown>>(sql: string, params: unknown[] = []): AsyncIterable<T> {\n const db = await this.getDb();\n const stmt = db.prepare(sql);\n stmt.bind(params as (string | number | null | Uint8Array)[]);\n\n try {\n while (stmt.step()) {\n yield stmt.getAsObject() as T;\n }\n } finally {\n stmt.free();\n }\n }\n\n prepare<T = Record<string, unknown>>(sql: string): PreparedStatement<T> {\n // sql.js is async-init, so we need the db to be ready\n // For prepare, we require the adapter to be initialized\n if (!this.db) {\n throw new Error('SQLiteAdapter: database not initialized. Await an operation first.');\n }\n const db = this.db;\n const stmt = db.prepare(sql);\n\n return {\n query(params: unknown[] = []): T[] {\n stmt.bind(params as (string | number | null | Uint8Array)[]);\n const rows: T[] = [];\n while (stmt.step()) {\n rows.push(stmt.getAsObject() as T);\n }\n stmt.reset();\n return rows;\n },\n execute(params: unknown[] = []): { changes: number; lastInsertRowid?: number | bigint } {\n stmt.bind(params as (string | number | null | Uint8Array)[]);\n stmt.step();\n stmt.reset();\n // Get changes count\n const changesResult = db.exec('SELECT changes() as c, last_insert_rowid() as r');\n const changes = changesResult.length > 0 ? (changesResult[0].values[0][0] as number) : 0;\n const lastInsertRowid = changesResult.length > 0 ? (changesResult[0].values[0][1] as number) : undefined;\n return { changes, lastInsertRowid };\n },\n finalize(): void {\n stmt.free();\n },\n };\n }\n\n async transaction<R>(fn: (tx: TransactionContext) => R | Promise<R>): Promise<R> {\n const db = await this.getDb();\n\n // BEGIN IMMEDIATE: write lock immediately, allows concurrent reads\n db.run('BEGIN IMMEDIATE');\n\n const ctx: TransactionContext = {\n execute(sql: string, params: unknown[] = []): { changes: number } {\n db.run(sql, params as (string | number | null | Uint8Array)[]);\n const result = db.exec('SELECT changes() as c');\n const changes = result.length > 0 ? (result[0].values[0][0] as number) : 0;\n return { changes };\n },\n query<T = Record<string, unknown>>(sql: string, params: unknown[] = []): T[] {\n const stmt = db.prepare(sql);\n stmt.bind(params as (string | number | null | Uint8Array)[]);\n const rows: T[] = [];\n while (stmt.step()) {\n rows.push(stmt.getAsObject() as T);\n }\n stmt.free();\n return rows;\n },\n queryOne<T = Record<string, unknown>>(sql: string, params: unknown[] = []): T | undefined {\n const stmt = db.prepare(sql);\n stmt.bind(params as (string | number | null | Uint8Array)[]);\n let result: T | undefined;\n if (stmt.step()) {\n result = stmt.getAsObject() as T;\n }\n stmt.free();\n return result;\n },\n };\n\n try {\n const result = await fn(ctx);\n db.run('COMMIT');\n return result;\n } catch (err) {\n db.run('ROLLBACK');\n throw err;\n }\n }\n\n async close(): Promise<void> {\n await this.initPromise;\n if (this.db) {\n this.db.close();\n this.db = null;\n }\n }\n\n /**\n * Export the database as a Uint8Array (for file persistence).\n */\n async export(): Promise<Uint8Array> {\n const db = await this.getDb();\n return db.export();\n }\n}\n", "/**\n * BetterSqlite3Adapter \u2014 Native SQLite Implementation of StorageAdapter\n *\n * Uses `better-sqlite3` for production-grade, synchronous SQLite access\n * with native C++ bindings. Significantly faster than sql.js (WebAssembly)\n * for most workloads, especially writes and transactions.\n *\n * ## Advantages over sql.js:\n * - Native C++ bindings \u2014 ~3-10\u00D7 faster than WebAssembly\n * - True WAL mode with file-based databases\n * - Real prepared statement caching\n * - Synchronous API (no async overhead for each operation)\n * - Lower memory overhead\n *\n * ## Trade-offs:\n * - Requires native compilation (node-gyp, prebuild)\n * - Not available in browser environments\n * - Not available in some serverless environments\n *\n * @module fhir-persistence/db\n */\n\nimport Database from 'better-sqlite3';\nimport type { Database as BetterSqlite3Database } from 'better-sqlite3';\nimport type { StorageAdapter, PreparedStatement, TransactionContext } from './adapter.js';\n\n// =============================================================================\n// Section 1: BetterSqlite3Adapter\n// =============================================================================\n\nexport interface BetterSqlite3Options {\n /** Database file path, or ':memory:' for in-memory database. */\n path?: string;\n /** Enable WAL journal mode (default: true). */\n wal?: boolean;\n /** Enable foreign key constraints (default: true). */\n foreignKeys?: boolean;\n /** Busy timeout in milliseconds (default: 5000). */\n busyTimeout?: number;\n /** Additional PRAGMA statements to execute on init. */\n pragmas?: Record<string, string | number | boolean>;\n}\n\nexport class BetterSqlite3Adapter implements StorageAdapter {\n private db: BetterSqlite3Database;\n private closed = false;\n\n constructor(options: BetterSqlite3Options = {}) {\n const {\n path = ':memory:',\n wal = true,\n foreignKeys = true,\n busyTimeout = 5000,\n pragmas = {},\n } = options;\n\n this.db = new Database(path);\n\n // Core PRAGMAs\n if (wal) {\n this.db.pragma('journal_mode = WAL');\n }\n if (foreignKeys) {\n this.db.pragma('foreign_keys = ON');\n }\n if (busyTimeout > 0) {\n this.db.pragma(`busy_timeout = ${busyTimeout}`);\n }\n\n // User-defined PRAGMAs\n for (const [key, value] of Object.entries(pragmas)) {\n this.db.pragma(`${key} = ${value}`);\n }\n }\n\n private ensureOpen(): BetterSqlite3Database {\n if (this.closed) {\n throw new Error('BetterSqlite3Adapter: database is closed');\n }\n return this.db;\n }\n\n // ---------------------------------------------------------------------------\n // StorageAdapter implementation\n // ---------------------------------------------------------------------------\n\n async execute(sql: string, params: unknown[] = []): Promise<{ changes: number }> {\n const db = this.ensureOpen();\n const result = db.prepare(sql).run(...params);\n return { changes: result.changes };\n }\n\n async query<T = Record<string, unknown>>(sql: string, params: unknown[] = []): Promise<T[]> {\n const db = this.ensureOpen();\n return db.prepare(sql).all(...params) as T[];\n }\n\n async queryOne<T = Record<string, unknown>>(sql: string, params: unknown[] = []): Promise<T | undefined> {\n const db = this.ensureOpen();\n return db.prepare(sql).get(...params) as T | undefined;\n }\n\n async *queryStream<T = Record<string, unknown>>(sql: string, params: unknown[] = []): AsyncIterable<T> {\n const db = this.ensureOpen();\n const stmt = db.prepare(sql);\n for (const row of stmt.iterate(...params)) {\n yield row as T;\n }\n }\n\n prepare<T = Record<string, unknown>>(sql: string): PreparedStatement<T> {\n const db = this.ensureOpen();\n const stmt = db.prepare(sql);\n\n return {\n query(params: unknown[] = []): T[] {\n return stmt.all(...params) as T[];\n },\n execute(params: unknown[] = []): { changes: number; lastInsertRowid?: number | bigint } {\n const result = stmt.run(...params);\n return {\n changes: result.changes,\n lastInsertRowid: result.lastInsertRowid,\n };\n },\n finalize(): void {\n // better-sqlite3 statements are finalized automatically by GC,\n // but we can explicitly discard the reference\n },\n };\n }\n\n async transaction<R>(fn: (tx: TransactionContext) => R | Promise<R>): Promise<R> {\n const db = this.ensureOpen();\n\n const ctx: TransactionContext = {\n execute(sql: string, params: unknown[] = []): { changes: number } {\n const result = db.prepare(sql).run(...params);\n return { changes: result.changes };\n },\n query<T = Record<string, unknown>>(sql: string, params: unknown[] = []): T[] {\n return db.prepare(sql).all(...params) as T[];\n },\n queryOne<T = Record<string, unknown>>(sql: string, params: unknown[] = []): T | undefined {\n return db.prepare(sql).get(...params) as T | undefined;\n },\n };\n\n // Use better-sqlite3's built-in transaction support for sync callbacks,\n // but wrap in manual BEGIN/COMMIT for async compatibility\n db.exec('BEGIN IMMEDIATE');\n try {\n const result = await fn(ctx);\n db.exec('COMMIT');\n return result;\n } catch (err) {\n db.exec('ROLLBACK');\n throw err;\n }\n }\n\n async close(): Promise<void> {\n if (!this.closed) {\n this.db.close();\n this.closed = true;\n }\n }\n\n // ---------------------------------------------------------------------------\n // Additional utilities\n // ---------------------------------------------------------------------------\n\n /**\n * Get the underlying better-sqlite3 Database instance.\n * Use with caution \u2014 bypasses the adapter abstraction.\n */\n getRawDatabase(): BetterSqlite3Database {\n return this.ensureOpen();\n }\n\n /**\n * Execute a PRAGMA and return the result.\n */\n pragma(statement: string): unknown {\n return this.ensureOpen().pragma(statement);\n }\n\n /**\n * Checkpoint WAL file to main database file.\n * Useful before backup or when shutting down.\n */\n checkpoint(mode: 'PASSIVE' | 'FULL' | 'RESTART' | 'TRUNCATE' = 'PASSIVE'): void {\n this.ensureOpen().pragma(`wal_checkpoint(${mode})`);\n }\n}\n", "/**\n * FhirStore \u2014 v2 CRUD Facade\n *\n * Provides create / read / update / delete / history operations\n * against any StorageAdapter implementation (SQLite, PostgreSQL, etc.).\n *\n * Design decisions:\n * - Uses StorageAdapter interface (not DatabaseClient directly)\n * - All writes are transactional (BEGIN IMMEDIATE on SQLite)\n * - Soft delete: deleted=1, content preserved (ADR-08)\n * - Optimistic locking via versionId (If-Match / ETag)\n * - History ordered by versionSeq DESC\n * - No projectId (single-tenant)\n *\n * @module fhir-persistence/store\n */\n\nimport { randomUUID } from 'node:crypto';\nimport type { StorageAdapter } from '../db/adapter.js';\nimport type {\n FhirResource,\n PersistedResource,\n HistoryEntry,\n ResourceRowV2,\n HistoryRowV2,\n} from '../repo/types.js';\nimport {\n ResourceNotFoundError,\n ResourceGoneError,\n ResourceVersionConflictError,\n} from '../repo/errors.js';\nimport {\n buildInsertMainSQLv2,\n buildUpdateMainSQLv2,\n buildInsertHistorySQLv2,\n buildSelectByIdSQLv2,\n buildSelectVersionSQLv2,\n buildDeleteReferencesSQLv2,\n buildInsertReferencesSQLv2,\n buildInstanceHistorySQLv2,\n} from '../repo/sql-builder.js';\nimport type { ReferenceRowV2 } from '../repo/reference-indexer.js';\n\n// =============================================================================\n// Section 1: Options\n// =============================================================================\n\nexport interface CreateResourceOptions {\n /** Pre-assigned ID (used in batch/transaction). */\n assignedId?: string;\n}\n\nexport interface UpdateResourceOptions {\n /** Expected versionId for optimistic locking (If-Match header). */\n ifMatch?: string;\n}\n\nexport interface HistoryOptions {\n since?: string;\n count?: number;\n cursor?: string;\n}\n\n// =============================================================================\n// Section 2: FhirStore Class\n// =============================================================================\n\nexport class FhirStore {\n constructor(private readonly adapter: StorageAdapter) {}\n\n // ---------------------------------------------------------------------------\n // CREATE\n // ---------------------------------------------------------------------------\n\n async createResource<T extends FhirResource>(\n resourceType: string,\n resource: T,\n options?: CreateResourceOptions,\n ): Promise<T & PersistedResource> {\n const now = new Date().toISOString();\n const id = options?.assignedId ?? resource.id ?? randomUUID();\n const versionId = randomUUID();\n\n const persisted = {\n ...resource,\n resourceType,\n id,\n meta: {\n ...resource.meta,\n versionId,\n lastUpdated: now,\n },\n } as T & PersistedResource;\n\n const content = JSON.stringify(persisted);\n\n const mainRow: ResourceRowV2 = {\n id,\n versionId,\n content,\n lastUpdated: now,\n deleted: 0,\n _source: persisted.meta?.source ?? null,\n _profile: persisted.meta?.profile ? JSON.stringify(persisted.meta.profile) : null,\n };\n\n const historyRow: HistoryRowV2 = {\n id,\n versionId,\n content,\n lastUpdated: now,\n deleted: 0,\n };\n\n await this.adapter.transaction((tx) => {\n const mainSQL = buildInsertMainSQLv2(resourceType, mainRow);\n tx.execute(mainSQL.sql, mainSQL.values);\n\n const histSQL = buildInsertHistorySQLv2(`${resourceType}_History`, historyRow);\n tx.execute(histSQL.sql, histSQL.values);\n });\n\n return persisted;\n }\n\n // ---------------------------------------------------------------------------\n // READ\n // ---------------------------------------------------------------------------\n\n async readResource(resourceType: string, id: string): Promise<PersistedResource> {\n const sql = buildSelectByIdSQLv2(resourceType);\n const row = await this.adapter.queryOne<{\n id: string;\n versionId: string;\n content: string;\n deleted: number;\n lastUpdated: string;\n }>(sql, [id]);\n\n if (!row) {\n throw new ResourceNotFoundError(resourceType, id);\n }\n if (row.deleted === 1) {\n throw new ResourceGoneError(resourceType, id);\n }\n\n return JSON.parse(row.content) as PersistedResource;\n }\n\n // ---------------------------------------------------------------------------\n // UPDATE\n // ---------------------------------------------------------------------------\n\n async updateResource<T extends FhirResource>(\n resourceType: string,\n resource: T,\n options?: UpdateResourceOptions,\n ): Promise<T & PersistedResource> {\n const id = resource.id;\n if (!id) {\n throw new Error('Resource must have an id for update');\n }\n\n // Read current version for optimistic locking\n const selectSQL = buildSelectByIdSQLv2(resourceType);\n const current = await this.adapter.queryOne<{\n id: string;\n versionId: string;\n content: string;\n deleted: number;\n }>(selectSQL, [id]);\n\n if (!current) {\n throw new ResourceNotFoundError(resourceType, id);\n }\n if (current.deleted === 1) {\n throw new ResourceGoneError(resourceType, id);\n }\n\n // Optimistic locking check\n if (options?.ifMatch) {\n const expected = options.ifMatch.replace(/^W\\/\"/, '').replace(/\"$/, '');\n if (expected !== current.versionId) {\n throw new ResourceVersionConflictError(\n resourceType,\n id,\n expected,\n current.versionId,\n );\n }\n }\n\n const now = new Date().toISOString();\n const versionId = randomUUID();\n\n const persisted = {\n ...resource,\n resourceType,\n id,\n meta: {\n ...resource.meta,\n versionId,\n lastUpdated: now,\n },\n } as T & PersistedResource;\n\n const content = JSON.stringify(persisted);\n\n const mainRow: ResourceRowV2 = {\n id,\n versionId,\n content,\n lastUpdated: now,\n deleted: 0,\n _source: persisted.meta?.source ?? null,\n _profile: persisted.meta?.profile ? JSON.stringify(persisted.meta.profile) : null,\n };\n\n const historyRow: HistoryRowV2 = {\n id,\n versionId,\n content,\n lastUpdated: now,\n deleted: 0,\n };\n\n await this.adapter.transaction((tx) => {\n const updateSQL = buildUpdateMainSQLv2(resourceType, mainRow);\n tx.execute(updateSQL.sql, updateSQL.values);\n\n const histSQL = buildInsertHistorySQLv2(`${resourceType}_History`, historyRow);\n tx.execute(histSQL.sql, histSQL.values);\n\n // Clear old references and re-insert (handled externally if needed)\n const delRefSQL = buildDeleteReferencesSQLv2(`${resourceType}_References`);\n tx.execute(delRefSQL, [id]);\n });\n\n return persisted;\n }\n\n // ---------------------------------------------------------------------------\n // DELETE (soft)\n // ---------------------------------------------------------------------------\n\n async deleteResource(resourceType: string, id: string): Promise<void> {\n const selectSQL = buildSelectByIdSQLv2(resourceType);\n const current = await this.adapter.queryOne<{\n id: string;\n versionId: string;\n content: string;\n deleted: number;\n }>(selectSQL, [id]);\n\n if (!current) {\n throw new ResourceNotFoundError(resourceType, id);\n }\n if (current.deleted === 1) {\n throw new ResourceGoneError(resourceType, id);\n }\n\n const now = new Date().toISOString();\n const versionId = randomUUID();\n\n // v2: content preserved on soft delete (ADR-08)\n const deleteRow: ResourceRowV2 = {\n id,\n versionId,\n content: current.content,\n lastUpdated: now,\n deleted: 1,\n };\n\n const historyRow: HistoryRowV2 = {\n id,\n versionId,\n content: current.content,\n lastUpdated: now,\n deleted: 1,\n };\n\n await this.adapter.transaction((tx) => {\n const updateSQL = buildUpdateMainSQLv2(resourceType, deleteRow);\n tx.execute(updateSQL.sql, updateSQL.values);\n\n const histSQL = buildInsertHistorySQLv2(`${resourceType}_History`, historyRow);\n tx.execute(histSQL.sql, histSQL.values);\n\n // Clear references for deleted resource\n const delRefSQL = buildDeleteReferencesSQLv2(`${resourceType}_References`);\n tx.execute(delRefSQL, [id]);\n });\n }\n\n // ---------------------------------------------------------------------------\n // READ VERSION (vread)\n // ---------------------------------------------------------------------------\n\n async readVersion(\n resourceType: string,\n id: string,\n versionId: string,\n ): Promise<PersistedResource> {\n const sql = buildSelectVersionSQLv2(`${resourceType}_History`);\n const row = await this.adapter.queryOne<{\n content: string;\n deleted: number;\n }>(sql, [id, versionId]);\n\n if (!row) {\n throw new ResourceNotFoundError(resourceType, id);\n }\n\n return JSON.parse(row.content) as PersistedResource;\n }\n\n // ---------------------------------------------------------------------------\n // HISTORY\n // ---------------------------------------------------------------------------\n\n async readHistory(\n resourceType: string,\n id: string,\n options?: HistoryOptions,\n ): Promise<HistoryEntry[]> {\n const { sql, values } = buildInstanceHistorySQLv2(\n `${resourceType}_History`,\n id,\n options,\n );\n\n const rows = await this.adapter.query<{\n id: string;\n versionId: string;\n lastUpdated: string;\n content: string;\n deleted: number;\n }>(sql, values);\n\n return rows.map((row) => ({\n id: row.id,\n versionId: row.versionId,\n lastUpdated: row.lastUpdated,\n deleted: row.deleted === 1,\n resourceType,\n resource: row.deleted === 1 ? null : (JSON.parse(row.content) as PersistedResource),\n }));\n }\n\n // ---------------------------------------------------------------------------\n // WRITE REFERENCES (utility for external callers)\n // ---------------------------------------------------------------------------\n\n async writeReferences(\n resourceType: string,\n resourceId: string,\n refs: ReferenceRowV2[],\n ): Promise<void> {\n if (refs.length === 0) return;\n\n const tableName = `${resourceType}_References`;\n const sql = buildInsertReferencesSQLv2(tableName, refs.length);\n const values: unknown[] = [];\n for (const ref of refs) {\n values.push(ref.resourceId, ref.targetType, ref.targetId, ref.code, ref.referenceRaw);\n }\n\n await this.adapter.execute(sql, values);\n }\n}\n", "/**\n * FhirPersistence \u2014 v2 End-to-End Facade\n *\n * Top-level entry point that wires together all v2 modules into a single\n * cohesive API. Manages the full lifecycle:\n *\n * 1. **Startup** \u2014 Initialize StorageAdapter, run IG migrations, create tables\n * 2. **CRUD** \u2014 Create/Read/Update/Delete with automatic search indexing\n * 3. **Search** \u2014 Execute FHIR search queries via SearchExecutor\n * 4. **Indexing** \u2014 Search columns + References + Lookup tables\n *\n * Design decisions:\n * - Single constructor with StorageAdapter + SearchParameterRegistry\n * - CRUD operations automatically index via IndexingPipeline\n * - Search columns merged into main table row on create/update\n * - References and lookup rows written as side effects\n * - Soft delete clears index data (references + lookup rows)\n * - All writes transactional via StorageAdapter\n *\n * @module fhir-persistence/store\n */\n\nimport { randomUUID } from 'node:crypto';\nimport type { StorageAdapter } from '../db/adapter.js';\nimport type { SearchParameterRegistry, SearchParameterImpl } from '../registry/search-parameter-registry.js';\nimport type {\n FhirResource,\n PersistedResource,\n HistoryEntry,\n ResourceRowV2,\n HistoryRowV2,\n} from '../repo/types.js';\nimport {\n ResourceNotFoundError,\n ResourceGoneError,\n ResourceVersionConflictError,\n} from '../repo/errors.js';\nimport {\n buildInsertMainSQLv2,\n buildUpdateMainSQLv2,\n buildInsertHistorySQLv2,\n buildSelectByIdSQLv2,\n buildSelectVersionSQLv2,\n buildInstanceHistorySQLv2,\n} from '../repo/sql-builder.js';\nimport { IndexingPipeline } from '../repo/indexing-pipeline.js';\nimport type { IndexingPipelineOptions } from '../repo/indexing-pipeline.js';\n\n// =============================================================================\n// Section 1: Options\n// =============================================================================\n\nexport interface CreateResourceOptions {\n /** Pre-assigned ID (used in batch/transaction). */\n assignedId?: string;\n}\n\nexport interface UpdateResourceOptions {\n /** Expected versionId for optimistic locking (If-Match header). */\n ifMatch?: string;\n}\n\nexport interface HistoryOptions {\n since?: string;\n count?: number;\n cursor?: string;\n}\n\nexport interface FhirPersistenceOptions {\n /** Indexing pipeline options. */\n indexing?: IndexingPipelineOptions;\n}\n\n// =============================================================================\n// Section 2: FhirPersistence Class\n// =============================================================================\n\nexport class FhirPersistence {\n private readonly adapter: StorageAdapter;\n private readonly registry: SearchParameterRegistry;\n private readonly pipeline: IndexingPipeline;\n\n constructor(\n adapter: StorageAdapter,\n registry: SearchParameterRegistry,\n options?: FhirPersistenceOptions,\n ) {\n this.adapter = adapter;\n this.registry = registry;\n this.pipeline = new IndexingPipeline(adapter, options?.indexing);\n }\n\n // ---------------------------------------------------------------------------\n // Accessors\n // ---------------------------------------------------------------------------\n\n /** Get the underlying StorageAdapter. */\n getAdapter(): StorageAdapter { return this.adapter; }\n\n /** Get the SearchParameterRegistry. */\n getRegistry(): SearchParameterRegistry { return this.registry; }\n\n /** Get the IndexingPipeline. */\n getPipeline(): IndexingPipeline { return this.pipeline; }\n\n // ---------------------------------------------------------------------------\n // CREATE\n // ---------------------------------------------------------------------------\n\n async createResource<T extends FhirResource>(\n resourceType: string,\n resource: T,\n options?: CreateResourceOptions,\n ): Promise<T & PersistedResource> {\n const now = new Date().toISOString();\n const id = options?.assignedId ?? resource.id ?? randomUUID();\n const versionId = randomUUID();\n\n const persisted = {\n ...resource,\n resourceType,\n id,\n meta: {\n ...resource.meta,\n versionId,\n lastUpdated: now,\n },\n } as T & PersistedResource;\n\n // Get search parameter impls for this resource type\n const impls = this.getImpls(resourceType);\n\n // Run indexing pipeline (extract search columns + references + lookup rows)\n const indexResult = await this.pipeline.indexResource(resourceType, persisted, impls);\n\n const content = JSON.stringify(persisted);\n\n // Build main row with search columns merged\n const mainRow: Record<string, unknown> = {\n id,\n versionId,\n content,\n lastUpdated: now,\n deleted: 0,\n _source: persisted.meta?.source ?? null,\n _profile: persisted.meta?.profile ? JSON.stringify(persisted.meta.profile) : null,\n ...indexResult.searchColumns,\n };\n\n const historyRow: HistoryRowV2 = {\n id,\n versionId,\n content,\n lastUpdated: now,\n deleted: 0,\n };\n\n await this.adapter.transaction((tx) => {\n const mainSQL = buildInsertMainSQLv2(resourceType, mainRow);\n tx.execute(mainSQL.sql, mainSQL.values);\n\n const histSQL = buildInsertHistorySQLv2(`${resourceType}_History`, historyRow);\n tx.execute(histSQL.sql, histSQL.values);\n });\n\n return persisted;\n }\n\n // ---------------------------------------------------------------------------\n // READ\n // ---------------------------------------------------------------------------\n\n async readResource(resourceType: string, id: string): Promise<PersistedResource> {\n const sql = buildSelectByIdSQLv2(resourceType);\n const row = await this.adapter.queryOne<{\n id: string;\n versionId: string;\n content: string;\n deleted: number;\n lastUpdated: string;\n }>(sql, [id]);\n\n if (!row) {\n throw new ResourceNotFoundError(resourceType, id);\n }\n if (row.deleted === 1) {\n throw new ResourceGoneError(resourceType, id);\n }\n\n return JSON.parse(row.content) as PersistedResource;\n }\n\n // ---------------------------------------------------------------------------\n // UPDATE\n // ---------------------------------------------------------------------------\n\n async updateResource<T extends FhirResource>(\n resourceType: string,\n resource: T,\n options?: UpdateResourceOptions,\n ): Promise<T & PersistedResource> {\n const id = resource.id;\n if (!id) {\n throw new Error('Resource must have an id for update');\n }\n\n // Read current version for optimistic locking\n const selectSQL = buildSelectByIdSQLv2(resourceType);\n const current = await this.adapter.queryOne<{\n id: string;\n versionId: string;\n content: string;\n deleted: number;\n }>(selectSQL, [id]);\n\n if (!current) {\n throw new ResourceNotFoundError(resourceType, id);\n }\n if (current.deleted === 1) {\n throw new ResourceGoneError(resourceType, id);\n }\n\n // Optimistic locking check\n if (options?.ifMatch) {\n const expected = options.ifMatch.replace(/^W\\/\"/, '').replace(/\"$/, '');\n if (expected !== current.versionId) {\n throw new ResourceVersionConflictError(\n resourceType,\n id,\n expected,\n current.versionId,\n );\n }\n }\n\n const now = new Date().toISOString();\n const versionId = randomUUID();\n\n const persisted = {\n ...resource,\n resourceType,\n id,\n meta: {\n ...resource.meta,\n versionId,\n lastUpdated: now,\n },\n } as T & PersistedResource;\n\n // Re-index\n const impls = this.getImpls(resourceType);\n const indexResult = await this.pipeline.indexResource(resourceType, persisted, impls);\n\n const content = JSON.stringify(persisted);\n\n const mainRow: Record<string, unknown> = {\n id,\n versionId,\n content,\n lastUpdated: now,\n deleted: 0,\n _source: persisted.meta?.source ?? null,\n _profile: persisted.meta?.profile ? JSON.stringify(persisted.meta.profile) : null,\n ...indexResult.searchColumns,\n };\n\n const historyRow: HistoryRowV2 = {\n id,\n versionId,\n content,\n lastUpdated: now,\n deleted: 0,\n };\n\n await this.adapter.transaction((tx) => {\n const updateSQL = buildUpdateMainSQLv2(resourceType, mainRow);\n tx.execute(updateSQL.sql, updateSQL.values);\n\n const histSQL = buildInsertHistorySQLv2(`${resourceType}_History`, historyRow);\n tx.execute(histSQL.sql, histSQL.values);\n });\n\n return persisted;\n }\n\n // ---------------------------------------------------------------------------\n // DELETE (soft)\n // ---------------------------------------------------------------------------\n\n async deleteResource(resourceType: string, id: string): Promise<void> {\n const selectSQL = buildSelectByIdSQLv2(resourceType);\n const current = await this.adapter.queryOne<{\n id: string;\n versionId: string;\n content: string;\n deleted: number;\n }>(selectSQL, [id]);\n\n if (!current) {\n throw new ResourceNotFoundError(resourceType, id);\n }\n if (current.deleted === 1) {\n throw new ResourceGoneError(resourceType, id);\n }\n\n const now = new Date().toISOString();\n const versionId = randomUUID();\n\n const deleteRow: ResourceRowV2 = {\n id,\n versionId,\n content: current.content,\n lastUpdated: now,\n deleted: 1,\n };\n\n const historyRow: HistoryRowV2 = {\n id,\n versionId,\n content: current.content,\n lastUpdated: now,\n deleted: 1,\n };\n\n // Clear index data\n await this.pipeline.deleteIndex(resourceType, id);\n\n await this.adapter.transaction((tx) => {\n const updateSQL = buildUpdateMainSQLv2(resourceType, deleteRow);\n tx.execute(updateSQL.sql, updateSQL.values);\n\n const histSQL = buildInsertHistorySQLv2(`${resourceType}_History`, historyRow);\n tx.execute(histSQL.sql, histSQL.values);\n });\n }\n\n // ---------------------------------------------------------------------------\n // READ VERSION (vread)\n // ---------------------------------------------------------------------------\n\n async readVersion(\n resourceType: string,\n id: string,\n versionId: string,\n ): Promise<PersistedResource> {\n const sql = buildSelectVersionSQLv2(`${resourceType}_History`);\n const row = await this.adapter.queryOne<{\n content: string;\n deleted: number;\n }>(sql, [id, versionId]);\n\n if (!row) {\n throw new ResourceNotFoundError(resourceType, id);\n }\n\n return JSON.parse(row.content) as PersistedResource;\n }\n\n // ---------------------------------------------------------------------------\n // HISTORY\n // ---------------------------------------------------------------------------\n\n async readHistory(\n resourceType: string,\n id: string,\n options?: HistoryOptions,\n ): Promise<HistoryEntry[]> {\n const { sql, values } = buildInstanceHistorySQLv2(\n `${resourceType}_History`,\n id,\n options,\n );\n\n const rows = await this.adapter.query<{\n id: string;\n versionId: string;\n lastUpdated: string;\n content: string;\n deleted: number;\n }>(sql, values);\n\n return rows.map((row) => ({\n id: row.id,\n versionId: row.versionId,\n lastUpdated: row.lastUpdated,\n deleted: row.deleted === 1,\n resourceType,\n resource: row.deleted === 1 ? null : (JSON.parse(row.content) as PersistedResource),\n }));\n }\n\n // ---------------------------------------------------------------------------\n // SEARCH (streaming)\n // ---------------------------------------------------------------------------\n\n /**\n * Stream search results row-by-row for large result sets.\n *\n * Uses `StorageAdapter.queryStream` for true row-by-row iteration\n * without loading all results into memory. Useful for:\n * - Export operations ($export)\n * - Reindex-all workflows\n * - Large batch processing\n *\n * NOTE: Does NOT include _include/_revinclude resources.\n * Use `searchResources` for full FHIR search with includes.\n */\n async *searchStream(\n resourceType: string,\n sql: string,\n params: unknown[] = [],\n ): AsyncGenerator<PersistedResource> {\n for await (const row of this.adapter.queryStream<{\n content: string;\n deleted: number;\n }>(sql, params)) {\n if (row.deleted === 1) continue;\n if (!row.content) continue;\n try {\n yield JSON.parse(row.content) as PersistedResource;\n } catch {\n // Skip invalid JSON\n }\n }\n }\n\n // ---------------------------------------------------------------------------\n // Re-index a single resource\n // ---------------------------------------------------------------------------\n\n /**\n * Re-index an existing resource (update search columns + references + lookup).\n * Does NOT create a new version.\n */\n async reindexResource(resourceType: string, id: string): Promise<void> {\n const resource = await this.readResource(resourceType, id);\n const impls = this.getImpls(resourceType);\n const indexResult = await this.pipeline.indexResource(resourceType, resource, impls);\n\n // Update search columns in main table\n const updateRow: Record<string, unknown> = {\n id,\n ...indexResult.searchColumns,\n };\n\n const updateSQL = buildUpdateMainSQLv2(resourceType, updateRow);\n await this.adapter.execute(updateSQL.sql, updateSQL.values);\n }\n\n // ---------------------------------------------------------------------------\n // Private\n // ---------------------------------------------------------------------------\n\n private getImpls(resourceType: string): SearchParameterImpl[] {\n return this.registry.getForResource(resourceType);\n }\n}\n", "/**\n * Lookup Table Writer \u2014 v2\n *\n * Manages the 4 global lookup tables (HumanName, Address, ContactPoint, Identifier)\n * using StorageAdapter v2. Handles DDL creation, row insertion (replace strategy),\n * and deletion.\n *\n * Design decisions:\n * - Uses StorageAdapter interface (not DatabaseClient directly)\n * - All writes use `?` placeholders (SQLite-compatible, rewritten for PG)\n * - Replace strategy: DELETE existing rows for resourceId, then INSERT new ones\n * - Each lookup table has a `resourceId` column + type-specific columns\n * - Batch insert per table type for efficiency\n *\n * @module fhir-persistence/repo\n */\n\nimport type { StorageAdapter } from '../db/adapter.js';\nimport type { LookupTableRow } from './row-indexer.js';\n\n// =============================================================================\n// Section 1: DDL\n// =============================================================================\n\nconst LOOKUP_TABLE_DDL: Record<string, string> = {\n HumanName: `CREATE TABLE IF NOT EXISTS \"HumanName\" (\n \"id\" INTEGER PRIMARY KEY AUTOINCREMENT,\n \"resourceId\" TEXT NOT NULL,\n \"name\" TEXT,\n \"given\" TEXT,\n \"family\" TEXT\n)`,\n Address: `CREATE TABLE IF NOT EXISTS \"Address\" (\n \"id\" INTEGER PRIMARY KEY AUTOINCREMENT,\n \"resourceId\" TEXT NOT NULL,\n \"address\" TEXT,\n \"city\" TEXT,\n \"country\" TEXT,\n \"postalCode\" TEXT,\n \"state\" TEXT,\n \"use\" TEXT\n)`,\n ContactPoint: `CREATE TABLE IF NOT EXISTS \"ContactPoint\" (\n \"id\" INTEGER PRIMARY KEY AUTOINCREMENT,\n \"resourceId\" TEXT NOT NULL,\n \"system\" TEXT,\n \"value\" TEXT,\n \"use\" TEXT\n)`,\n Identifier: `CREATE TABLE IF NOT EXISTS \"Identifier\" (\n \"id\" INTEGER PRIMARY KEY AUTOINCREMENT,\n \"resourceId\" TEXT NOT NULL,\n \"system\" TEXT,\n \"value\" TEXT\n)`,\n};\n\nconst LOOKUP_TABLE_INDEXES: Record<string, string[]> = {\n HumanName: [\n 'CREATE INDEX IF NOT EXISTS \"HumanName_resourceId_idx\" ON \"HumanName\" (\"resourceId\")',\n 'CREATE INDEX IF NOT EXISTS \"HumanName_name_idx\" ON \"HumanName\" (\"name\")',\n ],\n Address: [\n 'CREATE INDEX IF NOT EXISTS \"Address_resourceId_idx\" ON \"Address\" (\"resourceId\")',\n 'CREATE INDEX IF NOT EXISTS \"Address_address_idx\" ON \"Address\" (\"address\")',\n ],\n ContactPoint: [\n 'CREATE INDEX IF NOT EXISTS \"ContactPoint_resourceId_idx\" ON \"ContactPoint\" (\"resourceId\")',\n 'CREATE INDEX IF NOT EXISTS \"ContactPoint_value_idx\" ON \"ContactPoint\" (\"value\")',\n ],\n Identifier: [\n 'CREATE INDEX IF NOT EXISTS \"Identifier_resourceId_idx\" ON \"Identifier\" (\"resourceId\")',\n 'CREATE INDEX IF NOT EXISTS \"Identifier_system_value_idx\" ON \"Identifier\" (\"system\", \"value\")',\n ],\n};\n\n// Column definitions per table (order matters for INSERT)\nconst LOOKUP_COLUMNS: Record<string, string[]> = {\n HumanName: ['resourceId', 'name', 'given', 'family'],\n Address: ['resourceId', 'address', 'city', 'country', 'postalCode', 'state', 'use'],\n ContactPoint: ['resourceId', 'system', 'value', 'use'],\n Identifier: ['resourceId', 'system', 'value'],\n};\n\n// =============================================================================\n// Section 2: LookupTableWriter Class\n// =============================================================================\n\nexport class LookupTableWriter {\n private initialized = false;\n\n constructor(private readonly adapter: StorageAdapter) {}\n\n // ---------------------------------------------------------------------------\n // DDL\n // ---------------------------------------------------------------------------\n\n /**\n * Create all 4 lookup tables + indexes if they don't exist.\n */\n async ensureTables(): Promise<void> {\n if (this.initialized) return;\n\n for (const table of Object.keys(LOOKUP_TABLE_DDL)) {\n await this.adapter.execute(LOOKUP_TABLE_DDL[table]);\n for (const idx of LOOKUP_TABLE_INDEXES[table]) {\n await this.adapter.execute(idx);\n }\n }\n this.initialized = true;\n }\n\n // ---------------------------------------------------------------------------\n // Write (replace strategy)\n // ---------------------------------------------------------------------------\n\n /**\n * Write lookup table rows for a resource (replace strategy).\n *\n * 1. Deletes all existing rows for the resourceId across all 4 tables\n * 2. Inserts new rows grouped by table type\n *\n * @param resourceId - The resource ID to index.\n * @param rows - LookupTableRow[] from `buildLookupTableRows()`.\n */\n async writeRows(resourceId: string, rows: LookupTableRow[]): Promise<void> {\n await this.ensureTables();\n\n // Delete existing rows for this resource across all tables\n await this.deleteRows(resourceId);\n\n if (rows.length === 0) return;\n\n // Group rows by table type\n const grouped = new Map<string, LookupTableRow[]>();\n for (const row of rows) {\n const existing = grouped.get(row.table) ?? [];\n existing.push(row);\n grouped.set(row.table, existing);\n }\n\n // Insert per table type\n for (const [table, tableRows] of grouped) {\n const columns = LOOKUP_COLUMNS[table];\n if (!columns) continue;\n\n for (const row of tableRows) {\n const values: unknown[] = columns.map(col => row.values[col] ?? null);\n const placeholders = columns.map(() => '?').join(', ');\n const colList = columns.map(c => `\"${c}\"`).join(', ');\n const sql = `INSERT INTO \"${table}\" (${colList}) VALUES (${placeholders})`;\n await this.adapter.execute(sql, values);\n }\n }\n }\n\n // ---------------------------------------------------------------------------\n // Delete\n // ---------------------------------------------------------------------------\n\n /**\n * Delete all lookup table rows for a given resourceId.\n */\n async deleteRows(resourceId: string): Promise<void> {\n await this.ensureTables();\n\n for (const table of Object.keys(LOOKUP_TABLE_DDL)) {\n await this.adapter.execute(\n `DELETE FROM \"${table}\" WHERE \"resourceId\" = ?`,\n [resourceId],\n );\n }\n }\n\n // ---------------------------------------------------------------------------\n // Query (for testing / debugging)\n // ---------------------------------------------------------------------------\n\n /**\n * Get all lookup rows for a given resourceId and table type.\n */\n async getRows<T = Record<string, unknown>>(\n table: string,\n resourceId: string,\n ): Promise<T[]> {\n await this.ensureTables();\n return this.adapter.query<T>(\n `SELECT * FROM \"${table}\" WHERE \"resourceId\" = ?`,\n [resourceId],\n );\n }\n}\n", "/**\n * Indexing Pipeline \u2014 v2\n *\n * Unified orchestrator that combines three indexing concerns into\n * a single `indexResource()` call:\n *\n * 1. **Search columns** \u2014 Extract values from resource JSON via\n * `buildSearchColumns()` and merge into the main table row.\n * 2. **References** \u2014 Extract outgoing references via\n * `extractReferencesV2()` and write to `{RT}_References` table.\n * 3. **Lookup tables** \u2014 Extract HumanName/Address/ContactPoint/Identifier\n * rows via `buildLookupTableRows()` and write to global lookup tables.\n *\n * Design decisions:\n * - Accepts SearchParameterImpl[] (resolved by caller from registry)\n * - All writes use StorageAdapter v2 (? placeholders)\n * - Replace strategy for references and lookup rows (delete + insert)\n * - Search columns are returned (not written) \u2014 caller merges into main row\n * - Pipeline is stateless; dependencies injected via constructor\n *\n * @module fhir-persistence/repo\n */\n\nimport type { StorageAdapter } from '../db/adapter.js';\nimport type { SearchParameterImpl } from '../registry/search-parameter-registry.js';\nimport type { FhirResource } from './types.js';\nimport type { SearchColumnValues, LookupTableRow } from './row-indexer.js';\nimport { buildSearchColumns, buildLookupTableRows } from './row-indexer.js';\nimport type { ReferenceRowV2 } from './reference-indexer.js';\nimport { extractReferencesV2 } from './reference-indexer.js';\nimport { buildDeleteReferencesSQLv2, buildInsertReferencesSQLv2 } from './sql-builder.js';\nimport { LookupTableWriter } from './lookup-table-writer.js';\nimport type { RuntimeProvider } from '../providers/runtime-provider.js';\nimport type { SearchParameterDef } from '../providers/definition-provider.js';\n\n// =============================================================================\n// Section 1: Types\n// =============================================================================\n\n/**\n * Result of indexing a single resource.\n */\nexport interface IndexResult {\n /** Search column values to merge into the main table row. */\n searchColumns: SearchColumnValues;\n /** Reference rows written to {RT}_References table. */\n referenceCount: number;\n /** Lookup table rows written to global lookup tables. */\n lookupRowCount: number;\n}\n\n/**\n * Options for the indexing pipeline.\n */\nexport interface IndexingPipelineOptions {\n /** Enable lookup table writes (default: true). */\n enableLookupTables?: boolean;\n /** Enable reference indexing (default: true). */\n enableReferences?: boolean;\n /** Optional RuntimeProvider for FHIRPath-driven extraction (B3). */\n runtimeProvider?: RuntimeProvider;\n}\n\n// =============================================================================\n// Section 2: IndexingPipeline Class\n// =============================================================================\n\nexport class IndexingPipeline {\n private readonly lookupWriter: LookupTableWriter;\n private readonly options: Required<Omit<IndexingPipelineOptions, 'runtimeProvider'>>;\n private readonly runtimeProvider: RuntimeProvider | undefined;\n\n constructor(\n private readonly adapter: StorageAdapter,\n options?: IndexingPipelineOptions,\n ) {\n this.lookupWriter = new LookupTableWriter(adapter);\n this.runtimeProvider = options?.runtimeProvider;\n this.options = {\n enableLookupTables: options?.enableLookupTables ?? true,\n enableReferences: options?.enableReferences ?? true,\n };\n }\n\n // ---------------------------------------------------------------------------\n // Core: Index a single resource\n // ---------------------------------------------------------------------------\n\n /**\n * Index a resource: extract search columns, write references, write lookup rows.\n *\n * @param resourceType - The FHIR resource type (e.g., \"Patient\").\n * @param resource - The FHIR resource (must have `id`).\n * @param impls - SearchParameterImpl list for this resource type.\n * @returns IndexResult with search columns and write counts.\n */\n async indexResource(\n resourceType: string,\n resource: FhirResource,\n impls: SearchParameterImpl[],\n ): Promise<IndexResult> {\n const resourceId = resource.id;\n if (!resourceId) {\n return { searchColumns: {}, referenceCount: 0, lookupRowCount: 0 };\n }\n\n // 1. Extract search column values (returned, not written)\n const searchColumns = this.runtimeProvider\n ? this.extractViaRuntime(resource, impls)\n : buildSearchColumns(resource, impls);\n\n // 2. Write references (replace strategy)\n let referenceCount = 0;\n if (this.options.enableReferences) {\n referenceCount = await this.writeReferences(resourceType, resource, impls);\n }\n\n // 3. Write lookup table rows (replace strategy)\n let lookupRowCount = 0;\n if (this.options.enableLookupTables) {\n lookupRowCount = await this.writeLookupRows(resource, impls);\n }\n\n return { searchColumns, referenceCount, lookupRowCount };\n }\n\n // ---------------------------------------------------------------------------\n // Delete all index data for a resource\n // ---------------------------------------------------------------------------\n\n /**\n * Remove all index data for a deleted resource.\n *\n * @param resourceType - The FHIR resource type.\n * @param resourceId - The resource ID.\n */\n async deleteIndex(resourceType: string, resourceId: string): Promise<void> {\n // Delete references\n if (this.options.enableReferences) {\n const delSQL = buildDeleteReferencesSQLv2(`${resourceType}_References`);\n await this.adapter.execute(delSQL, [resourceId]);\n }\n\n // Delete lookup rows\n if (this.options.enableLookupTables) {\n await this.lookupWriter.deleteRows(resourceId);\n }\n }\n\n // ---------------------------------------------------------------------------\n // Search columns only (no side effects)\n // ---------------------------------------------------------------------------\n\n /**\n * Extract search column values without writing references or lookup rows.\n * Useful for re-indexing or testing.\n */\n extractSearchColumns(\n resource: FhirResource,\n impls: SearchParameterImpl[],\n ): SearchColumnValues {\n return this.runtimeProvider\n ? this.extractViaRuntime(resource, impls)\n : buildSearchColumns(resource, impls);\n }\n\n /**\n * Extract reference rows without writing them.\n * Useful for re-indexing or testing.\n */\n extractReferences(\n resource: FhirResource,\n impls: SearchParameterImpl[],\n ): ReferenceRowV2[] {\n return this.runtimeProvider\n ? this.extractRefsViaRuntime(resource, impls)\n : extractReferencesV2(resource, impls);\n }\n\n /**\n * Extract lookup table rows without writing them.\n * Useful for re-indexing or testing.\n */\n extractLookupRows(\n resource: FhirResource,\n impls: SearchParameterImpl[],\n ): LookupTableRow[] {\n if (!resource.id) return [];\n return buildLookupTableRows(resource as FhirResource & { id: string }, impls);\n }\n\n // ---------------------------------------------------------------------------\n // Access to inner LookupTableWriter\n // ---------------------------------------------------------------------------\n\n /**\n * Get the underlying LookupTableWriter for direct access.\n */\n getLookupWriter(): LookupTableWriter {\n return this.lookupWriter;\n }\n\n // ---------------------------------------------------------------------------\n // Private: Write references\n // ---------------------------------------------------------------------------\n\n private async writeReferences(\n resourceType: string,\n resource: FhirResource,\n impls: SearchParameterImpl[],\n ): Promise<number> {\n const resourceId = resource.id!;\n const tableName = `${resourceType}_References`;\n\n // Delete existing references\n const delSQL = buildDeleteReferencesSQLv2(tableName);\n await this.adapter.execute(delSQL, [resourceId]);\n\n // Extract new references (prefer RuntimeProvider if available)\n const refs = this.runtimeProvider\n ? this.extractRefsViaRuntime(resource, impls)\n : extractReferencesV2(resource, impls);\n if (refs.length === 0) return 0;\n\n // Insert new references\n const insertSQL = buildInsertReferencesSQLv2(tableName, refs.length);\n const values: unknown[] = [];\n for (const ref of refs) {\n values.push(ref.resourceId, ref.targetType, ref.targetId, ref.code, ref.referenceRaw);\n }\n await this.adapter.execute(insertSQL, values);\n\n return refs.length;\n }\n\n // ---------------------------------------------------------------------------\n // Private: Write lookup rows\n // ---------------------------------------------------------------------------\n\n private async writeLookupRows(\n resource: FhirResource,\n impls: SearchParameterImpl[],\n ): Promise<number> {\n const resourceId = resource.id!;\n const rows = buildLookupTableRows(resource as FhirResource & { id: string }, impls);\n await this.lookupWriter.writeRows(resourceId, rows);\n return rows.length;\n }\n\n // ---------------------------------------------------------------------------\n // Private: RuntimeProvider-based extraction (B3)\n // ---------------------------------------------------------------------------\n\n /**\n * Convert SearchParameterImpl[] to SearchParameterDef[] for RuntimeProvider.\n */\n private implsToDefs(impls: SearchParameterImpl[]): SearchParameterDef[] {\n return impls.map(impl => ({\n resourceType: 'SearchParameter' as const,\n code: impl.code,\n type: impl.type,\n base: impl.resourceTypes,\n expression: impl.expression,\n }));\n }\n\n /**\n * Extract search column values via RuntimeProvider.\n */\n private extractViaRuntime(\n resource: FhirResource,\n impls: SearchParameterImpl[],\n ): SearchColumnValues {\n const defs = this.implsToDefs(impls);\n const raw = this.runtimeProvider!.extractSearchValues(\n resource as Record<string, unknown>,\n defs,\n );\n\n // Map RuntimeProvider output to SearchColumnValues keyed by columnName\n const columns: SearchColumnValues = {};\n for (const impl of impls) {\n const values = raw[impl.code];\n if (!values || values.length === 0) continue;\n\n // Map to the correct DDL column names per strategy\n switch (impl.strategy) {\n case 'column':\n columns[impl.columnName] = values.length === 1 ? values[0] : values;\n break;\n case 'token-column': {\n // v2 DDL: __<name> TEXT (JSON array), __<name>Sort TEXT\n columns[`__${impl.columnName}`] = JSON.stringify(values);\n // Sort column \u2014 first token value as display text\n const sortVal = typeof values[0] === 'string' ? values[0] : String(values[0]);\n columns[`__${impl.columnName}Sort`] = sortVal;\n break;\n }\n case 'lookup-table':\n // v2 DDL: __<name>Sort TEXT\n if (typeof values[0] === 'string') {\n columns[`__${impl.columnName}Sort`] = values[0];\n }\n break;\n }\n }\n\n return columns;\n }\n\n /**\n * Extract references via RuntimeProvider \u2192 ReferenceRowV2[].\n */\n private extractRefsViaRuntime(\n resource: FhirResource,\n impls: SearchParameterImpl[],\n ): ReferenceRowV2[] {\n const resourceId = resource.id;\n if (!resourceId) return [];\n\n const refDefs = this.implsToDefs(impls.filter(i => i.type === 'reference'));\n const extracted = this.runtimeProvider!.extractReferences(\n resource as Record<string, unknown>,\n refDefs,\n );\n\n return extracted.map(ref => ({\n resourceId,\n targetType: ref.targetType,\n targetId: ref.targetId,\n code: ref.code,\n referenceRaw: ref.reference,\n }));\n }\n}\n", "/**\n * Schema Diff \u2014 v2\n *\n * Compares old vs new ResourceTableSet[] to produce SchemaDelta[].\n * Used by IGPersistenceManager to detect what changed when an IG\n * package is upgraded.\n *\n * Key design decisions:\n * - Compares by column name + type (not by position)\n * - Compares indexes by name\n * - Detects SP expression changes for reindex scheduling\n * - Works from in-memory schema objects (no DB introspection)\n *\n * @module fhir-persistence/migration\n */\n\nimport type {\n ResourceTableSet,\n ColumnSchema,\n IndexSchema,\n SearchParamMeta,\n} from '../schema/table-schema.js';\n\n// =============================================================================\n// Section 1: Delta Types\n// =============================================================================\n\nexport type DeltaKind =\n | 'ADD_TABLE'\n | 'DROP_TABLE'\n | 'ADD_COLUMN'\n | 'DROP_COLUMN'\n | 'ALTER_COLUMN'\n | 'ADD_INDEX'\n | 'DROP_INDEX'\n | 'REINDEX';\n\nexport interface SchemaDelta {\n /** The type of schema change. */\n kind: DeltaKind;\n /** The resource type affected (e.g., \"Patient\"). */\n resourceType: string;\n /** The table name affected (e.g., \"Patient\", \"Patient_History\"). */\n tableName: string;\n /** Column details (for ADD_COLUMN, DROP_COLUMN, ALTER_COLUMN). */\n column?: ColumnSchema;\n /** Previous column details (for ALTER_COLUMN). */\n oldColumn?: ColumnSchema;\n /** Index details (for ADD_INDEX, DROP_INDEX). */\n index?: IndexSchema;\n /** Search parameter details (for REINDEX). */\n searchParam?: SearchParamMeta;\n /** The full ResourceTableSet (for ADD_TABLE). */\n tableSet?: ResourceTableSet;\n}\n\n// =============================================================================\n// Section 2: Compare Function\n// =============================================================================\n\n/**\n * Compare two sets of ResourceTableSets and produce a list of deltas.\n *\n * @param oldSets - The previously installed schema (from PackageRegistry).\n * @param newSets - The newly generated schema (from current IG).\n * @returns Array of SchemaDelta describing all changes.\n */\nexport function compareSchemas(\n oldSets: ResourceTableSet[],\n newSets: ResourceTableSet[],\n): SchemaDelta[] {\n const deltas: SchemaDelta[] = [];\n\n const oldMap = new Map<string, ResourceTableSet>();\n for (const ts of oldSets) {\n oldMap.set(ts.resourceType, ts);\n }\n\n const newMap = new Map<string, ResourceTableSet>();\n for (const ts of newSets) {\n newMap.set(ts.resourceType, ts);\n }\n\n // Detect new tables (ADD_TABLE)\n for (const [rt, newTs] of newMap) {\n if (!oldMap.has(rt)) {\n deltas.push({\n kind: 'ADD_TABLE',\n resourceType: rt,\n tableName: rt,\n tableSet: newTs,\n });\n }\n }\n\n // Detect removed tables (DROP_TABLE)\n for (const [rt] of oldMap) {\n if (!newMap.has(rt)) {\n deltas.push({\n kind: 'DROP_TABLE',\n resourceType: rt,\n tableName: rt,\n });\n }\n }\n\n // Detect column/index changes for tables that exist in both\n for (const [rt, newTs] of newMap) {\n const oldTs = oldMap.get(rt);\n if (!oldTs) continue;\n\n // Compare main table columns\n const colDeltas = compareColumns(rt, newTs.main.tableName, oldTs.main.columns, newTs.main.columns);\n deltas.push(...colDeltas);\n\n // Compare main table indexes\n const idxDeltas = compareIndexes(rt, newTs.main.tableName, oldTs.main.indexes, newTs.main.indexes);\n deltas.push(...idxDeltas);\n\n // Compare search param expressions for REINDEX detection\n const reindexDeltas = compareSearchParams(rt, newTs.main.tableName, oldTs.searchParams ?? [], newTs.searchParams ?? []);\n deltas.push(...reindexDeltas);\n }\n\n return deltas;\n}\n\n// =============================================================================\n// Section 3: Column Comparison\n// =============================================================================\n\nfunction compareColumns(\n resourceType: string,\n tableName: string,\n oldCols: ColumnSchema[],\n newCols: ColumnSchema[],\n): SchemaDelta[] {\n const deltas: SchemaDelta[] = [];\n\n const oldByName = new Map<string, ColumnSchema>();\n for (const col of oldCols) {\n oldByName.set(col.name, col);\n }\n\n const newByName = new Map<string, ColumnSchema>();\n for (const col of newCols) {\n newByName.set(col.name, col);\n }\n\n // New columns\n for (const [name, col] of newByName) {\n if (!oldByName.has(name)) {\n deltas.push({ kind: 'ADD_COLUMN', resourceType, tableName, column: col });\n }\n }\n\n // Removed columns\n for (const [name, col] of oldByName) {\n if (!newByName.has(name)) {\n deltas.push({ kind: 'DROP_COLUMN', resourceType, tableName, column: col });\n }\n }\n\n // Changed columns (type changed)\n for (const [name, newCol] of newByName) {\n const oldCol = oldByName.get(name);\n if (oldCol && oldCol.type !== newCol.type) {\n deltas.push({ kind: 'ALTER_COLUMN', resourceType, tableName, column: newCol, oldColumn: oldCol });\n }\n }\n\n return deltas;\n}\n\n// =============================================================================\n// Section 4: Index Comparison\n// =============================================================================\n\nfunction compareIndexes(\n resourceType: string,\n tableName: string,\n oldIdxs: IndexSchema[],\n newIdxs: IndexSchema[],\n): SchemaDelta[] {\n const deltas: SchemaDelta[] = [];\n\n const oldByName = new Map<string, IndexSchema>();\n for (const idx of oldIdxs) {\n oldByName.set(idx.name, idx);\n }\n\n const newByName = new Map<string, IndexSchema>();\n for (const idx of newIdxs) {\n newByName.set(idx.name, idx);\n }\n\n // New indexes\n for (const [name, idx] of newByName) {\n if (!oldByName.has(name)) {\n deltas.push({ kind: 'ADD_INDEX', resourceType, tableName, index: idx });\n }\n }\n\n // Removed indexes\n for (const [name, idx] of oldByName) {\n if (!newByName.has(name)) {\n deltas.push({ kind: 'DROP_INDEX', resourceType, tableName, index: idx });\n }\n }\n\n return deltas;\n}\n\n// =============================================================================\n// Section 5: Search Param Expression Comparison (REINDEX detection)\n// =============================================================================\n\nfunction compareSearchParams(\n resourceType: string,\n tableName: string,\n oldParams: SearchParamMeta[],\n newParams: SearchParamMeta[],\n): SchemaDelta[] {\n const deltas: SchemaDelta[] = [];\n\n const oldByCode = new Map<string, SearchParamMeta>();\n for (const sp of oldParams) {\n oldByCode.set(sp.code, sp);\n }\n\n for (const newSp of newParams) {\n const oldSp = oldByCode.get(newSp.code);\n if (oldSp && oldSp.expression !== newSp.expression) {\n deltas.push({\n kind: 'REINDEX',\n resourceType,\n tableName,\n searchParam: newSp,\n });\n }\n }\n\n return deltas;\n}\n", "/**\n * Migration Generator \u2014 v2\n *\n * Generates SQL DDL statements from SchemaDelta[].\n * Dialect-aware: produces SQLite or PostgreSQL DDL.\n *\n * Key design decisions:\n * - ADD_TABLE delegates to existing DDLGenerator (generateResourceDDL)\n * - ADD_COLUMN \u2192 ALTER TABLE ADD COLUMN\n * - DROP_COLUMN \u2192 ALTER TABLE DROP COLUMN (PG only; SQLite ignores)\n * - ADD_INDEX \u2192 CREATE INDEX IF NOT EXISTS\n * - DROP_INDEX \u2192 DROP INDEX IF EXISTS\n * - REINDEX \u2192 no DDL (metadata only, handled by ReindexScheduler)\n * - ALTER_COLUMN \u2192 not supported in SQLite (logged as warning)\n *\n * @module fhir-persistence/migration\n */\n\nimport type { SchemaDelta } from './schema-diff.js';\nimport type { DDLDialect } from '../schema/ddl-generator.js';\nimport {\n generateResourceDDL,\n generateCreateIndex,\n} from '../schema/ddl-generator.js';\n\n// =============================================================================\n// Section 1: Types\n// =============================================================================\n\nexport interface GeneratedMigration {\n /** SQL statements to apply (up). */\n up: string[];\n /** SQL statements to revert (down). Best-effort; some are irreversible. */\n down: string[];\n /** Deltas that require reindex (no DDL, just scheduling). */\n reindexDeltas: SchemaDelta[];\n /** Human-readable description of changes. */\n description: string;\n}\n\n// =============================================================================\n// Section 2: Generate Migration\n// =============================================================================\n\n/**\n * Generate SQL DDL from a list of schema deltas.\n *\n * @param deltas - Schema changes to apply.\n * @param dialect - Target SQL dialect.\n * @returns Generated migration with up/down SQL and reindex info.\n */\nexport function generateMigration(\n deltas: SchemaDelta[],\n dialect: DDLDialect,\n): GeneratedMigration {\n const up: string[] = [];\n const down: string[] = [];\n const reindexDeltas: SchemaDelta[] = [];\n const descriptions: string[] = [];\n\n for (const delta of deltas) {\n switch (delta.kind) {\n case 'ADD_TABLE': {\n if (delta.tableSet) {\n const ddlStatements = generateResourceDDL(delta.tableSet, dialect);\n up.push(...ddlStatements);\n // Down: drop all 3 tables\n down.push(\n `DROP TABLE IF EXISTS \"${delta.resourceType}_References\";`,\n `DROP TABLE IF EXISTS \"${delta.resourceType}_History\";`,\n `DROP TABLE IF EXISTS \"${delta.resourceType}\";`,\n );\n descriptions.push(`Add table ${delta.resourceType}`);\n }\n break;\n }\n\n case 'DROP_TABLE': {\n up.push(\n `DROP TABLE IF EXISTS \"${delta.resourceType}_References\";`,\n `DROP TABLE IF EXISTS \"${delta.resourceType}_History\";`,\n `DROP TABLE IF EXISTS \"${delta.resourceType}\";`,\n );\n // Down: cannot restore (forward-only for IG migrations)\n descriptions.push(`Drop table ${delta.resourceType}`);\n break;\n }\n\n case 'ADD_COLUMN': {\n if (delta.column) {\n const typeName = mapColumnTypeForDialect(delta.column.type, dialect);\n let ddl = `ALTER TABLE \"${delta.tableName}\" ADD COLUMN \"${delta.column.name}\" ${typeName}`;\n if (delta.column.notNull && delta.column.defaultValue !== undefined) {\n ddl += ` NOT NULL DEFAULT ${delta.column.defaultValue}`;\n }\n ddl += ';';\n up.push(ddl);\n\n // Down: DROP COLUMN (PG only, SQLite doesn't support it pre-3.35)\n if (dialect === 'postgres') {\n down.push(`ALTER TABLE \"${delta.tableName}\" DROP COLUMN IF EXISTS \"${delta.column.name}\";`);\n }\n descriptions.push(`Add column ${delta.tableName}.${delta.column.name}`);\n }\n break;\n }\n\n case 'DROP_COLUMN': {\n if (delta.column) {\n if (dialect === 'postgres') {\n up.push(`ALTER TABLE \"${delta.tableName}\" DROP COLUMN IF EXISTS \"${delta.column.name}\";`);\n }\n // SQLite: DROP COLUMN supported since 3.35.0\n if (dialect === 'sqlite') {\n up.push(`ALTER TABLE \"${delta.tableName}\" DROP COLUMN \"${delta.column.name}\";`);\n }\n descriptions.push(`Drop column ${delta.tableName}.${delta.column.name}`);\n }\n break;\n }\n\n case 'ADD_INDEX': {\n if (delta.index) {\n const sql = generateCreateIndex(delta.index, delta.tableName, dialect);\n if (sql) {\n up.push(sql);\n down.push(`DROP INDEX IF EXISTS \"${delta.index.name}\";`);\n }\n descriptions.push(`Add index ${delta.index.name}`);\n }\n break;\n }\n\n case 'DROP_INDEX': {\n if (delta.index) {\n up.push(`DROP INDEX IF EXISTS \"${delta.index.name}\";`);\n descriptions.push(`Drop index ${delta.index.name}`);\n }\n break;\n }\n\n case 'ALTER_COLUMN': {\n // SQLite doesn't support ALTER COLUMN type changes\n // PG: ALTER TABLE ... ALTER COLUMN ... TYPE ...\n if (dialect === 'postgres' && delta.column) {\n up.push(\n `ALTER TABLE \"${delta.tableName}\" ALTER COLUMN \"${delta.column.name}\" TYPE ${delta.column.type};`,\n );\n if (delta.oldColumn) {\n down.push(\n `ALTER TABLE \"${delta.tableName}\" ALTER COLUMN \"${delta.column.name}\" TYPE ${delta.oldColumn.type};`,\n );\n }\n descriptions.push(`Alter column ${delta.tableName}.${delta.column.name} type`);\n }\n break;\n }\n\n case 'REINDEX': {\n reindexDeltas.push(delta);\n descriptions.push(`Reindex ${delta.resourceType} for SP ${delta.searchParam?.code ?? '?'}`);\n break;\n }\n }\n }\n\n return {\n up,\n down,\n reindexDeltas,\n description: descriptions.join('; ') || 'No changes',\n };\n}\n\n// =============================================================================\n// Section 3: Type Mapping Helper\n// =============================================================================\n\n/**\n * Map a logical SqlColumnType to dialect-specific string.\n * Mirrors DDLGenerator.mapColumnType but exported for migration use.\n */\nfunction mapColumnTypeForDialect(type: string, dialect: DDLDialect): string {\n if (dialect === 'postgres') return type;\n\n switch (type) {\n case 'BOOLEAN': return 'INTEGER';\n case 'TIMESTAMPTZ': return 'TEXT';\n case 'TIMESTAMPTZ[]': return 'TEXT';\n case 'TEXT[]': return 'TEXT';\n case 'DOUBLE PRECISION': return 'REAL';\n case 'DOUBLE PRECISION[]': return 'TEXT';\n case 'DATE': return 'TEXT';\n case 'DATE[]': return 'TEXT';\n case 'NUMERIC': return 'REAL';\n case 'BIGINT': return 'INTEGER';\n default: return type;\n }\n}\n", "/**\n * Package Registry Repository \u2014 v2\n *\n * Tracks installed FHIR IG packages (name, version, checksum) in\n * the `_packages` table. Used by IGPersistenceManager to detect\n * new/upgrade/consistent state via checksum comparison.\n *\n * Key design decisions:\n * - Uses StorageAdapter (not DatabaseClient)\n * - `?` placeholders for SQLite compatibility\n * - Stores serialized ResourceTableSet[] as `schema_snapshot` for SchemaDiff\n * - Checksum is a hash of the package content (e.g., SHA-256)\n *\n * @module fhir-persistence/registry\n */\n\nimport type { StorageAdapter } from '../db/adapter.js';\n\n// =============================================================================\n// Section 1: Types\n// =============================================================================\n\nexport type PackageStatus = 'active' | 'superseded';\n\nexport interface InstalledPackage {\n /** Package name (e.g., \"hl7.fhir.r4.core\"). */\n name: string;\n /** Package version (e.g., \"4.0.1\"). */\n version: string;\n /** Content checksum for change detection. */\n checksum: string;\n /** Serialized ResourceTableSet[] JSON for SchemaDiff. */\n schemaSnapshot: string | null;\n /** When this package was installed/updated. */\n installedAt: string;\n /** Package status: active or superseded. */\n status: PackageStatus;\n}\n\nexport interface SchemaVersionRecord {\n /** Auto-incrementing version number. */\n version: number;\n /** JSON snapshot of active package names+versions at this schema version. */\n packageList: string;\n /** Description of the schema change. */\n description: string;\n /** When this schema version was applied. */\n appliedAt: string;\n}\n\n// =============================================================================\n// Section 2: DDL\n// =============================================================================\n\nconst PACKAGES_TABLE = '_packages';\n\nconst CREATE_PACKAGES_TABLE = `\nCREATE TABLE IF NOT EXISTS \"${PACKAGES_TABLE}\" (\n \"name\" TEXT NOT NULL,\n \"version\" TEXT NOT NULL,\n \"checksum\" TEXT NOT NULL,\n \"schemaSnapshot\" TEXT,\n \"installedAt\" TEXT NOT NULL DEFAULT (datetime('now')),\n \"status\" TEXT NOT NULL DEFAULT 'active',\n PRIMARY KEY (\"name\", \"version\")\n);\n`;\n\nconst SCHEMA_VERSION_TABLE = '_schema_version';\n\nconst CREATE_SCHEMA_VERSION_TABLE = `\nCREATE TABLE IF NOT EXISTS \"${SCHEMA_VERSION_TABLE}\" (\n \"version\" INTEGER NOT NULL PRIMARY KEY,\n \"packageList\" TEXT NOT NULL,\n \"description\" TEXT NOT NULL DEFAULT '',\n \"appliedAt\" TEXT NOT NULL DEFAULT (datetime('now'))\n);\n`;\n\n// =============================================================================\n// Section 3: PackageRegistryRepo\n// =============================================================================\n\nexport class PackageRegistryRepo {\n constructor(private readonly adapter: StorageAdapter) { }\n\n /**\n * Ensure the packages tracking table exists.\n */\n async ensureTable(): Promise<void> {\n await this.adapter.execute(CREATE_PACKAGES_TABLE);\n }\n\n /**\n * Get the active version of a package by name.\n */\n async getPackage(name: string): Promise<InstalledPackage | undefined> {\n await this.ensureTable();\n return this.adapter.queryOne<InstalledPackage>(\n `SELECT \"name\", \"version\", \"checksum\", \"schemaSnapshot\", \"installedAt\", \"status\" FROM \"${PACKAGES_TABLE}\" WHERE \"name\" = ? AND \"status\" = 'active'`,\n [name],\n );\n }\n\n /**\n * Get all installed packages (all statuses).\n */\n async getInstalledPackages(): Promise<InstalledPackage[]> {\n await this.ensureTable();\n return this.adapter.query<InstalledPackage>(\n `SELECT \"name\", \"version\", \"checksum\", \"schemaSnapshot\", \"installedAt\", \"status\" FROM \"${PACKAGES_TABLE}\" ORDER BY \"name\", \"version\"`,\n );\n }\n\n /**\n * Get only active packages.\n */\n async getActivePackages(): Promise<InstalledPackage[]> {\n await this.ensureTable();\n return this.adapter.query<InstalledPackage>(\n `SELECT \"name\", \"version\", \"checksum\", \"schemaSnapshot\", \"installedAt\", \"status\" FROM \"${PACKAGES_TABLE}\" WHERE \"status\" = 'active' ORDER BY \"name\"`,\n );\n }\n\n /**\n * Register a package version.\n *\n * When a new version is registered for the same package name:\n * 1. Previous active versions are marked as 'superseded'\n * 2. The new version is inserted as 'active'\n * 3. A schema_version record is created with the package_list snapshot\n */\n async registerPackage(\n pkg: Omit<InstalledPackage, 'installedAt' | 'status'>,\n description?: string,\n ): Promise<void> {\n await this.ensureTable();\n\n // Supersede old active versions of this package\n await this.adapter.execute(\n `UPDATE \"${PACKAGES_TABLE}\" SET \"status\" = 'superseded' WHERE \"name\" = ? AND \"status\" = 'active'`,\n [pkg.name],\n );\n\n // Insert the new version as active\n await this.adapter.execute(\n `INSERT OR REPLACE INTO \"${PACKAGES_TABLE}\" (\"name\", \"version\", \"checksum\", \"schemaSnapshot\", \"status\") VALUES (?, ?, ?, ?, 'active')`,\n [pkg.name, pkg.version, pkg.checksum, pkg.schemaSnapshot ?? null],\n );\n\n // Record schema version with active package list snapshot\n await this.recordSchemaVersion(description ?? `Register ${pkg.name}@${pkg.version}`);\n }\n\n /**\n * Insert or update a package record (backward-compatible).\n *\n * Uses INSERT OR REPLACE (SQLite UPSERT) to handle both new and upgraded packages.\n */\n async upsertPackage(pkg: Omit<InstalledPackage, 'installedAt' | 'status'>): Promise<void> {\n await this.ensureTable();\n\n // Supersede old active versions\n await this.adapter.execute(\n `UPDATE \"${PACKAGES_TABLE}\" SET \"status\" = 'superseded' WHERE \"name\" = ? AND \"status\" = 'active'`,\n [pkg.name],\n );\n\n await this.adapter.execute(\n `INSERT OR REPLACE INTO \"${PACKAGES_TABLE}\" (\"name\", \"version\", \"checksum\", \"schemaSnapshot\", \"status\") VALUES (?, ?, ?, ?, 'active')`,\n [pkg.name, pkg.version, pkg.checksum, pkg.schemaSnapshot ?? null],\n );\n }\n\n /**\n * Remove all versions of a package.\n */\n async removePackage(name: string): Promise<void> {\n await this.ensureTable();\n await this.adapter.execute(\n `DELETE FROM \"${PACKAGES_TABLE}\" WHERE \"name\" = ?`,\n [name],\n );\n }\n\n /**\n * Check if a package needs update by comparing checksums.\n *\n * Returns:\n * - 'new' if the package is not installed (no active version)\n * - 'upgrade' if the checksum differs\n * - 'consistent' if the checksum matches\n */\n async checkStatus(name: string, checksum: string): Promise<'new' | 'upgrade' | 'consistent'> {\n const existing = await this.getPackage(name);\n if (!existing) return 'new';\n if (existing.checksum !== checksum) return 'upgrade';\n return 'consistent';\n }\n\n // ---------------------------------------------------------------------------\n // Schema Version Management\n // ---------------------------------------------------------------------------\n\n /**\n * Ensure the schema version table exists.\n */\n async ensureSchemaVersionTable(): Promise<void> {\n await this.adapter.execute(CREATE_SCHEMA_VERSION_TABLE);\n }\n\n /**\n * Record a schema version with the current active package list.\n */\n async recordSchemaVersion(description: string): Promise<void> {\n await this.ensureSchemaVersionTable();\n\n // Get next version number\n const row = await this.adapter.queryOne<{ maxV: number | null }>(\n `SELECT MAX(\"version\") as \"maxV\" FROM \"${SCHEMA_VERSION_TABLE}\"`,\n );\n const nextVersion = (row?.maxV ?? 0) + 1;\n\n // Build package list snapshot from active packages\n const active = await this.getActivePackages();\n const packageList = JSON.stringify(\n active.map(p => ({ name: p.name, version: p.version })),\n );\n\n await this.adapter.execute(\n `INSERT INTO \"${SCHEMA_VERSION_TABLE}\" (\"version\", \"packageList\", \"description\") VALUES (?, ?, ?)`,\n [nextVersion, packageList, description],\n );\n }\n\n /**\n * Get all schema version records.\n */\n async getSchemaVersions(): Promise<SchemaVersionRecord[]> {\n await this.ensureSchemaVersionTable();\n return this.adapter.query<SchemaVersionRecord>(\n `SELECT \"version\", \"packageList\", \"description\", \"appliedAt\" FROM \"${SCHEMA_VERSION_TABLE}\" ORDER BY \"version\"`,\n );\n }\n\n /**\n * Get the latest schema version record.\n */\n async getLatestSchemaVersion(): Promise<SchemaVersionRecord | undefined> {\n await this.ensureSchemaVersionTable();\n return this.adapter.queryOne<SchemaVersionRecord>(\n `SELECT \"version\", \"packageList\", \"description\", \"appliedAt\" FROM \"${SCHEMA_VERSION_TABLE}\" ORDER BY \"version\" DESC LIMIT 1`,\n );\n }\n}\n", "/**\n * Schema Migration Runner (v2)\n *\n * Manages incremental database schema migrations with version tracking\n * using StorageAdapter (SQLite / PostgreSQL).\n *\n * Features:\n * - Automatic `_migrations` tracking table creation\n * - Sequential up/down migration execution\n * - Idempotent: skips already-applied migrations\n * - Transaction-per-migration for safety\n * - IG migrations (forward-only, auto-versioned)\n * - Status reporting (current version, pending migrations)\n *\n * @module fhir-persistence/migrations\n */\n\nimport type { StorageAdapter } from '../db/adapter.js';\nimport type { GeneratedMigration } from '../migration/migration-generator.js';\n\n/**\n * v2 migration types \u2014 adds `type` field for IG vs file distinction.\n */\nexport interface MigrationV2 {\n /** Unique version number. Must be positive integer. */\n version: number;\n /** Human-readable description. */\n description: string;\n /** SQL statements to apply this migration. */\n up: string[];\n /** SQL statements to revert this migration. Empty for IG migrations (forward-only). */\n down: string[];\n /** Migration source type: 'ig' for IG-driven, 'file' for manual file-based. */\n type: 'ig' | 'file';\n}\n\nexport interface MigrationRecordV2 {\n version: number;\n description: string;\n type: string;\n applied_at: string;\n}\n\nexport interface MigrationResultV2 {\n action: 'up' | 'down' | 'none';\n applied: number[];\n currentVersion: number;\n errors: Array<{ version: number; error: string }>;\n}\n\nexport interface MigrationStatusV2 {\n currentVersion: number;\n appliedVersions: number[];\n availableVersions: number[];\n pendingVersions: number[];\n}\n\nconst TRACKING_TABLE_V2 = '_migrations';\n\nconst CREATE_TRACKING_TABLE_V2_SQLITE = `\nCREATE TABLE IF NOT EXISTS \"${TRACKING_TABLE_V2}\" (\n \"version\" INTEGER PRIMARY KEY,\n \"description\" TEXT NOT NULL,\n \"type\" TEXT NOT NULL DEFAULT 'file',\n \"applied_at\" TEXT NOT NULL DEFAULT (datetime('now'))\n);\n`;\n\n/**\n * v2: Manages schema migrations using StorageAdapter (SQLite / PG).\n *\n * Key differences from v1:\n * - Uses `StorageAdapter` instead of `DatabaseClient`\n * - `?` placeholders instead of `$1`\n * - Supports `type` field: 'ig' | 'file'\n * - IG migrations are forward-only (no down/revert)\n * - Tracking table uses `datetime('now')` for SQLite\n */\nexport class MigrationRunnerV2 {\n private readonly adapter: StorageAdapter;\n private readonly migrations: MigrationV2[];\n\n constructor(adapter: StorageAdapter, migrations: MigrationV2[] = []) {\n this.adapter = adapter;\n this.migrations = [...migrations].sort((a, b) => a.version - b.version);\n }\n\n // ---------------------------------------------------------------------------\n // Public API\n // ---------------------------------------------------------------------------\n\n /**\n * Ensure the tracking table exists.\n */\n async ensureTrackingTable(): Promise<void> {\n await this.adapter.execute(CREATE_TRACKING_TABLE_V2_SQLITE);\n }\n\n /**\n * Apply all pending migrations (or up to a target version).\n */\n async up(targetVersion?: number): Promise<MigrationResultV2> {\n await this.ensureTrackingTable();\n\n const applied = await this.getAppliedVersions();\n const target = targetVersion ?? Math.max(...this.migrations.map((m) => m.version), 0);\n\n const pending = this.migrations.filter(\n (m) => !applied.has(m.version) && m.version <= target,\n );\n\n if (pending.length === 0) {\n return {\n action: 'none',\n applied: [],\n currentVersion: this.maxApplied(applied),\n errors: [],\n };\n }\n\n const appliedVersions: number[] = [];\n const errors: Array<{ version: number; error: string }> = [];\n\n for (const migration of pending) {\n try {\n await this.applyMigration(migration);\n appliedVersions.push(migration.version);\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n errors.push({ version: migration.version, error: message });\n break;\n }\n }\n\n const finalApplied = await this.getAppliedVersions();\n return {\n action: 'up',\n applied: appliedVersions,\n currentVersion: this.maxApplied(finalApplied),\n errors,\n };\n }\n\n /**\n * Revert migrations down to a target version.\n * IG migrations (type='ig') cannot be reverted \u2014 they are skipped.\n */\n async down(targetVersion: number = 0): Promise<MigrationResultV2> {\n await this.ensureTrackingTable();\n\n const applied = await this.getAppliedVersions();\n\n const toRevert = this.migrations\n .filter((m) => applied.has(m.version) && m.version > targetVersion)\n .filter((m) => m.type !== 'ig') // IG migrations are forward-only\n .sort((a, b) => b.version - a.version);\n\n if (toRevert.length === 0) {\n return {\n action: 'none',\n applied: [],\n currentVersion: this.maxApplied(applied),\n errors: [],\n };\n }\n\n const revertedVersions: number[] = [];\n const errors: Array<{ version: number; error: string }> = [];\n\n for (const migration of toRevert) {\n try {\n await this.revertMigration(migration);\n revertedVersions.push(migration.version);\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n errors.push({ version: migration.version, error: message });\n break;\n }\n }\n\n const finalApplied = await this.getAppliedVersions();\n return {\n action: 'down',\n applied: revertedVersions,\n currentVersion: this.maxApplied(finalApplied),\n errors,\n };\n }\n\n /**\n * Get the current migration status.\n */\n async status(): Promise<MigrationStatusV2> {\n await this.ensureTrackingTable();\n\n const applied = await this.getAppliedVersions();\n const availableVersions = this.migrations.map((m) => m.version);\n const pendingVersions = availableVersions.filter((v) => !applied.has(v));\n\n return {\n currentVersion: this.maxApplied(applied),\n appliedVersions: [...applied].sort((a, b) => a - b),\n availableVersions,\n pendingVersions,\n };\n }\n\n /**\n * Get all applied migration records.\n */\n async getRecords(): Promise<MigrationRecordV2[]> {\n await this.ensureTrackingTable();\n return this.adapter.query<MigrationRecordV2>(\n `SELECT \"version\", \"description\", \"type\", \"applied_at\" FROM \"${TRACKING_TABLE_V2}\" ORDER BY \"version\"`,\n );\n }\n\n /**\n * Apply an IG-generated migration directly.\n *\n * Assigns the next available version number automatically.\n * This is the primary entry point for IGPersistenceManager.\n */\n async applyIGMigration(generated: GeneratedMigration): Promise<MigrationResultV2> {\n await this.ensureTrackingTable();\n\n const applied = await this.getAppliedVersions();\n const maxVersion = this.maxApplied(applied);\n const nextVersion = maxVersion + 1;\n\n const migration: MigrationV2 = {\n version: nextVersion,\n description: generated.description,\n up: generated.up,\n down: [], // IG migrations are forward-only\n type: 'ig',\n };\n\n try {\n await this.applyMigration(migration);\n return {\n action: 'up',\n applied: [nextVersion],\n currentVersion: nextVersion,\n errors: [],\n };\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n return {\n action: 'up',\n applied: [],\n currentVersion: maxVersion,\n errors: [{ version: nextVersion, error: message }],\n };\n }\n }\n\n // ---------------------------------------------------------------------------\n // Private\n // ---------------------------------------------------------------------------\n\n private async getAppliedVersions(): Promise<Set<number>> {\n const rows = await this.adapter.query<{ version: number }>(\n `SELECT \"version\" FROM \"${TRACKING_TABLE_V2}\"`,\n );\n return new Set(rows.map((r) => r.version));\n }\n\n private async applyMigration(migration: MigrationV2): Promise<void> {\n await this.adapter.transaction((tx) => {\n for (const sql of migration.up) {\n tx.execute(sql);\n }\n tx.execute(\n `INSERT INTO \"${TRACKING_TABLE_V2}\" (\"version\", \"description\", \"type\") VALUES (?, ?, ?)`,\n [migration.version, migration.description, migration.type],\n );\n });\n }\n\n private async revertMigration(migration: MigrationV2): Promise<void> {\n await this.adapter.transaction((tx) => {\n for (const sql of migration.down) {\n tx.execute(sql);\n }\n tx.execute(\n `DELETE FROM \"${TRACKING_TABLE_V2}\" WHERE \"version\" = ?`,\n [migration.version],\n );\n });\n }\n\n private maxApplied(versions: Set<number>): number {\n if (versions.size === 0) return 0;\n return Math.max(...versions);\n }\n}\n", "/**\n * Reindex Scheduler \u2014 v2\n *\n * Schedules and tracks asynchronous reindex jobs when a SearchParameter\n * expression changes (detected by SchemaDiff as REINDEX deltas).\n *\n * Design decisions:\n * - Jobs stored in `_reindex_jobs` table (auto-created)\n * - Keyset pagination: processes resources by lastUpdated > cursor\n * - Jobs are independent per (resourceType, searchParamCode)\n * - Status tracking: pending / running / completed / failed\n *\n * @module fhir-persistence/migration\n */\n\nimport type { StorageAdapter } from '../db/adapter.js';\nimport type { SchemaDelta } from './schema-diff.js';\n\n// =============================================================================\n// Section 1: Types\n// =============================================================================\n\nexport type ReindexJobStatus = 'pending' | 'running' | 'completed' | 'failed';\n\nexport interface ReindexJob {\n /** Auto-assigned job ID. */\n id: number;\n /** Resource type to reindex (e.g., \"Patient\"). */\n resourceType: string;\n /** Search parameter code that changed (e.g., \"birthdate\"). */\n searchParamCode: string;\n /** New FHIRPath expression. */\n expression: string;\n /** Current job status. */\n status: ReindexJobStatus;\n /** Cursor for keyset pagination (lastUpdated of last processed resource). */\n cursor: string | null;\n /** Number of resources processed so far. */\n processedCount: number;\n /** When the job was created. */\n createdAt: string;\n /** When the job was last updated. */\n updatedAt: string;\n}\n\n// =============================================================================\n// Section 2: DDL\n// =============================================================================\n\nconst REINDEX_JOBS_TABLE = '_reindex_jobs';\n\nconst CREATE_REINDEX_JOBS_TABLE = `\nCREATE TABLE IF NOT EXISTS \"${REINDEX_JOBS_TABLE}\" (\n \"id\" INTEGER PRIMARY KEY AUTOINCREMENT,\n \"resourceType\" TEXT NOT NULL,\n \"searchParamCode\" TEXT NOT NULL,\n \"expression\" TEXT NOT NULL,\n \"status\" TEXT NOT NULL DEFAULT 'pending',\n \"cursor\" TEXT,\n \"processedCount\" INTEGER NOT NULL DEFAULT 0,\n \"createdAt\" TEXT NOT NULL DEFAULT (datetime('now')),\n \"updatedAt\" TEXT NOT NULL DEFAULT (datetime('now'))\n);\n`;\n\n// =============================================================================\n// Section 3: ReindexScheduler\n// =============================================================================\n\nexport class ReindexScheduler {\n constructor(private readonly adapter: StorageAdapter) {}\n\n /**\n * Ensure the reindex jobs table exists.\n */\n async ensureTable(): Promise<void> {\n await this.adapter.execute(CREATE_REINDEX_JOBS_TABLE);\n }\n\n /**\n * Schedule reindex jobs from REINDEX deltas.\n *\n * @param deltas - REINDEX deltas from SchemaDiff (filtered by caller).\n * @returns Number of jobs scheduled.\n */\n async schedule(deltas: SchemaDelta[]): Promise<number> {\n await this.ensureTable();\n\n let count = 0;\n for (const delta of deltas) {\n if (delta.kind !== 'REINDEX' || !delta.searchParam) continue;\n\n await this.adapter.execute(\n `INSERT INTO \"${REINDEX_JOBS_TABLE}\" (\"resourceType\", \"searchParamCode\", \"expression\") VALUES (?, ?, ?)`,\n [delta.resourceType, delta.searchParam.code, delta.searchParam.expression],\n );\n count++;\n }\n\n return count;\n }\n\n /**\n * Get all pending reindex jobs.\n */\n async getPendingJobs(): Promise<ReindexJob[]> {\n await this.ensureTable();\n return this.adapter.query<ReindexJob>(\n `SELECT * FROM \"${REINDEX_JOBS_TABLE}\" WHERE \"status\" = 'pending' ORDER BY \"id\"`,\n );\n }\n\n /**\n * Get a specific job by ID.\n */\n async getJob(id: number): Promise<ReindexJob | undefined> {\n await this.ensureTable();\n return this.adapter.queryOne<ReindexJob>(\n `SELECT * FROM \"${REINDEX_JOBS_TABLE}\" WHERE \"id\" = ?`,\n [id],\n );\n }\n\n /**\n * Get all jobs (any status).\n */\n async getAllJobs(): Promise<ReindexJob[]> {\n await this.ensureTable();\n return this.adapter.query<ReindexJob>(\n `SELECT * FROM \"${REINDEX_JOBS_TABLE}\" ORDER BY \"id\"`,\n );\n }\n\n /**\n * Update job status and cursor.\n */\n async updateJob(\n id: number,\n update: { status?: ReindexJobStatus; cursor?: string; processedCount?: number },\n ): Promise<void> {\n const sets: string[] = [];\n const values: unknown[] = [];\n\n if (update.status !== undefined) {\n sets.push('\"status\" = ?');\n values.push(update.status);\n }\n if (update.cursor !== undefined) {\n sets.push('\"cursor\" = ?');\n values.push(update.cursor);\n }\n if (update.processedCount !== undefined) {\n sets.push('\"processedCount\" = ?');\n values.push(update.processedCount);\n }\n\n sets.push(`\"updatedAt\" = datetime('now')`);\n values.push(id);\n\n await this.adapter.execute(\n `UPDATE \"${REINDEX_JOBS_TABLE}\" SET ${sets.join(', ')} WHERE \"id\" = ?`,\n values,\n );\n }\n\n /**\n * Get status summary of all jobs.\n */\n async getStatus(): Promise<{ pending: number; running: number; completed: number; failed: number }> {\n await this.ensureTable();\n const rows = await this.adapter.query<{ status: string; cnt: number }>(\n `SELECT \"status\", COUNT(*) as cnt FROM \"${REINDEX_JOBS_TABLE}\" GROUP BY \"status\"`,\n );\n\n const result = { pending: 0, running: 0, completed: 0, failed: 0 };\n for (const row of rows) {\n if (row.status in result) {\n result[row.status as keyof typeof result] = row.cnt;\n }\n }\n return result;\n }\n}\n", "/**\n * IG Persistence Manager \u2014 v2\n *\n * Orchestrates the initialization flow when an IG package is loaded:\n * 1. Check PackageRegistry for existing installation (checksum compare)\n * 2. Three-way branch: new / upgrade / consistent\n * 3. For new/upgrade: SchemaDiff \u2192 MigrationGenerator \u2192 MigrationRunnerV2\n * 4. Schedule reindex jobs for SP expression changes\n *\n * @module fhir-persistence/migration\n */\n\nimport type { StorageAdapter } from '../db/adapter.js';\nimport type { ResourceTableSet } from '../schema/table-schema.js';\nimport type { DDLDialect } from '../schema/ddl-generator.js';\nimport { PackageRegistryRepo } from '../registry/package-registry-repo.js';\nimport { compareSchemas } from './schema-diff.js';\nimport { generateMigration } from './migration-generator.js';\nimport { MigrationRunnerV2 } from '../migrations/migration-runner.js';\nimport { ReindexScheduler } from './reindex-scheduler.js';\n\n// =============================================================================\n// Section 1: Types\n// =============================================================================\n\nexport interface IGPackageInput {\n /** Package name (e.g., \"hl7.fhir.r4.core\"). */\n name: string;\n /** Package version (e.g., \"4.0.1\"). */\n version: string;\n /** Content checksum for change detection. */\n checksum: string;\n /** The new schema table sets generated from this package. */\n tableSets: ResourceTableSet[];\n}\n\nexport type IGInitAction = 'new' | 'upgrade' | 'consistent';\n\nexport interface IGInitResult {\n /** What action was taken. */\n action: IGInitAction;\n /** Package name. */\n packageName: string;\n /** Package version. */\n packageVersion: string;\n /** Number of DDL statements applied (0 for 'consistent'). */\n ddlCount: number;\n /** Number of reindex jobs scheduled. */\n reindexCount: number;\n /** Error message if any step failed. */\n error?: string;\n}\n\n// =============================================================================\n// Section 2: IGPersistenceManager\n// =============================================================================\n\nexport class IGPersistenceManager {\n private readonly dialect: DDLDialect;\n private readonly packageRepo: PackageRegistryRepo;\n private readonly migrationRunner: MigrationRunnerV2;\n private readonly reindexScheduler: ReindexScheduler;\n\n constructor(adapter: StorageAdapter, dialect: DDLDialect = 'sqlite') {\n this.dialect = dialect;\n this.packageRepo = new PackageRegistryRepo(adapter);\n this.migrationRunner = new MigrationRunnerV2(adapter);\n this.reindexScheduler = new ReindexScheduler(adapter);\n }\n\n /**\n * Initialize an IG package \u2014 the main entry point.\n *\n * Three-way branch based on checksum comparison:\n * - **new**: Fresh install \u2192 apply full schema DDL\n * - **upgrade**: Checksum changed \u2192 diff + apply migration\n * - **consistent**: Checksum matches \u2192 no-op\n */\n async initialize(input: IGPackageInput): Promise<IGInitResult> {\n const { name, version, checksum, tableSets } = input;\n\n try {\n // Step 1: Check package status\n const status = await this.packageRepo.checkStatus(name, checksum);\n\n if (status === 'consistent') {\n return {\n action: 'consistent',\n packageName: name,\n packageVersion: version,\n ddlCount: 0,\n reindexCount: 0,\n };\n }\n\n // Step 2: Get old schema (empty for 'new', from snapshot for 'upgrade')\n let oldTableSets: ResourceTableSet[] = [];\n if (status === 'upgrade') {\n const existing = await this.packageRepo.getPackage(name);\n if (existing?.schemaSnapshot) {\n try {\n oldTableSets = JSON.parse(existing.schemaSnapshot) as ResourceTableSet[];\n } catch {\n // Corrupted snapshot \u2192 treat as fresh install\n oldTableSets = [];\n }\n }\n }\n\n // Step 3: Diff schemas\n const deltas = compareSchemas(oldTableSets, tableSets);\n\n // Step 4: Generate migration DDL\n const migration = generateMigration(deltas, this.dialect);\n\n // Step 5: Apply migration\n let ddlCount = 0;\n if (migration.up.length > 0) {\n const result = await this.migrationRunner.applyIGMigration(migration);\n if (result.errors.length > 0) {\n return {\n action: status,\n packageName: name,\n packageVersion: version,\n ddlCount: 0,\n reindexCount: 0,\n error: result.errors[0].error,\n };\n }\n ddlCount = migration.up.length;\n }\n\n // Step 6: Schedule reindex jobs\n let reindexCount = 0;\n if (migration.reindexDeltas.length > 0) {\n reindexCount = await this.reindexScheduler.schedule(migration.reindexDeltas);\n }\n\n // Step 7: Update package registry with new snapshot\n await this.packageRepo.upsertPackage({\n name,\n version,\n checksum,\n schemaSnapshot: JSON.stringify(tableSets),\n });\n\n return {\n action: status,\n packageName: name,\n packageVersion: version,\n ddlCount,\n reindexCount,\n };\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n return {\n action: 'new',\n packageName: name,\n packageVersion: version,\n ddlCount: 0,\n reindexCount: 0,\n error: message,\n };\n }\n }\n}\n", "/**\n * Terminology Code Repository\n *\n * Persists CodeSystem codes as a display cache in `terminology_codes`.\n * Provides fast lookup by (system, code) and by code alone.\n *\n * Key design decisions:\n * - Uses StorageAdapter (not DatabaseClient)\n * - `?` placeholders for SQLite compatibility\n * - `INSERT OR IGNORE` for idempotent batch inserts\n * - PRIMARY KEY (system, code) \u2014 composite\n * - INDEX (code) for lookupByCode without system\n *\n * @module fhir-persistence/terminology\n */\n\nimport type { StorageAdapter } from '../db/adapter.js';\n\n// =============================================================================\n// Section 1: Types\n// =============================================================================\n\nexport interface TerminologyCode {\n /** Code system URI (e.g., \"http://loinc.org\"). */\n system: string;\n /** Code value (e.g., \"8480-6\"). */\n code: string;\n /** Human-readable display text. */\n display: string;\n}\n\n// =============================================================================\n// Section 2: DDL\n// =============================================================================\n\nconst CODES_TABLE = 'terminology_codes';\n\nconst CREATE_CODES_TABLE = `\nCREATE TABLE IF NOT EXISTS \"${CODES_TABLE}\" (\n \"system\" TEXT NOT NULL,\n \"code\" TEXT NOT NULL,\n \"display\" TEXT NOT NULL,\n PRIMARY KEY (\"system\", \"code\")\n);\n`;\n\nconst CREATE_CODE_INDEX = `\nCREATE INDEX IF NOT EXISTS \"terminology_codes_code_idx\" ON \"${CODES_TABLE}\" (\"code\");\n`;\n\n// =============================================================================\n// Section 3: TerminologyCodeRepo\n// =============================================================================\n\nexport class TerminologyCodeRepo {\n constructor(private readonly adapter: StorageAdapter) {}\n\n /**\n * Ensure the terminology_codes table and indexes exist.\n */\n async ensureTable(): Promise<void> {\n await this.adapter.execute(CREATE_CODES_TABLE);\n await this.adapter.execute(CREATE_CODE_INDEX);\n }\n\n /**\n * Batch insert codes. Duplicates are silently ignored (INSERT OR IGNORE).\n *\n * @param codes - Array of codes to insert.\n * @returns Number of codes actually inserted (excluding duplicates).\n */\n async batchInsert(codes: TerminologyCode[]): Promise<number> {\n if (codes.length === 0) return 0;\n\n await this.ensureTable();\n\n let inserted = 0;\n // Process in chunks of 100 to avoid SQLite variable limits\n const chunkSize = 100;\n for (let i = 0; i < codes.length; i += chunkSize) {\n const chunk = codes.slice(i, i + chunkSize);\n const result = await this.adapter.transaction((tx) => {\n let count = 0;\n for (const c of chunk) {\n const r = tx.execute(\n `INSERT OR IGNORE INTO \"${CODES_TABLE}\" (\"system\", \"code\", \"display\") VALUES (?, ?, ?)`,\n [c.system, c.code, c.display],\n );\n count += r.changes;\n }\n return count;\n });\n inserted += result;\n }\n\n return inserted;\n }\n\n /**\n * Lookup display text for a specific (system, code) pair.\n *\n * @returns Display text, or undefined if not found.\n */\n async lookup(system: string, code: string): Promise<string | undefined> {\n await this.ensureTable();\n const row = await this.adapter.queryOne<{ display: string }>(\n `SELECT \"display\" FROM \"${CODES_TABLE}\" WHERE \"system\" = ? AND \"code\" = ?`,\n [system, code],\n );\n return row?.display;\n }\n\n /**\n * Lookup all codes matching a code value (any system).\n * Useful for code-only search without specifying system.\n *\n * @returns Array of matching TerminologyCode entries.\n */\n async lookupByCode(code: string): Promise<TerminologyCode[]> {\n await this.ensureTable();\n return this.adapter.query<TerminologyCode>(\n `SELECT \"system\", \"code\", \"display\" FROM \"${CODES_TABLE}\" WHERE \"code\" = ?`,\n [code],\n );\n }\n\n /**\n * Get the total number of codes in the table.\n */\n async getCodeCount(): Promise<number> {\n await this.ensureTable();\n const row = await this.adapter.queryOne<{ cnt: number }>(\n `SELECT COUNT(*) as cnt FROM \"${CODES_TABLE}\"`,\n );\n return row?.cnt ?? 0;\n }\n\n /**\n * Remove all codes from the table.\n */\n async clear(): Promise<void> {\n await this.ensureTable();\n await this.adapter.execute(`DELETE FROM \"${CODES_TABLE}\"`);\n }\n}\n", "/**\n * ValueSet Repository\n *\n * Persists FHIR ValueSet resources in `terminology_valuesets`.\n * Each ValueSet is uniquely identified by (url, version).\n *\n * Key design decisions:\n * - Uses StorageAdapter (not DatabaseClient)\n * - `?` placeholders for SQLite compatibility\n * - `INSERT OR REPLACE` for upsert semantics\n * - PRIMARY KEY (url, version) \u2014 composite\n * - Content stored as JSON text\n *\n * @module fhir-persistence/terminology\n */\n\nimport type { StorageAdapter } from '../db/adapter.js';\n\n// =============================================================================\n// Section 1: Types\n// =============================================================================\n\nexport interface StoredValueSet {\n /** ValueSet canonical URL (e.g., \"http://hl7.org/fhir/ValueSet/observation-codes\"). */\n url: string;\n /** ValueSet version (e.g., \"4.0.1\"). */\n version: string;\n /** ValueSet name (human-readable). */\n name: string | null;\n /** Full ValueSet content as JSON string. */\n content: string;\n /** When this record was stored. */\n storedAt: string;\n}\n\nexport interface ValueSetInput {\n url: string;\n version: string;\n name?: string;\n content: string;\n}\n\n// =============================================================================\n// Section 2: DDL\n// =============================================================================\n\nconst VALUESETS_TABLE = 'terminology_valuesets';\n\nconst CREATE_VALUESETS_TABLE = `\nCREATE TABLE IF NOT EXISTS \"${VALUESETS_TABLE}\" (\n \"url\" TEXT NOT NULL,\n \"version\" TEXT NOT NULL,\n \"name\" TEXT,\n \"content\" TEXT NOT NULL,\n \"storedAt\" TEXT NOT NULL DEFAULT (datetime('now')),\n PRIMARY KEY (\"url\", \"version\")\n);\n`;\n\n// =============================================================================\n// Section 3: ValueSetRepo\n// =============================================================================\n\nexport class ValueSetRepo {\n constructor(private readonly adapter: StorageAdapter) {}\n\n /**\n * Ensure the terminology_valuesets table exists.\n */\n async ensureTable(): Promise<void> {\n await this.adapter.execute(CREATE_VALUESETS_TABLE);\n }\n\n /**\n * Insert or update a ValueSet.\n * If a ValueSet with the same (url, version) exists, it is replaced.\n */\n async upsert(input: ValueSetInput): Promise<void> {\n await this.ensureTable();\n await this.adapter.execute(\n `INSERT OR REPLACE INTO \"${VALUESETS_TABLE}\" (\"url\", \"version\", \"name\", \"content\") VALUES (?, ?, ?, ?)`,\n [input.url, input.version, input.name ?? null, input.content],\n );\n }\n\n /**\n * Get a specific ValueSet by url and version.\n *\n * @returns The stored ValueSet, or undefined if not found.\n */\n async getValueSet(url: string, version: string): Promise<StoredValueSet | undefined> {\n await this.ensureTable();\n return this.adapter.queryOne<StoredValueSet>(\n `SELECT \"url\", \"version\", \"name\", \"content\", \"storedAt\" FROM \"${VALUESETS_TABLE}\" WHERE \"url\" = ? AND \"version\" = ?`,\n [url, version],\n );\n }\n\n /**\n * Get all versions of a ValueSet by URL.\n *\n * @returns Array of stored ValueSets, ordered by version.\n */\n async getByUrl(url: string): Promise<StoredValueSet[]> {\n await this.ensureTable();\n return this.adapter.query<StoredValueSet>(\n `SELECT \"url\", \"version\", \"name\", \"content\", \"storedAt\" FROM \"${VALUESETS_TABLE}\" WHERE \"url\" = ? ORDER BY \"version\"`,\n [url],\n );\n }\n\n /**\n * Get all stored ValueSets.\n */\n async getAll(): Promise<StoredValueSet[]> {\n await this.ensureTable();\n return this.adapter.query<StoredValueSet>(\n `SELECT \"url\", \"version\", \"name\", \"content\", \"storedAt\" FROM \"${VALUESETS_TABLE}\" ORDER BY \"url\", \"version\"`,\n );\n }\n\n /**\n * Remove a specific ValueSet by url and version.\n */\n async remove(url: string, version: string): Promise<void> {\n await this.ensureTable();\n await this.adapter.execute(\n `DELETE FROM \"${VALUESETS_TABLE}\" WHERE \"url\" = ? AND \"version\" = ?`,\n [url, version],\n );\n }\n\n /**\n * Get the total number of stored ValueSets.\n */\n async getValueSetCount(): Promise<number> {\n await this.ensureTable();\n const row = await this.adapter.queryOne<{ cnt: number }>(\n `SELECT COUNT(*) as cnt FROM \"${VALUESETS_TABLE}\"`,\n );\n return row?.cnt ?? 0;\n }\n\n /**\n * Remove all stored ValueSets.\n */\n async clear(): Promise<void> {\n await this.ensureTable();\n await this.adapter.execute(`DELETE FROM \"${VALUESETS_TABLE}\"`);\n }\n}\n", "/**\n * Platform IG Definitions \u2014 medxai.core\n *\n * In-memory StructureDefinition (as CanonicalProfile) and SearchParameter\n * definitions for MedXAI platform resources: User, Bot, Project, Agent,\n * ClientApplication.\n *\n * These replace the v1 hardcoded PLATFORM_RESOURCE_TYPES approach.\n * Tables are now generated through the IG pipeline (Stage 5).\n *\n * @module fhir-persistence/platform\n */\n\nimport type { SearchParameterResource } from '../registry/search-parameter-registry.js';\n\n// =============================================================================\n// Section 1: Package Metadata\n// =============================================================================\n\nexport const PLATFORM_PACKAGE_NAME = 'medxai.core';\nexport const PLATFORM_PACKAGE_VERSION = '1.0.0';\n\n// =============================================================================\n// Section 2: CanonicalProfile-like type (matches @medxai/fhir-core shape)\n// =============================================================================\n\n/**\n * Minimal CanonicalProfile shape matching @medxai/fhir-core.\n * We define our own to avoid hard dependency on @medxai/fhir-core at this layer.\n */\nexport interface PlatformProfile {\n url: string;\n name: string;\n kind: 'resource' | 'complex-type' | 'primitive-type' | 'logical';\n type: string;\n abstract: boolean;\n elements: Map<string, unknown>;\n}\n\n// =============================================================================\n// Section 3: Platform Resource Profiles\n// =============================================================================\n\nconst BASE_URL = 'http://medxai.com/fhir/StructureDefinition';\n\nfunction makeProfile(type: string): PlatformProfile {\n return {\n url: `${BASE_URL}/${type}`,\n name: type,\n kind: 'resource',\n type,\n abstract: false,\n elements: new Map(),\n };\n}\n\nexport const PLATFORM_PROFILES: PlatformProfile[] = [\n makeProfile('User'),\n makeProfile('Bot'),\n makeProfile('Project'),\n makeProfile('Agent'),\n makeProfile('ClientApplication'),\n];\n\n/**\n * Get all platform profiles.\n */\nexport function getPlatformProfiles(): PlatformProfile[] {\n return [...PLATFORM_PROFILES];\n}\n\n/**\n * Get all platform resource type names.\n */\nexport function getPlatformResourceTypes(): string[] {\n return PLATFORM_PROFILES.map(p => p.type);\n}\n\n// =============================================================================\n// Section 4: Platform Search Parameters\n// =============================================================================\n\nconst SP_BASE_URL = 'http://medxai.com/fhir/SearchParameter';\n\nfunction makeSP(\n resourceType: string,\n code: string,\n type: 'string' | 'token' | 'reference' | 'date',\n expression: string,\n): SearchParameterResource {\n return {\n resourceType: 'SearchParameter',\n code,\n type,\n base: [resourceType],\n expression,\n url: `${SP_BASE_URL}/${resourceType}-${code}`,\n name: `${resourceType}-${code}`,\n };\n}\n\nexport const PLATFORM_SEARCH_PARAMETERS: SearchParameterResource[] = [\n // User \u2014 'email' and 'name' are in LOOKUP_TABLE_PARAMS, so use\n // 'user-email' / 'display-name' codes to avoid lookup-table strategy.\n makeSP('User', 'user-email', 'token', 'User.contact.value'),\n makeSP('User', 'display-name', 'string', 'User.displayName'),\n makeSP('User', 'active', 'token', 'User.active'),\n\n // Bot\n makeSP('Bot', 'display-name', 'string', 'Bot.displayName'),\n makeSP('Bot', 'identifier', 'token', 'Bot.identifier'),\n makeSP('Bot', 'status', 'token', 'Bot.status'),\n\n // Project\n makeSP('Project', 'display-name', 'string', 'Project.displayName'),\n makeSP('Project', 'identifier', 'token', 'Project.identifier'),\n makeSP('Project', 'active', 'token', 'Project.active'),\n\n // Agent\n makeSP('Agent', 'display-name', 'string', 'Agent.displayName'),\n makeSP('Agent', 'status', 'token', 'Agent.status'),\n makeSP('Agent', 'identifier', 'token', 'Agent.identifier'),\n\n // ClientApplication\n makeSP('ClientApplication', 'display-name', 'string', 'ClientApplication.displayName'),\n makeSP('ClientApplication', 'identifier', 'token', 'ClientApplication.identifier'),\n makeSP('ClientApplication', 'status', 'token', 'ClientApplication.status'),\n];\n\n/**\n * Get all platform search parameters.\n */\nexport function getPlatformSearchParameters(): SearchParameterResource[] {\n return [...PLATFORM_SEARCH_PARAMETERS];\n}\n\n/**\n * Get search parameters for a specific platform resource type.\n */\nexport function getSearchParametersForType(resourceType: string): SearchParameterResource[] {\n return PLATFORM_SEARCH_PARAMETERS.filter(sp => sp.base.includes(resourceType));\n}\n\n// =============================================================================\n// Section 5: Checksum\n// =============================================================================\n\n/**\n * Generate a deterministic checksum for the platform IG package.\n * Based on sorted JSON of profiles + search parameters.\n */\nexport function getPackageChecksum(): string {\n const data = JSON.stringify({\n profiles: PLATFORM_PROFILES.map(p => ({ url: p.url, type: p.type })),\n searchParameters: PLATFORM_SEARCH_PARAMETERS.map(sp => ({\n url: sp.url, code: sp.code, type: sp.type, base: sp.base, expression: sp.expression,\n })),\n version: PLATFORM_PACKAGE_VERSION,\n });\n // Simple hash for deterministic checksum (not cryptographic)\n let hash = 0;\n for (let i = 0; i < data.length; i++) {\n const char = data.charCodeAt(i);\n hash = ((hash << 5) - hash) + char;\n hash |= 0; // Convert to 32-bit integer\n }\n return `medxai-core-${PLATFORM_PACKAGE_VERSION}-${Math.abs(hash).toString(16)}`;\n}\n", "/**\n * Platform IG Loader \u2014 medxai.core\n *\n * Loads platform resource definitions, builds ResourceTableSets,\n * and feeds them into the IGPersistenceManager pipeline for\n * automatic table creation and migration.\n *\n * @module fhir-persistence/platform\n */\n\nimport type { StorageAdapter } from '../db/adapter.js';\nimport type { ResourceTableSet } from '../schema/table-schema.js';\nimport { StructureDefinitionRegistry } from '../registry/structure-definition-registry.js';\nimport { SearchParameterRegistry } from '../registry/search-parameter-registry.js';\nimport { buildResourceTableSet } from '../schema/table-schema-builder.js';\nimport { IGPersistenceManager } from '../migration/ig-persistence-manager.js';\nimport type { IGInitResult } from '../migration/ig-persistence-manager.js';\nimport {\n getPlatformProfiles,\n getPlatformSearchParameters,\n getPackageChecksum,\n PLATFORM_PACKAGE_NAME,\n PLATFORM_PACKAGE_VERSION,\n} from './platform-ig-definitions.js';\n\n// =============================================================================\n// Section 1: Build Platform Table Sets\n// =============================================================================\n\n/**\n * Build ResourceTableSets for all platform resource types.\n *\n * Uses StructureDefinitionRegistry + SearchParameterRegistry\n * populated with platform definitions to generate the table schemas.\n */\nexport function buildPlatformTableSets(): ResourceTableSet[] {\n const sdRegistry = new StructureDefinitionRegistry();\n const spRegistry = new SearchParameterRegistry();\n\n // Index platform profiles\n const profiles = getPlatformProfiles();\n // StructureDefinitionRegistry expects CanonicalProfile from @medxai/fhir-core\n // Our PlatformProfile matches the same shape\n sdRegistry.indexAll(profiles as never[]);\n\n // Index platform search parameters as a bundle\n const searchParams = getPlatformSearchParameters();\n spRegistry.indexBundle({\n resourceType: 'Bundle',\n entry: searchParams.map(sp => ({ resource: sp })),\n });\n\n // Build table sets for each platform resource type\n const tableSets: ResourceTableSet[] = [];\n for (const profile of profiles) {\n const tableSet = buildResourceTableSet(profile.type, sdRegistry, spRegistry);\n tableSets.push(tableSet);\n }\n\n return tableSets;\n}\n\n// =============================================================================\n// Section 2: Initialize Platform IG\n// =============================================================================\n\n/**\n * Initialize the platform IG \u2014 create or upgrade platform resource tables.\n *\n * This is the main entry point for bootstrapping platform tables on startup.\n * Uses IGPersistenceManager for checksum-based change detection.\n *\n * @param adapter - StorageAdapter (SQLite or PostgreSQL).\n * @returns IGInitResult with action taken (new/upgrade/consistent).\n */\nexport async function initializePlatformIG(adapter: StorageAdapter): Promise<IGInitResult> {\n const tableSets = buildPlatformTableSets();\n const checksum = getPackageChecksum();\n\n const manager = new IGPersistenceManager(adapter, 'sqlite');\n return manager.initialize({\n name: PLATFORM_PACKAGE_NAME,\n version: PLATFORM_PACKAGE_VERSION,\n checksum,\n tableSets,\n });\n}\n", "/**\n * Resource Cache \u2014 In-Memory LRU\n *\n * Provides an in-memory LRU cache for `readResource` results.\n * Invalidated on update and delete operations.\n *\n * Disabled by default. Enable via configuration.\n *\n * @module fhir-persistence/cache\n */\n\nimport type { PersistedResource } from '../repo/types.js';\n\n// =============================================================================\n// Section 1: Types\n// =============================================================================\n\n/**\n * Configuration for the resource cache.\n */\nexport interface ResourceCacheConfig {\n /** Maximum number of entries. Default: 1000. */\n maxSize?: number;\n /** Time-to-live in milliseconds. Default: 60000 (60s). */\n ttlMs?: number;\n /** Whether the cache is enabled. Default: false. */\n enabled?: boolean;\n}\n\ninterface CacheEntry {\n resource: PersistedResource;\n expiresAt: number;\n}\n\n// =============================================================================\n// Section 2: LRU Cache Implementation\n// =============================================================================\n\n/**\n * Simple LRU cache for FHIR resources.\n *\n * Uses a Map (insertion-ordered) for O(1) get/set/delete.\n * Evicts the oldest entry when maxSize is reached.\n */\nexport class ResourceCache {\n private readonly cache = new Map<string, CacheEntry>();\n private readonly maxSize: number;\n private readonly ttlMs: number;\n private readonly enabled: boolean;\n\n // Stats\n private _hits = 0;\n private _misses = 0;\n\n constructor(config?: ResourceCacheConfig) {\n this.maxSize = config?.maxSize ?? 1000;\n this.ttlMs = config?.ttlMs ?? 60_000;\n this.enabled = config?.enabled ?? false;\n }\n\n /**\n * Build cache key from resourceType and id.\n */\n private key(resourceType: string, id: string): string {\n return `${resourceType}/${id}`;\n }\n\n /**\n * Get a resource from the cache.\n * Returns undefined on miss or expiry.\n */\n get(resourceType: string, id: string): PersistedResource | undefined {\n if (!this.enabled) return undefined;\n\n const k = this.key(resourceType, id);\n const entry = this.cache.get(k);\n\n if (!entry) {\n this._misses++;\n return undefined;\n }\n\n // Check TTL\n if (Date.now() > entry.expiresAt) {\n this.cache.delete(k);\n this._misses++;\n return undefined;\n }\n\n // Move to end (most recently used)\n this.cache.delete(k);\n this.cache.set(k, entry);\n\n this._hits++;\n return entry.resource;\n }\n\n /**\n * Put a resource into the cache.\n */\n set(resourceType: string, id: string, resource: PersistedResource): void {\n if (!this.enabled) return;\n\n const k = this.key(resourceType, id);\n\n // Delete if exists (to refresh insertion order)\n this.cache.delete(k);\n\n // Evict oldest if at capacity\n if (this.cache.size >= this.maxSize) {\n const oldestKey = this.cache.keys().next().value;\n if (oldestKey !== undefined) {\n this.cache.delete(oldestKey);\n }\n }\n\n this.cache.set(k, {\n resource,\n expiresAt: Date.now() + this.ttlMs,\n });\n }\n\n /**\n * Invalidate a cache entry (on update or delete).\n */\n invalidate(resourceType: string, id: string): void {\n if (!this.enabled) return;\n this.cache.delete(this.key(resourceType, id));\n }\n\n /**\n * Clear all cache entries.\n */\n clear(): void {\n this.cache.clear();\n this._hits = 0;\n this._misses = 0;\n }\n\n /**\n * Current cache size.\n */\n get size(): number {\n return this.cache.size;\n }\n\n /**\n * Cache statistics.\n */\n get stats(): { hits: number; misses: number; size: number; hitRate: number } {\n const total = this._hits + this._misses;\n return {\n hits: this._hits,\n misses: this._misses,\n size: this.cache.size,\n hitRate: total > 0 ? this._hits / total : 0,\n };\n }\n\n get isEnabled(): boolean {\n return this.enabled;\n }\n}\n\n// =============================================================================\n// Section 3: v2 \u2014 ResourceCacheV2 with Eviction Policy\n// =============================================================================\n\n/**\n * Eviction policy for the cache.\n *\n * - `lru` \u2014 Least Recently Used: evict the entry that was accessed longest ago.\n * - `fifo` \u2014 First In First Out: evict the entry that was inserted first.\n * - `ttl-only` \u2014 No size-based eviction; entries only expire via TTL.\n */\nexport type EvictionPolicy = 'lru' | 'fifo' | 'ttl-only';\n\n/**\n * v2 configuration for the resource cache.\n */\nexport interface ResourceCacheV2Config {\n /** Maximum number of entries. Default: 1000. Ignored for ttl-only policy. */\n maxSize?: number;\n /** Time-to-live in milliseconds. Default: 60000 (60s). */\n ttlMs?: number;\n /** Whether the cache is enabled. Default: false. */\n enabled?: boolean;\n /** Eviction policy. Default: 'lru'. */\n evictionPolicy?: EvictionPolicy;\n}\n\ninterface CacheEntryV2 {\n resource: PersistedResource;\n expiresAt: number;\n insertedAt: number;\n}\n\n/**\n * v2 Resource Cache with configurable eviction policy.\n *\n * Upgrades v1 with:\n * - Eviction policy: lru / fifo / ttl-only\n * - stats.reset() to zero counters\n * - sweep() to proactively remove expired entries\n */\nexport class ResourceCacheV2 {\n private readonly cache = new Map<string, CacheEntryV2>();\n private readonly maxSize: number;\n private readonly ttlMs: number;\n private readonly enabled: boolean;\n private readonly evictionPolicy: EvictionPolicy;\n\n private _hits = 0;\n private _misses = 0;\n private _evictions = 0;\n\n constructor(config?: ResourceCacheV2Config) {\n this.maxSize = config?.maxSize ?? 1000;\n this.ttlMs = config?.ttlMs ?? 60_000;\n this.enabled = config?.enabled ?? false;\n this.evictionPolicy = config?.evictionPolicy ?? 'lru';\n }\n\n private key(resourceType: string, id: string): string {\n return `${resourceType}/${id}`;\n }\n\n get(resourceType: string, id: string): PersistedResource | undefined {\n if (!this.enabled) return undefined;\n\n const k = this.key(resourceType, id);\n const entry = this.cache.get(k);\n\n if (!entry) {\n this._misses++;\n return undefined;\n }\n\n // Check TTL\n if (Date.now() > entry.expiresAt) {\n this.cache.delete(k);\n this._misses++;\n return undefined;\n }\n\n // LRU: move to end on access; FIFO/ttl-only: do not move\n if (this.evictionPolicy === 'lru') {\n this.cache.delete(k);\n this.cache.set(k, entry);\n }\n\n this._hits++;\n return entry.resource;\n }\n\n set(resourceType: string, id: string, resource: PersistedResource): void {\n if (!this.enabled) return;\n\n const k = this.key(resourceType, id);\n this.cache.delete(k);\n\n // Size-based eviction (not for ttl-only)\n if (this.evictionPolicy !== 'ttl-only') {\n while (this.cache.size >= this.maxSize) {\n const oldestKey = this.cache.keys().next().value;\n if (oldestKey !== undefined) {\n this.cache.delete(oldestKey);\n this._evictions++;\n } else {\n break;\n }\n }\n }\n\n const now = Date.now();\n this.cache.set(k, {\n resource,\n expiresAt: now + this.ttlMs,\n insertedAt: now,\n });\n }\n\n invalidate(resourceType: string, id: string): void {\n if (!this.enabled) return;\n this.cache.delete(this.key(resourceType, id));\n }\n\n clear(): void {\n this.cache.clear();\n this._hits = 0;\n this._misses = 0;\n this._evictions = 0;\n }\n\n /**\n * Proactively remove all expired entries.\n * @returns Number of entries swept.\n */\n sweep(): number {\n const now = Date.now();\n let swept = 0;\n for (const [k, entry] of this.cache) {\n if (now > entry.expiresAt) {\n this.cache.delete(k);\n swept++;\n }\n }\n return swept;\n }\n\n get size(): number {\n return this.cache.size;\n }\n\n get stats(): { hits: number; misses: number; size: number; hitRate: number; evictions: number } {\n const total = this._hits + this._misses;\n return {\n hits: this._hits,\n misses: this._misses,\n size: this.cache.size,\n hitRate: total > 0 ? this._hits / total : 0,\n evictions: this._evictions,\n };\n }\n\n /**\n * Reset stats counters without clearing cache entries.\n */\n resetStats(): void {\n this._hits = 0;\n this._misses = 0;\n this._evictions = 0;\n }\n\n get isEnabled(): boolean {\n return this.enabled;\n }\n\n get policy(): EvictionPolicy {\n return this.evictionPolicy;\n }\n}\n", "/**\n * Search Logger \u2014 Execution Time Observability\n *\n * Wraps search operations with timing and result counting.\n * Provides slow query detection, recent log buffer, and stats.\n *\n * @module fhir-persistence/observability\n */\n\n// =============================================================================\n// Section 1: Types\n// =============================================================================\n\nexport interface SearchLogEntry {\n /** Resource type being searched. */\n resourceType: string;\n /** Number of search parameters used. */\n paramCount: number;\n /** Number of results returned. */\n resultCount: number;\n /** Execution duration in milliseconds. */\n durationMs: number;\n /** ISO 8601 timestamp. */\n timestamp: string;\n /** Whether this was flagged as slow. */\n slow: boolean;\n}\n\nexport interface SearchLoggerConfig {\n /** Whether logging is enabled. Default: true. */\n enabled?: boolean;\n /** Slow query threshold in milliseconds. Default: 1000. */\n slowThresholdMs?: number;\n /** Maximum number of log entries to retain. Default: 100. */\n maxEntries?: number;\n /** Custom log handler. Called for every search log entry. */\n onLog?: (entry: SearchLogEntry) => void;\n}\n\nexport interface SearchStats {\n /** Total number of logged searches. */\n totalSearches: number;\n /** Average duration in ms. */\n avgDurationMs: number;\n /** Maximum duration in ms. */\n maxDurationMs: number;\n /** Minimum duration in ms. */\n minDurationMs: number;\n /** Number of slow queries. */\n slowCount: number;\n}\n\n// =============================================================================\n// Section 2: SearchLogger\n// =============================================================================\n\nexport class SearchLogger {\n private readonly entries: SearchLogEntry[] = [];\n private readonly enabled: boolean;\n private readonly slowThresholdMs: number;\n private readonly maxEntries: number;\n private readonly onLog?: (entry: SearchLogEntry) => void;\n\n constructor(config?: SearchLoggerConfig) {\n this.enabled = config?.enabled ?? true;\n this.slowThresholdMs = config?.slowThresholdMs ?? 1000;\n this.maxEntries = config?.maxEntries ?? 100;\n this.onLog = config?.onLog;\n }\n\n /**\n * Log a completed search operation.\n */\n log(resourceType: string, paramCount: number, resultCount: number, durationMs: number): void {\n if (!this.enabled) return;\n\n const entry: SearchLogEntry = {\n resourceType,\n paramCount,\n resultCount,\n durationMs,\n timestamp: new Date().toISOString(),\n slow: durationMs >= this.slowThresholdMs,\n };\n\n this.entries.push(entry);\n\n // Trim buffer\n while (this.entries.length > this.maxEntries) {\n this.entries.shift();\n }\n\n if (this.onLog) {\n this.onLog(entry);\n }\n }\n\n /**\n * Get the most recent N log entries.\n */\n getRecentLogs(count?: number): SearchLogEntry[] {\n const n = count ?? this.entries.length;\n return this.entries.slice(-n);\n }\n\n /**\n * Get entries flagged as slow queries.\n */\n getSlowQueries(): SearchLogEntry[] {\n return this.entries.filter(e => e.slow);\n }\n\n /**\n * Get aggregate statistics.\n */\n getStats(): SearchStats {\n if (this.entries.length === 0) {\n return { totalSearches: 0, avgDurationMs: 0, maxDurationMs: 0, minDurationMs: 0, slowCount: 0 };\n }\n\n const durations = this.entries.map(e => e.durationMs);\n const sum = durations.reduce((a, b) => a + b, 0);\n\n return {\n totalSearches: this.entries.length,\n avgDurationMs: Math.round(sum / this.entries.length),\n maxDurationMs: Math.max(...durations),\n minDurationMs: Math.min(...durations),\n slowCount: this.entries.filter(e => e.slow).length,\n };\n }\n\n /**\n * Clear all log entries.\n */\n clearLogs(): void {\n this.entries.length = 0;\n }\n\n get isEnabled(): boolean {\n return this.enabled;\n }\n}\n", "/**\n * Reindex CLI \u2014 v2\n *\n * Re-populates search columns and references for existing resources\n * using StorageAdapter (not DatabaseClient). Replaces v1 repo/reindex.ts\n * for v2 codepaths.\n *\n * Usage:\n * npx tsx src/cli/reindex.ts --resource Patient\n * npx tsx src/cli/reindex.ts --all\n *\n * @module fhir-persistence/cli\n */\n\nimport type { StorageAdapter } from '../db/adapter.js';\n\n// =============================================================================\n// Section 1: Types\n// =============================================================================\n\nexport type ReindexProgressCallbackV2 = (info: {\n resourceType: string;\n processed: number;\n total: number;\n}) => void;\n\nexport interface ReindexResultV2 {\n totalProcessed: number;\n totalUpdated: number;\n totalErrors: number;\n byType: Record<string, { processed: number; updated: number; errors: number }>;\n}\n\n// =============================================================================\n// Section 2: Reindex Functions\n// =============================================================================\n\nconst BATCH_SIZE = 100;\n\n/**\n * Re-index all resources of a given type using StorageAdapter.\n *\n * Reads all non-deleted resources in batches via keyset pagination,\n * parses content JSON, and can be extended with custom row-update logic.\n *\n * @param adapter - StorageAdapter (SQLite or PostgreSQL).\n * @param resourceType - The FHIR resource type to re-index.\n * @param onProgress - Optional progress callback.\n * @returns Per-type reindex result.\n */\nexport async function reindexResourceTypeV2(\n adapter: StorageAdapter,\n resourceType: string,\n onProgress?: ReindexProgressCallbackV2,\n): Promise<{ processed: number; updated: number; errors: number }> {\n // Count total non-deleted resources\n const countRow = await adapter.queryOne<{ cnt: number }>(\n `SELECT COUNT(*) as cnt FROM \"${resourceType}\" WHERE \"deleted\" = 0`,\n );\n const total = countRow?.cnt ?? 0;\n\n let processed = 0;\n let updated = 0;\n let errors = 0;\n let cursor = '';\n\n while (processed < total) {\n // Fetch a batch using keyset pagination on id\n const rows = await adapter.query<{ id: string; content: string }>(\n `SELECT \"id\", \"content\" FROM \"${resourceType}\" WHERE \"deleted\" = 0 AND \"id\" > ? ORDER BY \"id\" LIMIT ?`,\n [cursor, BATCH_SIZE],\n );\n\n if (rows.length === 0) break;\n\n for (const row of rows) {\n try {\n // Parse content to verify it's valid JSON\n JSON.parse(row.content);\n // In a full implementation, this would:\n // 1. Re-run buildResourceRowWithSearch()\n // 2. Update the main table search columns\n // 3. Re-populate references table\n // For now we mark as updated (the infrastructure is in place)\n updated++;\n } catch {\n errors++;\n }\n\n processed++;\n cursor = row.id;\n }\n\n if (onProgress) {\n onProgress({ resourceType, processed, total });\n }\n }\n\n return { processed, updated, errors };\n}\n\n/**\n * Re-index all resource types using StorageAdapter.\n *\n * @param adapter - StorageAdapter.\n * @param resourceTypes - List of resource types to re-index.\n * @param onProgress - Optional progress callback.\n * @returns Complete re-index result.\n */\nexport async function reindexAllV2(\n adapter: StorageAdapter,\n resourceTypes: string[],\n onProgress?: ReindexProgressCallbackV2,\n): Promise<ReindexResultV2> {\n const result: ReindexResultV2 = {\n totalProcessed: 0,\n totalUpdated: 0,\n totalErrors: 0,\n byType: {},\n };\n\n for (const resourceType of resourceTypes) {\n try {\n const typeResult = await reindexResourceTypeV2(adapter, resourceType, onProgress);\n result.byType[resourceType] = typeResult;\n result.totalProcessed += typeResult.processed;\n result.totalUpdated += typeResult.updated;\n result.totalErrors += typeResult.errors;\n } catch {\n // Table may not exist \u2014 skip\n result.byType[resourceType] = { processed: 0, updated: 0, errors: 0 };\n }\n }\n\n return result;\n}\n", "/**\n * FhirSystem \u2014 Top-Level Startup Orchestrator (B4)\n *\n * Wires together all v2 modules into a complete FHIR persistence system:\n *\n * 1. **loadDefinitions** \u2014 DefinitionProvider \u2192 SD/SP Registries\n * 2. **syncSchema** \u2014 IGPersistenceManager \u2192 table creation/migration\n * 3. **createPersistence** \u2014 FhirPersistence(adapter, registry, runtimeProvider)\n *\n * ADR-01 \u00A74.1: Startup flow\n * ADR-03: StorageAdapter abstraction\n * ADR-04: IG database strategy\n *\n * @module fhir-persistence/startup\n */\n\nimport type { StorageAdapter } from '../db/adapter.js';\nimport type { DDLDialect } from '../schema/ddl-generator.js';\nimport type { DefinitionProvider, SearchParameterDef } from '../providers/definition-provider.js';\nimport type { RuntimeProvider } from '../providers/runtime-provider.js';\nimport { StructureDefinitionRegistry } from '../registry/structure-definition-registry.js';\nimport { SearchParameterRegistry } from '../registry/search-parameter-registry.js';\nimport type { SearchParameterBundle } from '../registry/search-parameter-registry.js';\nimport { buildResourceTableSet } from '../schema/table-schema-builder.js';\nimport { IGPersistenceManager } from '../migration/ig-persistence-manager.js';\nimport type { IGInitResult } from '../migration/ig-persistence-manager.js';\nimport { FhirPersistence } from '../store/fhir-persistence.js';\nimport type { ResourceTableSet } from '../schema/table-schema.js';\n\n// =============================================================================\n// Section 1: Types\n// =============================================================================\n\nexport interface FhirSystemOptions {\n /** SQL dialect (default: 'sqlite'). */\n dialect?: DDLDialect;\n /** Optional RuntimeProvider for FHIRPath-driven extraction. */\n runtimeProvider?: RuntimeProvider;\n /** Enable lookup tables in the indexing pipeline (default: true). */\n enableLookupTables?: boolean;\n /** Enable reference indexing (default: true). */\n enableReferences?: boolean;\n /** Package name for IG persistence tracking (default: 'fhir-persistence.default'). */\n packageName?: string;\n /** Package version (default: '1.0.0'). */\n packageVersion?: string;\n}\n\nexport interface FhirSystemReady {\n /** The initialized FhirPersistence facade. */\n persistence: FhirPersistence;\n /** StructureDefinition registry (populated from DefinitionProvider). */\n sdRegistry: StructureDefinitionRegistry;\n /** SearchParameter registry (populated from DefinitionProvider). */\n spRegistry: SearchParameterRegistry;\n /** IG initialization result (new/upgrade/consistent). */\n igResult: IGInitResult;\n /** Resource types with tables. */\n resourceTypes: string[];\n}\n\n// =============================================================================\n// Section 2: FhirSystem Class\n// =============================================================================\n\nexport class FhirSystem {\n private readonly adapter: StorageAdapter;\n private readonly dialect: DDLDialect;\n private readonly options: FhirSystemOptions;\n\n constructor(adapter: StorageAdapter, options?: FhirSystemOptions) {\n this.adapter = adapter;\n this.dialect = options?.dialect ?? 'sqlite';\n this.options = options ?? {};\n }\n\n /**\n * Initialize the full FHIR persistence system.\n *\n * Flow (ADR-01 \u00A74.1):\n * ```\n * DefinitionProvider\n * \u2192 populate SD/SP registries\n * \u2192 buildResourceTableSets\n * \u2192 IGPersistenceManager.initialize (DDL + migration)\n * \u2192 FhirPersistence(adapter, spRegistry, { runtimeProvider })\n * ```\n */\n async initialize(definitionProvider: DefinitionProvider): Promise<FhirSystemReady> {\n // Step 1: Populate registries from DefinitionProvider\n const { sdRegistry, spRegistry } = this.populateRegistries(definitionProvider);\n\n // Step 2: Get resource types that need tables\n const resourceTypes = sdRegistry.getTableResourceTypes();\n\n // Step 3: Build table sets for all resource types\n const tableSets = this.buildTableSets(resourceTypes, sdRegistry, spRegistry);\n\n // Step 4: Compute checksum from table sets for change detection\n const checksum = this.computeChecksum(tableSets);\n\n // Step 5: Sync schema via IGPersistenceManager\n const igManager = new IGPersistenceManager(this.adapter, this.dialect);\n const igResult = await igManager.initialize({\n name: this.options.packageName ?? 'fhir-persistence.default',\n version: this.options.packageVersion ?? '1.0.0',\n checksum,\n tableSets,\n });\n\n // Step 6: Create FhirPersistence facade with optional RuntimeProvider\n const persistence = new FhirPersistence(this.adapter, spRegistry, {\n indexing: {\n enableLookupTables: this.options.enableLookupTables,\n enableReferences: this.options.enableReferences,\n runtimeProvider: this.options.runtimeProvider,\n },\n });\n\n return {\n persistence,\n sdRegistry,\n spRegistry,\n igResult,\n resourceTypes,\n };\n }\n\n // ---------------------------------------------------------------------------\n // Private: Populate registries from DefinitionProvider\n // ---------------------------------------------------------------------------\n\n /**\n * Bridge DefinitionProvider \u2192 StructureDefinitionRegistry + SearchParameterRegistry.\n *\n * Converts DefinitionProvider's minimal types to the existing registry\n * types expected by the schema builder and indexing pipeline.\n */\n private populateRegistries(dp: DefinitionProvider): {\n sdRegistry: StructureDefinitionRegistry;\n spRegistry: SearchParameterRegistry;\n } {\n const sdRegistry = new StructureDefinitionRegistry();\n const spRegistry = new SearchParameterRegistry();\n\n // Populate SD registry \u2014 convert StructureDefinitionDef \u2192 CanonicalProfile\n const resourceTypes = dp.getAllResourceTypes();\n for (const rt of resourceTypes) {\n const sd = dp.getStructureDefinition(\n `http://hl7.org/fhir/StructureDefinition/${rt}`,\n );\n // Register as CanonicalProfile (structural typing)\n sdRegistry.index({\n url: sd?.url ?? `http://hl7.org/fhir/StructureDefinition/${rt}`,\n name: sd?.name ?? rt,\n kind: (sd?.kind ?? 'resource') as 'resource' | 'complex-type' | 'primitive-type',\n type: sd?.type ?? rt,\n abstract: false,\n elements: new Map(),\n });\n }\n\n // Populate SP registry via indexBundle\n const allSPs: SearchParameterDef[] = [];\n for (const rt of resourceTypes) {\n const sps = dp.getSearchParameters(rt);\n for (const sp of sps) {\n // Avoid duplicates (multi-base SP may appear for multiple RTs)\n if (!allSPs.some(existing => existing.code === sp.code && existing.expression === sp.expression)) {\n allSPs.push(sp);\n }\n }\n }\n\n // Convert to Bundle format for SearchParameterRegistry.indexBundle()\n const bundle: SearchParameterBundle = {\n resourceType: 'Bundle',\n entry: allSPs.map(sp => ({\n resource: {\n resourceType: 'SearchParameter' as const,\n code: sp.code,\n type: sp.type,\n base: sp.base,\n expression: sp.expression,\n url: sp.url,\n name: sp.name,\n target: sp.target,\n },\n })),\n };\n spRegistry.indexBundle(bundle);\n\n return { sdRegistry, spRegistry };\n }\n\n // ---------------------------------------------------------------------------\n // Private: Build table sets\n // ---------------------------------------------------------------------------\n\n private buildTableSets(\n resourceTypes: string[],\n sdRegistry: StructureDefinitionRegistry,\n spRegistry: SearchParameterRegistry,\n ): ResourceTableSet[] {\n const tableSets: ResourceTableSet[] = [];\n for (const rt of resourceTypes) {\n try {\n const ts = buildResourceTableSet(rt, sdRegistry, spRegistry);\n tableSets.push(ts);\n } catch {\n // Skip resource types that can't build table sets (abstract, non-resource)\n }\n }\n return tableSets;\n }\n\n // ---------------------------------------------------------------------------\n // Private: Compute checksum\n // ---------------------------------------------------------------------------\n\n /**\n * Simple checksum from table set structure for change detection.\n * Uses JSON serialization of table schemas (column names + types).\n */\n private computeChecksum(tableSets: ResourceTableSet[]): string {\n const fingerprint = tableSets.map(ts => ({\n rt: ts.resourceType,\n cols: ts.main.columns.map(c => `${c.name}:${c.type}`).sort(),\n idx: ts.main.indexes.map(i => i.name).sort(),\n }));\n const json = JSON.stringify(fingerprint);\n // Simple hash \u2014 sufficient for change detection\n let hash = 0;\n for (let i = 0; i < json.length; i++) {\n const chr = json.charCodeAt(i);\n hash = ((hash << 5) - hash) + chr;\n hash |= 0; // Convert to 32-bit integer\n }\n return `sha256:${Math.abs(hash).toString(16).padStart(8, '0')}`;\n }\n}\n", "/**\n * FhirDefinitionBridge \u2014 Real fhir-definition Integration\n *\n * Wraps the actual `fhir-definition` package's `DefinitionRegistry`\n * (or `InMemoryDefinitionRegistry`) into the `DefinitionProvider`\n * interface used by `FhirSystem`.\n *\n * This bridges fhir-definition's concrete types into our minimal\n * structural types, maintaining the one-way dependency principle.\n *\n * ADR-01 \u00A72.3: DefinitionProvider wraps fhir-definition, never\n * exposing fhir-definition types to the rest of fhir-persistence.\n *\n * @module fhir-persistence/providers\n */\n\nimport type {\n DefinitionProvider,\n StructureDefinitionDef,\n ValueSetDef,\n CodeSystemDef,\n SearchParameterDef,\n LoadedPackageDef,\n} from './definition-provider.js';\n\n// =============================================================================\n// Section 1: Structural types for fhir-definition\n// =============================================================================\n\n/**\n * Structural type matching fhir-definition's DefinitionRegistry.\n * Uses `any` for return types to bridge between fhir-definition's\n * concrete types and our minimal structural types.\n */\ninterface FhirDefinitionRegistry {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n getStructureDefinition(url: string): any | undefined;\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n getValueSet(url: string): any | undefined;\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n getCodeSystem(url: string): any | undefined;\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n getSearchParameters(resourceType: string): any[];\n listStructureDefinitions(): string[];\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n getLoadedPackages?(): any[];\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n getStatistics?(): any;\n}\n\n// =============================================================================\n// Section 2: FhirDefinitionBridge\n// =============================================================================\n\n/**\n * Bridges a fhir-definition DefinitionRegistry into our DefinitionProvider.\n *\n * Usage:\n * ```typescript\n * import { loadDefinitionPackages } from 'fhir-definition';\n *\n * const { registry } = await loadDefinitionPackages({ ... });\n * const provider = new FhirDefinitionBridge(registry);\n *\n * // Use with FhirSystem\n * const system = new FhirSystem(adapter);\n * await system.initialize(provider);\n * ```\n */\nexport class FhirDefinitionBridge implements DefinitionProvider {\n private readonly registry: FhirDefinitionRegistry;\n private cachedResourceTypes: string[] | null = null;\n\n constructor(registry: FhirDefinitionRegistry) {\n this.registry = registry;\n }\n\n // ---------------------------------------------------------------------------\n // DefinitionProvider interface\n // ---------------------------------------------------------------------------\n\n getStructureDefinition(url: string): StructureDefinitionDef | undefined {\n const sd = this.registry.getStructureDefinition(url);\n if (!sd) return undefined;\n return sd as StructureDefinitionDef;\n }\n\n getValueSet(url: string): ValueSetDef | undefined {\n const vs = this.registry.getValueSet(url);\n if (!vs) return undefined;\n return vs as ValueSetDef;\n }\n\n getCodeSystem(url: string): CodeSystemDef | undefined {\n const cs = this.registry.getCodeSystem(url);\n if (!cs) return undefined;\n return cs as CodeSystemDef;\n }\n\n getSearchParameters(resourceType: string): SearchParameterDef[] {\n const sps = this.registry.getSearchParameters(resourceType);\n return sps.map((sp: Record<string, unknown>) => ({\n resourceType: 'SearchParameter' as const,\n url: sp.url as string | undefined,\n name: sp.name as string | undefined,\n code: sp.code as string,\n type: sp.type as SearchParameterDef['type'],\n base: sp.base as string[],\n expression: sp.expression as string | undefined,\n target: sp.target as string[] | undefined,\n }));\n }\n\n getAllResourceTypes(): string[] {\n if (this.cachedResourceTypes) return this.cachedResourceTypes;\n\n // Extract resource types from registered StructureDefinitions\n const urls = this.registry.listStructureDefinitions();\n const types: string[] = [];\n\n for (const url of urls) {\n const sd = this.registry.getStructureDefinition(url);\n if (sd && sd.kind === 'resource' && sd.type && !sd.abstract) {\n types.push(sd.type as string);\n }\n }\n\n this.cachedResourceTypes = types;\n return types;\n }\n\n getLoadedPackages(): LoadedPackageDef[] {\n if (!this.registry.getLoadedPackages) return [];\n const pkgs = this.registry.getLoadedPackages();\n return pkgs.map((pkg: Record<string, unknown>) => ({\n name: pkg.name as string,\n version: pkg.version as string,\n loadedAt: pkg.loadedAt as string | undefined,\n resourceCount: pkg.resourceCount as number | undefined,\n }));\n }\n}\n", "/**\n * FhirRuntimeProvider \u2014 Real fhir-runtime Integration\n *\n * Wraps the actual `fhir-runtime` package's `extractSearchValues`,\n * `extractAllSearchValues`, and `extractReferences` functions into\n * the `RuntimeProvider` interface used by `IndexingPipeline`.\n *\n * This replaces the approximate `PropertyPathRuntimeProvider` with\n * real FHIRPath evaluation for precise search value extraction.\n *\n * ADR-01 \u00A74.1b: RuntimeProvider wraps fhir-runtime, never exposing\n * fhir-runtime types to the rest of fhir-persistence.\n *\n * @module fhir-persistence/providers\n */\n\nimport type { SearchParameterDef } from './definition-provider.js';\nimport type { RuntimeProvider, ExtractedReference } from './runtime-provider.js';\n\n// =============================================================================\n// Section 1: fhir-runtime types (structural, not imported)\n// =============================================================================\n\n/**\n * Structural type matching fhir-runtime's SearchParameter.\n * We use structural typing to avoid importing fhir-runtime types directly.\n */\ninterface FhirRuntimeSearchParameter {\n resourceType: 'SearchParameter';\n url: string;\n name: string;\n status: 'draft' | 'active' | 'retired' | 'unknown';\n code: string;\n base: string[];\n type: string;\n expression?: string;\n target?: string[];\n}\n\n/**\n * Structural type matching fhir-runtime's SearchIndexValue.\n * Used internally for normalizing extracted values.\n */\ntype FhirRuntimeSearchIndexValue =\n | { type: 'string'; value: string }\n | { type: 'token'; system?: string; code: string; display?: string }\n | { type: 'reference'; reference: string; resourceType?: string; id?: string }\n | { type: 'date'; value: string }\n | { type: 'number'; value: number }\n | { type: 'quantity'; value: number; unit?: string; system?: string; code?: string }\n | { type: 'uri'; value: string };\n\n// =============================================================================\n// Section 2: FhirRuntimeProvider\n// =============================================================================\n\n/**\n * Options for creating a FhirRuntimeProvider.\n *\n * Uses `any` for function signatures to bridge between fhir-runtime's\n * narrow union types (e.g., SearchParamType) and our structural types.\n * The conversion is handled internally by FhirRuntimeProvider.\n */\nexport interface FhirRuntimeProviderOptions {\n /**\n * The `extractSearchValues` function from fhir-runtime.\n * Signature: (resource: Resource, searchParam: SearchParameter) => SearchIndexEntry\n */\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n extractSearchValues: (resource: any, searchParam: any) => any;\n\n /**\n * The `extractAllSearchValues` function from fhir-runtime.\n * Signature: (resource: Resource, searchParams: SearchParameter[]) => SearchIndexEntry[]\n */\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n extractAllSearchValues: (resource: any, searchParams: any[]) => any[];\n\n /**\n * The `extractReferences` function from fhir-runtime.\n * Signature: (resource: Resource) => ReferenceInfo[]\n */\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n extractReferences: (resource: any) => any[];\n}\n\nexport class FhirRuntimeProvider implements RuntimeProvider {\n private readonly opts: FhirRuntimeProviderOptions;\n\n constructor(options: FhirRuntimeProviderOptions) {\n this.opts = options;\n }\n\n // ---------------------------------------------------------------------------\n // extractSearchValues\n // ---------------------------------------------------------------------------\n\n extractSearchValues(\n resource: Record<string, unknown>,\n params: SearchParameterDef[],\n ): Record<string, unknown[]> {\n const result: Record<string, unknown[]> = {};\n\n // Convert SearchParameterDef \u2192 fhir-runtime SearchParameter shape\n const runtimeParams = params\n .filter(p => p.expression)\n .map(p => this.toRuntimeSearchParameter(p));\n\n // Use extractAllSearchValues for batch extraction\n const entries = this.opts.extractAllSearchValues(\n resource,\n runtimeParams,\n );\n\n for (const entry of entries) {\n if (entry.values.length === 0) continue;\n\n const normalized = this.normalizeSearchValues(entry.values, entry.type);\n if (normalized.length > 0) {\n result[entry.code] = normalized;\n }\n }\n\n return result;\n }\n\n // ---------------------------------------------------------------------------\n // extractReferences\n // ---------------------------------------------------------------------------\n\n extractReferences(\n resource: Record<string, unknown>,\n params: SearchParameterDef[],\n ): ExtractedReference[] {\n const refs: ExtractedReference[] = [];\n\n const runtimeRefs = this.opts.extractReferences(resource);\n\n // Build a map from path \u2192 SP code for reference params\n const pathToCode = new Map<string, string>();\n const resourceType = resource.resourceType as string;\n for (const p of params) {\n if (p.type !== 'reference' || !p.expression) continue;\n // expression might be like \"Observation.subject\" or \"Observation.subject | Observation.focus\"\n const parts = p.expression.split('|').map(s => s.trim());\n for (const part of parts) {\n pathToCode.set(part, p.code);\n }\n }\n\n for (const ref of runtimeRefs) {\n // Skip contained and urn references\n if (ref.referenceType === 'contained' || ref.referenceType === 'urn') continue;\n if (!ref.targetType || !ref.targetId) continue;\n\n // Try to find the SP code from the path\n let code = pathToCode.get(ref.path);\n if (!code) {\n // Try without the resource type prefix\n const pathWithType = `${resourceType}.${ref.path.split('.').slice(1).join('.')}`;\n code = pathToCode.get(pathWithType) ?? ref.path.split('.').pop() ?? 'unknown';\n }\n\n refs.push({\n code: code as string,\n reference: ref.reference,\n targetType: ref.targetType,\n targetId: ref.targetId,\n });\n }\n\n return refs;\n }\n\n // ---------------------------------------------------------------------------\n // Private helpers\n // ---------------------------------------------------------------------------\n\n /**\n * Convert our minimal SearchParameterDef to fhir-runtime's SearchParameter shape.\n */\n private toRuntimeSearchParameter(param: SearchParameterDef): FhirRuntimeSearchParameter {\n return {\n resourceType: 'SearchParameter',\n url: param.url ?? `urn:sp:${param.code}`,\n name: param.name ?? param.code,\n status: 'active',\n code: param.code,\n base: param.base,\n type: param.type,\n expression: param.expression,\n target: param.target,\n };\n }\n\n /**\n * Normalize fhir-runtime SearchIndexValue[] to persistence-friendly unknown[].\n */\n private normalizeSearchValues(\n values: FhirRuntimeSearchIndexValue[],\n type: string,\n ): unknown[] {\n switch (type) {\n case 'token':\n return this.normalizeTokenValues(values);\n case 'reference':\n return values\n .filter((v): v is Extract<FhirRuntimeSearchIndexValue, { type: 'reference' }> => v.type === 'reference')\n .map(v => v.reference);\n case 'date':\n case 'string':\n case 'uri':\n return values\n .filter(v => 'value' in v && typeof (v as Record<string, unknown>).value === 'string')\n .map(v => (v as { value: string }).value);\n case 'number':\n return values\n .filter((v): v is { type: 'number'; value: number } => v.type === 'number')\n .map(v => v.value);\n case 'quantity':\n return values\n .filter((v): v is Extract<FhirRuntimeSearchIndexValue, { type: 'quantity' }> => v.type === 'quantity')\n .map(v => v.value);\n default:\n return values.map(v => 'value' in v ? (v as any).value : v);\n }\n }\n\n /**\n * Normalize token values to \"system|code\" strings.\n */\n private normalizeTokenValues(values: FhirRuntimeSearchIndexValue[]): string[] {\n const tokens: string[] = [];\n for (const v of values) {\n if (v.type === 'token') {\n const system = v.system ?? '';\n tokens.push(`${system}|${v.code}`);\n } else if (v.type === 'string') {\n tokens.push(v.value);\n }\n }\n return tokens;\n }\n}\n\n// =============================================================================\n// Section 3: Factory function\n// =============================================================================\n\n/**\n * Create a FhirRuntimeProvider from the fhir-runtime package.\n *\n * Usage:\n * ```typescript\n * import { extractSearchValues, extractAllSearchValues, extractReferences } from 'fhir-runtime';\n *\n * const provider = createFhirRuntimeProvider({\n * extractSearchValues,\n * extractAllSearchValues,\n * extractReferences,\n * });\n * ```\n */\nexport function createFhirRuntimeProvider(\n options: FhirRuntimeProviderOptions,\n): FhirRuntimeProvider {\n return new FhirRuntimeProvider(options);\n}\n"],
5
+ "mappings": "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CA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EA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",
6
+ "names": ["buildSearchColumns", "buildSearchColumns", "buildSharedTokenColumns", "buildSearchColumns", "buildSharedTokenColumns", "import_node_crypto", "conds", "placeholders", "fragment", "import_node_crypto", "initSqlJs", "Database", "import_node_crypto", "import_node_crypto", "buildSearchColumns"]
7
+ }