UNPKG

@ycmd/creds

Version:

LSK.js CLI Creds is the easiest way to manage GitHub / Gitlab secrets and credentials

28 lines (23 loc) 11.4 kB
'use strict'; var path = require('path'); var stringify = require('@lsk4/stringify'); var fishbird = require('fishbird'); var promises = require('fs/promises'); var log = require('@lsk4/log'); var err = require('@lsk4/err'); var B = require('axios'); var D = require('libsodium-wrappers'); var fs = require('fs'); function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; } var B__default = /*#__PURE__*/_interopDefault(B); var D__default = /*#__PURE__*/_interopDefault(D); var V=Object.defineProperty;var c=(i,t)=>V(i,"name",{value:t,configurable:!0}),P=(i=>typeof require<"u"?require:typeof Proxy<"u"?new Proxy(i,{get:(t,e)=>(typeof require<"u"?require:t)[e]}):i)(function(i){if(typeof require<"u")return require.apply(this,arguments);throw Error('Dynamic require of "'+i+'" is not supported')});var f=log.createLogger("creds");var j=class{static{c(this,"Service");}client;log=log.createLogger(this.constructor.name);constructor(t){this.assign(t),this.checkConfig(),this.client=this.createClient(t.clientOptions);}createClient(t={}){return B__default.default.create(t)}assign(t){Object.assign(this,t);}checkConfig(){throw new err.Err("NOT_IMPLEMENTED","checkConfig method not implemented")}getServiceHostname(){throw new err.Err("NOT_IMPLEMENTED","getServiceHostname method not implemented")}getProjectUrl(){throw new err.Err("NOT_IMPLEMENTED","getProjectUrl method not implemented")}getProjectCICDSettingURL(){throw new err.Err("NOT_IMPLEMENTED","getProjectCICDSettingURL method not implemented")}getProjectPath(){let t=this.projectPath;if(!t)throw new err.Err("!projectPath");return t}getProjectId(){return this.projectId}getProjectCredsUrl(){let t=this.projectCredsUrl;if(!t)throw new err.Err("!projectCredsUrl");return t}getProjectCredsOwner(){let t=this.projectCredsOwner;if(!t)throw new err.Err("!projectCredsOwner");return t}async uploadSecret(t,e){throw new err.Err("NOT_IMPLEMENTED","uploadSecret method not implemented")}async uploadVariable(t,e){throw new err.Err("NOT_IMPLEMENTED","uploadVariable method not implemented")}async removeOldHooks(){}async uploadHook(t){}async uploadHooks(t){if(!t)throw new err.Err("!env");let{hooks:e=[]}=t;try{await this.removeOldHooks();}catch(o){this.log.error("[ERR] Old hooks removing failed:",err.Err.getMessage(o));}await fishbird.map(e,async(o,r)=>{try{await this.uploadHook(o),this.log.info(`[OK] Hook ${r} uploaded`);}catch(a){this.log.error(`[ERR] Hook ${r} not uploaded:`,err.Err.getMessage(a));}});}async uploadAll(t){if(!t)throw new err.Err("!env");let{secrets:e={},variables:o={},files:r=[]}=t;await this.uploadHooks(t),await fishbird.map(Object.entries(e),async([a,s])=>{try{await this.uploadSecret(a,s),this.log.info(`[OK] Secret ${a} uploaded`);}catch(n){this.log.error(`[ERR] Secret ${a} not uploaded as secret, because`,err.Err.getMessage(n)),this.log.trace(n);}}),await fishbird.map(Object.entries(o),async([a,s])=>{try{await this.uploadVariable(a,s),this.log.info(`[OK] Variable ${a} uploaded`);}catch(n){this.log.error(`[ERR] Variable ${a} not uploaded as variable, because`,err.Err.getMessage(n)),this.log.trace(n);}}),await fishbird.map(Object.values(r),async({name:a,credType:s,content:n})=>{let h=a,u=n;try{if(s==="variable")await this.uploadVariable(h,u);else if(s==="secret")await this.uploadSecret(h,u);else if(s==="skip"){this.log.debug(`[SKIP] File ${h} uploaded as ${s}`);return}else throw new err.Err("unknown credType",{credType:s});this.log.info(`[OK] File ${h} uploaded as ${s}`);}catch(m){this.log.error(`[ERR] File ${h} not uploaded as ${s}, because`,err.Err.getMessage(m)),this.log.trace(m);}});}};var $=class extends j{static{c(this,"GithubService");}projectName;projectPath;projectCredsUrl;projectCredsOwner;token;server;log=log.createLogger(this.constructor.name);constructor(t){super(t),this.assign(t),this.checkConfig(),this.client=this.createClient(t.clientOptions);}checkConfig(){if(!this.projectName)throw new err.Err("!projectName");if(!this.projectPath)throw new err.Err("!projectPath");if(!this.projectCredsUrl)throw new err.Err("!projectCredsUrl");if(!this.projectCredsOwner)throw new err.Err("!projectCredsOwner");if(!this.token)throw new err.Err("!token")}createClient(t={}){let o=`https://${this.server||"api.github.com"}/repos/${this.getProjectPath()}`;return B__default.default.create({baseURL:o,headers:{Accept:"application/vnd.github+json",Authorization:`Bearer ${this.token}`,"X-GitHub-Api-Version":"2022-11-28"},...t})}getServiceHostname(){return "github.com"}getProjectPath(){return this.projectPath}getProjectUrl(){return `https://${this.getServiceHostname()}/${this.getProjectPath()}`}getProjectCICDSettingURL(){return `${this.getProjectUrl()}/settings/secrets/actions`}async uploadSecret(t,e){let{data:o}=await this.client({method:"get",url:"/actions/secrets/public-key"}).catch(m=>{throw new err.Err(m.message,{data:m?.response?.data})}),r=typeof e=="string"?e:e.value;if(!o?.key)throw new err.Err("!publicKey");if(!o?.key_id)throw new err.Err("!publicKeyId");await D__default.default.ready;let a=D__default.default,s=a.from_base64(o.key,a.base64_variants.ORIGINAL),n=a.from_string(r),h=a.crypto_box_seal(n,s),u=a.to_base64(h,a.base64_variants.ORIGINAL);await this.client({method:"put",url:`/actions/secrets/${t}`,data:{encrypted_value:u,key_id:o.key_id}});}async uploadVariable(t,e){let o=typeof e=="string"?e:e.value,{data:r,status:a}=await this.client({method:"get",url:`/actions/variables/${t}`}).catch(s=>s?.response);a===404&&await this.client({method:"post",url:"/actions/variables",data:{name:t,value:o}}),a===200&&r.name.toLowerCase()===t.toLowerCase()&&await this.client({method:"patch",url:`/actions/variables/${t}`,data:{name:t,value:o}});}uploadHook(){throw new err.Err("Github hooks not supported yet")}};var S=!0,k=class extends j{static{c(this,"GitlabService");}projectId;projectName;projectPath;projectCredsUrl;projectCredsOwner;token;server;force=!0;log=log.createLogger(this.constructor.name);constructor(t){super(t),this.assign(t),this.checkConfig(),this.client=this.createClient(t.clientOptions);}checkConfig(){if(!this.projectId)throw new err.Err("!projectId");if(!this.server)throw new err.Err("!server");if(!this.projectName)throw new err.Err("!projectName");if(!this.projectPath)throw new err.Err("!projectPath");if(!this.projectCredsUrl)throw new err.Err("!projectCredsUrl");if(!this.projectCredsOwner)throw new err.Err("!projectCredsOwner");if(!this.token)throw new err.Err("!token")}createClient(t={}){return B__default.default.create({baseURL:`https://${this.server}/api/v4/projects/${this.projectId}`,headers:{"PRIVATE-TOKEN":this.token},...t})}getServiceHostname(){return this.server}getProjectUrl(){return `https://${this.getServiceHostname()}/${this.projectPath}`}getProjectCICDSettingURL(){return `${this.getProjectUrl()}/-/settings/ci_cd`}async uploadVariableOrSecret(t,e,o={}){let r=typeof e=="string"?e:e.value,a=e?.type||o?.type||"file",s=!!(e?.protected??o?.protected??!1),{data:n}=await this.client({method:"get",url:`/variables/${t}`}).catch(h=>{return {data:{value:"@lskjs/creds"}}});if(n.value&&n.value.indexOf("@lskjs/creds")===-1&&!S){this.log.warn(`[IGNORE] Project ${this.projectId} ${t}`);return}await this.client({method:"delete",url:`/variables/${t}`}).catch(()=>{}),await this.client({method:"post",url:"/variables",data:{key:t,value:r,variable_type:a,protected:s,...o}});}async uploadSecret(t,e,o={}){return this.uploadVariableOrSecret(t,e,{type:"file",protected:!!(o.protected??!0)})}async uploadVariable(t,e,o={}){return this.uploadVariableOrSecret(t,e,{type:"env_var",protected:!!(o.protected??!1)})}async uploadEnv(){throw this.log.warn("GitLab uploading env doesn't supported"),new err.Err("NOT_IMPLEMENTED")}async removeOldHooks(){let{data:t}=await this.client({method:"get",url:"/hooks"}).catch(e=>{return {data:{value:"@lskjs/creds"}}});await fishbird.map(t,async({id:e})=>{await this.client({method:"delete",url:`/hooks/${e}`});});}async uploadHook(t){await this.client({method:"post",url:"/hooks",data:t});}};async function U(i,{removeCache:t}={}){try{let e=P(i);return t&&delete P.cache[P.resolve(i)],e}catch(e){if(err.Err.getCode(e)==="MODULE_NOT_FOUND")throw new err.Err(`${i} not found`,e);if(err.Err.getCode(e).startsWith("Dynamic require of")||err.Err.getCode(e).startsWith("ReferenceError: module is not defined in ES module scope"))try{return await import(i)}catch(r){throw err.Err.getCode(r)==="ERR_MODULE_NOT_FOUND"?new err.Err(`${i} not found`,r):new err.Err("importErr",r)}throw new err.Err("requireErr",e)}}c(U,"importRequire");async function x(i){let t=`${i}/config.js`,e=await U(t);return {path:t,config:e.default||e}}c(x,"loadConfig");async function E(i,t={}){let{path:e,config:o}=await x(i),r=o.service?.serviceName;if(!r)throw new err.Err("!serviceName",{data:{configPath:e}});let a,s={...o.service,...t,config:o};if(r==="github")a=new $(s);else if(r==="gitlab")a=new k(s);else throw new err.Err("incorrect serviceName",{serviceName:r});return a}c(E,"createService");async function _(i,t={}){let e=t.log||f,o=t.buildDir||`${i}/build`,r=await E(i,t);await promises.unlink(`${o}`).catch(()=>{}),await promises.mkdir(o,{recursive:!0});let{config:a}=r,{files:s=[]}=a;await fishbird.mapSeries(s,async n=>{let{filename:h,handler:u}=n,m=await u(n,a),{credType:v,name:C}=n,O=stringify.getComment({filename:h,values:[["File type",n.type],["Cred type",v],["Cred name",C],["Server",r.getServiceHostname()],["Project",r.getProjectPath()],["Project ID",r.getProjectId()],["Project Url",r.getProjectUrl()],["CI/CD Setting",r.getProjectCICDSettingURL()]],footer:r.getProjectCredsUrl()&&` Auto generated by ${r.getProjectCredsUrl()} If you want to change something, please contact admin repo: ${r.getProjectCredsOwner()}. `.trim()}),M=n.format||n.type,N=`${o}/${h}`,{status:H}=await stringify.jsonToFile(N,m,{format:M,compare:!t.force,comment:O}),T=path.relative(process.cwd(),N);e.info(`[${H}] ${r.getProjectPath()} (${C})[${v}] => ${T}`);});}c(_,"build");async function y(i){let t=await promises.readdir(i,{withFileTypes:!0});return (await fishbird.map(t,async o=>o.isDirectory()?[{name:o.name,dir:path.resolve(i),filename:path.resolve(i,o.name)},...await y(path.resolve(i,o.name))]:[])).flat()}c(y,"getDirs");async function Pe(i,t={}){let e=await y(i),o=(await fishbird.map(e,async r=>{let{filename:a}=r;return await fs.existsSync(`${a}/index.js`)?r:null})).filter(Boolean);return fishbird.mapSeries(o,async({filename:r})=>{await _(r,t).catch(a=>{f.error(`Build error ${r}: `,err.Err.getMessage(a)),f.error(a);});})}c(Pe,"buildDeep");async function R(i,t){let e=t.buildDir||`${i}/build`,o=await E(i,t),{config:r}=o,{files:a=[],variables:s,secrets:n,hooks:h}=r,u=await fishbird.map(a,async m=>{let{filename:v}=m,C=await promises.readFile(`${e}/${v}`).then(O=>O.toString());return {...m,content:C}});await o.uploadAll({files:u,variables:s,secrets:n,hooks:h});}c(R,"upload");async function He(i,t={}){let e=await y(i),o=(await fishbird.map(e,async r=>{let{filename:a}=r;return await fs.existsSync(`${a}/index.js`)?r:null})).filter(Boolean);return fishbird.mapSeries(o,async({filename:r})=>{await R(r,t).catch(a=>{f.error(`Build error ${r}: `,err.Err.getMessage(a)),f.error(a);});})}c(He,"uploadDeep"); exports.build = _; exports.buildDeep = Pe; exports.upload = R; exports.uploadDeep = He; //# sourceMappingURL=out.js.map //# sourceMappingURL=index.js.map