Skip to content

feat: add MongoDB support with MongoStore implementation#49

Draft
pierzchala-m wants to merge 1 commit into
mainfrom
mongodb-support
Draft

feat: add MongoDB support with MongoStore implementation#49
pierzchala-m wants to merge 1 commit into
mainfrom
mongodb-support

Conversation

@pierzchala-m

Copy link
Copy Markdown
Collaborator
  • Added mongodb dependency to package.json
  • Implemented MongoStore class for data management with MongoDB
  • Integrated MongoStore into server initialization logic
  • Added schema versioning and migration handling for MongoDB
  • Created necessary document interfaces for MongoDB collections
  • Implemented CRUD operations for systems, locations, schedules, slots, and appointments in MongoStore
  • Added methods for handling HL7 message logging and slot holds

- Added mongodb dependency to package.json
- Implemented MongoStore class for data management with MongoDB
- Integrated MongoStore into server initialization logic
- Added schema versioning and migration handling for MongoDB
- Created necessary document interfaces for MongoDB collections
- Implemented CRUD operations for systems, locations, schedules, slots, and appointments in MongoStore
- Added methods for handling HL7 message logging and slot holds
Copilot AI review requested due to automatic review settings May 28, 2026 19:15

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot encountered an error and was unable to review this pull request. You can try again by re-requesting a review.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 7 out of 8 changed files in this pull request and generated 10 comments.

Comment thread src/store/mongoStore.ts
Comment on lines +216 to +226
await this.meta.updateOne(
{ key: 'schema_version' },
{ $set: { value: String(MONGO_SCHEMA_VERSION) } },
{ upsert: true }
);

return {
current,
expected: MONGO_SCHEMA_VERSION,
match: current === MONGO_SCHEMA_VERSION || current === 0,
migrated: current !== MONGO_SCHEMA_VERSION,
Comment thread src/server.ts
if (!schemaStatus.match) {
startupWarnings.push(
`⚠️ Mongo schema mismatch: database is v${schemaStatus.current}, code expects v${MONGO_SCHEMA_VERSION}`,
` Auto-migrated to v${MONGO_SCHEMA_VERSION}`,
Comment thread src/store/mongoStore.ts
}

function nowIso(): string {
return new Date().toISOString();
Comment thread src/store/mongoStore.ts
Comment on lines +679 to +680
filter.planningHorizonStart = { $lte: query.date };
filter.planningHorizonEnd = { $gte: query.date };
Comment thread src/store/mongoStore.ts
Comment on lines +716 to +721
actor: schedule.actor !== undefined ? schedule.actor : existing.actor,
planningHorizonStart: schedule.planningHorizon?.start !== undefined ? schedule.planningHorizon.start : existing.planningHorizonStart,
planningHorizonEnd: schedule.planningHorizon?.end !== undefined ? schedule.planningHorizon.end : existing.planningHorizonEnd,
comment: schedule.comment !== undefined ? schedule.comment : existing.comment,
metaLastUpdated: nowIso(),
};
Comment thread src/store/mongoStore.ts
Comment on lines +1029 to +1054
const existingHold = await this.getActiveHold(slotId);
if (existingHold) {
if (existingHold.sessionId === sessionId) {
const newExpiry = new Date(Date.now() + durationMinutes * 60 * 1000).toISOString();
await this.slotHolds.updateOne({ id: existingHold.id }, { $set: { expiresAt: newExpiry } });
return { ...existingHold, expiresAt: newExpiry };
}
throw new Error(`Slot ${slotId} is already held by another user`);
}

const id = this.generateId();
const holdToken = `hold-${Date.now()}-${Math.random().toString(36).slice(2, 11)}`;
const createdAt = nowIso();
const expiresAt = new Date(Date.now() + durationMinutes * 60 * 1000).toISOString();

const hold: SlotHoldDoc = {
id,
slotId,
holdToken,
sessionId,
createdAt,
expiresAt,
};

await this.slotHolds.insertOne(hold);
return this.toSlotHold(hold);
Comment thread src/store/mongoStore.ts
Comment on lines +289 to +297
const extension: Array<{ url: string; valueString?: string }> = [];
if (doc.systemId) {
const system = await this.systems.findOne({ id: doc.systemId });
if (system?.name) {
extension.push({
url: 'https://fhirtogether.org/fhir/StructureDefinition/system-name',
valueString: system.name,
});
}
Comment thread src/store/mongoStore.ts
Comment on lines +271 to +287
private async toSchedule(doc: ScheduleDoc): Promise<Schedule> {
const schedule: Schedule & { extension?: Array<{ url: string; valueString?: string }>; system_id?: string; location_id?: string } = {
resourceType: 'Schedule',
id: doc.id,
active: doc.active,
serviceCategory: doc.serviceCategory,
serviceType: doc.serviceType,
specialty: doc.specialty,
actor: doc.actor,
planningHorizon: doc.planningHorizonStart
? { start: doc.planningHorizonStart, end: doc.planningHorizonEnd }
: undefined,
comment: doc.comment,
meta: { lastUpdated: doc.metaLastUpdated },
system_id: doc.systemId,
location_id: doc.locationId,
};
Comment thread docker-compose.yml
Comment on lines 2 to +19
@@ -12,4 +14,17 @@ services:
environment:
- NODE_ENV=production
- SQLITE_DB_PATH=/app/data/fhirtogether.db
command: npm run dev No newline at end of file
- MONGO_URI=mongodb://mongo:27017
- MONGO_DB_NAME=fhirtogether
command: npm run dev
Comment thread src/server.ts
Comment on lines +175 to +188
} else if (STORE_BACKEND === 'mongo') {
store = new MongoStore();
const schemaStatus = await store.initialize();

if (!schemaStatus.match) {
startupWarnings.push(
`⚠️ Mongo schema mismatch: database is v${schemaStatus.current}, code expects v${MONGO_SCHEMA_VERSION}`,
` Auto-migrated to v${MONGO_SCHEMA_VERSION}`,
);
} else if (schemaStatus.migrated && schemaStatus.current === 0) {
fastify.log.info('Fresh Mongo database - schema initialized at v' + MONGO_SCHEMA_VERSION);
}

fastify.log.info('Mongo store initialized (schema v' + MONGO_SCHEMA_VERSION + ')');
@pierzchala-m pierzchala-m marked this pull request as draft June 15, 2026 14:45
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants