feat: add user-defined schema and migrations (#7418)

This commit is contained in:
Samuel Denis-D'Ortun
2021-11-01 09:28:49 -04:00
committed by GitHub
parent 653d25731f
commit 25d5c30be2
16 changed files with 1365 additions and 36 deletions

View File

@@ -831,7 +831,11 @@ export default class SchemaController {
const existingFields = schema.fields;
Object.keys(submittedFields).forEach(name => {
const field = submittedFields[name];
if (existingFields[name] && field.__op !== 'Delete') {
if (
existingFields[name] &&
existingFields[name].type !== field.type &&
field.__op !== 'Delete'
) {
throw new Parse.Error(255, `Field ${name} exists, cannot update.`);
}
if (!existingFields[name] && field.__op === 'Delete') {
@@ -1057,7 +1061,12 @@ export default class SchemaController {
// object if the provided className-fieldName-type tuple is valid.
// The className must already be validated.
// If 'freeze' is true, refuse to update the schema for this field.
enforceFieldExists(className: string, fieldName: string, type: string | SchemaField) {
enforceFieldExists(
className: string,
fieldName: string,
type: string | SchemaField,
isValidation?: boolean
) {
if (fieldName.indexOf('.') > 0) {
// subdocument key (x.y) => ok if x is of type 'object'
fieldName = fieldName.split('.')[0];
@@ -1101,7 +1110,14 @@ export default class SchemaController {
)} but got ${typeToString(type)}`
);
}
return undefined;
// If type options do not change
// we can safely return
if (isValidation || JSON.stringify(expectedType) === JSON.stringify(type)) {
return undefined;
}
// Field options are may be changed
// ensure to have an update to date schema field
return this._dbAdapter.updateFieldOptions(className, fieldName, type);
}
return this._dbAdapter
@@ -1236,7 +1252,7 @@ export default class SchemaController {
// Every object has ACL implicitly.
continue;
}
promises.push(schema.enforceFieldExists(className, fieldName, expected));
promises.push(schema.enforceFieldExists(className, fieldName, expected, true));
}
const results = await Promise.all(promises);
const enforceFields = results.filter(result => !!result);