Skip to content

Commit

Permalink
fix: improve id type semantic and restrict possible types to text and…
Browse files Browse the repository at this point in the history
… number
  • Loading branch information
jeanbmar authored and DanRibbens committed Sep 9, 2021
1 parent bc2a6e1 commit 29529b2
Show file tree
Hide file tree
Showing 10 changed files with 46 additions and 55 deletions.
2 changes: 1 addition & 1 deletion demo/collections/CustomID.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ const CustomID: CollectionConfig = {
singular: 'CustomID',
plural: 'CustomIDs',
},
id: Number,
idType: 'number',
fields: [
{
name: 'name',
Expand Down
2 changes: 1 addition & 1 deletion docs/configuration/collections.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ It's often best practice to write your Collections in separate files and then im
| **`access`** | Provide access control functions to define exactly who should be able to do what with Documents in this Collection. [More](/docs/access-control/overview/#collections) |
| **`auth`** | Specify options if you would like this Collection to feature authentication. For more, consult the [Authentication](/docs/authentication/config) documentation. |
| **`upload`** | Specify options if you would like this Collection to support file uploads. For more, consult the [Uploads](/docs/upload/overview) documentation. |
| **`id`** | Set a [Mongoose-compatible type](https://mongoosejs.com/docs/schematypes.html) to replace the auto-generated id with a customizable value when creating a new record. |
| **`idType`** | Set this option to replace the auto-generated id with a customizable value when creating a new record. Supported values are `text` and `number`. |
| **`timestamps`** | Set to false to disable documents' automatically generated `createdAt` and `updatedAt` timestamps. |

*\* An asterisk denotes that a property is required.*
Expand Down
9 changes: 5 additions & 4 deletions src/admin/components/views/collections/Edit/formatFields.tsx
Original file line number Diff line number Diff line change
@@ -1,18 +1,19 @@
import { Field } from '../../../../../fields/config/types';
import { text } from '../../../../../fields/validations';
import validations from '../../../../../fields/validations';

const formatFields = (collection, isEditing) => {
let fields = [
...collection.fields,
];
if (collection.id && !isEditing) {
if (collection.idType && !isEditing) {
const defaultValidate = validations[collection.idType];
fields = [
{
name: 'id',
type: 'text',
type: collection.idType,
label: 'ID',
required: true,
validate: (val) => text(val, { required: true }),
validate: (val) => defaultValidate(val, { required: true }),
} as Field,
...fields,
];
Expand Down
6 changes: 4 additions & 2 deletions src/collections/buildSchema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,10 @@ const buildCollectionSchema = (collection: SanitizedCollectionConfig, config: Sa
collection.fields,
{ timestamps: collection.timestamps !== false, ...schemaOptions },
);
if (collection.id) {
schema.add({ _id: collection.id });

if (collection.idType) {
const idSchemaType = collection.idType === 'number' ? Number : String;
schema.add({ _id: idSchemaType });
}

schema.plugin(paginate, { useEstimatedCount: true })
Expand Down
5 changes: 4 additions & 1 deletion src/collections/config/schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,10 @@ const collectionSchema = joi.object().keys({
singular: joi.string(),
plural: joi.string(),
}),
id: joi.any(),
idType: joi.alternatives().try(
joi.string(),
joi.number(),
),
access: joi.object({
create: joi.func(),
read: joi.func(),
Expand Down
6 changes: 5 additions & 1 deletion src/collections/config/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,10 @@ export interface AuthCollectionModel extends CollectionModel {
resetPasswordExpiration: Date;
}

export type IdType =
| 'text'
| 'number';

export type HookOperationType =
| 'create'
| 'read'
Expand Down Expand Up @@ -95,7 +99,7 @@ export type CollectionConfig = {
singular?: string;
plural?: string;
};
id?: any,
idType?: IdType,
fields: Field[];
admin?: {
useAsTitle?: string;
Expand Down
24 changes: 8 additions & 16 deletions src/collections/graphql/init.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,18 +49,10 @@ function registerCollections(): void {

collection.graphQL = {};

let idType;
let idFieldType;
switch (collection.config.id) {
case Number:
idType = GraphQLInt;
idFieldType = 'number';
break;

default:
idType = GraphQLString;
idFieldType = 'text';
}
const idType = collection.config.idType === 'number'
? GraphQLInt
: GraphQLString;

const baseFields: BaseFields = {
id: {
type: new GraphQLNonNull(idType),
Expand All @@ -71,10 +63,10 @@ function registerCollections(): void {
...fields,
];

if (collection.config.id) {
if (collection.config.idType) {
whereInputFields.push({
name: 'id',
type: collection.config.id,
type: collection.config.idType,
});
}

Expand Down Expand Up @@ -122,10 +114,10 @@ function registerCollections(): void {
});
}

const mutationInputFields = collection.config.id
const mutationInputFields = collection.config.idType
? [{
name: 'id',
type: idFieldType,
type: collection.config.idType,
required: true,
}, ...fields]
: fields;
Expand Down
2 changes: 1 addition & 1 deletion src/collections/operations/create.ts
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ async function create(this: Payload, incomingArgs: Arguments): Promise<Document>
// Custom id
// /////////////////////////////////////

if (args.collection.config.id !== undefined) {
if (args.collection.config.idType) {
data = {
_id: data.id,
...data,
Expand Down
12 changes: 2 additions & 10 deletions src/graphql/schema/buildMutationInputType.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,15 +19,7 @@ import { ArrayField, Field, FieldWithSubFields, GroupField, RelationshipField, R
import { toWords } from '../../utilities/formatLabels';
import payload from '../../index';

const getCollectionIDType = (id) => {
switch (id) {
case Number:
return GraphQLInt;

default:
return GraphQLString;
}
};
const getCollectionIDType = (idType) => (idType === 'number' ? GraphQLInt : GraphQLString);

function buildMutationInputType(name: string, fields: Field[], parentName: string, forceNullable = false): GraphQLInputObjectType {
const fieldToSchemaMap = {
Expand Down Expand Up @@ -101,7 +93,7 @@ function buildMutationInputType(name: string, fields: Field[], parentName: strin
},
});
} else {
type = getCollectionIDType(payload.collections[relationTo].config.id);
type = getCollectionIDType(payload.collections[relationTo].config.idType);
}

return { type: field.hasMany ? new GraphQLList(type) : type };
Expand Down
33 changes: 15 additions & 18 deletions src/mongoose/buildSchema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -343,20 +343,17 @@ const fieldToSchemaMap = {
let schemaToReturn: { [key: string]: any } = {};

const relationTo = [].concat(field.relationTo);
const relatedCollections = relationTo.map((slug) => (
config.collections.find((collection) => collection.slug === slug)
));
const ids = relatedCollections.map(({ id }) => id);
const areIdTypesConsistent = ids.every((id) => ids[0] === id);
let idType;
if (areIdTypesConsistent) {
if (ids[0] === undefined) {
idType = Schema.Types.ObjectId;
} else {
[idType] = ids;
}
} else {
idType = Schema.Types.Mixed;
const { idType: relatedIdType } = config.collections.find(({ slug }) => slug === relationTo[0]);
let idSchemaType;
switch (relatedIdType) {
case 'text':
idSchemaType = String;
break;
case 'number':
idSchemaType = Number;
break;
default:
idSchemaType = Schema.Types.ObjectId;
}

if (field.localized) {
Expand All @@ -367,14 +364,14 @@ const fieldToSchemaMap = {
if (hasManyRelations) {
localeSchema._id = false;
localeSchema.value = {
type: idType,
type: idSchemaType,
refPath: `${field.name}.${locale}.relationTo`,
};
localeSchema.relationTo = { type: String, enum: field.relationTo };
} else {
localeSchema = {
...formatBaseSchema(field),
type: idType,
type: idSchemaType,
ref: field.relationTo,
};
}
Expand All @@ -389,7 +386,7 @@ const fieldToSchemaMap = {
} else if (hasManyRelations) {
schemaToReturn._id = false;
schemaToReturn.value = {
type: idType,
type: idSchemaType,
refPath: `${field.name}.relationTo`,
};
schemaToReturn.relationTo = { type: String, enum: field.relationTo };
Expand All @@ -398,7 +395,7 @@ const fieldToSchemaMap = {
} else {
schemaToReturn = {
...formatBaseSchema(field),
type: idType,
type: idSchemaType,
ref: field.relationTo,
};

Expand Down

0 comments on commit 29529b2

Please sign in to comment.