chore: normalize payload collections and globals outside db adapter

This commit is contained in:
Dan Ribbens
2023-06-15 16:50:11 -04:00
parent 6aabdd05be
commit 504f5190d5
6 changed files with 180 additions and 159 deletions

View File

@@ -11,7 +11,12 @@ import { Auth, IncomingAuthType, User } from '../../auth/types';
import { IncomingUploadType, Upload } from '../../uploads/types';
import { IncomingCollectionVersions, SanitizedCollectionVersions } from '../../versions/types';
import { BuildQueryArgs } from '../../mongoose/queries/buildQuery';
import { CustomPreviewButtonProps, CustomPublishButtonProps, CustomSaveButtonProps, CustomSaveDraftButtonProps } from '../../admin/components/elements/types';
import {
CustomPreviewButtonProps,
CustomPublishButtonProps,
CustomSaveButtonProps,
CustomSaveDraftButtonProps,
} from '../../admin/components/elements/types';
import type { Props as ListProps } from '../../admin/components/views/collections/List/types';
import type { Props as EditProps } from '../../admin/components/views/collections/Edit/types';
@@ -354,7 +359,7 @@ export interface SanitizedCollectionConfig extends Omit<DeepRequired<CollectionC
}
export type Collection = {
Model: CollectionModel;
Model?: CollectionModel;
config: SanitizedCollectionConfig;
graphQL?: {
type: GraphQLObjectType

View File

@@ -7,7 +7,12 @@ import { PayloadRequest } from '../../express/types';
import { Access, Endpoint, EntityDescription, GeneratePreviewURL } from '../../config/types';
import { Field } from '../../fields/config/types';
import { IncomingGlobalVersions, SanitizedGlobalVersions } from '../../versions/types';
import { CustomSaveButtonProps, CustomSaveDraftButtonProps, CustomPublishButtonProps, CustomPreviewButtonProps } from '../../admin/components/elements/types';
import {
CustomPreviewButtonProps,
CustomPublishButtonProps,
CustomSaveButtonProps,
CustomSaveDraftButtonProps,
} from '../../admin/components/elements/types';
export type TypeWithID = {
id: string | number
@@ -143,7 +148,7 @@ export interface SanitizedGlobalConfig extends Omit<DeepRequired<GlobalConfig>,
}
export type Globals = {
Model: GlobalModel
Model?: GlobalModel
config: SanitizedGlobalConfig[]
graphQL?: {
[slug: string]: {

View File

@@ -1,5 +1,5 @@
/* eslint-disable no-param-reassign */
import { GraphQLNonNull, GraphQLBoolean, GraphQLInt, GraphQLString } from 'graphql';
import { GraphQLBoolean, GraphQLInt, GraphQLNonNull, GraphQLString } from 'graphql';
import { singular } from 'pluralize';
import formatName from '../../graphql/utilities/formatName';
import { buildVersionGlobalFields } from '../../versions/buildGlobalFields';
@@ -20,138 +20,136 @@ import { buildPolicyType } from '../../graphql/schema/buildPoliciesType';
import { docAccessResolver } from './resolvers/docAccess';
function initGlobalsGraphQL(payload: Payload): void {
if (payload.config.globals) {
Object.keys(payload.globals.config).forEach((slug) => {
const global: SanitizedGlobalConfig = payload.globals.config[slug];
const {
Object.keys(payload.globals.config).forEach((slug) => {
const global: SanitizedGlobalConfig = payload.globals.config[slug];
const {
fields,
versions,
} = global;
const formattedName = global.graphQL?.name ? global.graphQL.name : singular(toWords(global.slug, true));
const forceNullableObjectType = Boolean(versions?.drafts);
if (!payload.globals.graphQL) payload.globals.graphQL = {};
payload.globals.graphQL[slug] = {
type: buildObjectType({
payload,
name: formattedName,
parentName: formattedName,
fields,
versions,
} = global;
forceNullable: forceNullableObjectType,
}),
mutationInputType: new GraphQLNonNull(buildMutationInputType(
payload,
formattedName,
fields,
formattedName,
)),
};
const formattedName = global.graphQL?.name ? global.graphQL.name : singular(toWords(global.slug, true));
payload.Query.fields[formattedName] = {
type: payload.globals.graphQL[slug].type,
args: {
draft: { type: GraphQLBoolean },
...(payload.config.localization ? {
locale: { type: payload.types.localeInputType },
fallbackLocale: { type: payload.types.fallbackLocaleInputType },
} : {}),
},
resolve: findOneResolver(global),
};
const forceNullableObjectType = Boolean(versions?.drafts);
payload.Mutation.fields[`update${formattedName}`] = {
type: payload.globals.graphQL[slug].type,
args: {
data: { type: payload.globals.graphQL[slug].mutationInputType },
draft: { type: GraphQLBoolean },
...(payload.config.localization ? {
locale: { type: payload.types.localeInputType },
} : {}),
},
resolve: updateResolver(global),
};
if (!payload.globals.graphQL) payload.globals.graphQL = {};
payload.Query.fields[`docAccess${formattedName}`] = {
type: buildPolicyType({
typeSuffix: 'DocAccess',
entity: global,
type: 'global',
scope: 'docAccess',
}),
resolve: docAccessResolver(global),
};
payload.globals.graphQL[slug] = {
type: buildObjectType({
payload,
name: formattedName,
parentName: formattedName,
fields,
forceNullable: forceNullableObjectType,
}),
mutationInputType: new GraphQLNonNull(buildMutationInputType(
payload,
formattedName,
fields,
formattedName,
)),
};
if (global.versions) {
const versionGlobalFields: Field[] = [
...buildVersionGlobalFields(global),
{
name: 'id',
type: 'text',
},
{
name: 'createdAt',
label: 'Created At',
type: 'date',
},
{
name: 'updatedAt',
label: 'Updated At',
type: 'date',
},
];
payload.Query.fields[formattedName] = {
type: payload.globals.graphQL[slug].type,
payload.globals.graphQL[slug].versionType = buildObjectType({
payload,
name: `${formattedName}Version`,
parentName: `${formattedName}Version`,
fields: versionGlobalFields,
forceNullable: forceNullableObjectType,
});
payload.Query.fields[`version${formatName(formattedName)}`] = {
type: payload.globals.graphQL[slug].versionType,
args: {
draft: { type: GraphQLBoolean },
id: { type: GraphQLString },
...(payload.config.localization ? {
locale: { type: payload.types.localeInputType },
fallbackLocale: { type: payload.types.fallbackLocaleInputType },
} : {}),
},
resolve: findOneResolver(global),
resolve: findVersionByIDResolver(global),
};
payload.Mutation.fields[`update${formattedName}`] = {
type: payload.globals.graphQL[slug].type,
payload.Query.fields[`versions${formattedName}`] = {
type: buildPaginatedListType(`versions${formatName(formattedName)}`, payload.globals.graphQL[slug].versionType),
args: {
data: { type: payload.globals.graphQL[slug].mutationInputType },
draft: { type: GraphQLBoolean },
where: {
type: buildWhereInputType(
`versions${formattedName}`,
versionGlobalFields,
`versions${formattedName}`,
),
},
...(payload.config.localization ? {
locale: { type: payload.types.localeInputType },
fallbackLocale: { type: payload.types.fallbackLocaleInputType },
} : {}),
page: { type: GraphQLInt },
limit: { type: GraphQLInt },
sort: { type: GraphQLString },
},
resolve: updateResolver(global),
resolve: findVersionsResolver(global),
};
payload.Query.fields[`docAccess${formattedName}`] = {
type: buildPolicyType({
typeSuffix: 'DocAccess',
entity: global,
type: 'global',
scope: 'docAccess',
}),
resolve: docAccessResolver(global),
payload.Mutation.fields[`restoreVersion${formatName(formattedName)}`] = {
type: payload.globals.graphQL[slug].type,
args: {
id: { type: GraphQLString },
},
resolve: restoreVersionResolver(global),
};
if (global.versions) {
const versionGlobalFields: Field[] = [
...buildVersionGlobalFields(global),
{
name: 'id',
type: 'text',
},
{
name: 'createdAt',
label: 'Created At',
type: 'date',
},
{
name: 'updatedAt',
label: 'Updated At',
type: 'date',
},
];
payload.globals.graphQL[slug].versionType = buildObjectType({
payload,
name: `${formattedName}Version`,
parentName: `${formattedName}Version`,
fields: versionGlobalFields,
forceNullable: forceNullableObjectType,
});
payload.Query.fields[`version${formatName(formattedName)}`] = {
type: payload.globals.graphQL[slug].versionType,
args: {
id: { type: GraphQLString },
...(payload.config.localization ? {
locale: { type: payload.types.localeInputType },
fallbackLocale: { type: payload.types.fallbackLocaleInputType },
} : {}),
},
resolve: findVersionByIDResolver(global),
};
payload.Query.fields[`versions${formattedName}`] = {
type: buildPaginatedListType(`versions${formatName(formattedName)}`, payload.globals.graphQL[slug].versionType),
args: {
where: {
type: buildWhereInputType(
`versions${formattedName}`,
versionGlobalFields,
`versions${formattedName}`,
),
},
...(payload.config.localization ? {
locale: { type: payload.types.localeInputType },
fallbackLocale: { type: payload.types.fallbackLocaleInputType },
} : {}),
page: { type: GraphQLInt },
limit: { type: GraphQLInt },
sort: { type: GraphQLString },
},
resolve: findVersionsResolver(global),
};
payload.Mutation.fields[`restoreVersion${formatName(formattedName)}`] = {
type: payload.globals.graphQL[slug].type,
args: {
id: { type: GraphQLString },
},
resolve: restoreVersionResolver(global),
};
}
});
}
}
});
}
export default initGlobalsGraphQL;

View File

@@ -41,16 +41,23 @@ export async function init(
if (collection.indexes) {
collection.indexes.forEach((index) => {
// prefix 'version.' to each field in the index
const versionIndex = { fields: {}, options: index.options };
Object.entries(index.fields).forEach(([key, value]) => {
versionIndex.fields[`version.${key}`] = value;
});
const versionIndex = {
fields: {},
options: index.options,
};
Object.entries(index.fields)
.forEach(([key, value]) => {
versionIndex.fields[`version.${key}`] = value;
});
versionSchema.index(versionIndex.fields, versionIndex.options);
});
}
versionSchema.plugin(paginate, { useEstimatedCount: true })
.plugin(getBuildQueryPlugin({ collectionSlug: collection.slug, versionsFields: versionCollectionFields }));
.plugin(getBuildQueryPlugin({
collectionSlug: collection.slug,
versionsFields: versionCollectionFields,
}));
if (collection.versions?.drafts) {
versionSchema.plugin(mongooseAggregatePaginate);
@@ -70,43 +77,38 @@ export async function init(
};
});
if (payload.config.globals) {
const model = buildGlobalModel(payload.config);
this.globals = model;
const model = buildGlobalModel(payload.config);
this.globals = model;
payload.globals = {
Model: model,
config: payload.config.globals,
};
payload.globals.Model = model;
payload.config.globals.forEach((global) => {
if (global.versions) {
const versionModelName = getVersionsModelName(global);
payload.config.globals.forEach((global) => {
if (global.versions) {
const versionModelName = getVersionsModelName(global);
const versionGlobalFields = buildVersionGlobalFields(global);
const versionGlobalFields = buildVersionGlobalFields(global);
const versionSchema = buildSchema(
payload.config,
versionGlobalFields,
{
indexSortableFields: payload.config.indexSortableFields,
disableUnique: true,
draftsEnabled: true,
options: {
timestamps: false,
minimize: false,
},
const versionSchema = buildSchema(
payload.config,
versionGlobalFields,
{
indexSortableFields: payload.config.indexSortableFields,
disableUnique: true,
draftsEnabled: true,
options: {
timestamps: false,
minimize: false,
},
);
},
);
versionSchema.plugin(paginate, { useEstimatedCount: true })
.plugin(getBuildQueryPlugin({ versionsFields: versionGlobalFields }));
versionSchema.plugin(paginate, { useEstimatedCount: true })
.plugin(getBuildQueryPlugin({ versionsFields: versionGlobalFields }));
const versionsModel = mongoose.model(versionModelName, versionSchema) as CollectionModel;
this.versions[global.slug] = versionsModel;
const versionsModel = mongoose.model(versionModelName, versionSchema) as CollectionModel;
this.versions[global.slug] = versionsModel;
payload.versions[global.slug] = versionsModel;
}
});
}
payload.versions[global.slug] = versionsModel;
}
});
}

View File

@@ -194,6 +194,15 @@ export class BasePayload<TGeneratedTypes extends GeneratedTypes> {
this.config = await loadConfig(this.logger);
}
this.globals = {
config: this.config.globals,
};
this.config.collections.forEach((collection) => {
this.collections[collection.slug] = {
config: collection,
};
});
// THIS BLOCK IS TEMPORARY UNTIL 2.0.0
// We automatically add the Mongoose adapter
// if there is no defined database adapter
@@ -209,7 +218,9 @@ export class BasePayload<TGeneratedTypes extends GeneratedTypes> {
}
this.db = this.config.db;
this.mongoMemoryServer = await this.db.connect({ payload: this, config: this.config });
if (this.db?.connect) {
this.mongoMemoryServer = await this.db.connect({ payload: this, config: this.config });
}
// Configure email service
const emailOptions = options.email ? { ...(options.email) } : this.config.email;
@@ -221,12 +232,13 @@ export class BasePayload<TGeneratedTypes extends GeneratedTypes> {
this.email = buildEmail(this.emailOptions, this.logger);
this.sendEmail = sendEmail.bind(this);
await this.db.init({ payload: this, config: this.config });
if (!this.config.graphQL.disable) {
registerGraphQLSchema(this);
}
if (this.db.init) {
await this.db?.init({ payload: this, config: this.config });
}
this.preferences = { Model: PreferencesModel };
serverInitTelemetry(this);

View File

@@ -861,7 +861,7 @@ type User {
id: String
updatedAt: DateTime
createdAt: DateTime
email: EmailAddress
email: EmailAddress!
resetPasswordToken: String
resetPasswordExpiration: DateTime
salt: String
@@ -929,7 +929,6 @@ input User_email_operator {
in: [EmailAddress]
not_in: [EmailAddress]
all: [EmailAddress]
exists: Boolean
}
input User_id_operator {
@@ -1855,7 +1854,7 @@ input mutationCollection2Update_NestedGroup_MetaInput {
input mutationUserInput {
updatedAt: String
createdAt: String
email: String
email: String!
resetPasswordToken: String
resetPasswordExpiration: String
salt: String