@sinch/cli 0.1.8 → 0.1.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
"use strict";var Hn=Object.create;var Ke=Object.defineProperty;var Gn=Object.getOwnPropertyDescriptor;var Yn=Object.getOwnPropertyNames;var zn=Object.getPrototypeOf,Qn=Object.prototype.hasOwnProperty;var fe=(o,e)=>()=>(o&&(e=o(o=0)),e);var N=(o,e)=>()=>(e||o((e={exports:{}}).exports,e),e.exports),Be=(o,e)=>{for(var n in e)Ke(o,n,{get:e[n],enumerable:!0})},St=(o,e,n,i)=>{if(e&&typeof e=="object"||typeof e=="function")for(let r of Yn(e))!Qn.call(o,r)&&r!==n&&Ke(o,r,{get:()=>e[r],enumerable:!(i=Gn(e,r))||i.enumerable});return o};var m=(o,e,n)=>(n=o!=null?Hn(zn(o)):{},St(e||!o||!o.__esModule?Ke(n,"default",{value:o,enumerable:!0}):n,o)),O=o=>St(Ke({},"__esModule",{value:!0}),o);var Qe=N((yi,Zn)=>{Zn.exports={name:"@sinch/cli",version:"0.1.
|
|
2
|
+
"use strict";var Hn=Object.create;var Ke=Object.defineProperty;var Gn=Object.getOwnPropertyDescriptor;var Yn=Object.getOwnPropertyNames;var zn=Object.getPrototypeOf,Qn=Object.prototype.hasOwnProperty;var fe=(o,e)=>()=>(o&&(e=o(o=0)),e);var N=(o,e)=>()=>(e||o((e={exports:{}}).exports,e),e.exports),Be=(o,e)=>{for(var n in e)Ke(o,n,{get:e[n],enumerable:!0})},St=(o,e,n,i)=>{if(e&&typeof e=="object"||typeof e=="function")for(let r of Yn(e))!Qn.call(o,r)&&r!==n&&Ke(o,r,{get:()=>e[r],enumerable:!(i=Gn(e,r))||i.enumerable});return o};var m=(o,e,n)=>(n=o!=null?Hn(zn(o)):{},St(e||!o||!o.__esModule?Ke(n,"default",{value:o,enumerable:!0}):n,o)),O=o=>St(Ke({},"__esModule",{value:!0}),o);var Qe=N((yi,Zn)=>{Zn.exports={name:"@sinch/cli",version:"0.1.9",description:"Official Sinch CLI - Manage all Sinch products from your terminal",main:"dist/index.js",bin:{sinch:"bin/sinch"},scripts:{start:"tsx src/index.ts",dev:"tsx watch src/index.ts",build:"tsc && node scripts/post-build.js","build:prod":"tsup src/index.ts --format cjs --dts --clean --minify",typecheck:"tsc --noEmit",test:"jest",prepublishOnly:"npm run build:prod"},keywords:[],author:"Sinch <support@sinch.com> (https://www.sinch.com)",license:"MIT",private:!1,publishConfig:{access:"public",registry:"https://registry.npmjs.org/"},homepage:"https://www.sinch.com/products/apis/voice/",files:["dist/","bin/","README.md","LICENSE"],dependencies:{"@sinch/sdk-core":"^1.2.1","adm-zip":"^0.5.10",axios:"^1.7.9",blessed:"^0.1.81",chalk:"^4.1.2",chokidar:"^3.6.0","cli-spinners":"^2.9.2","cli-table3":"^0.6.3",clipboardy:"^2.3.0",commander:"^12.1.0",eventsource:"^4.0.0","form-data":"^4.0.0","fs-extra":"^11.1.1",inquirer:"8.2.6",keytar:"^7.9.0",ora:"^4.1.1"},devDependencies:{"@types/adm-zip":"^0.5.7","@types/blessed":"^0.1.25","@types/fs-extra":"^11.0.4","@types/inquirer":"^9.0.9","@types/keytar":"^4.4.0","@types/node":"^24.3.0",jest:"^29.7.0",nodemon:"^3.0.1",tsup:"^8.5.0",tsx:"^4.20.4",typescript:"^5.9.2"},engines:{node:">=20.0.0",npm:">=9.0.0"}}});var De={};Be(De,{SinchAPI:()=>A});var Ve,Xe,ke,A,L=fe(()=>{"use strict";Ve=m(require("axios")),Xe=m(require("form-data")),ke=m(require("chalk")),A=class{baseUrl;projectId;timeout;credentials;client;constructor(e={}){this.baseUrl=e.apiUrl||"https://functions.api.sinch.com/",this.projectId=e.projectId||"",this.timeout=e.timeout||3e4,this.credentials=e.credentials||null,this.client=Ve.default.create({baseURL:this.baseUrl,timeout:this.timeout,headers:{"User-Agent":"sinch-functions-cli/1.0.0"}}),this.client.interceptors.request.use(async n=>{if(this.credentials){let i=await this.getValidToken();i&&(n.headers.Authorization=`${i.token_type} ${i.access_token}`)}return process.env.DEBUG_HTTP&&console.log(ke.default.gray(`\u2192 ${n.method?.toUpperCase()} ${n.url}`)),n},n=>Promise.reject(n)),this.client.interceptors.response.use(n=>(process.env.DEBUG_HTTP&&console.log(ke.default.gray(`\u2190 ${n.status} ${n.config.url}`)),n),async n=>{if(process.env.DEBUG_HTTP&&console.log(ke.default.red(`\u2190 ${n.response?.status||"ERROR"} ${n.config?.url}`)),n.response?.status===401&&this.credentials&&n.config){let i=n.config;if(!i._retry){i._retry=!0;try{let r=await this.getValidToken();if(r)return i.headers.Authorization=`${r.token_type} ${r.access_token}`,this.client.request(i)}catch{console.error(ke.default.yellow("Token refresh failed during retry"))}}}return Promise.reject(n)})}async listAllTemplates(e=null){try{let n=e?{category:e}:{};return(await this.client.get(`/v1/projects/${this.projectId}/templates`,{params:n})).data}catch(n){throw this._handleError(n,"Failed to list templates")}}async listRuntimeTemplates(e,n=null){try{let i=n?{category:n}:{};return(await this.client.get(`/v1/projects/${this.projectId}/templates/${e}`,{params:i})).data}catch(i){throw this._handleError(i,`Failed to list ${e} templates`)}}async getTemplateDetails(e,n){try{return(await this.client.get(`/v1/projects/${this.projectId}/templates/${e}/${n}`)).data}catch(i){throw this._handleError(i,`Failed to get template details for ${e}/${n}`)}}async downloadTemplate(e,n){try{let i=await this.client.get(`/v1/projects/${this.projectId}/templates/${e}/${n}/download`,{responseType:"arraybuffer"});return Buffer.from(i.data)}catch(i){throw this._handleError(i,`Failed to download template ${e}/${n}`)}}async listFunctions(){try{return(await this.client.get(`/v1/projects/${this.projectId}/functions`)).data}catch(e){throw this._handleError(e,"Failed to list functions")}}async getFunction(e){try{return(await this.client.get(`/v1/projects/${this.projectId}/functions/${e}`)).data}catch(n){throw this._handleError(n,`Failed to get function ${e}`)}}async deployFunction(e,n,i,r){try{let s=new Xe.default;return s.append("name",e),s.append("runtime",n),s.append("code",i,{filename:"function.zip"}),r&&s.append("configuration",JSON.stringify(r)),(await this.client.post(`/v1/projects/${this.projectId}/functions`,s,{headers:{...s.getHeaders()},maxContentLength:1/0,maxBodyLength:1/0})).data}catch(s){throw this._handleError(s,"Failed to deploy function")}}async updateFunction(e,n,i){try{let r=new Xe.default;return r.append("code",n,{filename:"function.zip"}),i&&r.append("configuration",JSON.stringify(i)),(await this.client.put(`/v1/projects/${this.projectId}/functions/${e}`,r,{headers:{...r.getHeaders()},maxContentLength:1/0,maxBodyLength:1/0})).data}catch(r){throw this._handleError(r,`Failed to update function ${e}`)}}async deleteFunction(e){try{await this.client.delete(`/v1/projects/${this.projectId}/functions/${e}`)}catch(n){throw this._handleError(n,`Failed to delete function ${e}`)}}async downloadFunction(e){try{let n=await this.client.get(`/v1/projects/${this.projectId}/functions/${e}/download`,{responseType:"arraybuffer"});return Buffer.from(n.data)}catch(n){throw this._handleError(n,`Failed to download function ${e}`)}}async getFunctionLogs(e,n={}){try{return(await this.client.get(`/v1/projects/${this.projectId}/functions/${e}/logs`,{params:n})).data}catch(i){throw this._handleError(i,`Failed to get logs for function ${e}`)}}async getFunctionStatus(e){try{return(await this.client.get(`/v1/projects/${this.projectId}/functions/${e}/deployment/status`)).data}catch(n){throw this._handleError(n,`Failed to get status for function ${e}`)}}async generateDocumentationFromCode(e,n="node",i="function"){try{return(await this.client.post(`/v1/projects/${this.projectId}/test/documentation`,{Code:e,Runtime:n,Name:i})).data}catch(r){throw this._handleError(r,"Failed to generate documentation from code")}}async generateDocumentationForFunction(e,n){try{let i=n?{MarkdownOverride:n}:{};return(await this.client.post(`/v1/projects/${this.projectId}/functions/${e}/documentation`,i)).data}catch(i){throw this._handleError(i,`Failed to generate documentation for function ${e}`)}}async getDocumentationForFunction(e){try{return(await this.client.get(`/v1/projects/${this.projectId}/functions/${e}/documentation`)).data}catch(n){throw this._handleError(n,`Failed to get documentation for function ${e}`)}}async streamDeployment(e,n,i){let r=l=>l.status?"status":l.progress?"progress":l.completed?"completed":l.failed||l.error?"failed":l.connected?"connected":"message",s=new URL(`v1/projects/${this.projectId}/functions/${e}/deployment/stream`,this.baseUrl).href,a={Accept:"text/event-stream","Cache-Control":"no-cache"};if(this.credentials)try{let l=await this.credentials.retrieve();if(l&&l.keyId&&l.keySecret){let u=Buffer.from(`${l.keyId}:${l.keySecret}`).toString("base64");a.Authorization=`Basic ${u}`}}catch(l){console.error("Failed to add authentication:",l)}let c=null;try{c=new AbortController;let l=await fetch(s,{method:"GET",headers:a,signal:c.signal});if(!l.ok)throw new Error(`SSE connection failed: ${l.status} ${l.statusText}`);if(!l.body)throw new Error("Response body is null");let u=l.body.getReader(),g=new TextDecoder,h="";return(async()=>{let w="";try{for(;;){let{done:T,value:q}=await u.read();if(T)break;let $=g.decode(q,{stream:!0});h+=$;let C=h.split(`
|
|
3
3
|
`);h=C.pop()||"";for(let b of C){if(b.startsWith("event:")){w=b.substring(6).trim();continue}if(b.startsWith("data:")){let y=b.substring(5).trim();if(y)try{let P=JSON.parse(y),Q=w||r(P);n({type:Q,data:P}),w=""}catch{n({type:w||"message",data:y}),w=""}}b===""&&(w="")}}}catch(T){T.name!=="AbortError"&&i&&i(T)}})(),()=>{c&&c.abort()}}catch(l){throw console.error("Failed to create SSE stream:",l),i&&i(l),l}}async checkHealth(){try{return(await this.client.get("/health")).data}catch(e){throw this._handleError(e,"Health check failed")}}async getValidToken(){if(!this.credentials)return null;try{let e=await this.credentials.getOAuthToken();if(e)return{access_token:e,token_type:"Bearer",expires_in:3600};let n=await this.credentials.getBasicAuthToken();return n?{access_token:n,token_type:"Basic",expires_in:3600}:null}catch(e){return console.error(ke.default.yellow("Failed to get authentication token:",e.message)),null}}async authenticateOAuth(e,n){try{let i="https://auth.sinch.com/oauth2/token",r=new URLSearchParams;r.append("grant_type","client_credentials");let a=(await Ve.default.post(i,r,{headers:{"Content-Type":"application/x-www-form-urlencoded",Authorization:"Basic "+Buffer.from(`${e}:${n}`).toString("base64")},timeout:this.timeout})).data;return this.credentials&&await this.credentials.storeOAuthToken(a),a}catch(i){throw this._handleError(i,"OAuth authentication failed")}}_handleError(e,n){if(Ve.default.isAxiosError(e)){let i=e;if(i.response){let r=i.response.status,s=i.response.data,a=s?.message||s?.error||i.message;throw r===401?new Error('Authentication required. Please run "sinch auth login" first.'):r===403?new Error(`Permission denied: ${a}`):r===404?new Error(`Resource not found: ${a}`):r>=500?new Error(`Server error: ${a}`):new Error(`${n}: ${a}`)}else throw i.request?i.code==="ECONNREFUSED"?new Error(`Cannot connect to API at ${this.baseUrl}. Is the server running?`):i.code==="ETIMEDOUT"?new Error(`Request timeout after ${this.timeout}ms`):new Error(`${n}: No response from server`):new Error(`${n}: ${i.message}`)}else throw new Error(`${n}: ${e.message||e}`)}}});function qe(){if(!et)try{et=require("keytar")}catch{return null}return et}var kt,Z,et,je,U,Me,Pt=fe(()=>{"use strict";kt=m(require("os")),Z=m(require("chalk")),et=null;je="sinch-functions-cli",U=kt.userInfo().username,Me=class{config;keychainAvailable=null;constructor(e){this.config=e}async isKeychainAvailable(){if(this.keychainAvailable!==null)return this.keychainAvailable;if(this.config.get("keySecretPlaintext"))return this.keychainAvailable=!1,!1;try{let e=qe();if(!e)return this.keychainAvailable=!1,!1;let n=`${U}-test-${Date.now()}`;return await e.setPassword(je,n,"test"),await e.deletePassword(je,n),this.keychainAvailable=!0,!0}catch{return this.keychainAvailable=!1,!1}}async setPassword(e,n){if(!await this.isKeychainAvailable())return!1;let r=qe();return r?(await r.setPassword(je,e,n),!0):!1}async getPassword(e){if(!await this.isKeychainAvailable())return null;let i=qe();return i?await i.getPassword(je,e):null}async deletePassword(e){if(!await this.isKeychainAvailable())return!1;try{let i=qe();return i?(await i.deletePassword(je,e),!0):!1}catch{return!0}}async store(e){let{projectId:n,keyId:i,keySecret:r,applicationKey:s,applicationSecret:a}=e,c=await this.setPassword(`${U}-keySecret`,r),l=await this.setPassword(s,a);c&&l?(this.config.set("keySecretPlaintext",null),this.config.set("applicationSecretPlaintext",null)):(console.log(Z.default.yellow(`
|
|
4
4
|
\u26A0\uFE0F OS keychain not available (Docker/CI environment detected)`)),console.log(Z.default.yellow("\u26A0\uFE0F Storing secrets in plaintext config file")),console.log(Z.default.gray("Location: ~/.sinch/config.json")),console.log(Z.default.gray(`
|
|
5
5
|
For better security, export as environment variables instead:`)),console.log(Z.default.cyan(' export SINCH_KEY_SECRET="'+r+'"')),console.log(Z.default.cyan(' export SINCH_APPLICATION_SECRET="'+a+'"')),this.config.set("keySecretPlaintext",r),this.config.set("applicationSecretPlaintext",a)),this.config.set("projectId",n),this.config.set("keyId",i),this.config.set("defaultApplicationKey",s),this.config.set("credentialsStored",!0),await this.config.save()}async storeOAuthToken(e){let{access_token:n,refresh_token:i,expires_in:r,token_type:s}=e,a=new Date(Date.now()+r*1e3).toISOString(),c=await this.setPassword(`${U}-oauth-access`,n),l=!0;i&&(l=await this.setPassword(`${U}-oauth-refresh`,i)),this.config.set("oauthTokenType",s),this.config.set("oauthExpiresAt",a),this.config.set("oauthStored",c&&l),await this.config.save()}async reAuthenticateOAuth(){try{let e=await this.retrieve();if(!e)return null;let{SinchAPI:n}=(L(),O(De)),r=await new n({apiUrl:this.config.get("apiUrl")||"https://api.functions.dev.sinchvoice.org",projectId:e.projectId,credentials:null}).authenticateOAuth(e.keyId,e.keySecret);return await this.storeOAuthToken(r),r.access_token}catch{return null}}async getOAuthToken(){if(!this.config.get("oauthStored"))return await this.reAuthenticateOAuth();let n=this.config.get("oauthExpiresAt");if(n&&new Date(n)<new Date){console.log(Z.default.gray("Token expired, re-authenticating..."));let i=await this.reAuthenticateOAuth();return i?console.log(Z.default.green("\u2713 Token renewed successfully")):console.warn(Z.default.yellow("Failed to renew OAuth token. Please login again.")),i}return await this.getPassword(`${U}-oauth-access`)}async storeApplicationSecret(e,n){await this.setPassword(e,n),this.config.get("defaultApplicationKey")||(this.config.set("defaultApplicationKey",e),await this.config.save())}async retrieve(){let e=process.env.SINCH_KEY_ID,n=process.env.SINCH_KEY_SECRET,i=process.env.SINCH_APPLICATION_KEY,r=process.env.SINCH_APPLICATION_SECRET;if(e&&n&&i&&r)return{projectId:process.env.SINCH_PROJECT_ID||this.config.get("projectId")||"",keyId:e,keySecret:n,applicationKey:i,applicationSecret:r};if(!this.config.get("credentialsStored"))return null;let a=this.config.get("projectId"),c=this.config.get("keyId"),l=this.config.get("defaultApplicationKey"),u=await this.getPassword(`${U}-keySecret`),g=l?await this.getPassword(l):null;return(!u||!g)&&(u=u||n||null,g=g||r||null),(!u||!g)&&(u=u||this.config.get("keySecretPlaintext"),g=g||this.config.get("applicationSecretPlaintext")),!u||!g?null:{projectId:a,keyId:c,keySecret:u,applicationKey:l,applicationSecret:g}}async getApplicationCredentials(e=null){if(e||(e=this.config.get("defaultApplicationKey")),!e)return null;let n=await this.getPassword(e);return n||(n=process.env.SINCH_APPLICATION_SECRET||null),n||(n=this.config.get("applicationSecretPlaintext")),n?{applicationKey:e,applicationSecret:n}:null}async clear(){let e=this.config.get("defaultApplicationKey");await this.deletePassword(`${U}-keySecret`),await this.deletePassword(`${U}-oauth-access`),await this.deletePassword(`${U}-oauth-refresh`),e&&await this.deletePassword(e),this.config.set("projectId",null),this.config.set("keyId",null),this.config.set("defaultApplicationKey",null),this.config.set("credentialsStored",!1),this.config.set("oauthStored",!1),this.config.set("oauthTokenType",null),this.config.set("oauthExpiresAt",null),this.config.set("keySecretPlaintext",null),this.config.set("applicationSecretPlaintext",null),await this.config.save()}async hasCredentials(){if(!!(process.env.SINCH_KEY_ID&&process.env.SINCH_KEY_SECRET&&process.env.SINCH_APPLICATION_KEY&&process.env.SINCH_APPLICATION_SECRET))return!0;if(!this.config.get("credentialsStored"))return!1;if(this.config.get("keySecretPlaintext"))return!0;let i=await this.getPassword(`${U}-keySecret`),r=this.config.get("defaultApplicationKey"),s=r?await this.getPassword(r):null;return!!(i&&s)}async hasOAuthToken(){return this.config.get("oauthStored")?!!await this.getPassword(`${U}-oauth-access`):!1}getPublicInfo(){return{projectId:this.config.get("projectId"),keyId:this.config.get("keyId"),applicationKey:this.config.get("defaultApplicationKey"),hasCredentials:this.config.get("credentialsStored",!1),hasOAuth:this.config.get("oauthStored",!1),oauthExpiresAt:this.config.get("oauthExpiresAt")}}async createSinchClient(e=null){let n=await this.getApplicationCredentials(e);if(!n)throw new Error('No credentials found. Please run "sinch auth login" first.');let{SinchClient:i}=require("@sinch/sdk-core");return new i({applicationKey:n.applicationKey,applicationSecret:n.applicationSecret,projectId:this.config.get("projectId")})}async storeBasicAuthToken(e){await this.setPassword(`${U}-basic-auth`,e)&&(this.config.set("basicAuthStored",!0),await this.config.save())}async getBasicAuthToken(){return this.config.get("basicAuthStored")?await this.getPassword(`${U}-basic-auth`):null}async clearBasicAuthToken(){await this.deletePassword(`${U}-basic-auth`),this.config.set("basicAuthStored",!1),await this.config.save()}}});var he={};Be(he,{Config:()=>Je,config:()=>p});var W,Fe,At,tt,Je,p,I=fe(()=>{"use strict";W=m(require("fs-extra")),Fe=m(require("path")),At=m(require("os")),tt=m(require("chalk"));Pt();Je=class{configDir;configFile;projectConfigFile;_config=null;_projectConfig=null;_credentials=null;constructor(){this.configDir=Fe.join(At.homedir(),".sinch"),this.configFile=Fe.join(this.configDir,"config.json"),this.projectConfigFile=Fe.join(process.cwd(),"sinch.json")}async load(){try{await W.ensureDir(this.configDir),await W.pathExists(this.configFile)?this._config=await W.readJson(this.configFile):(this._config=this._getDefaultConfig(),await this.save())}catch(e){console.warn(tt.default.yellow(`Warning: Could not load config: ${e.message}`)),this._config=this._getDefaultConfig()}this._credentials=new Me(this);try{await W.pathExists(this.projectConfigFile)&&(this._projectConfig=await W.readJson(this.projectConfigFile))}catch(e){console.warn(tt.default.yellow(`Warning: Could not load project config: ${e.message}`))}}async save(){try{await W.ensureDir(this.configDir),await W.writeJson(this.configFile,this._config,{spaces:2})}catch(e){throw new Error(`Could not save config: ${e.message}`)}}async saveProjectConfig(){try{if(this._projectConfig){let e=Fe.join(process.cwd(),"sinch.json");await W.writeJson(e,this._projectConfig,{spaces:2})}}catch(e){throw new Error(`Could not save project config: ${e.message}`)}}get(e,n=null){if(!this._config)throw new Error("Config not loaded. Call load() first.");return this._projectConfig&&this._projectConfig[e]!==void 0?this._projectConfig[e]:this._config[e]!==void 0?this._config[e]:n}set(e,n,i=!1){if(!this._config)throw new Error("Config not loaded. Call load() first.");i?(this._projectConfig||(this._projectConfig={}),this._projectConfig[e]=n):this._config[e]=n}getApiConfig(){return{apiUrl:this.get("apiUrl"),projectId:this.get("projectId"),timeout:this.get("timeout"),credentials:this._credentials}}async initProject(e,n="node",i={},r=null){let s={name:e,runtime:n,version:"1.0.0",description:`Sinch Functions project: ${e}`,created:new Date().toISOString()};return i&&Object.keys(i).length>0&&(s.variables=i),r&&(s.applicationKey=r),this._projectConfig=s,await this.saveProjectConfig(),s}isInProject(){return this._projectConfig!==null}getProjectConfig(){return this._projectConfig}_getDefaultConfig(){return{apiUrl:"https://api.functions.dev.sinchvoice.org",projectId:"default-project",timeout:0,created:new Date().toISOString(),version:"1.0.0"}}async storeCredentials(e){if(!this._credentials)throw new Error("Config not loaded. Call load() first.");return await this._credentials.store(e)}async getCredentials(){if(!this._credentials)throw new Error("Config not loaded. Call load() first.");return await this._credentials.retrieve()}async clearCredentials(){if(!this._credentials)throw new Error("Config not loaded. Call load() first.");return await this._credentials.clear()}async hasCredentials(){if(!this._credentials)throw new Error("Config not loaded. Call load() first.");return await this._credentials.hasCredentials()}getPublicCredentialInfo(){if(!this._credentials)throw new Error("Config not loaded. Call load() first.");return this._credentials.getPublicInfo()}async createSinchClient(e=null){if(!this._credentials)throw new Error("Config not loaded. Call load() first.");return!e&&this.isInProject()&&(e=this._projectConfig?.applicationKey||null),await this._credentials.createSinchClient(e)}async getApplicationCredentials(e=null){if(!this._credentials)throw new Error("Config not loaded. Call load() first.");return!e&&this.isInProject()&&(e=this._projectConfig?.applicationKey||null),await this._credentials.getApplicationCredentials(e)}async storeApplicationSecret(e,n){if(!this._credentials)throw new Error("Config not loaded. Call load() first.");return await this._credentials.storeApplicationSecret(e,n)}getTunnelPreference(){return this._projectConfig&&this._projectConfig.tunnel?.preference||null}async setTunnelPreference(e){if(!this._projectConfig)throw new Error("Not in a project directory");this._projectConfig.tunnel||(this._projectConfig.tunnel={}),this._projectConfig.tunnel.preference=e,this._projectConfig.tunnel.lastUpdated=new Date().toISOString(),await this.saveProjectConfig()}getTunnelSubdomain(){return this._projectConfig&&this._projectConfig.tunnel?.subdomain||null}async setTunnelSubdomain(e){if(!this._projectConfig)throw new Error("Not in a project directory");this._projectConfig.tunnel||(this._projectConfig.tunnel={}),this._projectConfig.tunnel.subdomain=e,this._projectConfig.tunnel.lastUpdated=new Date().toISOString(),await this.saveProjectConfig()}getTunnelUrl(){return this._projectConfig&&this._projectConfig.tunnel?.lastUrl||null}async setTunnelUrl(e){if(!this._projectConfig)throw new Error("Not in a project directory");this._projectConfig.tunnel||(this._projectConfig.tunnel={}),this._projectConfig.tunnel.lastUrl=e,this._projectConfig.tunnel.lastUpdated=new Date().toISOString(),await this.saveProjectConfig()}},p=new Je});var H,re,nt,Et,ot,t,K=fe(()=>{"use strict";H=m(require("chalk")),re=m(require("fs")),nt=m(require("path")),Et=m(require("os")),ot=class{verbose;logFile;constructor(e={}){this.verbose=e.verbose||process.env.VERBOSE==="true";let n="cli";try{let i=nt.join(process.cwd(),"sinch.json");re.existsSync(i)&&(n=JSON.parse(re.readFileSync(i,"utf8")).name||"cli")}catch{}this.logFile=nt.join(Et.tmpdir(),`sinch-${n}.log`);try{re.writeFileSync(this.logFile,`=== Sinch CLI Debug Log - ${new Date().toISOString()} ===
|