@sinch/cli 0.1.0-beta.1 → 0.1.3-beta

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE CHANGED
@@ -1,21 +1,21 @@
1
- MIT License
2
-
3
- Copyright (c) 2025 Sinch
4
-
5
- Permission is hereby granted, free of charge, to any person obtaining a copy
6
- of this software and associated documentation files (the "Software"), to deal
7
- in the Software without restriction, including without limitation the rights
8
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
- copies of the Software, and to permit persons to whom the Software is
10
- furnished to do so, subject to the following conditions:
11
-
12
- The above copyright notice and this permission notice shall be included in all
13
- copies or substantial portions of the Software.
14
-
15
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
- SOFTWARE.
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Sinch
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,203 +1,209 @@
1
- # Sinch CLI
2
-
3
- > **Official command-line interface for Sinch - Manage Functions, Voice, SMS, and more from your terminal**
4
-
5
- [![npm version](https://img.shields.io/npm/v/@sinch/sinch-cli.svg)](https://www.npmjs.com/package/@sinch/sinch-cli)
6
- [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
7
-
8
- ## Overview
9
-
10
- The Sinch CLI is your unified developer tool for managing all Sinch products. Currently featuring full support for **Sinch Functions** - create, test, and deploy serverless voice applications. More Sinch products coming soon!
11
-
12
- ## Installation
13
-
14
- ```bash
15
- # Install beta version
16
- npm install -g @sinch/sinch-cli@beta
17
-
18
- # Or install specific version
19
- npm install -g @sinch/sinch-cli@0.1.0-beta.1
20
- ```
21
-
22
- **Note**: This is a beta release. Use `@beta` tag to install the latest pre-release version.
23
-
24
- ## Prerequisites
25
-
26
- - **Node.js**: 20.0.0 or higher (Node 20 LTS or Node 22 LTS recommended)
27
- - **npm**: 9.0.0 or higher
28
- - **OS**: Windows 10+, macOS 10.15+, or Ubuntu 20.04+
29
-
30
- ## Quick Start
31
-
32
- ### 1. Authenticate with Sinch
33
-
34
- ```bash
35
- sinch auth login
36
- ```
37
-
38
- ### 2. Create a new function
39
-
40
- ```bash
41
- # Interactive mode - choose from templates
42
- sinch functions init
43
-
44
- # Or specify a template directly
45
- sinch functions init --template node/simple-voice-ivr --name my-voice-app
46
- ```
47
-
48
- ### 3. Test locally
49
-
50
- ```bash
51
- cd my-voice-app
52
- sinch functions dev
53
-
54
- # With runtime tunnel for webhooks
55
- sinch functions dev
56
- ```
57
-
58
- ### 4. Deploy to production
59
-
60
- ```bash
61
- sinch functions deploy
62
- ```
63
-
64
- ### 5. Monitor your function
65
-
66
- ```bash
67
- # List all functions
68
- sinch functions list
69
-
70
- # Stream logs
71
- sinch functions logs <function-id> --follow
72
-
73
- # Check status
74
- sinch functions status <function-id>
75
- ```
76
-
77
- ## Available Commands
78
-
79
- | Command | Description |
80
- |---------|-------------|
81
- | `sinch auth login` | Authenticate with Sinch platform |
82
- | `sinch functions init` | Create new function from template |
83
- | `sinch functions dev` | Start local development server |
84
- | `sinch functions deploy` | Deploy function to production |
85
- | `sinch functions list` | List all deployed functions |
86
- | `sinch functions logs` | Stream function logs |
87
- | `sinch functions delete` | Delete a deployed function |
88
- | `sinch secrets add` | Store secrets securely |
89
- | `sinch templates list` | Browse available templates |
90
- | `sinch help` | Show help for any command |
91
-
92
- ## Templates
93
-
94
- Create functions from pre-built templates:
95
-
96
- ### Voice Templates
97
- - `node/simple-voice-ivr` - Interactive voice menu system
98
- - `node/call-forwarding` - Intelligent call routing
99
- - `node/number-masking` - Privacy-preserving calls
100
- - `node/conference-call` - Multi-party conferences
101
- - `node/voicemail` - Complete voicemail system
102
-
103
- ### More Languages
104
- - `csharp/simple-voice-ivr` - IVR in C#/.NET
105
- - `java/simple-voice-ivr` - Q4 2025
106
-
107
- ## Features
108
-
109
- ### 🔐 Secure Secrets Management
110
- Secrets are stored in your OS keychain (Windows Credential Manager, macOS Keychain, Linux Secret Service):
111
-
112
- ```bash
113
- # Add a secret
114
- sinch secrets add STRIPE_KEY sk_test_123456
115
-
116
- # List secrets
117
- sinch secrets list
118
-
119
- # Use in your function
120
- const stripeKey = process.env.STRIPE_KEY;
121
- ```
122
-
123
- ### 🔄 Hot Reload Development
124
- Changes to your function are automatically reloaded:
125
-
126
- ```bash
127
- sinch functions dev --watch
128
- ```
129
-
130
- ### 🐛 VS Code Debugging
131
- All templates include VS Code launch configs. Just press F5 to debug!
132
-
133
- ### 🌐 Tunnel Support
134
- Test webhooks locally with runtime-integrated tunneling:
135
-
136
- ```bash
137
- sinch functions dev
138
- # Choose tunnel preference when prompted
139
- # Tunnel runs inside your function runtime
140
- ```
141
-
142
- ## Documentation
143
-
144
- - **Full Documentation**: [/docs/README.md](./docs/README.md)
145
- - **Command Reference**: [/docs/COMMANDS.md](./docs/COMMANDS.md)
146
- - **Development Guide**: [/docs/DEVELOPMENT.md](./docs/DEVELOPMENT.md)
147
- - **Examples**: [/docs/examples/](./docs/examples/)
148
-
149
- ## Resources
150
-
151
- - **Sinch Voice API**: https://www.sinch.com/products/apis/voice/
152
- - **Documentation**: Full CLI reference in [/docs](./docs/README.md)
153
- - **Templates Gallery**: Browse available templates with `sinch templates list`
154
-
155
- ## Troubleshooting
156
-
157
- ### Authentication Issues
158
-
159
- ```bash
160
- # Check authentication status
161
- sinch auth status
162
-
163
- # Re-authenticate if needed
164
- sinch auth logout
165
- sinch auth login
166
- ```
167
-
168
- ### Debug Mode
169
-
170
- ```bash
171
- # Enable debug output
172
- DEBUG=1 sinch functions dev
173
-
174
- # HTTP request debugging
175
- DEBUG_HTTP=1 sinch functions deploy
176
- ```
177
-
178
- ### Common Issues
179
-
180
- - **Command not found**: Reinstall globally with `npm install -g @sinch/sinch-cli@beta`
181
- - **Authentication failed**: Check your Sinch API credentials with `sinch auth status`
182
- - **Deployment failed**: Verify your function configuration and project access
183
-
184
- ## Support
185
-
186
- - **Documentation**: [Full CLI Documentation](./docs/README.md)
187
- - **Issues**: [Report a Bug](https://gitlab.com/sinch/sinch-projects/voice/functions/sinch-cli/-/issues)
188
- - **Email**: support@sinch.com
189
-
190
- ## Contributing
191
-
192
- Contributions are welcome! Visit our [GitLab repository](https://gitlab.com/sinch/sinch-projects/voice/functions/sinch-cli) for development setup and contribution guidelines.
193
-
194
- ## License
195
-
196
- MIT License - Copyright © 2025 Sinch
197
-
198
- ---
199
-
200
- **npm**: https://www.npmjs.com/package/@sinch/sinch-cli
201
- **Repository**: https://gitlab.com/sinch/sinch-projects/voice/functions/sinch-cli
202
- **Version**: 0.1.0-beta.1
1
+ # Sinch CLI
2
+
3
+ > **Official command-line interface for Sinch - Manage Functions, Voice, SMS, and more from your terminal**
4
+
5
+ [![npm version](https://img.shields.io/npm/v/@sinch/sinch-cli.svg)](https://www.npmjs.com/package/@sinch/sinch-cli)
6
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
7
+
8
+ ## Overview
9
+
10
+ The Sinch CLI is your unified developer tool for managing all Sinch products. Currently featuring full support for **Sinch Functions** - create, test, and deploy serverless voice applications. More Sinch products coming soon!
11
+
12
+ ## Installation
13
+
14
+ ```bash
15
+ # Latest stable release (production)
16
+ npm install -g @sinch/cli
17
+
18
+ # Beta releases (pre-release testing)
19
+ npm install -g @sinch/cli@beta
20
+
21
+ # Dev channel (bleeding edge - latest from main branch)
22
+ npm install -g @sinch/cli@dev
23
+ ```
24
+
25
+ **Installation Channels:**
26
+ - **`@latest`** (default) - Production-ready stable releases
27
+ - **`@beta`** - Pre-release versions for testing new features
28
+ - **`@dev`** - Cutting-edge builds from main branch (auto-published on every commit)
29
+
30
+ ## Prerequisites
31
+
32
+ - **Node.js**: 20.0.0 or higher (Node 20 LTS or Node 22 LTS recommended)
33
+ - **npm**: 9.0.0 or higher
34
+ - **OS**: Windows 10+, macOS 10.15+, or Ubuntu 20.04+
35
+
36
+ ## Quick Start
37
+
38
+ ### 1. Authenticate with Sinch
39
+
40
+ ```bash
41
+ sinch auth login
42
+ ```
43
+
44
+ ### 2. Create a new function
45
+
46
+ ```bash
47
+ # Interactive mode - choose from templates
48
+ sinch functions init
49
+
50
+ # Or specify a template directly
51
+ sinch functions init --template node/simple-voice-ivr --name my-voice-app
52
+ ```
53
+
54
+ ### 3. Test locally
55
+
56
+ ```bash
57
+ cd my-voice-app
58
+ sinch functions dev
59
+
60
+ # With runtime tunnel for webhooks
61
+ sinch functions dev
62
+ ```
63
+
64
+ ### 4. Deploy to production
65
+
66
+ ```bash
67
+ sinch functions deploy
68
+ ```
69
+
70
+ ### 5. Monitor your function
71
+
72
+ ```bash
73
+ # List all functions
74
+ sinch functions list
75
+
76
+ # Stream logs
77
+ sinch functions logs <function-id> --follow
78
+
79
+ # Check status
80
+ sinch functions status <function-id>
81
+ ```
82
+
83
+ ## Available Commands
84
+
85
+ | Command | Description |
86
+ |---------|-------------|
87
+ | `sinch auth login` | Authenticate with Sinch platform |
88
+ | `sinch functions init` | Create new function from template |
89
+ | `sinch functions dev` | Start local development server |
90
+ | `sinch functions deploy` | Deploy function to production |
91
+ | `sinch functions list` | List all deployed functions |
92
+ | `sinch functions logs` | Stream function logs |
93
+ | `sinch functions delete` | Delete a deployed function |
94
+ | `sinch secrets add` | Store secrets securely |
95
+ | `sinch templates list` | Browse available templates |
96
+ | `sinch help` | Show help for any command |
97
+
98
+ ## Templates
99
+
100
+ Create functions from pre-built templates:
101
+
102
+ ### Voice Templates
103
+ - `node/simple-voice-ivr` - Interactive voice menu system
104
+ - `node/call-forwarding` - Intelligent call routing
105
+ - `node/number-masking` - Privacy-preserving calls
106
+ - `node/conference-call` - Multi-party conferences
107
+ - `node/voicemail` - Complete voicemail system
108
+
109
+ ### More Languages
110
+ - `csharp/simple-voice-ivr` - IVR in C#/.NET
111
+ - `java/simple-voice-ivr` - Q4 2025
112
+
113
+ ## Features
114
+
115
+ ### 🔐 Secure Secrets Management
116
+ Secrets are stored in your OS keychain (Windows Credential Manager, macOS Keychain, Linux Secret Service):
117
+
118
+ ```bash
119
+ # Add a secret
120
+ sinch secrets add STRIPE_KEY sk_test_123456
121
+
122
+ # List secrets
123
+ sinch secrets list
124
+
125
+ # Use in your function
126
+ const stripeKey = process.env.STRIPE_KEY;
127
+ ```
128
+
129
+ ### 🔄 Hot Reload Development
130
+ Changes to your function are automatically reloaded:
131
+
132
+ ```bash
133
+ sinch functions dev --watch
134
+ ```
135
+
136
+ ### 🐛 VS Code Debugging
137
+ All templates include VS Code launch configs. Just press F5 to debug!
138
+
139
+ ### 🌐 Tunnel Support
140
+ Test webhooks locally with runtime-integrated tunneling:
141
+
142
+ ```bash
143
+ sinch functions dev
144
+ # Choose tunnel preference when prompted
145
+ # Tunnel runs inside your function runtime
146
+ ```
147
+
148
+ ## Documentation
149
+
150
+ - **Full Documentation**: [/docs/README.md](./docs/README.md)
151
+ - **Command Reference**: [/docs/COMMANDS.md](./docs/COMMANDS.md)
152
+ - **Development Guide**: [/docs/DEVELOPMENT.md](./docs/DEVELOPMENT.md)
153
+ - **Examples**: [/docs/examples/](./docs/examples/)
154
+
155
+ ## Resources
156
+
157
+ - **Sinch Voice API**: https://www.sinch.com/products/apis/voice/
158
+ - **Documentation**: Full CLI reference in [/docs](./docs/README.md)
159
+ - **Templates Gallery**: Browse available templates with `sinch templates list`
160
+
161
+ ## Troubleshooting
162
+
163
+ ### Authentication Issues
164
+
165
+ ```bash
166
+ # Check authentication status
167
+ sinch auth status
168
+
169
+ # Re-authenticate if needed
170
+ sinch auth logout
171
+ sinch auth login
172
+ ```
173
+
174
+ ### Debug Mode
175
+
176
+ ```bash
177
+ # Enable debug output
178
+ DEBUG=1 sinch functions dev
179
+
180
+ # HTTP request debugging
181
+ DEBUG_HTTP=1 sinch functions deploy
182
+ ```
183
+
184
+ ### Common Issues
185
+
186
+ - **Command not found**: Reinstall globally with `npm install -g @sinch/sinch-cli@beta`
187
+ - **Authentication failed**: Check your Sinch API credentials with `sinch auth status`
188
+ - **Deployment failed**: Verify your function configuration and project access
189
+
190
+ ## Support
191
+
192
+ - **Documentation**: [Full CLI Documentation](./docs/README.md)
193
+ - **Issues**: [Report a Bug](https://gitlab.com/sinch/sinch-projects/voice/functions/sinch-cli/-/issues)
194
+ - **Email**: support@sinch.com
195
+
196
+ ## Contributing
197
+
198
+ Contributions are welcome! Visit our [GitLab repository](https://gitlab.com/sinch/sinch-projects/voice/functions/sinch-cli) for development setup and contribution guidelines.
199
+
200
+ ## License
201
+
202
+ MIT License - Copyright © 2025 Sinch
203
+
204
+ ---
205
+
206
+ **npm**: https://www.npmjs.com/package/@sinch/sinch-cli
207
+ **Repository**: https://gitlab.com/sinch/sinch-projects/voice/functions/sinch-cli
208
+ **Version**: 0.1.0-beta.1
203
209
  **Status**: Open Beta
package/bin/sinch CHANGED
@@ -1,4 +1,4 @@
1
1
  #!/usr/bin/env node
2
-
3
- // Use compiled TypeScript output
2
+
3
+ // Use compiled TypeScript output
4
4
  require('../dist/index.js');
package/dist/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- "use strict";var Vn=Object.create;var Ne=Object.defineProperty;var Kn=Object.getOwnPropertyDescriptor;var qn=Object.getOwnPropertyNames;var Mn=Object.getPrototypeOf,Jn=Object.prototype.hasOwnProperty;var fe=(o,e)=>()=>(o&&(e=o(o=0)),e);var _=(o,e)=>()=>(e||o((e={exports:{}}).exports,e),e.exports),Ue=(o,e)=>{for(var n in e)Ne(o,n,{get:e[n],enumerable:!0})},ht=(o,e,n,i)=>{if(e&&typeof e=="object"||typeof e=="function")for(let r of qn(e))!Jn.call(o,r)&&r!==n&&Ne(o,r,{get:()=>e[r],enumerable:!(i=Kn(e,r))||i.enumerable});return o};var m=(o,e,n)=>(n=o!=null?Vn(Mn(o)):{},ht(e||!o||!o.__esModule?Ne(n,"default",{value:o,enumerable:!0}):n,o)),N=o=>ht(Ne({},"__esModule",{value:!0}),o);var yt=_((ei,Wn)=>{Wn.exports={name:"@sinch/cli",version:"0.1.0-beta.1",description:"Official Sinch CLI - Manage all Sinch products from your terminal",main:"dist/index.js",bin:{sinch:"bin/sinch"},scripts:{start:"tsx src/index.ts",dev:"tsx watch src/index.ts",build:"tsc && node scripts/post-build.js","build:prod":"tsup src/index.ts --format cjs --dts --clean --minify",typecheck:"tsc --noEmit",test:"jest",prepublishOnly:"npm run build:prod"},keywords:[],author:"Sinch <support@sinch.com> (https://www.sinch.com)",license:"MIT",private:!1,publishConfig:{access:"public",registry:"https://registry.npmjs.org/"},homepage:"https://www.sinch.com/products/apis/voice/",files:["dist/","bin/","README.md","LICENSE"],dependencies:{"@sinch/sdk-core":"^1.2.1","adm-zip":"^0.5.10",axios:"^1.7.9",blessed:"^0.1.81",chalk:"^4.1.2",chokidar:"^4.0.3","cli-spinners":"^3.2.0","cli-table3":"^0.6.3",clipboardy:"^3.0.0",commander:"^14.0.0",eventsource:"^4.0.0","form-data":"^4.0.0","fs-extra":"^11.1.1",inquirer:"^9.3.8",keytar:"^7.9.0",ora:"^5.4.1"},devDependencies:{"@types/adm-zip":"^0.5.7","@types/blessed":"^0.1.25","@types/fs-extra":"^11.0.4","@types/inquirer":"^9.0.9","@types/keytar":"^4.4.0","@types/node":"^24.3.0",jest:"^29.7.0",nodemon:"^3.0.1",tsup:"^8.5.0",tsx:"^4.20.4",typescript:"^5.9.2"},engines:{node:">=20.0.0",npm:">=9.0.0"}}});var Ve={};Ue(Ve,{SinchAPI:()=>E});var Be,ze,Se,E,U=fe(()=>{"use strict";Be=m(require("axios")),ze=m(require("form-data")),Se=m(require("chalk")),E=class{baseUrl;projectId;timeout;credentials;client;constructor(e={}){this.baseUrl=e.apiUrl||"https://functions.api.sinch.com/",this.projectId=e.projectId||"",this.timeout=e.timeout||3e4,this.credentials=e.credentials||null,this.client=Be.default.create({baseURL:this.baseUrl,timeout:this.timeout,headers:{"User-Agent":"sinch-functions-cli/1.0.0"}}),this.client.interceptors.request.use(async n=>{if(this.credentials){let i=await this.getValidToken();i&&(n.headers.Authorization=`${i.token_type} ${i.access_token}`)}return process.env.DEBUG_HTTP&&console.log(Se.default.gray(`\u2192 ${n.method?.toUpperCase()} ${n.url}`)),n},n=>Promise.reject(n)),this.client.interceptors.response.use(n=>(process.env.DEBUG_HTTP&&console.log(Se.default.gray(`\u2190 ${n.status} ${n.config.url}`)),n),async n=>{if(process.env.DEBUG_HTTP&&console.log(Se.default.red(`\u2190 ${n.response?.status||"ERROR"} ${n.config?.url}`)),n.response?.status===401&&this.credentials&&n.config){let i=n.config;if(!i._retry){i._retry=!0;try{let r=await this.getValidToken();if(r)return i.headers.Authorization=`${r.token_type} ${r.access_token}`,this.client.request(i)}catch{console.error(Se.default.yellow("Token refresh failed during retry"))}}}return Promise.reject(n)})}async listAllTemplates(e=null){try{let n=e?{category:e}:{};return(await this.client.get(`/v1/projects/${this.projectId}/templates`,{params:n})).data}catch(n){throw this._handleError(n,"Failed to list templates")}}async listRuntimeTemplates(e,n=null){try{let i=n?{category:n}:{};return(await this.client.get(`/v1/projects/${this.projectId}/templates/${e}`,{params:i})).data}catch(i){throw this._handleError(i,`Failed to list ${e} templates`)}}async getTemplateDetails(e,n){try{return(await this.client.get(`/v1/projects/${this.projectId}/templates/${e}/${n}`)).data}catch(i){throw this._handleError(i,`Failed to get template details for ${e}/${n}`)}}async downloadTemplate(e,n){try{let i=await this.client.get(`/v1/projects/${this.projectId}/templates/${e}/${n}/download`,{responseType:"arraybuffer"});return Buffer.from(i.data)}catch(i){throw this._handleError(i,`Failed to download template ${e}/${n}`)}}async listFunctions(){try{return(await this.client.get(`/v1/projects/${this.projectId}/functions`)).data}catch(e){throw this._handleError(e,"Failed to list functions")}}async getFunction(e){try{return(await this.client.get(`/v1/projects/${this.projectId}/functions/${e}`)).data}catch(n){throw this._handleError(n,`Failed to get function ${e}`)}}async deployFunction(e,n,i,r){try{let s=new ze.default;return s.append("name",e),s.append("runtime",n),s.append("code",i,{filename:"function.zip"}),r&&s.append("configuration",JSON.stringify(r)),(await this.client.post(`/v1/projects/${this.projectId}/functions`,s,{headers:{...s.getHeaders()},maxContentLength:1/0,maxBodyLength:1/0})).data}catch(s){throw this._handleError(s,"Failed to deploy function")}}async updateFunction(e,n,i){try{let r=new ze.default;return r.append("code",n,{filename:"function.zip"}),i&&r.append("configuration",JSON.stringify(i)),(await this.client.put(`/v1/projects/${this.projectId}/functions/${e}`,r,{headers:{...r.getHeaders()},maxContentLength:1/0,maxBodyLength:1/0})).data}catch(r){throw this._handleError(r,`Failed to update function ${e}`)}}async deleteFunction(e){try{await this.client.delete(`/v1/projects/${this.projectId}/functions/${e}`)}catch(n){throw this._handleError(n,`Failed to delete function ${e}`)}}async downloadFunction(e){try{let n=await this.client.get(`/v1/projects/${this.projectId}/functions/${e}/download`,{responseType:"arraybuffer"});return Buffer.from(n.data)}catch(n){throw this._handleError(n,`Failed to download function ${e}`)}}async getFunctionLogs(e,n={}){try{return(await this.client.get(`/v1/projects/${this.projectId}/functions/${e}/logs`,{params:n})).data}catch(i){throw this._handleError(i,`Failed to get logs for function ${e}`)}}async getFunctionStatus(e){try{return(await this.client.get(`/v1/projects/${this.projectId}/functions/${e}/deployment/status`)).data}catch(n){throw this._handleError(n,`Failed to get status for function ${e}`)}}async generateDocumentationFromCode(e,n="node",i="function"){try{return(await this.client.post(`/v1/projects/${this.projectId}/test/documentation`,{Code:e,Runtime:n,Name:i})).data}catch(r){throw this._handleError(r,"Failed to generate documentation from code")}}async generateDocumentationForFunction(e,n){try{let i=n?{MarkdownOverride:n}:{};return(await this.client.post(`/v1/projects/${this.projectId}/functions/${e}/documentation`,i)).data}catch(i){throw this._handleError(i,`Failed to generate documentation for function ${e}`)}}async getDocumentationForFunction(e){try{return(await this.client.get(`/v1/projects/${this.projectId}/functions/${e}/documentation`)).data}catch(n){throw this._handleError(n,`Failed to get documentation for function ${e}`)}}async streamDeployment(e,n,i){let r=u=>u.status?"status":u.progress?"progress":u.completed?"completed":u.failed||u.error?"failed":u.connected?"connected":"message",s=`${this.baseUrl}v1/projects/${this.projectId}/functions/${e}/deployment/stream`,a={Accept:"text/event-stream","Cache-Control":"no-cache"};if(this.credentials)try{let u=await this.credentials.retrieve();if(u&&u.keyId&&u.keySecret){let l=Buffer.from(`${u.keyId}:${u.keySecret}`).toString("base64");a.Authorization=`Basic ${l}`}}catch(u){console.error("Failed to add authentication:",u)}let c=null;try{c=new AbortController;let u=await fetch(s,{method:"GET",headers:a,signal:c.signal});if(!u.ok)throw new Error(`SSE connection failed: ${u.status} ${u.statusText}`);if(!u.body)throw new Error("Response body is null");let l=u.body.getReader(),g=new TextDecoder,h="";return(async()=>{let C="";try{for(;;){let{done:M,value:G}=await l.read();if(M)break;let P=g.decode(G,{stream:!0});h+=P;let b=h.split(`
2
+ "use strict";var Vn=Object.create;var Ne=Object.defineProperty;var Kn=Object.getOwnPropertyDescriptor;var qn=Object.getOwnPropertyNames;var Mn=Object.getPrototypeOf,Jn=Object.prototype.hasOwnProperty;var fe=(o,e)=>()=>(o&&(e=o(o=0)),e);var _=(o,e)=>()=>(e||o((e={exports:{}}).exports,e),e.exports),Ue=(o,e)=>{for(var n in e)Ne(o,n,{get:e[n],enumerable:!0})},ht=(o,e,n,i)=>{if(e&&typeof e=="object"||typeof e=="function")for(let r of qn(e))!Jn.call(o,r)&&r!==n&&Ne(o,r,{get:()=>e[r],enumerable:!(i=Kn(e,r))||i.enumerable});return o};var m=(o,e,n)=>(n=o!=null?Vn(Mn(o)):{},ht(e||!o||!o.__esModule?Ne(n,"default",{value:o,enumerable:!0}):n,o)),N=o=>ht(Ne({},"__esModule",{value:!0}),o);var yt=_((ei,Wn)=>{Wn.exports={name:"@sinch/cli",version:"0.1.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",prepublishOnly:"npm run build:prod"},keywords:[],author:"Sinch <support@sinch.com> (https://www.sinch.com)",license:"MIT",private:!1,publishConfig:{access:"public",registry:"https://registry.npmjs.org/"},homepage:"https://www.sinch.com/products/apis/voice/",files:["dist/","bin/","README.md","LICENSE"],dependencies:{"@sinch/sdk-core":"^1.2.1","adm-zip":"^0.5.10",axios:"^1.7.9",blessed:"^0.1.81",chalk:"^4.1.2",chokidar:"^3.6.0","cli-spinners":"^3.2.0","cli-table3":"^0.6.3",clipboardy:"^2.3.0",commander:"^12.1.0",eventsource:"^4.0.0","form-data":"^4.0.0","fs-extra":"^11.1.1",inquirer:"8.2.6",keytar:"^7.9.0",ora:"^4.1.1"},devDependencies:{"@types/adm-zip":"^0.5.7","@types/blessed":"^0.1.25","@types/fs-extra":"^11.0.4","@types/inquirer":"^9.0.9","@types/keytar":"^4.4.0","@types/node":"^24.3.0",jest:"^29.7.0",nodemon:"^3.0.1",tsup:"^8.5.0",tsx:"^4.20.4",typescript:"^5.9.2"},engines:{node:">=20.0.0",npm:">=9.0.0"}}});var Ve={};Ue(Ve,{SinchAPI:()=>E});var Be,ze,Se,E,U=fe(()=>{"use strict";Be=m(require("axios")),ze=m(require("form-data")),Se=m(require("chalk")),E=class{baseUrl;projectId;timeout;credentials;client;constructor(e={}){this.baseUrl=e.apiUrl||"https://functions.api.sinch.com/",this.projectId=e.projectId||"",this.timeout=e.timeout||3e4,this.credentials=e.credentials||null,this.client=Be.default.create({baseURL:this.baseUrl,timeout:this.timeout,headers:{"User-Agent":"sinch-functions-cli/1.0.0"}}),this.client.interceptors.request.use(async n=>{if(this.credentials){let i=await this.getValidToken();i&&(n.headers.Authorization=`${i.token_type} ${i.access_token}`)}return process.env.DEBUG_HTTP&&console.log(Se.default.gray(`\u2192 ${n.method?.toUpperCase()} ${n.url}`)),n},n=>Promise.reject(n)),this.client.interceptors.response.use(n=>(process.env.DEBUG_HTTP&&console.log(Se.default.gray(`\u2190 ${n.status} ${n.config.url}`)),n),async n=>{if(process.env.DEBUG_HTTP&&console.log(Se.default.red(`\u2190 ${n.response?.status||"ERROR"} ${n.config?.url}`)),n.response?.status===401&&this.credentials&&n.config){let i=n.config;if(!i._retry){i._retry=!0;try{let r=await this.getValidToken();if(r)return i.headers.Authorization=`${r.token_type} ${r.access_token}`,this.client.request(i)}catch{console.error(Se.default.yellow("Token refresh failed during retry"))}}}return Promise.reject(n)})}async listAllTemplates(e=null){try{let n=e?{category:e}:{};return(await this.client.get(`/v1/projects/${this.projectId}/templates`,{params:n})).data}catch(n){throw this._handleError(n,"Failed to list templates")}}async listRuntimeTemplates(e,n=null){try{let i=n?{category:n}:{};return(await this.client.get(`/v1/projects/${this.projectId}/templates/${e}`,{params:i})).data}catch(i){throw this._handleError(i,`Failed to list ${e} templates`)}}async getTemplateDetails(e,n){try{return(await this.client.get(`/v1/projects/${this.projectId}/templates/${e}/${n}`)).data}catch(i){throw this._handleError(i,`Failed to get template details for ${e}/${n}`)}}async downloadTemplate(e,n){try{let i=await this.client.get(`/v1/projects/${this.projectId}/templates/${e}/${n}/download`,{responseType:"arraybuffer"});return Buffer.from(i.data)}catch(i){throw this._handleError(i,`Failed to download template ${e}/${n}`)}}async listFunctions(){try{return(await this.client.get(`/v1/projects/${this.projectId}/functions`)).data}catch(e){throw this._handleError(e,"Failed to list functions")}}async getFunction(e){try{return(await this.client.get(`/v1/projects/${this.projectId}/functions/${e}`)).data}catch(n){throw this._handleError(n,`Failed to get function ${e}`)}}async deployFunction(e,n,i,r){try{let s=new ze.default;return s.append("name",e),s.append("runtime",n),s.append("code",i,{filename:"function.zip"}),r&&s.append("configuration",JSON.stringify(r)),(await this.client.post(`/v1/projects/${this.projectId}/functions`,s,{headers:{...s.getHeaders()},maxContentLength:1/0,maxBodyLength:1/0})).data}catch(s){throw this._handleError(s,"Failed to deploy function")}}async updateFunction(e,n,i){try{let r=new ze.default;return r.append("code",n,{filename:"function.zip"}),i&&r.append("configuration",JSON.stringify(i)),(await this.client.put(`/v1/projects/${this.projectId}/functions/${e}`,r,{headers:{...r.getHeaders()},maxContentLength:1/0,maxBodyLength:1/0})).data}catch(r){throw this._handleError(r,`Failed to update function ${e}`)}}async deleteFunction(e){try{await this.client.delete(`/v1/projects/${this.projectId}/functions/${e}`)}catch(n){throw this._handleError(n,`Failed to delete function ${e}`)}}async downloadFunction(e){try{let n=await this.client.get(`/v1/projects/${this.projectId}/functions/${e}/download`,{responseType:"arraybuffer"});return Buffer.from(n.data)}catch(n){throw this._handleError(n,`Failed to download function ${e}`)}}async getFunctionLogs(e,n={}){try{return(await this.client.get(`/v1/projects/${this.projectId}/functions/${e}/logs`,{params:n})).data}catch(i){throw this._handleError(i,`Failed to get logs for function ${e}`)}}async getFunctionStatus(e){try{return(await this.client.get(`/v1/projects/${this.projectId}/functions/${e}/deployment/status`)).data}catch(n){throw this._handleError(n,`Failed to get status for function ${e}`)}}async generateDocumentationFromCode(e,n="node",i="function"){try{return(await this.client.post(`/v1/projects/${this.projectId}/test/documentation`,{Code:e,Runtime:n,Name:i})).data}catch(r){throw this._handleError(r,"Failed to generate documentation from code")}}async generateDocumentationForFunction(e,n){try{let i=n?{MarkdownOverride:n}:{};return(await this.client.post(`/v1/projects/${this.projectId}/functions/${e}/documentation`,i)).data}catch(i){throw this._handleError(i,`Failed to generate documentation for function ${e}`)}}async getDocumentationForFunction(e){try{return(await this.client.get(`/v1/projects/${this.projectId}/functions/${e}/documentation`)).data}catch(n){throw this._handleError(n,`Failed to get documentation for function ${e}`)}}async streamDeployment(e,n,i){let r=u=>u.status?"status":u.progress?"progress":u.completed?"completed":u.failed||u.error?"failed":u.connected?"connected":"message",s=`${this.baseUrl}v1/projects/${this.projectId}/functions/${e}/deployment/stream`,a={Accept:"text/event-stream","Cache-Control":"no-cache"};if(this.credentials)try{let u=await this.credentials.retrieve();if(u&&u.keyId&&u.keySecret){let l=Buffer.from(`${u.keyId}:${u.keySecret}`).toString("base64");a.Authorization=`Basic ${l}`}}catch(u){console.error("Failed to add authentication:",u)}let c=null;try{c=new AbortController;let u=await fetch(s,{method:"GET",headers:a,signal:c.signal});if(!u.ok)throw new Error(`SSE connection failed: ${u.status} ${u.statusText}`);if(!u.body)throw new Error("Response body is null");let l=u.body.getReader(),g=new TextDecoder,h="";return(async()=>{let C="";try{for(;;){let{done:M,value:G}=await l.read();if(M)break;let P=g.decode(G,{stream:!0});h+=P;let b=h.split(`
3
3
  `);h=b.pop()||"";for(let w of b){if(w.startsWith("event:")){C=w.substring(6).trim();continue}if(w.startsWith("data:")){let y=w.substring(5).trim();if(y)try{let k=JSON.parse(y),X=C||r(k);n({type:X,data:k}),C=""}catch{n({type:C||"message",data:y}),C=""}}w===""&&(C="")}}}catch(M){M.name!=="AbortError"&&i&&i(M)}})(),()=>{c&&c.abort()}}catch(u){throw console.error("Failed to create SSE stream:",u),i&&i(u),u}}async checkHealth(){try{return(await this.client.get("/health")).data}catch(e){throw this._handleError(e,"Health check failed")}}async getValidToken(){if(!this.credentials)return null;try{let e=await this.credentials.getOAuthToken();if(e)return{access_token:e,token_type:"Bearer",expires_in:3600};let n=await this.credentials.getBasicAuthToken();return n?{access_token:n,token_type:"Basic",expires_in:3600}:null}catch(e){return console.error(Se.default.yellow("Failed to get authentication token:",e.message)),null}}async authenticateOAuth(e,n){try{let i="https://auth.sinch.com/oauth2/token",r=new URLSearchParams;r.append("grant_type","client_credentials");let a=(await Be.default.post(i,r,{headers:{"Content-Type":"application/x-www-form-urlencoded",Authorization:"Basic "+Buffer.from(`${e}:${n}`).toString("base64")},timeout:this.timeout})).data;return this.credentials&&await this.credentials.storeOAuthToken(a),a}catch(i){throw this._handleError(i,"OAuth authentication failed")}}_handleError(e,n){if(Be.default.isAxiosError(e)){let i=e;if(i.response){let r=i.response.status,s=i.response.data,a=s?.message||s?.error||i.message;throw r===401?new Error('Authentication required. Please run "sinch auth login" first.'):r===403?new Error(`Permission denied: ${a}`):r===404?new Error(`Resource not found: ${a}`):r>=500?new Error(`Server error: ${a}`):new Error(`${n}: ${a}`)}else throw i.request?i.code==="ECONNREFUSED"?new Error(`Cannot connect to API at ${this.baseUrl}. Is the server running?`):i.code==="ETIMEDOUT"?new Error(`Request timeout after ${this.timeout}ms`):new Error(`${n}: No response from server`):new Error(`${n}: ${i.message}`)}else throw new Error(`${n}: ${e.message||e}`)}}});var A,wt,ve,R,B,Ke,bt=fe(()=>{"use strict";A=m(require("keytar")),wt=m(require("os")),ve=m(require("chalk")),R="sinch-functions-cli",B=wt.userInfo().username,Ke=class{config;constructor(e){this.config=e}async store(e){let{projectId:n,keyId:i,keySecret:r,applicationKey:s,applicationSecret:a}=e;await A.setPassword(R,`${B}-keySecret`,r),await A.setPassword(R,s,a),this.config.set("projectId",n),this.config.set("keyId",i),this.config.set("defaultApplicationKey",s),this.config.set("credentialsStored",!0),await this.config.save()}async storeOAuthToken(e){let{access_token:n,refresh_token:i,expires_in:r,token_type:s}=e,a=new Date(Date.now()+r*1e3).toISOString();await A.setPassword(R,`${B}-oauth-access`,n),i&&await A.setPassword(R,`${B}-oauth-refresh`,i),this.config.set("oauthTokenType",s),this.config.set("oauthExpiresAt",a),this.config.set("oauthStored",!0),await this.config.save()}async getOAuthToken(){if(!this.config.get("oauthStored"))return null;let n=this.config.get("oauthExpiresAt");if(n&&new Date(n)<new Date){console.log(ve.default.gray("Token expired, re-authenticating..."));try{let r=await A.getPassword(R,`${B}-keySecret`),s=this.config.get("keyId");if(s&&r){let{SinchAPI:a}=(U(),N(Ve)),u=await new a({apiUrl:this.config.get("apiUrl")||"http://localhost:5000",projectId:this.config.get("projectId"),credentials:null}).authenticateOAuth(s,r);return await this.storeOAuthToken(u),console.log(ve.default.green("\u2713 Token renewed successfully")),u.access_token}else return console.warn(ve.default.yellow("Missing credentials for re-authentication. Please login again.")),null}catch(r){return console.warn(ve.default.yellow("Failed to renew OAuth token. Please login again.")),console.error(ve.default.gray(`Authentication error: ${r.message}`)),null}}return await A.getPassword(R,`${B}-oauth-access`)}async storeApplicationSecret(e,n){await A.setPassword(R,e,n),this.config.get("defaultApplicationKey")||(this.config.set("defaultApplicationKey",e),await this.config.save())}async retrieve(){if(!this.config.get("credentialsStored"))return null;let n=this.config.get("projectId"),i=this.config.get("keyId"),r=this.config.get("defaultApplicationKey"),s=await A.getPassword(R,`${B}-keySecret`),a=r?await A.getPassword(R,r):null;return!s||!a?null:{projectId:n,keyId:i,keySecret:s,applicationKey:r,applicationSecret:a}}async getApplicationCredentials(e=null){if(e||(e=this.config.get("defaultApplicationKey")),!e)return null;let n=await A.getPassword(R,e);return n?{applicationKey:e,applicationSecret:n}:null}async clear(){let e=this.config.get("defaultApplicationKey");await A.deletePassword(R,`${B}-keySecret`),await A.deletePassword(R,`${B}-oauth-access`),await A.deletePassword(R,`${B}-oauth-refresh`),e&&await A.deletePassword(R,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),await this.config.save()}async hasCredentials(){if(!this.config.get("credentialsStored"))return!1;let n=await A.getPassword(R,`${B}-keySecret`),i=this.config.get("defaultApplicationKey"),r=i?await A.getPassword(R,i):null;return!!(n&&r)}async hasOAuthToken(){return this.config.get("oauthStored")?!!await A.getPassword(R,`${B}-oauth-access`):!1}getPublicInfo(){return{projectId:this.config.get("projectId"),keyId:this.config.get("keyId"),applicationKey:this.config.get("defaultApplicationKey"),hasCredentials:this.config.get("credentialsStored",!1),hasOAuth:this.config.get("oauthStored",!1),oauthExpiresAt:this.config.get("oauthExpiresAt")}}async createSinchClient(e=null){let n=await this.getApplicationCredentials(e);if(!n)throw new Error('No credentials found. Please run "sinch auth login" first.');let{SinchClient:i}=require("@sinch/sdk-core");return new i({applicationKey:n.applicationKey,applicationSecret:n.applicationSecret,projectId:this.config.get("projectId")})}async storeBasicAuthToken(e){await A.setPassword(R,`${B}-basic-auth`,e),this.config.set("basicAuthStored",!0),await this.config.save()}async getBasicAuthToken(){return this.config.get("basicAuthStored")?await A.getPassword(R,`${B}-basic-auth`):null}async clearBasicAuthToken(){await A.deletePassword(R,`${B}-basic-auth`),this.config.set("basicAuthStored",!1),await this.config.save()}}});var ge={};Ue(ge,{Config:()=>qe,config:()=>p});var H,Te,Ct,Ye,qe,p,T=fe(()=>{"use strict";H=m(require("fs-extra")),Te=m(require("path")),Ct=m(require("os")),Ye=m(require("chalk"));bt();qe=class{configDir;configFile;projectConfigFile;_config=null;_projectConfig=null;_credentials=null;constructor(){this.configDir=Te.join(Ct.homedir(),".sinch"),this.configFile=Te.join(this.configDir,"config.json"),this.projectConfigFile=Te.join(process.cwd(),"sinch.json")}async load(){try{await H.ensureDir(this.configDir),await H.pathExists(this.configFile)?this._config=await H.readJson(this.configFile):(this._config=this._getDefaultConfig(),await this.save())}catch(e){console.warn(Ye.default.yellow(`Warning: Could not load config: ${e.message}`)),this._config=this._getDefaultConfig()}this._credentials=new Ke(this);try{await H.pathExists(this.projectConfigFile)&&(this._projectConfig=await H.readJson(this.projectConfigFile))}catch(e){console.warn(Ye.default.yellow(`Warning: Could not load project config: ${e.message}`))}}async save(){try{await H.ensureDir(this.configDir),await H.writeJson(this.configFile,this._config,{spaces:2})}catch(e){throw new Error(`Could not save config: ${e.message}`)}}async saveProjectConfig(){try{if(this._projectConfig){let e=Te.join(process.cwd(),"sinch.json");await H.writeJson(e,this._projectConfig,{spaces:2})}}catch(e){throw new Error(`Could not save project config: ${e.message}`)}}get(e,n=null){if(!this._config)throw new Error("Config not loaded. Call load() first.");return this._projectConfig&&this._projectConfig[e]!==void 0?this._projectConfig[e]:this._config[e]!==void 0?this._config[e]:n}set(e,n,i=!1){if(!this._config)throw new Error("Config not loaded. Call load() first.");i?(this._projectConfig||(this._projectConfig={}),this._projectConfig[e]=n):this._config[e]=n}getApiConfig(){return{apiUrl:this.get("apiUrl"),projectId:this.get("projectId"),timeout:this.get("timeout"),credentials:this._credentials}}async initProject(e,n="node",i={},r=null){let s={name:e,runtime:n,version:"1.0.0",description:`Sinch Functions project: ${e}`,created:new Date().toISOString()};return i&&Object.keys(i).length>0&&(s.variables=i),r&&(s.applicationKey=r),this._projectConfig=s,await this.saveProjectConfig(),s}isInProject(){return this._projectConfig!==null}getProjectConfig(){return this._projectConfig}_getDefaultConfig(){return{apiUrl:"https://api.functions.dev.sinchvoice.org",projectId:"default-project",timeout:0,created:new Date().toISOString(),version:"1.0.0"}}async storeCredentials(e){if(!this._credentials)throw new Error("Config not loaded. Call load() first.");return await this._credentials.store(e)}async getCredentials(){if(!this._credentials)throw new Error("Config not loaded. Call load() first.");return await this._credentials.retrieve()}async clearCredentials(){if(!this._credentials)throw new Error("Config not loaded. Call load() first.");return await this._credentials.clear()}async hasCredentials(){if(!this._credentials)throw new Error("Config not loaded. Call load() first.");return await this._credentials.hasCredentials()}getPublicCredentialInfo(){if(!this._credentials)throw new Error("Config not loaded. Call load() first.");return this._credentials.getPublicInfo()}async createSinchClient(e=null){if(!this._credentials)throw new Error("Config not loaded. Call load() first.");return!e&&this.isInProject()&&(e=this._projectConfig?.applicationKey||null),await this._credentials.createSinchClient(e)}async getApplicationCredentials(e=null){if(!this._credentials)throw new Error("Config not loaded. Call load() first.");return!e&&this.isInProject()&&(e=this._projectConfig?.applicationKey||null),await this._credentials.getApplicationCredentials(e)}async storeApplicationSecret(e,n){if(!this._credentials)throw new Error("Config not loaded. Call load() first.");return await this._credentials.storeApplicationSecret(e,n)}getTunnelPreference(){return this._projectConfig&&this._projectConfig.tunnel?.preference||null}async setTunnelPreference(e){if(!this._projectConfig)throw new Error("Not in a project directory");this._projectConfig.tunnel||(this._projectConfig.tunnel={}),this._projectConfig.tunnel.preference=e,this._projectConfig.tunnel.lastUpdated=new Date().toISOString(),await this.saveProjectConfig()}getTunnelSubdomain(){return this._projectConfig&&this._projectConfig.tunnel?.subdomain||null}async setTunnelSubdomain(e){if(!this._projectConfig)throw new Error("Not in a project directory");this._projectConfig.tunnel||(this._projectConfig.tunnel={}),this._projectConfig.tunnel.subdomain=e,this._projectConfig.tunnel.lastUpdated=new Date().toISOString(),await this.saveProjectConfig()}getTunnelUrl(){return this._projectConfig&&this._projectConfig.tunnel?.lastUrl||null}async setTunnelUrl(e){if(!this._projectConfig)throw new Error("Not in a project directory");this._projectConfig.tunnel||(this._projectConfig.tunnel={}),this._projectConfig.tunnel.lastUrl=e,this._projectConfig.tunnel.lastUpdated=new Date().toISOString(),await this.saveProjectConfig()}},p=new qe});var z,se,Qe,$t,Ze,t,V=fe(()=>{"use strict";z=m(require("chalk")),se=m(require("fs")),Qe=m(require("path")),$t=m(require("os")),Ze=class{verbose;logFile;constructor(e={}){this.verbose=e.verbose||process.env.VERBOSE==="true";let n="cli";try{let i=Qe.join(process.cwd(),"sinch.json");se.existsSync(i)&&(n=JSON.parse(se.readFileSync(i,"utf8")).name||"cli")}catch{}this.logFile=Qe.join($t.tmpdir(),`sinch-${n}.log`);try{se.writeFileSync(this.logFile,`=== Sinch CLI Debug Log - ${new Date().toISOString()} ===
4
4
  `,{flag:"w"})}catch{}}writeToFile(e,n,...i){try{let s=`[${new Date().toISOString()}] ${e}: ${n} ${i.length>0?JSON.stringify(i):""}
5
5
  `;se.appendFileSync(this.logFile,s)}catch{}}info(e,...n){console.log(z.default.blue("\u2139"),e,...n),this.writeToFile("INFO",e,...n)}success(e,...n){console.log(z.default.green("\u2705"),e,...n),this.writeToFile("SUCCESS",e,...n)}warn(e,...n){console.log(z.default.yellow("\u26A0\uFE0F "),e,...n),this.writeToFile("WARN",e,...n)}error(e,...n){console.log(z.default.red("\u274C"),e,...n),this.writeToFile("ERROR",e,...n)}debug(e,...n){this.writeToFile("DEBUG",e,...n),(this.verbose||process.env.DEBUG)&&console.log(z.default.gray("\u{1F41B}"),z.default.gray(e),...n)}log(e,...n){console.log(e,...n)}title(e){console.log(z.default.blue.bold(`
package/package.json CHANGED
@@ -1,68 +1,68 @@
1
- {
2
- "name": "@sinch/cli",
3
- "version": "0.1.0-beta.1",
4
- "description": "Official Sinch CLI - Manage all Sinch products from your terminal",
5
- "main": "dist/index.js",
6
- "bin": {
7
- "sinch": "bin/sinch"
8
- },
9
- "scripts": {
10
- "start": "tsx src/index.ts",
11
- "dev": "tsx watch src/index.ts",
12
- "build": "tsc && node scripts/post-build.js",
13
- "build:prod": "tsup src/index.ts --format cjs --dts --clean --minify",
14
- "typecheck": "tsc --noEmit",
15
- "test": "jest",
16
- "prepublishOnly": "npm run build:prod"
17
- },
18
- "keywords": [],
19
- "author": "Sinch <support@sinch.com> (https://www.sinch.com)",
20
- "license": "MIT",
21
- "private": false,
22
- "publishConfig": {
23
- "access": "public",
24
- "registry": "https://registry.npmjs.org/"
25
- },
26
- "homepage": "https://www.sinch.com/products/apis/voice/",
27
- "files": [
28
- "dist/",
29
- "bin/",
30
- "README.md",
31
- "LICENSE"
32
- ],
33
- "dependencies": {
34
- "@sinch/sdk-core": "^1.2.1",
35
- "adm-zip": "^0.5.10",
36
- "axios": "^1.7.9",
37
- "blessed": "^0.1.81",
38
- "chalk": "^4.1.2",
39
- "chokidar": "^4.0.3",
40
- "cli-spinners": "^3.2.0",
41
- "cli-table3": "^0.6.3",
42
- "clipboardy": "^3.0.0",
43
- "commander": "^14.0.0",
44
- "eventsource": "^4.0.0",
45
- "form-data": "^4.0.0",
46
- "fs-extra": "^11.1.1",
47
- "inquirer": "^9.3.8",
48
- "keytar": "^7.9.0",
49
- "ora": "^5.4.1"
50
- },
51
- "devDependencies": {
52
- "@types/adm-zip": "^0.5.7",
53
- "@types/blessed": "^0.1.25",
54
- "@types/fs-extra": "^11.0.4",
55
- "@types/inquirer": "^9.0.9",
56
- "@types/keytar": "^4.4.0",
57
- "@types/node": "^24.3.0",
58
- "jest": "^29.7.0",
59
- "nodemon": "^3.0.1",
60
- "tsup": "^8.5.0",
61
- "tsx": "^4.20.4",
62
- "typescript": "^5.9.2"
63
- },
64
- "engines": {
65
- "node": ">=20.0.0",
66
- "npm": ">=9.0.0"
67
- }
68
- }
1
+ {
2
+ "name": "@sinch/cli",
3
+ "version": "0.1.3-beta",
4
+ "description": "Official Sinch CLI - Manage all Sinch products from your terminal",
5
+ "main": "dist/index.js",
6
+ "bin": {
7
+ "sinch": "bin/sinch"
8
+ },
9
+ "scripts": {
10
+ "start": "tsx src/index.ts",
11
+ "dev": "tsx watch src/index.ts",
12
+ "build": "tsc && node scripts/post-build.js",
13
+ "build:prod": "tsup src/index.ts --format cjs --dts --clean --minify",
14
+ "typecheck": "tsc --noEmit",
15
+ "test": "jest",
16
+ "prepublishOnly": "npm run build:prod"
17
+ },
18
+ "keywords": [],
19
+ "author": "Sinch <support@sinch.com> (https://www.sinch.com)",
20
+ "license": "MIT",
21
+ "private": false,
22
+ "publishConfig": {
23
+ "access": "public",
24
+ "registry": "https://registry.npmjs.org/"
25
+ },
26
+ "homepage": "https://www.sinch.com/products/apis/voice/",
27
+ "files": [
28
+ "dist/",
29
+ "bin/",
30
+ "README.md",
31
+ "LICENSE"
32
+ ],
33
+ "dependencies": {
34
+ "@sinch/sdk-core": "^1.2.1",
35
+ "adm-zip": "^0.5.10",
36
+ "axios": "^1.7.9",
37
+ "blessed": "^0.1.81",
38
+ "chalk": "^4.1.2",
39
+ "chokidar": "^3.6.0",
40
+ "cli-spinners": "^3.2.0",
41
+ "cli-table3": "^0.6.3",
42
+ "clipboardy": "^2.3.0",
43
+ "commander": "^12.1.0",
44
+ "eventsource": "^4.0.0",
45
+ "form-data": "^4.0.0",
46
+ "fs-extra": "^11.1.1",
47
+ "inquirer": "8.2.6",
48
+ "keytar": "^7.9.0",
49
+ "ora": "^4.1.1"
50
+ },
51
+ "devDependencies": {
52
+ "@types/adm-zip": "^0.5.7",
53
+ "@types/blessed": "^0.1.25",
54
+ "@types/fs-extra": "^11.0.4",
55
+ "@types/inquirer": "^9.0.9",
56
+ "@types/keytar": "^4.4.0",
57
+ "@types/node": "^24.3.0",
58
+ "jest": "^29.7.0",
59
+ "nodemon": "^3.0.1",
60
+ "tsup": "^8.5.0",
61
+ "tsx": "^4.20.4",
62
+ "typescript": "^5.9.2"
63
+ },
64
+ "engines": {
65
+ "node": ">=20.0.0",
66
+ "npm": ">=9.0.0"
67
+ }
68
+ }