Modernize the API.

This commit is contained in:
Jayden Seric 2021-06-11 15:23:05 +10:00
parent 9d5dfe07d8
commit 3db018dcc4
4 changed files with 368 additions and 559 deletions

848
api/package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -20,25 +20,25 @@
"npm": ">= 7" "npm": ">= 7"
}, },
"dependencies": { "dependencies": {
"apollo-server-koa": "^2.24.1", "apollo-server-koa": "^2.25.1",
"dotenv": "^10.0.0", "dotenv": "^10.0.0",
"graphql": "^15.5.0", "graphql": "^15.5.0",
"graphql-upload": "^12.0.0", "graphql-upload": "^12.0.0",
"koa": "^2.13.1", "koa": "^2.13.1",
"lowdb": "^1.0.0", "lowdb": "^2.1.0",
"mkdirp": "^1.0.4", "make-dir": "^3.1.0",
"shortid": "^2.2.16" "shortid": "^2.2.16"
}, },
"devDependencies": { "devDependencies": {
"eslint": "^7.27.0", "eslint": "^7.28.0",
"eslint-config-env": "^20.0.1", "eslint-config-env": "^20.0.1",
"eslint-config-prettier": "^8.3.0", "eslint-config-prettier": "^8.3.0",
"eslint-plugin-import": "^2.23.3", "eslint-plugin-import": "^2.23.4",
"eslint-plugin-jsdoc": "^35.0.0", "eslint-plugin-jsdoc": "^35.1.3",
"eslint-plugin-node": "^11.1.0", "eslint-plugin-node": "^11.1.0",
"eslint-plugin-prettier": "^3.4.0", "eslint-plugin-prettier": "^3.4.0",
"nodemon": "^2.0.7", "nodemon": "^2.0.7",
"prettier": "^2.3.0" "prettier": "^2.3.1"
}, },
"scripts": { "scripts": {
"test": "npm run test:eslint && npm run test:prettier", "test": "npm run test:eslint && npm run test:prettier",

View File

@ -7,7 +7,10 @@ export default new GraphQLObjectType({
uploads: { uploads: {
description: 'All stored files.', description: 'All stored files.',
type: GraphQLNonNull(GraphQLList(GraphQLNonNull(FileType))), type: GraphQLNonNull(GraphQLList(GraphQLNonNull(FileType))),
resolve: (source, args, { db }) => db.get('uploads').value(), async resolve(source, args, { db }) {
await db.read();
return db.data.uploads;
},
}, },
}), }),
}); });

View File

@ -1,21 +1,18 @@
import { createWriteStream, unlink } from 'fs'; import { createWriteStream, unlink } from 'fs';
import { fileURLToPath } from 'url';
import { ApolloServer } from 'apollo-server-koa'; import { ApolloServer } from 'apollo-server-koa';
import { graphqlUploadKoa } from 'graphql-upload'; import { graphqlUploadKoa } from 'graphql-upload';
import Koa from 'koa'; import Koa from 'koa';
import lowdb from 'lowdb'; // `eslint-plugin-node` doesnt support the package `exports` field, see:
import FileSync from 'lowdb/adapters/FileSync.js'; // https://github.com/mysticatea/eslint-plugin-node/issues/255
import mkdirp from 'mkdirp'; // eslint-disable-next-line node/no-missing-import
import shortid from 'shortid'; import { JSONFile, Low } from 'lowdb';
import makeDir from 'make-dir';
import shortId from 'shortid';
import schema from './schema/index.mjs'; import schema from './schema/index.mjs';
const UPLOAD_DIR = './uploads'; const UPLOAD_DIR = new URL('uploads/', import.meta.url);
const db = lowdb(new FileSync('db.json')); const db = new Low(new JSONFile('db.json'));
// Seed an empty DB.
db.defaults({ uploads: [] }).write();
// Ensure upload directory exists.
mkdirp.sync(UPLOAD_DIR);
/** /**
* Stores a GraphQL file upload. The file is stored in the filesystem and its * Stores a GraphQL file upload. The file is stored in the filesystem and its
@ -26,8 +23,8 @@ mkdirp.sync(UPLOAD_DIR);
async function storeUpload(upload) { async function storeUpload(upload) {
const { createReadStream, filename, mimetype } = await upload; const { createReadStream, filename, mimetype } = await upload;
const stream = createReadStream(); const stream = createReadStream();
const id = shortid.generate(); const id = shortId.generate();
const path = `${UPLOAD_DIR}/${id}-${filename}`; const path = new URL(`${id}-${filename}`, UPLOAD_DIR);
const file = { id, filename, mimetype, path }; const file = { id, filename, mimetype, path };
// Store the file in the filesystem. // Store the file in the filesystem.
@ -56,7 +53,9 @@ async function storeUpload(upload) {
}); });
// Record the file metadata in the DB. // Record the file metadata in the DB.
db.get('uploads').push(file).write(); await db.read();
db.data.uploads.push(file);
await db.write();
return file; return file;
} }
@ -81,10 +80,29 @@ new ApolloServer({
context: { db, storeUpload }, context: { db, storeUpload },
}).applyMiddleware({ app }); }).applyMiddleware({ app });
app.listen(process.env.PORT, (error) => { /**
if (error) throw error; * Starts the API server.
*/
async function startServer() {
await db.read();
console.info( // Seed an empty DB.
`Serving http://localhost:${process.env.PORT} for ${process.env.NODE_ENV}.` if (!db.data) {
); db.data = { uploads: [] };
});
await db.write();
}
// Ensure upload directory exists.
await makeDir(fileURLToPath(UPLOAD_DIR));
app.listen(process.env.PORT, (error) => {
if (error) throw error;
console.info(
`Serving http://localhost:${process.env.PORT} for ${process.env.NODE_ENV}.`
);
});
}
startServer();