{"id":20603472,"url":"https://github.com/danpoynor/school-admin-sql-rest-api","last_synced_at":"2026-04-10T07:11:54.111Z","repository":{"id":76599334,"uuid":"483783785","full_name":"danpoynor/school-admin-sql-rest-api","owner":"danpoynor","description":"Demo REST API developed using Node.js, Express, and Sequelize provides a way to administer a school database containing information about users and courses.","archived":false,"fork":false,"pushed_at":"2023-04-23T09:57:50.000Z","size":628,"stargazers_count":0,"open_issues_count":7,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-01-17T02:11:50.516Z","etag":null,"topics":["api-server","api-testing","authentication","bcryptjs","demo-app","expressjs","middleware","nodejs","postman","postman-collection","postman-test","rest-api","sequelize","validations"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":false,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/danpoynor.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2022-04-20T19:16:45.000Z","updated_at":"2022-04-27T21:29:18.000Z","dependencies_parsed_at":"2023-02-27T12:30:28.766Z","dependency_job_id":null,"html_url":"https://github.com/danpoynor/school-admin-sql-rest-api","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/danpoynor%2Fschool-admin-sql-rest-api","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/danpoynor%2Fschool-admin-sql-rest-api/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/danpoynor%2Fschool-admin-sql-rest-api/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/danpoynor%2Fschool-admin-sql-rest-api/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/danpoynor","download_url":"https://codeload.github.com/danpoynor/school-admin-sql-rest-api/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":242249023,"owners_count":20096778,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["api-server","api-testing","authentication","bcryptjs","demo-app","expressjs","middleware","nodejs","postman","postman-collection","postman-test","rest-api","sequelize","validations"],"created_at":"2024-11-16T09:17:23.170Z","updated_at":"2026-04-10T07:11:54.081Z","avatar_url":"https://github.com/danpoynor.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# School Admin SQL REST API\n\nDemo REST API developed using Node.js, Express, and Sequelize provides a way to administer a school database containing information about users and courses.\n\n---\n\n## Running the App\n\nAssuming you have `node` and `npm` already installed globally on your system - clone this repo, `cd` into the app folder, then install dependencies:\n\n```bash\ngit clone https://github.com/danpoynor/school-admin-sql-rest-api.git\ncd school-admin-sql-rest-api/\nnpm install\n```\n\nIn the terminal run the `npm run seed` command. This will create the `fsjstd-restapi.db` database and seed it with initial data. Then start the app with `npm start`\n\n```bash\nnpm run seed \u0026\u0026 npm start\n```\n\nIn your terminal output, you should see something similar to the following:\n\n```bash\n✅ 8 Routes found: [\n  { path: '/', method: 'GET' },\n  { path: '/api/courses/', method: 'GET' },\n  { path: '/api/courses/', method: 'POST' },\n  { path: '/api/courses/:id', method: 'GET' },\n  { path: '/api/courses/:id', method: 'PUT' },\n  { path: '/api/courses/:id', method: 'DELETE' },\n  { path: '/api/users/', method: 'GET' },\n  { path: '/api/users/', method: 'POST' }\n]\n✅ Express server is listening on port 5000\n✅ Connection to 'sqlite' database 'fsjstd-restapi.db' established.\n✅ Model 'Course' is defined. Table name is 'Courses'.\n✅ Model 'User' is defined. Table name is 'Users'.\n✅ 2 Tables found: [ 'Users', 'Courses' ] (Uncomment lines below to copy model starters)\n```\n\nVisiting \u003chttp://localhost:5000/\u003e in a web browser you should see a \"Welcome to the REST API project!\" message.\n\nThe `RESTAPI.postman_collection.json` file can be imported into [Postman](https://www.postman.com) to manually test the application. Or import `RESTAPI.postman_collection--with-tests.json` to run 63 automated test assertions (see [note below](#postman-test-collection)).\n\nOr, use the `tests.http` file as an alternative method for testing the application. You'll need to install the [REST Client](https://marketplace.visualstudio.com/items?itemName=humao.rest-client) package as a dependency in order to run the tests in this file.\n\n---\n\n## Project Features\n\n- REST API Validation\n- User Authentication Middleware using [bcryptjs](https://www.npmjs.com/package/bcryptjs).\n- `isEmail` validation of the emailAddress attribute in the User model to ensure that the provided email address is properly formatted.\n- `unique` constraint to the User model to ensure that the provided email address isn't already associated with an existing user.\n- `len` validation to the User model to ensure that the provided password is between 7 and 50 characters long.\n\u003c!-- - Added `is` validation to ensure password meets the following criteria:\n  - At least one uppercase letter\n  - At least one lowercase letter\n  - At least one number\n  - At least one special character --\u003e\n- [Express Hook](https://sequelize.org/docs/v6/other-topics/hooks/) `afterValidate` used to encrypt the User password with [bcryptjs](https://www.npmjs.com/package/bcryptjs)\n after it's validated and before it's saved to the database.\n\n---\n\n## API Endpoints\n\n\u003ccode\u003e\u003cfont color=\"#49cc90\"\u003eGET\u003c/font\u003e\u003c/code\u003e \u003ccode\u003e/\u003c/code\u003e Returns the message \"Welcome to the REST API project!\"\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003ccode\u003e\u003cfont color=\"#49cc90\"\u003eGET\u003c/font\u003e\u003c/code\u003e \u003ccode\u003e/api/users\u003c/code\u003e Returns all properties and values for the currently authenticated \u003ccode\u003eUser\u003c/code\u003e including \u003ccode\u003eCourses\u003c/code\u003e they own\u003c/summary\u003e\n\n\u003ctable\u003e\n  \u003cthead\u003e\n    \u003ctr\u003e\n      \u003cth width=\"120\"\u003eHTTP Status\u003c/th\u003e\n      \u003cth\u003eMessage\u003c/th\u003e\n      \u003cth\u003eNotes\u003c/th\u003e\n    \u003c/tr\u003e\n  \u003c/thead\u003e\n  \u003ctbody\u003e\n    \u003ctr\u003e\n      \u003ctd valign=\"top\"\u003e\u003ccode\u003e200 OK\u003c/code\u003e\u003c/td\u003e\n      \u003ctd\u003e\u003c/td\u003e\n      \u003ctd\u003e\n      User authenticated.\n      Returns all user properties and values.\n        \u003cul\u003e\n          \u003cli\u003eUser authenticated.\u003c/li\u003e\n          \u003cli\u003eReturns all user properties and values including `Courses` the user owns.\u003c/li\u003e\n          \u003cli\u003eFilters out `password`, `createdAt`, and `updatedAt` values.\u003c/li\u003e\n        \u003c/ul\u003e\n      \u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n      \u003ctd valign=\"top\"\u003e\u003ccode\u003e401 Unauthorized\u003c/code\u003e\u003c/td\u003e\u003ctd\u003eAccess Denied\u003c/td\u003e\u003ctd\u003eUser is not authenticated.\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n      \u003ctd\u003e\u003ccode\u003e404 Not Found\u003c/code\u003e\u003c/td\u003e\n      \u003ctd\u003eUser not found\u003c/td\u003e\n      \u003ctd\u003eAn authenticated user should always be able to find their own user record, so this might never be seen.\u003c/td\u003e\n    \u003c/tr\u003e\n  \u003c/tbody\u003e\n\u003c/table\u003e\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003ccode\u003e\u003cfont color=\"#49cc90\"\u003ePOST\u003c/font\u003e\u003c/code\u003e \u003ccode\u003e/api/users\u003c/code\u003e Creates a new user\u003c/summary\u003e\n\n\u003ctable\u003e\n  \u003cthead\u003e\n    \u003ctr\u003e\n      \u003cth width=\"120\"\u003eHTTP Status\u003c/th\u003e\n      \u003cth\u003eMessage\u003c/th\u003e\n      \u003cth\u003eNotes\u003c/th\u003e\n    \u003c/tr\u003e\n  \u003c/thead\u003e\n  \u003ctbody\u003e\n    \u003ctr\u003e\n      \u003ctd valign=\"top\"\u003e\u003ccode\u003e201 Created\u003c/code\u003e\u003c/td\u003e\n      \u003ctd\u003e\u003c/td\u003e\n      \u003ctd\u003e\n        \u003cul\u003e\n          \u003cli\u003eCurrent user is not authenticate before creating a new user.\u003c/li\u003e\n          \u003cli\u003eReturns no content.\u003c/li\u003e\n          \u003cli\u003eSet the \u003ccode\u003eLocation\u003c/code\u003e header to \u003ccode\u003e/\u003c/code\u003e.\u003c/li\u003e\n        \u003c/ul\u003e\n      \u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n      \u003ctd valign=\"top\"\u003e\u003ccode\u003e400 Bad Request\u003c/code\u003e\u003c/td\u003e\n      \u003ctd\u003e\n        \u003cul\u003e\n          \u003cli\u003eFirst Name value is required\u003c/li\u003e\n          \u003cli\u003eLast Name value is required\u003c/li\u003e\n          \u003cli\u003ePassword value is required\u003c/li\u003e\n          \u003cli\u003ePassword must 7 - 50 characters long\u003c/li\u003e\n          \u003c!-- \u003cli\u003ePassword must contain at least 1 uppercase letter, 1 lowercase letter, and 1 number. Special characters $%!@-+= okay.\u003c/li\u003e --\u003e\n          \u003cli\u003eEmail Address value is required\u003c/li\u003e\n          \u003cli\u003eEmail Address format is invalid\u003c/li\u003e\n          \u003cli\u003eEmail Address must be unique\u003c/li\u003e\n          \u003cli\u003eUser already exists\u003c/li\u003e\n        \u003c/ul\u003e\n      \u003c/td\u003e\n      \u003ctd\u003e\u003c/td\u003e\n    \u003c/tr\u003e\n  \u003c/tbody\u003e\n\u003c/table\u003e\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003ccode\u003e\u003cfont color=\"#49cc90\"\u003eGET\u003c/font\u003e\u003c/code\u003e \u003ccode\u003e/api/courses\u003c/code\u003e Returns all courses including the \u003ccode\u003eUser\u003c/code\u003e associated with each course\u003c/summary\u003e\n\n\u003ctable\u003e\n  \u003cthead\u003e\n    \u003ctr\u003e\n      \u003cth width=\"120\"\u003eHTTP Status\u003c/th\u003e\n      \u003cth\u003eMessage\u003c/th\u003e\n      \u003cth\u003eNotes\u003c/th\u003e\n    \u003c/tr\u003e\n  \u003c/thead\u003e\n  \u003ctbody\u003e\n    \u003ctr\u003e\n      \u003ctd valign=\"top\"\u003e\u003ccode\u003e200 OK\u003c/code\u003e\n      \u003c/td\u003e\u003ctd\u003e\u003c/td\u003e\n      \u003ctd\u003e\n        \u003cul\u003e\n          \u003cli\u003eReturns all courses including the User associated with each course.\u003c/li\u003e\n          \u003cli\u003eFilters out `createdAt`, and `updatedAt` values.\u003c/li\u003e\n        \u003c/ul\u003e\n      \u003c/td\u003e\n    \u003c/tr\u003e\n  \u003c/tbody\u003e\n\u003c/table\u003e\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003ccode\u003e\u003cfont color=\"#49cc90\"\u003eGET\u003c/font\u003e\u003c/code\u003e \u003ccode\u003e/api/courses/:id\u003c/code\u003e Returns the corresponding course including the \u003ccode\u003eUser\u003c/code\u003e associated with that course\u003c/summary\u003e\n\n\u003ctable\u003e\n  \u003cthead\u003e\n    \u003ctr\u003e\n      \u003cth width=\"120\"\u003eHTTP Status\u003c/th\u003e\n      \u003cth\u003eMessage\u003c/th\u003e\n      \u003cth\u003eNotes\u003c/th\u003e\n    \u003c/tr\u003e\n  \u003c/thead\u003e\n  \u003ctbody\u003e\n    \u003ctr\u003e\n      \u003ctd valign=\"top\"\u003e\u003ccode\u003e200 OK\u003c/code\u003e\u003c/td\u003e\n      \u003ctd\u003e\u003c/td\u003e\n      \u003ctd\u003e\n        \u003cul\u003e\n          \u003cli\u003eReturns the corresponding course including the User associated with that course.\u003c/li\u003e\n          \u003cli\u003eFilters out `createdAt`, and `updatedAt` values.\u003c/li\u003e\n        \u003c/ul\u003e\n      \u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n      \u003ctd valign=\"top\"\u003e\u003ccode\u003e404 Not Found\u003c/code\u003e\u003c/td\u003e\n      \u003ctd\u003eCourse not found\u003c/td\u003e\n      \u003ctd\u003e\u003c/td\u003e\n    \u003c/tr\u003e\n  \u003c/tbody\u003e\n\u003c/table\u003e\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003ccode\u003e\u003cfont color=\"#49cc90\"\u003ePOST\u003c/font\u003e\u003c/code\u003e \u003ccode\u003e/api/courses\u003c/code\u003e Create a new course, set the Location header to the URI for the newly created course\u003c/summary\u003e\n\n\u003ctable\u003e\n  \u003cthead\u003e\n    \u003ctr\u003e\n      \u003cth width=\"120\"\u003eHTTP Status\u003c/th\u003e\n      \u003cth\u003eMessage\u003c/th\u003e\n      \u003cth\u003eNotes\u003c/th\u003e\n    \u003c/tr\u003e\n  \u003c/thead\u003e\n  \u003ctbody\u003e\n    \u003ctr\u003e\n      \u003ctd valign=\"top\"\u003e\u003ccode\u003e201 Created\u003c/code\u003e\u003c/td\u003e\n      \u003ctd\u003e\u003c/td\u003e\n      \u003ctd\u003e\n        \u003cul\u003e\n          \u003cli\u003eUser authenticated.\u003c/li\u003e\n          \u003cli\u003eReturns no content\u003c/li\u003e\n          \u003cli\u003eSet the \u003ccode\u003eLocation\u003c/code\u003e header to the URI for the newly created course\u003c/li\u003e\n        \u003c/ul\u003e\n      \u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n      \u003ctd valign=\"top\"\u003e\u003ccode\u003e400 Bad Request\u003c/code\u003e\u003c/td\u003e\n      \u003ctd\u003e\n        \u003cul\u003e\n          \u003cli\u003eTitle is required\u003c/li\u003e\n          \u003cli\u003eDescription is required\u003c/li\u003e\n          \u003cli\u003eUser Id is required.\u003c/li\u003e\n        \u003c/ul\u003e\n      \u003c/td\u003e\n      \u003ctd\u003e\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n      \u003ctd valign=\"top\"\u003e\u003ccode\u003e401 Unauthorized\u003c/code\u003e\u003c/td\u003e\n      \u003ctd\u003eAccess Denied\u003c/td\u003e\n      \u003ctd\u003eUser is not authenticated.\u003c/td\u003e\n    \u003c/tr\u003e\n  \u003c/tbody\u003e\n\u003c/table\u003e\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003ccode\u003e\u003cfont color=\"#fca130\"\u003ePUT\u003c/font\u003e\u003c/code\u003e \u003ccode\u003e/api/courses/:id\u003c/code\u003e Update the corresponding course\u003c/summary\u003e\n\n\u003ctable\u003e\n  \u003cthead\u003e\n    \u003ctr\u003e\n      \u003cth width=\"120\"\u003eHTTP Status\u003c/th\u003e\n      \u003cth\u003eMessage\u003c/th\u003e\n      \u003cth\u003eNotes\u003c/th\u003e\n    \u003c/tr\u003e\n  \u003c/thead\u003e\n  \u003ctbody\u003e\n    \u003ctr\u003e\n      \u003ctd valign=\"top\"\u003e\u003ccode\u003e204 No Content\u003c/code\u003e\u003c/td\u003e\n      \u003ctd\u003e\u003c/td\u003e\n      \u003ctd\u003e\n        \u003cul\u003e\n          \u003cli\u003eUser authenticated.\u003c/li\u003e\n          \u003cli\u003eReturns no content.\u003c/li\u003e\n          \u003cli\u003eCourse successfully updated.\u003c/li\u003e\n        \u003c/ul\u003e\n      \u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n      \u003ctd valign=\"top\"\u003e\u003ccode\u003e400 Bad Request\u003c/code\u003e\u003c/td\u003e\n      \u003ctd\u003e\n        \u003cul\u003e\n          \u003cli\u003eTitle is required\u003c/li\u003e\n          \u003cli\u003eDescription is required\u003c/li\u003e\n        \u003c/ul\u003e\n      \u003c/td\u003e\n      \u003ctd\u003e\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n      \u003ctd valign=\"top\"\u003e\u003ccode\u003e401 Unauthorized\u003c/code\u003e\u003c/td\u003e\n      \u003ctd\u003eAccess Denied\u003c/td\u003e\n      \u003ctd\u003eUser is not authenticated.\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n      \u003ctd valign=\"top\"\u003e\u003ccode\u003e403 Forbidden\u003c/code\u003e\u003c/td\u003e\n      \u003ctd\u003eAccess Denied. You are not the owner of this course.\u003c/td\u003e\n      \u003ctd\u003eCurrent user is not the course owner.\u003c/td\u003e\n    \u003c/tr\u003e\n  \u003c/tbody\u003e\n\u003c/table\u003e\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003ccode\u003e\u003cfont color=\"#f93e3e\"\u003eDELETE\u003c/font\u003e\u003c/code\u003e \u003ccode\u003e/api/courses/:id\u003c/code\u003e Delete the corresponding course\u003c/summary\u003e\n\n\u003ctable\u003e\n  \u003cthead\u003e\n    \u003ctr\u003e\n      \u003cth width=\"120\"\u003eHTTP Status\u003c/th\u003e\n      \u003cth\u003eMessage\u003c/th\u003e\n      \u003cth\u003eNotes\u003c/th\u003e\n    \u003c/tr\u003e\n  \u003c/thead\u003e\n  \u003ctbody\u003e\n    \u003ctr\u003e\n      \u003ctd valign=\"top\"\u003e\u003ccode\u003e204 No Content\u003c/code\u003e\u003c/td\u003e\n      \u003ctd\u003e\u003c/td\u003e\n      \u003ctd\u003e\n        \u003cul\u003e\n          \u003cli\u003eUser authenticated.\u003c/li\u003e\n          \u003cli\u003eUser is course owner.\u003c/li\u003e\n          \u003cli\u003eReturns no content.\u003c/li\u003e\n          \u003cli\u003eCourse successfully deleted.\u003c/li\u003e\n        \u003c/ul\u003e\n      \u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n      \u003ctd valign=\"top\"\u003e\u003ccode\u003e401 Unauthorized\u003c/code\u003e\u003c/td\u003e\n      \u003ctd\u003eAccess Denied\u003c/td\u003e\n      \u003ctd\u003eUser is not authenticated.\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n      \u003ctd valign=\"top\"\u003e\u003ccode\u003e403 Forbidden\u003c/code\u003e\u003c/td\u003e\n      \u003ctd\u003eAccess Denied. You are not the owner of this course.\u003c/td\u003e\n      \u003ctd\u003eCurrent user is not the course owner.\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n      \u003ctd valign=\"top\"\u003e\u003ccode\u003e404 Not Found\u003c/code\u003e\u003c/td\u003e\n      \u003ctd\u003eCourse not found.\u003c/td\u003e\n      \u003ctd\u003eTries to find the course before authenticating the owner.\u003c/td\u003e\n    \u003c/tr\u003e\n  \u003c/tbody\u003e\n\u003c/table\u003e\n\n\u003c/details\u003e\n\n---\n\n## Postman Test Collection\n\nThe file `RESTAPI.postman_collection--with-tests.json` includes 63 API endpoint tests ([view Postman Test docs](https://learning.postman.com/docs/writing-scripts/script-references/test-examples/)). To run the collection of tests in [Postman](https://www.postman.com), click the three dots to the right of the name and select `Run Collection` in the dropdown menu ([more info](https://learning.postman.com/docs/running-collections/intro-to-collection-runs/#running-your-collections)).\n\nNote: You'll need to run `npm run seed` before running the tests each time since some endpoints manipulate the database.\n\n\u003cdetails\u003e\n\u003csummary\u003eView sample list of included tests\u003c/summary\u003e\n\nGet Users (With Auth)\n\n- \"Status code is `200 OK`\"\n- \"Response has a JSON body\"\n- \"Response type should be a JSON object\"\n- \"User `id`, `firstName`, `lastName`, `email` is returned\"\n- \"User owned `courses` array is returned\"\n- \"Courses length is 2\"\n- \"Response should not include `password`, `createdAt`, `updatedAt`\"\n\nCreate User (with dynamic values)\n\n- \"Status code is `201 Created`\"\n- \"Response should contain no content\"\n- \"`Location` header is `/`\"\n  \nCreate User (Existing Email Address) - EXCEEDS\n\n- \"Status code is 400 Bad Request\"\n- \"Response has a JSON body\"\n- \"'Email Address must be unique' error message should be returned\"\n  \nGet Courses\n\n- \"Status code is `200 OK`\"\n- \"Response has a JSON body\"\n- \"Response type should be a JSON array\"\n- \"Should return more than 1 courses\"\n- \"Should contain some correct titles\"\n- \"Course owners `firstName` and `lastName` should be included with each course\"\n- \"Response should not include `createdAt`, `updatedAt`\"\n  \netc...\n\n\u003c/details\u003e\n\n---\n\n## Other Notes\n\n- `sequelize.getDatabaseName()` returns `undefined` even though `.authenticate()` will return successful when `dialect` is set to `sqlite`. The function does not read the `config.json` `storage` value, so I kept the `database` value in `config.json`, even though I don't think it should be needed. Potential Sequelize issue or feature request needed to fix this, perhaps.\n- When the app first starts, the fancy logging messages in the terminal (with ✅ and ❌ icons) are my development sanity checks indicating the app is correctly configured initially and I haven't broken anything. If this code ever sees a production environment, I would remove the messages or use [`debug`](https://www.npmjs.com/package/debug) for logging.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdanpoynor%2Fschool-admin-sql-rest-api","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdanpoynor%2Fschool-admin-sql-rest-api","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdanpoynor%2Fschool-admin-sql-rest-api/lists"}