diff --git a/setup-mysql-user.sql b/setup-mysql-user.sql index af00878..afe2fa2 100644 --- a/setup-mysql-user.sql +++ b/setup-mysql-user.sql @@ -21,3 +21,4 @@ GRANT UPDATE ON openneo_impress.swf_assets TO impress2020; -- User data tables GRANT SELECT ON openneo_impress.item_outfit_relationships TO impress2020; GRANT SELECT ON openneo_impress.outfits TO impress2020; +GRANT SELECT ON openneo_impress.users TO impress2020; diff --git a/src/server/index.js b/src/server/index.js index 272abd6..20d7474 100644 --- a/src/server/index.js +++ b/src/server/index.js @@ -222,6 +222,11 @@ const typeDefs = gql` items: [Item!]! # deprecated alias for wornItems } + type User { + id: ID! + username: String! + } + type Query { allColors: [Color!]! @cacheControl(maxAge: 10800) # Cache for 3 hours (we might add more!) allSpecies: [Species!]! @cacheControl(maxAge: 10800) # Cache for 3 hours (we might add more!) @@ -256,6 +261,8 @@ const typeDefs = gql` color(id: ID!): Color species(id: ID!): Species + user(id: ID!): User + petOnNeopetsDotCom(petName: String!): Outfit } @@ -605,6 +612,12 @@ const resolvers = { .map((oir) => ({ id: oir.itemId })); }, }, + User: { + username: async ({ id }, _, { userLoader }) => { + const user = await userLoader.load(id); + return user.name; + }, + }, Query: { allColors: async (_, { ids }, { colorLoader }) => { const allColors = await colorLoader.loadAll(); @@ -688,6 +701,19 @@ const resolvers = { return petStates.map((petState) => ({ id: petState.id })); }, outfit: (_, { id }) => ({ id }), + user: async (_, { id }, { userLoader }) => { + try { + const user = await userLoader.load(id); + } catch (e) { + if (e.message.includes("could not find user")) { + return null; + } else { + throw e; + } + } + + return { id }; + }, petOnNeopetsDotCom: async (_, { petName }) => { const [petMetaData, customPetData] = await Promise.all([ neopets.loadPetMetaData(petName), diff --git a/src/server/loaders.js b/src/server/loaders.js index 2075fcb..1c4c316 100644 --- a/src/server/loaders.js +++ b/src/server/loaders.js @@ -425,6 +425,23 @@ const buildPetStatesForPetTypeLoader = (db, loaders) => ); }); +const buildUserLoader = (db) => new DataLoader(async (ids) => { + const qs = ids.map((_) => "?").join(","); + const [rows, _] = await db.execute( + `SELECT * FROM users WHERE id IN (${qs})`, + ids + ); + + const entities = rows.map(normalizeRow); + const entitiesById = new Map(entities.map((e) => [e.id, e])); + + return ids.map( + (id) => + entitiesById.get(String(id)) || + new Error(`could not find user with ID: ${id}`) + ); +}); + const buildZoneLoader = (db) => { const zoneLoader = new DataLoader(async (ids) => { const qs = ids.map((_) => "?").join(","); @@ -504,6 +521,7 @@ function buildLoaders(db) { ); loaders.speciesLoader = buildSpeciesLoader(db); loaders.speciesTranslationLoader = buildSpeciesTranslationLoader(db); + loaders.userLoader = buildUserLoader(db); loaders.zoneLoader = buildZoneLoader(db); loaders.zoneTranslationLoader = buildZoneTranslationLoader(db); diff --git a/src/server/query-tests/User.test.js b/src/server/query-tests/User.test.js new file mode 100644 index 0000000..87b2948 --- /dev/null +++ b/src/server/query-tests/User.test.js @@ -0,0 +1,63 @@ +const gql = require("graphql-tag"); +const { query, getDbCalls } = require("./setup.js"); + +describe("User", () => { + it("looks up a user", async () => { + const res = await query({ + query: gql` + query { + user(id: "6") { + id + username + } + } + `, + }); + + expect(res).toHaveNoErrors(); + expect(res.data).toMatchInlineSnapshot(` + Object { + "user": Object { + "id": "6", + "username": "matchu", + }, + } + `); + expect(getDbCalls()).toMatchInlineSnapshot(` + Array [ + Array [ + "SELECT * FROM users WHERE id IN (?)", + Array [ + "6", + ], + ], + ] + `); + }); + + it("returns null when user not found", async () => { + const res = await query({ + query: gql` + query { + user(id: "") { + id + username + } + } + `, + }); + + expect(res).toHaveNoErrors(); + expect(res.data.user).toBe(null); + expect(getDbCalls()).toMatchInlineSnapshot(` + Array [ + Array [ + "SELECT * FROM users WHERE id IN (?)", + Array [ + "", + ], + ], + ] + `); + }); +});