@sap/cli-core 2023.14.0 → 2023.18.0
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 +179 -2
- package/README.md +1 -1
- package/cache/secrets/SecretsStorageImpl.d.ts +22 -0
- package/cache/secrets/SecretsStorageImpl.js +147 -0
- package/cache/secrets/SecretsStorageSingleton.d.ts +4 -0
- package/cache/secrets/SecretsStorageSingleton.js +7 -0
- package/cache/secrets/types.d.ts +11 -0
- package/cache/secrets/types.js +2 -0
- package/cache/secrets/utils.d.ts +2 -0
- package/cache/secrets/utils.js +18 -0
- package/commands/{cache.command → config.command/cache.command}/clean.command.d.ts +1 -1
- package/commands/{cache.command → config.command/cache.command}/clean.command.js +3 -3
- package/commands/{cache.command → config.command/cache.command}/index.d.ts +1 -1
- package/commands/config.command/cache.command/init.command.d.ts +4 -0
- package/commands/{cache.command → config.command/cache.command}/init.command.js +15 -8
- package/commands/{cache.command → config.command/cache.command}/show.command.d.ts +1 -1
- package/commands/{cache.command → config.command/cache.command}/show.command.js +4 -4
- package/commands/{host.command.d.ts → config.command/host.command.d.ts} +1 -1
- package/commands/{host.command.js → config.command/host.command.js} +12 -12
- package/commands/config.command/index.d.ts +2 -0
- package/commands/config.command/index.js +19 -0
- package/commands/{passcode.command.d.ts → config.command/passcode.command.d.ts} +1 -1
- package/commands/{passcode.command.js → config.command/passcode.command.js} +8 -8
- package/commands/{secrets.command → config.command/secrets.command}/index.d.ts +1 -1
- package/commands/{secrets.command → config.command/secrets.command}/index.js +2 -1
- package/commands/config.command/secrets.command/reset.command.d.ts +3 -0
- package/commands/config.command/secrets.command/reset.command.js +17 -0
- package/commands/{secrets.command → config.command/secrets.command}/show.command.d.ts +1 -1
- package/commands/{secrets.command → config.command/secrets.command}/show.command.js +14 -7
- package/commands/handler/authentication/oauth/secretsProvider/cache.js +4 -5
- package/commands/handler/authentication/oauth/secretsProvider/file.js +3 -3
- package/commands/handler/authentication/oauth/secretsProvider/options.js +12 -6
- package/commands/handler/authentication/oauth/tokenProvider/getToken.js +5 -61
- package/commands/handler/authentication/oauth/tokenProvider/refreshToken.js +1 -1
- package/commands/handler/authentication/oauth/tokenProvider/setAuthorization.js +4 -4
- package/commands/handler/authentication/oauth/tokenProvider/utils.d.ts +2 -0
- package/commands/handler/authentication/oauth/tokenProvider/utils.js +77 -4
- package/commands/handler/authentication/oauth/utils.d.ts +0 -4
- package/commands/handler/authentication/oauth/utils.js +13 -27
- package/commands/handler/authentication/passcode/function.js +1 -1
- package/commands/handler/authentication/passcode/input.js +2 -2
- package/commands/handler/authentication/passcode/setPasscode.js +1 -1
- package/commands/handler/authentication/technicalJWT/index.js +2 -2
- package/commands/handler/checkOptionsExistence.js +1 -1
- package/commands/handler/error.js +2 -2
- package/commands/handler/fail.js +1 -1
- package/commands/handler/fetch/fetch.js +1 -1
- package/commands/handler/fetch/utils.js +1 -1
- package/commands/handler/input/file.js +1 -1
- package/commands/handler/input/input.js +2 -2
- package/commands/handler/mandatoryOptions.js +1 -1
- package/commands/handler/next.js +3 -2
- package/commands/handler/options/env.js +1 -2
- package/commands/handler/options/file.js +1 -1
- package/commands/handler/options/index.js +5 -4
- package/commands/handler/options/option.js +1 -1
- package/commands/handler/options/pipe.js +1 -1
- package/commands/handler/options/utils.d.ts +1 -1
- package/commands/handler/options/utils.js +11 -4
- package/commands/handler/or.js +3 -2
- package/commands/handler/parseArguments.js +1 -1
- package/commands/handler/resilient.js +2 -2
- package/commands/handler/root/index.js +2 -2
- package/commands/handler/stackTrace.js +2 -2
- package/commands/handler/succeed.js +1 -1
- package/commands/login.command.js +34 -4
- package/commands/logout.command.js +16 -6
- package/commands/openAPI.command/index.js +3 -8
- package/commands/openAPI.command/utils.js +4 -13
- package/commands/utils.d.ts +2 -0
- package/commands/utils.js +8 -0
- package/config/core.d.ts +1 -0
- package/config/core.js +5 -1
- package/config/index.js +1 -0
- package/constants.d.ts +3 -1
- package/constants.js +34 -5
- package/discovery/index.js +0 -4
- package/dwc/dwc.js +15 -26
- package/dwc/run.js +2 -0
- package/dwc/utils.d.ts +2 -0
- package/dwc/utils.js +34 -2
- package/index.d.ts +2 -1
- package/index.js +4 -1
- package/logger/index.d.ts +1 -10
- package/logger/types.d.ts +10 -0
- package/logger/types.js +2 -0
- package/logger/utils.d.ts +2 -0
- package/logger/utils.js +12 -0
- package/package.json +7 -6
- package/result/ResultHandlerFactory.js +1 -0
- package/result/ResultHandlerImpl.js +1 -0
- package/types.d.ts +9 -3
- package/utils/commands.d.ts +2 -2
- package/utils/commands.js +23 -11
- package/utils/http/index.js +0 -1
- package/utils/utils.d.ts +5 -1
- package/utils/utils.js +15 -4
- package/commands/cache.command/init.command.d.ts +0 -3
- /package/commands/{cache.command → config.command/cache.command}/index.js +0 -0
package/CHANGELOG.md
CHANGED
|
@@ -5,14 +5,191 @@ All notable changes to this project will be documented in this file.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
+
## 2023.18.0
|
|
9
|
+
|
|
10
|
+
### Added
|
|
11
|
+
|
|
12
|
+
- Support for managing multiple logins/secrets for different tenants in parallel. The `<cli> login` and `<cli> logout` commands have been updated, allowing you to login to multiple tenants in parallel. When running a command, the CLI uses the secret matching the currently maintained tenant URL via the `-H, --host` option or set via `<cli> config host set <host>`. You now must specify the host which you are logging in to using option `-H, --host`, or by setting the host globally first by calling `<cli> config host set <host>`, to allow the CLI to store the secret for the defined tenant URL.
|
|
13
|
+
|
|
14
|
+
You can list all locally stored secrets by running `<cli> config secrets show`.
|
|
15
|
+
|
|
16
|
+
```javascript
|
|
17
|
+
$ <cli> config secrets show
|
|
18
|
+
[
|
|
19
|
+
{
|
|
20
|
+
"id": 0,
|
|
21
|
+
"client_id": "sb-0d85e619...",
|
|
22
|
+
"client_secret": "1dcc0522-...",
|
|
23
|
+
"tenantUrl": "https://somehost.eu10.cloud.sap",
|
|
24
|
+
...
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
"id": 1,
|
|
28
|
+
"client_id": "sb-0d85e619...",
|
|
29
|
+
"client_secret": "1dcc0522-...",
|
|
30
|
+
"tenantUrl": "https://somehost.us10.cloud.sap",
|
|
31
|
+
...
|
|
32
|
+
}
|
|
33
|
+
]
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
In order to logout again, the `<cli> logout` command allows you to optionally specify the ID of the login/secret to remove using option `-l, --login-id <id>`.
|
|
37
|
+
|
|
38
|
+
```javascript
|
|
39
|
+
<cli> logout --help
|
|
40
|
+
Usage: <cli> logout [options]
|
|
41
|
+
|
|
42
|
+
log out from your account
|
|
43
|
+
|
|
44
|
+
Options:
|
|
45
|
+
-l, --login-id <id> specifies the login ID (optional) (choices: "0", default: "0")
|
|
46
|
+
-h, --help display help for command
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
By default, when you omit option `-l, --login-id <id>`, the login/secret with ID _0_ is removed.
|
|
50
|
+
|
|
51
|
+
You cannot login to the same tenant with different _access tokens_ at the same time. There can only be a single login/secret per tenant, but you can login into multiple tenants in parallel. If you need to login with different users into the same tenant, you have to logout first, then login again with a different user.
|
|
52
|
+
|
|
53
|
+
- Support for predefined OAuth clients where the client ID _does not_ start with the term `sb-`. When using a predefined OAuth client where the client ID _does not_ start with the term `sb-`, the CLI uses a different default port `65000` to retrieve the temporary code to retrieve the access token and refresh token. The port can be changed using the environment variable mentioned in the [README.md](README.md) file.
|
|
54
|
+
|
|
55
|
+
- Improved OAuth authorization URL and token URL support. You do not have to specify the options for the _OAuth Client Authorization URL_ and _Token URL_ anymore, if you specify the tenant URL using the _-H, --host_ option. The CLI calculates the required authorization and token URLs automatically based on the given _Client ID_, _Client Secret_, and _Tenant URL_. You can still use the respective options to provide values for the authorization URL and token URL to override the calculated values.
|
|
56
|
+
|
|
57
|
+
### Changed
|
|
58
|
+
|
|
59
|
+
- Generic options are hidden for all commands. Before, all options where shown, including generic options applicable to any command.
|
|
60
|
+
|
|
61
|
+
```bash
|
|
62
|
+
$ <cli> spaces read --help
|
|
63
|
+
Usage: <cli> spaces read [options]
|
|
64
|
+
fetch space details for a specified space
|
|
65
|
+
Options:
|
|
66
|
+
-V, --verbose print detailed log information to console (optional)
|
|
67
|
+
-O, --options-file <file> path to options file (optional)
|
|
68
|
+
-H, --host <host> specifies the url where the tenant is hosted (optional)
|
|
69
|
+
-c, --client-id <id> client id for interactive oauth session authentication (optional)
|
|
70
|
+
-C, --client-secret <secret> client secret for interactive oauth session authentication (optional)
|
|
71
|
+
-a, --access-token <token> access token for interactive oauth session authentication (optional)
|
|
72
|
+
-r, --refresh-token <token> refresh token for interactive oauth session authentication (optional)
|
|
73
|
+
-b, --code <code> code for oauth token retrieval (optional)
|
|
74
|
+
-t, --token-url <url> token url for interactive oauth session authentication (optional)
|
|
75
|
+
-A, --authorization-url <url> authorization url for interactive oauth session authentication (optional)
|
|
76
|
+
-p, --passcode <passcode> passcode for interactive session authentication (optional)
|
|
77
|
+
-s, --secrets-file <file> path to secrets file (optional)
|
|
78
|
+
-e, --expires-in <expires> expires in information for interactive oauth session authentication (optional)
|
|
79
|
+
-o, --output <output> specifies the file to store the output of the command (optional)
|
|
80
|
+
-P, --pretty pretty-formats JSON responses (optional)
|
|
81
|
+
-S, --space <space> space ID (optional)
|
|
82
|
+
-N, --no-space-definition do not read space definition (optional)
|
|
83
|
+
-m, --definitions [definitions] read definitions (optional)
|
|
84
|
+
-q, --connections [connections] read connections (optional)
|
|
85
|
+
-h, --help display help for command
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
Now, only command-specific options are shown.
|
|
89
|
+
|
|
90
|
+
```bash
|
|
91
|
+
$ <cli> spaces read --help
|
|
92
|
+
Usage: <cli> spaces read [options]
|
|
93
|
+
fetch space details for a specified space
|
|
94
|
+
Options:
|
|
95
|
+
-S, --space <space> space ID (optional)
|
|
96
|
+
-N, --no-space-definition do not read space definition (optional)
|
|
97
|
+
-m, --definitions [definitions] read definitions (optional)
|
|
98
|
+
-q, --connections [connections] read connections (optional)
|
|
99
|
+
-h, --help display help for command
|
|
100
|
+
Only command-specific options are listed here. To learn more about available generic options, visit https://your.generic.options.help.url
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
- Option `-P, --pretty` changes to `-n, --no-pretty`. You can now supply option `-n, --no-pretty` to not pretty-format the response of a command. By default, the response of a command is pretty-formatted. When adding the option `-h, --help` to any command, the help tells you about the possible uses.
|
|
104
|
+
|
|
105
|
+
```bash
|
|
106
|
+
$ <cli> spaces read --help
|
|
107
|
+
Usage: <cli> spaces read [options]
|
|
108
|
+
|
|
109
|
+
fetch space details for a specified space
|
|
110
|
+
|
|
111
|
+
Options:
|
|
112
|
+
-n, --no-pretty do not pretty-format JSON responses (optional)
|
|
113
|
+
-h, --help display help for command
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
When calling a command that supports the `-P, --pretty` option you can explicitly specify to pretty-print the result.
|
|
117
|
+
|
|
118
|
+
`$ <cli> spaces read --pretty true`
|
|
119
|
+
|
|
120
|
+
To disable pretty-printing, set `-P, --pretty` to `false`.
|
|
121
|
+
|
|
122
|
+
`$ <cli> spaces read --pretty false`
|
|
123
|
+
|
|
124
|
+
Calling a command without specifying the `-P, --pretty` option explicitly yields the same output as when calling the command with `--pretty true`.
|
|
125
|
+
|
|
126
|
+
- A new top-level command `config` has been introduced. This command groups all the CLI configuration-related commands such as `cache`, `secrets`, `host`, ...
|
|
127
|
+
|
|
128
|
+
**Old Structure**
|
|
129
|
+
|
|
130
|
+
```bash
|
|
131
|
+
$ <cli>
|
|
132
|
+
Usage: <cli> [options] [command]
|
|
133
|
+
|
|
134
|
+
<Your CLI description>
|
|
135
|
+
|
|
136
|
+
Options:
|
|
137
|
+
-v, --version output the current version
|
|
138
|
+
-H, --host <host> specifies the url where the tenant is hosted (optional)
|
|
139
|
+
-O, --options-file <file> path to options file (optional)
|
|
140
|
+
-h, --help display help for command
|
|
141
|
+
|
|
142
|
+
Commands:
|
|
143
|
+
cache work with the local CLI cache
|
|
144
|
+
dbusers [options] manage and orchestrate database users
|
|
145
|
+
help [command] display help for command
|
|
146
|
+
host configure host properties
|
|
147
|
+
login [options] log in to your account using interactive OAuth authentication
|
|
148
|
+
logout log out from your account
|
|
149
|
+
marketplace [options] manage and orchestrate your SAP Data Marketplace
|
|
150
|
+
passcode-url [options] display the passcode url
|
|
151
|
+
secrets work with the locally stored secrets
|
|
152
|
+
spaces [options] manage and orchestrate spaces
|
|
153
|
+
tasks [options] manage tasks
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
**New Structure**
|
|
157
|
+
|
|
158
|
+
```bash
|
|
159
|
+
$ <cli>
|
|
160
|
+
Usage: <cli> [options] [command]
|
|
161
|
+
|
|
162
|
+
<Your CLI description>
|
|
163
|
+
|
|
164
|
+
Options:
|
|
165
|
+
-v, --version output the current version
|
|
166
|
+
-H, --host <host> specifies the url where the tenant is hosted (optional)
|
|
167
|
+
-O, --options-file <file> path to options file (optional)
|
|
168
|
+
-h, --help display help for command
|
|
169
|
+
|
|
170
|
+
Commands:
|
|
171
|
+
config configure your CLI
|
|
172
|
+
dbusers [options] manage and orchestrate database users
|
|
173
|
+
help [command] display help for command
|
|
174
|
+
login [options] log in to your account using interactive OAuth authentication
|
|
175
|
+
logout log out from your account
|
|
176
|
+
marketplace [options] manage and orchestrate your SAP Data Marketplace
|
|
177
|
+
spaces [options] manage and orchestrate spaces
|
|
178
|
+
tasks [options] manage tasks
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
### Fixed
|
|
182
|
+
|
|
183
|
+
- Values entered for the _Authorization URL_ and _Token URL_ could be entered including query parameters like `https://some.authorization.url?some.parameter=some.value`. The CLI did not remove the query parameters when using the URLs to retrieve the temporary code. This has been changed, the query parameters are now removed. The CLI changes an URL from `https://some.authorization.url?some.parameter=some.value` to `https://some.authorization.url` to retrieve the temporary code.
|
|
184
|
+
|
|
8
185
|
## 2023.11.0
|
|
9
186
|
|
|
10
187
|
### Changed
|
|
11
188
|
|
|
12
189
|
- When using the CLI as a dependency in your Node.js project, calling a command now returns the result directly, if there's any. You don't need to provide a custom logger function anymore to catch the `output` logs. You can now write the following code to work with the result of a command:
|
|
13
190
|
|
|
14
|
-
```
|
|
15
|
-
import cli from "@sap
|
|
191
|
+
```bash
|
|
192
|
+
import cli from "@sap/<cli>";
|
|
16
193
|
|
|
17
194
|
const commands = await cli.getCommands("https://somehost.eu10.cloud.sap");
|
|
18
195
|
const result = await commands["some command"](options);
|
package/README.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
Command-Line Interface (CLI) Core Module.
|
|
4
4
|
|
|
5
|
-
[](https://nodejs.org/dist/latest-v18.x/docs/api/#) [](https://badge.fury.io/js/@sap%2Fcli-core)
|
|
6
6
|
|
|
7
7
|
## Content
|
|
8
8
|
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { Secret } from "../../types";
|
|
2
|
+
import { SecretsStorage } from "./types";
|
|
3
|
+
export declare class SecretsStorageImpl implements SecretsStorage {
|
|
4
|
+
private secrets;
|
|
5
|
+
private logger;
|
|
6
|
+
constructor();
|
|
7
|
+
deleteAllSecrets(): Promise<void>;
|
|
8
|
+
private recreateCalculatedValues;
|
|
9
|
+
initializeStorage(): Promise<void>;
|
|
10
|
+
getDefaultSecret(): Promise<Readonly<Secret>>;
|
|
11
|
+
getDefaultSecretId(): Promise<number>;
|
|
12
|
+
private ensureSecretsExist;
|
|
13
|
+
private throwIfSecretsDoesntExist;
|
|
14
|
+
getSecretById(id: number): Promise<Readonly<Secret>>;
|
|
15
|
+
private removeSecretsFromArray;
|
|
16
|
+
private updateSecret;
|
|
17
|
+
private updateUrls;
|
|
18
|
+
storeSecret(secret: Omit<Secret, "id" | "host" | "customClient">): Promise<void>;
|
|
19
|
+
deleteSecretById(id: number): void;
|
|
20
|
+
synchronizeSecretsToStorage(): Promise<void>;
|
|
21
|
+
getAllSecrets(): ReadonlyArray<Secret>;
|
|
22
|
+
}
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.SecretsStorageImpl = void 0;
|
|
4
|
+
const config_1 = require("../../config");
|
|
5
|
+
const constants_1 = require("../../constants");
|
|
6
|
+
const logger_1 = require("../../logger");
|
|
7
|
+
const http_1 = require("../../utils/http");
|
|
8
|
+
const utils_1 = require("../../utils/utils");
|
|
9
|
+
const cache_1 = require("../cache");
|
|
10
|
+
const utils_2 = require("./utils");
|
|
11
|
+
class SecretsStorageImpl {
|
|
12
|
+
secrets = [];
|
|
13
|
+
logger;
|
|
14
|
+
constructor() {
|
|
15
|
+
this.logger = (0, logger_1.get)("SecretsStorageImpl");
|
|
16
|
+
}
|
|
17
|
+
async deleteAllSecrets() {
|
|
18
|
+
await (0, cache_1.deleteFile)(constants_1.CACHE_SECRETS_FILE);
|
|
19
|
+
this.secrets = [];
|
|
20
|
+
}
|
|
21
|
+
async recreateCalculatedValues() {
|
|
22
|
+
for (let i = 0; i < this.secrets.length; i++) {
|
|
23
|
+
this.secrets[i].id = i;
|
|
24
|
+
if (!this.secrets[i].client_id) {
|
|
25
|
+
this.logger.warn(`client id is not set for secret with ID ${i}, skipping update of secret information`);
|
|
26
|
+
// eslint-disable-next-line no-continue
|
|
27
|
+
continue;
|
|
28
|
+
}
|
|
29
|
+
this.secrets[i].customClient = (0, utils_2.isCustomClient)(this.secrets[i].client_id);
|
|
30
|
+
// eslint-disable-next-line no-await-in-loop
|
|
31
|
+
await this.updateUrls(i);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
async initializeStorage() {
|
|
35
|
+
try {
|
|
36
|
+
this.secrets = JSON.parse(await (0, cache_1.readFile)(constants_1.CACHE_SECRETS_FILE));
|
|
37
|
+
if (!Array.isArray(this.secrets)) {
|
|
38
|
+
this.logger.warn("secrets data is no array, initializing secrets to empty array");
|
|
39
|
+
this.secrets = [];
|
|
40
|
+
}
|
|
41
|
+
await this.recreateCalculatedValues();
|
|
42
|
+
}
|
|
43
|
+
catch (err) {
|
|
44
|
+
this.logger.warn("failed to read or parse secrets file", err);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
async getDefaultSecret() {
|
|
48
|
+
return this.getSecretById(await this.getDefaultSecretId());
|
|
49
|
+
}
|
|
50
|
+
async getDefaultSecretId() {
|
|
51
|
+
const tenantUrl = (0, utils_2.getTenantUrl)();
|
|
52
|
+
const secret = this.secrets.find((s) => new URL(s.tenantUrl).host === new URL(tenantUrl).host);
|
|
53
|
+
if (!secret) {
|
|
54
|
+
throw new Error("Method not implemented.");
|
|
55
|
+
}
|
|
56
|
+
return secret.id;
|
|
57
|
+
}
|
|
58
|
+
ensureSecretsExist(id) {
|
|
59
|
+
return !!this.secrets.at(id);
|
|
60
|
+
}
|
|
61
|
+
throwIfSecretsDoesntExist(id) {
|
|
62
|
+
if (!this.ensureSecretsExist(id)) {
|
|
63
|
+
throw new Error(`no secrets exist for id ${id}`);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
async getSecretById(id) {
|
|
67
|
+
this.throwIfSecretsDoesntExist(id);
|
|
68
|
+
return this.secrets.at(id);
|
|
69
|
+
}
|
|
70
|
+
removeSecretsFromArray(id) {
|
|
71
|
+
this.secrets.splice(id, 1);
|
|
72
|
+
}
|
|
73
|
+
updateSecret(secret) {
|
|
74
|
+
const tenantUrl = (0, utils_2.getTenantUrl)();
|
|
75
|
+
let prevSecretIx = this.secrets.findIndex((s) => s.tenantUrl === tenantUrl);
|
|
76
|
+
let newSecret;
|
|
77
|
+
if (prevSecretIx > -1) {
|
|
78
|
+
newSecret = { ...this.secrets[prevSecretIx], ...secret };
|
|
79
|
+
this.secrets[prevSecretIx] = newSecret;
|
|
80
|
+
}
|
|
81
|
+
else {
|
|
82
|
+
newSecret = {
|
|
83
|
+
...secret,
|
|
84
|
+
id: this.secrets.length,
|
|
85
|
+
tenantUrl,
|
|
86
|
+
customClient: false,
|
|
87
|
+
};
|
|
88
|
+
this.secrets.push(newSecret);
|
|
89
|
+
prevSecretIx = this.secrets.length - 1;
|
|
90
|
+
}
|
|
91
|
+
return prevSecretIx;
|
|
92
|
+
}
|
|
93
|
+
async updateUrls(secretIndex) {
|
|
94
|
+
const secret = this.secrets[secretIndex];
|
|
95
|
+
if (secret.client_id) {
|
|
96
|
+
const config = (0, config_1.get)();
|
|
97
|
+
let oauth = {};
|
|
98
|
+
if (!secret.customClient) {
|
|
99
|
+
oauth = (await (0, http_1.fetch)({
|
|
100
|
+
method: "GET",
|
|
101
|
+
url: `${config.tenantUrl}/oauth`,
|
|
102
|
+
})).data;
|
|
103
|
+
}
|
|
104
|
+
let authorizationUrl = secret.authorization_url;
|
|
105
|
+
if (!authorizationUrl) {
|
|
106
|
+
if (!secret.customClient) {
|
|
107
|
+
authorizationUrl = oauth.authorizationUrl;
|
|
108
|
+
}
|
|
109
|
+
else {
|
|
110
|
+
authorizationUrl = config.authorizationUrl;
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
let tokenUrl = secret.token_url;
|
|
114
|
+
if (!tokenUrl) {
|
|
115
|
+
if (!secret.customClient) {
|
|
116
|
+
tokenUrl = oauth.tokenUrl;
|
|
117
|
+
}
|
|
118
|
+
else {
|
|
119
|
+
tokenUrl = config.tokenUrl;
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
this.secrets[secretIndex].authorization_url =
|
|
123
|
+
(0, utils_1.removeQueryParametersFromUrl)(authorizationUrl);
|
|
124
|
+
this.secrets[secretIndex].token_url = (0, utils_1.removeQueryParametersFromUrl)(tokenUrl);
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
async storeSecret(secret) {
|
|
128
|
+
this.updateSecret(secret);
|
|
129
|
+
await this.recreateCalculatedValues();
|
|
130
|
+
}
|
|
131
|
+
deleteSecretById(id) {
|
|
132
|
+
this.throwIfSecretsDoesntExist(id);
|
|
133
|
+
this.removeSecretsFromArray(id);
|
|
134
|
+
}
|
|
135
|
+
async synchronizeSecretsToStorage() {
|
|
136
|
+
try {
|
|
137
|
+
await (0, cache_1.writeFile)(constants_1.CACHE_SECRETS_FILE, JSON.stringify(this.secrets));
|
|
138
|
+
}
|
|
139
|
+
catch (err) {
|
|
140
|
+
this.logger.error("failed to synchronize secrets to storage", err);
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
getAllSecrets() {
|
|
144
|
+
return this.secrets;
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
exports.SecretsStorageImpl = SecretsStorageImpl;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { Secret } from "../../types";
|
|
2
|
+
export interface SecretsStorage {
|
|
3
|
+
getDefaultSecretId(): Promise<number>;
|
|
4
|
+
getDefaultSecret(): Promise<Readonly<Secret>>;
|
|
5
|
+
getSecretById(id: number): Promise<Readonly<Secret>>;
|
|
6
|
+
storeSecret(secret: Partial<Secret>): Promise<void>;
|
|
7
|
+
deleteSecretById(id: number): void;
|
|
8
|
+
synchronizeSecretsToStorage(): Promise<void>;
|
|
9
|
+
getAllSecrets(): ReadonlyArray<Secret>;
|
|
10
|
+
deleteAllSecrets(): Promise<void>;
|
|
11
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.getTenantUrl = exports.isCustomClient = void 0;
|
|
4
|
+
const config_1 = require("../../config");
|
|
5
|
+
const constants_1 = require("../../constants");
|
|
6
|
+
// Pre-delivered OAuth Client ID: 5a638330-5899-366e-ac00-ab62cc32dcda
|
|
7
|
+
// Custom OAuth Client ID: sb-00bb7bc2-cc32-423c-921c-2abdee11a29d!b49931|client!b3650
|
|
8
|
+
const isCustomClient = (clientId) => clientId ? clientId.startsWith("sb-") : true;
|
|
9
|
+
exports.isCustomClient = isCustomClient;
|
|
10
|
+
const getTenantUrl = () => {
|
|
11
|
+
const config = (0, config_1.get)();
|
|
12
|
+
const tenantUrl = config.tenantUrl ?? config.options[constants_1.OPTION_HOST.longName];
|
|
13
|
+
if (!tenantUrl) {
|
|
14
|
+
throw new Error("no tenant url found");
|
|
15
|
+
}
|
|
16
|
+
return tenantUrl;
|
|
17
|
+
};
|
|
18
|
+
exports.getTenantUrl = getTenantUrl;
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
const cache_1 = require("
|
|
4
|
-
const constants_1 = require("
|
|
5
|
-
const cleanHandler = () => async () => {
|
|
3
|
+
const cache_1 = require("../../../cache");
|
|
4
|
+
const constants_1 = require("../../../constants");
|
|
5
|
+
const cleanHandler = async () => async () => {
|
|
6
6
|
const files = (await (0, cache_1.getFiles)()).filter((file) => file.startsWith(constants_1.DISCOVERY_DOCUMENT_PREFIX));
|
|
7
7
|
await Promise.all(files.map(async (file) => (0, cache_1.deleteFile)(file)));
|
|
8
8
|
};
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
|
|
4
|
-
const
|
|
5
|
-
const
|
|
6
|
-
const
|
|
7
|
-
const
|
|
8
|
-
const
|
|
3
|
+
exports.init = void 0;
|
|
4
|
+
const constants_1 = require("../../../constants");
|
|
5
|
+
const discovery_1 = require("../../../discovery");
|
|
6
|
+
const handler_1 = require("../../handler");
|
|
7
|
+
const config_1 = require("../../../config");
|
|
8
|
+
const core_1 = require("../../../config/core");
|
|
9
|
+
const pre = () => {
|
|
9
10
|
const config = (0, config_1.get)();
|
|
10
11
|
(0, config_1.set)({
|
|
11
12
|
options: {
|
|
@@ -15,7 +16,7 @@ const pre = () => async () => {
|
|
|
15
16
|
doNotStoreResult: true,
|
|
16
17
|
});
|
|
17
18
|
};
|
|
18
|
-
const post =
|
|
19
|
+
const post = async () => {
|
|
19
20
|
const config = (0, config_1.get)();
|
|
20
21
|
await (0, discovery_1.addMetadata)({
|
|
21
22
|
tenant: config.publicfqdn,
|
|
@@ -26,11 +27,17 @@ const post = () => async () => {
|
|
|
26
27
|
delete options[constants_1.OPTION_OUTPUT.longName];
|
|
27
28
|
(0, config_1.set)({ options });
|
|
28
29
|
};
|
|
30
|
+
const init = async () => async () => {
|
|
31
|
+
pre();
|
|
32
|
+
await (await (0, handler_1.createFetchHandler)("GET", (0, core_1.getDiscoveryPath)())({}))();
|
|
33
|
+
await post();
|
|
34
|
+
};
|
|
35
|
+
exports.init = init;
|
|
29
36
|
const initCommand = {
|
|
30
37
|
type: "command",
|
|
31
38
|
command: "init",
|
|
32
39
|
description: "initialize the local CLI cache",
|
|
33
40
|
options: [],
|
|
34
|
-
handler: (0, handler_1.createNextHandler)((0, handler_1.createParseArgumentsHandler)(), (0, handler_1.createMandatoryOptionsHandler)(), (0, handler_1.createAuthenticationHandler)(),
|
|
41
|
+
handler: (0, handler_1.createNextHandler)((0, handler_1.createParseArgumentsHandler)(), (0, handler_1.createMandatoryOptionsHandler)(), (0, handler_1.createAuthenticationHandler)(), exports.init),
|
|
35
42
|
};
|
|
36
43
|
exports.default = initCommand;
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
const discovery_1 = require("
|
|
4
|
-
const logger_1 = require("
|
|
5
|
-
const handler_1 = require("
|
|
6
|
-
const show = () => async () => {
|
|
3
|
+
const discovery_1 = require("../../../discovery");
|
|
4
|
+
const logger_1 = require("../../../logger");
|
|
5
|
+
const handler_1 = require("../../handler");
|
|
6
|
+
const show = async () => async () => {
|
|
7
7
|
const { output } = (0, logger_1.get)("commands.show");
|
|
8
8
|
const metadata = await (0, discovery_1.getMetadata)();
|
|
9
9
|
if (metadata.length === 0) {
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { AddCommands } from "
|
|
1
|
+
import { AddCommands } from "../../types";
|
|
2
2
|
export declare const addCommands: AddCommands;
|
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.addCommands = void 0;
|
|
4
|
-
const config_1 = require("
|
|
5
|
-
const constants_1 = require("
|
|
6
|
-
const logger_1 = require("
|
|
7
|
-
const settings_1 = require("
|
|
8
|
-
const commands_1 = require("
|
|
9
|
-
const utils_1 = require("
|
|
10
|
-
const handler_1 = require("
|
|
4
|
+
const config_1 = require("../../config");
|
|
5
|
+
const constants_1 = require("../../constants");
|
|
6
|
+
const logger_1 = require("../../logger");
|
|
7
|
+
const settings_1 = require("../../settings");
|
|
8
|
+
const commands_1 = require("../../utils/commands");
|
|
9
|
+
const utils_1 = require("../../utils/utils");
|
|
10
|
+
const handler_1 = require("../handler");
|
|
11
11
|
const getLogger = () => (0, logger_1.get)("commands.host");
|
|
12
|
-
const set = () => async () => {
|
|
12
|
+
const set = async () => async () => {
|
|
13
13
|
const config = (0, config_1.get)();
|
|
14
14
|
try {
|
|
15
15
|
// throws if host is not valid
|
|
@@ -23,22 +23,22 @@ const set = () => async () => {
|
|
|
23
23
|
throw new Error("failed to set host");
|
|
24
24
|
}
|
|
25
25
|
};
|
|
26
|
-
const show = () => async () => {
|
|
26
|
+
const show = async () => async () => {
|
|
27
27
|
const { output } = getLogger();
|
|
28
28
|
const settings = await (0, settings_1.get)();
|
|
29
29
|
if (settings[constants_1.OPTION_HOST.longName]) {
|
|
30
30
|
output(settings[constants_1.OPTION_HOST.longName]);
|
|
31
31
|
}
|
|
32
32
|
else {
|
|
33
|
-
output(
|
|
33
|
+
output(`no global host set. use ${(0, utils_1.getBin)()} config host set <host> to set a global host`);
|
|
34
34
|
throw new Error("no global host set");
|
|
35
35
|
}
|
|
36
36
|
};
|
|
37
|
-
const clean = () => async () => {
|
|
37
|
+
const clean = async () => async () => {
|
|
38
38
|
await (0, settings_1.remove)(constants_1.OPTION_HOST.longName);
|
|
39
39
|
};
|
|
40
40
|
const addCommands = async (program) => {
|
|
41
|
-
(0, commands_1.buildCommand)(program, {
|
|
41
|
+
await (0, commands_1.buildCommand)(program, {
|
|
42
42
|
type: "topCommand",
|
|
43
43
|
command: "host",
|
|
44
44
|
description: "configure host properties",
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.addCommands = void 0;
|
|
7
|
+
const path_1 = __importDefault(require("path"));
|
|
8
|
+
const commands_1 = require("../../utils/commands");
|
|
9
|
+
const utils_1 = require("../../dwc/utils");
|
|
10
|
+
const addCommands = async (program) => {
|
|
11
|
+
const configCommand = await (0, commands_1.buildCommand)(program, {
|
|
12
|
+
type: "topCommand",
|
|
13
|
+
command: "config",
|
|
14
|
+
description: "configure your CLI",
|
|
15
|
+
subCommands: [],
|
|
16
|
+
});
|
|
17
|
+
await (0, utils_1.addCommandsFromFolder)(path_1.default.join(__dirname), configCommand);
|
|
18
|
+
};
|
|
19
|
+
exports.addCommands = addCommands;
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { AddCommands } from "
|
|
1
|
+
import { AddCommands } from "../../types";
|
|
2
2
|
export declare const addCommands: AddCommands;
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.addCommands = void 0;
|
|
4
|
-
const config_1 = require("
|
|
5
|
-
const core_1 = require("
|
|
6
|
-
const constants_1 = require("
|
|
7
|
-
const logger_1 = require("
|
|
8
|
-
const commands_1 = require("
|
|
9
|
-
const handler_1 = require("
|
|
10
|
-
const passcode = () => async () => {
|
|
4
|
+
const config_1 = require("../../config");
|
|
5
|
+
const core_1 = require("../../config/core");
|
|
6
|
+
const constants_1 = require("../../constants");
|
|
7
|
+
const logger_1 = require("../../logger");
|
|
8
|
+
const commands_1 = require("../../utils/commands");
|
|
9
|
+
const handler_1 = require("../handler");
|
|
10
|
+
const passcode = async () => async () => {
|
|
11
11
|
const { output } = (0, logger_1.get)("commands.passcode");
|
|
12
12
|
const config = (0, config_1.get)();
|
|
13
13
|
output(config.passcodeUrl);
|
|
@@ -20,7 +20,7 @@ const passcodeCommand = {
|
|
|
20
20
|
};
|
|
21
21
|
const addCommands = async (program) => {
|
|
22
22
|
if ((0, core_1.getAuthenticationMethods)().includes(constants_1.AuthenticationMethod.passcode)) {
|
|
23
|
-
(0, commands_1.buildCommand)(program, passcodeCommand);
|
|
23
|
+
await (0, commands_1.buildCommand)(program, passcodeCommand);
|
|
24
24
|
}
|
|
25
25
|
};
|
|
26
26
|
exports.addCommands = addCommands;
|