feat(gql): added some experimentation around graphql modules

This commit is contained in:
blam
2020-07-27 15:36:28 +02:00
committed by Fredrik Adelöw
parent c5c2c2c60c
commit 6efab40e05
19 changed files with 369 additions and 12 deletions
+3
View File
@@ -0,0 +1,3 @@
module.exports = {
extends: [require.resolve('@backstage/cli/config/eslint.backend')],
};
+13
View File
@@ -0,0 +1,13 @@
# graphql
Welcome to the graphql backend plugin!
_This plugin was created through the Backstage CLI_
## Getting started
Your plugin has been added to the example app in this repository, meaning you'll be able to access it by running `yarn start` in the root directory, and then navigating to [/graphql](http://localhost:3000/graphql).
You can also serve the plugin in isolation by running `yarn start` in the plugin directory.
This method of serving the plugin provides quicker iteration speed and a faster startup and hot reloads.
It is only meant for local development, and the setup for it can be found inside the [/dev](/dev) directory.
+44
View File
@@ -0,0 +1,44 @@
{
"name": "@backstage/plugin-bogus-graphql",
"version": "0.1.1-alpha.16",
"main": "src/index.ts",
"types": "src/index.ts",
"license": "Apache-2.0",
"private": true,
"publishConfig": {
"access": "public",
"main": "dist/index.esm.js",
"types": "dist/index.d.ts"
},
"scripts": {
"start": "backstage-cli backend:dev",
"build": "backstage-cli backend:build",
"lint": "backstage-cli lint",
"test": "backstage-cli test",
"prepack": "backstage-cli prepack",
"postpack": "backstage-cli postpack",
"clean": "backstage-cli clean",
"mock-data": "./scripts/mock-data.sh"
},
"dependencies": {
"@backstage/backend-common": "^0.1.1-alpha.16",
"@graphql-modules/core": "^0.7.17",
"@types/express": "^4.17.6",
"@types/whatwg-fetch": "^0.0.33",
"graphql": "^15.3.0",
"node-fetch": "^2.6.0",
"whatwg-fetch": "^2.0.0",
"winston": "^3.2.1",
"yn": "^4.0.0"
},
"devDependencies": {
"@backstage/cli": "^0.1.1-alpha.16",
"@types/supertest": "^2.0.8",
"eslint-plugin-graphql": "^4.0.0",
"msw": "^0.19.5",
"supertest": "^4.0.2"
},
"files": [
"dist"
]
}
+2
View File
@@ -0,0 +1,2 @@
#!/usr/bin/env bash
echo "use this script to load your service with some mock data if needed!"
@@ -0,0 +1,47 @@
/*
* Copyright 2020 Spotify AB
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { Logger } from 'winston';
import fs from 'fs';
import path from 'path';
import { GraphQLModule } from '@graphql-modules/core';
export interface ModuleOptions {
logger: Logger;
}
export async function createModule(
options: ModuleOptions,
): Promise<GraphQLModule> {
const typeDefs = await fs.promises.readFile(
path.resolve(__dirname, '..', 'schema.gql'),
'utf-8',
);
const resolvers = {
EntityMetadata: {
uppercaseName: metadata => metadata.name.toUpperCase(),
},
};
const module = new GraphQLModule({
typeDefs,
resolvers,
logger: options.logger as any,
});
return module;
}
+19
View File
@@ -0,0 +1,19 @@
/*
* Copyright 2020 Spotify AB
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
require('whatwg-fetch');
export * from './graphql/module';
+3
View File
@@ -0,0 +1,3 @@
type EntityMetadata {
uppercaseName: String
}
+18
View File
@@ -0,0 +1,18 @@
/*
* Copyright 2020 Spotify AB
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
require('whatwg-fetch');
export {};
+3
View File
@@ -0,0 +1,3 @@
module.exports = {
extends: [require.resolve('@backstage/cli/config/eslint.backend')],
};
+13
View File
@@ -0,0 +1,13 @@
# graphql
Welcome to the graphql backend plugin!
_This plugin was created through the Backstage CLI_
## Getting started
Your plugin has been added to the example app in this repository, meaning you'll be able to access it by running `yarn start` in the root directory, and then navigating to [/graphql](http://localhost:3000/graphql).
You can also serve the plugin in isolation by running `yarn start` in the plugin directory.
This method of serving the plugin provides quicker iteration speed and a faster startup and hot reloads.
It is only meant for local development, and the setup for it can be found inside the [/dev](/dev) directory.
+44
View File
@@ -0,0 +1,44 @@
{
"name": "@backstage/plugin-catalog-graphql",
"version": "0.1.1-alpha.16",
"main": "src/index.ts",
"types": "src/index.ts",
"license": "Apache-2.0",
"private": true,
"publishConfig": {
"access": "public",
"main": "dist/index.esm.js",
"types": "dist/index.d.ts"
},
"scripts": {
"start": "backstage-cli backend:dev",
"build": "backstage-cli backend:build",
"lint": "backstage-cli lint",
"test": "backstage-cli test",
"prepack": "backstage-cli prepack",
"postpack": "backstage-cli postpack",
"clean": "backstage-cli clean",
"mock-data": "./scripts/mock-data.sh"
},
"dependencies": {
"@backstage/backend-common": "^0.1.1-alpha.16",
"@graphql-modules/core": "^0.7.17",
"@types/express": "^4.17.6",
"@types/whatwg-fetch": "^0.0.33",
"graphql": "^15.3.0",
"node-fetch": "^2.6.0",
"whatwg-fetch": "^2.0.0",
"winston": "^3.2.1",
"yn": "^4.0.0"
},
"devDependencies": {
"@backstage/cli": "^0.1.1-alpha.16",
"@types/supertest": "^2.0.8",
"eslint-plugin-graphql": "^4.0.0",
"msw": "^0.19.5",
"supertest": "^4.0.2"
},
"files": [
"dist"
]
}
+2
View File
@@ -0,0 +1,2 @@
#!/usr/bin/env bash
echo "use this script to load your service with some mock data if needed!"
@@ -0,0 +1,82 @@
/*
* Copyright 2020 Spotify AB
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { Logger } from 'winston';
import fetch from 'node-fetch';
import fs from 'fs';
import path from 'path';
import { GraphQLModule } from '@graphql-modules/core';
export interface ModuleOptions {
logger: Logger;
}
// function wrapLogger(logger: Logger) {
// return {
// log: (msg: string | Error, ...extra: any[]) =>
// logger.info(String(msg), ...extra),
// debug: (msg: string | Error, ...extra: any[]) =>
// logger.info(String(msg), ...extra),
// info: (msg: string | Error, ...extra: any[]) =>
// logger.info(String(msg), ...extra),
// error: (msg: string | Error, ...extra: any[]) =>
// logger.info(String(msg), ...extra),
// clientError: (msg: string | Error, ...extra: any[]) =>
// logger.info(String(msg), ...extra),
// warn: (msg: string | Error, ...extra: any[]) =>
// logger.info(String(msg), ...extra),
// };
// }
class CatalogClient {
async list() {
const res = await fetch('http://localhost:7000/catalog/entities');
if (!res.ok) {
throw new Error(`NOPE, ${await res.text()}`);
}
return res.json();
}
}
export async function createModule(
options: ModuleOptions,
): Promise<GraphQLModule> {
const typeDefs = await fs.promises.readFile(
path.resolve(__dirname, '..', 'schema.gql'),
'utf-8',
);
const catalogClient = new CatalogClient();
const resolvers = {
Query: {
catalog: () => true,
},
CatalogQuery: {
list: () => catalogClient.list(),
},
CatalogEntity: () => ({}),
};
const module = new GraphQLModule({
typeDefs,
resolvers,
logger: options.logger as any,
});
return module;
}
+19
View File
@@ -0,0 +1,19 @@
/*
* Copyright 2020 Spotify AB
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
require('whatwg-fetch');
export * from './graphql/module';
+25
View File
@@ -0,0 +1,25 @@
type EntityMetadataAnnotation {
key: String!
value: String!
}
type EntityMetadata {
name: String!
namespace: String
annotation(name: String): EntityMetadataAnnotation
annotations: [EntityMetadataAnnotation!]!
}
type CatalogEntity {
apiVersion: String
kind: String!
metadata: EntityMetadata
}
type CatalogQuery {
list: [CatalogEntity!]!
}
type Query {
catalog: CatalogQuery!
}
+18
View File
@@ -0,0 +1,18 @@
/*
* Copyright 2020 Spotify AB
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
require('whatwg-fetch');
export {};
+3
View File
@@ -21,6 +21,9 @@
},
"dependencies": {
"@backstage/backend-common": "^0.1.1-alpha.18",
"@backstage/plugin-catalog-graphql": "^0.1.1-alpha.18",
"@backstage/plugin-bogus-graphql": "^0.1.1-alpha.18",
"@graphql-modules/core": "^0.7.17",
"@types/express": "^4.17.6",
"apollo-server": "^2.16.0",
"apollo-server-express": "^2.16.0",
-11
View File
@@ -1,11 +0,0 @@
type CatalogEntity {
id: String
}
type CatalogQuery {
list: [CatalogEntity!]!
}
type Query {
catalog: CatalogQuery!
}
+11 -1
View File
@@ -20,7 +20,10 @@ import Router from 'express-promise-router';
import { Logger } from 'winston';
import fs from 'fs';
import path from 'path';
import { GraphQLModule } from '@graphql-modules/core';
import { ApolloServer } from 'apollo-server-express';
import { createModule as createCatalogModule } from '@backstage/plugin-catalog-graphql';
import { createModule as createBogusModule } from '@backstage/plugin-bogus-graphql';
const schemaPath = path.resolve(
require.resolve('@backstage/plugin-graphql-backend/package.json'),
@@ -36,7 +39,14 @@ export async function createRouter(
): Promise<express.Router> {
const typeDefs = await fs.promises.readFile(schemaPath, 'utf-8');
const server = new ApolloServer({ typeDefs, logger: options.logger });
const catalogModule = await createCatalogModule(options);
const bogusModule = await createBogusModule(options);
const { schema } = new GraphQLModule({
imports: [catalogModule, bogusModule],
typeDefs,
});
const server = new ApolloServer({ schema, logger: options.logger });
const router = Router();
const apolloMiddlware = server.getMiddleware({ path: '/' });