UNPKG

@altostra/core

Version:

Core library for shared types and logic

1 lines • 20 kB
"use strict";var _BuildsManager_instances,_a,_BuildsManager_endpoints,_BuildsManager_projectsManager,_BuildsManager_git,_BuildsManager_customPresigning,_BuildsManager__git_get,_BuildsManager_validateRepositoryIsClean,_BuildsManager_collectMetadata,_BuildsManager_getUserId,_BuildsManager_getCommitHash,_BuildsManager_validateProjectIsNotEmpty,_BuildsManager_getPackageFiles,_BuildsManager_getProjectIdFromName,_BuildsManager_getPresignedUrls,_BuildsManager_isIgnoredFile,_BuildsManager_zipFiles,_BuildsManager_validateRequiredFilesExistence,_BuildsManager_isVersionAvailable,_BuildsManager_uploadBuiltProject,__createBinding=this&&this.__createBinding||(Object.create?function(e,t,r,i){void 0===i&&(i=r);var a=Object.getOwnPropertyDescriptor(t,r);a&&!("get"in a?!t.__esModule:a.writable||a.configurable)||(a={enumerable:!0,get:function(){return t[r]}}),Object.defineProperty(e,i,a)}:function(e,t,r,i){void 0===i&&(i=r),e[i]=t[r]}),__setModuleDefault=this&&this.__setModuleDefault||(Object.create?function(e,t){Object.defineProperty(e,"default",{enumerable:!0,value:t})}:function(e,t){e.default=t}),__importStar=this&&this.__importStar||function(e){if(e&&e.__esModule)return e;var t={};if(null!=e)for(var r in e)"default"!==r&&Object.prototype.hasOwnProperty.call(e,r)&&__createBinding(t,e,r);return __setModuleDefault(t,e),t},__awaiter=this&&this.__awaiter||function(e,t,r,i){return new(r||(r=Promise))((function(a,s){function n(e){try{l(i.next(e))}catch(e){s(e)}}function o(e){try{l(i.throw(e))}catch(e){s(e)}}function l(e){var t;e.done?a(e.value):(t=e.value,t instanceof r?t:new r((function(e){e(t)}))).then(n,o)}l((i=i.apply(e,t||[])).next())}))},__classPrivateFieldSet=this&&this.__classPrivateFieldSet||function(e,t,r,i,a){if("m"===i)throw new TypeError("Private method is not writable");if("a"===i&&!a)throw new TypeError("Private accessor was defined without a setter");if("function"==typeof t?e!==t||!a:!t.has(e))throw new TypeError("Cannot write private member to an object whose class did not declare it");return"a"===i?a.call(e,r):a?a.value=r:t.set(e,r),r},__classPrivateFieldGet=this&&this.__classPrivateFieldGet||function(e,t,r,i){if("a"===r&&!i)throw new TypeError("Private accessor was defined without a getter");if("function"==typeof t?e!==t||!i:!t.has(e))throw new TypeError("Cannot read private member from an object whose class did not declare it");return"m"===r?i:"a"===r?i.call(e):i?i.value:t.get(e)},__importDefault=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(exports,"__esModule",{value:!0}),exports.TO_DATE_FILTER_QUERY_PARAM=exports.FROM_DATE_FILTER_QUERY_PARAM=exports.NEXT_PAGE_QUERY_PARAM=exports.BuildsManager=exports.defaultConfig=exports.BuildsServiceClientBase=void 0;const fs_1=require("fs"),path_1=__importStar(require("path")),BlueprintHelper_1=require("../../../blueprint/Helpers/BlueprintHelper"),NonEmptyString_1=require("../../../common/CustomTypes/NonEmptyString"),Numerics_1=require("../../../common/CustomTypes/Numerics"),Errors_1=require("../../../common/Errors"),some_1=require("../../../common/Iterable/Operators/some"),Utils_1=require("../../../common/Utils"),Url_1=require("../../../common/Utils/Url"),jwt_1=require("../../../jwt"),primitives_1=require("@altostra/type-validations/lib/primitives"),from_1=require("@reactivex/ix-es2015-cjs/iterable/from"),filter_1=require("@reactivex/ix-es2015-cjs/iterable/operators/filter"),map_1=require("@reactivex/ix-es2015-cjs/iterable/operators/map"),axios_1=__importDefault(require("axios")),axios_retry_1=__importDefault(require("axios-retry")),chalk_1=__importDefault(require("chalk")),ignore_walk_1=__importDefault(require("ignore-walk")),jszip_1=__importDefault(require("jszip")),git_1=require("../../git"),Utils_2=require("../../ProjectManager/Utils"),AltostraProjectsManager_1=require("../AltostraProjectsManager"),common_1=require("../common"),ServiceClientBase_1=require("../ServiceClientBase"),ConfigurableServiceClient_1=require("../ServiceClientBase/ConfigurableServiceClient"),ProjectValidatingServiceClient_1=require("../ServiceClientBase/ProjectValidatingServiceClient"),Types_1=require("./Types");exports.BuildsServiceClientBase=(0,ConfigurableServiceClient_1.ConfigurableServiceClient)((0,ProjectValidatingServiceClient_1.ProjectValidatingServiceClient)(ServiceClientBase_1.ServiceClientBase)),exports.defaultConfig={runWithLimit:common_1.RUN_WITH_LIMIT};const IGNORE_FILE=".altoignore",FILE_CHUNK_SIZE=1e7,CONCURRENT_ZIPPED_FILES=(0,Numerics_1.naturalNumber)(3);class BuildsManager extends exports.BuildsServiceClientBase{constructor({axios:e,endpoints:t,getToken:r,logger:i,config:a,customPresigning:s,errorMapping:n={},git:o}){super({axios:e,getToken:r,logger:i,[ConfigurableServiceClient_1.configSym]:null!=a?a:exports.defaultConfig,[ProjectValidatingServiceClient_1.backofficeUrlSym]:t.backoffice,errorMapping:n}),_BuildsManager_instances.add(this),_BuildsManager_endpoints.set(this,void 0),_BuildsManager_projectsManager.set(this,void 0),_BuildsManager_git.set(this,void 0),_BuildsManager_customPresigning.set(this,void 0),__classPrivateFieldSet(this,_BuildsManager_git,o,"f"),__classPrivateFieldSet(this,_BuildsManager_customPresigning,s,"f"),__classPrivateFieldSet(this,_BuildsManager_endpoints,t,"f"),__classPrivateFieldSet(this,_BuildsManager_projectsManager,new AltostraProjectsManager_1.AltostraProjectsManager({endpoint:t.backoffice,getToken:r,logger:i,axios:e}),"f")}publishNonAltostraProject({project:e,packagePath:t,cfnTemplatePath:r,version:i,requireCommitOnPush:a}){return __awaiter(this,void 0,void 0,(function*(){const s=yield __classPrivateFieldGet(this,_BuildsManager_instances,"m",_BuildsManager_collectMetadata).call(this,a),n=null!==t?yield fs_1.promises.readFile(t):null,o=BuildsManager.getPartsNumberFromPackedFiles(n),l=yield this._withLogging("Getting repository information",()=>__awaiter(this,void 0,void 0,(function*(){const t=yield __classPrivateFieldGet(this,_BuildsManager_instances,"m",_BuildsManager_getPresignedUrls).call(this,{projectId:(0,NonEmptyString_1.nonEmptyString)(e.id),version:i,partsCount:o,projectType:e.type,metadata:s}),r=[];if(!(0,Types_1.isNonAltostraPresignedUrlsResponse)(t,e=>r.push(e)))throw Errors_1.AltoError.create("Server respond with invalid data",{data:{response:t,rejections:r}});return t})));yield this._withLogging("Uploading project parts",()=>__classPrivateFieldGet(this,_BuildsManager_instances,"m",_BuildsManager_uploadBuiltProject).call(this,{projectType:"serverless-framework",project:e,packedFiles:n,presignedUrls:l,version:i,cfnTemplatePath:r}))}))}publish({projectDir:e,version:t,force:r,project:i,initializeProject:a,requireCommitOnPush:s}){return __awaiter(this,void 0,void 0,(function*(){if(r)throw new Errors_1.AltoError("Force pushing is not implemented yet");if(!i){const t=yield this.validateProjectByType(e,"altostra",{initializeProject:a});i=t.project}if(yield this._withLogging("Validating version availability",()=>__awaiter(this,void 0,void 0,(function*(){if(!(yield __classPrivateFieldGet(this,_BuildsManager_instances,"m",_BuildsManager_isVersionAvailable).call(this,t,i.id)))throw Errors_1.AltoError.create(`Version name [${t}] is already in use.`,{data:{version:t,projectId:i.id}})}))),!(null==i?void 0:i.blueprints.length))return;const n=yield this._withLogging("Validating project content",()=>__awaiter(this,void 0,void 0,(function*(){const e=new BlueprintHelper_1.BlueprintHelper(i.blueprints[0]);return __classPrivateFieldGet(this,_BuildsManager_instances,"m",_BuildsManager_validateProjectIsNotEmpty).call(this,e),e}))),o=yield __classPrivateFieldGet(this,_BuildsManager_instances,"m",_BuildsManager_collectMetadata).call(this,s),l=yield this._withLogging("Packing files",()=>BuildsManager.packFiles(e,n)),d=yield this._withLogging("Getting repository information",()=>__awaiter(this,void 0,void 0,(function*(){const e=yield __classPrivateFieldGet(this,_BuildsManager_instances,"m",_BuildsManager_getPresignedUrls).call(this,{projectId:(0,NonEmptyString_1.nonEmptyString)(i.id),version:t,partsCount:BuildsManager.getPartsNumberFromPackedFiles(l),metadata:o});if(!(0,Types_1.isAltostraPresignedUrlsResponse)(e))throw Errors_1.AltoError.create("Server respond with invalid data");return e})));yield this._withLogging("Uploading project parts",()=>__classPrivateFieldGet(this,_BuildsManager_instances,"m",_BuildsManager_uploadBuiltProject).call(this,{projectType:"altostra",project:i,packedFiles:l,presignedUrls:d,version:t}))}))}list(e,t){return __awaiter(this,void 0,void 0,(function*(){const r="string"==typeof e?e:"id"in e?e.id:yield __classPrivateFieldGet(this,_BuildsManager_instances,"m",_BuildsManager_getProjectIdFromName).call(this,e.name),i=getListProjectVersionsUrl(__classPrivateFieldGet(this,_BuildsManager_endpoints,"f").integrations,r,t);try{return yield this._request({request:e=>__awaiter(this,void 0,void 0,(function*(){return yield e.get(i,{headers:yield this._getHeaders()})})),dataValidation:Types_1.isVersionsResponse,errorWrapping:{type:"get-project-versions",message:"Failed to retrieve project versions",data:{projectId:r}}})}catch(t){throw Errors_1.UserFacingError.wrapError(t,{type:"get-project-tags",category:"server-fault",message:"Failed to retrieve project versions",serializedGetter:Utils_1.axiosSerializedError,data:{projectId:r,projectIdOrSelection:e}})}}))}getVersionsSummary(){const e=getVersionsSummaryUrl(__classPrivateFieldGet(this,_BuildsManager_endpoints,"f").integrations);return this._request({request:t=>__awaiter(this,void 0,void 0,(function*(){return yield t.get(e,{headers:yield this._getHeaders()})})),dataValidation:Types_1.isVersionsSummaryResponse})}delete(e,t){return this._request({request:r=>__awaiter(this,void 0,void 0,(function*(){return yield r.delete(getSingleProjectVersionUrl(__classPrivateFieldGet(this,_BuildsManager_endpoints,"f").integrations,e,t),{headers:yield this._getHeaders()})})),dataValidation:primitives_1.any,errorWrapping:{message:"Deletion of the version has failed.\nPlease try again or contact support.",data:{projectId:e,version:t}}})}static packFiles(e,t,r){return __awaiter(this,void 0,void 0,(function*(){const i=yield __classPrivateFieldGet(this,_a,"m",_BuildsManager_getPackageFiles).call(this,e,r);return t&&(yield __classPrivateFieldGet(this,_a,"m",_BuildsManager_validateRequiredFilesExistence).call(this,t,i)),yield __classPrivateFieldGet(this,_a,"m",_BuildsManager_zipFiles).call(this,e,i)}))}static getPartsNumberFromPackedFiles(e){return null!==e?Math.ceil(e.byteLength/1e7):0}static uploadBuiltProject({uploadParams:e,cleanup:t,complete:r,concurrencyLimit:i}){return __awaiter(this,void 0,void 0,(function*(){const{packedFiles:a,presignedUrls:{packageZipUrls:s,uploadId:n},project:o,version:l}=e,d=BuildsManager.getPartsNumberFromPackedFiles(a),_=axios_1.default.create();delete _.defaults.headers.put["Content-Type"],(0,axios_retry_1.default)(_,{retries:3});const c=axios_1.default.create();if(!n&&d>1)throw Errors_1.AltoError.create("Problem has been occurred while trying to upload the project, Please contact support",{data:{projectId:o.id,version:l,uploadId:n,partsNumbers:d}});try{const t=[],u="altostra"===e.projectType?e.presignedUrls.projectJsonSignUrl:e.presignedUrls.cfnTemplateJsonSignUrl;if("altostra"!==e.projectType?t.push(()=>__awaiter(this,void 0,void 0,(function*(){return yield c.put(u,yield fs_1.promises.readFile(e.cfnTemplatePath),{headers:{"Content-Type":"application/json"}})}))):t.push(()=>c.put(u,JSON.stringify(o),{headers:{"Content-Type":"application/json"}})),1===d)t.push(()=>_.put(Object.values(s)[0],a,{headers:{"Content-Type":"application/zip"}}));else if(a){const e=Object.keys(s);for(const r of e){const i=parseInt(r),n=1e7*i,o=1e7*(i+1),l=i<e.length-1?a.slice(n,o):a.slice(n),d=s[i];t.push(()=>_.put(d,l))}}const[,...g]=yield(0,Utils_1.runWithLimit)(i,t),p=g.map((e,t)=>({ETag:e.headers.etag,PartNumber:t+1}));yield r({projectId:o.id,version:l,uploadId:n,parts:p,metadataId:e.presignedUrls.metadataId})}catch(e){try{yield t(o.id,l)}catch(t){throw Errors_1.AltoError.create("Project upload and cleanup error occurred!",{data:{uploadError:e,cleanupError:t}})}throw e}}))}}function getBaseProjectVersionsUrl(e,t){return e+Url_1.asUrl`/projects/${t}/tags`}function getListProjectVersionsUrl(e,t,{pageCursor:r,filter:{date:i}={}}={}){const a=getBaseProjectVersionsUrl(e,t),s=new URLSearchParams;s.append(exports.NEXT_PAGE_QUERY_PARAM,null!=r?r:""),void 0!==(null==i?void 0:i.from)&&s.append(exports.FROM_DATE_FILTER_QUERY_PARAM,n(i.from)),void 0!==(null==i?void 0:i.to)&&s.append(exports.TO_DATE_FILTER_QUERY_PARAM,n(i.to));return s.toString()?`${a}?${s}`:a;function n(e){return""+Number(new Date(e))}}function getSingleProjectVersionUrl(e,t,r){return getBaseProjectVersionsUrl(e,t)+Url_1.asUrl`/${r}`}function getVersionsSummaryUrl(e){return e+Url_1.asUrl`/versions-summary`}exports.BuildsManager=BuildsManager,_a=BuildsManager,_BuildsManager_endpoints=new WeakMap,_BuildsManager_projectsManager=new WeakMap,_BuildsManager_git=new WeakMap,_BuildsManager_customPresigning=new WeakMap,_BuildsManager_instances=new WeakSet,_BuildsManager__git_get=function(){return __classPrivateFieldGet(this,_BuildsManager_git,"f")||__classPrivateFieldSet(this,_BuildsManager_git,new git_1.Git(process.cwd()),"f"),__classPrivateFieldGet(this,_BuildsManager_git,"f")},_BuildsManager_validateRepositoryIsClean=function(){return __awaiter(this,void 0,void 0,(function*(){if(yield __classPrivateFieldGet(this,_BuildsManager_instances,"a",_BuildsManager__git_get).isDirty())throw Errors_1.AltoError.create("The current directory has uncommitted changes.\nPlease commit all changes, stash or discard them, then try again.")}))},_BuildsManager_collectMetadata=function(e){return this._withLogging("Collecting version metadata",()=>__awaiter(this,void 0,void 0,(function*(){let t;const r=yield __classPrivateFieldGet(this,_BuildsManager_instances,"m",_BuildsManager_getUserId).call(this);return e&&(yield __classPrivateFieldGet(this,_BuildsManager_instances,"m",_BuildsManager_validateRepositoryIsClean).call(this),t=yield __classPrivateFieldGet(this,_BuildsManager_instances,"m",_BuildsManager_getCommitHash).call(this)),{createdBy:r,commitSHA:t}})))},_BuildsManager_getUserId=function(){var e;return __awaiter(this,void 0,void 0,(function*(){const{token:t}=yield this._getToken(),r=jwt_1.JwtValidator.decodeUnverified(t.replace(/^Bearer /i,""),{ignoreExpiration:!0,skipSignatureVerification:!0});if("result-failure"===r.type){const{error:t}=r;throw Errors_1.AltoError.create(null!==(e=t.message)&&void 0!==e?e:jwt_1.ErrorCodes[t.code],{data:t})}const{value:i}=r;return(0,NonEmptyString_1.nonEmptyString)(i.user)}))},_BuildsManager_getCommitHash=function(){return __awaiter(this,void 0,void 0,(function*(){return(0,NonEmptyString_1.nonEmptyString)(yield __classPrivateFieldGet(this,_BuildsManager_instances,"a",_BuildsManager__git_get).headHash())}))},_BuildsManager_validateProjectIsNotEmpty=function(e){if(!(0,some_1.some)(e.resources))throw Errors_1.UserFacingError.create("Project is empty and contains no resources.\n\nAn empty project contains no resources to deploy.\nPlease add resources to the project in the designer and then try again.",{category:"user-fault",type:"empty-project"})},_BuildsManager_getPackageFiles=function(e,t){return __awaiter(this,void 0,void 0,(function*(){return t=null!=t?t:__classPrivateFieldGet(this,_a,"m",_BuildsManager_isIgnoredFile),(0,from_1.from)(yield Errors_1.AltoError.wrapPromise((0,ignore_walk_1.default)({path:e,ignoreFiles:[IGNORE_FILE]}),{message:"Unable to list source files. Please verify that you have read permission on project directory."})).pipe((0,filter_1.filter)(r=>!t(e,r)),(0,map_1.map)(e=>(0,path_1.normalize)(e)))}))},_BuildsManager_getProjectIdFromName=function(e){return __awaiter(this,void 0,void 0,(function*(){const{id:t}=yield __classPrivateFieldGet(this,_BuildsManager_projectsManager,"f").getProject({name:e});return t}))},_BuildsManager_getPresignedUrls=function({projectId:e,version:t,partsCount:r,projectType:i,metadata:a}){return __awaiter(this,void 0,void 0,(function*(){if(__classPrivateFieldGet(this,_BuildsManager_customPresigning,"f"))return yield __classPrivateFieldGet(this,_BuildsManager_customPresigning,"f").call(this,e,t,r,i);const s={projectId:e,version:t,partsNumbers:r,projectType:i,metadata:a};return yield this._request({request:e=>__awaiter(this,void 0,void 0,(function*(){return yield e.post(__classPrivateFieldGet(this,_BuildsManager_endpoints,"f").integrations+Url_1.asUrl`/upload/start`,s,{headers:yield this._getHeaders()})})),dataValidation:Types_1.isPresignedUrlsResponse,errorWrapping:{}})}))},_BuildsManager_isIgnoredFile=function(e,t){return t===(0,Utils_2.altostraProject)(e)||function(e){do{if((0,path_1.basename)(e).startsWith("."))return!0;e=(0,path_1.dirname)(e)}while(!r(e));return!1}(t);function r(e){return e===(0,path_1.dirname)(e)}},_BuildsManager_zipFiles=function(e,t){return __awaiter(this,void 0,void 0,(function*(){try{const r=new jszip_1.default,i=(0,from_1.from)(t).pipe((0,map_1.map)(t=>()=>fs_1.promises.readFile(path_1.default.join(e,t)).then(e=>({name:t,data:e}))));return(yield(0,Utils_1.runWithLimit)(CONCURRENT_ZIPPED_FILES,i)).forEach(({name:e,data:t})=>r.file(e,t)),yield r.generateAsync({type:"nodebuffer",compression:"DEFLATE",compressionOptions:{level:9}})}catch(e){throw Errors_1.AltoError.wrapError(e,{message:"Unable to zip source files for upload.\nPlease verify that you have read permission for project files, and that they are not under use."})}}))},_BuildsManager_validateRequiredFilesExistence=function(e,t){return __awaiter(this,void 0,void 0,(function*(){const r=new Set(t),i=[...(yield e.getRequiredFiles()).pipe((0,filter_1.filter)(({path:e})=>!r.has(e)))];if(i.length>0)throw Errors_1.AltoError.create(`The following required files could not be found:\n\t${i.map((function({path:e,requiringResources:[{resource:t},...r]}){const i=r.length>0?` and ${r.length} other resources`:"";return`${chalk_1.default.red(e)} is required by ${t.name} (${t.id})${i}`})).join("\n\t")}\n\n${chalk_1.default.yellowBright(`Please make sure that the above files exist and that they are not ignored by the ${chalk_1.default.bold(IGNORE_FILE)} file.`)}\n`,{data:{missingFiles:i}})}))},_BuildsManager_isVersionAvailable=function(e,t){return __awaiter(this,void 0,void 0,(function*(){try{const{versions:r}=yield this.list(t);return!r.find(t=>t.name===e)}catch(r){throw Errors_1.UserFacingError.wrapError(r,{message:"Version name availability check has failed with an error.",category:"server-fault",type:"version-validity-error",data:{newVersion:e,projectId:t}})}}))},_BuildsManager_uploadBuiltProject=function(e){return __awaiter(this,void 0,void 0,(function*(){const t=this;yield BuildsManager.uploadBuiltProject({uploadParams:e,cleanup:function(e,r){return __awaiter(this,void 0,void 0,(function*(){yield Errors_1.AltoError.wrapPromise(t._request({request:i=>__awaiter(this,void 0,void 0,(function*(){return yield i.delete(__classPrivateFieldGet(t,_BuildsManager_endpoints,"f").integrations+Url_1.asUrl`/projects/${e}/tags/${r}`,{headers:yield t._getHeaders()})})),dataValidation:primitives_1.any,errorWrapping:{}}),{message:"Failed to delete a faulty project",data:{projectId:e,version:r}})}))},complete:function({projectId:e,version:r,uploadId:i,metadataId:a,parts:s}){return __awaiter(this,void 0,void 0,(function*(){const n={projectId:(0,NonEmptyString_1.nonEmptyString)(e),version:r,uploadId:i,parts:s,metadataId:a};yield t._request({request:e=>__awaiter(this,void 0,void 0,(function*(){return yield e.post(__classPrivateFieldGet(t,_BuildsManager_endpoints,"f").integrations+Url_1.asUrl`/upload/complete`,n,{headers:yield t._getHeaders()})})),dataValidation:primitives_1.any,errorWrapping:{}})}))},concurrencyLimit:this.config.runWithLimit})}))},exports.NEXT_PAGE_QUERY_PARAM="next-page",exports.FROM_DATE_FILTER_QUERY_PARAM="from-date",exports.TO_DATE_FILTER_QUERY_PARAM="to-date";