Central Query provides a set of endpoints to query a MongoDB database containing meeting data. The current iteration uses a copy of the OIAA database as a demo of the capability.
This project serves as a proof-of-concept for Code for Recovery, demonstrating centralized management of meetings for entities around the globe.
-
Request access to a MongoDB collection of meeting data set up for testing and development.
-
Add a
.envfile containing:NODE_ENV=development MONGO_DB_NAME=central-exp # Example for local MongoDB server: # MONGO_URI=mongodb://root:example@localhost:27017/?authSource=admin&readPreference=primary&directConnection=true&ssl=false MONGO_URI=mongodb+srv://<username>:<password>@<databaseURL>
-
Clone the repo, and run
npm installinside the root folder. -
Run
npm run testto see the results of the unit tests. -
Run the server, using
npm run build && npm run startornpm run start-devto execute a version that will reload upon saving code changes.
Please note: This app uses "pure" ES modules and not the older CommonJS modules. Please stick with this approach.
Bugs and feature requests are tracked using GitHub Issues for the repo.
Gets meetings, accepting several query parameter options. If the start option is not provided, the API defaults to now based on the UTC time when the request is received. If no other parameters are passed, the controller limits the fetch to the next hour of meetings. (Note: This is a bug. See this issue for details.)
Options include:
communities: An array element of communitiesfeatures: An array element of featuresformats: An array element of formatshours: A number used to limit the range of meetings returned by the endpoint. The default is 1.languages: An Array element of alpha2 language codes based on ISO 639-1limit: A number representing how many meetings will be returned. Defaults to 1000 if not included. (Note: It is unclear if this option useful to a client, and it may be deprecated.)nameQuery: A case-insensitive string used to search for meetings by name. Partial matches are supported.scheduled: A boolean to filter meetings by schedule status. Defaults totrue(scheduled meetings). Set tofalseto retrieve unscheduled meetings withoutnextEventUTC.start: A timestamp reflecting the start time for meetings to be returned. For example, to get the next meeting starting after 2300 UTC:/api/v1/meetings/next?limit=1&start=20240113T230000Ztype: A string, either O (for Open) or C (for Closed)
Note: The API adjusts the query to include meetings started within the past 10 minutes.
To Do:
- If the fetched results are <10 meetings, re-fetch for the next two hours.
- Ensure API can handle fractional
hoursand then set default to 45 minutes.
Provides an object containing the active categories and languages associated with scheduled and unscheduled meetings in the database. These are only those values associated with active meetings, and not a complete list of all languages or categories that might exist.
See the specific interface of the MeetingFacets object.
See the specifics of the languages and categories interfaces.
Uses the slug to determine and provide details from a meeting and associated group. See MeetingGroup interface.
This API provides the OnlineMeeting interface (aliased as Meeting) which is better aligned to the terms used by Meeting Guide and, hopefully, Central.
Additionally, GroupDetails provides group specifics, including other meetings.
See the specifics of the interfaces.
The draft MeetingsOptions interface has been implemented for experimentation.
These should still be considered unstable.
Ignore, unless testing server-side proof of concept. These were added for testing, and will eventually be removed after suitable e2e tests are added.
central-query comes with jest for unit tests and Cypress for integration tests. Please continue to write tests for new code.
To make node work with ES modules, the node option of --experimental-vm-modules must be used as of node 18. This requirement should go away in the future.
To check coverage, execute NODE_OPTION=--experimental-vm-modules npx jest --coverage in the terminal. Currently 100% of the utils and common functions are covered by tests. A smaller percentage of the storage functions are covered in unit tests, but more of them are covered through Cypress.
To use Cypress to run tests during dev, start the api server using npm run start-dev. You should see output similar to:
1/13/2024, 10:54:41 PM debug: Routes registered.
1/13/2024, 10:54:41 PM info: Server listening on port 5001 with database connected to central-exp.
listening on port 5001In another terminal, execute npx cypress open. You may be presented with some configuration options, but then get a screen asking you to select E2E Testing. Do that, and then chose which browser to use. I use FireFox.
Integration tests can be found under the cypress/e2e folder.
Please ask for a demo if you're unfamiliar with Cypress. There is no reason to struggle, and once it is working, it is really a powerful dev environment.
This repo contains a Dockerfile used to build an image of the API server. Although not currently included, a Makefile has been created to create and push the image to the author's GitHub. Until this process is updated, the original author can push the images and update the demo on the C4R VPS.
Prefer to use the Udacity style guide for commits. There are other practices which are similar and should be fine, so feel free to discuss options.
Some, but not all, of the coding style choices are included in .prettierrc. This needs to be updated as we go along. For example, my vscode settings enforce two spaces for indents as I find it more readable with modern fonts. I'm also in the camp that agrees semi-colons are unnecessary. All of these style choices can be discussed, of course.
Using MongoDB's Compass app connected to the local database, create an aggregation against the meeting collection and then create the view meeting-view using Save->Create view.
[
{
"$lookup": {
"from": "group",https://code4recovery.slack.com/files/U010NSRGL31/F08PFNSH7AL/screenshot_2025-04-18_at_8.46.03___am.png
"$addFields": {
"groupEmail": {
"$arrayElemAt": ["$groupInfo.email", 0]
},
"groupWebsite": {
"$arrayElemAt": ["$groupInfo.website", 0]
},
"groupPhone": {
"$arrayElemAt": ["$groupInfo.phone", 0]
},
"groupNotes": {
"$arrayElemAt": ["$groupInfo.notes", 0]
}
}
},
{
"$addFields": {
"timeUTC": {
"$dateFromParts": {
"year": {
"$year": {
"date": "$$NOW",
"timezone": "$timezone"
}
},
"month": {
"$month": {
"date": "$$NOW",
"timezone": "$timezone"
}
},
"day": {
"$dayOfMonth": {
"date": "$$NOW",
"timezone": "$timezone"
}
},
"hour": {
"$hour": {
"date": "$startDateUTC",
"timezone": "$timezone"
}
},
"minute": {
"$minute": {
"date": "$startDateUTC",
"timezone": "$timezone"
}
},
"timezone": "$timezone"
}
},
"nowWeekday": {
"$toInt": {
"$dateToString": {
"date": "$$NOW",
"format": "%u"
}
}
},
"rtcWeekday": {
"$toInt": {
"$dateToString": {
"date": "$startDateUTC",
"format": "%u"
}
}
},
"dayOfWeekStr": {
"$dateToString": {
"date": "$startDateUTC",
"format": "%u"
}
}
}
},
{
"$addFields": {
"sortRTCDay": {
"$cond": {
"if": {
"$gte": ["$rtcWeekday", "$nowWeekday"]
},
"then": {
"$subtract": ["$rtcWeekday", 7]
},
"else": "$rtcWeekday"
}
},
"sortRTCTime": {
"$dateToString": {
"date": "$timeUTC",
"format": "%H:%M"
}
},
"rtc": {
"$concat": [
"$dayOfWeekStr",
":",
{
"$dateToString": {
"date": "$timeUTC",
"format": "%H:%M"
}
}
]
}
}
},
{
"$project": {
"_id": 0,
"startDateUTC": 0,
"time": 0,
"day": 0,
"archived": 0,
"accountID": 0,
"groupInfo": 0,
"createdAt": 0,
"updatedAt": 0,
"nowWeekday": 0,
"rtcWeekday": 0,
"dayOfWeekStr": 0
}
},
{
"$sort": {
"sortRTCDay": 1,
"sortRTCTime": 1,
"name": 1
}
},
{
"$project": {
"sortRTCDay": 0,
"sortRTCTime": 0
}
}
]- Add validation in the route file
- Discuss and implement API token requirements
- Document proposed database changes (Central) to support this API
- Add/refine endpoint filter options based on type, language and other criteria
- Re-work process to push image to C4R repo vice the original author's repo