diff --git a/.eslintignore b/.eslintignore new file mode 100644 index 0000000..aa039e4 --- /dev/null +++ b/.eslintignore @@ -0,0 +1,3 @@ +lib +lib-es +node_modules diff --git a/package.json b/package.json index 2544ebe..4de288a 100644 --- a/package.json +++ b/package.json @@ -25,6 +25,7 @@ "nexus-prisma": "^0.12.0", "path": "^0.12.7", "pluralize": "~7.0.0", + "prettier": "^2.0.5", "react": "~16.12.0", "react-admin": "^3.4.3", "react-dom": "~16.13.1", diff --git a/packages/backend/src/addCrudResolvers.ts b/packages/backend/src/addCrudResolvers.ts index 895d4bf..d33d84d 100644 --- a/packages/backend/src/addCrudResolvers.ts +++ b/packages/backend/src/addCrudResolvers.ts @@ -56,22 +56,22 @@ export default (resourceName: string) => { t.int(queryCountName, { args: { where: arg({ - type: typeName + "WhereInput", + type: `${typeName}WhereInput`, required: false, }), orderBy: arg({ - type: typeName + "OrderByInput", + type: `${typeName}OrderByInput`, required: false, }), skip: intArg({ required: false, }), after: arg({ - type: typeName + "WhereUniqueInput", + type: `${typeName}WhereUniqueInput`, required: false, }), before: arg({ - type: typeName + "WhereUniqueInput", + type: `${typeName}WhereUniqueInput`, required: false, }), first: intArg({ diff --git a/packages/dataprovider/generated/nexus-prisma.ts b/packages/dataprovider/generated/nexus-prisma.ts index 980bf47..febd8c9 100644 --- a/packages/dataprovider/generated/nexus-prisma.ts +++ b/packages/dataprovider/generated/nexus-prisma.ts @@ -249,31 +249,39 @@ type GetNexusPrisma< // Generated interface ModelTypes { UserRole: prisma.UserRole + UserSocialMedia: prisma.UserSocialMedia User: prisma.User } interface NexusPrismaInputs { Query: { userRoles: { - filtering: 'id' | 'users' | 'AND' | 'OR' | 'NOT' - ordering: 'id' + filtering: 'id' | 'name' | 'users' | 'AND' | 'OR' | 'NOT' + ordering: 'id' | 'name' +} + userSocialMedias: { + filtering: 'id' | 'instagram' | 'twitter' | 'userId' | 'AND' | 'OR' | 'NOT' | 'user' + ordering: 'id' | 'instagram' | 'twitter' | 'userId' } users: { - filtering: 'id' | 'email' | 'roles' | 'firstName' | 'lastName' | 'gender' | 'yearOfBirth' | 'wantsNewsletter' | 'AND' | 'OR' | 'NOT' + filtering: 'id' | 'email' | 'roles' | 'firstName' | 'lastName' | 'gender' | 'yearOfBirth' | 'wantsNewsletter' | 'AND' | 'OR' | 'NOT' | 'userSocialMedia' ordering: 'id' | 'email' | 'firstName' | 'lastName' | 'gender' | 'yearOfBirth' | 'wantsNewsletter' } }, UserRole: { users: { - filtering: 'id' | 'email' | 'roles' | 'firstName' | 'lastName' | 'gender' | 'yearOfBirth' | 'wantsNewsletter' | 'AND' | 'OR' | 'NOT' + filtering: 'id' | 'email' | 'roles' | 'firstName' | 'lastName' | 'gender' | 'yearOfBirth' | 'wantsNewsletter' | 'AND' | 'OR' | 'NOT' | 'userSocialMedia' ordering: 'id' | 'email' | 'firstName' | 'lastName' | 'gender' | 'yearOfBirth' | 'wantsNewsletter' } + }, UserSocialMedia: { + + }, User: { roles: { - filtering: 'id' | 'users' | 'AND' | 'OR' | 'NOT' - ordering: 'id' + filtering: 'id' | 'name' | 'users' | 'AND' | 'OR' | 'NOT' + ordering: 'id' | 'name' } } @@ -283,6 +291,8 @@ interface NexusPrismaTypes { Query: { userRole: 'UserRole' userRoles: 'UserRole' + userSocialMedia: 'UserSocialMedia' + userSocialMedias: 'UserSocialMedia' user: 'User' users: 'User' @@ -294,6 +304,12 @@ interface NexusPrismaTypes { deleteOneUserRole: 'UserRole' deleteManyUserRole: 'BatchPayload' upsertOneUserRole: 'UserRole' + createOneUserSocialMedia: 'UserSocialMedia' + updateOneUserSocialMedia: 'UserSocialMedia' + updateManyUserSocialMedia: 'BatchPayload' + deleteOneUserSocialMedia: 'UserSocialMedia' + deleteManyUserSocialMedia: 'BatchPayload' + upsertOneUserSocialMedia: 'UserSocialMedia' createOneUser: 'User' updateOneUser: 'User' updateManyUser: 'BatchPayload' @@ -304,8 +320,16 @@ interface NexusPrismaTypes { }, UserRole: { id: 'String' + name: 'String' users: 'User' +}, UserSocialMedia: { + id: 'String' + instagram: 'String' + twitter: 'String' + user: 'User' + userId: 'String' + }, User: { id: 'String' email: 'String' @@ -315,12 +339,14 @@ interface NexusPrismaTypes { gender: 'Gender' yearOfBirth: 'Int' wantsNewsletter: 'Boolean' + userSocialMedia: 'UserSocialMedia' } } interface NexusPrismaMethods { UserRole: NexusPrismaFields<'UserRole'> + UserSocialMedia: NexusPrismaFields<'UserSocialMedia'> User: NexusPrismaFields<'User'> Query: NexusPrismaFields<'Query'> Mutation: NexusPrismaFields<'Mutation'> diff --git a/packages/dataprovider/generated/nexus.ts b/packages/dataprovider/generated/nexus.ts index f9fc844..88e58cc 100644 --- a/packages/dataprovider/generated/nexus.ts +++ b/packages/dataprovider/generated/nexus.ts @@ -79,6 +79,7 @@ export interface NexusGenInputs { id?: string | null; // String lastName?: string | null; // String roles?: NexusGenInputs['UserRoleCreateManyWithoutUsersInput'] | null; // UserRoleCreateManyWithoutUsersInput + userSocialMedia?: NexusGenInputs['UserSocialMediaCreateOneWithoutUserInput'] | null; // UserSocialMediaCreateOneWithoutUserInput wantsNewsletter: boolean; // Boolean! yearOfBirth?: number | null; // Int } @@ -92,6 +93,7 @@ export interface NexusGenInputs { gender?: NexusGenEnums['Gender'] | null; // Gender id?: string | null; // String lastName?: string | null; // String + userSocialMedia?: NexusGenInputs['UserSocialMediaCreateOneWithoutUserInput'] | null; // UserSocialMediaCreateOneWithoutUserInput wantsNewsletter: boolean; // Boolean! yearOfBirth?: number | null; // Int } @@ -110,7 +112,8 @@ export interface NexusGenInputs { yearOfBirth?: NexusGenEnums['OrderByArg'] | null; // OrderByArg } UserRoleCreateInput: { // input type - id: string; // String! + id?: string | null; // String + name: string; // String! users?: NexusGenInputs['UserCreateManyWithoutRolesInput'] | null; // UserCreateManyWithoutRolesInput } UserRoleCreateManyWithoutUsersInput: { // input type @@ -118,7 +121,8 @@ export interface NexusGenInputs { create?: NexusGenInputs['UserRoleCreateWithoutUsersInput'][] | null; // [UserRoleCreateWithoutUsersInput!] } UserRoleCreateWithoutUsersInput: { // input type - id: string; // String! + id?: string | null; // String + name: string; // String! } UserRoleFilter: { // input type every?: NexusGenInputs['UserRoleWhereInput'] | null; // UserRoleWhereInput @@ -127,23 +131,28 @@ export interface NexusGenInputs { } UserRoleOrderByInput: { // input type id?: NexusGenEnums['OrderByArg'] | null; // OrderByArg + name?: NexusGenEnums['OrderByArg'] | null; // OrderByArg } UserRoleScalarWhereInput: { // input type AND?: NexusGenInputs['UserRoleScalarWhereInput'][] | null; // [UserRoleScalarWhereInput!] - id?: NexusGenInputs['StringFilter'] | null; // StringFilter + id?: NexusGenInputs['UUIDFilter'] | null; // UUIDFilter + name?: NexusGenInputs['StringFilter'] | null; // StringFilter NOT?: NexusGenInputs['UserRoleScalarWhereInput'][] | null; // [UserRoleScalarWhereInput!] OR?: NexusGenInputs['UserRoleScalarWhereInput'][] | null; // [UserRoleScalarWhereInput!] users?: NexusGenInputs['UserFilter'] | null; // UserFilter } UserRoleUpdateInput: { // input type id?: string | null; // String + name?: string | null; // String users?: NexusGenInputs['UserUpdateManyWithoutRolesInput'] | null; // UserUpdateManyWithoutRolesInput } UserRoleUpdateManyDataInput: { // input type id?: string | null; // String + name?: string | null; // String } UserRoleUpdateManyMutationInput: { // input type id?: string | null; // String + name?: string | null; // String } UserRoleUpdateManyWithWhereNestedInput: { // input type data: NexusGenInputs['UserRoleUpdateManyDataInput']; // UserRoleUpdateManyDataInput! @@ -166,6 +175,7 @@ export interface NexusGenInputs { } UserRoleUpdateWithoutUsersDataInput: { // input type id?: string | null; // String + name?: string | null; // String } UserRoleUpsertWithWhereUniqueWithoutUsersInput: { // input type create: NexusGenInputs['UserRoleCreateWithoutUsersInput']; // UserRoleCreateWithoutUsersInput! @@ -174,7 +184,8 @@ export interface NexusGenInputs { } UserRoleWhereInput: { // input type AND?: NexusGenInputs['UserRoleWhereInput'][] | null; // [UserRoleWhereInput!] - id?: NexusGenInputs['StringFilter'] | null; // StringFilter + id?: NexusGenInputs['UUIDFilter'] | null; // UUIDFilter + name?: NexusGenInputs['StringFilter'] | null; // StringFilter NOT?: NexusGenInputs['UserRoleWhereInput'][] | null; // [UserRoleWhereInput!] OR?: NexusGenInputs['UserRoleWhereInput'][] | null; // [UserRoleWhereInput!] users?: NexusGenInputs['UserFilter'] | null; // UserFilter @@ -195,6 +206,45 @@ export interface NexusGenInputs { wantsNewsletter?: NexusGenInputs['BooleanFilter'] | null; // BooleanFilter yearOfBirth?: NexusGenInputs['NullableIntFilter'] | null; // NullableIntFilter } + UserSocialMediaCreateOneWithoutUserInput: { // input type + connect?: NexusGenInputs['UserSocialMediaWhereUniqueInput'] | null; // UserSocialMediaWhereUniqueInput + create?: NexusGenInputs['UserSocialMediaCreateWithoutUserInput'] | null; // UserSocialMediaCreateWithoutUserInput + } + UserSocialMediaCreateWithoutUserInput: { // input type + id?: string | null; // String + instagram: string; // String! + twitter: string; // String! + } + UserSocialMediaUpdateOneWithoutUserInput: { // input type + connect?: NexusGenInputs['UserSocialMediaWhereUniqueInput'] | null; // UserSocialMediaWhereUniqueInput + create?: NexusGenInputs['UserSocialMediaCreateWithoutUserInput'] | null; // UserSocialMediaCreateWithoutUserInput + delete?: boolean | null; // Boolean + disconnect?: boolean | null; // Boolean + update?: NexusGenInputs['UserSocialMediaUpdateWithoutUserDataInput'] | null; // UserSocialMediaUpdateWithoutUserDataInput + upsert?: NexusGenInputs['UserSocialMediaUpsertWithoutUserInput'] | null; // UserSocialMediaUpsertWithoutUserInput + } + UserSocialMediaUpdateWithoutUserDataInput: { // input type + id?: string | null; // String + instagram?: string | null; // String + twitter?: string | null; // String + } + UserSocialMediaUpsertWithoutUserInput: { // input type + create: NexusGenInputs['UserSocialMediaCreateWithoutUserInput']; // UserSocialMediaCreateWithoutUserInput! + update: NexusGenInputs['UserSocialMediaUpdateWithoutUserDataInput']; // UserSocialMediaUpdateWithoutUserDataInput! + } + UserSocialMediaWhereInput: { // input type + AND?: NexusGenInputs['UserSocialMediaWhereInput'][] | null; // [UserSocialMediaWhereInput!] + id?: NexusGenInputs['UUIDFilter'] | null; // UUIDFilter + instagram?: NexusGenInputs['StringFilter'] | null; // StringFilter + NOT?: NexusGenInputs['UserSocialMediaWhereInput'][] | null; // [UserSocialMediaWhereInput!] + OR?: NexusGenInputs['UserSocialMediaWhereInput'][] | null; // [UserSocialMediaWhereInput!] + twitter?: NexusGenInputs['StringFilter'] | null; // StringFilter + user?: NexusGenInputs['UserWhereInput'] | null; // UserWhereInput + userId?: NexusGenInputs['StringFilter'] | null; // StringFilter + } + UserSocialMediaWhereUniqueInput: { // input type + id?: string | null; // String + } UserUpdateInput: { // input type email?: string | null; // String firstName?: string | null; // String @@ -202,6 +252,7 @@ export interface NexusGenInputs { id?: string | null; // String lastName?: string | null; // String roles?: NexusGenInputs['UserRoleUpdateManyWithoutUsersInput'] | null; // UserRoleUpdateManyWithoutUsersInput + userSocialMedia?: NexusGenInputs['UserSocialMediaUpdateOneWithoutUserInput'] | null; // UserSocialMediaUpdateOneWithoutUserInput wantsNewsletter?: boolean | null; // Boolean yearOfBirth?: number | null; // Int } @@ -248,6 +299,7 @@ export interface NexusGenInputs { gender?: NexusGenEnums['Gender'] | null; // Gender id?: string | null; // String lastName?: string | null; // String + userSocialMedia?: NexusGenInputs['UserSocialMediaUpdateOneWithoutUserInput'] | null; // UserSocialMediaUpdateOneWithoutUserInput wantsNewsletter?: boolean | null; // Boolean yearOfBirth?: number | null; // Int } @@ -266,6 +318,7 @@ export interface NexusGenInputs { NOT?: NexusGenInputs['UserWhereInput'][] | null; // [UserWhereInput!] OR?: NexusGenInputs['UserWhereInput'][] | null; // [UserWhereInput!] roles?: NexusGenInputs['UserRoleFilter'] | null; // UserRoleFilter + userSocialMedia?: NexusGenInputs['UserSocialMediaWhereInput'] | null; // UserSocialMediaWhereInput wantsNewsletter?: NexusGenInputs['BooleanFilter'] | null; // BooleanFilter yearOfBirth?: NexusGenInputs['NullableIntFilter'] | null; // NullableIntFilter } @@ -298,6 +351,12 @@ export interface NexusGenRootTypes { } UserRole: { // root type id: string; // String! + name: string; // String! + } + UserSocialMedia: { // root type + id: string; // String! + instagram: string; // String! + twitter: string; // String! } String: string; Int: number; @@ -335,6 +394,13 @@ export interface NexusGenAllTypes extends NexusGenRootTypes { UserRoleWhereInput: NexusGenInputs['UserRoleWhereInput']; UserRoleWhereUniqueInput: NexusGenInputs['UserRoleWhereUniqueInput']; UserScalarWhereInput: NexusGenInputs['UserScalarWhereInput']; + UserSocialMediaCreateOneWithoutUserInput: NexusGenInputs['UserSocialMediaCreateOneWithoutUserInput']; + UserSocialMediaCreateWithoutUserInput: NexusGenInputs['UserSocialMediaCreateWithoutUserInput']; + UserSocialMediaUpdateOneWithoutUserInput: NexusGenInputs['UserSocialMediaUpdateOneWithoutUserInput']; + UserSocialMediaUpdateWithoutUserDataInput: NexusGenInputs['UserSocialMediaUpdateWithoutUserDataInput']; + UserSocialMediaUpsertWithoutUserInput: NexusGenInputs['UserSocialMediaUpsertWithoutUserInput']; + UserSocialMediaWhereInput: NexusGenInputs['UserSocialMediaWhereInput']; + UserSocialMediaWhereUniqueInput: NexusGenInputs['UserSocialMediaWhereUniqueInput']; UserUpdateInput: NexusGenInputs['UserUpdateInput']; UserUpdateManyDataInput: NexusGenInputs['UserUpdateManyDataInput']; UserUpdateManyMutationInput: NexusGenInputs['UserUpdateManyMutationInput']; @@ -383,11 +449,19 @@ export interface NexusGenFieldTypes { lastName: string | null; // String logs: string[]; // [String!]! roles: NexusGenRootTypes['UserRole'][]; // [UserRole!]! + userSocialMedia: NexusGenRootTypes['UserSocialMedia'] | null; // UserSocialMedia wantsNewsletter: boolean; // Boolean! yearOfBirth: number | null; // Int } UserRole: { // field return type id: string; // String! + name: string; // String! + } + UserSocialMedia: { // field return type + id: string; // String! + instagram: string; // String! + twitter: string; // String! + user: NexusGenRootTypes['User']; // User! } } @@ -503,9 +577,9 @@ export interface NexusGenAbstractResolveReturnTypes { export interface NexusGenInheritedFields {} -export type NexusGenObjectNames = "BatchPayload" | "Mutation" | "Query" | "User" | "UserRole"; +export type NexusGenObjectNames = "BatchPayload" | "Mutation" | "Query" | "User" | "UserRole" | "UserSocialMedia"; -export type NexusGenInputNames = "BooleanFilter" | "NullableIntFilter" | "NullableStringFilter" | "StringFilter" | "UUIDFilter" | "UserCreateInput" | "UserCreateManyWithoutRolesInput" | "UserCreateWithoutRolesInput" | "UserFilter" | "UserOrderByInput" | "UserRoleCreateInput" | "UserRoleCreateManyWithoutUsersInput" | "UserRoleCreateWithoutUsersInput" | "UserRoleFilter" | "UserRoleOrderByInput" | "UserRoleScalarWhereInput" | "UserRoleUpdateInput" | "UserRoleUpdateManyDataInput" | "UserRoleUpdateManyMutationInput" | "UserRoleUpdateManyWithWhereNestedInput" | "UserRoleUpdateManyWithoutUsersInput" | "UserRoleUpdateWithWhereUniqueWithoutUsersInput" | "UserRoleUpdateWithoutUsersDataInput" | "UserRoleUpsertWithWhereUniqueWithoutUsersInput" | "UserRoleWhereInput" | "UserRoleWhereUniqueInput" | "UserScalarWhereInput" | "UserUpdateInput" | "UserUpdateManyDataInput" | "UserUpdateManyMutationInput" | "UserUpdateManyWithWhereNestedInput" | "UserUpdateManyWithoutRolesInput" | "UserUpdateWithWhereUniqueWithoutRolesInput" | "UserUpdateWithoutRolesDataInput" | "UserUpsertWithWhereUniqueWithoutRolesInput" | "UserWhereInput" | "UserWhereUniqueInput"; +export type NexusGenInputNames = "BooleanFilter" | "NullableIntFilter" | "NullableStringFilter" | "StringFilter" | "UUIDFilter" | "UserCreateInput" | "UserCreateManyWithoutRolesInput" | "UserCreateWithoutRolesInput" | "UserFilter" | "UserOrderByInput" | "UserRoleCreateInput" | "UserRoleCreateManyWithoutUsersInput" | "UserRoleCreateWithoutUsersInput" | "UserRoleFilter" | "UserRoleOrderByInput" | "UserRoleScalarWhereInput" | "UserRoleUpdateInput" | "UserRoleUpdateManyDataInput" | "UserRoleUpdateManyMutationInput" | "UserRoleUpdateManyWithWhereNestedInput" | "UserRoleUpdateManyWithoutUsersInput" | "UserRoleUpdateWithWhereUniqueWithoutUsersInput" | "UserRoleUpdateWithoutUsersDataInput" | "UserRoleUpsertWithWhereUniqueWithoutUsersInput" | "UserRoleWhereInput" | "UserRoleWhereUniqueInput" | "UserScalarWhereInput" | "UserSocialMediaCreateOneWithoutUserInput" | "UserSocialMediaCreateWithoutUserInput" | "UserSocialMediaUpdateOneWithoutUserInput" | "UserSocialMediaUpdateWithoutUserDataInput" | "UserSocialMediaUpsertWithoutUserInput" | "UserSocialMediaWhereInput" | "UserSocialMediaWhereUniqueInput" | "UserUpdateInput" | "UserUpdateManyDataInput" | "UserUpdateManyMutationInput" | "UserUpdateManyWithWhereNestedInput" | "UserUpdateManyWithoutRolesInput" | "UserUpdateWithWhereUniqueWithoutRolesInput" | "UserUpdateWithoutRolesDataInput" | "UserUpsertWithWhereUniqueWithoutRolesInput" | "UserWhereInput" | "UserWhereUniqueInput"; export type NexusGenEnumNames = "Gender" | "OrderByArg"; diff --git a/packages/dataprovider/generated/schema.graphql b/packages/dataprovider/generated/schema.graphql index 9a0571c..cef932d 100644 --- a/packages/dataprovider/generated/schema.graphql +++ b/packages/dataprovider/generated/schema.graphql @@ -93,6 +93,7 @@ type User { lastName: String logs(from: String!, to: String!): [String!]! roles(after: UserRoleWhereUniqueInput, before: UserRoleWhereUniqueInput, first: Int, last: Int, skip: Int, where: UserRoleWhereInput): [UserRole!]! + userSocialMedia: UserSocialMedia wantsNewsletter: Boolean! yearOfBirth: Int } @@ -104,6 +105,7 @@ input UserCreateInput { id: String lastName: String roles: UserRoleCreateManyWithoutUsersInput + userSocialMedia: UserSocialMediaCreateOneWithoutUserInput wantsNewsletter: Boolean! yearOfBirth: Int } @@ -119,6 +121,7 @@ input UserCreateWithoutRolesInput { gender: Gender id: String lastName: String + userSocialMedia: UserSocialMediaCreateOneWithoutUserInput wantsNewsletter: Boolean! yearOfBirth: Int } @@ -141,10 +144,12 @@ input UserOrderByInput { type UserRole { id: String! + name: String! } input UserRoleCreateInput { - id: String! + id: String + name: String! users: UserCreateManyWithoutRolesInput } @@ -154,7 +159,8 @@ input UserRoleCreateManyWithoutUsersInput { } input UserRoleCreateWithoutUsersInput { - id: String! + id: String + name: String! } input UserRoleFilter { @@ -165,11 +171,13 @@ input UserRoleFilter { input UserRoleOrderByInput { id: OrderByArg + name: OrderByArg } input UserRoleScalarWhereInput { AND: [UserRoleScalarWhereInput!] - id: StringFilter + id: UUIDFilter + name: StringFilter NOT: [UserRoleScalarWhereInput!] OR: [UserRoleScalarWhereInput!] users: UserFilter @@ -177,15 +185,18 @@ input UserRoleScalarWhereInput { input UserRoleUpdateInput { id: String + name: String users: UserUpdateManyWithoutRolesInput } input UserRoleUpdateManyDataInput { id: String + name: String } input UserRoleUpdateManyMutationInput { id: String + name: String } input UserRoleUpdateManyWithoutUsersInput { @@ -207,6 +218,7 @@ input UserRoleUpdateManyWithWhereNestedInput { input UserRoleUpdateWithoutUsersDataInput { id: String + name: String } input UserRoleUpdateWithWhereUniqueWithoutUsersInput { @@ -222,7 +234,8 @@ input UserRoleUpsertWithWhereUniqueWithoutUsersInput { input UserRoleWhereInput { AND: [UserRoleWhereInput!] - id: StringFilter + id: UUIDFilter + name: StringFilter NOT: [UserRoleWhereInput!] OR: [UserRoleWhereInput!] users: UserFilter @@ -246,6 +259,59 @@ input UserScalarWhereInput { yearOfBirth: NullableIntFilter } +type UserSocialMedia { + id: String! + instagram: String! + twitter: String! + user: User! +} + +input UserSocialMediaCreateOneWithoutUserInput { + connect: UserSocialMediaWhereUniqueInput + create: UserSocialMediaCreateWithoutUserInput +} + +input UserSocialMediaCreateWithoutUserInput { + id: String + instagram: String! + twitter: String! +} + +input UserSocialMediaUpdateOneWithoutUserInput { + connect: UserSocialMediaWhereUniqueInput + create: UserSocialMediaCreateWithoutUserInput + delete: Boolean + disconnect: Boolean + update: UserSocialMediaUpdateWithoutUserDataInput + upsert: UserSocialMediaUpsertWithoutUserInput +} + +input UserSocialMediaUpdateWithoutUserDataInput { + id: String + instagram: String + twitter: String +} + +input UserSocialMediaUpsertWithoutUserInput { + create: UserSocialMediaCreateWithoutUserInput! + update: UserSocialMediaUpdateWithoutUserDataInput! +} + +input UserSocialMediaWhereInput { + AND: [UserSocialMediaWhereInput!] + id: UUIDFilter + instagram: StringFilter + NOT: [UserSocialMediaWhereInput!] + OR: [UserSocialMediaWhereInput!] + twitter: StringFilter + user: UserWhereInput + userId: StringFilter +} + +input UserSocialMediaWhereUniqueInput { + id: String +} + input UserUpdateInput { email: String firstName: String @@ -253,6 +319,7 @@ input UserUpdateInput { id: String lastName: String roles: UserRoleUpdateManyWithoutUsersInput + userSocialMedia: UserSocialMediaUpdateOneWithoutUserInput wantsNewsletter: Boolean yearOfBirth: Int } @@ -300,6 +367,7 @@ input UserUpdateWithoutRolesDataInput { gender: Gender id: String lastName: String + userSocialMedia: UserSocialMediaUpdateOneWithoutUserInput wantsNewsletter: Boolean yearOfBirth: Int } @@ -325,6 +393,7 @@ input UserWhereInput { NOT: [UserWhereInput!] OR: [UserWhereInput!] roles: UserRoleFilter + userSocialMedia: UserSocialMediaWhereInput wantsNewsletter: BooleanFilter yearOfBirth: NullableIntFilter } diff --git a/packages/dataprovider/src/buildGqlQuery.test.ts b/packages/dataprovider/src/buildGqlQuery.test.ts index 70425e6..27cec8b 100644 --- a/packages/dataprovider/src/buildGqlQuery.test.ts +++ b/packages/dataprovider/src/buildGqlQuery.test.ts @@ -217,6 +217,14 @@ describe("buildGqlQuery", () => { } gender wantsNewsletter + userSocialMedia { + id + instagram + twitter + user { + id + } + } } total: usersCount(where: $where) } @@ -245,6 +253,14 @@ describe("buildGqlQuery", () => { } gender wantsNewsletter + userSocialMedia { + id + instagram + twitter + user { + id + } + } } total: usersCount(where: $where) } @@ -273,6 +289,14 @@ describe("buildGqlQuery", () => { } gender wantsNewsletter + userSocialMedia { + id + instagram + twitter + user { + id + } + } } total: usersCount(where: $where) } @@ -302,6 +326,14 @@ describe("buildGqlQuery", () => { } gender wantsNewsletter + userSocialMedia { + id + instagram + twitter + user { + id + } + } } } `, @@ -332,6 +364,14 @@ describe("buildGqlQuery", () => { } gender wantsNewsletter + userSocialMedia { + id + instagram + twitter + user { + id + } + } } } `, @@ -359,6 +399,14 @@ describe("buildGqlQuery", () => { } gender wantsNewsletter + userSocialMedia { + id + instagram + twitter + user { + id + } + } } } `, diff --git a/packages/dataprovider/src/buildVariables.test.ts b/packages/dataprovider/src/buildVariables.test.ts index 8f9647f..76a6ff3 100644 --- a/packages/dataprovider/src/buildVariables.test.ts +++ b/packages/dataprovider/src/buildVariables.test.ts @@ -94,7 +94,112 @@ describe("buildVariables", () => { }); }); - it("returns correct variables when linked with other resources", () => { + // one + it("create a new entity and create also its relation entity", () => { + const params = { + data: { + email: "albert.einstein@patentamt-bern.ch", + firstName: "Albert", + lastName: "Einstein", + wantsNewsletter: false, + userSocialMedia: { twitter: "@twitteru", instagram: "@instagramu" }, + }, + }; + + expect( + buildVariables(testIntrospection)(testUserResource, CREATE, params), + ).toEqual({ + data: { + email: "albert.einstein@patentamt-bern.ch", + firstName: "Albert", + lastName: "Einstein", + wantsNewsletter: false, + userSocialMedia: { + create: { twitter: "@twitteru", instagram: "@instagramu" }, + }, + }, + }); + }); + + it("create a new entity and connect an already existing related entity identified by primitive id", () => { + const params = { + data: { + email: "albert.einstein@patentamt-bern.ch", + firstName: "Albert", + lastName: "Einstein", + wantsNewsletter: false, + userSocialMedia: "socialId", + }, + }; + + expect( + buildVariables(testIntrospection)(testUserResource, CREATE, params), + ).toEqual({ + data: { + email: "albert.einstein@patentamt-bern.ch", + firstName: "Albert", + lastName: "Einstein", + wantsNewsletter: false, + userSocialMedia: { + connect: { id: "socialId" }, + }, + }, + }); + }); + + it("create a new entity and connect an already existing related entity identified by object with id property", () => { + const params = { + data: { + email: "albert.einstein@patentamt-bern.ch", + firstName: "Albert", + lastName: "Einstein", + wantsNewsletter: false, + userSocialMedia: { id: "socialId" }, + }, + }; + + expect( + buildVariables(testIntrospection)(testUserResource, CREATE, params), + ).toEqual({ + data: { + email: "albert.einstein@patentamt-bern.ch", + firstName: "Albert", + lastName: "Einstein", + wantsNewsletter: false, + userSocialMedia: { + connect: { id: "socialId" }, + }, + }, + }); + }); + + it("create a new entity and create also it's many relation entities when they provided no id", () => { + const params = { + data: { + email: "albert.einstein@patentamt-bern.ch", + firstName: "Albert", + lastName: "Einstein", + wantsNewsletter: false, + roles: [{ name: "admin" }, { name: "user" }], + }, + }; + + expect( + buildVariables(testIntrospection)(testUserResource, CREATE, params), + ).toEqual({ + data: { + email: "albert.einstein@patentamt-bern.ch", + firstName: "Albert", + lastName: "Einstein", + wantsNewsletter: false, + roles: { + create: [{ name: "admin" }, { name: "user" }], + }, + }, + }); + }); + + it("create a new entity and connect many already existing related entities identified by primitive id", () => { const params = { data: { firstName: "Albert", @@ -119,6 +224,59 @@ describe("buildVariables", () => { }, }); }); + + it("create a new entity and connect many already existing related entities identified by object with id property", () => { + const params = { + data: { + firstName: "Albert", + lastName: "Einstein", + wantsNewsletter: true, + email: "albert.einstein@patentamt-bern.ch", + roles: [{ id: "admin" }], + }, + }; + + expect( + buildVariables(testIntrospection)(testUserResource, CREATE, params), + ).toEqual({ + data: { + email: "albert.einstein@patentamt-bern.ch", + firstName: "Albert", + lastName: "Einstein", + wantsNewsletter: true, + roles: { + connect: [{ id: "admin" }], + }, + }, + }); + }); + + it("create a new entity and it's related entities with mixed primitive and object ids", () => { + const params = { + data: { + firstName: "Albert", + lastName: "Einstein", + wantsNewsletter: true, + email: "albert.einstein@patentamt-bern.ch", + roles: [{ id: "admin" }, { name: "User" }, "coordinator"], + }, + }; + + expect( + buildVariables(testIntrospection)(testUserResource, CREATE, params), + ).toEqual({ + data: { + email: "albert.einstein@patentamt-bern.ch", + firstName: "Albert", + lastName: "Einstein", + wantsNewsletter: true, + roles: { + create: [{ name: "User" }], + connect: [{ id: "admin" }, { id: "coordinator" }], + }, + }, + }); + }); }); describe("UPDATE", () => { @@ -145,7 +303,119 @@ describe("buildVariables", () => { }); }); - it("correctly connects new roles", () => { + // one + + it("update an entity and change the relation", () => { + const params = { + data: { + id: "einstein", + userSocialMedia: { id: "newId", twitter: "tw", instagram: "in" }, + }, + previousData: { + userSocialMedia: { id: "oldId", twitter: "t", instagram: "i" }, + }, + }; + + expect( + buildVariables(testIntrospection)(testUserResource, UPDATE, params), + ).toEqual({ + where: { id: "einstein" }, + data: { + userSocialMedia: { + connect: { id: "newId" }, + }, + }, + }); + }); + + it("update an entity and update also it's related entity", () => { + const params = { + data: { + id: "einstein", + userSocialMedia: { + id: "socialId", + twitter: "another-twitter", + instagram: "another-instagram", + }, + }, + previousData: { + userSocialMedia: { + id: "socialId", + twitter: "twitter", + instagram: "instagram", + }, + }, + }; + + expect( + buildVariables(testIntrospection)(testUserResource, UPDATE, params), + ).toEqual({ + where: { id: "einstein" }, + data: { + userSocialMedia: { + update: { + twitter: "another-twitter", + instagram: "another-instagram", + }, + }, + }, + }); + }); + + it("update an entity and create also new related entity when provided no id", () => { + const params = { + data: { + id: "einstein", + userSocialMedia: { + twitter: "new-twitter", + instagram: "new-instagram", + }, + }, + previousData: { + userSocialMedia: { + id: "socialId", + twitter: "twitter", + instagram: "instagram", + }, + }, + }; + + expect( + buildVariables(testIntrospection)(testUserResource, UPDATE, params), + ).toEqual({ + where: { id: "einstein" }, + data: { + userSocialMedia: { + create: { twitter: "new-twitter", instagram: "new-instagram" }, + }, + }, + }); + }); + + it("update an entity and disconnect the related entity", () => { + const params = { + data: { + id: "einstein", + }, + previousData: { + userSocialMedia: { id: "oldId", twitter: "t", instagram: "i" }, + }, + }; + + expect( + buildVariables(testIntrospection)(testUserResource, UPDATE, params), + ).toEqual({ + where: { id: "einstein" }, + data: { + userSocialMedia: { + disconnect: true, + }, + }, + }); + }); + + //many + it("update an entity and change it's many relation entities", () => { const params = { data: { id: "einstein", @@ -176,6 +446,130 @@ describe("buildVariables", () => { }, }); }); + + it("update an entity and update also it's related entities", () => { + const params = { + data: { + id: "einstein", + roles: [ + { id: "student", name: "Student Role" }, + { id: "human", name: "Human" }, + ], + }, + previousData: { + roles: [ + { id: "student", name: "Student" }, + { id: "human", name: "Human" }, + ], + }, + }; + + expect( + buildVariables(testIntrospection)(testUserResource, UPDATE, params), + ).toEqual({ + where: { id: "einstein" }, + data: { + roles: { + update: [ + { where: { id: "student" }, data: { name: "Student Role" } }, + ], + }, + }, + }); + }); + + it("update an entity and creates also new related entities if they provide no id", () => { + const params = { + data: { + id: "einstein", + roles: [{ name: "Student Role" }, { id: "human", name: "Human" }], + }, + previousData: { + roles: [{ id: "human", name: "Human" }], + }, + }; + + expect( + buildVariables(testIntrospection)(testUserResource, UPDATE, params), + ).toEqual({ + where: { id: "einstein" }, + data: { + roles: { + create: [{ name: "Student Role" }], + }, + }, + }); + }); + + it("update an entity and creates, update and disconnects related entities accordingly", () => { + const params = { + data: { + id: "einstein", + roles: [ + { name: "Student Role" }, + { id: "panter", name: "Panter" }, + { id: "manul", name: "Manul is a cat" }, + ], + }, + previousData: { + roles: [ + { id: "human", name: "Human" }, + { id: "manul", name: "Manul" }, + ], + }, + }; + + expect( + buildVariables(testIntrospection)(testUserResource, UPDATE, params), + ).toEqual({ + where: { id: "einstein" }, + data: { + roles: { + connect: [{ id: "panter" }], + create: [{ name: "Student Role" }], + disconnect: [{ id: "human" }], + update: [ + { where: { id: "manul" }, data: { name: "Manul is a cat" } }, + ], + }, + }, + }); + }); + + it("update an entity and it's related entities accordingly even with mixed primitive and object ids", () => { + const params = { + data: { + id: "einstein", + roles: [ + { name: "Student Role" }, + "panter", + { id: "manul", name: "Manul is a cat" }, + ], + }, + previousData: { + roles: [ + { id: "human", name: "Human" }, + { id: "manul", name: "Manul" }, + ], + }, + }; + + expect( + buildVariables(testIntrospection)(testUserResource, UPDATE, params), + ).toEqual({ + where: { id: "einstein" }, + data: { + roles: { + create: [{ name: "Student Role" }], + connect: [{ id: "panter" }], + disconnect: [{ id: "human" }], + update: [ + { where: { id: "manul" }, data: { name: "Manul is a cat" } }, + ], + }, + }, + }); + }); }); describe("GET_MANY", () => { diff --git a/packages/dataprovider/src/buildVariables.ts b/packages/dataprovider/src/buildVariables.ts index f81615a..a0b9a99 100644 --- a/packages/dataprovider/src/buildVariables.ts +++ b/packages/dataprovider/src/buildVariables.ts @@ -155,31 +155,39 @@ const buildNewInputValue = ( if (isObject(referencedField)) { // TODO: we assume "data.id" to be the id if (isObjectWithId(referencedField)) { - if (!updateListInputType) { - throw new Error( - `Input data for "${fieldName}" is of type "Object" but graphql endpoints does not expose the "update" mutation for "${fullFieldObjectType.name}"`, + const connectRelation = !previousFieldData?.find((p) => + p.id + ? p.id === referencedField.id + : p === referencedField.id, + ); + if (!updateListInputType || connectRelation) { + inputs.connect = [ + ...(inputs.connect || []), + { id: referencedField.id }, + ]; + } else { + // update + const data = buildData( + updateListInputType, + { + id: referencedField.id, + data: referencedField, + previousData: previousFieldData?.find( + (previousField) => { + // TODO: we assume ".id" to be the id + return previousField.id === referencedField.id; + }, + ), + }, + introspectionResults, ); + if (Object.keys(data).length) { + inputs.update = [ + ...(inputs.update || []), + { where: { id: referencedField.id }, data }, + ]; + } } - - // update - const data = buildData( - updateListInputType, - { - id: referencedField.id, - data: referencedField, - previousData: previousFieldData?.find( - (previousField) => { - // TODO: we assume ".id" to be the id - return previousField.id === referencedField.id; - }, - ), - }, - introspectionResults, - ); - inputs.update = [ - ...(inputs.update || []), - { where: { id: referencedField.id }, data }, - ]; } else { // create const data = buildData( @@ -245,9 +253,9 @@ const buildNewInputValue = ( disconnect: true, }; } - if (isObjectWithId(fieldData)) { - // TODO: we assume ".id" to be the id - if (!fieldData.id) { + if (isObject(fieldData)) { + if (!isObjectWithId(fieldData)) { + // TODO: we assume ".id" to be the id const createObjectModifierType = getFinalType( createModifier.type, ); @@ -288,7 +296,7 @@ const buildNewInputValue = ( return { connect: { id: fieldData.id } }; } } - } else if (previousFieldData !== fieldData) { + } else { return { connect: { id: fieldData } }; } } diff --git a/packages/dataprovider/src/getResponseParser.test.ts b/packages/dataprovider/src/getResponseParser.test.ts index b7feaa0..614703b 100644 --- a/packages/dataprovider/src/getResponseParser.test.ts +++ b/packages/dataprovider/src/getResponseParser.test.ts @@ -66,7 +66,7 @@ const testListTypes = (type: string) => { }; const testSingleTypes = (type: string) => { - it("returns the response expected by RA for " + type, async () => { + it(`returns the response expected by RA for ${type}`, async () => { const testIntrospection: IntrospectionResult = await getTestIntrospection(); const testUserResource: Resource = testIntrospection.resources.find( (r) => r.type.kind === "OBJECT" && r.type.name === "User", diff --git a/packages/dataprovider/test-data/datamodel.prisma b/packages/dataprovider/test-data/datamodel.prisma index 74c2245..66c535d 100644 --- a/packages/dataprovider/test-data/datamodel.prisma +++ b/packages/dataprovider/test-data/datamodel.prisma @@ -8,10 +8,19 @@ datasource db { } model UserRole { - id String @id + id String @default(uuid()) @id + name String users User[] @relation(references: [id]) } +model UserSocialMedia { + id String @default(uuid()) @id + instagram String + twitter String + user User @relation(fields: [userId], references: [id]) + userId String +} + enum Gender { MALE FEMALE @@ -19,12 +28,13 @@ enum Gender { } model User { - id String @default(uuid()) @id - email String @unique - roles UserRole[] @relation(references: [id]) + id String @default(uuid()) @id + email String @unique + roles UserRole[] @relation(references: [id]) firstName String? lastName String? gender Gender? yearOfBirth Int? wantsNewsletter Boolean -} \ No newline at end of file + userSocialMedia UserSocialMedia? +} diff --git a/packages/dataprovider/test-data/testSchema.ts b/packages/dataprovider/test-data/testSchema.ts index 543a03f..fb08806 100644 --- a/packages/dataprovider/test-data/testSchema.ts +++ b/packages/dataprovider/test-data/testSchema.ts @@ -18,6 +18,7 @@ const User = objectType({ t.model.roles({ filtering: true }); t.model.gender(); t.model.wantsNewsletter(); + t.model.userSocialMedia(null); // add one field that needs arguments and therefore can't be used by react-admin t.list.field("logs", { @@ -33,11 +34,24 @@ const UserRole = objectType({ name: "UserRole", definition(t) { t.model.id(); + t.model.name(); }, }); + +const UserSocialMedia = objectType({ + name: "UserSocialMedia", + definition(t) { + t.model.id(); + t.model.instagram(); + t.model.twitter(); + t.model.user(); + }, +}); + const types = [ User, UserRole, + UserSocialMedia, addCrudResolvers("User"), addCrudResolvers("UserRole"), ]; diff --git a/yarn.lock b/yarn.lock index 66126b9..50d76f6 100644 --- a/yarn.lock +++ b/yarn.lock @@ -8280,6 +8280,11 @@ prettier-linter-helpers@^1.0.0: dependencies: fast-diff "^1.1.2" +prettier@^2.0.5: + version "2.0.5" + resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.0.5.tgz#d6d56282455243f2f92cc1716692c08aa31522d4" + integrity sha512-7PtVymN48hGcO4fGjybyBSIWDsLU4H4XlvOHfq91pz9kkGlonzwTfYkaIEwiRg/dAJF9YlbsduBAgtYLi+8cFg== + pretty-format@^24.8.0: version "24.9.0" resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-24.9.0.tgz#12fac31b37019a4eea3c11aa9a959eb7628aa7c9"