Skip to content

Commit

Permalink
feat(graphql-service): added graphql service
Browse files Browse the repository at this point in the history
  • Loading branch information
k2on committed Nov 3, 2020
1 parent a65cfe9 commit e6015e1
Show file tree
Hide file tree
Showing 12 changed files with 384 additions and 37 deletions.
49 changes: 45 additions & 4 deletions src/classes/ServiceContext.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,15 @@ import yaml = require('js-yaml');
import fs = require('fs');
import { ServiceContextType } from '../types';
import ServiceFile from './ServiceFile';
import { dirname } from 'path';
import { dirname, join, resolve } from 'path';
import path = require('path');
import { getServiceContextPath, titleCase } from '../util';
import { Inquirer } from 'inquirer';
import inquirer = require('inquirer');
import { user } from '../user';

export default abstract class ServiceContext {
static NAME: string;
static DIRNAME: string = __dirname;

/**
* Abstract class to represent a service context
Expand All @@ -43,7 +44,7 @@ export default abstract class ServiceContext {
* @protected
* @returns {string} Path to the directory
*/
protected get serviceDirectory(): string {
get serviceDirectory(): string {
return dirname(this.serviceFile.path);
}

Expand Down Expand Up @@ -124,7 +125,7 @@ export default abstract class ServiceContext {
authors: [],
created: currentTimestamp,
modified: currentTimestamp,
license: 'CC',
license: 'CC-BY-1.0',
termsOfServiceURL: 'nix2.io/tos',
},
schemas: [],
Expand Down Expand Up @@ -210,4 +211,44 @@ export default abstract class ServiceContext {
this.schemas.splice(this.schemas.indexOf(schema), 1);
return true;
}

getTemplate(scope: string, fileName: string) {
const templatePath = join(
__dirname,
`services/${scope}/templates/`,
`${fileName}.template`,
);
return fs.readFileSync(templatePath, 'utf-8');
}

getREADMELines(): string[] {
return [`# ${this.info.label}`, `${this.info.description}`];
}

createREADME(): void {
const READMEContent = this.getREADMELines().join('\n');
console.log(READMEContent);

fs.writeFileSync(
join(this.serviceDirectory, 'README.md'),
READMEContent,
);
}

getFileHeaderLines(file: string): string[] {
let lines = [
`File: ${file}`,
`Created: ${new Date().toISOString()}`,
'----',
'Copyright: 2020 Nix² Technologies',
];
if (user != null) {
lines.push(`Author: ${user.name} (${user.email})`);
}
return lines;
}

postInitLogic(): void {
this.createREADME();
}
}
152 changes: 152 additions & 0 deletions src/classes/services/GraphQLServiceContext/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,152 @@
/*
* File: index.ts
* Created: 10/14/2020 13:03:39
* ----
* Copyright: 2020 Nix² Technologies
* Author: Max Koon (maxk@nix2.io)
*/
import { TypescriptServiceContext } from '..';
import { Info, Schema } from '../..';
import { GraphQLServiceContextType } from '../../../types';
import ServiceFile from '../../ServiceFile';

type DependenciesType = Record<string, string>;
export default class GraphQLServiceContext extends TypescriptServiceContext {
static NAME = 'graphql';
static DIRNAME: string = __dirname;

/**
* Class to represent an GraphQL Service context
* @class GraphQLServiceContext
* @param {string} filePath path to the service.yaml
* @param {Info} info info of the service
* @param {Array<Schema>} schemas list of service schemas
*/
constructor(serviceFile: ServiceFile, info: Info, schemas: Schema[]) {
super(serviceFile, info, 'graphql', schemas);
}

/**
* Deserialize an object into an `GraphQLServiceContext` instance
* @function deserialize
* @static
* @memberof GraphQLServiceContext
* @param {string} serviceFilePath path to the service.yaml
* @param {object} data Javascript object of the Info
* @returns {GraphQLServiceContext} Service context object
*/
static deserialize(
serviceFile: ServiceFile,
data: GraphQLServiceContextType,
): GraphQLServiceContext {
// Test if the values are present
const vals = ['info', 'schemas'];
for (const val of vals) {
if (Object.keys(data).indexOf(val) == -1)
throw Error(val + ' not given');
}

return new GraphQLServiceContext(
serviceFile,
Info.deserialize(data.info),
Object.values(data.schemas).map((schema: any) =>
Schema.deserialize(schema),
),
);
}

static createObject(
data: {
identifier: string;
label: string;
description: string;
userLeadDev: boolean;
},
user: any,
): GraphQLServiceContextType {
return {
...super.createObject(data, user),
...{
type: 'graphql',
},
};
}

/**
* Serialize a `GraphQLServiceContext` instance into an object
* @function serialize
* @memberof GraphQLServiceContext
* @returns {GraphQLServiceContextType} Javascript object
*/
serialize(): GraphQLServiceContextType {
return {
...super.serialize(),
...{
type: 'graphql',
},
};
}

/**
* GraphQL specifc dependencies
* @memberof GraphQLServiceContext
* @function dependencies
* @returns {Record<string, string>} Object of package name and version
*/
get dependencies(): DependenciesType {
return {
...super.dependencies,
...{
'apollo-server-express': '^2.19.0',
express: '^4.17.1',
graphql: '^15.4.0',
'reflect-metadata': '^0.1.13',
'type-graphql': '^1.1.0',
typeorm: '^0.2.29',
},
};
}

/**
* Object of dev dependencies and their version
* @memberof GraphQLServiceContext
* @function devDependencies
* @returns {Record<string, string>} Object of package name and version
*/
get devDependencies(): DependenciesType {
return {
...super.devDependencies,
...{
'@types/express': '^4.17.8',
'@types/graphql': '^14.5.0',
nodemon: '^2.0.6',
},
};
}

/**
* Object of the scripts
* @memberof GraphQLServiceContext
* @function scripts
* @returns {Record<string, string>} Object of the scripts
*/
get scripts(): Record<string, string> {
return {
...super.scripts,
...{
start: 'nodemon --exec ts-node ./src/index.ts',
},
};
}

getTemplate = (fileName: string) =>
super.getTemplate('GraphQLServiceContext', fileName);

getMainIndexFileContext(): string {
return super.getMainIndexFileContext() + this.getTemplate('index.ts');
}

postInitLogic() {
super.postInitLogic();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import "reflect-metadata";
import { ApolloServer } from "apollo-server-express";
import * as Express from "express";
import { buildSchema, Query, Resolver } from "type-graphql";

@Resolver()
class HelloResolver {
@Query(() => String)
async hello() {
return "hi world";
}
}

const main = async () => {
const schema = await buildSchema({
resolvers: [HelloResolver],
});

const apolloServer = new ApolloServer({ schema });

const app = Express();

apolloServer.applyMiddleware({ app });

app.listen(4000, () => {
console.log("started");
});
};

main();
79 changes: 67 additions & 12 deletions src/classes/services/TypescriptServiceContext/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,15 @@
* Copyright: 2020 Nix² Technologies
* Author: Max Koon (maxk@nix2.io)
*/
import { existsSync, readFileSync } from 'fs';
import { existsSync, readFileSync, writeFileSync, mkdirSync } from 'fs';
import { join } from 'path';
import { Info, Schema, ServiceContext } from '../..';
import { PACKAGES } from '../../../constants';
import PackageJSONType from '../../../types/PackageJSONType';
import { authed, user } from '../../../user';
import ServiceFile from '../../ServiceFile';
import { execSync } from 'child_process';

type DependenciesType = Record<string, string>;
export default abstract class TypescriptServiceContext extends ServiceContext {
static NAME = 'typescript';

Expand All @@ -32,8 +32,9 @@ export default abstract class TypescriptServiceContext extends ServiceContext {
info: Info,
type: string,
schemas: Schema[],
private _dependencies: DependenciesType = {},
private _devDependencies: DependenciesType = {},
private _dependencies: Record<string, string> = {},
private _devDependencies: Record<string, string> = {},
private _scripts: Record<string, string> = {},
) {
super(serviceFile, info, type, schemas);
}
Expand All @@ -44,7 +45,7 @@ export default abstract class TypescriptServiceContext extends ServiceContext {
* @function dependencies
* @returns {Record<string, string>} Object of package name and version
*/
get dependencies(): DependenciesType {
get dependencies(): Record<string, string> {
return { ...this._dependencies, ...{} };
}

Expand All @@ -54,17 +55,24 @@ export default abstract class TypescriptServiceContext extends ServiceContext {
* @function devDependencies
* @returns {Record<string, string>} Object of package name and version
*/
get devDependencies(): DependenciesType {
get devDependencies(): Record<string, string> {
return { ...this._devDependencies, ...PACKAGES.TYPESCRIPT.dev };
}

readPackageFile(): PackageJSONType {
let tempdir = '.';
// TODO: remove this
tempdir = join(this.serviceDirectory, '/serv');
const packagePath = join(tempdir, '/package.json');
/**
* Object of the scripts
* @memberof TypescriptServiceContext
* @function scripts
* @returns {Record<string, string>} Object of the scripts
*/
get scripts(): Record<string, string> {
return { ...this._scripts, ...{} };
}

readPackageFile(): PackageJSONType | null {
const packagePath = join(this.serviceDirectory, 'package.json');
if (!existsSync(packagePath)) {
throw Error('FILE_NOT_EXIST');
return null;
}
const fileContent = readFileSync(packagePath, 'utf-8');
const fileObject = JSON.parse(fileContent);
Expand All @@ -80,8 +88,55 @@ export default abstract class TypescriptServiceContext extends ServiceContext {
license: this.info.license || 'CC-BY-1.0',
dependencies: this.dependencies,
devDependencies: this.devDependencies,
scripts: this.scripts,
};
if (authed) packageContent.author = `${user?.name} <${user?.email}>`;
return packageContent;
}

createPackageFile() {
writeFileSync(
join(this.serviceDirectory, 'package.json'),
JSON.stringify(this.createPackageContent(), null, 4),
);
}

getFileHeader(fileName: string) {
return (
'/*\n' +
this.getFileHeaderLines(fileName)
.map((line) => ` * ${line}`)
.join('\n') +
'\n*/\n'
);
}

createSourceDirectory() {
const sourceDir = join(this.serviceDirectory, '/src');
if (!existsSync(sourceDir)) mkdirSync(sourceDir);
return sourceDir;
}

getMainIndexFileContext(): string {
return this.getFileHeader('index.ts');
}

createSourceFiles() {
const sourceDir = this.createSourceDirectory();
writeFileSync(
join(sourceDir, 'index.ts'),
this.getMainIndexFileContext(),
);
}

installPackages() {
execSync(`yarn --cwd ${this.serviceDirectory}`);
}

postInitLogic() {
super.postInitLogic();
this.createPackageFile();
this.createSourceFiles();
this.installPackages();
}
}
Loading

0 comments on commit e6015e1

Please sign in to comment.