"use strict"; const Parse = require('parse/node').Parse; const path = require('path'); // These methods handle batch requests. const batchPath = '/batch'; // Mounts a batch-handler onto a PromiseRouter. function mountOnto(router) { router.route('POST', batchPath, req => { return handleBatch(router, req); }); } function parseURL(urlString) { try { return new URL(urlString); } catch (error) { return undefined; } } function makeBatchRoutingPathFunction(originalUrl, serverURL, publicServerURL) { serverURL = serverURL ? parseURL(serverURL) : undefined; publicServerURL = publicServerURL ? parseURL(publicServerURL) : undefined; const apiPrefixLength = originalUrl.length - batchPath.length; let apiPrefix = originalUrl.slice(0, apiPrefixLength); const makeRoutablePath = function (requestPath) { // The routablePath is the path minus the api prefix if (requestPath.slice(0, apiPrefix.length) != apiPrefix) { throw new Parse.Error(Parse.Error.INVALID_JSON, 'cannot route batch path ' + requestPath); } return path.posix.join('/', requestPath.slice(apiPrefix.length)); }; if (serverURL && publicServerURL && serverURL.pathname != publicServerURL.pathname) { const localPath = serverURL.pathname; const publicPath = publicServerURL.pathname; // Override the api prefix apiPrefix = localPath; return function (requestPath) { // Figure out which server url was used by figuring out which // path more closely matches requestPath const startsWithLocal = requestPath.startsWith(localPath); const startsWithPublic = requestPath.startsWith(publicPath); const pathLengthToUse = startsWithLocal && startsWithPublic ? Math.max(localPath.length, publicPath.length) : startsWithLocal ? localPath.length : publicPath.length; const newPath = path.posix.join('/', localPath, '/', requestPath.slice(pathLengthToUse)); // Use the method for local routing return makeRoutablePath(newPath); }; } return makeRoutablePath; } // Returns a promise for a {response} object. // TODO: pass along auth correctly function handleBatch(router, req) { if (!Array.isArray(req.body.requests)) { throw new Parse.Error(Parse.Error.INVALID_JSON, 'requests must be an array'); } // The batch paths are all from the root of our domain. // That means they include the API prefix, that the API is mounted // to. However, our promise router does not route the api prefix. So // we need to figure out the API prefix, so that we can strip it // from all the subrequests. if (!req.originalUrl.endsWith(batchPath)) { throw 'internal routing problem - expected url to end with batch'; } const makeRoutablePath = makeBatchRoutingPathFunction(req.originalUrl, req.config.serverURL, req.config.publicServerURL); const batch = transactionRetries => { let initialPromise = Promise.resolve(); if (req.body.transaction === true) { initialPromise = req.config.database.createTransactionalSession(); } return initialPromise.then(() => { const promises = req.body.requests.map(restRequest => { const routablePath = makeRoutablePath(restRequest.path); // Construct a request that we can send to a handler const request = { body: restRequest.body, config: req.config, auth: req.auth, info: req.info }; return router.tryRouteRequest(restRequest.method, routablePath, request).then(response => { return { success: response.response }; }, error => { return { error: { code: error.code, error: error.message } }; }); }); return Promise.all(promises).then(results => { if (req.body.transaction === true) { if (results.find(result => typeof result.error === 'object')) { return req.config.database.abortTransactionalSession().then(() => { return Promise.reject({ response: results }); }); } else { return req.config.database.commitTransactionalSession().then(() => { return { response: results }; }); } } else { return { response: results }; } }).catch(error => { if (error && error.response && error.response.find(errorItem => typeof errorItem.error === 'object' && errorItem.error.code === 251) && transactionRetries > 0) { return batch(transactionRetries - 1); } throw error; }); }); }; return batch(5); } module.exports = { mountOnto, makeBatchRoutingPathFunction }; //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJQYXJzZSIsInJlcXVpcmUiLCJwYXRoIiwiYmF0Y2hQYXRoIiwibW91bnRPbnRvIiwicm91dGVyIiwicm91dGUiLCJyZXEiLCJoYW5kbGVCYXRjaCIsInBhcnNlVVJMIiwidXJsU3RyaW5nIiwiVVJMIiwiZXJyb3IiLCJ1bmRlZmluZWQiLCJtYWtlQmF0Y2hSb3V0aW5nUGF0aEZ1bmN0aW9uIiwib3JpZ2luYWxVcmwiLCJzZXJ2ZXJVUkwiLCJwdWJsaWNTZXJ2ZXJVUkwiLCJhcGlQcmVmaXhMZW5ndGgiLCJsZW5ndGgiLCJhcGlQcmVmaXgiLCJzbGljZSIsIm1ha2VSb3V0YWJsZVBhdGgiLCJyZXF1ZXN0UGF0aCIsIkVycm9yIiwiSU5WQUxJRF9KU09OIiwicG9zaXgiLCJqb2luIiwicGF0aG5hbWUiLCJsb2NhbFBhdGgiLCJwdWJsaWNQYXRoIiwic3RhcnRzV2l0aExvY2FsIiwic3RhcnRzV2l0aCIsInN0YXJ0c1dpdGhQdWJsaWMiLCJwYXRoTGVuZ3RoVG9Vc2UiLCJNYXRoIiwibWF4IiwibmV3UGF0aCIsIkFycmF5IiwiaXNBcnJheSIsImJvZHkiLCJyZXF1ZXN0cyIsImVuZHNXaXRoIiwiY29uZmlnIiwiYmF0Y2giLCJ0cmFuc2FjdGlvblJldHJpZXMiLCJpbml0aWFsUHJvbWlzZSIsIlByb21pc2UiLCJyZXNvbHZlIiwidHJhbnNhY3Rpb24iLCJkYXRhYmFzZSIsImNyZWF0ZVRyYW5zYWN0aW9uYWxTZXNzaW9uIiwidGhlbiIsInByb21pc2VzIiwibWFwIiwicmVzdFJlcXVlc3QiLCJyb3V0YWJsZVBhdGgiLCJyZXF1ZXN0IiwiYXV0aCIsImluZm8iLCJ0cnlSb3V0ZVJlcXVlc3QiLCJtZXRob2QiLCJyZXNwb25zZSIsInN1Y2Nlc3MiLCJjb2RlIiwibWVzc2FnZSIsImFsbCIsInJlc3VsdHMiLCJmaW5kIiwicmVzdWx0IiwiYWJvcnRUcmFuc2FjdGlvbmFsU2Vzc2lvbiIsInJlamVjdCIsImNvbW1pdFRyYW5zYWN0aW9uYWxTZXNzaW9uIiwiY2F0Y2giLCJlcnJvckl0ZW0iLCJtb2R1bGUiLCJleHBvcnRzIl0sInNvdXJjZXMiOlsiLi4vc3JjL2JhdGNoLmpzIl0sInNvdXJjZXNDb250ZW50IjpbImNvbnN0IFBhcnNlID0gcmVxdWlyZSgncGFyc2Uvbm9kZScpLlBhcnNlO1xuY29uc3QgcGF0aCA9IHJlcXVpcmUoJ3BhdGgnKTtcbi8vIFRoZXNlIG1ldGhvZHMgaGFuZGxlIGJhdGNoIHJlcXVlc3RzLlxuY29uc3QgYmF0Y2hQYXRoID0gJy9iYXRjaCc7XG5cbi8vIE1vdW50cyBhIGJhdGNoLWhhbmRsZXIgb250byBhIFByb21pc2VSb3V0ZXIuXG5mdW5jdGlvbiBtb3VudE9udG8ocm91dGVyKSB7XG4gIHJvdXRlci5yb3V0ZSgnUE9TVCcsIGJhdGNoUGF0aCwgcmVxID0+IHtcbiAgICByZXR1cm4gaGFuZGxlQmF0Y2gocm91dGVyLCByZXEpO1xuICB9KTtcbn1cblxuZnVuY3Rpb24gcGFyc2VVUkwodXJsU3RyaW5nKSB7XG4gIHRyeSB7XG4gICAgcmV0dXJuIG5ldyBVUkwodXJsU3RyaW5nKTtcbiAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICByZXR1cm4gdW5kZWZpbmVkO1xuICB9XG59XG5cbmZ1bmN0aW9uIG1ha2VCYXRjaFJvdXRpbmdQYXRoRnVuY3Rpb24ob3JpZ2luYWxVcmwsIHNlcnZlclVSTCwgcHVibGljU2VydmVyVVJMKSB7XG4gIHNlcnZlclVSTCA9IHNlcnZlclVSTCA/IHBhcnNlVVJMKHNlcnZlclVSTCkgOiB1bmRlZmluZWQ7XG4gIHB1YmxpY1NlcnZlclVSTCA9IHB1YmxpY1NlcnZlclVSTCA/IHBhcnNlVVJMKHB1YmxpY1NlcnZlclVSTCkgOiB1bmRlZmluZWQ7XG5cbiAgY29uc3QgYXBpUHJlZml4TGVuZ3RoID0gb3JpZ2luYWxVcmwubGVuZ3RoIC0gYmF0Y2hQYXRoLmxlbmd0aDtcbiAgbGV0IGFwaVByZWZpeCA9IG9yaWdpbmFsVXJsLnNsaWNlKDAsIGFwaVByZWZpeExlbmd0aCk7XG5cbiAgY29uc3QgbWFrZVJvdXRhYmxlUGF0aCA9IGZ1bmN0aW9uIChyZXF1ZXN0UGF0aCkge1xuICAgIC8vIFRoZSByb3V0YWJsZVBhdGggaXMgdGhlIHBhdGggbWludXMgdGhlIGFwaSBwcmVmaXhcbiAgICBpZiAocmVxdWVzdFBhdGguc2xpY2UoMCwgYXBpUHJlZml4Lmxlbmd0aCkgIT0gYXBpUHJlZml4KSB7XG4gICAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoUGFyc2UuRXJyb3IuSU5WQUxJRF9KU09OLCAnY2Fubm90IHJvdXRlIGJhdGNoIHBhdGggJyArIHJlcXVlc3RQYXRoKTtcbiAgICB9XG4gICAgcmV0dXJuIHBhdGgucG9zaXguam9pbignLycsIHJlcXVlc3RQYXRoLnNsaWNlKGFwaVByZWZpeC5sZW5ndGgpKTtcbiAgfTtcblxuICBpZiAoc2VydmVyVVJMICYmIHB1YmxpY1NlcnZlclVSTCAmJiBzZXJ2ZXJVUkwucGF0aG5hbWUgIT0gcHVibGljU2VydmVyVVJMLnBhdGhuYW1lKSB7XG4gICAgY29uc3QgbG9jYWxQYXRoID0gc2VydmVyVVJMLnBhdGhuYW1lO1xuICAgIGNvbnN0IHB1YmxpY1BhdGggPSBwdWJsaWNTZXJ2ZXJVUkwucGF0aG5hbWU7XG5cbiAgICAvLyBPdmVycmlkZSB0aGUgYXBpIHByZWZpeFxuICAgIGFwaVByZWZpeCA9IGxvY2FsUGF0aDtcbiAgICByZXR1cm4gZnVuY3Rpb24gKHJlcXVlc3RQYXRoKSB7XG4gICAgICAvLyBGaWd1cmUgb3V0IHdoaWNoIHNlcnZlciB1cmwgd2FzIHVzZWQgYnkgZmlndXJpbmcgb3V0IHdoaWNoXG4gICAgICAvLyBwYXRoIG1vcmUgY2xvc2VseSBtYXRjaGVzIHJlcXVlc3RQYXRoXG4gICAgICBjb25zdCBzdGFydHNXaXRoTG9jYWwgPSByZXF1ZXN0UGF0aC5zdGFydHNXaXRoKGxvY2FsUGF0aCk7XG4gICAgICBjb25zdCBzdGFydHNXaXRoUHVibGljID0gcmVxdWVzdFBhdGguc3RhcnRzV2l0aChwdWJsaWNQYXRoKTtcbiAgICAgIGNvbnN0IHBhdGhMZW5ndGhUb1VzZSA9XG4gICAgICAgIHN0YXJ0c1dpdGhMb2NhbCAmJiBzdGFydHNXaXRoUHVibGljXG4gICAgICAgICAgPyBNYXRoLm1heChsb2NhbFBhdGgubGVuZ3RoLCBwdWJsaWNQYXRoLmxlbmd0aClcbiAgICAgICAgICA6IHN0YXJ0c1dpdGhMb2NhbFxuICAgICAgICAgICAgPyBsb2NhbFBhdGgubGVuZ3RoXG4gICAgICAgICAgICA6IHB1YmxpY1BhdGgubGVuZ3RoO1xuXG4gICAgICBjb25zdCBuZXdQYXRoID0gcGF0aC5wb3NpeC5qb2luKCcvJywgbG9jYWxQYXRoLCAnLycsIHJlcXVlc3RQYXRoLnNsaWNlKHBhdGhMZW5ndGhUb1VzZSkpO1xuXG4gICAgICAvLyBVc2UgdGhlIG1ldGhvZCBmb3IgbG9jYWwgcm91dGluZ1xuICAgICAgcmV0dXJuIG1ha2VSb3V0YWJsZVBhdGgobmV3UGF0aCk7XG4gICAgfTtcbiAgfVxuXG4gIHJldHVybiBtYWtlUm91dGFibGVQYXRoO1xufVxuXG4vLyBSZXR1cm5zIGEgcHJvbWlzZSBmb3IgYSB7cmVzcG9uc2V9IG9iamVjdC5cbi8vIFRPRE86IHBhc3MgYWxvbmcgYXV0aCBjb3JyZWN0bHlcbmZ1bmN0aW9uIGhhbmRsZUJhdGNoKHJvdXRlciwgcmVxKSB7XG4gIGlmICghQXJyYXkuaXNBcnJheShyZXEuYm9keS5yZXF1ZXN0cykpIHtcbiAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoUGFyc2UuRXJyb3IuSU5WQUxJRF9KU09OLCAncmVxdWVzdHMgbXVzdCBiZSBhbiBhcnJheScpO1xuICB9XG5cbiAgLy8gVGhlIGJhdGNoIHBhdGhzIGFyZSBhbGwgZnJvbSB0aGUgcm9vdCBvZiBvdXIgZG9tYWluLlxuICAvLyBUaGF0IG1lYW5zIHRoZXkgaW5jbHVkZSB0aGUgQVBJIHByZWZpeCwgdGhhdCB0aGUgQVBJIGlzIG1vdW50ZWRcbiAgLy8gdG8uIEhvd2V2ZXIsIG91ciBwcm9taXNlIHJvdXRlciBkb2VzIG5vdCByb3V0ZSB0aGUgYXBpIHByZWZpeC4gU29cbiAgLy8gd2UgbmVlZCB0byBmaWd1cmUgb3V0IHRoZSBBUEkgcHJlZml4LCBzbyB0aGF0IHdlIGNhbiBzdHJpcCBpdFxuICAvLyBmcm9tIGFsbCB0aGUgc3VicmVxdWVzdHMuXG4gIGlmICghcmVxLm9yaWdpbmFsVXJsLmVuZHNXaXRoKGJhdGNoUGF0aCkpIHtcbiAgICB0aHJvdyAnaW50ZXJuYWwgcm91dGluZyBwcm9ibGVtIC0gZXhwZWN0ZWQgdXJsIHRvIGVuZCB3aXRoIGJhdGNoJztcbiAgfVxuXG4gIGNvbnN0IG1ha2VSb3V0YWJsZVBhdGggPSBtYWtlQmF0Y2hSb3V0aW5nUGF0aEZ1bmN0aW9uKFxuICAgIHJlcS5vcmlnaW5hbFVybCxcbiAgICByZXEuY29uZmlnLnNlcnZlclVSTCxcbiAgICByZXEuY29uZmlnLnB1YmxpY1NlcnZlclVSTFxuICApO1xuXG4gIGNvbnN0IGJhdGNoID0gdHJhbnNhY3Rpb25SZXRyaWVzID0+IHtcbiAgICBsZXQgaW5pdGlhbFByb21pc2UgPSBQcm9taXNlLnJlc29sdmUoKTtcbiAgICBpZiAocmVxLmJvZHkudHJhbnNhY3Rpb24gPT09IHRydWUpIHtcbiAgICAgIGluaXRpYWxQcm9taXNlID0gcmVxLmNvbmZpZy5kYXRhYmFzZS5jcmVhdGVUcmFuc2FjdGlvbmFsU2Vzc2lvbigpO1xuICAgIH1cblxuICAgIHJldHVybiBpbml0aWFsUHJvbWlzZS50aGVuKCgpID0+IHtcbiAgICAgIGNvbnN0IHByb21pc2VzID0gcmVxLmJvZHkucmVxdWVzdHMubWFwKHJlc3RSZXF1ZXN0ID0+IHtcbiAgICAgICAgY29uc3Qgcm91dGFibGVQYXRoID0gbWFrZVJvdXRhYmxlUGF0aChyZXN0UmVxdWVzdC5wYXRoKTtcblxuICAgICAgICAvLyBDb25zdHJ1Y3QgYSByZXF1ZXN0IHRoYXQgd2UgY2FuIHNlbmQgdG8gYSBoYW5kbGVyXG4gICAgICAgIGNvbnN0IHJlcXVlc3QgPSB7XG4gICAgICAgICAgYm9keTogcmVzdFJlcXVlc3QuYm9keSxcbiAgICAgICAgICBjb25maWc6IHJlcS5jb25maWcsXG4gICAgICAgICAgYXV0aDogcmVxLmF1dGgsXG4gICAgICAgICAgaW5mbzogcmVxLmluZm8sXG4gICAgICAgIH07XG5cbiAgICAgICAgcmV0dXJuIHJvdXRlci50cnlSb3V0ZVJlcXVlc3QocmVzdFJlcXVlc3QubWV0aG9kLCByb3V0YWJsZVBhdGgsIHJlcXVlc3QpLnRoZW4oXG4gICAgICAgICAgcmVzcG9uc2UgPT4ge1xuICAgICAgICAgICAgcmV0dXJuIHsgc3VjY2VzczogcmVzcG9uc2UucmVzcG9uc2UgfTtcbiAgICAgICAgICB9LFxuICAgICAgICAgIGVycm9yID0+IHtcbiAgICAgICAgICAgIHJldHVybiB7IGVycm9yOiB7IGNvZGU6IGVycm9yLmNvZGUsIGVycm9yOiBlcnJvci5tZXNzYWdlIH0gfTtcbiAgICAgICAgICB9XG4gICAgICAgICk7XG4gICAgICB9KTtcblxuICAgICAgcmV0dXJuIFByb21pc2UuYWxsKHByb21pc2VzKVxuICAgICAgICAudGhlbihyZXN1bHRzID0+IHtcbiAgICAgICAgICBpZiAocmVxLmJvZHkudHJhbnNhY3Rpb24gPT09IHRydWUpIHtcbiAgICAgICAgICAgIGlmIChyZXN1bHRzLmZpbmQocmVzdWx0ID0+IHR5cGVvZiByZXN1bHQuZXJyb3IgPT09ICdvYmplY3QnKSkge1xuICAgICAgICAgICAgICByZXR1cm4gcmVxLmNvbmZpZy5kYXRhYmFzZS5hYm9ydFRyYW5zYWN0aW9uYWxTZXNzaW9uKCkudGhlbigoKSA9PiB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIFByb21pc2UucmVqZWN0KHsgcmVzcG9uc2U6IHJlc3VsdHMgfSk7XG4gICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgcmV0dXJuIHJlcS5jb25maWcuZGF0YWJhc2UuY29tbWl0VHJhbnNhY3Rpb25hbFNlc3Npb24oKS50aGVuKCgpID0+IHtcbiAgICAgICAgICAgICAgICByZXR1cm4geyByZXNwb25zZTogcmVzdWx0cyB9O1xuICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcmV0dXJuIHsgcmVzcG9uc2U6IHJlc3VsdHMgfTtcbiAgICAgICAgICB9XG4gICAgICAgIH0pXG4gICAgICAgIC5jYXRjaChlcnJvciA9PiB7XG4gICAgICAgICAgaWYgKFxuICAgICAgICAgICAgZXJyb3IgJiZcbiAgICAgICAgICAgIGVycm9yLnJlc3BvbnNlICYmXG4gICAgICAgICAgICBlcnJvci5yZXNwb25zZS5maW5kKFxuICAgICAgICAgICAgICBlcnJvckl0ZW0gPT4gdHlwZW9mIGVycm9ySXRlbS5lcnJvciA9PT0gJ29iamVjdCcgJiYgZXJyb3JJdGVtLmVycm9yLmNvZGUgPT09IDI1MVxuICAgICAgICAgICAgKSAmJlxuICAgICAgICAgICAgdHJhbnNhY3Rpb25SZXRyaWVzID4gMFxuICAgICAgICAgICkge1xuICAgICAgICAgICAgcmV0dXJuIGJhdGNoKHRyYW5zYWN0aW9uUmV0cmllcyAtIDEpO1xuICAgICAgICAgIH1cbiAgICAgICAgICB0aHJvdyBlcnJvcjtcbiAgICAgICAgfSk7XG4gICAgfSk7XG4gIH07XG4gIHJldHVybiBiYXRjaCg1KTtcbn1cblxubW9kdWxlLmV4cG9ydHMgPSB7XG4gIG1vdW50T250byxcbiAgbWFrZUJhdGNoUm91dGluZ1BhdGhGdW5jdGlvbixcbn07XG4iXSwibWFwcGluZ3MiOiI7O0FBQUEsTUFBTUEsS0FBSyxHQUFHQyxPQUFPLENBQUMsWUFBWSxDQUFDLENBQUNELEtBQUs7QUFDekMsTUFBTUUsSUFBSSxHQUFHRCxPQUFPLENBQUMsTUFBTSxDQUFDO0FBQzVCO0FBQ0EsTUFBTUUsU0FBUyxHQUFHLFFBQVE7O0FBRTFCO0FBQ0EsU0FBU0MsU0FBU0EsQ0FBQ0MsTUFBTSxFQUFFO0VBQ3pCQSxNQUFNLENBQUNDLEtBQUssQ0FBQyxNQUFNLEVBQUVILFNBQVMsRUFBRUksR0FBRyxJQUFJO0lBQ3JDLE9BQU9DLFdBQVcsQ0FBQ0gsTUFBTSxFQUFFRSxHQUFHLENB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