├── .babelrc
├── .gitignore
├── README.md
├── __test__
├── apollo
│ ├── .env
│ ├── .gitignore
│ ├── config
│ │ └── db.js
│ ├── index.js
│ ├── models
│ │ ├── index.js
│ │ └── listing.js
│ ├── package-lock.json
│ ├── package.json
│ ├── resolvers
│ │ ├── index.js
│ │ ├── mutations
│ │ │ ├── createListing.js
│ │ │ ├── deleteListing.js
│ │ │ ├── index.js
│ │ │ └── updateListing.js
│ │ └── queries
│ │ │ ├── index.js
│ │ │ ├── listing.js
│ │ │ └── listings.js
│ ├── sample_queries
│ │ ├── create-listing.js
│ │ ├── delete-listing.js
│ │ ├── read-listings.js
│ │ ├── sample-query.js
│ │ └── update-listing.js
│ └── types
│ │ ├── Listing.js
│ │ ├── index.js
│ │ └── typesExport.js
├── enzyme
│ ├── Containers.test.js
│ └── GraphContext.test.js
└── express-server
│ ├── .gitignore
│ ├── app.js
│ ├── db
│ ├── comments-models.js
│ └── movie-models.js
│ ├── package-lock.json
│ ├── package.json
│ ├── sample_queries
│ ├── comment-mutation.js
│ ├── main-comment-query.js
│ ├── main-movie-query.js
│ └── min-movie-query.js
│ └── schema
│ ├── schema.js
│ └── types.js
├── contributing.md
├── dist
└── bundle.js
├── index.html
├── jest.config.js
├── nuqleus_npm_package
├── .gitignore
├── README.md
├── index.html
├── main.js
├── nuqleus.js
├── package-lock.json
├── package.json
├── public
│ ├── client
│ │ └── dist
│ │ │ └── bundle.js
│ └── src
│ │ └── assets
│ │ └── images
│ │ ├── nuQLeus_favicon_32x32.png
│ │ ├── nuQLeus_logo.png
│ │ ├── nuQLeus_logo_black_background.png
│ │ └── nuQLeus_logo_reversed.png
└── server.js
├── package-lock.json
├── package.json
├── src
├── assets
│ ├── gifs
│ │ └── nuqleus_showcase.gif
│ └── images
│ │ ├── nuQLeus_favicon_32x32.png
│ │ ├── nuQLeus_logo.png
│ │ ├── nuQLeus_logo_black_background.png
│ │ └── nuQLeus_logo_reversed.png
└── client
│ ├── App.jsx
│ ├── components
│ ├── EmptyTracingData.jsx
│ ├── NavBar.jsx
│ ├── OutputDisplay.jsx
│ ├── QueryField.jsx
│ ├── ServerField.jsx
│ ├── VariableField.jsx
│ └── VisualDisplay.jsx
│ ├── containers
│ ├── LeftContainer.jsx
│ ├── MainContainer.jsx
│ ├── MiddleContainer.jsx
│ └── RightContainer.jsx
│ ├── contexts
│ └── GraphContext.jsx
│ ├── index.jsx
│ └── stylesheets
│ ├── editor-theme.css
│ └── styles.css
├── tsconfig.json
└── webpack.config.js
/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 | "presets": [
3 | "@babel/preset-env",
4 | "@babel/preset-react"
5 | ]
6 | }
7 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .ds_store
2 | node_modules/
3 | .env
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # nuQLeus
2 |
3 | Boost GraphQL endpoint testing capabilities with resolver-level performance metrics.
4 |
5 |
6 |
7 |
8 |
9 |
10 | [](https://github.com/oslabs-beta/NuQLeus)
11 | 
12 |
13 | ## Table of Contents
14 |
15 | - [Description](#description)
16 | - [Motivation](#motivation)
17 | - [Features](#features)
18 | - [Getting Started with nuQLeus](#Getting-Started-with-nuQLeus)
19 | - [Install nuQLeus](#Install-nuQLeus)
20 | - [Apollo Server Setup](#Apollo-Server-Setup)
21 | - [Express-GraphQL Setup](#Express-GraphQL-Setup)
22 | - [Using the nuQLeus GUI](#Using-the-nuQLeus-GUI)
23 | - [Technologies](#technologies)
24 | - [Contributing](#contributing)
25 | - [Areas for Improvement](#areasforimprovement)
26 | - [Authors](#authors)
27 | - [License](#license)
28 | - [Links/Contact](Links/Contacts)
29 |
30 |
31 |
32 | ## Description
33 |
34 | NuQLeus is a lightweight, self-contained, GraphQL endpoint testing GUI that extracts resolver-level tracing performance metrics from GraphQL queries and mutations and allows an enduser to easily identify specific resolvers that are having a detrimental impact on application performance.
35 |
36 |
37 |
38 | ## Motivation
39 |
40 | 1. There is a considerable amount of overhead associated with building out a GraphQL API for the first time.
41 | 2. GraphQL APIs can be created using a multitude of different libraries such as Apollo Server and Express-GraphQL.
42 | 3. The library that is selected to build a GraphQL API can limit what features and metadata are accessible.
43 |
44 | The motivation for nuQLeus stems from the fact that there are a multitude of different libraries, each with varying sets of features, that can be used to implement a GraphQL API. The library that an enduser selected when first creating a GraphQL API can limit which metadata they will have access to; for example, GraphQL APIs setup via Apollo Server have access to resolver-level tracing metrics whle servers created with Express-GraphQL will not. nuQLeus seeks to help bridge this feature gap and enable an enduser to extract resolver-level tracing data from queries and mutations, regardless of which server they used to initially create their API.
45 |
46 |
47 |
48 | ## Features
49 |
50 | * Simulate GraphQL queries and mutations in the nuQLeus environment
51 | * Real-time tracing durations at individual resolver-level for GraphQL queries and mutations
52 | * Processing and visualization of tracing data to help identify performance drop-offs at a glance
53 |
54 |
55 |
56 | ## Getting Started With nuQLeus
57 |
58 | ### **Install nuQLeus**
59 |
60 | ```javascript
61 | npm install --save-dev nuqleus
62 | ```
63 |
64 |
65 |
66 | ### **Apollo Server Setup**
67 |
68 | The Apollo Server constructor function accepts an object with properties that convey schema options. Simply pass the existing options object into the `nuqleus.ApolloWrapOptions` method to return a new options object to be passed into the `ApolloServer` constructor.
69 |
70 | ```javascript
71 | const { ApolloServer } = require('apollo-server');
72 | const connectDb = require('./config/db');
73 | const typeDefs = require('./types');
74 | const resolvers = require('./resolvers');
75 | const models = require('./models');
76 | import nuqleus from 'nuqleus';
77 |
78 | connectDb();
79 |
80 | // 1. Define your context either as an object or function //
81 | // Add your models in here, if any //
82 | const userContext = {
83 | models,
84 | sampleObject: {},
85 | };
86 |
87 | // 2. Define your formatResponse, if any, as an object //
88 | const userFormatResponse = {
89 | formatResponse: (res, reqContext) => {
90 | res.http = {
91 | someUserHttp: {
92 | startTime: new Date().toISOString(),
93 | endTime: new Date(Date.now()).toISOString(),
94 | }
95 | };
96 | }
97 | };
98 |
99 | // 3. Create a nuqleusServerObject using the ApolloWrapOptions method //
100 | // Allowable inputs: typeDefs, resolvers, context, formatResponse, ...resolverInputs //
101 | const nuqleusServerObject = nuqleus.ApolloWrapOptions(
102 | typeDefs, resolvers, userContext, userFormatResponse
103 | );
104 |
105 | /**
106 | * If any resolverInputs will be inputted, they will be wrapped after
107 | * the nuQLeusTraceResolver around your schema with the applyMiddleware method.
108 | *
109 | * const schemaWithMiddleWare = applyMiddleware(clientSchema, nuqleusTraceResolvers, ...clientInputs);
110 | */
111 |
112 | // 4. Spread the nuqleusServerObject into your new ApolloServer instance //
113 | // If you have any add'l options, add them in after
114 | const server = new ApolloServer({
115 | ...nuqleusServerObject,
116 | // add'l user options,
117 | // add'l user options,
118 | });
119 |
120 | // 5. Run your server /
121 | server.listen(4001).then(({ url }) => {
122 | console.log(`🚀 Server ready at ${url}`);
123 | });
124 | ```
125 |
126 |
127 |
128 | ### **Express-GraphQL Setup**
129 |
130 | Express-graphql's `graphqlHTTP` function accepts an options parameter that can either be an object or a function. Simply pass existing options into `nuqleus.WrapOptions` function to return a new options callback to pass into `graphqlHTTP`.
131 |
132 | If users have `extensions`, simply pass the `extensions` callback into `nuqleus.WrapOptions` as a second optional argument.
133 |
134 | ```js
135 | const express = require('express');
136 | const { graphqlHTTP } = require('express-graphql');
137 | const schema = require('./schema');
138 | const models = require('./models');
139 | const nuqleus = require('./nuqleus');
140 |
141 | const extensions = ({ document, variables, operationName, result, context }) => ({
142 | hello: context.hello,
143 | });
144 |
145 | const options = {
146 | schema,
147 | context: { models, hello: 'world' },
148 | graphiql: true,
149 | };
150 |
151 | const newOptions = nuqleus.WrapOptions(options, extensions);
152 |
153 | app.use('/graphql', graphqlHTTP(newOptions));
154 |
155 | app.listen(4000, () => {
156 | console.log('Listening on port 4000');
157 | });
158 |
159 | ```
160 |
161 |
162 |
163 | ### **Using the nuQLeus GUI**
164 | The nuQLeus wrapper methods instantiate a server and serve the nuQLeus GUI whenever a user's GraphQL server is initialized. In order to access the nuQLeus GUI, navigate to http://localhost:3030/nuqleus while your server is running.
165 |
166 |
167 |
168 |
169 |
170 |
171 |
172 | ## Technologies
173 |
174 | * GraphQL
175 | * React
176 | * Codemirror
177 | * Graphql-middleware
178 | * Victory
179 | * Express & Node.js
180 | * Jest
181 | * Supertest
182 | * Enzyme
183 | * Webpack
184 | * MongoDB
185 |
186 |
187 |
188 | ## Contributing
189 |
190 | Development of nuQLeus is open source on Hithub through the tech accelerator umbrella OS Labs. We are grateful for the community's contribution to the project. Please read the [contribution documentation](contributing.md) to learn more on how you can participate in improvements.
191 |
192 |
193 |
194 | ## Areas for Improvement
195 |
196 | * Functionality
197 | * Include additional GraphQL servers into nuQLeus coverage
198 | * Ex. graphql-yoga or graphql-helix
199 | * Add tracing capability for GraphQL subscriptions
200 | * Set up a database to store historical user inputs and results
201 | * Allow performance metric comparisons between past and present queries and mutations
202 | * Alternatively, use localStorage for comparisons
203 | * Add onChange user input checks so only valid body/variables can be submitted
204 | * Add introspection capability for users to break down their schemas/queries/mutations in the frontend
205 | * UI/UX
206 | * Use React Router (or other method) to show multiple windows in the
207 | * Include additional visualizations of relevant information users may find helpful
208 | * Convert the Victory graph library to a more widely-used alternative such as D3
209 | * Code Base
210 | * Convert .js and .jsx code to .ts and .tsx
211 | * Implement CORS policy in wrapper for pre-set headers
212 | * Prevent the need for users to have to install and enable CORS
213 | * Refactor and improve code as seen
214 |
215 |
216 |
217 | ## Authors
218 |
219 | * Daniel Perez [Daniel-P3](https://github.com/Daniel-P3)
220 | * Jenny Hai [jhai420](https://github.com/jhai420)
221 | * Joshua Kim [jkim000](https://github.com/jkim000)
222 | * Zach Brucker [zbrucker](https://github.com/zbrucker)
223 |
224 |
225 |
226 | ## License
227 |
228 | [MIT](https://opensource.org/licenses/mit-license.php)
229 |
230 |
231 |
232 | ## Links/Contacts
233 |
234 | * Email: nuqleusjs@gmail.com
235 | * [Landing Page](http://www.nuqleus.io/)
236 | * [npm](https://www.npmjs.com/package/nuqleus)
237 | * [LinkedIn](https://www.linkedin.com/company/nuqleus)
238 |
239 |
240 |
241 | #
242 | ##### [Return to Top](#nuQLeus)
--------------------------------------------------------------------------------
/__test__/apollo/.env:
--------------------------------------------------------------------------------
1 | APOLLO_KEY=service:My-Graph-j33azt:8xr9d_mXPg2o0Hjzy2urHQ
2 | APOLLO_GRAPH_VARIANT=current
3 | DATABASE_URL='mongodb+srv://danny:Codesmith41@cluster0.nbdhe.mongodb.net/sample_airbnb?retryWrites=true&w=majority'
--------------------------------------------------------------------------------
/__test__/apollo/.gitignore:
--------------------------------------------------------------------------------
1 | .ds_store
2 | node_modules/
3 | .env
--------------------------------------------------------------------------------
/__test__/apollo/config/db.js:
--------------------------------------------------------------------------------
1 | require('dotenv').config();
2 | const mongoose = require('mongoose');
3 | const DATABASE_URL = process.env.DATABASE_URL;
4 |
5 | //Connect to Database
6 | const connectDb = () => {
7 | return mongoose.connect(
8 | DATABASE_URL,
9 | {
10 | useUnifiedTopology: true,
11 | useNewUrlParser: true,
12 | },
13 | (err) => {
14 | if (err) {
15 | console.log('Connection to Database failed.');
16 | } else {
17 | console.log('Database connection successful.');
18 | }
19 | }
20 | );
21 | };
22 |
23 | const db = mongoose.connection;
24 |
25 | db.on('error', console.error.bind(console, 'MongoDB connection error'));
26 |
27 | module.exports = connectDb;
28 |
--------------------------------------------------------------------------------
/__test__/apollo/index.js:
--------------------------------------------------------------------------------
1 | require('dotenv').config();
2 | const { ApolloServer } = require('apollo-server');
3 | const { makeExecutableSchema } = require('@graphql-tools/schema')
4 | const { applyMiddleware } = require('graphql-middleware');
5 | const connectDb = require('./config/db');
6 | const typeDefs = require('./types');
7 | const resolvers = require('./resolvers');
8 | const models = require('./models');
9 | const nuqleus = require('nuqleus');
10 |
11 | connectDb();
12 |
13 | // SAMPLE TEST INPUTS //
14 | const contextObject = {
15 | models,
16 | joshTest: {},
17 | };
18 | // SAMPLE TEST INPUTS //
19 | const contextFunction = ({ req, res }) => ({
20 | models,
21 | joshText: {},
22 | });
23 | // SAMPLE TEST INPUTS //
24 | const fResponse = {
25 | formatResponse: (res, reqContext) => {
26 | res.http = {
27 | joshTracing: {
28 | startTime: new Date(reqContext.context.nuqleusStartTime).toISOString(),
29 | endTime: new Date(Date.now()).toISOString(),
30 | }
31 | };
32 | }
33 | };
34 |
35 | // WHAT THE USER NEEDS TO CREATE
36 | const nuqleusServerObject = nuqleus.ApolloWrapOptions(
37 | typeDefs, resolvers, contextFunction, fResponse
38 | );
39 |
40 | const server = new ApolloServer({
41 | ...nuqleusServerObject,
42 | });
43 |
44 | server.listen(4001).then(({ url }) => {
45 | console.log(`🚀 Server ready at ${url}`);
46 | });
47 |
--------------------------------------------------------------------------------
/__test__/apollo/models/index.js:
--------------------------------------------------------------------------------
1 | const { Listing } = require('./listing');
2 |
3 | module.exports = {
4 | Listing,
5 | };
6 |
--------------------------------------------------------------------------------
/__test__/apollo/models/listing.js:
--------------------------------------------------------------------------------
1 | const mongoose = require("mongoose");
2 | const { Schema } = mongoose;
3 |
4 | const ListingAndReviewsSchema = new Schema({
5 | _id: {
6 | type: String,
7 | trim: true,
8 | },
9 |
10 | listing_url: {
11 | type: String,
12 | trim: true,
13 | },
14 |
15 | name: {
16 | type: String,
17 | trim: true,
18 | },
19 |
20 | summary: {
21 | type: String,
22 | trim: true,
23 | },
24 |
25 | space: {
26 | type: String,
27 | trim: true,
28 | },
29 |
30 | description: {
31 | type: String,
32 | trim: true,
33 | },
34 |
35 | neighborhood_overview: {
36 | type: String,
37 | trim: true,
38 | },
39 |
40 | notes: {
41 | type: String,
42 | trim: true,
43 | },
44 |
45 | transit: {
46 | type: String,
47 | trim: true,
48 | },
49 |
50 | access: {
51 | type: String,
52 | trim: true,
53 | },
54 |
55 | interaction: {
56 | type: String,
57 | trim: true,
58 | },
59 |
60 | house_rules: {
61 | type: String,
62 | trim: true,
63 | },
64 |
65 | property_type: {
66 | type: String,
67 | trim: true,
68 | },
69 |
70 | room_type: {
71 | type: String,
72 | trim: true
73 | },
74 |
75 | bed_type: {
76 | type: String,
77 | trim: true
78 | },
79 |
80 | minimum_nights: {
81 | type: String,
82 | trim: true
83 | },
84 |
85 | maximum_nights: {
86 | type: String,
87 | trim: true
88 | },
89 |
90 | cancellation_policy: {
91 | type: String,
92 | trim: true
93 | },
94 |
95 | last_scraped: {
96 | type: Date,
97 | },
98 |
99 | calendar_last_scraped: {
100 | type: Date,
101 | },
102 |
103 | accommodates: {
104 | type: Number
105 | },
106 |
107 | bedrooms: {
108 | type: Number
109 | },
110 |
111 | beds: {
112 | type: Number
113 | },
114 |
115 | number_of_reviews: {
116 | type: Number,
117 | },
118 |
119 | bathrooms: {
120 | type: Number,
121 | },
122 |
123 | amenities: {
124 | type: [String],
125 | },
126 |
127 | price: {
128 | type: Number,
129 | },
130 |
131 | extra_people: {
132 | type: Number,
133 | },
134 |
135 | guests_included: {
136 | type: Number,
137 | },
138 |
139 | reviews: {
140 | type: [String],
141 | },
142 |
143 | images: {
144 | type: Object,
145 | },
146 |
147 | host: {
148 | type: Object,
149 | },
150 |
151 | address: {
152 | type: Object,
153 | },
154 |
155 | availability: {
156 | type: Object,
157 | },
158 |
159 | review_scores: {
160 | type: [String],
161 | },
162 | });
163 |
164 | const Listing = mongoose.model('listing', ListingAndReviewsSchema);
165 |
166 | module.exports = { Listing };
167 |
--------------------------------------------------------------------------------
/__test__/apollo/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "apollo",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "index.js",
6 | "scripts": {
7 | "start": "nodemon index.js"
8 | },
9 | "keywords": [],
10 | "author": "",
11 | "license": "ISC",
12 | "dependencies": {
13 | "@graphql-tools/schema": "^7.1.3",
14 | "apollo-server": "^2.21.0",
15 | "apollo-server-express": "^2.21.0",
16 | "dotenv": "^8.2.0",
17 | "express": "^4.17.1",
18 | "graphql": "^15.5.0",
19 | "graphql-middleware": "^6.0.4",
20 | "mongoose": "^5.11.18",
21 | "nodemon": "^2.0.7",
22 | "nuqleus": "^0.1.0",
23 | "open": "^8.0.4"
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/__test__/apollo/resolvers/index.js:
--------------------------------------------------------------------------------
1 | const mutations = require('./mutations');
2 | const queries = require('./queries');
3 |
4 | module.exports = {
5 | Mutation: {
6 | ...mutations,
7 | },
8 | Query: {
9 | ...queries,
10 | },
11 | };
12 |
--------------------------------------------------------------------------------
/__test__/apollo/resolvers/mutations/createListing.js:
--------------------------------------------------------------------------------
1 | const { ApolloError } = require('apollo-server');
2 |
3 | //Take inputs from models folder and create a new item when the user on nuQLeus creates one
4 | module.exports = async (_, { input }, { models }) => {
5 | try {
6 | const newListing = await models.Listing.create(input);
7 | return newListing;
8 | } catch (e) {
9 | throw new ApolloError(e);
10 | }
11 | };
12 |
--------------------------------------------------------------------------------
/__test__/apollo/resolvers/mutations/deleteListing.js:
--------------------------------------------------------------------------------
1 | const { ApolloError } = require('apollo-server');
2 |
3 | //Take the id the user writes down, and delete the item matching the id in the database
4 | module.exports = async (_, { id }, { models }) => {
5 | const deleteListing = await models.Listing.deleteOne({ _id: id });
6 |
7 | if (deleteListing.deletedCount) return { id: id };
8 | else throw new ApolloError(`Failed to delete address.`);
9 | };
10 |
--------------------------------------------------------------------------------
/__test__/apollo/resolvers/mutations/index.js:
--------------------------------------------------------------------------------
1 | const createListing = require('./createListing');
2 | const updateListing = require('./updateListing');
3 | const deleteListing = require('./deleteListing');
4 |
5 | module.exports = {
6 | createListing,
7 | updateListing,
8 | deleteListing,
9 | };
10 |
--------------------------------------------------------------------------------
/__test__/apollo/resolvers/mutations/updateListing.js:
--------------------------------------------------------------------------------
1 | const { ApolloError } = require('apollo-server');
2 |
3 | //Take id and input from the models and update that id with the new input
4 | module.exports = async (_, { id, input }, { models }) => {
5 | try {
6 | const listingToUpdate = await models.Listing.findOne({ _id: id });
7 |
8 | if (!listingToUpdate) throw new ApolloError(`Could not find listing with id: '${id}'.`, 400);
9 |
10 | //create an array of object keys and for each,replace the current id with the new id
11 | Object.keys(input).forEach((value) => {
12 | listingToUpdate[value] = input[value];
13 | });
14 |
15 | const updatedListing = await listingToUpdate.save();
16 |
17 | return updatedListing;
18 | } catch (e) {
19 | throw new ApolloError(e);
20 | }
21 | };
22 |
--------------------------------------------------------------------------------
/__test__/apollo/resolvers/queries/index.js:
--------------------------------------------------------------------------------
1 | const listing = require('./listing');
2 | const listings = require('./listings');
3 |
4 | module.exports = {
5 | listing,
6 | listings,
7 | };
8 |
--------------------------------------------------------------------------------
/__test__/apollo/resolvers/queries/listing.js:
--------------------------------------------------------------------------------
1 | const { ApolloError } = require('apollo-server');
2 |
3 | //Given an id from models, search for the appropriate item in the database.
4 | module.exports = async (_, { _id }, { models }) => {
5 | try {
6 | const listingToRead = await models.Listing.findOne({ _id: _id });
7 | if (!listingToRead) throw new ApolloError(`Could not find listing with id: '${_id}'.`, 400);
8 | return listingToRead;
9 | }
10 | catch (e) {
11 | throw new ApolloError(e);
12 | }
13 | };
14 |
--------------------------------------------------------------------------------
/__test__/apollo/resolvers/queries/listings.js:
--------------------------------------------------------------------------------
1 | //Search for all items in the database
2 | module.exports = async (_, {}, { models }) => {
3 | return await models.Listing.find();
4 | };
5 |
--------------------------------------------------------------------------------
/__test__/apollo/sample_queries/create-listing.js:
--------------------------------------------------------------------------------
1 | mutation createListing {
2 | createListing(input: { name: "DogNamedFido", _id: "533327" }) {
3 | name
4 | _id
5 | }
6 | }
--------------------------------------------------------------------------------
/__test__/apollo/sample_queries/delete-listing.js:
--------------------------------------------------------------------------------
1 | mutation deleteListing {
2 | deleteListing(id:"533327"){
3 | id
4 | }
5 | }
--------------------------------------------------------------------------------
/__test__/apollo/sample_queries/read-listings.js:
--------------------------------------------------------------------------------
1 | query listings {
2 | listings {
3 | name
4 | _id
5 | }
6 | }
7 |
8 |
9 | // -----
10 | // query body
11 | query AnyQueryName($_id: ID!) {
12 | listing(_id: $_id) {
13 | name
14 | _id
15 | }
16 | }
17 | // variables
18 | {
19 | "_id": "1003530"
20 | }
21 | // -----
22 |
--------------------------------------------------------------------------------
/__test__/apollo/sample_queries/sample-query.js:
--------------------------------------------------------------------------------
1 | query listings {
2 | listings {
3 | name
4 | price
5 | }
6 | }
--------------------------------------------------------------------------------
/__test__/apollo/sample_queries/update-listing.js:
--------------------------------------------------------------------------------
1 | mutation updateListing {
2 | updateListing(id:533327,input:{
3 | name: "magic"
4 | }){
5 | name
6 | }
7 | }
--------------------------------------------------------------------------------
/__test__/apollo/types/Listing.js:
--------------------------------------------------------------------------------
1 | const { gql } = require('apollo-server');
2 |
3 | module.exports = gql`
4 | type Listing {
5 | _id: ID!
6 | listing_url: String
7 | name: String!
8 | summary: String
9 | space: String
10 | description: String
11 | neighborhood_overview: String
12 | notes: String
13 | transit: String
14 | access: String
15 | interaction: String
16 | house_rules: String
17 | property_type: String
18 | room_type: String
19 | bed_type: String
20 | minimum_nights: String
21 | maximum_nights: String
22 | cancellation_policy: String
23 | last_scraped: String
24 | calendar_last_scraped: String
25 | accommodates: Int
26 | bedrooms: Int
27 | beds: Int
28 | number_of_reviews: Int
29 | bathrooms: Float
30 | amenities: [String]
31 | price: Float
32 | extra_people: Float
33 | guests_included: Int
34 | reviews: [String]
35 | }
36 |
37 | input CreateListingInput {
38 | _id: ID!
39 | listing_url: String
40 | name: String!
41 | summary: String
42 | space: String
43 | description: String
44 | neighborhood_overview: String
45 | notes: String
46 | transit: String
47 | access: String
48 | interaction: String
49 | house_rules: String
50 | property_type: String
51 | room_type: String
52 | bed_type: String
53 | minimum_nights: String
54 | maximum_nights: String
55 | cancellation_policy: String
56 | last_scraped: String
57 | calendar_last_scraped: String
58 | accommodates: Int
59 | bedrooms: Int
60 | beds: Int
61 | number_of_reviews: Int
62 | bathrooms: Float
63 | amenities: [String]
64 | price: Float
65 | extra_people: Float
66 | guests_included: Int
67 | reviews: [String]
68 | }
69 |
70 | input UpdateListingInput {
71 | listing_url: String
72 | name: String!
73 | summary: String
74 | space: String
75 | description: String
76 | neighborhood_overview: String
77 | notes: String
78 | transit: String
79 | access: String
80 | interaction: String
81 | house_rules: String
82 | property_type: String
83 | room_type: String
84 | bed_type: String
85 | minimum_nights: String
86 | maximum_nights: String
87 | cancellation_policy: String
88 | last_scraped: String
89 | calendar_last_scraped: String
90 | accommodates: Int
91 | bedrooms: Int
92 | beds: Int
93 | number_of_reviews: Int
94 | bathrooms: Float
95 | amenities: [String]
96 | price: Float
97 | extra_people: Float
98 | guests_included: Int
99 | reviews: [String]
100 | }
101 |
102 | input DeleteListingInput {
103 | id: ID!
104 | listing_url: String
105 | name: String!
106 | summary: String
107 | space: String
108 | description: String
109 | neighborhood_overview: String
110 | notes: String
111 | transit: String
112 | access: String
113 | interaction: String
114 | house_rules: String
115 | property_type: String
116 | room_type: String
117 | bed_type: String
118 | minimum_nights: String
119 | maximum_nights: String
120 | cancellation_policy: String
121 | last_scraped: String
122 | calendar_last_scraped: String
123 | accommodates: Int
124 | bedrooms: Int
125 | beds: Int
126 | number_of_reviews: Int
127 | bathrooms: Float
128 | amenities: [String]
129 | price: Float
130 | extra_people: Float
131 | guests_included: Int
132 | reviews: [String]
133 | }
134 |
135 | type DeletePayload {
136 | id: ID!
137 | listing_url: String
138 | name: String!
139 | summary: String
140 | space: String
141 | description: String
142 | neighborhood_overview: String
143 | notes: String
144 | transit: String
145 | access: String
146 | interaction: String
147 | house_rules: String
148 | property_type: String
149 | room_type: String
150 | bed_type: String
151 | minimum_nights: String
152 | maximum_nights: String
153 | cancellation_policy: String
154 | last_scraped: String
155 | calendar_last_scraped: String
156 | accommodates: Int
157 | bedrooms: Int
158 | beds: Int
159 | number_of_reviews: Int
160 | bathrooms: Float
161 | amenities: [String]
162 | price: Float
163 | extra_people: Float
164 | guests_included: Int
165 | reviews: [String]
166 | }
167 |
168 | #For a query,listing, take in an id, and return that listing
169 | #For listings, return an array of all listings
170 | type Query {
171 | listing(_id: ID!): Listing
172 | listings: [Listing]
173 | }
174 |
175 | #For createListing, take in a required input of what you want to create given the schema
176 | #Given the id and an input according to the schema, return an updated value for that listing
177 | #for an id, delete the payload written by the user
178 | type Mutation {
179 | createListing(input: CreateListingInput!): Listing!
180 | updateListing(id: ID!, input: UpdateListingInput!): Listing!
181 | deleteListing(id: ID!): DeletePayload!
182 | }
183 | `;
184 |
--------------------------------------------------------------------------------
/__test__/apollo/types/index.js:
--------------------------------------------------------------------------------
1 | const Listing = require('./Listing');
2 |
3 | module.exports = [Listing];
4 |
--------------------------------------------------------------------------------
/__test__/apollo/types/typesExport.js:
--------------------------------------------------------------------------------
1 | const Listing = require("./Listing");
2 |
3 | module.exports = [Listing];
4 |
--------------------------------------------------------------------------------
/__test__/enzyme/Containers.test.js:
--------------------------------------------------------------------------------
1 | // const serverField = require('../ServerField');
2 | import MainContainer from '../../src/client/containers/MainContainer';
3 | import LeftContainer from '../../src/client/containers/LeftContainer';
4 | import MiddleContainer from '../../src/client/containers/MiddleContainer';
5 | import RightContainer from '../../src/client/containers/RightContainer';
6 | import Enzyme, { shallow, mount, render } from 'enzyme';
7 |
8 | // Enzyme test to check MainContainer rendering
9 | describe('Should render MainContainer', () => {
10 | let container = shallow( );
11 |
12 | it('Renders a div and three other container divs', () => {
13 | expect(container.type()).toEqual('div');
14 | expect(container.find('LeftContainer').length === 1, true);
15 | expect(container.find('RightContainer').length === 1, true);
16 | expect(container.find('MiddleContainer').length === 1, true);
17 | })
18 |
19 | // it('render correctly text component', () => {
20 | // const TextInputComponent = renderer.create( ).toJSON();
21 | // expect(TextInputComponent).toMatchSnapshot();
22 | // });
23 |
24 | });
25 |
26 | // Enzyme test to check LeftContainer rendering
27 | xdescribe('Should render LeftContainer', () => {
28 |
29 |
30 | });
31 | // Enzyme test to check MiddleContainer rendering
32 | xdescribe('Should render MiddleContainer', () => {
33 |
34 | });
35 |
36 | // Enzyme test to check RightContainer rendering
37 | xdescribe('Should render RightContainer', () => {
38 |
39 | });
40 |
--------------------------------------------------------------------------------
/__test__/enzyme/GraphContext.test.js:
--------------------------------------------------------------------------------
1 | import { useContext } from 'react';
2 | import { GraphContext, GraphContextProvider } from '../../src/clie/G/contextsraphContext';
3 | import Enzyme, { mount } from 'enzyme';
4 | import Adapter from 'enzyme-adapter-react-16';
5 |
6 | Enzyme.configure({ adapter: new Adapter() });
7 |
8 | describe('Check the server input and updated value after using setInfo', () => {
9 | const TestComponent = () => {
10 | // const [info, setInfo] = useContext(GraphContext);
11 | const { info, setInfo } = useContext(GraphContext);
12 | const testSetInfo = () => {
13 | setInfo(() => ({
14 | ...info,
15 | uri: 'http://localhost:1337',
16 | response: {resTest: 'some updated response data'},
17 | extensions: {extTest: 'some random test object'},
18 | queryTime: '6ms',
19 | }))
20 | };
21 |
22 | return (
23 | <>
24 | {info.uri.toString()}
25 | Send Query
26 | >
27 | );
28 | };
29 |
30 | const wrapper = mount(
31 |
32 |
33 |
34 | );
35 |
36 | expect(wrapper.find('[data-testid="value"]').text().toEqual('http://localhost:4001'));
37 |
38 | wrapper.find('button').simulate('click');
39 |
40 | expect(wrapper.find('[data-testid="value"]').text().toEqual('http://localhost:1337'));
41 | });
42 |
--------------------------------------------------------------------------------
/__test__/express-server/.gitignore:
--------------------------------------------------------------------------------
1 | .ds_store
2 | node_modules/
3 | .env
--------------------------------------------------------------------------------
/__test__/express-server/app.js:
--------------------------------------------------------------------------------
1 | require('dotenv').config()
2 | const express = require('express');
3 | const { graphqlHTTP } = require('express-graphql');
4 | const cors = require('cors');
5 | const mongoose = require('mongoose');
6 | const schema = require('./schema/schema');
7 | const app = express();
8 |
9 | /** Require in nuQLeus package **/
10 |
11 | const nuqleus = require('nuqleus');
12 |
13 |
14 | /** Initialize cors and process requests as a JSON **/
15 |
16 | app.use(cors());
17 | app.use(express.json());
18 |
19 | /**
20 | * @params { document, variables, operationName, result, context }
21 | * @returns optional extensions object to be passed in options object
22 | *
23 | **/
24 | const extensions = ({ document, variables, operationName, result, context }) => ({
25 | runTime: context.startTime,
26 | query: context.query,
27 | });
28 |
29 | /**
30 | * @params request, response, graphQLParams
31 | * @returns required options object or callback to be passed in graphqlHTTP function
32 | *
33 | **/
34 | const options = (request, response, graphQLParams) => ({
35 | schema,
36 | context: { startTime: 300, query: graphQLParams.query },
37 | graphiql: true,
38 | });
39 |
40 |
41 | /**
42 | * @params options, extensions(optional)
43 | * @returns new options object to be passed in graphQLHTTP function
44 | * nuQleus.WrapOptions adds middleware to the schema and modfies the context
45 | * and extensions fields to enable tracing data and visualization
46 | *
47 | **/
48 | const newOptions = nuqleus.WrapOptions(options, extensions);
49 |
50 | /** Initiate graphQL route, passing in new options created by nuQLeus **/
51 |
52 | app.use('/graphql', graphqlHTTP(newOptions));
53 |
54 | /** Connect to MongoDB **/
55 |
56 | mongoose
57 | .connect(process.env.MONGO_URI,
58 | {
59 | // options for the connect method to parse the URI
60 | useNewUrlParser: true,
61 | useUnifiedTopology: true,
62 | }
63 | )
64 | .then(() => console.log('Connected to Mongo DB.'))
65 | .catch((err) => console.log(err));
66 |
67 | /** Start server on PORT 4000 **/
68 |
69 | app.listen(4000, () => {
70 | console.log('Listening on port 4000');
71 | });
72 |
--------------------------------------------------------------------------------
/__test__/express-server/db/comments-models.js:
--------------------------------------------------------------------------------
1 | const mongoose = require('mongoose');
2 | const Schema = mongoose.Schema;
3 |
4 | const commentSchema = new Schema({
5 | name: String,
6 | email: String,
7 | movie_id: { type: Schema.Types.ObjectId, ref: 'movie' },
8 | text: String,
9 | date: Date,
10 | })
11 |
12 | module.exports = mongoose.model('comment', commentSchema);
--------------------------------------------------------------------------------
/__test__/express-server/db/movie-models.js:
--------------------------------------------------------------------------------
1 | const mongoose = require('mongoose');
2 | const Schema = mongoose.Schema;
3 |
4 | const movieSchema = new Schema({
5 | title: String,
6 | year: Number,
7 | runtime: Number,
8 | released: Date,
9 | poster: String,
10 | rated: String,
11 | cast: [String],
12 | plot: String,
13 | fullplot: String,
14 | lastupdated: Date,
15 | type: String,
16 | directors: [String],
17 | writers: [String],
18 | imdb: Object,
19 | awards: Object,
20 | languages: [String],
21 | countries: [String],
22 | genres: [String],
23 | tomatoes: Object,
24 | num_mflix_comments: Number
25 | })
26 |
27 | module.exports = mongoose.model('movie', movieSchema);
--------------------------------------------------------------------------------
/__test__/express-server/package-lock.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "express-server",
3 | "version": "1.0.0",
4 | "lockfileVersion": 1,
5 | "requires": true,
6 | "dependencies": {
7 | "@ardatan/aggregate-error": {
8 | "version": "0.0.6",
9 | "resolved": "https://registry.npmjs.org/@ardatan/aggregate-error/-/aggregate-error-0.0.6.tgz",
10 | "integrity": "sha512-vyrkEHG1jrukmzTPtyWB4NLPauUw5bQeg4uhn8f+1SSynmrOcyvlb1GKQjjgoBzElLdfXCRYX8UnBlhklOHYRQ==",
11 | "requires": {
12 | "tslib": "~2.0.1"
13 | },
14 | "dependencies": {
15 | "tslib": {
16 | "version": "2.0.3",
17 | "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.0.3.tgz",
18 | "integrity": "sha512-uZtkfKblCEQtZKBF6EBXVZeQNl82yqtDQdv+eck8u7tdPxjLu2/lp5/uPW+um2tpuxINHWy3GhiccY7QgEaVHQ=="
19 | }
20 | }
21 | },
22 | "@graphql-tools/batch-execute": {
23 | "version": "7.1.0",
24 | "resolved": "https://registry.npmjs.org/@graphql-tools/batch-execute/-/batch-execute-7.1.0.tgz",
25 | "integrity": "sha512-Yb4QRpHZqDk24+T4K3ARk/KFU26Dyl30XcbYeVvIrgIKcmeON/p3DfSeiB0+MaxYlsv+liQKvlxNbeC2hD31pA==",
26 | "requires": {
27 | "@graphql-tools/utils": "^7.7.0",
28 | "dataloader": "2.0.0",
29 | "is-promise": "4.0.0",
30 | "tslib": "~2.1.0"
31 | }
32 | },
33 | "@graphql-tools/delegate": {
34 | "version": "7.1.1",
35 | "resolved": "https://registry.npmjs.org/@graphql-tools/delegate/-/delegate-7.1.1.tgz",
36 | "integrity": "sha512-+uV0KZPI070sEykf3uxy+AhirHOqZnqbVqTqcfhH8/97+vdoLPE5oVceCTvMQsC7bDapbcbNiwcpYd8T6OQ4KQ==",
37 | "requires": {
38 | "@ardatan/aggregate-error": "0.0.6",
39 | "@graphql-tools/batch-execute": "^7.1.0",
40 | "@graphql-tools/schema": "^7.0.0",
41 | "@graphql-tools/utils": "^7.7.1",
42 | "dataloader": "2.0.0",
43 | "is-promise": "4.0.0",
44 | "tslib": "~2.1.0"
45 | }
46 | },
47 | "@graphql-tools/schema": {
48 | "version": "7.1.3",
49 | "resolved": "https://registry.npmjs.org/@graphql-tools/schema/-/schema-7.1.3.tgz",
50 | "integrity": "sha512-ZY76hmcJlF1iyg3Im0sQ3ASRkiShjgv102vLTVcH22lEGJeCaCyyS/GF1eUHom418S60bS8Th6+autRUxfBiBg==",
51 | "requires": {
52 | "@graphql-tools/utils": "^7.1.2",
53 | "tslib": "~2.1.0"
54 | }
55 | },
56 | "@graphql-tools/utils": {
57 | "version": "7.7.1",
58 | "resolved": "https://registry.npmjs.org/@graphql-tools/utils/-/utils-7.7.1.tgz",
59 | "integrity": "sha512-SFT4/dTfrwWer1wSOLU+jqgv3oa/xTR8q+MiNbE9nCH2FXyMsqIOaXKm9wHfKIWFWHozqBdcnwFkQZrdD7H2TQ==",
60 | "requires": {
61 | "@ardatan/aggregate-error": "0.0.6",
62 | "camel-case": "4.1.2",
63 | "tslib": "~2.1.0"
64 | }
65 | },
66 | "@types/bson": {
67 | "version": "4.0.3",
68 | "resolved": "https://registry.npmjs.org/@types/bson/-/bson-4.0.3.tgz",
69 | "integrity": "sha512-mVRvYnTOZJz3ccpxhr3wgxVmSeiYinW+zlzQz3SXWaJmD1DuL05Jeq7nKw3SnbKmbleW5qrLG5vdyWe/A9sXhw==",
70 | "requires": {
71 | "@types/node": "*"
72 | }
73 | },
74 | "@types/mongodb": {
75 | "version": "3.6.10",
76 | "resolved": "https://registry.npmjs.org/@types/mongodb/-/mongodb-3.6.10.tgz",
77 | "integrity": "sha512-BkwAHFiZSSWdTIqbUVGmgvIsiXXjqAketeK7Izy7oSs6G3N8Bn993tK9eq6QEovQDx6OQ2FGP2KWDDxBzdlJ6Q==",
78 | "requires": {
79 | "@types/bson": "*",
80 | "@types/node": "*"
81 | }
82 | },
83 | "@types/node": {
84 | "version": "14.14.35",
85 | "resolved": "https://registry.npmjs.org/@types/node/-/node-14.14.35.tgz",
86 | "integrity": "sha512-Lt+wj8NVPx0zUmUwumiVXapmaLUcAk3yPuHCFVXras9k5VT9TdhJqKqGVUQCD60OTMCl0qxJ57OiTL0Mic3Iag=="
87 | },
88 | "accepts": {
89 | "version": "1.3.7",
90 | "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz",
91 | "integrity": "sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA==",
92 | "requires": {
93 | "mime-types": "~2.1.24",
94 | "negotiator": "0.6.2"
95 | }
96 | },
97 | "array-flatten": {
98 | "version": "1.1.1",
99 | "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz",
100 | "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI="
101 | },
102 | "atomic-sleep": {
103 | "version": "1.0.0",
104 | "resolved": "https://registry.npmjs.org/atomic-sleep/-/atomic-sleep-1.0.0.tgz",
105 | "integrity": "sha512-kNOjDqAh7px0XWNI+4QbzoiR/nTkHAWNud2uvnJquD1/x5a7EQZMJT0AczqK0Qn67oY/TTQ1LbUKajZpp3I9tQ=="
106 | },
107 | "bl": {
108 | "version": "2.2.1",
109 | "resolved": "https://registry.npmjs.org/bl/-/bl-2.2.1.tgz",
110 | "integrity": "sha512-6Pesp1w0DEX1N550i/uGV/TqucVL4AM/pgThFSN/Qq9si1/DF9aIHs1BxD8V/QU0HoeHO6cQRTAuYnLPKq1e4g==",
111 | "requires": {
112 | "readable-stream": "^2.3.5",
113 | "safe-buffer": "^5.1.1"
114 | }
115 | },
116 | "bluebird": {
117 | "version": "3.5.1",
118 | "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.1.tgz",
119 | "integrity": "sha512-MKiLiV+I1AA596t9w1sQJ8jkiSr5+ZKi0WKrYGUn6d1Fx+Ij4tIj+m2WMQSGczs5jZVxV339chE8iwk6F64wjA=="
120 | },
121 | "body-parser": {
122 | "version": "1.19.0",
123 | "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.0.tgz",
124 | "integrity": "sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw==",
125 | "requires": {
126 | "bytes": "3.1.0",
127 | "content-type": "~1.0.4",
128 | "debug": "2.6.9",
129 | "depd": "~1.1.2",
130 | "http-errors": "1.7.2",
131 | "iconv-lite": "0.4.24",
132 | "on-finished": "~2.3.0",
133 | "qs": "6.7.0",
134 | "raw-body": "2.4.0",
135 | "type-is": "~1.6.17"
136 | }
137 | },
138 | "bson": {
139 | "version": "1.1.6",
140 | "resolved": "https://registry.npmjs.org/bson/-/bson-1.1.6.tgz",
141 | "integrity": "sha512-EvVNVeGo4tHxwi8L6bPj3y3itEvStdwvvlojVxxbyYfoaxJ6keLgrTuKdyfEAszFK+H3olzBuafE0yoh0D1gdg=="
142 | },
143 | "bytes": {
144 | "version": "3.1.0",
145 | "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz",
146 | "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg=="
147 | },
148 | "camel-case": {
149 | "version": "4.1.2",
150 | "resolved": "https://registry.npmjs.org/camel-case/-/camel-case-4.1.2.tgz",
151 | "integrity": "sha512-gxGWBrTT1JuMx6R+o5PTXMmUnhnVzLQ9SNutD4YqKtI6ap897t3tKECYla6gCWEkplXnlNybEkZg9GEGxKFCgw==",
152 | "requires": {
153 | "pascal-case": "^3.1.2",
154 | "tslib": "^2.0.3"
155 | }
156 | },
157 | "content-disposition": {
158 | "version": "0.5.3",
159 | "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.3.tgz",
160 | "integrity": "sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g==",
161 | "requires": {
162 | "safe-buffer": "5.1.2"
163 | }
164 | },
165 | "content-type": {
166 | "version": "1.0.4",
167 | "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz",
168 | "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA=="
169 | },
170 | "cookie": {
171 | "version": "0.4.0",
172 | "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.0.tgz",
173 | "integrity": "sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg=="
174 | },
175 | "cookie-signature": {
176 | "version": "1.0.6",
177 | "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz",
178 | "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw="
179 | },
180 | "core-util-is": {
181 | "version": "1.0.2",
182 | "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz",
183 | "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac="
184 | },
185 | "cors": {
186 | "version": "2.8.5",
187 | "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz",
188 | "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==",
189 | "requires": {
190 | "object-assign": "^4",
191 | "vary": "^1"
192 | }
193 | },
194 | "dataloader": {
195 | "version": "2.0.0",
196 | "resolved": "https://registry.npmjs.org/dataloader/-/dataloader-2.0.0.tgz",
197 | "integrity": "sha512-YzhyDAwA4TaQIhM5go+vCLmU0UikghC/t9DTQYZR2M/UvZ1MdOhPezSDZcjj9uqQJOMqjLcpWtyW2iNINdlatQ=="
198 | },
199 | "debug": {
200 | "version": "2.6.9",
201 | "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
202 | "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
203 | "requires": {
204 | "ms": "2.0.0"
205 | }
206 | },
207 | "define-lazy-prop": {
208 | "version": "2.0.0",
209 | "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz",
210 | "integrity": "sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og=="
211 | },
212 | "denque": {
213 | "version": "1.5.0",
214 | "resolved": "https://registry.npmjs.org/denque/-/denque-1.5.0.tgz",
215 | "integrity": "sha512-CYiCSgIF1p6EUByQPlGkKnP1M9g0ZV3qMIrqMqZqdwazygIA/YP2vrbcyl1h/WppKJTdl1F85cXIle+394iDAQ=="
216 | },
217 | "depd": {
218 | "version": "1.1.2",
219 | "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz",
220 | "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak="
221 | },
222 | "destroy": {
223 | "version": "1.0.4",
224 | "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz",
225 | "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA="
226 | },
227 | "dotenv": {
228 | "version": "8.2.0",
229 | "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-8.2.0.tgz",
230 | "integrity": "sha512-8sJ78ElpbDJBHNeBzUbUVLsqKdccaa/BXF1uPTw3GrvQTBgrQrtObr2mUrE38vzYd8cEv+m/JBfDLioYcfXoaw=="
231 | },
232 | "ee-first": {
233 | "version": "1.1.1",
234 | "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
235 | "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0="
236 | },
237 | "encodeurl": {
238 | "version": "1.0.2",
239 | "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz",
240 | "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k="
241 | },
242 | "escape-html": {
243 | "version": "1.0.3",
244 | "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz",
245 | "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg="
246 | },
247 | "etag": {
248 | "version": "1.8.1",
249 | "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz",
250 | "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc="
251 | },
252 | "express": {
253 | "version": "4.17.1",
254 | "resolved": "https://registry.npmjs.org/express/-/express-4.17.1.tgz",
255 | "integrity": "sha512-mHJ9O79RqluphRrcw2X/GTh3k9tVv8YcoyY4Kkh4WDMUYKRZUq0h1o0w2rrrxBqM7VoeUVqgb27xlEMXTnYt4g==",
256 | "requires": {
257 | "accepts": "~1.3.7",
258 | "array-flatten": "1.1.1",
259 | "body-parser": "1.19.0",
260 | "content-disposition": "0.5.3",
261 | "content-type": "~1.0.4",
262 | "cookie": "0.4.0",
263 | "cookie-signature": "1.0.6",
264 | "debug": "2.6.9",
265 | "depd": "~1.1.2",
266 | "encodeurl": "~1.0.2",
267 | "escape-html": "~1.0.3",
268 | "etag": "~1.8.1",
269 | "finalhandler": "~1.1.2",
270 | "fresh": "0.5.2",
271 | "merge-descriptors": "1.0.1",
272 | "methods": "~1.1.2",
273 | "on-finished": "~2.3.0",
274 | "parseurl": "~1.3.3",
275 | "path-to-regexp": "0.1.7",
276 | "proxy-addr": "~2.0.5",
277 | "qs": "6.7.0",
278 | "range-parser": "~1.2.1",
279 | "safe-buffer": "5.1.2",
280 | "send": "0.17.1",
281 | "serve-static": "1.14.1",
282 | "setprototypeof": "1.1.1",
283 | "statuses": "~1.5.0",
284 | "type-is": "~1.6.18",
285 | "utils-merge": "1.0.1",
286 | "vary": "~1.1.2"
287 | }
288 | },
289 | "express-graphql": {
290 | "version": "0.12.0",
291 | "resolved": "https://registry.npmjs.org/express-graphql/-/express-graphql-0.12.0.tgz",
292 | "integrity": "sha512-DwYaJQy0amdy3pgNtiTDuGGM2BLdj+YO2SgbKoLliCfuHv3VVTt7vNG/ZqK2hRYjtYHE2t2KB705EU94mE64zg==",
293 | "requires": {
294 | "accepts": "^1.3.7",
295 | "content-type": "^1.0.4",
296 | "http-errors": "1.8.0",
297 | "raw-body": "^2.4.1"
298 | },
299 | "dependencies": {
300 | "http-errors": {
301 | "version": "1.8.0",
302 | "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.8.0.tgz",
303 | "integrity": "sha512-4I8r0C5JDhT5VkvI47QktDW75rNlGVsUf/8hzjCC/wkWI/jdTRmBb9aI7erSG82r1bjKY3F6k28WnsVxB1C73A==",
304 | "requires": {
305 | "depd": "~1.1.2",
306 | "inherits": "2.0.4",
307 | "setprototypeof": "1.2.0",
308 | "statuses": ">= 1.5.0 < 2",
309 | "toidentifier": "1.0.0"
310 | }
311 | },
312 | "inherits": {
313 | "version": "2.0.4",
314 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
315 | "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
316 | },
317 | "raw-body": {
318 | "version": "2.4.1",
319 | "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.1.tgz",
320 | "integrity": "sha512-9WmIKF6mkvA0SLmA2Knm9+qj89e+j1zqgyn8aXGd7+nAduPoqgI9lO57SAZNn/Byzo5P7JhXTyg9PzaJbH73bA==",
321 | "requires": {
322 | "bytes": "3.1.0",
323 | "http-errors": "1.7.3",
324 | "iconv-lite": "0.4.24",
325 | "unpipe": "1.0.0"
326 | },
327 | "dependencies": {
328 | "http-errors": {
329 | "version": "1.7.3",
330 | "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.3.tgz",
331 | "integrity": "sha512-ZTTX0MWrsQ2ZAhA1cejAwDLycFsd7I7nVtnkT3Ol0aqodaKW+0CTZDQ1uBv5whptCnc8e8HeRRJxRs0kmm/Qfw==",
332 | "requires": {
333 | "depd": "~1.1.2",
334 | "inherits": "2.0.4",
335 | "setprototypeof": "1.1.1",
336 | "statuses": ">= 1.5.0 < 2",
337 | "toidentifier": "1.0.0"
338 | }
339 | },
340 | "setprototypeof": {
341 | "version": "1.1.1",
342 | "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz",
343 | "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw=="
344 | }
345 | }
346 | },
347 | "setprototypeof": {
348 | "version": "1.2.0",
349 | "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz",
350 | "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw=="
351 | }
352 | }
353 | },
354 | "fast-redact": {
355 | "version": "3.0.0",
356 | "resolved": "https://registry.npmjs.org/fast-redact/-/fast-redact-3.0.0.tgz",
357 | "integrity": "sha512-a/S/Hp6aoIjx7EmugtzLqXmcNsyFszqbt6qQ99BdG61QjBZF6shNis0BYR6TsZOQ1twYc0FN2Xdhwwbv6+KD0w=="
358 | },
359 | "fast-safe-stringify": {
360 | "version": "2.0.7",
361 | "resolved": "https://registry.npmjs.org/fast-safe-stringify/-/fast-safe-stringify-2.0.7.tgz",
362 | "integrity": "sha512-Utm6CdzT+6xsDk2m8S6uL8VHxNwI6Jub+e9NYTcAms28T84pTa25GJQV9j0CY0N1rM8hK4x6grpF2BQf+2qwVA=="
363 | },
364 | "finalhandler": {
365 | "version": "1.1.2",
366 | "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz",
367 | "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==",
368 | "requires": {
369 | "debug": "2.6.9",
370 | "encodeurl": "~1.0.2",
371 | "escape-html": "~1.0.3",
372 | "on-finished": "~2.3.0",
373 | "parseurl": "~1.3.3",
374 | "statuses": "~1.5.0",
375 | "unpipe": "~1.0.0"
376 | }
377 | },
378 | "flatstr": {
379 | "version": "1.0.12",
380 | "resolved": "https://registry.npmjs.org/flatstr/-/flatstr-1.0.12.tgz",
381 | "integrity": "sha512-4zPxDyhCyiN2wIAtSLI6gc82/EjqZc1onI4Mz/l0pWrAlsSfYH/2ZIcU+e3oA2wDwbzIWNKwa23F8rh6+DRWkw=="
382 | },
383 | "forwarded": {
384 | "version": "0.1.2",
385 | "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.2.tgz",
386 | "integrity": "sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ="
387 | },
388 | "fresh": {
389 | "version": "0.5.2",
390 | "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz",
391 | "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac="
392 | },
393 | "graphql": {
394 | "version": "15.5.0",
395 | "resolved": "https://registry.npmjs.org/graphql/-/graphql-15.5.0.tgz",
396 | "integrity": "sha512-OmaM7y0kaK31NKG31q4YbD2beNYa6jBBKtMFT6gLYJljHLJr42IqJ8KX08u3Li/0ifzTU5HjmoOOrwa5BRLeDA=="
397 | },
398 | "graphql-middleware": {
399 | "version": "6.0.5",
400 | "resolved": "https://registry.npmjs.org/graphql-middleware/-/graphql-middleware-6.0.5.tgz",
401 | "integrity": "sha512-wd1WO3ngF4ERUqN4uVAxynhHzfrNAJcfIXbp1BlIHZOTKCKE7OohyPhjyNXnsouaMUUYBAiUvLZMNunbJ2d7sA==",
402 | "requires": {
403 | "@graphql-tools/delegate": "^7.1.1",
404 | "@graphql-tools/schema": "^7.1.3"
405 | }
406 | },
407 | "http-errors": {
408 | "version": "1.7.2",
409 | "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.2.tgz",
410 | "integrity": "sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg==",
411 | "requires": {
412 | "depd": "~1.1.2",
413 | "inherits": "2.0.3",
414 | "setprototypeof": "1.1.1",
415 | "statuses": ">= 1.5.0 < 2",
416 | "toidentifier": "1.0.0"
417 | }
418 | },
419 | "iconv-lite": {
420 | "version": "0.4.24",
421 | "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
422 | "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==",
423 | "requires": {
424 | "safer-buffer": ">= 2.1.2 < 3"
425 | }
426 | },
427 | "inherits": {
428 | "version": "2.0.3",
429 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
430 | "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4="
431 | },
432 | "ipaddr.js": {
433 | "version": "1.9.1",
434 | "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz",
435 | "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g=="
436 | },
437 | "is-docker": {
438 | "version": "2.1.1",
439 | "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.1.1.tgz",
440 | "integrity": "sha512-ZOoqiXfEwtGknTiuDEy8pN2CfE3TxMHprvNer1mXiqwkOT77Rw3YVrUQ52EqAOU3QAWDQ+bQdx7HJzrv7LS2Hw=="
441 | },
442 | "is-promise": {
443 | "version": "4.0.0",
444 | "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-4.0.0.tgz",
445 | "integrity": "sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ=="
446 | },
447 | "is-wsl": {
448 | "version": "2.2.0",
449 | "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz",
450 | "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==",
451 | "requires": {
452 | "is-docker": "^2.0.0"
453 | }
454 | },
455 | "isarray": {
456 | "version": "1.0.0",
457 | "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
458 | "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE="
459 | },
460 | "kareem": {
461 | "version": "2.3.2",
462 | "resolved": "https://registry.npmjs.org/kareem/-/kareem-2.3.2.tgz",
463 | "integrity": "sha512-STHz9P7X2L4Kwn72fA4rGyqyXdmrMSdxqHx9IXon/FXluXieaFA6KJ2upcHAHxQPQ0LeM/OjLrhFxifHewOALQ=="
464 | },
465 | "lower-case": {
466 | "version": "2.0.2",
467 | "resolved": "https://registry.npmjs.org/lower-case/-/lower-case-2.0.2.tgz",
468 | "integrity": "sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg==",
469 | "requires": {
470 | "tslib": "^2.0.3"
471 | }
472 | },
473 | "media-typer": {
474 | "version": "0.3.0",
475 | "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz",
476 | "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g="
477 | },
478 | "memory-pager": {
479 | "version": "1.5.0",
480 | "resolved": "https://registry.npmjs.org/memory-pager/-/memory-pager-1.5.0.tgz",
481 | "integrity": "sha512-ZS4Bp4r/Zoeq6+NLJpP+0Zzm0pR8whtGPf1XExKLJBAczGMnSi3It14OiNCStjQjM6NU1okjQGSxgEZN8eBYKg==",
482 | "optional": true
483 | },
484 | "merge-descriptors": {
485 | "version": "1.0.1",
486 | "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz",
487 | "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E="
488 | },
489 | "methods": {
490 | "version": "1.1.2",
491 | "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz",
492 | "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4="
493 | },
494 | "mime": {
495 | "version": "1.6.0",
496 | "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz",
497 | "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg=="
498 | },
499 | "mime-db": {
500 | "version": "1.46.0",
501 | "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.46.0.tgz",
502 | "integrity": "sha512-svXaP8UQRZ5K7or+ZmfNhg2xX3yKDMUzqadsSqi4NCH/KomcH75MAMYAGVlvXn4+b/xOPhS3I2uHKRUzvjY7BQ=="
503 | },
504 | "mime-types": {
505 | "version": "2.1.29",
506 | "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.29.tgz",
507 | "integrity": "sha512-Y/jMt/S5sR9OaqteJtslsFZKWOIIqMACsJSiHghlCAyhf7jfVYjKBmLiX8OgpWeW+fjJ2b+Az69aPFPkUOY6xQ==",
508 | "requires": {
509 | "mime-db": "1.46.0"
510 | }
511 | },
512 | "mongodb": {
513 | "version": "3.6.5",
514 | "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-3.6.5.tgz",
515 | "integrity": "sha512-mQlYKw1iGbvJJejcPuyTaytq0xxlYbIoVDm2FODR+OHxyEiMR021vc32bTvamgBjCswsD54XIRwhg3yBaWqJjg==",
516 | "requires": {
517 | "bl": "^2.2.1",
518 | "bson": "^1.1.4",
519 | "denque": "^1.4.1",
520 | "require_optional": "^1.0.1",
521 | "safe-buffer": "^5.1.2",
522 | "saslprep": "^1.0.0"
523 | }
524 | },
525 | "mongoose": {
526 | "version": "5.12.2",
527 | "resolved": "https://registry.npmjs.org/mongoose/-/mongoose-5.12.2.tgz",
528 | "integrity": "sha512-kT9t6Nvu9WPsfssn7Gzke446Il8UdMilY7Sa5vALtwoOoNOGtZEVjekZBFwsBFzTWtBA/x5gBmJoYFP+1LeDlg==",
529 | "requires": {
530 | "@types/mongodb": "^3.5.27",
531 | "bson": "^1.1.4",
532 | "kareem": "2.3.2",
533 | "mongodb": "3.6.5",
534 | "mongoose-legacy-pluralize": "1.0.2",
535 | "mpath": "0.8.3",
536 | "mquery": "3.2.4",
537 | "ms": "2.1.2",
538 | "regexp-clone": "1.0.0",
539 | "safe-buffer": "5.2.1",
540 | "sift": "7.0.1",
541 | "sliced": "1.0.1"
542 | },
543 | "dependencies": {
544 | "ms": {
545 | "version": "2.1.2",
546 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
547 | "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
548 | },
549 | "safe-buffer": {
550 | "version": "5.2.1",
551 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
552 | "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ=="
553 | }
554 | }
555 | },
556 | "mongoose-legacy-pluralize": {
557 | "version": "1.0.2",
558 | "resolved": "https://registry.npmjs.org/mongoose-legacy-pluralize/-/mongoose-legacy-pluralize-1.0.2.tgz",
559 | "integrity": "sha512-Yo/7qQU4/EyIS8YDFSeenIvXxZN+ld7YdV9LqFVQJzTLye8unujAWPZ4NWKfFA+RNjh+wvTWKY9Z3E5XM6ZZiQ=="
560 | },
561 | "mpath": {
562 | "version": "0.8.3",
563 | "resolved": "https://registry.npmjs.org/mpath/-/mpath-0.8.3.tgz",
564 | "integrity": "sha512-eb9rRvhDltXVNL6Fxd2zM9D4vKBxjVVQNLNijlj7uoXUy19zNDsIif5zR+pWmPCWNKwAtqyo4JveQm4nfD5+eA=="
565 | },
566 | "mquery": {
567 | "version": "3.2.4",
568 | "resolved": "https://registry.npmjs.org/mquery/-/mquery-3.2.4.tgz",
569 | "integrity": "sha512-uOLpp7iRX0BV1Uu6YpsqJ5b42LwYnmu0WeF/f8qgD/On3g0XDaQM6pfn0m6UxO6SM8DioZ9Bk6xxbWIGHm2zHg==",
570 | "requires": {
571 | "bluebird": "3.5.1",
572 | "debug": "3.1.0",
573 | "regexp-clone": "^1.0.0",
574 | "safe-buffer": "5.1.2",
575 | "sliced": "1.0.1"
576 | },
577 | "dependencies": {
578 | "debug": {
579 | "version": "3.1.0",
580 | "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz",
581 | "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==",
582 | "requires": {
583 | "ms": "2.0.0"
584 | }
585 | }
586 | }
587 | },
588 | "ms": {
589 | "version": "2.0.0",
590 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
591 | "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
592 | },
593 | "negotiator": {
594 | "version": "0.6.2",
595 | "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz",
596 | "integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw=="
597 | },
598 | "no-case": {
599 | "version": "3.0.4",
600 | "resolved": "https://registry.npmjs.org/no-case/-/no-case-3.0.4.tgz",
601 | "integrity": "sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg==",
602 | "requires": {
603 | "lower-case": "^2.0.2",
604 | "tslib": "^2.0.3"
605 | }
606 | },
607 | "node-fetch": {
608 | "version": "2.6.1",
609 | "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.1.tgz",
610 | "integrity": "sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw=="
611 | },
612 | "nuqleus": {
613 | "version": "0.1.0",
614 | "resolved": "https://registry.npmjs.org/nuqleus/-/nuqleus-0.1.0.tgz",
615 | "integrity": "sha512-KpCFxVIAppD++j7K1ibVJXe74ciQeghGFZgtMWkGrtI19t5hqkXv8h2Eb/7Ro9XoCXQINh4WDdKSGLSzZykyDw==",
616 | "requires": {
617 | "@graphql-tools/schema": "^7.1.3",
618 | "express": "^4.17.1",
619 | "graphql-middleware": "^6.0.4"
620 | }
621 | },
622 | "object-assign": {
623 | "version": "4.1.1",
624 | "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
625 | "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM="
626 | },
627 | "on-finished": {
628 | "version": "2.3.0",
629 | "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz",
630 | "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=",
631 | "requires": {
632 | "ee-first": "1.1.1"
633 | }
634 | },
635 | "open": {
636 | "version": "8.0.4",
637 | "resolved": "https://registry.npmjs.org/open/-/open-8.0.4.tgz",
638 | "integrity": "sha512-Txc9FOcvjrr5Kv+Zb3w89uKMKiP7wH8mLdYj1xJa+YnhhntEYhbB6cQHjS4O6P+jFwMEzEQVVcpfnu9WkKNuLQ==",
639 | "requires": {
640 | "define-lazy-prop": "^2.0.0",
641 | "is-docker": "^2.1.1",
642 | "is-wsl": "^2.2.0"
643 | }
644 | },
645 | "parseurl": {
646 | "version": "1.3.3",
647 | "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz",
648 | "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ=="
649 | },
650 | "pascal-case": {
651 | "version": "3.1.2",
652 | "resolved": "https://registry.npmjs.org/pascal-case/-/pascal-case-3.1.2.tgz",
653 | "integrity": "sha512-uWlGT3YSnK9x3BQJaOdcZwrnV6hPpd8jFH1/ucpiLRPh/2zCVJKS19E4GvYHvaCcACn3foXZ0cLB9Wrx1KGe5g==",
654 | "requires": {
655 | "no-case": "^3.0.4",
656 | "tslib": "^2.0.3"
657 | }
658 | },
659 | "path-to-regexp": {
660 | "version": "0.1.7",
661 | "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz",
662 | "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w="
663 | },
664 | "pino": {
665 | "version": "6.11.2",
666 | "resolved": "https://registry.npmjs.org/pino/-/pino-6.11.2.tgz",
667 | "integrity": "sha512-bmzxwbrIPxQUlAuMkF4PWVErUGERU4z37HazlhflKFg08crsNE3fACGN6gPwg5xtKOK47Ux5cZm8YCuLV4wWJg==",
668 | "requires": {
669 | "fast-redact": "^3.0.0",
670 | "fast-safe-stringify": "^2.0.7",
671 | "flatstr": "^1.0.12",
672 | "pino-std-serializers": "^3.1.0",
673 | "quick-format-unescaped": "4.0.1",
674 | "sonic-boom": "^1.0.2"
675 | }
676 | },
677 | "pino-std-serializers": {
678 | "version": "3.2.0",
679 | "resolved": "https://registry.npmjs.org/pino-std-serializers/-/pino-std-serializers-3.2.0.tgz",
680 | "integrity": "sha512-EqX4pwDPrt3MuOAAUBMU0Tk5kR/YcCM5fNPEzgCO2zJ5HfX0vbiH9HbJglnyeQsN96Kznae6MWD47pZB5avTrg=="
681 | },
682 | "process-nextick-args": {
683 | "version": "2.0.1",
684 | "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz",
685 | "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag=="
686 | },
687 | "proxy-addr": {
688 | "version": "2.0.6",
689 | "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.6.tgz",
690 | "integrity": "sha512-dh/frvCBVmSsDYzw6n926jv974gddhkFPfiN8hPOi30Wax25QZyZEGveluCgliBnqmuM+UJmBErbAUFIoDbjOw==",
691 | "requires": {
692 | "forwarded": "~0.1.2",
693 | "ipaddr.js": "1.9.1"
694 | }
695 | },
696 | "qs": {
697 | "version": "6.7.0",
698 | "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz",
699 | "integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ=="
700 | },
701 | "quick-format-unescaped": {
702 | "version": "4.0.1",
703 | "resolved": "https://registry.npmjs.org/quick-format-unescaped/-/quick-format-unescaped-4.0.1.tgz",
704 | "integrity": "sha512-RyYpQ6Q5/drsJyOhrWHYMWTedvjTIat+FTwv0K4yoUxzvekw2aRHMQJLlnvt8UantkZg2++bEzD9EdxXqkWf4A=="
705 | },
706 | "range-parser": {
707 | "version": "1.2.1",
708 | "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz",
709 | "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg=="
710 | },
711 | "raw-body": {
712 | "version": "2.4.0",
713 | "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.0.tgz",
714 | "integrity": "sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q==",
715 | "requires": {
716 | "bytes": "3.1.0",
717 | "http-errors": "1.7.2",
718 | "iconv-lite": "0.4.24",
719 | "unpipe": "1.0.0"
720 | }
721 | },
722 | "readable-stream": {
723 | "version": "2.3.7",
724 | "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz",
725 | "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==",
726 | "requires": {
727 | "core-util-is": "~1.0.0",
728 | "inherits": "~2.0.3",
729 | "isarray": "~1.0.0",
730 | "process-nextick-args": "~2.0.0",
731 | "safe-buffer": "~5.1.1",
732 | "string_decoder": "~1.1.1",
733 | "util-deprecate": "~1.0.1"
734 | }
735 | },
736 | "regexp-clone": {
737 | "version": "1.0.0",
738 | "resolved": "https://registry.npmjs.org/regexp-clone/-/regexp-clone-1.0.0.tgz",
739 | "integrity": "sha512-TuAasHQNamyyJ2hb97IuBEif4qBHGjPHBS64sZwytpLEqtBQ1gPJTnOaQ6qmpET16cK14kkjbazl6+p0RRv0yw=="
740 | },
741 | "require_optional": {
742 | "version": "1.0.1",
743 | "resolved": "https://registry.npmjs.org/require_optional/-/require_optional-1.0.1.tgz",
744 | "integrity": "sha512-qhM/y57enGWHAe3v/NcwML6a3/vfESLe/sGM2dII+gEO0BpKRUkWZow/tyloNqJyN6kXSl3RyyM8Ll5D/sJP8g==",
745 | "requires": {
746 | "resolve-from": "^2.0.0",
747 | "semver": "^5.1.0"
748 | }
749 | },
750 | "resolve-from": {
751 | "version": "2.0.0",
752 | "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-2.0.0.tgz",
753 | "integrity": "sha1-lICrIOlP+h2egKgEx+oUdhGWa1c="
754 | },
755 | "safe-buffer": {
756 | "version": "5.1.2",
757 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
758 | "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="
759 | },
760 | "safer-buffer": {
761 | "version": "2.1.2",
762 | "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
763 | "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
764 | },
765 | "saslprep": {
766 | "version": "1.0.3",
767 | "resolved": "https://registry.npmjs.org/saslprep/-/saslprep-1.0.3.tgz",
768 | "integrity": "sha512-/MY/PEMbk2SuY5sScONwhUDsV2p77Znkb/q3nSVstq/yQzYJOH/Azh29p9oJLsl3LnQwSvZDKagDGBsBwSooag==",
769 | "optional": true,
770 | "requires": {
771 | "sparse-bitfield": "^3.0.3"
772 | }
773 | },
774 | "semver": {
775 | "version": "5.7.1",
776 | "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
777 | "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ=="
778 | },
779 | "send": {
780 | "version": "0.17.1",
781 | "resolved": "https://registry.npmjs.org/send/-/send-0.17.1.tgz",
782 | "integrity": "sha512-BsVKsiGcQMFwT8UxypobUKyv7irCNRHk1T0G680vk88yf6LBByGcZJOTJCrTP2xVN6yI+XjPJcNuE3V4fT9sAg==",
783 | "requires": {
784 | "debug": "2.6.9",
785 | "depd": "~1.1.2",
786 | "destroy": "~1.0.4",
787 | "encodeurl": "~1.0.2",
788 | "escape-html": "~1.0.3",
789 | "etag": "~1.8.1",
790 | "fresh": "0.5.2",
791 | "http-errors": "~1.7.2",
792 | "mime": "1.6.0",
793 | "ms": "2.1.1",
794 | "on-finished": "~2.3.0",
795 | "range-parser": "~1.2.1",
796 | "statuses": "~1.5.0"
797 | },
798 | "dependencies": {
799 | "ms": {
800 | "version": "2.1.1",
801 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz",
802 | "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg=="
803 | }
804 | }
805 | },
806 | "serve-static": {
807 | "version": "1.14.1",
808 | "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.14.1.tgz",
809 | "integrity": "sha512-JMrvUwE54emCYWlTI+hGrGv5I8dEwmco/00EvkzIIsR7MqrHonbD9pO2MOfFnpFntl7ecpZs+3mW+XbQZu9QCg==",
810 | "requires": {
811 | "encodeurl": "~1.0.2",
812 | "escape-html": "~1.0.3",
813 | "parseurl": "~1.3.3",
814 | "send": "0.17.1"
815 | }
816 | },
817 | "setprototypeof": {
818 | "version": "1.1.1",
819 | "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz",
820 | "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw=="
821 | },
822 | "sift": {
823 | "version": "7.0.1",
824 | "resolved": "https://registry.npmjs.org/sift/-/sift-7.0.1.tgz",
825 | "integrity": "sha512-oqD7PMJ+uO6jV9EQCl0LrRw1OwsiPsiFQR5AR30heR+4Dl7jBBbDLnNvWiak20tzZlSE1H7RB30SX/1j/YYT7g=="
826 | },
827 | "sliced": {
828 | "version": "1.0.1",
829 | "resolved": "https://registry.npmjs.org/sliced/-/sliced-1.0.1.tgz",
830 | "integrity": "sha1-CzpmK10Ewxd7GSa+qCsD+Dei70E="
831 | },
832 | "sonic-boom": {
833 | "version": "1.4.0",
834 | "resolved": "https://registry.npmjs.org/sonic-boom/-/sonic-boom-1.4.0.tgz",
835 | "integrity": "sha512-1xUAszhQBOrjk7uisbStQZYkZxD3vkYlCUw5qzOblWQ1ILN5v0dVPAs+QPgszzoPmbdWx6jyT9XiLJ95JdlLiQ==",
836 | "requires": {
837 | "atomic-sleep": "^1.0.0",
838 | "flatstr": "^1.0.12"
839 | }
840 | },
841 | "sparse-bitfield": {
842 | "version": "3.0.3",
843 | "resolved": "https://registry.npmjs.org/sparse-bitfield/-/sparse-bitfield-3.0.3.tgz",
844 | "integrity": "sha1-/0rm5oZWBWuks+eSqzM004JzyhE=",
845 | "optional": true,
846 | "requires": {
847 | "memory-pager": "^1.0.2"
848 | }
849 | },
850 | "statuses": {
851 | "version": "1.5.0",
852 | "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz",
853 | "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow="
854 | },
855 | "string_decoder": {
856 | "version": "1.1.1",
857 | "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
858 | "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
859 | "requires": {
860 | "safe-buffer": "~5.1.0"
861 | }
862 | },
863 | "toidentifier": {
864 | "version": "1.0.0",
865 | "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz",
866 | "integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw=="
867 | },
868 | "tslib": {
869 | "version": "2.1.0",
870 | "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.1.0.tgz",
871 | "integrity": "sha512-hcVC3wYEziELGGmEEXue7D75zbwIIVUMWAVbHItGPx0ziyXxrOMQx4rQEVEV45Ut/1IotuEvwqPopzIOkDMf0A=="
872 | },
873 | "type-is": {
874 | "version": "1.6.18",
875 | "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz",
876 | "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==",
877 | "requires": {
878 | "media-typer": "0.3.0",
879 | "mime-types": "~2.1.24"
880 | }
881 | },
882 | "unpipe": {
883 | "version": "1.0.0",
884 | "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz",
885 | "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw="
886 | },
887 | "util-deprecate": {
888 | "version": "1.0.2",
889 | "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
890 | "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8="
891 | },
892 | "utils-merge": {
893 | "version": "1.0.1",
894 | "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz",
895 | "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM="
896 | },
897 | "vary": {
898 | "version": "1.1.2",
899 | "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz",
900 | "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw="
901 | }
902 | }
903 | }
904 |
--------------------------------------------------------------------------------
/__test__/express-server/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "express-server",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "index.js",
6 | "scripts": {
7 | "start": "nodemon app.js"
8 | },
9 | "keywords": [],
10 | "author": "",
11 | "license": "ISC",
12 | "dependencies": {
13 | "cors": "^2.8.5",
14 | "dotenv": "^8.2.0",
15 | "express": "^4.17.1",
16 | "express-graphql": "^0.12.0",
17 | "graphql": "^15.5.0",
18 | "graphql-middleware": "^6.0.4",
19 | "mongoose": "^5.11.18",
20 | "node-fetch": "^2.6.1",
21 | "nuqleus": "^0.1.0",
22 | "open": "^8.0.4",
23 | "pino": "^6.11.1"
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/__test__/express-server/sample_queries/comment-mutation.js:
--------------------------------------------------------------------------------
1 | // addComment mutation:
2 |
3 | mutation {
4 | addComment (name: "test", email: "test@gmail.com", movie_id: "573a1390f29313caabcd5293", text: "hello world", date:"03-04-2021") {
5 | _id
6 | text
7 | }
8 | }
--------------------------------------------------------------------------------
/__test__/express-server/sample_queries/main-comment-query.js:
--------------------------------------------------------------------------------
1 | // Single comment
2 | query {
3 | comment(id: "5a9427648b0beebeb6957b18") {
4 | _id
5 | name
6 | email
7 | text
8 | date
9 | movie_id
10 | movie {
11 | title
12 | }
13 | }
14 | }
15 |
16 | // First 100 comments
17 | query comments {
18 | comments(first: 100) {
19 | _id
20 | name
21 | email
22 | text
23 | date
24 | movie_id
25 | movie {
26 | title
27 | }
28 | }
29 | }
30 |
31 | // Variable Example
32 | query comments ($id: ID!) {
33 | comment(id: $id) {
34 | _id
35 | name
36 | email
37 | text
38 | date
39 | movie_id
40 | movie {
41 | title
42 | cast
43 | }
44 | }
45 | }
46 |
47 | {"id": "5a9427648b0beebeb6957b18"}
--------------------------------------------------------------------------------
/__test__/express-server/sample_queries/main-movie-query.js:
--------------------------------------------------------------------------------
1 | // First five full movie query:
2 |
3 | query movies {
4 | movies (first: 4) {
5 | _id
6 | title
7 | year
8 | runtime
9 | released
10 | poster
11 | rated
12 | cast
13 | plot
14 | fullplot
15 | lastupdated
16 | type
17 | directors
18 | writers
19 | imdb {
20 | id
21 | }
22 | awards {
23 | wins
24 | nominations
25 | text
26 | }
27 | tomatoes {
28 | lastUpdated
29 | }
30 | languages
31 | countries
32 | genres
33 | num_mflix_comments
34 | comments {
35 | name
36 | }
37 | }
38 | }
--------------------------------------------------------------------------------
/__test__/express-server/sample_queries/min-movie-query.js:
--------------------------------------------------------------------------------
1 | // First 10 movies with only title, cast, and comments fields
2 | query movies {
3 | movies (first: 10) {
4 | title
5 | cast
6 | comments {
7 | name
8 | }
9 | }
10 | }
11 |
12 | // First 5 movies with only title and cast fields
13 | query movies {
14 | movies (first: 5) {
15 | title
16 | cast
17 | }
18 | }
--------------------------------------------------------------------------------
/__test__/express-server/schema/schema.js:
--------------------------------------------------------------------------------
1 | const graphql = require('graphql');
2 | const Movie = require('../db/movie-models');
3 | const Comment = require('../db/comments-models');
4 | const types = require('./types');
5 |
6 | const { GraphQLObjectType, GraphQLString, GraphQLID, GraphQLInt, GraphQLList,
7 | GraphQLNonNull, GraphQLInputObjectType, GraphQLFloat, GraphQLSchema } = graphql;
8 |
9 | //Schema defines data on the Graph like object types(book type), relation between
10 | //these object types and descibes how it can reach into the graph to interact with
11 | //the data to retrieve or mutate the data
12 |
13 | // const fakeBookDatabase = [
14 | // { name:"Book 1", pages:432 , id:1},
15 | // { name: "Book 2", pages: 32, id: 2},
16 | // { name: "Book 3", pages: 532, id: 3 }
17 | // ]
18 |
19 | //RootQuery describe how users can use the graph and grab data.
20 | //E.g Root query to get all authors, get all books, get a particular book
21 | //or get a particular author.
22 |
23 | const RootQuery = new GraphQLObjectType({
24 | name: 'RootQueryType',
25 | fields: {
26 | movie: {
27 | type: types.MovieType,
28 | //args passed by user while making query
29 | args: { id: { type: GraphQLID } },
30 | resolve(parent, args) {
31 | // Define how to get data from a database source
32 | return Movie.findById(args.id);
33 | }
34 | },
35 | movies: {
36 | type: new GraphQLList(types.MovieType),
37 | args: { first: { type: GraphQLInt } },
38 | resolve(parent, args) {
39 | return Movie.find({}).limit(args.first);
40 | }
41 | },
42 | comment: {
43 | type: types.CommentType,
44 | args: { id: { type: GraphQLID } },
45 | resolve(parent, args) {
46 | return Comment.findById(args.id);
47 | }
48 | },
49 | comments: {
50 | type: new GraphQLList(types.CommentType),
51 | args: { first: { type: GraphQLInt } },
52 | resolve(parent, args) {
53 | return Comment.find({}).limit(args.first);
54 | }
55 | }
56 | }
57 | });
58 |
59 | const Mutation = new GraphQLObjectType({
60 | name: 'Mutation',
61 | fields: {
62 | addMovie: {
63 | type: types.MovieType,
64 | args: {
65 | title: { type: new GraphQLNonNull(GraphQLString) },
66 | year: { type: new GraphQLNonNull(GraphQLInt) },
67 | runtime: { type: new GraphQLNonNull(GraphQLInt) },
68 | released: { type: new GraphQLNonNull(GraphQLString) },
69 | poster: { type: GraphQLString },
70 | rated: { type: GraphQLString },
71 | cast: { type: new GraphQLList(GraphQLString) },
72 | plot: { type: GraphQLString },
73 | fullplot: { type: GraphQLString },
74 | lastupdated: { type: GraphQLString },
75 | type: { type: GraphQLString },
76 | directors: { type: new GraphQLList(GraphQLString) },
77 | writers: { type: new GraphQLList(GraphQLString) },
78 | imdb: { type: new GraphQLInputObjectType({
79 | name: 'ImdbInput',
80 | fields: {
81 | rating: { type: GraphQLInt },
82 | votes: { type: GraphQLInt },
83 | id: { type: GraphQLInt }
84 | }
85 | })},
86 | awards: { type: new GraphQLInputObjectType({
87 | name: 'AwardsInput',
88 | fields: {
89 | wins: { type: GraphQLInt },
90 | nominations: { type: GraphQLInt },
91 | text: { type: GraphQLString },
92 | },
93 | }) },
94 | tomatoes: { type: new GraphQLInputObjectType({
95 | name: 'TomatoesInput',
96 | fields: {
97 | viewer: {
98 | type: new GraphQLInputObjectType({
99 | name: 'ViewerInput',
100 | fields: () => ({
101 | rating: { type: GraphQLInt },
102 | numReviews: { type: GraphQLInt },
103 | meter: { type: GraphQLInt }
104 | })
105 | })
106 | },
107 | lastUpdated: { type: GraphQLString }
108 | }
109 | }) },
110 | languages: { type: new GraphQLList(GraphQLString) },
111 | countries: { type: new GraphQLList(GraphQLString) },
112 | genres: { type: new GraphQLList(GraphQLString) },
113 | num_mflix_comments: { type: GraphQLInt },
114 | },
115 | resolve(parent, args) {
116 | let movie = new Movie({
117 | title: args.title,
118 | year: args.year,
119 | runtime: args.runtime,
120 | released: args.released,
121 | poster: args.poster,
122 | rated: args.rated,
123 | cast: args.cast,
124 | plot: args.plot,
125 | fullplot: args.fullplot,
126 | lastupdated: args.lastupdated,
127 | type: args.type,
128 | directors: args.directors,
129 | writers: args.writers,
130 | imdb: args.imdb,
131 | awards: args.awards,
132 | tomatoes: args.tomatoes,
133 | languages: args.languages,
134 | countries: args.countries,
135 | genres: args.genres,
136 | num_mflix_comments: args.num_mflix_comments
137 | });
138 | return movie.save();
139 | }
140 | },
141 | addComment: {
142 | type: types.CommentType,
143 | args: {
144 | // _id: { type: new GraphQLNonNull(GraphQLID) },
145 | name: { type: new GraphQLNonNull(GraphQLString) },
146 | email: { type: new GraphQLNonNull(GraphQLString) },
147 | movie_id: { type: new GraphQLNonNull(GraphQLID)},
148 | text: { type: new GraphQLNonNull(GraphQLString) },
149 | date: {
150 | type: GraphQLString,
151 | resolve() {
152 | return Date.now();
153 | }
154 | },
155 | },
156 | resolve(parent, args) {
157 | let comment = new Comment({
158 | //_id: args._id,
159 | name: args.name,
160 | email: args.email,
161 | movie_id: args.movie_id,
162 | text: args.text,
163 | date: args.date
164 | })
165 | return comment.save();
166 | }
167 | }
168 | }
169 | });
170 |
171 | //Creating a new GraphQL Schema, with options query which defines query
172 | //we will allow users to use when they are making request.
173 |
174 | module.exports = new GraphQLSchema({
175 | query: RootQuery,
176 | mutation: Mutation
177 | });
178 |
--------------------------------------------------------------------------------
/__test__/express-server/schema/types.js:
--------------------------------------------------------------------------------
1 | const graphql = require('graphql');
2 | const Movie = require('../db/movie-models');
3 | const Comment = require('../db/comments-models');
4 |
5 | const {
6 | GraphQLObjectType,
7 | GraphQLString,
8 | GraphQLID,
9 | GraphQLInt,
10 | GraphQLList,
11 | GraphQLNonNull,
12 | GraphQLInputObjectType,
13 | GraphQLFloat,
14 | GraphQLSchema
15 | } = graphql;
16 |
17 | const ImdbType = new GraphQLObjectType({
18 | name: 'imdb',
19 | fields: () => ({
20 | rating: { type: GraphQLString },
21 | votes: { type: GraphQLString },
22 | id: { type: GraphQLInt }
23 | })
24 | });
25 |
26 | const AwardsType = new GraphQLObjectType({
27 | name: 'awards',
28 | fields: () => ({
29 | wins: { type: GraphQLInt },
30 | nominations: { type: GraphQLInt },
31 | text: { type: GraphQLString },
32 | })
33 | });
34 |
35 | const ViewerType = new GraphQLObjectType({
36 | name: 'viewer',
37 | fields: () => ({
38 | rating: { type: GraphQLFloat },
39 | numReviews: { type: GraphQLInt },
40 | meter: { type: GraphQLInt }
41 | })
42 | });
43 |
44 | const TomatoesType = new GraphQLObjectType({
45 | name: 'tomatoes',
46 | fields: () => ({
47 | viewer: { type: ViewerType },
48 | lastUpdated: { type: GraphQLString }
49 | })
50 | });
51 |
52 | const MovieType = new GraphQLObjectType({
53 | name: 'Movie',
54 | fields: () => ({
55 | _id: { type: GraphQLID },
56 | title: { type: GraphQLString },
57 | year: { type: GraphQLInt },
58 | runtime: { type: GraphQLInt },
59 | released: { type: GraphQLString },
60 | poster: { type: GraphQLString },
61 | rated: { type: GraphQLString },
62 | cast: { type: GraphQLList(GraphQLString) },
63 | plot: { type: GraphQLString },
64 | fullplot: { type: GraphQLString },
65 | lastupdated: { type: GraphQLString },
66 | type: { type: GraphQLString },
67 | directors: { type: GraphQLList(GraphQLString) },
68 | writers: { type: GraphQLList(GraphQLString) },
69 | imdb: { type: ImdbType },
70 | awards: { type: AwardsType },
71 | tomatoes: { type: TomatoesType },
72 | languages: { type: GraphQLList(GraphQLString) },
73 | countries: { type: GraphQLList(GraphQLString) },
74 | genres: { type: GraphQLList(GraphQLString) },
75 | num_mflix_comments: { type: GraphQLInt },
76 | comments: {
77 | type: new GraphQLList(CommentType),
78 | async resolve(parent, args) {
79 | return await Comment.find({ movie_id: parent._id })
80 | }
81 | }
82 | })
83 | });
84 |
85 | const CommentType = new GraphQLObjectType({
86 | name: 'Comment',
87 | fields: () => ({
88 | _id: { type: GraphQLID },
89 | name: { type: GraphQLString },
90 | email: { type: GraphQLString },
91 | movie_id: { type: GraphQLString },
92 | movie: {
93 | type: MovieType,
94 | async resolve(parent, args) {
95 | return await Movie.findById(parent.movie_id)
96 | }
97 | },
98 | text: { type: GraphQLString },
99 | date: { type: GraphQLString },
100 | })
101 | });
102 |
103 | const InputMovieType = new GraphQLInputObjectType({
104 | name: 'MovieInput',
105 | fields: {
106 | title: { type: new GraphQLNonNull(GraphQLString) },
107 | year: { type: new GraphQLNonNull(GraphQLInt) },
108 | runtime: { type: new GraphQLNonNull(GraphQLInt) },
109 | released: { type: new GraphQLNonNull(GraphQLString) },
110 | poster: { type: GraphQLString },
111 | rated: { type: GraphQLString },
112 | cast: { type: new GraphQLList(GraphQLString) },
113 | plot: { type: GraphQLString },
114 | fullplot: { type: GraphQLString },
115 | lastupdated: { type: GraphQLString },
116 | type: { type: GraphQLString },
117 | directors: { type: new GraphQLList(GraphQLString) },
118 | writers: { type: new GraphQLList(GraphQLString) },
119 | imdb: { type: new GraphQLInputObjectType({
120 | name: 'ImdbInput',
121 | fields: {
122 | rating: { type: GraphQLInt },
123 | votes: { type: GraphQLInt },
124 | id: { type: GraphQLInt }
125 | }
126 | })},
127 | awards: { type: new GraphQLInputObjectType({
128 | name: 'AwardsInput',
129 | fields: {
130 | wins: { type: GraphQLInt },
131 | nominations: { type: GraphQLInt },
132 | text: { type: GraphQLString },
133 | },
134 | }) },
135 | tomatoes: { type: new GraphQLInputObjectType({
136 | name: 'TomatoesInput',
137 | fields: {
138 | viewer: {
139 | type: new GraphQLInputObjectType({
140 | name: 'ViewerInput',
141 | fields: () => ({
142 | rating: { type: GraphQLInt },
143 | numReviews: { type: GraphQLInt },
144 | meter: { type: GraphQLInt }
145 | })
146 | })
147 | },
148 | lastUpdated: { type: GraphQLString }
149 | }
150 | }) },
151 | languages: { type: new GraphQLList(GraphQLString) },
152 | countries: { type: new GraphQLList(GraphQLString) },
153 | genres: { type: new GraphQLList(GraphQLString) },
154 | num_mflix_comments: { type: GraphQLInt },
155 | }
156 | });
157 |
158 | module.exports = { ImdbType, TomatoesType, AwardsType, MovieType, CommentType, InputMovieType };
159 |
--------------------------------------------------------------------------------
/contributing.md:
--------------------------------------------------------------------------------
1 | # Contributing
2 |
3 | nuQLeus encourages open source contributions and feedback to this product.
4 |
5 | ## Pull Requests
6 |
7 | nuQLeus welcomes all pull requests.
8 |
9 | 1. Fork the repo and create a working branch from `main`.
10 | 2. If you've added any code that requires testing, add tests.
11 | 3. Make sure code is formatted with `prettier` and follows the [Airbnb React/JSX Style Guide](https://github.com/airbnb/javascript/blob/master/react/README.md).
12 | 4. Create a pull request to `staging`.
13 |
14 | ## Issues
15 |
16 | Please do not hesitate to file issues. nuQLeus is based off of community feedback and is always looking for ways to get better. The team behind nuQLeus is interested to hear about your experience and how we can improve it.
17 |
18 | Please do not hesitate to submit issues that promote bugs or offer ways to enhance to nuQLeus. When submitting issues, ensure your description is clear and has instructions to be able to reproduce the issue.
19 |
20 | ## Get in touch
21 |
22 | We use GitHub as a platform of communication between users and developers to promote transparency. We thrive off of the community support and feedback. Mostly.
--------------------------------------------------------------------------------
/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | nuQLeus
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/jest.config.js:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/nuqleus_npm_package/.gitignore:
--------------------------------------------------------------------------------
1 | .ds_store
2 | node_modules/
--------------------------------------------------------------------------------
/nuqleus_npm_package/README.md:
--------------------------------------------------------------------------------
1 | # nuQLeus
2 |
3 | Boost GraphQL endpoint testing capabilities with resolver-level performance metrics.
4 |
5 |
6 |
7 |
8 |
9 |
10 | [](https://github.com/oslabs-beta/NuQLeus)
11 | 
12 |
13 | ## Table of Contents
14 |
15 | - [Description](#description)
16 | - [Features](#features)
17 | - [Getting Started with nuQLeus](#Getting-Started-with-nuQLeus)
18 | - [Install nuQLeus](#Install-nuQLeus)
19 | - [Apollo Server Setup](#Apollo-Server-Setup)
20 | - [Express-GraphQL Setup](#Express-GraphQL-Setup)
21 | - [Using the nuQLeus GUI](#Using-the-nuQLeus-GUI)
22 | - [Contributing](#contributing)
23 | - [Authors](#authors)
24 | - [License](#license)
25 | - [Links/Contact](Links/Contacts)
26 |
27 |
28 |
29 | ## Description
30 |
31 | NuQLeus is a lightweight, self-contained, GraphQL endpoint testing GUI that extracts resolver-level tracing performance metrics from GraphQL queries and mutations and allows an enduser to easily identify specific resolvers that are having a detrimental impact on application performance.
32 |
33 |
34 |
35 | ## Features
36 |
37 | * Simulate GraphQL queries and mutations in the nuQLeus environment
38 | * Real-time tracing durations at individual resolver-level for GraphQL queries and mutations
39 | * Processing and visualization of tracing data to help identify performance drop-offs at a glance
40 |
41 |
42 |
43 | ## Getting Started With nuQLeus
44 |
45 | ### **Install nuQLeus**
46 |
47 | ```javascript
48 | npm install --save-dev nuqleus
49 | ```
50 |
51 |
52 |
53 | ### **Apollo Server Setup**
54 |
55 | The Apollo Server constructor function accepts an object with properties that convey schema options. Simply pass the existing options object into the `nuqleus.ApolloWrapOptions` method to return a new options object to be passed into the `ApolloServer` constructor.
56 |
57 | ```javascript
58 | const { ApolloServer } = require('apollo-server');
59 | const connectDb = require('./config/db');
60 | const typeDefs = require('./types');
61 | const resolvers = require('./resolvers');
62 | const models = require('./models');
63 | import nuqleus from 'nuqleus';
64 |
65 | connectDb();
66 |
67 | // 1. Define your context either as an object or function //
68 | // Add your models in here, if any //
69 | const userContext = {
70 | models,
71 | sampleObject: {},
72 | };
73 |
74 | // 2. Define your formatResponse, if any, as an object //
75 | const userFormatResponse = {
76 | formatResponse: (res, reqContext) => {
77 | res.http = {
78 | someUserHttp: {
79 | startTime: new Date().toISOString(),
80 | endTime: new Date(Date.now()).toISOString(),
81 | }
82 | };
83 | }
84 | };
85 |
86 | // 3. Create a nuqleusServerObject using the ApolloWrapOptions method //
87 | // Allowable inputs: typeDefs, resolvers, context, formatResponse, ...resolverInputs //
88 | const nuqleusServerObject = nuqleus.ApolloWrapOptions(
89 | typeDefs, resolvers, userContext, userFormatResponse
90 | );
91 |
92 | /**
93 | * If any resolverInputs will be inputted, they will be wrapped after
94 | * the nuQLeusTraceResolver around your schema with the applyMiddleware method.
95 | *
96 | * const schemaWithMiddleWare = applyMiddleware(clientSchema, nuqleusTraceResolvers, ...clientInputs);
97 | */
98 |
99 | // 4. Spread the nuqleusServerObject into your new ApolloServer instance //
100 | // If you have any add'l options, add them in after
101 | const server = new ApolloServer({
102 | ...nuqleusServerObject,
103 | // add'l user options,
104 | // add'l user options,
105 | });
106 |
107 | // 5. Run your server /
108 | server.listen(4001).then(({ url }) => {
109 | console.log(`🚀 Server ready at ${url}`);
110 | });
111 | ```
112 |
113 |
114 |
115 | ### **Express-GraphQL Setup**
116 |
117 | Express-graphql's `graphqlHTTP` function accepts an options parameter that can either be an object or a function. Simply pass existing options into `nuqleus.WrapOptions` function to return a new options callback to pass into `graphqlHTTP`.
118 |
119 | If users have `extensions`, simply pass the `extensions` callback into `nuqleus.WrapOptions` as a second optional argument.
120 |
121 | ```js
122 | const express = require('express');
123 | const { graphqlHTTP } = require('express-graphql');
124 | const schema = require('./schema');
125 | const models = require('./models');
126 | const nuqleus = require('./nuqleus');
127 |
128 | const extensions = ({ document, variables, operationName, result, context }) => ({
129 | hello: context.hello,
130 | });
131 |
132 | const options = {
133 | schema,
134 | context: { models, hello: 'world' },
135 | graphiql: true,
136 | };
137 |
138 | const newOptions = nuqleus.WrapOptions(options, extensions);
139 |
140 | app.use('/graphql', graphqlHTTP(newOptions));
141 |
142 | app.listen(4000, () => {
143 | console.log('Listening on port 4000');
144 | });
145 |
146 | ```
147 |
148 |
149 |
150 | ### **Using the nuQLeus GUI**
151 | The nuQLeus wrapper methods instantiate a server and serve the nuQLeus GUI whenever a user's GraphQL server is initialized. In order to access the nuQLeus GUI, navigate to http://localhost:3030/nuqleus while your server is running.
152 |
153 |
154 |
155 |
156 |
157 |
158 |
159 | ## Contributing
160 |
161 | Development of nuQLeus is open source on Hithub through the tech accelerator umbrella OS Labs. We are grateful for the community's contribution to the project. Please read the [contribution documentation](contributing.md) to learn more on how you can participate in improvements.
162 |
163 |
164 |
165 | ## Authors
166 |
167 | * Daniel Perez [Daniel-P3](https://github.com/Daniel-P3)
168 | * Jenny Hai [jhai420](https://github.com/jhai420)
169 | * Joshua Kim [jkim000](https://github.com/jkim000)
170 | * Zach Brucker [zbrucker](https://github.com/zbrucker)
171 |
172 |
173 |
174 | ## License
175 |
176 | [MIT](https://opensource.org/licenses/mit-license.php)
177 |
178 |
179 |
180 | ## Links/Contacts
181 |
182 | * Email: nuqleusjs@gmail.com
183 | * [Landing Page](http://www.nuqleus.io/)
184 | * [npm](https://www.npmjs.com/package/nuqleus)
185 | * [LinkedIn](https://www.linkedin.com/company/nuqleus)
186 |
187 |
188 |
189 | #
190 | ##### [Return to Top](#nuQLeus)
--------------------------------------------------------------------------------
/nuqleus_npm_package/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | nuQLeus
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/nuqleus_npm_package/main.js:
--------------------------------------------------------------------------------
1 | const exec = require('child_process').exec;
2 | exec('node server.js', { encoding: 'utf-8' });
3 |
--------------------------------------------------------------------------------
/nuqleus_npm_package/nuqleus.js:
--------------------------------------------------------------------------------
1 | const { makeExecutableSchema } = require('@graphql-tools/schema');
2 | const { applyMiddleware } = require('graphql-middleware');
3 | const { exec } = require('child_process');
4 |
5 | const nuqleus = {};
6 |
7 | const connectToNuqleus = () => {
8 | exec('node server.js', { encoding: 'utf-8' });
9 | };
10 |
11 | /**
12 | * @param {*} options can be an object or a callback function
13 | * @param {*} clientExtensions optional callback function
14 | * @returns new options callback containing nuQleus tracing data
15 | */
16 | nuqleus.WrapOptions = (options, clientExtensions) => {
17 | // connectToNuqleus() starts an express server and serves nuQLeus GUI to localhost:3030/nuqleus
18 | connectToNuqleus();
19 |
20 | const traceResolvers = async (resolve, root, args, context, info) => {
21 | const startTime = Date.now();
22 | const result = await resolve(root, args, context, info);
23 | const endTime = Date.now();
24 |
25 | const pathArray = [];
26 | let curPath = info.path;
27 | do {
28 | pathArray.push(curPath.key);
29 | curPath = curPath.prev;
30 | } while (curPath);
31 |
32 | const resolverData = {
33 | path: pathArray.reverse(),
34 | startTime: new Date(startTime).toISOString(),
35 | endTime: new Date(endTime).toISOString(),
36 | fieldName: info.fieldName,
37 | duration: endTime - startTime,
38 | operation: info.operation.operation,
39 | parentType: info.parentType,
40 | returnType: info.returnType,
41 | };
42 |
43 | context.nuqleusQueryTimes.push(resolverData);
44 | return result;
45 | };
46 |
47 | const extensions = ({ document, variables, operationName, result, context }) => {
48 | // Create another callback that modifies that OGExt and return a single object
49 | const nuqleusExt = ({ document, variables, operationName, result, context }) => ({
50 | nuQLeusTracing: {
51 | startTime: new Date(context.nuqleusStartTime).toISOString(),
52 | endTime: new Date(Date.now()).toISOString(),
53 | duration: Date.now() - context.nuqleusStartTime,
54 | resolvers: context.nuqleusQueryTimes,
55 | },
56 | });
57 |
58 | const newExt = nuqleusExt({ document, variables, operationName, result, context });
59 |
60 | // If clientExtensions does not exist, return nuqleus-tracing extensions
61 | if (!clientExtensions) return newExt;
62 |
63 | // If clientExtensions do exist, then process existing clientExtensions and combine into a single object with nuqleus-tracing extensions
64 | const originalExt = clientExtensions({ document, variables, operationName, result, context });
65 | return {
66 | ...originalExt,
67 | ...newExt,
68 | };
69 | };
70 |
71 | if (typeof options === 'object') {
72 | return (request, response, graphQLParams) => ({
73 | ...options,
74 | schema: applyMiddleware(options.schema, traceResolvers),
75 | context: options.context
76 | ? { ...options.context, nuqleusStartTime: Date.now(), nuqleusQueryTimes: [] }
77 | : { nuqleusStartTime: Date.now(), nuqleusQueryTimes: [] },
78 | extensions,
79 | });
80 | }
81 | if (typeof options === 'function') {
82 | return (request, response, graphQLParams) => {
83 | const originalOptions = options(request, response, graphQLParams);
84 | return {
85 | ...originalOptions,
86 | schema: applyMiddleware(originalOptions.schema, traceResolvers),
87 | context: originalOptions.context
88 | ? { ...originalOptions.context, nuqleusStartTime: Date.now(), nuqleusQueryTimes: [] }
89 | : { nuqleusStartTime: Date.now(), nuqleusQueryTimes: [] },
90 | extensions,
91 | };
92 | };
93 | }
94 | };
95 |
96 | /**
97 | * @param {*} typeDefs required
98 | * @param {*} resolvers required
99 | * @param {*} clientContext optional; can be object or callback
100 | * @param {*} clientFormatResponse option; must be object with a formatResponse key
101 | * @param {*} clientInputs optional; can be spread with multiple callbacks
102 | * @returns object to be spread into the client's new ApolloServer() instance
103 | */
104 | nuqleus.ApolloWrapOptions = (
105 | typeDefs,
106 | resolvers,
107 | clientContext,
108 | clientFormatResponse,
109 | ...clientInputs
110 | ) => {
111 | // connectToNuqleus() starts an express server and serves nuQLeus GUI to localhost:3030/nuqleus
112 | connectToNuqleus();
113 | // create executableSchema
114 | const schema = makeExecutableSchema({
115 | typeDefs,
116 | resolvers,
117 | });
118 |
119 | // resolver level metrics invoked at each call
120 | const traceResolvers = async (resolve, root, args, context, info) => {
121 | const startTime = Date.now();
122 | const result = await resolve(root, args, context, info);
123 | const endTime = Date.now();
124 |
125 | const pathArray = [];
126 | let curPath = info.path;
127 | do {
128 | pathArray.push(curPath.key);
129 | curPath = curPath.prev;
130 | } while (curPath);
131 |
132 | const resolverData = {
133 | path: pathArray.reverse(),
134 | startTime: new Date(startTime).toISOString(),
135 | endTime: new Date(endTime).toISOString(),
136 | fieldName: info.fieldName,
137 | duration: endTime - startTime,
138 | operation: info.operation.operation,
139 | parentType: info.parentType,
140 | returnType: info.returnType,
141 | };
142 |
143 | context.nuqleusQueryTimes.push(resolverData);
144 | return result;
145 | };
146 |
147 | // apply middleware to schema
148 | const schemaWithMiddleWare = applyMiddleware(schema, traceResolvers, ...clientInputs);
149 |
150 | /**
151 | * @returns must be a function that returns an object
152 | *
153 | * fuse client context object with nuQLeus context
154 | */
155 | const fuseContexts = () => {
156 | if (typeof clientContext === 'object') {
157 | return async ({ req, res }) => ({
158 | ...clientContext,
159 | nuqleusStartTime: Date.now(),
160 | nuqleusQueryTimes: [],
161 | });
162 | }
163 | if (typeof clientContext === 'function') {
164 | return async ({ req, res }) => ({
165 | ...clientContext({ req, res }),
166 | nuqleusStartTime: Date.now(),
167 | nuqleusQueryTimes: [],
168 | });
169 | }
170 | };
171 |
172 | /**
173 | * @returns must be a function that returns the response with an extensions object
174 | *
175 | * fuse client formatResponse function with nuQLeus formatResponse
176 | */
177 | const nuqleusFormatResponse = (response, requestContext) => {
178 | if (response.extensions) {
179 | response.extensions.nuQLeusTracing = {
180 | startTime: new Date(requestContext.context.nuqleusStartTime).toISOString(),
181 | endTime: new Date(Date.now()).toISOString(),
182 | duration: Date.now() - requestContext.context.nuqleusStartTime,
183 | resolvers: requestContext.context.nuqleusQueryTimes,
184 | };
185 | } else {
186 | response.extensions = {
187 | nuQLeusTracing: {
188 | startTime: new Date(requestContext.context.nuqleusStartTime).toISOString(),
189 | endTime: new Date(Date.now()).toISOString(),
190 | duration: Date.now() - requestContext.context.nuqleusStartTime,
191 | resolvers: requestContext.context.nuqleusQueryTimes,
192 | },
193 | };
194 | }
195 | };
196 |
197 | const fuseFormatResponse = () => (response, requestContext) => {
198 | clientFormatResponse.formatResponse(response, requestContext);
199 | nuqleusFormatResponse(response, requestContext);
200 | };
201 |
202 | /**
203 | * @returns object with schema, context, and formatResponse
204 | *
205 | * drop this object output into the client's new ApolloServer() instance
206 | */
207 | return {
208 | schema: schemaWithMiddleWare,
209 | context: fuseContexts(),
210 | formatResponse: fuseFormatResponse(),
211 | };
212 | };
213 |
214 | module.exports = nuqleus;
215 |
--------------------------------------------------------------------------------
/nuqleus_npm_package/package-lock.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "nuqleus",
3 | "version": "0.1.0",
4 | "lockfileVersion": 2,
5 | "requires": true,
6 | "packages": {
7 | "": {
8 | "name": "nuqleus",
9 | "version": "0.1.0",
10 | "license": "ISC",
11 | "dependencies": {
12 | "@graphql-tools/schema": "^7.1.3",
13 | "express": "^4.17.1",
14 | "graphql": "^15.5.0",
15 | "graphql-middleware": "^6.0.4",
16 | "open": "^8.0.4"
17 | }
18 | },
19 | "node_modules/@ardatan/aggregate-error": {
20 | "version": "0.0.6",
21 | "resolved": "https://registry.npmjs.org/@ardatan/aggregate-error/-/aggregate-error-0.0.6.tgz",
22 | "integrity": "sha512-vyrkEHG1jrukmzTPtyWB4NLPauUw5bQeg4uhn8f+1SSynmrOcyvlb1GKQjjgoBzElLdfXCRYX8UnBlhklOHYRQ==",
23 | "dependencies": {
24 | "tslib": "~2.0.1"
25 | },
26 | "engines": {
27 | "node": ">=8"
28 | }
29 | },
30 | "node_modules/@ardatan/aggregate-error/node_modules/tslib": {
31 | "version": "2.0.3",
32 | "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.0.3.tgz",
33 | "integrity": "sha512-uZtkfKblCEQtZKBF6EBXVZeQNl82yqtDQdv+eck8u7tdPxjLu2/lp5/uPW+um2tpuxINHWy3GhiccY7QgEaVHQ=="
34 | },
35 | "node_modules/@graphql-tools/batch-execute": {
36 | "version": "7.0.0",
37 | "resolved": "https://registry.npmjs.org/@graphql-tools/batch-execute/-/batch-execute-7.0.0.tgz",
38 | "integrity": "sha512-+ywPfK6N2Ddna6oOa5Qb1Mv7EA8LOwRNOAPP9dL37FEhksJM9pYqPSceUcqMqg7S9b0+Cgr78s408rgvurV3/Q==",
39 | "dependencies": {
40 | "@graphql-tools/utils": "^7.0.0",
41 | "dataloader": "2.0.0",
42 | "is-promise": "4.0.0",
43 | "tslib": "~2.0.1"
44 | }
45 | },
46 | "node_modules/@graphql-tools/batch-execute/node_modules/tslib": {
47 | "version": "2.0.3",
48 | "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.0.3.tgz",
49 | "integrity": "sha512-uZtkfKblCEQtZKBF6EBXVZeQNl82yqtDQdv+eck8u7tdPxjLu2/lp5/uPW+um2tpuxINHWy3GhiccY7QgEaVHQ=="
50 | },
51 | "node_modules/@graphql-tools/delegate": {
52 | "version": "7.0.10",
53 | "resolved": "https://registry.npmjs.org/@graphql-tools/delegate/-/delegate-7.0.10.tgz",
54 | "integrity": "sha512-6Di9ia5ohoDvrHuhj2cak1nJGhIefJmUsd3WKZcJ2nu2yZAFawWMxGvQImqv3N7iyaWKiVhrrK8Roi/JrYhdKg==",
55 | "dependencies": {
56 | "@ardatan/aggregate-error": "0.0.6",
57 | "@graphql-tools/batch-execute": "^7.0.0",
58 | "@graphql-tools/schema": "^7.0.0",
59 | "@graphql-tools/utils": "^7.1.6",
60 | "dataloader": "2.0.0",
61 | "is-promise": "4.0.0",
62 | "tslib": "~2.1.0"
63 | }
64 | },
65 | "node_modules/@graphql-tools/schema": {
66 | "version": "7.1.3",
67 | "resolved": "https://registry.npmjs.org/@graphql-tools/schema/-/schema-7.1.3.tgz",
68 | "integrity": "sha512-ZY76hmcJlF1iyg3Im0sQ3ASRkiShjgv102vLTVcH22lEGJeCaCyyS/GF1eUHom418S60bS8Th6+autRUxfBiBg==",
69 | "dependencies": {
70 | "@graphql-tools/utils": "^7.1.2",
71 | "tslib": "~2.1.0"
72 | }
73 | },
74 | "node_modules/@graphql-tools/utils": {
75 | "version": "7.6.0",
76 | "resolved": "https://registry.npmjs.org/@graphql-tools/utils/-/utils-7.6.0.tgz",
77 | "integrity": "sha512-YCZDDdhfb4Yhie0IH031eGdvQG8C73apDuNg6lqBNbauNw45OG/b8wi3+vuMiDnJTJN32GQUb1Gt9gxDKoRDKw==",
78 | "dependencies": {
79 | "@ardatan/aggregate-error": "0.0.6",
80 | "camel-case": "4.1.2",
81 | "tslib": "~2.1.0"
82 | }
83 | },
84 | "node_modules/accepts": {
85 | "version": "1.3.7",
86 | "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz",
87 | "integrity": "sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA==",
88 | "dependencies": {
89 | "mime-types": "~2.1.24",
90 | "negotiator": "0.6.2"
91 | },
92 | "engines": {
93 | "node": ">= 0.6"
94 | }
95 | },
96 | "node_modules/array-flatten": {
97 | "version": "1.1.1",
98 | "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz",
99 | "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI="
100 | },
101 | "node_modules/body-parser": {
102 | "version": "1.19.0",
103 | "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.0.tgz",
104 | "integrity": "sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw==",
105 | "dependencies": {
106 | "bytes": "3.1.0",
107 | "content-type": "~1.0.4",
108 | "debug": "2.6.9",
109 | "depd": "~1.1.2",
110 | "http-errors": "1.7.2",
111 | "iconv-lite": "0.4.24",
112 | "on-finished": "~2.3.0",
113 | "qs": "6.7.0",
114 | "raw-body": "2.4.0",
115 | "type-is": "~1.6.17"
116 | },
117 | "engines": {
118 | "node": ">= 0.8"
119 | }
120 | },
121 | "node_modules/bytes": {
122 | "version": "3.1.0",
123 | "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz",
124 | "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==",
125 | "engines": {
126 | "node": ">= 0.8"
127 | }
128 | },
129 | "node_modules/camel-case": {
130 | "version": "4.1.2",
131 | "resolved": "https://registry.npmjs.org/camel-case/-/camel-case-4.1.2.tgz",
132 | "integrity": "sha512-gxGWBrTT1JuMx6R+o5PTXMmUnhnVzLQ9SNutD4YqKtI6ap897t3tKECYla6gCWEkplXnlNybEkZg9GEGxKFCgw==",
133 | "dependencies": {
134 | "pascal-case": "^3.1.2",
135 | "tslib": "^2.0.3"
136 | }
137 | },
138 | "node_modules/content-disposition": {
139 | "version": "0.5.3",
140 | "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.3.tgz",
141 | "integrity": "sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g==",
142 | "dependencies": {
143 | "safe-buffer": "5.1.2"
144 | },
145 | "engines": {
146 | "node": ">= 0.6"
147 | }
148 | },
149 | "node_modules/content-type": {
150 | "version": "1.0.4",
151 | "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz",
152 | "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==",
153 | "engines": {
154 | "node": ">= 0.6"
155 | }
156 | },
157 | "node_modules/cookie": {
158 | "version": "0.4.0",
159 | "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.0.tgz",
160 | "integrity": "sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg==",
161 | "engines": {
162 | "node": ">= 0.6"
163 | }
164 | },
165 | "node_modules/cookie-signature": {
166 | "version": "1.0.6",
167 | "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz",
168 | "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw="
169 | },
170 | "node_modules/dataloader": {
171 | "version": "2.0.0",
172 | "resolved": "https://registry.npmjs.org/dataloader/-/dataloader-2.0.0.tgz",
173 | "integrity": "sha512-YzhyDAwA4TaQIhM5go+vCLmU0UikghC/t9DTQYZR2M/UvZ1MdOhPezSDZcjj9uqQJOMqjLcpWtyW2iNINdlatQ=="
174 | },
175 | "node_modules/debug": {
176 | "version": "2.6.9",
177 | "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
178 | "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
179 | "dependencies": {
180 | "ms": "2.0.0"
181 | }
182 | },
183 | "node_modules/define-lazy-prop": {
184 | "version": "2.0.0",
185 | "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz",
186 | "integrity": "sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==",
187 | "engines": {
188 | "node": ">=8"
189 | }
190 | },
191 | "node_modules/depd": {
192 | "version": "1.1.2",
193 | "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz",
194 | "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=",
195 | "engines": {
196 | "node": ">= 0.6"
197 | }
198 | },
199 | "node_modules/destroy": {
200 | "version": "1.0.4",
201 | "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz",
202 | "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA="
203 | },
204 | "node_modules/ee-first": {
205 | "version": "1.1.1",
206 | "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
207 | "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0="
208 | },
209 | "node_modules/encodeurl": {
210 | "version": "1.0.2",
211 | "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz",
212 | "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=",
213 | "engines": {
214 | "node": ">= 0.8"
215 | }
216 | },
217 | "node_modules/escape-html": {
218 | "version": "1.0.3",
219 | "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz",
220 | "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg="
221 | },
222 | "node_modules/etag": {
223 | "version": "1.8.1",
224 | "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz",
225 | "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=",
226 | "engines": {
227 | "node": ">= 0.6"
228 | }
229 | },
230 | "node_modules/express": {
231 | "version": "4.17.1",
232 | "resolved": "https://registry.npmjs.org/express/-/express-4.17.1.tgz",
233 | "integrity": "sha512-mHJ9O79RqluphRrcw2X/GTh3k9tVv8YcoyY4Kkh4WDMUYKRZUq0h1o0w2rrrxBqM7VoeUVqgb27xlEMXTnYt4g==",
234 | "dependencies": {
235 | "accepts": "~1.3.7",
236 | "array-flatten": "1.1.1",
237 | "body-parser": "1.19.0",
238 | "content-disposition": "0.5.3",
239 | "content-type": "~1.0.4",
240 | "cookie": "0.4.0",
241 | "cookie-signature": "1.0.6",
242 | "debug": "2.6.9",
243 | "depd": "~1.1.2",
244 | "encodeurl": "~1.0.2",
245 | "escape-html": "~1.0.3",
246 | "etag": "~1.8.1",
247 | "finalhandler": "~1.1.2",
248 | "fresh": "0.5.2",
249 | "merge-descriptors": "1.0.1",
250 | "methods": "~1.1.2",
251 | "on-finished": "~2.3.0",
252 | "parseurl": "~1.3.3",
253 | "path-to-regexp": "0.1.7",
254 | "proxy-addr": "~2.0.5",
255 | "qs": "6.7.0",
256 | "range-parser": "~1.2.1",
257 | "safe-buffer": "5.1.2",
258 | "send": "0.17.1",
259 | "serve-static": "1.14.1",
260 | "setprototypeof": "1.1.1",
261 | "statuses": "~1.5.0",
262 | "type-is": "~1.6.18",
263 | "utils-merge": "1.0.1",
264 | "vary": "~1.1.2"
265 | },
266 | "engines": {
267 | "node": ">= 0.10.0"
268 | }
269 | },
270 | "node_modules/finalhandler": {
271 | "version": "1.1.2",
272 | "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz",
273 | "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==",
274 | "dependencies": {
275 | "debug": "2.6.9",
276 | "encodeurl": "~1.0.2",
277 | "escape-html": "~1.0.3",
278 | "on-finished": "~2.3.0",
279 | "parseurl": "~1.3.3",
280 | "statuses": "~1.5.0",
281 | "unpipe": "~1.0.0"
282 | },
283 | "engines": {
284 | "node": ">= 0.8"
285 | }
286 | },
287 | "node_modules/forwarded": {
288 | "version": "0.1.2",
289 | "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.2.tgz",
290 | "integrity": "sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ=",
291 | "engines": {
292 | "node": ">= 0.6"
293 | }
294 | },
295 | "node_modules/fresh": {
296 | "version": "0.5.2",
297 | "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz",
298 | "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=",
299 | "engines": {
300 | "node": ">= 0.6"
301 | }
302 | },
303 | "node_modules/graphql": {
304 | "version": "15.5.0",
305 | "resolved": "https://registry.npmjs.org/graphql/-/graphql-15.5.0.tgz",
306 | "integrity": "sha512-OmaM7y0kaK31NKG31q4YbD2beNYa6jBBKtMFT6gLYJljHLJr42IqJ8KX08u3Li/0ifzTU5HjmoOOrwa5BRLeDA==",
307 | "engines": {
308 | "node": ">= 10.x"
309 | }
310 | },
311 | "node_modules/graphql-middleware": {
312 | "version": "6.0.4",
313 | "resolved": "https://registry.npmjs.org/graphql-middleware/-/graphql-middleware-6.0.4.tgz",
314 | "integrity": "sha512-T49lpvrRHpUzBXUupNnBx82WAmWBoTmsWcc+XdblYClj9WnRMrtxeunQlTsbsSCSD7ZahN1MELd0xKfC2hfwUw==",
315 | "dependencies": {
316 | "@graphql-tools/delegate": "^7.0.10",
317 | "@graphql-tools/schema": "^7.1.3"
318 | }
319 | },
320 | "node_modules/http-errors": {
321 | "version": "1.7.2",
322 | "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.2.tgz",
323 | "integrity": "sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg==",
324 | "dependencies": {
325 | "depd": "~1.1.2",
326 | "inherits": "2.0.3",
327 | "setprototypeof": "1.1.1",
328 | "statuses": ">= 1.5.0 < 2",
329 | "toidentifier": "1.0.0"
330 | },
331 | "engines": {
332 | "node": ">= 0.6"
333 | }
334 | },
335 | "node_modules/iconv-lite": {
336 | "version": "0.4.24",
337 | "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
338 | "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==",
339 | "dependencies": {
340 | "safer-buffer": ">= 2.1.2 < 3"
341 | },
342 | "engines": {
343 | "node": ">=0.10.0"
344 | }
345 | },
346 | "node_modules/inherits": {
347 | "version": "2.0.3",
348 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
349 | "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4="
350 | },
351 | "node_modules/ipaddr.js": {
352 | "version": "1.9.1",
353 | "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz",
354 | "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==",
355 | "engines": {
356 | "node": ">= 0.10"
357 | }
358 | },
359 | "node_modules/is-docker": {
360 | "version": "2.1.1",
361 | "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.1.1.tgz",
362 | "integrity": "sha512-ZOoqiXfEwtGknTiuDEy8pN2CfE3TxMHprvNer1mXiqwkOT77Rw3YVrUQ52EqAOU3QAWDQ+bQdx7HJzrv7LS2Hw==",
363 | "bin": {
364 | "is-docker": "cli.js"
365 | },
366 | "engines": {
367 | "node": ">=8"
368 | }
369 | },
370 | "node_modules/is-promise": {
371 | "version": "4.0.0",
372 | "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-4.0.0.tgz",
373 | "integrity": "sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ=="
374 | },
375 | "node_modules/is-wsl": {
376 | "version": "2.2.0",
377 | "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz",
378 | "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==",
379 | "dependencies": {
380 | "is-docker": "^2.0.0"
381 | },
382 | "engines": {
383 | "node": ">=8"
384 | }
385 | },
386 | "node_modules/lower-case": {
387 | "version": "2.0.2",
388 | "resolved": "https://registry.npmjs.org/lower-case/-/lower-case-2.0.2.tgz",
389 | "integrity": "sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg==",
390 | "dependencies": {
391 | "tslib": "^2.0.3"
392 | }
393 | },
394 | "node_modules/media-typer": {
395 | "version": "0.3.0",
396 | "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz",
397 | "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=",
398 | "engines": {
399 | "node": ">= 0.6"
400 | }
401 | },
402 | "node_modules/merge-descriptors": {
403 | "version": "1.0.1",
404 | "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz",
405 | "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E="
406 | },
407 | "node_modules/methods": {
408 | "version": "1.1.2",
409 | "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz",
410 | "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=",
411 | "engines": {
412 | "node": ">= 0.6"
413 | }
414 | },
415 | "node_modules/mime": {
416 | "version": "1.6.0",
417 | "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz",
418 | "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==",
419 | "bin": {
420 | "mime": "cli.js"
421 | },
422 | "engines": {
423 | "node": ">=4"
424 | }
425 | },
426 | "node_modules/mime-db": {
427 | "version": "1.46.0",
428 | "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.46.0.tgz",
429 | "integrity": "sha512-svXaP8UQRZ5K7or+ZmfNhg2xX3yKDMUzqadsSqi4NCH/KomcH75MAMYAGVlvXn4+b/xOPhS3I2uHKRUzvjY7BQ==",
430 | "engines": {
431 | "node": ">= 0.6"
432 | }
433 | },
434 | "node_modules/mime-types": {
435 | "version": "2.1.29",
436 | "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.29.tgz",
437 | "integrity": "sha512-Y/jMt/S5sR9OaqteJtslsFZKWOIIqMACsJSiHghlCAyhf7jfVYjKBmLiX8OgpWeW+fjJ2b+Az69aPFPkUOY6xQ==",
438 | "dependencies": {
439 | "mime-db": "1.46.0"
440 | },
441 | "engines": {
442 | "node": ">= 0.6"
443 | }
444 | },
445 | "node_modules/ms": {
446 | "version": "2.0.0",
447 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
448 | "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
449 | },
450 | "node_modules/negotiator": {
451 | "version": "0.6.2",
452 | "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz",
453 | "integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw==",
454 | "engines": {
455 | "node": ">= 0.6"
456 | }
457 | },
458 | "node_modules/no-case": {
459 | "version": "3.0.4",
460 | "resolved": "https://registry.npmjs.org/no-case/-/no-case-3.0.4.tgz",
461 | "integrity": "sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg==",
462 | "dependencies": {
463 | "lower-case": "^2.0.2",
464 | "tslib": "^2.0.3"
465 | }
466 | },
467 | "node_modules/on-finished": {
468 | "version": "2.3.0",
469 | "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz",
470 | "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=",
471 | "dependencies": {
472 | "ee-first": "1.1.1"
473 | },
474 | "engines": {
475 | "node": ">= 0.8"
476 | }
477 | },
478 | "node_modules/open": {
479 | "version": "8.0.4",
480 | "resolved": "https://registry.npmjs.org/open/-/open-8.0.4.tgz",
481 | "integrity": "sha512-Txc9FOcvjrr5Kv+Zb3w89uKMKiP7wH8mLdYj1xJa+YnhhntEYhbB6cQHjS4O6P+jFwMEzEQVVcpfnu9WkKNuLQ==",
482 | "dependencies": {
483 | "define-lazy-prop": "^2.0.0",
484 | "is-docker": "^2.1.1",
485 | "is-wsl": "^2.2.0"
486 | },
487 | "engines": {
488 | "node": ">=12"
489 | }
490 | },
491 | "node_modules/parseurl": {
492 | "version": "1.3.3",
493 | "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz",
494 | "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==",
495 | "engines": {
496 | "node": ">= 0.8"
497 | }
498 | },
499 | "node_modules/pascal-case": {
500 | "version": "3.1.2",
501 | "resolved": "https://registry.npmjs.org/pascal-case/-/pascal-case-3.1.2.tgz",
502 | "integrity": "sha512-uWlGT3YSnK9x3BQJaOdcZwrnV6hPpd8jFH1/ucpiLRPh/2zCVJKS19E4GvYHvaCcACn3foXZ0cLB9Wrx1KGe5g==",
503 | "dependencies": {
504 | "no-case": "^3.0.4",
505 | "tslib": "^2.0.3"
506 | }
507 | },
508 | "node_modules/path-to-regexp": {
509 | "version": "0.1.7",
510 | "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz",
511 | "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w="
512 | },
513 | "node_modules/proxy-addr": {
514 | "version": "2.0.6",
515 | "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.6.tgz",
516 | "integrity": "sha512-dh/frvCBVmSsDYzw6n926jv974gddhkFPfiN8hPOi30Wax25QZyZEGveluCgliBnqmuM+UJmBErbAUFIoDbjOw==",
517 | "dependencies": {
518 | "forwarded": "~0.1.2",
519 | "ipaddr.js": "1.9.1"
520 | },
521 | "engines": {
522 | "node": ">= 0.10"
523 | }
524 | },
525 | "node_modules/qs": {
526 | "version": "6.7.0",
527 | "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz",
528 | "integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==",
529 | "engines": {
530 | "node": ">=0.6"
531 | }
532 | },
533 | "node_modules/range-parser": {
534 | "version": "1.2.1",
535 | "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz",
536 | "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==",
537 | "engines": {
538 | "node": ">= 0.6"
539 | }
540 | },
541 | "node_modules/raw-body": {
542 | "version": "2.4.0",
543 | "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.0.tgz",
544 | "integrity": "sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q==",
545 | "dependencies": {
546 | "bytes": "3.1.0",
547 | "http-errors": "1.7.2",
548 | "iconv-lite": "0.4.24",
549 | "unpipe": "1.0.0"
550 | },
551 | "engines": {
552 | "node": ">= 0.8"
553 | }
554 | },
555 | "node_modules/safe-buffer": {
556 | "version": "5.1.2",
557 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
558 | "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="
559 | },
560 | "node_modules/safer-buffer": {
561 | "version": "2.1.2",
562 | "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
563 | "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
564 | },
565 | "node_modules/send": {
566 | "version": "0.17.1",
567 | "resolved": "https://registry.npmjs.org/send/-/send-0.17.1.tgz",
568 | "integrity": "sha512-BsVKsiGcQMFwT8UxypobUKyv7irCNRHk1T0G680vk88yf6LBByGcZJOTJCrTP2xVN6yI+XjPJcNuE3V4fT9sAg==",
569 | "dependencies": {
570 | "debug": "2.6.9",
571 | "depd": "~1.1.2",
572 | "destroy": "~1.0.4",
573 | "encodeurl": "~1.0.2",
574 | "escape-html": "~1.0.3",
575 | "etag": "~1.8.1",
576 | "fresh": "0.5.2",
577 | "http-errors": "~1.7.2",
578 | "mime": "1.6.0",
579 | "ms": "2.1.1",
580 | "on-finished": "~2.3.0",
581 | "range-parser": "~1.2.1",
582 | "statuses": "~1.5.0"
583 | },
584 | "engines": {
585 | "node": ">= 0.8.0"
586 | }
587 | },
588 | "node_modules/send/node_modules/ms": {
589 | "version": "2.1.1",
590 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz",
591 | "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg=="
592 | },
593 | "node_modules/serve-static": {
594 | "version": "1.14.1",
595 | "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.14.1.tgz",
596 | "integrity": "sha512-JMrvUwE54emCYWlTI+hGrGv5I8dEwmco/00EvkzIIsR7MqrHonbD9pO2MOfFnpFntl7ecpZs+3mW+XbQZu9QCg==",
597 | "dependencies": {
598 | "encodeurl": "~1.0.2",
599 | "escape-html": "~1.0.3",
600 | "parseurl": "~1.3.3",
601 | "send": "0.17.1"
602 | },
603 | "engines": {
604 | "node": ">= 0.8.0"
605 | }
606 | },
607 | "node_modules/setprototypeof": {
608 | "version": "1.1.1",
609 | "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz",
610 | "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw=="
611 | },
612 | "node_modules/statuses": {
613 | "version": "1.5.0",
614 | "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz",
615 | "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=",
616 | "engines": {
617 | "node": ">= 0.6"
618 | }
619 | },
620 | "node_modules/toidentifier": {
621 | "version": "1.0.0",
622 | "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz",
623 | "integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==",
624 | "engines": {
625 | "node": ">=0.6"
626 | }
627 | },
628 | "node_modules/tslib": {
629 | "version": "2.1.0",
630 | "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.1.0.tgz",
631 | "integrity": "sha512-hcVC3wYEziELGGmEEXue7D75zbwIIVUMWAVbHItGPx0ziyXxrOMQx4rQEVEV45Ut/1IotuEvwqPopzIOkDMf0A=="
632 | },
633 | "node_modules/type-is": {
634 | "version": "1.6.18",
635 | "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz",
636 | "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==",
637 | "dependencies": {
638 | "media-typer": "0.3.0",
639 | "mime-types": "~2.1.24"
640 | },
641 | "engines": {
642 | "node": ">= 0.6"
643 | }
644 | },
645 | "node_modules/unpipe": {
646 | "version": "1.0.0",
647 | "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz",
648 | "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=",
649 | "engines": {
650 | "node": ">= 0.8"
651 | }
652 | },
653 | "node_modules/utils-merge": {
654 | "version": "1.0.1",
655 | "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz",
656 | "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=",
657 | "engines": {
658 | "node": ">= 0.4.0"
659 | }
660 | },
661 | "node_modules/vary": {
662 | "version": "1.1.2",
663 | "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz",
664 | "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=",
665 | "engines": {
666 | "node": ">= 0.8"
667 | }
668 | }
669 | },
670 | "dependencies": {
671 | "@ardatan/aggregate-error": {
672 | "version": "0.0.6",
673 | "resolved": "https://registry.npmjs.org/@ardatan/aggregate-error/-/aggregate-error-0.0.6.tgz",
674 | "integrity": "sha512-vyrkEHG1jrukmzTPtyWB4NLPauUw5bQeg4uhn8f+1SSynmrOcyvlb1GKQjjgoBzElLdfXCRYX8UnBlhklOHYRQ==",
675 | "requires": {
676 | "tslib": "~2.0.1"
677 | },
678 | "dependencies": {
679 | "tslib": {
680 | "version": "2.0.3",
681 | "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.0.3.tgz",
682 | "integrity": "sha512-uZtkfKblCEQtZKBF6EBXVZeQNl82yqtDQdv+eck8u7tdPxjLu2/lp5/uPW+um2tpuxINHWy3GhiccY7QgEaVHQ=="
683 | }
684 | }
685 | },
686 | "@graphql-tools/batch-execute": {
687 | "version": "7.0.0",
688 | "resolved": "https://registry.npmjs.org/@graphql-tools/batch-execute/-/batch-execute-7.0.0.tgz",
689 | "integrity": "sha512-+ywPfK6N2Ddna6oOa5Qb1Mv7EA8LOwRNOAPP9dL37FEhksJM9pYqPSceUcqMqg7S9b0+Cgr78s408rgvurV3/Q==",
690 | "requires": {
691 | "@graphql-tools/utils": "^7.0.0",
692 | "dataloader": "2.0.0",
693 | "is-promise": "4.0.0",
694 | "tslib": "~2.0.1"
695 | },
696 | "dependencies": {
697 | "tslib": {
698 | "version": "2.0.3",
699 | "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.0.3.tgz",
700 | "integrity": "sha512-uZtkfKblCEQtZKBF6EBXVZeQNl82yqtDQdv+eck8u7tdPxjLu2/lp5/uPW+um2tpuxINHWy3GhiccY7QgEaVHQ=="
701 | }
702 | }
703 | },
704 | "@graphql-tools/delegate": {
705 | "version": "7.0.10",
706 | "resolved": "https://registry.npmjs.org/@graphql-tools/delegate/-/delegate-7.0.10.tgz",
707 | "integrity": "sha512-6Di9ia5ohoDvrHuhj2cak1nJGhIefJmUsd3WKZcJ2nu2yZAFawWMxGvQImqv3N7iyaWKiVhrrK8Roi/JrYhdKg==",
708 | "requires": {
709 | "@ardatan/aggregate-error": "0.0.6",
710 | "@graphql-tools/batch-execute": "^7.0.0",
711 | "@graphql-tools/schema": "^7.0.0",
712 | "@graphql-tools/utils": "^7.1.6",
713 | "dataloader": "2.0.0",
714 | "is-promise": "4.0.0",
715 | "tslib": "~2.1.0"
716 | }
717 | },
718 | "@graphql-tools/schema": {
719 | "version": "7.1.3",
720 | "resolved": "https://registry.npmjs.org/@graphql-tools/schema/-/schema-7.1.3.tgz",
721 | "integrity": "sha512-ZY76hmcJlF1iyg3Im0sQ3ASRkiShjgv102vLTVcH22lEGJeCaCyyS/GF1eUHom418S60bS8Th6+autRUxfBiBg==",
722 | "requires": {
723 | "@graphql-tools/utils": "^7.1.2",
724 | "tslib": "~2.1.0"
725 | }
726 | },
727 | "@graphql-tools/utils": {
728 | "version": "7.6.0",
729 | "resolved": "https://registry.npmjs.org/@graphql-tools/utils/-/utils-7.6.0.tgz",
730 | "integrity": "sha512-YCZDDdhfb4Yhie0IH031eGdvQG8C73apDuNg6lqBNbauNw45OG/b8wi3+vuMiDnJTJN32GQUb1Gt9gxDKoRDKw==",
731 | "requires": {
732 | "@ardatan/aggregate-error": "0.0.6",
733 | "camel-case": "4.1.2",
734 | "tslib": "~2.1.0"
735 | }
736 | },
737 | "accepts": {
738 | "version": "1.3.7",
739 | "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz",
740 | "integrity": "sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA==",
741 | "requires": {
742 | "mime-types": "~2.1.24",
743 | "negotiator": "0.6.2"
744 | }
745 | },
746 | "array-flatten": {
747 | "version": "1.1.1",
748 | "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz",
749 | "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI="
750 | },
751 | "body-parser": {
752 | "version": "1.19.0",
753 | "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.0.tgz",
754 | "integrity": "sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw==",
755 | "requires": {
756 | "bytes": "3.1.0",
757 | "content-type": "~1.0.4",
758 | "debug": "2.6.9",
759 | "depd": "~1.1.2",
760 | "http-errors": "1.7.2",
761 | "iconv-lite": "0.4.24",
762 | "on-finished": "~2.3.0",
763 | "qs": "6.7.0",
764 | "raw-body": "2.4.0",
765 | "type-is": "~1.6.17"
766 | }
767 | },
768 | "bytes": {
769 | "version": "3.1.0",
770 | "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz",
771 | "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg=="
772 | },
773 | "camel-case": {
774 | "version": "4.1.2",
775 | "resolved": "https://registry.npmjs.org/camel-case/-/camel-case-4.1.2.tgz",
776 | "integrity": "sha512-gxGWBrTT1JuMx6R+o5PTXMmUnhnVzLQ9SNutD4YqKtI6ap897t3tKECYla6gCWEkplXnlNybEkZg9GEGxKFCgw==",
777 | "requires": {
778 | "pascal-case": "^3.1.2",
779 | "tslib": "^2.0.3"
780 | }
781 | },
782 | "content-disposition": {
783 | "version": "0.5.3",
784 | "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.3.tgz",
785 | "integrity": "sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g==",
786 | "requires": {
787 | "safe-buffer": "5.1.2"
788 | }
789 | },
790 | "content-type": {
791 | "version": "1.0.4",
792 | "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz",
793 | "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA=="
794 | },
795 | "cookie": {
796 | "version": "0.4.0",
797 | "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.0.tgz",
798 | "integrity": "sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg=="
799 | },
800 | "cookie-signature": {
801 | "version": "1.0.6",
802 | "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz",
803 | "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw="
804 | },
805 | "dataloader": {
806 | "version": "2.0.0",
807 | "resolved": "https://registry.npmjs.org/dataloader/-/dataloader-2.0.0.tgz",
808 | "integrity": "sha512-YzhyDAwA4TaQIhM5go+vCLmU0UikghC/t9DTQYZR2M/UvZ1MdOhPezSDZcjj9uqQJOMqjLcpWtyW2iNINdlatQ=="
809 | },
810 | "debug": {
811 | "version": "2.6.9",
812 | "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
813 | "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
814 | "requires": {
815 | "ms": "2.0.0"
816 | }
817 | },
818 | "define-lazy-prop": {
819 | "version": "2.0.0",
820 | "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz",
821 | "integrity": "sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og=="
822 | },
823 | "depd": {
824 | "version": "1.1.2",
825 | "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz",
826 | "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak="
827 | },
828 | "destroy": {
829 | "version": "1.0.4",
830 | "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz",
831 | "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA="
832 | },
833 | "ee-first": {
834 | "version": "1.1.1",
835 | "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
836 | "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0="
837 | },
838 | "encodeurl": {
839 | "version": "1.0.2",
840 | "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz",
841 | "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k="
842 | },
843 | "escape-html": {
844 | "version": "1.0.3",
845 | "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz",
846 | "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg="
847 | },
848 | "etag": {
849 | "version": "1.8.1",
850 | "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz",
851 | "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc="
852 | },
853 | "express": {
854 | "version": "4.17.1",
855 | "resolved": "https://registry.npmjs.org/express/-/express-4.17.1.tgz",
856 | "integrity": "sha512-mHJ9O79RqluphRrcw2X/GTh3k9tVv8YcoyY4Kkh4WDMUYKRZUq0h1o0w2rrrxBqM7VoeUVqgb27xlEMXTnYt4g==",
857 | "requires": {
858 | "accepts": "~1.3.7",
859 | "array-flatten": "1.1.1",
860 | "body-parser": "1.19.0",
861 | "content-disposition": "0.5.3",
862 | "content-type": "~1.0.4",
863 | "cookie": "0.4.0",
864 | "cookie-signature": "1.0.6",
865 | "debug": "2.6.9",
866 | "depd": "~1.1.2",
867 | "encodeurl": "~1.0.2",
868 | "escape-html": "~1.0.3",
869 | "etag": "~1.8.1",
870 | "finalhandler": "~1.1.2",
871 | "fresh": "0.5.2",
872 | "merge-descriptors": "1.0.1",
873 | "methods": "~1.1.2",
874 | "on-finished": "~2.3.0",
875 | "parseurl": "~1.3.3",
876 | "path-to-regexp": "0.1.7",
877 | "proxy-addr": "~2.0.5",
878 | "qs": "6.7.0",
879 | "range-parser": "~1.2.1",
880 | "safe-buffer": "5.1.2",
881 | "send": "0.17.1",
882 | "serve-static": "1.14.1",
883 | "setprototypeof": "1.1.1",
884 | "statuses": "~1.5.0",
885 | "type-is": "~1.6.18",
886 | "utils-merge": "1.0.1",
887 | "vary": "~1.1.2"
888 | }
889 | },
890 | "finalhandler": {
891 | "version": "1.1.2",
892 | "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz",
893 | "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==",
894 | "requires": {
895 | "debug": "2.6.9",
896 | "encodeurl": "~1.0.2",
897 | "escape-html": "~1.0.3",
898 | "on-finished": "~2.3.0",
899 | "parseurl": "~1.3.3",
900 | "statuses": "~1.5.0",
901 | "unpipe": "~1.0.0"
902 | }
903 | },
904 | "forwarded": {
905 | "version": "0.1.2",
906 | "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.2.tgz",
907 | "integrity": "sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ="
908 | },
909 | "fresh": {
910 | "version": "0.5.2",
911 | "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz",
912 | "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac="
913 | },
914 | "graphql": {
915 | "version": "15.5.0",
916 | "resolved": "https://registry.npmjs.org/graphql/-/graphql-15.5.0.tgz",
917 | "integrity": "sha512-OmaM7y0kaK31NKG31q4YbD2beNYa6jBBKtMFT6gLYJljHLJr42IqJ8KX08u3Li/0ifzTU5HjmoOOrwa5BRLeDA=="
918 | },
919 | "graphql-middleware": {
920 | "version": "6.0.4",
921 | "resolved": "https://registry.npmjs.org/graphql-middleware/-/graphql-middleware-6.0.4.tgz",
922 | "integrity": "sha512-T49lpvrRHpUzBXUupNnBx82WAmWBoTmsWcc+XdblYClj9WnRMrtxeunQlTsbsSCSD7ZahN1MELd0xKfC2hfwUw==",
923 | "requires": {
924 | "@graphql-tools/delegate": "^7.0.10",
925 | "@graphql-tools/schema": "^7.1.3"
926 | }
927 | },
928 | "http-errors": {
929 | "version": "1.7.2",
930 | "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.2.tgz",
931 | "integrity": "sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg==",
932 | "requires": {
933 | "depd": "~1.1.2",
934 | "inherits": "2.0.3",
935 | "setprototypeof": "1.1.1",
936 | "statuses": ">= 1.5.0 < 2",
937 | "toidentifier": "1.0.0"
938 | }
939 | },
940 | "iconv-lite": {
941 | "version": "0.4.24",
942 | "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
943 | "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==",
944 | "requires": {
945 | "safer-buffer": ">= 2.1.2 < 3"
946 | }
947 | },
948 | "inherits": {
949 | "version": "2.0.3",
950 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
951 | "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4="
952 | },
953 | "ipaddr.js": {
954 | "version": "1.9.1",
955 | "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz",
956 | "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g=="
957 | },
958 | "is-docker": {
959 | "version": "2.1.1",
960 | "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.1.1.tgz",
961 | "integrity": "sha512-ZOoqiXfEwtGknTiuDEy8pN2CfE3TxMHprvNer1mXiqwkOT77Rw3YVrUQ52EqAOU3QAWDQ+bQdx7HJzrv7LS2Hw=="
962 | },
963 | "is-promise": {
964 | "version": "4.0.0",
965 | "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-4.0.0.tgz",
966 | "integrity": "sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ=="
967 | },
968 | "is-wsl": {
969 | "version": "2.2.0",
970 | "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz",
971 | "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==",
972 | "requires": {
973 | "is-docker": "^2.0.0"
974 | }
975 | },
976 | "lower-case": {
977 | "version": "2.0.2",
978 | "resolved": "https://registry.npmjs.org/lower-case/-/lower-case-2.0.2.tgz",
979 | "integrity": "sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg==",
980 | "requires": {
981 | "tslib": "^2.0.3"
982 | }
983 | },
984 | "media-typer": {
985 | "version": "0.3.0",
986 | "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz",
987 | "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g="
988 | },
989 | "merge-descriptors": {
990 | "version": "1.0.1",
991 | "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz",
992 | "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E="
993 | },
994 | "methods": {
995 | "version": "1.1.2",
996 | "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz",
997 | "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4="
998 | },
999 | "mime": {
1000 | "version": "1.6.0",
1001 | "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz",
1002 | "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg=="
1003 | },
1004 | "mime-db": {
1005 | "version": "1.46.0",
1006 | "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.46.0.tgz",
1007 | "integrity": "sha512-svXaP8UQRZ5K7or+ZmfNhg2xX3yKDMUzqadsSqi4NCH/KomcH75MAMYAGVlvXn4+b/xOPhS3I2uHKRUzvjY7BQ=="
1008 | },
1009 | "mime-types": {
1010 | "version": "2.1.29",
1011 | "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.29.tgz",
1012 | "integrity": "sha512-Y/jMt/S5sR9OaqteJtslsFZKWOIIqMACsJSiHghlCAyhf7jfVYjKBmLiX8OgpWeW+fjJ2b+Az69aPFPkUOY6xQ==",
1013 | "requires": {
1014 | "mime-db": "1.46.0"
1015 | }
1016 | },
1017 | "ms": {
1018 | "version": "2.0.0",
1019 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
1020 | "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
1021 | },
1022 | "negotiator": {
1023 | "version": "0.6.2",
1024 | "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz",
1025 | "integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw=="
1026 | },
1027 | "no-case": {
1028 | "version": "3.0.4",
1029 | "resolved": "https://registry.npmjs.org/no-case/-/no-case-3.0.4.tgz",
1030 | "integrity": "sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg==",
1031 | "requires": {
1032 | "lower-case": "^2.0.2",
1033 | "tslib": "^2.0.3"
1034 | }
1035 | },
1036 | "on-finished": {
1037 | "version": "2.3.0",
1038 | "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz",
1039 | "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=",
1040 | "requires": {
1041 | "ee-first": "1.1.1"
1042 | }
1043 | },
1044 | "open": {
1045 | "version": "8.0.4",
1046 | "resolved": "https://registry.npmjs.org/open/-/open-8.0.4.tgz",
1047 | "integrity": "sha512-Txc9FOcvjrr5Kv+Zb3w89uKMKiP7wH8mLdYj1xJa+YnhhntEYhbB6cQHjS4O6P+jFwMEzEQVVcpfnu9WkKNuLQ==",
1048 | "requires": {
1049 | "define-lazy-prop": "^2.0.0",
1050 | "is-docker": "^2.1.1",
1051 | "is-wsl": "^2.2.0"
1052 | }
1053 | },
1054 | "parseurl": {
1055 | "version": "1.3.3",
1056 | "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz",
1057 | "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ=="
1058 | },
1059 | "pascal-case": {
1060 | "version": "3.1.2",
1061 | "resolved": "https://registry.npmjs.org/pascal-case/-/pascal-case-3.1.2.tgz",
1062 | "integrity": "sha512-uWlGT3YSnK9x3BQJaOdcZwrnV6hPpd8jFH1/ucpiLRPh/2zCVJKS19E4GvYHvaCcACn3foXZ0cLB9Wrx1KGe5g==",
1063 | "requires": {
1064 | "no-case": "^3.0.4",
1065 | "tslib": "^2.0.3"
1066 | }
1067 | },
1068 | "path-to-regexp": {
1069 | "version": "0.1.7",
1070 | "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz",
1071 | "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w="
1072 | },
1073 | "proxy-addr": {
1074 | "version": "2.0.6",
1075 | "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.6.tgz",
1076 | "integrity": "sha512-dh/frvCBVmSsDYzw6n926jv974gddhkFPfiN8hPOi30Wax25QZyZEGveluCgliBnqmuM+UJmBErbAUFIoDbjOw==",
1077 | "requires": {
1078 | "forwarded": "~0.1.2",
1079 | "ipaddr.js": "1.9.1"
1080 | }
1081 | },
1082 | "qs": {
1083 | "version": "6.7.0",
1084 | "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz",
1085 | "integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ=="
1086 | },
1087 | "range-parser": {
1088 | "version": "1.2.1",
1089 | "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz",
1090 | "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg=="
1091 | },
1092 | "raw-body": {
1093 | "version": "2.4.0",
1094 | "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.0.tgz",
1095 | "integrity": "sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q==",
1096 | "requires": {
1097 | "bytes": "3.1.0",
1098 | "http-errors": "1.7.2",
1099 | "iconv-lite": "0.4.24",
1100 | "unpipe": "1.0.0"
1101 | }
1102 | },
1103 | "safe-buffer": {
1104 | "version": "5.1.2",
1105 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
1106 | "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="
1107 | },
1108 | "safer-buffer": {
1109 | "version": "2.1.2",
1110 | "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
1111 | "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
1112 | },
1113 | "send": {
1114 | "version": "0.17.1",
1115 | "resolved": "https://registry.npmjs.org/send/-/send-0.17.1.tgz",
1116 | "integrity": "sha512-BsVKsiGcQMFwT8UxypobUKyv7irCNRHk1T0G680vk88yf6LBByGcZJOTJCrTP2xVN6yI+XjPJcNuE3V4fT9sAg==",
1117 | "requires": {
1118 | "debug": "2.6.9",
1119 | "depd": "~1.1.2",
1120 | "destroy": "~1.0.4",
1121 | "encodeurl": "~1.0.2",
1122 | "escape-html": "~1.0.3",
1123 | "etag": "~1.8.1",
1124 | "fresh": "0.5.2",
1125 | "http-errors": "~1.7.2",
1126 | "mime": "1.6.0",
1127 | "ms": "2.1.1",
1128 | "on-finished": "~2.3.0",
1129 | "range-parser": "~1.2.1",
1130 | "statuses": "~1.5.0"
1131 | },
1132 | "dependencies": {
1133 | "ms": {
1134 | "version": "2.1.1",
1135 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz",
1136 | "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg=="
1137 | }
1138 | }
1139 | },
1140 | "serve-static": {
1141 | "version": "1.14.1",
1142 | "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.14.1.tgz",
1143 | "integrity": "sha512-JMrvUwE54emCYWlTI+hGrGv5I8dEwmco/00EvkzIIsR7MqrHonbD9pO2MOfFnpFntl7ecpZs+3mW+XbQZu9QCg==",
1144 | "requires": {
1145 | "encodeurl": "~1.0.2",
1146 | "escape-html": "~1.0.3",
1147 | "parseurl": "~1.3.3",
1148 | "send": "0.17.1"
1149 | }
1150 | },
1151 | "setprototypeof": {
1152 | "version": "1.1.1",
1153 | "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz",
1154 | "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw=="
1155 | },
1156 | "statuses": {
1157 | "version": "1.5.0",
1158 | "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz",
1159 | "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow="
1160 | },
1161 | "toidentifier": {
1162 | "version": "1.0.0",
1163 | "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz",
1164 | "integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw=="
1165 | },
1166 | "tslib": {
1167 | "version": "2.1.0",
1168 | "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.1.0.tgz",
1169 | "integrity": "sha512-hcVC3wYEziELGGmEEXue7D75zbwIIVUMWAVbHItGPx0ziyXxrOMQx4rQEVEV45Ut/1IotuEvwqPopzIOkDMf0A=="
1170 | },
1171 | "type-is": {
1172 | "version": "1.6.18",
1173 | "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz",
1174 | "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==",
1175 | "requires": {
1176 | "media-typer": "0.3.0",
1177 | "mime-types": "~2.1.24"
1178 | }
1179 | },
1180 | "unpipe": {
1181 | "version": "1.0.0",
1182 | "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz",
1183 | "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw="
1184 | },
1185 | "utils-merge": {
1186 | "version": "1.0.1",
1187 | "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz",
1188 | "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM="
1189 | },
1190 | "vary": {
1191 | "version": "1.1.2",
1192 | "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz",
1193 | "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw="
1194 | }
1195 | }
1196 | }
1197 |
--------------------------------------------------------------------------------
/nuqleus_npm_package/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "nuqleus",
3 | "version": "0.1.0",
4 | "description": "",
5 | "main": "nuqleus.js",
6 | "scripts": {
7 | "test": "echo \"Error: no test specified\" && exit 1"
8 | },
9 | "keywords": [],
10 | "author": "",
11 | "license": "ISC",
12 | "dependencies": {
13 | "@graphql-tools/schema": "^7.1.3",
14 | "express": "^4.17.1",
15 | "graphql": "^15.5.0",
16 | "graphql-middleware": "^6.0.4",
17 | "open": "^8.0.4"
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/nuqleus_npm_package/public/src/assets/images/nuQLeus_favicon_32x32.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oslabs-beta/nuQLeus/4c7da39122e60631c9516663021874d39fefa255/nuqleus_npm_package/public/src/assets/images/nuQLeus_favicon_32x32.png
--------------------------------------------------------------------------------
/nuqleus_npm_package/public/src/assets/images/nuQLeus_logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oslabs-beta/nuQLeus/4c7da39122e60631c9516663021874d39fefa255/nuqleus_npm_package/public/src/assets/images/nuQLeus_logo.png
--------------------------------------------------------------------------------
/nuqleus_npm_package/public/src/assets/images/nuQLeus_logo_black_background.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oslabs-beta/nuQLeus/4c7da39122e60631c9516663021874d39fefa255/nuqleus_npm_package/public/src/assets/images/nuQLeus_logo_black_background.png
--------------------------------------------------------------------------------
/nuqleus_npm_package/public/src/assets/images/nuQLeus_logo_reversed.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oslabs-beta/nuQLeus/4c7da39122e60631c9516663021874d39fefa255/nuqleus_npm_package/public/src/assets/images/nuQLeus_logo_reversed.png
--------------------------------------------------------------------------------
/nuqleus_npm_package/server.js:
--------------------------------------------------------------------------------
1 | /*
2 | Creates an Express server that serves static files for the nuQLeus GUI to: localhost:3030/nuqleus
3 | when the nuqleus wrapper methods are invoked on an enduser's server.
4 | */
5 |
6 | const path = require('path');
7 | const express = require('express');
8 | const app = express();
9 | const PORT = 3030;
10 |
11 | app.use(express.json());
12 | app.use(express.urlencoded({ extended: true }));
13 |
14 | app.use(express.static('.'));
15 |
16 | app.get('/nuqleus', (req, res) => {
17 | res.status(200).sendFile(path.join(__dirname, './index.html'));
18 | });
19 |
20 | app.listen(PORT, () => {
21 | console.log(`Listening on port ${PORT}`);
22 | });
23 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "nuqleus",
3 | "version": "0.1.0",
4 | "description": "Boost GraphQL endpoint testing capabilities with resolver-level performance metrics",
5 | "main": "main.js",
6 | "scripts": {
7 | "build": "webpack --config webpack.config.js",
8 | "dev": "webpack serve --open --hot"
9 | },
10 | "repository": {
11 | "type": "git",
12 | "url": "git+https://github.com/oslabs-beta/NuQLeus"
13 | },
14 | "author": "",
15 | "license": "MIT",
16 | "bugs": {
17 | "url": "https://github.com/oslabs-beta/NuQLeus/issues"
18 | },
19 | "homepage": "https://github.com/oslabs-beta/NuQLeus#readme",
20 | "jest": {
21 | "moduleFileExtensions": ["js", "jsx"],
22 | "moduleDirectories": ["node_modules", "bower_components", "shared"],
23 | "moduleNameMapper": {
24 | "\\.(css|less)$": "/__mocks__/styleMock.js"
25 | },
26 | "transformIgnorePatterns": [
27 | "/node_modules/codemirror/lib.+\\.css$"
28 | ],
29 | "^react(.*)$": "/vendor/react-master$1",
30 | "^config$": "/configs/app-config.js"
31 | },
32 | "dependencies": {
33 | "@tsconfig/recommended": "^1.0.1",
34 | "@wojtekmaj/enzyme-adapter-react-17": "^0.6.1",
35 | "codemirror": "^5.59.4",
36 | "codemirror-graphql": "^1.0.0",
37 | "graphql": "^15.5.0",
38 | "react": "^16.14.0",
39 | "react-codemirror2": "^7.2.1",
40 | "react-dom": "^16.14.0",
41 | "react-router": "^5.2.0",
42 | "react-router-dom": "^5.2.0",
43 | "victory": "^35.4.11"
44 | },
45 | "devDependencies": {
46 | "@babel/cli": "^7.1.0",
47 | "@babel/core": "^7.1.0",
48 | "@babel/plugin-proposal-class-properties": "^7.13.0",
49 | "@babel/plugin-proposal-decorators": "^7.13.5",
50 | "@babel/plugin-transform-runtime": "^7.12.15",
51 | "@babel/preset-env": "^7.1.0",
52 | "@babel/preset-react": "^7.0.0",
53 | "@testing-library/jest-dom": "^5.11.9",
54 | "@testing-library/react": "^11.2.5",
55 | "@types/jest": "^26.0.23",
56 | "@types/react": "^17.0.2",
57 | "@types/react-dom": "^17.0.1",
58 | "babel-jest": "^26.6.3",
59 | "babel-loader": "^8.0.2",
60 | "css-loader": "^1.0.0",
61 | "enzyme": "^3.11.0",
62 | "jest": "^26.6.3",
63 | "style-loader": "^0.23.0",
64 | "ts-loader": "^8.0.17",
65 | "typescript": "^4.2.2",
66 | "webpack": "^4.46.0",
67 | "webpack-cli": "^4.5.0",
68 | "webpack-dev-server": "^3.11.2"
69 | }
70 | }
71 |
--------------------------------------------------------------------------------
/src/assets/gifs/nuqleus_showcase.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oslabs-beta/nuQLeus/4c7da39122e60631c9516663021874d39fefa255/src/assets/gifs/nuqleus_showcase.gif
--------------------------------------------------------------------------------
/src/assets/images/nuQLeus_favicon_32x32.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oslabs-beta/nuQLeus/4c7da39122e60631c9516663021874d39fefa255/src/assets/images/nuQLeus_favicon_32x32.png
--------------------------------------------------------------------------------
/src/assets/images/nuQLeus_logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oslabs-beta/nuQLeus/4c7da39122e60631c9516663021874d39fefa255/src/assets/images/nuQLeus_logo.png
--------------------------------------------------------------------------------
/src/assets/images/nuQLeus_logo_black_background.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oslabs-beta/nuQLeus/4c7da39122e60631c9516663021874d39fefa255/src/assets/images/nuQLeus_logo_black_background.png
--------------------------------------------------------------------------------
/src/assets/images/nuQLeus_logo_reversed.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oslabs-beta/nuQLeus/4c7da39122e60631c9516663021874d39fefa255/src/assets/images/nuQLeus_logo_reversed.png
--------------------------------------------------------------------------------
/src/client/App.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { GraphContextProvider } from './contexts/GraphContext';
3 | import MainContainer from './containers/MainContainer';
4 | import NavBar from './components/NavBar';
5 | import "./stylesheets/styles.css";
6 |
7 | const App = () => (
8 |
9 |
10 |
11 |
12 |
13 |
14 | );
15 |
16 | export default App;
17 |
--------------------------------------------------------------------------------
/src/client/components/EmptyTracingData.jsx:
--------------------------------------------------------------------------------
1 | import React, { useContext } from 'react';
2 | import { GraphContext } from '../contexts/GraphContext';
3 |
4 | const EmptyTracingData = () => {
5 | const [info, setInfo] = useContext(GraphContext);
6 |
7 | const message = info.extensions === '' ? '' : 'No tracing data available';
8 | return (
9 |
12 | );
13 | };
14 |
15 | export default EmptyTracingData;
16 |
--------------------------------------------------------------------------------
/src/client/components/NavBar.jsx:
--------------------------------------------------------------------------------
1 | import * as React from "react";
2 |
3 | const NavBar = () => {
4 | return (
5 |
6 |
7 |
8 | );
9 | };
10 |
11 | export default NavBar;
12 |
--------------------------------------------------------------------------------
/src/client/components/OutputDisplay.jsx:
--------------------------------------------------------------------------------
1 | import React, { useContext } from 'react';
2 | import { Controlled as CodeMirror } from 'react-codemirror2';
3 | import { GraphContext } from '../contexts/GraphContext';
4 |
5 | require('codemirror/mode/xml/xml');
6 | require('codemirror/mode/javascript/javascript');
7 | require('codemirror-graphql/mode');
8 | require('codemirror/mode/jsx/jsx');
9 | require('codemirror-graphql/hint');
10 | require('codemirror-graphql/lint');
11 | require('codemirror/lib/codemirror.css');
12 | require('../stylesheets/editor-theme.css');
13 | require('codemirror/addon/edit/closebrackets');
14 |
15 | const OutputDisplay = () => {
16 | const [info, setInfo] = useContext(GraphContext);
17 |
18 | const DEFAULT_JSX_OPTIONS = {
19 | theme: 'custom-0',
20 | autoCloseBrackets: true,
21 | cursorScrollMargin: 48,
22 | mode: 'javascript',
23 | lineNumbers: true,
24 | indentUnit: 2,
25 | tabSize: 2,
26 | styleActiveLine: true,
27 | viewportMargin: 99,
28 | };
29 |
30 | return (
31 | <>
32 | {
37 | value = info.response;
38 | }}
39 | onChange={(editor, metadata, value) => {
40 | value = info.response;
41 | }}
42 | />
43 | >
44 | );
45 | };
46 |
47 | export default OutputDisplay;
48 |
--------------------------------------------------------------------------------
/src/client/components/QueryField.jsx:
--------------------------------------------------------------------------------
1 | import * as React from 'react';
2 | import { useContext } from 'react';
3 | import { Controlled as CodeMirror } from 'react-codemirror2';
4 | import { GraphContext } from '../contexts/GraphContext';
5 |
6 | require('codemirror/mode/xml/xml');
7 | require('codemirror/mode/javascript/javascript');
8 | require('codemirror-graphql/mode');
9 | require('codemirror/mode/jsx/jsx');
10 | require('codemirror-graphql/hint');
11 | require('codemirror-graphql/lint');
12 | require('codemirror/lib/codemirror.css');
13 | require('../stylesheets/editor-theme.css');
14 | require('codemirror/addon/edit/closebrackets');
15 |
16 | const QueryEditor = () => {
17 | const [info, setInfo] = useContext(GraphContext);
18 |
19 | const DEFAULT_JSX_OPTIONS = {
20 | theme: 'custom-0',
21 | autoCloseBrackets: true,
22 | cursorScrollMargin: 48,
23 | mode: 'graphql',
24 | lineNumbers: true,
25 | indentUnit: 2,
26 | tabSize: 2,
27 | styleActiveLine: true,
28 | viewportMargin: 99,
29 | placeholder: 'Enter query or mutation'
30 | };
31 |
32 | const onChange = (editor, data, value) => {
33 | setInfo(() => ({
34 | ...info,
35 | body: value,
36 | }));
37 | };
38 |
39 | return (
40 | <>
41 | Body
42 | {
47 | // final value, no need to setState here
48 | }}
49 | />
50 | >
51 | );
52 | };
53 |
54 | export default QueryEditor;
55 |
--------------------------------------------------------------------------------
/src/client/components/ServerField.jsx:
--------------------------------------------------------------------------------
1 | import React, { useContext } from 'react';
2 | import { GraphContext } from '../contexts/GraphContext';
3 |
4 | const ServerField = () => {
5 | // Pull state into component from ApolloContext using 'useContext' hook
6 | const [info, setInfo] = useContext(GraphContext);
7 |
8 | // Invokes query to the GraphQL server/API
9 | function queryTime(extensions) {
10 | // Grab variables from nuQLeusTracing field:
11 | const { startTime, endTime, duration } = extensions.nuQLeusTracing;
12 | return { startTime, endTime, duration };
13 | };
14 |
15 | // Resolvers argument should be an array of resolver objects
16 | function resolverTime(resolvers) {
17 | const averageResolverResponse = [];
18 | const cache = {};
19 |
20 | for (let i = 0; i < resolvers.length; i++) {
21 | const { parentType } = resolvers[i];
22 | const { fieldName } = resolvers[i];
23 | const key = `${parentType}-${fieldName}`;
24 | if (!cache[key]) cache[key] = [];
25 | cache[key].push(resolvers[i].duration);
26 | };
27 |
28 | for (const key in cache) {
29 | const keys = key.split('-');
30 | const obj = {
31 | parentType: keys[0],
32 | fieldName: keys[1],
33 | durations: cache[key],
34 | average: Math.round((cache[key].reduce((a, b) => a + b) / cache[key].length) * 100) / 100,
35 | };
36 | averageResolverResponse.push(obj);
37 | };
38 |
39 | return averageResolverResponse;
40 | };
41 |
42 | function updateGraphData(queryTime, resolverTime) {
43 | const data = [];
44 |
45 | data.push({x: 'Total Query Time', y: queryTime.duration, label: queryTime.duration + 'ms'});
46 |
47 | resolverTime.forEach((ele) => {
48 | const coordinate = {};
49 | coordinate.x = ele.parentType + ' : ' + ele.fieldName;
50 | coordinate.y = ele.average;
51 | coordinate.label = ele.average + 'ms';
52 |
53 | data.push(coordinate);
54 | })
55 |
56 | // Reverse bar chart to show highest values on top
57 | data.reverse();
58 | return data;
59 | };
60 |
61 | // Invokes query to the Apollo client
62 | function handleClick(e) {
63 | e.preventDefault();
64 |
65 | // Gather user input from 'Server', 'Query', and 'Variables' input fields; determine request 'type'
66 | const userURI = document.getElementById('input-link').value;
67 | let userVariables;
68 | if (info.variables === '') userVariables = {};
69 | else userVariables = JSON.parse(info.variables);
70 |
71 | // Function to send the user's query to the GraphQL server/API
72 | const handleRequest = () => {
73 | fetch(`${userURI}`, {
74 | method: 'POST',
75 | headers: {
76 | 'Content-Type': 'application/json',
77 | },
78 | body: JSON.stringify({
79 | query: `${info.body}`,
80 | variables: userVariables,
81 | }),
82 | })
83 | .then((res) => res.json())
84 | .then((res) => {
85 | const extensionsExist = res.extensions ? true : false;
86 |
87 | if (extensionsExist && res.extensions.nuQLeusTracing) {
88 | const queryTimeData = queryTime(res.extensions);
89 | const resolverTimeData = resolverTime(res.extensions.nuQLeusTracing.resolvers);
90 | const graphData = updateGraphData(queryTimeData, resolverTimeData);
91 |
92 | setInfo(() => ({
93 | ...info,
94 | response: res.data,
95 | extensions: res.extensions,
96 | queryTime: queryTimeData,
97 | resolverTime: resolverTimeData,
98 | graphData
99 | }));
100 | } else {
101 | setInfo(() => ({
102 | ...info,
103 | response: res.data ? res.data : res,
104 | extensions: null
105 | }));
106 | }
107 | })
108 | .catch((err) => {
109 | setInfo(() => ({
110 | ...info,
111 | response: 'Request to server failed.',
112 | }));
113 | })
114 | };
115 |
116 | // Function to handle invalid user input
117 | const handleInvalid = () => {
118 | setInfo(() => ({
119 | ...info,
120 | response: 'Invalid Syntax',
121 | }));
122 | };
123 |
124 | // Validate Input
125 | if (
126 | info.body.substring(0, 5).toLowerCase() === 'query'
127 | || info.body.substring(0, 5).toLowerCase() === 'mutat'
128 | || info.body[0] === '{'
129 | ) {
130 | handleRequest();
131 | } else {
132 | handleInvalid();
133 | };
134 | };
135 |
136 | return (
137 |
138 |
Server:
139 |
140 |
Send
141 |
142 | );
143 | };
144 |
145 | export default ServerField;
146 |
--------------------------------------------------------------------------------
/src/client/components/VariableField.jsx:
--------------------------------------------------------------------------------
1 | import * as React from 'react';
2 | import { useContext } from 'react';
3 | import { Controlled as CodeMirror } from 'react-codemirror2';
4 | import { GraphContext } from '../contexts/GraphContext';
5 |
6 | require('codemirror/mode/xml/xml');
7 | require('codemirror/mode/javascript/javascript');
8 | require('codemirror-graphql/mode');
9 | require('codemirror/mode/jsx/jsx');
10 | require('codemirror-graphql/hint');
11 | require('codemirror-graphql/lint');
12 | require('codemirror/lib/codemirror.css');
13 | require('../stylesheets/editor-theme.css');
14 | require('codemirror/addon/edit/closebrackets');
15 | require('codemirror/addon/display/placeholder');
16 |
17 | const VariableField = () => {
18 | const [info, setInfo] = useContext(GraphContext);
19 | const DEFAULT_JSX_OPTIONS = {
20 | theme: 'custom-0',
21 | autoCloseBrackets: true,
22 | cursorScrollMargin: 48,
23 | mode: 'javascript',
24 | lineNumbers: true,
25 | indentUnit: 2,
26 | tabSize: 2,
27 | styleActiveLine: true,
28 | viewportMargin: 99,
29 | placeholder: 'Variables must be in JSON format',
30 | };
31 |
32 | const onChange = (editor, data, value) => {
33 | setInfo(() => ({
34 | ...info,
35 | variables: value,
36 | }));
37 | };
38 |
39 | return (
40 | <>
41 | Variables
42 | {
47 | // final value, no need to setState here
48 | }}
49 | />
50 | >
51 | );
52 | };
53 |
54 | export default VariableField;
55 |
--------------------------------------------------------------------------------
/src/client/components/VisualDisplay.jsx:
--------------------------------------------------------------------------------
1 | import React, { useEffect, useState, useContext } from 'react';
2 | import { VictoryBar, VictoryChart, VictoryTheme, VictoryLabel, VictoryGroup, VictoryAxis, VictoryTooltip } from 'victory';
3 | import { GraphContext } from '../contexts/GraphContext';
4 |
5 | const VisualDisplay = () => {
6 | const [info, setInfo] = useContext(GraphContext);
7 | const [data, setData] = useState(info.graphData);
8 | // Write out the axis labels into arrays
9 | const labelsData = [];
10 | const labelLenData = [];
11 | // Use values from state (updated from ServerField to GraphContext) to update [x, y] coordinates
12 | for (let i = 0; i < data.length; ++i) {
13 | labelsData.push(data[i].x);
14 | labelLenData.push(i);
15 | };
16 |
17 | const [labels, setLabels] = useState(labelsData);
18 | const [labelLen, setLabelLen] = useState(labelLenData);
19 |
20 | // Whenever a query is made and state gets updated,
21 | useEffect(() => {
22 | setData(info.graphData);
23 | }, [info.response]);
24 |
25 | useEffect(() => {
26 | const labels = [];
27 | const labelLen = [];
28 |
29 | for (let i = 0; i < data.length; ++i) {
30 | labels.push(data[i].x);
31 | labelLen.push(i);
32 | }
33 |
34 | setLabels(labels);
35 | setLabelLen(labelLen);
36 | }, [data])
37 |
38 | // Conditiionally adjust height according to number of rows:
39 | let height = 300;
40 | if (labelLen.length > 7) height = 600;
41 |
42 | return (
43 | <>
44 |
55 | ({
64 | _y: 0,
65 | })
66 | }
67 | }}
68 | labelComponent={
69 |
77 | }
78 | />
79 |
87 | (`${x}ms`))}
90 | style={{
91 | axis: { stroke: 'white', },
92 | tickLabels: { fill: 'white', },
93 | }}
94 | fixLabelOverlap={true}
95 | />
96 |
97 | >
98 | );
99 | };
100 |
101 | export default VisualDisplay;
102 |
--------------------------------------------------------------------------------
/src/client/containers/LeftContainer.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import ServerField from '../components/ServerField';
3 | import VariableField from '../components/VariableField';
4 | import QueryField from '../components/QueryField';
5 |
6 | const LeftContainer = () => (
7 |
8 |
9 |
10 |
11 |
12 | );
13 |
14 | export default LeftContainer;
15 |
--------------------------------------------------------------------------------
/src/client/containers/MainContainer.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import LeftContainer from './LeftContainer';
3 | import MiddleContainer from './MiddleContainer';
4 | import RightContainer from './RightContainer';
5 |
6 | const MainContainer = () => (
7 |
8 |
9 |
10 |
11 |
12 | );
13 |
14 | export default MainContainer;
15 |
--------------------------------------------------------------------------------
/src/client/containers/MiddleContainer.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import OutputDisplay from '../components/OutputDisplay';
3 |
4 | const MiddleContainer = () => (
5 |
6 |
Response
7 |
8 |
9 | );
10 |
11 | export default MiddleContainer;
12 |
--------------------------------------------------------------------------------
/src/client/containers/RightContainer.jsx:
--------------------------------------------------------------------------------
1 | import React, { useContext } from 'react';
2 | import VisualDisplay from '../components/VisualDisplay';
3 | import EmptyTracingData from '../components/EmptyTracingData';
4 | import { GraphContext } from '../contexts/GraphContext';
5 |
6 | const RightContainer = () => {
7 | const [info, setInfo] = useContext(GraphContext);
8 |
9 | const conditionRender = info.extensions ? : ;
10 |
11 | return (
12 |
13 |
Tracing Data
14 | {conditionRender}
15 |
16 | )
17 | };
18 |
19 | export default RightContainer;
20 |
--------------------------------------------------------------------------------
/src/client/contexts/GraphContext.jsx:
--------------------------------------------------------------------------------
1 | import React, { createContext, useState } from 'react';
2 |
3 | export const GraphContext = createContext();
4 |
5 | export const GraphContextProvider = (props) => {
6 | const [info, setInfo] = useState({
7 | uri: '',
8 | body: '',
9 | variables: '',
10 | response: '',
11 | extensions: '',
12 | queryTime: '',
13 | resolverTime: '',
14 | graphData: []
15 | });
16 |
17 | return {props.children} ;
18 | };
19 |
--------------------------------------------------------------------------------
/src/client/index.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import ReactDOM from 'react-dom';
3 | import App from './App';
4 |
5 | ReactDOM.render( , document.getElementById('root'));
6 |
--------------------------------------------------------------------------------
/src/client/stylesheets/editor-theme.css:
--------------------------------------------------------------------------------
1 | .cm-s-custom-0 {
2 | background: rgb(19, 19, 37);
3 | color: rgb(173, 170, 204);
4 | font-weight: 300;
5 | line-height: 1.4;
6 | font-size: 14px;
7 | font-family: "IBM Plex Mono", monospace;
8 | letter-spacing: 0.41px;
9 | }
10 |
11 | .cm-s-custom-0 .CodeMirror-cursor {
12 | border-color: #fff;
13 | outline: 1px solid #fff;
14 | }
15 |
16 | .cm-s-custom-0 .CodeMirror-activeline-background {
17 | background: rgba(240, 240, 255, 0.8);
18 | }
19 |
20 | .cm-s-custom-0 .CodeMirror-selected {
21 | background: rgba(55, 55, 77, 0.3);
22 | }
23 |
24 | .cm-s-custom-0 .cm-comment {
25 | font-style: italic;
26 | color: #676b79;
27 | }
28 |
29 | .cm-s-custom-0 .cm-operator {
30 | color: #f3f3f3;
31 | }
32 |
33 | .cm-s-custom-0 .cm-string {
34 | color: #c267f9;
35 | }
36 |
37 | .cm-s-custom-0 .cm-string-2 {
38 | color: #ffb86c;
39 | }
40 |
41 | .cm-s-custom-0 .cm-tag {
42 | color: #ff2c6d;
43 | }
44 |
45 | .cm-s-custom-0 .cm-meta {
46 | color: #b084eb;
47 | }
48 |
49 | .cm-s-custom-0 .cm-number {
50 | color: #ffb86c;
51 | }
52 |
53 | .cm-s-custom-0 .cm-atom {
54 | color: #ff2c6d;
55 | }
56 |
57 | .cm-s-custom-0 .cm-keyword {
58 | color: #b095e4;
59 | }
60 |
61 | .cm-s-custom-0 .cm-variable {
62 | color: #f73c91;
63 | }
64 |
65 | .cm-s-custom-0 .cm-variable-2 {
66 | color: #ff9ac1;
67 | }
68 |
69 | .cm-s-custom-0 .cm-variable-3 .cm-s-custom-0 .cm-type {
70 | color: #ff9ac1;
71 | }
72 |
73 | .cm-s-custom-0 .cm-def {
74 | color: #e6e6e6;
75 | }
76 |
77 | .cm-s-custom-0 .cm-property {
78 | color: #f3f3f3;
79 | }
80 |
81 | .cm-s-custom-0 .cm-unit {
82 | color: #ffb86c;
83 | }
84 |
85 | .cm-s-custom-0 .cm-attribute {
86 | color: #d8baea;
87 | }
88 |
89 | .cm-s-custom-0 .CodeMirror-matchingbracket {
90 | border-bottom: 1px dotted #19f9d8;
91 | padding-bottom: 2px;
92 | color: #e6e6e6;
93 | }
94 |
95 | .cm-s-custom-0 .CodeMirror-gutters {
96 | background: rgb(19, 19, 37);
97 | border-right-color: rgb(19, 19, 37);
98 | width: 40px;
99 | margin-right: 5px;
100 | }
101 |
102 | .cm-s-custom-0 .CodeMirror-linenumber {
103 | color: rgb(173, 170, 204);
104 | opacity: 0.75;
105 | background: rgb(19, 19, 37);
106 | padding: 0 8px 0 4px;
107 | font-size: 14px;
108 | border-top: 2px solid transparent;
109 | }
110 |
111 | .cm-s-custom-0 .CodeMirror-lines .CodeMirror-code div {
112 | padding-left: 2px;
113 | };
114 |
--------------------------------------------------------------------------------
/src/client/stylesheets/styles.css:
--------------------------------------------------------------------------------
1 | body {
2 | font-family: -apple-system,BlinkMacSystemFont,segoe ui,roboto,oxygen,ubuntu,cantarell,fira sans,droid sans,helvetica neue,sans-serif;
3 | background-color: rgb(1, 2, 11);
4 | color: rgb(195, 194, 197);
5 | }
6 |
7 | input:focus,
8 | select:focus,
9 | textarea:focus,
10 | button:focus {
11 | outline: none;
12 | }
13 |
14 | /***** TITLES *****/
15 | h3 {
16 | margin-block-start: 0em;
17 | }
18 |
19 | .no-tracing {
20 | display: flex;
21 | flex-direction: column;
22 | justify-content: center;
23 | align-items: center;
24 | height: 100%;
25 | }
26 |
27 | .notracing .no-tracing-msg {
28 | align-self: center;
29 | }
30 |
31 | .no-tracing-msg {
32 | color: #3e3a41;
33 | }
34 |
35 | /***** CONTAINERS *****/
36 | #main-container {
37 | display: flex;
38 | flex-direction: row;
39 | justify-content: space-evenly;
40 | }
41 |
42 | #left-container,
43 | #middle-container,
44 | #right-container {
45 | width: 33%;
46 | min-height: 95%;
47 | }
48 |
49 |
50 | /***** CODEMIRROR *****/
51 |
52 | .CodeMirror {
53 | min-height: 100%;
54 | /* font-family: 'Ubuntu Mono', monospace !important; */
55 | /* font-family: "IBM Plex Mono", monospace; */
56 | }
57 |
58 | .react-codemirror2 {
59 | width: 95%;
60 | }
61 |
62 | .Resizer {
63 | height: 100vh;
64 | min-width: 2px;
65 | background: #333;
66 | cursor: row-resize;
67 | }
68 |
69 | /***** NAVBAR *****/
70 |
71 | .logo-img {
72 | width: 250px
73 | }
74 |
75 | .nav-bar {
76 | margin-bottom: 5px;
77 | }
78 |
79 | /***** INPUTS *****/
80 | .input {
81 | overflow-wrap: break-word;
82 | }
83 |
84 | #input-link {
85 | height: 1.2em;
86 | width: 100%;
87 | background-color: rgb(19, 19, 37);
88 | border: none;
89 | color: white;
90 | padding: 10px;
91 | /* margin: 0px 10px; */
92 | }
93 |
94 | .btn-gray {
95 | background-color: transparent;
96 | text-indent: 0px;
97 | text-shadow: none;
98 | border:none;
99 | margin-left: 30px;
100 | background-color: #1c232f;
101 | padding: 12px 30px;
102 | text-align: center;
103 | text-transform: uppercase;
104 | transition: 0.5s;
105 | background-size: 200% auto;
106 | color: #bec0c2;
107 | border-radius: 10px;
108 | display: inline;
109 | }
110 |
111 | .btn-gray:hover {
112 | background-color: #141a24;
113 | }
114 |
115 | /* #query-input {
116 | height: 6em;
117 | width: 95%;
118 | }
119 |
120 | #variable-input {
121 | height: 6em;
122 | width: 95%;
123 | } */
124 |
125 | /***** OUTPUTS *****/
126 |
127 | .output-display {
128 | height: 95%;
129 | width: 95%;
130 | /* overflow: auto;
131 | overflow-wrap: break-word;
132 | border: 1px solid purple; */
133 | }
134 |
135 | .server-field {
136 | display: inline-flex;
137 | width: 95%;
138 | align-items: center;
139 | justify-content: space-between;
140 | }
141 |
142 | .server-title, .server-btn {
143 | flex-grow: 1
144 | }
145 |
146 | .server-input {
147 | flex-grow: 40
148 | }
149 |
150 | /***** RESPONSIVE CSS *****/
151 |
152 | @media only screen and (max-width: 768px) {
153 | /* For mobile phones: */
154 | #main-container {
155 | display: flex;
156 | flex-direction: column;
157 | justify-content: space-evenly;
158 | }
159 |
160 | #left-container,
161 | #middle-container,
162 | #right-container {
163 | width: 100%;
164 | min-height: 50%;
165 | margin-bottom: 20px;
166 | }
167 | }
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | /* Visit https://aka.ms/tsconfig.json to read more about this file */
4 |
5 | /* Basic Options */
6 | // "incremental": true, /* Enable incremental compilation */
7 | "target": "ES2015", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019', 'ES2020', or 'ESNEXT'. */
8 | "module": "commonjs", /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', 'es2020', or 'ESNext'. */
9 | // "lib": [], /* Specify library files to be included in the compilation. */
10 | // "allowJs": true, /* Allow javascript files to be compiled. */
11 | // "checkJs": true, /* Report errors in .js files. */
12 | "jsx": "react", /* Specify JSX code generation: 'preserve', 'react-native', 'react', 'react-jsx' or 'react-jsxdev'. */
13 | // "declaration": true, /* Generates corresponding '.d.ts' file. */
14 | // "declarationMap": true, /* Generates a sourcemap for each corresponding '.d.ts' file. */
15 | "sourceMap": true, /* Generates corresponding '.map' file. */
16 | // "outFile": "./", /* Concatenate and emit output to single file. */
17 | // "outDir": "./", /* Redirect output structure to the directory. */
18 | // "rootDir": "./", /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */
19 | // "composite": true, /* Enable project compilation */
20 | // "tsBuildInfoFile": "./", /* Specify file to store incremental compilation information */
21 | // "removeComments": true, /* Do not emit comments to output. */
22 | // "noEmit": true, /* Do not emit outputs. */
23 | // "importHelpers": true, /* Import emit helpers from 'tslib'. */
24 | // "downlevelIteration": true, /* Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'. */
25 | // "isolatedModules": true, /* Transpile each file as a separate module (similar to 'ts.transpileModule'). */
26 |
27 | /* Strict Type-Checking Options */
28 | "strict": true, /* Enable all strict type-checking options. */
29 | // "noImplicitAny": true, /* Raise error on expressions and declarations with an implied 'any' type. */
30 | // "strictNullChecks": true, /* Enable strict null checks. */
31 | // "strictFunctionTypes": true, /* Enable strict checking of function types. */
32 | // "strictBindCallApply": true, /* Enable strict 'bind', 'call', and 'apply' methods on functions. */
33 | // "strictPropertyInitialization": true, /* Enable strict checking of property initialization in classes. */
34 | // "noImplicitThis": true, /* Raise error on 'this' expressions with an implied 'any' type. */
35 | // "alwaysStrict": true, /* Parse in strict mode and emit "use strict" for each source file. */
36 |
37 | /* Additional Checks */
38 | // "noUnusedLocals": true, /* Report errors on unused locals. */
39 | // "noUnusedParameters": true, /* Report errors on unused parameters. */
40 | // "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */
41 | // "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */
42 | // "noUncheckedIndexedAccess": true, /* Include 'undefined' in index signature results */
43 | // "noPropertyAccessFromIndexSignature": true, /* Require undeclared properties from index signatures to use element accesses. */
44 |
45 | /* Module Resolution Options */
46 | "moduleResolution": "node", /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */
47 | // "baseUrl": "./", /* Base directory to resolve non-absolute module names. */
48 | // "paths": {}, /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */
49 | // "rootDirs": [], /* List of root folders whose combined content represents the structure of the project at runtime. */
50 | // "typeRoots": [], /* List of folders to include type definitions from. */
51 | // "types": [], /* Type declaration files to be included in compilation. */
52 | // "allowSyntheticDefaultImports": true, /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */
53 | "esModuleInterop": true, /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */
54 | // "preserveSymlinks": true, /* Do not resolve the real path of symlinks. */
55 | // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */
56 |
57 | /* Source Map Options */
58 | // "sourceRoot": "", /* Specify the location where debugger should locate TypeScript files instead of source locations. */
59 | // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */
60 | // "inlineSourceMap": true, /* Emit a single file with source maps instead of having a separate file. */
61 | // "inlineSources": true, /* Emit the source alongside the sourcemaps within a single file; requires '--inlineSourceMap' or '--sourceMap' to be set. */
62 |
63 | /* Experimental Options */
64 | "experimentalDecorators": true, /* Enables experimental support for ES7 decorators. */
65 | // "emitDecoratorMetadata": true, /* Enables experimental support for emitting type metadata for decorators. */
66 |
67 | /* Advanced Options */
68 | "skipLibCheck": true, /* Skip type checking of declaration files. */
69 | "forceConsistentCasingInFileNames": true, /* Disallow inconsistently-cased references to the same file. */
70 | }
71 | }
72 |
--------------------------------------------------------------------------------
/webpack.config.js:
--------------------------------------------------------------------------------
1 | const path = require('path');
2 |
3 | module.exports = {
4 | entry: './src/client/index.jsx',
5 | mode: 'production',
6 | module: {
7 | rules: [
8 | {
9 | test: /\.tsx?$/,
10 | exclude: /node_modules/,
11 | include: [path.resolve(__dirname, 'src')],
12 | use: 'ts-loader',
13 | },
14 | {
15 | test: /\.(jsx?)$/,
16 | exclude: /node_modules/,
17 | loader: 'babel-loader',
18 | options: {
19 | presets: ['@babel/preset-env', '@babel/preset-react'],
20 | },
21 | },
22 | {
23 | test: /\.(css)$/,
24 | // exclude: /node_modules/,
25 | use: ['style-loader', 'css-loader'],
26 | },
27 | ],
28 | },
29 | resolve: {
30 | extensions: ['.ts', '.js', '.tsx', '.jsx'],
31 | },
32 | output: {
33 | publicPath: '/dist/',
34 | path: path.resolve(__dirname, 'dist'),
35 | filename: 'bundle.js',
36 | },
37 | devServer: {
38 | publicPath: '/dist/',
39 | hot: true,
40 | },
41 | };
42 |
--------------------------------------------------------------------------------