Update dependencies to enable Greenkeeper 🌴 (#3940)
* chore(package): update dependencies * docs(readme): add Greenkeeper badge * Fix indent issues with eslint 4.0 see http://eslint.org/docs/user-guide/migrating-to-4.0.0\#-the-indent-rule-is-more-strict
This commit is contained in:
committed by
Arthur Cinader
parent
16954c2f74
commit
e94991b368
@@ -129,11 +129,11 @@ OAuth.nonce = function(){
|
||||
}
|
||||
|
||||
OAuth.buildParameterString = function(obj){
|
||||
// Sort keys and encode values
|
||||
// Sort keys and encode values
|
||||
if (obj) {
|
||||
var keys = Object.keys(obj).sort();
|
||||
|
||||
// Map key=value, join them by &
|
||||
// Map key=value, join them by &
|
||||
return keys.map(function(key){
|
||||
return key + "=" + OAuth.encode(obj[key]);
|
||||
}).join("&");
|
||||
@@ -161,7 +161,7 @@ OAuth.signature = function(text, key){
|
||||
OAuth.signRequest = function(request, oauth_parameters, consumer_secret, auth_token_secret){
|
||||
oauth_parameters = oauth_parameters || {};
|
||||
|
||||
// Set default values
|
||||
// Set default values
|
||||
if (!oauth_parameters.oauth_nonce) {
|
||||
oauth_parameters.oauth_nonce = OAuth.nonce();
|
||||
}
|
||||
@@ -178,12 +178,12 @@ OAuth.signRequest = function(request, oauth_parameters, consumer_secret, auth_to
|
||||
if(!auth_token_secret){
|
||||
auth_token_secret = "";
|
||||
}
|
||||
// Force GET method if unset
|
||||
// Force GET method if unset
|
||||
if (!request.method) {
|
||||
request.method = "GET"
|
||||
}
|
||||
|
||||
// Collect all the parameters in one signatureParameters object
|
||||
// Collect all the parameters in one signatureParameters object
|
||||
var signatureParams = {};
|
||||
var parametersToMerge = [request.params, request.body, oauth_parameters];
|
||||
for(var i in parametersToMerge) {
|
||||
@@ -193,25 +193,25 @@ OAuth.signRequest = function(request, oauth_parameters, consumer_secret, auth_to
|
||||
}
|
||||
}
|
||||
|
||||
// Create a string based on the parameters
|
||||
// Create a string based on the parameters
|
||||
var parameterString = OAuth.buildParameterString(signatureParams);
|
||||
|
||||
// Build the signature string
|
||||
// Build the signature string
|
||||
var url = "https://" + request.host + "" + request.path;
|
||||
|
||||
var signatureString = OAuth.buildSignatureString(request.method, url, parameterString);
|
||||
// Hash the signature string
|
||||
// Hash the signature string
|
||||
var signatureKey = [OAuth.encode(consumer_secret), OAuth.encode(auth_token_secret)].join("&");
|
||||
|
||||
var signature = OAuth.signature(signatureString, signatureKey);
|
||||
|
||||
// Set the signature in the params
|
||||
// Set the signature in the params
|
||||
oauth_parameters.oauth_signature = signature;
|
||||
if(!request.headers){
|
||||
request.headers = {};
|
||||
}
|
||||
|
||||
// Set the authorization header
|
||||
// Set the authorization header
|
||||
var authHeader = Object.keys(oauth_parameters).sort().map(function(key){
|
||||
var value = oauth_parameters[key];
|
||||
return key + '="' + value + '"';
|
||||
@@ -219,7 +219,7 @@ OAuth.signRequest = function(request, oauth_parameters, consumer_secret, auth_to
|
||||
|
||||
request.headers.Authorization = 'OAuth ' + authHeader;
|
||||
|
||||
// Set the content type header
|
||||
// Set the content type header
|
||||
request.headers["Content-Type"] = "application/x-www-form-urlencoded";
|
||||
return request;
|
||||
|
||||
|
||||
@@ -110,7 +110,7 @@ class MongoSchemaCollection {
|
||||
|
||||
_fetchAllSchemasFrom_SCHEMA() {
|
||||
return this._collection._rawFind({})
|
||||
.then(schemas => schemas.map(mongoSchemaToParseSchema));
|
||||
.then(schemas => schemas.map(mongoSchemaToParseSchema));
|
||||
}
|
||||
|
||||
_fechOneSchemaFrom_SCHEMA(name: string) {
|
||||
@@ -149,32 +149,32 @@ class MongoSchemaCollection {
|
||||
// TODO: don't spend an extra query on finding the schema if the type we are trying to add isn't a GeoPoint.
|
||||
addFieldIfNotExists(className: string, fieldName: string, type: string) {
|
||||
return this._fechOneSchemaFrom_SCHEMA(className)
|
||||
.then(schema => {
|
||||
.then(schema => {
|
||||
// The schema exists. Check for existing GeoPoints.
|
||||
if (type.type === 'GeoPoint') {
|
||||
if (type.type === 'GeoPoint') {
|
||||
// Make sure there are not other geopoint fields
|
||||
if (Object.keys(schema.fields).some(existingField => schema.fields[existingField].type === 'GeoPoint')) {
|
||||
throw new Parse.Error(Parse.Error.INCORRECT_TYPE, 'MongoDB only supports one GeoPoint field in a class.');
|
||||
if (Object.keys(schema.fields).some(existingField => schema.fields[existingField].type === 'GeoPoint')) {
|
||||
throw new Parse.Error(Parse.Error.INCORRECT_TYPE, 'MongoDB only supports one GeoPoint field in a class.');
|
||||
}
|
||||
}
|
||||
}
|
||||
return;
|
||||
}, error => {
|
||||
return;
|
||||
}, error => {
|
||||
// If error is undefined, the schema doesn't exist, and we can create the schema with the field.
|
||||
// If some other error, reject with it.
|
||||
if (error === undefined) {
|
||||
return;
|
||||
}
|
||||
throw error;
|
||||
})
|
||||
.then(() => {
|
||||
if (error === undefined) {
|
||||
return;
|
||||
}
|
||||
throw error;
|
||||
})
|
||||
.then(() => {
|
||||
// We use $exists and $set to avoid overwriting the field type if it
|
||||
// already exists. (it could have added inbetween the last query and the update)
|
||||
return this.upsertSchema(
|
||||
className,
|
||||
{ [fieldName]: { '$exists': false } },
|
||||
{ '$set' : { [fieldName]: parseFieldTypeToMongoFieldType(type) } }
|
||||
);
|
||||
});
|
||||
return this.upsertSchema(
|
||||
className,
|
||||
{ [fieldName]: { '$exists': false } },
|
||||
{ '$set' : { [fieldName]: parseFieldTypeToMongoFieldType(type) } }
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -22,17 +22,17 @@ const MongoSchemaCollectionName = '_SCHEMA';
|
||||
|
||||
const storageAdapterAllCollections = mongoAdapter => {
|
||||
return mongoAdapter.connect()
|
||||
.then(() => mongoAdapter.database.collections())
|
||||
.then(collections => {
|
||||
return collections.filter(collection => {
|
||||
if (collection.namespace.match(/\.system\./)) {
|
||||
return false;
|
||||
}
|
||||
// TODO: If you have one app with a collection prefix that happens to be a prefix of another
|
||||
// apps prefix, this will go very very badly. We should fix that somehow.
|
||||
return (collection.collectionName.indexOf(mongoAdapter._collectionPrefix) == 0);
|
||||
.then(() => mongoAdapter.database.collections())
|
||||
.then(collections => {
|
||||
return collections.filter(collection => {
|
||||
if (collection.namespace.match(/\.system\./)) {
|
||||
return false;
|
||||
}
|
||||
// TODO: If you have one app with a collection prefix that happens to be a prefix of another
|
||||
// apps prefix, this will go very very badly. We should fix that somehow.
|
||||
return (collection.collectionName.indexOf(mongoAdapter._collectionPrefix) == 0);
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
const convertParseSchemaToMongoSchema = ({...schema}) => {
|
||||
@@ -157,9 +157,9 @@ export class MongoStorageAdapter {
|
||||
|
||||
setClassLevelPermissions(className, CLPs) {
|
||||
return this._schemaCollection()
|
||||
.then(schemaCollection => schemaCollection.updateSchema(className, {
|
||||
$set: { _metadata: { class_permissions: CLPs } }
|
||||
}));
|
||||
.then(schemaCollection => schemaCollection.updateSchema(className, {
|
||||
$set: { _metadata: { class_permissions: CLPs } }
|
||||
}));
|
||||
}
|
||||
|
||||
createClass(className, schema) {
|
||||
@@ -167,43 +167,43 @@ export class MongoStorageAdapter {
|
||||
const mongoObject = mongoSchemaFromFieldsAndClassNameAndCLP(schema.fields, className, schema.classLevelPermissions);
|
||||
mongoObject._id = className;
|
||||
return this._schemaCollection()
|
||||
.then(schemaCollection => schemaCollection._collection.insertOne(mongoObject))
|
||||
.then(result => MongoSchemaCollection._TESTmongoSchemaToParseSchema(result.ops[0]))
|
||||
.catch(error => {
|
||||
if (error.code === 11000) { //Mongo's duplicate key error
|
||||
throw new Parse.Error(Parse.Error.DUPLICATE_VALUE, 'Class already exists.');
|
||||
} else {
|
||||
throw error;
|
||||
}
|
||||
})
|
||||
.then(schemaCollection => schemaCollection._collection.insertOne(mongoObject))
|
||||
.then(result => MongoSchemaCollection._TESTmongoSchemaToParseSchema(result.ops[0]))
|
||||
.catch(error => {
|
||||
if (error.code === 11000) { //Mongo's duplicate key error
|
||||
throw new Parse.Error(Parse.Error.DUPLICATE_VALUE, 'Class already exists.');
|
||||
} else {
|
||||
throw error;
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
addFieldIfNotExists(className, fieldName, type) {
|
||||
return this._schemaCollection()
|
||||
.then(schemaCollection => schemaCollection.addFieldIfNotExists(className, fieldName, type));
|
||||
.then(schemaCollection => schemaCollection.addFieldIfNotExists(className, fieldName, type));
|
||||
}
|
||||
|
||||
// Drops a collection. Resolves with true if it was a Parse Schema (eg. _User, Custom, etc.)
|
||||
// and resolves with false if it wasn't (eg. a join table). Rejects if deletion was impossible.
|
||||
deleteClass(className) {
|
||||
return this._adaptiveCollection(className)
|
||||
.then(collection => collection.drop())
|
||||
.catch(error => {
|
||||
.then(collection => collection.drop())
|
||||
.catch(error => {
|
||||
// 'ns not found' means collection was already gone. Ignore deletion attempt.
|
||||
if (error.message == 'ns not found') {
|
||||
return;
|
||||
}
|
||||
throw error;
|
||||
})
|
||||
if (error.message == 'ns not found') {
|
||||
return;
|
||||
}
|
||||
throw error;
|
||||
})
|
||||
// We've dropped the collection, now remove the _SCHEMA document
|
||||
.then(() => this._schemaCollection())
|
||||
.then(schemaCollection => schemaCollection.findAndDeleteSchema(className))
|
||||
.then(() => this._schemaCollection())
|
||||
.then(schemaCollection => schemaCollection.findAndDeleteSchema(className))
|
||||
}
|
||||
|
||||
// Delete all data known to this adatper. Used for testing.
|
||||
deleteAllClasses() {
|
||||
return storageAdapterAllCollections(this)
|
||||
.then(collections => Promise.all(collections.map(collection => collection.drop())));
|
||||
.then(collections => Promise.all(collections.map(collection => collection.drop())));
|
||||
}
|
||||
|
||||
// Remove the column and all the data. For Relations, the _Join collection is handled
|
||||
@@ -245,9 +245,9 @@ export class MongoStorageAdapter {
|
||||
});
|
||||
|
||||
return this._adaptiveCollection(className)
|
||||
.then(collection => collection.updateMany({}, collectionUpdate))
|
||||
.then(() => this._schemaCollection())
|
||||
.then(schemaCollection => schemaCollection.updateSchema(className, schemaUpdate));
|
||||
.then(collection => collection.updateMany({}, collectionUpdate))
|
||||
.then(() => this._schemaCollection())
|
||||
.then(schemaCollection => schemaCollection.updateSchema(className, schemaUpdate));
|
||||
}
|
||||
|
||||
// Return a promise for all schemas known to this adapter, in Parse format. In case the
|
||||
@@ -262,7 +262,7 @@ export class MongoStorageAdapter {
|
||||
// undefined as the reason.
|
||||
getClass(className) {
|
||||
return this._schemaCollection()
|
||||
.then(schemasCollection => schemasCollection._fechOneSchemaFrom_SCHEMA(className))
|
||||
.then(schemasCollection => schemasCollection._fechOneSchemaFrom_SCHEMA(className))
|
||||
}
|
||||
|
||||
// TODO: As yet not particularly well specified. Creates an object. Maybe shouldn't even need the schema,
|
||||
@@ -272,14 +272,14 @@ export class MongoStorageAdapter {
|
||||
schema = convertParseSchemaToMongoSchema(schema);
|
||||
const mongoObject = parseObjectToMongoObjectForCreate(className, object, schema);
|
||||
return this._adaptiveCollection(className)
|
||||
.then(collection => collection.insertOne(mongoObject))
|
||||
.catch(error => {
|
||||
if (error.code === 11000) { // Duplicate value
|
||||
throw new Parse.Error(Parse.Error.DUPLICATE_VALUE,
|
||||
.then(collection => collection.insertOne(mongoObject))
|
||||
.catch(error => {
|
||||
if (error.code === 11000) { // Duplicate value
|
||||
throw new Parse.Error(Parse.Error.DUPLICATE_VALUE,
|
||||
'A duplicate value for a field with unique values was provided');
|
||||
}
|
||||
throw error;
|
||||
});
|
||||
}
|
||||
throw error;
|
||||
});
|
||||
}
|
||||
|
||||
// Remove all objects that match the given Parse Query.
|
||||
@@ -288,18 +288,18 @@ export class MongoStorageAdapter {
|
||||
deleteObjectsByQuery(className, schema, query) {
|
||||
schema = convertParseSchemaToMongoSchema(schema);
|
||||
return this._adaptiveCollection(className)
|
||||
.then(collection => {
|
||||
const mongoWhere = transformWhere(className, query, schema);
|
||||
return collection.deleteMany(mongoWhere)
|
||||
})
|
||||
.then(({ result }) => {
|
||||
if (result.n === 0) {
|
||||
throw new Parse.Error(Parse.Error.OBJECT_NOT_FOUND, 'Object not found.');
|
||||
}
|
||||
return Promise.resolve();
|
||||
}, () => {
|
||||
throw new Parse.Error(Parse.Error.INTERNAL_SERVER_ERROR, 'Database adapter error');
|
||||
});
|
||||
.then(collection => {
|
||||
const mongoWhere = transformWhere(className, query, schema);
|
||||
return collection.deleteMany(mongoWhere)
|
||||
})
|
||||
.then(({ result }) => {
|
||||
if (result.n === 0) {
|
||||
throw new Parse.Error(Parse.Error.OBJECT_NOT_FOUND, 'Object not found.');
|
||||
}
|
||||
return Promise.resolve();
|
||||
}, () => {
|
||||
throw new Parse.Error(Parse.Error.INTERNAL_SERVER_ERROR, 'Database adapter error');
|
||||
});
|
||||
}
|
||||
|
||||
// Apply the update to all objects that match the given Parse Query.
|
||||
@@ -308,7 +308,7 @@ export class MongoStorageAdapter {
|
||||
const mongoUpdate = transformUpdate(className, update, schema);
|
||||
const mongoWhere = transformWhere(className, query, schema);
|
||||
return this._adaptiveCollection(className)
|
||||
.then(collection => collection.updateMany(mongoWhere, mongoUpdate));
|
||||
.then(collection => collection.updateMany(mongoWhere, mongoUpdate));
|
||||
}
|
||||
|
||||
// Atomically finds and updates an object based on query.
|
||||
@@ -318,8 +318,8 @@ export class MongoStorageAdapter {
|
||||
const mongoUpdate = transformUpdate(className, update, schema);
|
||||
const mongoWhere = transformWhere(className, query, schema);
|
||||
return this._adaptiveCollection(className)
|
||||
.then(collection => collection._mongoCollection.findAndModify(mongoWhere, [], mongoUpdate, { new: true }))
|
||||
.then(result => mongoObjectToParseObject(className, result.value, schema));
|
||||
.then(collection => collection._mongoCollection.findAndModify(mongoWhere, [], mongoUpdate, { new: true }))
|
||||
.then(result => mongoObjectToParseObject(className, result.value, schema));
|
||||
}
|
||||
|
||||
// Hopefully we can get rid of this. It's only used for config and hooks.
|
||||
@@ -328,7 +328,7 @@ export class MongoStorageAdapter {
|
||||
const mongoUpdate = transformUpdate(className, update, schema);
|
||||
const mongoWhere = transformWhere(className, query, schema);
|
||||
return this._adaptiveCollection(className)
|
||||
.then(collection => collection.upsertOne(mongoWhere, mongoUpdate));
|
||||
.then(collection => collection.upsertOne(mongoWhere, mongoUpdate));
|
||||
}
|
||||
|
||||
// Executes a find. Accepts: className, query in Parse format, and { skip, limit, sort }.
|
||||
@@ -341,14 +341,14 @@ export class MongoStorageAdapter {
|
||||
return memo;
|
||||
}, {});
|
||||
return this._adaptiveCollection(className)
|
||||
.then(collection => collection.find(mongoWhere, {
|
||||
skip,
|
||||
limit,
|
||||
sort: mongoSort,
|
||||
keys: mongoKeys,
|
||||
maxTimeMS: this._maxTimeMS,
|
||||
}))
|
||||
.then(objects => objects.map(object => mongoObjectToParseObject(className, object, schema)))
|
||||
.then(collection => collection.find(mongoWhere, {
|
||||
skip,
|
||||
limit,
|
||||
sort: mongoSort,
|
||||
keys: mongoKeys,
|
||||
maxTimeMS: this._maxTimeMS,
|
||||
}))
|
||||
.then(objects => objects.map(object => mongoObjectToParseObject(className, object, schema)))
|
||||
}
|
||||
|
||||
// Create a unique index. Unique indexes on nullable fields are not allowed. Since we don't
|
||||
@@ -364,14 +364,14 @@ export class MongoStorageAdapter {
|
||||
indexCreationRequest[fieldName] = 1;
|
||||
});
|
||||
return this._adaptiveCollection(className)
|
||||
.then(collection => collection._ensureSparseUniqueIndexInBackground(indexCreationRequest))
|
||||
.catch(error => {
|
||||
if (error.code === 11000) {
|
||||
throw new Parse.Error(Parse.Error.DUPLICATE_VALUE, 'Tried to ensure field uniqueness for a class that already has duplicates.');
|
||||
} else {
|
||||
throw error;
|
||||
}
|
||||
});
|
||||
.then(collection => collection._ensureSparseUniqueIndexInBackground(indexCreationRequest))
|
||||
.catch(error => {
|
||||
if (error.code === 11000) {
|
||||
throw new Parse.Error(Parse.Error.DUPLICATE_VALUE, 'Tried to ensure field uniqueness for a class that already has duplicates.');
|
||||
} else {
|
||||
throw error;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Used in tests
|
||||
@@ -385,9 +385,9 @@ export class MongoStorageAdapter {
|
||||
count(className, schema, query) {
|
||||
schema = convertParseSchemaToMongoSchema(schema);
|
||||
return this._adaptiveCollection(className)
|
||||
.then(collection => collection.count(transformWhere(className, query, schema), {
|
||||
maxTimeMS: this._maxTimeMS,
|
||||
}));
|
||||
.then(collection => collection.count(transformWhere(className, query, schema), {
|
||||
maxTimeMS: this._maxTimeMS,
|
||||
}));
|
||||
}
|
||||
|
||||
performInitialization() {
|
||||
@@ -396,7 +396,7 @@ export class MongoStorageAdapter {
|
||||
|
||||
createIndex(className, index) {
|
||||
return this._adaptiveCollection(className)
|
||||
.then(collection => collection._mongoCollection.createIndex(index));
|
||||
.then(collection => collection._mongoCollection.createIndex(index));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -101,7 +101,7 @@ const transformKeyValueForUpdate = (className, restKey, restValue, parseFormatSc
|
||||
return {key, value};
|
||||
}
|
||||
|
||||
// Handle update operators
|
||||
// Handle update operators
|
||||
if (typeof restValue === 'object' && '__op' in restValue) {
|
||||
return {key, value: transformUpdateOperator(restValue, false)};
|
||||
}
|
||||
@@ -562,7 +562,7 @@ function transformConstraint(constraint, inArray) {
|
||||
const arr = constraint[key];
|
||||
if (!(arr instanceof Array)) {
|
||||
throw new Parse.Error(Parse.Error.INVALID_JSON,
|
||||
'bad ' + key + ' value');
|
||||
'bad ' + key + ' value');
|
||||
}
|
||||
answer[key] = arr.map(transformInteriorAtom);
|
||||
break;
|
||||
|
||||
@@ -505,15 +505,15 @@ export class PostgresStorageAdapter {
|
||||
_ensureSchemaCollectionExists(conn) {
|
||||
conn = conn || this._client;
|
||||
return conn.none('CREATE TABLE IF NOT EXISTS "_SCHEMA" ( "className" varChar(120), "schema" jsonb, "isParseClass" bool, PRIMARY KEY ("className") )')
|
||||
.catch(error => {
|
||||
if (error.code === PostgresDuplicateRelationError
|
||||
.catch(error => {
|
||||
if (error.code === PostgresDuplicateRelationError
|
||||
|| error.code === PostgresUniqueIndexViolationError
|
||||
|| error.code === PostgresDuplicateObjectError) {
|
||||
// Table already exists, must have been created by a different request. Ignore error.
|
||||
} else {
|
||||
throw error;
|
||||
}
|
||||
});
|
||||
} else {
|
||||
throw error;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
classExists(name) {
|
||||
@@ -536,19 +536,19 @@ export class PostgresStorageAdapter {
|
||||
|
||||
return t.batch([q1, q2]);
|
||||
})
|
||||
.then(() => {
|
||||
return toParseSchema(schema)
|
||||
})
|
||||
.catch((err) => {
|
||||
if (Array.isArray(err.data) && err.data.length > 1 && err.data[0].result.code === PostgresTransactionAbortedError) {
|
||||
err = err.data[1].result;
|
||||
}
|
||||
.then(() => {
|
||||
return toParseSchema(schema)
|
||||
})
|
||||
.catch((err) => {
|
||||
if (Array.isArray(err.data) && err.data.length > 1 && err.data[0].result.code === PostgresTransactionAbortedError) {
|
||||
err = err.data[1].result;
|
||||
}
|
||||
|
||||
if (err.code === PostgresUniqueIndexViolationError && err.detail.includes(className)) {
|
||||
throw new Parse.Error(Parse.Error.DUPLICATE_VALUE, `Class ${className} already exists.`)
|
||||
}
|
||||
throw err;
|
||||
})
|
||||
if (err.code === PostgresUniqueIndexViolationError && err.detail.includes(className)) {
|
||||
throw new Parse.Error(Parse.Error.DUPLICATE_VALUE, `Class ${className} already exists.`)
|
||||
}
|
||||
throw err;
|
||||
})
|
||||
}
|
||||
|
||||
// Just create a table, do not insert in schema
|
||||
@@ -592,19 +592,19 @@ export class PostgresStorageAdapter {
|
||||
const qs = `CREATE TABLE IF NOT EXISTS $1:name (${patternsArray.join(',')})`;
|
||||
const values = [className, ...valuesArray];
|
||||
return this._ensureSchemaCollectionExists(conn)
|
||||
.then(() => conn.none(qs, values))
|
||||
.catch(error => {
|
||||
if (error.code === PostgresDuplicateRelationError) {
|
||||
.then(() => conn.none(qs, values))
|
||||
.catch(error => {
|
||||
if (error.code === PostgresDuplicateRelationError) {
|
||||
// Table already exists, must have been created by a different request. Ignore error.
|
||||
} else {
|
||||
throw error;
|
||||
}
|
||||
}).then(() => {
|
||||
} else {
|
||||
throw error;
|
||||
}
|
||||
}).then(() => {
|
||||
// Create the relation tables
|
||||
return Promise.all(relations.map((fieldName) => {
|
||||
return conn.none('CREATE TABLE IF NOT EXISTS $<joinTable:name> ("relatedId" varChar(120), "owningId" varChar(120), PRIMARY KEY("relatedId", "owningId") )', {joinTable: `_Join:${fieldName}:${className}`});
|
||||
}));
|
||||
});
|
||||
return Promise.all(relations.map((fieldName) => {
|
||||
return conn.none('CREATE TABLE IF NOT EXISTS $<joinTable:name> ("relatedId" varChar(120), "owningId" varChar(120), PRIMARY KEY("relatedId", "owningId") )', {joinTable: `_Join:${fieldName}:${className}`});
|
||||
}));
|
||||
});
|
||||
}
|
||||
|
||||
addFieldIfNotExists(className, fieldName, type) {
|
||||
@@ -618,16 +618,16 @@ export class PostgresStorageAdapter {
|
||||
fieldName,
|
||||
postgresType: parseTypeToPostgresType(type)
|
||||
})
|
||||
.catch(error => {
|
||||
if (error.code === PostgresRelationDoesNotExistError) {
|
||||
return this.createClass(className, {fields: {[fieldName]: type}})
|
||||
} else if (error.code === PostgresDuplicateColumnError) {
|
||||
.catch(error => {
|
||||
if (error.code === PostgresRelationDoesNotExistError) {
|
||||
return this.createClass(className, {fields: {[fieldName]: type}})
|
||||
} else if (error.code === PostgresDuplicateColumnError) {
|
||||
// Column already exists, created by other request. Carry on to
|
||||
// See if it's the right type.
|
||||
} else {
|
||||
throw error;
|
||||
}
|
||||
})
|
||||
} else {
|
||||
throw error;
|
||||
}
|
||||
})
|
||||
} else {
|
||||
promise = t.none('CREATE TABLE IF NOT EXISTS $<joinTable:name> ("relatedId" varChar(120), "owningId" varChar(120), PRIMARY KEY("relatedId", "owningId") )', {joinTable: `_Join:${fieldName}:${className}`})
|
||||
}
|
||||
@@ -663,22 +663,22 @@ export class PostgresStorageAdapter {
|
||||
const now = new Date().getTime();
|
||||
debug('deleteAllClasses');
|
||||
return this._client.any('SELECT * FROM "_SCHEMA"')
|
||||
.then(results => {
|
||||
const joins = results.reduce((list, schema) => {
|
||||
return list.concat(joinTablesForSchema(schema.schema));
|
||||
}, []);
|
||||
const classes = ['_SCHEMA','_PushStatus','_JobStatus','_JobSchedule','_Hooks','_GlobalConfig', ...results.map(result => result.className), ...joins];
|
||||
return this._client.tx(t=>t.batch(classes.map(className=>t.none('DROP TABLE IF EXISTS $<className:name>', { className }))));
|
||||
}, error => {
|
||||
if (error.code === PostgresRelationDoesNotExistError) {
|
||||
.then(results => {
|
||||
const joins = results.reduce((list, schema) => {
|
||||
return list.concat(joinTablesForSchema(schema.schema));
|
||||
}, []);
|
||||
const classes = ['_SCHEMA','_PushStatus','_JobStatus','_JobSchedule','_Hooks','_GlobalConfig', ...results.map(result => result.className), ...joins];
|
||||
return this._client.tx(t=>t.batch(classes.map(className=>t.none('DROP TABLE IF EXISTS $<className:name>', { className }))));
|
||||
}, error => {
|
||||
if (error.code === PostgresRelationDoesNotExistError) {
|
||||
// No _SCHEMA collection. Don't delete anything.
|
||||
return;
|
||||
} else {
|
||||
throw error;
|
||||
}
|
||||
}).then(() => {
|
||||
debug(`deleteAllClasses done in ${new Date().getTime() - now}`);
|
||||
});
|
||||
return;
|
||||
} else {
|
||||
throw error;
|
||||
}
|
||||
}).then(() => {
|
||||
debug(`deleteAllClasses done in ${new Date().getTime() - now}`);
|
||||
});
|
||||
}
|
||||
|
||||
// Remove the column and all the data. For Relations, the _Join collection is handled
|
||||
@@ -697,34 +697,34 @@ export class PostgresStorageAdapter {
|
||||
deleteFields(className, schema, fieldNames) {
|
||||
debug('deleteFields', className, fieldNames);
|
||||
return Promise.resolve()
|
||||
.then(() => {
|
||||
fieldNames = fieldNames.reduce((list, fieldName) => {
|
||||
const field = schema.fields[fieldName]
|
||||
if (field.type !== 'Relation') {
|
||||
list.push(fieldName);
|
||||
}
|
||||
delete schema.fields[fieldName];
|
||||
return list;
|
||||
}, []);
|
||||
.then(() => {
|
||||
fieldNames = fieldNames.reduce((list, fieldName) => {
|
||||
const field = schema.fields[fieldName]
|
||||
if (field.type !== 'Relation') {
|
||||
list.push(fieldName);
|
||||
}
|
||||
delete schema.fields[fieldName];
|
||||
return list;
|
||||
}, []);
|
||||
|
||||
const values = [className, ...fieldNames];
|
||||
const columns = fieldNames.map((name, idx) => {
|
||||
return `$${idx + 2}:name`;
|
||||
}).join(', DROP COLUMN');
|
||||
const values = [className, ...fieldNames];
|
||||
const columns = fieldNames.map((name, idx) => {
|
||||
return `$${idx + 2}:name`;
|
||||
}).join(', DROP COLUMN');
|
||||
|
||||
const doBatch = (t) => {
|
||||
const batch = [
|
||||
t.none('UPDATE "_SCHEMA" SET "schema"=$<schema> WHERE "className"=$<className>', {schema, className})
|
||||
];
|
||||
if (values.length > 1) {
|
||||
batch.push(t.none(`ALTER TABLE $1:name DROP COLUMN ${columns}`, values));
|
||||
const doBatch = (t) => {
|
||||
const batch = [
|
||||
t.none('UPDATE "_SCHEMA" SET "schema"=$<schema> WHERE "className"=$<className>', {schema, className})
|
||||
];
|
||||
if (values.length > 1) {
|
||||
batch.push(t.none(`ALTER TABLE $1:name DROP COLUMN ${columns}`, values));
|
||||
}
|
||||
return batch;
|
||||
}
|
||||
return batch;
|
||||
}
|
||||
return this._client.tx((t) => {
|
||||
return t.batch(doBatch(t));
|
||||
return this._client.tx((t) => {
|
||||
return t.batch(doBatch(t));
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// Return a promise for all schemas known to this adapter, in Parse format. In case the
|
||||
@@ -732,8 +732,8 @@ export class PostgresStorageAdapter {
|
||||
// rejection reason are TBD.
|
||||
getAllClasses() {
|
||||
return this._ensureSchemaCollectionExists()
|
||||
.then(() => this._client.map('SELECT * FROM "_SCHEMA"', null, row => ({ className: row.className, ...row.schema })))
|
||||
.then(res => res.map(toParseSchema))
|
||||
.then(() => this._client.map('SELECT * FROM "_SCHEMA"', null, row => ({ className: row.className, ...row.schema })))
|
||||
.then(res => res.map(toParseSchema))
|
||||
}
|
||||
|
||||
// Return a promise for the schema with the given name, in Parse format. If
|
||||
@@ -742,13 +742,13 @@ export class PostgresStorageAdapter {
|
||||
getClass(className) {
|
||||
debug('getClass', className);
|
||||
return this._client.any('SELECT * FROM "_SCHEMA" WHERE "className"=$<className>', { className })
|
||||
.then(result => {
|
||||
if (result.length === 1) {
|
||||
return result[0].schema;
|
||||
} else {
|
||||
throw undefined;
|
||||
}
|
||||
}).then(toParseSchema);
|
||||
.then(result => {
|
||||
if (result.length === 1) {
|
||||
return result[0].schema;
|
||||
} else {
|
||||
throw undefined;
|
||||
}
|
||||
}).then(toParseSchema);
|
||||
}
|
||||
|
||||
// TODO: remove the mongo format dependency in the return value
|
||||
@@ -830,7 +830,7 @@ export class PostgresStorageAdapter {
|
||||
valuesArray.push(object[fieldName].name);
|
||||
break;
|
||||
case 'GeoPoint':
|
||||
// pop the point and process later
|
||||
// pop the point and process later
|
||||
geoPoints[fieldName] = object[fieldName];
|
||||
columnsArray.pop();
|
||||
break;
|
||||
@@ -864,14 +864,14 @@ export class PostgresStorageAdapter {
|
||||
const values = [className, ...columnsArray, ...valuesArray]
|
||||
debug(qs, values);
|
||||
return this._client.none(qs, values)
|
||||
.then(() => ({ ops: [object] }))
|
||||
.catch(error => {
|
||||
if (error.code === PostgresUniqueIndexViolationError) {
|
||||
throw new Parse.Error(Parse.Error.DUPLICATE_VALUE, 'A duplicate value for a field with unique values was provided');
|
||||
} else {
|
||||
throw error;
|
||||
}
|
||||
})
|
||||
.then(() => ({ ops: [object] }))
|
||||
.catch(error => {
|
||||
if (error.code === PostgresUniqueIndexViolationError) {
|
||||
throw new Parse.Error(Parse.Error.DUPLICATE_VALUE, 'A duplicate value for a field with unique values was provided');
|
||||
} else {
|
||||
throw error;
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// Remove all objects that match the given Parse Query.
|
||||
@@ -889,13 +889,13 @@ export class PostgresStorageAdapter {
|
||||
const qs = `WITH deleted AS (DELETE FROM $1:name WHERE ${where.pattern} RETURNING *) SELECT count(*) FROM deleted`;
|
||||
debug(qs, values);
|
||||
return this._client.one(qs, values , a => +a.count)
|
||||
.then(count => {
|
||||
if (count === 0) {
|
||||
throw new Parse.Error(Parse.Error.OBJECT_NOT_FOUND, 'Object not found.');
|
||||
} else {
|
||||
return count;
|
||||
}
|
||||
});
|
||||
.then(count => {
|
||||
if (count === 0) {
|
||||
throw new Parse.Error(Parse.Error.OBJECT_NOT_FOUND, 'Object not found.');
|
||||
} else {
|
||||
return count;
|
||||
}
|
||||
});
|
||||
}
|
||||
// Return value not currently well specified.
|
||||
findOneAndUpdate(className, schema, query, update) {
|
||||
@@ -1145,72 +1145,72 @@ export class PostgresStorageAdapter {
|
||||
const qs = `SELECT ${columns} FROM $1:name ${wherePattern} ${sortPattern} ${limitPattern} ${skipPattern}`;
|
||||
debug(qs, values);
|
||||
return this._client.any(qs, values)
|
||||
.catch((err) => {
|
||||
.catch((err) => {
|
||||
// Query on non existing table, don't crash
|
||||
if (err.code === PostgresRelationDoesNotExistError) {
|
||||
return [];
|
||||
}
|
||||
return Promise.reject(err);
|
||||
})
|
||||
.then(results => results.map(object => {
|
||||
Object.keys(schema.fields).forEach(fieldName => {
|
||||
if (schema.fields[fieldName].type === 'Pointer' && object[fieldName]) {
|
||||
object[fieldName] = { objectId: object[fieldName], __type: 'Pointer', className: schema.fields[fieldName].targetClass };
|
||||
if (err.code === PostgresRelationDoesNotExistError) {
|
||||
return [];
|
||||
}
|
||||
if (schema.fields[fieldName].type === 'Relation') {
|
||||
object[fieldName] = {
|
||||
__type: "Relation",
|
||||
className: schema.fields[fieldName].targetClass
|
||||
return Promise.reject(err);
|
||||
})
|
||||
.then(results => results.map(object => {
|
||||
Object.keys(schema.fields).forEach(fieldName => {
|
||||
if (schema.fields[fieldName].type === 'Pointer' && object[fieldName]) {
|
||||
object[fieldName] = { objectId: object[fieldName], __type: 'Pointer', className: schema.fields[fieldName].targetClass };
|
||||
}
|
||||
}
|
||||
if (object[fieldName] && schema.fields[fieldName].type === 'GeoPoint') {
|
||||
object[fieldName] = {
|
||||
__type: "GeoPoint",
|
||||
latitude: object[fieldName].y,
|
||||
longitude: object[fieldName].x
|
||||
if (schema.fields[fieldName].type === 'Relation') {
|
||||
object[fieldName] = {
|
||||
__type: "Relation",
|
||||
className: schema.fields[fieldName].targetClass
|
||||
}
|
||||
}
|
||||
}
|
||||
if (object[fieldName] && schema.fields[fieldName].type === 'File') {
|
||||
object[fieldName] = {
|
||||
__type: 'File',
|
||||
name: object[fieldName]
|
||||
if (object[fieldName] && schema.fields[fieldName].type === 'GeoPoint') {
|
||||
object[fieldName] = {
|
||||
__type: "GeoPoint",
|
||||
latitude: object[fieldName].y,
|
||||
longitude: object[fieldName].x
|
||||
}
|
||||
}
|
||||
if (object[fieldName] && schema.fields[fieldName].type === 'File') {
|
||||
object[fieldName] = {
|
||||
__type: 'File',
|
||||
name: object[fieldName]
|
||||
}
|
||||
}
|
||||
});
|
||||
//TODO: remove this reliance on the mongo format. DB adapter shouldn't know there is a difference between created at and any other date field.
|
||||
if (object.createdAt) {
|
||||
object.createdAt = object.createdAt.toISOString();
|
||||
}
|
||||
if (object.updatedAt) {
|
||||
object.updatedAt = object.updatedAt.toISOString();
|
||||
}
|
||||
if (object.expiresAt) {
|
||||
object.expiresAt = { __type: 'Date', iso: object.expiresAt.toISOString() };
|
||||
}
|
||||
if (object._email_verify_token_expires_at) {
|
||||
object._email_verify_token_expires_at = { __type: 'Date', iso: object._email_verify_token_expires_at.toISOString() };
|
||||
}
|
||||
if (object._account_lockout_expires_at) {
|
||||
object._account_lockout_expires_at = { __type: 'Date', iso: object._account_lockout_expires_at.toISOString() };
|
||||
}
|
||||
if (object._perishable_token_expires_at) {
|
||||
object._perishable_token_expires_at = { __type: 'Date', iso: object._perishable_token_expires_at.toISOString() };
|
||||
}
|
||||
if (object._password_changed_at) {
|
||||
object._password_changed_at = { __type: 'Date', iso: object._password_changed_at.toISOString() };
|
||||
}
|
||||
});
|
||||
//TODO: remove this reliance on the mongo format. DB adapter shouldn't know there is a difference between created at and any other date field.
|
||||
if (object.createdAt) {
|
||||
object.createdAt = object.createdAt.toISOString();
|
||||
}
|
||||
if (object.updatedAt) {
|
||||
object.updatedAt = object.updatedAt.toISOString();
|
||||
}
|
||||
if (object.expiresAt) {
|
||||
object.expiresAt = { __type: 'Date', iso: object.expiresAt.toISOString() };
|
||||
}
|
||||
if (object._email_verify_token_expires_at) {
|
||||
object._email_verify_token_expires_at = { __type: 'Date', iso: object._email_verify_token_expires_at.toISOString() };
|
||||
}
|
||||
if (object._account_lockout_expires_at) {
|
||||
object._account_lockout_expires_at = { __type: 'Date', iso: object._account_lockout_expires_at.toISOString() };
|
||||
}
|
||||
if (object._perishable_token_expires_at) {
|
||||
object._perishable_token_expires_at = { __type: 'Date', iso: object._perishable_token_expires_at.toISOString() };
|
||||
}
|
||||
if (object._password_changed_at) {
|
||||
object._password_changed_at = { __type: 'Date', iso: object._password_changed_at.toISOString() };
|
||||
}
|
||||
|
||||
for (const fieldName in object) {
|
||||
if (object[fieldName] === null) {
|
||||
delete object[fieldName];
|
||||
for (const fieldName in object) {
|
||||
if (object[fieldName] === null) {
|
||||
delete object[fieldName];
|
||||
}
|
||||
if (object[fieldName] instanceof Date) {
|
||||
object[fieldName] = { __type: 'Date', iso: object[fieldName].toISOString() };
|
||||
}
|
||||
}
|
||||
if (object[fieldName] instanceof Date) {
|
||||
object[fieldName] = { __type: 'Date', iso: object[fieldName].toISOString() };
|
||||
}
|
||||
}
|
||||
|
||||
return object;
|
||||
}));
|
||||
return object;
|
||||
}));
|
||||
}
|
||||
|
||||
// Create a unique index. Unique indexes on nullable fields are not allowed. Since we don't
|
||||
@@ -1225,16 +1225,16 @@ export class PostgresStorageAdapter {
|
||||
const constraintPatterns = fieldNames.map((fieldName, index) => `$${index + 3}:name`);
|
||||
const qs = `ALTER TABLE $1:name ADD CONSTRAINT $2:name UNIQUE (${constraintPatterns.join(',')})`;
|
||||
return this._client.none(qs,[className, constraintName, ...fieldNames])
|
||||
.catch(error => {
|
||||
if (error.code === PostgresDuplicateRelationError && error.message.includes(constraintName)) {
|
||||
.catch(error => {
|
||||
if (error.code === PostgresDuplicateRelationError && error.message.includes(constraintName)) {
|
||||
// Index already exists. Ignore error.
|
||||
} else if (error.code === PostgresUniqueIndexViolationError && error.message.includes(constraintName)) {
|
||||
} else if (error.code === PostgresUniqueIndexViolationError && error.message.includes(constraintName)) {
|
||||
// Cast the error into the proper parse error
|
||||
throw new Parse.Error(Parse.Error.DUPLICATE_VALUE, 'A duplicate value for a field with unique values was provided');
|
||||
} else {
|
||||
throw error;
|
||||
}
|
||||
});
|
||||
throw new Parse.Error(Parse.Error.DUPLICATE_VALUE, 'A duplicate value for a field with unique values was provided');
|
||||
} else {
|
||||
throw error;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Executes a count.
|
||||
@@ -1352,11 +1352,11 @@ function literalizeRegexPart(s) {
|
||||
// remove all instances of \Q and \E from the remaining text & escape single quotes
|
||||
return (
|
||||
s.replace(/([^\\])(\\E)/, '$1')
|
||||
.replace(/([^\\])(\\Q)/, '$1')
|
||||
.replace(/^\\E/, '')
|
||||
.replace(/^\\Q/, '')
|
||||
.replace(/([^'])'/, `$1''`)
|
||||
.replace(/^'([^'])/, `''$1`)
|
||||
.replace(/([^\\])(\\Q)/, '$1')
|
||||
.replace(/^\\E/, '')
|
||||
.replace(/^\\Q/, '')
|
||||
.replace(/([^'])'/, `$1''`)
|
||||
.replace(/^'([^'])/, `''$1`)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user