Skip to content

Commit

Permalink
CLI api
Browse files Browse the repository at this point in the history
  • Loading branch information
mkleszcz committed May 7, 2023
1 parent 8f80dc5 commit 897bb4e
Show file tree
Hide file tree
Showing 14 changed files with 215 additions and 88 deletions.
18 changes: 18 additions & 0 deletions apps/app/src/pages/api/cli/graphql.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { createYoga } from 'graphql-yoga';
import type { NextApiRequest, NextApiResponse } from 'next';

import schema from '@vm/graphql/schema/cli';

export default createYoga<{
req: NextApiRequest;
res: NextApiResponse;
}>({
schema,
graphqlEndpoint: '/api/cli/graphql',
});

export const config = {
api: {
bodyParser: false,
},
};
9 changes: 9 additions & 0 deletions packages/graphql/schema/cli/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { GraphQLSchema } from 'graphql/type';

import { builder } from '../../builder';
import '../../types';
import '../nodes';
import './version';

const schema: GraphQLSchema = builder.toSchema();
export default schema;
83 changes: 83 additions & 0 deletions packages/graphql/schema/cli/version.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
import { ZodError } from 'zod';

import prismaClient from '@vm/prisma/client';

import { builder } from '../../builder';

const VersionInput = builder.inputType('VersionInput', {
fields: (t) => ({
name: t.string({
required: true,
}),
environmentId: t.string({
required: true,
validate: {
uuid: true,
refine: [
async (id) => {
const count = await prismaClient.environment.count({
where: {
id,
},
});
return count === 1;
},
{ message: 'EnvironmentId is invalid' },
],
},
}),
isCurrent: t.boolean({
required: true,
validate: {
type: 'boolean',
},
}),
}),
validate: [
async (args) => {
const name = args['name'];
const environmentId = args['environmentId'];
if (!name || !environmentId) return false;
const count = await prismaClient.version.count({
where: {
name,
environmentId,
},
});
return count === 0;
},
{ message: 'Version name must be unique' },
],
});

builder.mutationField('createVersion', (t) =>
t.prismaField({
type: 'Version',
errors: {
types: [ZodError],
},
args: { input: t.arg({ type: VersionInput, required: true }) },
resolve: async (root, _parent, args) => {
const { input } = args;
const getCreateVersionQuery = () =>
prismaClient.version.create({
data: input,
});
if (!input.isCurrent) {
return getCreateVersionQuery();
}
const [_, version] = await prismaClient.$transaction([
prismaClient.version.updateMany({
where: {
environmentId: input.environmentId,
},
data: {
isCurrent: false,
},
}),
getCreateVersionQuery(),
]);
return version;
},
})
);
25 changes: 0 additions & 25 deletions packages/graphql/schema/environment.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,31 +4,6 @@ import prismaClient from '@vm/prisma/client';

import { builder } from '../builder';

builder.prismaNode('Environment', {
id: { field: 'id' },
fields: (t) => ({
name: t.exposeString('name'),
project: t.relation('project'),
versions: t.prismaConnection({
type: 'Version',
cursor: 'id',
resolve: (query, parent) => prismaClient.version.findMany({ ...query, where: { environmentId: parent.id } }),
}),
currentVersion: t.prismaField({
type: 'Version',
nullable: true,
resolve: async (query, parent) =>
prismaClient.version.findFirst({
...query,
where: {
isCurrent: true,
environmentId: parent.id,
},
}),
}),
}),
});

const EnvironmentInput = builder.inputType('EnvironmentInput', {
fields: (t) => ({
name: t.string({
Expand Down
2 changes: 1 addition & 1 deletion packages/graphql/schema/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@ import { GraphQLSchema } from 'graphql/type';
import { builder } from '../builder';
import '../types';
import './environment';
import './nodes';
import './project';
import './service';
import './serviceVersion';
import './version';

const schema: GraphQLSchema = builder.toSchema();
Expand Down
28 changes: 28 additions & 0 deletions packages/graphql/schema/nodes/environment.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import prismaClient from '@vm/prisma/client';

import { builder } from '../../builder';

builder.prismaNode('Environment', {
id: { field: 'id' },
fields: (t) => ({
name: t.exposeString('name'),
project: t.relation('project'),
versions: t.prismaConnection({
type: 'Version',
cursor: 'id',
resolve: (query, parent) => prismaClient.version.findMany({ ...query, where: { environmentId: parent.id } }),
}),
currentVersion: t.prismaField({
type: 'Version',
nullable: true,
resolve: async (query, parent) =>
prismaClient.version.findFirst({
...query,
where: {
isCurrent: true,
environmentId: parent.id,
},
}),
}),
}),
});
5 changes: 5 additions & 0 deletions packages/graphql/schema/nodes/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import './environment';
import './project';
import './service';
import './serviceVersion';
import './version';
22 changes: 22 additions & 0 deletions packages/graphql/schema/nodes/project.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import prismaClient from '@vm/prisma/client';

import { builder } from '../../builder';

builder.prismaNode('Project', {
id: { field: 'id' },
fields: (t) => ({
name: t.exposeString('name'),
environments: t.prismaConnection({
type: 'Environment',
cursor: 'id',
resolve: (query, parent, args, context, info) =>
prismaClient.environment.findMany({ ...query, where: { projectId: parent.id } }),
}),
services: t.prismaConnection({
type: 'Service',
cursor: 'id',
resolve: (query, parent, args, context, info) =>
prismaClient.service.findMany({ ...query, where: { projectId: parent.id } }),
}),
}),
});
28 changes: 28 additions & 0 deletions packages/graphql/schema/nodes/service.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import prismaClient from '@vm/prisma/client';

import { builder } from '../../builder';

builder.prismaNode('Service', {
id: { field: 'id' },
fields: (t) => ({
name: t.exposeString('name'),
project: t.relation('project'),
versions: t.prismaConnection({
type: 'ServiceVersion',
cursor: 'id',
resolve: (query, parent) => prismaClient.serviceVersion.findMany({ ...query, where: { serviceId: parent.id } }),
}),
currentVersion: t.prismaField({
type: 'ServiceVersion',
nullable: true,
resolve: async (query, parent) =>
prismaClient.serviceVersion.findFirst({
...query,
where: {
isCurrent: true,
serviceId: parent.id,
},
}),
}),
}),
});
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { builder } from '../builder';
import { builder } from '../../builder';

builder.prismaNode('ServiceVersion', {
id: { field: 'id' },
Expand Down
20 changes: 20 additions & 0 deletions packages/graphql/schema/nodes/version.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import prismaClient from '@vm/prisma/client';

import { builder } from '../../builder';

builder.prismaNode('Version', {
id: { field: 'id' },
fields: (t) => ({
name: t.exposeString('name'),
createdAt: t.expose('createdAt', {
type: 'DateTime',
}),
isCurrent: t.exposeBoolean('isCurrent'),
environment: t.relation('environment'),
serviceVersions: t.prismaConnection({
type: 'ServiceVersion',
cursor: 'id',
resolve: (query, parent) => prismaClient.serviceVersion.findMany({ ...query, where: { versionId: parent.id } }),
}),
}),
});
19 changes: 0 additions & 19 deletions packages/graphql/schema/project.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,25 +4,6 @@ import prismaClient from '@vm/prisma/client';

import { builder } from '../builder';

builder.prismaNode('Project', {
id: { field: 'id' },
fields: (t) => ({
name: t.exposeString('name'),
environments: t.prismaConnection({
type: 'Environment',
cursor: 'id',
resolve: (query, parent, args, context, info) =>
prismaClient.environment.findMany({ ...query, where: { projectId: parent.id } }),
}),
services: t.prismaConnection({
type: 'Service',
cursor: 'id',
resolve: (query, parent, args, context, info) =>
prismaClient.service.findMany({ ...query, where: { projectId: parent.id } }),
}),
}),
});

const ProjectInput = builder.inputType('ProjectInput', {
fields: (t) => ({
name: t.string({
Expand Down
25 changes: 0 additions & 25 deletions packages/graphql/schema/service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,31 +4,6 @@ import prismaClient from '@vm/prisma/client';

import { builder } from '../builder';

builder.prismaNode('Service', {
id: { field: 'id' },
fields: (t) => ({
name: t.exposeString('name'),
project: t.relation('project'),
versions: t.prismaConnection({
type: 'ServiceVersion',
cursor: 'id',
resolve: (query, parent) => prismaClient.serviceVersion.findMany({ ...query, where: { serviceId: parent.id } }),
}),
currentVersion: t.prismaField({
type: 'ServiceVersion',
nullable: true,
resolve: async (query, parent) =>
prismaClient.serviceVersion.findFirst({
...query,
where: {
isCurrent: true,
serviceId: parent.id,
},
}),
}),
}),
});

const ServiceInput = builder.inputType('ServiceInput', {
fields: (t) => ({
name: t.string({
Expand Down
17 changes: 0 additions & 17 deletions packages/graphql/schema/version.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,23 +4,6 @@ import prismaClient from '@vm/prisma/client';

import { builder } from '../builder';

builder.prismaNode('Version', {
id: { field: 'id' },
fields: (t) => ({
name: t.exposeString('name'),
createdAt: t.expose('createdAt', {
type: 'DateTime',
}),
isCurrent: t.exposeBoolean('isCurrent'),
environment: t.relation('environment'),
serviceVersions: t.prismaConnection({
type: 'ServiceVersion',
cursor: 'id',
resolve: (query, parent) => prismaClient.serviceVersion.findMany({ ...query, where: { versionId: parent.id } }),
}),
}),
});

const VersionInput = builder.inputType('VersionInput', {
fields: (t) => ({
name: t.string({
Expand Down

0 comments on commit 897bb4e

Please sign in to comment.