@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 +21 -21
- package/README.md +208 -202
- package/bin/sinch +2 -2
- package/dist/index.js +1 -1
- package/package.json +68 -68
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
|
-
[](https://www.npmjs.com/package/@sinch/sinch-cli)
|
|
6
|
-
[](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
|
-
#
|
|
16
|
-
npm install -g @sinch/
|
|
17
|
-
|
|
18
|
-
#
|
|
19
|
-
npm install -g @sinch/
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
-
|
|
27
|
-
-
|
|
28
|
-
-
|
|
29
|
-
|
|
30
|
-
##
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
###
|
|
39
|
-
|
|
40
|
-
```bash
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
```
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
```
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
sinch functions
|
|
62
|
-
```
|
|
63
|
-
|
|
64
|
-
###
|
|
65
|
-
|
|
66
|
-
```bash
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
#
|
|
74
|
-
sinch functions
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
|
86
|
-
|
|
87
|
-
| `sinch
|
|
88
|
-
| `sinch
|
|
89
|
-
| `sinch
|
|
90
|
-
| `sinch
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
- `
|
|
105
|
-
- `
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
###
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
#
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
- **
|
|
152
|
-
- **
|
|
153
|
-
- **
|
|
154
|
-
|
|
155
|
-
##
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
```
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
- **
|
|
187
|
-
- **
|
|
188
|
-
- **
|
|
189
|
-
|
|
190
|
-
##
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
1
|
+
# Sinch CLI
|
|
2
|
+
|
|
3
|
+
> **Official command-line interface for Sinch - Manage Functions, Voice, SMS, and more from your terminal**
|
|
4
|
+
|
|
5
|
+
[](https://www.npmjs.com/package/@sinch/sinch-cli)
|
|
6
|
+
[](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
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
|
|
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.
|
|
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": "^
|
|
40
|
-
"cli-spinners": "^3.2.0",
|
|
41
|
-
"cli-table3": "^0.6.3",
|
|
42
|
-
"clipboardy": "^3.0
|
|
43
|
-
"commander": "^
|
|
44
|
-
"eventsource": "^4.0.0",
|
|
45
|
-
"form-data": "^4.0.0",
|
|
46
|
-
"fs-extra": "^11.1.1",
|
|
47
|
-
"inquirer": "
|
|
48
|
-
"keytar": "^7.9.0",
|
|
49
|
-
"ora": "^
|
|
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
|
+
}
|