summaryrefslogtreecommitdiffstats
path: root/sick-fits/backend/src
diff options
context:
space:
mode:
authorWes Bos <wesbos@gmail.com>2018-06-14 16:44:21 -0400
committerWes Bos <wesbos@gmail.com>2018-06-14 16:44:21 -0400
commitb1600adec47a04f60e1da07d94a3ed3906ff5aee (patch)
tree828f786da6806d7237ee5cbc5df61e552353b85b /sick-fits/backend/src
parenta95e08cd2dd5d7ec0a0412adae02515a5f9cec4f (diff)
starter files
Diffstat (limited to 'sick-fits/backend/src')
-rw-r--r--sick-fits/backend/src/createServer.js20
-rw-r--r--sick-fits/backend/src/db.js10
-rw-r--r--sick-fits/backend/src/generated/prisma.graphql2126
-rw-r--r--sick-fits/backend/src/index.js41
-rw-r--r--sick-fits/backend/src/mail.js28
-rw-r--r--sick-fits/backend/src/resolvers/Mutation.js354
-rw-r--r--sick-fits/backend/src/resolvers/Query.js62
-rw-r--r--sick-fits/backend/src/schema.graphql39
-rw-r--r--sick-fits/backend/src/stripe.js1
-rw-r--r--sick-fits/backend/src/utils.js17
10 files changed, 2698 insertions, 0 deletions
diff --git a/sick-fits/backend/src/createServer.js b/sick-fits/backend/src/createServer.js
new file mode 100644
index 0000000..036d15a
--- /dev/null
+++ b/sick-fits/backend/src/createServer.js
@@ -0,0 +1,20 @@
+const { GraphQLServer } = require('graphql-yoga');
+const Mutation = require('./resolvers/Mutation');
+const Query = require('./resolvers/Query');
+const db = require('./db');
+
+function createServer() {
+ return new GraphQLServer({
+ typeDefs: 'src/schema.graphql',
+ resolverValidationOptions: {
+ requireResolversForResolveType: false,
+ },
+ resolvers: {
+ Mutation,
+ Query,
+ },
+ context: req => ({ ...req, db }),
+ });
+}
+
+module.exports = createServer;
diff --git a/sick-fits/backend/src/db.js b/sick-fits/backend/src/db.js
new file mode 100644
index 0000000..e8caa14
--- /dev/null
+++ b/sick-fits/backend/src/db.js
@@ -0,0 +1,10 @@
+const { Prisma } = require('prisma-binding');
+
+const db = new Prisma({
+ typeDefs: 'src/generated/prisma.graphql',
+ endpoint: process.env.PRISMA_ENDPOINT, // the endpoint of the Prisma DB service (value is set in variables.env)
+ secret: process.env.PRISMA_SECRET, // taken from prisma/prisma.yml (value is set in .env)
+ debug: false, // log all GraphQL queries & mutations
+});
+
+module.exports = db; \ No newline at end of file
diff --git a/sick-fits/backend/src/generated/prisma.graphql b/sick-fits/backend/src/generated/prisma.graphql
new file mode 100644
index 0000000..953ddc2
--- /dev/null
+++ b/sick-fits/backend/src/generated/prisma.graphql
@@ -0,0 +1,2126 @@
+# source: https://us1.prisma.sh/wesbos/sick-fits/dev
+# timestamp: Fri May 25 2018 10:46:45 GMT-0400 (EDT)
+
+type AggregateCartItem {
+ count: Int!
+}
+
+type AggregateItem {
+ count: Int!
+}
+
+type AggregateOrder {
+ count: Int!
+}
+
+type AggregateOrderItem {
+ count: Int!
+}
+
+type AggregateUser {
+ count: Int!
+}
+
+type BatchPayload {
+ """The number of nodes that have been affected by the Batch operation."""
+ count: Long!
+}
+
+type CartItem implements Node {
+ id: ID!
+ quantity: Int!
+ item(where: ItemWhereInput): Item
+ user(where: UserWhereInput): User!
+ createdAt: DateTime!
+ updatedAt: DateTime!
+}
+
+"""A connection to a list of items."""
+type CartItemConnection {
+ """Information to aid in pagination."""
+ pageInfo: PageInfo!
+
+ """A list of edges."""
+ edges: [CartItemEdge]!
+ aggregate: AggregateCartItem!
+}
+
+input CartItemCreateInput {
+ quantity: Int
+ item: ItemCreateOneInput
+ user: UserCreateOneWithoutCartInput!
+}
+
+input CartItemCreateManyWithoutUserInput {
+ create: [CartItemCreateWithoutUserInput!]
+ connect: [CartItemWhereUniqueInput!]
+}
+
+input CartItemCreateWithoutUserInput {
+ quantity: Int
+ item: ItemCreateOneInput
+}
+
+"""An edge in a connection."""
+type CartItemEdge {
+ """The item at the end of the edge."""
+ node: CartItem!
+
+ """A cursor for use in pagination."""
+ cursor: String!
+}
+
+enum CartItemOrderByInput {
+ id_ASC
+ id_DESC
+ quantity_ASC
+ quantity_DESC
+ createdAt_ASC
+ createdAt_DESC
+ updatedAt_ASC
+ updatedAt_DESC
+}
+
+type CartItemPreviousValues {
+ id: ID!
+ quantity: Int!
+ createdAt: DateTime!
+ updatedAt: DateTime!
+}
+
+type CartItemSubscriptionPayload {
+ mutation: MutationType!
+ node: CartItem
+ updatedFields: [String!]
+ previousValues: CartItemPreviousValues
+}
+
+input CartItemSubscriptionWhereInput {
+ """Logical AND on all given filters."""
+ AND: [CartItemSubscriptionWhereInput!]
+
+ """Logical OR on all given filters."""
+ OR: [CartItemSubscriptionWhereInput!]
+
+ """Logical NOT on all given filters combined by AND."""
+ NOT: [CartItemSubscriptionWhereInput!]
+
+ """
+ The subscription event gets dispatched when it's listed in mutation_in
+ """
+ mutation_in: [MutationType!]
+
+ """
+ The subscription event gets only dispatched when one of the updated fields names is included in this list
+ """
+ updatedFields_contains: String
+
+ """
+ The subscription event gets only dispatched when all of the field names included in this list have been updated
+ """
+ updatedFields_contains_every: [String!]
+
+ """
+ The subscription event gets only dispatched when some of the field names included in this list have been updated
+ """
+ updatedFields_contains_some: [String!]
+ node: CartItemWhereInput
+}
+
+input CartItemUpdateInput {
+ quantity: Int
+ item: ItemUpdateOneInput
+ user: UserUpdateOneWithoutCartInput
+}
+
+input CartItemUpdateManyWithoutUserInput {
+ create: [CartItemCreateWithoutUserInput!]
+ connect: [CartItemWhereUniqueInput!]
+ disconnect: [CartItemWhereUniqueInput!]
+ delete: [CartItemWhereUniqueInput!]
+ update: [CartItemUpdateWithWhereUniqueWithoutUserInput!]
+ upsert: [CartItemUpsertWithWhereUniqueWithoutUserInput!]
+}
+
+input CartItemUpdateWithoutUserDataInput {
+ quantity: Int
+ item: ItemUpdateOneInput
+}
+
+input CartItemUpdateWithWhereUniqueWithoutUserInput {
+ where: CartItemWhereUniqueInput!
+ data: CartItemUpdateWithoutUserDataInput!
+}
+
+input CartItemUpsertWithWhereUniqueWithoutUserInput {
+ where: CartItemWhereUniqueInput!
+ update: CartItemUpdateWithoutUserDataInput!
+ create: CartItemCreateWithoutUserInput!
+}
+
+input CartItemWhereInput {
+ """Logical AND on all given filters."""
+ AND: [CartItemWhereInput!]
+
+ """Logical OR on all given filters."""
+ OR: [CartItemWhereInput!]
+
+ """Logical NOT on all given filters combined by AND."""
+ NOT: [CartItemWhereInput!]
+ id: ID
+
+ """All values that are not equal to given value."""
+ id_not: ID
+
+ """All values that are contained in given list."""
+ id_in: [ID!]
+
+ """All values that are not contained in given list."""
+ id_not_in: [ID!]
+
+ """All values less than the given value."""
+ id_lt: ID
+
+ """All values less than or equal the given value."""
+ id_lte: ID
+
+ """All values greater than the given value."""
+ id_gt: ID
+
+ """All values greater than or equal the given value."""
+ id_gte: ID
+
+ """All values containing the given string."""
+ id_contains: ID
+
+ """All values not containing the given string."""
+ id_not_contains: ID
+
+ """All values starting with the given string."""
+ id_starts_with: ID
+
+ """All values not starting with the given string."""
+ id_not_starts_with: ID
+
+ """All values ending with the given string."""
+ id_ends_with: ID
+
+ """All values not ending with the given string."""
+ id_not_ends_with: ID
+ quantity: Int
+
+ """All values that are not equal to given value."""
+ quantity_not: Int
+
+ """All values that are contained in given list."""
+ quantity_in: [Int!]
+
+ """All values that are not contained in given list."""
+ quantity_not_in: [Int!]
+
+ """All values less than the given value."""
+ quantity_lt: Int
+
+ """All values less than or equal the given value."""
+ quantity_lte: Int
+
+ """All values greater than the given value."""
+ quantity_gt: Int
+
+ """All values greater than or equal the given value."""
+ quantity_gte: Int
+ createdAt: DateTime
+
+ """All values that are not equal to given value."""
+ createdAt_not: DateTime
+
+ """All values that are contained in given list."""
+ createdAt_in: [DateTime!]
+
+ """All values that are not contained in given list."""
+ createdAt_not_in: [DateTime!]
+
+ """All values less than the given value."""
+ createdAt_lt: DateTime
+
+ """All values less than or equal the given value."""
+ createdAt_lte: DateTime
+
+ """All values greater than the given value."""
+ createdAt_gt: DateTime
+
+ """All values greater than or equal the given value."""
+ createdAt_gte: DateTime
+ updatedAt: DateTime
+
+ """All values that are not equal to given value."""
+ updatedAt_not: DateTime
+
+ """All values that are contained in given list."""
+ updatedAt_in: [DateTime!]
+
+ """All values that are not contained in given list."""
+ updatedAt_not_in: [DateTime!]
+
+ """All values less than the given value."""
+ updatedAt_lt: DateTime
+
+ """All values less than or equal the given value."""
+ updatedAt_lte: DateTime
+
+ """All values greater than the given value."""
+ updatedAt_gt: DateTime
+
+ """All values greater than or equal the given value."""
+ updatedAt_gte: DateTime
+ item: ItemWhereInput
+ user: UserWhereInput
+}
+
+input CartItemWhereUniqueInput {
+ id: ID
+}
+
+scalar DateTime
+
+type Item implements Node {
+ id: ID!
+ title: String!
+ description: String!
+ image: String
+ largeImage: String
+ price: Int!
+ createdAt: DateTime!
+ updatedAt: DateTime!
+ user(where: UserWhereInput): User!
+}
+
+"""A connection to a list of items."""
+type ItemConnection {
+ """Information to aid in pagination."""
+ pageInfo: PageInfo!
+
+ """A list of edges."""
+ edges: [ItemEdge]!
+ aggregate: AggregateItem!
+}
+
+input ItemCreateInput {
+ title: String!
+ description: String!
+ image: String
+ largeImage: String
+ price: Int!
+ user: UserCreateOneInput!
+}
+
+input ItemCreateOneInput {
+ create: ItemCreateInput
+ connect: ItemWhereUniqueInput
+}
+
+"""An edge in a connection."""
+type ItemEdge {
+ """The item at the end of the edge."""
+ node: Item!
+
+ """A cursor for use in pagination."""
+ cursor: String!
+}
+
+enum ItemOrderByInput {
+ id_ASC
+ id_DESC
+ title_ASC
+ title_DESC
+ description_ASC
+ description_DESC
+ image_ASC
+ image_DESC
+ largeImage_ASC
+ largeImage_DESC
+ price_ASC
+ price_DESC
+ createdAt_ASC
+ createdAt_DESC
+ updatedAt_ASC
+ updatedAt_DESC
+}
+
+type ItemPreviousValues {
+ id: ID!
+ title: String!
+ description: String!
+ image: String
+ largeImage: String
+ price: Int!
+ createdAt: DateTime!
+ updatedAt: DateTime!
+}
+
+type ItemSubscriptionPayload {
+ mutation: MutationType!
+ node: Item
+ updatedFields: [String!]
+ previousValues: ItemPreviousValues
+}
+
+input ItemSubscriptionWhereInput {
+ """Logical AND on all given filters."""
+ AND: [ItemSubscriptionWhereInput!]
+
+ """Logical OR on all given filters."""
+ OR: [ItemSubscriptionWhereInput!]
+
+ """Logical NOT on all given filters combined by AND."""
+ NOT: [ItemSubscriptionWhereInput!]
+
+ """
+ The subscription event gets dispatched when it's listed in mutation_in
+ """
+ mutation_in: [MutationType!]
+
+ """
+ The subscription event gets only dispatched when one of the updated fields names is included in this list
+ """
+ updatedFields_contains: String
+
+ """
+ The subscription event gets only dispatched when all of the field names included in this list have been updated
+ """
+ updatedFields_contains_every: [String!]
+
+ """
+ The subscription event gets only dispatched when some of the field names included in this list have been updated
+ """
+ updatedFields_contains_some: [String!]
+ node: ItemWhereInput
+}
+
+input ItemUpdateDataInput {
+ title: String
+ description: String
+ image: String
+ largeImage: String
+ price: Int
+ user: UserUpdateOneInput
+}
+
+input ItemUpdateInput {
+ title: String
+ description: String
+ image: String
+ largeImage: String
+ price: Int
+ user: UserUpdateOneInput
+}
+
+input ItemUpdateOneInput {
+ create: ItemCreateInput
+ connect: ItemWhereUniqueInput
+ disconnect: Boolean
+ delete: Boolean
+ update: ItemUpdateDataInput
+ upsert: ItemUpsertNestedInput
+}
+
+input ItemUpsertNestedInput {
+ update: ItemUpdateDataInput!
+ create: ItemCreateInput!
+}
+
+input ItemWhereInput {
+ """Logical AND on all given filters."""
+ AND: [ItemWhereInput!]
+
+ """Logical OR on all given filters."""
+ OR: [ItemWhereInput!]
+
+ """Logical NOT on all given filters combined by AND."""
+ NOT: [ItemWhereInput!]
+ id: ID
+
+ """All values that are not equal to given value."""
+ id_not: ID
+
+ """All values that are contained in given list."""
+ id_in: [ID!]
+
+ """All values that are not contained in given list."""
+ id_not_in: [ID!]
+
+ """All values less than the given value."""
+ id_lt: ID
+
+ """All values less than or equal the given value."""
+ id_lte: ID
+
+ """All values greater than the given value."""
+ id_gt: ID
+
+ """All values greater than or equal the given value."""
+ id_gte: ID
+
+ """All values containing the given string."""
+ id_contains: ID
+
+ """All values not containing the given string."""
+ id_not_contains: ID
+
+ """All values starting with the given string."""
+ id_starts_with: ID
+
+ """All values not starting with the given string."""
+ id_not_starts_with: ID
+
+ """All values ending with the given string."""
+ id_ends_with: ID
+
+ """All values not ending with the given string."""
+ id_not_ends_with: ID
+ title: String
+
+ """All values that are not equal to given value."""
+ title_not: String
+
+ """All values that are contained in given list."""
+ title_in: [String!]
+
+ """All values that are not contained in given list."""
+ title_not_in: [String!]
+
+ """All values less than the given value."""
+ title_lt: String
+
+ """All values less than or equal the given value."""
+ title_lte: String
+
+ """All values greater than the given value."""
+ title_gt: String
+
+ """All values greater than or equal the given value."""
+ title_gte: String
+
+ """All values containing the given string."""
+ title_contains: String
+
+ """All values not containing the given string."""
+ title_not_contains: String
+
+ """All values starting with the given string."""
+ title_starts_with: String
+
+ """All values not starting with the given string."""
+ title_not_starts_with: String
+
+ """All values ending with the given string."""
+ title_ends_with: String
+
+ """All values not ending with the given string."""
+ title_not_ends_with: String
+ description: String
+
+ """All values that are not equal to given value."""
+ description_not: String
+
+ """All values that are contained in given list."""
+ description_in: [String!]
+
+ """All values that are not contained in given list."""
+ description_not_in: [String!]
+
+ """All values less than the given value."""
+ description_lt: String
+
+ """All values less than or equal the given value."""
+ description_lte: String
+
+ """All values greater than the given value."""
+ description_gt: String
+
+ """All values greater than or equal the given value."""
+ description_gte: String
+
+ """All values containing the given string."""
+ description_contains: String
+
+ """All values not containing the given string."""
+ description_not_contains: String
+
+ """All values starting with the given string."""
+ description_starts_with: String
+
+ """All values not starting with the given string."""
+ description_not_starts_with: String
+
+ """All values ending with the given string."""
+ description_ends_with: String
+
+ """All values not ending with the given string."""
+ description_not_ends_with: String
+ image: String
+
+ """All values that are not equal to given value."""
+ image_not: String
+
+ """All values that are contained in given list."""
+ image_in: [String!]
+
+ """All values that are not contained in given list."""
+ image_not_in: [String!]
+
+ """All values less than the given value."""
+ image_lt: String
+
+ """All values less than or equal the given value."""
+ image_lte: String
+
+ """All values greater than the given value."""
+ image_gt: String
+
+ """All values greater than or equal the given value."""
+ image_gte: String
+
+ """All values containing the given string."""
+ image_contains: String
+
+ """All values not containing the given string."""
+ image_not_contains: String
+
+ """All values starting with the given string."""
+ image_starts_with: String
+
+ """All values not starting with the given string."""
+ image_not_starts_with: String
+
+ """All values ending with the given string."""
+ image_ends_with: String
+
+ """All values not ending with the given string."""
+ image_not_ends_with: String
+ largeImage: String
+
+ """All values that are not equal to given value."""
+ largeImage_not: String
+
+ """All values that are contained in given list."""
+ largeImage_in: [String!]
+
+ """All values that are not contained in given list."""
+ largeImage_not_in: [String!]
+
+ """All values less than the given value."""
+ largeImage_lt: String
+
+ """All values less than or equal the given value."""
+ largeImage_lte: String
+
+ """All values greater than the given value."""
+ largeImage_gt: String
+
+ """All values greater than or equal the given value."""
+ largeImage_gte: String
+
+ """All values containing the given string."""
+ largeImage_contains: String
+
+ """All values not containing the given string."""
+ largeImage_not_contains: String
+
+ """All values starting with the given string."""
+ largeImage_starts_with: String
+
+ """All values not starting with the given string."""
+ largeImage_not_starts_with: String
+
+ """All values ending with the given string."""
+ largeImage_ends_with: String
+
+ """All values not ending with the given string."""
+ largeImage_not_ends_with: String
+ price: Int
+
+ """All values that are not equal to given value."""
+ price_not: Int
+
+ """All values that are contained in given list."""
+ price_in: [Int!]
+
+ """All values that are not contained in given list."""
+ price_not_in: [Int!]
+
+ """All values less than the given value."""
+ price_lt: Int
+
+ """All values less than or equal the given value."""
+ price_lte: Int
+
+ """All values greater than the given value."""
+ price_gt: Int
+
+ """All values greater than or equal the given value."""
+ price_gte: Int
+ createdAt: DateTime
+
+ """All values that are not equal to given value."""
+ createdAt_not: DateTime
+
+ """All values that are contained in given list."""
+ createdAt_in: [DateTime!]
+
+ """All values that are not contained in given list."""
+ createdAt_not_in: [DateTime!]
+
+ """All values less than the given value."""
+ createdAt_lt: DateTime
+
+ """All values less than or equal the given value."""
+ createdAt_lte: DateTime
+
+ """All values greater than the given value."""
+ createdAt_gt: DateTime
+
+ """All values greater than or equal the given value."""
+ createdAt_gte: DateTime
+ updatedAt: DateTime
+
+ """All values that are not equal to given value."""
+ updatedAt_not: DateTime
+
+ """All values that are contained in given list."""
+ updatedAt_in: [DateTime!]
+
+ """All values that are not contained in given list."""
+ updatedAt_not_in: [DateTime!]
+
+ """All values less than the given value."""
+ updatedAt_lt: DateTime
+
+ """All values less than or equal the given value."""
+ updatedAt_lte: DateTime
+
+ """All values greater than the given value."""
+ updatedAt_gt: DateTime
+
+ """All values greater than or equal the given value."""
+ updatedAt_gte: DateTime
+ user: UserWhereInput
+}
+
+input ItemWhereUniqueInput {
+ id: ID
+}
+
+"""
+The `Long` scalar type represents non-fractional signed whole numeric values.
+Long can represent values between -(2^63) and 2^63 - 1.
+"""
+scalar Long
+
+type Mutation {
+ createUser(data: UserCreateInput!): User!
+ createCartItem(data: CartItemCreateInput!): CartItem!
+ createItem(data: ItemCreateInput!): Item!
+ createOrderItem(data: OrderItemCreateInput!): OrderItem!
+ createOrder(data: OrderCreateInput!): Order!
+ updateUser(data: UserUpdateInput!, where: UserWhereUniqueInput!): User
+ updateCartItem(data: CartItemUpdateInput!, where: CartItemWhereUniqueInput!): CartItem
+ updateItem(data: ItemUpdateInput!, where: ItemWhereUniqueInput!): Item
+ updateOrderItem(data: OrderItemUpdateInput!, where: OrderItemWhereUniqueInput!): OrderItem
+ updateOrder(data: OrderUpdateInput!, where: OrderWhereUniqueInput!): Order
+ deleteUser(where: UserWhereUniqueInput!): User
+ deleteCartItem(where: CartItemWhereUniqueInput!): CartItem
+ deleteItem(where: ItemWhereUniqueInput!): Item
+ deleteOrderItem(where: OrderItemWhereUniqueInput!): OrderItem
+ deleteOrder(where: OrderWhereUniqueInput!): Order
+ upsertUser(where: UserWhereUniqueInput!, create: UserCreateInput!, update: UserUpdateInput!): User!
+ upsertCartItem(where: CartItemWhereUniqueInput!, create: CartItemCreateInput!, update: CartItemUpdateInput!): CartItem!
+ upsertItem(where: ItemWhereUniqueInput!, create: ItemCreateInput!, update: ItemUpdateInput!): Item!
+ upsertOrderItem(where: OrderItemWhereUniqueInput!, create: OrderItemCreateInput!, update: OrderItemUpdateInput!): OrderItem!
+ upsertOrder(where: OrderWhereUniqueInput!, create: OrderCreateInput!, update: OrderUpdateInput!): Order!
+ updateManyUsers(data: UserUpdateInput!, where: UserWhereInput): BatchPayload!
+ updateManyCartItems(data: CartItemUpdateInput!, where: CartItemWhereInput): BatchPayload!
+ updateManyItems(data: ItemUpdateInput!, where: ItemWhereInput): BatchPayload!
+ updateManyOrderItems(data: OrderItemUpdateInput!, where: OrderItemWhereInput): BatchPayload!
+ updateManyOrders(data: OrderUpdateInput!, where: OrderWhereInput): BatchPayload!
+ deleteManyUsers(where: UserWhereInput): BatchPayload!
+ deleteManyCartItems(where: CartItemWhereInput): BatchPayload!
+ deleteManyItems(where: ItemWhereInput): BatchPayload!
+ deleteManyOrderItems(where: OrderItemWhereInput): BatchPayload!
+ deleteManyOrders(where: OrderWhereInput): BatchPayload!
+}
+
+enum MutationType {
+ CREATED
+ UPDATED
+ DELETED
+}
+
+"""An object with an ID"""
+interface Node {
+ """The id of the object."""
+ id: ID!
+}
+
+type Order implements Node {
+ id: ID!
+ items(where: OrderItemWhereInput, orderBy: OrderItemOrderByInput, skip: Int, after: String, before: String, first: Int, last: Int): [OrderItem!]
+ total: Int!
+ user(where: UserWhereInput): User!
+ createdAt: DateTime!
+ updatedAt: DateTime!
+ charge: String!
+}
+
+"""A connection to a list of items."""
+type OrderConnection {
+ """Information to aid in pagination."""
+ pageInfo: PageInfo!
+
+ """A list of edges."""
+ edges: [OrderEdge]!
+ aggregate: AggregateOrder!
+}
+
+input OrderCreateInput {
+ total: Int!
+ charge: String!
+ items: OrderItemCreateManyInput
+ user: UserCreateOneWithoutOrdersInput!
+}
+
+input OrderCreateManyWithoutUserInput {
+ create: [OrderCreateWithoutUserInput!]
+ connect: [OrderWhereUniqueInput!]
+}
+
+input OrderCreateWithoutUserInput {
+ total: Int!
+ charge: String!
+ items: OrderItemCreateManyInput
+}
+
+"""An edge in a connection."""
+type OrderEdge {
+ """The item at the end of the edge."""
+ node: Order!
+
+ """A cursor for use in pagination."""
+ cursor: String!
+}
+
+type OrderItem implements Node {
+ id: ID!
+ title: String!
+ description: String!
+ image: String
+ largeImage: String
+ price: Int!
+ createdAt: DateTime!
+ updatedAt: DateTime!
+ quantity: Int!
+}
+
+"""A connection to a list of items."""
+type OrderItemConnection {
+ """Information to aid in pagination."""
+ pageInfo: PageInfo!
+
+ """A list of edges."""
+ edges: [OrderItemEdge]!
+ aggregate: AggregateOrderItem!
+}
+
+input OrderItemCreateInput {
+ title: String!
+ description: String!
+ image: String
+ largeImage: String
+ price: Int!
+ quantity: Int
+}
+
+input OrderItemCreateManyInput {
+ create: [OrderItemCreateInput!]
+ connect: [OrderItemWhereUniqueInput!]
+}
+
+"""An edge in a connection."""
+type OrderItemEdge {
+ """The item at the end of the edge."""
+ node: OrderItem!
+
+ """A cursor for use in pagination."""
+ cursor: String!
+}
+
+enum OrderItemOrderByInput {
+ id_ASC
+ id_DESC
+ title_ASC
+ title_DESC
+ description_ASC
+ description_DESC
+ image_ASC
+ image_DESC
+ largeImage_ASC
+ largeImage_DESC
+ price_ASC
+ price_DESC
+ createdAt_ASC
+ createdAt_DESC
+ updatedAt_ASC
+ updatedAt_DESC
+ quantity_ASC
+ quantity_DESC
+}
+
+type OrderItemPreviousValues {
+ id: ID!
+ title: String!
+ description: String!
+ image: String
+ largeImage: String
+ price: Int!
+ createdAt: DateTime!
+ updatedAt: DateTime!
+ quantity: Int!
+}
+
+type OrderItemSubscriptionPayload {
+ mutation: MutationType!
+ node: OrderItem
+ updatedFields: [String!]
+ previousValues: OrderItemPreviousValues
+}
+
+input OrderItemSubscriptionWhereInput {
+ """Logical AND on all given filters."""
+ AND: [OrderItemSubscriptionWhereInput!]
+
+ """Logical OR on all given filters."""
+ OR: [OrderItemSubscriptionWhereInput!]
+
+ """Logical NOT on all given filters combined by AND."""
+ NOT: [OrderItemSubscriptionWhereInput!]
+
+ """
+ The subscription event gets dispatched when it's listed in mutation_in
+ """
+ mutation_in: [MutationType!]
+
+ """
+ The subscription event gets only dispatched when one of the updated fields names is included in this list
+ """
+ updatedFields_contains: String
+
+ """
+ The subscription event gets only dispatched when all of the field names included in this list have been updated
+ """
+ updatedFields_contains_every: [String!]
+
+ """
+ The subscription event gets only dispatched when some of the field names included in this list have been updated
+ """
+ updatedFields_contains_some: [String!]
+ node: OrderItemWhereInput
+}
+
+input OrderItemUpdateDataInput {
+ title: String
+ description: String
+ image: String
+ largeImage: String
+ price: Int
+ quantity: Int
+}
+
+input OrderItemUpdateInput {
+ title: String
+ description: String
+ image: String
+ largeImage: String
+ price: Int
+ quantity: Int
+}
+
+input OrderItemUpdateManyInput {
+ create: [OrderItemCreateInput!]
+ connect: [OrderItemWhereUniqueInput!]
+ disconnect: [OrderItemWhereUniqueInput!]
+ delete: [OrderItemWhereUniqueInput!]
+ update: [OrderItemUpdateWithWhereUniqueNestedInput!]
+ upsert: [OrderItemUpsertWithWhereUniqueNestedInput!]
+}
+
+input OrderItemUpdateWithWhereUniqueNestedInput {
+ where: OrderItemWhereUniqueInput!
+ data: OrderItemUpdateDataInput!
+}
+
+input OrderItemUpsertWithWhereUniqueNestedInput {
+ where: OrderItemWhereUniqueInput!
+ update: OrderItemUpdateDataInput!
+ create: OrderItemCreateInput!
+}
+
+input OrderItemWhereInput {
+ """Logical AND on all given filters."""
+ AND: [OrderItemWhereInput!]
+
+ """Logical OR on all given filters."""
+ OR: [OrderItemWhereInput!]
+
+ """Logical NOT on all given filters combined by AND."""
+ NOT: [OrderItemWhereInput!]
+ id: ID
+
+ """All values that are not equal to given value."""
+ id_not: ID
+
+ """All values that are contained in given list."""
+ id_in: [ID!]
+
+ """All values that are not contained in given list."""
+ id_not_in: [ID!]
+
+ """All values less than the given value."""
+ id_lt: ID
+
+ """All values less than or equal the given value."""
+ id_lte: ID
+
+ """All values greater than the given value."""
+ id_gt: ID
+
+ """All values greater than or equal the given value."""
+ id_gte: ID
+
+ """All values containing the given string."""
+ id_contains: ID
+
+ """All values not containing the given string."""
+ id_not_contains: ID
+
+ """All values starting with the given string."""
+ id_starts_with: ID
+
+ """All values not starting with the given string."""
+ id_not_starts_with: ID
+
+ """All values ending with the given string."""
+ id_ends_with: ID
+
+ """All values not ending with the given string."""
+ id_not_ends_with: ID
+ title: String
+
+ """All values that are not equal to given value."""
+ title_not: String
+
+ """All values that are contained in given list."""
+ title_in: [String!]
+
+ """All values that are not contained in given list."""
+ title_not_in: [String!]
+
+ """All values less than the given value."""
+ title_lt: String
+
+ """All values less than or equal the given value."""
+ title_lte: String
+
+ """All values greater than the given value."""
+ title_gt: String
+
+ """All values greater than or equal the given value."""
+ title_gte: String
+
+ """All values containing the given string."""
+ title_contains: String
+
+ """All values not containing the given string."""
+ title_not_contains: String
+
+ """All values starting with the given string."""
+ title_starts_with: String
+
+ """All values not starting with the given string."""
+ title_not_starts_with: String
+
+ """All values ending with the given string."""
+ title_ends_with: String
+
+ """All values not ending with the given string."""
+ title_not_ends_with: String
+ description: String
+
+ """All values that are not equal to given value."""
+ description_not: String
+
+ """All values that are contained in given list."""
+ description_in: [String!]
+
+ """All values that are not contained in given list."""
+ description_not_in: [String!]
+
+ """All values less than the given value."""
+ description_lt: String
+
+ """All values less than or equal the given value."""
+ description_lte: String
+
+ """All values greater than the given value."""
+ description_gt: String
+
+ """All values greater than or equal the given value."""
+ description_gte: String
+
+ """All values containing the given string."""
+ description_contains: String
+
+ """All values not containing the given string."""
+ description_not_contains: String
+
+ """All values starting with the given string."""
+ description_starts_with: String
+
+ """All values not starting with the given string."""
+ description_not_starts_with: String
+
+ """All values ending with the given string."""
+ description_ends_with: String
+
+ """All values not ending with the given string."""
+ description_not_ends_with: String
+ image: String
+
+ """All values that are not equal to given value."""
+ image_not: String
+
+ """All values that are contained in given list."""
+ image_in: [String!]
+
+ """All values that are not contained in given list."""
+ image_not_in: [String!]
+
+ """All values less than the given value."""
+ image_lt: String
+
+ """All values less than or equal the given value."""
+ image_lte: String
+
+ """All values greater than the given value."""
+ image_gt: String
+
+ """All values greater than or equal the given value."""
+ image_gte: String
+
+ """All values containing the given string."""
+ image_contains: String
+
+ """All values not containing the given string."""
+ image_not_contains: String
+
+ """All values starting with the given string."""
+ image_starts_with: String
+
+ """All values not starting with the given string."""
+ image_not_starts_with: String
+
+ """All values ending with the given string."""
+ image_ends_with: String
+
+ """All values not ending with the given string."""
+ image_not_ends_with: String
+ largeImage: String
+
+ """All values that are not equal to given value."""
+ largeImage_not: String
+
+ """All values that are contained in given list."""
+ largeImage_in: [String!]
+
+ """All values that are not contained in given list."""
+ largeImage_not_in: [String!]
+
+ """All values less than the given value."""
+ largeImage_lt: String
+
+ """All values less than or equal the given value."""
+ largeImage_lte: String
+
+ """All values greater than the given value."""
+ largeImage_gt: String
+
+ """All values greater than or equal the given value."""
+ largeImage_gte: String
+
+ """All values containing the given string."""
+ largeImage_contains: String
+
+ """All values not containing the given string."""
+ largeImage_not_contains: String
+
+ """All values starting with the given string."""
+ largeImage_starts_with: String
+
+ """All values not starting with the given string."""
+ largeImage_not_starts_with: String
+
+ """All values ending with the given string."""
+ largeImage_ends_with: String
+
+ """All values not ending with the given string."""
+ largeImage_not_ends_with: String
+ price: Int
+
+ """All values that are not equal to given value."""
+ price_not: Int
+
+ """All values that are contained in given list."""
+ price_in: [Int!]
+
+ """All values that are not contained in given list."""
+ price_not_in: [Int!]
+
+ """All values less than the given value."""
+ price_lt: Int
+
+ """All values less than or equal the given value."""
+ price_lte: Int
+
+ """All values greater than the given value."""
+ price_gt: Int
+
+ """All values greater than or equal the given value."""
+ price_gte: Int
+ createdAt: DateTime
+
+ """All values that are not equal to given value."""
+ createdAt_not: DateTime
+
+ """All values that are contained in given list."""
+ createdAt_in: [DateTime!]
+
+ """All values that are not contained in given list."""
+ createdAt_not_in: [DateTime!]
+
+ """All values less than the given value."""
+ createdAt_lt: DateTime
+
+ """All values less than or equal the given value."""
+ createdAt_lte: DateTime
+
+ """All values greater than the given value."""
+ createdAt_gt: DateTime
+
+ """All values greater than or equal the given value."""
+ createdAt_gte: DateTime
+ updatedAt: DateTime
+
+ """All values that are not equal to given value."""
+ updatedAt_not: DateTime
+
+ """All values that are contained in given list."""
+ updatedAt_in: [DateTime!]
+
+ """All values that are not contained in given list."""
+ updatedAt_not_in: [DateTime!]
+
+ """All values less than the given value."""
+ updatedAt_lt: DateTime
+
+ """All values less than or equal the given value."""
+ updatedAt_lte: DateTime
+
+ """All values greater than the given value."""
+ updatedAt_gt: DateTime
+
+ """All values greater than or equal the given value."""
+ updatedAt_gte: DateTime
+ quantity: Int
+
+ """All values that are not equal to given value."""
+ quantity_not: Int
+
+ """All values that are contained in given list."""
+ quantity_in: [Int!]
+
+ """All values that are not contained in given list."""
+ quantity_not_in: [Int!]
+
+ """All values less than the given value."""
+ quantity_lt: Int
+
+ """All values less than or equal the given value."""
+ quantity_lte: Int
+
+ """All values greater than the given value."""
+ quantity_gt: Int
+
+ """All values greater than or equal the given value."""
+ quantity_gte: Int
+}
+
+input OrderItemWhereUniqueInput {
+ id: ID
+}
+
+enum OrderOrderByInput {
+ id_ASC
+ id_DESC
+ total_ASC
+ total_DESC
+ createdAt_ASC
+ createdAt_DESC
+ updatedAt_ASC
+ updatedAt_DESC
+ charge_ASC
+ charge_DESC
+}
+
+type OrderPreviousValues {
+ id: ID!
+ total: Int!
+ createdAt: DateTime!
+ updatedAt: DateTime!
+ charge: String!
+}
+
+type OrderSubscriptionPayload {
+ mutation: MutationType!
+ node: Order
+ updatedFields: [String!]
+ previousValues: OrderPreviousValues
+}
+
+input OrderSubscriptionWhereInput {
+ """Logical AND on all given filters."""
+ AND: [OrderSubscriptionWhereInput!]
+
+ """Logical OR on all given filters."""
+ OR: [OrderSubscriptionWhereInput!]
+
+ """Logical NOT on all given filters combined by AND."""
+ NOT: [OrderSubscriptionWhereInput!]
+
+ """
+ The subscription event gets dispatched when it's listed in mutation_in
+ """
+ mutation_in: [MutationType!]
+
+ """
+ The subscription event gets only dispatched when one of the updated fields names is included in this list
+ """
+ updatedFields_contains: String
+
+ """
+ The subscription event gets only dispatched when all of the field names included in this list have been updated
+ """
+ updatedFields_contains_every: [String!]
+
+ """
+ The subscription event gets only dispatched when some of the field names included in this list have been updated
+ """
+ updatedFields_contains_some: [String!]
+ node: OrderWhereInput
+}
+
+input OrderUpdateInput {
+ total: Int
+ charge: String
+ items: OrderItemUpdateManyInput
+ user: UserUpdateOneWithoutOrdersInput
+}
+
+input OrderUpdateManyWithoutUserInput {
+ create: [OrderCreateWithoutUserInput!]
+ connect: [OrderWhereUniqueInput!]
+ disconnect: [OrderWhereUniqueInput!]
+ delete: [OrderWhereUniqueInput!]
+ update: [OrderUpdateWithWhereUniqueWithoutUserInput!]
+ upsert: [OrderUpsertWithWhereUniqueWithoutUserInput!]
+}
+
+input OrderUpdateWithoutUserDataInput {
+ total: Int
+ charge: String
+ items: OrderItemUpdateManyInput
+}
+
+input OrderUpdateWithWhereUniqueWithoutUserInput {
+ where: OrderWhereUniqueInput!
+ data: OrderUpdateWithoutUserDataInput!
+}
+
+input OrderUpsertWithWhereUniqueWithoutUserInput {
+ where: OrderWhereUniqueInput!
+ update: OrderUpdateWithoutUserDataInput!
+ create: OrderCreateWithoutUserInput!
+}
+
+input OrderWhereInput {
+ """Logical AND on all given filters."""
+ AND: [OrderWhereInput!]
+
+ """Logical OR on all given filters."""
+ OR: [OrderWhereInput!]
+
+ """Logical NOT on all given filters combined by AND."""
+ NOT: [OrderWhereInput!]
+ id: ID
+
+ """All values that are not equal to given value."""
+ id_not: ID
+
+ """All values that are contained in given list."""
+ id_in: [ID!]
+
+ """All values that are not contained in given list."""
+ id_not_in: [ID!]
+
+ """All values less than the given value."""
+ id_lt: ID
+
+ """All values less than or equal the given value."""
+ id_lte: ID
+
+ """All values greater than the given value."""
+ id_gt: ID
+
+ """All values greater than or equal the given value."""
+ id_gte: ID
+
+ """All values containing the given string."""
+ id_contains: ID
+
+ """All values not containing the given string."""
+ id_not_contains: ID
+
+ """All values starting with the given string."""
+ id_starts_with: ID
+
+ """All values not starting with the given string."""
+ id_not_starts_with: ID
+
+ """All values ending with the given string."""
+ id_ends_with: ID
+
+ """All values not ending with the given string."""
+ id_not_ends_with: ID
+ total: Int
+
+ """All values that are not equal to given value."""
+ total_not: Int
+
+ """All values that are contained in given list."""
+ total_in: [Int!]
+
+ """All values that are not contained in given list."""
+ total_not_in: [Int!]
+
+ """All values less than the given value."""
+ total_lt: Int
+
+ """All values less than or equal the given value."""
+ total_lte: Int
+
+ """All values greater than the given value."""
+ total_gt: Int
+
+ """All values greater than or equal the given value."""
+ total_gte: Int
+ createdAt: DateTime
+
+ """All values that are not equal to given value."""
+ createdAt_not: DateTime
+
+ """All values that are contained in given list."""
+ createdAt_in: [DateTime!]
+
+ """All values that are not contained in given list."""
+ createdAt_not_in: [DateTime!]
+
+ """All values less than the given value."""
+ createdAt_lt: DateTime
+
+ """All values less than or equal the given value."""
+ createdAt_lte: DateTime
+
+ """All values greater than the given value."""
+ createdAt_gt: DateTime
+
+ """All values greater than or equal the given value."""
+ createdAt_gte: DateTime
+ updatedAt: DateTime
+
+ """All values that are not equal to given value."""
+ updatedAt_not: DateTime
+
+ """All values that are contained in given list."""
+ updatedAt_in: [DateTime!]
+
+ """All values that are not contained in given list."""
+ updatedAt_not_in: [DateTime!]
+
+ """All values less than the given value."""
+ updatedAt_lt: DateTime
+
+ """All values less than or equal the given value."""
+ updatedAt_lte: DateTime
+
+ """All values greater than the given value."""
+ updatedAt_gt: DateTime
+
+ """All values greater than or equal the given value."""
+ updatedAt_gte: DateTime
+ charge: String
+
+ """All values that are not equal to given value."""
+ charge_not: String
+
+ """All values that are contained in given list."""
+ charge_in: [String!]
+
+ """All values that are not contained in given list."""
+ charge_not_in: [String!]
+
+ """All values less than the given value."""
+ charge_lt: String
+
+ """All values less than or equal the given value."""
+ charge_lte: String
+
+ """All values greater than the given value."""
+ charge_gt: String
+
+ """All values greater than or equal the given value."""
+ charge_gte: String
+
+ """All values containing the given string."""
+ charge_contains: String
+
+ """All values not containing the given string."""
+ charge_not_contains: String
+
+ """All values starting with the given string."""
+ charge_starts_with: String
+
+ """All values not starting with the given string."""
+ charge_not_starts_with: String
+
+ """All values ending with the given string."""
+ charge_ends_with: String
+
+ """All values not ending with the given string."""
+ charge_not_ends_with: String
+ items_every: OrderItemWhereInput
+ items_some: OrderItemWhereInput
+ items_none: OrderItemWhereInput
+ user: UserWhereInput
+}
+
+input OrderWhereUniqueInput {
+ id: ID
+}
+
+"""Information about pagination in a connection."""
+type PageInfo {
+ """When paginating forwards, are there more items?"""
+ hasNextPage: Boolean!
+
+ """When paginating backwards, are there more items?"""
+ hasPreviousPage: Boolean!
+
+ """When paginating backwards, the cursor to continue."""
+ startCursor: String
+
+ """When paginating forwards, the cursor to continue."""
+ endCursor: String
+}
+
+enum Permission {
+ ADMIN
+ USER
+ ITEMCREATE
+ ITEMUPDATE
+ ITEMDELETE
+ PERMISSIONUPDATE
+}
+
+type Query {
+ users(where: UserWhereInput, orderBy: UserOrderByInput, skip: Int, after: String, before: String, first: Int, last: Int): [User]!
+ cartItems(where: CartItemWhereInput, orderBy: CartItemOrderByInput, skip: Int, after: String, before: String, first: Int, last: Int): [CartItem]!
+ items(where: ItemWhereInput, orderBy: ItemOrderByInput, skip: Int, after: String, before: String, first: Int, last: Int): [Item]!
+ orderItems(where: OrderItemWhereInput, orderBy: OrderItemOrderByInput, skip: Int, after: String, before: String, first: Int, last: Int): [OrderItem]!
+ orders(where: OrderWhereInput, orderBy: OrderOrderByInput, skip: Int, after: String, before: String, first: Int, last: Int): [Order]!
+ user(where: UserWhereUniqueInput!): User
+ cartItem(where: CartItemWhereUniqueInput!): CartItem
+ item(where: ItemWhereUniqueInput!): Item
+ orderItem(where: OrderItemWhereUniqueInput!): OrderItem
+ order(where: OrderWhereUniqueInput!): Order
+ usersConnection(where: UserWhereInput, orderBy: UserOrderByInput, skip: Int, after: String, before: String, first: Int, last: Int): UserConnection!
+ cartItemsConnection(where: CartItemWhereInput, orderBy: CartItemOrderByInput, skip: Int, after: String, before: String, first: Int, last: Int): CartItemConnection!
+ itemsConnection(where: ItemWhereInput, orderBy: ItemOrderByInput, skip: Int, after: String, before: String, first: Int, last: Int): ItemConnection!
+ orderItemsConnection(where: OrderItemWhereInput, orderBy: OrderItemOrderByInput, skip: Int, after: String, before: String, first: Int, last: Int): OrderItemConnection!
+ ordersConnection(where: OrderWhereInput, orderBy: OrderOrderByInput, skip: Int, after: String, before: String, first: Int, last: Int): OrderConnection!
+
+ """Fetches an object given its ID"""
+ node(
+ """The ID of an object"""
+ id: ID!
+ ): Node
+}
+
+type Subscription {
+ user(where: UserSubscriptionWhereInput): UserSubscriptionPayload
+ cartItem(where: CartItemSubscriptionWhereInput): CartItemSubscriptionPayload
+ item(where: ItemSubscriptionWhereInput): ItemSubscriptionPayload
+ orderItem(where: OrderItemSubscriptionWhereInput): OrderItemSubscriptionPayload
+ order(where: OrderSubscriptionWhereInput): OrderSubscriptionPayload
+}
+
+type User implements Node {
+ id: ID!
+ email: String!
+ password: String!
+ name: String!
+ orders(where: OrderWhereInput, orderBy: OrderOrderByInput, skip: Int, after: String, before: String, first: Int, last: Int): [Order!]
+ resetToken: String
+ resetTokenExpiry: String
+ cart(where: CartItemWhereInput, orderBy: CartItemOrderByInput, skip: Int, after: String, before: String, first: Int, last: Int): [CartItem!]
+ createdAt: DateTime!
+ updatedAt: DateTime!
+ permissions: [Permission!]
+}
+
+"""A connection to a list of items."""
+type UserConnection {
+ """Information to aid in pagination."""
+ pageInfo: PageInfo!
+
+ """A list of edges."""
+ edges: [UserEdge]!
+ aggregate: AggregateUser!
+}
+
+input UserCreateInput {
+ email: String!
+ password: String!
+ name: String!
+ resetToken: String
+ resetTokenExpiry: String
+ permissions: UserCreatepermissionsInput
+ orders: OrderCreateManyWithoutUserInput
+ cart: CartItemCreateManyWithoutUserInput
+}
+
+input UserCreateOneInput {
+ create: UserCreateInput
+ connect: UserWhereUniqueInput
+}
+
+input UserCreateOneWithoutCartInput {
+ create: UserCreateWithoutCartInput
+ connect: UserWhereUniqueInput
+}
+
+input UserCreateOneWithoutOrdersInput {
+ create: UserCreateWithoutOrdersInput
+ connect: UserWhereUniqueInput
+}
+
+input UserCreatepermissionsInput {
+ set: [Permission!]
+}
+
+input UserCreateWithoutCartInput {
+ email: String!
+ password: String!
+ name: String!
+ resetToken: String
+ resetTokenExpiry: String
+ permissions: UserCreatepermissionsInput
+ orders: OrderCreateManyWithoutUserInput
+}
+
+input UserCreateWithoutOrdersInput {
+ email: String!
+ password: String!
+ name: String!
+ resetToken: String
+ resetTokenExpiry: String
+ permissions: UserCreatepermissionsInput
+ cart: CartItemCreateManyWithoutUserInput
+}
+
+"""An edge in a connection."""
+type UserEdge {
+ """The item at the end of the edge."""
+ node: User!
+
+ """A cursor for use in pagination."""
+ cursor: String!
+}
+
+enum UserOrderByInput {
+ id_ASC
+ id_DESC
+ email_ASC
+ email_DESC
+ password_ASC
+ password_DESC
+ name_ASC
+ name_DESC
+ resetToken_ASC
+ resetToken_DESC
+ resetTokenExpiry_ASC
+ resetTokenExpiry_DESC
+ createdAt_ASC
+ createdAt_DESC
+ updatedAt_ASC
+ updatedAt_DESC
+}
+
+type UserPreviousValues {
+ id: ID!
+ email: String!
+ password: String!
+ name: String!
+ resetToken: String
+ resetTokenExpiry: String
+ createdAt: DateTime!
+ updatedAt: DateTime!
+ permissions: [Permission!]
+}
+
+type UserSubscriptionPayload {
+ mutation: MutationType!
+ node: User
+ updatedFields: [String!]
+ previousValues: UserPreviousValues
+}
+
+input UserSubscriptionWhereInput {
+ """Logical AND on all given filters."""
+ AND: [UserSubscriptionWhereInput!]
+
+ """Logical OR on all given filters."""
+ OR: [UserSubscriptionWhereInput!]
+
+ """Logical NOT on all given filters combined by AND."""
+ NOT: [UserSubscriptionWhereInput!]
+
+ """
+ The subscription event gets dispatched when it's listed in mutation_in
+ """
+ mutation_in: [MutationType!]
+
+ """
+ The subscription event gets only dispatched when one of the updated fields names is included in this list
+ """
+ updatedFields_contains: String
+
+ """
+ The subscription event gets only dispatched when all of the field names included in this list have been updated
+ """
+ updatedFields_contains_every: [String!]
+
+ """
+ The subscription event gets only dispatched when some of the field names included in this list have been updated
+ """
+ updatedFields_contains_some: [String!]
+ node: UserWhereInput
+}
+
+input UserUpdateDataInput {
+ email: String
+ password: String
+ name: String
+ resetToken: String
+ resetTokenExpiry: String
+ permissions: UserUpdatepermissionsInput
+ orders: OrderUpdateManyWithoutUserInput
+ cart: CartItemUpdateManyWithoutUserInput
+}
+
+input UserUpdateInput {
+ email: String
+ password: String
+ name: String
+ resetToken: String
+ resetTokenExpiry: String
+ permissions: UserUpdatepermissionsInput
+ orders: OrderUpdateManyWithoutUserInput
+ cart: CartItemUpdateManyWithoutUserInput
+}
+
+input UserUpdateOneInput {
+ create: UserCreateInput
+ connect: UserWhereUniqueInput
+ delete: Boolean
+ update: UserUpdateDataInput
+ upsert: UserUpsertNestedInput
+}
+
+input UserUpdateOneWithoutCartInput {
+ create: UserCreateWithoutCartInput
+ connect: UserWhereUniqueInput
+ delete: Boolean
+ update: UserUpdateWithoutCartDataInput
+ upsert: UserUpsertWithoutCartInput
+}
+
+input UserUpdateOneWithoutOrdersInput {
+ create: UserCreateWithoutOrdersInput
+ connect: UserWhereUniqueInput
+ delete: Boolean
+ update: UserUpdateWithoutOrdersDataInput
+ upsert: UserUpsertWithoutOrdersInput
+}
+
+input UserUpdatepermissionsInput {
+ set: [Permission!]
+}
+
+input UserUpdateWithoutCartDataInput {
+ email: String
+ password: String
+ name: String
+ resetToken: String
+ resetTokenExpiry: String
+ permissions: UserUpdatepermissionsInput
+ orders: OrderUpdateManyWithoutUserInput
+}
+
+input UserUpdateWithoutOrdersDataInput {
+ email: String
+ password: String
+ name: String
+ resetToken: String
+ resetTokenExpiry: String
+ permissions: UserUpdatepermissionsInput
+ cart: CartItemUpdateManyWithoutUserInput
+}
+
+input UserUpsertNestedInput {
+ update: UserUpdateDataInput!
+ create: UserCreateInput!
+}
+
+input UserUpsertWithoutCartInput {
+ update: UserUpdateWithoutCartDataInput!
+ create: UserCreateWithoutCartInput!
+}
+
+input UserUpsertWithoutOrdersInput {
+ update: UserUpdateWithoutOrdersDataInput!
+ create: UserCreateWithoutOrdersInput!
+}
+
+input UserWhereInput {
+ """Logical AND on all given filters."""
+ AND: [UserWhereInput!]
+
+ """Logical OR on all given filters."""
+ OR: [UserWhereInput!]
+
+ """Logical NOT on all given filters combined by AND."""
+ NOT: [UserWhereInput!]
+ id: ID
+
+ """All values that are not equal to given value."""
+ id_not: ID
+
+ """All values that are contained in given list."""
+ id_in: [ID!]
+
+ """All values that are not contained in given list."""
+ id_not_in: [ID!]
+
+ """All values less than the given value."""
+ id_lt: ID
+
+ """All values less than or equal the given value."""
+ id_lte: ID
+
+ """All values greater than the given value."""
+ id_gt: ID
+
+ """All values greater than or equal the given value."""
+ id_gte: ID
+
+ """All values containing the given string."""
+ id_contains: ID
+
+ """All values not containing the given string."""
+ id_not_contains: ID
+
+ """All values starting with the given string."""
+ id_starts_with: ID
+
+ """All values not starting with the given string."""
+ id_not_starts_with: ID
+
+ """All values ending with the given string."""
+ id_ends_with: ID
+
+ """All values not ending with the given string."""
+ id_not_ends_with: ID
+ email: String
+
+ """All values that are not equal to given value."""
+ email_not: String
+
+ """All values that are contained in given list."""
+ email_in: [String!]
+
+ """All values that are not contained in given list."""
+ email_not_in: [String!]
+
+ """All values less than the given value."""
+ email_lt: String
+
+ """All values less than or equal the given value."""
+ email_lte: String
+
+ """All values greater than the given value."""
+ email_gt: String
+
+ """All values greater than or equal the given value."""
+ email_gte: String
+
+ """All values containing the given string."""
+ email_contains: String
+
+ """All values not containing the given string."""
+ email_not_contains: String
+
+ """All values starting with the given string."""
+ email_starts_with: String
+
+ """All values not starting with the given string."""
+ email_not_starts_with: String
+
+ """All values ending with the given string."""
+ email_ends_with: String
+
+ """All values not ending with the given string."""
+ email_not_ends_with: String
+ password: String
+
+ """All values that are not equal to given value."""
+ password_not: String
+
+ """All values that are contained in given list."""
+ password_in: [String!]
+
+ """All values that are not contained in given list."""
+ password_not_in: [String!]
+
+ """All values less than the given value."""
+ password_lt: String
+
+ """All values less than or equal the given value."""
+ password_lte: String
+
+ """All values greater than the given value."""
+ password_gt: String
+
+ """All values greater than or equal the given value."""
+ password_gte: String
+
+ """All values containing the given string."""
+ password_contains: String
+
+ """All values not containing the given string."""
+ password_not_contains: String
+
+ """All values starting with the given string."""
+ password_starts_with: String
+
+ """All values not starting with the given string."""
+ password_not_starts_with: String
+
+ """All values ending with the given string."""
+ password_ends_with: String
+
+ """All values not ending with the given string."""
+ password_not_ends_with: String
+ name: String
+
+ """All values that are not equal to given value."""
+ name_not: String
+
+ """All values that are contained in given list."""
+ name_in: [String!]
+
+ """All values that are not contained in given list."""
+ name_not_in: [String!]
+
+ """All values less than the given value."""
+ name_lt: String
+
+ """All values less than or equal the given value."""
+ name_lte: String
+
+ """All values greater than the given value."""
+ name_gt: String
+
+ """All values greater than or equal the given value."""
+ name_gte: String
+
+ """All values containing the given string."""
+ name_contains: String
+
+ """All values not containing the given string."""
+ name_not_contains: String
+
+ """All values starting with the given string."""
+ name_starts_with: String
+
+ """All values not starting with the given string."""
+ name_not_starts_with: String
+
+ """All values ending with the given string."""
+ name_ends_with: String
+
+ """All values not ending with the given string."""
+ name_not_ends_with: String
+ resetToken: String
+
+ """All values that are not equal to given value."""
+ resetToken_not: String
+
+ """All values that are contained in given list."""
+ resetToken_in: [String!]
+
+ """All values that are not contained in given list."""
+ resetToken_not_in: [String!]
+
+ """All values less than the given value."""
+ resetToken_lt: String
+
+ """All values less than or equal the given value."""
+ resetToken_lte: String
+
+ """All values greater than the given value."""
+ resetToken_gt: String
+
+ """All values greater than or equal the given value."""
+ resetToken_gte: String
+
+ """All values containing the given string."""
+ resetToken_contains: String
+
+ """All values not containing the given string."""
+ resetToken_not_contains: String
+
+ """All values starting with the given string."""
+ resetToken_starts_with: String
+
+ """All values not starting with the given string."""
+ resetToken_not_starts_with: String
+
+ """All values ending with the given string."""
+ resetToken_ends_with: String
+
+ """All values not ending with the given string."""
+ resetToken_not_ends_with: String
+ resetTokenExpiry: String
+
+ """All values that are not equal to given value."""
+ resetTokenExpiry_not: String
+
+ """All values that are contained in given list."""
+ resetTokenExpiry_in: [String!]
+
+ """All values that are not contained in given list."""
+ resetTokenExpiry_not_in: [String!]
+
+ """All values less than the given value."""
+ resetTokenExpiry_lt: String
+
+ """All values less than or equal the given value."""
+ resetTokenExpiry_lte: String
+
+ """All values greater than the given value."""
+ resetTokenExpiry_gt: String
+
+ """All values greater than or equal the given value."""
+ resetTokenExpiry_gte: String
+
+ """All values containing the given string."""
+ resetTokenExpiry_contains: String
+
+ """All values not containing the given string."""
+ resetTokenExpiry_not_contains: String
+
+ """All values starting with the given string."""
+ resetTokenExpiry_starts_with: String
+
+ """All values not starting with the given string."""
+ resetTokenExpiry_not_starts_with: String
+
+ """All values ending with the given string."""
+ resetTokenExpiry_ends_with: String
+
+ """All values not ending with the given string."""
+ resetTokenExpiry_not_ends_with: String
+ createdAt: DateTime
+
+ """All values that are not equal to given value."""
+ createdAt_not: DateTime
+
+ """All values that are contained in given list."""
+ createdAt_in: [DateTime!]
+
+ """All values that are not contained in given list."""
+ createdAt_not_in: [DateTime!]
+
+ """All values less than the given value."""
+ createdAt_lt: DateTime
+
+ """All values less than or equal the given value."""
+ createdAt_lte: DateTime
+
+ """All values greater than the given value."""
+ createdAt_gt: DateTime
+
+ """All values greater than or equal the given value."""
+ createdAt_gte: DateTime
+ updatedAt: DateTime
+
+ """All values that are not equal to given value."""
+ updatedAt_not: DateTime
+
+ """All values that are contained in given list."""
+ updatedAt_in: [DateTime!]
+
+ """All values that are not contained in given list."""
+ updatedAt_not_in: [DateTime!]
+
+ """All values less than the given value."""
+ updatedAt_lt: DateTime
+
+ """All values less than or equal the given value."""
+ updatedAt_lte: DateTime
+
+ """All values greater than the given value."""
+ updatedAt_gt: DateTime
+
+ """All values greater than or equal the given value."""
+ updatedAt_gte: DateTime
+ orders_every: OrderWhereInput
+ orders_some: OrderWhereInput
+ orders_none: OrderWhereInput
+ cart_every: CartItemWhereInput
+ cart_some: CartItemWhereInput
+ cart_none: CartItemWhereInput
+}
+
+input UserWhereUniqueInput {
+ id: ID
+ email: String
+}
diff --git a/sick-fits/backend/src/index.js b/sick-fits/backend/src/index.js
new file mode 100644
index 0000000..94911ec
--- /dev/null
+++ b/sick-fits/backend/src/index.js
@@ -0,0 +1,41 @@
+/* eslint-disable */
+require('dotenv').config({ path: 'variables.env' });
+/* eslint-enable */
+const jwt = require('jsonwebtoken');
+const createServer = require('./createServer');
+const db = require('./db');
+const cookieParser = require('cookie-parser');
+
+const server = createServer();
+
+server.express.use(cookieParser());
+
+server.express.use((req, res, next) => {
+ const { token } = req.cookies;
+ if (token) {
+ const { userId } = jwt.verify(token, process.env.APP_SECRET);
+ req.userId = userId;
+ }
+ next();
+});
+
+// 2. Get User from their ID
+server.express.use(async (req, res, next) => {
+ if (!req.userId) return next();
+ const user = await db.query.user({ where: { id: req.userId } }, `{ id, permissions, email, name }`);
+ req.user = user;
+ next();
+});
+
+server.start(
+ {
+ cors: {
+ credentials: true,
+ origin: process.env.FRONTEND_URL,
+ },
+ port: 4444,
+ },
+ deets => {
+ console.log(`Server is running on http://localhost:${deets.port}`);
+ }
+);
diff --git a/sick-fits/backend/src/mail.js b/sick-fits/backend/src/mail.js
new file mode 100644
index 0000000..fc4a47b
--- /dev/null
+++ b/sick-fits/backend/src/mail.js
@@ -0,0 +1,28 @@
+const nodemailer = require('nodemailer');
+
+const transport = nodemailer.createTransport({
+ host: 'smtp.mailtrap.io',
+ port: 2525,
+ auth: {
+ user: 'c41bab08214808',
+ pass: '04992d4af4bdcf',
+ },
+});
+
+const makeANiceEmail = text => `
+ <div className="email" style="
+ border:1px solid black;
+ padding: 20px;
+ font-family: sans-serif;
+ line-height: 2;
+ font-size: 20px;
+ ">
+ <h2>Hello There</h2>
+ <p>${text}</p>
+
+ <p>😘 Wes Bos</p>
+ </div>
+`;
+
+exports.transport = transport;
+exports.makeANiceEmail = makeANiceEmail;
diff --git a/sick-fits/backend/src/resolvers/Mutation.js b/sick-fits/backend/src/resolvers/Mutation.js
new file mode 100644
index 0000000..0f1d9ba
--- /dev/null
+++ b/sick-fits/backend/src/resolvers/Mutation.js
@@ -0,0 +1,354 @@
+const bcrypt = require('bcryptjs');
+const jwt = require('jsonwebtoken');
+const { hasPermission } = require('../utils');
+const { randomBytes } = require('crypto');
+const { promisify } = require('util');
+const mail = require('../mail');
+const stripe = require('../stripe');
+
+const mutations = {
+ // Signup Mutations
+ async signup(parent, args, ctx, info) {
+ args.email = args.email.toLowerCase();
+ const password = await bcrypt.hash(args.password, 10);
+ const user = await ctx.db.mutation.createUser(
+ {
+ data: {
+ ...args,
+ password,
+ permissions: { set: ['USER'] },
+ },
+ },
+ info
+ );
+ const token = jwt.sign({ userId: user.id }, process.env.APP_SECRET);
+ ctx.response.cookie('token', token, {
+ maxAge: 1000 * 60 * 60 * 24 * 365,
+ httpOnly: true,
+ });
+ return user;
+ },
+
+ async signout(parent, args, ctx, info) {
+ ctx.response.clearCookie('token');
+ return { message: 'goodbye!' };
+ },
+
+ async signin(parent, { email, password }, ctx, info) {
+ const user = await ctx.db.query.user({ where: { email } });
+ if (!user) {
+ throw new Error(`No such user found for email: ${email}`);
+ }
+
+ const valid = await bcrypt.compare(password, user.password);
+ if (!valid) {
+ throw new Error('Invalid password');
+ }
+ // set the cookie
+ const token = jwt.sign({ userId: user.id }, process.env.APP_SECRET);
+ ctx.response.cookie('token', token, {
+ maxAge: 1000 * 60 * 60 * 24 * 365,
+ httpOnly: true,
+ });
+ return user;
+ },
+
+ // Create An Item
+ async createItem(parent, args, ctx, info) {
+ if (!ctx.request.userId) {
+ throw new Error('You must be logged in to create an item');
+ }
+
+ const item = await ctx.db.mutation.createItem(
+ {
+ data: {
+ user: {
+ connect: {
+ id: ctx.request.userId,
+ },
+ },
+ ...args,
+ },
+ },
+ info
+ );
+ return item;
+ },
+
+ async deleteItem(parent, args, ctx, info) {
+ const where = {
+ id: args.id,
+ };
+ // 1. find the item
+ const item = await ctx.db.query.item({ where }, `{ user {id}, title, id, description }`);
+ // 2. if they 1. Don't own it AND 2. aren't an admin
+ if (item.user.id !== ctx.request.user.id && !ctx.request.user.permissions.includes('ADMIN')) {
+ throw new Error("You aren't allowed to delete that item!");
+ }
+
+ // 3. remove any orderItems this item is in
+
+ return ctx.db.mutation.deleteItem({ where }, info);
+ },
+
+ async updateItem(parent, args, ctx, info) {
+ const user = ctx.request.user;
+ const item = await ctx.db.query.item({ where: { id: args.id } }, `{ user { id } }`);
+
+ if (item.user.id !== user.id || !hasPermission(user, ['ADMIN'])) {
+ throw new Error('You are not allowed to update that item!');
+ }
+
+ const updates = { ...args };
+ // remove the ID because you can't update that
+ delete updates.id;
+ return ctx.db.mutation.updateItem(
+ {
+ where: { id: args.id },
+ data: {
+ ...updates,
+ },
+ },
+ info
+ );
+ },
+
+ // Send password request
+ async requestReset(parent, args, ctx, info) {
+ // 1. find if there is a user with that email
+ const user = await ctx.db.query.user({ where: { email: args.email } });
+
+ if (!user) {
+ throw new Error(`No user with the email ${args.email}`);
+ }
+ // 2. Set a reset token, and a reset date
+ const resetToken = (await promisify(randomBytes)(20)).toString('hex');
+ const resetTokenExpiry = Date.now() + 3600000; // 1 hour from now
+ console.log({ resetToken, resetTokenExpiry });
+ const res = await ctx.db.mutation.updateUser({
+ where: { email: args.email },
+ data: { resetToken, resetTokenExpiry },
+ });
+
+ // 3. Send them their token via email
+ const mailRes = await mail.transport.sendMail({
+ from: 'wesbos@gmail.com',
+ to: user.email,
+ subject: 'Your password reset token',
+ html: mail.makeANiceEmail(
+ `Your password reset link is here! \n\n<a href="${process.env
+ .FRONTEND_URL}/reset?resetToken=${resetToken}">Click Here to reset</a>`
+ ),
+ });
+ return res.updateUser;
+ },
+
+ async resetPassword(parent, args, ctx, info) {
+ // 1. Check that the passwords match
+ if (args.password !== args.confirmPassword) {
+ throw new Error('Passwords do not match');
+ }
+
+ // 2. Check that this is a legit resetToken
+ // 3. Check that it's not expired
+ // Note: If we didn't need the user here, we could also use db.exists()
+ const [user] = await ctx.db.query.users({
+ where: {
+ resetToken: args.resetToken,
+ resetTokenExpiry_gte: Date.now() - 3600000, // within the last hour
+ },
+ });
+
+ if (!user) {
+ throw new Error('This token is either invalid or expired.');
+ }
+
+ // 4. Hash the password
+ const password = await bcrypt.hash(args.password, 10);
+
+ // 5. Update the users password
+ // clean up the resetToken fields at the same time
+ const updatedUser = await ctx.db.mutation.updateUser({
+ where: { email: user.email },
+ data: {
+ password,
+ resetToken: null,
+ resetTokenExpiry: null,
+ },
+ });
+ const token = jwt.sign({ userId: updatedUser.id }, process.env.APP_SECRET);
+ ctx.response.cookie('token', token, {
+ maxAge: 1000 * 60 * 60 * 24 * 365,
+ httpOnly: true,
+ });
+
+ // 6. send back the User for the GraphQL request on the client
+ return updatedUser;
+ },
+ /*
+ Add to cart
+ */
+ async addToCart(parent, args, ctx, info) {
+ const userId = ctx.request.userId;
+
+ if (!userId) {
+ throw new Error('You must be signed in to add to cart!');
+ }
+
+ // 1. Check if there is a CartItem for this user and item already
+ const [existingCartItem] = await ctx.db.query.cartItems({
+ where: {
+ user: { id: userId },
+ item: { id: args.id },
+ },
+ });
+
+ if (existingCartItem) {
+ return ctx.db.mutation.updateCartItem(
+ {
+ where: { id: existingCartItem.id },
+ data: { quantity: existingCartItem.quantity + 1 },
+ },
+ info
+ );
+ }
+
+ // Otherwise create a new cartItem
+ return ctx.db.mutation.createCartItem(
+ {
+ data: {
+ user: {
+ connect: {
+ id: userId,
+ },
+ },
+ item: {
+ connect: { id: args.id },
+ },
+ },
+ },
+ info
+ );
+ },
+
+ // delete that cart item
+ async removeFromCart(parent, args, ctx, info) {
+ console.log(args.id);
+ // 1. Find the CartItem
+ const cartItem = await ctx.db.query.cartItem(
+ {
+ where: { id: args.id },
+ },
+ `{ id, user { id, permissions }}`
+ );
+ // 2. Check they own it
+ if (cartItem.user.id !== ctx.request.userId) {
+ throw new Error("Cheatin' huh");
+ }
+ // 3. Delete it
+ return ctx.db.mutation.deleteCartItem(
+ {
+ where: {
+ id: args.id,
+ },
+ },
+ info
+ );
+ },
+
+ async createOrder(parent, args, ctx, info) {
+ const userId = ctx.request.userId;
+ const user = await ctx.db.query.user(
+ { where: { id: userId } },
+ '{ id, name, email, cart { id, quantity, item { title, price, id, description, image } }}'
+ );
+ // 1. Recalculate the total for the price
+ const amount = user.cart.reduce(
+ (tally, cartItem) => tally + cartItem.item.price * cartItem.quantity,
+ 0
+ );
+ // 2. Create a stripe charge
+ const charge = await stripe.charges.create({
+ amount,
+ currency: 'usd',
+ source: args.token,
+ });
+
+ // 3. convert the items they want to OrderItems
+ const orderItems = user.cart.map(cartItem => {
+ const orderItem = {
+ quantity: cartItem.quantity,
+ // copy all the item details so it's there forever
+ ...cartItem.item,
+ item: {
+ // relationship to the Item incase we need it
+ connect: { id: cartItem.item.id },
+ },
+ user: { connect: { id: user.id } },
+ };
+ // scrub the ID from it because the orderItem will have it's own ID
+ delete orderItem.id;
+ return orderItem;
+ });
+
+ // 4. Create the Order
+ const order = await ctx.db.mutation.createOrder({
+ data: {
+ total: charge.amount,
+ charge: charge.id,
+ items: {
+ create: orderItems,
+ },
+ user: {
+ connect: {
+ id: user.id,
+ },
+ },
+ },
+ });
+
+ // 5. Clean up, clear the users cart and send back { user, order }
+ // Delete the users current cart items
+ const cartItemIds = user.cart.map(cartItem => cartItem.id);
+ await ctx.db.mutation.deleteManyCartItems({
+ where: {
+ id_in: cartItemIds,
+ },
+ });
+
+ // 6. Send the order back to the client
+ return order;
+ },
+
+ async updateUser(parent, args, ctx, info) {
+ const userId = ctx.request.userId;
+ const updatedUser = await ctx.db.mutation.updateUser(
+ {
+ data: args,
+ where: { id: userId },
+ },
+ info
+ );
+ return updatedUser;
+ },
+
+ async updatePermissions(parent, args, ctx, info) {
+ const userId = ctx.request.userId;
+ const currentUser = await ctx.db.query.user({ where: { id: userId } }, info);
+ if (!currentUser) throw new Error('You Must be logged in to updat permissions!');
+ hasPermission(currentUser, ['ADMIN', 'PERMISSIONUPDATE']);
+ return ctx.db.mutation.updateUser(
+ {
+ data: {
+ permissions: {
+ set: args.permissions,
+ },
+ },
+ where: { id: args.userId },
+ },
+ info
+ );
+ },
+};
+
+module.exports = mutations;
diff --git a/sick-fits/backend/src/resolvers/Query.js b/sick-fits/backend/src/resolvers/Query.js
new file mode 100644
index 0000000..51c2c42
--- /dev/null
+++ b/sick-fits/backend/src/resolvers/Query.js
@@ -0,0 +1,62 @@
+const { hasPermission } = require('../utils');
+
+const { forwardTo } = require('prisma-binding');
+
+const Query = {
+ items: forwardTo('db'),
+ itemsConnection: forwardTo('db'),
+
+ async order(parent, args, ctx, info) {
+ // 1. make sure they are signed in
+ if (!ctx.request.userId) {
+ throw new Error('You Must be signed in to view an order');
+ }
+
+ // 2. Create the query
+ const where = {
+ id: args.id,
+ user: {
+ id: ctx.request.userId,
+ },
+ };
+ // 3. Fire off the query
+ const [order] = await ctx.db.query.orders({ where }, info);
+
+ // 4. Check that they are allowed to view the order
+ if (order.user.id !== ctx.request.userId || hasPermission(ctx.request.user, ['ADMIN'])) {
+ throw new Error("You don't have permission");
+ }
+ // 5. If everything checks out, return the order
+ return order;
+ },
+
+ me(parent, args, ctx, info) {
+ if (!ctx.request.userId) {
+ return null; // don't error out, just return nothing
+ }
+
+ return ctx.db.query.user(
+ {
+ where: { id: ctx.request.userId },
+ },
+ info
+ );
+ },
+
+ async orders(parent, args, ctx, info) {
+ const { userId } = ctx.request;
+ if (!userId) {
+ throw new Error('You must be signed in to see your orders');
+ }
+ return ctx.db.query.orders(
+ {
+ where: {
+ user: { id: userId },
+ },
+ },
+ info
+ );
+ },
+};
+
+module.exports = Query;
diff --git a/sick-fits/backend/src/schema.graphql b/sick-fits/backend/src/schema.graphql
new file mode 100644
index 0000000..07533eb
--- /dev/null
+++ b/sick-fits/backend/src/schema.graphql
@@ -0,0 +1,39 @@
+# The Below line looks like a comment, but it's not!
+# import * from './generated/prisma.graphql'
+
+type Query {
+ me: User
+ order(id: ID!): Order!
+ orders(where: OrderWhereInput, orderBy: OrderOrderByInput, skip: Int, after: String, before: String, first: Int, last: Int): [Order]!
+ items(where: ItemWhereInput, orderBy: ItemOrderByInput, skip: Int, after: String, before: String, first: Int, last: Int): [Item]!
+ itemsConnection(where: ItemWhereInput, orderBy: ItemOrderByInput, first: Int, last: Int, skip: Int): ItemConnection!
+}
+
+type Mutation {
+ signup(email: String!, password: String!, name: String!): User!
+ signin(email: String!, password: String!): User!
+ requestReset(email: String!): User
+ resetPassword(resetToken: String!, password: String!, confirmPassword: String!): User!
+ createItem(title: String, description: String, price: Int, image: String, largeImage: String): Item!
+ deleteItem(id: ID!): Item!
+ updateItem(id: ID!, title: String, description: String, price: Int): Item!
+ addToCart(id: ID!): CartItem
+ removeFromCart(id: ID!): CartItem
+ createOrder(token: String!): Order!
+ updateUser(name: String): User
+ signout: SuccessMessage
+ updatePermissions(permissions: [Permission], userId: ID!): User
+}
+
+type SuccessMessage {
+ message: String
+}
+
+type User {
+ id: ID!
+ email: String!
+ name: String!
+ orders: [Order!]!
+ cart: [CartItem!]!
+ permissions: [Permission]!
+}
diff --git a/sick-fits/backend/src/stripe.js b/sick-fits/backend/src/stripe.js
new file mode 100644
index 0000000..c6be8ca
--- /dev/null
+++ b/sick-fits/backend/src/stripe.js
@@ -0,0 +1 @@
+module.exports = require('stripe')(process.env.STRIPE_SECRET);
diff --git a/sick-fits/backend/src/utils.js b/sick-fits/backend/src/utils.js
new file mode 100644
index 0000000..faf028b
--- /dev/null
+++ b/sick-fits/backend/src/utils.js
@@ -0,0 +1,17 @@
+function hasPermission(user, permissionsNeeded) {
+ const matchedPermissions = user.permissions.filter(permissionTheyHave =>
+ permissionsNeeded.includes(permissionTheyHave)
+ );
+ if (!matchedPermissions.length) {
+ throw new Error(`You do not have sufficient permissions
+
+ : ${permissionsNeeded}
+
+ You Have:
+
+ ${user.permissions}
+ `);
+ }
+}
+
+exports.hasPermission = hasPermission;