chore: fixes and cleanup

This commit is contained in:
James
2022-09-11 20:07:02 -07:00
parent cd209379b2
commit ad4f7a5fff
16 changed files with 87 additions and 62 deletions

View File

@@ -201,7 +201,7 @@ export type TabsField = Omit<FieldBase, 'admin' | 'name' | 'localized'> & {
admin?: TabsAdmin
}
type TabAsField = Tab & {
export type TabAsField = Tab & {
type: 'tab'
};
@@ -370,7 +370,6 @@ export type Field =
| RowField
| CollapsibleField
| TabsField
| TabAsField
| UIField;
export type FieldAffectingData =
@@ -465,11 +464,11 @@ export function fieldHasMaxDepth(field: Field): field is FieldWithMaxDepth {
return (field.type === 'upload' || field.type === 'relationship') && typeof field.maxDepth === 'number';
}
export function fieldIsPresentationalOnly(field: Field): field is UIField {
export function fieldIsPresentationalOnly(field: Field | TabAsField): field is UIField {
return field.type === 'ui';
}
export function fieldAffectsData(field: Field): field is FieldAffectingData {
export function fieldAffectsData(field: Field | TabAsField): field is FieldAffectingData {
return 'name' in field && !fieldIsPresentationalOnly(field);
}

View File

@@ -1,12 +1,12 @@
/* eslint-disable no-param-reassign */
import { PayloadRequest } from '../../../express/types';
import { Field, fieldAffectsData, tabHasName } from '../../config/types';
import { Field, fieldAffectsData, TabAsField, tabHasName } from '../../config/types';
import { traverseFields } from './traverseFields';
type Args = {
data: Record<string, unknown>
doc: Record<string, unknown>
field: Field
field: Field | TabAsField
operation: 'create' | 'update'
req: PayloadRequest
siblingData: Record<string, unknown>

View File

@@ -1,11 +1,11 @@
import { Field } from '../../config/types';
import { Field, TabAsField } from '../../config/types';
import { promise } from './promise';
import { PayloadRequest } from '../../../express/types';
type Args = {
data: Record<string, unknown>
doc: Record<string, unknown>
fields: Field[]
fields: (Field | TabAsField)[]
operation: 'create' | 'update'
req: PayloadRequest
siblingData: Record<string, unknown>

View File

@@ -1,5 +1,5 @@
/* eslint-disable no-param-reassign */
import { Field, fieldAffectsData, tabHasName } from '../../config/types';
import { Field, fieldAffectsData, TabAsField, tabHasName } from '../../config/types';
import { PayloadRequest } from '../../../express/types';
import { traverseFields } from './traverseFields';
import richTextRelationshipPromise from '../../richText/richTextRelationshipPromise';
@@ -9,7 +9,7 @@ type Args = {
currentDepth: number
depth: number
doc: Record<string, unknown>
field: Field
field: Field | TabAsField
fieldPromises: Promise<void>[]
findMany: boolean
flattenLocales: boolean

View File

@@ -1,4 +1,4 @@
import { Field } from '../../config/types';
import { Field, TabAsField } from '../../config/types';
import { promise } from './promise';
import { PayloadRequest } from '../../../express/types';
@@ -7,7 +7,7 @@ type Args = {
depth: number
doc: Record<string, unknown>
fieldPromises: Promise<void>[]
fields: Field[]
fields: (Field | TabAsField)[]
findMany: boolean
flattenLocales: boolean
populationPromises: Promise<void>[]

View File

@@ -1,6 +1,6 @@
/* eslint-disable no-param-reassign */
import merge from 'deepmerge';
import { Field, fieldAffectsData, tabHasName } from '../../config/types';
import { Field, fieldAffectsData, TabAsField, tabHasName } from '../../config/types';
import { Operation } from '../../../types';
import { PayloadRequest } from '../../../express/types';
import getValueWithDefault from '../../getDefaultValue';
@@ -12,7 +12,7 @@ type Args = {
doc: Record<string, unknown>
docWithLocales: Record<string, unknown>
errors: { message: string, field: string }[]
field: Field
field: Field | TabAsField
id?: string | number
mergeLocaleActions: (() => void)[]
operation: Operation
@@ -62,7 +62,7 @@ export const promise = async ({
siblingData[field.name] = siblingDoc[field.name];
}
// Otherwise compute default value
// Otherwise compute default value
} else if (typeof field.defaultValue !== 'undefined') {
siblingData[field.name] = await getValueWithDefault({
value: siblingData[field.name],

View File

@@ -1,4 +1,4 @@
import { Field } from '../../config/types';
import { Field, TabAsField } from '../../config/types';
import { promise } from './promise';
import { Operation } from '../../../types';
import { PayloadRequest } from '../../../express/types';
@@ -8,7 +8,7 @@ type Args = {
doc: Record<string, unknown>
docWithLocales: Record<string, unknown>
errors: { message: string, field: string }[]
fields: Field[]
fields: (Field | TabAsField)[]
id?: string | number
mergeLocaleActions: (() => void)[]
operation: Operation

View File

@@ -1,12 +1,12 @@
/* eslint-disable no-param-reassign */
import { PayloadRequest } from '../../../express/types';
import { Field, fieldAffectsData, tabHasName, valueIsValueWithRelation } from '../../config/types';
import { Field, fieldAffectsData, TabAsField, tabHasName, valueIsValueWithRelation } from '../../config/types';
import { traverseFields } from './traverseFields';
type Args = {
data: Record<string, unknown>
doc: Record<string, unknown>
field: Field
field: Field | TabAsField
id?: string | number
operation: 'create' | 'update'
overrideAccess: boolean

View File

@@ -1,11 +1,11 @@
import { PayloadRequest } from '../../../express/types';
import { Field } from '../../config/types';
import { Field, TabAsField } from '../../config/types';
import { promise } from './promise';
type Args = {
data: Record<string, unknown>
doc: Record<string, unknown>
fields: Field[]
fields: (Field | TabAsField)[]
id?: string | number
operation: 'create' | 'update'
overrideAccess: boolean

View File

@@ -16,10 +16,11 @@ import { GraphQLJSON } from 'graphql-type-json';
import withNullableType from './withNullableType';
import formatName from '../utilities/formatName';
import combineParentName from '../utilities/combineParentName';
import { ArrayField, CodeField, DateField, EmailField, Field, fieldAffectsData, fieldIsPresentationalOnly, GroupField, NumberField, PointField, RadioField, RelationshipField, RichTextField, RowField, SelectField, TextareaField, TextField, UploadField, CollapsibleField, TabsField, CheckboxField, BlockField } from '../../fields/config/types';
import { ArrayField, CodeField, DateField, EmailField, Field, fieldAffectsData, GroupField, NumberField, PointField, RadioField, RelationshipField, RichTextField, RowField, SelectField, TextareaField, TextField, UploadField, CollapsibleField, TabsField, CheckboxField, BlockField, tabHasName } from '../../fields/config/types';
import { toWords } from '../../utilities/formatLabels';
import { Payload } from '../../index';
import { SanitizedCollectionConfig } from '../../collections/config/types';
import { groupOrTabHasRequiredSubfield } from '../../utilities/groupOrTabHasRequiredSubfield';
export const getCollectionIDType = (config: SanitizedCollectionConfig): GraphQLScalarType => {
const idField = config.fields.find((field) => fieldAffectsData(field) && field.name === 'id');
@@ -163,7 +164,7 @@ function buildMutationInputType(payload: Payload, name: string, fields: Field[],
};
},
group: (inputObjectTypeConfig: InputObjectTypeConfig, field: GroupField) => {
const requiresAtLeastOneField = field.fields.some((subField) => (!fieldIsPresentationalOnly(subField) && subField.required && !subField.localized));
const requiresAtLeastOneField = groupOrTabHasRequiredSubfield(field);
const fullName = combineParentName(parentName, field.label === false ? toWords(field.name, true) : field.label);
let type: GraphQLType = buildMutationInputType(payload, fullName, field.fields, fullName);
if (requiresAtLeastOneField) type = new GraphQLNonNull(type);
@@ -186,16 +187,30 @@ function buildMutationInputType(payload: Payload, name: string, fields: Field[],
if (addSubField) return addSubField(acc, subField);
return acc;
}, inputObjectTypeConfig),
tabs: (inputObjectTypeConfig: InputObjectTypeConfig, field: TabsField) => field.tabs.reduce((acc, tab) => {
return {
...acc,
...tab.fields.reduce((subFieldSchema, subField) => {
const addSubField = fieldToSchemaMap[subField.type];
if (addSubField) return addSubField(subFieldSchema, subField);
return subFieldSchema;
}, acc),
};
}, inputObjectTypeConfig),
tabs: (inputObjectTypeConfig: InputObjectTypeConfig, field: TabsField) => {
return field.tabs.reduce((acc, tab) => {
if (tabHasName(tab)) {
const fullName = combineParentName(parentName, toWords(tab.name, true));
const requiresAtLeastOneField = groupOrTabHasRequiredSubfield(field);
let type: GraphQLType = buildMutationInputType(payload, fullName, tab.fields, fullName);
if (requiresAtLeastOneField) type = new GraphQLNonNull(type);
return {
...inputObjectTypeConfig,
[tab.name]: { type },
};
}
return {
...acc,
...tab.fields.reduce((subFieldSchema, subField) => {
const addSubField = fieldToSchemaMap[subField.type];
if (addSubField) return addSubField(subFieldSchema, subField);
return subFieldSchema;
}, acc),
};
}, inputObjectTypeConfig);
},
};
const fieldName = formatName(name);

View File

@@ -1,7 +1,7 @@
import { GraphQLNonNull, GraphQLType } from 'graphql';
import { NonPresentationalField } from '../../fields/config/types';
import { FieldAffectingData } from '../../fields/config/types';
const withNullableType = (field: NonPresentationalField, type: GraphQLType, forceNullable = false): GraphQLType => {
const withNullableType = (field: FieldAffectingData, type: GraphQLType, forceNullable = false): GraphQLType => {
const hasReadAccessControl = field.access && field.access.read;
const condition = field.admin && field.admin.condition;

View File

@@ -14,6 +14,7 @@ import {
DateField,
EmailField,
Field,
FieldAffectingData,
fieldAffectsData, fieldIsLocalized,
fieldIsPresentationalOnly,
GroupField,
@@ -43,7 +44,7 @@ export type BuildSchemaOptions = {
type FieldSchemaGenerator = (field: Field, schema: Schema, config: SanitizedConfig, buildSchemaOptions: BuildSchemaOptions) => void;
const formatBaseSchema = (field: NonPresentationalField, buildSchemaOptions: BuildSchemaOptions) => {
const formatBaseSchema = (field: FieldAffectingData, buildSchemaOptions: BuildSchemaOptions) => {
const schema: SchemaTypeOptions<unknown> = {
unique: (!buildSchemaOptions.disableUnique && field.unique) || false,
required: false,
@@ -57,8 +58,8 @@ const formatBaseSchema = (field: NonPresentationalField, buildSchemaOptions: Bui
return schema;
};
const localizeSchema = (field: NonPresentationalField | Tab, schema, localization) => {
if (fieldIsLocalized(field) && localization && Array.isArray(localization.locales)) {
const localizeSchema = (entity: NonPresentationalField | Tab, schema, localization) => {
if (fieldIsLocalized(entity) && localization && Array.isArray(localization.locales)) {
return {
type: localization.locales.reduce((localeSchema, locale) => ({
...localeSchema,
@@ -295,17 +296,18 @@ const fieldToSchemaMap: Record<string, FieldSchemaGenerator> = {
tabs: (field: TabsField, schema: Schema, config: SanitizedConfig, buildSchemaOptions: BuildSchemaOptions): void => {
field.tabs.forEach((tab) => {
if (tabHasName(tab)) {
const formattedBaseSchema = formatBaseSchema(field, buildSchemaOptions);
const baseSchema = {
...formattedBaseSchema,
type: buildSchema(config, tab.fields, {
options: {
_id: false,
id: false,
type: buildSchema(
config,
tab.fields,
{
options: {
_id: false,
id: false,
},
disableUnique: buildSchemaOptions.disableUnique,
},
disableUnique: buildSchemaOptions.disableUnique,
}),
),
};
schema.add({
@@ -341,14 +343,10 @@ const fieldToSchemaMap: Record<string, FieldSchemaGenerator> = {
});
},
group: (field: GroupField, schema: Schema, config: SanitizedConfig, buildSchemaOptions: BuildSchemaOptions): void => {
let { required } = field;
if (field?.admin?.condition || field?.localized || field?.access?.create) required = false;
const formattedBaseSchema = formatBaseSchema(field, buildSchemaOptions);
const baseSchema = {
...formattedBaseSchema,
required: required && field.fields.some((subField) => (!fieldIsPresentationalOnly(subField) && subField.required && !subField.localized && !subField?.admin?.condition && !subField?.access?.create)),
type: buildSchema(
config,
field.fields,

View File

@@ -0,0 +1,15 @@
import { Field, fieldAffectsData, Tab } from '../fields/config/types';
export const groupOrTabHasRequiredSubfield = (entity: Field | Tab): boolean => {
if ('type' in entity && entity.type === 'group') {
return entity.fields.some((subField) => {
return (fieldAffectsData(subField) && subField.required) || groupOrTabHasRequiredSubfield(subField);
});
}
if ('fields' in entity && 'name' in entity) {
return (entity as Tab).fields.some((subField) => groupOrTabHasRequiredSubfield(subField));
}
return false;
};

View File

@@ -176,25 +176,29 @@ const TabsFields: CollectionConfig = {
label: 'Hooks Tab',
hooks: {
beforeValidate: [
({ data }) => {
({ data = {} }) => {
if (!data.hooksTab) data.hooksTab = {};
data.hooksTab.beforeValidate = true;
return data.hooksTab;
},
],
beforeChange: [
({ data }) => {
({ data = {} }) => {
if (!data.hooksTab) data.hooksTab = {};
data.hooksTab.beforeChange = true;
return data.hooksTab;
},
],
afterChange: [
({ data }) => {
({ data = {} }) => {
if (!data.hooksTab) data.hooksTab = {};
data.hooksTab.afterChange = true;
return data.hooksTab;
},
],
afterRead: [
({ data }) => {
({ data = {} }) => {
if (!data.hooksTab) data.hooksTab = {};
data.hooksTab.afterRead = true;
return data.hooksTab;
},

View File

@@ -5,7 +5,6 @@ import config from '../uploads/config';
import payload from '../../src';
import { pointDoc } from './collections/Point';
import type { ArrayField, GroupField, TabsField } from './payload-types';
import type { ArrayField, GroupField } from './payload-types';
import { arrayFieldsSlug, arrayDefaultValue, arrayDoc } from './collections/Array';
import { groupFieldsSlug, groupDefaultChild, groupDefaultValue, groupDoc } from './collections/Group';
import { defaultText } from './collections/Text';
@@ -292,7 +291,7 @@ describe('Fields', () => {
collection,
id,
locale: 'all',
}) as unknown as {localized: {en: unknown, es: unknown}};
}) as unknown as { localized: { en: unknown, es: unknown } };
expect(enDoc.localized[0].text).toStrictEqual(enText);
expect(esDoc.localized[0].text).toStrictEqual(esText);

View File

@@ -5814,11 +5814,6 @@ extract-files@^9.0.0:
resolved "https://registry.npmjs.org/extract-files/-/extract-files-9.0.0.tgz#8a7744f2437f81f5ed3250ed9f1550de902fe54a"
integrity sha512-CvdFfHkC95B4bBBk36hcEmvdR2awOdhhVUYH6S/zrVj3477zven/fJMYg7121h4T1xHZC+tetUpubpAhxwI7hQ==
"falsey@^1.0.0":
version "1.0.0"
resolved "https://registry.npmjs.org/falsey/-/falsey-1.0.0.tgz#71bdd775c24edad9f2f5c015ce8be24400bb5d7d"
integrity sha512-zMDNZ/Ipd8MY0+346CPvhzP1AsiVyNfTOayJza4reAIWf72xbkuFUDcJNxSAsQE1b9Bu0wijKb8Ngnh/a7fI5w==
fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3:
version "3.1.3"
resolved "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525"