Add and test logic for adding fields to the DB
This commit is contained in:
@@ -494,6 +494,7 @@ ExportAdapter.prototype.smartFind = function(coll, where, options) {
|
||||
|
||||
var index = {};
|
||||
index[key] = '2d';
|
||||
//TODO: condiser moving index creation logic into Schema.js
|
||||
return coll.createIndex(index).then(() => {
|
||||
// Retry, but just once.
|
||||
return coll.find(where, options).toArray();
|
||||
|
||||
34
Schema.js
34
Schema.js
@@ -137,7 +137,7 @@ function schemaAPITypeToMongoFieldType(type) {
|
||||
return { error: "invalid JSON", code: Parse.Error.INVALID_JSON };
|
||||
}
|
||||
switch (type.type) {
|
||||
default : return { error: 'invalid field type: ' + type.type };
|
||||
default: return { error: 'invalid field type: ' + type.type };
|
||||
case 'Number': return { result: 'number' };
|
||||
case 'String': return { result: 'string' };
|
||||
case 'Boolean': return { result: 'boolean' };
|
||||
@@ -241,14 +241,38 @@ Schema.prototype.addClassIfNotExists = function(className, fields) {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
return this.collection.insertOne({
|
||||
var mongoObject = {
|
||||
_id: className,
|
||||
objectId: 'string',
|
||||
updatedAt: 'string',
|
||||
createdAt: 'string',
|
||||
})
|
||||
};
|
||||
for (fieldName in defaultColumns[className]) {
|
||||
validatedField = schemaAPITypeToMongoFieldType(defaultColumns[className][fieldName]);
|
||||
if (validatedField.code) {
|
||||
return Promise.reject(validatedField);
|
||||
}
|
||||
mongoObject[fieldName] = validatedField.result;
|
||||
}
|
||||
|
||||
for (fieldName in fields) {
|
||||
validatedField = schemaAPITypeToMongoFieldType(fields[fieldName]);
|
||||
if (validatedField.code) {
|
||||
return Promise.reject(validatedField);
|
||||
}
|
||||
mongoObject[fieldName] = validatedField.result;
|
||||
}
|
||||
|
||||
var geoPoints = Object.keys(mongoObject).filter(key => mongoObject[key] === 'geopoint');
|
||||
|
||||
if (geoPoints.length > 1) {
|
||||
return Promise.reject({
|
||||
code: Parse.Error.INCORRECT_TYPE,
|
||||
error: 'currently, only one GeoPoint field may exist in an object. Adding ' + geoPoints[1] + ' when ' + geoPoints[0] + ' already exists.',
|
||||
});
|
||||
}
|
||||
|
||||
return this.collection.insertOne(mongoObject)
|
||||
.then(result => result.ops[0])
|
||||
.catch(error => {
|
||||
if (error.code === 11000) { //Mongo's duplicate key error
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
// These tests check that the Schema operates correctly.
|
||||
var Config = require('../Config');
|
||||
var Schema = require('../Schema');
|
||||
var dd = require('deep-diff');
|
||||
|
||||
var config = new Config('test');
|
||||
|
||||
@@ -142,7 +143,8 @@ describe('Schema', () => {
|
||||
_id: 'NewClass',
|
||||
objectId: 'string',
|
||||
updatedAt: 'string',
|
||||
createdAt: 'string'
|
||||
createdAt: 'string',
|
||||
foo: 'string',
|
||||
})
|
||||
done();
|
||||
});
|
||||
@@ -183,7 +185,8 @@ describe('Schema', () => {
|
||||
_id: 'NewClass',
|
||||
objectId: 'string',
|
||||
updatedAt: 'string',
|
||||
createdAt: 'string'
|
||||
createdAt: 'string',
|
||||
foo: 'string',
|
||||
});
|
||||
});
|
||||
Promise.all([p1,p2])
|
||||
@@ -229,4 +232,136 @@ describe('Schema', () => {
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('refuses to add fields with invalid types', done => {
|
||||
config.database.loadSchema()
|
||||
.then(schema => schema.addClassIfNotExists('NewClass', {
|
||||
foo: {type: 7}
|
||||
}))
|
||||
.catch(error => {
|
||||
expect(error.code).toEqual(Parse.Error.INVALID_JSON);
|
||||
expect(error.error).toEqual('invalid JSON');
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('refuses to add fields with invalid pointer types', done => {
|
||||
config.database.loadSchema()
|
||||
.then(schema => schema.addClassIfNotExists('NewClass', {
|
||||
foo: {type: 'Pointer'},
|
||||
}))
|
||||
.catch(error => {
|
||||
expect(error.code).toEqual(135);
|
||||
expect(error.error).toEqual('type Pointer needs a class name');
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('refuses to add fields with invalid pointer target', done => {
|
||||
config.database.loadSchema()
|
||||
.then(schema => schema.addClassIfNotExists('NewClass', {
|
||||
foo: {type: 'Pointer', targetClass: 7},
|
||||
}))
|
||||
.catch(error => {
|
||||
expect(error.code).toEqual(Parse.Error.INVALID_JSON);
|
||||
expect(error.error).toEqual('invalid JSON');
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('refuses to add fields with invalid Relation type', done => {
|
||||
config.database.loadSchema()
|
||||
.then(schema => schema.addClassIfNotExists('NewClass', {
|
||||
foo: {type: 'Relation', uselessKey: 7},
|
||||
}))
|
||||
.catch(error => {
|
||||
expect(error.code).toEqual(135);
|
||||
expect(error.error).toEqual('type Relation needs a class name');
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('refuses to add fields with invalid relation target', done => {
|
||||
config.database.loadSchema()
|
||||
.then(schema => schema.addClassIfNotExists('NewClass', {
|
||||
foo: {type: 'Relation', targetClass: 7},
|
||||
}))
|
||||
.catch(error => {
|
||||
expect(error.code).toEqual(Parse.Error.INVALID_JSON);
|
||||
expect(error.error).toEqual('invalid JSON');
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('refuses to add fields with uncreatable pointer target class', done => {
|
||||
config.database.loadSchema()
|
||||
.then(schema => schema.addClassIfNotExists('NewClass', {
|
||||
foo: {type: 'Pointer', targetClass: 'not a valid class name'},
|
||||
}))
|
||||
.catch(error => {
|
||||
expect(error.code).toEqual(Parse.Error.INVALID_CLASS_NAME);
|
||||
expect(error.error).toEqual('Invalid classname: not a valid class name, classnames can only have alphanumeric characters and _, and must start with an alpha character ');
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('refuses to add fields with uncreatable relation target class', done => {
|
||||
config.database.loadSchema()
|
||||
.then(schema => schema.addClassIfNotExists('NewClass', {
|
||||
foo: {type: 'Relation', targetClass: 'not a valid class name'},
|
||||
}))
|
||||
.catch(error => {
|
||||
expect(error.code).toEqual(Parse.Error.INVALID_CLASS_NAME);
|
||||
expect(error.error).toEqual('Invalid classname: not a valid class name, classnames can only have alphanumeric characters and _, and must start with an alpha character ');
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('will create classes', done => {
|
||||
config.database.loadSchema()
|
||||
.then(schema => schema.addClassIfNotExists('NewClass', {
|
||||
aNumber: {type: 'Number'},
|
||||
aString: {type: 'String'},
|
||||
aBool: {type: 'Boolean'},
|
||||
aDate: {type: 'Date'},
|
||||
aObject: {type: 'Object'},
|
||||
aArray: {type: 'Array'},
|
||||
aGeoPoint: {type: 'GeoPoint'},
|
||||
aFile: {type: 'File'},
|
||||
aPointer: {type: 'Pointer', targetClass: 'ThisClassDoesNotExistYet'},
|
||||
aRelation: {type: 'Relation', targetClass: 'NewClass'},
|
||||
}))
|
||||
.then(mongoObj => {
|
||||
expect(mongoObj).toEqual({
|
||||
_id: 'NewClass',
|
||||
objectId: 'string',
|
||||
createdAt: 'string',
|
||||
updatedAt: 'string',
|
||||
aNumber: 'number',
|
||||
aString: 'string',
|
||||
aBool: 'boolean',
|
||||
aDate: 'date',
|
||||
aObject: 'object',
|
||||
aArray: 'array',
|
||||
aGeoPoint: 'geopoint',
|
||||
aFile: 'file',
|
||||
aPointer: '*ThisClassDoesNotExistYet',
|
||||
aRelation: 'relation<NewClass>',
|
||||
});
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('refuses to create two geopoints', done => {
|
||||
config.database.loadSchema()
|
||||
.then(schema => schema.addClassIfNotExists('NewClass', {
|
||||
geo1: {type: 'GeoPoint'},
|
||||
geo2: {type: 'GeoPoint'},
|
||||
}))
|
||||
.catch(error => {
|
||||
expect(error.code).toEqual(Parse.Error.INCORRECT_TYPE);
|
||||
expect(error.error).toEqual('currently, only one GeoPoint field may exist in an object. Adding geo2 when geo1 already exists.');
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user