Skip to content

Commit

Permalink
crudToIgraphQL
Browse files Browse the repository at this point in the history
  • Loading branch information
pavelbrui committed Sep 1, 2023
1 parent 2982379 commit a90774b
Show file tree
Hide file tree
Showing 10 changed files with 111 additions and 114 deletions.
2 changes: 1 addition & 1 deletion packages/integrations/gei-crud/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "gei-crud",
"version": "0.8.6",
"version": "0.8.7",
"description": "GraphQL Editor integration for stucco. Allows basic crud operations and relations.",
"main": "lib/index.js",
"private": false,
Expand Down
8 changes: 4 additions & 4 deletions packages/integrations/gei-crud/src/Mutation/create.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { ObjectId, OptionalId } from 'mongodb';
import { FieldResolveInput } from 'stucco-js';
import { prepareModel, prepareSourceParameters } from '../data.js';
import { DB } from '../db/mongo.js';
import { DB } from '../db/orm.js';
import { getReturnTypeName } from '../shared.js';

export const handler = async (input: FieldResolveInput) =>
Expand All @@ -21,8 +21,8 @@ export const handler = async (input: FieldResolveInput) =>
createdAt: new Date().toISOString(),
updatedAt: new Date().toISOString(),
};
return db
.collection(prepareModel(input))
.insertOne(creationInput)

return db(prepareModel(input))
.collection.insertOne(creationInput)
.then((result) => result.insertedId);
});
62 changes: 30 additions & 32 deletions packages/integrations/gei-crud/src/Mutation/delete.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,6 @@
import { FieldResolveInput } from 'stucco-js';
import {
prepareModel,
prepare_id,
prepareSourceParameters,
prepareRelatedField,
} from '../data.js';
import { DB } from '../db/mongo.js';
import { prepareModel, prepare_id, prepareSourceParameters, prepareRelatedField } from '../data.js';
import { DB } from '../db/orm.js';
import { getResolverData } from '../shared.js';

export const handler = async (input: FieldResolveInput) => {
Expand All @@ -14,48 +9,51 @@ export const handler = async (input: FieldResolveInput) => {
const _id = prepare_id(input) || prepareSourceParameters(input)._id;
if (!_id) throw new Error('_id not found');

const object = await db.collection(prepareModel(input)).findOne({ _id });
const object = await db(prepareModel(input)).collection.findOne({ _id });
if (!object) {
throw new Error('Object with this _id not found');
}

const res = await db.collection(prepareModel(input)).deleteOne({ _id, ...prepareSourceParameters(input) });
const res = await db(prepareModel(input)).collection.deleteOne({ _id, ...prepareSourceParameters(input) });
if (!res.deletedCount) {
throw new Error(
`Object not found. Please check parameters: ${JSON.stringify({ _id, ...prepareSourceParameters(input) })}`,
);
}

const { data } = getResolverData<{ relatedModel: string }>(input);
const relatedCollectionsField = data?.relatedModel.value;
if (relatedCollectionsField) {
const relatedCollectionsField = data?.relatedModel?.value;
console.log(relatedCollectionsField?.length);
console.log(relatedCollectionsField);

const s = object as Record<string, any>;
const relatedCollections = relatedCollectionsField.replace(/["' ]/g, '').split(',');
const prepareFields = prepareRelatedField(input)?.replace(/[{ }]/g, '').split(',');
let i = 0;
for (const rC of relatedCollections) {
const prepareField = prepareFields[i]?.split(':') || prepareFields[0]?.split(':');
i++;
if (prepareField) {
const fieldForFounding = prepareField[0];
const fieldWithIdOrArray = prepareField[1] || undefined;
if (relatedCollectionsField && relatedCollectionsField?.length > 2) {
console.log('kkdlckm');
const s = object as Record<string, any>;
const relatedCollections = relatedCollectionsField.replace(/["' ]/g, '').split(',');
const prepareFields = prepareRelatedField(input)?.replace(/[{ }]/g, '').split(',');
let i = 0;
for (const rC of relatedCollections) {
const prepareField = prepareFields[i]?.split(':') || prepareFields[0]?.split(':');
i++;
if (prepareField) {
const fieldForFounding = prepareField[0];
const fieldWithIdOrArray = prepareField[1] || undefined;

if (!fieldWithIdOrArray) {
await db.collection(rC).updateMany({}, { $pull: { [fieldForFounding]: s._id } });
await db.collection(rC).deleteMany({ [fieldForFounding]: s._id });
} else if (!s[fieldWithIdOrArray]?.length) {
return !!res.deletedCount;
} else {
if (typeof s[fieldWithIdOrArray] === 'string') {
await db.collection(rC).updateMany({}, { $pull: { [fieldForFounding]: s[fieldWithIdOrArray] } });
await db.collection(rC).deleteMany({ [fieldForFounding]: s[fieldWithIdOrArray] });
if (!fieldWithIdOrArray) {
await db(rC).collection.updateMany({}, { $pull: { [fieldForFounding]: s._id } });
await db(rC).collection.deleteMany({ [fieldForFounding]: s._id });
} else if (!s[fieldWithIdOrArray]?.length) {
return !!res.deletedCount;
} else {
await db.collection(rC).deleteMany({ [fieldForFounding]: { $in: s[fieldWithIdOrArray] } });
if (typeof s[fieldWithIdOrArray] === 'string') {
await db(rC).collection.updateMany({}, { $pull: { [fieldForFounding]: s[fieldWithIdOrArray] } });
await db(rC).collection.deleteMany({ [fieldForFounding]: s[fieldWithIdOrArray] });
} else {
await db(rC).collection.deleteMany({ [fieldForFounding]: { $in: s[fieldWithIdOrArray] } });
}
}
}
}
}
}
return !!res.deletedCount;
};
32 changes: 17 additions & 15 deletions packages/integrations/gei-crud/src/Mutation/update.ts
Original file line number Diff line number Diff line change
@@ -1,34 +1,36 @@
import { FieldResolveInput } from 'stucco-js';
import { prepareModel, prepare_id, prepareSourceParameters } from '../data.js';
import { DB } from '../db/mongo.js';
import { DB } from '../db/orm.js';

export const handler = async (input: FieldResolveInput) =>
DB().then(async (db) => {
const _id = prepare_id(input) || (prepareSourceParameters(input)._id as string);
if (!_id) throw new Error('_id not found');
const entries = Object.entries(input.arguments || {});
const reconstructedObject: Record<string, any> = {};

const entriesWithOutId = entries.filter((e) => e[0] !== '_id');
if (!entriesWithOutId) {
throw new Error(`You need update input argument for this resolver to work`);
}

if (typeof entriesWithOutId[0][1] ==='object' ) {
if(entriesWithOutId[1]) throw new Error(
'There should be only string arguments or _id argument and one argument of "input" type to update this model',
)
} else{
(entriesWithOutId as [string, any][]).forEach((entry: [string, any]) => {

if (typeof entriesWithOutId[0][1] === 'object') {
if (entriesWithOutId[1])
throw new Error(
'There should be only string arguments or _id argument and one argument of "input" type to update this model',
);
} else {
(entriesWithOutId as [string, any][]).forEach((entry: [string, any]) => {
const [key, value] = entry;
reconstructedObject[key] = value;
});
}
const setter = typeof entriesWithOutId[0][1] ==='object' ? entriesWithOutId[0][1] : reconstructedObject
const setter = typeof entriesWithOutId[0][1] === 'object' ? entriesWithOutId[0][1] : reconstructedObject;
const filterInput: Record<string, any> = { _id, ...prepareSourceParameters(input) };
const res = await db
.collection(prepareModel(input))
.updateOne(filterInput, { $set: { ...(setter), updatedAt: new Date().toISOString() } })
if(res.matchedCount<1) throw new Error(`Object for update not found. Please check parameters: ${ JSON.stringify(filterInput)}`)
return res.modifiedCount>=1
const res = await db(prepareModel(input)).collection.updateOne(filterInput, {
$set: { ...setter, updatedAt: new Date().toISOString() },
});
if (res.matchedCount < 1)
throw new Error(`Object for update not found. Please check parameters: ${JSON.stringify(filterInput)}`);
return res.modifiedCount >= 1;
});
7 changes: 3 additions & 4 deletions packages/integrations/gei-crud/src/Object/oneToMany.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { FieldResolveInput } from 'stucco-js';
import { prepareRelatedField, prepareRelatedModel } from '../data.js';
import { DB } from '../db/mongo.js';
import { DB } from '../db/orm.js';

export const handler = async (input: FieldResolveInput) => {
return DB().then(async (db) => {
Expand All @@ -26,9 +26,8 @@ export const handler = async (input: FieldResolveInput) => {
}
}

return db
.collection(prepareRelatedModel(input))
.find({
return db(prepareRelatedModel(input))
.collection.find({
[fieldForFounding]: fieldWithArray ? { $in: s[fieldWithArray] } : s._id,
})
.toArray();
Expand Down
4 changes: 2 additions & 2 deletions packages/integrations/gei-crud/src/Object/oneToOne.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { FieldResolveInput } from 'stucco-js';
import { prepareRelatedField, prepareRelatedModel } from '../data.js';
import { DB } from '../db/mongo.js';
import { DB } from '../db/orm.js';

export const handler = async (input: FieldResolveInput) =>
DB().then(async (db) => {
Expand All @@ -15,5 +15,5 @@ export const handler = async (input: FieldResolveInput) =>
const field = prepareField[0];
const objectField = prepareField[1] ? prepareField[1] : undefined;
if (objectField && typeof s[objectField] !== 'string') return objectField;
return db.collection(prepareRelatedModel(input)).findOne({ [field]: objectField || s._id });
return db(prepareRelatedModel(input)).collection.findOne({ [field]: objectField || s._id });
});
71 changes: 36 additions & 35 deletions packages/integrations/gei-crud/src/Query/objects.ts
Original file line number Diff line number Diff line change
@@ -1,76 +1,77 @@
import { FieldResolveInput } from 'stucco-js';
import { prepareModel, prepareSourceParameters } from '../data.js';
import { DB } from '../db/mongo.js';
import { DB } from '../db/orm.js';

export const handler = async (input: FieldResolveInput) => {
return DB().then((db) => {
const sortArg = input.arguments?.sortByField || input.arguments?.sort
const sort = (typeof sortArg === 'object') ? sortArg as {field: string, order?: boolean} : undefined
const field = snakeCaseToCamelCase(sort?.field as unknown as string)
const fieldFilter = input.arguments?.fieldFilter
const dateFilter =input.arguments?.dateFilter
const fieldRegexFilter: any = input.arguments?.fieldRegexFilter ? input.arguments?.fieldRegexFilter : fieldFilter ? {} : checkStringFields(input.arguments)? input.arguments : {}
if (fieldRegexFilter?.sortByField) delete fieldRegexFilter?.sortByField
if (fieldRegexFilter?.sort) delete fieldRegexFilter?.sort
if (fieldRegexFilter?.dateFilter) delete fieldRegexFilter?.dateFilter
const sortArg = input.arguments?.sortByField || input.arguments?.sort;
const sort = typeof sortArg === 'object' ? (sortArg as { field: string; order?: boolean }) : undefined;
const field = snakeCaseToCamelCase(sort?.field as unknown as string);
const fieldFilter = input.arguments?.fieldFilter;
const dateFilter = input.arguments?.dateFilter;
const fieldRegexFilter: any = input.arguments?.fieldRegexFilter
? input.arguments?.fieldRegexFilter
: fieldFilter
? {}
: checkStringFields(input.arguments)
? input.arguments
: {};
if (fieldRegexFilter?.sortByField) delete fieldRegexFilter?.sortByField;
if (fieldRegexFilter?.sort) delete fieldRegexFilter?.sort;
if (fieldRegexFilter?.dateFilter) delete fieldRegexFilter?.dateFilter;
const filterInput = {
...prepareSourceParameters(input),
...convertDateFilter(dateFilter as QueryObject),
...(ifValueIsArray(fieldFilter as QueryObject)),
...ifValueIsArray(fieldFilter as QueryObject),
...convertObjectToRegexFormat(ifValueIsArray(fieldRegexFilter) as QueryObject),
};

return db.collection(prepareModel(input)).find(filterInput).sort(field ? { [field]: sort?.order === false ? -1 : 1 } : { _id: 1 }).toArray();

return db(prepareModel(input))
.collection.find(filterInput)
.sort(field ? { [field]: sort?.order === false ? -1 : 1 } : { _id: 1 })
.toArray();
});
};

interface QueryObject {
[key: string]: unknown;
}


// Function to convert the object to the desired format
function convertObjectToRegexFormat(obj: QueryObject): QueryObject | undefined {


for (const key in obj) {
if (Array.isArray(obj[key])) obj[key] = { $regex: { $in: obj[key]}, $options: 'i' }
if (obj[key]&& typeof obj[key] === 'string' ) obj[key] = { $regex: obj[key], $options: 'i' };
if (Array.isArray(obj[key])) obj[key] = { $regex: { $in: obj[key] }, $options: 'i' };
if (obj[key] && typeof obj[key] === 'string') obj[key] = { $regex: obj[key], $options: 'i' };
}
return obj;
}


function ifValueIsArray(obj: QueryObject): QueryObject | undefined {
for (const key in obj) {
if (Array.isArray(obj[key]) ) obj[key] = { $in: obj[key]}
if (Array.isArray(obj[key])) obj[key] = { $in: obj[key] };
}
return obj;
}


function snakeCaseToCamelCase(input: string | null | undefined) {
function snakeCaseToCamelCase(input: string | null | undefined) {
return input?.toLowerCase().replace(/_([a-z])/g, (match, group1) => group1.toUpperCase());
}


function checkStringFields(obj: Record<string, unknown> | undefined): boolean {
for (const key in obj) {
if (typeof obj[key] === 'string' || Array.isArray(obj[key])) {
return true;
if (typeof obj[key] === 'string' || Array.isArray(obj[key])) {
return true;
}
}
return false;
return false;
}


function convertDateFilter(obj: QueryObject): QueryObject | undefined {
if(!obj) return {}
return { [obj.dateFieldName? obj.dateFieldName as string : 'createdAt'] : {
$gte: obj.from || "",
...(obj.to ? { $lte: obj.to } : {}),
}}
if (!obj) return {};
return {
[obj.dateFieldName ? (obj.dateFieldName as string) : 'createdAt']: {
$gte: obj.from || '',
...(obj.to ? { $lte: obj.to } : {}),
},
};
}



4 changes: 2 additions & 2 deletions packages/integrations/gei-crud/src/Query/oneById.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import { FieldResolveInput } from 'stucco-js';
import { prepareModel, prepareRequired_id, prepareSourceParameters } from '../data.js';
import { DB } from '../db/mongo.js';
import { DB } from '../db/orm.js';

export const handler = async (input: FieldResolveInput) =>
DB().then(async (db) => {
const _id = prepareRequired_id(input);
const filterInput: Record<string, any> = { _id, ...prepareSourceParameters(input) };
return db.collection(prepareModel(input)).findOne(filterInput);
return db(prepareModel(input)).collection.findOne(filterInput);
});
19 changes: 0 additions & 19 deletions packages/integrations/gei-crud/src/db/mongo.ts

This file was deleted.

16 changes: 16 additions & 0 deletions packages/integrations/gei-crud/src/db/orm.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { iGraphQL } from 'i-graphql';
import { ObjectId } from 'mongodb';

export const orm = async () => {
console.log('IGraphQl');
//const modell = collection.replace("Collection", "Model")

return iGraphQL<Record<string, any>, { _id: () => string; createdAt: () => string }>({
_id: () => new ObjectId().toHexString(),
createdAt: () => new Date().toISOString(),
});
};

export async function DB() {
return orm();
}

0 comments on commit a90774b

Please sign in to comment.