feat: move some stuff over to the new adapter pattern (#2880)
* chore: add jsdocs for limit * moar jsdocs * Replace find in deleteByID * (check this:) add missing locale * move findByID * Make findByID return only one document * _id => id * _id => id * Improve version types * Improve sortOrder types * move version stuff over * version stuff * fix: sort types * fix params * fix: findVersionByID generic * fix: type error for versions * remove unused value * fix: Document import * add todo * feat: updateOne to mongoose * remove unnecessary Model * more update stuff * remove unnecessary imports * remove unnecessary function arguments * fix: auth db update calls * fix: bad updateByID which made tests fail * fix: update returned docs to fix tests * fix: update from version using mongoose directly even though the Model does not exist * feat: implement deleteOne * fix: assign verificationToken only when it exists - fixes test * migrate saveVersion partly * feat: make dev:generate-graphql-schema work even without specifying extra argument * fix: this.db can be null * chore: use destructured locale where possible * chore: improve variable name * fix: SanitizedConfig type * feat: findGlobal database adapter * fix: flaky e2e test * chore: improve incorrect comment * chore: undo diffs * fix: id types * fix: id typing
This commit is contained in:
@@ -75,15 +75,12 @@ async function resetPassword(args: Arguments): Promise<Result> {
|
||||
user._verified = true;
|
||||
}
|
||||
|
||||
const { updatedDocs } = await payload.db.update({
|
||||
const doc = await payload.db.updateOne({
|
||||
collection: collectionConfig.slug,
|
||||
where: {
|
||||
id: { equals: user.id },
|
||||
},
|
||||
id: user.id,
|
||||
data: user,
|
||||
});
|
||||
|
||||
const doc = sanitizeInternalFields(updatedDocs[0]);
|
||||
|
||||
await authenticateLocalStrategy({ password: data.password, doc });
|
||||
|
||||
|
||||
@@ -24,7 +24,7 @@ async function unlock(args: Args): Promise<boolean> {
|
||||
},
|
||||
req,
|
||||
req: {
|
||||
payload,
|
||||
locale,
|
||||
},
|
||||
overrideAccess,
|
||||
} = args;
|
||||
@@ -49,6 +49,7 @@ async function unlock(args: Args): Promise<boolean> {
|
||||
collection: collectionConfig.slug,
|
||||
where: { email: { equals: data.email.toLowerCase() } },
|
||||
limit: 1,
|
||||
locale,
|
||||
});
|
||||
|
||||
const [user] = docs;
|
||||
|
||||
@@ -32,11 +32,9 @@ async function verifyEmail(args: Args): Promise<boolean> {
|
||||
if (!user) throw new APIError('Verification token is invalid.', httpStatus.BAD_REQUEST);
|
||||
if (user && user._verified === true) throw new APIError('This account has already been activated.', httpStatus.ACCEPTED);
|
||||
|
||||
await req.payload.db.update({
|
||||
await req.payload.db.updateOne({
|
||||
collection: collection.config.slug,
|
||||
where: {
|
||||
id: user.id,
|
||||
},
|
||||
data: {
|
||||
_verified: true,
|
||||
_verificationToken: undefined,
|
||||
|
||||
@@ -4,6 +4,7 @@ import { AggregatePaginateModel, IndexDefinition, IndexOptions, Model, PaginateM
|
||||
import { GraphQLInputObjectType, GraphQLNonNull, GraphQLObjectType } from 'graphql';
|
||||
import { Response } from 'express';
|
||||
import { Config as GeneratedTypes } from 'payload/generated-types';
|
||||
import { Where } from '../../types';
|
||||
import { Access, Endpoint, EntityDescription, GeneratePreviewURL } from '../../config/types';
|
||||
import { Field } from '../../fields/config/types';
|
||||
import { PayloadRequest } from '../../express/types';
|
||||
@@ -28,7 +29,7 @@ interface PassportLocalModel {
|
||||
}
|
||||
|
||||
export interface CollectionModel extends Model<any>, PaginateModel<any>, AggregatePaginateModel<any>, PassportLocalModel {
|
||||
buildQuery: (args: BuildQueryArgs) => Promise<Record<string, unknown>>
|
||||
buildQuery: (args: BuildQueryArgs) => Promise<Record<string, unknown>> // TODO: Delete this
|
||||
}
|
||||
|
||||
export interface AuthCollectionModel extends CollectionModel {
|
||||
@@ -99,13 +100,13 @@ export type AfterChangeHook<T extends TypeWithID = any> = (args: {
|
||||
export type BeforeReadHook<T extends TypeWithID = any> = (args: {
|
||||
doc: T;
|
||||
req: PayloadRequest;
|
||||
query: { [key: string]: any };
|
||||
query: Where;
|
||||
}) => any;
|
||||
|
||||
export type AfterReadHook<T extends TypeWithID = any> = (args: {
|
||||
doc: T;
|
||||
req: PayloadRequest;
|
||||
query?: { [key: string]: any };
|
||||
query?: Where;
|
||||
findMany?: boolean
|
||||
}) => any;
|
||||
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
/* eslint-disable no-param-reassign */
|
||||
import { Response } from 'express';
|
||||
import { Collection } from '../../config/types';
|
||||
import { Collection, TypeWithID } from '../../config/types';
|
||||
import { PayloadRequest } from '../../../express/types';
|
||||
import findVersionByID from '../../operations/findVersionByID';
|
||||
import type { TypeWithVersion } from '../../../versions/types';
|
||||
|
||||
export type Resolver = (
|
||||
export type Resolver<T extends TypeWithID = any> = (
|
||||
_: unknown,
|
||||
args: {
|
||||
locale?: string
|
||||
@@ -16,7 +17,7 @@ export type Resolver = (
|
||||
req: PayloadRequest,
|
||||
res: Response
|
||||
}
|
||||
) => Promise<Document>
|
||||
) => Promise<TypeWithVersion<T>>
|
||||
|
||||
export default function findVersionByIDResolver(collection: Collection): Resolver {
|
||||
return async function resolver(_, args, context) {
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import { Config as GeneratedTypes } from 'payload/generated-types';
|
||||
import { PayloadRequest } from '../../express/types';
|
||||
import sanitizeInternalFields from '../../utilities/sanitizeInternalFields';
|
||||
import { Forbidden, NotFound } from '../../errors';
|
||||
import executeAccess from '../../auth/executeAccess';
|
||||
import { BeforeOperationHook, Collection } from '../config/types';
|
||||
@@ -40,7 +39,6 @@ async function deleteByID<TSlug extends keyof GeneratedTypes['collections']>(inc
|
||||
const {
|
||||
depth,
|
||||
collection: {
|
||||
Model,
|
||||
config: collectionConfig,
|
||||
},
|
||||
id,
|
||||
@@ -80,34 +78,31 @@ async function deleteByID<TSlug extends keyof GeneratedTypes['collections']>(inc
|
||||
// Retrieve document
|
||||
// /////////////////////////////////////
|
||||
|
||||
const query = await Model.buildQuery({
|
||||
payload,
|
||||
locale: req.locale,
|
||||
const { docs } = await req.payload.db.find({
|
||||
collection: collectionConfig.slug,
|
||||
where: combineQueries({ id: { equals: id } }, accessResults),
|
||||
locale: req.locale,
|
||||
limit: 1,
|
||||
});
|
||||
|
||||
const docToDelete = await Model.findOne(query);
|
||||
const [docToDelete] = docs;
|
||||
|
||||
if (!docToDelete && !hasWhereAccess) throw new NotFound(t);
|
||||
if (!docToDelete && hasWhereAccess) throw new Forbidden(t);
|
||||
|
||||
const resultToDelete = docToDelete.toJSON({ virtuals: true });
|
||||
|
||||
await deleteAssociatedFiles({ config, collectionConfig, doc: resultToDelete, t, overrideDelete: true });
|
||||
await deleteAssociatedFiles({ config, collectionConfig, doc: docToDelete, t, overrideDelete: true });
|
||||
|
||||
// /////////////////////////////////////
|
||||
// Delete document
|
||||
// /////////////////////////////////////
|
||||
|
||||
const doc = await Model.findOneAndDelete({ _id: id });
|
||||
|
||||
let result: Document = doc.toJSON({ virtuals: true });
|
||||
let result = await req.payload.db.deleteOne({
|
||||
collection: collectionConfig.slug,
|
||||
id,
|
||||
});
|
||||
|
||||
// custom id type reset
|
||||
result.id = result._id;
|
||||
result = JSON.stringify(result);
|
||||
result = JSON.parse(result);
|
||||
result = sanitizeInternalFields(result);
|
||||
|
||||
// /////////////////////////////////////
|
||||
// Delete Preferences
|
||||
|
||||
@@ -8,6 +8,7 @@ import executeAccess from '../../auth/executeAccess';
|
||||
import replaceWithDraftIfAvailable from '../../versions/drafts/replaceWithDraftIfAvailable';
|
||||
import { afterRead } from '../../fields/hooks/afterRead';
|
||||
import { combineQueries } from '../../database/combineQueries';
|
||||
import { FindArgs } from '../../database/types';
|
||||
|
||||
export type Arguments = {
|
||||
collection: Collection
|
||||
@@ -42,14 +43,13 @@ async function findByID<T extends TypeWithID>(
|
||||
const {
|
||||
depth,
|
||||
collection: {
|
||||
Model,
|
||||
config: collectionConfig,
|
||||
},
|
||||
id,
|
||||
req,
|
||||
req: {
|
||||
t,
|
||||
payload,
|
||||
locale,
|
||||
},
|
||||
disableErrors,
|
||||
currentDepth,
|
||||
@@ -67,22 +67,25 @@ async function findByID<T extends TypeWithID>(
|
||||
// If errors are disabled, and access returns false, return null
|
||||
if (accessResult === false) return null;
|
||||
|
||||
const query = await Model.buildQuery({
|
||||
where: combineQueries({ _id: { equals: id } }, accessResult),
|
||||
payload,
|
||||
locale: req.locale,
|
||||
});
|
||||
|
||||
const findArgs: FindArgs = {
|
||||
collection: collectionConfig.slug,
|
||||
where: combineQueries({ id: { equals: id } }, accessResult),
|
||||
locale,
|
||||
limit: 1,
|
||||
};
|
||||
|
||||
// /////////////////////////////////////
|
||||
// Find by ID
|
||||
// /////////////////////////////////////
|
||||
|
||||
if (!query.$and[0]._id) throw new NotFound(t);
|
||||
if (!findArgs.where.and[0].id) throw new NotFound(t);
|
||||
|
||||
if (!req.findByID) req.findByID = {};
|
||||
|
||||
if (!req.findByID[collectionConfig.slug]) {
|
||||
const nonMemoizedFindByID = async (q) => Model.findOne(q, {}).lean();
|
||||
const nonMemoizedFindByID = async (query: FindArgs) => (await req.payload.db.find(query)).docs[0];
|
||||
|
||||
req.findByID[collectionConfig.slug] = memoize(nonMemoizedFindByID, {
|
||||
isPromise: true,
|
||||
maxSize: 100,
|
||||
@@ -92,7 +95,7 @@ async function findByID<T extends TypeWithID>(
|
||||
});
|
||||
}
|
||||
|
||||
let result = await req.findByID[collectionConfig.slug](query);
|
||||
let result = await req.findByID[collectionConfig.slug](findArgs) as T;
|
||||
|
||||
if (!result) {
|
||||
if (!disableErrors) {
|
||||
@@ -113,7 +116,6 @@ async function findByID<T extends TypeWithID>(
|
||||
|
||||
if (collectionConfig.versions?.drafts && draftEnabled) {
|
||||
result = await replaceWithDraftIfAvailable({
|
||||
payload,
|
||||
entity: collectionConfig,
|
||||
entityType: 'collection',
|
||||
doc: result,
|
||||
@@ -132,7 +134,7 @@ async function findByID<T extends TypeWithID>(
|
||||
|
||||
result = await hook({
|
||||
req,
|
||||
query,
|
||||
query: findArgs.where,
|
||||
doc: result,
|
||||
}) || result;
|
||||
}, Promise.resolve());
|
||||
@@ -160,7 +162,7 @@ async function findByID<T extends TypeWithID>(
|
||||
|
||||
result = await hook({
|
||||
req,
|
||||
query,
|
||||
query: findArgs.where,
|
||||
doc: result,
|
||||
}) || result;
|
||||
}, Promise.resolve());
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/* eslint-disable no-underscore-dangle */
|
||||
import httpStatus from 'http-status';
|
||||
import { PayloadRequest } from '../../express/types';
|
||||
import { Collection } from '../config/types';
|
||||
import { Collection, TypeWithID } from '../config/types';
|
||||
import { APIError, Forbidden, NotFound } from '../../errors';
|
||||
import executeAccess from '../../auth/executeAccess';
|
||||
import { TypeWithVersion } from '../../versions/types';
|
||||
@@ -19,7 +19,7 @@ export type Arguments = {
|
||||
depth?: number
|
||||
}
|
||||
|
||||
async function findVersionByID<T extends TypeWithVersion<T> = any>(args: Arguments): Promise<T> {
|
||||
async function findVersionByID<T extends TypeWithID = any>(args: Arguments): Promise<TypeWithVersion<T>> {
|
||||
const {
|
||||
depth,
|
||||
collection: {
|
||||
|
||||
@@ -5,11 +5,11 @@ import { Collection, TypeWithID } from '../config/types';
|
||||
import { APIError, Forbidden, NotFound } from '../../errors';
|
||||
import executeAccess from '../../auth/executeAccess';
|
||||
import { hasWhereAccessResult } from '../../auth/types';
|
||||
import sanitizeInternalFields from '../../utilities/sanitizeInternalFields';
|
||||
import { afterChange } from '../../fields/hooks/afterChange';
|
||||
import { afterRead } from '../../fields/hooks/afterRead';
|
||||
import { getLatestCollectionVersion } from '../../versions/getLatestCollectionVersion';
|
||||
import { combineQueries } from '../../database/combineQueries';
|
||||
import { FindArgs } from '../../database/types';
|
||||
|
||||
export type Arguments = {
|
||||
collection: Collection
|
||||
@@ -25,7 +25,6 @@ export type Arguments = {
|
||||
async function restoreVersion<T extends TypeWithID = any>(args: Arguments): Promise<T> {
|
||||
const {
|
||||
collection: {
|
||||
Model,
|
||||
config: collectionConfig,
|
||||
},
|
||||
id,
|
||||
@@ -50,16 +49,20 @@ async function restoreVersion<T extends TypeWithID = any>(args: Arguments): Prom
|
||||
|
||||
const VersionModel = payload.versions[collectionConfig.slug];
|
||||
|
||||
let rawVersion = await VersionModel.findOne({
|
||||
_id: id,
|
||||
|
||||
const { docs: versionDocs } = await req.payload.db.findVersions({
|
||||
collection: collectionConfig.slug,
|
||||
where: { id: { equals: id } },
|
||||
locale,
|
||||
limit: 1,
|
||||
});
|
||||
|
||||
const [rawVersion] = versionDocs;
|
||||
|
||||
if (!rawVersion) {
|
||||
throw new NotFound(t);
|
||||
}
|
||||
|
||||
rawVersion = rawVersion.toJSON({ virtuals: true });
|
||||
|
||||
const parentDocID = rawVersion.parent;
|
||||
|
||||
// /////////////////////////////////////
|
||||
@@ -73,13 +76,16 @@ async function restoreVersion<T extends TypeWithID = any>(args: Arguments): Prom
|
||||
// Retrieve document
|
||||
// /////////////////////////////////////
|
||||
|
||||
const query = await Model.buildQuery({
|
||||
const findArgs: FindArgs = {
|
||||
collection: collectionConfig.slug,
|
||||
where: combineQueries({ id: { equals: parentDocID } }, accessResults),
|
||||
payload,
|
||||
locale,
|
||||
});
|
||||
limit: 1,
|
||||
};
|
||||
|
||||
const doc = await Model.findOne(query);
|
||||
const { docs } = await req.payload.db.find(findArgs);
|
||||
|
||||
const [doc] = docs;
|
||||
|
||||
if (!doc && !hasWherePolicy) throw new NotFound(t);
|
||||
if (!doc && hasWherePolicy) throw new Forbidden(t);
|
||||
@@ -91,8 +97,7 @@ async function restoreVersion<T extends TypeWithID = any>(args: Arguments): Prom
|
||||
const prevDocWithLocales = await getLatestCollectionVersion({
|
||||
payload,
|
||||
id: parentDocID,
|
||||
query,
|
||||
Model,
|
||||
query: findArgs,
|
||||
config: collectionConfig,
|
||||
});
|
||||
|
||||
@@ -100,18 +105,12 @@ async function restoreVersion<T extends TypeWithID = any>(args: Arguments): Prom
|
||||
// Update
|
||||
// /////////////////////////////////////
|
||||
|
||||
let result = await Model.findByIdAndUpdate(
|
||||
{ _id: parentDocID },
|
||||
rawVersion.version,
|
||||
{ new: true },
|
||||
);
|
||||
let result = await req.payload.db.updateOne({
|
||||
collection: collectionConfig.slug,
|
||||
id: parentDocID,
|
||||
data: rawVersion.version,
|
||||
|
||||
result = result.toJSON({ virtuals: true });
|
||||
|
||||
// custom id type reset
|
||||
result.id = result._id;
|
||||
result = JSON.parse(JSON.stringify(result));
|
||||
result = sanitizeInternalFields(result);
|
||||
});
|
||||
|
||||
// /////////////////////////////////////
|
||||
// Save `previousDoc` as a version after restoring
|
||||
|
||||
@@ -5,7 +5,7 @@ import { Where } from '../../types';
|
||||
import { BulkOperationResult, Collection } from '../config/types';
|
||||
import sanitizeInternalFields from '../../utilities/sanitizeInternalFields';
|
||||
import executeAccess from '../../auth/executeAccess';
|
||||
import { APIError, ValidationError } from '../../errors';
|
||||
import { APIError } from '../../errors';
|
||||
import { PayloadRequest } from '../../express/types';
|
||||
import { saveVersion } from '../../versions/saveVersion';
|
||||
import { uploadFiles } from '../../uploads/uploadFiles';
|
||||
@@ -56,7 +56,6 @@ async function update<TSlug extends keyof GeneratedTypes['collections']>(
|
||||
depth,
|
||||
collection,
|
||||
collection: {
|
||||
Model,
|
||||
config: collectionConfig,
|
||||
},
|
||||
where,
|
||||
@@ -243,26 +242,13 @@ async function update<TSlug extends keyof GeneratedTypes['collections']>(
|
||||
// /////////////////////////////////////
|
||||
|
||||
if (!shouldSaveDraft) {
|
||||
try {
|
||||
result = await Model.findByIdAndUpdate(
|
||||
{ _id: id },
|
||||
result,
|
||||
{ new: true },
|
||||
);
|
||||
} catch (error) {
|
||||
// Handle uniqueness error from MongoDB
|
||||
throw error.code === 11000 && error.keyValue
|
||||
? new ValidationError([{
|
||||
message: 'Value must be unique',
|
||||
field: Object.keys(error.keyValue)[0],
|
||||
}], t)
|
||||
: error;
|
||||
result = await req.payload.db.updateOne({
|
||||
collection: collectionConfig.slug,
|
||||
locale,
|
||||
id,
|
||||
data: result,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
result = JSON.parse(JSON.stringify(result));
|
||||
result.id = result._id as string | number;
|
||||
result = sanitizeInternalFields(result);
|
||||
|
||||
// /////////////////////////////////////
|
||||
// Create version
|
||||
|
||||
@@ -1,11 +1,9 @@
|
||||
import httpStatus from 'http-status';
|
||||
import { Config as GeneratedTypes } from 'payload/generated-types';
|
||||
import { DeepPartial } from 'ts-essentials';
|
||||
import { Document } from '../../types';
|
||||
import { Collection } from '../config/types';
|
||||
import sanitizeInternalFields from '../../utilities/sanitizeInternalFields';
|
||||
import executeAccess from '../../auth/executeAccess';
|
||||
import { APIError, Forbidden, NotFound, ValidationError } from '../../errors';
|
||||
import { APIError, Forbidden, NotFound } from '../../errors';
|
||||
import { PayloadRequest } from '../../express/types';
|
||||
import { hasWhereAccessResult } from '../../auth/types';
|
||||
import { saveVersion } from '../../versions/saveVersion';
|
||||
@@ -20,6 +18,7 @@ import { deleteAssociatedFiles } from '../../uploads/deleteAssociatedFiles';
|
||||
import { unlinkTempFiles } from '../../uploads/unlinkTempFiles';
|
||||
import { generatePasswordSaltHash } from '../../auth/strategies/local/generatePasswordSaltHash';
|
||||
import { combineQueries } from '../../database/combineQueries';
|
||||
import { FindArgs } from '../../database/types';
|
||||
|
||||
export type Arguments<T extends { [field: string | number | symbol]: unknown }> = {
|
||||
collection: Collection
|
||||
@@ -57,7 +56,6 @@ async function updateByID<TSlug extends keyof GeneratedTypes['collections']>(
|
||||
depth,
|
||||
collection,
|
||||
collection: {
|
||||
Model,
|
||||
config: collectionConfig,
|
||||
},
|
||||
id,
|
||||
@@ -85,7 +83,6 @@ async function updateByID<TSlug extends keyof GeneratedTypes['collections']>(
|
||||
const { password } = data;
|
||||
const shouldSaveDraft = Boolean(draftArg && collectionConfig.versions.drafts);
|
||||
const shouldSavePassword = Boolean(password && collectionConfig.auth && !shouldSaveDraft);
|
||||
const lean = !shouldSavePassword;
|
||||
|
||||
// /////////////////////////////////////
|
||||
// Access
|
||||
@@ -98,26 +95,24 @@ async function updateByID<TSlug extends keyof GeneratedTypes['collections']>(
|
||||
// Retrieve document
|
||||
// /////////////////////////////////////
|
||||
|
||||
const query = await Model.buildQuery({
|
||||
where: combineQueries({ id: { equals: id } }, accessResults),
|
||||
payload,
|
||||
locale,
|
||||
});
|
||||
|
||||
const doc = await getLatestCollectionVersion({
|
||||
const findArgs: FindArgs = {
|
||||
collection: collectionConfig.slug,
|
||||
where: combineQueries({ id: { equals: id } }, accessResults),
|
||||
locale,
|
||||
limit: 1,
|
||||
};
|
||||
|
||||
const docWithLocales = await getLatestCollectionVersion({
|
||||
payload,
|
||||
Model,
|
||||
config: collectionConfig,
|
||||
id,
|
||||
query,
|
||||
lean,
|
||||
query: findArgs,
|
||||
});
|
||||
|
||||
if (!doc && !hasWherePolicy) throw new NotFound(t);
|
||||
if (!doc && hasWherePolicy) throw new Forbidden(t);
|
||||
if (!docWithLocales && !hasWherePolicy) throw new NotFound(t);
|
||||
if (!docWithLocales && hasWherePolicy) throw new Forbidden(t);
|
||||
|
||||
let docWithLocales: Document = JSON.stringify(lean ? doc : doc.toJSON({ virtuals: true }));
|
||||
docWithLocales = JSON.parse(docWithLocales);
|
||||
|
||||
const originalDoc = await afterRead({
|
||||
depth: 0,
|
||||
@@ -147,7 +142,7 @@ async function updateByID<TSlug extends keyof GeneratedTypes['collections']>(
|
||||
// Delete any associated files
|
||||
// /////////////////////////////////////
|
||||
|
||||
await deleteAssociatedFiles({ config, collectionConfig, files: filesToUpload, doc, t, overrideDelete: false });
|
||||
await deleteAssociatedFiles({ config, collectionConfig, files: filesToUpload, doc: docWithLocales, t, overrideDelete: false });
|
||||
|
||||
// /////////////////////////////////////
|
||||
// beforeValidate - Fields
|
||||
@@ -235,23 +230,13 @@ async function updateByID<TSlug extends keyof GeneratedTypes['collections']>(
|
||||
// /////////////////////////////////////
|
||||
|
||||
if (!shouldSaveDraft) {
|
||||
try {
|
||||
result = await Model.findByIdAndUpdate(
|
||||
{ _id: id },
|
||||
dataToUpdate,
|
||||
{ new: true },
|
||||
);
|
||||
} catch (error) {
|
||||
// Handle uniqueness error from MongoDB
|
||||
throw error.code === 11000 && error.keyValue
|
||||
? new ValidationError([{ message: 'Value must be unique', field: Object.keys(error.keyValue)[0] }], t)
|
||||
: error;
|
||||
result = await req.payload.db.updateOne({
|
||||
collection: collectionConfig.slug,
|
||||
locale,
|
||||
id,
|
||||
data: dataToUpdate,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
result = JSON.parse(JSON.stringify(result));
|
||||
result.id = result._id as string | number;
|
||||
result = sanitizeInternalFields(result);
|
||||
|
||||
// /////////////////////////////////////
|
||||
// Create version
|
||||
|
||||
@@ -25,8 +25,10 @@ import type {
|
||||
UploadField,
|
||||
} from '../fields/config/types';
|
||||
import type { TypeWithID } from '../collections/config/types';
|
||||
import type { TypeWithID as GlobalsTypeWithID } from '../globals/config/types';
|
||||
import type { Payload } from '../payload';
|
||||
import type { Document, Where } from '../types';
|
||||
import type { TypeWithVersion } from '../versions/types';
|
||||
|
||||
export interface DatabaseAdapter {
|
||||
/**
|
||||
@@ -116,12 +118,12 @@ export interface DatabaseAdapter {
|
||||
// operations
|
||||
find: <T = TypeWithID>(args: FindArgs) => Promise<PaginatedDocs<T>>;
|
||||
|
||||
// TODO: ADD findGlobal method
|
||||
findVersions: <T = TypeWithID>(args: FindVersionArgs) => Promise<PaginatedDocs<T>>;
|
||||
findGlobalVersions: <T = TypeWithID>(args: FindGlobalVersionArgs) => Promise<PaginatedDocs<T>>;
|
||||
findGlobal: FindGlobal;
|
||||
|
||||
findVersions: <T = TypeWithID>(args: FindVersionArgs) => Promise<PaginatedDocs<TypeWithVersion<T>>>;
|
||||
findGlobalVersions: <T = TypeWithID>(args: FindGlobalVersionArgs) => Promise<PaginatedDocs<TypeWithVersion<T>>>;
|
||||
findOne: FindOne;
|
||||
create: Create;
|
||||
update: Update;
|
||||
updateOne: UpdateOne;
|
||||
deleteOne: DeleteOne;
|
||||
deleteMany: DeleteMany;
|
||||
@@ -134,7 +136,7 @@ export type QueryDraftsArgs = {
|
||||
limit?: number
|
||||
pagination?: boolean
|
||||
sortProperty?: string
|
||||
sortOrder?: string
|
||||
sortOrder?: SortArgs
|
||||
locale?: string
|
||||
}
|
||||
|
||||
@@ -144,10 +146,11 @@ export type FindArgs = {
|
||||
page?: number
|
||||
skip?: number
|
||||
versions?: boolean
|
||||
/** Setting limit to 1 is equal to the previous Model.findOne(). Setting limit to 0 disables the limit */
|
||||
limit?: number
|
||||
pagination?: boolean
|
||||
sortProperty?: string
|
||||
sortOrder?: string
|
||||
sortOrder?: SortArgs
|
||||
locale?: string
|
||||
}
|
||||
|
||||
@@ -160,7 +163,7 @@ export type FindVersionArgs = {
|
||||
limit?: number
|
||||
pagination?: boolean
|
||||
sortProperty?: string
|
||||
sortOrder?: string
|
||||
sortOrder?: SortArgs
|
||||
locale?: string
|
||||
}
|
||||
|
||||
@@ -173,10 +176,19 @@ export type FindGlobalVersionArgs = {
|
||||
limit?: number
|
||||
pagination?: boolean
|
||||
sortProperty?: string
|
||||
sortOrder?: string
|
||||
sortOrder?: SortArgs
|
||||
locale?: string
|
||||
}
|
||||
|
||||
export type FindGlobalArgs = {
|
||||
slug: string
|
||||
locale?: string
|
||||
where: Where
|
||||
}
|
||||
|
||||
type FindGlobal = <T extends GlobalsTypeWithID = any>(args: FindGlobalArgs) => Promise<T>
|
||||
|
||||
|
||||
export type FindOneArgs = {
|
||||
collection: string
|
||||
where: Where
|
||||
@@ -186,6 +198,7 @@ export type FindOneArgs = {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
type FindOne = (args: FindOneArgs) => Promise<PaginatedDocs>
|
||||
|
||||
export type CreateArgs = {
|
||||
@@ -195,30 +208,18 @@ export type CreateArgs = {
|
||||
|
||||
type Create = (args: CreateArgs) => Promise<Document>
|
||||
|
||||
type UpdateArgs = {
|
||||
collection: string
|
||||
data: Record<string, unknown>
|
||||
where: Where
|
||||
draft?: boolean
|
||||
locale?: string
|
||||
}
|
||||
|
||||
type Update = (args: UpdateArgs) => Promise<Document>
|
||||
|
||||
type UpdateOneArgs = {
|
||||
export type UpdateOneArgs = {
|
||||
collection: string,
|
||||
data: Record<string, unknown>,
|
||||
where: Where,
|
||||
draft?: boolean
|
||||
id: string | number,
|
||||
locale?: string
|
||||
}
|
||||
|
||||
type UpdateOne = (args: UpdateOneArgs) => Promise<Document>
|
||||
|
||||
type DeleteOneArgs = {
|
||||
export type DeleteOneArgs = {
|
||||
collection: string,
|
||||
data: Record<string, unknown>,
|
||||
where: Where,
|
||||
id: string | number,
|
||||
}
|
||||
|
||||
type DeleteOne = (args: DeleteOneArgs) => Promise<Document>
|
||||
@@ -252,7 +253,7 @@ export type BuildSortParam = (args: {
|
||||
locale: string
|
||||
}) => {
|
||||
sortProperty: string
|
||||
sortOrder: string
|
||||
sortOrder: SortArgs
|
||||
}
|
||||
|
||||
export type PaginatedDocs<T = any> = {
|
||||
@@ -326,3 +327,5 @@ export type FieldGenerator<TSchema, TField> = {
|
||||
config: SanitizedConfig,
|
||||
options: BuildSchemaOptions,
|
||||
}
|
||||
|
||||
export type SortArgs = 'asc' | 'desc';
|
||||
|
||||
@@ -5,7 +5,7 @@ import { UploadedFile } from 'express-fileupload';
|
||||
import { Payload } from '../payload';
|
||||
import { Collection, TypeWithID } from '../collections/config/types';
|
||||
import { User } from '../auth/types';
|
||||
import { Document } from '../types';
|
||||
import { FindArgs } from '../database/types';
|
||||
|
||||
/** Express request with some Payload related context added */
|
||||
export declare type PayloadRequest<U = any> = Request & {
|
||||
@@ -46,6 +46,6 @@ export declare type PayloadRequest<U = any> = Request & {
|
||||
payloadUploadSizes?: Record<string, Buffer>;
|
||||
/** Cache of documents related to the current request */
|
||||
findByID?: {
|
||||
[slug: string]: (q: unknown) => Document;
|
||||
[slug: string]: (q: FindArgs) => Promise<TypeWithID>;
|
||||
};
|
||||
};
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import executeAccess from '../../auth/executeAccess';
|
||||
import { AccessResult } from '../../config/types';
|
||||
import sanitizeInternalFields from '../../utilities/sanitizeInternalFields';
|
||||
import replaceWithDraftIfAvailable from '../../versions/drafts/replaceWithDraftIfAvailable';
|
||||
import { afterRead } from '../../fields/hooks/afterRead';
|
||||
import { SanitizedGlobalConfig } from '../config/types';
|
||||
@@ -23,7 +22,6 @@ async function findOne<T extends Record<string, unknown>>(args: Args): Promise<T
|
||||
globalConfig,
|
||||
req,
|
||||
req: {
|
||||
payload,
|
||||
locale,
|
||||
},
|
||||
slug,
|
||||
@@ -33,8 +31,6 @@ async function findOne<T extends Record<string, unknown>>(args: Args): Promise<T
|
||||
overrideAccess = false,
|
||||
} = args;
|
||||
|
||||
const { globals: { Model } } = payload;
|
||||
|
||||
// /////////////////////////////////////
|
||||
// Retrieve and execute access
|
||||
// /////////////////////////////////////
|
||||
@@ -45,30 +41,15 @@ async function findOne<T extends Record<string, unknown>>(args: Args): Promise<T
|
||||
accessResult = await executeAccess({ req }, globalConfig.access.read);
|
||||
}
|
||||
|
||||
const query = await Model.buildQuery({
|
||||
where: combineQueries({ globalType: { equals: slug } }, accessResult),
|
||||
payload,
|
||||
locale,
|
||||
overrideAccess,
|
||||
globalSlug: slug,
|
||||
});
|
||||
|
||||
// /////////////////////////////////////
|
||||
// Perform database operation
|
||||
// /////////////////////////////////////
|
||||
|
||||
let doc = await Model.findOne(query).lean() as any;
|
||||
|
||||
if (!doc) {
|
||||
doc = {};
|
||||
} else if (doc._id) {
|
||||
doc.id = doc._id;
|
||||
delete doc._id;
|
||||
}
|
||||
|
||||
doc = JSON.stringify(doc);
|
||||
doc = JSON.parse(doc);
|
||||
doc = sanitizeInternalFields(doc);
|
||||
let doc = await req.payload.db.findGlobal({
|
||||
slug,
|
||||
locale,
|
||||
where: overrideAccess ? { globalType: { equals: slug } } : combineQueries({ globalType: { equals: slug } }, accessResult),
|
||||
});
|
||||
|
||||
// /////////////////////////////////////
|
||||
// Replace document with draft if available
|
||||
@@ -76,7 +57,6 @@ async function findOne<T extends Record<string, unknown>>(args: Args): Promise<T
|
||||
|
||||
if (globalConfig.versions?.drafts && draftEnabled) {
|
||||
doc = await replaceWithDraftIfAvailable({
|
||||
payload,
|
||||
entity: globalConfig,
|
||||
entityType: 'global',
|
||||
doc,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import type { MongooseAdapter } from '.';
|
||||
import { CreateArgs } from '../database/types';
|
||||
import { Document } from '../../types';
|
||||
import { Document } from '../types';
|
||||
|
||||
export async function create<T = unknown>(
|
||||
this: MongooseAdapter,
|
||||
@@ -16,6 +16,8 @@ export async function create<T = unknown>(
|
||||
// custom id type reset
|
||||
result.id = result._id;
|
||||
result = JSON.parse(JSON.stringify(result));
|
||||
if (verificationToken) {
|
||||
result._verificationToken = verificationToken;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
24
src/mongoose/deleteOne.ts
Normal file
24
src/mongoose/deleteOne.ts
Normal file
@@ -0,0 +1,24 @@
|
||||
import type { MongooseAdapter } from '.';
|
||||
import type { DeleteOneArgs } from '../database/types';
|
||||
import sanitizeInternalFields from '../utilities/sanitizeInternalFields';
|
||||
import { Document } from '../types';
|
||||
|
||||
export async function deleteOne<T = unknown>(
|
||||
this: MongooseAdapter,
|
||||
{ collection, id }: DeleteOneArgs,
|
||||
): Promise<T> {
|
||||
const Model = this.collections[collection];
|
||||
|
||||
const doc = await Model.findOneAndDelete({ _id: id });
|
||||
|
||||
let result: Document = doc.toJSON({ virtuals: true });
|
||||
|
||||
// custom id type reset
|
||||
result.id = result._id;
|
||||
result = JSON.stringify(result);
|
||||
result = JSON.parse(result);
|
||||
result = sanitizeInternalFields(result);
|
||||
|
||||
|
||||
return result;
|
||||
}
|
||||
33
src/mongoose/findGlobal.ts
Normal file
33
src/mongoose/findGlobal.ts
Normal file
@@ -0,0 +1,33 @@
|
||||
import type { MongooseAdapter } from '.';
|
||||
import { FindGlobalArgs } from '../database/types';
|
||||
import sanitizeInternalFields from '../utilities/sanitizeInternalFields';
|
||||
import { TypeWithID } from '../globals/config/types';
|
||||
|
||||
export async function findGlobal<T extends TypeWithID = any>(
|
||||
this: MongooseAdapter,
|
||||
{ slug, locale, where }: FindGlobalArgs,
|
||||
): Promise<T> {
|
||||
const Model = this.globals;
|
||||
|
||||
const query = await Model.buildQuery({
|
||||
where,
|
||||
payload: this.payload,
|
||||
locale,
|
||||
globalSlug: slug,
|
||||
});
|
||||
|
||||
let doc = await Model.findOne(query).lean() as any;
|
||||
|
||||
if (!doc) {
|
||||
doc = {};
|
||||
} else if (doc._id) {
|
||||
doc.id = doc._id;
|
||||
delete doc._id;
|
||||
}
|
||||
|
||||
doc = JSON.parse(JSON.stringify(doc));
|
||||
doc = sanitizeInternalFields(doc);
|
||||
|
||||
|
||||
return doc;
|
||||
}
|
||||
@@ -3,11 +3,12 @@ import { PaginatedDocs } from './types';
|
||||
import { FindGlobalVersionArgs } from '../database/types';
|
||||
import sanitizeInternalFields from '../utilities/sanitizeInternalFields';
|
||||
import flattenWhereToOperators from '../database/flattenWhereToOperators';
|
||||
import type { TypeWithVersion } from '../versions/types';
|
||||
|
||||
export async function findGlobalVersions<T = unknown>(
|
||||
this: MongooseAdapter,
|
||||
{ global, where, page, limit, sortProperty, sortOrder, locale, pagination, skip }: FindGlobalVersionArgs,
|
||||
): Promise<PaginatedDocs<T>> {
|
||||
): Promise<PaginatedDocs<TypeWithVersion<T>>> {
|
||||
const Model = this.versions[global];
|
||||
|
||||
let useEstimatedCount = false;
|
||||
|
||||
@@ -3,11 +3,12 @@ import { PaginatedDocs } from './types';
|
||||
import { FindVersionArgs } from '../database/types';
|
||||
import sanitizeInternalFields from '../utilities/sanitizeInternalFields';
|
||||
import flattenWhereToOperators from '../database/flattenWhereToOperators';
|
||||
import type { TypeWithVersion } from '../versions/types';
|
||||
|
||||
export async function findVersions<T = unknown>(
|
||||
this: MongooseAdapter,
|
||||
{ collection, where, page, limit, sortProperty, sortOrder, locale, pagination, skip }: FindVersionArgs,
|
||||
): Promise<PaginatedDocs<T>> {
|
||||
): Promise<PaginatedDocs<TypeWithVersion<T>>> {
|
||||
const Model = this.versions[collection];
|
||||
|
||||
let useEstimatedCount = false;
|
||||
|
||||
@@ -8,9 +8,12 @@ import { queryDrafts } from './queryDrafts';
|
||||
import { GlobalModel } from '../globals/config/types';
|
||||
import { find } from './find';
|
||||
import { create } from './create';
|
||||
import { updateOne } from './updateOne';
|
||||
import { deleteOne } from './deleteOne';
|
||||
import { findVersions } from './findVersions';
|
||||
import { findGlobalVersions } from './findGlobalVersions';
|
||||
import type { Payload } from '../index';
|
||||
import { findGlobal } from './findGlobal';
|
||||
|
||||
export interface Args {
|
||||
payload: Payload,
|
||||
@@ -59,7 +62,10 @@ export function mongooseAdapter({ payload, url, connectOptions }: Args): Mongoos
|
||||
queryDrafts,
|
||||
find,
|
||||
findVersions,
|
||||
findGlobal,
|
||||
findGlobalVersions,
|
||||
create,
|
||||
updateOne,
|
||||
deleteOne,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
import mongoose from 'mongoose';
|
||||
import paginate from 'mongoose-paginate-v2';
|
||||
import mongooseAggregatePaginate from 'mongoose-aggregate-paginate-v2';
|
||||
import { SanitizedConfig } from 'payload/config';
|
||||
import { buildVersionCollectionFields } from '../versions/buildCollectionFields';
|
||||
import getBuildQueryPlugin from './queries/buildQuery';
|
||||
import buildCollectionSchema from './models/buildCollectionSchema';
|
||||
@@ -12,6 +11,8 @@ import { getVersionsModelName } from '../versions/getVersionsModelName';
|
||||
import type { MongooseAdapter } from '.';
|
||||
import { buildGlobalModel } from './models/buildGlobalModel';
|
||||
import { buildVersionGlobalFields } from '../versions/buildGlobalFields';
|
||||
import type { SanitizedConfig } from '../config/types';
|
||||
|
||||
|
||||
export async function init(
|
||||
this: MongooseAdapter,
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { Config } from '../../config/types';
|
||||
import { getLocalizedSortProperty } from './getLocalizedSortProperty';
|
||||
import { Field } from '../../fields/config/types';
|
||||
import type { SortArgs } from '../../database/types';
|
||||
|
||||
type Args = {
|
||||
sort: string
|
||||
@@ -10,9 +11,9 @@ type Args = {
|
||||
locale: string
|
||||
}
|
||||
|
||||
export const buildSortParam = ({ sort, config, fields, timestamps, locale }: Args): [string, string] => {
|
||||
export const buildSortParam = ({ sort, config, fields, timestamps, locale }: Args): [string, SortArgs] => {
|
||||
let sortProperty: string;
|
||||
let sortOrder = 'desc';
|
||||
let sortOrder: SortArgs = 'desc';
|
||||
|
||||
if (!sort) {
|
||||
if (timestamps) {
|
||||
|
||||
36
src/mongoose/updateOne.ts
Normal file
36
src/mongoose/updateOne.ts
Normal file
@@ -0,0 +1,36 @@
|
||||
import { t } from 'i18next';
|
||||
import type { MongooseAdapter } from '.';
|
||||
import type { UpdateOneArgs } from '../database/types';
|
||||
import { ValidationError } from '../errors';
|
||||
import sanitizeInternalFields from '../utilities/sanitizeInternalFields';
|
||||
|
||||
export async function updateOne<T = unknown>(
|
||||
this: MongooseAdapter,
|
||||
{ collection, data, id, locale }: UpdateOneArgs,
|
||||
): Promise<T> {
|
||||
const Model = this.collections[collection];
|
||||
|
||||
let result;
|
||||
try {
|
||||
result = await Model.findByIdAndUpdate(
|
||||
{ _id: id, locale },
|
||||
data,
|
||||
{ new: true },
|
||||
);
|
||||
} catch (error) {
|
||||
// Handle uniqueness error from MongoDB
|
||||
throw error.code === 11000 && error.keyValue
|
||||
? new ValidationError([{
|
||||
message: 'Value must be unique',
|
||||
field: Object.keys(error.keyValue)[0],
|
||||
}], t)
|
||||
: error;
|
||||
}
|
||||
|
||||
result = JSON.parse(JSON.stringify(result));
|
||||
result.id = result._id as string | number;
|
||||
result = sanitizeInternalFields(result);
|
||||
|
||||
|
||||
return result;
|
||||
}
|
||||
@@ -233,7 +233,7 @@ export class BasePayload<TGeneratedTypes extends GeneratedTypes> {
|
||||
registerGraphQLSchema(this);
|
||||
}
|
||||
|
||||
if (this.db.init) {
|
||||
if (this.db?.init) {
|
||||
await this.db?.init({ config: this.config });
|
||||
}
|
||||
|
||||
|
||||
@@ -2,14 +2,14 @@ import { Payload } from '../../payload';
|
||||
import { docHasTimestamps, PayloadRequest, Where } from '../../types';
|
||||
import { hasWhereAccessResult } from '../../auth';
|
||||
import { AccessResult } from '../../config/types';
|
||||
import { CollectionModel, SanitizedCollectionConfig, TypeWithID } from '../../collections/config/types';
|
||||
import { SanitizedCollectionConfig, TypeWithID } from '../../collections/config/types';
|
||||
import sanitizeInternalFields from '../../utilities/sanitizeInternalFields';
|
||||
import { appendVersionToQueryKey } from './appendVersionToQueryKey';
|
||||
import { SanitizedGlobalConfig } from '../../globals/config/types';
|
||||
import { combineQueries } from '../../database/combineQueries';
|
||||
import { FindVersionArgs } from '../../database/types';
|
||||
|
||||
type Arguments<T> = {
|
||||
payload: Payload
|
||||
entity: SanitizedCollectionConfig | SanitizedGlobalConfig
|
||||
entityType: 'collection' | 'global'
|
||||
doc: T
|
||||
@@ -19,15 +19,12 @@ type Arguments<T> = {
|
||||
}
|
||||
|
||||
const replaceWithDraftIfAvailable = async <T extends TypeWithID>({
|
||||
payload,
|
||||
entity,
|
||||
entityType,
|
||||
doc,
|
||||
req,
|
||||
accessResult,
|
||||
}: Arguments<T>): Promise<T> => {
|
||||
const VersionModel = payload.versions[entity.slug] as CollectionModel;
|
||||
|
||||
const queryToBuild: Where = {
|
||||
and: [
|
||||
{
|
||||
@@ -60,17 +57,21 @@ const replaceWithDraftIfAvailable = async <T extends TypeWithID>({
|
||||
versionAccessResult = appendVersionToQueryKey(accessResult);
|
||||
}
|
||||
|
||||
const query = await VersionModel.buildQuery({
|
||||
where: combineQueries(queryToBuild, versionAccessResult),
|
||||
payload,
|
||||
locale: req.locale,
|
||||
globalSlug: entityType === 'global' ? entity.slug : undefined,
|
||||
});
|
||||
|
||||
let draft = await VersionModel.findOne(query, {}, {
|
||||
lean: true,
|
||||
sort: { updatedAt: 'desc' },
|
||||
});
|
||||
const findVersionArgs: FindVersionArgs = {
|
||||
locale: req.locale,
|
||||
where: combineQueries(queryToBuild, versionAccessResult),
|
||||
collection: entity.slug,
|
||||
limit: 1,
|
||||
sortProperty: 'updatedAt',
|
||||
sortOrder: 'desc',
|
||||
|
||||
};
|
||||
|
||||
const { docs: versionDocs } = await req.payload.db.findVersions<T>(findVersionArgs);
|
||||
|
||||
let draft = versionDocs[0];
|
||||
|
||||
|
||||
if (!draft) {
|
||||
return doc;
|
||||
|
||||
@@ -1,39 +1,39 @@
|
||||
import { docHasTimestamps } from '../types';
|
||||
import { Payload } from '../payload';
|
||||
import { CollectionModel, SanitizedCollectionConfig, TypeWithID } from '../collections/config/types';
|
||||
import { SanitizedCollectionConfig, TypeWithID } from '../collections/config/types';
|
||||
import { TypeWithVersion } from './types';
|
||||
import { FindArgs } from '../database/types';
|
||||
|
||||
type Args = {
|
||||
payload: Payload
|
||||
query: Record<string, unknown>
|
||||
lean?: boolean
|
||||
query: FindArgs
|
||||
id: string | number
|
||||
Model: CollectionModel
|
||||
config: SanitizedCollectionConfig
|
||||
}
|
||||
|
||||
export const getLatestCollectionVersion = async <T extends TypeWithID = any>({
|
||||
payload,
|
||||
config,
|
||||
Model,
|
||||
query,
|
||||
id,
|
||||
lean = true,
|
||||
}: Args): Promise<T> => {
|
||||
let latestVersion;
|
||||
let latestVersion: TypeWithVersion<T>;
|
||||
|
||||
if (config.versions?.drafts) {
|
||||
latestVersion = await payload.versions[config.slug].findOne({
|
||||
parent: id,
|
||||
}, {}, {
|
||||
sort: { updatedAt: 'desc' },
|
||||
lean,
|
||||
const { docs } = await payload.db.findVersions<T>({
|
||||
collection: config.slug,
|
||||
where: { parent: { equals: id } },
|
||||
sortProperty: 'updatedAt',
|
||||
sortOrder: 'desc',
|
||||
});
|
||||
[latestVersion] = docs;
|
||||
}
|
||||
|
||||
const doc = await Model.findOne(query, {}, { lean });
|
||||
const { docs } = await payload.db.find<T>(query);
|
||||
const [doc] = docs;
|
||||
|
||||
|
||||
if (!latestVersion || (docHasTimestamps(doc) && latestVersion.updatedAt < doc.updatedAt)) {
|
||||
doc.id = doc._id;
|
||||
return doc;
|
||||
}
|
||||
|
||||
|
||||
@@ -50,10 +50,22 @@ export const saveVersion = async ({
|
||||
if (autosave) {
|
||||
const query: FilterQuery<unknown> = {};
|
||||
if (collection) query.parent = id;
|
||||
const latestVersion = await VersionModel.findOne(query, {}, { sort: { updatedAt: 'desc' } });
|
||||
const { docs } = await payload.db.findVersions({
|
||||
collection: entityConfig.slug,
|
||||
limit: 1,
|
||||
where: {
|
||||
parent: {
|
||||
equals: id,
|
||||
},
|
||||
},
|
||||
sortOrder: 'desc',
|
||||
sortProperty: 'updatedAt',
|
||||
});
|
||||
const [latestVersion] = docs;
|
||||
|
||||
|
||||
// overwrite the latest version if it's set to autosave
|
||||
if (latestVersion?.autosave === true) {
|
||||
if ((latestVersion as any)?.autosave === true) {
|
||||
createNewVersion = false;
|
||||
|
||||
const data: Record<string, unknown> = {
|
||||
@@ -64,7 +76,7 @@ export const saveVersion = async ({
|
||||
|
||||
result = await VersionModel.findByIdAndUpdate(
|
||||
{
|
||||
_id: latestVersion._id,
|
||||
_id: latestVersion.id,
|
||||
},
|
||||
data,
|
||||
{ new: true, lean: true },
|
||||
|
||||
@@ -297,7 +297,7 @@ describe('admin', () => {
|
||||
await createPost();
|
||||
|
||||
await page.locator('.list-controls__toggle-columns').click();
|
||||
await wait(500); // Wait for column toggle UI, should probably use waitForSelector
|
||||
await page.waitForSelector('.column-selector'); // Waiting for column toggle UI
|
||||
|
||||
const numberOfColumns = await page.locator(columnCountLocator).count();
|
||||
await expect(await page.locator('table >> thead >> tr >> th:nth-child(2)')).toHaveText('ID');
|
||||
@@ -306,13 +306,13 @@ describe('admin', () => {
|
||||
|
||||
// Remove ID column
|
||||
await idButton.click();
|
||||
await wait(100);
|
||||
await wait(200);
|
||||
await expect(await page.locator(columnCountLocator)).toHaveCount(numberOfColumns - 1);
|
||||
await expect(await page.locator('table >> thead >> tr >> th:nth-child(2)')).toHaveText('Number');
|
||||
|
||||
// Add back ID column
|
||||
await idButton.click();
|
||||
await wait(100);
|
||||
await wait(200);
|
||||
await expect(await page.locator(columnCountLocator)).toHaveCount(numberOfColumns);
|
||||
await expect(await page.locator('table >> thead >> tr >> th:nth-child(2)')).toHaveText('ID');
|
||||
});
|
||||
|
||||
@@ -4,9 +4,24 @@ import { generateGraphQLSchema } from '../src/bin/generateGraphQLSchema';
|
||||
|
||||
const [testConfigDir] = process.argv.slice(2);
|
||||
|
||||
const testDir = path.resolve(__dirname, testConfigDir);
|
||||
let testDir;
|
||||
if (testConfigDir) {
|
||||
testDir = path.resolve(__dirname, testConfigDir);
|
||||
setPaths(testDir);
|
||||
generateGraphQLSchema();
|
||||
} else {
|
||||
// Generate graphql schema for entire directory
|
||||
testDir = __dirname;
|
||||
|
||||
fs.readdirSync(__dirname, { withFileTypes: true })
|
||||
.filter((f) => f.isDirectory())
|
||||
.forEach((dir) => {
|
||||
const suiteDir = path.resolve(testDir, dir.name);
|
||||
const configFound = setPaths(suiteDir);
|
||||
if (configFound) generateGraphQLSchema();
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
// Set config path and TS output path using test dir
|
||||
function setPaths(dir) {
|
||||
|
||||
Reference in New Issue
Block a user