BVB Source Codes

parse-server Show triggers.js Source code

Return Download parse-server: download triggers.js Source code - Download parse-server Source code - Type:.js
  1. // triggers.js
  2. import Parse    from 'parse/node';
  3. import { logger } from './logger';
  4.  
  5. export const Types = {
  6.   beforeSave: 'beforeSave',
  7.   afterSave: 'afterSave',
  8.   beforeDelete: 'beforeDelete',
  9.   afterDelete: 'afterDelete',
  10.   beforeFind: 'beforeFind',
  11.   afterFind: 'afterFind'
  12. };
  13.  
  14. const baseStore = function() {
  15.   const Validators = {};
  16.   const Functions = {};
  17.   const Jobs = {};
  18.   const Triggers = Object.keys(Types).reduce(function(base, key){
  19.     base[key] = {};
  20.     return base;
  21.   }, {});
  22.  
  23.   return Object.freeze({
  24.     Functions,
  25.     Jobs,
  26.     Validators,
  27.     Triggers
  28.   });
  29. };
  30.  
  31. const _triggerStore = {};
  32.  
  33. export function addFunction(functionName, handler, validationHandler, applicationId) {
  34.   applicationId = applicationId || Parse.applicationId;
  35.   _triggerStore[applicationId] =  _triggerStore[applicationId] || baseStore();
  36.   _triggerStore[applicationId].Functions[functionName] = handler;
  37.   _triggerStore[applicationId].Validators[functionName] = validationHandler;
  38. }
  39.  
  40. export function addJob(jobName, handler, applicationId) {
  41.   applicationId = applicationId || Parse.applicationId;
  42.   _triggerStore[applicationId] =  _triggerStore[applicationId] || baseStore();
  43.   _triggerStore[applicationId].Jobs[jobName] = handler;
  44. }
  45.  
  46. export function addTrigger(type, className, handler, applicationId) {
  47.   applicationId = applicationId || Parse.applicationId;
  48.   _triggerStore[applicationId] =  _triggerStore[applicationId] || baseStore();
  49.   _triggerStore[applicationId].Triggers[type][className] = handler;
  50. }
  51.  
  52. export function removeFunction(functionName, applicationId) {
  53.   applicationId = applicationId || Parse.applicationId;
  54.   delete _triggerStore[applicationId].Functions[functionName]
  55. }
  56.  
  57. export function removeJob(jobName, applicationId) {
  58.   applicationId = applicationId || Parse.applicationId;
  59.   delete _triggerStore[applicationId].Jobs[jobName]
  60. }
  61.  
  62. export function removeTrigger(type, className, applicationId) {
  63.   applicationId = applicationId || Parse.applicationId;
  64.   delete _triggerStore[applicationId].Triggers[type][className]
  65. }
  66.  
  67. export function _unregister(appId,category,className,type) {
  68.   if (type) {
  69.     removeTrigger(className,type,appId);
  70.     delete _triggerStore[appId][category][className][type];
  71.   } else {
  72.     delete _triggerStore[appId][category][className];
  73.   }
  74. }
  75.  
  76. export function _unregisterAll() {
  77.   Object.keys(_triggerStore).forEach(appId => delete _triggerStore[appId]);
  78. }
  79.  
  80. export function getTrigger(className, triggerType, applicationId) {
  81.   if (!applicationId) {
  82.     throw "Missing ApplicationID";
  83.   }
  84.   var manager = _triggerStore[applicationId]
  85.   if (manager
  86.     && manager.Triggers
  87.     && manager.Triggers[triggerType]
  88.     && manager.Triggers[triggerType][className]) {
  89.     return manager.Triggers[triggerType][className];
  90.   }
  91.   return undefined;
  92. }
  93.  
  94. export function triggerExists(className: string, type: string, applicationId: string): boolean {
  95.   return (getTrigger(className, type, applicationId) != undefined);
  96. }
  97.  
  98. export function getFunction(functionName, applicationId) {
  99.   var manager = _triggerStore[applicationId];
  100.   if (manager && manager.Functions) {
  101.     return manager.Functions[functionName];
  102.   }
  103.   return undefined;
  104. }
  105.  
  106. export function getJob(jobName, applicationId) {
  107.   var manager = _triggerStore[applicationId];
  108.   if (manager && manager.Jobs) {
  109.     return manager.Jobs[jobName];
  110.   }
  111.   return undefined;
  112. }
  113.  
  114. export function getJobs(applicationId) {
  115.   var manager = _triggerStore[applicationId];
  116.   if (manager && manager.Jobs) {
  117.     return manager.Jobs;
  118.   }
  119.   return undefined;
  120. }
  121.  
  122.  
  123. export function getValidator(functionName, applicationId) {
  124.   var manager = _triggerStore[applicationId];
  125.   if (manager && manager.Validators) {
  126.     return manager.Validators[functionName];
  127.   }
  128.   return undefined;
  129. }
  130.  
  131. export function getRequestObject(triggerType, auth, parseObject, originalParseObject, config) {
  132.   var request = {
  133.     triggerName: triggerType,
  134.     object: parseObject,
  135.     master: false,
  136.     log: config.loggerController
  137.   };
  138.  
  139.   if (originalParseObject) {
  140.     request.original = originalParseObject;
  141.   }
  142.  
  143.   if (!auth) {
  144.     return request;
  145.   }
  146.   if (auth.isMaster) {
  147.     request['master'] = true;
  148.   }
  149.   if (auth.user) {
  150.     request['user'] = auth.user;
  151.   }
  152.   if (auth.installationId) {
  153.     request['installationId'] = auth.installationId;
  154.   }
  155.   return request;
  156. }
  157.  
  158. export function getRequestQueryObject(triggerType, auth, query, count, config) {
  159.   var request = {
  160.     triggerName: triggerType,
  161.     query,
  162.     master: false,
  163.     count,
  164.     log: config.loggerController
  165.   };
  166.  
  167.   if (!auth) {
  168.     return request;
  169.   }
  170.   if (auth.isMaster) {
  171.     request['master'] = true;
  172.   }
  173.   if (auth.user) {
  174.     request['user'] = auth.user;
  175.   }
  176.   if (auth.installationId) {
  177.     request['installationId'] = auth.installationId;
  178.   }
  179.   return request;
  180. }
  181.  
  182. // Creates the response object, and uses the request object to pass data
  183. // The API will call this with REST API formatted objects, this will
  184. // transform them to Parse.Object instances expected by Cloud Code.
  185. // Any changes made to the object in a beforeSave will be included.
  186. export function getResponseObject(request, resolve, reject) {
  187.   return {
  188.     success: function(response) {
  189.       if (request.triggerName === Types.afterFind) {
  190.         if(!response){
  191.           response = request.objects;
  192.         }
  193.         response = response.map(object => {
  194.           return object.toJSON();
  195.         });
  196.         return resolve(response);
  197.       }
  198.       // Use the JSON response
  199.       if (response && !request.object.equals(response)
  200.           && request.triggerName === Types.beforeSave) {
  201.         return resolve(response);
  202.       }
  203.       response = {};
  204.       if (request.triggerName === Types.beforeSave) {
  205.         response['object'] = request.object._getSaveJSON();
  206.       }
  207.       return resolve(response);
  208.     },
  209.     error: function(code, message) {
  210.       if (!message) {
  211.         message = code;
  212.         code = Parse.Error.SCRIPT_FAILED;
  213.       }
  214.       var scriptError = new Parse.Error(code, message);
  215.       return reject(scriptError);
  216.     }
  217.   }
  218. }
  219.  
  220. function userIdForLog(auth) {
  221.   return (auth && auth.user) ? auth.user.id : undefined;
  222. }
  223.  
  224. function logTriggerAfterHook(triggerType, className, input, auth) {
  225.   const cleanInput = logger.truncateLogMessage(JSON.stringify(input));
  226.   logger.info(`${triggerType} triggered for ${className} for user ${userIdForLog(auth)}:\n  Input: ${cleanInput}`, {
  227.     className,
  228.     triggerType,
  229.     user: userIdForLog(auth)
  230.   });
  231. }
  232.  
  233. function logTriggerSuccessBeforeHook(triggerType, className, input, result, auth) {
  234.   const cleanInput = logger.truncateLogMessage(JSON.stringify(input));
  235.   const cleanResult = logger.truncateLogMessage(JSON.stringify(result));
  236.   logger.info(`${triggerType} triggered for ${className} for user ${userIdForLog(auth)}:\n  Input: ${cleanInput}\n  Result: ${cleanResult}`, {
  237.     className,
  238.     triggerType,
  239.     user: userIdForLog(auth)
  240.   });
  241. }
  242.  
  243. function logTriggerErrorBeforeHook(triggerType, className, input, auth, error) {
  244.   const cleanInput = logger.truncateLogMessage(JSON.stringify(input));
  245.   logger.error(`${triggerType} failed for ${className} for user ${userIdForLog(auth)}:\n  Input: ${cleanInput}\n  Error: ${JSON.stringify(error)}`, {
  246.     className,
  247.     triggerType,
  248.     error,
  249.     user: userIdForLog(auth)
  250.   });
  251. }
  252.  
  253. export function maybeRunAfterFindTrigger(triggerType, auth, className, objects, config) {
  254.   return new Promise((resolve, reject) => {
  255.     const trigger = getTrigger(className, triggerType, config.applicationId);
  256.     if (!trigger) {
  257.       return resolve();
  258.     }
  259.     const request = getRequestObject(triggerType, auth, null, null, config);
  260.     const response = getResponseObject(request,
  261.       object => {
  262.         resolve(object);
  263.       },
  264.       error => {
  265.         reject(error);
  266.       });
  267.     logTriggerSuccessBeforeHook(triggerType, className, 'AfterFind', JSON.stringify(objects), auth);
  268.     request.objects = objects.map(object => {
  269.       //setting the class name to transform into parse object
  270.       object.className = className;
  271.       return Parse.Object.fromJSON(object);
  272.     });
  273.     const triggerPromise = trigger(request, response);
  274.     if (triggerPromise && typeof triggerPromise.then === "function") {
  275.       return triggerPromise.then(promiseResults => {
  276.         if(promiseResults) {
  277.           resolve(promiseResults);
  278.         }else{
  279.           return reject(new Parse.Error(Parse.Error.SCRIPT_FAILED, "AfterFind expect results to be returned in the promise"));
  280.         }
  281.       });
  282.     }
  283.   }).then((results) => {
  284.     logTriggerAfterHook(triggerType, className, JSON.stringify(results), auth);
  285.     return results;
  286.   });
  287. }
  288.  
  289. export function maybeRunQueryTrigger(triggerType, className, restWhere, restOptions, config, auth) {
  290.   const trigger = getTrigger(className, triggerType, config.applicationId);
  291.   if (!trigger) {
  292.     return Promise.resolve({
  293.       restWhere,
  294.       restOptions
  295.     });
  296.   }
  297.  
  298.   const parseQuery = new Parse.Query(className);
  299.   if (restWhere) {
  300.     parseQuery._where = restWhere;
  301.   }
  302.   let count = false;
  303.   if (restOptions) {
  304.     if (restOptions.include && restOptions.include.length > 0) {
  305.       parseQuery._include = restOptions.include.split(',');
  306.     }
  307.     if (restOptions.skip) {
  308.       parseQuery._skip = restOptions.skip;
  309.     }
  310.     if (restOptions.limit) {
  311.       parseQuery._limit = restOptions.limit;
  312.     }
  313.     count = !!restOptions.count;
  314.   }
  315.   const requestObject = getRequestQueryObject(triggerType, auth, parseQuery, count, config);
  316.   return Promise.resolve().then(() => {
  317.     return trigger(requestObject);
  318.   }).then((result) => {
  319.     let queryResult = parseQuery;
  320.     if (result && result instanceof Parse.Query) {
  321.       queryResult = result;
  322.     }
  323.     const jsonQuery = queryResult.toJSON();
  324.     if (jsonQuery.where) {
  325.       restWhere = jsonQuery.where;
  326.     }
  327.     if (jsonQuery.limit) {
  328.       restOptions = restOptions || {};
  329.       restOptions.limit = jsonQuery.limit;
  330.     }
  331.     if (jsonQuery.skip) {
  332.       restOptions = restOptions || {};
  333.       restOptions.skip = jsonQuery.skip;
  334.     }
  335.     if (jsonQuery.include) {
  336.       restOptions = restOptions || {};
  337.       restOptions.include = jsonQuery.include;
  338.     }
  339.     if (jsonQuery.keys) {
  340.       restOptions = restOptions || {};
  341.       restOptions.keys = jsonQuery.keys;
  342.     }
  343.     return {
  344.       restWhere,
  345.       restOptions
  346.     };
  347.   }, (err) => {
  348.     if (typeof err === 'string') {
  349.       throw new Parse.Error(1, err);
  350.     } else {
  351.       throw err;
  352.     }
  353.   });
  354. }
  355.  
  356. // To be used as part of the promise chain when saving/deleting an object
  357. // Will resolve successfully if no trigger is configured
  358. // Resolves to an object, empty or containing an object key. A beforeSave
  359. // trigger will set the object key to the rest format object to save.
  360. // originalParseObject is optional, we only need that for before/afterSave functions
  361. export function maybeRunTrigger(triggerType, auth, parseObject, originalParseObject, config) {
  362.   if (!parseObject) {
  363.     return Promise.resolve({});
  364.   }
  365.   return new Promise(function (resolve, reject) {
  366.     var trigger = getTrigger(parseObject.className, triggerType, config.applicationId);
  367.     if (!trigger) return resolve();
  368.     var request = getRequestObject(triggerType, auth, parseObject, originalParseObject, config);
  369.     var response = getResponseObject(request, (object) => {
  370.       logTriggerSuccessBeforeHook(
  371.           triggerType, parseObject.className, parseObject.toJSON(), object, auth);
  372.       resolve(object);
  373.     }, (error) => {
  374.       logTriggerErrorBeforeHook(
  375.           triggerType, parseObject.className, parseObject.toJSON(), auth, error);
  376.       reject(error);
  377.     });
  378.     // Force the current Parse app before the trigger
  379.     Parse.applicationId = config.applicationId;
  380.     Parse.javascriptKey = config.javascriptKey || '';
  381.     Parse.masterKey = config.masterKey;
  382.  
  383.     // AfterSave and afterDelete triggers can return a promise, which if they
  384.     // do, needs to be resolved before this promise is resolved,
  385.     // so trigger execution is synced with RestWrite.execute() call.
  386.     // If triggers do not return a promise, they can run async code parallel
  387.     // to the RestWrite.execute() call.
  388.     var triggerPromise = trigger(request, response);
  389.     if(triggerType === Types.afterSave || triggerType === Types.afterDelete)
  390.     {
  391.       logTriggerAfterHook(triggerType, parseObject.className, parseObject.toJSON(), auth);
  392.       if(triggerPromise && typeof triggerPromise.then === "function") {
  393.         return triggerPromise.then(resolve, resolve);
  394.       }
  395.       else {
  396.         return resolve();
  397.       }
  398.     }
  399.   });
  400. }
  401.  
  402. // Converts a REST-format object to a Parse.Object
  403. // data is either className or an object
  404. export function inflate(data, restObject) {
  405.   var copy = typeof data == 'object' ? data : {className: data};
  406.   for (var key in restObject) {
  407.     copy[key] = restObject[key];
  408.   }
  409.   return Parse.Object.fromJSON(copy);
  410. }
  411.  
downloadtriggers.js Source code - Download parse-server Source code
Related Source Codes/Software:
react-boilerplate - 2017-06-07
webtorrent - Streaming torrent client for the web ... 2017-06-06
machine-learning-for-software-engineers - A complete daily plan for studying to become a mac... 2017-06-06
upterm - A terminal emulator for the 21st century. 2017-06-06
lottie-android - Render After Effects animations natively on Androi... 2017-06-07
AsyncDisplayKit - Smooth asynchronous user interfaces for iOS apps. ... 2017-06-07
ionicons - The premium icon font for Ionic ... 2017-06-07
storybook - 2017-06-07
prettier - Prettier is an opinionated JavaScript formatter. ... 2017-06-08
CRYENGINE - CRYENGINE is a powerful real-time game development... 2017-06-11
postal - 2017-06-11
reactide - Reactide is the first dedicated IDE for React web ... 2017-06-11
rkt - rkt is a pod-native container engine for Linux. It... 2017-06-11
uWebSockets - Tiny WebSockets https://for... 2017-06-11
realworld - TodoMVC for the RealWorld - Exemplary fullstack Me... 2017-06-11
goreplay - GoReplay is an open-source tool for capturing and ... 2017-06-10
pyenv - Simple Python version management 2017-06-10
redux-saga - An alternative side effect model for Redux apps ... 2017-06-10
angular-starter - 2017-06-10

 Back to top