-
Notifications
You must be signed in to change notification settings - Fork 2
Backend
The backend of StuyActivities is written in JavaScript. The main technologies/libraries it uses are Node.JS, GraphQL (Apollo), and Sequelize. The actual database uses MySQL, but you can also use SQLite in development. To work on the API, pull the repository and install the dependencies (usually with npm i). You might have trouble installing the SQLite dependency, sqlite3, in which case you may need to install some dependencies as outlined in the Installation section of this page. You can also skip SQLite3 and run a local MySQL server (!). Run the program with npm run dev to work on it, but make sure you run npm authenticate first. You can log in with any account, but make sure you don't put other people's emails in your database or you might end up sending them emails from your account.
-
package.json- outlines the dependencies. -
captain-definition- The backend runs on CapRover (captain.stuysu.org), so each application is a docker container, including the backend and the MySQL server it connects to. This file contains the Dockerfile lines (as a JSON array) required to create the docker container from the code that CapRover pulls from GitHub. TheDockerfilefile contains the same info. Read more about Dockerfiles here. -
src/- the code for the API-
app.db- the SQLite database that gets created if you use SQLite in your development -
index.js- this is the entryway into the app. In production mode, it spawns several workers, one for each CPU core, so that the program can be multi-threaded. -
app.js- this is the main app file. It creates an Express.JS app and adds the GraphQL middleware. It also initializes the tasks that are run on intervals (src/googleApis/gmailWatcherandsrc/utils/createRecurringMeetings). -
constants.js- this contains the constants that the app uses. -
graphql/- this folder contains all of the information and code behind the GraphQL API---this is the meat of the code-
index.js- this is the main GraphQL file. It creates an Apollo server and defines the functions that get passed to resolvers, as well as error handling code and JWT code. -
schema/- this folder contains all of the GraphQL code that defines how the API works-
index.js- this file imports every other file in the folder and exports it in one neat package forsrc/graphql/index.js -
Query.js- this file contains all of the query operations you can make. -
Mutation.js- this file contains all of the mutation operations you can make. - The rest of the files in this folder are GraphQL type definitions.
-
-
resolvers/- this folder contains all of the JavaScript code that implements the schema in thesrc/graphql/schemafolder.-
index.js- this file imports every other file in the folder and exports it in one neat package forsrc/graphql/index.js -
Query/- this folder contains all of the functions for query operations-
index.js- this file imports every other file in the folder and exports it forsrc/graphql/resolvers/index.js
-
-
Mutation/- this folder contains all of the functions for mutations-
index.js- this file imports every other file in the folder and exports it forsrc/graphql/resolvers/index.js -
login/andlinkOAuthPlatform/are sub-folders for functions that are split into multiple files (although usually we'd put these files into thesrc/utilsfolder now)
-
- Every other folder in this directory has files that describe how to get certain properties of the type their folder is named after. For example, the
Meeting/folder has a file calledorganization.jswhich fetches the organization related to the meeting when someone queries for it.
-
-
-
database/- this folder contains information on how to work with the database.-
models/- this folder contains the database models. Each model corresponds to a database table, and describes how the table works. Most of these models are partially or completely automatically generated.-
index.js- this file automatically imports every model in the directory and initializes the Sequelize object.
-
-
migrations/- this folder contains migrations, which are changes made to the database (such as new tables or changes in table structure). Most of these are also automatically generated, although some are created by hand. These files are only run when you runnpm run migrate. -
seeders/- this folder contains files to "seed" the database by adding info to it. These files have not been updated and should not be used. If you need to seed the database, you can download the existing one and create a fake club for yourself to play around with. -
dataloaders/- this folder contains basic methods for loading specific objects from the databse. They are used in the models.
-
-
middleware/- this folder contains various middlewares that theapp.jsfile uses. -
utils/- this folder contains utilities that are either too long to be put into a file with the other code or that are used in multiple places. -
googleApis/- this folder contains the files used for interacting with Google APIs. -
emailTemplates/- this folder contains the email templates used in certain resolvers.
-
If you want to edit the live database directly, go to adminer.stuysu.org and use the credentials located in the stuyactivities-credentials repository or in the environment variables of the mysql app on CapRover. If you don't see the stuyactivities-credentials repo, you might not have access to it. For adminer, use the url captain.stuysu.org or srv-captain--mysql-db, the database stuyactivities, and the user stuyactivities.
If you want to edit your local database, and you're using SQLite, run the command sqlite3 app.db (the app.db folder is located in src/). Then, run any SQL commands you'd like. To make it easier to see, you can change the display format by using .mode (e.g. .mode table). You can also run commands like .schema to get the schema of a table.
In order to create and edit tables, you need to use sequelize-cli to create migrations (it should be installed after you run npm i). Each migration is a change to the database. The first command you need to run is a command that generates the model or migration.
NOTE: When you use sequelize-cli, make sure you do so in the base directory of the API, and not in any sub-directory.
To generate a model, use the command npx sequelize-cli model:generate with the appropriate options. Just running npx sequelize-cli model:generate will list the options, and the types required on the right. As the command will tell you, the only required options are name and attributes. Here is an example command with these options:
npx sequelize-cli model:generate --name rooms --attributes name:string,floor:integer,approvalRequired:booleanYou don't need to include an id, createdAt, or updatedAt, as sequelize automatically includes those.
Once that command has been sucecssfully run, you can make any changes you need to the database model by editing the file in src/database/models/<table name>.js. This includes any associations that you want to include. For example, the updates model includes the following lines dictating its associations:
updates.belongsTo(models.organizations);
updates.belongsTo(models.users, { foreignKey: 'submittingUserId' });
updates.hasMany(models.updateApprovalMessage);You should also add any data loaders in the model. Data loaders are efficient ways of finding certain rows in a table. There are a few generic data loaders in the src/database/dataloaders folder that you might want to include.
- The
findOneLoaderis for finding one entry whose attribute matches the given attribute. For example, the linestatic orgIdLoader = findOneLoader(joinInstructions, 'organizationId');creates an orgIdLoader such that callingjoinInstructions.orgIdLoader(orgId)returns one joinInstruction with theorganizationIdattribute equal toorgId. - The
findManyLoaderdoes the same thing but for multiple items. For example, the linestatic userIdLoader = findManyLoader(updates, 'submittingUserId');creates a userIdLoader such that callingupdates.userIdLoader(userId)returns an array of updates for which thesubmittingUserIdattribute is equal touserId.
Tables are edited through migrations. To generate a migration, run npx sequelize migration:generate with the name attribute. Again, make sure to run the command in the base directory of the API, so it puts the file in the right location.
Once you've done that, it will tell you that it's created a new file. Edit that file with the changes you want to make. This page has more information on what things you can do.
Once you're done with all of the changes, run npm migrate to commit the migrations to the database. The backend will automatically migrate when the master branch is updated, so you don't have to worry about that.
Talk about which functions are provided and stuff (!).