Demonstration bridge between ATproto and GraphQL. Generate schema types and interface with the ATmosphere via GraphQL queries. Includes a TypeScript server with IDE.
at main 86 lines 2.4 kB view raw
1import express from "express"; 2import { createHandler } from "graphql-http/lib/use/http"; 3import { buildSchema } from "graphql"; 4import { ruruHTML } from "ruru/server"; 5import { serveStatic } from "ruru/static"; 6import { generateDefinitions } from "../generateLexiconSchema"; 7 8// Initialize Express app 9const app = express(); 10 11const lexiconIds = (await import("../../lexicons.json")).lexicons; 12 13// Generate definitions (this is what main.ts does when no --output flag is provided) 14const { chunks: generatedDefinitions, lexiconCalls } = 15 generateDefinitions(lexiconIds); 16 17// Define GraphQL schema using GraphQL-JS 18const schema = buildSchema( 19 generatedDefinitions.join("\n\n") + 20 ` 21type Query { 22 lexicon: Lexicon 23}`, 24); 25 26const ty = (schema.getQueryType().getFields()["lexicon"].resolve = () => ({})); 27 28// Serve static files 29for (const key of Object.keys(lexiconCalls)) { 30 const segments = key.split("."); 31 const ty = schema.getType( 32 ["Lexicon"].concat(segments.slice(0, -1)).join("_"), 33 ); 34 ty.getFields()[segments.slice(-1)[0]].resolve = lexiconCalls[key]; 35 36 for (let i = 1; i < segments.length; i++) { 37 const ty = schema.getType( 38 ["Lexicon"].concat(segments.slice(0, i - 1)).join("_"), 39 ); 40 ty.getFields()[segments.slice(0, i).pop()].resolve = () => ({}); 41 } 42} 43 44app.use(express.static("public")); 45 46// Serve lexicons.json at /lexicons path 47app.get("/lexicons", (req, res) => { 48 res.json(Object.keys(lexiconCalls)); 49}); 50 51const handler = createHandler({ schema }); 52 53// GraphQL endpoint 54app.all("/graphql", handler); 55 56/** 57 * Setup GraphiQL 58 */ 59 60const config = { staticPath: "/ruru-static/", endpoint: "/graphql" }; 61 62// Serve Ruru HTML 63app.get("/graphiql", (req, res) => { 64 res.format({ 65 html: () => res.status(200).send(ruruHTML(config)), 66 default: () => res.status(406).send("Not Acceptable"), 67 }); 68}); 69 70// Serve static files 71app.use(serveStatic(config.staticPath)); 72 73// Start the HTTP server 74const PORT = process.env.PORT || 4000; 75const httpServer = app.listen(PORT, () => { 76 console.log(`Server ready at http://localhost:${PORT}`); 77 console.log(`GraphQL endpoint: http://localhost:${PORT}/graphql`); 78 console.log(`GraphiQL endpoint: http://localhost:${PORT}/graphiql`); 79}); 80 81// Handle server shutdown gracefully 82process.on("SIGINT", () => { 83 httpServer.close(() => { 84 console.log("Server closed"); 85 }); 86});