@sinch/cli 0.3.0 → 0.3.2

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.
Files changed (2) hide show
  1. package/dist/index.js +113 -109
  2. package/package.json +7 -1
package/dist/index.js CHANGED
@@ -1,45 +1,49 @@
1
1
  #!/usr/bin/env node
2
- "use strict";var Ts=Object.create;var Qt=Object.defineProperty;var Rs=Object.getOwnPropertyDescriptor;var Ns=Object.getOwnPropertyNames;var Os=Object.getPrototypeOf,js=Object.prototype.hasOwnProperty;var W=(i,e)=>()=>(i&&(e=i(i=0)),e);var x=(i,e)=>()=>(e||i((e={exports:{}}).exports,e),e.exports),xe=(i,e)=>{for(var t in e)Qt(i,t,{get:e[t],enumerable:!0})},ki=(i,e,t,o)=>{if(e&&typeof e=="object"||typeof e=="function")for(let r of Ns(e))!js.call(i,r)&&r!==t&&Qt(i,r,{get:()=>e[r],enumerable:!(o=Rs(e,r))||o.enumerable});return i};var y=(i,e,t)=>(t=i!=null?Ts(Os(i)):{},ki(e||!i||!i.__esModule?Qt(t,"default",{value:i,enumerable:!0}):t,i)),L=i=>ki(Qt({},"__esModule",{value:!0}),i);var In=x((Fc,Fs)=>{Fs.exports={name:"@sinch/cli",version:"0.3.0",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 --config jest.config.js && jest --config tests/e2e/jest.config.js","test:unit":"jest --config jest.config.js","test:e2e":"jest --config tests/e2e/jest.config.js","test:e2e:staging":"jest --config tests/e2e/jest.config.js --env=staging",prepublishOnly:"npm run build:prod",format:"prettier --write .","format:check":"prettier --check ."},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:{"@inquirer/prompts":"^8.2.0","@sinch/fax":"^1.0.0","@sinch/sdk-core":"^1.2.1","adm-zip":"^0.5.10",axios:"^1.13.3","axios-retry":"^4.5.0",blessed:"^0.1.81",chalk:"^4.1.2",chokidar:"^3.6.0","cli-spinners":"^2.9.2","cli-table3":"^0.6.3",clipboardy:"^5.1.0",commander:"^14.0.0",eventsource:"^4.0.0","form-data":"^4.0.0","fs-extra":"^11.3.3","google-libphonenumber":"^3.2.44",inquirer:"8.2.7",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/google-libphonenumber":"^7.4.30","@types/inquirer":"^9.0.9","@types/jest":"^30.0.0","@types/keytar":"^4.4.0","@types/node":"24.10.9",execa:"^5.1.1",jest:"^30.0.0",nodemon:"^3.0.1",prettier:"^3.8.1","ts-jest":"^29.4.6",tsup:"^8.5.0",tsx:"^4.20.4",typescript:"^5.9.2"},engines:{node:">=20.0.0",npm:">=9.0.0"}}});var $,R,pt=W(()=>{"use strict";$={SUCCESS:0,FAILURE:1,USAGE:2,USAGE_ERROR:64,DATA_ERROR:65,NO_INPUT:66,UNAVAILABLE:69,SOFTWARE:70,CANT_CREATE:73,IO_ERROR:74,NO_PERMISSION:77,CONFIG_ERROR:78,AUTH_REQUIRED:100,AUTH_FAILED:101,NOT_FOUND:102,CONFLICT:103,TIMEOUT:104},R=class extends Error{exitCode;constructor(e,t=$.FAILURE){super(e),this.name="CLIError",this.exitCode=t}}});function en(i){if(!i)return i;let e=i;for(let t of Ws)e=e.replace(t,o=>{let r=o.match(/^[A-Za-z]+\s+/)?.[0]||"";return r?`${r}[REDACTED]`:"[REDACTED]"});return e}function Ei(i){let e={...i};if(e.Authorization){let r=e.Authorization.match(/^([A-Za-z]+)\s+/),s=r?r[1]:"Bearer";e.Authorization=`${s} [REDACTED]`}let t=["x-api-key","x-auth-token","api-key","token"];for(let o of t){let r=Object.keys(e).find(s=>s.toLowerCase()===o);r&&(e[r]="[REDACTED]")}return e}var Ws,xi=W(()=>{"use strict";Ws=[/Bearer\s+[A-Za-z0-9\-_.]+/g,/Basic\s+[A-Za-z0-9+/=]+/g,/[Aa]uthorization["\s:=]+["']?[^"'\s]+/g]});var Ti={};xe(Ti,{DebugLevel:()=>Dt,debugLog:()=>ue,getDebugLevel:()=>se,setConfigDebugLevel:()=>zs});function zs(i){kn=Math.max(0,Math.min(i,3))}function se(){let i=process.env.SINCH_DEBUG;if(i){let e=parseInt(i,10);if(!isNaN(e))return Math.max(0,Math.min(e,3));if(i.toLowerCase()==="true")return 1}return kn!==null?kn:0}function ue(i,e,...t){se()>=i&&console.log(Di.default.gray(`[DEBUG:${i}]`),e,...t)}var Di,Dt,kn,Tt=W(()=>{"use strict";Di=y(require("chalk")),Dt=(r=>(r[r.NONE=0]="NONE",r[r.INFO=1]="INFO",r[r.HTTP=2]="HTTP",r[r.VERBOSE=3]="VERBOSE",r))(Dt||{}),kn=null});var Qe={};xe(Qe,{SinchAPI:()=>V});var tn,nn,An,En,V,X=W(()=>{"use strict";tn=y(require("axios")),nn=y(require("axios-retry")),An=y(require("form-data")),En=y(require("chalk"));xi();pt();Tt();V=class{baseUrl;oauthUrl;projectId;timeout;credentials;client;constructor(e={}){this.baseUrl=e.apiUrl||"https://functions.api.sinch.com/",this.oauthUrl=e.oauthUrl||"https://auth.sinch.com/oauth2/token",this.projectId=e.projectId||"",this.timeout=6e4,this.credentials=e.credentials||null,this.client=tn.default.create({baseURL:this.baseUrl,timeout:this.timeout,headers:{"User-Agent":"sinch-functions-cli/1.0.0"}}),(0,nn.default)(this.client,{retries:3,retryDelay:(t,o)=>{let r=o.response?.headers?.["retry-after"];return r?parseInt(r,10)*1e3:nn.default.exponentialDelay(t)},retryCondition:t=>{if(nn.default.isNetworkError(t))return!0;let o=t.response?.status;return!!(o&&o>=500||o===429)},onRetry:(t,o)=>{ue(1,`Retry ${t}/3: ${o.message}`)}}),this.client.interceptors.request.use(async t=>{if(this.credentials){let o=await this.getValidToken();o&&(t.headers.Authorization=`${o.token_type} ${o.access_token}`)}if(se()>=2){let o=en(t.url||"");if(ue(2,`\u2192 ${t.method?.toUpperCase()} ${o}`),se()>=3){let r=Ei(t.headers);ue(3," Headers:",JSON.stringify(r,null,2))}}return t},t=>Promise.reject(t)),this.client.interceptors.response.use(t=>{if(se()>=2){let o=en(t.config.url||"");ue(2,`\u2190 ${t.status} ${o}`)}return t},async t=>{if(se()>=2){let o=en(t.config?.url||"");ue(2,`\u2190 ${t.response?.status||"ERROR"} ${o}`)}if(t.response?.status===401&&this.credentials&&t.config){let o=t.config;if(!o._retry){o._retry=!0;try{let r=await this.getValidToken();if(r)return o.headers.Authorization=`${r.token_type} ${r.access_token}`,this.client.request(o)}catch{console.error(En.default.yellow("Token refresh failed during retry"))}}}return Promise.reject(t)})}async listAllTemplates(e=null){try{let t=e?{category:e}:{};return(await this.client.get(`/v1/projects/${this.projectId}/templates`,{params:t})).data}catch(t){throw this._handleError(t,"Failed to list templates")}}async listRuntimeTemplates(e,t=null){try{let o=t?{category:t}:{};return(await this.client.get(`/v1/projects/${this.projectId}/templates/${e}`,{params:o})).data}catch(o){throw this._handleError(o,`Failed to list ${e} templates`)}}async getTemplateDetails(e,t){try{return(await this.client.get(`/v1/projects/${this.projectId}/templates/${e}/${t}`)).data}catch(o){throw this._handleError(o,`Failed to get template details for ${e}/${t}`)}}async downloadTemplate(e,t){try{let o=await this.client.get(`/v1/projects/${this.projectId}/templates/${e}/${t}/download`,{responseType:"arraybuffer"});return Buffer.from(o.data)}catch(o){throw this._handleError(o,`Failed to download template ${e}/${t}`)}}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(t){throw this._handleError(t,`Failed to get function ${e}`)}}async deployFunction(e,t,o,r,s="public"){try{let a=new An.default;return a.append("name",e),a.append("runtime",t),a.append("code",o,{filename:"function.zip"}),a.append("accessLevel",s),r&&a.append("configuration",JSON.stringify(r)),(await this.client.post(`/v1/projects/${this.projectId}/functions`,a,{headers:{...a.getHeaders()},maxContentLength:1/0,maxBodyLength:1/0})).data}catch(a){throw this._handleError(a,"Failed to deploy function")}}async updateFunction(e,t,o){try{let r=new An.default;return r.append("code",t,{filename:"function.zip"}),o&&r.append("configuration",JSON.stringify(o)),(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(t){throw this._handleError(t,`Failed to delete function ${e}`)}}async downloadFunction(e){try{let t=await this.client.get(`/v1/projects/${this.projectId}/functions/${e}/download`,{responseType:"arraybuffer"});return Buffer.from(t.data)}catch(t){throw this._handleError(t,`Failed to download function ${e}`)}}async getFunctionLogs(e,t={}){try{return(await this.client.get(`/v1/projects/${this.projectId}/functions/${e}/logs`,{params:t})).data}catch(o){throw this._handleError(o,`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(t){throw this._handleError(t,`Failed to get status for function ${e}`)}}async generateDocumentationFromCode(e,t="node",o="function"){try{return(await this.client.post(`/v1/projects/${this.projectId}/test/documentation`,{Code:e,Runtime:t,Name:o})).data}catch(r){throw this._handleError(r,"Failed to generate documentation from code")}}async generateDocumentationForFunction(e,t){try{let o=t?{MarkdownOverride:t}:{};return(await this.client.post(`/v1/projects/${this.projectId}/functions/${e}/documentation`,o)).data}catch(o){throw this._handleError(o,`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(t){throw this._handleError(t,`Failed to get documentation for function ${e}`)}}async streamDeployment(e,t,o){let r=p=>p.status?"status":p.progress?"progress":p.completed?"completed":p.failed||p.error?"failed":p.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 p=await this.credentials.retrieve();if(p&&p.keyId&&p.keySecret){let d=Buffer.from(`${p.keyId}:${p.keySecret}`).toString("base64");a.Authorization=`Basic ${d}`}}catch(p){console.error("Failed to add authentication:",p)}let l=null;try{l=new AbortController;let p=await fetch(s,{method:"GET",headers:a,signal:l.signal});if(!p.ok)throw new Error(`SSE connection failed: ${p.status} ${p.statusText}`);if(!p.body)throw new Error("Response body is null");let d=p.body.getReader(),u=new TextDecoder,m="";return(async()=>{let h="";try{for(;;){let{done:C,value:v}=await d.read();if(C)break;let T=u.decode(v,{stream:!0});m+=T;let ee=m.split(`
3
- `);m=ee.pop()||"";for(let O of ee){if(O.startsWith("event:")){h=O.substring(6).trim();continue}if(O.startsWith("data:")){let P=O.substring(5).trim();if(P)try{let S=JSON.parse(P),I=h||r(S);t({type:I,data:S}),h=""}catch{t({type:h||"message",data:P}),h=""}}O===""&&(h="")}}}catch(C){C.name!=="AbortError"&&o&&o(C)}})(),()=>{l&&l.abort()}}catch(p){throw console.error("Failed to create SSE stream:",p),o&&o(p),p}}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 t=await this.credentials.getBasicAuthToken();return t?{access_token:t,token_type:"Basic",expires_in:3600}:null}catch(e){return console.error(En.default.yellow("Failed to get authentication token:",e.message)),null}}async authenticateOAuth(e,t){try{let o=this.oauthUrl,r=new URLSearchParams;r.append("grant_type","client_credentials");let a=(await tn.default.post(o,r,{headers:{"Content-Type":"application/x-www-form-urlencoded",Authorization:"Basic "+Buffer.from(`${e}:${t}`).toString("base64")},timeout:this.timeout})).data;return this.credentials&&await this.credentials.storeOAuthToken(a),a}catch(o){throw this._handleError(o,"OAuth authentication failed")}}async getTosStatus(){try{return(await this.client.get(`/v1/operations/projects/${this.projectId}/tos-status`)).data}catch(e){throw this._handleError(e,"Failed to check Terms of Service status")}}async acceptTos(e,t){try{let o={acceptedBy:e};return t&&(o.version=t),(await this.client.post(`/v1/operations/projects/${this.projectId}/accept-tos`,o)).data}catch(o){throw this._handleError(o,"Failed to accept Terms of Service")}}_handleError(e,t){if(tn.default.isAxiosError(e)){let o=e;if(o.response){let r=o.response.status,s=o.response.data,a=s?.message||s?.error||o.message;throw r===401?new R('Authentication required. Please run "sinch auth login" first.',$.AUTH_REQUIRED):r===403?new R(`Permission denied: ${a}`,$.NO_PERMISSION):r===404?new R(`Resource not found: ${a}`,$.NOT_FOUND):r===409?new R(`Conflict: ${a}`,$.CONFLICT):r===429?new R(`Rate limited: ${a}`,$.UNAVAILABLE):r>=500?new R(`Server error: ${a}`,$.UNAVAILABLE):new R(`${t}: ${a}`,$.FAILURE)}else throw o.request?o.code==="ECONNREFUSED"?new R(`Cannot connect to API at ${this.baseUrl}. Is the server running?`,$.UNAVAILABLE):o.code==="ETIMEDOUT"?new R(`Request timeout after ${this.timeout}ms`,$.TIMEOUT):new R(`${t}: No response from server (${o.code||"unknown error"})`,$.IO_ERROR):new R(`${t}: ${o.message}`,$.FAILURE)}else throw new R(`${t}: ${e.message||e}`,$.FAILURE)}}});function on(){if(!xn)try{xn=require("keytar")}catch{return null}return xn}var Ri,ae,xn,Rt,Dn,rn,Ni=W(()=>{"use strict";Ri=y(require("os")),ae=y(require("chalk")),xn=null;Rt="sinch-functions-cli",Dn=Ri.userInfo().username,rn=class{config;keychainAvailable=null;accountPrefix;constructor(e,t="default"){this.config=e,this.accountPrefix=t==="default"?Dn:`${t}-${Dn}`}async isKeychainAvailable(){if(this.keychainAvailable!==null)return this.keychainAvailable;if(this.config.get("keySecretPlaintext"))return this.keychainAvailable=!1,!1;try{let e=on();if(!e)return this.keychainAvailable=!1,!1;let t=`${Dn}-test-${Date.now()}`;return await e.setPassword(Rt,t,"test"),await e.deletePassword(Rt,t),this.keychainAvailable=!0,!0}catch{return this.keychainAvailable=!1,!1}}async setPassword(e,t){if(!await this.isKeychainAvailable())return!1;let r=on();return r?(await r.setPassword(Rt,e,t),!0):!1}async getPassword(e){if(!await this.isKeychainAvailable())return null;let o=on();return o?await o.getPassword(Rt,e):null}async deletePassword(e){if(!await this.isKeychainAvailable())return!1;try{let o=on();return o?(await o.deletePassword(Rt,e),!0):!1}catch{return!0}}async store(e){let{projectId:t,keyId:o,keySecret:r,applicationKey:s,applicationSecret:a}=e,l=await this.setPassword(`${this.accountPrefix}-keySecret`,r),p=!0;s&&a&&(p=await this.setPassword(s,a)),l&&p?(this.config.set("keySecretPlaintext",null),a&&this.config.set("applicationSecretPlaintext",null)):(console.log(ae.default.yellow(`
4
- \u26A0\uFE0F OS keychain not available (Docker/CI environment detected)`)),console.log(ae.default.yellow("\u26A0\uFE0F Storing secrets in plaintext config file")),console.log(ae.default.gray("Location: ~/.sinch/config.json")),console.log(ae.default.gray(`
5
- For better security, export as environment variables instead:`)),console.log(ae.default.cyan(' export SINCH_KEY_SECRET="'+r+'"')),a&&console.log(ae.default.cyan(' export SINCH_APPLICATION_SECRET="'+a+'"')),this.config.set("keySecretPlaintext",r),a&&this.config.set("applicationSecretPlaintext",a)),this.config.set("projectId",t),this.config.set("keyId",o),s&&this.config.set("defaultApplicationKey",s),this.config.set("credentialsStored",!0),await this.config.save()}async storeOAuthToken(e){let{access_token:t,refresh_token:o,expires_in:r,token_type:s}=e,a=new Date(Date.now()+r*1e3).toISOString(),l=await this.setPassword(`${this.accountPrefix}-oauth-access`,t),p=!0;o&&(p=await this.setPassword(`${this.accountPrefix}-oauth-refresh`,o)),this.config.set("oauthTokenType",s),this.config.set("oauthExpiresAt",a),this.config.set("oauthStored",l&&p),await this.config.save()}async reAuthenticateOAuth(){try{let e=await this.retrieve();if(!e)return null;let{SinchAPI:t}=(X(),L(Qe)),r=await new t({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 t=this.config.get("oauthExpiresAt");if(t&&new Date(t)<new Date){console.log(ae.default.gray("Token expired, re-authenticating..."));let o=await this.reAuthenticateOAuth();return o?console.log(ae.default.green("\u2713 Token renewed successfully")):console.warn(ae.default.yellow("Failed to renew OAuth token. Please login again.")),o}return await this.getPassword(`${this.accountPrefix}-oauth-access`)}async storeApplicationSecret(e,t){await this.setPassword(e,t),this.config.get("defaultApplicationKey")||(this.config.set("defaultApplicationKey",e),await this.config.save())}async retrieve(){let e=process.env.SINCH_KEY_ID,t=process.env.SINCH_KEY_SECRET,o=process.env.SINCH_APPLICATION_KEY,r=process.env.SINCH_APPLICATION_SECRET;if(e&&t)return{projectId:process.env.SINCH_PROJECT_ID||this.config.get("projectId")||"",keyId:e,keySecret:t,applicationKey:o||void 0,applicationSecret:r||void 0};if(!this.config.get("credentialsStored"))return null;let a=this.config.get("projectId"),l=this.config.get("keyId"),p=this.config.get("defaultApplicationKey"),d=await this.getPassword(`${this.accountPrefix}-keySecret`);if(d||(d=t||null),d||(d=this.config.get("keySecretPlaintext")),!d)return null;let u=null;return p&&(u=await this.getPassword(p),u||(u=r||null),u||(u=this.config.get("applicationSecretPlaintext"))),{projectId:a,keyId:l,keySecret:d,applicationKey:p||void 0,applicationSecret:u||void 0}}async getApplicationCredentials(e=null){if(e||(e=this.config.get("defaultApplicationKey")),!e)return null;let t=await this.getPassword(e);return t||(t=process.env.SINCH_APPLICATION_SECRET||null),t||(t=this.config.get("applicationSecretPlaintext")),t?{applicationKey:e,applicationSecret:t}:null}async clear(){let e=this.config.get("defaultApplicationKey");await this.deletePassword(`${this.accountPrefix}-keySecret`),await this.deletePassword(`${this.accountPrefix}-oauth-access`),await this.deletePassword(`${this.accountPrefix}-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(){return process.env.SINCH_KEY_ID&&process.env.SINCH_KEY_SECRET?!0:this.config.get("credentialsStored")?this.config.get("keySecretPlaintext")?!0:!!await this.getPassword(`${this.accountPrefix}-keySecret`):!1}async hasVoiceCredentials(){let e=process.env.SINCH_APPLICATION_KEY,t=process.env.SINCH_APPLICATION_SECRET;if(e&&t)return!0;let o=this.config.get("defaultApplicationKey");return o?await this.getPassword(o)?!0:!!this.config.get("applicationSecretPlaintext"):!1}async hasOAuthToken(){return this.config.get("oauthStored")?!!await this.getPassword(`${this.accountPrefix}-oauth-access`):!1}getPublicInfo(){return process.env.SINCH_KEY_ID&&process.env.SINCH_KEY_SECRET?{projectId:process.env.SINCH_PROJECT_ID||this.config.get("projectId"),keyId:process.env.SINCH_KEY_ID,applicationKey:process.env.SINCH_APPLICATION_KEY||this.config.get("defaultApplicationKey"),hasCredentials:!0,hasOAuth:!1,oauthExpiresAt:null,source:"environment"}:{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"),source:"config"}}async createSinchClient(e=null){let t=await this.retrieve();if(!t)throw new Error('No credentials found. Please run "sinch auth login" first.');let o=await this.getApplicationCredentials(e),{SinchClient:r}=require("@sinch/sdk-core");return new r({applicationKey:o?.applicationKey||t.applicationKey,applicationSecret:o?.applicationSecret||t.applicationSecret,projectId:t.projectId,keyId:t.keyId,keySecret:t.keySecret,conversationRegion:"us"})}async storeBasicAuthToken(e){await this.setPassword(`${this.accountPrefix}-basic-auth`,e)&&(this.config.set("basicAuthStored",!0),await this.config.save())}async getBasicAuthToken(){return this.config.get("basicAuthStored")?await this.getPassword(`${this.accountPrefix}-basic-auth`):null}async clearBasicAuthToken(){await this.deletePassword(`${this.accountPrefix}-basic-auth`),this.config.set("basicAuthStored",!1),await this.config.save()}async storeFax(e){let{projectId:t,keyId:o,keySecret:r}=e;await this.setPassword(`${this.accountPrefix}-fax-keySecret`,r)?this.config.set("faxKeySecretPlaintext",null):(console.log(ae.default.yellow(`
6
- \u26A0\uFE0F OS keychain not available (Docker/CI environment detected)`)),console.log(ae.default.yellow("\u26A0\uFE0F Storing fax secret in plaintext config file")),console.log(ae.default.gray("Location: ~/.sinch/config.json")),console.log(ae.default.gray(`
7
- For better security, export as environment variable instead:`)),console.log(ae.default.cyan(' export SINCH_FAX_KEY_SECRET="'+r+'"')),this.config.set("faxKeySecretPlaintext",r)),this.config.set("faxProjectId",t),this.config.set("faxKeyId",o),this.config.set("faxCredentialsStored",!0),await this.config.save()}async retrieveFax(){let e=process.env.SINCH_FAX_KEY_ID,t=process.env.SINCH_FAX_KEY_SECRET;if(e&&t)return{projectId:process.env.SINCH_FAX_PROJECT_ID||this.config.get("faxProjectId")||"",keyId:e,keySecret:t};if(!this.config.get("faxCredentialsStored"))return null;let r=this.config.get("faxProjectId"),s=this.config.get("faxKeyId"),a=await this.getPassword(`${this.accountPrefix}-fax-keySecret`);return a||(a=t||null),a||(a=this.config.get("faxKeySecretPlaintext")),a?{projectId:r,keyId:s,keySecret:a}:null}async hasFaxCredentials(){return process.env.SINCH_FAX_KEY_ID&&process.env.SINCH_FAX_KEY_SECRET?!0:this.config.get("faxCredentialsStored")?this.config.get("faxKeySecretPlaintext")?!0:!!await this.getPassword(`${this.accountPrefix}-fax-keySecret`):!1}async clearFax(){await this.deletePassword(`${this.accountPrefix}-fax-keySecret`),this.config.set("faxProjectId",null),this.config.set("faxKeyId",null),this.config.set("faxCredentialsStored",!1),this.config.set("faxKeySecretPlaintext",null),await this.config.save()}getFaxPublicInfo(){return process.env.SINCH_FAX_KEY_ID&&process.env.SINCH_FAX_KEY_SECRET?{projectId:process.env.SINCH_FAX_PROJECT_ID||this.config.get("faxProjectId"),keyId:process.env.SINCH_FAX_KEY_ID,hasCredentials:!0,source:"environment"}:{projectId:this.config.get("faxProjectId"),keyId:this.config.get("faxKeyId"),hasCredentials:this.config.get("faxCredentialsStored",!1),source:"config"}}}});var Nt={};xe(Nt,{ProfileManager:()=>sn,profileManager:()=>ut});var U,ye,Oi,sn,ut,ft=W(()=>{"use strict";U=y(require("fs-extra")),ye=y(require("path")),Oi=y(require("os")),sn=class{configDir;profilesDir;metaFile;constructor(){this.configDir=ye.join(Oi.homedir(),".sinch"),this.profilesDir=ye.join(this.configDir,"profiles"),this.metaFile=ye.join(this.configDir,"config.json")}async init(){await U.ensureDir(this.profilesDir),(await this.list()).length===0&&await this.migrateFromLegacy()}async migrateFromLegacy(){if(!await U.pathExists(this.metaFile)){await this.create("default");return}try{let e=await U.readJson(this.metaFile),t={name:"default",projectId:e.projectId,keyId:e.keyId,apiUrl:e.apiUrl,oauthUrl:e.oauthUrl,defaultApplicationKey:e.defaultApplicationKey,credentialsStored:e.credentialsStored,created:e.created||new Date().toISOString()};await U.writeJson(ye.join(this.profilesDir,"default.json"),t,{spaces:2}),e.activeProfile="default",await U.writeJson(this.metaFile,e,{spaces:2})}catch{await this.create("default")}}async create(e){let t=ye.join(this.profilesDir,`${e}.json`);if(await U.pathExists(t))throw new Error(`Profile '${e}' already exists`);let o={name:e,created:new Date().toISOString()};await U.ensureDir(this.profilesDir),await U.writeJson(t,o,{spaces:2})}async delete(e){let t=await this.getActive();if(e===t)throw new Error(`Cannot delete the active profile '${e}'. Switch to another profile first.`);let o=ye.join(this.profilesDir,`${e}.json`);if(!await U.pathExists(o))throw new Error(`Profile '${e}' does not exist`);await U.remove(o)}async use(e){let t=ye.join(this.profilesDir,`${e}.json`);if(!await U.pathExists(t))throw new Error(`Profile '${e}' does not exist`);let o=await this.getMeta();o.activeProfile=e,await U.writeJson(this.metaFile,o,{spaces:2})}async list(){if(!await U.pathExists(this.profilesDir))return[];let e=await U.readdir(this.profilesDir),t=await this.getActive(),o=[];for(let r of e)if(r.endsWith(".json"))try{let s=await U.readJson(ye.join(this.profilesDir,r));o.push({name:s.name,projectId:s.projectId,keyId:s.keyId,active:s.name===t,created:s.created})}catch{}return o}async getActive(){return(await this.getMeta()).activeProfile||"default"}async loadProfile(e){let t=e||await this.getActive(),o=ye.join(this.profilesDir,`${t}.json`);return await U.pathExists(o)?await U.readJson(o):(await this.create(t),{name:t,created:new Date().toISOString()})}async saveProfile(e){let t=ye.join(this.profilesDir,`${e.name}.json`);await U.ensureDir(this.profilesDir),await U.writeJson(t,e,{spaces:2})}async getMeta(){try{if(await U.pathExists(this.metaFile))return await U.readJson(this.metaFile)}catch{}return{activeProfile:"default"}}get profilesDirPath(){return this.profilesDir}},ut=new sn});var De={};xe(De,{config:()=>f});var we,Ot,ji,Tn,Rn,f,A=W(()=>{"use strict";we=y(require("fs-extra")),Ot=y(require("path")),ji=y(require("os")),Tn=y(require("chalk"));Ni();ft();Rn=class{configDir;configFile;projectConfigFile;_config=null;_projectConfig=null;_credentials=null;_profileName="default";_profileOverride=null;constructor(){this.configDir=Ot.join(ji.homedir(),".sinch"),this.configFile=Ot.join(this.configDir,"config.json"),this.projectConfigFile=Ot.join(process.cwd(),"sinch.json")}setProfileOverride(e){this._profileOverride=e}getActiveProfileName(){return this._profileName}async load(){await ut.init(),this._profileName=this._profileOverride||await ut.getActive();try{let t=await ut.loadProfile(this._profileName);this._config=this._profileDataToConfig(t)}catch(t){console.warn(Tn.default.yellow(`Warning: Could not load profile '${this._profileName}': ${t.message}`)),this._config=this._getDefaultConfig()}this._credentials=new rn(this,this._profileName);let e=this.get("debug",0);if(e>0){let{setConfigDebugLevel:t}=(Tt(),L(Ti));t(e)}try{await we.pathExists(this.projectConfigFile)&&(this._projectConfig=await we.readJson(this.projectConfigFile))}catch(t){console.warn(Tn.default.yellow(`Warning: Could not load project config: ${t.message}`))}}async save(){try{let e=this._configToProfileData(this._config);await ut.saveProfile(e),await we.ensureDir(this.configDir);let t=await we.pathExists(this.configFile)?await we.readJson(this.configFile):{};t.activeProfile=this._profileName,t.apiUrl=this._config?.apiUrl,t.projectId=this._config?.projectId,await we.writeJson(this.configFile,t,{spaces:2})}catch(e){throw new Error(`Could not save config: ${e.message}`)}}_profileDataToConfig(e){return{apiUrl:e.apiUrl||"https://functions.api.sinch.com",oauthUrl:e.oauthUrl||"https://auth.sinch.com/oauth2/token",projectId:e.projectId||"default-project",created:e.created,keyId:e.keyId,defaultApplicationKey:e.defaultApplicationKey,credentialsStored:e.credentialsStored,...e}}_configToProfileData(e){return{name:this._profileName,projectId:e.projectId,keyId:e.keyId,apiUrl:e.apiUrl,oauthUrl:e.oauthUrl,defaultApplicationKey:e.defaultApplicationKey,credentialsStored:e.credentialsStored,created:e.created,...e}}async saveProjectConfig(){try{if(this._projectConfig){let e=Ot.join(process.cwd(),"sinch.json");await we.writeJson(e,this._projectConfig,{spaces:2})}}catch(e){throw new Error(`Could not save project config: ${e.message}`)}}get(e,t=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]:t}set(e,t,o=!1){if(!this._config)throw new Error("Config not loaded. Call load() first.");o?(this._projectConfig||(this._projectConfig={}),this._projectConfig[e]=t):this._config[e]=t}getApiConfig(){return{apiUrl:this.get("apiUrl"),oauthUrl:this.get("oauthUrl","https://auth.sinch.com/oauth2/token"),projectId:this.get("projectId"),credentials:this._credentials}}async initProject(e,t="node",o={},r=null){let s={name:e,runtime:t,description:`Sinch Functions project: ${e}`,created:new Date().toISOString()};return o&&Object.keys(o).length>0&&(s.variables=o),r&&(s.applicationKey=r),this._projectConfig=s,await this.saveProjectConfig(),s}isInProject(){return this._projectConfig!==null}getProjectConfig(){return this._projectConfig}_getDefaultConfig(){return{apiUrl:"https://functions.api.sinch.com",oauthUrl:"https://auth.sinch.com/oauth2/token",projectId:"default-project",created:new Date().toISOString()}}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,t){if(!this._credentials)throw new Error("Config not loaded. Call load() first.");return await this._credentials.storeApplicationSecret(e,t)}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()}async setFaxServiceId(e){this.set("faxServiceId",e),await this.save()}getFaxServiceId(){return this.get("faxServiceId",null)}async setFaxSenderNumber(e){this.set("faxSenderNumber",e),await this.save()}getFaxSenderNumber(){return this.get("faxSenderNumber",null)}async storeFaxCredentials(e){if(!this._credentials)throw new Error("Config not loaded. Call load() first.");return await this._credentials.storeFax(e)}async getFaxCredentials(){if(!this._credentials)throw new Error("Config not loaded. Call load() first.");return await this._credentials.retrieveFax()}async hasFaxCredentials(){if(!this._credentials)throw new Error("Config not loaded. Call load() first.");return await this._credentials.hasFaxCredentials()}async clearFaxCredentials(){if(!this._credentials)throw new Error("Config not loaded. Call load() first.");return await this._credentials.clearFax()}getFaxPublicCredentialInfo(){if(!this._credentials)throw new Error("Config not loaded. Call load() first.");return this._credentials.getFaxPublicInfo()}},f=new Rn});var Li={};xe(Li,{logger:()=>n});var ne,Ue,Nn,Fi,On,n,E=W(()=>{"use strict";ne=y(require("chalk")),Ue=y(require("fs")),Nn=y(require("path")),Fi=y(require("os"));Tt();On=class{logFile;constructor(){let e="cli";try{let t=Nn.join(process.cwd(),"sinch.json");Ue.existsSync(t)&&(e=JSON.parse(Ue.readFileSync(t,"utf8")).name||"cli")}catch{}this.logFile=Nn.join(Fi.tmpdir(),`sinch-${e}.log`);try{Ue.writeFileSync(this.logFile,`=== Sinch CLI Debug Log - ${new Date().toISOString()} ===
2
+ "use strict";var zs=Object.create;var an=Object.defineProperty;var Gs=Object.getOwnPropertyDescriptor;var Ys=Object.getOwnPropertyNames;var Xs=Object.getPrototypeOf,Zs=Object.prototype.hasOwnProperty;var G=(i,e)=>()=>(i&&(e=i(i=0)),e);var N=(i,e)=>()=>(e||i((e={exports:{}}).exports,e),e.exports),xe=(i,e)=>{for(var t in e)an(i,t,{get:e[t],enumerable:!0})},Li=(i,e,t,o)=>{if(e&&typeof e=="object"||typeof e=="function")for(let r of Ys(e))!Zs.call(i,r)&&r!==t&&an(i,r,{get:()=>e[r],enumerable:!(o=Gs(e,r))||o.enumerable});return i};var y=(i,e,t)=>(t=i!=null?zs(Xs(i)):{},Li(e||!i||!i.__esModule?an(t,"default",{value:i,enumerable:!0}):t,i)),F=i=>Li(an({},"__esModule",{value:!0}),i);var Ot=N((pl,Qs)=>{Qs.exports={name:"@sinch/cli",version:"0.3.2",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 --config jest.config.js && jest --config tests/e2e/jest.config.js","test:unit":"jest --config jest.config.js","test:e2e":"jest --config tests/e2e/jest.config.js","test:e2e:staging":"jest --config tests/e2e/jest.config.js --env=staging",prepublishOnly:"npm run build:prod",format:"prettier --write .","format:check":"prettier --check ."},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:{"@inquirer/prompts":"^8.2.0","@opentelemetry/api":"^1.9.0","@opentelemetry/auto-instrumentations-node":"^0.69.0","@opentelemetry/exporter-trace-otlp-http":"^0.212.0","@opentelemetry/resources":"^2.5.1","@opentelemetry/sdk-node":"^0.212.0","@opentelemetry/semantic-conventions":"^1.39.0","@sinch/fax":"^1.0.0","@sinch/sdk-core":"^1.2.1","adm-zip":"^0.5.10",axios:"^1.13.3","axios-retry":"^4.5.0",blessed:"^0.1.81",chalk:"^4.1.2",chokidar:"^3.6.0","cli-spinners":"^2.9.2","cli-table3":"^0.6.3",clipboardy:"^5.1.0",commander:"^14.0.0",eventsource:"^4.0.0","form-data":"^4.0.0","fs-extra":"^11.3.3","google-libphonenumber":"^3.2.44",inquirer:"8.2.7",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/google-libphonenumber":"^7.4.30","@types/inquirer":"^9.0.9","@types/jest":"^30.0.0","@types/keytar":"^4.4.0","@types/node":"24.10.9",execa:"^5.1.1",jest:"^30.0.0",nodemon:"^3.0.1",prettier:"^3.8.1","ts-jest":"^29.4.6",tsup:"^8.5.0",tsx:"^4.20.4",typescript:"^5.9.2"},engines:{node:">=20.0.0",npm:">=9.0.0"}}});var I,D,ut=G(()=>{"use strict";I={SUCCESS:0,FAILURE:1,USAGE:2,USAGE_ERROR:64,DATA_ERROR:65,NO_INPUT:66,UNAVAILABLE:69,SOFTWARE:70,CANT_CREATE:73,IO_ERROR:74,NO_PERMISSION:77,CONFIG_ERROR:78,AUTH_REQUIRED:100,AUTH_FAILED:101,NOT_FOUND:102,CONFLICT:103,TIMEOUT:104},D=class extends Error{exitCode;constructor(e,t=I.FAILURE){super(e),this.name="CLIError",this.exitCode=t}}});function dn(i){if(!i)return i;let e=i;for(let t of Ca)e=e.replace(t,o=>{let r=o.match(/^[A-Za-z]+\s+/)?.[0]||"";return r?`${r}[REDACTED]`:"[REDACTED]"});return e}function Ki(i){let e={...i};if(e.Authorization){let r=e.Authorization.match(/^([A-Za-z]+)\s+/),s=r?r[1]:"Bearer";e.Authorization=`${s} [REDACTED]`}let t=["x-api-key","x-auth-token","api-key","token"];for(let o of t){let r=Object.keys(e).find(s=>s.toLowerCase()===o);r&&(e[r]="[REDACTED]")}return e}var Ca,Hi=G(()=>{"use strict";Ca=[/Bearer\s+[A-Za-z0-9\-_.]+/g,/Basic\s+[A-Za-z0-9+/=]+/g,/[Aa]uthorization["\s:=]+["']?[^"'\s]+/g]});var zi={};xe(zi,{DebugLevel:()=>jt,debugLog:()=>Ce,getDebugLevel:()=>ae,setConfigDebugLevel:()=>va});function va(i){jn=Math.max(0,Math.min(i,3))}function ae(){let i=process.env.SINCH_DEBUG;if(i){let e=parseInt(i,10);if(!isNaN(e))return Math.max(0,Math.min(e,3));if(i.toLowerCase()==="true")return 1}return jn!==null?jn:0}function Ce(i,e,...t){ae()>=i&&console.log(Wi.default.gray(`[DEBUG:${i}]`),e,...t)}var Wi,jt,jn,Lt=G(()=>{"use strict";Wi=y(require("chalk")),jt=(r=>(r[r.NONE=0]="NONE",r[r.INFO=1]="INFO",r[r.HTTP=2]="HTTP",r[r.VERBOSE=3]="VERBOSE",r))(jt||{}),jn=null});var et={};xe(et,{SinchAPI:()=>J});var pn,un,Ln,_n,J,Q=G(()=>{"use strict";pn=y(require("axios")),un=y(require("axios-retry")),Ln=y(require("form-data")),_n=y(require("chalk"));Hi();ut();Lt();J=class{baseUrl;oauthUrl;projectId;timeout;credentials;client;constructor(e={}){this.baseUrl=e.apiUrl||"https://functions.api.sinch.com/",this.oauthUrl=e.oauthUrl||"https://auth.sinch.com/oauth2/token",this.projectId=e.projectId||"",this.timeout=6e4,this.credentials=e.credentials||null,this.client=pn.default.create({baseURL:this.baseUrl,timeout:this.timeout,headers:{"User-Agent":"sinch-functions-cli/1.0.0"}}),(0,un.default)(this.client,{retries:3,retryDelay:(t,o)=>{let r=o.response?.headers?.["retry-after"];return r?parseInt(r,10)*1e3:un.default.exponentialDelay(t)},retryCondition:t=>{if(un.default.isNetworkError(t))return!0;let o=t.response?.status;return!!(o&&o>=500||o===429)},onRetry:(t,o)=>{Ce(1,`Retry ${t}/3: ${o.message}`)}}),this.client.interceptors.request.use(async t=>{if(this.credentials){let o=await this.getValidToken();o&&(t.headers.Authorization=`${o.token_type} ${o.access_token}`)}if(ae()>=2){let o=dn(t.url||"");if(Ce(2,`\u2192 ${t.method?.toUpperCase()} ${o}`),ae()>=3){let r=Ki(t.headers);Ce(3," Headers:",JSON.stringify(r,null,2))}}return t},t=>Promise.reject(t)),this.client.interceptors.response.use(t=>{if(ae()>=2){let o=dn(t.config.url||"");Ce(2,`\u2190 ${t.status} ${o}`)}return t},async t=>{if(ae()>=2){let o=dn(t.config?.url||"");Ce(2,`\u2190 ${t.response?.status||"ERROR"} ${o}`)}if(t.response?.status===401&&this.credentials&&t.config){let o=t.config;if(!o._retry){o._retry=!0;try{let r=await this.getValidToken();if(r)return o.headers.Authorization=`${r.token_type} ${r.access_token}`,this.client.request(o)}catch{console.error(_n.default.yellow("Token refresh failed during retry"))}}}return Promise.reject(t)})}async listAllTemplates(e=null){try{let t=e?{category:e}:{};return(await this.client.get(`/v1/projects/${this.projectId}/templates`,{params:t})).data}catch(t){throw this._handleError(t,"Failed to list templates")}}async listRuntimeTemplates(e,t=null){try{let o=t?{category:t}:{};return(await this.client.get(`/v1/projects/${this.projectId}/templates/${e}`,{params:o})).data}catch(o){throw this._handleError(o,`Failed to list ${e} templates`)}}async getTemplateDetails(e,t){try{return(await this.client.get(`/v1/projects/${this.projectId}/templates/${e}/${t}`)).data}catch(o){throw this._handleError(o,`Failed to get template details for ${e}/${t}`)}}async downloadTemplate(e,t){try{let o=await this.client.get(`/v1/projects/${this.projectId}/templates/${e}/${t}/download`,{responseType:"arraybuffer"});return Buffer.from(o.data)}catch(o){throw this._handleError(o,`Failed to download template ${e}/${t}`)}}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(t){throw this._handleError(t,`Failed to get function ${e}`)}}async deployFunction(e,t,o,r,s="public"){try{let a=new Ln.default;return a.append("name",e),a.append("runtime",t),a.append("code",o,{filename:"function.zip"}),a.append("accessLevel",s),r&&a.append("configuration",JSON.stringify(r)),(await this.client.post(`/v1/projects/${this.projectId}/functions`,a,{headers:{...a.getHeaders()},maxContentLength:1/0,maxBodyLength:1/0})).data}catch(a){throw this._handleError(a,"Failed to deploy function")}}async updateFunction(e,t,o){try{let r=new Ln.default;return r.append("code",t,{filename:"function.zip"}),o&&r.append("configuration",JSON.stringify(o)),(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(t){throw this._handleError(t,`Failed to delete function ${e}`)}}async downloadFunction(e){try{let t=await this.client.get(`/v1/projects/${this.projectId}/functions/${e}/download`,{responseType:"arraybuffer"});return Buffer.from(t.data)}catch(t){throw this._handleError(t,`Failed to download function ${e}`)}}async getFunctionLogs(e,t={}){try{return(await this.client.get(`/v1/projects/${this.projectId}/functions/${e}/logs`,{params:t})).data}catch(o){throw this._handleError(o,`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(t){throw this._handleError(t,`Failed to get status for function ${e}`)}}async generateDocumentationFromCode(e,t="node",o="function"){try{return(await this.client.post(`/v1/projects/${this.projectId}/test/documentation`,{Code:e,Runtime:t,Name:o})).data}catch(r){throw this._handleError(r,"Failed to generate documentation from code")}}async generateDocumentationForFunction(e,t){try{let o=t?{MarkdownOverride:t}:{};return(await this.client.post(`/v1/projects/${this.projectId}/functions/${e}/documentation`,o)).data}catch(o){throw this._handleError(o,`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(t){throw this._handleError(t,`Failed to get documentation for function ${e}`)}}async streamDeployment(e,t,o){let r=p=>p.status?"status":p.progress?"progress":p.completed?"completed":p.failed||p.error?"failed":p.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 p=await this.credentials.retrieve();if(p&&p.keyId&&p.keySecret){let d=Buffer.from(`${p.keyId}:${p.keySecret}`).toString("base64");a.Authorization=`Basic ${d}`}}catch(p){console.error("Failed to add authentication:",p)}let l=null;try{l=new AbortController;let p=await fetch(s,{method:"GET",headers:a,signal:l.signal});if(!p.ok)throw new Error(`SSE connection failed: ${p.status} ${p.statusText}`);if(!p.body)throw new Error("Response body is null");let d=p.body.getReader(),u=new TextDecoder,m="";return(async()=>{let h="";try{for(;;){let{done:C,value:v}=await d.read();if(C)break;let k=u.decode(v,{stream:!0});m+=k;let re=m.split(`
3
+ `);m=re.pop()||"";for(let j of re){if(j.startsWith("event:")){h=j.substring(6).trim();continue}if(j.startsWith("data:")){let M=j.substring(5).trim();if(M)try{let fe=JSON.parse(M),H=h||r(fe);t({type:H,data:fe}),h=""}catch{t({type:h||"message",data:M}),h=""}}j===""&&(h="")}}}catch(C){C.name!=="AbortError"&&o&&o(C)}})(),()=>{l&&l.abort()}}catch(p){throw console.error("Failed to create SSE stream:",p),o&&o(p),p}}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 t=await this.credentials.getBasicAuthToken();return t?{access_token:t,token_type:"Basic",expires_in:3600}:null}catch(e){return console.error(_n.default.yellow("Failed to get authentication token:",e.message)),null}}async authenticateOAuth(e,t){try{let o=this.oauthUrl,r=new URLSearchParams;r.append("grant_type","client_credentials");let a=(await pn.default.post(o,r,{headers:{"Content-Type":"application/x-www-form-urlencoded",Authorization:"Basic "+Buffer.from(`${e}:${t}`).toString("base64")},timeout:this.timeout})).data;return this.credentials&&await this.credentials.storeOAuthToken(a),a}catch(o){throw this._handleError(o,"OAuth authentication failed")}}async getTosStatus(){try{return(await this.client.get(`/v1/projects/${this.projectId}/terms-of-service`)).data}catch(e){throw this._handleError(e,"Failed to check Terms of Service status")}}async acceptTos(e,t){try{let o={acceptedBy:e};return t&&(o.version=t),(await this.client.post(`/v1/projects/${this.projectId}/terms-of-service`,o)).data}catch(o){throw this._handleError(o,"Failed to accept Terms of Service")}}_handleError(e,t){if(pn.default.isAxiosError(e)){let o=e;if(o.response){let r=o.response.status,s=o.response.data,a=s?.message||s?.error||o.message;throw r===401?new D('Authentication required. Please run "sinch auth login" first.',I.AUTH_REQUIRED):r===403?new D(`Permission denied: ${a}`,I.NO_PERMISSION):r===404?new D(`Resource not found: ${a}`,I.NOT_FOUND):r===409?new D(`Conflict: ${a}`,I.CONFLICT):r===429?new D(`Rate limited: ${a}`,I.UNAVAILABLE):r>=500?new D(`Server error: ${a}`,I.UNAVAILABLE):new D(`${t}: ${a}`,I.FAILURE)}else throw o.request?o.code==="ECONNREFUSED"?new D(`Cannot connect to API at ${this.baseUrl}. Is the server running?`,I.UNAVAILABLE):o.code==="ETIMEDOUT"?new D(`Request timeout after ${this.timeout}ms`,I.TIMEOUT):new D(`${t}: No response from server (${o.code||"unknown error"})`,I.IO_ERROR):new D(`${t}: ${o.message}`,I.FAILURE)}else throw new D(`${t}: ${e.message||e}`,I.FAILURE)}}});function fn(){if(!Un)try{Un=require("keytar")}catch{return null}return Un}var Gi,ce,Un,_t,Mn,mn,Yi=G(()=>{"use strict";Gi=y(require("os")),ce=y(require("chalk")),Un=null;_t="sinch-functions-cli",Mn=Gi.userInfo().username,mn=class{config;keychainAvailable=null;accountPrefix;constructor(e,t="default"){this.config=e,this.accountPrefix=t==="default"?Mn:`${t}-${Mn}`}async isKeychainAvailable(){if(this.keychainAvailable!==null)return this.keychainAvailable;if(this.config.get("keySecretPlaintext"))return this.keychainAvailable=!1,!1;try{let e=fn();if(!e)return this.keychainAvailable=!1,!1;let t=`${Mn}-test-${Date.now()}`;return await e.setPassword(_t,t,"test"),await e.deletePassword(_t,t),this.keychainAvailable=!0,!0}catch{return this.keychainAvailable=!1,!1}}async setPassword(e,t){if(!await this.isKeychainAvailable())return!1;let r=fn();return r?(await r.setPassword(_t,e,t),!0):!1}async getPassword(e){if(!await this.isKeychainAvailable())return null;let o=fn();return o?await o.getPassword(_t,e):null}async deletePassword(e){if(!await this.isKeychainAvailable())return!1;try{let o=fn();return o?(await o.deletePassword(_t,e),!0):!1}catch{return!0}}async store(e){let{projectId:t,keyId:o,keySecret:r,applicationKey:s,applicationSecret:a}=e,l=await this.setPassword(`${this.accountPrefix}-keySecret`,r),p=!0;s&&a&&(p=await this.setPassword(s,a)),l&&p?(this.config.set("keySecretPlaintext",null),a&&this.config.set("applicationSecretPlaintext",null)):(console.log(ce.default.yellow(`
4
+ \u26A0\uFE0F OS keychain not available (Docker/CI environment detected)`)),console.log(ce.default.yellow("\u26A0\uFE0F Storing secrets in plaintext config file")),console.log(ce.default.gray("Location: ~/.sinch/config.json")),console.log(ce.default.gray(`
5
+ For better security, export as environment variables instead:`)),console.log(ce.default.cyan(' export SINCH_KEY_SECRET="'+r+'"')),a&&console.log(ce.default.cyan(' export SINCH_APPLICATION_SECRET="'+a+'"')),this.config.set("keySecretPlaintext",r),a&&this.config.set("applicationSecretPlaintext",a)),this.config.set("projectId",t),this.config.set("keyId",o),s&&this.config.set("defaultApplicationKey",s),this.config.set("credentialsStored",!0),await this.config.save()}async storeOAuthToken(e){let{access_token:t,refresh_token:o,expires_in:r,token_type:s}=e,a=new Date(Date.now()+r*1e3).toISOString(),l=await this.setPassword(`${this.accountPrefix}-oauth-access`,t),p=!0;o&&(p=await this.setPassword(`${this.accountPrefix}-oauth-refresh`,o)),this.config.set("oauthTokenType",s),this.config.set("oauthExpiresAt",a),this.config.set("oauthStored",l&&p),await this.config.save()}async reAuthenticateOAuth(){try{let e=await this.retrieve();if(!e)return null;let{SinchAPI:t}=(Q(),F(et)),r=await new t({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 t=this.config.get("oauthExpiresAt");if(t&&new Date(t)<new Date){console.log(ce.default.gray("Token expired, re-authenticating..."));let o=await this.reAuthenticateOAuth();return o?console.log(ce.default.green("\u2713 Token renewed successfully")):console.warn(ce.default.yellow("Failed to renew OAuth token. Please login again.")),o}return await this.getPassword(`${this.accountPrefix}-oauth-access`)}async storeApplicationSecret(e,t){await this.setPassword(e,t),this.config.get("defaultApplicationKey")||(this.config.set("defaultApplicationKey",e),await this.config.save())}async retrieve(){let e=process.env.SINCH_KEY_ID,t=process.env.SINCH_KEY_SECRET,o=process.env.SINCH_APPLICATION_KEY,r=process.env.SINCH_APPLICATION_SECRET;if(e&&t)return{projectId:process.env.SINCH_PROJECT_ID||this.config.get("projectId")||"",keyId:e,keySecret:t,applicationKey:o||void 0,applicationSecret:r||void 0};if(!this.config.get("credentialsStored"))return null;let a=this.config.get("projectId"),l=this.config.get("keyId"),p=this.config.get("defaultApplicationKey"),d=await this.getPassword(`${this.accountPrefix}-keySecret`);if(d||(d=t||null),d||(d=this.config.get("keySecretPlaintext")),!d)return null;let u=null;return p&&(u=await this.getPassword(p),u||(u=r||null),u||(u=this.config.get("applicationSecretPlaintext"))),{projectId:a,keyId:l,keySecret:d,applicationKey:p||void 0,applicationSecret:u||void 0}}async getApplicationCredentials(e=null){if(e||(e=this.config.get("defaultApplicationKey")),!e)return null;let t=await this.getPassword(e);return t||(t=process.env.SINCH_APPLICATION_SECRET||null),t||(t=this.config.get("applicationSecretPlaintext")),t?{applicationKey:e,applicationSecret:t}:null}async clear(){let e=this.config.get("defaultApplicationKey");await this.deletePassword(`${this.accountPrefix}-keySecret`),await this.deletePassword(`${this.accountPrefix}-oauth-access`),await this.deletePassword(`${this.accountPrefix}-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(){return process.env.SINCH_KEY_ID&&process.env.SINCH_KEY_SECRET?!0:this.config.get("credentialsStored")?this.config.get("keySecretPlaintext")?!0:!!await this.getPassword(`${this.accountPrefix}-keySecret`):!1}async hasVoiceCredentials(){let e=process.env.SINCH_APPLICATION_KEY,t=process.env.SINCH_APPLICATION_SECRET;if(e&&t)return!0;let o=this.config.get("defaultApplicationKey");return o?await this.getPassword(o)?!0:!!this.config.get("applicationSecretPlaintext"):!1}async hasOAuthToken(){return this.config.get("oauthStored")?!!await this.getPassword(`${this.accountPrefix}-oauth-access`):!1}getPublicInfo(){return process.env.SINCH_KEY_ID&&process.env.SINCH_KEY_SECRET?{projectId:process.env.SINCH_PROJECT_ID||this.config.get("projectId"),keyId:process.env.SINCH_KEY_ID,applicationKey:process.env.SINCH_APPLICATION_KEY||this.config.get("defaultApplicationKey"),hasCredentials:!0,hasOAuth:!1,oauthExpiresAt:null,source:"environment"}:{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"),source:"config"}}async createSinchClient(e=null){let t=await this.retrieve();if(!t)throw new Error('No credentials found. Please run "sinch auth login" first.');let o=await this.getApplicationCredentials(e),{SinchClient:r}=require("@sinch/sdk-core");return new r({applicationKey:o?.applicationKey||t.applicationKey,applicationSecret:o?.applicationSecret||t.applicationSecret,projectId:t.projectId,keyId:t.keyId,keySecret:t.keySecret,conversationRegion:"us"})}async storeBasicAuthToken(e){await this.setPassword(`${this.accountPrefix}-basic-auth`,e)&&(this.config.set("basicAuthStored",!0),await this.config.save())}async getBasicAuthToken(){return this.config.get("basicAuthStored")?await this.getPassword(`${this.accountPrefix}-basic-auth`):null}async clearBasicAuthToken(){await this.deletePassword(`${this.accountPrefix}-basic-auth`),this.config.set("basicAuthStored",!1),await this.config.save()}async storeFax(e){let{projectId:t,keyId:o,keySecret:r}=e;await this.setPassword(`${this.accountPrefix}-fax-keySecret`,r)?this.config.set("faxKeySecretPlaintext",null):(console.log(ce.default.yellow(`
6
+ \u26A0\uFE0F OS keychain not available (Docker/CI environment detected)`)),console.log(ce.default.yellow("\u26A0\uFE0F Storing fax secret in plaintext config file")),console.log(ce.default.gray("Location: ~/.sinch/config.json")),console.log(ce.default.gray(`
7
+ For better security, export as environment variable instead:`)),console.log(ce.default.cyan(' export SINCH_FAX_KEY_SECRET="'+r+'"')),this.config.set("faxKeySecretPlaintext",r)),this.config.set("faxProjectId",t),this.config.set("faxKeyId",o),this.config.set("faxCredentialsStored",!0),await this.config.save()}async retrieveFax(){let e=process.env.SINCH_FAX_KEY_ID,t=process.env.SINCH_FAX_KEY_SECRET;if(e&&t)return{projectId:process.env.SINCH_FAX_PROJECT_ID||this.config.get("faxProjectId")||"",keyId:e,keySecret:t};if(!this.config.get("faxCredentialsStored"))return null;let r=this.config.get("faxProjectId"),s=this.config.get("faxKeyId"),a=await this.getPassword(`${this.accountPrefix}-fax-keySecret`);return a||(a=t||null),a||(a=this.config.get("faxKeySecretPlaintext")),a?{projectId:r,keyId:s,keySecret:a}:null}async hasFaxCredentials(){return process.env.SINCH_FAX_KEY_ID&&process.env.SINCH_FAX_KEY_SECRET?!0:this.config.get("faxCredentialsStored")?this.config.get("faxKeySecretPlaintext")?!0:!!await this.getPassword(`${this.accountPrefix}-fax-keySecret`):!1}async clearFax(){await this.deletePassword(`${this.accountPrefix}-fax-keySecret`),this.config.set("faxProjectId",null),this.config.set("faxKeyId",null),this.config.set("faxCredentialsStored",!1),this.config.set("faxKeySecretPlaintext",null),await this.config.save()}getFaxPublicInfo(){return process.env.SINCH_FAX_KEY_ID&&process.env.SINCH_FAX_KEY_SECRET?{projectId:process.env.SINCH_FAX_PROJECT_ID||this.config.get("faxProjectId"),keyId:process.env.SINCH_FAX_KEY_ID,hasCredentials:!0,source:"environment"}:{projectId:this.config.get("faxProjectId"),keyId:this.config.get("faxKeyId"),hasCredentials:this.config.get("faxCredentialsStored",!1),source:"config"}}}});var Ut={};xe(Ut,{ProfileManager:()=>gn,profileManager:()=>gt});var L,Se,Xi,gn,gt,ht=G(()=>{"use strict";L=y(require("fs-extra")),Se=y(require("path")),Xi=y(require("os")),gn=class{configDir;profilesDir;metaFile;constructor(){this.configDir=Se.join(Xi.homedir(),".sinch"),this.profilesDir=Se.join(this.configDir,"profiles"),this.metaFile=Se.join(this.configDir,"config.json")}async init(){await L.ensureDir(this.profilesDir),(await this.list()).length===0&&await this.migrateFromLegacy()}async migrateFromLegacy(){if(!await L.pathExists(this.metaFile)){await this.create("default");return}try{let e=await L.readJson(this.metaFile),t={name:"default",projectId:e.projectId,keyId:e.keyId,apiUrl:e.apiUrl,oauthUrl:e.oauthUrl,defaultApplicationKey:e.defaultApplicationKey,credentialsStored:e.credentialsStored,created:e.created||new Date().toISOString()};await L.writeJson(Se.join(this.profilesDir,"default.json"),t,{spaces:2}),e.activeProfile="default",await L.writeJson(this.metaFile,e,{spaces:2})}catch{await this.create("default")}}async create(e){let t=Se.join(this.profilesDir,`${e}.json`);if(await L.pathExists(t))throw new Error(`Profile '${e}' already exists`);let o={name:e,created:new Date().toISOString()};await L.ensureDir(this.profilesDir),await L.writeJson(t,o,{spaces:2})}async delete(e){let t=await this.getActive();if(e===t)throw new Error(`Cannot delete the active profile '${e}'. Switch to another profile first.`);let o=Se.join(this.profilesDir,`${e}.json`);if(!await L.pathExists(o))throw new Error(`Profile '${e}' does not exist`);await L.remove(o)}async use(e){let t=Se.join(this.profilesDir,`${e}.json`);if(!await L.pathExists(t))throw new Error(`Profile '${e}' does not exist`);let o=await this.getMeta();o.activeProfile=e,await L.writeJson(this.metaFile,o,{spaces:2})}async list(){if(!await L.pathExists(this.profilesDir))return[];let e=await L.readdir(this.profilesDir),t=await this.getActive(),o=[];for(let r of e)if(r.endsWith(".json"))try{let s=await L.readJson(Se.join(this.profilesDir,r));o.push({name:s.name,projectId:s.projectId,keyId:s.keyId,active:s.name===t,created:s.created})}catch{}return o}async getActive(){return(await this.getMeta()).activeProfile||"default"}async loadProfile(e){let t=e||await this.getActive(),o=Se.join(this.profilesDir,`${t}.json`);return await L.pathExists(o)?await L.readJson(o):(await this.create(t),{name:t,created:new Date().toISOString()})}async saveProfile(e){let t=Se.join(this.profilesDir,`${e.name}.json`);await L.ensureDir(this.profilesDir),await L.writeJson(t,e,{spaces:2})}async getMeta(){try{if(await L.pathExists(this.metaFile))return await L.readJson(this.metaFile)}catch{}return{activeProfile:"default"}}get profilesDirPath(){return this.profilesDir}},gt=new gn});var Oe={};xe(Oe,{config:()=>f});var be,Mt,Zi,qn,Jn,f,E=G(()=>{"use strict";be=y(require("fs-extra")),Mt=y(require("path")),Zi=y(require("os")),qn=y(require("chalk"));Yi();ht();Jn=class{configDir;configFile;projectConfigFile;_config=null;_projectConfig=null;_credentials=null;_profileName="default";_profileOverride=null;constructor(){this.configDir=Mt.join(Zi.homedir(),".sinch"),this.configFile=Mt.join(this.configDir,"config.json"),this.projectConfigFile=Mt.join(process.cwd(),"sinch.json")}setProfileOverride(e){this._profileOverride=e}getActiveProfileName(){return this._profileName}async load(){await gt.init(),this._profileName=this._profileOverride||await gt.getActive();try{let t=await gt.loadProfile(this._profileName);this._config=this._profileDataToConfig(t)}catch(t){console.warn(qn.default.yellow(`Warning: Could not load profile '${this._profileName}': ${t.message}`)),this._config=this._getDefaultConfig()}this._credentials=new mn(this,this._profileName);let e=this.get("debug",0);if(e>0){let{setConfigDebugLevel:t}=(Lt(),F(zi));t(e)}try{await be.pathExists(this.projectConfigFile)&&(this._projectConfig=await be.readJson(this.projectConfigFile))}catch(t){console.warn(qn.default.yellow(`Warning: Could not load project config: ${t.message}`))}}async save(){try{let e=this._configToProfileData(this._config);await gt.saveProfile(e),await be.ensureDir(this.configDir);let t=await be.pathExists(this.configFile)?await be.readJson(this.configFile):{};t.activeProfile=this._profileName,t.apiUrl=this._config?.apiUrl,t.projectId=this._config?.projectId,await be.writeJson(this.configFile,t,{spaces:2})}catch(e){throw new Error(`Could not save config: ${e.message}`)}}_profileDataToConfig(e){return{apiUrl:e.apiUrl||"https://functions.api.sinch.com",oauthUrl:e.oauthUrl||"https://auth.sinch.com/oauth2/token",projectId:e.projectId||"default-project",created:e.created,keyId:e.keyId,defaultApplicationKey:e.defaultApplicationKey,credentialsStored:e.credentialsStored,...e}}_configToProfileData(e){return{name:this._profileName,projectId:e.projectId,keyId:e.keyId,apiUrl:e.apiUrl,oauthUrl:e.oauthUrl,defaultApplicationKey:e.defaultApplicationKey,credentialsStored:e.credentialsStored,created:e.created,...e}}async saveProjectConfig(){try{if(this._projectConfig){let e=Mt.join(process.cwd(),"sinch.json");await be.writeJson(e,this._projectConfig,{spaces:2})}}catch(e){throw new Error(`Could not save project config: ${e.message}`)}}get(e,t=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]:t}set(e,t,o=!1){if(!this._config)throw new Error("Config not loaded. Call load() first.");o?(this._projectConfig||(this._projectConfig={}),this._projectConfig[e]=t):this._config[e]=t}getApiConfig(){return{apiUrl:this.get("apiUrl"),oauthUrl:this.get("oauthUrl","https://auth.sinch.com/oauth2/token"),projectId:this.get("projectId"),credentials:this._credentials}}async initProject(e,t="node",o={},r=null){let s={name:e,runtime:t,description:`Sinch Functions project: ${e}`,created:new Date().toISOString()};return o&&Object.keys(o).length>0&&(s.variables=o),r&&(s.applicationKey=r),this._projectConfig=s,await this.saveProjectConfig(),s}isInProject(){return this._projectConfig!==null}getProjectConfig(){return this._projectConfig}_getDefaultConfig(){return{apiUrl:"https://functions.api.sinch.com",oauthUrl:"https://auth.sinch.com/oauth2/token",projectId:"default-project",created:new Date().toISOString()}}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,t){if(!this._credentials)throw new Error("Config not loaded. Call load() first.");return await this._credentials.storeApplicationSecret(e,t)}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()}async setFaxServiceId(e){this.set("faxServiceId",e),await this.save()}getFaxServiceId(){return this.get("faxServiceId",null)}async setFaxSenderNumber(e){this.set("faxSenderNumber",e),await this.save()}getFaxSenderNumber(){return this.get("faxSenderNumber",null)}async storeFaxCredentials(e){if(!this._credentials)throw new Error("Config not loaded. Call load() first.");return await this._credentials.storeFax(e)}async getFaxCredentials(){if(!this._credentials)throw new Error("Config not loaded. Call load() first.");return await this._credentials.retrieveFax()}async hasFaxCredentials(){if(!this._credentials)throw new Error("Config not loaded. Call load() first.");return await this._credentials.hasFaxCredentials()}async clearFaxCredentials(){if(!this._credentials)throw new Error("Config not loaded. Call load() first.");return await this._credentials.clearFax()}getFaxPublicCredentialInfo(){if(!this._credentials)throw new Error("Config not loaded. Call load() first.");return this._credentials.getFaxPublicInfo()}},f=new Jn});var eo={};xe(eo,{logger:()=>n});var ne,Ve,Vn,Qi,Bn,n,T=G(()=>{"use strict";ne=y(require("chalk")),Ve=y(require("fs")),Vn=y(require("path")),Qi=y(require("os"));Lt();Bn=class{logFile;constructor(){let e="cli";try{let t=Vn.join(process.cwd(),"sinch.json");Ve.existsSync(t)&&(e=JSON.parse(Ve.readFileSync(t,"utf8")).name||"cli")}catch{}this.logFile=Vn.join(Qi.tmpdir(),`sinch-${e}.log`);try{Ve.writeFileSync(this.logFile,`=== Sinch CLI Debug Log - ${new Date().toISOString()} ===
8
8
  `,{flag:"w"})}catch{}}writeToFile(e,t,...o){try{let s=`[${new Date().toISOString()}] ${e}: ${t} ${o.length>0?JSON.stringify(o):""}
9
- `;Ue.appendFileSync(this.logFile,s)}catch{}}info(e,...t){console.log(ne.default.blue("\u2139"),e,...t),this.writeToFile("INFO",e,...t)}success(e,...t){console.log(ne.default.green("\u2705"),e,...t),this.writeToFile("SUCCESS",e,...t)}warn(e,...t){console.log(ne.default.yellow("\u26A0\uFE0F "),e,...t),this.writeToFile("WARN",e,...t)}error(e,...t){console.log(ne.default.red("\u274C"),e,...t),this.writeToFile("ERROR",e,...t)}debug(e,...t){this.writeToFile("DEBUG",e,...t),se()>=1&&console.log(ne.default.gray("\u{1F41B}"),ne.default.gray(e),...t)}httpDebug(e,...t){this.writeToFile("HTTP",e,...t),se()>=2&&console.log(ne.default.gray("\u{1F310}"),ne.default.gray(e),...t)}verboseDebug(e,...t){this.writeToFile("VERBOSE",e,...t),se()>=3&&console.log(ne.default.gray("\u{1F4CB}"),ne.default.gray(e),...t)}log(e,...t){console.log(e,...t)}title(e){console.log(ne.default.blue.bold(`
9
+ `;Ve.appendFileSync(this.logFile,s)}catch{}}info(e,...t){console.log(ne.default.blue("\u2139"),e,...t),this.writeToFile("INFO",e,...t)}success(e,...t){console.log(ne.default.green("\u2705"),e,...t),this.writeToFile("SUCCESS",e,...t)}warn(e,...t){console.log(ne.default.yellow("\u26A0\uFE0F "),e,...t),this.writeToFile("WARN",e,...t)}error(e,...t){console.log(ne.default.red("\u274C"),e,...t),this.writeToFile("ERROR",e,...t)}debug(e,...t){this.writeToFile("DEBUG",e,...t),ae()>=1&&console.log(ne.default.gray("\u{1F41B}"),ne.default.gray(e),...t)}httpDebug(e,...t){this.writeToFile("HTTP",e,...t),ae()>=2&&console.log(ne.default.gray("\u{1F310}"),ne.default.gray(e),...t)}verboseDebug(e,...t){this.writeToFile("VERBOSE",e,...t),ae()>=3&&console.log(ne.default.gray("\u{1F4CB}"),ne.default.gray(e),...t)}log(e,...t){console.log(e,...t)}title(e){console.log(ne.default.blue.bold(`
10
10
  \u{1F3AF} ${e}`))}subtitle(e){console.log(ne.default.gray(`
11
- ${e}`))}list(e,t={}){let{indent:o=" ",bullet:r="\u2022"}=t;e.forEach(s=>{console.log(`${o}${ne.default.gray(r)} ${s}`)})}calculateColumnWidths(e,t){let o=e.map(r=>r.length);return t.forEach(r=>{r.forEach((s,a)=>{o[a]=Math.max(o[a]??0,String(s).length)})}),o}table(e,t){let o=this.calculateColumnWidths(e,t),r=e.map((s,a)=>s.padEnd(o[a]??0)).join(" ");console.log(ne.default.bold(r)),console.log(ne.default.gray("-".repeat(r.length))),t.forEach(s=>{let a=s.map((l,p)=>String(l).padEnd(o[p]??0)).join(" ");console.log(a)})}newline(){console.log()}},n=new On});var mt={};xe(mt,{spinner:()=>c});var _i,Ui,jn,c,D=W(()=>{"use strict";_i=y(require("ora")),Ui=y(require("cli-spinners")),jn=class{spinner=null;spinnerType=Ui.default.dots;start(e){return this.spinner=(0,_i.default)({text:e,spinner:this.spinnerType}).start(),this}succeed(e){return this.spinner&&(this.spinner.succeed(e),this.spinner=null),this}fail(e){return this.spinner&&(this.spinner.fail(e),this.spinner=null),this}info(e){return this.spinner&&(this.spinner.info(e),this.spinner=null),this}warn(e){return this.spinner&&(this.spinner.warn(e),this.spinner=null),this}stop(){return this.spinner&&(this.spinner.stop(),this.spinner=null),this}update(e){return this.spinner&&(this.spinner.text=e),this}get isSpinning(){return this.spinner?.isSpinning??!1}get text(){return this.spinner?.text??""}set text(e){this.spinner&&(this.spinner.text=e)}},c=new jn});var Bi=x((el,Ji)=>{"use strict";var G=y(require("fs-extra")),qe=y(require("path")),Z=y(require("chalk")),Me=y(require("inquirer")),qi=require("commander");A();E();D();X();var gt=require("child_process"),Mi=y(require("adm-zip")),Fn=y(require("keytar")),Vi=new qi.Command("init");Vi.description("Initialize a new Sinch Functions project").argument("[template]","Template to use (simple-ivr, customer-lookup, smart-routing)").option("--name <name>","Function name (default: template name)").option("--runtime <runtime>","Runtime to use (node, csharp)").option("--skip-install","Skip npm install for Node.js projects").option("--non-interactive","Use default values without prompting").action(async(i,e)=>{try{await f.load();let t=process.cwd(),o=new V(f.getApiConfig()),r=e.runtime;r||(e.nonInteractive?r="node":r=(await Me.default.prompt([{type:"list",name:"runtime",message:"Choose a runtime:",choices:[{name:"Node.js",value:"node"},{name:"C# (.NET)",value:"csharp"}],default:"node"}])).runtime),c.start(`Fetching available templates for ${r}...`);let s=await o.listRuntimeTemplates(r);if(c.stop(),!s.templates||s.templates.length===0)throw new Error(`No templates available for runtime '${r}'`);let a=i;if(!a)if(e.nonInteractive){let S=s.templates.filter(I=>I.name&&I.name.trim());if(S.length>0)a=S[0]?.name||"",n.info(`Using default template: ${a} (non-interactive mode)`);else throw new Error("No templates available")}else{let S=s.templates.filter(b=>b.name&&b.name.trim()).map(b=>({name:`${b.name} - ${(b.description||"No description available").substring(0,100)}`,value:b.name}));a=(await Me.default.prompt([{type:"list",name:"selectedTemplate",message:"Choose a template:",choices:S,pageSize:10}])).selectedTemplate}let l=e.name;l||(e.nonInteractive?l=a:l=(await Me.default.prompt([{type:"input",name:"name",message:"Function name:",default:a,validate:I=>!I||I.trim().length===0?"Function name is required":/^[a-z][a-z0-9-]*$/.test(I.trim())?!0:"Function name must be lowercase, start with a letter, and contain only letters, numbers, and hyphens"}])).name.trim());let p=qe.default.join(t,l);if(await G.default.pathExists(p)){let S=!1;if(e.nonInteractive?(S=!0,n.info(`Directory '${l}' already exists. Overwriting (non-interactive mode)...`)):S=(await Me.default.prompt([{type:"confirm",name:"overwrite",message:`Directory '${l}' already exists. Overwrite?`,default:!1}])).overwrite,!S){n.info("Initialization cancelled");return}await G.default.remove(p)}await G.default.ensureDir(p);let d=s.templates.find(S=>S.name===a);if(!d){let S=s.templates.map(I=>I.name).join(", ");throw new Error(`Template '${a}' not found. Available templates: ${S}`)}let u=["node","csharp"];if(!u.includes(r))throw new Error(`Runtime '${r}' not supported. Supported runtimes: ${u.join(", ")}`);c.start(`\u{1F680} Initializing ${l} with ${a} template (${r})...`);let m=await o.downloadTemplate(r,a);new Mi.default(m).extractAllTo(p,!0),c.succeed("\u{1F4E6} Template extracted");let h={},C=[],v=d.category,T=qe.default.join(p,"template.json");if(await G.default.pathExists(T)){let S=await G.default.readJson(T);if(S.category&&(v=S.category),!v&&S.requirements?.sinchServices?.includes("voice")&&(v="voice"),S.variables&&Object.keys(S.variables).length>0)if(e.nonInteractive){n.info("\u{1F4DD} Using default values for template variables (non-interactive mode):");for(let[b,j]of Object.entries(S.variables)){let re;typeof j=="string"?re=j:re=j.default||"",h[b]=re,n.info(` ${b}: ${re}`)}}else{n.newline(),n.info("\u{1F4DD} Configure template variables:");for(let[b,j]of Object.entries(S.variables)){let re;typeof j=="string"?re={type:"input",name:b,message:`${b.replace(/_/g," ").toLowerCase()}:`,default:j}:(re={type:j.type==="number"?"number":"input",name:b,message:`${j.description||b.replace(/_/g," ").toLowerCase()}:`,default:j.default},j.type==="number"&&(re.validate=_e=>j.min!==void 0&&_e<j.min?`Value must be at least ${j.min}`:j.max!==void 0&&_e>j.max?`Value must be at most ${j.max}`:!0));let Ee=await Me.default.prompt([re]);h[b]=Ee[b]}}let I="sinch-functions-cli";if(S.secrets&&Object.keys(S.secrets).length>0)if(C=Object.keys(S.secrets),e.nonInteractive){n.info("\u{1F4DD} Template secrets detected (non-interactive mode):");for(let b of Object.keys(S.secrets))n.info(` ${b}: [will need to be set manually]`)}else{n.newline(),n.info("\u{1F510} Configure template secrets (stored securely in OS keychain):");for(let[b,j]of Object.entries(S.secrets)){let re=j.description||b.replace(/_/g," ").toLowerCase(),Ee=j.required!==!1,_e={type:"password",name:b,message:`${re}:`,validate:te=>Ee&&(!te||te.trim()==="")?"This secret is required":!0},xt=(await Me.default.prompt([_e]))[b];if(xt&&xt.trim()!=="")try{let te=`${l}-${b}`;await Fn.default.setPassword(I,te,xt),n.info(` \u2705 ${b} stored securely in keychain`)}catch(te){n.warn(` \u26A0\uFE0F Could not store ${b} in keychain: ${te.message}`),n.info(` \u{1F4A1} You can add it later with: sinch secrets add ${b} <value>`)}}}await G.default.remove(T)}let ee=v==="voice";if(ee&&!e.nonInteractive&&!await f.getApplicationCredentials()){n.newline(),n.info(Z.default.blue("\u{1F50A} This template uses voice callbacks and needs Voice application credentials.")),n.info(Z.default.gray(` You can find these in the Sinch Dashboard under your Voice app.
12
- `));let I=await Me.default.prompt([{type:"input",name:"applicationKey",message:"Voice Application Key:",validate:b=>b.length>0||"Application Key is required for voice templates"},{type:"password",name:"applicationSecret",message:"Voice Application Secret:",validate:b=>b.length>0||"Application Secret is required for voice templates"}]);await f.storeApplicationSecret(I.applicationKey,I.applicationSecret),f.set("defaultApplicationKey",I.applicationKey),await f.save(),n.info(Z.default.green(" \u2705 Voice credentials stored securely"))}c.start("\u{1F527} Finalizing function configuration...");let O=qe.default.join(p,"sinch.json"),P;if(await G.default.pathExists(O)){if(P=await G.default.readJson(O),P.name=l,P.description=`Sinch Functions function: ${l}`,P.functionId=null,delete P.projectId,delete P.voiceAppId,P.variables)for(let[S,I]of Object.entries(P.variables))typeof I=="string"&&(I==="your-project-id"||I==="{{PROJECT_ID}}"?P.variables[S]=f.get("projectId"):(I==="your-application-key"||I==="{{SINCH_APPLICATION_KEY}}")&&(P.variables[S]=f.get("defaultApplicationKey")));P.created=new Date().toISOString(),P.variables={},P.secrets&&delete P.secrets}else P={name:l,functionId:null,runtime:r,description:`Sinch Functions function: ${l}`,created:new Date().toISOString(),variables:{},custom:{}};if(await G.default.writeJson(O,P,{spaces:2}),r==="node"){let S=qe.default.join(p,"package.json");if(await G.default.pathExists(S)){let F=await G.default.readJson(S);F.name=l,F.description=P.description,await G.default.writeJson(S,F,{spaces:2})}let I=qe.default.join(p,".env"),b=`# Sinch Functions Environment Variables
13
- `;b+=`# Generated by sinch functions init
11
+ ${e}`))}list(e,t={}){let{indent:o=" ",bullet:r="\u2022"}=t;e.forEach(s=>{console.log(`${o}${ne.default.gray(r)} ${s}`)})}calculateColumnWidths(e,t){let o=e.map(r=>r.length);return t.forEach(r=>{r.forEach((s,a)=>{o[a]=Math.max(o[a]??0,String(s).length)})}),o}table(e,t){let o=this.calculateColumnWidths(e,t),r=e.map((s,a)=>s.padEnd(o[a]??0)).join(" ");console.log(ne.default.bold(r)),console.log(ne.default.gray("-".repeat(r.length))),t.forEach(s=>{let a=s.map((l,p)=>String(l).padEnd(o[p]??0)).join(" ");console.log(a)})}newline(){console.log()}},n=new Bn});var yt={};xe(yt,{spinner:()=>c});var to,no,Kn,c,R=G(()=>{"use strict";to=y(require("ora")),no=y(require("cli-spinners")),Kn=class{spinner=null;spinnerType=no.default.dots;start(e){return this.spinner=(0,to.default)({text:e,spinner:this.spinnerType}).start(),this}succeed(e){return this.spinner&&(this.spinner.succeed(e),this.spinner=null),this}fail(e){return this.spinner&&(this.spinner.fail(e),this.spinner=null),this}info(e){return this.spinner&&(this.spinner.info(e),this.spinner=null),this}warn(e){return this.spinner&&(this.spinner.warn(e),this.spinner=null),this}stop(){return this.spinner&&(this.spinner.stop(),this.spinner=null),this}update(e){return this.spinner&&(this.spinner.text=e),this}get isSpinning(){return this.spinner?.isSpinning??!1}get text(){return this.spinner?.text??""}set text(e){this.spinner&&(this.spinner.text=e)}},c=new Kn});var ao=N((Ll,so)=>{"use strict";var X=y(require("fs-extra")),Be=y(require("path")),ee=y(require("chalk")),Fe=y(require("inquirer")),io=require("commander");E();T();R();Q();var wt=require("child_process"),oo=y(require("adm-zip")),Hn=y(require("keytar")),ro=new io.Command("init");ro.description("Initialize a new Sinch Functions project").argument("[template]","Template to use (simple-ivr, customer-lookup, smart-routing)").option("--name <name>","Function name (default: template name)").option("--runtime <runtime>","Runtime to use (node, csharp)").option("--skip-install","Skip npm install for Node.js projects").option("--non-interactive","Use default values without prompting").action(async(i,e)=>{try{await f.load();let t=process.cwd(),o=new J(f.getApiConfig()),r=e.runtime;r||(e.nonInteractive?r="node":r=(await Fe.default.prompt([{type:"list",name:"runtime",message:"Choose a runtime:",choices:[{name:"Node.js",value:"node"},{name:"C# (.NET)",value:"csharp"}],default:"node"}])).runtime),c.start(`Fetching available templates for ${r}...`);let s=await o.listRuntimeTemplates(r);if(c.stop(),!s.templates||s.templates.length===0)throw new Error(`No templates available for runtime '${r}'`);let a=i;if(!a)if(e.nonInteractive){let S=s.templates.filter(b=>b.name&&b.name.trim());if(S.length>0)a=S[0]?.name||"",n.info(`Using default template: ${a} (non-interactive mode)`);else throw new Error("No templates available")}else{let S=s.templates.filter($=>$.name&&$.name.trim()).map($=>({name:`${$.name} - ${($.description||"No description available").substring(0,100)}`,value:$.name}));a=(await Fe.default.prompt([{type:"list",name:"selectedTemplate",message:"Choose a template:",choices:S,pageSize:10}])).selectedTemplate}let l=e.name;l||(e.nonInteractive?l=a:l=(await Fe.default.prompt([{type:"input",name:"name",message:"Function name:",default:a,validate:b=>!b||b.trim().length===0?"Function name is required":/^[a-z][a-z0-9-]*$/.test(b.trim())?!0:"Function name must be lowercase, start with a letter, and contain only letters, numbers, and hyphens"}])).name.trim());let p=Be.default.join(t,l);if(await X.default.pathExists(p)){let S=!1;if(e.nonInteractive?(S=!0,n.info(`Directory '${l}' already exists. Overwriting (non-interactive mode)...`)):S=(await Fe.default.prompt([{type:"confirm",name:"overwrite",message:`Directory '${l}' already exists. Overwrite?`,default:!1}])).overwrite,!S){n.info("Initialization cancelled");return}await X.default.remove(p)}await X.default.ensureDir(p);let d=s.templates.find(S=>S.name===a);if(!d){let S=s.templates.map(b=>b.name).join(", ");throw new Error(`Template '${a}' not found. Available templates: ${S}`)}let u=["node","csharp"];if(!u.includes(r))throw new Error(`Runtime '${r}' not supported. Supported runtimes: ${u.join(", ")}`);c.start(`\u{1F680} Initializing ${l} with ${a} template (${r})...`);let m=await o.downloadTemplate(r,a);new oo.default(m).extractAllTo(p,!0),c.succeed("\u{1F4E6} Template extracted");let h={},C=[],v=d.category,k=[],re=Be.default.join(p,"template.json");if(await X.default.pathExists(re)){let S=await X.default.readJson(re);S.category&&(v=S.category),!v&&S.requirements?.sinchServices?.includes("voice")&&(v="voice");let b=new Set(["voice","conversation"]);k=(S.requirements?.sinchServices??[]).filter(O=>b.has(O));let $=["AUTO_CONFIGURE_VOICE","AUTO_CONFIGURE_CONVERSATION"],me=S.variables?Object.fromEntries(Object.entries(S.variables).filter(([O])=>!$.includes(O))):{};if(Object.keys(me).length>0)if(e.nonInteractive){n.info("\u{1F4DD} Using default values for template variables (non-interactive mode):");for(let[O,K]of Object.entries(me)){let P;typeof K=="string"?P=K:P=K.default||"",h[O]=P,n.info(` ${O}: ${P}`)}}else{n.newline(),n.info("\u{1F4DD} Configure template variables:");for(let[O,K]of Object.entries(me)){let P;typeof K=="string"?P={type:"input",name:O,message:`${O.replace(/_/g," ").toLowerCase()}:`,default:K}:(P={type:K.type==="number"?"number":"input",name:O,message:`${K.description||O.replace(/_/g," ").toLowerCase()}:`,default:K.default},K.type==="number"&&(P.validate=de=>K.min!==void 0&&de<K.min?`Value must be at least ${K.min}`:K.max!==void 0&&de>K.max?`Value must be at most ${K.max}`:!0));let xt=await Fe.default.prompt([P]);h[O]=xt[O]}}let Dt="sinch-functions-cli";if(S.secrets&&Object.keys(S.secrets).length>0)if(C=Object.keys(S.secrets),e.nonInteractive){n.info("\u{1F4DD} Template secrets detected (non-interactive mode):");for(let O of Object.keys(S.secrets))n.info(` ${O}: [will need to be set manually]`)}else{n.newline(),n.info("\u{1F510} Configure template secrets (stored securely in OS keychain):");for(let[O,K]of Object.entries(S.secrets)){let P=K.description||O.replace(/_/g," ").toLowerCase(),xt=K.required!==!1,de={type:"password",name:O,message:`${P}:`,validate:pe=>xt&&(!pe||pe.trim()==="")?"This secret is required":!0},se=(await Fe.default.prompt([de]))[O];if(se&&se.trim()!=="")try{let pe=`${l}-${O}`;await Hn.default.setPassword(Dt,pe,se),n.info(` \u2705 ${O} stored securely in keychain`)}catch(pe){n.warn(` \u26A0\uFE0F Could not store ${O} in keychain: ${pe.message}`),n.info(` \u{1F4A1} You can add it later with: sinch secrets add ${O} <value>`)}}}await X.default.remove(re)}let j=k.length>0;if(k.length>0&&!e.nonInteractive){let S=k.join(" + "),{autoConfig:b}=await Fe.default.prompt([{type:"confirm",name:"autoConfig",message:`Auto-configure ${S} integration on deploy?`,default:!0}]);j=b}let M=v==="voice";if(M&&!e.nonInteractive&&!await f.getApplicationCredentials()){n.newline(),n.info(ee.default.blue("\u{1F50A} This template uses voice callbacks and needs Voice application credentials.")),n.info(ee.default.gray(` You can find these in the Sinch Dashboard under your Voice app.
12
+ `));let b=await Fe.default.prompt([{type:"input",name:"applicationKey",message:"Voice Application Key:",validate:$=>$.length>0||"Application Key is required for voice templates"},{type:"password",name:"applicationSecret",message:"Voice Application Secret:",validate:$=>$.length>0||"Application Secret is required for voice templates"}]);await f.storeApplicationSecret(b.applicationKey,b.applicationSecret),f.set("defaultApplicationKey",b.applicationKey),await f.save(),n.info(ee.default.green(" \u2705 Voice credentials stored securely"))}c.start("\u{1F527} Finalizing function configuration...");let fe=Be.default.join(p,"sinch.json"),H;if(await X.default.pathExists(fe)){if(H=await X.default.readJson(fe),H.name=l,H.description=`Sinch Functions function: ${l}`,H.functionId=null,delete H.projectId,delete H.voiceAppId,H.variables)for(let[S,b]of Object.entries(H.variables))typeof b=="string"&&(b==="your-project-id"||b==="{{PROJECT_ID}}"?H.variables[S]=f.get("projectId"):(b==="your-application-key"||b==="{{SINCH_APPLICATION_KEY}}")&&(H.variables[S]=f.get("defaultApplicationKey")));H.created=new Date().toISOString(),H.variables={},H.secrets&&delete H.secrets}else H={name:l,functionId:null,runtime:r,description:`Sinch Functions function: ${l}`,created:new Date().toISOString(),variables:{},custom:{}};if(await X.default.writeJson(fe,H,{spaces:2}),r==="node"){let S=Be.default.join(p,"package.json");if(await X.default.pathExists(S)){let P=await X.default.readJson(S);P.name=l,P.description=H.description,await X.default.writeJson(S,P,{spaces:2})}let b=Be.default.join(p,".env"),$=`# Sinch Functions Environment Variables
13
+ `;$+=`# Generated by sinch functions init
14
14
 
15
- `,b+=`# Template Variables
16
- `,Object.keys(h).forEach(F=>{b+=`${F}=${h[F]}
17
- `});let j=f.get("projectId"),re=f.get("functionId"),Ee=f.get("defaultApplicationKey"),_e=f.get("keyId");b+=`
15
+ `,$+=`# Template Variables
16
+ `,Object.keys(h).forEach(P=>{$+=`${P}=${h[P]}
17
+ `});let me=f.get("projectId"),Dt=f.get("functionId"),O=f.get("defaultApplicationKey"),K=f.get("keyId");$+=`
18
18
  # Sinch Configuration
19
- `,b+=`PROJECT_ID=${j||""}
20
- `,b+=`FUNCTION_ID=${re||""}
21
- `,b+=`PROJECT_ID_API_KEY=${_e||""}
22
- `,(ee||Ee)&&(b+=`VOICE_APPLICATION_KEY=${Ee||""}
23
- `,b+=`PROTECT_VOICE_CALLBACKS=deploy
24
- `),b+=`
19
+ `,$+=`PROJECT_ID=${me||""}
20
+ `,$+=`FUNCTION_ID=${Dt||""}
21
+ `,$+=`PROJECT_ID_API_KEY=${K||""}
22
+ `,(M||O)&&($+=`VOICE_APPLICATION_KEY=${O||""}
23
+ `,$+=`PROTECT_VOICE_CALLBACKS=deploy
24
+ `),$+=`
25
25
  # Secrets (stored in OS keychain - use "sinch auth login" to configure)
26
- `,b+=`PROJECT_ID_API_SECRET=
27
- `,(ee||Ee)&&(b+=`VOICE_APPLICATION_SECRET=
28
- `),C.length>0&&(b+=`
26
+ `,$+=`PROJECT_ID_API_SECRET=
27
+ `,(M||O)&&($+=`VOICE_APPLICATION_SECRET=
28
+ `),C.length>0&&($+=`
29
29
  # Template Secrets (stored in OS keychain - use "sinch secrets add <KEY> <VALUE>")
30
- `,C.forEach(F=>{b+=`${F}=
31
- `})),b+=`
30
+ `,C.forEach(P=>{$+=`${P}=
31
+ `})),k.length>0&&($+=`
32
+ # Sinch Service Auto-Configuration
33
+ `,$+=`AUTO_CONFIGURE=${j}
34
+ `,$+=`SINCH_SERVICES=${k.join(",")}
35
+ `),$+=`
32
36
  # Environment
33
- `,b+=`NODE_ENV=development
34
- `,b+=`PORT=3000
35
- `,b+=`SINCH_TUNNEL=false
36
- `,await G.default.writeFile(I,b),n.info(""),n.info("\u{1F510} Secrets Management for Node.js:");try{let F=await f.getCredentials();F&&F.keySecret?(n.info(" \u2705 Sinch credentials found in secure storage"),n.info(" \u2705 F5 debugging will automatically load secrets from OS keychain"),n.info(""),n.info(" \u{1F4A1} To add custom secrets, use:"),n.info(` ${Z.default.cyan("sinch functions secrets add <KEY> <VALUE>")}`)):(n.info(" \u26A0\uFE0F No Sinch credentials found in secure storage"),n.info(""),n.info(" To set up authentication:"),n.info(` ${Z.default.cyan("sinch auth login")}`),n.info(""),n.info(" To add custom secrets:"),n.info(` ${Z.default.cyan("sinch functions secrets add <KEY> <VALUE>")}`))}catch{n.info(" \u2139\uFE0F Set up authentication with:"),n.info(` ${Z.default.cyan("sinch auth login")}`)}n.info(""),n.info(" \u{1F4DD} Note: Secrets are stored securely in your OS keychain"),n.info(" \u{1F4DD} Note: F5 debugging requires keytar (npm install keytar)")}if(r==="csharp"){let S=qe.default.join(p,"appsettings.json"),I;await G.default.pathExists(S)?I=await G.default.readJson(S):I={Logging:{LogLevel:{Default:"Information","Microsoft.AspNetCore":"Warning"}},AllowedHosts:"*"},I.Logging||(I.Logging={LogLevel:{Default:"Information","Microsoft.AspNetCore":"Warning"}}),I.AllowedHosts||(I.AllowedHosts="*"),Object.keys(h).forEach(F=>{I[F]=h[F]});let b=f.get("projectId"),j=f.get("defaultApplicationKey"),re=f.get("keyId");I.PROJECT_ID=b||"",I.PROJECT_ID_API_KEY=re||"",I.PROJECT_ID_API_SECRET="",(ee||j)&&(I.VOICE_APPLICATION_KEY=j||"",I.VOICE_APPLICATION_SECRET=""),C.forEach(F=>{I[F]=""}),await G.default.writeJson(S,I,{spaces:2});let Ee=qe.default.join(p,"appsettings.Development.json"),_e={Logging:{LogLevel:{Default:"Debug","Microsoft.AspNetCore":"Information"}},SinchTunnel:!1};await G.default.writeJson(Ee,_e,{spaces:2});try{let F=await f.getCredentials();await new Promise((te,ge)=>{let he=(0,gt.spawn)("dotnet",["user-secrets","init"],{cwd:p,shell:!0});he.on("close",Xe=>Xe===0?te():ge(new Error("Failed to init user-secrets"))),he.on("error",ge)}),F&&F.keySecret&&await new Promise((te,ge)=>{let he=(0,gt.spawn)("dotnet",["user-secrets","set","PROJECT_ID_API_SECRET",F.keySecret],{cwd:p,shell:!0});he.on("close",Xe=>Xe===0?te():ge(new Error("Failed to set API secret"))),he.on("error",ge)}),F&&F.applicationSecret&&await new Promise((te,ge)=>{let he=(0,gt.spawn)("dotnet",["user-secrets","set","VOICE_APPLICATION_SECRET",F.applicationSecret],{cwd:p,shell:!0});he.on("close",Xe=>Xe===0?te():ge(new Error("Failed to set app secret"))),he.on("error",ge)});let xt="sinch-functions-cli";for(let te of C)try{let ge=`${l}-${te}`,he=await Fn.default.getPassword(xt,ge);he&&await new Promise((Xe,$i)=>{let Pi=(0,gt.spawn)("dotnet",["user-secrets","set",te,he],{cwd:p,shell:!0});Pi.on("close",Ds=>Ds===0?Xe():$i(new Error(`Failed to set ${te}`))),Pi.on("error",$i)})}catch{}(F&&(F.keySecret||F.applicationSecret)||C.length>0)&&(n.info(""),n.info("\u{1F510} Secrets Management for C#:"),n.info(" \u2705 User secrets have been configured automatically"),n.info(" You can view them with: "+Z.default.cyan("dotnet user-secrets list")),C.length>0&&n.info(" \u{1F4A1} Template secrets have been added to user-secrets"))}catch{n.info(""),n.info("\u{1F510} Secrets Management for C#:"),n.info(" For local development, use dotnet user-secrets:"),n.info(` ${Z.default.cyan("dotnet user-secrets init")}`),n.info(` ${Z.default.cyan('dotnet user-secrets set "PROJECT_ID_API_SECRET" "your-api-secret"')}`),n.info(` ${Z.default.cyan('dotnet user-secrets set "VOICE_APPLICATION_SECRET" "your-app-secret"')}`)}}if(c.succeed("\u{1F680} Function initialized successfully"),n.newline(),n.title(`Function: ${Z.default.cyan(l)}`),n.info(`Template: ${Z.default.yellow(a)}`),n.info(`Runtime: ${Z.default.blue(r)}`),n.info(`Location: ${Z.default.gray(p)}`),r==="node"&&!e.skipInstall){n.newline(),c.start("Installing npm packages...");try{await new Promise((S,I)=>{let b=(0,gt.spawn)("npm",["install"],{cwd:p,stdio:"inherit",shell:!0});b.on("close",j=>{j===0?S():I(new Error(`npm install failed with code ${j}`))}),b.on("error",j=>{I(j)})}),c.succeed("\u{1F4E6} Dependencies installed successfully")}catch(S){c.fail("\u{1F4E6} Failed to install dependencies"),S.code==="ENOENT"?n.warn("npm not found. Please ensure Node.js is installed and in your PATH."):n.debug(`npm install error: ${S.message}`)}}n.newline(),n.info("\u{1F4CB} Next steps:"),n.info(` 1. \u{1F4C1} Navigate to function: ${Z.default.cyan(`cd ${l}`)}`),r==="node"?n.info(" 2. \u{1F3C3} Start development: sinch functions dev"):n.info(" 2. \u{1F3C3} Start development: dotnet run"),n.info(" 3. \u{1F680} Deploy to production: sinch functions deploy"),n.info(" 4. \u{1F4CA} View logs: sinch functions logs --follow"),n.newline(),n.info("\u{1F4A1} Template info:"),n.info(`\u2022 ${d.description}`),d.features&&d.features.length>0&&d.features.forEach(S=>{n.info(`\u2022 ${S}`)})}catch(t){c.stop(),n.error(`Failed to initialize function: ${t.message}`),process.exit(1)}});Ji.exports=Vi});var Gi=x((rl,zi)=>{"use strict";var q=y(require("chalk")),Ki=require("commander"),Hi=y(require("cli-table3")),jt=y(require("inquirer"));X();A();E();D();var Wi=new Ki.Command("list");Wi.description("List all functions").option("--status <status>","Filter by status (Running, Failed, Pending, Building)").option("--runtime <runtime>","Filter by runtime (node, csharp, python)").option("--limit <limit>","Limit number of results","50").option("-i, --interactive","Interactive mode - select function for actions").action(async i=>{try{await f.load();let e=new V(f.getApiConfig());c.start("\u{1F4CB} Loading functions...");let t={limit:parseInt(i.limit||"50")};i.status&&(t.status=i.status),i.runtime&&(t.runtime=i.runtime);let o=await e.listFunctions();if(c.succeed(`\u{1F4CB} Found ${o.functions.length} functions`),o.functions.length===0){n.newline(),n.info("No functions found"),n.info("\u{1F4A1} Create your first function with:"),n.info(` ${q.default.cyan("sinch functions init")}`);return}n.newline(),n.title("Functions:");let r=o.functions.map(a=>{let l=new Date(a.createdAt).toLocaleDateString(),p=Ln(a.status),d=a.containerAppUrl?a.containerAppUrl.length>40?a.containerAppUrl.substring(0,37)+"...":a.containerAppUrl:q.default.gray("Not deployed");return[q.default.cyan(a.name),q.default.yellow(a.runtime),p,q.default.gray(l),q.default.blue(d)]}),s=new Hi.default({head:["Name","Runtime","Status","Created","URL"],style:{head:["cyan"]},colWidths:[20,10,15,12,45]});if(s.push(...r),console.log(s.toString()),o.pagination){let{page:a,totalCount:l,totalPages:p}=o.pagination;n.newline(),n.info(q.default.gray(`Page ${a} of ${p} (${l} total functions)`)),a<p&&n.info(q.default.gray("\u{1F4A1} Use --limit to see more results"))}if(i.interactive&&o.functions.length>0){n.newline();let a=o.functions.map(d=>({name:`${d.name.padEnd(20)} ${d.runtime.padEnd(8)} ${Ln(d.status).padEnd(20)} ${d.id.substring(0,8)}`,value:d.id,short:d.name}));a.push(new jt.default.Separator),a.push({name:q.default.gray("Exit"),value:"exit",short:"Exit"});let{selectedFunction:l}=await jt.default.prompt([{type:"list",name:"selectedFunction",message:"Select a function for actions:",choices:a,pageSize:15}]);if(l==="exit")return;let p=o.functions.find(d=>d.id===l);p&&await Gs(p,e)}else n.newline(),n.info("\u{1F4A1} Function commands:"),n.info(` \u2022 View details: ${q.default.cyan("sinch functions status 01HX3KC5V8G3KCNZ8S5Y9ABC")}`),n.info(` \u2022 View logs: ${q.default.cyan("sinch functions logs 01HX3KC5V8G3KCNZ8S5Y9ABC")}`),n.info(` \u2022 Download: ${q.default.cyan("sinch functions download 01HX3KC5V8G3KCNZ8S5Y9ABC")}`),n.info(` \u2022 Interactive mode: ${q.default.cyan("sinch functions list -i")}`),n.info(` \u2022 Deploy new function: ${q.default.cyan("sinch functions deploy")}`)}catch(e){c.stop(),n.error(`Failed to list functions: ${e.message}`),process.exit(1)}});function Ln(i){return{Running:q.default.green("\u2705 Running"),Failed:q.default.red("\u274C Failed"),Pending:q.default.yellow("\u23F3 Pending"),Building:q.default.blue("\u{1F528} Building")}[i]||q.default.gray(i)}async function Gs(i,e){n.newline(),n.info(`\u{1F4CB} Selected: ${q.default.cyan(i.name)}`),n.info(` ID: ${q.default.gray(i.id)}`),n.info(` Status: ${Ln(i.status)}`),n.newline();let{action:t}=await jt.default.prompt([{type:"list",name:"action",message:"What would you like to do?",choices:[{name:"\u{1F4E5} Download source code",value:"download"},{name:"\u{1F4CA} View status details",value:"status"},{name:"\u{1F4DC} View logs",value:"logs"},{name:"\u{1F517} Copy URL to clipboard",value:"copy-url"},{name:"\u{1F5D1}\uFE0F Delete function",value:"delete"},new jt.default.Separator,{name:q.default.gray("Back"),value:"back"}]}]);switch(t){case"download":n.info(`
37
- \u{1F4A1} To download this function, run:`),n.info(` ${q.default.cyan(`sinch functions download ${i.id}`)}`);break;case"status":n.info(`
38
- \u{1F4A1} To view status, run:`),n.info(` ${q.default.cyan(`sinch functions status ${i.id}`)}`);break;case"logs":n.info(`
39
- \u{1F4A1} To view logs, run:`),n.info(` ${q.default.cyan(`sinch functions logs ${i.id}`)}`);break;case"copy-url":i.containerAppUrl?(await require("clipboardy").write(i.containerAppUrl),n.success(`\u2705 URL copied to clipboard: ${i.containerAppUrl}`)):n.warn("\u26A0\uFE0F Function has no URL (not deployed)");break;case"delete":n.info(`
40
- \u{1F4A1} To delete this function, run:`),n.info(` ${q.default.cyan(`sinch functions delete ${i.id}`)}`);break;case"back":return}}zi.exports=Wi});async function Un(i){if(!await f.hasCredentials())throw new Error('No Sinch credentials found. Run "sinch auth login" first.');let e=await f.getApplicationCredentials();if(!e)throw new Error('No application credentials found. Run "sinch auth login" first.');let o=`https://callingapi.sinch.com/v1/configuration/callbacks/applications/${e.applicationKey}/`,r={url:{primary:i}},s=`${e.applicationKey}:${e.applicationSecret}`,a=Buffer.from(s).toString("base64");await _n.default.post(o,r,{headers:{Authorization:`Basic ${a}`,"Content-Type":"application/json"},timeout:1e4}),await new Promise(u=>setTimeout(u,1e3));let d=(await _n.default.get(o,{headers:{Authorization:`Basic ${a}`},timeout:1e4})).data?.url?.primary;if(d!==i)throw n.debug(`Callback verification mismatch. Expected: ${i}, Got: ${d}`),new Error(`Callback URL update verification failed. Expected: ${i}, Got: ${d}`);n.debug("Voice callback URL successfully updated and verified")}var _n,Yi=W(()=>{"use strict";_n=y(require("axios"));A();E()});function Ys(){return"https://us.conversation.api.sinch.com"}async function Xs(i,e,t){let o="https://auth.sinch.com/oauth2/token",r=new URLSearchParams;r.append("grant_type","client_credentials");let s=`${e}:${t}`,a=Buffer.from(s).toString("base64");return(await Ft.default.post(o,r,{headers:{Authorization:`Basic ${a}`,"Content-Type":"application/x-www-form-urlencoded"},timeout:1e4})).data.access_token}async function an(){let i=Lt.default.join(process.cwd(),"appsettings.json");if(await Te.default.pathExists(i))try{let t=await Te.default.readJson(i);if(t.Webhooks?.AutoConfigureConversation!==!0)return{isConversation:!1};let o=t.CONVERSATION_APP_ID;if(o)return{isConversation:!0,appId:o}}catch(t){n.debug("Could not read appsettings.json: "+t.message)}let e=Lt.default.join(process.cwd(),".env");if(await Te.default.pathExists(e))try{let t=await Te.default.readFile(e,"utf8"),o={};if(t.split(`
41
- `).forEach(s=>{if(s.trim()&&!s.trim().startsWith("#")){let[a,...l]=s.split("=");a&&(o[a.trim()]=l.join("=").trim())}}),o.AUTO_CONFIGURE_CONVERSATION!=="true")return{isConversation:!1};let r=o.CONVERSATION_APP_ID;if(r)return{isConversation:!0,appId:r}}catch(t){n.debug("Could not read .env file: "+t.message)}return{isConversation:!1}}async function qn(i){if(!await f.hasCredentials())throw new Error('No Sinch credentials found. Run "sinch auth login" first.');let{isConversation:e,appId:t}=await an();if(n.debug(`isConversationFunction check: isConversation=${e}, appId=${t}`),!e||!t){n.debug("Not a Conversation function or missing CONVERSATION_APP_ID, skipping webhook config");return}let o=await f.getCredentials();if(!o?.projectId||!o?.keyId||!o?.keySecret)throw new Error('Missing project credentials. Run "sinch auth login" first.');let r=Ys(),s=`${i}/conversation`;n.debug(`Conversation webhook URL: ${s}`),n.debug(`Project ID: ${o.projectId}, App ID: ${t}`),n.debug("Getting OAuth access token...");let a=await Xs(o.projectId,o.keyId,o.keySecret);n.debug("Got access token successfully");let l={Authorization:`Bearer ${a}`,"Content-Type":"application/json"},p=`${r}/v1/projects/${o.projectId}/apps/${t}/webhooks`;n.debug(`Listing webhooks: GET ${p}`);let d=await Ft.default.get(p,{headers:l,timeout:1e4});n.debug(`Found ${d.data.webhooks?.length||0} webhooks`);let u=d.data.webhooks?.find(C=>C.target?.includes(".sinch.com")&&(C.target?.includes("fn-dev.")||C.target?.includes("fn-prod.")||C.target?.includes("functions."))),m=["MESSAGE_INBOUND"];if(u){n.debug(`Found existing webhook: id=${u.id}, target=${u.target}`);let C=`${r}/v1/projects/${o.projectId}/webhooks/${u.id}`;n.debug(`Deleting webhook: DELETE ${C}`);try{await Ft.default.delete(C,{headers:l,timeout:1e4}),n.debug(`Deleted existing Conversation webhook ${u.id}`)}catch(v){n.debug(`Failed to delete webhook: ${v.response?.status} ${v.response?.data?JSON.stringify(v.response.data):v.message}`)}}let w=`${r}/v1/projects/${o.projectId}/webhooks`,h={app_id:t,target:s,target_type:"HTTP",triggers:m};n.debug(`Creating webhook: POST ${w}`),n.debug(`Payload: ${JSON.stringify(h)}`);try{let C=await Ft.default.post(w,h,{headers:l,timeout:1e4});n.debug(`Created new Conversation webhook: ${JSON.stringify(C.data)}`)}catch(C){throw n.debug(`Failed to create webhook: ${C.response?.status} ${C.response?.data?JSON.stringify(C.response.data):C.message}`),C}n.debug("Conversation webhook successfully configured")}async function Mn(){let i=Lt.default.join(process.cwd(),"appsettings.json");if(await Te.default.pathExists(i))try{let t=await Te.default.readJson(i);return t.Webhooks?t.Webhooks.AutoConfigureVoice===!0:!0}catch(t){n.debug("Could not read appsettings.json: "+t.message)}let e=Lt.default.join(process.cwd(),".env");if(await Te.default.pathExists(e))try{let t=await Te.default.readFile(e,"utf8"),o={};return t.split(`
42
- `).forEach(s=>{if(s.trim()&&!s.trim().startsWith("#")){let[a,...l]=s.split("=");a&&(o[a.trim()]=l.join("=").trim())}}),Object.keys(o).some(s=>s.startsWith("AUTO_CONFIGURE_"))?o.AUTO_CONFIGURE_VOICE==="true":!0}catch(t){n.debug("Could not read .env file: "+t.message)}return!0}var Ft,Te,Lt,Xi=W(()=>{"use strict";Ft=y(require("axios")),Te=y(require("fs-extra")),Lt=y(require("path"));A();E()});var to={};xe(to,{combineDocumentation:()=>Qi,detectRuntimeFromFile:()=>eo,findFunctionFile:()=>Zi,generateDocsFromLocal:()=>Vn,saveDocumentationToFile:()=>Jn});async function Vn(){let i=process.cwd(),e=await Zi(i);if(!e)throw new Error("No function file found. Make sure you're in a function directory with function.js, function.ts, index.js, index.ts, handler.js, or handler.ts");let t=await ht.readFile(e,"utf8"),o=eo(e),r=Ve.basename(i),a=await new V(f.getApiConfig()).generateDocumentationFromCode(t,o,r);return Qi(a)}async function Zi(i){let e=["function.js","function.ts","index.js","index.ts","handler.js","handler.ts","function.py","handler.py","Function.cs","Handler.cs"];for(let t of e){let o=Ve.join(i,t);if(await ht.pathExists(o))return o}return null}function Qi(i){let e=i.documentation||"",t=i.diagram||i.callFlowDiagram;return t&&(e&&!e.endsWith(`
37
+ `,$+=`NODE_ENV=development
38
+ `,$+=`PORT=3000
39
+ `,$+=`SINCH_TUNNEL=false
40
+ `,await X.default.writeFile(b,$),n.info(""),n.info("\u{1F510} Secrets Management for Node.js:");try{let P=await f.getCredentials();P&&P.keySecret?(n.info(" \u2705 Sinch credentials found in secure storage"),n.info(" \u2705 F5 debugging will automatically load secrets from OS keychain"),n.info(""),n.info(" \u{1F4A1} To add custom secrets, use:"),n.info(` ${ee.default.cyan("sinch functions secrets add <KEY> <VALUE>")}`)):(n.info(" \u26A0\uFE0F No Sinch credentials found in secure storage"),n.info(""),n.info(" To set up authentication:"),n.info(` ${ee.default.cyan("sinch auth login")}`),n.info(""),n.info(" To add custom secrets:"),n.info(` ${ee.default.cyan("sinch functions secrets add <KEY> <VALUE>")}`))}catch{n.info(" \u2139\uFE0F Set up authentication with:"),n.info(` ${ee.default.cyan("sinch auth login")}`)}n.info(""),n.info(" \u{1F4DD} Note: Secrets are stored securely in your OS keychain"),n.info(" \u{1F4DD} Note: F5 debugging requires keytar (npm install keytar)")}if(r==="csharp"){let S=Be.default.join(p,"appsettings.json"),b;await X.default.pathExists(S)?b=await X.default.readJson(S):b={Logging:{LogLevel:{Default:"Information","Microsoft.AspNetCore":"Warning"}},AllowedHosts:"*"},b.Logging||(b.Logging={LogLevel:{Default:"Information","Microsoft.AspNetCore":"Warning"}}),b.AllowedHosts||(b.AllowedHosts="*"),Object.keys(h).forEach(P=>{b[P]=h[P]});let $=f.get("projectId"),me=f.get("defaultApplicationKey"),Dt=f.get("keyId");b.PROJECT_ID=$||"",b.PROJECT_ID_API_KEY=Dt||"",b.PROJECT_ID_API_SECRET="",(M||me)&&(b.VOICE_APPLICATION_KEY=me||"",b.VOICE_APPLICATION_SECRET=""),C.forEach(P=>{b[P]=""}),await X.default.writeJson(S,b,{spaces:2});let O=Be.default.join(p,"appsettings.Development.json"),K={Logging:{LogLevel:{Default:"Debug","Microsoft.AspNetCore":"Information"}},SinchTunnel:!1};await X.default.writeJson(O,K,{spaces:2});try{let P=await f.getCredentials();await new Promise((de,we)=>{let se=(0,wt.spawn)("dotnet",["user-secrets","init"],{cwd:p,shell:!0});se.on("close",pe=>pe===0?de():we(new Error("Failed to init user-secrets"))),se.on("error",we)}),P&&P.keySecret&&await new Promise((de,we)=>{let se=(0,wt.spawn)("dotnet",["user-secrets","set","PROJECT_ID_API_SECRET",P.keySecret],{cwd:p,shell:!0});se.on("close",pe=>pe===0?de():we(new Error("Failed to set API secret"))),se.on("error",we)}),P&&P.applicationSecret&&await new Promise((de,we)=>{let se=(0,wt.spawn)("dotnet",["user-secrets","set","VOICE_APPLICATION_SECRET",P.applicationSecret],{cwd:p,shell:!0});se.on("close",pe=>pe===0?de():we(new Error("Failed to set app secret"))),se.on("error",we)});let xt="sinch-functions-cli";for(let de of C)try{let we=`${l}-${de}`,se=await Hn.default.getPassword(xt,we);se&&await new Promise((pe,Fi)=>{let ji=(0,wt.spawn)("dotnet",["user-secrets","set",de,se],{cwd:p,shell:!0});ji.on("close",Ws=>Ws===0?pe():Fi(new Error(`Failed to set ${de}`))),ji.on("error",Fi)})}catch{}(P&&(P.keySecret||P.applicationSecret)||C.length>0)&&(n.info(""),n.info("\u{1F510} Secrets Management for C#:"),n.info(" \u2705 User secrets have been configured automatically"),n.info(" You can view them with: "+ee.default.cyan("dotnet user-secrets list")),C.length>0&&n.info(" \u{1F4A1} Template secrets have been added to user-secrets"))}catch{n.info(""),n.info("\u{1F510} Secrets Management for C#:"),n.info(" For local development, use dotnet user-secrets:"),n.info(` ${ee.default.cyan("dotnet user-secrets init")}`),n.info(` ${ee.default.cyan('dotnet user-secrets set "PROJECT_ID_API_SECRET" "your-api-secret"')}`),n.info(` ${ee.default.cyan('dotnet user-secrets set "VOICE_APPLICATION_SECRET" "your-app-secret"')}`)}}if(c.succeed("\u{1F680} Function initialized successfully"),n.newline(),n.title(`Function: ${ee.default.cyan(l)}`),n.info(`Template: ${ee.default.yellow(a)}`),n.info(`Runtime: ${ee.default.blue(r)}`),n.info(`Location: ${ee.default.gray(p)}`),r==="node"&&!e.skipInstall){n.newline(),c.start("Installing npm packages...");try{await new Promise((S,b)=>{let $=(0,wt.spawn)("npm",["install"],{cwd:p,stdio:"inherit",shell:!0});$.on("close",me=>{me===0?S():b(new Error(`npm install failed with code ${me}`))}),$.on("error",me=>{b(me)})}),c.succeed("\u{1F4E6} Dependencies installed successfully")}catch(S){c.fail("\u{1F4E6} Failed to install dependencies"),S.code==="ENOENT"?n.warn("npm not found. Please ensure Node.js is installed and in your PATH."):n.debug(`npm install error: ${S.message}`)}}n.newline(),n.info("\u{1F4CB} Next steps:"),n.info(` 1. \u{1F4C1} Navigate to function: ${ee.default.cyan(`cd ${l}`)}`),r==="node"?n.info(" 2. \u{1F3C3} Start development: sinch functions dev"):n.info(" 2. \u{1F3C3} Start development: dotnet run"),n.info(" 3. \u{1F680} Deploy to production: sinch functions deploy"),n.info(" 4. \u{1F4CA} View logs: sinch functions logs --follow"),n.newline(),n.info("\u{1F4A1} Template info:"),n.info(`\u2022 ${d.description}`),d.features&&d.features.length>0&&d.features.forEach(S=>{n.info(`\u2022 ${S}`)})}catch(t){c.stop(),n.error(`Failed to initialize function: ${t.message}`),process.exit(1)}});so.exports=ro});var fo=N((Jl,uo)=>{"use strict";var _=y(require("chalk")),co=require("commander"),lo=y(require("cli-table3")),qt=y(require("inquirer"));Q();E();T();R();var po=new co.Command("list");po.description("List all functions").option("--status <status>","Filter by status (Running, Failed, Pending, Building)").option("--runtime <runtime>","Filter by runtime (node, csharp, python)").option("--limit <limit>","Limit number of results","50").option("-i, --interactive","Interactive mode - select function for actions").action(async i=>{try{await f.load();let e=new J(f.getApiConfig());c.start("\u{1F4CB} Loading functions...");let t={limit:parseInt(i.limit||"50")};i.status&&(t.status=i.status),i.runtime&&(t.runtime=i.runtime);let o=await e.listFunctions();if(c.succeed(`\u{1F4CB} Found ${o.functions.length} functions`),o.functions.length===0){n.newline(),n.info("No functions found"),n.info("\u{1F4A1} Create your first function with:"),n.info(` ${_.default.cyan("sinch functions init")}`);return}n.newline(),n.title("Functions:");let r=o.functions.map(a=>{let l=new Date(a.createdAt).toLocaleDateString(),p=Wn(a.status),d=a.containerAppUrl?a.containerAppUrl.length>40?a.containerAppUrl.substring(0,37)+"...":a.containerAppUrl:_.default.gray("Not deployed");return[_.default.cyan(a.name),_.default.yellow(a.runtime),p,_.default.gray(l),_.default.blue(d)]}),s=new lo.default({head:["Name","Runtime","Status","Created","URL"],style:{head:["cyan"]},colWidths:[20,10,15,12,45]});if(s.push(...r),console.log(s.toString()),o.pagination){let{page:a,totalCount:l,totalPages:p}=o.pagination;n.newline(),n.info(_.default.gray(`Page ${a} of ${p} (${l} total functions)`)),a<p&&n.info(_.default.gray("\u{1F4A1} Use --limit to see more results"))}if(i.interactive&&o.functions.length>0){n.newline();let a=o.functions.map(d=>({name:`${d.name.padEnd(20)} ${d.runtime.padEnd(8)} ${Wn(d.status).padEnd(20)} ${d.id.substring(0,8)}`,value:d.id,short:d.name}));a.push(new qt.default.Separator),a.push({name:_.default.gray("Exit"),value:"exit",short:"Exit"});let{selectedFunction:l}=await qt.default.prompt([{type:"list",name:"selectedFunction",message:"Select a function for actions:",choices:a,pageSize:15}]);if(l==="exit")return;let p=o.functions.find(d=>d.id===l);p&&await Sa(p,e)}else n.newline(),n.info("\u{1F4A1} Function commands:"),n.info(` \u2022 View details: ${_.default.cyan("sinch functions status 01HX3KC5V8G3KCNZ8S5Y9ABC")}`),n.info(` \u2022 View logs: ${_.default.cyan("sinch functions logs 01HX3KC5V8G3KCNZ8S5Y9ABC")}`),n.info(` \u2022 Download: ${_.default.cyan("sinch functions download 01HX3KC5V8G3KCNZ8S5Y9ABC")}`),n.info(` \u2022 Interactive mode: ${_.default.cyan("sinch functions list -i")}`),n.info(` \u2022 Deploy new function: ${_.default.cyan("sinch functions deploy")}`)}catch(e){c.stop(),n.error(`Failed to list functions: ${e.message}`),process.exit(1)}});function Wn(i){return{Running:_.default.green("\u2705 Running"),Failed:_.default.red("\u274C Failed"),Pending:_.default.yellow("\u23F3 Pending"),Building:_.default.blue("\u{1F528} Building")}[i]||_.default.gray(i)}async function Sa(i,e){n.newline(),n.info(`\u{1F4CB} Selected: ${_.default.cyan(i.name)}`),n.info(` ID: ${_.default.gray(i.id)}`),n.info(` Status: ${Wn(i.status)}`),n.newline();let{action:t}=await qt.default.prompt([{type:"list",name:"action",message:"What would you like to do?",choices:[{name:"\u{1F4E5} Download source code",value:"download"},{name:"\u{1F4CA} View status details",value:"status"},{name:"\u{1F4DC} View logs",value:"logs"},{name:"\u{1F517} Copy URL to clipboard",value:"copy-url"},{name:"\u{1F5D1}\uFE0F Delete function",value:"delete"},new qt.default.Separator,{name:_.default.gray("Back"),value:"back"}]}]);switch(t){case"download":n.info(`
41
+ \u{1F4A1} To download this function, run:`),n.info(` ${_.default.cyan(`sinch functions download ${i.id}`)}`);break;case"status":n.info(`
42
+ \u{1F4A1} To view status, run:`),n.info(` ${_.default.cyan(`sinch functions status ${i.id}`)}`);break;case"logs":n.info(`
43
+ \u{1F4A1} To view logs, run:`),n.info(` ${_.default.cyan(`sinch functions logs ${i.id}`)}`);break;case"copy-url":i.containerAppUrl?(await require("clipboardy").write(i.containerAppUrl),n.success(`\u2705 URL copied to clipboard: ${i.containerAppUrl}`)):n.warn("\u26A0\uFE0F Function has no URL (not deployed)");break;case"delete":n.info(`
44
+ \u{1F4A1} To delete this function, run:`),n.info(` ${_.default.cyan(`sinch functions delete ${i.id}`)}`);break;case"back":return}}uo.exports=po});async function Gn(i){if(!await f.hasCredentials())throw new Error('No Sinch credentials found. Run "sinch auth login" first.');let e=await f.getApplicationCredentials();if(!e)throw new Error('No application credentials found. Run "sinch auth login" first.');let o=`https://callingapi.sinch.com/v1/configuration/callbacks/applications/${e.applicationKey}/`,r={url:{primary:i}},s=`${e.applicationKey}:${e.applicationSecret}`,a=Buffer.from(s).toString("base64");await zn.default.post(o,r,{headers:{Authorization:`Basic ${a}`,"Content-Type":"application/json"},timeout:1e4}),await new Promise(u=>setTimeout(u,1e3));let d=(await zn.default.get(o,{headers:{Authorization:`Basic ${a}`},timeout:1e4})).data?.url?.primary;if(d!==i)throw n.debug(`Callback verification mismatch. Expected: ${i}, Got: ${d}`),new Error(`Callback URL update verification failed. Expected: ${i}, Got: ${d}`);n.debug("Voice callback URL successfully updated and verified")}var zn,mo=G(()=>{"use strict";zn=y(require("axios"));E();T()});function ba(){return"https://us.conversation.api.sinch.com"}async function Ia(i,e,t){let o="https://auth.sinch.com/oauth2/token",r=new URLSearchParams;r.append("grant_type","client_credentials");let s=`${e}:${t}`,a=Buffer.from(s).toString("base64");return(await Jt.default.post(o,r,{headers:{Authorization:`Basic ${a}`,"Content-Type":"application/x-www-form-urlencoded"},timeout:1e4})).data.access_token}async function hn(){let i=Vt.default.join(process.cwd(),"appsettings.json");if(await je.default.pathExists(i))try{let t=await je.default.readJson(i);if(t.Webhooks?.AutoConfigureConversation!==!0)return{isConversation:!1};let o=t.CONVERSATION_APP_ID;if(o)return{isConversation:!0,appId:o}}catch(t){n.debug("Could not read appsettings.json: "+t.message)}let e=Vt.default.join(process.cwd(),".env");if(await je.default.pathExists(e))try{let t=await je.default.readFile(e,"utf8"),o={};if(t.split(`
45
+ `).forEach(s=>{if(s.trim()&&!s.trim().startsWith("#")){let[a,...l]=s.split("=");a&&(o[a.trim()]=l.join("=").trim())}}),"AUTO_CONFIGURE"in o){if(o.AUTO_CONFIGURE!=="true")return{isConversation:!1};if(!(o.SINCH_SERVICES??"").split(",").map(l=>l.trim()).includes("conversation"))return{isConversation:!1};let a=o.CONVERSATION_APP_ID;return a?{isConversation:!0,appId:a}:{isConversation:!1}}if(o.AUTO_CONFIGURE_CONVERSATION!=="true")return{isConversation:!1};let r=o.CONVERSATION_APP_ID;if(r)return{isConversation:!0,appId:r}}catch(t){n.debug("Could not read .env file: "+t.message)}return{isConversation:!1}}async function Yn(i){if(!await f.hasCredentials())throw new Error('No Sinch credentials found. Run "sinch auth login" first.');let{isConversation:e,appId:t}=await hn();if(n.debug(`isConversationFunction check: isConversation=${e}, appId=${t}`),!e||!t){n.debug("Not a Conversation function or missing CONVERSATION_APP_ID, skipping webhook config");return}let o=await f.getCredentials();if(!o?.projectId||!o?.keyId||!o?.keySecret)throw new Error('Missing project credentials. Run "sinch auth login" first.');let r=ba(),s=`${i}/webhook`;n.debug(`Conversation webhook URL: ${s}`),n.debug(`Project ID: ${o.projectId}, App ID: ${t}`),n.debug("Getting OAuth access token...");let a=await Ia(o.projectId,o.keyId,o.keySecret);n.debug("Got access token successfully");let l={Authorization:`Bearer ${a}`,"Content-Type":"application/json"},p=`${r}/v1/projects/${o.projectId}/apps/${t}/webhooks`;n.debug(`Listing webhooks: GET ${p}`);let d=await Jt.default.get(p,{headers:l,timeout:1e4});n.debug(`Found ${d.data.webhooks?.length||0} webhooks`);let u=d.data.webhooks?.find(C=>C.target?.includes(".sinch.com")&&(C.target?.includes("fn-dev.")||C.target?.includes("fn-prod.")||C.target?.includes("functions."))),m=["MESSAGE_INBOUND"];if(u){n.debug(`Found existing webhook: id=${u.id}, target=${u.target}`);let C=`${r}/v1/projects/${o.projectId}/webhooks/${u.id}`;n.debug(`Deleting webhook: DELETE ${C}`);try{await Jt.default.delete(C,{headers:l,timeout:1e4}),n.debug(`Deleted existing Conversation webhook ${u.id}`)}catch(v){n.debug(`Failed to delete webhook: ${v.response?.status} ${v.response?.data?JSON.stringify(v.response.data):v.message}`)}}let w=`${r}/v1/projects/${o.projectId}/webhooks`,h={app_id:t,target:s,target_type:"HTTP",triggers:m};n.debug(`Creating webhook: POST ${w}`),n.debug(`Payload: ${JSON.stringify(h)}`);try{let C=await Jt.default.post(w,h,{headers:l,timeout:1e4});n.debug(`Created new Conversation webhook: ${JSON.stringify(C.data)}`)}catch(C){throw n.debug(`Failed to create webhook: ${C.response?.status} ${C.response?.data?JSON.stringify(C.response.data):C.message}`),C}n.debug("Conversation webhook successfully configured")}async function Xn(){let i=Vt.default.join(process.cwd(),"appsettings.json");if(await je.default.pathExists(i))try{let t=await je.default.readJson(i);return t.Webhooks?t.Webhooks.AutoConfigureVoice===!0:!0}catch(t){n.debug("Could not read appsettings.json: "+t.message)}let e=Vt.default.join(process.cwd(),".env");if(await je.default.pathExists(e))try{let t=await je.default.readFile(e,"utf8"),o={};return t.split(`
46
+ `).forEach(r=>{if(r.trim()&&!r.trim().startsWith("#")){let[s,...a]=r.split("=");s&&(o[s.trim()]=a.join("=").trim())}}),"AUTO_CONFIGURE"in o?o.AUTO_CONFIGURE!=="true"?!1:(o.SINCH_SERVICES??"").split(",").map(s=>s.trim()).includes("voice"):o.AUTO_CONFIGURE_VOICE==="true"}catch(t){n.debug("Could not read .env file: "+t.message)}return!1}var Jt,je,Vt,go=G(()=>{"use strict";Jt=y(require("axios")),je=y(require("fs-extra")),Vt=y(require("path"));E();T()});var Co={};xe(Co,{combineDocumentation:()=>yo,detectRuntimeFromFile:()=>wo,findFunctionFile:()=>ho,generateDocsFromLocal:()=>Zn,saveDocumentationToFile:()=>Qn});async function Zn(){let i=process.cwd(),e=await ho(i);if(!e)throw new Error("No function file found. Make sure you're in a function directory with function.js, function.ts, index.js, index.ts, handler.js, or handler.ts");let t=await Ct.readFile(e,"utf8"),o=wo(e),r=Ke.basename(i),a=await new J(f.getApiConfig()).generateDocumentationFromCode(t,o,r);return yo(a)}async function ho(i){let e=["function.js","function.ts","index.js","index.ts","handler.js","handler.ts","function.py","handler.py","Function.cs","Handler.cs"];for(let t of e){let o=Ke.join(i,t);if(await Ct.pathExists(o))return o}return null}function yo(i){let e=i.documentation||"",t=i.diagram||i.callFlowDiagram;return t&&(e&&!e.endsWith(`
43
47
 
44
48
  `)&&(e+=`
45
49
 
@@ -49,63 +53,63 @@ ${e}`))}list(e,t={}){let{indent:o=" ",bullet:r="\u2022"}=t;e.forEach(s=>{consol
49
53
  ---
50
54
 
51
55
  `,e+=`*Documentation generated on ${new Date(i.generatedAt).toLocaleString()} using Sinch AI*
52
- `),e}async function Jn(i,e){let t=Ve.resolve(e);await ht.writeFile(t,i,"utf8")}function eo(i){switch(Ve.extname(i).toLowerCase()){case".js":case".ts":return"node";case".py":return"python";case".cs":return"csharp";default:return"node"}}var ht,Ve,Bn=W(()=>{"use strict";ht=y(require("fs-extra")),Ve=y(require("path"));X();A()});var lo=x((Sl,co)=>{"use strict";var Ce=y(require("fs-extra")),et=y(require("path")),N=y(require("chalk")),io=require("commander");X();A();E();D();pt();Yi();Xi();var oo=y(require("adm-zip")),ro=y(require("os")),Kn=y(require("inquirer")),_t=require("child_process"),so=y(require("keytar")),ao=new io.Command("deploy");ao.description("Deploy function to production").option("-n, --name <name>","Function name (default: current directory)").option("--no-wait","Don't wait for deployment to complete").option("--non-interactive","Use default values without prompting (auto-generates docs)").option("--no-docs","no doc generation").option("--private","Deploy to private namespace (internal access only, not publicly accessible)").action(async i=>{try{if(await f.load(),!f.isInProject())throw new Error('Not in a Sinch Functions project directory. Run "sinch functions init" first.');let e=f.getProjectConfig(),t=i.name||e.name,o=e.runtime;if(await ta(e,i),o==="csharp"){let u=await Ce.default.readdir(process.cwd()).then(w=>w.filter(h=>h.endsWith(".csproj")));if(u.length===0)throw new Error("No .csproj file found. Make sure you're in a valid C# function directory.");let m=u[0];await oa(process.cwd(),m)}c.start("\u{1F4E6} Packaging function...");let r=await Zs(t);c.succeed("\u{1F4E6} Function packaged"),c.start("\u{1F527} Preparing configuration...");let s=await Qs(o,t);c.succeed("\u{1F527} Configuration prepared");let a=await ia(e,i);c.start("\u{1F680} Submitting deployment...");let l=new V(f.getApiConfig()),p=await Ce.default.readFile(r),d=await l.deployFunction(t,o,p,s,a);if(await Ce.default.remove(r),c.succeed("\u{1F680} Deployment submitted"),f.set("functionId",d.id,!0),await f.saveProjectConfig(),n.newline(),n.info(`Function ID: ${N.default.cyan(d.id)}`),n.info(`Status: ${Hn(d.status)}`),i.wait===!1){n.newline(),n.info("\u{1F4A1} Check deployment progress with:"),n.info(` ${N.default.cyan(`sinch functions status ${d.id}`)}`);return}await ea(l,d.id)}catch(e){c.stop(),n.error(`Failed to deploy function: ${e.message}`);let t=e.exitCode||$.FAILURE;process.exit(t)}});async function Zs(i){let e=new oo.default,t=process.cwd(),o=et.default.join(ro.default.tmpdir(),`${i}-${Date.now()}.zip`),r=["node_modules","bin","obj",".git",".DS_Store","*.zip",".env",".env.local","npm-debug.log*",".sinch-tmp","examples","claude.md","readme.md",".vs",".vscode",".idea",".cursor","*.user","*.suo"];async function s(a,l=""){let p=await Ce.default.readdir(a);for(let d of p){let u=et.default.join(a,d),m=et.default.join(l,d).replace(/\\/g,"/");if(r.some(h=>d.match(new RegExp(h.replace("*",".*")))))continue;if((await Ce.default.stat(u)).isDirectory())await s(u,m);else{let h=await Ce.default.readFile(u);e.addFile(m,h)}}}return await s(t),e.writeZip(o),o}async function Qs(i,e){let t={},o=null;try{o=await f.getCredentials()}catch(r){n.debug("Could not load credentials from secure storage: "+r.message)}if(i==="csharp"){let r=et.default.join(process.cwd(),"appsettings.json");if(await Ce.default.pathExists(r))try{let s=await Ce.default.readJson(r);for(let a of Object.keys(s)){if(a==="Logging"||a==="AllowedHosts")continue;let l=s[a];if(l===""||l===null||l===void 0){let p="",d=!1;try{let m=(0,_t.execSync)("dotnet user-secrets list",{cwd:process.cwd(),encoding:"utf8",stdio:["pipe","pipe","pipe"]}).trim().split(`
53
- `);for(let w of m){let h=w.match(/^([^=]+)\s*=\s*(.+)$/);if(h&&h[1]&&h[2]&&h[1].trim()===a){p=h[2].trim(),d=!0,n.debug(`Found ${a} in dotnet user-secrets`);break}}}catch{}!p&&o&&(a==="PROJECT_ID"&&o.projectId?p=o.projectId:a==="PROJECT_ID_API_KEY"&&o.keyId?p=o.keyId:a==="PROJECT_ID_API_SECRET"&&o.keySecret?(p=o.keySecret,d=!0):a==="VOICE_APPLICATION_KEY"&&o.applicationKey?p=o.applicationKey:a==="VOICE_APPLICATION_SECRET"&&o.applicationSecret&&(p=o.applicationSecret,d=!0)),p&&(t[a]={Value:p,Secret:d})}else t[a]={Value:String(l),Secret:!1}}}catch(s){n.debug("Could not read appsettings.json: "+s.message)}}else{let r=et.default.join(process.cwd(),".env");if(await Ce.default.pathExists(r))try{let s=await Ce.default.readFile(r,"utf8"),a={};s.split(`
54
- `).forEach(p=>{if(p.trim()&&!p.trim().startsWith("#")){let[d,...u]=p.split("=");d&&(a[d.trim()]=u.join("=").trim())}});let l=["PORT","NODE_ENV","SINCH_TUNNEL"];for(let[p,d]of Object.entries(a))if(!l.includes(p))if(d===""||d===null||d===void 0){let u="",m=!1;if(o&&(p==="PROJECT_ID"&&o.projectId?u=o.projectId:p==="PROJECT_ID_API_KEY"&&o.keyId?u=o.keyId:p==="PROJECT_ID_API_SECRET"&&o.keySecret?(u=o.keySecret,m=!0):p==="VOICE_APPLICATION_KEY"&&o.applicationKey?u=o.applicationKey:p==="VOICE_APPLICATION_SECRET"&&o.applicationSecret&&(u=o.applicationSecret,m=!0)),!u)try{let w="sinch-functions-cli",h=`${e}-${p}`;u=await so.default.getPassword(w,h)||"",u&&(m=!0,n.debug(`Loaded custom secret ${p} from keychain`))}catch(w){n.debug(`Could not load ${p} from keychain: ${w.message}`)}u&&(t[p]={Value:u,Secret:m})}else t[p]={Value:d,Secret:!1}}catch(s){n.debug("Could not read .env file: "+s.message)}}return t}async function ea(i,e){let o=Date.now(),r=!1,s;return n.newline(),c.start("\u23F3 Connecting to deployment stream..."),new Promise((a,l)=>{let p,d;i.streamDeployment(e,u=>{let m=Math.floor((Date.now()-o)/1e3);switch(u.type){case"connected":c.text="\u23F3 Deployment stream connected, waiting for updates...";break;case"status":let w=u.data.data.message;c.text=`\u23F3 ${w} (${m}s)`;break;case"progress":let h=u.data.data.message,C=u.data.data.percentComplete;C?c.text=`\u23F3 ${h} (${C}%, ${m}s)`:c.text=`\u23F3 ${h} (${m}s)`;break;case"completed":r=!0,s=u.data.data.url,c.succeed("\u2705 Function deployed successfully"),i.getFunction(e).then(async T=>{if(n.newline(),n.info("\u{1F389} Deployment Complete!"),n.info(` Function: ${N.default.cyan(T.name)}`),n.info(` Status: ${Hn("Running")}`),n.info(` URL: ${N.default.blue(s)}`),s){let ee=await an(),O=await Mn();if(ee.isConversation){n.newline(),n.info("\u{1F4AC} Conversation Integration:");try{c.start("Updating Sinch Conversation webhook..."),await qn(s),c.succeed("Conversation webhook updated automatically"),n.info(` Webhook URL set to: ${N.default.cyan(s+"/conversation")}`)}catch(P){c.fail("Failed to update Conversation webhook");let S=P.response?.data?JSON.stringify(P.response.data):P.message;n.warn(` Error: ${S}`)}}if(O){n.newline(),n.info("\u{1F4DE} Voice Integration:");try{c.start("Updating Sinch Voice callback URL..."),await Un(s),c.succeed("Voice callback URL updated automatically"),n.info(` Callback URL set to: ${N.default.cyan(s)}`)}catch(P){c.fail("Failed to update callback URL automatically"),n.warn(` Error: ${P.message}`),n.info(` Manual setup: ${N.default.cyan(`sinch voice callback-url ${s}`)}`)}}n.info(` Test function: ${N.default.cyan(`curl ${s}`)}`)}n.newline(),n.info("\u{1F4A1} Next steps:"),n.info(` \u2022 View logs: ${N.default.cyan(`sinch functions logs ${e} --follow`)}`),n.info(` \u2022 Check status: ${N.default.cyan(`sinch functions status ${e}`)}`),p&&p(),d&&clearTimeout(d),a()}).catch(T=>{n.error(`Failed to get function details: ${T.message}`),p&&p(),d&&clearTimeout(d),a()});break;case"failed":r=!0;let v=u.data.data.errorMessage;c.fail("\u274C Deployment failed"),n.newline(),n.error("Deployment failed:"),v&&n.error(` ${v}`),n.newline(),n.info("\u{1F4A1} Troubleshooting:"),n.info(` \u2022 Check logs: ${N.default.cyan(`sinch functions logs ${e}`)}`),n.info(` \u2022 Check status: ${N.default.cyan(`sinch functions status ${e}`)}`),p&&p(),d&&clearTimeout(d),process.exit(1);break}},u=>{n.debug("SSE stream error, falling back to polling:",u),c.text="\u23F3 Deployment stream unavailable, checking status...",p&&p(),no(i,e,o,3e5).then(a).catch(l)}).then(u=>{n.debug("SSE stream setup successful, cleanup function received"),p=u,d=setTimeout(()=>{r||(c.fail("\u23F0 Deployment timeout"),n.newline(),n.warn("Deployment is taking longer than expected"),n.info("\u{1F4A1} Check deployment progress with:"),n.info(` ${N.default.cyan(`sinch functions status ${e}`)}`),p&&p(),a())},3e5)}).catch(u=>{n.debug(`Failed to set up SSE stream, falling back to polling: ${u.message}`),no(i,e,o,3e5).then(a).catch(l)})})}async function no(i,e,t,o){for(;Date.now()-t<o;){try{let a=(await i.getFunctionStatus(e)).function;if(a.status==="Running"){if(c.succeed("\u2705 Function deployed successfully"),n.newline(),n.info("\u{1F389} Deployment Complete!"),n.info(` Function: ${N.default.cyan(a.name)}`),n.info(` Status: ${Hn(a.status)}`),n.info(` URL: ${N.default.blue(a.containerAppUrl)}`),a.containerAppUrl){let p=await an(),d=await Mn();if(p.isConversation){n.newline(),n.info("\u{1F4AC} Conversation Integration:");try{c.start("Updating Sinch Conversation webhook..."),await qn(a.containerAppUrl),c.succeed("Conversation webhook updated automatically"),n.info(` Webhook URL set to: ${N.default.cyan(a.containerAppUrl+"/conversation")}`)}catch(u){c.fail("Failed to update Conversation webhook");let m=u.response?.data?JSON.stringify(u.response.data):u.message;n.warn(` Error: ${m}`)}}if(d){n.newline(),n.info("\u{1F4DE} Voice Integration:");try{c.start("Updating Sinch Voice callback URL..."),await Un(a.containerAppUrl),c.succeed("Voice callback URL updated automatically"),n.info(` Callback URL set to: ${N.default.cyan(a.containerAppUrl)}`)}catch(u){c.fail("Failed to update callback URL automatically"),n.warn(` Error: ${u.message}`),n.info(` Manual setup: ${N.default.cyan(`sinch voice callback-url ${a.containerAppUrl}`)}`)}}n.info(` Test function: ${N.default.cyan(`curl ${a.containerAppUrl}`)}`)}n.newline(),n.info("\u{1F4A1} Next steps:"),n.info(` \u2022 View logs: ${N.default.cyan(`sinch functions logs ${e} --follow`)}`),n.info(` \u2022 Check status: ${N.default.cyan(`sinch functions status ${e}`)}`);return}a.status==="Failed"&&(c.fail("\u274C Deployment failed"),n.newline(),n.error("Deployment failed:"),a.errorMessage&&n.error(` ${a.errorMessage}`),n.newline(),n.info("\u{1F4A1} Troubleshooting:"),n.info(` \u2022 Check logs: ${N.default.cyan(`sinch functions logs ${e}`)}`),n.info(` \u2022 Check status: ${N.default.cyan(`sinch functions status ${e}`)}`),process.exit(1));let l=Math.floor((Date.now()-t)/1e3);c.text=`\u23F3 Deploying function... (${a.status}, ${l}s)`}catch(s){n.debug(`Status check failed: ${s.message}`)}await new Promise(s=>setTimeout(s,3e3))}c.fail("\u23F0 Deployment timeout"),n.newline(),n.warn("Deployment is taking longer than expected"),n.info("\u{1F4A1} Check deployment progress with:"),n.info(` ${N.default.cyan(`sinch functions status ${e}`)}`)}function Hn(i){return{Running:N.default.green("\u2705 Running"),Failed:N.default.red("\u274C Failed"),Pending:N.default.yellow("\u23F3 Pending"),Building:N.default.blue("\u{1F528} Building")}[i]||N.default.gray(i)}async function ta(i,e){let t=!1;if(e.docs===!1){n.info("Skipping documentation generation (--no-docs flag)");return}if(e.nonInteractive)n.info("Generating documentation (non-interactive mode)"),t=!0;else{if(i.docsPreference==="never")return;if(na(i))t=!0;else{let o=await Kn.default.prompt([{type:"list",name:"docsChoice",message:"Generate/update documentation before deployment?",choices:[{name:"Yes - Generate documentation this time",value:"yes"},{name:"No - Skip documentation this time",value:"no"},{name:"Always - Generate documentation and remember preference",value:"always"},{name:"Never - Don't generate documentation and remember preference",value:"never"}],default:"yes"}]);o.docsChoice==="yes"?t=!0:o.docsChoice==="no"?t=!1:o.docsChoice==="always"?(t=!0,f.set("docsPreference","always",!0),await f.saveProjectConfig()):o.docsChoice==="never"&&(t=!1,f.set("docsPreference","never",!0),await f.saveProjectConfig())}}if(t)try{c.start("\u{1F4DD} Generating documentation...");let{generateDocsFromLocal:o,saveDocumentationToFile:r}=(Bn(),L(to)),s=await o(),a=et.default.basename(process.cwd());await r(s,"README.md",a),c.succeed("\u{1F4DD} Documentation updated in README.md")}catch(o){c.warn(`\u26A0\uFE0F Failed to generate documentation: ${o.message}`),n.warn("Continuing with deployment...")}}function na(i){return i.docsPreference==="always"}async function ia(i,e){if(e.private||i.accessPreference==="always-private")return"private";if(i.accessPreference==="always-public"||e.nonInteractive)return"public";let o=(await Kn.default.prompt([{type:"list",name:"accessChoice",message:"Deployment access level?",choices:[{name:"Public - Accessible from the internet",value:"public"},{name:"Private - Internal access only (Sinch services)",value:"private"},{name:"Always Public - Remember this choice",value:"always-public"},{name:"Always Private - Remember this choice",value:"always-private"}],default:"public"}])).accessChoice;return o==="always-public"?(f.set("accessPreference","always-public",!0),await f.saveProjectConfig(),"public"):o==="always-private"?(f.set("accessPreference","always-private",!0),await f.saveProjectConfig(),"private"):o}async function oa(i,e){c.start("Building function locally...");try{await new Promise((r,s)=>{let a=(0,_t.spawn)("dotnet",["build",e,"-c","Release"],{cwd:i,stdio:"pipe",shell:!0}),l="",p="";a.stdout?.on("data",d=>{p+=d}),a.stderr?.on("data",d=>{l+=d}),a.on("close",d=>{d!==0?s(new Error(`Build failed:
55
- ${l||p}`)):r()})}),c.succeed("Build successful")}catch(r){throw c.fail("Build failed"),r}c.start("Starting function for validation...");let t=null,o="";try{if(t=(0,_t.spawn)("dotnet",["run","--project",e,"--no-build","-c","Release"],{cwd:i,stdio:"pipe",shell:!0}),t.stdout?.on("data",s=>{o+=s.toString()}),t.stderr?.on("data",s=>{o+=s.toString()}),await ra("http://localhost:3000/health",3e4))c.succeed("Function started and health check passed");else throw c.fail("Function failed to start within timeout"),o&&console.error(`
56
+ `),e}async function Qn(i,e){let t=Ke.resolve(e);await Ct.writeFile(t,i,"utf8")}function wo(i){switch(Ke.extname(i).toLowerCase()){case".js":case".ts":return"node";case".py":return"python";case".cs":return"csharp";default:return"node"}}var Ct,Ke,ei=G(()=>{"use strict";Ct=y(require("fs-extra")),Ke=y(require("path"));Q();E()});var Eo=N((rd,Ao)=>{"use strict";var Ie=y(require("fs-extra")),tt=y(require("path")),x=y(require("chalk")),So=require("commander");Q();E();T();R();ut();mo();go();var bo=y(require("adm-zip")),Io=y(require("os")),ti=y(require("inquirer")),Bt=require("child_process"),$o=y(require("keytar")),Po=new So.Command("deploy");Po.description("Deploy function to production").option("-n, --name <name>","Function name (default: current directory)").option("--no-wait","Don't wait for deployment to complete").option("--non-interactive","Use default values without prompting (auto-generates docs)").option("--no-docs","no doc generation").option("--private","Deploy to private namespace (internal access only, not publicly accessible)").action(async i=>{try{if(await f.load(),!f.isInProject())throw new Error('Not in a Sinch Functions project directory. Run "sinch functions init" first.');let e=f.getProjectConfig(),t=i.name||e.name,o=e.runtime;if(await Ea(e,i),o==="csharp"){let u=await Ie.default.readdir(process.cwd()).then(w=>w.filter(h=>h.endsWith(".csproj")));if(u.length===0)throw new Error("No .csproj file found. Make sure you're in a valid C# function directory.");let m=u[0];await Na(process.cwd(),m)}c.start("\u{1F4E6} Packaging function...");let r=await $a(t);c.succeed("\u{1F4E6} Function packaged"),c.start("\u{1F527} Preparing configuration...");let s=await Pa(o,t);c.succeed("\u{1F527} Configuration prepared");let a=await Ta(e,i);c.start("\u{1F680} Submitting deployment...");let l=new J(f.getApiConfig()),p=await Ie.default.readFile(r),d=await l.deployFunction(t,o,p,s,a);if(await Ie.default.remove(r),c.succeed("\u{1F680} Deployment submitted"),f.set("functionId",d.id,!0),await f.saveProjectConfig(),n.newline(),n.info(`Function ID: ${x.default.cyan(d.id)}`),n.info(`Status: ${ni(d.status)}`),i.wait===!1){n.newline(),n.info("\u{1F4A1} Check deployment progress with:"),n.info(` ${x.default.cyan(`sinch functions status ${d.id}`)}`);return}await Aa(l,d.id)}catch(e){c.stop(),n.error(`Failed to deploy function: ${e.message}`);let t=e.exitCode||I.FAILURE;process.exit(t)}});async function $a(i){let e=new bo.default,t=process.cwd(),o=tt.default.join(Io.default.tmpdir(),`${i}-${Date.now()}.zip`),r=["node_modules","bin","obj",".git",".DS_Store","*.zip",".env",".env.local","npm-debug.log*",".sinch-tmp","examples","claude.md","readme.md",".vs",".vscode",".idea",".cursor","*.user","*.suo"];async function s(a,l=""){let p=await Ie.default.readdir(a);for(let d of p){let u=tt.default.join(a,d),m=tt.default.join(l,d).replace(/\\/g,"/");if(r.some(h=>d.match(new RegExp(h.replace("*",".*")))))continue;if((await Ie.default.stat(u)).isDirectory())await s(u,m);else{let h=await Ie.default.readFile(u);e.addFile(m,h)}}}return await s(t),e.writeZip(o),o}async function Pa(i,e){let t={},o=null;try{o=await f.getCredentials()}catch(r){n.debug("Could not load credentials from secure storage: "+r.message)}if(i==="csharp"){let r=tt.default.join(process.cwd(),"appsettings.json");if(await Ie.default.pathExists(r))try{let s=await Ie.default.readJson(r);for(let a of Object.keys(s)){if(a==="Logging"||a==="AllowedHosts")continue;let l=s[a];if(l===""||l===null||l===void 0){let p="",d=!1;try{let m=(0,Bt.execSync)("dotnet user-secrets list",{cwd:process.cwd(),encoding:"utf8",stdio:["pipe","pipe","pipe"]}).trim().split(`
57
+ `);for(let w of m){let h=w.match(/^([^=]+)\s*=\s*(.+)$/);if(h&&h[1]&&h[2]&&h[1].trim()===a){p=h[2].trim(),d=!0,n.debug(`Found ${a} in dotnet user-secrets`);break}}}catch{}!p&&o&&(a==="PROJECT_ID"&&o.projectId?p=o.projectId:a==="PROJECT_ID_API_KEY"&&o.keyId?p=o.keyId:a==="PROJECT_ID_API_SECRET"&&o.keySecret?(p=o.keySecret,d=!0):a==="VOICE_APPLICATION_KEY"&&o.applicationKey?p=o.applicationKey:a==="VOICE_APPLICATION_SECRET"&&o.applicationSecret&&(p=o.applicationSecret,d=!0)),p&&(t[a]={Value:p,Secret:d})}else t[a]={Value:String(l),Secret:!1}}}catch(s){n.debug("Could not read appsettings.json: "+s.message)}}else{let r=tt.default.join(process.cwd(),".env");if(await Ie.default.pathExists(r))try{let s=await Ie.default.readFile(r,"utf8"),a={};s.split(`
58
+ `).forEach(p=>{if(p.trim()&&!p.trim().startsWith("#")){let[d,...u]=p.split("=");d&&(a[d.trim()]=u.join("=").trim())}});let l=["PORT","NODE_ENV","SINCH_TUNNEL"];for(let[p,d]of Object.entries(a))if(!l.includes(p))if(d===""||d===null||d===void 0){let u="",m=!1;if(o&&(p==="PROJECT_ID"&&o.projectId?u=o.projectId:p==="PROJECT_ID_API_KEY"&&o.keyId?u=o.keyId:p==="PROJECT_ID_API_SECRET"&&o.keySecret?(u=o.keySecret,m=!0):p==="VOICE_APPLICATION_KEY"&&o.applicationKey?u=o.applicationKey:p==="VOICE_APPLICATION_SECRET"&&o.applicationSecret&&(u=o.applicationSecret,m=!0)),!u)try{let w="sinch-functions-cli",h=`${e}-${p}`;u=await $o.default.getPassword(w,h)||"",u&&(m=!0,n.debug(`Loaded custom secret ${p} from keychain`))}catch(w){n.debug(`Could not load ${p} from keychain: ${w.message}`)}u&&(t[p]={Value:u,Secret:m})}else t[p]={Value:d,Secret:!1}}catch(s){n.debug("Could not read .env file: "+s.message)}}return t}async function Aa(i,e){let o=Date.now(),r=!1,s;return n.newline(),c.start("\u23F3 Connecting to deployment stream..."),new Promise((a,l)=>{let p,d;i.streamDeployment(e,u=>{let m=Math.floor((Date.now()-o)/1e3);switch(u.type){case"connected":c.text="\u23F3 Deployment stream connected, waiting for updates...";break;case"status":let w=u.data.data.message;c.text=`\u23F3 ${w} (${m}s)`;break;case"progress":let h=u.data.data.message,C=u.data.data.percentComplete;C?c.text=`\u23F3 ${h} (${C}%, ${m}s)`:c.text=`\u23F3 ${h} (${m}s)`;break;case"completed":r=!0,s=u.data.data.url,c.succeed("\u2705 Function deployed successfully"),i.getFunction(e).then(async k=>{if(n.newline(),n.info("\u{1F389} Deployment Complete!"),n.info(` Function: ${x.default.cyan(k.name)}`),n.info(` Status: ${ni("Running")}`),n.info(` URL: ${x.default.blue(s)}`),s){let re=await hn(),j=await Xn();if(re.isConversation){n.newline(),n.info("\u{1F4AC} Conversation Integration:");try{c.start("Updating Sinch Conversation webhook..."),await Yn(s),c.succeed("Conversation webhook updated automatically"),n.info(` Webhook URL set to: ${x.default.cyan(s+"/conversation")}`)}catch(M){c.fail("Failed to update Conversation webhook");let fe=M.response?.data?JSON.stringify(M.response.data):M.message;n.warn(` Error: ${fe}`)}}if(j){n.newline(),n.info("\u{1F4DE} Voice Integration:");try{c.start("Updating Sinch Voice callback URL..."),await Gn(s),c.succeed("Voice callback URL updated automatically"),n.info(` Callback URL set to: ${x.default.cyan(s)}`)}catch(M){c.fail("Failed to update callback URL automatically"),n.warn(` Error: ${M.message}`),n.info(` Manual setup: ${x.default.cyan(`sinch voice callback-url ${s}`)}`)}}n.info(` Test function: ${x.default.cyan(`curl ${s}`)}`)}n.newline(),n.info("\u{1F4A1} Next steps:"),n.info(` \u2022 View logs: ${x.default.cyan(`sinch functions logs ${e} --follow`)}`),n.info(` \u2022 Check status: ${x.default.cyan(`sinch functions status ${e}`)}`),p&&p(),d&&clearTimeout(d),a()}).catch(k=>{n.error(`Failed to get function details: ${k.message}`),p&&p(),d&&clearTimeout(d),a()});break;case"failed":r=!0;let v=u.data.data.errorMessage;c.fail("\u274C Deployment failed"),n.newline(),n.error("Deployment failed:"),v&&n.error(` ${v}`),n.newline(),n.info("\u{1F4A1} Troubleshooting:"),n.info(` \u2022 Check logs: ${x.default.cyan(`sinch functions logs ${e}`)}`),n.info(` \u2022 Check status: ${x.default.cyan(`sinch functions status ${e}`)}`),p&&p(),d&&clearTimeout(d),process.exit(1);break}},u=>{n.debug("SSE stream error, falling back to polling:",u),c.text="\u23F3 Deployment stream unavailable, checking status...",p&&p(),vo(i,e,o,3e5).then(a).catch(l)}).then(u=>{n.debug("SSE stream setup successful, cleanup function received"),p=u,d=setTimeout(()=>{r||(c.fail("\u23F0 Deployment timeout"),n.newline(),n.warn("Deployment is taking longer than expected"),n.info("\u{1F4A1} Check deployment progress with:"),n.info(` ${x.default.cyan(`sinch functions status ${e}`)}`),p&&p(),a())},3e5)}).catch(u=>{n.debug(`Failed to set up SSE stream, falling back to polling: ${u.message}`),vo(i,e,o,3e5).then(a).catch(l)})})}async function vo(i,e,t,o){for(;Date.now()-t<o;){try{let a=(await i.getFunctionStatus(e)).function;if(a.status==="Running"){if(c.succeed("\u2705 Function deployed successfully"),n.newline(),n.info("\u{1F389} Deployment Complete!"),n.info(` Function: ${x.default.cyan(a.name)}`),n.info(` Status: ${ni(a.status)}`),n.info(` URL: ${x.default.blue(a.containerAppUrl)}`),a.containerAppUrl){let p=await hn(),d=await Xn();if(p.isConversation){n.newline(),n.info("\u{1F4AC} Conversation Integration:");try{c.start("Updating Sinch Conversation webhook..."),await Yn(a.containerAppUrl),c.succeed("Conversation webhook updated automatically"),n.info(` Webhook URL set to: ${x.default.cyan(a.containerAppUrl+"/conversation")}`)}catch(u){c.fail("Failed to update Conversation webhook");let m=u.response?.data?JSON.stringify(u.response.data):u.message;n.warn(` Error: ${m}`)}}if(d){n.newline(),n.info("\u{1F4DE} Voice Integration:");try{c.start("Updating Sinch Voice callback URL..."),await Gn(a.containerAppUrl),c.succeed("Voice callback URL updated automatically"),n.info(` Callback URL set to: ${x.default.cyan(a.containerAppUrl)}`)}catch(u){c.fail("Failed to update callback URL automatically"),n.warn(` Error: ${u.message}`),n.info(` Manual setup: ${x.default.cyan(`sinch voice callback-url ${a.containerAppUrl}`)}`)}}n.info(` Test function: ${x.default.cyan(`curl ${a.containerAppUrl}`)}`)}n.newline(),n.info("\u{1F4A1} Next steps:"),n.info(` \u2022 View logs: ${x.default.cyan(`sinch functions logs ${e} --follow`)}`),n.info(` \u2022 Check status: ${x.default.cyan(`sinch functions status ${e}`)}`);return}a.status==="Failed"&&(c.fail("\u274C Deployment failed"),n.newline(),n.error("Deployment failed:"),a.errorMessage&&n.error(` ${a.errorMessage}`),n.newline(),n.info("\u{1F4A1} Troubleshooting:"),n.info(` \u2022 Check logs: ${x.default.cyan(`sinch functions logs ${e}`)}`),n.info(` \u2022 Check status: ${x.default.cyan(`sinch functions status ${e}`)}`),process.exit(1));let l=Math.floor((Date.now()-t)/1e3);c.text=`\u23F3 Deploying function... (${a.status}, ${l}s)`}catch(s){n.debug(`Status check failed: ${s.message}`)}await new Promise(s=>setTimeout(s,3e3))}c.fail("\u23F0 Deployment timeout"),n.newline(),n.warn("Deployment is taking longer than expected"),n.info("\u{1F4A1} Check deployment progress with:"),n.info(` ${x.default.cyan(`sinch functions status ${e}`)}`)}function ni(i){return{Running:x.default.green("\u2705 Running"),Failed:x.default.red("\u274C Failed"),Pending:x.default.yellow("\u23F3 Pending"),Building:x.default.blue("\u{1F528} Building")}[i]||x.default.gray(i)}async function Ea(i,e){let t=!1;if(e.docs===!1){n.info("Skipping documentation generation (--no-docs flag)");return}if(e.nonInteractive)n.info("Generating documentation (non-interactive mode)"),t=!0;else{if(i.docsPreference==="never")return;if(ka(i))t=!0;else{let o=await ti.default.prompt([{type:"list",name:"docsChoice",message:"Generate/update documentation before deployment?",choices:[{name:"Yes - Generate documentation this time",value:"yes"},{name:"No - Skip documentation this time",value:"no"},{name:"Always - Generate documentation and remember preference",value:"always"},{name:"Never - Don't generate documentation and remember preference",value:"never"}],default:"yes"}]);o.docsChoice==="yes"?t=!0:o.docsChoice==="no"?t=!1:o.docsChoice==="always"?(t=!0,f.set("docsPreference","always",!0),await f.saveProjectConfig()):o.docsChoice==="never"&&(t=!1,f.set("docsPreference","never",!0),await f.saveProjectConfig())}}if(t)try{c.start("\u{1F4DD} Generating documentation...");let{generateDocsFromLocal:o,saveDocumentationToFile:r}=(ei(),F(Co)),s=await o(),a=tt.default.basename(process.cwd());await r(s,"README.md",a),c.succeed("\u{1F4DD} Documentation updated in README.md")}catch(o){c.warn(`\u26A0\uFE0F Failed to generate documentation: ${o.message}`),n.warn("Continuing with deployment...")}}function ka(i){return i.docsPreference==="always"}async function Ta(i,e){if(e.private||i.accessPreference==="always-private")return"private";if(i.accessPreference==="always-public"||e.nonInteractive)return"public";let o=(await ti.default.prompt([{type:"list",name:"accessChoice",message:"Deployment access level?",choices:[{name:"Public - Accessible from the internet",value:"public"},{name:"Private - Internal access only (Sinch services)",value:"private"},{name:"Always Public - Remember this choice",value:"always-public"},{name:"Always Private - Remember this choice",value:"always-private"}],default:"public"}])).accessChoice;return o==="always-public"?(f.set("accessPreference","always-public",!0),await f.saveProjectConfig(),"public"):o==="always-private"?(f.set("accessPreference","always-private",!0),await f.saveProjectConfig(),"private"):o}async function Na(i,e){c.start("Building function locally...");try{await new Promise((r,s)=>{let a=(0,Bt.spawn)("dotnet",["build",e,"-c","Release"],{cwd:i,stdio:"pipe",shell:!0}),l="",p="";a.stdout?.on("data",d=>{p+=d}),a.stderr?.on("data",d=>{l+=d}),a.on("close",d=>{d!==0?s(new Error(`Build failed:
59
+ ${l||p}`)):r()})}),c.succeed("Build successful")}catch(r){throw c.fail("Build failed"),r}c.start("Starting function for validation...");let t=null,o="";try{if(t=(0,Bt.spawn)("dotnet",["run","--project",e,"--no-build","-c","Release"],{cwd:i,stdio:"pipe",shell:!0}),t.stdout?.on("data",s=>{o+=s.toString()}),t.stderr?.on("data",s=>{o+=s.toString()}),await Ra("http://localhost:3000/health",3e4))c.succeed("Function started and health check passed");else throw c.fail("Function failed to start within timeout"),o&&console.error(`
56
60
  Process output:
57
61
  `+o),new Error("Function validation failed: could not start function")}catch(r){throw c.fail("Validation failed"),o&&console.error(`
58
62
  Process output:
59
- `+o),r}finally{if(t&&t.pid){try{process.kill(t.pid)}catch{}await new Promise(r=>setTimeout(r,1e3))}}}async function ra(i,e){let t=Date.now();for(;Date.now()-t<e;){try{if((await fetch(i)).ok)return!0}catch{}await new Promise(o=>setTimeout(o,500))}return!1}co.exports=ao});function aa(i){return sa.some(e=>typeof e=="string"?i===e:e.test(i))}function po(i){let e={};for(let[t,o]of Object.entries(process.env))aa(t)&&(e[t]=o);return i&&Object.assign(e,i),e}var sa,uo=W(()=>{"use strict";sa=["PATH","PATHEXT","SYSTEMROOT","SYSTEMDRIVE","WINDIR","COMSPEC","HOMEDRIVE","HOMEPATH","USERPROFILE","APPDATA","LOCALAPPDATA","PROGRAMFILES","PROGRAMDATA","TEMP","TMP","OS","HOME","USER","SHELL","LANG","LC_ALL","LC_CTYPE","TERM","TZ","TMPDIR","XDG_RUNTIME_DIR","NODE_PATH","NODE_ENV","NODE_OPTIONS","NODE_NO_WARNINGS","NODE_EXTRA_CA_CERTS","DEBUG","EDITOR","TERM_PROGRAM",/^SINCH_/,/^ASPNETCORE_/,/^DOTNET_/,/^npm_/]});var yo=x((Dl,ho)=>{"use strict";var K=y(require("fs-extra")),Ie=y(require("path")),Ut=y(require("chalk")),Wn=require("child_process"),fo=require("commander"),mo=y(require("inquirer"));A();E();D();pt();uo();var go=new fo.Command("dev");go.description("Start local development server").option("-p, --port <port>","Port to run on","3000").option("-d, --debug","Enable debugging with --inspect").option("--tunnel","Force tunnel creation").option("--no-tunnel",'Disable tunnel and reset "always" preference').action(async i=>{try{if(await f.load(),!f.isInProject())throw new Error('Not in a Sinch Functions project directory. Run "sinch functions init" first.');let e=f.getProjectConfig();if(!e)throw new Error("No project configuration found");let t=e.runtime||"node",o;if(t==="csharp"){let r=await K.default.readdir(process.cwd()).then(s=>s.filter(a=>a.endsWith(".csproj")));if(r.length===0)throw new Error("No .csproj file found. Make sure you're in a valid C# function directory.");o=r[0],n.debug(`Using project file: ${o}`)}else{let r=Ie.default.join(process.cwd(),"node_modules",".bin","sinch-runtime");if(!await K.default.pathExists(r))throw new Error("@sinch/functions-runtime not found. Run npm install first.")}n.title(`Starting ${e.name} (${e.runtime})`),n.info(`Port: ${i.port}`),n.newline(),await la(i,e,o)}catch(e){c.stop(),n.error(`Failed to start development server: ${e.message}`);let t=e.exitCode||$.FAILURE;process.exit(t)}});async function ca(i,e){if(e==="node"){let t=Ie.default.join(process.cwd(),".env");if(await K.default.pathExists(t)){let o=await K.default.readFile(t,"utf-8"),r=`SINCH_TUNNEL=${i}`;o.includes("SINCH_TUNNEL=")?o=o.replace(/SINCH_TUNNEL=(true|false)/g,r):o+=`
63
+ `+o),r}finally{if(t&&t.pid){try{process.kill(t.pid)}catch{}await new Promise(r=>setTimeout(r,1e3))}}}async function Ra(i,e){let t=Date.now();for(;Date.now()-t<e;){try{if((await fetch(i)).ok)return!0}catch{}await new Promise(o=>setTimeout(o,500))}return!1}Ao.exports=Po});function xa(i){return Da.some(e=>typeof e=="string"?i===e:e.test(i))}function ko(i){let e={};for(let[t,o]of Object.entries(process.env))xa(t)&&(e[t]=o);return i&&Object.assign(e,i),e}var Da,To=G(()=>{"use strict";Da=["PATH","PATHEXT","SYSTEMROOT","SYSTEMDRIVE","WINDIR","COMSPEC","HOMEDRIVE","HOMEPATH","USERPROFILE","APPDATA","LOCALAPPDATA","PROGRAMFILES","PROGRAMDATA","TEMP","TMP","OS","HOME","USER","SHELL","LANG","LC_ALL","LC_CTYPE","TERM","TZ","TMPDIR","XDG_RUNTIME_DIR","NODE_PATH","NODE_ENV","NODE_OPTIONS","NODE_NO_WARNINGS","NODE_EXTRA_CA_CERTS","DEBUG","EDITOR","TERM_PROGRAM",/^SINCH_/,/^ASPNETCORE_/,/^DOTNET_/,/^npm_/]});var Oo=N((fd,xo)=>{"use strict";var z=y(require("fs-extra")),ke=y(require("path")),Kt=y(require("chalk")),ii=require("child_process"),No=require("commander"),Ro=y(require("inquirer"));E();T();R();ut();To();var Do=new No.Command("dev");Do.description("Start local development server").option("-p, --port <port>","Port to run on","3000").option("-d, --debug","Enable debugging with --inspect").option("--tunnel","Force tunnel creation").option("--no-tunnel",'Disable tunnel and reset "always" preference').action(async i=>{try{if(await f.load(),!f.isInProject())throw new Error('Not in a Sinch Functions project directory. Run "sinch functions init" first.');let e=f.getProjectConfig();if(!e)throw new Error("No project configuration found");let t=e.runtime||"node",o;if(t==="csharp"){let r=await z.default.readdir(process.cwd()).then(s=>s.filter(a=>a.endsWith(".csproj")));if(r.length===0)throw new Error("No .csproj file found. Make sure you're in a valid C# function directory.");o=r[0],n.debug(`Using project file: ${o}`)}else{let r=ke.default.join(process.cwd(),"node_modules",".bin","sinch-runtime");if(!await z.default.pathExists(r))throw new Error("@sinch/functions-runtime not found. Run npm install first.")}n.title(`Starting ${e.name} (${e.runtime})`),n.info(`Port: ${i.port}`),n.newline(),await Fa(i,e,o)}catch(e){c.stop(),n.error(`Failed to start development server: ${e.message}`);let t=e.exitCode||I.FAILURE;process.exit(t)}});async function Oa(i,e){if(e==="node"){let t=ke.default.join(process.cwd(),".env");if(await z.default.pathExists(t)){let o=await z.default.readFile(t,"utf-8"),r=`SINCH_TUNNEL=${i}`;o.includes("SINCH_TUNNEL=")?o=o.replace(/SINCH_TUNNEL=(true|false)/g,r):o+=`
60
64
  ${r}
61
- `,await K.default.writeFile(t,o,"utf-8"),n.debug(`Updated .env: SINCH_TUNNEL=${i}`)}}else if(e==="csharp"){let t=Ie.default.join(process.cwd(),"appsettings.Development.json");if(await K.default.pathExists(t)){let o=await K.default.readJson(t);o.SinchTunnel=i,await K.default.writeJson(t,o,{spaces:2}),n.debug(`Updated appsettings.Development.json: SinchTunnel=${i}`)}}}async function la(i,e,t){let o=e.runtime||"node",r=!1;if(i.tunnel===!0)r=!0;else if(i.tunnel===!1)r=!1,e.tunnel?.preference==="always"&&(f.set("tunnel",{...e.tunnel,preference:"no"},!0),await f.saveProjectConfig());else if(e.tunnel?.preference==="never")r=!1;else if(fa(e))r=!0;else{let{tunnelChoice:d}=await mo.default.prompt([{type:"list",name:"tunnelChoice",message:"Enable Sinch tunnel for external access?",choices:[{name:"Yes - Enable tunnel this time",value:"yes"},{name:"No - Local only this time",value:"no"},{name:"Always - Enable tunnel and remember preference",value:"always"},{name:"Never - Don't enable tunnel and remember preference",value:"never"}],default:"no"}]);d==="yes"?r=!0:d==="no"?r=!1:d==="always"?(r=!0,f.set("tunnel",{...e.tunnel,preference:"always"},!0),await f.saveProjectConfig()):d==="never"&&(r=!1,f.set("tunnel",{...e.tunnel,preference:"never"},!0),await f.saveProjectConfig())}await ca(r,o);let s=po({PORT:i.port,NODE_ENV:"development",SINCH_FUNCTIONS_LOCAL:"true",SINCH_TUNNEL:r?"true":"false"});e.variables&&Object.entries(e.variables).forEach(([d,u])=>{s[d]=u});try{let d=await f.getApplicationCredentials(e.voiceAppKey);d?(s.SINCH_APPLICATION_KEY=d.applicationKey,s.SINCH_APPLICATION_SECRET=d.applicationSecret,n.debug("\u2705 Injected application credentials for voice operations")):n.debug("\u26A0\uFE0F No application credentials found - voice features may not work")}catch(d){n.debug(`\u26A0\uFE0F Could not load application credentials: ${d.message}`)}n.info("\u{1F680} Starting local server...");let a=null,l=!1;function p(){if(a&&a.kill(),o==="csharp"){let d=["watch","run","--no-launch-profile"];t&&d.push("--project",t),i.port&&d.push("--urls",`http://localhost:${i.port}`),s.ASPNETCORE_ENVIRONMENT="Development",s.ASPNETCORE_URLS=`http://localhost:${i.port}`,a=(0,Wn.spawn)("dotnet",d,{env:s,stdio:"inherit",cwd:process.cwd()})}else a=(0,Wn.spawn)("npm",["run","dev"],{env:s,stdio:"inherit",cwd:process.cwd(),shell:!0});a.on("spawn",async()=>{if(!l){l=!0,n.newline(),n.success(`\u2705 Server running on http://localhost:${i.port}`),i.debug&&(n.newline(),o==="csharp"?ma():da()),n.newline(),n.info("\u{1F4A1} Development commands:"),n.info(` \u2022 Test function: ${Ut.default.cyan(`curl http://localhost:${i.port}`)}`),n.info(` \u2022 View in browser: ${Ut.default.cyan(`http://localhost:${i.port}`)}`),n.info(` \u2022 Stop server: ${Ut.default.gray("Ctrl+C")}`);let d=o==="csharp"?"dotnet watch":"nodemon";n.info(` \u2022 File watching: ${Ut.default.green(`enabled (via ${d})`)}`)}}),a.on("error",d=>{n.error(`Server error: ${d.message}`)}),a.on("exit",(d,u)=>{u!=="SIGTERM"&&u!=="SIGKILL"&&n.error(`Server exited with code ${d}`)})}p(),process.on("SIGINT",()=>{n.newline(),n.info("\u{1F534} Stopping development server..."),a&&a.kill("SIGTERM"),process.exit(0)}),await new Promise(()=>{})}async function da(){try{let i=await yt("code",".vscode"),e=await yt("cursor",".cursor"),t=await yt("webstorm",".idea");if(i||e){let o=i?"VS Code":"Cursor",r=".vscode";if(n.info(`\u{1F41B} ${o} detected! Debug setup:`),await ua(r))n.info(" 1. \u2705 Created .vscode/launch.json for you");else{let a=Ie.default.join(process.cwd(),r,"launch.json");await K.default.pathExists(a)?n.info(" 1. \u2705 Found existing .vscode/launch.json"):n.info(" 1. \u26A0\uFE0F Could not create .vscode/launch.json")}n.info(" 2. \u{1F50D} Press F5 to attach debugger"),n.info(" 3. \u{1F534} Set breakpoints in your function.js"),n.info(" 4. \u{1F4DE} Test your function to hit breakpoints")}else t?(n.info("\u{1F41B} WebStorm detected! Debug setup:"),n.info(" 1. \u{1F50D} Run \u2192 Attach to Node.js/Chrome \u2192 localhost:9229"),n.info(" 2. \u{1F534} Set breakpoints in your function.js")):(n.info("\u{1F41B} Manual debug setup:"),n.info(' \u2022 VS Code/Cursor: Open "Run and Debug" \u2192 "Attach to Node.js Process"'),n.info(' \u2022 Chrome DevTools: Visit chrome://inspect \u2192 Click "inspect"'),n.info(" \u2022 Manual: Connect debugger to ws://localhost:9229"))}catch{n.info("\u{1F41B} Debug instructions:"),n.info(" \u2022 Connect your debugger to ws://localhost:9229"),n.info(" \u2022 Set breakpoints and test your function")}}async function yt(i,e){try{if(i==="code"&&pa())return!0;let{spawn:t}=require("child_process"),o=await new Promise(s=>{let a=t(i,["--version"],{stdio:"pipe"});a.on("close",l=>s(l===0)),a.on("error",()=>s(!1))}),r=e?await K.default.pathExists(e):!1;return o||r}catch{return!1}}function pa(){return process.env.TERM_PROGRAM==="vscode"||!!process.env.VSCODE_IPC_HOOK||!!process.env.VSCODE_PID}async function ua(i=".vscode"){try{let e=Ie.default.join(process.cwd(),i),t=Ie.default.join(e,"launch.json");if(await K.default.pathExists(t))return!1;await K.default.ensureDir(e);let o={version:"0.2.0",configurations:[{name:"Attach to Sinch Function",type:"node",request:"attach",port:9229,localRoot:"${workspaceFolder}",remoteRoot:"${workspaceFolder}",skipFiles:["<node_internals>/**","node_modules/**"]}]};return await K.default.writeJson(t,o,{spaces:2}),!!await K.default.pathExists(t)}catch{return!1}}function fa(i){return i.tunnel?i.tunnel.preference==="always":!1}async function ma(){try{let i=await yt("code",".vscode"),e=await yt("devenv"),t=await yt("rider",".idea");i?(n.info("\u{1F41B} VS Code detected! Debug setup:"),await ga(".vscode")?n.info(" 1. \u2705 Created .vscode/launch.json for C#"):n.info(" 1. \u2705 Found existing .vscode/launch.json"),n.info(" 2. \u{1F50D} Press F5 to attach debugger"),n.info(" 3. \u{1F534} Set breakpoints in your Function.cs"),n.info(" 4. \u{1F4DE} Test your function to hit breakpoints")):e?(n.info("\u{1F41B} Visual Studio detected! Debug setup:"),n.info(" 1. \u{1F50D} Debug \u2192 Attach to Process \u2192 dotnet.exe"),n.info(" 2. \u{1F534} Set breakpoints in your Function.cs"),n.info(" 3. \u{1F4DE} Test your function to hit breakpoints")):t?(n.info("\u{1F41B} JetBrains Rider detected! Debug setup:"),n.info(" 1. \u{1F50D} Run \u2192 Attach to Process \u2192 dotnet"),n.info(" 2. \u{1F534} Set breakpoints in your Function.cs")):(n.info("\u{1F41B} C# Debug setup:"),n.info(" \u2022 Visual Studio: Debug \u2192 Attach to Process \u2192 dotnet.exe"),n.info(" \u2022 VS Code: Install C# extension, then F5 to debug"),n.info(" \u2022 Rider: Run \u2192 Attach to Process"))}catch{n.info("\u{1F41B} C# Debug instructions:"),n.info(" \u2022 Attach your debugger to the dotnet process"),n.info(" \u2022 Set breakpoints in Function.cs")}}async function ga(i=".vscode"){try{let e=Ie.default.join(process.cwd(),i),t=Ie.default.join(e,"launch.json");if(await K.default.pathExists(t))return!1;await K.default.ensureDir(e);let o={version:"0.2.0",configurations:[{name:".NET Core Launch (web)",type:"coreclr",request:"launch",preLaunchTask:"build",program:"${workspaceFolder}/bin/Debug/net8.0/Function.dll",args:[],cwd:"${workspaceFolder}",stopAtEntry:!1,serverReadyAction:{action:"openExternally",pattern:"\\bNow listening on:\\s+(https?://\\S+)"},env:{ASPNETCORE_ENVIRONMENT:"Development"},sourceFileMap:{"/Views":"${workspaceFolder}/Views"}},{name:".NET Core Attach",type:"coreclr",request:"attach"}]};await K.default.writeJson(t,o,{spaces:2});let r=Ie.default.join(e,"tasks.json");if(!await K.default.pathExists(r)){let s={version:"2.0.0",tasks:[{label:"build",command:"dotnet",type:"process",args:["build","${workspaceFolder}/Function.csproj","/property:GenerateFullPaths=true","/consoleloggerparameters:NoSummary"],problemMatcher:"$msCompile"}]};await K.default.writeJson(r,s,{spaces:2})}return await K.default.pathExists(t)}catch{return!1}}ho.exports=go});var So=x((jl,bo)=>{"use strict";var le=y(require("chalk")),wo=require("commander");X();A();E();D();var Co=new wo.Command("status");Co.description("Show function status and details").argument("[function-id]","Function ID to check (optional if sinch.json exists)").option("-f, --follow","Watch status changes in real-time").option("--json","Output raw JSON").action(async(i,e)=>{try{await f.load();let t=new V(f.getApiConfig()),o=i;if(!o){if(!f.isInProject())throw new Error("Function ID required. Provide as argument or run from function directory with sinch.json");if(o=f.getProjectConfig()?.functionId,!o)throw new Error("No function ID found in sinch.json. Deploy the function first or provide function ID as argument.")}e.follow?await ya(t,o):await ha(t,o,e)}catch(t){c.stop(),n.error(`Failed to get function status: ${t.message}`),process.exit(1)}});async function ha(i,e,t){c.start("\u{1F4E1} Loading function status...");try{let o=await i.getFunction(e),r=await i.getFunctionStatus(e);if(c.stop(),t.json){console.log(JSON.stringify({function:o,deployment:r},null,2));return}let s=o,a=r.status,l=r.error;n.newline(),n.title(`Function Status: ${s.name}`),n.newline(),n.info("\u{1F4CB} Function Details:"),n.info(` ID: ${le.default.gray(s.id)}`),n.info(` Name: ${le.default.cyan(s.name)}`),n.info(` Runtime: ${le.default.yellow(s.runtime)}`),n.info(` Deployment Status: ${vo(a)}`),s.created&&n.info(` Created: ${new Date(s.created).toLocaleString()}`),s.updated&&n.info(` Updated: ${new Date(s.updated).toLocaleString()}`),s.url&&n.info(` URL: ${le.default.blue(s.url)}`),a==="Failed"&&l&&(n.newline(),n.error("Deployment Error:"),n.error(` ${l}`)),n.newline(),n.info("\u{1F4A1} Commands:"),n.info(` \u2022 View logs: ${le.default.cyan(`sinch functions logs ${e}`)}`),n.info(` \u2022 Redeploy: ${le.default.cyan("sinch functions deploy")}`),n.info(` \u2022 Delete: ${le.default.cyan(`sinch functions delete ${e}`)}`)}catch(o){throw c.stop(),o}}async function ya(i,e){n.info("\u{1F440} Watching deployment status (press Ctrl+C to stop)..."),n.newline();let t=null,o=setInterval(async()=>{try{let r=await i.getFunctionStatus(e),s=r.status;if(s!==t){let a=new Date().toLocaleTimeString();if(n.info(`[${a}] Status: ${vo(s)}`),t=s,s==="Running"){n.success("Function deployment is now running!");try{let l=await i.getFunction(e);l.url&&n.info(`URL: ${le.default.blue(l.url)}`)}catch{}}else s==="Failed"&&(n.error("Function deployment failed!"),r.error&&n.error(`Error: ${r.error}`),clearInterval(o))}}catch(r){n.error(`Error checking status: ${r.message}`)}},3e3);process.on("SIGINT",()=>{clearInterval(o),n.newline(),n.info("Stopped watching function status"),process.exit(0)})}function vo(i){return{Running:le.default.green("\u2705 Running"),Failed:le.default.red("\u274C Failed"),Pending:le.default.yellow("\u23F3 Pending"),Building:le.default.blue("\u{1F528} Building")}[i]||le.default.gray(i)}bo.exports=Co});var To=x((ql,Do)=>{"use strict";var tt=y(require("chalk")),Po=require("commander");X();A();E();D();var zn=require("child_process"),qt=y(require("fs")),Mt=y(require("os")),Vt=y(require("path")),Gn=new Po.Command("logs");Gn.description("View function logs").argument("[function-id]","Function ID to get logs for (optional if sinch.json exists)").option("-f, --follow","Follow log output in real-time").option("-n, --lines <number>","Number of historical lines to show","50").option("--level <level>","Filter by log level (debug, info, warning, error)").option("--search <text>","Search for text in log messages").option("--since <duration>","Show logs since duration (e.g., 1h, 30m, 5s)").action(async(i,e)=>{try{await f.load();let t=new V(f.getApiConfig()),o=i;if(!o){if(!f.isInProject())throw new Error("Function ID required. Provide as argument or run from function directory with sinch.json");let s=f.getProjectConfig();if(!s)throw new Error("No project configuration found");if(o=s.functionId,!o)throw new Error("No function ID found in sinch.json. Deploy the function first or provide function ID as argument.")}c.start("Loading function details...");let r=await t.getFunction(o);c.stop(),n.info(`\u{1F4CB} Logs for function: ${tt.default.cyan(r.name)} (${Ca(r.status)})`),n.newline(),e.follow?await ko(t,o,r.name,e):await xa(t,o,e)}catch(t){c.stop(),n.error(`Failed to get logs: ${t.message}`),process.exit(1)}});Gn.command("stream").description("Stream function logs in real-time").argument("[function-id]","Function ID to stream logs for (optional if sinch.json exists)").option("--level <level>","Filter by log level (debug, info, warning, error)").option("--search <text>","Search for text in log messages").action(async(i,e)=>{try{await f.load();let t=new V(f.getApiConfig()),o=i;if(!o){if(!f.isInProject())throw new Error("Function ID required. Provide as argument or run from function directory with sinch.json");let s=f.getProjectConfig();if(!s)throw new Error("No project configuration found");if(o=s.functionId,!o)throw new Error("No function ID found in sinch.json. Deploy the function first or provide function ID as argument.")}c.start("Connecting to log stream...");let r=await wa(t,o);c.stop(),await ko(t,o,r.name,{...e,follow:!0})}catch(t){c.stop(),n.error(`Failed to stream logs: ${t.message}`),process.exit(1)}});async function wa(i,e){return await i.getFunction(e)}async function ko(i,e,t,o){let r=i.baseUrl.replace(/\/+$/,""),s=i.projectId,a=`${r}/v1/projects/${s}/functions/${e}/logs/stream`,l=i.credentials,p=[],d=Eo(p,"STREAMING",t),u={Accept:"text/event-stream","Cache-Control":"no-cache"};if(l)try{let w=await l.retrieve();if(w&&w.keyId&&w.keySecret){let h=Buffer.from(`${w.keyId}:${w.keySecret}`).toString("base64");u.Authorization=`Basic ${h}`}}catch(w){n.debug("Failed to add authentication:",w)}let m=new AbortController;try{let w=await fetch(a,{method:"GET",headers:u,signal:m.signal});if(!w.ok)throw new Error(`SSE connection failed: ${w.status} ${w.statusText}`);if(!w.body)throw new Error("Response body is null");Io(d.statusBar,"CONNECTED",t),d.screen.render();let h=w.body.getReader(),C=new TextDecoder,v="";(async()=>{try{for(;;){let{done:ee,value:O}=await h.read();if(ee)break;v+=C.decode(O,{stream:!0});let P=v.split(`
62
- `);v=P.pop()||"";for(let S of P)if(!S.startsWith("event:")&&S.startsWith("data:")){let I=S.substring(5).trim();if(I)try{let b=JSON.parse(I);b.type==="request"&&b.request&&(p.push(b.request),Ao(d.table,b.request,p),d.table.focus(),d.screen.render())}catch{}}}}catch(ee){ee.name!=="AbortError"&&(Io(d.statusBar,"RECONNECTING",t),d.screen.render())}})(),d.screen.key(["q","C-c"],()=>{m.abort(),process.exit(0)}),await new Promise(()=>{})}catch(w){m.abort(),n.error(`\u274C Streaming failed: ${w.message}`),process.exit(1)}}function Ca(i){return{Running:tt.default.green("\u2705 Running"),Failed:tt.default.red("\u274C Failed"),Pending:tt.default.yellow("\u23F3 Pending"),Building:tt.default.blue("\u{1F528} Building")}[i]||tt.default.gray(i)}var nt=[];function Ao(i,e,t){let o=new Date(e.startTime),r=o.getFullYear()+"-"+String(o.getMonth()+1).padStart(2,"0")+"-"+String(o.getDate()).padStart(2,"0")+" "+String(o.getHours()).padStart(2,"0")+":"+String(o.getMinutes()).padStart(2,"0")+":"+String(o.getSeconds()).padStart(2,"0"),s=Ea(e),a=`${e.executionTimeMs}ms`,l=e.statusCode.toString(),p=process.stdout.columns||120,u=Math.max(30,p-35),m=e.url.length>u?e.url.substring(0,u-2)+"..":e.url;nt.push([r,s,a,l,m]),nt.length>100&&(nt=nt.slice(-100),t&&t.length>100&&t.splice(0,t.length-100));let w=[["Time","Callback","Duration","Status","Path"],...nt];i.setData(w)}function va(i,e,t,o,r){try{let s=require("blessed");n.debug(`Showing request details for ${i.httpMethod} ${i.url}`);let a=s.box({parent:e,top:0,left:0,width:"100%",height:"100%",border:{type:"line"},style:{border:{fg:"cyan"},bg:"black",fg:"white"},scrollable:!0,alwaysScroll:!0,keys:!0,vi:!0,tags:!0,label:" Request Details "}),l=s.box({parent:a,top:1,left:2,width:"100%-4",height:1,content:"{gray-fg}[Esc/Q] Close [\u2191\u2193] Scroll [J/1] JSON [C/2] cURL{/}",tags:!0,style:{bg:"blue",fg:"white"}});s.box({parent:a,top:2,left:2,width:"100%-4",height:1,content:`{bold}{cyan-fg}${i.httpMethod}{/} {blue-fg}${i.url}{/} - {${ka(i.statusCode)}}${i.statusCode}{/} - {yellow-fg}${i.executionTimeMs}ms{/} - {magenta-fg}${i.memoryUsedMB||0}MB{/}`,tags:!0,style:{bg:"black"}});let p=s.box({parent:a,top:4,left:2,width:"100%-4",height:"100%-5",scrollable:!0,alwaysScroll:!0,keys:!0,vi:!0,tags:!0,content:ba(i)});p.focus(),e.render();let d=!0,u=()=>{d&&(d=!1,a.destroy(),t.focus(),e.render())};e.key(["escape","q"],()=>{d&&u()}),e.key(["up","k"],()=>{d&&(p.scroll(-1),e.render())}),e.key(["down","j"],()=>{d&&(p.scroll(1),e.render())}),e.on("keypress",(m,w)=>{d&&n.debug(`Key pressed: ch="${m}" key=${JSON.stringify(w)}`)}),e.key(["J","j"],()=>{d&&(n.debug("J/j key pressed - attempting JSON copy"),l.setContent("{black-bg}{yellow-fg} J KEY PRESSED - COPYING JSON... {/}"),e.render(),setTimeout(()=>{try{let m=JSON.stringify(i,null,2);n.debug(`JSON content length: ${m.length}`),n.debug("Attempting native clipboard copy"),cn(m).then(()=>{l.setContent("{green-fg}\u2713 Request JSON copied to clipboard!{/}"),n.debug("Native clipboard copy succeeded"),e.render(),setTimeout(()=>{d&&(l.setContent("{gray-fg}[Esc/Q] Close [\u2191\u2193] Scroll [J] JSON [C] cURL{/}"),e.render())},3e3)}).catch(w=>{n.debug(`Native clipboard failed: ${w.message}`);let h=Vt.default.join(Mt.default.tmpdir(),`sinch-request-${Date.now()}.json`);qt.default.writeFileSync(h,m),l.setContent(`{yellow-fg}\u2713 JSON saved to: ${h}{/}`),n.debug(`Saved to temp file: ${h}`),e.render(),setTimeout(()=>{d&&(l.setContent("{gray-fg}[Esc/Q] Close [\u2191\u2193] Scroll [J] JSON [C] cURL{/}"),e.render())},3e3)})}catch(m){n.debug(`JSON copy error: ${m.message}`),l.setContent(`{red-fg}\u2717 Copy failed: ${m.message}{/}`),e.render(),setTimeout(()=>{d&&(l.setContent("{gray-fg}[Esc/Q] Close [\u2191\u2193] Scroll [J] JSON [C] cURL{/}"),e.render())},3e3)}},100))}),e.key(["C","c"],()=>{d&&(n.debug("C/c key pressed - attempting cURL copy"),l.setContent("{black-bg}{yellow-fg} C KEY PRESSED - COPYING CURL... {/}"),e.render(),setTimeout(()=>{try{let m=$o(i);n.debug("Attempting native clipboard copy for cURL"),cn(m).then(()=>{l.setContent("{green-fg}\u2713 cURL command copied to clipboard!{/}"),n.debug("Native clipboard copy succeeded for cURL"),e.render(),setTimeout(()=>{d&&(l.setContent("{gray-fg}[Esc/Q] Close [\u2191\u2193] Scroll [J] JSON [C] cURL{/}"),e.render())},3e3)}).catch(w=>{n.debug(`Native clipboard failed for cURL: ${w.message}`);let h=Vt.default.join(Mt.default.tmpdir(),`sinch-curl-${Date.now()}.sh`);qt.default.writeFileSync(h,m),l.setContent(`{yellow-fg}\u2713 cURL saved to: ${h}{/}`),e.render(),setTimeout(()=>{d&&(l.setContent("{gray-fg}[Esc/Q] Close [\u2191\u2193] Scroll [J] JSON [C] cURL{/}"),e.render())},3e3)})}catch(m){n.debug(`cURL copy error: ${m.message}`),l.setContent(`{red-fg}\u2717 Copy failed: ${m.message}{/}`),e.render(),setTimeout(()=>{d&&(l.setContent("{gray-fg}[Esc/Q] Close [\u2191\u2193] Scroll [J] JSON [C] cURL{/}"),e.render())},3e3)}},100))}),e.key(["1"],()=>{d&&(n.debug("1 key pressed - copying JSON (alternative binding)"),l.setContent("{black-bg}{yellow-fg} 1 KEY - COPYING JSON... {/}"),e.render(),setTimeout(()=>{try{let m=JSON.stringify(i,null,2);cn(m).then(()=>{l.setContent("{green-fg}\u2713 Request JSON copied to clipboard!{/}"),e.render(),setTimeout(()=>{d&&(l.setContent("{gray-fg}[Esc/Q] Close [\u2191\u2193] Scroll [J] JSON [C] cURL{/}"),e.render())},3e3)}).catch(w=>{let h=Vt.default.join(Mt.default.tmpdir(),`sinch-request-${Date.now()}.json`);qt.default.writeFileSync(h,m),l.setContent(`{yellow-fg}\u2713 JSON saved to: ${h}{/}`),e.render(),setTimeout(()=>{d&&(l.setContent("{gray-fg}[Esc/Q] Close [\u2191\u2193] Scroll [J] JSON [C] cURL{/}"),e.render())},3e3)})}catch(m){l.setContent(`{red-fg}\u2717 Copy failed: ${m.message}{/}`),e.render(),setTimeout(()=>{d&&(l.setContent("{gray-fg}[Esc/Q] Close [\u2191\u2193] Scroll [J] JSON [C] cURL{/}"),e.render())},3e3)}},100))}),e.key(["2"],()=>{d&&(n.debug("2 key pressed - copying cURL (alternative binding)"),l.setContent("{black-bg}{yellow-fg} 2 KEY - COPYING CURL... {/}"),e.render(),setTimeout(()=>{try{let m=$o(i);cn(m).then(()=>{l.setContent("{green-fg}\u2713 cURL command copied to clipboard!{/}"),e.render(),setTimeout(()=>{d&&(l.setContent("{gray-fg}[Esc/Q] Close [\u2191\u2193] Scroll [J] JSON [C] cURL{/}"),e.render())},3e3)}).catch(w=>{let h=Vt.default.join(Mt.default.tmpdir(),`sinch-curl-${Date.now()}.sh`);qt.default.writeFileSync(h,m),l.setContent(`{yellow-fg}\u2713 cURL saved to: ${h}{/}`),e.render(),setTimeout(()=>{d&&(l.setContent("{gray-fg}[Esc/Q] Close [\u2191\u2193] Scroll [J] JSON [C] cURL{/}"),e.render())},3e3)})}catch(m){l.setContent(`{red-fg}\u2717 Copy failed: ${m.message}{/}`),e.render(),setTimeout(()=>{d&&(l.setContent("{gray-fg}[Esc/Q] Close [\u2191\u2193] Scroll [J] JSON [C] cURL{/}"),e.render())},3e3)}},100))})}catch(s){n.debug(`Error in showBlessedZoomedRequest: ${s.message}`)}}function ba(i){let e="";return e+=`
63
- `,e+=Sa(i),e+=`
64
- `,e+=Ia(i),e+=`
65
- `,e+=$a(i),e}function Sa(i){let e="",t=process.stdout.columns-6;e+="{bold}{green-fg}\u250C\u2500 REQUEST "+"\u2500".repeat(Math.max(0,t-10))+`\u2510{/}
66
- `;let o=Aa(i);if(o&&(e+=`{green-fg}\u2502{/} {bold}Call ID:{/} {cyan-fg}${o}{/}
65
+ `,await z.default.writeFile(t,o,"utf-8"),n.debug(`Updated .env: SINCH_TUNNEL=${i}`)}}else if(e==="csharp"){let t=ke.default.join(process.cwd(),"appsettings.Development.json");if(await z.default.pathExists(t)){let o=await z.default.readJson(t);o.SinchTunnel=i,await z.default.writeJson(t,o,{spaces:2}),n.debug(`Updated appsettings.Development.json: SinchTunnel=${i}`)}}}async function Fa(i,e,t){let o=e.runtime||"node",r=!1;if(i.tunnel===!0)r=!0;else if(i.tunnel===!1)r=!1,e.tunnel?.preference==="always"&&(f.set("tunnel",{...e.tunnel,preference:"no"},!0),await f.saveProjectConfig());else if(e.tunnel?.preference==="never")r=!1;else if(Ua(e))r=!0;else{let{tunnelChoice:d}=await Ro.default.prompt([{type:"list",name:"tunnelChoice",message:"Enable Sinch tunnel for external access?",choices:[{name:"Yes - Enable tunnel this time",value:"yes"},{name:"No - Local only this time",value:"no"},{name:"Always - Enable tunnel and remember preference",value:"always"},{name:"Never - Don't enable tunnel and remember preference",value:"never"}],default:"no"}]);d==="yes"?r=!0:d==="no"?r=!1:d==="always"?(r=!0,f.set("tunnel",{...e.tunnel,preference:"always"},!0),await f.saveProjectConfig()):d==="never"&&(r=!1,f.set("tunnel",{...e.tunnel,preference:"never"},!0),await f.saveProjectConfig())}await Oa(r,o);let s=ko({PORT:i.port,NODE_ENV:"development",SINCH_FUNCTIONS_LOCAL:"true",SINCH_TUNNEL:r?"true":"false"});e.variables&&Object.entries(e.variables).forEach(([d,u])=>{s[d]=u});try{let d=await f.getApplicationCredentials(e.voiceAppKey);d?(s.SINCH_APPLICATION_KEY=d.applicationKey,s.SINCH_APPLICATION_SECRET=d.applicationSecret,n.debug("\u2705 Injected application credentials for voice operations")):n.debug("\u26A0\uFE0F No application credentials found - voice features may not work")}catch(d){n.debug(`\u26A0\uFE0F Could not load application credentials: ${d.message}`)}n.info("\u{1F680} Starting local server...");let a=null,l=!1;function p(){if(a&&a.kill(),o==="csharp"){let d=["watch","run","--no-launch-profile"];t&&d.push("--project",t),i.port&&d.push("--urls",`http://localhost:${i.port}`),s.ASPNETCORE_ENVIRONMENT="Development",s.ASPNETCORE_URLS=`http://localhost:${i.port}`,a=(0,ii.spawn)("dotnet",d,{env:s,stdio:"inherit",cwd:process.cwd()})}else a=(0,ii.spawn)("npm",["run","dev"],{env:s,stdio:"inherit",cwd:process.cwd(),shell:!0});a.on("spawn",async()=>{if(!l){l=!0,n.newline(),n.success(`\u2705 Server running on http://localhost:${i.port}`),i.debug&&(n.newline(),o==="csharp"?Ma():ja()),n.newline(),n.info("\u{1F4A1} Development commands:"),n.info(` \u2022 Test function: ${Kt.default.cyan(`curl http://localhost:${i.port}`)}`),n.info(` \u2022 View in browser: ${Kt.default.cyan(`http://localhost:${i.port}`)}`),n.info(` \u2022 Stop server: ${Kt.default.gray("Ctrl+C")}`);let d=o==="csharp"?"dotnet watch":"nodemon";n.info(` \u2022 File watching: ${Kt.default.green(`enabled (via ${d})`)}`)}}),a.on("error",d=>{n.error(`Server error: ${d.message}`)}),a.on("exit",(d,u)=>{u!=="SIGTERM"&&u!=="SIGKILL"&&n.error(`Server exited with code ${d}`)})}p(),process.on("SIGINT",()=>{n.newline(),n.info("\u{1F534} Stopping development server..."),a&&a.kill("SIGTERM"),process.exit(0)}),await new Promise(()=>{})}async function ja(){try{let i=await vt("code",".vscode"),e=await vt("cursor",".cursor"),t=await vt("webstorm",".idea");if(i||e){let o=i?"VS Code":"Cursor",r=".vscode";if(n.info(`\u{1F41B} ${o} detected! Debug setup:`),await _a(r))n.info(" 1. \u2705 Created .vscode/launch.json for you");else{let a=ke.default.join(process.cwd(),r,"launch.json");await z.default.pathExists(a)?n.info(" 1. \u2705 Found existing .vscode/launch.json"):n.info(" 1. \u26A0\uFE0F Could not create .vscode/launch.json")}n.info(" 2. \u{1F50D} Press F5 to attach debugger"),n.info(" 3. \u{1F534} Set breakpoints in your function.js"),n.info(" 4. \u{1F4DE} Test your function to hit breakpoints")}else t?(n.info("\u{1F41B} WebStorm detected! Debug setup:"),n.info(" 1. \u{1F50D} Run \u2192 Attach to Node.js/Chrome \u2192 localhost:9229"),n.info(" 2. \u{1F534} Set breakpoints in your function.js")):(n.info("\u{1F41B} Manual debug setup:"),n.info(' \u2022 VS Code/Cursor: Open "Run and Debug" \u2192 "Attach to Node.js Process"'),n.info(' \u2022 Chrome DevTools: Visit chrome://inspect \u2192 Click "inspect"'),n.info(" \u2022 Manual: Connect debugger to ws://localhost:9229"))}catch{n.info("\u{1F41B} Debug instructions:"),n.info(" \u2022 Connect your debugger to ws://localhost:9229"),n.info(" \u2022 Set breakpoints and test your function")}}async function vt(i,e){try{if(i==="code"&&La())return!0;let{spawn:t}=require("child_process"),o=await new Promise(s=>{let a=t(i,["--version"],{stdio:"pipe"});a.on("close",l=>s(l===0)),a.on("error",()=>s(!1))}),r=e?await z.default.pathExists(e):!1;return o||r}catch{return!1}}function La(){return process.env.TERM_PROGRAM==="vscode"||!!process.env.VSCODE_IPC_HOOK||!!process.env.VSCODE_PID}async function _a(i=".vscode"){try{let e=ke.default.join(process.cwd(),i),t=ke.default.join(e,"launch.json");if(await z.default.pathExists(t))return!1;await z.default.ensureDir(e);let o={version:"0.2.0",configurations:[{name:"Attach to Sinch Function",type:"node",request:"attach",port:9229,localRoot:"${workspaceFolder}",remoteRoot:"${workspaceFolder}",skipFiles:["<node_internals>/**","node_modules/**"]}]};return await z.default.writeJson(t,o,{spaces:2}),!!await z.default.pathExists(t)}catch{return!1}}function Ua(i){return i.tunnel?i.tunnel.preference==="always":!1}async function Ma(){try{let i=await vt("code",".vscode"),e=await vt("devenv"),t=await vt("rider",".idea");i?(n.info("\u{1F41B} VS Code detected! Debug setup:"),await qa(".vscode")?n.info(" 1. \u2705 Created .vscode/launch.json for C#"):n.info(" 1. \u2705 Found existing .vscode/launch.json"),n.info(" 2. \u{1F50D} Press F5 to attach debugger"),n.info(" 3. \u{1F534} Set breakpoints in your Function.cs"),n.info(" 4. \u{1F4DE} Test your function to hit breakpoints")):e?(n.info("\u{1F41B} Visual Studio detected! Debug setup:"),n.info(" 1. \u{1F50D} Debug \u2192 Attach to Process \u2192 dotnet.exe"),n.info(" 2. \u{1F534} Set breakpoints in your Function.cs"),n.info(" 3. \u{1F4DE} Test your function to hit breakpoints")):t?(n.info("\u{1F41B} JetBrains Rider detected! Debug setup:"),n.info(" 1. \u{1F50D} Run \u2192 Attach to Process \u2192 dotnet"),n.info(" 2. \u{1F534} Set breakpoints in your Function.cs")):(n.info("\u{1F41B} C# Debug setup:"),n.info(" \u2022 Visual Studio: Debug \u2192 Attach to Process \u2192 dotnet.exe"),n.info(" \u2022 VS Code: Install C# extension, then F5 to debug"),n.info(" \u2022 Rider: Run \u2192 Attach to Process"))}catch{n.info("\u{1F41B} C# Debug instructions:"),n.info(" \u2022 Attach your debugger to the dotnet process"),n.info(" \u2022 Set breakpoints in Function.cs")}}async function qa(i=".vscode"){try{let e=ke.default.join(process.cwd(),i),t=ke.default.join(e,"launch.json");if(await z.default.pathExists(t))return!1;await z.default.ensureDir(e);let o={version:"0.2.0",configurations:[{name:".NET Core Launch (web)",type:"coreclr",request:"launch",preLaunchTask:"build",program:"${workspaceFolder}/bin/Debug/net8.0/Function.dll",args:[],cwd:"${workspaceFolder}",stopAtEntry:!1,serverReadyAction:{action:"openExternally",pattern:"\\bNow listening on:\\s+(https?://\\S+)"},env:{ASPNETCORE_ENVIRONMENT:"Development"},sourceFileMap:{"/Views":"${workspaceFolder}/Views"}},{name:".NET Core Attach",type:"coreclr",request:"attach"}]};await z.default.writeJson(t,o,{spaces:2});let r=ke.default.join(e,"tasks.json");if(!await z.default.pathExists(r)){let s={version:"2.0.0",tasks:[{label:"build",command:"dotnet",type:"process",args:["build","${workspaceFolder}/Function.csproj","/property:GenerateFullPaths=true","/consoleloggerparameters:NoSummary"],problemMatcher:"$msCompile"}]};await z.default.writeJson(r,s,{spaces:2})}return await z.default.pathExists(t)}catch{return!1}}xo.exports=Do});var Uo=N((wd,_o)=>{"use strict";var ue=y(require("chalk")),Fo=require("commander");Q();E();T();R();var jo=new Fo.Command("status");jo.description("Show function status and details").argument("[function-id]","Function ID to check (optional if sinch.json exists)").option("-f, --follow","Watch status changes in real-time").option("--json","Output raw JSON").action(async(i,e)=>{try{await f.load();let t=new J(f.getApiConfig()),o=i;if(!o){if(!f.isInProject())throw new Error("Function ID required. Provide as argument or run from function directory with sinch.json");if(o=f.getProjectConfig()?.functionId,!o)throw new Error("No function ID found in sinch.json. Deploy the function first or provide function ID as argument.")}e.follow?await Va(t,o):await Ja(t,o,e)}catch(t){c.stop(),n.error(`Failed to get function status: ${t.message}`),process.exit(1)}});async function Ja(i,e,t){c.start("\u{1F4E1} Loading function status...");try{let o=await i.getFunction(e),r=await i.getFunctionStatus(e);if(c.stop(),t.json){console.log(JSON.stringify({function:o,deployment:r},null,2));return}let s=o,a=r.status,l=r.error;n.newline(),n.title(`Function Status: ${s.name}`),n.newline(),n.info("\u{1F4CB} Function Details:"),n.info(` ID: ${ue.default.gray(s.id)}`),n.info(` Name: ${ue.default.cyan(s.name)}`),n.info(` Runtime: ${ue.default.yellow(s.runtime)}`),n.info(` Deployment Status: ${Lo(a)}`),s.created&&n.info(` Created: ${new Date(s.created).toLocaleString()}`),s.updated&&n.info(` Updated: ${new Date(s.updated).toLocaleString()}`),s.url&&n.info(` URL: ${ue.default.blue(s.url)}`),a==="Failed"&&l&&(n.newline(),n.error("Deployment Error:"),n.error(` ${l}`)),n.newline(),n.info("\u{1F4A1} Commands:"),n.info(` \u2022 View logs: ${ue.default.cyan(`sinch functions logs ${e}`)}`),n.info(` \u2022 Redeploy: ${ue.default.cyan("sinch functions deploy")}`),n.info(` \u2022 Delete: ${ue.default.cyan(`sinch functions delete ${e}`)}`)}catch(o){throw c.stop(),o}}async function Va(i,e){n.info("\u{1F440} Watching deployment status (press Ctrl+C to stop)..."),n.newline();let t=null,o=setInterval(async()=>{try{let r=await i.getFunctionStatus(e),s=r.status;if(s!==t){let a=new Date().toLocaleTimeString();if(n.info(`[${a}] Status: ${Lo(s)}`),t=s,s==="Running"){n.success("Function deployment is now running!");try{let l=await i.getFunction(e);l.url&&n.info(`URL: ${ue.default.blue(l.url)}`)}catch{}}else s==="Failed"&&(n.error("Function deployment failed!"),r.error&&n.error(`Error: ${r.error}`),clearInterval(o))}}catch(r){n.error(`Error checking status: ${r.message}`)}},3e3);process.on("SIGINT",()=>{clearInterval(o),n.newline(),n.info("Stopped watching function status"),process.exit(0)})}function Lo(i){return{Running:ue.default.green("\u2705 Running"),Failed:ue.default.red("\u274C Failed"),Pending:ue.default.yellow("\u23F3 Pending"),Building:ue.default.blue("\u{1F528} Building")}[i]||ue.default.gray(i)}_o.exports=jo});var zo=N((Id,Wo)=>{"use strict";var nt=y(require("chalk")),Jo=require("commander");Q();E();T();R();var oi=require("child_process"),Ht=y(require("fs")),Wt=y(require("os")),zt=y(require("path")),ri=new Jo.Command("logs");ri.description("View function logs").argument("[function-id]","Function ID to get logs for (optional if sinch.json exists)").option("-f, --follow","Follow log output in real-time").option("-n, --lines <number>","Number of historical lines to show","50").option("--level <level>","Filter by log level (debug, info, warning, error)").option("--search <text>","Search for text in log messages").option("--since <duration>","Show logs since duration (e.g., 1h, 30m, 5s)").action(async(i,e)=>{try{await f.load();let t=new J(f.getApiConfig()),o=i;if(!o){if(!f.isInProject())throw new Error("Function ID required. Provide as argument or run from function directory with sinch.json");let s=f.getProjectConfig();if(!s)throw new Error("No project configuration found");if(o=s.functionId,!o)throw new Error("No function ID found in sinch.json. Deploy the function first or provide function ID as argument.")}c.start("Loading function details...");let r=await t.getFunction(o);c.stop(),n.info(`\u{1F4CB} Logs for function: ${nt.default.cyan(r.name)} (${Ka(r.status)})`),n.newline(),e.follow?await Vo(t,o,r.name,e):await tc(t,o,e)}catch(t){c.stop(),n.error(`Failed to get logs: ${t.message}`),process.exit(1)}});ri.command("stream").description("Stream function logs in real-time").argument("[function-id]","Function ID to stream logs for (optional if sinch.json exists)").option("--level <level>","Filter by log level (debug, info, warning, error)").option("--search <text>","Search for text in log messages").action(async(i,e)=>{try{await f.load();let t=new J(f.getApiConfig()),o=i;if(!o){if(!f.isInProject())throw new Error("Function ID required. Provide as argument or run from function directory with sinch.json");let s=f.getProjectConfig();if(!s)throw new Error("No project configuration found");if(o=s.functionId,!o)throw new Error("No function ID found in sinch.json. Deploy the function first or provide function ID as argument.")}c.start("Connecting to log stream...");let r=await Ba(t,o);c.stop(),await Vo(t,o,r.name,{...e,follow:!0})}catch(t){c.stop(),n.error(`Failed to stream logs: ${t.message}`),process.exit(1)}});async function Ba(i,e){return await i.getFunction(e)}async function Vo(i,e,t,o){let r=i.baseUrl.replace(/\/+$/,""),s=i.projectId,a=`${r}/v1/projects/${s}/functions/${e}/logs/stream`,l=i.credentials,p=[],d=Ko(p,"STREAMING",t),u={Accept:"text/event-stream","Cache-Control":"no-cache"};if(l)try{let w=await l.retrieve();if(w&&w.keyId&&w.keySecret){let h=Buffer.from(`${w.keyId}:${w.keySecret}`).toString("base64");u.Authorization=`Basic ${h}`}}catch(w){n.debug("Failed to add authentication:",w)}let m=new AbortController;try{let w=await fetch(a,{method:"GET",headers:u,signal:m.signal});if(!w.ok)throw new Error(`SSE connection failed: ${w.status} ${w.statusText}`);if(!w.body)throw new Error("Response body is null");Mo(d.statusBar,"CONNECTED",t),d.screen.render();let h=w.body.getReader(),C=new TextDecoder,v="";(async()=>{try{for(;;){let{done:re,value:j}=await h.read();if(re)break;v+=C.decode(j,{stream:!0});let M=v.split(`
66
+ `);v=M.pop()||"";for(let fe of M)if(!fe.startsWith("event:")&&fe.startsWith("data:")){let H=fe.substring(5).trim();if(H)try{let S=JSON.parse(H);S.type==="request"&&S.request&&(p.push(S.request),Bo(d.table,S.request,p),d.table.focus(),d.screen.render())}catch{}}}}catch(re){re.name!=="AbortError"&&(Mo(d.statusBar,"RECONNECTING",t),d.screen.render())}})(),d.screen.key(["q","C-c"],()=>{m.abort(),process.exit(0)}),await new Promise(()=>{})}catch(w){m.abort(),n.error(`\u274C Streaming failed: ${w.message}`),process.exit(1)}}function Ka(i){return{Running:nt.default.green("\u2705 Running"),Failed:nt.default.red("\u274C Failed"),Pending:nt.default.yellow("\u23F3 Pending"),Building:nt.default.blue("\u{1F528} Building")}[i]||nt.default.gray(i)}var it=[];function Bo(i,e,t){let o=new Date(e.startTime),r=o.getFullYear()+"-"+String(o.getMonth()+1).padStart(2,"0")+"-"+String(o.getDate()).padStart(2,"0")+" "+String(o.getHours()).padStart(2,"0")+":"+String(o.getMinutes()).padStart(2,"0")+":"+String(o.getSeconds()).padStart(2,"0"),s=ec(e),a=`${e.executionTimeMs}ms`,l=e.statusCode.toString(),p=process.stdout.columns||120,u=Math.max(30,p-35),m=e.url.length>u?e.url.substring(0,u-2)+"..":e.url;it.push([r,s,a,l,m]),it.length>100&&(it=it.slice(-100),t&&t.length>100&&t.splice(0,t.length-100));let w=[["Time","Callback","Duration","Status","Path"],...it];i.setData(w)}function Ha(i,e,t,o,r){try{let s=require("blessed");n.debug(`Showing request details for ${i.httpMethod} ${i.url}`);let a=s.box({parent:e,top:0,left:0,width:"100%",height:"100%",border:{type:"line"},style:{border:{fg:"cyan"},bg:"black",fg:"white"},scrollable:!0,alwaysScroll:!0,keys:!0,vi:!0,tags:!0,label:" Request Details "}),l=s.box({parent:a,top:1,left:2,width:"100%-4",height:1,content:"{gray-fg}[Esc/Q] Close [\u2191\u2193] Scroll [J/1] JSON [C/2] cURL{/}",tags:!0,style:{bg:"blue",fg:"white"}});s.box({parent:a,top:2,left:2,width:"100%-4",height:1,content:`{bold}{cyan-fg}${i.httpMethod}{/} {blue-fg}${i.url}{/} - {${Za(i.statusCode)}}${i.statusCode}{/} - {yellow-fg}${i.executionTimeMs}ms{/} - {magenta-fg}${i.memoryUsedMB||0}MB{/}`,tags:!0,style:{bg:"black"}});let p=s.box({parent:a,top:4,left:2,width:"100%-4",height:"100%-5",scrollable:!0,alwaysScroll:!0,keys:!0,vi:!0,tags:!0,content:Wa(i)});p.focus(),e.render();let d=!0,u=()=>{d&&(d=!1,a.destroy(),t.focus(),e.render())};e.key(["escape","q"],()=>{d&&u()}),e.key(["up","k"],()=>{d&&(p.scroll(-1),e.render())}),e.key(["down","j"],()=>{d&&(p.scroll(1),e.render())}),e.on("keypress",(m,w)=>{d&&n.debug(`Key pressed: ch="${m}" key=${JSON.stringify(w)}`)}),e.key(["J","j"],()=>{d&&(n.debug("J/j key pressed - attempting JSON copy"),l.setContent("{black-bg}{yellow-fg} J KEY PRESSED - COPYING JSON... {/}"),e.render(),setTimeout(()=>{try{let m=JSON.stringify(i,null,2);n.debug(`JSON content length: ${m.length}`),n.debug("Attempting native clipboard copy"),yn(m).then(()=>{l.setContent("{green-fg}\u2713 Request JSON copied to clipboard!{/}"),n.debug("Native clipboard copy succeeded"),e.render(),setTimeout(()=>{d&&(l.setContent("{gray-fg}[Esc/Q] Close [\u2191\u2193] Scroll [J] JSON [C] cURL{/}"),e.render())},3e3)}).catch(w=>{n.debug(`Native clipboard failed: ${w.message}`);let h=zt.default.join(Wt.default.tmpdir(),`sinch-request-${Date.now()}.json`);Ht.default.writeFileSync(h,m),l.setContent(`{yellow-fg}\u2713 JSON saved to: ${h}{/}`),n.debug(`Saved to temp file: ${h}`),e.render(),setTimeout(()=>{d&&(l.setContent("{gray-fg}[Esc/Q] Close [\u2191\u2193] Scroll [J] JSON [C] cURL{/}"),e.render())},3e3)})}catch(m){n.debug(`JSON copy error: ${m.message}`),l.setContent(`{red-fg}\u2717 Copy failed: ${m.message}{/}`),e.render(),setTimeout(()=>{d&&(l.setContent("{gray-fg}[Esc/Q] Close [\u2191\u2193] Scroll [J] JSON [C] cURL{/}"),e.render())},3e3)}},100))}),e.key(["C","c"],()=>{d&&(n.debug("C/c key pressed - attempting cURL copy"),l.setContent("{black-bg}{yellow-fg} C KEY PRESSED - COPYING CURL... {/}"),e.render(),setTimeout(()=>{try{let m=qo(i);n.debug("Attempting native clipboard copy for cURL"),yn(m).then(()=>{l.setContent("{green-fg}\u2713 cURL command copied to clipboard!{/}"),n.debug("Native clipboard copy succeeded for cURL"),e.render(),setTimeout(()=>{d&&(l.setContent("{gray-fg}[Esc/Q] Close [\u2191\u2193] Scroll [J] JSON [C] cURL{/}"),e.render())},3e3)}).catch(w=>{n.debug(`Native clipboard failed for cURL: ${w.message}`);let h=zt.default.join(Wt.default.tmpdir(),`sinch-curl-${Date.now()}.sh`);Ht.default.writeFileSync(h,m),l.setContent(`{yellow-fg}\u2713 cURL saved to: ${h}{/}`),e.render(),setTimeout(()=>{d&&(l.setContent("{gray-fg}[Esc/Q] Close [\u2191\u2193] Scroll [J] JSON [C] cURL{/}"),e.render())},3e3)})}catch(m){n.debug(`cURL copy error: ${m.message}`),l.setContent(`{red-fg}\u2717 Copy failed: ${m.message}{/}`),e.render(),setTimeout(()=>{d&&(l.setContent("{gray-fg}[Esc/Q] Close [\u2191\u2193] Scroll [J] JSON [C] cURL{/}"),e.render())},3e3)}},100))}),e.key(["1"],()=>{d&&(n.debug("1 key pressed - copying JSON (alternative binding)"),l.setContent("{black-bg}{yellow-fg} 1 KEY - COPYING JSON... {/}"),e.render(),setTimeout(()=>{try{let m=JSON.stringify(i,null,2);yn(m).then(()=>{l.setContent("{green-fg}\u2713 Request JSON copied to clipboard!{/}"),e.render(),setTimeout(()=>{d&&(l.setContent("{gray-fg}[Esc/Q] Close [\u2191\u2193] Scroll [J] JSON [C] cURL{/}"),e.render())},3e3)}).catch(w=>{let h=zt.default.join(Wt.default.tmpdir(),`sinch-request-${Date.now()}.json`);Ht.default.writeFileSync(h,m),l.setContent(`{yellow-fg}\u2713 JSON saved to: ${h}{/}`),e.render(),setTimeout(()=>{d&&(l.setContent("{gray-fg}[Esc/Q] Close [\u2191\u2193] Scroll [J] JSON [C] cURL{/}"),e.render())},3e3)})}catch(m){l.setContent(`{red-fg}\u2717 Copy failed: ${m.message}{/}`),e.render(),setTimeout(()=>{d&&(l.setContent("{gray-fg}[Esc/Q] Close [\u2191\u2193] Scroll [J] JSON [C] cURL{/}"),e.render())},3e3)}},100))}),e.key(["2"],()=>{d&&(n.debug("2 key pressed - copying cURL (alternative binding)"),l.setContent("{black-bg}{yellow-fg} 2 KEY - COPYING CURL... {/}"),e.render(),setTimeout(()=>{try{let m=qo(i);yn(m).then(()=>{l.setContent("{green-fg}\u2713 cURL command copied to clipboard!{/}"),e.render(),setTimeout(()=>{d&&(l.setContent("{gray-fg}[Esc/Q] Close [\u2191\u2193] Scroll [J] JSON [C] cURL{/}"),e.render())},3e3)}).catch(w=>{let h=zt.default.join(Wt.default.tmpdir(),`sinch-curl-${Date.now()}.sh`);Ht.default.writeFileSync(h,m),l.setContent(`{yellow-fg}\u2713 cURL saved to: ${h}{/}`),e.render(),setTimeout(()=>{d&&(l.setContent("{gray-fg}[Esc/Q] Close [\u2191\u2193] Scroll [J] JSON [C] cURL{/}"),e.render())},3e3)})}catch(m){l.setContent(`{red-fg}\u2717 Copy failed: ${m.message}{/}`),e.render(),setTimeout(()=>{d&&(l.setContent("{gray-fg}[Esc/Q] Close [\u2191\u2193] Scroll [J] JSON [C] cURL{/}"),e.render())},3e3)}},100))})}catch(s){n.debug(`Error in showBlessedZoomedRequest: ${s.message}`)}}function Wa(i){let e="";return e+=`
67
+ `,e+=za(i),e+=`
68
+ `,e+=Ga(i),e+=`
69
+ `,e+=Ya(i),e}function za(i){let e="",t=process.stdout.columns-6;e+="{bold}{green-fg}\u250C\u2500 REQUEST "+"\u2500".repeat(Math.max(0,t-10))+`\u2510{/}
70
+ `;let o=Qa(i);if(o&&(e+=`{green-fg}\u2502{/} {bold}Call ID:{/} {cyan-fg}${o}{/}
67
71
  `),i.headers){e+=`{green-fg}\u2502{/} {bold}Headers:{/}
68
- `;try{let r=typeof i.headers=="string"?JSON.parse(i.headers):i.headers;Object.entries(r).forEach(([s,a])=>{let l=` ${s}: ${a}`;e+=$e(l,t-2,"{green-fg}\u2502{/} ")})}catch{e+=$e(` ${i.headers}`,t-2,"{green-fg}\u2502{/} ")}}if(i.requestBody){e+=`{green-fg}\u2502{/} {bold}Body:{/}
72
+ `;try{let r=typeof i.headers=="string"?JSON.parse(i.headers):i.headers;Object.entries(r).forEach(([s,a])=>{let l=` ${s}: ${a}`;e+=Te(l,t-2,"{green-fg}\u2502{/} ")})}catch{e+=Te(` ${i.headers}`,t-2,"{green-fg}\u2502{/} ")}}if(i.requestBody){e+=`{green-fg}\u2502{/} {bold}Body:{/}
69
73
  `;try{let r=JSON.parse(i.requestBody);JSON.stringify(r,null,2).split(`
70
- `).forEach(a=>{e+=$e(a,t-2,"{green-fg}\u2502{/} ")})}catch{e+=$e(i.requestBody,t-2,"{green-fg}\u2502{/} ")}}return e+="{green-fg}\u2514"+"\u2500".repeat(Math.max(0,t))+`\u2518{/}
71
- `,e}function Ia(i){let e="",t=process.stdout.columns-6;if(e+="{bold}{blue-fg}\u250C\u2500 RESPONSE "+"\u2500".repeat(Math.max(0,t-11))+`\u2510{/}
74
+ `).forEach(a=>{e+=Te(a,t-2,"{green-fg}\u2502{/} ")})}catch{e+=Te(i.requestBody,t-2,"{green-fg}\u2502{/} ")}}return e+="{green-fg}\u2514"+"\u2500".repeat(Math.max(0,t))+`\u2518{/}
75
+ `,e}function Ga(i){let e="",t=process.stdout.columns-6;if(e+="{bold}{blue-fg}\u250C\u2500 RESPONSE "+"\u2500".repeat(Math.max(0,t-11))+`\u2510{/}
72
76
  `,i.responseHeaders){e+=`{blue-fg}\u2502{/} {bold}Headers:{/}
73
- `;try{let o=typeof i.responseHeaders=="string"?JSON.parse(i.responseHeaders):i.responseHeaders;Object.entries(o).forEach(([r,s])=>{let a=` ${r}: ${s}`;e+=$e(a,t-2,"{blue-fg}\u2502{/} ")})}catch{e+=$e(` ${i.responseHeaders}`,t-2,"{blue-fg}\u2502{/} ")}}if(i.responseBody){e+=`{blue-fg}\u2502{/} {bold}Body:{/}
77
+ `;try{let o=typeof i.responseHeaders=="string"?JSON.parse(i.responseHeaders):i.responseHeaders;Object.entries(o).forEach(([r,s])=>{let a=` ${r}: ${s}`;e+=Te(a,t-2,"{blue-fg}\u2502{/} ")})}catch{e+=Te(` ${i.responseHeaders}`,t-2,"{blue-fg}\u2502{/} ")}}if(i.responseBody){e+=`{blue-fg}\u2502{/} {bold}Body:{/}
74
78
  `;try{let o=JSON.parse(i.responseBody);JSON.stringify(o,null,2).split(`
75
- `).forEach(s=>{e+=$e(s,t-2,"{blue-fg}\u2502{/} ")})}catch{e+=$e(i.responseBody,t-2,"{blue-fg}\u2502{/} ")}}return i.errorMessage&&(e+=`{blue-fg}\u2502{/} {bold}{red-fg}Error:{/}
76
- `,e+=$e(i.errorMessage,t-2,"{blue-fg}\u2502{/} ")),e+="{blue-fg}\u2514"+"\u2500".repeat(Math.max(0,t))+`\u2518{/}
77
- `,e}function $a(i){let e="",t=process.stdout.columns-6;return e+="{bold}{magenta-fg}\u250C\u2500 CONSOLE LOGS "+"\u2500".repeat(Math.max(0,t-15))+`\u2510{/}
78
- `,i.logs&&i.logs.length>0?i.logs.forEach((o,r)=>{let s=new Date(o.timestamp).toLocaleTimeString(),a=o.level.toUpperCase().padEnd(5),l=Pa(o.level),p=`${s} [${a}] ${o.message}`;e+=$e(p,t-2,"{magenta-fg}\u2502{/} ",l)}):e+=`{magenta-fg}\u2502{/} {gray-fg}No console logs for this request{/}
79
+ `).forEach(s=>{e+=Te(s,t-2,"{blue-fg}\u2502{/} ")})}catch{e+=Te(i.responseBody,t-2,"{blue-fg}\u2502{/} ")}}return i.errorMessage&&(e+=`{blue-fg}\u2502{/} {bold}{red-fg}Error:{/}
80
+ `,e+=Te(i.errorMessage,t-2,"{blue-fg}\u2502{/} ")),e+="{blue-fg}\u2514"+"\u2500".repeat(Math.max(0,t))+`\u2518{/}
81
+ `,e}function Ya(i){let e="",t=process.stdout.columns-6;return e+="{bold}{magenta-fg}\u250C\u2500 CONSOLE LOGS "+"\u2500".repeat(Math.max(0,t-15))+`\u2510{/}
82
+ `,i.logs&&i.logs.length>0?i.logs.forEach((o,r)=>{let s=new Date(o.timestamp).toLocaleTimeString(),a=o.level.toUpperCase().padEnd(5),l=Xa(o.level),p=`${s} [${a}] ${o.message}`;e+=Te(p,t-2,"{magenta-fg}\u2502{/} ",l)}):e+=`{magenta-fg}\u2502{/} {gray-fg}No console logs for this request{/}
79
83
  `,e+="{magenta-fg}\u2514"+"\u2500".repeat(Math.max(0,t))+`\u2518{/}
80
- `,e}function $e(i,e,t,o=""){if(!i)return"";let r="";return i.split(`
84
+ `,e}function Te(i,e,t,o=""){if(!i)return"";let r="";return i.split(`
81
85
  `).forEach(a=>{if(a.length<=e)r+=`${t}${o}${a}{/}
82
86
  `;else{let l=a,p=!0;for(;l.length>e;){let d=e-(p?0:4),u=l.substring(0,d);r+=`${t}${p?"":" "}${o}${u}{/}
83
87
  `,l=l.substring(d),p=!1}l.length>0&&(r+=`${t}${p?"":" "}${o}${l}{/}
84
- `)}}),r}function Pa(i){switch(i.toLowerCase()){case"debug":return"gray-fg";case"info":return"blue-fg";case"warning":return"yellow-fg";case"error":return"red-fg";default:return"white-fg"}}function ka(i){return i>=200&&i<300?"green-fg":i>=300&&i<400?"yellow-fg":i>=400&&i<500?"red-fg":i>=500?"red-fg}{bold":"white-fg"}function Aa(i){try{if(i.requestBody){let e=JSON.parse(i.requestBody);return e.callId||e.callid||e.call_id||null}}catch{}return null}function Ea(i){try{let e="";if(i.requestBody){let t=JSON.parse(i.requestBody);if(t.event)e=t.event.toLowerCase();else{let o=i.url.split("/").filter(r=>r);e=o[o.length-1]||""}return e||""}}catch{}return""}async function xa(i,e,t){try{c.start(`Loading ${t.lines} recent log entries...`);let o={limit:parseInt(t.lines||"50"),level:t.level,search:t.search};if(t.since){let a=Da(t.since);a&&(o.startTime=a.toISOString())}let r=await i.getFunctionLogs(e,o);if(c.stop(),n.debug("Historical API response:",{totalRequests:r.requests?.length||0,firstRequest:r.requests?.[0]||"No requests",responseKeys:Object.keys(r)}),!r.requests||r.requests.length===0){n.info("\u{1F4DD} No logs found"),n.info("\u{1F4A1} Logs will appear here after function receives requests");return}let s=r.requests;n.debug("Historical requests:",{totalRequests:s.length,firstRequest:s[0]||"No requests",requestTimestamps:s.slice(0,3).map(a=>a.startTime)}),await Ta(s,"HISTORICAL","Function")}catch(o){throw c.stop(),o}}function Da(i){if(!i)return null;let e=i.match(/^(\d+)([smhd])$/);if(!e)return null;let t=parseInt(e[1]),o=e[2],r=new Date;switch(o){case"s":return new Date(r.getTime()-t*1e3);case"m":return new Date(r.getTime()-t*60*1e3);case"h":return new Date(r.getTime()-t*60*60*1e3);case"d":return new Date(r.getTime()-t*24*60*60*1e3);default:return null}}async function Ta(i,e,t){let o=Eo(i,e,t);i.forEach(r=>{Ao(o.table,r,i)}),o.screen.render(),await new Promise(()=>{})}function Eo(i,e,t){let o=require("blessed");process.stdout.write("\x1Bc"),nt=[];let r=o.screen({smartCSR:!0,title:`Sinch Functions - ${t} Logs`,fullUnicode:!0}),s=o.box({parent:r,top:0,left:0,width:"100%",height:1,content:xo(e,t),tags:!0,style:{bg:"black"}}),a=o.listtable({parent:r,top:1,left:0,width:"100%",height:"100%-1",border:{type:"line",fg:"blue"},style:{header:{fg:"white",bg:"blue",bold:!0},cell:{fg:"white"},selected:{bg:"blue",fg:"white",bold:!0}},keys:!0,vi:!0,mouse:!0,interactive:!0,label:`${t} Logs (q to quit)`,align:"left",pad:1}),l=["Time","Callback","Duration","Status","Path"];a.setData([l]),a.focus(),r.key(["q","C-c"],()=>{process.exit(0)});let p=()=>{try{let d=a.selected||0,u=d-1;if(u>=0&&u<i.length&&i[u])n.debug(`Opening request details for index ${u}`),va(i[u],r,a,s,t);else{let m=`Selected: ${d}, DataIndex: ${u}, Requests: ${i.length}, TableData: ${nt.length}`;n.debug(`Selection out of bounds: ${m}`)}}catch(d){n.debug(`Error in request selection: ${d.message}`)}};return r.key(["enter"],p),a.on("select",(d,u)=>{p()}),r.on("wheelup",()=>{a.focused&&(a.scroll(-1),r.render())}),r.on("wheeldown",()=>{a.focused&&(a.scroll(1),r.render())}),{screen:r,table:a,statusBar:s}}function xo(i,e){switch(i){case"STREAMING":return"{blue-fg}\u{1F534} STREAMING: "+e+"{/} {gray-fg}| \u2191\u2193/Wheel=scroll | Enter/Click=details | Q=quit{/}";case"CONNECTED":return"{green-fg}\u2705 CONNECTED: "+e+"{/} {gray-fg}| \u2191\u2193/Wheel=scroll | Enter/Click=details | Q=quit{/}";case"RECONNECTING":return"{yellow-fg}\u26A0\uFE0F RECONNECTING: "+e+"{/} {gray-fg}| \u2191\u2193/Wheel=scroll | Enter/Click=details | Q=quit{/}";case"HISTORICAL":return"{cyan-fg}\u{1F4DC} HISTORICAL: "+e+"{/} {gray-fg}| \u2191\u2193/Wheel=scroll | Enter/Click=details | Q=quit{/}";default:return"{gray-fg}"+e+" | \u2191\u2193/Wheel=scroll | Enter/Click=details | Q=quit{/}"}}function Io(i,e,t){i.setContent(xo(e,t))}function cn(i){return new Promise((e,t)=>{let o,r;process.platform==="win32"?(o="clip",r=[]):process.platform==="darwin"?(o="pbcopy",r=[]):(o="xclip",r=["-selection","clipboard"]),n.debug(`Using clipboard command: ${o} with args:`,r);let s=(0,zn.spawn)(o,r,{stdio:["pipe","ignore","pipe"]}),a="";s.stderr.on("data",l=>{a+=l.toString()}),s.on("error",l=>{if(n.debug(`Clipboard process error: ${l.message}`),process.platform==="linux"&&o==="xclip"){n.debug("Trying xsel as fallback");let p=(0,zn.spawn)("xsel",["--clipboard","--input"],{stdio:["pipe","ignore","pipe"]});p.on("error",d=>{t(new Error(`No clipboard utility found: ${l.message} / ${d.message}`))}),p.on("close",d=>{d===0?e():t(new Error(`xsel failed with code ${d}`))}),p.stdin&&(p.stdin.write(i),p.stdin.end());return}t(l)}),s.on("close",l=>{l===0?(n.debug("Clipboard copy successful"),e()):(n.debug(`Clipboard process failed with code ${l}, error: ${a}`),t(new Error(`Clipboard command failed with code ${l}: ${a}`)))}),s.stdin&&(s.stdin.write(i),s.stdin.end())})}function $o(i){let e=process.platform==="win32",t=`curl -X ${i.httpMethod}`,o={};if(i.headers)try{o=typeof i.headers=="string"?JSON.parse(i.headers):i.headers}catch{}let r=i.url;if(r&&!r.startsWith("http")){let s=o.host||o.Host;s&&(r=`${s.includes("localhost")||s.includes("127.0.0.1")?"http":"https"}://${s}${r.startsWith("/")?r:"/"+r}`)}if(t+=` "${r}"`,Object.entries(o).forEach(([s,a])=>{let l=["content-length","connection","user-agent"];i.url.startsWith("http")||l.push("host"),l.includes(s.toLowerCase())||(e?t+=` -H "${s}: ${a}"`:t+=` \\
88
+ `)}}),r}function Xa(i){switch(i.toLowerCase()){case"debug":return"gray-fg";case"info":return"blue-fg";case"warning":return"yellow-fg";case"error":return"red-fg";default:return"white-fg"}}function Za(i){return i>=200&&i<300?"green-fg":i>=300&&i<400?"yellow-fg":i>=400&&i<500?"red-fg":i>=500?"red-fg}{bold":"white-fg"}function Qa(i){try{if(i.requestBody){let e=JSON.parse(i.requestBody);return e.callId||e.callid||e.call_id||null}}catch{}return null}function ec(i){try{let e="";if(i.requestBody){let t=JSON.parse(i.requestBody);if(t.event)e=t.event.toLowerCase();else{let o=i.url.split("/").filter(r=>r);e=o[o.length-1]||""}return e||""}}catch{}return""}async function tc(i,e,t){try{c.start(`Loading ${t.lines} recent log entries...`);let o={limit:parseInt(t.lines||"50"),level:t.level,search:t.search};if(t.since){let a=nc(t.since);a&&(o.startTime=a.toISOString())}let r=await i.getFunctionLogs(e,o);if(c.stop(),n.debug("Historical API response:",{totalRequests:r.requests?.length||0,firstRequest:r.requests?.[0]||"No requests",responseKeys:Object.keys(r)}),!r.requests||r.requests.length===0){n.info("\u{1F4DD} No logs found"),n.info("\u{1F4A1} Logs will appear here after function receives requests");return}let s=r.requests;n.debug("Historical requests:",{totalRequests:s.length,firstRequest:s[0]||"No requests",requestTimestamps:s.slice(0,3).map(a=>a.startTime)}),await ic(s,"HISTORICAL","Function")}catch(o){throw c.stop(),o}}function nc(i){if(!i)return null;let e=i.match(/^(\d+)([smhd])$/);if(!e)return null;let t=parseInt(e[1]),o=e[2],r=new Date;switch(o){case"s":return new Date(r.getTime()-t*1e3);case"m":return new Date(r.getTime()-t*60*1e3);case"h":return new Date(r.getTime()-t*60*60*1e3);case"d":return new Date(r.getTime()-t*24*60*60*1e3);default:return null}}async function ic(i,e,t){let o=Ko(i,e,t);i.forEach(r=>{Bo(o.table,r,i)}),o.screen.render(),await new Promise(()=>{})}function Ko(i,e,t){let o=require("blessed");process.stdout.write("\x1Bc"),it=[];let r=o.screen({smartCSR:!0,title:`Sinch Functions - ${t} Logs`,fullUnicode:!0}),s=o.box({parent:r,top:0,left:0,width:"100%",height:1,content:Ho(e,t),tags:!0,style:{bg:"black"}}),a=o.listtable({parent:r,top:1,left:0,width:"100%",height:"100%-1",border:{type:"line",fg:"blue"},style:{header:{fg:"white",bg:"blue",bold:!0},cell:{fg:"white"},selected:{bg:"blue",fg:"white",bold:!0}},keys:!0,vi:!0,mouse:!0,interactive:!0,label:`${t} Logs (q to quit)`,align:"left",pad:1}),l=["Time","Callback","Duration","Status","Path"];a.setData([l]),a.focus(),r.key(["q","C-c"],()=>{process.exit(0)});let p=()=>{try{let d=a.selected||0,u=d-1;if(u>=0&&u<i.length&&i[u])n.debug(`Opening request details for index ${u}`),Ha(i[u],r,a,s,t);else{let m=`Selected: ${d}, DataIndex: ${u}, Requests: ${i.length}, TableData: ${it.length}`;n.debug(`Selection out of bounds: ${m}`)}}catch(d){n.debug(`Error in request selection: ${d.message}`)}};return r.key(["enter"],p),a.on("select",(d,u)=>{p()}),r.on("wheelup",()=>{a.focused&&(a.scroll(-1),r.render())}),r.on("wheeldown",()=>{a.focused&&(a.scroll(1),r.render())}),{screen:r,table:a,statusBar:s}}function Ho(i,e){switch(i){case"STREAMING":return"{blue-fg}\u{1F534} STREAMING: "+e+"{/} {gray-fg}| \u2191\u2193/Wheel=scroll | Enter/Click=details | Q=quit{/}";case"CONNECTED":return"{green-fg}\u2705 CONNECTED: "+e+"{/} {gray-fg}| \u2191\u2193/Wheel=scroll | Enter/Click=details | Q=quit{/}";case"RECONNECTING":return"{yellow-fg}\u26A0\uFE0F RECONNECTING: "+e+"{/} {gray-fg}| \u2191\u2193/Wheel=scroll | Enter/Click=details | Q=quit{/}";case"HISTORICAL":return"{cyan-fg}\u{1F4DC} HISTORICAL: "+e+"{/} {gray-fg}| \u2191\u2193/Wheel=scroll | Enter/Click=details | Q=quit{/}";default:return"{gray-fg}"+e+" | \u2191\u2193/Wheel=scroll | Enter/Click=details | Q=quit{/}"}}function Mo(i,e,t){i.setContent(Ho(e,t))}function yn(i){return new Promise((e,t)=>{let o,r;process.platform==="win32"?(o="clip",r=[]):process.platform==="darwin"?(o="pbcopy",r=[]):(o="xclip",r=["-selection","clipboard"]),n.debug(`Using clipboard command: ${o} with args:`,r);let s=(0,oi.spawn)(o,r,{stdio:["pipe","ignore","pipe"]}),a="";s.stderr.on("data",l=>{a+=l.toString()}),s.on("error",l=>{if(n.debug(`Clipboard process error: ${l.message}`),process.platform==="linux"&&o==="xclip"){n.debug("Trying xsel as fallback");let p=(0,oi.spawn)("xsel",["--clipboard","--input"],{stdio:["pipe","ignore","pipe"]});p.on("error",d=>{t(new Error(`No clipboard utility found: ${l.message} / ${d.message}`))}),p.on("close",d=>{d===0?e():t(new Error(`xsel failed with code ${d}`))}),p.stdin&&(p.stdin.write(i),p.stdin.end());return}t(l)}),s.on("close",l=>{l===0?(n.debug("Clipboard copy successful"),e()):(n.debug(`Clipboard process failed with code ${l}, error: ${a}`),t(new Error(`Clipboard command failed with code ${l}: ${a}`)))}),s.stdin&&(s.stdin.write(i),s.stdin.end())})}function qo(i){let e=process.platform==="win32",t=`curl -X ${i.httpMethod}`,o={};if(i.headers)try{o=typeof i.headers=="string"?JSON.parse(i.headers):i.headers}catch{}let r=i.url;if(r&&!r.startsWith("http")){let s=o.host||o.Host;s&&(r=`${s.includes("localhost")||s.includes("127.0.0.1")?"http":"https"}://${s}${r.startsWith("/")?r:"/"+r}`)}if(t+=` "${r}"`,Object.entries(o).forEach(([s,a])=>{let l=["content-length","connection","user-agent"];i.url.startsWith("http")||l.push("host"),l.includes(s.toLowerCase())||(e?t+=` -H "${s}: ${a}"`:t+=` \\
85
89
  -H "${s}: ${a}"`)}),i.requestBody&&["POST","PUT","PATCH"].includes(i.httpMethod)){try{let s=JSON.parse(i.requestBody),a=JSON.stringify(s);e?t+=` -d '${a.replace(/'/g,"\\'")}'`:t+=` \\
86
90
  -d '${JSON.stringify(s,null,2)}'`}catch{e?t+=` -d '${i.requestBody.replace(/'/g,"\\'")}'`:t+=` \\
87
91
  -d '${i.requestBody}'`}t.toLowerCase().includes("content-type")||(e?t+=' -H "Content-Type: application/json"':t+=` \\
88
92
  -H "Content-Type: application/json"`)}return e?t+=" -v":t+=` \\
89
- -v`,t}Do.exports=Gn});var Fo=x((Kl,jo)=>{"use strict";var de=y(require("chalk")),Ro=y(require("inquirer")),No=require("commander");X();A();E();D();var Oo=new No.Command("delete");Oo.alias("del").description("Delete a function").argument("<function-id>","Function ID to delete").option("-f, --force","Skip confirmation").action(async(i,e)=>{try{await f.load();let t=new V(f.getApiConfig());c.start("Loading function details...");let o=await t.getFunction(i);if(c.stop(),n.newline(),n.info("\u{1F5D1}\uFE0F Function to delete:"),n.info(` Name: ${de.default.cyan(o.name)}`),n.info(` ID: ${de.default.gray(o.id)}`),n.info(` Runtime: ${de.default.yellow(o.runtime)}`),n.info(` Status: ${Ra(o.status)}`),n.info(` Created: ${new Date(o.createdAt).toLocaleString()}`),o.containerAppUrl&&n.info(` URL: ${de.default.blue(o.containerAppUrl)}`),!e.force){n.newline(),n.warn("\u26A0\uFE0F This action cannot be undone!");let{confirm:r}=await Ro.default.prompt([{type:"confirm",name:"confirm",message:`Are you sure you want to delete function '${o.name}'?`,default:!1}]);if(!r){n.info("Deletion cancelled");return}}c.start("Deleting function..."),await t.deleteFunction(i),c.succeed(`Function '${o.name}' deleted successfully`),f.isInProject()&&f.getProjectConfig()?.functionId===i&&(f.set("functionId",void 0,!0),await f.saveProjectConfig(),n.newline(),n.info("\u{1F4A1} Removed function ID from sinch.json"),n.info(" Deploy again with: sinch functions deploy")),n.newline(),n.info("\u{1F4A1} Next steps:"),n.info(` \u2022 List remaining functions: ${de.default.cyan("sinch functions list")}`),n.info(` \u2022 Deploy new function: ${de.default.cyan("sinch functions deploy")}`)}catch(t){c.stop(),t.message.includes("404")||t.message.includes("not found")?(n.error(`Function '${i}' not found`),n.info("\u{1F4A1} List available functions with:"),n.info(` ${de.default.cyan("sinch functions list")}`)):n.error(`Failed to delete function: ${t.message}`),process.exit(1)}});function Ra(i){return{Running:de.default.green("\u2705 Running"),Failed:de.default.red("\u274C Failed"),Pending:de.default.yellow("\u23F3 Pending"),Building:de.default.blue("\u{1F528} Building")}[i]||de.default.gray(i)}jo.exports=Oo});var Uo=x((Xl,_o)=>{"use strict";var Lo=require("commander"),Yn=y(require("fs-extra")),Xn=y(require("path")),it=y(require("chalk"));A();E();D();Bn();X();var Zn=new Lo.Command("docs");Zn.description("Generate documentation for voice functions (saves to README.md)");Zn.option("-f, --fresh","Force regeneration (skip cache)").option("-u, --update","Update documentation for deployed function via API").action(async i=>{try{await f.load(),i.update?await Oa():await Na(i)}catch(e){c.fail("\u274C Failed to generate documentation"),e.message.includes("No function file found")?n.error("No function file found. Make sure you're in a function directory with function.js, index.js, or handler.js"):e.message.includes("unauthorized")||e.message.includes("401")?n.error("Authentication failed. Run `sinch auth login` first."):e.message.includes("AI service")?n.error("AI documentation service unavailable. Please try again later."):e.message.includes("Function not found")||e.message.includes("404")?n.error("Function not found. Make sure the function is deployed first."):n.error(`Error: ${e.message}`),n.debug("Full error:",e),process.exit(1)}});async function Na(i){c.start("\u{1F916} Generating documentation...");let e=await Vn();c.succeed("\u2705 Documentation generated!"),await Jn(e,"README.md"),await ja()}async function Oa(){let i=Xn.default.basename(process.cwd());c.start("\u{1F4D6} Reading local README.md...");let e=Xn.default.join(process.cwd(),"README.md");if(!await Yn.default.pathExists(e))throw new Error("README.md not found. Run `sinch functions docs` first to generate documentation locally.");if(!(await Yn.default.readFile(e,"utf8")).trim())throw new Error("README.md is empty. Run `sinch functions docs` first to generate documentation.");c.text="\u{1F50D} Finding deployed function...";let s=(await new V(f.getApiConfig()).listFunctions()).find(a=>a.name===i);if(!s)throw new Error(`Function '${i}' not found in project. Make sure it's deployed first.`);c.text="\u{1F4E4} Uploading documentation content...",n.info("Documentation content ready for update"),c.succeed("\u2705 Documentation updated!"),n.newline(),n.success(`\u{1F4C4} Documentation updated for deployed function: ${it.default.cyan(i)}`),n.info(""),n.info("\u2728 Your function documentation has been updated:"),n.info(` \u2022 Function ID: ${it.default.gray(s.id)}`),n.info(` \u2022 Source: ${it.default.gray("Local README.md")}`),n.info(` \u2022 Updated: ${it.default.gray(new Date().toLocaleString())}`),n.info(` \u2022 View in dashboard: ${it.default.cyan("Dashboard \u2192 Functions \u2192 "+i)}`),n.newline(),n.info("\u{1F4A1} The updated documentation is now available in the dashboard!")}async function ja(){n.newline(),n.success(`\u{1F4C4} Documentation updated in: ${it.default.cyan("README.md")}`),n.info(""),n.info("\u2728 Your function documentation is ready:"),n.info(" \u2022 Review and edit the AI-generated content as needed"),n.info(" \u2022 Sinch-themed diagrams will render in markdown viewers"),n.info(" \u2022 File is ready for version control and deployment"),n.newline(),n.info("\u{1F4A1} Popular markdown viewers:"),n.info(" \u2022 VS Code (built-in)"),n.info(" \u2022 GitHub (drag & drop file)"),n.info(" \u2022 Typora, Mark Text, or any markdown app")}_o.exports=Zn});var Bo=x((nd,Jo)=>{"use strict";var Q=y(require("chalk")),Qn=y(require("inquirer")),qo=require("commander"),ve=y(require("fs-extra")),Je=y(require("path")),Mo=y(require("adm-zip"));X();A();E();D();var Vo=new qo.Command("download");Vo.description("Download function source code").argument("[function-id]","Function ID to download (ULID format)").option("-o, --output <dir>","Output directory (default: ./functions/<function-name>)").option("--no-extract","Keep as ZIP file without extracting").option("--non-interactive","Skip interactive selection").option("-f, --force","Overwrite existing directory without prompting").action(async(i,e)=>{try{await f.load();let t=new V(f.getApiConfig()),o=i;if(!o&&!e.nonInteractive){let d=await Fa(t);if(!d){n.info("Download cancelled");return}o=d}o||(n.error("Function ID required. Provide as argument or select interactively"),n.info(`Usage: ${Q.default.cyan("sinch functions download 01HX3KC5V8G3KCNZ8S5Y9ABCDE")}`),n.info(` or: ${Q.default.cyan("sinch functions download")} (interactive selection)`),process.exit(1)),c.start("\u{1F4E1} Fetching function metadata...");let r=await t.getFunction(o);c.succeed("Function metadata loaded");let s=Je.join("functions",r.name),a=e.output||s,l=Je.resolve(a);if(await ve.pathExists(l)){if(!e.force){let{overwrite:d}=await Qn.default.prompt([{type:"confirm",name:"overwrite",message:`Directory '${a}' already exists. Overwrite?`,default:!1}]);if(!d){n.info("Download cancelled");return}}c.start("\u{1F5D1}\uFE0F Removing existing directory..."),await ve.remove(l),c.succeed("Existing directory removed")}c.start("\u{1F4E5} Downloading function source code...");let p=await t.downloadFunction(o);if(c.succeed("Source code downloaded"),e.extract!==!1){c.start("\u{1F4E6} Extracting files..."),await ve.ensureDir(l);let d=new Mo.default(p),u=d.getEntries();d.extractAllTo(l,!0),c.succeed(`\u{1F4E6} Extracted ${u.length} files`);let m=Je.join(l,"sinch-metadata.json"),w={functionId:r.id,name:r.name,runtime:r.runtime,status:r.status,downloadedAt:new Date().toISOString(),url:r.containerAppUrl,configuration:r.configuration};await ve.writeJson(m,w,{spaces:2}),n.newline(),n.success("\u2705 Function downloaded successfully!"),n.newline(),n.info(`\u{1F4C1} Location: ${Q.default.cyan(a)}`),n.info(`\u{1F4CB} Files: ${u.length} files extracted`);let h=Je.join(l,"sinch.json");await ve.pathExists(h)&&n.info("\u{1F527} Config: sinch.json found"),n.newline(),n.info("\u{1F4A1} Next steps:"),n.info(` \u2022 Navigate: ${Q.default.cyan(`cd ${a}`)}`),n.info(` \u2022 Run locally: ${Q.default.cyan("sinch functions dev")}`),n.info(` \u2022 Deploy changes: ${Q.default.cyan("sinch functions deploy")}`)}else{let d=`${r.name}.zip`,u=e.output?Je.resolve(e.output):Je.resolve(d);c.start(`\u{1F4BE} Saving as ${d}...`),await ve.writeFile(u,p),c.succeed("ZIP file saved"),n.newline(),n.success("\u2705 Function downloaded as ZIP!"),n.info(`\u{1F4C1} File: ${Q.default.cyan(u)}`),n.info(`\u{1F4E6} Size: ${(p.length/1024).toFixed(2)} KB`)}}catch(t){c.stop(),t.message.includes("404")||t.message.includes("not found")?(n.error(`Function not found with ID: ${i}`),n.info("\u{1F4A1} List available functions with:"),n.info(` ${Q.default.cyan("sinch functions list")}`),n.info("\u{1F4A1} Or use interactive selection:"),n.info(` ${Q.default.cyan("sinch functions download")}`)):n.error(`Failed to download function: ${t.message}`),process.exit(1)}});async function Fa(i){try{c.start("\u{1F4CB} Loading functions...");let e=await i.listFunctions();if(c.stop(),!e.functions||e.functions.length===0)return n.warn("No functions found to download"),null;let t=e.functions.map(r=>({name:`${Q.default.cyan(r.name.padEnd(20))} ${Q.default.yellow(r.runtime.padEnd(8))} ${La(r.status)}`,value:r.id,short:r.name}));n.newline();let{selectedFunction:o}=await Qn.default.prompt([{type:"list",name:"selectedFunction",message:"Select a function to download:",choices:t,pageSize:15}]);return o}catch(e){throw c.stop(),e}}function La(i){return{Running:Q.default.green("\u2705 Running"),Failed:Q.default.red("\u274C Failed"),Pending:Q.default.yellow("\u23F3 Pending"),Building:Q.default.blue("\u{1F528} Building")}[i]||Q.default.gray(i)}Jo.exports=Vo});var Wo=x((id,Ho)=>{"use strict";var Ko=require("commander"),_a=Bi(),Ua=Gi(),qa=lo(),Ma=yo(),Va=So(),Ja=To(),Ba=Fo(),Ka=Uo(),Ha=Bo(),be=new Ko.Command("functions");be.description("Manage Sinch Functions");be.addCommand(_a);be.addCommand(Ua);be.addCommand(qa);be.addCommand(Ha);be.addCommand(Ma);be.addCommand(Va);be.addCommand(Ja);be.addCommand(Ba);be.addCommand(Ka);Ho.exports=be});var Yo=x((cd,Go)=>{"use strict";var zo=require("commander"),pe=y(require("chalk"));X();A();E();D();var Pe=new zo.Command("templates");Pe.description("Browse and manage function templates");Pe.command("list").alias("ls").description("List available templates").argument("[runtime]","Filter by runtime (node, csharp, python)").option("-c, --category <category>","Filter by category (voice, sms, verification)").option("-d, --detailed","Show detailed information").action(async(i,e)=>{try{await f.load();let t=new V(f.getApiConfig());c.start("Loading templates...");let o;if(i?o=await t.listRuntimeTemplates(i,e.category):o=await t.listAllTemplates(e.category),c.stop(),o.templates.length===0){n.info(`No templates found${i?` for ${i}`:""}${e.category?` in category ${e.category}`:""}`);return}let r=`Available Templates${i?` (${i})`:""}${e.category?` - ${e.category}`:""}`;if(n.title(r),e.detailed)o.templates.forEach((s,a)=>{a>0&&n.newline(),n.log(pe.default.bold.blue(`${s.name}`)),n.log(` Runtime: ${s.runtime}`),n.log(` Category: ${s.category}`),n.log(` Description: ${s.description}`),s.tags&&s.tags.length>0&&n.log(` Tags: ${s.tags.map(l=>pe.default.gray(l)).join(", ")}`),n.log(` Path: ${pe.default.gray(s.path)}`)});else{let s=o.templates.map(a=>[a.name,a.runtime,a.category,a.description.substring(0,50)+(a.description.length>50?"...":""),a.tags?a.tags.slice(0,2).join(", ")+(a.tags.length>2?"...":""):""]);n.table(["Name","Runtime","Category","Description","Tags"],s)}n.newline(),n.info(`Found ${o.templates.length} template${o.templates.length===1?"":"s"}`),n.info('Use "sinch templates show <runtime>/<template>" for details')}catch(t){c.stop(),n.error(`Failed to list templates: ${t.message}`),process.exit(1)}});Pe.command("show").description("Show detailed template information").argument("<template>",'Template name in format "runtime/template-name"').action(async i=>{try{await f.load();let e=new V(f.getApiConfig());if(!i.includes("/"))throw new Error('Template must be in format "runtime/template-name" (e.g., "node/simple-voice-ivr")');let t=i.split("/"),o=t[0],r=t[1];if(!o||!r)throw new Error('Template must be in format "runtime/template-name" (e.g., "node/simple-voice-ivr")');c.start(`Loading template details for ${i}...`);let s=await e.getTemplateDetails(o,r);c.stop(),n.title(`Template: ${s.name}`),n.newline(),n.log(pe.default.bold("Basic Information:")),n.log(` Runtime: ${s.runtime}`),n.log(` Category: ${s.category}`),n.log(` Description: ${s.description}`),s.tags&&s.tags.length>0&&n.log(` Tags: ${s.tags.map(a=>pe.default.blue(a)).join(", ")}`),s.variables&&Object.keys(s.variables).length>0&&(n.newline(),n.log(pe.default.bold("Template Variables:")),Object.entries(s.variables).forEach(([a,l])=>{n.log(` ${a}: ${pe.default.gray(l)}`)})),s.files&&s.files.length>0&&(n.newline(),n.log(pe.default.bold("Files:")),s.files.forEach(a=>{n.log(` ${pe.default.gray("\u2022")} ${a}`)})),s.readmeContent&&(n.newline(),n.log(pe.default.bold("README:")),s.readmeContent.split(`
90
- `).slice(0,10).forEach(l=>{n.log(` ${pe.default.gray(l)}`)}),s.readmeContent.split(`
91
- `).length>10&&n.log(` ${pe.default.gray("... (truncated)")}`)),n.newline(),n.info(`Use "sinch functions init --template ${i}" to create a function from this template`)}catch(e){c.stop(),n.error(`Failed to show template details: ${e.message}`),process.exit(1)}});Pe.command("node").description("List Node.js templates").option("-c, --category <category>","Filter by category").action(async i=>{let e=Pe.commands.find(t=>t.name()==="list");e&&await e.action("node",i)});Pe.command("csharp").description("List C# templates").option("-c, --category <category>","Filter by category").action(async i=>{let e=Pe.commands.find(t=>t.name()==="list");e&&await e.action("csharp",i)});Pe.command("python").description("List Python templates").option("-c, --category <category>","Filter by category").action(async i=>{let e=Pe.commands.find(t=>t.name()==="list");e&&await e.action("python",i)});Go.exports=Pe});var er=x((ud,Qo)=>{"use strict";var Xo=require("commander"),ot=y(require("chalk")),Zo=y(require("inquirer"));A();E();D();var Jt=new Xo.Command("voice");Jt.description("Manage Sinch Voice applications and settings");Jt.command("callback-url").alias("webhook").description("Update webhook callback URL for your Voice application").argument("[url]","New callback URL (if not provided, will prompt)").option("-a, --app-key <key>","Application key (if not provided, will show selection)").action(async(i,e)=>{try{await f.load(),await ei()||(n.error('Not authenticated. Run "sinch auth login" first.'),process.exit(1));let t=await Wa(),o=e.appKey;if(!o){let r=f.getPublicCredentialInfo()?.applicationKey;r||(n.error('No default application key found. Run "sinch auth login" first.'),process.exit(1)),o=r,n.info(`Using default application: ${o}`)}if(!i){let{newUrl:r}=await Zo.default.prompt([{type:"input",name:"newUrl",message:"Enter new callback URL:",validate:s=>{if(!s)return"URL is required";try{return new URL(s),!0}catch{return"Please enter a valid URL"}}}]);i=r}c.start("Updating callback URL...");try{let r=await t.voice.applications.get(o),s={...r,capability:{...r.capability,voice:{...r.capability?.voice,webhooks:{...r.capability?.voice?.webhooks,url:i,method:"POST"}}}};await t.voice.applications.update(o,s),c.succeed("Callback URL updated successfully!"),n.newline(),n.info(`Application: ${r.displayName||o}`),n.info(`New callback URL: ${i}`),n.newline(),n.info("\u{1F389} Your Voice functions will now receive webhooks at this URL"),n.info("\u{1F4A1} Test with: sinch functions dev --tunnel")}catch(r){throw c.fail("Failed to update callback URL"),r}}catch(t){c.stop(),n.error(`Failed to update callback URL: ${t.message}`),process.exit(1)}});Jt.command("get-callbacks").description("Get current callback URLs with full debug output").option("-a, --app-key <key>","Application key (defaults to stored app key)").option("--curl","Show equivalent curl command").action(async i=>{try{await f.load(),await ei()||(n.error('Not authenticated. Run "sinch auth login" first.'),process.exit(1));let e=await f.getApplicationCredentials();e||(n.error('No application credentials found. Run "sinch auth login" first.'),process.exit(1));let t=i.appKey||e.applicationKey;if(n.info("\u{1F50D} Getting callback URLs..."),n.newline(),i.curl){let o=`${e.applicationKey}:${e.applicationSecret}`,r=Buffer.from(o).toString("base64");n.info("\u{1F4CB} CURL Command:"),n.info(ot.default.gray("```bash"));let s=`curl -X GET \\
93
+ -v`,t}Wo.exports=ri});var Qo=N((kd,Zo)=>{"use strict";var ge=y(require("chalk")),Go=y(require("inquirer")),Yo=require("commander");Q();E();T();R();var Xo=new Yo.Command("delete");Xo.alias("del").description("Delete a function").argument("<function-id>","Function ID to delete").option("-f, --force","Skip confirmation").action(async(i,e)=>{try{await f.load();let t=new J(f.getApiConfig());c.start("Loading function details...");let o=await t.getFunction(i);if(c.stop(),n.newline(),n.info("\u{1F5D1}\uFE0F Function to delete:"),n.info(` Name: ${ge.default.cyan(o.name)}`),n.info(` ID: ${ge.default.gray(o.id)}`),n.info(` Runtime: ${ge.default.yellow(o.runtime)}`),n.info(` Status: ${oc(o.status)}`),n.info(` Created: ${new Date(o.createdAt).toLocaleString()}`),o.containerAppUrl&&n.info(` URL: ${ge.default.blue(o.containerAppUrl)}`),!e.force){n.newline(),n.warn("\u26A0\uFE0F This action cannot be undone!");let{confirm:r}=await Go.default.prompt([{type:"confirm",name:"confirm",message:`Are you sure you want to delete function '${o.name}'?`,default:!1}]);if(!r){n.info("Deletion cancelled");return}}c.start("Deleting function..."),await t.deleteFunction(i),c.succeed(`Function '${o.name}' deleted successfully`),f.isInProject()&&f.getProjectConfig()?.functionId===i&&(f.set("functionId",void 0,!0),await f.saveProjectConfig(),n.newline(),n.info("\u{1F4A1} Removed function ID from sinch.json"),n.info(" Deploy again with: sinch functions deploy")),n.newline(),n.info("\u{1F4A1} Next steps:"),n.info(` \u2022 List remaining functions: ${ge.default.cyan("sinch functions list")}`),n.info(` \u2022 Deploy new function: ${ge.default.cyan("sinch functions deploy")}`)}catch(t){c.stop(),t.message.includes("404")||t.message.includes("not found")?(n.error(`Function '${i}' not found`),n.info("\u{1F4A1} List available functions with:"),n.info(` ${ge.default.cyan("sinch functions list")}`)):n.error(`Failed to delete function: ${t.message}`),process.exit(1)}});function oc(i){return{Running:ge.default.green("\u2705 Running"),Failed:ge.default.red("\u274C Failed"),Pending:ge.default.yellow("\u23F3 Pending"),Building:ge.default.blue("\u{1F528} Building")}[i]||ge.default.gray(i)}Zo.exports=Xo});var nr=N((Od,tr)=>{"use strict";var er=require("commander"),si=y(require("fs-extra")),ai=y(require("path")),ot=y(require("chalk"));E();T();R();ei();Q();var ci=new er.Command("docs");ci.description("Generate documentation for voice functions (saves to README.md)");ci.option("-f, --fresh","Force regeneration (skip cache)").option("-u, --update","Update documentation for deployed function via API").action(async i=>{try{await f.load(),i.update?await sc():await rc(i)}catch(e){c.fail("\u274C Failed to generate documentation"),e.message.includes("No function file found")?n.error("No function file found. Make sure you're in a function directory with function.js, index.js, or handler.js"):e.message.includes("unauthorized")||e.message.includes("401")?n.error("Authentication failed. Run `sinch auth login` first."):e.message.includes("AI service")?n.error("AI documentation service unavailable. Please try again later."):e.message.includes("Function not found")||e.message.includes("404")?n.error("Function not found. Make sure the function is deployed first."):n.error(`Error: ${e.message}`),n.debug("Full error:",e),process.exit(1)}});async function rc(i){c.start("\u{1F916} Generating documentation...");let e=await Zn();c.succeed("\u2705 Documentation generated!"),await Qn(e,"README.md"),await ac()}async function sc(){let i=ai.default.basename(process.cwd());c.start("\u{1F4D6} Reading local README.md...");let e=ai.default.join(process.cwd(),"README.md");if(!await si.default.pathExists(e))throw new Error("README.md not found. Run `sinch functions docs` first to generate documentation locally.");if(!(await si.default.readFile(e,"utf8")).trim())throw new Error("README.md is empty. Run `sinch functions docs` first to generate documentation.");c.text="\u{1F50D} Finding deployed function...";let s=(await new J(f.getApiConfig()).listFunctions()).find(a=>a.name===i);if(!s)throw new Error(`Function '${i}' not found in project. Make sure it's deployed first.`);c.text="\u{1F4E4} Uploading documentation content...",n.info("Documentation content ready for update"),c.succeed("\u2705 Documentation updated!"),n.newline(),n.success(`\u{1F4C4} Documentation updated for deployed function: ${ot.default.cyan(i)}`),n.info(""),n.info("\u2728 Your function documentation has been updated:"),n.info(` \u2022 Function ID: ${ot.default.gray(s.id)}`),n.info(` \u2022 Source: ${ot.default.gray("Local README.md")}`),n.info(` \u2022 Updated: ${ot.default.gray(new Date().toLocaleString())}`),n.info(` \u2022 View in dashboard: ${ot.default.cyan("Dashboard \u2192 Functions \u2192 "+i)}`),n.newline(),n.info("\u{1F4A1} The updated documentation is now available in the dashboard!")}async function ac(){n.newline(),n.success(`\u{1F4C4} Documentation updated in: ${ot.default.cyan("README.md")}`),n.info(""),n.info("\u2728 Your function documentation is ready:"),n.info(" \u2022 Review and edit the AI-generated content as needed"),n.info(" \u2022 Sinch-themed diagrams will render in markdown viewers"),n.info(" \u2022 File is ready for version control and deployment"),n.newline(),n.info("\u{1F4A1} Popular markdown viewers:"),n.info(" \u2022 VS Code (built-in)"),n.info(" \u2022 GitHub (drag & drop file)"),n.info(" \u2022 Typora, Mark Text, or any markdown app")}tr.exports=ci});var ar=N((Ud,sr)=>{"use strict";var te=y(require("chalk")),li=y(require("inquirer")),ir=require("commander"),$e=y(require("fs-extra")),He=y(require("path")),or=y(require("adm-zip"));Q();E();T();R();var rr=new ir.Command("download");rr.description("Download function source code").argument("[function-id]","Function ID to download (ULID format)").option("-o, --output <dir>","Output directory (default: ./functions/<function-name>)").option("--no-extract","Keep as ZIP file without extracting").option("--non-interactive","Skip interactive selection").option("-f, --force","Overwrite existing directory without prompting").action(async(i,e)=>{try{await f.load();let t=new J(f.getApiConfig()),o=i;if(!o&&!e.nonInteractive){let d=await cc(t);if(!d){n.info("Download cancelled");return}o=d}o||(n.error("Function ID required. Provide as argument or select interactively"),n.info(`Usage: ${te.default.cyan("sinch functions download 01HX3KC5V8G3KCNZ8S5Y9ABCDE")}`),n.info(` or: ${te.default.cyan("sinch functions download")} (interactive selection)`),process.exit(1)),c.start("\u{1F4E1} Fetching function metadata...");let r=await t.getFunction(o);c.succeed("Function metadata loaded");let s=He.join("functions",r.name),a=e.output||s,l=He.resolve(a);if(await $e.pathExists(l)){if(!e.force){let{overwrite:d}=await li.default.prompt([{type:"confirm",name:"overwrite",message:`Directory '${a}' already exists. Overwrite?`,default:!1}]);if(!d){n.info("Download cancelled");return}}c.start("\u{1F5D1}\uFE0F Removing existing directory..."),await $e.remove(l),c.succeed("Existing directory removed")}c.start("\u{1F4E5} Downloading function source code...");let p=await t.downloadFunction(o);if(c.succeed("Source code downloaded"),e.extract!==!1){c.start("\u{1F4E6} Extracting files..."),await $e.ensureDir(l);let d=new or.default(p),u=d.getEntries();d.extractAllTo(l,!0),c.succeed(`\u{1F4E6} Extracted ${u.length} files`);let m=He.join(l,"sinch-metadata.json"),w={functionId:r.id,name:r.name,runtime:r.runtime,status:r.status,downloadedAt:new Date().toISOString(),url:r.containerAppUrl,configuration:r.configuration};await $e.writeJson(m,w,{spaces:2}),n.newline(),n.success("\u2705 Function downloaded successfully!"),n.newline(),n.info(`\u{1F4C1} Location: ${te.default.cyan(a)}`),n.info(`\u{1F4CB} Files: ${u.length} files extracted`);let h=He.join(l,"sinch.json");await $e.pathExists(h)&&n.info("\u{1F527} Config: sinch.json found"),n.newline(),n.info("\u{1F4A1} Next steps:"),n.info(` \u2022 Navigate: ${te.default.cyan(`cd ${a}`)}`),n.info(` \u2022 Run locally: ${te.default.cyan("sinch functions dev")}`),n.info(` \u2022 Deploy changes: ${te.default.cyan("sinch functions deploy")}`)}else{let d=`${r.name}.zip`,u=e.output?He.resolve(e.output):He.resolve(d);c.start(`\u{1F4BE} Saving as ${d}...`),await $e.writeFile(u,p),c.succeed("ZIP file saved"),n.newline(),n.success("\u2705 Function downloaded as ZIP!"),n.info(`\u{1F4C1} File: ${te.default.cyan(u)}`),n.info(`\u{1F4E6} Size: ${(p.length/1024).toFixed(2)} KB`)}}catch(t){c.stop(),t.message.includes("404")||t.message.includes("not found")?(n.error(`Function not found with ID: ${i}`),n.info("\u{1F4A1} List available functions with:"),n.info(` ${te.default.cyan("sinch functions list")}`),n.info("\u{1F4A1} Or use interactive selection:"),n.info(` ${te.default.cyan("sinch functions download")}`)):n.error(`Failed to download function: ${t.message}`),process.exit(1)}});async function cc(i){try{c.start("\u{1F4CB} Loading functions...");let e=await i.listFunctions();if(c.stop(),!e.functions||e.functions.length===0)return n.warn("No functions found to download"),null;let t=e.functions.map(r=>({name:`${te.default.cyan(r.name.padEnd(20))} ${te.default.yellow(r.runtime.padEnd(8))} ${lc(r.status)}`,value:r.id,short:r.name}));n.newline();let{selectedFunction:o}=await li.default.prompt([{type:"list",name:"selectedFunction",message:"Select a function to download:",choices:t,pageSize:15}]);return o}catch(e){throw c.stop(),e}}function lc(i){return{Running:te.default.green("\u2705 Running"),Failed:te.default.red("\u274C Failed"),Pending:te.default.yellow("\u23F3 Pending"),Building:te.default.blue("\u{1F528} Building")}[i]||te.default.gray(i)}sr.exports=rr});var dr=N((Md,lr)=>{"use strict";var cr=require("commander"),dc=ao(),pc=fo(),uc=Eo(),fc=Oo(),mc=Uo(),gc=zo(),hc=Qo(),yc=nr(),wc=ar(),Pe=new cr.Command("functions");Pe.description("Manage Sinch Functions");Pe.addCommand(dc);Pe.addCommand(pc);Pe.addCommand(uc);Pe.addCommand(wc);Pe.addCommand(fc);Pe.addCommand(mc);Pe.addCommand(gc);Pe.addCommand(hc);Pe.addCommand(yc);lr.exports=Pe});var fr=N((Kd,ur)=>{"use strict";var pr=require("commander"),he=y(require("chalk"));Q();E();T();R();var Ne=new pr.Command("templates");Ne.description("Browse and manage function templates");Ne.command("list").alias("ls").description("List available templates").argument("[runtime]","Filter by runtime (node, csharp, python)").option("-c, --category <category>","Filter by category (voice, sms, verification)").option("-d, --detailed","Show detailed information").action(async(i,e)=>{try{await f.load();let t=new J(f.getApiConfig());c.start("Loading templates...");let o;if(i?o=await t.listRuntimeTemplates(i,e.category):o=await t.listAllTemplates(e.category),c.stop(),o.templates.length===0){n.info(`No templates found${i?` for ${i}`:""}${e.category?` in category ${e.category}`:""}`);return}let r=`Available Templates${i?` (${i})`:""}${e.category?` - ${e.category}`:""}`;if(n.title(r),e.detailed)o.templates.forEach((s,a)=>{a>0&&n.newline(),n.log(he.default.bold.blue(`${s.name}`)),n.log(` Runtime: ${s.runtime}`),n.log(` Category: ${s.category}`),n.log(` Description: ${s.description}`),s.tags&&s.tags.length>0&&n.log(` Tags: ${s.tags.map(l=>he.default.gray(l)).join(", ")}`),n.log(` Path: ${he.default.gray(s.path)}`)});else{let s=o.templates.map(a=>[a.name,a.runtime,a.category,a.description.substring(0,50)+(a.description.length>50?"...":""),a.tags?a.tags.slice(0,2).join(", ")+(a.tags.length>2?"...":""):""]);n.table(["Name","Runtime","Category","Description","Tags"],s)}n.newline(),n.info(`Found ${o.templates.length} template${o.templates.length===1?"":"s"}`),n.info('Use "sinch templates show <runtime>/<template>" for details')}catch(t){c.stop(),n.error(`Failed to list templates: ${t.message}`),process.exit(1)}});Ne.command("show").description("Show detailed template information").argument("<template>",'Template name in format "runtime/template-name"').action(async i=>{try{await f.load();let e=new J(f.getApiConfig());if(!i.includes("/"))throw new Error('Template must be in format "runtime/template-name" (e.g., "node/simple-voice-ivr")');let t=i.split("/"),o=t[0],r=t[1];if(!o||!r)throw new Error('Template must be in format "runtime/template-name" (e.g., "node/simple-voice-ivr")');c.start(`Loading template details for ${i}...`);let s=await e.getTemplateDetails(o,r);c.stop(),n.title(`Template: ${s.name}`),n.newline(),n.log(he.default.bold("Basic Information:")),n.log(` Runtime: ${s.runtime}`),n.log(` Category: ${s.category}`),n.log(` Description: ${s.description}`),s.tags&&s.tags.length>0&&n.log(` Tags: ${s.tags.map(a=>he.default.blue(a)).join(", ")}`),s.variables&&Object.keys(s.variables).length>0&&(n.newline(),n.log(he.default.bold("Template Variables:")),Object.entries(s.variables).forEach(([a,l])=>{n.log(` ${a}: ${he.default.gray(l)}`)})),s.files&&s.files.length>0&&(n.newline(),n.log(he.default.bold("Files:")),s.files.forEach(a=>{n.log(` ${he.default.gray("\u2022")} ${a}`)})),s.readmeContent&&(n.newline(),n.log(he.default.bold("README:")),s.readmeContent.split(`
94
+ `).slice(0,10).forEach(l=>{n.log(` ${he.default.gray(l)}`)}),s.readmeContent.split(`
95
+ `).length>10&&n.log(` ${he.default.gray("... (truncated)")}`)),n.newline(),n.info(`Use "sinch functions init --template ${i}" to create a function from this template`)}catch(e){c.stop(),n.error(`Failed to show template details: ${e.message}`),process.exit(1)}});Ne.command("node").description("List Node.js templates").option("-c, --category <category>","Filter by category").action(async i=>{let e=Ne.commands.find(t=>t.name()==="list");e&&await e.action("node",i)});Ne.command("csharp").description("List C# templates").option("-c, --category <category>","Filter by category").action(async i=>{let e=Ne.commands.find(t=>t.name()==="list");e&&await e.action("csharp",i)});Ne.command("python").description("List Python templates").option("-c, --category <category>","Filter by category").action(async i=>{let e=Ne.commands.find(t=>t.name()==="list");e&&await e.action("python",i)});ur.exports=Ne});var yr=N((Gd,hr)=>{"use strict";var mr=require("commander"),rt=y(require("chalk")),gr=y(require("inquirer"));E();T();R();var Gt=new mr.Command("voice");Gt.description("Manage Sinch Voice applications and settings");Gt.command("callback-url").alias("webhook").description("Update webhook callback URL for your Voice application").argument("[url]","New callback URL (if not provided, will prompt)").option("-a, --app-key <key>","Application key (if not provided, will show selection)").action(async(i,e)=>{try{await f.load(),await di()||(n.error('Not authenticated. Run "sinch auth login" first.'),process.exit(1));let t=await Cc(),o=e.appKey;if(!o){let r=f.getPublicCredentialInfo()?.applicationKey;r||(n.error('No default application key found. Run "sinch auth login" first.'),process.exit(1)),o=r,n.info(`Using default application: ${o}`)}if(!i){let{newUrl:r}=await gr.default.prompt([{type:"input",name:"newUrl",message:"Enter new callback URL:",validate:s=>{if(!s)return"URL is required";try{return new URL(s),!0}catch{return"Please enter a valid URL"}}}]);i=r}c.start("Updating callback URL...");try{let r=await t.voice.applications.get(o),s={...r,capability:{...r.capability,voice:{...r.capability?.voice,webhooks:{...r.capability?.voice?.webhooks,url:i,method:"POST"}}}};await t.voice.applications.update(o,s),c.succeed("Callback URL updated successfully!"),n.newline(),n.info(`Application: ${r.displayName||o}`),n.info(`New callback URL: ${i}`),n.newline(),n.info("\u{1F389} Your Voice functions will now receive webhooks at this URL"),n.info("\u{1F4A1} Test with: sinch functions dev --tunnel")}catch(r){throw c.fail("Failed to update callback URL"),r}}catch(t){c.stop(),n.error(`Failed to update callback URL: ${t.message}`),process.exit(1)}});Gt.command("get-callbacks").description("Get current callback URLs with full debug output").option("-a, --app-key <key>","Application key (defaults to stored app key)").option("--curl","Show equivalent curl command").action(async i=>{try{await f.load(),await di()||(n.error('Not authenticated. Run "sinch auth login" first.'),process.exit(1));let e=await f.getApplicationCredentials();e||(n.error('No application credentials found. Run "sinch auth login" first.'),process.exit(1));let t=i.appKey||e.applicationKey;if(n.info("\u{1F50D} Getting callback URLs..."),n.newline(),i.curl){let o=`${e.applicationKey}:${e.applicationSecret}`,r=Buffer.from(o).toString("base64");n.info("\u{1F4CB} CURL Command:"),n.info(rt.default.gray("```bash"));let s=`curl -X GET \\
92
96
  https://calling.api.sinch.com/calling/v1/applications/${t}/callbacks/urls \\
93
- -H "Authorization: Basic ${r}"`;n.info(ot.default.cyan(s)),n.info(ot.default.gray("```")),n.newline()}try{let{SinchClient:o}=require("@sinch/sdk-core"),r=new o({applicationKey:e.applicationKey,applicationSecret:e.applicationSecret});c.start("Fetching callback URLs...");let s=await r.voice.applications.getCallbackURLs({applicationkey:t});c.succeed("Callback URLs retrieved"),n.newline(),n.info("\u{1F4E5} Current Callback Configuration:"),n.info(` currentCallbacks.primary: ${s?.primary||"undefined"}`),n.info(` currentCallbacks.fallback: ${s?.fallback||"undefined"}`)}catch(o){c.fail("Failed to get callback URLs"),n.error(`Error: ${o.message}`),n.newline(),n.info("Full error details:"),n.info(JSON.stringify(o,null,2))}}catch(e){n.error(`Command failed: ${e.message}`),process.exit(1)}});Jt.command("set-callback").description("Update callback URL with debug output showing exact API call").argument("<url>","Callback URL to set").option("-a, --app-key <key>","Application key (defaults to stored app key)").option("--primary-only","Only set primary URL (no fallback)").option("--debug","Show full curl command and response").action(async(i,e)=>{try{await f.load(),await ei()||(n.error('Not authenticated. Run "sinch auth login" first.'),process.exit(1));let t=await f.getApplicationCredentials();t||(n.error('No application credentials found. Run "sinch auth login" first.'),process.exit(1));let o=e.appKey||t.applicationKey;n.info("\u{1F527} Updating callback URL with debug output..."),n.newline();let r=e.primaryOnly?{url:{primary:i}}:{url:{primary:i,fallback:i}},s=`${t.applicationKey}:${t.applicationSecret}`,a=Buffer.from(s).toString("base64");n.info("\u{1F4CB} CURL Command:"),n.info(ot.default.gray("```bash"));let l=`curl -X POST \\
97
+ -H "Authorization: Basic ${r}"`;n.info(rt.default.cyan(s)),n.info(rt.default.gray("```")),n.newline()}try{let{SinchClient:o}=require("@sinch/sdk-core"),r=new o({applicationKey:e.applicationKey,applicationSecret:e.applicationSecret});c.start("Fetching callback URLs...");let s=await r.voice.applications.getCallbackURLs({applicationkey:t});c.succeed("Callback URLs retrieved"),n.newline(),n.info("\u{1F4E5} Current Callback Configuration:"),n.info(` currentCallbacks.primary: ${s?.primary||"undefined"}`),n.info(` currentCallbacks.fallback: ${s?.fallback||"undefined"}`)}catch(o){c.fail("Failed to get callback URLs"),n.error(`Error: ${o.message}`),n.newline(),n.info("Full error details:"),n.info(JSON.stringify(o,null,2))}}catch(e){n.error(`Command failed: ${e.message}`),process.exit(1)}});Gt.command("set-callback").description("Update callback URL with debug output showing exact API call").argument("<url>","Callback URL to set").option("-a, --app-key <key>","Application key (defaults to stored app key)").option("--primary-only","Only set primary URL (no fallback)").option("--debug","Show full curl command and response").action(async(i,e)=>{try{await f.load(),await di()||(n.error('Not authenticated. Run "sinch auth login" first.'),process.exit(1));let t=await f.getApplicationCredentials();t||(n.error('No application credentials found. Run "sinch auth login" first.'),process.exit(1));let o=e.appKey||t.applicationKey;n.info("\u{1F527} Updating callback URL with debug output..."),n.newline();let r=e.primaryOnly?{url:{primary:i}}:{url:{primary:i,fallback:i}},s=`${t.applicationKey}:${t.applicationSecret}`,a=Buffer.from(s).toString("base64");n.info("\u{1F4CB} CURL Command:"),n.info(rt.default.gray("```bash"));let l=`curl -X POST \\
94
98
  https://calling.api.sinch.com/calling/v1/applications/${o}/callbacks/urls \\
95
99
  -H "Authorization: Basic ${a}" \\
96
100
  -H "Content-Type: application/json" \\
97
- -d '${JSON.stringify(r,null,2)}'`;n.info(ot.default.cyan(l)),n.info(ot.default.gray("```")),n.newline();try{let{SinchClient:p}=require("@sinch/sdk-core"),d=new p({applicationKey:t.applicationKey,applicationSecret:t.applicationSecret});n.info("\u{1F4E4} Request Body:"),n.info(JSON.stringify(r,null,2)),n.newline(),c.start("Sending update request..."),await d.voice.applications.updateCallbackURLs({applicationkey:o,updateCallbacksRequestBody:r}),c.succeed("Update request sent"),c.start("Waiting for changes to propagate..."),await new Promise(w=>setTimeout(w,5e3)),c.start("Verifying update...");let u=await d.voice.applications.getCallbackURLs({applicationkey:o});c.succeed("Verification complete"),n.newline(),n.info("\u{1F4E5} Current Callback URLs:"),n.info(JSON.stringify(u,null,2));let m=u?.url||u?.primary||u?.urls?.primary;m===i?(n.newline(),n.success("\u2705 Callback URL successfully updated!")):(n.newline(),n.warn("\u26A0\uFE0F Callback URL may not have been updated correctly"),n.info("Expected: "+i),n.info("Actual: "+(typeof m=="object"?JSON.stringify(m):m||"not found")),n.newline(),n.info("\u{1F50D} Debug - Response structure:"),n.info(" typeof currentCallbacks: "+typeof u),n.info(" currentCallbacks.url: "+(u?.url||"undefined")),n.info(" currentCallbacks.primary: "+(u?.primary||"undefined")),n.info(" currentCallbacks.urls?.primary: "+(u?.urls?.primary||"undefined")))}catch(p){c.fail("Update failed"),n.error(`Error: ${p.message}`),e.debug&&(n.newline(),n.info("Full error details:"),n.info(JSON.stringify(p,null,2)))}}catch(t){n.error(`Command failed: ${t.message}`),process.exit(1)}});async function ei(){return await f.hasCredentials()}async function Wa(){return await f.createSinchClient()}Qo.exports=Jt});var ir=x((md,nr)=>{"use strict";var tr=require("commander"),Re=y(require("keytar")),z=y(require("chalk"));E();var ti=y(require("inquirer")),Be="sinch-functions-cli",rt=new tr.Command("secrets");rt.description("Manage secure secrets in OS keychain").addHelpText("after",`
101
+ -d '${JSON.stringify(r,null,2)}'`;n.info(rt.default.cyan(l)),n.info(rt.default.gray("```")),n.newline();try{let{SinchClient:p}=require("@sinch/sdk-core"),d=new p({applicationKey:t.applicationKey,applicationSecret:t.applicationSecret});n.info("\u{1F4E4} Request Body:"),n.info(JSON.stringify(r,null,2)),n.newline(),c.start("Sending update request..."),await d.voice.applications.updateCallbackURLs({applicationkey:o,updateCallbacksRequestBody:r}),c.succeed("Update request sent"),c.start("Waiting for changes to propagate..."),await new Promise(w=>setTimeout(w,5e3)),c.start("Verifying update...");let u=await d.voice.applications.getCallbackURLs({applicationkey:o});c.succeed("Verification complete"),n.newline(),n.info("\u{1F4E5} Current Callback URLs:"),n.info(JSON.stringify(u,null,2));let m=u?.url||u?.primary||u?.urls?.primary;m===i?(n.newline(),n.success("\u2705 Callback URL successfully updated!")):(n.newline(),n.warn("\u26A0\uFE0F Callback URL may not have been updated correctly"),n.info("Expected: "+i),n.info("Actual: "+(typeof m=="object"?JSON.stringify(m):m||"not found")),n.newline(),n.info("\u{1F50D} Debug - Response structure:"),n.info(" typeof currentCallbacks: "+typeof u),n.info(" currentCallbacks.url: "+(u?.url||"undefined")),n.info(" currentCallbacks.primary: "+(u?.primary||"undefined")),n.info(" currentCallbacks.urls?.primary: "+(u?.urls?.primary||"undefined")))}catch(p){c.fail("Update failed"),n.error(`Error: ${p.message}`),e.debug&&(n.newline(),n.info("Full error details:"),n.info(JSON.stringify(p,null,2)))}}catch(t){n.error(`Command failed: ${t.message}`),process.exit(1)}});async function di(){return await f.hasCredentials()}async function Cc(){return await f.createSinchClient()}hr.exports=Gt});var vr=N((Xd,Cr)=>{"use strict";var wr=require("commander"),Le=y(require("keytar")),Y=y(require("chalk"));T();var pi=y(require("inquirer")),We="sinch-functions-cli",st=new wr.Command("secrets");st.description("Manage secure secrets in OS keychain").addHelpText("after",`
98
102
  Examples:
99
- ${z.default.cyan("sinch secrets list")} List all custom secrets
100
- ${z.default.cyan("sinch secrets add API_KEY abc123")} Add or update a secret
101
- ${z.default.cyan("sinch secrets get API_KEY")} Get a specific secret value
102
- ${z.default.cyan("sinch secrets delete API_KEY")} Remove a secret
103
+ ${Y.default.cyan("sinch secrets list")} List all custom secrets
104
+ ${Y.default.cyan("sinch secrets add API_KEY abc123")} Add or update a secret
105
+ ${Y.default.cyan("sinch secrets get API_KEY")} Get a specific secret value
106
+ ${Y.default.cyan("sinch secrets delete API_KEY")} Remove a secret
103
107
 
104
108
  Note: Secrets are stored securely in your OS keychain:
105
109
  - Windows: Credential Manager
106
110
  - macOS: Keychain
107
111
  - Linux: Secret Service API
108
- `);rt.command("list").description("List all custom secrets (keys only)").action(async()=>{try{let e=(await Re.default.findCredentials(Be)).filter(t=>t.account&&t.account.startsWith("custom-")).map(t=>t.account.replace("custom-",""));if(e.length===0){n.info("No custom secrets found"),n.info(""),n.info("\u{1F4A1} Add a secret with:"),n.info(` ${z.default.cyan("sinch secrets add <KEY> <VALUE>")}`);return}n.info(z.default.bold("Custom Secrets:")),n.info(""),e.forEach(t=>{n.info(` \u{1F510} ${z.default.cyan(t)}`)}),n.info(""),n.info(`Total: ${e.length} secret(s)`)}catch(i){n.error("Failed to list secrets:",i.message),process.exit(1)}});rt.command("add <key> <value>").description("Add or update a secret in OS keychain").action(async(i,e)=>{try{i.match(/^[A-Z0-9_]+$/)||(n.error("Secret key must be uppercase letters, numbers, and underscores only"),n.info(`Example: ${z.default.cyan("API_KEY")}, ${z.default.cyan("DATABASE_PASSWORD")}`),process.exit(1));let t=`custom-${i}`,r=await Re.default.getPassword(Be,t)!==null;await Re.default.setPassword(Be,t,e),r?n.success(`\u2705 Updated secret: ${z.default.cyan(i)}`):n.success(`\u2705 Added secret: ${z.default.cyan(i)}`),n.info(""),n.info("\u{1F4DD} To use in your function:"),n.info(` 1. Add ${z.default.cyan(i+"=")} to your .env file (leave value empty)`),n.info(` 2. Access via ${z.default.cyan("process.env."+i)} in your code`),n.info(" 3. The secret will be loaded automatically from OS keychain")}catch(t){n.error("Failed to add secret:",t.message),process.exit(1)}});rt.command("get <key>").description("Get a specific secret value").option("--show","Show the actual value (be careful!)").action(async(i,e)=>{try{let t=`custom-${i}`,o=await Re.default.getPassword(Be,t);o||(n.error(`Secret not found: ${z.default.cyan(i)}`),n.info(""),n.info("\u{1F4A1} Available secrets:"),n.info(` Run ${z.default.cyan("sinch secrets list")} to see all secrets`),process.exit(1)),n.info(`Secret: ${z.default.cyan(i)}`),e.show?(n.warn("\u26A0\uFE0F Showing secret value - be careful not to expose it!"),n.info(`Value: ${o}`)):(n.info(`Value: ${z.default.gray("[HIDDEN - use --show to reveal]")}`),n.info(`Length: ${o.length} characters`))}catch(t){n.error("Failed to get secret:",t.message),process.exit(1)}});rt.command("delete <key>").alias("remove").alias("rm").description("Remove a secret from OS keychain").option("-f, --force","Skip confirmation").action(async(i,e)=>{try{let t=`custom-${i}`;if(await Re.default.getPassword(Be,t)||(n.error(`Secret not found: ${z.default.cyan(i)}`),process.exit(1)),!e.force&&!(await ti.default.prompt([{type:"confirm",name:"confirm",message:`Are you sure you want to delete secret '${i}'?`,default:!1}])).confirm){n.info("Cancelled");return}await Re.default.deletePassword(Be,t)?n.success(`\u2705 Deleted secret: ${z.default.cyan(i)}`):(n.error("Failed to delete secret"),process.exit(1))}catch(t){n.error("Failed to delete secret:",t.message),process.exit(1)}});rt.command("clear").description("Remove ALL custom secrets (use with caution!)").option("-f, --force","Skip confirmation").action(async i=>{try{let t=(await Re.default.findCredentials(Be)).filter(r=>r.account&&r.account.startsWith("custom-"));if(t.length===0){n.info("No custom secrets to clear");return}if(!i.force&&(n.warn(`\u26A0\uFE0F This will delete ${t.length} custom secret(s)`),!(await ti.default.prompt([{type:"confirm",name:"confirm",message:"Are you sure you want to delete ALL custom secrets?",default:!1}])).confirm)){n.info("Cancelled");return}let o=0;for(let r of t)await Re.default.deletePassword(Be,r.account)&&o++;n.success(`\u2705 Deleted ${o} custom secret(s)`)}catch(e){n.error("Failed to clear secrets:",e.message),process.exit(1)}});nr.exports=rt});var lr=x((hd,cr)=>{"use strict";var or=require("commander"),B=y(require("chalk")),J=y(require("fs-extra")),ie=y(require("path")),rr=y(require("os"));E();function sr(){return ie.default.join(__dirname,"..","skills")}function ni(){return ie.default.join(rr.default.homedir(),".claude","skills","sinch-functions")}function ii(){return ie.default.join(process.cwd(),".claude","skills","sinch-functions")}function oi(){return ie.default.join(process.cwd(),".github","skills","sinch-functions")}function ar(i={}){let e=[],t=ni();if(e.push({tool:"Claude Code",path:t,type:"global",installed:J.default.existsSync(ie.default.join(t,"SKILL.md"))}),i.project){let o=ii();e.push({tool:"Claude Code",path:o,type:"project",installed:J.default.existsSync(ie.default.join(o,"SKILL.md"))})}if(i.project){let o=oi();e.push({tool:"GitHub Copilot",path:o,type:"project",installed:J.default.existsSync(ie.default.join(o,"SKILL.md"))})}return e}var wt=new or.Command("skills");wt.description("Manage AI coding assistant skills for Sinch development").addHelpText("after",`
112
+ `);st.command("list").description("List all custom secrets (keys only)").action(async()=>{try{let e=(await Le.default.findCredentials(We)).filter(t=>t.account&&t.account.startsWith("custom-")).map(t=>t.account.replace("custom-",""));if(e.length===0){n.info("No custom secrets found"),n.info(""),n.info("\u{1F4A1} Add a secret with:"),n.info(` ${Y.default.cyan("sinch secrets add <KEY> <VALUE>")}`);return}n.info(Y.default.bold("Custom Secrets:")),n.info(""),e.forEach(t=>{n.info(` \u{1F510} ${Y.default.cyan(t)}`)}),n.info(""),n.info(`Total: ${e.length} secret(s)`)}catch(i){n.error("Failed to list secrets:",i.message),process.exit(1)}});st.command("add <key> <value>").description("Add or update a secret in OS keychain").action(async(i,e)=>{try{i.match(/^[A-Z0-9_]+$/)||(n.error("Secret key must be uppercase letters, numbers, and underscores only"),n.info(`Example: ${Y.default.cyan("API_KEY")}, ${Y.default.cyan("DATABASE_PASSWORD")}`),process.exit(1));let t=`custom-${i}`,r=await Le.default.getPassword(We,t)!==null;await Le.default.setPassword(We,t,e),r?n.success(`\u2705 Updated secret: ${Y.default.cyan(i)}`):n.success(`\u2705 Added secret: ${Y.default.cyan(i)}`),n.info(""),n.info("\u{1F4DD} To use in your function:"),n.info(` 1. Add ${Y.default.cyan(i+"=")} to your .env file (leave value empty)`),n.info(` 2. Access via ${Y.default.cyan("process.env."+i)} in your code`),n.info(" 3. The secret will be loaded automatically from OS keychain")}catch(t){n.error("Failed to add secret:",t.message),process.exit(1)}});st.command("get <key>").description("Get a specific secret value").option("--show","Show the actual value (be careful!)").action(async(i,e)=>{try{let t=`custom-${i}`,o=await Le.default.getPassword(We,t);o||(n.error(`Secret not found: ${Y.default.cyan(i)}`),n.info(""),n.info("\u{1F4A1} Available secrets:"),n.info(` Run ${Y.default.cyan("sinch secrets list")} to see all secrets`),process.exit(1)),n.info(`Secret: ${Y.default.cyan(i)}`),e.show?(n.warn("\u26A0\uFE0F Showing secret value - be careful not to expose it!"),n.info(`Value: ${o}`)):(n.info(`Value: ${Y.default.gray("[HIDDEN - use --show to reveal]")}`),n.info(`Length: ${o.length} characters`))}catch(t){n.error("Failed to get secret:",t.message),process.exit(1)}});st.command("delete <key>").alias("remove").alias("rm").description("Remove a secret from OS keychain").option("-f, --force","Skip confirmation").action(async(i,e)=>{try{let t=`custom-${i}`;if(await Le.default.getPassword(We,t)||(n.error(`Secret not found: ${Y.default.cyan(i)}`),process.exit(1)),!e.force&&!(await pi.default.prompt([{type:"confirm",name:"confirm",message:`Are you sure you want to delete secret '${i}'?`,default:!1}])).confirm){n.info("Cancelled");return}await Le.default.deletePassword(We,t)?n.success(`\u2705 Deleted secret: ${Y.default.cyan(i)}`):(n.error("Failed to delete secret"),process.exit(1))}catch(t){n.error("Failed to delete secret:",t.message),process.exit(1)}});st.command("clear").description("Remove ALL custom secrets (use with caution!)").option("-f, --force","Skip confirmation").action(async i=>{try{let t=(await Le.default.findCredentials(We)).filter(r=>r.account&&r.account.startsWith("custom-"));if(t.length===0){n.info("No custom secrets to clear");return}if(!i.force&&(n.warn(`\u26A0\uFE0F This will delete ${t.length} custom secret(s)`),!(await pi.default.prompt([{type:"confirm",name:"confirm",message:"Are you sure you want to delete ALL custom secrets?",default:!1}])).confirm)){n.info("Cancelled");return}let o=0;for(let r of t)await Le.default.deletePassword(We,r.account)&&o++;n.success(`\u2705 Deleted ${o} custom secret(s)`)}catch(e){n.error("Failed to clear secrets:",e.message),process.exit(1)}});Cr.exports=st});var Ar=N((Qd,Pr)=>{"use strict";var Sr=require("commander"),B=y(require("chalk")),V=y(require("fs-extra")),ie=y(require("path")),br=y(require("os"));T();function Ir(){return ie.default.join(__dirname,"..","skills")}function ui(){return ie.default.join(br.default.homedir(),".claude","skills","sinch-functions")}function fi(){return ie.default.join(process.cwd(),".claude","skills","sinch-functions")}function mi(){return ie.default.join(process.cwd(),".github","skills","sinch-functions")}function $r(i={}){let e=[],t=ui();if(e.push({tool:"Claude Code",path:t,type:"global",installed:V.default.existsSync(ie.default.join(t,"SKILL.md"))}),i.project){let o=fi();e.push({tool:"Claude Code",path:o,type:"project",installed:V.default.existsSync(ie.default.join(o,"SKILL.md"))})}if(i.project){let o=mi();e.push({tool:"GitHub Copilot",path:o,type:"project",installed:V.default.existsSync(ie.default.join(o,"SKILL.md"))})}return e}var St=new Sr.Command("skills");St.description("Manage AI coding assistant skills for Sinch development").addHelpText("after",`
109
113
  Examples:
110
114
  ${B.default.cyan("sinch skills install")} Install skills globally (Claude Code)
111
115
  ${B.default.cyan("sinch skills install --project")} Install to current project (Claude + Copilot)
@@ -115,14 +119,14 @@ Examples:
115
119
  ${B.default.cyan("sinch skills uninstall")} Remove installed skills
116
120
 
117
121
  Skills provide AI coding assistants with accurate Sinch development patterns.
118
- `);wt.command("install").description("Install Sinch skills for AI coding assistants").option("--claude","Install for Claude Code only").option("--copilot","Install for GitHub Copilot only (requires --project)").option("--project","Install to current project (for team sharing via git)").option("--link","Symlink instead of copy (for development)").option("--force","Overwrite existing skills without prompting").action(async i=>{try{let e=sr();J.default.existsSync(e)||(n.error("Skills source not found. This may indicate a corrupted CLI installation."),n.info(`Expected path: ${e}`),process.exit(1));let t=ie.default.join(e,"sinch-functions");J.default.existsSync(t)||(n.error("Skill source not found."),process.exit(1));let o=0,r=0,s=i.claude||!i.claude&&!i.copilot,a=i.copilot||!i.claude&&!i.copilot&&i.project;if(s){if(!i.project||i.claude){let l=ni();J.default.existsSync(ie.default.join(l,"SKILL.md"))&&!i.force?(n.warn(`Claude Code skill already installed at ${l}`),n.info("Use --force to overwrite"),r++):(await J.default.ensureDir(ie.default.dirname(l)),i.link&&process.platform!=="win32"?(J.default.existsSync(l)&&await J.default.remove(l),await J.default.symlink(t,l,"junction"),n.success(`Linked Claude Code skill to ${l}`)):(await J.default.copy(t,l,{overwrite:!0}),n.success(`Installed Claude Code skill to ${l}`)),o++)}if(i.project){let l=ii();J.default.existsSync(ie.default.join(l,"SKILL.md"))&&!i.force?(n.warn(`Claude Code project skill already installed at ${l}`),n.info("Use --force to overwrite"),r++):(await J.default.ensureDir(ie.default.dirname(l)),await J.default.copy(t,l,{overwrite:!0}),n.success(`Installed Claude Code skill to ${l}`),o++)}}if(a&&i.project){let l=oi();J.default.existsSync(ie.default.join(l,"SKILL.md"))&&!i.force?(n.warn(`Copilot skill already installed at ${l}`),n.info("Use --force to overwrite"),r++):(await J.default.ensureDir(ie.default.dirname(l)),await J.default.copy(t,l,{overwrite:!0}),n.success(`Installed Copilot skill to ${l}`),o++)}else i.copilot&&!i.project&&(n.warn("Copilot requires --project flag (no global installation supported)"),n.info("Use: sinch skills install --copilot --project"));n.info(""),o>0&&n.success(`Installed ${o} skill(s)`),r>0&&n.info(`Skipped ${r} existing skill(s)`),o>0&&(n.info(""),n.info(B.default.bold("Next steps:")),s&&(n.info(` ${B.default.cyan("\u2022")} Claude Code will now have Sinch expertise`),n.info(` ${B.default.cyan("\u2022")} Ask about voice IVRs, SVAML, or CLI commands`)),a&&i.project&&(n.info(` ${B.default.cyan("\u2022")} Copilot will use Sinch patterns for code suggestions`),n.info(` ${B.default.cyan("\u2022")} Commit .github/skills/ to share with team`)))}catch(e){n.error("Failed to install skills:",e.message),process.exit(1)}});wt.command("list").description("Show installed skill locations").action(async()=>{try{let i=ar({project:!0}),e=i.filter(a=>a.type==="global"),t=i.filter(a=>a.type==="project");n.info(B.default.bold(`Sinch Skills Installation Status
119
- `)),n.info(B.default.underline("Global (personal machine):"));let o=!1;for(let a of e)a.installed?(n.info(` ${B.default.green("\u2713")} ${a.tool}: ${B.default.gray(a.path)}`),o=!0):n.info(` ${B.default.gray("\u25CB")} ${a.tool}: ${B.default.gray("not installed")}`);o||n.info(` ${B.default.gray("No global skills installed")}`),n.info(""),n.info(B.default.underline("Project (current directory):"));let r=!1;for(let a of t)a.installed?(n.info(` ${B.default.green("\u2713")} ${a.tool}: ${B.default.gray(a.path)}`),r=!0):n.info(` ${B.default.gray("\u25CB")} ${a.tool}: ${B.default.gray("not installed")}`);r||n.info(` ${B.default.gray("No project skills installed")}`),n.info(""),i.some(a=>a.installed)||(n.info("Run `sinch skills install` to install skills globally"),n.info("Run `sinch skills install --project` to install for this project"))}catch(i){n.error("Failed to list skills:",i.message),process.exit(1)}});wt.command("uninstall").description("Remove installed Sinch skills").option("--claude","Uninstall from Claude Code only").option("--copilot","Uninstall from GitHub Copilot only").option("--project","Uninstall from current project only").option("--all","Uninstall from all locations").action(async i=>{try{let e=0,t=!i.claude&&!i.copilot&&!i.project&&!i.all,o=i.all||t,r=i.project&&!i.all&&!t,s=i.claude||o||r,a=i.copilot||o||r;if(s){if(!r){let l=ni();J.default.existsSync(l)&&(await J.default.remove(l),n.success(`Removed Claude Code skill from ${l}`),e++)}if(r||o){let l=ii();J.default.existsSync(l)&&(await J.default.remove(l),n.success(`Removed Claude Code skill from ${l}`),e++)}}if(a&&(r||o)){let l=oi();J.default.existsSync(l)&&(await J.default.remove(l),n.success(`Removed Copilot skill from ${l}`),e++)}n.info(""),e>0?n.success(`Removed ${e} skill(s)`):n.info("No skills found to remove")}catch(e){n.error("Failed to uninstall skills:",e.message),process.exit(1)}});wt.command("update").description("Update skills to latest version").option("--project","Update project skills as well").action(async i=>{try{n.info(`Updating Sinch skills...
120
- `);let t=ar({project:i.project}).filter(a=>a.installed);if(t.length===0){n.info("No skills installed. Run `sinch skills install` first.");return}let o=sr(),r=ie.default.join(o,"sinch-functions"),s=0;for(let a of t)await J.default.copy(r,a.path,{overwrite:!0}),n.success(`Updated ${a.tool} (${a.type})`),s++;n.info(""),n.success(`Updated ${s} skill(s)`)}catch(e){n.error("Failed to update skills:",e.message),process.exit(1)}});cr.exports=wt});async function za(){await f.load(),await f.hasCredentials()||(n.error('Not authenticated. Run "sinch auth login" first.'),process.exit(1))}async function M(){return await za(),await f.createSinchClient()}function Ct(i){let e=i||f.get("conversation-app-id");return e||(n.error("No Conversation App ID configured."),n.info("Set default: sinch config set conversation-app-id <id>"),n.info("Or specify: --app <app-id>"),process.exit(1)),e}var st=W(()=>{"use strict";A();E()});var mr=x((Id,fr)=>{"use strict";var dr=require("commander"),pr=y(require("inquirer"));E();D();st();var ur=new dr.Command("send");ur.description("Send a message via Conversation API").argument("[recipient]","Recipient phone number (e.g., +15551234567)").argument("[message]","Message text to send").option("-c, --channel <channel>","Channel (SMS, WHATSAPP, MESSENGER, etc.)","SMS").option("-a, --app <app-id>","Conversation App ID (uses default if configured)").option("-m, --media <url>","Media URL for media messages").option("--caption <text>","Caption for media messages").option("-t, --template <name>","Template name for template messages").option("-p, --params <json>","Template parameters as JSON string").option("--location","Send location message").option("--lat <latitude>","Latitude for location messages",parseFloat).option("--lng <longitude>","Longitude for location messages",parseFloat).option("-n, --name <name>","Location name").option("--json","Output result as JSON").action(async(i,e,t)=>{try{let o=await M();if(!i||!e&&!t?.media&&!t?.template&&!t?.location){let s=await pr.default.prompt([{type:"input",name:"recipient",message:"Enter recipient phone number:",when:!i,validate:a=>a?a.startsWith("+")?!0:"Phone number must start with +":"Recipient is required"},{type:"input",name:"message",message:"Enter message:",when:!e&&!t?.media&&!t?.template&&!t?.location,validate:a=>a?!0:"Message is required"},{type:"list",name:"channel",message:"Select channel:",choices:["SMS","WHATSAPP","MESSENGER","INSTAGRAM","VIBER","TELEGRAM","RCS","LINE"],default:t?.channel||"SMS",when:!t?.channel}]);i=i||s.recipient,e=e||s.message,s.channel&&(t={...t,channel:s.channel})}let r=Ct(t?.app);c.start("Sending message...");try{let s;if(t?.location)(!t.lat||!t.lng)&&(c.fail("Location messages require --lat and --lng"),process.exit(1)),s=await o.conversation.messages.send({sendMessageRequestBody:{app_id:r,recipient:{identified_by:{channel_identities:[{channel:t.channel||"SMS",identity:i}]}},message:{location_message:{coordinates:{latitude:t.lat,longitude:t.lng},title:t.name}}}});else if(t?.template){let a=t.params?JSON.parse(t.params):{};s=await o.conversation.messages.send({sendMessageRequestBody:{app_id:r,recipient:{identified_by:{channel_identities:[{channel:t.channel||"WHATSAPP",identity:i}]}},message:{template_message:{template_reference:{template_id:t.template,version:a.version||"1"},parameters:a}}}})}else t?.media?s=await o.conversation.messages.send({sendMessageRequestBody:{app_id:r,recipient:{identified_by:{channel_identities:[{channel:t.channel||"WHATSAPP",identity:i}]}},message:{media_message:{url:t.media,caption:t.caption}}}}):s=await o.conversation.messages.send({sendMessageRequestBody:{app_id:r,recipient:{identified_by:{channel_identities:[{channel:t?.channel||"SMS",identity:i}]}},message:{text_message:{text:e}}}});c.succeed("Message sent successfully!"),t?.json?console.log(JSON.stringify(s,null,2)):(n.newline(),n.info(`Message ID: ${s.message_id}`),n.info(`Recipient: ${i}`),n.info(`Channel: ${t?.channel||"SMS"}`))}catch(s){c.fail("Failed to send message"),n.error(`Error: ${s.message}`),(s.message?.includes("WHATSAPP")||s.message?.includes("channel not configured"))&&(n.newline(),n.info("To use WhatsApp, configure WhatsApp credentials in your Conversation app:"),n.info(" 1. Visit https://dashboard.sinch.com/convapi/apps"),n.info(" 2. Add WhatsApp channel credentials"),n.info(" 3. Verify your WhatsApp Business Account"),n.newline(),n.info("Or use SMS (no additional setup required):"),n.info(` sinch conversation send ${i} "${e}"`)),process.exit(1)}}catch(o){c.stop(),n.error(`Failed to send message: ${o.message}`),process.exit(1)}});fr.exports=ur});var yr=x((Ad,hr)=>{"use strict";var gr=require("commander");E();D();st();var Bt=new gr.Command("messages");Bt.description("Manage conversation messages");Bt.command("get").description("Get a specific message by ID").argument("<message-id>","Message ID to retrieve").option("--json","Output result as JSON").action(async(i,e)=>{try{let t=await M();c.start("Fetching message...");let o=await t.conversation.messages.get({message_id:i});c.succeed("Message retrieved"),e.json?console.log(JSON.stringify(o,null,2)):(n.newline(),n.info(`Message ID: ${o.id}`),n.info(`Direction: ${o.direction}`),n.info(`Channel: ${o.channel_identity?.channel||"N/A"}`),n.info(`Contact ID: ${o.contact_id||"N/A"}`),n.info(`Conversation ID: ${o.conversation_id||"N/A"}`),n.info(`Status: ${o.accept_time?"Accepted":"Pending"}`),o.text_message&&n.info(`Text: ${o.text_message.text}`),o.media_message&&n.info(`Media URL: ${o.media_message.url}`))}catch(t){c.stop(),n.error(`Failed to get message: ${t.message}`),process.exit(1)}});Bt.command("list").description("List messages").option("-c, --channel <channel>","Filter by channel").option("-l, --limit <number>","Limit number of results",parseInt,20).option("--json","Output result as JSON").action(async i=>{try{let e=await M();c.start("Fetching messages...");let t=await e.conversation.messages.list({page_size:i.limit||20,...i.channel&&{channel:i.channel}});c.succeed(`Retrieved ${t.messages?.length||0} messages`),i.json?console.log(JSON.stringify(t,null,2)):(n.newline(),t.messages&&t.messages.length>0?t.messages.forEach(o=>{n.info(`[${o.id}] ${o.direction} via ${o.channel_identity?.channel||"N/A"}`),o.text_message&&n.info(` "${o.text_message.text}"`),n.newline()}):n.info("No messages found"))}catch(e){c.stop(),n.error(`Failed to list messages: ${e.message}`),process.exit(1)}});Bt.command("delete").description("Delete a message").argument("<message-id>","Message ID to delete").action(async i=>{try{let e=await M();c.start("Deleting message..."),await e.conversation.messages.delete({message_id:i}),c.succeed("Message deleted successfully")}catch(e){c.stop(),n.error(`Failed to delete message: ${e.message}`),process.exit(1)}});hr.exports=Bt});function _(i){try{let e=wr.parse(i);return wr.format(e,ln.PhoneNumberFormat.INTERNATIONAL)}catch{return i}}var ln,wr,vt=W(()=>{"use strict";ln=require("google-libphonenumber"),wr=ln.PhoneNumberUtil.getInstance()});var br=x((Nd,vr)=>{"use strict";var Cr=require("commander"),ce=y(require("inquirer"));E();D();st();vt();var dn=class{sinchClient;constructor(e){this.sinchClient=e}hasChannel(e,t){return e.channel_identities?.some(o=>{let r=o.channel;return r==="CHANNEL_UNSPECIFIED"&&o.identity.includes("@")&&(r="EMAIL"),t.includes(r)})}getChannelIdentities(e,t){return e.channel_identities.filter(o=>{let r=o.channel;return r==="CHANNEL_UNSPECIFIED"&&o.identity.includes("@")&&(r="EMAIL"),t.includes(r)})}buildContactMenu(e){let t=this.hasChannel(e,["SMS","WHATSAPP"]),o=this.hasChannel(e,["SMS","WHATSAPP"]),r=this.hasChannel(e,["EMAIL"]),s=[];return t&&s.push({name:"\u{1F4AC} Send Message",value:"send-message"}),s.push({name:"Edit Name",value:"edit-name"}),o&&s.push({name:"Edit Phone",value:"edit-phone"}),r&&s.push({name:"Edit Email",value:"edit-email"}),s.push({name:"Delete Contact",value:"delete"},{name:"See More Details",value:"details"},{name:"\u2190 Back",value:"back"}),s}async sendMessage(e){let t=e.channel_identities.map(s=>{let a=s.channel;return a==="CHANNEL_UNSPECIFIED"&&s.identity.includes("@")&&(a="EMAIL"),{name:`${a}: ${_(s.identity)}`,value:{channel:a,identity:s.identity}}});t.push({name:"\u2190 Back",value:"back"});let{selectedChannel:o}=await ce.default.prompt([{type:"list",name:"selectedChannel",message:"Select channel to send to:",choices:t}]);if(o==="back")return!1;let{messageText:r}=await ce.default.prompt([{type:"input",name:"messageText",message:"Enter your message:",validate:s=>s?!0:"Message is required"}]);try{let s=Ct();c.start("Sending message...");let a=await this.sinchClient.conversation.messages.send({sendMessageRequestBody:{app_id:s,recipient:{identified_by:{channel_identities:[{channel:o.channel,identity:o.identity,app_id:""}]}},message:{text_message:{text:r}}}});c.succeed("Message sent successfully!"),n.newline(),n.info(`Message ID: ${a.message_id}`),n.info(`Recipient: ${_(o.identity)}`),n.info(`Channel: ${o.channel}`),n.newline()}catch(s){c.fail("Failed to send message"),n.error(`Error: ${s.message}`),n.newline()}return!1}showDetails(e){n.newline(),n.info("Contact Details:"),n.info(`ID: ${e.id}`),n.info(`Display Name: ${e.display_name||"N/A"}`),n.info(`Email: ${e.email||"N/A"}`),n.info(`External ID: ${e.external_id||"N/A"}`),n.info(`Language: ${e.language||"N/A"}`),n.info(`Metadata: ${e.metadata||"N/A"}`),e.channel_identities&&e.channel_identities.length>0&&(n.newline(),n.info("Channel Identities:"),e.channel_identities.forEach(t=>{let o=t.channel;o==="CHANNEL_UNSPECIFIED"&&t.identity.includes("@")&&(o="EMAIL"),n.info(` ${o}: ${_(t.identity)}`)})),n.newline()}async editName(e,t){let{newDisplayName:o}=await ce.default.prompt([{type:"input",name:"newDisplayName",message:"Enter new display name:",default:e.display_name}]);c.start("Updating contact..."),await this.sinchClient.conversation.contact.update({contact_id:t,display_name:o}),c.succeed("Contact updated successfully!"),e.display_name=o,n.newline()}async editChannelIdentities(e,t,o){let s={phone:{channels:["SMS","WHATSAPP"],addPrompt:"+ Add new phone number",selectPrompt:"Select phone number to edit or add new:",typePrompt:"Select type:",valuePrompt:"Enter phone number:",editPrompt:"Enter new phone number:",typeChoices:["SMS","WHATSAPP"],successAdd:"Phone number added successfully!",successEdit:"Phone number updated successfully!",successDelete:"Phone number deleted successfully!",validator:d=>d?d.startsWith("+")?!0:"Phone number must start with +":"Phone number is required"},email:{channels:["EMAIL"],addPrompt:"+ Add new email address",selectPrompt:"Select email address to edit or add new:",typePrompt:null,valuePrompt:"Enter email address:",editPrompt:"Enter new email address:",typeChoices:null,successAdd:"Email address added successfully!",successEdit:"Email address updated successfully!",successDelete:"Email address deleted successfully!",validator:d=>d?d.includes("@")?!0:"Invalid email address":"Email is required"}}[o],l=this.getChannelIdentities(e,s.channels).map(d=>{let u=e.channel_identities.indexOf(d),m=d.channel;return m==="CHANNEL_UNSPECIFIED"&&d.identity.includes("@")&&(m="EMAIL"),{name:`${m}: ${_(d.identity)}`,value:u}});l.push({name:s.addPrompt,value:"add"}),l.push({name:"\u2190 Back",value:"cancel"});let{identityAction:p}=await ce.default.prompt([{type:"list",name:"identityAction",message:s.selectPrompt,choices:l}]);if(p!=="cancel")if(p==="add"){let d=[];s.typePrompt&&s.typeChoices&&d.push({type:"list",name:"newIdentityType",message:s.typePrompt,choices:s.typeChoices}),d.push({type:"input",name:"newIdentityValue",message:s.valuePrompt,validate:s.validator});let u=await ce.default.prompt(d);e.channel_identities.push({channel:u.newIdentityType||s.channels[0],identity:u.newIdentityValue,app_id:""}),c.start("Updating contact..."),await this.sinchClient.conversation.contact.update({contact_id:t,channel_identities:e.channel_identities,display_name:e.display_name}),c.succeed(s.successAdd),n.newline()}else{let d=e.channel_identities[p],{editOrDelete:u}=await ce.default.prompt([{type:"list",name:"editOrDelete",message:"What would you like to do?",choices:["Edit","Delete","\u2190 Back"]}]);if(u==="Edit"){let{newValue:m}=await ce.default.prompt([{type:"input",name:"newValue",message:s.editPrompt,default:d.identity,validate:s.validator}]);d.identity=m,c.start("Updating contact..."),await this.sinchClient.conversation.contact.update({contact_id:t,channel_identities:e.channel_identities,display_name:e.display_name}),c.succeed(s.successEdit),n.newline()}else u==="Delete"&&(e.channel_identities.splice(p,1),c.start("Updating contact..."),await this.sinchClient.conversation.contact.update({contact_id:t,channel_identities:e.channel_identities,display_name:e.display_name}),c.succeed(s.successDelete),n.newline())}}async deleteContact(e,t,o){let{confirmDelete:r}=await ce.default.prompt([{type:"confirm",name:"confirmDelete",message:`Are you sure you want to delete "${e.display_name||"this contact"}"?`,default:!1}]);if(r){c.start("Deleting contact..."),await this.sinchClient.conversation.contact.delete({contact_id:t}),c.succeed("Contact deleted successfully");let s=o.findIndex(a=>a.id===t);if(s>-1&&o.splice(s,1),o.length===0)return n.info("No more contacts."),!0;n.newline()}return!1}async handleAction(e,t,o,r){switch(e){case"send-message":return await this.sendMessage(t);case"details":return this.showDetails(t),!1;case"edit-name":return await this.editName(t,o),!1;case"edit-phone":return await this.editChannelIdentities(t,o,"phone"),!1;case"edit-email":return await this.editChannelIdentities(t,o,"email"),!1;case"delete":return await this.deleteContact(t,o,r);default:return!1}}async runInteractiveList(e){let t=!0;for(;t;){let o=[];e.forEach(p=>{o.push(new ce.default.Separator(`
121
- ${p.display_name||"No name"}`)),p.channel_identities&&p.channel_identities.length>0&&p.channel_identities.forEach(d=>{let u=d.channel;u==="CHANNEL_UNSPECIFIED"&&d.identity.includes("@")&&(u="EMAIL"),o.push(new ce.default.Separator(`${u}: ${d.identity}`))}),o.push({name:"Edit Delete More",value:`menu:${p.id}`})}),o.push(new ce.default.Separator("")),o.push({name:"\u2190 Exit",value:"exit"});let{action:r}=await ce.default.prompt([{type:"list",name:"action",message:"Contacts",choices:o,pageSize:20}]);if(r==="exit")break;if(!r||!r.includes(":"))continue;let[s,a]=r.split(":"),l=e.find(p=>p.id===a);if(s==="menu"){let p=this.buildContactMenu(l),{subAction:d}=await ce.default.prompt([{type:"list",name:"subAction",message:`Actions for ${l.display_name||"contact"}:`,choices:p}]);if(d==="back")continue;await this.handleAction(d,l,a,e)&&(t=!1)}}}},Ke=new Cr.Command("contacts");Ke.description("Manage conversation contacts");Ke.command("create").description("Create a new contact").option("-p, --phone <number>","Phone number").option("-e, --email <email>","Email address").option("-n, --name <name>","Contact name").option("-d, --display-name <name>","Display name").option("--json","Output result as JSON").action(async i=>{try{if(!i.phone&&!i.email){let s=await ce.default.prompt([{type:"input",name:"phone",message:"Enter phone number (optional):",validate:a=>a&&!a.startsWith("+")?"Phone number must start with +":!0},{type:"input",name:"email",message:"Enter email address (optional):"},{type:"input",name:"name",message:"Enter contact name (optional):"}]);i={...i,...s}}!i.phone&&!i.email&&(n.error("At least one of phone or email is required"),process.exit(1));let e=await M();c.start("Creating contact...");let t=[];i.phone&&t.push({channel:"SMS",identity:i.phone}),i.email&&t.push({channel:"EMAIL",identity:i.email});let o={contactCreateRequestBody:{channel_identities:t,display_name:i.displayName||i.name,language:"EN_US"}},r=await e.conversation.contact.create(o);c.succeed("Contact created successfully!"),i.json||(n.newline(),n.info(`Contact ID: ${r.id}`),n.info(`Display Name: ${r.display_name||"N/A"}`),i.phone&&n.info(`Phone: ${_(i.phone)}`),i.email&&n.info(`Email: ${i.email}`))}catch(e){c.stop(),n.error(`Failed to create contact: ${e.message}`),e.response?.data&&n.error("API Response:",JSON.stringify(e.response.data,null,2)),e.data&&n.error("Error data:",JSON.stringify(e.data,null,2)),process.exit(1)}});Ke.command("get").description("Get a specific contact by ID").argument("<contact-id>","Contact ID to retrieve").option("--json","Output result as JSON").action(async(i,e)=>{try{let t=await M();c.start("Fetching contact...");let o=await t.conversation.contact.get({contact_id:i});c.succeed("Contact retrieved"),e.json?console.log(JSON.stringify(o,null,2)):new dn(t).showDetails(o)}catch(t){c.stop(),n.error(`Failed to get contact: ${t.message}`),process.exit(1)}});Ke.command("list").description("List contacts").option("-l, --limit <number>","Limit number of results",parseInt,50).option("--json","Output result as JSON").option("--no-interactive","Disable interactive mode").action(async i=>{try{let e=await M();c.start("Fetching contacts...");let t=await e.conversation.contact.list({page_size:i.limit||50}),o=t.data||t.contacts||[];if(c.succeed(`Retrieved ${o.length} contacts`),i.json){console.log(JSON.stringify(t,null,2));return}o&&o.length>0?(n.newline(),n.newline(),i.interactive!==!1?await new dn(e).runInteractiveList(o):o.forEach(r=>{n.info(r.display_name||"No name"),r.channel_identities&&r.channel_identities.length>0&&r.channel_identities.forEach(s=>{let a=s.channel;a==="CHANNEL_UNSPECIFIED"&&s.identity.includes("@")&&(a="EMAIL"),n.info(`${a}: ${s.identity}`)}),n.newline()})):(n.newline(),n.info("No contacts found"))}catch(e){c.stop(),n.error(`Failed to list contacts: ${e.message}`),process.exit(1)}});Ke.command("update").description("Update a contact").argument("<contact-id>","Contact ID to update").option("-n, --name <name>","New contact name").option("-d, --display-name <name>","New display name").option("--json","Output result as JSON").action(async(i,e)=>{try{!e.displayName&&!e.name&&(n.error("At least one update field is required (--name or --display-name)"),process.exit(1));let t=await M();c.start("Updating contact...");let o=await t.conversation.contact.update({contact_id:i,display_name:e.displayName||e.name,...e.name&&{metadata:JSON.stringify({name:e.name})}});c.succeed("Contact updated successfully!"),e.json?console.log(JSON.stringify(o,null,2)):(n.newline(),n.info(`Contact ID: ${o.id}`),n.info(`Display Name: ${o.display_name||"N/A"}`))}catch(t){c.stop(),n.error(`Failed to update contact: ${t.message}`),process.exit(1)}});Ke.command("delete").description("Delete a contact").argument("<contact-id>","Contact ID to delete").action(async i=>{try{let e=await M();c.start("Deleting contact..."),await e.conversation.contact.delete({contact_id:i}),c.succeed("Contact deleted successfully")}catch(e){c.stop(),n.error(`Failed to delete contact: ${e.message}`),process.exit(1)}});Ke.command("merge").description("Merge two contacts").argument("<source-id>","Source contact ID (will be merged into destination)").argument("<dest-id>","Destination contact ID").option("--json","Output result as JSON").action(async(i,e,t)=>{try{let o=await M();c.start("Merging contacts...");let r=await o.conversation.contact.mergeContact({destination_id:e,source_id:i});c.succeed("Contacts merged successfully!"),t.json?console.log(JSON.stringify(r,null,2)):(n.newline(),n.info(`Source contact ${i} merged into ${e}`),n.info(`Result Contact ID: ${r.id}`))}catch(o){c.stop(),n.error(`Failed to merge contacts: ${o.message}`),process.exit(1)}});vr.exports=Ke});var $r=x((Ld,Ir)=>{"use strict";var Sr=require("commander");E();D();st();var Kt=new Sr.Command("conversations");Kt.description("Manage conversations");Kt.command("list").description("List conversations").option("-a, --app <app-id>","Filter by Conversation App ID").option("-l, --limit <number>","Limit number of results",parseInt,50).option("--json","Output result as JSON").action(async i=>{try{let e=await M();c.start("Fetching conversations...");let t=await e.conversation.conversation.list({page_size:i.limit||50,...i.app&&{app_id:i.app}});c.succeed(`Retrieved ${t.conversations?.length||0} conversations`),i.json?console.log(JSON.stringify(t,null,2)):(n.newline(),t.conversations&&t.conversations.length>0?t.conversations.forEach(o=>{n.info(`[${o.id}]`),n.info(` App ID: ${o.app_id}`),n.info(` Active: ${o.active_channel||"N/A"}`),n.info(` Last Updated: ${o.last_received?new Date(o.last_received).toLocaleString():"N/A"}`),n.newline()}):n.info("No conversations found"))}catch(e){c.stop(),n.error(`Failed to list conversations: ${e.message}`),process.exit(1)}});Kt.command("get").description("Get a specific conversation by ID").argument("<conversation-id>","Conversation ID to retrieve").option("--json","Output result as JSON").action(async(i,e)=>{try{let t=await M();c.start("Fetching conversation...");let o=await t.conversation.conversation.get({conversation_id:i});c.succeed("Conversation retrieved"),e.json?console.log(JSON.stringify(o,null,2)):(n.newline(),n.info(`Conversation ID: ${o.id}`),n.info(`App ID: ${o.app_id}`),n.info(`Active Channel: ${o.active_channel||"N/A"}`),n.info(`Contact ID: ${o.contact_id||"N/A"}`),o.metadata&&(n.newline(),n.info("Metadata:"),n.info(JSON.stringify(o.metadata,null,2))))}catch(t){c.stop(),n.error(`Failed to get conversation: ${t.message}`),process.exit(1)}});Kt.command("stop").description("Stop an active conversation").argument("<conversation-id>","Conversation ID to stop").action(async i=>{try{let e=await M();c.start("Stopping conversation..."),await e.conversation.conversation.delete({conversation_id:i}),c.succeed("Conversation stopped successfully")}catch(e){c.stop(),n.error(`Failed to stop conversation: ${e.message}`),process.exit(1)}});Ir.exports=Kt});var Ar=x((Md,kr)=>{"use strict";var Pr=require("commander"),ri=y(require("inquirer"));E();D();st();var bt=new Pr.Command("apps");bt.description("Manage Conversation apps");bt.command("list").description("List Conversation apps").option("-l, --limit <number>","Limit number of results",parseInt,50).option("--json","Output result as JSON").action(async i=>{try{let e=await M();c.start("Fetching apps...");let t=await e.conversation.app.list({page_size:i.limit||50});c.succeed(`Retrieved ${t.apps?.length||0} apps`),i.json?console.log(JSON.stringify(t,null,2)):(n.newline(),t.apps&&t.apps.length>0?t.apps.forEach(o=>{n.info(`[${o.id}] ${o.display_name||"No name"}`),n.info(` Channels: ${o.channel_credentials?.length||0} configured`),n.newline()}):n.info("No apps found"))}catch(e){c.stop(),n.error(`Failed to list apps: ${e.message}`),process.exit(1)}});bt.command("get").description("Get a specific Conversation app by ID").argument("<app-id>","App ID to retrieve").option("--json","Output result as JSON").action(async(i,e)=>{try{let t=await M();c.start("Fetching app...");let o=await t.conversation.app.get({app_id:i});c.succeed("App retrieved"),e.json?console.log(JSON.stringify(o,null,2)):(n.newline(),n.info(`App ID: ${o.id}`),n.info(`Display Name: ${o.display_name||"N/A"}`),n.info("Rate Limits:",o.rate_limits||"N/A"),o.channel_credentials&&o.channel_credentials.length>0&&(n.newline(),n.info("Configured Channels:"),o.channel_credentials.forEach(r=>{n.info(` - ${r.channel}`)})),o.conversation_metadata_report_view&&(n.newline(),n.info(`Metadata Report: ${o.conversation_metadata_report_view}`)))}catch(t){c.stop(),n.error(`Failed to get app: ${t.message}`),process.exit(1)}});bt.command("create").description("Create a new Conversation app").argument("[name]","App display name").option("--json","Output result as JSON").action(async(i,e)=>{try{i||(i=(await ri.default.prompt([{type:"input",name:"name",message:"Enter app display name:",validate:s=>s?!0:"App name is required"}])).name);let t=await M();c.start("Creating app...");let o=await t.conversation.app.create({display_name:i});c.succeed("App created successfully!"),e?.json?console.log(JSON.stringify(o,null,2)):(n.newline(),n.info(`App ID: ${o.id}`),n.info(`Display Name: ${o.display_name}`),n.newline(),n.info("\u{1F4A1} Set as default: sinch config set conversation-app-id "+o.id))}catch(t){c.stop(),n.error(`Failed to create app: ${t.message}`),process.exit(1)}});bt.command("delete").description("Delete a Conversation app").argument("<app-id>","App ID to delete").action(async i=>{try{let{confirm:e}=await ri.default.prompt([{type:"confirm",name:"confirm",message:`Are you sure you want to delete app ${i}?`,default:!1}]);if(!e){n.info("Deletion cancelled");return}let t=await M();c.start("Deleting app..."),await t.conversation.app.delete({app_id:i}),c.succeed("App deleted successfully")}catch(e){c.stop(),n.error(`Failed to delete app: ${e.message}`),process.exit(1)}});kr.exports=bt});var Dr=x((Hd,xr)=>{"use strict";var Er=require("commander"),si=y(require("inquirer"));A();E();D();st();var St=new Er.Command("webhooks");St.description("Manage webhooks for Conversation apps");St.command("list").description("List webhooks for a Conversation app").option("-a, --app <app-id>","Conversation App ID").option("--json","Output result as JSON").action(async i=>{try{let e=Ct(i.app),t=await M();c.start("Fetching webhooks...");let o=await t.conversation.webhooks.list({app_id:e});c.succeed(`Retrieved ${o.webhooks?.length||0} webhooks`),i.json?console.log(JSON.stringify(o,null,2)):(n.newline(),o.webhooks&&o.webhooks.length>0?o.webhooks.forEach(r=>{n.info(`[${r.id}]`),n.info(` URL: ${r.target}`),n.info(` Triggers: ${r.triggers?.join(", ")||"N/A"}`),n.info(` Secret: ${r.secret?"********":"Not set"}`),n.newline()}):n.info("No webhooks found for this app"))}catch(e){c.stop(),n.error(`Failed to list webhooks: ${e.message}`),process.exit(1)}});St.command("create").description("Create a new webhook for a Conversation app").option("-a, --app <app-id>","Conversation App ID").option("-u, --url <url>","Webhook URL").option("-t, --triggers <triggers>","Comma-separated list of triggers (e.g., MESSAGE_INBOUND,MESSAGE_DELIVERY)").option("-s, --secret <secret>","Webhook secret for signature validation").option("--json","Output result as JSON").action(async i=>{try{await f.load(),await f.hasCredentials()||(n.error('Not authenticated. Run "sinch auth login" first.'),process.exit(1));let t=i.app;if(!t){let a=f.get("conversation-app-id");a&&(t=a,n.info(`Using default app: ${t}`))}if(!t||!i.url||!i.triggers){let a=await si.default.prompt([{type:"input",name:"appId",message:"Enter Conversation App ID:",when:!t,validate:l=>l?!0:"App ID is required"},{type:"input",name:"url",message:"Enter webhook URL:",when:!i.url,validate:l=>{if(!l)return"URL is required";try{return new URL(l),!0}catch{return"Please enter a valid URL"}}},{type:"checkbox",name:"triggers",message:"Select webhook triggers:",when:!i.triggers,choices:["MESSAGE_INBOUND","MESSAGE_DELIVERY","MESSAGE_SUBMIT","EVENT_INBOUND","CONVERSATION_START","CONVERSATION_STOP","CONTACT_CREATE","CONTACT_DELETE","CONTACT_MERGE","CONTACT_UPDATE"],validate:l=>l.length>0?!0:"Select at least one trigger"},{type:"input",name:"secret",message:"Enter webhook secret (optional, press enter to skip):"}]);t=t||a.appId,i.url=i.url||a.url,i.triggers=i.triggers||a.triggers.join(","),i.secret=i.secret||a.secret}let o=await M(),r=i.triggers.split(",").map(a=>a.trim());c.start("Creating webhook...");let s=await o.conversation.webhooks.create({app_id:t,target:i.url,triggers:r,...i.secret&&{secret:i.secret}});c.succeed("Webhook created successfully!"),i.json?console.log(JSON.stringify(s,null,2)):(n.newline(),n.info(`Webhook ID: ${s.id}`),n.info(`URL: ${s.target}`),n.info(`Triggers: ${s.triggers?.join(", ")}`),i.secret&&n.info("Secret: ********"))}catch(e){c.stop(),n.error(`Failed to create webhook: ${e.message}`),process.exit(1)}});St.command("update").description("Update a webhook").argument("<webhook-id>","Webhook ID to update").option("-u, --url <url>","New webhook URL").option("-t, --triggers <triggers>","New comma-separated list of triggers").option("-s, --secret <secret>","New webhook secret").option("--json","Output result as JSON").action(async(i,e)=>{try{!e.url&&!e.triggers&&!e.secret&&(n.error("At least one update field is required (--url, --triggers, or --secret)"),process.exit(1));let t=await M(),o={};e.url&&(o.target=e.url),e.triggers&&(o.triggers=e.triggers.split(",").map(s=>s.trim())),e.secret&&(o.secret=e.secret),c.start("Updating webhook...");let r=await t.conversation.webhooks.update({webhook_id:i,...o});c.succeed("Webhook updated successfully!"),e.json?console.log(JSON.stringify(r,null,2)):(n.newline(),n.info(`Webhook ID: ${r.id}`),n.info(`URL: ${r.target}`),n.info(`Triggers: ${r.triggers?.join(", ")}`))}catch(t){c.stop(),n.error(`Failed to update webhook: ${t.message}`),process.exit(1)}});St.command("delete").description("Delete a webhook").argument("<webhook-id>","Webhook ID to delete").action(async i=>{try{let{confirm:e}=await si.default.prompt([{type:"confirm",name:"confirm",message:`Are you sure you want to delete webhook ${i}?`,default:!1}]);if(!e){n.info("Deletion cancelled");return}let t=await M();c.start("Deleting webhook..."),await t.conversation.webhooks.delete({webhook_id:i}),c.succeed("Webhook deleted successfully")}catch(e){c.stop(),n.error(`Failed to delete webhook: ${e.message}`),process.exit(1)}});xr.exports=St});var Nr=x((Wd,Rr)=>{"use strict";var Tr=require("commander"),Ga=mr(),Ya=yr(),Xa=br(),Za=$r(),Qa=Ar(),ec=Dr(),He=new Tr.Command("conversation");He.description("Manage Sinch Conversations API");He.addCommand(Ga);He.addCommand(Ya);He.addCommand(Xa);He.addCommand(Za);He.addCommand(Qa);He.addCommand(ec);Rr.exports=He});var ai,pn,Or,oe,We=W(()=>{"use strict";ai=y(require("axios")),pn=y(require("axios-retry")),Or=y(require("chalk"));pt();Tt();oe=class{baseUrl="https://elastic-trunking.api.sinch.com";projectId;credentials;client;timeout=6e4;constructor(e){this.projectId=e.projectId,this.credentials=e.credentials,this.client=ai.default.create({baseURL:this.baseUrl,timeout:this.timeout,headers:{"Content-Type":"application/json","User-Agent":"sinch-functions-cli/1.0.0"}}),(0,pn.default)(this.client,{retries:3,retryDelay:(t,o)=>{let r=o.response?.headers?.["retry-after"];return r?parseInt(r,10)*1e3:pn.default.exponentialDelay(t)},retryCondition:t=>{if(pn.default.isNetworkError(t))return!0;let o=t.response?.status;return!!(o&&o>=500||o===429)},onRetry:(t,o)=>{ue(1,`Retry ${t}/3: ${o.message}`)}}),this.client.interceptors.request.use(async t=>{let o=await this.getAuthHeader();return o&&(t.headers.Authorization=o),se()>=2&&ue(2,`\u2192 ${t.method?.toUpperCase()} ${t.url}`),t},t=>Promise.reject(t)),this.client.interceptors.response.use(t=>(se()>=2&&ue(2,`\u2190 ${t.status} ${t.config.url}`),t),t=>(se()>=2&&ue(2,`\u2190 ${t.response?.status||"ERROR"} ${t.config?.url}`),Promise.reject(t)))}async getAuthHeader(){try{let e=await this.credentials.retrieve();return e&&e.keyId&&e.keySecret?`Basic ${Buffer.from(`${e.keyId}:${e.keySecret}`).toString("base64")}`:null}catch{return console.error(Or.default.yellow("Failed to get authentication credentials")),null}}async listTrunks(e={}){try{let t={};return e.page&&(t.pageToken=e.page),e.pageSize&&(t.pageSize=e.pageSize),(await this.client.get(`/v1/projects/${this.projectId}/trunks`,{params:t})).data}catch(t){throw this.handleError(t,"Failed to list SIP trunks")}}async getTrunk(e){try{return(await this.client.get(`/v1/projects/${this.projectId}/trunks/${e}`)).data}catch(t){throw this.handleError(t,`Failed to get SIP trunk ${e}`)}}async createTrunk(e){try{return(await this.client.post(`/v1/projects/${this.projectId}/trunks`,e)).data}catch(t){throw this.handleError(t,"Failed to create SIP trunk")}}async updateTrunk(e,t){try{return(await this.client.put(`/v1/projects/${this.projectId}/trunks/${e}`,t)).data}catch(o){throw this.handleError(o,`Failed to update SIP trunk ${e}`)}}async deleteTrunk(e){try{await this.client.delete(`/v1/projects/${this.projectId}/trunks/${e}`)}catch(t){throw this.handleError(t,`Failed to delete SIP trunk ${e}`)}}async listEndpoints(e,t={}){try{let o={};return t.page&&(o.pageToken=t.page),t.pageSize&&(o.pageSize=t.pageSize),(await this.client.get(`/v1/projects/${this.projectId}/trunks/${e}/endpoints`,{params:o})).data}catch(o){throw this.handleError(o,`Failed to list endpoints for trunk ${e}`)}}async getEndpoint(e,t){try{return(await this.client.get(`/v1/projects/${this.projectId}/trunks/${e}/endpoints/${t}`)).data}catch(o){throw this.handleError(o,`Failed to get endpoint ${t}`)}}async createEndpoint(e,t){try{return(await this.client.post(`/v1/projects/${this.projectId}/trunks/${e}/endpoints`,t)).data}catch(o){throw this.handleError(o,"Failed to create SIP endpoint")}}async updateEndpoint(e,t,o){try{return(await this.client.put(`/v1/projects/${this.projectId}/trunks/${e}/endpoints/${t}`,o)).data}catch(r){throw this.handleError(r,`Failed to update endpoint ${t}`)}}async deleteEndpoint(e,t){try{await this.client.delete(`/v1/projects/${this.projectId}/trunks/${e}/endpoints/${t}`)}catch(o){throw this.handleError(o,`Failed to delete endpoint ${t}`)}}async listAcls(e={}){try{let t={};return e.page&&(t.pageToken=e.page),e.pageSize&&(t.pageSize=e.pageSize),(await this.client.get(`/v1/projects/${this.projectId}/accessControlLists`,{params:t})).data}catch(t){throw this.handleError(t,"Failed to list ACLs")}}async getAcl(e){try{return(await this.client.get(`/v1/projects/${this.projectId}/accessControlLists/${e}`)).data}catch(t){throw this.handleError(t,`Failed to get ACL ${e}`)}}async createAcl(e){try{return(await this.client.post(`/v1/projects/${this.projectId}/accessControlLists`,e)).data}catch(t){throw this.handleError(t,"Failed to create ACL")}}async updateAcl(e,t){try{return(await this.client.put(`/v1/projects/${this.projectId}/accessControlLists/${e}`,t)).data}catch(o){throw this.handleError(o,`Failed to update ACL ${e}`)}}async deleteAcl(e){try{await this.client.delete(`/v1/projects/${this.projectId}/accessControlLists/${e}`)}catch(t){throw this.handleError(t,`Failed to delete ACL ${e}`)}}async getAclTrunks(e,t={}){try{let o={};return t.page&&(o.pageToken=t.page),t.pageSize&&(o.pageSize=t.pageSize),(await this.client.get(`/v1/projects/${this.projectId}/accessControlLists/${e}/trunks`,{params:o})).data}catch(o){throw this.handleError(o,`Failed to get trunks for ACL ${e}`)}}async listIpRanges(e,t={}){try{let o={};return t.page&&(o.pageToken=t.page),t.pageSize&&(o.pageSize=t.pageSize),(await this.client.get(`/v1/projects/${this.projectId}/accessControlLists/${e}/ipRanges`,{params:o})).data}catch(o){throw this.handleError(o,`Failed to list IP ranges for ACL ${e}`)}}async getIpRange(e,t){try{return(await this.client.get(`/v1/projects/${this.projectId}/accessControlLists/${e}/ipRanges/${t}`)).data}catch(o){throw this.handleError(o,`Failed to get IP range ${t}`)}}async addIpRange(e,t){try{return(await this.client.post(`/v1/projects/${this.projectId}/accessControlLists/${e}/ipRanges`,t)).data}catch(o){throw this.handleError(o,`Failed to add IP range to ACL ${e}`)}}async updateIpRange(e,t,o){try{return(await this.client.put(`/v1/projects/${this.projectId}/accessControlLists/${e}/ipRanges/${t}`,o)).data}catch(r){throw this.handleError(r,`Failed to update IP range ${t}`)}}async deleteIpRange(e,t){try{await this.client.delete(`/v1/projects/${this.projectId}/accessControlLists/${e}/ipRanges/${t}`)}catch(o){throw this.handleError(o,`Failed to delete IP range ${t}`)}}async listCountryPermissions(e={}){try{let t={};return e.page&&(t.pageToken=e.page),e.pageSize&&(t.pageSize=e.pageSize),(await this.client.get(`/v1/projects/${this.projectId}/countryPermissions`,{params:t})).data}catch(t){throw this.handleError(t,"Failed to list country permissions")}}async getCountryPermission(e){try{return(await this.client.get(`/v1/projects/${this.projectId}/countryPermissions/${e}`)).data}catch(t){throw this.handleError(t,`Failed to get country permission for ${e}`)}}async updateCountryPermission(e,t){try{return(await this.client.put(`/v1/projects/${this.projectId}/countryPermissions/${e}`,{enabled:t})).data}catch(o){throw this.handleError(o,`Failed to update country permission for ${e}`)}}async listTrunkAcls(e,t={}){try{let o={};return t.page&&(o.pageToken=t.page),t.pageSize&&(o.pageSize=t.pageSize),(await this.client.get(`/v1/projects/${this.projectId}/trunks/${e}/accessControlLists`,{params:o})).data}catch(o){throw this.handleError(o,`Failed to list ACLs for trunk ${e}`)}}async addTrunkAcl(e,t){try{await this.client.post(`/v1/projects/${this.projectId}/trunks/${e}/accessControlLists`,{accessControlListId:t})}catch(o){throw this.handleError(o,`Failed to add ACL ${t} to trunk ${e}`)}}async removeTrunkAcl(e,t){try{await this.client.delete(`/v1/projects/${this.projectId}/trunks/${e}/accessControlLists/${t}`)}catch(o){throw this.handleError(o,`Failed to remove ACL ${t} from trunk ${e}`)}}async getCredentialListTrunks(e,t={}){try{let o={};return t.page&&(o.pageNumber=t.page),t.pageSize&&(o.pageSize=t.pageSize),(await this.client.get(`/v1/projects/${this.projectId}/credentialLists/${e}/trunks`,{params:o})).data}catch(o){throw this.handleError(o,`Failed to get trunks for credential list ${e}`)}}async updateTrunkCredentialLists(e,t){try{return(await this.client.put(`/v1/projects/${this.projectId}/trunks/${e}/credentialLists`,{credentialListIds:t})).data}catch(o){throw this.handleError(o,`Failed to update credential lists for trunk ${e}`)}}async findCalls(e={}){try{let t={};return e.from&&(t.from=e.from),e.to&&(t.to=e.to),e.trunkId&&(t.trunkId=e.trunkId),e.createTime&&(t.createTime=e.createTime),e.callResult&&(t.callResult=e.callResult),e.direction&&(t.direction=e.direction),e.page&&(t.pageNumber=e.page),e.pageSize&&(t.pageSize=e.pageSize),(await this.client.get(`/v1/projects/${this.projectId}/calls`,{params:t})).data}catch(t){throw this.handleError(t,"Failed to find calls")}}async getCall(e){try{return(await this.client.get(`/v1/projects/${this.projectId}/calls/${e}`)).data}catch(t){throw this.handleError(t,`Failed to get call ${e}`)}}handleError(e,t){if(ai.default.isAxiosError(e)){let o=e;if(o.response){let r=o.response.status,s=o.response.data,a=s?.message||s?.error||o.message;throw r===401?new R('Authentication required. Please run "sinch auth login" first.',$.AUTH_REQUIRED):r===403?new R(`Permission denied: ${a}`,$.NO_PERMISSION):r===404?new R(`Resource not found: ${a}`,$.NOT_FOUND):r===429?new R(`Rate limited: ${a}`,$.UNAVAILABLE):r>=500?new R(`Server error: ${a}`,$.UNAVAILABLE):new R(`${t}: ${a}`,$.FAILURE)}else throw o.request?o.code==="ECONNREFUSED"?new R(`Cannot connect to EST API at ${this.baseUrl}`,$.UNAVAILABLE):o.code==="ETIMEDOUT"?new R(`Request timeout after ${this.timeout}ms`,$.TIMEOUT):new R(`${t}: No response from server (${o.code||"unknown error"})`,$.IO_ERROR):new R(`${t}: ${o.message}`,$.FAILURE)}else throw new R(`${t}: ${e.message||e}`,$.FAILURE)}}});var Fr=x((op,jr)=>{"use strict";var un=require("commander"),Ne=y(require("inquirer"));E();D();A();We();async function Oe(){await f.load(),await f.hasCredentials()||(n.error('Not authenticated. Run "sinch auth login" first.'),process.exit(1));let e=f.getApiConfig();return new oe({projectId:e.projectId,credentials:e.credentials})}function ci(i){n.info(`ID: ${i.id}`),n.info(`Name: ${i.name}`),i.hostName&&n.info(`Host: ${i.hostName}`),n.info(`Caller ID: ${i.enableCallerId?"enabled":"disabled"}`),i.createTime&&n.info(`Created: ${new Date(i.createTime).toLocaleString()}`),i.updateTime&&n.info(`Updated: ${new Date(i.updateTime).toLocaleString()}`)}var je=new un.Command("trunks");je.description("Manage SIP trunks");je.command("list").description("List all SIP trunks").option("-l, --limit <number>","Limit number of results",parseInt,50).option("--json","Output result as JSON").action(async i=>{try{let e=await Oe();c.start("Fetching SIP trunks...");let t=await e.listTrunks({pageSize:i.limit});c.succeed(`Retrieved ${t.trunks?.length||0} trunk(s)`),i.json?console.log(JSON.stringify(t,null,2)):(n.newline(),t.trunks&&t.trunks.length>0?t.trunks.forEach(o=>{n.info(`[${o.id}] ${o.name}`),o.hostName&&n.info(` Host: ${o.hostName}`),n.info(` Caller ID: ${o.enableCallerId?"enabled":"disabled"}`),n.newline()}):(n.info("No SIP trunks found"),n.newline(),n.info("Create one with: sinch sip trunks create")))}catch(e){c.stop(),n.error(`Failed to list trunks: ${e.message}`),process.exit(1)}});je.command("get").description("Get a SIP trunk by ID").argument("<trunk-id>","Trunk ID to retrieve").option("--json","Output result as JSON").action(async(i,e)=>{try{let t=await Oe();c.start("Fetching trunk...");let o=await t.getTrunk(i);c.succeed("Trunk retrieved"),e.json?console.log(JSON.stringify(o,null,2)):(n.newline(),ci(o))}catch(t){c.stop(),n.error(`Failed to get trunk: ${t.message}`),process.exit(1)}});je.command("create").description("Create a new SIP trunk").option("-n, --name <name>","Trunk name (required)").option("-h, --host-name <hostname>","Host name for the trunk (required)").option("--caller-id","Enable caller ID").option("--non-interactive","Skip prompts, use defaults for missing options").option("--json","Output result as JSON").action(async i=>{try{let e=i.name,t=i.hostName,o=i.callerId??!1,r=!i.nonInteractive;e||(r?e=(await Ne.default.prompt([{type:"input",name:"name",message:"Enter trunk name:",validate:p=>p?!0:"Trunk name is required"}])).name:(n.error("Name is required. Use --name <name>"),process.exit(1))),t||(r?t=(await Ne.default.prompt([{type:"input",name:"hostName",message:"Enter host name:",validate:p=>p?!0:"Host name is required"}])).hostName:(n.error("Host name is required. Use --host-name <hostname>"),process.exit(1))),i.callerId===void 0&&r&&(o=(await Ne.default.prompt([{type:"confirm",name:"enableCallerId",message:"Enable caller ID?",default:!1}])).enableCallerId);let s=await Oe();c.start("Creating SIP trunk...");let a=await s.createTrunk({name:e,hostName:t,enableCallerId:o});c.succeed("SIP trunk created successfully!"),i.json?console.log(JSON.stringify(a,null,2)):(n.newline(),ci(a),n.newline(),n.info(`Add an endpoint: sinch sip endpoints create ${a.id}`))}catch(e){c.stop(),n.error(`Failed to create trunk: ${e.message}`),process.exit(1)}});je.command("update").description("Update a SIP trunk").argument("<trunk-id>","Trunk ID to update").option("-n, --name <name>","New trunk name").option("-h, --host-name <hostname>","New host name").option("--caller-id","Enable caller ID").option("--no-caller-id","Disable caller ID").option("--non-interactive","Skip prompts, use current values for missing options").option("--json","Output result as JSON").action(async(i,e)=>{try{let t=await Oe();c.start("Fetching current trunk details...");let o=await t.getTrunk(i);c.stop();let r=e.name,s=e.hostName,a=e.callerId,l=!e.nonInteractive;r||(l?r=(await Ne.default.prompt([{type:"input",name:"name",message:"Enter trunk name:",default:o.name,validate:u=>u?!0:"Trunk name is required"}])).name:r=o.name),s===void 0&&(l?s=(await Ne.default.prompt([{type:"input",name:"hostName",message:"Enter host name:",default:o.hostName||""}])).hostName||void 0:s=o.hostName),a===void 0&&(l?a=(await Ne.default.prompt([{type:"confirm",name:"enableCallerId",message:"Enable caller ID?",default:o.enableCallerId??!1}])).enableCallerId:a=o.enableCallerId),c.start("Updating SIP trunk...");let p=await t.updateTrunk(i,{name:r,hostName:s,enableCallerId:a});c.succeed("SIP trunk updated successfully!"),e.json?console.log(JSON.stringify(p,null,2)):(n.newline(),ci(p))}catch(t){c.stop(),n.error(`Failed to update trunk: ${t.message}`),process.exit(1)}});je.command("delete").description("Delete a SIP trunk").argument("<trunk-id>","Trunk ID to delete").option("-f, --force","Skip confirmation prompt").action(async(i,e)=>{try{if(!e.force){let{confirm:o}=await Ne.default.prompt([{type:"confirm",name:"confirm",message:`Are you sure you want to delete trunk ${i}?`,default:!1}]);if(!o){n.info("Deletion cancelled");return}}let t=await Oe();c.start("Deleting SIP trunk..."),await t.deleteTrunk(i),c.succeed("SIP trunk deleted successfully")}catch(t){c.stop(),n.error(`Failed to delete trunk: ${t.message}`),process.exit(1)}});var Ht=new un.Command("acls");Ht.description("Manage ACLs for a trunk");Ht.command("list").description("List ACLs associated with a trunk").argument("<trunk-id>","Trunk ID").option("-l, --limit <number>","Limit number of results",parseInt,50).option("--json","Output result as JSON").action(async(i,e)=>{try{let t=await Oe();c.start("Fetching trunk ACLs...");let o=await t.listTrunkAcls(i,{pageSize:e.limit});c.succeed(`Retrieved ${o.accessControlLists?.length||0} ACL(s)`),e.json?console.log(JSON.stringify(o,null,2)):(n.newline(),o.accessControlLists&&o.accessControlLists.length>0?o.accessControlLists.forEach(r=>{let s=r.enabled!==!1?"":" (disabled)";n.info(`[${r.id}] ${r.name}${s}`),n.newline()}):(n.info("No ACLs associated with this trunk"),n.newline(),n.info(`Add an ACL: sinch sip trunks acls add ${i} <acl-id>`)))}catch(t){c.stop(),n.error(`Failed to list trunk ACLs: ${t.message}`),process.exit(1)}});Ht.command("add").description("Add an ACL to a trunk").argument("<trunk-id>","Trunk ID").argument("<acl-id>","ACL ID to add").option("--json","Output result as JSON").action(async(i,e,t)=>{try{let o=await Oe();c.start(`Adding ACL ${e} to trunk ${i}...`),await o.addTrunkAcl(i,e),c.succeed("ACL added to trunk successfully"),t.json||(n.newline(),n.info(`ACL ${e} is now associated with trunk ${i}`))}catch(o){c.stop(),n.error(`Failed to add ACL to trunk: ${o.message}`),process.exit(1)}});Ht.command("remove").description("Remove an ACL from a trunk").argument("<trunk-id>","Trunk ID").argument("<acl-id>","ACL ID to remove").option("-f, --force","Skip confirmation prompt").action(async(i,e,t)=>{try{if(!t.force){let{confirm:r}=await Ne.default.prompt([{type:"confirm",name:"confirm",message:`Remove ACL ${e} from trunk ${i}?`,default:!1}]);if(!r){n.info("Operation cancelled");return}}let o=await Oe();c.start("Removing ACL from trunk..."),await o.removeTrunkAcl(i,e),c.succeed("ACL removed from trunk successfully")}catch(o){c.stop(),n.error(`Failed to remove ACL from trunk: ${o.message}`),process.exit(1)}});je.addCommand(Ht);var li=new un.Command("credential-lists");li.description("Manage credential lists for a trunk");li.command("update").description("Bulk update credential lists for a trunk").argument("<trunk-id>","Trunk ID").argument("<credential-list-ids...>","Credential list IDs to assign (space-separated)").option("--json","Output result as JSON").action(async(i,e,t)=>{try{let o=await Oe();c.start(`Updating credential lists for trunk ${i}...`);let r=await o.updateTrunkCredentialLists(i,e);if(c.succeed("Credential lists updated successfully"),t.json)console.log(JSON.stringify(r,null,2));else{n.newline();let s=r?.credentialListIds??[];n.info(`Trunk ${i} now uses ${s.length} credential list(s):`),s.forEach(a=>{n.info(` - ${a}`)})}}catch(o){c.stop(),n.error(`Failed to update credential lists: ${o.message}`),process.exit(1)}});je.addCommand(li);jr.exports=je});var Ur=x((dp,_r)=>{"use strict";var Lr=require("commander"),ke=y(require("inquirer"));E();D();A();We();async function Wt(){await f.load(),await f.hasCredentials()||(n.error('Not authenticated. Run "sinch auth login" first.'),process.exit(1));let e=f.getApiConfig();return new oe({projectId:e.projectId,credentials:e.credentials})}async function di(i,e){c.start("Looking up endpoint...");let o=(await i.listTrunks()).trunks||[];for(let r of o)if(((await i.listEndpoints(r.id)).endpoints||[]).find(p=>p.id===e))return c.stop(),r.id;throw c.stop(),new Error(`Endpoint ${e} not found`)}function pi(i){if(n.info(`ID: ${i.id}`),n.info(`Name: ${i.name}`),i.address){let e=i.port?`${i.address}:${i.port}`:i.address;n.info(`Address: ${e}`)}i.transport&&n.info(`Transport: ${i.transport}`),n.info(`Priority: ${i.priority}`),n.info(`Enabled: ${i.enabled!==!1?"yes":"no"}`),i.createTime&&n.info(`Created: ${new Date(i.createTime).toLocaleString()}`),i.updateTime&&n.info(`Updated: ${new Date(i.updateTime).toLocaleString()}`)}var at=new Lr.Command("endpoints");at.description("Manage SIP endpoints");at.command("list").description("List all SIP endpoints for a trunk").argument("<trunk-id>","Trunk ID").option("-l, --limit <number>","Limit number of results",parseInt,50).option("--json","Output result as JSON").action(async(i,e)=>{try{let t=await Wt();c.start("Fetching SIP endpoints...");let o=await t.listEndpoints(i,{pageSize:e.limit});c.succeed(`Retrieved ${o.endpoints?.length||0} endpoint(s)`),e.json?console.log(JSON.stringify(o,null,2)):(n.newline(),o.endpoints&&o.endpoints.length>0?o.endpoints.forEach(r=>{let s=r.enabled!==!1?"":" (disabled)",a=r.port?`${r.address}:${r.port}`:r.address;n.info(`[${r.id}] ${r.name}${s}`),n.info(` Address: ${a||"N/A"}`),n.info(` Priority: ${r.priority}, Transport: ${r.transport||"UDP"}`),n.newline()}):(n.info("No endpoints found for this trunk"),n.newline(),n.info(`Create one with: sinch sip endpoints create ${i}`)))}catch(t){c.stop(),n.error(`Failed to list endpoints: ${t.message}`),process.exit(1)}});at.command("get").description("Get a SIP endpoint by ID").argument("<endpoint-id>","Endpoint ID to retrieve").option("--json","Output result as JSON").action(async(i,e)=>{try{let t=await Wt(),o=await di(t,i);c.start("Fetching endpoint...");let r=await t.getEndpoint(o,i);c.succeed("Endpoint retrieved"),e.json?console.log(JSON.stringify(r,null,2)):(n.newline(),pi(r))}catch(t){c.stop(),n.error(`Failed to get endpoint: ${t.message}`),process.exit(1)}});at.command("create").description("Create a new SIP endpoint").argument("<trunk-id>","Trunk ID to add endpoint to").option("-n, --name <name>","Endpoint name (required)").option("-a, --address <address>","SIP address (IP or hostname, without port)").option("--port <number>","SIP port (default: 5060)",parseInt).option("-t, --transport <transport>","Transport protocol: UDP, TCP, or TLS (default: UDP)").option("-p, --priority <number>","Priority (required, lower = higher priority)",parseInt).option("--non-interactive","Skip prompts, use defaults for missing options").option("--json","Output result as JSON").action(async(i,e)=>{try{let t=e.name,o=e.address,r=e.port,s=e.transport,a=e.priority,l=!e.nonInteractive;t||(l?t=(await ke.default.prompt([{type:"input",name:"name",message:"Enter endpoint name:",validate:m=>m?!0:"Endpoint name is required"}])).name:(n.error("Name is required. Use --name <name>"),process.exit(1))),o||(l?o=(await ke.default.prompt([{type:"input",name:"address",message:"Enter SIP address (IP or hostname):",validate:m=>m?!0:"SIP address is required"}])).address:(n.error("Address is required. Use --address <address>"),process.exit(1))),r===void 0&&l&&(r=(await ke.default.prompt([{type:"input",name:"port",message:"Enter SIP port (default 5060):",default:"5060",filter:m=>m?parseInt(m,10):5060}])).port),a===void 0&&(l?a=(await ke.default.prompt([{type:"input",name:"priority",message:"Enter priority (lower = higher priority):",default:"1",filter:m=>parseInt(m,10),validate:m=>{let w=parseInt(m,10);return isNaN(w)?"Please enter a valid number":!0}}])).priority:(n.error("Priority is required. Use --priority <number>"),process.exit(1)));let p=await Wt();c.start("Creating SIP endpoint...");let d=await p.createEndpoint(i,{name:t,address:o,port:r,transport:s,priority:a});c.succeed("SIP endpoint created successfully!"),e.json?console.log(JSON.stringify(d,null,2)):(n.newline(),pi(d))}catch(t){c.stop(),n.error(`Failed to create endpoint: ${t.message}`),process.exit(1)}});at.command("update").description("Update a SIP endpoint").argument("<endpoint-id>","Endpoint ID to update").option("-n, --name <name>","New endpoint name").option("-a, --address <address>","New SIP address").option("--port <number>","New SIP port",parseInt).option("-t, --transport <transport>","Transport protocol: UDP, TCP, or TLS").option("-p, --priority <number>","New priority",parseInt).option("--non-interactive","Skip prompts, use current values for missing options").option("--json","Output result as JSON").action(async(i,e)=>{try{let t=await Wt(),o=await di(t,i);c.start("Fetching current endpoint details...");let r=await t.getEndpoint(o,i);c.stop();let s=e.name,a=e.address,l=e.port,p=e.transport,d=e.priority,u=!e.nonInteractive;s||(u?s=(await ke.default.prompt([{type:"input",name:"name",message:"Enter endpoint name:",default:r.name,validate:h=>h?!0:"Name is required"}])).name:s=r.name),a||(u?a=(await ke.default.prompt([{type:"input",name:"address",message:"Enter SIP address:",default:r.address,validate:h=>h?!0:"SIP address is required"}])).address:a=r.address||""),l===void 0&&(u?l=(await ke.default.prompt([{type:"input",name:"port",message:"Enter SIP port:",default:(r.port||5060).toString(),filter:h=>parseInt(h,10)}])).port:l=r.port),d===void 0&&(u?d=(await ke.default.prompt([{type:"input",name:"priority",message:"Enter priority:",default:r.priority.toString(),filter:h=>parseInt(h,10)}])).priority:d=r.priority),c.start("Updating SIP endpoint...");let m=await t.updateEndpoint(o,i,{name:s,address:a,port:l,transport:p,priority:d});c.succeed("SIP endpoint updated successfully!"),e.json?console.log(JSON.stringify(m,null,2)):(n.newline(),pi(m))}catch(t){c.stop(),n.error(`Failed to update endpoint: ${t.message}`),process.exit(1)}});at.command("delete").description("Delete a SIP endpoint").argument("<endpoint-id>","Endpoint ID to delete").option("-f, --force","Skip confirmation prompt").action(async(i,e)=>{try{let t=await Wt(),o=await di(t,i);if(!e.force){let{confirm:r}=await ke.default.prompt([{type:"confirm",name:"confirm",message:`Are you sure you want to delete endpoint ${i}?`,default:!1}]);if(!r){n.info("Deletion cancelled");return}}c.start("Deleting SIP endpoint..."),await t.deleteEndpoint(o,i),c.succeed("SIP endpoint deleted successfully")}catch(t){c.stop(),n.error(`Failed to delete endpoint: ${t.message}`),process.exit(1)}});_r.exports=at});var Vr=x((yp,Mr)=>{"use strict";var ui=require("commander"),Y=y(require("inquirer"));E();D();A();We();async function Ae(){await f.load(),await f.hasCredentials()||(n.error('Not authenticated. Run "sinch auth login" first.'),process.exit(1));let e=f.getApiConfig();return new oe({projectId:e.projectId,credentials:e.credentials})}function fi(i){n.info(`ID: ${i.id}`),n.info(`Name: ${i.name}`),n.info(`Enabled: ${i.enabled!==!1?"yes":"no"}`),i.createTime&&n.info(`Created: ${new Date(i.createTime).toLocaleString()}`),i.updateTime&&n.info(`Updated: ${new Date(i.updateTime).toLocaleString()}`)}function qr(i){n.info(`ID: ${i.id}`),i.description&&n.info(`Description: ${i.description}`),i.ipAddress&&n.info(`IP Address: ${i.ipAddress}`),i.range&&n.info(`CIDR Range: ${i.range}`),i.createTime&&n.info(`Created: ${new Date(i.createTime).toLocaleString()}`)}function ct(i){return/^(\d{1,3}\.){3}\d{1,3}$/.test(i)?i.split(".").every(o=>{let r=parseInt(o,10);return r>=0&&r<=255}):!1}function fn(i){if(!/^(\d{1,3}\.){3}\d{1,3}\/\d{1,2}$/.test(i))return!1;let t=i.split("/");if(t.length!==2)return!1;let o=t[0],r=t[1];if(!o||!r)return!1;let s=parseInt(r,10);return ct(o)&&s>=0&&s<=32}var Fe=new ui.Command("acls");Fe.description("Manage Access Control Lists (ACLs)");Fe.command("list").description("List all Access Control Lists").option("-l, --limit <number>","Limit number of results",parseInt,50).option("--json","Output result as JSON").action(async i=>{try{let e=await Ae();c.start("Fetching ACLs...");let t=await e.listAcls({pageSize:i.limit});c.succeed(`Retrieved ${t.accessControlLists?.length||0} ACL(s)`),i.json?console.log(JSON.stringify(t,null,2)):(n.newline(),t.accessControlLists&&t.accessControlLists.length>0?t.accessControlLists.forEach(o=>{let r=o.enabled!==!1?"":" (disabled)";n.info(`[${o.id}] ${o.name}${r}`),n.newline()}):(n.info("No ACLs found"),n.newline(),n.info("Create one with: sinch sip acls create")))}catch(e){c.stop(),n.error(`Failed to list ACLs: ${e.message}`),process.exit(1)}});Fe.command("get").description("Get an ACL by ID").argument("<acl-id>","ACL ID to retrieve").option("--json","Output result as JSON").action(async(i,e)=>{try{let t=await Ae();c.start("Fetching ACL...");let o=await t.getAcl(i);c.succeed("ACL retrieved"),e.json?console.log(JSON.stringify(o,null,2)):(n.newline(),fi(o))}catch(t){c.stop(),n.error(`Failed to get ACL: ${t.message}`),process.exit(1)}});Fe.command("create").description("Create a new Access Control List").option("-n, --name <name>","ACL name (required)").option("--enabled","Enable the ACL (default: true)").option("--disabled","Create ACL in disabled state").option("-i, --ip <address>","IP address for initial IP range (required)").option("-r, --range <cidr>","CIDR mask for IP range (default: 32)",parseInt).option("--ip-description <text>","Description for the IP range").option("--non-interactive","Skip prompts, use defaults for missing options").option("--json","Output result as JSON").action(async i=>{try{let e=i.name,t=i.enabled??!i.disabled,o=i.ip,r=i.range,s=i.ipDescription,a=!i.nonInteractive;e||(a?e=(await Y.default.prompt([{type:"input",name:"name",message:"Enter ACL name:",validate:m=>m?!0:"ACL name is required"}])).name:(n.error("Name is required. Use --name <name>"),process.exit(1))),i.enabled===void 0&&!i.disabled&&a&&(t=(await Y.default.prompt([{type:"confirm",name:"enabled",message:"Enable ACL?",default:!0}])).enabled),o?ct(o)||(n.error(`Invalid IP address format: ${o}`),process.exit(1)):a?o=(await Y.default.prompt([{type:"input",name:"ipAddress",message:"Enter IP address for initial IP range (required):",validate:m=>m?ct(m)?!0:"Invalid IP address format":"At least one IP range is required to create an ACL"}])).ipAddress:(n.error("IP address is required. Use --ip <address>"),process.exit(1)),r===void 0&&a&&(r=(await Y.default.prompt([{type:"input",name:"range",message:"Enter CIDR mask (default 32):",default:"32",filter:m=>parseInt(m,10),validate:m=>{let w=parseInt(m,10);return!isNaN(w)&&w>=0&&w<=32?!0:"Please enter a number between 0 and 32"}}])).range),s===void 0&&a&&(s=(await Y.default.prompt([{type:"input",name:"description",message:"Enter IP range description (optional):"}])).description||void 0);let l=await Ae(),p={ipAddress:o};r!==void 0&&(p.range=r),s&&(p.description=s),c.start("Creating ACL...");let d=await l.createAcl({name:e,enabled:t,ipRanges:[p]});c.succeed("ACL created successfully!"),i.json?console.log(JSON.stringify(d,null,2)):(n.newline(),fi(d),n.newline(),n.info(`Add an IP range: sinch sip acls ip-ranges add ${d.id}`))}catch(e){c.stop(),n.error(`Failed to create ACL: ${e.message}`),process.exit(1)}});Fe.command("update").description("Update an ACL").argument("<acl-id>","ACL ID to update").option("-n, --name <name>","New ACL name").option("--enabled","Enable the ACL").option("--disabled","Disable the ACL").option("--non-interactive","Skip prompts, use current values for missing options").option("--json","Output result as JSON").action(async(i,e)=>{try{let t=await Ae();c.start("Fetching current ACL details...");let o=await t.getAcl(i);c.stop();let r=e.name,s;e.enabled?s=!0:e.disabled&&(s=!1);let a=!e.nonInteractive;r||(a?r=(await Y.default.prompt([{type:"input",name:"name",message:"Enter ACL name:",default:o.name,validate:d=>d?!0:"ACL name is required"}])).name:r=o.name),s===void 0&&(a?s=(await Y.default.prompt([{type:"confirm",name:"enabled",message:"Enable ACL?",default:o.enabled??!0}])).enabled:s=o.enabled),c.start("Updating ACL...");let l=await t.updateAcl(i,{name:r,enabled:s});c.succeed("ACL updated successfully!"),e.json?console.log(JSON.stringify(l,null,2)):(n.newline(),fi(l))}catch(t){c.stop(),n.error(`Failed to update ACL: ${t.message}`),process.exit(1)}});Fe.command("delete").description("Delete an ACL").argument("<acl-id>","ACL ID to delete").option("-f, --force","Skip confirmation prompt").action(async(i,e)=>{try{if(!e.force){let{confirm:o}=await Y.default.prompt([{type:"confirm",name:"confirm",message:`Are you sure you want to delete ACL ${i}?`,default:!1}]);if(!o){n.info("Deletion cancelled");return}}let t=await Ae();c.start("Deleting ACL..."),await t.deleteAcl(i),c.succeed("ACL deleted successfully")}catch(t){c.stop(),n.error(`Failed to delete ACL: ${t.message}`),process.exit(1)}});Fe.command("trunks").description("List trunks using an ACL").argument("<acl-id>","ACL ID").option("-l, --limit <number>","Limit number of results",parseInt,50).option("--json","Output result as JSON").action(async(i,e)=>{try{let t=await Ae();c.start("Fetching trunks...");let o=await t.getAclTrunks(i,{pageSize:e.limit});c.succeed(`Retrieved ${o.trunks?.length||0} trunk(s)`),e.json?console.log(JSON.stringify(o,null,2)):(n.newline(),o.trunks&&o.trunks.length>0?o.trunks.forEach(r=>{n.info(`[${r.id}] ${r.name}`),r.hostName&&n.info(` Host: ${r.hostName}`),n.newline()}):n.info("No trunks are using this ACL"))}catch(t){c.stop(),n.error(`Failed to list trunks: ${t.message}`),process.exit(1)}});var It=new ui.Command("ip-ranges");It.description("Manage IP ranges for ACLs");It.command("list").description("List IP ranges for an ACL").argument("<acl-id>","ACL ID").option("-l, --limit <number>","Limit number of results",parseInt,50).option("--json","Output result as JSON").action(async(i,e)=>{try{let t=await Ae();c.start("Fetching IP ranges...");let o=await t.listIpRanges(i,{pageSize:e.limit});c.succeed(`Retrieved ${o.ipRanges?.length||0} IP range(s)`),e.json?console.log(JSON.stringify(o,null,2)):(n.newline(),o.ipRanges&&o.ipRanges.length>0?o.ipRanges.forEach(r=>{let s=r.range||r.ipAddress||"N/A";n.info(`[${r.id}] ${s}`),r.description&&n.info(` ${r.description}`),n.newline()}):(n.info("No IP ranges found for this ACL"),n.newline(),n.info(`Add one with: sinch sip acls ip-ranges add ${i}`)))}catch(t){c.stop(),n.error(`Failed to list IP ranges: ${t.message}`),process.exit(1)}});It.command("add").description("Add an IP range to an ACL").argument("<acl-id>","ACL ID").option("-d, --description <description>","Description for the IP range").option("-i, --ip <ip>","Single IP address (e.g., 192.168.1.1)").option("-r, --range <cidr>","CIDR range (e.g., 192.168.1.0/24)").option("--non-interactive","Skip prompts, use defaults for missing options").option("--json","Output result as JSON").action(async(i,e)=>{try{let t=e.description,o=e.ip,r=e.range,s=!e.nonInteractive;o&&r&&(n.error("Cannot specify both --ip and --range. Please provide only one."),process.exit(1)),!o&&!r&&(s?(await Y.default.prompt([{type:"list",name:"type",message:"What would you like to add?",choices:[{name:"Single IP address",value:"ip"},{name:"CIDR range",value:"range"}]}])).type==="ip"?o=(await Y.default.prompt([{type:"input",name:"ipAddress",message:"Enter IP address (e.g., 192.168.1.1):",validate:m=>m?ct(m)?!0:"Invalid IP address format":"IP address is required"}])).ipAddress:r=(await Y.default.prompt([{type:"input",name:"range",message:"Enter CIDR range (e.g., 192.168.1.0/24):",validate:m=>m?fn(m)?!0:"Invalid CIDR format (e.g., 192.168.1.0/24)":"CIDR range is required"}])).range:(n.error("Either --ip or --range is required"),process.exit(1))),o&&!ct(o)&&(n.error(`Invalid IP address format: ${o}`),process.exit(1)),r&&!fn(r)&&(n.error(`Invalid CIDR range format: ${r}. Expected format: 192.168.1.0/24`),process.exit(1)),!t&&s&&(t=(await Y.default.prompt([{type:"input",name:"description",message:"Enter description (optional):"}])).description||void 0);let a=await Ae();c.start("Adding IP range...");let l={description:t};o?l.ipAddress=o:r&&(l.range=r);let p=await a.addIpRange(i,l);c.succeed("IP range added successfully!"),e.json?console.log(JSON.stringify(p,null,2)):(n.newline(),qr(p))}catch(t){c.stop(),n.error(`Failed to add IP range: ${t.message}`),process.exit(1)}});It.command("update").description("Update an IP range").argument("<acl-id>","ACL ID").argument("<ip-range-id>","IP range ID to update").option("-d, --description <description>","New description").option("-i, --ip <ip>","New single IP address").option("-r, --range <cidr>","New CIDR range").option("--non-interactive","Skip prompts, use current values for missing options").option("--json","Output result as JSON").action(async(i,e,t)=>{try{let o=await Ae();c.start("Fetching current IP range details...");let r;try{r=await o.getIpRange(i,e)}catch(m){c.stop(),n.error(`IP range ${e} not found in ACL ${i}: ${m.message}`),process.exit(1)}c.stop();let s=t.description,a=t.ip,l=t.range,p=!t.nonInteractive;if(a&&l&&(n.error("Cannot specify both --ip and --range. Please provide only one."),process.exit(1)),s===void 0&&p?s=(await Y.default.prompt([{type:"input",name:"description",message:"Enter description:",default:r.description||""}])).description||void 0:s===void 0&&(s=r.description),!a&&!l&&p){let m=r.range||r.ipAddress||"",w=r.range?"range":"ip";(await Y.default.prompt([{type:"list",name:"type",message:"Update as:",choices:[{name:"Single IP address",value:"ip"},{name:"CIDR range",value:"range"}],default:w}])).type==="ip"?(a=(await Y.default.prompt([{type:"input",name:"ipAddress",message:"Enter IP address:",default:w==="ip"?m:"",validate:v=>v?ct(v)?!0:"Invalid IP address format":"IP address is required"}])).ipAddress,l=void 0):(l=(await Y.default.prompt([{type:"input",name:"range",message:"Enter CIDR range:",default:w==="range"?m:"",validate:v=>v?fn(v)?!0:"Invalid CIDR format":"CIDR range is required"}])).range,a=void 0)}else!a&&!l?(a=r.ipAddress,l=r.range):a?l=void 0:l&&(a=void 0);a&&!ct(a)&&(n.error(`Invalid IP address format: ${a}`),process.exit(1)),l&&!fn(l)&&(n.error(`Invalid CIDR range format: ${l}`),process.exit(1)),c.start("Updating IP range...");let d={description:s};a?d.ipAddress=a:l&&(d.range=l);let u=await o.updateIpRange(i,e,d);c.succeed("IP range updated successfully!"),t.json?console.log(JSON.stringify(u,null,2)):(n.newline(),qr(u))}catch(o){c.stop(),n.error(`Failed to update IP range: ${o.message}`),process.exit(1)}});It.command("delete").description("Delete an IP range").argument("<acl-id>","ACL ID").argument("<ip-range-id>","IP range ID to delete").option("-f, --force","Skip confirmation prompt").action(async(i,e,t)=>{try{if(!t.force){let{confirm:r}=await Y.default.prompt([{type:"confirm",name:"confirm",message:`Are you sure you want to delete IP range ${e}?`,default:!1}]);if(!r){n.info("Deletion cancelled");return}}let o=await Ae();c.start("Deleting IP range..."),await o.deleteIpRange(i,e),c.succeed("IP range deleted successfully")}catch(o){c.stop(),n.error(`Failed to delete IP range: ${o.message}`),process.exit(1)}});Fe.addCommand(It);Mr.exports=Fe});var Kr=x((Ip,Br)=>{"use strict";var Jr=require("commander");E();D();A();We();async function mn(){await f.load(),await f.hasCredentials()||(n.error('Not authenticated. Run "sinch auth login" first.'),process.exit(1));let e=f.getApiConfig();return new oe({projectId:e.projectId,credentials:e.credentials})}function mi(i){n.info(`ISO Code: ${i.isoCode}`),n.info(`Country: ${i.name}`),n.info(`Continent: ${i.continent}`),n.info(`Dialing Codes: ${i.countryDialingCodes.join(", ")}`),n.info(`Status: ${i.enabled?"enabled":"disabled"}`)}var $t=new Jr.Command("countries");$t.description("Manage country permissions for dialing");$t.command("list").description("List all country permissions").option("-l, --limit <number>","Limit number of results",parseInt,50).option("--json","Output result as JSON").action(async i=>{try{let e=await mn();c.start("Fetching country permissions...");let t=await e.listCountryPermissions({pageSize:i.limit});c.succeed(`Retrieved ${t.countryPermissions?.length||0} country permission(s)`),i.json?console.log(JSON.stringify(t,null,2)):(n.newline(),t.countryPermissions&&t.countryPermissions.length>0?([...t.countryPermissions].sort((r,s)=>r.isoCode.localeCompare(s.isoCode)).forEach(r=>{let s=r.enabled?"\u2713 enabled":"\u2717 disabled",a=r.name.padEnd(30);n.info(`${r.isoCode.padEnd(4)} ${a} ${s}`)}),n.newline(),n.info("Enable a country: sinch sip countries enable <iso-code>"),n.info("Disable a country: sinch sip countries disable <iso-code>")):n.info("No country permissions found"))}catch(e){c.stop(),n.error(`Failed to list country permissions: ${e.message}`),process.exit(1)}});$t.command("get").description("Get a specific country permission by ISO code").argument("<iso-code>","ISO country code (e.g., US, CA, *)").option("--json","Output result as JSON").action(async(i,e)=>{try{let t=await mn();c.start("Fetching country permission...");let o=await t.getCountryPermission(i.toUpperCase());c.succeed("Country permission retrieved"),e.json?console.log(JSON.stringify(o,null,2)):(n.newline(),mi(o))}catch(t){c.stop(),n.error(`Failed to get country permission: ${t.message}`),process.exit(1)}});$t.command("enable").description("Enable a country for dialing").argument("<iso-code>","ISO country code (e.g., US, CA, *)").option("--json","Output result as JSON").action(async(i,e)=>{try{let t=await mn();c.start(`Enabling country ${i.toUpperCase()}...`);let o=await t.updateCountryPermission(i.toUpperCase(),!0);c.succeed(`Country ${i.toUpperCase()} enabled for dialing`),e.json?console.log(JSON.stringify(o,null,2)):(n.newline(),mi(o),n.newline(),n.info(`Country ${i.toUpperCase()} is now enabled for dialing`))}catch(t){c.stop(),n.error(`Failed to enable country: ${t.message}`),process.exit(1)}});$t.command("disable").description("Disable a country for dialing").argument("<iso-code>","ISO country code (e.g., US, CA, *)").option("--json","Output result as JSON").action(async(i,e)=>{try{let t=await mn();c.start(`Disabling country ${i.toUpperCase()}...`);let o=await t.updateCountryPermission(i.toUpperCase(),!1);c.succeed(`Country ${i.toUpperCase()} disabled for dialing`),e.json?console.log(JSON.stringify(o,null,2)):(n.newline(),mi(o),n.newline(),n.info(`Country ${i.toUpperCase()} is now disabled for dialing`))}catch(t){c.stop(),n.error(`Failed to disable country: ${t.message}`),process.exit(1)}});Br.exports=$t});var zr=x((xp,Wr)=>{"use strict";var Hr=require("commander");E();D();A();We();async function tc(){await f.load(),await f.hasCredentials()||(n.error('Not authenticated. Run "sinch auth login" first.'),process.exit(1));let e=f.getApiConfig();return new oe({projectId:e.projectId,credentials:e.credentials})}var gi=new Hr.Command("credential-lists");gi.description("Manage credential list relationships");gi.command("trunks").description("Get trunks using a credential list").argument("<credential-list-id>","Credential list ID").option("-l, --limit <number>","Limit number of results",parseInt,50).option("--json","Output result as JSON").action(async(i,e)=>{try{let t=await tc();c.start("Fetching trunks using credential list...");let o=await t.getCredentialListTrunks(i,{pageSize:e.limit});c.succeed(`Retrieved ${o.trunks?.length||0} trunk(s)`),e.json?console.log(JSON.stringify(o,null,2)):(n.newline(),o.trunks&&o.trunks.length>0?(n.info(`Trunks using credential list ${i}:`),n.newline(),o.trunks.forEach(r=>{n.info(`[${r.id}] ${r.name}`),r.hostName&&n.info(` Host: ${r.hostName}`),n.info(` Caller ID: ${r.enableCallerId?"enabled":"disabled"}`),n.newline()}),o.totalItems&&n.info(`Total: ${o.totalItems} trunk(s)`)):n.info("No trunks found using this credential list"))}catch(t){c.stop(),n.error(`Failed to get trunks for credential list: ${t.message}`),process.exit(1)}});Wr.exports=gi});var Zr=x((_p,zt)=>{"use strict";var Gr=require("commander");E();D();A();We();vt();async function Yr(){await f.load(),await f.hasCredentials()||(n.error('Not authenticated. Run "sinch auth login" first.'),process.exit(1));let e=f.getApiConfig();return new oe({projectId:e.projectId,credentials:e.credentials})}function Xr(i){if(!i){let t=new Date;return`>=${new Date(t.getTime()-1440*60*1e3).toISOString()}`}if(i.startsWith(">=")||i.startsWith("<=")||i.startsWith(">")||i.startsWith("<"))return i;let e=i.split("-");if(e.length===1&&e[0]){let t=e[0];return`>=${t}-01-01T00:00:00Z,<=${t}-12-31T23:59:59Z`}else if(e.length===2&&e[0]&&e[1]){let t=e[0],o=e[1],r=new Date(parseInt(t),parseInt(o),0).getDate();return`>=${t}-${o}-01T00:00:00Z,<=${t}-${o}-${r.toString().padStart(2,"0")}T23:59:59Z`}else return`>=${i}T00:00:00Z,<=${i}T23:59:59Z`}function gn(i){if(i===void 0||i===0)return"-";let e=Math.floor(i/3600),t=Math.floor(i%3600/60),o=i%60;return e>0?`${e}h ${t}m ${o}s`:t>0?`${t}m ${o}s`:`${o}s`}function hi(i){return!i||!i.amount?"-":`${parseFloat(i.amount).toFixed(4)} ${i.currencyCode}`}function nc(i,e=!1){n.info(`Call ID: ${i.callId}`),n.info(`From: ${_(i.from)}`),n.info(`To: ${_(i.to)}`),n.info(`Direction: ${i.direction}`),n.info(`Status: ${i.callResult||"In Progress"}`),(e||i.durationSeconds)&&n.info(`Duration: ${gn(i.durationSeconds)}`),(e||i.billingDurationSeconds)&&n.info(`Billing Duration: ${gn(i.billingDurationSeconds)}`),i.price&&n.info(`Cost: ${hi(i.price)}`),n.info(`Trunk ID: ${i.trunkId}`),n.info(`Created: ${new Date(i.createTime).toLocaleString()}`),i.answerTime&&n.info(`Answered: ${new Date(i.answerTime).toLocaleString()}`),i.endTime&&n.info(`Ended: ${new Date(i.endTime).toLocaleString()}`)}var hn=new Gr.Command("calls");hn.description("View call history and details");hn.command("list").description("List calls with filtering options").option("--from <number>","Filter by originating phone number (supports partial matching)").option("--to <number>","Filter by destination phone number (supports partial matching)").option("--trunk-id <id>","Filter by trunk ID").option("--direction <direction>","Filter by direction (INBOUND or OUTBOUND)").option("--result <result>","Filter by call result (COMPLETED, NO_ANSWER, CANCEL, BUSY, FAILED)").option("--date <date>","Filter by date (YYYY-MM-DD, YYYY-MM, or YYYY). Defaults to last 24 hours.").option("--page <number>","Page number",parseInt).option("--page-size <number>","Number of results per page (max 1000)",parseInt,100).option("--json","Output result as JSON").action(async i=>{try{let e=await Yr(),t={pageSize:i.pageSize};if(i.from&&(t.from=i.from),i.to&&(t.to=i.to),i.trunkId&&(t.trunkId=i.trunkId),i.direction&&(["INBOUND","OUTBOUND"].includes(i.direction.toUpperCase())||(n.error("Invalid direction. Must be INBOUND or OUTBOUND."),process.exit(1)),t.direction=i.direction.toUpperCase()),i.result){let r=["COMPLETED","NO_ANSWER","CANCEL","BUSY","FAILED"];r.includes(i.result.toUpperCase())||(n.error(`Invalid result. Must be one of: ${r.join(", ")}`),process.exit(1)),t.callResult=i.result.toUpperCase()}i.page&&(t.page=i.page),t.createTime=Xr(i.date),c.start("Fetching calls...");let o=await e.findCalls(t);c.succeed(`Retrieved ${o.calls?.length||0} call(s)`),i.json?console.log(JSON.stringify(o,null,2)):(n.newline(),o.calls&&o.calls.length>0?(o.calls.forEach(r=>{let s=gn(r.durationSeconds),a=r.callResult||"In Progress",l=hi(r.price);n.info(`${r.callId}`),n.info(` ${_(r.from)} \u2192 ${_(r.to)}`),n.info(` ${r.direction} | ${a} | ${s} | ${l}`),n.info(` ${new Date(r.createTime).toLocaleString()}`),n.newline()}),o.totalItems&&(n.info(`Total: ${o.totalItems} call(s)`),o.pageNumber&&n.info(`Page: ${o.pageNumber}`))):(n.info("No calls found matching the filters"),n.newline(),n.info("Try adjusting your filters or date range.")))}catch(e){c.fail("Failed to fetch calls"),n.error(e.message),process.exit(1)}});hn.command("get").description("Get details of a specific call").argument("<call-id>","Call ID").option("--json","Output result as JSON").action(async(i,e)=>{try{let t=await Yr();c.start(`Fetching call ${i}...`);let o=await t.getCall(i);c.succeed("Call retrieved"),e.json?console.log(JSON.stringify(o,null,2)):(n.newline(),nc(o,!0))}catch(t){c.fail("Failed to get call"),n.error(t.message),process.exit(1)}});zt.exports=hn;zt.exports.parseDateFilter=Xr;zt.exports.formatDuration=gn;zt.exports.formatPrice=hi});var ts=x((Up,es)=>{"use strict";var Qr=require("commander"),ic=Fr(),oc=Ur(),rc=Vr(),sc=Kr(),ac=zr(),cc=Zr(),ze=new Qr.Command("sip");ze.description("Manage Elastic SIP Trunking resources");ze.addCommand(ic);ze.addCommand(oc);ze.addCommand(rc);ze.addCommand(sc);ze.addCommand(ac);ze.addCommand(cc);es.exports=ze});var os=x((Bp,is)=>{"use strict";var ns=require("commander"),fe=y(require("inquirer"));E();D();A();vt();async function yn(){return await f.load(),await f.hasCredentials()||(n.error('Not authenticated. Run "sinch auth login" first.'),process.exit(1)),(await f.createSinchClient()).numbers}function yi(i){n.info(`Phone Number: ${_(i.phoneNumber)}`),i.displayName&&n.info(`Display Name: ${i.displayName}`),n.info(`Region: ${i.regionCode}`),n.info(`Type: ${i.type}`),n.info(`Capabilities: ${i.capability?.join(", ")||"none"}`),i.money&&n.info(`Cost: ${i.money.amount} ${i.money.currencyCode}/month`),i.nextChargeDate&&n.info(`Next Charge: ${new Date(i.nextChargeDate).toLocaleDateString()}`),i.expireAt&&n.info(`Expires: ${new Date(i.expireAt).toLocaleDateString()}`),i.smsConfiguration&&(n.info(`SMS Service Plan: ${i.smsConfiguration.servicePlanId||"n/a"}`),i.smsConfiguration.campaignId&&n.info(`SMS Campaign: ${i.smsConfiguration.campaignId}`)),i.voiceConfiguration&&(n.info(`Voice Type: ${i.voiceConfiguration.type||"n/a"}`),i.voiceConfiguration.appId&&n.info(`Voice App: ${i.voiceConfiguration.appId}`),i.voiceConfiguration.trunkId&&n.info(`EST Trunk: ${i.voiceConfiguration.trunkId}`)),i.callbackUrl&&n.info(`Callback: ${i.callbackUrl}`)}var Pt=new ns.Command("active");Pt.description("Manage your active phone numbers");Pt.command("list").description("List all active numbers for this project").option("-r, --region <code>","Filter by region code (e.g. US, GB, SE)").option("-t, --type <type>","Filter by type: MOBILE, LOCAL, or TOLL_FREE").option("-c, --capability <cap...>","Filter by capability: SMS, VOICE").option("-p, --pattern <digits>","Filter by digit pattern").option("--search-pattern <mode>","Pattern match mode: START, CONTAINS, or END").option("-l, --limit <number>","Max results",parseInt).option("--order-by <field>","Sort by: phoneNumber or displayName").option("--non-interactive","Skip prompts, require all options as flags").option("--json","Output result as JSON").action(async i=>{try{let e=!i.nonInteractive,t=i.region,o=i.type;!t&&e&&(t=(await fe.default.prompt([{type:"input",name:"regionCode",message:"Region code to filter by (e.g. US, GB, SE) \u2014 leave blank for all:"}])).regionCode||void 0),!o&&e&&(o=(await fe.default.prompt([{type:"list",name:"type",message:"Filter by number type?",choices:[{name:"All types",value:""},{name:"MOBILE",value:"MOBILE"},{name:"LOCAL",value:"LOCAL"},{name:"TOLL_FREE",value:"TOLL_FREE"}]}])).type||void 0);let r=await yn();c.start("Fetching active numbers...");let s=i.limit||100,a=[],l={};t&&(l.regionCode=t),o&&(l.type=o),i.capability&&(l.capability=i.capability),i.pattern&&(l["numberPattern.pattern"]=i.pattern),i.searchPattern&&(l["numberPattern.searchPattern"]=i.searchPattern),i.limit&&(l.pageSize=i.limit),i.orderBy&&(l.orderBy=i.orderBy);for await(let d of r.list(l))if(a.push(d),a.length>=s)break;let p=a.length;c.succeed(`Found ${p} active number(s)`),i.json?console.log(JSON.stringify(a,null,2)):(n.newline(),p>0?a.forEach(d=>{let u=d.capability?.join(", ")||"",m=d.displayName?` "${d.displayName}"`:"";console.log(`${_(d.phoneNumber)}${m} [${d.regionCode}] ${d.type} ${u}`)}):(n.info("No active numbers found for this project."),n.newline(),n.info("Search for available numbers: sinch numbers available search")))}catch(e){c.stop(),n.error(`Failed to list active numbers: ${e.message}`),process.exit(1)}});Pt.command("get").description("Get details for a specific active number").argument("[phone-number]","Phone number in E.164 format (e.g. +12025550134)").option("--non-interactive","Skip prompts").option("--json","Output result as JSON").action(async(i,e)=>{try{let t=!e.nonInteractive;i||(t?i=(await fe.default.prompt([{type:"input",name:"phoneNumber",message:"Enter the phone number (E.164 format, e.g. +12025550134):",validate:a=>a?a.startsWith("+")?!0:"Phone number must start with + (E.164 format)":"Phone number is required"}])).phoneNumber:(n.error("Phone number is required. Usage: sinch numbers active get <phone-number>"),process.exit(1)));let o=await yn();c.start(`Fetching number ${i}...`);let r=await o.get({phoneNumber:i});c.succeed("Number retrieved"),e.json?console.log(JSON.stringify(r,null,2)):(n.newline(),yi(r))}catch(t){c.stop(),n.error(`Failed to get number: ${t.message}`),process.exit(1)}});Pt.command("update").description("Update an active phone number (display name, SMS/Voice config)").argument("[phone-number]","Phone number in E.164 format").option("-d, --display-name <name>","New display name").option("--sms-service-plan <id>","SMS service plan ID (empty string to unlink)").option("--sms-campaign <id>","SMS campaign ID").option("--voice-app <id>","Voice app ID").option("--callback-url <url>","Callback URL for provisioning events").option("--non-interactive","Skip prompts").option("--json","Output result as JSON").action(async(i,e)=>{try{let t=!e.nonInteractive;i||(t?i=(await fe.default.prompt([{type:"input",name:"phoneNumber",message:"Which number do you want to update? (E.164 format):",validate:h=>h?h.startsWith("+")?!0:"Phone number must start with + (E.164 format)":"Phone number is required"}])).phoneNumber:(n.error("Phone number is required. Usage: sinch numbers active update <phone-number>"),process.exit(1)));let o=await yn();c.start(`Fetching current details for ${i}...`);let r=await o.get({phoneNumber:i});c.stop();let s=e.displayName,a=e.smsServicePlan,l=e.smsCampaign,p=e.voiceApp,d=e.callbackUrl;if(t){n.newline(),n.info(`Current configuration for ${i}:`),yi(r),n.newline(),s===void 0&&(s=(await fe.default.prompt([{type:"input",name:"displayName",message:"Display name:",default:r.displayName||""}])).displayName||void 0),d===void 0&&(d=(await fe.default.prompt([{type:"input",name:"callbackUrl",message:"Callback URL (leave blank to keep current):",default:r.callbackUrl||""}])).callbackUrl||void 0);let w=await fe.default.prompt([{type:"checkbox",name:"configure",message:"Which configurations do you want to update?",choices:[{name:"SMS Configuration",value:"sms"},{name:"Voice Configuration",value:"voice"}]}]);if(w.configure.includes("sms")&&a===void 0){let h=await fe.default.prompt([{type:"input",name:"servicePlanId",message:"SMS service plan ID (empty to unlink):",default:r.smsConfiguration?.servicePlanId||""},{type:"input",name:"campaignId",message:"SMS campaign ID (for US numbers):",default:r.smsConfiguration?.campaignId||""}]);a=h.servicePlanId,l=h.campaignId||void 0}w.configure.includes("voice")&&p===void 0&&(p=(await fe.default.prompt([{type:"input",name:"appId",message:"Voice app ID:",default:r.voiceConfiguration?.appId||""}])).appId||void 0)}let u={};if(s!==void 0&&(u.displayName=s),d!==void 0&&(u.callbackUrl=d),a!==void 0&&(u.smsConfiguration={servicePlanId:a},l&&(u.smsConfiguration.campaignId=l)),p!==void 0&&(u.voiceConfiguration={type:"RTC",appId:p}),Object.keys(u).length===0){n.info("No changes specified. Nothing to update.");return}c.start(`Updating ${i}...`);let m=await o.update({phoneNumber:i,updateActiveNumberRequestBody:u});c.succeed("Number updated successfully!"),e.json?console.log(JSON.stringify(m,null,2)):(n.newline(),yi(m))}catch(t){c.stop(),n.error(`Failed to update number: ${t.message}`),process.exit(1)}});Pt.command("release").description("Release (cancel subscription for) an active number").argument("[phone-number]","Phone number in E.164 format").option("-f, --force","Skip confirmation prompt").option("--non-interactive","Skip prompts").option("--json","Output result as JSON").action(async(i,e)=>{try{let t=!e.nonInteractive;if(i||(t?i=(await fe.default.prompt([{type:"input",name:"phoneNumber",message:"Which number do you want to release? (E.164 format):",validate:a=>a?a.startsWith("+")?!0:"Phone number must start with + (E.164 format)":"Phone number is required"}])).phoneNumber:(n.error("Phone number is required. Usage: sinch numbers active release <phone-number>"),process.exit(1))),!e.force){let{confirm:s}=await fe.default.prompt([{type:"confirm",name:"confirm",message:`Are you sure you want to release ${i}? This will cancel your subscription.`,default:!1}]);if(!s){n.info("Release cancelled");return}}let o=await yn();c.start(`Releasing ${i}...`);let r=await o.release({phoneNumber:i});c.succeed(`Number ${i} released`),e.json?console.log(JSON.stringify(r,null,2)):(n.newline(),n.info(`${i} has been released from your project.`))}catch(t){c.stop(),n.error(`Failed to release number: ${t.message}`),process.exit(1)}});is.exports=Pt});var ls=x((Yp,cs)=>{"use strict";var rs=require("commander"),k=y(require("inquirer"));E();D();A();We();vt();async function lc(){let i=f.getApiConfig();return new oe({projectId:i.projectId,credentials:i.credentials})}async function ss(){try{c.start("Fetching EST trunks...");let e=await(await lc()).listTrunks({pageSize:50});c.stop();let t=e.trunks||[];if(t.length===0){console.log("No trunks found. You can create one with: sinch sip trunks create");let{trunkId:s}=await k.default.prompt([{type:"input",name:"trunkId",message:"Enter trunk ID manually:",validate:a=>a?!0:"Trunk ID is required for EST"}]);return s}let o=t.map(s=>({name:`${s.name||s.id}${s.hostName?` (${s.hostName})`:""}`,value:s.id}));o.push(new k.default.Separator),o.push({name:"Enter trunk ID manually",value:"__manual__"});let{selected:r}=await k.default.prompt([{type:"list",name:"selected",message:"Select a trunk:",choices:o}]);if(r==="__manual__"){let{trunkId:s}=await k.default.prompt([{type:"input",name:"trunkId",message:"Enter trunk ID:",validate:a=>a?!0:"Trunk ID is required"}]);return s}return r}catch{c.stop();let{trunkId:i}=await k.default.prompt([{type:"input",name:"trunkId",message:"EST trunk ID (could not fetch trunk list):",validate:e=>e?!0:"Trunk ID is required for EST"}]);return i}}async function as(){try{c.start("Fetching fax services...");let i=await f.createSinchClient(),e=[];for await(let r of i.fax.services.list({projectId:f.getApiConfig().projectId}))e.push(r);if(c.stop(),e.length===0){console.log("No fax services found.");let{serviceId:r}=await k.default.prompt([{type:"input",name:"serviceId",message:"Enter fax service ID manually:",validate:s=>s?!0:"Service ID is required for FAX"}]);return r}let t=e.map(r=>({name:`${r.name||r.id}${r.defaultForProject?" (default)":""}`,value:r.id}));t.push(new k.default.Separator),t.push({name:"Enter service ID manually",value:"__manual__"});let{selected:o}=await k.default.prompt([{type:"list",name:"selected",message:"Select a fax service:",choices:t}]);if(o==="__manual__"){let{serviceId:r}=await k.default.prompt([{type:"input",name:"serviceId",message:"Enter fax service ID:",validate:s=>s?!0:"Service ID is required"}]);return r}return o}catch{c.stop();let{serviceId:i}=await k.default.prompt([{type:"input",name:"serviceId",message:"Fax service ID (could not fetch service list):",validate:e=>e?!0:"Service ID is required for FAX"}]);return i}}async function Cn(){return await f.load(),await f.hasCredentials()||(n.error('Not authenticated. Run "sinch auth login" first.'),process.exit(1)),(await f.createSinchClient()).numbers}function wn(i){let e=i.capability?.join(", ")||"",t=i.setupPrice?`${i.setupPrice.amount} ${i.setupPrice.currencyCode} setup`:"",o=i.monthlyPrice?`${i.monthlyPrice.amount} ${i.monthlyPrice.currencyCode}/mo`:"",r=[t,o].filter(Boolean).join(" + "),s=i.supportingDocumentationRequired?" [docs required]":"";return`${_(i.phoneNumber)} ${e} ${r}${s}`}async function dc(i,e){let t,o,r,{configureSms:s}=await k.default.prompt([{type:"confirm",name:"configureSms",message:"Configure SMS for this number?",default:!1}]);if(s){let m=await k.default.prompt([{type:"input",name:"servicePlanId",message:"SMS service plan ID:",validate:w=>w?!0:"Service plan ID is required for SMS"},{type:"input",name:"campaignId",message:"SMS campaign ID (required for US, optional otherwise):"}]);t={servicePlanId:m.servicePlanId},m.campaignId&&(t.campaignId=m.campaignId)}let{voiceType:a}=await k.default.prompt([{type:"list",name:"voiceType",message:"Voice configuration:",choices:[{name:"None (configure later)",value:"none"},{name:"RTC \u2014 Real-time Communication",value:"RTC"},{name:"EST \u2014 Elastic SIP Trunking",value:"EST"},{name:"FAX",value:"FAX"}]}]);if(a==="RTC"){let{appId:m}=await k.default.prompt([{type:"input",name:"appId",message:"Voice app ID:",validate:w=>w?!0:"Voice app ID is required"}]);o={type:"RTC",appId:m}}else a==="EST"?o={type:"EST",trunkId:await ss()}:a==="FAX"&&(o={type:"FAX",serviceId:await as()});r=(await k.default.prompt([{type:"input",name:"callbackUrl",message:"Callback URL for provisioning events (optional):"}])).callbackUrl||void 0;let{confirm:p}=await k.default.prompt([{type:"confirm",name:"confirm",message:`Rent ${_(e)}? This will activate it on your project.`,default:!0}]);if(!p){console.log("Rental cancelled.");return}let d={};t&&(d.smsConfiguration=t),o&&(d.voiceConfiguration=o),r&&(d.callbackUrl=r),c.start(`Renting ${e}...`);let u=await i.rent({phoneNumber:e,rentNumberRequestBody:d});c.succeed(`${_(u.phoneNumber)} rented successfully!`),console.log(),console.log(` Phone Number: ${_(u.phoneNumber)}`),console.log(` Region: ${u.regionCode}`),console.log(` Type: ${u.type}`),console.log(` Capabilities: ${u.capability?.join(", ")}`),u.money&&console.log(` Cost: ${u.money.amount} ${u.money.currencyCode}/month`),console.log(),console.log(`Manage this number: sinch numbers active get ${e}`)}var kt=new rs.Command("available");kt.description("Search and rent available phone numbers");kt.command("search").description("Search for available phone numbers to rent").option("-r, --region <code>","Region code (required, e.g. US, GB, SE)").option("-t, --type <type>","Number type (required): MOBILE, LOCAL, or TOLL_FREE").option("-c, --capabilities <cap...>","Capabilities: SMS, VOICE").option("-p, --pattern <digits>","Digit pattern to match").option("--search-pattern <mode>","Pattern match: START, CONTAINS, or END").option("-s, --size <number>","Max results",parseInt).option("--non-interactive","Skip prompts, require all options as flags").option("--json","Output result as JSON").action(async i=>{try{let e=!i.nonInteractive,t=i.region,o=i.type,r=i.capabilities;if(t||(e?t=(await k.default.prompt([{type:"input",name:"regionCode",message:"Region code (e.g. US, GB, SE):",default:"US"}])).regionCode.toUpperCase():(n.error("Region code is required. Use --region <code>"),process.exit(1))),o||(e?o=(await k.default.prompt([{type:"list",name:"type",message:"What type of number?",choices:[{name:"LOCAL \u2014 assigned to a geographic region",value:"LOCAL"},{name:"MOBILE \u2014 belongs to a mobile range",value:"MOBILE"},{name:"TOLL_FREE \u2014 free for the caller",value:"TOLL_FREE"}]}])).type:(n.error("Number type is required. Use --type <MOBILE|LOCAL|TOLL_FREE>"),process.exit(1))),!r&&e){let u=await k.default.prompt([{type:"checkbox",name:"capabilities",message:"Required capabilities:",choices:[{name:"SMS",value:"SMS",checked:!0},{name:"VOICE",value:"VOICE"}]}]);r=u.capabilities.length>0?u.capabilities:void 0}let s=i.pattern,a=i.searchPattern;!s&&e&&(s=(await k.default.prompt([{type:"input",name:"pattern",message:"Digit pattern to search for (leave blank for any):"}])).pattern||void 0,s&&!a&&(a=(await k.default.prompt([{type:"list",name:"searchPattern",message:"Where should the pattern appear?",choices:[{name:"Starts with these digits",value:"START"},{name:"Contains these digits",value:"CONTAINS"},{name:"Ends with these digits",value:"END"}]}])).searchPattern));let l=await Cn();c.start(`Searching for ${o} numbers in ${t}...`);let p=await l.searchForAvailableNumbers({regionCode:t,type:o,capabilities:r,"numberPattern.pattern":s,"numberPattern.searchPattern":a,size:i.size}),d=p.availableNumbers?.length||0;if(c.succeed(`Found ${d} available number(s)`),i.json)console.log(JSON.stringify(p,null,2));else if(d===0)console.log(),console.log("No numbers found matching your criteria."),console.log("Try a different region, type, or relax your pattern filter.");else if(e){let u=p.availableNumbers.map(w=>({name:wn(w),value:w.phoneNumber}));u.push(new k.default.Separator),u.push({name:"Exit without renting",value:""});let{selected:m}=await k.default.prompt([{type:"list",name:"selected",message:`Select a number to rent (${d} available):`,choices:u,pageSize:Math.min(d+2,20)}]);m&&await dc(l,m)}else console.log(),p.availableNumbers.forEach(u=>console.log(wn(u)))}catch(e){c.stop(),n.error(`Failed to search numbers: ${e.message}`),process.exit(1)}});kt.command("check").description("Check if a specific phone number is available").argument("[phone-number]","Phone number in E.164 format").option("--non-interactive","Skip prompts").option("--json","Output result as JSON").action(async(i,e)=>{try{let t=!e.nonInteractive;i||(t?i=(await k.default.prompt([{type:"input",name:"phoneNumber",message:"Enter the phone number to check (E.164, e.g. +12025550134):",validate:a=>a?a.startsWith("+")?!0:"Must be in E.164 format (starts with +)":"Phone number is required"}])).phoneNumber:(n.error("Phone number is required. Usage: sinch numbers available check <phone-number>"),process.exit(1)));let o=await Cn();c.start(`Checking availability for ${i}...`);let r=await o.checkAvailability({phoneNumber:i});c.succeed("Number is available!"),e.json?console.log(JSON.stringify(r,null,2)):(console.log(),console.log(wn(r)),console.log(),console.log(`Rent this number: sinch numbers available rent ${i}`))}catch(t){c.stop(),n.error(`${t.message}`),process.exit(1)}});kt.command("rent").description("Rent (activate) a specific phone number").argument("[phone-number]","Phone number in E.164 format").option("--sms-service-plan <id>","SMS service plan ID").option("--sms-campaign <id>","SMS campaign ID (for US numbers)").option("--voice-app <id>","Voice app ID (for RTC)").option("--voice-type <type>","Voice config type: RTC, EST, or FAX").option("--trunk-id <id>","EST trunk ID (when voice-type is EST)").option("--callback-url <url>","Callback URL for provisioning events").option("-f, --force","Skip confirmation").option("--non-interactive","Skip all prompts").option("--json","Output result as JSON").action(async(i,e)=>{try{let t=!e.nonInteractive;i||(t?i=(await k.default.prompt([{type:"input",name:"phoneNumber",message:"Which number do you want to rent? (E.164 format):",validate:u=>u?u.startsWith("+")?!0:"Must be in E.164 format (starts with +)":"Phone number is required"}])).phoneNumber:(n.error("Phone number is required. Usage: sinch numbers available rent <phone-number>"),process.exit(1)));let o=await Cn();if(t){c.start(`Checking availability for ${i}...`);try{let d=await o.checkAvailability({phoneNumber:i});c.succeed("Number is available"),console.log(),console.log(wn(d)),console.log()}catch{c.fail("Number may not be available"),n.warn("Could not verify availability. Proceeding anyway..."),n.newline()}}let r,s,a=e.callbackUrl;if(e.smsServicePlan&&(r={servicePlanId:e.smsServicePlan},e.smsCampaign&&(r.campaignId=e.smsCampaign)),(e.voiceApp||e.trunkId)&&(s={type:e.voiceType||"RTC"},e.voiceApp&&(s.appId=e.voiceApp),e.trunkId&&(s.trunkId=e.trunkId)),t&&!r&&!s){let{configureSms:d}=await k.default.prompt([{type:"confirm",name:"configureSms",message:"Configure SMS for this number?",default:!1}]);if(d){let m=await k.default.prompt([{type:"input",name:"servicePlanId",message:"SMS service plan ID:",validate:w=>w?!0:"Service plan ID is required for SMS"},{type:"input",name:"campaignId",message:"SMS campaign ID (required for US, optional otherwise):"}]);r={servicePlanId:m.servicePlanId},m.campaignId&&(r.campaignId=m.campaignId)}let{voiceType:u}=await k.default.prompt([{type:"list",name:"voiceType",message:"Voice configuration:",choices:[{name:"None (configure later)",value:"none"},{name:"RTC \u2014 Real-time Communication",value:"RTC"},{name:"EST \u2014 Elastic SIP Trunking",value:"EST"},{name:"FAX",value:"FAX"}]}]);if(u==="RTC"){let{appId:m}=await k.default.prompt([{type:"input",name:"appId",message:"Voice app ID:",validate:w=>w?!0:"Voice app ID is required"}]);s={type:"RTC",appId:m}}else u==="EST"?s={type:"EST",trunkId:await ss()}:u==="FAX"&&(s={type:"FAX",serviceId:await as()});a||(a=(await k.default.prompt([{type:"input",name:"callbackUrl",message:"Callback URL for provisioning events (optional):"}])).callbackUrl||void 0)}if(!e.force){let{confirm:d}=await k.default.prompt([{type:"confirm",name:"confirm",message:`Rent ${i}? This will activate it on your project.`,default:!0}]);if(!d){n.info("Rental cancelled");return}}let l={};r&&(l.smsConfiguration=r),s&&(l.voiceConfiguration=s),a&&(l.callbackUrl=a),c.start(`Renting ${i}...`);let p=await o.rent({phoneNumber:i,rentNumberRequestBody:l});c.succeed(`Number ${i} rented successfully!`),e.json?console.log(JSON.stringify(p,null,2)):(console.log(),console.log(` Phone Number: ${_(p.phoneNumber)}`),console.log(` Region: ${p.regionCode}`),console.log(` Type: ${p.type}`),console.log(` Capabilities: ${p.capability?.join(", ")}`),p.money&&console.log(` Cost: ${p.money.amount} ${p.money.currencyCode}/month`),console.log(),console.log(`Manage this number: sinch numbers active get ${i}`))}catch(t){c.stop(),n.error(`Failed to rent number: ${t.message}`),process.exit(1)}});kt.command("rent-any").description("Rent any number matching your criteria (US LOCAL only)").option("-r, --region <code>","Region code (required)").option("-t, --type <type>","Number type (required): MOBILE, LOCAL, or TOLL_FREE").option("-c, --capabilities <cap...>","Capabilities: SMS, VOICE").option("-p, --pattern <digits>","Digit pattern to match").option("--search-pattern <mode>","Pattern match: START, CONTAINS, or END").option("--sms-service-plan <id>","SMS service plan ID").option("--sms-campaign <id>","SMS campaign ID").option("--voice-app <id>","Voice app ID").option("--callback-url <url>","Callback URL").option("-f, --force","Skip confirmation").option("--non-interactive","Skip all prompts").option("--json","Output result as JSON").action(async i=>{try{let e=!i.nonInteractive,t=i.region,o=i.type,r=i.capabilities;if(t||(e?t=(await k.default.prompt([{type:"input",name:"regionCode",message:"Region code (e.g. US, GB, SE):",default:"US"}])).regionCode.toUpperCase():(n.error("Region code is required. Use --region <code>"),process.exit(1))),o||(e?o=(await k.default.prompt([{type:"list",name:"type",message:"Number type:",choices:[{name:"LOCAL",value:"LOCAL"},{name:"MOBILE",value:"MOBILE"},{name:"TOLL_FREE",value:"TOLL_FREE"}]}])).type:(n.error("Number type is required. Use --type <MOBILE|LOCAL|TOLL_FREE>"),process.exit(1))),!r&&e){let m=await k.default.prompt([{type:"checkbox",name:"capabilities",message:"Required capabilities:",choices:[{name:"SMS",value:"SMS",checked:!0},{name:"VOICE",value:"VOICE"}]}]);r=m.capabilities.length>0?m.capabilities:void 0}let s,a;if(i.smsServicePlan)s={servicePlanId:i.smsServicePlan},i.smsCampaign&&(s.campaignId=i.smsCampaign);else if(e&&(await k.default.prompt([{type:"confirm",name:"configureSms",message:"Configure SMS for this number?",default:!1}])).configureSms){let w=await k.default.prompt([{type:"input",name:"servicePlanId",message:"SMS service plan ID:",validate:h=>h?!0:"Required"},{type:"input",name:"campaignId",message:"SMS campaign ID (optional):"}]);s={servicePlanId:w.servicePlanId},w.campaignId&&(s.campaignId=w.campaignId)}i.voiceApp&&(a={type:"RTC",appId:i.voiceApp});let l=i.callbackUrl;if(!l&&e&&(l=(await k.default.prompt([{type:"input",name:"callbackUrl",message:"Callback URL (optional):"}])).callbackUrl||void 0),!i.force){let{confirm:m}=await k.default.prompt([{type:"confirm",name:"confirm",message:`Rent any available ${o} number in ${t}?`,default:!0}]);if(!m){n.info("Rental cancelled");return}}let p=await Cn(),d={regionCode:t,type:o};r&&(d.capabilities=r),i.pattern&&(d.numberPattern={pattern:i.pattern,searchPattern:i.searchPattern||"CONTAINS"}),s&&(d.smsConfiguration=s),a&&(d.voiceConfiguration=a),l&&(d.callbackUrl=l),c.start(`Finding and renting a ${o} number in ${t}...`);let u=await p.rentAny({rentAnyNumberRequestBody:d});c.succeed(`Rented ${u.phoneNumber}!`),i.json?console.log(JSON.stringify(u,null,2)):(console.log(),console.log(` Phone Number: ${_(u.phoneNumber)}`),console.log(` Region: ${u.regionCode}`),console.log(` Type: ${u.type}`),console.log(` Capabilities: ${u.capability?.join(", ")}`),u.money&&console.log(` Cost: ${u.money.amount} ${u.money.currencyCode}/month`),console.log(),console.log(`Manage this number: sinch numbers active get ${u.phoneNumber}`))}catch(e){c.stop(),n.error(`Failed to rent number: ${e.message}`),process.exit(1)}});cs.exports=kt});var us=x((eu,ps)=>{"use strict";var ds=require("commander");E();D();A();async function pc(){return await f.load(),await f.hasCredentials()||(n.error('Not authenticated. Run "sinch auth login" first.'),process.exit(1)),(await f.createSinchClient()).numbers}var wi=new ds.Command("regions");wi.description("List regions where numbers are available");wi.command("list").description("List all available regions for phone numbers").option("-t, --types <type...>","Filter by number type: MOBILE, LOCAL, TOLL_FREE").option("--json","Output result as JSON").action(async i=>{try{let e=await pc();c.start("Fetching available regions...");let t=await e.availableRegions.list({types:i.types}),o=t.availableRegions?.length||0;c.succeed(`Found ${o} region(s)`),i.json?console.log(JSON.stringify(t,null,2)):(n.newline(),o>0?t.availableRegions.forEach(r=>{console.log(`${r.regionCode} ${r.regionName} [${r.types?.join(", ")}]`)}):n.info("No regions found."))}catch(e){c.stop(),n.error(`Failed to list regions: ${e.message}`),process.exit(1)}});ps.exports=wi});var gs=x((tu,ms)=>{"use strict";var fs=require("commander"),uc=os(),fc=ls(),mc=us(),Gt=new fs.Command("numbers");Gt.description("Manage Sinch phone numbers \u2014 search, rent, update, and release");Gt.addCommand(uc);Gt.addCommand(fc);Gt.addCommand(mc);ms.exports=Gt});async function me(i){let e={};for(let t of i){if(t.when!==void 0&&!(typeof t.when=="function"?await t.when(e):t.when))continue;let o;switch(t.type){case"input":{let r=await(0,Se.input)({message:t.message,default:t.default,validate:t.validate});t.filter&&(r=t.filter(r)),o=r;break}case"password":o=await(0,Se.password)({message:t.message,validate:t.validate});break;case"confirm":o=await(0,Se.confirm)({message:t.message,default:t.default});break;case"list":o=await(0,Se.select)({message:t.message,choices:(t.choices||[]).map(r=>typeof r=="string"?{name:r,value:r}:r),default:t.default,pageSize:t.pageSize});break;case"checkbox":o=await(0,Se.checkbox)({message:t.message,choices:(t.choices||[]).map(r=>typeof r=="string"?{name:r,value:r}:r),pageSize:t.pageSize});break;default:throw new Error(`Unsupported prompt type: ${t.type}`)}e[t.name]=o}return e}var Se,hs=W(()=>{"use strict";Se=require("@inquirer/prompts")});var ys,Ci,vi,ws=W(()=>{"use strict";ys=require("@sinch/sdk-core");A();Ci=class{client=null;initialized=!1;async initialize(){if(!(this.initialized&&this.client))try{await f.load();let e=await f.getCredentials();if(!e)throw new Error("Not authenticated. Please run: sinch auth login");this.client=new ys.SinchClient({projectId:e.projectId,keyId:e.keyId,keySecret:e.keySecret}),this.initialized=!0}catch(e){throw new Error(`Failed to initialize fax client: ${e.message}`)}}async getClient(){return this.initialized||await this.initialize(),this.client}isInitialized(){return this.initialized}async getServiceConfig(){return await f.load(),{serviceId:f.getFaxServiceId(),senderNumber:f.getFaxSenderNumber()}}async validateConfig(){let e=await this.getServiceConfig(),t=[];return e.serviceId||t.push("fax service ID (set with: sinch config set fax service-id <id>)"),{valid:t.length===0,missing:t}}},vi=new Ci});var Ps={};xe(Ps,{FaxManager:()=>vn,default:()=>hc,getFaxClient:()=>Is,getFaxManager:()=>Le});async function Is(){try{return await f.load(),await f.hasCredentials()||(n.error("Not authenticated. Please run: sinch auth login"),process.exit(1)),await vi.initialize(),await vi.getClient()}catch(i){n.error(`Failed to initialize fax client: ${i.message}`),process.exit(1)}}async function Le(){let i=await Is(),e=await f.getFaxCredentials();return new vn(i,e)}async function gc(){let i=vs.platform();try{if(i==="darwin")return(0,Yt.execSync)(`osascript -e '${`
122
+ `);St.command("install").description("Install Sinch skills for AI coding assistants").option("--claude","Install for Claude Code only").option("--copilot","Install for GitHub Copilot only (requires --project)").option("--project","Install to current project (for team sharing via git)").option("--link","Symlink instead of copy (for development)").option("--force","Overwrite existing skills without prompting").action(async i=>{try{let e=Ir();V.default.existsSync(e)||(n.error("Skills source not found. This may indicate a corrupted CLI installation."),n.info(`Expected path: ${e}`),process.exit(1));let t=ie.default.join(e,"sinch-functions");V.default.existsSync(t)||(n.error("Skill source not found."),process.exit(1));let o=0,r=0,s=i.claude||!i.claude&&!i.copilot,a=i.copilot||!i.claude&&!i.copilot&&i.project;if(s){if(!i.project||i.claude){let l=ui();V.default.existsSync(ie.default.join(l,"SKILL.md"))&&!i.force?(n.warn(`Claude Code skill already installed at ${l}`),n.info("Use --force to overwrite"),r++):(await V.default.ensureDir(ie.default.dirname(l)),i.link&&process.platform!=="win32"?(V.default.existsSync(l)&&await V.default.remove(l),await V.default.symlink(t,l,"junction"),n.success(`Linked Claude Code skill to ${l}`)):(await V.default.copy(t,l,{overwrite:!0}),n.success(`Installed Claude Code skill to ${l}`)),o++)}if(i.project){let l=fi();V.default.existsSync(ie.default.join(l,"SKILL.md"))&&!i.force?(n.warn(`Claude Code project skill already installed at ${l}`),n.info("Use --force to overwrite"),r++):(await V.default.ensureDir(ie.default.dirname(l)),await V.default.copy(t,l,{overwrite:!0}),n.success(`Installed Claude Code skill to ${l}`),o++)}}if(a&&i.project){let l=mi();V.default.existsSync(ie.default.join(l,"SKILL.md"))&&!i.force?(n.warn(`Copilot skill already installed at ${l}`),n.info("Use --force to overwrite"),r++):(await V.default.ensureDir(ie.default.dirname(l)),await V.default.copy(t,l,{overwrite:!0}),n.success(`Installed Copilot skill to ${l}`),o++)}else i.copilot&&!i.project&&(n.warn("Copilot requires --project flag (no global installation supported)"),n.info("Use: sinch skills install --copilot --project"));n.info(""),o>0&&n.success(`Installed ${o} skill(s)`),r>0&&n.info(`Skipped ${r} existing skill(s)`),o>0&&(n.info(""),n.info(B.default.bold("Next steps:")),s&&(n.info(` ${B.default.cyan("\u2022")} Claude Code will now have Sinch expertise`),n.info(` ${B.default.cyan("\u2022")} Ask about voice IVRs, SVAML, or CLI commands`)),a&&i.project&&(n.info(` ${B.default.cyan("\u2022")} Copilot will use Sinch patterns for code suggestions`),n.info(` ${B.default.cyan("\u2022")} Commit .github/skills/ to share with team`)))}catch(e){n.error("Failed to install skills:",e.message),process.exit(1)}});St.command("list").description("Show installed skill locations").action(async()=>{try{let i=$r({project:!0}),e=i.filter(a=>a.type==="global"),t=i.filter(a=>a.type==="project");n.info(B.default.bold(`Sinch Skills Installation Status
123
+ `)),n.info(B.default.underline("Global (personal machine):"));let o=!1;for(let a of e)a.installed?(n.info(` ${B.default.green("\u2713")} ${a.tool}: ${B.default.gray(a.path)}`),o=!0):n.info(` ${B.default.gray("\u25CB")} ${a.tool}: ${B.default.gray("not installed")}`);o||n.info(` ${B.default.gray("No global skills installed")}`),n.info(""),n.info(B.default.underline("Project (current directory):"));let r=!1;for(let a of t)a.installed?(n.info(` ${B.default.green("\u2713")} ${a.tool}: ${B.default.gray(a.path)}`),r=!0):n.info(` ${B.default.gray("\u25CB")} ${a.tool}: ${B.default.gray("not installed")}`);r||n.info(` ${B.default.gray("No project skills installed")}`),n.info(""),i.some(a=>a.installed)||(n.info("Run `sinch skills install` to install skills globally"),n.info("Run `sinch skills install --project` to install for this project"))}catch(i){n.error("Failed to list skills:",i.message),process.exit(1)}});St.command("uninstall").description("Remove installed Sinch skills").option("--claude","Uninstall from Claude Code only").option("--copilot","Uninstall from GitHub Copilot only").option("--project","Uninstall from current project only").option("--all","Uninstall from all locations").action(async i=>{try{let e=0,t=!i.claude&&!i.copilot&&!i.project&&!i.all,o=i.all||t,r=i.project&&!i.all&&!t,s=i.claude||o||r,a=i.copilot||o||r;if(s){if(!r){let l=ui();V.default.existsSync(l)&&(await V.default.remove(l),n.success(`Removed Claude Code skill from ${l}`),e++)}if(r||o){let l=fi();V.default.existsSync(l)&&(await V.default.remove(l),n.success(`Removed Claude Code skill from ${l}`),e++)}}if(a&&(r||o)){let l=mi();V.default.existsSync(l)&&(await V.default.remove(l),n.success(`Removed Copilot skill from ${l}`),e++)}n.info(""),e>0?n.success(`Removed ${e} skill(s)`):n.info("No skills found to remove")}catch(e){n.error("Failed to uninstall skills:",e.message),process.exit(1)}});St.command("update").description("Update skills to latest version").option("--project","Update project skills as well").action(async i=>{try{n.info(`Updating Sinch skills...
124
+ `);let t=$r({project:i.project}).filter(a=>a.installed);if(t.length===0){n.info("No skills installed. Run `sinch skills install` first.");return}let o=Ir(),r=ie.default.join(o,"sinch-functions"),s=0;for(let a of t)await V.default.copy(r,a.path,{overwrite:!0}),n.success(`Updated ${a.tool} (${a.type})`),s++;n.info(""),n.success(`Updated ${s} skill(s)`)}catch(e){n.error("Failed to update skills:",e.message),process.exit(1)}});Pr.exports=St});async function vc(){await f.load(),await f.hasCredentials()||(n.error('Not authenticated. Run "sinch auth login" first.'),process.exit(1))}async function U(){return await vc(),await f.createSinchClient()}function bt(i){let e=i||f.get("conversation-app-id");return e||(n.error("No Conversation App ID configured."),n.info("Set default: sinch config set conversation-app-id <id>"),n.info("Or specify: --app <app-id>"),process.exit(1)),e}var at=G(()=>{"use strict";E();T()});var Rr=N((sp,Nr)=>{"use strict";var Er=require("commander"),kr=y(require("inquirer"));T();R();at();var Tr=new Er.Command("send");Tr.description("Send a message via Conversation API").argument("[recipient]","Recipient phone number (e.g., +15551234567)").argument("[message]","Message text to send").option("-c, --channel <channel>","Channel (SMS, WHATSAPP, MESSENGER, etc.)","SMS").option("-a, --app <app-id>","Conversation App ID (uses default if configured)").option("-m, --media <url>","Media URL for media messages").option("--caption <text>","Caption for media messages").option("-t, --template <name>","Template name for template messages").option("-p, --params <json>","Template parameters as JSON string").option("--location","Send location message").option("--lat <latitude>","Latitude for location messages",parseFloat).option("--lng <longitude>","Longitude for location messages",parseFloat).option("-n, --name <name>","Location name").option("--json","Output result as JSON").action(async(i,e,t)=>{try{let o=await U();if(!i||!e&&!t?.media&&!t?.template&&!t?.location){let s=await kr.default.prompt([{type:"input",name:"recipient",message:"Enter recipient phone number:",when:!i,validate:a=>a?a.startsWith("+")?!0:"Phone number must start with +":"Recipient is required"},{type:"input",name:"message",message:"Enter message:",when:!e&&!t?.media&&!t?.template&&!t?.location,validate:a=>a?!0:"Message is required"},{type:"list",name:"channel",message:"Select channel:",choices:["SMS","WHATSAPP","MESSENGER","INSTAGRAM","VIBER","TELEGRAM","RCS","LINE"],default:t?.channel||"SMS",when:!t?.channel}]);i=i||s.recipient,e=e||s.message,s.channel&&(t={...t,channel:s.channel})}let r=bt(t?.app);c.start("Sending message...");try{let s;if(t?.location)(!t.lat||!t.lng)&&(c.fail("Location messages require --lat and --lng"),process.exit(1)),s=await o.conversation.messages.send({sendMessageRequestBody:{app_id:r,recipient:{identified_by:{channel_identities:[{channel:t.channel||"SMS",identity:i}]}},message:{location_message:{coordinates:{latitude:t.lat,longitude:t.lng},title:t.name}}}});else if(t?.template){let a=t.params?JSON.parse(t.params):{};s=await o.conversation.messages.send({sendMessageRequestBody:{app_id:r,recipient:{identified_by:{channel_identities:[{channel:t.channel||"WHATSAPP",identity:i}]}},message:{template_message:{template_reference:{template_id:t.template,version:a.version||"1"},parameters:a}}}})}else t?.media?s=await o.conversation.messages.send({sendMessageRequestBody:{app_id:r,recipient:{identified_by:{channel_identities:[{channel:t.channel||"WHATSAPP",identity:i}]}},message:{media_message:{url:t.media,caption:t.caption}}}}):s=await o.conversation.messages.send({sendMessageRequestBody:{app_id:r,recipient:{identified_by:{channel_identities:[{channel:t?.channel||"SMS",identity:i}]}},message:{text_message:{text:e}}}});c.succeed("Message sent successfully!"),t?.json?console.log(JSON.stringify(s,null,2)):(n.newline(),n.info(`Message ID: ${s.message_id}`),n.info(`Recipient: ${i}`),n.info(`Channel: ${t?.channel||"SMS"}`))}catch(s){c.fail("Failed to send message"),n.error(`Error: ${s.message}`),(s.message?.includes("WHATSAPP")||s.message?.includes("channel not configured"))&&(n.newline(),n.info("To use WhatsApp, configure WhatsApp credentials in your Conversation app:"),n.info(" 1. Visit https://dashboard.sinch.com/convapi/apps"),n.info(" 2. Add WhatsApp channel credentials"),n.info(" 3. Verify your WhatsApp Business Account"),n.newline(),n.info("Or use SMS (no additional setup required):"),n.info(` sinch conversation send ${i} "${e}"`)),process.exit(1)}}catch(o){c.stop(),n.error(`Failed to send message: ${o.message}`),process.exit(1)}});Nr.exports=Tr});var Or=N((dp,xr)=>{"use strict";var Dr=require("commander");T();R();at();var Yt=new Dr.Command("messages");Yt.description("Manage conversation messages");Yt.command("get").description("Get a specific message by ID").argument("<message-id>","Message ID to retrieve").option("--json","Output result as JSON").action(async(i,e)=>{try{let t=await U();c.start("Fetching message...");let o=await t.conversation.messages.get({message_id:i});c.succeed("Message retrieved"),e.json?console.log(JSON.stringify(o,null,2)):(n.newline(),n.info(`Message ID: ${o.id}`),n.info(`Direction: ${o.direction}`),n.info(`Channel: ${o.channel_identity?.channel||"N/A"}`),n.info(`Contact ID: ${o.contact_id||"N/A"}`),n.info(`Conversation ID: ${o.conversation_id||"N/A"}`),n.info(`Status: ${o.accept_time?"Accepted":"Pending"}`),o.text_message&&n.info(`Text: ${o.text_message.text}`),o.media_message&&n.info(`Media URL: ${o.media_message.url}`))}catch(t){c.stop(),n.error(`Failed to get message: ${t.message}`),process.exit(1)}});Yt.command("list").description("List messages").option("-c, --channel <channel>","Filter by channel").option("-l, --limit <number>","Limit number of results",parseInt,20).option("--json","Output result as JSON").action(async i=>{try{let e=await U();c.start("Fetching messages...");let t=await e.conversation.messages.list({page_size:i.limit||20,...i.channel&&{channel:i.channel}});c.succeed(`Retrieved ${t.messages?.length||0} messages`),i.json?console.log(JSON.stringify(t,null,2)):(n.newline(),t.messages&&t.messages.length>0?t.messages.forEach(o=>{n.info(`[${o.id}] ${o.direction} via ${o.channel_identity?.channel||"N/A"}`),o.text_message&&n.info(` "${o.text_message.text}"`),n.newline()}):n.info("No messages found"))}catch(e){c.stop(),n.error(`Failed to list messages: ${e.message}`),process.exit(1)}});Yt.command("delete").description("Delete a message").argument("<message-id>","Message ID to delete").action(async i=>{try{let e=await U();c.start("Deleting message..."),await e.conversation.messages.delete({message_id:i}),c.succeed("Message deleted successfully")}catch(e){c.stop(),n.error(`Failed to delete message: ${e.message}`),process.exit(1)}});xr.exports=Yt});function q(i){try{let e=Fr.parse(i);return Fr.format(e,wn.PhoneNumberFormat.INTERNATIONAL)}catch{return i}}var wn,Fr,It=G(()=>{"use strict";wn=require("google-libphonenumber"),Fr=wn.PhoneNumberUtil.getInstance()});var _r=N((hp,Lr)=>{"use strict";var jr=require("commander"),le=y(require("inquirer"));T();R();at();It();var Cn=class{sinchClient;constructor(e){this.sinchClient=e}hasChannel(e,t){return e.channel_identities?.some(o=>{let r=o.channel;return r==="CHANNEL_UNSPECIFIED"&&o.identity.includes("@")&&(r="EMAIL"),t.includes(r)})}getChannelIdentities(e,t){return e.channel_identities.filter(o=>{let r=o.channel;return r==="CHANNEL_UNSPECIFIED"&&o.identity.includes("@")&&(r="EMAIL"),t.includes(r)})}buildContactMenu(e){let t=this.hasChannel(e,["SMS","WHATSAPP"]),o=this.hasChannel(e,["SMS","WHATSAPP"]),r=this.hasChannel(e,["EMAIL"]),s=[];return t&&s.push({name:"\u{1F4AC} Send Message",value:"send-message"}),s.push({name:"Edit Name",value:"edit-name"}),o&&s.push({name:"Edit Phone",value:"edit-phone"}),r&&s.push({name:"Edit Email",value:"edit-email"}),s.push({name:"Delete Contact",value:"delete"},{name:"See More Details",value:"details"},{name:"\u2190 Back",value:"back"}),s}async sendMessage(e){let t=e.channel_identities.map(s=>{let a=s.channel;return a==="CHANNEL_UNSPECIFIED"&&s.identity.includes("@")&&(a="EMAIL"),{name:`${a}: ${q(s.identity)}`,value:{channel:a,identity:s.identity}}});t.push({name:"\u2190 Back",value:"back"});let{selectedChannel:o}=await le.default.prompt([{type:"list",name:"selectedChannel",message:"Select channel to send to:",choices:t}]);if(o==="back")return!1;let{messageText:r}=await le.default.prompt([{type:"input",name:"messageText",message:"Enter your message:",validate:s=>s?!0:"Message is required"}]);try{let s=bt();c.start("Sending message...");let a=await this.sinchClient.conversation.messages.send({sendMessageRequestBody:{app_id:s,recipient:{identified_by:{channel_identities:[{channel:o.channel,identity:o.identity,app_id:""}]}},message:{text_message:{text:r}}}});c.succeed("Message sent successfully!"),n.newline(),n.info(`Message ID: ${a.message_id}`),n.info(`Recipient: ${q(o.identity)}`),n.info(`Channel: ${o.channel}`),n.newline()}catch(s){c.fail("Failed to send message"),n.error(`Error: ${s.message}`),n.newline()}return!1}showDetails(e){n.newline(),n.info("Contact Details:"),n.info(`ID: ${e.id}`),n.info(`Display Name: ${e.display_name||"N/A"}`),n.info(`Email: ${e.email||"N/A"}`),n.info(`External ID: ${e.external_id||"N/A"}`),n.info(`Language: ${e.language||"N/A"}`),n.info(`Metadata: ${e.metadata||"N/A"}`),e.channel_identities&&e.channel_identities.length>0&&(n.newline(),n.info("Channel Identities:"),e.channel_identities.forEach(t=>{let o=t.channel;o==="CHANNEL_UNSPECIFIED"&&t.identity.includes("@")&&(o="EMAIL"),n.info(` ${o}: ${q(t.identity)}`)})),n.newline()}async editName(e,t){let{newDisplayName:o}=await le.default.prompt([{type:"input",name:"newDisplayName",message:"Enter new display name:",default:e.display_name}]);c.start("Updating contact..."),await this.sinchClient.conversation.contact.update({contact_id:t,display_name:o}),c.succeed("Contact updated successfully!"),e.display_name=o,n.newline()}async editChannelIdentities(e,t,o){let s={phone:{channels:["SMS","WHATSAPP"],addPrompt:"+ Add new phone number",selectPrompt:"Select phone number to edit or add new:",typePrompt:"Select type:",valuePrompt:"Enter phone number:",editPrompt:"Enter new phone number:",typeChoices:["SMS","WHATSAPP"],successAdd:"Phone number added successfully!",successEdit:"Phone number updated successfully!",successDelete:"Phone number deleted successfully!",validator:d=>d?d.startsWith("+")?!0:"Phone number must start with +":"Phone number is required"},email:{channels:["EMAIL"],addPrompt:"+ Add new email address",selectPrompt:"Select email address to edit or add new:",typePrompt:null,valuePrompt:"Enter email address:",editPrompt:"Enter new email address:",typeChoices:null,successAdd:"Email address added successfully!",successEdit:"Email address updated successfully!",successDelete:"Email address deleted successfully!",validator:d=>d?d.includes("@")?!0:"Invalid email address":"Email is required"}}[o],l=this.getChannelIdentities(e,s.channels).map(d=>{let u=e.channel_identities.indexOf(d),m=d.channel;return m==="CHANNEL_UNSPECIFIED"&&d.identity.includes("@")&&(m="EMAIL"),{name:`${m}: ${q(d.identity)}`,value:u}});l.push({name:s.addPrompt,value:"add"}),l.push({name:"\u2190 Back",value:"cancel"});let{identityAction:p}=await le.default.prompt([{type:"list",name:"identityAction",message:s.selectPrompt,choices:l}]);if(p!=="cancel")if(p==="add"){let d=[];s.typePrompt&&s.typeChoices&&d.push({type:"list",name:"newIdentityType",message:s.typePrompt,choices:s.typeChoices}),d.push({type:"input",name:"newIdentityValue",message:s.valuePrompt,validate:s.validator});let u=await le.default.prompt(d);e.channel_identities.push({channel:u.newIdentityType||s.channels[0],identity:u.newIdentityValue,app_id:""}),c.start("Updating contact..."),await this.sinchClient.conversation.contact.update({contact_id:t,channel_identities:e.channel_identities,display_name:e.display_name}),c.succeed(s.successAdd),n.newline()}else{let d=e.channel_identities[p],{editOrDelete:u}=await le.default.prompt([{type:"list",name:"editOrDelete",message:"What would you like to do?",choices:["Edit","Delete","\u2190 Back"]}]);if(u==="Edit"){let{newValue:m}=await le.default.prompt([{type:"input",name:"newValue",message:s.editPrompt,default:d.identity,validate:s.validator}]);d.identity=m,c.start("Updating contact..."),await this.sinchClient.conversation.contact.update({contact_id:t,channel_identities:e.channel_identities,display_name:e.display_name}),c.succeed(s.successEdit),n.newline()}else u==="Delete"&&(e.channel_identities.splice(p,1),c.start("Updating contact..."),await this.sinchClient.conversation.contact.update({contact_id:t,channel_identities:e.channel_identities,display_name:e.display_name}),c.succeed(s.successDelete),n.newline())}}async deleteContact(e,t,o){let{confirmDelete:r}=await le.default.prompt([{type:"confirm",name:"confirmDelete",message:`Are you sure you want to delete "${e.display_name||"this contact"}"?`,default:!1}]);if(r){c.start("Deleting contact..."),await this.sinchClient.conversation.contact.delete({contact_id:t}),c.succeed("Contact deleted successfully");let s=o.findIndex(a=>a.id===t);if(s>-1&&o.splice(s,1),o.length===0)return n.info("No more contacts."),!0;n.newline()}return!1}async handleAction(e,t,o,r){switch(e){case"send-message":return await this.sendMessage(t);case"details":return this.showDetails(t),!1;case"edit-name":return await this.editName(t,o),!1;case"edit-phone":return await this.editChannelIdentities(t,o,"phone"),!1;case"edit-email":return await this.editChannelIdentities(t,o,"email"),!1;case"delete":return await this.deleteContact(t,o,r);default:return!1}}async runInteractiveList(e){let t=!0;for(;t;){let o=[];e.forEach(p=>{o.push(new le.default.Separator(`
125
+ ${p.display_name||"No name"}`)),p.channel_identities&&p.channel_identities.length>0&&p.channel_identities.forEach(d=>{let u=d.channel;u==="CHANNEL_UNSPECIFIED"&&d.identity.includes("@")&&(u="EMAIL"),o.push(new le.default.Separator(`${u}: ${d.identity}`))}),o.push({name:"Edit Delete More",value:`menu:${p.id}`})}),o.push(new le.default.Separator("")),o.push({name:"\u2190 Exit",value:"exit"});let{action:r}=await le.default.prompt([{type:"list",name:"action",message:"Contacts",choices:o,pageSize:20}]);if(r==="exit")break;if(!r||!r.includes(":"))continue;let[s,a]=r.split(":"),l=e.find(p=>p.id===a);if(s==="menu"){let p=this.buildContactMenu(l),{subAction:d}=await le.default.prompt([{type:"list",name:"subAction",message:`Actions for ${l.display_name||"contact"}:`,choices:p}]);if(d==="back")continue;await this.handleAction(d,l,a,e)&&(t=!1)}}}},ze=new jr.Command("contacts");ze.description("Manage conversation contacts");ze.command("create").description("Create a new contact").option("-p, --phone <number>","Phone number").option("-e, --email <email>","Email address").option("-n, --name <name>","Contact name").option("-d, --display-name <name>","Display name").option("--json","Output result as JSON").action(async i=>{try{if(!i.phone&&!i.email){let s=await le.default.prompt([{type:"input",name:"phone",message:"Enter phone number (optional):",validate:a=>a&&!a.startsWith("+")?"Phone number must start with +":!0},{type:"input",name:"email",message:"Enter email address (optional):"},{type:"input",name:"name",message:"Enter contact name (optional):"}]);i={...i,...s}}!i.phone&&!i.email&&(n.error("At least one of phone or email is required"),process.exit(1));let e=await U();c.start("Creating contact...");let t=[];i.phone&&t.push({channel:"SMS",identity:i.phone}),i.email&&t.push({channel:"EMAIL",identity:i.email});let o={contactCreateRequestBody:{channel_identities:t,display_name:i.displayName||i.name,language:"EN_US"}},r=await e.conversation.contact.create(o);c.succeed("Contact created successfully!"),i.json||(n.newline(),n.info(`Contact ID: ${r.id}`),n.info(`Display Name: ${r.display_name||"N/A"}`),i.phone&&n.info(`Phone: ${q(i.phone)}`),i.email&&n.info(`Email: ${i.email}`))}catch(e){c.stop(),n.error(`Failed to create contact: ${e.message}`),e.response?.data&&n.error("API Response:",JSON.stringify(e.response.data,null,2)),e.data&&n.error("Error data:",JSON.stringify(e.data,null,2)),process.exit(1)}});ze.command("get").description("Get a specific contact by ID").argument("<contact-id>","Contact ID to retrieve").option("--json","Output result as JSON").action(async(i,e)=>{try{let t=await U();c.start("Fetching contact...");let o=await t.conversation.contact.get({contact_id:i});c.succeed("Contact retrieved"),e.json?console.log(JSON.stringify(o,null,2)):new Cn(t).showDetails(o)}catch(t){c.stop(),n.error(`Failed to get contact: ${t.message}`),process.exit(1)}});ze.command("list").description("List contacts").option("-l, --limit <number>","Limit number of results",parseInt,50).option("--json","Output result as JSON").option("--no-interactive","Disable interactive mode").action(async i=>{try{let e=await U();c.start("Fetching contacts...");let t=await e.conversation.contact.list({page_size:i.limit||50}),o=t.data||t.contacts||[];if(c.succeed(`Retrieved ${o.length} contacts`),i.json){console.log(JSON.stringify(t,null,2));return}o&&o.length>0?(n.newline(),n.newline(),i.interactive!==!1?await new Cn(e).runInteractiveList(o):o.forEach(r=>{n.info(r.display_name||"No name"),r.channel_identities&&r.channel_identities.length>0&&r.channel_identities.forEach(s=>{let a=s.channel;a==="CHANNEL_UNSPECIFIED"&&s.identity.includes("@")&&(a="EMAIL"),n.info(`${a}: ${s.identity}`)}),n.newline()})):(n.newline(),n.info("No contacts found"))}catch(e){c.stop(),n.error(`Failed to list contacts: ${e.message}`),process.exit(1)}});ze.command("update").description("Update a contact").argument("<contact-id>","Contact ID to update").option("-n, --name <name>","New contact name").option("-d, --display-name <name>","New display name").option("--json","Output result as JSON").action(async(i,e)=>{try{!e.displayName&&!e.name&&(n.error("At least one update field is required (--name or --display-name)"),process.exit(1));let t=await U();c.start("Updating contact...");let o=await t.conversation.contact.update({contact_id:i,display_name:e.displayName||e.name,...e.name&&{metadata:JSON.stringify({name:e.name})}});c.succeed("Contact updated successfully!"),e.json?console.log(JSON.stringify(o,null,2)):(n.newline(),n.info(`Contact ID: ${o.id}`),n.info(`Display Name: ${o.display_name||"N/A"}`))}catch(t){c.stop(),n.error(`Failed to update contact: ${t.message}`),process.exit(1)}});ze.command("delete").description("Delete a contact").argument("<contact-id>","Contact ID to delete").action(async i=>{try{let e=await U();c.start("Deleting contact..."),await e.conversation.contact.delete({contact_id:i}),c.succeed("Contact deleted successfully")}catch(e){c.stop(),n.error(`Failed to delete contact: ${e.message}`),process.exit(1)}});ze.command("merge").description("Merge two contacts").argument("<source-id>","Source contact ID (will be merged into destination)").argument("<dest-id>","Destination contact ID").option("--json","Output result as JSON").action(async(i,e,t)=>{try{let o=await U();c.start("Merging contacts...");let r=await o.conversation.contact.mergeContact({destination_id:e,source_id:i});c.succeed("Contacts merged successfully!"),t.json?console.log(JSON.stringify(r,null,2)):(n.newline(),n.info(`Source contact ${i} merged into ${e}`),n.info(`Result Contact ID: ${r.id}`))}catch(o){c.stop(),n.error(`Failed to merge contacts: ${o.message}`),process.exit(1)}});Lr.exports=ze});var qr=N((vp,Mr)=>{"use strict";var Ur=require("commander");T();R();at();var Xt=new Ur.Command("conversations");Xt.description("Manage conversations");Xt.command("list").description("List conversations").option("-a, --app <app-id>","Filter by Conversation App ID").option("-l, --limit <number>","Limit number of results",parseInt,50).option("--json","Output result as JSON").action(async i=>{try{let e=await U();c.start("Fetching conversations...");let t=await e.conversation.conversation.list({page_size:i.limit||50,...i.app&&{app_id:i.app}});c.succeed(`Retrieved ${t.conversations?.length||0} conversations`),i.json?console.log(JSON.stringify(t,null,2)):(n.newline(),t.conversations&&t.conversations.length>0?t.conversations.forEach(o=>{n.info(`[${o.id}]`),n.info(` App ID: ${o.app_id}`),n.info(` Active: ${o.active_channel||"N/A"}`),n.info(` Last Updated: ${o.last_received?new Date(o.last_received).toLocaleString():"N/A"}`),n.newline()}):n.info("No conversations found"))}catch(e){c.stop(),n.error(`Failed to list conversations: ${e.message}`),process.exit(1)}});Xt.command("get").description("Get a specific conversation by ID").argument("<conversation-id>","Conversation ID to retrieve").option("--json","Output result as JSON").action(async(i,e)=>{try{let t=await U();c.start("Fetching conversation...");let o=await t.conversation.conversation.get({conversation_id:i});c.succeed("Conversation retrieved"),e.json?console.log(JSON.stringify(o,null,2)):(n.newline(),n.info(`Conversation ID: ${o.id}`),n.info(`App ID: ${o.app_id}`),n.info(`Active Channel: ${o.active_channel||"N/A"}`),n.info(`Contact ID: ${o.contact_id||"N/A"}`),o.metadata&&(n.newline(),n.info("Metadata:"),n.info(JSON.stringify(o.metadata,null,2))))}catch(t){c.stop(),n.error(`Failed to get conversation: ${t.message}`),process.exit(1)}});Xt.command("stop").description("Stop an active conversation").argument("<conversation-id>","Conversation ID to stop").action(async i=>{try{let e=await U();c.start("Stopping conversation..."),await e.conversation.conversation.delete({conversation_id:i}),c.succeed("Conversation stopped successfully")}catch(e){c.stop(),n.error(`Failed to stop conversation: ${e.message}`),process.exit(1)}});Mr.exports=Xt});var Br=N(($p,Vr)=>{"use strict";var Jr=require("commander"),gi=y(require("inquirer"));T();R();at();var $t=new Jr.Command("apps");$t.description("Manage Conversation apps");$t.command("list").description("List Conversation apps").option("-l, --limit <number>","Limit number of results",parseInt,50).option("--json","Output result as JSON").action(async i=>{try{let e=await U();c.start("Fetching apps...");let t=await e.conversation.app.list({page_size:i.limit||50});c.succeed(`Retrieved ${t.apps?.length||0} apps`),i.json?console.log(JSON.stringify(t,null,2)):(n.newline(),t.apps&&t.apps.length>0?t.apps.forEach(o=>{n.info(`[${o.id}] ${o.display_name||"No name"}`),n.info(` Channels: ${o.channel_credentials?.length||0} configured`),n.newline()}):n.info("No apps found"))}catch(e){c.stop(),n.error(`Failed to list apps: ${e.message}`),process.exit(1)}});$t.command("get").description("Get a specific Conversation app by ID").argument("<app-id>","App ID to retrieve").option("--json","Output result as JSON").action(async(i,e)=>{try{let t=await U();c.start("Fetching app...");let o=await t.conversation.app.get({app_id:i});c.succeed("App retrieved"),e.json?console.log(JSON.stringify(o,null,2)):(n.newline(),n.info(`App ID: ${o.id}`),n.info(`Display Name: ${o.display_name||"N/A"}`),n.info("Rate Limits:",o.rate_limits||"N/A"),o.channel_credentials&&o.channel_credentials.length>0&&(n.newline(),n.info("Configured Channels:"),o.channel_credentials.forEach(r=>{n.info(` - ${r.channel}`)})),o.conversation_metadata_report_view&&(n.newline(),n.info(`Metadata Report: ${o.conversation_metadata_report_view}`)))}catch(t){c.stop(),n.error(`Failed to get app: ${t.message}`),process.exit(1)}});$t.command("create").description("Create a new Conversation app").argument("[name]","App display name").option("--json","Output result as JSON").action(async(i,e)=>{try{i||(i=(await gi.default.prompt([{type:"input",name:"name",message:"Enter app display name:",validate:s=>s?!0:"App name is required"}])).name);let t=await U();c.start("Creating app...");let o=await t.conversation.app.create({display_name:i});c.succeed("App created successfully!"),e?.json?console.log(JSON.stringify(o,null,2)):(n.newline(),n.info(`App ID: ${o.id}`),n.info(`Display Name: ${o.display_name}`),n.newline(),n.info("\u{1F4A1} Set as default: sinch config set conversation-app-id "+o.id))}catch(t){c.stop(),n.error(`Failed to create app: ${t.message}`),process.exit(1)}});$t.command("delete").description("Delete a Conversation app").argument("<app-id>","App ID to delete").action(async i=>{try{let{confirm:e}=await gi.default.prompt([{type:"confirm",name:"confirm",message:`Are you sure you want to delete app ${i}?`,default:!1}]);if(!e){n.info("Deletion cancelled");return}let t=await U();c.start("Deleting app..."),await t.conversation.app.delete({app_id:i}),c.succeed("App deleted successfully")}catch(e){c.stop(),n.error(`Failed to delete app: ${e.message}`),process.exit(1)}});Vr.exports=$t});var Wr=N((Tp,Hr)=>{"use strict";var Kr=require("commander"),hi=y(require("inquirer"));E();T();R();at();var Pt=new Kr.Command("webhooks");Pt.description("Manage webhooks for Conversation apps");Pt.command("list").description("List webhooks for a Conversation app").option("-a, --app <app-id>","Conversation App ID").option("--json","Output result as JSON").action(async i=>{try{let e=bt(i.app),t=await U();c.start("Fetching webhooks...");let o=await t.conversation.webhooks.list({app_id:e});c.succeed(`Retrieved ${o.webhooks?.length||0} webhooks`),i.json?console.log(JSON.stringify(o,null,2)):(n.newline(),o.webhooks&&o.webhooks.length>0?o.webhooks.forEach(r=>{n.info(`[${r.id}]`),n.info(` URL: ${r.target}`),n.info(` Triggers: ${r.triggers?.join(", ")||"N/A"}`),n.info(` Secret: ${r.secret?"********":"Not set"}`),n.newline()}):n.info("No webhooks found for this app"))}catch(e){c.stop(),n.error(`Failed to list webhooks: ${e.message}`),process.exit(1)}});Pt.command("create").description("Create a new webhook for a Conversation app").option("-a, --app <app-id>","Conversation App ID").option("-u, --url <url>","Webhook URL").option("-t, --triggers <triggers>","Comma-separated list of triggers (e.g., MESSAGE_INBOUND,MESSAGE_DELIVERY)").option("-s, --secret <secret>","Webhook secret for signature validation").option("--json","Output result as JSON").action(async i=>{try{await f.load(),await f.hasCredentials()||(n.error('Not authenticated. Run "sinch auth login" first.'),process.exit(1));let t=i.app;if(!t){let a=f.get("conversation-app-id");a&&(t=a,n.info(`Using default app: ${t}`))}if(!t||!i.url||!i.triggers){let a=await hi.default.prompt([{type:"input",name:"appId",message:"Enter Conversation App ID:",when:!t,validate:l=>l?!0:"App ID is required"},{type:"input",name:"url",message:"Enter webhook URL:",when:!i.url,validate:l=>{if(!l)return"URL is required";try{return new URL(l),!0}catch{return"Please enter a valid URL"}}},{type:"checkbox",name:"triggers",message:"Select webhook triggers:",when:!i.triggers,choices:["MESSAGE_INBOUND","MESSAGE_DELIVERY","MESSAGE_SUBMIT","EVENT_INBOUND","CONVERSATION_START","CONVERSATION_STOP","CONTACT_CREATE","CONTACT_DELETE","CONTACT_MERGE","CONTACT_UPDATE"],validate:l=>l.length>0?!0:"Select at least one trigger"},{type:"input",name:"secret",message:"Enter webhook secret (optional, press enter to skip):"}]);t=t||a.appId,i.url=i.url||a.url,i.triggers=i.triggers||a.triggers.join(","),i.secret=i.secret||a.secret}let o=await U(),r=i.triggers.split(",").map(a=>a.trim());c.start("Creating webhook...");let s=await o.conversation.webhooks.create({app_id:t,target:i.url,triggers:r,...i.secret&&{secret:i.secret}});c.succeed("Webhook created successfully!"),i.json?console.log(JSON.stringify(s,null,2)):(n.newline(),n.info(`Webhook ID: ${s.id}`),n.info(`URL: ${s.target}`),n.info(`Triggers: ${s.triggers?.join(", ")}`),i.secret&&n.info("Secret: ********"))}catch(e){c.stop(),n.error(`Failed to create webhook: ${e.message}`),process.exit(1)}});Pt.command("update").description("Update a webhook").argument("<webhook-id>","Webhook ID to update").option("-u, --url <url>","New webhook URL").option("-t, --triggers <triggers>","New comma-separated list of triggers").option("-s, --secret <secret>","New webhook secret").option("--json","Output result as JSON").action(async(i,e)=>{try{!e.url&&!e.triggers&&!e.secret&&(n.error("At least one update field is required (--url, --triggers, or --secret)"),process.exit(1));let t=await U(),o={};e.url&&(o.target=e.url),e.triggers&&(o.triggers=e.triggers.split(",").map(s=>s.trim())),e.secret&&(o.secret=e.secret),c.start("Updating webhook...");let r=await t.conversation.webhooks.update({webhook_id:i,...o});c.succeed("Webhook updated successfully!"),e.json?console.log(JSON.stringify(r,null,2)):(n.newline(),n.info(`Webhook ID: ${r.id}`),n.info(`URL: ${r.target}`),n.info(`Triggers: ${r.triggers?.join(", ")}`))}catch(t){c.stop(),n.error(`Failed to update webhook: ${t.message}`),process.exit(1)}});Pt.command("delete").description("Delete a webhook").argument("<webhook-id>","Webhook ID to delete").action(async i=>{try{let{confirm:e}=await hi.default.prompt([{type:"confirm",name:"confirm",message:`Are you sure you want to delete webhook ${i}?`,default:!1}]);if(!e){n.info("Deletion cancelled");return}let t=await U();c.start("Deleting webhook..."),await t.conversation.webhooks.delete({webhook_id:i}),c.succeed("Webhook deleted successfully")}catch(e){c.stop(),n.error(`Failed to delete webhook: ${e.message}`),process.exit(1)}});Hr.exports=Pt});var Yr=N((Np,Gr)=>{"use strict";var zr=require("commander"),Sc=Rr(),bc=Or(),Ic=_r(),$c=qr(),Pc=Br(),Ac=Wr(),Ge=new zr.Command("conversation");Ge.description("Manage Sinch Conversations API");Ge.addCommand(Sc);Ge.addCommand(bc);Ge.addCommand(Ic);Ge.addCommand($c);Ge.addCommand(Pc);Ge.addCommand(Ac);Gr.exports=Ge});var yi,vn,Xr,oe,Ye=G(()=>{"use strict";yi=y(require("axios")),vn=y(require("axios-retry")),Xr=y(require("chalk"));ut();Lt();oe=class{baseUrl="https://elastic-trunking.api.sinch.com";projectId;credentials;client;timeout=6e4;constructor(e){this.projectId=e.projectId,this.credentials=e.credentials,this.client=yi.default.create({baseURL:this.baseUrl,timeout:this.timeout,headers:{"Content-Type":"application/json","User-Agent":"sinch-functions-cli/1.0.0"}}),(0,vn.default)(this.client,{retries:3,retryDelay:(t,o)=>{let r=o.response?.headers?.["retry-after"];return r?parseInt(r,10)*1e3:vn.default.exponentialDelay(t)},retryCondition:t=>{if(vn.default.isNetworkError(t))return!0;let o=t.response?.status;return!!(o&&o>=500||o===429)},onRetry:(t,o)=>{Ce(1,`Retry ${t}/3: ${o.message}`)}}),this.client.interceptors.request.use(async t=>{let o=await this.getAuthHeader();return o&&(t.headers.Authorization=o),ae()>=2&&Ce(2,`\u2192 ${t.method?.toUpperCase()} ${t.url}`),t},t=>Promise.reject(t)),this.client.interceptors.response.use(t=>(ae()>=2&&Ce(2,`\u2190 ${t.status} ${t.config.url}`),t),t=>(ae()>=2&&Ce(2,`\u2190 ${t.response?.status||"ERROR"} ${t.config?.url}`),Promise.reject(t)))}async getAuthHeader(){try{let e=await this.credentials.retrieve();return e&&e.keyId&&e.keySecret?`Basic ${Buffer.from(`${e.keyId}:${e.keySecret}`).toString("base64")}`:null}catch{return console.error(Xr.default.yellow("Failed to get authentication credentials")),null}}async listTrunks(e={}){try{let t={};return e.page&&(t.pageToken=e.page),e.pageSize&&(t.pageSize=e.pageSize),(await this.client.get(`/v1/projects/${this.projectId}/trunks`,{params:t})).data}catch(t){throw this.handleError(t,"Failed to list SIP trunks")}}async getTrunk(e){try{return(await this.client.get(`/v1/projects/${this.projectId}/trunks/${e}`)).data}catch(t){throw this.handleError(t,`Failed to get SIP trunk ${e}`)}}async createTrunk(e){try{return(await this.client.post(`/v1/projects/${this.projectId}/trunks`,e)).data}catch(t){throw this.handleError(t,"Failed to create SIP trunk")}}async updateTrunk(e,t){try{return(await this.client.put(`/v1/projects/${this.projectId}/trunks/${e}`,t)).data}catch(o){throw this.handleError(o,`Failed to update SIP trunk ${e}`)}}async deleteTrunk(e){try{await this.client.delete(`/v1/projects/${this.projectId}/trunks/${e}`)}catch(t){throw this.handleError(t,`Failed to delete SIP trunk ${e}`)}}async listEndpoints(e,t={}){try{let o={};return t.page&&(o.pageToken=t.page),t.pageSize&&(o.pageSize=t.pageSize),(await this.client.get(`/v1/projects/${this.projectId}/trunks/${e}/endpoints`,{params:o})).data}catch(o){throw this.handleError(o,`Failed to list endpoints for trunk ${e}`)}}async getEndpoint(e,t){try{return(await this.client.get(`/v1/projects/${this.projectId}/trunks/${e}/endpoints/${t}`)).data}catch(o){throw this.handleError(o,`Failed to get endpoint ${t}`)}}async createEndpoint(e,t){try{return(await this.client.post(`/v1/projects/${this.projectId}/trunks/${e}/endpoints`,t)).data}catch(o){throw this.handleError(o,"Failed to create SIP endpoint")}}async updateEndpoint(e,t,o){try{return(await this.client.put(`/v1/projects/${this.projectId}/trunks/${e}/endpoints/${t}`,o)).data}catch(r){throw this.handleError(r,`Failed to update endpoint ${t}`)}}async deleteEndpoint(e,t){try{await this.client.delete(`/v1/projects/${this.projectId}/trunks/${e}/endpoints/${t}`)}catch(o){throw this.handleError(o,`Failed to delete endpoint ${t}`)}}async listAcls(e={}){try{let t={};return e.page&&(t.pageToken=e.page),e.pageSize&&(t.pageSize=e.pageSize),(await this.client.get(`/v1/projects/${this.projectId}/accessControlLists`,{params:t})).data}catch(t){throw this.handleError(t,"Failed to list ACLs")}}async getAcl(e){try{return(await this.client.get(`/v1/projects/${this.projectId}/accessControlLists/${e}`)).data}catch(t){throw this.handleError(t,`Failed to get ACL ${e}`)}}async createAcl(e){try{return(await this.client.post(`/v1/projects/${this.projectId}/accessControlLists`,e)).data}catch(t){throw this.handleError(t,"Failed to create ACL")}}async updateAcl(e,t){try{return(await this.client.put(`/v1/projects/${this.projectId}/accessControlLists/${e}`,t)).data}catch(o){throw this.handleError(o,`Failed to update ACL ${e}`)}}async deleteAcl(e){try{await this.client.delete(`/v1/projects/${this.projectId}/accessControlLists/${e}`)}catch(t){throw this.handleError(t,`Failed to delete ACL ${e}`)}}async getAclTrunks(e,t={}){try{let o={};return t.page&&(o.pageToken=t.page),t.pageSize&&(o.pageSize=t.pageSize),(await this.client.get(`/v1/projects/${this.projectId}/accessControlLists/${e}/trunks`,{params:o})).data}catch(o){throw this.handleError(o,`Failed to get trunks for ACL ${e}`)}}async listIpRanges(e,t={}){try{let o={};return t.page&&(o.pageToken=t.page),t.pageSize&&(o.pageSize=t.pageSize),(await this.client.get(`/v1/projects/${this.projectId}/accessControlLists/${e}/ipRanges`,{params:o})).data}catch(o){throw this.handleError(o,`Failed to list IP ranges for ACL ${e}`)}}async getIpRange(e,t){try{return(await this.client.get(`/v1/projects/${this.projectId}/accessControlLists/${e}/ipRanges/${t}`)).data}catch(o){throw this.handleError(o,`Failed to get IP range ${t}`)}}async addIpRange(e,t){try{return(await this.client.post(`/v1/projects/${this.projectId}/accessControlLists/${e}/ipRanges`,t)).data}catch(o){throw this.handleError(o,`Failed to add IP range to ACL ${e}`)}}async updateIpRange(e,t,o){try{return(await this.client.put(`/v1/projects/${this.projectId}/accessControlLists/${e}/ipRanges/${t}`,o)).data}catch(r){throw this.handleError(r,`Failed to update IP range ${t}`)}}async deleteIpRange(e,t){try{await this.client.delete(`/v1/projects/${this.projectId}/accessControlLists/${e}/ipRanges/${t}`)}catch(o){throw this.handleError(o,`Failed to delete IP range ${t}`)}}async listCountryPermissions(e={}){try{let t={};return e.page&&(t.pageToken=e.page),e.pageSize&&(t.pageSize=e.pageSize),(await this.client.get(`/v1/projects/${this.projectId}/countryPermissions`,{params:t})).data}catch(t){throw this.handleError(t,"Failed to list country permissions")}}async getCountryPermission(e){try{return(await this.client.get(`/v1/projects/${this.projectId}/countryPermissions/${e}`)).data}catch(t){throw this.handleError(t,`Failed to get country permission for ${e}`)}}async updateCountryPermission(e,t){try{return(await this.client.put(`/v1/projects/${this.projectId}/countryPermissions/${e}`,{enabled:t})).data}catch(o){throw this.handleError(o,`Failed to update country permission for ${e}`)}}async listTrunkAcls(e,t={}){try{let o={};return t.page&&(o.pageToken=t.page),t.pageSize&&(o.pageSize=t.pageSize),(await this.client.get(`/v1/projects/${this.projectId}/trunks/${e}/accessControlLists`,{params:o})).data}catch(o){throw this.handleError(o,`Failed to list ACLs for trunk ${e}`)}}async addTrunkAcl(e,t){try{await this.client.post(`/v1/projects/${this.projectId}/trunks/${e}/accessControlLists`,{accessControlListId:t})}catch(o){throw this.handleError(o,`Failed to add ACL ${t} to trunk ${e}`)}}async removeTrunkAcl(e,t){try{await this.client.delete(`/v1/projects/${this.projectId}/trunks/${e}/accessControlLists/${t}`)}catch(o){throw this.handleError(o,`Failed to remove ACL ${t} from trunk ${e}`)}}async getCredentialListTrunks(e,t={}){try{let o={};return t.page&&(o.pageNumber=t.page),t.pageSize&&(o.pageSize=t.pageSize),(await this.client.get(`/v1/projects/${this.projectId}/credentialLists/${e}/trunks`,{params:o})).data}catch(o){throw this.handleError(o,`Failed to get trunks for credential list ${e}`)}}async updateTrunkCredentialLists(e,t){try{return(await this.client.put(`/v1/projects/${this.projectId}/trunks/${e}/credentialLists`,{credentialListIds:t})).data}catch(o){throw this.handleError(o,`Failed to update credential lists for trunk ${e}`)}}async findCalls(e={}){try{let t={};return e.from&&(t.from=e.from),e.to&&(t.to=e.to),e.trunkId&&(t.trunkId=e.trunkId),e.createTime&&(t.createTime=e.createTime),e.callResult&&(t.callResult=e.callResult),e.direction&&(t.direction=e.direction),e.page&&(t.pageNumber=e.page),e.pageSize&&(t.pageSize=e.pageSize),(await this.client.get(`/v1/projects/${this.projectId}/calls`,{params:t})).data}catch(t){throw this.handleError(t,"Failed to find calls")}}async getCall(e){try{return(await this.client.get(`/v1/projects/${this.projectId}/calls/${e}`)).data}catch(t){throw this.handleError(t,`Failed to get call ${e}`)}}handleError(e,t){if(yi.default.isAxiosError(e)){let o=e;if(o.response){let r=o.response.status,s=o.response.data,a=s?.message||s?.error||o.message;throw r===401?new D('Authentication required. Please run "sinch auth login" first.',I.AUTH_REQUIRED):r===403?new D(`Permission denied: ${a}`,I.NO_PERMISSION):r===404?new D(`Resource not found: ${a}`,I.NOT_FOUND):r===429?new D(`Rate limited: ${a}`,I.UNAVAILABLE):r>=500?new D(`Server error: ${a}`,I.UNAVAILABLE):new D(`${t}: ${a}`,I.FAILURE)}else throw o.request?o.code==="ECONNREFUSED"?new D(`Cannot connect to EST API at ${this.baseUrl}`,I.UNAVAILABLE):o.code==="ETIMEDOUT"?new D(`Request timeout after ${this.timeout}ms`,I.TIMEOUT):new D(`${t}: No response from server (${o.code||"unknown error"})`,I.IO_ERROR):new D(`${t}: ${o.message}`,I.FAILURE)}else throw new D(`${t}: ${e.message||e}`,I.FAILURE)}}});var Qr=N((qp,Zr)=>{"use strict";var Sn=require("commander"),_e=y(require("inquirer"));T();R();E();Ye();async function Ue(){await f.load(),await f.hasCredentials()||(n.error('Not authenticated. Run "sinch auth login" first.'),process.exit(1));let e=f.getApiConfig();return new oe({projectId:e.projectId,credentials:e.credentials})}function wi(i){n.info(`ID: ${i.id}`),n.info(`Name: ${i.name}`),i.hostName&&n.info(`Host: ${i.hostName}`),n.info(`Caller ID: ${i.enableCallerId?"enabled":"disabled"}`),i.createTime&&n.info(`Created: ${new Date(i.createTime).toLocaleString()}`),i.updateTime&&n.info(`Updated: ${new Date(i.updateTime).toLocaleString()}`)}var Me=new Sn.Command("trunks");Me.description("Manage SIP trunks");Me.command("list").description("List all SIP trunks").option("-l, --limit <number>","Limit number of results",parseInt,50).option("--json","Output result as JSON").action(async i=>{try{let e=await Ue();c.start("Fetching SIP trunks...");let t=await e.listTrunks({pageSize:i.limit});c.succeed(`Retrieved ${t.trunks?.length||0} trunk(s)`),i.json?console.log(JSON.stringify(t,null,2)):(n.newline(),t.trunks&&t.trunks.length>0?t.trunks.forEach(o=>{n.info(`[${o.id}] ${o.name}`),o.hostName&&n.info(` Host: ${o.hostName}`),n.info(` Caller ID: ${o.enableCallerId?"enabled":"disabled"}`),n.newline()}):(n.info("No SIP trunks found"),n.newline(),n.info("Create one with: sinch sip trunks create")))}catch(e){c.stop(),n.error(`Failed to list trunks: ${e.message}`),process.exit(1)}});Me.command("get").description("Get a SIP trunk by ID").argument("<trunk-id>","Trunk ID to retrieve").option("--json","Output result as JSON").action(async(i,e)=>{try{let t=await Ue();c.start("Fetching trunk...");let o=await t.getTrunk(i);c.succeed("Trunk retrieved"),e.json?console.log(JSON.stringify(o,null,2)):(n.newline(),wi(o))}catch(t){c.stop(),n.error(`Failed to get trunk: ${t.message}`),process.exit(1)}});Me.command("create").description("Create a new SIP trunk").option("-n, --name <name>","Trunk name (required)").option("-h, --host-name <hostname>","Host name for the trunk (required)").option("--caller-id","Enable caller ID").option("--non-interactive","Skip prompts, use defaults for missing options").option("--json","Output result as JSON").action(async i=>{try{let e=i.name,t=i.hostName,o=i.callerId??!1,r=!i.nonInteractive;e||(r?e=(await _e.default.prompt([{type:"input",name:"name",message:"Enter trunk name:",validate:p=>p?!0:"Trunk name is required"}])).name:(n.error("Name is required. Use --name <name>"),process.exit(1))),t||(r?t=(await _e.default.prompt([{type:"input",name:"hostName",message:"Enter host name:",validate:p=>p?!0:"Host name is required"}])).hostName:(n.error("Host name is required. Use --host-name <hostname>"),process.exit(1))),i.callerId===void 0&&r&&(o=(await _e.default.prompt([{type:"confirm",name:"enableCallerId",message:"Enable caller ID?",default:!1}])).enableCallerId);let s=await Ue();c.start("Creating SIP trunk...");let a=await s.createTrunk({name:e,hostName:t,enableCallerId:o});c.succeed("SIP trunk created successfully!"),i.json?console.log(JSON.stringify(a,null,2)):(n.newline(),wi(a),n.newline(),n.info(`Add an endpoint: sinch sip endpoints create ${a.id}`))}catch(e){c.stop(),n.error(`Failed to create trunk: ${e.message}`),process.exit(1)}});Me.command("update").description("Update a SIP trunk").argument("<trunk-id>","Trunk ID to update").option("-n, --name <name>","New trunk name").option("-h, --host-name <hostname>","New host name").option("--caller-id","Enable caller ID").option("--no-caller-id","Disable caller ID").option("--non-interactive","Skip prompts, use current values for missing options").option("--json","Output result as JSON").action(async(i,e)=>{try{let t=await Ue();c.start("Fetching current trunk details...");let o=await t.getTrunk(i);c.stop();let r=e.name,s=e.hostName,a=e.callerId,l=!e.nonInteractive;r||(l?r=(await _e.default.prompt([{type:"input",name:"name",message:"Enter trunk name:",default:o.name,validate:u=>u?!0:"Trunk name is required"}])).name:r=o.name),s===void 0&&(l?s=(await _e.default.prompt([{type:"input",name:"hostName",message:"Enter host name:",default:o.hostName||""}])).hostName||void 0:s=o.hostName),a===void 0&&(l?a=(await _e.default.prompt([{type:"confirm",name:"enableCallerId",message:"Enable caller ID?",default:o.enableCallerId??!1}])).enableCallerId:a=o.enableCallerId),c.start("Updating SIP trunk...");let p=await t.updateTrunk(i,{name:r,hostName:s,enableCallerId:a});c.succeed("SIP trunk updated successfully!"),e.json?console.log(JSON.stringify(p,null,2)):(n.newline(),wi(p))}catch(t){c.stop(),n.error(`Failed to update trunk: ${t.message}`),process.exit(1)}});Me.command("delete").description("Delete a SIP trunk").argument("<trunk-id>","Trunk ID to delete").option("-f, --force","Skip confirmation prompt").action(async(i,e)=>{try{if(!e.force){let{confirm:o}=await _e.default.prompt([{type:"confirm",name:"confirm",message:`Are you sure you want to delete trunk ${i}?`,default:!1}]);if(!o){n.info("Deletion cancelled");return}}let t=await Ue();c.start("Deleting SIP trunk..."),await t.deleteTrunk(i),c.succeed("SIP trunk deleted successfully")}catch(t){c.stop(),n.error(`Failed to delete trunk: ${t.message}`),process.exit(1)}});var Zt=new Sn.Command("acls");Zt.description("Manage ACLs for a trunk");Zt.command("list").description("List ACLs associated with a trunk").argument("<trunk-id>","Trunk ID").option("-l, --limit <number>","Limit number of results",parseInt,50).option("--json","Output result as JSON").action(async(i,e)=>{try{let t=await Ue();c.start("Fetching trunk ACLs...");let o=await t.listTrunkAcls(i,{pageSize:e.limit});c.succeed(`Retrieved ${o.accessControlLists?.length||0} ACL(s)`),e.json?console.log(JSON.stringify(o,null,2)):(n.newline(),o.accessControlLists&&o.accessControlLists.length>0?o.accessControlLists.forEach(r=>{let s=r.enabled!==!1?"":" (disabled)";n.info(`[${r.id}] ${r.name}${s}`),n.newline()}):(n.info("No ACLs associated with this trunk"),n.newline(),n.info(`Add an ACL: sinch sip trunks acls add ${i} <acl-id>`)))}catch(t){c.stop(),n.error(`Failed to list trunk ACLs: ${t.message}`),process.exit(1)}});Zt.command("add").description("Add an ACL to a trunk").argument("<trunk-id>","Trunk ID").argument("<acl-id>","ACL ID to add").option("--json","Output result as JSON").action(async(i,e,t)=>{try{let o=await Ue();c.start(`Adding ACL ${e} to trunk ${i}...`),await o.addTrunkAcl(i,e),c.succeed("ACL added to trunk successfully"),t.json||(n.newline(),n.info(`ACL ${e} is now associated with trunk ${i}`))}catch(o){c.stop(),n.error(`Failed to add ACL to trunk: ${o.message}`),process.exit(1)}});Zt.command("remove").description("Remove an ACL from a trunk").argument("<trunk-id>","Trunk ID").argument("<acl-id>","ACL ID to remove").option("-f, --force","Skip confirmation prompt").action(async(i,e,t)=>{try{if(!t.force){let{confirm:r}=await _e.default.prompt([{type:"confirm",name:"confirm",message:`Remove ACL ${e} from trunk ${i}?`,default:!1}]);if(!r){n.info("Operation cancelled");return}}let o=await Ue();c.start("Removing ACL from trunk..."),await o.removeTrunkAcl(i,e),c.succeed("ACL removed from trunk successfully")}catch(o){c.stop(),n.error(`Failed to remove ACL from trunk: ${o.message}`),process.exit(1)}});Me.addCommand(Zt);var Ci=new Sn.Command("credential-lists");Ci.description("Manage credential lists for a trunk");Ci.command("update").description("Bulk update credential lists for a trunk").argument("<trunk-id>","Trunk ID").argument("<credential-list-ids...>","Credential list IDs to assign (space-separated)").option("--json","Output result as JSON").action(async(i,e,t)=>{try{let o=await Ue();c.start(`Updating credential lists for trunk ${i}...`);let r=await o.updateTrunkCredentialLists(i,e);if(c.succeed("Credential lists updated successfully"),t.json)console.log(JSON.stringify(r,null,2));else{n.newline();let s=r?.credentialListIds??[];n.info(`Trunk ${i} now uses ${s.length} credential list(s):`),s.forEach(a=>{n.info(` - ${a}`)})}}catch(o){c.stop(),n.error(`Failed to update credential lists: ${o.message}`),process.exit(1)}});Me.addCommand(Ci);Zr.exports=Me});var ns=N((Wp,ts)=>{"use strict";var es=require("commander"),Re=y(require("inquirer"));T();R();E();Ye();async function Qt(){await f.load(),await f.hasCredentials()||(n.error('Not authenticated. Run "sinch auth login" first.'),process.exit(1));let e=f.getApiConfig();return new oe({projectId:e.projectId,credentials:e.credentials})}async function vi(i,e){c.start("Looking up endpoint...");let o=(await i.listTrunks()).trunks||[];for(let r of o)if(((await i.listEndpoints(r.id)).endpoints||[]).find(p=>p.id===e))return c.stop(),r.id;throw c.stop(),new Error(`Endpoint ${e} not found`)}function Si(i){if(n.info(`ID: ${i.id}`),n.info(`Name: ${i.name}`),i.address){let e=i.port?`${i.address}:${i.port}`:i.address;n.info(`Address: ${e}`)}i.transport&&n.info(`Transport: ${i.transport}`),n.info(`Priority: ${i.priority}`),n.info(`Enabled: ${i.enabled!==!1?"yes":"no"}`),i.createTime&&n.info(`Created: ${new Date(i.createTime).toLocaleString()}`),i.updateTime&&n.info(`Updated: ${new Date(i.updateTime).toLocaleString()}`)}var ct=new es.Command("endpoints");ct.description("Manage SIP endpoints");ct.command("list").description("List all SIP endpoints for a trunk").argument("<trunk-id>","Trunk ID").option("-l, --limit <number>","Limit number of results",parseInt,50).option("--json","Output result as JSON").action(async(i,e)=>{try{let t=await Qt();c.start("Fetching SIP endpoints...");let o=await t.listEndpoints(i,{pageSize:e.limit});c.succeed(`Retrieved ${o.endpoints?.length||0} endpoint(s)`),e.json?console.log(JSON.stringify(o,null,2)):(n.newline(),o.endpoints&&o.endpoints.length>0?o.endpoints.forEach(r=>{let s=r.enabled!==!1?"":" (disabled)",a=r.port?`${r.address}:${r.port}`:r.address;n.info(`[${r.id}] ${r.name}${s}`),n.info(` Address: ${a||"N/A"}`),n.info(` Priority: ${r.priority}, Transport: ${r.transport||"UDP"}`),n.newline()}):(n.info("No endpoints found for this trunk"),n.newline(),n.info(`Create one with: sinch sip endpoints create ${i}`)))}catch(t){c.stop(),n.error(`Failed to list endpoints: ${t.message}`),process.exit(1)}});ct.command("get").description("Get a SIP endpoint by ID").argument("<endpoint-id>","Endpoint ID to retrieve").option("--json","Output result as JSON").action(async(i,e)=>{try{let t=await Qt(),o=await vi(t,i);c.start("Fetching endpoint...");let r=await t.getEndpoint(o,i);c.succeed("Endpoint retrieved"),e.json?console.log(JSON.stringify(r,null,2)):(n.newline(),Si(r))}catch(t){c.stop(),n.error(`Failed to get endpoint: ${t.message}`),process.exit(1)}});ct.command("create").description("Create a new SIP endpoint").argument("<trunk-id>","Trunk ID to add endpoint to").option("-n, --name <name>","Endpoint name (required)").option("-a, --address <address>","SIP address (IP or hostname, without port)").option("--port <number>","SIP port (default: 5060)",parseInt).option("-t, --transport <transport>","Transport protocol: UDP, TCP, or TLS (default: UDP)").option("-p, --priority <number>","Priority (required, lower = higher priority)",parseInt).option("--non-interactive","Skip prompts, use defaults for missing options").option("--json","Output result as JSON").action(async(i,e)=>{try{let t=e.name,o=e.address,r=e.port,s=e.transport,a=e.priority,l=!e.nonInteractive;t||(l?t=(await Re.default.prompt([{type:"input",name:"name",message:"Enter endpoint name:",validate:m=>m?!0:"Endpoint name is required"}])).name:(n.error("Name is required. Use --name <name>"),process.exit(1))),o||(l?o=(await Re.default.prompt([{type:"input",name:"address",message:"Enter SIP address (IP or hostname):",validate:m=>m?!0:"SIP address is required"}])).address:(n.error("Address is required. Use --address <address>"),process.exit(1))),r===void 0&&l&&(r=(await Re.default.prompt([{type:"input",name:"port",message:"Enter SIP port (default 5060):",default:"5060",filter:m=>m?parseInt(m,10):5060}])).port),a===void 0&&(l?a=(await Re.default.prompt([{type:"input",name:"priority",message:"Enter priority (lower = higher priority):",default:"1",filter:m=>parseInt(m,10),validate:m=>{let w=parseInt(m,10);return isNaN(w)?"Please enter a valid number":!0}}])).priority:(n.error("Priority is required. Use --priority <number>"),process.exit(1)));let p=await Qt();c.start("Creating SIP endpoint...");let d=await p.createEndpoint(i,{name:t,address:o,port:r,transport:s,priority:a});c.succeed("SIP endpoint created successfully!"),e.json?console.log(JSON.stringify(d,null,2)):(n.newline(),Si(d))}catch(t){c.stop(),n.error(`Failed to create endpoint: ${t.message}`),process.exit(1)}});ct.command("update").description("Update a SIP endpoint").argument("<endpoint-id>","Endpoint ID to update").option("-n, --name <name>","New endpoint name").option("-a, --address <address>","New SIP address").option("--port <number>","New SIP port",parseInt).option("-t, --transport <transport>","Transport protocol: UDP, TCP, or TLS").option("-p, --priority <number>","New priority",parseInt).option("--non-interactive","Skip prompts, use current values for missing options").option("--json","Output result as JSON").action(async(i,e)=>{try{let t=await Qt(),o=await vi(t,i);c.start("Fetching current endpoint details...");let r=await t.getEndpoint(o,i);c.stop();let s=e.name,a=e.address,l=e.port,p=e.transport,d=e.priority,u=!e.nonInteractive;s||(u?s=(await Re.default.prompt([{type:"input",name:"name",message:"Enter endpoint name:",default:r.name,validate:h=>h?!0:"Name is required"}])).name:s=r.name),a||(u?a=(await Re.default.prompt([{type:"input",name:"address",message:"Enter SIP address:",default:r.address,validate:h=>h?!0:"SIP address is required"}])).address:a=r.address||""),l===void 0&&(u?l=(await Re.default.prompt([{type:"input",name:"port",message:"Enter SIP port:",default:(r.port||5060).toString(),filter:h=>parseInt(h,10)}])).port:l=r.port),d===void 0&&(u?d=(await Re.default.prompt([{type:"input",name:"priority",message:"Enter priority:",default:r.priority.toString(),filter:h=>parseInt(h,10)}])).priority:d=r.priority),c.start("Updating SIP endpoint...");let m=await t.updateEndpoint(o,i,{name:s,address:a,port:l,transport:p,priority:d});c.succeed("SIP endpoint updated successfully!"),e.json?console.log(JSON.stringify(m,null,2)):(n.newline(),Si(m))}catch(t){c.stop(),n.error(`Failed to update endpoint: ${t.message}`),process.exit(1)}});ct.command("delete").description("Delete a SIP endpoint").argument("<endpoint-id>","Endpoint ID to delete").option("-f, --force","Skip confirmation prompt").action(async(i,e)=>{try{let t=await Qt(),o=await vi(t,i);if(!e.force){let{confirm:r}=await Re.default.prompt([{type:"confirm",name:"confirm",message:`Are you sure you want to delete endpoint ${i}?`,default:!1}]);if(!r){n.info("Deletion cancelled");return}}c.start("Deleting SIP endpoint..."),await t.deleteEndpoint(o,i),c.succeed("SIP endpoint deleted successfully")}catch(t){c.stop(),n.error(`Failed to delete endpoint: ${t.message}`),process.exit(1)}});ts.exports=ct});var rs=N((eu,os)=>{"use strict";var bi=require("commander"),Z=y(require("inquirer"));T();R();E();Ye();async function De(){await f.load(),await f.hasCredentials()||(n.error('Not authenticated. Run "sinch auth login" first.'),process.exit(1));let e=f.getApiConfig();return new oe({projectId:e.projectId,credentials:e.credentials})}function Ii(i){n.info(`ID: ${i.id}`),n.info(`Name: ${i.name}`),n.info(`Enabled: ${i.enabled!==!1?"yes":"no"}`),i.createTime&&n.info(`Created: ${new Date(i.createTime).toLocaleString()}`),i.updateTime&&n.info(`Updated: ${new Date(i.updateTime).toLocaleString()}`)}function is(i){n.info(`ID: ${i.id}`),i.description&&n.info(`Description: ${i.description}`),i.ipAddress&&n.info(`IP Address: ${i.ipAddress}`),i.range&&n.info(`CIDR Range: ${i.range}`),i.createTime&&n.info(`Created: ${new Date(i.createTime).toLocaleString()}`)}function lt(i){return/^(\d{1,3}\.){3}\d{1,3}$/.test(i)?i.split(".").every(o=>{let r=parseInt(o,10);return r>=0&&r<=255}):!1}function bn(i){if(!/^(\d{1,3}\.){3}\d{1,3}\/\d{1,2}$/.test(i))return!1;let t=i.split("/");if(t.length!==2)return!1;let o=t[0],r=t[1];if(!o||!r)return!1;let s=parseInt(r,10);return lt(o)&&s>=0&&s<=32}var qe=new bi.Command("acls");qe.description("Manage Access Control Lists (ACLs)");qe.command("list").description("List all Access Control Lists").option("-l, --limit <number>","Limit number of results",parseInt,50).option("--json","Output result as JSON").action(async i=>{try{let e=await De();c.start("Fetching ACLs...");let t=await e.listAcls({pageSize:i.limit});c.succeed(`Retrieved ${t.accessControlLists?.length||0} ACL(s)`),i.json?console.log(JSON.stringify(t,null,2)):(n.newline(),t.accessControlLists&&t.accessControlLists.length>0?t.accessControlLists.forEach(o=>{let r=o.enabled!==!1?"":" (disabled)";n.info(`[${o.id}] ${o.name}${r}`),n.newline()}):(n.info("No ACLs found"),n.newline(),n.info("Create one with: sinch sip acls create")))}catch(e){c.stop(),n.error(`Failed to list ACLs: ${e.message}`),process.exit(1)}});qe.command("get").description("Get an ACL by ID").argument("<acl-id>","ACL ID to retrieve").option("--json","Output result as JSON").action(async(i,e)=>{try{let t=await De();c.start("Fetching ACL...");let o=await t.getAcl(i);c.succeed("ACL retrieved"),e.json?console.log(JSON.stringify(o,null,2)):(n.newline(),Ii(o))}catch(t){c.stop(),n.error(`Failed to get ACL: ${t.message}`),process.exit(1)}});qe.command("create").description("Create a new Access Control List").option("-n, --name <name>","ACL name (required)").option("--enabled","Enable the ACL (default: true)").option("--disabled","Create ACL in disabled state").option("-i, --ip <address>","IP address for initial IP range (required)").option("-r, --range <cidr>","CIDR mask for IP range (default: 32)",parseInt).option("--ip-description <text>","Description for the IP range").option("--non-interactive","Skip prompts, use defaults for missing options").option("--json","Output result as JSON").action(async i=>{try{let e=i.name,t=i.enabled??!i.disabled,o=i.ip,r=i.range,s=i.ipDescription,a=!i.nonInteractive;e||(a?e=(await Z.default.prompt([{type:"input",name:"name",message:"Enter ACL name:",validate:m=>m?!0:"ACL name is required"}])).name:(n.error("Name is required. Use --name <name>"),process.exit(1))),i.enabled===void 0&&!i.disabled&&a&&(t=(await Z.default.prompt([{type:"confirm",name:"enabled",message:"Enable ACL?",default:!0}])).enabled),o?lt(o)||(n.error(`Invalid IP address format: ${o}`),process.exit(1)):a?o=(await Z.default.prompt([{type:"input",name:"ipAddress",message:"Enter IP address for initial IP range (required):",validate:m=>m?lt(m)?!0:"Invalid IP address format":"At least one IP range is required to create an ACL"}])).ipAddress:(n.error("IP address is required. Use --ip <address>"),process.exit(1)),r===void 0&&a&&(r=(await Z.default.prompt([{type:"input",name:"range",message:"Enter CIDR mask (default 32):",default:"32",filter:m=>parseInt(m,10),validate:m=>{let w=parseInt(m,10);return!isNaN(w)&&w>=0&&w<=32?!0:"Please enter a number between 0 and 32"}}])).range),s===void 0&&a&&(s=(await Z.default.prompt([{type:"input",name:"description",message:"Enter IP range description (optional):"}])).description||void 0);let l=await De(),p={ipAddress:o};r!==void 0&&(p.range=r),s&&(p.description=s),c.start("Creating ACL...");let d=await l.createAcl({name:e,enabled:t,ipRanges:[p]});c.succeed("ACL created successfully!"),i.json?console.log(JSON.stringify(d,null,2)):(n.newline(),Ii(d),n.newline(),n.info(`Add an IP range: sinch sip acls ip-ranges add ${d.id}`))}catch(e){c.stop(),n.error(`Failed to create ACL: ${e.message}`),process.exit(1)}});qe.command("update").description("Update an ACL").argument("<acl-id>","ACL ID to update").option("-n, --name <name>","New ACL name").option("--enabled","Enable the ACL").option("--disabled","Disable the ACL").option("--non-interactive","Skip prompts, use current values for missing options").option("--json","Output result as JSON").action(async(i,e)=>{try{let t=await De();c.start("Fetching current ACL details...");let o=await t.getAcl(i);c.stop();let r=e.name,s;e.enabled?s=!0:e.disabled&&(s=!1);let a=!e.nonInteractive;r||(a?r=(await Z.default.prompt([{type:"input",name:"name",message:"Enter ACL name:",default:o.name,validate:d=>d?!0:"ACL name is required"}])).name:r=o.name),s===void 0&&(a?s=(await Z.default.prompt([{type:"confirm",name:"enabled",message:"Enable ACL?",default:o.enabled??!0}])).enabled:s=o.enabled),c.start("Updating ACL...");let l=await t.updateAcl(i,{name:r,enabled:s});c.succeed("ACL updated successfully!"),e.json?console.log(JSON.stringify(l,null,2)):(n.newline(),Ii(l))}catch(t){c.stop(),n.error(`Failed to update ACL: ${t.message}`),process.exit(1)}});qe.command("delete").description("Delete an ACL").argument("<acl-id>","ACL ID to delete").option("-f, --force","Skip confirmation prompt").action(async(i,e)=>{try{if(!e.force){let{confirm:o}=await Z.default.prompt([{type:"confirm",name:"confirm",message:`Are you sure you want to delete ACL ${i}?`,default:!1}]);if(!o){n.info("Deletion cancelled");return}}let t=await De();c.start("Deleting ACL..."),await t.deleteAcl(i),c.succeed("ACL deleted successfully")}catch(t){c.stop(),n.error(`Failed to delete ACL: ${t.message}`),process.exit(1)}});qe.command("trunks").description("List trunks using an ACL").argument("<acl-id>","ACL ID").option("-l, --limit <number>","Limit number of results",parseInt,50).option("--json","Output result as JSON").action(async(i,e)=>{try{let t=await De();c.start("Fetching trunks...");let o=await t.getAclTrunks(i,{pageSize:e.limit});c.succeed(`Retrieved ${o.trunks?.length||0} trunk(s)`),e.json?console.log(JSON.stringify(o,null,2)):(n.newline(),o.trunks&&o.trunks.length>0?o.trunks.forEach(r=>{n.info(`[${r.id}] ${r.name}`),r.hostName&&n.info(` Host: ${r.hostName}`),n.newline()}):n.info("No trunks are using this ACL"))}catch(t){c.stop(),n.error(`Failed to list trunks: ${t.message}`),process.exit(1)}});var At=new bi.Command("ip-ranges");At.description("Manage IP ranges for ACLs");At.command("list").description("List IP ranges for an ACL").argument("<acl-id>","ACL ID").option("-l, --limit <number>","Limit number of results",parseInt,50).option("--json","Output result as JSON").action(async(i,e)=>{try{let t=await De();c.start("Fetching IP ranges...");let o=await t.listIpRanges(i,{pageSize:e.limit});c.succeed(`Retrieved ${o.ipRanges?.length||0} IP range(s)`),e.json?console.log(JSON.stringify(o,null,2)):(n.newline(),o.ipRanges&&o.ipRanges.length>0?o.ipRanges.forEach(r=>{let s=r.range||r.ipAddress||"N/A";n.info(`[${r.id}] ${s}`),r.description&&n.info(` ${r.description}`),n.newline()}):(n.info("No IP ranges found for this ACL"),n.newline(),n.info(`Add one with: sinch sip acls ip-ranges add ${i}`)))}catch(t){c.stop(),n.error(`Failed to list IP ranges: ${t.message}`),process.exit(1)}});At.command("add").description("Add an IP range to an ACL").argument("<acl-id>","ACL ID").option("-d, --description <description>","Description for the IP range").option("-i, --ip <ip>","Single IP address (e.g., 192.168.1.1)").option("-r, --range <cidr>","CIDR range (e.g., 192.168.1.0/24)").option("--non-interactive","Skip prompts, use defaults for missing options").option("--json","Output result as JSON").action(async(i,e)=>{try{let t=e.description,o=e.ip,r=e.range,s=!e.nonInteractive;o&&r&&(n.error("Cannot specify both --ip and --range. Please provide only one."),process.exit(1)),!o&&!r&&(s?(await Z.default.prompt([{type:"list",name:"type",message:"What would you like to add?",choices:[{name:"Single IP address",value:"ip"},{name:"CIDR range",value:"range"}]}])).type==="ip"?o=(await Z.default.prompt([{type:"input",name:"ipAddress",message:"Enter IP address (e.g., 192.168.1.1):",validate:m=>m?lt(m)?!0:"Invalid IP address format":"IP address is required"}])).ipAddress:r=(await Z.default.prompt([{type:"input",name:"range",message:"Enter CIDR range (e.g., 192.168.1.0/24):",validate:m=>m?bn(m)?!0:"Invalid CIDR format (e.g., 192.168.1.0/24)":"CIDR range is required"}])).range:(n.error("Either --ip or --range is required"),process.exit(1))),o&&!lt(o)&&(n.error(`Invalid IP address format: ${o}`),process.exit(1)),r&&!bn(r)&&(n.error(`Invalid CIDR range format: ${r}. Expected format: 192.168.1.0/24`),process.exit(1)),!t&&s&&(t=(await Z.default.prompt([{type:"input",name:"description",message:"Enter description (optional):"}])).description||void 0);let a=await De();c.start("Adding IP range...");let l={description:t};o?l.ipAddress=o:r&&(l.range=r);let p=await a.addIpRange(i,l);c.succeed("IP range added successfully!"),e.json?console.log(JSON.stringify(p,null,2)):(n.newline(),is(p))}catch(t){c.stop(),n.error(`Failed to add IP range: ${t.message}`),process.exit(1)}});At.command("update").description("Update an IP range").argument("<acl-id>","ACL ID").argument("<ip-range-id>","IP range ID to update").option("-d, --description <description>","New description").option("-i, --ip <ip>","New single IP address").option("-r, --range <cidr>","New CIDR range").option("--non-interactive","Skip prompts, use current values for missing options").option("--json","Output result as JSON").action(async(i,e,t)=>{try{let o=await De();c.start("Fetching current IP range details...");let r;try{r=await o.getIpRange(i,e)}catch(m){c.stop(),n.error(`IP range ${e} not found in ACL ${i}: ${m.message}`),process.exit(1)}c.stop();let s=t.description,a=t.ip,l=t.range,p=!t.nonInteractive;if(a&&l&&(n.error("Cannot specify both --ip and --range. Please provide only one."),process.exit(1)),s===void 0&&p?s=(await Z.default.prompt([{type:"input",name:"description",message:"Enter description:",default:r.description||""}])).description||void 0:s===void 0&&(s=r.description),!a&&!l&&p){let m=r.range||r.ipAddress||"",w=r.range?"range":"ip";(await Z.default.prompt([{type:"list",name:"type",message:"Update as:",choices:[{name:"Single IP address",value:"ip"},{name:"CIDR range",value:"range"}],default:w}])).type==="ip"?(a=(await Z.default.prompt([{type:"input",name:"ipAddress",message:"Enter IP address:",default:w==="ip"?m:"",validate:v=>v?lt(v)?!0:"Invalid IP address format":"IP address is required"}])).ipAddress,l=void 0):(l=(await Z.default.prompt([{type:"input",name:"range",message:"Enter CIDR range:",default:w==="range"?m:"",validate:v=>v?bn(v)?!0:"Invalid CIDR format":"CIDR range is required"}])).range,a=void 0)}else!a&&!l?(a=r.ipAddress,l=r.range):a?l=void 0:l&&(a=void 0);a&&!lt(a)&&(n.error(`Invalid IP address format: ${a}`),process.exit(1)),l&&!bn(l)&&(n.error(`Invalid CIDR range format: ${l}`),process.exit(1)),c.start("Updating IP range...");let d={description:s};a?d.ipAddress=a:l&&(d.range=l);let u=await o.updateIpRange(i,e,d);c.succeed("IP range updated successfully!"),t.json?console.log(JSON.stringify(u,null,2)):(n.newline(),is(u))}catch(o){c.stop(),n.error(`Failed to update IP range: ${o.message}`),process.exit(1)}});At.command("delete").description("Delete an IP range").argument("<acl-id>","ACL ID").argument("<ip-range-id>","IP range ID to delete").option("-f, --force","Skip confirmation prompt").action(async(i,e,t)=>{try{if(!t.force){let{confirm:r}=await Z.default.prompt([{type:"confirm",name:"confirm",message:`Are you sure you want to delete IP range ${e}?`,default:!1}]);if(!r){n.info("Deletion cancelled");return}}let o=await De();c.start("Deleting IP range..."),await o.deleteIpRange(i,e),c.succeed("IP range deleted successfully")}catch(o){c.stop(),n.error(`Failed to delete IP range: ${o.message}`),process.exit(1)}});qe.addCommand(At);os.exports=qe});var cs=N((su,as)=>{"use strict";var ss=require("commander");T();R();E();Ye();async function In(){await f.load(),await f.hasCredentials()||(n.error('Not authenticated. Run "sinch auth login" first.'),process.exit(1));let e=f.getApiConfig();return new oe({projectId:e.projectId,credentials:e.credentials})}function $i(i){n.info(`ISO Code: ${i.isoCode}`),n.info(`Country: ${i.name}`),n.info(`Continent: ${i.continent}`),n.info(`Dialing Codes: ${i.countryDialingCodes.join(", ")}`),n.info(`Status: ${i.enabled?"enabled":"disabled"}`)}var Et=new ss.Command("countries");Et.description("Manage country permissions for dialing");Et.command("list").description("List all country permissions").option("-l, --limit <number>","Limit number of results",parseInt,50).option("--json","Output result as JSON").action(async i=>{try{let e=await In();c.start("Fetching country permissions...");let t=await e.listCountryPermissions({pageSize:i.limit});c.succeed(`Retrieved ${t.countryPermissions?.length||0} country permission(s)`),i.json?console.log(JSON.stringify(t,null,2)):(n.newline(),t.countryPermissions&&t.countryPermissions.length>0?([...t.countryPermissions].sort((r,s)=>r.isoCode.localeCompare(s.isoCode)).forEach(r=>{let s=r.enabled?"\u2713 enabled":"\u2717 disabled",a=r.name.padEnd(30);n.info(`${r.isoCode.padEnd(4)} ${a} ${s}`)}),n.newline(),n.info("Enable a country: sinch sip countries enable <iso-code>"),n.info("Disable a country: sinch sip countries disable <iso-code>")):n.info("No country permissions found"))}catch(e){c.stop(),n.error(`Failed to list country permissions: ${e.message}`),process.exit(1)}});Et.command("get").description("Get a specific country permission by ISO code").argument("<iso-code>","ISO country code (e.g., US, CA, *)").option("--json","Output result as JSON").action(async(i,e)=>{try{let t=await In();c.start("Fetching country permission...");let o=await t.getCountryPermission(i.toUpperCase());c.succeed("Country permission retrieved"),e.json?console.log(JSON.stringify(o,null,2)):(n.newline(),$i(o))}catch(t){c.stop(),n.error(`Failed to get country permission: ${t.message}`),process.exit(1)}});Et.command("enable").description("Enable a country for dialing").argument("<iso-code>","ISO country code (e.g., US, CA, *)").option("--json","Output result as JSON").action(async(i,e)=>{try{let t=await In();c.start(`Enabling country ${i.toUpperCase()}...`);let o=await t.updateCountryPermission(i.toUpperCase(),!0);c.succeed(`Country ${i.toUpperCase()} enabled for dialing`),e.json?console.log(JSON.stringify(o,null,2)):(n.newline(),$i(o),n.newline(),n.info(`Country ${i.toUpperCase()} is now enabled for dialing`))}catch(t){c.stop(),n.error(`Failed to enable country: ${t.message}`),process.exit(1)}});Et.command("disable").description("Disable a country for dialing").argument("<iso-code>","ISO country code (e.g., US, CA, *)").option("--json","Output result as JSON").action(async(i,e)=>{try{let t=await In();c.start(`Disabling country ${i.toUpperCase()}...`);let o=await t.updateCountryPermission(i.toUpperCase(),!1);c.succeed(`Country ${i.toUpperCase()} disabled for dialing`),e.json?console.log(JSON.stringify(o,null,2)):(n.newline(),$i(o),n.newline(),n.info(`Country ${i.toUpperCase()} is now disabled for dialing`))}catch(t){c.stop(),n.error(`Failed to disable country: ${t.message}`),process.exit(1)}});as.exports=Et});var ps=N((uu,ds)=>{"use strict";var ls=require("commander");T();R();E();Ye();async function Ec(){await f.load(),await f.hasCredentials()||(n.error('Not authenticated. Run "sinch auth login" first.'),process.exit(1));let e=f.getApiConfig();return new oe({projectId:e.projectId,credentials:e.credentials})}var Pi=new ls.Command("credential-lists");Pi.description("Manage credential list relationships");Pi.command("trunks").description("Get trunks using a credential list").argument("<credential-list-id>","Credential list ID").option("-l, --limit <number>","Limit number of results",parseInt,50).option("--json","Output result as JSON").action(async(i,e)=>{try{let t=await Ec();c.start("Fetching trunks using credential list...");let o=await t.getCredentialListTrunks(i,{pageSize:e.limit});c.succeed(`Retrieved ${o.trunks?.length||0} trunk(s)`),e.json?console.log(JSON.stringify(o,null,2)):(n.newline(),o.trunks&&o.trunks.length>0?(n.info(`Trunks using credential list ${i}:`),n.newline(),o.trunks.forEach(r=>{n.info(`[${r.id}] ${r.name}`),r.hostName&&n.info(` Host: ${r.hostName}`),n.info(` Caller ID: ${r.enableCallerId?"enabled":"disabled"}`),n.newline()}),o.totalItems&&n.info(`Total: ${o.totalItems} trunk(s)`)):n.info("No trunks found using this credential list"))}catch(t){c.stop(),n.error(`Failed to get trunks for credential list: ${t.message}`),process.exit(1)}});ds.exports=Pi});var gs=N((Su,en)=>{"use strict";var us=require("commander");T();R();E();Ye();It();async function fs(){await f.load(),await f.hasCredentials()||(n.error('Not authenticated. Run "sinch auth login" first.'),process.exit(1));let e=f.getApiConfig();return new oe({projectId:e.projectId,credentials:e.credentials})}function ms(i){if(!i){let t=new Date;return`>=${new Date(t.getTime()-1440*60*1e3).toISOString()}`}if(i.startsWith(">=")||i.startsWith("<=")||i.startsWith(">")||i.startsWith("<"))return i;let e=i.split("-");if(e.length===1&&e[0]){let t=e[0];return`>=${t}-01-01T00:00:00Z,<=${t}-12-31T23:59:59Z`}else if(e.length===2&&e[0]&&e[1]){let t=e[0],o=e[1],r=new Date(parseInt(t),parseInt(o),0).getDate();return`>=${t}-${o}-01T00:00:00Z,<=${t}-${o}-${r.toString().padStart(2,"0")}T23:59:59Z`}else return`>=${i}T00:00:00Z,<=${i}T23:59:59Z`}function $n(i){if(i===void 0||i===0)return"-";let e=Math.floor(i/3600),t=Math.floor(i%3600/60),o=i%60;return e>0?`${e}h ${t}m ${o}s`:t>0?`${t}m ${o}s`:`${o}s`}function Ai(i){return!i||!i.amount?"-":`${parseFloat(i.amount).toFixed(4)} ${i.currencyCode}`}function kc(i,e=!1){n.info(`Call ID: ${i.callId}`),n.info(`From: ${q(i.from)}`),n.info(`To: ${q(i.to)}`),n.info(`Direction: ${i.direction}`),n.info(`Status: ${i.callResult||"In Progress"}`),(e||i.durationSeconds)&&n.info(`Duration: ${$n(i.durationSeconds)}`),(e||i.billingDurationSeconds)&&n.info(`Billing Duration: ${$n(i.billingDurationSeconds)}`),i.price&&n.info(`Cost: ${Ai(i.price)}`),n.info(`Trunk ID: ${i.trunkId}`),n.info(`Created: ${new Date(i.createTime).toLocaleString()}`),i.answerTime&&n.info(`Answered: ${new Date(i.answerTime).toLocaleString()}`),i.endTime&&n.info(`Ended: ${new Date(i.endTime).toLocaleString()}`)}var Pn=new us.Command("calls");Pn.description("View call history and details");Pn.command("list").description("List calls with filtering options").option("--from <number>","Filter by originating phone number (supports partial matching)").option("--to <number>","Filter by destination phone number (supports partial matching)").option("--trunk-id <id>","Filter by trunk ID").option("--direction <direction>","Filter by direction (INBOUND or OUTBOUND)").option("--result <result>","Filter by call result (COMPLETED, NO_ANSWER, CANCEL, BUSY, FAILED)").option("--date <date>","Filter by date (YYYY-MM-DD, YYYY-MM, or YYYY). Defaults to last 24 hours.").option("--page <number>","Page number",parseInt).option("--page-size <number>","Number of results per page (max 1000)",parseInt,100).option("--json","Output result as JSON").action(async i=>{try{let e=await fs(),t={pageSize:i.pageSize};if(i.from&&(t.from=i.from),i.to&&(t.to=i.to),i.trunkId&&(t.trunkId=i.trunkId),i.direction&&(["INBOUND","OUTBOUND"].includes(i.direction.toUpperCase())||(n.error("Invalid direction. Must be INBOUND or OUTBOUND."),process.exit(1)),t.direction=i.direction.toUpperCase()),i.result){let r=["COMPLETED","NO_ANSWER","CANCEL","BUSY","FAILED"];r.includes(i.result.toUpperCase())||(n.error(`Invalid result. Must be one of: ${r.join(", ")}`),process.exit(1)),t.callResult=i.result.toUpperCase()}i.page&&(t.page=i.page),t.createTime=ms(i.date),c.start("Fetching calls...");let o=await e.findCalls(t);c.succeed(`Retrieved ${o.calls?.length||0} call(s)`),i.json?console.log(JSON.stringify(o,null,2)):(n.newline(),o.calls&&o.calls.length>0?(o.calls.forEach(r=>{let s=$n(r.durationSeconds),a=r.callResult||"In Progress",l=Ai(r.price);n.info(`${r.callId}`),n.info(` ${q(r.from)} \u2192 ${q(r.to)}`),n.info(` ${r.direction} | ${a} | ${s} | ${l}`),n.info(` ${new Date(r.createTime).toLocaleString()}`),n.newline()}),o.totalItems&&(n.info(`Total: ${o.totalItems} call(s)`),o.pageNumber&&n.info(`Page: ${o.pageNumber}`))):(n.info("No calls found matching the filters"),n.newline(),n.info("Try adjusting your filters or date range.")))}catch(e){c.fail("Failed to fetch calls"),n.error(e.message),process.exit(1)}});Pn.command("get").description("Get details of a specific call").argument("<call-id>","Call ID").option("--json","Output result as JSON").action(async(i,e)=>{try{let t=await fs();c.start(`Fetching call ${i}...`);let o=await t.getCall(i);c.succeed("Call retrieved"),e.json?console.log(JSON.stringify(o,null,2)):(n.newline(),kc(o,!0))}catch(t){c.fail("Failed to get call"),n.error(t.message),process.exit(1)}});en.exports=Pn;en.exports.parseDateFilter=ms;en.exports.formatDuration=$n;en.exports.formatPrice=Ai});var ws=N((bu,ys)=>{"use strict";var hs=require("commander"),Tc=Qr(),Nc=ns(),Rc=rs(),Dc=cs(),xc=ps(),Oc=gs(),Xe=new hs.Command("sip");Xe.description("Manage Elastic SIP Trunking resources");Xe.addCommand(Tc);Xe.addCommand(Nc);Xe.addCommand(Rc);Xe.addCommand(Dc);Xe.addCommand(xc);Xe.addCommand(Oc);ys.exports=Xe});var Ss=N((Eu,vs)=>{"use strict";var Cs=require("commander"),ve=y(require("inquirer"));T();R();E();It();async function An(){return await f.load(),await f.hasCredentials()||(n.error('Not authenticated. Run "sinch auth login" first.'),process.exit(1)),(await f.createSinchClient()).numbers}function Ei(i){n.info(`Phone Number: ${q(i.phoneNumber)}`),i.displayName&&n.info(`Display Name: ${i.displayName}`),n.info(`Region: ${i.regionCode}`),n.info(`Type: ${i.type}`),n.info(`Capabilities: ${i.capability?.join(", ")||"none"}`),i.money&&n.info(`Cost: ${i.money.amount} ${i.money.currencyCode}/month`),i.nextChargeDate&&n.info(`Next Charge: ${new Date(i.nextChargeDate).toLocaleDateString()}`),i.expireAt&&n.info(`Expires: ${new Date(i.expireAt).toLocaleDateString()}`),i.smsConfiguration&&(n.info(`SMS Service Plan: ${i.smsConfiguration.servicePlanId||"n/a"}`),i.smsConfiguration.campaignId&&n.info(`SMS Campaign: ${i.smsConfiguration.campaignId}`)),i.voiceConfiguration&&(n.info(`Voice Type: ${i.voiceConfiguration.type||"n/a"}`),i.voiceConfiguration.appId&&n.info(`Voice App: ${i.voiceConfiguration.appId}`),i.voiceConfiguration.trunkId&&n.info(`EST Trunk: ${i.voiceConfiguration.trunkId}`)),i.callbackUrl&&n.info(`Callback: ${i.callbackUrl}`)}var kt=new Cs.Command("active");kt.description("Manage your active phone numbers");kt.command("list").description("List all active numbers for this project").option("-r, --region <code>","Filter by region code (e.g. US, GB, SE)").option("-t, --type <type>","Filter by type: MOBILE, LOCAL, or TOLL_FREE").option("-c, --capability <cap...>","Filter by capability: SMS, VOICE").option("-p, --pattern <digits>","Filter by digit pattern").option("--search-pattern <mode>","Pattern match mode: START, CONTAINS, or END").option("-l, --limit <number>","Max results",parseInt).option("--order-by <field>","Sort by: phoneNumber or displayName").option("--non-interactive","Skip prompts, require all options as flags").option("--json","Output result as JSON").action(async i=>{try{let e=!i.nonInteractive,t=i.region,o=i.type;!t&&e&&(t=(await ve.default.prompt([{type:"input",name:"regionCode",message:"Region code to filter by (e.g. US, GB, SE) \u2014 leave blank for all:"}])).regionCode||void 0),!o&&e&&(o=(await ve.default.prompt([{type:"list",name:"type",message:"Filter by number type?",choices:[{name:"All types",value:""},{name:"MOBILE",value:"MOBILE"},{name:"LOCAL",value:"LOCAL"},{name:"TOLL_FREE",value:"TOLL_FREE"}]}])).type||void 0);let r=await An();c.start("Fetching active numbers...");let s=i.limit||100,a=[],l={};t&&(l.regionCode=t),o&&(l.type=o),i.capability&&(l.capability=i.capability),i.pattern&&(l["numberPattern.pattern"]=i.pattern),i.searchPattern&&(l["numberPattern.searchPattern"]=i.searchPattern),i.limit&&(l.pageSize=i.limit),i.orderBy&&(l.orderBy=i.orderBy);for await(let d of r.list(l))if(a.push(d),a.length>=s)break;let p=a.length;c.succeed(`Found ${p} active number(s)`),i.json?console.log(JSON.stringify(a,null,2)):(n.newline(),p>0?a.forEach(d=>{let u=d.capability?.join(", ")||"",m=d.displayName?` "${d.displayName}"`:"";console.log(`${q(d.phoneNumber)}${m} [${d.regionCode}] ${d.type} ${u}`)}):(n.info("No active numbers found for this project."),n.newline(),n.info("Search for available numbers: sinch numbers available search")))}catch(e){c.stop(),n.error(`Failed to list active numbers: ${e.message}`),process.exit(1)}});kt.command("get").description("Get details for a specific active number").argument("[phone-number]","Phone number in E.164 format (e.g. +12025550134)").option("--non-interactive","Skip prompts").option("--json","Output result as JSON").action(async(i,e)=>{try{let t=!e.nonInteractive;i||(t?i=(await ve.default.prompt([{type:"input",name:"phoneNumber",message:"Enter the phone number (E.164 format, e.g. +12025550134):",validate:a=>a?a.startsWith("+")?!0:"Phone number must start with + (E.164 format)":"Phone number is required"}])).phoneNumber:(n.error("Phone number is required. Usage: sinch numbers active get <phone-number>"),process.exit(1)));let o=await An();c.start(`Fetching number ${i}...`);let r=await o.get({phoneNumber:i});c.succeed("Number retrieved"),e.json?console.log(JSON.stringify(r,null,2)):(n.newline(),Ei(r))}catch(t){c.stop(),n.error(`Failed to get number: ${t.message}`),process.exit(1)}});kt.command("update").description("Update an active phone number (display name, SMS/Voice config)").argument("[phone-number]","Phone number in E.164 format").option("-d, --display-name <name>","New display name").option("--sms-service-plan <id>","SMS service plan ID (empty string to unlink)").option("--sms-campaign <id>","SMS campaign ID").option("--voice-app <id>","Voice app ID").option("--callback-url <url>","Callback URL for provisioning events").option("--non-interactive","Skip prompts").option("--json","Output result as JSON").action(async(i,e)=>{try{let t=!e.nonInteractive;i||(t?i=(await ve.default.prompt([{type:"input",name:"phoneNumber",message:"Which number do you want to update? (E.164 format):",validate:h=>h?h.startsWith("+")?!0:"Phone number must start with + (E.164 format)":"Phone number is required"}])).phoneNumber:(n.error("Phone number is required. Usage: sinch numbers active update <phone-number>"),process.exit(1)));let o=await An();c.start(`Fetching current details for ${i}...`);let r=await o.get({phoneNumber:i});c.stop();let s=e.displayName,a=e.smsServicePlan,l=e.smsCampaign,p=e.voiceApp,d=e.callbackUrl;if(t){n.newline(),n.info(`Current configuration for ${i}:`),Ei(r),n.newline(),s===void 0&&(s=(await ve.default.prompt([{type:"input",name:"displayName",message:"Display name:",default:r.displayName||""}])).displayName||void 0),d===void 0&&(d=(await ve.default.prompt([{type:"input",name:"callbackUrl",message:"Callback URL (leave blank to keep current):",default:r.callbackUrl||""}])).callbackUrl||void 0);let w=await ve.default.prompt([{type:"checkbox",name:"configure",message:"Which configurations do you want to update?",choices:[{name:"SMS Configuration",value:"sms"},{name:"Voice Configuration",value:"voice"}]}]);if(w.configure.includes("sms")&&a===void 0){let h=await ve.default.prompt([{type:"input",name:"servicePlanId",message:"SMS service plan ID (empty to unlink):",default:r.smsConfiguration?.servicePlanId||""},{type:"input",name:"campaignId",message:"SMS campaign ID (for US numbers):",default:r.smsConfiguration?.campaignId||""}]);a=h.servicePlanId,l=h.campaignId||void 0}w.configure.includes("voice")&&p===void 0&&(p=(await ve.default.prompt([{type:"input",name:"appId",message:"Voice app ID:",default:r.voiceConfiguration?.appId||""}])).appId||void 0)}let u={};if(s!==void 0&&(u.displayName=s),d!==void 0&&(u.callbackUrl=d),a!==void 0&&(u.smsConfiguration={servicePlanId:a},l&&(u.smsConfiguration.campaignId=l)),p!==void 0&&(u.voiceConfiguration={type:"RTC",appId:p}),Object.keys(u).length===0){n.info("No changes specified. Nothing to update.");return}c.start(`Updating ${i}...`);let m=await o.update({phoneNumber:i,updateActiveNumberRequestBody:u});c.succeed("Number updated successfully!"),e.json?console.log(JSON.stringify(m,null,2)):(n.newline(),Ei(m))}catch(t){c.stop(),n.error(`Failed to update number: ${t.message}`),process.exit(1)}});kt.command("release").description("Release (cancel subscription for) an active number").argument("[phone-number]","Phone number in E.164 format").option("-f, --force","Skip confirmation prompt").option("--non-interactive","Skip prompts").option("--json","Output result as JSON").action(async(i,e)=>{try{let t=!e.nonInteractive;if(i||(t?i=(await ve.default.prompt([{type:"input",name:"phoneNumber",message:"Which number do you want to release? (E.164 format):",validate:a=>a?a.startsWith("+")?!0:"Phone number must start with + (E.164 format)":"Phone number is required"}])).phoneNumber:(n.error("Phone number is required. Usage: sinch numbers active release <phone-number>"),process.exit(1))),!e.force){let{confirm:s}=await ve.default.prompt([{type:"confirm",name:"confirm",message:`Are you sure you want to release ${i}? This will cancel your subscription.`,default:!1}]);if(!s){n.info("Release cancelled");return}}let o=await An();c.start(`Releasing ${i}...`);let r=await o.release({phoneNumber:i});c.succeed(`Number ${i} released`),e.json?console.log(JSON.stringify(r,null,2)):(n.newline(),n.info(`${i} has been released from your project.`))}catch(t){c.stop(),n.error(`Failed to release number: ${t.message}`),process.exit(1)}});vs.exports=kt});var As=N((xu,Ps)=>{"use strict";var bs=require("commander"),A=y(require("inquirer"));T();R();E();Ye();It();async function Fc(){let i=f.getApiConfig();return new oe({projectId:i.projectId,credentials:i.credentials})}async function Is(){try{c.start("Fetching EST trunks...");let e=await(await Fc()).listTrunks({pageSize:50});c.stop();let t=e.trunks||[];if(t.length===0){console.log("No trunks found. You can create one with: sinch sip trunks create");let{trunkId:s}=await A.default.prompt([{type:"input",name:"trunkId",message:"Enter trunk ID manually:",validate:a=>a?!0:"Trunk ID is required for EST"}]);return s}let o=t.map(s=>({name:`${s.name||s.id}${s.hostName?` (${s.hostName})`:""}`,value:s.id}));o.push(new A.default.Separator),o.push({name:"Enter trunk ID manually",value:"__manual__"});let{selected:r}=await A.default.prompt([{type:"list",name:"selected",message:"Select a trunk:",choices:o}]);if(r==="__manual__"){let{trunkId:s}=await A.default.prompt([{type:"input",name:"trunkId",message:"Enter trunk ID:",validate:a=>a?!0:"Trunk ID is required"}]);return s}return r}catch{c.stop();let{trunkId:i}=await A.default.prompt([{type:"input",name:"trunkId",message:"EST trunk ID (could not fetch trunk list):",validate:e=>e?!0:"Trunk ID is required for EST"}]);return i}}async function $s(){try{c.start("Fetching fax services...");let i=await f.createSinchClient(),e=[];for await(let r of i.fax.services.list({projectId:f.getApiConfig().projectId}))e.push(r);if(c.stop(),e.length===0){console.log("No fax services found.");let{serviceId:r}=await A.default.prompt([{type:"input",name:"serviceId",message:"Enter fax service ID manually:",validate:s=>s?!0:"Service ID is required for FAX"}]);return r}let t=e.map(r=>({name:`${r.name||r.id}${r.defaultForProject?" (default)":""}`,value:r.id}));t.push(new A.default.Separator),t.push({name:"Enter service ID manually",value:"__manual__"});let{selected:o}=await A.default.prompt([{type:"list",name:"selected",message:"Select a fax service:",choices:t}]);if(o==="__manual__"){let{serviceId:r}=await A.default.prompt([{type:"input",name:"serviceId",message:"Enter fax service ID:",validate:s=>s?!0:"Service ID is required"}]);return r}return o}catch{c.stop();let{serviceId:i}=await A.default.prompt([{type:"input",name:"serviceId",message:"Fax service ID (could not fetch service list):",validate:e=>e?!0:"Service ID is required for FAX"}]);return i}}async function kn(){return await f.load(),await f.hasCredentials()||(n.error('Not authenticated. Run "sinch auth login" first.'),process.exit(1)),(await f.createSinchClient()).numbers}function En(i){let e=i.capability?.join(", ")||"",t=i.setupPrice?`${i.setupPrice.amount} ${i.setupPrice.currencyCode} setup`:"",o=i.monthlyPrice?`${i.monthlyPrice.amount} ${i.monthlyPrice.currencyCode}/mo`:"",r=[t,o].filter(Boolean).join(" + "),s=i.supportingDocumentationRequired?" [docs required]":"";return`${q(i.phoneNumber)} ${e} ${r}${s}`}async function jc(i,e){let t,o,r,{configureSms:s}=await A.default.prompt([{type:"confirm",name:"configureSms",message:"Configure SMS for this number?",default:!1}]);if(s){let m=await A.default.prompt([{type:"input",name:"servicePlanId",message:"SMS service plan ID:",validate:w=>w?!0:"Service plan ID is required for SMS"},{type:"input",name:"campaignId",message:"SMS campaign ID (required for US, optional otherwise):"}]);t={servicePlanId:m.servicePlanId},m.campaignId&&(t.campaignId=m.campaignId)}let{voiceType:a}=await A.default.prompt([{type:"list",name:"voiceType",message:"Voice configuration:",choices:[{name:"None (configure later)",value:"none"},{name:"RTC \u2014 Real-time Communication",value:"RTC"},{name:"EST \u2014 Elastic SIP Trunking",value:"EST"},{name:"FAX",value:"FAX"}]}]);if(a==="RTC"){let{appId:m}=await A.default.prompt([{type:"input",name:"appId",message:"Voice app ID:",validate:w=>w?!0:"Voice app ID is required"}]);o={type:"RTC",appId:m}}else a==="EST"?o={type:"EST",trunkId:await Is()}:a==="FAX"&&(o={type:"FAX",serviceId:await $s()});r=(await A.default.prompt([{type:"input",name:"callbackUrl",message:"Callback URL for provisioning events (optional):"}])).callbackUrl||void 0;let{confirm:p}=await A.default.prompt([{type:"confirm",name:"confirm",message:`Rent ${q(e)}? This will activate it on your project.`,default:!0}]);if(!p){console.log("Rental cancelled.");return}let d={};t&&(d.smsConfiguration=t),o&&(d.voiceConfiguration=o),r&&(d.callbackUrl=r),c.start(`Renting ${e}...`);let u=await i.rent({phoneNumber:e,rentNumberRequestBody:d});c.succeed(`${q(u.phoneNumber)} rented successfully!`),console.log(),console.log(` Phone Number: ${q(u.phoneNumber)}`),console.log(` Region: ${u.regionCode}`),console.log(` Type: ${u.type}`),console.log(` Capabilities: ${u.capability?.join(", ")}`),u.money&&console.log(` Cost: ${u.money.amount} ${u.money.currencyCode}/month`),console.log(),console.log(`Manage this number: sinch numbers active get ${e}`)}var Tt=new bs.Command("available");Tt.description("Search and rent available phone numbers");Tt.command("search").description("Search for available phone numbers to rent").option("-r, --region <code>","Region code (required, e.g. US, GB, SE)").option("-t, --type <type>","Number type (required): MOBILE, LOCAL, or TOLL_FREE").option("-c, --capabilities <cap...>","Capabilities: SMS, VOICE").option("-p, --pattern <digits>","Digit pattern to match").option("--search-pattern <mode>","Pattern match: START, CONTAINS, or END").option("-s, --size <number>","Max results",parseInt).option("--non-interactive","Skip prompts, require all options as flags").option("--json","Output result as JSON").action(async i=>{try{let e=!i.nonInteractive,t=i.region,o=i.type,r=i.capabilities;if(t||(e?t=(await A.default.prompt([{type:"input",name:"regionCode",message:"Region code (e.g. US, GB, SE):",default:"US"}])).regionCode.toUpperCase():(n.error("Region code is required. Use --region <code>"),process.exit(1))),o||(e?o=(await A.default.prompt([{type:"list",name:"type",message:"What type of number?",choices:[{name:"LOCAL \u2014 assigned to a geographic region",value:"LOCAL"},{name:"MOBILE \u2014 belongs to a mobile range",value:"MOBILE"},{name:"TOLL_FREE \u2014 free for the caller",value:"TOLL_FREE"}]}])).type:(n.error("Number type is required. Use --type <MOBILE|LOCAL|TOLL_FREE>"),process.exit(1))),!r&&e){let u=await A.default.prompt([{type:"checkbox",name:"capabilities",message:"Required capabilities:",choices:[{name:"SMS",value:"SMS",checked:!0},{name:"VOICE",value:"VOICE"}]}]);r=u.capabilities.length>0?u.capabilities:void 0}let s=i.pattern,a=i.searchPattern;!s&&e&&(s=(await A.default.prompt([{type:"input",name:"pattern",message:"Digit pattern to search for (leave blank for any):"}])).pattern||void 0,s&&!a&&(a=(await A.default.prompt([{type:"list",name:"searchPattern",message:"Where should the pattern appear?",choices:[{name:"Starts with these digits",value:"START"},{name:"Contains these digits",value:"CONTAINS"},{name:"Ends with these digits",value:"END"}]}])).searchPattern));let l=await kn();c.start(`Searching for ${o} numbers in ${t}...`);let p=await l.searchForAvailableNumbers({regionCode:t,type:o,capabilities:r,"numberPattern.pattern":s,"numberPattern.searchPattern":a,size:i.size}),d=p.availableNumbers?.length||0;if(c.succeed(`Found ${d} available number(s)`),i.json)console.log(JSON.stringify(p,null,2));else if(d===0)console.log(),console.log("No numbers found matching your criteria."),console.log("Try a different region, type, or relax your pattern filter.");else if(e){let u=p.availableNumbers.map(w=>({name:En(w),value:w.phoneNumber}));u.push(new A.default.Separator),u.push({name:"Exit without renting",value:""});let{selected:m}=await A.default.prompt([{type:"list",name:"selected",message:`Select a number to rent (${d} available):`,choices:u,pageSize:Math.min(d+2,20)}]);m&&await jc(l,m)}else console.log(),p.availableNumbers.forEach(u=>console.log(En(u)))}catch(e){c.stop(),n.error(`Failed to search numbers: ${e.message}`),process.exit(1)}});Tt.command("check").description("Check if a specific phone number is available").argument("[phone-number]","Phone number in E.164 format").option("--non-interactive","Skip prompts").option("--json","Output result as JSON").action(async(i,e)=>{try{let t=!e.nonInteractive;i||(t?i=(await A.default.prompt([{type:"input",name:"phoneNumber",message:"Enter the phone number to check (E.164, e.g. +12025550134):",validate:a=>a?a.startsWith("+")?!0:"Must be in E.164 format (starts with +)":"Phone number is required"}])).phoneNumber:(n.error("Phone number is required. Usage: sinch numbers available check <phone-number>"),process.exit(1)));let o=await kn();c.start(`Checking availability for ${i}...`);let r=await o.checkAvailability({phoneNumber:i});c.succeed("Number is available!"),e.json?console.log(JSON.stringify(r,null,2)):(console.log(),console.log(En(r)),console.log(),console.log(`Rent this number: sinch numbers available rent ${i}`))}catch(t){c.stop(),n.error(`${t.message}`),process.exit(1)}});Tt.command("rent").description("Rent (activate) a specific phone number").argument("[phone-number]","Phone number in E.164 format").option("--sms-service-plan <id>","SMS service plan ID").option("--sms-campaign <id>","SMS campaign ID (for US numbers)").option("--voice-app <id>","Voice app ID (for RTC)").option("--voice-type <type>","Voice config type: RTC, EST, or FAX").option("--trunk-id <id>","EST trunk ID (when voice-type is EST)").option("--callback-url <url>","Callback URL for provisioning events").option("-f, --force","Skip confirmation").option("--non-interactive","Skip all prompts").option("--json","Output result as JSON").action(async(i,e)=>{try{let t=!e.nonInteractive;i||(t?i=(await A.default.prompt([{type:"input",name:"phoneNumber",message:"Which number do you want to rent? (E.164 format):",validate:u=>u?u.startsWith("+")?!0:"Must be in E.164 format (starts with +)":"Phone number is required"}])).phoneNumber:(n.error("Phone number is required. Usage: sinch numbers available rent <phone-number>"),process.exit(1)));let o=await kn();if(t){c.start(`Checking availability for ${i}...`);try{let d=await o.checkAvailability({phoneNumber:i});c.succeed("Number is available"),console.log(),console.log(En(d)),console.log()}catch{c.fail("Number may not be available"),n.warn("Could not verify availability. Proceeding anyway..."),n.newline()}}let r,s,a=e.callbackUrl;if(e.smsServicePlan&&(r={servicePlanId:e.smsServicePlan},e.smsCampaign&&(r.campaignId=e.smsCampaign)),(e.voiceApp||e.trunkId)&&(s={type:e.voiceType||"RTC"},e.voiceApp&&(s.appId=e.voiceApp),e.trunkId&&(s.trunkId=e.trunkId)),t&&!r&&!s){let{configureSms:d}=await A.default.prompt([{type:"confirm",name:"configureSms",message:"Configure SMS for this number?",default:!1}]);if(d){let m=await A.default.prompt([{type:"input",name:"servicePlanId",message:"SMS service plan ID:",validate:w=>w?!0:"Service plan ID is required for SMS"},{type:"input",name:"campaignId",message:"SMS campaign ID (required for US, optional otherwise):"}]);r={servicePlanId:m.servicePlanId},m.campaignId&&(r.campaignId=m.campaignId)}let{voiceType:u}=await A.default.prompt([{type:"list",name:"voiceType",message:"Voice configuration:",choices:[{name:"None (configure later)",value:"none"},{name:"RTC \u2014 Real-time Communication",value:"RTC"},{name:"EST \u2014 Elastic SIP Trunking",value:"EST"},{name:"FAX",value:"FAX"}]}]);if(u==="RTC"){let{appId:m}=await A.default.prompt([{type:"input",name:"appId",message:"Voice app ID:",validate:w=>w?!0:"Voice app ID is required"}]);s={type:"RTC",appId:m}}else u==="EST"?s={type:"EST",trunkId:await Is()}:u==="FAX"&&(s={type:"FAX",serviceId:await $s()});a||(a=(await A.default.prompt([{type:"input",name:"callbackUrl",message:"Callback URL for provisioning events (optional):"}])).callbackUrl||void 0)}if(!e.force){let{confirm:d}=await A.default.prompt([{type:"confirm",name:"confirm",message:`Rent ${i}? This will activate it on your project.`,default:!0}]);if(!d){n.info("Rental cancelled");return}}let l={};r&&(l.smsConfiguration=r),s&&(l.voiceConfiguration=s),a&&(l.callbackUrl=a),c.start(`Renting ${i}...`);let p=await o.rent({phoneNumber:i,rentNumberRequestBody:l});c.succeed(`Number ${i} rented successfully!`),e.json?console.log(JSON.stringify(p,null,2)):(console.log(),console.log(` Phone Number: ${q(p.phoneNumber)}`),console.log(` Region: ${p.regionCode}`),console.log(` Type: ${p.type}`),console.log(` Capabilities: ${p.capability?.join(", ")}`),p.money&&console.log(` Cost: ${p.money.amount} ${p.money.currencyCode}/month`),console.log(),console.log(`Manage this number: sinch numbers active get ${i}`))}catch(t){c.stop(),n.error(`Failed to rent number: ${t.message}`),process.exit(1)}});Tt.command("rent-any").description("Rent any number matching your criteria (US LOCAL only)").option("-r, --region <code>","Region code (required)").option("-t, --type <type>","Number type (required): MOBILE, LOCAL, or TOLL_FREE").option("-c, --capabilities <cap...>","Capabilities: SMS, VOICE").option("-p, --pattern <digits>","Digit pattern to match").option("--search-pattern <mode>","Pattern match: START, CONTAINS, or END").option("--sms-service-plan <id>","SMS service plan ID").option("--sms-campaign <id>","SMS campaign ID").option("--voice-app <id>","Voice app ID").option("--callback-url <url>","Callback URL").option("-f, --force","Skip confirmation").option("--non-interactive","Skip all prompts").option("--json","Output result as JSON").action(async i=>{try{let e=!i.nonInteractive,t=i.region,o=i.type,r=i.capabilities;if(t||(e?t=(await A.default.prompt([{type:"input",name:"regionCode",message:"Region code (e.g. US, GB, SE):",default:"US"}])).regionCode.toUpperCase():(n.error("Region code is required. Use --region <code>"),process.exit(1))),o||(e?o=(await A.default.prompt([{type:"list",name:"type",message:"Number type:",choices:[{name:"LOCAL",value:"LOCAL"},{name:"MOBILE",value:"MOBILE"},{name:"TOLL_FREE",value:"TOLL_FREE"}]}])).type:(n.error("Number type is required. Use --type <MOBILE|LOCAL|TOLL_FREE>"),process.exit(1))),!r&&e){let m=await A.default.prompt([{type:"checkbox",name:"capabilities",message:"Required capabilities:",choices:[{name:"SMS",value:"SMS",checked:!0},{name:"VOICE",value:"VOICE"}]}]);r=m.capabilities.length>0?m.capabilities:void 0}let s,a;if(i.smsServicePlan)s={servicePlanId:i.smsServicePlan},i.smsCampaign&&(s.campaignId=i.smsCampaign);else if(e&&(await A.default.prompt([{type:"confirm",name:"configureSms",message:"Configure SMS for this number?",default:!1}])).configureSms){let w=await A.default.prompt([{type:"input",name:"servicePlanId",message:"SMS service plan ID:",validate:h=>h?!0:"Required"},{type:"input",name:"campaignId",message:"SMS campaign ID (optional):"}]);s={servicePlanId:w.servicePlanId},w.campaignId&&(s.campaignId=w.campaignId)}i.voiceApp&&(a={type:"RTC",appId:i.voiceApp});let l=i.callbackUrl;if(!l&&e&&(l=(await A.default.prompt([{type:"input",name:"callbackUrl",message:"Callback URL (optional):"}])).callbackUrl||void 0),!i.force){let{confirm:m}=await A.default.prompt([{type:"confirm",name:"confirm",message:`Rent any available ${o} number in ${t}?`,default:!0}]);if(!m){n.info("Rental cancelled");return}}let p=await kn(),d={regionCode:t,type:o};r&&(d.capabilities=r),i.pattern&&(d.numberPattern={pattern:i.pattern,searchPattern:i.searchPattern||"CONTAINS"}),s&&(d.smsConfiguration=s),a&&(d.voiceConfiguration=a),l&&(d.callbackUrl=l),c.start(`Finding and renting a ${o} number in ${t}...`);let u=await p.rentAny({rentAnyNumberRequestBody:d});c.succeed(`Rented ${u.phoneNumber}!`),i.json?console.log(JSON.stringify(u,null,2)):(console.log(),console.log(` Phone Number: ${q(u.phoneNumber)}`),console.log(` Region: ${u.regionCode}`),console.log(` Type: ${u.type}`),console.log(` Capabilities: ${u.capability?.join(", ")}`),u.money&&console.log(` Cost: ${u.money.amount} ${u.money.currencyCode}/month`),console.log(),console.log(`Manage this number: sinch numbers active get ${u.phoneNumber}`))}catch(e){c.stop(),n.error(`Failed to rent number: ${e.message}`),process.exit(1)}});Ps.exports=Tt});var Ts=N((Lu,ks)=>{"use strict";var Es=require("commander");T();R();E();async function Lc(){return await f.load(),await f.hasCredentials()||(n.error('Not authenticated. Run "sinch auth login" first.'),process.exit(1)),(await f.createSinchClient()).numbers}var ki=new Es.Command("regions");ki.description("List regions where numbers are available");ki.command("list").description("List all available regions for phone numbers").option("-t, --types <type...>","Filter by number type: MOBILE, LOCAL, TOLL_FREE").option("--json","Output result as JSON").action(async i=>{try{let e=await Lc();c.start("Fetching available regions...");let t=await e.availableRegions.list({types:i.types}),o=t.availableRegions?.length||0;c.succeed(`Found ${o} region(s)`),i.json?console.log(JSON.stringify(t,null,2)):(n.newline(),o>0?t.availableRegions.forEach(r=>{console.log(`${r.regionCode} ${r.regionName} [${r.types?.join(", ")}]`)}):n.info("No regions found."))}catch(e){c.stop(),n.error(`Failed to list regions: ${e.message}`),process.exit(1)}});ks.exports=ki});var Ds=N((_u,Rs)=>{"use strict";var Ns=require("commander"),_c=Ss(),Uc=As(),Mc=Ts(),tn=new Ns.Command("numbers");tn.description("Manage Sinch phone numbers \u2014 search, rent, update, and release");tn.addCommand(_c);tn.addCommand(Uc);tn.addCommand(Mc);Rs.exports=tn});async function ye(i){let e={};for(let t of i){if(t.when!==void 0&&!(typeof t.when=="function"?await t.when(e):t.when))continue;let o;switch(t.type){case"input":{let r=await(0,Ae.input)({message:t.message,default:t.default,validate:t.validate});t.filter&&(r=t.filter(r)),o=r;break}case"password":o=await(0,Ae.password)({message:t.message,validate:t.validate});break;case"confirm":o=await(0,Ae.confirm)({message:t.message,default:t.default});break;case"list":o=await(0,Ae.select)({message:t.message,choices:(t.choices||[]).map(r=>typeof r=="string"?{name:r,value:r}:r),default:t.default,pageSize:t.pageSize});break;case"checkbox":o=await(0,Ae.checkbox)({message:t.message,choices:(t.choices||[]).map(r=>typeof r=="string"?{name:r,value:r}:r),pageSize:t.pageSize});break;default:throw new Error(`Unsupported prompt type: ${t.type}`)}e[t.name]=o}return e}var Ae,xs=G(()=>{"use strict";Ae=require("@inquirer/prompts")});var Os,Ti,Ni,Fs=G(()=>{"use strict";Os=require("@sinch/sdk-core");E();Ti=class{client=null;initialized=!1;async initialize(){if(!(this.initialized&&this.client))try{await f.load();let e=await f.getCredentials();if(!e)throw new Error("Not authenticated. Please run: sinch auth login");this.client=new Os.SinchClient({projectId:e.projectId,keyId:e.keyId,keySecret:e.keySecret}),this.initialized=!0}catch(e){throw new Error(`Failed to initialize fax client: ${e.message}`)}}async getClient(){return this.initialized||await this.initialize(),this.client}isInitialized(){return this.initialized}async getServiceConfig(){return await f.load(),{serviceId:f.getFaxServiceId(),senderNumber:f.getFaxSenderNumber()}}async validateConfig(){let e=await this.getServiceConfig(),t=[];return e.serviceId||t.push("fax service ID (set with: sinch config set fax service-id <id>)"),{valid:t.length===0,missing:t}}},Ni=new Ti});var Js={};xe(Js,{FaxManager:()=>Tn,default:()=>Bc,getFaxClient:()=>Us,getFaxManager:()=>Ee});async function Us(){try{return await f.load(),await f.hasCredentials()||(n.error("Not authenticated. Please run: sinch auth login"),process.exit(1)),await Ni.initialize(),await Ni.getClient()}catch(i){n.error(`Failed to initialize fax client: ${i.message}`),process.exit(1)}}async function Ee(){let i=await Us(),e=await f.getFaxCredentials();return new Tn(i,e)}function on(i){n.newline(),n.info("\u{1F4E0} Fax Status"),n.info("\u2550".repeat(50)),n.info(`Status: ${i.status||"N/A"}`),n.info(`ID: ${i.id||"N/A"}`),n.info(`To: ${i.to||"N/A"}`),n.info(`From: ${i.from||"N/A"}`),n.info(`Pages: ${i.numberOfPages??i.pages??"N/A"}`),(i.createTime||i.createdAt)&&n.info(`Created: ${i.createTime||i.createdAt}`),(i.completedTime||i.completedAt)&&n.info(`Completed: ${i.completedTime||i.completedAt}`),i.duration&&n.info(`Duration: ${i.duration}s`),i.attempts!==void 0&&n.info(`Attempts: ${i.attempts}`),i.errorCode&&n.info(`Error Code: ${i.errorCode}`),i.errorMessage&&n.info(`Error: ${i.errorMessage}`),n.info("\u2550".repeat(50)),n.newline()}function Ms(i){n.newline(),n.info("\u{1F4E0} Fax Details"),n.info("\u2550".repeat(50)),n.info(`ID: ${i.id||"N/A"}`),n.info(`Status: ${i.status||"N/A"}`),i.direction&&n.info(`Direction: ${i.direction}`),n.info(`To: ${i.to||"N/A"}`),n.info(`From: ${i.from||"N/A"}`),n.info(`Pages: ${i.numberOfPages??i.pages??"N/A"}`),i.projectId&&n.info(`Project ID: ${i.projectId}`),i.serviceId&&n.info(`Service ID: ${i.serviceId}`),(i.createTime||i.createdAt)&&n.info(`Created: ${i.createTime||i.createdAt}`),(i.startTime||i.startedAt)&&n.info(`Started: ${i.startTime||i.startedAt}`),(i.completedTime||i.completedAt)&&n.info(`Completed: ${i.completedTime||i.completedAt}`),i.duration&&n.info(`Duration: ${i.duration}s`),i.attempts!==void 0&&n.info(`Attempts: ${i.attempts}`),i.maxRetries!==void 0&&n.info(`Max Retries: ${i.maxRetries}`),i.retryDelaySeconds!==void 0&&n.info(`Retry Delay: ${i.retryDelaySeconds}s`),i.resolution&&n.info(`Resolution: ${i.resolution}`),i.imageConversionMethod&&n.info(`Conversion Method: ${i.imageConversionMethod}`),i.headerPageNumbers!==void 0&&n.info(`Header Page Numbers: ${i.headerPageNumbers}`),i.headerText!==void 0&&n.info(`Header Text: ${i.headerText||"(empty)"}`),i.headerTimeZone&&n.info(`Header Timezone: ${i.headerTimeZone}`),i.contentUrl&&n.info(`Content URL: ${i.contentUrl}`),i.hasFile!==void 0&&n.info(`Has File: ${i.hasFile}`),i.callbackUrl&&n.info(`Callback URL: ${i.callbackUrl}`),i.callbackUrlContentType&&n.info(`Callback Type: ${i.callbackUrlContentType}`),i.callId&&n.info(`Call ID: ${i.callId}`),i.price?n.info(`Price: ${i.price.amount} ${i.price.currency_code}`):i.amount&&i.currencyCode?n.info(`Price: ${i.amount} ${i.currencyCode}`):i.pricePerPage&&n.info(`Price Per Page: ${i.pricePerPage}`),i.errorCode&&n.info(`Error Code: ${i.errorCode}`),i.errorMessage&&n.info(`Error: ${i.errorMessage}`),n.info("\u2550".repeat(50)),n.newline()}async function qc(i,e,t){let o=parseInt(t.timeout||"300",10),r=Date.now(),s=5e3;for(t.json||(n.newline(),c.start(`Waiting for fax ${e} to complete (timeout: ${o}s)...`));;)try{let a=await i.getFaxStatus(e,t.serviceId);if(a.status==="completed"||a.status==="failed"){t.json?console.log(JSON.stringify(a,null,2)):(c.succeed(`Fax ${a.status}!`),on(a));return}if((Date.now()-r)/1e3>=o){t.json?console.log(JSON.stringify({...a,timedOut:!0},null,2)):(c.warn(`Timeout reached after ${o}s. Current status:`),on(a));return}await new Promise(p=>setTimeout(p,s))}catch(a){t.json?console.error(JSON.stringify({error:a.message},null,2)):(c.fail("Failed to get fax status"),n.error(a.message)),process.exit(1)}}async function Jc(i,e,t){let o=parseInt(t.interval||"5",10),r=o*1e3;if(t.json){let s=!0,a=setInterval(async()=>{try{let l=await i.getFaxStatus(e,t.serviceId);s||console.log(""),console.log(JSON.stringify(l,null,2)),s=!1,(l.status==="completed"||l.status==="failed")&&(clearInterval(a),process.exit(0))}catch(l){clearInterval(a),console.error(JSON.stringify({error:l.message},null,2)),process.exit(1)}},r);try{let l=await i.getFaxStatus(e,t.serviceId);console.log(JSON.stringify(l,null,2)),(l.status==="completed"||l.status==="failed")&&(clearInterval(a),process.exit(0))}catch(l){clearInterval(a),console.error(JSON.stringify({error:l.message},null,2)),process.exit(1)}}else{n.newline(),n.info(`\u{1F441}\uFE0F Watching fax ${e} (press Ctrl+C to exit)`),n.info(`Polling every ${o}s...`),n.newline(),process.on("SIGINT",()=>{n.newline(),n.info("Watch stopped by user"),n.newline(),process.exit(0)});let s=async()=>{try{let a=await i.getFaxStatus(e,t.serviceId);process.stdout.isTTY&&process.stdout.write("\x1B[2J\x1B[0f"),n.info(`\u{1F441}\uFE0F Watching fax ${e} (press Ctrl+C to exit)`),n.info(`Polling every ${o}s...`),n.info(`Last updated: ${new Date().toLocaleTimeString()}`),on(a),(a.status==="completed"||a.status==="failed")&&(n.info(`Fax ${a.status}. Exiting watch mode.`),n.newline(),process.exit(0))}catch(a){n.newline(),n.error(`Failed to get fax status: ${a.message}`),process.exit(1)}};await s(),setInterval(s,r)}}async function Vc(){let i=Ls.platform();try{if(i==="darwin")return(0,nn.execSync)(`osascript -e '${`
122
126
  set fileTypes to {"pdf", "tif", "tiff", "doc", "docx", "txt", "html", "htm"}
123
127
  set theFile to choose file with prompt "Select a file to send:" of type fileTypes
124
128
  return POSIX path of theFile
125
- `.replace(/'/g,"'\\''")}' 2>/dev/null`,{encoding:"utf8",stdio:["pipe","pipe","pipe"]}).trim()||null;if(i==="win32")return(0,Yt.execSync)(`powershell -Command "${`
129
+ `.replace(/'/g,"'\\''")}' 2>/dev/null`,{encoding:"utf8",stdio:["pipe","pipe","pipe"]}).trim()||null;if(i==="win32")return(0,nn.execSync)(`powershell -Command "${`
126
130
  Add-Type -AssemblyName System.Windows.Forms
127
131
  $dialog = New-Object System.Windows.Forms.OpenFileDialog
128
132
  $dialog.Filter = "Fax Files|*.pdf;*.tif;*.tiff;*.doc;*.docx;*.txt;*.html;*.htm"
@@ -131,75 +135,75 @@ ${p.display_name||"No name"}`)),p.channel_identities&&p.channel_identities.lengt
131
135
  if ($result -eq 'OK') {
132
136
  Write-Output $dialog.FileName
133
137
  }
134
- `.replace(/"/g,'\\"')}"`,{encoding:"utf8",stdio:["pipe","pipe","pipe"]}).trim()||null;try{return(0,Yt.execSync)(`zenity --file-selection --title="Select a file to send" --file-filter='Fax Files | *.pdf *.tif *.tiff *.doc *.docx *.txt *.html *.htm' 2>/dev/null`,{encoding:"utf8",stdio:["pipe","pipe","pipe"]}).trim()||null}catch{return(0,Yt.execSync)('kdialog --getopenfilename ~ "*.pdf *.tif *.tiff *.doc *.docx *.txt *.html *.htm|Fax Files" 2>/dev/null',{encoding:"utf8",stdio:["pipe","pipe","pipe"]}).trim()||null}}catch{return null}}async function $s(){let{inputMethod:i}=await me([{type:"list",name:"inputMethod",message:"How would you like to select the file?",choices:[{name:"\u{1F4C1} Browse files",value:"browse"},{name:"\u2328\uFE0F Enter file path manually",value:"manual"}]}]);if(i==="browse"){let e=await gc();if(e)return n.info(`Selected: ${e}`),e;{n.warn("File selection cancelled or unavailable, please enter path manually");let{file:t}=await me([{type:"input",name:"file",message:"Enter the path to the file you want to send:",validate:o=>!o||o.trim().length===0?"File path is required":!0}]);return t}}else{let{file:e}=await me([{type:"input",name:"file",message:"Enter the path to the file you want to send:",validate:t=>!t||t.trim().length===0?"File path is required":!0}]);return e}}var Cs,At,lt,vs,Yt,bs,Ss,vn,Ge,hc,ks=W(()=>{"use strict";Cs=require("commander");E();D();hs();ws();A();At=y(require("fs-extra")),lt=y(require("path")),vs=y(require("os")),Yt=require("child_process");vt();bs=y(require("form-data")),Ss=y(require("axios")),vn=class{credentials;constructor(e,t){this.credentials=t}async validateFile(e){let t=lt.resolve(e);if(!await At.pathExists(t))throw new Error(`File not found: ${e}`);let r=await At.stat(t);if(!r.isFile())throw new Error(`Path is not a file: ${e}`);let s=lt.extname(t).toLowerCase(),a=[".pdf",".tif",".tiff",".doc",".docx",".txt",".html",".htm"];if(!a.includes(s))throw new Error(`Unsupported file type: ${s}. Supported types: ${a.join(", ")}`);let l=20*1024*1024;if(r.size>l)throw new Error(`File too large: ${(r.size/1024/1024).toFixed(2)}MB. Maximum size: 20MB`)}validateUrl(e){try{let t=new URL(e);if(!["http:","https:"].includes(t.protocol))throw new Error("URL must use HTTP or HTTPS protocol")}catch(t){throw new Error(`Invalid URL: ${t.message}`)}}async sendFax(e){let{to:t,from:o,file:r,contentUrl:s,serviceId:a}=e;if(!r&&!s)throw new Error("Either --file or --content-url must be provided");let l=a||f.getFaxServiceId();if(!l)throw new Error("Fax service ID is required. Set it with: sinch config --set fax serviceID=<id>");let p=o||f.getFaxSenderNumber();if(r&&await this.validateFile(r),s){let h=Array.isArray(s)?s:[s];for(let C of h)this.validateUrl(C)}let d=new bs.default;if(d.append("to",t),p&&d.append("from",p),d.append("serviceId",l),r){let h=lt.resolve(r),C=At.createReadStream(h),v=lt.basename(h);d.append("file",C,v)}s&&(Array.isArray(s)?d.append("contentUrl",s.join(",")):d.append("contentUrl",s));let u=this.credentials||await f.getCredentials();if(!u)throw new Error("Not authenticated. Please run: sinch auth login");let w=`https://fax.api.sinch.com/v3/projects/${u.projectId}/faxes`;try{return(await Ss.default.post(w,d,{headers:{...d.getHeaders()},auth:{username:u.keyId,password:u.keySecret},maxContentLength:1/0,maxBodyLength:1/0})).data}catch(h){if(h.response){let C=h.response.status,v=h.response.data,T=`HTTP ${C}`;if(h.response.statusText&&(T+=` ${h.response.statusText}`),v)if(typeof v=="string"&&v.trim()?T+=`: ${v}`:v.message&&(T+=`: ${v.message}`),v.details&&Array.isArray(v.details))for(let O of v.details)if(O.fieldViolations&&Array.isArray(O.fieldViolations)){T+=`
138
+ `.replace(/"/g,'\\"')}"`,{encoding:"utf8",stdio:["pipe","pipe","pipe"]}).trim()||null;try{return(0,nn.execSync)(`zenity --file-selection --title="Select a file to send" --file-filter='Fax Files | *.pdf *.tif *.tiff *.doc *.docx *.txt *.html *.htm' 2>/dev/null`,{encoding:"utf8",stdio:["pipe","pipe","pipe"]}).trim()||null}catch{return(0,nn.execSync)('kdialog --getopenfilename ~ "*.pdf *.tif *.tiff *.doc *.docx *.txt *.html *.htm|Fax Files" 2>/dev/null',{encoding:"utf8",stdio:["pipe","pipe","pipe"]}).trim()||null}}catch{return null}}async function qs(){let{inputMethod:i}=await ye([{type:"list",name:"inputMethod",message:"How would you like to select the file?",choices:[{name:"\u{1F4C1} Browse files",value:"browse"},{name:"\u2328\uFE0F Enter file path manually",value:"manual"}]}]);if(i==="browse"){let e=await Vc();if(e)return n.info(`Selected: ${e}`),e;{n.warn("File selection cancelled or unavailable, please enter path manually");let{file:t}=await ye([{type:"input",name:"file",message:"Enter the path to the file you want to send:",validate:o=>!o||o.trim().length===0?"File path is required":!0}]);return t}}else{let{file:e}=await ye([{type:"input",name:"file",message:"Enter the path to the file you want to send:",validate:t=>!t||t.trim().length===0?"File path is required":!0}]);return e}}var js,Nt,dt,Ls,nn,_s,Ri,Tn,Je,Bc,Vs=G(()=>{"use strict";js=require("commander");T();R();xs();Fs();E();Nt=y(require("fs-extra")),dt=y(require("path")),Ls=y(require("os")),nn=require("child_process");It();_s=y(require("form-data")),Ri=y(require("axios")),Tn=class{credentials;constructor(e,t){this.credentials=t}async validateFile(e){let t=dt.resolve(e);if(!await Nt.pathExists(t))throw new Error(`File not found: ${e}`);let r=await Nt.stat(t);if(!r.isFile())throw new Error(`Path is not a file: ${e}`);let s=dt.extname(t).toLowerCase(),a=[".pdf",".tif",".tiff",".doc",".docx",".txt",".html",".htm"];if(!a.includes(s))throw new Error(`Unsupported file type: ${s}. Supported types: ${a.join(", ")}`);let l=20*1024*1024;if(r.size>l)throw new Error(`File too large: ${(r.size/1024/1024).toFixed(2)}MB. Maximum size: 20MB`)}validateUrl(e){try{let t=new URL(e);if(!["http:","https:"].includes(t.protocol))throw new Error("URL must use HTTP or HTTPS protocol")}catch(t){throw new Error(`Invalid URL: ${t.message}`)}}async sendFax(e){let{to:t,from:o,file:r,contentUrl:s,serviceId:a}=e;if(!r&&!s)throw new Error("Either --file or --content-url must be provided");let l=a||f.getFaxServiceId();if(!l)throw new Error("Fax service ID is required. Set it with: sinch config --set fax serviceID=<id>");let p=o||f.getFaxSenderNumber();if(r&&await this.validateFile(r),s){let h=Array.isArray(s)?s:[s];for(let C of h)this.validateUrl(C)}let d=new _s.default;if(d.append("to",t),p&&d.append("from",p),d.append("serviceId",l),r){let h=dt.resolve(r),C=Nt.createReadStream(h),v=dt.basename(h);d.append("file",C,v)}s&&(Array.isArray(s)?d.append("contentUrl",s.join(",")):d.append("contentUrl",s));let u=this.credentials||await f.getCredentials();if(!u)throw new Error("Not authenticated. Please run: sinch auth login");let w=`https://fax.api.sinch.com/v3/projects/${u.projectId}/faxes`;try{return(await Ri.default.post(w,d,{headers:{...d.getHeaders()},auth:{username:u.keyId,password:u.keySecret},maxContentLength:1/0,maxBodyLength:1/0})).data}catch(h){if(h.response){let C=h.response.status,v=h.response.data,k=`HTTP ${C}`;if(h.response.statusText&&(k+=` ${h.response.statusText}`),v)if(typeof v=="string"&&v.trim()?k+=`: ${v}`:v.message&&(k+=`: ${v.message}`),v.details&&Array.isArray(v.details))for(let j of v.details)if(j.fieldViolations&&Array.isArray(j.fieldViolations)){k+=`
135
139
 
136
- Validation Errors:`;for(let P of O.fieldViolations)T+=`
137
- \u2022 ${P.field}: ${P.description}`}else O.message&&(T+=`
138
- ${O.message}`);else v.error?T+=`: ${v.error}`:v.errorMessage&&(T+=`: ${v.errorMessage}`);throw v?.details?.some(O=>O.fieldViolations?.length>0)||(C===401?T+=`
140
+ Validation Errors:`;for(let M of j.fieldViolations)k+=`
141
+ \u2022 ${M.field}: ${M.description}`}else j.message&&(k+=`
142
+ ${j.message}`);else v.error?k+=`: ${v.error}`:v.errorMessage&&(k+=`: ${v.errorMessage}`);throw v?.details?.some(j=>j.fieldViolations?.length>0)||(C===401?k+=`
139
143
 
140
- \u2192 Authentication failed. Please verify your credentials with: sinch auth login`:C===403?T+=`
144
+ \u2192 Authentication failed. Please verify your credentials with: sinch auth login`:C===403?k+=`
141
145
 
142
- \u2192 Permission denied. Please check that your API credentials have access to the Fax API and that the service ID is correct.`:C===404?T+=`
146
+ \u2192 Permission denied. Please check that your API credentials have access to the Fax API and that the service ID is correct.`:C===404?k+=`
143
147
 
144
- \u2192 Resource not found. Please verify your project ID and service ID.`:C===400?T+=`
148
+ \u2192 Resource not found. Please verify your project ID and service ID.`:C===400?k+=`
145
149
 
146
- \u2192 Invalid request. Please check your phone numbers and file format.`:C===422&&(T+=`
150
+ \u2192 Invalid request. Please check your phone numbers and file format.`:C===422&&(k+=`
147
151
 
148
- \u2192 Validation failed. Common issues:`,T+=`
149
- \u2022 Phone numbers must be in E.164 format (e.g., +12025551234)`,T+=`
150
- \u2022 Service ID must be valid`,T+=`
151
- \u2022 From number must be a number that belongs to your project`)),new Error(T)}else throw h.request?new Error(`No response from Fax API: ${h.message}`):new Error(`Failed to send fax: ${h.message}`)}}async listFaxes(e){let{serviceId:t}=e;if(!(t||f.getFaxServiceId()))throw new Error("Fax service ID is required. Set it with: sinch config set fax service-id <id>");return[]}async getFax(e,t){let o=t||f.getFaxServiceId();if(!o)throw new Error("Fax service ID is required. Set it with: sinch config set fax service-id <id>");return{id:e,status:"completed",serviceId:o}}async cancelFax(e,t){if(!(t||f.getFaxServiceId()))throw new Error("Fax service ID is required. Set it with: sinch config set fax service-id <id>")}displayFaxDetails(e){n.newline(),n.info("Fax Details:"),n.info(`ID: ${e.id}`),n.info(`To: ${e.to?_(e.to):"N/A"}`),n.info(`From: ${e.from?_(e.from):"N/A"}`),n.info(`Status: ${e.status||"N/A"}`),n.info(`Created: ${e.createdAt||e.created_at||"N/A"}`),n.newline()}};Ge=new Cs.Command("fax");Ge.description("Manage Sinch Fax API");Ge.action(async()=>{try{n.newline();let{action:i}=await me([{type:"list",name:"action",message:"What would you like to do?",choices:[{name:"\u{1F4E4} Send a fax",value:"send"},{name:"\u{1F4CB} List faxes",value:"list"},{name:"\u{1F50D} Get fax details",value:"get"},{name:"\u{1F6AB} Cancel a fax",value:"cancel"},{name:"\u{1F4CA} Check status",value:"status"}]}]);if(i==="send"){let e=await me([{type:"input",name:"to",message:"Who would you like to send this fax to?",validate:a=>!a||a.trim().length===0?"Recipient fax number is required":/^\+?[1-9]\d{1,14}$/.test(a.trim())?!0:"Please enter a valid phone number in E.164 format (e.g., +12025551234)"},{type:"list",name:"contentType",message:"How would you like to provide the fax content?",choices:[{name:"File",value:"file"},{name:"URL",value:"url"}]}]),t,o;e.contentType==="file"?t=await $s():o=(await me([{type:"input",name:"contentUrl",message:"Enter the URL of the content to send:",validate:l=>{if(!l||l.trim().length===0)return"Content URL is required";try{return new URL(l),!0}catch{return"Please enter a valid URL (e.g., https://example.com/document.pdf)"}}}])).contentUrl;let r=await Le();n.newline(),c.start("Sending fax...");let s=await r.sendFax({to:e.to,file:t,contentUrl:o});c.succeed("Fax sent successfully!"),n.newline(),n.info("Fax Details:"),n.info(`ID: ${s.id}`),n.info(`To: ${_(s.to)}`),n.info(`From: ${_(s.from)}`),n.info(`Status: ${s.status}`),n.info(`Service ID: ${s.serviceId}`),n.info(`Created: ${s.createTime}`),n.newline(),n.info('\u{1F4A1} Tip: Use "sinch fax get <fax-id>" to check fax status'),n.newline()}else if(i==="list")await Le(),n.newline(),n.info("\u{1F4E0} Coming soon!"),n.newline();else if(i==="get"){let{faxId:e}=await me([{type:"input",name:"faxId",message:"Enter the fax ID:",validate:t=>!t||t.trim().length===0?"Fax ID is required":!0}]);await Le(),n.newline(),n.info("\u{1F4E0} Coming soon!"),n.newline()}else if(i==="cancel"){let{faxId:e}=await me([{type:"input",name:"faxId",message:"Enter the fax ID to cancel:",validate:t=>!t||t.trim().length===0?"Fax ID is required":!0}]);await Le(),n.newline(),n.info("\u{1F4E0} Coming soon!"),n.newline()}else if(i==="status"){await f.load();let e=await f.hasFaxCredentials(),t=f.getFaxPublicCredentialInfo(),o=f.getFaxServiceId(),r=f.getFaxSenderNumber();n.newline(),e?(n.info("\u2713 Fax service authenticated"),n.info(`Project ID: ${t.projectId||"N/A"}`),n.info(`Key ID: ${t.keyId||"N/A"}`),n.info(`Service ID: ${o||"Not configured"}`),n.info(`Sender Number: ${r?_(r):"Not configured"}`),n.info(`Source: ${t.source}`)):(n.info("\u2717 Not authenticated"),n.info("Run: sinch auth login")),n.newline()}}catch(i){c.fail("Operation failed"),n.error(i.message),process.exit(1)}});Ge.command("send").description("Send a fax").option("-t, --to <number>","Recipient fax number").option("-f, --file <path>","Path to file to send").option("-u, --content-url <url>","URL to content to send",(i,e)=>e?[...Array.isArray(e)?e:[e],i]:i).option("--from <number>","Sender fax number (uses default if not specified)").option("--service-id <id>","Fax service ID (uses default if not specified)").option("--json","Output result as JSON").action(async i=>{try{let e=i.to,t=i.file,o=i.contentUrl;i.json?(e||(console.error(JSON.stringify({error:"Recipient number (-t, --to) is required in JSON mode"},null,2)),process.exit(1)),!t&&!o&&(console.error(JSON.stringify({error:"Either --file or --content-url must be provided"},null,2)),process.exit(1))):(e||(e=(await me([{type:"input",name:"to",message:"Who would you like to send this fax to?",validate:l=>!l||l.trim().length===0?"Recipient fax number is required":/^\+?[1-9]\d{1,14}$/.test(l.trim())?!0:"Please enter a valid phone number in E.164 format (e.g., +12025551234)"}])).to),!t&&!o&&((await me([{type:"list",name:"contentType",message:"How would you like to provide the fax content?",choices:[{name:"File",value:"file"},{name:"URL",value:"url"}]}])).contentType==="file"?t=await $s():o=(await me([{type:"input",name:"contentUrl",message:"Enter the URL of the content to send:",validate:p=>{if(!p||p.trim().length===0)return"Content URL is required";try{return new URL(p),!0}catch{return"Please enter a valid URL (e.g., https://example.com/document.pdf)"}}}])).contentUrl));let r=await Le();i.json||(n.newline(),c.start("Sending fax..."));let s=await r.sendFax({to:e,from:i.from,file:t,contentUrl:o,serviceId:i.serviceId});i.json?console.log(JSON.stringify(s,null,2)):(c.succeed("Fax sent successfully!"),n.newline(),n.info("Fax Details:"),n.info(`ID: ${s.id}`),n.info(`To: ${s.to}`),n.info(`From: ${s.from}`),n.info(`Status: ${s.status}`),n.info(`Service ID: ${s.serviceId}`),n.info(`Created: ${s.createTime}`),n.newline(),n.info('\u{1F4A1} Tip: Use "sinch fax get <fax-id>" to check fax status'),n.newline())}catch(e){i.json?console.error(JSON.stringify({error:e.message},null,2)):(c.fail("Failed to send fax"),n.error(e.message)),process.exit(1)}});Ge.command("list").description("List sent faxes").option("-l, --limit <number>","Maximum number of faxes to return","10").option("--service-id <id>","Fax service ID (uses default if not specified)").option("--json","Output result as JSON").action(async i=>{try{await Le(),n.newline(),n.info("\u{1F4E0} Coming soon!"),n.newline()}catch(e){n.error(`Failed to list faxes: ${e.message}`),process.exit(1)}});Ge.command("get").description("Get fax details").argument("<fax-id>","Fax ID").option("--service-id <id>","Fax service ID (uses default if not specified)").option("--json","Output result as JSON").action(async(i,e)=>{try{await Le(),n.newline(),n.info("\u{1F4E0} Coming soon!"),n.newline()}catch(t){n.error(`Failed to get fax: ${t.message}`),process.exit(1)}});Ge.command("cancel").description("Cancel a pending fax").argument("<fax-id>","Fax ID to cancel").option("--service-id <id>","Fax service ID (uses default if not specified)").action(async(i,e)=>{try{await Le(),n.newline(),n.info("\u{1F4E0} Coming soon!"),n.newline()}catch(t){n.error(`Failed to cancel fax: ${t.message}`),process.exit(1)}});Ge.command("status").description("Check fax service authentication status").action(async()=>{try{await f.load();let i=await f.hasFaxCredentials(),e=f.getFaxPublicCredentialInfo(),t=f.getFaxServiceId(),o=f.getFaxSenderNumber();n.newline(),i?(n.info("\u2713 Fax service authenticated"),n.info(`Project ID: ${e.projectId||"N/A"}`),n.info(`Key ID: ${e.keyId||"N/A"}`),n.info(`Service ID: ${t||"Not configured"}`),n.info(`Sender Number: ${o?_(o):"Not configured"}`),n.info(`Source: ${e.source}`)):(n.info("\u2717 Not authenticated"),n.info("Run: sinch auth login")),n.newline()}catch(i){n.error(`Failed to check status: ${i.message}`),process.exit(1)}});hc=Ge});var bi={};xe(bi,{checkAndPromptTos:()=>yc});async function yc(i){let{api:e,keyId:t,nonInteractive:o=!1,spinner:r}=i,s=await e.getTosStatus();if(s.hasAccepted)return{accepted:!0,version:s.tosVersion,acceptedAt:s.acceptedAt};if(r&&r.stop(),o)return console.error(bn.default.red(`
152
+ \u2192 Validation failed. Common issues:`,k+=`
153
+ \u2022 Phone numbers must be in E.164 format (e.g., +12025551234)`,k+=`
154
+ \u2022 Service ID must be valid`,k+=`
155
+ \u2022 From number must be a number that belongs to your project`)),new Error(k)}else throw h.request?new Error(`No response from Fax API: ${h.message}`):new Error(`Failed to send fax: ${h.message}`)}}async listFaxes(e){let{serviceId:t}=e;if(!(t||f.getFaxServiceId()))throw new Error("Fax service ID is required. Set it with: sinch config set fax service-id <id>");return[]}async getFaxStatus(e,t){let o=this.credentials||await f.getCredentials();if(!o)throw new Error("Not authenticated. Please run: sinch auth login");let s=`https://fax.api.sinch.com/v3/projects/${o.projectId}/faxes/${e}`;try{return(await Ri.default.get(s,{auth:{username:o.keyId,password:o.keySecret}})).data}catch(a){if(a.response){let l=a.response.status,p=a.response.data,d=`HTTP ${l}`;throw l===404?new Error(`Fax not found: ${e}`):l===401?new Error("Authentication failed. Please verify your credentials with: sinch auth login"):l===403?new Error("Permission denied. Please check that your API credentials have access to the Fax API."):(p?.message&&(d+=`: ${p.message}`),new Error(d))}throw new Error(`Failed to get fax status: ${a.message}`)}}async getFax(e,t){return this.getFaxStatus(e,t)}async cancelFax(e,t){if(!(t||f.getFaxServiceId()))throw new Error("Fax service ID is required. Set it with: sinch config set fax service-id <id>")}};Je=new js.Command("fax");Je.description("Manage Sinch Fax API");Je.action(async()=>{try{n.newline();let{action:i}=await ye([{type:"list",name:"action",message:"What would you like to do?",choices:[{name:"\u{1F4E4} Send a fax",value:"send"},{name:"\u{1F4CB} List faxes",value:"list"},{name:"\u{1F50D} Get fax details",value:"get"},{name:"\uFFFD Check fax status",value:"status"},{name:"\u{1F6AB} Cancel a fax",value:"cancel"},{name:"\u{1F510} Check authentication",value:"auth-status"}]}]);if(i==="send"){let e=await ye([{type:"input",name:"to",message:"Who would you like to send this fax to?",validate:a=>!a||a.trim().length===0?"Recipient fax number is required":/^\+?[1-9]\d{1,14}$/.test(a.trim())?!0:"Please enter a valid phone number in E.164 format (e.g., +12025551234)"},{type:"list",name:"contentType",message:"How would you like to provide the fax content?",choices:[{name:"File",value:"file"},{name:"URL",value:"url"}]}]),t,o;e.contentType==="file"?t=await qs():o=(await ye([{type:"input",name:"contentUrl",message:"Enter the URL of the content to send:",validate:l=>{if(!l||l.trim().length===0)return"Content URL is required";try{return new URL(l),!0}catch{return"Please enter a valid URL (e.g., https://example.com/document.pdf)"}}}])).contentUrl;let r=await Ee();n.newline(),c.start("Sending fax...");let s=await r.sendFax({to:e.to,file:t,contentUrl:o});c.succeed("Fax sent successfully!"),n.newline(),n.info("Fax Details:"),n.info(`ID: ${s.id}`),n.info(`To: ${q(s.to)}`),n.info(`From: ${q(s.from)}`),n.info(`Status: ${s.status}`),n.info(`Service ID: ${s.serviceId}`),n.info(`Created: ${s.createTime}`),n.newline(),n.info('\u{1F4A1} Tip: Use "sinch fax get <fax-id>" to check fax status'),n.newline()}else if(i==="list")await Ee(),n.newline(),n.info("\u{1F4E0} Coming soon!"),n.newline();else if(i==="get"){let{faxId:e}=await ye([{type:"input",name:"faxId",message:"Enter the fax ID:",validate:o=>!o||o.trim().length===0?"Fax ID is required":!0}]),t=await Ee();n.newline(),c.start("Fetching fax details...");try{let o=await t.getFax(e);c.succeed("Fax details retrieved!"),Ms(o)}catch(o){c.fail("Failed to get fax details"),n.error(o.message)}n.newline()}else if(i==="status"){let{faxId:e}=await ye([{type:"input",name:"faxId",message:"Enter the fax ID:",validate:o=>!o||o.trim().length===0?"Fax ID is required":!0}]),t=await Ee();n.newline(),c.start("Fetching fax status...");try{let o=await t.getFaxStatus(e);c.succeed("Status retrieved!"),on(o)}catch(o){c.fail("Failed to get fax status"),n.error(o.message)}n.newline()}else if(i==="cancel"){let{faxId:e}=await ye([{type:"input",name:"faxId",message:"Enter the fax ID to cancel:",validate:t=>!t||t.trim().length===0?"Fax ID is required":!0}]);await Ee(),n.newline(),n.info("\u{1F4E0} Coming soon!"),n.newline()}else if(i==="auth-status"){await f.load();let e=await f.hasFaxCredentials(),t=f.getFaxPublicCredentialInfo(),o=f.getFaxServiceId(),r=f.getFaxSenderNumber();n.newline(),e?(n.info("\u2713 Fax service authenticated"),n.info(`Project ID: ${t.projectId||"N/A"}`),n.info(`Key ID: ${t.keyId||"N/A"}`),n.info(`Service ID: ${o||"Not configured"}`),n.info(`Sender Number: ${r?q(r):"Not configured"}`),n.info(`Source: ${t.source}`)):(n.info("\u2717 Not authenticated"),n.info("Run: sinch auth login")),n.newline()}}catch(i){c.fail("Operation failed"),n.error(i.message),process.exit(1)}});Je.command("send").description("Send a fax").option("-t, --to <number>","Recipient fax number").option("-f, --file <path>","Path to file to send").option("-u, --content-url <url>","URL to content to send",(i,e)=>e?[...Array.isArray(e)?e:[e],i]:i).option("--from <number>","Sender fax number (uses default if not specified)").option("--service-id <id>","Fax service ID (uses default if not specified)").option("--json","Output result as JSON").action(async i=>{try{let e=i.to,t=i.file,o=i.contentUrl;i.json?(e||(console.error(JSON.stringify({error:"Recipient number (-t, --to) is required in JSON mode"},null,2)),process.exit(1)),!t&&!o&&(console.error(JSON.stringify({error:"Either --file or --content-url must be provided"},null,2)),process.exit(1))):(e||(e=(await ye([{type:"input",name:"to",message:"Who would you like to send this fax to?",validate:l=>!l||l.trim().length===0?"Recipient fax number is required":/^\+?[1-9]\d{1,14}$/.test(l.trim())?!0:"Please enter a valid phone number in E.164 format (e.g., +12025551234)"}])).to),!t&&!o&&((await ye([{type:"list",name:"contentType",message:"How would you like to provide the fax content?",choices:[{name:"File",value:"file"},{name:"URL",value:"url"}]}])).contentType==="file"?t=await qs():o=(await ye([{type:"input",name:"contentUrl",message:"Enter the URL of the content to send:",validate:p=>{if(!p||p.trim().length===0)return"Content URL is required";try{return new URL(p),!0}catch{return"Please enter a valid URL (e.g., https://example.com/document.pdf)"}}}])).contentUrl));let r=await Ee();i.json||(n.newline(),c.start("Sending fax..."));let s=await r.sendFax({to:e,from:i.from,file:t,contentUrl:o,serviceId:i.serviceId});i.json?console.log(JSON.stringify(s,null,2)):(c.succeed("Fax sent successfully!"),n.newline(),n.info("Fax Details:"),n.info(`ID: ${s.id}`),n.info(`To: ${s.to}`),n.info(`From: ${s.from}`),n.info(`Status: ${s.status}`),n.info(`Service ID: ${s.serviceId}`),n.info(`Created: ${s.createTime}`),n.newline(),n.info('\u{1F4A1} Tip: Use "sinch fax get <fax-id>" to check fax status'),n.newline())}catch(e){i.json?console.error(JSON.stringify({error:e.message},null,2)):(c.fail("Failed to send fax"),n.error(e.message)),process.exit(1)}});Je.command("list").description("List sent faxes").option("-l, --limit <number>","Maximum number of faxes to return","10").option("--service-id <id>","Fax service ID (uses default if not specified)").option("--json","Output result as JSON").action(async i=>{try{await Ee(),n.newline(),n.info("\u{1F4E0} Coming soon!"),n.newline()}catch(e){n.error(`Failed to list faxes: ${e.message}`),process.exit(1)}});Je.command("get").description("Get fax details").argument("<fax-id>","Fax ID").option("--service-id <id>","Fax service ID (uses default if not specified)").option("--json","Output result as JSON").action(async(i,e)=>{try{let o=await(await Ee()).getFax(i,e.serviceId);e.json?console.log(JSON.stringify(o,null,2)):Ms(o)}catch(t){e.json?console.error(JSON.stringify({error:t.message},null,2)):n.error(`Failed to get fax: ${t.message}`),process.exit(1)}});Je.command("cancel").description("Cancel a pending fax").argument("<fax-id>","Fax ID to cancel").option("--service-id <id>","Fax service ID (uses default if not specified)").action(async(i,e)=>{try{await Ee(),n.newline(),n.info("\u{1F4E0} Coming soon!"),n.newline()}catch(t){n.error(`Failed to cancel fax: ${t.message}`),process.exit(1)}});Je.command("auth-status").description("Check fax service authentication status").action(async()=>{try{await f.load();let i=await f.hasFaxCredentials(),e=f.getFaxPublicCredentialInfo(),t=f.getFaxServiceId(),o=f.getFaxSenderNumber();n.newline(),i?(n.info("\u2713 Fax service authenticated"),n.info(`Project ID: ${e.projectId||"N/A"}`),n.info(`Key ID: ${e.keyId||"N/A"}`),n.info(`Service ID: ${t||"Not configured"}`),n.info(`Sender Number: ${o?q(o):"Not configured"}`),n.info(`Source: ${e.source}`)):(n.info("\u2717 Not authenticated"),n.info("Run: sinch auth login")),n.newline()}catch(i){n.error(`Failed to check status: ${i.message}`),process.exit(1)}});Je.command("status").description("Get the status of a fax").argument("<fax-id>","Fax ID (e.g., 01K5SJVRNRXM6FP4J9M9HQ5J18)").option("--service-id <id>","Fax service ID (uses default if not specified)").option("--json","Output result as JSON").option("--wait","Wait for fax to complete or fail").option("--timeout <seconds>","Timeout in seconds for --wait mode (default: 300)","300").option("--watch","Watch fax status in real-time").option("--interval <seconds>","Polling interval in seconds for --watch mode (default: 5)","5").action(async(i,e)=>{try{let t=await Ee();if(e.wait&&e.watch&&(e.json?console.error(JSON.stringify({error:"Cannot use --wait and --watch together"},null,2)):n.error("Cannot use --wait and --watch together"),process.exit(1)),e.watch)await Jc(t,i,e);else if(e.wait)await qc(t,i,e);else{let o=await t.getFaxStatus(i,e.serviceId);e.json?console.log(JSON.stringify(o,null,2)):on(o)}}catch(t){e.json?console.error(JSON.stringify({error:t.message},null,2)):n.error(`Failed to get fax status: ${t.message}`),process.exit(1)}});Bc=Je});var Di={};xe(Di,{checkAndPromptTos:()=>Kc});async function Kc(i){let{api:e,keyId:t,nonInteractive:o=!1,spinner:r}=i,s=await e.getTosStatus();if(s.hasAccepted)return{accepted:!0,version:s.tosVersion,acceptedAt:s.acceptedAt};if(r&&r.stop(),o)return console.error(Nn.default.red(`
152
156
  Terms of Service not accepted
153
157
  `)),console.error("This project requires Terms of Service acceptance before use."),console.error(`Please run 'sinch auth login' interactively to accept the ToS.
154
- `),console.error("After acceptance, you can use these credentials in CI/CD environments."),{accepted:!1};console.log(bn.default.blue(`
158
+ `),console.error("After acceptance, you can use these credentials in CI/CD environments."),{accepted:!1};console.log(Nn.default.blue(`
155
159
  Terms of Service
156
160
  `)),console.log(`Before using Sinch Functions, you must accept our Terms of Service.
157
161
  `),console.log("Key points:"),console.log(" - Usage-based billing for compute time"),console.log(" - You are responsible for function code and its behavior"),console.log(" - We may suspend service for policy violations"),console.log(` - Data processing per Sinch privacy policy
158
- `),console.log(bn.default.cyan(`Full terms: https://sinch.com/functions/terms
159
- `));let{accepted:a}=await As.default.prompt([{type:"confirm",name:"accepted",message:"Do you accept the Terms of Service?",default:!1}]);if(!a)return{accepted:!1};let l=await e.acceptTos(t,s.currentVersion);return{accepted:!0,version:l.tosVersion,acceptedAt:l.acceptedAt}}var bn,As,Si=W(()=>{"use strict";bn=y(require("chalk")),As=y(require("inquirer"))});var Xt=require("commander"),g=y(require("chalk")),Ye=y(require("fs-extra")),Sn=y(require("path")),Ii=y(require("os")),xs=require("child_process");var Ze=y(require("fs")),$n=y(require("path")),Pn=y(require("chalk")),Ls=18e5,_s="https://registry.npmjs.org/@sinch/cli";function Us(){if(process.platform!=="win32")try{if(Ze.default.existsSync("/.dockerenv"))return!0;let i=Ze.default.readFileSync("/proc/1/cgroup","utf8");return i.includes("docker")||i.includes("containerd")}catch{return!1}return!!process.env.DOCKER_CONTAINER}function qs(){return!!process.env.CI}function Ms(){return Us()||qs()}function Vs(i){return i.includes("-dev.")?"dev":parseInt(i.split(".")[0]||"0")>=1?"latest":"beta"}function Js(i){try{if(!Ze.default.existsSync(i))return!0;let e=parseInt(Ze.default.readFileSync(i,"utf8"));return Date.now()-e>Ls}catch{return!0}}function Bs(i,e){let t=i.replace(/^v/,"").split("-")[0]||"0.0.0",o=e.replace(/^v/,"").split("-")[0]||"0.0.0",r=t.split(".").map(a=>parseInt(a)||0),s=o.split(".").map(a=>parseInt(a)||0);for(let a=0;a<3;a++){let l=r[a]||0,p=s[a]||0;if(p>l)return!0;if(p<l)return!1}if(i.includes("-dev.")&&e.includes("-dev.")){let a=parseInt(i.split("-dev.")[1]||"0");return parseInt(e.split("-dev.")[1]||"0")>a}return!1}async function Ks(i){try{let e=await fetch(_s,{signal:AbortSignal.timeout(3e3)});return e.ok&&(await e.json())["dist-tags"]?.[i]||null}catch{return null}}async function Hs(i,e){let t=In().version,o=Vs(t);try{let r=await Ks(o);if(!r)return;Bs(t,r)&&(console.log(Pn.default.yellow(`
160
- \u{1F4E6} Update available: ${t} \u2192 ${r}`)),console.log(Pn.default.cyan(`Run: npm install -g @sinch/cli@${o}
161
- `))),Ze.default.mkdirSync(i,{recursive:!0}),Ze.default.writeFileSync(e,Date.now().toString())}catch{}}function Ai(){if(Ms())return;let i=$n.default.join(require("os").homedir(),".sinch"),e=$n.default.join(i,".last-update-check");Js(e)&&Hs(i,e).catch(()=>{})}pt();process.env.NODE_NO_WARNINGS||(process.env.NODE_NO_WARNINGS="1",process.removeAllListeners("warning"));Ai();var wc=In(),Cc=Wo(),vc=Yo(),bc=er(),Sc=ir(),Ic=lr(),$c=Nr(),Pc=ts(),kc=gs(),Es=(ks(),L(Ps)),Ac=Es.default||Es,H=new Xt.Command;H.name("sinch").description("Sinch Functions - Serverless function platform for voice applications").version(wc.version,"-V, --version","output the version number").helpOption("-h, --help","Display help for command").option("--profile <name>","Use a specific credential profile");H.addCommand(Cc);H.addCommand(vc);H.addCommand(bc);H.addCommand(Sc);H.addCommand(Ic);H.addCommand($c);H.addCommand(Pc);H.addCommand(kc);H.addCommand(Ac);var Zt=new Xt.Command("auth");Zt.description("Authentication management for Sinch Voice API");Zt.command("login").description("Authenticate with Sinch Voice API").option("-f, --credentials-file <path>","Path to credentials JSON file").action(async i=>{let{config:e}=(A(),L(De)),t=require("inquirer");try{let o=H.opts().profile;if(o&&e.setProfileOverride(o),await e.load(),i.credentialsFile){console.log(g.default.blue(`
162
+ `),console.log(Nn.default.cyan(`Full terms: https://sinch.com/functions/terms
163
+ `));let{accepted:a}=await Bs.default.prompt([{type:"confirm",name:"accepted",message:"Do you accept the Terms of Service?",default:!1}]);if(!a)return{accepted:!1};let l=await e.acceptTos(t,s.currentVersion);return{accepted:!0,version:l.tosVersion,acceptedAt:l.acceptedAt}}var Nn,Bs,xi=G(()=>{"use strict";Nn=y(require("chalk")),Bs=y(require("inquirer"))});var rn=require("commander"),g=y(require("chalk")),Ze=y(require("fs-extra")),Rn=y(require("path")),Oi=y(require("os")),Hs=require("child_process");var Qe=y(require("fs")),Dn=y(require("path")),xn=y(require("chalk")),ea=18e5,ta="https://registry.npmjs.org/@sinch/cli";function na(){if(process.platform!=="win32")try{if(Qe.default.existsSync("/.dockerenv"))return!0;let i=Qe.default.readFileSync("/proc/1/cgroup","utf8");return i.includes("docker")||i.includes("containerd")}catch{return!1}return!!process.env.DOCKER_CONTAINER}function ia(){return!!process.env.CI}function oa(){return na()||ia()}function ra(i){return i.includes("-dev.")?"dev":parseInt(i.split(".")[0]||"0")>=1?"latest":"beta"}function sa(i){try{if(!Qe.default.existsSync(i))return!0;let e=parseInt(Qe.default.readFileSync(i,"utf8"));return Date.now()-e>ea}catch{return!0}}function aa(i,e){let t=i.replace(/^v/,"").split("-")[0]||"0.0.0",o=e.replace(/^v/,"").split("-")[0]||"0.0.0",r=t.split(".").map(a=>parseInt(a)||0),s=o.split(".").map(a=>parseInt(a)||0);for(let a=0;a<3;a++){let l=r[a]||0,p=s[a]||0;if(p>l)return!0;if(p<l)return!1}if(i.includes("-dev.")&&e.includes("-dev.")){let a=parseInt(i.split("-dev.")[1]||"0");return parseInt(e.split("-dev.")[1]||"0")>a}return!1}async function ca(i){try{let e=await fetch(ta,{signal:AbortSignal.timeout(3e3)});return e.ok&&(await e.json())["dist-tags"]?.[i]||null}catch{return null}}async function la(i,e){let t=Ot().version,o=ra(t);try{let r=await ca(o);if(!r)return;aa(t,r)&&(console.log(xn.default.yellow(`
164
+ \u{1F4E6} Update available: ${t} \u2192 ${r}`)),console.log(xn.default.cyan(`Run: npm install -g @sinch/cli@${o}
165
+ `))),Qe.default.mkdirSync(i,{recursive:!0}),Qe.default.writeFileSync(e,Date.now().toString())}catch{}}function _i(){if(oa())return;let i=Dn.default.join(require("os").homedir(),".sinch"),e=Dn.default.join(i,".last-update-check");sa(e)&&la(i,e).catch(()=>{})}ut();var Ui=require("@opentelemetry/sdk-node"),Mi=require("@opentelemetry/exporter-trace-otlp-http"),qi=require("@opentelemetry/auto-instrumentations-node"),Ji=require("@opentelemetry/resources"),ln=require("@opentelemetry/semantic-conventions"),da=Ot(),pa="https://otlp-gateway-prod-us-east-3.grafana.net/otlp",ua="Basic MTUyNjc0OTpnbGNfZXlKdklqb2lNVFkzTURBME1pSXNJbTRpT2lKNWIzVnlMV2R5WVdaaGJtRXRkRzlyWlc0aUxDSnJJam9pZERSRE5qSXdORFUxWW5reGVsSkJTRXMyV1dRNGFreGxJaXdpYlNJNmV5SnlJam9pY0hKdlpDMTFjeTFsWVhOMExUTWlmWDA9",cn=null;function On(){try{return process.env.OTEL_METRICS_EXPORTER="none",process.env.OTEL_LOGS_EXPORTER="none",cn=new Ui.NodeSDK({resource:(0,Ji.resourceFromAttributes)({[ln.ATTR_SERVICE_NAME]:"sinch-cli",[ln.ATTR_SERVICE_VERSION]:da.version}),traceExporter:new Mi.OTLPTraceExporter({url:`${pa}/v1/traces`,headers:{Authorization:ua}}),instrumentations:[(0,qi.getNodeAutoInstrumentations)({"@opentelemetry/instrumentation-fs":{enabled:!1},"@opentelemetry/instrumentation-dns":{enabled:!1},"@opentelemetry/instrumentation-net":{enabled:!1},"@opentelemetry/instrumentation-http":{ignoreOutgoingRequestHook:i=>{let e=i.hostname||i.host||"";return!e.includes("sinch")&&!e.includes("grafana.net")},headersToSpanAttributes:{client:{requestHeaders:[],responseHeaders:[]},server:{requestHeaders:[],responseHeaders:[]}}}})]}),cn.start(),!0}catch{return!1}}async function ft(){if(cn)try{await cn.shutdown()}catch{}}var mt=require("@opentelemetry/api");var fa=Ot();function Vi(i){return{"cli.command":ma(i),"cli.version":fa.version,"cli.sdk_version":ga(),"cli.node_version":process.version,"cli.os":process.platform,"cli.arch":process.arch,"cli.auth_method":ha(),"cli.is_ci":ya()}}function ma(i){let e=[],t=i;for(;t&&t.name()!=="sinch";)e.unshift(t.name()),t=t.parent;return e.join(" ")||"help"}function ga(){try{return require("@sinch/sdk-core/package.json").version}catch{return"not_installed"}}function ha(){return process.env.SINCH_KEY_ID&&process.env.SINCH_KEY_SECRET?"env":process.env.SINCH_AUTH_TOKEN?"token":"config"}function ya(){return!!(process.env.CI||process.env.GITHUB_ACTIONS||process.env.GITLAB_CI||process.env.JENKINS_URL||process.env.CIRCLECI||process.env.TRAVIS)}var wa=mt.trace.getTracer("sinch-cli"),Bi=new WeakMap;function Fn(i){i.hook("preAction",(e,t)=>{let o=Vi(t),r=wa.startSpan(`sinch ${o["cli.command"]}`,{attributes:o});Bi.set(t,{span:r,startTime:Date.now()})}),i.hook("postAction",(e,t)=>{let o=Bi.get(t);if(!o)return;let r=Date.now()-o.startTime;o.span.setAttribute("cli.duration_ms",r),o.span.setAttribute("cli.exit_code",0),o.span.setStatus({code:mt.SpanStatusCode.OK}),o.span.end()})}function Ft(i,e){let t=mt.trace.getActiveSpan();t&&(t.recordException(i),t.setAttribute("cli.exit_code",e),t.setStatus({code:mt.SpanStatusCode.ERROR,message:i.message}),t.end())}process.env.NODE_NO_WARNINGS||(process.env.NODE_NO_WARNINGS="1",process.removeAllListeners("warning"));var Hc=On();_i();var Wc=Ot(),zc=dr(),Gc=fr(),Yc=yr(),Xc=vr(),Zc=Ar(),Qc=Yr(),el=ws(),tl=Ds(),Ks=(Vs(),F(Js)),nl=Ks.default||Ks,W=new rn.Command;W.name("sinch").description("Sinch Functions - Serverless function platform for voice applications").version(Wc.version,"-V, --version","output the version number").helpOption("-h, --help","Display help for command").option("--profile <name>","Use a specific credential profile");W.addCommand(zc);W.addCommand(Gc);W.addCommand(Yc);W.addCommand(Xc);W.addCommand(Zc);W.addCommand(Qc);W.addCommand(el);W.addCommand(tl);W.addCommand(nl);Hc&&Fn(W);var sn=new rn.Command("auth");sn.description("Authentication management for Sinch Voice API");sn.command("login").description("Authenticate with Sinch Voice API").option("-f, --credentials-file <path>","Path to credentials JSON file").action(async i=>{let{config:e}=(E(),F(Oe)),t=require("inquirer");try{let o=W.opts().profile;if(o&&e.setProfileOverride(o),await e.load(),i.credentialsFile){console.log(g.default.blue(`
162
166
  \u{1F510} Sinch Voice API Authentication`)),console.log(g.default.gray(`Loading credentials from: ${i.credentialsFile}
163
- `)),Ye.default.existsSync(i.credentialsFile)||(console.error(g.default.red(`\u274C Credentials file not found: ${i.credentialsFile}`)),process.exit($.NO_INPUT));try{let d=Ye.default.readFileSync(i.credentialsFile,"utf-8"),u=JSON.parse(d),w=["projectId","keyId","keySecret"].filter(v=>!u[v]);w.length>0&&(console.error(g.default.red(`\u274C Missing required fields in credentials file: ${w.join(", ")}`)),console.error(g.default.gray(`
164
- Expected format:`)),console.error(g.default.gray(JSON.stringify({projectId:"your-project-id",keyId:"your-key-id",keySecret:"your-key-secret",applicationKey:"(optional) your-app-key",applicationSecret:"(optional) your-app-secret"},null,2))),process.exit($.DATA_ERROR));let h={projectId:u.projectId,keyId:u.keyId,keySecret:u.keySecret,applicationKey:u.applicationKey||void 0,applicationSecret:u.applicationSecret||void 0},{spinner:C}=(D(),L(mt));C.start("Verifying credentials...");try{C.update("Obtaining OAuth access token...");let{SinchAPI:v}=(X(),L(Qe)),T=new v({apiUrl:e.get("apiUrl"),projectId:h.projectId,credentials:e._credentials}),ee=await T.authenticateOAuth(h.keyId,h.keySecret);if(C.succeed("OAuth token obtained successfully!"),h.applicationKey&&h.applicationSecret){C.start("Testing Voice API connection...");let{SinchClient:O}=require("@sinch/sdk-core");await new O({applicationKey:h.applicationKey,applicationSecret:h.applicationSecret}).voice.applications.getCallbackURLs({applicationkey:h.applicationKey}),C.succeed("Voice credentials verified!")}else console.log(g.default.gray(" Voice credentials not provided (can be added later)"));await e._credentials.storeOAuthToken(ee),C.start("Checking Terms of Service...");try{let{checkAndPromptTos:O}=(Si(),L(bi)),P=await O({api:T,keyId:h.keyId,nonInteractive:!!process.env.CI,spinner:C});P.accepted||(console.log(g.default.yellow(`
165
- Terms of Service acceptance is required to use Sinch Functions.`)),process.exit($.NO_PERMISSION)),C.succeed("Terms of Service accepted"),P.version&&(e.set("tosVersion",P.version),e.set("tosAcceptedAt",P.acceptedAt),await e.save())}catch(O){if(O.message?.includes("not found")||O.message?.includes("404"))C.info("Terms of Service check not available yet");else throw O}await e._credentials.store(h),console.log(g.default.green(`
167
+ `)),Ze.default.existsSync(i.credentialsFile)||(console.error(g.default.red(`\u274C Credentials file not found: ${i.credentialsFile}`)),process.exit(I.NO_INPUT));try{let d=Ze.default.readFileSync(i.credentialsFile,"utf-8"),u=JSON.parse(d),w=["projectId","keyId","keySecret"].filter(v=>!u[v]);w.length>0&&(console.error(g.default.red(`\u274C Missing required fields in credentials file: ${w.join(", ")}`)),console.error(g.default.gray(`
168
+ Expected format:`)),console.error(g.default.gray(JSON.stringify({projectId:"your-project-id",keyId:"your-key-id",keySecret:"your-key-secret",applicationKey:"(optional) your-app-key",applicationSecret:"(optional) your-app-secret"},null,2))),process.exit(I.DATA_ERROR));let h={projectId:u.projectId,keyId:u.keyId,keySecret:u.keySecret,applicationKey:u.applicationKey||void 0,applicationSecret:u.applicationSecret||void 0},{spinner:C}=(R(),F(yt));C.start("Verifying credentials...");try{C.update("Obtaining OAuth access token...");let{SinchAPI:v}=(Q(),F(et)),k=new v({apiUrl:e.get("apiUrl"),projectId:h.projectId,credentials:e._credentials}),re=await k.authenticateOAuth(h.keyId,h.keySecret);if(C.succeed("OAuth token obtained successfully!"),h.applicationKey&&h.applicationSecret){C.start("Testing Voice API connection...");let{SinchClient:j}=require("@sinch/sdk-core");await new j({applicationKey:h.applicationKey,applicationSecret:h.applicationSecret}).voice.applications.getCallbackURLs({applicationkey:h.applicationKey}),C.succeed("Voice credentials verified!")}else console.log(g.default.gray(" Voice credentials not provided (can be added later)"));await e._credentials.storeOAuthToken(re),C.start("Checking Terms of Service...");try{let{checkAndPromptTos:j}=(xi(),F(Di)),M=await j({api:k,keyId:h.keyId,nonInteractive:!!process.env.CI,spinner:C});M.accepted||(console.log(g.default.yellow(`
169
+ Terms of Service acceptance is required to use Sinch Functions.`)),process.exit(I.NO_PERMISSION)),C.succeed("Terms of Service accepted"),M.version&&(e.set("tosVersion",M.version),e.set("tosAcceptedAt",M.acceptedAt),await e.save())}catch(j){if(j.message?.includes("not found")||j.message?.includes("404"))C.info("Terms of Service check not available yet");else throw j}await e._credentials.store(h),console.log(g.default.green(`
166
170
  \u2705 Authentication successful!`));return}catch(v){C.fail(g.default.red("Authentication failed")),console.error(g.default.red(`
167
- \u274C ${v.message||"Failed to authenticate with provided credentials"}`)),process.exit($.AUTH_FAILED)}}catch(d){console.error(g.default.red(`\u274C Failed to parse credentials file: ${d.message}`)),process.exit($.DATA_ERROR)}}let r=await e.getCredentials(),s=e.getPublicCredentialInfo();console.log(g.default.blue(`
171
+ \u274C ${v.message||"Failed to authenticate with provided credentials"}`)),process.exit(I.AUTH_FAILED)}}catch(d){console.error(g.default.red(`\u274C Failed to parse credentials file: ${d.message}`)),process.exit(I.DATA_ERROR)}}let r=await e.getCredentials(),s=e.getPublicCredentialInfo();console.log(g.default.blue(`
168
172
  \u{1F510} Sinch API Authentication`)),console.log(r?g.default.gray(`Found existing credentials. Press Enter to reuse them or enter new values.
169
173
  `):g.default.gray(`Enter your Sinch API credentials (from the Sinch Dashboard)
170
- `));let a=await t.prompt([{type:"input",name:"projectId",message:"Project ID (from Sinch Dashboard):",default:s?.projectId||void 0,validate:d=>!d&&s?.projectId?!0:d.length>0||"Project ID is required"},{type:"input",name:"keyId",message:"Key ID (from Project \u2192 Access Keys):",default:s?.keyId||void 0,validate:d=>!d&&s?.keyId?!0:d.length>0||"Key ID is required"},{type:"password",name:"keySecret",message:"Key Secret:",default:r?.keySecret||void 0,validate:d=>!d&&r?.keySecret?!0:d.length>0||"Key Secret is required"}]),l={projectId:a.projectId||s?.projectId,keyId:a.keyId||s?.keyId,keySecret:a.keySecret||r?.keySecret},{spinner:p}=(D(),L(mt));p.start("Verifying credentials...");try{p.update("Obtaining OAuth access token...");let{SinchAPI:d}=(X(),L(Qe)),u=new d({apiUrl:e.get("apiUrl"),projectId:l.projectId||e.get("projectId"),credentials:e._credentials}),m=await u.authenticateOAuth(l.keyId,l.keySecret);p.succeed("API credentials verified!"),await e._credentials.storeOAuthToken(m),p.start("Checking Terms of Service...");try{let{checkAndPromptTos:C}=(Si(),L(bi)),v=await C({api:u,keyId:l.keyId,nonInteractive:process.argv.includes("--non-interactive")||!!process.env.CI,spinner:p});v.accepted||(console.log(g.default.yellow(`
174
+ `));let a=await t.prompt([{type:"input",name:"projectId",message:"Project ID (from Sinch Dashboard):",default:s?.projectId||void 0,validate:d=>!d&&s?.projectId?!0:d.length>0||"Project ID is required"},{type:"input",name:"keyId",message:"Key ID (from Project \u2192 Access Keys):",default:s?.keyId||void 0,validate:d=>!d&&s?.keyId?!0:d.length>0||"Key ID is required"},{type:"password",name:"keySecret",message:"Key Secret:",default:r?.keySecret||void 0,validate:d=>!d&&r?.keySecret?!0:d.length>0||"Key Secret is required"}]),l={projectId:a.projectId||s?.projectId,keyId:a.keyId||s?.keyId,keySecret:a.keySecret||r?.keySecret},{spinner:p}=(R(),F(yt));p.start("Verifying credentials...");try{p.update("Obtaining OAuth access token...");let{SinchAPI:d}=(Q(),F(et)),u=new d({apiUrl:e.get("apiUrl"),projectId:l.projectId||e.get("projectId"),credentials:e._credentials}),m=await u.authenticateOAuth(l.keyId,l.keySecret);p.succeed("API credentials verified!"),await e._credentials.storeOAuthToken(m),p.start("Checking Terms of Service...");try{let{checkAndPromptTos:C}=(xi(),F(Di)),v=await C({api:u,keyId:l.keyId,nonInteractive:process.argv.includes("--non-interactive")||!!process.env.CI,spinner:p});v.accepted||(console.log(g.default.yellow(`
171
175
  Terms of Service acceptance is required to use Sinch Functions.`)),process.exit(1)),p.succeed("Terms of Service accepted"),v.version&&(e.set("tosVersion",v.version),e.set("tosAcceptedAt",v.acceptedAt),await e.save())}catch(C){if(C.message?.includes("not found")||C.message?.includes("404"))p.info("Terms of Service check not available yet");else throw C}let w=s?.applicationKey&&r?.applicationSecret,{addVoice:h}=await t.prompt([{type:"confirm",name:"addVoice",message:"Add Voice application credentials? (for voice templates and callbacks)",default:w||!1}]);if(h){let C=await t.prompt([{type:"input",name:"applicationKey",message:"Voice Application Key:",default:s?.applicationKey||void 0,validate:v=>!v&&s?.applicationKey?!0:v.length>0||"Application Key is required"},{type:"password",name:"applicationSecret",message:"Voice Application Secret:",default:r?.applicationSecret||void 0,validate:v=>!v&&r?.applicationSecret?!0:v.length>0||"Application Secret is required"}]);l.applicationKey=C.applicationKey||s?.applicationKey,l.applicationSecret=C.applicationSecret||r?.applicationSecret,p.start("Testing Voice API connection...");try{let{SinchClient:v}=require("@sinch/sdk-core");await new v({applicationKey:l.applicationKey,applicationSecret:l.applicationSecret}).voice.applications.getCallbackURLs({applicationkey:l.applicationKey}),p.succeed("Voice credentials verified!")}catch(v){p.fail("Voice API test failed"),console.log(g.default.yellow(` ${v.message}`)),console.log(g.default.gray(" Voice credentials will be saved but may not work."))}}await e._credentials.store(l),console.log(g.default.green(`
172
176
  \u2705 Authentication successful!`))}catch(d){p.fail("Authentication failed"),console.error(g.default.red(`
173
177
  \u274C Error: ${d.message}`)),console.log(g.default.yellow(`
174
- \u{1F4A1} Please check your credentials and try again`)),process.exit($.AUTH_FAILED)}}catch(o){console.error(g.default.red(`Authentication failed: ${o.message}`)),process.exit($.AUTH_FAILED)}});Zt.command("status").description("Show current authentication status").action(async()=>{let{config:i}=(A(),L(De));try{await i.load();let e=await i.hasCredentials(),t=i.getPublicCredentialInfo();if(console.log(g.default.blue(`
175
- \u{1F510} Authentication Status`)),e&&t){console.log(g.default.green("\u2705 Authenticated")),console.log(` Project ID: ${t.projectId}`),console.log(` Key ID: ${t.keyId}`),t.source==="environment"?console.log(g.default.gray(" (Credentials from environment variables)")):console.log(g.default.gray(" (Secrets stored securely in OS keychain)")),t.applicationKey?console.log(` Voice App Key: ${t.applicationKey}`):(console.log(g.default.gray(" Voice credentials: Not configured")),console.log(g.default.gray(" (Add with: sinch auth login)")));try{let r=(X(),L(Qe)).default,s=i.getApiConfig();await new r(s).authenticate(),console.log(g.default.green(" OAuth Token: Valid"))}catch{console.log(g.default.yellow(" OAuth Token: Expired or invalid (will auto-refresh on next API call)"))}let o=await i.getApplicationCredentials();if(o){let{spinner:r}=(D(),L(mt));r.start("Testing Voice API connection...");try{let{SinchClient:s}=require("@sinch/sdk-core");await new s({applicationKey:o.applicationKey,applicationSecret:o.applicationSecret}).voice.applications.getCallbackURLs({applicationkey:o.applicationKey}),r.succeed("Voice connection active")}catch{r.fail("Voice connection failed"),console.log(g.default.yellow("\u26A0\uFE0F Voice credentials may be expired or invalid"))}}try{let{SinchAPI:r}=(X(),L(Qe)),s=i.getApiConfig(),l=await new r(s).getTosStatus();console.log(g.default.blue(`
178
+ \u{1F4A1} Please check your credentials and try again`)),process.exit(I.AUTH_FAILED)}}catch(o){console.error(g.default.red(`Authentication failed: ${o.message}`)),process.exit(I.AUTH_FAILED)}});sn.command("status").description("Show current authentication status").action(async()=>{let{config:i}=(E(),F(Oe));try{await i.load();let e=await i.hasCredentials(),t=i.getPublicCredentialInfo();if(console.log(g.default.blue(`
179
+ \u{1F510} Authentication Status`)),e&&t){console.log(g.default.green("\u2705 Authenticated")),console.log(` Project ID: ${t.projectId}`),console.log(` Key ID: ${t.keyId}`),t.source==="environment"?console.log(g.default.gray(" (Credentials from environment variables)")):console.log(g.default.gray(" (Secrets stored securely in OS keychain)")),t.applicationKey?console.log(` Voice App Key: ${t.applicationKey}`):(console.log(g.default.gray(" Voice credentials: Not configured")),console.log(g.default.gray(" (Add with: sinch auth login)")));try{let r=(Q(),F(et)).default,s=i.getApiConfig();await new r(s).authenticate(),console.log(g.default.green(" OAuth Token: Valid"))}catch{console.log(g.default.yellow(" OAuth Token: Expired or invalid (will auto-refresh on next API call)"))}let o=await i.getApplicationCredentials();if(o){let{spinner:r}=(R(),F(yt));r.start("Testing Voice API connection...");try{let{SinchClient:s}=require("@sinch/sdk-core");await new s({applicationKey:o.applicationKey,applicationSecret:o.applicationSecret}).voice.applications.getCallbackURLs({applicationkey:o.applicationKey}),r.succeed("Voice connection active")}catch{r.fail("Voice connection failed"),console.log(g.default.yellow("\u26A0\uFE0F Voice credentials may be expired or invalid"))}}try{let{SinchAPI:r}=(Q(),F(et)),s=i.getApiConfig(),l=await new r(s).getTosStatus();console.log(g.default.blue(`
176
180
  Terms of Service:`)),l.hasAccepted?(console.log(g.default.green(" Accepted")),l.tosVersion&&console.log(` Version: ${l.tosVersion}`),l.acceptedAt&&console.log(` Accepted: ${new Date(l.acceptedAt).toLocaleString()}`)):(console.log(g.default.yellow(" Not accepted")),console.log(g.default.yellow(' Run "sinch auth login" to accept the Terms of Service')))}catch{let s=i.get("tosVersion");if(s){console.log(g.default.blue(`
177
- Terms of Service:`)),console.log(g.default.gray(` Last accepted version: ${s}`));let a=i.get("tosAcceptedAt");a&&console.log(g.default.gray(` Accepted: ${new Date(a).toLocaleString()}`)),console.log(g.default.gray(" (Could not verify with API)"))}}}else console.log(g.default.red("\u274C Not authenticated")),console.log(g.default.gray('Run "sinch auth login" to authenticate'))}catch(e){console.error(g.default.red(`Failed to check status: ${e.message}`)),process.exit(1)}});Zt.command("logout").description("Clear stored authentication credentials").action(async()=>{let{config:i}=(A(),L(De)),e=require("inquirer");try{(await e.prompt([{type:"confirm",name:"confirm",message:"Are you sure you want to logout and clear credentials?",default:!1}])).confirm?(await i.load(),await i.clearCredentials(),console.log(g.default.green("\u2705 Logged out successfully")),console.log(g.default.gray("All credentials cleared from secure storage"))):console.log(g.default.gray("Logout cancelled"))}catch(t){console.error(g.default.red(`Logout failed: ${t.message}`)),process.exit(1)}});H.addCommand(Zt);var dt=new Xt.Command("config");dt.description("Configuration management");dt.command("set <args...>").description("Set configuration value (key=value or fax serviceID=value)").action(async i=>{let{config:e}=(A(),L(De)),t=H.opts().profile;t&&e.setProfileOverride(t);try{if(await e.load(),i[0]==="fax"&&i.length===2){let[o,...r]=i[1].split("="),s=r.join("=");(!o||!s)&&(console.error(g.default.red("Invalid format. Use: sinch config set fax serviceID=<value>")),process.exit(1));let a=o.toLowerCase().replace(/-/g,"");a==="serviceid"?(await e.setFaxServiceId(s),console.log(g.default.green(`Set fax service-id = ${s}`))):a==="sendernumber"?(await e.setFaxSenderNumber(s),console.log(g.default.green(`Set fax sender-number = ${s}`))):(console.error(g.default.red(`Unknown fax config key: ${o}`)),console.error(g.default.gray("Valid fax config keys: serviceID (or service-id), senderNumber (or sender-number)")),process.exit(1))}else{let[o,...r]=i[0].split("="),s=r.join("=");(!o||!s)&&(console.error(g.default.red("Invalid format. Use: sinch config set key=value")),process.exit(1)),e.set(o,s),await e.save(),console.log(g.default.green(`Set ${o} = ${s}`))}}catch(o){console.error(g.default.red(`Failed to set config: ${o.message}`)),process.exit(1)}});dt.command("get <args...>").description("Get configuration value").action(async i=>{let{config:e}=(A(),L(De)),t=H.opts().profile;t&&e.setProfileOverride(t);try{if(await e.load(),i[0]==="fax"&&i.length===2){let o=i[1],r=o.toLowerCase().replace(/-/g,"");if(r==="serviceid"){let s=e.getFaxServiceId();console.log(s!==null?s:g.default.gray("(not set)"))}else if(r==="sendernumber"){let s=e.getFaxSenderNumber();console.log(s!==null?s:g.default.gray("(not set)"))}else console.error(g.default.red(`Unknown fax config key: ${o}`)),process.exit(1)}else{let o=i.join(" "),r=e.get(o);console.log(r!==null?r:g.default.gray("(not set)"))}}catch(o){console.error(g.default.red(`Failed to get config: ${o.message}`)),process.exit(1)}});dt.command("list").description("List all configuration values").action(async()=>{let{config:i}=(A(),L(De)),e=H.opts().profile;e&&i.setProfileOverride(e);try{await i.load(),console.log(g.default.blue(`
181
+ Terms of Service:`)),console.log(g.default.gray(` Last accepted version: ${s}`));let a=i.get("tosAcceptedAt");a&&console.log(g.default.gray(` Accepted: ${new Date(a).toLocaleString()}`)),console.log(g.default.gray(" (Could not verify with API)"))}}}else console.log(g.default.red("\u274C Not authenticated")),console.log(g.default.gray('Run "sinch auth login" to authenticate'))}catch(e){console.error(g.default.red(`Failed to check status: ${e.message}`)),process.exit(1)}});sn.command("logout").description("Clear stored authentication credentials").action(async()=>{let{config:i}=(E(),F(Oe)),e=require("inquirer");try{(await e.prompt([{type:"confirm",name:"confirm",message:"Are you sure you want to logout and clear credentials?",default:!1}])).confirm?(await i.load(),await i.clearCredentials(),console.log(g.default.green("\u2705 Logged out successfully")),console.log(g.default.gray("All credentials cleared from secure storage"))):console.log(g.default.gray("Logout cancelled"))}catch(t){console.error(g.default.red(`Logout failed: ${t.message}`)),process.exit(1)}});W.addCommand(sn);var pt=new rn.Command("config");pt.description("Configuration management");pt.command("set <args...>").description("Set configuration value (key=value or fax serviceID=value)").action(async i=>{let{config:e}=(E(),F(Oe)),t=W.opts().profile;t&&e.setProfileOverride(t);try{if(await e.load(),i[0]==="fax"&&i.length===2){let[o,...r]=i[1].split("="),s=r.join("=");(!o||!s)&&(console.error(g.default.red("Invalid format. Use: sinch config set fax serviceID=<value>")),process.exit(1));let a=o.toLowerCase().replace(/-/g,"");a==="serviceid"?(await e.setFaxServiceId(s),console.log(g.default.green(`Set fax service-id = ${s}`))):a==="sendernumber"?(await e.setFaxSenderNumber(s),console.log(g.default.green(`Set fax sender-number = ${s}`))):(console.error(g.default.red(`Unknown fax config key: ${o}`)),console.error(g.default.gray("Valid fax config keys: serviceID (or service-id), senderNumber (or sender-number)")),process.exit(1))}else{let[o,...r]=i[0].split("="),s=r.join("=");(!o||!s)&&(console.error(g.default.red("Invalid format. Use: sinch config set key=value")),process.exit(1)),e.set(o,s),await e.save(),console.log(g.default.green(`Set ${o} = ${s}`))}}catch(o){console.error(g.default.red(`Failed to set config: ${o.message}`)),process.exit(1)}});pt.command("get <args...>").description("Get configuration value").action(async i=>{let{config:e}=(E(),F(Oe)),t=W.opts().profile;t&&e.setProfileOverride(t);try{if(await e.load(),i[0]==="fax"&&i.length===2){let o=i[1],r=o.toLowerCase().replace(/-/g,"");if(r==="serviceid"){let s=e.getFaxServiceId();console.log(s!==null?s:g.default.gray("(not set)"))}else if(r==="sendernumber"){let s=e.getFaxSenderNumber();console.log(s!==null?s:g.default.gray("(not set)"))}else console.error(g.default.red(`Unknown fax config key: ${o}`)),process.exit(1)}else{let o=i.join(" "),r=e.get(o);console.log(r!==null?r:g.default.gray("(not set)"))}}catch(o){console.error(g.default.red(`Failed to get config: ${o.message}`)),process.exit(1)}});pt.command("list").description("List all configuration values").action(async()=>{let{config:i}=(E(),F(Oe)),e=W.opts().profile;e&&i.setProfileOverride(e);try{await i.load(),console.log(g.default.blue(`
178
182
  Configuration (profile: ${i.getActiveProfileName()}):`));let t=i.getApiConfig();Object.entries(t).forEach(([s,a])=>{console.log(s==="credentials"?` ${s}: ${g.default.gray("(secure)")}`:` ${s}: ${a}`)});let o=i.getFaxServiceId(),r=i.getFaxSenderNumber();(o||r)&&(console.log(g.default.blue(`
179
- Fax Configuration:`)),o&&console.log(` serviceID: ${o}`),r&&console.log(` senderNumber: ${r}`))}catch(t){console.error(g.default.red(`Failed to list config: ${t.message}`)),process.exit(1)}});var Et=new Xt.Command("profile");Et.description("Manage credential profiles for multi-project workflows");Et.command("create <name>").description("Create a new credential profile").action(async i=>{let e=require("inquirer"),{profileManager:t}=(ft(),L(Nt));try{await t.init(),await t.create(i),console.log(g.default.green(`Profile '${i}' created.`));let{switchNow:o}=await e.prompt([{type:"confirm",name:"switchNow",message:`Switch to profile '${i}' now?`,default:!0}]);if(o){await t.use(i),console.log(g.default.green(`Switched to profile '${i}'.`));let{authNow:r}=await e.prompt([{type:"confirm",name:"authNow",message:"Authenticate now?",default:!0}]);r&&await H.parseAsync(["auth","login","--profile",i],{from:"user"})}}catch(o){console.error(g.default.red(`Failed to create profile: ${o.message}`)),process.exit(1)}});Et.command("use <name>").description("Switch the active credential profile").action(async i=>{let{profileManager:e}=(ft(),L(Nt));try{await e.init(),await e.use(i),console.log(g.default.green(`Switched to profile '${i}'.`))}catch(t){console.error(g.default.red(`Failed to switch profile: ${t.message}`)),process.exit(1)}});Et.command("list").description("List all credential profiles").action(async()=>{let{profileManager:i}=(ft(),L(Nt)),{logger:e}=(E(),L(Li));try{await i.init();let t=await i.list();if(t.length===0){console.log(g.default.gray("No profiles configured."));return}console.log(g.default.blue(`
183
+ Fax Configuration:`)),o&&console.log(` serviceID: ${o}`),r&&console.log(` senderNumber: ${r}`))}catch(t){console.error(g.default.red(`Failed to list config: ${t.message}`)),process.exit(1)}});var Rt=new rn.Command("profile");Rt.description("Manage credential profiles for multi-project workflows");Rt.command("create <name>").description("Create a new credential profile").action(async i=>{let e=require("inquirer"),{profileManager:t}=(ht(),F(Ut));try{await t.init(),await t.create(i),console.log(g.default.green(`Profile '${i}' created.`));let{switchNow:o}=await e.prompt([{type:"confirm",name:"switchNow",message:`Switch to profile '${i}' now?`,default:!0}]);if(o){await t.use(i),console.log(g.default.green(`Switched to profile '${i}'.`));let{authNow:r}=await e.prompt([{type:"confirm",name:"authNow",message:"Authenticate now?",default:!0}]);r&&await W.parseAsync(["auth","login","--profile",i],{from:"user"})}}catch(o){console.error(g.default.red(`Failed to create profile: ${o.message}`)),process.exit(1)}});Rt.command("use <name>").description("Switch the active credential profile").action(async i=>{let{profileManager:e}=(ht(),F(Ut));try{await e.init(),await e.use(i),console.log(g.default.green(`Switched to profile '${i}'.`))}catch(t){console.error(g.default.red(`Failed to switch profile: ${t.message}`)),process.exit(1)}});Rt.command("list").description("List all credential profiles").action(async()=>{let{profileManager:i}=(ht(),F(Ut)),{logger:e}=(T(),F(eo));try{await i.init();let t=await i.list();if(t.length===0){console.log(g.default.gray("No profiles configured."));return}console.log(g.default.blue(`
180
184
  Credential Profiles:
181
- `));let o=["Name","Project ID","Key ID","Active"],r=t.map(s=>[s.name,s.projectId||g.default.gray("(not set)"),s.keyId||g.default.gray("(not set)"),s.active?g.default.green("*"):""]);e.table(o,r),console.log("")}catch(t){console.error(g.default.red(`Failed to list profiles: ${t.message}`)),process.exit(1)}});Et.command("delete <name>").description("Delete a credential profile").action(async i=>{let e=require("inquirer"),{profileManager:t}=(ft(),L(Nt));try{await t.init();let{confirm:o}=await e.prompt([{type:"confirm",name:"confirm",message:`Delete profile '${i}'? This cannot be undone.`,default:!1}]);if(!o){console.log(g.default.gray("Cancelled."));return}await t.delete(i),console.log(g.default.green(`Profile '${i}' deleted.`))}catch(o){console.error(g.default.red(`Failed to delete profile: ${o.message}`)),process.exit(1)}});dt.addCommand(Et);dt.action(async()=>{console.log(g.default.blue(`
185
+ `));let o=["Name","Project ID","Key ID","Active"],r=t.map(s=>[s.name,s.projectId||g.default.gray("(not set)"),s.keyId||g.default.gray("(not set)"),s.active?g.default.green("*"):""]);e.table(o,r),console.log("")}catch(t){console.error(g.default.red(`Failed to list profiles: ${t.message}`)),process.exit(1)}});Rt.command("delete <name>").description("Delete a credential profile").action(async i=>{let e=require("inquirer"),{profileManager:t}=(ht(),F(Ut));try{await t.init();let{confirm:o}=await e.prompt([{type:"confirm",name:"confirm",message:`Delete profile '${i}'? This cannot be undone.`,default:!1}]);if(!o){console.log(g.default.gray("Cancelled."));return}await t.delete(i),console.log(g.default.green(`Profile '${i}' deleted.`))}catch(o){console.error(g.default.red(`Failed to delete profile: ${o.message}`)),process.exit(1)}});pt.addCommand(Rt);pt.action(async()=>{console.log(g.default.blue(`
182
186
  Configuration Management`)),console.log(g.default.gray(`Use "sinch config --help" for available commands
183
- `)),console.log(" sinch config set key=value Set a config value"),console.log(" sinch config get <key> Get a config value"),console.log(" sinch config list List all config values"),console.log(" sinch config profile list List profiles"),console.log(" sinch config profile create <name> Create a profile"),console.log(" sinch config profile use <name> Switch profile"),console.log(" sinch config profile delete <name> Delete a profile"),console.log("")});H.addCommand(dt);H.command("health").description("Check API connection and health").action(async()=>{let{SinchAPI:i}=(X(),L(Qe)),{config:e}=(A(),L(De)),{spinner:t}=(D(),L(mt));try{await e.load();let o=new i(e.getApiConfig());t.start("Checking API health...");let r=await o.checkHealth();t.succeed("API is healthy"),console.log(g.default.blue(`
187
+ `)),console.log(" sinch config set key=value Set a config value"),console.log(" sinch config get <key> Get a config value"),console.log(" sinch config list List all config values"),console.log(" sinch config profile list List profiles"),console.log(" sinch config profile create <name> Create a profile"),console.log(" sinch config profile use <name> Switch profile"),console.log(" sinch config profile delete <name> Delete a profile"),console.log("")});W.addCommand(pt);W.command("health").description("Check API connection and health").action(async()=>{let{SinchAPI:i}=(Q(),F(et)),{config:e}=(E(),F(Oe)),{spinner:t}=(R(),F(yt));try{await e.load();let o=new i(e.getApiConfig());t.start("Checking API health...");let r=await o.checkHealth();t.succeed("API is healthy"),console.log(g.default.blue(`
184
188
  \u{1F3E5} Health Status:`)),console.log(` Status: ${g.default.green(r.status)}`),console.log(` API URL: ${e.get("apiUrl")}`),console.log(` Project ID: ${e.get("projectId")}`)}catch(o){t.fail("API health check failed"),console.error(g.default.red(`
185
- \u274C ${o.message}`)),process.exit(1)}});H.command("completion").description("Generate shell completion scripts").option("--shell <shell>","Shell type (powershell, bash, zsh)","powershell").option("--install","Automatically install completion (PowerShell only)").action(async i=>{let e=i.shell.toLowerCase();i.install&&e==="powershell"?await xc():e==="powershell"?Rc():e==="bash"?Nc():e==="zsh"?Oc():(console.error(g.default.red(`Unsupported shell: ${e}`)),console.log("Supported shells: powershell, bash, zsh"),process.exit(1))});process.on("uncaughtException",i=>{console.error(g.default.red(`
186
- \u{1F4A5} Uncaught Exception: ${i.message}`)),process.env.SINCH_DEBUG&&console.error(i.stack);let e=i instanceof R?i.exitCode:$.SOFTWARE;process.exit(e)});process.on("unhandledRejection",i=>{console.error(g.default.red(`
187
- \u{1F4A5} Unhandled Rejection: ${i}`)),process.env.SINCH_DEBUG&&console.error(i);let e=i instanceof R?i.exitCode:$.SOFTWARE;process.exit(e)});async function Ec(){let i=process.argv.slice(2),e=i[0],t=["auth","config","help","completion","--help","-h","--version","-V"],o=i.includes("--non-interactive");if(e&&!t.includes(e)&&!t.some(r=>i.includes(r))){let{config:r}=(A(),L(De)),s=i.indexOf("--profile");s!==-1&&i[s+1]&&r.setProfileOverride(i[s+1]),await r.load();let a=e==="fax",l=!1,p="Sinch",d="sinch auth login";if(l=await r.hasCredentials(),a&&(p="Sinch Fax API"),!l){o&&(console.error(g.default.red(`
188
- \u274C Authentication required`)),console.error(`Please set up authentication first with: ${d}`),console.error("Or provide credentials via environment variables for CI/CD"),process.exit($.AUTH_REQUIRED));let u=require("inquirer");console.log(g.default.yellow(`
189
+ \u274C ${o.message}`)),process.exit(1)}});W.command("completion").description("Generate shell completion scripts").option("--shell <shell>","Shell type (powershell, bash, zsh)","powershell").option("--install","Automatically install completion (PowerShell only)").action(async i=>{let e=i.shell.toLowerCase();i.install&&e==="powershell"?await ol():e==="powershell"?al():e==="bash"?cl():e==="zsh"?ll():(console.error(g.default.red(`Unsupported shell: ${e}`)),console.log("Supported shells: powershell, bash, zsh"),process.exit(1))});process.on("uncaughtException",i=>{console.error(g.default.red(`
190
+ \u{1F4A5} Uncaught Exception: ${i.message}`)),process.env.SINCH_DEBUG&&console.error(i.stack);let e=i instanceof D?i.exitCode:I.SOFTWARE;Ft(i,e),ft().finally(()=>process.exit(e))});process.on("unhandledRejection",i=>{console.error(g.default.red(`
191
+ \u{1F4A5} Unhandled Rejection: ${i}`)),process.env.SINCH_DEBUG&&console.error(i);let e=i instanceof D?i.exitCode:I.SOFTWARE,t=i instanceof Error?i:new Error(String(i));Ft(t,e),ft().finally(()=>process.exit(e))});async function il(){let i=process.argv.slice(2),e=i[0],t=["auth","config","help","completion","--help","-h","--version","-V"],o=i.includes("--non-interactive");if(e&&!t.includes(e)&&!t.some(r=>i.includes(r))){let{config:r}=(E(),F(Oe)),s=i.indexOf("--profile");s!==-1&&i[s+1]&&r.setProfileOverride(i[s+1]),await r.load();let a=e==="fax",l=!1,p="Sinch",d="sinch auth login";if(l=await r.hasCredentials(),a&&(p="Sinch Fax API"),!l){o&&(console.error(g.default.red(`
192
+ \u274C Authentication required`)),console.error(`Please set up authentication first with: ${d}`),console.error("Or provide credentials via environment variables for CI/CD"),process.exit(I.AUTH_REQUIRED));let u=require("inquirer");console.log(g.default.yellow(`
189
193
  \u26A0\uFE0F Authentication Required`)),console.log(`You need to authenticate with ${p} to use the CLI.
190
194
  `);let{shouldLogin:m}=await u.prompt([{type:"confirm",name:"shouldLogin",message:"Would you like to login now?",default:!0}]);m?process.argv.splice(2,process.argv.length-2,"auth","login"):(console.log(`
191
195
  You can authenticate anytime with:`),console.log(` ${g.default.cyan(d)}
192
- `),process.exit(0))}}H.parse(process.argv),process.argv.slice(2).length||(console.log(g.default.blue.bold(`
196
+ `),process.exit(0))}}await W.parseAsync(process.argv),process.argv.slice(2).length||(console.log(g.default.blue.bold(`
193
197
  \u{1F3AF} Sinch Functions CLI`)),console.log(g.default.gray(`Serverless function platform for voice applications
194
- `)),console.log("Quick start:"),console.log(` ${g.default.cyan("sinch auth login")} # Authenticate with Sinch Voice API`),console.log(` ${g.default.cyan("sinch templates list")} # Browse available templates`),console.log(` ${g.default.cyan("sinch functions init")} # Create a new function`),console.log(` ${g.default.cyan("sinch functions dev")} # Start local development`),console.log(` ${g.default.cyan("sinch voice callback-url")} # Update webhook URL for live testing`),console.log(` ${g.default.cyan("sinch functions deploy")} # Deploy to production`),console.log(` ${g.default.cyan("sinch functions status [id]")} # Check deployment status`),console.log(` ${g.default.cyan("sinch secrets list")} # Manage custom secrets`),console.log(""),H.help())}Ec().catch(i=>{console.error(g.default.red("Error:"),i.message),process.exit(1)});async function xc(){let{spinner:i}=(D(),L(mt));try{i.start("Installing PowerShell completion...");let e=Sn.default.join(Ii.default.homedir(),"Documents","PowerShell"),t=Sn.default.join(e,"sinch-completion.ps1");await Ye.default.ensureDir(e),i.update("Creating completion script...");let o=Tc();await Ye.default.writeFile(t,o),i.update("Updating PowerShell profile...");let r=await Dc(),s="";await Ye.default.pathExists(r)&&(s=await Ye.default.readFile(r,"utf8"));let a='. "$env:USERPROFILE\\Documents\\PowerShell\\sinch-completion.ps1"';if(s.includes("sinch-completion.ps1"))i.info("PowerShell completion already installed"),console.log(g.default.blue(`
198
+ `)),console.log("Quick start:"),console.log(` ${g.default.cyan("sinch auth login")} # Authenticate with Sinch Voice API`),console.log(` ${g.default.cyan("sinch templates list")} # Browse available templates`),console.log(` ${g.default.cyan("sinch functions init")} # Create a new function`),console.log(` ${g.default.cyan("sinch functions dev")} # Start local development`),console.log(` ${g.default.cyan("sinch voice callback-url")} # Update webhook URL for live testing`),console.log(` ${g.default.cyan("sinch functions deploy")} # Deploy to production`),console.log(` ${g.default.cyan("sinch functions status [id]")} # Check deployment status`),console.log(` ${g.default.cyan("sinch secrets list")} # Manage custom secrets`),console.log(""),W.help())}il().then(()=>ft()).catch(async i=>{console.error(g.default.red("Error:"),i.message),Ft(i instanceof Error?i:new Error(String(i)),1),await ft(),process.exit(1)});async function ol(){let{spinner:i}=(R(),F(yt));try{i.start("Installing PowerShell completion...");let e=Rn.default.join(Oi.default.homedir(),"Documents","PowerShell"),t=Rn.default.join(e,"sinch-completion.ps1");await Ze.default.ensureDir(e),i.update("Creating completion script...");let o=sl();await Ze.default.writeFile(t,o),i.update("Updating PowerShell profile...");let r=await rl(),s="";await Ze.default.pathExists(r)&&(s=await Ze.default.readFile(r,"utf8"));let a='. "$env:USERPROFILE\\Documents\\PowerShell\\sinch-completion.ps1"';if(s.includes("sinch-completion.ps1"))i.info("PowerShell completion already installed"),console.log(g.default.blue(`
195
199
  \u2139\uFE0F Completion is already installed`)),console.log(g.default.gray("If tab completion isn't working, try restarting PowerShell"));else{let l=s+(s?`
196
200
  `:"")+`# Sinch Functions CLI completion
197
201
  `+a+`
198
- `;await Ye.default.writeFile(r,l),i.succeed("PowerShell completion installed successfully!"),console.log(g.default.green(`
202
+ `;await Ze.default.writeFile(r,l),i.succeed("PowerShell completion installed successfully!"),console.log(g.default.green(`
199
203
  \u2705 Installation Complete!`)),console.log(g.default.blue("\u{1F4C1} Files created:")),console.log(` ${g.default.gray(t)}`),console.log(` ${g.default.gray("Updated:")} ${r}`),console.log(g.default.yellow(`
200
204
  \u26A1 To activate completion:`)),console.log(" 1. Restart PowerShell, OR"),console.log(" 2. Run: "+g.default.cyan(". $PROFILE")),console.log(g.default.gray(`
201
205
  \u{1F4A1} Test with: sinch functions <TAB>`))}}catch(e){i.fail("Failed to install PowerShell completion"),console.error(g.default.red(`\u274C Error: ${e.message}`)),console.log(g.default.yellow(`
202
- \u{1F4A1} Try manual installation with: sinch completion`)),process.exit(1)}}async function Dc(){return new Promise(i=>{let e=t=>new Promise(o=>{let r=(0,xs.spawn)(t,["-Command","$PROFILE"],{stdio:["ignore","pipe","pipe"]}),s="";r.stdout.on("data",a=>{s+=a.toString()}),r.on("close",a=>{o(a===0?{success:!0,path:s.trim(),version:t}:{success:!1})}),r.on("error",()=>{o({success:!1})})});e("pwsh").then(t=>{t.success&&t.path?(console.log(g.default.gray(` Detected PowerShell 7 profile: ${t.path}`)),i(t.path)):e("powershell").then(o=>{if(o.success&&o.path)console.log(g.default.gray(` Detected Windows PowerShell profile: ${o.path}`)),i(o.path);else{let r=Sn.default.join(Ii.default.homedir(),"Documents","PowerShell","Microsoft.PowerShell_profile.ps1");console.log(g.default.gray(` Using fallback profile path: ${r}`)),i(r)}})})})}function Tc(){return`# PowerShell completion for Sinch Functions CLI
206
+ \u{1F4A1} Try manual installation with: sinch completion`)),process.exit(1)}}async function rl(){return new Promise(i=>{let e=t=>new Promise(o=>{let r=(0,Hs.spawn)(t,["-Command","$PROFILE"],{stdio:["ignore","pipe","pipe"]}),s="";r.stdout.on("data",a=>{s+=a.toString()}),r.on("close",a=>{o(a===0?{success:!0,path:s.trim(),version:t}:{success:!1})}),r.on("error",()=>{o({success:!1})})});e("pwsh").then(t=>{t.success&&t.path?(console.log(g.default.gray(` Detected PowerShell 7 profile: ${t.path}`)),i(t.path)):e("powershell").then(o=>{if(o.success&&o.path)console.log(g.default.gray(` Detected Windows PowerShell profile: ${o.path}`)),i(o.path);else{let r=Rn.default.join(Oi.default.homedir(),"Documents","PowerShell","Microsoft.PowerShell_profile.ps1");console.log(g.default.gray(` Using fallback profile path: ${r}`)),i(r)}})})})}function sl(){return`# PowerShell completion for Sinch Functions CLI
203
207
  # Auto-generated by 'sinch completion --install'
204
208
  # Compatible with both PowerShell 7 and Windows PowerShell 5.1
205
209
 
@@ -246,7 +250,7 @@ Register-ArgumentCompleter -Native -CommandName sinch -ScriptBlock {
246
250
  # Silently fail if there are any errors in completion
247
251
  # This prevents PowerShell startup errors
248
252
  }
249
- }`}function Rc(){let i=`
253
+ }`}function al(){let i=`
250
254
  # PowerShell completion for Sinch Functions CLI
251
255
  Register-ArgumentCompleter -Native -CommandName sinch -ScriptBlock {
252
256
  param($wordToComplete, $commandAst, $cursorPosition)
@@ -297,7 +301,7 @@ Register-ArgumentCompleter -Native -CommandName sinch -ScriptBlock {
297
301
  #
298
302
  # To find your profile location, run: $PROFILE
299
303
  `;console.log(g.default.blue("\u{1F527} PowerShell Completion Script")),console.log(g.default.gray(`Copy and save this to your PowerShell profile:
300
- `)),console.log(i),console.log(g.default.yellow("Installation Instructions:")),console.log(g.default.green("\u{1F680} Easy way: ")+g.default.cyan("sinch completion --install")),console.log(g.default.gray("\u{1F4DD} Manual way:")),console.log("1. Save this script as sinch-completion.ps1 in your Documents\\PowerShell folder"),console.log("2. Add this line to your PowerShell profile:"),console.log(g.default.cyan(' . "$env:USERPROFILE\\\\Documents\\\\PowerShell\\\\sinch-completion.ps1"')),console.log("3. Restart PowerShell or run: . $PROFILE")}function Nc(){let i=`
304
+ `)),console.log(i),console.log(g.default.yellow("Installation Instructions:")),console.log(g.default.green("\u{1F680} Easy way: ")+g.default.cyan("sinch completion --install")),console.log(g.default.gray("\u{1F4DD} Manual way:")),console.log("1. Save this script as sinch-completion.ps1 in your Documents\\PowerShell folder"),console.log("2. Add this line to your PowerShell profile:"),console.log(g.default.cyan(' . "$env:USERPROFILE\\\\Documents\\\\PowerShell\\\\sinch-completion.ps1"')),console.log("3. Restart PowerShell or run: . $PROFILE")}function cl(){let i=`
301
305
  # Bash completion for Sinch Functions CLI
302
306
  _sinch_completion() {
303
307
  local cur prev commands
@@ -338,7 +342,7 @@ complete -F _sinch_completion sinch
338
342
 
339
343
  # To install: Add this to your ~/.bashrc or ~/.bash_profile
340
344
  `;console.log(g.default.blue("\u{1F527} Bash Completion Script")),console.log(g.default.gray(`Add this to your ~/.bashrc or ~/.bash_profile:
341
- `)),console.log(i)}function Oc(){let i=`
345
+ `)),console.log(i)}function ll(){let i=`
342
346
  #compdef sinch
343
347
 
344
348
  _sinch() {