UNPKG

synapse-react-client

Version:

[![Build Status](https://travis-ci.com/Sage-Bionetworks/Synapse-React-Client.svg?branch=main)](https://travis-ci.com/Sage-Bionetworks/Synapse-React-Client) [![npm version](https://badge.fury.io/js/synapse-react-client.svg)](https://badge.fury.io/js/synaps

966 lines 91.9 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.getWikiAttachmentsFromEvaluation = exports.getWikiAttachmentsFromEntity = exports.getWikiPageKeyForAccessRequirement = exports.getWikiPageKeyForEntity = exports.getTeamList = exports.getUserTeamList = exports.getUserChallenges = exports.removeUserFavorite = exports.getUserFavorites = exports.getEntityWiki = exports.getEntityBundleV2 = exports.deleteEntity = exports.updateEntity = exports.getEntityHeader = exports.getEntityHeaders = exports.getEntityHeadersByIds = exports.getEntity = exports.getBulkFiles = exports.getFiles = exports.lookupChildEntity = exports.getEntityChildren = exports.getUserProfiles = exports.getGroupHeadersBatch = exports.getUserGroupHeaders = exports.getUserBundle = exports.getUserProfileById = exports.getUserProfile = exports.createProject = exports.createEntity = exports.oAuthSessionRequest = exports.oAuthUrlRequest = exports.login = exports.getFullQueryTableResults = exports.getQueryTableResults = exports.getAsyncResultFromJobId = exports.getFileHandleByIdURL = exports.getActualFileHandleByIdURL = exports.getFileHandleById = exports.getDownloadFromTableRequest = exports.addFilesToDownloadList = exports.getVersion = exports.doPut = exports.doDelete = exports.doGet = exports.doPost = exports.delay = exports.getRootURL = exports.SYNAPSE_STORAGE_LOCATION_ID = exports.ACCESS_TOKEN_COOKIE_KEY = exports.IS_OUTSIDE_SYNAPSE_ORG = void 0; exports.getAccessRequirement = exports.getRestrictionInformation = exports.getProjectStatistics = exports.rejectFormData = exports.acceptFormData = exports.listFormDataAsFormAdmin = exports.listFormData = exports.submitFormData = exports.deleteFormData = exports.updateFormData = exports.createFormData = exports.updateFormACL = exports.getFormACL = exports.createFormGroup = exports.consentToOAuth2Request = exports.getAuthenticatedOn = exports.getOAuth2Client = exports.hasUserAuthorizedOAuthClient = exports.getOAuth2RequestDescription = exports.getEvaluationSubmissions = exports.deleteEvaluationRound = exports.updateEvaluationRound = exports.createEvaluationRound = exports.getEvaluationRoundsList = exports.getEvaluationRound = exports.deleteEvaluation = exports.createEvaluation = exports.updateEvaluation = exports.getEvaluation = exports.getEvaluationPermissions = exports.submitToEvaluation = exports.createACL = exports.addFilesToDownloadListV2 = exports.createManifestFromDownloadListV2 = exports.createPackageFromDownloadListV2 = exports.addFileToDownloadListV2 = exports.getFileResult = exports.getFileHandleContent = exports.getFileHandleContentFromID = exports.startMultipartUpload = exports.checkUploadComplete = exports.uploadFile = exports.signOut = exports.detectSSOCode = exports.getPrincipalAliasRequest = exports.getUseUtcTimeFromCookie = exports.getAccessTokenFromCookie = exports.setAccessTokenCookie = exports.isInSynapseExperimentalMode = exports.getPresignedUrlForWikiAttachment = void 0; exports.updateEntityJson = exports.getEntityJson = exports.hasAccessToEntity = exports.getValidationSchema = exports.getSchema = exports.getSchemaValidationResults = exports.getSchemaBinding = exports.cancelDataAccessRequest = exports.submitDataAccessRequest = exports.updateDataAccessRequest = exports.getDataAccessRequestForUpdate = exports.getResearchProject = exports.updateResearchProject = exports.removeItemFromDownloadListV2 = exports.getDownloadListActionsRequired = exports.getDownloadListStatistics = exports.getAvailableFilesToDownload = exports.clearDownloadListV2 = exports.searchEntities = exports.getEntityVersions = exports.getEntityPath = exports.getUserProjects = exports.getMyProjects = exports.deletePersonalAccessToken = exports.getPersonalAccessTokenRecords = exports.createPersonalAccessToken = exports.getTransformSqlWithFacetsRequest = exports.updateTable = exports.deleteDownloadList = exports.deleteDownloadListFiles = exports.getAllOfPaginatedService = exports.getDownloadOrder = exports.getDownloadList = exports.postAccessApproval = exports.getAccessApproval = exports.getAllAccessRequirements = exports.getAccessRequirementStatus = exports.getAccessRequirementById = void 0; var tslib_1 = require("tslib"); var spark_md5_1 = (0, tslib_1.__importDefault)(require("spark-md5")); var universal_cookie_1 = (0, tslib_1.__importDefault)(require("universal-cookie")); var _1 = require("."); var APIConstants_1 = require("./APIConstants"); var dispatchDownloadListChangeEvent_1 = require("./functions/dispatchDownloadListChangeEvent"); var getEndpoint_1 = require("./functions/getEndpoint"); var ObjectUtils_1 = require("./functions/ObjectUtils"); var SynapseConstants_1 = require("./SynapseConstants"); var synapseTypes_1 = require("./synapseTypes/"); var cookies = new universal_cookie_1.default(); // TODO: Create JSON response types for all return types exports.IS_OUTSIDE_SYNAPSE_ORG = window.location.hostname .toLowerCase() .includes('.synapse.org') ? false : true; exports.ACCESS_TOKEN_COOKIE_KEY = 'org.sagebionetworks.security.user.login.token'; // Max size file that we will allow the caller to read into memory (5MB) var MAX_JS_FILE_DOWNLOAD_SIZE = 5242880; // This corresponds to the Synapse-managed S3 storage location: exports.SYNAPSE_STORAGE_LOCATION_ID = 1; var getRootURL = function () { var portString = window.location.port ? ":" + window.location.port : ''; return window.location.protocol + "//" + window.location.hostname + portString + "/"; }; exports.getRootURL = getRootURL; /** * Waits t number of milliseconds * * @export * @param {number} t milliseconds * @returns after t milliseconds */ function delay(t) { return new Promise(function (resolve) { setTimeout(resolve.bind(null, {}), t); }); } exports.delay = delay; /* 0 - no internet connection 429 - Too Many Requests 502 - Bad Gateway 503 - Service Unavailable 504 - Gateway Timeout */ var RETRY_STATUS_CODES = [0, 429, 502, 503, 504]; var fetchWithExponentialTimeout = function (url, options, delayMs) { if (delayMs === void 0) { delayMs = 1000; } return fetch(url, options) .then(function (resp) { return resp .text() .then(function (text) { // try to parse it as json try { var json = JSON.parse(text); return resp.ok ? Promise.resolve(json) : Promise.reject(json); } catch (error) { // failed to parse json, return text return resp.ok ? Promise.resolve(text) : Promise.reject(text); } }) .catch(function (error) { if (resp.ok) { // possible empty response return Promise.resolve({ reason: error, status: resp.status, }); } if (error.reason && resp.status) { // successful return from server but invalid call return Promise.reject((0, tslib_1.__assign)((0, tslib_1.__assign)({}, error), { status: resp.status })); } // This occurs if the response is not ok and does not have json or is empty return Promise.reject({ reason: error, status: resp.status, }); }); }) .catch(function (error) { if (error.status && RETRY_STATUS_CODES.indexOf(error.status) !== -1) { return delay(delayMs).then(function () { return fetchWithExponentialTimeout(url, options, delayMs * 2); }); } else { return Promise.reject(error); } }); }; var doPost = function (url, requestJsonObject, accessToken, initCredentials, endpoint) { var options = { body: JSON.stringify(requestJsonObject), headers: { Accept: '*/*', 'Access-Control-Request-Headers': 'authorization', 'Content-Type': 'application/json', }, method: 'POST', mode: 'cors', credentials: initCredentials, }; if (accessToken) { // @ts-ignore options.headers.authorization = "Bearer " + accessToken; } var usedEndpoint = (0, getEndpoint_1.getEndpoint)(endpoint); return fetchWithExponentialTimeout(usedEndpoint + url, options); }; exports.doPost = doPost; var doGet = function (url, accessToken, initCredentials, endpoint) { var options = { headers: { Accept: '*/*', 'Access-Control-Request-Headers': 'authorization', }, method: 'GET', mode: 'cors', credentials: initCredentials, }; if (accessToken) { // @ts-ignore options.headers.authorization = "Bearer " + accessToken; } var usedEndpoint = (0, getEndpoint_1.getEndpoint)(endpoint); return fetchWithExponentialTimeout(usedEndpoint + url, options); }; exports.doGet = doGet; var doDelete = function (url, accessToken, initCredentials, endpoint) { var options = { headers: { Accept: '*/*', 'Access-Control-Request-Headers': 'authorization', }, method: 'DELETE', mode: 'cors', credentials: initCredentials, }; if (accessToken) { // @ts-ignore options.headers.authorization = "Bearer " + accessToken; } var usedEndpoint = (0, getEndpoint_1.getEndpoint)(endpoint); return fetchWithExponentialTimeout(usedEndpoint + url, options); }; exports.doDelete = doDelete; var doPut = function (url, requestJsonObject, accessToken, initCredentials, endpoint) { var options = { body: JSON.stringify(requestJsonObject), headers: { Accept: '*/*', 'Access-Control-Request-Headers': 'authorization', 'Content-Type': 'application/json', }, method: 'PUT', mode: 'cors', credentials: initCredentials, }; if (accessToken) { // @ts-ignore options.headers.authorization = "Bearer " + accessToken; } var usedEndpoint = (0, getEndpoint_1.getEndpoint)(endpoint); return fetchWithExponentialTimeout(usedEndpoint + url, options); }; exports.doPut = doPut; var getVersion = function () { return (0, exports.doGet)('/repo/v1/version', undefined, undefined, getEndpoint_1.BackendDestinationEnum.REPO_ENDPOINT); }; exports.getVersion = getVersion; /** * https://rest-docs.synapse.org/rest/POST/download/list/add/async/start.html */ //Start an asynchronous job to add files to a user's download list. var addFilesToDownloadList = function (request, accessToken, updateParentState) { return (0, exports.doPost)("/file/v1/download/list/add/async/start", request, accessToken, undefined, getEndpoint_1.BackendDestinationEnum.REPO_ENDPOINT) .then(function (resp) { var requestUrl = "/file/v1/download/list/add/async/get/" + resp.token; return (0, exports.getAsyncResultFromJobId)(requestUrl, accessToken, updateParentState).then(function (data) { (0, dispatchDownloadListChangeEvent_1.dispatchDownloadListChangeEvent)(data.downloadList); return data; }); }) .catch(function (error) { throw error; }); }; exports.addFilesToDownloadList = addFilesToDownloadList; /** * https://rest-docs.synapse.org/rest/POST/entity/id/table/download/csv/async/start.html */ var getDownloadFromTableRequest = function (request, accessToken, updateParentState) { if (accessToken === void 0) { accessToken = undefined; } return (0, exports.doPost)("/repo/v1/entity/" + request.entityId + "/table/download/csv/async/start", request, accessToken, undefined, getEndpoint_1.BackendDestinationEnum.REPO_ENDPOINT) .then(function (resp) { var requestUrl = "/repo/v1/entity/" + request.entityId + "/table/download/csv/async/get/" + resp.token; return (0, exports.getAsyncResultFromJobId)(requestUrl, accessToken, updateParentState); }) .catch(function (error) { throw error; }); }; exports.getDownloadFromTableRequest = getDownloadFromTableRequest; /** * https://rest-docs.synapse.org/rest/GET/fileHandle/handleId.html * Get a FileHandle using its ID. * Note: Only the user that created the FileHandle can access it directly. * @return FileHandle **/ var getFileHandleById = function (handleId, accessToken) { if (accessToken === void 0) { accessToken = undefined; } return (0, exports.doGet)("/file/v1/fileHandle/" + handleId, accessToken, undefined, getEndpoint_1.BackendDestinationEnum.REPO_ENDPOINT); }; exports.getFileHandleById = getFileHandleById; /** * http://rest-docs.synapse.org/rest/GET/file/id.html * Get the actual URL of the file from with an associated object . * @return a short lived presignedURL to be redirected with **/ var getActualFileHandleByIdURL = function (handleId, accessToken, fileAssociateType, fileAssociateId, redirect) { if (accessToken === void 0) { accessToken = undefined; } if (redirect === void 0) { redirect = true; } // get the presigned URL for this file handle association. return (0, exports.doGet)("/file/v1/file/" + handleId + "?fileAssociateType=" + fileAssociateType + "&fileAssociateId=" + fileAssociateId + "&redirect=" + redirect, accessToken, undefined, getEndpoint_1.BackendDestinationEnum.REPO_ENDPOINT); }; exports.getActualFileHandleByIdURL = getActualFileHandleByIdURL; /** * https://rest-docs.synapse.org/rest/GET/fileHandle/handleId/url.html * Note: Only the user that created the FileHandle can use this method for download. * @return a short lived presignedURL to be redirected with **/ var getFileHandleByIdURL = function (handleId, accessToken) { if (accessToken === void 0) { accessToken = undefined; } // get the presigned URL for this file handle return (0, exports.doGet)("/file/v1/fileHandle/" + handleId + "/url?redirect=false", accessToken, undefined, getEndpoint_1.BackendDestinationEnum.REPO_ENDPOINT); }; exports.getFileHandleByIdURL = getFileHandleByIdURL; var getAsyncResultFromJobId = function (urlRequest, accessToken, updateParentState) { if (accessToken === void 0) { accessToken = undefined; } return (0, exports.doGet)(urlRequest, accessToken, undefined, getEndpoint_1.BackendDestinationEnum.REPO_ENDPOINT) .then(function (resp) { // is this the job status? if (resp.jobState && resp.jobState !== 'FAILED') { updateParentState && updateParentState({ asyncJobStatus: resp, }); // still processing, wait for a second and try again return delay(500).then(function () { return (0, exports.getAsyncResultFromJobId)(urlRequest, accessToken, updateParentState); }); } // these must be the query results! return resp; }) .catch(function (error) { throw error; }); }; exports.getAsyncResultFromJobId = getAsyncResultFromJobId; /** * https://rest-docs.synapse.org/rest/POST/entity/id/table/query/nextPage/async/start.html * @param {*} queryBundleRequest * @param {*} accessToken * @param {*} endpoint */ var getQueryTableResults = function (queryBundleRequest, accessToken, updateParentState) { if (accessToken === void 0) { accessToken = undefined; } return (0, exports.doPost)("/repo/v1/entity/" + queryBundleRequest.entityId + "/table/query/async/start", queryBundleRequest, accessToken, undefined, getEndpoint_1.BackendDestinationEnum.REPO_ENDPOINT) .then(function (resp) { return (0, exports.getAsyncResultFromJobId)("/repo/v1/entity/" + queryBundleRequest.entityId + "/table/query/async/get/" + resp.token, accessToken, updateParentState); }) .catch(function (error) { throw error; }); }; exports.getQueryTableResults = getQueryTableResults; /** * Run and return results from queryBundleRequest, queryBundle request must be of the * form: * { * concreteType: String, * query: { * sql: String, * partMask: Number * } * } * @param {*} queryBundleRequest * @param {*} [accessToken=undefined] * @param {boolean} [onlyGetFacets=false] Specify if the query only needs facets and no * data-- (internally this limits the row count to 1 on the request) * @returns Full dataset from synapse table query */ var getFullQueryTableResults = function (queryBundleRequest, accessToken) { if (accessToken === void 0) { accessToken = undefined; } return (0, tslib_1.__awaiter)(void 0, void 0, void 0, function () { var data, offset, query, rest, queryRequest, response, isDone, response_1; var _a; return (0, tslib_1.__generator)(this, function (_b) { switch (_b.label) { case 0: offset = 0; query = queryBundleRequest.query, rest = (0, tslib_1.__rest)(queryBundleRequest, ["query"]); queryRequest = (0, tslib_1.__assign)((0, tslib_1.__assign)({}, rest), { query: (0, tslib_1.__assign)((0, tslib_1.__assign)({}, query), { offset: offset }), partMask: queryBundleRequest.partMask | _1.SynapseConstants.BUNDLE_MASK_QUERY_MAX_ROWS_PER_PAGE }); return [4 /*yield*/, (0, exports.getQueryTableResults)(queryRequest, accessToken)]; case 1: response = _b.sent(); data = response; isDone = response.queryResult.queryResults.rows.length < data.maxRowsPerPage; offset += response.queryResult.queryResults.rows.length; queryRequest.query.limit = data.maxRowsPerPage; // set the limit to the actual max rows per page _b.label = 2; case 2: if (!!isDone) return [3 /*break*/, 4]; queryRequest.query.offset = offset; return [4 /*yield*/, (0, exports.getQueryTableResults)(queryRequest, accessToken)]; case 3: response_1 = _b.sent(); (_a = data.queryResult.queryResults.rows).push.apply(_a, response_1.queryResult.queryResults.rows); isDone = response_1.queryResult.queryResults.rows.length < queryRequest.query.limit; offset += response_1.queryResult.queryResults.rows.length; return [3 /*break*/, 2]; case 4: return [2 /*return*/, data]; } }); }); }; exports.getFullQueryTableResults = getFullQueryTableResults; /** * Log-in using the given username and password. Will return a access token that must be used in * authenticated requests. * https://rest-docs.synapse.org/rest/POST/login2.html */ var login = function (username, password, authenticationReceipt, endpoint) { if (endpoint === void 0) { endpoint = getEndpoint_1.BackendDestinationEnum.REPO_ENDPOINT; } return (0, exports.doPost)('/auth/v1/login2', { username: username, password: password, authenticationReceipt: authenticationReceipt }, undefined, undefined, endpoint); }; exports.login = login; /** * Get redirect url * https://rest-docs.synapse.org/rest/POST/oauth2/authurl.html * @param {*} provider * @param {*} redirectUrl * @param {*} endpoint */ var oAuthUrlRequest = function (provider, redirectUrl, endpoint) { if (endpoint === void 0) { endpoint = getEndpoint_1.BackendDestinationEnum.REPO_ENDPOINT; } return (0, exports.doPost)('/auth/v1/oauth2/authurl', { provider: provider, redirectUrl: redirectUrl }, undefined, undefined, endpoint); }; exports.oAuthUrlRequest = oAuthUrlRequest; /** * Get access token from SSO * https://rest-docs.synapse.org/rest/POST/oauth2/session2.html * @param {*} provider * @param {*} authenticationCode * @param {*} redirectUrl * @param {*} endpoint */ var oAuthSessionRequest = function (provider, authenticationCode, redirectUrl, endpoint) { if (endpoint === void 0) { endpoint = getEndpoint_1.BackendDestinationEnum.REPO_ENDPOINT; } return (0, exports.doPost)('/auth/v1/oauth2/session2', { provider: provider, authenticationCode: authenticationCode, redirectUrl: redirectUrl }, undefined, undefined, endpoint); }; exports.oAuthSessionRequest = oAuthSessionRequest; /** * Create an entity (Project, Folder, File, Table, View) * https://rest-docs.synapse.org/rest/POST/entity.html */ var createEntity = function (entity, accessToken) { return (0, exports.doPost)(APIConstants_1.ENTITY, entity, accessToken, undefined, getEndpoint_1.BackendDestinationEnum.REPO_ENDPOINT); }; exports.createEntity = createEntity; /** * Create a project with the given name. * https://rest-docs.synapse.org/rest/POST/entity.html */ var createProject = function (name, accessToken) { return (0, exports.createEntity)({ name: name, concreteType: 'org.sagebionetworks.repo.model.Project', }, accessToken); }; exports.createProject = createProject; /** * Return this user's UserProfile * https://rest-docs.synapse.org/rest/GET/userProfile.html */ var getUserProfile = function (accessToken) { return (0, exports.doGet)(APIConstants_1.USER_PROFILE, accessToken, undefined, getEndpoint_1.BackendDestinationEnum.REPO_ENDPOINT); }; exports.getUserProfile = getUserProfile; /** * Return any user's UserProfile * https://rest-docs.synapse.org/rest/GET/userProfile.html */ var getUserProfileById = function (accessToken, ownerId) { return (0, exports.doGet)((0, APIConstants_1.USER_PROFILE_ID)(ownerId), accessToken, undefined, getEndpoint_1.BackendDestinationEnum.REPO_ENDPOINT); }; exports.getUserProfileById = getUserProfileById; /** * Return this user's profile bundle * https://rest-docs.synapse.org/rest/org/sagebionetworks/repo/model/UserBundle.html */ var getUserBundle = function (id, mask, accessToken) { return (0, exports.doGet)((0, APIConstants_1.USER_ID_BUNDLE)(id) + "?mask=" + mask, accessToken, undefined, getEndpoint_1.BackendDestinationEnum.REPO_ENDPOINT); }; exports.getUserBundle = getUserBundle; /** * Get Users and Groups that match the given prefix. * http://rest-docs.synapse.org/rest/GET/userGroupHeaders.html */ var getUserGroupHeaders = function (prefix, typeFilter, offset, limit) { if (prefix === void 0) { prefix = ''; } if (typeFilter === void 0) { typeFilter = 'ALL'; } if (offset === void 0) { offset = 0; } if (limit === void 0) { limit = 20; } return (0, exports.doGet)("/repo/v1/userGroupHeaders?prefix=" + prefix + "&typeFilter=" + typeFilter + "&offset=" + offset + "&limit=" + limit, undefined, undefined, getEndpoint_1.BackendDestinationEnum.REPO_ENDPOINT); }; exports.getUserGroupHeaders = getUserGroupHeaders; /** * Return batch of user group headers * https://rest-docs.synapse.org/rest/org/sagebionetworks/repo/model/UserGroupHeaderResponsePage.html */ var getGroupHeadersBatch = function (ids, accessToken) { return (0, exports.doGet)("/repo/v1/userGroupHeaders/batch?ids=" + ids.join(','), accessToken, undefined, getEndpoint_1.BackendDestinationEnum.REPO_ENDPOINT); }; exports.getGroupHeadersBatch = getGroupHeadersBatch; /** * Return the User Profiles for the given list of user IDs * https://rest-docs.synapse.org/rest/POST/userProfile.html */ var getUserProfiles = function (list, accessToken) { if (accessToken === void 0) { accessToken = undefined; } return (0, exports.doPost)(APIConstants_1.USER_PROFILE, { list: list }, accessToken, undefined, getEndpoint_1.BackendDestinationEnum.REPO_ENDPOINT); }; exports.getUserProfiles = getUserProfiles; /** * Return the children (Files/Folders) of the given entity (Project or Folder). * https://rest-docs.synapse.org/rest/POST/entity/children.html */ var getEntityChildren = function (request, accessToken) { if (accessToken === void 0) { accessToken = undefined; } return (0, exports.doPost)('/repo/v1/entity/children', request, accessToken, undefined, getEndpoint_1.BackendDestinationEnum.REPO_ENDPOINT); }; exports.getEntityChildren = getEntityChildren; /** * Retrieve an entityId for a given parent ID and entity name. * https://rest-docs.synapse.org/rest/POST/entity/child.html */ var lookupChildEntity = function (request, accessToken) { if (accessToken === void 0) { accessToken = undefined; } return (0, exports.doPost)('/repo/v1/entity/child', request, accessToken, undefined, getEndpoint_1.BackendDestinationEnum.REPO_ENDPOINT); }; exports.lookupChildEntity = lookupChildEntity; /** * Get a batch of pre-signed URLs and/or FileHandles for the given list of FileHandleAssociations. * https://rest-docs.synapse.org/rest/POST/fileHandle/batch.html */ var getFiles = function (request, accessToken) { if (accessToken === void 0) { accessToken = undefined; } return (0, exports.doPost)('/file/v1/fileHandle/batch', request, accessToken, undefined, getEndpoint_1.BackendDestinationEnum.REPO_ENDPOINT); }; exports.getFiles = getFiles; /** * Get a batch of pre-signed URLs and/or FileHandles for the given list of FileHandleAssociations. * https://rest-docs.synapse.org/rest/POST/fileHandle/batch.html */ var getBulkFiles = function (bulkFileDownloadRequest, accessToken) { if (accessToken === void 0) { accessToken = undefined; } return (0, exports.doPost)('/file/v1/file/bulk/async/start', bulkFileDownloadRequest, accessToken, undefined, getEndpoint_1.BackendDestinationEnum.REPO_ENDPOINT) .then(function (asyncJobId) { var urlRequest = "/file/v1/file/bulk/async/get/" + asyncJobId.token; return (0, exports.getAsyncResultFromJobId)(urlRequest, accessToken); }) .catch(function (err) { console.error('Error on getBulkFiles ', err); throw err; }); }; exports.getBulkFiles = getBulkFiles; var getEntity = function (accessToken, entityId, versionNumber) { if (accessToken === void 0) { accessToken = undefined; } if (entityId.indexOf('.') > -1) { // PORTALS-1943: we were given an entity Id with a version! var entityTokens = entityId.split('.'); entityId = entityTokens[0]; versionNumber = entityTokens[1]; } var url = versionNumber ? "/repo/v1/entity/" + entityId + "/version/" + versionNumber : "/repo/v1/entity/" + entityId; return (0, exports.doGet)(url, accessToken, undefined, getEndpoint_1.BackendDestinationEnum.REPO_ENDPOINT); }; exports.getEntity = getEntity; /** * Get a list of entity headers given by entity ids * http://rest-docs.synapse.org/rest/GET/entity/type.html */ var getEntityHeadersByIds = function (entityIds, accessToken) { return (0, exports.doGet)("/repo/v1/entity/type?batch=" + entityIds.join(','), accessToken, undefined, getEndpoint_1.BackendDestinationEnum.REPO_ENDPOINT); }; exports.getEntityHeadersByIds = getEntityHeadersByIds; /** * Get the EntityHeader for a list of references with a POST. * If any item in the batch fails (e.g., with a 404) it will be EXCLUDED in the result set. * https://rest-docs.synapse.org/rest/POST/entity/header.html */ var getEntityHeaders = function (references, accessToken) { // if references contains entity IDs with dot notation, fix the reference object var fixedReferences = references.map(function (reference) { if (reference.targetId.indexOf('.') > -1) { var entityTokens = reference.targetId.split('.'); return { targetId: entityTokens[0], version: entityTokens[1], }; } else return reference; }); return (0, exports.doPost)(APIConstants_1.ENTITY_HEADERS, { references: fixedReferences }, accessToken, undefined, getEndpoint_1.BackendDestinationEnum.REPO_ENDPOINT); }; exports.getEntityHeaders = getEntityHeaders; /** * Get the EntityHeader for a single entity * https://rest-docs.synapse.org/rest/GET/entity/id/type.html */ var getEntityHeader = function (entityId, accessToken) { return (0, exports.doGet)("/repo/v1/entity/" + entityId + "/type", accessToken, undefined, getEndpoint_1.BackendDestinationEnum.REPO_ENDPOINT); }; exports.getEntityHeader = getEntityHeader; var updateEntity = function (entity, accessToken) { if (accessToken === void 0) { accessToken = undefined; } var url = "/repo/v1/entity/" + entity.id; return (0, exports.doPut)(url, entity, accessToken, undefined, getEndpoint_1.BackendDestinationEnum.REPO_ENDPOINT); }; exports.updateEntity = updateEntity; var deleteEntity = function (accessToken, entityId) { if (accessToken === void 0) { accessToken = undefined; } return (0, exports.doDelete)((0, APIConstants_1.ENTITY_ID)(entityId), accessToken, undefined, getEndpoint_1.BackendDestinationEnum.REPO_ENDPOINT); }; exports.deleteEntity = deleteEntity; var getEntityBundleV2 = function (entityId, requestObject, version, accessToken) { return (0, exports.doPost)((0, APIConstants_1.ENTITY_BUNDLE_V2)(entityId, version), requestObject, accessToken, undefined, getEndpoint_1.BackendDestinationEnum.REPO_ENDPOINT); }; exports.getEntityBundleV2 = getEntityBundleV2; /** * Get a corresponding string value of ObjectType: **/ function getObjectTypeToString(key) { return synapseTypes_1.ObjectType[key]; } /** * Get Wiki page contents, call is of the form: * https://rest-docs.synapse.org/rest/GET/entity/ownerId/wiki.html */ var getEntityWiki = function (accessToken, ownerId, wikiId, objectType) { if (wikiId === void 0) { wikiId = ''; } if (objectType === void 0) { objectType = synapseTypes_1.ObjectType.ENTITY; } var objectTypeString = getObjectTypeToString(objectType); var url = "/repo/v1/" + (objectTypeString === null || objectTypeString === void 0 ? void 0 : objectTypeString.toLocaleLowerCase()) + "/" + ownerId + "/wiki/" + wikiId; return (0, exports.doGet)(url, accessToken, undefined, getEndpoint_1.BackendDestinationEnum.REPO_ENDPOINT); }; exports.getEntityWiki = getEntityWiki; /** * Returns synapse user favorites list given their access token * https://rest-docs.synapse.org/rest/GET/favorite.html */ var getUserFavorites = function (accessToken, offset, limit) { if (offset === void 0) { offset = 0; } if (limit === void 0) { limit = 200; } // https://sagebionetworks.jira.com/browse/PLFM-6616 var url = APIConstants_1.FAVORITES + "?offset=" + offset + "&limit=" + limit; return (0, exports.doGet)(url, accessToken, undefined, getEndpoint_1.BackendDestinationEnum.REPO_ENDPOINT); }; exports.getUserFavorites = getUserFavorites; /** * Remove a favorite * http://rest-docs.synapse.org/rest/DELETE/favorite/id.html */ var removeUserFavorite = function (entityId, accessToken) { return (0, exports.doDelete)("/repo/v1/favorite/" + entityId, accessToken, undefined, getEndpoint_1.BackendDestinationEnum.REPO_ENDPOINT); }; exports.removeUserFavorite = removeUserFavorite; /** * Get a list of challenges for which the given user is registered. * see http://rest-docs.synapse.org/rest/GET/challenge.html */ var getUserChallenges = function (accessToken, userId, offset, limit) { if (offset === void 0) { offset = 0; } if (limit === void 0) { limit = 200; } var url = "/repo/v1/challenge?participantId=" + userId + "&offset=" + offset + "&limit=" + limit; return (0, exports.doGet)(url, accessToken, undefined, getEndpoint_1.BackendDestinationEnum.REPO_ENDPOINT); }; exports.getUserChallenges = getUserChallenges; /** * Get the user's list of teams they are on * * @param {*} id ownerID of the synapse user see - https://rest-docs.synapse.org/rest/org/sagebionetworks/repo/model/UserProfile.html */ var getUserTeamList = function (accessToken, userId, offset, limit) { if (offset === void 0) { offset = 0; } if (limit === void 0) { limit = 200; } var url = "/repo/v1/user/" + userId + "/team?offset=" + offset + "&limit=" + limit; return (0, exports.doGet)(url, accessToken, undefined, getEndpoint_1.BackendDestinationEnum.REPO_ENDPOINT); }; exports.getUserTeamList = getUserTeamList; /** * Get the user's list of teams they are on * * @param {*} id ownerID of the synapse user see -https://rest-docs.synapse.org/rest/GET/teamMembers/id.html * @param {*} fragment (optional) a prefix of the user's first or last name or email address (optional) * @param {*} limit (optional) the maximum number of members to return (default 10, max limit 50) * @param {*} offset (optional) the starting index of the returned results (default 0) * */ var getTeamList = function (accessToken, id, fragment, limit, offset) { if (fragment === void 0) { fragment = ''; } if (limit === void 0) { limit = 10; } if (offset === void 0) { offset = 0; } var url = "/repo/v1/teamMembers/" + id + "?limit=" + limit + "&offset=" + offset + (fragment ? "&fragment=" + fragment : ''); return (0, exports.doGet)(url, accessToken, undefined, getEndpoint_1.BackendDestinationEnum.REPO_ENDPOINT); }; exports.getTeamList = getTeamList; /** * https://rest-docs.synapse.org/rest/GET/entity/ownerId/wikikey.html * Get the root WikiPageKey for an Entity. * Note: The caller must be granted the ACCESS_TYPE.READ permission on the owner. * @return WikiPageKey **/ var getWikiPageKeyForEntity = function (accessToken, ownerId) { var url = "/repo/v1/entity/" + ownerId + "/wikikey"; return (0, exports.doGet)(url, accessToken, undefined, getEndpoint_1.BackendDestinationEnum.REPO_ENDPOINT); }; exports.getWikiPageKeyForEntity = getWikiPageKeyForEntity; /** * https://rest-docs.synapse.org/rest/GET/access_requirement/ownerId/wikikey.html * Get the root WikiPageKey for an Access Requirement. * Note: The caller must be granted the ACCESS_TYPE.READ permission on the owner. * @return WikiPageKey **/ var getWikiPageKeyForAccessRequirement = function (accessToken, ownerId) { var url = "/repo/v1/access_requirement/" + ownerId + "/wikikey"; return (0, exports.doGet)(url, accessToken, undefined, getEndpoint_1.BackendDestinationEnum.REPO_ENDPOINT); }; exports.getWikiPageKeyForAccessRequirement = getWikiPageKeyForAccessRequirement; var getWikiAttachmentsFromEntity = function (accessToken, id, wikiId, objectType) { if (objectType === void 0) { objectType = synapseTypes_1.ObjectType.ENTITY; } var objectTypeString = getObjectTypeToString(objectType); var url = "/repo/v1/" + objectTypeString.toLocaleLowerCase() + "/" + id + "/wiki2/" + wikiId + "/attachmenthandles"; return (0, exports.doGet)(url, accessToken, undefined, getEndpoint_1.BackendDestinationEnum.REPO_ENDPOINT); }; exports.getWikiAttachmentsFromEntity = getWikiAttachmentsFromEntity; var getWikiAttachmentsFromEvaluation = function (accessToken, id, wikiId) { var url = "/repo/v1/evaluation/" + id + "/wiki/" + wikiId + "/attachmenthandles"; return (0, exports.doGet)(url, accessToken, undefined, getEndpoint_1.BackendDestinationEnum.REPO_ENDPOINT); }; exports.getWikiAttachmentsFromEvaluation = getWikiAttachmentsFromEvaluation; var getPresignedUrlForWikiAttachment = function (accessToken, id, wikiId, fileName, objectType) { if (objectType === void 0) { objectType = synapseTypes_1.ObjectType.ENTITY; } var objectTypeString = getObjectTypeToString(objectType); var url = "/repo/v1/" + objectTypeString.toLocaleLowerCase() + "/" + id + "/wiki2/" + wikiId + "/attachment?fileName=" + fileName + "&redirect=false"; return (0, exports.doGet)(url, accessToken, undefined, getEndpoint_1.BackendDestinationEnum.REPO_ENDPOINT); }; exports.getPresignedUrlForWikiAttachment = getPresignedUrlForWikiAttachment; var isInSynapseExperimentalMode = function () { // bang bang, you're a boolean! return !!cookies.get(_1.SynapseConstants.EXPERIMENTAL_MODE_COOKIE); }; exports.isInSynapseExperimentalMode = isInSynapseExperimentalMode; /** * Set the access token cookie. Note that this will only succeed if your app is running on * a .synapse.org subdomain. * * @param {*} token Access token. If undefined, then call should instruct the browser to delete the cookie. */ var setAccessTokenCookie = function (token, sessionCallback) { return (0, tslib_1.__awaiter)(void 0, void 0, void 0, function () { return (0, tslib_1.__generator)(this, function (_a) { switch (_a.label) { case 0: if (!exports.IS_OUTSIDE_SYNAPSE_ORG) return [3 /*break*/, 4]; if (!!token) return [3 /*break*/, 2]; cookies.remove(exports.ACCESS_TOKEN_COOKIE_KEY, { path: '/' }); // See - https://github.com/reactivestack/cookies/issues/189 return [4 /*yield*/, delay(100)]; case 1: // See - https://github.com/reactivestack/cookies/issues/189 _a.sent(); return [3 /*break*/, 3]; case 2: // set's cookie in session storage cookies.set(exports.ACCESS_TOKEN_COOKIE_KEY, token, { // expires in a day maxAge: 60 * 60 * 24, path: '/', }); _a.label = 3; case 3: sessionCallback(); return [3 /*break*/, 5]; case 4: // will set cookie in the http header (0, exports.doPost)('Portal/sessioncookie', { sessionToken: token }, undefined, 'include', getEndpoint_1.BackendDestinationEnum.PORTAL_ENDPOINT) .then(function (_) { sessionCallback(); }) .catch(function (err) { console.error('Error on setting access token ', err); }); _a.label = 5; case 5: return [2 /*return*/]; } }); }); }; exports.setAccessTokenCookie = setAccessTokenCookie; /** * Get the current access token from a cookie. Note that this will only succeed if your app is running on * a .synapse.org subdomain. */ var getAccessTokenFromCookie = function () { return (0, tslib_1.__awaiter)(void 0, void 0, void 0, function () { return (0, tslib_1.__generator)(this, function (_a) { if (exports.IS_OUTSIDE_SYNAPSE_ORG) { return [2 /*return*/, cookies.get(exports.ACCESS_TOKEN_COOKIE_KEY)]; } return [2 /*return*/, (0, exports.doGet)('Portal/sessioncookie?validate=true', undefined, 'include', getEndpoint_1.BackendDestinationEnum.PORTAL_ENDPOINT)]; }); }); }; exports.getAccessTokenFromCookie = getAccessTokenFromCookie; var getUseUtcTimeFromCookie = function () { return cookies.get(SynapseConstants_1.DATETIME_UTC_COOKIE_KEY) === 'true'; }; exports.getUseUtcTimeFromCookie = getUseUtcTimeFromCookie; var getPrincipalAliasRequest = function (accessToken, alias, type) { var url = '/repo/v1/principal/alias'; return (0, exports.doPost)(url, { alias: alias, type: type }, accessToken, undefined, getEndpoint_1.BackendDestinationEnum.REPO_ENDPOINT); }; exports.getPrincipalAliasRequest = getPrincipalAliasRequest; /* During SSO login, the authorization provider (Google) will send the user back to the portal with an authorization code, which can be exchanged for a Synapse user session. This function should be called whenever the root App is initialized (to look for this code parameter and complete the round-trip). */ var detectSSOCode = function () { var redirectURL = (0, exports.getRootURL)(); // 'code' handling (from SSO) should be preformed on the root page, and then redirect to original route. var fullUrl = new URL(window.location.href); // in test environment the searchParams isn't defined var searchParams = fullUrl.searchParams; if (!searchParams) { return; } var code = searchParams.get('code'); var provider = searchParams.get('provider'); if (code && provider) { (0, exports.oAuthSessionRequest)(provider, code, redirectURL + "?provider=" + provider, getEndpoint_1.BackendDestinationEnum.REPO_ENDPOINT) .then(function (synToken) { (0, exports.setAccessTokenCookie)(synToken.accessToken, function () { // go back to original route after successful SSO login var originalUrl = localStorage.getItem('after-sso-login-url'); localStorage.removeItem('after-sso-login-url'); if (originalUrl) { window.location.replace(originalUrl); } }); }) .catch(function (err) { if (err.status === 404) { // Synapse account not found, send to registration page window.location.replace(getEndpoint_1.PRODUCTION_ENDPOINT_CONFIG.PORTAL + "#!RegisterAccount:0"); } console.error('Error on sso sign in ', err); }); } }; exports.detectSSOCode = detectSSOCode; var signOut = function (sessionCallback) { return (0, tslib_1.__awaiter)(void 0, void 0, void 0, function () { return (0, tslib_1.__generator)(this, function (_a) { switch (_a.label) { case 0: return [4 /*yield*/, (0, exports.setAccessTokenCookie)(undefined, sessionCallback)]; case 1: _a.sent(); return [2 /*return*/]; } }); }); }; exports.signOut = signOut; /** * Upload file. Note that this currently only supports Synapse storage (Sage s3 bucket) * @param accessToken * @param file * @param endpoint */ var uploadFile = function (accessToken, filename, file) { return new Promise(function (fileUploadResolve, fileUploadReject) { var partSize = Math.max(5242880, file.size / 10000); var request = { contentType: file.type, fileName: filename, fileSizeBytes: file.size, partSizeBytes: partSize, storageLocationId: exports.SYNAPSE_STORAGE_LOCATION_ID, }; calculateMd5(file).then(function (md5) { request.contentMD5Hex = md5; (0, exports.startMultipartUpload)(accessToken, filename, file, request, fileUploadResolve, fileUploadReject); }); }); }; exports.uploadFile = uploadFile; var calculateMd5 = function (fileBlob) { // code taken from md5 example from library return new Promise(function (resolve, reject) { var blobSlice = File.prototype.slice, file = fileBlob, chunkSize = 2097152, // Read in chunks of 2MB chunks = Math.ceil(file.size / chunkSize), spark = new spark_md5_1.default.ArrayBuffer(), fileReader = new FileReader(); var currentChunk = 0; fileReader.onload = function (e) { console.log('read chunk nr', currentChunk + 1, 'of', chunks); spark.append(fileReader.result); // Append array buffer currentChunk++; if (currentChunk < chunks) { loadNext(); } else { console.log('finished loading'); var md5 = spark.end(); console.info('computed hash', md5); // Compute hash resolve(md5); } }; fileReader.onerror = function () { console.warn('oops, something went wrong.'); reject(fileReader.error); }; var loadNext = function () { var start = currentChunk * chunkSize, end = start + chunkSize >= file.size ? file.size : start + chunkSize; fileReader.readAsArrayBuffer(blobSlice.call(file, start, end)); }; loadNext(); }); }; var processFilePart = function (partNumber, multipartUploadStatus, accessToken, fileName, file, request, fileUploadResolve, fileUploadReject) { if (multipartUploadStatus.clientSidePartsState[partNumber - 1]) { // no-op. this part has already been processed! return; } var uploadId = multipartUploadStatus.uploadId; var presignedUploadUrlRequest = { uploadId: uploadId, contentType: 'application/octet-stream', partNumbers: [partNumber], }; var presignedUrlUrl = "/file/v1/file/multipart/" + uploadId + "/presigned/url/batch"; (0, exports.doPost)(presignedUrlUrl, presignedUploadUrlRequest, accessToken, undefined, getEndpoint_1.BackendDestinationEnum.REPO_ENDPOINT).then(function (presignedUrlResponse) { return (0, tslib_1.__awaiter)(void 0, void 0, void 0, function () { var presignedUrl, startByte, endByte, fileSlice; return (0, tslib_1.__generator)(this, function (_a) { switch (_a.label) { case 0: presignedUrl = presignedUrlResponse.partPresignedUrls[0].uploadPresignedUrl; startByte = (partNumber - 1) * request.partSizeBytes; endByte = partNumber * request.partSizeBytes - 1; if (endByte >= request.fileSizeBytes) { endByte = request.fileSizeBytes - 1; } fileSlice = file.slice(startByte, endByte + 1, presignedUploadUrlRequest.contentType); return [4 /*yield*/, uploadFilePart(presignedUrl, fileSlice, presignedUploadUrlRequest.contentType) // uploaded the part. calculate md5 of the part and add the part to the upload ]; case 1: _a.sent(); // uploaded the part. calculate md5 of the part and add the part to the upload calculateMd5(fileSlice).then(function (md5) { var addPartUrl = "/file/v1/file/multipart/" + uploadId + "/add/" + partNumber + "?partMD5Hex=" + md5; (0, exports.doPut)(addPartUrl, undefined, accessToken, undefined, getEndpoint_1.BackendDestinationEnum.REPO_ENDPOINT).then(function (addPartResponse) { if (addPartResponse.addPartState === 'ADD_SUCCESS') { // done with this part! multipartUploadStatus.clientSidePartsState[partNumber - 1] = true; (0, exports.checkUploadComplete)(multipartUploadStatus, fileName, accessToken, fileUploadResolve, fileUploadReject); } else { // retry after a brief delay delay(1000).then(function () { processFilePart(partNumber, multipartUploadStatus, accessToken, fileName, file, request, fileUploadResolve, fileUploadReject); }); } }); }); return [2 /*return*/]; } }); }); }); }; var checkUploadComplete = function (status, fileHandleName, accessToken, fileUploadResolve, fileUploadReject) { // if all client-side parts are true (uploaded), then complete the upload and get the file handle! if (status.clientSidePartsState.every(function (v) { return v; })) { var url = "/file/v1/file/multipart/" + status.uploadId + "/complete"; (0, exports.doPut)(url, undefined, accessToken, undefined, getEndpoint_1.BackendDestinationEnum.REPO_ENDPOINT) .then(function (newStatus) { // success! fileUploadResolve({ fileHandleId: newStatus.resultFileHandleId, fileName: fileHandleName, }); }) .catch(function (error) { fileUploadReject(error); }); } }; exports.checkUploadComplete = checkUploadComplete; var uploadFilePart = function (presignedUrl, file, contentType) { return (0, tslib_1.__awaiter)(void 0, void 0, void 0, function () { return (0, tslib_1.__generator)(this, function (_a) { switch (_a.label) { case 0: // TODO: could try using axios to get upload progress, then update the client-side part state (change to numbers from 0-1) // This would give progress for the single file (across all parts). // The parent would still need to figure out progress (for the total file set). return [4 /*yield*/, fetch(presignedUrl, { method: 'PUT', headers: { 'Content-Type': contentType, }, body: file, })]; case 1: // TODO: could try using axios to get upload progress, then update the client-side part state (change to numbers from 0-1) // This would give progress for the single file (across all parts). // The parent would still need to figure out progress (for the total file set). _a.sent(); return [2 /*return*/]; } }); }); }; var startMultipartUpload = function (accessToken, fileName, file, request, fileUploadResolve, fileUploadReject) { var url = '/file/v1/file/multipart'; (0, exports.doPost)(url, request, accessToken, undefined, getEndpoint_1.BackendDestinationEnum.REPO_ENDPOINT) .then(function (status) { return (0, tslib_1.__awaiter)(void 0, void 0, void 0, function () { var clientSidePartsState, i; return (0, tslib_1.__generator)(this, function (_a) { switch (_a.label) { case 0: clientSidePartsState = status.partsState .split('') .map(function (bit) { return bit === '1'; }); status.clientSidePartsState = clientSidePartsState; i = 0; _a.label = 1; case 1: if (!(i < clientSidePartsState.length)) return [3 /*break*/, 4]; if (!!clientSidePartsState[i]) return [3 /*break*/, 3]; // upload this part. note that partNumber is always the index+1 return [4 /*yield*/, pro