├── example ├── meals │ ├── Meals │ │ ├── routes │ │ │ └── .gitkeep │ │ ├── .gitignore │ │ ├── .dockerignore │ │ ├── Dockerfile │ │ ├── app.js │ │ ├── middlewares │ │ │ ├── welcome │ │ │ │ ├── template.txt │ │ │ │ └── index.js │ │ │ └── graphql │ │ │ │ └── index.js │ │ ├── models │ │ │ ├── schema_migrations.js │ │ │ ├── menus.js │ │ │ ├── menus_products.js │ │ │ ├── orders_products.js │ │ │ ├── chef_availabilities.js │ │ │ ├── ar_internal_metadata.js │ │ │ ├── orders.js │ │ │ ├── chefs.js │ │ │ ├── product_images.js │ │ │ ├── customers.js │ │ │ ├── delivery_men.js │ │ │ ├── products.js │ │ │ └── index.js │ │ ├── docker-compose.yml │ │ ├── package.json │ │ ├── public │ │ │ └── favicon.png │ │ ├── bin │ │ │ └── www │ │ └── graphql │ │ │ ├── menus.js │ │ │ ├── schema_migrations.js │ │ │ ├── menus_products.js │ │ │ ├── orders_products.js │ │ │ ├── chef_availabilities.js │ │ │ ├── orders.js │ │ │ ├── chefs.js │ │ │ ├── ar_internal_metadata.js │ │ │ ├── customers.js │ │ │ ├── product_images.js │ │ │ ├── delivery_men.js │ │ │ └── products.js │ └── docker-compose.yml ├── movies │ ├── Movies │ │ ├── routes │ │ │ └── .gitkeep │ │ ├── .gitignore │ │ ├── .dockerignore │ │ ├── Dockerfile │ │ ├── app.js │ │ ├── middlewares │ │ │ ├── welcome │ │ │ │ ├── template.txt │ │ │ │ └── index.js │ │ │ └── graphql │ │ │ │ └── index.js │ │ ├── models │ │ │ ├── actors.js │ │ │ ├── genres.js │ │ │ ├── countries.js │ │ │ ├── schema_migrations.js │ │ │ ├── actor_images.js │ │ │ ├── actors_movies.js │ │ │ ├── genres_movies.js │ │ │ ├── countries_movies.js │ │ │ ├── rentals.js │ │ │ ├── comments.js │ │ │ ├── index.js │ │ │ ├── movies.js │ │ │ └── customers.js │ │ ├── docker-compose.yml │ │ ├── package.json │ │ ├── public │ │ │ └── favicon.png │ │ ├── bin │ │ │ └── www │ │ └── graphql │ │ │ ├── actors.js │ │ │ ├── genres.js │ │ │ ├── countries.js │ │ │ ├── actor_images.js │ │ │ ├── actors_movies.js │ │ │ ├── genres_movies.js │ │ │ ├── schema_migrations.js │ │ │ ├── countries_movies.js │ │ │ ├── rentals.js │ │ │ ├── comments.js │ │ │ ├── movies.js │ │ │ └── customers.js │ └── docker-compose.yml └── api-gateway │ ├── package.json │ ├── index.js │ └── package-lock.json ├── .gitignore ├── assets └── logo.png ├── .babelrc ├── package.json ├── LICENSE ├── index.js └── README.md /example/meals/Meals/routes/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /example/movies/Movies/routes/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules 3 | .env 4 | -------------------------------------------------------------------------------- /example/meals/Meals/.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules 3 | .env 4 | -------------------------------------------------------------------------------- /example/movies/Movies/.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules 3 | .env 4 | -------------------------------------------------------------------------------- /example/meals/Meals/.dockerignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | npm-debug.log 3 | .env 4 | -------------------------------------------------------------------------------- /example/movies/Movies/.dockerignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | npm-debug.log 3 | .env 4 | -------------------------------------------------------------------------------- /assets/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ForestAdmin/graphql-stitcher/HEAD/assets/logo.png -------------------------------------------------------------------------------- /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": [["@babel/preset-env", { 3 | "useBuiltIns": "entry" 4 | }]], 5 | "plugins": [ 6 | "@babel/plugin-proposal-class-properties" 7 | ] 8 | } 9 | -------------------------------------------------------------------------------- /example/meals/Meals/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM node:10-alpine 2 | RUN apk add --no-cache \ 3 | git 4 | WORKDIR /usr/src/app 5 | COPY package*.json ./ 6 | RUN npm install 7 | COPY . . 8 | EXPOSE 3004 9 | CMD ["npm", "start"] 10 | -------------------------------------------------------------------------------- /example/movies/Movies/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM node:10-alpine 2 | RUN apk add --no-cache \ 3 | git 4 | WORKDIR /usr/src/app 5 | COPY package*.json ./ 6 | RUN npm install 7 | COPY . . 8 | EXPOSE 3005 9 | CMD ["npm", "start"] 10 | -------------------------------------------------------------------------------- /example/meals/docker-compose.yml: -------------------------------------------------------------------------------- 1 | postgres : 2 | image : postgres:latest 3 | container_name : meals 4 | ports : 5 | - "5446:5432" 6 | environment: 7 | - POSTGRES_DB=meals 8 | - POSTGRES_USER=forest 9 | - POSTGRES_PASSWORD=secret 10 | -------------------------------------------------------------------------------- /example/movies/docker-compose.yml: -------------------------------------------------------------------------------- 1 | postgres : 2 | image : postgres:latest 3 | container_name : movies 4 | ports : 5 | - "5445:5432" 6 | environment: 7 | - POSTGRES_DB=movies 8 | - POSTGRES_USER=forest 9 | - POSTGRES_PASSWORD=secret 10 | -------------------------------------------------------------------------------- /example/meals/Meals/app.js: -------------------------------------------------------------------------------- 1 | const express = require('express'); 2 | const requireAll = require('require-all'); 3 | 4 | const app = express(); 5 | 6 | requireAll({ 7 | dirname: __dirname + '/middlewares', 8 | recursive: true, 9 | resolve: Module => new Module(app), 10 | }); 11 | 12 | module.exports = app; 13 | -------------------------------------------------------------------------------- /example/meals/Meals/middlewares/welcome/template.txt: -------------------------------------------------------------------------------- 1 | 2 | 3 | It works! 4 | 5 | 6 |

Installed middlewares

7 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /example/movies/Movies/app.js: -------------------------------------------------------------------------------- 1 | const express = require('express'); 2 | const requireAll = require('require-all'); 3 | 4 | const app = express(); 5 | 6 | requireAll({ 7 | dirname: __dirname + '/middlewares', 8 | recursive: true, 9 | resolve: Module => new Module(app), 10 | }); 11 | 12 | module.exports = app; 13 | -------------------------------------------------------------------------------- /example/movies/Movies/middlewares/welcome/template.txt: -------------------------------------------------------------------------------- 1 | 2 | 3 | It works! 4 | 5 | 6 |

Installed middlewares

7 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /example/meals/Meals/middlewares/graphql/index.js: -------------------------------------------------------------------------------- 1 | const models = require('../../models'); 2 | 3 | module.exports = function (app) { 4 | require('lumber-graphql').run(app, { 5 | Sequelize: models.Sequelize, 6 | sequelize: models.sequelize, 7 | modelsDir: __dirname + '/../../models', 8 | schemasDir: __dirname + '/../../graphql', 9 | }); 10 | }; 11 | -------------------------------------------------------------------------------- /example/movies/Movies/middlewares/graphql/index.js: -------------------------------------------------------------------------------- 1 | const models = require('../../models'); 2 | 3 | module.exports = function (app) { 4 | require('lumber-graphql').run(app, { 5 | Sequelize: models.Sequelize, 6 | sequelize: models.sequelize, 7 | modelsDir: __dirname + '/../../models', 8 | schemasDir: __dirname + '/../../graphql', 9 | }); 10 | }; 11 | -------------------------------------------------------------------------------- /example/movies/Movies/models/actors.js: -------------------------------------------------------------------------------- 1 | module.exports = (sequelize, DataTypes) => { 2 | const Model = sequelize.define('actors', { 3 | 'name': { 4 | type: DataTypes.STRING, 5 | }, 6 | }, { 7 | tableName: 'actors', 8 | 9 | timestamps: false, 10 | 11 | }); 12 | 13 | Model.associate = (models) => { 14 | }; 15 | 16 | return Model; 17 | }; 18 | 19 | -------------------------------------------------------------------------------- /example/movies/Movies/models/genres.js: -------------------------------------------------------------------------------- 1 | module.exports = (sequelize, DataTypes) => { 2 | const Model = sequelize.define('genres', { 3 | 'genre': { 4 | type: DataTypes.STRING, 5 | }, 6 | }, { 7 | tableName: 'genres', 8 | 9 | timestamps: false, 10 | 11 | }); 12 | 13 | Model.associate = (models) => { 14 | }; 15 | 16 | return Model; 17 | }; 18 | 19 | -------------------------------------------------------------------------------- /example/movies/Movies/models/countries.js: -------------------------------------------------------------------------------- 1 | module.exports = (sequelize, DataTypes) => { 2 | const Model = sequelize.define('countries', { 3 | 'name': { 4 | type: DataTypes.STRING, 5 | }, 6 | }, { 7 | tableName: 'countries', 8 | 9 | timestamps: false, 10 | 11 | }); 12 | 13 | Model.associate = (models) => { 14 | }; 15 | 16 | return Model; 17 | }; 18 | 19 | -------------------------------------------------------------------------------- /example/movies/Movies/models/schema_migrations.js: -------------------------------------------------------------------------------- 1 | module.exports = (sequelize, DataTypes) => { 2 | const Model = sequelize.define('schema_migrations', { 3 | 'version': { 4 | type: DataTypes.STRING, 5 | }, 6 | }, { 7 | tableName: 'schema_migrations', 8 | 9 | timestamps: false, 10 | 11 | }); 12 | 13 | Model.associate = (models) => { 14 | }; 15 | 16 | return Model; 17 | }; 18 | 19 | -------------------------------------------------------------------------------- /example/meals/Meals/models/schema_migrations.js: -------------------------------------------------------------------------------- 1 | module.exports = (sequelize, DataTypes) => { 2 | const Model = sequelize.define('schema_migrations', { 3 | 'version': { 4 | type: DataTypes.STRING, 5 | primaryKey: true 6 | }, 7 | }, { 8 | tableName: 'schema_migrations', 9 | 10 | timestamps: false, 11 | 12 | }); 13 | 14 | Model.associate = (models) => { 15 | }; 16 | 17 | return Model; 18 | }; 19 | 20 | -------------------------------------------------------------------------------- /example/api-gateway/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "api-gateway", 3 | "version": "1.0.0", 4 | "description": "This projects shows how it is easy to implement the concept of GraphQL Schema Stitching using graphql-stitcher.", 5 | "main": "index.js", 6 | "author": "Sandro Munda ", 7 | "license": "MIT", 8 | "dependencies": { 9 | "apollo-server-express": "^2.4.8", 10 | "express": "^4.16.4", 11 | "graphql-stitcher": "beta" 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /example/meals/Meals/models/menus.js: -------------------------------------------------------------------------------- 1 | module.exports = (sequelize, DataTypes) => { 2 | const Model = sequelize.define('menus', { 3 | 'available_at': { 4 | type: DataTypes.DATE, 5 | }, 6 | 'chef_id': { 7 | type: DataTypes.INTEGER, 8 | }, 9 | }, { 10 | tableName: 'menus', 11 | underscored: true, 12 | timestamps: false, 13 | 14 | }); 15 | 16 | Model.associate = (models) => { 17 | }; 18 | 19 | return Model; 20 | }; 21 | 22 | -------------------------------------------------------------------------------- /example/movies/Movies/models/actor_images.js: -------------------------------------------------------------------------------- 1 | module.exports = (sequelize, DataTypes) => { 2 | const Model = sequelize.define('actor_images', { 3 | 'url': { 4 | type: DataTypes.STRING, 5 | }, 6 | 'actor_id': { 7 | type: DataTypes.INTEGER, 8 | }, 9 | }, { 10 | tableName: 'actor_images', 11 | underscored: true, 12 | timestamps: false, 13 | 14 | }); 15 | 16 | Model.associate = (models) => { 17 | }; 18 | 19 | return Model; 20 | }; 21 | 22 | -------------------------------------------------------------------------------- /example/movies/Movies/models/actors_movies.js: -------------------------------------------------------------------------------- 1 | module.exports = (sequelize, DataTypes) => { 2 | const Model = sequelize.define('actors_movies', { 3 | 'movie_id': { 4 | type: DataTypes.INTEGER, 5 | }, 6 | 'actor_id': { 7 | type: DataTypes.INTEGER, 8 | }, 9 | }, { 10 | tableName: 'actors_movies', 11 | underscored: true, 12 | timestamps: false, 13 | 14 | }); 15 | 16 | Model.associate = (models) => { 17 | }; 18 | 19 | return Model; 20 | }; 21 | 22 | -------------------------------------------------------------------------------- /example/movies/Movies/models/genres_movies.js: -------------------------------------------------------------------------------- 1 | module.exports = (sequelize, DataTypes) => { 2 | const Model = sequelize.define('genres_movies', { 3 | 'movie_id': { 4 | type: DataTypes.INTEGER, 5 | }, 6 | 'genre_id': { 7 | type: DataTypes.INTEGER, 8 | }, 9 | }, { 10 | tableName: 'genres_movies', 11 | underscored: true, 12 | timestamps: false, 13 | 14 | }); 15 | 16 | Model.associate = (models) => { 17 | }; 18 | 19 | return Model; 20 | }; 21 | 22 | -------------------------------------------------------------------------------- /example/meals/Meals/models/menus_products.js: -------------------------------------------------------------------------------- 1 | module.exports = (sequelize, DataTypes) => { 2 | const Model = sequelize.define('menus_products', { 3 | 'product_id': { 4 | type: DataTypes.INTEGER, 5 | }, 6 | 'menu_id': { 7 | type: DataTypes.INTEGER, 8 | }, 9 | }, { 10 | tableName: 'menus_products', 11 | underscored: true, 12 | timestamps: false, 13 | 14 | }); 15 | 16 | Model.associate = (models) => { 17 | }; 18 | 19 | return Model; 20 | }; 21 | 22 | -------------------------------------------------------------------------------- /example/meals/Meals/models/orders_products.js: -------------------------------------------------------------------------------- 1 | module.exports = (sequelize, DataTypes) => { 2 | const Model = sequelize.define('orders_products', { 3 | 'order_id': { 4 | type: DataTypes.INTEGER, 5 | }, 6 | 'product_id': { 7 | type: DataTypes.INTEGER, 8 | }, 9 | }, { 10 | tableName: 'orders_products', 11 | underscored: true, 12 | timestamps: false, 13 | 14 | }); 15 | 16 | Model.associate = (models) => { 17 | }; 18 | 19 | return Model; 20 | }; 21 | 22 | -------------------------------------------------------------------------------- /example/movies/Movies/models/countries_movies.js: -------------------------------------------------------------------------------- 1 | module.exports = (sequelize, DataTypes) => { 2 | const Model = sequelize.define('countries_movies', { 3 | 'movie_id': { 4 | type: DataTypes.INTEGER, 5 | }, 6 | 'country_id': { 7 | type: DataTypes.INTEGER, 8 | }, 9 | }, { 10 | tableName: 'countries_movies', 11 | underscored: true, 12 | timestamps: false, 13 | 14 | }); 15 | 16 | Model.associate = (models) => { 17 | }; 18 | 19 | return Model; 20 | }; 21 | 22 | -------------------------------------------------------------------------------- /example/meals/Meals/models/chef_availabilities.js: -------------------------------------------------------------------------------- 1 | module.exports = (sequelize, DataTypes) => { 2 | const Model = sequelize.define('chef_availabilities', { 3 | 'chef_id': { 4 | type: DataTypes.INTEGER, 5 | }, 6 | 'available_at': { 7 | type: DataTypes.DATE, 8 | }, 9 | }, { 10 | tableName: 'chef_availabilities', 11 | underscored: true, 12 | timestamps: false, 13 | 14 | }); 15 | 16 | Model.associate = (models) => { 17 | }; 18 | 19 | return Model; 20 | }; 21 | 22 | -------------------------------------------------------------------------------- /example/meals/Meals/middlewares/welcome/index.js: -------------------------------------------------------------------------------- 1 | const fs = require('fs'); 2 | const _ = require('lodash'); 3 | const requireAll = require('require-all'); 4 | 5 | module.exports = function (app) { 6 | app.get('/', (req, res) => { 7 | const middlewares = requireAll({ dirname: `${__dirname}/..` }); 8 | const templatePath = `${__dirname}/template.txt`; 9 | const template = _.template(fs.readFileSync(templatePath, 'utf-8')); 10 | 11 | res.send(template({ middlewares: Object.keys(middlewares) })); 12 | }); 13 | }; 14 | -------------------------------------------------------------------------------- /example/movies/Movies/middlewares/welcome/index.js: -------------------------------------------------------------------------------- 1 | const fs = require('fs'); 2 | const _ = require('lodash'); 3 | const requireAll = require('require-all'); 4 | 5 | module.exports = function (app) { 6 | app.get('/', (req, res) => { 7 | const middlewares = requireAll({ dirname: `${__dirname}/..` }); 8 | const templatePath = `${__dirname}/template.txt`; 9 | const template = _.template(fs.readFileSync(templatePath, 'utf-8')); 10 | 11 | res.send(template({ middlewares: Object.keys(middlewares) })); 12 | }); 13 | }; 14 | -------------------------------------------------------------------------------- /example/meals/Meals/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '3' 2 | services: 3 | app: 4 | build: 5 | context: . 6 | dockerfile: Dockerfile 7 | container_name: Meals 8 | environment: 9 | - DATABASE_URL=postgres://forest:secret@host.docker.internal:5446/meals 10 | - AUTH_SECRET=e9d7adcb966ef20e2065ac96394b8b4f0324736e108e4c552dd531fe22ca724bd02ccf555534f9aa9b2624d19013d6e3 11 | - PORT=3004 12 | # - SSL_DATABASE=true 13 | # - ENCRYPT_DATABASE=true 14 | 15 | ports: 16 | - "3004:3004" 17 | -------------------------------------------------------------------------------- /example/movies/Movies/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '3' 2 | services: 3 | app: 4 | build: 5 | context: . 6 | dockerfile: Dockerfile 7 | container_name: Movies 8 | environment: 9 | - DATABASE_URL=postgres://forest:secret@host.docker.internal:5445/movies 10 | - AUTH_SECRET=c6985ba57a187b1394431006260bc78b021987920f3bf83e447bfaee4f3c1d563540725234a59224bcedf3fdf6a33350 11 | - PORT=3005 12 | # - SSL_DATABASE=true 13 | # - ENCRYPT_DATABASE=true 14 | 15 | ports: 16 | - "3005:3005" 17 | -------------------------------------------------------------------------------- /example/movies/Movies/models/rentals.js: -------------------------------------------------------------------------------- 1 | module.exports = (sequelize, DataTypes) => { 2 | const Model = sequelize.define('rentals', { 3 | 'customer_id': { 4 | type: DataTypes.INTEGER, 5 | }, 6 | 'movie_id': { 7 | type: DataTypes.INTEGER, 8 | }, 9 | 'created_at': { 10 | type: DataTypes.DATE, 11 | }, 12 | 'updated_at': { 13 | type: DataTypes.DATE, 14 | }, 15 | }, { 16 | tableName: 'rentals', 17 | underscored: true, 18 | 19 | 20 | }); 21 | 22 | Model.associate = (models) => { 23 | }; 24 | 25 | return Model; 26 | }; 27 | 28 | -------------------------------------------------------------------------------- /example/meals/Meals/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Meals", 3 | "version": "0.0.1", 4 | "private": true, 5 | "scripts": { 6 | "start": "node ./bin/www" 7 | }, 8 | "dependencies": { 9 | "apollo-server-express": "^2.4.8", 10 | "chalk": "~1.1.3", 11 | "debug": "~4.0.1", 12 | "dotenv": "~6.1.0", 13 | "express": "~4.16.3", 14 | "forest-express-sequelize": "^3.1.0", 15 | "graphql": "^14.2.1", 16 | "graphql-iso-date": "^3.6.1", 17 | "graphql-type-json": "^0.3.0", 18 | "lumber-graphql": "0.0.1-beta.6", 19 | "pg": "~6.1.0", 20 | "require-all": "^3.0.0", 21 | "sequelize": "~5.7.4" 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /example/meals/Meals/models/ar_internal_metadata.js: -------------------------------------------------------------------------------- 1 | module.exports = (sequelize, DataTypes) => { 2 | const Model = sequelize.define('ar_internal_metadata', { 3 | 'key': { 4 | type: DataTypes.STRING, 5 | primaryKey: true 6 | }, 7 | 'value': { 8 | type: DataTypes.STRING, 9 | }, 10 | 'created_at': { 11 | type: DataTypes.DATE, 12 | }, 13 | 'updated_at': { 14 | type: DataTypes.DATE, 15 | }, 16 | }, { 17 | tableName: 'ar_internal_metadata', 18 | underscored: true, 19 | 20 | 21 | }); 22 | 23 | Model.associate = (models) => { 24 | }; 25 | 26 | return Model; 27 | }; 28 | 29 | -------------------------------------------------------------------------------- /example/movies/Movies/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Movies", 3 | "version": "0.0.1", 4 | "private": true, 5 | "scripts": { 6 | "start": "node ./bin/www" 7 | }, 8 | "dependencies": { 9 | "apollo-server-express": "^2.4.8", 10 | "chalk": "~1.1.3", 11 | "debug": "~4.0.1", 12 | "dotenv": "~6.1.0", 13 | "express": "~4.16.3", 14 | "forest-express-sequelize": "^3.1.0", 15 | "graphql": "^14.2.1", 16 | "graphql-iso-date": "^3.6.1", 17 | "graphql-type-json": "^0.3.0", 18 | "lumber-graphql": "0.0.1-beta.6", 19 | "pg": "~6.1.0", 20 | "require-all": "^3.0.0", 21 | "sequelize": "~5.7.4" 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /example/meals/Meals/models/orders.js: -------------------------------------------------------------------------------- 1 | module.exports = (sequelize, DataTypes) => { 2 | const Model = sequelize.define('orders', { 3 | 'customer_id': { 4 | type: DataTypes.INTEGER, 5 | }, 6 | 'created_at': { 7 | type: DataTypes.DATE, 8 | }, 9 | 'updated_at': { 10 | type: DataTypes.DATE, 11 | }, 12 | 'delivery_address': { 13 | type: DataTypes.STRING, 14 | }, 15 | 'status': { 16 | type: DataTypes.INTEGER, 17 | }, 18 | }, { 19 | tableName: 'orders', 20 | underscored: true, 21 | 22 | 23 | }); 24 | 25 | Model.associate = (models) => { 26 | }; 27 | 28 | return Model; 29 | }; 30 | 31 | -------------------------------------------------------------------------------- /example/movies/Movies/models/comments.js: -------------------------------------------------------------------------------- 1 | module.exports = (sequelize, DataTypes) => { 2 | const Model = sequelize.define('comments', { 3 | 'comment': { 4 | type: DataTypes.STRING, 5 | }, 6 | 'customer_id': { 7 | type: DataTypes.INTEGER, 8 | }, 9 | 'movie_id': { 10 | type: DataTypes.INTEGER, 11 | }, 12 | 'created_at': { 13 | type: DataTypes.DATE, 14 | }, 15 | 'updated_at': { 16 | type: DataTypes.DATE, 17 | }, 18 | 'status': { 19 | type: DataTypes.INTEGER, 20 | }, 21 | }, { 22 | tableName: 'comments', 23 | underscored: true, 24 | 25 | 26 | }); 27 | 28 | Model.associate = (models) => { 29 | }; 30 | 31 | return Model; 32 | }; 33 | 34 | -------------------------------------------------------------------------------- /example/meals/Meals/models/chefs.js: -------------------------------------------------------------------------------- 1 | module.exports = (sequelize, DataTypes) => { 2 | const Model = sequelize.define('chefs', { 3 | 'firstname': { 4 | type: DataTypes.STRING, 5 | }, 6 | 'lastname': { 7 | type: DataTypes.STRING, 8 | }, 9 | 'email': { 10 | type: DataTypes.STRING, 11 | }, 12 | 'phone': { 13 | type: DataTypes.STRING, 14 | }, 15 | 'address': { 16 | type: DataTypes.STRING, 17 | }, 18 | 'created_at': { 19 | type: DataTypes.DATE, 20 | }, 21 | 'updated_at': { 22 | type: DataTypes.DATE, 23 | }, 24 | }, { 25 | tableName: 'chefs', 26 | underscored: true, 27 | 28 | 29 | }); 30 | 31 | Model.associate = (models) => { 32 | }; 33 | 34 | return Model; 35 | }; 36 | 37 | -------------------------------------------------------------------------------- /example/meals/Meals/models/product_images.js: -------------------------------------------------------------------------------- 1 | module.exports = (sequelize, DataTypes) => { 2 | const Model = sequelize.define('product_images', { 3 | 'product_id': { 4 | type: DataTypes.INTEGER, 5 | }, 6 | 'created_at': { 7 | type: DataTypes.DATE, 8 | }, 9 | 'updated_at': { 10 | type: DataTypes.DATE, 11 | }, 12 | 'image_file_name': { 13 | type: DataTypes.STRING, 14 | }, 15 | 'image_content_type': { 16 | type: DataTypes.STRING, 17 | }, 18 | 'image_file_size': { 19 | type: DataTypes.INTEGER, 20 | }, 21 | 'image_updated_at': { 22 | type: DataTypes.DATE, 23 | }, 24 | }, { 25 | tableName: 'product_images', 26 | underscored: true, 27 | 28 | 29 | }); 30 | 31 | Model.associate = (models) => { 32 | }; 33 | 34 | return Model; 35 | }; 36 | 37 | -------------------------------------------------------------------------------- /example/meals/Meals/models/customers.js: -------------------------------------------------------------------------------- 1 | module.exports = (sequelize, DataTypes) => { 2 | const Model = sequelize.define('customers', { 3 | 'firstname': { 4 | type: DataTypes.STRING, 5 | }, 6 | 'lastname': { 7 | type: DataTypes.STRING, 8 | }, 9 | 'address': { 10 | type: DataTypes.STRING, 11 | }, 12 | 'phone': { 13 | type: DataTypes.STRING, 14 | }, 15 | 'created_at': { 16 | type: DataTypes.DATE, 17 | }, 18 | 'updated_at': { 19 | type: DataTypes.DATE, 20 | }, 21 | 'stripe_id': { 22 | type: DataTypes.STRING, 23 | }, 24 | 'bulk_action_started_by': { 25 | type: DataTypes.INTEGER, 26 | }, 27 | }, { 28 | tableName: 'customers', 29 | underscored: true, 30 | 31 | 32 | }); 33 | 34 | Model.associate = (models) => { 35 | }; 36 | 37 | return Model; 38 | }; 39 | 40 | -------------------------------------------------------------------------------- /example/meals/Meals/models/delivery_men.js: -------------------------------------------------------------------------------- 1 | module.exports = (sequelize, DataTypes) => { 2 | const Model = sequelize.define('delivery_men', { 3 | 'firstname': { 4 | type: DataTypes.STRING, 5 | }, 6 | 'lastname': { 7 | type: DataTypes.STRING, 8 | }, 9 | 'email': { 10 | type: DataTypes.STRING, 11 | }, 12 | 'phone': { 13 | type: DataTypes.STRING, 14 | }, 15 | 'location': { 16 | type: DataTypes.STRING, 17 | }, 18 | 'available': { 19 | type: DataTypes.BOOLEAN, 20 | }, 21 | 'created_at': { 22 | type: DataTypes.DATE, 23 | }, 24 | 'updated_at': { 25 | type: DataTypes.DATE, 26 | }, 27 | 'geoloc': { 28 | type: DataTypes.STRING, 29 | }, 30 | }, { 31 | tableName: 'delivery_men', 32 | underscored: true, 33 | 34 | 35 | }); 36 | 37 | Model.associate = (models) => { 38 | }; 39 | 40 | return Model; 41 | }; 42 | 43 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "graphql-stitcher", 3 | "version": "0.0.2-beta.3", 4 | "description": "Make the implementation of GraphQL Schema Stitching easy.", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "npm test", 8 | "start": "node ./index.js" 9 | }, 10 | "repository": { 11 | "type": "git", 12 | "url": "git+https://github.com/forestAdmin/graphql-stitcher.git" 13 | }, 14 | "keywords": [ 15 | "GraphQL", 16 | "API", 17 | "Schema", 18 | "Stitching" 19 | ], 20 | "author": "Sandro Munda ", 21 | "license": "MIT", 22 | "bugs": { 23 | "url": "https://github.com/forestAdmin/graphql-stitcher/issues" 24 | }, 25 | "homepage": "https://github.com/forestAdmin/graphql-stitcher#readme", 26 | "dependencies": { 27 | "apollo-link-http": "^1.5.14", 28 | "graphql": "^14.0.0", 29 | "graphql-tag": "^2.10.1", 30 | "graphql-tools": "^4.0.4", 31 | "node-fetch": "^2.3.0" 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /example/api-gateway/index.js: -------------------------------------------------------------------------------- 1 | const express = require('express'); 2 | const ApolloServer = require('apollo-server-express').ApolloServer; 3 | const GraphQLStitcher = require('graphql-stitcher'); 4 | 5 | const app = express(); 6 | const port = 3000; 7 | 8 | const MEALS_ENDPOINT = 'http://localhost:3004/graphql'; 9 | const MOVIES_ENDPOINT = 'http://localhost:3005/graphql'; 10 | 11 | (async () => { 12 | const stitcher = new GraphQLStitcher(); 13 | 14 | // Meals endpoint 15 | await stitcher.loadRemoteSchema(MEALS_ENDPOINT); 16 | 17 | // Movies endpoint 18 | await stitcher.loadRemoteSchema(MOVIES_ENDPOINT); 19 | 20 | // Stitch! 21 | const schema = stitcher.stitch(); 22 | 23 | const server = new ApolloServer({ introspection: true, playground: true, schema }); 24 | server.applyMiddleware({ app, path: '/graphql' }); 25 | 26 | app.listen(port, () => console.log(`API Gateway listening on port ${port}!`)); 27 | })().catch((err) => { 28 | console.error(err); 29 | }); 30 | -------------------------------------------------------------------------------- /example/meals/Meals/models/products.js: -------------------------------------------------------------------------------- 1 | module.exports = (sequelize, DataTypes) => { 2 | const Model = sequelize.define('products', { 3 | 'title': { 4 | type: DataTypes.STRING, 5 | }, 6 | 'description': { 7 | type: DataTypes.STRING, 8 | }, 9 | 'instructions': { 10 | type: DataTypes.STRING, 11 | }, 12 | 'created_at': { 13 | type: DataTypes.DATE, 14 | }, 15 | 'updated_at': { 16 | type: DataTypes.DATE, 17 | }, 18 | 'product_type': { 19 | type: DataTypes.INTEGER, 20 | }, 21 | 'image_file_name': { 22 | type: DataTypes.STRING, 23 | }, 24 | 'image_content_type': { 25 | type: DataTypes.STRING, 26 | }, 27 | 'image_file_size': { 28 | type: DataTypes.INTEGER, 29 | }, 30 | 'image_updated_at': { 31 | type: DataTypes.DATE, 32 | }, 33 | 'price': { 34 | type: DataTypes.DOUBLE, 35 | }, 36 | }, { 37 | tableName: 'products', 38 | underscored: true, 39 | 40 | 41 | }); 42 | 43 | Model.associate = (models) => { 44 | }; 45 | 46 | return Model; 47 | }; 48 | 49 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2019 Forest Admin Inc 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /example/meals/Meals/public/favicon.png: -------------------------------------------------------------------------------- 1 | �PNG 2 |  3 | IHDR@@�iq�sRGB���;IDATx�[[O\U��a(����P(7��Zhim�5�Ԉ�F_L��6�&�L����>� c4Qkc4*�����^��J�� �B�܆;tf��>�!�� ������Yd8�}]�[��uL/V�ZDST�.�n`X@�#`�n0,���G�x"����F��H�A��}�[��;h��%ʌ,�y� �%l�Τ<�&?3��n��>}���sґiK��bCB� +���O��I���lZ~U ύ�|oCx��4�J�!�K-D2 �C��U��y���n��%��ݯ#�LX����냭"����܋���P5�P$��U�o�kBY��FSإ�a�q!�O���̾�~�� �vj 4 | ��%�"��w�7�å�F��yL�fC�3�:>�n ��n�AG� 5 | 3��~����aȉ�}�0=?|2�fJ����=�B���L`�3 ��̹�>�d?| �7|���P���8`7���s�r_�t_�1�Ȝ��A3��r%y�;��ݿ��{Q�Y���w���?u!"<ۚ���b�,x*�p��C����K.�g�Se�w�j?�Fo���|{& 6 | �Q��U��4�t]�;� ' 7 | ^B �$�߇��N�ձt6;>�>l�l0-. �#�*�y�s=ו]���H�M�~G��]tޠ�&@��M-���O�\~i� 8 | �����N�0�H8LHv�=$��3����[����XwSp���զq� ��� � ��Wq���a�ĭ�������旚��2S��N��{7p��ȚM]f�=����i�גU�k� 9 | s[��4�jv�! ]�߈/���y�7��MY��q ��d��Ձ��P��i�P����;�We�e}-�.�&�~k� �~Ϫk�� �ʬA�luw�n� �N):q��p@E��ȼ{�q��������I[�:�|�=���s`^Ṍ2�[wOaPL�L����;3�w��Jޠ��oyHwOa @~逸B�'�^^r����\fH(�nJ��zv[�����2�^I&�`1�1晒�^JaYN��]��Jm!���j�)�y�Z�.(��+ �M�?LO5ZOHm��}B��܃tk�2^�/8��#��������;�؄47�����Xv6���������rP@��h���GW-�gG�g�� @�"�%d���#�p �PX�������uߑ���� ��J�,�o�E5����p�{�G��?CKXDf�� w� �]�����`��7, �5�˿a��������iq�����IEND�B`� -------------------------------------------------------------------------------- /example/movies/Movies/public/favicon.png: -------------------------------------------------------------------------------- 1 | �PNG 2 |  3 | IHDR@@�iq�sRGB���;IDATx�[[O\U��a(����P(7��Zhim�5�Ԉ�F_L��6�&�L����>� c4Qkc4*�����^��J�� �B�܆;tf��>�!�� ������Yd8�}]�[��uL/V�ZDST�.�n`X@�#`�n0,���G�x"����F��H�A��}�[��;h��%ʌ,�y� �%l�Τ<�&?3��n��>}���sґiK��bCB� +���O��I���lZ~U ύ�|oCx��4�J�!�K-D2 �C��U��y���n��%��ݯ#�LX����냭"����܋���P5�P$��U�o�kBY��FSإ�a�q!�O���̾�~�� �vj 4 | ��%�"��w�7�å�F��yL�fC�3�:>�n ��n�AG� 5 | 3��~����aȉ�}�0=?|2�fJ����=�B���L`�3 ��̹�>�d?| �7|���P���8`7���s�r_�t_�1�Ȝ��A3��r%y�;��ݿ��{Q�Y���w���?u!"<ۚ���b�,x*�p��C����K.�g�Se�w�j?�Fo���|{& 6 | �Q��U��4�t]�;� ' 7 | ^B �$�߇��N�ձt6;>�>l�l0-. �#�*�y�s=ו]���H�M�~G��]tޠ�&@��M-���O�\~i� 8 | �����N�0�H8LHv�=$��3����[����XwSp���զq� ��� � ��Wq���a�ĭ�������旚��2S��N��{7p��ȚM]f�=����i�גU�k� 9 | s[��4�jv�! ]�߈/���y�7��MY��q ��d��Ձ��P��i�P����;�We�e}-�.�&�~k� �~Ϫk�� �ʬA�luw�n� �N):q��p@E��ȼ{�q��������I[�:�|�=���s`^Ṍ2�[wOaPL�L����;3�w��Jޠ��oyHwOa @~逸B�'�^^r����\fH(�nJ��zv[�����2�^I&�`1�1晒�^JaYN��]��Jm!���j�)�y�Z�.(��+ �M�?LO5ZOHm��}B��܃tk�2^�/8��#��������;�؄47�����Xv6���������rP@��h���GW-�gG�g�� @�"�%d���#�p �PX�������uߑ���� ��J�,�o�E5����p�{�G��?CKXDf�� w� �]�����`��7, �5�˿a��������iq�����IEND�B`� -------------------------------------------------------------------------------- /example/meals/Meals/bin/www: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | require('dotenv').config(); 3 | const app = require('../app'); 4 | const debug = require('debug')('{name}:server'); 5 | const http = require('http'); 6 | const chalk = require('chalk'); 7 | 8 | function normalizePort(val) { 9 | var port = parseInt(val, 10); 10 | 11 | if (isNaN(port)) { return val; } 12 | if (port >= 0) { return port; } 13 | 14 | return false; 15 | } 16 | 17 | function onError(error) { 18 | if (error.syscall !== 'listen') { 19 | throw error; 20 | } 21 | 22 | var bind = typeof port === 'string' 23 | ? 'Pipe ' + port 24 | : 'Port ' + port; 25 | 26 | switch (error.code) { 27 | case 'EACCES': 28 | console.error(bind + ' requires elevated privileges'); 29 | process.exit(1); 30 | break; 31 | case 'EADDRINUSE': 32 | console.error(bind + ' is already in use'); 33 | process.exit(1); 34 | break; 35 | default: 36 | throw error; 37 | } 38 | } 39 | 40 | function onListening() { 41 | const addr = server.address(); 42 | const bind = typeof addr === 'string' 43 | ? 'pipe ' + addr 44 | : 'port ' + addr.port; 45 | debug('Listening on ' + bind); 46 | 47 | console.log(chalk.cyan(`Your application is listening on ${bind}.`)); 48 | } 49 | 50 | const port = normalizePort(process.env.PORT || '3000'); 51 | app.set('port', port); 52 | 53 | const server = http.createServer(app); 54 | 55 | server.listen(port); 56 | server.on('error', onError); 57 | server.on('listening', onListening); 58 | -------------------------------------------------------------------------------- /example/meals/Meals/models/index.js: -------------------------------------------------------------------------------- 1 | const fs = require('fs'); 2 | const path = require('path'); 3 | const Sequelize = require('sequelize'); 4 | 5 | if (!process.env.DATABASE_URL) { 6 | console.error('Cannot connect to the database. Please declare the DATABASE_URL environment variable with the correct database connection string.'); 7 | process.exit(); 8 | } 9 | 10 | let databaseOptions = { 11 | logging: process.env.NODE_ENV === 'development' ? console.log : false, 12 | pool: { maxConnections: 10, minConnections: 1 }, 13 | dialectOptions: {} 14 | }; 15 | 16 | if (process.env.SSL_DATABASE) { 17 | databaseOptions.dialectOptions.ssl = true; 18 | } 19 | 20 | if (process.env.ENCRYPT_DATABASE) { 21 | databaseOptions.dialectOptions.encrypt = true; 22 | } 23 | 24 | let sequelize = new Sequelize(process.env.DATABASE_URL, databaseOptions); 25 | let db = {}; 26 | 27 | fs 28 | .readdirSync(__dirname) 29 | .filter(function (file) { 30 | return (file.indexOf('.') !== 0) && (file !== 'index.js'); 31 | }) 32 | .forEach(function (file) { 33 | try { 34 | var model = sequelize['import'](path.join(__dirname, file)); 35 | db[model.name] = model; 36 | } catch (error) { 37 | console.error('Model creation error: ' + error); 38 | } 39 | }); 40 | 41 | Object.keys(db).forEach(function(modelName) { 42 | if ('associate' in db[modelName]) { 43 | db[modelName].associate(db); 44 | } 45 | }); 46 | 47 | db.sequelize = sequelize; 48 | db.Sequelize = Sequelize; 49 | 50 | module.exports = db; 51 | 52 | -------------------------------------------------------------------------------- /example/movies/Movies/bin/www: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | require('dotenv').config(); 3 | const app = require('../app'); 4 | const debug = require('debug')('{name}:server'); 5 | const http = require('http'); 6 | const chalk = require('chalk'); 7 | 8 | function normalizePort(val) { 9 | var port = parseInt(val, 10); 10 | 11 | if (isNaN(port)) { return val; } 12 | if (port >= 0) { return port; } 13 | 14 | return false; 15 | } 16 | 17 | function onError(error) { 18 | if (error.syscall !== 'listen') { 19 | throw error; 20 | } 21 | 22 | var bind = typeof port === 'string' 23 | ? 'Pipe ' + port 24 | : 'Port ' + port; 25 | 26 | switch (error.code) { 27 | case 'EACCES': 28 | console.error(bind + ' requires elevated privileges'); 29 | process.exit(1); 30 | break; 31 | case 'EADDRINUSE': 32 | console.error(bind + ' is already in use'); 33 | process.exit(1); 34 | break; 35 | default: 36 | throw error; 37 | } 38 | } 39 | 40 | function onListening() { 41 | const addr = server.address(); 42 | const bind = typeof addr === 'string' 43 | ? 'pipe ' + addr 44 | : 'port ' + addr.port; 45 | debug('Listening on ' + bind); 46 | 47 | console.log(chalk.cyan(`Your application is listening on ${bind}.`)); 48 | } 49 | 50 | const port = normalizePort(process.env.PORT || '3000'); 51 | app.set('port', port); 52 | 53 | const server = http.createServer(app); 54 | 55 | server.listen(port); 56 | server.on('error', onError); 57 | server.on('listening', onListening); 58 | -------------------------------------------------------------------------------- /example/movies/Movies/models/index.js: -------------------------------------------------------------------------------- 1 | const fs = require('fs'); 2 | const path = require('path'); 3 | const Sequelize = require('sequelize'); 4 | 5 | if (!process.env.DATABASE_URL) { 6 | console.error('Cannot connect to the database. Please declare the DATABASE_URL environment variable with the correct database connection string.'); 7 | process.exit(); 8 | } 9 | 10 | let databaseOptions = { 11 | logging: process.env.NODE_ENV === 'development' ? console.log : false, 12 | pool: { maxConnections: 10, minConnections: 1 }, 13 | dialectOptions: {} 14 | }; 15 | 16 | if (process.env.SSL_DATABASE) { 17 | databaseOptions.dialectOptions.ssl = true; 18 | } 19 | 20 | if (process.env.ENCRYPT_DATABASE) { 21 | databaseOptions.dialectOptions.encrypt = true; 22 | } 23 | 24 | let sequelize = new Sequelize(process.env.DATABASE_URL, databaseOptions); 25 | let db = {}; 26 | 27 | fs 28 | .readdirSync(__dirname) 29 | .filter(function (file) { 30 | return (file.indexOf('.') !== 0) && (file !== 'index.js'); 31 | }) 32 | .forEach(function (file) { 33 | try { 34 | var model = sequelize['import'](path.join(__dirname, file)); 35 | db[model.name] = model; 36 | } catch (error) { 37 | console.error('Model creation error: ' + error); 38 | } 39 | }); 40 | 41 | Object.keys(db).forEach(function(modelName) { 42 | if ('associate' in db[modelName]) { 43 | db[modelName].associate(db); 44 | } 45 | }); 46 | 47 | db.sequelize = sequelize; 48 | db.Sequelize = Sequelize; 49 | 50 | module.exports = db; 51 | 52 | -------------------------------------------------------------------------------- /example/movies/Movies/models/movies.js: -------------------------------------------------------------------------------- 1 | module.exports = (sequelize, DataTypes) => { 2 | const Model = sequelize.define('movies', { 3 | 'imdb_id': { 4 | type: DataTypes.STRING, 5 | }, 6 | 'title': { 7 | type: DataTypes.STRING, 8 | }, 9 | 'year': { 10 | type: DataTypes.STRING, 11 | }, 12 | 'runtime': { 13 | type: DataTypes.STRING, 14 | }, 15 | 'released': { 16 | type: DataTypes.DATE, 17 | }, 18 | 'imdb_rating': { 19 | type: DataTypes.DOUBLE, 20 | }, 21 | 'imdb_votes': { 22 | type: DataTypes.DOUBLE, 23 | }, 24 | 'short_plot': { 25 | type: DataTypes.STRING, 26 | }, 27 | 'full_plot': { 28 | type: DataTypes.STRING, 29 | }, 30 | 'language': { 31 | type: DataTypes.STRING, 32 | }, 33 | 'country': { 34 | type: DataTypes.STRING, 35 | }, 36 | 'awards': { 37 | type: DataTypes.STRING, 38 | }, 39 | 'created_at': { 40 | type: DataTypes.DATE, 41 | }, 42 | 'updated_at': { 43 | type: DataTypes.DATE, 44 | }, 45 | 'price': { 46 | type: DataTypes.DOUBLE, 47 | }, 48 | 'poster_file_name': { 49 | type: DataTypes.STRING, 50 | }, 51 | 'poster_content_type': { 52 | type: DataTypes.STRING, 53 | }, 54 | 'poster_file_size': { 55 | type: DataTypes.INTEGER, 56 | }, 57 | 'poster_updated_at': { 58 | type: DataTypes.DATE, 59 | }, 60 | }, { 61 | tableName: 'movies', 62 | underscored: true, 63 | 64 | 65 | }); 66 | 67 | Model.associate = (models) => { 68 | }; 69 | 70 | return Model; 71 | }; 72 | 73 | -------------------------------------------------------------------------------- /example/movies/Movies/models/customers.js: -------------------------------------------------------------------------------- 1 | module.exports = (sequelize, DataTypes) => { 2 | const Model = sequelize.define('customers', { 3 | 'firstname': { 4 | type: DataTypes.STRING, 5 | }, 6 | 'lastname': { 7 | type: DataTypes.STRING, 8 | }, 9 | 'email': { 10 | type: DataTypes.STRING, 11 | }, 12 | 'stripe_id': { 13 | type: DataTypes.STRING, 14 | }, 15 | 'country': { 16 | type: DataTypes.STRING, 17 | }, 18 | 'city': { 19 | type: DataTypes.STRING, 20 | }, 21 | 'street_address': { 22 | type: DataTypes.STRING, 23 | }, 24 | 'zip_code': { 25 | type: DataTypes.STRING, 26 | }, 27 | 'state': { 28 | type: DataTypes.STRING, 29 | }, 30 | 'created_at': { 31 | type: DataTypes.DATE, 32 | }, 33 | 'updated_at': { 34 | type: DataTypes.DATE, 35 | }, 36 | 'encrypted_password': { 37 | type: DataTypes.STRING, 38 | }, 39 | 'reset_password_token': { 40 | type: DataTypes.STRING, 41 | }, 42 | 'reset_password_sent_at': { 43 | type: DataTypes.DATE, 44 | }, 45 | 'remember_created_at': { 46 | type: DataTypes.DATE, 47 | }, 48 | 'sign_in_count': { 49 | type: DataTypes.INTEGER, 50 | }, 51 | 'current_sign_in_at': { 52 | type: DataTypes.DATE, 53 | }, 54 | 'last_sign_in_at': { 55 | type: DataTypes.DATE, 56 | }, 57 | 'gender': { 58 | type: DataTypes.STRING, 59 | }, 60 | }, { 61 | tableName: 'customers', 62 | underscored: true, 63 | 64 | 65 | }); 66 | 67 | Model.associate = (models) => { 68 | }; 69 | 70 | return Model; 71 | }; 72 | 73 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | const fs = require('fs'); 2 | const gql = require('graphql-tag'); 3 | const GraphQLTools = require('graphql-tools'); 4 | const HttpLink = require('apollo-link-http').HttpLink; 5 | const fetch = require('node-fetch'); 6 | 7 | module.exports = function (args) { 8 | const schemas = []; 9 | 10 | this.linkSchema = ` 11 | type Query { 12 | _: Boolean 13 | } 14 | 15 | type Mutation { 16 | _: Boolean 17 | } 18 | 19 | type Subscription { 20 | _: Boolean 21 | } 22 | `; 23 | 24 | this.addScalar = function (scalar) { 25 | this.linkSchema = this.linkSchema.replace(/^/, ` scalar ${scalar}\n`); 26 | }; 27 | 28 | this.loadRemoteSchema = async function (uri, moreOpts) { 29 | let opts = { uri, fetch }; 30 | 31 | const link = new HttpLink({ ...opts, ...moreOpts, }); 32 | const schema = GraphQLTools.makeRemoteExecutableSchema({ 33 | schema: await GraphQLTools.introspectSchema(link), 34 | link 35 | }); 36 | 37 | schemas.push(schema); 38 | return schema; 39 | }; 40 | 41 | this.loadLocalSchema = function (dir) { 42 | const typeDefs = [gql(this.linkSchema)]; 43 | const resolvers = []; 44 | 45 | fs.readdirSync(dir).forEach((file) => { 46 | if (file !== 'index.js') { 47 | const GraphQLSchema = new (require(`${dir}/${file}`))(args); 48 | 49 | typeDefs.push(GraphQLSchema.getSchema()); 50 | resolvers.push(GraphQLSchema.getResolver()); 51 | } 52 | }); 53 | 54 | const schema = GraphQLTools.makeExecutableSchema({ typeDefs, resolvers, }); 55 | schemas.push(schema); 56 | 57 | return schema; 58 | }; 59 | 60 | this.stitch = function () { 61 | return GraphQLTools.mergeSchemas({ schemas }); 62 | }; 63 | }; 64 | -------------------------------------------------------------------------------- /example/movies/Movies/graphql/actors.js: -------------------------------------------------------------------------------- 1 | const gql = require('apollo-server-express').gql; 2 | const models = require('../models'); 3 | const Liana = require('forest-express-sequelize'); 4 | 5 | const { GraphQLDateTime } = require('graphql-iso-date'); 6 | const GraphQLJSON = require('graphql-type-json'); 7 | 8 | module.exports = function (opts) { 9 | this.getSchema = function () { 10 | return gql` 11 | extend type Query { 12 | count_actors(search: String, filter: JSON): Int 13 | list_actors(page: JSON, sort: String, search: String, filter: JSON): [actors!] 14 | get_actors(id: ID!): actors 15 | } 16 | 17 | extend type Mutation { 18 | create_actors( 19 | name: String, 20 | ): actors 21 | 22 | update_actors( 23 | name: String, 24 | ): actors 25 | 26 | delete_actors(id: ID!): Boolean 27 | } 28 | 29 | type actors { 30 | id: ID! 31 | name: String 32 | } 33 | `; 34 | }; 35 | 36 | this.getResolver = function () { 37 | return { 38 | DateTime: GraphQLDateTime, 39 | JSON: GraphQLJSON, 40 | Query: { 41 | count_actors: async (obj, params) => { 42 | if (!params.filterType) { params.filterType = 'and'; } 43 | if (!params.timezone) { params.timezone = 'Europe/London'; } 44 | 45 | return await new Liana.ResourcesGetter(models.actors, opts, params).count(); 46 | }, 47 | list_actors: async (obj, params) => { 48 | if (!params.filterType) { params.filterType = 'and'; } 49 | if (!params.timezone) { params.timezone = 'Europe/London'; } 50 | 51 | const r = await new Liana.ResourcesGetter(models.actors, opts, params).perform(); 52 | return r[0]; 53 | }, 54 | get_actors: async (obj, { id }, context, info) => { 55 | return await new Liana.ResourceGetter(models.actors, { recordId: id }).perform(); 56 | }, 57 | }, 58 | Mutation: { 59 | create_actors: async (obj, params) => { 60 | return await new Liana.ResourceCreator(models.actors, params).perform(); 61 | }, 62 | update_actors: async (obj, params) => { 63 | return await new Liana.ResourceUpdater(models.actors, { recordId: params.id }, params).perform(); 64 | }, 65 | delete_actors: async (obj, params) => { 66 | return await new Liana.ResourceRemover(models.actors, { recordId: params.id }).perform(); 67 | }, 68 | } 69 | } 70 | }; 71 | } 72 | -------------------------------------------------------------------------------- /example/movies/Movies/graphql/genres.js: -------------------------------------------------------------------------------- 1 | const gql = require('apollo-server-express').gql; 2 | const models = require('../models'); 3 | const Liana = require('forest-express-sequelize'); 4 | 5 | const { GraphQLDateTime } = require('graphql-iso-date'); 6 | const GraphQLJSON = require('graphql-type-json'); 7 | 8 | module.exports = function (opts) { 9 | this.getSchema = function () { 10 | return gql` 11 | extend type Query { 12 | count_genres(search: String, filter: JSON): Int 13 | list_genres(page: JSON, sort: String, search: String, filter: JSON): [genres!] 14 | get_genres(id: ID!): genres 15 | } 16 | 17 | extend type Mutation { 18 | create_genres( 19 | genre: String, 20 | ): genres 21 | 22 | update_genres( 23 | genre: String, 24 | ): genres 25 | 26 | delete_genres(id: ID!): Boolean 27 | } 28 | 29 | type genres { 30 | id: ID! 31 | genre: String 32 | } 33 | `; 34 | }; 35 | 36 | this.getResolver = function () { 37 | return { 38 | DateTime: GraphQLDateTime, 39 | JSON: GraphQLJSON, 40 | Query: { 41 | count_genres: async (obj, params) => { 42 | if (!params.filterType) { params.filterType = 'and'; } 43 | if (!params.timezone) { params.timezone = 'Europe/London'; } 44 | 45 | return await new Liana.ResourcesGetter(models.genres, opts, params).count(); 46 | }, 47 | list_genres: async (obj, params) => { 48 | if (!params.filterType) { params.filterType = 'and'; } 49 | if (!params.timezone) { params.timezone = 'Europe/London'; } 50 | 51 | const r = await new Liana.ResourcesGetter(models.genres, opts, params).perform(); 52 | return r[0]; 53 | }, 54 | get_genres: async (obj, { id }, context, info) => { 55 | return await new Liana.ResourceGetter(models.genres, { recordId: id }).perform(); 56 | }, 57 | }, 58 | Mutation: { 59 | create_genres: async (obj, params) => { 60 | return await new Liana.ResourceCreator(models.genres, params).perform(); 61 | }, 62 | update_genres: async (obj, params) => { 63 | return await new Liana.ResourceUpdater(models.genres, { recordId: params.id }, params).perform(); 64 | }, 65 | delete_genres: async (obj, params) => { 66 | return await new Liana.ResourceRemover(models.genres, { recordId: params.id }).perform(); 67 | }, 68 | } 69 | } 70 | }; 71 | } 72 | -------------------------------------------------------------------------------- /example/movies/Movies/graphql/countries.js: -------------------------------------------------------------------------------- 1 | const gql = require('apollo-server-express').gql; 2 | const models = require('../models'); 3 | const Liana = require('forest-express-sequelize'); 4 | 5 | const { GraphQLDateTime } = require('graphql-iso-date'); 6 | const GraphQLJSON = require('graphql-type-json'); 7 | 8 | module.exports = function (opts) { 9 | this.getSchema = function () { 10 | return gql` 11 | extend type Query { 12 | count_countries(search: String, filter: JSON): Int 13 | list_countries(page: JSON, sort: String, search: String, filter: JSON): [countries!] 14 | get_countries(id: ID!): countries 15 | } 16 | 17 | extend type Mutation { 18 | create_countries( 19 | name: String, 20 | ): countries 21 | 22 | update_countries( 23 | name: String, 24 | ): countries 25 | 26 | delete_countries(id: ID!): Boolean 27 | } 28 | 29 | type countries { 30 | id: ID! 31 | name: String 32 | } 33 | `; 34 | }; 35 | 36 | this.getResolver = function () { 37 | return { 38 | DateTime: GraphQLDateTime, 39 | JSON: GraphQLJSON, 40 | Query: { 41 | count_countries: async (obj, params) => { 42 | if (!params.filterType) { params.filterType = 'and'; } 43 | if (!params.timezone) { params.timezone = 'Europe/London'; } 44 | 45 | return await new Liana.ResourcesGetter(models.countries, opts, params).count(); 46 | }, 47 | list_countries: async (obj, params) => { 48 | if (!params.filterType) { params.filterType = 'and'; } 49 | if (!params.timezone) { params.timezone = 'Europe/London'; } 50 | 51 | const r = await new Liana.ResourcesGetter(models.countries, opts, params).perform(); 52 | return r[0]; 53 | }, 54 | get_countries: async (obj, { id }, context, info) => { 55 | return await new Liana.ResourceGetter(models.countries, { recordId: id }).perform(); 56 | }, 57 | }, 58 | Mutation: { 59 | create_countries: async (obj, params) => { 60 | return await new Liana.ResourceCreator(models.countries, params).perform(); 61 | }, 62 | update_countries: async (obj, params) => { 63 | return await new Liana.ResourceUpdater(models.countries, { recordId: params.id }, params).perform(); 64 | }, 65 | delete_countries: async (obj, params) => { 66 | return await new Liana.ResourceRemover(models.countries, { recordId: params.id }).perform(); 67 | }, 68 | } 69 | } 70 | }; 71 | } 72 | -------------------------------------------------------------------------------- /example/meals/Meals/graphql/menus.js: -------------------------------------------------------------------------------- 1 | const gql = require('apollo-server-express').gql; 2 | const models = require('../models'); 3 | const Liana = require('forest-express-sequelize'); 4 | 5 | const { GraphQLDateTime } = require('graphql-iso-date'); 6 | const GraphQLJSON = require('graphql-type-json'); 7 | 8 | module.exports = function (opts) { 9 | this.getSchema = function () { 10 | return gql` 11 | extend type Query { 12 | count_menus(search: String, filter: JSON): Int 13 | list_menus(page: JSON, sort: String, search: String, filter: JSON): [menus!] 14 | get_menus(id: ID!): menus 15 | } 16 | 17 | extend type Mutation { 18 | create_menus( 19 | available_at: DateTime, 20 | chef_id: Int, 21 | ): menus 22 | 23 | update_menus( 24 | available_at: DateTime, 25 | chef_id: Int, 26 | ): menus 27 | 28 | delete_menus(id: ID!): Boolean 29 | } 30 | 31 | type menus { 32 | id: ID! 33 | available_at: DateTime 34 | chef_id: Int 35 | } 36 | `; 37 | }; 38 | 39 | this.getResolver = function () { 40 | return { 41 | DateTime: GraphQLDateTime, 42 | JSON: GraphQLJSON, 43 | Query: { 44 | count_menus: async (obj, params) => { 45 | if (!params.filterType) { params.filterType = 'and'; } 46 | if (!params.timezone) { params.timezone = 'Europe/London'; } 47 | 48 | return await new Liana.ResourcesGetter(models.menus, opts, params).count(); 49 | }, 50 | list_menus: async (obj, params) => { 51 | if (!params.filterType) { params.filterType = 'and'; } 52 | if (!params.timezone) { params.timezone = 'Europe/London'; } 53 | 54 | const r = await new Liana.ResourcesGetter(models.menus, opts, params).perform(); 55 | return r[0]; 56 | }, 57 | get_menus: async (obj, { id }, context, info) => { 58 | return await new Liana.ResourceGetter(models.menus, { recordId: id }).perform(); 59 | }, 60 | }, 61 | Mutation: { 62 | create_menus: async (obj, params) => { 63 | return await new Liana.ResourceCreator(models.menus, params).perform(); 64 | }, 65 | update_menus: async (obj, params) => { 66 | return await new Liana.ResourceUpdater(models.menus, { recordId: params.id }, params).perform(); 67 | }, 68 | delete_menus: async (obj, params) => { 69 | return await new Liana.ResourceRemover(models.menus, { recordId: params.id }).perform(); 70 | }, 71 | } 72 | } 73 | }; 74 | } 75 | -------------------------------------------------------------------------------- /example/movies/Movies/graphql/actor_images.js: -------------------------------------------------------------------------------- 1 | const gql = require('apollo-server-express').gql; 2 | const models = require('../models'); 3 | const Liana = require('forest-express-sequelize'); 4 | 5 | const { GraphQLDateTime } = require('graphql-iso-date'); 6 | const GraphQLJSON = require('graphql-type-json'); 7 | 8 | module.exports = function (opts) { 9 | this.getSchema = function () { 10 | return gql` 11 | extend type Query { 12 | count_actor_images(search: String, filter: JSON): Int 13 | list_actor_images(page: JSON, sort: String, search: String, filter: JSON): [actor_images!] 14 | get_actor_images(id: ID!): actor_images 15 | } 16 | 17 | extend type Mutation { 18 | create_actor_images( 19 | url: String, 20 | actor_id: Int, 21 | ): actor_images 22 | 23 | update_actor_images( 24 | url: String, 25 | actor_id: Int, 26 | ): actor_images 27 | 28 | delete_actor_images(id: ID!): Boolean 29 | } 30 | 31 | type actor_images { 32 | id: ID! 33 | url: String 34 | actor_id: Int 35 | } 36 | `; 37 | }; 38 | 39 | this.getResolver = function () { 40 | return { 41 | DateTime: GraphQLDateTime, 42 | JSON: GraphQLJSON, 43 | Query: { 44 | count_actor_images: async (obj, params) => { 45 | if (!params.filterType) { params.filterType = 'and'; } 46 | if (!params.timezone) { params.timezone = 'Europe/London'; } 47 | 48 | return await new Liana.ResourcesGetter(models.actor_images, opts, params).count(); 49 | }, 50 | list_actor_images: async (obj, params) => { 51 | if (!params.filterType) { params.filterType = 'and'; } 52 | if (!params.timezone) { params.timezone = 'Europe/London'; } 53 | 54 | const r = await new Liana.ResourcesGetter(models.actor_images, opts, params).perform(); 55 | return r[0]; 56 | }, 57 | get_actor_images: async (obj, { id }, context, info) => { 58 | return await new Liana.ResourceGetter(models.actor_images, { recordId: id }).perform(); 59 | }, 60 | }, 61 | Mutation: { 62 | create_actor_images: async (obj, params) => { 63 | return await new Liana.ResourceCreator(models.actor_images, params).perform(); 64 | }, 65 | update_actor_images: async (obj, params) => { 66 | return await new Liana.ResourceUpdater(models.actor_images, { recordId: params.id }, params).perform(); 67 | }, 68 | delete_actor_images: async (obj, params) => { 69 | return await new Liana.ResourceRemover(models.actor_images, { recordId: params.id }).perform(); 70 | }, 71 | } 72 | } 73 | }; 74 | } 75 | -------------------------------------------------------------------------------- /example/movies/Movies/graphql/actors_movies.js: -------------------------------------------------------------------------------- 1 | const gql = require('apollo-server-express').gql; 2 | const models = require('../models'); 3 | const Liana = require('forest-express-sequelize'); 4 | 5 | const { GraphQLDateTime } = require('graphql-iso-date'); 6 | const GraphQLJSON = require('graphql-type-json'); 7 | 8 | module.exports = function (opts) { 9 | this.getSchema = function () { 10 | return gql` 11 | extend type Query { 12 | count_actors_movies(search: String, filter: JSON): Int 13 | list_actors_movies(page: JSON, sort: String, search: String, filter: JSON): [actors_movies!] 14 | get_actors_movies(id: ID!): actors_movies 15 | } 16 | 17 | extend type Mutation { 18 | create_actors_movies( 19 | movie_id: Int, 20 | actor_id: Int, 21 | ): actors_movies 22 | 23 | update_actors_movies( 24 | movie_id: Int, 25 | actor_id: Int, 26 | ): actors_movies 27 | 28 | delete_actors_movies(id: ID!): Boolean 29 | } 30 | 31 | type actors_movies { 32 | movie_id: Int 33 | actor_id: Int 34 | } 35 | `; 36 | }; 37 | 38 | this.getResolver = function () { 39 | return { 40 | DateTime: GraphQLDateTime, 41 | JSON: GraphQLJSON, 42 | Query: { 43 | count_actors_movies: async (obj, params) => { 44 | if (!params.filterType) { params.filterType = 'and'; } 45 | if (!params.timezone) { params.timezone = 'Europe/London'; } 46 | 47 | return await new Liana.ResourcesGetter(models.actors_movies, opts, params).count(); 48 | }, 49 | list_actors_movies: async (obj, params) => { 50 | if (!params.filterType) { params.filterType = 'and'; } 51 | if (!params.timezone) { params.timezone = 'Europe/London'; } 52 | 53 | const r = await new Liana.ResourcesGetter(models.actors_movies, opts, params).perform(); 54 | return r[0]; 55 | }, 56 | get_actors_movies: async (obj, { id }, context, info) => { 57 | return await new Liana.ResourceGetter(models.actors_movies, { recordId: id }).perform(); 58 | }, 59 | }, 60 | Mutation: { 61 | create_actors_movies: async (obj, params) => { 62 | return await new Liana.ResourceCreator(models.actors_movies, params).perform(); 63 | }, 64 | update_actors_movies: async (obj, params) => { 65 | return await new Liana.ResourceUpdater(models.actors_movies, { recordId: params.id }, params).perform(); 66 | }, 67 | delete_actors_movies: async (obj, params) => { 68 | return await new Liana.ResourceRemover(models.actors_movies, { recordId: params.id }).perform(); 69 | }, 70 | } 71 | } 72 | }; 73 | } 74 | -------------------------------------------------------------------------------- /example/movies/Movies/graphql/genres_movies.js: -------------------------------------------------------------------------------- 1 | const gql = require('apollo-server-express').gql; 2 | const models = require('../models'); 3 | const Liana = require('forest-express-sequelize'); 4 | 5 | const { GraphQLDateTime } = require('graphql-iso-date'); 6 | const GraphQLJSON = require('graphql-type-json'); 7 | 8 | module.exports = function (opts) { 9 | this.getSchema = function () { 10 | return gql` 11 | extend type Query { 12 | count_genres_movies(search: String, filter: JSON): Int 13 | list_genres_movies(page: JSON, sort: String, search: String, filter: JSON): [genres_movies!] 14 | get_genres_movies(id: ID!): genres_movies 15 | } 16 | 17 | extend type Mutation { 18 | create_genres_movies( 19 | movie_id: Int, 20 | genre_id: Int, 21 | ): genres_movies 22 | 23 | update_genres_movies( 24 | movie_id: Int, 25 | genre_id: Int, 26 | ): genres_movies 27 | 28 | delete_genres_movies(id: ID!): Boolean 29 | } 30 | 31 | type genres_movies { 32 | movie_id: Int 33 | genre_id: Int 34 | } 35 | `; 36 | }; 37 | 38 | this.getResolver = function () { 39 | return { 40 | DateTime: GraphQLDateTime, 41 | JSON: GraphQLJSON, 42 | Query: { 43 | count_genres_movies: async (obj, params) => { 44 | if (!params.filterType) { params.filterType = 'and'; } 45 | if (!params.timezone) { params.timezone = 'Europe/London'; } 46 | 47 | return await new Liana.ResourcesGetter(models.genres_movies, opts, params).count(); 48 | }, 49 | list_genres_movies: async (obj, params) => { 50 | if (!params.filterType) { params.filterType = 'and'; } 51 | if (!params.timezone) { params.timezone = 'Europe/London'; } 52 | 53 | const r = await new Liana.ResourcesGetter(models.genres_movies, opts, params).perform(); 54 | return r[0]; 55 | }, 56 | get_genres_movies: async (obj, { id }, context, info) => { 57 | return await new Liana.ResourceGetter(models.genres_movies, { recordId: id }).perform(); 58 | }, 59 | }, 60 | Mutation: { 61 | create_genres_movies: async (obj, params) => { 62 | return await new Liana.ResourceCreator(models.genres_movies, params).perform(); 63 | }, 64 | update_genres_movies: async (obj, params) => { 65 | return await new Liana.ResourceUpdater(models.genres_movies, { recordId: params.id }, params).perform(); 66 | }, 67 | delete_genres_movies: async (obj, params) => { 68 | return await new Liana.ResourceRemover(models.genres_movies, { recordId: params.id }).perform(); 69 | }, 70 | } 71 | } 72 | }; 73 | } 74 | -------------------------------------------------------------------------------- /example/meals/Meals/graphql/schema_migrations.js: -------------------------------------------------------------------------------- 1 | const gql = require('apollo-server-express').gql; 2 | const models = require('../models'); 3 | const Liana = require('forest-express-sequelize'); 4 | 5 | const { GraphQLDateTime } = require('graphql-iso-date'); 6 | const GraphQLJSON = require('graphql-type-json'); 7 | 8 | module.exports = function (opts) { 9 | this.getSchema = function () { 10 | return gql` 11 | extend type Query { 12 | count_schema_migrations(search: String, filter: JSON): Int 13 | list_schema_migrations(page: JSON, sort: String, search: String, filter: JSON): [schema_migrations!] 14 | get_schema_migrations(id: ID!): schema_migrations 15 | } 16 | 17 | extend type Mutation { 18 | create_schema_migrations( 19 | version: String, 20 | ): schema_migrations 21 | 22 | update_schema_migrations( 23 | version: String, 24 | ): schema_migrations 25 | 26 | delete_schema_migrations(id: ID!): Boolean 27 | } 28 | 29 | type schema_migrations { 30 | version: String 31 | } 32 | `; 33 | }; 34 | 35 | this.getResolver = function () { 36 | return { 37 | DateTime: GraphQLDateTime, 38 | JSON: GraphQLJSON, 39 | Query: { 40 | count_schema_migrations: async (obj, params) => { 41 | if (!params.filterType) { params.filterType = 'and'; } 42 | if (!params.timezone) { params.timezone = 'Europe/London'; } 43 | 44 | return await new Liana.ResourcesGetter(models.schema_migrations, opts, params).count(); 45 | }, 46 | list_schema_migrations: async (obj, params) => { 47 | if (!params.filterType) { params.filterType = 'and'; } 48 | if (!params.timezone) { params.timezone = 'Europe/London'; } 49 | 50 | const r = await new Liana.ResourcesGetter(models.schema_migrations, opts, params).perform(); 51 | return r[0]; 52 | }, 53 | get_schema_migrations: async (obj, { id }, context, info) => { 54 | return await new Liana.ResourceGetter(models.schema_migrations, { recordId: id }).perform(); 55 | }, 56 | }, 57 | Mutation: { 58 | create_schema_migrations: async (obj, params) => { 59 | return await new Liana.ResourceCreator(models.schema_migrations, params).perform(); 60 | }, 61 | update_schema_migrations: async (obj, params) => { 62 | return await new Liana.ResourceUpdater(models.schema_migrations, { recordId: params.id }, params).perform(); 63 | }, 64 | delete_schema_migrations: async (obj, params) => { 65 | return await new Liana.ResourceRemover(models.schema_migrations, { recordId: params.id }).perform(); 66 | }, 67 | } 68 | } 69 | }; 70 | } 71 | -------------------------------------------------------------------------------- /example/movies/Movies/graphql/schema_migrations.js: -------------------------------------------------------------------------------- 1 | const gql = require('apollo-server-express').gql; 2 | const models = require('../models'); 3 | const Liana = require('forest-express-sequelize'); 4 | 5 | const { GraphQLDateTime } = require('graphql-iso-date'); 6 | const GraphQLJSON = require('graphql-type-json'); 7 | 8 | module.exports = function (opts) { 9 | this.getSchema = function () { 10 | return gql` 11 | extend type Query { 12 | count_schema_migrations(search: String, filter: JSON): Int 13 | list_schema_migrations(page: JSON, sort: String, search: String, filter: JSON): [schema_migrations!] 14 | get_schema_migrations(id: ID!): schema_migrations 15 | } 16 | 17 | extend type Mutation { 18 | create_schema_migrations( 19 | version: String, 20 | ): schema_migrations 21 | 22 | update_schema_migrations( 23 | version: String, 24 | ): schema_migrations 25 | 26 | delete_schema_migrations(id: ID!): Boolean 27 | } 28 | 29 | type schema_migrations { 30 | version: String 31 | } 32 | `; 33 | }; 34 | 35 | this.getResolver = function () { 36 | return { 37 | DateTime: GraphQLDateTime, 38 | JSON: GraphQLJSON, 39 | Query: { 40 | count_schema_migrations: async (obj, params) => { 41 | if (!params.filterType) { params.filterType = 'and'; } 42 | if (!params.timezone) { params.timezone = 'Europe/London'; } 43 | 44 | return await new Liana.ResourcesGetter(models.schema_migrations, opts, params).count(); 45 | }, 46 | list_schema_migrations: async (obj, params) => { 47 | if (!params.filterType) { params.filterType = 'and'; } 48 | if (!params.timezone) { params.timezone = 'Europe/London'; } 49 | 50 | const r = await new Liana.ResourcesGetter(models.schema_migrations, opts, params).perform(); 51 | return r[0]; 52 | }, 53 | get_schema_migrations: async (obj, { id }, context, info) => { 54 | return await new Liana.ResourceGetter(models.schema_migrations, { recordId: id }).perform(); 55 | }, 56 | }, 57 | Mutation: { 58 | create_schema_migrations: async (obj, params) => { 59 | return await new Liana.ResourceCreator(models.schema_migrations, params).perform(); 60 | }, 61 | update_schema_migrations: async (obj, params) => { 62 | return await new Liana.ResourceUpdater(models.schema_migrations, { recordId: params.id }, params).perform(); 63 | }, 64 | delete_schema_migrations: async (obj, params) => { 65 | return await new Liana.ResourceRemover(models.schema_migrations, { recordId: params.id }).perform(); 66 | }, 67 | } 68 | } 69 | }; 70 | } 71 | -------------------------------------------------------------------------------- /example/meals/Meals/graphql/menus_products.js: -------------------------------------------------------------------------------- 1 | const gql = require('apollo-server-express').gql; 2 | const models = require('../models'); 3 | const Liana = require('forest-express-sequelize'); 4 | 5 | const { GraphQLDateTime } = require('graphql-iso-date'); 6 | const GraphQLJSON = require('graphql-type-json'); 7 | 8 | module.exports = function (opts) { 9 | this.getSchema = function () { 10 | return gql` 11 | extend type Query { 12 | count_menus_products(search: String, filter: JSON): Int 13 | list_menus_products(page: JSON, sort: String, search: String, filter: JSON): [menus_products!] 14 | get_menus_products(id: ID!): menus_products 15 | } 16 | 17 | extend type Mutation { 18 | create_menus_products( 19 | product_id: Int, 20 | menu_id: Int, 21 | ): menus_products 22 | 23 | update_menus_products( 24 | product_id: Int, 25 | menu_id: Int, 26 | ): menus_products 27 | 28 | delete_menus_products(id: ID!): Boolean 29 | } 30 | 31 | type menus_products { 32 | id: ID! 33 | product_id: Int 34 | menu_id: Int 35 | } 36 | `; 37 | }; 38 | 39 | this.getResolver = function () { 40 | return { 41 | DateTime: GraphQLDateTime, 42 | JSON: GraphQLJSON, 43 | Query: { 44 | count_menus_products: async (obj, params) => { 45 | if (!params.filterType) { params.filterType = 'and'; } 46 | if (!params.timezone) { params.timezone = 'Europe/London'; } 47 | 48 | return await new Liana.ResourcesGetter(models.menus_products, opts, params).count(); 49 | }, 50 | list_menus_products: async (obj, params) => { 51 | if (!params.filterType) { params.filterType = 'and'; } 52 | if (!params.timezone) { params.timezone = 'Europe/London'; } 53 | 54 | const r = await new Liana.ResourcesGetter(models.menus_products, opts, params).perform(); 55 | return r[0]; 56 | }, 57 | get_menus_products: async (obj, { id }, context, info) => { 58 | return await new Liana.ResourceGetter(models.menus_products, { recordId: id }).perform(); 59 | }, 60 | }, 61 | Mutation: { 62 | create_menus_products: async (obj, params) => { 63 | return await new Liana.ResourceCreator(models.menus_products, params).perform(); 64 | }, 65 | update_menus_products: async (obj, params) => { 66 | return await new Liana.ResourceUpdater(models.menus_products, { recordId: params.id }, params).perform(); 67 | }, 68 | delete_menus_products: async (obj, params) => { 69 | return await new Liana.ResourceRemover(models.menus_products, { recordId: params.id }).perform(); 70 | }, 71 | } 72 | } 73 | }; 74 | } 75 | -------------------------------------------------------------------------------- /example/meals/Meals/graphql/orders_products.js: -------------------------------------------------------------------------------- 1 | const gql = require('apollo-server-express').gql; 2 | const models = require('../models'); 3 | const Liana = require('forest-express-sequelize'); 4 | 5 | const { GraphQLDateTime } = require('graphql-iso-date'); 6 | const GraphQLJSON = require('graphql-type-json'); 7 | 8 | module.exports = function (opts) { 9 | this.getSchema = function () { 10 | return gql` 11 | extend type Query { 12 | count_orders_products(search: String, filter: JSON): Int 13 | list_orders_products(page: JSON, sort: String, search: String, filter: JSON): [orders_products!] 14 | get_orders_products(id: ID!): orders_products 15 | } 16 | 17 | extend type Mutation { 18 | create_orders_products( 19 | order_id: Int, 20 | product_id: Int, 21 | ): orders_products 22 | 23 | update_orders_products( 24 | order_id: Int, 25 | product_id: Int, 26 | ): orders_products 27 | 28 | delete_orders_products(id: ID!): Boolean 29 | } 30 | 31 | type orders_products { 32 | id: ID! 33 | order_id: Int 34 | product_id: Int 35 | } 36 | `; 37 | }; 38 | 39 | this.getResolver = function () { 40 | return { 41 | DateTime: GraphQLDateTime, 42 | JSON: GraphQLJSON, 43 | Query: { 44 | count_orders_products: async (obj, params) => { 45 | if (!params.filterType) { params.filterType = 'and'; } 46 | if (!params.timezone) { params.timezone = 'Europe/London'; } 47 | 48 | return await new Liana.ResourcesGetter(models.orders_products, opts, params).count(); 49 | }, 50 | list_orders_products: async (obj, params) => { 51 | if (!params.filterType) { params.filterType = 'and'; } 52 | if (!params.timezone) { params.timezone = 'Europe/London'; } 53 | 54 | const r = await new Liana.ResourcesGetter(models.orders_products, opts, params).perform(); 55 | return r[0]; 56 | }, 57 | get_orders_products: async (obj, { id }, context, info) => { 58 | return await new Liana.ResourceGetter(models.orders_products, { recordId: id }).perform(); 59 | }, 60 | }, 61 | Mutation: { 62 | create_orders_products: async (obj, params) => { 63 | return await new Liana.ResourceCreator(models.orders_products, params).perform(); 64 | }, 65 | update_orders_products: async (obj, params) => { 66 | return await new Liana.ResourceUpdater(models.orders_products, { recordId: params.id }, params).perform(); 67 | }, 68 | delete_orders_products: async (obj, params) => { 69 | return await new Liana.ResourceRemover(models.orders_products, { recordId: params.id }).perform(); 70 | }, 71 | } 72 | } 73 | }; 74 | } 75 | -------------------------------------------------------------------------------- /example/movies/Movies/graphql/countries_movies.js: -------------------------------------------------------------------------------- 1 | const gql = require('apollo-server-express').gql; 2 | const models = require('../models'); 3 | const Liana = require('forest-express-sequelize'); 4 | 5 | const { GraphQLDateTime } = require('graphql-iso-date'); 6 | const GraphQLJSON = require('graphql-type-json'); 7 | 8 | module.exports = function (opts) { 9 | this.getSchema = function () { 10 | return gql` 11 | extend type Query { 12 | count_countries_movies(search: String, filter: JSON): Int 13 | list_countries_movies(page: JSON, sort: String, search: String, filter: JSON): [countries_movies!] 14 | get_countries_movies(id: ID!): countries_movies 15 | } 16 | 17 | extend type Mutation { 18 | create_countries_movies( 19 | movie_id: Int, 20 | country_id: Int, 21 | ): countries_movies 22 | 23 | update_countries_movies( 24 | movie_id: Int, 25 | country_id: Int, 26 | ): countries_movies 27 | 28 | delete_countries_movies(id: ID!): Boolean 29 | } 30 | 31 | type countries_movies { 32 | movie_id: Int 33 | country_id: Int 34 | } 35 | `; 36 | }; 37 | 38 | this.getResolver = function () { 39 | return { 40 | DateTime: GraphQLDateTime, 41 | JSON: GraphQLJSON, 42 | Query: { 43 | count_countries_movies: async (obj, params) => { 44 | if (!params.filterType) { params.filterType = 'and'; } 45 | if (!params.timezone) { params.timezone = 'Europe/London'; } 46 | 47 | return await new Liana.ResourcesGetter(models.countries_movies, opts, params).count(); 48 | }, 49 | list_countries_movies: async (obj, params) => { 50 | if (!params.filterType) { params.filterType = 'and'; } 51 | if (!params.timezone) { params.timezone = 'Europe/London'; } 52 | 53 | const r = await new Liana.ResourcesGetter(models.countries_movies, opts, params).perform(); 54 | return r[0]; 55 | }, 56 | get_countries_movies: async (obj, { id }, context, info) => { 57 | return await new Liana.ResourceGetter(models.countries_movies, { recordId: id }).perform(); 58 | }, 59 | }, 60 | Mutation: { 61 | create_countries_movies: async (obj, params) => { 62 | return await new Liana.ResourceCreator(models.countries_movies, params).perform(); 63 | }, 64 | update_countries_movies: async (obj, params) => { 65 | return await new Liana.ResourceUpdater(models.countries_movies, { recordId: params.id }, params).perform(); 66 | }, 67 | delete_countries_movies: async (obj, params) => { 68 | return await new Liana.ResourceRemover(models.countries_movies, { recordId: params.id }).perform(); 69 | }, 70 | } 71 | } 72 | }; 73 | } 74 | -------------------------------------------------------------------------------- /example/movies/Movies/graphql/rentals.js: -------------------------------------------------------------------------------- 1 | const gql = require('apollo-server-express').gql; 2 | const models = require('../models'); 3 | const Liana = require('forest-express-sequelize'); 4 | 5 | const { GraphQLDateTime } = require('graphql-iso-date'); 6 | const GraphQLJSON = require('graphql-type-json'); 7 | 8 | module.exports = function (opts) { 9 | this.getSchema = function () { 10 | return gql` 11 | extend type Query { 12 | count_rentals(search: String, filter: JSON): Int 13 | list_rentals(page: JSON, sort: String, search: String, filter: JSON): [rentals!] 14 | get_rentals(id: ID!): rentals 15 | } 16 | 17 | extend type Mutation { 18 | create_rentals( 19 | customer_id: Int, 20 | movie_id: Int, 21 | created_at: DateTime, 22 | updated_at: DateTime, 23 | ): rentals 24 | 25 | update_rentals( 26 | customer_id: Int, 27 | movie_id: Int, 28 | created_at: DateTime, 29 | updated_at: DateTime, 30 | ): rentals 31 | 32 | delete_rentals(id: ID!): Boolean 33 | } 34 | 35 | type rentals { 36 | id: ID! 37 | customer_id: Int 38 | movie_id: Int 39 | created_at: DateTime 40 | updated_at: DateTime 41 | } 42 | `; 43 | }; 44 | 45 | this.getResolver = function () { 46 | return { 47 | DateTime: GraphQLDateTime, 48 | JSON: GraphQLJSON, 49 | Query: { 50 | count_rentals: async (obj, params) => { 51 | if (!params.filterType) { params.filterType = 'and'; } 52 | if (!params.timezone) { params.timezone = 'Europe/London'; } 53 | 54 | return await new Liana.ResourcesGetter(models.rentals, opts, params).count(); 55 | }, 56 | list_rentals: async (obj, params) => { 57 | if (!params.filterType) { params.filterType = 'and'; } 58 | if (!params.timezone) { params.timezone = 'Europe/London'; } 59 | 60 | const r = await new Liana.ResourcesGetter(models.rentals, opts, params).perform(); 61 | return r[0]; 62 | }, 63 | get_rentals: async (obj, { id }, context, info) => { 64 | return await new Liana.ResourceGetter(models.rentals, { recordId: id }).perform(); 65 | }, 66 | }, 67 | Mutation: { 68 | create_rentals: async (obj, params) => { 69 | return await new Liana.ResourceCreator(models.rentals, params).perform(); 70 | }, 71 | update_rentals: async (obj, params) => { 72 | return await new Liana.ResourceUpdater(models.rentals, { recordId: params.id }, params).perform(); 73 | }, 74 | delete_rentals: async (obj, params) => { 75 | return await new Liana.ResourceRemover(models.rentals, { recordId: params.id }).perform(); 76 | }, 77 | } 78 | } 79 | }; 80 | } 81 | -------------------------------------------------------------------------------- /example/meals/Meals/graphql/chef_availabilities.js: -------------------------------------------------------------------------------- 1 | const gql = require('apollo-server-express').gql; 2 | const models = require('../models'); 3 | const Liana = require('forest-express-sequelize'); 4 | 5 | const { GraphQLDateTime } = require('graphql-iso-date'); 6 | const GraphQLJSON = require('graphql-type-json'); 7 | 8 | module.exports = function (opts) { 9 | this.getSchema = function () { 10 | return gql` 11 | extend type Query { 12 | count_chef_availabilities(search: String, filter: JSON): Int 13 | list_chef_availabilities(page: JSON, sort: String, search: String, filter: JSON): [chef_availabilities!] 14 | get_chef_availabilities(id: ID!): chef_availabilities 15 | } 16 | 17 | extend type Mutation { 18 | create_chef_availabilities( 19 | chef_id: Int, 20 | available_at: DateTime, 21 | ): chef_availabilities 22 | 23 | update_chef_availabilities( 24 | chef_id: Int, 25 | available_at: DateTime, 26 | ): chef_availabilities 27 | 28 | delete_chef_availabilities(id: ID!): Boolean 29 | } 30 | 31 | type chef_availabilities { 32 | id: ID! 33 | chef_id: Int 34 | available_at: DateTime 35 | } 36 | `; 37 | }; 38 | 39 | this.getResolver = function () { 40 | return { 41 | DateTime: GraphQLDateTime, 42 | JSON: GraphQLJSON, 43 | Query: { 44 | count_chef_availabilities: async (obj, params) => { 45 | if (!params.filterType) { params.filterType = 'and'; } 46 | if (!params.timezone) { params.timezone = 'Europe/London'; } 47 | 48 | return await new Liana.ResourcesGetter(models.chef_availabilities, opts, params).count(); 49 | }, 50 | list_chef_availabilities: async (obj, params) => { 51 | if (!params.filterType) { params.filterType = 'and'; } 52 | if (!params.timezone) { params.timezone = 'Europe/London'; } 53 | 54 | const r = await new Liana.ResourcesGetter(models.chef_availabilities, opts, params).perform(); 55 | return r[0]; 56 | }, 57 | get_chef_availabilities: async (obj, { id }, context, info) => { 58 | return await new Liana.ResourceGetter(models.chef_availabilities, { recordId: id }).perform(); 59 | }, 60 | }, 61 | Mutation: { 62 | create_chef_availabilities: async (obj, params) => { 63 | return await new Liana.ResourceCreator(models.chef_availabilities, params).perform(); 64 | }, 65 | update_chef_availabilities: async (obj, params) => { 66 | return await new Liana.ResourceUpdater(models.chef_availabilities, { recordId: params.id }, params).perform(); 67 | }, 68 | delete_chef_availabilities: async (obj, params) => { 69 | return await new Liana.ResourceRemover(models.chef_availabilities, { recordId: params.id }).perform(); 70 | }, 71 | } 72 | } 73 | }; 74 | } 75 | -------------------------------------------------------------------------------- /example/meals/Meals/graphql/orders.js: -------------------------------------------------------------------------------- 1 | const gql = require('apollo-server-express').gql; 2 | const models = require('../models'); 3 | const Liana = require('forest-express-sequelize'); 4 | 5 | const { GraphQLDateTime } = require('graphql-iso-date'); 6 | const GraphQLJSON = require('graphql-type-json'); 7 | 8 | module.exports = function (opts) { 9 | this.getSchema = function () { 10 | return gql` 11 | extend type Query { 12 | count_orders(search: String, filter: JSON): Int 13 | list_orders(page: JSON, sort: String, search: String, filter: JSON): [orders!] 14 | get_orders(id: ID!): orders 15 | } 16 | 17 | extend type Mutation { 18 | create_orders( 19 | customer_id: Int, 20 | created_at: DateTime, 21 | updated_at: DateTime, 22 | delivery_address: String, 23 | status: Int, 24 | ): orders 25 | 26 | update_orders( 27 | customer_id: Int, 28 | created_at: DateTime, 29 | updated_at: DateTime, 30 | delivery_address: String, 31 | status: Int, 32 | ): orders 33 | 34 | delete_orders(id: ID!): Boolean 35 | } 36 | 37 | type orders { 38 | id: ID! 39 | customer_id: Int 40 | created_at: DateTime 41 | updated_at: DateTime 42 | delivery_address: String 43 | status: Int 44 | } 45 | `; 46 | }; 47 | 48 | this.getResolver = function () { 49 | return { 50 | DateTime: GraphQLDateTime, 51 | JSON: GraphQLJSON, 52 | Query: { 53 | count_orders: async (obj, params) => { 54 | if (!params.filterType) { params.filterType = 'and'; } 55 | if (!params.timezone) { params.timezone = 'Europe/London'; } 56 | 57 | return await new Liana.ResourcesGetter(models.orders, opts, params).count(); 58 | }, 59 | list_orders: async (obj, params) => { 60 | if (!params.filterType) { params.filterType = 'and'; } 61 | if (!params.timezone) { params.timezone = 'Europe/London'; } 62 | 63 | const r = await new Liana.ResourcesGetter(models.orders, opts, params).perform(); 64 | return r[0]; 65 | }, 66 | get_orders: async (obj, { id }, context, info) => { 67 | return await new Liana.ResourceGetter(models.orders, { recordId: id }).perform(); 68 | }, 69 | }, 70 | Mutation: { 71 | create_orders: async (obj, params) => { 72 | return await new Liana.ResourceCreator(models.orders, params).perform(); 73 | }, 74 | update_orders: async (obj, params) => { 75 | return await new Liana.ResourceUpdater(models.orders, { recordId: params.id }, params).perform(); 76 | }, 77 | delete_orders: async (obj, params) => { 78 | return await new Liana.ResourceRemover(models.orders, { recordId: params.id }).perform(); 79 | }, 80 | } 81 | } 82 | }; 83 | } 84 | -------------------------------------------------------------------------------- /example/movies/Movies/graphql/comments.js: -------------------------------------------------------------------------------- 1 | const gql = require('apollo-server-express').gql; 2 | const models = require('../models'); 3 | const Liana = require('forest-express-sequelize'); 4 | 5 | const { GraphQLDateTime } = require('graphql-iso-date'); 6 | const GraphQLJSON = require('graphql-type-json'); 7 | 8 | module.exports = function (opts) { 9 | this.getSchema = function () { 10 | return gql` 11 | extend type Query { 12 | count_comments(search: String, filter: JSON): Int 13 | list_comments(page: JSON, sort: String, search: String, filter: JSON): [comments!] 14 | get_comments(id: ID!): comments 15 | } 16 | 17 | extend type Mutation { 18 | create_comments( 19 | comment: String, 20 | customer_id: Int, 21 | movie_id: Int, 22 | created_at: DateTime, 23 | updated_at: DateTime, 24 | status: Int, 25 | ): comments 26 | 27 | update_comments( 28 | comment: String, 29 | customer_id: Int, 30 | movie_id: Int, 31 | created_at: DateTime, 32 | updated_at: DateTime, 33 | status: Int, 34 | ): comments 35 | 36 | delete_comments(id: ID!): Boolean 37 | } 38 | 39 | type comments { 40 | id: ID! 41 | comment: String 42 | customer_id: Int 43 | movie_id: Int 44 | created_at: DateTime 45 | updated_at: DateTime 46 | status: Int 47 | } 48 | `; 49 | }; 50 | 51 | this.getResolver = function () { 52 | return { 53 | DateTime: GraphQLDateTime, 54 | JSON: GraphQLJSON, 55 | Query: { 56 | count_comments: async (obj, params) => { 57 | if (!params.filterType) { params.filterType = 'and'; } 58 | if (!params.timezone) { params.timezone = 'Europe/London'; } 59 | 60 | return await new Liana.ResourcesGetter(models.comments, opts, params).count(); 61 | }, 62 | list_comments: async (obj, params) => { 63 | if (!params.filterType) { params.filterType = 'and'; } 64 | if (!params.timezone) { params.timezone = 'Europe/London'; } 65 | 66 | const r = await new Liana.ResourcesGetter(models.comments, opts, params).perform(); 67 | return r[0]; 68 | }, 69 | get_comments: async (obj, { id }, context, info) => { 70 | return await new Liana.ResourceGetter(models.comments, { recordId: id }).perform(); 71 | }, 72 | }, 73 | Mutation: { 74 | create_comments: async (obj, params) => { 75 | return await new Liana.ResourceCreator(models.comments, params).perform(); 76 | }, 77 | update_comments: async (obj, params) => { 78 | return await new Liana.ResourceUpdater(models.comments, { recordId: params.id }, params).perform(); 79 | }, 80 | delete_comments: async (obj, params) => { 81 | return await new Liana.ResourceRemover(models.comments, { recordId: params.id }).perform(); 82 | }, 83 | } 84 | } 85 | }; 86 | } 87 | -------------------------------------------------------------------------------- /example/meals/Meals/graphql/chefs.js: -------------------------------------------------------------------------------- 1 | const gql = require('apollo-server-express').gql; 2 | const models = require('../models'); 3 | const Liana = require('forest-express-sequelize'); 4 | 5 | const { GraphQLDateTime } = require('graphql-iso-date'); 6 | const GraphQLJSON = require('graphql-type-json'); 7 | 8 | module.exports = function (opts) { 9 | this.getSchema = function () { 10 | return gql` 11 | extend type Query { 12 | count_chefs(search: String, filter: JSON): Int 13 | list_chefs(page: JSON, sort: String, search: String, filter: JSON): [chefs!] 14 | get_chefs(id: ID!): chefs 15 | } 16 | 17 | extend type Mutation { 18 | create_chefs( 19 | firstname: String, 20 | lastname: String, 21 | email: String, 22 | phone: String, 23 | address: String, 24 | created_at: DateTime, 25 | updated_at: DateTime, 26 | ): chefs 27 | 28 | update_chefs( 29 | firstname: String, 30 | lastname: String, 31 | email: String, 32 | phone: String, 33 | address: String, 34 | created_at: DateTime, 35 | updated_at: DateTime, 36 | ): chefs 37 | 38 | delete_chefs(id: ID!): Boolean 39 | } 40 | 41 | type chefs { 42 | id: ID! 43 | firstname: String 44 | lastname: String 45 | email: String 46 | phone: String 47 | address: String 48 | created_at: DateTime 49 | updated_at: DateTime 50 | } 51 | `; 52 | }; 53 | 54 | this.getResolver = function () { 55 | return { 56 | DateTime: GraphQLDateTime, 57 | JSON: GraphQLJSON, 58 | Query: { 59 | count_chefs: async (obj, params) => { 60 | if (!params.filterType) { params.filterType = 'and'; } 61 | if (!params.timezone) { params.timezone = 'Europe/London'; } 62 | 63 | return await new Liana.ResourcesGetter(models.chefs, opts, params).count(); 64 | }, 65 | list_chefs: async (obj, params) => { 66 | if (!params.filterType) { params.filterType = 'and'; } 67 | if (!params.timezone) { params.timezone = 'Europe/London'; } 68 | 69 | const r = await new Liana.ResourcesGetter(models.chefs, opts, params).perform(); 70 | return r[0]; 71 | }, 72 | get_chefs: async (obj, { id }, context, info) => { 73 | return await new Liana.ResourceGetter(models.chefs, { recordId: id }).perform(); 74 | }, 75 | }, 76 | Mutation: { 77 | create_chefs: async (obj, params) => { 78 | return await new Liana.ResourceCreator(models.chefs, params).perform(); 79 | }, 80 | update_chefs: async (obj, params) => { 81 | return await new Liana.ResourceUpdater(models.chefs, { recordId: params.id }, params).perform(); 82 | }, 83 | delete_chefs: async (obj, params) => { 84 | return await new Liana.ResourceRemover(models.chefs, { recordId: params.id }).perform(); 85 | }, 86 | } 87 | } 88 | }; 89 | } 90 | -------------------------------------------------------------------------------- /example/meals/Meals/graphql/ar_internal_metadata.js: -------------------------------------------------------------------------------- 1 | const gql = require('apollo-server-express').gql; 2 | const models = require('../models'); 3 | const Liana = require('forest-express-sequelize'); 4 | 5 | const { GraphQLDateTime } = require('graphql-iso-date'); 6 | const GraphQLJSON = require('graphql-type-json'); 7 | 8 | module.exports = function (opts) { 9 | this.getSchema = function () { 10 | return gql` 11 | extend type Query { 12 | count_ar_internal_metadata(search: String, filter: JSON): Int 13 | list_ar_internal_metadata(page: JSON, sort: String, search: String, filter: JSON): [ar_internal_metadata!] 14 | get_ar_internal_metadata(id: ID!): ar_internal_metadata 15 | } 16 | 17 | extend type Mutation { 18 | create_ar_internal_metadata( 19 | key: String, 20 | value: String, 21 | created_at: DateTime, 22 | updated_at: DateTime, 23 | ): ar_internal_metadata 24 | 25 | update_ar_internal_metadata( 26 | key: String, 27 | value: String, 28 | created_at: DateTime, 29 | updated_at: DateTime, 30 | ): ar_internal_metadata 31 | 32 | delete_ar_internal_metadata(id: ID!): Boolean 33 | } 34 | 35 | type ar_internal_metadata { 36 | key: String 37 | value: String 38 | created_at: DateTime 39 | updated_at: DateTime 40 | } 41 | `; 42 | }; 43 | 44 | this.getResolver = function () { 45 | return { 46 | DateTime: GraphQLDateTime, 47 | JSON: GraphQLJSON, 48 | Query: { 49 | count_ar_internal_metadata: async (obj, params) => { 50 | if (!params.filterType) { params.filterType = 'and'; } 51 | if (!params.timezone) { params.timezone = 'Europe/London'; } 52 | 53 | return await new Liana.ResourcesGetter(models.ar_internal_metadata, opts, params).count(); 54 | }, 55 | list_ar_internal_metadata: async (obj, params) => { 56 | if (!params.filterType) { params.filterType = 'and'; } 57 | if (!params.timezone) { params.timezone = 'Europe/London'; } 58 | 59 | const r = await new Liana.ResourcesGetter(models.ar_internal_metadata, opts, params).perform(); 60 | return r[0]; 61 | }, 62 | get_ar_internal_metadata: async (obj, { id }, context, info) => { 63 | return await new Liana.ResourceGetter(models.ar_internal_metadata, { recordId: id }).perform(); 64 | }, 65 | }, 66 | Mutation: { 67 | create_ar_internal_metadata: async (obj, params) => { 68 | return await new Liana.ResourceCreator(models.ar_internal_metadata, params).perform(); 69 | }, 70 | update_ar_internal_metadata: async (obj, params) => { 71 | return await new Liana.ResourceUpdater(models.ar_internal_metadata, { recordId: params.id }, params).perform(); 72 | }, 73 | delete_ar_internal_metadata: async (obj, params) => { 74 | return await new Liana.ResourceRemover(models.ar_internal_metadata, { recordId: params.id }).perform(); 75 | }, 76 | } 77 | } 78 | }; 79 | } 80 | -------------------------------------------------------------------------------- /example/meals/Meals/graphql/customers.js: -------------------------------------------------------------------------------- 1 | const gql = require('apollo-server-express').gql; 2 | const models = require('../models'); 3 | const Liana = require('forest-express-sequelize'); 4 | 5 | const { GraphQLDateTime } = require('graphql-iso-date'); 6 | const GraphQLJSON = require('graphql-type-json'); 7 | 8 | module.exports = function (opts) { 9 | this.getSchema = function () { 10 | return gql` 11 | extend type Query { 12 | count_customers(search: String, filter: JSON): Int 13 | list_customers(page: JSON, sort: String, search: String, filter: JSON): [customers!] 14 | get_customers(id: ID!): customers 15 | } 16 | 17 | extend type Mutation { 18 | create_customers( 19 | firstname: String, 20 | lastname: String, 21 | address: String, 22 | phone: String, 23 | created_at: DateTime, 24 | updated_at: DateTime, 25 | stripe_id: String, 26 | bulk_action_started_by: Int, 27 | ): customers 28 | 29 | update_customers( 30 | firstname: String, 31 | lastname: String, 32 | address: String, 33 | phone: String, 34 | created_at: DateTime, 35 | updated_at: DateTime, 36 | stripe_id: String, 37 | bulk_action_started_by: Int, 38 | ): customers 39 | 40 | delete_customers(id: ID!): Boolean 41 | } 42 | 43 | type customers { 44 | id: ID! 45 | firstname: String 46 | lastname: String 47 | address: String 48 | phone: String 49 | created_at: DateTime 50 | updated_at: DateTime 51 | stripe_id: String 52 | bulk_action_started_by: Int 53 | } 54 | `; 55 | }; 56 | 57 | this.getResolver = function () { 58 | return { 59 | DateTime: GraphQLDateTime, 60 | JSON: GraphQLJSON, 61 | Query: { 62 | count_customers: async (obj, params) => { 63 | if (!params.filterType) { params.filterType = 'and'; } 64 | if (!params.timezone) { params.timezone = 'Europe/London'; } 65 | 66 | return await new Liana.ResourcesGetter(models.customers, opts, params).count(); 67 | }, 68 | list_customers: async (obj, params) => { 69 | if (!params.filterType) { params.filterType = 'and'; } 70 | if (!params.timezone) { params.timezone = 'Europe/London'; } 71 | 72 | const r = await new Liana.ResourcesGetter(models.customers, opts, params).perform(); 73 | return r[0]; 74 | }, 75 | get_customers: async (obj, { id }, context, info) => { 76 | return await new Liana.ResourceGetter(models.customers, { recordId: id }).perform(); 77 | }, 78 | }, 79 | Mutation: { 80 | create_customers: async (obj, params) => { 81 | return await new Liana.ResourceCreator(models.customers, params).perform(); 82 | }, 83 | update_customers: async (obj, params) => { 84 | return await new Liana.ResourceUpdater(models.customers, { recordId: params.id }, params).perform(); 85 | }, 86 | delete_customers: async (obj, params) => { 87 | return await new Liana.ResourceRemover(models.customers, { recordId: params.id }).perform(); 88 | }, 89 | } 90 | } 91 | }; 92 | } 93 | -------------------------------------------------------------------------------- /example/meals/Meals/graphql/product_images.js: -------------------------------------------------------------------------------- 1 | const gql = require('apollo-server-express').gql; 2 | const models = require('../models'); 3 | const Liana = require('forest-express-sequelize'); 4 | 5 | const { GraphQLDateTime } = require('graphql-iso-date'); 6 | const GraphQLJSON = require('graphql-type-json'); 7 | 8 | module.exports = function (opts) { 9 | this.getSchema = function () { 10 | return gql` 11 | extend type Query { 12 | count_product_images(search: String, filter: JSON): Int 13 | list_product_images(page: JSON, sort: String, search: String, filter: JSON): [product_images!] 14 | get_product_images(id: ID!): product_images 15 | } 16 | 17 | extend type Mutation { 18 | create_product_images( 19 | product_id: Int, 20 | created_at: DateTime, 21 | updated_at: DateTime, 22 | image_file_name: String, 23 | image_content_type: String, 24 | image_file_size: Int, 25 | image_updated_at: DateTime, 26 | ): product_images 27 | 28 | update_product_images( 29 | product_id: Int, 30 | created_at: DateTime, 31 | updated_at: DateTime, 32 | image_file_name: String, 33 | image_content_type: String, 34 | image_file_size: Int, 35 | image_updated_at: DateTime, 36 | ): product_images 37 | 38 | delete_product_images(id: ID!): Boolean 39 | } 40 | 41 | type product_images { 42 | id: ID! 43 | product_id: Int 44 | created_at: DateTime 45 | updated_at: DateTime 46 | image_file_name: String 47 | image_content_type: String 48 | image_file_size: Int 49 | image_updated_at: DateTime 50 | } 51 | `; 52 | }; 53 | 54 | this.getResolver = function () { 55 | return { 56 | DateTime: GraphQLDateTime, 57 | JSON: GraphQLJSON, 58 | Query: { 59 | count_product_images: async (obj, params) => { 60 | if (!params.filterType) { params.filterType = 'and'; } 61 | if (!params.timezone) { params.timezone = 'Europe/London'; } 62 | 63 | return await new Liana.ResourcesGetter(models.product_images, opts, params).count(); 64 | }, 65 | list_product_images: async (obj, params) => { 66 | if (!params.filterType) { params.filterType = 'and'; } 67 | if (!params.timezone) { params.timezone = 'Europe/London'; } 68 | 69 | const r = await new Liana.ResourcesGetter(models.product_images, opts, params).perform(); 70 | return r[0]; 71 | }, 72 | get_product_images: async (obj, { id }, context, info) => { 73 | return await new Liana.ResourceGetter(models.product_images, { recordId: id }).perform(); 74 | }, 75 | }, 76 | Mutation: { 77 | create_product_images: async (obj, params) => { 78 | return await new Liana.ResourceCreator(models.product_images, params).perform(); 79 | }, 80 | update_product_images: async (obj, params) => { 81 | return await new Liana.ResourceUpdater(models.product_images, { recordId: params.id }, params).perform(); 82 | }, 83 | delete_product_images: async (obj, params) => { 84 | return await new Liana.ResourceRemover(models.product_images, { recordId: params.id }).perform(); 85 | }, 86 | } 87 | } 88 | }; 89 | } 90 | -------------------------------------------------------------------------------- /example/meals/Meals/graphql/delivery_men.js: -------------------------------------------------------------------------------- 1 | const gql = require('apollo-server-express').gql; 2 | const models = require('../models'); 3 | const Liana = require('forest-express-sequelize'); 4 | 5 | const { GraphQLDateTime } = require('graphql-iso-date'); 6 | const GraphQLJSON = require('graphql-type-json'); 7 | 8 | module.exports = function (opts) { 9 | this.getSchema = function () { 10 | return gql` 11 | extend type Query { 12 | count_delivery_men(search: String, filter: JSON): Int 13 | list_delivery_men(page: JSON, sort: String, search: String, filter: JSON): [delivery_men!] 14 | get_delivery_men(id: ID!): delivery_men 15 | } 16 | 17 | extend type Mutation { 18 | create_delivery_men( 19 | firstname: String, 20 | lastname: String, 21 | email: String, 22 | phone: String, 23 | location: String, 24 | available: Boolean, 25 | created_at: DateTime, 26 | updated_at: DateTime, 27 | geoloc: String, 28 | ): delivery_men 29 | 30 | update_delivery_men( 31 | firstname: String, 32 | lastname: String, 33 | email: String, 34 | phone: String, 35 | location: String, 36 | available: Boolean, 37 | created_at: DateTime, 38 | updated_at: DateTime, 39 | geoloc: String, 40 | ): delivery_men 41 | 42 | delete_delivery_men(id: ID!): Boolean 43 | } 44 | 45 | type delivery_men { 46 | id: ID! 47 | firstname: String 48 | lastname: String 49 | email: String 50 | phone: String 51 | location: String 52 | available: Boolean 53 | created_at: DateTime 54 | updated_at: DateTime 55 | geoloc: String 56 | } 57 | `; 58 | }; 59 | 60 | this.getResolver = function () { 61 | return { 62 | DateTime: GraphQLDateTime, 63 | JSON: GraphQLJSON, 64 | Query: { 65 | count_delivery_men: async (obj, params) => { 66 | if (!params.filterType) { params.filterType = 'and'; } 67 | if (!params.timezone) { params.timezone = 'Europe/London'; } 68 | 69 | return await new Liana.ResourcesGetter(models.delivery_men, opts, params).count(); 70 | }, 71 | list_delivery_men: async (obj, params) => { 72 | if (!params.filterType) { params.filterType = 'and'; } 73 | if (!params.timezone) { params.timezone = 'Europe/London'; } 74 | 75 | const r = await new Liana.ResourcesGetter(models.delivery_men, opts, params).perform(); 76 | return r[0]; 77 | }, 78 | get_delivery_men: async (obj, { id }, context, info) => { 79 | return await new Liana.ResourceGetter(models.delivery_men, { recordId: id }).perform(); 80 | }, 81 | }, 82 | Mutation: { 83 | create_delivery_men: async (obj, params) => { 84 | return await new Liana.ResourceCreator(models.delivery_men, params).perform(); 85 | }, 86 | update_delivery_men: async (obj, params) => { 87 | return await new Liana.ResourceUpdater(models.delivery_men, { recordId: params.id }, params).perform(); 88 | }, 89 | delete_delivery_men: async (obj, params) => { 90 | return await new Liana.ResourceRemover(models.delivery_men, { recordId: params.id }).perform(); 91 | }, 92 | } 93 | } 94 | }; 95 | } 96 | -------------------------------------------------------------------------------- /example/meals/Meals/graphql/products.js: -------------------------------------------------------------------------------- 1 | const gql = require('apollo-server-express').gql; 2 | const models = require('../models'); 3 | const Liana = require('forest-express-sequelize'); 4 | 5 | const { GraphQLDateTime } = require('graphql-iso-date'); 6 | const GraphQLJSON = require('graphql-type-json'); 7 | 8 | module.exports = function (opts) { 9 | this.getSchema = function () { 10 | return gql` 11 | extend type Query { 12 | count_products(search: String, filter: JSON): Int 13 | list_products(page: JSON, sort: String, search: String, filter: JSON): [products!] 14 | get_products(id: ID!): products 15 | } 16 | 17 | extend type Mutation { 18 | create_products( 19 | title: String, 20 | description: String, 21 | instructions: String, 22 | created_at: DateTime, 23 | updated_at: DateTime, 24 | product_type: Int, 25 | image_file_name: String, 26 | image_content_type: String, 27 | image_file_size: Int, 28 | image_updated_at: DateTime, 29 | price: Float, 30 | ): products 31 | 32 | update_products( 33 | title: String, 34 | description: String, 35 | instructions: String, 36 | created_at: DateTime, 37 | updated_at: DateTime, 38 | product_type: Int, 39 | image_file_name: String, 40 | image_content_type: String, 41 | image_file_size: Int, 42 | image_updated_at: DateTime, 43 | price: Float, 44 | ): products 45 | 46 | delete_products(id: ID!): Boolean 47 | } 48 | 49 | type products { 50 | id: ID! 51 | title: String 52 | description: String 53 | instructions: String 54 | created_at: DateTime 55 | updated_at: DateTime 56 | product_type: Int 57 | image_file_name: String 58 | image_content_type: String 59 | image_file_size: Int 60 | image_updated_at: DateTime 61 | price: Float 62 | } 63 | `; 64 | }; 65 | 66 | this.getResolver = function () { 67 | return { 68 | DateTime: GraphQLDateTime, 69 | JSON: GraphQLJSON, 70 | Query: { 71 | count_products: async (obj, params) => { 72 | if (!params.filterType) { params.filterType = 'and'; } 73 | if (!params.timezone) { params.timezone = 'Europe/London'; } 74 | 75 | return await new Liana.ResourcesGetter(models.products, opts, params).count(); 76 | }, 77 | list_products: async (obj, params) => { 78 | if (!params.filterType) { params.filterType = 'and'; } 79 | if (!params.timezone) { params.timezone = 'Europe/London'; } 80 | 81 | const r = await new Liana.ResourcesGetter(models.products, opts, params).perform(); 82 | return r[0]; 83 | }, 84 | get_products: async (obj, { id }, context, info) => { 85 | return await new Liana.ResourceGetter(models.products, { recordId: id }).perform(); 86 | }, 87 | }, 88 | Mutation: { 89 | create_products: async (obj, params) => { 90 | return await new Liana.ResourceCreator(models.products, params).perform(); 91 | }, 92 | update_products: async (obj, params) => { 93 | return await new Liana.ResourceUpdater(models.products, { recordId: params.id }, params).perform(); 94 | }, 95 | delete_products: async (obj, params) => { 96 | return await new Liana.ResourceRemover(models.products, { recordId: params.id }).perform(); 97 | }, 98 | } 99 | } 100 | }; 101 | } 102 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # GraphQL Stitcher 2 | 3 |

4 | GraphQL Stitcher Logo 5 |

6 | 7 | * [About the Project](#about-the-project) 8 | * [Quickstart](#quickstart) 9 | * [Prerequisites](#prerequisites) 10 | * [Installation](#installation) 11 | * [Usage](#usage) 12 | * [Contributing](#contributing) 13 | * [License](#license) 14 | * [Contact](#contact) 15 | 16 | ## About the project 17 | This project is a **human-friendly** library used to implement the concept GraphQL Schema Stitching. The goal is to stitch together multiple GraphQL schema in a flash. 18 | 19 | A use case could be the need to abstract multiple heterogeneous datasources through a single GraphQL endpoint. This is commonly encountered in large microservices architecture. 20 | 21 | ## Quickstart 22 | 23 | ### Prerequisites 24 | 25 | - NodeJS 26 | - NPM 27 | 28 | ### Installation 29 | 30 | ```sh 31 | npm install graphql-stitcher 32 | ``` 33 | 34 | ### Usage 35 | 36 | ```javascript 37 | const stitcher = new GraphQLStitcher(); 38 | 39 | // "countries" public API 40 | const countrySchema = await stitcher.loadRemoteSchema('https://countries.trevorblades.com'); 41 | 42 | // Github API 43 | const githubSchema = await stitcher.loadRemoteSchema('https://api.github.com/graphql', { 44 | headers: { authorization: `Bearer ${process.env.STRIPE_TOKEN}`, }, 45 | }); 46 | 47 | // Local GraphQL schema 48 | const dbSchema = stitche.loadLocalSchema(__dirname + '/graphql'); 49 | 50 | // Stitch! 51 | const schema = stitcher.stitch(); 52 | 53 | // … … … 54 | 55 | // Example with ApolloServer 56 | const server = new ApolloServer({ schema }); 57 | ``` 58 | 59 | A complete example can be found in the [example/](https://github.com/ForestAdmin/graphql-stitcher/tree/master/example) directory. 60 | 61 | 62 | ### Adding a remote schema 63 | 64 | ```javascript 65 | .loadRemoteSchema(string uri, object opts) -> Promise 66 | ``` 67 | 68 | - uri: the remote location of the GraphQL remote schema. Example: `'https://api.github.com/graphql'` 69 | - opts: (optional) a Javascript Object to pass more options to the HTTP request that will fetch the GraphQL schema. Most of the time, it is used to pass authentication details. Example: 70 | 71 | ```javascript 72 | { headers: { authorization: `Bearer ${process.env.STRIPE_TOKEN}` }} 73 | ``` 74 | 75 | 76 | ### Adding a local schema 77 | 78 | ```javascript 79 | .loadLocalSchema(string directory) -> Object 80 | ``` 81 | 82 | The `loadLocalSchema` function automatically import all files specified under the parameter passed as an argument `directory`. Each file should respect the following syntax: 83 | 84 | ```javascript 85 | module.exports = function () { 86 | this.getSchema = function () { 87 | }; 88 | 89 | this.getResolver = function () { 90 | }; 91 | } 92 | ``` 93 | 94 | A complete example can be found in the [example/](https://github.com/ForestAdmin/graphql-stitcher/tree/master/example) directory. 95 | 96 | ## Contributing 97 | 98 | Contributions are what make the open source community such an amazing place to be learn, inspire, and create. Any contributions you make are greatly appreciated. 99 | 100 | - Fork the Project 101 | - Create your Feature Branch (git checkout -b feature/AmazingFeature) 102 | - Commit your Changes (git commit -m 'Add some AmazingFeature) 103 | - Push to the Branch (git push origin feature/AmazingFeature) 104 | - Open a Pull Request 105 | 106 | ## License 107 | [MIT](https://github.com/ForestAdmin/graphql-stitcher/blob/master/LICENSE) 108 | 109 | ## Contact 110 | This project is currently maintained by [Forest Admin](https://www.forestadmin.com). Don't hesitate to join the Slack community if you have any questions: [http://community.forestadmin.com](http://community.forestadmin.com) 111 | -------------------------------------------------------------------------------- /example/movies/Movies/graphql/movies.js: -------------------------------------------------------------------------------- 1 | const gql = require('apollo-server-express').gql; 2 | const models = require('../models'); 3 | const Liana = require('forest-express-sequelize'); 4 | 5 | const { GraphQLDateTime } = require('graphql-iso-date'); 6 | const GraphQLJSON = require('graphql-type-json'); 7 | 8 | module.exports = function (opts) { 9 | this.getSchema = function () { 10 | return gql` 11 | extend type Query { 12 | count_movies(search: String, filter: JSON): Int 13 | list_movies(page: JSON, sort: String, search: String, filter: JSON): [movies!] 14 | get_movies(id: ID!): movies 15 | } 16 | 17 | extend type Mutation { 18 | create_movies( 19 | imdb_id: String, 20 | title: String, 21 | year: String, 22 | runtime: String, 23 | released: DateTime, 24 | imdb_rating: Float, 25 | imdb_votes: Float, 26 | short_plot: String, 27 | full_plot: String, 28 | language: String, 29 | country: String, 30 | awards: String, 31 | created_at: DateTime, 32 | updated_at: DateTime, 33 | price: Float, 34 | poster_file_name: String, 35 | poster_content_type: String, 36 | poster_file_size: Int, 37 | poster_updated_at: DateTime, 38 | ): movies 39 | 40 | update_movies( 41 | imdb_id: String, 42 | title: String, 43 | year: String, 44 | runtime: String, 45 | released: DateTime, 46 | imdb_rating: Float, 47 | imdb_votes: Float, 48 | short_plot: String, 49 | full_plot: String, 50 | language: String, 51 | country: String, 52 | awards: String, 53 | created_at: DateTime, 54 | updated_at: DateTime, 55 | price: Float, 56 | poster_file_name: String, 57 | poster_content_type: String, 58 | poster_file_size: Int, 59 | poster_updated_at: DateTime, 60 | ): movies 61 | 62 | delete_movies(id: ID!): Boolean 63 | } 64 | 65 | type movies { 66 | id: ID! 67 | imdb_id: String 68 | title: String 69 | year: String 70 | runtime: String 71 | released: DateTime 72 | imdb_rating: Float 73 | imdb_votes: Float 74 | short_plot: String 75 | full_plot: String 76 | language: String 77 | country: String 78 | awards: String 79 | created_at: DateTime 80 | updated_at: DateTime 81 | price: Float 82 | poster_file_name: String 83 | poster_content_type: String 84 | poster_file_size: Int 85 | poster_updated_at: DateTime 86 | } 87 | `; 88 | }; 89 | 90 | this.getResolver = function () { 91 | return { 92 | DateTime: GraphQLDateTime, 93 | JSON: GraphQLJSON, 94 | Query: { 95 | count_movies: async (obj, params) => { 96 | if (!params.filterType) { params.filterType = 'and'; } 97 | if (!params.timezone) { params.timezone = 'Europe/London'; } 98 | 99 | return await new Liana.ResourcesGetter(models.movies, opts, params).count(); 100 | }, 101 | list_movies: async (obj, params) => { 102 | if (!params.filterType) { params.filterType = 'and'; } 103 | if (!params.timezone) { params.timezone = 'Europe/London'; } 104 | 105 | const r = await new Liana.ResourcesGetter(models.movies, opts, params).perform(); 106 | return r[0]; 107 | }, 108 | get_movies: async (obj, { id }, context, info) => { 109 | return await new Liana.ResourceGetter(models.movies, { recordId: id }).perform(); 110 | }, 111 | }, 112 | Mutation: { 113 | create_movies: async (obj, params) => { 114 | return await new Liana.ResourceCreator(models.movies, params).perform(); 115 | }, 116 | update_movies: async (obj, params) => { 117 | return await new Liana.ResourceUpdater(models.movies, { recordId: params.id }, params).perform(); 118 | }, 119 | delete_movies: async (obj, params) => { 120 | return await new Liana.ResourceRemover(models.movies, { recordId: params.id }).perform(); 121 | }, 122 | } 123 | } 124 | }; 125 | } 126 | -------------------------------------------------------------------------------- /example/movies/Movies/graphql/customers.js: -------------------------------------------------------------------------------- 1 | const gql = require('apollo-server-express').gql; 2 | const models = require('../models'); 3 | const Liana = require('forest-express-sequelize'); 4 | 5 | const { GraphQLDateTime } = require('graphql-iso-date'); 6 | const GraphQLJSON = require('graphql-type-json'); 7 | 8 | module.exports = function (opts) { 9 | this.getSchema = function () { 10 | return gql` 11 | extend type Query { 12 | count_customers(search: String, filter: JSON): Int 13 | list_customers(page: JSON, sort: String, search: String, filter: JSON): [customers!] 14 | get_customers(id: ID!): customers 15 | } 16 | 17 | extend type Mutation { 18 | create_customers( 19 | firstname: String, 20 | lastname: String, 21 | email: String, 22 | stripe_id: String, 23 | country: String, 24 | city: String, 25 | street_address: String, 26 | zip_code: String, 27 | state: String, 28 | created_at: DateTime, 29 | updated_at: DateTime, 30 | encrypted_password: String, 31 | reset_password_token: String, 32 | reset_password_sent_at: DateTime, 33 | remember_created_at: DateTime, 34 | sign_in_count: Int, 35 | current_sign_in_at: DateTime, 36 | last_sign_in_at: DateTime, 37 | gender: String, 38 | ): customers 39 | 40 | update_customers( 41 | firstname: String, 42 | lastname: String, 43 | email: String, 44 | stripe_id: String, 45 | country: String, 46 | city: String, 47 | street_address: String, 48 | zip_code: String, 49 | state: String, 50 | created_at: DateTime, 51 | updated_at: DateTime, 52 | encrypted_password: String, 53 | reset_password_token: String, 54 | reset_password_sent_at: DateTime, 55 | remember_created_at: DateTime, 56 | sign_in_count: Int, 57 | current_sign_in_at: DateTime, 58 | last_sign_in_at: DateTime, 59 | gender: String, 60 | ): customers 61 | 62 | delete_customers(id: ID!): Boolean 63 | } 64 | 65 | type customers { 66 | id: ID! 67 | firstname: String 68 | lastname: String 69 | email: String 70 | stripe_id: String 71 | country: String 72 | city: String 73 | street_address: String 74 | zip_code: String 75 | state: String 76 | created_at: DateTime 77 | updated_at: DateTime 78 | encrypted_password: String 79 | reset_password_token: String 80 | reset_password_sent_at: DateTime 81 | remember_created_at: DateTime 82 | sign_in_count: Int 83 | current_sign_in_at: DateTime 84 | last_sign_in_at: DateTime 85 | gender: String 86 | } 87 | `; 88 | }; 89 | 90 | this.getResolver = function () { 91 | return { 92 | DateTime: GraphQLDateTime, 93 | JSON: GraphQLJSON, 94 | Query: { 95 | count_customers: async (obj, params) => { 96 | if (!params.filterType) { params.filterType = 'and'; } 97 | if (!params.timezone) { params.timezone = 'Europe/London'; } 98 | 99 | return await new Liana.ResourcesGetter(models.customers, opts, params).count(); 100 | }, 101 | list_customers: async (obj, params) => { 102 | if (!params.filterType) { params.filterType = 'and'; } 103 | if (!params.timezone) { params.timezone = 'Europe/London'; } 104 | 105 | const r = await new Liana.ResourcesGetter(models.customers, opts, params).perform(); 106 | return r[0]; 107 | }, 108 | get_customers: async (obj, { id }, context, info) => { 109 | return await new Liana.ResourceGetter(models.customers, { recordId: id }).perform(); 110 | }, 111 | }, 112 | Mutation: { 113 | create_customers: async (obj, params) => { 114 | return await new Liana.ResourceCreator(models.customers, params).perform(); 115 | }, 116 | update_customers: async (obj, params) => { 117 | return await new Liana.ResourceUpdater(models.customers, { recordId: params.id }, params).perform(); 118 | }, 119 | delete_customers: async (obj, params) => { 120 | return await new Liana.ResourceRemover(models.customers, { recordId: params.id }).perform(); 121 | }, 122 | } 123 | } 124 | }; 125 | } 126 | -------------------------------------------------------------------------------- /example/api-gateway/package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "api-gateway", 3 | "version": "1.0.0", 4 | "lockfileVersion": 1, 5 | "requires": true, 6 | "dependencies": { 7 | "@apollographql/apollo-tools": { 8 | "version": "0.3.5", 9 | "resolved": "https://registry.npmjs.org/@apollographql/apollo-tools/-/apollo-tools-0.3.5.tgz", 10 | "integrity": "sha512-5ySiiNT2EIwxGKWyoAOnibCPUXvbxKOVxiPMK4uIXmvF+qbGNleQWP+vekciiAmCCESPmGd5szscRwDm4G/NNg==", 11 | "requires": { 12 | "apollo-env": "0.4.0" 13 | } 14 | }, 15 | "@apollographql/graphql-playground-html": { 16 | "version": "1.6.6", 17 | "resolved": "https://registry.npmjs.org/@apollographql/graphql-playground-html/-/graphql-playground-html-1.6.6.tgz", 18 | "integrity": "sha512-lqK94b+caNtmKFs5oUVXlSpN3sm5IXZ+KfhMxOtr0LR2SqErzkoJilitjDvJ1WbjHlxLI7WtCjRmOLdOGJqtMQ==" 19 | }, 20 | "@protobufjs/aspromise": { 21 | "version": "1.1.2", 22 | "resolved": "https://registry.npmjs.org/@protobufjs/aspromise/-/aspromise-1.1.2.tgz", 23 | "integrity": "sha1-m4sMxmPWaafY9vXQiToU00jzD78=" 24 | }, 25 | "@protobufjs/base64": { 26 | "version": "1.1.2", 27 | "resolved": "https://registry.npmjs.org/@protobufjs/base64/-/base64-1.1.2.tgz", 28 | "integrity": "sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==" 29 | }, 30 | "@protobufjs/codegen": { 31 | "version": "2.0.4", 32 | "resolved": "https://registry.npmjs.org/@protobufjs/codegen/-/codegen-2.0.4.tgz", 33 | "integrity": "sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg==" 34 | }, 35 | "@protobufjs/eventemitter": { 36 | "version": "1.1.0", 37 | "resolved": "https://registry.npmjs.org/@protobufjs/eventemitter/-/eventemitter-1.1.0.tgz", 38 | "integrity": "sha1-NVy8mLr61ZePntCV85diHx0Ga3A=" 39 | }, 40 | "@protobufjs/fetch": { 41 | "version": "1.1.0", 42 | "resolved": "https://registry.npmjs.org/@protobufjs/fetch/-/fetch-1.1.0.tgz", 43 | "integrity": "sha1-upn7WYYUr2VwDBYZ/wbUVLDYTEU=", 44 | "requires": { 45 | "@protobufjs/aspromise": "^1.1.1", 46 | "@protobufjs/inquire": "^1.1.0" 47 | } 48 | }, 49 | "@protobufjs/float": { 50 | "version": "1.0.2", 51 | "resolved": "https://registry.npmjs.org/@protobufjs/float/-/float-1.0.2.tgz", 52 | "integrity": "sha1-Xp4avctz/Ap8uLKR33jIy9l7h9E=" 53 | }, 54 | "@protobufjs/inquire": { 55 | "version": "1.1.0", 56 | "resolved": "https://registry.npmjs.org/@protobufjs/inquire/-/inquire-1.1.0.tgz", 57 | "integrity": "sha1-/yAOPnzyQp4tyvwRQIKOjMY48Ik=" 58 | }, 59 | "@protobufjs/path": { 60 | "version": "1.1.2", 61 | "resolved": "https://registry.npmjs.org/@protobufjs/path/-/path-1.1.2.tgz", 62 | "integrity": "sha1-bMKyDFya1q0NzP0hynZz2Nf79o0=" 63 | }, 64 | "@protobufjs/pool": { 65 | "version": "1.1.0", 66 | "resolved": "https://registry.npmjs.org/@protobufjs/pool/-/pool-1.1.0.tgz", 67 | "integrity": "sha1-Cf0V8tbTq/qbZbw2ZQbWrXhG/1Q=" 68 | }, 69 | "@protobufjs/utf8": { 70 | "version": "1.1.0", 71 | "resolved": "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.0.tgz", 72 | "integrity": "sha1-p3c2C1s5oaLlEG+OhY8v0tBgxXA=" 73 | }, 74 | "@types/accepts": { 75 | "version": "1.3.5", 76 | "resolved": "https://registry.npmjs.org/@types/accepts/-/accepts-1.3.5.tgz", 77 | "integrity": "sha512-jOdnI/3qTpHABjM5cx1Hc0sKsPoYCp+DP/GJRGtDlPd7fiV9oXGGIcjW/ZOxLIvjGz8MA+uMZI9metHlgqbgwQ==", 78 | "requires": { 79 | "@types/node": "*" 80 | } 81 | }, 82 | "@types/body-parser": { 83 | "version": "1.17.0", 84 | "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.17.0.tgz", 85 | "integrity": "sha512-a2+YeUjPkztKJu5aIF2yArYFQQp8d51wZ7DavSHjFuY1mqVgidGyzEQ41JIVNy82fXj8yPgy2vJmfIywgESW6w==", 86 | "requires": { 87 | "@types/connect": "*", 88 | "@types/node": "*" 89 | } 90 | }, 91 | "@types/connect": { 92 | "version": "3.4.32", 93 | "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.32.tgz", 94 | "integrity": "sha512-4r8qa0quOvh7lGD0pre62CAb1oni1OO6ecJLGCezTmhQ8Fz50Arx9RUszryR8KlgK6avuSXvviL6yWyViQABOg==", 95 | "requires": { 96 | "@types/node": "*" 97 | } 98 | }, 99 | "@types/cors": { 100 | "version": "2.8.4", 101 | "resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.4.tgz", 102 | "integrity": "sha512-ipZjBVsm2tF/n8qFGOuGBkUij9X9ZswVi9G3bx/6dz7POpVa6gVHcj1wsX/LVEn9MMF41fxK/PnZPPoTD1UFPw==", 103 | "requires": { 104 | "@types/express": "*" 105 | } 106 | }, 107 | "@types/events": { 108 | "version": "3.0.0", 109 | "resolved": "https://registry.npmjs.org/@types/events/-/events-3.0.0.tgz", 110 | "integrity": "sha512-EaObqwIvayI5a8dCzhFrjKzVwKLxjoG9T6Ppd5CEo07LRKfQ8Yokw54r5+Wq7FaBQ+yXRvQAYPrHwya1/UFt9g==" 111 | }, 112 | "@types/express": { 113 | "version": "4.16.1", 114 | "resolved": "https://registry.npmjs.org/@types/express/-/express-4.16.1.tgz", 115 | "integrity": "sha512-V0clmJow23WeyblmACoxbHBu2JKlE5TiIme6Lem14FnPW9gsttyHtk6wq7njcdIWH1njAaFgR8gW09lgY98gQg==", 116 | "requires": { 117 | "@types/body-parser": "*", 118 | "@types/express-serve-static-core": "*", 119 | "@types/serve-static": "*" 120 | } 121 | }, 122 | "@types/express-serve-static-core": { 123 | "version": "4.16.2", 124 | "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.16.2.tgz", 125 | "integrity": "sha512-qgc8tjnDrc789rAQed8NoiFLV5VGcItA4yWNFphqGU0RcuuQngD00g3LHhWIK3HQ2XeDgVCmlNPDlqi3fWBHnQ==", 126 | "requires": { 127 | "@types/node": "*", 128 | "@types/range-parser": "*" 129 | } 130 | }, 131 | "@types/long": { 132 | "version": "4.0.0", 133 | "resolved": "https://registry.npmjs.org/@types/long/-/long-4.0.0.tgz", 134 | "integrity": "sha512-1w52Nyx4Gq47uuu0EVcsHBxZFJgurQ+rTKS3qMHxR1GY2T8c2AJYd6vZoZ9q1rupaDjU0yT+Jc2XTyXkjeMA+Q==" 135 | }, 136 | "@types/mime": { 137 | "version": "2.0.1", 138 | "resolved": "https://registry.npmjs.org/@types/mime/-/mime-2.0.1.tgz", 139 | "integrity": "sha512-FwI9gX75FgVBJ7ywgnq/P7tw+/o1GUbtP0KzbtusLigAOgIgNISRK0ZPl4qertvXSIE8YbsVJueQ90cDt9YYyw==" 140 | }, 141 | "@types/node": { 142 | "version": "11.13.0", 143 | "resolved": "https://registry.npmjs.org/@types/node/-/node-11.13.0.tgz", 144 | "integrity": "sha512-rx29MMkRdVmzunmiA4lzBYJNnXsW/PhG4kMBy2ATsYaDjGGR75dCFEVVROKpNwlVdcUX3xxlghKQOeDPBJobng==" 145 | }, 146 | "@types/range-parser": { 147 | "version": "1.2.3", 148 | "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.3.tgz", 149 | "integrity": "sha512-ewFXqrQHlFsgc09MK5jP5iR7vumV/BYayNC6PgJO2LPe8vrnNFyjQjSppfEngITi0qvfKtzFvgKymGheFM9UOA==" 150 | }, 151 | "@types/serve-static": { 152 | "version": "1.13.2", 153 | "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.13.2.tgz", 154 | "integrity": "sha512-/BZ4QRLpH/bNYgZgwhKEh+5AsboDBcUdlBYgzoLX0fpj3Y2gp6EApyOlM3bK53wQS/OE1SrdSYBAbux2D1528Q==", 155 | "requires": { 156 | "@types/express-serve-static-core": "*", 157 | "@types/mime": "*" 158 | } 159 | }, 160 | "@types/ws": { 161 | "version": "6.0.1", 162 | "resolved": "https://registry.npmjs.org/@types/ws/-/ws-6.0.1.tgz", 163 | "integrity": "sha512-EzH8k1gyZ4xih/MaZTXwT2xOkPiIMSrhQ9b8wrlX88L0T02eYsddatQlwVFlEPyEqV0ChpdpNnE51QPH6NVT4Q==", 164 | "requires": { 165 | "@types/events": "*", 166 | "@types/node": "*" 167 | } 168 | }, 169 | "accepts": { 170 | "version": "1.3.5", 171 | "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.5.tgz", 172 | "integrity": "sha1-63d99gEXI6OxTopywIBcjoZ0a9I=", 173 | "requires": { 174 | "mime-types": "~2.1.18", 175 | "negotiator": "0.6.1" 176 | } 177 | }, 178 | "apollo-cache-control": { 179 | "version": "0.5.2", 180 | "resolved": "https://registry.npmjs.org/apollo-cache-control/-/apollo-cache-control-0.5.2.tgz", 181 | "integrity": "sha512-uehXDUrd3Qim+nzxqqN7XT1YTbNSyumW3/FY5BxbKZTI8d4oPG4eyVQKqaggooSjswKQnOoIQVes3+qg9tGAkw==", 182 | "requires": { 183 | "apollo-server-env": "2.2.0", 184 | "graphql-extensions": "0.5.4" 185 | }, 186 | "dependencies": { 187 | "graphql-extensions": { 188 | "version": "0.5.4", 189 | "resolved": "https://registry.npmjs.org/graphql-extensions/-/graphql-extensions-0.5.4.tgz", 190 | "integrity": "sha512-qLThJGVMqcItE7GDf/xX/E40m/aeqFheEKiR5bfra4q5eHxQKGjnIc20P9CVqjOn9I0FkEiU9ypOobfmIf7t6g==", 191 | "requires": { 192 | "@apollographql/apollo-tools": "^0.3.3" 193 | } 194 | } 195 | } 196 | }, 197 | "apollo-datasource": { 198 | "version": "0.3.1", 199 | "resolved": "https://registry.npmjs.org/apollo-datasource/-/apollo-datasource-0.3.1.tgz", 200 | "integrity": "sha512-qdEUeonc9pPZvYwXK36h2NZoT7Pddmy0HYOzdV0ON5pcG1YtNmUyyYi83Q60V5wTWjuaCjyJ9hOY6wr0BMvQuA==", 201 | "requires": { 202 | "apollo-server-caching": "0.3.1", 203 | "apollo-server-env": "2.2.0" 204 | } 205 | }, 206 | "apollo-engine-reporting": { 207 | "version": "1.0.7", 208 | "resolved": "https://registry.npmjs.org/apollo-engine-reporting/-/apollo-engine-reporting-1.0.7.tgz", 209 | "integrity": "sha512-mFsXvd+1/o5jSa9tI2RoXYGcvCLcwwcfLwchjSTxqUd4ViB8RbqYKynzEZ+Omji7PBRM0azioBm43f7PSsQPqA==", 210 | "requires": { 211 | "apollo-engine-reporting-protobuf": "0.2.1", 212 | "apollo-graphql": "^0.1.0", 213 | "apollo-server-core": "2.4.8", 214 | "apollo-server-env": "2.2.0", 215 | "async-retry": "^1.2.1", 216 | "graphql-extensions": "0.5.7" 217 | } 218 | }, 219 | "apollo-engine-reporting-protobuf": { 220 | "version": "0.2.1", 221 | "resolved": "https://registry.npmjs.org/apollo-engine-reporting-protobuf/-/apollo-engine-reporting-protobuf-0.2.1.tgz", 222 | "integrity": "sha512-5pYR84uWeylRS2OJowtkTczT3bWTwOErWtfnkRKccUi/wZ/AZJBP+D5HKNzM7xoFcz9XvrJyS+wBTz1oBi0Jiw==", 223 | "requires": { 224 | "protobufjs": "^6.8.6" 225 | } 226 | }, 227 | "apollo-env": { 228 | "version": "0.4.0", 229 | "resolved": "https://registry.npmjs.org/apollo-env/-/apollo-env-0.4.0.tgz", 230 | "integrity": "sha512-TZpk59RTbXd8cEqwmI0KHFoRrgBRplvPAP4bbRrX4uDSxXvoiY0Y6tQYUlJ35zi398Hob45mXfrZxeRDzoFMkQ==", 231 | "requires": { 232 | "core-js": "3.0.0-beta.13", 233 | "node-fetch": "^2.2.0", 234 | "sha.js": "^2.4.11" 235 | } 236 | }, 237 | "apollo-graphql": { 238 | "version": "0.1.3", 239 | "resolved": "https://registry.npmjs.org/apollo-graphql/-/apollo-graphql-0.1.3.tgz", 240 | "integrity": "sha512-bYgDh71jFfHKO9ioGlxnnoSYgpNp6LRl+/QHTx6tktQEN0Z+AdpkOKFNCHO/pRU/4vSqV5wuIhxhnCecxJQrMA==", 241 | "requires": { 242 | "apollo-env": "0.4.0", 243 | "lodash.sortby": "^4.7.0" 244 | } 245 | }, 246 | "apollo-link": { 247 | "version": "1.2.11", 248 | "resolved": "https://registry.npmjs.org/apollo-link/-/apollo-link-1.2.11.tgz", 249 | "integrity": "sha512-PQvRCg13VduLy3X/0L79M6uOpTh5iHdxnxYuo8yL7sJlWybKRJwsv4IcRBJpMFbChOOaHY7Og9wgPo6DLKDKDA==", 250 | "requires": { 251 | "apollo-utilities": "^1.2.1", 252 | "ts-invariant": "^0.3.2", 253 | "tslib": "^1.9.3", 254 | "zen-observable-ts": "^0.8.18" 255 | } 256 | }, 257 | "apollo-link-http": { 258 | "version": "1.5.14", 259 | "resolved": "https://registry.npmjs.org/apollo-link-http/-/apollo-link-http-1.5.14.tgz", 260 | "integrity": "sha512-XEoPXmGpxFG3wioovgAlPXIarWaW4oWzt8YzjTYZ87R4R7d1A3wKR/KcvkdMV1m5G7YSAHcNkDLe/8hF2nH6cg==", 261 | "requires": { 262 | "apollo-link": "^1.2.11", 263 | "apollo-link-http-common": "^0.2.13", 264 | "tslib": "^1.9.3" 265 | } 266 | }, 267 | "apollo-link-http-common": { 268 | "version": "0.2.13", 269 | "resolved": "https://registry.npmjs.org/apollo-link-http-common/-/apollo-link-http-common-0.2.13.tgz", 270 | "integrity": "sha512-Uyg1ECQpTTA691Fwx5e6Rc/6CPSu4TB4pQRTGIpwZ4l5JDOQ+812Wvi/e3IInmzOZpwx5YrrOfXrtN8BrsDXoA==", 271 | "requires": { 272 | "apollo-link": "^1.2.11", 273 | "ts-invariant": "^0.3.2", 274 | "tslib": "^1.9.3" 275 | } 276 | }, 277 | "apollo-server-caching": { 278 | "version": "0.3.1", 279 | "resolved": "https://registry.npmjs.org/apollo-server-caching/-/apollo-server-caching-0.3.1.tgz", 280 | "integrity": "sha512-mfxzikYXbB/OoEms77AGYwRh7FF3Oim5v5XWAL+VL49FrkbZt5lopVa4bABi7Mz8Nt3Htl9EBJN8765s/yh8IA==", 281 | "requires": { 282 | "lru-cache": "^5.0.0" 283 | } 284 | }, 285 | "apollo-server-core": { 286 | "version": "2.4.8", 287 | "resolved": "https://registry.npmjs.org/apollo-server-core/-/apollo-server-core-2.4.8.tgz", 288 | "integrity": "sha512-N+5UOzHhMOnHizEiArJtNvEe/cGhSHQyTn5tlU4RJ36FDBJ/WlYZfPbGDMLISSUCJ6t+aP8GLL4Mnudt9d2PDQ==", 289 | "requires": { 290 | "@apollographql/apollo-tools": "^0.3.3", 291 | "@apollographql/graphql-playground-html": "^1.6.6", 292 | "@types/ws": "^6.0.0", 293 | "apollo-cache-control": "0.5.2", 294 | "apollo-datasource": "0.3.1", 295 | "apollo-engine-reporting": "1.0.7", 296 | "apollo-server-caching": "0.3.1", 297 | "apollo-server-env": "2.2.0", 298 | "apollo-server-errors": "2.2.1", 299 | "apollo-server-plugin-base": "0.3.7", 300 | "apollo-tracing": "0.5.2", 301 | "fast-json-stable-stringify": "^2.0.0", 302 | "graphql-extensions": "0.5.7", 303 | "graphql-subscriptions": "^1.0.0", 304 | "graphql-tag": "^2.9.2", 305 | "graphql-tools": "^4.0.0", 306 | "graphql-upload": "^8.0.2", 307 | "sha.js": "^2.4.11", 308 | "subscriptions-transport-ws": "^0.9.11", 309 | "ws": "^6.0.0" 310 | } 311 | }, 312 | "apollo-server-env": { 313 | "version": "2.2.0", 314 | "resolved": "https://registry.npmjs.org/apollo-server-env/-/apollo-server-env-2.2.0.tgz", 315 | "integrity": "sha512-wjJiI5nQWPBpNmpiLP389Ezpstp71szS6DHAeTgYLb/ulCw3CTuuA+0/E1bsThVWiQaDeHZE0sE3yI8q2zrYiA==", 316 | "requires": { 317 | "node-fetch": "^2.1.2", 318 | "util.promisify": "^1.0.0" 319 | } 320 | }, 321 | "apollo-server-errors": { 322 | "version": "2.2.1", 323 | "resolved": "https://registry.npmjs.org/apollo-server-errors/-/apollo-server-errors-2.2.1.tgz", 324 | "integrity": "sha512-wY/YE3iJVMYC+WYIf8QODBjIP4jhI+oc7kiYo9mrz7LdYPKAgxr/he+NteGcqn/0Ea9K5/ZFTGJDbEstSMeP8g==" 325 | }, 326 | "apollo-server-express": { 327 | "version": "2.4.8", 328 | "resolved": "https://registry.npmjs.org/apollo-server-express/-/apollo-server-express-2.4.8.tgz", 329 | "integrity": "sha512-i60l32mfVe33jnKDPNYgUKUKu4Al0xEm2HLOSMgtJ9Wbpe/MbOx5X8M5F27fnHYdM+G5XfAErsakAyRGnQJ48Q==", 330 | "requires": { 331 | "@apollographql/graphql-playground-html": "^1.6.6", 332 | "@types/accepts": "^1.3.5", 333 | "@types/body-parser": "1.17.0", 334 | "@types/cors": "^2.8.4", 335 | "@types/express": "4.16.1", 336 | "accepts": "^1.3.5", 337 | "apollo-server-core": "2.4.8", 338 | "body-parser": "^1.18.3", 339 | "cors": "^2.8.4", 340 | "graphql-subscriptions": "^1.0.0", 341 | "graphql-tools": "^4.0.0", 342 | "type-is": "^1.6.16" 343 | } 344 | }, 345 | "apollo-server-plugin-base": { 346 | "version": "0.3.7", 347 | "resolved": "https://registry.npmjs.org/apollo-server-plugin-base/-/apollo-server-plugin-base-0.3.7.tgz", 348 | "integrity": "sha512-hW1jaLKf9qNOxMTwRq2CSqz3eqXsZuEiCc8/mmEtOciiVBq1GMtxFf19oIYM9HQuPvQU2RWpns1VrYN59L3vbg==" 349 | }, 350 | "apollo-tracing": { 351 | "version": "0.5.2", 352 | "resolved": "https://registry.npmjs.org/apollo-tracing/-/apollo-tracing-0.5.2.tgz", 353 | "integrity": "sha512-2FdwRvPIq9uuF6OzONroXep6VBGqzHOkP6LlcFQe7SdwxfRP+SD/ycHNSC1acVg2b8d+am9Kzqg2vV54UpOIKA==", 354 | "requires": { 355 | "apollo-server-env": "2.2.0", 356 | "graphql-extensions": "0.5.4" 357 | }, 358 | "dependencies": { 359 | "graphql-extensions": { 360 | "version": "0.5.4", 361 | "resolved": "https://registry.npmjs.org/graphql-extensions/-/graphql-extensions-0.5.4.tgz", 362 | "integrity": "sha512-qLThJGVMqcItE7GDf/xX/E40m/aeqFheEKiR5bfra4q5eHxQKGjnIc20P9CVqjOn9I0FkEiU9ypOobfmIf7t6g==", 363 | "requires": { 364 | "@apollographql/apollo-tools": "^0.3.3" 365 | } 366 | } 367 | } 368 | }, 369 | "apollo-utilities": { 370 | "version": "1.2.1", 371 | "resolved": "https://registry.npmjs.org/apollo-utilities/-/apollo-utilities-1.2.1.tgz", 372 | "integrity": "sha512-Zv8Udp9XTSFiN8oyXOjf6PMHepD4yxxReLsl6dPUy5Ths7jti3nmlBzZUOxuTWRwZn0MoclqL7RQ5UEJN8MAxg==", 373 | "requires": { 374 | "fast-json-stable-stringify": "^2.0.0", 375 | "ts-invariant": "^0.2.1", 376 | "tslib": "^1.9.3" 377 | }, 378 | "dependencies": { 379 | "ts-invariant": { 380 | "version": "0.2.1", 381 | "resolved": "https://registry.npmjs.org/ts-invariant/-/ts-invariant-0.2.1.tgz", 382 | "integrity": "sha512-Z/JSxzVmhTo50I+LKagEISFJW3pvPCqsMWLamCTX8Kr3N5aMrnGOqcflbe5hLUzwjvgPfnLzQtHZv0yWQ+FIHg==", 383 | "requires": { 384 | "tslib": "^1.9.3" 385 | } 386 | } 387 | } 388 | }, 389 | "array-flatten": { 390 | "version": "1.1.1", 391 | "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", 392 | "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=" 393 | }, 394 | "async-limiter": { 395 | "version": "1.0.0", 396 | "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.0.tgz", 397 | "integrity": "sha512-jp/uFnooOiO+L211eZOoSyzpOITMXx1rBITauYykG3BRYPu8h0UcxsPNB04RR5vo4Tyz3+ay17tR6JVf9qzYWg==" 398 | }, 399 | "async-retry": { 400 | "version": "1.2.3", 401 | "resolved": "https://registry.npmjs.org/async-retry/-/async-retry-1.2.3.tgz", 402 | "integrity": "sha512-tfDb02Th6CE6pJUF2gjW5ZVjsgwlucVXOEQMvEX9JgSJMs9gAX+Nz3xRuJBKuUYjTSYORqvDBORdAQ3LU59g7Q==", 403 | "requires": { 404 | "retry": "0.12.0" 405 | } 406 | }, 407 | "backo2": { 408 | "version": "1.0.2", 409 | "resolved": "https://registry.npmjs.org/backo2/-/backo2-1.0.2.tgz", 410 | "integrity": "sha1-MasayLEpNjRj41s+u2n038+6eUc=" 411 | }, 412 | "body-parser": { 413 | "version": "1.18.3", 414 | "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.18.3.tgz", 415 | "integrity": "sha1-WykhmP/dVTs6DyDe0FkrlWlVyLQ=", 416 | "requires": { 417 | "bytes": "3.0.0", 418 | "content-type": "~1.0.4", 419 | "debug": "2.6.9", 420 | "depd": "~1.1.2", 421 | "http-errors": "~1.6.3", 422 | "iconv-lite": "0.4.23", 423 | "on-finished": "~2.3.0", 424 | "qs": "6.5.2", 425 | "raw-body": "2.3.3", 426 | "type-is": "~1.6.16" 427 | }, 428 | "dependencies": { 429 | "http-errors": { 430 | "version": "1.6.3", 431 | "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", 432 | "integrity": "sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0=", 433 | "requires": { 434 | "depd": "~1.1.2", 435 | "inherits": "2.0.3", 436 | "setprototypeof": "1.1.0", 437 | "statuses": ">= 1.4.0 < 2" 438 | } 439 | }, 440 | "setprototypeof": { 441 | "version": "1.1.0", 442 | "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz", 443 | "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==" 444 | } 445 | } 446 | }, 447 | "busboy": { 448 | "version": "0.3.0", 449 | "resolved": "https://registry.npmjs.org/busboy/-/busboy-0.3.0.tgz", 450 | "integrity": "sha512-e+kzZRAbbvJPLjQz2z+zAyr78BSi9IFeBTyLwF76g78Q2zRt/RZ1NtS3MS17v2yLqYfLz69zHdC+1L4ja8PwqQ==", 451 | "requires": { 452 | "dicer": "0.3.0" 453 | } 454 | }, 455 | "bytes": { 456 | "version": "3.0.0", 457 | "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", 458 | "integrity": "sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg=" 459 | }, 460 | "content-disposition": { 461 | "version": "0.5.2", 462 | "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.2.tgz", 463 | "integrity": "sha1-DPaLud318r55YcOoUXjLhdunjLQ=" 464 | }, 465 | "content-type": { 466 | "version": "1.0.4", 467 | "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", 468 | "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==" 469 | }, 470 | "cookie": { 471 | "version": "0.3.1", 472 | "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.3.1.tgz", 473 | "integrity": "sha1-5+Ch+e9DtMi6klxcWpboBtFoc7s=" 474 | }, 475 | "cookie-signature": { 476 | "version": "1.0.6", 477 | "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", 478 | "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=" 479 | }, 480 | "core-js": { 481 | "version": "3.0.0-beta.13", 482 | "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.0.0-beta.13.tgz", 483 | "integrity": "sha512-16Q43c/3LT9NyePUJKL8nRIQgYWjcBhjJSMWg96PVSxoS0PeE0NHitPI3opBrs9MGGHjte1KoEVr9W63YKlTXQ==" 484 | }, 485 | "cors": { 486 | "version": "2.8.5", 487 | "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", 488 | "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==", 489 | "requires": { 490 | "object-assign": "^4", 491 | "vary": "^1" 492 | } 493 | }, 494 | "debug": { 495 | "version": "2.6.9", 496 | "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", 497 | "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", 498 | "requires": { 499 | "ms": "2.0.0" 500 | } 501 | }, 502 | "define-properties": { 503 | "version": "1.1.3", 504 | "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", 505 | "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", 506 | "requires": { 507 | "object-keys": "^1.0.12" 508 | } 509 | }, 510 | "depd": { 511 | "version": "1.1.2", 512 | "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", 513 | "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=" 514 | }, 515 | "deprecated-decorator": { 516 | "version": "0.1.6", 517 | "resolved": "https://registry.npmjs.org/deprecated-decorator/-/deprecated-decorator-0.1.6.tgz", 518 | "integrity": "sha1-AJZjF7ehL+kvPMgx91g68ym4bDc=" 519 | }, 520 | "destroy": { 521 | "version": "1.0.4", 522 | "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", 523 | "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=" 524 | }, 525 | "dicer": { 526 | "version": "0.3.0", 527 | "resolved": "https://registry.npmjs.org/dicer/-/dicer-0.3.0.tgz", 528 | "integrity": "sha512-MdceRRWqltEG2dZqO769g27N/3PXfcKl04VhYnBlo2YhH7zPi88VebsjTKclaOyiuMaGU72hTfw3VkUitGcVCA==", 529 | "requires": { 530 | "streamsearch": "0.1.2" 531 | } 532 | }, 533 | "ee-first": { 534 | "version": "1.1.1", 535 | "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", 536 | "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" 537 | }, 538 | "encodeurl": { 539 | "version": "1.0.2", 540 | "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", 541 | "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=" 542 | }, 543 | "es-abstract": { 544 | "version": "1.13.0", 545 | "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.13.0.tgz", 546 | "integrity": "sha512-vDZfg/ykNxQVwup/8E1BZhVzFfBxs9NqMzGcvIJrqg5k2/5Za2bWo40dK2J1pgLngZ7c+Shh8lwYtLGyrwPutg==", 547 | "requires": { 548 | "es-to-primitive": "^1.2.0", 549 | "function-bind": "^1.1.1", 550 | "has": "^1.0.3", 551 | "is-callable": "^1.1.4", 552 | "is-regex": "^1.0.4", 553 | "object-keys": "^1.0.12" 554 | } 555 | }, 556 | "es-to-primitive": { 557 | "version": "1.2.0", 558 | "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.0.tgz", 559 | "integrity": "sha512-qZryBOJjV//LaxLTV6UC//WewneB3LcXOL9NP++ozKVXsIIIpm/2c13UDiD9Jp2eThsecw9m3jPqDwTyobcdbg==", 560 | "requires": { 561 | "is-callable": "^1.1.4", 562 | "is-date-object": "^1.0.1", 563 | "is-symbol": "^1.0.2" 564 | } 565 | }, 566 | "escape-html": { 567 | "version": "1.0.3", 568 | "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", 569 | "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=" 570 | }, 571 | "etag": { 572 | "version": "1.8.1", 573 | "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", 574 | "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=" 575 | }, 576 | "eventemitter3": { 577 | "version": "3.1.0", 578 | "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-3.1.0.tgz", 579 | "integrity": "sha512-ivIvhpq/Y0uSjcHDcOIccjmYjGLcP09MFGE7ysAwkAvkXfpZlC985pH2/ui64DKazbTW/4kN3yqozUxlXzI6cA==" 580 | }, 581 | "express": { 582 | "version": "4.16.4", 583 | "resolved": "https://registry.npmjs.org/express/-/express-4.16.4.tgz", 584 | "integrity": "sha512-j12Uuyb4FMrd/qQAm6uCHAkPtO8FDTRJZBDd5D2KOL2eLaz1yUNdUB/NOIyq0iU4q4cFarsUCrnFDPBcnksuOg==", 585 | "requires": { 586 | "accepts": "~1.3.5", 587 | "array-flatten": "1.1.1", 588 | "body-parser": "1.18.3", 589 | "content-disposition": "0.5.2", 590 | "content-type": "~1.0.4", 591 | "cookie": "0.3.1", 592 | "cookie-signature": "1.0.6", 593 | "debug": "2.6.9", 594 | "depd": "~1.1.2", 595 | "encodeurl": "~1.0.2", 596 | "escape-html": "~1.0.3", 597 | "etag": "~1.8.1", 598 | "finalhandler": "1.1.1", 599 | "fresh": "0.5.2", 600 | "merge-descriptors": "1.0.1", 601 | "methods": "~1.1.2", 602 | "on-finished": "~2.3.0", 603 | "parseurl": "~1.3.2", 604 | "path-to-regexp": "0.1.7", 605 | "proxy-addr": "~2.0.4", 606 | "qs": "6.5.2", 607 | "range-parser": "~1.2.0", 608 | "safe-buffer": "5.1.2", 609 | "send": "0.16.2", 610 | "serve-static": "1.13.2", 611 | "setprototypeof": "1.1.0", 612 | "statuses": "~1.4.0", 613 | "type-is": "~1.6.16", 614 | "utils-merge": "1.0.1", 615 | "vary": "~1.1.2" 616 | }, 617 | "dependencies": { 618 | "setprototypeof": { 619 | "version": "1.1.0", 620 | "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz", 621 | "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==" 622 | }, 623 | "statuses": { 624 | "version": "1.4.0", 625 | "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.4.0.tgz", 626 | "integrity": "sha512-zhSCtt8v2NDrRlPQpCNtw/heZLtfUDqxBM1udqikb/Hbk52LK4nQSwr10u77iopCW5LsyHpuXS0GnEc48mLeew==" 627 | } 628 | } 629 | }, 630 | "fast-json-stable-stringify": { 631 | "version": "2.0.0", 632 | "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz", 633 | "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=" 634 | }, 635 | "finalhandler": { 636 | "version": "1.1.1", 637 | "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.1.tgz", 638 | "integrity": "sha512-Y1GUDo39ez4aHAw7MysnUD5JzYX+WaIj8I57kO3aEPT1fFRL4sr7mjei97FgnwhAyyzRYmQZaTHb2+9uZ1dPtg==", 639 | "requires": { 640 | "debug": "2.6.9", 641 | "encodeurl": "~1.0.2", 642 | "escape-html": "~1.0.3", 643 | "on-finished": "~2.3.0", 644 | "parseurl": "~1.3.2", 645 | "statuses": "~1.4.0", 646 | "unpipe": "~1.0.0" 647 | }, 648 | "dependencies": { 649 | "statuses": { 650 | "version": "1.4.0", 651 | "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.4.0.tgz", 652 | "integrity": "sha512-zhSCtt8v2NDrRlPQpCNtw/heZLtfUDqxBM1udqikb/Hbk52LK4nQSwr10u77iopCW5LsyHpuXS0GnEc48mLeew==" 653 | } 654 | } 655 | }, 656 | "forwarded": { 657 | "version": "0.1.2", 658 | "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.2.tgz", 659 | "integrity": "sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ=" 660 | }, 661 | "fresh": { 662 | "version": "0.5.2", 663 | "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", 664 | "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=" 665 | }, 666 | "fs-capacitor": { 667 | "version": "2.0.1", 668 | "resolved": "https://registry.npmjs.org/fs-capacitor/-/fs-capacitor-2.0.1.tgz", 669 | "integrity": "sha512-kyV2oaG1/pu9NPosfGACmBym6okgzyg6hEtA5LSUq0dGpGLe278MVfMwVnSHDA/OBcTCHkPNqWL9eIwbPN6dDg==" 670 | }, 671 | "function-bind": { 672 | "version": "1.1.1", 673 | "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", 674 | "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" 675 | }, 676 | "graphql": { 677 | "version": "14.2.1", 678 | "resolved": "https://registry.npmjs.org/graphql/-/graphql-14.2.1.tgz", 679 | "integrity": "sha512-2PL1UbvKeSjy/lUeJqHk+eR9CvuErXoCNwJI4jm3oNFEeY+9ELqHNKO1ZuSxAkasPkpWbmT/iMRMFxd3cEL3tQ==", 680 | "requires": { 681 | "iterall": "^1.2.2" 682 | } 683 | }, 684 | "graphql-extensions": { 685 | "version": "0.5.7", 686 | "resolved": "https://registry.npmjs.org/graphql-extensions/-/graphql-extensions-0.5.7.tgz", 687 | "integrity": "sha512-HrU6APE1PiehZ46scMB3S5DezSeCATd8v+e4mmg2bqszMyCFkmAnmK6hR1b5VjHxhzt5/FX21x1WsXfqF4FwdQ==", 688 | "requires": { 689 | "@apollographql/apollo-tools": "^0.3.3" 690 | } 691 | }, 692 | "graphql-stitcher": { 693 | "version": "0.0.2-beta.3", 694 | "resolved": "https://registry.npmjs.org/graphql-stitcher/-/graphql-stitcher-0.0.2-beta.3.tgz", 695 | "integrity": "sha512-xEm4hUeO3IxEU/BoxSWQMmrFrSlwVPmHL184IOTE3VHmW5qp7sFk4jW40wvFbF99+5mEjfgPeJiktTJAFQsQFA==", 696 | "requires": { 697 | "apollo-link-http": "^1.5.14", 698 | "graphql": "^14.0.0", 699 | "graphql-tag": "^2.10.1", 700 | "graphql-tools": "^4.0.4", 701 | "node-fetch": "^2.3.0" 702 | } 703 | }, 704 | "graphql-subscriptions": { 705 | "version": "1.0.0", 706 | "resolved": "https://registry.npmjs.org/graphql-subscriptions/-/graphql-subscriptions-1.0.0.tgz", 707 | "integrity": "sha512-+ytmryoHF1LVf58NKEaNPRUzYyXplm120ntxfPcgOBC7TnK7Tv/4VRHeh4FAR9iL+O1bqhZs4nkibxQ+OA5cDQ==", 708 | "requires": { 709 | "iterall": "^1.2.1" 710 | } 711 | }, 712 | "graphql-tag": { 713 | "version": "2.10.1", 714 | "resolved": "https://registry.npmjs.org/graphql-tag/-/graphql-tag-2.10.1.tgz", 715 | "integrity": "sha512-jApXqWBzNXQ8jYa/HLkZJaVw9jgwNqZkywa2zfFn16Iv1Zb7ELNHkJaXHR7Quvd5SIGsy6Ny7SUKATgnu05uEg==" 716 | }, 717 | "graphql-tools": { 718 | "version": "4.0.4", 719 | "resolved": "https://registry.npmjs.org/graphql-tools/-/graphql-tools-4.0.4.tgz", 720 | "integrity": "sha512-chF12etTIGVVGy3fCTJ1ivJX2KB7OSG4c6UOJQuqOHCmBQwTyNgCDuejZKvpYxNZiEx7bwIjrodDgDe9RIkjlw==", 721 | "requires": { 722 | "apollo-link": "^1.2.3", 723 | "apollo-utilities": "^1.0.1", 724 | "deprecated-decorator": "^0.1.6", 725 | "iterall": "^1.1.3", 726 | "uuid": "^3.1.0" 727 | } 728 | }, 729 | "graphql-upload": { 730 | "version": "8.0.4", 731 | "resolved": "https://registry.npmjs.org/graphql-upload/-/graphql-upload-8.0.4.tgz", 732 | "integrity": "sha512-jsTfVYXJ5mU6BXiiJ20CUCAcf41ICCQJ2ltwQFUuaFKiY4JhlG99uZZp5S3hbpQ/oA1kS7hz4pRtsnxPCa7Yfg==", 733 | "requires": { 734 | "busboy": "^0.3.0", 735 | "fs-capacitor": "^2.0.0", 736 | "http-errors": "^1.7.1", 737 | "object-path": "^0.11.4" 738 | } 739 | }, 740 | "has": { 741 | "version": "1.0.3", 742 | "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", 743 | "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", 744 | "requires": { 745 | "function-bind": "^1.1.1" 746 | } 747 | }, 748 | "has-symbols": { 749 | "version": "1.0.0", 750 | "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.0.tgz", 751 | "integrity": "sha1-uhqPGvKg/DllD1yFA2dwQSIGO0Q=" 752 | }, 753 | "http-errors": { 754 | "version": "1.7.2", 755 | "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.2.tgz", 756 | "integrity": "sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg==", 757 | "requires": { 758 | "depd": "~1.1.2", 759 | "inherits": "2.0.3", 760 | "setprototypeof": "1.1.1", 761 | "statuses": ">= 1.5.0 < 2", 762 | "toidentifier": "1.0.0" 763 | } 764 | }, 765 | "iconv-lite": { 766 | "version": "0.4.23", 767 | "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.23.tgz", 768 | "integrity": "sha512-neyTUVFtahjf0mB3dZT77u+8O0QB89jFdnBkd5P1JgYPbPaia3gXXOVL2fq8VyU2gMMD7SaN7QukTB/pmXYvDA==", 769 | "requires": { 770 | "safer-buffer": ">= 2.1.2 < 3" 771 | } 772 | }, 773 | "inherits": { 774 | "version": "2.0.3", 775 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", 776 | "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" 777 | }, 778 | "ipaddr.js": { 779 | "version": "1.8.0", 780 | "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.8.0.tgz", 781 | "integrity": "sha1-6qM9bd16zo9/b+DJygRA5wZzix4=" 782 | }, 783 | "is-callable": { 784 | "version": "1.1.4", 785 | "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.4.tgz", 786 | "integrity": "sha512-r5p9sxJjYnArLjObpjA4xu5EKI3CuKHkJXMhT7kwbpUyIFD1n5PMAsoPvWnvtZiNz7LjkYDRZhd7FlI0eMijEA==" 787 | }, 788 | "is-date-object": { 789 | "version": "1.0.1", 790 | "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.1.tgz", 791 | "integrity": "sha1-mqIOtq7rv/d/vTPnTKAbM1gdOhY=" 792 | }, 793 | "is-regex": { 794 | "version": "1.0.4", 795 | "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.4.tgz", 796 | "integrity": "sha1-VRdIm1RwkbCTDglWVM7SXul+lJE=", 797 | "requires": { 798 | "has": "^1.0.1" 799 | } 800 | }, 801 | "is-symbol": { 802 | "version": "1.0.2", 803 | "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.2.tgz", 804 | "integrity": "sha512-HS8bZ9ox60yCJLH9snBpIwv9pYUAkcuLhSA1oero1UB5y9aiQpRA8y2ex945AOtCZL1lJDeIk3G5LthswI46Lw==", 805 | "requires": { 806 | "has-symbols": "^1.0.0" 807 | } 808 | }, 809 | "iterall": { 810 | "version": "1.2.2", 811 | "resolved": "https://registry.npmjs.org/iterall/-/iterall-1.2.2.tgz", 812 | "integrity": "sha512-yynBb1g+RFUPY64fTrFv7nsjRrENBQJaX2UL+2Szc9REFrSNm1rpSXHGzhmAy7a9uv3vlvgBlXnf9RqmPH1/DA==" 813 | }, 814 | "lodash.sortby": { 815 | "version": "4.7.0", 816 | "resolved": "https://registry.npmjs.org/lodash.sortby/-/lodash.sortby-4.7.0.tgz", 817 | "integrity": "sha1-7dFMgk4sycHgsKG0K7UhBRakJDg=" 818 | }, 819 | "long": { 820 | "version": "4.0.0", 821 | "resolved": "https://registry.npmjs.org/long/-/long-4.0.0.tgz", 822 | "integrity": "sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA==" 823 | }, 824 | "lru-cache": { 825 | "version": "5.1.1", 826 | "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", 827 | "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", 828 | "requires": { 829 | "yallist": "^3.0.2" 830 | } 831 | }, 832 | "media-typer": { 833 | "version": "0.3.0", 834 | "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", 835 | "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=" 836 | }, 837 | "merge-descriptors": { 838 | "version": "1.0.1", 839 | "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", 840 | "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=" 841 | }, 842 | "methods": { 843 | "version": "1.1.2", 844 | "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", 845 | "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=" 846 | }, 847 | "mime": { 848 | "version": "1.4.1", 849 | "resolved": "https://registry.npmjs.org/mime/-/mime-1.4.1.tgz", 850 | "integrity": "sha512-KI1+qOZu5DcW6wayYHSzR/tXKCDC5Om4s1z2QJjDULzLcmf3DvzS7oluY4HCTrc+9FiKmWUgeNLg7W3uIQvxtQ==" 851 | }, 852 | "mime-db": { 853 | "version": "1.38.0", 854 | "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.38.0.tgz", 855 | "integrity": "sha512-bqVioMFFzc2awcdJZIzR3HjZFX20QhilVS7hytkKrv7xFAn8bM1gzc/FOX2awLISvWe0PV8ptFKcon+wZ5qYkg==" 856 | }, 857 | "mime-types": { 858 | "version": "2.1.22", 859 | "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.22.tgz", 860 | "integrity": "sha512-aGl6TZGnhm/li6F7yx82bJiBZwgiEa4Hf6CNr8YO+r5UHr53tSTYZb102zyU50DOWWKeOv0uQLRL0/9EiKWCog==", 861 | "requires": { 862 | "mime-db": "~1.38.0" 863 | } 864 | }, 865 | "ms": { 866 | "version": "2.0.0", 867 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", 868 | "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" 869 | }, 870 | "negotiator": { 871 | "version": "0.6.1", 872 | "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.1.tgz", 873 | "integrity": "sha1-KzJxhOiZIQEXeyhWP7XnECrNDKk=" 874 | }, 875 | "node-fetch": { 876 | "version": "2.3.0", 877 | "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.3.0.tgz", 878 | "integrity": "sha512-MOd8pV3fxENbryESLgVIeaGKrdl+uaYhCSSVkjeOb/31/njTpcis5aWfdqgNlHIrKOLRbMnfPINPOML2CIFeXA==" 879 | }, 880 | "object-assign": { 881 | "version": "4.1.1", 882 | "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", 883 | "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" 884 | }, 885 | "object-keys": { 886 | "version": "1.1.0", 887 | "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.0.tgz", 888 | "integrity": "sha512-6OO5X1+2tYkNyNEx6TsCxEqFfRWaqx6EtMiSbGrw8Ob8v9Ne+Hl8rBAgLBZn5wjEz3s/s6U1WXFUFOcxxAwUpg==" 889 | }, 890 | "object-path": { 891 | "version": "0.11.4", 892 | "resolved": "https://registry.npmjs.org/object-path/-/object-path-0.11.4.tgz", 893 | "integrity": "sha1-NwrnUvvzfePqcKhhwju6iRVpGUk=" 894 | }, 895 | "object.getownpropertydescriptors": { 896 | "version": "2.0.3", 897 | "resolved": "https://registry.npmjs.org/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.0.3.tgz", 898 | "integrity": "sha1-h1jIRvW0B62rDyNuCYbxSwUcqhY=", 899 | "requires": { 900 | "define-properties": "^1.1.2", 901 | "es-abstract": "^1.5.1" 902 | } 903 | }, 904 | "on-finished": { 905 | "version": "2.3.0", 906 | "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", 907 | "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", 908 | "requires": { 909 | "ee-first": "1.1.1" 910 | } 911 | }, 912 | "parseurl": { 913 | "version": "1.3.2", 914 | "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.2.tgz", 915 | "integrity": "sha1-/CidTtiZMRlGDBViUyYs3I3mW/M=" 916 | }, 917 | "path-to-regexp": { 918 | "version": "0.1.7", 919 | "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", 920 | "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=" 921 | }, 922 | "protobufjs": { 923 | "version": "6.8.8", 924 | "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-6.8.8.tgz", 925 | "integrity": "sha512-AAmHtD5pXgZfi7GMpllpO3q1Xw1OYldr+dMUlAnffGTAhqkg72WdmSY71uKBF/JuyiKs8psYbtKrhi0ASCD8qw==", 926 | "requires": { 927 | "@protobufjs/aspromise": "^1.1.2", 928 | "@protobufjs/base64": "^1.1.2", 929 | "@protobufjs/codegen": "^2.0.4", 930 | "@protobufjs/eventemitter": "^1.1.0", 931 | "@protobufjs/fetch": "^1.1.0", 932 | "@protobufjs/float": "^1.0.2", 933 | "@protobufjs/inquire": "^1.1.0", 934 | "@protobufjs/path": "^1.1.2", 935 | "@protobufjs/pool": "^1.1.0", 936 | "@protobufjs/utf8": "^1.1.0", 937 | "@types/long": "^4.0.0", 938 | "@types/node": "^10.1.0", 939 | "long": "^4.0.0" 940 | }, 941 | "dependencies": { 942 | "@types/node": { 943 | "version": "10.14.4", 944 | "resolved": "https://registry.npmjs.org/@types/node/-/node-10.14.4.tgz", 945 | "integrity": "sha512-DT25xX/YgyPKiHFOpNuANIQIVvYEwCWXgK2jYYwqgaMrYE6+tq+DtmMwlD3drl6DJbUwtlIDnn0d7tIn/EbXBg==" 946 | } 947 | } 948 | }, 949 | "proxy-addr": { 950 | "version": "2.0.4", 951 | "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.4.tgz", 952 | "integrity": "sha512-5erio2h9jp5CHGwcybmxmVqHmnCBZeewlfJ0pex+UW7Qny7OOZXTtH56TGNyBizkgiOwhJtMKrVzDTeKcySZwA==", 953 | "requires": { 954 | "forwarded": "~0.1.2", 955 | "ipaddr.js": "1.8.0" 956 | } 957 | }, 958 | "qs": { 959 | "version": "6.5.2", 960 | "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", 961 | "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==" 962 | }, 963 | "range-parser": { 964 | "version": "1.2.0", 965 | "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.0.tgz", 966 | "integrity": "sha1-9JvmtIeJTdxA3MlKMi9hEJLgDV4=" 967 | }, 968 | "raw-body": { 969 | "version": "2.3.3", 970 | "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.3.3.tgz", 971 | "integrity": "sha512-9esiElv1BrZoI3rCDuOuKCBRbuApGGaDPQfjSflGxdy4oyzqghxu6klEkkVIvBje+FF0BX9coEv8KqW6X/7njw==", 972 | "requires": { 973 | "bytes": "3.0.0", 974 | "http-errors": "1.6.3", 975 | "iconv-lite": "0.4.23", 976 | "unpipe": "1.0.0" 977 | }, 978 | "dependencies": { 979 | "http-errors": { 980 | "version": "1.6.3", 981 | "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", 982 | "integrity": "sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0=", 983 | "requires": { 984 | "depd": "~1.1.2", 985 | "inherits": "2.0.3", 986 | "setprototypeof": "1.1.0", 987 | "statuses": ">= 1.4.0 < 2" 988 | } 989 | }, 990 | "setprototypeof": { 991 | "version": "1.1.0", 992 | "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz", 993 | "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==" 994 | } 995 | } 996 | }, 997 | "retry": { 998 | "version": "0.12.0", 999 | "resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz", 1000 | "integrity": "sha1-G0KmJmoh8HQh0bC1S33BZ7AcATs=" 1001 | }, 1002 | "safe-buffer": { 1003 | "version": "5.1.2", 1004 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", 1005 | "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" 1006 | }, 1007 | "safer-buffer": { 1008 | "version": "2.1.2", 1009 | "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", 1010 | "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" 1011 | }, 1012 | "send": { 1013 | "version": "0.16.2", 1014 | "resolved": "https://registry.npmjs.org/send/-/send-0.16.2.tgz", 1015 | "integrity": "sha512-E64YFPUssFHEFBvpbbjr44NCLtI1AohxQ8ZSiJjQLskAdKuriYEP6VyGEsRDH8ScozGpkaX1BGvhanqCwkcEZw==", 1016 | "requires": { 1017 | "debug": "2.6.9", 1018 | "depd": "~1.1.2", 1019 | "destroy": "~1.0.4", 1020 | "encodeurl": "~1.0.2", 1021 | "escape-html": "~1.0.3", 1022 | "etag": "~1.8.1", 1023 | "fresh": "0.5.2", 1024 | "http-errors": "~1.6.2", 1025 | "mime": "1.4.1", 1026 | "ms": "2.0.0", 1027 | "on-finished": "~2.3.0", 1028 | "range-parser": "~1.2.0", 1029 | "statuses": "~1.4.0" 1030 | }, 1031 | "dependencies": { 1032 | "http-errors": { 1033 | "version": "1.6.3", 1034 | "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", 1035 | "integrity": "sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0=", 1036 | "requires": { 1037 | "depd": "~1.1.2", 1038 | "inherits": "2.0.3", 1039 | "setprototypeof": "1.1.0", 1040 | "statuses": ">= 1.4.0 < 2" 1041 | } 1042 | }, 1043 | "setprototypeof": { 1044 | "version": "1.1.0", 1045 | "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz", 1046 | "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==" 1047 | }, 1048 | "statuses": { 1049 | "version": "1.4.0", 1050 | "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.4.0.tgz", 1051 | "integrity": "sha512-zhSCtt8v2NDrRlPQpCNtw/heZLtfUDqxBM1udqikb/Hbk52LK4nQSwr10u77iopCW5LsyHpuXS0GnEc48mLeew==" 1052 | } 1053 | } 1054 | }, 1055 | "serve-static": { 1056 | "version": "1.13.2", 1057 | "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.13.2.tgz", 1058 | "integrity": "sha512-p/tdJrO4U387R9oMjb1oj7qSMaMfmOyd4j9hOFoxZe2baQszgHcSWjuya/CiT5kgZZKRudHNOA0pYXOl8rQ5nw==", 1059 | "requires": { 1060 | "encodeurl": "~1.0.2", 1061 | "escape-html": "~1.0.3", 1062 | "parseurl": "~1.3.2", 1063 | "send": "0.16.2" 1064 | } 1065 | }, 1066 | "setprototypeof": { 1067 | "version": "1.1.1", 1068 | "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz", 1069 | "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==" 1070 | }, 1071 | "sha.js": { 1072 | "version": "2.4.11", 1073 | "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz", 1074 | "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==", 1075 | "requires": { 1076 | "inherits": "^2.0.1", 1077 | "safe-buffer": "^5.0.1" 1078 | } 1079 | }, 1080 | "statuses": { 1081 | "version": "1.5.0", 1082 | "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", 1083 | "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=" 1084 | }, 1085 | "streamsearch": { 1086 | "version": "0.1.2", 1087 | "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-0.1.2.tgz", 1088 | "integrity": "sha1-gIudDlb8Jz2Am6VzOOkpkZoanxo=" 1089 | }, 1090 | "subscriptions-transport-ws": { 1091 | "version": "0.9.16", 1092 | "resolved": "https://registry.npmjs.org/subscriptions-transport-ws/-/subscriptions-transport-ws-0.9.16.tgz", 1093 | "integrity": "sha512-pQdoU7nC+EpStXnCfh/+ho0zE0Z+ma+i7xvj7bkXKb1dvYHSZxgRPaU6spRP+Bjzow67c/rRDoix5RT0uU9omw==", 1094 | "requires": { 1095 | "backo2": "^1.0.2", 1096 | "eventemitter3": "^3.1.0", 1097 | "iterall": "^1.2.1", 1098 | "symbol-observable": "^1.0.4", 1099 | "ws": "^5.2.0" 1100 | }, 1101 | "dependencies": { 1102 | "ws": { 1103 | "version": "5.2.2", 1104 | "resolved": "https://registry.npmjs.org/ws/-/ws-5.2.2.tgz", 1105 | "integrity": "sha512-jaHFD6PFv6UgoIVda6qZllptQsMlDEJkTQcybzzXDYM1XO9Y8em691FGMPmM46WGyLU4z9KMgQN+qrux/nhlHA==", 1106 | "requires": { 1107 | "async-limiter": "~1.0.0" 1108 | } 1109 | } 1110 | } 1111 | }, 1112 | "symbol-observable": { 1113 | "version": "1.2.0", 1114 | "resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-1.2.0.tgz", 1115 | "integrity": "sha512-e900nM8RRtGhlV36KGEU9k65K3mPb1WV70OdjfxlG2EAuM1noi/E/BaW/uMhL7bPEssK8QV57vN3esixjUvcXQ==" 1116 | }, 1117 | "toidentifier": { 1118 | "version": "1.0.0", 1119 | "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz", 1120 | "integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==" 1121 | }, 1122 | "ts-invariant": { 1123 | "version": "0.3.2", 1124 | "resolved": "https://registry.npmjs.org/ts-invariant/-/ts-invariant-0.3.2.tgz", 1125 | "integrity": "sha512-QsY8BCaRnHiB5T6iE4DPlJMAKEG3gzMiUco9FEt1jUXQf0XP6zi0idT0i0rMTu8A326JqNSDsmlkA9dRSh1TRg==", 1126 | "requires": { 1127 | "tslib": "^1.9.3" 1128 | } 1129 | }, 1130 | "tslib": { 1131 | "version": "1.9.3", 1132 | "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.9.3.tgz", 1133 | "integrity": "sha512-4krF8scpejhaOgqzBEcGM7yDIEfi0/8+8zDRZhNZZ2kjmHJ4hv3zCbQWxoJGz1iw5U0Jl0nma13xzHXcncMavQ==" 1134 | }, 1135 | "type-is": { 1136 | "version": "1.6.16", 1137 | "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.16.tgz", 1138 | "integrity": "sha512-HRkVv/5qY2G6I8iab9cI7v1bOIdhm94dVjQCPFElW9W+3GeDOSHmy2EBYe4VTApuzolPcmgFTN3ftVJRKR2J9Q==", 1139 | "requires": { 1140 | "media-typer": "0.3.0", 1141 | "mime-types": "~2.1.18" 1142 | } 1143 | }, 1144 | "unpipe": { 1145 | "version": "1.0.0", 1146 | "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", 1147 | "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=" 1148 | }, 1149 | "util.promisify": { 1150 | "version": "1.0.0", 1151 | "resolved": "https://registry.npmjs.org/util.promisify/-/util.promisify-1.0.0.tgz", 1152 | "integrity": "sha512-i+6qA2MPhvoKLuxnJNpXAGhg7HphQOSUq2LKMZD0m15EiskXUkMvKdF4Uui0WYeCUGea+o2cw/ZuwehtfsrNkA==", 1153 | "requires": { 1154 | "define-properties": "^1.1.2", 1155 | "object.getownpropertydescriptors": "^2.0.3" 1156 | } 1157 | }, 1158 | "utils-merge": { 1159 | "version": "1.0.1", 1160 | "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", 1161 | "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=" 1162 | }, 1163 | "uuid": { 1164 | "version": "3.3.2", 1165 | "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.2.tgz", 1166 | "integrity": "sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA==" 1167 | }, 1168 | "vary": { 1169 | "version": "1.1.2", 1170 | "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", 1171 | "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=" 1172 | }, 1173 | "ws": { 1174 | "version": "6.2.1", 1175 | "resolved": "https://registry.npmjs.org/ws/-/ws-6.2.1.tgz", 1176 | "integrity": "sha512-GIyAXC2cB7LjvpgMt9EKS2ldqr0MTrORaleiOno6TweZ6r3TKtoFQWay/2PceJ3RuBasOHzXNn5Lrw1X0bEjqA==", 1177 | "requires": { 1178 | "async-limiter": "~1.0.0" 1179 | } 1180 | }, 1181 | "yallist": { 1182 | "version": "3.0.3", 1183 | "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.0.3.tgz", 1184 | "integrity": "sha512-S+Zk8DEWE6oKpV+vI3qWkaK+jSbIK86pCwe2IF/xwIpQ8jEuxpw9NyaGjmp9+BoJv5FV2piqCDcoCtStppiq2A==" 1185 | }, 1186 | "zen-observable": { 1187 | "version": "0.8.13", 1188 | "resolved": "https://registry.npmjs.org/zen-observable/-/zen-observable-0.8.13.tgz", 1189 | "integrity": "sha512-fa+6aDUVvavYsefZw0zaZ/v3ckEtMgCFi30sn91SEZea4y/6jQp05E3omjkX91zV6RVdn15fqnFZ6RKjRGbp2g==" 1190 | }, 1191 | "zen-observable-ts": { 1192 | "version": "0.8.18", 1193 | "resolved": "https://registry.npmjs.org/zen-observable-ts/-/zen-observable-ts-0.8.18.tgz", 1194 | "integrity": "sha512-q7d05s75Rn1j39U5Oapg3HI2wzriVwERVo4N7uFGpIYuHB9ff02P/E92P9B8T7QVC93jCMHpbXH7X0eVR5LA7A==", 1195 | "requires": { 1196 | "tslib": "^1.9.3", 1197 | "zen-observable": "^0.8.0" 1198 | } 1199 | } 1200 | } 1201 | } 1202 | --------------------------------------------------------------------------------