@getbrevo/cli 0.0.1-alpha.1
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/CHANGELOG.md +13 -0
- package/LICENSE +21 -0
- package/README.md +182 -0
- package/dist/api/client.d.ts +23 -0
- package/dist/api/client.d.ts.map +1 -0
- package/dist/api/client.js +186 -0
- package/dist/api/client.js.map +1 -0
- package/dist/bin/index.d.ts +3 -0
- package/dist/bin/index.d.ts.map +1 -0
- package/dist/bin/index.js +179 -0
- package/dist/bin/index.js.map +1 -0
- package/dist/commands/app/create.d.ts +7 -0
- package/dist/commands/app/create.d.ts.map +1 -0
- package/dist/commands/app/create.js +261 -0
- package/dist/commands/app/create.js.map +1 -0
- package/dist/commands/app/credentials.d.ts +6 -0
- package/dist/commands/app/credentials.d.ts.map +1 -0
- package/dist/commands/app/credentials.js +106 -0
- package/dist/commands/app/credentials.js.map +1 -0
- package/dist/commands/app/delete.d.ts +6 -0
- package/dist/commands/app/delete.d.ts.map +1 -0
- package/dist/commands/app/delete.js +146 -0
- package/dist/commands/app/delete.js.map +1 -0
- package/dist/commands/app/list.d.ts +4 -0
- package/dist/commands/app/list.d.ts.map +1 -0
- package/dist/commands/app/list.js +46 -0
- package/dist/commands/app/list.js.map +1 -0
- package/dist/commands/app/scaffold.d.ts +5 -0
- package/dist/commands/app/scaffold.d.ts.map +1 -0
- package/dist/commands/app/scaffold.js +199 -0
- package/dist/commands/app/scaffold.js.map +1 -0
- package/dist/commands/app/start.d.ts +5 -0
- package/dist/commands/app/start.d.ts.map +1 -0
- package/dist/commands/app/start.js +138 -0
- package/dist/commands/app/start.js.map +1 -0
- package/dist/commands/app/test.d.ts +6 -0
- package/dist/commands/app/test.d.ts.map +1 -0
- package/dist/commands/app/test.js +495 -0
- package/dist/commands/app/test.js.map +1 -0
- package/dist/commands/app/update.d.ts +2 -0
- package/dist/commands/app/update.d.ts.map +1 -0
- package/dist/commands/app/update.js +324 -0
- package/dist/commands/app/update.js.map +1 -0
- package/dist/commands/definitions.d.ts +4 -0
- package/dist/commands/definitions.d.ts.map +1 -0
- package/dist/commands/definitions.js +197 -0
- package/dist/commands/definitions.js.map +1 -0
- package/dist/commands/init.d.ts +2 -0
- package/dist/commands/init.d.ts.map +1 -0
- package/dist/commands/init.js +90 -0
- package/dist/commands/init.js.map +1 -0
- package/dist/commands/login.d.ts +6 -0
- package/dist/commands/login.d.ts.map +1 -0
- package/dist/commands/login.js +219 -0
- package/dist/commands/login.js.map +1 -0
- package/dist/commands/logout.d.ts +5 -0
- package/dist/commands/logout.d.ts.map +1 -0
- package/dist/commands/logout.js +54 -0
- package/dist/commands/logout.js.map +1 -0
- package/dist/commands/whoami.d.ts +4 -0
- package/dist/commands/whoami.d.ts.map +1 -0
- package/dist/commands/whoami.js +74 -0
- package/dist/commands/whoami.js.map +1 -0
- package/dist/container.d.ts +7 -0
- package/dist/container.d.ts.map +1 -0
- package/dist/container.js +28 -0
- package/dist/container.js.map +1 -0
- package/dist/lang/en.d.ts +110 -0
- package/dist/lang/en.d.ts.map +1 -0
- package/dist/lang/en.js +133 -0
- package/dist/lang/en.js.map +1 -0
- package/dist/lib/abort.d.ts +3 -0
- package/dist/lib/abort.d.ts.map +1 -0
- package/dist/lib/abort.js +30 -0
- package/dist/lib/abort.js.map +1 -0
- package/dist/lib/auth-guard.d.ts +3 -0
- package/dist/lib/auth-guard.d.ts.map +1 -0
- package/dist/lib/auth-guard.js +25 -0
- package/dist/lib/auth-guard.js.map +1 -0
- package/dist/lib/browser.d.ts +2 -0
- package/dist/lib/browser.d.ts.map +1 -0
- package/dist/lib/browser.js +16 -0
- package/dist/lib/browser.js.map +1 -0
- package/dist/lib/command-handler.d.ts +10 -0
- package/dist/lib/command-handler.d.ts.map +1 -0
- package/dist/lib/command-handler.js +16 -0
- package/dist/lib/command-handler.js.map +1 -0
- package/dist/lib/command-registry.d.ts +28 -0
- package/dist/lib/command-registry.d.ts.map +1 -0
- package/dist/lib/command-registry.js +54 -0
- package/dist/lib/command-registry.js.map +1 -0
- package/dist/lib/config.d.ts +76 -0
- package/dist/lib/config.d.ts.map +1 -0
- package/dist/lib/config.js +314 -0
- package/dist/lib/config.js.map +1 -0
- package/dist/lib/constants.d.ts +35 -0
- package/dist/lib/constants.d.ts.map +1 -0
- package/dist/lib/constants.js +97 -0
- package/dist/lib/constants.js.map +1 -0
- package/dist/lib/errors.d.ts +30 -0
- package/dist/lib/errors.d.ts.map +1 -0
- package/dist/lib/errors.js +66 -0
- package/dist/lib/errors.js.map +1 -0
- package/dist/lib/exit-codes.d.ts +9 -0
- package/dist/lib/exit-codes.d.ts.map +1 -0
- package/dist/lib/exit-codes.js +12 -0
- package/dist/lib/exit-codes.js.map +1 -0
- package/dist/lib/hidden-input.d.ts +2 -0
- package/dist/lib/hidden-input.d.ts.map +1 -0
- package/dist/lib/hidden-input.js +78 -0
- package/dist/lib/hidden-input.js.map +1 -0
- package/dist/lib/json-output.d.ts +6 -0
- package/dist/lib/json-output.d.ts.map +1 -0
- package/dist/lib/json-output.js +11 -0
- package/dist/lib/json-output.js.map +1 -0
- package/dist/lib/logger.d.ts +11 -0
- package/dist/lib/logger.d.ts.map +1 -0
- package/dist/lib/logger.js +87 -0
- package/dist/lib/logger.js.map +1 -0
- package/dist/lib/port.d.ts +12 -0
- package/dist/lib/port.d.ts.map +1 -0
- package/dist/lib/port.js +79 -0
- package/dist/lib/port.js.map +1 -0
- package/dist/lib/ui.d.ts +14 -0
- package/dist/lib/ui.d.ts.map +1 -0
- package/dist/lib/ui.js +75 -0
- package/dist/lib/ui.js.map +1 -0
- package/dist/lib/validators.d.ts +32 -0
- package/dist/lib/validators.d.ts.map +1 -0
- package/dist/lib/validators.js +96 -0
- package/dist/lib/validators.js.map +1 -0
- package/dist/services/account.d.ts +8 -0
- package/dist/services/account.d.ts.map +1 -0
- package/dist/services/account.js +15 -0
- package/dist/services/account.js.map +1 -0
- package/dist/services/app.d.ts +35 -0
- package/dist/services/app.d.ts.map +1 -0
- package/dist/services/app.js +117 -0
- package/dist/services/app.js.map +1 -0
- package/dist/services/browser-auth.d.ts +15 -0
- package/dist/services/browser-auth.d.ts.map +1 -0
- package/dist/services/browser-auth.js +187 -0
- package/dist/services/browser-auth.js.map +1 -0
- package/dist/services/normalize-app-id.d.ts +12 -0
- package/dist/services/normalize-app-id.d.ts.map +1 -0
- package/dist/services/normalize-app-id.js +38 -0
- package/dist/services/normalize-app-id.js.map +1 -0
- package/dist/services/oauth-refresh.d.ts +14 -0
- package/dist/services/oauth-refresh.d.ts.map +1 -0
- package/dist/services/oauth-refresh.js +70 -0
- package/dist/services/oauth-refresh.js.map +1 -0
- package/dist/templates/files/AGENTS.md.tmpl +41 -0
- package/dist/templates/files/CLAUDE.md.tmpl +50 -0
- package/dist/templates/files/README.md.tmpl +77 -0
- package/dist/templates/files/app-config.json.tmpl +23 -0
- package/dist/templates/files/gitignore.tmpl +9 -0
- package/dist/templates/files/src/oauth/.env.example.tmpl +13 -0
- package/dist/templates/files/src/oauth/.env.local.tmpl +10 -0
- package/dist/templates/files/src/oauth/handler.js.tmpl +203 -0
- package/dist/templates/files/src/oauth/package.json.tmpl +15 -0
- package/dist/templates/files/src/oauth/server.js.tmpl +226 -0
- package/dist/templates/files/src/oauth/token-store.js.tmpl +39 -0
- package/dist/templates/index.d.ts +36 -0
- package/dist/templates/index.d.ts.map +1 -0
- package/dist/templates/index.js +105 -0
- package/dist/templates/index.js.map +1 -0
- package/dist/types.d.ts +30 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +3 -0
- package/dist/types.js.map +1 -0
- package/package.json +81 -0
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
# @getbrevo/cli
|
|
2
|
+
|
|
3
|
+
## 0.0.1-alpha.1
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- first cli package
|
|
8
|
+
|
|
9
|
+
## 0.0.1-alpha.0
|
|
10
|
+
|
|
11
|
+
### Patch Changes
|
|
12
|
+
|
|
13
|
+
- afbe341: Publish to the public npm registry (`registry.npmjs.org`) instead of GitHub Package Registry. The package is now installable via `npm install -g @getbrevo/cli` without any registry configuration.
|
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Brevo
|
|
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
ADDED
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
# Brevo Developer CLI
|
|
2
|
+
|
|
3
|
+
Command-line tool to create, manage, and test [Brevo](https://www.brevo.com/) OAuth integrations from your terminal.
|
|
4
|
+
|
|
5
|
+
## Requirements
|
|
6
|
+
|
|
7
|
+
- **Node.js** 20.15.0 or newer (required to run the CLI)
|
|
8
|
+
- **Yarn** 1.19.1 or newer (only required for developing/building from source; not needed when installing via `npm install -g @getbrevo/cli`)
|
|
9
|
+
|
|
10
|
+
## Installation
|
|
11
|
+
|
|
12
|
+
Install globally from the public npm registry:
|
|
13
|
+
|
|
14
|
+
```bash
|
|
15
|
+
npm install -g @getbrevo/cli
|
|
16
|
+
# or:
|
|
17
|
+
yarn global add @getbrevo/cli
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
This puts the `brevo` binary on your PATH. Verify:
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
brevo --version
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
To upgrade later: `npm install -g @getbrevo/cli@latest`.
|
|
27
|
+
|
|
28
|
+
> Building from source? See [Development](#development) below.
|
|
29
|
+
|
|
30
|
+
## Quick start
|
|
31
|
+
|
|
32
|
+
The fastest path is `brevo app init`, which walks you through login, creating your first app, and generating starter code:
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
brevo app init
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
Or step by step:
|
|
39
|
+
|
|
40
|
+
1. **Authenticate.** `brevo login` defaults to a browser sign-in; you can also pick API-key auth from the prompt or pass `--browser` to skip it:
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
brevo login # interactive — choose browser (default) or API key
|
|
44
|
+
brevo login --browser # force the browser flow
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
For non-interactive use (CI), set `BREVO_API_KEY` ([create or copy a key](https://app.brevo.com/settings/keys/api)) before running `brevo login`:
|
|
48
|
+
|
|
49
|
+
```bash
|
|
50
|
+
export BREVO_API_KEY=xkeysib-...
|
|
51
|
+
brevo login
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
2. **Confirm** the active account:
|
|
55
|
+
|
|
56
|
+
```bash
|
|
57
|
+
brevo whoami
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
3. **Manage OAuth apps** (examples):
|
|
61
|
+
|
|
62
|
+
```bash
|
|
63
|
+
brevo app list
|
|
64
|
+
brevo app create --name "My App" --distribution private
|
|
65
|
+
brevo app scaffold --app-id 42
|
|
66
|
+
brevo app start oauth --port 3000
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
Run `brevo --help` or `brevo <command> --help` for full command and option lists. Every command supports `--json` for machine-readable output.
|
|
70
|
+
|
|
71
|
+
## Commands
|
|
72
|
+
|
|
73
|
+
| Command | Description |
|
|
74
|
+
| --- | --- |
|
|
75
|
+
| `brevo login` | Authenticate — browser sign-in by default, or `BREVO_API_KEY` for CI |
|
|
76
|
+
| `brevo logout` | Clear stored credentials (`--force` to skip confirmation) |
|
|
77
|
+
| `brevo whoami` | Show the authenticated user |
|
|
78
|
+
| `brevo app init` | Guided setup — login, create app, and scaffold in one go |
|
|
79
|
+
| `brevo app create` | Create an OAuth app (`--name`, `--distribution private\|public`, repeatable `--redirect-uri`) |
|
|
80
|
+
| `brevo app list` | List OAuth apps in your account |
|
|
81
|
+
| `brevo app credentials` | Show client ID and secret (`--app-id`, `--reveal-secret`) |
|
|
82
|
+
| `brevo app update` | Update app name or redirect URLs (`--app-id`, `--name`, repeatable `--redirect-url`, `--yes`) |
|
|
83
|
+
| `brevo app delete` | Delete an app (`--app-id`, `--force`) |
|
|
84
|
+
| `brevo app scaffold` | Generate starter code for an app (`--app-id`) |
|
|
85
|
+
| `brevo app start` | Run a scaffolded feature locally (e.g. `brevo app start oauth --port 3000`) |
|
|
86
|
+
|
|
87
|
+
Most commands require a successful `brevo login` first, except authentication/help flows (`brevo login`, `brevo logout`, `brevo app init`, `--help`). Every command accepts `--json` for machine-readable output.
|
|
88
|
+
|
|
89
|
+
### Browser login
|
|
90
|
+
|
|
91
|
+
`brevo login` defaults to a browser-based sign-in. The CLI starts a temporary loopback server, opens your browser to the Brevo CLI login service, and stores the returned tokens in `~/.brevo/credentials.json`. Access tokens refresh automatically on expiry.
|
|
92
|
+
|
|
93
|
+
Flags:
|
|
94
|
+
|
|
95
|
+
- `--browser` — force browser flow.
|
|
96
|
+
|
|
97
|
+
For non-interactive use (CI), set `BREVO_API_KEY=<key>` before running `brevo login`. The legacy `--api-key <key>` flag was removed because it leaks the secret into process listings and shell history; the env var is the only supported way to pass an API key non-interactively.
|
|
98
|
+
|
|
99
|
+
Environment overrides:
|
|
100
|
+
|
|
101
|
+
- `BREVO_API_URL` — points the CLI at a different Brevo API (defaults to `https://api.brevo.com`).
|
|
102
|
+
- `BREVO_OAUTH_PROXY_URL` — points the browser-login flow at a different OAuth proxy (defaults to `https://oauth-cli.brevo.com`; useful for staging or local Worker development).
|
|
103
|
+
|
|
104
|
+
## Exit codes
|
|
105
|
+
|
|
106
|
+
| Code | Meaning |
|
|
107
|
+
| --- | --- |
|
|
108
|
+
| `0` | Success |
|
|
109
|
+
| `1` | General error |
|
|
110
|
+
| `2` | Aborted (Ctrl+C or SIGTERM) |
|
|
111
|
+
| `3` | Authentication failure (401) |
|
|
112
|
+
| `4` | Network error (API unreachable) |
|
|
113
|
+
| `5` | Not found (404) |
|
|
114
|
+
|
|
115
|
+
## Configuration
|
|
116
|
+
|
|
117
|
+
| Variable | Purpose | Default |
|
|
118
|
+
| --- | --- | --- |
|
|
119
|
+
| `BREVO_API_KEY` | API key used for non-interactive `brevo login` | – |
|
|
120
|
+
| `BREVO_API_URL` | API base URL (HTTPS required, except for `localhost`) | `https://api.brevo.com` |
|
|
121
|
+
| `BREVO_OAUTH_PROXY_URL` | OAuth proxy used by browser login (HTTPS required, except for `localhost`) | `https://oauth-cli.brevo.com` |
|
|
122
|
+
| `BREVO_CONFIG_HOME` | Override for the credentials directory | `~/.brevo/` |
|
|
123
|
+
| `NO_COLOR` / `FORCE_COLOR` | Disable / force ANSI colour output | – |
|
|
124
|
+
| `DEBUG` or `--debug` | Verbose HTTP and error logging | off |
|
|
125
|
+
|
|
126
|
+
Credentials are stored at `~/.brevo/credentials.json`; per-app client secrets are cached under an `apps` key. Linked project config lives in `./.brevo.json` (gitignored).
|
|
127
|
+
|
|
128
|
+
## Development
|
|
129
|
+
|
|
130
|
+
```bash
|
|
131
|
+
git clone https://github.com/getbrevo/brevo-cli.git
|
|
132
|
+
cd brevo-cli
|
|
133
|
+
yarn install
|
|
134
|
+
yarn build # compile TypeScript + copy templates to dist/
|
|
135
|
+
yarn link:dev # build and yarn link the binary for local testing
|
|
136
|
+
yarn dev # watch mode (rebuilds on save)
|
|
137
|
+
yarn test # run jest
|
|
138
|
+
yarn test:ci # jest --coverage
|
|
139
|
+
yarn lint # ESLint on src/
|
|
140
|
+
yarn format # prettier --write
|
|
141
|
+
yarn clean # remove dist/
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
A husky pre-commit hook runs prettier and eslint on staged `.ts` files and then runs the full test suite.
|
|
145
|
+
|
|
146
|
+
### Using the mock API
|
|
147
|
+
|
|
148
|
+
A Prism-based mock server (spec in `mock/openapi.yaml`) is bundled for offline development:
|
|
149
|
+
|
|
150
|
+
```bash
|
|
151
|
+
yarn mock # starts on http://localhost:3112
|
|
152
|
+
BREVO_API_URL=http://localhost:3112 brevo app init
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
## Reporting issues
|
|
156
|
+
|
|
157
|
+
Found a bug or have a feature request? Please [open an issue](https://github.com/getbrevo/brevo-cli/issues/new/choose) on GitHub.
|
|
158
|
+
|
|
159
|
+
When filing a bug, please include:
|
|
160
|
+
|
|
161
|
+
- CLI version (`brevo --version`)
|
|
162
|
+
- Node.js version (`node --version`) and OS
|
|
163
|
+
- The command you ran and the full output (run with `--debug` for verbose logging if relevant)
|
|
164
|
+
- **Never paste real credentials** — redact API keys, client secrets, and access tokens before sharing
|
|
165
|
+
|
|
166
|
+
For security vulnerabilities, please **do not open a public issue**. Email the Brevo security team or use GitHub's [private vulnerability reporting](https://github.com/getbrevo/brevo-cli/security/advisories/new) instead.
|
|
167
|
+
|
|
168
|
+
## Contributing
|
|
169
|
+
|
|
170
|
+
Contributions are welcome. See [`AGENTS.md`](./AGENTS.md) and [`CLAUDE.md`](./CLAUDE.md) for the project structure, conventions, and what to check before opening a PR.
|
|
171
|
+
|
|
172
|
+
## Resources
|
|
173
|
+
|
|
174
|
+
- [Brevo Developers](https://developers.brevo.com)
|
|
175
|
+
- [Package on npm](https://www.npmjs.com/package/@getbrevo/cli)
|
|
176
|
+
- [Repository](https://github.com/getbrevo/brevo-cli)
|
|
177
|
+
- [Issue tracker](https://github.com/getbrevo/brevo-cli/issues)
|
|
178
|
+
- [Changelog](./CHANGELOG.md)
|
|
179
|
+
|
|
180
|
+
## License
|
|
181
|
+
|
|
182
|
+
[MIT](./LICENSE)
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
type AuthFailureHandler = () => Promise<void>;
|
|
2
|
+
export interface ApiClientDeps {
|
|
3
|
+
baseUrl: string;
|
|
4
|
+
getAuthHeader: () => Record<string, string> | undefined;
|
|
5
|
+
}
|
|
6
|
+
export declare function parseRetryAfter(header: string | null): number;
|
|
7
|
+
export declare function sanitizeErrorMessage(msg: string): string;
|
|
8
|
+
export declare class ApiClient {
|
|
9
|
+
private deps;
|
|
10
|
+
private onAuthFailure?;
|
|
11
|
+
constructor(deps: ApiClientDeps);
|
|
12
|
+
setOnAuthFailure(handler: AuthFailureHandler): void;
|
|
13
|
+
get<T>(path: string): Promise<T>;
|
|
14
|
+
post<T>(path: string, body?: unknown): Promise<T>;
|
|
15
|
+
patch<T>(path: string, body?: unknown): Promise<T>;
|
|
16
|
+
put<T>(path: string, body?: unknown): Promise<T>;
|
|
17
|
+
delete<T>(path: string): Promise<T>;
|
|
18
|
+
getWithKey<T>(path: string, apiKey: string): Promise<T>;
|
|
19
|
+
getWithBearer<T>(path: string, accessToken: string, tokenType?: string): Promise<T>;
|
|
20
|
+
private request;
|
|
21
|
+
}
|
|
22
|
+
export {};
|
|
23
|
+
//# sourceMappingURL=client.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/api/client.ts"],"names":[],"mappings":"AAaA,KAAK,kBAAkB,GAAG,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;AAE9C,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,MAAM,CAAC;IAChB,aAAa,EAAE,MAAM,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,SAAS,CAAC;CACzD;AAqBD,wBAAgB,eAAe,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,GAAG,MAAM,CAK7D;AAKD,wBAAgB,oBAAoB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAcxD;AAoBD,qBAAa,SAAS;IAGR,OAAO,CAAC,IAAI;IAFxB,OAAO,CAAC,aAAa,CAAC,CAAqB;gBAEvB,IAAI,EAAE,aAAa;IAEvC,gBAAgB,CAAC,OAAO,EAAE,kBAAkB,GAAG,IAAI;IAInD,GAAG,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC,CAAC;IAIhC,IAAI,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,CAAC,CAAC;IAIjD,KAAK,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,CAAC,CAAC;IAIlD,GAAG,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,CAAC,CAAC;IAIhD,MAAM,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC,CAAC;IAInC,UAAU,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC,CAAC;IASvD,aAAa,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,SAAS,SAAW,GAAG,OAAO,CAAC,CAAC,CAAC;YASvE,OAAO;CA0FtB"}
|
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ApiClient = void 0;
|
|
4
|
+
exports.parseRetryAfter = parseRetryAfter;
|
|
5
|
+
exports.sanitizeErrorMessage = sanitizeErrorMessage;
|
|
6
|
+
const errors_1 = require("../lib/errors");
|
|
7
|
+
const logger_1 = require("../lib/logger");
|
|
8
|
+
const en_1 = require("../lang/en");
|
|
9
|
+
const MAX_RETRIES = 3;
|
|
10
|
+
const DEFAULT_RETRY_AFTER_SECONDS = 5;
|
|
11
|
+
const MAX_RETRY_AFTER_SECONDS = 300;
|
|
12
|
+
const apiCodeMessages = {
|
|
13
|
+
APP_LIMIT_REACHED: en_1.messages.APP_CREATE_LIMIT_REACHED,
|
|
14
|
+
REGISTRY_ERROR: en_1.messages.ERR_REGISTRY,
|
|
15
|
+
};
|
|
16
|
+
function resolveErrorMessage(apiCode, fallback) {
|
|
17
|
+
if (apiCode && apiCode in apiCodeMessages) {
|
|
18
|
+
return apiCodeMessages[apiCode];
|
|
19
|
+
}
|
|
20
|
+
return fallback;
|
|
21
|
+
}
|
|
22
|
+
// Server-provided `retry-after` is untrusted input. Cap it to avoid indefinite
|
|
23
|
+
// waits from a malicious or misconfigured server, and reject NaN/negatives
|
|
24
|
+
// which would otherwise turn into a 0ms tight retry loop.
|
|
25
|
+
function parseRetryAfter(header) {
|
|
26
|
+
if (!header)
|
|
27
|
+
return DEFAULT_RETRY_AFTER_SECONDS;
|
|
28
|
+
const parsed = Number.parseInt(header, 10);
|
|
29
|
+
if (!Number.isFinite(parsed) || parsed <= 0)
|
|
30
|
+
return DEFAULT_RETRY_AFTER_SECONDS;
|
|
31
|
+
return Math.min(parsed, MAX_RETRY_AFTER_SECONDS);
|
|
32
|
+
}
|
|
33
|
+
// Sanitize untrusted server-provided error strings before they reach the terminal:
|
|
34
|
+
// strip ANSI escape sequences and non-printable control characters that could
|
|
35
|
+
// reposition the cursor, clear the screen, or inject fake prompts.
|
|
36
|
+
function sanitizeErrorMessage(msg) {
|
|
37
|
+
return (msg
|
|
38
|
+
// ANSI CSI/OSC escape sequences
|
|
39
|
+
// eslint-disable-next-line no-control-regex
|
|
40
|
+
.replace(/\x1B\[[0-?]*[ -/]*[@-~]/g, '')
|
|
41
|
+
// eslint-disable-next-line no-control-regex
|
|
42
|
+
.replace(/\x1B\][^\x07]*(?:\x07|\x1B\\)/g, '')
|
|
43
|
+
// C0 + DEL + C1 control chars, keeping \t \n \r.
|
|
44
|
+
// Includes 0x80–0x9F so 8-bit CSI (0x9B) / OSC (0x9D) introducers
|
|
45
|
+
// are stripped alongside their 7-bit ESC-prefixed equivalents.
|
|
46
|
+
// eslint-disable-next-line no-control-regex
|
|
47
|
+
.replace(/[\x00-\x08\x0B\x0C\x0E-\x1F\x7F-\x9F]/g, ''));
|
|
48
|
+
}
|
|
49
|
+
function mapErrorCode(status, apiCode) {
|
|
50
|
+
if (apiCode === 'APP_LIMIT_REACHED')
|
|
51
|
+
return errors_1.ErrorCode.APP_LIMIT_REACHED;
|
|
52
|
+
if (apiCode === 'REGISTRY_ERROR')
|
|
53
|
+
return errors_1.ErrorCode.REGISTRY_ERROR;
|
|
54
|
+
switch (status) {
|
|
55
|
+
case 401:
|
|
56
|
+
return errors_1.ErrorCode.AUTH_INVALID;
|
|
57
|
+
case 403:
|
|
58
|
+
return errors_1.ErrorCode.ACCESS_DENIED;
|
|
59
|
+
case 404:
|
|
60
|
+
return errors_1.ErrorCode.APP_NOT_FOUND;
|
|
61
|
+
case 429:
|
|
62
|
+
return errors_1.ErrorCode.RATE_LIMITED;
|
|
63
|
+
default:
|
|
64
|
+
return undefined;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
class ApiClient {
|
|
68
|
+
deps;
|
|
69
|
+
onAuthFailure;
|
|
70
|
+
constructor(deps) {
|
|
71
|
+
this.deps = deps;
|
|
72
|
+
}
|
|
73
|
+
setOnAuthFailure(handler) {
|
|
74
|
+
this.onAuthFailure = handler;
|
|
75
|
+
}
|
|
76
|
+
get(path) {
|
|
77
|
+
return this.request({ method: 'GET', path });
|
|
78
|
+
}
|
|
79
|
+
post(path, body) {
|
|
80
|
+
return this.request({ method: 'POST', path, body });
|
|
81
|
+
}
|
|
82
|
+
patch(path, body) {
|
|
83
|
+
return this.request({ method: 'PATCH', path, body });
|
|
84
|
+
}
|
|
85
|
+
put(path, body) {
|
|
86
|
+
return this.request({ method: 'PUT', path, body });
|
|
87
|
+
}
|
|
88
|
+
delete(path) {
|
|
89
|
+
return this.request({ method: 'DELETE', path });
|
|
90
|
+
}
|
|
91
|
+
getWithKey(path, apiKey) {
|
|
92
|
+
return this.request({
|
|
93
|
+
method: 'GET',
|
|
94
|
+
path,
|
|
95
|
+
skipAuth: true,
|
|
96
|
+
authHeader: { 'api-key': apiKey },
|
|
97
|
+
});
|
|
98
|
+
}
|
|
99
|
+
getWithBearer(path, accessToken, tokenType = 'Bearer') {
|
|
100
|
+
return this.request({
|
|
101
|
+
method: 'GET',
|
|
102
|
+
path,
|
|
103
|
+
skipAuth: true,
|
|
104
|
+
authHeader: { Authorization: `${tokenType} ${accessToken}` },
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
async request(opts, isRetry = false, retryCount = 0) {
|
|
108
|
+
const url = `${this.deps.baseUrl}${opts.path}`;
|
|
109
|
+
const explicitAuth = opts.authHeader;
|
|
110
|
+
const authHeader = explicitAuth ?? (opts.skipAuth ? undefined : this.deps.getAuthHeader());
|
|
111
|
+
const headers = {
|
|
112
|
+
'Content-Type': 'application/json',
|
|
113
|
+
Accept: 'application/json',
|
|
114
|
+
...opts.headers,
|
|
115
|
+
...(authHeader ?? {}),
|
|
116
|
+
};
|
|
117
|
+
(0, logger_1.logHttp)(opts.method, opts.path);
|
|
118
|
+
let response;
|
|
119
|
+
try {
|
|
120
|
+
response = await fetch(url, {
|
|
121
|
+
method: opts.method,
|
|
122
|
+
headers,
|
|
123
|
+
body: opts.body ? JSON.stringify(opts.body) : undefined,
|
|
124
|
+
signal: AbortSignal.timeout(30_000),
|
|
125
|
+
});
|
|
126
|
+
}
|
|
127
|
+
catch (err) {
|
|
128
|
+
throw new errors_1.ApiError(en_1.messages.ERR_NETWORK, 0, errors_1.ErrorCode.NETWORK_ERROR);
|
|
129
|
+
}
|
|
130
|
+
(0, logger_1.logHttpResponse)(response.status, opts.path);
|
|
131
|
+
if (response.status === 401 && !isRetry && !opts.skipAuth) {
|
|
132
|
+
if (this.onAuthFailure) {
|
|
133
|
+
await this.onAuthFailure();
|
|
134
|
+
return this.request(opts, true, retryCount);
|
|
135
|
+
}
|
|
136
|
+
throw new errors_1.ApiError(en_1.messages.AUTH_EXPIRED, 401, errors_1.ErrorCode.AUTH_EXPIRED);
|
|
137
|
+
}
|
|
138
|
+
if (response.status === 429) {
|
|
139
|
+
if (retryCount >= MAX_RETRIES) {
|
|
140
|
+
throw new errors_1.ApiError('Rate limited — max retries exceeded.', 429, errors_1.ErrorCode.RATE_LIMITED);
|
|
141
|
+
}
|
|
142
|
+
const retryAfter = parseRetryAfter(response.headers.get('retry-after'));
|
|
143
|
+
process.stderr.write(` ${en_1.messages.ERR_RATE_LIMITED(retryAfter)}\n`);
|
|
144
|
+
await new Promise((r) => setTimeout(r, retryAfter * 1000));
|
|
145
|
+
return this.request(opts, isRetry, retryCount + 1);
|
|
146
|
+
}
|
|
147
|
+
if (response.status === 502 && retryCount < 1) {
|
|
148
|
+
await new Promise((r) => setTimeout(r, 2000));
|
|
149
|
+
return this.request(opts, isRetry, retryCount + 1);
|
|
150
|
+
}
|
|
151
|
+
const text = await response.text();
|
|
152
|
+
// Detect HTML bodies returned by auth gateways (Cloudflare Access, SSO proxies).
|
|
153
|
+
// Matches case-insensitively and runs regardless of response status, since
|
|
154
|
+
// gateways frequently return HTML on 401/403 as well as 2xx.
|
|
155
|
+
const looksLikeHtml = (s) => {
|
|
156
|
+
const lower = s.toLowerCase();
|
|
157
|
+
return lower.includes('<!doctype html') || lower.includes('<html');
|
|
158
|
+
};
|
|
159
|
+
let data;
|
|
160
|
+
try {
|
|
161
|
+
data = text ? JSON.parse(text) : {};
|
|
162
|
+
}
|
|
163
|
+
catch {
|
|
164
|
+
if (looksLikeHtml(text)) {
|
|
165
|
+
throw new errors_1.ApiError(en_1.messages.ERR_AUTH_GATEWAY, response.status, errors_1.ErrorCode.AUTH_GATEWAY);
|
|
166
|
+
}
|
|
167
|
+
data = { message: text };
|
|
168
|
+
}
|
|
169
|
+
if (typeof data?.message === 'string' && looksLikeHtml(data.message)) {
|
|
170
|
+
throw new errors_1.ApiError(en_1.messages.ERR_AUTH_GATEWAY, response.status, errors_1.ErrorCode.AUTH_GATEWAY);
|
|
171
|
+
}
|
|
172
|
+
(0, logger_1.logDebug)(`response ${opts.path}`, data);
|
|
173
|
+
if (!response.ok) {
|
|
174
|
+
const apiCode = data?.code;
|
|
175
|
+
const rawFallback = typeof data?.message === 'string' && data.message
|
|
176
|
+
? data.message
|
|
177
|
+
: `Request failed with status ${response.status}`;
|
|
178
|
+
const fallback = sanitizeErrorMessage(rawFallback);
|
|
179
|
+
const message = resolveErrorMessage(apiCode, fallback);
|
|
180
|
+
throw new errors_1.ApiError(message, response.status, mapErrorCode(response.status, apiCode), apiCode);
|
|
181
|
+
}
|
|
182
|
+
return data;
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
exports.ApiClient = ApiClient;
|
|
186
|
+
//# sourceMappingURL=client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.js","sourceRoot":"","sources":["../../src/api/client.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/bin/index.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
"use strict";
|
|
3
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
4
|
+
if (k2 === undefined) k2 = k;
|
|
5
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
6
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
7
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
8
|
+
}
|
|
9
|
+
Object.defineProperty(o, k2, desc);
|
|
10
|
+
}) : (function(o, m, k, k2) {
|
|
11
|
+
if (k2 === undefined) k2 = k;
|
|
12
|
+
o[k2] = m[k];
|
|
13
|
+
}));
|
|
14
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
15
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
16
|
+
}) : function(o, v) {
|
|
17
|
+
o["default"] = v;
|
|
18
|
+
});
|
|
19
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
20
|
+
var ownKeys = function(o) {
|
|
21
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
22
|
+
var ar = [];
|
|
23
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
24
|
+
return ar;
|
|
25
|
+
};
|
|
26
|
+
return ownKeys(o);
|
|
27
|
+
};
|
|
28
|
+
return function (mod) {
|
|
29
|
+
if (mod && mod.__esModule) return mod;
|
|
30
|
+
var result = {};
|
|
31
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
32
|
+
__setModuleDefault(result, mod);
|
|
33
|
+
return result;
|
|
34
|
+
};
|
|
35
|
+
})();
|
|
36
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
37
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
38
|
+
};
|
|
39
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
40
|
+
const fs = __importStar(require("fs"));
|
|
41
|
+
const path = __importStar(require("path"));
|
|
42
|
+
const commander_1 = require("commander");
|
|
43
|
+
const auth_guard_1 = require("../lib/auth-guard");
|
|
44
|
+
const logger_1 = require("../lib/logger");
|
|
45
|
+
const exit_codes_1 = require("../lib/exit-codes");
|
|
46
|
+
const errors_1 = require("../lib/errors");
|
|
47
|
+
const en_1 = require("../lang/en");
|
|
48
|
+
const hidden_input_1 = require("../lib/hidden-input");
|
|
49
|
+
const config_1 = require("../lib/config");
|
|
50
|
+
const constants_1 = require("../lib/constants");
|
|
51
|
+
const oauth_refresh_1 = require("../services/oauth-refresh");
|
|
52
|
+
const errors_2 = require("../lib/errors");
|
|
53
|
+
const ui_1 = require("../lib/ui");
|
|
54
|
+
const container_1 = require("../container");
|
|
55
|
+
const command_registry_1 = require("../lib/command-registry");
|
|
56
|
+
const definitions_1 = require("../commands/definitions");
|
|
57
|
+
const simple_update_notifier_1 = __importDefault(require("simple-update-notifier"));
|
|
58
|
+
const pkg = JSON.parse(fs.readFileSync(path.resolve(__dirname, '../../package.json'), 'utf-8'));
|
|
59
|
+
const version = pkg.version;
|
|
60
|
+
// Version update check — fire-and-forget, swallows network errors so the CLI
|
|
61
|
+
// never blocks or fails because the npm registry is unreachable.
|
|
62
|
+
void (0, simple_update_notifier_1.default)({ pkg: { name: pkg.name, version: pkg.version } }).catch(() => { });
|
|
63
|
+
if (process.env.NODE_TLS_REJECT_UNAUTHORIZED === '0') {
|
|
64
|
+
(0, logger_1.logWarn)(en_1.messages.TLS_VERIFICATION_DISABLED);
|
|
65
|
+
}
|
|
66
|
+
const program = new commander_1.Command();
|
|
67
|
+
program
|
|
68
|
+
.name('brevo')
|
|
69
|
+
.description('Brevo Developer CLI — create, manage, and test OAuth integrations')
|
|
70
|
+
.version(version)
|
|
71
|
+
.option('--debug', 'Enable debug logging')
|
|
72
|
+
.configureHelp({
|
|
73
|
+
formatHelp: (_cmd, helper) => {
|
|
74
|
+
const version = helper.commandDescription(_cmd);
|
|
75
|
+
return [
|
|
76
|
+
`Usage: brevo [options] [command]`,
|
|
77
|
+
``,
|
|
78
|
+
version,
|
|
79
|
+
``,
|
|
80
|
+
`Options:`,
|
|
81
|
+
` -V, --version output the version number`,
|
|
82
|
+
` -h, --help display help for command`,
|
|
83
|
+
``,
|
|
84
|
+
`Commands:`,
|
|
85
|
+
` login [--browser] [--json] Authenticate with your Brevo account`,
|
|
86
|
+
` logout [--json] Clear stored credentials`,
|
|
87
|
+
` whoami [--json] Show current authenticated user`,
|
|
88
|
+
` app init Quick setup — login, create app, and scaffold`,
|
|
89
|
+
` app create [--name] [--distribution private|public] [--json]`,
|
|
90
|
+
` app list [--json]`,
|
|
91
|
+
` app credentials [--app-id <id>] [--reveal-secret] [--json]`,
|
|
92
|
+
` app update [--json]`,
|
|
93
|
+
` app delete [--app-id <id>] [--force] [--json]`,
|
|
94
|
+
` app scaffold [--app-id <id>] [--json]`,
|
|
95
|
+
` app start [feature] [--port <port>]`,
|
|
96
|
+
``,
|
|
97
|
+
`Run \`brevo <command> --help\` for details on a specific command.`,
|
|
98
|
+
``,
|
|
99
|
+
`Examples:`,
|
|
100
|
+
` $ brevo login # authenticate interactively`,
|
|
101
|
+
` $ brevo app init # guided setup`,
|
|
102
|
+
` $ brevo app create --name "My App" --json # create app, JSON output`,
|
|
103
|
+
` $ brevo app list --json # list apps as JSON`,
|
|
104
|
+
` $ brevo app scaffold --app-id APPID # generate starter code`,
|
|
105
|
+
` $ brevo app start oauth --port 3000 # start OAuth test server`,
|
|
106
|
+
``,
|
|
107
|
+
].join('\n');
|
|
108
|
+
},
|
|
109
|
+
})
|
|
110
|
+
.action(() => program.help());
|
|
111
|
+
// Auth guard — blocks unauthenticated access (except login, logout, help)
|
|
112
|
+
(0, auth_guard_1.installAuthGuard)(program);
|
|
113
|
+
// ──────────────── Register all commands ────────────────
|
|
114
|
+
(0, command_registry_1.registerAll)(program, definitions_1.topLevelCommands, [definitions_1.appCommandGroup]);
|
|
115
|
+
// ──────────────── Re-auth handler ────────────────
|
|
116
|
+
container_1.client.setOnAuthFailure(async () => {
|
|
117
|
+
const auth = (0, config_1.getAuthCred)();
|
|
118
|
+
// OAuth: silently refresh the access token and let the original request retry.
|
|
119
|
+
// If the refresh itself returns 401, the refresh token is dead — clear creds
|
|
120
|
+
// and surface a friendly "please log in again" message instead of falling
|
|
121
|
+
// through to the api-key prompt.
|
|
122
|
+
if (auth?.kind === 'oauth') {
|
|
123
|
+
try {
|
|
124
|
+
const refreshed = await (0, oauth_refresh_1.refreshAccessToken)(auth.refreshToken, constants_1.OAUTH_PROXY_URL);
|
|
125
|
+
(0, config_1.updateOauthTokens)(refreshed);
|
|
126
|
+
return;
|
|
127
|
+
}
|
|
128
|
+
catch (err) {
|
|
129
|
+
if (err instanceof oauth_refresh_1.RefreshError && err.unauthorized) {
|
|
130
|
+
(0, config_1.clearCredentials)();
|
|
131
|
+
throw new errors_2.AuthExpiredError();
|
|
132
|
+
}
|
|
133
|
+
throw err;
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
// API-key: prompt for a new key and re-validate.
|
|
137
|
+
(0, ui_1.stopActiveSpinner)();
|
|
138
|
+
(0, config_1.clearCredentials)();
|
|
139
|
+
(0, logger_1.logWarn)(en_1.messages.AUTH_EXPIRED);
|
|
140
|
+
(0, logger_1.logInfo)(` ${en_1.messages.AUTH_GET_KEY_URL}\n`);
|
|
141
|
+
const newKey = await (0, hidden_input_1.readHiddenInput)(en_1.messages.AUTH_EXPIRED_PROMPT + ' ');
|
|
142
|
+
const account = await container_1.client.getWithKey(constants_1.ENDPOINTS.ACCOUNT, newKey);
|
|
143
|
+
(0, config_1.saveCredentials)(newKey, {
|
|
144
|
+
email: account.email,
|
|
145
|
+
organizationId: account.organization_id,
|
|
146
|
+
userId: account.user_id,
|
|
147
|
+
});
|
|
148
|
+
(0, logger_1.logSuccess)(en_1.messages.AUTH_SUCCESS(account.email));
|
|
149
|
+
});
|
|
150
|
+
// ──────────────── Signal handling ────────────────
|
|
151
|
+
for (const signal of ['SIGINT', 'SIGTERM']) {
|
|
152
|
+
process.on(signal, () => {
|
|
153
|
+
(0, logger_1.logInfo)(`\n Received ${signal}, shutting down.\n`);
|
|
154
|
+
process.exit(exit_codes_1.EXIT_CODES.ABORTED);
|
|
155
|
+
});
|
|
156
|
+
}
|
|
157
|
+
// ──────────────── Error handling ────────────────
|
|
158
|
+
// Emit deferred warning if BREVO_API_URL had a path stripped
|
|
159
|
+
(0, constants_1.warnIfPathStripped)();
|
|
160
|
+
program
|
|
161
|
+
.parseAsync(process.argv)
|
|
162
|
+
.then(() => {
|
|
163
|
+
// Force exit — Node's native fetch keeps TCP connections alive which can
|
|
164
|
+
// prevent the process from exiting when running against local servers.
|
|
165
|
+
process.exit(0);
|
|
166
|
+
})
|
|
167
|
+
.catch((err) => {
|
|
168
|
+
if (err instanceof errors_1.AbortError) {
|
|
169
|
+
(0, logger_1.logInfo)(`\n ${en_1.messages.ABORTED}`);
|
|
170
|
+
process.exit(exit_codes_1.EXIT_CODES.ABORTED);
|
|
171
|
+
}
|
|
172
|
+
if (err instanceof errors_1.CliError) {
|
|
173
|
+
(0, logger_1.logError)(err.message);
|
|
174
|
+
process.exit(err.exitCode);
|
|
175
|
+
}
|
|
176
|
+
(0, logger_1.logError)(err.message, err);
|
|
177
|
+
process.exit(exit_codes_1.EXIT_CODES.ERROR);
|
|
178
|
+
});
|
|
179
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/bin/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAEA,uCAAyB;AACzB,2CAA6B;AAC7B,yCAAoC;AACpC,kDAAqD;AACrD,0CAAuE;AACvE,kDAA+C;AAC/C,0CAAqD;AACrD,mCAAsC;AACtC,sDAAsD;AACtD,0CAAkG;AAClG,gDAAkF;AAClF,6DAA6E;AAC7E,0CAAiD;AACjD,kCAA8C;AAE9C,4CAAsC;AACtC,8DAAsD;AACtD,yDAA4E;AAC5E,oFAA0D;AAE1D,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,YAAY,CAAC,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,oBAAoB,CAAC,EAAE,OAAO,CAAC,CAAC,CAAC;AAChG,MAAM,OAAO,GAAW,GAAG,CAAC,OAAO,CAAC;AAEpC,6EAA6E;AAC7E,iEAAiE;AACjE,KAAK,IAAA,gCAAoB,EAAC,EAAE,GAAG,EAAE,EAAE,IAAI,EAAE,GAAG,CAAC,IAAI,EAAE,OAAO,EAAE,GAAG,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;AAE7F,IAAI,OAAO,CAAC,GAAG,CAAC,4BAA4B,KAAK,GAAG,EAAE,CAAC;IACrD,IAAA,gBAAO,EAAC,aAAQ,CAAC,yBAAyB,CAAC,CAAC;AAC9C,CAAC;AAED,MAAM,OAAO,GAAG,IAAI,mBAAO,EAAE,CAAC;AAE9B,OAAO;KACJ,IAAI,CAAC,OAAO,CAAC;KACb,WAAW,CAAC,mEAAmE,CAAC;KAChF,OAAO,CAAC,OAAO,CAAC;KAChB,MAAM,CAAC,SAAS,EAAE,sBAAsB,CAAC;KACzC,aAAa,CAAC;IACb,UAAU,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE;QAC3B,MAAM,OAAO,GAAG,MAAM,CAAC,kBAAkB,CAAC,IAAI,CAAC,CAAC;QAChD,OAAO;YACL,kCAAkC;YAClC,EAAE;YACF,OAAO;YACP,EAAE;YACF,UAAU;YACV,8CAA8C;YAC9C,6CAA6C;YAC7C,EAAE;YACF,WAAW;YACX,iFAAiF;YACjF,oEAAoE;YACpE,2EAA2E;YAC3E,yFAAyF;YACzF,qEAAqE;YACrE,4BAA4B;YAC5B,8DAA8D;YAC9D,4BAA4B;YAC5B,sDAAsD;YACtD,4CAA4C;YAC5C,6CAA6C;YAC7C,EAAE;YACF,mEAAmE;YACnE,EAAE;YACF,WAAW;YACX,gFAAgF;YAChF,kEAAkE;YAClE,6EAA6E;YAC7E,uEAAuE;YACvE,2EAA2E;YAC3E,6EAA6E;YAC7E,EAAE;SACH,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACf,CAAC;CACF,CAAC;KACD,MAAM,CAAC,GAAG,EAAE,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC;AAEhC,0EAA0E;AAC1E,IAAA,6BAAgB,EAAC,OAAO,CAAC,CAAC;AAE1B,0DAA0D;AAE1D,IAAA,8BAAW,EAAC,OAAO,EAAE,8BAAgB,EAAE,CAAC,6BAAe,CAAC,CAAC,CAAC;AAE1D,oDAAoD;AAEpD,kBAAM,CAAC,gBAAgB,CAAC,KAAK,IAAI,EAAE;IACjC,MAAM,IAAI,GAAG,IAAA,oBAAW,GAAE,CAAC;IAE3B,+EAA+E;IAC/E,6EAA6E;IAC7E,0EAA0E;IAC1E,iCAAiC;IACjC,IAAI,IAAI,EAAE,IAAI,KAAK,OAAO,EAAE,CAAC;QAC3B,IAAI,CAAC;YACH,MAAM,SAAS,GAAG,MAAM,IAAA,kCAAkB,EAAC,IAAI,CAAC,YAAY,EAAE,2BAAe,CAAC,CAAC;YAC/E,IAAA,0BAAiB,EAAC,SAAS,CAAC,CAAC;YAC7B,OAAO;QACT,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,IAAI,GAAG,YAAY,4BAAY,IAAI,GAAG,CAAC,YAAY,EAAE,CAAC;gBACpD,IAAA,yBAAgB,GAAE,CAAC;gBACnB,MAAM,IAAI,yBAAgB,EAAE,CAAC;YAC/B,CAAC;YACD,MAAM,GAAG,CAAC;QACZ,CAAC;IACH,CAAC;IAED,iDAAiD;IACjD,IAAA,sBAAiB,GAAE,CAAC;IACpB,IAAA,yBAAgB,GAAE,CAAC;IACnB,IAAA,gBAAO,EAAC,aAAQ,CAAC,YAAY,CAAC,CAAC;IAC/B,IAAA,gBAAO,EAAC,KAAK,aAAQ,CAAC,gBAAgB,IAAI,CAAC,CAAC;IAC5C,MAAM,MAAM,GAAG,MAAM,IAAA,8BAAe,EAAC,aAAQ,CAAC,mBAAmB,GAAG,GAAG,CAAC,CAAC;IACzE,MAAM,OAAO,GAAG,MAAM,kBAAM,CAAC,UAAU,CAAkB,qBAAS,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;IACpF,IAAA,wBAAe,EAAC,MAAM,EAAE;QACtB,KAAK,EAAE,OAAO,CAAC,KAAK;QACpB,cAAc,EAAE,OAAO,CAAC,eAAe;QACvC,MAAM,EAAE,OAAO,CAAC,OAAO;KACxB,CAAC,CAAC;IACH,IAAA,mBAAU,EAAC,aAAQ,CAAC,YAAY,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC;AACnD,CAAC,CAAC,CAAC;AAEH,oDAAoD;AAEpD,KAAK,MAAM,MAAM,IAAI,CAAC,QAAQ,EAAE,SAAS,CAAU,EAAE,CAAC;IACpD,OAAO,CAAC,EAAE,CAAC,MAAM,EAAE,GAAG,EAAE;QACtB,IAAA,gBAAO,EAAC,gBAAgB,MAAM,oBAAoB,CAAC,CAAC;QACpD,OAAO,CAAC,IAAI,CAAC,uBAAU,CAAC,OAAO,CAAC,CAAC;IACnC,CAAC,CAAC,CAAC;AACL,CAAC;AAED,mDAAmD;AAEnD,6DAA6D;AAC7D,IAAA,8BAAkB,GAAE,CAAC;AAErB,OAAO;KACJ,UAAU,CAAC,OAAO,CAAC,IAAI,CAAC;KACxB,IAAI,CAAC,GAAG,EAAE;IACT,yEAAyE;IACzE,uEAAuE;IACvE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC;KACD,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE;IACb,IAAI,GAAG,YAAY,mBAAU,EAAE,CAAC;QAC9B,IAAA,gBAAO,EAAC,OAAO,aAAQ,CAAC,OAAO,EAAE,CAAC,CAAC;QACnC,OAAO,CAAC,IAAI,CAAC,uBAAU,CAAC,OAAO,CAAC,CAAC;IACnC,CAAC;IACD,IAAI,GAAG,YAAY,iBAAQ,EAAE,CAAC;QAC5B,IAAA,iBAAQ,EAAC,GAAG,CAAC,OAAO,CAAC,CAAC;QACtB,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;IAC7B,CAAC;IACD,IAAA,iBAAQ,EAAC,GAAG,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC;IAC3B,OAAO,CAAC,IAAI,CAAC,uBAAU,CAAC,KAAK,CAAC,CAAC;AACjC,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"create.d.ts","sourceRoot":"","sources":["../../../src/commands/app/create.ts"],"names":[],"mappings":"AAeA,eAAO,MAAM,aAAa;WAEf,MAAM;mBACE,MAAM;kBACP,MAAM,EAAE;WACf,OAAO;mBA0PjB,CAAC"}
|