chore: begins work to build queries from fields instead of mongoose schema

This commit is contained in:
James
2023-04-14 15:52:38 -04:00
parent 299ae4fce5
commit 2d0441a72e
25 changed files with 325 additions and 237 deletions

View File

@@ -16,26 +16,24 @@ const getExecuteStaticAccess = ({ config, Model }) => async (req: PayloadRequest
if (typeof accessResult === 'object') {
const filename = decodeURI(req.path).replace(/^\/|\/$/g, '');
const queryToBuild: { where: Where } = {
where: {
and: [
{
or: [
{
filename: {
equals: filename,
},
const queryToBuild: Where = {
and: [
{
or: [
{
filename: {
equals: filename,
},
],
},
accessResult,
],
},
},
],
},
accessResult,
],
};
if (config.upload.imageSizes) {
config.upload.imageSizes.forEach(({ name }) => {
queryToBuild.where.and[0].or.push({
queryToBuild.and[0].or.push({
[`sizes.${name}.filename`]: {
equals: filename,
},
@@ -43,7 +41,12 @@ const getExecuteStaticAccess = ({ config, Model }) => async (req: PayloadRequest
});
}
const query = await Model.buildQuery(queryToBuild, req.locale);
const query = await Model.buildQuery({
where: queryToBuild,
req,
overrideAccess: true,
});
const doc = await Model.findOne(query);
if (!doc) {

View File

@@ -45,7 +45,6 @@ export default (payload: Payload, { Model, config }): PassportAPIKey => {
},
req: req as PayloadRequest,
overrideAccess: true,
queryHiddenFields: true,
depth: config.auth.depth,
});

View File

@@ -1,7 +1,7 @@
import paginate from 'mongoose-paginate-v2';
import { Schema } from 'mongoose';
import { SanitizedConfig } from '../config/types';
import buildQueryPlugin from '../mongoose/buildQuery';
import getBuildQueryPlugin from '../mongoose/buildQuery';
import buildSchema from '../mongoose/buildSchema';
import { SanitizedCollectionConfig } from './config/types';
@@ -26,7 +26,7 @@ const buildCollectionSchema = (collection: SanitizedCollectionConfig, config: Sa
}
schema.plugin(paginate, { useEstimatedCount: true })
.plugin(buildQueryPlugin);
.plugin(getBuildQueryPlugin({ collectionSlug: collection.slug }));
return schema;
};

View File

@@ -10,6 +10,7 @@ import { Auth, IncomingAuthType } from '../../auth/types';
import { IncomingUploadType, Upload } from '../../uploads/types';
import { IncomingCollectionVersions, SanitizedCollectionVersions } from '../../versions/types';
import { Config as GeneratedTypes } from '../../generated-types';
import { BuildQueryArgs } from '../../mongoose/buildQuery';
type Register<T = any> = (doc: T, password: string) => T;
@@ -19,7 +20,7 @@ interface PassportLocalModel {
}
export interface CollectionModel extends Model<any>, PaginateModel<any>, AggregatePaginateModel<any>, PassportLocalModel {
buildQuery: (query: unknown, locale: string, queryHiddenFields?: boolean) => Record<string, unknown>
buildQuery: (args: BuildQueryArgs) => Promise<Record<string, unknown>>
}
export interface AuthCollectionModel extends CollectionModel {

View File

@@ -3,7 +3,7 @@ import paginate from 'mongoose-paginate-v2';
import passportLocalMongoose from 'passport-local-mongoose';
import mongooseAggregatePaginate from 'mongoose-aggregate-paginate-v2';
import { buildVersionCollectionFields } from '../versions/buildCollectionFields';
import buildQueryPlugin from '../mongoose/buildQuery';
import getBuildQueryPlugin from '../mongoose/buildQuery';
import buildCollectionSchema from './buildSchema';
import buildSchema from '../mongoose/buildSchema';
import { CollectionModel, SanitizedCollectionConfig } from './config/types';
@@ -62,9 +62,11 @@ export default function initCollectionsLocal(ctx: Payload): void {
if (collection.versions) {
const versionModelName = getVersionsModelName(collection);
const versionCollectionFields = buildVersionCollectionFields(collection);
const versionSchema = buildSchema(
ctx.config,
buildVersionCollectionFields(collection),
versionCollectionFields,
{
disableUnique: true,
draftsEnabled: true,
@@ -76,7 +78,7 @@ export default function initCollectionsLocal(ctx: Payload): void {
);
versionSchema.plugin(paginate, { useEstimatedCount: true })
.plugin(buildQueryPlugin);
.plugin(getBuildQueryPlugin({ collectionSlug: collection.slug, isVersionsModel: true }));
if (collection.versions?.drafts) {
versionSchema.plugin(mongooseAggregatePaginate);

View File

@@ -74,21 +74,19 @@ async function deleteOperation<TSlug extends keyof GeneratedTypes['collections']
// Access
// /////////////////////////////////////
const queryToBuild: { where?: Where } = {
where: {
and: [],
},
let queryToBuild: Where = {
and: [],
};
if (where) {
queryToBuild.where = {
queryToBuild = {
and: [],
...where,
};
if (Array.isArray(where.AND)) {
queryToBuild.where.and = [
...queryToBuild.where.and,
queryToBuild.and = [
...queryToBuild.and,
...where.AND,
];
}
@@ -100,11 +98,15 @@ async function deleteOperation<TSlug extends keyof GeneratedTypes['collections']
accessResult = await executeAccess({ req }, collectionConfig.access.delete);
if (hasWhereAccessResult(accessResult)) {
queryToBuild.where.and.push(accessResult);
queryToBuild.and.push(accessResult);
}
}
const query = await Model.buildQuery(queryToBuild, locale);
const query = await Model.buildQuery({
where: queryToBuild,
req,
overrideAccess,
});
// /////////////////////////////////////
// Retrieve documents

View File

@@ -45,7 +45,6 @@ async function deleteByID<TSlug extends keyof GeneratedTypes['collections']>(inc
req,
req: {
t,
locale,
payload,
payload: {
config,
@@ -80,25 +79,25 @@ async function deleteByID<TSlug extends keyof GeneratedTypes['collections']>(inc
// Retrieve document
// /////////////////////////////////////
const queryToBuild: {
where: Where
} = {
where: {
and: [
{
id: {
equals: id,
},
const queryToBuild: Where = {
and: [
{
id: {
equals: id,
},
],
},
},
],
};
if (hasWhereAccessResult(accessResults)) {
(queryToBuild.where.and as Where[]).push(accessResults);
queryToBuild.and.push(accessResults);
}
const query = await Model.buildQuery(queryToBuild, locale);
const query = await Model.buildQuery({
req,
where: queryToBuild,
overrideAccess,
});
const docToDelete = await Model.findOne(query);

View File

@@ -24,7 +24,6 @@ export type Arguments = {
disableErrors?: boolean
pagination?: boolean
showHiddenFields?: boolean
queryHiddenFields?: boolean
draft?: boolean
}
@@ -66,7 +65,6 @@ async function find<T extends TypeWithID & Record<string, unknown>>(
overrideAccess,
disableErrors,
showHiddenFields,
queryHiddenFields,
pagination = true,
} = args;
@@ -74,23 +72,21 @@ async function find<T extends TypeWithID & Record<string, unknown>>(
// Access
// /////////////////////////////////////
const queryToBuild: { where?: Where } = {
where: {
and: [],
},
let queryToBuild: Where = {
and: [],
};
let useEstimatedCount = false;
if (where) {
queryToBuild.where = {
queryToBuild = {
and: [],
...where,
};
if (Array.isArray(where.AND)) {
queryToBuild.where.and = [
...queryToBuild.where.and,
queryToBuild.and = [
...queryToBuild.and,
...where.AND,
];
}
@@ -122,11 +118,15 @@ async function find<T extends TypeWithID & Record<string, unknown>>(
}
if (hasWhereAccessResult(accessResult)) {
queryToBuild.where.and.push(accessResult);
queryToBuild.and.push(accessResult);
}
}
const query = await Model.buildQuery(queryToBuild, locale, queryHiddenFields);
const query = await Model.buildQuery({
req,
where: queryToBuild,
overrideAccess,
});
// /////////////////////////////////////
// Find
@@ -166,7 +166,8 @@ async function find<T extends TypeWithID & Record<string, unknown>>(
result = await queryDrafts<T>({
accessResult,
collection,
locale,
req,
overrideAccess,
paginationOptions,
payload,
where,

View File

@@ -50,7 +50,6 @@ async function findByID<T extends TypeWithID>(
req,
req: {
t,
locale,
payload,
},
disableErrors,
@@ -69,23 +68,25 @@ async function findByID<T extends TypeWithID>(
// If errors are disabled, and access returns false, return null
if (accessResult === false) return null;
const queryToBuild: { where: Where } = {
where: {
and: [
{
_id: {
equals: id,
},
const queryToBuild: Where = {
and: [
{
_id: {
equals: id,
},
],
},
},
],
};
if (hasWhereAccessResult(accessResult)) {
queryToBuild.where.and.push(accessResult);
queryToBuild.and.push(accessResult);
}
const query = await Model.buildQuery(queryToBuild, locale);
const query = await Model.buildQuery({
where: queryToBuild,
req,
overrideAccess,
});
// /////////////////////////////////////
// Find by ID
@@ -132,7 +133,8 @@ async function findByID<T extends TypeWithID>(
entityType: 'collection',
doc: result,
accessResult,
locale,
req,
overrideAccess,
});
}

View File

@@ -31,7 +31,6 @@ async function findVersionByID<T extends TypeWithVersion<T> = any>(args: Argumen
req,
req: {
t,
locale,
payload,
},
disableErrors,
@@ -57,23 +56,25 @@ async function findVersionByID<T extends TypeWithVersion<T> = any>(args: Argumen
const hasWhereAccess = typeof accessResults === 'object';
const queryToBuild: { where: Where } = {
where: {
and: [
{
_id: {
equals: id,
},
const queryToBuild: Where = {
and: [
{
_id: {
equals: id,
},
],
},
},
],
};
if (hasWhereAccessResult(accessResults)) {
(queryToBuild.where.and as Where[]).push(accessResults);
queryToBuild.and.push(accessResults);
}
const query = await VersionsModel.buildQuery(queryToBuild, locale);
const query = await VersionsModel.buildQuery({
where: queryToBuild,
req,
overrideAccess,
});
// /////////////////////////////////////
// Find by ID

View File

@@ -49,7 +49,7 @@ async function findVersions<T extends TypeWithVersion<T>>(
// Access
// /////////////////////////////////////
const queryToBuild: { where?: Where } = {};
let queryToBuild: Where = {};
let useEstimatedCount = false;
if (where) {
@@ -58,7 +58,7 @@ async function findVersions<T extends TypeWithVersion<T>>(
if (Array.isArray(where.and)) and = where.and;
if (Array.isArray(where.AND)) and = where.AND;
queryToBuild.where = {
queryToBuild = {
...where,
and: [
...and,
@@ -75,18 +75,22 @@ async function findVersions<T extends TypeWithVersion<T>>(
if (hasWhereAccessResult(accessResults)) {
if (!where) {
queryToBuild.where = {
queryToBuild = {
and: [
accessResults,
],
};
} else {
(queryToBuild.where.and as Where[]).push(accessResults);
queryToBuild.and.push(accessResults);
}
}
}
const query = await VersionsModel.buildQuery(queryToBuild, locale);
const query = await VersionsModel.buildQuery({
where: queryToBuild,
req,
overrideAccess,
});
// /////////////////////////////////////
// Find

View File

@@ -20,7 +20,6 @@ export type Options<T extends keyof GeneratedTypes['collections']> = {
overrideAccess?: boolean
disableErrors?: boolean
showHiddenFields?: boolean
queryHiddenFields?: boolean
pagination?: boolean
sort?: string
where?: Where
@@ -45,7 +44,6 @@ export default async function findLocal<T extends keyof GeneratedTypes['collecti
overrideAccess = true,
disableErrors,
showHiddenFields,
queryHiddenFields,
sort,
draft = false,
pagination = true,
@@ -81,7 +79,6 @@ export default async function findLocal<T extends keyof GeneratedTypes['collecti
overrideAccess,
disableErrors,
showHiddenFields,
queryHiddenFields,
draft,
pagination,
req,

View File

@@ -73,23 +73,25 @@ async function restoreVersion<T extends TypeWithID = any>(args: Arguments): Prom
// Retrieve document
// /////////////////////////////////////
const queryToBuild: { where: Where } = {
where: {
and: [
{
id: {
equals: parentDocID,
},
const queryToBuild: Where = {
and: [
{
id: {
equals: parentDocID,
},
],
},
},
],
};
if (hasWhereAccessResult(accessResults)) {
(queryToBuild.where.and as Where[]).push(accessResults);
queryToBuild.and.push(accessResults);
}
const query = await Model.buildQuery(queryToBuild, locale);
const query = await Model.buildQuery({
where: queryToBuild,
req,
overrideAccess,
});
const doc = await Model.findOne(query);

View File

@@ -84,21 +84,19 @@ async function update<TSlug extends keyof GeneratedTypes['collections']>(
// Access
// /////////////////////////////////////
const queryToBuild: { where?: Where } = {
where: {
and: [],
},
let queryToBuild: Where = {
and: [],
};
if (where) {
queryToBuild.where = {
queryToBuild = {
and: [],
...where,
};
if (Array.isArray(where.AND)) {
queryToBuild.where.and = [
...queryToBuild.where.and,
queryToBuild.and = [
...queryToBuild.and,
...where.AND,
];
}
@@ -110,11 +108,15 @@ async function update<TSlug extends keyof GeneratedTypes['collections']>(
accessResult = await executeAccess({ req }, collectionConfig.access.update);
if (hasWhereAccessResult(accessResult)) {
queryToBuild.where.and.push(accessResult);
queryToBuild.and.push(accessResult);
}
}
const query = await Model.buildQuery(queryToBuild, locale);
const query = await Model.buildQuery({
where: queryToBuild,
req,
overrideAccess,
});
// /////////////////////////////////////
// Retrieve documents
@@ -125,7 +127,8 @@ async function update<TSlug extends keyof GeneratedTypes['collections']>(
docs = await queryDrafts<GeneratedTypes['collections'][TSlug]>({
accessResult,
collection,
locale,
req,
overrideAccess,
payload,
where: query,
});

View File

@@ -96,23 +96,25 @@ async function updateByID<TSlug extends keyof GeneratedTypes['collections']>(
// Retrieve document
// /////////////////////////////////////
const queryToBuild: { where: Where } = {
where: {
and: [
{
id: {
equals: id,
},
const queryToBuild: Where = {
and: [
{
id: {
equals: id,
},
],
},
},
],
};
if (hasWhereAccessResult(accessResults)) {
(queryToBuild.where.and as Where[]).push(accessResults);
queryToBuild.and.push(accessResults);
}
const query = await Model.buildQuery(queryToBuild, locale);
const query = await Model.buildQuery({
where: queryToBuild,
req,
overrideAccess,
});
const doc = await getLatestCollectionVersion({
payload,

View File

@@ -1,14 +1,14 @@
import mongoose from 'mongoose';
import buildSchema from '../mongoose/buildSchema';
import { SanitizedConfig } from '../config/types';
import buildQueryPlugin from '../mongoose/buildQuery';
import getBuildQueryPlugin from '../mongoose/buildQuery';
import { GlobalModel } from './config/types';
const buildModel = (config: SanitizedConfig): GlobalModel | null => {
if (config.globals && config.globals.length > 0) {
const globalsSchema = new mongoose.Schema({}, { discriminatorKey: 'globalType', timestamps: true, minimize: false });
globalsSchema.plugin(buildQueryPlugin);
globalsSchema.plugin(getBuildQueryPlugin({ isGlobalModel: true }));
const Globals = mongoose.model('globals', globalsSchema) as unknown as GlobalModel;

View File

@@ -1,6 +1,6 @@
import mongoose from 'mongoose';
import paginate from 'mongoose-paginate-v2';
import buildQueryPlugin from '../mongoose/buildQuery';
import getBuildQueryPlugin from '../mongoose/buildQuery';
import buildModel from './buildModel';
import { Payload } from '../payload';
import { getVersionsModelName } from '../versions/getVersionsModelName';
@@ -19,9 +19,11 @@ export default function initGlobalsLocal(ctx: Payload): void {
if (global.versions) {
const versionModelName = getVersionsModelName(global);
const versionGlobalFields = buildVersionGlobalFields(global);
const versionSchema = buildSchema(
ctx.config,
buildVersionGlobalFields(global),
versionGlobalFields,
{
disableUnique: true,
draftsEnabled: true,
@@ -33,7 +35,7 @@ export default function initGlobalsLocal(ctx: Payload): void {
);
versionSchema.plugin(paginate, { useEstimatedCount: true })
.plugin(buildQueryPlugin);
.plugin(getBuildQueryPlugin({ globalSlug: global.slug, isVersionsModel: true }));
ctx.versions[global.slug] = mongoose.model(versionModelName, versionSchema) as CollectionModel;
}

View File

@@ -40,16 +40,14 @@ async function findOne<T extends Record<string, unknown>>(args: Args): Promise<T
// Retrieve and execute access
// /////////////////////////////////////
const queryToBuild: { where?: Where } = {
where: {
and: [
{
globalType: {
equals: slug,
},
const queryToBuild: Where = {
and: [
{
globalType: {
equals: slug,
},
],
},
},
],
};
let accessResult: AccessResult;
@@ -58,11 +56,15 @@ async function findOne<T extends Record<string, unknown>>(args: Args): Promise<T
accessResult = await executeAccess({ req }, globalConfig.access.read);
if (hasWhereAccessResult(accessResult)) {
queryToBuild.where.and.push(accessResult);
queryToBuild.and.push(accessResult);
}
}
const query = await Model.buildQuery(queryToBuild, locale);
const query = await Model.buildQuery({
where: queryToBuild,
req,
overrideAccess,
});
// /////////////////////////////////////
// Perform database operation
@@ -91,7 +93,8 @@ async function findOne<T extends Record<string, unknown>>(args: Args): Promise<T
entity: globalConfig,
entityType: 'global',
doc,
locale,
req,
overrideAccess,
accessResult,
});
}

View File

@@ -50,23 +50,25 @@ async function findVersionByID<T extends TypeWithVersion<T> = any>(args: Argumen
const hasWhereAccess = typeof accessResults === 'object';
const queryToBuild: { where: Where } = {
where: {
and: [
{
_id: {
equals: id,
},
const queryToBuild: Where = {
and: [
{
_id: {
equals: id,
},
],
},
},
],
};
if (hasWhereAccessResult(accessResults)) {
(queryToBuild.where.and as Where[]).push(accessResults);
queryToBuild.and.push(accessResults);
}
const query = await VersionsModel.buildQuery(queryToBuild, locale);
const query = await VersionsModel.buildQuery({
where: queryToBuild,
req,
overrideAccess,
});
// /////////////////////////////////////
// Find by ID

View File

@@ -47,7 +47,7 @@ async function findVersions<T extends TypeWithVersion<T>>(
// Access
// /////////////////////////////////////
const queryToBuild: { where?: Where } = {};
let queryToBuild: Where = {};
let useEstimatedCount = false;
if (where) {
@@ -56,7 +56,7 @@ async function findVersions<T extends TypeWithVersion<T>>(
if (Array.isArray(where.and)) and = where.and;
if (Array.isArray(where.AND)) and = where.AND;
queryToBuild.where = {
queryToBuild = {
...where,
and: [
...and,
@@ -73,18 +73,22 @@ async function findVersions<T extends TypeWithVersion<T>>(
if (hasWhereAccessResult(accessResults)) {
if (!where) {
queryToBuild.where = {
queryToBuild = {
and: [
accessResults,
],
};
} else {
(queryToBuild.where.and as Where[]).push(accessResults);
queryToBuild.and.push(accessResults);
}
}
}
const query = await VersionsModel.buildQuery(queryToBuild, locale);
const query = await VersionsModel.buildQuery({
where: queryToBuild,
req,
overrideAccess,
});
// /////////////////////////////////////
// Find

View File

@@ -62,23 +62,25 @@ async function update<TSlug extends keyof GeneratedTypes['globals']>(
// Retrieve document
// /////////////////////////////////////
const queryToBuild: { where: Where } = {
where: {
and: [
{
globalType: {
equals: slug,
},
const queryToBuild: Where = {
and: [
{
globalType: {
equals: slug,
},
],
},
},
],
};
if (hasWhereAccessResult(accessResults)) {
(queryToBuild.where.and as Where[]).push(accessResults);
queryToBuild.and.push(accessResults);
}
const query = await Model.buildQuery(queryToBuild, locale);
const query = await Model.buildQuery({
where: queryToBuild,
req,
overrideAccess,
});
// /////////////////////////////////////
// 2. Retrieve document

View File

@@ -7,6 +7,7 @@ import { CollectionModel } from '../collections/config/types';
import { getSchemaTypeOptions } from './getSchemaTypeOptions';
import { operatorMap } from './operatorMap';
import { sanitizeQueryValue } from './sanitizeFormattedValue';
import { PayloadRequest, Where } from '../types';
const validOperators = ['like', 'contains', 'in', 'all', 'not_in', 'greater_than_equal', 'greater_than', 'less_than_equal', 'less_than', 'not_equals', 'equals', 'exists', 'near'];
@@ -35,11 +36,19 @@ type SearchParam = {
}
class ParamParser {
locale: string;
collectionSlug?: string
queryHiddenFields: boolean
globalSlug?: string
rawParams: any;
isGlobalModel?: boolean
isVersionsModel?: boolean
overrideAccess: boolean
req: PayloadRequest
where: Where;
model: any;
@@ -50,12 +59,25 @@ class ParamParser {
sort: boolean;
};
constructor(model, rawParams, locale: string, queryHiddenFields?: boolean) {
constructor({
req,
collectionSlug,
globalSlug,
isGlobalModel,
isVersionsModel,
model,
where,
overrideAccess,
}) {
this.req = req;
this.collectionSlug = collectionSlug;
this.globalSlug = globalSlug;
this.isGlobalModel = isGlobalModel;
this.isVersionsModel = isVersionsModel;
this.parse = this.parse.bind(this);
this.model = model;
this.rawParams = rawParams;
this.locale = locale;
this.queryHiddenFields = queryHiddenFields;
this.where = where;
this.overrideAccess = overrideAccess;
this.query = {
searchParams: {},
sort: false,
@@ -65,14 +87,8 @@ class ParamParser {
// Entry point to the ParamParser class
async parse(): Promise<ParseType> {
if (typeof this.rawParams === 'object') {
for (const key of Object.keys(this.rawParams)) {
if (key === 'where') {
this.query.searchParams = await this.parsePathOrRelation(this.rawParams.where);
} else if (key === 'sort') {
this.query.sort = this.rawParams[key];
}
}
if (typeof this.where === 'object') {
this.query.searchParams = await this.parsePathOrRelation(this.where);
return this.query;
}
return {};
@@ -174,7 +190,7 @@ class ParamParser {
return true;
}
const localePath = `${currentPath}.${this.locale}`;
const localePath = `${currentPath}.${this.req.locale}`;
const localizedSchemaType = schema.path(localePath);
if (localizedSchemaType || operator === 'near') {
@@ -231,7 +247,7 @@ class ParamParser {
const schemaOptions = getSchemaTypeOptions(schemaType);
const formattedValue = sanitizeQueryValue(schemaType, path, operator, val);
if (!this.queryHiddenFields && (['salt', 'hash'].includes(path) || schemaType?.options?.hidden)) {
if (!this.overrideAccess && (['salt', 'hash'].includes(path) || schemaType?.options?.hidden)) {
return undefined;
}
@@ -258,7 +274,9 @@ class ParamParser {
[operator]: val,
},
},
}, this.locale);
req: this.req,
overrideAccess: this.overrideAccess,
});
const result = await SubModel.find(subQuery, subQueryOptions);
@@ -360,15 +378,46 @@ class ParamParser {
return undefined;
}
}
type GetBuildQueryPluginArgs = {
collectionSlug?: string
globalSlug?: string
isGlobalModel?: boolean
isVersionsModel?: boolean
}
export type BuildQueryArgs = {
req: PayloadRequest
where: Where
overrideAccess: boolean
}
// This plugin asynchronously builds a list of Mongoose query constraints
// which can then be used in subsequent Mongoose queries.
function buildQueryPlugin(schema) {
const modifiedSchema = schema;
async function buildQuery(rawParams, locale, queryHiddenFields = false) {
const paramParser = new ParamParser(this, rawParams, locale, queryHiddenFields);
const params = await paramParser.parse();
return params.searchParams;
}
modifiedSchema.statics.buildQuery = buildQuery;
}
export default buildQueryPlugin;
const getBuildQueryPlugin = ({
collectionSlug,
globalSlug,
isGlobalModel,
isVersionsModel,
}: GetBuildQueryPluginArgs) => {
return function buildQueryPlugin(schema) {
const modifiedSchema = schema;
async function buildQuery({ req, where, overrideAccess = false }: BuildQueryArgs) {
const paramParser = new ParamParser({
req,
collectionSlug,
globalSlug,
isGlobalModel,
isVersionsModel,
model: this,
where,
overrideAccess,
});
const params = await paramParser.parse();
return params.searchParams;
}
modifiedSchema.statics.buildQuery = buildQuery;
};
};
export default getBuildQueryPlugin;

View File

@@ -1,18 +1,18 @@
import { WhereField } from '../types';
import { WhereField, Where } from '../types';
const flattenWhereConstraints = (query): WhereField[] => {
if (!query.where && !query.and && !query.or) {
return Object.keys(query).map((key) => query[key]);
// Take a where query and flatten it to all top-level operators
const flattenWhereConstraints = (query: Where): WhereField[] => Object.entries(query).reduce((flattenedConstraints, [key, val]) => {
if ((key === 'and' || key === 'or') && Array.isArray(val)) {
return [
...flattenedConstraints,
...val.map((subVal) => flattenWhereConstraints(subVal)),
];
}
if (query.where) {
const whereResult = flattenWhereConstraints(query.where);
return Object.keys(whereResult).map((key) => whereResult[key]);
}
const nested = [...query.or || [], ...query.and || []];
if (nested.length > 0) {
return nested.flatMap((nest) => flattenWhereConstraints(nest));
}
return query;
};
return [
...flattenedConstraints,
val,
];
}, []);
export default flattenWhereConstraints;

View File

@@ -1,6 +1,6 @@
import { PaginateOptions } from 'mongoose';
import { AccessResult } from '../../config/types';
import { Where } from '../../types';
import { PayloadRequest, Where } from '../../types';
import { Payload } from '../../payload';
import { PaginatedDocs } from '../../mongoose/types';
import { Collection, CollectionModel, TypeWithID } from '../../collections/config/types';
@@ -17,7 +17,8 @@ type AggregateVersion<T> = {
type Args = {
accessResult: AccessResult
collection: Collection
locale: string
req: PayloadRequest
overrideAccess: boolean
paginationOptions?: PaginateOptions
payload: Payload
where: Where
@@ -26,7 +27,8 @@ type Args = {
export const queryDrafts = async <T extends TypeWithID>({
accessResult,
collection,
locale,
req,
overrideAccess,
payload,
paginationOptions,
where: incomingWhere,
@@ -35,21 +37,23 @@ export const queryDrafts = async <T extends TypeWithID>({
const where = appendVersionToQueryKey(incomingWhere || {});
const versionQueryToBuild: { where: Where } = {
where: {
...where,
and: [
...where?.and || [],
],
},
const versionQueryToBuild: Where = {
...where,
and: [
...where?.and || [],
],
};
if (hasWhereAccessResult(accessResult)) {
const versionAccessResult = appendVersionToQueryKey(accessResult);
versionQueryToBuild.where.and.push(versionAccessResult);
versionQueryToBuild.and.push(versionAccessResult);
}
const versionQuery = await VersionModel.buildQuery(versionQueryToBuild, locale);
const versionQuery = await VersionModel.buildQuery({
where: versionQueryToBuild,
req,
overrideAccess,
});
const aggregate = VersionModel.aggregate<AggregateVersion<T>>([
// Sort so that newest are first

View File

@@ -1,5 +1,5 @@
import { Payload } from '../../payload';
import { docHasTimestamps, Where } from '../../types';
import { docHasTimestamps, PayloadRequest, Where } from '../../types';
import { hasWhereAccessResult } from '../../auth';
import { AccessResult } from '../../config/types';
import { CollectionModel, SanitizedCollectionConfig, TypeWithID } from '../../collections/config/types';
@@ -12,7 +12,8 @@ type Arguments<T> = {
entity: SanitizedCollectionConfig | SanitizedGlobalConfig
entityType: 'collection' | 'global'
doc: T
locale: string
req: PayloadRequest
overrideAccess: boolean
accessResult: AccessResult
}
@@ -21,25 +22,24 @@ const replaceWithDraftIfAvailable = async <T extends TypeWithID>({
entity,
entityType,
doc,
locale,
req,
overrideAccess,
accessResult,
}: Arguments<T>): Promise<T> => {
const VersionModel = payload.versions[entity.slug] as CollectionModel;
const queryToBuild: { where: Where } = {
where: {
and: [
{
'version._status': {
equals: 'draft',
},
const queryToBuild: Where = {
and: [
{
'version._status': {
equals: 'draft',
},
],
},
},
],
};
if (entityType === 'collection') {
queryToBuild.where.and.push({
queryToBuild.and.push({
parent: {
equals: doc.id,
},
@@ -47,7 +47,7 @@ const replaceWithDraftIfAvailable = async <T extends TypeWithID>({
}
if (docHasTimestamps(doc)) {
queryToBuild.where.and.push({
queryToBuild.and.push({
updatedAt: {
greater_than: doc.updatedAt,
},
@@ -56,10 +56,14 @@ const replaceWithDraftIfAvailable = async <T extends TypeWithID>({
if (hasWhereAccessResult(accessResult)) {
const versionAccessResult = appendVersionToQueryKey(accessResult);
queryToBuild.where.and.push(versionAccessResult);
queryToBuild.and.push(versionAccessResult);
}
const query = await VersionModel.buildQuery(queryToBuild, locale);
const query = await VersionModel.buildQuery({
where: queryToBuild,
req,
overrideAccess,
});
let draft = await VersionModel.findOne(query, {}, {
lean: true,