add isCommonlyUsedByItems to Zone
This is in preparation for hiding bio zone restrictions but showing item zone restrictions! I also refactor the build-cached-data script substantially, to run GraphQL against the server instead of a custom query.
This commit is contained in:
parent
8f9f1a14de
commit
3a6e3fac8e
5 changed files with 95 additions and 31 deletions
|
@ -1,41 +1,62 @@
|
|||
// We run this on build to cache some stable database tables into the JS
|
||||
// bundle!
|
||||
require("honeycomb-beeline")({
|
||||
writeKey: process.env["HONEYCOMB_WRITE_KEY"],
|
||||
dataset:
|
||||
process.env["NODE_ENV"] === "production"
|
||||
? "Dress to Impress (2020)"
|
||||
: "Dress to Impress (2020, dev)",
|
||||
serviceName: "impress-2020-build-process",
|
||||
});
|
||||
const fs = require("fs").promises;
|
||||
const path = require("path");
|
||||
|
||||
const { ApolloServer } = require("apollo-server");
|
||||
const { createTestClient } = require("apollo-server-testing");
|
||||
const gql = require("graphql-tag");
|
||||
|
||||
const connectToDb = require("../src/server/db");
|
||||
const { normalizeRow } = require("../src/server/util");
|
||||
const { config } = require("../src/server");
|
||||
|
||||
const cachedDataPath = path.join(__dirname, "..", "src", "app", "cached-data");
|
||||
|
||||
async function buildZonesCache(db) {
|
||||
const [rows] = await db.query(
|
||||
`SELECT z.id, z.depth, zt.label FROM zones z ` +
|
||||
`INNER JOIN zone_translations zt ON z.id = zt.zone_id ` +
|
||||
`WHERE locale = "en" ORDER BY z.id;`
|
||||
);
|
||||
const entities = rows.map(normalizeRow);
|
||||
async function main() {
|
||||
await fs.mkdir(cachedDataPath, { recursive: true });
|
||||
|
||||
// Check out this scrappy way of making a query against server code ^_^`
|
||||
const { query } = createTestClient(new ApolloServer(config));
|
||||
const res = await query({
|
||||
query: gql`
|
||||
query BuildCachedData {
|
||||
allZones {
|
||||
id
|
||||
label
|
||||
depth
|
||||
isCommonlyUsedByItems
|
||||
}
|
||||
}
|
||||
`,
|
||||
});
|
||||
if (res.errors) {
|
||||
for (const error of res.errors) {
|
||||
console.error(error);
|
||||
}
|
||||
throw new Error(`GraphQL request failed`);
|
||||
}
|
||||
|
||||
const filePath = path.join(cachedDataPath, "zones.json");
|
||||
fs.writeFile(filePath, JSON.stringify(entities, null, 4), "utf8");
|
||||
await fs.writeFile(
|
||||
filePath,
|
||||
JSON.stringify(res.data.allZones, null, 4),
|
||||
"utf8"
|
||||
);
|
||||
|
||||
console.log(`📚 Wrote zones to ${path.relative(process.cwd(), filePath)}`);
|
||||
}
|
||||
|
||||
async function main() {
|
||||
const db = await connectToDb();
|
||||
await fs.mkdir(cachedDataPath, { recursive: true });
|
||||
|
||||
try {
|
||||
await buildZonesCache(db);
|
||||
} catch (e) {
|
||||
db.close();
|
||||
throw e;
|
||||
}
|
||||
db.close();
|
||||
}
|
||||
|
||||
main().catch((e) => {
|
||||
main()
|
||||
.catch((e) => {
|
||||
console.error(e);
|
||||
process.exitCode = 1;
|
||||
});
|
||||
process.exit(1);
|
||||
})
|
||||
.then(() => process.exit());
|
||||
|
|
|
@ -105,6 +105,15 @@ const typePolicies = {
|
|||
const id = readField("id");
|
||||
return label || cachedZonesById.get(id)?.label || `Zone #${id}`;
|
||||
},
|
||||
|
||||
isCommonlyUsedByItems: (isCommonlyUsedByItems, { readField }) => {
|
||||
const id = readField("id");
|
||||
return (
|
||||
isCommonlyUsedByItems ||
|
||||
cachedZonesById.get(id)?.isCommonlyUsedByItems ||
|
||||
false
|
||||
);
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
const { gql, makeExecutableSchema } = require("apollo-server");
|
||||
import { addBeelineToSchema, beelinePlugin } from "./lib/beeline-graphql";
|
||||
const { addBeelineToSchema, beelinePlugin } = require("./lib/beeline-graphql");
|
||||
|
||||
const connectToDb = require("./db");
|
||||
const buildLoaders = require("./loaders");
|
||||
|
@ -177,6 +177,7 @@ const typeDefs = gql`
|
|||
id: ID!
|
||||
depth: Int!
|
||||
label: String!
|
||||
isCommonlyUsedByItems: Boolean!
|
||||
}
|
||||
|
||||
type ItemSearchResult {
|
||||
|
@ -224,6 +225,7 @@ const typeDefs = gql`
|
|||
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!)
|
||||
allValidSpeciesColorPairs: [SpeciesColorPair!]! # deprecated
|
||||
allZones: [Zone!]!
|
||||
item(id: ID!): Item
|
||||
items(ids: [ID!]!): [Item!]!
|
||||
itemSearch(query: String!): ItemSearchResult!
|
||||
|
@ -536,6 +538,15 @@ const resolvers = {
|
|||
const zoneTranslation = await zoneTranslationLoader.load(id);
|
||||
return zoneTranslation.label;
|
||||
},
|
||||
isCommonlyUsedByItems: async ({ id }, _, { zoneLoader }) => {
|
||||
// Zone metadata marks item zones with types 2, 3, and 4. But also, in
|
||||
// practice, the Biology Effects zone (type 1) has been used for a few
|
||||
// items too. So, that's what we return true for!
|
||||
const zone = await zoneLoader.load(id);
|
||||
const isMarkedForItems = ["2", "3", "4"].includes(zone.typeId);
|
||||
const isBiologyEffects = zone.id === "4";
|
||||
return isMarkedForItems || isBiologyEffects;
|
||||
},
|
||||
},
|
||||
Color: {
|
||||
name: async ({ id }, _, { colorTranslationLoader }) => {
|
||||
|
@ -599,6 +610,10 @@ const resolvers = {
|
|||
}));
|
||||
return allPairs;
|
||||
},
|
||||
allZones: async (_, __, { zoneLoader }) => {
|
||||
const zones = await zoneLoader.loadAll();
|
||||
return zones.map(({ id }) => ({ id }));
|
||||
},
|
||||
item: (_, { id }) => ({ id }),
|
||||
items: (_, { ids }) => {
|
||||
return ids.map((id) => ({ id }));
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
const beeline = require("honeycomb-beeline");
|
||||
const gql = require("graphql");
|
||||
|
||||
export function addBeelineToSchema(schema) {
|
||||
function addBeelineToSchema(schema) {
|
||||
if (!beeline) return;
|
||||
forEachField(schema, (field) => {
|
||||
if (!field.resolve) return;
|
||||
|
@ -68,7 +68,7 @@ const fieldsFor = (name, path) => ({
|
|||
"graphql.key": path.split(".").pop(),
|
||||
});
|
||||
|
||||
export const beelinePlugin = {
|
||||
const beelinePlugin = {
|
||||
requestDidStart() {
|
||||
const trace = beeline.startTrace();
|
||||
return {
|
||||
|
@ -84,3 +84,8 @@ export const beelinePlugin = {
|
|||
};
|
||||
},
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
addBeelineToSchema,
|
||||
beelinePlugin,
|
||||
};
|
||||
|
|
|
@ -397,8 +397,8 @@ const buildPetStatesForPetTypeLoader = (db, loaders) =>
|
|||
);
|
||||
});
|
||||
|
||||
const buildZoneLoader = (db) =>
|
||||
new DataLoader(async (ids) => {
|
||||
const buildZoneLoader = (db) => {
|
||||
const zoneLoader = new DataLoader(async (ids) => {
|
||||
const qs = ids.map((_) => "?").join(",");
|
||||
const [rows, _] = await db.execute(
|
||||
`SELECT * FROM zones WHERE id IN (${qs})`,
|
||||
|
@ -415,6 +415,20 @@ const buildZoneLoader = (db) =>
|
|||
);
|
||||
});
|
||||
|
||||
zoneLoader.loadAll = async () => {
|
||||
const [rows, _] = await db.execute(`SELECT * FROM zones`);
|
||||
const entities = rows.map(normalizeRow);
|
||||
|
||||
for (const zone of entities) {
|
||||
zoneLoader.prime(zone.id, zone);
|
||||
}
|
||||
|
||||
return entities;
|
||||
};
|
||||
|
||||
return zoneLoader;
|
||||
};
|
||||
|
||||
const buildZoneTranslationLoader = (db) =>
|
||||
new DataLoader(async (zoneIds) => {
|
||||
const qs = zoneIds.map((_) => "?").join(",");
|
||||
|
|
Loading…
Reference in a new issue