Skip to content

Commit 903412e

Browse files
committed
query builder created
1 parent ab9ce44 commit 903412e

File tree

4 files changed

+580
-14
lines changed

4 files changed

+580
-14
lines changed

.gitignore

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,4 +7,8 @@ coverage
77

88
# Examples
99
example/**/*
10-
!example/index.js
10+
!example/index.js
11+
12+
# Random files
13+
newQueryBuilder.ts
14+
query-builder.ts

dist/stack.js

Lines changed: 260 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -517,23 +517,92 @@ class Stack {
517517
}
518518
throw new Error('Kindly pass a query object for \'.queryReferences()\'');
519519
}
520+
queryReferencesBeta(query) {
521+
if (query && typeof query === 'object') {
522+
this.internal.queryReferencesBeta = query;
523+
return this;
524+
}
525+
throw new Error('Kindly pass a query object for \'.queryReferences()\'');
526+
}
520527
getQuery() {
521528
return Object.assign({}, this.q);
522529
}
530+
include(fields) {
531+
if (fields.length === 0) {
532+
throw new Error('Kindly pass a valid reference field path to \'.include()\' ');
533+
}
534+
else if (typeof fields === 'string') {
535+
this.internal.includeSpecificReferences = [fields];
536+
}
537+
else {
538+
this.internal.includeSpecificReferences = fields;
539+
}
540+
return this;
541+
}
523542
find(query = {}) {
524543
return new Promise((resolve, reject) => {
525-
const queryFilters = this.preProcess(query);
526-
if (this.internal.sort) {
527-
this.collection = this.collection.find(queryFilters).sort(this.internal.sort);
528-
}
529-
else {
530-
this.collection = this.collection.find(queryFilters);
531-
}
544+
let queryFilters = this.preProcess(query);
532545
if (this.internal.queryReferences) {
533546
return this.queryOnReferences()
534547
.then(resolve)
535548
.catch(reject);
536549
}
550+
if (this.internal.queryReferencesBeta) {
551+
return this.queryBuilder(this.internal.queryReferencesBeta, this.q.locale, this.q.content_type_uid)
552+
.then((query) => {
553+
queryFilters = lodash_1.merge(queryFilters, query);
554+
this.collection = this.collection.find(queryFilters);
555+
return this.collection
556+
.project(this.internal.projections)
557+
.limit(this.internal.limit)
558+
.skip(this.internal.skip)
559+
.toArray()
560+
.then((result) => {
561+
let contentType;
562+
if (this.internal.includeSchema && this.q.content_type_uid !== 'contentTypes' && this.q.content_type_uid !==
563+
'_assets') {
564+
contentType = lodash_1.remove(result, { uid: this.q.content_type_uid });
565+
contentType = (typeof contentType === 'object' && contentType instanceof Array && contentType.length) ?
566+
contentType[0] : null;
567+
}
568+
if (this.internal.excludeReferences || this.q.content_type_uid === 'contentTypes' || this.q.content_type_uid
569+
=== '_assets') {
570+
result = this.postProcess(result, contentType);
571+
return resolve(result);
572+
}
573+
else if (this.internal.includeSpecificReferences) {
574+
return this.includeSpecificReferences(result, this.q.locale, {}, undefined, this.internal.includeSpecificReferences)
575+
.then(() => {
576+
result = this.postProcess(result, contentType);
577+
return resolve(result);
578+
})
579+
.catch((refError) => {
580+
this.cleanup();
581+
return reject(refError);
582+
});
583+
}
584+
else {
585+
return this.includeReferencesI(result, this.q.locale, {}, undefined)
586+
.then(() => {
587+
result = this.postProcess(result, contentType);
588+
return resolve(result);
589+
})
590+
.catch((refError) => {
591+
this.cleanup();
592+
return reject(refError);
593+
});
594+
}
595+
})
596+
.catch((error) => {
597+
this.cleanup();
598+
return reject(error);
599+
});
600+
})
601+
.catch((error) => {
602+
this.cleanup();
603+
return reject(error);
604+
});
605+
}
537606
return this.collection
538607
.project(this.internal.projections)
539608
.limit(this.internal.limit)
@@ -552,6 +621,17 @@ class Stack {
552621
result = this.postProcess(result, contentType);
553622
return resolve(result);
554623
}
624+
else if (this.internal.includeSpecificReferences) {
625+
return this.includeSpecificReferences(result, this.q.locale, {}, undefined, this.internal.includeSpecificReferences)
626+
.then(() => {
627+
result = this.postProcess(result, contentType);
628+
return resolve(result);
629+
})
630+
.catch((refError) => {
631+
this.cleanup();
632+
return reject(refError);
633+
});
634+
}
555635
else {
556636
return this.includeReferencesI(result, this.q.locale, {}, undefined)
557637
.then(() => {
@@ -833,5 +913,178 @@ class Stack {
833913
.catch(reject);
834914
});
835915
}
916+
isPartOfInclude(pth, include) {
917+
for (let i = 0, j = include.length; i < j; i++) {
918+
if (include[i].indexOf(pth) !== -1) {
919+
return true;
920+
}
921+
}
922+
return false;
923+
}
924+
includeSpecificReferences(entry, locale, references, parentUid, includePths = [], parentField = '') {
925+
const self = this;
926+
return new Promise((resolve, reject) => {
927+
if (entry === null || typeof entry !== 'object') {
928+
return resolve();
929+
}
930+
if (entry.uid) {
931+
parentUid = entry.uid;
932+
}
933+
const referencesFound = [];
934+
for (const prop in entry) {
935+
if (entry[prop] !== null && typeof entry[prop] === 'object') {
936+
let currentPth;
937+
if (parentField === '' && isNaN(parseInt(prop))) {
938+
currentPth = prop;
939+
}
940+
else if (parentField === '' && !isNaN(parseInt(prop))) {
941+
currentPth = parentField;
942+
}
943+
else {
944+
currentPth = parentField.concat('.', prop);
945+
}
946+
if (entry[prop] && entry[prop].reference_to) {
947+
if (entry[prop].reference_to === '_assets' || this.isPartOfInclude(currentPth, includePths)) {
948+
if (entry[prop].values.length === 0) {
949+
entry[prop] = [];
950+
}
951+
else {
952+
let uids = entry[prop].values;
953+
if (typeof uids === 'string') {
954+
uids = [uids];
955+
}
956+
if (entry[prop].reference_to !== '_assets') {
957+
uids = lodash_1.filter(uids, (uid) => {
958+
return !(util_1.checkCyclic(uid, references));
959+
});
960+
}
961+
if (uids.length) {
962+
const query = {
963+
content_type_uid: entry[prop].reference_to,
964+
locale,
965+
uid: {
966+
$in: uids,
967+
},
968+
};
969+
referencesFound.push(new Promise((rs, rj) => {
970+
return self.db.collection(this.contentStore.collectionName)
971+
.find(query)
972+
.project(self.config.contentStore.projections)
973+
.toArray()
974+
.then((result) => {
975+
if (result.length === 0) {
976+
entry[prop] = [];
977+
return rs();
978+
}
979+
else if (parentUid) {
980+
references[parentUid] = references[parentUid] || [];
981+
references[parentUid] = lodash_1.uniq(references[parentUid].concat(lodash_1.map(result, 'uid')));
982+
}
983+
if (typeof entry[prop].values === 'string') {
984+
entry[prop] = ((result === null) || result.length === 0) ? null : result[0];
985+
}
986+
else {
987+
const referenceBucket = [];
988+
query.uid.$in.forEach((entityUid) => {
989+
const elem = lodash_1.find(result, (entity) => {
990+
return entity.uid === entityUid;
991+
});
992+
if (elem) {
993+
referenceBucket.push(elem);
994+
}
995+
});
996+
entry[prop] = referenceBucket;
997+
}
998+
return self.includeSpecificReferences(entry[prop], locale, references, parentUid, includePths, currentPth)
999+
.then(rs)
1000+
.catch(rj);
1001+
})
1002+
.catch(rj);
1003+
}));
1004+
}
1005+
}
1006+
}
1007+
}
1008+
else {
1009+
referencesFound.push(self.includeSpecificReferences(entry[prop], locale, references, parentUid, includePths, currentPth));
1010+
}
1011+
}
1012+
}
1013+
return Promise.all(referencesFound)
1014+
.then(resolve)
1015+
.catch(reject);
1016+
});
1017+
}
1018+
queryBuilder(query, language, ct) {
1019+
return new Promise((resolve, reject) => {
1020+
if (query && Object.keys(query).length && ct) {
1021+
return this.db.collection(this.contentStore.collectionName)
1022+
.find({
1023+
content_type_uid: 'contentTypes',
1024+
locale: language,
1025+
uid: ct
1026+
})
1027+
.project({
1028+
reference_to: 1
1029+
})
1030+
.limit(1)
1031+
.toArray()
1032+
.then((result) => {
1033+
if (result === null || result.length === 0) {
1034+
return resolve();
1035+
}
1036+
const references = result[0].reference_to;
1037+
if (references && Object.keys(references).length > 0) {
1038+
const promises = [];
1039+
for (const field in query) {
1040+
let filterField = field;
1041+
let refQuery, refContentType;
1042+
for (let refField in references) {
1043+
if (field.indexOf(refField) === 0) {
1044+
filterField = filterField.split('.');
1045+
filterField[filterField.length - 1] = 'uid';
1046+
filterField = filterField.join('.');
1047+
refQuery = refQuery || {};
1048+
refContentType = references[refField];
1049+
refQuery[filterField] = query[field];
1050+
refQuery.content_type_uid = refContentType;
1051+
refQuery.locale = language;
1052+
delete query[field];
1053+
}
1054+
}
1055+
if (refQuery && Object.keys(refQuery).length) {
1056+
promises.push(this.db.collection(this.contentStore.collectionName)
1057+
.find(refQuery)
1058+
.project({ uid: 1 })
1059+
.toArray()
1060+
.then((result) => {
1061+
if (result === null || result.length === 0) {
1062+
query[filterField] = {
1063+
$in: []
1064+
};
1065+
}
1066+
else {
1067+
query[filterField] = {
1068+
$in: lodash_1.map(result, 'uid')
1069+
};
1070+
}
1071+
}));
1072+
}
1073+
else if (query[field] !== null && typeof query[field] === 'object' && query[field] instanceof Array && query[field].length) {
1074+
promises.push(this.queryBuilder(query[field], language, ct));
1075+
}
1076+
}
1077+
}
1078+
else {
1079+
return resolve(query);
1080+
}
1081+
})
1082+
.catch(reject);
1083+
}
1084+
else {
1085+
return resolve(query);
1086+
}
1087+
});
1088+
}
8361089
}
8371090
exports.Stack = Stack;

0 commit comments

Comments
 (0)