Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feat/fix empty #41

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
248 changes: 167 additions & 81 deletions src/buildVariables.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@ import { computeFieldsToAddRemoveUpdate } from './utils/computeAddRemoveUpdate';
import {
PRISMA_CONNECT,
PRISMA_DISCONNECT,
PRISMA_UPDATE
PRISMA_UPDATE,
PRISMA_CREATE
} from './constants/mutations';
import {
IntrospectionInputObjectType,
Expand Down Expand Up @@ -143,6 +144,35 @@ const inputFieldExistsForType = (
return !!findInputFieldForType(introspectionResults, typeName, field);
};

const findMutationInputType = (
introspectionResults: IntrospectionResult,
typeName: string,
field: string,
mutationType: string
) => {
const inputType = findInputFieldForType(
introspectionResults,
typeName,
field
);
return findInputFieldForType(
introspectionResults,
inputType!.name,
mutationType
);
};

const hasMutationInputType = (
introspectionResults: IntrospectionResult,
typeName: string,
field: string,
mutationType: string
) => {
return Boolean(
findMutationInputType(introspectionResults, typeName, field, mutationType)
);
};

const buildReferenceField = ({
inputArg,
introspectionResults,
Expand All @@ -156,14 +186,10 @@ const buildReferenceField = ({
field: string;
mutationType: string;
}) => {
const inputType = findInputFieldForType(
const mutationInputType = findMutationInputType(
introspectionResults,
typeName,
field
);
const mutationInputType = findInputFieldForType(
introspectionResults,
inputType!.name,
field,
mutationType
);

Expand All @@ -178,6 +204,65 @@ const buildReferenceField = ({
}, {});
};

const shouldDisconnect = (inputArg: { [key: string]: any }) => {
// if inputArg is something like {id: null} or {id: ""}, we need to disconnect
// TODO: find a better way how to handle this case
return !Object.keys(inputArg).some(key => Boolean(inputArg[key]));
};

const buildObjectMutationData = ({
inputArg,
introspectionResults,
typeName,
key,
type
}: {
inputArg: { [key: string]: any };
introspectionResults: IntrospectionResult;
typeName: string;
key: string;
type: 'create' | 'update';
}) => {
const hasConnect = hasMutationInputType(
introspectionResults,
typeName,
key,
PRISMA_CONNECT
);
if (shouldDisconnect(inputArg)) {
if (type === 'update') {
return {
[key]: {
[PRISMA_DISCONNECT]: true
}
};
} else {
// on create, just ignore it. We can't disconnect on create
return {};
}
} else {
const mutationType = hasConnect ? PRISMA_CONNECT : PRISMA_CREATE;

const fields = buildReferenceField({
inputArg,
introspectionResults,
typeName,
field: key,
mutationType
});

// If no fields in the object are valid, continue
if (Object.keys(fields).length === 0) {
return {};
}

// Else, connect the nodes
return {
[key]: { [mutationType]: { ...fields } }
};
}
};

interface UpdateParams {
id: string;
data: { [key: string]: any };
Expand All @@ -191,17 +276,26 @@ const buildUpdateVariables = (introspectionResults: IntrospectionResult) => (
) => {
return Object.keys(params.data).reduce(
(acc, key) => {
if (Array.isArray(params.data[key])) {
const inputType = findInputFieldForType(
introspectionResults,
`${resource.type.name}UpdateInput`,
key
);
// Put id field in a where object
if (key === 'id' && params.data[key]) {
return {
...acc,
where: {
id: params.data[key]
}
};
}
const inputType = findInputFieldForType(
introspectionResults,
`${resource.type.name}UpdateInput`,
key
);

if (!inputType) {
return acc;
}
if (!inputType) {
return acc;
}

if (Array.isArray(params.data[key])) {
//TODO: Make connect, disconnect and update overridable
//TODO: Make updates working
const {
Expand All @@ -226,37 +320,24 @@ const buildUpdateVariables = (introspectionResults: IntrospectionResult) => (
}

if (isObject(params.data[key])) {
const fieldsToUpdate = buildReferenceField({
inputArg: params.data[key],
introspectionResults,
typeName: `${resource.type.name}UpdateInput`,
field: key,
mutationType: PRISMA_CONNECT
});
if (inputType.kind !== 'SCALAR') {
const typeName = `${resource.type.name}UpdateInput`;

// If no fields in the object are valid, continue
if (Object.keys(fieldsToUpdate).length === 0) {
return acc;
const data = buildObjectMutationData({
inputArg: params.data[key],
introspectionResults,
typeName,
key,
type: 'update'
});
return {
...acc,
data: {
...acc.data,
...data
}
};
}

// Else, connect the nodes
return {
...acc,
data: {
...acc.data,
[key]: { [PRISMA_CONNECT]: { ...fieldsToUpdate } }
}
};
}

// Put id field in a where object
if (key === 'id' && params.data[key]) {
return {
...acc,
where: {
id: params.data[key]
}
};
}

const type = introspectionResults.types.find(
Expand Down Expand Up @@ -291,17 +372,26 @@ const buildCreateVariables = (introspectionResults: IntrospectionResult) => (
) =>
Object.keys(params.data).reduce(
(acc, key) => {
if (Array.isArray(params.data[key])) {
if (
!inputFieldExistsForType(
introspectionResults,
`${resource.type.name}CreateInput`,
key
)
) {
return acc;
}
// Put id field in a where object
if (key === 'id' && params.data[key]) {
return {
...acc,
where: {
id: params.data[key]
}
};
}

const inputType = findInputFieldForType(
introspectionResults,
`${resource.type.name}UpdateInput`,
key
);

if (!inputType) {
return acc;
}
if (Array.isArray(params.data[key])) {
return {
...acc,
data: {
Expand All @@ -316,37 +406,33 @@ const buildCreateVariables = (introspectionResults: IntrospectionResult) => (
}

if (isObject(params.data[key])) {
const fieldsToConnect = buildReferenceField({
inputArg: params.data[key],
const inputType = findInputFieldForType(
introspectionResults,
typeName: `${resource.type.name}CreateInput`,
field: key,
mutationType: PRISMA_CONNECT
});
`${resource.type.name}UpdateInput`,
key
);

// If no fields in the object are valid, continue
if (Object.keys(fieldsToConnect).length === 0) {
if (!inputType) {
return acc;
}

// Else, connect the nodes
return {
...acc,
data: {
...acc.data,
[key]: { [PRISMA_CONNECT]: { ...fieldsToConnect } }
}
};
}

// Put id field in a where object
if (key === 'id' && params.data[key]) {
return {
...acc,
where: {
id: params.data[key]
}
};
if (inputType.kind !== 'SCALAR') {
const typeName = `${resource.type.name}CreateInput`;
const data = buildObjectMutationData({
inputArg: params.data[key],
introspectionResults,
typeName,
key,
type: 'create'
});
return {
...acc,
data: {
...acc.data,
...data
}
};
}
}

const type = introspectionResults.types.find(
Expand Down